This is to enable alert management.
Signed-off-by: XINHUI LI <lxinhui@vmware.com>
Change-Id: If3e7273f70f8fafadd118aa87735388d76e027db
--- /dev/null
+.build/
+.tarballs/
+
+!.build/linux-amd64/
--- /dev/null
+<!--
+
+ Please do *NOT* ask usage questions in Github issues.
+
+ If your issue is not a feature request or bug report use:
+ https://groups.google.com/forum/#!forum/prometheus-users. If
+ you are unsure whether you hit a bug, search and ask in the
+ mailing list first.
+
+ You can find more information at: https://prometheus.io/community/
+
+-->
+
+**What did you do?**
+
+**What did you expect to see?**
+
+**What did you see instead? Under which circumstances?**
+
+**Environment**
+
+* System information:
+
+ insert output of `uname -srm` here
+
+* Alertmanager version:
+
+ insert output of `alertmanager --version` here
+
+* Prometheus version:
+
+ insert output of `prometheus -version` here (if relevant to the issue)
+
+* Alertmanager configuration file:
+```
+insert configuration here
+```
+
+* Prometheus configuration file:
+```
+insert configuration here (if relevant to the issue)
+```
+
+* Logs:
+```
+insert Prometheus and Alertmanager logs relevant to the issue here
+```
--- /dev/null
+/data/
+/alertmanager
+/amtool
+*.yml
+*.yaml
+/.build
+/.release
+/.tarballs
+
+!/cli/testdata/*.yml
+!/cli/config/testdata/*.yml
+!/doc/examples/simple.yml
+!/circle.yml
+!/.travis.yml
+!/.promu.yml
--- /dev/null
+repository:
+ path: github.com/prometheus/alertmanager
+build:
+ binaries:
+ - name: alertmanager
+ path: ./cmd/alertmanager
+ - name: amtool
+ path: ./cmd/amtool
+ flags: -a -tags netgo
+ ldflags: |
+ -X {{repoPath}}/vendor/github.com/prometheus/common/version.Version={{.Version}}
+ -X {{repoPath}}/vendor/github.com/prometheus/common/version.Revision={{.Revision}}
+ -X {{repoPath}}/vendor/github.com/prometheus/common/version.Branch={{.Branch}}
+ -X {{repoPath}}/vendor/github.com/prometheus/common/version.BuildUser={{user}}@{{host}}
+ -X {{repoPath}}/vendor/github.com/prometheus/common/version.BuildDate={{date "20060102-15:04:05"}}
+tarball:
+ files:
+ - examples/ha/alertmanager.yml
+ - LICENSE
+ - NOTICE
+crossbuild:
+ platforms:
+ - linux/amd64
+ - linux/386
+ - darwin/amd64
+ - darwin/386
+ - windows/amd64
+ - windows/386
+ - freebsd/amd64
+ - freebsd/386
+ - openbsd/amd64
+ - openbsd/386
+ - netbsd/amd64
+ - netbsd/386
+ - dragonfly/amd64
+ - linux/arm
+ - linux/arm64
+ - freebsd/arm
+ - netbsd/arm
+ - linux/ppc64
+ - linux/ppc64le
+ - linux/mips64
+ - linux/mips64le
--- /dev/null
+sudo: false
+language: go
+
+services:
+- docker
+
+go:
+- 1.10.x
+
+script:
+# test front-end
+- make clean
+- cd ui/app/ && make && cd ../..
+- make assets
+- git diff --exit-code
+# test back-end
+- make
--- /dev/null
+## 0.15.0 / 2018-06-22
+
+* [CHANGE] [amtool] Update silence add and update flags (#1298)
+* [CHANGE] Replace deprecated InstrumentHandler() (#1302)
+* [CHANGE] Validate Slack field config and only allow the necessary input (#1334)
+* [CHANGE] Remove legacy alert ingest endpoint (#1362)
+* [CHANGE] Moved to memberlist as underlying gossip protocol
+* [BUGFIX/CHANGE] The default group by is no labels. (#1287)
+* [FEATURE] [amtool] Filter alerts by receiver (#1402)
+* [FEATURE] Wait for mesh to settle before sending alerts (#1209)
+* [FEATURE] [amtool] Support basic auth in alertmanager url (#1279)
+* [FEATURE] Make HTTP clients used for integrations configurable
+* [ENHANCEMENT] Support receiving alerts with end time and zero start time
+* [ENHANCEMENT] Sort dispatched alerts by job+instance (#1234)
+* [ENHANCEMENT] Support alert query filters `active` and `unprocessed` (#1366)
+* [ENHANCEMENT] [amtool] Expose alert query flags --active and --unprocessed (#1370)
+* [ENHANCEMENT] Add Slack actions to notifications (#1355)
+* [BUGFIX] Register nflog snapShotSize metric
+* [BUGFIX] Sort alerts in correct order before flushing to notifiers (#1349)
+* [BUGFIX] Don't reset initial wait timer if flush is in-progress (#1301)
+* [BUGFIX] Fix resolved alerts still inhibiting (#1331)
+* [BUGFIX] Template wechat config fields (#1356)
+* [BUGFIX] Notify resolved alerts properly (#1408)
+* [BUGFIX] Fix parsing for label values with commas (#1395)
+* [BUGFIX] Hide sensitive Wechat configuration (#1253)
+* [BUGFIX] Prepopulate matchers when recreating a silence (#1270)
+* [BUGFIX] Fix wechat panic (#1293)
+* [BUGFIX] Allow empty matchers in silences/filtering (#1289)
+* [BUGFIX] Properly configure HTTP client for Wechat integration
+
+## 0.14.0 / 2018-02-12
+
+* [ENHANCEMENT] [amtool] Silence update support dwy suffixes to expire flag (#1197)
+* [ENHANCEMENT] Allow templating PagerDuty receiver severity (#1214)
+* [ENHANCEMENT] Include receiver name in failed notifications log messages (#1207)
+* [ENHANCEMENT] Allow global opsgenie api key (#1208)
+* [ENHANCEMENT] Add mesh metrics (#1225)
+* [ENHANCEMENT] Add Class field to PagerDuty; add templating to PagerDuty-CEF fields (#1231)
+* [BUGFIX] Don't notify of resolved alerts if none were reported firing (#1198)
+* [BUGFIX] Notify only when new firing alerts are added (#1205)
+* [BUGFIX] [mesh] Fix pending connections never set to established (#1204)
+* [BUGFIX] Allow OpsGenie notifier to have empty team fields (#1224)
+* [BUGFIX] Don't count alerts with EndTime in the future as resolved (#1233)
+* [BUGFIX] Speed up re-rendering of Silence UI (#1235)
+* [BUGFIX] Forbid 0 value for group_interval and repeat_interval (#1230)
+* [BUGFIX] Fix WeChat agentid issue (#1229)
+
+## 0.13.0 / 2018-01-12
+
+* [CHANGE] Switch cmd/alertmanager to kingpin (#974)
+* [CHANGE] [amtool] Switch amtool to kingpin (#976)
+* [CHANGE] [amtool] silence query: --expired flag only shows expired silences (#1190)
+* [CHANGE] Return config reload result from reload endpoint (#1180)
+* [FEATURE] UI silence form is populated from location bar (#1148)
+* [FEATURE] Add /-/healthy endpoint (#1159)
+* [ENHANCEMENT] Instrument and log snapshot sizes on maintenance (#1155)
+* [ENHANCEMENT] Make alertGC interval configurable (#1151)
+* [ENHANCEMENT] Display mesh connections in the Status page (#1164)
+* [BUGFIX] Template service keys for pagerduty notifier (#1182)
+* [BUGFIX] Fix expire buttons on the silences page (#1171)
+* [BUGFIX] Fix JavaScript error in MSIE due to endswith() usage (#1172)
+* [BUGFIX] Correctly format UI error output (#1167)
+
+## 0.12.0 / 2017-12-15
+
+* [FEATURE] package amtool in docker container (#1127)
+* [FEATURE] Add notify support for Chinese User wechat (#1059)
+* [FEATURE] [amtool] Add a new `silence import` command (#1082)
+* [FEATURE] [amtool] Add new command to update silence (#1123)
+* [FEATURE] [amtool] Add ability to query for silences that will expire soon (#1120)
+* [ENHANCEMENT] Template source field in PagerDuty alert payload (#1117)
+* [ENHANCEMENT] Add footer field for slack messages (#1141)
+* [ENHANCEMENT] Add Slack additional "fields" to notifications (#1135)
+* [ENHANCEMENT] Adding check for webhook's URL formatting (#1129)
+* [ENHANCEMENT] Let the browser remember the creator of a silence (#1112)
+* [BUGFIX] Fix race in stopping inhibitor (#1118)
+* [BUGFIX] Fix browser UI when entering negative duration (#1132)
+
+## 0.11.0 / 2017-11-16
+
+* [CHANGE] Make silence negative filtering consistent with alert filtering (#1095)
+* [CHANGE] Change HipChat and OpsGenie api config names (#1087)
+* [ENHANCEMENT] amtool: Allow 'd', 'w', 'y' time suffixes when creating silence (#1091)
+* [ENHANCEMENT] Support OpsGenie Priority field (#1094)
+* [BUGFIX] Fix UI when no silences are present (#1090)
+* [BUGFIX] Fix OpsGenie Teams field (#1101)
+* [BUGFIX] Fix OpsGenie Tags field (#1108)
+
+## 0.10.0 / 2017-11-09
+
+* [CHANGE] Prevent inhibiting alerts in the source of the inhibition (#1017)
+* [ENHANCEMENT] Improve amtool check-config use and description text (#1016)
+* [ENHANCEMENT] Add metrics about current silences and alerts (#998)
+* [ENHANCEMENT] Sorted silences based on current status (#1015)
+* [ENHANCEMENT] Add metric of alertmanager position in mesh (#1024)
+* [ENHANCEMENT] Initialise notifications_total and notifications_failed_total (#1011)
+* [ENHANCEMENT] Allow selectable matchers on silence view (#1030)
+* [ENHANCEMENT] Allow template in victorops message_type field (#1038)
+* [ENHANCEMENT] Optionally hide inhibited alerts in API response (#1039)
+* [ENHANCEMENT] Toggle silenced and inhibited alerts in UI (#1049)
+* [ENHANCEMENT] Fix pushover limits (title, message, url) (#1055)
+* [ENHANCEMENT] Add limit to OpsGenie message (#1045)
+* [ENHANCEMENT] Upgrade OpsGenie notifier to v2 API. (#1061)
+* [ENHANCEMENT] Allow template in victorops routing_key field (#1083)
+* [ENHANCEMENT] Add support for PagerDuty API v2 (#1054)
+* [BUGFIX] Fix inhibit race (#1032)
+* [BUGFIX] Fix segfault on amtool (#1031)
+* [BUGFIX] Remove .WasInhibited and .WasSilenced fields of Alert type (#1026)
+* [BUGFIX] nflog: Fix Log() crash when gossip is nil (#1064)
+* [BUGFIX] Fix notifications for flapping alerts (#1071)
+* [BUGFIX] Fix shutdown crash with nil mesh router (#1077)
+* [BUGFIX] Fix negative matchers filtering (#1077)
+
+## 0.9.1 / 2017-09-29
+* [BUGFIX] Fix -web.external-url regression in ui (#1008)
+* [BUGFIX] Fix multipart email implementation (#1009)
+
+## 0.9.0 / 2017-09-28
+* [ENHANCEMENT] Add current time to webhook message (#909)
+* [ENHANCEMENT] Add link_names to slack notifier (#912)
+* [ENHANCEMENT] Make ui labels selectable/highlightable (#932)
+* [ENHANCEMENT] Make links in ui annotations selectable (#946)
+* [ENHANCEMENT] Expose the alert's "fingerprint" (unique identifier) through API (#786)
+* [ENHANCEMENT] Add README information for amtool (#939)
+* [ENHANCEMENT] Use user-set logging option consistently throughout alertmanager (#968)
+* [ENHANCEMENT] Sort alerts returned from API by their fingerprint (#969)
+* [ENHANCEMENT] Add edit/delete silence buttons on silence page view (#970)
+* [ENHANCEMENT] Add check-config subcommand to amtool (#978)
+* [ENHANCEMENT] Add email notification text content support (#934)
+* [ENHANCEMENT] Support passing binary name to make build target (#990)
+* [ENHANCEMENT] Show total no. of silenced alerts in preview (#994)
+* [ENHANCEMENT] Added confirmation dialog when expiring silences (#993)
+* [BUGFIX] Fix crash when no mesh router is configured (#919)
+* [BUGFIX] Render status page without mesh (#920)
+* [BUGFIX] Exit amtool subcommands with non-zero error code (#938)
+* [BUGFIX] Change mktemp invocation in makefile to work for macOS (#971)
+* [BUGFIX] Add a mutex to silences.go:gossipData (#984)
+* [BUGFIX] silences: avoid deadlock (#995)
+* [BUGFIX] Ignore expired silences OnGossip (#999)
+
+## 0.8.0 / 2017-07-20
+
+* [FEATURE] Add ability to filter alerts by receiver in the UI (#890)
+* [FEATURE] Add User-Agent for webhook requests (#893)
+* [ENHANCEMENT] Add possibility to have a global victorops api_key (#897)
+* [ENHANCEMENT] Add EntityDisplayName and improve StateMessage for Victorops
+ (#769)
+* [ENHANCEMENT] Omit empty config fields and show regex upon re-marshalling to
+ elide secrets (#864)
+* [ENHANCEMENT] Parse API error messages in UI (#866)
+* [ENHANCEMENT] Enable sending mail via smtp port 465 (#704)
+* [BUGFIX] Prevent duplicate notifications by sorting matchers (#882)
+* [BUGFIX] Remove timeout for UI requests (#890)
+* [BUGFIX] Update config file location of CLI in flag usage text (#895)
+
+## 0.7.1 / 2017-06-09
+
+* [BUGFIX] Fix filtering by label on Alert list and Silence list page
+
+## 0.7.0 / 2017-06-08
+
+* [CHANGE] Rewrite UI from scratch improving UX
+* [CHANGE] Rename `config` to `configYAML` on `api/v1/status`
+* [FEATURE] Add ability to update a silence on `api/v1/silences` POST endpoint (See #765)
+* [FEATURE] Return alert status on `api/v1/alerts` GET endpoint
+* [FEATURE] Serve silence state on `api/v1/silences` GET endpoint
+* [FEATURE] Add ability to specify a route prefix
+* [FEATURE] Add option to disable AM listening on mesh port
+* [ENHANCEMENT] Add ability to specify `filter` string and `silenced` flag on `api/v1/alerts` GET endpoint
+* [ENHANCEMENT] Update `cache-control` to prevent caching for web assets in general.
+* [ENHANCEMENT] Serve web assets by alertmanager instead of external CDN (See #846)
+* [ENHANCEMENT] Elide secrets in alertmanager config (See #840)
+* [ENHANCEMENT] AMTool: Move config file to a more consistent location (See #843)
+* [BUGFIX] Enable builds for Solaris/Illumos
+* [BUGFIX] Load web assets based on url path (See #323)
+
+## 0.6.2 / 2017-05-09
+
+* [BUGFIX] Correctly link to silences from alert again
+* [BUGFIX] Correctly hide silenced/show active alerts in UI again
+* [BUGFIX] Fix regression of alerts not being displayed until first processing
+* [BUGFIX] Fix internal usage of wrong lock for silence markers
+* [BUGFIX] Adapt amtool's API parsing to recent API changes
+* [BUGFIX] Correctly marshal regexes in config JSON response
+* [CHANGE] Anchor silence regex matchers to be consistent with Prometheus
+* [ENHANCEMENT] Error if root route is using `continue` keyword
+
+## 0.6.1 / 2017-04-28
+
+* [BUGFIX] Fix incorrectly serialized hash for notification providers.
+* [ENHANCEMENT] Add processing status field to alerts.
+* [FEATURE] Add config hash metric.
+
+## 0.6.0 / 2017-04-25
+
+* [BUGFIX] Add `groupKey` to `alerts/groups` endpoint https://github.com/prometheus/alertmanager/pull/576
+* [BUGFIX] Only notify on firing alerts https://github.com/prometheus/alertmanager/pull/595
+* [BUGFIX] Correctly marshal regex's in config for routing tree https://github.com/prometheus/alertmanager/pull/602
+* [BUGFIX] Prevent panic when failing to load config https://github.com/prometheus/alertmanager/pull/607
+* [BUGFIX] Prevent panic when alertmanager is started with an empty `-mesh.peer` https://github.com/prometheus/alertmanager/pull/726
+* [CHANGE] Rename VictorOps config variables https://github.com/prometheus/alertmanager/pull/667
+* [CHANGE] No longer generate releases for openbsd/arm https://github.com/prometheus/alertmanager/pull/732
+* [ENHANCEMENT] Add `DELETE` as accepted CORS method https://github.com/prometheus/alertmanager/commit/0ecc59076ca6b4cbb63252fa7720a3d89d1c81d3
+* [ENHANCEMENT] Switch to using `gogoproto` for protobuf https://github.com/prometheus/alertmanager/pull/715
+* [ENHANCEMENT] Include notifier type in logs and errors https://github.com/prometheus/alertmanager/pull/702
+* [FEATURE] Expose mesh peers on status page https://github.com/prometheus/alertmanager/pull/644
+* [FEATURE] Add `reReplaceAll` template function https://github.com/prometheus/alertmanager/pull/639
+* [FEATURE] Allow label-based filtering alerts/silences through API https://github.com/prometheus/alertmanager/pull/633
+* [FEATURE] Add commandline tool for interacting with alertmanager https://github.com/prometheus/alertmanager/pull/636
+
+## 0.5.1 / 2016-11-24
+
+* [BUGFIX] Fix crash caused by race condition in silencing
+* [ENHANCEMENT] Improve logging of API errors
+* [ENHANCEMENT] Add metrics for the notification log
+
+## 0.5.0 / 2016-11-01
+
+This release requires a storage wipe. It contains fundamental internal
+changes that came with implementing the high availability mode.
+
+* [FEATURE] Alertmanager clustering for high availability
+* [FEATURE] Garbage collection of old silences and notification logs
+* [CHANGE] New storage format
+* [CHANGE] Stricter silence semantics for consistent historical view
+
+## 0.4.2 / 2016-09-02
+
+* [BUGFIX] Fix broken regex checkbox in silence form
+* [BUGFIX] Simplify inconsistent silence update behavior
+
+## 0.4.1 / 2016-08-31
+
+* [BUGFIX] Wait for silence query to finish instead of showing error
+* [BUGFIX] Fix sorting of silences
+* [BUGFIX] Provide visual feedback after creating a silence
+* [BUGFIX] Fix styling of silences
+* [ENHANCEMENT] Provide cleaner API silence interface
+
+## 0.4.0 / 2016-08-23
+
+* [FEATURE] Silences are now paginated in the web ui
+* [CHANGE] Failure to start on unparsed flags
+
+## 0.3.0 / 2016-07-07
+
+* [CHANGE] Alerts are purely in memory and no longer persistent across restarts
+* [FEATURE] Add SMTP LOGIN authentication mechanism
+
+## 0.2.1 / 2016-06-23
+
+* [ENHANCEMENT] Allow inheritance of route receiver
+* [ENHANCEMENT] Add silence cache to silence provider
+* [BUGFIX] Fix HipChat room number in integration URL
+
+## 0.2.0 / 2016-06-17
+
+This release uses a new storage backend based on BoltDB. You have to backup
+and wipe your former storage path to run it.
+
+* [CHANGE] Use BoltDB as data store.
+* [CHANGE] Move SMTP authentification to configuration file
+* [FEATURE] add /-/reload HTTP endpoint
+* [FEATURE] Filter silenced alerts in web UI
+* [ENHANCEMENT] reduce inhibition computation complexity
+* [ENHANCEMENT] Add support for teams and tags in OpsGenie integration
+* [BUGFIX] Handle OpsGenie responses correctly
+* [BUGFIX] Fix Pushover queue length issue
+* [BUGFIX] STARTTLS before querying auth mechanism in email integration
+
+## 0.1.1 / 2016-03-15
+* [BUGFIX] Fix global database lock issue
+* [ENHANCEMENT] Improve SQLite alerts index
+* [ENHANCEMENT] Enable debug endpoint
+
+## 0.1.0 / 2016-02-23
+This version is a full rewrite of the Alertmanager with a very different
+feature set. Thus, there is no meaningful changelog.
+
+Changes with respect to 0.1.0-beta2:
+* [CHANGE] Expose same data structure to templates and webhook
+* [ENHANCEMENT] Show generator URL in default templates and web UI
+* [ENHANCEMENT] Support for Slack icon_emoji field
+* [ENHANCEMENT] Expose incident key to templates and webhook data
+* [ENHANCEMENT] Allow markdown in Slack 'text' field
+* [BUGFIX] Fixed database locking issue
+
+## 0.1.0-beta2 / 2016-02-03
+* [BUGFIX] Properly set timeout for incoming alerts with fixed start time
+* [ENHANCEMENT] Send source field in OpsGenie integration
+* [ENHANCEMENT] Improved routing configuration validation
+* [FEATURE] Basic instrumentation added
+
+## 0.1.0-beta1 / 2016-01-08
+* [BUGFIX] Send full alert group state on each update. Fixes erroneous resolved notifications.
+* [FEATURE] HipChat integration
+* [CHANGE] Slack integration no longer sends resolved notifications by default
+
+## 0.1.0-beta0 / 2015-12-23
+This version is a full rewrite of the Alertmanager with a very different
+feature set. Thus, there is no meaningful changelog.
+
+## 0.0.4 / 2015-09-09
+* [BUGFIX] Fix version info string in startup message.
+* [BUGFIX] Fix Pushover notifications by setting the right priority level, as
+ well as required retry and expiry intervals.
+* [FEATURE] Make it possible to link to individual alerts in the UI.
+* [FEATURE] Rearrange alert columns in UI and allow expanding more alert details.
+* [FEATURE] Add Amazon SNS notifications.
+* [FEATURE] Add OpsGenie Webhook notifications.
+* [FEATURE] Add `-web.external-url` flag to control the externally visible
+ Alertmanager URL.
+* [FEATURE] Add runbook and alertmanager URLs to PagerDuty and email notifications.
+* [FEATURE] Add a GET API to /api/alerts which pulls JSON formatted
+ AlertAggregates.
+* [ENHANCEMENT] Sort alerts consistently in web UI.
+* [ENHANCEMENT] Suggest to use email address as silence creator.
+* [ENHANCEMENT] Make Slack timeout configurable.
+* [ENHANCEMENT] Add channel name to error logging about Slack notifications.
+* [ENHANCEMENT] Refactoring and tests for Flowdock notifications.
+* [ENHANCEMENT] New Dockerfile using alpine-golang-make-onbuild base image.
+* [CLEANUP] Add Docker instructions and other cleanups in README.md.
+* [CLEANUP] Update Makefile.COMMON from prometheus/utils.
+
+## 0.0.3 / 2015-06-10
+* [BUGFIX] Fix email template body writer being called with parameters in wrong order.
+
+## 0.0.2 / 2015-06-09
+
+* [BUGFIX] Fixed silences.json permissions in Docker image.
+* [CHANGE] Changed case of API JSON properties to initial lower letter.
+* [CHANGE] Migrated logging to use http://github.com/prometheus/log.
+* [FEATURE] Flowdock notification support.
+* [FEATURE] Slack notification support.
+* [FEATURE] Generic webhook notification support.
+* [FEATURE] Support for "@"-mentions in HipChat notifications.
+* [FEATURE] Path prefix option to support reverse proxies.
+* [ENHANCEMENT] Improved web redirection and 404 behavior.
+* [CLEANUP] Updated compiled web assets from source.
+* [CLEANUP] Updated fsnotify package to its new source location.
+* [CLEANUP] Updates to README.md and AUTHORS.md.
+* [CLEANUP] Various smaller cleanups and improvements.
--- /dev/null
+# Contributing
+
+Alertmanager uses GitHub to manage reviews of pull requests.
+
+* If you have a trivial fix or improvement, go ahead and create a pull request,
+ addressing (with `@...`) the maintainer of this repository (see
+ [MAINTAINERS.md](MAINTAINERS.md)) in the description of the pull request.
+
+* If you plan to do something more involved, first discuss your ideas
+ on our [mailing list](https://groups.google.com/forum/?fromgroups#!forum/prometheus-developers).
+ This will avoid unnecessary work and surely give you and us a good deal
+ of inspiration.
+
+* Relevant coding style guidelines are the [Go Code Review
+ Comments](https://code.google.com/p/go-wiki/wiki/CodeReviewComments)
+ and the _Formatting and style_ section of Peter Bourgon's [Go: Best
+ Practices for Production
+ Environments](http://peter.bourgon.org/go-in-production/#formatting-and-style).
--- /dev/null
+FROM prom/busybox:latest
+MAINTAINER The Prometheus Authors <prometheus-developers@googlegroups.com>
+
+COPY amtool /bin/amtool
+COPY alertmanager /bin/alertmanager
+COPY examples/ha/alertmanager.yml /etc/alertmanager/alertmanager.yml
+
+EXPOSE 9093
+VOLUME [ "/alertmanager" ]
+WORKDIR /etc/alertmanager
+ENTRYPOINT [ "/bin/alertmanager" ]
+CMD [ "--storage.path=/alertmanager" ]
--- /dev/null
+FROM arm64v8/busybox:latest
+MAINTAINER The Prometheus Authors <prometheus-developers@googlegroups.com>
+
+COPY amtool /bin/amtool
+COPY alertmanager /bin/alertmanager
+COPY examples/ha/alertmanager.yml /etc/alertmanager/alertmanager.yml
+RUN chmod +x /bin/amtool /bin/alertmanager
+
+EXPOSE 9093
+VOLUME [ "/alertmanager" ]
+WORKDIR /etc/alertmanager
+ENTRYPOINT [ "/bin/alertmanager" ]
+CMD [ "--storage.path=/alertmanager" ]
--- /dev/null
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
--- /dev/null
+* Stuart Nelson <stuartnelson3@gmail.com>
--- /dev/null
+# Copyright 2015 The Prometheus Authors
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+include Makefile.common
+
+FRONTEND_DIR = $(BIN_DIR)/ui/app
+DOCKER_IMAGE_NAME ?= alertmanager
+
+ifdef DEBUG
+ bindata_flags = -debug
+endif
+
+STATICCHECK_IGNORE = \
+ github.com/prometheus/alertmanager/notify/notify.go:SA6002
+
+
+.PHONY: build-all
+# Will build both the front-end as well as the back-end
+build-all: assets build
+
+assets: go-bindata ui/bindata.go template/internal/deftmpl/bindata.go
+
+go-bindata:
+ -@$(GO) get -u github.com/jteeuwen/go-bindata/...
+
+template/internal/deftmpl/bindata.go: template/default.tmpl
+ @go-bindata $(bindata_flags) -mode 420 -modtime 1 -pkg deftmpl -o template/internal/deftmpl/bindata.go template/default.tmpl
+ @$(GO) fmt ./template/internal/deftmpl
+
+ui/bindata.go: ui/app/script.js ui/app/index.html ui/app/lib
+# Using "-mode 420" and "-modtime 1" to make assets make target deterministic.
+# It sets all file permissions and time stamps to 420 and 1
+ @go-bindata $(bindata_flags) -mode 420 -modtime 1 -pkg ui -o \
+ ui/bindata.go ui/app/script.js \
+ ui/app/index.html \
+ ui/app/favicon.ico \
+ ui/app/lib/...
+ @$(GO) fmt ./ui
+
+ui/app/script.js: $(shell find ui/app/src -iname *.elm)
+ cd $(FRONTEND_DIR) && $(MAKE) script.js
+
+.PHONY: proto
+proto:
+ scripts/genproto.sh
+
+.PHONY: clean
+clean:
+ rm template/internal/deftmpl/bindata.go
+ rm ui/bindata.go
+ cd $(FRONTEND_DIR) && $(MAKE) clean
--- /dev/null
+# Copyright 2018 The Prometheus Authors
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+# A common Makefile that includes rules to be reused in different prometheus projects.
+# !!! Open PRs only against the prometheus/prometheus/Makefile.common repository!
+
+# Example usage :
+# Create the main Makefile in the root project directory.
+# include Makefile.common
+# customTarget:
+# @echo ">> Running customTarget"
+#
+
+# Ensure GOBIN is not set during build so that promu is installed to the correct path
+unexport GOBIN
+
+GO ?= go
+GOFMT ?= $(GO)fmt
+FIRST_GOPATH := $(firstword $(subst :, ,$(shell $(GO) env GOPATH)))
+PROMU := $(FIRST_GOPATH)/bin/promu
+STATICCHECK := $(FIRST_GOPATH)/bin/staticcheck
+GOVENDOR := $(FIRST_GOPATH)/bin/govendor
+pkgs = ./...
+
+PREFIX ?= $(shell pwd)
+BIN_DIR ?= $(shell pwd)
+DOCKER_IMAGE_TAG ?= $(subst /,-,$(shell git rev-parse --abbrev-ref HEAD))
+MACH ?= $(shell uname -m)
+DOCKERFILE ?= Dockerfile
+
+.PHONY: all
+all: style staticcheck unused build test
+
+.PHONY: style
+style:
+ @echo ">> checking code style"
+ ! $(GOFMT) -d $$(find . -path ./vendor -prune -o -name '*.go' -print) | grep '^'
+
+.PHONY: check_license
+check_license:
+ @echo ">> checking license header"
+ @licRes=$$(for file in $$(find . -type f -iname '*.go' ! -path './vendor/*') ; do \
+ awk 'NR<=3' $$file | grep -Eq "(Copyright|generated|GENERATED)" || echo $$file; \
+ done); \
+ if [ -n "$${licRes}" ]; then \
+ echo "license header checking failed:"; echo "$${licRes}"; \
+ exit 1; \
+ fi
+
+.PHONY: test-short
+test-short:
+ @echo ">> running short tests"
+ $(GO) test -short $(pkgs)
+
+.PHONY: test
+test:
+ @echo ">> running all tests"
+ $(GO) test -race $(pkgs)
+
+.PHONY: format
+format:
+ @echo ">> formatting code"
+ $(GO) fmt $(pkgs)
+
+.PHONY: vet
+vet:
+ @echo ">> vetting code"
+ $(GO) vet $(pkgs)
+
+.PHONY: staticcheck
+staticcheck: $(STATICCHECK)
+ @echo ">> running staticcheck"
+ $(STATICCHECK) -ignore "$(STATICCHECK_IGNORE)" $(pkgs)
+
+.PHONY: unused
+unused: $(GOVENDOR)
+ @echo ">> running check for unused packages"
+ @$(GOVENDOR) list +unused | grep . && exit 1 || echo 'No unused packages'
+
+.PHONY: build
+build: promu
+ @echo ">> building binaries"
+ $(PROMU) build --prefix $(PREFIX)
+
+.PHONY: tarball
+tarball: promu
+ @echo ">> building release tarball"
+ $(PROMU) tarball --prefix $(PREFIX) $(BIN_DIR)
+
+.PHONY: docker
+docker:
+ifeq ($(MACH), aarch64)
+ $(eval DOCKERFILE=Dockerfile.arm64v8)
+endif
+ @echo ">> building docker image from $(DOCKERFILE)"
+ docker build --file $(DOCKERFILE) -t "$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)" .
+
+.PHONY: promu
+promu:
+ GOOS= GOARCH= $(GO) get -u github.com/prometheus/promu
+
+.PHONY: $(STATICCHECK)
+$(STATICCHECK):
+ GOOS= GOARCH= $(GO) get -u honnef.co/go/tools/cmd/staticcheck
+
+.PHONY: $(GOVENDOR)
+$(GOVENDOR):
+ GOOS= GOARCH= $(GO) get -u github.com/kardianos/govendor
--- /dev/null
+Prometheus Alertmanager
+Copyright 2013-2015 The Prometheus Authors
+
+This product includes software developed at
+SoundCloud Ltd. (http://soundcloud.com/).
+
+
+The following components are included in this product:
+
+Bootstrap
+http://getbootstrap.com
+Copyright 2011-2014 Twitter, Inc.
+Licensed under the MIT License
+
+bootstrap-datetimepicker.js
+http://www.eyecon.ro/bootstrap-datepicker
+Copyright 2012 Stefan Petre
+Licensed under the Apache License, Version 2.0
--- /dev/null
+a1: ./alertmanager --log.level=debug --storage.path=$TMPDIR/a1 --web.listen-address=:9093 --cluster.listen-address=127.0.0.1:8001 --config.file=examples/ha/alertmanager.yml
+a2: ./alertmanager --log.level=debug --storage.path=$TMPDIR/a2 --web.listen-address=:9094 --cluster.listen-address=127.0.0.1:8002 --cluster.peer=127.0.0.1:8001 --config.file=examples/ha/alertmanager.yml
+a3: ./alertmanager --log.level=debug --storage.path=$TMPDIR/a3 --web.listen-address=:9095 --cluster.listen-address=127.0.0.1:8003 --cluster.peer=127.0.0.1:8001 --config.file=examples/ha/alertmanager.yml
+wh: go run ./examples/webhook/echo.go
+
--- /dev/null
+# Alertmanager [][travis]
+
+[][circleci]
+[][quay]
+[][hub]
+
+The Alertmanager handles alerts sent by client applications such as the Prometheus server. It takes care of deduplicating, grouping, and routing them to the correct receiver integrations such as email, PagerDuty, or OpsGenie. It also takes care of silencing and inhibition of alerts.
+
+* [Documentation](http://prometheus.io/docs/alerting/alertmanager/)
+
+
+## Install
+
+There are various ways of installing Alertmanager.
+
+### Precompiled binaries
+
+Precompiled binaries for released versions are available in the
+[*download* section](https://prometheus.io/download/)
+on [prometheus.io](https://prometheus.io). Using the latest production release binary
+is the recommended way of installing Alertmanager.
+
+### Docker images
+
+Docker images are available on [Quay.io](https://quay.io/repository/prometheus/alertmanager).
+
+### Compiling the binary
+
+You can either `go get` it:
+
+```
+$ GO15VENDOREXPERIMENT=1 go get github.com/prometheus/alertmanager/cmd/...
+# cd $GOPATH/src/github.com/prometheus/alertmanager
+$ alertmanager --config.file=<your_file>
+```
+
+Or checkout the source code and build manually:
+
+```
+$ mkdir -p $GOPATH/src/github.com/prometheus
+$ cd $GOPATH/src/github.com/prometheus
+$ git clone https://github.com/prometheus/alertmanager.git
+$ cd alertmanager
+$ make build
+$ ./alertmanager --config.file=<your_file>
+```
+
+You can also build just one of the binaries in this repo by passing a name to the build function:
+```
+$ make build BINARIES=amtool
+```
+
+## Example
+
+This is an example configuration that should cover most relevant aspects of the new YAML configuration format. The full documentation of the configuration can be found [here](https://prometheus.io/docs/alerting/configuration/).
+
+```yaml
+global:
+ # The smarthost and SMTP sender used for mail notifications.
+ smtp_smarthost: 'localhost:25'
+ smtp_from: 'alertmanager@example.org'
+
+# The root route on which each incoming alert enters.
+route:
+ # The root route must not have any matchers as it is the entry point for
+ # all alerts. It needs to have a receiver configured so alerts that do not
+ # match any of the sub-routes are sent to someone.
+ receiver: 'team-X-mails'
+
+ # The labels by which incoming alerts are grouped together. For example,
+ # multiple alerts coming in for cluster=A and alertname=LatencyHigh would
+ # be batched into a single group.
+ group_by: ['alertname', 'cluster']
+
+ # When a new group of alerts is created by an incoming alert, wait at
+ # least 'group_wait' to send the initial notification.
+ # This way ensures that you get multiple alerts for the same group that start
+ # firing shortly after another are batched together on the first
+ # notification.
+ group_wait: 30s
+
+ # When the first notification was sent, wait 'group_interval' to send a batch
+ # of new alerts that started firing for that group.
+ group_interval: 5m
+
+ # If an alert has successfully been sent, wait 'repeat_interval' to
+ # resend them.
+ repeat_interval: 3h
+
+ # All the above attributes are inherited by all child routes and can
+ # overwritten on each.
+
+ # The child route trees.
+ routes:
+ # This routes performs a regular expression match on alert labels to
+ # catch alerts that are related to a list of services.
+ - match_re:
+ service: ^(foo1|foo2|baz)$
+ receiver: team-X-mails
+
+ # The service has a sub-route for critical alerts, any alerts
+ # that do not match, i.e. severity != critical, fall-back to the
+ # parent node and are sent to 'team-X-mails'
+ routes:
+ - match:
+ severity: critical
+ receiver: team-X-pager
+
+ - match:
+ service: files
+ receiver: team-Y-mails
+
+ routes:
+ - match:
+ severity: critical
+ receiver: team-Y-pager
+
+ # This route handles all alerts coming from a database service. If there's
+ # no team to handle it, it defaults to the DB team.
+ - match:
+ service: database
+
+ receiver: team-DB-pager
+ # Also group alerts by affected database.
+ group_by: [alertname, cluster, database]
+
+ routes:
+ - match:
+ owner: team-X
+ receiver: team-X-pager
+
+ - match:
+ owner: team-Y
+ receiver: team-Y-pager
+
+
+# Inhibition rules allow to mute a set of alerts given that another alert is
+# firing.
+# We use this to mute any warning-level notifications if the same alert is
+# already critical.
+inhibit_rules:
+- source_match:
+ severity: 'critical'
+ target_match:
+ severity: 'warning'
+ # Apply inhibition if the alertname is the same.
+ equal: ['alertname']
+
+
+receivers:
+- name: 'team-X-mails'
+ email_configs:
+ - to: 'team-X+alerts@example.org, team-Y+alerts@example.org'
+
+- name: 'team-X-pager'
+ email_configs:
+ - to: 'team-X+alerts-critical@example.org'
+ pagerduty_configs:
+ - routing_key: <team-X-key>
+
+- name: 'team-Y-mails'
+ email_configs:
+ - to: 'team-Y+alerts@example.org'
+
+- name: 'team-Y-pager'
+ pagerduty_configs:
+ - routing_key: <team-Y-key>
+
+- name: 'team-DB-pager'
+ pagerduty_configs:
+ - routing_key: <team-DB-key>
+```
+
+## Amtool
+
+`amtool` is a cli tool for interacting with the alertmanager api. It is bundled with all releases of alertmanager.
+
+### Install
+
+Alternatively you can install with:
+```
+go get github.com/prometheus/alertmanager/cmd/amtool
+```
+
+### Examples
+
+View all currently firing alerts
+```
+$ amtool alert
+Alertname Starts At Summary
+Test_Alert 2017-08-02 18:30:18 UTC This is a testing alert!
+Test_Alert 2017-08-02 18:30:18 UTC This is a testing alert!
+Check_Foo_Fails 2017-08-02 18:30:18 UTC This is a testing alert!
+Check_Foo_Fails 2017-08-02 18:30:18 UTC This is a testing alert!
+```
+
+View all currently firing alerts with extended output
+```
+$ amtool -o extended alert
+Labels Annotations Starts At Ends At Generator URL
+alertname="Test_Alert" instance="node0" link="https://example.com" summary="This is a testing alert!" 2017-08-02 18:31:24 UTC 0001-01-01 00:00:00 UTC http://my.testing.script.local
+alertname="Test_Alert" instance="node1" link="https://example.com" summary="This is a testing alert!" 2017-08-02 18:31:24 UTC 0001-01-01 00:00:00 UTC http://my.testing.script.local
+alertname="Check_Foo_Fails" instance="node0" link="https://example.com" summary="This is a testing alert!" 2017-08-02 18:31:24 UTC 0001-01-01 00:00:00 UTC http://my.testing.script.local
+alertname="Check_Foo_Fails" instance="node1" link="https://example.com" summary="This is a testing alert!" 2017-08-02 18:31:24 UTC 0001-01-01 00:00:00 UTC http://my.testing.script.local
+```
+
+In addition to viewing alerts you can use the rich query syntax provided by alertmanager
+```
+$ amtool -o extended alert query alertname="Test_Alert"
+Labels Annotations Starts At Ends At Generator URL
+alertname="Test_Alert" instance="node0" link="https://example.com" summary="This is a testing alert!" 2017-08-02 18:31:24 UTC 0001-01-01 00:00:00 UTC http://my.testing.script.local
+alertname="Test_Alert" instance="node1" link="https://example.com" summary="This is a testing alert!" 2017-08-02 18:31:24 UTC 0001-01-01 00:00:00 UTC http://my.testing.script.local
+
+$ amtool -o extended alert query instance=~".+1"
+Labels Annotations Starts At Ends At Generator URL
+alertname="Test_Alert" instance="node1" link="https://example.com" summary="This is a testing alert!" 2017-08-02 18:31:24 UTC 0001-01-01 00:00:00 UTC http://my.testing.script.local
+alertname="Check_Foo_Fails" instance="node1" link="https://example.com" summary="This is a testing alert!" 2017-08-02 18:31:24 UTC 0001-01-01 00:00:00 UTC http://my.testing.script.local
+
+$ amtool -o extended alert query alertname=~"Test.*" instance=~".+1"
+Labels Annotations Starts At Ends At Generator URL
+alertname="Test_Alert" instance="node1" link="https://example.com" summary="This is a testing alert!" 2017-08-02 18:31:24 UTC 0001-01-01 00:00:00 UTC http://my.testing.script.local
+```
+
+Silence an alert
+```
+$ amtool silence add alertname=Test_Alert
+b3ede22e-ca14-4aa0-932c-ca2f3445f926
+
+$ amtool silence add alertname="Test_Alert" instance=~".+0"
+e48cb58a-0b17-49ba-b734-3585139b1d25
+```
+
+View silences
+```
+$ amtool silence query
+ID Matchers Ends At Created By Comment
+b3ede22e-ca14-4aa0-932c-ca2f3445f926 alertname=Test_Alert 2017-08-02 19:54:50 UTC kellel
+
+$ amtool silence query instance=~".+0"
+ID Matchers Ends At Created By Comment
+e48cb58a-0b17-49ba-b734-3585139b1d25 alertname=Test_Alert instance=~.+0 2017-08-02 22:41:39 UTC kellel
+```
+
+Expire a silence
+```
+$ amtool silence expire b3ede22e-ca14-4aa0-932c-ca2f3445f926
+```
+
+Expire all silences matching a query
+```
+$ amtool silence query instance=~".+0"
+ID Matchers Ends At Created By Comment
+e48cb58a-0b17-49ba-b734-3585139b1d25 alertname=Test_Alert instance=~.+0 2017-08-02 22:41:39 UTC kellel
+
+$ amtool silence expire $(amtool silence -q query instance=~".+0")
+
+$ amtool silence query instance=~".+0"
+
+```
+
+Expire all silences
+```
+$ amtool silence expire $(amtool silence query -q)
+```
+
+### Config
+
+Amtool allows a config file to specify some options for convenience. The default config file paths are `$HOME/.config/amtool/config.yml` or `/etc/amtool/config.yml`
+
+An example configfile might look like the following:
+
+```
+# Define the path that amtool can find your `alertmanager` instance at
+alertmanager.url: "http://localhost:9093"
+
+# Override the default author. (unset defaults to your username)
+author: me@example.com
+
+# Force amtool to give you an error if you don't include a comment on a silence
+comment_required: true
+
+# Set a default output format. (unset defaults to simple)
+output: extended
+
+# Set a default receiver
+receiver: team-X-pager
+```
+
+## High Availability
+
+> Warning: High Availability is under active development
+
+To create a highly available cluster of the Alertmanager the instances need to
+be configured to communicate with each other. This is configured using the
+`--cluster.*` flags.
+
+- `--cluster.listen-address` string: cluster listen address (default "0.0.0.0:9094")
+- `--cluster.advertise-address` string: cluster advertise address
+- `--cluster.peer` value: initial peers (repeat flag for each additional peer)
+- `--cluster.peer-timeout` value: peer timeout period (default "15s")
+- `--cluster.gossip-interval` value: cluster message propagation speed
+ (default "200ms")
+- `--cluster.pushpull-interval` value: lower values will increase
+ convergence speeds at expense of bandwidth (default "1m0s")
+- `--cluster.settle-timeout` value: maximum time to wait for cluster
+ connections to settle before evaluating notifications.
+- `--cluster.tcp-timeout` value: timeout value for tcp connections, reads and writes (default "10s")
+- `--cluster.probe-timeout` value: time to wait for ack before marking node unhealthy
+ (default "500ms")
+- `--cluster.probe-interval` value: interval between random node probes (default "1s")
+
+The chosen port in the `cluster.listen-address` flag is the port that needs to be
+specified in the `cluster.peer` flag of the other peers.
+
+To start a cluster of three peers on your local machine use `goreman` and the
+Procfile within this repository.
+
+ goreman start
+
+To point your Prometheus 1.4, or later, instance to multiple Alertmanagers, configure them
+in your `prometheus.yml` configuration file, for example:
+
+```yaml
+alerting:
+ alertmanagers:
+ - static_configs:
+ - targets:
+ - alertmanager1:9093
+ - alertmanager2:9093
+ - alertmanager3:9093
+```
+
+> Important: Do not load balance traffic between Prometheus and its Alertmanagers, but instead point Prometheus to a list of all Alertmanagers. The Alertmanager implementation expects all alerts to be sent to all Alertmanagers to ensure high availability.
+
+## Contributing to the Front-End
+
+Refer to [ui/app/CONTRIBUTING.md](ui/app/CONTRIBUTING.md).
+
+## Architecture
+
+
+
+
+[travis]: https://travis-ci.org/prometheus/alertmanager
+[hub]: https://hub.docker.com/r/prom/alertmanager/
+[circleci]: https://circleci.com/gh/prometheus/alertmanager
+[quay]: https://quay.io/repository/prometheus/alertmanager
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package api
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net/http"
+ "regexp"
+ "sort"
+ "sync"
+ "time"
+
+ "github.com/go-kit/kit/log"
+ "github.com/go-kit/kit/log/level"
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/common/model"
+ "github.com/prometheus/common/route"
+ "github.com/prometheus/common/version"
+ "github.com/prometheus/prometheus/pkg/labels"
+
+ "github.com/prometheus/alertmanager/cluster"
+ "github.com/prometheus/alertmanager/config"
+ "github.com/prometheus/alertmanager/dispatch"
+ "github.com/prometheus/alertmanager/pkg/parse"
+ "github.com/prometheus/alertmanager/provider"
+ "github.com/prometheus/alertmanager/silence"
+ "github.com/prometheus/alertmanager/silence/silencepb"
+ "github.com/prometheus/alertmanager/types"
+)
+
+var (
+ numReceivedAlerts = prometheus.NewCounterVec(prometheus.CounterOpts{
+ Namespace: "alertmanager",
+ Name: "alerts_received_total",
+ Help: "The total number of received alerts.",
+ }, []string{"status"})
+
+ numInvalidAlerts = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "alertmanager",
+ Name: "alerts_invalid_total",
+ Help: "The total number of received alerts that were invalid.",
+ })
+)
+
+func init() {
+ numReceivedAlerts.WithLabelValues("firing")
+ numReceivedAlerts.WithLabelValues("resolved")
+
+ prometheus.Register(numReceivedAlerts)
+ prometheus.Register(numInvalidAlerts)
+}
+
+var corsHeaders = map[string]string{
+ "Access-Control-Allow-Headers": "Accept, Authorization, Content-Type, Origin",
+ "Access-Control-Allow-Methods": "GET, DELETE, OPTIONS",
+ "Access-Control-Allow-Origin": "*",
+ "Access-Control-Expose-Headers": "Date",
+}
+
+// Enables cross-site script calls.
+func setCORS(w http.ResponseWriter) {
+ for h, v := range corsHeaders {
+ w.Header().Set(h, v)
+ }
+}
+
+// API provides registration of handlers for API routes.
+type API struct {
+ alerts provider.Alerts
+ silences *silence.Silences
+ config *config.Config
+ route *dispatch.Route
+ resolveTimeout time.Duration
+ uptime time.Time
+ peer *cluster.Peer
+ logger log.Logger
+
+ groups groupsFn
+ getAlertStatus getAlertStatusFn
+
+ mtx sync.RWMutex
+}
+
+type groupsFn func([]*labels.Matcher) dispatch.AlertOverview
+type getAlertStatusFn func(model.Fingerprint) types.AlertStatus
+
+// New returns a new API.
+func New(
+ alerts provider.Alerts,
+ silences *silence.Silences,
+ gf groupsFn,
+ sf getAlertStatusFn,
+ peer *cluster.Peer,
+ l log.Logger,
+) *API {
+ if l == nil {
+ l = log.NewNopLogger()
+ }
+
+ return &API{
+ alerts: alerts,
+ silences: silences,
+ groups: gf,
+ getAlertStatus: sf,
+ uptime: time.Now(),
+ peer: peer,
+ logger: l,
+ }
+}
+
+// Register registers the API handlers under their correct routes
+// in the given router.
+func (api *API) Register(r *route.Router) {
+ wrap := func(f http.HandlerFunc) http.HandlerFunc {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ setCORS(w)
+ f(w, r)
+ })
+ }
+
+ r.Options("/*path", wrap(func(w http.ResponseWriter, r *http.Request) {}))
+
+ r.Get("/status", wrap(api.status))
+ r.Get("/receivers", wrap(api.receivers))
+
+ r.Get("/alerts/groups", wrap(api.alertGroups))
+ r.Get("/alerts", wrap(api.listAlerts))
+ r.Post("/alerts", wrap(api.addAlerts))
+
+ r.Get("/silences", wrap(api.listSilences))
+ r.Post("/silences", wrap(api.setSilence))
+ r.Get("/silence/:sid", wrap(api.getSilence))
+ r.Del("/silence/:sid", wrap(api.delSilence))
+}
+
+// Update sets the configuration string to a new value.
+func (api *API) Update(cfg *config.Config, resolveTimeout time.Duration) error {
+ api.mtx.Lock()
+ defer api.mtx.Unlock()
+
+ api.resolveTimeout = resolveTimeout
+ api.config = cfg
+ api.route = dispatch.NewRoute(cfg.Route, nil)
+ return nil
+}
+
+type errorType string
+
+const (
+ errorNone errorType = ""
+ errorInternal errorType = "server_error"
+ errorBadData errorType = "bad_data"
+)
+
+type apiError struct {
+ typ errorType
+ err error
+}
+
+func (e *apiError) Error() string {
+ return fmt.Sprintf("%s: %s", e.typ, e.err)
+}
+
+func (api *API) receivers(w http.ResponseWriter, req *http.Request) {
+ api.mtx.RLock()
+ defer api.mtx.RUnlock()
+
+ receivers := make([]string, 0, len(api.config.Receivers))
+ for _, r := range api.config.Receivers {
+ receivers = append(receivers, r.Name)
+ }
+
+ api.respond(w, receivers)
+}
+
+func (api *API) status(w http.ResponseWriter, req *http.Request) {
+ api.mtx.RLock()
+
+ var status = struct {
+ ConfigYAML string `json:"configYAML"`
+ ConfigJSON *config.Config `json:"configJSON"`
+ VersionInfo map[string]string `json:"versionInfo"`
+ Uptime time.Time `json:"uptime"`
+ ClusterStatus *clusterStatus `json:"clusterStatus"`
+ }{
+ ConfigYAML: api.config.String(),
+ ConfigJSON: api.config,
+ VersionInfo: map[string]string{
+ "version": version.Version,
+ "revision": version.Revision,
+ "branch": version.Branch,
+ "buildUser": version.BuildUser,
+ "buildDate": version.BuildDate,
+ "goVersion": version.GoVersion,
+ },
+ Uptime: api.uptime,
+ ClusterStatus: getClusterStatus(api.peer),
+ }
+
+ api.mtx.RUnlock()
+
+ api.respond(w, status)
+}
+
+type peerStatus struct {
+ Name string `json:"name"`
+ Address string `json:"address"`
+}
+
+type clusterStatus struct {
+ Name string `json:"name"`
+ Status string `json:"status"`
+ Peers []peerStatus `json:"peers"`
+}
+
+func getClusterStatus(p *cluster.Peer) *clusterStatus {
+ if p == nil {
+ return nil
+ }
+ s := &clusterStatus{Name: p.Name(), Status: p.Status()}
+
+ for _, n := range p.Peers() {
+ s.Peers = append(s.Peers, peerStatus{
+ Name: n.Name,
+ Address: n.Address(),
+ })
+ }
+ return s
+}
+
+func (api *API) alertGroups(w http.ResponseWriter, r *http.Request) {
+ var err error
+ matchers := []*labels.Matcher{}
+
+ if filter := r.FormValue("filter"); filter != "" {
+ matchers, err = parse.Matchers(filter)
+ if err != nil {
+ api.respondError(w, apiError{
+ typ: errorBadData,
+ err: err,
+ }, nil)
+ return
+ }
+ }
+
+ groups := api.groups(matchers)
+
+ api.respond(w, groups)
+}
+
+func (api *API) listAlerts(w http.ResponseWriter, r *http.Request) {
+ var (
+ err error
+ receiverFilter *regexp.Regexp
+ // Initialize result slice to prevent api returning `null` when there
+ // are no alerts present
+ res = []*dispatch.APIAlert{}
+ matchers = []*labels.Matcher{}
+
+ showActive, showInhibited bool
+ showSilenced, showUnprocessed bool
+ )
+
+ getBoolParam := func(name string) (bool, error) {
+ v := r.FormValue(name)
+ if v == "" {
+ return true, nil
+ }
+ if v == "false" {
+ return false, nil
+ }
+ if v != "true" {
+ err := fmt.Errorf("parameter %q can either be 'true' or 'false', not %q", name, v)
+ api.respondError(w, apiError{
+ typ: errorBadData,
+ err: err,
+ }, nil)
+ return false, err
+ }
+ return true, nil
+ }
+
+ if filter := r.FormValue("filter"); filter != "" {
+ matchers, err = parse.Matchers(filter)
+ if err != nil {
+ api.respondError(w, apiError{
+ typ: errorBadData,
+ err: err,
+ }, nil)
+ return
+ }
+ }
+
+ showActive, err = getBoolParam("active")
+ if err != nil {
+ return
+ }
+
+ showSilenced, err = getBoolParam("silenced")
+ if err != nil {
+ return
+ }
+
+ showInhibited, err = getBoolParam("inhibited")
+ if err != nil {
+ return
+ }
+
+ showUnprocessed, err = getBoolParam("unprocessed")
+ if err != nil {
+ return
+ }
+
+ if receiverParam := r.FormValue("receiver"); receiverParam != "" {
+ receiverFilter, err = regexp.Compile("^(?:" + receiverParam + ")$")
+ if err != nil {
+ api.respondError(w, apiError{
+ typ: errorBadData,
+ err: fmt.Errorf(
+ "failed to parse receiver param: %s",
+ receiverParam,
+ ),
+ }, nil)
+ return
+ }
+ }
+
+ alerts := api.alerts.GetPending()
+ defer alerts.Close()
+
+ api.mtx.RLock()
+ // TODO(fabxc): enforce a sensible timeout.
+ for a := range alerts.Next() {
+ if err = alerts.Err(); err != nil {
+ break
+ }
+
+ routes := api.route.Match(a.Labels)
+ receivers := make([]string, 0, len(routes))
+ for _, r := range routes {
+ receivers = append(receivers, r.RouteOpts.Receiver)
+ }
+
+ if receiverFilter != nil && !receiversMatchFilter(receivers, receiverFilter) {
+ continue
+ }
+
+ if !alertMatchesFilterLabels(&a.Alert, matchers) {
+ continue
+ }
+
+ // Continue if the alert is resolved.
+ if !a.Alert.EndsAt.IsZero() && a.Alert.EndsAt.Before(time.Now()) {
+ continue
+ }
+
+ status := api.getAlertStatus(a.Fingerprint())
+
+ if !showActive && status.State == types.AlertStateActive {
+ continue
+ }
+
+ if !showUnprocessed && status.State == types.AlertStateUnprocessed {
+ continue
+ }
+
+ if !showSilenced && len(status.SilencedBy) != 0 {
+ continue
+ }
+
+ if !showInhibited && len(status.InhibitedBy) != 0 {
+ continue
+ }
+
+ apiAlert := &dispatch.APIAlert{
+ Alert: &a.Alert,
+ Status: status,
+ Receivers: receivers,
+ Fingerprint: a.Fingerprint().String(),
+ }
+
+ res = append(res, apiAlert)
+ }
+ api.mtx.RUnlock()
+
+ if err != nil {
+ api.respondError(w, apiError{
+ typ: errorInternal,
+ err: err,
+ }, nil)
+ return
+ }
+ sort.Slice(res, func(i, j int) bool {
+ return res[i].Fingerprint < res[j].Fingerprint
+ })
+ api.respond(w, res)
+}
+
+func receiversMatchFilter(receivers []string, filter *regexp.Regexp) bool {
+ for _, r := range receivers {
+ if filter.MatchString(r) {
+ return true
+ }
+ }
+
+ return false
+}
+
+func alertMatchesFilterLabels(a *model.Alert, matchers []*labels.Matcher) bool {
+ sms := make(map[string]string)
+ for name, value := range a.Labels {
+ sms[string(name)] = string(value)
+ }
+ return matchFilterLabels(matchers, sms)
+}
+
+func (api *API) addAlerts(w http.ResponseWriter, r *http.Request) {
+ var alerts []*types.Alert
+ if err := api.receive(r, &alerts); err != nil {
+ api.respondError(w, apiError{
+ typ: errorBadData,
+ err: err,
+ }, nil)
+ return
+ }
+
+ api.insertAlerts(w, r, alerts...)
+}
+
+func (api *API) insertAlerts(w http.ResponseWriter, r *http.Request, alerts ...*types.Alert) {
+ now := time.Now()
+
+ api.mtx.RLock()
+ resolveTimeout := api.resolveTimeout
+ api.mtx.RUnlock()
+
+ for _, alert := range alerts {
+ alert.UpdatedAt = now
+
+ // Ensure StartsAt is set.
+ if alert.StartsAt.IsZero() {
+ if alert.EndsAt.IsZero() {
+ alert.StartsAt = now
+ } else {
+ alert.StartsAt = alert.EndsAt
+ }
+ }
+ // If no end time is defined, set a timeout after which an alert
+ // is marked resolved if it is not updated.
+ if alert.EndsAt.IsZero() {
+ alert.Timeout = true
+ alert.EndsAt = now.Add(resolveTimeout)
+ }
+ if alert.EndsAt.After(time.Now()) {
+ numReceivedAlerts.WithLabelValues("firing").Inc()
+ } else {
+ numReceivedAlerts.WithLabelValues("resolved").Inc()
+ }
+ }
+
+ // Make a best effort to insert all alerts that are valid.
+ var (
+ validAlerts = make([]*types.Alert, 0, len(alerts))
+ validationErrs = &types.MultiError{}
+ )
+ for _, a := range alerts {
+ removeEmptyLabels(a.Labels)
+
+ if err := a.Validate(); err != nil {
+ validationErrs.Add(err)
+ numInvalidAlerts.Inc()
+ continue
+ }
+ validAlerts = append(validAlerts, a)
+ }
+ if err := api.alerts.Put(validAlerts...); err != nil {
+ api.respondError(w, apiError{
+ typ: errorInternal,
+ err: err,
+ }, nil)
+ return
+ }
+
+ if validationErrs.Len() > 0 {
+ api.respondError(w, apiError{
+ typ: errorBadData,
+ err: validationErrs,
+ }, nil)
+ return
+ }
+
+ api.respond(w, nil)
+}
+
+func removeEmptyLabels(ls model.LabelSet) {
+ for k, v := range ls {
+ if string(v) == "" {
+ delete(ls, k)
+ }
+ }
+}
+
+func (api *API) setSilence(w http.ResponseWriter, r *http.Request) {
+ var sil types.Silence
+ if err := api.receive(r, &sil); err != nil {
+ api.respondError(w, apiError{
+ typ: errorBadData,
+ err: err,
+ }, nil)
+ return
+ }
+
+ // This is an API only validation, it cannot be done internally
+ // because the expired silence is semantically important.
+ // But one should not be able to create expired silences, that
+ // won't have any use.
+ if sil.Expired() {
+ api.respondError(w, apiError{
+ typ: errorBadData,
+ err: errors.New("start time must not be equal to end time"),
+ }, nil)
+ return
+ }
+
+ if sil.EndsAt.Before(time.Now()) {
+ api.respondError(w, apiError{
+ typ: errorBadData,
+ err: errors.New("end time can't be in the past"),
+ }, nil)
+ return
+ }
+
+ psil, err := silenceToProto(&sil)
+ if err != nil {
+ api.respondError(w, apiError{
+ typ: errorBadData,
+ err: err,
+ }, nil)
+ return
+ }
+
+ sid, err := api.silences.Set(psil)
+ if err != nil {
+ api.respondError(w, apiError{
+ typ: errorBadData,
+ err: err,
+ }, nil)
+ return
+ }
+
+ api.respond(w, struct {
+ SilenceID string `json:"silenceId"`
+ }{
+ SilenceID: sid,
+ })
+}
+
+func (api *API) getSilence(w http.ResponseWriter, r *http.Request) {
+ sid := route.Param(r.Context(), "sid")
+
+ sils, err := api.silences.Query(silence.QIDs(sid))
+ if err != nil || len(sils) == 0 {
+ http.Error(w, fmt.Sprint("Error getting silence: ", err), http.StatusNotFound)
+ return
+ }
+ sil, err := silenceFromProto(sils[0])
+ if err != nil {
+ api.respondError(w, apiError{
+ typ: errorInternal,
+ err: err,
+ }, nil)
+ return
+ }
+
+ api.respond(w, sil)
+}
+
+func (api *API) delSilence(w http.ResponseWriter, r *http.Request) {
+ sid := route.Param(r.Context(), "sid")
+
+ if err := api.silences.Expire(sid); err != nil {
+ api.respondError(w, apiError{
+ typ: errorBadData,
+ err: err,
+ }, nil)
+ return
+ }
+ api.respond(w, nil)
+}
+
+func (api *API) listSilences(w http.ResponseWriter, r *http.Request) {
+ psils, err := api.silences.Query()
+ if err != nil {
+ api.respondError(w, apiError{
+ typ: errorInternal,
+ err: err,
+ }, nil)
+ return
+ }
+
+ matchers := []*labels.Matcher{}
+ if filter := r.FormValue("filter"); filter != "" {
+ matchers, err = parse.Matchers(filter)
+ if err != nil {
+ api.respondError(w, apiError{
+ typ: errorBadData,
+ err: err,
+ }, nil)
+ return
+ }
+ }
+
+ sils := []*types.Silence{}
+ for _, ps := range psils {
+ s, err := silenceFromProto(ps)
+ if err != nil {
+ api.respondError(w, apiError{
+ typ: errorInternal,
+ err: err,
+ }, nil)
+ return
+ }
+
+ if !silenceMatchesFilterLabels(s, matchers) {
+ continue
+ }
+ sils = append(sils, s)
+ }
+
+ var active, pending, expired []*types.Silence
+
+ for _, s := range sils {
+ switch s.Status.State {
+ case types.SilenceStateActive:
+ active = append(active, s)
+ case types.SilenceStatePending:
+ pending = append(pending, s)
+ case types.SilenceStateExpired:
+ expired = append(expired, s)
+ }
+ }
+
+ sort.Slice(active, func(i int, j int) bool {
+ return active[i].EndsAt.Before(active[j].EndsAt)
+ })
+ sort.Slice(pending, func(i int, j int) bool {
+ return pending[i].StartsAt.Before(pending[j].EndsAt)
+ })
+ sort.Slice(expired, func(i int, j int) bool {
+ return expired[i].EndsAt.After(expired[j].EndsAt)
+ })
+
+ // Initialize silences explicitly to an empty list (instead of nil)
+ // So that it does not get converted to "null" in JSON.
+ silences := []*types.Silence{}
+ silences = append(silences, active...)
+ silences = append(silences, pending...)
+ silences = append(silences, expired...)
+
+ api.respond(w, silences)
+}
+
+func silenceMatchesFilterLabels(s *types.Silence, matchers []*labels.Matcher) bool {
+ sms := make(map[string]string)
+ for _, m := range s.Matchers {
+ sms[m.Name] = m.Value
+ }
+
+ return matchFilterLabels(matchers, sms)
+}
+
+func matchFilterLabels(matchers []*labels.Matcher, sms map[string]string) bool {
+ for _, m := range matchers {
+ v, prs := sms[m.Name]
+ switch m.Type {
+ case labels.MatchNotRegexp, labels.MatchNotEqual:
+ if string(m.Value) == "" && prs {
+ continue
+ }
+ if !m.Matches(string(v)) {
+ return false
+ }
+ default:
+ if string(m.Value) == "" && !prs {
+ continue
+ }
+ if !prs || !m.Matches(string(v)) {
+ return false
+ }
+ }
+ }
+
+ return true
+}
+
+func silenceToProto(s *types.Silence) (*silencepb.Silence, error) {
+ sil := &silencepb.Silence{
+ Id: s.ID,
+ StartsAt: s.StartsAt,
+ EndsAt: s.EndsAt,
+ UpdatedAt: s.UpdatedAt,
+ Comment: s.Comment,
+ CreatedBy: s.CreatedBy,
+ }
+ for _, m := range s.Matchers {
+ matcher := &silencepb.Matcher{
+ Name: m.Name,
+ Pattern: m.Value,
+ Type: silencepb.Matcher_EQUAL,
+ }
+ if m.IsRegex {
+ matcher.Type = silencepb.Matcher_REGEXP
+ }
+ sil.Matchers = append(sil.Matchers, matcher)
+ }
+ return sil, nil
+}
+
+func silenceFromProto(s *silencepb.Silence) (*types.Silence, error) {
+ sil := &types.Silence{
+ ID: s.Id,
+ StartsAt: s.StartsAt,
+ EndsAt: s.EndsAt,
+ UpdatedAt: s.UpdatedAt,
+ Status: types.SilenceStatus{
+ State: types.CalcSilenceState(s.StartsAt, s.EndsAt),
+ },
+ Comment: s.Comment,
+ CreatedBy: s.CreatedBy,
+ }
+ for _, m := range s.Matchers {
+ matcher := &types.Matcher{
+ Name: m.Name,
+ Value: m.Pattern,
+ }
+ switch m.Type {
+ case silencepb.Matcher_EQUAL:
+ case silencepb.Matcher_REGEXP:
+ matcher.IsRegex = true
+ default:
+ return nil, fmt.Errorf("unknown matcher type")
+ }
+ sil.Matchers = append(sil.Matchers, matcher)
+ }
+
+ return sil, nil
+}
+
+type status string
+
+const (
+ statusSuccess status = "success"
+ statusError status = "error"
+)
+
+type response struct {
+ Status status `json:"status"`
+ Data interface{} `json:"data,omitempty"`
+ ErrorType errorType `json:"errorType,omitempty"`
+ Error string `json:"error,omitempty"`
+}
+
+func (api *API) respond(w http.ResponseWriter, data interface{}) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(200)
+
+ b, err := json.Marshal(&response{
+ Status: statusSuccess,
+ Data: data,
+ })
+ if err != nil {
+ level.Error(api.logger).Log("msg", "Error marshalling JSON", "err", err)
+ return
+ }
+ w.Write(b)
+}
+
+func (api *API) respondError(w http.ResponseWriter, apiErr apiError, data interface{}) {
+ w.Header().Set("Content-Type", "application/json")
+
+ switch apiErr.typ {
+ case errorBadData:
+ w.WriteHeader(http.StatusBadRequest)
+ case errorInternal:
+ w.WriteHeader(http.StatusInternalServerError)
+ default:
+ panic(fmt.Sprintf("unknown error type %q", apiErr.Error()))
+ }
+
+ b, err := json.Marshal(&response{
+ Status: statusError,
+ ErrorType: apiErr.typ,
+ Error: apiErr.err.Error(),
+ Data: data,
+ })
+ if err != nil {
+ return
+ }
+ level.Error(api.logger).Log("msg", "API error", "err", apiErr.Error())
+
+ w.Write(b)
+}
+
+func (api *API) receive(r *http.Request, v interface{}) error {
+ dec := json.NewDecoder(r.Body)
+ defer r.Body.Close()
+
+ err := dec.Decode(v)
+ if err != nil {
+ level.Debug(api.logger).Log("msg", "Decoding request failed", "err", err)
+ }
+ return err
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package api
+
+import (
+ "bytes"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "net/http/httptest"
+ "regexp"
+ "testing"
+ "time"
+
+ "github.com/prometheus/alertmanager/config"
+ "github.com/prometheus/alertmanager/dispatch"
+ "github.com/prometheus/alertmanager/provider"
+ "github.com/prometheus/alertmanager/types"
+ "github.com/prometheus/common/model"
+ "github.com/prometheus/prometheus/pkg/labels"
+ "github.com/stretchr/testify/require"
+)
+
+// fakeAlerts is a struct implementing the provider.Alerts interface for tests.
+type fakeAlerts struct {
+ fps map[model.Fingerprint]int
+ alerts []*types.Alert
+ err error
+}
+
+func newFakeAlerts(alerts []*types.Alert, withErr bool) *fakeAlerts {
+ fps := make(map[model.Fingerprint]int)
+ for i, a := range alerts {
+ fps[a.Fingerprint()] = i
+ }
+ f := &fakeAlerts{
+ alerts: alerts,
+ fps: fps,
+ }
+ if withErr {
+ f.err = errors.New("Error occured")
+ }
+ return f
+}
+
+func (f *fakeAlerts) Subscribe() provider.AlertIterator { return nil }
+func (f *fakeAlerts) Get(model.Fingerprint) (*types.Alert, error) { return nil, nil }
+func (f *fakeAlerts) Put(alerts ...*types.Alert) error {
+ return f.err
+}
+func (f *fakeAlerts) GetPending() provider.AlertIterator {
+ ch := make(chan *types.Alert)
+ done := make(chan struct{})
+ go func() {
+ defer close(ch)
+ for _, a := range f.alerts {
+ ch <- a
+ }
+ }()
+ return provider.NewAlertIterator(ch, done, f.err)
+}
+
+func groupAlerts([]*labels.Matcher) dispatch.AlertOverview { return dispatch.AlertOverview{} }
+func newGetAlertStatus(f *fakeAlerts) func(model.Fingerprint) types.AlertStatus {
+ return func(fp model.Fingerprint) types.AlertStatus {
+ status := types.AlertStatus{SilencedBy: []string{}, InhibitedBy: []string{}}
+
+ i, ok := f.fps[fp]
+ if !ok {
+ return status
+ }
+ alert := f.alerts[i]
+ switch alert.Labels["state"] {
+ case "active":
+ status.State = types.AlertStateActive
+ case "unprocessed":
+ status.State = types.AlertStateUnprocessed
+ case "suppressed":
+ status.State = types.AlertStateSuppressed
+ }
+ if alert.Labels["silenced_by"] != "" {
+ status.SilencedBy = append(status.SilencedBy, string(alert.Labels["silenced_by"]))
+ }
+ if alert.Labels["inhibited_by"] != "" {
+ status.InhibitedBy = append(status.InhibitedBy, string(alert.Labels["inhibited_by"]))
+ }
+ return status
+ }
+}
+
+func TestAddAlerts(t *testing.T) {
+ now := func(offset int) time.Time {
+ return time.Now().Add(time.Duration(offset) * time.Second)
+ }
+
+ for i, tc := range []struct {
+ start, end time.Time
+ err bool
+ code int
+ }{
+ {time.Time{}, time.Time{}, false, 200},
+ {now(0), time.Time{}, false, 200},
+ {time.Time{}, now(-1), false, 200},
+ {time.Time{}, now(0), false, 200},
+ {time.Time{}, now(1), false, 200},
+ {now(-2), now(-1), false, 200},
+ {now(1), now(2), false, 200},
+ {now(1), now(0), false, 400},
+ {now(0), time.Time{}, true, 500},
+ } {
+ alerts := []model.Alert{{
+ StartsAt: tc.start,
+ EndsAt: tc.end,
+ Labels: model.LabelSet{"label1": "test1"},
+ Annotations: model.LabelSet{"annotation1": "some text"},
+ }}
+ b, err := json.Marshal(&alerts)
+ if err != nil {
+ t.Errorf("Unexpected error %v", err)
+ }
+
+ alertsProvider := newFakeAlerts([]*types.Alert{}, tc.err)
+ api := New(alertsProvider, nil, groupAlerts, newGetAlertStatus(alertsProvider), nil, nil)
+
+ r, err := http.NewRequest("POST", "/api/v1/alerts", bytes.NewReader(b))
+ w := httptest.NewRecorder()
+ if err != nil {
+ t.Errorf("Unexpected error %v", err)
+ }
+
+ api.addAlerts(w, r)
+ res := w.Result()
+ body, _ := ioutil.ReadAll(res.Body)
+
+ require.Equal(t, tc.code, w.Code, fmt.Sprintf("test case: %d, StartsAt %v, EndsAt %v, Response: %s", i, tc.start, tc.end, string(body)))
+ }
+}
+
+func TestListAlerts(t *testing.T) {
+ now := time.Now()
+ alerts := []*types.Alert{
+ &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{"state": "active", "alertname": "alert1"},
+ StartsAt: now.Add(-time.Minute),
+ },
+ },
+ &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{"state": "unprocessed", "alertname": "alert2"},
+ StartsAt: now.Add(-time.Minute),
+ },
+ },
+ &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{"state": "suppressed", "silenced_by": "abc", "alertname": "alert3"},
+ StartsAt: now.Add(-time.Minute),
+ },
+ },
+ &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{"state": "suppressed", "inhibited_by": "abc", "alertname": "alert4"},
+ StartsAt: now.Add(-time.Minute),
+ },
+ },
+ &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{"alertname": "alert5"},
+ StartsAt: now.Add(-2 * time.Minute),
+ EndsAt: now.Add(-time.Minute),
+ },
+ },
+ }
+
+ for i, tc := range []struct {
+ err bool
+ params map[string]string
+
+ code int
+ anames []string
+ }{
+ {
+ false,
+ map[string]string{},
+ 200,
+ []string{"alert1", "alert2", "alert3", "alert4"},
+ },
+ {
+ false,
+ map[string]string{"active": "true", "unprocessed": "true", "silenced": "true", "inhibited": "true"},
+ 200,
+ []string{"alert1", "alert2", "alert3", "alert4"},
+ },
+ {
+ false,
+ map[string]string{"active": "false", "unprocessed": "true", "silenced": "true", "inhibited": "true"},
+ 200,
+ []string{"alert2", "alert3", "alert4"},
+ },
+ {
+ false,
+ map[string]string{"active": "true", "unprocessed": "false", "silenced": "true", "inhibited": "true"},
+ 200,
+ []string{"alert1", "alert3", "alert4"},
+ },
+ {
+ false,
+ map[string]string{"active": "true", "unprocessed": "true", "silenced": "false", "inhibited": "true"},
+ 200,
+ []string{"alert1", "alert2", "alert4"},
+ },
+ {
+ false,
+ map[string]string{"active": "true", "unprocessed": "true", "silenced": "true", "inhibited": "false"},
+ 200,
+ []string{"alert1", "alert2", "alert3"},
+ },
+ {
+ false,
+ map[string]string{"filter": "{alertname=\"alert3\""},
+ 200,
+ []string{"alert3"},
+ },
+ {
+ false,
+ map[string]string{"filter": "{alertname"},
+ 400,
+ []string{},
+ },
+ {
+ false,
+ map[string]string{"receiver": "other"},
+ 200,
+ []string{},
+ },
+ {
+ false,
+ map[string]string{"active": "invalid"},
+ 400,
+ []string{},
+ },
+ {
+ true,
+ map[string]string{},
+ 500,
+ []string{},
+ },
+ } {
+ alertsProvider := newFakeAlerts(alerts, tc.err)
+ api := New(alertsProvider, nil, groupAlerts, newGetAlertStatus(alertsProvider), nil, nil)
+ api.route = dispatch.NewRoute(&config.Route{Receiver: "def-receiver"}, nil)
+
+ r, err := http.NewRequest("GET", "/api/v1/alerts", nil)
+ if err != nil {
+ t.Fatalf("Unexpected error %v", err)
+ }
+ q := r.URL.Query()
+ for k, v := range tc.params {
+ q.Add(k, v)
+ }
+ r.URL.RawQuery = q.Encode()
+ w := httptest.NewRecorder()
+
+ api.listAlerts(w, r)
+ body, _ := ioutil.ReadAll(w.Result().Body)
+
+ var res response
+ err = json.Unmarshal(body, &res)
+ if err != nil {
+ t.Fatalf("Unexpected error %v", err)
+ }
+
+ require.Equal(t, tc.code, w.Code, fmt.Sprintf("test case: %d, response: %s", i, string(body)))
+ if w.Code != 200 {
+ continue
+ }
+
+ // Data needs to be serialized/deserialized to be converted to the real type.
+ b, err := json.Marshal(res.Data)
+ if err != nil {
+ t.Fatalf("Unexpected error %v", err)
+ }
+ retAlerts := []*dispatch.APIAlert{}
+ err = json.Unmarshal(b, &retAlerts)
+ if err != nil {
+ t.Fatalf("Unexpected error %v", err)
+ }
+
+ anames := []string{}
+ for _, a := range retAlerts {
+ name, ok := a.Labels["alertname"]
+ if ok {
+ anames = append(anames, string(name))
+ }
+ }
+ require.Equal(t, tc.anames, anames, fmt.Sprintf("test case: %d, alert names are not equal", i))
+ }
+}
+
+func TestAlertFiltering(t *testing.T) {
+ type test struct {
+ alert *model.Alert
+ msg string
+ expected bool
+ }
+
+ // Equal
+ equal, err := labels.NewMatcher(labels.MatchEqual, "label1", "test1")
+ if err != nil {
+ t.Errorf("Unexpected error %v", err)
+ }
+
+ tests := []test{
+ {&model.Alert{Labels: model.LabelSet{"label1": "test1"}}, "label1=test1", true},
+ {&model.Alert{Labels: model.LabelSet{"label1": "test2"}}, "label1=test2", false},
+ {&model.Alert{Labels: model.LabelSet{"label2": "test2"}}, "label2=test2", false},
+ }
+
+ for _, test := range tests {
+ actual := alertMatchesFilterLabels(test.alert, []*labels.Matcher{equal})
+ msg := fmt.Sprintf("Expected %t for %s", test.expected, test.msg)
+ require.Equal(t, test.expected, actual, msg)
+ }
+
+ // Not Equal
+ notEqual, err := labels.NewMatcher(labels.MatchNotEqual, "label1", "test1")
+ if err != nil {
+ t.Errorf("Unexpected error %v", err)
+ }
+
+ tests = []test{
+ {&model.Alert{Labels: model.LabelSet{"label1": "test1"}}, "label1!=test1", false},
+ {&model.Alert{Labels: model.LabelSet{"label1": "test2"}}, "label1!=test2", true},
+ {&model.Alert{Labels: model.LabelSet{"label2": "test2"}}, "label2!=test2", true},
+ }
+
+ for _, test := range tests {
+ actual := alertMatchesFilterLabels(test.alert, []*labels.Matcher{notEqual})
+ msg := fmt.Sprintf("Expected %t for %s", test.expected, test.msg)
+ require.Equal(t, test.expected, actual, msg)
+ }
+
+ // Regexp Equal
+ regexpEqual, err := labels.NewMatcher(labels.MatchRegexp, "label1", "tes.*")
+ if err != nil {
+ t.Errorf("Unexpected error %v", err)
+ }
+
+ tests = []test{
+ {&model.Alert{Labels: model.LabelSet{"label1": "test1"}}, "label1=~test1", true},
+ {&model.Alert{Labels: model.LabelSet{"label1": "test2"}}, "label1=~test2", true},
+ {&model.Alert{Labels: model.LabelSet{"label2": "test2"}}, "label2=~test2", false},
+ }
+
+ for _, test := range tests {
+ actual := alertMatchesFilterLabels(test.alert, []*labels.Matcher{regexpEqual})
+ msg := fmt.Sprintf("Expected %t for %s", test.expected, test.msg)
+ require.Equal(t, test.expected, actual, msg)
+ }
+
+ // Regexp Not Equal
+ regexpNotEqual, err := labels.NewMatcher(labels.MatchNotRegexp, "label1", "tes.*")
+ if err != nil {
+ t.Errorf("Unexpected error %v", err)
+ }
+
+ tests = []test{
+ {&model.Alert{Labels: model.LabelSet{"label1": "test1"}}, "label1!~test1", false},
+ {&model.Alert{Labels: model.LabelSet{"label1": "test2"}}, "label1!~test2", false},
+ {&model.Alert{Labels: model.LabelSet{"label2": "test2"}}, "label2!~test2", true},
+ }
+
+ for _, test := range tests {
+ actual := alertMatchesFilterLabels(test.alert, []*labels.Matcher{regexpNotEqual})
+ msg := fmt.Sprintf("Expected %t for %s", test.expected, test.msg)
+ require.Equal(t, test.expected, actual, msg)
+ }
+}
+
+func TestSilenceFiltering(t *testing.T) {
+ type test struct {
+ silence *types.Silence
+ msg string
+ expected bool
+ }
+
+ // Equal
+ equal, err := labels.NewMatcher(labels.MatchEqual, "label1", "test1")
+ if err != nil {
+ t.Errorf("Unexpected error %v", err)
+ }
+
+ tests := []test{
+ {
+ &types.Silence{Matchers: newMatcher(model.LabelSet{"label1": "test1"})},
+ "label1=test1",
+ true,
+ },
+ {
+ &types.Silence{Matchers: newMatcher(model.LabelSet{"label1": "test2"})},
+ "label1=test2",
+ false,
+ },
+ {
+ &types.Silence{Matchers: newMatcher(model.LabelSet{"label2": "test2"})},
+ "label2=test2",
+ false,
+ },
+ }
+
+ for _, test := range tests {
+ actual := silenceMatchesFilterLabels(test.silence, []*labels.Matcher{equal})
+ msg := fmt.Sprintf("Expected %t for %s", test.expected, test.msg)
+ require.Equal(t, test.expected, actual, msg)
+ }
+
+ // Not Equal
+ notEqual, err := labels.NewMatcher(labels.MatchNotEqual, "label1", "test1")
+ if err != nil {
+ t.Errorf("Unexpected error %v", err)
+ }
+
+ tests = []test{
+ {
+ &types.Silence{Matchers: newMatcher(model.LabelSet{"label1": "test1"})},
+ "label1!=test1",
+ false,
+ },
+ {
+ &types.Silence{Matchers: newMatcher(model.LabelSet{"label1": "test2"})},
+ "label1!=test2",
+ true,
+ },
+ {
+ &types.Silence{Matchers: newMatcher(model.LabelSet{"label2": "test2"})},
+ "label2!=test2",
+ true,
+ },
+ }
+
+ for _, test := range tests {
+ actual := silenceMatchesFilterLabels(test.silence, []*labels.Matcher{notEqual})
+ msg := fmt.Sprintf("Expected %t for %s", test.expected, test.msg)
+ require.Equal(t, test.expected, actual, msg)
+ }
+
+ // Regexp Equal
+ regexpEqual, err := labels.NewMatcher(labels.MatchRegexp, "label1", "tes.*")
+ if err != nil {
+ t.Errorf("Unexpected error %v", err)
+ }
+
+ tests = []test{
+ {
+ &types.Silence{Matchers: newMatcher(model.LabelSet{"label1": "test1"})},
+ "label1=~test1",
+ true,
+ },
+ {
+ &types.Silence{Matchers: newMatcher(model.LabelSet{"label1": "test2"})},
+ "label1=~test2",
+ true,
+ },
+ {
+ &types.Silence{Matchers: newMatcher(model.LabelSet{"label2": "test2"})},
+ "label2=~test2",
+ false,
+ },
+ }
+
+ for _, test := range tests {
+ actual := silenceMatchesFilterLabels(test.silence, []*labels.Matcher{regexpEqual})
+ msg := fmt.Sprintf("Expected %t for %s", test.expected, test.msg)
+ require.Equal(t, test.expected, actual, msg)
+ }
+
+ // Regexp Not Equal
+ regexpNotEqual, err := labels.NewMatcher(labels.MatchNotRegexp, "label1", "tes.*")
+ if err != nil {
+ t.Errorf("Unexpected error %v", err)
+ }
+
+ tests = []test{
+ {
+ &types.Silence{Matchers: newMatcher(model.LabelSet{"label1": "test1"})},
+ "label1!~test1",
+ false,
+ },
+ {
+ &types.Silence{Matchers: newMatcher(model.LabelSet{"label1": "test2"})},
+ "label1!~test2",
+ false,
+ },
+ {
+ &types.Silence{Matchers: newMatcher(model.LabelSet{"label2": "test2"})},
+ "label2!~test2",
+ true,
+ },
+ }
+
+ for _, test := range tests {
+ actual := silenceMatchesFilterLabels(test.silence, []*labels.Matcher{regexpNotEqual})
+ msg := fmt.Sprintf("Expected %t for %s", test.expected, test.msg)
+ require.Equal(t, test.expected, actual, msg)
+ }
+}
+
+func TestReceiversMatchFilter(t *testing.T) {
+ receivers := []string{"pagerduty", "slack", "hipchat"}
+
+ filter, err := regexp.Compile(fmt.Sprintf("^(?:%s)$", "hip.*"))
+ if err != nil {
+ t.Errorf("Unexpected error %v", err)
+ }
+ require.True(t, receiversMatchFilter(receivers, filter))
+
+ filter, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", "hip"))
+ if err != nil {
+ t.Errorf("Unexpected error %v", err)
+ }
+ require.False(t, receiversMatchFilter(receivers, filter))
+}
+
+func TestMatchFilterLabels(t *testing.T) {
+ testCases := []struct {
+ matcher labels.MatchType
+ expected bool
+ }{
+ {labels.MatchEqual, true},
+ {labels.MatchRegexp, true},
+ {labels.MatchNotEqual, false},
+ {labels.MatchNotRegexp, false},
+ }
+
+ for _, tc := range testCases {
+ l, err := labels.NewMatcher(tc.matcher, "foo", "")
+ require.NoError(t, err)
+ sms := map[string]string{
+ "baz": "bar",
+ }
+ ls := []*labels.Matcher{l}
+
+ require.Equal(t, tc.expected, matchFilterLabels(ls, sms))
+
+ l, err = labels.NewMatcher(tc.matcher, "foo", "")
+ require.NoError(t, err)
+ sms = map[string]string{
+ "baz": "bar",
+ "foo": "quux",
+ }
+ ls = []*labels.Matcher{l}
+ require.NotEqual(t, tc.expected, matchFilterLabels(ls, sms))
+ }
+}
+
+func newMatcher(labelSet model.LabelSet) types.Matchers {
+ matchers := make([]*types.Matcher, 0, len(labelSet))
+ for key, val := range labelSet {
+ matchers = append(matchers, types.NewMatcher(key, string(val)))
+ }
+ return matchers
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cli
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "strings"
+
+ "github.com/prometheus/client_golang/api"
+ "gopkg.in/alecthomas/kingpin.v2"
+
+ "github.com/prometheus/alertmanager/cli/format"
+ "github.com/prometheus/alertmanager/client"
+ "github.com/prometheus/alertmanager/pkg/parse"
+)
+
+type alertQueryCmd struct {
+ inhibited, silenced, active, unprocessed bool
+ receiver string
+ matcherGroups []string
+}
+
+const alertHelp = `View and search through current alerts.
+
+Amtool has a simplified prometheus query syntax, but contains robust support for
+bash variable expansions. The non-option section of arguments constructs a list
+of "Matcher Groups" that will be used to filter your query. The following
+examples will attempt to show this behaviour in action:
+
+amtool alert query alertname=foo node=bar
+
+ This query will match all alerts with the alertname=foo and node=bar label
+ value pairs set.
+
+amtool alert query foo node=bar
+
+ If alertname is omitted and the first argument does not contain a '=' or a
+ '=~' then it will be assumed to be the value of the alertname pair.
+
+amtool alert query 'alertname=~foo.*'
+
+ As well as direct equality, regex matching is also supported. The '=~' syntax
+ (similar to prometheus) is used to represent a regex match. Regex matching
+ can be used in combination with a direct match.
+
+Amtool supports several flags for filtering the returned alerts by state
+(inhibited, silenced, active, unprocessed). If none of these flags is given,
+only active alerts are returned.
+`
+
+func configureAlertCmd(app *kingpin.Application) {
+ var (
+ a = &alertQueryCmd{}
+ alertCmd = app.Command("alert", alertHelp).PreAction(requireAlertManagerURL)
+ queryCmd = alertCmd.Command("query", alertHelp).Default()
+ )
+ queryCmd.Flag("inhibited", "Show inhibited alerts").Short('i').BoolVar(&a.inhibited)
+ queryCmd.Flag("silenced", "Show silenced alerts").Short('s').BoolVar(&a.silenced)
+ queryCmd.Flag("active", "Show active alerts").Short('a').BoolVar(&a.active)
+ queryCmd.Flag("unprocessed", "Show unprocessed alerts").Short('u').BoolVar(&a.unprocessed)
+ queryCmd.Flag("receiver", "Show alerts matching receiver (Supports regex syntax)").Short('r').StringVar(&a.receiver)
+ queryCmd.Arg("matcher-groups", "Query filter").StringsVar(&a.matcherGroups)
+ queryCmd.Action(a.queryAlerts)
+}
+
+func (a *alertQueryCmd) queryAlerts(ctx *kingpin.ParseContext) error {
+ var filterString = ""
+ if len(a.matcherGroups) == 1 {
+ // If the parser fails then we likely don't have a (=|=~|!=|!~) so lets
+ // assume that the user wants alertname=<arg> and prepend `alertname=`
+ // to the front.
+ _, err := parse.Matcher(a.matcherGroups[0])
+ if err != nil {
+ filterString = fmt.Sprintf("{alertname=%s}", a.matcherGroups[0])
+ } else {
+ filterString = fmt.Sprintf("{%s}", strings.Join(a.matcherGroups, ","))
+ }
+ } else if len(a.matcherGroups) > 1 {
+ filterString = fmt.Sprintf("{%s}", strings.Join(a.matcherGroups, ","))
+ }
+
+ c, err := api.NewClient(api.Config{Address: alertmanagerURL.String()})
+ if err != nil {
+ return err
+ }
+ alertAPI := client.NewAlertAPI(c)
+ // If no selector was passed, default to showing active alerts.
+ if !a.silenced && !a.inhibited && !a.active && !a.unprocessed {
+ a.active = true
+ }
+ fetchedAlerts, err := alertAPI.List(context.Background(), filterString, a.receiver, a.silenced, a.inhibited, a.active, a.unprocessed)
+ if err != nil {
+ return err
+ }
+
+ formatter, found := format.Formatters[output]
+ if !found {
+ return errors.New("unknown output formatter")
+ }
+ return formatter.FormatAlerts(fetchedAlerts)
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cli
+
+import (
+ "fmt"
+
+ "github.com/prometheus/alertmanager/config"
+ "github.com/prometheus/alertmanager/template"
+ "gopkg.in/alecthomas/kingpin.v2"
+)
+
+// TODO: This can just be a type that is []string, doesn't have to be a struct
+type checkConfigCmd struct {
+ files []string
+}
+
+const checkConfigHelp = `Validate alertmanager config files
+
+Will validate the syntax and schema for alertmanager config file
+and associated templates. Non existing templates will not trigger
+errors.
+`
+
+func configureCheckConfigCmd(app *kingpin.Application) {
+ var (
+ c = &checkConfigCmd{}
+ checkCmd = app.Command("check-config", checkConfigHelp)
+ )
+ checkCmd.Arg("check-files", "Files to be validated").ExistingFilesVar(&c.files)
+ checkCmd.Action(c.checkConfig)
+}
+
+func (c *checkConfigCmd) checkConfig(ctx *kingpin.ParseContext) error {
+ return CheckConfig(c.files)
+}
+
+func CheckConfig(args []string) error {
+ failed := 0
+
+ for _, arg := range args {
+ fmt.Printf("Checking '%s'", arg)
+ cfg, _, err := config.LoadFile(arg)
+ if err != nil {
+ fmt.Printf(" FAILED: %s\n", err)
+ failed++
+ } else {
+ fmt.Printf(" SUCCESS\n")
+ }
+
+ if cfg != nil {
+ fmt.Println("Found:")
+ if cfg.Global != nil {
+ fmt.Println(" - global config")
+ }
+ if cfg.Route != nil {
+ fmt.Println(" - route")
+ }
+ fmt.Printf(" - %d inhibit rules\n", len(cfg.InhibitRules))
+ fmt.Printf(" - %d receivers\n", len(cfg.Receivers))
+ fmt.Printf(" - %d templates\n", len(cfg.Templates))
+ if len(cfg.Templates) > 0 {
+ _, err = template.FromGlobs(cfg.Templates...)
+ if err != nil {
+ fmt.Printf(" FAILED: %s\n", err)
+ failed++
+ } else {
+ fmt.Printf(" SUCCESS\n")
+ }
+ }
+ }
+ fmt.Printf("\n")
+ }
+ if failed > 0 {
+ return fmt.Errorf("failed to validate %d file(s)", failed)
+ }
+ return nil
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cli
+
+import (
+ "testing"
+)
+
+func TestCheckConfig(t *testing.T) {
+ err := CheckConfig([]string{"testdata/conf.good.yml"})
+ if err != nil {
+ t.Fatalf("checking valid config file failed with: %v", err)
+ }
+
+ err = CheckConfig([]string{"testdata/conf.bad.yml"})
+ if err == nil {
+ t.Fatalf("failed to detect invalid file.")
+ }
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cli
+
+import (
+ "context"
+ "errors"
+
+ "github.com/prometheus/client_golang/api"
+ "gopkg.in/alecthomas/kingpin.v2"
+
+ "github.com/prometheus/alertmanager/cli/format"
+ "github.com/prometheus/alertmanager/client"
+)
+
+const configHelp = `View current config.
+
+The amount of output is controlled by the output selection flag:
+ - Simple: Print just the running config
+ - Extended: Print the running config as well as uptime and all version info
+ - Json: Print entire config object as json
+`
+
+// configCmd represents the config command
+func configureConfigCmd(app *kingpin.Application) {
+ app.Command("config", configHelp).Action(queryConfig).PreAction(requireAlertManagerURL)
+
+}
+
+func queryConfig(ctx *kingpin.ParseContext) error {
+ c, err := api.NewClient(api.Config{Address: alertmanagerURL.String()})
+ if err != nil {
+ return err
+ }
+ statusAPI := client.NewStatusAPI(c)
+ status, err := statusAPI.Get(context.Background())
+ if err != nil {
+ return err
+ }
+
+ formatter, found := format.Formatters[output]
+ if !found {
+ return errors.New("unknown output formatter")
+ }
+
+ return formatter.FormatConfig(status)
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+ "io/ioutil"
+ "os"
+
+ "gopkg.in/alecthomas/kingpin.v2"
+ "gopkg.in/yaml.v2"
+)
+
+type getFlagger interface {
+ GetFlag(name string) *kingpin.FlagClause
+}
+
+// Resolver represents a configuration file resolver for kingpin.
+type Resolver struct {
+ flags map[string]string
+}
+
+// NewResolver returns a Resolver structure.
+func NewResolver(files []string, legacyFlags map[string]string) (*Resolver, error) {
+ flags := map[string]string{}
+ for _, f := range files {
+ b, err := ioutil.ReadFile(f)
+ if err != nil {
+ if os.IsNotExist(err) {
+ continue
+ }
+ return nil, err
+ }
+
+ var m map[string]string
+ err = yaml.Unmarshal(b, &m)
+ if err != nil {
+ return nil, err
+ }
+ for k, v := range m {
+ if flag, ok := legacyFlags[k]; ok {
+ if _, ok := m[flag]; ok {
+ continue
+ }
+ k = flag
+ }
+ if _, ok := flags[k]; !ok {
+ flags[k] = v
+ }
+ }
+ }
+
+ return &Resolver{flags: flags}, nil
+}
+
+func (c *Resolver) setDefault(v getFlagger) {
+ for name, value := range c.flags {
+ f := v.GetFlag(name)
+ if f != nil {
+ f.Default(value)
+ }
+ }
+}
+
+// Bind sets active flags with their default values from the configuration file(s).
+func (c *Resolver) Bind(app *kingpin.Application, args []string) error {
+ // Parse the command line arguments to get the selected command.
+ pc, err := app.ParseContext(args)
+ if err != nil {
+ return err
+ }
+
+ c.setDefault(app)
+ if pc.SelectedCommand != nil {
+ c.setDefault(pc.SelectedCommand)
+ }
+
+ return nil
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+ "io/ioutil"
+ "testing"
+
+ "gopkg.in/alecthomas/kingpin.v2"
+)
+
+var (
+ url *string
+ id *string
+)
+
+func newApp() *kingpin.Application {
+ url = new(string)
+ id = new(string)
+
+ app := kingpin.New("app", "")
+ app.UsageWriter(ioutil.Discard)
+ app.ErrorWriter(ioutil.Discard)
+ app.Terminate(nil)
+
+ app.Flag("url", "").StringVar(url)
+
+ silence := app.Command("silence", "")
+ silenceDel := silence.Command("del", "")
+ silenceDel.Flag("id", "").StringVar(id)
+
+ return app
+}
+
+func TestNewConfigResolver(t *testing.T) {
+ for i, tc := range []struct {
+ files []string
+ err bool
+ }{
+ {[]string{}, false},
+ {[]string{"testdata/amtool.good1.yml", "testdata/amtool.good2.yml"}, false},
+ {[]string{"testdata/amtool.good1.yml", "testdata/not_existing.yml"}, false},
+ {[]string{"testdata/amtool.good1.yml", "testdata/amtool.bad.yml"}, true},
+ } {
+ _, err := NewResolver(tc.files, nil)
+ if tc.err != (err != nil) {
+ if tc.err {
+ t.Fatalf("%d: expected error but got none", i)
+ } else {
+ t.Fatalf("%d: expected no error but got %v", i, err)
+ }
+ }
+ }
+}
+
+type expectFn func()
+
+func TestConfigResolverBind(t *testing.T) {
+ expectURL := func(expected string) expectFn {
+ return func() {
+ if *url != expected {
+ t.Fatalf("expected url flag %q but got %q", expected, *url)
+ }
+ }
+ }
+ expectID := func(expected string) expectFn {
+ return func() {
+ if *id != expected {
+ t.Fatalf("expected ID flag %q but got %q", expected, *id)
+ }
+ }
+ }
+
+ for i, tc := range []struct {
+ files []string
+ legacyFlags map[string]string
+ args []string
+
+ err bool
+ expCmd string
+ expFns []expectFn
+ }{
+ {
+ []string{"testdata/amtool.good1.yml", "testdata/amtool.good2.yml"},
+ nil,
+ []string{},
+
+ true,
+ "",
+ []expectFn{expectURL("url1")}, // from amtool.good1.yml
+ },
+ {
+ []string{"testdata/amtool.good2.yml"},
+ nil,
+ []string{},
+
+ true,
+ "",
+ []expectFn{expectURL("url2")}, // from amtool.good2.yml
+ },
+ {
+ []string{"testdata/amtool.good1.yml", "testdata/amtool.good2.yml"},
+ nil,
+ []string{"--url", "url3"},
+
+ true,
+ "",
+ []expectFn{expectURL("url3")}, // from command line
+ },
+ {
+ []string{"testdata/amtool.good1.yml", "testdata/amtool.good2.yml"},
+ map[string]string{"old-id": "id"},
+ []string{"silence", "del"},
+
+ false,
+ "silence del",
+ []expectFn{
+ expectURL("url1"), // from amtool.good1.yml
+ expectID("id1"), // from amtool.good1.yml
+ },
+ },
+ {
+ []string{"testdata/amtool.good2.yml"},
+ map[string]string{"old-id": "id"},
+ []string{"silence", "del"},
+
+ false,
+ "silence del",
+ []expectFn{
+ expectURL("url2"), // from amtool.good2.yml
+ expectID("id2"), // from amtool.good2.yml
+ },
+ },
+ {
+ []string{"testdata/amtool.good2.yml"},
+ map[string]string{"old-id": "id"},
+ []string{"silence", "del", "--id", "id3"},
+
+ false,
+ "silence del",
+ []expectFn{
+ expectURL("url2"), // from amtool.good2.yml
+ expectID("id3"), // from command line
+ },
+ },
+ } {
+ r, err := NewResolver(tc.files, tc.legacyFlags)
+ if err != nil {
+ t.Fatalf("%d: expected no error but got: %v", i, err)
+ }
+
+ app := newApp()
+ err = r.Bind(app, tc.args)
+ if err != nil {
+ t.Fatalf("%d: expected Bind() to return no error but got: %v", i, err)
+ }
+
+ cmd, err := app.Parse(tc.args)
+ if tc.err != (err != nil) {
+ if tc.err {
+ t.Fatalf("%d: expected Parse() to return an error but got none", i)
+ } else {
+ t.Fatalf("%d: expected Parse() to return no error but got: %v", i, err)
+ }
+ }
+ if cmd != tc.expCmd {
+ t.Fatalf("%d: expected command %q but got %q", i, tc.expCmd, cmd)
+ }
+ for _, fn := range tc.expFns {
+ fn()
+ }
+ }
+}
--- /dev/null
+id: id1
+url: url1
--- /dev/null
+old-id: id2
+url: url2
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package format
+
+import (
+ "io"
+ "time"
+
+ "gopkg.in/alecthomas/kingpin.v2"
+
+ "github.com/prometheus/alertmanager/client"
+ "github.com/prometheus/alertmanager/types"
+)
+
+const DefaultDateFormat = "2006-01-02 15:04:05 MST"
+
+var (
+ dateFormat *string
+)
+
+func InitFormatFlags(app *kingpin.Application) {
+ dateFormat = app.Flag("date.format", "Format of date output").Default(DefaultDateFormat).String()
+}
+
+// Formatter needs to be implemented for each new output formatter.
+type Formatter interface {
+ SetOutput(io.Writer)
+ FormatSilences([]types.Silence) error
+ FormatAlerts([]*client.ExtendedAlert) error
+ FormatConfig(*client.ServerStatus) error
+}
+
+// Formatters is a map of cli argument names to formatter interface object.
+var Formatters = map[string]Formatter{}
+
+func FormatDate(input time.Time) string {
+ return input.Format(*dateFormat)
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package format
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "sort"
+ "strings"
+ "text/tabwriter"
+
+ "github.com/prometheus/alertmanager/client"
+ "github.com/prometheus/alertmanager/types"
+)
+
+type ExtendedFormatter struct {
+ writer io.Writer
+}
+
+func init() {
+ Formatters["extended"] = &ExtendedFormatter{writer: os.Stdout}
+}
+
+func (formatter *ExtendedFormatter) SetOutput(writer io.Writer) {
+ formatter.writer = writer
+}
+
+func (formatter *ExtendedFormatter) FormatSilences(silences []types.Silence) error {
+ w := tabwriter.NewWriter(formatter.writer, 0, 0, 2, ' ', 0)
+ sort.Sort(ByEndAt(silences))
+ fmt.Fprintln(w, "ID\tMatchers\tStarts At\tEnds At\tUpdated At\tCreated By\tComment\t")
+ for _, silence := range silences {
+ fmt.Fprintf(
+ w,
+ "%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
+ silence.ID,
+ extendedFormatMatchers(silence.Matchers),
+ FormatDate(silence.StartsAt),
+ FormatDate(silence.EndsAt),
+ FormatDate(silence.UpdatedAt),
+ silence.CreatedBy,
+ silence.Comment,
+ )
+ }
+ w.Flush()
+ return nil
+}
+
+func (formatter *ExtendedFormatter) FormatAlerts(alerts []*client.ExtendedAlert) error {
+ w := tabwriter.NewWriter(formatter.writer, 0, 0, 2, ' ', 0)
+ sort.Sort(ByStartsAt(alerts))
+ fmt.Fprintln(w, "Labels\tAnnotations\tStarts At\tEnds At\tGenerator URL\t")
+ for _, alert := range alerts {
+ fmt.Fprintf(
+ w,
+ "%s\t%s\t%s\t%s\t%s\t\n",
+ extendedFormatLabels(alert.Labels),
+ extendedFormatAnnotations(alert.Annotations),
+ FormatDate(alert.StartsAt),
+ FormatDate(alert.EndsAt),
+ alert.GeneratorURL,
+ )
+ }
+ w.Flush()
+ return nil
+}
+
+func (formatter *ExtendedFormatter) FormatConfig(status *client.ServerStatus) error {
+ fmt.Fprintln(formatter.writer, status.ConfigYAML)
+ fmt.Fprintln(formatter.writer, "buildUser", status.VersionInfo["buildUser"])
+ fmt.Fprintln(formatter.writer, "goVersion", status.VersionInfo["goVersion"])
+ fmt.Fprintln(formatter.writer, "revision", status.VersionInfo["revision"])
+ fmt.Fprintln(formatter.writer, "version", status.VersionInfo["version"])
+ fmt.Fprintln(formatter.writer, "branch", status.VersionInfo["branch"])
+ fmt.Fprintln(formatter.writer, "buildDate", status.VersionInfo["buildDate"])
+ fmt.Fprintln(formatter.writer, "uptime", status.Uptime)
+ return nil
+}
+
+func extendedFormatLabels(labels client.LabelSet) string {
+ output := []string{}
+ for name, value := range labels {
+ output = append(output, fmt.Sprintf("%s=\"%s\"", name, value))
+ }
+ sort.Strings(output)
+ return strings.Join(output, " ")
+}
+
+func extendedFormatAnnotations(labels client.LabelSet) string {
+ output := []string{}
+ for name, value := range labels {
+ output = append(output, fmt.Sprintf("%s=\"%s\"", name, value))
+ }
+ sort.Strings(output)
+ return strings.Join(output, " ")
+}
+
+func extendedFormatMatchers(matchers types.Matchers) string {
+ output := []string{}
+ for _, matcher := range matchers {
+ output = append(output, extendedFormatMatcher(*matcher))
+ }
+ return strings.Join(output, " ")
+}
+
+func extendedFormatMatcher(matcher types.Matcher) string {
+ if matcher.IsRegex {
+ return fmt.Sprintf("%s~=%s", matcher.Name, matcher.Value)
+ }
+ return fmt.Sprintf("%s=%s", matcher.Name, matcher.Value)
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package format
+
+import (
+ "encoding/json"
+ "io"
+ "os"
+
+ "github.com/prometheus/alertmanager/client"
+ "github.com/prometheus/alertmanager/types"
+)
+
+type JSONFormatter struct {
+ writer io.Writer
+}
+
+func init() {
+ Formatters["json"] = &JSONFormatter{writer: os.Stdout}
+}
+
+func (formatter *JSONFormatter) SetOutput(writer io.Writer) {
+ formatter.writer = writer
+}
+
+func (formatter *JSONFormatter) FormatSilences(silences []types.Silence) error {
+ enc := json.NewEncoder(formatter.writer)
+ return enc.Encode(silences)
+}
+
+func (formatter *JSONFormatter) FormatAlerts(alerts []*client.ExtendedAlert) error {
+ enc := json.NewEncoder(formatter.writer)
+ return enc.Encode(alerts)
+}
+
+func (formatter *JSONFormatter) FormatConfig(status *client.ServerStatus) error {
+ enc := json.NewEncoder(formatter.writer)
+ return enc.Encode(status)
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package format
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "sort"
+ "strings"
+ "text/tabwriter"
+
+ "github.com/prometheus/alertmanager/client"
+ "github.com/prometheus/alertmanager/types"
+)
+
+type SimpleFormatter struct {
+ writer io.Writer
+}
+
+func init() {
+ Formatters["simple"] = &SimpleFormatter{writer: os.Stdout}
+}
+
+func (formatter *SimpleFormatter) SetOutput(writer io.Writer) {
+ formatter.writer = writer
+}
+
+func (formatter *SimpleFormatter) FormatSilences(silences []types.Silence) error {
+ w := tabwriter.NewWriter(formatter.writer, 0, 0, 2, ' ', 0)
+ sort.Sort(ByEndAt(silences))
+ fmt.Fprintln(w, "ID\tMatchers\tEnds At\tCreated By\tComment\t")
+ for _, silence := range silences {
+ fmt.Fprintf(
+ w,
+ "%s\t%s\t%s\t%s\t%s\t\n",
+ silence.ID,
+ simpleFormatMatchers(silence.Matchers),
+ FormatDate(silence.EndsAt),
+ silence.CreatedBy,
+ silence.Comment,
+ )
+ }
+ w.Flush()
+ return nil
+}
+
+func (formatter *SimpleFormatter) FormatAlerts(alerts []*client.ExtendedAlert) error {
+ w := tabwriter.NewWriter(formatter.writer, 0, 0, 2, ' ', 0)
+ sort.Sort(ByStartsAt(alerts))
+ fmt.Fprintln(w, "Alertname\tStarts At\tSummary\t")
+ for _, alert := range alerts {
+ fmt.Fprintf(
+ w,
+ "%s\t%s\t%s\t\n",
+ alert.Labels["alertname"],
+ FormatDate(alert.StartsAt),
+ alert.Annotations["summary"],
+ )
+ }
+ w.Flush()
+ return nil
+}
+
+func (formatter *SimpleFormatter) FormatConfig(status *client.ServerStatus) error {
+ fmt.Fprintln(formatter.writer, status.ConfigYAML)
+ return nil
+}
+
+func simpleFormatMatchers(matchers types.Matchers) string {
+ output := []string{}
+ for _, matcher := range matchers {
+ output = append(output, simpleFormatMatcher(*matcher))
+ }
+ return strings.Join(output, " ")
+}
+
+func simpleFormatMatcher(matcher types.Matcher) string {
+ if matcher.IsRegex {
+ return fmt.Sprintf("%s=~%s", matcher.Name, matcher.Value)
+ }
+ return fmt.Sprintf("%s=%s", matcher.Name, matcher.Value)
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package format
+
+import (
+ "github.com/prometheus/alertmanager/client"
+ "github.com/prometheus/alertmanager/types"
+)
+
+type ByEndAt []types.Silence
+
+func (s ByEndAt) Len() int { return len(s) }
+func (s ByEndAt) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s ByEndAt) Less(i, j int) bool { return s[i].EndsAt.Before(s[j].EndsAt) }
+
+type ByStartsAt []*client.ExtendedAlert
+
+func (s ByStartsAt) Len() int { return len(s) }
+func (s ByStartsAt) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s ByStartsAt) Less(i, j int) bool { return s[i].StartsAt.Before(s[j].StartsAt) }
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cli
+
+import (
+ "net/url"
+ "os"
+
+ "github.com/prometheus/common/version"
+ "gopkg.in/alecthomas/kingpin.v2"
+
+ "github.com/prometheus/alertmanager/cli/config"
+ "github.com/prometheus/alertmanager/cli/format"
+)
+
+var (
+ verbose bool
+ alertmanagerURL *url.URL
+ output string
+
+ configFiles = []string{os.ExpandEnv("$HOME/.config/amtool/config.yml"), "/etc/amtool/config.yml"}
+ legacyFlags = map[string]string{"comment_required": "require-comment"}
+)
+
+func requireAlertManagerURL(pc *kingpin.ParseContext) error {
+ // Return without error if any help flag is set.
+ for _, elem := range pc.Elements {
+ f, ok := elem.Clause.(*kingpin.FlagClause)
+ if !ok {
+ continue
+ }
+ name := f.Model().Name
+ if name == "help" || name == "help-long" || name == "help-man" {
+ return nil
+ }
+ }
+ if alertmanagerURL == nil {
+ kingpin.Fatalf("required flag --alertmanager.url not provided")
+ }
+ return nil
+}
+
+func Execute() {
+ var (
+ app = kingpin.New("amtool", helpRoot).DefaultEnvars()
+ )
+
+ format.InitFormatFlags(app)
+
+ app.Flag("verbose", "Verbose running information").Short('v').BoolVar(&verbose)
+ app.Flag("alertmanager.url", "Alertmanager to talk to").URLVar(&alertmanagerURL)
+ app.Flag("output", "Output formatter (simple, extended, json)").Short('o').Default("simple").EnumVar(&output, "simple", "extended", "json")
+ app.Version(version.Print("amtool"))
+ app.GetFlag("help").Short('h')
+ app.UsageTemplate(kingpin.CompactUsageTemplate)
+
+ resolver, err := config.NewResolver(configFiles, legacyFlags)
+ if err != nil {
+ kingpin.Fatalf("could not load config file: %v\n", err)
+ }
+
+ configureAlertCmd(app)
+ configureSilenceCmd(app)
+ configureCheckConfigCmd(app)
+ configureConfigCmd(app)
+
+ err = resolver.Bind(app, os.Args[1:])
+ if err != nil {
+ kingpin.Fatalf("%v\n", err)
+ }
+
+ _, err = app.Parse(os.Args[1:])
+ if err != nil {
+ kingpin.Fatalf("%v\n", err)
+ }
+}
+
+const (
+ helpRoot = `View and modify the current Alertmanager state.
+
+Config File:
+The alertmanager tool will read a config file in YAML format from one of two
+default config locations: $HOME/.config/amtool/config.yml or
+/etc/amtool/config.yml
+
+All flags can be given in the config file, but the following are the suited for
+static configuration:
+
+ alertmanager.url
+ Set a default alertmanager url for each request
+
+ author
+ Set a default author value for new silences. If this argument is not
+ specified then the username will be used
+
+ require-comment
+ Bool, whether to require a comment on silence creation. Defaults to true
+
+ output
+ Set a default output type. Options are (simple, extended, json)
+
+ date.format
+ Sets the output format for dates. Defaults to "2006-01-02 15:04:05 MST"
+`
+)
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cli
+
+import "gopkg.in/alecthomas/kingpin.v2"
+
+// silenceCmd represents the silence command
+func configureSilenceCmd(app *kingpin.Application) {
+ silenceCmd := app.Command("silence", "Add, expire or view silences. For more information and additional flags see query help").PreAction(requireAlertManagerURL)
+ configureSilenceAddCmd(silenceCmd)
+ configureSilenceExpireCmd(silenceCmd)
+ configureSilenceImportCmd(silenceCmd)
+ configureSilenceQueryCmd(silenceCmd)
+ configureSilenceUpdateCmd(silenceCmd)
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cli
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "os/user"
+ "time"
+
+ "github.com/prometheus/client_golang/api"
+ "github.com/prometheus/common/model"
+ "gopkg.in/alecthomas/kingpin.v2"
+
+ "github.com/prometheus/alertmanager/client"
+ "github.com/prometheus/alertmanager/types"
+)
+
+func username() string {
+ user, err := user.Current()
+ if err != nil {
+ return ""
+ }
+ return user.Username
+}
+
+type silenceAddCmd struct {
+ author string
+ requireComment bool
+ duration string
+ start string
+ end string
+ comment string
+ matchers []string
+}
+
+const silenceAddHelp = `Add a new alertmanager silence
+
+ Amtool uses a simplified Prometheus syntax to represent silences. The
+ non-option section of arguments constructs a list of "Matcher Groups"
+ that will be used to create a number of silences. The following examples
+ will attempt to show this behaviour in action:
+
+ amtool silence add alertname=foo node=bar
+
+ This statement will add a silence that matches alerts with the
+ alertname=foo and node=bar label value pairs set.
+
+ amtool silence add foo node=bar
+
+ If alertname is omitted and the first argument does not contain a '=' or a
+ '=~' then it will be assumed to be the value of the alertname pair.
+
+ amtool silence add 'alertname=~foo.*'
+
+ As well as direct equality, regex matching is also supported. The '=~' syntax
+ (similar to Prometheus) is used to represent a regex match. Regex matching
+ can be used in combination with a direct match.
+`
+
+func configureSilenceAddCmd(cc *kingpin.CmdClause) {
+ var (
+ c = &silenceAddCmd{}
+ addCmd = cc.Command("add", silenceAddHelp)
+ )
+ addCmd.Flag("author", "Username for CreatedBy field").Short('a').Default(username()).StringVar(&c.author)
+ addCmd.Flag("require-comment", "Require comment to be set").Hidden().Default("true").BoolVar(&c.requireComment)
+ addCmd.Flag("duration", "Duration of silence").Short('d').Default("1h").StringVar(&c.duration)
+ addCmd.Flag("start", "Set when the silence should start. RFC3339 format 2006-01-02T15:04:05Z07:00").StringVar(&c.start)
+ addCmd.Flag("end", "Set when the silence should end (overwrites duration). RFC3339 format 2006-01-02T15:04:05Z07:00").StringVar(&c.end)
+ addCmd.Flag("comment", "A comment to help describe the silence").Short('c').StringVar(&c.comment)
+ addCmd.Arg("matcher-groups", "Query filter").StringsVar(&c.matchers)
+ addCmd.Action(c.add)
+
+}
+
+func (c *silenceAddCmd) add(ctx *kingpin.ParseContext) error {
+ var err error
+
+ matchers, err := parseMatchers(c.matchers)
+ if err != nil {
+ return err
+ }
+
+ if len(matchers) < 1 {
+ return fmt.Errorf("no matchers specified")
+ }
+
+ var endsAt time.Time
+ if c.end != "" {
+ endsAt, err = time.Parse(time.RFC3339, c.end)
+ if err != nil {
+ return err
+ }
+ } else {
+ d, err := model.ParseDuration(c.duration)
+ if err != nil {
+ return err
+ }
+ if d == 0 {
+ return fmt.Errorf("silence duration must be greater than 0")
+ }
+ endsAt = time.Now().UTC().Add(time.Duration(d))
+ }
+
+ if c.requireComment && c.comment == "" {
+ return errors.New("comment required by config")
+ }
+
+ var startsAt time.Time
+ if c.start != "" {
+ startsAt, err = time.Parse(time.RFC3339, c.start)
+ if err != nil {
+ return err
+ }
+
+ } else {
+ startsAt = time.Now().UTC()
+ }
+
+ if startsAt.After(endsAt) {
+ return errors.New("silence cannot start after it ends")
+ }
+
+ typeMatchers, err := TypeMatchers(matchers)
+ if err != nil {
+ return err
+ }
+
+ silence := types.Silence{
+ Matchers: typeMatchers,
+ StartsAt: startsAt,
+ EndsAt: endsAt,
+ CreatedBy: c.author,
+ Comment: c.comment,
+ }
+
+ apiClient, err := api.NewClient(api.Config{Address: alertmanagerURL.String()})
+ if err != nil {
+ return err
+ }
+ silenceAPI := client.NewSilenceAPI(apiClient)
+ silenceID, err := silenceAPI.Set(context.Background(), silence)
+ if err != nil {
+ return err
+ }
+
+ _, err = fmt.Println(silenceID)
+ return err
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cli
+
+import (
+ "context"
+ "errors"
+
+ "github.com/prometheus/client_golang/api"
+ "gopkg.in/alecthomas/kingpin.v2"
+
+ "github.com/prometheus/alertmanager/client"
+)
+
+type silenceExpireCmd struct {
+ ids []string
+}
+
+func configureSilenceExpireCmd(cc *kingpin.CmdClause) {
+ var (
+ c = &silenceExpireCmd{}
+ expireCmd = cc.Command("expire", "expire an alertmanager silence")
+ )
+ expireCmd.Arg("silence-ids", "Ids of silences to expire").StringsVar(&c.ids)
+ expireCmd.Action(c.expire)
+}
+
+func (c *silenceExpireCmd) expire(ctx *kingpin.ParseContext) error {
+ if len(c.ids) < 1 {
+ return errors.New("no silence IDs specified")
+ }
+
+ apiClient, err := api.NewClient(api.Config{Address: alertmanagerURL.String()})
+ if err != nil {
+ return err
+ }
+ silenceAPI := client.NewSilenceAPI(apiClient)
+
+ for _, id := range c.ids {
+ err := silenceAPI.Expire(context.Background(), id)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cli
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "os"
+ "strings"
+ "sync"
+
+ "github.com/pkg/errors"
+ "github.com/prometheus/client_golang/api"
+ "gopkg.in/alecthomas/kingpin.v2"
+
+ "github.com/prometheus/alertmanager/client"
+ "github.com/prometheus/alertmanager/types"
+)
+
+type silenceImportCmd struct {
+ force bool
+ workers int
+ file string
+}
+
+const silenceImportHelp = `Import alertmanager silences from JSON file or stdin
+
+This command can be used to bulk import silences from a JSON file
+created by query command. For example:
+
+amtool silence query -o json foo > foo.json
+
+amtool silence import foo.json
+
+JSON data can also come from stdin if no param is specified.
+`
+
+func configureSilenceImportCmd(cc *kingpin.CmdClause) {
+ var (
+ c = &silenceImportCmd{}
+ importCmd = cc.Command("import", silenceImportHelp)
+ )
+
+ importCmd.Flag("force", "Force adding new silences even if it already exists").Short('f').BoolVar(&c.force)
+ importCmd.Flag("worker", "Number of concurrent workers to use for import").Short('w').Default("8").IntVar(&c.workers)
+ importCmd.Arg("input-file", "JSON file with silences").ExistingFileVar(&c.file)
+ importCmd.Action(c.bulkImport)
+}
+
+func addSilenceWorker(sclient client.SilenceAPI, silencec <-chan *types.Silence, errc chan<- error) {
+ for s := range silencec {
+ silenceID, err := sclient.Set(context.Background(), *s)
+ sid := s.ID
+ if err != nil && strings.Contains(err.Error(), "not found") {
+ // silence doesn't exists yet, retry to create as a new one
+ s.ID = ""
+ silenceID, err = sclient.Set(context.Background(), *s)
+ }
+
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error adding silence id='%v': %v\n", sid, err)
+ } else {
+ fmt.Println(silenceID)
+ }
+ errc <- err
+ }
+}
+
+func (c *silenceImportCmd) bulkImport(ctx *kingpin.ParseContext) error {
+ input := os.Stdin
+ var err error
+ if c.file != "" {
+ input, err = os.Open(c.file)
+ if err != nil {
+ return err
+ }
+ defer input.Close()
+ }
+
+ dec := json.NewDecoder(input)
+ // read open square bracket
+ _, err = dec.Token()
+ if err != nil {
+ return errors.Wrap(err, "couldn't unmarshal input data, is it JSON?")
+ }
+
+ apiClient, err := api.NewClient(api.Config{Address: alertmanagerURL.String()})
+ if err != nil {
+ return err
+ }
+ silenceAPI := client.NewSilenceAPI(apiClient)
+ silencec := make(chan *types.Silence, 100)
+ errc := make(chan error, 100)
+ var wg sync.WaitGroup
+ for w := 0; w < c.workers; w++ {
+ wg.Add(1)
+ go func() {
+ addSilenceWorker(silenceAPI, silencec, errc)
+ wg.Done()
+ }()
+ }
+
+ errCount := 0
+ go func() {
+ for err := range errc {
+ if err != nil {
+ errCount++
+ }
+ }
+ }()
+
+ count := 0
+ for dec.More() {
+ var s types.Silence
+ err := dec.Decode(&s)
+ if err != nil {
+ return errors.Wrap(err, "couldn't unmarshal input data, is it JSON?")
+ }
+
+ if c.force {
+ // reset the silence ID so Alertmanager will always create new silence
+ s.ID = ""
+ }
+
+ silencec <- &s
+ count++
+ }
+
+ close(silencec)
+ wg.Wait()
+ close(errc)
+
+ if errCount > 0 {
+ return fmt.Errorf("couldn't import %v out of %v silences", errCount, count)
+ }
+ return nil
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cli
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+
+ "github.com/prometheus/client_golang/api"
+ "gopkg.in/alecthomas/kingpin.v2"
+
+ "github.com/prometheus/alertmanager/cli/format"
+ "github.com/prometheus/alertmanager/client"
+ "github.com/prometheus/alertmanager/pkg/parse"
+ "github.com/prometheus/alertmanager/types"
+)
+
+type silenceQueryCmd struct {
+ expired bool
+ quiet bool
+ matchers []string
+ within time.Duration
+}
+
+const querySilenceHelp = `Query Alertmanager silences.
+
+Amtool has a simplified prometheus query syntax, but contains robust support for
+bash variable expansions. The non-option section of arguments constructs a list
+of "Matcher Groups" that will be used to filter your query. The following
+examples will attempt to show this behaviour in action:
+
+amtool silence query alertname=foo node=bar
+
+ This query will match all silences with the alertname=foo and node=bar label
+ value pairs set.
+
+amtool silence query foo node=bar
+
+ If alertname is omitted and the first argument does not contain a '=' or a
+ '=~' then it will be assumed to be the value of the alertname pair.
+
+amtool silence query 'alertname=~foo.*'
+
+ As well as direct equality, regex matching is also supported. The '=~' syntax
+ (similar to prometheus) is used to represent a regex match. Regex matching
+ can be used in combination with a direct match.
+
+In addition to filtering by silence labels, one can also query for silences
+that are due to expire soon with the "--within" parameter. In the event that
+you want to preemptively act upon expiring silences by either fixing them or
+extending them. For example:
+
+amtool silence query --within 8h
+
+returns all the silences due to expire within the next 8 hours. This syntax can
+also be combined with the label based filtering above for more flexibility.
+
+The "--expired" parameter returns only expired silences. Used in combination
+with "--within=TIME", amtool returns the silences that expired within the
+preceding duration.
+
+amtool silence query --within 2h --expired
+
+returns all silences that expired within the preceeding 2 hours.
+`
+
+func configureSilenceQueryCmd(cc *kingpin.CmdClause) {
+ var (
+ c = &silenceQueryCmd{}
+ queryCmd = cc.Command("query", querySilenceHelp).Default()
+ )
+
+ queryCmd.Flag("expired", "Show expired silences instead of active").BoolVar(&c.expired)
+ queryCmd.Flag("quiet", "Only show silence ids").Short('q').BoolVar(&c.quiet)
+ queryCmd.Arg("matcher-groups", "Query filter").StringsVar(&c.matchers)
+ queryCmd.Flag("within", "Show silences that will expire or have expired within a duration").DurationVar(&c.within)
+ queryCmd.Action(c.query)
+}
+
+func (c *silenceQueryCmd) query(ctx *kingpin.ParseContext) error {
+ var filterString = ""
+ if len(c.matchers) == 1 {
+ // If the parser fails then we likely don't have a (=|=~|!=|!~) so lets
+ // assume that the user wants alertname=<arg> and prepend `alertname=`
+ // to the front.
+ _, err := parse.Matcher(c.matchers[0])
+ if err != nil {
+ filterString = fmt.Sprintf("{alertname=%s}", c.matchers[0])
+ } else {
+ filterString = fmt.Sprintf("{%s}", strings.Join(c.matchers, ","))
+ }
+ } else if len(c.matchers) > 1 {
+ filterString = fmt.Sprintf("{%s}", strings.Join(c.matchers, ","))
+ }
+
+ apiClient, err := api.NewClient(api.Config{Address: alertmanagerURL.String()})
+ if err != nil {
+ return err
+ }
+ silenceAPI := client.NewSilenceAPI(apiClient)
+ fetchedSilences, err := silenceAPI.List(context.Background(), filterString)
+ if err != nil {
+ return err
+ }
+
+ displaySilences := []types.Silence{}
+ for _, silence := range fetchedSilences {
+ // skip expired silences if --expired is not set
+ if !c.expired && silence.EndsAt.Before(time.Now()) {
+ continue
+ }
+ // skip active silences if --expired is set
+ if c.expired && silence.EndsAt.After(time.Now()) {
+ continue
+ }
+ // skip active silences expiring after "--within"
+ if !c.expired && int64(c.within) > 0 && silence.EndsAt.After(time.Now().UTC().Add(c.within)) {
+ continue
+ }
+ // skip silences that expired before "--within"
+ if c.expired && int64(c.within) > 0 && silence.EndsAt.Before(time.Now().UTC().Add(-c.within)) {
+ continue
+ }
+
+ displaySilences = append(displaySilences, *silence)
+ }
+
+ if c.quiet {
+ for _, silence := range displaySilences {
+ fmt.Println(silence.ID)
+ }
+ } else {
+ formatter, found := format.Formatters[output]
+ if !found {
+ return errors.New("unknown output formatter")
+ }
+ formatter.FormatSilences(displaySilences)
+ }
+ return nil
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cli
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "time"
+
+ "github.com/prometheus/client_golang/api"
+ "gopkg.in/alecthomas/kingpin.v2"
+
+ "github.com/prometheus/alertmanager/cli/format"
+ "github.com/prometheus/alertmanager/client"
+ "github.com/prometheus/alertmanager/types"
+ "github.com/prometheus/common/model"
+)
+
+type silenceUpdateCmd struct {
+ quiet bool
+ duration string
+ start string
+ end string
+ comment string
+ ids []string
+}
+
+func configureSilenceUpdateCmd(cc *kingpin.CmdClause) {
+ var (
+ c = &silenceUpdateCmd{}
+ updateCmd = cc.Command("update", "Update silences")
+ )
+ updateCmd.Flag("quiet", "Only show silence ids").Short('q').BoolVar(&c.quiet)
+ updateCmd.Flag("duration", "Duration of silence").Short('d').StringVar(&c.duration)
+ updateCmd.Flag("start", "Set when the silence should start. RFC3339 format 2006-01-02T15:04:05Z07:00").StringVar(&c.start)
+ updateCmd.Flag("end", "Set when the silence should end (overwrites duration). RFC3339 format 2006-01-02T15:04:05Z07:00").StringVar(&c.end)
+ updateCmd.Flag("comment", "A comment to help describe the silence").Short('c').StringVar(&c.comment)
+ updateCmd.Arg("update-ids", "Silence IDs to update").StringsVar(&c.ids)
+
+ updateCmd.Action(c.update)
+}
+
+func (c *silenceUpdateCmd) update(ctx *kingpin.ParseContext) error {
+ if len(c.ids) < 1 {
+ return fmt.Errorf("no silence IDs specified")
+ }
+
+ apiClient, err := api.NewClient(api.Config{Address: alertmanagerURL.String()})
+ if err != nil {
+ return err
+ }
+ silenceAPI := client.NewSilenceAPI(apiClient)
+
+ var updatedSilences []types.Silence
+ for _, silenceID := range c.ids {
+ silence, err := silenceAPI.Get(context.Background(), silenceID)
+ if err != nil {
+ return err
+ }
+ if c.start != "" {
+ silence.StartsAt, err = time.Parse(time.RFC3339, c.start)
+ if err != nil {
+ return err
+ }
+ }
+
+ if c.end != "" {
+ silence.EndsAt, err = time.Parse(time.RFC3339, c.end)
+ if err != nil {
+ return err
+ }
+ } else if c.duration != "" {
+ d, err := model.ParseDuration(c.duration)
+ if err != nil {
+ return err
+ }
+ if d == 0 {
+ return fmt.Errorf("silence duration must be greater than 0")
+ }
+ silence.EndsAt = silence.StartsAt.UTC().Add(time.Duration(d))
+ }
+
+ if silence.StartsAt.After(silence.EndsAt) {
+ return errors.New("silence cannot start after it ends")
+ }
+
+ if c.comment != "" {
+ silence.Comment = c.comment
+ }
+
+ newID, err := silenceAPI.Set(context.Background(), *silence)
+ if err != nil {
+ return err
+ }
+ silence.ID = newID
+
+ updatedSilences = append(updatedSilences, *silence)
+ }
+
+ if c.quiet {
+ for _, silence := range updatedSilences {
+ fmt.Println(silence.ID)
+ }
+ } else {
+ formatter, found := format.Formatters[output]
+ if !found {
+ return fmt.Errorf("unknown output formatter")
+ }
+ formatter.FormatSilences(updatedSilences)
+ }
+ return nil
+}
--- /dev/null
+BAD
\ No newline at end of file
--- /dev/null
+global:
+ smtp_smarthost: 'localhost:25'
+
+templates:
+ - '/etc/alertmanager/template/*.tmpl'
+
+route:
+ receiver: default
+
+receivers:
+ - name: default
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cli
+
+import (
+ "fmt"
+ "net/url"
+ "path"
+
+ "github.com/prometheus/alertmanager/pkg/parse"
+ "github.com/prometheus/alertmanager/types"
+ "github.com/prometheus/common/model"
+ "github.com/prometheus/prometheus/pkg/labels"
+)
+
+type ByAlphabetical []labels.Matcher
+
+func (s ByAlphabetical) Len() int { return len(s) }
+func (s ByAlphabetical) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s ByAlphabetical) Less(i, j int) bool {
+ if s[i].Name != s[j].Name {
+ return s[i].Name < s[j].Name
+ } else if s[i].Type != s[j].Type {
+ return s[i].Type < s[j].Type
+ } else if s[i].Value != s[j].Value {
+ return s[i].Value < s[j].Value
+ }
+ return false
+}
+
+func GetAlertmanagerURL(p string) url.URL {
+ amURL := *alertmanagerURL
+ amURL.Path = path.Join(alertmanagerURL.Path, p)
+ return amURL
+}
+
+// Parse a list of labels (cli arguments)
+func parseMatchers(inputLabels []string) ([]labels.Matcher, error) {
+ matchers := make([]labels.Matcher, 0)
+
+ for _, v := range inputLabels {
+ name, value, matchType, err := parse.Input(v)
+ if err != nil {
+ return []labels.Matcher{}, err
+ }
+
+ matchers = append(matchers, labels.Matcher{
+ Type: matchType,
+ Name: name,
+ Value: value,
+ })
+ }
+
+ return matchers, nil
+}
+
+// Only valid for when you are going to add a silence
+func TypeMatchers(matchers []labels.Matcher) (types.Matchers, error) {
+ typeMatchers := types.Matchers{}
+ for _, matcher := range matchers {
+ typeMatcher, err := TypeMatcher(matcher)
+ if err != nil {
+ return types.Matchers{}, err
+ }
+ typeMatchers = append(typeMatchers, &typeMatcher)
+ }
+ return typeMatchers, nil
+}
+
+// Only valid for when you are going to add a silence
+// Doesn't allow negative operators
+func TypeMatcher(matcher labels.Matcher) (types.Matcher, error) {
+ typeMatcher := types.NewMatcher(model.LabelName(matcher.Name), matcher.Value)
+
+ switch matcher.Type {
+ case labels.MatchEqual:
+ typeMatcher.IsRegex = false
+ case labels.MatchRegexp:
+ typeMatcher.IsRegex = true
+ default:
+ return types.Matcher{}, fmt.Errorf("invalid match type for creation operation: %s", matcher.Type)
+ }
+ return *typeMatcher, nil
+}
--- /dev/null
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package client
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "net/url"
+ "time"
+
+ "github.com/prometheus/client_golang/api"
+
+ "github.com/prometheus/alertmanager/config"
+ "github.com/prometheus/alertmanager/types"
+)
+
+const (
+ apiPrefix = "/api/v1"
+
+ epStatus = apiPrefix + "/status"
+ epSilence = apiPrefix + "/silence/:id"
+ epSilences = apiPrefix + "/silences"
+ epAlerts = apiPrefix + "/alerts"
+ epAlertGroups = apiPrefix + "/alerts/groups"
+
+ statusSuccess = "success"
+ statusError = "error"
+)
+
+// ServerStatus represents the status of the AlertManager endpoint.
+type ServerStatus struct {
+ ConfigYAML string `json:"configYAML"`
+ ConfigJSON *config.Config `json:"configJSON"`
+ VersionInfo map[string]string `json:"versionInfo"`
+ Uptime time.Time `json:"uptime"`
+ ClusterStatus *ClusterStatus `json:"clusterStatus"`
+}
+
+// PeerStatus represents the status of a peer in the cluster.
+type PeerStatus struct {
+ Name string `json:"name"`
+ Address string `json:"address"`
+}
+
+// ClusterStatus represents the status of the cluster.
+type ClusterStatus struct {
+ Name string `json:"name"`
+ Status string `json:"status"`
+ Peers []PeerStatus `json:"peers"`
+}
+
+// apiClient wraps a regular client and processes successful API responses.
+// Successful also includes responses that errored at the API level.
+type apiClient struct {
+ api.Client
+}
+
+type apiResponse struct {
+ Status string `json:"status"`
+ Data json.RawMessage `json:"data,omitempty"`
+ ErrorType string `json:"errorType,omitempty"`
+ Error string `json:"error,omitempty"`
+}
+
+type clientError struct {
+ code int
+ msg string
+}
+
+func (e *clientError) Error() string {
+ return fmt.Sprintf("%s (code: %d)", e.msg, e.code)
+}
+
+func (c apiClient) Do(ctx context.Context, req *http.Request) (*http.Response, []byte, error) {
+ resp, body, err := c.Client.Do(ctx, req)
+ if err != nil {
+ return resp, body, err
+ }
+
+ code := resp.StatusCode
+
+ var result apiResponse
+ if err = json.Unmarshal(body, &result); err != nil {
+ // Pass the returned body rather than the JSON error because some API
+ // endpoints return plain text instead of JSON payload.
+ return resp, body, &clientError{
+ code: code,
+ msg: string(body),
+ }
+ }
+
+ if (code/100 == 2) && (result.Status != statusSuccess) {
+ return resp, body, &clientError{
+ code: code,
+ msg: "inconsistent body for response code",
+ }
+ }
+
+ if result.Status == statusError {
+ err = &clientError{
+ code: code,
+ msg: result.Error,
+ }
+ }
+
+ return resp, []byte(result.Data), err
+}
+
+// StatusAPI provides bindings for the Alertmanager's status API.
+type StatusAPI interface {
+ // Get returns the server's configuration, version, uptime and cluster information.
+ Get(ctx context.Context) (*ServerStatus, error)
+}
+
+// NewStatusAPI returns a status API client.
+func NewStatusAPI(c api.Client) StatusAPI {
+ return &httpStatusAPI{client: apiClient{c}}
+}
+
+type httpStatusAPI struct {
+ client api.Client
+}
+
+func (h *httpStatusAPI) Get(ctx context.Context) (*ServerStatus, error) {
+ u := h.client.URL(epStatus, nil)
+
+ req, _ := http.NewRequest(http.MethodGet, u.String(), nil)
+
+ _, body, err := h.client.Do(ctx, req)
+ if err != nil {
+ return nil, err
+ }
+
+ var ss *ServerStatus
+ err = json.Unmarshal(body, &ss)
+
+ return ss, err
+}
+
+// AlertAPI provides bindings for the Alertmanager's alert API.
+type AlertAPI interface {
+ // List returns all the active alerts.
+ List(ctx context.Context, filter, receiver string, silenced, inhibited, active, unprocessed bool) ([]*ExtendedAlert, error)
+ // Push sends a list of alerts to the Alertmanager.
+ Push(ctx context.Context, alerts ...Alert) error
+}
+
+// Alert represents an alert as expected by the AlertManager's push alert API.
+type Alert struct {
+ Labels LabelSet `json:"labels"`
+ Annotations LabelSet `json:"annotations"`
+ StartsAt time.Time `json:"startsAt,omitempty"`
+ EndsAt time.Time `json:"endsAt,omitempty"`
+ GeneratorURL string `json:"generatorURL"`
+}
+
+// ExtendedAlert represents an alert as returned by the AlertManager's list alert API.
+type ExtendedAlert struct {
+ Alert
+ Status types.AlertStatus `json:"status"`
+ Receivers []string `json:"receivers"`
+ Fingerprint string `json:"fingerprint"`
+}
+
+// LabelSet represents a collection of label names and values as a map.
+type LabelSet map[LabelName]LabelValue
+
+// LabelName represents the name of a label.
+type LabelName string
+
+// LabelValue represents the value of a label.
+type LabelValue string
+
+// NewAlertAPI returns a new AlertAPI for the client.
+func NewAlertAPI(c api.Client) AlertAPI {
+ return &httpAlertAPI{client: apiClient{c}}
+}
+
+type httpAlertAPI struct {
+ client api.Client
+}
+
+func (h *httpAlertAPI) List(ctx context.Context, filter, receiver string, silenced, inhibited, active, unprocessed bool) ([]*ExtendedAlert, error) {
+ u := h.client.URL(epAlerts, nil)
+ params := url.Values{}
+ if filter != "" {
+ params.Add("filter", filter)
+ }
+ params.Add("silenced", fmt.Sprintf("%t", silenced))
+ params.Add("inhibited", fmt.Sprintf("%t", inhibited))
+ params.Add("active", fmt.Sprintf("%t", active))
+ params.Add("unprocessed", fmt.Sprintf("%t", unprocessed))
+ params.Add("receiver", receiver)
+ u.RawQuery = params.Encode()
+
+ req, _ := http.NewRequest(http.MethodGet, u.String(), nil)
+
+ _, body, err := h.client.Do(ctx, req)
+ if err != nil {
+ return nil, err
+ }
+
+ var alts []*ExtendedAlert
+ err = json.Unmarshal(body, &alts)
+
+ return alts, err
+}
+
+func (h *httpAlertAPI) Push(ctx context.Context, alerts ...Alert) error {
+ u := h.client.URL(epAlerts, nil)
+
+ var buf bytes.Buffer
+ if err := json.NewEncoder(&buf).Encode(&alerts); err != nil {
+ return err
+ }
+
+ req, _ := http.NewRequest(http.MethodPost, u.String(), &buf)
+
+ _, _, err := h.client.Do(ctx, req)
+ return err
+}
+
+// SilenceAPI provides bindings for the Alertmanager's silence API.
+type SilenceAPI interface {
+ // Get returns the silence associated with the given ID.
+ Get(ctx context.Context, id string) (*types.Silence, error)
+ // Set updates or creates the given silence and returns its ID.
+ Set(ctx context.Context, sil types.Silence) (string, error)
+ // Expire expires the silence with the given ID.
+ Expire(ctx context.Context, id string) error
+ // List returns silences matching the given filter.
+ List(ctx context.Context, filter string) ([]*types.Silence, error)
+}
+
+// NewSilenceAPI returns a new SilenceAPI for the client.
+func NewSilenceAPI(c api.Client) SilenceAPI {
+ return &httpSilenceAPI{client: apiClient{c}}
+}
+
+type httpSilenceAPI struct {
+ client api.Client
+}
+
+func (h *httpSilenceAPI) Get(ctx context.Context, id string) (*types.Silence, error) {
+ u := h.client.URL(epSilence, map[string]string{
+ "id": id,
+ })
+
+ req, _ := http.NewRequest(http.MethodGet, u.String(), nil)
+
+ _, body, err := h.client.Do(ctx, req)
+ if err != nil {
+ return nil, err
+ }
+
+ var sil types.Silence
+ err = json.Unmarshal(body, &sil)
+
+ return &sil, err
+}
+
+func (h *httpSilenceAPI) Expire(ctx context.Context, id string) error {
+ u := h.client.URL(epSilence, map[string]string{
+ "id": id,
+ })
+
+ req, _ := http.NewRequest(http.MethodDelete, u.String(), nil)
+
+ _, _, err := h.client.Do(ctx, req)
+ return err
+}
+
+func (h *httpSilenceAPI) Set(ctx context.Context, sil types.Silence) (string, error) {
+ u := h.client.URL(epSilences, nil)
+
+ var buf bytes.Buffer
+ if err := json.NewEncoder(&buf).Encode(&sil); err != nil {
+ return "", err
+ }
+
+ req, _ := http.NewRequest(http.MethodPost, u.String(), &buf)
+
+ _, body, err := h.client.Do(ctx, req)
+ if err != nil {
+ return "", err
+ }
+
+ var res struct {
+ SilenceID string `json:"silenceId"`
+ }
+ err = json.Unmarshal(body, &res)
+
+ return res.SilenceID, err
+}
+
+func (h *httpSilenceAPI) List(ctx context.Context, filter string) ([]*types.Silence, error) {
+ u := h.client.URL(epSilences, nil)
+ params := url.Values{}
+ if filter != "" {
+ params.Add("filter", filter)
+ }
+ u.RawQuery = params.Encode()
+
+ req, _ := http.NewRequest(http.MethodGet, u.String(), nil)
+
+ _, body, err := h.client.Do(ctx, req)
+ if err != nil {
+ return nil, err
+ }
+
+ var sils []*types.Silence
+ err = json.Unmarshal(body, &sils)
+
+ return sils, err
+}
--- /dev/null
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package client
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "net/url"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/prometheus/alertmanager/config"
+ "github.com/prometheus/alertmanager/types"
+)
+
+type apiTest struct {
+ // Wrapper around the tested function.
+ do func() (interface{}, error)
+
+ apiRes fakeAPIResponse
+
+ // Expected values returned by the tested function.
+ res interface{}
+ err error
+}
+
+// Fake HTTP client for TestAPI.
+type fakeAPIClient struct {
+ *testing.T
+ ch chan fakeAPIResponse
+}
+
+type fakeAPIResponse struct {
+ // Expected input values.
+ path string
+ method string
+
+ // Values to be returned by fakeAPIClient.Do().
+ err error
+ res interface{}
+}
+
+func (c *fakeAPIClient) URL(ep string, args map[string]string) *url.URL {
+ path := ep
+ for k, v := range args {
+ path = strings.Replace(path, ":"+k, v, -1)
+ }
+
+ return &url.URL{
+ Host: "test:9093",
+ Path: path,
+ }
+}
+
+func (c *fakeAPIClient) Do(ctx context.Context, req *http.Request) (*http.Response, []byte, error) {
+ test := <-c.ch
+
+ if req.URL.Path != test.path {
+ c.Errorf("unexpected request path: want %s, got %s", test.path, req.URL.Path)
+ }
+ if req.Method != test.method {
+ c.Errorf("unexpected request method: want %s, got %s", test.method, req.Method)
+ }
+
+ b, err := json.Marshal(test.res)
+ if err != nil {
+ c.Fatal(err)
+ }
+
+ return &http.Response{}, b, test.err
+}
+
+func TestAPI(t *testing.T) {
+ client := &fakeAPIClient{T: t, ch: make(chan fakeAPIResponse, 1)}
+ now := time.Now()
+
+ statusData := &ServerStatus{
+ ConfigYAML: "{}",
+ ConfigJSON: &config.Config{},
+ VersionInfo: map[string]string{"version": "v1"},
+ Uptime: now,
+ ClusterStatus: &ClusterStatus{Peers: []PeerStatus{}},
+ }
+ doStatus := func() (interface{}, error) {
+ api := httpStatusAPI{client: client}
+ return api.Get(context.Background())
+ }
+
+ alertOne := Alert{
+ StartsAt: now,
+ EndsAt: now.Add(time.Duration(5 * time.Minute)),
+ Labels: LabelSet{"label1": "test1"},
+ Annotations: LabelSet{"annotation1": "some text"},
+ }
+ alerts := []*ExtendedAlert{
+ {
+ Alert: alertOne,
+ Fingerprint: "1c93eec3511dc156",
+ Status: types.AlertStatus{
+ State: types.AlertStateActive,
+ },
+ },
+ }
+ doAlertList := func() (interface{}, error) {
+ api := httpAlertAPI{client: client}
+ return api.List(context.Background(), "", "", false, false, false, false)
+ }
+ doAlertPush := func() (interface{}, error) {
+ api := httpAlertAPI{client: client}
+ return nil, api.Push(context.Background(), []Alert{alertOne}...)
+ }
+
+ silOne := &types.Silence{
+ ID: "abc",
+ Matchers: []*types.Matcher{
+ {
+ Name: "label1",
+ Value: "test1",
+ IsRegex: false,
+ },
+ },
+ StartsAt: now,
+ EndsAt: now.Add(time.Duration(2 * time.Hour)),
+ UpdatedAt: now,
+ CreatedBy: "alice",
+ Comment: "some comment",
+ Status: types.SilenceStatus{
+ State: "active",
+ },
+ }
+ doSilenceGet := func(id string) func() (interface{}, error) {
+ return func() (interface{}, error) {
+ api := httpSilenceAPI{client: client}
+ return api.Get(context.Background(), id)
+ }
+ }
+ doSilenceSet := func(sil types.Silence) func() (interface{}, error) {
+ return func() (interface{}, error) {
+ api := httpSilenceAPI{client: client}
+ return api.Set(context.Background(), sil)
+ }
+ }
+ doSilenceExpire := func(id string) func() (interface{}, error) {
+ return func() (interface{}, error) {
+ api := httpSilenceAPI{client: client}
+ return nil, api.Expire(context.Background(), id)
+ }
+ }
+ doSilenceList := func() (interface{}, error) {
+ api := httpSilenceAPI{client: client}
+ return api.List(context.Background(), "")
+ }
+
+ tests := []apiTest{
+ {
+ do: doStatus,
+ apiRes: fakeAPIResponse{
+ res: statusData,
+ path: "/api/v1/status",
+ method: http.MethodGet,
+ },
+ res: statusData,
+ },
+ {
+ do: doStatus,
+ apiRes: fakeAPIResponse{
+ err: fmt.Errorf("some error"),
+ path: "/api/v1/status",
+ method: http.MethodGet,
+ },
+ err: fmt.Errorf("some error"),
+ },
+ {
+ do: doAlertList,
+ apiRes: fakeAPIResponse{
+ res: alerts,
+ path: "/api/v1/alerts",
+ method: http.MethodGet,
+ },
+ res: alerts,
+ },
+ {
+ do: doAlertList,
+ apiRes: fakeAPIResponse{
+ err: fmt.Errorf("some error"),
+ path: "/api/v1/alerts",
+ method: http.MethodGet,
+ },
+ err: fmt.Errorf("some error"),
+ },
+ {
+ do: doAlertPush,
+ apiRes: fakeAPIResponse{
+ res: nil,
+ path: "/api/v1/alerts",
+ method: http.MethodPost,
+ },
+ res: nil,
+ },
+ {
+ do: doAlertPush,
+ apiRes: fakeAPIResponse{
+ err: fmt.Errorf("some error"),
+ path: "/api/v1/alerts",
+ method: http.MethodPost,
+ },
+ err: fmt.Errorf("some error"),
+ },
+ {
+ do: doSilenceGet("abc"),
+ apiRes: fakeAPIResponse{
+ res: silOne,
+ path: "/api/v1/silence/abc",
+ method: http.MethodGet,
+ },
+ res: silOne,
+ },
+ {
+ do: doSilenceGet("abc"),
+ apiRes: fakeAPIResponse{
+ err: fmt.Errorf("some error"),
+ path: "/api/v1/silence/abc",
+ method: http.MethodGet,
+ },
+ err: fmt.Errorf("some error"),
+ },
+ {
+ do: doSilenceSet(*silOne),
+ apiRes: fakeAPIResponse{
+ res: map[string]string{"SilenceId": "abc"},
+ path: "/api/v1/silences",
+ method: http.MethodPost,
+ },
+ res: "abc",
+ },
+ {
+ do: doSilenceSet(*silOne),
+ apiRes: fakeAPIResponse{
+ err: fmt.Errorf("some error"),
+ path: "/api/v1/silences",
+ method: http.MethodPost,
+ },
+ err: fmt.Errorf("some error"),
+ },
+ {
+ do: doSilenceExpire("abc"),
+ apiRes: fakeAPIResponse{
+ path: "/api/v1/silence/abc",
+ method: http.MethodDelete,
+ },
+ },
+ {
+ do: doSilenceExpire("abc"),
+ apiRes: fakeAPIResponse{
+ err: fmt.Errorf("some error"),
+ path: "/api/v1/silence/abc",
+ method: http.MethodDelete,
+ },
+ err: fmt.Errorf("some error"),
+ },
+ {
+ do: doSilenceList,
+ apiRes: fakeAPIResponse{
+ res: []*types.Silence{silOne},
+ path: "/api/v1/silences",
+ method: http.MethodGet,
+ },
+ res: []*types.Silence{silOne},
+ },
+ {
+ do: doSilenceList,
+ apiRes: fakeAPIResponse{
+ err: fmt.Errorf("some error"),
+ path: "/api/v1/silences",
+ method: http.MethodGet,
+ },
+ err: fmt.Errorf("some error"),
+ },
+ }
+ for _, test := range tests {
+ test := test
+ client.ch <- test.apiRes
+ t.Run(fmt.Sprintf("%s %s", test.apiRes.method, test.apiRes.path), func(t *testing.T) {
+ res, err := test.do()
+ if test.err != nil {
+ if err == nil {
+ t.Errorf("unexpected error: want: %s but got none", test.err)
+ return
+ }
+ if err.Error() != test.err.Error() {
+ t.Errorf("unexpected error: want: %s, got: %s", test.err, err)
+ }
+ return
+ }
+ if err != nil {
+ t.Errorf("unexpected error: %s", err)
+ return
+ }
+ want, err := json.Marshal(test.res)
+ if err != nil {
+ t.Fatal(err)
+ }
+ got, err := json.Marshal(res)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if bytes.Compare(want, got) != 0 {
+ t.Errorf("unexpected result: want: %s, got: %s", string(want), string(got))
+ }
+ })
+ }
+}
+
+// Fake HTTP client for TestAPIClientDo.
+type fakeClient struct {
+ *testing.T
+ ch chan fakeResponse
+}
+
+type fakeResponse struct {
+ code int
+ res interface{}
+ err error
+}
+
+func (c fakeClient) URL(string, map[string]string) *url.URL {
+ return nil
+}
+
+func (c fakeClient) Do(context.Context, *http.Request) (*http.Response, []byte, error) {
+ fakeRes := <-c.ch
+
+ if fakeRes.err != nil {
+ return nil, nil, fakeRes.err
+ }
+
+ var b []byte
+ var err error
+ switch v := fakeRes.res.(type) {
+ case string:
+ b = []byte(v)
+ default:
+ b, err = json.Marshal(v)
+ if err != nil {
+ c.Fatal(err)
+ }
+ }
+
+ return &http.Response{StatusCode: fakeRes.code}, b, nil
+}
+
+type apiClientTest struct {
+ response fakeResponse
+
+ expected string
+ err error
+}
+
+func TestAPIClientDo(t *testing.T) {
+ tests := []apiClientTest{
+ {
+ response: fakeResponse{
+ code: http.StatusOK,
+ res: &apiResponse{
+ Status: statusSuccess,
+ Data: json.RawMessage(`"test"`),
+ },
+ err: nil,
+ },
+ expected: `"test"`,
+ err: nil,
+ },
+ {
+ response: fakeResponse{
+ code: http.StatusBadRequest,
+ res: &apiResponse{
+ Status: statusError,
+ Error: "some error",
+ },
+ err: nil,
+ },
+ err: fmt.Errorf("some error (code: 400)"),
+ },
+ {
+ response: fakeResponse{
+ code: http.StatusOK,
+ res: &apiResponse{
+ Status: statusError,
+ Error: "some error",
+ },
+ err: nil,
+ },
+ err: fmt.Errorf("inconsistent body for response code (code: 200)"),
+ },
+ {
+ response: fakeResponse{
+ code: http.StatusNotFound,
+ res: "not found",
+ err: nil,
+ },
+ err: fmt.Errorf("not found (code: 404)"),
+ },
+ {
+ response: fakeResponse{
+ err: fmt.Errorf("some error"),
+ },
+ err: fmt.Errorf("some error"),
+ },
+ }
+
+ fake := fakeClient{T: t, ch: make(chan fakeResponse, 1)}
+ client := apiClient{fake}
+
+ for _, test := range tests {
+ t.Run("", func(t *testing.T) {
+ fake.ch <- test.response
+
+ _, body, err := client.Do(context.Background(), &http.Request{})
+ if test.err != nil {
+ if err == nil {
+ t.Errorf("expected error %q but got none", test.err)
+ return
+ }
+ if test.err.Error() != err.Error() {
+ t.Errorf("unexpected error: want %q, got %q", test.err, err)
+ return
+ }
+ return
+ }
+
+ if err != nil {
+ t.Errorf("unexpected error %q", err)
+ return
+ }
+
+ want, got := test.expected, string(body)
+ if want != got {
+ t.Errorf("unexpected body: want %q, got %q", want, got)
+ }
+ })
+ }
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cluster
+
+import (
+ "net"
+
+ "github.com/hashicorp/go-sockaddr"
+ "github.com/pkg/errors"
+)
+
+// calculateAdvertiseAddress attempts to clone logic from deep within memberlist
+// (NetTransport.FinalAdvertiseAddr) in order to surface its conclusions to the
+// application, so we can provide more actionable error messages if the user has
+// inadvertantly misconfigured their cluster.
+//
+// https://github.com/hashicorp/memberlist/blob/022f081/net_transport.go#L126
+func calculateAdvertiseAddress(bindAddr, advertiseAddr string) (net.IP, error) {
+ if advertiseAddr != "" {
+ ip := net.ParseIP(advertiseAddr)
+ if ip == nil {
+ return nil, errors.Errorf("failed to parse advertise addr '%s'", advertiseAddr)
+ }
+ if ip4 := ip.To4(); ip4 != nil {
+ ip = ip4
+ }
+ return ip, nil
+ }
+
+ if isAny(bindAddr) {
+ privateIP, err := sockaddr.GetPrivateIP()
+ if err != nil {
+ return nil, errors.Wrap(err, "failed to get private IP")
+ }
+ if privateIP == "" {
+ return nil, errors.Wrap(err, "no private IP found, explicit advertise addr not provided")
+ }
+ ip := net.ParseIP(privateIP)
+ if ip == nil {
+ return nil, errors.Errorf("failed to parse private IP '%s'", privateIP)
+ }
+ return ip, nil
+ }
+
+ ip := net.ParseIP(bindAddr)
+ if ip == nil {
+ return nil, errors.Errorf("failed to parse bind addr '%s'", bindAddr)
+ }
+ return ip, nil
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cluster
+
+import (
+ "sync"
+ "time"
+
+ "github.com/go-kit/kit/log"
+ "github.com/go-kit/kit/log/level"
+ "github.com/gogo/protobuf/proto"
+ "github.com/hashicorp/memberlist"
+ "github.com/prometheus/alertmanager/cluster/clusterpb"
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+// Channel allows clients to send messages for a specific state type that will be
+// broadcasted in a best-effort manner.
+type Channel struct {
+ key string
+ send func([]byte)
+ peers func() []*memberlist.Node
+ sendOversize func(*memberlist.Node, []byte) error
+
+ msgc chan []byte
+ logger log.Logger
+
+ oversizeGossipMessageFailureTotal prometheus.Counter
+ oversizeGossipMessageDroppedTotal prometheus.Counter
+ oversizeGossipMessageSentTotal prometheus.Counter
+ oversizeGossipDuration prometheus.Histogram
+}
+
+// NewChannel creates a new Channel struct, which handles sending normal and
+// oversize messages to peers.
+func NewChannel(
+ key string,
+ send func([]byte),
+ peers func() []*memberlist.Node,
+ sendOversize func(*memberlist.Node, []byte) error,
+ logger log.Logger,
+ stopc chan struct{},
+ reg prometheus.Registerer,
+) *Channel {
+ oversizeGossipMessageFailureTotal := prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "alertmanager_oversized_gossip_message_failure_total",
+ Help: "Number of oversized gossip message sends that failed.",
+ ConstLabels: prometheus.Labels{"key": key},
+ })
+ oversizeGossipMessageSentTotal := prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "alertmanager_oversized_gossip_message_sent_total",
+ Help: "Number of oversized gossip message sent.",
+ ConstLabels: prometheus.Labels{"key": key},
+ })
+ oversizeGossipMessageDroppedTotal := prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "alertmanager_oversized_gossip_message_dropped_total",
+ Help: "Number of oversized gossip messages that were dropped due to a full message queue.",
+ ConstLabels: prometheus.Labels{"key": key},
+ })
+ oversizeGossipDuration := prometheus.NewHistogram(prometheus.HistogramOpts{
+ Name: "alertmanager_oversize_gossip_message_duration_seconds",
+ Help: "Duration of oversized gossip message requests.",
+ ConstLabels: prometheus.Labels{"key": key},
+ })
+
+ reg.MustRegister(oversizeGossipDuration, oversizeGossipMessageFailureTotal, oversizeGossipMessageDroppedTotal, oversizeGossipMessageSentTotal)
+
+ c := &Channel{
+ key: key,
+ send: send,
+ peers: peers,
+ logger: logger,
+ msgc: make(chan []byte, 200),
+ sendOversize: sendOversize,
+ oversizeGossipMessageFailureTotal: oversizeGossipMessageFailureTotal,
+ oversizeGossipMessageDroppedTotal: oversizeGossipMessageDroppedTotal,
+ oversizeGossipMessageSentTotal: oversizeGossipMessageSentTotal,
+ oversizeGossipDuration: oversizeGossipDuration,
+ }
+
+ go c.handleOverSizedMessages(stopc)
+
+ return c
+}
+
+// handleOverSizedMessages prevents memberlist from opening too many parallel
+// TCP connections to its peers.
+func (c *Channel) handleOverSizedMessages(stopc chan struct{}) {
+ var wg sync.WaitGroup
+ for {
+ select {
+ case b := <-c.msgc:
+ for _, n := range c.peers() {
+ wg.Add(1)
+ go func(n *memberlist.Node) {
+ defer wg.Done()
+ c.oversizeGossipMessageSentTotal.Inc()
+ start := time.Now()
+ if err := c.sendOversize(n, b); err != nil {
+ level.Debug(c.logger).Log("msg", "failed to send reliable", "key", c.key, "node", n, "err", err)
+ c.oversizeGossipMessageFailureTotal.Inc()
+ return
+ }
+ c.oversizeGossipDuration.Observe(time.Since(start).Seconds())
+ }(n)
+ }
+
+ wg.Wait()
+ case <-stopc:
+ return
+ }
+ }
+}
+
+// Broadcast enqueues a message for broadcasting.
+func (c *Channel) Broadcast(b []byte) {
+ b, err := proto.Marshal(&clusterpb.Part{Key: c.key, Data: b})
+ if err != nil {
+ return
+ }
+
+ if OversizedMessage(b) {
+ select {
+ case c.msgc <- b:
+ default:
+ level.Debug(c.logger).Log("msg", "oversized gossip channel full")
+ c.oversizeGossipMessageDroppedTotal.Inc()
+ }
+ } else {
+ c.send(b)
+ }
+}
+
+// OversizedMessage indicates whether or not the byte payload should be sent
+// via TCP.
+func OversizedMessage(b []byte) bool {
+ return len(b) > maxGossipPacketSize/2
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cluster
+
+import (
+ "bytes"
+ "context"
+ "io"
+ "os"
+ "testing"
+
+ "github.com/go-kit/kit/log"
+ "github.com/hashicorp/memberlist"
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+func TestNormalMessagesGossiped(t *testing.T) {
+ var sent bool
+ c := newChannel(
+ func(_ []byte) { sent = true },
+ func() []*memberlist.Node { return nil },
+ func(_ *memberlist.Node, _ []byte) error { return nil },
+ )
+
+ c.Broadcast([]byte{})
+
+ if sent != true {
+ t.Fatalf("small message not sent")
+ }
+}
+
+func TestOversizedMessagesGossiped(t *testing.T) {
+ var sent bool
+ ctx, cancel := context.WithCancel(context.Background())
+ c := newChannel(
+ func(_ []byte) {},
+ func() []*memberlist.Node { return []*memberlist.Node{&memberlist.Node{}} },
+ func(_ *memberlist.Node, _ []byte) error { sent = true; cancel(); return nil },
+ )
+
+ f, err := os.Open("/dev/zero")
+ if err != nil {
+ t.Fatalf("failed to open /dev/zero: %v", err)
+ }
+ defer f.Close()
+
+ buf := new(bytes.Buffer)
+ toCopy := int64(800)
+ if n, err := io.CopyN(buf, f, toCopy); err != nil {
+ t.Fatalf("failed to copy bytes: %v", err)
+ } else if n != toCopy {
+ t.Fatalf("wanted to copy %d bytes, only copied %d", toCopy, n)
+ }
+
+ c.Broadcast(buf.Bytes())
+
+ <-ctx.Done()
+
+ if sent != true {
+ t.Fatalf("oversized message not sent")
+ }
+}
+
+func newChannel(
+ send func([]byte),
+ peers func() []*memberlist.Node,
+ sendOversize func(*memberlist.Node, []byte) error,
+) *Channel {
+ return NewChannel(
+ "test",
+ send,
+ peers,
+ sendOversize,
+ log.NewNopLogger(),
+ make(chan struct{}),
+ prometheus.NewRegistry(),
+ )
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cluster
+
+import (
+ "context"
+ "fmt"
+ "math/rand"
+ "net"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/go-kit/kit/log"
+ "github.com/go-kit/kit/log/level"
+ "github.com/hashicorp/memberlist"
+ "github.com/oklog/ulid"
+ "github.com/pkg/errors"
+
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+// Peer is a single peer in a gossip cluster.
+type Peer struct {
+ mlist *memberlist.Memberlist
+ delegate *delegate
+
+ mtx sync.RWMutex
+ states map[string]State
+ stopc chan struct{}
+ readyc chan struct{}
+
+ peerLock sync.RWMutex
+ peers map[string]peer
+ failedPeers []peer
+
+ failedReconnectionsCounter prometheus.Counter
+ reconnectionsCounter prometheus.Counter
+ peerLeaveCounter prometheus.Counter
+ peerUpdateCounter prometheus.Counter
+ peerJoinCounter prometheus.Counter
+
+ logger log.Logger
+}
+
+// peer is an internal type used for bookkeeping. It holds the state of peers
+// in the cluster.
+type peer struct {
+ status PeerStatus
+ leaveTime time.Time
+
+ *memberlist.Node
+}
+
+// PeerStatus is the state that a peer is in.
+type PeerStatus int
+
+const (
+ StatusNone PeerStatus = iota
+ StatusAlive
+ StatusFailed
+)
+
+func (s PeerStatus) String() string {
+ switch s {
+ case StatusNone:
+ return "none"
+ case StatusAlive:
+ return "alive"
+ case StatusFailed:
+ return "failed"
+ default:
+ panic(fmt.Sprintf("unknown PeerStatus: %d", s))
+ }
+}
+
+const (
+ DefaultPushPullInterval = 60 * time.Second
+ DefaultGossipInterval = 200 * time.Millisecond
+ DefaultTcpTimeout = 10 * time.Second
+ DefaultProbeTimeout = 500 * time.Millisecond
+ DefaultProbeInterval = 1 * time.Second
+ DefaultReconnectInterval = 10 * time.Second
+ DefaultReconnectTimeout = 6 * time.Hour
+ maxGossipPacketSize = 1400
+)
+
+func Join(
+ l log.Logger,
+ reg prometheus.Registerer,
+ bindAddr string,
+ advertiseAddr string,
+ knownPeers []string,
+ waitIfEmpty bool,
+ pushPullInterval time.Duration,
+ gossipInterval time.Duration,
+ tcpTimeout time.Duration,
+ probeTimeout time.Duration,
+ probeInterval time.Duration,
+ reconnectInterval time.Duration,
+ reconnectTimeout time.Duration,
+) (*Peer, error) {
+ bindHost, bindPortStr, err := net.SplitHostPort(bindAddr)
+ if err != nil {
+ return nil, err
+ }
+ bindPort, err := strconv.Atoi(bindPortStr)
+ if err != nil {
+ return nil, errors.Wrap(err, "invalid listen address")
+ }
+
+ var advertiseHost string
+ var advertisePort int
+ if advertiseAddr != "" {
+ var advertisePortStr string
+ advertiseHost, advertisePortStr, err = net.SplitHostPort(advertiseAddr)
+ if err != nil {
+ return nil, errors.Wrap(err, "invalid advertise address")
+ }
+ advertisePort, err = strconv.Atoi(advertisePortStr)
+ if err != nil {
+ return nil, errors.Wrap(err, "invalid advertise address, wrong port")
+ }
+ }
+
+ resolvedPeers, err := resolvePeers(context.Background(), knownPeers, advertiseAddr, net.Resolver{}, waitIfEmpty)
+ if err != nil {
+ return nil, errors.Wrap(err, "resolve peers")
+ }
+ level.Debug(l).Log("msg", "resolved peers to following addresses", "peers", strings.Join(resolvedPeers, ","))
+
+ // Initial validation of user-specified advertise address.
+ addr, err := calculateAdvertiseAddress(bindHost, advertiseHost)
+ if err != nil {
+ level.Warn(l).Log("err", "couldn't deduce an advertise address: "+err.Error())
+ } else if hasNonlocal(resolvedPeers) && isUnroutable(addr.String()) {
+ level.Warn(l).Log("err", "this node advertises itself on an unroutable address", "addr", addr.String())
+ level.Warn(l).Log("err", "this node will be unreachable in the cluster")
+ level.Warn(l).Log("err", "provide --cluster.advertise-address as a routable IP address or hostname")
+ } else if isAny(bindAddr) && advertiseHost == "" {
+ // memberlist doesn't advertise properly when the bind address is empty or unspecified.
+ level.Info(l).Log("msg", "setting advertise address explicitly", "addr", addr.String(), "port", bindPort)
+ advertiseHost = addr.String()
+ advertisePort = bindPort
+ }
+
+ // TODO(fabxc): generate human-readable but random names?
+ name, err := ulid.New(ulid.Now(), rand.New(rand.NewSource(time.Now().UnixNano())))
+ if err != nil {
+ return nil, err
+ }
+
+ p := &Peer{
+ states: map[string]State{},
+ stopc: make(chan struct{}),
+ readyc: make(chan struct{}),
+ logger: l,
+ peers: map[string]peer{},
+ }
+
+ p.register(reg)
+
+ retransmit := len(knownPeers) / 2
+ if retransmit < 3 {
+ retransmit = 3
+ }
+ p.delegate = newDelegate(l, reg, p, retransmit)
+
+ cfg := memberlist.DefaultLANConfig()
+ cfg.Name = name.String()
+ cfg.BindAddr = bindHost
+ cfg.BindPort = bindPort
+ cfg.Delegate = p.delegate
+ cfg.Events = p.delegate
+ cfg.GossipInterval = gossipInterval
+ cfg.PushPullInterval = pushPullInterval
+ cfg.TCPTimeout = tcpTimeout
+ cfg.ProbeTimeout = probeTimeout
+ cfg.ProbeInterval = probeInterval
+ cfg.LogOutput = &logWriter{l: l}
+ cfg.GossipNodes = retransmit
+ cfg.UDPBufferSize = maxGossipPacketSize
+
+ if advertiseHost != "" {
+ cfg.AdvertiseAddr = advertiseHost
+ cfg.AdvertisePort = advertisePort
+ p.setInitialFailed(resolvedPeers, fmt.Sprintf("%s:%d", advertiseHost, advertisePort))
+ } else {
+ p.setInitialFailed(resolvedPeers, bindAddr)
+ }
+
+ ml, err := memberlist.Create(cfg)
+ if err != nil {
+ return nil, errors.Wrap(err, "create memberlist")
+ }
+ p.mlist = ml
+
+ n, err := ml.Join(resolvedPeers)
+ if err != nil {
+ level.Warn(l).Log("msg", "failed to join cluster", "err", err)
+ } else {
+ level.Debug(l).Log("msg", "joined cluster", "peers", n)
+ }
+
+ if reconnectInterval != 0 {
+ go p.handleReconnect(reconnectInterval)
+ }
+ if reconnectTimeout != 0 {
+ go p.handleReconnectTimeout(5*time.Minute, reconnectTimeout)
+ }
+
+ return p, nil
+}
+
+// All peers are initially added to the failed list. They will be removed from
+// this list in peerJoin when making their initial connection.
+func (p *Peer) setInitialFailed(peers []string, myAddr string) {
+ if len(peers) == 0 {
+ return
+ }
+
+ p.peerLock.RLock()
+ defer p.peerLock.RUnlock()
+
+ now := time.Now()
+ for _, peerAddr := range peers {
+ if peerAddr == myAddr {
+ // Don't add ourselves to the initially failing list,
+ // we don't connect to ourselves.
+ continue
+ }
+ host, port, err := net.SplitHostPort(peerAddr)
+ if err != nil {
+ continue
+ }
+ ip := net.ParseIP(host)
+ if ip == nil {
+ // Don't add textual addresses since memberlist only advertises
+ // dotted decimal or IPv6 addresses.
+ continue
+ }
+ portUint, err := strconv.ParseUint(port, 10, 16)
+ if err != nil {
+ continue
+ }
+
+ pr := peer{
+ status: StatusFailed,
+ leaveTime: now,
+ Node: &memberlist.Node{
+ Addr: ip,
+ Port: uint16(portUint),
+ },
+ }
+ p.failedPeers = append(p.failedPeers, pr)
+ p.peers[peerAddr] = pr
+ }
+}
+
+type logWriter struct {
+ l log.Logger
+}
+
+func (l *logWriter) Write(b []byte) (int, error) {
+ return len(b), level.Debug(l.l).Log("memberlist", string(b))
+}
+
+func (p *Peer) register(reg prometheus.Registerer) {
+ clusterFailedPeers := prometheus.NewGaugeFunc(prometheus.GaugeOpts{
+ Name: "alertmanager_cluster_failed_peers",
+ Help: "Number indicating the current number of failed peers in the cluster.",
+ }, func() float64 {
+ p.peerLock.RLock()
+ defer p.peerLock.RUnlock()
+
+ return float64(len(p.failedPeers))
+ })
+ p.failedReconnectionsCounter = prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "alertmanager_cluster_reconnections_failed_total",
+ Help: "A counter of the number of failed cluster peer reconnection attempts.",
+ })
+
+ p.reconnectionsCounter = prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "alertmanager_cluster_reconnections_total",
+ Help: "A counter of the number of cluster peer reconnections.",
+ })
+
+ p.peerLeaveCounter = prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "alertmanager_cluster_peers_left_total",
+ Help: "A counter of the number of peers that have left.",
+ })
+ p.peerUpdateCounter = prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "alertmanager_cluster_peers_update_total",
+ Help: "A counter of the number of peers that have updated metadata.",
+ })
+ p.peerJoinCounter = prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "alertmanager_cluster_peers_joined_total",
+ Help: "A counter of the number of peers that have joined.",
+ })
+
+ reg.MustRegister(clusterFailedPeers, p.failedReconnectionsCounter, p.reconnectionsCounter,
+ p.peerLeaveCounter, p.peerUpdateCounter, p.peerJoinCounter)
+}
+
+func (p *Peer) handleReconnectTimeout(d time.Duration, timeout time.Duration) {
+ tick := time.NewTicker(d)
+ defer tick.Stop()
+
+ for {
+ select {
+ case <-p.stopc:
+ return
+ case <-tick.C:
+ p.removeFailedPeers(timeout)
+ }
+ }
+}
+
+func (p *Peer) removeFailedPeers(timeout time.Duration) {
+ p.peerLock.Lock()
+ defer p.peerLock.Unlock()
+
+ now := time.Now()
+
+ keep := make([]peer, 0, len(p.failedPeers))
+ for _, pr := range p.failedPeers {
+ if pr.leaveTime.Add(timeout).After(now) {
+ keep = append(keep, pr)
+ } else {
+ level.Debug(p.logger).Log("msg", "failed peer has timed out", "peer", pr.Node, "addr", pr.Address())
+ delete(p.peers, pr.Name)
+ }
+ }
+
+ p.failedPeers = keep
+}
+
+func (p *Peer) handleReconnect(d time.Duration) {
+ tick := time.NewTicker(d)
+ defer tick.Stop()
+
+ for {
+ select {
+ case <-p.stopc:
+ return
+ case <-tick.C:
+ p.reconnect()
+ }
+ }
+}
+
+func (p *Peer) reconnect() {
+ p.peerLock.RLock()
+ failedPeers := p.failedPeers
+ p.peerLock.RUnlock()
+
+ logger := log.With(p.logger, "msg", "reconnect")
+ for _, pr := range failedPeers {
+ // No need to do book keeping on failedPeers here. If a
+ // reconnect is successful, they will be announced in
+ // peerJoin().
+ if _, err := p.mlist.Join([]string{pr.Address()}); err != nil {
+ p.failedReconnectionsCounter.Inc()
+ level.Debug(logger).Log("result", "failure", "peer", pr.Node, "addr", pr.Address())
+ } else {
+ p.reconnectionsCounter.Inc()
+ level.Debug(logger).Log("result", "success", "peer", pr.Node, "addr", pr.Address())
+ }
+ }
+}
+
+func (p *Peer) peerJoin(n *memberlist.Node) {
+ p.peerLock.Lock()
+ defer p.peerLock.Unlock()
+
+ var oldStatus PeerStatus
+ pr, ok := p.peers[n.Address()]
+ if !ok {
+ oldStatus = StatusNone
+ pr = peer{
+ status: StatusAlive,
+ Node: n,
+ }
+ } else {
+ oldStatus = pr.status
+ pr.Node = n
+ pr.status = StatusAlive
+ pr.leaveTime = time.Time{}
+ }
+
+ p.peers[n.Address()] = pr
+ p.peerJoinCounter.Inc()
+
+ if oldStatus == StatusFailed {
+ level.Debug(p.logger).Log("msg", "peer rejoined", "peer", pr.Node)
+ p.failedPeers = removeOldPeer(p.failedPeers, pr.Address())
+ }
+}
+
+func (p *Peer) peerLeave(n *memberlist.Node) {
+ p.peerLock.Lock()
+ defer p.peerLock.Unlock()
+
+ pr, ok := p.peers[n.Address()]
+ if !ok {
+ // Why are we receiving a leave notification from a node that
+ // never joined?
+ return
+ }
+
+ pr.status = StatusFailed
+ pr.leaveTime = time.Now()
+ p.failedPeers = append(p.failedPeers, pr)
+ p.peers[n.Address()] = pr
+
+ p.peerLeaveCounter.Inc()
+ level.Debug(p.logger).Log("msg", "peer left", "peer", pr.Node)
+}
+
+func (p *Peer) peerUpdate(n *memberlist.Node) {
+ p.peerLock.Lock()
+ defer p.peerLock.Unlock()
+
+ pr, ok := p.peers[n.Address()]
+ if !ok {
+ // Why are we receiving an update from a node that never
+ // joined?
+ return
+ }
+
+ pr.Node = n
+ p.peers[n.Address()] = pr
+
+ p.peerUpdateCounter.Inc()
+ level.Debug(p.logger).Log("msg", "peer updated", "peer", pr.Node)
+}
+
+// AddState adds a new state that will be gossiped. It returns a channel to which
+// broadcast messages for the state can be sent.
+func (p *Peer) AddState(key string, s State, reg prometheus.Registerer) *Channel {
+ p.states[key] = s
+ send := func(b []byte) {
+ p.delegate.bcast.QueueBroadcast(simpleBroadcast(b))
+ }
+ peers := func() []*memberlist.Node {
+ nodes := p.Peers()
+ for i, n := range nodes {
+ if n.Name == p.Self().Name {
+ nodes = append(nodes[:i], nodes[i+1:]...)
+ break
+ }
+ }
+ return nodes
+ }
+ sendOversize := func(n *memberlist.Node, b []byte) error {
+ return p.mlist.SendReliable(n, b)
+ }
+ return NewChannel(key, send, peers, sendOversize, p.logger, p.stopc, reg)
+}
+
+// Leave the cluster, waiting up to timeout.
+func (p *Peer) Leave(timeout time.Duration) error {
+ close(p.stopc)
+ level.Debug(p.logger).Log("msg", "leaving cluster")
+ return p.mlist.Leave(timeout)
+}
+
+// Name returns the unique ID of this peer in the cluster.
+func (p *Peer) Name() string {
+ return p.mlist.LocalNode().Name
+}
+
+// ClusterSize returns the current number of alive members in the cluster.
+func (p *Peer) ClusterSize() int {
+ return p.mlist.NumMembers()
+}
+
+// Return true when router has settled.
+func (p *Peer) Ready() bool {
+ select {
+ case <-p.readyc:
+ return true
+ default:
+ }
+ return false
+}
+
+// Wait until Settle() has finished.
+func (p *Peer) WaitReady() {
+ <-p.readyc
+}
+
+// Return a status string representing the peer state.
+func (p *Peer) Status() string {
+ if p.Ready() {
+ return "ready"
+ } else {
+ return "settling"
+ }
+}
+
+// Info returns a JSON-serializable dump of cluster state.
+// Useful for debug.
+func (p *Peer) Info() map[string]interface{} {
+ p.mtx.RLock()
+ defer p.mtx.RUnlock()
+
+ return map[string]interface{}{
+ "self": p.mlist.LocalNode(),
+ "members": p.mlist.Members(),
+ }
+}
+
+// Self returns the node information about the peer itself.
+func (p *Peer) Self() *memberlist.Node {
+ return p.mlist.LocalNode()
+}
+
+// Peers returns the peers in the cluster.
+func (p *Peer) Peers() []*memberlist.Node {
+ return p.mlist.Members()
+}
+
+// Position returns the position of the peer in the cluster.
+func (p *Peer) Position() int {
+ all := p.Peers()
+ sort.Slice(all, func(i, j int) bool {
+ return all[i].Name < all[j].Name
+ })
+
+ k := 0
+ for _, n := range all {
+ if n.Name == p.Self().Name {
+ break
+ }
+ k++
+ }
+ return k
+}
+
+// Settle waits until the mesh is ready (and sets the appropriate internal state when it is).
+// The idea is that we don't want to start "working" before we get a chance to know most of the alerts and/or silences.
+// Inspired from https://github.com/apache/cassandra/blob/7a40abb6a5108688fb1b10c375bb751cbb782ea4/src/java/org/apache/cassandra/gms/Gossiper.java
+// This is clearly not perfect or strictly correct but should prevent the alertmanager to send notification before it is obviously not ready.
+// This is especially important for those that do not have persistent storage.
+func (p *Peer) Settle(ctx context.Context, interval time.Duration) {
+ const NumOkayRequired = 3
+ level.Info(p.logger).Log("msg", "Waiting for gossip to settle...", "interval", interval)
+ start := time.Now()
+ nPeers := 0
+ nOkay := 0
+ totalPolls := 0
+ for {
+ select {
+ case <-ctx.Done():
+ elapsed := time.Since(start)
+ level.Info(p.logger).Log("msg", "gossip not settled but continuing anyway", "polls", totalPolls, "elapsed", elapsed)
+ close(p.readyc)
+ return
+ case <-time.After(interval):
+ }
+ elapsed := time.Since(start)
+ n := len(p.Peers())
+ if nOkay >= NumOkayRequired {
+ level.Info(p.logger).Log("msg", "gossip settled; proceeding", "elapsed", elapsed)
+ break
+ }
+ if n == nPeers {
+ nOkay++
+ level.Debug(p.logger).Log("msg", "gossip looks settled", "elapsed", elapsed)
+ } else {
+ nOkay = 0
+ level.Info(p.logger).Log("msg", "gossip not settled", "polls", totalPolls, "before", nPeers, "now", n, "elapsed", elapsed)
+ }
+ nPeers = n
+ totalPolls++
+ }
+ close(p.readyc)
+}
+
+// State is a piece of state that can be serialized and merged with other
+// serialized state.
+type State interface {
+ // MarshalBinary serializes the underlying state.
+ MarshalBinary() ([]byte, error)
+
+ // Merge merges serialized state into the underlying state.
+ Merge(b []byte) error
+}
+
+// We use a simple broadcast implementation in which items are never invalidated by others.
+type simpleBroadcast []byte
+
+func (b simpleBroadcast) Message() []byte { return []byte(b) }
+func (b simpleBroadcast) Invalidates(memberlist.Broadcast) bool { return false }
+func (b simpleBroadcast) Finished() {}
+
+func resolvePeers(ctx context.Context, peers []string, myAddress string, res net.Resolver, waitIfEmpty bool) ([]string, error) {
+ var resolvedPeers []string
+
+ for _, peer := range peers {
+ host, port, err := net.SplitHostPort(peer)
+ if err != nil {
+ return nil, errors.Wrapf(err, "split host/port for peer %s", peer)
+ }
+
+ retryCtx, cancel := context.WithCancel(ctx)
+
+ ips, err := res.LookupIPAddr(ctx, host)
+ if err != nil {
+ // Assume direct address.
+ resolvedPeers = append(resolvedPeers, peer)
+ continue
+ }
+
+ if len(ips) == 0 {
+ var lookupErrSpotted bool
+
+ err := retry(2*time.Second, retryCtx.Done(), func() error {
+ if lookupErrSpotted {
+ // We need to invoke cancel in next run of retry when lookupErrSpotted to preserve LookupIPAddr error.
+ cancel()
+ }
+
+ ips, err = res.LookupIPAddr(retryCtx, host)
+ if err != nil {
+ lookupErrSpotted = true
+ return errors.Wrapf(err, "IP Addr lookup for peer %s", peer)
+ }
+
+ ips = removeMyAddr(ips, port, myAddress)
+ if len(ips) == 0 {
+ if !waitIfEmpty {
+ return nil
+ }
+ return errors.New("empty IPAddr result. Retrying")
+ }
+
+ return nil
+ })
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ for _, ip := range ips {
+ resolvedPeers = append(resolvedPeers, net.JoinHostPort(ip.String(), port))
+ }
+ }
+
+ return resolvedPeers, nil
+}
+
+func removeMyAddr(ips []net.IPAddr, targetPort string, myAddr string) []net.IPAddr {
+ var result []net.IPAddr
+
+ for _, ip := range ips {
+ if net.JoinHostPort(ip.String(), targetPort) == myAddr {
+ continue
+ }
+ result = append(result, ip)
+ }
+
+ return result
+}
+
+func hasNonlocal(clusterPeers []string) bool {
+ for _, peer := range clusterPeers {
+ if host, _, err := net.SplitHostPort(peer); err == nil {
+ peer = host
+ }
+ if ip := net.ParseIP(peer); ip != nil && !ip.IsLoopback() {
+ return true
+ } else if ip == nil && strings.ToLower(peer) != "localhost" {
+ return true
+ }
+ }
+ return false
+}
+
+func isUnroutable(addr string) bool {
+ if host, _, err := net.SplitHostPort(addr); err == nil {
+ addr = host
+ }
+ if ip := net.ParseIP(addr); ip != nil && (ip.IsUnspecified() || ip.IsLoopback()) {
+ return true // typically 0.0.0.0 or localhost
+ } else if ip == nil && strings.ToLower(addr) == "localhost" {
+ return true
+ }
+ return false
+}
+
+func isAny(addr string) bool {
+ if host, _, err := net.SplitHostPort(addr); err == nil {
+ addr = host
+ }
+ return addr == "" || net.ParseIP(addr).IsUnspecified()
+}
+
+// retry executes f every interval seconds until timeout or no error is returned from f.
+func retry(interval time.Duration, stopc <-chan struct{}, f func() error) error {
+ tick := time.NewTicker(interval)
+ defer tick.Stop()
+
+ var err error
+ for {
+ if err = f(); err == nil {
+ return nil
+ }
+ select {
+ case <-stopc:
+ return err
+ case <-tick.C:
+ }
+ }
+}
+
+func removeOldPeer(old []peer, addr string) []peer {
+ new := make([]peer, 0, len(old))
+ for _, p := range old {
+ if p.Address() != addr {
+ new = append(new, p)
+ }
+ }
+
+ return new
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cluster
+
+import (
+ "context"
+ "testing"
+ "time"
+
+ "github.com/go-kit/kit/log"
+ "github.com/stretchr/testify/require"
+
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+func TestJoinLeave(t *testing.T) {
+ logger := log.NewNopLogger()
+ p, err := Join(
+ logger,
+ prometheus.NewRegistry(),
+ "0.0.0.0:0",
+ "",
+ []string{},
+ true,
+ DefaultPushPullInterval,
+ DefaultGossipInterval,
+ DefaultTcpTimeout,
+ DefaultProbeTimeout,
+ DefaultProbeInterval,
+ DefaultReconnectInterval,
+ DefaultReconnectTimeout,
+ )
+ require.NoError(t, err)
+ require.NotNil(t, p)
+ require.False(t, p.Ready())
+ require.Equal(t, p.Status(), "settling")
+ go p.Settle(context.Background(), 0*time.Second)
+ p.WaitReady()
+ require.Equal(t, p.Status(), "ready")
+
+ // Create the peer who joins the first.
+ p2, err := Join(
+ logger,
+ prometheus.NewRegistry(),
+ "0.0.0.0:0",
+ "",
+ []string{p.Self().Address()},
+ true,
+ DefaultPushPullInterval,
+ DefaultGossipInterval,
+ DefaultTcpTimeout,
+ DefaultProbeTimeout,
+ DefaultProbeInterval,
+ DefaultReconnectInterval,
+ DefaultReconnectTimeout,
+ )
+ require.NoError(t, err)
+ require.NotNil(t, p2)
+ go p2.Settle(context.Background(), 0*time.Second)
+
+ require.Equal(t, 2, p.ClusterSize())
+ p2.Leave(0 * time.Second)
+ require.Equal(t, 1, p.ClusterSize())
+ require.Equal(t, 1, len(p.failedPeers))
+ require.Equal(t, p2.Self().Address(), p.peers[p2.Self().Address()].Node.Address())
+ require.Equal(t, p2.Name(), p.failedPeers[0].Name)
+}
+
+func TestReconnect(t *testing.T) {
+ logger := log.NewNopLogger()
+ p, err := Join(
+ logger,
+ prometheus.NewRegistry(),
+ "0.0.0.0:0",
+ "",
+ []string{},
+ true,
+ DefaultPushPullInterval,
+ DefaultGossipInterval,
+ DefaultTcpTimeout,
+ DefaultProbeTimeout,
+ DefaultProbeInterval,
+ DefaultReconnectInterval,
+ DefaultReconnectTimeout,
+ )
+ require.NoError(t, err)
+ require.NotNil(t, p)
+ go p.Settle(context.Background(), 0*time.Second)
+ p.WaitReady()
+
+ p2, err := Join(
+ logger,
+ prometheus.NewRegistry(),
+ "0.0.0.0:0",
+ "",
+ []string{},
+ true,
+ DefaultPushPullInterval,
+ DefaultGossipInterval,
+ DefaultTcpTimeout,
+ DefaultProbeTimeout,
+ DefaultProbeInterval,
+ DefaultReconnectInterval,
+ DefaultReconnectTimeout,
+ )
+ require.NoError(t, err)
+ require.NotNil(t, p2)
+ go p2.Settle(context.Background(), 0*time.Second)
+ p2.WaitReady()
+
+ p.peerJoin(p2.Self())
+ p.peerLeave(p2.Self())
+
+ require.Equal(t, 1, p.ClusterSize())
+ require.Equal(t, 1, len(p.failedPeers))
+
+ p.reconnect()
+
+ require.Equal(t, 2, p.ClusterSize())
+ require.Equal(t, 0, len(p.failedPeers))
+ require.Equal(t, StatusAlive, p.peers[p2.Self().Address()].status)
+}
+
+func TestRemoveFailedPeers(t *testing.T) {
+ logger := log.NewNopLogger()
+ p, err := Join(
+ logger,
+ prometheus.NewRegistry(),
+ "0.0.0.0:0",
+ "",
+ []string{},
+ true,
+ DefaultPushPullInterval,
+ DefaultGossipInterval,
+ DefaultTcpTimeout,
+ DefaultProbeTimeout,
+ DefaultProbeInterval,
+ DefaultReconnectInterval,
+ DefaultReconnectTimeout,
+ )
+ require.NoError(t, err)
+ require.NotNil(t, p)
+ n := p.Self()
+
+ now := time.Now()
+ p1 := peer{
+ status: StatusFailed,
+ leaveTime: now,
+ Node: n,
+ }
+ p2 := peer{
+ status: StatusFailed,
+ leaveTime: now.Add(-time.Hour),
+ Node: n,
+ }
+ p3 := peer{
+ status: StatusFailed,
+ leaveTime: now.Add(30 * -time.Minute),
+ Node: n,
+ }
+ p.failedPeers = []peer{p1, p2, p3}
+
+ p.removeFailedPeers(30 * time.Minute)
+ require.Equal(t, 1, len(p.failedPeers))
+ require.Equal(t, p1, p.failedPeers[0])
+}
+
+func TestInitiallyFailingPeers(t *testing.T) {
+ logger := log.NewNopLogger()
+ myAddr := "1.2.3.4:5000"
+ peerAddrs := []string{myAddr, "2.3.4.5:5000", "3.4.5.6:5000", "foo.example.com:5000"}
+ p, err := Join(
+ logger,
+ prometheus.NewRegistry(),
+ "0.0.0.0:0",
+ "",
+ []string{},
+ true,
+ DefaultPushPullInterval,
+ DefaultGossipInterval,
+ DefaultTcpTimeout,
+ DefaultProbeTimeout,
+ DefaultProbeInterval,
+ DefaultReconnectInterval,
+ DefaultReconnectTimeout,
+ )
+ require.NoError(t, err)
+ require.NotNil(t, p)
+
+ p.setInitialFailed(peerAddrs, myAddr)
+
+ // We shouldn't have added "our" bind addr and the FQDN address to the
+ // failed peers list.
+ require.Equal(t, len(peerAddrs)-2, len(p.failedPeers))
+ for _, addr := range peerAddrs {
+ if addr == myAddr || addr == "foo.example.com:5000" {
+ continue
+ }
+
+ pr, ok := p.peers[addr]
+ require.True(t, ok)
+ require.Equal(t, StatusFailed.String(), pr.status.String())
+ require.Equal(t, addr, pr.Address())
+ expectedLen := len(p.failedPeers) - 1
+ p.peerJoin(pr.Node)
+ require.Equal(t, expectedLen, len(p.failedPeers))
+ }
+}
--- /dev/null
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: cluster.proto
+
+/*
+ Package clusterpb is a generated protocol buffer package.
+
+ It is generated from these files:
+ cluster.proto
+
+ It has these top-level messages:
+ Part
+ FullState
+*/
+package clusterpb
+
+import proto "github.com/gogo/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import _ "github.com/gogo/protobuf/gogoproto"
+
+import io "io"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
+
+type Part struct {
+ Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
+ Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
+}
+
+func (m *Part) Reset() { *m = Part{} }
+func (m *Part) String() string { return proto.CompactTextString(m) }
+func (*Part) ProtoMessage() {}
+func (*Part) Descriptor() ([]byte, []int) { return fileDescriptorCluster, []int{0} }
+
+type FullState struct {
+ Parts []Part `protobuf:"bytes,1,rep,name=parts" json:"parts"`
+}
+
+func (m *FullState) Reset() { *m = FullState{} }
+func (m *FullState) String() string { return proto.CompactTextString(m) }
+func (*FullState) ProtoMessage() {}
+func (*FullState) Descriptor() ([]byte, []int) { return fileDescriptorCluster, []int{1} }
+
+func init() {
+ proto.RegisterType((*Part)(nil), "clusterpb.Part")
+ proto.RegisterType((*FullState)(nil), "clusterpb.FullState")
+}
+func (m *Part) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Part) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Key) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintCluster(dAtA, i, uint64(len(m.Key)))
+ i += copy(dAtA[i:], m.Key)
+ }
+ if len(m.Data) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintCluster(dAtA, i, uint64(len(m.Data)))
+ i += copy(dAtA[i:], m.Data)
+ }
+ return i, nil
+}
+
+func (m *FullState) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *FullState) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Parts) > 0 {
+ for _, msg := range m.Parts {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintCluster(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ return i, nil
+}
+
+func encodeVarintCluster(dAtA []byte, offset int, v uint64) int {
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return offset + 1
+}
+func (m *Part) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Key)
+ if l > 0 {
+ n += 1 + l + sovCluster(uint64(l))
+ }
+ l = len(m.Data)
+ if l > 0 {
+ n += 1 + l + sovCluster(uint64(l))
+ }
+ return n
+}
+
+func (m *FullState) Size() (n int) {
+ var l int
+ _ = l
+ if len(m.Parts) > 0 {
+ for _, e := range m.Parts {
+ l = e.Size()
+ n += 1 + l + sovCluster(uint64(l))
+ }
+ }
+ return n
+}
+
+func sovCluster(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+func sozCluster(x uint64) (n int) {
+ return sovCluster(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Part) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowCluster
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Part: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Part: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowCluster
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthCluster
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Key = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowCluster
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthCluster
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
+ if m.Data == nil {
+ m.Data = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipCluster(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthCluster
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *FullState) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowCluster
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: FullState: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: FullState: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Parts", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowCluster
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthCluster
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Parts = append(m.Parts, Part{})
+ if err := m.Parts[len(m.Parts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipCluster(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthCluster
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipCluster(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowCluster
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowCluster
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ return iNdEx, nil
+ case 1:
+ iNdEx += 8
+ return iNdEx, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowCluster
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ iNdEx += length
+ if length < 0 {
+ return 0, ErrInvalidLengthCluster
+ }
+ return iNdEx, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = iNdEx
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowCluster
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := skipCluster(dAtA[start:])
+ if err != nil {
+ return 0, err
+ }
+ iNdEx = start + next
+ }
+ return iNdEx, nil
+ case 4:
+ return iNdEx, nil
+ case 5:
+ iNdEx += 4
+ return iNdEx, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
+
+var (
+ ErrInvalidLengthCluster = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowCluster = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("cluster.proto", fileDescriptorCluster) }
+
+var fileDescriptorCluster = []byte{
+ // 168 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4d, 0xce, 0x29, 0x2d,
+ 0x2e, 0x49, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x84, 0x72, 0x0b, 0x92, 0xa4,
+ 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0xa2, 0xfa, 0x20, 0x16, 0x44, 0x81, 0x92, 0x0e, 0x17, 0x4b,
+ 0x40, 0x62, 0x51, 0x89, 0x90, 0x00, 0x17, 0x73, 0x76, 0x6a, 0xa5, 0x04, 0xa3, 0x02, 0xa3, 0x06,
+ 0x67, 0x10, 0x88, 0x29, 0x24, 0xc4, 0xc5, 0x92, 0x92, 0x58, 0x92, 0x28, 0xc1, 0xa4, 0xc0, 0xa8,
+ 0xc1, 0x13, 0x04, 0x66, 0x2b, 0x59, 0x70, 0x71, 0xba, 0x95, 0xe6, 0xe4, 0x04, 0x97, 0x24, 0x96,
+ 0xa4, 0x0a, 0x69, 0x73, 0xb1, 0x16, 0x24, 0x16, 0x95, 0x14, 0x4b, 0x30, 0x2a, 0x30, 0x6b, 0x70,
+ 0x1b, 0xf1, 0xeb, 0xc1, 0xed, 0xd2, 0x03, 0x19, 0xe9, 0xc4, 0x72, 0xe2, 0x9e, 0x3c, 0x43, 0x10,
+ 0x44, 0x8d, 0x93, 0xc0, 0x89, 0x87, 0x72, 0x0c, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7,
+ 0xf8, 0xe0, 0x91, 0x1c, 0x63, 0x12, 0x1b, 0xd8, 0x01, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0xfd, 0x3c, 0xdb, 0xe7, 0xb2, 0x00, 0x00, 0x00,
+}
--- /dev/null
+syntax = "proto3";
+
+package clusterpb;
+import "gogoproto/gogo.proto";
+
+option (gogoproto.marshaler_all) = true;
+option (gogoproto.sizer_all) = true;
+option (gogoproto.unmarshaler_all) = true;
+option (gogoproto.goproto_getters_all) = false;
+
+message Part {
+ string key = 1;
+ bytes data = 2;
+}
+
+message FullState {
+ repeated Part parts = 1 [(gogoproto.nullable) = false];
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cluster
+
+import (
+ "time"
+
+ "github.com/go-kit/kit/log"
+ "github.com/go-kit/kit/log/level"
+ "github.com/gogo/protobuf/proto"
+ "github.com/hashicorp/memberlist"
+ "github.com/prometheus/alertmanager/cluster/clusterpb"
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+// Maximum number of messages to be held in the queue.
+const maxQueueSize = 4096
+
+// delegate implements memberlist.Delegate and memberlist.EventDelegate
+// and broadcasts its peer's state in the cluster.
+type delegate struct {
+ *Peer
+
+ logger log.Logger
+ bcast *memberlist.TransmitLimitedQueue
+
+ messagesReceived *prometheus.CounterVec
+ messagesReceivedSize *prometheus.CounterVec
+ messagesSent *prometheus.CounterVec
+ messagesSentSize *prometheus.CounterVec
+ messagesPruned prometheus.Counter
+}
+
+func newDelegate(l log.Logger, reg prometheus.Registerer, p *Peer, retransmit int) *delegate {
+ bcast := &memberlist.TransmitLimitedQueue{
+ NumNodes: p.ClusterSize,
+ RetransmitMult: retransmit,
+ }
+ messagesReceived := prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "alertmanager_cluster_messages_received_total",
+ Help: "Total number of cluster messsages received.",
+ }, []string{"msg_type"})
+ messagesReceivedSize := prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "alertmanager_cluster_messages_received_size_total",
+ Help: "Total size of cluster messages received.",
+ }, []string{"msg_type"})
+ messagesSent := prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "alertmanager_cluster_messages_sent_total",
+ Help: "Total number of cluster messsages sent.",
+ }, []string{"msg_type"})
+ messagesSentSize := prometheus.NewCounterVec(prometheus.CounterOpts{
+ Name: "alertmanager_cluster_messages_sent_size_total",
+ Help: "Total size of cluster messages sent.",
+ }, []string{"msg_type"})
+ messagesPruned := prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "alertmanager_cluster_messages_pruned_total",
+ Help: "Total number of cluster messsages pruned.",
+ })
+ gossipClusterMembers := prometheus.NewGaugeFunc(prometheus.GaugeOpts{
+ Name: "alertmanager_cluster_members",
+ Help: "Number indicating current number of members in cluster.",
+ }, func() float64 {
+ return float64(p.ClusterSize())
+ })
+ peerPosition := prometheus.NewGaugeFunc(prometheus.GaugeOpts{
+ Name: "alertmanager_peer_position",
+ Help: "Position the Alertmanager instance believes it's in. The position determines a peer's behavior in the cluster.",
+ }, func() float64 {
+ return float64(p.Position())
+ })
+ healthScore := prometheus.NewGaugeFunc(prometheus.GaugeOpts{
+ Name: "alertmanager_cluster_health_score",
+ Help: "Health score of the cluster. Lower values are better and zero means 'totally healthy'.",
+ }, func() float64 {
+ return float64(p.mlist.GetHealthScore())
+ })
+ messagesQueued := prometheus.NewGaugeFunc(prometheus.GaugeOpts{
+ Name: "alertmanager_cluster_messages_queued",
+ Help: "Number of cluster messsages which are queued.",
+ }, func() float64 {
+ return float64(bcast.NumQueued())
+ })
+
+ messagesReceived.WithLabelValues("full_state")
+ messagesReceivedSize.WithLabelValues("full_state")
+ messagesReceived.WithLabelValues("update")
+ messagesReceivedSize.WithLabelValues("update")
+ messagesSent.WithLabelValues("full_state")
+ messagesSentSize.WithLabelValues("full_state")
+ messagesSent.WithLabelValues("update")
+ messagesSentSize.WithLabelValues("update")
+
+ reg.MustRegister(messagesReceived, messagesReceivedSize, messagesSent, messagesSentSize,
+ gossipClusterMembers, peerPosition, healthScore, messagesQueued, messagesPruned)
+
+ d := &delegate{
+ logger: l,
+ Peer: p,
+ bcast: bcast,
+ messagesReceived: messagesReceived,
+ messagesReceivedSize: messagesReceivedSize,
+ messagesSent: messagesSent,
+ messagesSentSize: messagesSentSize,
+ messagesPruned: messagesPruned,
+ }
+
+ go d.handleQueueDepth()
+
+ return d
+}
+
+// NodeMeta retrieves meta-data about the current node when broadcasting an alive message.
+func (d *delegate) NodeMeta(limit int) []byte {
+ return []byte{}
+}
+
+// NotifyMsg is the callback invoked when a user-level gossip message is received.
+func (d *delegate) NotifyMsg(b []byte) {
+ d.messagesReceived.WithLabelValues("update").Inc()
+ d.messagesReceivedSize.WithLabelValues("update").Add(float64(len(b)))
+
+ var p clusterpb.Part
+ if err := proto.Unmarshal(b, &p); err != nil {
+ level.Warn(d.logger).Log("msg", "decode broadcast", "err", err)
+ return
+ }
+ s, ok := d.states[p.Key]
+ if !ok {
+ return
+ }
+ if err := s.Merge(p.Data); err != nil {
+ level.Warn(d.logger).Log("msg", "merge broadcast", "err", err, "key", p.Key)
+ return
+ }
+}
+
+// GetBroadcasts is called when user data messages can be broadcasted.
+func (d *delegate) GetBroadcasts(overhead, limit int) [][]byte {
+ msgs := d.bcast.GetBroadcasts(overhead, limit)
+ d.messagesSent.WithLabelValues("update").Add(float64(len(msgs)))
+ for _, m := range msgs {
+ d.messagesSentSize.WithLabelValues("update").Add(float64(len(m)))
+ }
+ return msgs
+}
+
+// LocalState is called when gossip fetches local state.
+func (d *delegate) LocalState(_ bool) []byte {
+ all := &clusterpb.FullState{
+ Parts: make([]clusterpb.Part, 0, len(d.states)),
+ }
+ for key, s := range d.states {
+ b, err := s.MarshalBinary()
+ if err != nil {
+ level.Warn(d.logger).Log("msg", "encode local state", "err", err, "key", key)
+ return nil
+ }
+ all.Parts = append(all.Parts, clusterpb.Part{Key: key, Data: b})
+ }
+ b, err := proto.Marshal(all)
+ if err != nil {
+ level.Warn(d.logger).Log("msg", "encode local state", "err", err)
+ return nil
+ }
+ d.messagesSent.WithLabelValues("full_state").Inc()
+ d.messagesSentSize.WithLabelValues("full_state").Add(float64(len(b)))
+ return b
+}
+
+func (d *delegate) MergeRemoteState(buf []byte, _ bool) {
+ d.messagesReceived.WithLabelValues("full_state").Inc()
+ d.messagesReceivedSize.WithLabelValues("full_state").Add(float64(len(buf)))
+
+ var fs clusterpb.FullState
+ if err := proto.Unmarshal(buf, &fs); err != nil {
+ level.Warn(d.logger).Log("msg", "merge remote state", "err", err)
+ return
+ }
+ d.mtx.RLock()
+ defer d.mtx.RUnlock()
+
+ for _, p := range fs.Parts {
+ s, ok := d.states[p.Key]
+ if !ok {
+ continue
+ }
+ if err := s.Merge(p.Data); err != nil {
+ level.Warn(d.logger).Log("msg", "merge remote state", "err", err, "key", p.Key)
+ return
+ }
+ }
+}
+
+// NotifyJoin is called if a peer joins the cluster.
+func (d *delegate) NotifyJoin(n *memberlist.Node) {
+ level.Debug(d.logger).Log("received", "NotifyJoin", "node", n.Name, "addr", n.Address())
+ d.Peer.peerJoin(n)
+}
+
+// NotifyLeave is called if a peer leaves the cluster.
+func (d *delegate) NotifyLeave(n *memberlist.Node) {
+ level.Debug(d.logger).Log("received", "NotifyLeave", "node", n.Name, "addr", n.Address())
+ d.Peer.peerLeave(n)
+}
+
+// NotifyUpdate is called if a cluster peer gets updated.
+func (d *delegate) NotifyUpdate(n *memberlist.Node) {
+ level.Debug(d.logger).Log("received", "NotifyUpdate", "node", n.Name, "addr", n.Address())
+ d.Peer.peerUpdate(n)
+}
+
+// handleQueueDepth ensures that the queue doesn't grow unbounded by pruning
+// older messages at regular interval.
+func (d *delegate) handleQueueDepth() {
+ for {
+ select {
+ case <-d.stopc:
+ return
+ case <-time.After(15 * time.Minute):
+ n := d.bcast.NumQueued()
+ if n > maxQueueSize {
+ level.Warn(d.logger).Log("msg", "dropping messages because too many are queued", "current", n, "limit", maxQueueSize)
+ d.bcast.Prune(maxQueueSize)
+ d.messagesPruned.Add(float64(n - maxQueueSize))
+ }
+ }
+ }
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "context"
+ "crypto/md5"
+ "encoding/binary"
+ "fmt"
+ "net"
+ "net/http"
+ "net/url"
+ "os"
+ "os/signal"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "sync"
+ "syscall"
+ "time"
+
+ "github.com/go-kit/kit/log"
+ "github.com/go-kit/kit/log/level"
+ "github.com/prometheus/alertmanager/api"
+ "github.com/prometheus/alertmanager/cluster"
+ "github.com/prometheus/alertmanager/config"
+ "github.com/prometheus/alertmanager/dispatch"
+ "github.com/prometheus/alertmanager/inhibit"
+ "github.com/prometheus/alertmanager/nflog"
+ "github.com/prometheus/alertmanager/notify"
+ "github.com/prometheus/alertmanager/provider/mem"
+ "github.com/prometheus/alertmanager/silence"
+ "github.com/prometheus/alertmanager/template"
+ "github.com/prometheus/alertmanager/types"
+ "github.com/prometheus/alertmanager/ui"
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/client_golang/prometheus/promhttp"
+ "github.com/prometheus/common/promlog"
+ "github.com/prometheus/common/route"
+ "github.com/prometheus/common/version"
+ "github.com/prometheus/prometheus/pkg/labels"
+ "gopkg.in/alecthomas/kingpin.v2"
+)
+
+var (
+ configHash = prometheus.NewGauge(prometheus.GaugeOpts{
+ Name: "alertmanager_config_hash",
+ Help: "Hash of the currently loaded alertmanager configuration.",
+ })
+ configSuccess = prometheus.NewGauge(prometheus.GaugeOpts{
+ Name: "alertmanager_config_last_reload_successful",
+ Help: "Whether the last configuration reload attempt was successful.",
+ })
+ configSuccessTime = prometheus.NewGauge(prometheus.GaugeOpts{
+ Name: "alertmanager_config_last_reload_success_timestamp_seconds",
+ Help: "Timestamp of the last successful configuration reload.",
+ })
+ alertsActive prometheus.GaugeFunc
+ alertsSuppressed prometheus.GaugeFunc
+ requestDuration = prometheus.NewHistogramVec(
+ prometheus.HistogramOpts{
+ Name: "alertmanager_http_request_duration_seconds",
+ Help: "Histogram of latencies for HTTP requests.",
+ Buckets: []float64{.05, 0.1, .25, .5, .75, 1, 2, 5, 20, 60},
+ },
+ []string{"handler", "method"},
+ )
+ responseSize = prometheus.NewHistogramVec(
+ prometheus.HistogramOpts{
+ Name: "alertmanager_http_response_size_bytes",
+ Help: "Histogram of response size for HTTP requests.",
+ Buckets: prometheus.ExponentialBuckets(100, 10, 7),
+ },
+ []string{"handler", "method"},
+ )
+)
+
+func init() {
+ prometheus.MustRegister(configSuccess)
+ prometheus.MustRegister(configSuccessTime)
+ prometheus.MustRegister(configHash)
+ prometheus.MustRegister(requestDuration)
+ prometheus.MustRegister(responseSize)
+ prometheus.MustRegister(version.NewCollector("alertmanager"))
+}
+
+func instrumentHandler(handlerName string, handler http.HandlerFunc) http.HandlerFunc {
+ return promhttp.InstrumentHandlerDuration(
+ requestDuration.MustCurryWith(prometheus.Labels{"handler": handlerName}),
+ promhttp.InstrumentHandlerResponseSize(
+ responseSize.MustCurryWith(prometheus.Labels{"handler": handlerName}),
+ handler,
+ ),
+ )
+}
+
+func newAlertMetricByState(marker types.Marker, st types.AlertState) prometheus.GaugeFunc {
+ return prometheus.NewGaugeFunc(
+ prometheus.GaugeOpts{
+ Name: "alertmanager_alerts",
+ Help: "How many alerts by state.",
+ ConstLabels: prometheus.Labels{"state": string(st)},
+ },
+ func() float64 {
+ return float64(marker.Count(st))
+ },
+ )
+}
+
+func newMarkerMetrics(marker types.Marker) {
+ alertsActive = newAlertMetricByState(marker, types.AlertStateActive)
+ alertsSuppressed = newAlertMetricByState(marker, types.AlertStateSuppressed)
+
+ prometheus.MustRegister(alertsActive)
+ prometheus.MustRegister(alertsSuppressed)
+}
+
+const defaultClusterAddr = "0.0.0.0:9094"
+
+func main() {
+ if os.Getenv("DEBUG") != "" {
+ runtime.SetBlockProfileRate(20)
+ runtime.SetMutexProfileFraction(20)
+ }
+
+ logLevel := &promlog.AllowedLevel{}
+ if err := logLevel.Set("info"); err != nil {
+ panic(err)
+ }
+ var (
+ configFile = kingpin.Flag("config.file", "Alertmanager configuration file name.").Default("alertmanager.yml").String()
+ dataDir = kingpin.Flag("storage.path", "Base path for data storage.").Default("data/").String()
+ retention = kingpin.Flag("data.retention", "How long to keep data for.").Default("120h").Duration()
+ alertGCInterval = kingpin.Flag("alerts.gc-interval", "Interval between alert GC.").Default("30m").Duration()
+ logLevelString = kingpin.Flag("log.level", "Only log messages with the given severity or above.").Default("info").Enum("debug", "info", "warn", "error")
+
+ externalURL = kingpin.Flag("web.external-url", "The URL under which Alertmanager is externally reachable (for example, if Alertmanager is served via a reverse proxy). Used for generating relative and absolute links back to Alertmanager itself. If the URL has a path portion, it will be used to prefix all HTTP endpoints served by Alertmanager. If omitted, relevant URL components will be derived automatically.").String()
+ routePrefix = kingpin.Flag("web.route-prefix", "Prefix for the internal routes of web endpoints. Defaults to path of --web.external-url.").String()
+ listenAddress = kingpin.Flag("web.listen-address", "Address to listen on for the web interface and API.").Default(":9093").String()
+
+ clusterBindAddr = kingpin.Flag("cluster.listen-address", "Listen address for cluster.").
+ Default(defaultClusterAddr).String()
+ clusterAdvertiseAddr = kingpin.Flag("cluster.advertise-address", "Explicit address to advertise in cluster.").String()
+ peers = kingpin.Flag("cluster.peer", "Initial peers (may be repeated).").Strings()
+ peerTimeout = kingpin.Flag("cluster.peer-timeout", "Time to wait between peers to send notifications.").Default("15s").Duration()
+ gossipInterval = kingpin.Flag("cluster.gossip-interval", "Interval between sending gossip messages. By lowering this value (more frequent) gossip messages are propagated across the cluster more quickly at the expense of increased bandwidth.").Default(cluster.DefaultGossipInterval.String()).Duration()
+ pushPullInterval = kingpin.Flag("cluster.pushpull-interval", "Interval for gossip state syncs. Setting this interval lower (more frequent) will increase convergence speeds across larger clusters at the expense of increased bandwidth usage.").Default(cluster.DefaultPushPullInterval.String()).Duration()
+ tcpTimeout = kingpin.Flag("cluster.tcp-timeout", "Timeout for establishing a stream connection with a remote node for a full state sync, and for stream read and write operations.").Default(cluster.DefaultTcpTimeout.String()).Duration()
+ probeTimeout = kingpin.Flag("cluster.probe-timeout", "Timeout to wait for an ack from a probed node before assuming it is unhealthy. This should be set to 99-percentile of RTT (round-trip time) on your network.").Default(cluster.DefaultProbeTimeout.String()).Duration()
+ probeInterval = kingpin.Flag("cluster.probe-interval", "Interval between random node probes. Setting this lower (more frequent) will cause the cluster to detect failed nodes more quickly at the expense of increased bandwidth usage.").Default(cluster.DefaultProbeInterval.String()).Duration()
+ settleTimeout = kingpin.Flag("cluster.settle-timeout", "Maximum time to wait for cluster connections to settle before evaluating notifications.").Default(cluster.DefaultPushPullInterval.String()).Duration()
+ reconnectInterval = kingpin.Flag("cluster.reconnect-interval", "Interval between attempting to reconnect to lost peers.").Default(cluster.DefaultReconnectInterval.String()).Duration()
+ peerReconnectTimeout = kingpin.Flag("cluster.reconnect-timeout", "Length of time to attempt to reconnect to a lost peer.").Default(cluster.DefaultReconnectTimeout.String()).Duration()
+ )
+
+ kingpin.Version(version.Print("alertmanager"))
+ kingpin.CommandLine.GetFlag("help").Short('h')
+ kingpin.Parse()
+
+ logLevel.Set(*logLevelString)
+ logger := promlog.New(*logLevel)
+
+ level.Info(logger).Log("msg", "Starting Alertmanager", "version", version.Info())
+ level.Info(logger).Log("build_context", version.BuildContext())
+
+ err := os.MkdirAll(*dataDir, 0777)
+ if err != nil {
+ level.Error(logger).Log("msg", "Unable to create data directory", "err", err)
+ os.Exit(1)
+ }
+
+ var peer *cluster.Peer
+ if *clusterBindAddr != "" {
+ peer, err = cluster.Join(
+ log.With(logger, "component", "cluster"),
+ prometheus.DefaultRegisterer,
+ *clusterBindAddr,
+ *clusterAdvertiseAddr,
+ *peers,
+ true,
+ *pushPullInterval,
+ *gossipInterval,
+ *tcpTimeout,
+ *probeTimeout,
+ *probeInterval,
+ *reconnectInterval,
+ *peerReconnectTimeout,
+ )
+ if err != nil {
+ level.Error(logger).Log("msg", "Unable to initialize gossip mesh", "err", err)
+ os.Exit(1)
+ }
+ ctx, cancel := context.WithTimeout(context.Background(), *settleTimeout)
+ defer func() {
+ cancel()
+ peer.Leave(10 * time.Second)
+ }()
+ go peer.Settle(ctx, *gossipInterval*10)
+ }
+
+ stopc := make(chan struct{})
+ var wg sync.WaitGroup
+ wg.Add(1)
+
+ notificationLogOpts := []nflog.Option{
+ nflog.WithRetention(*retention),
+ nflog.WithSnapshot(filepath.Join(*dataDir, "nflog")),
+ nflog.WithMaintenance(15*time.Minute, stopc, wg.Done),
+ nflog.WithMetrics(prometheus.DefaultRegisterer),
+ nflog.WithLogger(log.With(logger, "component", "nflog")),
+ }
+
+ notificationLog, err := nflog.New(notificationLogOpts...)
+ if err != nil {
+ level.Error(logger).Log("err", err)
+ os.Exit(1)
+ }
+ if peer != nil {
+ c := peer.AddState("nfl", notificationLog, prometheus.DefaultRegisterer)
+ notificationLog.SetBroadcast(c.Broadcast)
+ }
+
+ marker := types.NewMarker()
+ newMarkerMetrics(marker)
+
+ silenceOpts := silence.Options{
+ SnapshotFile: filepath.Join(*dataDir, "silences"),
+ Retention: *retention,
+ Logger: log.With(logger, "component", "silences"),
+ Metrics: prometheus.DefaultRegisterer,
+ }
+
+ silences, err := silence.New(silenceOpts)
+ if err != nil {
+ level.Error(logger).Log("err", err)
+ os.Exit(1)
+ }
+ if peer != nil {
+ c := peer.AddState("sil", silences, prometheus.DefaultRegisterer)
+ silences.SetBroadcast(c.Broadcast)
+ }
+
+ // Start providers before router potentially sends updates.
+ wg.Add(1)
+ go func() {
+ silences.Maintenance(15*time.Minute, filepath.Join(*dataDir, "silences"), stopc)
+ wg.Done()
+ }()
+
+ defer func() {
+ close(stopc)
+ wg.Wait()
+ }()
+
+ alerts, err := mem.NewAlerts(marker, *alertGCInterval)
+ if err != nil {
+ level.Error(logger).Log("err", err)
+ os.Exit(1)
+ }
+ defer alerts.Close()
+
+ var (
+ inhibitor *inhibit.Inhibitor
+ tmpl *template.Template
+ pipeline notify.Stage
+ disp *dispatch.Dispatcher
+ )
+ defer disp.Stop()
+
+ apiv := api.New(
+ alerts,
+ silences,
+ func(matchers []*labels.Matcher) dispatch.AlertOverview {
+ return disp.Groups(matchers)
+ },
+ marker.Status,
+ peer,
+ logger,
+ )
+
+ amURL, err := extURL(*listenAddress, *externalURL)
+ if err != nil {
+ level.Error(logger).Log("err", err)
+ os.Exit(1)
+ }
+
+ waitFunc := func() time.Duration { return 0 }
+ if peer != nil {
+ waitFunc = clusterWait(peer, *peerTimeout)
+ }
+ timeoutFunc := func(d time.Duration) time.Duration {
+ if d < notify.MinTimeout {
+ d = notify.MinTimeout
+ }
+ return d + waitFunc()
+ }
+
+ var hash float64
+ reload := func() (err error) {
+ level.Info(logger).Log("msg", "Loading configuration file", "file", *configFile)
+ defer func() {
+ if err != nil {
+ level.Error(logger).Log("msg", "Loading configuration file failed", "file", *configFile, "err", err)
+ configSuccess.Set(0)
+ } else {
+ configSuccess.Set(1)
+ configSuccessTime.Set(float64(time.Now().Unix()))
+ configHash.Set(hash)
+ }
+ }()
+
+ conf, plainCfg, err := config.LoadFile(*configFile)
+ if err != nil {
+ return err
+ }
+
+ hash = md5HashAsMetricValue(plainCfg)
+
+ err = apiv.Update(conf, time.Duration(conf.Global.ResolveTimeout))
+ if err != nil {
+ return err
+ }
+
+ tmpl, err = template.FromGlobs(conf.Templates...)
+ if err != nil {
+ return err
+ }
+ tmpl.ExternalURL = amURL
+
+ inhibitor.Stop()
+ disp.Stop()
+
+ inhibitor = inhibit.NewInhibitor(alerts, conf.InhibitRules, marker, logger)
+ pipeline = notify.BuildPipeline(
+ conf.Receivers,
+ tmpl,
+ waitFunc,
+ inhibitor,
+ silences,
+ notificationLog,
+ marker,
+ peer,
+ logger,
+ )
+ disp = dispatch.NewDispatcher(alerts, dispatch.NewRoute(conf.Route, nil), pipeline, marker, timeoutFunc, logger)
+
+ go disp.Run()
+ go inhibitor.Run()
+
+ return nil
+ }
+
+ if err := reload(); err != nil {
+ os.Exit(1)
+ }
+
+ // Make routePrefix default to externalURL path if empty string.
+ if routePrefix == nil || *routePrefix == "" {
+ *routePrefix = amURL.Path
+ }
+
+ *routePrefix = "/" + strings.Trim(*routePrefix, "/")
+
+ router := route.New().WithInstrumentation(instrumentHandler)
+
+ if *routePrefix != "/" {
+ router = router.WithPrefix(*routePrefix)
+ }
+
+ webReload := make(chan chan error)
+
+ ui.Register(router, webReload, logger)
+
+ apiv.Register(router.WithPrefix("/api/v1"))
+
+ level.Info(logger).Log("msg", "Listening", "address", *listenAddress)
+ go listen(*listenAddress, router, logger)
+
+ var (
+ hup = make(chan os.Signal)
+ hupReady = make(chan bool)
+ term = make(chan os.Signal, 1)
+ )
+ signal.Notify(hup, syscall.SIGHUP)
+ signal.Notify(term, os.Interrupt, syscall.SIGTERM)
+
+ go func() {
+ <-hupReady
+ for {
+ select {
+ case <-hup:
+ reload()
+ case errc := <-webReload:
+ errc <- reload()
+ }
+ }
+ }()
+
+ // Wait for reload or termination signals.
+ close(hupReady) // Unblock SIGHUP handler.
+
+ <-term
+
+ level.Info(logger).Log("msg", "Received SIGTERM, exiting gracefully...")
+}
+
+// clusterWait returns a function that inspects the current peer state and returns
+// a duration of one base timeout for each peer with a higher ID than ourselves.
+func clusterWait(p *cluster.Peer, timeout time.Duration) func() time.Duration {
+ return func() time.Duration {
+ return time.Duration(p.Position()) * timeout
+ }
+}
+
+func extURL(listen, external string) (*url.URL, error) {
+ if external == "" {
+ hostname, err := os.Hostname()
+ if err != nil {
+ return nil, err
+ }
+ _, port, err := net.SplitHostPort(listen)
+ if err != nil {
+ return nil, err
+ }
+
+ external = fmt.Sprintf("http://%s:%s/", hostname, port)
+ }
+
+ u, err := url.Parse(external)
+ if err != nil {
+ return nil, err
+ }
+
+ ppref := strings.TrimRight(u.Path, "/")
+ if ppref != "" && !strings.HasPrefix(ppref, "/") {
+ ppref = "/" + ppref
+ }
+ u.Path = ppref
+
+ return u, nil
+}
+
+func listen(listen string, router *route.Router, logger log.Logger) {
+ if err := http.ListenAndServe(listen, router); err != nil {
+ level.Error(logger).Log("msg", "Listen error", "err", err)
+ os.Exit(1)
+ }
+}
+
+func md5HashAsMetricValue(data []byte) float64 {
+ sum := md5.Sum(data)
+ // We only want 48 bits as a float64 only has a 53 bit mantissa.
+ smallSum := sum[0:6]
+ var bytes = make([]byte, 8)
+ copy(bytes, smallSum)
+ return float64(binary.LittleEndian.Uint64(bytes))
+}
--- /dev/null
+# Generating amtool artifacts
+
+Amtool comes with the option to create a number of ease-of-use artifacts that can be created.
+
+## Shell completion
+
+A bash completion script can be generated by calling `amtool --completion-script-bash`.
+
+The bash completion file can be added to `/etc/bash_completion.d/`.
+
+## Man pages
+
+A man page can be generated by calling `amtool --help-man`.
+
+Man pages can be added to the man directory of your choice
+
+ amtool --help-man > /usr/local/share/man/man1/amtool.1
+ sudo mandb
+
+Then you should be able to view the man pages as expected.
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import "github.com/prometheus/alertmanager/cli"
+
+func main() {
+ cli.Execute()
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "path/filepath"
+ "regexp"
+ "strings"
+ "time"
+
+ commoncfg "github.com/prometheus/common/config"
+ "github.com/prometheus/common/model"
+ "gopkg.in/yaml.v2"
+)
+
+// Secret is a string that must not be revealed on marshaling.
+type Secret string
+
+// MarshalYAML implements the yaml.Marshaler interface.
+func (s Secret) MarshalYAML() (interface{}, error) {
+ if s != "" {
+ return "<secret>", nil
+ }
+ return nil, nil
+}
+
+//UnmarshalYAML implements the yaml.Unmarshaler interface for Secrets.
+func (s *Secret) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ type plain Secret
+ return unmarshal((*plain)(s))
+}
+
+// MarshalJSON implements the json.Marshaler interface.
+func (s Secret) MarshalJSON() ([]byte, error) {
+ return json.Marshal("<secret>")
+}
+
+// Load parses the YAML input s into a Config.
+func Load(s string) (*Config, error) {
+ cfg := &Config{}
+ err := yaml.UnmarshalStrict([]byte(s), cfg)
+ if err != nil {
+ return nil, err
+ }
+ // Check if we have a root route. We cannot check for it in the
+ // UnmarshalYAML method because it won't be called if the input is empty
+ // (e.g. the config file is empty or only contains whitespace).
+ if cfg.Route == nil {
+ return nil, errors.New("no route provided in config")
+ }
+
+ // Check if continue in root route.
+ if cfg.Route.Continue {
+ return nil, errors.New("cannot have continue in root route")
+ }
+
+ cfg.original = s
+ return cfg, nil
+}
+
+// LoadFile parses the given YAML file into a Config.
+func LoadFile(filename string) (*Config, []byte, error) {
+ content, err := ioutil.ReadFile(filename)
+ if err != nil {
+ return nil, nil, err
+ }
+ cfg, err := Load(string(content))
+ if err != nil {
+ return nil, nil, err
+ }
+
+ resolveFilepaths(filepath.Dir(filename), cfg)
+ return cfg, content, nil
+}
+
+// resolveFilepaths joins all relative paths in a configuration
+// with a given base directory.
+func resolveFilepaths(baseDir string, cfg *Config) {
+ join := func(fp string) string {
+ if len(fp) > 0 && !filepath.IsAbs(fp) {
+ fp = filepath.Join(baseDir, fp)
+ }
+ return fp
+ }
+
+ for i, tf := range cfg.Templates {
+ cfg.Templates[i] = join(tf)
+ }
+}
+
+// Config is the top-level configuration for Alertmanager's config files.
+type Config struct {
+ Global *GlobalConfig `yaml:"global,omitempty" json:"global,omitempty"`
+ Route *Route `yaml:"route,omitempty" json:"route,omitempty"`
+ InhibitRules []*InhibitRule `yaml:"inhibit_rules,omitempty" json:"inhibit_rules,omitempty"`
+ Receivers []*Receiver `yaml:"receivers,omitempty" json:"receivers,omitempty"`
+ Templates []string `yaml:"templates" json:"templates"`
+
+ // original is the input from which the config was parsed.
+ original string
+}
+
+func (c Config) String() string {
+ b, err := yaml.Marshal(c)
+ if err != nil {
+ return fmt.Sprintf("<error creating config string: %s>", err)
+ }
+ return string(b)
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ // We want to set c to the defaults and then overwrite it with the input.
+ // To make unmarshal fill the plain data struct rather than calling UnmarshalYAML
+ // again, we have to hide it using a type indirection.
+ type plain Config
+ if err := unmarshal((*plain)(c)); err != nil {
+ return err
+ }
+
+ // If a global block was open but empty the default global config is overwritten.
+ // We have to restore it here.
+ if c.Global == nil {
+ c.Global = &GlobalConfig{}
+ *c.Global = DefaultGlobalConfig
+ }
+
+ names := map[string]struct{}{}
+
+ for _, rcv := range c.Receivers {
+ if _, ok := names[rcv.Name]; ok {
+ return fmt.Errorf("notification config name %q is not unique", rcv.Name)
+ }
+ for _, wh := range rcv.WebhookConfigs {
+ if wh.HTTPConfig == nil {
+ wh.HTTPConfig = c.Global.HTTPConfig
+ }
+ }
+ for _, ec := range rcv.EmailConfigs {
+ if ec.Smarthost == "" {
+ if c.Global.SMTPSmarthost == "" {
+ return fmt.Errorf("no global SMTP smarthost set")
+ }
+ ec.Smarthost = c.Global.SMTPSmarthost
+ }
+ if ec.From == "" {
+ if c.Global.SMTPFrom == "" {
+ return fmt.Errorf("no global SMTP from set")
+ }
+ ec.From = c.Global.SMTPFrom
+ }
+ if ec.Hello == "" {
+ ec.Hello = c.Global.SMTPHello
+ }
+ if ec.AuthUsername == "" {
+ ec.AuthUsername = c.Global.SMTPAuthUsername
+ }
+ if ec.AuthPassword == "" {
+ ec.AuthPassword = c.Global.SMTPAuthPassword
+ }
+ if ec.AuthSecret == "" {
+ ec.AuthSecret = c.Global.SMTPAuthSecret
+ }
+ if ec.AuthIdentity == "" {
+ ec.AuthIdentity = c.Global.SMTPAuthIdentity
+ }
+ if ec.RequireTLS == nil {
+ ec.RequireTLS = new(bool)
+ *ec.RequireTLS = c.Global.SMTPRequireTLS
+ }
+ }
+ for _, sc := range rcv.SlackConfigs {
+ if sc.HTTPConfig == nil {
+ sc.HTTPConfig = c.Global.HTTPConfig
+ }
+ if sc.APIURL == "" {
+ if c.Global.SlackAPIURL == "" {
+ return fmt.Errorf("no global Slack API URL set")
+ }
+ sc.APIURL = c.Global.SlackAPIURL
+ }
+ }
+ for _, hc := range rcv.HipchatConfigs {
+ if hc.HTTPConfig == nil {
+ hc.HTTPConfig = c.Global.HTTPConfig
+ }
+ if hc.APIURL == "" {
+ if c.Global.HipchatAPIURL == "" {
+ return fmt.Errorf("no global Hipchat API URL set")
+ }
+ hc.APIURL = c.Global.HipchatAPIURL
+ }
+ if !strings.HasSuffix(hc.APIURL, "/") {
+ hc.APIURL += "/"
+ }
+ if hc.AuthToken == "" {
+ if c.Global.HipchatAuthToken == "" {
+ return fmt.Errorf("no global Hipchat Auth Token set")
+ }
+ hc.AuthToken = c.Global.HipchatAuthToken
+ }
+ }
+ for _, poc := range rcv.PushoverConfigs {
+ if poc.HTTPConfig == nil {
+ poc.HTTPConfig = c.Global.HTTPConfig
+ }
+ }
+ for _, pdc := range rcv.PagerdutyConfigs {
+ if pdc.HTTPConfig == nil {
+ pdc.HTTPConfig = c.Global.HTTPConfig
+ }
+ if pdc.URL == "" {
+ if c.Global.PagerdutyURL == "" {
+ return fmt.Errorf("no global PagerDuty URL set")
+ }
+ pdc.URL = c.Global.PagerdutyURL
+ }
+ }
+ for _, ogc := range rcv.OpsGenieConfigs {
+ if ogc.HTTPConfig == nil {
+ ogc.HTTPConfig = c.Global.HTTPConfig
+ }
+ if ogc.APIURL == "" {
+ if c.Global.OpsGenieAPIURL == "" {
+ return fmt.Errorf("no global OpsGenie URL set")
+ }
+ ogc.APIURL = c.Global.OpsGenieAPIURL
+ }
+ if !strings.HasSuffix(ogc.APIURL, "/") {
+ ogc.APIURL += "/"
+ }
+ if ogc.APIKey == "" {
+ if c.Global.OpsGenieAPIKey == "" {
+ return fmt.Errorf("no global OpsGenie API Key set")
+ }
+ ogc.APIKey = c.Global.OpsGenieAPIKey
+ }
+ }
+ for _, wcc := range rcv.WechatConfigs {
+ if wcc.HTTPConfig == nil {
+ wcc.HTTPConfig = c.Global.HTTPConfig
+ }
+
+ if wcc.APIURL == "" {
+ if c.Global.WeChatAPIURL == "" {
+ return fmt.Errorf("no global Wechat URL set")
+ }
+ wcc.APIURL = c.Global.WeChatAPIURL
+ }
+
+ if wcc.APISecret == "" {
+ if c.Global.WeChatAPISecret == "" {
+ return fmt.Errorf("no global Wechat ApiSecret set")
+ }
+ wcc.APISecret = c.Global.WeChatAPISecret
+ }
+
+ if wcc.CorpID == "" {
+ if c.Global.WeChatAPICorpID == "" {
+ return fmt.Errorf("no global Wechat CorpID set")
+ }
+ wcc.CorpID = c.Global.WeChatAPICorpID
+ }
+
+ if !strings.HasSuffix(wcc.APIURL, "/") {
+ wcc.APIURL += "/"
+ }
+ }
+ for _, voc := range rcv.VictorOpsConfigs {
+ if voc.HTTPConfig == nil {
+ voc.HTTPConfig = c.Global.HTTPConfig
+ }
+ if voc.APIURL == "" {
+ if c.Global.VictorOpsAPIURL == "" {
+ return fmt.Errorf("no global VictorOps URL set")
+ }
+ voc.APIURL = c.Global.VictorOpsAPIURL
+ }
+ if !strings.HasSuffix(voc.APIURL, "/") {
+ voc.APIURL += "/"
+ }
+ if voc.APIKey == "" {
+ if c.Global.VictorOpsAPIKey == "" {
+ return fmt.Errorf("no global VictorOps API Key set")
+ }
+ voc.APIKey = c.Global.VictorOpsAPIKey
+ }
+ }
+ names[rcv.Name] = struct{}{}
+ }
+
+ // The root route must not have any matchers as it is the fallback node
+ // for all alerts.
+ if c.Route == nil {
+ return fmt.Errorf("no routes provided")
+ }
+ if len(c.Route.Receiver) == 0 {
+ return fmt.Errorf("root route must specify a default receiver")
+ }
+ if len(c.Route.Match) > 0 || len(c.Route.MatchRE) > 0 {
+ return fmt.Errorf("root route must not have any matchers")
+ }
+
+ // Validate that all receivers used in the routing tree are defined.
+ return checkReceiver(c.Route, names)
+}
+
+// checkReceiver returns an error if a node in the routing tree
+// references a receiver not in the given map.
+func checkReceiver(r *Route, receivers map[string]struct{}) error {
+ if r.Receiver == "" {
+ return nil
+ }
+ if _, ok := receivers[r.Receiver]; !ok {
+ return fmt.Errorf("undefined receiver %q used in route", r.Receiver)
+ }
+ for _, sr := range r.Routes {
+ if err := checkReceiver(sr, receivers); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// DefaultGlobalConfig provides global default values.
+var DefaultGlobalConfig = GlobalConfig{
+ ResolveTimeout: model.Duration(5 * time.Minute),
+ HTTPConfig: &commoncfg.HTTPClientConfig{},
+
+ SMTPHello: "localhost",
+ SMTPRequireTLS: true,
+ PagerdutyURL: "https://events.pagerduty.com/v2/enqueue",
+ HipchatAPIURL: "https://api.hipchat.com/",
+ OpsGenieAPIURL: "https://api.opsgenie.com/",
+ WeChatAPIURL: "https://qyapi.weixin.qq.com/cgi-bin/",
+ VictorOpsAPIURL: "https://alert.victorops.com/integrations/generic/20131114/alert/",
+}
+
+// GlobalConfig defines configuration parameters that are valid globally
+// unless overwritten.
+type GlobalConfig struct {
+ // ResolveTimeout is the time after which an alert is declared resolved
+ // if it has not been updated.
+ ResolveTimeout model.Duration `yaml:"resolve_timeout" json:"resolve_timeout"`
+
+ HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
+
+ SMTPFrom string `yaml:"smtp_from,omitempty" json:"smtp_from,omitempty"`
+ SMTPHello string `yaml:"smtp_hello,omitempty" json:"smtp_hello,omitempty"`
+ SMTPSmarthost string `yaml:"smtp_smarthost,omitempty" json:"smtp_smarthost,omitempty"`
+ SMTPAuthUsername string `yaml:"smtp_auth_username,omitempty" json:"smtp_auth_username,omitempty"`
+ SMTPAuthPassword Secret `yaml:"smtp_auth_password,omitempty" json:"smtp_auth_password,omitempty"`
+ SMTPAuthSecret Secret `yaml:"smtp_auth_secret,omitempty" json:"smtp_auth_secret,omitempty"`
+ SMTPAuthIdentity string `yaml:"smtp_auth_identity,omitempty" json:"smtp_auth_identity,omitempty"`
+ SMTPRequireTLS bool `yaml:"smtp_require_tls,omitempty" json:"smtp_require_tls,omitempty"`
+ SlackAPIURL Secret `yaml:"slack_api_url,omitempty" json:"slack_api_url,omitempty"`
+ PagerdutyURL string `yaml:"pagerduty_url,omitempty" json:"pagerduty_url,omitempty"`
+ HipchatAPIURL string `yaml:"hipchat_api_url,omitempty" json:"hipchat_api_url,omitempty"`
+ HipchatAuthToken Secret `yaml:"hipchat_auth_token,omitempty" json:"hipchat_auth_token,omitempty"`
+ OpsGenieAPIURL string `yaml:"opsgenie_api_url,omitempty" json:"opsgenie_api_url,omitempty"`
+ OpsGenieAPIKey Secret `yaml:"opsgenie_api_key,omitempty" json:"opsgenie_api_key,omitempty"`
+ WeChatAPIURL string `yaml:"wechat_api_url,omitempty" json:"wechat_api_url,omitempty"`
+ WeChatAPISecret Secret `yaml:"wechat_api_secret,omitempty" json:"wechat_api_secret,omitempty"`
+ WeChatAPICorpID string `yaml:"wechat_api_corp_id,omitempty" json:"wechat_api_corp_id,omitempty"`
+ VictorOpsAPIURL string `yaml:"victorops_api_url,omitempty" json:"victorops_api_url,omitempty"`
+ VictorOpsAPIKey Secret `yaml:"victorops_api_key,omitempty" json:"victorops_api_key,omitempty"`
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (c *GlobalConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ *c = DefaultGlobalConfig
+ type plain GlobalConfig
+ return unmarshal((*plain)(c))
+}
+
+// A Route is a node that contains definitions of how to handle alerts.
+type Route struct {
+ Receiver string `yaml:"receiver,omitempty" json:"receiver,omitempty"`
+ GroupBy []model.LabelName `yaml:"group_by,omitempty" json:"group_by,omitempty"`
+
+ Match map[string]string `yaml:"match,omitempty" json:"match,omitempty"`
+ MatchRE map[string]Regexp `yaml:"match_re,omitempty" json:"match_re,omitempty"`
+ Continue bool `yaml:"continue,omitempty" json:"continue,omitempty"`
+ Routes []*Route `yaml:"routes,omitempty" json:"routes,omitempty"`
+
+ GroupWait *model.Duration `yaml:"group_wait,omitempty" json:"group_wait,omitempty"`
+ GroupInterval *model.Duration `yaml:"group_interval,omitempty" json:"group_interval,omitempty"`
+ RepeatInterval *model.Duration `yaml:"repeat_interval,omitempty" json:"repeat_interval,omitempty"`
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (r *Route) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ type plain Route
+ if err := unmarshal((*plain)(r)); err != nil {
+ return err
+ }
+
+ for k := range r.Match {
+ if !model.LabelNameRE.MatchString(k) {
+ return fmt.Errorf("invalid label name %q", k)
+ }
+ }
+
+ for k := range r.MatchRE {
+ if !model.LabelNameRE.MatchString(k) {
+ return fmt.Errorf("invalid label name %q", k)
+ }
+ }
+
+ groupBy := map[model.LabelName]struct{}{}
+
+ for _, ln := range r.GroupBy {
+ if _, ok := groupBy[ln]; ok {
+ return fmt.Errorf("duplicated label %q in group_by", ln)
+ }
+ groupBy[ln] = struct{}{}
+ }
+
+ if r.GroupInterval != nil && time.Duration(*r.GroupInterval) == time.Duration(0) {
+ return fmt.Errorf("group_interval cannot be zero")
+ }
+ if r.RepeatInterval != nil && time.Duration(*r.RepeatInterval) == time.Duration(0) {
+ return fmt.Errorf("repeat_interval cannot be zero")
+ }
+
+ return nil
+}
+
+// InhibitRule defines an inhibition rule that mutes alerts that match the
+// target labels if an alert matching the source labels exists.
+// Both alerts have to have a set of labels being equal.
+type InhibitRule struct {
+ // SourceMatch defines a set of labels that have to equal the given
+ // value for source alerts.
+ SourceMatch map[string]string `yaml:"source_match,omitempty" json:"source_match,omitempty"`
+ // SourceMatchRE defines pairs like SourceMatch but does regular expression
+ // matching.
+ SourceMatchRE map[string]Regexp `yaml:"source_match_re,omitempty" json:"source_match_re,omitempty"`
+ // TargetMatch defines a set of labels that have to equal the given
+ // value for target alerts.
+ TargetMatch map[string]string `yaml:"target_match,omitempty" json:"target_match,omitempty"`
+ // TargetMatchRE defines pairs like TargetMatch but does regular expression
+ // matching.
+ TargetMatchRE map[string]Regexp `yaml:"target_match_re,omitempty" json:"target_match_re,omitempty"`
+ // A set of labels that must be equal between the source and target alert
+ // for them to be a match.
+ Equal model.LabelNames `yaml:"equal,omitempty" json:"equal,omitempty"`
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (r *InhibitRule) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ type plain InhibitRule
+ if err := unmarshal((*plain)(r)); err != nil {
+ return err
+ }
+
+ for k := range r.SourceMatch {
+ if !model.LabelNameRE.MatchString(k) {
+ return fmt.Errorf("invalid label name %q", k)
+ }
+ }
+
+ for k := range r.SourceMatchRE {
+ if !model.LabelNameRE.MatchString(k) {
+ return fmt.Errorf("invalid label name %q", k)
+ }
+ }
+
+ for k := range r.TargetMatch {
+ if !model.LabelNameRE.MatchString(k) {
+ return fmt.Errorf("invalid label name %q", k)
+ }
+ }
+
+ for k := range r.TargetMatchRE {
+ if !model.LabelNameRE.MatchString(k) {
+ return fmt.Errorf("invalid label name %q", k)
+ }
+ }
+
+ return nil
+}
+
+// Receiver configuration provides configuration on how to contact a receiver.
+type Receiver struct {
+ // A unique identifier for this receiver.
+ Name string `yaml:"name" json:"name"`
+
+ EmailConfigs []*EmailConfig `yaml:"email_configs,omitempty" json:"email_configs,omitempty"`
+ PagerdutyConfigs []*PagerdutyConfig `yaml:"pagerduty_configs,omitempty" json:"pagerduty_configs,omitempty"`
+ HipchatConfigs []*HipchatConfig `yaml:"hipchat_configs,omitempty" json:"hipchat_configs,omitempty"`
+ SlackConfigs []*SlackConfig `yaml:"slack_configs,omitempty" json:"slack_configs,omitempty"`
+ WebhookConfigs []*WebhookConfig `yaml:"webhook_configs,omitempty" json:"webhook_configs,omitempty"`
+ OpsGenieConfigs []*OpsGenieConfig `yaml:"opsgenie_configs,omitempty" json:"opsgenie_configs,omitempty"`
+ WechatConfigs []*WechatConfig `yaml:"wechat_configs,omitempty" json:"wechat_configs,omitempty"`
+ PushoverConfigs []*PushoverConfig `yaml:"pushover_configs,omitempty" json:"pushover_configs,omitempty"`
+ VictorOpsConfigs []*VictorOpsConfig `yaml:"victorops_configs,omitempty" json:"victorops_configs,omitempty"`
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (c *Receiver) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ type plain Receiver
+ if err := unmarshal((*plain)(c)); err != nil {
+ return err
+ }
+ if c.Name == "" {
+ return fmt.Errorf("missing name in receiver")
+ }
+ return nil
+}
+
+// Regexp encapsulates a regexp.Regexp and makes it YAML marshalable.
+type Regexp struct {
+ *regexp.Regexp
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (re *Regexp) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ var s string
+ if err := unmarshal(&s); err != nil {
+ return err
+ }
+ regex, err := regexp.Compile("^(?:" + s + ")$")
+ if err != nil {
+ return err
+ }
+ re.Regexp = regex
+ return nil
+}
+
+// MarshalYAML implements the yaml.Marshaler interface.
+func (re Regexp) MarshalYAML() (interface{}, error) {
+ if re.Regexp != nil {
+ return re.String(), nil
+ }
+ return nil, nil
+}
+
+// UnmarshalJSON implements the json.Marshaler interface
+func (re *Regexp) UnmarshalJSON(data []byte) error {
+ var s string
+ if err := json.Unmarshal(data, &s); err != nil {
+ return err
+ }
+ regex, err := regexp.Compile("^(?:" + s + ")$")
+ if err != nil {
+ return err
+ }
+ re.Regexp = regex
+ return nil
+}
+
+// MarshalJSON implements the json.Marshaler interface.
+func (re Regexp) MarshalJSON() ([]byte, error) {
+ if re.Regexp != nil {
+ return json.Marshal(re.String())
+ }
+ return nil, nil
+}
--- /dev/null
+// Copyright 2016 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+ "encoding/json"
+ "reflect"
+ "regexp"
+ "strings"
+ "testing"
+ "time"
+
+ commoncfg "github.com/prometheus/common/config"
+ "github.com/prometheus/common/model"
+ "github.com/stretchr/testify/require"
+ "gopkg.in/yaml.v2"
+)
+
+func TestLoadEmptyString(t *testing.T) {
+
+ var in string
+ _, err := Load(in)
+
+ expected := "no route provided in config"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%v", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error())
+ }
+}
+
+func TestDefaultReceiverExists(t *testing.T) {
+ in := `
+route:
+ group_wait: 30s
+`
+ _, err := Load(in)
+
+ expected := "root route must specify a default receiver"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%v", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error())
+ }
+}
+
+func TestReceiverNameIsUnique(t *testing.T) {
+ in := `
+route:
+ receiver: team-X
+
+receivers:
+- name: 'team-X'
+- name: 'team-X'
+`
+ _, err := Load(in)
+
+ expected := "notification config name \"team-X\" is not unique"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%q", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%q\ngot:\n%q", expected, err.Error())
+ }
+
+}
+
+func TestReceiverExists(t *testing.T) {
+ in := `
+route:
+ receiver: team-X
+
+receivers:
+- name: 'team-Y'
+`
+ _, err := Load(in)
+
+ expected := "undefined receiver \"team-X\" used in route"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%q", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%q\ngot:\n%q", expected, err.Error())
+ }
+
+}
+
+func TestReceiverHasName(t *testing.T) {
+ in := `
+route:
+
+receivers:
+- name: ''
+`
+ _, err := Load(in)
+
+ expected := "missing name in receiver"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%q", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%q\ngot:\n%q", expected, err.Error())
+ }
+
+}
+
+func TestGroupByHasNoDuplicatedLabels(t *testing.T) {
+ in := `
+route:
+ group_by: ['alertname', 'cluster', 'service', 'cluster']
+
+receivers:
+- name: 'team-X-mails'
+`
+ _, err := Load(in)
+
+ expected := "duplicated label \"cluster\" in group_by"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%q", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%q\ngot:\n%q", expected, err.Error())
+ }
+
+}
+
+func TestRootRouteExists(t *testing.T) {
+ in := `
+receivers:
+- name: 'team-X-mails'
+`
+ _, err := Load(in)
+
+ expected := "no routes provided"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%q", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%q\ngot:\n%q", expected, err.Error())
+ }
+
+}
+
+func TestRootRouteHasNoMatcher(t *testing.T) {
+ in := `
+route:
+ receiver: 'team-X'
+ match:
+ severity: critical
+
+receivers:
+- name: 'team-X'
+`
+ _, err := Load(in)
+
+ expected := "root route must not have any matchers"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%q", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%q\ngot:\n%q", expected, err.Error())
+ }
+
+}
+
+func TestContinueErrorInRouteRoot(t *testing.T) {
+ in := `
+route:
+ receiver: team-X-mails
+ continue: true
+
+receivers:
+- name: 'team-X-mails'
+`
+ _, err := Load(in)
+
+ expected := "cannot have continue in root route"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%q", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%q\ngot:\n%q", expected, err.Error())
+ }
+
+}
+
+func TestGroupIntervalIsGreaterThanZero(t *testing.T) {
+ in := `
+route:
+ receiver: team-X-mails
+ group_interval: 0s
+
+receivers:
+- name: 'team-X-mails'
+`
+ _, err := Load(in)
+
+ expected := "group_interval cannot be zero"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%q", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%q\ngot:\n%q", expected, err.Error())
+ }
+}
+
+func TestRepeatIntervalIsGreaterThanZero(t *testing.T) {
+ in := `
+route:
+ receiver: team-X-mails
+ repeat_interval: 0s
+
+receivers:
+- name: 'team-X-mails'
+`
+ _, err := Load(in)
+
+ expected := "repeat_interval cannot be zero"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%q", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%q\ngot:\n%q", expected, err.Error())
+ }
+}
+
+func TestHideConfigSecrets(t *testing.T) {
+ c, _, err := LoadFile("testdata/conf.good.yml")
+ if err != nil {
+ t.Errorf("Error parsing %s: %s", "testdata/conf.good.yml", err)
+ }
+
+ // String method must not reveal authentication credentials.
+ s := c.String()
+ secretRe := regexp.MustCompile("<secret>")
+ matches := secretRe.FindAllStringIndex(s, -1)
+ if len(matches) != 14 || strings.Contains(s, "mysecret") {
+ t.Fatal("config's String method reveals authentication credentials.")
+ }
+}
+
+func TestJSONMarshal(t *testing.T) {
+ c, _, err := LoadFile("testdata/conf.good.yml")
+ if err != nil {
+ t.Errorf("Error parsing %s: %s", "testdata/conf.good.yml", err)
+ }
+
+ _, err = json.Marshal(c)
+ if err != nil {
+ t.Fatal("JSON Marshaling failed:", err)
+ }
+}
+
+func TestJSONMarshalSecret(t *testing.T) {
+ test := struct {
+ S Secret
+ }{
+ S: Secret("test"),
+ }
+
+ c, err := json.Marshal(test)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // u003c -> "<"
+ // u003e -> ">"
+ require.Equal(t, "{\"S\":\"\\u003csecret\\u003e\"}", string(c), "Secret not properly elided.")
+}
+
+func TestJSONUnmarshalMarshaled(t *testing.T) {
+ c, _, err := LoadFile("testdata/conf.good.yml")
+ if err != nil {
+ t.Errorf("Error parsing %s: %s", "testdata/conf.good.yml", err)
+ }
+
+ plainCfg, err := json.Marshal(c)
+ if err != nil {
+ t.Fatal("JSON Marshaling failed:", err)
+ }
+
+ cfg := Config{}
+ err = json.Unmarshal(plainCfg, &cfg)
+ if err != nil {
+ t.Fatal("JSON Unmarshaling failed:", err)
+ }
+}
+
+func TestEmptyFieldsAndRegex(t *testing.T) {
+ boolFoo := true
+ var regexpFoo Regexp
+ regexpFoo.Regexp, _ = regexp.Compile("^(?:^(foo1|foo2|baz)$)$")
+
+ var expectedConf = Config{
+
+ Global: &GlobalConfig{
+ HTTPConfig: &commoncfg.HTTPClientConfig{},
+ ResolveTimeout: model.Duration(5 * time.Minute),
+ SMTPSmarthost: "localhost:25",
+ SMTPFrom: "alertmanager@example.org",
+ HipchatAuthToken: "mysecret",
+ HipchatAPIURL: "https://hipchat.foobar.org/",
+ SlackAPIURL: "mysecret",
+ SMTPRequireTLS: true,
+ PagerdutyURL: "https://events.pagerduty.com/v2/enqueue",
+ OpsGenieAPIURL: "https://api.opsgenie.com/",
+ WeChatAPIURL: "https://qyapi.weixin.qq.com/cgi-bin/",
+ VictorOpsAPIURL: "https://alert.victorops.com/integrations/generic/20131114/alert/",
+ },
+
+ Templates: []string{
+ "/etc/alertmanager/template/*.tmpl",
+ },
+ Route: &Route{
+ Receiver: "team-X-mails",
+ GroupBy: []model.LabelName{
+ "alertname",
+ "cluster",
+ "service",
+ },
+ Routes: []*Route{
+ {
+ Receiver: "team-X-mails",
+ MatchRE: map[string]Regexp{
+ "service": regexpFoo,
+ },
+ },
+ },
+ },
+ Receivers: []*Receiver{
+ {
+ Name: "team-X-mails",
+ EmailConfigs: []*EmailConfig{
+ {
+ To: "team-X+alerts@example.org",
+ From: "alertmanager@example.org",
+ Smarthost: "localhost:25",
+ HTML: "{{ template \"email.default.html\" . }}",
+ RequireTLS: &boolFoo,
+ },
+ },
+ },
+ },
+ }
+
+ config, _, err := LoadFile("testdata/conf.empty-fields.yml")
+ if err != nil {
+ t.Errorf("Error parsing %s: %s", "testdata/conf.empty-fields.yml", err)
+ }
+
+ configGot, err := yaml.Marshal(config)
+ if err != nil {
+ t.Fatal("YAML Marshaling failed:", err)
+ }
+
+ configExp, err := yaml.Marshal(expectedConf)
+ if err != nil {
+ t.Fatalf("%s", err)
+ }
+
+ if !reflect.DeepEqual(configGot, configExp) {
+ t.Fatalf("%s: unexpected config result: \n\n%s\n expected\n\n%s", "testdata/conf.empty-fields.yml", configGot, configExp)
+ }
+}
+
+func TestSMTPHello(t *testing.T) {
+ c, _, err := LoadFile("testdata/conf.good.yml")
+ if err != nil {
+ t.Errorf("Error parsing %s: %s", "testdata/conf.good.yml", err)
+ }
+
+ const refValue = "host.example.org"
+ var hostName = c.Global.SMTPHello
+ if hostName != refValue {
+ t.Errorf("Invalid SMTP Hello hostname: %s\nExpected: %s", hostName, refValue)
+ }
+}
+
+func TestVictorOpsDefaultAPIKey(t *testing.T) {
+ conf, _, err := LoadFile("testdata/conf.victorops-default-apikey.yml")
+ if err != nil {
+ t.Errorf("Error parsing %s: %s", "testdata/conf.victorops-default-apikey.yml", err)
+ }
+
+ var defaultKey = conf.Global.VictorOpsAPIKey
+ if defaultKey != conf.Receivers[0].VictorOpsConfigs[0].APIKey {
+ t.Errorf("Invalid victorops key: %s\nExpected: %s", conf.Receivers[0].VictorOpsConfigs[0].APIKey, defaultKey)
+ }
+ if defaultKey == conf.Receivers[1].VictorOpsConfigs[0].APIKey {
+ t.Errorf("Invalid victorops key: %s\nExpected: %s", conf.Receivers[0].VictorOpsConfigs[0].APIKey, "qwe456")
+ }
+}
+
+func TestVictorOpsNoAPIKey(t *testing.T) {
+ _, _, err := LoadFile("testdata/conf.victorops-no-apikey.yml")
+ if err == nil {
+ t.Errorf("Expected an error parsing %s: %s", "testdata/conf.victorops-no-apikey.yml", err)
+ }
+ if err.Error() != "no global VictorOps API Key set" {
+ t.Errorf("Expected: %s\nGot: %s", "no global VictorOps API Key set", err.Error())
+ }
+}
+
+func TestOpsGenieDefaultAPIKey(t *testing.T) {
+ conf, _, err := LoadFile("testdata/conf.opsgenie-default-apikey.yml")
+ if err != nil {
+ t.Errorf("Error parsing %s: %s", "testdata/conf.opsgenie-default-apikey.yml", err)
+ }
+
+ var defaultKey = conf.Global.OpsGenieAPIKey
+ if defaultKey != conf.Receivers[0].OpsGenieConfigs[0].APIKey {
+ t.Errorf("Invalid OpsGenie key: %s\nExpected: %s", conf.Receivers[0].OpsGenieConfigs[0].APIKey, defaultKey)
+ }
+ if defaultKey == conf.Receivers[1].OpsGenieConfigs[0].APIKey {
+ t.Errorf("Invalid OpsGenie key: %s\nExpected: %s", conf.Receivers[0].OpsGenieConfigs[0].APIKey, "qwe456")
+ }
+}
+
+func TestOpsGenieNoAPIKey(t *testing.T) {
+ _, _, err := LoadFile("testdata/conf.opsgenie-no-apikey.yml")
+ if err == nil {
+ t.Errorf("Expected an error parsing %s: %s", "testdata/conf.opsgenie-no-apikey.yml", err)
+ }
+ if err.Error() != "no global OpsGenie API Key set" {
+ t.Errorf("Expected: %s\nGot: %s", "no global OpsGenie API Key set", err.Error())
+ }
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+ "fmt"
+ "net/url"
+ "strings"
+ "time"
+
+ commoncfg "github.com/prometheus/common/config"
+)
+
+var (
+ // DefaultWebhookConfig defines default values for Webhook configurations.
+ DefaultWebhookConfig = WebhookConfig{
+ NotifierConfig: NotifierConfig{
+ VSendResolved: true,
+ },
+ }
+
+ // DefaultEmailConfig defines default values for Email configurations.
+ DefaultEmailConfig = EmailConfig{
+ NotifierConfig: NotifierConfig{
+ VSendResolved: false,
+ },
+ HTML: `{{ template "email.default.html" . }}`,
+ Text: ``,
+ }
+
+ // DefaultEmailSubject defines the default Subject header of an Email.
+ DefaultEmailSubject = `{{ template "email.default.subject" . }}`
+
+ // DefaultPagerdutyConfig defines default values for PagerDuty configurations.
+ DefaultPagerdutyConfig = PagerdutyConfig{
+ NotifierConfig: NotifierConfig{
+ VSendResolved: true,
+ },
+ Description: `{{ template "pagerduty.default.description" .}}`,
+ Client: `{{ template "pagerduty.default.client" . }}`,
+ ClientURL: `{{ template "pagerduty.default.clientURL" . }}`,
+ Details: map[string]string{
+ "firing": `{{ template "pagerduty.default.instances" .Alerts.Firing }}`,
+ "resolved": `{{ template "pagerduty.default.instances" .Alerts.Resolved }}`,
+ "num_firing": `{{ .Alerts.Firing | len }}`,
+ "num_resolved": `{{ .Alerts.Resolved | len }}`,
+ },
+ }
+
+ // DefaultSlackConfig defines default values for Slack configurations.
+ DefaultSlackConfig = SlackConfig{
+ NotifierConfig: NotifierConfig{
+ VSendResolved: false,
+ },
+ Color: `{{ if eq .Status "firing" }}danger{{ else }}good{{ end }}`,
+ Username: `{{ template "slack.default.username" . }}`,
+ Title: `{{ template "slack.default.title" . }}`,
+ TitleLink: `{{ template "slack.default.titlelink" . }}`,
+ IconEmoji: `{{ template "slack.default.iconemoji" . }}`,
+ IconURL: `{{ template "slack.default.iconurl" . }}`,
+ Pretext: `{{ template "slack.default.pretext" . }}`,
+ Text: `{{ template "slack.default.text" . }}`,
+ Fallback: `{{ template "slack.default.fallback" . }}`,
+ Footer: `{{ template "slack.default.footer" . }}`,
+ }
+
+ // DefaultHipchatConfig defines default values for Hipchat configurations.
+ DefaultHipchatConfig = HipchatConfig{
+ NotifierConfig: NotifierConfig{
+ VSendResolved: false,
+ },
+ Color: `{{ if eq .Status "firing" }}red{{ else }}green{{ end }}`,
+ From: `{{ template "hipchat.default.from" . }}`,
+ Notify: false,
+ Message: `{{ template "hipchat.default.message" . }}`,
+ MessageFormat: `text`,
+ }
+
+ // DefaultOpsGenieConfig defines default values for OpsGenie configurations.
+ DefaultOpsGenieConfig = OpsGenieConfig{
+ NotifierConfig: NotifierConfig{
+ VSendResolved: true,
+ },
+ Message: `{{ template "opsgenie.default.message" . }}`,
+ Description: `{{ template "opsgenie.default.description" . }}`,
+ Source: `{{ template "opsgenie.default.source" . }}`,
+ // TODO: Add a details field with all the alerts.
+ }
+
+ // DefaultWechatConfig defines default values for wechat configurations.
+ DefaultWechatConfig = WechatConfig{
+ NotifierConfig: NotifierConfig{
+ VSendResolved: false,
+ },
+ Message: `{{ template "wechat.default.message" . }}`,
+ APISecret: `{{ template "wechat.default.api_secret" . }}`,
+ ToUser: `{{ template "wechat.default.to_user" . }}`,
+ ToParty: `{{ template "wechat.default.to_party" . }}`,
+ ToTag: `{{ template "wechat.default.to_tag" . }}`,
+ AgentID: `{{ template "wechat.default.agent_id" . }}`,
+ }
+
+ // DefaultVictorOpsConfig defines default values for VictorOps configurations.
+ DefaultVictorOpsConfig = VictorOpsConfig{
+ NotifierConfig: NotifierConfig{
+ VSendResolved: true,
+ },
+ MessageType: `CRITICAL`,
+ StateMessage: `{{ template "victorops.default.state_message" . }}`,
+ EntityDisplayName: `{{ template "victorops.default.entity_display_name" . }}`,
+ MonitoringTool: `{{ template "victorops.default.monitoring_tool" . }}`,
+ }
+
+ // DefaultPushoverConfig defines default values for Pushover configurations.
+ DefaultPushoverConfig = PushoverConfig{
+ NotifierConfig: NotifierConfig{
+ VSendResolved: true,
+ },
+ Title: `{{ template "pushover.default.title" . }}`,
+ Message: `{{ template "pushover.default.message" . }}`,
+ URL: `{{ template "pushover.default.url" . }}`,
+ Priority: `{{ if eq .Status "firing" }}2{{ else }}0{{ end }}`, // emergency (firing) or normal
+ Retry: duration(1 * time.Minute),
+ Expire: duration(1 * time.Hour),
+ }
+)
+
+// NotifierConfig contains base options common across all notifier configurations.
+type NotifierConfig struct {
+ VSendResolved bool `yaml:"send_resolved" json:"send_resolved"`
+}
+
+func (nc *NotifierConfig) SendResolved() bool {
+ return nc.VSendResolved
+}
+
+// EmailConfig configures notifications via mail.
+type EmailConfig struct {
+ NotifierConfig `yaml:",inline" json:",inline"`
+
+ // Email address to notify.
+ To string `yaml:"to,omitempty" json:"to,omitempty"`
+ From string `yaml:"from,omitempty" json:"from,omitempty"`
+ Hello string `yaml:"hello,omitempty" json:"hello,omitempty"`
+ Smarthost string `yaml:"smarthost,omitempty" json:"smarthost,omitempty"`
+ AuthUsername string `yaml:"auth_username,omitempty" json:"auth_username,omitempty"`
+ AuthPassword Secret `yaml:"auth_password,omitempty" json:"auth_password,omitempty"`
+ AuthSecret Secret `yaml:"auth_secret,omitempty" json:"auth_secret,omitempty"`
+ AuthIdentity string `yaml:"auth_identity,omitempty" json:"auth_identity,omitempty"`
+ Headers map[string]string `yaml:"headers,omitempty" json:"headers,omitempty"`
+ HTML string `yaml:"html,omitempty" json:"html,omitempty"`
+ Text string `yaml:"text,omitempty" json:"text,omitempty"`
+ RequireTLS *bool `yaml:"require_tls,omitempty" json:"require_tls,omitempty"`
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (c *EmailConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ *c = DefaultEmailConfig
+ type plain EmailConfig
+ if err := unmarshal((*plain)(c)); err != nil {
+ return err
+ }
+ if c.To == "" {
+ return fmt.Errorf("missing to address in email config")
+ }
+ // Header names are case-insensitive, check for collisions.
+ normalizedHeaders := map[string]string{}
+ for h, v := range c.Headers {
+ normalized := strings.Title(h)
+ if _, ok := normalizedHeaders[normalized]; ok {
+ return fmt.Errorf("duplicate header %q in email config", normalized)
+ }
+ normalizedHeaders[normalized] = v
+ }
+ c.Headers = normalizedHeaders
+
+ return nil
+}
+
+// PagerdutyConfig configures notifications via PagerDuty.
+type PagerdutyConfig struct {
+ NotifierConfig `yaml:",inline" json:",inline"`
+
+ HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
+
+ ServiceKey Secret `yaml:"service_key,omitempty" json"service_key,omitempty"`
+ RoutingKey Secret `yaml:"routing_key,omitempty" json:"routing_key,omitempty"`
+ URL string `yaml:"url,omitempty" json:"url,omitempty"`
+ Client string `yaml:"client,omitempty" json:"client,omitempty"`
+ ClientURL string `yaml:"client_url,omitempty" json:"client_url,omitempty"`
+ Description string `yaml:"description,omitempty" json:"description,omitempty"`
+ Details map[string]string `yaml:"details,omitempty" json:"details,omitempty"`
+ Severity string `yaml:"severity,omitempty" json:"severity,omitempty"`
+ Class string `yaml:"class,omitempty" json:"class,omitempty"`
+ Component string `yaml:"component,omitempty" json:"component,omitempty"`
+ Group string `yaml:"group,omitempty" json:"group,omitempty"`
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (c *PagerdutyConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ *c = DefaultPagerdutyConfig
+ type plain PagerdutyConfig
+ if err := unmarshal((*plain)(c)); err != nil {
+ return err
+ }
+ if c.RoutingKey == "" && c.ServiceKey == "" {
+ return fmt.Errorf("missing service or routing key in PagerDuty config")
+ }
+ return nil
+}
+
+// SlackAction configures a single Slack action that is sent with each notification.
+// Each action must contain a type, text, and url.
+// See https://api.slack.com/docs/message-attachments#action_fields for more information.
+type SlackAction struct {
+ Type string `yaml:"type,omitempty" json:"type,omitempty"`
+ Text string `yaml:"text,omitempty" json:"text,omitempty"`
+ URL string `yaml:"url,omitempty" json:"url,omitempty"`
+ Style string `yaml:"style,omitempty" json:"style,omitempty"`
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface for SlackAction.
+func (c *SlackAction) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ type plain SlackAction
+ if err := unmarshal((*plain)(c)); err != nil {
+ return err
+ }
+ if c.Type == "" {
+ return fmt.Errorf("missing type in Slack action configuration")
+ }
+ if c.Text == "" {
+ return fmt.Errorf("missing value in Slack text configuration")
+ }
+ if c.URL == "" {
+ return fmt.Errorf("missing value in Slack url configuration")
+ }
+ return nil
+}
+
+// SlackField configures a single Slack field that is sent with each notification.
+// Each field must contain a title, value, and optionally, a boolean value to indicate if the field
+// is short enough to be displayed next to other fields designated as short.
+// See https://api.slack.com/docs/message-attachments#fields for more information.
+type SlackField struct {
+ Title string `yaml:"title,omitempty" json:"title,omitempty"`
+ Value string `yaml:"value,omitempty" json:"value,omitempty"`
+ Short *bool `yaml:"short,omitempty" json:"short,omitempty"`
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface for SlackField.
+func (c *SlackField) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ type plain SlackField
+ if err := unmarshal((*plain)(c)); err != nil {
+ return err
+ }
+ if c.Title == "" {
+ return fmt.Errorf("missing title in Slack field configuration")
+ }
+ if c.Value == "" {
+ return fmt.Errorf("missing value in Slack field configuration")
+ }
+ return nil
+}
+
+// SlackConfig configures notifications via Slack.
+type SlackConfig struct {
+ NotifierConfig `yaml:",inline" json:",inline"`
+
+ HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
+
+ APIURL Secret `yaml:"api_url,omitempty" json:"api_url,omitempty"`
+
+ // Slack channel override, (like #other-channel or @username).
+ Channel string `yaml:"channel,omitempty" json:"channel,omitempty"`
+ Username string `yaml:"username,omitempty" json:"username,omitempty"`
+ Color string `yaml:"color,omitempty" json:"color,omitempty"`
+
+ Title string `yaml:"title,omitempty" json:"title,omitempty"`
+ TitleLink string `yaml:"title_link,omitempty" json:"title_link,omitempty"`
+ Pretext string `yaml:"pretext,omitempty" json:"pretext,omitempty"`
+ Text string `yaml:"text,omitempty" json:"text,omitempty"`
+ Fields []*SlackField `yaml:"fields,omitempty" json:"fields,omitempty"`
+ ShortFields bool `yaml:"short_fields,omitempty" json:"short_fields,omitempty"`
+ Footer string `yaml:"footer,omitempty" json:"footer,omitempty"`
+ Fallback string `yaml:"fallback,omitempty" json:"fallback,omitempty"`
+ IconEmoji string `yaml:"icon_emoji,omitempty" json:"icon_emoji,omitempty"`
+ IconURL string `yaml:"icon_url,omitempty" json:"icon_url,omitempty"`
+ LinkNames bool `yaml:"link_names,omitempty" json:"link_names,omitempty"`
+ Actions []*SlackAction `yaml:"actions,omitempty" json:"actions,omitempty"`
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (c *SlackConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ *c = DefaultSlackConfig
+ type plain SlackConfig
+ return unmarshal((*plain)(c))
+}
+
+// HipchatConfig configures notifications via Hipchat.
+type HipchatConfig struct {
+ NotifierConfig `yaml:",inline" json:",inline"`
+
+ HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
+
+ APIURL string `yaml:"api_url,omitempty" json:"api_url,omitempty"`
+ AuthToken Secret `yaml:"auth_token,omitempty" json:"auth_token,omitempty"`
+ RoomID string `yaml:"room_id,omitempty" json:"room_id,omitempty"`
+ From string `yaml:"from,omitempty" json:"from,omitempty"`
+ Notify bool `yaml:"notify,omitempty" json:"notify,omitempty"`
+ Message string `yaml:"message,omitempty" json:"message,omitempty"`
+ MessageFormat string `yaml:"message_format,omitempty" json:"message_format,omitempty"`
+ Color string `yaml:"color,omitempty" json:"color,omitempty"`
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (c *HipchatConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ *c = DefaultHipchatConfig
+ type plain HipchatConfig
+ if err := unmarshal((*plain)(c)); err != nil {
+ return err
+ }
+ if c.RoomID == "" {
+ return fmt.Errorf("missing room id in Hipchat config")
+ }
+ return nil
+}
+
+// WebhookConfig configures notifications via a generic webhook.
+type WebhookConfig struct {
+ NotifierConfig `yaml:",inline" json:",inline"`
+
+ HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
+
+ // URL to send POST request to.
+ URL string `yaml:"url" json:"url"`
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (c *WebhookConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ *c = DefaultWebhookConfig
+ type plain WebhookConfig
+ if err := unmarshal((*plain)(c)); err != nil {
+ return err
+ }
+ if c.URL == "" {
+ return fmt.Errorf("missing URL in webhook config")
+ }
+ url, err := url.Parse(c.URL)
+ if err != nil {
+ return err
+ }
+ if url.Scheme != "https" && url.Scheme != "http" {
+ return fmt.Errorf("scheme required for webhook url")
+ }
+ c.URL = url.String()
+ return nil
+}
+
+// WechatConfig configures notifications via Wechat.
+type WechatConfig struct {
+ NotifierConfig `yaml:",inline" json:",inline"`
+
+ HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
+
+ APISecret Secret `yaml:"api_secret,omitempty" json:"api_secret,omitempty"`
+ CorpID string `yaml:"corp_id,omitempty" json:"corp_id,omitempty"`
+ Message string `yaml:"message,omitempty" json:"message,omitempty"`
+ APIURL string `yaml:"api_url,omitempty" json:"api_url,omitempty"`
+ ToUser string `yaml:"to_user,omitempty" json:"to_user,omitempty"`
+ ToParty string `yaml:"to_party,omitempty" json:"to_party,omitempty"`
+ ToTag string `yaml:"to_tag,omitempty" json:"to_tag,omitempty"`
+ AgentID string `yaml:"agent_id,omitempty" json:"agent_id,omitempty"`
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (c *WechatConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ *c = DefaultWechatConfig
+ type plain WechatConfig
+ if err := unmarshal((*plain)(c)); err != nil {
+ return err
+ }
+ if c.APISecret == "" {
+ return fmt.Errorf("missing Wechat APISecret in Wechat config")
+ }
+ if c.CorpID == "" {
+ return fmt.Errorf("missing Wechat CorpID in Wechat config")
+ }
+ return nil
+}
+
+// OpsGenieConfig configures notifications via OpsGenie.
+type OpsGenieConfig struct {
+ NotifierConfig `yaml:",inline" json:",inline"`
+
+ HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
+
+ APIKey Secret `yaml:"api_key,omitempty" json:"api_key,omitempty"`
+ APIURL string `yaml:"api_url,omitempty" json:"api_url,omitempty"`
+ Message string `yaml:"message,omitempty" json:"message,omitempty"`
+ Description string `yaml:"description,omitempty" json:"description,omitempty"`
+ Source string `yaml:"source,omitempty" json:"source,omitempty"`
+ Details map[string]string `yaml:"details,omitempty" json:"details,omitempty"`
+ Teams string `yaml:"teams,omitempty" json:"teams,omitempty"`
+ Tags string `yaml:"tags,omitempty" json:"tags,omitempty"`
+ Note string `yaml:"note,omitempty" json:"note,omitempty"`
+ Priority string `yaml:"priority,omitempty" json:"priority,omitempty"`
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (c *OpsGenieConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ *c = DefaultOpsGenieConfig
+ type plain OpsGenieConfig
+ return unmarshal((*plain)(c))
+}
+
+// VictorOpsConfig configures notifications via VictorOps.
+type VictorOpsConfig struct {
+ NotifierConfig `yaml:",inline" json:",inline"`
+
+ HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
+
+ APIKey Secret `yaml:"api_key" json:"api_key"`
+ APIURL string `yaml:"api_url" json:"api_url"`
+ RoutingKey string `yaml:"routing_key" json:"routing_key"`
+ MessageType string `yaml:"message_type" json:"message_type"`
+ StateMessage string `yaml:"state_message" json:"state_message"`
+ EntityDisplayName string `yaml:"entity_display_name" json:"entity_display_name"`
+ MonitoringTool string `yaml:"monitoring_tool" json:"monitoring_tool"`
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (c *VictorOpsConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ *c = DefaultVictorOpsConfig
+ type plain VictorOpsConfig
+ if err := unmarshal((*plain)(c)); err != nil {
+ return err
+ }
+ if c.RoutingKey == "" {
+ return fmt.Errorf("missing Routing key in VictorOps config")
+ }
+ return nil
+}
+
+type duration time.Duration
+
+func (d *duration) UnmarshalText(text []byte) error {
+ parsed, err := time.ParseDuration(string(text))
+ if err == nil {
+ *d = duration(parsed)
+ }
+ return err
+}
+
+func (d duration) MarshalText() ([]byte, error) {
+ return []byte(time.Duration(d).String()), nil
+}
+
+type PushoverConfig struct {
+ NotifierConfig `yaml:",inline" json:",inline"`
+
+ HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
+
+ UserKey Secret `yaml:"user_key,omitempty" json:"user_key,omitempty"`
+ Token Secret `yaml:"token,omitempty" json:"token,omitempty"`
+ Title string `yaml:"title,omitempty" json:"title,omitempty"`
+ Message string `yaml:"message,omitempty" json:"message,omitempty"`
+ URL string `yaml:"url,omitempty" json:"url,omitempty"`
+ Priority string `yaml:"priority,omitempty" json:"priority,omitempty"`
+ Retry duration `yaml:"retry,omitempty" json:"retry,omitempty"`
+ Expire duration `yaml:"expire,omitempty" json:"expire,omitempty"`
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (c *PushoverConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ *c = DefaultPushoverConfig
+ type plain PushoverConfig
+ if err := unmarshal((*plain)(c)); err != nil {
+ return err
+ }
+ if c.UserKey == "" {
+ return fmt.Errorf("missing user key in Pushover config")
+ }
+ if c.Token == "" {
+ return fmt.Errorf("missing token in Pushover config")
+ }
+ return nil
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+ "strings"
+ "testing"
+
+ "gopkg.in/yaml.v2"
+)
+
+func TestEmailToIsPresent(t *testing.T) {
+ in := `
+to: ''
+`
+ var cfg EmailConfig
+ err := yaml.UnmarshalStrict([]byte(in), &cfg)
+
+ expected := "missing to address in email config"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%v", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error())
+ }
+}
+
+func TestEmailHeadersCollision(t *testing.T) {
+ in := `
+to: 'to@email.com'
+headers:
+ Subject: 'Alert'
+ subject: 'New Alert'
+`
+ var cfg EmailConfig
+ err := yaml.UnmarshalStrict([]byte(in), &cfg)
+
+ expected := "duplicate header \"Subject\" in email config"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%v", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error())
+ }
+}
+
+func TestPagerdutyRoutingKeyIsPresent(t *testing.T) {
+ in := `
+routing_key: ''
+`
+ var cfg PagerdutyConfig
+ err := yaml.UnmarshalStrict([]byte(in), &cfg)
+
+ expected := "missing service or routing key in PagerDuty config"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%v", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error())
+ }
+}
+
+func TestPagerdutyServiceKeyIsPresent(t *testing.T) {
+ in := `
+service_key: ''
+`
+ var cfg PagerdutyConfig
+ err := yaml.UnmarshalStrict([]byte(in), &cfg)
+
+ expected := "missing service or routing key in PagerDuty config"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%v", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error())
+ }
+}
+
+func TestHipchatRoomIDIsPresent(t *testing.T) {
+ in := `
+room_id: ''
+`
+ var cfg HipchatConfig
+ err := yaml.UnmarshalStrict([]byte(in), &cfg)
+
+ expected := "missing room id in Hipchat config"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%v", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error())
+ }
+}
+
+func TestWebhookURLIsPresent(t *testing.T) {
+ in := `
+url: ''
+`
+ var cfg WebhookConfig
+ err := yaml.UnmarshalStrict([]byte(in), &cfg)
+
+ expected := "missing URL in webhook config"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%v", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error())
+ }
+}
+
+func TestWebhookHttpConfigIsValid(t *testing.T) {
+ in := `
+url: 'http://example.com'
+http_config:
+ bearer_token: foo
+ bearer_token_file: /tmp/bar
+`
+ var cfg WebhookConfig
+ err := yaml.UnmarshalStrict([]byte(in), &cfg)
+
+ expected := "at most one of bearer_token & bearer_token_file must be configured"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%v", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error())
+ }
+}
+
+func TestWebhookHttpConfigIsOptional(t *testing.T) {
+ in := `
+url: 'http://example.com'
+`
+ var cfg WebhookConfig
+ err := yaml.UnmarshalStrict([]byte(in), &cfg)
+
+ if err != nil {
+ t.Fatalf("no error expected, returned:\n%v", err.Error())
+ }
+}
+
+func TestWebhookPasswordIsObsfucated(t *testing.T) {
+ in := `
+url: 'http://example.com'
+http_config:
+ basic_auth:
+ username: foo
+ password: supersecret
+`
+ var cfg WebhookConfig
+ err := yaml.UnmarshalStrict([]byte(in), &cfg)
+
+ if err != nil {
+ t.Fatalf("no error expected, returned:\n%v", err.Error())
+ }
+
+ ycfg, err := yaml.Marshal(cfg)
+ if err != nil {
+ t.Fatalf("no error expected, returned:\n%v", err.Error())
+ }
+ if strings.Contains(string(ycfg), "supersecret") {
+ t.Errorf("Found password in the YAML cfg: %s\n", ycfg)
+ }
+}
+
+func TestWechatAPIKeyIsPresent(t *testing.T) {
+ in := `
+api_secret: ''
+`
+ var cfg WechatConfig
+ err := yaml.UnmarshalStrict([]byte(in), &cfg)
+
+ expected := "missing Wechat APISecret in Wechat config"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%v", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error())
+ }
+}
+func TestWechatCorpIDIsPresent(t *testing.T) {
+ in := `
+api_secret: 'api_secret'
+corp_id: ''
+`
+ var cfg WechatConfig
+ err := yaml.UnmarshalStrict([]byte(in), &cfg)
+
+ expected := "missing Wechat CorpID in Wechat config"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%v", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error())
+ }
+}
+
+func TestVictorOpsRoutingKeyIsPresent(t *testing.T) {
+ in := `
+routing_key: ''
+`
+ var cfg VictorOpsConfig
+ err := yaml.UnmarshalStrict([]byte(in), &cfg)
+
+ expected := "missing Routing key in VictorOps config"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%v", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error())
+ }
+}
+
+func TestPushoverUserKeyIsPresent(t *testing.T) {
+ in := `
+user_key: ''
+`
+ var cfg PushoverConfig
+ err := yaml.UnmarshalStrict([]byte(in), &cfg)
+
+ expected := "missing user key in Pushover config"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%v", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error())
+ }
+}
+
+func TestPushoverTokenIsPresent(t *testing.T) {
+ in := `
+user_key: '<user_key>'
+token: ''
+`
+ var cfg PushoverConfig
+ err := yaml.UnmarshalStrict([]byte(in), &cfg)
+
+ expected := "missing token in Pushover config"
+
+ if err == nil {
+ t.Fatalf("no error returned, expected:\n%v", expected)
+ }
+ if err.Error() != expected {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error())
+ }
+}
+
+func TestSlackFieldConfigValidation(t *testing.T) {
+ var tests = []struct {
+ in string
+ expected string
+ }{
+ {
+ in: `
+fields:
+- title: first
+ value: hello
+- title: second
+`,
+ expected: "missing value in Slack field configuration",
+ },
+ {
+ in: `
+fields:
+- title: first
+ value: hello
+ short: true
+- value: world
+ short: true
+`,
+ expected: "missing title in Slack field configuration",
+ },
+ {
+ in: `
+fields:
+- title: first
+ value: hello
+ short: true
+- title: second
+ value: world
+`,
+ expected: "",
+ },
+ }
+
+ for _, rt := range tests {
+ var cfg SlackConfig
+ err := yaml.UnmarshalStrict([]byte(rt.in), &cfg)
+
+ // Check if an error occurred when it was NOT expected to.
+ if rt.expected == "" && err != nil {
+ t.Fatalf("\nerror returned when none expected, error:\n%v", err)
+ }
+ // Check that an error occurred if one was expected to.
+ if rt.expected != "" && err == nil {
+ t.Fatalf("\nno error returned, expected:\n%v", rt.expected)
+ }
+ // Check that the error that occurred was what was expected.
+ if err != nil && err.Error() != rt.expected {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", rt.expected, err.Error())
+ }
+ }
+}
+
+func TestSlackFieldConfigUnmarshalling(t *testing.T) {
+ in := `
+fields:
+- title: first
+ value: hello
+ short: true
+- title: second
+ value: world
+- title: third
+ value: slack field test
+ short: false
+`
+ expected := []*SlackField{
+ &SlackField{
+ Title: "first",
+ Value: "hello",
+ Short: newBoolPointer(true),
+ },
+ &SlackField{
+ Title: "second",
+ Value: "world",
+ Short: nil,
+ },
+ &SlackField{
+ Title: "third",
+ Value: "slack field test",
+ Short: newBoolPointer(false),
+ },
+ }
+
+ var cfg SlackConfig
+ err := yaml.UnmarshalStrict([]byte(in), &cfg)
+ if err != nil {
+ t.Fatalf("\nerror returned when none expected, error:\n%v", err)
+ }
+
+ for index, field := range cfg.Fields {
+ exp := expected[index]
+ if field.Title != exp.Title {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", exp.Title, field.Title)
+ }
+ if field.Value != exp.Value {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", exp.Value, field.Value)
+ }
+ if exp.Short == nil && field.Short != nil {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", exp.Short, *field.Short)
+ }
+ if exp.Short != nil && field.Short == nil {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", *exp.Short, field.Short)
+ }
+ if exp.Short != nil && *exp.Short != *field.Short {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", *exp.Short, *field.Short)
+ }
+ }
+}
+
+func newBoolPointer(b bool) *bool {
+ return &b
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package dispatch
+
+import (
+ "fmt"
+ "sort"
+ "sync"
+ "time"
+
+ "github.com/go-kit/kit/log"
+ "github.com/go-kit/kit/log/level"
+ "github.com/prometheus/common/model"
+ "github.com/prometheus/prometheus/pkg/labels"
+ "golang.org/x/net/context"
+
+ "github.com/prometheus/alertmanager/notify"
+ "github.com/prometheus/alertmanager/provider"
+ "github.com/prometheus/alertmanager/types"
+)
+
+// Dispatcher sorts incoming alerts into aggregation groups and
+// assigns the correct notifiers to each.
+type Dispatcher struct {
+ route *Route
+ alerts provider.Alerts
+ stage notify.Stage
+
+ marker types.Marker
+ timeout func(time.Duration) time.Duration
+
+ aggrGroups map[*Route]map[model.Fingerprint]*aggrGroup
+ mtx sync.RWMutex
+
+ done chan struct{}
+ ctx context.Context
+ cancel func()
+
+ logger log.Logger
+}
+
+// NewDispatcher returns a new Dispatcher.
+func NewDispatcher(
+ ap provider.Alerts,
+ r *Route,
+ s notify.Stage,
+ mk types.Marker,
+ to func(time.Duration) time.Duration,
+ l log.Logger,
+) *Dispatcher {
+ disp := &Dispatcher{
+ alerts: ap,
+ stage: s,
+ route: r,
+ marker: mk,
+ timeout: to,
+ logger: log.With(l, "component", "dispatcher"),
+ }
+ return disp
+}
+
+// Run starts dispatching alerts incoming via the updates channel.
+func (d *Dispatcher) Run() {
+ d.done = make(chan struct{})
+
+ d.mtx.Lock()
+ d.aggrGroups = map[*Route]map[model.Fingerprint]*aggrGroup{}
+ d.mtx.Unlock()
+
+ d.ctx, d.cancel = context.WithCancel(context.Background())
+
+ d.run(d.alerts.Subscribe())
+ close(d.done)
+}
+
+// AlertBlock contains a list of alerts associated with a set of
+// routing options.
+type AlertBlock struct {
+ RouteOpts *RouteOpts `json:"routeOpts"`
+ Alerts []*APIAlert `json:"alerts"`
+}
+
+// APIAlert is the API representation of an alert, which is a regular alert
+// annotated with silencing and inhibition info.
+type APIAlert struct {
+ *model.Alert
+ Status types.AlertStatus `json:"status"`
+ Receivers []string `json:"receivers"`
+ Fingerprint string `json:"fingerprint"`
+}
+
+// AlertGroup is a list of alert blocks grouped by the same label set.
+type AlertGroup struct {
+ Labels model.LabelSet `json:"labels"`
+ GroupKey string `json:"groupKey"`
+ Blocks []*AlertBlock `json:"blocks"`
+}
+
+// AlertOverview is a representation of all active alerts in the system.
+type AlertOverview []*AlertGroup
+
+func (ao AlertOverview) Swap(i, j int) { ao[i], ao[j] = ao[j], ao[i] }
+func (ao AlertOverview) Less(i, j int) bool { return ao[i].Labels.Before(ao[j].Labels) }
+func (ao AlertOverview) Len() int { return len(ao) }
+
+func matchesFilterLabels(a *APIAlert, matchers []*labels.Matcher) bool {
+ for _, m := range matchers {
+ if v, prs := a.Labels[model.LabelName(m.Name)]; !prs || !m.Matches(string(v)) {
+ return false
+ }
+ }
+
+ return true
+}
+
+// Groups populates an AlertOverview from the dispatcher's internal state.
+func (d *Dispatcher) Groups(matchers []*labels.Matcher) AlertOverview {
+ overview := AlertOverview{}
+
+ d.mtx.RLock()
+ defer d.mtx.RUnlock()
+
+ seen := map[model.Fingerprint]*AlertGroup{}
+
+ for route, ags := range d.aggrGroups {
+ for _, ag := range ags {
+ alertGroup, ok := seen[ag.fingerprint()]
+ if !ok {
+ alertGroup = &AlertGroup{Labels: ag.labels}
+ alertGroup.GroupKey = ag.GroupKey()
+
+ seen[ag.fingerprint()] = alertGroup
+ }
+
+ now := time.Now()
+
+ var apiAlerts []*APIAlert
+ for _, a := range types.Alerts(ag.alertSlice()...) {
+ if !a.EndsAt.IsZero() && a.EndsAt.Before(now) {
+ continue
+ }
+ status := d.marker.Status(a.Fingerprint())
+ aa := &APIAlert{
+ Alert: a,
+ Status: status,
+ Fingerprint: a.Fingerprint().String(),
+ }
+
+ if !matchesFilterLabels(aa, matchers) {
+ continue
+ }
+
+ apiAlerts = append(apiAlerts, aa)
+ }
+ if len(apiAlerts) == 0 {
+ continue
+ }
+
+ alertGroup.Blocks = append(alertGroup.Blocks, &AlertBlock{
+ RouteOpts: &route.RouteOpts,
+ Alerts: apiAlerts,
+ })
+
+ overview = append(overview, alertGroup)
+ }
+ }
+
+ sort.Sort(overview)
+
+ return overview
+}
+
+func (d *Dispatcher) run(it provider.AlertIterator) {
+ cleanup := time.NewTicker(30 * time.Second)
+ defer cleanup.Stop()
+
+ defer it.Close()
+
+ for {
+ select {
+ case alert, ok := <-it.Next():
+ if !ok {
+ // Iterator exhausted for some reason.
+ if err := it.Err(); err != nil {
+ level.Error(d.logger).Log("msg", "Error on alert update", "err", err)
+ }
+ return
+ }
+
+ level.Debug(d.logger).Log("msg", "Received alert", "alert", alert)
+
+ // Log errors but keep trying.
+ if err := it.Err(); err != nil {
+ level.Error(d.logger).Log("msg", "Error on alert update", "err", err)
+ continue
+ }
+
+ for _, r := range d.route.Match(alert.Labels) {
+ d.processAlert(alert, r)
+ }
+
+ case <-cleanup.C:
+ d.mtx.Lock()
+
+ for _, groups := range d.aggrGroups {
+ for _, ag := range groups {
+ if ag.empty() {
+ ag.stop()
+ delete(groups, ag.fingerprint())
+ }
+ }
+ }
+
+ d.mtx.Unlock()
+
+ case <-d.ctx.Done():
+ return
+ }
+ }
+}
+
+// Stop the dispatcher.
+func (d *Dispatcher) Stop() {
+ if d == nil || d.cancel == nil {
+ return
+ }
+ d.cancel()
+ d.cancel = nil
+
+ <-d.done
+}
+
+// notifyFunc is a function that performs notifcation for the alert
+// with the given fingerprint. It aborts on context cancelation.
+// Returns false iff notifying failed.
+type notifyFunc func(context.Context, ...*types.Alert) bool
+
+// processAlert determines in which aggregation group the alert falls
+// and inserts it.
+func (d *Dispatcher) processAlert(alert *types.Alert, route *Route) {
+ groupLabels := model.LabelSet{}
+
+ for ln, lv := range alert.Labels {
+ if _, ok := route.RouteOpts.GroupBy[ln]; ok {
+ groupLabels[ln] = lv
+ }
+ }
+
+ fp := groupLabels.Fingerprint()
+
+ d.mtx.Lock()
+ group, ok := d.aggrGroups[route]
+ if !ok {
+ group = map[model.Fingerprint]*aggrGroup{}
+ d.aggrGroups[route] = group
+ }
+ d.mtx.Unlock()
+
+ // If the group does not exist, create it.
+ ag, ok := group[fp]
+ if !ok {
+ ag = newAggrGroup(d.ctx, groupLabels, route, d.timeout, d.logger)
+ group[fp] = ag
+
+ go ag.run(func(ctx context.Context, alerts ...*types.Alert) bool {
+ _, _, err := d.stage.Exec(ctx, d.logger, alerts...)
+ if err != nil {
+ level.Error(d.logger).Log("msg", "Notify for alerts failed", "num_alerts", len(alerts), "err", err)
+ }
+ return err == nil
+ })
+ }
+
+ ag.insert(alert)
+}
+
+// aggrGroup aggregates alert fingerprints into groups to which a
+// common set of routing options applies.
+// It emits notifications in the specified intervals.
+type aggrGroup struct {
+ labels model.LabelSet
+ opts *RouteOpts
+ logger log.Logger
+ routeKey string
+
+ ctx context.Context
+ cancel func()
+ done chan struct{}
+ next *time.Timer
+ timeout func(time.Duration) time.Duration
+
+ mtx sync.RWMutex
+ alerts map[model.Fingerprint]*types.Alert
+ hasFlushed bool
+}
+
+// newAggrGroup returns a new aggregation group.
+func newAggrGroup(ctx context.Context, labels model.LabelSet, r *Route, to func(time.Duration) time.Duration, logger log.Logger) *aggrGroup {
+ if to == nil {
+ to = func(d time.Duration) time.Duration { return d }
+ }
+ ag := &aggrGroup{
+ labels: labels,
+ routeKey: r.Key(),
+ opts: &r.RouteOpts,
+ timeout: to,
+ alerts: map[model.Fingerprint]*types.Alert{},
+ }
+ ag.ctx, ag.cancel = context.WithCancel(ctx)
+
+ ag.logger = log.With(logger, "aggrGroup", ag)
+
+ // Set an initial one-time wait before flushing
+ // the first batch of notifications.
+ ag.next = time.NewTimer(ag.opts.GroupWait)
+
+ return ag
+}
+
+func (ag *aggrGroup) fingerprint() model.Fingerprint {
+ return ag.labels.Fingerprint()
+}
+
+func (ag *aggrGroup) GroupKey() string {
+ return fmt.Sprintf("%s:%s", ag.routeKey, ag.labels)
+}
+
+func (ag *aggrGroup) String() string {
+ return ag.GroupKey()
+}
+
+func (ag *aggrGroup) alertSlice() []*types.Alert {
+ ag.mtx.RLock()
+ defer ag.mtx.RUnlock()
+
+ var alerts []*types.Alert
+ for _, a := range ag.alerts {
+ alerts = append(alerts, a)
+ }
+ return alerts
+}
+
+func (ag *aggrGroup) run(nf notifyFunc) {
+ ag.done = make(chan struct{})
+
+ defer close(ag.done)
+ defer ag.next.Stop()
+
+ for {
+ select {
+ case now := <-ag.next.C:
+ // Give the notifications time until the next flush to
+ // finish before terminating them.
+ ctx, cancel := context.WithTimeout(ag.ctx, ag.timeout(ag.opts.GroupInterval))
+
+ // The now time we retrieve from the ticker is the only reliable
+ // point of time reference for the subsequent notification pipeline.
+ // Calculating the current time directly is prone to flaky behavior,
+ // which usually only becomes apparent in tests.
+ ctx = notify.WithNow(ctx, now)
+
+ // Populate context with information needed along the pipeline.
+ ctx = notify.WithGroupKey(ctx, ag.GroupKey())
+ ctx = notify.WithGroupLabels(ctx, ag.labels)
+ ctx = notify.WithReceiverName(ctx, ag.opts.Receiver)
+ ctx = notify.WithRepeatInterval(ctx, ag.opts.RepeatInterval)
+
+ // Wait the configured interval before calling flush again.
+ ag.mtx.Lock()
+ ag.next.Reset(ag.opts.GroupInterval)
+ ag.hasFlushed = true
+ ag.mtx.Unlock()
+
+ ag.flush(func(alerts ...*types.Alert) bool {
+ return nf(ctx, alerts...)
+ })
+
+ cancel()
+
+ case <-ag.ctx.Done():
+ return
+ }
+ }
+}
+
+func (ag *aggrGroup) stop() {
+ // Calling cancel will terminate all in-process notifications
+ // and the run() loop.
+ ag.cancel()
+ <-ag.done
+}
+
+// insert inserts the alert into the aggregation group.
+func (ag *aggrGroup) insert(alert *types.Alert) {
+ ag.mtx.Lock()
+ defer ag.mtx.Unlock()
+
+ ag.alerts[alert.Fingerprint()] = alert
+
+ // Immediately trigger a flush if the wait duration for this
+ // alert is already over.
+ if !ag.hasFlushed && alert.StartsAt.Add(ag.opts.GroupWait).Before(time.Now()) {
+ ag.next.Reset(0)
+ }
+}
+
+func (ag *aggrGroup) empty() bool {
+ ag.mtx.RLock()
+ defer ag.mtx.RUnlock()
+
+ return len(ag.alerts) == 0
+}
+
+// flush sends notifications for all new alerts.
+func (ag *aggrGroup) flush(notify func(...*types.Alert) bool) {
+ if ag.empty() {
+ return
+ }
+ ag.mtx.Lock()
+
+ var (
+ alerts = make(map[model.Fingerprint]*types.Alert, len(ag.alerts))
+ alertsSlice = make(types.AlertSlice, 0, len(ag.alerts))
+ )
+ for fp, alert := range ag.alerts {
+ alerts[fp] = alert
+ alertsSlice = append(alertsSlice, alert)
+ }
+ sort.Stable(alertsSlice)
+
+ ag.mtx.Unlock()
+
+ level.Debug(ag.logger).Log("msg", "Flushing", "alerts", fmt.Sprintf("%v", alertsSlice))
+
+ if notify(alertsSlice...) {
+ ag.mtx.Lock()
+ for fp, a := range alerts {
+ // Only delete if the fingerprint has not been inserted
+ // again since we notified about it.
+ if a.Resolved() && ag.alerts[fp] == a {
+ delete(ag.alerts, fp)
+ }
+ }
+ ag.mtx.Unlock()
+ }
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package dispatch
+
+import (
+ "reflect"
+ "sort"
+ "sync"
+ "testing"
+ "time"
+
+ "github.com/go-kit/kit/log"
+ "github.com/prometheus/common/model"
+ "github.com/prometheus/prometheus/pkg/labels"
+ "golang.org/x/net/context"
+
+ "github.com/prometheus/alertmanager/notify"
+ "github.com/prometheus/alertmanager/types"
+)
+
+func newAPIAlert(labels model.LabelSet) APIAlert {
+ return APIAlert{
+ Alert: &model.Alert{
+ Labels: labels,
+ StartsAt: time.Now().Add(1 * time.Minute),
+ EndsAt: time.Now().Add(1 * time.Hour),
+ },
+ }
+}
+
+func TestFilterLabels(t *testing.T) {
+
+ var (
+ a1 = newAPIAlert(model.LabelSet{
+ "a": "v1",
+ "b": "v2",
+ "c": "v3",
+ })
+ a2 = newAPIAlert(model.LabelSet{
+ "a": "v1",
+ "b": "v2",
+ "c": "v4",
+ })
+ a3 = newAPIAlert(model.LabelSet{
+ "a": "v1",
+ "b": "v2",
+ "c": "v5",
+ })
+ a4 = newAPIAlert(model.LabelSet{
+ "foo": "bar",
+ "baz": "qux",
+ })
+ alertsSlices = []struct {
+ in, want []APIAlert
+ }{
+ {
+ in: []APIAlert{a1, a2, a3},
+ want: []APIAlert{a1, a2, a3},
+ },
+ {
+ in: []APIAlert{a1, a4},
+ want: []APIAlert{a1},
+ },
+ {
+ in: []APIAlert{a4},
+ want: []APIAlert{},
+ },
+ }
+ )
+
+ matcher, err := labels.NewMatcher(labels.MatchRegexp, "c", "v.*")
+ if err != nil {
+ t.Fatalf("error making matcher: %v", err)
+ }
+ matcher2, err := labels.NewMatcher(labels.MatchEqual, "a", "v1")
+ if err != nil {
+ t.Fatalf("error making matcher: %v", err)
+ }
+
+ matchers := []*labels.Matcher{matcher, matcher2}
+
+ for _, alerts := range alertsSlices {
+ got := []APIAlert{}
+ for _, a := range alerts.in {
+ if matchesFilterLabels(&a, matchers) {
+ got = append(got, a)
+ }
+ }
+ if !reflect.DeepEqual(got, alerts.want) {
+ t.Fatalf("error: returned alerts do not match:\ngot %v\nwant %v", got, alerts.want)
+ }
+ }
+}
+
+func TestAggrGroup(t *testing.T) {
+ lset := model.LabelSet{
+ "a": "v1",
+ "b": "v2",
+ }
+ opts := &RouteOpts{
+ Receiver: "n1",
+ GroupBy: map[model.LabelName]struct{}{},
+ GroupWait: 1 * time.Second,
+ GroupInterval: 300 * time.Millisecond,
+ RepeatInterval: 1 * time.Hour,
+ }
+ route := &Route{
+ RouteOpts: *opts,
+ }
+
+ var (
+ a1 = &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{
+ "a": "v1",
+ "b": "v2",
+ "c": "v3",
+ },
+ StartsAt: time.Now().Add(time.Minute),
+ EndsAt: time.Now().Add(time.Hour),
+ },
+ UpdatedAt: time.Now(),
+ }
+ a2 = &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{
+ "a": "v1",
+ "b": "v2",
+ "c": "v4",
+ },
+ StartsAt: time.Now().Add(-time.Hour),
+ EndsAt: time.Now().Add(2 * time.Hour),
+ },
+ UpdatedAt: time.Now(),
+ }
+ a3 = &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{
+ "a": "v1",
+ "b": "v2",
+ "c": "v5",
+ },
+ StartsAt: time.Now().Add(time.Minute),
+ EndsAt: time.Now().Add(5 * time.Minute),
+ },
+ UpdatedAt: time.Now(),
+ }
+ )
+
+ var (
+ last = time.Now()
+ current = time.Now()
+ lastCurMtx = &sync.Mutex{}
+ alertsCh = make(chan types.AlertSlice)
+ )
+
+ ntfy := func(ctx context.Context, alerts ...*types.Alert) bool {
+ // Validate that the context is properly populated.
+ if _, ok := notify.Now(ctx); !ok {
+ t.Errorf("now missing")
+ }
+ if _, ok := notify.GroupKey(ctx); !ok {
+ t.Errorf("group key missing")
+ }
+ if lbls, ok := notify.GroupLabels(ctx); !ok || !reflect.DeepEqual(lbls, lset) {
+ t.Errorf("wrong group labels: %q", lbls)
+ }
+ if rcv, ok := notify.ReceiverName(ctx); !ok || rcv != opts.Receiver {
+ t.Errorf("wrong receiver: %q", rcv)
+ }
+ if ri, ok := notify.RepeatInterval(ctx); !ok || ri != opts.RepeatInterval {
+ t.Errorf("wrong repeat interval: %q", ri)
+ }
+
+ lastCurMtx.Lock()
+ last = current
+ current = time.Now()
+ lastCurMtx.Unlock()
+
+ alertsCh <- types.AlertSlice(alerts)
+
+ return true
+ }
+
+ // Test regular situation where we wait for group_wait to send out alerts.
+ ag := newAggrGroup(context.Background(), lset, route, nil, log.NewNopLogger())
+ go ag.run(ntfy)
+
+ ag.insert(a1)
+
+ select {
+ case <-time.After(2 * opts.GroupWait):
+ t.Fatalf("expected initial batch after group_wait")
+
+ case batch := <-alertsCh:
+ if s := time.Since(last); s < opts.GroupWait {
+ t.Fatalf("received batch too early after %v", s)
+ }
+ exp := types.AlertSlice{a1}
+ sort.Sort(batch)
+
+ if !reflect.DeepEqual(batch, exp) {
+ t.Fatalf("expected alerts %v but got %v", exp, batch)
+ }
+ }
+
+ for i := 0; i < 3; i++ {
+ // New alert should come in after group interval.
+ ag.insert(a3)
+
+ select {
+ case <-time.After(2 * opts.GroupInterval):
+ t.Fatalf("expected new batch after group interval but received none")
+
+ case batch := <-alertsCh:
+ if s := time.Since(last); s < opts.GroupInterval {
+ t.Fatalf("received batch too early after %v", s)
+ }
+ exp := types.AlertSlice{a1, a3}
+ sort.Sort(batch)
+
+ if !reflect.DeepEqual(batch, exp) {
+ t.Fatalf("expected alerts %v but got %v", exp, batch)
+ }
+ }
+ }
+
+ ag.stop()
+
+ // Add an alert that started more than group_interval in the past. We expect
+ // immediate flushing.
+ // Finally, set all alerts to be resolved. After successful notify the aggregation group
+ // should empty itself.
+ ag = newAggrGroup(context.Background(), lset, route, nil, log.NewNopLogger())
+ go ag.run(ntfy)
+
+ ag.insert(a1)
+ ag.insert(a2)
+
+ // a2 lies way in the past so the initial group_wait should be skipped.
+ select {
+ case <-time.After(opts.GroupWait / 2):
+ t.Fatalf("expected immediate alert but received none")
+
+ case batch := <-alertsCh:
+ exp := types.AlertSlice{a1, a2}
+ sort.Sort(batch)
+
+ if !reflect.DeepEqual(batch, exp) {
+ t.Fatalf("expected alerts %v but got %v", exp, batch)
+ }
+ }
+
+ for i := 0; i < 3; i++ {
+ // New alert should come in after group interval.
+ ag.insert(a3)
+
+ select {
+ case <-time.After(2 * opts.GroupInterval):
+ t.Fatalf("expected new batch after group interval but received none")
+
+ case batch := <-alertsCh:
+ lastCurMtx.Lock()
+ s := time.Since(last)
+ lastCurMtx.Unlock()
+ if s < opts.GroupInterval {
+ t.Fatalf("received batch too early after %v", s)
+ }
+ exp := types.AlertSlice{a1, a2, a3}
+ sort.Sort(batch)
+
+ if !reflect.DeepEqual(batch, exp) {
+ t.Fatalf("expected alerts %v but got %v", exp, batch)
+ }
+ }
+ }
+
+ // Resolve all alerts, they should be removed after the next batch was sent.
+ a1r, a2r, a3r := *a1, *a2, *a3
+ resolved := types.AlertSlice{&a1r, &a2r, &a3r}
+ for _, a := range resolved {
+ a.EndsAt = time.Now()
+ ag.insert(a)
+ }
+
+ select {
+ case <-time.After(2 * opts.GroupInterval):
+ t.Fatalf("expected new batch after group interval but received none")
+
+ case batch := <-alertsCh:
+ if s := time.Since(last); s < opts.GroupInterval {
+ t.Fatalf("received batch too early after %v", s)
+ }
+ sort.Sort(batch)
+
+ if !reflect.DeepEqual(batch, resolved) {
+ t.Fatalf("expected alerts %v but got %v", resolved, batch)
+ }
+
+ if !ag.empty() {
+ t.Fatalf("Expected aggregation group to be empty after resolving alerts: %v", ag)
+ }
+ }
+
+ ag.stop()
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package dispatch
+
+import (
+ "encoding/json"
+ "fmt"
+ "sort"
+ "time"
+
+ "github.com/prometheus/common/model"
+
+ "github.com/prometheus/alertmanager/config"
+ "github.com/prometheus/alertmanager/types"
+)
+
+// DefaultRouteOpts are the defaulting routing options which apply
+// to the root route of a routing tree.
+var DefaultRouteOpts = RouteOpts{
+ GroupWait: 30 * time.Second,
+ GroupInterval: 5 * time.Minute,
+ RepeatInterval: 4 * time.Hour,
+ GroupBy: map[model.LabelName]struct{}{},
+}
+
+// A Route is a node that contains definitions of how to handle alerts.
+type Route struct {
+ parent *Route
+
+ // The configuration parameters for matches of this route.
+ RouteOpts RouteOpts
+
+ // Equality or regex matchers an alert has to fulfill to match
+ // this route.
+ Matchers types.Matchers
+
+ // If true, an alert matches further routes on the same level.
+ Continue bool
+
+ // Children routes of this route.
+ Routes []*Route
+}
+
+// NewRoute returns a new route.
+func NewRoute(cr *config.Route, parent *Route) *Route {
+ // Create default and overwrite with configured settings.
+ opts := DefaultRouteOpts
+ if parent != nil {
+ opts = parent.RouteOpts
+ }
+
+ if cr.Receiver != "" {
+ opts.Receiver = cr.Receiver
+ }
+ if cr.GroupBy != nil {
+ opts.GroupBy = map[model.LabelName]struct{}{}
+ for _, ln := range cr.GroupBy {
+ opts.GroupBy[ln] = struct{}{}
+ }
+ }
+ if cr.GroupWait != nil {
+ opts.GroupWait = time.Duration(*cr.GroupWait)
+ }
+ if cr.GroupInterval != nil {
+ opts.GroupInterval = time.Duration(*cr.GroupInterval)
+ }
+ if cr.RepeatInterval != nil {
+ opts.RepeatInterval = time.Duration(*cr.RepeatInterval)
+ }
+
+ // Build matchers.
+ var matchers types.Matchers
+
+ for ln, lv := range cr.Match {
+ matchers = append(matchers, types.NewMatcher(model.LabelName(ln), lv))
+ }
+ for ln, lv := range cr.MatchRE {
+ matchers = append(matchers, types.NewRegexMatcher(model.LabelName(ln), lv.Regexp))
+ }
+ sort.Sort(matchers)
+
+ route := &Route{
+ parent: parent,
+ RouteOpts: opts,
+ Matchers: matchers,
+ Continue: cr.Continue,
+ }
+
+ route.Routes = NewRoutes(cr.Routes, route)
+
+ return route
+}
+
+// NewRoutes returns a slice of routes.
+func NewRoutes(croutes []*config.Route, parent *Route) []*Route {
+ res := []*Route{}
+ for _, cr := range croutes {
+ res = append(res, NewRoute(cr, parent))
+ }
+ return res
+}
+
+// Match does a depth-first left-to-right search through the route tree
+// and returns the matching routing nodes.
+func (r *Route) Match(lset model.LabelSet) []*Route {
+ if !r.Matchers.Match(lset) {
+ return nil
+ }
+
+ var all []*Route
+
+ for _, cr := range r.Routes {
+ matches := cr.Match(lset)
+
+ all = append(all, matches...)
+
+ if matches != nil && !cr.Continue {
+ break
+ }
+ }
+
+ // If no child nodes were matches, the current node itself is a match.
+ if len(all) == 0 {
+ all = append(all, r)
+ }
+
+ return all
+}
+
+// Key returns a key for the route. It does not uniquely identify a the route in general.
+func (r *Route) Key() string {
+ b := make([]byte, 0, 1024)
+
+ if r.parent != nil {
+ b = append(b, r.parent.Key()...)
+ b = append(b, '/')
+ }
+ return string(append(b, r.Matchers.String()...))
+}
+
+// RouteOpts holds various routing options necessary for processing alerts
+// that match a given route.
+type RouteOpts struct {
+ // The identifier of the associated notification configuration.
+ Receiver string
+
+ // What labels to group alerts by for notifications.
+ GroupBy map[model.LabelName]struct{}
+
+ // How long to wait to group matching alerts before sending
+ // a notification.
+ GroupWait time.Duration
+ GroupInterval time.Duration
+ RepeatInterval time.Duration
+}
+
+func (ro *RouteOpts) String() string {
+ var labels []model.LabelName
+ for ln := range ro.GroupBy {
+ labels = append(labels, ln)
+ }
+ return fmt.Sprintf("<RouteOpts send_to:%q group_by:%q timers:%q|%q>", ro.Receiver, labels, ro.GroupWait, ro.GroupInterval)
+}
+
+// MarshalJSON returns a JSON representation of the routing options.
+func (ro *RouteOpts) MarshalJSON() ([]byte, error) {
+ v := struct {
+ Receiver string `json:"receiver"`
+ GroupBy model.LabelNames `json:"groupBy"`
+ GroupWait time.Duration `json:"groupWait"`
+ GroupInterval time.Duration `json:"groupInterval"`
+ RepeatInterval time.Duration `json:"repeatInterval"`
+ }{
+ Receiver: ro.Receiver,
+ GroupWait: ro.GroupWait,
+ GroupInterval: ro.GroupInterval,
+ RepeatInterval: ro.RepeatInterval,
+ }
+ for ln := range ro.GroupBy {
+ v.GroupBy = append(v.GroupBy, ln)
+ }
+
+ return json.Marshal(&v)
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package dispatch
+
+import (
+ "reflect"
+ "testing"
+ "time"
+
+ "github.com/prometheus/common/model"
+ "gopkg.in/yaml.v2"
+
+ "github.com/prometheus/alertmanager/config"
+)
+
+func TestRouteMatch(t *testing.T) {
+ in := `
+receiver: 'notify-def'
+
+routes:
+- match:
+ owner: 'team-A'
+
+ receiver: 'notify-A'
+
+ routes:
+ - match:
+ env: 'testing'
+
+ receiver: 'notify-testing'
+ group_by: []
+
+ - match:
+ env: "production"
+
+ receiver: 'notify-productionA'
+ group_wait: 1m
+
+ continue: true
+
+ - match_re:
+ env: "produ.*"
+ job: ".*"
+
+ receiver: 'notify-productionB'
+ group_wait: 30s
+ group_interval: 5m
+ repeat_interval: 1h
+ group_by: ['job']
+
+
+- match_re:
+ owner: 'team-(B|C)'
+
+ group_by: ['foo', 'bar']
+ group_wait: 2m
+ receiver: 'notify-BC'
+
+- match:
+ group_by: 'role'
+ group_by: ['role']
+
+ routes:
+ - match:
+ env: 'testing'
+ receiver: 'notify-testing'
+ routes:
+ - match:
+ wait: 'long'
+ group_wait: 2m
+`
+
+ var ctree config.Route
+ if err := yaml.UnmarshalStrict([]byte(in), &ctree); err != nil {
+ t.Fatal(err)
+ }
+ var (
+ def = DefaultRouteOpts
+ tree = NewRoute(&ctree, nil)
+ )
+ lset := func(labels ...string) map[model.LabelName]struct{} {
+ s := map[model.LabelName]struct{}{}
+ for _, ls := range labels {
+ s[model.LabelName(ls)] = struct{}{}
+ }
+ return s
+ }
+
+ tests := []struct {
+ input model.LabelSet
+ result []*RouteOpts
+ keys []string
+ }{
+ {
+ input: model.LabelSet{
+ "owner": "team-A",
+ },
+ result: []*RouteOpts{
+ {
+ Receiver: "notify-A",
+ GroupBy: def.GroupBy,
+ GroupWait: def.GroupWait,
+ GroupInterval: def.GroupInterval,
+ RepeatInterval: def.RepeatInterval,
+ },
+ },
+ keys: []string{"{}/{owner=\"team-A\"}"},
+ },
+ {
+ input: model.LabelSet{
+ "owner": "team-A",
+ "env": "unset",
+ },
+ result: []*RouteOpts{
+ {
+ Receiver: "notify-A",
+ GroupBy: def.GroupBy,
+ GroupWait: def.GroupWait,
+ GroupInterval: def.GroupInterval,
+ RepeatInterval: def.RepeatInterval,
+ },
+ },
+ keys: []string{"{}/{owner=\"team-A\"}"},
+ },
+ {
+ input: model.LabelSet{
+ "owner": "team-C",
+ },
+ result: []*RouteOpts{
+ {
+ Receiver: "notify-BC",
+ GroupBy: lset("foo", "bar"),
+ GroupWait: 2 * time.Minute,
+ GroupInterval: def.GroupInterval,
+ RepeatInterval: def.RepeatInterval,
+ },
+ },
+ keys: []string{"{}/{owner=~\"^(?:team-(B|C))$\"}"},
+ },
+ {
+ input: model.LabelSet{
+ "owner": "team-A",
+ "env": "testing",
+ },
+ result: []*RouteOpts{
+ {
+ Receiver: "notify-testing",
+ GroupBy: lset(),
+ GroupWait: def.GroupWait,
+ GroupInterval: def.GroupInterval,
+ RepeatInterval: def.RepeatInterval,
+ },
+ },
+ keys: []string{"{}/{owner=\"team-A\"}/{env=\"testing\"}"},
+ },
+ {
+ input: model.LabelSet{
+ "owner": "team-A",
+ "env": "production",
+ },
+ result: []*RouteOpts{
+ {
+ Receiver: "notify-productionA",
+ GroupBy: def.GroupBy,
+ GroupWait: 1 * time.Minute,
+ GroupInterval: def.GroupInterval,
+ RepeatInterval: def.RepeatInterval,
+ },
+ {
+ Receiver: "notify-productionB",
+ GroupBy: lset("job"),
+ GroupWait: 30 * time.Second,
+ GroupInterval: 5 * time.Minute,
+ RepeatInterval: 1 * time.Hour,
+ },
+ },
+ keys: []string{
+ "{}/{owner=\"team-A\"}/{env=\"production\"}",
+ "{}/{owner=\"team-A\"}/{env=~\"^(?:produ.*)$\",job=~\"^(?:.*)$\"}",
+ },
+ },
+ {
+ input: model.LabelSet{
+ "group_by": "role",
+ },
+ result: []*RouteOpts{
+ {
+ Receiver: "notify-def",
+ GroupBy: lset("role"),
+ GroupWait: def.GroupWait,
+ GroupInterval: def.GroupInterval,
+ RepeatInterval: def.RepeatInterval,
+ },
+ },
+ keys: []string{"{}/{group_by=\"role\"}"},
+ },
+ {
+ input: model.LabelSet{
+ "env": "testing",
+ "group_by": "role",
+ },
+ result: []*RouteOpts{
+ {
+ Receiver: "notify-testing",
+ GroupBy: lset("role"),
+ GroupWait: def.GroupWait,
+ GroupInterval: def.GroupInterval,
+ RepeatInterval: def.RepeatInterval,
+ },
+ },
+ keys: []string{"{}/{group_by=\"role\"}/{env=\"testing\"}"},
+ },
+ {
+ input: model.LabelSet{
+ "env": "testing",
+ "group_by": "role",
+ "wait": "long",
+ },
+ result: []*RouteOpts{
+ {
+ Receiver: "notify-testing",
+ GroupBy: lset("role"),
+ GroupWait: 2 * time.Minute,
+ GroupInterval: def.GroupInterval,
+ RepeatInterval: def.RepeatInterval,
+ },
+ },
+ keys: []string{"{}/{group_by=\"role\"}/{env=\"testing\"}/{wait=\"long\"}"},
+ },
+ }
+
+ for _, test := range tests {
+ var matches []*RouteOpts
+ var keys []string
+
+ for _, r := range tree.Match(test.input) {
+ matches = append(matches, &r.RouteOpts)
+ keys = append(keys, r.Key())
+ }
+
+ if !reflect.DeepEqual(matches, test.result) {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", test.result, matches)
+ }
+
+ if !reflect.DeepEqual(keys, test.keys) {
+ t.Errorf("\nexpected:\n%v\ngot:\n%v", test.keys, keys)
+ }
+ }
+}
--- /dev/null
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="658px" height="494px" version="1.1" content="<mxfile userAgent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36" version="8.6.9" editor="www.draw.io" type="google"><diagram id="eda46daa-11a9-bbae-2e7a-d514aa78bb29" name="Page-1">7V1bk5s6Ev41rjr7YBfizuNcMjmnKtmaymxV9jzKINvaMJYP4MxMfv0KLGFQg41tge3JjCsVWwgB+r5utVrdYmTdPb9+TvBq8ZVFJB6ZRvQ6su5Hpols0+X/5SVvmxLPNDYF84RGotK24In+IqJQVlvTiKS1ihljcUZX9cKQLZckzGplOEnYS73ajMX1q67wnICCpxDHsPQ7jbLFptR3jG35n4TOF/LKyBBHnrGsLArSBY7YS6XI+jSy7hLGss2359c7EuedJ/tlc95Dy9HyxhKyzLqcYJMwCs0onEUBJgEJx8gMNm38xPFaPO6/WUZnNMQZZUt+5JGuSEyXRDxB9ia75WVBM/K0wmH++4VDP7JuF9lzzH8h/pUleJn36+2MxvEdi1lSnGY9PHy6u+M3eDtPcET5jctjS7bMq5d9ZOR1Ypym4nuaJewHqbTkG/mHH4lwuiCRuO5PkmT87uObmM6XvCxj+Y3N2DJ7Evee11qwhP7iZVjeblFhQz1kid8P+JnGOWlvEppXvBV9xa9AXlshQCWwXCIIeyZZ8sariBNsSRshDKa3+fmyZZZpiSqLCqvswBKMFmyel01vAedfBOYt+LszbBNvSgzPN6JoOrZcAP/IdGN+zdsp/zLPv3wjIaH8meUBfpHyWFk5UUsi+lMWfRp/xTSunF45diirNiSQYogO4stt8WmlSMLWy6igUX42FsdCjit/9v4I4SiEsE0bMMJrIgTSwAegD1wHEOKJZLxgoxW4Gv4ATAXMCzoBJqVarwBDvBok8CiZVgUVtPqdTBeM/WjXAVci6r2peilMh0q2DqLMfByYKIqCEPu+740RHOgBILDHq3As8Cqv9/w6z828ySxmL+ECJ9lklbCQ5FjcNiHaV++a1r5xFKEmKfRO71wTdOU9TVc4CxdbiapKgy7D6cH65O4wnFQhMIq/wySpm/XUG6bBXuOoEVTkaBAZhACsn1ma0hWElA+JWXywRXyKQrOsIHh4aADomUZRfv3BdJpbQ8hH3VSaowEfONTdPP51OghtYjYU6e26IpMiUO1Rv4Hypg7K+7BLY/4svOgzWZIEZyxJq/SvdLT7zzqfthbdMk6LmdMNr4DM1evGBBDHVaMgr39SQ388JvmTLsg6/VfF0ti026JyhxvZqvNIUw9BrLpStKzhRjppNVS6kkRzIsWCJdmCzdkSx5+2pYomqnQ0WUY3uT+G/5zGLPyxKXqgcV04K8Jo3+efoh6/8//mTU4c+fNvcQXySrPNIdsTP/+WV+TfH0lC+YPnc4J9qjF/tt0g8a5g6ySUtYT8ZDiZk3IsagYzITHOuM1da6wJG3HqI6OFoAgSeF6NBEidTWxuQZxUdQEp7fh1/e0pzWyeDjRT8KR8mCPnliZ0NjzRmCx5b5oGF+qfNMrtJ1V0hXRGOMMp10ekRRorPIvxlMSPLKWFC6syJZSD5xelQjmIgkmkOtxOWZax5x5HA+TVpR15zsQBAu82yLsOGwiCJnkGQYNQnW9CN5S5g6T4DDHXh1hAC+gbW2e/JRKm1c3y7AkJOJv+jml2MA6H2/+djI69amyDFaRBfejWAlvdB2L6wznLrJkxJYFv+CHBBNv22LE+UDvKxTkkalDYHE+rEVpai45iLKbchsqkgVo6VXiZsFCNLibs/0iWvQlU8TpjhUNH3uAXliPYPpusMgLtsXqPs1jbB/iqDds29Gi3am3FHDWli3SPWavFHnWhOtBJtMujky7KOA3TnoZawYmUOV5jeDZA9iZOCI7eoC8vLZ79oTfkJa5V6JXJsCDHFnnjupH3rJ2jizExa0Jfrk0cq0xkFTabpUS/nnCgsfet5OhlWN3AdEj5XdDl/AuZZaLJ86x5WUMujkIN731o+KPk3O0m50YzFwbQ8C70XN+TaL26IJm8kPAEy+q26tyPBHrQffShO7sid1bd6ZkAuSuJBBosnuO8+MDZS4FMfsMfznSp+xSJaojAGc6VbkDE5GrrB2DiqLL6IVe+B8ALeAvtAdxOxkVakVu3U83pVNy5LgtTCkPNwlSD1trYcqLXSQ0zKm9mj9eJQ4DfKtVWeYV0x3WM+nXcQCHkpsFjZ6qQsdAoflpP0zChUxisxIU0q1M0ISn9hadFhRx58Xi8tnM7cu67KIhSlRRK6BaHP+aFRFSG8lnx18C6w3SKSPYQtzsqUyyqRGwR6V2OCUv2YembGJ3kmhAtj+seD7d+vha/BVztMADmGvQXqmqvrVe6RVtcnm7Tpb8khnvc5kPNkD0/dCI/MD1s+EEQOWO5Qqkrcqcd467w7MW5nWIaQ3bgGGNCIFE/445tqOOOstqhL/oG8EGmi/TLB8/RKdCDEMJxpobpIDPE0XRqTMOxc0ZCIGc4Qtj9m7f71jD7Vf26VL1UpXuWu/xzqXoZXP2BZB3J1viP3UC65wPSHQrIywOrh/XjZp3rKDrX7i/kAAI8UCTLdQB88vJRC8B+S9rdEADDGfhfywWd0oxB3977D9JE0uo8S2osXPy9i9dpdlE5emWE4NXk6CHHmihr/EbQEKIu9yuo4iwXTPTiDGXukZAErk/xdugqJaNtxk8YszVvdp9Hvbvc7Ui57OSdAA42HYC5rgqY1ZBR0ACX7fYBl17HRKtbvc1aPSZA63L9Um1Kb7eJu3FeDRG4od6f3YtT0hipDoISfVTFvsEpedXoty4K1+Bv5shZ0NfrhNqP/j7Zf1cuaRmxcVxw5gDoa/VTXB6OepZNd6NnnIpe85wJyVPaVkRbHJGwITVPVU1T1xjQD/jVkF9ahEyorPsNlj73mIS2WUcJGZMdOzS0rGnW53pjhXR6grEBxr7WEeSdLl32bP216RAlacxQmtCYW67SQq7ZfIj+waIfmFci+g3ZmyITHU71j4KZy2cqkKmgHhdhwG25mJtQ4f8Ugjy2T8b3gK2SUH3ENmWWyp5QOdSHq82B+Vb1XURVf9sXNu8VtH0ptOeDzanHF1kySuccHlLnAhYOr3mYrW0F0zD0tiwPnGPu5Qy2tPj+oW5d9bmQWDAI/gAu198F/PZdWfagP1g2tIq+q9fl+k4xrqLXEjjSQyiCYsO5yvpYjzMmV6sr9nqR1w+qaxwFKmjIbduEZYi9MZxry68dLKF9yHRaILRwnvUnvyQvufmJaYynNKZZfvPPLCIdohy2XZgjo3/bowtaBZdBQDIoyIdL4Mhze8KxOa+pngk4nydkjjPosqrzvJO8VbAIij+lkxt3m+otCdOob3DrwE2dfQ92vBq1pafjoZ/wM+9fqNZ66PTqLgDCqVTPNDf7BEHJhG3YZbjJW2T6p4MAAuwtrabHAFGQAN+7OxHmc1J8pH7TA9V9uyDysavpARoyejM9IDvModgxQDR7e4CYzsjatpeC7AkEME8k4fEKwPpQAP0ogKC++n68AlAb6qgADs2QbruOrhRpSL33lPV0Ju3SKfPVPXXDyKO1iwONa4B5bS5Tvj4OODWq3Su8GkrAt2Pkn9ERu26Ue2k0z27ZOsvfundXvtPQGME3FbDZjIZkErJlSFZZOgkFneDUuMnyF0YoTlebK8zoa35OfzaoW1/7CtyGsHHUMAdDGuKQW9M8f/upADLhCyUGmws0LOp/COslCisym5I8hpPWpvfcqQP5dlwNc/cUDffIZm24rHZ6HZJdUWInDrS7d79pMdAr/e80yKksO9GWtFBdTfjmcaakZSvqBoGAI03GpHrHcnuF3oxJp+ntqe+LlC3D5qWQsnzV8ums7JYkejInRYJOf5zssuXttXHyYuim2kCd6abaXO5AKlBcRxfdkOvZljlzncg2XBLhpteKTiYTwLj9oX2HBvKVMbcwJrBq9TXm3YrCDguITUm1kv9O0USGhYkYGJoML1tN10QONLyaXhGu5Y2AKsCy0SrA/Kf49/vBrAllV1EIZgAz5W09GPOfCcvfoLiV+Xw+8pVFJK/xfw==</diagram></mxfile>"><defs/><g transform="translate(0.5,0.5)"><rect x="427" y="0" width="230" height="493" fill="#ffeccf" stroke="#808080" stroke-dasharray="3 3" pointer-events="none"/><g transform="translate(479.5,7.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="124" height="13" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 13px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 126px; white-space: nowrap; word-wrap: normal; font-weight: bold; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Notification Pipeline</div></div></foreignObject><text x="62" y="13" fill="#000000" text-anchor="middle" font-size="13px" font-family="Arial" font-weight="bold">Notification Pipeline</text></switch></g><rect x="527" y="397" width="70" height="41" fill="#ffffff" stroke="#b3b3b3" pointer-events="none"/><g transform="translate(536.5,404.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="50" height="26" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 52px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b>Receiver</b><br /><div>E-Mail</div></div></div></foreignObject><text x="25" y="19" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial">[Not supported by viewer]</text></switch></g><rect x="527" y="452" width="70" height="30" fill="#ffffff" stroke="#b3b3b3" pointer-events="none"/><g transform="translate(530.5,459.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="62" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 62px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Set Notifies</div></div></foreignObject><text x="31" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial">Set Notifies</text></switch></g><rect x="442" y="397" width="70" height="40" fill="#ffffff" stroke="#b3b3b3" pointer-events="none"/><g transform="translate(451.5,404.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="50" height="26" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 52px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><div><b>Receiver</b></div><div>Webhook<br /></div></div></div></foreignObject><text x="25" y="19" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial">[Not supported by viewer]</text></switch></g><rect x="0" y="0" width="110" height="37" rx="2.22" ry="2.22" fill="#ffffff" stroke="#000000" pointer-events="none"/><rect x="267" y="0" width="110" height="150" fill="#fff3e6" stroke="#000000" pointer-events="none"/><g transform="translate(290.5,7.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="62" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 64px; white-space: nowrap; word-wrap: normal; font-weight: bold; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Dispatcher<br /></div></div></foreignObject><text x="31" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial" font-weight="bold">Dispatcher<br></text></switch></g><rect x="443" y="54" width="70" height="45" fill="#ffffff" stroke="#3399ff" pointer-events="none"/><g transform="translate(458.5,63.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="38" height="26" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 38px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Gossip<br />Settle</div></div></foreignObject><text x="19" y="19" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial">[Not supported by viewer]</text></switch></g><rect x="20" y="63" width="78" height="120" fill="#fff3e6" stroke="#000000" pointer-events="none"/><g transform="translate(48.5,116.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="20" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 22px; white-space: nowrap; word-wrap: normal; font-weight: bold; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">API</div></div></foreignObject><text x="10" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial" font-weight="bold">API</text></switch></g><rect x="7" y="6" width="110" height="37" rx="2.22" ry="2.22" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(17.5,11.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="88" height="26" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 90px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Alert Generators<br style="font-size: 12px" /><font style="font-size: 12px">(Prometheus)</font></div></div></foreignObject><text x="44" y="19" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial">[Not supported by viewer]</text></switch></g><path d="M 59 43 L 59 54.88" fill="none" stroke="#4d4d4d" stroke-miterlimit="10" pointer-events="none"/><path d="M 59 61.88 L 55.5 54.88 L 62.5 54.88 Z" fill="#4d4d4d" stroke="#4d4d4d" stroke-miterlimit="10" pointer-events="none"/><path d="M 147 154.5 C 147 146.5 207 146.5 207 154.5 L 207 192.5 C 207 200.5 147 200.5 147 192.5 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 147 154.5 C 147 160.5 207 160.5 207 154.5 M 147 157.5 C 147 163.5 207 163.5 207 157.5 M 147 160.5 C 147 166.5 207 166.5 207 160.5" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(148.5,168.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="56" height="26" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 56px; white-space: normal; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Silence Provider</div></div></foreignObject><text x="28" y="19" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial">Silence Provider</text></switch></g><rect x="443" y="159" width="70" height="30" fill="#ffffff" stroke="#b3b3b3" pointer-events="none"/><g transform="translate(455.5,166.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="44" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 44px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Silencer</div></div></foreignObject><text x="22" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial">Silencer</text></switch></g><rect x="443" y="204" width="70" height="30" fill="#ffffff" stroke="#b3b3b3" pointer-events="none"/><g transform="translate(459.5,211.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="36" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 38px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Router</div></div></foreignObject><text x="18" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial">Router</text></switch></g><rect x="442" y="262" width="70" height="30" fill="#ffffff" stroke="#3399ff" pointer-events="none"/><g transform="translate(464.5,269.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="24" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 24px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Wait</div></div></foreignObject><text x="12" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial">Wait</text></switch></g><rect x="527" y="262" width="70" height="30" fill="#ffffff" stroke="#3399ff" pointer-events="none"/><g transform="translate(549.5,269.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="24" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 24px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Wait</div></div></foreignObject><text x="12" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial">Wait</text></switch></g><path d="M 478 189 L 478 195.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 478 202.88 L 474.5 195.88 L 481.5 195.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 477 337 L 477 357 L 477 332 L 477 343.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 477 350.88 L 473.5 343.88 L 480.5 343.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 433.88 322 L 367 322" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 440.88 322 L 433.88 325.5 L 433.88 318.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(378.5,290.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="37" height="24" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">Already<br />sent?</div></div></foreignObject><text x="19" y="18" fill="#000000" text-anchor="middle" font-size="11px" font-family="Arial">Already<br>sent?</text></switch></g><rect x="442" y="352" width="70" height="30" fill="#ffffff" stroke="#b3b3b3" pointer-events="none"/><g transform="translate(462.5,359.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="28" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 30px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Retry</div></div></foreignObject><text x="14" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial">Retry</text></switch></g><path d="M 562 337 L 562 357 L 562 332 L 562 343.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 562 350.88 L 558.5 343.88 L 565.5 343.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><rect x="527" y="307" width="70" height="30" fill="#ffffff" stroke="#b3b3b3" pointer-events="none"/><g transform="translate(543.5,314.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="36" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 36px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Dedup</div></div></foreignObject><text x="18" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial">Dedup</text></switch></g><rect x="527" y="352" width="70" height="30" fill="#ffffff" stroke="#b3b3b3" pointer-events="none"/><g transform="translate(547.5,359.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="28" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 30px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Retry</div></div></foreignObject><text x="14" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial">Retry</text></switch></g><rect x="442" y="452" width="70" height="30" fill="#ffffff" stroke="#b3b3b3" pointer-events="none"/><g transform="translate(445.5,459.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="62" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 62px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Set Notifies</div></div></foreignObject><text x="31" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial">Set Notifies</text></switch></g><path d="M 307 303 C 307 295 367 295 367 303 L 367 341 C 367 349 307 349 307 341 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 307 303 C 307 309 367 309 367 303 M 307 306 C 307 312 367 312 367 306 M 307 309 C 307 315 367 315 367 309" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(308.5,316.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="56" height="26" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 56px; white-space: normal; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Notify Provider</div></div></foreignObject><text x="28" y="19" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial">Notify Provider</text></switch></g><path d="M 147 57 C 147 49 207 49 207 57 L 207 95 C 207 103 147 103 147 95 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 147 57 C 147 63 207 63 207 57 M 147 60 C 147 66 207 66 207 60 M 147 63 C 147 69 207 69 207 63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(148.5,70.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="56" height="26" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 56px; white-space: normal; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Alert Provider</div></div></foreignObject><text x="28" y="19" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial">Alert Provider</text></switch></g><path d="M 177 51 L 177 42 L 271.88 42" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 278.88 42 L 271.88 45.5 L 271.88 38.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(210.5,43.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="49" height="11" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">Subscribe</div></div></foreignObject><text x="25" y="11" fill="#000000" text-anchor="middle" font-size="11px" font-family="Arial">Subscribe</text></switch></g><path d="M 207 174 L 434.88 174" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 441.88 174 L 434.88 177.5 L 434.88 170.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 367 77 L 434.88 77" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 441.88 77 L 434.88 80.5 L 434.88 73.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 367 110 L 405 110 L 405 88 L 434.88 88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 441.88 88 L 434.88 91.5 L 434.88 84.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 477 292 L 477 298.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 477 305.88 L 473.5 298.88 L 480.5 298.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 562 292 L 562 298.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 562 305.88 L 558.5 298.88 L 565.5 298.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 477 382 L 477 388.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 477 395.88 L 473.5 388.88 L 480.5 388.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 562 382 L 562 388.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 562 395.88 L 558.5 388.88 L 565.5 388.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><rect x="443" y="114" width="70" height="30" fill="#ffffff" stroke="#b3b3b3" pointer-events="none"/><g transform="translate(456.5,121.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="42" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 44px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Inhibitor</div></div></foreignObject><text x="21" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial">Inhibitor</text></switch></g><rect x="130.5" y="282.5" width="93" height="79" fill="#fff3e6" stroke="#3399ff" pointer-events="none"/><g transform="translate(156.5,290.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="41" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 43px; white-space: nowrap; word-wrap: normal; font-weight: bold; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Cluster<br /></div></div></foreignObject><text x="21" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial" font-weight="bold">Cluster<br></text></switch></g><path d="M 159.25 319.5 C 146.65 319.5 143.5 331 153.58 333.3 C 143.5 338.36 154.84 349.4 163.03 344.8 C 168.7 354 187.6 354 193.9 344.8 C 206.5 344.8 206.5 335.6 198.63 331 C 206.5 321.8 193.9 312.6 182.88 317.2 C 175 310.3 162.4 310.3 159.25 319.5 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(160.5,325.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="29" height="11" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 29px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Peers</div></div></foreignObject><text x="15" y="11" fill="#000000" text-anchor="middle" font-size="11px" font-family="Arial">Peers</text></switch></g><path d="M 177 274.88 L 177 207.12" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 177 281.88 L 173.5 274.88 L 180.5 274.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 177 200.12 L 180.5 207.12 L 173.5 207.12 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 298.88 322 L 232.12 322" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 305.88 322 L 298.88 325.5 L 298.88 318.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 225.12 322 L 232.12 318.5 L 232.12 325.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 442 467 L 337 467 L 337 355.12" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 337 348.12 L 340.5 355.12 L 333.5 355.12 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 98 76 L 138.88 76" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 145.88 76 L 138.88 79.5 L 138.88 72.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(100.5,77.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="26" height="11" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">Store</div></div></foreignObject><text x="13" y="11" fill="#000000" text-anchor="middle" font-size="11px" font-family="Arial">Store</text></switch></g><path d="M 97 174 L 138.88 174" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 145.88 174 L 138.88 177.5 L 138.88 170.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(100.5,159.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="26" height="11" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">Store</div></div></foreignObject><text x="13" y="11" fill="#000000" text-anchor="middle" font-size="11px" font-family="Arial">Store</text></switch></g><g transform="translate(189.5,234.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="42" height="11" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Silences</div></div></foreignObject><text x="21" y="11" fill="#000000" text-anchor="middle" font-size="11px" font-family="Arial">Silences</text></switch></g><g transform="translate(242.5,325.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="54" height="24" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Notification<br />Logs</div></div></foreignObject><text x="27" y="18" fill="#000000" text-anchor="middle" font-size="11px" font-family="Arial">Notification<br>Logs</text></switch></g><path d="M 478 99 L 478 105.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 478 112.88 L 474.5 105.88 L 481.5 105.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 478 144 L 478 150.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 478 157.88 L 474.5 150.88 L 481.5 150.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 478 234 L 477 234 L 477 253.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 477 260.88 L 473.5 253.88 L 480.5 253.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 478 242 L 562 242 L 562 253.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 562 260.88 L 558.5 253.88 L 565.5 253.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 537 242 L 627 242 L 627 253.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 627 260.88 L 623.5 253.88 L 630.5 253.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><rect x="442" y="307" width="70" height="30" fill="#ffffff" stroke="#b3b3b3" pointer-events="none"/><g transform="translate(458.5,314.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="36" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 36px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Dedup</div></div></foreignObject><text x="18" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial">Dedup</text></switch></g><rect x="1" y="458" width="176" height="30" rx="4.5" ry="4.5" fill="#ffffff" stroke="#3399ff" pointer-events="none"/><g transform="translate(34.5,467.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="108" height="11" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 110px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">High Availability mode<br /></div></div></foreignObject><text x="54" y="11" fill="#000000" text-anchor="middle" font-size="11px" font-family="Arial">High Availability mode<br></text></switch></g><rect x="280" y="30" width="87" height="24" fill="#ffffff" stroke="#999999" pointer-events="none"/><g transform="translate(295.5,35.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="55" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 57px; white-space: nowrap; word-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Aggregate</div></div></foreignObject><text x="28" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Arial">Aggregate</text></switch></g><rect x="307" y="63" width="60" height="28" fill="#ffffff" stroke="#999999" pointer-events="none"/><g transform="translate(311.5,71.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="28" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 29px; white-space: nowrap; word-wrap: normal;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Group</div></div></foreignObject><text x="14" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Arial">Group</text></switch></g><path d="M 489 397 L 489 390.12" fill="none" stroke="#cc0000" stroke-miterlimit="10" pointer-events="none"/><path d="M 489 383.12 L 492.5 390.12 L 485.5 390.12 Z" fill="#cc0000" stroke="#cc0000" stroke-miterlimit="10" pointer-events="none"/><path d="M 477 437 L 477 443.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 477 450.88 L 473.5 443.88 L 480.5 443.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 574 397 L 574 390.12" fill="none" stroke="#cc0000" stroke-miterlimit="10" pointer-events="none"/><path d="M 574 383.12 L 577.5 390.12 L 570.5 390.12 Z" fill="#cc0000" stroke="#cc0000" stroke-miterlimit="10" pointer-events="none"/><path d="M 562 438 L 562 443.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 562 450.88 L 558.5 443.88 L 565.5 443.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 356.62 80.28 C 356.77 80.41 356.79 80.65 356.64 80.83 C 356.51 80.96 356.3 81.03 356.11 80.9 L 352.62 78.21 C 352.54 78.13 352.47 78.05 352.48 77.89 L 352.48 72.03 C 352.48 71.79 352.69 71.63 352.88 71.63 C 353.13 71.63 353.28 71.86 353.28 72.03 L 353.28 77.72 Z M 353.04 84.18 C 356.98 84.18 359.67 80.86 359.67 77.51 C 359.67 73.44 356.32 70.83 353.02 70.83 C 348.64 70.83 346.34 74.62 346.34 77.32 C 346.34 81.87 349.95 84.18 353.04 84.18 Z M 352.96 85.5 C 349.02 85.5 345.1 82.48 345 77.41 C 345 73.52 348.27 69.5 352.97 69.5 C 357.1 69.5 361 72.7 361 77.54 C 361 81.84 357.53 85.5 352.96 85.5 Z" fill="#505050" stroke="none" pointer-events="none"/><rect x="307" y="96" width="60" height="28" fill="#ffffff" stroke="#999999" pointer-events="none"/><g transform="translate(311.5,104.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="28" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 29px; white-space: nowrap; word-wrap: normal;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Group</div></div></foreignObject><text x="14" y="10" fill="#000000" text-anchor="middle" font-size="10px" font-family="Arial">Group</text></switch></g><path d="M 356.62 113.28 C 356.77 113.41 356.79 113.65 356.64 113.83 C 356.51 113.96 356.3 114.03 356.11 113.9 L 352.62 111.21 C 352.54 111.13 352.47 111.05 352.48 110.89 L 352.48 105.03 C 352.48 104.79 352.69 104.63 352.88 104.63 C 353.13 104.63 353.28 104.86 353.28 105.03 L 353.28 110.72 Z M 353.04 117.18 C 356.98 117.18 359.67 113.86 359.67 110.51 C 359.67 106.44 356.32 103.83 353.02 103.83 C 348.64 103.83 346.34 107.62 346.34 110.32 C 346.34 114.87 349.95 117.18 353.04 117.18 Z M 352.96 118.5 C 349.02 118.5 345.1 115.48 345 110.41 C 345 106.52 348.27 102.5 352.97 102.5 C 357.1 102.5 361 105.7 361 110.54 C 361 114.84 357.53 118.5 352.96 118.5 Z" fill="#505050" stroke="none" pointer-events="none"/><path d="M 287 55 L 287 77 L 300.63 77" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 305.88 77 L 298.88 80.5 L 300.63 77 L 298.88 73.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 287 73 L 287 110 L 300.63 110" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 305.88 110 L 298.88 113.5 L 300.63 110 L 298.88 106.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 287 101 L 287 138 L 300.63 138" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 305.88 138 L 298.88 141.5 L 300.63 138 L 298.88 134.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(331.5,129.5)rotate(90,6.5,8)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="13" height="16" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 15px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; font-weight: bold; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">...</div></div></foreignObject><text x="7" y="16" fill="#000000" text-anchor="middle" font-size="15px" font-family="Arial" font-weight="bold">...</text></switch></g><g transform="translate(616.5,265.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="21" height="16" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 15px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; font-weight: bold; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">. . .</div></div></foreignObject><text x="11" y="16" fill="#000000" text-anchor="middle" font-size="15px" font-family="Arial" font-weight="bold">. . .</text></switch></g></g></svg>
\ No newline at end of file
--- /dev/null
+<mxfile userAgent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36" version="8.6.9" editor="www.draw.io" type="google"><diagram id="eda46daa-11a9-bbae-2e7a-d514aa78bb29" name="Page-1">7V1bk9o6Ev41VO0+QPlu8ziXkHOqkq2pzFZlz6OwBWjjQaxtMpPz61eyLWOrZTAgG5hM5iEgy7Ksr7vVVzGyH17ePidos/pKIxyPLCN6G9mPI8syHctj//GWX0WLbxlFwzIhUdlp1/BM/sZlo+i2JRFOGx0zSuOMbJqNIV2vcZg12lCS0NdmtwWNm0/doCUGDc8himHrdxJlq6I1cI1d+x+YLFfiyaZRXnlBonPZkK5QRF9rTfankf2QUJoVn17eHnDMF0+sS3HfrOVqNbEEr7MuNzg4jEIrChfRFOEpDsemNS3G+Inibfm6/6IZWZAQZYSu2ZUnssExWePyDbJfYlleVyTDzxsU8u+vDPqRfb/KXmL2zWQfaYLWfF3vFySOH2hMk/w2ezb79PDAJni/TFBE2MTFtTVd8+7VGhm8T4zStPycZgn9gWsjBQb/Y1cilK5wVD73J04yNvv4LibLNWvLKJ/Ygq6z53LuvNeKJuRv1obEdPMOBemZdvl9hl5IzIn2LiG84325VuwJ+K0VArMClnEEpi84S36xLuUNjiCbkhksv/j6uqMsyy67rGpU5UztkqJLal5WQ+8AZx9KzFvw9xbIwf4cG35gRNF8bHsA/pHlxeyZ93P2Yck/fMMhJuydxQX2kOpa1TmRWyLyUzR9Gn9FJK7dXrt2LFUVRCDY0DyKXu7zv1YSSeh2HeVkxO9G5bWQ4crevT+CcCWCcCwHUISvIghTAz0AeeC5gCCeccYaCqnAxPAHYDJg/rQTYIKr9TIwxEvBgSfxtMyoYNTveL6i9Ee7DLgRVu9N1AtmOpazdRDKIkBTy4yiaYiCIPDHJtzoASBwxetwrNCG93t5W3I1b7KI6Wu4Qkk22SQ0xByLexWifa2uZR/aR01TxYX++YtrgaV8JOkGZeFqx1F1btClOM3sT94exUlmAiP/dxwnddOeesN0elA5UoJquhpYxjQBrJ9pmpINhJRtiVl8tEZ8jkCz7el0NlMA9EKiiD9/MJnmNRAKzG4izdWAD9zq7p7+PB+ENjYbiuidpiATLFBf0UBB8pYOkg/gksbsXVjTZ7zGCcpoktbJv7bQ3v+23GzNl2Wc5pbTHetgWpu3QgUor8tKAe9/1kD/eEr4m67wNv1nTdMoxm0RucPtbHU70tJDIHZTKNr2cDud0BpqS4mjJRZsQZNsRZd0jeJPu1ZJEtUWGq+jO+6PYV/nMQ1/FE0zEjeZs8aMziP/y/uxmf+HDzlxxde/yifgN5IVlxy//PqXeCL7/IQTwl6c2wSHRCN/t/0gsaWg2yQUvUr+yVCyxNVepAYzwTHKmM7dGEyFTXnrEyU5o5RE4PsNIjBla6KYQnlT3QUkjRM05bcvDVO8HRgmp5PqZU60LS3obHgmMV6z1bQMxtQ/ScT1J5l1S+6MUIZSJo9wCzfW6CxGcxw/0ZTkLqyaSSg2zy9Sh2oTBUakvN3OaZbRlx53A9NvcrvpuxMXMLyn4HcdOhAETdAZBA1CdTmDbih1xxTsM4StD7GAGtA3us1+SyQsu5vm2RMS0Jr+jkh2NA7H6/+dlI6DYqzACpJBc+vWAlvTB2IFAzrLAGwOtNxb9xvykoeF6nCpV7FtU6m2inw7ukfhj2W+vDVUF/k/1iV/2F26KcJXuTtTfFmQNw7IfTmfx1WW8bjXHV8GaxZGa2tCQrpeEAZcMgnZE60Z3yvZf7ydqe+zIgg2RutovF1zt1+K4jEK+TzTMe80TrmPd2a5Hl9TtseyzTqYbNbLo2i08jccpFGzRqMxXmQ55WWoXDgz0ER8nt1UmlS2laWwrUTbOcRnL4w5ngZGEGKEkeOMXftDZJzkX7+syHB9gNA5FlBlqriSpZIyBT4T1lHl0WNtpXlkdLGf/ouz7FeJKtpmNPcmigl+oRzBdleGzKD7TK7RSeZSu3ZZN6Da9B7tJpUj2UKW8M8fsKm0GEMeFAc6Ce36yEkXybgKm1vRa3omyZwuMXwHIHsXJxhFv6AjOc3ffdYb8gLXOvSSJ6Ykjh3yxm0j79t7dxdjYjWYvgqMnSpMRBe6WORalGY54UJL41tFo9dh8gHVIWWzIOvll1yzy4e8TMDVHjIyDyW8/yHhT+JzrxufG2paGEDCezBs8oij7eaKePJKcmNsu1vKQz8c6EPf5Yfs7IrcRWWnDx01N5KGNlgy0WXxgdZLjgyf8EckR8g+iaMU6V/DxXEMiJgI9X8AVl6VQm8i7WIAvIC30BnA7WRcpRa5czs1nE75zHVpmIIZGhqmnDHZRi1nep3kHLdqMge8TgwC9KvWbcM7pHueYzSf400lgiwGPNVShRQLleLn7TwNEzKHmXKMSbMmiSY4JX+jed6BI1++Huvt3o/cxy4CohIlHQIuMtUdJ1PKSqNyuqOqvqdOiC0svc8xYYs1rHwTo7NcE+XI46bHw2ver8VvAaMdBsBcg/wy69Jr55VukRbXJ9t0yS+B4QG3+VAWsh+EbhRMLR8ZwXQauWMRHteVNtaOcVd4DuLcTmIa88XgHmNBIM1+9h3HkPcdKdqhL/UL0IOoVeqXHnxXJ0MPQhCuOzcs17RCFM3nxjwcuxckCNMdjiCc/tXbQzHMfkW/LlEvROmBcFdwKVEvMvs/kGwi2Zr/sR9I73JAekMBeX1g9RA/VstcV5K5Tn8pBxDggTJZbgPgs8NHLQAHLTWfQwAMLfA/1ysyJxmFvr33nyFsCq3zInXZMPj7EG/T7KoKRKsMwZspEDVdeyLF+I2poj5CHJZRx1kETPTiDHnuCeMExqfYOGST4tGu3CyM6ZYn9mpL+NxT73tURm7lYNMBmOfJgNmKchYFXI7XB1x6HROtbvU2bfWUBK3r9Uu1Cb39Km7hvBoicUOen9OLU9IYyQ6CCn2zjr3CKXnT6LcGhRvwq2nkIujrdUIdRv8Q778rl7TI2DgtOXMA9LX6Ka4PRz1h0/3oGeeip7aZTHFLW0S0xREJB5KLpOUzEjQm9AP6UhQ35ykTMtX9BqHPAyqhqMKr/M7GZM/xIC0xzaatN5aITk8yNsA40LqDvNPQZc/aX5sMkYrGDGkIjQcbyGQhYjYfrH8060+tG2F9RfVmeQwCNPVPgpnxZ1oiMwLFsS21mEWq8L9zRh47Z+N7xDldZnPHtkSVyoFUObMPV5sL662aR9jK/rYvdNkraIdKaC8Hm9vML7JFls4lPKTuFQQOb3mbbZxDpNh6W8IDl7C93MFCi+8f6taoz5XkgkHwB3C5/i7gtx8JdAD9waqhZfQ9vS7Xd4pxHb2WxJEeUhEkHc6T4mM9WkyeVlfs7SKvH1TPOAlUMJDXdgjLEGdjuLdWXztYQfuQ5bSAaaGd9Qd7JGu5+4lIjOYkJhmf/AuNcIcsh90ScmT0H3t0RVFwkQQkkoICGAI3fa8nHNV1Tc1KwOUywUuUQZdVk8478VsNi2n+T1pk5WlTvRVhGs3TlV14onjgw4WXs7b0LDz0E35m6wvFWg+LXj8FoHQqNSvNrT5BkCphFcewqbxFOo5hgyCofvFGWv+PIwAvfQTgeGpoIj3Hl/KPTFchfFUHrGugPlDeYWtVfAfIwQUIPzzsQ/hyiq/ZjCyAvNuuii8YyOhN8YXUAUXR7dZSHCkbulLOoRS0Tv6QIlllAH8IhNj+EAD9CIBpM/fjdAEgD9RRABxbn9/2HF0F+pD03lPN3YWkS6e6a+/c40pPli4uNO1Uyu1Omat+ORO41OrLW/rUpHID1+B/oxPOfKnUYrU2TbcZ/8HRh+rnXI0R/JEWuliQEDNldx3iTZZOwpKcoGNGZXeWGifQsHuzgLxm5HXqKYoWTIUHwNSQBd9aZPzbG6KmBX9Lpy9LFKLQ4QTgD2a9AmY1LVWJ0XDcqvqJT3kj3+2rIbfPSXiANxvbZX3Rm5Dsy1E8c6Pdf/ZSi4JeW39Xwaei7Uxd0jabYiKwTlMlbUcSNyZId9OkTMozFod79KZMuh3caDdOlC3b5rUQZfUr8+dTZbcS5bNpsiwP648muxy4fGs0eTXkJutAnclN1rm8gURg+Rxd5GZ6vmNbC8+NHMPDEVL9ovJkMgEUdzix9Ng00irjG2ak1rU+ZdV32dghfK0q6Rb07za99fqc9SZw1kMF3VYp6McHStnXhPIfFt3RA9dVv9II8x7/Bw==</diagram></mxfile>
\ No newline at end of file
--- /dev/null
+global:
+ # The smarthost and SMTP sender used for mail notifications.
+ smtp_smarthost: 'localhost:25'
+ smtp_from: 'alertmanager@example.org'
+ smtp_auth_username: 'alertmanager'
+ smtp_auth_password: 'password'
+ # The auth token for Hipchat.
+ hipchat_auth_token: '1234556789'
+ # Alternative host for Hipchat.
+ hipchat_api_url: 'https://hipchat.foobar.org/'
+
+# The directory from which notification templates are read.
+templates:
+- '/etc/alertmanager/template/*.tmpl'
+
+# The root route on which each incoming alert enters.
+route:
+ # The labels by which incoming alerts are grouped together. For example,
+ # multiple alerts coming in for cluster=A and alertname=LatencyHigh would
+ # be batched into a single group.
+ group_by: ['alertname', 'cluster', 'service']
+
+ # When a new group of alerts is created by an incoming alert, wait at
+ # least 'group_wait' to send the initial notification.
+ # This way ensures that you get multiple alerts for the same group that start
+ # firing shortly after another are batched together on the first
+ # notification.
+ group_wait: 30s
+
+ # When the first notification was sent, wait 'group_interval' to send a batch
+ # of new alerts that started firing for that group.
+ group_interval: 5m
+
+ # If an alert has successfully been sent, wait 'repeat_interval' to
+ # resend them.
+ repeat_interval: 3h
+
+ # A default receiver
+ receiver: team-X-mails
+
+ # All the above attributes are inherited by all child routes and can
+ # overwritten on each.
+
+ # The child route trees.
+ routes:
+ # This routes performs a regular expression match on alert labels to
+ # catch alerts that are related to a list of services.
+ - match_re:
+ service: ^(foo1|foo2|baz)$
+ receiver: team-X-mails
+ # The service has a sub-route for critical alerts, any alerts
+ # that do not match, i.e. severity != critical, fall-back to the
+ # parent node and are sent to 'team-X-mails'
+ routes:
+ - match:
+ severity: critical
+ receiver: team-X-pager
+ - match:
+ service: files
+ receiver: team-Y-mails
+
+ routes:
+ - match:
+ severity: critical
+ receiver: team-Y-pager
+
+ # This route handles all alerts coming from a database service. If there's
+ # no team to handle it, it defaults to the DB team.
+ - match:
+ service: database
+ receiver: team-DB-pager
+ # Also group alerts by affected database.
+ group_by: [alertname, cluster, database]
+ routes:
+ - match:
+ owner: team-X
+ receiver: team-X-pager
+ - match:
+ owner: team-Y
+ receiver: team-Y-pager
+
+
+# Inhibition rules allow to mute a set of alerts given that another alert is
+# firing.
+# We use this to mute any warning-level notifications if the same alert is
+# already critical.
+inhibit_rules:
+- source_match:
+ severity: 'critical'
+ target_match:
+ severity: 'warning'
+ # Apply inhibition if the alertname is the same.
+ equal: ['alertname', 'cluster', 'service']
+
+
+receivers:
+- name: 'team-X-mails'
+ email_configs:
+ - to: 'team-X+alerts@example.org'
+
+- name: 'team-X-pager'
+ email_configs:
+ - to: 'team-X+alerts-critical@example.org'
+ pagerduty_configs:
+ - service_key: <team-X-key>
+
+- name: 'team-Y-mails'
+ email_configs:
+ - to: 'team-Y+alerts@example.org'
+
+- name: 'team-Y-pager'
+ pagerduty_configs:
+ - service_key: <team-Y-key>
+
+- name: 'team-DB-pager'
+ pagerduty_configs:
+ - service_key: <team-DB-key>
+
+- name: 'team-X-hipchat'
+ hipchat_configs:
+ - auth_token: <auth_token>
+ room_id: 85
+ message_format: html
+ notify: true
--- /dev/null
+alerts1='[
+ {
+ "labels": {
+ "alertname": "DiskRunningFull",
+ "dev": "sda1",
+ "instance": "example1"
+ },
+ "annotations": {
+ "info": "The disk sda1 is running full",
+ "summary": "please check the instance example1"
+ }
+ },
+ {
+ "labels": {
+ "alertname": "DiskRunningFull",
+ "dev": "sda2",
+ "instance": "example1"
+ },
+ "annotations": {
+ "info": "The disk sda2 is running full",
+ "summary": "please check the instance example1",
+ "runbook": "the following link http://test-url should be clickable"
+ }
+ },
+ {
+ "labels": {
+ "alertname": "DiskRunningFull",
+ "dev": "sda1",
+ "instance": "example2"
+ },
+ "annotations": {
+ "info": "The disk sda1 is running full",
+ "summary": "please check the instance example2"
+ }
+ },
+ {
+ "labels": {
+ "alertname": "DiskRunningFull",
+ "dev": "sdb2",
+ "instance": "example2"
+ },
+ "annotations": {
+ "info": "The disk sdb2 is running full",
+ "summary": "please check the instance example2"
+ }
+ },
+ {
+ "labels": {
+ "alertname": "DiskRunningFull",
+ "dev": "sda1",
+ "instance": "example3",
+ "severity": "critical"
+ }
+ },
+ {
+ "labels": {
+ "alertname": "DiskRunningFull",
+ "dev": "sda1",
+ "instance": "example3",
+ "severity": "warning"
+ }
+ }
+]'
+curl -XPOST -d"$alerts1" http://localhost:9093/api/v1/alerts
+curl -XPOST -d"$alerts1" http://localhost:9094/api/v1/alerts
+curl -XPOST -d"$alerts1" http://localhost:9095/api/v1/alerts
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "io/ioutil"
+ "log"
+ "net/http"
+)
+
+func main() {
+ http.ListenAndServe(":5001", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ b, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ panic(err)
+ }
+ defer r.Body.Close()
+ var buf bytes.Buffer
+ if err := json.Indent(&buf, b, " >", " "); err != nil {
+ panic(err)
+ }
+ log.Println(buf.String())
+ }))
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package inhibit
+
+import (
+ "context"
+ "sync"
+ "time"
+
+ "github.com/go-kit/kit/log"
+ "github.com/go-kit/kit/log/level"
+ "github.com/oklog/oklog/pkg/group"
+ "github.com/prometheus/common/model"
+
+ "github.com/prometheus/alertmanager/config"
+ "github.com/prometheus/alertmanager/provider"
+ "github.com/prometheus/alertmanager/types"
+)
+
+// An Inhibitor determines whether a given label set is muted
+// based on the currently active alerts and a set of inhibition rules.
+type Inhibitor struct {
+ alerts provider.Alerts
+ rules []*InhibitRule
+ marker types.Marker
+ logger log.Logger
+
+ mtx sync.RWMutex
+ cancel func()
+}
+
+// NewInhibitor returns a new Inhibitor.
+func NewInhibitor(ap provider.Alerts, rs []*config.InhibitRule, mk types.Marker, logger log.Logger) *Inhibitor {
+ ih := &Inhibitor{
+ alerts: ap,
+ marker: mk,
+ logger: logger,
+ }
+ for _, cr := range rs {
+ r := NewInhibitRule(cr)
+ ih.rules = append(ih.rules, r)
+ }
+ return ih
+}
+
+func (ih *Inhibitor) runGC(ctx context.Context) {
+ for {
+ select {
+ case <-time.After(15 * time.Minute):
+ for _, r := range ih.rules {
+ r.gc()
+ }
+ case <-ctx.Done():
+ return
+ }
+ }
+}
+
+func (ih *Inhibitor) run(ctx context.Context) {
+ it := ih.alerts.Subscribe()
+ defer it.Close()
+
+ for {
+ select {
+ case <-ctx.Done():
+ return
+ case a := <-it.Next():
+ if err := it.Err(); err != nil {
+ level.Error(ih.logger).Log("msg", "Error iterating alerts", "err", err)
+ continue
+ }
+ // Update the inhibition rules' cache.
+ for _, r := range ih.rules {
+ if r.SourceMatchers.Match(a.Labels) {
+ r.set(a)
+ }
+ }
+ }
+ }
+}
+
+// Run the Inihibitor's background processing.
+func (ih *Inhibitor) Run() {
+ var (
+ g group.Group
+ ctx context.Context
+ )
+
+ ih.mtx.Lock()
+ ctx, ih.cancel = context.WithCancel(context.Background())
+ ih.mtx.Unlock()
+ gcCtx, gcCancel := context.WithCancel(ctx)
+ runCtx, runCancel := context.WithCancel(ctx)
+
+ g.Add(func() error {
+ ih.runGC(gcCtx)
+ return nil
+ }, func(err error) {
+ gcCancel()
+ })
+ g.Add(func() error {
+ ih.run(runCtx)
+ return nil
+ }, func(err error) {
+ runCancel()
+ })
+
+ g.Run()
+}
+
+// Stop the Inhibitor's background processing.
+func (ih *Inhibitor) Stop() {
+ if ih == nil {
+ return
+ }
+
+ ih.mtx.RLock()
+ defer ih.mtx.RUnlock()
+ if ih.cancel != nil {
+ ih.cancel()
+ }
+}
+
+// Mutes returns true iff the given label set is muted.
+func (ih *Inhibitor) Mutes(lset model.LabelSet) bool {
+ fp := lset.Fingerprint()
+
+ for _, r := range ih.rules {
+ // Only inhibit if target matchers match but source matchers don't.
+ if inhibitedByFP, eq := r.hasEqual(lset); !r.SourceMatchers.Match(lset) && r.TargetMatchers.Match(lset) && eq {
+ ih.marker.SetInhibited(fp, inhibitedByFP.String())
+ return true
+ }
+ }
+ ih.marker.SetInhibited(fp)
+
+ return false
+}
+
+// An InhibitRule specifies that a class of (source) alerts should inhibit
+// notifications for another class of (target) alerts if all specified matching
+// labels are equal between the two alerts. This may be used to inhibit alerts
+// from sending notifications if their meaning is logically a subset of a
+// higher-level alert.
+type InhibitRule struct {
+ // The set of Filters which define the group of source alerts (which inhibit
+ // the target alerts).
+ SourceMatchers types.Matchers
+ // The set of Filters which define the group of target alerts (which are
+ // inhibited by the source alerts).
+ TargetMatchers types.Matchers
+ // A set of label names whose label values need to be identical in source and
+ // target alerts in order for the inhibition to take effect.
+ Equal map[model.LabelName]struct{}
+
+ mtx sync.RWMutex
+ // Cache of alerts matching source labels.
+ scache map[model.Fingerprint]*types.Alert
+}
+
+// NewInhibitRule returns a new InihibtRule based on a configuration definition.
+func NewInhibitRule(cr *config.InhibitRule) *InhibitRule {
+ var (
+ sourcem types.Matchers
+ targetm types.Matchers
+ )
+
+ for ln, lv := range cr.SourceMatch {
+ sourcem = append(sourcem, types.NewMatcher(model.LabelName(ln), lv))
+ }
+ for ln, lv := range cr.SourceMatchRE {
+ sourcem = append(sourcem, types.NewRegexMatcher(model.LabelName(ln), lv.Regexp))
+ }
+
+ for ln, lv := range cr.TargetMatch {
+ targetm = append(targetm, types.NewMatcher(model.LabelName(ln), lv))
+ }
+ for ln, lv := range cr.TargetMatchRE {
+ targetm = append(targetm, types.NewRegexMatcher(model.LabelName(ln), lv.Regexp))
+ }
+
+ equal := map[model.LabelName]struct{}{}
+ for _, ln := range cr.Equal {
+ equal[ln] = struct{}{}
+ }
+
+ return &InhibitRule{
+ SourceMatchers: sourcem,
+ TargetMatchers: targetm,
+ Equal: equal,
+ scache: map[model.Fingerprint]*types.Alert{},
+ }
+}
+
+// set the alert in the source cache.
+func (r *InhibitRule) set(a *types.Alert) {
+ r.mtx.Lock()
+ defer r.mtx.Unlock()
+
+ r.scache[a.Fingerprint()] = a
+}
+
+// hasEqual checks whether the source cache contains alerts matching
+// the equal labels for the given label set.
+func (r *InhibitRule) hasEqual(lset model.LabelSet) (model.Fingerprint, bool) {
+ r.mtx.RLock()
+ defer r.mtx.RUnlock()
+
+Outer:
+ for fp, a := range r.scache {
+ // The cache might be stale and contain resolved alerts.
+ if a.Resolved() {
+ continue
+ }
+ for n := range r.Equal {
+ if a.Labels[n] != lset[n] {
+ continue Outer
+ }
+ }
+ return fp, true
+ }
+ return model.Fingerprint(0), false
+}
+
+// gc clears out resolved alerts from the source cache.
+func (r *InhibitRule) gc() {
+ r.mtx.Lock()
+ defer r.mtx.Unlock()
+
+ for fp, a := range r.scache {
+ if a.Resolved() {
+ delete(r.scache, fp)
+ }
+ }
+}
--- /dev/null
+// Copyright 2016 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package inhibit
+
+import (
+ "reflect"
+ "testing"
+ "time"
+
+ "github.com/go-kit/kit/log"
+ "github.com/kylelemons/godebug/pretty"
+ "github.com/prometheus/common/model"
+
+ "github.com/prometheus/alertmanager/config"
+ "github.com/prometheus/alertmanager/provider"
+ "github.com/prometheus/alertmanager/types"
+)
+
+var nopLogger = log.NewNopLogger()
+
+func TestInhibitRuleHasEqual(t *testing.T) {
+ t.Parallel()
+
+ now := time.Now()
+ cases := []struct {
+ initial map[model.Fingerprint]*types.Alert
+ equal model.LabelNames
+ input model.LabelSet
+ result bool
+ }{
+ {
+ // No source alerts at all.
+ initial: map[model.Fingerprint]*types.Alert{},
+ input: model.LabelSet{"a": "b"},
+ result: false,
+ },
+ {
+ // No equal labels, any source alerts satisfies the requirement.
+ initial: map[model.Fingerprint]*types.Alert{1: &types.Alert{}},
+ input: model.LabelSet{"a": "b"},
+ result: true,
+ },
+ {
+ // Matching but already resolved.
+ initial: map[model.Fingerprint]*types.Alert{
+ 1: &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{"a": "b", "b": "f"},
+ StartsAt: now.Add(-time.Minute),
+ EndsAt: now.Add(-time.Second),
+ },
+ },
+ 2: &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{"a": "b", "b": "c"},
+ StartsAt: now.Add(-time.Minute),
+ EndsAt: now.Add(-time.Second),
+ },
+ },
+ },
+ equal: model.LabelNames{"a", "b"},
+ input: model.LabelSet{"a": "b", "b": "c"},
+ result: false,
+ },
+ {
+ // Matching and unresolved.
+ initial: map[model.Fingerprint]*types.Alert{
+ 1: &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{"a": "b", "c": "d"},
+ StartsAt: now.Add(-time.Minute),
+ EndsAt: now.Add(-time.Second),
+ },
+ },
+ 2: &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{"a": "b", "c": "f"},
+ StartsAt: now.Add(-time.Minute),
+ EndsAt: now.Add(time.Hour),
+ },
+ },
+ },
+ equal: model.LabelNames{"a"},
+ input: model.LabelSet{"a": "b"},
+ result: true,
+ },
+ {
+ // Equal label does not match.
+ initial: map[model.Fingerprint]*types.Alert{
+ 1: &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{"a": "c", "c": "d"},
+ StartsAt: now.Add(-time.Minute),
+ EndsAt: now.Add(-time.Second),
+ },
+ },
+ 2: &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{"a": "c", "c": "f"},
+ StartsAt: now.Add(-time.Minute),
+ EndsAt: now.Add(-time.Second),
+ },
+ },
+ },
+ equal: model.LabelNames{"a"},
+ input: model.LabelSet{"a": "b"},
+ result: false,
+ },
+ }
+
+ for _, c := range cases {
+ r := &InhibitRule{
+ Equal: map[model.LabelName]struct{}{},
+ scache: map[model.Fingerprint]*types.Alert{},
+ }
+ for _, ln := range c.equal {
+ r.Equal[ln] = struct{}{}
+ }
+ for k, v := range c.initial {
+ r.scache[k] = v
+ }
+
+ if _, have := r.hasEqual(c.input); have != c.result {
+ t.Errorf("Unexpected result %t, expected %t", have, c.result)
+ }
+ if !reflect.DeepEqual(r.scache, c.initial) {
+ t.Errorf("Cache state unexpectedly changed")
+ t.Errorf(pretty.Compare(r.scache, c.initial))
+ }
+ }
+}
+
+func TestInhibitRuleMatches(t *testing.T) {
+ t.Parallel()
+
+ // Simple inhibut rule
+ cr := config.InhibitRule{
+ SourceMatch: map[string]string{"s": "1"},
+ TargetMatch: map[string]string{"t": "1"},
+ Equal: model.LabelNames{"e"},
+ }
+ m := types.NewMarker()
+ ih := NewInhibitor(nil, []*config.InhibitRule{&cr}, m, nopLogger)
+ ir := ih.rules[0]
+ now := time.Now()
+ // Active alert that matches the source filter
+ sourceAlert := types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{"s": "1", "e": "1"},
+ StartsAt: now.Add(-time.Minute),
+ EndsAt: now.Add(time.Hour),
+ },
+ }
+ ir.scache = map[model.Fingerprint]*types.Alert{1: &sourceAlert}
+
+ cases := []struct {
+ target model.LabelSet
+ expected bool
+ }{
+ {
+ // Matches target filter, inhibited
+ target: model.LabelSet{"t": "1", "e": "1"},
+ expected: true,
+ },
+ {
+ // Matches target filter (plus noise), inhibited
+ target: model.LabelSet{"t": "1", "t2": "1", "e": "1"},
+ expected: true,
+ },
+ {
+ // Doesn't match target filter, not inhibited
+ target: model.LabelSet{"t": "0", "e": "1"},
+ expected: false,
+ },
+ {
+ // Matches both source and target filters, not inhibited
+ target: model.LabelSet{"s": "1", "t": "1", "e": "1"},
+ expected: false,
+ },
+ {
+ // Matches target filter, equal label doesn't match, not inhibited
+ target: model.LabelSet{"t": "1", "e": "0"},
+ expected: false,
+ },
+ }
+
+ for _, c := range cases {
+ if actual := ih.Mutes(c.target); actual != c.expected {
+ t.Errorf("Expected (*Inhibitor).Mutes(%v) to return %t but got %t", c.target, c.expected, actual)
+ }
+ }
+}
+
+func TestInhibitRuleGC(t *testing.T) {
+ // TODO(fabxc): add now() injection function to Resolved() to remove
+ // dependency on machine time in this test.
+ now := time.Now()
+ newAlert := func(start, end time.Duration) *types.Alert {
+ return &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{"a": "b"},
+ StartsAt: now.Add(start * time.Minute),
+ EndsAt: now.Add(end * time.Minute),
+ },
+ }
+ }
+
+ before := map[model.Fingerprint]*types.Alert{
+ 0: newAlert(-10, -5),
+ 1: newAlert(10, 20),
+ 2: newAlert(-10, 10),
+ 3: newAlert(-10, -1),
+ }
+ after := map[model.Fingerprint]*types.Alert{
+ 1: newAlert(10, 20),
+ 2: newAlert(-10, 10),
+ }
+
+ r := &InhibitRule{scache: before}
+ r.gc()
+
+ if !reflect.DeepEqual(r.scache, after) {
+ t.Errorf("Unexpected cache state after GC")
+ t.Errorf(pretty.Compare(r.scache, after))
+ }
+}
+
+type fakeAlerts struct {
+ alerts []*types.Alert
+ finished chan struct{}
+}
+
+func newFakeAlerts(alerts []*types.Alert) *fakeAlerts {
+ return &fakeAlerts{
+ alerts: alerts,
+ finished: make(chan struct{}),
+ }
+}
+
+func (f *fakeAlerts) GetPending() provider.AlertIterator { return nil }
+func (f *fakeAlerts) Get(model.Fingerprint) (*types.Alert, error) { return nil, nil }
+func (f *fakeAlerts) Put(...*types.Alert) error { return nil }
+func (f *fakeAlerts) Subscribe() provider.AlertIterator {
+ ch := make(chan *types.Alert)
+ done := make(chan struct{})
+ go func() {
+ for _, a := range f.alerts {
+ ch <- a
+ }
+ // Send another (meaningless) alert to make sure that the inhibitor has
+ // processed everything.
+ ch <- &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{},
+ StartsAt: time.Now(),
+ },
+ }
+ close(f.finished)
+ <-done
+ }()
+ return provider.NewAlertIterator(ch, done, nil)
+}
+
+func TestInhibit(t *testing.T) {
+ t.Parallel()
+
+ now := time.Now()
+ inhibitRule := func() *config.InhibitRule {
+ return &config.InhibitRule{
+ SourceMatch: map[string]string{"s": "1"},
+ TargetMatch: map[string]string{"t": "1"},
+ Equal: model.LabelNames{"e"},
+ }
+ }
+ // alertOne is muted by alertTwo when it is active.
+ alertOne := func() *types.Alert {
+ return &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{"t": "1", "e": "f"},
+ StartsAt: now.Add(-time.Minute),
+ EndsAt: now.Add(time.Hour),
+ },
+ }
+ }
+ alertTwo := func(resolved bool) *types.Alert {
+ var end time.Time
+ if resolved {
+ end = now.Add(-time.Second)
+ } else {
+ end = now.Add(time.Hour)
+ }
+ return &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{"s": "1", "e": "f"},
+ StartsAt: now.Add(-time.Minute),
+ EndsAt: end,
+ },
+ }
+ }
+
+ type exp struct {
+ lbls model.LabelSet
+ muted bool
+ }
+ for i, tc := range []struct {
+ alerts []*types.Alert
+ expected []exp
+ }{
+ {
+ // alertOne shouldn't be muted since alertTwo hasn't fired.
+ alerts: []*types.Alert{alertOne()},
+ expected: []exp{
+ {
+ lbls: model.LabelSet{"t": "1", "e": "f"},
+ muted: false,
+ },
+ },
+ },
+ {
+ // alertOne should be muted by alertTwo which is active.
+ alerts: []*types.Alert{alertOne(), alertTwo(false)},
+ expected: []exp{
+ {
+ lbls: model.LabelSet{"t": "1", "e": "f"},
+ muted: true,
+ },
+ {
+ lbls: model.LabelSet{"s": "1", "e": "f"},
+ muted: false,
+ },
+ },
+ },
+ {
+ // alertOne shouldn't be muted since alertTwo is resolved.
+ alerts: []*types.Alert{alertOne(), alertTwo(false), alertTwo(true)},
+ expected: []exp{
+ {
+ lbls: model.LabelSet{"t": "1", "e": "f"},
+ muted: false,
+ },
+ {
+ lbls: model.LabelSet{"s": "1", "e": "f"},
+ muted: false,
+ },
+ },
+ },
+ } {
+ ap := newFakeAlerts(tc.alerts)
+ mk := types.NewMarker()
+ inhibitor := NewInhibitor(ap, []*config.InhibitRule{inhibitRule()}, mk, nopLogger)
+
+ go func() {
+ for ap.finished != nil {
+ select {
+ case <-ap.finished:
+ ap.finished = nil
+ default:
+ }
+ }
+ inhibitor.Stop()
+ }()
+ inhibitor.Run()
+
+ for _, expected := range tc.expected {
+ if inhibitor.Mutes(expected.lbls) != expected.muted {
+ mute := "unmuted"
+ if expected.muted {
+ mute = "muted"
+ }
+ t.Errorf("tc: %d, expected alert with labels %q to be %s", i, expected.lbls, mute)
+ }
+ }
+ }
+}
--- /dev/null
+// Copyright 2016 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package nflog implements a garbage-collected and snapshottable append-only log of
+// active/resolved notifications. Each log entry stores the active/resolved state,
+// the notified receiver, and a hash digest of the notification's identifying contents.
+// The log can be queried along different parameters.
+package nflog
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "math/rand"
+ "os"
+ "sync"
+ "time"
+
+ "github.com/go-kit/kit/log"
+ "github.com/go-kit/kit/log/level"
+ "github.com/matttproud/golang_protobuf_extensions/pbutil"
+ "github.com/prometheus/alertmanager/cluster"
+ pb "github.com/prometheus/alertmanager/nflog/nflogpb"
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+// ErrNotFound is returned for empty query results.
+var ErrNotFound = errors.New("not found")
+
+// ErrInvalidState is returned if the state isn't valid.
+var ErrInvalidState = fmt.Errorf("invalid state")
+
+// query currently allows filtering by and/or receiver group key.
+// It is configured via QueryParameter functions.
+//
+// TODO(fabxc): Future versions could allow querying a certain receiver
+// group or a given time interval.
+type query struct {
+ recv *pb.Receiver
+ groupKey string
+}
+
+// QueryParam is a function that modifies a query to incorporate
+// a set of parameters. Returns an error for invalid or conflicting
+// parameters.
+type QueryParam func(*query) error
+
+// QReceiver adds a receiver parameter to a query.
+func QReceiver(r *pb.Receiver) QueryParam {
+ return func(q *query) error {
+ q.recv = r
+ return nil
+ }
+}
+
+// QGroupKey adds a group key as querying argument.
+func QGroupKey(gk string) QueryParam {
+ return func(q *query) error {
+ q.groupKey = gk
+ return nil
+ }
+}
+
+type Log struct {
+ logger log.Logger
+ metrics *metrics
+ now func() time.Time
+ retention time.Duration
+
+ runInterval time.Duration
+ snapf string
+ stopc chan struct{}
+ done func()
+
+ // For now we only store the most recently added log entry.
+ // The key is a serialized concatenation of group key and receiver.
+ mtx sync.RWMutex
+ st state
+ broadcast func([]byte)
+}
+
+type metrics struct {
+ gcDuration prometheus.Summary
+ snapshotDuration prometheus.Summary
+ snapshotSize prometheus.Gauge
+ queriesTotal prometheus.Counter
+ queryErrorsTotal prometheus.Counter
+ queryDuration prometheus.Histogram
+ propagatedMessagesTotal prometheus.Counter
+}
+
+func newMetrics(r prometheus.Registerer) *metrics {
+ m := &metrics{}
+
+ m.gcDuration = prometheus.NewSummary(prometheus.SummaryOpts{
+ Name: "alertmanager_nflog_gc_duration_seconds",
+ Help: "Duration of the last notification log garbage collection cycle.",
+ })
+ m.snapshotDuration = prometheus.NewSummary(prometheus.SummaryOpts{
+ Name: "alertmanager_nflog_snapshot_duration_seconds",
+ Help: "Duration of the last notification log snapshot.",
+ })
+ m.snapshotSize = prometheus.NewGauge(prometheus.GaugeOpts{
+ Name: "alertmanager_nflog_snapshot_size_bytes",
+ Help: "Size of the last notification log snapshot in bytes.",
+ })
+ m.queriesTotal = prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "alertmanager_nflog_queries_total",
+ Help: "Number of notification log queries were received.",
+ })
+ m.queryErrorsTotal = prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "alertmanager_nflog_query_errors_total",
+ Help: "Number notification log received queries that failed.",
+ })
+ m.queryDuration = prometheus.NewHistogram(prometheus.HistogramOpts{
+ Name: "alertmanager_nflog_query_duration_seconds",
+ Help: "Duration of notification log query evaluation.",
+ })
+ m.propagatedMessagesTotal = prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "alertmanager_nflog_gossip_messages_propagated_total",
+ Help: "Number of received gossip messages that have been further gossiped.",
+ })
+
+ if r != nil {
+ r.MustRegister(
+ m.gcDuration,
+ m.snapshotDuration,
+ m.snapshotSize,
+ m.queriesTotal,
+ m.queryErrorsTotal,
+ m.queryDuration,
+ m.propagatedMessagesTotal,
+ )
+ }
+ return m
+}
+
+// Option configures a new Log implementation.
+type Option func(*Log) error
+
+// WithRetention sets the retention time for log st.
+func WithRetention(d time.Duration) Option {
+ return func(l *Log) error {
+ l.retention = d
+ return nil
+ }
+}
+
+// WithNow overwrites the function used to retrieve a timestamp
+// for the current point in time.
+// This is generally useful for injection during tests.
+func WithNow(f func() time.Time) Option {
+ return func(l *Log) error {
+ l.now = f
+ return nil
+ }
+}
+
+// WithLogger configures a logger for the notification log.
+func WithLogger(logger log.Logger) Option {
+ return func(l *Log) error {
+ l.logger = logger
+ return nil
+ }
+}
+
+// WithMetrics registers metrics for the notification log.
+func WithMetrics(r prometheus.Registerer) Option {
+ return func(l *Log) error {
+ l.metrics = newMetrics(r)
+ return nil
+ }
+}
+
+// WithMaintenance configures the Log to run garbage collection
+// and snapshotting, if configured, at the given interval.
+//
+// The maintenance terminates on receiving from the provided channel.
+// The done function is called after the final snapshot was completed.
+func WithMaintenance(d time.Duration, stopc chan struct{}, done func()) Option {
+ return func(l *Log) error {
+ if d == 0 {
+ return fmt.Errorf("maintenance interval must not be 0")
+ }
+ l.runInterval = d
+ l.stopc = stopc
+ l.done = done
+ return nil
+ }
+}
+
+// WithSnapshot configures the log to be initialized from a given snapshot file.
+// If maintenance is configured, a snapshot will be saved periodically and on
+// shutdown as well.
+func WithSnapshot(sf string) Option {
+ return func(l *Log) error {
+ l.snapf = sf
+ return nil
+ }
+}
+
+func utcNow() time.Time {
+ return time.Now().UTC()
+}
+
+type state map[string]*pb.MeshEntry
+
+func (s state) clone() state {
+ c := make(state, len(s))
+ for k, v := range s {
+ c[k] = v
+ }
+ return c
+}
+
+// merge returns true or false whether the MeshEntry was merged or
+// not. This information is used to decide to gossip the message further.
+func (s state) merge(e *pb.MeshEntry) bool {
+ k := stateKey(string(e.Entry.GroupKey), e.Entry.Receiver)
+
+ prev, ok := s[k]
+ if !ok || prev.Entry.Timestamp.Before(e.Entry.Timestamp) {
+ s[k] = e
+ return true
+ }
+ return false
+}
+
+func (s state) MarshalBinary() ([]byte, error) {
+ var buf bytes.Buffer
+
+ for _, e := range s {
+ if _, err := pbutil.WriteDelimited(&buf, e); err != nil {
+ return nil, err
+ }
+ }
+ return buf.Bytes(), nil
+}
+
+func decodeState(r io.Reader) (state, error) {
+ st := state{}
+ for {
+ var e pb.MeshEntry
+ _, err := pbutil.ReadDelimited(r, &e)
+ if err == nil {
+ if e.Entry == nil || e.Entry.Receiver == nil {
+ return nil, ErrInvalidState
+ }
+ st[stateKey(string(e.Entry.GroupKey), e.Entry.Receiver)] = &e
+ continue
+ }
+ if err == io.EOF {
+ break
+ }
+ return nil, err
+ }
+ return st, nil
+}
+
+func marshalMeshEntry(e *pb.MeshEntry) ([]byte, error) {
+ var buf bytes.Buffer
+ if _, err := pbutil.WriteDelimited(&buf, e); err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+// New creates a new notification log based on the provided options.
+// The snapshot is loaded into the Log if it is set.
+func New(opts ...Option) (*Log, error) {
+ l := &Log{
+ logger: log.NewNopLogger(),
+ now: utcNow,
+ st: state{},
+ broadcast: func([]byte) {},
+ }
+ for _, o := range opts {
+ if err := o(l); err != nil {
+ return nil, err
+ }
+ }
+ if l.metrics == nil {
+ l.metrics = newMetrics(nil)
+ }
+
+ if l.snapf != "" {
+ if f, err := os.Open(l.snapf); !os.IsNotExist(err) {
+ if err != nil {
+ return l, err
+ }
+ defer f.Close()
+
+ if err := l.loadSnapshot(f); err != nil {
+ return l, err
+ }
+ }
+ }
+
+ go l.run()
+
+ return l, nil
+}
+
+// run periodic background maintenance.
+func (l *Log) run() {
+ if l.runInterval == 0 || l.stopc == nil {
+ return
+ }
+ t := time.NewTicker(l.runInterval)
+ defer t.Stop()
+
+ if l.done != nil {
+ defer l.done()
+ }
+
+ f := func() error {
+ start := l.now()
+ var size int64
+
+ level.Debug(l.logger).Log("msg", "Running maintenance")
+ defer func() {
+ level.Debug(l.logger).Log("msg", "Maintenance done", "duration", l.now().Sub(start), "size", size)
+ l.metrics.snapshotSize.Set(float64(size))
+ }()
+
+ if _, err := l.GC(); err != nil {
+ return err
+ }
+ if l.snapf == "" {
+ return nil
+ }
+ f, err := openReplace(l.snapf)
+ if err != nil {
+ return err
+ }
+ if size, err = l.Snapshot(f); err != nil {
+ return err
+ }
+ return f.Close()
+ }
+
+Loop:
+ for {
+ select {
+ case <-l.stopc:
+ break Loop
+ case <-t.C:
+ if err := f(); err != nil {
+ level.Error(l.logger).Log("msg", "Running maintenance failed", "err", err)
+ }
+ }
+ }
+ // No need to run final maintenance if we don't want to snapshot.
+ if l.snapf == "" {
+ return
+ }
+ if err := f(); err != nil {
+ level.Error(l.logger).Log("msg", "Creating shutdown snapshot failed", "err", err)
+ }
+}
+
+func receiverKey(r *pb.Receiver) string {
+ return fmt.Sprintf("%s/%s/%d", r.GroupName, r.Integration, r.Idx)
+}
+
+// stateKey returns a string key for a log entry consisting of the group key
+// and receiver.
+func stateKey(k string, r *pb.Receiver) string {
+ return fmt.Sprintf("%s:%s", k, receiverKey(r))
+}
+
+func (l *Log) Log(r *pb.Receiver, gkey string, firingAlerts, resolvedAlerts []uint64) error {
+ // Write all st with the same timestamp.
+ now := l.now()
+ key := stateKey(gkey, r)
+
+ l.mtx.Lock()
+ defer l.mtx.Unlock()
+
+ if prevle, ok := l.st[key]; ok {
+ // Entry already exists, only overwrite if timestamp is newer.
+ // This may happen with raciness or clock-drift across AM nodes.
+ if prevle.Entry.Timestamp.After(now) {
+ return nil
+ }
+ }
+
+ e := &pb.MeshEntry{
+ Entry: &pb.Entry{
+ Receiver: r,
+ GroupKey: []byte(gkey),
+ Timestamp: now,
+ FiringAlerts: firingAlerts,
+ ResolvedAlerts: resolvedAlerts,
+ },
+ ExpiresAt: now.Add(l.retention),
+ }
+
+ b, err := marshalMeshEntry(e)
+ if err != nil {
+ return err
+ }
+ l.st.merge(e)
+ l.broadcast(b)
+
+ return nil
+}
+
+// GC implements the Log interface.
+func (l *Log) GC() (int, error) {
+ start := time.Now()
+ defer func() { l.metrics.gcDuration.Observe(time.Since(start).Seconds()) }()
+
+ now := l.now()
+ var n int
+
+ l.mtx.Lock()
+ defer l.mtx.Unlock()
+
+ for k, le := range l.st {
+ if le.ExpiresAt.IsZero() {
+ return n, errors.New("unexpected zero expiration timestamp")
+ }
+ if !le.ExpiresAt.After(now) {
+ delete(l.st, k)
+ n++
+ }
+ }
+
+ return n, nil
+}
+
+// Query implements the Log interface.
+func (l *Log) Query(params ...QueryParam) ([]*pb.Entry, error) {
+ start := time.Now()
+ l.metrics.queriesTotal.Inc()
+
+ entries, err := func() ([]*pb.Entry, error) {
+ q := &query{}
+ for _, p := range params {
+ if err := p(q); err != nil {
+ return nil, err
+ }
+ }
+ // TODO(fabxc): For now our only query mode is the most recent entry for a
+ // receiver/group_key combination.
+ if q.recv == nil || q.groupKey == "" {
+ // TODO(fabxc): allow more complex queries in the future.
+ // How to enable pagination?
+ return nil, errors.New("no query parameters specified")
+ }
+
+ l.mtx.RLock()
+ defer l.mtx.RUnlock()
+
+ if le, ok := l.st[stateKey(q.groupKey, q.recv)]; ok {
+ return []*pb.Entry{le.Entry}, nil
+ }
+ return nil, ErrNotFound
+ }()
+ if err != nil {
+ l.metrics.queryErrorsTotal.Inc()
+ }
+ l.metrics.queryDuration.Observe(time.Since(start).Seconds())
+ return entries, err
+}
+
+// loadSnapshot loads a snapshot generated by Snapshot() into the state.
+func (l *Log) loadSnapshot(r io.Reader) error {
+ st, err := decodeState(r)
+ if err != nil {
+ return err
+ }
+
+ l.mtx.Lock()
+ l.st = st
+ l.mtx.Unlock()
+
+ return nil
+}
+
+// Snapshot implements the Log interface.
+func (l *Log) Snapshot(w io.Writer) (int64, error) {
+ start := time.Now()
+ defer func() { l.metrics.snapshotDuration.Observe(time.Since(start).Seconds()) }()
+
+ l.mtx.RLock()
+ defer l.mtx.RUnlock()
+
+ b, err := l.st.MarshalBinary()
+ if err != nil {
+ return 0, err
+ }
+
+ return io.Copy(w, bytes.NewReader(b))
+}
+
+// MarshalBinary serializes all contents of the notification log.
+func (l *Log) MarshalBinary() ([]byte, error) {
+ l.mtx.Lock()
+ defer l.mtx.Unlock()
+
+ return l.st.MarshalBinary()
+}
+
+// Merge merges notification log state received from the cluster with the local state.
+func (l *Log) Merge(b []byte) error {
+ st, err := decodeState(bytes.NewReader(b))
+ if err != nil {
+ return err
+ }
+ l.mtx.Lock()
+ defer l.mtx.Unlock()
+
+ for _, e := range st {
+ if merged := l.st.merge(e); merged && !cluster.OversizedMessage(b) {
+ // If this is the first we've seen the message and it's
+ // not oversized, gossip it to other nodes. We don't
+ // propagate oversized messages because they're sent to
+ // all nodes already.
+ l.broadcast(b)
+ l.metrics.propagatedMessagesTotal.Inc()
+ level.Debug(l.logger).Log("msg", "gossiping new entry", "entry", e)
+ }
+ }
+ return nil
+}
+
+// SetBroadcast sets a broadcast callback that will be invoked with serialized state
+// on updates.
+func (l *Log) SetBroadcast(f func([]byte)) {
+ l.mtx.Lock()
+ l.broadcast = f
+ l.mtx.Unlock()
+}
+
+// replaceFile wraps a file that is moved to another filename on closing.
+type replaceFile struct {
+ *os.File
+ filename string
+}
+
+func (f *replaceFile) Close() error {
+ if err := f.File.Sync(); err != nil {
+ return err
+ }
+ if err := f.File.Close(); err != nil {
+ return err
+ }
+ return os.Rename(f.File.Name(), f.filename)
+}
+
+// openReplace opens a new temporary file that is moved to filename on closing.
+func openReplace(filename string) (*replaceFile, error) {
+ tmpFilename := fmt.Sprintf("%s.%x", filename, uint64(rand.Int63()))
+
+ f, err := os.Create(tmpFilename)
+ if err != nil {
+ return nil, err
+ }
+
+ rf := &replaceFile{
+ File: f,
+ filename: filename,
+ }
+ return rf, nil
+}
--- /dev/null
+// Copyright 2016 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package nflog
+
+import (
+ "bytes"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "testing"
+ "time"
+
+ pb "github.com/prometheus/alertmanager/nflog/nflogpb"
+ "github.com/stretchr/testify/require"
+)
+
+func TestLogGC(t *testing.T) {
+ now := utcNow()
+ // We only care about key names and expiration timestamps.
+ newEntry := func(ts time.Time) *pb.MeshEntry {
+ return &pb.MeshEntry{
+ ExpiresAt: ts,
+ }
+ }
+
+ l := &Log{
+ st: state{
+ "a1": newEntry(now),
+ "a2": newEntry(now.Add(time.Second)),
+ "a3": newEntry(now.Add(-time.Second)),
+ },
+ now: func() time.Time { return now },
+ metrics: newMetrics(nil),
+ }
+ n, err := l.GC()
+ require.NoError(t, err, "unexpected error in garbage collection")
+ require.Equal(t, 2, n, "unexpected number of removed entries")
+
+ expected := state{
+ "a2": newEntry(now.Add(time.Second)),
+ }
+ require.Equal(t, l.st, expected, "unepexcted state after garbage collection")
+}
+
+func TestLogSnapshot(t *testing.T) {
+ // Check whether storing and loading the snapshot is symmetric.
+ now := utcNow()
+
+ cases := []struct {
+ entries []*pb.MeshEntry
+ }{
+ {
+ entries: []*pb.MeshEntry{
+ {
+ Entry: &pb.Entry{
+ GroupKey: []byte("d8e8fca2dc0f896fd7cb4cb0031ba249"),
+ Receiver: &pb.Receiver{GroupName: "abc", Integration: "test1", Idx: 1},
+ GroupHash: []byte("126a8a51b9d1bbd07fddc65819a542c3"),
+ Resolved: false,
+ Timestamp: now,
+ },
+ ExpiresAt: now,
+ }, {
+ Entry: &pb.Entry{
+ GroupKey: []byte("d8e8fca2dc0f8abce7cb4cb0031ba249"),
+ Receiver: &pb.Receiver{GroupName: "def", Integration: "test2", Idx: 29},
+ GroupHash: []byte("122c2331b9d1bbd07fddc65819a542c3"),
+ Resolved: true,
+ Timestamp: now,
+ },
+ ExpiresAt: now,
+ }, {
+ Entry: &pb.Entry{
+ GroupKey: []byte("aaaaaca2dc0f896fd7cb4cb0031ba249"),
+ Receiver: &pb.Receiver{GroupName: "ghi", Integration: "test3", Idx: 0},
+ GroupHash: []byte("126a8a51b9d1bbd07fddc6e3e3e542c3"),
+ Resolved: false,
+ Timestamp: now,
+ },
+ ExpiresAt: now,
+ },
+ },
+ },
+ }
+
+ for _, c := range cases {
+ f, err := ioutil.TempFile("", "snapshot")
+ require.NoError(t, err, "creating temp file failed")
+
+ l1 := &Log{
+ st: state{},
+ metrics: newMetrics(nil),
+ }
+ // Setup internal state manually.
+ for _, e := range c.entries {
+ l1.st[stateKey(string(e.Entry.GroupKey), e.Entry.Receiver)] = e
+ }
+ _, err = l1.Snapshot(f)
+ require.NoError(t, err, "creating snapshot failed")
+ require.NoError(t, f.Close(), "closing snapshot file failed")
+
+ f, err = os.Open(f.Name())
+ require.NoError(t, err, "opening snapshot file failed")
+
+ // Check again against new nlog instance.
+ l2 := &Log{}
+ err = l2.loadSnapshot(f)
+ require.NoError(t, err, "error loading snapshot")
+ require.Equal(t, l1.st, l2.st, "state after loading snapshot did not match snapshotted state")
+
+ require.NoError(t, f.Close(), "closing snapshot file failed")
+ }
+}
+
+func TestReplaceFile(t *testing.T) {
+ dir, err := ioutil.TempDir("", "replace_file")
+ require.NoError(t, err, "creating temp dir failed")
+
+ origFilename := filepath.Join(dir, "testfile")
+
+ of, err := os.Create(origFilename)
+ require.NoError(t, err, "creating file failed")
+
+ nf, err := openReplace(origFilename)
+ require.NoError(t, err, "opening replacement file failed")
+
+ _, err = nf.Write([]byte("test"))
+ require.NoError(t, err, "writing replace file failed")
+
+ require.NotEqual(t, nf.Name(), of.Name(), "replacement file must have different name while editing")
+ require.NoError(t, nf.Close(), "closing replacement file failed")
+ require.NoError(t, of.Close(), "closing original file failed")
+
+ ofr, err := os.Open(origFilename)
+ require.NoError(t, err, "opening original file failed")
+ defer ofr.Close()
+
+ res, err := ioutil.ReadAll(ofr)
+ require.NoError(t, err, "reading original file failed")
+ require.Equal(t, "test", string(res), "unexpected file contents")
+}
+
+func TestStateMerge(t *testing.T) {
+ now := utcNow()
+
+ // We only care about key names and timestamps for the
+ // merging logic.
+ newEntry := func(ts time.Time, name string) *pb.MeshEntry {
+ return &pb.MeshEntry{
+ Entry: &pb.Entry{
+ Timestamp: ts,
+ GroupKey: []byte("key"),
+ Receiver: &pb.Receiver{
+ GroupName: name,
+ Idx: 1,
+ Integration: "integr",
+ },
+ },
+ }
+ }
+ cases := []struct {
+ a, b state
+ final state
+ }{
+ {
+ a: state{
+ "key:a1/integr/1": newEntry(now, "a1"),
+ "key:a2/integr/1": newEntry(now, "a2"),
+ "key:a3/integr/1": newEntry(now, "a3"),
+ },
+ b: state{
+ "key:b1/integr/1": newEntry(now, "b1"), // new key, should be added
+ "key:a2/integr/1": newEntry(now.Add(-time.Minute), "a2"), // older timestamp, should be dropped
+ "key:a3/integr/1": newEntry(now.Add(time.Minute), "a3"), // newer timestamp, should overwrite
+ },
+ final: state{
+ "key:a1/integr/1": newEntry(now, "a1"),
+ "key:a2/integr/1": newEntry(now, "a2"),
+ "key:a3/integr/1": newEntry(now.Add(time.Minute), "a3"),
+ "key:b1/integr/1": newEntry(now, "b1"),
+ },
+ },
+ }
+
+ for _, c := range cases {
+ ca, cb := c.a.clone(), c.b.clone()
+
+ res := c.a.clone()
+ for _, e := range cb {
+ res.merge(e)
+ }
+ require.Equal(t, c.final, res, "Merge result should match expectation")
+ require.Equal(t, c.b, cb, "Merged state should remain unmodified")
+ require.NotEqual(t, c.final, ca, "Merge should not change original state")
+ }
+}
+
+func TestStateDataCoding(t *testing.T) {
+ // Check whether encoding and decoding the data is symmetric.
+ now := utcNow()
+
+ cases := []struct {
+ entries []*pb.MeshEntry
+ }{
+ {
+ entries: []*pb.MeshEntry{
+ {
+ Entry: &pb.Entry{
+ GroupKey: []byte("d8e8fca2dc0f896fd7cb4cb0031ba249"),
+ Receiver: &pb.Receiver{GroupName: "abc", Integration: "test1", Idx: 1},
+ GroupHash: []byte("126a8a51b9d1bbd07fddc65819a542c3"),
+ Resolved: false,
+ Timestamp: now,
+ },
+ ExpiresAt: now,
+ }, {
+ Entry: &pb.Entry{
+ GroupKey: []byte("d8e8fca2dc0f8abce7cb4cb0031ba249"),
+ Receiver: &pb.Receiver{GroupName: "def", Integration: "test2", Idx: 29},
+ GroupHash: []byte("122c2331b9d1bbd07fddc65819a542c3"),
+ Resolved: true,
+ Timestamp: now,
+ },
+ ExpiresAt: now,
+ }, {
+ Entry: &pb.Entry{
+ GroupKey: []byte("aaaaaca2dc0f896fd7cb4cb0031ba249"),
+ Receiver: &pb.Receiver{GroupName: "ghi", Integration: "test3", Idx: 0},
+ GroupHash: []byte("126a8a51b9d1bbd07fddc6e3e3e542c3"),
+ Resolved: false,
+ Timestamp: now,
+ },
+ ExpiresAt: now,
+ },
+ },
+ },
+ }
+
+ for _, c := range cases {
+ // Create gossip data from input.
+ in := state{}
+ for _, e := range c.entries {
+ in[stateKey(string(e.Entry.GroupKey), e.Entry.Receiver)] = e
+ }
+ msg, err := in.MarshalBinary()
+ require.NoError(t, err)
+
+ out, err := decodeState(bytes.NewReader(msg))
+ require.NoError(t, err, "decoding message failed")
+
+ require.Equal(t, in, out, "decoded data doesn't match encoded data")
+ }
+}
+
+func TestQuery(t *testing.T) {
+ nl, err := New()
+ if err != nil {
+ require.NoError(t, err, "constructing nflog failed")
+ }
+
+ recv := new(pb.Receiver)
+
+ // no key param
+ _, err = nl.Query(QGroupKey("key"))
+ require.EqualError(t, err, "no query parameters specified")
+
+ // no recv param
+ _, err = nl.Query(QReceiver(recv))
+ require.EqualError(t, err, "no query parameters specified")
+
+ // no entry
+ _, err = nl.Query(QGroupKey("nonexistingkey"), QReceiver(recv))
+ require.EqualError(t, err, "not found")
+
+ // existing entry
+ firingAlerts := []uint64{1, 2, 3}
+ resolvedAlerts := []uint64{4, 5}
+
+ err = nl.Log(recv, "key", firingAlerts, resolvedAlerts)
+ require.NoError(t, err, "logging notification failed")
+
+ entries, err := nl.Query(QGroupKey("key"), QReceiver(recv))
+ require.NoError(t, err, "querying nflog failed")
+ entry := entries[0]
+ require.EqualValues(t, firingAlerts, entry.FiringAlerts)
+ require.EqualValues(t, resolvedAlerts, entry.ResolvedAlerts)
+}
+
+func TestStateDecodingError(t *testing.T) {
+ // Check whether decoding copes with erroneous data.
+ s := state{"": &pb.MeshEntry{}}
+
+ msg, err := s.MarshalBinary()
+ require.NoError(t, err)
+
+ _, err = decodeState(bytes.NewReader(msg))
+ require.Equal(t, ErrInvalidState, err)
+}
--- /dev/null
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: nflog.proto
+
+/*
+ Package nflogpb is a generated protocol buffer package.
+
+ It is generated from these files:
+ nflog.proto
+
+ It has these top-level messages:
+ Receiver
+ Entry
+ MeshEntry
+*/
+package nflogpb
+
+import proto "github.com/gogo/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+import _ "github.com/gogo/protobuf/gogoproto"
+
+import time "time"
+
+import types "github.com/gogo/protobuf/types"
+
+import io "io"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+var _ = time.Kitchen
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
+
+type Receiver struct {
+ // Configured name of the receiver group.
+ GroupName string `protobuf:"bytes,1,opt,name=group_name,json=groupName,proto3" json:"group_name,omitempty"`
+ // Name of the integration of the receiver.
+ Integration string `protobuf:"bytes,2,opt,name=integration,proto3" json:"integration,omitempty"`
+ // Index of the receiver with respect to the integration.
+ // Every integration in a group may have 0..N configurations.
+ Idx uint32 `protobuf:"varint,3,opt,name=idx,proto3" json:"idx,omitempty"`
+}
+
+func (m *Receiver) Reset() { *m = Receiver{} }
+func (m *Receiver) String() string { return proto.CompactTextString(m) }
+func (*Receiver) ProtoMessage() {}
+func (*Receiver) Descriptor() ([]byte, []int) { return fileDescriptorNflog, []int{0} }
+
+// Entry holds information about a successful notification
+// sent to a receiver.
+type Entry struct {
+ // The key identifying the dispatching group.
+ GroupKey []byte `protobuf:"bytes,1,opt,name=group_key,json=groupKey,proto3" json:"group_key,omitempty"`
+ // The receiver that was notified.
+ Receiver *Receiver `protobuf:"bytes,2,opt,name=receiver" json:"receiver,omitempty"`
+ // Hash over the state of the group at notification time.
+ // Deprecated in favor of FiringAlerts field, but kept for compatibility.
+ GroupHash []byte `protobuf:"bytes,3,opt,name=group_hash,json=groupHash,proto3" json:"group_hash,omitempty"`
+ // Whether the notification was about a resolved alert.
+ // Deprecated in favor of ResolvedAlerts field, but kept for compatibility.
+ Resolved bool `protobuf:"varint,4,opt,name=resolved,proto3" json:"resolved,omitempty"`
+ // Timestamp of the succeeding notification.
+ Timestamp time.Time `protobuf:"bytes,5,opt,name=timestamp,stdtime" json:"timestamp"`
+ // FiringAlerts list of hashes of firing alerts at the last notification time.
+ FiringAlerts []uint64 `protobuf:"varint,6,rep,packed,name=firing_alerts,json=firingAlerts" json:"firing_alerts,omitempty"`
+ // ResolvedAlerts list of hashes of resolved alerts at the last notification time.
+ ResolvedAlerts []uint64 `protobuf:"varint,7,rep,packed,name=resolved_alerts,json=resolvedAlerts" json:"resolved_alerts,omitempty"`
+}
+
+func (m *Entry) Reset() { *m = Entry{} }
+func (m *Entry) String() string { return proto.CompactTextString(m) }
+func (*Entry) ProtoMessage() {}
+func (*Entry) Descriptor() ([]byte, []int) { return fileDescriptorNflog, []int{1} }
+
+// MeshEntry is a wrapper message to communicate a notify log
+// entry through a mesh network.
+type MeshEntry struct {
+ // The original raw notify log entry.
+ Entry *Entry `protobuf:"bytes,1,opt,name=entry" json:"entry,omitempty"`
+ // A timestamp indicating when the mesh peer should evict
+ // the log entry from its state.
+ ExpiresAt time.Time `protobuf:"bytes,2,opt,name=expires_at,json=expiresAt,stdtime" json:"expires_at"`
+}
+
+func (m *MeshEntry) Reset() { *m = MeshEntry{} }
+func (m *MeshEntry) String() string { return proto.CompactTextString(m) }
+func (*MeshEntry) ProtoMessage() {}
+func (*MeshEntry) Descriptor() ([]byte, []int) { return fileDescriptorNflog, []int{2} }
+
+func init() {
+ proto.RegisterType((*Receiver)(nil), "nflogpb.Receiver")
+ proto.RegisterType((*Entry)(nil), "nflogpb.Entry")
+ proto.RegisterType((*MeshEntry)(nil), "nflogpb.MeshEntry")
+}
+func (m *Receiver) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Receiver) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.GroupName) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintNflog(dAtA, i, uint64(len(m.GroupName)))
+ i += copy(dAtA[i:], m.GroupName)
+ }
+ if len(m.Integration) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintNflog(dAtA, i, uint64(len(m.Integration)))
+ i += copy(dAtA[i:], m.Integration)
+ }
+ if m.Idx != 0 {
+ dAtA[i] = 0x18
+ i++
+ i = encodeVarintNflog(dAtA, i, uint64(m.Idx))
+ }
+ return i, nil
+}
+
+func (m *Entry) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Entry) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.GroupKey) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintNflog(dAtA, i, uint64(len(m.GroupKey)))
+ i += copy(dAtA[i:], m.GroupKey)
+ }
+ if m.Receiver != nil {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintNflog(dAtA, i, uint64(m.Receiver.Size()))
+ n1, err := m.Receiver.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n1
+ }
+ if len(m.GroupHash) > 0 {
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintNflog(dAtA, i, uint64(len(m.GroupHash)))
+ i += copy(dAtA[i:], m.GroupHash)
+ }
+ if m.Resolved {
+ dAtA[i] = 0x20
+ i++
+ if m.Resolved {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ }
+ dAtA[i] = 0x2a
+ i++
+ i = encodeVarintNflog(dAtA, i, uint64(types.SizeOfStdTime(m.Timestamp)))
+ n2, err := types.StdTimeMarshalTo(m.Timestamp, dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n2
+ if len(m.FiringAlerts) > 0 {
+ dAtA4 := make([]byte, len(m.FiringAlerts)*10)
+ var j3 int
+ for _, num := range m.FiringAlerts {
+ for num >= 1<<7 {
+ dAtA4[j3] = uint8(uint64(num)&0x7f | 0x80)
+ num >>= 7
+ j3++
+ }
+ dAtA4[j3] = uint8(num)
+ j3++
+ }
+ dAtA[i] = 0x32
+ i++
+ i = encodeVarintNflog(dAtA, i, uint64(j3))
+ i += copy(dAtA[i:], dAtA4[:j3])
+ }
+ if len(m.ResolvedAlerts) > 0 {
+ dAtA6 := make([]byte, len(m.ResolvedAlerts)*10)
+ var j5 int
+ for _, num := range m.ResolvedAlerts {
+ for num >= 1<<7 {
+ dAtA6[j5] = uint8(uint64(num)&0x7f | 0x80)
+ num >>= 7
+ j5++
+ }
+ dAtA6[j5] = uint8(num)
+ j5++
+ }
+ dAtA[i] = 0x3a
+ i++
+ i = encodeVarintNflog(dAtA, i, uint64(j5))
+ i += copy(dAtA[i:], dAtA6[:j5])
+ }
+ return i, nil
+}
+
+func (m *MeshEntry) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *MeshEntry) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Entry != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintNflog(dAtA, i, uint64(m.Entry.Size()))
+ n7, err := m.Entry.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n7
+ }
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintNflog(dAtA, i, uint64(types.SizeOfStdTime(m.ExpiresAt)))
+ n8, err := types.StdTimeMarshalTo(m.ExpiresAt, dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n8
+ return i, nil
+}
+
+func encodeVarintNflog(dAtA []byte, offset int, v uint64) int {
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return offset + 1
+}
+func (m *Receiver) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.GroupName)
+ if l > 0 {
+ n += 1 + l + sovNflog(uint64(l))
+ }
+ l = len(m.Integration)
+ if l > 0 {
+ n += 1 + l + sovNflog(uint64(l))
+ }
+ if m.Idx != 0 {
+ n += 1 + sovNflog(uint64(m.Idx))
+ }
+ return n
+}
+
+func (m *Entry) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.GroupKey)
+ if l > 0 {
+ n += 1 + l + sovNflog(uint64(l))
+ }
+ if m.Receiver != nil {
+ l = m.Receiver.Size()
+ n += 1 + l + sovNflog(uint64(l))
+ }
+ l = len(m.GroupHash)
+ if l > 0 {
+ n += 1 + l + sovNflog(uint64(l))
+ }
+ if m.Resolved {
+ n += 2
+ }
+ l = types.SizeOfStdTime(m.Timestamp)
+ n += 1 + l + sovNflog(uint64(l))
+ if len(m.FiringAlerts) > 0 {
+ l = 0
+ for _, e := range m.FiringAlerts {
+ l += sovNflog(uint64(e))
+ }
+ n += 1 + sovNflog(uint64(l)) + l
+ }
+ if len(m.ResolvedAlerts) > 0 {
+ l = 0
+ for _, e := range m.ResolvedAlerts {
+ l += sovNflog(uint64(e))
+ }
+ n += 1 + sovNflog(uint64(l)) + l
+ }
+ return n
+}
+
+func (m *MeshEntry) Size() (n int) {
+ var l int
+ _ = l
+ if m.Entry != nil {
+ l = m.Entry.Size()
+ n += 1 + l + sovNflog(uint64(l))
+ }
+ l = types.SizeOfStdTime(m.ExpiresAt)
+ n += 1 + l + sovNflog(uint64(l))
+ return n
+}
+
+func sovNflog(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+func sozNflog(x uint64) (n int) {
+ return sovNflog(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Receiver) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Receiver: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Receiver: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field GroupName", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthNflog
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.GroupName = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Integration", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthNflog
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Integration = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Idx", wireType)
+ }
+ m.Idx = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Idx |= (uint32(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipNflog(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthNflog
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *Entry) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Entry: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Entry: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field GroupKey", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthNflog
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.GroupKey = append(m.GroupKey[:0], dAtA[iNdEx:postIndex]...)
+ if m.GroupKey == nil {
+ m.GroupKey = []byte{}
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Receiver", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthNflog
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Receiver == nil {
+ m.Receiver = &Receiver{}
+ }
+ if err := m.Receiver.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field GroupHash", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthNflog
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.GroupHash = append(m.GroupHash[:0], dAtA[iNdEx:postIndex]...)
+ if m.GroupHash == nil {
+ m.GroupHash = []byte{}
+ }
+ iNdEx = postIndex
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Resolved", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Resolved = bool(v != 0)
+ case 5:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthNflog
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 6:
+ if wireType == 0 {
+ var v uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.FiringAlerts = append(m.FiringAlerts, v)
+ } else if wireType == 2 {
+ var packedLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ packedLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if packedLen < 0 {
+ return ErrInvalidLengthNflog
+ }
+ postIndex := iNdEx + packedLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ for iNdEx < postIndex {
+ var v uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.FiringAlerts = append(m.FiringAlerts, v)
+ }
+ } else {
+ return fmt.Errorf("proto: wrong wireType = %d for field FiringAlerts", wireType)
+ }
+ case 7:
+ if wireType == 0 {
+ var v uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.ResolvedAlerts = append(m.ResolvedAlerts, v)
+ } else if wireType == 2 {
+ var packedLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ packedLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if packedLen < 0 {
+ return ErrInvalidLengthNflog
+ }
+ postIndex := iNdEx + packedLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ for iNdEx < postIndex {
+ var v uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.ResolvedAlerts = append(m.ResolvedAlerts, v)
+ }
+ } else {
+ return fmt.Errorf("proto: wrong wireType = %d for field ResolvedAlerts", wireType)
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipNflog(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthNflog
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MeshEntry) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: MeshEntry: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MeshEntry: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Entry", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthNflog
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Entry == nil {
+ m.Entry = &Entry{}
+ }
+ if err := m.Entry.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ExpiresAt", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthNflog
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := types.StdTimeUnmarshal(&m.ExpiresAt, dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipNflog(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthNflog
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipNflog(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ return iNdEx, nil
+ case 1:
+ iNdEx += 8
+ return iNdEx, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ iNdEx += length
+ if length < 0 {
+ return 0, ErrInvalidLengthNflog
+ }
+ return iNdEx, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = iNdEx
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowNflog
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := skipNflog(dAtA[start:])
+ if err != nil {
+ return 0, err
+ }
+ iNdEx = start + next
+ }
+ return iNdEx, nil
+ case 4:
+ return iNdEx, nil
+ case 5:
+ iNdEx += 4
+ return iNdEx, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
+
+var (
+ ErrInvalidLengthNflog = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowNflog = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("nflog.proto", fileDescriptorNflog) }
+
+var fileDescriptorNflog = []byte{
+ // 385 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x90, 0xcf, 0x6e, 0xd3, 0x40,
+ 0x10, 0xc6, 0xbb, 0x4d, 0xd3, 0xda, 0xe3, 0xb4, 0x94, 0x15, 0x07, 0xcb, 0x08, 0xc7, 0x0a, 0x48,
+ 0xf8, 0x82, 0x23, 0x95, 0x27, 0x68, 0x10, 0x12, 0x12, 0x82, 0xc3, 0x8a, 0x2b, 0xb2, 0x36, 0x74,
+ 0xb2, 0x5e, 0x61, 0x7b, 0xad, 0xf5, 0x36, 0x6a, 0xde, 0x82, 0x47, 0xe0, 0x71, 0x72, 0xe4, 0x09,
+ 0xf8, 0x93, 0x27, 0x41, 0xde, 0xb5, 0x1d, 0x8e, 0xdc, 0x66, 0x7f, 0xf3, 0xcd, 0xcc, 0xb7, 0x1f,
+ 0x04, 0xf5, 0xa6, 0x54, 0x22, 0x6b, 0xb4, 0x32, 0x8a, 0x5e, 0xd8, 0x47, 0xb3, 0x8e, 0xe6, 0x42,
+ 0x29, 0x51, 0xe2, 0xd2, 0xe2, 0xf5, 0xfd, 0x66, 0x69, 0x64, 0x85, 0xad, 0xe1, 0x55, 0xe3, 0x94,
+ 0xd1, 0x13, 0xa1, 0x84, 0xb2, 0xe5, 0xb2, 0xab, 0x1c, 0x5d, 0x7c, 0x06, 0x8f, 0xe1, 0x17, 0x94,
+ 0x5b, 0xd4, 0xf4, 0x19, 0x80, 0xd0, 0xea, 0xbe, 0xc9, 0x6b, 0x5e, 0x61, 0x48, 0x12, 0x92, 0xfa,
+ 0xcc, 0xb7, 0xe4, 0x23, 0xaf, 0x90, 0x26, 0x10, 0xc8, 0xda, 0xa0, 0xd0, 0xdc, 0x48, 0x55, 0x87,
+ 0xa7, 0xb6, 0xff, 0x2f, 0xa2, 0xd7, 0x30, 0x91, 0x77, 0x0f, 0xe1, 0x24, 0x21, 0xe9, 0x25, 0xeb,
+ 0xca, 0xc5, 0xf7, 0x53, 0x98, 0xbe, 0xad, 0x8d, 0xde, 0xd1, 0xa7, 0xe0, 0x56, 0xe5, 0x5f, 0x71,
+ 0x67, 0x77, 0xcf, 0x98, 0x67, 0xc1, 0x7b, 0xdc, 0xd1, 0x57, 0xe0, 0xe9, 0xde, 0x85, 0xdd, 0x1b,
+ 0xdc, 0x3c, 0xce, 0xfa, 0x8f, 0x65, 0x83, 0x3d, 0x36, 0x4a, 0x8e, 0x46, 0x0b, 0xde, 0x16, 0xf6,
+ 0xdc, 0xac, 0x37, 0xfa, 0x8e, 0xb7, 0x05, 0x8d, 0xba, 0x6d, 0xad, 0x2a, 0xb7, 0x78, 0x17, 0x9e,
+ 0x25, 0x24, 0xf5, 0xd8, 0xf8, 0xa6, 0x2b, 0xf0, 0xc7, 0x60, 0xc2, 0xa9, 0x3d, 0x15, 0x65, 0x2e,
+ 0xba, 0x6c, 0x88, 0x2e, 0xfb, 0x34, 0x28, 0x56, 0xde, 0xfe, 0xe7, 0xfc, 0xe4, 0xdb, 0xaf, 0x39,
+ 0x61, 0xc7, 0x31, 0xfa, 0x1c, 0x2e, 0x37, 0x52, 0xcb, 0x5a, 0xe4, 0xbc, 0x44, 0x6d, 0xda, 0xf0,
+ 0x3c, 0x99, 0xa4, 0x67, 0x6c, 0xe6, 0xe0, 0xad, 0x65, 0xf4, 0x25, 0x3c, 0x1a, 0x8e, 0x0e, 0xb2,
+ 0x0b, 0x2b, 0xbb, 0x1a, 0xb0, 0x13, 0x2e, 0xb6, 0xe0, 0x7f, 0xc0, 0xb6, 0x70, 0x29, 0xbd, 0x80,
+ 0x29, 0x76, 0x85, 0x4d, 0x28, 0xb8, 0xb9, 0x1a, 0x53, 0xb0, 0x6d, 0xe6, 0x9a, 0xf4, 0x0d, 0x00,
+ 0x3e, 0x34, 0x52, 0x63, 0x9b, 0x73, 0xd3, 0x07, 0xf6, 0x9f, 0xbf, 0xe8, 0xe7, 0x6e, 0xcd, 0xea,
+ 0x7a, 0xff, 0x27, 0x3e, 0xd9, 0x1f, 0x62, 0xf2, 0xe3, 0x10, 0x93, 0xdf, 0x87, 0x98, 0xac, 0xcf,
+ 0xed, 0xe8, 0xeb, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x49, 0xcd, 0xa7, 0x1e, 0x61, 0x02, 0x00,
+ 0x00,
+}
--- /dev/null
+syntax = "proto3";
+
+package nflogpb;
+
+import "google/protobuf/timestamp.proto";
+import "gogoproto/gogo.proto";
+
+option (gogoproto.marshaler_all) = true;
+option (gogoproto.sizer_all) = true;
+option (gogoproto.unmarshaler_all) = true;
+option (gogoproto.goproto_getters_all) = false;
+
+message Receiver {
+ // Configured name of the receiver group.
+ string group_name = 1;
+ // Name of the integration of the receiver.
+ string integration = 2;
+ // Index of the receiver with respect to the integration.
+ // Every integration in a group may have 0..N configurations.
+ uint32 idx = 3;
+}
+
+// Entry holds information about a successful notification
+// sent to a receiver.
+message Entry {
+ // The key identifying the dispatching group.
+ bytes group_key = 1;
+ // The receiver that was notified.
+ Receiver receiver = 2;
+ // Hash over the state of the group at notification time.
+ // Deprecated in favor of FiringAlerts field, but kept for compatibility.
+ bytes group_hash = 3;
+ // Whether the notification was about a resolved alert.
+ // Deprecated in favor of ResolvedAlerts field, but kept for compatibility.
+ bool resolved = 4;
+ // Timestamp of the succeeding notification.
+ google.protobuf.Timestamp timestamp = 5 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
+ // FiringAlerts list of hashes of firing alerts at the last notification time.
+ repeated uint64 firing_alerts = 6;
+ // ResolvedAlerts list of hashes of resolved alerts at the last notification time.
+ repeated uint64 resolved_alerts = 7;
+}
+
+// MeshEntry is a wrapper message to communicate a notify log
+// entry through a mesh network.
+message MeshEntry {
+ // The original raw notify log entry.
+ Entry entry = 1;
+ // A timestamp indicating when the mesh peer should evict
+ // the log entry from its state.
+ google.protobuf.Timestamp expires_at = 2 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
+}
--- /dev/null
+// Copyright 2017 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package nflogpb
+
+// IsFiringSubset returns whether the given subset is a subset of the alerts
+// that were firing at the time of the last notification.
+func (m *Entry) IsFiringSubset(subset map[uint64]struct{}) bool {
+ set := map[uint64]struct{}{}
+ for i := range m.FiringAlerts {
+ set[m.FiringAlerts[i]] = struct{}{}
+ }
+
+ return isSubset(set, subset)
+}
+
+// IsResolvedSubset returns whether the given subset is a subset of the alerts
+// that were resolved at the time of the last notification.
+func (m *Entry) IsResolvedSubset(subset map[uint64]struct{}) bool {
+ set := map[uint64]struct{}{}
+ for i := range m.ResolvedAlerts {
+ set[m.ResolvedAlerts[i]] = struct{}{}
+ }
+
+ return isSubset(set, subset)
+}
+
+func isSubset(set, subset map[uint64]struct{}) bool {
+ for k := range subset {
+ _, exists := set[k]
+ if !exists {
+ return false
+ }
+ }
+
+ return true
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package nflogpb
+
+import (
+ "testing"
+)
+
+func TestIsFiringSubset(t *testing.T) {
+ e := &Entry{
+ FiringAlerts: []uint64{1, 2, 3},
+ }
+
+ tests := []struct {
+ subset map[uint64]struct{}
+ expected bool
+ }{
+ {newSubset(), true}, //empty subset
+ {newSubset(1), true},
+ {newSubset(2), true},
+ {newSubset(3), true},
+ {newSubset(1, 2), true},
+ {newSubset(1, 2), true},
+ {newSubset(1, 2, 3), true},
+ {newSubset(4), false},
+ {newSubset(1, 5), false},
+ {newSubset(1, 2, 3, 6), false},
+ }
+
+ for _, test := range tests {
+ if result := e.IsFiringSubset(test.subset); result != test.expected {
+ t.Errorf("Expected %t, got %t for subset %v", test.expected, result, elements(test.subset))
+ }
+ }
+}
+
+func TestIsResolvedSubset(t *testing.T) {
+ e := &Entry{
+ ResolvedAlerts: []uint64{1, 2, 3},
+ }
+
+ tests := []struct {
+ subset map[uint64]struct{}
+ expected bool
+ }{
+ {newSubset(), true}, //empty subset
+ {newSubset(1), true},
+ {newSubset(2), true},
+ {newSubset(3), true},
+ {newSubset(1, 2), true},
+ {newSubset(1, 2), true},
+ {newSubset(1, 2, 3), true},
+ {newSubset(4), false},
+ {newSubset(1, 5), false},
+ {newSubset(1, 2, 3, 6), false},
+ }
+
+ for _, test := range tests {
+ if result := e.IsResolvedSubset(test.subset); result != test.expected {
+ t.Errorf("Expected %t, got %t for subset %v", test.expected, result, elements(test.subset))
+ }
+ }
+}
+
+func newSubset(elements ...uint64) map[uint64]struct{} {
+ subset := make(map[uint64]struct{})
+ for _, el := range elements {
+ subset[el] = struct{}{}
+ }
+
+ return subset
+}
+
+func elements(m map[uint64]struct{}) []uint64 {
+ els := make([]uint64, 0, len(m))
+ for k, _ := range m {
+ els = append(els, k)
+ }
+
+ return els
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package notify
+
+import (
+ "bytes"
+ "crypto/sha256"
+ "crypto/tls"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "mime"
+ "mime/multipart"
+ "net"
+ "net/http"
+ "net/mail"
+ "net/smtp"
+ "net/textproto"
+ "net/url"
+ "strings"
+ "time"
+
+ "github.com/go-kit/kit/log"
+ "github.com/go-kit/kit/log/level"
+ commoncfg "github.com/prometheus/common/config"
+ "github.com/prometheus/common/model"
+ "github.com/prometheus/common/version"
+ "golang.org/x/net/context"
+ "golang.org/x/net/context/ctxhttp"
+
+ "github.com/prometheus/alertmanager/config"
+ "github.com/prometheus/alertmanager/template"
+ "github.com/prometheus/alertmanager/types"
+)
+
+// A Notifier notifies about alerts under constraints of the given context.
+// It returns an error if unsuccessful and a flag whether the error is
+// recoverable. This information is useful for a retry logic.
+type Notifier interface {
+ Notify(context.Context, ...*types.Alert) (bool, error)
+}
+
+// An Integration wraps a notifier and its config to be uniquely identified by
+// name and index from its origin in the configuration.
+type Integration struct {
+ notifier Notifier
+ conf notifierConfig
+ name string
+ idx int
+}
+
+// Notify implements the Notifier interface.
+func (i *Integration) Notify(ctx context.Context, alerts ...*types.Alert) (bool, error) {
+ return i.notifier.Notify(ctx, alerts...)
+}
+
+// BuildReceiverIntegrations builds a list of integration notifiers off of a
+// receivers config.
+func BuildReceiverIntegrations(nc *config.Receiver, tmpl *template.Template, logger log.Logger) []Integration {
+ var (
+ integrations []Integration
+ add = func(name string, i int, n Notifier, nc notifierConfig) {
+ integrations = append(integrations, Integration{
+ notifier: n,
+ conf: nc,
+ name: name,
+ idx: i,
+ })
+ }
+ )
+
+ for i, c := range nc.WebhookConfigs {
+ n := NewWebhook(c, tmpl, logger)
+ add("webhook", i, n, c)
+ }
+ for i, c := range nc.EmailConfigs {
+ n := NewEmail(c, tmpl, logger)
+ add("email", i, n, c)
+ }
+ for i, c := range nc.PagerdutyConfigs {
+ n := NewPagerDuty(c, tmpl, logger)
+ add("pagerduty", i, n, c)
+ }
+ for i, c := range nc.OpsGenieConfigs {
+ n := NewOpsGenie(c, tmpl, logger)
+ add("opsgenie", i, n, c)
+ }
+ for i, c := range nc.WechatConfigs {
+ n := NewWechat(c, tmpl, logger)
+ add("wechat", i, n, c)
+ }
+ for i, c := range nc.SlackConfigs {
+ n := NewSlack(c, tmpl, logger)
+ add("slack", i, n, c)
+ }
+ for i, c := range nc.HipchatConfigs {
+ n := NewHipchat(c, tmpl, logger)
+ add("hipchat", i, n, c)
+ }
+ for i, c := range nc.VictorOpsConfigs {
+ n := NewVictorOps(c, tmpl, logger)
+ add("victorops", i, n, c)
+ }
+ for i, c := range nc.PushoverConfigs {
+ n := NewPushover(c, tmpl, logger)
+ add("pushover", i, n, c)
+ }
+ return integrations
+}
+
+const contentTypeJSON = "application/json"
+
+var userAgentHeader = fmt.Sprintf("Alertmanager/%s", version.Version)
+
+// Webhook implements a Notifier for generic webhooks.
+type Webhook struct {
+ conf *config.WebhookConfig
+ tmpl *template.Template
+ logger log.Logger
+}
+
+// NewWebhook returns a new Webhook.
+func NewWebhook(conf *config.WebhookConfig, t *template.Template, l log.Logger) *Webhook {
+ return &Webhook{conf: conf, tmpl: t, logger: l}
+}
+
+// WebhookMessage defines the JSON object send to webhook endpoints.
+type WebhookMessage struct {
+ *template.Data
+
+ // The protocol version.
+ Version string `json:"version"`
+ GroupKey string `json:"groupKey"`
+}
+
+// Notify implements the Notifier interface.
+func (w *Webhook) Notify(ctx context.Context, alerts ...*types.Alert) (bool, error) {
+ data := w.tmpl.Data(receiverName(ctx, w.logger), groupLabels(ctx, w.logger), alerts...)
+
+ groupKey, ok := GroupKey(ctx)
+ if !ok {
+ level.Error(w.logger).Log("msg", "group key missing")
+ }
+
+ msg := &WebhookMessage{
+ Version: "4",
+ Data: data,
+ GroupKey: groupKey,
+ }
+
+ var buf bytes.Buffer
+ if err := json.NewEncoder(&buf).Encode(msg); err != nil {
+ return false, err
+ }
+
+ req, err := http.NewRequest("POST", w.conf.URL, &buf)
+ if err != nil {
+ return true, err
+ }
+ req.Header.Set("Content-Type", contentTypeJSON)
+ req.Header.Set("User-Agent", userAgentHeader)
+
+ c, err := commoncfg.NewClientFromConfig(*w.conf.HTTPConfig, "webhook")
+ if err != nil {
+ return false, err
+ }
+
+ resp, err := ctxhttp.Do(ctx, c, req)
+ if err != nil {
+ return true, err
+ }
+ resp.Body.Close()
+
+ return w.retry(resp.StatusCode)
+}
+
+func (w *Webhook) retry(statusCode int) (bool, error) {
+ // Webhooks are assumed to respond with 2xx response codes on a successful
+ // request and 5xx response codes are assumed to be recoverable.
+ if statusCode/100 != 2 {
+ return (statusCode/100 == 5), fmt.Errorf("unexpected status code %v from %s", statusCode, w.conf.URL)
+ }
+
+ return false, nil
+}
+
+// Email implements a Notifier for email notifications.
+type Email struct {
+ conf *config.EmailConfig
+ tmpl *template.Template
+ logger log.Logger
+}
+
+// NewEmail returns a new Email notifier.
+func NewEmail(c *config.EmailConfig, t *template.Template, l log.Logger) *Email {
+ if _, ok := c.Headers["Subject"]; !ok {
+ c.Headers["Subject"] = config.DefaultEmailSubject
+ }
+ if _, ok := c.Headers["To"]; !ok {
+ c.Headers["To"] = c.To
+ }
+ if _, ok := c.Headers["From"]; !ok {
+ c.Headers["From"] = c.From
+ }
+ return &Email{conf: c, tmpl: t, logger: l}
+}
+
+// auth resolves a string of authentication mechanisms.
+func (n *Email) auth(mechs string) (smtp.Auth, error) {
+ username := n.conf.AuthUsername
+
+ for _, mech := range strings.Split(mechs, " ") {
+ switch mech {
+ case "CRAM-MD5":
+ secret := string(n.conf.AuthSecret)
+ if secret == "" {
+ continue
+ }
+ return smtp.CRAMMD5Auth(username, secret), nil
+
+ case "PLAIN":
+ password := string(n.conf.AuthPassword)
+ if password == "" {
+ continue
+ }
+ identity := n.conf.AuthIdentity
+
+ // We need to know the hostname for both auth and TLS.
+ host, _, err := net.SplitHostPort(n.conf.Smarthost)
+ if err != nil {
+ return nil, fmt.Errorf("invalid address: %s", err)
+ }
+ return smtp.PlainAuth(identity, username, password, host), nil
+ case "LOGIN":
+ password := string(n.conf.AuthPassword)
+ if password == "" {
+ continue
+ }
+ return LoginAuth(username, password), nil
+ }
+ }
+ return nil, nil
+}
+
+// Notify implements the Notifier interface.
+func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) {
+ // We need to know the hostname for both auth and TLS.
+ var c *smtp.Client
+ host, port, err := net.SplitHostPort(n.conf.Smarthost)
+ if err != nil {
+ return false, fmt.Errorf("invalid address: %s", err)
+ }
+
+ if port == "465" {
+ conn, err := tls.Dial("tcp", n.conf.Smarthost, &tls.Config{ServerName: host})
+ if err != nil {
+ return true, err
+ }
+ c, err = smtp.NewClient(conn, n.conf.Smarthost)
+ if err != nil {
+ return true, err
+ }
+
+ } else {
+ // Connect to the SMTP smarthost.
+ c, err = smtp.Dial(n.conf.Smarthost)
+ if err != nil {
+ return true, err
+ }
+ }
+ defer c.Quit()
+
+ if n.conf.Hello != "" {
+ err := c.Hello(n.conf.Hello)
+ if err != nil {
+ return true, err
+ }
+ }
+
+ // Global Config guarantees RequireTLS is not nil
+ if *n.conf.RequireTLS {
+ if ok, _ := c.Extension("STARTTLS"); !ok {
+ return true, fmt.Errorf("require_tls: true (default), but %q does not advertise the STARTTLS extension", n.conf.Smarthost)
+ }
+ tlsConf := &tls.Config{ServerName: host}
+ if err := c.StartTLS(tlsConf); err != nil {
+ return true, fmt.Errorf("starttls failed: %s", err)
+ }
+ }
+
+ if ok, mech := c.Extension("AUTH"); ok {
+ auth, err := n.auth(mech)
+ if err != nil {
+ return true, err
+ }
+ if auth != nil {
+ if err := c.Auth(auth); err != nil {
+ return true, fmt.Errorf("%T failed: %s", auth, err)
+ }
+ }
+ }
+
+ var (
+ data = n.tmpl.Data(receiverName(ctx, n.logger), groupLabels(ctx, n.logger), as...)
+ tmpl = tmplText(n.tmpl, data, &err)
+ from = tmpl(n.conf.From)
+ to = tmpl(n.conf.To)
+ )
+ if err != nil {
+ return false, err
+ }
+
+ addrs, err := mail.ParseAddressList(from)
+ if err != nil {
+ return false, fmt.Errorf("parsing from addresses: %s", err)
+ }
+ if len(addrs) != 1 {
+ return false, fmt.Errorf("must be exactly one from address")
+ }
+ if err := c.Mail(addrs[0].Address); err != nil {
+ return true, fmt.Errorf("sending mail from: %s", err)
+ }
+ addrs, err = mail.ParseAddressList(to)
+ if err != nil {
+ return false, fmt.Errorf("parsing to addresses: %s", err)
+ }
+ for _, addr := range addrs {
+ if err := c.Rcpt(addr.Address); err != nil {
+ return true, fmt.Errorf("sending rcpt to: %s", err)
+ }
+ }
+
+ // Send the email body.
+ wc, err := c.Data()
+ if err != nil {
+ return true, err
+ }
+ defer wc.Close()
+
+ for header, t := range n.conf.Headers {
+ value, err := n.tmpl.ExecuteTextString(t, data)
+ if err != nil {
+ return false, fmt.Errorf("executing %q header template: %s", header, err)
+ }
+ fmt.Fprintf(wc, "%s: %s\r\n", header, mime.QEncoding.Encode("utf-8", value))
+ }
+
+ buffer := &bytes.Buffer{}
+ multipartWriter := multipart.NewWriter(buffer)
+
+ fmt.Fprintf(wc, "Date: %s\r\n", time.Now().Format(time.RFC1123Z))
+ fmt.Fprintf(wc, "Content-Type: multipart/alternative; boundary=%s\r\n", multipartWriter.Boundary())
+ fmt.Fprintf(wc, "MIME-Version: 1.0\r\n")
+
+ // TODO: Add some useful headers here, such as URL of the alertmanager
+ // and active/resolved.
+ fmt.Fprintf(wc, "\r\n")
+
+ if len(n.conf.Text) > 0 {
+ // Text template
+ w, err := multipartWriter.CreatePart(textproto.MIMEHeader{"Content-Type": {"text/plain; charset=UTF-8"}})
+ if err != nil {
+ return false, fmt.Errorf("creating part for text template: %s", err)
+ }
+ body, err := n.tmpl.ExecuteTextString(n.conf.Text, data)
+ if err != nil {
+ return false, fmt.Errorf("executing email text template: %s", err)
+ }
+ _, err = w.Write([]byte(body))
+ if err != nil {
+ return true, err
+ }
+ }
+
+ if len(n.conf.HTML) > 0 {
+ // Html template
+ // Preferred alternative placed last per section 5.1.4 of RFC 2046
+ // https://www.ietf.org/rfc/rfc2046.txt
+ w, err := multipartWriter.CreatePart(textproto.MIMEHeader{"Content-Type": {"text/html; charset=UTF-8"}})
+ if err != nil {
+ return false, fmt.Errorf("creating part for html template: %s", err)
+ }
+ body, err := n.tmpl.ExecuteHTMLString(n.conf.HTML, data)
+ if err != nil {
+ return false, fmt.Errorf("executing email html template: %s", err)
+ }
+ _, err = w.Write([]byte(body))
+ if err != nil {
+ return true, err
+ }
+ }
+
+ multipartWriter.Close()
+ wc.Write(buffer.Bytes())
+
+ return false, nil
+}
+
+// PagerDuty implements a Notifier for PagerDuty notifications.
+type PagerDuty struct {
+ conf *config.PagerdutyConfig
+ tmpl *template.Template
+ logger log.Logger
+}
+
+// NewPagerDuty returns a new PagerDuty notifier.
+func NewPagerDuty(c *config.PagerdutyConfig, t *template.Template, l log.Logger) *PagerDuty {
+ return &PagerDuty{conf: c, tmpl: t, logger: l}
+}
+
+const (
+ pagerDutyEventTrigger = "trigger"
+ pagerDutyEventResolve = "resolve"
+)
+
+type pagerDutyMessage struct {
+ RoutingKey string `json:"routing_key,omitempty"`
+ ServiceKey string `json:"service_key,omitempty"`
+ DedupKey string `json:"dedup_key,omitempty"`
+ IncidentKey string `json:"incident_key,omitempty"`
+ EventType string `json:"event_type,omitempty"`
+ Description string `json:"description,omitempty"`
+ EventAction string `json:"event_action"`
+ Payload *pagerDutyPayload `json:"payload"`
+ Client string `json:"client,omitempty"`
+ ClientURL string `json:"client_url,omitempty"`
+ Details map[string]string `json:"details,omitempty"`
+}
+
+type pagerDutyPayload struct {
+ Summary string `json:"summary"`
+ Source string `json:"source"`
+ Severity string `json:"severity"`
+ Timestamp string `json:"timestamp,omitempty"`
+ Class string `json:"class,omitempty"`
+ Component string `json:"component,omitempty"`
+ Group string `json:"group,omitempty"`
+ CustomDetails map[string]string `json:"custom_details,omitempty"`
+}
+
+func (n *PagerDuty) notifyV1(ctx context.Context, c *http.Client, eventType, key string, tmpl func(string) string, details map[string]string, as ...*types.Alert) (bool, error) {
+
+ msg := &pagerDutyMessage{
+ ServiceKey: tmpl(string(n.conf.ServiceKey)),
+ EventType: eventType,
+ IncidentKey: hashKey(key),
+ Description: tmpl(n.conf.Description),
+ Details: details,
+ }
+
+ n.conf.URL = "https://events.pagerduty.com/generic/2010-04-15/create_event.json"
+
+ if eventType == pagerDutyEventTrigger {
+ msg.Client = tmpl(n.conf.Client)
+ msg.ClientURL = tmpl(n.conf.ClientURL)
+ }
+
+ var buf bytes.Buffer
+ if err := json.NewEncoder(&buf).Encode(msg); err != nil {
+ return false, err
+ }
+
+ resp, err := ctxhttp.Post(ctx, c, n.conf.URL, contentTypeJSON, &buf)
+ if err != nil {
+ return true, err
+ }
+ defer resp.Body.Close()
+
+ return n.retryV1(resp.StatusCode)
+}
+
+func (n *PagerDuty) notifyV2(ctx context.Context, c *http.Client, eventType, key string, tmpl func(string) string, details map[string]string, as ...*types.Alert) (bool, error) {
+ if n.conf.Severity == "" {
+ n.conf.Severity = "error"
+ }
+
+ var payload *pagerDutyPayload
+ if eventType == pagerDutyEventTrigger {
+ payload = &pagerDutyPayload{
+ Summary: tmpl(n.conf.Description),
+ Source: tmpl(n.conf.Client),
+ Severity: tmpl(n.conf.Severity),
+ CustomDetails: details,
+ Class: tmpl(n.conf.Class),
+ Component: tmpl(n.conf.Component),
+ Group: tmpl(n.conf.Group),
+ }
+ }
+
+ msg := &pagerDutyMessage{
+ RoutingKey: tmpl(string(n.conf.RoutingKey)),
+ EventAction: eventType,
+ DedupKey: hashKey(key),
+ Payload: payload,
+ }
+
+ if eventType == pagerDutyEventTrigger {
+ msg.Client = tmpl(n.conf.Client)
+ msg.ClientURL = tmpl(n.conf.ClientURL)
+ }
+
+ var buf bytes.Buffer
+ if err := json.NewEncoder(&buf).Encode(msg); err != nil {
+ return false, err
+ }
+
+ resp, err := ctxhttp.Post(ctx, c, n.conf.URL, contentTypeJSON, &buf)
+ if err != nil {
+ return true, err
+ }
+ defer resp.Body.Close()
+
+ return n.retryV2(resp.StatusCode)
+}
+
+// Notify implements the Notifier interface.
+//
+// https://v2.developer.pagerduty.com/docs/events-api-v2
+func (n *PagerDuty) Notify(ctx context.Context, as ...*types.Alert) (bool, error) {
+ key, ok := GroupKey(ctx)
+ if !ok {
+ return false, fmt.Errorf("group key missing")
+ }
+
+ var err error
+ var (
+ alerts = types.Alerts(as...)
+ data = n.tmpl.Data(receiverName(ctx, n.logger), groupLabels(ctx, n.logger), as...)
+ tmpl = tmplText(n.tmpl, data, &err)
+ eventType = pagerDutyEventTrigger
+ )
+ if alerts.Status() == model.AlertResolved {
+ eventType = pagerDutyEventResolve
+ }
+
+ level.Debug(n.logger).Log("msg", "Notifying PagerDuty", "incident", key, "eventType", eventType)
+
+ details := make(map[string]string, len(n.conf.Details))
+ for k, v := range n.conf.Details {
+ details[k] = tmpl(v)
+ }
+
+ if err != nil {
+ return false, err
+ }
+
+ c, err := commoncfg.NewClientFromConfig(*n.conf.HTTPConfig, "pagerduty")
+ if err != nil {
+ return false, err
+ }
+
+ if n.conf.ServiceKey != "" {
+ return n.notifyV1(ctx, c, eventType, key, tmpl, details, as...)
+ }
+ return n.notifyV2(ctx, c, eventType, key, tmpl, details, as...)
+}
+
+func (n *PagerDuty) retryV1(statusCode int) (bool, error) {
+ // Retrying can solve the issue on 403 (rate limiting) and 5xx response codes.
+ // 2xx response codes indicate a successful request.
+ // https://v2.developer.pagerduty.com/docs/trigger-events
+ if statusCode/100 != 2 {
+ return (statusCode == 403 || statusCode/100 == 5), fmt.Errorf("unexpected status code %v", statusCode)
+ }
+
+ return false, nil
+}
+
+func (n *PagerDuty) retryV2(statusCode int) (bool, error) {
+ // Retrying can solve the issue on 429 (rate limiting) and 5xx response codes.
+ // 2xx response codes indicate a successful request.
+ // https://v2.developer.pagerduty.com/docs/events-api-v2#api-response-codes--retry-logic
+ if statusCode/100 != 2 {
+ return (statusCode == 429 || statusCode/100 == 5), fmt.Errorf("unexpected status code %v", statusCode)
+ }
+
+ return false, nil
+}
+
+// Slack implements a Notifier for Slack notifications.
+type Slack struct {
+ conf *config.SlackConfig
+ tmpl *template.Template
+ logger log.Logger
+}
+
+// NewSlack returns a new Slack notification handler.
+func NewSlack(c *config.SlackConfig, t *template.Template, l log.Logger) *Slack {
+ return &Slack{
+ conf: c,
+ tmpl: t,
+ logger: l,
+ }
+}
+
+// slackReq is the request for sending a slack notification.
+type slackReq struct {
+ Channel string `json:"channel,omitempty"`
+ Username string `json:"username,omitempty"`
+ IconEmoji string `json:"icon_emoji,omitempty"`
+ IconURL string `json:"icon_url,omitempty"`
+ LinkNames bool `json:"link_names,omitempty"`
+ Attachments []slackAttachment `json:"attachments"`
+}
+
+// slackAttachment is used to display a richly-formatted message block.
+type slackAttachment struct {
+ Title string `json:"title,omitempty"`
+ TitleLink string `json:"title_link,omitempty"`
+ Pretext string `json:"pretext,omitempty"`
+ Text string `json:"text"`
+ Fallback string `json:"fallback"`
+ Fields []config.SlackField `json:"fields,omitempty"`
+ Actions []config.SlackAction `json:"actions,omitempty"`
+ Footer string `json:"footer"`
+
+ Color string `json:"color,omitempty"`
+ MrkdwnIn []string `json:"mrkdwn_in,omitempty"`
+}
+
+// Notify implements the Notifier interface.
+func (n *Slack) Notify(ctx context.Context, as ...*types.Alert) (bool, error) {
+ var err error
+ var (
+ data = n.tmpl.Data(receiverName(ctx, n.logger), groupLabels(ctx, n.logger), as...)
+ tmplText = tmplText(n.tmpl, data, &err)
+ )
+
+ attachment := &slackAttachment{
+ Title: tmplText(n.conf.Title),
+ TitleLink: tmplText(n.conf.TitleLink),
+ Pretext: tmplText(n.conf.Pretext),
+ Text: tmplText(n.conf.Text),
+ Fallback: tmplText(n.conf.Fallback),
+ Footer: tmplText(n.conf.Footer),
+ Color: tmplText(n.conf.Color),
+ MrkdwnIn: []string{"fallback", "pretext", "text"},
+ }
+
+ var numFields = len(n.conf.Fields)
+ if numFields > 0 {
+ var fields = make([]config.SlackField, numFields)
+ for index, field := range n.conf.Fields {
+ // Check if short was defined for the field otherwise fallback to the global setting
+ var short bool
+ if field.Short != nil {
+ short = *field.Short
+ } else {
+ short = n.conf.ShortFields
+ }
+
+ // Rebuild the field by executing any templates and setting the new value for short
+ fields[index] = config.SlackField{
+ Title: tmplText(field.Title),
+ Value: tmplText(field.Value),
+ Short: &short,
+ }
+ }
+ attachment.Fields = fields
+ }
+
+ var numActions = len(n.conf.Actions)
+ if numActions > 0 {
+ var actions = make([]config.SlackAction, numActions)
+ for index, action := range n.conf.Actions {
+ actions[index] = config.SlackAction{
+ Type: tmplText(action.Type),
+ Text: tmplText(action.Text),
+ URL: tmplText(action.URL),
+ Style: tmplText(action.Style),
+ }
+ }
+ attachment.Actions = actions
+ }
+
+ req := &slackReq{
+ Channel: tmplText(n.conf.Channel),
+ Username: tmplText(n.conf.Username),
+ IconEmoji: tmplText(n.conf.IconEmoji),
+ IconURL: tmplText(n.conf.IconURL),
+ LinkNames: n.conf.LinkNames,
+ Attachments: []slackAttachment{*attachment},
+ }
+ if err != nil {
+ return false, err
+ }
+
+ var buf bytes.Buffer
+ if err := json.NewEncoder(&buf).Encode(req); err != nil {
+ return false, err
+ }
+
+ c, err := commoncfg.NewClientFromConfig(*n.conf.HTTPConfig, "slack")
+ if err != nil {
+ return false, err
+ }
+
+ resp, err := ctxhttp.Post(ctx, c, string(n.conf.APIURL), contentTypeJSON, &buf)
+ if err != nil {
+ return true, err
+ }
+ resp.Body.Close()
+
+ return n.retry(resp.StatusCode)
+}
+
+func (n *Slack) retry(statusCode int) (bool, error) {
+ // Only 5xx response codes are recoverable and 2xx codes are successful.
+ // https://api.slack.com/incoming-webhooks#handling_errors
+ // https://api.slack.com/changelog/2016-05-17-changes-to-errors-for-incoming-webhooks
+ if statusCode/100 != 2 {
+ return (statusCode/100 == 5), fmt.Errorf("unexpected status code %v", statusCode)
+ }
+
+ return false, nil
+}
+
+// Hipchat implements a Notifier for Hipchat notifications.
+type Hipchat struct {
+ conf *config.HipchatConfig
+ tmpl *template.Template
+ logger log.Logger
+}
+
+// NewHipchat returns a new Hipchat notification handler.
+func NewHipchat(c *config.HipchatConfig, t *template.Template, l log.Logger) *Hipchat {
+ return &Hipchat{
+ conf: c,
+ tmpl: t,
+ logger: l,
+ }
+}
+
+type hipchatReq struct {
+ From string `json:"from"`
+ Notify bool `json:"notify"`
+ Message string `json:"message"`
+ MessageFormat string `json:"message_format"`
+ Color string `json:"color"`
+}
+
+// Notify implements the Notifier interface.
+func (n *Hipchat) Notify(ctx context.Context, as ...*types.Alert) (bool, error) {
+ var err error
+ var msg string
+ var (
+ data = n.tmpl.Data(receiverName(ctx, n.logger), groupLabels(ctx, n.logger), as...)
+ tmplText = tmplText(n.tmpl, data, &err)
+ tmplHTML = tmplHTML(n.tmpl, data, &err)
+ url = fmt.Sprintf("%sv2/room/%s/notification?auth_token=%s", n.conf.APIURL, n.conf.RoomID, n.conf.AuthToken)
+ )
+
+ if n.conf.MessageFormat == "html" {
+ msg = tmplHTML(n.conf.Message)
+ } else {
+ msg = tmplText(n.conf.Message)
+ }
+
+ req := &hipchatReq{
+ From: tmplText(n.conf.From),
+ Notify: n.conf.Notify,
+ Message: msg,
+ MessageFormat: n.conf.MessageFormat,
+ Color: tmplText(n.conf.Color),
+ }
+ if err != nil {
+ return false, err
+ }
+
+ var buf bytes.Buffer
+ if err := json.NewEncoder(&buf).Encode(req); err != nil {
+ return false, err
+ }
+
+ c, err := commoncfg.NewClientFromConfig(*n.conf.HTTPConfig, "hipchat")
+ if err != nil {
+ return false, err
+ }
+
+ resp, err := ctxhttp.Post(ctx, c, url, contentTypeJSON, &buf)
+ if err != nil {
+ return true, err
+ }
+
+ defer resp.Body.Close()
+
+ return n.retry(resp.StatusCode)
+}
+
+func (n *Hipchat) retry(statusCode int) (bool, error) {
+ // Response codes 429 (rate limiting) and 5xx can potentially recover. 2xx
+ // responce codes indicate successful requests.
+ // https://developer.atlassian.com/hipchat/guide/hipchat-rest-api/api-response-codes
+ if statusCode/100 != 2 {
+ return (statusCode == 429 || statusCode/100 == 5), fmt.Errorf("unexpected status code %v", statusCode)
+ }
+
+ return false, nil
+}
+
+// Wechat implements a Notfier for wechat notifications
+type Wechat struct {
+ conf *config.WechatConfig
+ tmpl *template.Template
+ logger log.Logger
+
+ accessToken string
+ accessTokenAt time.Time
+}
+
+// Wechat AccessToken with corpid and corpsecret.
+type WechatToken struct {
+ AccessToken string `json:"access_token"`
+}
+
+type weChatMessage struct {
+ Text weChatMessageContent `yaml:"text,omitempty" json:"text,omitempty"`
+ ToUser string `yaml:"touser,omitempty" json:"touser,omitempty"`
+ ToParty string `yaml:"toparty,omitempty" json:"toparty,omitempty"`
+ Totag string `yaml:"totag,omitempty" json:"totag,omitempty"`
+ AgentID string `yaml:"agentid,omitempty" json:"agentid,omitempty"`
+ Safe string `yaml:"safe,omitempty" json:"safe,omitempty"`
+ Type string `yaml:"msgtype,omitempty" json:"msgtype,omitempty"`
+}
+
+type weChatMessageContent struct {
+ Content string `json:"content"`
+}
+
+type weChatResponse struct {
+ Code int `json:"code"`
+ Error string `json:"error"`
+}
+
+// NewWechat returns a new Wechat notifier.
+func NewWechat(c *config.WechatConfig, t *template.Template, l log.Logger) *Wechat {
+ return &Wechat{conf: c, tmpl: t, logger: l}
+}
+
+// Notify implements the Notifier interface.
+func (n *Wechat) Notify(ctx context.Context, as ...*types.Alert) (bool, error) {
+ key, ok := GroupKey(ctx)
+ if !ok {
+ return false, fmt.Errorf("group key missing")
+ }
+
+ level.Debug(n.logger).Log("msg", "Notifying Wechat", "incident", key)
+ data := n.tmpl.Data(receiverName(ctx, n.logger), groupLabels(ctx, n.logger), as...)
+
+ var err error
+ tmpl := tmplText(n.tmpl, data, &err)
+ if err != nil {
+ return false, err
+ }
+
+ c, err := commoncfg.NewClientFromConfig(*n.conf.HTTPConfig, "wechat")
+ if err != nil {
+ return false, err
+ }
+
+ // Refresh AccessToken over 2 hours
+ if n.accessToken == "" || time.Now().Sub(n.accessTokenAt) > 2*time.Hour {
+ parameters := url.Values{}
+ parameters.Add("corpsecret", tmpl(string(n.conf.APISecret)))
+ parameters.Add("corpid", tmpl(string(n.conf.CorpID)))
+
+ apiURL := n.conf.APIURL + "gettoken"
+
+ u, err := url.Parse(apiURL)
+ if err != nil {
+ return false, err
+ }
+
+ u.RawQuery = parameters.Encode()
+
+ level.Debug(n.logger).Log("msg", "Sending Wechat message", "incident", key, "url", u.String())
+
+ req, err := http.NewRequest(http.MethodGet, u.String(), nil)
+ if err != nil {
+ return true, err
+ }
+
+ req.Header.Set("Content-Type", contentTypeJSON)
+
+ resp, err := c.Do(req.WithContext(ctx))
+ if err != nil {
+ return true, err
+ }
+ defer resp.Body.Close()
+
+ var wechatToken WechatToken
+ if err := json.NewDecoder(resp.Body).Decode(&wechatToken); err != nil {
+ return false, err
+ }
+
+ if wechatToken.AccessToken == "" {
+ return false, fmt.Errorf("invalid APISecret for CorpID: %s", n.conf.CorpID)
+ }
+
+ // Cache accessToken
+ n.accessToken = wechatToken.AccessToken
+ n.accessTokenAt = time.Now()
+ }
+
+ msg := &weChatMessage{
+ Text: weChatMessageContent{
+ Content: tmpl(n.conf.Message),
+ },
+ ToUser: tmpl(n.conf.ToUser),
+ ToParty: tmpl(n.conf.ToParty),
+ Totag: tmpl(n.conf.ToTag),
+ AgentID: tmpl(n.conf.AgentID),
+ Type: "text",
+ Safe: "0",
+ }
+
+ var buf bytes.Buffer
+ if err := json.NewEncoder(&buf).Encode(msg); err != nil {
+ return false, err
+ }
+
+ postMessageURL := n.conf.APIURL + "message/send?access_token=" + n.accessToken
+
+ req, err := http.NewRequest(http.MethodPost, postMessageURL, &buf)
+ if err != nil {
+ return true, err
+ }
+
+ resp, err := c.Do(req.WithContext(ctx))
+ if err != nil {
+ return true, err
+ }
+ defer resp.Body.Close()
+
+ body, _ := ioutil.ReadAll(resp.Body)
+ level.Debug(n.logger).Log("msg", "response: "+string(body), "incident", key)
+
+ if resp.StatusCode != 200 {
+ return true, fmt.Errorf("unexpected status code %v", resp.StatusCode)
+ } else {
+ var weResp weChatResponse
+ if err := json.Unmarshal(body, &weResp); err != nil {
+ return true, err
+ }
+
+ // https://work.weixin.qq.com/api/doc#10649
+ if weResp.Code == 0 {
+ return false, nil
+ }
+
+ // AccessToken is expired
+ if weResp.Code == 42001 {
+ n.accessToken = ""
+ return true, errors.New(weResp.Error)
+ }
+
+ return false, errors.New(weResp.Error)
+ }
+}
+
+// OpsGenie implements a Notifier for OpsGenie notifications.
+type OpsGenie struct {
+ conf *config.OpsGenieConfig
+ tmpl *template.Template
+ logger log.Logger
+}
+
+// NewOpsGenie returns a new OpsGenie notifier.
+func NewOpsGenie(c *config.OpsGenieConfig, t *template.Template, l log.Logger) *OpsGenie {
+ return &OpsGenie{conf: c, tmpl: t, logger: l}
+}
+
+type opsGenieCreateMessage struct {
+ Alias string `json:"alias"`
+ Message string `json:"message"`
+ Description string `json:"description,omitempty"`
+ Details map[string]string `json:"details"`
+ Source string `json:"source"`
+ Teams []map[string]string `json:"teams,omitempty"`
+ Tags []string `json:"tags,omitempty"`
+ Note string `json:"note,omitempty"`
+ Priority string `json:"priority,omitempty"`
+}
+
+type opsGenieCloseMessage struct {
+ Source string `json:"source"`
+}
+
+// Notify implements the Notifier interface.
+func (n *OpsGenie) Notify(ctx context.Context, as ...*types.Alert) (bool, error) {
+ req, retry, err := n.createRequest(ctx, as...)
+ if err != nil {
+ return retry, err
+ }
+
+ c, err := commoncfg.NewClientFromConfig(*n.conf.HTTPConfig, "opsgenie")
+ if err != nil {
+ return false, err
+ }
+
+ resp, err := ctxhttp.Do(ctx, c, req)
+
+ if err != nil {
+ return true, err
+ }
+ defer resp.Body.Close()
+
+ return n.retry(resp.StatusCode)
+}
+
+// Like Split but filter out empty strings.
+func safeSplit(s string, sep string) []string {
+ a := strings.Split(strings.TrimSpace(s), sep)
+ b := a[:0]
+ for _, x := range a {
+ if x != "" {
+ b = append(b, x)
+ }
+ }
+ return b
+}
+
+// Create requests for a list of alerts.
+func (n *OpsGenie) createRequest(ctx context.Context, as ...*types.Alert) (*http.Request, bool, error) {
+ key, ok := GroupKey(ctx)
+ if !ok {
+ return nil, false, fmt.Errorf("group key missing")
+ }
+ data := n.tmpl.Data(receiverName(ctx, n.logger), groupLabels(ctx, n.logger), as...)
+
+ level.Debug(n.logger).Log("msg", "Notifying OpsGenie", "incident", key)
+
+ var err error
+ tmpl := tmplText(n.tmpl, data, &err)
+
+ details := make(map[string]string, len(n.conf.Details))
+ for k, v := range n.conf.Details {
+ details[k] = tmpl(v)
+ }
+
+ var (
+ msg interface{}
+ apiURL string
+ alias = hashKey(key)
+ alerts = types.Alerts(as...)
+ )
+ switch alerts.Status() {
+ case model.AlertResolved:
+ apiURL = fmt.Sprintf("%sv2/alerts/%s/close?identifierType=alias", n.conf.APIURL, alias)
+ msg = &opsGenieCloseMessage{Source: tmpl(n.conf.Source)}
+ default:
+ message := tmpl(n.conf.Message)
+ if len(message) > 130 {
+ message = message[:127] + "..."
+ level.Debug(n.logger).Log("msg", "Truncated message to %q due to OpsGenie message limit", "truncated_message", message, "incident", key)
+ }
+
+ apiURL = n.conf.APIURL + "v2/alerts"
+ var teams []map[string]string
+ for _, t := range safeSplit(string(tmpl(n.conf.Teams)), ",") {
+ teams = append(teams, map[string]string{"name": t})
+ }
+ tags := safeSplit(string(tmpl(n.conf.Tags)), ",")
+
+ msg = &opsGenieCreateMessage{
+ Alias: alias,
+ Message: message,
+ Description: tmpl(n.conf.Description),
+ Details: details,
+ Source: tmpl(n.conf.Source),
+ Teams: teams,
+ Tags: tags,
+ Note: tmpl(n.conf.Note),
+ Priority: tmpl(n.conf.Priority),
+ }
+ }
+ if err != nil {
+ return nil, false, fmt.Errorf("templating error: %s", err)
+ }
+
+ var buf bytes.Buffer
+ if err := json.NewEncoder(&buf).Encode(msg); err != nil {
+ return nil, false, err
+ }
+
+ req, err := http.NewRequest("POST", apiURL, &buf)
+ if err != nil {
+ return nil, true, err
+ }
+ req.Header.Set("Content-Type", contentTypeJSON)
+ req.Header.Set("Authorization", fmt.Sprintf("GenieKey %s", n.conf.APIKey))
+ return req, true, nil
+}
+
+func (n *OpsGenie) retry(statusCode int) (bool, error) {
+ // https://docs.opsgenie.com/docs/response#section-response-codes
+ // Response codes 429 (rate limiting) and 5xx are potentially recoverable
+ if statusCode/100 == 5 || statusCode == 429 {
+ return true, fmt.Errorf("unexpected status code %v", statusCode)
+ } else if statusCode/100 != 2 {
+ return false, fmt.Errorf("unexpected status code %v", statusCode)
+ }
+
+ return false, nil
+}
+
+// VictorOps implements a Notifier for VictorOps notifications.
+type VictorOps struct {
+ conf *config.VictorOpsConfig
+ tmpl *template.Template
+ logger log.Logger
+}
+
+// NewVictorOps returns a new VictorOps notifier.
+func NewVictorOps(c *config.VictorOpsConfig, t *template.Template, l log.Logger) *VictorOps {
+ return &VictorOps{
+ conf: c,
+ tmpl: t,
+ logger: l,
+ }
+}
+
+const (
+ victorOpsEventTrigger = "CRITICAL"
+ victorOpsEventResolve = "RECOVERY"
+)
+
+type victorOpsMessage struct {
+ MessageType string `json:"message_type"`
+ EntityID string `json:"entity_id"`
+ EntityDisplayName string `json:"entity_display_name"`
+ StateMessage string `json:"state_message"`
+ MonitoringTool string `json:"monitoring_tool"`
+}
+
+// Notify implements the Notifier interface.
+func (n *VictorOps) Notify(ctx context.Context, as ...*types.Alert) (bool, error) {
+ victorOpsAllowedEvents := map[string]bool{
+ "INFO": true,
+ "WARNING": true,
+ "CRITICAL": true,
+ }
+
+ key, ok := GroupKey(ctx)
+ if !ok {
+ return false, fmt.Errorf("group key missing")
+ }
+
+ var err error
+ var (
+ alerts = types.Alerts(as...)
+ data = n.tmpl.Data(receiverName(ctx, n.logger), groupLabels(ctx, n.logger), as...)
+ tmpl = tmplText(n.tmpl, data, &err)
+ apiURL = fmt.Sprintf("%s%s/%s", n.conf.APIURL, n.conf.APIKey, tmpl(n.conf.RoutingKey))
+ messageType = tmpl(n.conf.MessageType)
+ stateMessage = tmpl(n.conf.StateMessage)
+ )
+
+ if alerts.Status() == model.AlertFiring && !victorOpsAllowedEvents[messageType] {
+ messageType = victorOpsEventTrigger
+ }
+
+ if alerts.Status() == model.AlertResolved {
+ messageType = victorOpsEventResolve
+ }
+
+ if len(stateMessage) > 20480 {
+ stateMessage = stateMessage[0:20475] + "\n..."
+ level.Debug(n.logger).Log("msg", "Truncated stateMessage due to VictorOps stateMessage limit", "truncated_state_message", stateMessage, "incident", key)
+ }
+
+ msg := &victorOpsMessage{
+ MessageType: messageType,
+ EntityID: hashKey(key),
+ EntityDisplayName: tmpl(n.conf.EntityDisplayName),
+ StateMessage: stateMessage,
+ MonitoringTool: tmpl(n.conf.MonitoringTool),
+ }
+
+ if err != nil {
+ return false, fmt.Errorf("templating error: %s", err)
+ }
+
+ var buf bytes.Buffer
+ if err := json.NewEncoder(&buf).Encode(msg); err != nil {
+ return false, err
+ }
+
+ c, err := commoncfg.NewClientFromConfig(*n.conf.HTTPConfig, "victorops")
+ if err != nil {
+ return false, err
+ }
+
+ resp, err := ctxhttp.Post(ctx, c, apiURL, contentTypeJSON, &buf)
+ if err != nil {
+ return true, err
+ }
+
+ defer resp.Body.Close()
+
+ return n.retry(resp.StatusCode)
+}
+
+func (n *VictorOps) retry(statusCode int) (bool, error) {
+ // Missing documentation therefore assuming only 5xx response codes are
+ // recoverable.
+ if statusCode/100 == 5 {
+ return true, fmt.Errorf("unexpected status code %v", statusCode)
+ } else if statusCode/100 != 2 {
+ return false, fmt.Errorf("unexpected status code %v", statusCode)
+ }
+
+ return false, nil
+}
+
+// Pushover implements a Notifier for Pushover notifications.
+type Pushover struct {
+ conf *config.PushoverConfig
+ tmpl *template.Template
+ logger log.Logger
+}
+
+// NewPushover returns a new Pushover notifier.
+func NewPushover(c *config.PushoverConfig, t *template.Template, l log.Logger) *Pushover {
+ return &Pushover{conf: c, tmpl: t, logger: l}
+}
+
+// Notify implements the Notifier interface.
+func (n *Pushover) Notify(ctx context.Context, as ...*types.Alert) (bool, error) {
+ key, ok := GroupKey(ctx)
+ if !ok {
+ return false, fmt.Errorf("group key missing")
+ }
+ data := n.tmpl.Data(receiverName(ctx, n.logger), groupLabels(ctx, n.logger), as...)
+
+ level.Debug(n.logger).Log("msg", "Notifying Pushover", "incident", key)
+
+ var err error
+ tmpl := tmplText(n.tmpl, data, &err)
+
+ parameters := url.Values{}
+ parameters.Add("token", tmpl(string(n.conf.Token)))
+ parameters.Add("user", tmpl(string(n.conf.UserKey)))
+
+ title := tmpl(n.conf.Title)
+ if len(title) > 250 {
+ title = title[:247] + "..."
+ level.Debug(n.logger).Log("msg", "Truncated title due to Pushover title limit", "truncated_title", title, "incident", key)
+ }
+ parameters.Add("title", title)
+
+ message := tmpl(n.conf.Message)
+ if len(message) > 1024 {
+ message = message[:1021] + "..."
+ level.Debug(n.logger).Log("msg", "Truncated message due to Pushover message limit", "truncated_message", message, "incident", key)
+ }
+ message = strings.TrimSpace(message)
+ if message == "" {
+ // Pushover rejects empty messages.
+ message = "(no details)"
+ }
+ parameters.Add("message", message)
+
+ supplementaryURL := tmpl(n.conf.URL)
+ if len(supplementaryURL) > 512 {
+ supplementaryURL = supplementaryURL[:509] + "..."
+ level.Debug(n.logger).Log("msg", "Truncated URL due to Pushover url limit", "truncated_url", supplementaryURL, "incident", key)
+ }
+ parameters.Add("url", supplementaryURL)
+
+ parameters.Add("priority", tmpl(n.conf.Priority))
+ parameters.Add("retry", fmt.Sprintf("%d", int64(time.Duration(n.conf.Retry).Seconds())))
+ parameters.Add("expire", fmt.Sprintf("%d", int64(time.Duration(n.conf.Expire).Seconds())))
+ if err != nil {
+ return false, err
+ }
+
+ apiURL := "https://api.pushover.net/1/messages.json"
+ u, err := url.Parse(apiURL)
+ if err != nil {
+ return false, err
+ }
+ u.RawQuery = parameters.Encode()
+ level.Debug(n.logger).Log("msg", "Sending Pushover message", "incident", key, "url", u.String())
+
+ c, err := commoncfg.NewClientFromConfig(*n.conf.HTTPConfig, "pushover")
+ if err != nil {
+ return false, err
+ }
+
+ resp, err := ctxhttp.Post(ctx, c, u.String(), "text/plain", nil)
+ if err != nil {
+ return true, err
+ }
+ defer resp.Body.Close()
+
+ return n.retry(resp.StatusCode)
+}
+
+func (n *Pushover) retry(statusCode int) (bool, error) {
+ // Only documented behaviour is that 2xx response codes are successful and
+ // 4xx are unsuccessful, therefore assuming only 5xx are recoverable.
+ // https://pushover.net/api#response
+ if statusCode/100 == 5 {
+ return true, fmt.Errorf("unexpected status code %v", statusCode)
+ } else if statusCode/100 != 2 {
+ return false, fmt.Errorf("unexpected status code %v", statusCode)
+ }
+
+ return false, nil
+}
+
+func tmplText(tmpl *template.Template, data *template.Data, err *error) func(string) string {
+ return func(name string) (s string) {
+ if *err != nil {
+ return
+ }
+ s, *err = tmpl.ExecuteTextString(name, data)
+ return s
+ }
+}
+
+func tmplHTML(tmpl *template.Template, data *template.Data, err *error) func(string) string {
+ return func(name string) (s string) {
+ if *err != nil {
+ return
+ }
+ s, *err = tmpl.ExecuteHTMLString(name, data)
+ return s
+ }
+}
+
+type loginAuth struct {
+ username, password string
+}
+
+func LoginAuth(username, password string) smtp.Auth {
+ return &loginAuth{username, password}
+}
+
+func (a *loginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
+ return "LOGIN", []byte{}, nil
+}
+
+// Used for AUTH LOGIN. (Maybe password should be encrypted)
+func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
+ if more {
+ switch strings.ToLower(string(fromServer)) {
+ case "username:":
+ return []byte(a.username), nil
+ case "password:":
+ return []byte(a.password), nil
+ default:
+ return nil, errors.New("unexpected server challenge")
+ }
+ }
+ return nil, nil
+}
+
+// hashKey returns the sha256 for a group key as integrations may have
+// maximum length requirements on deduplication keys.
+func hashKey(s string) string {
+ h := sha256.New()
+ h.Write([]byte(s))
+ return fmt.Sprintf("%x", h.Sum(nil))
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package notify
+
+import (
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "testing"
+ "time"
+
+ "github.com/go-kit/kit/log"
+ "github.com/stretchr/testify/require"
+ "golang.org/x/net/context"
+
+ "github.com/prometheus/alertmanager/config"
+ "github.com/prometheus/alertmanager/template"
+ "github.com/prometheus/alertmanager/types"
+ "github.com/prometheus/common/model"
+)
+
+func TestWebhookRetry(t *testing.T) {
+ notifier := &Webhook{conf: &config.WebhookConfig{URL: "http://example.com/"}}
+ for statusCode, expected := range retryTests(defaultRetryCodes()) {
+ actual, _ := notifier.retry(statusCode)
+ require.Equal(t, expected, actual, fmt.Sprintf("error on status %d", statusCode))
+ }
+}
+
+func TestPagerDutyRetryV1(t *testing.T) {
+ notifier := new(PagerDuty)
+
+ retryCodes := append(defaultRetryCodes(), http.StatusForbidden)
+ for statusCode, expected := range retryTests(retryCodes) {
+ actual, _ := notifier.retryV1(statusCode)
+ require.Equal(t, expected, actual, fmt.Sprintf("retryv1 - error on status %d", statusCode))
+ }
+}
+
+func TestPagerDutyRetryV2(t *testing.T) {
+ notifier := new(PagerDuty)
+
+ retryCodes := append(defaultRetryCodes(), http.StatusTooManyRequests)
+ for statusCode, expected := range retryTests(retryCodes) {
+ actual, _ := notifier.retryV2(statusCode)
+ require.Equal(t, expected, actual, fmt.Sprintf("retryv2 - error on status %d", statusCode))
+ }
+}
+
+func TestSlackRetry(t *testing.T) {
+ notifier := new(Slack)
+ for statusCode, expected := range retryTests(defaultRetryCodes()) {
+ actual, _ := notifier.retry(statusCode)
+ require.Equal(t, expected, actual, fmt.Sprintf("error on status %d", statusCode))
+ }
+}
+
+func TestHipchatRetry(t *testing.T) {
+ notifier := new(Hipchat)
+ retryCodes := append(defaultRetryCodes(), http.StatusTooManyRequests)
+ for statusCode, expected := range retryTests(retryCodes) {
+ actual, _ := notifier.retry(statusCode)
+ require.Equal(t, expected, actual, fmt.Sprintf("error on status %d", statusCode))
+ }
+}
+
+func TestOpsGenieRetry(t *testing.T) {
+ notifier := new(OpsGenie)
+
+ retryCodes := append(defaultRetryCodes(), http.StatusTooManyRequests)
+ for statusCode, expected := range retryTests(retryCodes) {
+ actual, _ := notifier.retry(statusCode)
+ require.Equal(t, expected, actual, fmt.Sprintf("error on status %d", statusCode))
+ }
+}
+
+func TestVictorOpsRetry(t *testing.T) {
+ notifier := new(VictorOps)
+ for statusCode, expected := range retryTests(defaultRetryCodes()) {
+ actual, _ := notifier.retry(statusCode)
+ require.Equal(t, expected, actual, fmt.Sprintf("error on status %d", statusCode))
+ }
+}
+
+func TestPushoverRetry(t *testing.T) {
+ notifier := new(Pushover)
+ for statusCode, expected := range retryTests(defaultRetryCodes()) {
+ actual, _ := notifier.retry(statusCode)
+ require.Equal(t, expected, actual, fmt.Sprintf("error on status %d", statusCode))
+ }
+}
+
+func retryTests(retryCodes []int) map[int]bool {
+ tests := map[int]bool{
+ // 1xx
+ http.StatusContinue: false,
+ http.StatusSwitchingProtocols: false,
+ http.StatusProcessing: false,
+
+ // 2xx
+ http.StatusOK: false,
+ http.StatusCreated: false,
+ http.StatusAccepted: false,
+ http.StatusNonAuthoritativeInfo: false,
+ http.StatusNoContent: false,
+ http.StatusResetContent: false,
+ http.StatusPartialContent: false,
+ http.StatusMultiStatus: false,
+ http.StatusAlreadyReported: false,
+ http.StatusIMUsed: false,
+
+ // 3xx
+ http.StatusMultipleChoices: false,
+ http.StatusMovedPermanently: false,
+ http.StatusFound: false,
+ http.StatusSeeOther: false,
+ http.StatusNotModified: false,
+ http.StatusUseProxy: false,
+ http.StatusTemporaryRedirect: false,
+ http.StatusPermanentRedirect: false,
+
+ // 4xx
+ http.StatusBadRequest: false,
+ http.StatusUnauthorized: false,
+ http.StatusPaymentRequired: false,
+ http.StatusForbidden: false,
+ http.StatusNotFound: false,
+ http.StatusMethodNotAllowed: false,
+ http.StatusNotAcceptable: false,
+ http.StatusProxyAuthRequired: false,
+ http.StatusRequestTimeout: false,
+ http.StatusConflict: false,
+ http.StatusGone: false,
+ http.StatusLengthRequired: false,
+ http.StatusPreconditionFailed: false,
+ http.StatusRequestEntityTooLarge: false,
+ http.StatusRequestURITooLong: false,
+ http.StatusUnsupportedMediaType: false,
+ http.StatusRequestedRangeNotSatisfiable: false,
+ http.StatusExpectationFailed: false,
+ http.StatusTeapot: false,
+ http.StatusUnprocessableEntity: false,
+ http.StatusLocked: false,
+ http.StatusFailedDependency: false,
+ http.StatusUpgradeRequired: false,
+ http.StatusPreconditionRequired: false,
+ http.StatusTooManyRequests: false,
+ http.StatusRequestHeaderFieldsTooLarge: false,
+ http.StatusUnavailableForLegalReasons: false,
+
+ // 5xx
+ http.StatusInternalServerError: false,
+ http.StatusNotImplemented: false,
+ http.StatusBadGateway: false,
+ http.StatusServiceUnavailable: false,
+ http.StatusGatewayTimeout: false,
+ http.StatusHTTPVersionNotSupported: false,
+ http.StatusVariantAlsoNegotiates: false,
+ http.StatusInsufficientStorage: false,
+ http.StatusLoopDetected: false,
+ http.StatusNotExtended: false,
+ http.StatusNetworkAuthenticationRequired: false,
+ }
+
+ for _, statusCode := range retryCodes {
+ tests[statusCode] = true
+ }
+
+ return tests
+}
+
+func defaultRetryCodes() []int {
+ return []int{
+ http.StatusInternalServerError,
+ http.StatusNotImplemented,
+ http.StatusBadGateway,
+ http.StatusServiceUnavailable,
+ http.StatusGatewayTimeout,
+ http.StatusHTTPVersionNotSupported,
+ http.StatusVariantAlsoNegotiates,
+ http.StatusInsufficientStorage,
+ http.StatusLoopDetected,
+ http.StatusNotExtended,
+ http.StatusNetworkAuthenticationRequired,
+ }
+}
+
+func createTmpl(t *testing.T) *template.Template {
+ tmpl, err := template.FromGlobs()
+ require.NoError(t, err)
+ tmpl.ExternalURL, _ = url.Parse("http://am")
+ return tmpl
+}
+
+func readBody(t *testing.T, r *http.Request) string {
+ body, err := ioutil.ReadAll(r.Body)
+ require.NoError(t, err)
+ return string(body)
+}
+
+func TestOpsGenie(t *testing.T) {
+ logger := log.NewNopLogger()
+ tmpl := createTmpl(t)
+ conf := &config.OpsGenieConfig{
+ NotifierConfig: config.NotifierConfig{
+ VSendResolved: true,
+ },
+ Message: `{{ .CommonLabels.Message }}`,
+ Description: `{{ .CommonLabels.Description }}`,
+ Source: `{{ .CommonLabels.Source }}`,
+ Teams: `{{ .CommonLabels.Teams }}`,
+ Tags: `{{ .CommonLabels.Tags }}`,
+ Note: `{{ .CommonLabels.Note }}`,
+ Priority: `{{ .CommonLabels.Priority }}`,
+ APIKey: `s3cr3t`,
+ APIURL: `https://opsgenie/api`,
+ }
+ notifier := NewOpsGenie(conf, tmpl, logger)
+
+ ctx := context.Background()
+ ctx = WithGroupKey(ctx, "1")
+
+ expectedUrl, _ := url.Parse("https://opsgenie/apiv2/alerts")
+
+ // Empty alert.
+ alert1 := &types.Alert{
+ Alert: model.Alert{
+ StartsAt: time.Now(),
+ EndsAt: time.Now().Add(time.Hour),
+ },
+ }
+ expectedBody := `{"alias":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","message":"","details":{},"source":""}
+`
+ req, retry, err := notifier.createRequest(ctx, alert1)
+ require.NoError(t, err)
+ require.Equal(t, true, retry)
+ require.Equal(t, expectedUrl, req.URL)
+ require.Equal(t, "GenieKey s3cr3t", req.Header.Get("Authorization"))
+ require.Equal(t, expectedBody, readBody(t, req))
+
+ // Fully defined alert.
+ alert2 := &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{
+ "Message": "message",
+ "Description": "description",
+ "Source": "http://prometheus",
+ "Teams": "TeamA,TeamB,",
+ "Tags": "tag1,tag2",
+ "Note": "this is a note",
+ "Priotity": "P1",
+ },
+ StartsAt: time.Now(),
+ EndsAt: time.Now().Add(time.Hour),
+ },
+ }
+ expectedBody = `{"alias":"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b","message":"message","description":"description","details":{},"source":"http://prometheus","teams":[{"name":"TeamA"},{"name":"TeamB"}],"tags":["tag1","tag2"],"note":"this is a note"}
+`
+ req, retry, err = notifier.createRequest(ctx, alert2)
+ require.NoError(t, err)
+ require.Equal(t, true, retry)
+ require.Equal(t, expectedBody, readBody(t, req))
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package notify
+
+import (
+ "fmt"
+ "sort"
+ "sync"
+ "time"
+
+ "github.com/cenkalti/backoff"
+ "github.com/cespare/xxhash"
+ "github.com/go-kit/kit/log"
+ "github.com/go-kit/kit/log/level"
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/common/model"
+ "golang.org/x/net/context"
+
+ "github.com/prometheus/alertmanager/cluster"
+ "github.com/prometheus/alertmanager/config"
+ "github.com/prometheus/alertmanager/nflog"
+ "github.com/prometheus/alertmanager/nflog/nflogpb"
+ "github.com/prometheus/alertmanager/silence"
+ "github.com/prometheus/alertmanager/template"
+ "github.com/prometheus/alertmanager/types"
+)
+
+var (
+ numNotifications = prometheus.NewCounterVec(prometheus.CounterOpts{
+ Namespace: "alertmanager",
+ Name: "notifications_total",
+ Help: "The total number of attempted notifications.",
+ }, []string{"integration"})
+
+ numFailedNotifications = prometheus.NewCounterVec(prometheus.CounterOpts{
+ Namespace: "alertmanager",
+ Name: "notifications_failed_total",
+ Help: "The total number of failed notifications.",
+ }, []string{"integration"})
+
+ notificationLatencySeconds = prometheus.NewHistogramVec(prometheus.HistogramOpts{
+ Namespace: "alertmanager",
+ Name: "notification_latency_seconds",
+ Help: "The latency of notifications in seconds.",
+ Buckets: []float64{1, 5, 10, 15, 20},
+ }, []string{"integration"})
+)
+
+func init() {
+ numNotifications.WithLabelValues("email")
+ numNotifications.WithLabelValues("hipchat")
+ numNotifications.WithLabelValues("pagerduty")
+ numNotifications.WithLabelValues("wechat")
+ numNotifications.WithLabelValues("pushover")
+ numNotifications.WithLabelValues("slack")
+ numNotifications.WithLabelValues("opsgenie")
+ numNotifications.WithLabelValues("webhook")
+ numNotifications.WithLabelValues("victorops")
+ numFailedNotifications.WithLabelValues("email")
+ numFailedNotifications.WithLabelValues("hipchat")
+ numFailedNotifications.WithLabelValues("pagerduty")
+ numFailedNotifications.WithLabelValues("wechat")
+ numFailedNotifications.WithLabelValues("pushover")
+ numFailedNotifications.WithLabelValues("slack")
+ numFailedNotifications.WithLabelValues("opsgenie")
+ numFailedNotifications.WithLabelValues("webhook")
+ numFailedNotifications.WithLabelValues("victorops")
+ notificationLatencySeconds.WithLabelValues("email")
+ notificationLatencySeconds.WithLabelValues("hipchat")
+ notificationLatencySeconds.WithLabelValues("pagerduty")
+ notificationLatencySeconds.WithLabelValues("wechat")
+ notificationLatencySeconds.WithLabelValues("pushover")
+ notificationLatencySeconds.WithLabelValues("slack")
+ notificationLatencySeconds.WithLabelValues("opsgenie")
+ notificationLatencySeconds.WithLabelValues("webhook")
+ notificationLatencySeconds.WithLabelValues("victorops")
+
+ prometheus.Register(numNotifications)
+ prometheus.Register(numFailedNotifications)
+ prometheus.Register(notificationLatencySeconds)
+}
+
+type notifierConfig interface {
+ SendResolved() bool
+}
+
+// MinTimeout is the minimum timeout that is set for the context of a call
+// to a notification pipeline.
+const MinTimeout = 10 * time.Second
+
+// notifyKey defines a custom type with which a context is populated to
+// avoid accidental collisions.
+type notifyKey int
+
+const (
+ keyReceiverName notifyKey = iota
+ keyRepeatInterval
+ keyGroupLabels
+ keyGroupKey
+ keyFiringAlerts
+ keyResolvedAlerts
+ keyNow
+)
+
+// WithReceiverName populates a context with a receiver name.
+func WithReceiverName(ctx context.Context, rcv string) context.Context {
+ return context.WithValue(ctx, keyReceiverName, rcv)
+}
+
+// WithGroupKey populates a context with a group key.
+func WithGroupKey(ctx context.Context, s string) context.Context {
+ return context.WithValue(ctx, keyGroupKey, s)
+}
+
+// WithFiringAlerts populates a context with a slice of firing alerts.
+func WithFiringAlerts(ctx context.Context, alerts []uint64) context.Context {
+ return context.WithValue(ctx, keyFiringAlerts, alerts)
+}
+
+// WithResolvedAlerts populates a context with a slice of resolved alerts.
+func WithResolvedAlerts(ctx context.Context, alerts []uint64) context.Context {
+ return context.WithValue(ctx, keyResolvedAlerts, alerts)
+}
+
+// WithGroupLabels populates a context with grouping labels.
+func WithGroupLabels(ctx context.Context, lset model.LabelSet) context.Context {
+ return context.WithValue(ctx, keyGroupLabels, lset)
+}
+
+// WithNow populates a context with a now timestamp.
+func WithNow(ctx context.Context, t time.Time) context.Context {
+ return context.WithValue(ctx, keyNow, t)
+}
+
+// WithRepeatInterval populates a context with a repeat interval.
+func WithRepeatInterval(ctx context.Context, t time.Duration) context.Context {
+ return context.WithValue(ctx, keyRepeatInterval, t)
+}
+
+// RepeatInterval extracts a repeat interval from the context. Iff none exists, the
+// second argument is false.
+func RepeatInterval(ctx context.Context) (time.Duration, bool) {
+ v, ok := ctx.Value(keyRepeatInterval).(time.Duration)
+ return v, ok
+}
+
+// ReceiverName extracts a receiver name from the context. Iff none exists, the
+// second argument is false.
+func ReceiverName(ctx context.Context) (string, bool) {
+ v, ok := ctx.Value(keyReceiverName).(string)
+ return v, ok
+}
+
+func receiverName(ctx context.Context, l log.Logger) string {
+ recv, ok := ReceiverName(ctx)
+ if !ok {
+ level.Error(l).Log("msg", "Missing receiver")
+ }
+ return recv
+}
+
+// GroupKey extracts a group key from the context. Iff none exists, the
+// second argument is false.
+func GroupKey(ctx context.Context) (string, bool) {
+ v, ok := ctx.Value(keyGroupKey).(string)
+ return v, ok
+}
+
+func groupLabels(ctx context.Context, l log.Logger) model.LabelSet {
+ groupLabels, ok := GroupLabels(ctx)
+ if !ok {
+ level.Error(l).Log("msg", "Missing group labels")
+ }
+ return groupLabels
+}
+
+// GroupLabels extracts grouping label set from the context. Iff none exists, the
+// second argument is false.
+func GroupLabels(ctx context.Context) (model.LabelSet, bool) {
+ v, ok := ctx.Value(keyGroupLabels).(model.LabelSet)
+ return v, ok
+}
+
+// Now extracts a now timestamp from the context. Iff none exists, the
+// second argument is false.
+func Now(ctx context.Context) (time.Time, bool) {
+ v, ok := ctx.Value(keyNow).(time.Time)
+ return v, ok
+}
+
+// FiringAlerts extracts a slice of firing alerts from the context.
+// Iff none exists, the second argument is false.
+func FiringAlerts(ctx context.Context) ([]uint64, bool) {
+ v, ok := ctx.Value(keyFiringAlerts).([]uint64)
+ return v, ok
+}
+
+// ResolvedAlerts extracts a slice of firing alerts from the context.
+// Iff none exists, the second argument is false.
+func ResolvedAlerts(ctx context.Context) ([]uint64, bool) {
+ v, ok := ctx.Value(keyResolvedAlerts).([]uint64)
+ return v, ok
+}
+
+// A Stage processes alerts under the constraints of the given context.
+type Stage interface {
+ Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error)
+}
+
+// StageFunc wraps a function to represent a Stage.
+type StageFunc func(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error)
+
+// Exec implements Stage interface.
+func (f StageFunc) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) {
+ return f(ctx, l, alerts...)
+}
+
+type NotificationLog interface {
+ Log(r *nflogpb.Receiver, gkey string, firingAlerts, resolvedAlerts []uint64) error
+ Query(params ...nflog.QueryParam) ([]*nflogpb.Entry, error)
+}
+
+// BuildPipeline builds a map of receivers to Stages.
+func BuildPipeline(
+ confs []*config.Receiver,
+ tmpl *template.Template,
+ wait func() time.Duration,
+ muter types.Muter,
+ silences *silence.Silences,
+ notificationLog NotificationLog,
+ marker types.Marker,
+ peer *cluster.Peer,
+ logger log.Logger,
+) RoutingStage {
+ rs := RoutingStage{}
+
+ ms := NewGossipSettleStage(peer)
+ is := NewInhibitStage(muter)
+ ss := NewSilenceStage(silences, marker)
+
+ for _, rc := range confs {
+ rs[rc.Name] = MultiStage{ms, is, ss, createStage(rc, tmpl, wait, notificationLog, logger)}
+ }
+ return rs
+}
+
+// createStage creates a pipeline of stages for a receiver.
+func createStage(rc *config.Receiver, tmpl *template.Template, wait func() time.Duration, notificationLog NotificationLog, logger log.Logger) Stage {
+ var fs FanoutStage
+ for _, i := range BuildReceiverIntegrations(rc, tmpl, logger) {
+ recv := &nflogpb.Receiver{
+ GroupName: rc.Name,
+ Integration: i.name,
+ Idx: uint32(i.idx),
+ }
+ var s MultiStage
+ s = append(s, NewWaitStage(wait))
+ s = append(s, NewDedupStage(i, notificationLog, recv))
+ s = append(s, NewRetryStage(i, rc.Name))
+ s = append(s, NewSetNotifiesStage(notificationLog, recv))
+
+ fs = append(fs, s)
+ }
+ return fs
+}
+
+// RoutingStage executes the inner stages based on the receiver specified in
+// the context.
+type RoutingStage map[string]Stage
+
+// Exec implements the Stage interface.
+func (rs RoutingStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) {
+ receiver, ok := ReceiverName(ctx)
+ if !ok {
+ return ctx, nil, fmt.Errorf("receiver missing")
+ }
+
+ s, ok := rs[receiver]
+ if !ok {
+ return ctx, nil, fmt.Errorf("stage for receiver missing")
+ }
+
+ return s.Exec(ctx, l, alerts...)
+}
+
+// A MultiStage executes a series of stages sequencially.
+type MultiStage []Stage
+
+// Exec implements the Stage interface.
+func (ms MultiStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) {
+ var err error
+ for _, s := range ms {
+ if len(alerts) == 0 {
+ return ctx, nil, nil
+ }
+
+ ctx, alerts, err = s.Exec(ctx, l, alerts...)
+ if err != nil {
+ return ctx, nil, err
+ }
+ }
+ return ctx, alerts, nil
+}
+
+// FanoutStage executes its stages concurrently
+type FanoutStage []Stage
+
+// Exec attempts to execute all stages concurrently and discards the results.
+// It returns its input alerts and a types.MultiError if one or more stages fail.
+func (fs FanoutStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) {
+ var (
+ wg sync.WaitGroup
+ me types.MultiError
+ )
+ wg.Add(len(fs))
+
+ for _, s := range fs {
+ go func(s Stage) {
+ if _, _, err := s.Exec(ctx, l, alerts...); err != nil {
+ me.Add(err)
+ level.Error(l).Log("msg", "Error on notify", "err", err)
+ }
+ wg.Done()
+ }(s)
+ }
+ wg.Wait()
+
+ if me.Len() > 0 {
+ return ctx, alerts, &me
+ }
+ return ctx, alerts, nil
+}
+
+// GossipSettleStage waits until the Gossip has settled to forward alerts.
+type GossipSettleStage struct {
+ peer *cluster.Peer
+}
+
+// NewGossipSettleStage returns a new GossipSettleStage.
+func NewGossipSettleStage(p *cluster.Peer) *GossipSettleStage {
+ return &GossipSettleStage{peer: p}
+}
+
+func (n *GossipSettleStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) {
+ if n.peer != nil {
+ n.peer.WaitReady()
+ }
+ return ctx, alerts, nil
+}
+
+// InhibitStage filters alerts through an inhibition muter.
+type InhibitStage struct {
+ muter types.Muter
+}
+
+// NewInhibitStage return a new InhibitStage.
+func NewInhibitStage(m types.Muter) *InhibitStage {
+ return &InhibitStage{muter: m}
+}
+
+// Exec implements the Stage interface.
+func (n *InhibitStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) {
+ var filtered []*types.Alert
+ for _, a := range alerts {
+ // TODO(fabxc): increment total alerts counter.
+ // Do not send the alert if the silencer mutes it.
+ if !n.muter.Mutes(a.Labels) {
+ // TODO(fabxc): increment muted alerts counter.
+ filtered = append(filtered, a)
+ }
+ }
+
+ return ctx, filtered, nil
+}
+
+// SilenceStage filters alerts through a silence muter.
+type SilenceStage struct {
+ silences *silence.Silences
+ marker types.Marker
+}
+
+// NewSilenceStage returns a new SilenceStage.
+func NewSilenceStage(s *silence.Silences, mk types.Marker) *SilenceStage {
+ return &SilenceStage{
+ silences: s,
+ marker: mk,
+ }
+}
+
+// Exec implements the Stage interface.
+func (n *SilenceStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) {
+ var filtered []*types.Alert
+ for _, a := range alerts {
+ // TODO(fabxc): increment total alerts counter.
+ // Do not send the alert if the silencer mutes it.
+ sils, err := n.silences.Query(
+ silence.QState(types.SilenceStateActive),
+ silence.QMatches(a.Labels),
+ )
+ if err != nil {
+ level.Error(l).Log("msg", "Querying silences failed", "err", err)
+ }
+
+ if len(sils) == 0 {
+ // TODO(fabxc): increment muted alerts counter.
+ filtered = append(filtered, a)
+ n.marker.SetSilenced(a.Labels.Fingerprint())
+ } else {
+ ids := make([]string, len(sils))
+ for i, s := range sils {
+ ids[i] = s.Id
+ }
+ n.marker.SetSilenced(a.Labels.Fingerprint(), ids...)
+ }
+ }
+
+ return ctx, filtered, nil
+}
+
+// WaitStage waits for a certain amount of time before continuing or until the
+// context is done.
+type WaitStage struct {
+ wait func() time.Duration
+}
+
+// NewWaitStage returns a new WaitStage.
+func NewWaitStage(wait func() time.Duration) *WaitStage {
+ return &WaitStage{
+ wait: wait,
+ }
+}
+
+// Exec implements the Stage interface.
+func (ws *WaitStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) {
+ select {
+ case <-time.After(ws.wait()):
+ case <-ctx.Done():
+ return ctx, nil, ctx.Err()
+ }
+ return ctx, alerts, nil
+}
+
+// DedupStage filters alerts.
+// Filtering happens based on a notification log.
+type DedupStage struct {
+ nflog NotificationLog
+ recv *nflogpb.Receiver
+ conf notifierConfig
+
+ now func() time.Time
+ hash func(*types.Alert) uint64
+}
+
+// NewDedupStage wraps a DedupStage that runs against the given notification log.
+func NewDedupStage(i Integration, l NotificationLog, recv *nflogpb.Receiver) *DedupStage {
+ return &DedupStage{
+ nflog: l,
+ recv: recv,
+ conf: i.conf,
+ now: utcNow,
+ hash: hashAlert,
+ }
+}
+
+func utcNow() time.Time {
+ return time.Now().UTC()
+}
+
+var hashBuffers = sync.Pool{}
+
+func getHashBuffer() []byte {
+ b := hashBuffers.Get()
+ if b == nil {
+ return make([]byte, 0, 1024)
+ }
+ return b.([]byte)
+}
+
+func putHashBuffer(b []byte) {
+ b = b[:0]
+ hashBuffers.Put(b)
+}
+
+func hashAlert(a *types.Alert) uint64 {
+ const sep = '\xff'
+
+ b := getHashBuffer()
+ defer putHashBuffer(b)
+
+ names := make(model.LabelNames, 0, len(a.Labels))
+
+ for ln := range a.Labels {
+ names = append(names, ln)
+ }
+ sort.Sort(names)
+
+ for _, ln := range names {
+ b = append(b, string(ln)...)
+ b = append(b, sep)
+ b = append(b, string(a.Labels[ln])...)
+ b = append(b, sep)
+ }
+
+ hash := xxhash.Sum64(b)
+
+ return hash
+}
+
+func (n *DedupStage) needsUpdate(entry *nflogpb.Entry, firing, resolved map[uint64]struct{}, repeat time.Duration) bool {
+ // If we haven't notified about the alert group before, notify right away
+ // unless we only have resolved alerts.
+ if entry == nil {
+ return len(firing) > 0
+ }
+
+ if !entry.IsFiringSubset(firing) {
+ return true
+ }
+
+ // Notify about all alerts being resolved.
+ // This is done irrespective of the send_resolved flag to make sure that
+ // the firing alerts are cleared from the notification log.
+ if len(firing) == 0 {
+ // If the current alert group and last notification contain no firing
+ // alert, it means that some alerts have been fired and resolved during the
+ // last interval. In this case, there is no need to notify the receiver
+ // since it doesn't know about them.
+ return len(entry.FiringAlerts) > 0
+ }
+
+ if n.conf.SendResolved() && !entry.IsResolvedSubset(resolved) {
+ return true
+ }
+
+ // Nothing changed, only notify if the repeat interval has passed.
+ return entry.Timestamp.Before(n.now().Add(-repeat))
+}
+
+// Exec implements the Stage interface.
+func (n *DedupStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) {
+ gkey, ok := GroupKey(ctx)
+ if !ok {
+ return ctx, nil, fmt.Errorf("group key missing")
+ }
+
+ repeatInterval, ok := RepeatInterval(ctx)
+ if !ok {
+ return ctx, nil, fmt.Errorf("repeat interval missing")
+ }
+
+ firingSet := map[uint64]struct{}{}
+ resolvedSet := map[uint64]struct{}{}
+ firing := []uint64{}
+ resolved := []uint64{}
+
+ var hash uint64
+ for _, a := range alerts {
+ hash = n.hash(a)
+ if a.Resolved() {
+ resolved = append(resolved, hash)
+ resolvedSet[hash] = struct{}{}
+ } else {
+ firing = append(firing, hash)
+ firingSet[hash] = struct{}{}
+ }
+ }
+
+ ctx = WithFiringAlerts(ctx, firing)
+ ctx = WithResolvedAlerts(ctx, resolved)
+
+ entries, err := n.nflog.Query(nflog.QGroupKey(gkey), nflog.QReceiver(n.recv))
+
+ if err != nil && err != nflog.ErrNotFound {
+ return ctx, nil, err
+ }
+ var entry *nflogpb.Entry
+ switch len(entries) {
+ case 0:
+ case 1:
+ entry = entries[0]
+ case 2:
+ return ctx, nil, fmt.Errorf("unexpected entry result size %d", len(entries))
+ }
+ if n.needsUpdate(entry, firingSet, resolvedSet, repeatInterval) {
+ return ctx, alerts, nil
+ }
+ return ctx, nil, nil
+}
+
+// RetryStage notifies via passed integration with exponential backoff until it
+// succeeds. It aborts if the context is canceled or timed out.
+type RetryStage struct {
+ integration Integration
+ groupName string
+}
+
+// NewRetryStage returns a new instance of a RetryStage.
+func NewRetryStage(i Integration, groupName string) *RetryStage {
+ return &RetryStage{
+ integration: i,
+ groupName: groupName,
+ }
+}
+
+// Exec implements the Stage interface.
+func (r RetryStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) {
+ var sent []*types.Alert
+
+ // If we shouldn't send notifications for resolved alerts, but there are only
+ // resolved alerts, report them all as successfully notified (we still want the
+ // notification log to log them for the next run of DedupStage).
+ if !r.integration.conf.SendResolved() {
+ firing, ok := FiringAlerts(ctx)
+ if !ok {
+ return ctx, nil, fmt.Errorf("firing alerts missing")
+ }
+ if len(firing) == 0 {
+ return ctx, alerts, nil
+ }
+ for _, a := range alerts {
+ if a.Status() != model.AlertResolved {
+ sent = append(sent, a)
+ }
+ }
+ } else {
+ sent = alerts
+ }
+
+ var (
+ i = 0
+ b = backoff.NewExponentialBackOff()
+ tick = backoff.NewTicker(b)
+ iErr error
+ )
+ defer tick.Stop()
+
+ for {
+ i++
+ // Always check the context first to not notify again.
+ select {
+ case <-ctx.Done():
+ if iErr != nil {
+ return ctx, nil, iErr
+ }
+
+ return ctx, nil, ctx.Err()
+ default:
+ }
+
+ select {
+ case <-tick.C:
+ now := time.Now()
+ retry, err := r.integration.Notify(ctx, sent...)
+ notificationLatencySeconds.WithLabelValues(r.integration.name).Observe(time.Since(now).Seconds())
+ if err != nil {
+ numFailedNotifications.WithLabelValues(r.integration.name).Inc()
+ level.Debug(l).Log("msg", "Notify attempt failed", "attempt", i, "integration", r.integration.name, "receiver", r.groupName, "err", err)
+ if !retry {
+ return ctx, alerts, fmt.Errorf("cancelling notify retry for %q due to unrecoverable error: %s", r.integration.name, err)
+ }
+
+ // Save this error to be able to return the last seen error by an
+ // integration upon context timeout.
+ iErr = err
+ } else {
+ numNotifications.WithLabelValues(r.integration.name).Inc()
+ return ctx, alerts, nil
+ }
+ case <-ctx.Done():
+ if iErr != nil {
+ return ctx, nil, iErr
+ }
+
+ return ctx, nil, ctx.Err()
+ }
+ }
+}
+
+// SetNotifiesStage sets the notification information about passed alerts. The
+// passed alerts should have already been sent to the receivers.
+type SetNotifiesStage struct {
+ nflog NotificationLog
+ recv *nflogpb.Receiver
+}
+
+// NewSetNotifiesStage returns a new instance of a SetNotifiesStage.
+func NewSetNotifiesStage(l NotificationLog, recv *nflogpb.Receiver) *SetNotifiesStage {
+ return &SetNotifiesStage{
+ nflog: l,
+ recv: recv,
+ }
+}
+
+// Exec implements the Stage interface.
+func (n SetNotifiesStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) {
+ gkey, ok := GroupKey(ctx)
+ if !ok {
+ return ctx, nil, fmt.Errorf("group key missing")
+ }
+
+ firing, ok := FiringAlerts(ctx)
+ if !ok {
+ return ctx, nil, fmt.Errorf("firing alerts missing")
+ }
+
+ resolved, ok := ResolvedAlerts(ctx)
+ if !ok {
+ return ctx, nil, fmt.Errorf("resolved alerts missing")
+ }
+
+ return ctx, alerts, n.nflog.Log(n.recv, gkey, firing, resolved)
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package notify
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "reflect"
+ "testing"
+ "time"
+
+ "github.com/go-kit/kit/log"
+ "github.com/prometheus/common/model"
+ "github.com/stretchr/testify/require"
+ "golang.org/x/net/context"
+
+ "github.com/prometheus/alertmanager/nflog"
+ "github.com/prometheus/alertmanager/nflog/nflogpb"
+ "github.com/prometheus/alertmanager/silence"
+ "github.com/prometheus/alertmanager/silence/silencepb"
+ "github.com/prometheus/alertmanager/types"
+)
+
+type notifierConfigFunc func() bool
+
+func (f notifierConfigFunc) SendResolved() bool {
+ return f()
+}
+
+type notifierFunc func(ctx context.Context, alerts ...*types.Alert) (bool, error)
+
+func (f notifierFunc) Notify(ctx context.Context, alerts ...*types.Alert) (bool, error) {
+ return f(ctx, alerts...)
+}
+
+type failStage struct{}
+
+func (s failStage) Exec(ctx context.Context, l log.Logger, as ...*types.Alert) (context.Context, []*types.Alert, error) {
+ return ctx, nil, fmt.Errorf("some error")
+}
+
+type testNflog struct {
+ qres []*nflogpb.Entry
+ qerr error
+
+ logFunc func(r *nflogpb.Receiver, gkey string, firingAlerts, resolvedAlerts []uint64) error
+}
+
+func (l *testNflog) Query(p ...nflog.QueryParam) ([]*nflogpb.Entry, error) {
+ return l.qres, l.qerr
+}
+
+func (l *testNflog) Log(r *nflogpb.Receiver, gkey string, firingAlerts, resolvedAlerts []uint64) error {
+ return l.logFunc(r, gkey, firingAlerts, resolvedAlerts)
+}
+
+func (l *testNflog) GC() (int, error) {
+ return 0, nil
+}
+
+func (l *testNflog) Snapshot(w io.Writer) (int, error) {
+ return 0, nil
+}
+
+func alertHashSet(hashes ...uint64) map[uint64]struct{} {
+ res := map[uint64]struct{}{}
+
+ for _, h := range hashes {
+ res[h] = struct{}{}
+ }
+
+ return res
+}
+
+func TestDedupStageNeedsUpdate(t *testing.T) {
+ now := utcNow()
+
+ cases := []struct {
+ entry *nflogpb.Entry
+ firingAlerts map[uint64]struct{}
+ resolvedAlerts map[uint64]struct{}
+ repeat time.Duration
+ resolve bool
+
+ res bool
+ }{
+ {
+ // No matching nflog entry should update.
+ entry: nil,
+ firingAlerts: alertHashSet(2, 3, 4),
+ res: true,
+ }, {
+ // No matching nflog entry shouldn't update if no alert fires.
+ entry: nil,
+ resolvedAlerts: alertHashSet(2, 3, 4),
+ res: false,
+ }, {
+ // Different sets of firing alerts should update.
+ entry: &nflogpb.Entry{FiringAlerts: []uint64{1, 2, 3}},
+ firingAlerts: alertHashSet(2, 3, 4),
+ res: true,
+ }, {
+ // Zero timestamp in the nflog entry should always update.
+ entry: &nflogpb.Entry{
+ FiringAlerts: []uint64{1, 2, 3},
+ Timestamp: time.Time{},
+ },
+ firingAlerts: alertHashSet(1, 2, 3),
+ res: true,
+ }, {
+ // Identical sets of alerts shouldn't update before repeat_interval.
+ entry: &nflogpb.Entry{
+ FiringAlerts: []uint64{1, 2, 3},
+ Timestamp: now.Add(-9 * time.Minute),
+ },
+ repeat: 10 * time.Minute,
+ firingAlerts: alertHashSet(1, 2, 3),
+ res: false,
+ }, {
+ // Identical sets of alerts should update after repeat_interval.
+ entry: &nflogpb.Entry{
+ FiringAlerts: []uint64{1, 2, 3},
+ Timestamp: now.Add(-11 * time.Minute),
+ },
+ repeat: 10 * time.Minute,
+ firingAlerts: alertHashSet(1, 2, 3),
+ res: true,
+ }, {
+ // Different sets of resolved alerts without firing alerts shouldn't update after repeat_interval.
+ entry: &nflogpb.Entry{
+ ResolvedAlerts: []uint64{1, 2, 3},
+ Timestamp: now.Add(-11 * time.Minute),
+ },
+ repeat: 10 * time.Minute,
+ resolvedAlerts: alertHashSet(3, 4, 5),
+ resolve: true,
+ res: false,
+ }, {
+ // Different sets of resolved alerts shouldn't update when resolve is false.
+ entry: &nflogpb.Entry{
+ FiringAlerts: []uint64{1, 2},
+ ResolvedAlerts: []uint64{3},
+ Timestamp: now.Add(-9 * time.Minute),
+ },
+ repeat: 10 * time.Minute,
+ firingAlerts: alertHashSet(1),
+ resolvedAlerts: alertHashSet(2, 3),
+ resolve: false,
+ res: false,
+ }, {
+ // Different sets of resolved alerts should update when resolve is true.
+ entry: &nflogpb.Entry{
+ FiringAlerts: []uint64{1, 2},
+ ResolvedAlerts: []uint64{3},
+ Timestamp: now.Add(-9 * time.Minute),
+ },
+ repeat: 10 * time.Minute,
+ firingAlerts: alertHashSet(1),
+ resolvedAlerts: alertHashSet(2, 3),
+ resolve: true,
+ res: true,
+ }, {
+ // Empty set of firing alerts should update when resolve is false.
+ entry: &nflogpb.Entry{
+ FiringAlerts: []uint64{1, 2},
+ ResolvedAlerts: []uint64{3},
+ Timestamp: now.Add(-9 * time.Minute),
+ },
+ repeat: 10 * time.Minute,
+ firingAlerts: alertHashSet(),
+ resolvedAlerts: alertHashSet(1, 2, 3),
+ resolve: false,
+ res: true,
+ }, {
+ // Empty set of firing alerts should update when resolve is true.
+ entry: &nflogpb.Entry{
+ FiringAlerts: []uint64{1, 2},
+ ResolvedAlerts: []uint64{3},
+ Timestamp: now.Add(-9 * time.Minute),
+ },
+ repeat: 10 * time.Minute,
+ firingAlerts: alertHashSet(),
+ resolvedAlerts: alertHashSet(1, 2, 3),
+ resolve: true,
+ res: true,
+ },
+ }
+ for i, c := range cases {
+ t.Log("case", i)
+
+ s := &DedupStage{
+ now: func() time.Time { return now },
+ conf: notifierConfigFunc(func() bool { return c.resolve }),
+ }
+ res := s.needsUpdate(c.entry, c.firingAlerts, c.resolvedAlerts, c.repeat)
+ require.Equal(t, c.res, res)
+ }
+}
+
+func TestDedupStage(t *testing.T) {
+ i := 0
+ now := utcNow()
+ s := &DedupStage{
+ hash: func(a *types.Alert) uint64 {
+ res := uint64(i)
+ i++
+ return res
+ },
+ now: func() time.Time {
+ return now
+ },
+ conf: notifierConfigFunc(func() bool { return false }),
+ }
+
+ ctx := context.Background()
+
+ _, _, err := s.Exec(ctx, log.NewNopLogger())
+ require.EqualError(t, err, "group key missing")
+
+ ctx = WithGroupKey(ctx, "1")
+
+ _, _, err = s.Exec(ctx, log.NewNopLogger())
+ require.EqualError(t, err, "repeat interval missing")
+
+ ctx = WithRepeatInterval(ctx, time.Hour)
+
+ alerts := []*types.Alert{{}, {}, {}}
+
+ // Must catch notification log query errors.
+ s.nflog = &testNflog{
+ qerr: errors.New("bad things"),
+ }
+ ctx, _, err = s.Exec(ctx, log.NewNopLogger(), alerts...)
+ require.EqualError(t, err, "bad things")
+
+ // ... but skip ErrNotFound.
+ s.nflog = &testNflog{
+ qerr: nflog.ErrNotFound,
+ }
+ ctx, res, err := s.Exec(ctx, log.NewNopLogger(), alerts...)
+ require.NoError(t, err, "unexpected error on not found log entry")
+ require.Equal(t, alerts, res, "input alerts differ from result alerts")
+
+ s.nflog = &testNflog{
+ qerr: nil,
+ qres: []*nflogpb.Entry{
+ {FiringAlerts: []uint64{0, 1, 2}},
+ {FiringAlerts: []uint64{1, 2, 3}},
+ },
+ }
+ ctx, _, err = s.Exec(ctx, log.NewNopLogger(), alerts...)
+ require.Contains(t, err.Error(), "result size")
+
+ // Must return no error and no alerts no need to update.
+ i = 0
+ s.nflog = &testNflog{
+ qerr: nflog.ErrNotFound,
+ qres: []*nflogpb.Entry{
+ {
+ FiringAlerts: []uint64{0, 1, 2},
+ Timestamp: now,
+ },
+ },
+ }
+ ctx, res, err = s.Exec(ctx, log.NewNopLogger(), alerts...)
+ require.NoError(t, err)
+ require.Nil(t, res, "unexpected alerts returned")
+
+ // Must return no error and all input alerts on changes.
+ i = 0
+ s.nflog = &testNflog{
+ qerr: nil,
+ qres: []*nflogpb.Entry{
+ {
+ FiringAlerts: []uint64{1, 2, 3, 4},
+ Timestamp: now,
+ },
+ },
+ }
+ _, res, err = s.Exec(ctx, log.NewNopLogger(), alerts...)
+ require.NoError(t, err)
+ require.Equal(t, alerts, res, "unexpected alerts returned")
+}
+
+func TestMultiStage(t *testing.T) {
+ var (
+ alerts1 = []*types.Alert{{}}
+ alerts2 = []*types.Alert{{}, {}}
+ alerts3 = []*types.Alert{{}, {}, {}}
+ )
+
+ stage := MultiStage{
+ StageFunc(func(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) {
+ if !reflect.DeepEqual(alerts, alerts1) {
+ t.Fatal("Input not equal to input of MultiStage")
+ }
+ ctx = context.WithValue(ctx, "key", "value")
+ return ctx, alerts2, nil
+ }),
+ StageFunc(func(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) {
+ if !reflect.DeepEqual(alerts, alerts2) {
+ t.Fatal("Input not equal to output of previous stage")
+ }
+ v, ok := ctx.Value("key").(string)
+ if !ok || v != "value" {
+ t.Fatalf("Expected value %q for key %q but got %q", "value", "key", v)
+ }
+ return ctx, alerts3, nil
+ }),
+ }
+
+ _, alerts, err := stage.Exec(context.Background(), log.NewNopLogger(), alerts1...)
+ if err != nil {
+ t.Fatalf("Exec failed: %s", err)
+ }
+
+ if !reflect.DeepEqual(alerts, alerts3) {
+ t.Fatal("Output of MultiStage is not equal to the output of the last stage")
+ }
+}
+
+func TestMultiStageFailure(t *testing.T) {
+ var (
+ ctx = context.Background()
+ s1 = failStage{}
+ stage = MultiStage{s1}
+ )
+
+ _, _, err := stage.Exec(ctx, log.NewNopLogger(), nil)
+ if err.Error() != "some error" {
+ t.Fatal("Errors were not propagated correctly by MultiStage")
+ }
+}
+
+func TestRoutingStage(t *testing.T) {
+ var (
+ alerts1 = []*types.Alert{{}}
+ alerts2 = []*types.Alert{{}, {}}
+ )
+
+ stage := RoutingStage{
+ "name": StageFunc(func(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) {
+ if !reflect.DeepEqual(alerts, alerts1) {
+ t.Fatal("Input not equal to input of RoutingStage")
+ }
+ return ctx, alerts2, nil
+ }),
+ "not": failStage{},
+ }
+
+ ctx := WithReceiverName(context.Background(), "name")
+
+ _, alerts, err := stage.Exec(ctx, log.NewNopLogger(), alerts1...)
+ if err != nil {
+ t.Fatalf("Exec failed: %s", err)
+ }
+
+ if !reflect.DeepEqual(alerts, alerts2) {
+ t.Fatal("Output of RoutingStage is not equal to the output of the inner stage")
+ }
+}
+
+func TestRetryStageWithError(t *testing.T) {
+ fail, retry := true, true
+ sent := []*types.Alert{}
+ i := Integration{
+ notifier: notifierFunc(func(ctx context.Context, alerts ...*types.Alert) (bool, error) {
+ if fail {
+ fail = false
+ return retry, errors.New("fail to deliver notification")
+ }
+ sent = append(sent, alerts...)
+ return false, nil
+ }),
+ conf: notifierConfigFunc(func() bool { return false }),
+ }
+ r := RetryStage{
+ integration: i,
+ }
+
+ alerts := []*types.Alert{
+ &types.Alert{
+ Alert: model.Alert{
+ EndsAt: time.Now().Add(time.Hour),
+ },
+ },
+ }
+
+ ctx := context.Background()
+ ctx = WithFiringAlerts(ctx, []uint64{0})
+
+ // Notify with a recoverable error should retry and succeed.
+ resctx, res, err := r.Exec(ctx, log.NewNopLogger(), alerts...)
+ require.Nil(t, err)
+ require.Equal(t, alerts, res)
+ require.Equal(t, alerts, sent)
+ require.NotNil(t, resctx)
+
+ // Notify with an unrecoverable error should fail.
+ sent = sent[:0]
+ fail = true
+ retry = false
+ resctx, _, err = r.Exec(ctx, log.NewNopLogger(), alerts...)
+ require.NotNil(t, err)
+ require.NotNil(t, resctx)
+}
+
+func TestRetryStageNoResolved(t *testing.T) {
+ sent := []*types.Alert{}
+ i := Integration{
+ notifier: notifierFunc(func(ctx context.Context, alerts ...*types.Alert) (bool, error) {
+ sent = append(sent, alerts...)
+ return false, nil
+ }),
+ conf: notifierConfigFunc(func() bool { return false }),
+ }
+ r := RetryStage{
+ integration: i,
+ }
+
+ alerts := []*types.Alert{
+ &types.Alert{
+ Alert: model.Alert{
+ EndsAt: time.Now().Add(-time.Hour),
+ },
+ },
+ &types.Alert{
+ Alert: model.Alert{
+ EndsAt: time.Now().Add(time.Hour),
+ },
+ },
+ }
+
+ ctx := context.Background()
+
+ resctx, res, err := r.Exec(ctx, log.NewNopLogger(), alerts...)
+ require.EqualError(t, err, "firing alerts missing")
+ require.Nil(t, res)
+ require.NotNil(t, resctx)
+
+ ctx = WithFiringAlerts(ctx, []uint64{0})
+
+ resctx, res, err = r.Exec(ctx, log.NewNopLogger(), alerts...)
+ require.Nil(t, err)
+ require.Equal(t, alerts, res)
+ require.Equal(t, []*types.Alert{alerts[1]}, sent)
+ require.NotNil(t, resctx)
+
+ // All alerts are resolved.
+ sent = sent[:0]
+ ctx = WithFiringAlerts(ctx, []uint64{})
+ alerts[1].Alert.EndsAt = time.Now().Add(-time.Hour)
+
+ resctx, res, err = r.Exec(ctx, log.NewNopLogger(), alerts...)
+ require.Nil(t, err)
+ require.Equal(t, alerts, res)
+ require.Equal(t, []*types.Alert{}, sent)
+ require.NotNil(t, resctx)
+}
+
+func TestRetryStageSendResolved(t *testing.T) {
+ sent := []*types.Alert{}
+ i := Integration{
+ notifier: notifierFunc(func(ctx context.Context, alerts ...*types.Alert) (bool, error) {
+ sent = append(sent, alerts...)
+ return false, nil
+ }),
+ conf: notifierConfigFunc(func() bool { return true }),
+ }
+ r := RetryStage{
+ integration: i,
+ }
+
+ alerts := []*types.Alert{
+ &types.Alert{
+ Alert: model.Alert{
+ EndsAt: time.Now().Add(-time.Hour),
+ },
+ },
+ &types.Alert{
+ Alert: model.Alert{
+ EndsAt: time.Now().Add(time.Hour),
+ },
+ },
+ }
+
+ ctx := context.Background()
+ ctx = WithFiringAlerts(ctx, []uint64{0})
+
+ resctx, res, err := r.Exec(ctx, log.NewNopLogger(), alerts...)
+ require.Nil(t, err)
+ require.Equal(t, alerts, res)
+ require.Equal(t, alerts, sent)
+ require.NotNil(t, resctx)
+
+ // All alerts are resolved.
+ sent = sent[:0]
+ ctx = WithFiringAlerts(ctx, []uint64{})
+ alerts[1].Alert.EndsAt = time.Now().Add(-time.Hour)
+
+ resctx, res, err = r.Exec(ctx, log.NewNopLogger(), alerts...)
+ require.Nil(t, err)
+ require.Equal(t, alerts, res)
+ require.Equal(t, alerts, sent)
+ require.NotNil(t, resctx)
+}
+
+func TestSetNotifiesStage(t *testing.T) {
+ tnflog := &testNflog{}
+ s := &SetNotifiesStage{
+ recv: &nflogpb.Receiver{GroupName: "test"},
+ nflog: tnflog,
+ }
+ alerts := []*types.Alert{{}, {}, {}}
+ ctx := context.Background()
+
+ resctx, res, err := s.Exec(ctx, log.NewNopLogger(), alerts...)
+ require.EqualError(t, err, "group key missing")
+ require.Nil(t, res)
+ require.NotNil(t, resctx)
+
+ ctx = WithGroupKey(ctx, "1")
+
+ resctx, res, err = s.Exec(ctx, log.NewNopLogger(), alerts...)
+ require.EqualError(t, err, "firing alerts missing")
+ require.Nil(t, res)
+ require.NotNil(t, resctx)
+
+ ctx = WithFiringAlerts(ctx, []uint64{0, 1, 2})
+
+ resctx, res, err = s.Exec(ctx, log.NewNopLogger(), alerts...)
+ require.EqualError(t, err, "resolved alerts missing")
+ require.Nil(t, res)
+ require.NotNil(t, resctx)
+
+ ctx = WithResolvedAlerts(ctx, []uint64{})
+
+ tnflog.logFunc = func(r *nflogpb.Receiver, gkey string, firingAlerts, resolvedAlerts []uint64) error {
+ require.Equal(t, s.recv, r)
+ require.Equal(t, "1", gkey)
+ require.Equal(t, []uint64{0, 1, 2}, firingAlerts)
+ require.Equal(t, []uint64{}, resolvedAlerts)
+ return nil
+ }
+ resctx, res, err = s.Exec(ctx, log.NewNopLogger(), alerts...)
+ require.Nil(t, err)
+ require.Equal(t, alerts, res)
+ require.NotNil(t, resctx)
+
+ ctx = WithFiringAlerts(ctx, []uint64{})
+ ctx = WithResolvedAlerts(ctx, []uint64{0, 1, 2})
+
+ tnflog.logFunc = func(r *nflogpb.Receiver, gkey string, firingAlerts, resolvedAlerts []uint64) error {
+ require.Equal(t, s.recv, r)
+ require.Equal(t, "1", gkey)
+ require.Equal(t, []uint64{}, firingAlerts)
+ require.Equal(t, []uint64{0, 1, 2}, resolvedAlerts)
+ return nil
+ }
+ resctx, res, err = s.Exec(ctx, log.NewNopLogger(), alerts...)
+ require.Nil(t, err)
+ require.Equal(t, alerts, res)
+ require.NotNil(t, resctx)
+}
+
+func TestSilenceStage(t *testing.T) {
+ silences, err := silence.New(silence.Options{})
+ if err != nil {
+ t.Fatal(err)
+ }
+ if _, err := silences.Set(&silencepb.Silence{
+ EndsAt: utcNow().Add(time.Hour),
+ Matchers: []*silencepb.Matcher{{Name: "mute", Pattern: "me"}},
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ marker := types.NewMarker()
+ silencer := NewSilenceStage(silences, marker)
+
+ in := []model.LabelSet{
+ {},
+ {"test": "set"},
+ {"mute": "me"},
+ {"foo": "bar", "test": "set"},
+ {"foo": "bar", "mute": "me"},
+ {},
+ {"not": "muted"},
+ }
+ out := []model.LabelSet{
+ {},
+ {"test": "set"},
+ {"foo": "bar", "test": "set"},
+ {},
+ {"not": "muted"},
+ }
+
+ var inAlerts []*types.Alert
+ for _, lset := range in {
+ inAlerts = append(inAlerts, &types.Alert{
+ Alert: model.Alert{Labels: lset},
+ })
+ }
+
+ // Set the second alert as previously silenced. It is expected to have
+ // the WasSilenced flag set to true afterwards.
+ marker.SetSilenced(inAlerts[1].Fingerprint(), "123")
+
+ _, alerts, err := silencer.Exec(nil, log.NewNopLogger(), inAlerts...)
+ if err != nil {
+ t.Fatalf("Exec failed: %s", err)
+ }
+
+ var got []model.LabelSet
+ for _, a := range alerts {
+ got = append(got, a.Labels)
+ }
+
+ if !reflect.DeepEqual(got, out) {
+ t.Fatalf("Muting failed, expected: %v\ngot %v", out, got)
+ }
+}
+
+func TestInhibitStage(t *testing.T) {
+ // Mute all label sets that have a "mute" key.
+ muter := types.MuteFunc(func(lset model.LabelSet) bool {
+ _, ok := lset["mute"]
+ return ok
+ })
+
+ inhibitor := NewInhibitStage(muter)
+
+ in := []model.LabelSet{
+ {},
+ {"test": "set"},
+ {"mute": "me"},
+ {"foo": "bar", "test": "set"},
+ {"foo": "bar", "mute": "me"},
+ {},
+ {"not": "muted"},
+ }
+ out := []model.LabelSet{
+ {},
+ {"test": "set"},
+ {"foo": "bar", "test": "set"},
+ {},
+ {"not": "muted"},
+ }
+
+ var inAlerts []*types.Alert
+ for _, lset := range in {
+ inAlerts = append(inAlerts, &types.Alert{
+ Alert: model.Alert{Labels: lset},
+ })
+ }
+
+ _, alerts, err := inhibitor.Exec(nil, log.NewNopLogger(), inAlerts...)
+ if err != nil {
+ t.Fatalf("Exec failed: %s", err)
+ }
+
+ var got []model.LabelSet
+ for _, a := range alerts {
+ got = append(got, a.Labels)
+ }
+
+ if !reflect.DeepEqual(got, out) {
+ t.Fatalf("Muting failed, expected: %v\ngot %v", out, got)
+ }
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package parse
+
+import (
+ "fmt"
+ "regexp"
+ "strings"
+
+ "github.com/prometheus/prometheus/pkg/labels"
+)
+
+var (
+ re = regexp.MustCompile(`(?:\s?)(\w+)(=|=~|!=|!~)(?:\"([^"=~!]+)\"|([^"=~!]+)|\"\")`)
+ typeMap = map[string]labels.MatchType{
+ "=": labels.MatchEqual,
+ "!=": labels.MatchNotEqual,
+ "=~": labels.MatchRegexp,
+ "!~": labels.MatchNotRegexp,
+ }
+)
+
+func Matchers(s string) ([]*labels.Matcher, error) {
+ matchers := []*labels.Matcher{}
+ if strings.HasPrefix(s, "{") {
+ s = s[1:]
+ }
+ if strings.HasSuffix(s, "}") {
+ s = s[:len(s)-1]
+ }
+
+ var insideQuotes bool
+ var token string
+ var tokens []string
+ for _, r := range s {
+ if !insideQuotes && r == ',' {
+ tokens = append(tokens, token)
+ token = ""
+ continue
+ }
+ token += string(r)
+ if r == '"' {
+ insideQuotes = !insideQuotes
+ }
+ }
+ if token != "" {
+ tokens = append(tokens, token)
+ }
+ for _, token := range tokens {
+ m, err := Matcher(token)
+ if err != nil {
+ return nil, err
+ }
+ matchers = append(matchers, m)
+ }
+
+ return matchers, nil
+}
+
+func Matcher(s string) (*labels.Matcher, error) {
+ name, value, matchType, err := Input(s)
+ if err != nil {
+ return nil, err
+ }
+
+ m, err := labels.NewMatcher(matchType, name, value)
+ if err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func Input(s string) (name, value string, matchType labels.MatchType, err error) {
+ ms := re.FindStringSubmatch(s)
+ if len(ms) < 4 {
+ return "", "", labels.MatchEqual, fmt.Errorf("bad matcher format: %s", s)
+ }
+
+ var prs bool
+ name = ms[1]
+ matchType, prs = typeMap[ms[2]]
+
+ if ms[3] != "" {
+ value = ms[3]
+ } else {
+ value = ms[4]
+ }
+
+ if name == "" || !prs {
+ return "", "", labels.MatchEqual, fmt.Errorf("failed to parse")
+ }
+
+ return name, value, matchType, nil
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package parse
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/prometheus/prometheus/pkg/labels"
+)
+
+func TestMatchers(t *testing.T) {
+ testCases := []struct {
+ input string
+ want []*labels.Matcher
+ err error
+ }{
+ {
+ input: `{foo="bar"}`,
+ want: func() []*labels.Matcher {
+ ms := []*labels.Matcher{}
+ m, _ := labels.NewMatcher(labels.MatchEqual, "foo", "bar")
+ return append(ms, m)
+ }(),
+ },
+ {
+ input: `{foo=~"bar.*"}`,
+ want: func() []*labels.Matcher {
+ ms := []*labels.Matcher{}
+ m, _ := labels.NewMatcher(labels.MatchRegexp, "foo", "bar.*")
+ return append(ms, m)
+ }(),
+ },
+ {
+ input: `{foo!="bar"}`,
+ want: func() []*labels.Matcher {
+ ms := []*labels.Matcher{}
+ m, _ := labels.NewMatcher(labels.MatchNotEqual, "foo", "bar")
+ return append(ms, m)
+ }(),
+ },
+ {
+ input: `{foo!~"bar.*"}`,
+ want: func() []*labels.Matcher {
+ ms := []*labels.Matcher{}
+ m, _ := labels.NewMatcher(labels.MatchNotRegexp, "foo", "bar.*")
+ return append(ms, m)
+ }(),
+ },
+ {
+ input: `{foo="bar", baz!="quux"}`,
+ want: func() []*labels.Matcher {
+ ms := []*labels.Matcher{}
+ m, _ := labels.NewMatcher(labels.MatchEqual, "foo", "bar")
+ m2, _ := labels.NewMatcher(labels.MatchNotEqual, "baz", "quux")
+ return append(ms, m, m2)
+ }(),
+ },
+ {
+ input: `{foo="bar", baz!~"quux.*"}`,
+ want: func() []*labels.Matcher {
+ ms := []*labels.Matcher{}
+ m, _ := labels.NewMatcher(labels.MatchEqual, "foo", "bar")
+ m2, _ := labels.NewMatcher(labels.MatchNotRegexp, "baz", "quux.*")
+ return append(ms, m, m2)
+ }(),
+ },
+ {
+ input: `{foo="bar",baz!~".*quux", derp="wat"}`,
+ want: func() []*labels.Matcher {
+ ms := []*labels.Matcher{}
+ m, _ := labels.NewMatcher(labels.MatchEqual, "foo", "bar")
+ m2, _ := labels.NewMatcher(labels.MatchNotRegexp, "baz", ".*quux")
+ m3, _ := labels.NewMatcher(labels.MatchEqual, "derp", "wat")
+ return append(ms, m, m2, m3)
+ }(),
+ },
+ {
+ input: `{foo="bar", baz!="quux", derp="wat"}`,
+ want: func() []*labels.Matcher {
+ ms := []*labels.Matcher{}
+ m, _ := labels.NewMatcher(labels.MatchEqual, "foo", "bar")
+ m2, _ := labels.NewMatcher(labels.MatchNotEqual, "baz", "quux")
+ m3, _ := labels.NewMatcher(labels.MatchEqual, "derp", "wat")
+ return append(ms, m, m2, m3)
+ }(),
+ },
+ {
+ input: `{foo="bar", baz!~".*quux.*", derp="wat"}`,
+ want: func() []*labels.Matcher {
+ ms := []*labels.Matcher{}
+ m, _ := labels.NewMatcher(labels.MatchEqual, "foo", "bar")
+ m2, _ := labels.NewMatcher(labels.MatchNotRegexp, "baz", ".*quux.*")
+ m3, _ := labels.NewMatcher(labels.MatchEqual, "derp", "wat")
+ return append(ms, m, m2, m3)
+ }(),
+ },
+ {
+ input: `{foo="bar", instance=~"some-api.*"}`,
+ want: func() []*labels.Matcher {
+ ms := []*labels.Matcher{}
+ m, _ := labels.NewMatcher(labels.MatchEqual, "foo", "bar")
+ m2, _ := labels.NewMatcher(labels.MatchRegexp, "instance", "some-api.*")
+ return append(ms, m, m2)
+ }(),
+ },
+ {
+ input: `{foo=""}`,
+ want: func() []*labels.Matcher {
+ ms := []*labels.Matcher{}
+ m, _ := labels.NewMatcher(labels.MatchEqual, "foo", "")
+ return append(ms, m)
+ }(),
+ },
+ {
+ input: `{foo="bar,quux", job="job1"}`,
+ want: func() []*labels.Matcher {
+ ms := []*labels.Matcher{}
+ m, _ := labels.NewMatcher(labels.MatchEqual, "foo", "bar,quux")
+ m2, _ := labels.NewMatcher(labels.MatchEqual, "job", "job1")
+ return append(ms, m, m2)
+ }(),
+ },
+ }
+
+ for i, tc := range testCases {
+ got, err := Matchers(tc.input)
+ if tc.err != err {
+ t.Fatalf("error not equal (i=%d):\ngot %v\nwant %v", i, err, tc.err)
+ }
+ if !reflect.DeepEqual(got, tc.want) {
+ t.Fatalf("labels not equal (i=%d):\ngot %v\nwant %v", i, got, tc.want)
+ }
+ }
+
+}
--- /dev/null
+// Copyright 2016 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/lic:wenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package mem
+
+import (
+ "sync"
+ "time"
+
+ "github.com/prometheus/alertmanager/provider"
+ "github.com/prometheus/alertmanager/types"
+ "github.com/prometheus/common/model"
+)
+
+// Alerts gives access to a set of alerts. All methods are goroutine-safe.
+type Alerts struct {
+ mtx sync.RWMutex
+ alerts map[model.Fingerprint]*types.Alert
+ marker types.Marker
+ intervalGC time.Duration
+ stopGC chan struct{}
+
+ listeners map[int]chan *types.Alert
+ next int
+}
+
+// NewAlerts returns a new alert provider.
+func NewAlerts(m types.Marker, intervalGC time.Duration) (*Alerts, error) {
+ a := &Alerts{
+ alerts: map[model.Fingerprint]*types.Alert{},
+ marker: m,
+ intervalGC: intervalGC,
+ stopGC: make(chan struct{}),
+ listeners: map[int]chan *types.Alert{},
+ next: 0,
+ }
+ go a.runGC()
+
+ return a, nil
+}
+
+func (a *Alerts) runGC() {
+ for {
+ select {
+ case <-a.stopGC:
+ return
+ case <-time.After(a.intervalGC):
+ }
+
+ a.mtx.Lock()
+
+ for fp, alert := range a.alerts {
+ // As we don't persist alerts, we no longer consider them after
+ // they are resolved. Alerts waiting for resolved notifications are
+ // held in memory in aggregation groups redundantly.
+ if alert.EndsAt.Before(time.Now()) {
+ delete(a.alerts, fp)
+ a.marker.Delete(fp)
+ }
+ }
+
+ a.mtx.Unlock()
+ }
+}
+
+// Close the alert provider.
+func (a *Alerts) Close() error {
+ close(a.stopGC)
+ return nil
+}
+
+// Subscribe returns an iterator over active alerts that have not been
+// resolved and successfully notified about.
+// They are not guaranteed to be in chronological order.
+func (a *Alerts) Subscribe() provider.AlertIterator {
+ var (
+ ch = make(chan *types.Alert, 200)
+ done = make(chan struct{})
+ )
+ alerts, err := a.getPending()
+
+ a.mtx.Lock()
+ i := a.next
+ a.next++
+ a.listeners[i] = ch
+ a.mtx.Unlock()
+
+ go func() {
+ defer func() {
+ a.mtx.Lock()
+ delete(a.listeners, i)
+ close(ch)
+ a.mtx.Unlock()
+ }()
+
+ for _, a := range alerts {
+ select {
+ case ch <- a:
+ case <-done:
+ return
+ }
+ }
+
+ <-done
+ }()
+
+ return provider.NewAlertIterator(ch, done, err)
+}
+
+// GetPending returns an iterator over all alerts that have
+// pending notifications.
+func (a *Alerts) GetPending() provider.AlertIterator {
+ var (
+ ch = make(chan *types.Alert, 200)
+ done = make(chan struct{})
+ )
+
+ alerts, err := a.getPending()
+
+ go func() {
+ defer close(ch)
+
+ for _, a := range alerts {
+ select {
+ case ch <- a:
+ case <-done:
+ return
+ }
+ }
+ }()
+
+ return provider.NewAlertIterator(ch, done, err)
+}
+
+func (a *Alerts) getPending() ([]*types.Alert, error) {
+ a.mtx.RLock()
+ defer a.mtx.RUnlock()
+
+ res := make([]*types.Alert, 0, len(a.alerts))
+
+ for _, alert := range a.alerts {
+ res = append(res, alert)
+ }
+
+ return res, nil
+}
+
+// Get returns the alert for a given fingerprint.
+func (a *Alerts) Get(fp model.Fingerprint) (*types.Alert, error) {
+ a.mtx.RLock()
+ defer a.mtx.RUnlock()
+
+ alert, ok := a.alerts[fp]
+ if !ok {
+ return nil, provider.ErrNotFound
+ }
+ return alert, nil
+}
+
+// Put adds the given alert to the set.
+func (a *Alerts) Put(alerts ...*types.Alert) error {
+ a.mtx.Lock()
+ defer a.mtx.Unlock()
+
+ for _, alert := range alerts {
+ fp := alert.Fingerprint()
+
+ if old, ok := a.alerts[fp]; ok {
+ // Merge alerts if there is an overlap in activity range.
+ if (alert.EndsAt.After(old.StartsAt) && alert.EndsAt.Before(old.EndsAt)) ||
+ (alert.StartsAt.After(old.StartsAt) && alert.StartsAt.Before(old.EndsAt)) {
+ alert = old.Merge(alert)
+ }
+ }
+
+ a.alerts[fp] = alert
+
+ for _, ch := range a.listeners {
+ ch <- alert
+ }
+ }
+
+ return nil
+}
--- /dev/null
+// Copyright 2016 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/lic:wenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package mem
+
+import (
+ "fmt"
+ "reflect"
+ "testing"
+ "time"
+
+ "sync"
+
+ "github.com/kylelemons/godebug/pretty"
+ "github.com/prometheus/alertmanager/provider"
+ "github.com/prometheus/alertmanager/types"
+ "github.com/prometheus/common/model"
+)
+
+var (
+ t0 = time.Now()
+ t1 = t0.Add(100 * time.Millisecond)
+
+ alert1 = &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{"bar": "foo"},
+ Annotations: model.LabelSet{"foo": "bar"},
+ StartsAt: t0,
+ EndsAt: t1,
+ GeneratorURL: "http://example.com/prometheus",
+ },
+ UpdatedAt: t0,
+ Timeout: false,
+ }
+
+ alert2 = &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{"bar": "foo2"},
+ Annotations: model.LabelSet{"foo": "bar2"},
+ StartsAt: t0,
+ EndsAt: t1,
+ GeneratorURL: "http://example.com/prometheus",
+ },
+ UpdatedAt: t0,
+ Timeout: false,
+ }
+
+ alert3 = &types.Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{"bar": "foo3"},
+ Annotations: model.LabelSet{"foo": "bar3"},
+ StartsAt: t0,
+ EndsAt: t1,
+ GeneratorURL: "http://example.com/prometheus",
+ },
+ UpdatedAt: t0,
+ Timeout: false,
+ }
+)
+
+func init() {
+ pretty.CompareConfig.IncludeUnexported = true
+}
+
+func TestAlertsPut(t *testing.T) {
+ marker := types.NewMarker()
+ alerts, err := NewAlerts(marker, 30*time.Minute)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ insert := []*types.Alert{alert1, alert2, alert3}
+
+ if err := alerts.Put(insert...); err != nil {
+ t.Fatalf("Insert failed: %s", err)
+ }
+
+ for i, a := range insert {
+ res, err := alerts.Get(a.Fingerprint())
+ if err != nil {
+ t.Fatalf("retrieval error: %s", err)
+ }
+ if !alertsEqual(res, a) {
+ t.Errorf("Unexpected alert: %d", i)
+ t.Fatalf(pretty.Compare(res, a))
+ }
+ }
+}
+
+func TestAlertsSubscribe(t *testing.T) {
+ marker := types.NewMarker()
+ alerts, err := NewAlerts(marker, 30*time.Minute)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // add alert1 to validate if pending alerts will be send
+ if err := alerts.Put(alert1); err != nil {
+ t.Fatalf("Insert failed: %s", err)
+ }
+
+ var wg sync.WaitGroup
+ wg.Add(2)
+ fatalc := make(chan string, 2)
+
+ iterator1 := alerts.Subscribe()
+ iterator2 := alerts.Subscribe()
+
+ go func() {
+ defer wg.Done()
+ expectedAlerts := map[model.Fingerprint]*types.Alert{
+ alert1.Fingerprint(): alert1,
+ alert2.Fingerprint(): alert2,
+ alert3.Fingerprint(): alert3,
+ }
+
+ for i := 0; i < 3; i++ {
+ actual := <-iterator1.Next()
+ expected := expectedAlerts[actual.Fingerprint()]
+ if !alertsEqual(actual, expected) {
+ fatalc <- fmt.Sprintf("Unexpected alert (iterator1)\n%s", pretty.Compare(actual, expected))
+ return
+ }
+
+ delete(expectedAlerts, actual.Fingerprint())
+ }
+
+ if len(expectedAlerts) != 0 {
+ fatalc <- fmt.Sprintf("Unexpected number of alerts (iterator1): %d", len(expectedAlerts))
+ }
+ }()
+
+ go func() {
+ defer wg.Done()
+ expectedAlerts := map[model.Fingerprint]*types.Alert{
+ alert1.Fingerprint(): alert1,
+ alert2.Fingerprint(): alert2,
+ alert3.Fingerprint(): alert3,
+ }
+
+ for i := 0; i < 3; i++ {
+ actual := <-iterator2.Next()
+ expected := expectedAlerts[actual.Fingerprint()]
+ if !alertsEqual(actual, expected) {
+ t.Errorf("Unexpected alert")
+ fatalc <- fmt.Sprintf("Unexpected alert (iterator2)\n%s", pretty.Compare(actual, expected))
+ }
+
+ delete(expectedAlerts, actual.Fingerprint())
+ }
+
+ if len(expectedAlerts) != 0 {
+ fatalc <- fmt.Sprintf("Unexpected number of alerts (iterator2): %d", len(expectedAlerts))
+ }
+ }()
+
+ go func() {
+ wg.Wait()
+ close(fatalc)
+ }()
+
+ if err := alerts.Put(alert2); err != nil {
+ t.Fatalf("Insert failed: %s", err)
+ }
+
+ if err := alerts.Put(alert3); err != nil {
+ t.Fatalf("Insert failed: %s", err)
+ }
+
+ fatal, ok := <-fatalc
+ if ok {
+ t.Fatalf(fatal)
+ }
+
+ iterator1.Close()
+ iterator2.Close()
+}
+
+func TestAlertsGetPending(t *testing.T) {
+ marker := types.NewMarker()
+ alerts, err := NewAlerts(marker, 30*time.Minute)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err := alerts.Put(alert1, alert2); err != nil {
+ t.Fatalf("Insert failed: %s", err)
+ }
+
+ expectedAlerts := map[model.Fingerprint]*types.Alert{
+ alert1.Fingerprint(): alert1,
+ alert2.Fingerprint(): alert2,
+ }
+ iterator := alerts.GetPending()
+ for actual := range iterator.Next() {
+ expected := expectedAlerts[actual.Fingerprint()]
+ if !alertsEqual(actual, expected) {
+ t.Errorf("Unexpected alert")
+ t.Fatalf(pretty.Compare(actual, expected))
+ }
+ }
+
+ if err := alerts.Put(alert3); err != nil {
+ t.Fatalf("Insert failed: %s", err)
+ }
+
+ expectedAlerts = map[model.Fingerprint]*types.Alert{
+ alert1.Fingerprint(): alert1,
+ alert2.Fingerprint(): alert2,
+ alert3.Fingerprint(): alert3,
+ }
+ iterator = alerts.GetPending()
+ for actual := range iterator.Next() {
+ expected := expectedAlerts[actual.Fingerprint()]
+ if !alertsEqual(actual, expected) {
+ t.Errorf("Unexpected alert")
+ t.Fatalf(pretty.Compare(actual, expected))
+ }
+ }
+}
+
+func TestAlertsGC(t *testing.T) {
+ marker := types.NewMarker()
+ alerts, err := NewAlerts(marker, 200*time.Millisecond)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ insert := []*types.Alert{alert1, alert2, alert3}
+
+ if err := alerts.Put(insert...); err != nil {
+ t.Fatalf("Insert failed: %s", err)
+ }
+
+ for _, a := range insert {
+ marker.SetActive(a.Fingerprint())
+ if !marker.Active(a.Fingerprint()) {
+ t.Errorf("error setting status: %v", a)
+ }
+ }
+
+ time.Sleep(300 * time.Millisecond)
+
+ for i, a := range insert {
+ _, err := alerts.Get(a.Fingerprint())
+ if err != provider.ErrNotFound {
+ t.Errorf("alert %d didn't get GC'd", i)
+ }
+
+ s := marker.Status(a.Fingerprint())
+ if s.State != types.AlertStateUnprocessed {
+ t.Errorf("marker %d didn't get GC'd: %v", i, s)
+ }
+ }
+}
+
+func alertsEqual(a1, a2 *types.Alert) bool {
+ if !reflect.DeepEqual(a1.Labels, a2.Labels) {
+ return false
+ }
+ if !reflect.DeepEqual(a1.Annotations, a2.Annotations) {
+ return false
+ }
+ if a1.GeneratorURL != a2.GeneratorURL {
+ return false
+ }
+ if !a1.StartsAt.Equal(a2.StartsAt) {
+ return false
+ }
+ if !a1.EndsAt.Equal(a2.EndsAt) {
+ return false
+ }
+ if !a1.UpdatedAt.Equal(a2.UpdatedAt) {
+ return false
+ }
+ return a1.Timeout == a2.Timeout
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package provider
+
+import (
+ "fmt"
+
+ "github.com/prometheus/common/model"
+
+ "github.com/prometheus/alertmanager/types"
+)
+
+var (
+ // ErrNotFound is returned if a provider cannot find a requested item.
+ ErrNotFound = fmt.Errorf("item not found")
+)
+
+// Iterator provides the functions common to all iterators. To be useful, a
+// specific iterator interface (e.g. AlertIterator) has to be implemented that
+// provides a Next method.
+type Iterator interface {
+ // Err returns the current error. It is not safe to call it concurrently
+ // with other iterator methods or while reading from a channel returned
+ // by the iterator.
+ Err() error
+ // Close must be called to release resources once the iterator is not
+ // used anymore.
+ Close()
+}
+
+// AlertIterator is an Iterator for Alerts.
+type AlertIterator interface {
+ Iterator
+ // Next returns a channel that will be closed once the iterator is
+ // exhausted. It is not necessary to exhaust the iterator but Close must
+ // be called in any case to release resources used by the iterator (even
+ // if the iterator is exhausted).
+ Next() <-chan *types.Alert
+}
+
+// NewAlertIterator returns a new AlertIterator based on the generic alertIterator type
+func NewAlertIterator(ch <-chan *types.Alert, done chan struct{}, err error) AlertIterator {
+ return &alertIterator{
+ ch: ch,
+ done: done,
+ err: err,
+ }
+}
+
+// alertIterator implements AlertIterator. So far, this one fits all providers.
+type alertIterator struct {
+ ch <-chan *types.Alert
+ done chan struct{}
+ err error
+}
+
+func (ai alertIterator) Next() <-chan *types.Alert {
+ return ai.ch
+}
+
+func (ai alertIterator) Err() error { return ai.err }
+func (ai alertIterator) Close() { close(ai.done) }
+
+// Alerts gives access to a set of alerts. All methods are goroutine-safe.
+type Alerts interface {
+ // Subscribe returns an iterator over active alerts that have not been
+ // resolved and successfully notified about.
+ // They are not guaranteed to be in chronological order.
+ Subscribe() AlertIterator
+ // GetPending returns an iterator over all alerts that have
+ // pending notifications.
+ GetPending() AlertIterator
+ // Get returns the alert for a given fingerprint.
+ Get(model.Fingerprint) (*types.Alert, error)
+ // Put adds the given alert to the set.
+ Put(...*types.Alert) error
+}
--- /dev/null
+#!/usr/bin/env bash
+#
+# Generate all protobuf bindings.
+# Run from repository root.
+#
+# Initial script taken from etcd under the Apache 2.0 license
+# File: https://github.com/coreos/etcd/blob/78a5eb79b510eb497deddd1a76f5153bc4b202d2/scripts/genproto.sh
+
+set -e
+set -u
+
+if ! [[ "$0" =~ "scripts/genproto.sh" ]]; then
+ echo "must be run from repository root"
+ exit 255
+fi
+
+if ! [[ $(protoc --version) =~ "3.5.1" ]]; then
+ echo "could not find protoc 3.5.1, is it installed + in PATH?"
+ exit 255
+fi
+
+GOGOPROTO_ROOT="${GOPATH}/src/github.com/gogo/protobuf"
+GOGOPROTO_PATH="${GOGOPROTO_ROOT}:${GOGOPROTO_ROOT}/protobuf"
+GRPC_GATEWAY_ROOT="${GOPATH}/src/github.com/grpc-ecosystem/grpc-gateway"
+
+DIRS="nflog/nflogpb silence/silencepb cluster/clusterpb"
+
+for dir in ${DIRS}; do
+ pushd ${dir}
+ protoc --gogofast_out=plugins=grpc:. -I=. \
+ -I="${GOGOPROTO_PATH}" \
+ -I="${GRPC_GATEWAY_ROOT}/third_party/googleapis" \
+ *.proto
+
+ sed -i.bak -E 's/import _ \"gogoproto\"//g' *.pb.go
+ sed -i.bak -E 's/import _ \"google\/protobuf\"//g' *.pb.go
+ rm -f *.bak
+ goimports -w *.pb.go
+ popd
+done
--- /dev/null
+// Copyright 2016 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package silence provides a storage for silences, which can share its
+// state over a mesh network and snapshot it.
+package silence
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "math/rand"
+ "os"
+ "reflect"
+ "regexp"
+ "sync"
+ "time"
+
+ "github.com/go-kit/kit/log"
+ "github.com/go-kit/kit/log/level"
+ "github.com/matttproud/golang_protobuf_extensions/pbutil"
+ "github.com/pkg/errors"
+ "github.com/prometheus/alertmanager/cluster"
+ pb "github.com/prometheus/alertmanager/silence/silencepb"
+ "github.com/prometheus/alertmanager/types"
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/common/model"
+ "github.com/satori/go.uuid"
+)
+
+// ErrNotFound is returned if a silence was not found.
+var ErrNotFound = fmt.Errorf("not found")
+
+// ErrInvalidState is returned if the state isn't valid.
+var ErrInvalidState = fmt.Errorf("invalid state")
+
+func utcNow() time.Time {
+ return time.Now().UTC()
+}
+
+type matcherCache map[*pb.Silence]types.Matchers
+
+// Get retrieves the matchers for a given silence. If it is a missed cache
+// access, it compiles and adds the matchers of the requested silence to the
+// cache.
+func (c matcherCache) Get(s *pb.Silence) (types.Matchers, error) {
+ if m, ok := c[s]; ok {
+ return m, nil
+ }
+ return c.add(s)
+}
+
+// add compiles a silences' matchers and adds them to the cache.
+// It returns the compiled matchers.
+func (c matcherCache) add(s *pb.Silence) (types.Matchers, error) {
+ var (
+ ms types.Matchers
+ mt *types.Matcher
+ )
+
+ for _, m := range s.Matchers {
+ mt = &types.Matcher{
+ Name: m.Name,
+ Value: m.Pattern,
+ }
+ switch m.Type {
+ case pb.Matcher_EQUAL:
+ mt.IsRegex = false
+ case pb.Matcher_REGEXP:
+ mt.IsRegex = true
+ }
+ err := mt.Init()
+ if err != nil {
+ return nil, err
+ }
+
+ ms = append(ms, mt)
+ }
+
+ c[s] = ms
+
+ return ms, nil
+}
+
+// Silences holds a silence state that can be modified, queried, and snapshot.
+type Silences struct {
+ logger log.Logger
+ metrics *metrics
+ now func() time.Time
+ retention time.Duration
+
+ mtx sync.RWMutex
+ st state
+ broadcast func([]byte)
+ mc matcherCache
+}
+
+type metrics struct {
+ gcDuration prometheus.Summary
+ snapshotDuration prometheus.Summary
+ snapshotSize prometheus.Gauge
+ queriesTotal prometheus.Counter
+ queryErrorsTotal prometheus.Counter
+ queryDuration prometheus.Histogram
+ silencesActive prometheus.GaugeFunc
+ silencesPending prometheus.GaugeFunc
+ silencesExpired prometheus.GaugeFunc
+ propagatedMessagesTotal prometheus.Counter
+}
+
+func newSilenceMetricByState(s *Silences, st types.SilenceState) prometheus.GaugeFunc {
+ return prometheus.NewGaugeFunc(
+ prometheus.GaugeOpts{
+ Name: "alertmanager_silences",
+ Help: "How many silences by state.",
+ ConstLabels: prometheus.Labels{"state": string(st)},
+ },
+ func() float64 {
+ count, err := s.CountState(st)
+ if err != nil {
+ level.Error(s.logger).Log("msg", "Counting silences failed", "err", err)
+ }
+ return float64(count)
+ },
+ )
+}
+
+func newMetrics(r prometheus.Registerer, s *Silences) *metrics {
+ m := &metrics{}
+
+ m.gcDuration = prometheus.NewSummary(prometheus.SummaryOpts{
+ Name: "alertmanager_silences_gc_duration_seconds",
+ Help: "Duration of the last silence garbage collection cycle.",
+ })
+ m.snapshotDuration = prometheus.NewSummary(prometheus.SummaryOpts{
+ Name: "alertmanager_silences_snapshot_duration_seconds",
+ Help: "Duration of the last silence snapshot.",
+ })
+ m.snapshotSize = prometheus.NewGauge(prometheus.GaugeOpts{
+ Name: "alertmanager_silences_snapshot_size_bytes",
+ Help: "Size of the last silence snapshot in bytes.",
+ })
+ m.queriesTotal = prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "alertmanager_silences_queries_total",
+ Help: "How many silence queries were received.",
+ })
+ m.queryErrorsTotal = prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "alertmanager_silences_query_errors_total",
+ Help: "How many silence received queries did not succeed.",
+ })
+ m.queryDuration = prometheus.NewHistogram(prometheus.HistogramOpts{
+ Name: "alertmanager_silences_query_duration_seconds",
+ Help: "Duration of silence query evaluation.",
+ })
+ m.propagatedMessagesTotal = prometheus.NewCounter(prometheus.CounterOpts{
+ Name: "alertmanager_silences_gossip_messages_propagated_total",
+ Help: "Number of received gossip messages that have been further gossiped.",
+ })
+ if s != nil {
+ m.silencesActive = newSilenceMetricByState(s, types.SilenceStateActive)
+ m.silencesPending = newSilenceMetricByState(s, types.SilenceStatePending)
+ m.silencesExpired = newSilenceMetricByState(s, types.SilenceStateExpired)
+ }
+
+ if r != nil {
+ r.MustRegister(
+ m.gcDuration,
+ m.snapshotDuration,
+ m.snapshotSize,
+ m.queriesTotal,
+ m.queryErrorsTotal,
+ m.queryDuration,
+ m.silencesActive,
+ m.silencesPending,
+ m.silencesExpired,
+ m.propagatedMessagesTotal,
+ )
+ }
+ return m
+}
+
+// Options exposes configuration options for creating a new Silences object.
+// Its zero value is a safe default.
+type Options struct {
+ // A snapshot file or reader from which the initial state is loaded.
+ // None or only one of them must be set.
+ SnapshotFile string
+ SnapshotReader io.Reader
+
+ // Retention time for newly created Silences. Silences may be
+ // garbage collected after the given duration after they ended.
+ Retention time.Duration
+
+ // A logger used by background processing.
+ Logger log.Logger
+ Metrics prometheus.Registerer
+}
+
+func (o *Options) validate() error {
+ if o.SnapshotFile != "" && o.SnapshotReader != nil {
+ return fmt.Errorf("only one of SnapshotFile and SnapshotReader must be set")
+ }
+ return nil
+}
+
+// New returns a new Silences object with the given configuration.
+func New(o Options) (*Silences, error) {
+ if err := o.validate(); err != nil {
+ return nil, err
+ }
+ if o.SnapshotFile != "" {
+ if r, err := os.Open(o.SnapshotFile); err != nil {
+ if !os.IsNotExist(err) {
+ return nil, err
+ }
+ } else {
+ o.SnapshotReader = r
+ }
+ }
+ s := &Silences{
+ mc: matcherCache{},
+ logger: log.NewNopLogger(),
+ retention: o.Retention,
+ now: utcNow,
+ broadcast: func([]byte) {},
+ st: state{},
+ }
+ s.metrics = newMetrics(o.Metrics, s)
+
+ if o.Logger != nil {
+ s.logger = o.Logger
+ }
+ if o.SnapshotReader != nil {
+ if err := s.loadSnapshot(o.SnapshotReader); err != nil {
+ return s, err
+ }
+ }
+ return s, nil
+}
+
+// Maintenance garbage collects the silence state at the given interval. If the snapshot
+// file is set, a snapshot is written to it afterwards.
+// Terminates on receiving from stopc.
+func (s *Silences) Maintenance(interval time.Duration, snapf string, stopc <-chan struct{}) {
+ t := time.NewTicker(interval)
+ defer t.Stop()
+
+ f := func() error {
+ start := s.now()
+ var size int64
+
+ level.Debug(s.logger).Log("msg", "Running maintenance")
+ defer func() {
+ level.Debug(s.logger).Log("msg", "Maintenance done", "duration", s.now().Sub(start), "size", size)
+ s.metrics.snapshotSize.Set(float64(size))
+ }()
+
+ if _, err := s.GC(); err != nil {
+ return err
+ }
+ if snapf == "" {
+ return nil
+ }
+ f, err := openReplace(snapf)
+ if err != nil {
+ return err
+ }
+ if size, err = s.Snapshot(f); err != nil {
+ return err
+ }
+ return f.Close()
+ }
+
+Loop:
+ for {
+ select {
+ case <-stopc:
+ break Loop
+ case <-t.C:
+ if err := f(); err != nil {
+ level.Info(s.logger).Log("msg", "Running maintenance failed", "err", err)
+ }
+ }
+ }
+ // No need for final maintenance if we don't want to snapshot.
+ if snapf == "" {
+ return
+ }
+ if err := f(); err != nil {
+ level.Info(s.logger).Log("msg", "Creating shutdown snapshot failed", "err", err)
+ }
+}
+
+// GC runs a garbage collection that removes silences that have ended longer
+// than the configured retention time ago.
+func (s *Silences) GC() (int, error) {
+ start := time.Now()
+ defer func() { s.metrics.gcDuration.Observe(time.Since(start).Seconds()) }()
+
+ now := s.now()
+ var n int
+
+ s.mtx.Lock()
+ defer s.mtx.Unlock()
+
+ for id, sil := range s.st {
+ if sil.ExpiresAt.IsZero() {
+ return n, errors.New("unexpected zero expiration timestamp")
+ }
+ if !sil.ExpiresAt.After(now) {
+ delete(s.st, id)
+ delete(s.mc, sil.Silence)
+ n++
+ }
+ }
+
+ return n, nil
+}
+
+func validateMatcher(m *pb.Matcher) error {
+ if !model.LabelName(m.Name).IsValid() {
+ return fmt.Errorf("invalid label name %q", m.Name)
+ }
+ switch m.Type {
+ case pb.Matcher_EQUAL:
+ if !model.LabelValue(m.Pattern).IsValid() {
+ return fmt.Errorf("invalid label value %q", m.Pattern)
+ }
+ case pb.Matcher_REGEXP:
+ if _, err := regexp.Compile(m.Pattern); err != nil {
+ return fmt.Errorf("invalid regular expression %q: %s", m.Pattern, err)
+ }
+ default:
+ return fmt.Errorf("unknown matcher type %q", m.Type)
+ }
+ return nil
+}
+
+func validateSilence(s *pb.Silence) error {
+ if s.Id == "" {
+ return errors.New("ID missing")
+ }
+ if len(s.Matchers) == 0 {
+ return errors.New("at least one matcher required")
+ }
+ for i, m := range s.Matchers {
+ if err := validateMatcher(m); err != nil {
+ return fmt.Errorf("invalid label matcher %d: %s", i, err)
+ }
+ }
+ if s.StartsAt.IsZero() {
+ return errors.New("invalid zero start timestamp")
+ }
+ if s.EndsAt.IsZero() {
+ return errors.New("invalid zero end timestamp")
+ }
+ if s.EndsAt.Before(s.StartsAt) {
+ return errors.New("end time must not be before start time")
+ }
+ if s.UpdatedAt.IsZero() {
+ return errors.New("invalid zero update timestamp")
+ }
+ return nil
+}
+
+// cloneSilence returns a shallow copy of a silence.
+func cloneSilence(sil *pb.Silence) *pb.Silence {
+ s := *sil
+ return &s
+}
+
+func (s *Silences) getSilence(id string) (*pb.Silence, bool) {
+ msil, ok := s.st[id]
+ if !ok {
+ return nil, false
+ }
+ return msil.Silence, true
+}
+
+func (s *Silences) setSilence(sil *pb.Silence) error {
+ sil.UpdatedAt = s.now()
+
+ if err := validateSilence(sil); err != nil {
+ return errors.Wrap(err, "silence invalid")
+ }
+
+ msil := &pb.MeshSilence{
+ Silence: sil,
+ ExpiresAt: sil.EndsAt.Add(s.retention),
+ }
+ b, err := marshalMeshSilence(msil)
+ if err != nil {
+ return err
+ }
+
+ s.st.merge(msil)
+ s.broadcast(b)
+
+ return nil
+}
+
+// Set the specified silence. If a silence with the ID already exists and the modification
+// modifies history, the old silence gets expired and a new one is created.
+func (s *Silences) Set(sil *pb.Silence) (string, error) {
+ s.mtx.Lock()
+ defer s.mtx.Unlock()
+
+ now := s.now()
+ prev, ok := s.getSilence(sil.Id)
+
+ if sil.Id != "" && !ok {
+ return "", ErrNotFound
+ }
+ if ok {
+ if canUpdate(prev, sil, now) {
+ return sil.Id, s.setSilence(sil)
+ }
+ if getState(prev, s.now()) != types.SilenceStateExpired {
+ // We cannot update the silence, expire the old one.
+ if err := s.expire(prev.Id); err != nil {
+ return "", errors.Wrap(err, "expire previous silence")
+ }
+ }
+ }
+ // If we got here it's either a new silence or a replacing one.
+ sil.Id = uuid.NewV4().String()
+
+ if sil.StartsAt.Before(now) {
+ sil.StartsAt = now
+ }
+
+ return sil.Id, s.setSilence(sil)
+}
+
+// canUpdate returns true if silence a can be updated to b without
+// affecting the historic view of silencing.
+func canUpdate(a, b *pb.Silence, now time.Time) bool {
+ if !reflect.DeepEqual(a.Matchers, b.Matchers) {
+ return false
+ }
+ // Allowed timestamp modifications depend on the current time.
+ switch st := getState(a, now); st {
+ case types.SilenceStateActive:
+ if !b.StartsAt.Equal(a.StartsAt) {
+ return false
+ }
+ if b.EndsAt.Before(now) {
+ return false
+ }
+ case types.SilenceStatePending:
+ if b.StartsAt.Before(now) {
+ return false
+ }
+ case types.SilenceStateExpired:
+ return false
+ default:
+ panic("unknown silence state")
+ }
+ return true
+}
+
+// Expire the silence with the given ID immediately.
+func (s *Silences) Expire(id string) error {
+ s.mtx.Lock()
+ defer s.mtx.Unlock()
+ return s.expire(id)
+}
+
+// Expire the silence with the given ID immediately.
+func (s *Silences) expire(id string) error {
+ sil, ok := s.getSilence(id)
+ if !ok {
+ return ErrNotFound
+ }
+ sil = cloneSilence(sil)
+ now := s.now()
+
+ switch getState(sil, now) {
+ case types.SilenceStateExpired:
+ return errors.Errorf("silence %s already expired", id)
+ case types.SilenceStateActive:
+ sil.EndsAt = now
+ case types.SilenceStatePending:
+ // Set both to now to make Silence move to "expired" state
+ sil.StartsAt = now
+ sil.EndsAt = now
+ }
+
+ return s.setSilence(sil)
+}
+
+// QueryParam expresses parameters along which silences are queried.
+type QueryParam func(*query) error
+
+type query struct {
+ ids []string
+ filters []silenceFilter
+}
+
+// silenceFilter is a function that returns true if a silence
+// should be dropped from a result set for a given time.
+type silenceFilter func(*pb.Silence, *Silences, time.Time) (bool, error)
+
+var errNotSupported = errors.New("query parameter not supported")
+
+// QIDs configures a query to select the given silence IDs.
+func QIDs(ids ...string) QueryParam {
+ return func(q *query) error {
+ q.ids = append(q.ids, ids...)
+ return nil
+ }
+}
+
+// QTimeRange configures a query to search for silences that are active
+// in the given time range.
+// TODO(fabxc): not supported yet.
+func QTimeRange(start, end time.Time) QueryParam {
+ return func(q *query) error {
+ return errNotSupported
+ }
+}
+
+// QMatches returns silences that match the given label set.
+func QMatches(set model.LabelSet) QueryParam {
+ return func(q *query) error {
+ f := func(sil *pb.Silence, s *Silences, _ time.Time) (bool, error) {
+ m, err := s.mc.Get(sil)
+ if err != nil {
+ return true, err
+ }
+ return m.Match(set), nil
+ }
+ q.filters = append(q.filters, f)
+ return nil
+ }
+}
+
+// getState returns a silence's SilenceState at the given timestamp.
+func getState(sil *pb.Silence, ts time.Time) types.SilenceState {
+ if ts.Before(sil.StartsAt) {
+ return types.SilenceStatePending
+ }
+ if ts.After(sil.EndsAt) {
+ return types.SilenceStateExpired
+ }
+ return types.SilenceStateActive
+}
+
+// QState filters queried silences by the given states.
+func QState(states ...types.SilenceState) QueryParam {
+ return func(q *query) error {
+ f := func(sil *pb.Silence, _ *Silences, now time.Time) (bool, error) {
+ s := getState(sil, now)
+
+ for _, ps := range states {
+ if s == ps {
+ return true, nil
+ }
+ }
+ return false, nil
+ }
+ q.filters = append(q.filters, f)
+ return nil
+ }
+}
+
+// QueryOne queries with the given parameters and returns the first result.
+// Returns ErrNotFound if the query result is empty.
+func (s *Silences) QueryOne(params ...QueryParam) (*pb.Silence, error) {
+ res, err := s.Query(params...)
+ if err != nil {
+ return nil, err
+ }
+ if len(res) == 0 {
+ return nil, ErrNotFound
+ }
+ return res[0], nil
+}
+
+// Query for silences based on the given query parameters.
+func (s *Silences) Query(params ...QueryParam) ([]*pb.Silence, error) {
+ start := time.Now()
+ s.metrics.queriesTotal.Inc()
+
+ sils, err := func() ([]*pb.Silence, error) {
+ q := &query{}
+ for _, p := range params {
+ if err := p(q); err != nil {
+ return nil, err
+ }
+ }
+ return s.query(q, s.now())
+ }()
+ if err != nil {
+ s.metrics.queryErrorsTotal.Inc()
+ }
+ s.metrics.queryDuration.Observe(time.Since(start).Seconds())
+ return sils, err
+}
+
+// Count silences by state.
+func (s *Silences) CountState(states ...types.SilenceState) (int, error) {
+ // This could probably be optimized.
+ sils, err := s.Query(QState(states...))
+ if err != nil {
+ return -1, err
+ }
+ return len(sils), nil
+}
+
+func (s *Silences) query(q *query, now time.Time) ([]*pb.Silence, error) {
+ // If we have an ID constraint, all silences are our base set.
+ // This and the use of post-filter functions is the
+ // the trivial solution for now.
+ var res []*pb.Silence
+
+ s.mtx.Lock()
+ defer s.mtx.Unlock()
+
+ if q.ids != nil {
+ for _, id := range q.ids {
+ if s, ok := s.st[id]; ok {
+ res = append(res, s.Silence)
+ }
+ }
+ } else {
+ for _, sil := range s.st {
+ res = append(res, sil.Silence)
+ }
+ }
+
+ var resf []*pb.Silence
+ for _, sil := range res {
+ remove := false
+ for _, f := range q.filters {
+ ok, err := f(sil, s, now)
+ if err != nil {
+ return nil, err
+ }
+ if !ok {
+ remove = true
+ break
+ }
+ }
+ if !remove {
+ resf = append(resf, cloneSilence(sil))
+ }
+ }
+
+ return resf, nil
+}
+
+// loadSnapshot loads a snapshot generated by Snapshot() into the state.
+// Any previous state is wiped.
+func (s *Silences) loadSnapshot(r io.Reader) error {
+ st, err := decodeState(r)
+ if err != nil {
+ return err
+ }
+ for _, e := range st {
+ // Comments list was moved to a single comment. Upgrade on loading the snapshot.
+ if len(e.Silence.Comments) > 0 {
+ e.Silence.Comment = e.Silence.Comments[0].Comment
+ e.Silence.CreatedBy = e.Silence.Comments[0].Author
+ e.Silence.Comments = nil
+ }
+ st[e.Silence.Id] = e
+ }
+ s.mtx.Lock()
+ s.st = st
+ s.mtx.Unlock()
+
+ return nil
+}
+
+// Snapshot writes the full internal state into the writer and returns the number of bytes
+// written.
+func (s *Silences) Snapshot(w io.Writer) (int64, error) {
+ start := time.Now()
+ defer func() { s.metrics.snapshotDuration.Observe(time.Since(start).Seconds()) }()
+
+ s.mtx.RLock()
+ defer s.mtx.RUnlock()
+
+ b, err := s.st.MarshalBinary()
+ if err != nil {
+ return 0, err
+ }
+
+ return io.Copy(w, bytes.NewReader(b))
+}
+
+// MarshalBinary serializes all silences.
+func (s *Silences) MarshalBinary() ([]byte, error) {
+ s.mtx.Lock()
+ defer s.mtx.Unlock()
+
+ return s.st.MarshalBinary()
+}
+
+// Merge merges silence state received from the cluster with the local state.
+func (s *Silences) Merge(b []byte) error {
+ st, err := decodeState(bytes.NewReader(b))
+ if err != nil {
+ return err
+ }
+ s.mtx.Lock()
+ defer s.mtx.Unlock()
+
+ for _, e := range st {
+ if merged := s.st.merge(e); merged && !cluster.OversizedMessage(b) {
+ // If this is the first we've seen the message and it's
+ // not oversized, gossip it to other nodes. We don't
+ // propagate oversized messages because they're sent to
+ // all nodes already.
+ s.broadcast(b)
+ s.metrics.propagatedMessagesTotal.Inc()
+ level.Debug(s.logger).Log("msg", "gossiping new silence", "silence", e)
+ }
+ }
+ return nil
+}
+
+func (s *Silences) SetBroadcast(f func([]byte)) {
+ s.mtx.Lock()
+ s.broadcast = f
+ s.mtx.Unlock()
+}
+
+type state map[string]*pb.MeshSilence
+
+func (s state) merge(e *pb.MeshSilence) bool {
+ // Comments list was moved to a single comment. Apply upgrade
+ // on silences received from peers.
+ if len(e.Silence.Comments) > 0 {
+ e.Silence.Comment = e.Silence.Comments[0].Comment
+ e.Silence.CreatedBy = e.Silence.Comments[0].Author
+ e.Silence.Comments = nil
+ }
+ id := e.Silence.Id
+
+ prev, ok := s[id]
+ if !ok || prev.Silence.UpdatedAt.Before(e.Silence.UpdatedAt) {
+ s[id] = e
+ return true
+ }
+ return false
+}
+
+func (s state) MarshalBinary() ([]byte, error) {
+ var buf bytes.Buffer
+
+ for _, e := range s {
+ if _, err := pbutil.WriteDelimited(&buf, e); err != nil {
+ return nil, err
+ }
+ }
+ return buf.Bytes(), nil
+}
+
+func decodeState(r io.Reader) (state, error) {
+ st := state{}
+ for {
+ var s pb.MeshSilence
+ _, err := pbutil.ReadDelimited(r, &s)
+ if err == nil {
+ if s.Silence == nil {
+ return nil, ErrInvalidState
+ }
+ st[s.Silence.Id] = &s
+ continue
+ }
+ if err == io.EOF {
+ break
+ }
+ return nil, err
+ }
+ return st, nil
+}
+
+func marshalMeshSilence(e *pb.MeshSilence) ([]byte, error) {
+ var buf bytes.Buffer
+ if _, err := pbutil.WriteDelimited(&buf, e); err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+// replaceFile wraps a file that is moved to another filename on closing.
+type replaceFile struct {
+ *os.File
+ filename string
+}
+
+func (f *replaceFile) Close() error {
+ if err := f.File.Sync(); err != nil {
+ return err
+ }
+ if err := f.File.Close(); err != nil {
+ return err
+ }
+ return os.Rename(f.File.Name(), f.filename)
+}
+
+// openReplace opens a new temporary file that is moved to filename on closing.
+func openReplace(filename string) (*replaceFile, error) {
+ tmpFilename := fmt.Sprintf("%s.%x", filename, uint64(rand.Int63()))
+
+ f, err := os.Create(tmpFilename)
+ if err != nil {
+ return nil, err
+ }
+
+ rf := &replaceFile{
+ File: f,
+ filename: filename,
+ }
+ return rf, nil
+}
--- /dev/null
+// Copyright 2016 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package silence
+
+import (
+ "bytes"
+ "io/ioutil"
+ "os"
+ "sort"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/matttproud/golang_protobuf_extensions/pbutil"
+ pb "github.com/prometheus/alertmanager/silence/silencepb"
+ "github.com/prometheus/alertmanager/types"
+ "github.com/prometheus/common/model"
+ "github.com/stretchr/testify/require"
+)
+
+func TestOptionsValidate(t *testing.T) {
+ cases := []struct {
+ options *Options
+ err string
+ }{
+ {
+ options: &Options{
+ SnapshotReader: &bytes.Buffer{},
+ },
+ },
+ {
+ options: &Options{
+ SnapshotFile: "test.bkp",
+ },
+ },
+ {
+ options: &Options{
+ SnapshotFile: "test bkp",
+ SnapshotReader: &bytes.Buffer{},
+ },
+ err: "only one of SnapshotFile and SnapshotReader must be set",
+ },
+ }
+
+ for _, c := range cases {
+ err := c.options.validate()
+ if err == nil {
+ if c.err != "" {
+ t.Errorf("expected error containing %q but got none", c.err)
+ }
+ continue
+ }
+ if err != nil && c.err == "" {
+ t.Errorf("unexpected error %q", err)
+ continue
+ }
+ if !strings.Contains(err.Error(), c.err) {
+ t.Errorf("expected error to contain %q but got %q", c.err, err)
+ }
+ }
+}
+
+func TestSilencesGC(t *testing.T) {
+ s, err := New(Options{})
+ require.NoError(t, err)
+
+ now := utcNow()
+ s.now = func() time.Time { return now }
+
+ newSilence := func(exp time.Time) *pb.MeshSilence {
+ return &pb.MeshSilence{ExpiresAt: exp}
+ }
+ s.st = state{
+ "1": newSilence(now),
+ "2": newSilence(now.Add(-time.Second)),
+ "3": newSilence(now.Add(time.Second)),
+ }
+ want := state{
+ "3": newSilence(now.Add(time.Second)),
+ }
+
+ n, err := s.GC()
+ require.NoError(t, err)
+ require.Equal(t, 2, n)
+ require.Equal(t, want, s.st)
+}
+
+func TestSilencesSnapshot(t *testing.T) {
+ // Check whether storing and loading the snapshot is symmetric.
+ now := utcNow()
+
+ cases := []struct {
+ entries []*pb.MeshSilence
+ }{
+ {
+ entries: []*pb.MeshSilence{
+ {
+ Silence: &pb.Silence{
+ Id: "3be80475-e219-4ee7-b6fc-4b65114e362f",
+ Matchers: []*pb.Matcher{
+ {Name: "label1", Pattern: "val1", Type: pb.Matcher_EQUAL},
+ {Name: "label2", Pattern: "val.+", Type: pb.Matcher_REGEXP},
+ },
+ StartsAt: now,
+ EndsAt: now,
+ UpdatedAt: now,
+ },
+ ExpiresAt: now,
+ },
+ {
+ Silence: &pb.Silence{
+ Id: "4b1e760d-182c-4980-b873-c1a6827c9817",
+ Matchers: []*pb.Matcher{
+ {Name: "label1", Pattern: "val1", Type: pb.Matcher_EQUAL},
+ },
+ StartsAt: now.Add(time.Hour),
+ EndsAt: now.Add(2 * time.Hour),
+ UpdatedAt: now,
+ },
+ ExpiresAt: now.Add(24 * time.Hour),
+ },
+ },
+ },
+ }
+
+ for _, c := range cases {
+ f, err := ioutil.TempFile("", "snapshot")
+ require.NoError(t, err, "creating temp file failed")
+
+ s1 := &Silences{st: state{}, metrics: newMetrics(nil, nil)}
+ // Setup internal state manually.
+ for _, e := range c.entries {
+ s1.st[e.Silence.Id] = e
+ }
+ _, err = s1.Snapshot(f)
+ require.NoError(t, err, "creating snapshot failed")
+
+ require.NoError(t, f.Close(), "closing snapshot file failed")
+
+ f, err = os.Open(f.Name())
+ require.NoError(t, err, "opening snapshot file failed")
+
+ // Check again against new nlog instance.
+ s2 := &Silences{mc: matcherCache{}, st: state{}}
+ err = s2.loadSnapshot(f)
+ require.NoError(t, err, "error loading snapshot")
+ require.Equal(t, s1.st, s2.st, "state after loading snapshot did not match snapshotted state")
+
+ require.NoError(t, f.Close(), "closing snapshot file failed")
+ }
+}
+
+func TestSilencesSetSilence(t *testing.T) {
+ s, err := New(Options{
+ Retention: time.Minute,
+ })
+ require.NoError(t, err)
+
+ now := utcNow()
+ nowpb := now
+
+ sil := &pb.Silence{
+ Id: "some_id",
+ Matchers: []*pb.Matcher{{Name: "abc", Pattern: "def"}},
+ StartsAt: nowpb,
+ EndsAt: nowpb,
+ }
+
+ want := state{
+ "some_id": &pb.MeshSilence{
+ Silence: sil,
+ ExpiresAt: now.Add(time.Minute),
+ },
+ }
+
+ done := make(chan bool)
+ s.broadcast = func(b []byte) {
+ var e pb.MeshSilence
+ r := bytes.NewReader(b)
+ _, err := pbutil.ReadDelimited(r, &e)
+ require.NoError(t, err)
+
+ require.Equal(t, want["some_id"], &e)
+ close(done)
+ }
+
+ // setSilence() is always called with s.mtx locked()
+ go func() {
+ s.mtx.Lock()
+ require.NoError(t, s.setSilence(sil))
+ s.mtx.Unlock()
+ }()
+
+ // GossipBroadcast is called in a goroutine.
+ select {
+ case <-done:
+ case <-time.After(1 * time.Second):
+ t.Fatal("GossipBroadcast was not called")
+ }
+
+ require.Equal(t, want, s.st, "Unexpected silence state")
+}
+
+func TestSilenceSet(t *testing.T) {
+ s, err := New(Options{
+ Retention: time.Hour,
+ })
+ require.NoError(t, err)
+
+ now := utcNow()
+ now1 := now
+ s.now = func() time.Time { return now }
+
+ // Insert silence with fixed start time.
+ sil1 := &pb.Silence{
+ Matchers: []*pb.Matcher{{Name: "a", Pattern: "b"}},
+ StartsAt: now.Add(2 * time.Minute),
+ EndsAt: now.Add(5 * time.Minute),
+ }
+ id1, err := s.Set(sil1)
+ require.NoError(t, err)
+ require.NotEqual(t, id1, "")
+
+ want := state{
+ id1: &pb.MeshSilence{
+ Silence: &pb.Silence{
+ Id: id1,
+ Matchers: []*pb.Matcher{{Name: "a", Pattern: "b"}},
+ StartsAt: now1.Add(2 * time.Minute),
+ EndsAt: now1.Add(5 * time.Minute),
+ UpdatedAt: now1,
+ },
+ ExpiresAt: now1.Add(5*time.Minute + s.retention),
+ },
+ }
+ require.Equal(t, want, s.st, "unexpected state after silence creation")
+
+ // Insert silence with unset start time. Must be set to now.
+ now = now.Add(time.Minute)
+ now2 := now
+
+ sil2 := &pb.Silence{
+ Matchers: []*pb.Matcher{{Name: "a", Pattern: "b"}},
+ EndsAt: now.Add(1 * time.Minute),
+ }
+ id2, err := s.Set(sil2)
+ require.NoError(t, err)
+ require.NotEqual(t, id2, "")
+
+ want = state{
+ id1: want[id1],
+ id2: &pb.MeshSilence{
+ Silence: &pb.Silence{
+ Id: id2,
+ Matchers: []*pb.Matcher{{Name: "a", Pattern: "b"}},
+ StartsAt: now2,
+ EndsAt: now2.Add(1 * time.Minute),
+ UpdatedAt: now2,
+ },
+ ExpiresAt: now2.Add(1*time.Minute + s.retention),
+ },
+ }
+ require.Equal(t, want, s.st, "unexpected state after silence creation")
+
+ // Overwrite silence 2 with new end time.
+ now = now.Add(time.Minute)
+ now3 := now
+
+ sil3 := cloneSilence(sil2)
+ sil3.EndsAt = now.Add(100 * time.Minute)
+
+ id3, err := s.Set(sil3)
+ require.NoError(t, err)
+ require.Equal(t, id2, id3)
+
+ want = state{
+ id1: want[id1],
+ id2: &pb.MeshSilence{
+ Silence: &pb.Silence{
+ Id: id2,
+ Matchers: []*pb.Matcher{{Name: "a", Pattern: "b"}},
+ StartsAt: now2,
+ EndsAt: now3.Add(100 * time.Minute),
+ UpdatedAt: now3,
+ },
+ ExpiresAt: now3.Add(100*time.Minute + s.retention),
+ },
+ }
+ require.Equal(t, want, s.st, "unexpected state after silence creation")
+
+ // Update silence 2 with new matcher expires it and creates a new one.
+ now = now.Add(time.Minute)
+ now4 := now
+
+ sil4 := cloneSilence(sil3)
+ sil4.Matchers = []*pb.Matcher{{Name: "a", Pattern: "c"}}
+
+ id4, err := s.Set(sil4)
+ require.NoError(t, err)
+ require.NotEqual(t, id2, id4)
+
+ want = state{
+ id1: want[id1],
+ id2: &pb.MeshSilence{
+ Silence: &pb.Silence{
+ Id: id2,
+ Matchers: []*pb.Matcher{{Name: "a", Pattern: "b"}},
+ StartsAt: now2,
+ EndsAt: now4,
+ UpdatedAt: now4,
+ },
+ ExpiresAt: now4.Add(s.retention),
+ },
+ id4: &pb.MeshSilence{
+ Silence: &pb.Silence{
+ Id: id4,
+ Matchers: []*pb.Matcher{{Name: "a", Pattern: "c"}},
+ StartsAt: now4,
+ EndsAt: now3.Add(100 * time.Minute),
+ UpdatedAt: now4,
+ },
+ ExpiresAt: now3.Add(100*time.Minute + s.retention),
+ },
+ }
+ require.Equal(t, want, s.st, "unexpected state after silence creation")
+
+ // Re-create expired silence.
+ now = now.Add(time.Minute)
+ now5 := now
+
+ sil5 := cloneSilence(sil3)
+ sil5.StartsAt = now
+ sil5.EndsAt = now.Add(5 * time.Minute)
+
+ id5, err := s.Set(sil5)
+ require.NoError(t, err)
+ require.NotEqual(t, id2, id4)
+
+ want = state{
+ id1: want[id1],
+ id2: want[id2],
+ id4: want[id4],
+ id5: &pb.MeshSilence{
+ Silence: &pb.Silence{
+ Id: id5,
+ Matchers: []*pb.Matcher{{Name: "a", Pattern: "b"}},
+ StartsAt: now5,
+ EndsAt: now5.Add(5 * time.Minute),
+ UpdatedAt: now5,
+ },
+ ExpiresAt: now5.Add(5*time.Minute + s.retention),
+ },
+ }
+ require.Equal(t, want, s.st, "unexpected state after silence creation")
+}
+
+func TestSilencesSetFail(t *testing.T) {
+ s, err := New(Options{})
+ require.NoError(t, err)
+
+ now := utcNow()
+ s.now = func() time.Time { return now }
+
+ cases := []struct {
+ s *pb.Silence
+ err string
+ }{
+ {
+ s: &pb.Silence{Id: "some_id"},
+ err: ErrNotFound.Error(),
+ }, {
+ s: &pb.Silence{}, // Silence without matcher.
+ err: "silence invalid",
+ },
+ }
+ for _, c := range cases {
+ _, err := s.Set(c.s)
+ if err == nil {
+ if c.err != "" {
+ t.Errorf("expected error containing %q but got none", c.err)
+ }
+ continue
+ }
+ if err != nil && c.err == "" {
+ t.Errorf("unexpected error %q", err)
+ continue
+ }
+ if !strings.Contains(err.Error(), c.err) {
+ t.Errorf("expected error to contain %q but got %q", c.err, err)
+ }
+ }
+}
+
+func TestQState(t *testing.T) {
+ now := utcNow()
+
+ cases := []struct {
+ sil *pb.Silence
+ states []types.SilenceState
+ keep bool
+ }{
+ {
+ sil: &pb.Silence{
+ StartsAt: now.Add(time.Minute),
+ EndsAt: now.Add(time.Hour),
+ },
+ states: []types.SilenceState{types.SilenceStateActive, types.SilenceStateExpired},
+ keep: false,
+ },
+ {
+ sil: &pb.Silence{
+ StartsAt: now.Add(time.Minute),
+ EndsAt: now.Add(time.Hour),
+ },
+ states: []types.SilenceState{types.SilenceStatePending},
+ keep: true,
+ },
+ {
+ sil: &pb.Silence{
+ StartsAt: now.Add(time.Minute),
+ EndsAt: now.Add(time.Hour),
+ },
+ states: []types.SilenceState{types.SilenceStateExpired, types.SilenceStatePending},
+ keep: true,
+ },
+ }
+ for i, c := range cases {
+ q := &query{}
+ QState(c.states...)(q)
+ f := q.filters[0]
+
+ keep, err := f(c.sil, nil, now)
+ require.NoError(t, err)
+ require.Equal(t, c.keep, keep, "unexpected filter result for case %d", i)
+ }
+}
+
+func TestQMatches(t *testing.T) {
+ qp := QMatches(model.LabelSet{
+ "job": "test",
+ "instance": "web-1",
+ "path": "/user/profile",
+ "method": "GET",
+ })
+
+ q := &query{}
+ qp(q)
+ f := q.filters[0]
+
+ cases := []struct {
+ sil *pb.Silence
+ drop bool
+ }{
+ {
+ sil: &pb.Silence{
+ Matchers: []*pb.Matcher{
+ {Name: "job", Pattern: "test", Type: pb.Matcher_EQUAL},
+ },
+ },
+ drop: true,
+ },
+ {
+ sil: &pb.Silence{
+ Matchers: []*pb.Matcher{
+ {Name: "job", Pattern: "test", Type: pb.Matcher_EQUAL},
+ {Name: "method", Pattern: "POST", Type: pb.Matcher_EQUAL},
+ },
+ },
+ drop: false,
+ },
+ {
+ sil: &pb.Silence{
+ Matchers: []*pb.Matcher{
+ {Name: "path", Pattern: "/user/.+", Type: pb.Matcher_REGEXP},
+ },
+ },
+ drop: true,
+ },
+ {
+ sil: &pb.Silence{
+ Matchers: []*pb.Matcher{
+ {Name: "path", Pattern: "/user/.+", Type: pb.Matcher_REGEXP},
+ {Name: "path", Pattern: "/nothing/.+", Type: pb.Matcher_REGEXP},
+ },
+ },
+ drop: false,
+ },
+ }
+ for _, c := range cases {
+ drop, err := f(c.sil, &Silences{mc: matcherCache{}, st: state{}}, time.Time{})
+ require.NoError(t, err)
+ require.Equal(t, c.drop, drop, "unexpected filter result")
+ }
+}
+
+func TestSilencesQuery(t *testing.T) {
+ s, err := New(Options{})
+ require.NoError(t, err)
+
+ s.st = state{
+ "1": &pb.MeshSilence{Silence: &pb.Silence{Id: "1"}},
+ "2": &pb.MeshSilence{Silence: &pb.Silence{Id: "2"}},
+ "3": &pb.MeshSilence{Silence: &pb.Silence{Id: "3"}},
+ "4": &pb.MeshSilence{Silence: &pb.Silence{Id: "4"}},
+ "5": &pb.MeshSilence{Silence: &pb.Silence{Id: "5"}},
+ }
+ cases := []struct {
+ q *query
+ exp []*pb.Silence
+ }{
+ {
+ // Default query of retrieving all silences.
+ q: &query{},
+ exp: []*pb.Silence{
+ {Id: "1"},
+ {Id: "2"},
+ {Id: "3"},
+ {Id: "4"},
+ {Id: "5"},
+ },
+ },
+ {
+ // Retrieve by IDs.
+ q: &query{
+ ids: []string{"2", "5"},
+ },
+ exp: []*pb.Silence{
+ {Id: "2"},
+ {Id: "5"},
+ },
+ },
+ {
+ // Retrieve all and filter
+ q: &query{
+ filters: []silenceFilter{
+ func(sil *pb.Silence, _ *Silences, _ time.Time) (bool, error) {
+ return sil.Id == "1" || sil.Id == "2", nil
+ },
+ },
+ },
+ exp: []*pb.Silence{
+ {Id: "1"},
+ {Id: "2"},
+ },
+ },
+ {
+ // Retrieve by IDs and filter
+ q: &query{
+ ids: []string{"2", "5"},
+ filters: []silenceFilter{
+ func(sil *pb.Silence, _ *Silences, _ time.Time) (bool, error) {
+ return sil.Id == "1" || sil.Id == "2", nil
+ },
+ },
+ },
+ exp: []*pb.Silence{
+ {Id: "2"},
+ },
+ },
+ }
+
+ for _, c := range cases {
+ // Run default query of retrieving all silences.
+ res, err := s.query(c.q, time.Time{})
+ require.NoError(t, err, "unexpected error on querying")
+
+ // Currently there are no sorting guarantees in the querying API.
+ sort.Sort(silencesByID(c.exp))
+ sort.Sort(silencesByID(res))
+ require.Equal(t, c.exp, res, "unexpected silences in result")
+ }
+}
+
+type silencesByID []*pb.Silence
+
+func (s silencesByID) Len() int { return len(s) }
+func (s silencesByID) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s silencesByID) Less(i, j int) bool { return s[i].Id < s[j].Id }
+
+func TestSilenceCanUpdate(t *testing.T) {
+ now := utcNow()
+
+ cases := []struct {
+ a, b *pb.Silence
+ ok bool
+ }{
+ // Bad arguments.
+ {
+ a: &pb.Silence{},
+ b: &pb.Silence{
+ StartsAt: now,
+ EndsAt: now.Add(-time.Minute),
+ },
+ ok: false,
+ },
+ // Expired silence.
+ {
+ a: &pb.Silence{
+ StartsAt: now.Add(-time.Hour),
+ EndsAt: now.Add(-time.Second),
+ },
+ b: &pb.Silence{
+ StartsAt: now,
+ EndsAt: now,
+ },
+ ok: false,
+ },
+ // Pending silences.
+ {
+ a: &pb.Silence{
+ StartsAt: now.Add(time.Hour),
+ EndsAt: now.Add(2 * time.Hour),
+ UpdatedAt: now.Add(-time.Hour),
+ },
+ b: &pb.Silence{
+ StartsAt: now.Add(-time.Minute),
+ EndsAt: now.Add(time.Hour),
+ },
+ ok: false,
+ },
+ {
+ a: &pb.Silence{
+ StartsAt: now.Add(time.Hour),
+ EndsAt: now.Add(2 * time.Hour),
+ UpdatedAt: now.Add(-time.Hour),
+ },
+ b: &pb.Silence{
+ StartsAt: now.Add(time.Minute),
+ EndsAt: now.Add(time.Minute),
+ },
+ ok: true,
+ },
+ {
+ a: &pb.Silence{
+ StartsAt: now.Add(time.Hour),
+ EndsAt: now.Add(2 * time.Hour),
+ UpdatedAt: now.Add(-time.Hour),
+ },
+ b: &pb.Silence{
+ StartsAt: now, // set to exactly start now.
+ EndsAt: now.Add(2 * time.Hour),
+ },
+ ok: true,
+ },
+ // Active silences.
+ {
+ a: &pb.Silence{
+ StartsAt: now.Add(-time.Hour),
+ EndsAt: now.Add(2 * time.Hour),
+ UpdatedAt: now.Add(-time.Hour),
+ },
+ b: &pb.Silence{
+ StartsAt: now.Add(-time.Minute),
+ EndsAt: now.Add(2 * time.Hour),
+ },
+ ok: false,
+ },
+ {
+ a: &pb.Silence{
+ StartsAt: now.Add(-time.Hour),
+ EndsAt: now.Add(2 * time.Hour),
+ UpdatedAt: now.Add(-time.Hour),
+ },
+ b: &pb.Silence{
+ StartsAt: now.Add(-time.Hour),
+ EndsAt: now.Add(-time.Second),
+ },
+ ok: false,
+ },
+ {
+ a: &pb.Silence{
+ StartsAt: now.Add(-time.Hour),
+ EndsAt: now.Add(2 * time.Hour),
+ UpdatedAt: now.Add(-time.Hour),
+ },
+ b: &pb.Silence{
+ StartsAt: now.Add(-time.Hour),
+ EndsAt: now,
+ },
+ ok: true,
+ },
+ {
+ a: &pb.Silence{
+ StartsAt: now.Add(-time.Hour),
+ EndsAt: now.Add(2 * time.Hour),
+ UpdatedAt: now.Add(-time.Hour),
+ },
+ b: &pb.Silence{
+ StartsAt: now.Add(-time.Hour),
+ EndsAt: now.Add(3 * time.Hour),
+ },
+ ok: true,
+ },
+ }
+ for _, c := range cases {
+ ok := canUpdate(c.a, c.b, now)
+ if ok && !c.ok {
+ t.Errorf("expected not-updateable but was: %v, %v", c.a, c.b)
+ }
+ if ok && !c.ok {
+ t.Errorf("expected updateable but was not: %v, %v", c.a, c.b)
+ }
+ }
+}
+
+func TestSilenceExpire(t *testing.T) {
+ s, err := New(Options{})
+ require.NoError(t, err)
+
+ now := time.Now()
+ s.now = func() time.Time { return now }
+
+ m := &pb.Matcher{Type: pb.Matcher_EQUAL, Name: "a", Pattern: "b"}
+
+ s.st = state{
+ "pending": &pb.MeshSilence{Silence: &pb.Silence{
+ Id: "pending",
+ Matchers: []*pb.Matcher{m},
+ StartsAt: now.Add(time.Minute),
+ EndsAt: now.Add(time.Hour),
+ UpdatedAt: now.Add(-time.Hour),
+ }},
+ "active": &pb.MeshSilence{Silence: &pb.Silence{
+ Id: "active",
+ Matchers: []*pb.Matcher{m},
+ StartsAt: now.Add(-time.Minute),
+ EndsAt: now.Add(time.Hour),
+ UpdatedAt: now.Add(-time.Hour),
+ }},
+ "expired": &pb.MeshSilence{Silence: &pb.Silence{
+ Id: "expired",
+ Matchers: []*pb.Matcher{m},
+ StartsAt: now.Add(-time.Hour),
+ EndsAt: now.Add(-time.Minute),
+ UpdatedAt: now.Add(-time.Hour),
+ }},
+ }
+
+ count, err := s.CountState(types.SilenceStatePending)
+ require.NoError(t, err)
+ require.Equal(t, 1, count)
+
+ require.NoError(t, s.expire("pending"))
+ require.NoError(t, s.expire("active"))
+
+ err = s.expire("expired")
+ require.Error(t, err)
+ require.Contains(t, err.Error(), "already expired")
+
+ sil, err := s.QueryOne(QIDs("pending"))
+ require.NoError(t, err)
+ require.Equal(t, &pb.Silence{
+ Id: "pending",
+ Matchers: []*pb.Matcher{m},
+ StartsAt: now,
+ EndsAt: now,
+ UpdatedAt: now,
+ }, sil)
+
+ count, err = s.CountState(types.SilenceStatePending)
+ require.NoError(t, err)
+ require.Equal(t, 0, count)
+
+ // Expiring a pending Silence should make the API return the
+ // SilenceStateExpired Silence state.
+ silenceState := types.CalcSilenceState(sil.StartsAt, sil.EndsAt)
+ require.Equal(t, silenceState, types.SilenceStateExpired)
+
+ sil, err = s.QueryOne(QIDs("active"))
+ require.NoError(t, err)
+ require.Equal(t, &pb.Silence{
+ Id: "active",
+ Matchers: []*pb.Matcher{m},
+ StartsAt: now.Add(-time.Minute),
+ EndsAt: now,
+ UpdatedAt: now,
+ }, sil)
+
+ sil, err = s.QueryOne(QIDs("expired"))
+ require.NoError(t, err)
+ require.Equal(t, &pb.Silence{
+ Id: "expired",
+ Matchers: []*pb.Matcher{m},
+ StartsAt: now.Add(-time.Hour),
+ EndsAt: now.Add(-time.Minute),
+ UpdatedAt: now.Add(-time.Hour),
+ }, sil)
+}
+
+func TestValidateMatcher(t *testing.T) {
+ cases := []struct {
+ m *pb.Matcher
+ err string
+ }{
+ {
+ m: &pb.Matcher{
+ Name: "a",
+ Pattern: "b",
+ Type: pb.Matcher_EQUAL,
+ },
+ err: "",
+ }, {
+ m: &pb.Matcher{
+ Name: "00",
+ Pattern: "a",
+ Type: pb.Matcher_EQUAL,
+ },
+ err: "invalid label name",
+ }, {
+ m: &pb.Matcher{
+ Name: "a",
+ Pattern: "((",
+ Type: pb.Matcher_REGEXP,
+ },
+ err: "invalid regular expression",
+ }, {
+ m: &pb.Matcher{
+ Name: "a",
+ Pattern: "\xff",
+ Type: pb.Matcher_EQUAL,
+ },
+ err: "invalid label value",
+ }, {
+ m: &pb.Matcher{
+ Name: "a",
+ Pattern: "b",
+ Type: 333,
+ },
+ err: "unknown matcher type",
+ },
+ }
+
+ for _, c := range cases {
+ err := validateMatcher(c.m)
+ if err == nil {
+ if c.err != "" {
+ t.Errorf("expected error containing %q but got none", c.err)
+ }
+ continue
+ }
+ if err != nil && c.err == "" {
+ t.Errorf("unexpected error %q", err)
+ continue
+ }
+ if !strings.Contains(err.Error(), c.err) {
+ t.Errorf("expected error to contain %q but got %q", c.err, err)
+ }
+ }
+}
+
+func TestValidateSilence(t *testing.T) {
+ var (
+ now = utcNow()
+ zeroTimestamp = time.Time{}
+ validTimestamp = now
+ )
+ cases := []struct {
+ s *pb.Silence
+ err string
+ }{
+ {
+ s: &pb.Silence{
+ Id: "some_id",
+ Matchers: []*pb.Matcher{
+ &pb.Matcher{Name: "a", Pattern: "b"},
+ },
+ StartsAt: validTimestamp,
+ EndsAt: validTimestamp,
+ UpdatedAt: validTimestamp,
+ },
+ err: "",
+ },
+ {
+ s: &pb.Silence{
+ Id: "",
+ Matchers: []*pb.Matcher{
+ &pb.Matcher{Name: "a", Pattern: "b"},
+ },
+ StartsAt: validTimestamp,
+ EndsAt: validTimestamp,
+ UpdatedAt: validTimestamp,
+ },
+ err: "ID missing",
+ },
+ {
+ s: &pb.Silence{
+ Id: "some_id",
+ Matchers: []*pb.Matcher{},
+ StartsAt: validTimestamp,
+ EndsAt: validTimestamp,
+ UpdatedAt: validTimestamp,
+ },
+ err: "at least one matcher required",
+ },
+ {
+ s: &pb.Silence{
+ Id: "some_id",
+ Matchers: []*pb.Matcher{
+ &pb.Matcher{Name: "a", Pattern: "b"},
+ &pb.Matcher{Name: "00", Pattern: "b"},
+ },
+ StartsAt: validTimestamp,
+ EndsAt: validTimestamp,
+ UpdatedAt: validTimestamp,
+ },
+ err: "invalid label matcher",
+ },
+ {
+ s: &pb.Silence{
+ Id: "some_id",
+ Matchers: []*pb.Matcher{
+ &pb.Matcher{Name: "a", Pattern: "b"},
+ },
+ StartsAt: now,
+ EndsAt: now.Add(-time.Second),
+ UpdatedAt: validTimestamp,
+ },
+ err: "end time must not be before start time",
+ },
+ {
+ s: &pb.Silence{
+ Id: "some_id",
+ Matchers: []*pb.Matcher{
+ &pb.Matcher{Name: "a", Pattern: "b"},
+ },
+ StartsAt: zeroTimestamp,
+ EndsAt: validTimestamp,
+ UpdatedAt: validTimestamp,
+ },
+ err: "invalid zero start timestamp",
+ },
+ {
+ s: &pb.Silence{
+ Id: "some_id",
+ Matchers: []*pb.Matcher{
+ &pb.Matcher{Name: "a", Pattern: "b"},
+ },
+ StartsAt: validTimestamp,
+ EndsAt: zeroTimestamp,
+ UpdatedAt: validTimestamp,
+ },
+ err: "invalid zero end timestamp",
+ },
+ {
+ s: &pb.Silence{
+ Id: "some_id",
+ Matchers: []*pb.Matcher{
+ &pb.Matcher{Name: "a", Pattern: "b"},
+ },
+ StartsAt: validTimestamp,
+ EndsAt: validTimestamp,
+ UpdatedAt: zeroTimestamp,
+ },
+ err: "invalid zero update timestamp",
+ },
+ }
+ for _, c := range cases {
+ err := validateSilence(c.s)
+ if err == nil {
+ if c.err != "" {
+ t.Errorf("expected error containing %q but got none", c.err)
+ }
+ continue
+ }
+ if err != nil && c.err == "" {
+ t.Errorf("unexpected error %q", err)
+ continue
+ }
+ if !strings.Contains(err.Error(), c.err) {
+ t.Errorf("expected error to contain %q but got %q", c.err, err)
+ }
+ }
+}
+
+func TestStateMerge(t *testing.T) {
+ now := utcNow()
+
+ // We only care about key names and timestamps for the
+ // merging logic.
+ newSilence := func(id string, ts time.Time) *pb.MeshSilence {
+ return &pb.MeshSilence{
+ Silence: &pb.Silence{Id: id, UpdatedAt: ts},
+ }
+ }
+
+ cases := []struct {
+ a, b state
+ final state
+ }{
+ {
+ a: state{
+ "a1": newSilence("a1", now),
+ "a2": newSilence("a2", now),
+ "a3": newSilence("a3", now),
+ },
+ b: state{
+ "b1": newSilence("b1", now), // new key, should be added
+ "a2": newSilence("a2", now.Add(-time.Minute)), // older timestamp, should be dropped
+ "a3": newSilence("a3", now.Add(time.Minute)), // newer timestamp, should overwrite
+ },
+ final: state{
+ "a1": newSilence("a1", now),
+ "a2": newSilence("a2", now),
+ "a3": newSilence("a3", now.Add(time.Minute)),
+ "b1": newSilence("b1", now),
+ },
+ },
+ }
+
+ for _, c := range cases {
+ for _, e := range c.b {
+ c.a.merge(e)
+ }
+
+ require.Equal(t, c.final, c.a, "Merge result should match expectation")
+ }
+}
+
+func TestStateCoding(t *testing.T) {
+ // Check whether encoding and decoding the data is symmetric.
+ now := utcNow()
+
+ cases := []struct {
+ entries []*pb.MeshSilence
+ }{
+ {
+ entries: []*pb.MeshSilence{
+ {
+ Silence: &pb.Silence{
+ Id: "3be80475-e219-4ee7-b6fc-4b65114e362f",
+ Matchers: []*pb.Matcher{
+ {Name: "label1", Pattern: "val1", Type: pb.Matcher_EQUAL},
+ {Name: "label2", Pattern: "val.+", Type: pb.Matcher_REGEXP},
+ },
+ StartsAt: now,
+ EndsAt: now,
+ UpdatedAt: now,
+ },
+ ExpiresAt: now,
+ },
+ {
+ Silence: &pb.Silence{
+ Id: "4b1e760d-182c-4980-b873-c1a6827c9817",
+ Matchers: []*pb.Matcher{
+ {Name: "label1", Pattern: "val1", Type: pb.Matcher_EQUAL},
+ },
+ StartsAt: now.Add(time.Hour),
+ EndsAt: now.Add(2 * time.Hour),
+ UpdatedAt: now,
+ },
+ ExpiresAt: now.Add(24 * time.Hour),
+ },
+ },
+ },
+ }
+
+ for _, c := range cases {
+ // Create gossip data from input.
+ in := state{}
+ for _, e := range c.entries {
+ in[e.Silence.Id] = e
+ }
+ msg, err := in.MarshalBinary()
+ require.NoError(t, err)
+
+ out, err := decodeState(bytes.NewReader(msg))
+ require.NoError(t, err, "decoding message failed")
+
+ require.Equal(t, in, out, "decoded data doesn't match encoded data")
+ }
+}
+
+func TestStateDecodingError(t *testing.T) {
+ // Check whether decoding copes with erroneous data.
+ s := state{"": &pb.MeshSilence{}}
+
+ msg, err := s.MarshalBinary()
+ require.NoError(t, err)
+
+ _, err = decodeState(bytes.NewReader(msg))
+ require.Equal(t, ErrInvalidState, err)
+}
--- /dev/null
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: silence.proto
+
+/*
+ Package silencepb is a generated protocol buffer package.
+
+ It is generated from these files:
+ silence.proto
+
+ It has these top-level messages:
+ Matcher
+ Comment
+ Silence
+ MeshSilence
+*/
+package silencepb
+
+import proto "github.com/gogo/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+import _ "github.com/gogo/protobuf/gogoproto"
+
+import time "time"
+
+import types "github.com/gogo/protobuf/types"
+
+import io "io"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+var _ = time.Kitchen
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
+
+// Type specifies how the given name and pattern are matched
+// against a label set.
+type Matcher_Type int32
+
+const (
+ Matcher_EQUAL Matcher_Type = 0
+ Matcher_REGEXP Matcher_Type = 1
+)
+
+var Matcher_Type_name = map[int32]string{
+ 0: "EQUAL",
+ 1: "REGEXP",
+}
+var Matcher_Type_value = map[string]int32{
+ "EQUAL": 0,
+ "REGEXP": 1,
+}
+
+func (x Matcher_Type) String() string {
+ return proto.EnumName(Matcher_Type_name, int32(x))
+}
+func (Matcher_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptorSilence, []int{0, 0} }
+
+// Matcher specifies a rule, which can match or set of labels or not.
+type Matcher struct {
+ Type Matcher_Type `protobuf:"varint,1,opt,name=type,proto3,enum=silencepb.Matcher_Type" json:"type,omitempty"`
+ // The label name in a label set to against which the matcher
+ // checks the pattern.
+ Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+ // The pattern being checked according to the matcher's type.
+ Pattern string `protobuf:"bytes,3,opt,name=pattern,proto3" json:"pattern,omitempty"`
+}
+
+func (m *Matcher) Reset() { *m = Matcher{} }
+func (m *Matcher) String() string { return proto.CompactTextString(m) }
+func (*Matcher) ProtoMessage() {}
+func (*Matcher) Descriptor() ([]byte, []int) { return fileDescriptorSilence, []int{0} }
+
+// DEPRECATED: A comment can be attached to a silence.
+type Comment struct {
+ Author string `protobuf:"bytes,1,opt,name=author,proto3" json:"author,omitempty"`
+ Comment string `protobuf:"bytes,2,opt,name=comment,proto3" json:"comment,omitempty"`
+ Timestamp time.Time `protobuf:"bytes,3,opt,name=timestamp,stdtime" json:"timestamp"`
+}
+
+func (m *Comment) Reset() { *m = Comment{} }
+func (m *Comment) String() string { return proto.CompactTextString(m) }
+func (*Comment) ProtoMessage() {}
+func (*Comment) Descriptor() ([]byte, []int) { return fileDescriptorSilence, []int{1} }
+
+// Silence specifies an object that ignores alerts based
+// on a set of matchers during a given time frame.
+type Silence struct {
+ // A globally unique identifier.
+ Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+ // A set of matchers all of which have to be true for a silence
+ // to affect a given label set.
+ Matchers []*Matcher `protobuf:"bytes,2,rep,name=matchers" json:"matchers,omitempty"`
+ // The time range during which the silence is active.
+ StartsAt time.Time `protobuf:"bytes,3,opt,name=starts_at,json=startsAt,stdtime" json:"starts_at"`
+ EndsAt time.Time `protobuf:"bytes,4,opt,name=ends_at,json=endsAt,stdtime" json:"ends_at"`
+ // The last motification made to the silence.
+ UpdatedAt time.Time `protobuf:"bytes,5,opt,name=updated_at,json=updatedAt,stdtime" json:"updated_at"`
+ // DEPRECATED: A set of comments made on the silence.
+ Comments []*Comment `protobuf:"bytes,7,rep,name=comments" json:"comments,omitempty"`
+ // Comment for the silence.
+ CreatedBy string `protobuf:"bytes,8,opt,name=created_by,json=createdBy,proto3" json:"created_by,omitempty"`
+ Comment string `protobuf:"bytes,9,opt,name=comment,proto3" json:"comment,omitempty"`
+}
+
+func (m *Silence) Reset() { *m = Silence{} }
+func (m *Silence) String() string { return proto.CompactTextString(m) }
+func (*Silence) ProtoMessage() {}
+func (*Silence) Descriptor() ([]byte, []int) { return fileDescriptorSilence, []int{2} }
+
+// MeshSilence wraps a regular silence with an expiration timestamp
+// after which the silence may be garbage collected.
+type MeshSilence struct {
+ Silence *Silence `protobuf:"bytes,1,opt,name=silence" json:"silence,omitempty"`
+ ExpiresAt time.Time `protobuf:"bytes,2,opt,name=expires_at,json=expiresAt,stdtime" json:"expires_at"`
+}
+
+func (m *MeshSilence) Reset() { *m = MeshSilence{} }
+func (m *MeshSilence) String() string { return proto.CompactTextString(m) }
+func (*MeshSilence) ProtoMessage() {}
+func (*MeshSilence) Descriptor() ([]byte, []int) { return fileDescriptorSilence, []int{3} }
+
+func init() {
+ proto.RegisterType((*Matcher)(nil), "silencepb.Matcher")
+ proto.RegisterType((*Comment)(nil), "silencepb.Comment")
+ proto.RegisterType((*Silence)(nil), "silencepb.Silence")
+ proto.RegisterType((*MeshSilence)(nil), "silencepb.MeshSilence")
+ proto.RegisterEnum("silencepb.Matcher_Type", Matcher_Type_name, Matcher_Type_value)
+}
+func (m *Matcher) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Matcher) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Type != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintSilence(dAtA, i, uint64(m.Type))
+ }
+ if len(m.Name) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintSilence(dAtA, i, uint64(len(m.Name)))
+ i += copy(dAtA[i:], m.Name)
+ }
+ if len(m.Pattern) > 0 {
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintSilence(dAtA, i, uint64(len(m.Pattern)))
+ i += copy(dAtA[i:], m.Pattern)
+ }
+ return i, nil
+}
+
+func (m *Comment) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Comment) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Author) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintSilence(dAtA, i, uint64(len(m.Author)))
+ i += copy(dAtA[i:], m.Author)
+ }
+ if len(m.Comment) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintSilence(dAtA, i, uint64(len(m.Comment)))
+ i += copy(dAtA[i:], m.Comment)
+ }
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintSilence(dAtA, i, uint64(types.SizeOfStdTime(m.Timestamp)))
+ n1, err := types.StdTimeMarshalTo(m.Timestamp, dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n1
+ return i, nil
+}
+
+func (m *Silence) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Silence) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Id) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintSilence(dAtA, i, uint64(len(m.Id)))
+ i += copy(dAtA[i:], m.Id)
+ }
+ if len(m.Matchers) > 0 {
+ for _, msg := range m.Matchers {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintSilence(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintSilence(dAtA, i, uint64(types.SizeOfStdTime(m.StartsAt)))
+ n2, err := types.StdTimeMarshalTo(m.StartsAt, dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n2
+ dAtA[i] = 0x22
+ i++
+ i = encodeVarintSilence(dAtA, i, uint64(types.SizeOfStdTime(m.EndsAt)))
+ n3, err := types.StdTimeMarshalTo(m.EndsAt, dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n3
+ dAtA[i] = 0x2a
+ i++
+ i = encodeVarintSilence(dAtA, i, uint64(types.SizeOfStdTime(m.UpdatedAt)))
+ n4, err := types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n4
+ if len(m.Comments) > 0 {
+ for _, msg := range m.Comments {
+ dAtA[i] = 0x3a
+ i++
+ i = encodeVarintSilence(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ if len(m.CreatedBy) > 0 {
+ dAtA[i] = 0x42
+ i++
+ i = encodeVarintSilence(dAtA, i, uint64(len(m.CreatedBy)))
+ i += copy(dAtA[i:], m.CreatedBy)
+ }
+ if len(m.Comment) > 0 {
+ dAtA[i] = 0x4a
+ i++
+ i = encodeVarintSilence(dAtA, i, uint64(len(m.Comment)))
+ i += copy(dAtA[i:], m.Comment)
+ }
+ return i, nil
+}
+
+func (m *MeshSilence) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *MeshSilence) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Silence != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintSilence(dAtA, i, uint64(m.Silence.Size()))
+ n5, err := m.Silence.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n5
+ }
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintSilence(dAtA, i, uint64(types.SizeOfStdTime(m.ExpiresAt)))
+ n6, err := types.StdTimeMarshalTo(m.ExpiresAt, dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n6
+ return i, nil
+}
+
+func encodeVarintSilence(dAtA []byte, offset int, v uint64) int {
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return offset + 1
+}
+func (m *Matcher) Size() (n int) {
+ var l int
+ _ = l
+ if m.Type != 0 {
+ n += 1 + sovSilence(uint64(m.Type))
+ }
+ l = len(m.Name)
+ if l > 0 {
+ n += 1 + l + sovSilence(uint64(l))
+ }
+ l = len(m.Pattern)
+ if l > 0 {
+ n += 1 + l + sovSilence(uint64(l))
+ }
+ return n
+}
+
+func (m *Comment) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Author)
+ if l > 0 {
+ n += 1 + l + sovSilence(uint64(l))
+ }
+ l = len(m.Comment)
+ if l > 0 {
+ n += 1 + l + sovSilence(uint64(l))
+ }
+ l = types.SizeOfStdTime(m.Timestamp)
+ n += 1 + l + sovSilence(uint64(l))
+ return n
+}
+
+func (m *Silence) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Id)
+ if l > 0 {
+ n += 1 + l + sovSilence(uint64(l))
+ }
+ if len(m.Matchers) > 0 {
+ for _, e := range m.Matchers {
+ l = e.Size()
+ n += 1 + l + sovSilence(uint64(l))
+ }
+ }
+ l = types.SizeOfStdTime(m.StartsAt)
+ n += 1 + l + sovSilence(uint64(l))
+ l = types.SizeOfStdTime(m.EndsAt)
+ n += 1 + l + sovSilence(uint64(l))
+ l = types.SizeOfStdTime(m.UpdatedAt)
+ n += 1 + l + sovSilence(uint64(l))
+ if len(m.Comments) > 0 {
+ for _, e := range m.Comments {
+ l = e.Size()
+ n += 1 + l + sovSilence(uint64(l))
+ }
+ }
+ l = len(m.CreatedBy)
+ if l > 0 {
+ n += 1 + l + sovSilence(uint64(l))
+ }
+ l = len(m.Comment)
+ if l > 0 {
+ n += 1 + l + sovSilence(uint64(l))
+ }
+ return n
+}
+
+func (m *MeshSilence) Size() (n int) {
+ var l int
+ _ = l
+ if m.Silence != nil {
+ l = m.Silence.Size()
+ n += 1 + l + sovSilence(uint64(l))
+ }
+ l = types.SizeOfStdTime(m.ExpiresAt)
+ n += 1 + l + sovSilence(uint64(l))
+ return n
+}
+
+func sovSilence(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+func sozSilence(x uint64) (n int) {
+ return sovSilence(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Matcher) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Matcher: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Matcher: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
+ }
+ m.Type = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Type |= (Matcher_Type(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthSilence
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Name = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Pattern", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthSilence
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Pattern = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipSilence(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthSilence
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *Comment) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Comment: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Comment: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Author", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthSilence
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Author = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Comment", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthSilence
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Comment = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthSilence
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipSilence(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthSilence
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *Silence) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Silence: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Silence: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthSilence
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Id = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Matchers", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthSilence
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Matchers = append(m.Matchers, &Matcher{})
+ if err := m.Matchers[len(m.Matchers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field StartsAt", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthSilence
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := types.StdTimeUnmarshal(&m.StartsAt, dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field EndsAt", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthSilence
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := types.StdTimeUnmarshal(&m.EndsAt, dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 5:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field UpdatedAt", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthSilence
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 7:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Comments", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthSilence
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Comments = append(m.Comments, &Comment{})
+ if err := m.Comments[len(m.Comments)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 8:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field CreatedBy", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthSilence
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.CreatedBy = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 9:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Comment", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthSilence
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Comment = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipSilence(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthSilence
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MeshSilence) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: MeshSilence: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MeshSilence: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Silence", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthSilence
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Silence == nil {
+ m.Silence = &Silence{}
+ }
+ if err := m.Silence.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ExpiresAt", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthSilence
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := types.StdTimeUnmarshal(&m.ExpiresAt, dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipSilence(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthSilence
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipSilence(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ return iNdEx, nil
+ case 1:
+ iNdEx += 8
+ return iNdEx, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ iNdEx += length
+ if length < 0 {
+ return 0, ErrInvalidLengthSilence
+ }
+ return iNdEx, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = iNdEx
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowSilence
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := skipSilence(dAtA[start:])
+ if err != nil {
+ return 0, err
+ }
+ iNdEx = start + next
+ }
+ return iNdEx, nil
+ case 4:
+ return iNdEx, nil
+ case 5:
+ iNdEx += 4
+ return iNdEx, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
+
+var (
+ ErrInvalidLengthSilence = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowSilence = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("silence.proto", fileDescriptorSilence) }
+
+var fileDescriptorSilence = []byte{
+ // 444 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x51, 0x4d, 0x6b, 0xdb, 0x40,
+ 0x10, 0xf5, 0x2a, 0x8e, 0x65, 0x8d, 0x69, 0x30, 0x43, 0x69, 0x85, 0x21, 0xb6, 0xd1, 0xc9, 0xd0,
+ 0x22, 0x83, 0x7b, 0xee, 0x41, 0x0e, 0xa6, 0x97, 0x06, 0x5a, 0x35, 0x85, 0xde, 0xca, 0xda, 0x9a,
+ 0xda, 0x82, 0x48, 0xbb, 0x48, 0x63, 0xa8, 0x4f, 0x2d, 0xf4, 0x0f, 0xf4, 0x67, 0xf9, 0xd8, 0x5f,
+ 0xd0, 0x0f, 0xff, 0x8b, 0xde, 0x8a, 0x56, 0x2b, 0x37, 0x21, 0x27, 0xdf, 0x66, 0x66, 0xdf, 0x9b,
+ 0xb7, 0xef, 0x0d, 0x3c, 0x2a, 0xd3, 0x5b, 0xca, 0x57, 0x14, 0xea, 0x42, 0xb1, 0x42, 0xcf, 0xb6,
+ 0x7a, 0x39, 0x18, 0xad, 0x95, 0x5a, 0xdf, 0xd2, 0xd4, 0x3c, 0x2c, 0xb7, 0x9f, 0xa6, 0x9c, 0x66,
+ 0x54, 0xb2, 0xcc, 0x74, 0x8d, 0x1d, 0x3c, 0x5e, 0xab, 0xb5, 0x32, 0xe5, 0xb4, 0xaa, 0xea, 0x69,
+ 0xf0, 0x4d, 0x80, 0x7b, 0x2d, 0x79, 0xb5, 0xa1, 0x02, 0x9f, 0x41, 0x9b, 0x77, 0x9a, 0x7c, 0x31,
+ 0x16, 0x93, 0x8b, 0xd9, 0xd3, 0xf0, 0xb8, 0x3c, 0xb4, 0x88, 0xf0, 0x66, 0xa7, 0x29, 0x36, 0x20,
+ 0x44, 0x68, 0xe7, 0x32, 0x23, 0xdf, 0x19, 0x8b, 0x89, 0x17, 0x9b, 0x1a, 0x7d, 0x70, 0xb5, 0x64,
+ 0xa6, 0x22, 0xf7, 0xcf, 0xcc, 0xb8, 0x69, 0x83, 0x4b, 0x68, 0x57, 0x5c, 0xf4, 0xe0, 0x7c, 0xf1,
+ 0xf6, 0x7d, 0xf4, 0xba, 0xdf, 0x42, 0x80, 0x4e, 0xbc, 0x78, 0xb5, 0xf8, 0xf0, 0xa6, 0x2f, 0x82,
+ 0x2f, 0xe0, 0x5e, 0xa9, 0x2c, 0xa3, 0x9c, 0xf1, 0x09, 0x74, 0xe4, 0x96, 0x37, 0xaa, 0x30, 0xdf,
+ 0xf0, 0x62, 0xdb, 0x55, 0xbb, 0x57, 0x35, 0xc4, 0x4a, 0x36, 0x2d, 0xce, 0xc1, 0x3b, 0x7a, 0x35,
+ 0xba, 0xbd, 0xd9, 0x20, 0xac, 0xd3, 0x08, 0x9b, 0x34, 0xc2, 0x9b, 0x06, 0x31, 0xef, 0xee, 0x7f,
+ 0x8e, 0x5a, 0xdf, 0x7f, 0x8d, 0x44, 0xfc, 0x9f, 0x16, 0xfc, 0x75, 0xc0, 0x7d, 0x57, 0xdb, 0xc5,
+ 0x0b, 0x70, 0xd2, 0xc4, 0xaa, 0x3b, 0x69, 0x82, 0x21, 0x74, 0xb3, 0xda, 0x7f, 0xe9, 0x3b, 0xe3,
+ 0xb3, 0x49, 0x6f, 0x86, 0x0f, 0xa3, 0x89, 0x8f, 0x18, 0x8c, 0xc0, 0x2b, 0x59, 0x16, 0x5c, 0x7e,
+ 0x94, 0x7c, 0xd2, 0x7f, 0xba, 0x35, 0x2d, 0x62, 0x7c, 0x09, 0x2e, 0xe5, 0x89, 0x59, 0xd0, 0x3e,
+ 0x61, 0x41, 0xa7, 0x22, 0x45, 0x8c, 0x57, 0x00, 0x5b, 0x9d, 0x48, 0xa6, 0xa4, 0xda, 0x70, 0x7e,
+ 0x4a, 0x24, 0x96, 0x17, 0x71, 0x65, 0xdb, 0x26, 0x5c, 0xfa, 0xee, 0x03, 0xdb, 0xf6, 0x5c, 0xf1,
+ 0x11, 0x83, 0x97, 0x00, 0xab, 0x82, 0x8c, 0xe8, 0x72, 0xe7, 0x77, 0x4d, 0x7c, 0x9e, 0x9d, 0xcc,
+ 0x77, 0x77, 0xef, 0xe7, 0xdd, 0xbb, 0x5f, 0xf0, 0x55, 0x40, 0xef, 0x9a, 0xca, 0x4d, 0x93, 0xff,
+ 0x73, 0x70, 0xad, 0x8e, 0x39, 0xc2, 0x7d, 0x5d, 0x0b, 0x8a, 0x1b, 0x48, 0xe5, 0x95, 0x3e, 0xeb,
+ 0xb4, 0x20, 0x93, 0x96, 0x73, 0x8a, 0x57, 0xcb, 0x8b, 0x78, 0xde, 0xdf, 0xff, 0x19, 0xb6, 0xf6,
+ 0x87, 0xa1, 0xf8, 0x71, 0x18, 0x8a, 0xdf, 0x87, 0xa1, 0x58, 0x76, 0x0c, 0xf5, 0xc5, 0xbf, 0x00,
+ 0x00, 0x00, 0xff, 0xff, 0xde, 0x36, 0xea, 0xdd, 0x71, 0x03, 0x00, 0x00,
+}
--- /dev/null
+syntax = "proto3";
+
+package silencepb;
+
+import "google/protobuf/timestamp.proto";
+import "gogoproto/gogo.proto";
+
+option (gogoproto.marshaler_all) = true;
+option (gogoproto.sizer_all) = true;
+option (gogoproto.unmarshaler_all) = true;
+option (gogoproto.goproto_getters_all) = false;
+
+// Matcher specifies a rule, which can match or set of labels or not.
+message Matcher {
+ // Type specifies how the given name and pattern are matched
+ // against a label set.
+ enum Type {
+ EQUAL = 0;
+ REGEXP = 1;
+ };
+ Type type = 1;
+
+ // The label name in a label set to against which the matcher
+ // checks the pattern.
+ string name = 2;
+ // The pattern being checked according to the matcher's type.
+ string pattern = 3;
+}
+
+// DEPRECATED: A comment can be attached to a silence.
+message Comment {
+ string author = 1;
+ string comment = 2;
+ google.protobuf.Timestamp timestamp = 3 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
+}
+
+// Silence specifies an object that ignores alerts based
+// on a set of matchers during a given time frame.
+message Silence {
+ // A globally unique identifier.
+ string id = 1;
+
+ // A set of matchers all of which have to be true for a silence
+ // to affect a given label set.
+ repeated Matcher matchers = 2;
+
+ // The time range during which the silence is active.
+ google.protobuf.Timestamp starts_at = 3 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
+ google.protobuf.Timestamp ends_at = 4 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
+
+ // The last motification made to the silence.
+ google.protobuf.Timestamp updated_at = 5 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
+
+ // DEPRECATED: A set of comments made on the silence.
+ repeated Comment comments = 7;
+ // Comment for the silence.
+ string created_by = 8;
+ string comment = 9;
+}
+
+// MeshSilence wraps a regular silence with an expiration timestamp
+// after which the silence may be garbage collected.
+message MeshSilence {
+ Silence silence = 1;
+ google.protobuf.Timestamp expires_at = 2 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
+}
\ No newline at end of file
--- /dev/null
+{{ define "__alertmanager" }}AlertManager{{ end }}
+{{ define "__alertmanagerURL" }}{{ .ExternalURL }}/#/alerts?receiver={{ .Receiver }}{{ end }}
+
+{{ define "__subject" }}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .GroupLabels.SortedPairs.Values | join " " }} {{ if gt (len .CommonLabels) (len .GroupLabels) }}({{ with .CommonLabels.Remove .GroupLabels.Names }}{{ .Values | join " " }}{{ end }}){{ end }}{{ end }}
+{{ define "__description" }}{{ end }}
+
+{{ define "__text_alert_list" }}{{ range . }}Labels:
+{{ range .Labels.SortedPairs }} - {{ .Name }} = {{ .Value }}
+{{ end }}Annotations:
+{{ range .Annotations.SortedPairs }} - {{ .Name }} = {{ .Value }}
+{{ end }}Source: {{ .GeneratorURL }}
+{{ end }}{{ end }}
+
+
+{{ define "slack.default.title" }}{{ template "__subject" . }}{{ end }}
+{{ define "slack.default.username" }}{{ template "__alertmanager" . }}{{ end }}
+{{ define "slack.default.fallback" }}{{ template "slack.default.title" . }} | {{ template "slack.default.titlelink" . }}{{ end }}
+{{ define "slack.default.pretext" }}{{ end }}
+{{ define "slack.default.titlelink" }}{{ template "__alertmanagerURL" . }}{{ end }}
+{{ define "slack.default.iconemoji" }}{{ end }}
+{{ define "slack.default.iconurl" }}{{ end }}
+{{ define "slack.default.text" }}{{ end }}
+{{ define "slack.default.footer" }}{{ end }}
+
+
+{{ define "hipchat.default.from" }}{{ template "__alertmanager" . }}{{ end }}
+{{ define "hipchat.default.message" }}{{ template "__subject" . }}{{ end }}
+
+
+{{ define "pagerduty.default.description" }}{{ template "__subject" . }}{{ end }}
+{{ define "pagerduty.default.client" }}{{ template "__alertmanager" . }}{{ end }}
+{{ define "pagerduty.default.clientURL" }}{{ template "__alertmanagerURL" . }}{{ end }}
+{{ define "pagerduty.default.instances" }}{{ template "__text_alert_list" . }}{{ end }}
+
+
+{{ define "opsgenie.default.message" }}{{ template "__subject" . }}{{ end }}
+{{ define "opsgenie.default.description" }}{{ .CommonAnnotations.SortedPairs.Values | join " " }}
+{{ if gt (len .Alerts.Firing) 0 -}}
+Alerts Firing:
+{{ template "__text_alert_list" .Alerts.Firing }}
+{{- end }}
+{{ if gt (len .Alerts.Resolved) 0 -}}
+Alerts Resolved:
+{{ template "__text_alert_list" .Alerts.Resolved }}
+{{- end }}
+{{- end }}
+{{ define "opsgenie.default.source" }}{{ template "__alertmanagerURL" . }}{{ end }}
+
+
+{{ define "wechat.default.message" }}{{ template "__subject" . }}
+{{ .CommonAnnotations.SortedPairs.Values | join " " }}
+{{ if gt (len .Alerts.Firing) 0 -}}
+Alerts Firing:
+{{ template "__text_alert_list" .Alerts.Firing }}
+{{- end }}
+{{ if gt (len .Alerts.Resolved) 0 -}}
+Alerts Resolved:
+{{ template "__text_alert_list" .Alerts.Resolved }}
+{{- end }}
+AlertmanagerUrl:
+{{ template "__alertmanagerURL" . }}
+{{- end }}
+
+
+
+{{ define "victorops.default.state_message" }}{{ .CommonAnnotations.SortedPairs.Values | join " " }}
+{{ if gt (len .Alerts.Firing) 0 -}}
+Alerts Firing:
+{{ template "__text_alert_list" .Alerts.Firing }}
+{{- end }}
+{{ if gt (len .Alerts.Resolved) 0 -}}
+Alerts Resolved:
+{{ template "__text_alert_list" .Alerts.Resolved }}
+{{- end }}
+{{- end }}
+{{ define "victorops.default.entity_display_name" }}{{ template "__subject" . }}{{ end }}
+{{ define "victorops.default.monitoring_tool" }}{{ template "__alertmanager" . }}{{ end }}
+
+{{ define "email.default.subject" }}{{ template "__subject" . }}{{ end }}
+{{ define "email.default.html" }}
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--
+Style and HTML derived from https://github.com/mailgun/transactional-email-templates
+
+
+The MIT License (MIT)
+
+Copyright (c) 2014 Mailgun
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
+<head style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
+<meta name="viewport" content="width=device-width" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />
+<title style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">{{ template "__subject" . }}</title>
+
+</head>
+
+<body itemscope="" itemtype="http://schema.org/EmailMessage" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; height: 100%; line-height: 1.6em; width: 100% !important; background-color: #f6f6f6; margin: 0; padding: 0;" bgcolor="#f6f6f6">
+
+<table style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; background-color: #f6f6f6; margin: 0;" bgcolor="#f6f6f6">
+ <tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
+ <td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;" valign="top"></td>
+ <td width="600" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; display: block !important; max-width: 600px !important; clear: both !important; width: 100% !important; margin: 0 auto; padding: 0;" valign="top">
+ <div style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; max-width: 600px; display: block; margin: 0 auto; padding: 0;">
+ <table width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; border-radius: 3px; background-color: #fff; margin: 0; border: 1px solid #e9e9e9;" bgcolor="#fff">
+ <tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
+ <td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; vertical-align: top; color: #fff; font-weight: 500; text-align: center; border-radius: 3px 3px 0 0; background-color: #E6522C; margin: 0; padding: 20px;" align="center" bgcolor="#E6522C" valign="top">
+ {{ .Alerts | len }} alert{{ if gt (len .Alerts) 1 }}s{{ end }} for {{ range .GroupLabels.SortedPairs }}
+ {{ .Name }}={{ .Value }}
+ {{ end }}
+ </td>
+ </tr>
+ <tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
+ <td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 10px;" valign="top">
+ <table width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
+ <tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
+ <td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
+ <a href="{{ template "__alertmanagerURL" . }}" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; color: #FFF; text-decoration: none; line-height: 2em; font-weight: bold; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; text-transform: capitalize; background-color: #348eda; margin: 0; border-color: #348eda; border-style: solid; border-width: 10px 20px;">View in {{ template "__alertmanager" . }}</a>
+ </td>
+ </tr>
+ {{ if gt (len .Alerts.Firing) 0 }}
+ <tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
+ <td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
+ <strong style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">[{{ .Alerts.Firing | len }}] Firing</strong>
+ </td>
+ </tr>
+ {{ end }}
+ {{ range .Alerts.Firing }}
+ <tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
+ <td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
+ <strong style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">Labels</strong><br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />
+ {{ range .Labels.SortedPairs }}{{ .Name }} = {{ .Value }}<br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />{{ end }}
+ {{ if gt (len .Annotations) 0 }}<strong style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">Annotations</strong><br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />{{ end }}
+ {{ range .Annotations.SortedPairs }}{{ .Name }} = {{ .Value }}<br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />{{ end }}
+ <a href="{{ .GeneratorURL }}" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; color: #348eda; text-decoration: underline; margin: 0;">Source</a><br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />
+ </td>
+ </tr>
+ {{ end }}
+
+ {{ if gt (len .Alerts.Resolved) 0 }}
+ {{ if gt (len .Alerts.Firing) 0 }}
+ <tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
+ <td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
+ <br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />
+ <hr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />
+ <br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />
+ </td>
+ </tr>
+ {{ end }}
+ <tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
+ <td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
+ <strong style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">[{{ .Alerts.Resolved | len }}] Resolved</strong>
+ </td>
+ </tr>
+ {{ end }}
+ {{ range .Alerts.Resolved }}
+ <tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
+ <td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
+ <strong style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">Labels</strong><br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />
+ {{ range .Labels.SortedPairs }}{{ .Name }} = {{ .Value }}<br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />{{ end }}
+ {{ if gt (len .Annotations) 0 }}<strong style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">Annotations</strong><br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />{{ end }}
+ {{ range .Annotations.SortedPairs }}{{ .Name }} = {{ .Value }}<br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />{{ end }}
+ <a href="{{ .GeneratorURL }}" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; color: #348eda; text-decoration: underline; margin: 0;">Source</a><br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />
+ </td>
+ </tr>
+ {{ end }}
+ </table>
+ </td>
+ </tr>
+ </table>
+
+ <div style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;">
+ <table width="100%" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
+ <tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
+ <td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; text-align: center; color: #999; margin: 0; padding: 0 0 20px;" align="center" valign="top"><a href="{{ .ExternalURL }}" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: underline; margin: 0;">Sent by {{ template "__alertmanager" . }}</a></td>
+ </tr>
+ </table>
+ </div></div>
+ </td>
+ <td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;" valign="top"></td>
+ </tr>
+</table>
+
+</body>
+</html>
+
+{{ end }}
+
+{{ define "pushover.default.title" }}{{ template "__subject" . }}{{ end }}
+{{ define "pushover.default.message" }}{{ .CommonAnnotations.SortedPairs.Values | join " " }}
+{{ if gt (len .Alerts.Firing) 0 }}
+Alerts Firing:
+{{ template "__text_alert_list" .Alerts.Firing }}
+{{ end }}
+{{ if gt (len .Alerts.Resolved) 0 }}
+Alerts Resolved:
+{{ template "__text_alert_list" .Alerts.Resolved }}
+{{ end }}
+{{ end }}
+{{ define "pushover.default.url" }}{{ template "__alertmanagerURL" . }}{{ end }}
--- /dev/null
+<!--
+Style and HTML derived from https://github.com/mailgun/transactional-email-templates
+
+
+The MIT License (MIT)
+
+Copyright (c) 2014 Mailgun
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta name="viewport" content="width=device-width" />
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>{{ template "__subject" . }}</title>
+<style>
+/* -------------------------------------
+ GLOBAL
+ A very basic CSS reset
+------------------------------------- */
+* {
+ margin: 0;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ box-sizing: border-box;
+ font-size: 14px;
+}
+
+img {
+ max-width: 100%;
+}
+
+body {
+ -webkit-font-smoothing: antialiased;
+ -webkit-text-size-adjust: none;
+ width: 100% !important;
+ height: 100%;
+ line-height: 1.6em;
+ /* 1.6em * 14px = 22.4px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
+ /*line-height: 22px;*/
+}
+
+/* Let's make sure all tables have defaults */
+table td {
+ vertical-align: top;
+}
+
+/* -------------------------------------
+ BODY & CONTAINER
+------------------------------------- */
+body {
+ background-color: #f6f6f6;
+}
+
+.body-wrap {
+ background-color: #f6f6f6;
+ width: 100%;
+}
+
+.container {
+ display: block !important;
+ max-width: 600px !important;
+ margin: 0 auto !important;
+ /* makes it centered */
+ clear: both !important;
+}
+
+.content {
+ max-width: 600px;
+ margin: 0 auto;
+ display: block;
+ padding: 20px;
+}
+
+/* -------------------------------------
+ HEADER, FOOTER, MAIN
+------------------------------------- */
+.main {
+ background-color: #fff;
+ border: 1px solid #e9e9e9;
+ border-radius: 3px;
+}
+
+.content-wrap {
+ padding: 30px;
+}
+
+.content-block {
+ padding: 0 0 20px;
+}
+
+.header {
+ width: 100%;
+ margin-bottom: 20px;
+}
+
+.footer {
+ width: 100%;
+ clear: both;
+ color: #999;
+ padding: 20px;
+}
+.footer p, .footer a, .footer td {
+ color: #999;
+ font-size: 12px;
+}
+
+/* -------------------------------------
+ TYPOGRAPHY
+------------------------------------- */
+h1, h2, h3 {
+ font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
+ color: #000;
+ margin: 40px 0 0;
+ line-height: 1.2em;
+ font-weight: 400;
+}
+
+h1 {
+ font-size: 32px;
+ font-weight: 500;
+ /* 1.2em * 32px = 38.4px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
+ /*line-height: 38px;*/
+}
+
+h2 {
+ font-size: 24px;
+ /* 1.2em * 24px = 28.8px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
+ /*line-height: 29px;*/
+}
+
+h3 {
+ font-size: 18px;
+ /* 1.2em * 18px = 21.6px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
+ /*line-height: 22px;*/
+}
+
+h4 {
+ font-size: 14px;
+ font-weight: 600;
+}
+
+p, ul, ol {
+ margin-bottom: 10px;
+ font-weight: normal;
+}
+p li, ul li, ol li {
+ margin-left: 5px;
+ list-style-position: inside;
+}
+
+/* -------------------------------------
+ LINKS & BUTTONS
+------------------------------------- */
+a {
+ color: #348eda;
+ text-decoration: underline;
+}
+
+.btn-primary {
+ text-decoration: none;
+ color: #FFF;
+ background-color: #348eda;
+ border: solid #348eda;
+ border-width: 10px 20px;
+ line-height: 2em;
+ /* 2em * 14px = 28px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
+ /*line-height: 28px;*/
+ font-weight: bold;
+ text-align: center;
+ cursor: pointer;
+ display: inline-block;
+ border-radius: 5px;
+ text-transform: capitalize;
+}
+
+/* -------------------------------------
+ OTHER STYLES THAT MIGHT BE USEFUL
+------------------------------------- */
+.last {
+ margin-bottom: 0;
+}
+
+.first {
+ margin-top: 0;
+}
+
+.aligncenter {
+ text-align: center;
+}
+
+.alignright {
+ text-align: right;
+}
+
+.alignleft {
+ text-align: left;
+}
+
+.clear {
+ clear: both;
+}
+
+/* -------------------------------------
+ ALERTS
+ Change the class depending on warning email, good email or bad email
+------------------------------------- */
+.alert {
+ font-size: 16px;
+ color: #fff;
+ font-weight: 500;
+ padding: 20px;
+ text-align: center;
+ border-radius: 3px 3px 0 0;
+}
+.alert a {
+ color: #fff;
+ text-decoration: none;
+ font-weight: 500;
+ font-size: 16px;
+}
+.alert.alert-warning {
+ background-color: ##E6522C;
+}
+.alert.alert-bad {
+ background-color: #D0021B;
+}
+.alert.alert-good {
+ background-color: #68B90F;
+}
+
+/* -------------------------------------
+ INVOICE
+ Styles for the billing table
+------------------------------------- */
+.invoice {
+ margin: 40px auto;
+ text-align: left;
+ width: 80%;
+}
+.invoice td {
+ padding: 5px 0;
+}
+.invoice .invoice-items {
+ width: 100%;
+}
+.invoice .invoice-items td {
+ border-top: #eee 1px solid;
+}
+.invoice .invoice-items .total td {
+ border-top: 2px solid #333;
+ border-bottom: 2px solid #333;
+ font-weight: 700;
+}
+
+/* -------------------------------------
+ RESPONSIVE AND MOBILE FRIENDLY STYLES
+------------------------------------- */
+@media only screen and (max-width: 640px) {
+ body {
+ padding: 0 !important;
+ }
+
+ h1, h2, h3, h4 {
+ font-weight: 800 !important;
+ margin: 20px 0 5px !important;
+ }
+
+ h1 {
+ font-size: 22px !important;
+ }
+
+ h2 {
+ font-size: 18px !important;
+ }
+
+ h3 {
+ font-size: 16px !important;
+ }
+
+ .container {
+ padding: 0 !important;
+ width: 100% !important;
+ }
+
+ .content {
+ padding: 0 !important;
+ }
+
+ .content-wrap {
+ padding: 10px !important;
+ }
+
+ .invoice {
+ width: 100% !important;
+ }
+}
+</style>
+</head>
+
+<body itemscope itemtype="http://schema.org/EmailMessage">
+
+<table class="body-wrap">
+ <tr>
+ <td></td>
+ <td class="container" width="600">
+ <div class="content">
+ <table class="main" width="100%" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="alert alert-warning">
+ {{ .Alerts | len }} alert{{ if gt (len .Alerts) 1 }}s{{ end }} for {{ range .GroupLabels.SortedPairs }}
+ {{ .Name }}={{ .Value }}
+ {{ end }}
+ </td>
+ </tr>
+ <tr>
+ <td class="content-wrap">
+ <table width="100%" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="content-block">
+ <a href='{{ template "__alertmanagerURL" . }}' class="btn-primary">View in {{ template "__alertmanager" . }}</a>
+ </td>
+ </tr>
+ {{ if gt (len .Alerts.Firing) 0 }}
+ <tr>
+ <td class="content-block">
+ <strong>[{{ .Alerts.Firing | len }}] Firing</strong>
+ </td>
+ </tr>
+ {{ end }}
+ {{ range .Alerts.Firing }}
+ <tr>
+ <td class="content-block">
+ <strong>Labels</strong><br />
+ {{ range .Labels.SortedPairs }}{{ .Name }} = {{ .Value }}<br />{{ end }}
+ {{ if gt (len .Annotations) 0 }}<strong>Annotations</strong><br />{{ end }}
+ {{ range .Annotations.SortedPairs }}{{ .Name }} = {{ .Value }}<br />{{ end }}
+ <a href="{{ .GeneratorURL }}">Source</a><br />
+ </td>
+ </tr>
+ {{ end }}
+
+ {{ if gt (len .Alerts.Resolved) 0 }}
+ {{ if gt (len .Alerts.Firing) 0 }}
+ <tr>
+ <td class="content-block">
+ <br />
+ <hr />
+ <br />
+ </td>
+ </tr>
+ {{ end }}
+ <tr>
+ <td class="content-block">
+ <strong>[{{ .Alerts.Resolved | len }}] Resolved</strong>
+ </td>
+ </tr>
+ {{ end }}
+ {{ range .Alerts.Resolved }}
+ <tr>
+ <td class="content-block">
+ <strong>Labels</strong><br />
+ {{ range .Labels.SortedPairs }}{{ .Name }} = {{ .Value }}<br />{{ end }}
+ {{ if gt (len .Annotations) 0 }}<strong>Annotations</strong><br />{{ end }}
+ {{ range .Annotations.SortedPairs }}{{ .Name }} = {{ .Value }}<br />{{ end }}
+ <a href="{{ .GeneratorURL }}">Source</a><br />
+ </td>
+ </tr>
+ {{ end }}
+ </table>
+ </td>
+ </tr>
+ </table>
+
+ <div class="footer">
+ <table width="100%">
+ <tr>
+ <td class="aligncenter content-block"><a href='{{ .ExternalURL }}'>Sent by {{ template "__alertmanager" . }}</a></td>
+ </tr>
+ </table>
+ </div></div>
+ </td>
+ <td></td>
+ </tr>
+</table>
+
+</body>
+</html>
--- /dev/null
+// Code generated by go-bindata.
+// sources:
+// template/default.tmpl
+// DO NOT EDIT!
+
+package deftmpl
+
+import (
+ "bytes"
+ "compress/gzip"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+)
+
+func bindataRead(data []byte, name string) ([]byte, error) {
+ gz, err := gzip.NewReader(bytes.NewBuffer(data))
+ if err != nil {
+ return nil, fmt.Errorf("Read %q: %v", name, err)
+ }
+
+ var buf bytes.Buffer
+ _, err = io.Copy(&buf, gz)
+ clErr := gz.Close()
+
+ if err != nil {
+ return nil, fmt.Errorf("Read %q: %v", name, err)
+ }
+ if clErr != nil {
+ return nil, err
+ }
+
+ return buf.Bytes(), nil
+}
+
+type asset struct {
+ bytes []byte
+ info os.FileInfo
+}
+
+type bindataFileInfo struct {
+ name string
+ size int64
+ mode os.FileMode
+ modTime time.Time
+}
+
+func (fi bindataFileInfo) Name() string {
+ return fi.name
+}
+func (fi bindataFileInfo) Size() int64 {
+ return fi.size
+}
+func (fi bindataFileInfo) Mode() os.FileMode {
+ return fi.mode
+}
+func (fi bindataFileInfo) ModTime() time.Time {
+ return fi.modTime
+}
+func (fi bindataFileInfo) IsDir() bool {
+ return false
+}
+func (fi bindataFileInfo) Sys() interface{} {
+ return nil
+}
+
+var _templateDefaultTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x1b\xff\x4f\xdb\xb8\xfe\xf7\xfc\x15\x9f\xcb\xe9\xe9\x86\xd4\x36\x85\xdd\x4d\x47\x69\x79\xea\x4a\x18\xd1\x2b\x29\x4a\xc3\x76\xd3\xe9\x84\xdc\xc4\x6d\xbd\x25\x76\xce\x76\x28\x3d\xd6\xff\xfd\xc9\x4e\xfa\x25\x34\x85\x82\x76\xd0\xf7\x0e\xd0\x46\xe2\xf8\xf3\xfd\xab\x63\xe7\xf6\x16\x42\x3c\x24\x14\x83\x79\x75\x85\x22\xcc\x65\x8c\x28\x1a\x61\x6e\xc2\x6c\xd6\x56\xf7\xe7\xd9\xfd\xed\x2d\x60\x1a\xc2\x6c\x66\x6c\x04\xb9\xf4\xba\x0a\xea\xf6\x16\x6a\xf6\x8d\xc4\x9c\xa2\xe8\xd2\xeb\xc2\x6c\x66\xfd\x68\xe9\x79\xe2\xdf\x1c\x07\x98\x5c\x63\xde\x52\x93\xbc\xfc\x26\x83\xc9\xb1\x17\xd1\x8b\x74\xf0\x05\x07\x52\xa1\xfd\x5d\x81\xf4\x25\x92\xa9\x80\x6f\x20\xd9\x65\x92\xcc\x41\xc9\x10\xf0\x9f\x8b\x87\xe6\x90\x70\x42\x47\x0a\xa6\xa1\x60\xb4\x14\xa2\x76\xaa\x47\xe1\x1b\x44\x98\xae\x52\xfc\x03\xd4\xa4\x0f\x9c\xa5\x49\x17\x0d\x70\x24\x6a\x7d\xc6\x25\x0e\x2f\x10\xe1\xa2\xf6\x11\x45\x29\x56\x04\xbf\x30\x42\xc1\x04\x85\x15\x32\x92\x23\x09\x6f\x14\xae\x5a\x87\xc5\x31\xa3\x19\xf0\x5e\x3e\xb6\x82\x6f\x0f\x66\xb3\x37\xb7\xb7\x30\x21\x72\x5c\x9c\x5c\xf3\x70\xcc\xae\x71\x91\xba\x8b\x62\x2c\x72\x35\x96\x51\x5f\x30\xbe\xb7\xb8\xda\x60\x9b\x10\x8b\x80\x93\x44\x12\x46\xcd\x7b\x74\x2c\xf1\x8d\xcc\xec\x78\x15\x11\x21\xf3\xa9\x1c\xd1\x11\x86\x1a\xcc\x66\x19\x5f\x0d\x63\x39\xb8\xae\x27\xa5\x95\xaa\x56\xa4\x62\x5f\xdd\xb5\x60\x21\x40\xce\x58\x46\xbc\x4d\x29\x93\x48\xf1\x54\x40\xb9\x32\xfc\x34\xbc\x7d\x96\xf2\x00\x37\x32\x63\x62\x8a\x39\x92\x8c\x67\xee\x67\x94\x28\xaa\xa0\x03\x11\xa1\xe0\x6b\x2d\xc4\x43\x94\x46\xb2\x26\x89\x8c\x70\xae\x05\x89\xe3\x24\x42\xb2\xe8\x8b\xb5\x4d\x2a\x2f\xe2\x49\x85\x0a\x81\xb8\x0c\x55\x31\xd0\xb6\xc4\x37\x44\x51\x34\x40\xc1\xd7\x35\x7c\xa5\xec\x2b\xa4\xf0\x0d\x1e\x9a\x18\x11\xfa\x75\x6b\x0e\x12\x8e\x95\xb3\x98\xdb\xcd\x5e\xc1\x7f\xaf\x02\x74\xda\xd8\x92\x03\x12\x30\x8a\x63\xf6\x85\x6c\xc9\x83\x9a\x9f\xf2\x68\x5b\x8e\xb7\x17\x6e\xc8\x98\xcc\x92\xe4\x06\x9f\x1a\x93\x24\x18\x23\xb9\x04\xe0\x2c\x7e\xba\x27\xdc\xc5\x16\x63\x21\xd0\xe8\x11\x5e\x5a\xe0\x2d\x51\xd4\xc2\x54\x4e\x17\xf8\xd6\x53\xc5\xe3\x3c\x7f\x1d\x63\x10\x11\x4c\xe5\xd3\x25\xde\x84\x71\x59\x64\x9e\xe6\x4f\xeb\x78\x09\x15\x12\xd1\x00\x8b\x12\xbc\x6b\xb9\xf1\x1e\xad\xb2\x44\x8c\x30\x25\xf8\xe9\x46\xba\x0f\xd9\xba\x85\xf2\x52\xb2\x21\x73\x96\xd6\x0e\xe3\x4e\xe5\x2a\x94\xc6\x3d\xa8\x43\x75\x36\x33\xb2\x41\xc8\x06\x75\x8e\xbe\x5f\x23\xc5\xfa\xaa\x89\x54\x57\x24\x2a\xa1\xe7\x61\xc1\xa2\x6b\x1c\xde\xa1\x38\x1f\xde\x9e\xe6\x1c\x62\x8d\x6a\x75\x1b\x95\x0a\x5d\x32\x1e\xef\x4d\x05\xab\x4f\xf0\x53\x02\xd3\x78\xb5\xdf\x3d\xf6\x6b\xaf\xea\x9f\x47\x6b\xf8\x4a\xed\xb3\x8a\xa0\x68\xa2\x6b\x12\x48\xc6\x59\x22\x96\x96\x97\x48\xe2\xab\xa2\xad\x5e\xcd\xf1\xb8\x70\x5a\xd7\x2a\xa6\x92\xc8\xe9\x55\x48\x44\x12\xa1\xe9\xd5\x86\xde\xe7\xe1\xdc\xb7\x8e\x39\x66\x94\x48\xa6\x14\x72\x25\x19\x8b\x1e\x59\x55\x56\x71\xe3\x18\x91\x68\xe9\x07\xcb\xe5\xc5\xa3\xb9\x2c\x62\x1a\xcb\x58\xb3\x65\x34\x7f\x38\xe9\x75\xfc\xcf\x17\x36\xa8\x21\xb8\xb8\x7c\xdf\x75\x3a\x60\x56\x2d\xeb\xd3\xdb\x8e\x65\x9d\xf8\x27\xf0\xdb\x99\x7f\xde\x85\xfd\x5a\x1d\x7c\x8e\xa8\x20\xca\xd9\x50\x64\x59\xb6\x6b\x82\x39\x96\x32\x69\x58\xd6\x64\x32\xa9\x4d\xde\xd6\x18\x1f\x59\xbe\x67\xdd\x28\x5c\xfb\x0a\x38\xbf\xac\xca\x15\xc8\x5a\x28\x43\xf3\xd8\x68\xfe\x50\xad\x1a\x7d\x39\x8d\x30\x20\x1a\x82\x26\x12\x62\x4e\x94\x41\x55\xf7\x01\x0a\xb5\x68\x58\xd6\x88\xc8\x71\x3a\xa8\x05\x2c\xb6\x94\x0c\xa3\x94\x5a\x1a\x1d\x0a\x32\x7c\x55\x2d\x5a\x75\xae\x0e\x61\x18\x86\x3f\xc6\x70\xee\xf8\xd0\x25\x01\xa6\x02\xc3\x9b\x73\xc7\xdf\x33\x8c\x0e\x4b\xa6\x9c\x8c\xc6\x12\xde\x04\x7b\x70\x50\xdf\xff\x19\xce\x33\x8c\x86\x71\x81\x79\x4c\x84\x20\x8c\x02\x11\x30\xc6\x1c\x0f\xa6\x30\xe2\x88\x4a\x1c\x56\x60\xc8\x31\x06\x36\x84\x60\x8c\xf8\x08\x57\x40\x32\x40\x74\x0a\x09\xe6\x82\x51\x60\x03\x89\x08\x55\xfe\x8f\x20\x60\xc9\xd4\x60\x43\x90\x63\x22\x40\xb0\xa1\x9c\x20\x9e\x49\x88\x84\x60\x01\x41\x12\x87\x10\xb2\x20\x8d\x31\xcd\x02\x17\x86\x24\xc2\x02\xde\xc8\x31\x06\xb3\x9f\x43\x98\x7b\x9a\x48\x88\x51\x64\x10\x0a\xea\xd9\xfc\x91\x5e\x99\xb1\x54\x02\xc7\x42\x72\xa2\xb5\x50\x01\x42\x83\x28\x0d\x15\x0f\xf3\xc7\x11\x89\x49\x4e\x41\x81\x6b\xc1\x85\x21\x19\xa4\x02\x57\x34\x9f\x15\x88\x59\x48\x86\xea\x2f\xd6\x62\x25\xe9\x20\x22\x62\x5c\x81\x90\x28\xd4\x83\x54\xe2\x0a\x08\x35\xa8\xf5\x58\x51\x72\x58\x8c\x83\xc0\x51\x64\x04\x2c\x21\x58\x80\x96\x75\xc9\x9d\x9e\xa3\x58\x4f\x94\x42\x65\xae\x22\xa1\x46\x26\x63\x16\x17\x25\x21\xc2\x18\xa6\x9c\x12\x31\xc6\x1a\x26\x64\x20\x98\xa6\xa8\xbc\x59\x8d\xa8\xe9\x43\x16\x45\x6c\xa2\x44\x0b\x18\x0d\x49\xbe\x18\xd3\x46\x46\x03\xb5\x20\x0d\x16\x76\xa5\x4c\x92\x20\x53\xb7\x36\x40\xb2\xb4\x6a\xfe\x48\x8c\x51\x14\xc1\x00\xe7\x0a\xc3\x21\x10\x0a\x68\x45\x1c\xae\xc8\xab\x16\x4b\x12\x14\x41\xc2\xb8\xa6\x77\x57\xcc\x9a\x61\xf8\x67\x36\xf4\x7b\xa7\xfe\xa7\xb6\x67\x83\xd3\x87\x0b\xaf\xf7\xd1\x39\xb1\x4f\xc0\x6c\xf7\xc1\xe9\x9b\x15\xf8\xe4\xf8\x67\xbd\x4b\x1f\x3e\xb5\x3d\xaf\xed\xfa\x9f\xa1\x77\x0a\x6d\xf7\x33\xfc\xc7\x71\x4f\x2a\x60\xff\x76\xe1\xd9\xfd\x3e\xf4\x3c\xc3\x39\xbf\xe8\x3a\xf6\x49\x05\x1c\xb7\xd3\xbd\x3c\x71\xdc\x0f\xf0\xfe\xd2\x07\xb7\xe7\x43\xd7\x39\x77\x7c\xfb\x04\xfc\x1e\x28\x82\x39\x2a\xc7\xee\x2b\x64\xe7\xb6\xd7\x39\x6b\xbb\x7e\xfb\xbd\xd3\x75\xfc\xcf\x15\xe3\xd4\xf1\x5d\x85\xf3\xb4\xe7\x41\x1b\x2e\xda\x9e\xef\x74\x2e\xbb\x6d\x0f\x2e\x2e\xbd\x8b\x5e\xdf\x86\xb6\x7b\x02\x6e\xcf\x75\xdc\x53\xcf\x71\x3f\xd8\xe7\xb6\xeb\xd7\xc0\x71\xc1\xed\x81\xfd\xd1\x76\x7d\xe8\x9f\xb5\xbb\x5d\x45\xca\x68\x5f\xfa\x67\x3d\x4f\xf1\x07\x9d\xde\xc5\x67\xcf\xf9\x70\xe6\xc3\x59\xaf\x7b\x62\x7b\x7d\x78\x6f\x43\xd7\x69\xbf\xef\xda\x19\x29\xf7\x33\x74\xba\x6d\xe7\xbc\x02\x27\xed\xf3\xf6\x07\x5b\x43\xf5\xfc\x33\xdb\x33\xd4\xb4\x8c\x3b\xf8\x74\x66\xab\x21\x45\xaf\xed\x42\xbb\xe3\x3b\x3d\x57\x89\xd1\xe9\xb9\xbe\xd7\xee\xf8\x15\xf0\x7b\x9e\xbf\x00\xfd\xe4\xf4\xed\x0a\xb4\x3d\xa7\xaf\x14\x72\xea\xf5\xce\x2b\x86\x52\x67\xef\x54\x4d\x71\x5c\x05\xe7\xda\x19\x16\xa5\x6a\x28\x58\xa4\xe7\xe9\xfb\xcb\xbe\xbd\x40\x08\x27\x76\xbb\xeb\xb8\x1f\xfa\x0a\x58\x89\x38\x9f\x5c\x33\xaa\xd5\x63\xa3\xa9\x53\xe0\x4d\x1c\x51\xd1\x2a\x49\x6c\xfb\x87\x87\x87\x59\x3e\x33\xb7\x9b\x24\x54\x72\x6b\x99\x43\x46\x65\x75\x88\x62\x12\x4d\x1b\xf0\xd3\x19\x8e\xae\xb1\x24\x01\x02\x17\xa7\xf8\xa7\x0a\x2c\x06\x2a\xd0\xe6\x04\x45\x15\x10\x88\x8a\xaa\xc0\x9c\x0c\x8f\x60\xc0\x6e\xaa\x82\xfc\xa5\x6a\x31\x0c\x18\x0f\x31\xaf\x0e\xd8\xcd\x11\x68\xa4\x82\xfc\x85\x1b\xb0\xff\x73\x72\x73\x04\x31\xe2\x23\x42\x1b\x50\x3f\x52\xb9\x75\x8c\x51\xf8\x92\xf4\x63\x2c\x11\xa8\x8a\xda\x32\xaf\x09\x9e\xa8\x28\x32\x55\xf4\x4a\x4c\x65\xcb\x9c\x90\x50\x8e\x5b\x21\xbe\x26\x01\xae\xea\x9b\x97\x53\x16\x58\x73\x76\x95\x31\xab\xf8\xcf\x94\x5c\xb7\xcc\x4e\xc6\x6a\xd5\x9f\x26\x78\x85\x71\xd5\x8a\x58\xca\xb8\x47\xba\x12\x08\x2c\x5b\x97\xfe\x69\xf5\xd7\x17\x66\x5f\xbf\xba\x78\x39\x73\xdf\xd7\x8b\x34\x2d\xcd\xdc\xb1\x61\x34\x2d\xe5\x94\xea\x62\xc0\xc2\x29\x10\x89\x63\x11\xb0\x04\xb7\x4c\x53\xdf\xc8\xa9\xba\xce\x23\x4a\x04\x63\x1c\x23\x1d\x51\xb6\xaa\xee\xe7\xf3\xde\xf7\x59\x85\xac\x4e\xf0\xe0\x2b\x91\xd5\xec\x41\xcc\x98\x1c\x6b\xa0\xac\x36\x10\x24\x70\xb8\x9c\xa4\x7c\x43\x43\x57\x51\xf8\x25\x15\xb2\x01\x94\x51\x7c\x04\x63\xac\x2a\x53\x03\xf6\xeb\xf5\x7f\x1d\x41\x44\x28\xae\x2e\x86\x6a\xef\x70\x7c\x04\x3a\x02\xb2\x09\xf0\x03\x89\x55\xb0\x20\x2a\x8f\x60\x80\x82\xaf\x23\xce\x52\x1a\x56\x03\x16\x31\xde\x80\x1f\x87\xef\xd4\xef\xaa\xfa\x21\x41\x61\xa8\xb9\x52\xde\x30\x18\xe9\x99\x2d\x33\x9f\x69\x2a\x7d\x4b\x34\x78\x6e\xf7\x58\x11\x69\x4b\x39\x4a\x79\x07\x68\x4a\xfe\x82\x79\x0c\x40\x71\xf0\xcc\x99\xf4\x1a\x73\x85\x24\xaa\xa2\x88\x8c\x68\x03\x24\x4b\x8a\x8a\xba\xd6\x0f\x5a\xa6\x64\x89\x79\xdc\xb4\x64\xb8\x64\x34\xcb\xac\xe6\xbb\x7a\xfd\x99\x43\xa5\x94\xe9\x7c\x69\xd5\x80\x41\xc4\x82\xaf\x05\xdf\x8e\xd1\x4d\x35\x77\x92\x77\xf5\x7a\x72\x53\x78\x18\x44\x18\x71\x45\x50\x8e\x0b\xe3\x9b\x02\x65\xa1\x1c\x40\xa9\x64\x77\x42\xa2\xa0\x2d\xad\x28\x80\x66\x48\xae\x9f\xdb\xad\x8a\xf2\xde\x55\xce\xfd\x42\xcc\xf9\x56\x46\xd6\xc1\x9c\xdb\x59\x69\xc2\x84\x00\x47\x51\x3e\xbb\x65\xd6\xb3\x7b\x91\xa0\x60\x7e\xff\xac\x82\xe6\x0f\x39\x0a\x49\x2a\x1a\xf0\x56\x8f\x95\x24\x80\xe1\xb0\x90\xc5\x32\xb0\x06\xec\x27\x37\x20\x58\x44\x42\xf8\x11\x1f\xaa\xdf\x62\x62\x18\x0e\x57\x74\xb1\x0b\xd9\x61\xc9\xc9\xf3\x65\x89\x77\x1b\x03\xae\xa0\x5d\x0d\x32\xc9\x4b\xcd\x2f\xf5\xfa\x11\xe8\x12\x95\xcf\x0f\x30\x95\x98\x97\xd9\x4b\xff\xab\x6b\xa3\xac\xdb\xcd\x7e\xf7\xcb\xc1\x41\xa7\xbc\x00\x1d\x28\xbf\x36\x21\x8f\xb7\x8c\xc0\xaa\xf5\x32\xd8\xf2\x88\x9c\xff\x2c\x77\x40\x17\x5b\x9f\xa0\x5f\x96\x94\xbe\x4b\xda\x83\x7d\x98\xcd\xc4\xe2\x85\x07\x0c\x19\x87\xe5\x2e\xdd\x86\x5d\x52\x98\xcd\xee\x50\x85\xd5\x3d\xbb\x56\x61\xc7\x6e\x6d\x5a\xfe\x6a\xa5\x60\xfc\x45\x0e\x5e\xdc\xf3\x57\x37\xdd\xa6\x98\x2d\x9d\x67\x3f\x73\x9e\xfb\x7c\x63\xe7\x73\xdf\x46\xb5\xef\x96\x13\xec\xba\x2b\xd4\xa1\x3e\xcf\x25\xf7\xb9\x43\x2e\x06\x82\x31\xc7\xc3\x96\xb9\xcd\x4b\xf7\x67\xf6\x87\x79\xd2\x3c\x3d\x3d\xcd\x93\x6f\x88\x03\xc6\xf5\x3b\xb9\xf9\xf2\xa0\xb0\x20\x38\x50\xcb\x81\x42\xde\x1e\xb0\x28\x2c\x4f\xdc\x41\xca\x85\xc2\x9e\x30\x92\x0d\x2c\x1a\x0a\x42\x35\xd2\xbc\xaf\xb8\x93\xe0\x7f\x51\x8c\x69\x7c\xfa\x25\xea\x90\xf1\xb8\x01\x01\x4a\x88\x44\x11\xf9\x0b\x97\x26\xfd\xb7\x3f\xff\x8a\x43\x54\x52\xaf\xd7\x66\xe4\xc3\x5a\xcb\x8d\xac\x90\x2f\x06\x17\xdd\x5b\x72\x93\x9b\xf7\xf8\x23\xc1\x13\x20\x14\x1e\x7c\x3b\xde\xb4\x50\xa9\x0f\xdf\x49\xbc\xe5\xe9\x37\xfb\x79\x68\xf3\xa3\xa4\x28\xbc\x86\xec\xdf\x13\xb2\x42\x72\x46\x47\x2f\xa7\xda\xdf\x37\x9f\xb3\xfa\x23\xdf\xf9\x6a\x5a\x19\x93\xdf\xc1\xeb\x4a\x1a\x86\xfc\xc9\xfc\x30\xd1\xdd\x2d\xb4\x57\x3f\xfc\x67\xf8\x61\xd6\x9a\x2e\x5c\xad\x39\x78\x39\x33\x83\x55\xae\xa3\x07\x4e\xd1\x6d\x3e\xea\xf6\xc2\xc2\x6c\x8e\x3b\x28\xa9\x05\xcb\x4d\xf4\xac\x12\xbc\xb8\x67\xac\x70\xb4\x2b\xee\xf1\xa0\x46\x1f\x3c\x1a\xf9\x3f\xea\x2c\xab\x1d\xe6\xdd\xb3\x9a\x2f\xd4\x50\xce\xdb\xad\xb5\x9e\x32\xa5\x21\xe6\xaa\xfb\x2b\xba\x53\x76\xda\x54\x35\x51\xbb\x97\x63\x9e\x56\x4d\xb7\x6c\xef\x56\xcf\x9a\x94\x9a\xf7\xb5\x2b\xdc\x99\x6a\xbc\x73\x9e\x09\xd0\x1c\xef\x20\x4f\x3b\xa7\xa7\xc7\x44\xf0\x7d\x1d\xf1\x6b\x60\xfd\x7f\xb6\xb9\xab\xcb\xad\xc5\x99\xbd\xe5\x82\x6b\x3e\xf4\x02\x4b\xae\xd5\x13\x84\xaf\xde\xf8\xcf\xf0\xc6\xd7\x45\xd7\xeb\xa2\xeb\x75\xd1\xb5\xeb\xce\xf2\xba\xe8\xda\x99\x96\x6d\x93\xa1\x9a\x96\xde\x8f\x3b\x7e\xc4\x56\xe8\x02\x64\x39\xf2\xec\x27\x31\x0a\x47\x93\x56\x4e\x9a\x2c\x0d\x7d\x78\x78\x78\xdf\x06\x77\x71\x67\x77\x7d\x4b\x72\x37\x9a\x86\x5d\x6a\x5f\x9e\xb3\x75\x39\xd8\xd8\xba\x94\x6e\xa2\x3d\x64\xf2\x95\xde\xe6\xce\xb9\x86\xe2\x29\xac\xd5\x74\x55\xfc\x9a\xfc\xf9\x1c\xe2\x60\x35\x5b\x69\x89\xb6\x4e\x55\x98\x4a\x18\x4c\xb7\xdb\x87\x5b\xcf\x1d\x6b\xe7\x1d\xee\x66\x86\xa6\x15\x92\xeb\xe3\xec\x7f\xa3\x98\x26\x76\xad\xad\xdd\x70\xbc\x2e\x13\x71\x99\xbf\x9a\xd6\x80\x85\x53\x35\x32\x96\x71\x74\x6c\x18\xe5\xdf\xef\x24\xa9\x18\xb3\x6b\xcc\xbf\xc3\xd7\xda\x6b\xa8\xfe\xfe\xef\xc1\xbe\xcf\xe7\x60\xdb\x7f\x0d\xf6\xfd\x3e\x06\x5b\xa1\xb9\x85\x26\x97\x9f\x5c\x3f\xe2\xb3\xca\xff\x06\x00\x00\xff\xff\x96\x70\x0b\x9a\x8b\x42\x00\x00")
+
+func templateDefaultTmplBytes() ([]byte, error) {
+ return bindataRead(
+ _templateDefaultTmpl,
+ "template/default.tmpl",
+ )
+}
+
+func templateDefaultTmpl() (*asset, error) {
+ bytes, err := templateDefaultTmplBytes()
+ if err != nil {
+ return nil, err
+ }
+
+ info := bindataFileInfo{name: "template/default.tmpl", size: 17035, mode: os.FileMode(420), modTime: time.Unix(1, 0)}
+ a := &asset{bytes: bytes, info: info}
+ return a, nil
+}
+
+// Asset loads and returns the asset for the given name.
+// It returns an error if the asset could not be found or
+// could not be loaded.
+func Asset(name string) ([]byte, error) {
+ cannonicalName := strings.Replace(name, "\\", "/", -1)
+ if f, ok := _bindata[cannonicalName]; ok {
+ a, err := f()
+ if err != nil {
+ return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
+ }
+ return a.bytes, nil
+ }
+ return nil, fmt.Errorf("Asset %s not found", name)
+}
+
+// MustAsset is like Asset but panics when Asset would return an error.
+// It simplifies safe initialization of global variables.
+func MustAsset(name string) []byte {
+ a, err := Asset(name)
+ if err != nil {
+ panic("asset: Asset(" + name + "): " + err.Error())
+ }
+
+ return a
+}
+
+// AssetInfo loads and returns the asset info for the given name.
+// It returns an error if the asset could not be found or
+// could not be loaded.
+func AssetInfo(name string) (os.FileInfo, error) {
+ cannonicalName := strings.Replace(name, "\\", "/", -1)
+ if f, ok := _bindata[cannonicalName]; ok {
+ a, err := f()
+ if err != nil {
+ return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
+ }
+ return a.info, nil
+ }
+ return nil, fmt.Errorf("AssetInfo %s not found", name)
+}
+
+// AssetNames returns the names of the assets.
+func AssetNames() []string {
+ names := make([]string, 0, len(_bindata))
+ for name := range _bindata {
+ names = append(names, name)
+ }
+ return names
+}
+
+// _bindata is a table, holding each asset generator, mapped to its name.
+var _bindata = map[string]func() (*asset, error){
+ "template/default.tmpl": templateDefaultTmpl,
+}
+
+// AssetDir returns the file names below a certain
+// directory embedded in the file by go-bindata.
+// For example if you run go-bindata on data/... and data contains the
+// following hierarchy:
+// data/
+// foo.txt
+// img/
+// a.png
+// b.png
+// then AssetDir("data") would return []string{"foo.txt", "img"}
+// AssetDir("data/img") would return []string{"a.png", "b.png"}
+// AssetDir("foo.txt") and AssetDir("notexist") would return an error
+// AssetDir("") will return []string{"data"}.
+func AssetDir(name string) ([]string, error) {
+ node := _bintree
+ if len(name) != 0 {
+ cannonicalName := strings.Replace(name, "\\", "/", -1)
+ pathList := strings.Split(cannonicalName, "/")
+ for _, p := range pathList {
+ node = node.Children[p]
+ if node == nil {
+ return nil, fmt.Errorf("Asset %s not found", name)
+ }
+ }
+ }
+ if node.Func != nil {
+ return nil, fmt.Errorf("Asset %s not found", name)
+ }
+ rv := make([]string, 0, len(node.Children))
+ for childName := range node.Children {
+ rv = append(rv, childName)
+ }
+ return rv, nil
+}
+
+type bintree struct {
+ Func func() (*asset, error)
+ Children map[string]*bintree
+}
+
+var _bintree = &bintree{nil, map[string]*bintree{
+ "template": &bintree{nil, map[string]*bintree{
+ "default.tmpl": &bintree{templateDefaultTmpl, map[string]*bintree{}},
+ }},
+}}
+
+// RestoreAsset restores an asset under the given directory
+func RestoreAsset(dir, name string) error {
+ data, err := Asset(name)
+ if err != nil {
+ return err
+ }
+ info, err := AssetInfo(name)
+ if err != nil {
+ return err
+ }
+ err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
+ if err != nil {
+ return err
+ }
+ err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
+ if err != nil {
+ return err
+ }
+ err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// RestoreAssets restores an asset under the given directory recursively
+func RestoreAssets(dir, name string) error {
+ children, err := AssetDir(name)
+ // File
+ if err != nil {
+ return RestoreAsset(dir, name)
+ }
+ // Dir
+ for _, child := range children {
+ err = RestoreAssets(dir, filepath.Join(name, child))
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func _filePath(dir, name string) string {
+ cannonicalName := strings.Replace(name, "\\", "/", -1)
+ return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package template
+
+import (
+ "bytes"
+ "net/url"
+ "path/filepath"
+ "regexp"
+ "sort"
+ "strings"
+ "time"
+
+ tmplhtml "html/template"
+ tmpltext "text/template"
+
+ "github.com/prometheus/common/model"
+
+ "github.com/prometheus/alertmanager/template/internal/deftmpl"
+ "github.com/prometheus/alertmanager/types"
+)
+
+// Template bundles a text and a html template instance.
+type Template struct {
+ text *tmpltext.Template
+ html *tmplhtml.Template
+
+ ExternalURL *url.URL
+}
+
+// FromGlobs calls ParseGlob on all path globs provided and returns the
+// resulting Template.
+func FromGlobs(paths ...string) (*Template, error) {
+ t := &Template{
+ text: tmpltext.New("").Option("missingkey=zero"),
+ html: tmplhtml.New("").Option("missingkey=zero"),
+ }
+ var err error
+
+ t.text = t.text.Funcs(tmpltext.FuncMap(DefaultFuncs))
+ t.html = t.html.Funcs(tmplhtml.FuncMap(DefaultFuncs))
+
+ b, err := deftmpl.Asset("template/default.tmpl")
+ if err != nil {
+ return nil, err
+ }
+ if t.text, err = t.text.Parse(string(b)); err != nil {
+ return nil, err
+ }
+ if t.html, err = t.html.Parse(string(b)); err != nil {
+ return nil, err
+ }
+
+ for _, tp := range paths {
+ // ParseGlob in the template packages errors if not at least one file is
+ // matched. We want to allow empty matches that may be populated later on.
+ p, err := filepath.Glob(tp)
+ if err != nil {
+ return nil, err
+ }
+ if len(p) > 0 {
+ if t.text, err = t.text.ParseGlob(tp); err != nil {
+ return nil, err
+ }
+ if t.html, err = t.html.ParseGlob(tp); err != nil {
+ return nil, err
+ }
+ }
+ }
+ return t, nil
+}
+
+// ExecuteTextString needs a meaningful doc comment (TODO(fabxc)).
+func (t *Template) ExecuteTextString(text string, data interface{}) (string, error) {
+ if text == "" {
+ return "", nil
+ }
+ tmpl, err := t.text.Clone()
+ if err != nil {
+ return "", err
+ }
+ tmpl, err = tmpl.New("").Option("missingkey=zero").Parse(text)
+ if err != nil {
+ return "", err
+ }
+ var buf bytes.Buffer
+ err = tmpl.Execute(&buf, data)
+ return buf.String(), err
+}
+
+// ExecuteHTMLString needs a meaningful doc comment (TODO(fabxc)).
+func (t *Template) ExecuteHTMLString(html string, data interface{}) (string, error) {
+ if html == "" {
+ return "", nil
+ }
+ tmpl, err := t.html.Clone()
+ if err != nil {
+ return "", err
+ }
+ tmpl, err = tmpl.New("").Option("missingkey=zero").Parse(html)
+ if err != nil {
+ return "", err
+ }
+ var buf bytes.Buffer
+ err = tmpl.Execute(&buf, data)
+ return buf.String(), err
+}
+
+type FuncMap map[string]interface{}
+
+var DefaultFuncs = FuncMap{
+ "toUpper": strings.ToUpper,
+ "toLower": strings.ToLower,
+ "title": strings.Title,
+ // join is equal to strings.Join but inverts the argument order
+ // for easier pipelining in templates.
+ "join": func(sep string, s []string) string {
+ return strings.Join(s, sep)
+ },
+ "safeHtml": func(text string) tmplhtml.HTML {
+ return tmplhtml.HTML(text)
+ },
+ "reReplaceAll": func(pattern, repl, text string) string {
+ re := regexp.MustCompile(pattern)
+ return re.ReplaceAllString(text, repl)
+ },
+}
+
+// Pair is a key/value string pair.
+type Pair struct {
+ Name, Value string
+}
+
+// Pairs is a list of key/value string pairs.
+type Pairs []Pair
+
+// Names returns a list of names of the pairs.
+func (ps Pairs) Names() []string {
+ ns := make([]string, 0, len(ps))
+ for _, p := range ps {
+ ns = append(ns, p.Name)
+ }
+ return ns
+}
+
+// Values returns a list of values of the pairs.
+func (ps Pairs) Values() []string {
+ vs := make([]string, 0, len(ps))
+ for _, p := range ps {
+ vs = append(vs, p.Value)
+ }
+ return vs
+}
+
+// KV is a set of key/value string pairs.
+type KV map[string]string
+
+// SortedPairs returns a sorted list of key/value pairs.
+func (kv KV) SortedPairs() Pairs {
+ var (
+ pairs = make([]Pair, 0, len(kv))
+ keys = make([]string, 0, len(kv))
+ sortStart = 0
+ )
+ for k := range kv {
+ if k == string(model.AlertNameLabel) {
+ keys = append([]string{k}, keys...)
+ sortStart = 1
+ } else {
+ keys = append(keys, k)
+ }
+ }
+ sort.Strings(keys[sortStart:])
+
+ for _, k := range keys {
+ pairs = append(pairs, Pair{k, kv[k]})
+ }
+ return pairs
+}
+
+// Remove returns a copy of the key/value set without the given keys.
+func (kv KV) Remove(keys []string) KV {
+ keySet := make(map[string]struct{}, len(keys))
+ for _, k := range keys {
+ keySet[k] = struct{}{}
+ }
+
+ res := KV{}
+ for k, v := range kv {
+ if _, ok := keySet[k]; !ok {
+ res[k] = v
+ }
+ }
+ return res
+}
+
+// Names returns the names of the label names in the LabelSet.
+func (kv KV) Names() []string {
+ return kv.SortedPairs().Names()
+}
+
+// Values returns a list of the values in the LabelSet.
+func (kv KV) Values() []string {
+ return kv.SortedPairs().Values()
+}
+
+// Data is the data passed to notification templates and webhook pushes.
+//
+// End-users should not be exposed to Go's type system, as this will confuse them and prevent
+// simple things like simple equality checks to fail. Map everything to float64/string.
+type Data struct {
+ Receiver string `json:"receiver"`
+ Status string `json:"status"`
+ Alerts Alerts `json:"alerts"`
+
+ GroupLabels KV `json:"groupLabels"`
+ CommonLabels KV `json:"commonLabels"`
+ CommonAnnotations KV `json:"commonAnnotations"`
+
+ ExternalURL string `json:"externalURL"`
+}
+
+// Alert holds one alert for notification templates.
+type Alert struct {
+ Status string `json:"status"`
+ Labels KV `json:"labels"`
+ Annotations KV `json:"annotations"`
+ StartsAt time.Time `json:"startsAt"`
+ EndsAt time.Time `json:"endsAt"`
+ GeneratorURL string `json:"generatorURL"`
+}
+
+// Alerts is a list of Alert objects.
+type Alerts []Alert
+
+// Firing returns the subset of alerts that are firing.
+func (as Alerts) Firing() []Alert {
+ res := []Alert{}
+ for _, a := range as {
+ if a.Status == string(model.AlertFiring) {
+ res = append(res, a)
+ }
+ }
+ return res
+}
+
+// Resolved returns the subset of alerts that are resolved.
+func (as Alerts) Resolved() []Alert {
+ res := []Alert{}
+ for _, a := range as {
+ if a.Status == string(model.AlertResolved) {
+ res = append(res, a)
+ }
+ }
+ return res
+}
+
+// Data assembles data for template expansion.
+func (t *Template) Data(recv string, groupLabels model.LabelSet, alerts ...*types.Alert) *Data {
+ data := &Data{
+ Receiver: regexp.QuoteMeta(strings.SplitN(recv, "/", 2)[0]),
+ Status: string(types.Alerts(alerts...).Status()),
+ Alerts: make(Alerts, 0, len(alerts)),
+ GroupLabels: KV{},
+ CommonLabels: KV{},
+ CommonAnnotations: KV{},
+ ExternalURL: t.ExternalURL.String(),
+ }
+
+ // The call to types.Alert is necessary to correctly resolve the internal
+ // representation to the user representation.
+ for _, a := range types.Alerts(alerts...) {
+ alert := Alert{
+ Status: string(a.Status()),
+ Labels: make(KV, len(a.Labels)),
+ Annotations: make(KV, len(a.Annotations)),
+ StartsAt: a.StartsAt,
+ EndsAt: a.EndsAt,
+ GeneratorURL: a.GeneratorURL,
+ }
+ for k, v := range a.Labels {
+ alert.Labels[string(k)] = string(v)
+ }
+ for k, v := range a.Annotations {
+ alert.Annotations[string(k)] = string(v)
+ }
+ data.Alerts = append(data.Alerts, alert)
+ }
+
+ for k, v := range groupLabels {
+ data.GroupLabels[string(k)] = string(v)
+ }
+
+ if len(alerts) >= 1 {
+ var (
+ commonLabels = alerts[0].Labels.Clone()
+ commonAnnotations = alerts[0].Annotations.Clone()
+ )
+ for _, a := range alerts[1:] {
+ for ln, lv := range commonLabels {
+ if a.Labels[ln] != lv {
+ delete(commonLabels, ln)
+ }
+ }
+ for an, av := range commonAnnotations {
+ if a.Annotations[an] != av {
+ delete(commonAnnotations, an)
+ }
+ }
+ }
+ for k, v := range commonLabels {
+ data.CommonLabels[string(k)] = string(v)
+ }
+ for k, v := range commonAnnotations {
+ data.CommonAnnotations[string(k)] = string(v)
+ }
+ }
+
+ return data
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package template
+
+import (
+ "testing"
+
+ "github.com/prometheus/common/model"
+ "github.com/stretchr/testify/require"
+)
+
+func TestPairNames(t *testing.T) {
+ pairs := Pairs{
+ {"name1", "value1"},
+ {"name2", "value2"},
+ {"name3", "value3"},
+ }
+
+ expected := []string{"name1", "name2", "name3"}
+ require.EqualValues(t, expected, pairs.Names())
+}
+
+func TestPairValues(t *testing.T) {
+ pairs := Pairs{
+ {"name1", "value1"},
+ {"name2", "value2"},
+ {"name3", "value3"},
+ }
+
+ expected := []string{"value1", "value2", "value3"}
+ require.EqualValues(t, expected, pairs.Values())
+}
+
+func TestKVSortedPairs(t *testing.T) {
+ kv := KV{"d": "dVal", "b": "bVal", "c": "cVal"}
+
+ expectedPairs := Pairs{
+ {"b", "bVal"},
+ {"c", "cVal"},
+ {"d", "dVal"},
+ }
+
+ for i, p := range kv.SortedPairs() {
+ require.EqualValues(t, p.Name, expectedPairs[i].Name)
+ require.EqualValues(t, p.Value, expectedPairs[i].Value)
+ }
+
+ // validates alertname always comes first
+ kv = KV{"d": "dVal", "b": "bVal", "c": "cVal", "alertname": "alert", "a": "aVal"}
+
+ expectedPairs = Pairs{
+ {"alertname", "alert"},
+ {"a", "aVal"},
+ {"b", "bVal"},
+ {"c", "cVal"},
+ {"d", "dVal"},
+ }
+
+ for i, p := range kv.SortedPairs() {
+ require.EqualValues(t, p.Name, expectedPairs[i].Name)
+ require.EqualValues(t, p.Value, expectedPairs[i].Value)
+ }
+}
+
+func TestKVRemove(t *testing.T) {
+ kv := KV{
+ "key1": "val1",
+ "key2": "val2",
+ "key3": "val3",
+ "key4": "val4",
+ }
+
+ kv = kv.Remove([]string{"key2", "key4"})
+
+ expected := []string{"key1", "key3"}
+ require.EqualValues(t, expected, kv.Names())
+}
+
+func TestAlertsFiring(t *testing.T) {
+ alerts := Alerts{
+ {Status: string(model.AlertFiring)},
+ {Status: string(model.AlertResolved)},
+ {Status: string(model.AlertFiring)},
+ {Status: string(model.AlertResolved)},
+ {Status: string(model.AlertResolved)},
+ }
+
+ for _, alert := range alerts.Firing() {
+ if alert.Status != string(model.AlertFiring) {
+ t.Errorf("unexpected status %q", alert.Status)
+ }
+ }
+}
+
+func TestAlertsResolved(t *testing.T) {
+ alerts := Alerts{
+ {Status: string(model.AlertFiring)},
+ {Status: string(model.AlertResolved)},
+ {Status: string(model.AlertFiring)},
+ {Status: string(model.AlertResolved)},
+ {Status: string(model.AlertResolved)},
+ }
+
+ for _, alert := range alerts.Resolved() {
+ if alert.Status != string(model.AlertResolved) {
+ t.Errorf("unexpected status %q", alert.Status)
+ }
+ }
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package test
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net"
+ "net/http"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "sync"
+ "syscall"
+ "testing"
+ "time"
+
+ "github.com/prometheus/client_golang/api"
+ "github.com/prometheus/common/model"
+ "golang.org/x/net/context"
+
+ "github.com/prometheus/alertmanager/client"
+)
+
+// AcceptanceTest provides declarative definition of given inputs and expected
+// output of an Alertmanager setup.
+type AcceptanceTest struct {
+ *testing.T
+
+ opts *AcceptanceOpts
+
+ ams []*Alertmanager
+ collectors []*Collector
+
+ actions map[float64][]func()
+}
+
+// AcceptanceOpts defines configuration paramters for an acceptance test.
+type AcceptanceOpts struct {
+ Tolerance time.Duration
+ baseTime time.Time
+}
+
+func (opts *AcceptanceOpts) alertString(a *model.Alert) string {
+ if a.EndsAt.IsZero() {
+ return fmt.Sprintf("%s[%v:]", a, opts.relativeTime(a.StartsAt))
+ }
+ return fmt.Sprintf("%s[%v:%v]", a, opts.relativeTime(a.StartsAt), opts.relativeTime(a.EndsAt))
+}
+
+// expandTime returns the absolute time for the relative time
+// calculated from the test's base time.
+func (opts *AcceptanceOpts) expandTime(rel float64) time.Time {
+ return opts.baseTime.Add(time.Duration(rel * float64(time.Second)))
+}
+
+// expandTime returns the relative time for the given time
+// calculated from the test's base time.
+func (opts *AcceptanceOpts) relativeTime(act time.Time) float64 {
+ return float64(act.Sub(opts.baseTime)) / float64(time.Second)
+}
+
+// NewAcceptanceTest returns a new acceptance test with the base time
+// set to the current time.
+func NewAcceptanceTest(t *testing.T, opts *AcceptanceOpts) *AcceptanceTest {
+ test := &AcceptanceTest{
+ T: t,
+ opts: opts,
+ actions: map[float64][]func(){},
+ }
+ opts.baseTime = time.Now()
+
+ return test
+}
+
+// freeAddress returns a new listen address not currently in use.
+func freeAddress() string {
+ // Let the OS allocate a free address, close it and hope
+ // it is still free when starting Alertmanager.
+ l, err := net.Listen("tcp4", "localhost:0")
+ if err != nil {
+ panic(err)
+ }
+ defer l.Close()
+
+ return l.Addr().String()
+}
+
+// Do sets the given function to be executed at the given time.
+func (t *AcceptanceTest) Do(at float64, f func()) {
+ t.actions[at] = append(t.actions[at], f)
+}
+
+// Alertmanager returns a new structure that allows starting an instance
+// of Alertmanager on a random port.
+func (t *AcceptanceTest) Alertmanager(conf string) *Alertmanager {
+ am := &Alertmanager{
+ t: t,
+ opts: t.opts,
+ }
+
+ dir, err := ioutil.TempDir("", "am_test")
+ if err != nil {
+ t.Fatal(err)
+ }
+ am.dir = dir
+
+ cf, err := os.Create(filepath.Join(dir, "config.yml"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ am.confFile = cf
+ am.UpdateConfig(conf)
+
+ am.apiAddr = freeAddress()
+ am.clusterAddr = freeAddress()
+
+ t.Logf("AM on %s", am.apiAddr)
+
+ c, err := api.NewClient(api.Config{
+ Address: fmt.Sprintf("http://%s", am.apiAddr),
+ })
+ if err != nil {
+ t.Fatal(err)
+ }
+ am.client = c
+
+ t.ams = append(t.ams, am)
+
+ return am
+}
+
+// Collector returns a new collector bound to the test instance.
+func (t *AcceptanceTest) Collector(name string) *Collector {
+ co := &Collector{
+ t: t.T,
+ name: name,
+ opts: t.opts,
+ collected: map[float64][]model.Alerts{},
+ expected: map[Interval][]model.Alerts{},
+ }
+ t.collectors = append(t.collectors, co)
+
+ return co
+}
+
+// Run starts all Alertmanagers and runs queries against them. It then checks
+// whether all expected notifications have arrived at the expected receiver.
+func (t *AcceptanceTest) Run() {
+ errc := make(chan error)
+
+ for _, am := range t.ams {
+ am.errc = errc
+
+ am.Start()
+ defer func(am *Alertmanager) {
+ am.Terminate()
+ am.cleanup()
+ t.Logf("stdout:\n%v", am.cmd.Stdout)
+ t.Logf("stderr:\n%v", am.cmd.Stderr)
+ }(am)
+ }
+
+ go t.runActions()
+
+ var latest float64
+ for _, coll := range t.collectors {
+ if l := coll.latest(); l > latest {
+ latest = l
+ }
+ }
+
+ deadline := t.opts.expandTime(latest)
+
+ select {
+ case <-time.After(deadline.Sub(time.Now())):
+ // continue
+ case err := <-errc:
+ t.Error(err)
+ }
+
+ for _, coll := range t.collectors {
+ report := coll.check()
+ t.Log(report)
+ }
+}
+
+// runActions performs the stored actions at the defined times.
+func (t *AcceptanceTest) runActions() {
+ var wg sync.WaitGroup
+
+ for at, fs := range t.actions {
+ ts := t.opts.expandTime(at)
+ wg.Add(len(fs))
+
+ for _, f := range fs {
+ go func(f func()) {
+ time.Sleep(ts.Sub(time.Now()))
+ f()
+ wg.Done()
+ }(f)
+ }
+ }
+
+ wg.Wait()
+}
+
+type buffer struct {
+ b bytes.Buffer
+ mtx sync.Mutex
+}
+
+func (b *buffer) Write(p []byte) (int, error) {
+ b.mtx.Lock()
+ defer b.mtx.Unlock()
+ return b.b.Write(p)
+}
+
+func (b *buffer) String() string {
+ b.mtx.Lock()
+ defer b.mtx.Unlock()
+ return b.b.String()
+}
+
+// Alertmanager encapsulates an Alertmanager process and allows
+// declaring alerts being pushed to it at fixed points in time.
+type Alertmanager struct {
+ t *AcceptanceTest
+ opts *AcceptanceOpts
+
+ apiAddr string
+ clusterAddr string
+ client api.Client
+ cmd *exec.Cmd
+ confFile *os.File
+ dir string
+
+ errc chan<- error
+}
+
+// Start the alertmanager and wait until it is ready to receive.
+func (am *Alertmanager) Start() {
+ cmd := exec.Command("../../alertmanager",
+ "--config.file", am.confFile.Name(),
+ "--log.level", "debug",
+ "--web.listen-address", am.apiAddr,
+ "--storage.path", am.dir,
+ "--cluster.listen-address", am.clusterAddr,
+ "--cluster.settle-timeout", "0s",
+ )
+
+ if am.cmd == nil {
+ var outb, errb buffer
+ cmd.Stdout = &outb
+ cmd.Stderr = &errb
+ } else {
+ cmd.Stdout = am.cmd.Stdout
+ cmd.Stderr = am.cmd.Stderr
+ }
+ am.cmd = cmd
+
+ if err := am.cmd.Start(); err != nil {
+ am.t.Fatalf("Starting alertmanager failed: %s", err)
+ }
+
+ go func() {
+ if err := am.cmd.Wait(); err != nil {
+ am.errc <- err
+ }
+ }()
+
+ time.Sleep(50 * time.Millisecond)
+ for i := 0; i < 10; i++ {
+ resp, err := http.Get(fmt.Sprintf("http://%s/status", am.apiAddr))
+ if err == nil {
+ _, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ am.t.Fatalf("Starting alertmanager failed: %s", err)
+ }
+ resp.Body.Close()
+ return
+ }
+ time.Sleep(500 * time.Millisecond)
+ }
+ am.t.Fatalf("Starting alertmanager failed: timeout")
+}
+
+// Terminate kills the underlying Alertmanager process and remove intermediate
+// data.
+func (am *Alertmanager) Terminate() {
+ syscall.Kill(am.cmd.Process.Pid, syscall.SIGTERM)
+}
+
+// Reload sends the reloading signal to the Alertmanager process.
+func (am *Alertmanager) Reload() {
+ syscall.Kill(am.cmd.Process.Pid, syscall.SIGHUP)
+}
+
+func (am *Alertmanager) cleanup() {
+ os.RemoveAll(am.confFile.Name())
+}
+
+// Push declares alerts that are to be pushed to the Alertmanager
+// server at a relative point in time.
+func (am *Alertmanager) Push(at float64, alerts ...*TestAlert) {
+ var cas []client.Alert
+ for i := range alerts {
+ a := alerts[i].nativeAlert(am.opts)
+ al := client.Alert{
+ Labels: client.LabelSet{},
+ Annotations: client.LabelSet{},
+ StartsAt: a.StartsAt,
+ EndsAt: a.EndsAt,
+ GeneratorURL: a.GeneratorURL,
+ }
+ for n, v := range a.Labels {
+ al.Labels[client.LabelName(n)] = client.LabelValue(v)
+ }
+ for n, v := range a.Annotations {
+ al.Annotations[client.LabelName(n)] = client.LabelValue(v)
+ }
+ cas = append(cas, al)
+ }
+
+ alertAPI := client.NewAlertAPI(am.client)
+
+ am.t.Do(at, func() {
+ if err := alertAPI.Push(context.Background(), cas...); err != nil {
+ am.t.Errorf("Error pushing %v: %s", cas, err)
+ }
+ })
+}
+
+// SetSilence updates or creates the given Silence.
+func (am *Alertmanager) SetSilence(at float64, sil *TestSilence) {
+ am.t.Do(at, func() {
+ var buf bytes.Buffer
+ if err := json.NewEncoder(&buf).Encode(sil.nativeSilence(am.opts)); err != nil {
+ am.t.Errorf("Error setting silence %v: %s", sil, err)
+ return
+ }
+
+ resp, err := http.Post(fmt.Sprintf("http://%s/api/v1/silences", am.apiAddr), "application/json", &buf)
+ if err != nil {
+ am.t.Errorf("Error setting silence %v: %s", sil, err)
+ return
+ }
+ defer resp.Body.Close()
+
+ b, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ panic(err)
+ }
+
+ var v struct {
+ Status string `json:"status"`
+ Data struct {
+ SilenceID string `json:"silenceId"`
+ } `json:"data"`
+ }
+ if err := json.Unmarshal(b, &v); err != nil || resp.StatusCode/100 != 2 {
+ am.t.Errorf("error setting silence %v: %s", sil, err)
+ return
+ }
+ sil.SetID(v.Data.SilenceID)
+ })
+}
+
+// DelSilence deletes the silence with the sid at the given time.
+func (am *Alertmanager) DelSilence(at float64, sil *TestSilence) {
+ am.t.Do(at, func() {
+ req, err := http.NewRequest("DELETE", fmt.Sprintf("http://%s/api/v1/silence/%s", am.apiAddr, sil.ID()), nil)
+ if err != nil {
+ am.t.Errorf("Error deleting silence %v: %s", sil, err)
+ return
+ }
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil || resp.StatusCode/100 != 2 {
+ am.t.Errorf("Error deleting silence %v: %s", sil, err)
+ return
+ }
+ })
+}
+
+// UpdateConfig rewrites the configuration file for the Alertmanager. It does not
+// initiate config reloading.
+func (am *Alertmanager) UpdateConfig(conf string) {
+ if _, err := am.confFile.WriteString(conf); err != nil {
+ am.t.Fatal(err)
+ return
+ }
+ if err := am.confFile.Sync(); err != nil {
+ am.t.Fatal(err)
+ return
+ }
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package test
+
+import (
+ "fmt"
+ "testing"
+ "time"
+
+ . "github.com/prometheus/alertmanager/test"
+)
+
+func TestInhibiting(t *testing.T) {
+ t.Parallel()
+
+ // This integration test checks that alerts can be inhibited and that an
+ // inhibited alert will be notified again as soon as the inhibiting alert
+ // gets resolved.
+
+ conf := `
+route:
+ receiver: "default"
+ group_by: []
+ group_wait: 1s
+ group_interval: 1s
+ repeat_interval: 1s
+
+receivers:
+- name: "default"
+ webhook_configs:
+ - url: 'http://%s'
+
+inhibit_rules:
+- source_match:
+ alertname: JobDown
+ target_match:
+ alertname: InstanceDown
+ equal:
+ - job
+ - zone
+`
+
+ at := NewAcceptanceTest(t, &AcceptanceOpts{
+ Tolerance: 150 * time.Millisecond,
+ })
+
+ co := at.Collector("webhook")
+ wh := NewWebhook(co)
+
+ am := at.Alertmanager(fmt.Sprintf(conf, wh.Address()))
+
+ am.Push(At(1), Alert("alertname", "test1", "job", "testjob", "zone", "aa"))
+ am.Push(At(1), Alert("alertname", "InstanceDown", "job", "testjob", "zone", "aa"))
+ am.Push(At(1), Alert("alertname", "InstanceDown", "job", "testjob", "zone", "ab"))
+
+ // This JobDown in zone aa should inhibit InstanceDown in zone aa in the
+ // second batch of notifications.
+ am.Push(At(2.2), Alert("alertname", "JobDown", "job", "testjob", "zone", "aa"))
+
+ // InstanceDown in zone aa should fire again in the third batch of
+ // notifications once JobDown in zone aa gets resolved.
+ am.Push(At(3.6), Alert("alertname", "JobDown", "job", "testjob", "zone", "aa").Active(2.2, 3.6))
+
+ co.Want(Between(2, 2.5),
+ Alert("alertname", "test1", "job", "testjob", "zone", "aa").Active(1),
+ Alert("alertname", "InstanceDown", "job", "testjob", "zone", "aa").Active(1),
+ Alert("alertname", "InstanceDown", "job", "testjob", "zone", "ab").Active(1),
+ )
+
+ co.Want(Between(3, 3.5),
+ Alert("alertname", "test1", "job", "testjob", "zone", "aa").Active(1),
+ Alert("alertname", "InstanceDown", "job", "testjob", "zone", "ab").Active(1),
+ Alert("alertname", "JobDown", "job", "testjob", "zone", "aa").Active(2.2),
+ )
+
+ co.Want(Between(4, 4.5),
+ Alert("alertname", "test1", "job", "testjob", "zone", "aa").Active(1),
+ Alert("alertname", "InstanceDown", "job", "testjob", "zone", "aa").Active(1),
+ Alert("alertname", "InstanceDown", "job", "testjob", "zone", "ab").Active(1),
+ Alert("alertname", "JobDown", "job", "testjob", "zone", "aa").Active(2.2, 3.6),
+ )
+
+ at.Run()
+}
+
+func TestAlwaysInhibiting(t *testing.T) {
+ t.Parallel()
+
+ // This integration test checks that when inhibited and inhibiting alerts
+ // gets resolved at the same time, the final notification contains both
+ // alerts.
+
+ conf := `
+route:
+ receiver: "default"
+ group_by: []
+ group_wait: 1s
+ group_interval: 1s
+ repeat_interval: 1s
+
+receivers:
+- name: "default"
+ webhook_configs:
+ - url: 'http://%s'
+
+inhibit_rules:
+- source_match:
+ alertname: JobDown
+ target_match:
+ alertname: InstanceDown
+ equal:
+ - job
+ - zone
+`
+
+ at := NewAcceptanceTest(t, &AcceptanceOpts{
+ Tolerance: 150 * time.Millisecond,
+ })
+
+ co := at.Collector("webhook")
+ wh := NewWebhook(co)
+
+ am := at.Alertmanager(fmt.Sprintf(conf, wh.Address()))
+
+ am.Push(At(1), Alert("alertname", "InstanceDown", "job", "testjob", "zone", "aa"))
+ am.Push(At(1), Alert("alertname", "JobDown", "job", "testjob", "zone", "aa"))
+
+ am.Push(At(2.6), Alert("alertname", "JobDown", "job", "testjob", "zone", "aa").Active(1, 2.6))
+ am.Push(At(2.6), Alert("alertname", "InstanceDown", "job", "testjob", "zone", "aa").Active(1, 2.6))
+
+ co.Want(Between(2, 2.5),
+ Alert("alertname", "JobDown", "job", "testjob", "zone", "aa").Active(1),
+ )
+
+ co.Want(Between(3, 3.5),
+ Alert("alertname", "InstanceDown", "job", "testjob", "zone", "aa").Active(1, 2.6),
+ Alert("alertname", "JobDown", "job", "testjob", "zone", "aa").Active(1, 2.6),
+ )
+
+ at.Run()
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package test
+
+import (
+ "fmt"
+ "sync"
+ "testing"
+ "time"
+
+ . "github.com/prometheus/alertmanager/test"
+)
+
+// This file contains acceptance tests around the basic sending logic
+// for notifications, which includes batching and ensuring that each
+// notification is eventually sent at least once and ideally exactly
+// once.
+
+func TestMergeAlerts(t *testing.T) {
+ t.Parallel()
+
+ conf := `
+route:
+ receiver: "default"
+ group_by: [alertname]
+ group_wait: 1s
+ group_interval: 1s
+ repeat_interval: 1ms
+
+receivers:
+- name: "default"
+ webhook_configs:
+ - url: 'http://%s'
+ send_resolved: true
+`
+
+ at := NewAcceptanceTest(t, &AcceptanceOpts{
+ Tolerance: 150 * time.Millisecond,
+ })
+
+ co := at.Collector("webhook")
+ wh := NewWebhook(co)
+
+ am := at.Alertmanager(fmt.Sprintf(conf, wh.Address()))
+
+ // Refresh an alert several times. The starting time must remain at the earliest
+ // point in time.
+ am.Push(At(1), Alert("alertname", "test").Active(1.1))
+ // Another Prometheus server might be sending later but with an earlier start time.
+ am.Push(At(1.2), Alert("alertname", "test").Active(1))
+
+ co.Want(Between(2, 2.5), Alert("alertname", "test").Active(1))
+
+ am.Push(At(2.1), Alert("alertname", "test").Annotate("ann", "v1").Active(2))
+
+ co.Want(Between(3, 3.5), Alert("alertname", "test").Annotate("ann", "v1").Active(1))
+
+ // Annotations are always overwritten by the alert that arrived most recently.
+ am.Push(At(3.6), Alert("alertname", "test").Annotate("ann", "v2").Active(1.5))
+
+ co.Want(Between(4, 4.5), Alert("alertname", "test").Annotate("ann", "v2").Active(1))
+
+ // If an alert is marked resolved twice, the latest point in time must be
+ // set as the eventual resolve time.
+ am.Push(At(4.6), Alert("alertname", "test").Annotate("ann", "v2").Active(3, 4.5))
+ am.Push(At(4.8), Alert("alertname", "test").Annotate("ann", "v3").Active(2.9, 4.8))
+ am.Push(At(4.8), Alert("alertname", "test").Annotate("ann", "v3").Active(2.9, 4.1))
+
+ co.Want(Between(5, 5.5), Alert("alertname", "test").Annotate("ann", "v3").Active(1, 4.8))
+
+ // Reactivate an alert after a previous occurrence has been resolved.
+ // No overlap, no merge must occur.
+ am.Push(At(5.3), Alert("alertname", "test"))
+
+ co.Want(Between(6, 6.5), Alert("alertname", "test").Active(5.3))
+
+ // Test against a bug which ocurrec after a restart. The previous occurrence of
+ // the alert was sent rather than the most recent one.
+ //
+ // XXX(fabxc) disabled as notification info won't be persisted. Thus, with a mesh
+ // notifier we lose the state in this single-node setup.
+ //at.Do(At(6.7), func() {
+ // am.Terminate()
+ // am.Start()
+ //})
+
+ // On restart the alert is flushed right away as the group_wait has already passed.
+ // However, it must be caught in the deduplication stage.
+ // The next attempt will be 1s later and won't be filtered in deduping.
+ //co.Want(Between(7.7, 8), Alert("alertname", "test").Active(5.3))
+
+ at.Run()
+}
+
+func TestRepeat(t *testing.T) {
+ t.Parallel()
+
+ conf := `
+route:
+ receiver: "default"
+ group_by: [alertname]
+ group_wait: 1s
+ group_interval: 1s
+ repeat_interval: 1ms
+
+receivers:
+- name: "default"
+ webhook_configs:
+ - url: 'http://%s'
+`
+
+ // Create a new acceptance test that instantiates new Alertmanagers
+ // with the given configuration and verifies times with the given
+ // tollerance.
+ at := NewAcceptanceTest(t, &AcceptanceOpts{
+ Tolerance: 150 * time.Millisecond,
+ })
+
+ // Create a collector to which alerts can be written and verified
+ // against a set of expected alert notifications.
+ co := at.Collector("webhook")
+ // Run something that satisfies the webhook interface to which the
+ // Alertmanager pushes as defined by its configuration.
+ wh := NewWebhook(co)
+
+ // Create a new Alertmanager process listening to a random port
+ am := at.Alertmanager(fmt.Sprintf(conf, wh.Address()))
+
+ // Declare pushes to be made to the Alertmanager at the given time.
+ // Times are provided in fractions of seconds.
+ am.Push(At(1), Alert("alertname", "test").Active(1))
+
+ // XXX(fabxc): disabled as long as alerts are not persisted.
+ // at.Do(At(1.2), func() {
+ // am.Terminate()
+ // am.Start()
+ // })
+ am.Push(At(3.5), Alert("alertname", "test").Active(1, 3))
+
+ // Declare which alerts are expected to arrive at the collector within
+ // the defined time intervals.
+ co.Want(Between(2, 2.5), Alert("alertname", "test").Active(1))
+ co.Want(Between(3, 3.5), Alert("alertname", "test").Active(1))
+ co.Want(Between(4, 4.5), Alert("alertname", "test").Active(1, 3))
+
+ // Start the flow as defined above and run the checks afterwards.
+ at.Run()
+}
+
+func TestRetry(t *testing.T) {
+ t.Parallel()
+
+ // We create a notification config that fans out into two different
+ // webhooks.
+ // The succeeding one must still only receive the first successful
+ // notifications. Sending to the succeeding one must eventually succeed.
+ conf := `
+route:
+ receiver: "default"
+ group_by: [alertname]
+ group_wait: 1s
+ group_interval: 1s
+ repeat_interval: 3s
+
+receivers:
+- name: "default"
+ webhook_configs:
+ - url: 'http://%s'
+ - url: 'http://%s'
+`
+
+ at := NewAcceptanceTest(t, &AcceptanceOpts{
+ Tolerance: 150 * time.Millisecond,
+ })
+
+ co1 := at.Collector("webhook")
+ wh1 := NewWebhook(co1)
+
+ co2 := at.Collector("webhook_failing")
+ wh2 := NewWebhook(co2)
+
+ wh2.Func = func(ts float64) bool {
+ // Fail the first two interval periods but eventually
+ // succeed in the third interval after a few failed attempts.
+ return ts < 4.5
+ }
+
+ am := at.Alertmanager(fmt.Sprintf(conf, wh1.Address(), wh2.Address()))
+
+ am.Push(At(1), Alert("alertname", "test1"))
+
+ co1.Want(Between(2, 2.5), Alert("alertname", "test1").Active(1))
+ co1.Want(Between(5, 5.5), Alert("alertname", "test1").Active(1))
+
+ co2.Want(Between(4.5, 5), Alert("alertname", "test1").Active(1))
+}
+
+func TestBatching(t *testing.T) {
+ t.Parallel()
+
+ conf := `
+route:
+ receiver: "default"
+ group_by: []
+ group_wait: 1s
+ group_interval: 1s
+ # use a value slightly below the 5s interval to avoid timing issues
+ repeat_interval: 4900ms
+
+receivers:
+- name: "default"
+ webhook_configs:
+ - url: 'http://%s'
+`
+
+ at := NewAcceptanceTest(t, &AcceptanceOpts{
+ Tolerance: 150 * time.Millisecond,
+ })
+
+ co := at.Collector("webhook")
+ wh := NewWebhook(co)
+
+ am := at.Alertmanager(fmt.Sprintf(conf, wh.Address()))
+
+ am.Push(At(1.1), Alert("alertname", "test1").Active(1))
+ am.Push(At(1.7), Alert("alertname", "test5").Active(1))
+
+ co.Want(Between(2.0, 2.5),
+ Alert("alertname", "test1").Active(1),
+ Alert("alertname", "test5").Active(1),
+ )
+
+ am.Push(At(3.3),
+ Alert("alertname", "test2").Active(1.5),
+ Alert("alertname", "test3").Active(1.5),
+ Alert("alertname", "test4").Active(1.6),
+ )
+
+ co.Want(Between(4.1, 4.5),
+ Alert("alertname", "test1").Active(1),
+ Alert("alertname", "test5").Active(1),
+ Alert("alertname", "test2").Active(1.5),
+ Alert("alertname", "test3").Active(1.5),
+ Alert("alertname", "test4").Active(1.6),
+ )
+
+ // While no changes happen expect no additional notifications
+ // until the 5s repeat interval has ended.
+
+ co.Want(Between(9.1, 9.5),
+ Alert("alertname", "test1").Active(1),
+ Alert("alertname", "test5").Active(1),
+ Alert("alertname", "test2").Active(1.5),
+ Alert("alertname", "test3").Active(1.5),
+ Alert("alertname", "test4").Active(1.6),
+ )
+
+ at.Run()
+}
+
+func TestResolved(t *testing.T) {
+ t.Parallel()
+
+ var wg sync.WaitGroup
+ wg.Add(10)
+
+ for i := 0; i < 10; i++ {
+ go func() {
+ conf := `
+global:
+ resolve_timeout: 10s
+
+route:
+ receiver: "default"
+ group_by: [alertname]
+ group_wait: 1s
+ group_interval: 5s
+
+receivers:
+- name: "default"
+ webhook_configs:
+ - url: 'http://%s'
+`
+
+ at := NewAcceptanceTest(t, &AcceptanceOpts{
+ Tolerance: 150 * time.Millisecond,
+ })
+
+ co := at.Collector("webhook")
+ wh := NewWebhook(co)
+
+ am := at.Alertmanager(fmt.Sprintf(conf, wh.Address()))
+
+ am.Push(At(1),
+ Alert("alertname", "test", "lbl", "v1"),
+ Alert("alertname", "test", "lbl", "v2"),
+ Alert("alertname", "test", "lbl", "v3"),
+ )
+
+ co.Want(Between(2, 2.5),
+ Alert("alertname", "test", "lbl", "v1").Active(1),
+ Alert("alertname", "test", "lbl", "v2").Active(1),
+ Alert("alertname", "test", "lbl", "v3").Active(1),
+ )
+ co.Want(Between(12, 13),
+ Alert("alertname", "test", "lbl", "v1").Active(1, 11),
+ Alert("alertname", "test", "lbl", "v2").Active(1, 11),
+ Alert("alertname", "test", "lbl", "v3").Active(1, 11),
+ )
+
+ at.Run()
+ wg.Done()
+ }()
+ }
+
+ wg.Wait()
+}
+
+func TestResolvedFilter(t *testing.T) {
+ t.Parallel()
+
+ // This integration test ensures that even though resolved alerts may not be
+ // notified about, they must be set as notified. Resolved alerts, even when
+ // filtered, have to end up in the SetNotifiesStage, otherwise when an alert
+ // fires again it is ambiguous whether it was resolved in between or not.
+
+ conf := `
+global:
+ resolve_timeout: 10s
+
+route:
+ receiver: "default"
+ group_by: [alertname]
+ group_wait: 1s
+ group_interval: 5s
+
+receivers:
+- name: "default"
+ webhook_configs:
+ - url: 'http://%s'
+ send_resolved: true
+ - url: 'http://%s'
+ send_resolved: false
+`
+
+ at := NewAcceptanceTest(t, &AcceptanceOpts{
+ Tolerance: 150 * time.Millisecond,
+ })
+
+ co1 := at.Collector("webhook1")
+ wh1 := NewWebhook(co1)
+
+ co2 := at.Collector("webhook2")
+ wh2 := NewWebhook(co2)
+
+ am := at.Alertmanager(fmt.Sprintf(conf, wh1.Address(), wh2.Address()))
+
+ am.Push(At(1),
+ Alert("alertname", "test", "lbl", "v1"),
+ Alert("alertname", "test", "lbl", "v2"),
+ )
+ am.Push(At(3),
+ Alert("alertname", "test", "lbl", "v1").Active(1, 4),
+ Alert("alertname", "test", "lbl", "v3"),
+ )
+ am.Push(At(8),
+ Alert("alertname", "test", "lbl", "v3").Active(3),
+ )
+
+ co1.Want(Between(2, 2.5),
+ Alert("alertname", "test", "lbl", "v1").Active(1),
+ Alert("alertname", "test", "lbl", "v2").Active(1),
+ )
+ co1.Want(Between(7, 7.5),
+ Alert("alertname", "test", "lbl", "v1").Active(1, 4),
+ Alert("alertname", "test", "lbl", "v2").Active(1),
+ Alert("alertname", "test", "lbl", "v3").Active(3),
+ )
+ // Notification should be sent because the v2 alert is resolved due to the time-out.
+ co1.Want(Between(12, 12.5),
+ Alert("alertname", "test", "lbl", "v2").Active(1, 11),
+ Alert("alertname", "test", "lbl", "v3").Active(3),
+ )
+
+ co2.Want(Between(2, 2.5),
+ Alert("alertname", "test", "lbl", "v1").Active(1),
+ Alert("alertname", "test", "lbl", "v2").Active(1),
+ )
+ co2.Want(Between(7, 7.5),
+ Alert("alertname", "test", "lbl", "v2").Active(1),
+ Alert("alertname", "test", "lbl", "v3").Active(3),
+ )
+ // No notification should be sent after group_interval because no new alert has been fired.
+ co2.Want(Between(12, 12.5))
+
+ at.Run()
+}
+
+func TestReload(t *testing.T) {
+ t.Parallel()
+
+ // This integration test ensures that the first alert isn't notified twice
+ // and repeat_interval applies after the AlertManager process has been
+ // reloaded.
+ conf := `
+route:
+ receiver: "default"
+ group_by: []
+ group_wait: 1s
+ group_interval: 6s
+ repeat_interval: 10m
+
+receivers:
+- name: "default"
+ webhook_configs:
+ - url: 'http://%s'
+`
+
+ at := NewAcceptanceTest(t, &AcceptanceOpts{
+ Tolerance: 150 * time.Millisecond,
+ })
+
+ co := at.Collector("webhook")
+ wh := NewWebhook(co)
+
+ am := at.Alertmanager(fmt.Sprintf(conf, wh.Address()))
+
+ am.Push(At(1), Alert("alertname", "test1"))
+ at.Do(At(3), am.Reload)
+ am.Push(At(4), Alert("alertname", "test2"))
+
+ co.Want(Between(2, 2.5), Alert("alertname", "test1").Active(1))
+ // Timers are reset on reload regardless, so we count the 6 second group
+ // interval from 3 onwards.
+ co.Want(Between(9, 9.5),
+ Alert("alertname", "test1").Active(1),
+ Alert("alertname", "test2").Active(4),
+ )
+
+ at.Run()
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package test
+
+import (
+ "fmt"
+ "testing"
+ "time"
+
+ . "github.com/prometheus/alertmanager/test"
+)
+
+func TestSilencing(t *testing.T) {
+ t.Parallel()
+
+ conf := `
+route:
+ receiver: "default"
+ group_by: []
+ group_wait: 1s
+ group_interval: 1s
+ repeat_interval: 1ms
+
+receivers:
+- name: "default"
+ webhook_configs:
+ - url: 'http://%s'
+`
+
+ at := NewAcceptanceTest(t, &AcceptanceOpts{
+ Tolerance: 150 * time.Millisecond,
+ })
+
+ co := at.Collector("webhook")
+ wh := NewWebhook(co)
+
+ am := at.Alertmanager(fmt.Sprintf(conf, wh.Address()))
+
+ // No repeat interval is configured. Thus, we receive an alert
+ // notification every second.
+ am.Push(At(1), Alert("alertname", "test1").Active(1))
+ am.Push(At(1), Alert("alertname", "test2").Active(1))
+
+ co.Want(Between(2, 2.5),
+ Alert("alertname", "test1").Active(1),
+ Alert("alertname", "test2").Active(1),
+ )
+
+ // Add a silence that affects the first alert.
+ am.SetSilence(At(2.3), Silence(2.5, 4.5).Match("alertname", "test1"))
+
+ co.Want(Between(3, 3.5), Alert("alertname", "test2").Active(1))
+ co.Want(Between(4, 4.5), Alert("alertname", "test2").Active(1))
+
+ // Silence should be over now and we receive both alerts again.
+
+ co.Want(Between(5, 5.5),
+ Alert("alertname", "test1").Active(1),
+ Alert("alertname", "test2").Active(1),
+ )
+
+ at.Run()
+}
+
+func TestSilenceDelete(t *testing.T) {
+ t.Parallel()
+
+ conf := `
+route:
+ receiver: "default"
+ group_by: []
+ group_wait: 1s
+ group_interval: 1s
+ repeat_interval: 1ms
+
+receivers:
+- name: "default"
+ webhook_configs:
+ - url: 'http://%s'
+`
+
+ at := NewAcceptanceTest(t, &AcceptanceOpts{
+ Tolerance: 150 * time.Millisecond,
+ })
+
+ co := at.Collector("webhook")
+ wh := NewWebhook(co)
+
+ am := at.Alertmanager(fmt.Sprintf(conf, wh.Address()))
+
+ // No repeat interval is configured. Thus, we receive an alert
+ // notification every second.
+ am.Push(At(1), Alert("alertname", "test1").Active(1))
+ am.Push(At(1), Alert("alertname", "test2").Active(1))
+
+ // Silence everything for a long time and delete the silence after
+ // two iterations.
+ sil := Silence(1.5, 100).MatchRE("alertname", ".*")
+
+ am.SetSilence(At(1.3), sil)
+ am.DelSilence(At(3.5), sil)
+
+ co.Want(Between(3.5, 4.5),
+ Alert("alertname", "test1").Active(1),
+ Alert("alertname", "test2").Active(1),
+ )
+
+ at.Run()
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package test
+
+import (
+ "fmt"
+ "sync"
+ "testing"
+ "time"
+
+ "github.com/prometheus/common/model"
+)
+
+// Collector gathers alerts received by a notification receiver
+// and verifies whether all arrived and within the correct time boundaries.
+type Collector struct {
+ t *testing.T
+ name string
+ opts *AcceptanceOpts
+
+ collected map[float64][]model.Alerts
+ expected map[Interval][]model.Alerts
+
+ mtx sync.RWMutex
+}
+
+func (c *Collector) String() string {
+ return c.name
+}
+
+func batchesEqual(as, bs model.Alerts, opts *AcceptanceOpts) bool {
+ if len(as) != len(bs) {
+ return false
+ }
+
+ for _, a := range as {
+ found := false
+ for _, b := range bs {
+ if equalAlerts(a, b, opts) {
+ found = true
+ break
+ }
+ }
+ if !found {
+ return false
+ }
+ }
+ return true
+}
+
+// latest returns the latest relative point in time where a notification is
+// expected.
+func (c *Collector) latest() float64 {
+ c.mtx.RLock()
+ defer c.mtx.RUnlock()
+ var latest float64
+ for iv := range c.expected {
+ if iv.end > latest {
+ latest = iv.end
+ }
+ }
+ return latest
+}
+
+// Want declares that the Collector expects to receive the given alerts
+// within the given time boundaries.
+func (c *Collector) Want(iv Interval, alerts ...*TestAlert) {
+ c.mtx.Lock()
+ defer c.mtx.Unlock()
+ var nas model.Alerts
+ for _, a := range alerts {
+ nas = append(nas, a.nativeAlert(c.opts))
+ }
+
+ c.expected[iv] = append(c.expected[iv], nas)
+}
+
+// add the given alerts to the collected alerts.
+func (c *Collector) add(alerts ...*model.Alert) {
+ c.mtx.Lock()
+ defer c.mtx.Unlock()
+ arrival := c.opts.relativeTime(time.Now())
+
+ c.collected[arrival] = append(c.collected[arrival], model.Alerts(alerts))
+}
+
+func (c *Collector) check() string {
+ report := fmt.Sprintf("\ncollector %q:\n\n", c)
+
+ c.mtx.RLock()
+ defer c.mtx.RUnlock()
+ for iv, expected := range c.expected {
+ report += fmt.Sprintf("interval %v\n", iv)
+
+ var alerts []model.Alerts
+ for at, got := range c.collected {
+ if iv.contains(at) {
+ alerts = append(alerts, got...)
+ }
+ }
+
+ for _, exp := range expected {
+ found := len(exp) == 0 && len(alerts) == 0
+
+ report += fmt.Sprintf("---\n")
+
+ for _, e := range exp {
+ report += fmt.Sprintf("- %v\n", c.opts.alertString(e))
+ }
+
+ for _, a := range alerts {
+ if batchesEqual(exp, a, c.opts) {
+ found = true
+ break
+ }
+ }
+
+ if found {
+ report += fmt.Sprintf(" [ ✓ ]\n")
+ } else {
+ c.t.Fail()
+ report += fmt.Sprintf(" [ ✗ ]\n")
+ }
+ }
+ }
+
+ // Detect unexpected notifications.
+ var totalExp, totalAct int
+ for _, exp := range c.expected {
+ for _, e := range exp {
+ totalExp += len(e)
+ }
+ }
+ for _, act := range c.collected {
+ for _, a := range act {
+ if len(a) == 0 {
+ c.t.Error("received empty notifications")
+ }
+ totalAct += len(a)
+ }
+ }
+ if totalExp != totalAct {
+ c.t.Fail()
+ report += fmt.Sprintf("\nExpected total of %d alerts, got %d", totalExp, totalAct)
+ }
+
+ if c.t.Failed() {
+ report += "\nreceived:\n"
+
+ for at, col := range c.collected {
+ for _, alerts := range col {
+ report += fmt.Sprintf("@ %v\n", at)
+ for _, a := range alerts {
+ report += fmt.Sprintf("- %v\n", c.opts.alertString(a))
+ }
+ }
+ }
+ }
+
+ return report
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package test
+
+import (
+ "encoding/json"
+ "fmt"
+ "net"
+ "net/http"
+ "reflect"
+ "sync"
+ "time"
+
+ "github.com/prometheus/common/model"
+
+ "github.com/prometheus/alertmanager/notify"
+ "github.com/prometheus/alertmanager/types"
+)
+
+// At is a convenience method to allow for declarative syntax of Acceptance
+// test definitions.
+func At(ts float64) float64 {
+ return ts
+}
+
+type Interval struct {
+ start, end float64
+}
+
+func (iv Interval) String() string {
+ return fmt.Sprintf("[%v,%v]", iv.start, iv.end)
+}
+
+func (iv Interval) contains(f float64) bool {
+ return f >= iv.start && f <= iv.end
+}
+
+// Between is a convenience constructor for an interval for declarative syntax
+// of Acceptance test definitions.
+func Between(start, end float64) Interval {
+ return Interval{start: start, end: end}
+}
+
+// TestSilence models a model.Silence with relative times.
+type TestSilence struct {
+ id string
+ match []string
+ matchRE []string
+ startsAt, endsAt float64
+
+ mtx sync.RWMutex
+}
+
+// Silence creates a new TestSilence active for the relative interval given
+// by start and end.
+func Silence(start, end float64) *TestSilence {
+ return &TestSilence{
+ startsAt: start,
+ endsAt: end,
+ }
+}
+
+// Match adds a new plain matcher to the silence.
+func (s *TestSilence) Match(v ...string) *TestSilence {
+ s.match = append(s.match, v...)
+ return s
+}
+
+// MatchRE adds a new regex matcher to the silence
+func (s *TestSilence) MatchRE(v ...string) *TestSilence {
+ if len(v)%2 == 1 {
+ panic("bad key/values")
+ }
+ s.matchRE = append(s.matchRE, v...)
+ return s
+}
+
+// SetID sets the silence ID.
+func (s *TestSilence) SetID(ID string) {
+ s.mtx.Lock()
+ defer s.mtx.Unlock()
+ s.id = ID
+}
+
+// ID gets the silence ID.
+func (s *TestSilence) ID() string {
+ s.mtx.RLock()
+ defer s.mtx.RUnlock()
+ return s.id
+}
+
+// nativeSilence converts the declared test silence into a regular
+// silence with resolved times.
+func (s *TestSilence) nativeSilence(opts *AcceptanceOpts) *types.Silence {
+ nsil := &types.Silence{}
+
+ for i := 0; i < len(s.match); i += 2 {
+ nsil.Matchers = append(nsil.Matchers, &types.Matcher{
+ Name: s.match[i],
+ Value: s.match[i+1],
+ })
+ }
+ for i := 0; i < len(s.matchRE); i += 2 {
+ nsil.Matchers = append(nsil.Matchers, &types.Matcher{
+ Name: s.matchRE[i],
+ Value: s.matchRE[i+1],
+ IsRegex: true,
+ })
+ }
+
+ if s.startsAt > 0 {
+ nsil.StartsAt = opts.expandTime(s.startsAt)
+ }
+ if s.endsAt > 0 {
+ nsil.EndsAt = opts.expandTime(s.endsAt)
+ }
+ nsil.Comment = "some comment"
+ nsil.CreatedBy = "admin@example.com"
+
+ return nsil
+}
+
+// TestAlert models a model.Alert with relative times.
+type TestAlert struct {
+ labels model.LabelSet
+ annotations model.LabelSet
+ startsAt, endsAt float64
+}
+
+// Alert creates a new alert declaration with the given key/value pairs
+// as identifying labels.
+func Alert(keyval ...interface{}) *TestAlert {
+ if len(keyval)%2 == 1 {
+ panic("bad key/values")
+ }
+ a := &TestAlert{
+ labels: model.LabelSet{},
+ annotations: model.LabelSet{},
+ }
+
+ for i := 0; i < len(keyval); i += 2 {
+ ln := model.LabelName(keyval[i].(string))
+ lv := model.LabelValue(keyval[i+1].(string))
+
+ a.labels[ln] = lv
+ }
+
+ return a
+}
+
+// nativeAlert converts the declared test alert into a full alert based
+// on the given paramters.
+func (a *TestAlert) nativeAlert(opts *AcceptanceOpts) *model.Alert {
+ na := &model.Alert{
+ Labels: a.labels,
+ Annotations: a.annotations,
+ }
+
+ if a.startsAt > 0 {
+ na.StartsAt = opts.expandTime(a.startsAt)
+ }
+ if a.endsAt > 0 {
+ na.EndsAt = opts.expandTime(a.endsAt)
+ }
+ return na
+}
+
+// Annotate the alert with the given key/value pairs.
+func (a *TestAlert) Annotate(keyval ...interface{}) *TestAlert {
+ if len(keyval)%2 == 1 {
+ panic("bad key/values")
+ }
+
+ for i := 0; i < len(keyval); i += 2 {
+ ln := model.LabelName(keyval[i].(string))
+ lv := model.LabelValue(keyval[i+1].(string))
+
+ a.annotations[ln] = lv
+ }
+
+ return a
+}
+
+// Active declares the relative activity time for this alert. It
+// must be a single starting value or two values where the second value
+// declares the resolved time.
+func (a *TestAlert) Active(tss ...float64) *TestAlert {
+ if len(tss) > 2 || len(tss) == 0 {
+ panic("only one or two timestamps allowed")
+ }
+ if len(tss) == 2 {
+ a.endsAt = tss[1]
+ }
+ a.startsAt = tss[0]
+
+ return a
+}
+
+func equalAlerts(a, b *model.Alert, opts *AcceptanceOpts) bool {
+ if !reflect.DeepEqual(a.Labels, b.Labels) {
+ return false
+ }
+ if !reflect.DeepEqual(a.Annotations, b.Annotations) {
+ return false
+ }
+
+ if !equalTime(a.StartsAt, b.StartsAt, opts) {
+ return false
+ }
+ if !equalTime(a.EndsAt, b.EndsAt, opts) {
+ return false
+ }
+ return true
+}
+
+func equalTime(a, b time.Time, opts *AcceptanceOpts) bool {
+ if a.IsZero() != b.IsZero() {
+ return false
+ }
+
+ diff := a.Sub(b)
+ if diff < 0 {
+ diff = -diff
+ }
+ return diff <= opts.Tolerance
+}
+
+type MockWebhook struct {
+ opts *AcceptanceOpts
+ collector *Collector
+ listener net.Listener
+
+ Func func(timestamp float64) bool
+}
+
+func NewWebhook(c *Collector) *MockWebhook {
+ l, err := net.Listen("tcp4", "localhost:0")
+ if err != nil {
+ // TODO(fabxc): if shutdown of mock destinations ever becomes a concern
+ // we want to shut them down after test completion. Then we might want to
+ // log the error properly, too.
+ panic(err)
+ }
+ wh := &MockWebhook{
+ listener: l,
+ collector: c,
+ opts: c.opts,
+ }
+ go http.Serve(l, wh)
+
+ return wh
+}
+
+func (ws *MockWebhook) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ // Inject Func if it exists.
+ if ws.Func != nil {
+ if ws.Func(ws.opts.relativeTime(time.Now())) {
+ return
+ }
+ }
+
+ dec := json.NewDecoder(req.Body)
+ defer req.Body.Close()
+
+ var v notify.WebhookMessage
+ if err := dec.Decode(&v); err != nil {
+ panic(err)
+ }
+
+ // Transform the webhook message alerts back into model.Alerts.
+ var alerts model.Alerts
+ for _, a := range v.Alerts {
+ var (
+ labels = model.LabelSet{}
+ annotations = model.LabelSet{}
+ )
+ for k, v := range a.Labels {
+ labels[model.LabelName(k)] = model.LabelValue(v)
+ }
+ for k, v := range a.Annotations {
+ annotations[model.LabelName(k)] = model.LabelValue(v)
+ }
+
+ alerts = append(alerts, &model.Alert{
+ Labels: labels,
+ Annotations: annotations,
+ StartsAt: a.StartsAt,
+ EndsAt: a.EndsAt,
+ GeneratorURL: a.GeneratorURL,
+ })
+ }
+
+ ws.collector.add(alerts...)
+}
+
+func (ws *MockWebhook) Address() string {
+ return ws.listener.Addr().String()
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package types
+
+import (
+ "fmt"
+ "regexp"
+ "sort"
+
+ "bytes"
+
+ "github.com/prometheus/common/model"
+)
+
+// Matcher defines a matching rule for the value of a given label.
+type Matcher struct {
+ Name string `json:"name"`
+ Value string `json:"value"`
+ IsRegex bool `json:"isRegex"`
+
+ regex *regexp.Regexp
+}
+
+// Init internals of the Matcher. Must be called before using Match.
+func (m *Matcher) Init() error {
+ if !m.IsRegex {
+ return nil
+ }
+ re, err := regexp.Compile("^(?:" + m.Value + ")$")
+ if err == nil {
+ m.regex = re
+ }
+ return err
+}
+
+func (m *Matcher) String() string {
+ if m.IsRegex {
+ return fmt.Sprintf("%s=~%q", m.Name, m.Value)
+ }
+ return fmt.Sprintf("%s=%q", m.Name, m.Value)
+}
+
+// Validate returns true iff all fields of the matcher have valid values.
+func (m *Matcher) Validate() error {
+ if !model.LabelName(m.Name).IsValid() {
+ return fmt.Errorf("invalid name %q", m.Name)
+ }
+ if m.IsRegex {
+ if _, err := regexp.Compile(m.Value); err != nil {
+ return fmt.Errorf("invalid regular expression %q", m.Value)
+ }
+ } else if !model.LabelValue(m.Value).IsValid() || len(m.Value) == 0 {
+ return fmt.Errorf("invalid value %q", m.Value)
+ }
+ return nil
+}
+
+// Match checks whether the label of the matcher has the specified
+// matching value.
+func (m *Matcher) Match(lset model.LabelSet) bool {
+ // Unset labels are treated as unset labels globally. Thus, if a
+ // label is not set we retrieve the empty label which is correct
+ // for the comparison below.
+ v := lset[model.LabelName(m.Name)]
+
+ if m.IsRegex {
+ return m.regex.MatchString(string(v))
+ }
+ return string(v) == m.Value
+}
+
+// NewMatcher returns a new matcher that compares against equality of
+// the given value.
+func NewMatcher(name model.LabelName, value string) *Matcher {
+ return &Matcher{
+ Name: string(name),
+ Value: value,
+ IsRegex: false,
+ }
+}
+
+// NewRegexMatcher returns a new matcher that compares values against
+// a regular expression. The matcher is already initialized.
+//
+// TODO(fabxc): refactor usage.
+func NewRegexMatcher(name model.LabelName, re *regexp.Regexp) *Matcher {
+ return &Matcher{
+ Name: string(name),
+ Value: re.String(),
+ IsRegex: true,
+ regex: re,
+ }
+}
+
+// Matchers provides the Match and Fingerprint methods for a slice of Matchers.
+// Matchers must always be sorted.
+type Matchers []*Matcher
+
+// NewMatchers returns the given Matchers sorted.
+func NewMatchers(ms ...*Matcher) Matchers {
+ m := Matchers(ms)
+ sort.Sort(m)
+ return m
+}
+
+func (ms Matchers) Len() int { return len(ms) }
+func (ms Matchers) Swap(i, j int) { ms[i], ms[j] = ms[j], ms[i] }
+
+func (ms Matchers) Less(i, j int) bool {
+ if ms[i].Name > ms[j].Name {
+ return false
+ }
+ if ms[i].Name < ms[j].Name {
+ return true
+ }
+ if ms[i].Value > ms[j].Value {
+ return false
+ }
+ if ms[i].Value < ms[j].Value {
+ return true
+ }
+ return !ms[i].IsRegex && ms[j].IsRegex
+}
+
+// Equal returns whether both Matchers are equal.
+func (ms Matchers) Equal(o Matchers) bool {
+ if len(ms) != len(o) {
+ return false
+ }
+ for i, a := range ms {
+ if *a != *o[i] {
+ return false
+ }
+ }
+ return true
+}
+
+// Match checks whether all matchers are fulfilled against the given label set.
+func (ms Matchers) Match(lset model.LabelSet) bool {
+ for _, m := range ms {
+ if !m.Match(lset) {
+ return false
+ }
+ }
+ return true
+}
+
+func (ms Matchers) String() string {
+ var buf bytes.Buffer
+
+ buf.WriteByte('{')
+ for i, m := range ms {
+ if i > 0 {
+ buf.WriteByte(',')
+ }
+ buf.WriteString(m.String())
+ }
+ buf.WriteByte('}')
+
+ return buf.String()
+}
--- /dev/null
+// Copyright 2018 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package types
+
+import (
+ "fmt"
+ "regexp"
+ "testing"
+
+ "github.com/prometheus/common/model"
+ "github.com/stretchr/testify/require"
+)
+
+func TestMatcherValidate(t *testing.T) {
+
+ validLabelName := "valid_label_name"
+ validStringValue := "value"
+ validRegexValue := ".*"
+
+ invalidLabelName := "123_invalid_name"
+ invalidStringValue := ""
+ invalidRegexValue := "]*.["
+
+ tests := []struct {
+ matcher Matcher
+ valid bool
+ errorMsg string
+ }{
+ //valid tests
+ {
+ matcher: Matcher{Name: validLabelName, Value: validStringValue},
+ valid: true,
+ },
+ {
+ matcher: Matcher{Name: validLabelName, Value: validRegexValue, IsRegex: true},
+ valid: true,
+ },
+ // invalid tests
+ {
+ matcher: Matcher{Name: invalidLabelName, Value: validStringValue},
+ valid: false,
+ errorMsg: fmt.Sprintf("invalid name %q", invalidLabelName),
+ },
+ {
+ matcher: Matcher{Name: validLabelName, Value: invalidStringValue},
+ valid: false,
+ errorMsg: fmt.Sprintf("invalid value %q", invalidStringValue),
+ },
+ {
+ matcher: Matcher{Name: validLabelName, Value: invalidRegexValue, IsRegex: true},
+ valid: false,
+ errorMsg: fmt.Sprintf("invalid regular expression %q", invalidRegexValue),
+ },
+ }
+
+ for _, test := range tests {
+ test.matcher.Init()
+
+ if test.valid {
+ require.NoError(t, test.matcher.Validate())
+ continue
+ }
+
+ require.EqualError(t, test.matcher.Validate(), test.errorMsg)
+ }
+}
+
+func TestMatcherInit(t *testing.T) {
+ m := Matcher{Name: "label", Value: ".*", IsRegex: true}
+ require.NoError(t, m.Init())
+ require.EqualValues(t, "^(?:.*)$", m.regex.String())
+
+ m = Matcher{Name: "label", Value: "]*.[", IsRegex: true}
+ require.Error(t, m.Init())
+}
+
+func TestMatcherMatch(t *testing.T) {
+ tests := []struct {
+ matcher Matcher
+ expected bool
+ }{
+ {matcher: Matcher{Name: "label", Value: "value"}, expected: true},
+ {matcher: Matcher{Name: "label", Value: "val"}, expected: false},
+ {matcher: Matcher{Name: "label", Value: "val.*", IsRegex: true}, expected: true},
+ {matcher: Matcher{Name: "label", Value: "diffval.*", IsRegex: true}, expected: false},
+ //unset label
+ {matcher: Matcher{Name: "difflabel", Value: "value"}, expected: false},
+ }
+
+ lset := model.LabelSet{"label": "value"}
+ for _, test := range tests {
+ test.matcher.Init()
+
+ actual := test.matcher.Match(lset)
+ require.EqualValues(t, test.expected, actual)
+ }
+}
+
+func TestMatcherString(t *testing.T) {
+ m := NewMatcher("foo", "bar")
+
+ if m.String() != "foo=\"bar\"" {
+ t.Errorf("unexpected matcher string %#v", m.String())
+ }
+
+ re, err := regexp.Compile(".*")
+ if err != nil {
+ t.Errorf("unexpected error: %s", err)
+ }
+
+ m = NewRegexMatcher("foo", re)
+
+ if m.String() != "foo=~\".*\"" {
+ t.Errorf("unexpected matcher string %#v", m.String())
+ }
+}
+
+func TestMatchersString(t *testing.T) {
+ m1 := NewMatcher("foo", "bar")
+
+ re, err := regexp.Compile(".*")
+ if err != nil {
+ t.Errorf("unexpected error: %s", err)
+ }
+
+ m2 := NewRegexMatcher("bar", re)
+
+ matchers := NewMatchers(m1, m2)
+
+ if matchers.String() != "{bar=~\".*\",foo=\"bar\"}" {
+ t.Errorf("unexpected matcher string %#v", matchers.String())
+ }
+}
+
+func TestMatchersMatch(t *testing.T) {
+
+ m1 := &Matcher{Name: "label1", Value: "value1"}
+ m1.Init()
+ m2 := &Matcher{Name: "label2", Value: "val.*", IsRegex: true}
+ m2.Init()
+ m3 := &Matcher{Name: "label3", Value: "value3"}
+ m3.Init()
+
+ tests := []struct {
+ matchers Matchers
+ expected bool
+ }{
+ {matchers: Matchers{m1, m2}, expected: true},
+ {matchers: Matchers{m1, m3}, expected: false},
+ }
+
+ lset := model.LabelSet{"label1": "value1", "label2": "value2"}
+ for _, test := range tests {
+ actual := test.matchers.Match(lset)
+ require.EqualValues(t, test.expected, actual)
+ }
+}
+
+func TestMatchersEqual(t *testing.T) {
+
+ m1 := &Matcher{Name: "label1", Value: "value1"}
+ m1.Init()
+ m2 := &Matcher{Name: "label2", Value: "val.*", IsRegex: true}
+ m2.Init()
+ m3 := &Matcher{Name: "label3", Value: "value3"}
+ m3.Init()
+
+ tests := []struct {
+ matchers1 Matchers
+ matchers2 Matchers
+ expected bool
+ }{
+ {matchers1: Matchers{m1, m2}, matchers2: Matchers{m1, m2}, expected: true},
+ {matchers1: Matchers{m1, m3}, matchers2: Matchers{m1, m2}, expected: false},
+ }
+
+ for _, test := range tests {
+ actual := test.matchers1.Equal(test.matchers2)
+ require.EqualValues(t, test.expected, actual)
+ }
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package types
+
+import (
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/prometheus/common/model"
+)
+
+type AlertState string
+
+const (
+ AlertStateUnprocessed AlertState = "unprocessed"
+ AlertStateActive AlertState = "active"
+ AlertStateSuppressed AlertState = "suppressed"
+)
+
+// AlertStatus stores the state and values associated with an Alert.
+type AlertStatus struct {
+ State AlertState `json:"state"`
+ SilencedBy []string `json:"silencedBy"`
+ InhibitedBy []string `json:"inhibitedBy"`
+}
+
+// Marker helps to mark alerts as silenced and/or inhibited.
+// All methods are goroutine-safe.
+type Marker interface {
+ SetActive(alert model.Fingerprint)
+ SetInhibited(alert model.Fingerprint, ids ...string)
+ SetSilenced(alert model.Fingerprint, ids ...string)
+
+ Count(...AlertState) int
+
+ Status(model.Fingerprint) AlertStatus
+ Delete(model.Fingerprint)
+
+ Unprocessed(model.Fingerprint) bool
+ Active(model.Fingerprint) bool
+ Silenced(model.Fingerprint) ([]string, bool)
+ Inhibited(model.Fingerprint) ([]string, bool)
+}
+
+// NewMarker returns an instance of a Marker implementation.
+func NewMarker() Marker {
+ return &memMarker{
+ m: map[model.Fingerprint]*AlertStatus{},
+ }
+}
+
+type memMarker struct {
+ m map[model.Fingerprint]*AlertStatus
+
+ mtx sync.RWMutex
+}
+
+// Count alerts of a given state.
+func (m *memMarker) Count(states ...AlertState) int {
+ count := 0
+
+ m.mtx.RLock()
+ defer m.mtx.RUnlock()
+
+ if len(states) == 0 {
+ count = len(m.m)
+ } else {
+ for _, status := range m.m {
+ for _, state := range states {
+ if status.State == state {
+ count++
+ }
+ }
+ }
+ }
+ return count
+}
+
+// SetSilenced sets the AlertStatus to suppressed and stores the associated silence IDs.
+func (m *memMarker) SetSilenced(alert model.Fingerprint, ids ...string) {
+ m.mtx.Lock()
+
+ s, found := m.m[alert]
+ if !found {
+ s = &AlertStatus{}
+ m.m[alert] = s
+ }
+
+ // If there are any silence or alert IDs associated with the
+ // fingerprint, it is suppressed. Otherwise, set it to
+ // AlertStateUnprocessed.
+ if len(ids) == 0 && len(s.InhibitedBy) == 0 {
+ m.mtx.Unlock()
+ m.SetActive(alert)
+ return
+ }
+
+ s.State = AlertStateSuppressed
+ s.SilencedBy = ids
+
+ m.mtx.Unlock()
+}
+
+// SetInhibited sets the AlertStatus to suppressed and stores the associated alert IDs.
+func (m *memMarker) SetInhibited(alert model.Fingerprint, ids ...string) {
+ m.mtx.Lock()
+
+ s, found := m.m[alert]
+ if !found {
+ s = &AlertStatus{}
+ m.m[alert] = s
+ }
+
+ // If there are any silence or alert IDs associated with the
+ // fingerprint, it is suppressed. Otherwise, set it to
+ // AlertStateUnprocessed.
+ if len(ids) == 0 && len(s.SilencedBy) == 0 {
+ m.mtx.Unlock()
+ m.SetActive(alert)
+ return
+ }
+
+ s.State = AlertStateSuppressed
+ s.InhibitedBy = ids
+
+ m.mtx.Unlock()
+}
+
+func (m *memMarker) SetActive(alert model.Fingerprint) {
+ m.mtx.Lock()
+ defer m.mtx.Unlock()
+
+ s, found := m.m[alert]
+ if !found {
+ s = &AlertStatus{
+ SilencedBy: []string{},
+ InhibitedBy: []string{},
+ }
+ m.m[alert] = s
+ }
+
+ s.State = AlertStateActive
+ s.SilencedBy = []string{}
+ s.InhibitedBy = []string{}
+}
+
+// Status returns the AlertStatus for the given Fingerprint.
+func (m *memMarker) Status(alert model.Fingerprint) AlertStatus {
+ m.mtx.RLock()
+ defer m.mtx.RUnlock()
+
+ s, found := m.m[alert]
+ if !found {
+ s = &AlertStatus{
+ State: AlertStateUnprocessed,
+ SilencedBy: []string{},
+ InhibitedBy: []string{},
+ }
+ }
+ return *s
+}
+
+// Delete deletes the given Fingerprint from the internal cache.
+func (m *memMarker) Delete(alert model.Fingerprint) {
+ m.mtx.Lock()
+ defer m.mtx.Unlock()
+
+ delete(m.m, alert)
+}
+
+// Unprocessed returns whether the alert for the given Fingerprint is in the
+// Unprocessed state.
+func (m *memMarker) Unprocessed(alert model.Fingerprint) bool {
+ return m.Status(alert).State == AlertStateUnprocessed
+}
+
+// Active returns whether the alert for the given Fingerprint is in the Active
+// state.
+func (m *memMarker) Active(alert model.Fingerprint) bool {
+ return m.Status(alert).State == AlertStateActive
+}
+
+// Inhibited returns whether the alert for the given Fingerprint is in the
+// Inhibited state and any associated alert IDs.
+func (m *memMarker) Inhibited(alert model.Fingerprint) ([]string, bool) {
+ s := m.Status(alert)
+ return s.InhibitedBy,
+ s.State == AlertStateSuppressed && len(s.InhibitedBy) > 0
+}
+
+// Silenced returns whether the alert for the given Fingerprint is in the
+// Silenced state and any associated silence IDs.
+func (m *memMarker) Silenced(alert model.Fingerprint) ([]string, bool) {
+ s := m.Status(alert)
+ return s.SilencedBy,
+ s.State == AlertStateSuppressed && len(s.SilencedBy) > 0
+}
+
+// MultiError contains multiple errors and implements the error interface. Its
+// zero value is ready to use. All its methods are goroutine safe.
+type MultiError struct {
+ mtx sync.Mutex
+ errors []error
+}
+
+// Add adds an error to the MultiError.
+func (e *MultiError) Add(err error) {
+ e.mtx.Lock()
+ defer e.mtx.Unlock()
+
+ e.errors = append(e.errors, err)
+}
+
+// Len returns the number of errors added to the MultiError.
+func (e *MultiError) Len() int {
+ e.mtx.Lock()
+ defer e.mtx.Unlock()
+
+ return len(e.errors)
+}
+
+// Errors returns the errors added to the MuliError. The returned slice is a
+// copy of the internal slice of errors.
+func (e *MultiError) Errors() []error {
+ e.mtx.Lock()
+ defer e.mtx.Unlock()
+
+ return append(make([]error, 0, len(e.errors)), e.errors...)
+}
+
+func (e *MultiError) Error() string {
+ e.mtx.Lock()
+ defer e.mtx.Unlock()
+
+ es := make([]string, 0, len(e.errors))
+ for _, err := range e.errors {
+ es = append(es, err.Error())
+ }
+ return strings.Join(es, "; ")
+}
+
+// Alert wraps a model.Alert with additional information relevant
+// to internal of the Alertmanager.
+// The type is never exposed to external communication and the
+// embedded alert has to be sanitized beforehand.
+type Alert struct {
+ model.Alert
+
+ // The authoritative timestamp.
+ UpdatedAt time.Time
+ Timeout bool
+}
+
+// AlertSlice is a sortable slice of Alerts.
+type AlertSlice []*Alert
+
+func (as AlertSlice) Less(i, j int) bool {
+ // Look at labels.job, then labels.instance.
+ for _, overrideKey := range [...]model.LabelName{"job", "instance"} {
+ iVal, iOk := as[i].Labels[overrideKey]
+ jVal, jOk := as[j].Labels[overrideKey]
+ if !iOk && !jOk {
+ continue
+ }
+ if !iOk {
+ return false
+ }
+ if !jOk {
+ return true
+ }
+ if iVal != jVal {
+ return iVal < jVal
+ }
+ }
+ return as[i].Labels.Before(as[j].Labels)
+}
+func (as AlertSlice) Swap(i, j int) { as[i], as[j] = as[j], as[i] }
+func (as AlertSlice) Len() int { return len(as) }
+
+// Alerts turns a sequence of internal alerts into a list of
+// exposable model.Alert structures.
+func Alerts(alerts ...*Alert) model.Alerts {
+ res := make(model.Alerts, 0, len(alerts))
+ for _, a := range alerts {
+ v := a.Alert
+ // If the end timestamp was set as the expected value in case
+ // of a timeout but is not reached yet, do not expose it.
+ if a.Timeout && !a.Resolved() {
+ v.EndsAt = time.Time{}
+ }
+ res = append(res, &v)
+ }
+ return res
+}
+
+// Merge merges the timespan of two alerts based and overwrites annotations
+// based on the authoritative timestamp. A new alert is returned, the labels
+// are assumed to be equal.
+func (a *Alert) Merge(o *Alert) *Alert {
+ // Let o always be the younger alert.
+ if o.UpdatedAt.Before(a.UpdatedAt) {
+ return o.Merge(a)
+ }
+
+ res := *o
+
+ // Always pick the earliest starting time.
+ if a.StartsAt.Before(o.StartsAt) {
+ res.StartsAt = a.StartsAt
+ }
+
+ // A non-timeout resolved timestamp always rules.
+ // The latest explicit resolved timestamp wins.
+ if a.EndsAt.After(o.EndsAt) && !a.Timeout {
+ res.EndsAt = a.EndsAt
+ }
+
+ return &res
+}
+
+// A Muter determines whether a given label set is muted.
+type Muter interface {
+ Mutes(model.LabelSet) bool
+}
+
+// A MuteFunc is a function that implements the Muter interface.
+type MuteFunc func(model.LabelSet) bool
+
+// Mutes implements the Muter interface.
+func (f MuteFunc) Mutes(lset model.LabelSet) bool { return f(lset) }
+
+// A Silence determines whether a given label set is muted.
+type Silence struct {
+ // A unique identifier across all connected instances.
+ ID string `json:"id"`
+ // A set of matchers determining if a label set is affect
+ // by the silence.
+ Matchers Matchers `json:"matchers"`
+
+ // Time range of the silence.
+ //
+ // * StartsAt must not be before creation time
+ // * EndsAt must be after StartsAt
+ // * Deleting a silence means to set EndsAt to now
+ // * Time range must not be modified in different ways
+ //
+ // TODO(fabxc): this may potentially be extended by
+ // creation and update timestamps.
+ StartsAt time.Time `json:"startsAt"`
+ EndsAt time.Time `json:"endsAt"`
+
+ // The last time the silence was updated.
+ UpdatedAt time.Time `json:"updatedAt"`
+
+ // Information about who created the silence for which reason.
+ CreatedBy string `json:"createdBy"`
+ Comment string `json:"comment,omitempty"`
+
+ // timeFunc provides the time against which to evaluate
+ // the silence. Used for test injection.
+ now func() time.Time
+
+ Status SilenceStatus `json:"status"`
+}
+
+// Expired return if the silence is expired
+// meaning that both StartsAt and EndsAt are equal
+func (s *Silence) Expired() bool {
+ return s.StartsAt.Equal(s.EndsAt)
+}
+
+type SilenceStatus struct {
+ State SilenceState `json:"state"`
+}
+
+type SilenceState string
+
+const (
+ SilenceStateExpired SilenceState = "expired"
+ SilenceStateActive SilenceState = "active"
+ SilenceStatePending SilenceState = "pending"
+)
+
+func CalcSilenceState(start, end time.Time) SilenceState {
+ current := time.Now()
+ if current.Before(start) {
+ return SilenceStatePending
+ }
+ if current.Before(end) {
+ return SilenceStateActive
+ }
+ return SilenceStateExpired
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package types
+
+import (
+ "reflect"
+ "sort"
+ "testing"
+ "time"
+
+ "github.com/prometheus/common/model"
+ "github.com/stretchr/testify/require"
+)
+
+func TestAlertMerge(t *testing.T) {
+ now := time.Now()
+
+ pairs := []struct {
+ A, B, Res *Alert
+ }{
+ {
+ A: &Alert{
+ Alert: model.Alert{
+ StartsAt: now.Add(-time.Minute),
+ EndsAt: now.Add(2 * time.Minute),
+ },
+ UpdatedAt: now,
+ Timeout: true,
+ },
+ B: &Alert{
+ Alert: model.Alert{
+ StartsAt: now.Add(-time.Minute),
+ EndsAt: now.Add(3 * time.Minute),
+ },
+ UpdatedAt: now.Add(time.Minute),
+ Timeout: true,
+ },
+ Res: &Alert{
+ Alert: model.Alert{
+ StartsAt: now.Add(-time.Minute),
+ EndsAt: now.Add(3 * time.Minute),
+ },
+ UpdatedAt: now.Add(time.Minute),
+ Timeout: true,
+ },
+ },
+ }
+
+ for _, p := range pairs {
+ if res := p.A.Merge(p.B); !reflect.DeepEqual(p.Res, res) {
+ t.Errorf("unexpected merged alert %#v", res)
+ }
+ }
+}
+
+func TestCalcSilenceState(t *testing.T) {
+
+ var (
+ pastStartTime = time.Now()
+ pastEndTime = time.Now()
+
+ futureStartTime = time.Now().Add(time.Hour)
+ futureEndTime = time.Now().Add(time.Hour)
+ )
+
+ expected := CalcSilenceState(futureStartTime, futureEndTime)
+ require.Equal(t, SilenceStatePending, expected)
+
+ expected = CalcSilenceState(pastStartTime, futureEndTime)
+ require.Equal(t, SilenceStateActive, expected)
+
+ expected = CalcSilenceState(pastStartTime, pastEndTime)
+ require.Equal(t, SilenceStateExpired, expected)
+}
+
+func TestSilenceExpired(t *testing.T) {
+ now := time.Now()
+ silence := Silence{StartsAt: now, EndsAt: now}
+ require.True(t, silence.Expired())
+
+ silence = Silence{StartsAt: now.Add(time.Hour), EndsAt: now.Add(time.Hour)}
+ require.True(t, silence.Expired())
+
+ silence = Silence{StartsAt: now, EndsAt: now.Add(time.Hour)}
+ require.False(t, silence.Expired())
+}
+
+func TestAlertSliceSort(t *testing.T) {
+ var (
+ a1 = &Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{
+ "job": "j1",
+ "instance": "i1",
+ "alertname": "an1",
+ },
+ },
+ }
+ a2 = &Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{
+ "job": "j1",
+ "instance": "i1",
+ "alertname": "an2",
+ },
+ },
+ }
+ a3 = &Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{
+ "job": "j2",
+ "instance": "i1",
+ "alertname": "an1",
+ },
+ },
+ }
+ a4 = &Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{
+ "alertname": "an1",
+ },
+ },
+ }
+ a5 = &Alert{
+ Alert: model.Alert{
+ Labels: model.LabelSet{
+ "alertname": "an2",
+ },
+ },
+ }
+ )
+
+ cases := []struct {
+ alerts AlertSlice
+ exp AlertSlice
+ }{
+ {
+ alerts: AlertSlice{a2, a1},
+ exp: AlertSlice{a1, a2},
+ },
+ {
+ alerts: AlertSlice{a3, a2, a1},
+ exp: AlertSlice{a1, a2, a3},
+ },
+ {
+ alerts: AlertSlice{a4, a2, a4},
+ exp: AlertSlice{a2, a4, a4},
+ },
+ {
+ alerts: AlertSlice{a5, a4},
+ exp: AlertSlice{a4, a5},
+ },
+ }
+
+ for _, tc := range cases {
+ sort.Stable(tc.alerts)
+ if !reflect.DeepEqual(tc.alerts, tc.exp) {
+ t.Fatalf("expected %v but got %v", tc.exp, tc.alerts)
+ }
+ }
+}
--- /dev/null
+FROM node:6.10
+
+RUN npm install -g elm@0.18.0 elm-format@0.6.1-alpha elm-test@0.18.3 uglify-js@3.0.15
--- /dev/null
+dist/
+elm-stuff/
+script.js
--- /dev/null
+# Contributing
+
+This document describes how to:
+
+- Set up your dev environment
+- Become familiar with [Elm](http://elm-lang.org/)
+- Develop against AlertManager
+
+## Dev Environment Setup
+
+You can either use our default Docker setup or install all dev dependencies
+locally. For the former you only need Docker installed, for the latter you need
+to set the environment flag `NO_DOCKER` to `true` and have the following
+dependencies installed:
+
+- [Elm](https://guide.elm-lang.org/install.html#install)
+- [Elm-Format](https://github.com/avh4/elm-format) is installed
+
+In addition for easier development you
+can [configure](https://guide.elm-lang.org/install.html#configure-your-editor)
+your editor.
+
+**All submitted elm code must be formatted with `elm-format`**. Install and
+execute it however works best for you. We recommend having formatting the file
+on save, similar to how many developers use `gofmt`.
+
+If you prefer, there's a make target available to format all elm source files:
+
+```
+# make format
+```
+
+Once you've installed Elm, install the dependencies listed in
+`elm-package.json`:
+
+```
+# elm package install -y
+```
+
+## Elm Resources
+
+- The [Official Elm Guide](https://guide.elm-lang.org/) is a great place to
+ start. Going through the entire guide takes about an hour, and is a good
+ primer to get involved in our codebase. Once you've worked through it, you
+ should be able to start writing your feature with the help of the compiler.
+- Check the [syntax reference](http://elm-lang.org/docs/syntax) when you need a
+ reminder of how the language works.
+- Read up on [how to write elm code](http://elm-lang.org/docs/style-guide).
+- Watch videos from the
+ latest [elm-conf](https://www.youtube.com/channel/UCOpGiN9AkczVjlpGDaBwQrQ)
+- Learn how to use the debugger! Elm comes packaged with an excellent
+ [debugger](http://elm-lang.org/blog/the-perfect-bug-report). We've found this
+ tool to be invaluable in understanding how the app is working as we're
+ debugging behavior.
+
+## Local development workflow
+
+At the top level of this repo, follow the HA AlertManager instructions. Compile
+the binary, then run with `goreman`. Add example alerts with the file provided
+in the HA example folder. Then start the development server:
+
+```
+# cd ui/app
+# make dev-server
+```
+
+Your app should be available at `http://localhost:<port>`. Navigate to
+`src/Main.elm`. Any changes to the file system are detected automatically,
+triggering a recompile of the project.
+
+## Commiting changes
+
+Before you commit changes, please run `make build-all` on the root level
+Makefile. Please include `ui/bindata.go` in your commit.
--- /dev/null
+ELM_FILES := $(shell find src -iname *.elm)
+DOCKER_IMG :=elm-env
+DOCKER_CMD := docker run --rm -t -v $(PWD):/app -w /app $(DOCKER_IMG)
+# macOS requires mktemp template to be at the end of the filename.
+TEMPFILE := $(shell mktemp ./elm-XXXXXXXXXX)
+# --output flag for elm make must end in .js or .html.
+TEMPFILE_JS := "$(TEMPFILE).js"
+
+ifeq ($(NO_DOCKER), true)
+ DOCKER_CMD=
+endif
+
+all: test script.js
+
+elm-env:
+ @(if [ "$(NO_DOCKER)" != "true" ] ; then \
+ echo ">> building elm-env docker image"; \
+ docker build -t $(DOCKER_IMG) ../. > /dev/null; \
+ fi; )
+
+format: elm-env $(ELM_FILES)
+ @echo ">> format front-end code"
+ @$(DOCKER_CMD) elm-format --yes $(ELM_FILES)
+
+test: elm-env
+ @$(DOCKER_CMD) elm-format $(ELM_FILES) --validate
+ @$(DOCKER_CMD) elm-test
+
+dev-server:
+ elm-reactor
+
+script.js: elm-env format $(ELM_FILES)
+ @echo ">> building script.js"
+ @$(DOCKER_CMD) elm make src/Main.elm --yes --output $(TEMPFILE_JS)
+ @$(DOCKER_CMD) uglifyjs $(TEMPFILE_JS) --compress unused --mangle --output $(@)
+ @rm -rf $(TEMPFILE_JS)
+ @rm -rf $(TEMPFILE)
+
+clean:
+ - @rm script.js
+ - @docker rmi $(DOCKER_IMG)
--- /dev/null
+# Alertmanager UI
+
+This is a re-write of the Alertmanager UI in [elm-lang](http://elm-lang.org/).
+
+## Usage
+
+### Filtering on the alerts page
+
+By default, the alerts page only shows active (not silenced) alerts. Adding a
+query string containing the following will additionally show silenced alerts.
+
+```
+http://alertmanager/#/alerts?silenced=true
+```
+
+The alerts page can also be filtered by the receivers for a page. Receivers are
+configured in Alertmanager's yaml configuration file.
+
+```
+http://alertmanager/#/alerts?receiver=backend
+```
+
+Filtering based on label matchers is available. They can easily be added and
+modified through the UI.
+
+```
+http://alertmanager/#/alerts?filter=%7Bseverity%3D%22warning%22%2C%20owner%3D%22backend%22%7D
+```
+
+These filters can be used in conjunction.
+
+### Filtering on the silences page
+
+Filtering based on label matchers is available. They can easily be added and
+modified through the UI.
+
+```
+http://alertmanager/#/silences?filter=%7Bseverity%3D%22warning%22%2C%20owner%3D%22backend%22%7D
+```
+
+### Note on filtering via label matchers
+
+Filtering via label matchers follows the same syntax and semantics as Prometheus.
+
+A properly formatted filter is a set of label matchers joined by accepted
+matching operators, surrounded by curly braces:
+
+```
+{foo="bar", baz=~"quu.*"}
+```
+
+Operators include:
+
+- `=`
+- `!=`
+- `=~`
+- `!~`
+
+See the official documentation for additional information: https://prometheus.io/docs/querying/basics/#instant-vector-selectors
--- /dev/null
+{
+ "version": "1.0.0",
+ "summary": "Alertmanager UI",
+ "repository": "https://github.com/prometheus/alertmanager.git",
+ "license": "Apache-2.0",
+ "source-directories": [
+ "src"
+ ],
+ "exposed-modules": [],
+ "dependencies": {
+ "elm-lang/core": "5.0.0 <= v < 6.0.0",
+ "elm-lang/dom": "1.1.1 <= v < 2.0.0",
+ "elm-lang/html": "2.0.0 <= v < 3.0.0",
+ "elm-lang/http": "1.0.0 <= v < 2.0.0",
+ "elm-lang/navigation": "2.0.1 <= v < 3.0.0",
+ "elm-tools/parser": "2.0.0 <= v < 3.0.0",
+ "evancz/url-parser": "2.0.1 <= v < 3.0.0",
+ "jweir/elm-iso8601": "3.0.2 <= v < 4.0.0",
+ "krisajenkins/elm-dialog": "4.0.3 <= v < 5.0.0",
+ "rluiten/elm-date-extra": "8.5.0 <= v < 9.0.0"
+ },
+ "elm-version": "0.18.0 <= v < 0.19.0"
+}
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+ <title>Alertmanager</title>
+ </head>
+ <body>
+ <script>
+ // If there is no trailing slash at the end of the path in the url,
+ // add one. This ensures assets like script.js are loaded properly
+ if (window.location.pathname.substr(-1) != '/') {
+ window.location.pathname = window.location.pathname + '/';
+ console.log('added slash');
+ }
+ </script>
+ <script src="script.js"></script>
+ <script>
+ var app = Elm.Main.embed(document.body, { production: true, defaultCreator: window.localStorage.getItem('defaultCreator') });
+ app.ports.persistDefaultCreator.subscribe(function(name) {
+ window.localStorage.setItem('defaultCreator', name);
+ });
+ </script>
+ </body>
+</html>
--- /dev/null
+/*!
+ * Bootstrap v4.0.0-alpha.6 (https://getbootstrap.com)
+ * Copyright 2011-2017 The Bootstrap Authors
+ * Copyright 2011-2017 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ *//*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}template{display:none}[hidden]{display:none}@media print{*,::after,::before,blockquote::first-letter,blockquote::first-line,div::first-letter,div::first-line,li::first-letter,li::first-line,p::first-letter,p::first-line{text-shadow:none!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}html{-webkit-box-sizing:border-box;box-sizing:border-box}*,::after,::before{-webkit-box-sizing:inherit;box-sizing:inherit}@-ms-viewport{width:device-width}html{-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:1rem;font-weight:400;line-height:1.5;color:#292b2c;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{cursor:help}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}a{color:#0275d8;text-decoration:none}a:focus,a:hover{color:#014c8c;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle}[role=button]{cursor:pointer}[role=button],a,area,button,input,label,select,summary,textarea{-ms-touch-action:manipulation;touch-action:manipulation}table{border-collapse:collapse;background-color:transparent}caption{padding-top:.75rem;padding-bottom:.75rem;color:#636c72;text-align:left;caption-side:bottom}th{text-align:left}label{display:inline-block;margin-bottom:.5rem}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,select,textarea{line-height:inherit}input[type=checkbox]:disabled,input[type=radio]:disabled{cursor:not-allowed}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{-webkit-appearance:listbox}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit}input[type=search]{-webkit-appearance:none}output{display:inline-block}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.1}.display-2{font-size:5.5rem;font-weight:300;line-height:1.1}.display-3{font-size:4.5rem;font-weight:300;line-height:1.1}.display-4{font-size:3.5rem;font-weight:300;line-height:1.1}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:5px}.initialism{font-size:90%;text-transform:uppercase}.blockquote{padding:.5rem 1rem;margin-bottom:1rem;font-size:1.25rem;border-left:.25rem solid #eceeef}.blockquote-footer{display:block;font-size:80%;color:#636c72}.blockquote-footer::before{content:"\2014 \00A0"}.blockquote-reverse{padding-right:1rem;padding-left:0;text-align:right;border-right:.25rem solid #eceeef;border-left:0}.blockquote-reverse .blockquote-footer::before{content:""}.blockquote-reverse .blockquote-footer::after{content:"\00A0 \2014"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #ddd;border-radius:.25rem;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#636c72}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}code{padding:.2rem .4rem;font-size:90%;color:#bd4147;background-color:#f7f7f9;border-radius:.25rem}a>code{padding:0;color:inherit;background-color:inherit}kbd{padding:.2rem .4rem;font-size:90%;color:#fff;background-color:#292b2c;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;margin-top:0;margin-bottom:1rem;font-size:90%;color:#292b2c}pre code{padding:0;font-size:inherit;color:inherit;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{position:relative;margin-left:auto;margin-right:auto;padding-right:15px;padding-left:15px}@media (min-width:576px){.container{padding-right:15px;padding-left:15px}}@media (min-width:768px){.container{padding-right:15px;padding-left:15px}}@media (min-width:992px){.container{padding-right:15px;padding-left:15px}}@media (min-width:1200px){.container{padding-right:15px;padding-left:15px}}@media (min-width:576px){.container{width:540px;max-width:100%}}@media (min-width:768px){.container{width:720px;max-width:100%}}@media (min-width:992px){.container{width:960px;max-width:100%}}@media (min-width:1200px){.container{width:1140px;max-width:100%}}.container-fluid{position:relative;margin-left:auto;margin-right:auto;padding-right:15px;padding-left:15px}@media (min-width:576px){.container-fluid{padding-right:15px;padding-left:15px}}@media (min-width:768px){.container-fluid{padding-right:15px;padding-left:15px}}@media (min-width:992px){.container-fluid{padding-right:15px;padding-left:15px}}@media (min-width:1200px){.container-fluid{padding-right:15px;padding-left:15px}}.row{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}@media (min-width:576px){.row{margin-right:-15px;margin-left:-15px}}@media (min-width:768px){.row{margin-right:-15px;margin-left:-15px}}@media (min-width:992px){.row{margin-right:-15px;margin-left:-15px}}@media (min-width:1200px){.row{margin-right:-15px;margin-left:-15px}}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9{position:relative;width:100%;min-height:1px;padding-right:15px;padding-left:15px}@media (min-width:576px){.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9{padding-right:15px;padding-left:15px}}@media (min-width:768px){.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9{padding-right:15px;padding-left:15px}}@media (min-width:992px){.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9{padding-right:15px;padding-left:15px}}@media (min-width:1200px){.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9{padding-right:15px;padding-left:15px}}.col{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.col-1{-webkit-box-flex:0;-webkit-flex:0 0 8.333333%;-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-webkit-box-flex:0;-webkit-flex:0 0 16.666667%;-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-webkit-box-flex:0;-webkit-flex:0 0 33.333333%;-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-webkit-box-flex:0;-webkit-flex:0 0 41.666667%;-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-webkit-box-flex:0;-webkit-flex:0 0 58.333333%;-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-webkit-box-flex:0;-webkit-flex:0 0 66.666667%;-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-webkit-box-flex:0;-webkit-flex:0 0 83.333333%;-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-webkit-box-flex:0;-webkit-flex:0 0 91.666667%;-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.pull-0{right:auto}.pull-1{right:8.333333%}.pull-2{right:16.666667%}.pull-3{right:25%}.pull-4{right:33.333333%}.pull-5{right:41.666667%}.pull-6{right:50%}.pull-7{right:58.333333%}.pull-8{right:66.666667%}.pull-9{right:75%}.pull-10{right:83.333333%}.pull-11{right:91.666667%}.pull-12{right:100%}.push-0{left:auto}.push-1{left:8.333333%}.push-2{left:16.666667%}.push-3{left:25%}.push-4{left:33.333333%}.push-5{left:41.666667%}.push-6{left:50%}.push-7{left:58.333333%}.push-8{left:66.666667%}.push-9{left:75%}.push-10{left:83.333333%}.push-11{left:91.666667%}.push-12{left:100%}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.col-sm-1{-webkit-box-flex:0;-webkit-flex:0 0 8.333333%;-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-webkit-box-flex:0;-webkit-flex:0 0 16.666667%;-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-webkit-box-flex:0;-webkit-flex:0 0 33.333333%;-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-webkit-box-flex:0;-webkit-flex:0 0 41.666667%;-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-webkit-box-flex:0;-webkit-flex:0 0 58.333333%;-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-webkit-box-flex:0;-webkit-flex:0 0 66.666667%;-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-webkit-box-flex:0;-webkit-flex:0 0 83.333333%;-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-webkit-box-flex:0;-webkit-flex:0 0 91.666667%;-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.pull-sm-0{right:auto}.pull-sm-1{right:8.333333%}.pull-sm-2{right:16.666667%}.pull-sm-3{right:25%}.pull-sm-4{right:33.333333%}.pull-sm-5{right:41.666667%}.pull-sm-6{right:50%}.pull-sm-7{right:58.333333%}.pull-sm-8{right:66.666667%}.pull-sm-9{right:75%}.pull-sm-10{right:83.333333%}.pull-sm-11{right:91.666667%}.pull-sm-12{right:100%}.push-sm-0{left:auto}.push-sm-1{left:8.333333%}.push-sm-2{left:16.666667%}.push-sm-3{left:25%}.push-sm-4{left:33.333333%}.push-sm-5{left:41.666667%}.push-sm-6{left:50%}.push-sm-7{left:58.333333%}.push-sm-8{left:66.666667%}.push-sm-9{left:75%}.push-sm-10{left:83.333333%}.push-sm-11{left:91.666667%}.push-sm-12{left:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.col-md-1{-webkit-box-flex:0;-webkit-flex:0 0 8.333333%;-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-webkit-box-flex:0;-webkit-flex:0 0 16.666667%;-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-webkit-box-flex:0;-webkit-flex:0 0 33.333333%;-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-webkit-box-flex:0;-webkit-flex:0 0 41.666667%;-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-webkit-box-flex:0;-webkit-flex:0 0 58.333333%;-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-webkit-box-flex:0;-webkit-flex:0 0 66.666667%;-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-webkit-box-flex:0;-webkit-flex:0 0 83.333333%;-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-webkit-box-flex:0;-webkit-flex:0 0 91.666667%;-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.pull-md-0{right:auto}.pull-md-1{right:8.333333%}.pull-md-2{right:16.666667%}.pull-md-3{right:25%}.pull-md-4{right:33.333333%}.pull-md-5{right:41.666667%}.pull-md-6{right:50%}.pull-md-7{right:58.333333%}.pull-md-8{right:66.666667%}.pull-md-9{right:75%}.pull-md-10{right:83.333333%}.pull-md-11{right:91.666667%}.pull-md-12{right:100%}.push-md-0{left:auto}.push-md-1{left:8.333333%}.push-md-2{left:16.666667%}.push-md-3{left:25%}.push-md-4{left:33.333333%}.push-md-5{left:41.666667%}.push-md-6{left:50%}.push-md-7{left:58.333333%}.push-md-8{left:66.666667%}.push-md-9{left:75%}.push-md-10{left:83.333333%}.push-md-11{left:91.666667%}.push-md-12{left:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.col-lg-1{-webkit-box-flex:0;-webkit-flex:0 0 8.333333%;-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-webkit-box-flex:0;-webkit-flex:0 0 16.666667%;-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-webkit-box-flex:0;-webkit-flex:0 0 33.333333%;-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-webkit-box-flex:0;-webkit-flex:0 0 41.666667%;-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-webkit-box-flex:0;-webkit-flex:0 0 58.333333%;-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-webkit-box-flex:0;-webkit-flex:0 0 66.666667%;-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-webkit-box-flex:0;-webkit-flex:0 0 83.333333%;-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-webkit-box-flex:0;-webkit-flex:0 0 91.666667%;-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.pull-lg-0{right:auto}.pull-lg-1{right:8.333333%}.pull-lg-2{right:16.666667%}.pull-lg-3{right:25%}.pull-lg-4{right:33.333333%}.pull-lg-5{right:41.666667%}.pull-lg-6{right:50%}.pull-lg-7{right:58.333333%}.pull-lg-8{right:66.666667%}.pull-lg-9{right:75%}.pull-lg-10{right:83.333333%}.pull-lg-11{right:91.666667%}.pull-lg-12{right:100%}.push-lg-0{left:auto}.push-lg-1{left:8.333333%}.push-lg-2{left:16.666667%}.push-lg-3{left:25%}.push-lg-4{left:33.333333%}.push-lg-5{left:41.666667%}.push-lg-6{left:50%}.push-lg-7{left:58.333333%}.push-lg-8{left:66.666667%}.push-lg-9{left:75%}.push-lg-10{left:83.333333%}.push-lg-11{left:91.666667%}.push-lg-12{left:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.col-xl-1{-webkit-box-flex:0;-webkit-flex:0 0 8.333333%;-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-webkit-box-flex:0;-webkit-flex:0 0 16.666667%;-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-webkit-box-flex:0;-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-webkit-box-flex:0;-webkit-flex:0 0 33.333333%;-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-webkit-box-flex:0;-webkit-flex:0 0 41.666667%;-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-webkit-box-flex:0;-webkit-flex:0 0 58.333333%;-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-webkit-box-flex:0;-webkit-flex:0 0 66.666667%;-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-webkit-box-flex:0;-webkit-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-webkit-box-flex:0;-webkit-flex:0 0 83.333333%;-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-webkit-box-flex:0;-webkit-flex:0 0 91.666667%;-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-webkit-box-flex:0;-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.pull-xl-0{right:auto}.pull-xl-1{right:8.333333%}.pull-xl-2{right:16.666667%}.pull-xl-3{right:25%}.pull-xl-4{right:33.333333%}.pull-xl-5{right:41.666667%}.pull-xl-6{right:50%}.pull-xl-7{right:58.333333%}.pull-xl-8{right:66.666667%}.pull-xl-9{right:75%}.pull-xl-10{right:83.333333%}.pull-xl-11{right:91.666667%}.pull-xl-12{right:100%}.push-xl-0{left:auto}.push-xl-1{left:8.333333%}.push-xl-2{left:16.666667%}.push-xl-3{left:25%}.push-xl-4{left:33.333333%}.push-xl-5{left:41.666667%}.push-xl-6{left:50%}.push-xl-7{left:58.333333%}.push-xl-8{left:66.666667%}.push-xl-9{left:75%}.push-xl-10{left:83.333333%}.push-xl-11{left:91.666667%}.push-xl-12{left:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;max-width:100%;margin-bottom:1rem}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #eceeef}.table thead th{vertical-align:bottom;border-bottom:2px solid #eceeef}.table tbody+tbody{border-top:2px solid #eceeef}.table .table{background-color:#fff}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #eceeef}.table-bordered td,.table-bordered th{border:1px solid #eceeef}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{background-color:rgba(0,0,0,.075)}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table-success,.table-success>td,.table-success>th{background-color:#dff0d8}.table-hover .table-success:hover{background-color:#d0e9c6}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#d0e9c6}.table-info,.table-info>td,.table-info>th{background-color:#d9edf7}.table-hover .table-info:hover{background-color:#c4e3f3}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#c4e3f3}.table-warning,.table-warning>td,.table-warning>th{background-color:#fcf8e3}.table-hover .table-warning:hover{background-color:#faf2cc}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#faf2cc}.table-danger,.table-danger>td,.table-danger>th{background-color:#f2dede}.table-hover .table-danger:hover{background-color:#ebcccc}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#ebcccc}.thead-inverse th{color:#fff;background-color:#292b2c}.thead-default th{color:#464a4c;background-color:#eceeef}.table-inverse{color:#fff;background-color:#292b2c}.table-inverse td,.table-inverse th,.table-inverse thead th{border-color:#fff}.table-inverse.table-bordered{border:0}.table-responsive{display:block;width:100%;overflow-x:auto;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive.table-bordered{border:0}.form-control{display:block;width:100%;padding:.5rem .75rem;font-size:1rem;line-height:1.25;color:#464a4c;background-color:#fff;background-image:none;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s,-webkit-box-shadow ease-in-out .15s}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#464a4c;background-color:#fff;border-color:#5cb3fd;outline:0}.form-control::-webkit-input-placeholder{color:#636c72;opacity:1}.form-control::-moz-placeholder{color:#636c72;opacity:1}.form-control:-ms-input-placeholder{color:#636c72;opacity:1}.form-control::placeholder{color:#636c72;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#eceeef;opacity:1}.form-control:disabled{cursor:not-allowed}select.form-control:not([size]):not([multiple]){height:calc(2.25rem + 2px)}select.form-control:focus::-ms-value{color:#464a4c;background-color:#fff}.form-control-file,.form-control-range{display:block}.col-form-label{padding-top:calc(.5rem - 1px * 2);padding-bottom:calc(.5rem - 1px * 2);margin-bottom:0}.col-form-label-lg{padding-top:calc(.75rem - 1px * 2);padding-bottom:calc(.75rem - 1px * 2);font-size:1.25rem}.col-form-label-sm{padding-top:calc(.25rem - 1px * 2);padding-bottom:calc(.25rem - 1px * 2);font-size:.875rem}.col-form-legend{padding-top:.5rem;padding-bottom:.5rem;margin-bottom:0;font-size:1rem}.form-control-static{padding-top:.5rem;padding-bottom:.5rem;margin-bottom:0;line-height:1.25;border:solid transparent;border-width:1px 0}.form-control-static.form-control-lg,.form-control-static.form-control-sm,.input-group-lg>.form-control-static.form-control,.input-group-lg>.form-control-static.input-group-addon,.input-group-lg>.input-group-btn>.form-control-static.btn,.input-group-sm>.form-control-static.form-control,.input-group-sm>.form-control-static.input-group-addon,.input-group-sm>.input-group-btn>.form-control-static.btn{padding-right:0;padding-left:0}.form-control-sm,.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.input-group-sm>.input-group-btn>select.btn:not([size]):not([multiple]),.input-group-sm>select.form-control:not([size]):not([multiple]),.input-group-sm>select.input-group-addon:not([size]):not([multiple]),select.form-control-sm:not([size]):not([multiple]){height:1.8125rem}.form-control-lg,.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{padding:.75rem 1.5rem;font-size:1.25rem;border-radius:.3rem}.input-group-lg>.input-group-btn>select.btn:not([size]):not([multiple]),.input-group-lg>select.form-control:not([size]):not([multiple]),.input-group-lg>select.input-group-addon:not([size]):not([multiple]),select.form-control-lg:not([size]):not([multiple]){height:3.166667rem}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-check{position:relative;display:block;margin-bottom:.5rem}.form-check.disabled .form-check-label{color:#636c72;cursor:not-allowed}.form-check-label{padding-left:1.25rem;margin-bottom:0;cursor:pointer}.form-check-input{position:absolute;margin-top:.25rem;margin-left:-1.25rem}.form-check-input:only-child{position:static}.form-check-inline{display:inline-block}.form-check-inline .form-check-label{vertical-align:middle}.form-check-inline+.form-check-inline{margin-left:.75rem}.form-control-feedback{margin-top:.25rem}.form-control-danger,.form-control-success,.form-control-warning{padding-right:2.25rem;background-repeat:no-repeat;background-position:center right .5625rem;-webkit-background-size:1.125rem 1.125rem;background-size:1.125rem 1.125rem}.has-success .col-form-label,.has-success .custom-control,.has-success .form-check-label,.has-success .form-control-feedback,.has-success .form-control-label{color:#5cb85c}.has-success .form-control{border-color:#5cb85c}.has-success .input-group-addon{color:#5cb85c;border-color:#5cb85c;background-color:#eaf6ea}.has-success .form-control-success{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%235cb85c' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E")}.has-warning .col-form-label,.has-warning .custom-control,.has-warning .form-check-label,.has-warning .form-control-feedback,.has-warning .form-control-label{color:#f0ad4e}.has-warning .form-control{border-color:#f0ad4e}.has-warning .input-group-addon{color:#f0ad4e;border-color:#f0ad4e;background-color:#fff}.has-warning .form-control-warning{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23f0ad4e' d='M4.4 5.324h-.8v-2.46h.8zm0 1.42h-.8V5.89h.8zM3.76.63L.04 7.075c-.115.2.016.425.26.426h7.397c.242 0 .372-.226.258-.426C6.726 4.924 5.47 2.79 4.253.63c-.113-.174-.39-.174-.494 0z'/%3E%3C/svg%3E")}.has-danger .col-form-label,.has-danger .custom-control,.has-danger .form-check-label,.has-danger .form-control-feedback,.has-danger .form-control-label{color:#d9534f}.has-danger .form-control{border-color:#d9534f}.has-danger .input-group-addon{color:#d9534f;border-color:#d9534f;background-color:#fdf7f7}.has-danger .form-control-danger{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23d9534f' viewBox='-2 -2 7 7'%3E%3Cpath stroke='%23d9534f' d='M0 0l3 3m0-3L0 3'/%3E%3Ccircle r='.5'/%3E%3Ccircle cx='3' r='.5'/%3E%3Ccircle cy='3' r='.5'/%3E%3Ccircle cx='3' cy='3' r='.5'/%3E%3C/svg%3E")}.form-inline{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{width:auto}.form-inline .form-control-label{margin-bottom:0;vertical-align:middle}.form-inline .form-check{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;width:auto;margin-top:0;margin-bottom:0}.form-inline .form-check-label{padding-left:0}.form-inline .form-check-input{position:relative;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;padding-left:0}.form-inline .custom-control-indicator{position:static;display:inline-block;margin-right:.25rem;vertical-align:text-bottom}.form-inline .has-feedback .form-control-feedback{top:0}}.btn{display:inline-block;font-weight:400;line-height:1.25;text-align:center;white-space:nowrap;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid transparent;padding:.5rem 1rem;font-size:1rem;border-radius:.25rem;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.btn:focus,.btn:hover{text-decoration:none}.btn.focus,.btn:focus{outline:0;-webkit-box-shadow:0 0 0 2px rgba(2,117,216,.25);box-shadow:0 0 0 2px rgba(2,117,216,.25)}.btn.disabled,.btn:disabled{cursor:not-allowed;opacity:.65}.btn.active,.btn:active{background-image:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#0275d8;border-color:#0275d8}.btn-primary:hover{color:#fff;background-color:#025aa5;border-color:#01549b}.btn-primary.focus,.btn-primary:focus{-webkit-box-shadow:0 0 0 2px rgba(2,117,216,.5);box-shadow:0 0 0 2px rgba(2,117,216,.5)}.btn-primary.disabled,.btn-primary:disabled{background-color:#0275d8;border-color:#0275d8}.btn-primary.active,.btn-primary:active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#025aa5;background-image:none;border-color:#01549b}.btn-secondary{color:#292b2c;background-color:#fff;border-color:#ccc}.btn-secondary:hover{color:#292b2c;background-color:#e6e6e6;border-color:#adadad}.btn-secondary.focus,.btn-secondary:focus{-webkit-box-shadow:0 0 0 2px rgba(204,204,204,.5);box-shadow:0 0 0 2px rgba(204,204,204,.5)}.btn-secondary.disabled,.btn-secondary:disabled{background-color:#fff;border-color:#ccc}.btn-secondary.active,.btn-secondary:active,.show>.btn-secondary.dropdown-toggle{color:#292b2c;background-color:#e6e6e6;background-image:none;border-color:#adadad}.btn-info{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#2aabd2}.btn-info.focus,.btn-info:focus{-webkit-box-shadow:0 0 0 2px rgba(91,192,222,.5);box-shadow:0 0 0 2px rgba(91,192,222,.5)}.btn-info.disabled,.btn-info:disabled{background-color:#5bc0de;border-color:#5bc0de}.btn-info.active,.btn-info:active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#31b0d5;background-image:none;border-color:#2aabd2}.btn-success{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#419641}.btn-success.focus,.btn-success:focus{-webkit-box-shadow:0 0 0 2px rgba(92,184,92,.5);box-shadow:0 0 0 2px rgba(92,184,92,.5)}.btn-success.disabled,.btn-success:disabled{background-color:#5cb85c;border-color:#5cb85c}.btn-success.active,.btn-success:active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#449d44;background-image:none;border-color:#419641}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#f0ad4e}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#eb9316}.btn-warning.focus,.btn-warning:focus{-webkit-box-shadow:0 0 0 2px rgba(240,173,78,.5);box-shadow:0 0 0 2px rgba(240,173,78,.5)}.btn-warning.disabled,.btn-warning:disabled{background-color:#f0ad4e;border-color:#f0ad4e}.btn-warning.active,.btn-warning:active,.show>.btn-warning.dropdown-toggle{color:#fff;background-color:#ec971f;background-image:none;border-color:#eb9316}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d9534f}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#c12e2a}.btn-danger.focus,.btn-danger:focus{-webkit-box-shadow:0 0 0 2px rgba(217,83,79,.5);box-shadow:0 0 0 2px rgba(217,83,79,.5)}.btn-danger.disabled,.btn-danger:disabled{background-color:#d9534f;border-color:#d9534f}.btn-danger.active,.btn-danger:active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#c9302c;background-image:none;border-color:#c12e2a}.btn-outline-primary{color:#0275d8;background-image:none;background-color:transparent;border-color:#0275d8}.btn-outline-primary:hover{color:#fff;background-color:#0275d8;border-color:#0275d8}.btn-outline-primary.focus,.btn-outline-primary:focus{-webkit-box-shadow:0 0 0 2px rgba(2,117,216,.5);box-shadow:0 0 0 2px rgba(2,117,216,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#0275d8;background-color:transparent}.btn-outline-primary.active,.btn-outline-primary:active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#0275d8;border-color:#0275d8}.btn-outline-secondary{color:#ccc;background-image:none;background-color:transparent;border-color:#ccc}.btn-outline-secondary:hover{color:#fff;background-color:#ccc;border-color:#ccc}.btn-outline-secondary.focus,.btn-outline-secondary:focus{-webkit-box-shadow:0 0 0 2px rgba(204,204,204,.5);box-shadow:0 0 0 2px rgba(204,204,204,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#ccc;background-color:transparent}.btn-outline-secondary.active,.btn-outline-secondary:active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#ccc;border-color:#ccc}.btn-outline-info{color:#5bc0de;background-image:none;background-color:transparent;border-color:#5bc0de}.btn-outline-info:hover{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.btn-outline-info.focus,.btn-outline-info:focus{-webkit-box-shadow:0 0 0 2px rgba(91,192,222,.5);box-shadow:0 0 0 2px rgba(91,192,222,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#5bc0de;background-color:transparent}.btn-outline-info.active,.btn-outline-info:active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.btn-outline-success{color:#5cb85c;background-image:none;background-color:transparent;border-color:#5cb85c}.btn-outline-success:hover{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.btn-outline-success.focus,.btn-outline-success:focus{-webkit-box-shadow:0 0 0 2px rgba(92,184,92,.5);box-shadow:0 0 0 2px rgba(92,184,92,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#5cb85c;background-color:transparent}.btn-outline-success.active,.btn-outline-success:active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#5cb85c;border-color:#5cb85c}.btn-outline-warning{color:#f0ad4e;background-image:none;background-color:transparent;border-color:#f0ad4e}.btn-outline-warning:hover{color:#fff;background-color:#f0ad4e;border-color:#f0ad4e}.btn-outline-warning.focus,.btn-outline-warning:focus{-webkit-box-shadow:0 0 0 2px rgba(240,173,78,.5);box-shadow:0 0 0 2px rgba(240,173,78,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#f0ad4e;background-color:transparent}.btn-outline-warning.active,.btn-outline-warning:active,.show>.btn-outline-warning.dropdown-toggle{color:#fff;background-color:#f0ad4e;border-color:#f0ad4e}.btn-outline-danger{color:#d9534f;background-image:none;background-color:transparent;border-color:#d9534f}.btn-outline-danger:hover{color:#fff;background-color:#d9534f;border-color:#d9534f}.btn-outline-danger.focus,.btn-outline-danger:focus{-webkit-box-shadow:0 0 0 2px rgba(217,83,79,.5);box-shadow:0 0 0 2px rgba(217,83,79,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#d9534f;background-color:transparent}.btn-outline-danger.active,.btn-outline-danger:active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#d9534f;border-color:#d9534f}.btn-link{font-weight:400;color:#0275d8;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link:disabled{background-color:transparent}.btn-link,.btn-link:active,.btn-link:focus{border-color:transparent}.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#014c8c;text-decoration:underline;background-color:transparent}.btn-link:disabled{color:#636c72}.btn-link:disabled:focus,.btn-link:disabled:hover{text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:.75rem 1.5rem;font-size:1.25rem;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.show{opacity:1}.collapse{display:none}.collapse.show{display:block}tr.collapse.show{display:table-row}tbody.collapse.show{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.dropdown,.dropup{position:relative}.dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.3em;vertical-align:middle;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-left:.3em solid transparent}.dropdown-toggle:focus{outline:0}.dropup .dropdown-toggle::after{border-top:0;border-bottom:.3em solid}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#292b2c;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-divider{height:1px;margin:.5rem 0;overflow:hidden;background-color:#eceeef}.dropdown-item{display:block;width:100%;padding:3px 1.5rem;clear:both;font-weight:400;color:#292b2c;text-align:inherit;white-space:nowrap;background:0 0;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#1d1e1f;text-decoration:none;background-color:#f7f7f9}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#0275d8}.dropdown-item.disabled,.dropdown-item:disabled{color:#636c72;cursor:not-allowed;background-color:transparent}.show>.dropdown-menu{display:block}.show>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#636c72;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.dropup .dropdown-menu{top:auto;bottom:100%;margin-bottom:.125rem}.btn-group,.btn-group-vertical{position:relative;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-webkit-box-flex:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:2}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group,.btn-group-vertical .btn+.btn,.btn-group-vertical .btn+.btn-group,.btn-group-vertical .btn-group+.btn,.btn-group-vertical .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn+.dropdown-toggle-split::after{margin-left:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:1.125rem;padding-left:1.125rem}.btn-group-vertical{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.btn-group-vertical .btn,.btn-group-vertical .btn-group{width:100%}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%}.input-group .form-control{position:relative;z-index:2;-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;margin-bottom:0}.input-group .form-control:active,.input-group .form-control:focus,.input-group .form-control:hover{z-index:3}.input-group .form-control,.input-group-addon,.input-group-btn{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{white-space:nowrap;vertical-align:middle}.input-group-addon{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.25;color:#464a4c;text-align:center;background-color:#eceeef;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.input-group-addon.form-control-sm,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.input-group-addon.btn{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.input-group-addon.form-control-lg,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.input-group-addon.btn{padding:.75rem 1.5rem;font-size:1.25rem;border-radius:.3rem}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:not(:last-child),.input-group-addon:not(:last-child),.input-group-btn:not(:first-child)>.btn-group:not(:last-child)>.btn,.input-group-btn:not(:first-child)>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:not(:last-child)>.btn,.input-group-btn:not(:last-child)>.btn-group>.btn,.input-group-btn:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:not(:last-child){border-right:0}.input-group .form-control:not(:first-child),.input-group-addon:not(:first-child),.input-group-btn:not(:first-child)>.btn,.input-group-btn:not(:first-child)>.btn-group>.btn,.input-group-btn:not(:first-child)>.dropdown-toggle,.input-group-btn:not(:last-child)>.btn-group:not(:first-child)>.btn,.input-group-btn:not(:last-child)>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.form-control+.input-group-addon:not(:first-child){border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative;-webkit-box-flex:1;-webkit-flex:1 1 0%;-ms-flex:1 1 0%;flex:1 1 0%}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:3}.input-group-btn:not(:last-child)>.btn,.input-group-btn:not(:last-child)>.btn-group{margin-right:-1px}.input-group-btn:not(:first-child)>.btn,.input-group-btn:not(:first-child)>.btn-group{z-index:2;margin-left:-1px}.input-group-btn:not(:first-child)>.btn-group:active,.input-group-btn:not(:first-child)>.btn-group:focus,.input-group-btn:not(:first-child)>.btn-group:hover,.input-group-btn:not(:first-child)>.btn:active,.input-group-btn:not(:first-child)>.btn:focus,.input-group-btn:not(:first-child)>.btn:hover{z-index:3}.custom-control{position:relative;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;min-height:1.5rem;padding-left:1.5rem;margin-right:1rem;cursor:pointer}.custom-control-input{position:absolute;z-index:-1;opacity:0}.custom-control-input:checked~.custom-control-indicator{color:#fff;background-color:#0275d8}.custom-control-input:focus~.custom-control-indicator{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 3px #0275d8;box-shadow:0 0 0 1px #fff,0 0 0 3px #0275d8}.custom-control-input:active~.custom-control-indicator{color:#fff;background-color:#8fcafe}.custom-control-input:disabled~.custom-control-indicator{cursor:not-allowed;background-color:#eceeef}.custom-control-input:disabled~.custom-control-description{color:#636c72;cursor:not-allowed}.custom-control-indicator{position:absolute;top:.25rem;left:0;display:block;width:1rem;height:1rem;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#ddd;background-repeat:no-repeat;background-position:center center;-webkit-background-size:50% 50%;background-size:50% 50%}.custom-checkbox .custom-control-indicator{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-indicator{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-indicator{background-color:#0275d8;background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E")}.custom-radio .custom-control-indicator{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-indicator{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E")}.custom-controls-stacked{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.custom-controls-stacked .custom-control{margin-bottom:.25rem}.custom-controls-stacked .custom-control+.custom-control{margin-left:0}.custom-select{display:inline-block;max-width:100%;height:calc(2.25rem + 2px);padding:.375rem 1.75rem .375rem .75rem;line-height:1.25;color:#464a4c;vertical-align:middle;background:#fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23333' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right .75rem center;-webkit-background-size:8px 10px;background-size:8px 10px;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;-moz-appearance:none;-webkit-appearance:none}.custom-select:focus{border-color:#5cb3fd;outline:0}.custom-select:focus::-ms-value{color:#464a4c;background-color:#fff}.custom-select:disabled{color:#636c72;cursor:not-allowed;background-color:#eceeef}.custom-select::-ms-expand{opacity:0}.custom-select-sm{padding-top:.375rem;padding-bottom:.375rem;font-size:75%}.custom-file{position:relative;display:inline-block;max-width:100%;height:2.5rem;margin-bottom:0;cursor:pointer}.custom-file-input{min-width:14rem;max-width:100%;height:2.5rem;margin:0;filter:alpha(opacity=0);opacity:0}.custom-file-control{position:absolute;top:0;right:0;left:0;z-index:5;height:2.5rem;padding:.5rem 1rem;line-height:1.5;color:#464a4c;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#fff;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.custom-file-control:lang(en)::after{content:"Choose file..."}.custom-file-control::before{position:absolute;top:-1px;right:-1px;bottom:-1px;z-index:6;display:block;height:2.5rem;padding:.5rem 1rem;line-height:1.5;color:#464a4c;background-color:#eceeef;border:1px solid rgba(0,0,0,.15);border-radius:0 .25rem .25rem 0}.custom-file-control:lang(en)::before{content:"Browse"}.nav{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5em 1em}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#636c72;cursor:not-allowed}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-right-radius:.25rem;border-top-left-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#eceeef #eceeef #ddd}.nav-tabs .nav-link.disabled{color:#636c72;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#464a4c;background-color:#fff;border-color:#ddd #ddd #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-item.show .nav-link,.nav-pills .nav-link.active{color:#fff;cursor:default;background-color:#0275d8}.nav-fill .nav-item{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-webkit-box-flex:1;-webkit-flex:1 1 100%;-ms-flex:1 1 100%;flex:1 1 100%;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding:.5rem 1rem}.navbar-brand{display:inline-block;padding-top:.25rem;padding-bottom:.25rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-text{display:inline-block;padding-top:.425rem;padding-bottom:.425rem}.navbar-toggler{-webkit-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start;padding:.25rem .75rem;font-size:1.25rem;line-height:1;background:0 0;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;-webkit-background-size:100% 100%;background-size:100% 100%}.navbar-toggler-left{position:absolute;left:1rem}.navbar-toggler-right{position:absolute;right:1rem}@media (max-width:575px){.navbar-toggleable .navbar-nav .dropdown-menu{position:static;float:none}.navbar-toggleable>.container{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-toggleable{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.navbar-toggleable .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-toggleable .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-toggleable>.container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.navbar-toggleable .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;width:100%}.navbar-toggleable .navbar-toggler{display:none}}@media (max-width:767px){.navbar-toggleable-sm .navbar-nav .dropdown-menu{position:static;float:none}.navbar-toggleable-sm>.container{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-toggleable-sm{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.navbar-toggleable-sm .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-toggleable-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-toggleable-sm>.container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.navbar-toggleable-sm .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;width:100%}.navbar-toggleable-sm .navbar-toggler{display:none}}@media (max-width:991px){.navbar-toggleable-md .navbar-nav .dropdown-menu{position:static;float:none}.navbar-toggleable-md>.container{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-toggleable-md{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.navbar-toggleable-md .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-toggleable-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-toggleable-md>.container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.navbar-toggleable-md .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;width:100%}.navbar-toggleable-md .navbar-toggler{display:none}}@media (max-width:1199px){.navbar-toggleable-lg .navbar-nav .dropdown-menu{position:static;float:none}.navbar-toggleable-lg>.container{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-toggleable-lg{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.navbar-toggleable-lg .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-toggleable-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-toggleable-lg>.container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.navbar-toggleable-lg .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;width:100%}.navbar-toggleable-lg .navbar-toggler{display:none}}.navbar-toggleable-xl{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.navbar-toggleable-xl .navbar-nav .dropdown-menu{position:static;float:none}.navbar-toggleable-xl>.container{padding-right:0;padding-left:0}.navbar-toggleable-xl .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar-toggleable-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-toggleable-xl>.container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.navbar-toggleable-xl .navbar-collapse{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important;width:100%}.navbar-toggleable-xl .navbar-toggler{display:none}.navbar-light .navbar-brand,.navbar-light .navbar-toggler{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover,.navbar-light .navbar-toggler:focus,.navbar-light .navbar-toggler:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.open,.navbar-light .navbar-nav .open>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-toggler{color:#fff}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-toggler:focus,.navbar-inverse .navbar-toggler:hover{color:#fff}.navbar-inverse .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-inverse .navbar-nav .nav-link:focus,.navbar-inverse .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-inverse .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-inverse .navbar-nav .active>.nav-link,.navbar-inverse .navbar-nav .nav-link.active,.navbar-inverse .navbar-nav .nav-link.open,.navbar-inverse .navbar-nav .open>.nav-link{color:#fff}.navbar-inverse .navbar-toggler{border-color:rgba(255,255,255,.1)}.navbar-inverse .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E")}.navbar-inverse .navbar-text{color:rgba(255,255,255,.5)}.card{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;background-color:#fff;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card-block{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card>.list-group:first-child .list-group-item:first-child{border-top-right-radius:.25rem;border-top-left-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:#f7f7f9;border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{padding:.75rem 1.25rem;background-color:#f7f7f9;border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-primary{background-color:#0275d8;border-color:#0275d8}.card-primary .card-footer,.card-primary .card-header{background-color:transparent}.card-success{background-color:#5cb85c;border-color:#5cb85c}.card-success .card-footer,.card-success .card-header{background-color:transparent}.card-info{background-color:#5bc0de;border-color:#5bc0de}.card-info .card-footer,.card-info .card-header{background-color:transparent}.card-warning{background-color:#f0ad4e;border-color:#f0ad4e}.card-warning .card-footer,.card-warning .card-header{background-color:transparent}.card-danger{background-color:#d9534f;border-color:#d9534f}.card-danger .card-footer,.card-danger .card-header{background-color:transparent}.card-outline-primary{background-color:transparent;border-color:#0275d8}.card-outline-secondary{background-color:transparent;border-color:#ccc}.card-outline-info{background-color:transparent;border-color:#5bc0de}.card-outline-success{background-color:transparent;border-color:#5cb85c}.card-outline-warning{background-color:transparent;border-color:#f0ad4e}.card-outline-danger{background-color:transparent;border-color:#d9534f}.card-inverse{color:rgba(255,255,255,.65)}.card-inverse .card-footer,.card-inverse .card-header{background-color:transparent;border-color:rgba(255,255,255,.2)}.card-inverse .card-blockquote,.card-inverse .card-footer,.card-inverse .card-header,.card-inverse .card-title{color:#fff}.card-inverse .card-blockquote .blockquote-footer,.card-inverse .card-link,.card-inverse .card-subtitle,.card-inverse .card-text{color:rgba(255,255,255,.65)}.card-inverse .card-link:focus,.card-inverse .card-link:hover{color:#fff}.card-blockquote{padding:0;margin-bottom:0;border-left:0}.card-img{border-radius:calc(.25rem - 1px)}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img-top{border-top-right-radius:calc(.25rem - 1px);border-top-left-radius:calc(.25rem - 1px)}.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}@media (min-width:576px){.card-deck{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-deck .card{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1 0 0%;-ms-flex:1 0 0%;flex:1 0 0%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.card-deck .card:not(:first-child){margin-left:15px}.card-deck .card:not(:last-child){margin-right:15px}}@media (min-width:576px){.card-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group .card{-webkit-box-flex:1;-webkit-flex:1 0 0%;-ms-flex:1 0 0%;flex:1 0 0%}.card-group .card+.card{margin-left:0;border-left:0}.card-group .card:first-child{border-bottom-right-radius:0;border-top-right-radius:0}.card-group .card:first-child .card-img-top{border-top-right-radius:0}.card-group .card:first-child .card-img-bottom{border-bottom-right-radius:0}.card-group .card:last-child{border-bottom-left-radius:0;border-top-left-radius:0}.card-group .card:last-child .card-img-top{border-top-left-radius:0}.card-group .card:last-child .card-img-bottom{border-bottom-left-radius:0}.card-group .card:not(:first-child):not(:last-child){border-radius:0}.card-group .card:not(:first-child):not(:last-child) .card-img-bottom,.card-group .card:not(:first-child):not(:last-child) .card-img-top{border-radius:0}}@media (min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem}.card-columns .card{display:inline-block;width:100%;margin-bottom:.75rem}}.breadcrumb{padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#eceeef;border-radius:.25rem}.breadcrumb::after{display:block;content:"";clear:both}.breadcrumb-item{float:left}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;padding-left:.5rem;color:#636c72;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#636c72}.pagination{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-item:first-child .page-link{margin-left:0;border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.page-item:last-child .page-link{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.page-item.active .page-link{z-index:2;color:#fff;background-color:#0275d8;border-color:#0275d8}.page-item.disabled .page-link{color:#636c72;pointer-events:none;cursor:not-allowed;background-color:#fff;border-color:#ddd}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#0275d8;background-color:#fff;border:1px solid #ddd}.page-link:focus,.page-link:hover{color:#014c8c;text-decoration:none;background-color:#eceeef;border-color:#ddd}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem}.pagination-lg .page-item:first-child .page-link{border-bottom-left-radius:.3rem;border-top-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-bottom-right-radius:.3rem;border-top-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem}.pagination-sm .page-item:first-child .page-link{border-bottom-left-radius:.2rem;border-top-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-bottom-right-radius:.2rem;border-top-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-default{background-color:#636c72}.badge-default[href]:focus,.badge-default[href]:hover{background-color:#4b5257}.badge-primary{background-color:#0275d8}.badge-primary[href]:focus,.badge-primary[href]:hover{background-color:#025aa5}.badge-success{background-color:#5cb85c}.badge-success[href]:focus,.badge-success[href]:hover{background-color:#449d44}.badge-info{background-color:#5bc0de}.badge-info[href]:focus,.badge-info[href]:hover{background-color:#31b0d5}.badge-warning{background-color:#f0ad4e}.badge-warning[href]:focus,.badge-warning[href]:hover{background-color:#ec971f}.badge-danger{background-color:#d9534f}.badge-danger[href]:focus,.badge-danger[href]:hover{background-color:#c9302c}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#eceeef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-hr{border-top-color:#d0d5d8}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible .close{position:relative;top:-.75rem;right:-1.25rem;padding:.75rem 1.25rem;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d0e9c6;color:#3c763d}.alert-success hr{border-top-color:#c1e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bcdff1;color:#31708f}.alert-info hr{border-top-color:#a6d5ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faf2cc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7ecb5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebcccc;color:#a94442}.alert-danger hr{border-top-color:#e4b9b9}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;overflow:hidden;font-size:.75rem;line-height:1rem;text-align:center;background-color:#eceeef;border-radius:.25rem}.progress-bar{height:1rem;color:#fff;background-color:#0275d8}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:1rem 1rem;background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;-o-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}.media{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start}.media-body{-webkit-box-flex:1;-webkit-flex:1 1 0%;-ms-flex:1 1 0%;flex:1 1 0%}.list-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.list-group-item-action{width:100%;color:#464a4c;text-align:inherit}.list-group-item-action .list-group-item-heading{color:#292b2c}.list-group-item-action:focus,.list-group-item-action:hover{color:#464a4c;text-decoration:none;background-color:#f7f7f9}.list-group-item-action:active{color:#292b2c;background-color:#eceeef}.list-group-item{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;padding:.75rem 1.25rem;margin-bottom:-1px;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-right-radius:.25rem;border-top-left-radius:.25rem}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.list-group-item:focus,.list-group-item:hover{text-decoration:none}.list-group-item.disabled,.list-group-item:disabled{color:#636c72;cursor:not-allowed;background-color:#fff}.list-group-item.disabled .list-group-item-heading,.list-group-item:disabled .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item:disabled .list-group-item-text{color:#636c72}.list-group-item.active{z-index:2;color:#fff;background-color:#0275d8;border-color:#0275d8}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text{color:#daeeff}.list-group-flush .list-group-item{border-right:0;border-left:0;border-radius:0}.list-group-flush:first-child .list-group-item:first-child{border-top:0}.list-group-flush:last-child .list-group-item:last-child{border-bottom:0}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,button.list-group-item-success.active{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,button.list-group-item-info.active{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,button.list-group-item-warning.active{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,button.list-group-item-danger.active{color:#fff;background-color:#a94442;border-color:#a94442}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.75}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out,-o-transform .3s ease-out;-webkit-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.show .modal-dialog{-webkit-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;padding:15px;border-bottom:1px solid #eceeef}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;padding:15px}.modal-footer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;padding:15px;border-top:1px solid #eceeef}.modal-footer>:not(:first-child){margin-left:.25rem}.modal-footer>:not(:last-child){margin-right:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:30px auto}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg{max-width:800px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip.bs-tether-element-attached-bottom,.tooltip.tooltip-top{padding:5px 0;margin-top:-3px}.tooltip.bs-tether-element-attached-bottom .tooltip-inner::before,.tooltip.tooltip-top .tooltip-inner::before{bottom:0;left:50%;margin-left:-5px;content:"";border-width:5px 5px 0;border-top-color:#000}.tooltip.bs-tether-element-attached-left,.tooltip.tooltip-right{padding:0 5px;margin-left:3px}.tooltip.bs-tether-element-attached-left .tooltip-inner::before,.tooltip.tooltip-right .tooltip-inner::before{top:50%;left:0;margin-top:-5px;content:"";border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.bs-tether-element-attached-top,.tooltip.tooltip-bottom{padding:5px 0;margin-top:3px}.tooltip.bs-tether-element-attached-top .tooltip-inner::before,.tooltip.tooltip-bottom .tooltip-inner::before{top:0;left:50%;margin-left:-5px;content:"";border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bs-tether-element-attached-right,.tooltip.tooltip-left{padding:0 5px;margin-left:-3px}.tooltip.bs-tether-element-attached-right .tooltip-inner::before,.tooltip.tooltip-left .tooltip-inner::before{top:50%;right:0;margin-top:-5px;content:"";border-width:5px 0 5px 5px;border-left-color:#000}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.tooltip-inner::before{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;padding:1px;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;font-size:.875rem;word-wrap:break-word;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover.bs-tether-element-attached-bottom,.popover.popover-top{margin-top:-10px}.popover.bs-tether-element-attached-bottom::after,.popover.bs-tether-element-attached-bottom::before,.popover.popover-top::after,.popover.popover-top::before{left:50%;border-bottom-width:0}.popover.bs-tether-element-attached-bottom::before,.popover.popover-top::before{bottom:-11px;margin-left:-11px;border-top-color:rgba(0,0,0,.25)}.popover.bs-tether-element-attached-bottom::after,.popover.popover-top::after{bottom:-10px;margin-left:-10px;border-top-color:#fff}.popover.bs-tether-element-attached-left,.popover.popover-right{margin-left:10px}.popover.bs-tether-element-attached-left::after,.popover.bs-tether-element-attached-left::before,.popover.popover-right::after,.popover.popover-right::before{top:50%;border-left-width:0}.popover.bs-tether-element-attached-left::before,.popover.popover-right::before{left:-11px;margin-top:-11px;border-right-color:rgba(0,0,0,.25)}.popover.bs-tether-element-attached-left::after,.popover.popover-right::after{left:-10px;margin-top:-10px;border-right-color:#fff}.popover.bs-tether-element-attached-top,.popover.popover-bottom{margin-top:10px}.popover.bs-tether-element-attached-top::after,.popover.bs-tether-element-attached-top::before,.popover.popover-bottom::after,.popover.popover-bottom::before{left:50%;border-top-width:0}.popover.bs-tether-element-attached-top::before,.popover.popover-bottom::before{top:-11px;margin-left:-11px;border-bottom-color:rgba(0,0,0,.25)}.popover.bs-tether-element-attached-top::after,.popover.popover-bottom::after{top:-10px;margin-left:-10px;border-bottom-color:#f7f7f7}.popover.bs-tether-element-attached-top .popover-title::before,.popover.popover-bottom .popover-title::before{position:absolute;top:0;left:50%;display:block;width:20px;margin-left:-10px;content:"";border-bottom:1px solid #f7f7f7}.popover.bs-tether-element-attached-right,.popover.popover-left{margin-left:-10px}.popover.bs-tether-element-attached-right::after,.popover.bs-tether-element-attached-right::before,.popover.popover-left::after,.popover.popover-left::before{top:50%;border-right-width:0}.popover.bs-tether-element-attached-right::before,.popover.popover-left::before{right:-11px;margin-top:-11px;border-left-color:rgba(0,0,0,.25)}.popover.bs-tether-element-attached-right::after,.popover.popover-left::after{right:-10px;margin-top:-10px;border-left-color:#fff}.popover-title{padding:8px 14px;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-right-radius:calc(.3rem - 1px);border-top-left-radius:calc(.3rem - 1px)}.popover-title:empty{display:none}.popover-content{padding:9px 14px}.popover::after,.popover::before{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover::before{content:"";border-width:11px}.popover::after{content:"";border-width:10px}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-item{position:relative;display:none;width:100%}@media (-webkit-transform-3d){.carousel-item{-webkit-transition:-webkit-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out,-o-transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}}@supports ((-webkit-transform:translate3d(0,0,0)) or (transform:translate3d(0,0,0))){.carousel-item{-webkit-transition:-webkit-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out,-o-transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.carousel-item-next,.carousel-item-prev{position:absolute;top:0}@media (-webkit-transform-3d){.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.active.carousel-item-right,.carousel-item-next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.active.carousel-item-left,.carousel-item-prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}@supports ((-webkit-transform:translate3d(0,0,0)) or (transform:translate3d(0,0,0))){.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.active.carousel-item-right,.carousel-item-next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.active.carousel-item-left,.carousel-item-prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:transparent no-repeat center center;-webkit-background-size:100% 100%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M4 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E")}.carousel-control-next-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M1.5 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E")}.carousel-indicators{position:absolute;right:0;bottom:10px;left:0;z-index:15;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{position:relative;-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;max-width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:rgba(255,255,255,.5)}.carousel-indicators li::before{position:absolute;top:-10px;left:0;display:inline-block;width:100%;height:10px;content:""}.carousel-indicators li::after{position:absolute;bottom:-10px;left:0;display:inline-block;width:100%;height:10px;content:""}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-faded{background-color:#f7f7f7}.bg-primary{background-color:#0275d8!important}a.bg-primary:focus,a.bg-primary:hover{background-color:#025aa5!important}.bg-success{background-color:#5cb85c!important}a.bg-success:focus,a.bg-success:hover{background-color:#449d44!important}.bg-info{background-color:#5bc0de!important}a.bg-info:focus,a.bg-info:hover{background-color:#31b0d5!important}.bg-warning{background-color:#f0ad4e!important}a.bg-warning:focus,a.bg-warning:hover{background-color:#ec971f!important}.bg-danger{background-color:#d9534f!important}a.bg-danger:focus,a.bg-danger:hover{background-color:#c9302c!important}.bg-inverse{background-color:#292b2c!important}a.bg-inverse:focus,a.bg-inverse:hover{background-color:#101112!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.rounded{border-radius:.25rem}.rounded-top{border-top-right-radius:.25rem;border-top-left-radius:.25rem}.rounded-right{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.rounded-bottom{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.rounded-left{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.rounded-circle{border-radius:50%}.rounded-0{border-radius:0}.clearfix::after{display:block;content:"";clear:both}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-cell{display:table-cell!important}.d-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-webkit-box!important;display:-webkit-flex!important;display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}.flex-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.flex-last{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.flex-unordered{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.flex-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;-ms-grid-row-align:auto!important;align-self:auto!important}.align-self-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;-ms-grid-row-align:center!important;align-self:center!important}.align-self-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;-ms-grid-row-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.flex-sm-last{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.flex-sm-unordered{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.flex-sm-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-sm-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;-ms-grid-row-align:auto!important;align-self:auto!important}.align-self-sm-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;-ms-grid-row-align:center!important;align-self:center!important}.align-self-sm-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;-ms-grid-row-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.flex-md-last{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.flex-md-unordered{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.flex-md-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-md-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;-ms-grid-row-align:auto!important;align-self:auto!important}.align-self-md-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;-ms-grid-row-align:center!important;align-self:center!important}.align-self-md-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;-ms-grid-row-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.flex-lg-last{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.flex-lg-unordered{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.flex-lg-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-lg-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;-ms-grid-row-align:auto!important;align-self:auto!important}.align-self-lg-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;-ms-grid-row-align:center!important;align-self:center!important}.align-self-lg-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;-ms-grid-row-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.flex-xl-last{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.flex-xl-unordered{-webkit-box-ordinal-group:1;-webkit-order:0;-ms-flex-order:0;order:0}.flex-xl-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-webkit-flex-direction:row!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-webkit-flex-direction:column!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-webkit-flex-wrap:wrap!important;-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-webkit-flex-wrap:nowrap!important;-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-webkit-flex-wrap:wrap-reverse!important;-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-xl-start{-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-webkit-box-pack:center!important;-webkit-justify-content:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-webkit-justify-content:space-around!important;-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-webkit-box-align:start!important;-webkit-align-items:flex-start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-webkit-box-align:end!important;-webkit-align-items:flex-end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-webkit-box-align:center!important;-webkit-align-items:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-webkit-align-content:flex-start!important;-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-webkit-align-content:flex-end!important;-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-webkit-align-content:center!important;-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-webkit-align-content:space-between!important;-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-webkit-align-content:space-around!important;-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-webkit-align-content:stretch!important;-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-webkit-align-self:auto!important;-ms-flex-item-align:auto!important;-ms-grid-row-align:auto!important;align-self:auto!important}.align-self-xl-start{-webkit-align-self:flex-start!important;-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-webkit-align-self:flex-end!important;-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-webkit-align-self:center!important;-ms-flex-item-align:center!important;-ms-grid-row-align:center!important;align-self:center!important}.align-self-xl-baseline{-webkit-align-self:baseline!important;-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-webkit-align-self:stretch!important;-ms-flex-item-align:stretch!important;-ms-grid-row-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1030}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.m-0{margin:0 0!important}.mt-0{margin-top:0!important}.mr-0{margin-right:0!important}.mb-0{margin-bottom:0!important}.ml-0{margin-left:0!important}.mx-0{margin-right:0!important;margin-left:0!important}.my-0{margin-top:0!important;margin-bottom:0!important}.m-1{margin:.25rem .25rem!important}.mt-1{margin-top:.25rem!important}.mr-1{margin-right:.25rem!important}.mb-1{margin-bottom:.25rem!important}.ml-1{margin-left:.25rem!important}.mx-1{margin-right:.25rem!important;margin-left:.25rem!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.m-2{margin:.5rem .5rem!important}.mt-2{margin-top:.5rem!important}.mr-2{margin-right:.5rem!important}.mb-2{margin-bottom:.5rem!important}.ml-2{margin-left:.5rem!important}.mx-2{margin-right:.5rem!important;margin-left:.5rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.m-3{margin:1rem 1rem!important}.mt-3{margin-top:1rem!important}.mr-3{margin-right:1rem!important}.mb-3{margin-bottom:1rem!important}.ml-3{margin-left:1rem!important}.mx-3{margin-right:1rem!important;margin-left:1rem!important}.my-3{margin-top:1rem!important;margin-bottom:1rem!important}.m-4{margin:1.5rem 1.5rem!important}.mt-4{margin-top:1.5rem!important}.mr-4{margin-right:1.5rem!important}.mb-4{margin-bottom:1.5rem!important}.ml-4{margin-left:1.5rem!important}.mx-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.my-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.m-5{margin:3rem 3rem!important}.mt-5{margin-top:3rem!important}.mr-5{margin-right:3rem!important}.mb-5{margin-bottom:3rem!important}.ml-5{margin-left:3rem!important}.mx-5{margin-right:3rem!important;margin-left:3rem!important}.my-5{margin-top:3rem!important;margin-bottom:3rem!important}.p-0{padding:0 0!important}.pt-0{padding-top:0!important}.pr-0{padding-right:0!important}.pb-0{padding-bottom:0!important}.pl-0{padding-left:0!important}.px-0{padding-right:0!important;padding-left:0!important}.py-0{padding-top:0!important;padding-bottom:0!important}.p-1{padding:.25rem .25rem!important}.pt-1{padding-top:.25rem!important}.pr-1{padding-right:.25rem!important}.pb-1{padding-bottom:.25rem!important}.pl-1{padding-left:.25rem!important}.px-1{padding-right:.25rem!important;padding-left:.25rem!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.p-2{padding:.5rem .5rem!important}.pt-2{padding-top:.5rem!important}.pr-2{padding-right:.5rem!important}.pb-2{padding-bottom:.5rem!important}.pl-2{padding-left:.5rem!important}.px-2{padding-right:.5rem!important;padding-left:.5rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.p-3{padding:1rem 1rem!important}.pt-3{padding-top:1rem!important}.pr-3{padding-right:1rem!important}.pb-3{padding-bottom:1rem!important}.pl-3{padding-left:1rem!important}.px-3{padding-right:1rem!important;padding-left:1rem!important}.py-3{padding-top:1rem!important;padding-bottom:1rem!important}.p-4{padding:1.5rem 1.5rem!important}.pt-4{padding-top:1.5rem!important}.pr-4{padding-right:1.5rem!important}.pb-4{padding-bottom:1.5rem!important}.pl-4{padding-left:1.5rem!important}.px-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.py-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.p-5{padding:3rem 3rem!important}.pt-5{padding-top:3rem!important}.pr-5{padding-right:3rem!important}.pb-5{padding-bottom:3rem!important}.pl-5{padding-left:3rem!important}.px-5{padding-right:3rem!important;padding-left:3rem!important}.py-5{padding-top:3rem!important;padding-bottom:3rem!important}.m-auto{margin:auto!important}.mt-auto{margin-top:auto!important}.mr-auto{margin-right:auto!important}.mb-auto{margin-bottom:auto!important}.ml-auto{margin-left:auto!important}.mx-auto{margin-right:auto!important;margin-left:auto!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}@media (min-width:576px){.m-sm-0{margin:0 0!important}.mt-sm-0{margin-top:0!important}.mr-sm-0{margin-right:0!important}.mb-sm-0{margin-bottom:0!important}.ml-sm-0{margin-left:0!important}.mx-sm-0{margin-right:0!important;margin-left:0!important}.my-sm-0{margin-top:0!important;margin-bottom:0!important}.m-sm-1{margin:.25rem .25rem!important}.mt-sm-1{margin-top:.25rem!important}.mr-sm-1{margin-right:.25rem!important}.mb-sm-1{margin-bottom:.25rem!important}.ml-sm-1{margin-left:.25rem!important}.mx-sm-1{margin-right:.25rem!important;margin-left:.25rem!important}.my-sm-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.m-sm-2{margin:.5rem .5rem!important}.mt-sm-2{margin-top:.5rem!important}.mr-sm-2{margin-right:.5rem!important}.mb-sm-2{margin-bottom:.5rem!important}.ml-sm-2{margin-left:.5rem!important}.mx-sm-2{margin-right:.5rem!important;margin-left:.5rem!important}.my-sm-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.m-sm-3{margin:1rem 1rem!important}.mt-sm-3{margin-top:1rem!important}.mr-sm-3{margin-right:1rem!important}.mb-sm-3{margin-bottom:1rem!important}.ml-sm-3{margin-left:1rem!important}.mx-sm-3{margin-right:1rem!important;margin-left:1rem!important}.my-sm-3{margin-top:1rem!important;margin-bottom:1rem!important}.m-sm-4{margin:1.5rem 1.5rem!important}.mt-sm-4{margin-top:1.5rem!important}.mr-sm-4{margin-right:1.5rem!important}.mb-sm-4{margin-bottom:1.5rem!important}.ml-sm-4{margin-left:1.5rem!important}.mx-sm-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.my-sm-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.m-sm-5{margin:3rem 3rem!important}.mt-sm-5{margin-top:3rem!important}.mr-sm-5{margin-right:3rem!important}.mb-sm-5{margin-bottom:3rem!important}.ml-sm-5{margin-left:3rem!important}.mx-sm-5{margin-right:3rem!important;margin-left:3rem!important}.my-sm-5{margin-top:3rem!important;margin-bottom:3rem!important}.p-sm-0{padding:0 0!important}.pt-sm-0{padding-top:0!important}.pr-sm-0{padding-right:0!important}.pb-sm-0{padding-bottom:0!important}.pl-sm-0{padding-left:0!important}.px-sm-0{padding-right:0!important;padding-left:0!important}.py-sm-0{padding-top:0!important;padding-bottom:0!important}.p-sm-1{padding:.25rem .25rem!important}.pt-sm-1{padding-top:.25rem!important}.pr-sm-1{padding-right:.25rem!important}.pb-sm-1{padding-bottom:.25rem!important}.pl-sm-1{padding-left:.25rem!important}.px-sm-1{padding-right:.25rem!important;padding-left:.25rem!important}.py-sm-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.p-sm-2{padding:.5rem .5rem!important}.pt-sm-2{padding-top:.5rem!important}.pr-sm-2{padding-right:.5rem!important}.pb-sm-2{padding-bottom:.5rem!important}.pl-sm-2{padding-left:.5rem!important}.px-sm-2{padding-right:.5rem!important;padding-left:.5rem!important}.py-sm-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.p-sm-3{padding:1rem 1rem!important}.pt-sm-3{padding-top:1rem!important}.pr-sm-3{padding-right:1rem!important}.pb-sm-3{padding-bottom:1rem!important}.pl-sm-3{padding-left:1rem!important}.px-sm-3{padding-right:1rem!important;padding-left:1rem!important}.py-sm-3{padding-top:1rem!important;padding-bottom:1rem!important}.p-sm-4{padding:1.5rem 1.5rem!important}.pt-sm-4{padding-top:1.5rem!important}.pr-sm-4{padding-right:1.5rem!important}.pb-sm-4{padding-bottom:1.5rem!important}.pl-sm-4{padding-left:1.5rem!important}.px-sm-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.py-sm-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.p-sm-5{padding:3rem 3rem!important}.pt-sm-5{padding-top:3rem!important}.pr-sm-5{padding-right:3rem!important}.pb-sm-5{padding-bottom:3rem!important}.pl-sm-5{padding-left:3rem!important}.px-sm-5{padding-right:3rem!important;padding-left:3rem!important}.py-sm-5{padding-top:3rem!important;padding-bottom:3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto{margin-top:auto!important}.mr-sm-auto{margin-right:auto!important}.mb-sm-auto{margin-bottom:auto!important}.ml-sm-auto{margin-left:auto!important}.mx-sm-auto{margin-right:auto!important;margin-left:auto!important}.my-sm-auto{margin-top:auto!important;margin-bottom:auto!important}}@media (min-width:768px){.m-md-0{margin:0 0!important}.mt-md-0{margin-top:0!important}.mr-md-0{margin-right:0!important}.mb-md-0{margin-bottom:0!important}.ml-md-0{margin-left:0!important}.mx-md-0{margin-right:0!important;margin-left:0!important}.my-md-0{margin-top:0!important;margin-bottom:0!important}.m-md-1{margin:.25rem .25rem!important}.mt-md-1{margin-top:.25rem!important}.mr-md-1{margin-right:.25rem!important}.mb-md-1{margin-bottom:.25rem!important}.ml-md-1{margin-left:.25rem!important}.mx-md-1{margin-right:.25rem!important;margin-left:.25rem!important}.my-md-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.m-md-2{margin:.5rem .5rem!important}.mt-md-2{margin-top:.5rem!important}.mr-md-2{margin-right:.5rem!important}.mb-md-2{margin-bottom:.5rem!important}.ml-md-2{margin-left:.5rem!important}.mx-md-2{margin-right:.5rem!important;margin-left:.5rem!important}.my-md-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.m-md-3{margin:1rem 1rem!important}.mt-md-3{margin-top:1rem!important}.mr-md-3{margin-right:1rem!important}.mb-md-3{margin-bottom:1rem!important}.ml-md-3{margin-left:1rem!important}.mx-md-3{margin-right:1rem!important;margin-left:1rem!important}.my-md-3{margin-top:1rem!important;margin-bottom:1rem!important}.m-md-4{margin:1.5rem 1.5rem!important}.mt-md-4{margin-top:1.5rem!important}.mr-md-4{margin-right:1.5rem!important}.mb-md-4{margin-bottom:1.5rem!important}.ml-md-4{margin-left:1.5rem!important}.mx-md-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.my-md-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.m-md-5{margin:3rem 3rem!important}.mt-md-5{margin-top:3rem!important}.mr-md-5{margin-right:3rem!important}.mb-md-5{margin-bottom:3rem!important}.ml-md-5{margin-left:3rem!important}.mx-md-5{margin-right:3rem!important;margin-left:3rem!important}.my-md-5{margin-top:3rem!important;margin-bottom:3rem!important}.p-md-0{padding:0 0!important}.pt-md-0{padding-top:0!important}.pr-md-0{padding-right:0!important}.pb-md-0{padding-bottom:0!important}.pl-md-0{padding-left:0!important}.px-md-0{padding-right:0!important;padding-left:0!important}.py-md-0{padding-top:0!important;padding-bottom:0!important}.p-md-1{padding:.25rem .25rem!important}.pt-md-1{padding-top:.25rem!important}.pr-md-1{padding-right:.25rem!important}.pb-md-1{padding-bottom:.25rem!important}.pl-md-1{padding-left:.25rem!important}.px-md-1{padding-right:.25rem!important;padding-left:.25rem!important}.py-md-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.p-md-2{padding:.5rem .5rem!important}.pt-md-2{padding-top:.5rem!important}.pr-md-2{padding-right:.5rem!important}.pb-md-2{padding-bottom:.5rem!important}.pl-md-2{padding-left:.5rem!important}.px-md-2{padding-right:.5rem!important;padding-left:.5rem!important}.py-md-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.p-md-3{padding:1rem 1rem!important}.pt-md-3{padding-top:1rem!important}.pr-md-3{padding-right:1rem!important}.pb-md-3{padding-bottom:1rem!important}.pl-md-3{padding-left:1rem!important}.px-md-3{padding-right:1rem!important;padding-left:1rem!important}.py-md-3{padding-top:1rem!important;padding-bottom:1rem!important}.p-md-4{padding:1.5rem 1.5rem!important}.pt-md-4{padding-top:1.5rem!important}.pr-md-4{padding-right:1.5rem!important}.pb-md-4{padding-bottom:1.5rem!important}.pl-md-4{padding-left:1.5rem!important}.px-md-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.py-md-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.p-md-5{padding:3rem 3rem!important}.pt-md-5{padding-top:3rem!important}.pr-md-5{padding-right:3rem!important}.pb-md-5{padding-bottom:3rem!important}.pl-md-5{padding-left:3rem!important}.px-md-5{padding-right:3rem!important;padding-left:3rem!important}.py-md-5{padding-top:3rem!important;padding-bottom:3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto{margin-top:auto!important}.mr-md-auto{margin-right:auto!important}.mb-md-auto{margin-bottom:auto!important}.ml-md-auto{margin-left:auto!important}.mx-md-auto{margin-right:auto!important;margin-left:auto!important}.my-md-auto{margin-top:auto!important;margin-bottom:auto!important}}@media (min-width:992px){.m-lg-0{margin:0 0!important}.mt-lg-0{margin-top:0!important}.mr-lg-0{margin-right:0!important}.mb-lg-0{margin-bottom:0!important}.ml-lg-0{margin-left:0!important}.mx-lg-0{margin-right:0!important;margin-left:0!important}.my-lg-0{margin-top:0!important;margin-bottom:0!important}.m-lg-1{margin:.25rem .25rem!important}.mt-lg-1{margin-top:.25rem!important}.mr-lg-1{margin-right:.25rem!important}.mb-lg-1{margin-bottom:.25rem!important}.ml-lg-1{margin-left:.25rem!important}.mx-lg-1{margin-right:.25rem!important;margin-left:.25rem!important}.my-lg-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.m-lg-2{margin:.5rem .5rem!important}.mt-lg-2{margin-top:.5rem!important}.mr-lg-2{margin-right:.5rem!important}.mb-lg-2{margin-bottom:.5rem!important}.ml-lg-2{margin-left:.5rem!important}.mx-lg-2{margin-right:.5rem!important;margin-left:.5rem!important}.my-lg-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.m-lg-3{margin:1rem 1rem!important}.mt-lg-3{margin-top:1rem!important}.mr-lg-3{margin-right:1rem!important}.mb-lg-3{margin-bottom:1rem!important}.ml-lg-3{margin-left:1rem!important}.mx-lg-3{margin-right:1rem!important;margin-left:1rem!important}.my-lg-3{margin-top:1rem!important;margin-bottom:1rem!important}.m-lg-4{margin:1.5rem 1.5rem!important}.mt-lg-4{margin-top:1.5rem!important}.mr-lg-4{margin-right:1.5rem!important}.mb-lg-4{margin-bottom:1.5rem!important}.ml-lg-4{margin-left:1.5rem!important}.mx-lg-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.my-lg-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.m-lg-5{margin:3rem 3rem!important}.mt-lg-5{margin-top:3rem!important}.mr-lg-5{margin-right:3rem!important}.mb-lg-5{margin-bottom:3rem!important}.ml-lg-5{margin-left:3rem!important}.mx-lg-5{margin-right:3rem!important;margin-left:3rem!important}.my-lg-5{margin-top:3rem!important;margin-bottom:3rem!important}.p-lg-0{padding:0 0!important}.pt-lg-0{padding-top:0!important}.pr-lg-0{padding-right:0!important}.pb-lg-0{padding-bottom:0!important}.pl-lg-0{padding-left:0!important}.px-lg-0{padding-right:0!important;padding-left:0!important}.py-lg-0{padding-top:0!important;padding-bottom:0!important}.p-lg-1{padding:.25rem .25rem!important}.pt-lg-1{padding-top:.25rem!important}.pr-lg-1{padding-right:.25rem!important}.pb-lg-1{padding-bottom:.25rem!important}.pl-lg-1{padding-left:.25rem!important}.px-lg-1{padding-right:.25rem!important;padding-left:.25rem!important}.py-lg-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.p-lg-2{padding:.5rem .5rem!important}.pt-lg-2{padding-top:.5rem!important}.pr-lg-2{padding-right:.5rem!important}.pb-lg-2{padding-bottom:.5rem!important}.pl-lg-2{padding-left:.5rem!important}.px-lg-2{padding-right:.5rem!important;padding-left:.5rem!important}.py-lg-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.p-lg-3{padding:1rem 1rem!important}.pt-lg-3{padding-top:1rem!important}.pr-lg-3{padding-right:1rem!important}.pb-lg-3{padding-bottom:1rem!important}.pl-lg-3{padding-left:1rem!important}.px-lg-3{padding-right:1rem!important;padding-left:1rem!important}.py-lg-3{padding-top:1rem!important;padding-bottom:1rem!important}.p-lg-4{padding:1.5rem 1.5rem!important}.pt-lg-4{padding-top:1.5rem!important}.pr-lg-4{padding-right:1.5rem!important}.pb-lg-4{padding-bottom:1.5rem!important}.pl-lg-4{padding-left:1.5rem!important}.px-lg-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.py-lg-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.p-lg-5{padding:3rem 3rem!important}.pt-lg-5{padding-top:3rem!important}.pr-lg-5{padding-right:3rem!important}.pb-lg-5{padding-bottom:3rem!important}.pl-lg-5{padding-left:3rem!important}.px-lg-5{padding-right:3rem!important;padding-left:3rem!important}.py-lg-5{padding-top:3rem!important;padding-bottom:3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto{margin-top:auto!important}.mr-lg-auto{margin-right:auto!important}.mb-lg-auto{margin-bottom:auto!important}.ml-lg-auto{margin-left:auto!important}.mx-lg-auto{margin-right:auto!important;margin-left:auto!important}.my-lg-auto{margin-top:auto!important;margin-bottom:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0 0!important}.mt-xl-0{margin-top:0!important}.mr-xl-0{margin-right:0!important}.mb-xl-0{margin-bottom:0!important}.ml-xl-0{margin-left:0!important}.mx-xl-0{margin-right:0!important;margin-left:0!important}.my-xl-0{margin-top:0!important;margin-bottom:0!important}.m-xl-1{margin:.25rem .25rem!important}.mt-xl-1{margin-top:.25rem!important}.mr-xl-1{margin-right:.25rem!important}.mb-xl-1{margin-bottom:.25rem!important}.ml-xl-1{margin-left:.25rem!important}.mx-xl-1{margin-right:.25rem!important;margin-left:.25rem!important}.my-xl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.m-xl-2{margin:.5rem .5rem!important}.mt-xl-2{margin-top:.5rem!important}.mr-xl-2{margin-right:.5rem!important}.mb-xl-2{margin-bottom:.5rem!important}.ml-xl-2{margin-left:.5rem!important}.mx-xl-2{margin-right:.5rem!important;margin-left:.5rem!important}.my-xl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.m-xl-3{margin:1rem 1rem!important}.mt-xl-3{margin-top:1rem!important}.mr-xl-3{margin-right:1rem!important}.mb-xl-3{margin-bottom:1rem!important}.ml-xl-3{margin-left:1rem!important}.mx-xl-3{margin-right:1rem!important;margin-left:1rem!important}.my-xl-3{margin-top:1rem!important;margin-bottom:1rem!important}.m-xl-4{margin:1.5rem 1.5rem!important}.mt-xl-4{margin-top:1.5rem!important}.mr-xl-4{margin-right:1.5rem!important}.mb-xl-4{margin-bottom:1.5rem!important}.ml-xl-4{margin-left:1.5rem!important}.mx-xl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.my-xl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.m-xl-5{margin:3rem 3rem!important}.mt-xl-5{margin-top:3rem!important}.mr-xl-5{margin-right:3rem!important}.mb-xl-5{margin-bottom:3rem!important}.ml-xl-5{margin-left:3rem!important}.mx-xl-5{margin-right:3rem!important;margin-left:3rem!important}.my-xl-5{margin-top:3rem!important;margin-bottom:3rem!important}.p-xl-0{padding:0 0!important}.pt-xl-0{padding-top:0!important}.pr-xl-0{padding-right:0!important}.pb-xl-0{padding-bottom:0!important}.pl-xl-0{padding-left:0!important}.px-xl-0{padding-right:0!important;padding-left:0!important}.py-xl-0{padding-top:0!important;padding-bottom:0!important}.p-xl-1{padding:.25rem .25rem!important}.pt-xl-1{padding-top:.25rem!important}.pr-xl-1{padding-right:.25rem!important}.pb-xl-1{padding-bottom:.25rem!important}.pl-xl-1{padding-left:.25rem!important}.px-xl-1{padding-right:.25rem!important;padding-left:.25rem!important}.py-xl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.p-xl-2{padding:.5rem .5rem!important}.pt-xl-2{padding-top:.5rem!important}.pr-xl-2{padding-right:.5rem!important}.pb-xl-2{padding-bottom:.5rem!important}.pl-xl-2{padding-left:.5rem!important}.px-xl-2{padding-right:.5rem!important;padding-left:.5rem!important}.py-xl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.p-xl-3{padding:1rem 1rem!important}.pt-xl-3{padding-top:1rem!important}.pr-xl-3{padding-right:1rem!important}.pb-xl-3{padding-bottom:1rem!important}.pl-xl-3{padding-left:1rem!important}.px-xl-3{padding-right:1rem!important;padding-left:1rem!important}.py-xl-3{padding-top:1rem!important;padding-bottom:1rem!important}.p-xl-4{padding:1.5rem 1.5rem!important}.pt-xl-4{padding-top:1.5rem!important}.pr-xl-4{padding-right:1.5rem!important}.pb-xl-4{padding-bottom:1.5rem!important}.pl-xl-4{padding-left:1.5rem!important}.px-xl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.py-xl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.p-xl-5{padding:3rem 3rem!important}.pt-xl-5{padding-top:3rem!important}.pr-xl-5{padding-right:3rem!important}.pb-xl-5{padding-bottom:3rem!important}.pl-xl-5{padding-left:3rem!important}.px-xl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xl-5{padding-top:3rem!important;padding-bottom:3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto{margin-top:auto!important}.mr-xl-auto{margin-right:auto!important}.mb-xl-auto{margin-bottom:auto!important}.ml-xl-auto{margin-left:auto!important}.mx-xl-auto{margin-right:auto!important;margin-left:auto!important}.my-xl-auto{margin-top:auto!important;margin-bottom:auto!important}}.text-justify{text-align:justify!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-normal{font-weight:400}.font-weight-bold{font-weight:700}.font-italic{font-style:italic}.text-white{color:#fff!important}.text-muted{color:#636c72!important}a.text-muted:focus,a.text-muted:hover{color:#4b5257!important}.text-primary{color:#0275d8!important}a.text-primary:focus,a.text-primary:hover{color:#025aa5!important}.text-success{color:#5cb85c!important}a.text-success:focus,a.text-success:hover{color:#449d44!important}.text-info{color:#5bc0de!important}a.text-info:focus,a.text-info:hover{color:#31b0d5!important}.text-warning{color:#f0ad4e!important}a.text-warning:focus,a.text-warning:hover{color:#ec971f!important}.text-danger{color:#d9534f!important}a.text-danger:focus,a.text-danger:hover{color:#c9302c!important}.text-gray-dark{color:#292b2c!important}a.text-gray-dark:focus,a.text-gray-dark:hover{color:#101112!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.invisible{visibility:hidden!important}.hidden-xs-up{display:none!important}@media (max-width:575px){.hidden-xs-down{display:none!important}}@media (min-width:576px){.hidden-sm-up{display:none!important}}@media (max-width:767px){.hidden-sm-down{display:none!important}}@media (min-width:768px){.hidden-md-up{display:none!important}}@media (max-width:991px){.hidden-md-down{display:none!important}}@media (min-width:992px){.hidden-lg-up{display:none!important}}@media (max-width:1199px){.hidden-lg-down{display:none!important}}@media (min-width:1200px){.hidden-xl-up{display:none!important}}.hidden-xl-down{display:none!important}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}/*# sourceMappingURL=bootstrap.min.css.map */
\ No newline at end of file
--- /dev/null
+{"version":3,"sources":["../../scss/_normalize.scss","bootstrap.css","../../scss/_print.scss","../../scss/_reboot.scss","../../scss/_variables.scss","../../scss/mixins/_hover.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/mixins/_border-radius.scss","../../scss/_mixins.scss","../../scss/_code.scss","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_breakpoints.scss","../../scss/mixins/_grid-framework.scss","../../scss/_tables.scss","../../scss/mixins/_table-row.scss","../../scss/_forms.scss","../../scss/mixins/_forms.scss","../../scss/_buttons.scss","../../scss/mixins/_buttons.scss","../../scss/_transitions.scss","../../scss/_dropdown.scss","../../scss/mixins/_nav-divider.scss","../../scss/_button-group.scss","../../scss/_input-group.scss","../../scss/_custom-forms.scss","../../scss/_nav.scss","../../scss/_navbar.scss","../../scss/_card.scss","../../scss/mixins/_cards.scss","../../scss/_breadcrumb.scss","../../scss/mixins/_clearfix.scss","../../scss/_pagination.scss","../../scss/mixins/_pagination.scss","../../scss/_badge.scss","../../scss/mixins/_badge.scss","../../scss/_jumbotron.scss","../../scss/_alert.scss","../../scss/mixins/_alert.scss","../../scss/_progress.scss","../../scss/mixins/_gradients.scss","../../scss/_media.scss","../../scss/_list-group.scss","../../scss/mixins/_list-group.scss","../../scss/_responsive-embed.scss","../../scss/_close.scss","../../scss/_modal.scss","../../scss/_tooltip.scss","../../scss/mixins/_reset-text.scss","../../scss/_popover.scss","../../scss/_carousel.scss","../../scss/mixins/_transforms.scss","../../scss/utilities/_align.scss","../../scss/utilities/_background.scss","../../scss/mixins/_background-variant.scss","../../scss/utilities/_borders.scss","../../scss/utilities/_display.scss","../../scss/utilities/_flex.scss","../../scss/utilities/_float.scss","../../scss/mixins/_float.scss","../../scss/utilities/_position.scss","../../scss/utilities/_screenreaders.scss","../../scss/mixins/_screen-reader.scss","../../scss/utilities/_sizing.scss","../../scss/utilities/_spacing.scss","../../scss/utilities/_text.scss","../../scss/mixins/_text-truncate.scss","../../scss/mixins/_text-emphasis.scss","../../scss/mixins/_text-hide.scss","../../scss/utilities/_visibility.scss","../../scss/mixins/_visibility.scss"],"names":[],"mappings":";;;;;4EAYA,KACE,YAAA,WACA,YAAA,KACA,qBAAA,KACA,yBAAA,KAUF,KACE,OAAA,EAOF,QAAA,MAAA,OAAA,OAAA,IAAA,QAME,QAAA,MAQF,GACE,UAAA,IACA,OAAA,MAAA,EAWF,WAAA,OAAA,KAGE,QAAA,MAOF,OACE,OAAA,IAAA,KAQF,GACE,mBAAA,YAAA,WAAA,YACA,OAAA,EACA,SAAA,QAQF,IACE,YAAA,UAAA,UACA,UAAA,IAWF,EACE,iBAAA,YACA,6BAAA,QAQF,SAAA,QAEE,cAAA,EAQF,YACE,cAAA,KACA,gBAAA,UACA,gBAAA,UAAA,OAOF,EAAA,OAEE,YAAA,QAOF,EAAA,OAEE,YAAA,OAQF,KAAA,IAAA,KAGE,YAAA,UAAA,UACA,UAAA,IAOF,IACE,WAAA,OAOF,KACE,iBAAA,KACA,MAAA,KAOF,MACE,UAAA,IAQF,IAAA,IAEE,UAAA,IACA,YAAA,EACA,SAAA,SACA,eAAA,SAGF,IACE,OAAA,OAGF,IACE,IAAA,MAUF,MAAA,MAEE,QAAA,aAOF,sBACE,QAAA,KACA,OAAA,EAOF,IACE,aAAA,KAOF,eACE,SAAA,OAWF,OAAA,MAAA,SAAA,OAAA,SAKE,YAAA,WACA,UAAA,KACA,YAAA,KACA,OAAA,EAQF,OAAA,MAEE,SAAA,QAQF,OAAA,OAEE,eAAA,KASF,aAAA,cAAA,OAAA,mBAIE,mBAAA,OAOF,gCAAA,+BAAA,gCAAA,yBAIE,aAAA,KACA,QAAA,EAOF,6BAAA,4BAAA,6BAAA,sBAIE,QAAA,IAAA,OAAA,WAOF,SACE,OAAA,IAAA,MAAA,OACA,OAAA,EAAA,IACA,QAAA,MAAA,OAAA,MAUF,OACE,mBAAA,WAAA,WAAA,WACA,MAAA,QACA,QAAA,MACA,UAAA,KACA,QAAA,EACA,YAAA,OAQF,SACE,QAAA,aACA,eAAA,SAOF,SACE,SAAA,KC/JF,gBAAA,aDyKE,mBAAA,WAAA,WAAA,WACA,QAAA,ECpKF,yCAAA,yCD6KE,OAAA,KCxKF,cDiLE,mBAAA,UACA,eAAA,KC7KF,4CAAA,yCDsLE,mBAAA,KAQF,6BACE,mBAAA,OACA,KAAA,QAWF,QAAA,KAEE,QAAA,MAOF,QACE,QAAA,UAUF,OACE,QAAA,aAOF,SACE,QAAA,KC7MF,SDwNE,QAAA,KEhcA,aACE,EAAA,QAAA,SAAA,yBAAA,uBAAA,kBAAA,gBAAA,iBAAA,eAAA,gBAAA,cAcE,YAAA,eAEA,mBAAA,eAAA,WAAA,eAGF,EAAA,UAEE,gBAAA,UAQF,mBACE,QAA6B,KAA7B,YAA6B,IAc/B,IACE,YAAA,mBAEF,WAAA,IAEE,OAAA,IAAA,MAAA,KACA,kBAAA,MAQF,MACE,QAAA,mBAGF,IAAA,GAEE,kBAAA,MAGF,GAAA,GAAA,EAGE,QAAA,EACA,OAAA,EAGF,GAAA,GAEE,iBAAA,MAMF,QACE,QAAA,KAEF,OACE,OAAA,IAAA,MAAA,KAGF,OACE,gBAAA,mBADF,UAAA,UAKI,iBAAA,eAGJ,mBAAA,mBAGI,OAAA,IAAA,MAAA,gBC3FR,KACE,mBAAA,WAAA,WAAA,WAGF,EAAA,QAAA,SAGE,mBAAA,QAAA,WAAA,QAoBA,cAAgB,MAAA,aAQlB,KAYE,mBAAA,UAGA,4BAAA,YAGF,KACE,YAAA,cAAA,UAAA,mBAAA,WAAA,OC2K4H,iBD3K5H,MAAA,WACA,UAAA,KACA,YAAA,IACA,YAAA,IAEA,MAAA,QAEA,iBAAA,KFmQF,sBE1PE,QAAA,YAYF,GAAI,GAAI,GAAI,GAAI,GAAI,GAClB,WAAA,EACA,cAAA,MAOF,EACE,WAAA,EACA,cAAA,KAIF,0BAAA,YAGE,OAAA,KAGF,QACE,cAAA,KACA,WAAA,OACA,YAAA,QAGF,GAAA,GAAA,GAGE,WAAA,EACA,cAAA,KAGF,MAAA,MAAA,MAAA,MAIE,cAAA,EAGF,GACE,YAAA,IAGF,GACE,cAAA,MACA,YAAA,EAGF,WACE,OAAA,EAAA,EAAA,KAQF,EACE,MAAA,QACA,gBAAA,KEhJE,QAAA,QFmJA,MAAA,QACA,gBAAA,UAUJ,8BACE,MAAA,QACA,gBAAA,KEhKE,oCAAA,oCFmKA,MAAA,QACA,gBAAA,KANJ,oCAUI,QAAA,EASJ,IAEE,WAAA,EAEA,cAAA,KAEA,SAAA,KAQF,OAGE,OAAA,EAAA,EAAA,KAQF,IAGE,eAAA,OF8MF,cEjME,OAAA,QAcF,cAAA,EAAA,KAAA,OAAA,MAAA,MAAA,OAAA,QAAA,SASE,iBAAA,aAAA,aAAA,aAQF,MAEE,gBAAA,SAEA,iBAAA,YAGF,QACE,YAAA,OACA,eAAA,OACA,MAAA,QACA,WAAA,KACA,aAAA,OAGF,GAEE,WAAA,KAQF,MAEE,QAAA,aACA,cAAA,MAOF,aACE,QAAA,IAAA,OACA,QAAA,IAAA,KAAA,yBAGF,OAAA,MAAA,OAAA,SAME,YAAA,QAGF,8BAAA,2BAMI,OAAA,YAKJ,iBAAA,iBAAA,2BAAA,kBASE,mBAAA,QAGF,SAEE,OAAA,SAGF,SAME,UAAA,EAEA,QAAA,EACA,OAAA,EACA,OAAA,EAGF,OAEE,QAAA,MACA,MAAA,KACA,QAAA,EACA,cAAA,MACA,UAAA,OACA,YAAA,QAGF,mBAKE,mBAAA,KAIF,OACE,QAAA,aF8IF,SEtIE,QAAA,eG/XF,IAAK,IAAK,IAAK,IAAK,IAAK,IAAzB,GAAI,GAAI,GAAI,GAAI,GAAI,GAElB,cAAA,MACA,YAAA,QACA,YAAA,IACA,YAAA,IACA,MAAA,QAGE,IAAJ,GAAU,UAAA,OACN,IAAJ,GAAU,UAAA,KACN,IAAJ,GAAU,UAAA,QACN,IAAJ,GAAU,UAAA,OACN,IAAJ,GAAU,UAAA,QACN,IAAJ,GAAU,UAAA,KAEV,MACE,UAAA,QACA,YAAA,IAIF,WACE,UAAA,KACA,YAAA,IACA,YAAA,IAEF,WACE,UAAA,OACA,YAAA,IACA,YAAA,IAEF,WACE,UAAA,OACA,YAAA,IACA,YAAA,IAEF,WACE,UAAA,OACA,YAAA,IACA,YAAA,IAQF,GACE,WAAA,KACA,cAAA,KACA,OAAA,EACA,WAAA,IAAA,MAAA,eAQF,OAAA,MAEE,UAAA,IACA,YAAA,IAGF,MAAA,KAEE,QAAA,KACA,iBAAA,QAQF,eC7EE,aAAA,EACA,WAAA,KDiFF,aClFE,aAAA,EACA,WAAA,KDoFF,kBACE,QAAA,aADF,mCAII,aAAA,IAUJ,YACE,UAAA,IACA,eAAA,UAIF,YACE,QAAA,MAAA,KACA,cAAA,KACA,UAAA,QACA,YAAA,OAAA,MAAA,QAGF,mBACE,QAAA,MACA,UAAA,IACA,MAAA,QAHF,2BAMI,QAAsB,cAK1B,oBACE,cAAA,KACA,aAAA,EACA,WAAA,MACA,aAAA,OAAA,MAAA,QACA,YAAA,EAGF,+CAEI,QAAW,GAFf,8CAKI,QAAsB,cErI1B,WCIE,UAAA,KAGA,OAAA,KDDF,eACE,QAAA,OACA,iBAAA,KACA,OAAA,IAAA,MAAA,KEZE,cAAA,OCWE,mBAAA,IAAA,IAAA,YAAA,cAAA,IAAA,IAAA,YAAA,WAAA,IAAA,IAAA,YFJJ,UAAA,KAGA,OAAA,KDeF,QAEE,QAAA,aAGF,YACE,cAAA,MACA,YAAA,EAGF,gBACE,UAAA,IACA,MAAA,QIxCF,KAAA,IAAA,IAAA,KAIE,YAAA,MAAA,OAAA,SAAA,kBRmP2F,cQnP3F,UAIF,KACE,QAAA,MAAA,MACA,UAAA,IACA,MAAA,QACA,iBAAA,QFTE,cAAA,OEaF,OACE,QAAA,EACA,MAAA,QACA,iBAAA,QAKJ,IACE,QAAA,MAAA,MACA,UAAA,IACA,MAAA,KACA,iBAAA,QFzBE,cAAA,MEqBJ,QASI,QAAA,EACA,UAAA,KACA,YAAA,IAMJ,IACE,QAAA,MACA,WAAA,EACA,cAAA,KACA,UAAA,IACA,MAAA,QALF,SASI,QAAA,EACA,UAAA,QACA,MAAA,QACA,iBAAA,YACA,cAAA,EAKJ,gBACE,WAAA,MACA,WAAA,OCzDA,WCAA,SAAA,SACA,YAAA,KACA,aAAA,KAKI,cAAA,KACA,aAAA,KC2CF,yBFnDF,WCOI,cAAA,KACA,aAAA,MC2CF,yBFnDF,WCOI,cAAA,KACA,aAAA,MC2CF,yBFnDF,WCOI,cAAA,KACA,aAAA,MC2CF,0BFnDF,WCOI,cAAA,KACA,aAAA,MC2CF,yBFnDF,WCkBI,MAAA,MACA,UAAA,MCgCF,yBFnDF,WCkBI,MAAA,MACA,UAAA,MCgCF,yBFnDF,WCkBI,MAAA,MACA,UAAA,MCgCF,0BFnDF,WCkBI,MAAA,OACA,UAAA,MDPJ,iBCZA,SAAA,SACA,YAAA,KACA,aAAA,KAKI,cAAA,KACA,aAAA,KC2CF,yBFvCF,iBCLI,cAAA,KACA,aAAA,MC2CF,yBFvCF,iBCLI,cAAA,KACA,aAAA,MC2CF,yBFvCF,iBCLI,cAAA,KACA,aAAA,MC2CF,0BFvCF,iBCLI,cAAA,KACA,aAAA,MDcJ,KCaA,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,kBAAA,KAAA,cAAA,KAAA,UAAA,KAKI,aAAA,MACA,YAAA,MCSF,yBF7BF,KCmBI,aAAA,MACA,YAAA,OCSF,yBF7BF,KCmBI,aAAA,MACA,YAAA,OCSF,yBF7BF,KCmBI,aAAA,MACA,YAAA,OCSF,0BF7BF,KCmBI,aAAA,MACA,YAAA,ODdJ,YACE,aAAA,EACA,YAAA,EAFF,iBAAA,0BAMI,cAAA,EACA,aAAA,EGjCJ,KAAA,OAAA,QAAA,QAAA,QAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UACE,SAAA,SACA,MAAA,KACA,WAAA,IFuBE,cAAA,KACA,aAAA,KCsBF,yBCjDF,KAAA,OAAA,QAAA,QAAA,QAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UF0BI,cAAA,KACA,aAAA,MCsBF,yBCjDF,KAAA,OAAA,QAAA,QAAA,QAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UF0BI,cAAA,KACA,aAAA,MCsBF,yBCjDF,KAAA,OAAA,QAAA,QAAA,QAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UF0BI,cAAA,KACA,aAAA,MCsBF,0BCjDF,KAAA,OAAA,QAAA,QAAA,QAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,QAAA,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UF0BI,cAAA,KACA,aAAA,MEJA,KACE,mBAAA,EAAA,wBAAA,EAAA,WAAA,EACA,iBAAA,EAAA,kBAAA,EAAA,kBAAA,EAAA,UAAA,EACA,UAAA,KAEF,UACE,iBAAA,EAAA,aAAA,EAAA,EAAA,KAAA,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KAIA,OF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,UAAA,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAKA,UAAA,UElCM,OF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,OF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,IAAA,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAKA,UAAA,IElCM,OF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,OF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,OF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,IAAA,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAKA,UAAA,IElCM,OF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,OF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,OF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,IAAA,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAKA,UAAA,IElCM,QF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,QF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,QF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,KAAA,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAKA,UAAA,KE3BQ,QFuCR,MAAA,KEvCQ,QFuCR,MAAA,UEvCQ,QFuCR,MAAA,WEvCQ,QFuCR,MAAA,IEvCQ,QFuCR,MAAA,WEvCQ,QFuCR,MAAA,WEvCQ,QFuCR,MAAA,IEvCQ,QFuCR,MAAA,WEvCQ,QFuCR,MAAA,WEvCQ,QFuCR,MAAA,IEvCQ,SFuCR,MAAA,WEvCQ,SFuCR,MAAA,WEvCQ,SFuCR,MAAA,KEvCQ,QFmCR,KAAA,KEnCQ,QFmCR,KAAA,UEnCQ,QFmCR,KAAA,WEnCQ,QFmCR,KAAA,IEnCQ,QFmCR,KAAA,WEnCQ,QFmCR,KAAA,WEnCQ,QFmCR,KAAA,IEnCQ,QFmCR,KAAA,WEnCQ,QFmCR,KAAA,WEnCQ,QFmCR,KAAA,IEnCQ,SFmCR,KAAA,WEnCQ,SFmCR,KAAA,WEnCQ,SFmCR,KAAA,KE1BQ,UFsBR,YAAA,UEtBQ,UFsBR,YAAA,WEtBQ,UFsBR,YAAA,IEtBQ,UFsBR,YAAA,WEtBQ,UFsBR,YAAA,WEtBQ,UFsBR,YAAA,IEtBQ,UFsBR,YAAA,WEtBQ,UFsBR,YAAA,WEtBQ,UFsBR,YAAA,IEtBQ,WFsBR,YAAA,WEtBQ,WFsBR,YAAA,WCvBE,yBC1BE,QACE,mBAAA,EAAA,wBAAA,EAAA,WAAA,EACA,iBAAA,EAAA,kBAAA,EAAA,kBAAA,EAAA,UAAA,EACA,UAAA,KAEF,aACE,iBAAA,EAAA,aAAA,EAAA,EAAA,KAAA,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KAIA,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,UAAA,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAKA,UAAA,UElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,IAAA,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAKA,UAAA,IElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,IAAA,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAKA,UAAA,IElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,IAAA,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAKA,UAAA,IElCM,WF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,WF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,WF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,KAAA,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAKA,UAAA,KE3BQ,WFuCR,MAAA,KEvCQ,WFuCR,MAAA,UEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,IEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,IEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,IEvCQ,YFuCR,MAAA,WEvCQ,YFuCR,MAAA,WEvCQ,YFuCR,MAAA,KEvCQ,WFmCR,KAAA,KEnCQ,WFmCR,KAAA,UEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,IEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,IEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,IEnCQ,YFmCR,KAAA,WEnCQ,YFmCR,KAAA,WEnCQ,YFmCR,KAAA,KE1BQ,aFsBR,YAAA,EEtBQ,aFsBR,YAAA,UEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,IEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,IEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,IEtBQ,cFsBR,YAAA,WEtBQ,cFsBR,YAAA,YCvBE,yBC1BE,QACE,mBAAA,EAAA,wBAAA,EAAA,WAAA,EACA,iBAAA,EAAA,kBAAA,EAAA,kBAAA,EAAA,UAAA,EACA,UAAA,KAEF,aACE,iBAAA,EAAA,aAAA,EAAA,EAAA,KAAA,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KAIA,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,UAAA,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAKA,UAAA,UElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,IAAA,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAKA,UAAA,IElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,IAAA,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAKA,UAAA,IElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,IAAA,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAKA,UAAA,IElCM,WF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,WF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,WF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,KAAA,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAKA,UAAA,KE3BQ,WFuCR,MAAA,KEvCQ,WFuCR,MAAA,UEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,IEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,IEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,IEvCQ,YFuCR,MAAA,WEvCQ,YFuCR,MAAA,WEvCQ,YFuCR,MAAA,KEvCQ,WFmCR,KAAA,KEnCQ,WFmCR,KAAA,UEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,IEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,IEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,IEnCQ,YFmCR,KAAA,WEnCQ,YFmCR,KAAA,WEnCQ,YFmCR,KAAA,KE1BQ,aFsBR,YAAA,EEtBQ,aFsBR,YAAA,UEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,IEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,IEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,IEtBQ,cFsBR,YAAA,WEtBQ,cFsBR,YAAA,YCvBE,yBC1BE,QACE,mBAAA,EAAA,wBAAA,EAAA,WAAA,EACA,iBAAA,EAAA,kBAAA,EAAA,kBAAA,EAAA,UAAA,EACA,UAAA,KAEF,aACE,iBAAA,EAAA,aAAA,EAAA,EAAA,KAAA,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KAIA,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,UAAA,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAKA,UAAA,UElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,IAAA,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAKA,UAAA,IElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,IAAA,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAKA,UAAA,IElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,IAAA,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAKA,UAAA,IElCM,WF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,WF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,WF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,KAAA,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAKA,UAAA,KE3BQ,WFuCR,MAAA,KEvCQ,WFuCR,MAAA,UEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,IEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,IEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,IEvCQ,YFuCR,MAAA,WEvCQ,YFuCR,MAAA,WEvCQ,YFuCR,MAAA,KEvCQ,WFmCR,KAAA,KEnCQ,WFmCR,KAAA,UEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,IEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,IEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,IEnCQ,YFmCR,KAAA,WEnCQ,YFmCR,KAAA,WEnCQ,YFmCR,KAAA,KE1BQ,aFsBR,YAAA,EEtBQ,aFsBR,YAAA,UEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,IEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,IEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,IEtBQ,cFsBR,YAAA,WEtBQ,cFsBR,YAAA,YCvBE,0BC1BE,QACE,mBAAA,EAAA,wBAAA,EAAA,WAAA,EACA,iBAAA,EAAA,kBAAA,EAAA,kBAAA,EAAA,UAAA,EACA,UAAA,KAEF,aACE,iBAAA,EAAA,aAAA,EAAA,EAAA,KAAA,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KAIA,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,UAAA,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAKA,UAAA,UElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,IAAA,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAKA,UAAA,IElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,IAAA,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAKA,UAAA,IElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,UF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,IAAA,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAKA,UAAA,IElCM,WF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,WF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,WAAA,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAKA,UAAA,WElCM,WF6BN,iBAAA,EAAA,aAAA,EAAA,EAAA,KAAA,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAKA,UAAA,KE3BQ,WFuCR,MAAA,KEvCQ,WFuCR,MAAA,UEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,IEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,IEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,WEvCQ,WFuCR,MAAA,IEvCQ,YFuCR,MAAA,WEvCQ,YFuCR,MAAA,WEvCQ,YFuCR,MAAA,KEvCQ,WFmCR,KAAA,KEnCQ,WFmCR,KAAA,UEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,IEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,IEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,WEnCQ,WFmCR,KAAA,IEnCQ,YFmCR,KAAA,WEnCQ,YFmCR,KAAA,WEnCQ,YFmCR,KAAA,KE1BQ,aFsBR,YAAA,EEtBQ,aFsBR,YAAA,UEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,IEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,IEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,WEtBQ,aFsBR,YAAA,IEtBQ,cFsBR,YAAA,WEtBQ,cFsBR,YAAA,YG3EF,OACE,MAAA,KACA,UAAA,KACA,cAAA,KAHF,UAAA,UAOI,QAAA,OACA,eAAA,IACA,WAAA,IAAA,MAAA,QATJ,gBAaI,eAAA,OACA,cAAA,IAAA,MAAA,QAdJ,mBAkBI,WAAA,IAAA,MAAA,QAlBJ,cAsBI,iBAAA,KASJ,aAAA,aAGI,QAAA,MASJ,gBACE,OAAA,IAAA,MAAA,QADF,mBAAA,mBAKI,OAAA,IAAA,MAAA,QALJ,yBAAA,yBAWM,oBAAA,IAUN,yCAEI,iBAAA,gBASJ,4BAGM,iBAAA,iBC7EJ,cAAA,iBAAA,iBAII,iBAAA,iBAMJ,iCAKM,iBAAA,iBALN,oCAAA,oCASQ,iBAAA,iBAnBR,eAAA,kBAAA,kBAII,iBAAA,QAMJ,kCAKM,iBAAA,QALN,qCAAA,qCASQ,iBAAA,QAnBR,YAAA,eAAA,eAII,iBAAA,QAMJ,+BAKM,iBAAA,QALN,kCAAA,kCASQ,iBAAA,QAnBR,eAAA,kBAAA,kBAII,iBAAA,QAMJ,kCAKM,iBAAA,QALN,qCAAA,qCASQ,iBAAA,QAnBR,cAAA,iBAAA,iBAII,iBAAA,QAMJ,iCAKM,iBAAA,QALN,oCAAA,oCASQ,iBAAA,QDiFV,kBAEI,MAAA,KACA,iBAAA,QAIJ,kBAEI,MAAA,QACA,iBAAA,QAIJ,eACE,MAAA,KACA,iBAAA,QAFF,kBAAA,kBAAA,wBAOI,aAAA,KAPJ,8BAWI,OAAA,EAYJ,kBACE,QAAA,MACA,MAAA,KACA,WAAA,KACA,mBAAA,yBAJF,iCAQI,OAAA,EEhJJ,cACE,QAAA,MACA,MAAA,KAGA,QAAA,MAAA,OACA,UAAA,KACA,YAAA,KACA,MAAA,QACA,iBAAA,KAEA,iBAAA,KACA,wBAAA,YAAA,gBAAA,YACA,OAAA,IAAA,MAAA,gBAKE,cAAA,ORTE,mBAAA,aAAA,YAAA,KAAA,mBAAA,YAAA,KAAA,WAAA,aAAA,YAAA,KAAA,mBAAA,YAAA,KAAA,cAAA,aAAA,YAAA,KAAA,WAAA,YAAA,KAAA,WAAA,aAAA,YAAA,KAAA,WAAA,YAAA,KAAA,WAAA,aAAA,YAAA,KAAA,WAAA,YAAA,KAAA,mBAAA,YAAA,KQTN,0BA6BI,iBAAA,YACA,OAAA,ECSF,oBACE,MAAA,QACA,iBAAA,KACA,aAAA,QACA,QAAA,ED3CJ,yCAsCI,MAAA,QAEA,QAAA,EAxCJ,gCAsCI,MAAA,QAEA,QAAA,EAxCJ,oCAsCI,MAAA,QAEA,QAAA,EAxCJ,2BAsCI,MAAA,QAEA,QAAA,EAxCJ,uBAAwB,wBAkDpB,iBAAA,QAEA,QAAA,EApDJ,uBAwDI,OAAA,YAIJ,gDAGI,OAAA,oBAHJ,qCAYI,MAAA,QACA,iBAAA,KAKJ,mBAAA,oBAEE,QAAA,MAUF,gBACE,YAAA,sBACA,eAAA,sBACA,cAAA,EAGF,mBACE,YAAA,uBACA,eAAA,uBACA,UAAA,QAGF,mBACE,YAAA,uBACA,eAAA,uBACA,UAAA,QAUF,iBACE,YAAA,MACA,eAAA,MACA,cAAA,EACA,UAAA,KASF,qBACE,YAAA,MACA,eAAA,MACA,cAAA,EACA,YAAA,KACA,OAAA,MAAA,YACA,aAAA,IAAA,EAN6D,qCAA/D,qCAAqG,kDAArG,uDAAA,0DAAsC,kDAAtC,uDAAA,0DAUI,cAAA,EACA,aAAA,EAaJ,iBAAkB,8BAAlB,mCAAA,sCACE,QAAA,OAAA,MACA,UAAA,QT5JE,cAAA,MSgKJ,wEAAoD,gEAApD,qEAAA,mDAEI,OAAA,UAIJ,iBAAkB,8BAAlB,mCAAA,sCACE,QAAA,OAAA,OACA,UAAA,QTxKE,cAAA,MS4KJ,wEAAoD,gEAApD,qEAAA,mDAEI,OAAA,YAUJ,YACE,cAAA,KAGF,WACE,QAAA,MACA,WAAA,OAQF,YACE,SAAA,SACA,QAAA,MACA,cAAA,MAHF,uCAOM,MAAA,QACA,OAAA,YAKN,kBACE,aAAA,QACA,cAAA,EACA,OAAA,QAGF,kBACE,SAAA,SACA,WAAA,OACA,YAAA,SAHF,6BAMI,SAAA,OAKJ,mBACE,QAAA,aADF,qCAII,eAAA,OAJJ,sCAQI,YAAA,OASJ,uBACE,WAAA,OAGF,qBAAA,sBAAA,sBAGE,cAAA,QACA,kBAAA,UACA,oBAAA,OAAA,MAAA,SACA,wBAAA,SAAA,SAAA,gBAAA,SAAA,SC5PA,6BAAA,6BAAA,+BAAA,oCAAA,iCAKE,MAAA,QAIF,2BACE,aAAA,QAQF,gCACE,MAAA,QACA,aAAA,QACA,iBAAA,QD2OJ,mCAII,iBAAA,wPCpQF,6BAAA,6BAAA,+BAAA,oCAAA,iCAKE,MAAA,QAIF,2BACE,aAAA,QAQF,gCACE,MAAA,QACA,aAAA,QACA,iBAAA,KDmPJ,mCAII,iBAAA,iUC5QF,4BAAA,4BAAA,8BAAA,mCAAA,gCAKE,MAAA,QAIF,0BACE,aAAA,QAQF,+BACE,MAAA,QACA,aAAA,QACA,iBAAA,QD2PJ,iCAII,iBAAA,kSAcJ,aACE,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,kBAAA,IAAA,KAAA,cAAA,IAAA,KAAA,UAAA,IAAA,KACA,kBAAA,OAAA,oBAAA,OAAA,eAAA,OAAA,YAAA,OAHF,yBASI,MAAA,KJ1PA,yBIiPF,mBAeI,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,kBAAA,OAAA,oBAAA,OAAA,eAAA,OAAA,YAAA,OACA,iBAAA,OAAA,wBAAA,OAAA,cAAA,OAAA,gBAAA,OACA,cAAA,EAlBJ,yBAuBI,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,iBAAA,EAAA,aAAA,EAAA,EAAA,KAAA,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,kBAAA,IAAA,KAAA,cAAA,IAAA,KAAA,UAAA,IAAA,KACA,kBAAA,OAAA,oBAAA,OAAA,eAAA,OAAA,YAAA,OACA,cAAA,EA3BJ,2BAgCI,QAAA,aACA,MAAA,KACA,eAAA,OAlCJ,kCAuCI,QAAA,aAvCJ,0BA2CI,MAAA,KA3CJ,iCA+CI,cAAA,EACA,eAAA,OAhDJ,yBAsDI,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,kBAAA,OAAA,oBAAA,OAAA,eAAA,OAAA,YAAA,OACA,iBAAA,OAAA,wBAAA,OAAA,cAAA,OAAA,gBAAA,OACA,MAAA,KACA,WAAA,EACA,cAAA,EA3DJ,+BA8DI,aAAA,EA9DJ,+BAiEI,SAAA,SACA,WAAA,EACA,aAAA,OACA,YAAA,EApEJ,6BAyEI,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,kBAAA,OAAA,oBAAA,OAAA,eAAA,OAAA,YAAA,OACA,iBAAA,OAAA,wBAAA,OAAA,cAAA,OAAA,gBAAA,OACA,aAAA,EA5EJ,uCA+EI,SAAA,OACA,QAAA,aACA,aAAA,OACA,eAAA,YAlFJ,kDAuFI,IAAA,GE1XN,KACE,QAAA,aACA,YAAA,IACA,YAAA,KACA,WAAA,OACA,YAAA,OACA,eAAA,OACA,oBAAA,KAAA,iBAAA,KAAA,gBAAA,KAAA,YAAA,KACA,OAAA,IAAA,MAAA,YCoEA,QAAA,MAAA,KACA,UAAA,KZ/EE,cAAA,OCWE,mBAAA,IAAA,IAAA,YAAA,cAAA,IAAA,IAAA,YAAA,WAAA,IAAA,IAAA,YNKF,WAAA,WgBAA,gBAAA,KAdQ,WAAZ,WAkBI,QAAA,EACA,mBAAA,EAAA,EAAA,EAAA,IAAA,oBAAA,WAAA,EAAA,EAAA,EAAA,IAAA,oBAnBJ,cAAe,cAyBX,OAAA,YACA,QAAA,IA1BS,YAAb,YAgCI,iBAAA,KAMJ,eAAA,yBAEE,eAAA,KAQF,aC7CE,MAAA,KACA,iBAAA,QACA,aAAA,QjBDE,mBiBMA,MAAA,KACA,iBAAA,QACA,aAAA,QAEF,mBAAA,mBAMI,mBAAA,EAAA,EAAA,EAAA,IAAA,mBAAA,WAAA,EAAA,EAAA,EAAA,IAAA,mBAKJ,sBAAA,sBAEE,iBAAA,QACA,aAAA,QAGF,oBAAA,oBAAA,mCAGE,MAAA,KACA,iBAAA,QACA,iBAAA,KACA,aAAA,QDcJ,eChDE,MAAA,QACA,iBAAA,KACA,aAAA,KjBDE,qBiBMA,MAAA,QACA,iBAAA,QACA,aAAA,QAEF,qBAAA,qBAMI,mBAAA,EAAA,EAAA,EAAA,IAAA,qBAAA,WAAA,EAAA,EAAA,EAAA,IAAA,qBAKJ,wBAAA,wBAEE,iBAAA,KACA,aAAA,KAGF,sBAAA,sBAAA,qCAGE,MAAA,QACA,iBAAA,QACA,iBAAA,KACA,aAAA,QDiBJ,UCnDE,MAAA,KACA,iBAAA,QACA,aAAA,QjBDE,gBiBMA,MAAA,KACA,iBAAA,QACA,aAAA,QAEF,gBAAA,gBAMI,mBAAA,EAAA,EAAA,EAAA,IAAA,oBAAA,WAAA,EAAA,EAAA,EAAA,IAAA,oBAKJ,mBAAA,mBAEE,iBAAA,QACA,aAAA,QAGF,iBAAA,iBAAA,gCAGE,MAAA,KACA,iBAAA,QACA,iBAAA,KACA,aAAA,QDoBJ,aCtDE,MAAA,KACA,iBAAA,QACA,aAAA,QjBDE,mBiBMA,MAAA,KACA,iBAAA,QACA,aAAA,QAEF,mBAAA,mBAMI,mBAAA,EAAA,EAAA,EAAA,IAAA,mBAAA,WAAA,EAAA,EAAA,EAAA,IAAA,mBAKJ,sBAAA,sBAEE,iBAAA,QACA,aAAA,QAGF,oBAAA,oBAAA,mCAGE,MAAA,KACA,iBAAA,QACA,iBAAA,KACA,aAAA,QDuBJ,aCzDE,MAAA,KACA,iBAAA,QACA,aAAA,QjBDE,mBiBMA,MAAA,KACA,iBAAA,QACA,aAAA,QAEF,mBAAA,mBAMI,mBAAA,EAAA,EAAA,EAAA,IAAA,oBAAA,WAAA,EAAA,EAAA,EAAA,IAAA,oBAKJ,sBAAA,sBAEE,iBAAA,QACA,aAAA,QAGF,oBAAA,oBAAA,mCAGE,MAAA,KACA,iBAAA,QACA,iBAAA,KACA,aAAA,QD0BJ,YC5DE,MAAA,KACA,iBAAA,QACA,aAAA,QjBDE,kBiBMA,MAAA,KACA,iBAAA,QACA,aAAA,QAEF,kBAAA,kBAMI,mBAAA,EAAA,EAAA,EAAA,IAAA,mBAAA,WAAA,EAAA,EAAA,EAAA,IAAA,mBAKJ,qBAAA,qBAEE,iBAAA,QACA,aAAA,QAGF,mBAAA,mBAAA,kCAGE,MAAA,KACA,iBAAA,QACA,iBAAA,KACA,aAAA,QD+BJ,qBCzBE,MAAA,QACA,iBAAA,KACA,iBAAA,YACA,aAAA,QjB1CE,2BiB6CA,MAAA,KACA,iBAAA,QACA,aAAA,QAGF,2BAAA,2BAEE,mBAAA,EAAA,EAAA,EAAA,IAAA,mBAAA,WAAA,EAAA,EAAA,EAAA,IAAA,mBAGF,8BAAA,8BAEE,MAAA,QACA,iBAAA,YAGF,4BAAA,4BAAA,2CAGE,MAAA,KACA,iBAAA,QACA,aAAA,QDCJ,uBC5BE,MAAA,KACA,iBAAA,KACA,iBAAA,YACA,aAAA,KjB1CE,6BiB6CA,MAAA,KACA,iBAAA,KACA,aAAA,KAGF,6BAAA,6BAEE,mBAAA,EAAA,EAAA,EAAA,IAAA,qBAAA,WAAA,EAAA,EAAA,EAAA,IAAA,qBAGF,gCAAA,gCAEE,MAAA,KACA,iBAAA,YAGF,8BAAA,8BAAA,6CAGE,MAAA,KACA,iBAAA,KACA,aAAA,KDIJ,kBC/BE,MAAA,QACA,iBAAA,KACA,iBAAA,YACA,aAAA,QjB1CE,wBiB6CA,MAAA,KACA,iBAAA,QACA,aAAA,QAGF,wBAAA,wBAEE,mBAAA,EAAA,EAAA,EAAA,IAAA,oBAAA,WAAA,EAAA,EAAA,EAAA,IAAA,oBAGF,2BAAA,2BAEE,MAAA,QACA,iBAAA,YAGF,yBAAA,yBAAA,wCAGE,MAAA,KACA,iBAAA,QACA,aAAA,QDOJ,qBClCE,MAAA,QACA,iBAAA,KACA,iBAAA,YACA,aAAA,QjB1CE,2BiB6CA,MAAA,KACA,iBAAA,QACA,aAAA,QAGF,2BAAA,2BAEE,mBAAA,EAAA,EAAA,EAAA,IAAA,mBAAA,WAAA,EAAA,EAAA,EAAA,IAAA,mBAGF,8BAAA,8BAEE,MAAA,QACA,iBAAA,YAGF,4BAAA,4BAAA,2CAGE,MAAA,KACA,iBAAA,QACA,aAAA,QDUJ,qBCrCE,MAAA,QACA,iBAAA,KACA,iBAAA,YACA,aAAA,QjB1CE,2BiB6CA,MAAA,KACA,iBAAA,QACA,aAAA,QAGF,2BAAA,2BAEE,mBAAA,EAAA,EAAA,EAAA,IAAA,oBAAA,WAAA,EAAA,EAAA,EAAA,IAAA,oBAGF,8BAAA,8BAEE,MAAA,QACA,iBAAA,YAGF,4BAAA,4BAAA,2CAGE,MAAA,KACA,iBAAA,QACA,aAAA,QDaJ,oBCxCE,MAAA,QACA,iBAAA,KACA,iBAAA,YACA,aAAA,QjB1CE,0BiB6CA,MAAA,KACA,iBAAA,QACA,aAAA,QAGF,0BAAA,0BAEE,mBAAA,EAAA,EAAA,EAAA,IAAA,mBAAA,WAAA,EAAA,EAAA,EAAA,IAAA,mBAGF,6BAAA,6BAEE,MAAA,QACA,iBAAA,YAGF,2BAAA,2BAAA,0CAGE,MAAA,KACA,iBAAA,QACA,aAAA,QDuBJ,UACE,YAAA,IACA,MAAA,QACA,cAAA,EAHF,UAA6B,iBAAlB,iBAAoC,mBAS3C,iBAAA,YATJ,UAA4B,iBAAjB,gBAeP,aAAA,YhBxGA,gBgB2GA,aAAA,YhBjGA,gBAAA,gBgBoGA,MAAA,QACA,gBAAA,UACA,iBAAA,YAvBJ,mBA0BI,MAAA,QhBzGA,yBAAA,yBgB4GE,gBAAA,KAUG,mBAAT,QCxDE,QAAA,OAAA,OACA,UAAA,QZ/EE,cAAA,MW0IK,mBAAT,QC5DE,QAAA,OAAA,MACA,UAAA,QZ/EE,cAAA,MWoJJ,WACE,QAAA,MACA,MAAA,KAIF,sBACE,WAAA,MAIF,6BAAA,4BAAA,6BAII,MAAA,KEvKJ,MACE,QAAA,EZcI,mBAAA,QAAA,KAAA,OAAA,cAAA,QAAA,KAAA,OAAA,WAAA,QAAA,KAAA,OYfN,WAKI,QAAA,EAIJ,UACE,QAAA,KADF,eAGI,QAAA,MAIJ,iBAEI,QAAA,UAIJ,oBAEI,QAAA,gBAIJ,YACE,SAAA,SACA,OAAA,EACA,SAAA,OZhBI,mBAAA,OAAA,KAAA,KAAA,cAAA,OAAA,KAAA,KAAA,WAAA,OAAA,KAAA,KadN,UAAA,QAEE,SAAA,SAGF,wBAGI,QAAA,aACA,MAAA,EACA,OAAA,EACA,YAAA,KACA,eAAA,OACA,QAAW,GACX,WAAA,KAAA,MACA,aAAA,KAAA,MAAA,YACA,YAAA,KAAA,MAAA,YAXJ,uBAgBI,QAAA,EAIJ,gCAGM,WAAA,EACA,cAAA,KAAA,MAMN,eACE,SAAA,SACA,IAAA,KACA,KAAA,EACA,QAAA,KACA,QAAA,KACA,MAAA,KACA,UAAA,MACA,QAAA,MAAA,EACA,OAAA,QAAA,EAAA,EACA,UAAA,KACA,MAAA,QACA,WAAA,KACA,WAAA,KACA,iBAAA,KACA,wBAAA,YAAA,gBAAA,YACA,OAAA,IAAA,MAAA,gBdhDE,cAAA,OcsDJ,kBCrDE,OAAA,IACA,OAAA,MAAA,EACA,SAAA,OACA,iBAAA,QDyDF,eACE,QAAA,MACA,MAAA,KACA,QAAA,IAAA,OACA,MAAA,KACA,YAAA,IACA,MAAA,QACA,WAAA,QACA,YAAA,OACA,WAAA,IACA,OAAA,EnBvDE,qBAAA,qBmB0DA,MAAA,QACA,gBAAA,KACA,iBAAA,QAfJ,sBAAuB,sBAoBnB,MAAA,KACA,gBAAA,KACA,iBAAA,QAtBJ,wBAAyB,wBA2BrB,MAAA,QACA,OAAA,YACA,iBAAA,YASJ,qBAGI,QAAA,MAHJ,QAQI,QAAA,EAQJ,qBACE,MAAA,EACA,KAAA,KAGF,oBACE,MAAA,KACA,KAAA,EAIF,iBACE,QAAA,MACA,QAAA,MAAA,OACA,cAAA,EACA,UAAA,QACA,MAAA,QACA,YAAA,OAIF,mBACE,SAAA,MACA,IAAA,EACA,MAAA,EACA,OAAA,EACA,KAAA,EACA,QAAA,IAOF,uBAGI,IAAA,KACA,OAAA,KACA,cAAA,QE3JJ,WAAA,oBAEE,SAAA,SACA,QAAA,mBAAA,QAAA,oBAAA,QAAA,mBAAA,QAAA,YACA,eAAA,OAJF,yBAAA,gBAOI,SAAA,SACA,iBAAA,EAAA,aAAA,EAAA,EAAA,KAAA,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KARJ,+BAAA,sBAaM,QAAA,EAbN,gCAAA,gCAAA,+BAAmD,uBAA1B,uBAAzB,sBAkBM,QAAA,EAlBN,qBAAA,2BAAA,2BAAA,iCAAA,8BAAA,oCAAA,oCAAA,0CA2BI,YAAA,KAKJ,aACE,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,iBAAA,MAAA,wBAAA,WAAA,cAAA,MAAA,gBAAA,WAFF,0BAKI,MAAA,KAIJ,yEACE,cAAA,EAIF,4BACE,YAAA,EADF,mEhBhCI,2BAAA,EACA,wBAAA,EgBuCJ,6CAAA,8ChB1BI,0BAAA,EACA,uBAAA,EgB+BJ,sBACE,MAAA,KAEF,8DACE,cAAA,EAEF,mEAAA,oEhBpDI,2BAAA,EACA,wBAAA,EgByDJ,oEhB5CI,0BAAA,EACA,uBAAA,EgBgDJ,mCAAA,iCAEE,QAAA,EAgBF,4BACE,cAAA,OACA,aAAA,OAFF,mCAKI,YAAA,EAI8B,0CAAlC,+BACE,cAAA,QACA,aAAA,QAGgC,0CAAlC,+BACE,cAAA,SACA,aAAA,SAoBF,oBACE,QAAA,mBAAA,QAAA,oBAAA,QAAA,mBAAA,QAAA,YACA,mBAAA,SAAA,sBAAA,OAAA,uBAAA,OAAA,mBAAA,OAAA,eAAA,OACA,kBAAA,MAAA,oBAAA,WAAA,eAAA,MAAA,YAAA,WACA,iBAAA,OAAA,wBAAA,OAAA,cAAA,OAAA,gBAAA,OAJF,yBAAA,+BAQI,MAAA,KARJ,8BAAA,oCAAA,oCAAA,0CAeI,WAAA,KACA,YAAA,EAIJ,4DAEI,cAAA,EAFJ,sDhBlII,2BAAA,EACA,0BAAA,EgBiIJ,sDhBhJI,wBAAA,EACA,uBAAA,EgB0JJ,uEACE,cAAA,EAEF,4EAAA,6EhBhJI,2BAAA,EACA,0BAAA,EgBqJJ,6EhBpKI,wBAAA,EACA,uBAAA,ET0gGJ,gDAAA,6CAAA,2DAAA,wDyBj1FM,SAAA,SACA,KAAA,cACA,eAAA,KClMN,aACE,SAAA,SACA,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,MAAA,KAHF,2BAQI,SAAA,SACA,QAAA,EACA,iBAAA,EAAA,aAAA,EAAA,EAAA,KAAA,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAGA,MAAA,GACA,cAAA,EAd8B,kCAAlC,iCAAqE,iCAkB/D,QAAA,EAKN,2BAAA,mBAAA,iBAIE,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,mBAAA,SAAA,sBAAA,OAAA,uBAAA,OAAA,mBAAA,OAAA,eAAA,OACA,iBAAA,OAAA,wBAAA,OAAA,cAAA,OAAA,gBAAA,OANF,8DAAA,sDAAA,oDjBvBI,cAAA,EiBoCJ,mBAAA,iBAEE,YAAA,OACA,eAAA,OAyBF,mBACE,QAAA,MAAA,OACA,cAAA,EACA,UAAA,KACA,YAAA,IACA,YAAA,KACA,MAAA,QACA,WAAA,OACA,iBAAA,QACA,OAAA,IAAA,MAAA,gBjBzEE,cAAA,OiBgEJ,mCAAA,mCAAA,wDAcI,QAAA,OAAA,MACA,UAAA,QjB/EA,cAAA,MiBgEJ,mCAAA,mCAAA,wDAmBI,QAAA,OAAA,OACA,UAAA,QjBpFA,cAAA,MiBgEJ,wCAAA,qCA4BI,WAAA,EAUJ,4CAAA,oCAAA,oEAAA,+EAAA,uCAAA,kDAAA,mDjBzFI,2BAAA,EACA,wBAAA,EiBiGJ,oCACE,aAAA,EAEF,6CAAA,qCAAA,wCAAA,mDAAA,oDAAA,oEAAA,yDjBvFI,0BAAA,EACA,uBAAA,EiB+FJ,mDACE,YAAA,EAOF,iBACE,SAAA,SAGA,UAAA,EACA,YAAA,OALF,sBAUI,SAAA,SAEA,iBAAA,EAAA,aAAA,EAAA,EAAA,GAAA,SAAA,EAAA,EAAA,GAAA,KAAA,EAAA,EAAA,GAZJ,2BAeM,YAAA,KAfyB,6BAA/B,4BAA+D,4BAoBzD,QAAA,EApBN,uCAAA,6CA4BM,aAAA,KA5BN,wCAAA,8CAkCM,QAAA,EACA,YAAA,KAnCN,qDAAA,oDAAA,oDAAiD,+CAAjD,8CAAmG,8CAsC3F,QAAA,EClKR,gBACE,SAAA,SACA,QAAA,mBAAA,QAAA,oBAAA,QAAA,mBAAA,QAAA,YACA,WAAA,OACA,aAAA,OACA,aAAA,KACA,OAAA,QAGF,sBACE,SAAA,SACA,QAAA,GACA,QAAA,EAHF,wDAMI,MAAA,KACA,iBAAA,QAPJ,sDAaI,mBAAA,EAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,EAAA,IAAA,QAAA,WAAA,EAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,EAAA,IAAA,QAbJ,uDAiBI,MAAA,KACA,iBAAA,QAlBJ,yDAwBM,OAAA,YACA,iBAAA,QAzBN,2DA6BM,MAAA,QACA,OAAA,YASN,0BACE,SAAA,SACA,IAAA,OACA,KAAA,EACA,QAAA,MACA,MAAA,KACA,OAAA,KACA,eAAA,KACA,oBAAA,KAAA,iBAAA,KAAA,gBAAA,KAAA,YAAA,KACA,iBAAA,KACA,kBAAA,UACA,oBAAA,OAAA,OACA,wBAAA,IAAA,IAAA,gBAAA,IAAA,IAQF,2ClB3EI,cAAA,OkB2EJ,yEAMI,iBAAA,yMANJ,+EAUI,iBAAA,QACA,iBAAA,sJASJ,wCAEI,cAAA,IAFJ,sEAMI,iBAAA,mJAUJ,yBACE,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,mBAAA,SAAA,sBAAA,OAAA,uBAAA,OAAA,mBAAA,OAAA,eAAA,OAFF,yCAKI,cAAA,OALJ,yDAQM,YAAA,EAYN,eACE,QAAA,aACA,UAAA,KAEA,OAAA,oBACA,QAAA,QAAA,QAAA,QAAA,OACA,YAAA,KACA,MAAA,QACA,eAAA,OACA,WAAA,KAAA,oKAAA,UAAA,MAAA,OAAA,OACA,wBAAA,IAAA,KAAA,gBAAA,IAAA,KACA,OAAA,IAAA,MAAA,gBlB9IE,cAAA,OkBiJF,gBAAA,KACA,mBAAA,KAfF,qBAkBI,aAAA,QACA,QAAA,EAnBJ,gCA4BM,MAAA,QACA,iBAAA,KA7BN,wBAkCI,MAAA,QACA,OAAA,YACA,iBAAA,QApCJ,2BAyCI,QAAA,EAIJ,kBACE,YAAA,QACA,eAAA,QACA,UAAA,IAaF,aACE,SAAA,SACA,QAAA,aACA,UAAA,KACA,OAAA,OACA,cAAA,EACA,OAAA,QAGF,mBACE,UAAA,MACA,UAAA,KACA,OAAA,OACA,OAAA,EACA,OAAA,iBACA,QAAA,EAOF,qBACE,SAAA,SACA,IAAA,EACA,MAAA,EACA,KAAA,EACA,QAAA,EACA,OAAA,OACA,QAAA,MAAA,KACA,YAAA,IACA,MAAA,QACA,eAAA,KACA,oBAAA,KAAA,iBAAA,KAAA,gBAAA,KAAA,YAAA,KACA,iBAAA,KACA,OAAA,IAAA,MAAA,gBlBnOE,cAAA,OkBsNJ,qCAmBM,QxB8SkB,iBwBjUxB,6BAwBI,SAAA,SACA,IAAA,KACA,MAAA,KACA,OAAA,KACA,QAAA,EACA,QAAA,MACA,OAAA,OACA,QAAA,MAAA,KACA,YAAA,IACA,MAAA,QACA,iBAAA,QACA,OAAA,IAAA,MAAA,gBlBzPA,cAAA,EAAA,OAAA,OAAA,EkBsNJ,sCAyCM,QxB2RU,SyBzhBhB,KACE,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,aAAA,EACA,cAAA,EACA,WAAA,KAGF,UACE,QAAA,MACA,QAAA,KAAA,IxBME,gBAAA,gBwBHA,gBAAA,KALJ,mBAUI,MAAA,QACA,OAAA,YASJ,UACE,cAAA,IAAA,MAAA,KADF,oBAII,cAAA,KAJJ,oBAQI,OAAA,IAAA,MAAA,YnB9BA,wBAAA,OACA,uBAAA,OmBqBJ,0BAA2B,0BAYrB,aAAA,QAAA,QAAA,KAZN,6BAgBM,MAAA,QACA,iBAAA,YACA,aAAA,YAlBN,mCAAA,2BAwBI,MAAA,QACA,iBAAA,KACA,aAAA,KAAA,KAAA,KA1BJ,yBA+BI,WAAA,KnBrDA,wBAAA,EACA,uBAAA,EmB+DJ,qBnBtEI,cAAA,OmBsEJ,oCAAA,4BAOI,MAAA,KACA,OAAA,QACA,iBAAA,QASJ,oBAEI,iBAAA,EAAA,aAAA,EAAA,EAAA,KAAA,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,WAAA,OAIJ,yBAEI,iBAAA,EAAA,aAAA,EAAA,EAAA,KAAA,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,WAAA,OASJ,uBAEI,QAAA,KAFJ,qBAKI,QAAA,MCnGJ,QACE,SAAA,SACA,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,mBAAA,SAAA,sBAAA,OAAA,uBAAA,OAAA,mBAAA,OAAA,eAAA,OACA,QAAA,MAAA,KAQF,cACE,QAAA,aACA,YAAA,OACA,eAAA,OACA,aAAA,KACA,UAAA,QACA,YAAA,QACA,YAAA,OzBhBE,oBAAA,oByBmBA,gBAAA,KASJ,YACE,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,mBAAA,SAAA,sBAAA,OAAA,uBAAA,OAAA,mBAAA,OAAA,eAAA,OACA,aAAA,EACA,cAAA,EACA,WAAA,KALF,sBAQI,cAAA,EACA,aAAA,EASJ,aACE,QAAA,aACA,YAAA,QACA,eAAA,QAUF,gBACE,mBAAA,WAAA,oBAAA,MAAA,WAAA,WACA,QAAA,OAAA,OACA,UAAA,QACA,YAAA,EACA,WAAA,IACA,OAAA,IAAA,MAAA,YpBjFE,cAAA,OLgBA,sBAAA,sByBqEA,gBAAA,KAMJ,qBACE,QAAA,aACA,MAAA,MACA,OAAA,MACA,eAAA,OACA,QAAW,GACX,WAAA,UAAA,OAAA,OACA,wBAAA,KAAA,KAAA,gBAAA,KAAA,KAKF,qBACE,SAAA,SACA,KAAA,KAEF,sBACE,SAAA,SACA,MAAA,Kf5CE,yBeiDF,8CASU,SAAA,OACA,MAAA,KAVV,8BAeQ,cAAA,EACA,aAAA,Gf9EN,yBe8DF,mBAqBM,mBAAA,WAAA,sBAAA,OAAA,uBAAA,IAAA,mBAAA,IAAA,eAAA,IACA,kBAAA,OAAA,cAAA,OAAA,UAAA,OACA,kBAAA,OAAA,oBAAA,OAAA,eAAA,OAAA,YAAA,OAvBN,+BA0BQ,mBAAA,WAAA,sBAAA,OAAA,uBAAA,IAAA,mBAAA,IAAA,eAAA,IA1BR,yCA6BU,cAAA,MACA,aAAA,MA9BV,8BAoCQ,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,kBAAA,OAAA,cAAA,OAAA,UAAA,OACA,kBAAA,OAAA,oBAAA,OAAA,eAAA,OAAA,YAAA,OAtCR,oCA2CQ,QAAA,sBAAA,QAAA,uBAAA,QAAA,sBAAA,QAAA,eACA,MAAA,KA5CR,mCAiDQ,QAAA,MflGN,yBesDA,iDAIQ,SAAA,OACA,MAAA,KALR,iCAUM,cAAA,EACA,aAAA,Gf9EN,yBemEA,sBAgBI,mBAAA,WAAA,sBAAA,OAAA,uBAAA,IAAA,mBAAA,IAAA,eAAA,IACA,kBAAA,OAAA,cAAA,OAAA,UAAA,OACA,kBAAA,OAAA,oBAAA,OAAA,eAAA,OAAA,YAAA,OAlBJ,kCAqBM,mBAAA,WAAA,sBAAA,OAAA,uBAAA,IAAA,mBAAA,IAAA,eAAA,IArBN,4CAwBQ,cAAA,MACA,aAAA,MAzBR,iCA+BM,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,kBAAA,OAAA,cAAA,OAAA,UAAA,OACA,kBAAA,OAAA,oBAAA,OAAA,eAAA,OAAA,YAAA,OAjCN,uCAsCM,QAAA,sBAAA,QAAA,uBAAA,QAAA,sBAAA,QAAA,eACA,MAAA,KAvCN,sCA4CM,QAAA,MflGN,yBesDA,iDAIQ,SAAA,OACA,MAAA,KALR,iCAUM,cAAA,EACA,aAAA,Gf9EN,yBemEA,sBAgBI,mBAAA,WAAA,sBAAA,OAAA,uBAAA,IAAA,mBAAA,IAAA,eAAA,IACA,kBAAA,OAAA,cAAA,OAAA,UAAA,OACA,kBAAA,OAAA,oBAAA,OAAA,eAAA,OAAA,YAAA,OAlBJ,kCAqBM,mBAAA,WAAA,sBAAA,OAAA,uBAAA,IAAA,mBAAA,IAAA,eAAA,IArBN,4CAwBQ,cAAA,MACA,aAAA,MAzBR,iCA+BM,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,kBAAA,OAAA,cAAA,OAAA,UAAA,OACA,kBAAA,OAAA,oBAAA,OAAA,eAAA,OAAA,YAAA,OAjCN,uCAsCM,QAAA,sBAAA,QAAA,uBAAA,QAAA,sBAAA,QAAA,eACA,MAAA,KAvCN,sCA4CM,QAAA,MflGN,0BesDA,iDAIQ,SAAA,OACA,MAAA,KALR,iCAUM,cAAA,EACA,aAAA,Gf9EN,0BemEA,sBAgBI,mBAAA,WAAA,sBAAA,OAAA,uBAAA,IAAA,mBAAA,IAAA,eAAA,IACA,kBAAA,OAAA,cAAA,OAAA,UAAA,OACA,kBAAA,OAAA,oBAAA,OAAA,eAAA,OAAA,YAAA,OAlBJ,kCAqBM,mBAAA,WAAA,sBAAA,OAAA,uBAAA,IAAA,mBAAA,IAAA,eAAA,IArBN,4CAwBQ,cAAA,MACA,aAAA,MAzBR,iCA+BM,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,kBAAA,OAAA,cAAA,OAAA,UAAA,OACA,kBAAA,OAAA,oBAAA,OAAA,eAAA,OAAA,YAAA,OAjCN,uCAsCM,QAAA,sBAAA,QAAA,uBAAA,QAAA,sBAAA,QAAA,eACA,MAAA,KAvCN,sCA4CM,QAAA,MA5CN,sBAgBI,mBAAA,WAAA,sBAAA,OAAA,uBAAA,IAAA,mBAAA,IAAA,eAAA,IACA,kBAAA,OAAA,cAAA,OAAA,UAAA,OACA,kBAAA,OAAA,oBAAA,OAAA,eAAA,OAAA,YAAA,OAlBJ,iDAIQ,SAAA,OACA,MAAA,KALR,iCAUM,cAAA,EACA,aAAA,EAXN,kCAqBM,mBAAA,WAAA,sBAAA,OAAA,uBAAA,IAAA,mBAAA,IAAA,eAAA,IArBN,4CAwBQ,cAAA,MACA,aAAA,MAzBR,iCA+BM,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,kBAAA,OAAA,cAAA,OAAA,UAAA,OACA,kBAAA,OAAA,oBAAA,OAAA,eAAA,OAAA,YAAA,OAjCN,uCAsCM,QAAA,sBAAA,QAAA,uBAAA,QAAA,sBAAA,QAAA,eACA,MAAA,KAvCN,sCA4CM,QAAA,KAaV,4BAAA,8BAGI,MAAA,eAHJ,kCAAmC,kCAAnC,oCAAA,oCAMM,MAAA,eANN,oCAYM,MAAA,eAZN,0CAA2C,0CAenC,MAAA,eAfR,6CAmBQ,MAAA,eAnBR,4CAAA,2CAAA,yCAAA,0CA2BM,MAAA,eA3BN,8BAgCI,aAAA,eAhCJ,mCAoCI,iBAAA,oPApCJ,2BAwCI,MAAA,eAKJ,8BAAA,gCAGI,MAAA,KAHJ,oCAAqC,oCAArC,sCAAA,sCAMM,MAAA,KANN,sCAYM,MAAA,qBAZN,4CAA6C,4CAerC,MAAA,sBAfR,+CAmBQ,MAAA,sBAnBR,8CAAA,6CAAA,2CAAA,4CA2BM,MAAA,KA3BN,gCAgCI,aAAA,qBAhCJ,qCAoCI,iBAAA,0PApCJ,6BAwCI,MAAA,qBCrQJ,MACE,SAAA,SACA,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,mBAAA,SAAA,sBAAA,OAAA,uBAAA,OAAA,mBAAA,OAAA,eAAA,OACA,iBAAA,KACA,OAAA,IAAA,MAAA,iBrBLE,cAAA,OqBSJ,YAGE,iBAAA,EAAA,aAAA,EAAA,EAAA,KAAA,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,QAAA,QAGF,YACE,cAAA,OAGF,eACE,WAAA,SACA,cAAA,EAGF,sBACE,cAAA,E1BpBE,iB0ByBA,gBAAA,KAFJ,sBAMI,YAAA,QAIJ,2DrBjCI,wBAAA,OACA,uBAAA,OqBgCJ,yDrBnBI,2BAAA,OACA,0BAAA,OqBqCJ,aACE,QAAA,OAAA,QACA,cAAA,EACA,iBAAA,QACA,cAAA,IAAA,MAAA,iBAJF,yBrB1DI,cAAA,mBAAA,mBAAA,EAAA,EqBqEJ,aACE,QAAA,OAAA,QACA,iBAAA,QACA,WAAA,IAAA,MAAA,iBAHF,wBrBrEI,cAAA,EAAA,EAAA,mBAAA,mBqBoFJ,kBACE,aAAA,SACA,cAAA,QACA,YAAA,SACA,cAAA,EAGF,mBACE,aAAA,SACA,YAAA,SAQF,cCtGE,iBAAA,QACA,aAAA,QAEA,2BAAA,2BAEE,iBAAA,YDoGJ,cCzGE,iBAAA,QACA,aAAA,QAEA,2BAAA,2BAEE,iBAAA,YDuGJ,WC5GE,iBAAA,QACA,aAAA,QAEA,wBAAA,wBAEE,iBAAA,YD0GJ,cC/GE,iBAAA,QACA,aAAA,QAEA,2BAAA,2BAEE,iBAAA,YD6GJ,aClHE,iBAAA,QACA,aAAA,QAEA,0BAAA,0BAEE,iBAAA,YDkHJ,sBC7GE,iBAAA,YACA,aAAA,QD+GF,wBChHE,iBAAA,YACA,aAAA,KDkHF,mBCnHE,iBAAA,YACA,aAAA,QDqHF,sBCtHE,iBAAA,YACA,aAAA,QDwHF,sBCzHE,iBAAA,YACA,aAAA,QD2HF,qBC5HE,iBAAA,YACA,aAAA,QDmIF,cC3HE,MAAA,sBAEA,2BAAA,2BAEE,iBAAA,YACA,aAAA,qBAEF,+BAAA,2BAAA,2BAAA,0BAIE,MAAA,KAEF,kDAAA,yBAAA,6BAAA,yBAIE,MAAA,sBAEF,+BAAA,+BAEI,MAAA,KD8GN,iBACE,QAAA,EACA,cAAA,EACA,YAAA,EAIF,UrB5JI,cAAA,mBqBgKJ,kBACE,SAAA,SACA,IAAA,EACA,MAAA,EACA,OAAA,EACA,KAAA,EACA,QAAA,QAMF,crBtKI,wBAAA,mBACA,uBAAA,mBqBwKJ,iBrB3JI,2BAAA,mBACA,0BAAA,mBK+BA,yBgBmIF,WACE,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,kBAAA,IAAA,KAAA,cAAA,IAAA,KAAA,UAAA,IAAA,KAFF,iBAKI,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,iBAAA,EAAA,aAAA,EAAA,EAAA,GAAA,SAAA,EAAA,EAAA,GAAA,KAAA,EAAA,EAAA,GACA,mBAAA,SAAA,sBAAA,OAAA,uBAAA,OAAA,mBAAA,OAAA,eAAA,OAPJ,mCAY0B,YAAA,KAZ1B,kCAayB,aAAA,MhBhJvB,yBgB2JF,YACE,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,kBAAA,IAAA,KAAA,cAAA,IAAA,KAAA,UAAA,IAAA,KAFF,kBAKI,iBAAA,EAAA,aAAA,EAAA,EAAA,GAAA,SAAA,EAAA,EAAA,GAAA,KAAA,EAAA,EAAA,GALJ,wBAQM,YAAA,EACA,YAAA,EATN,8BrBlME,2BAAA,EACA,wBAAA,EqBiMF,4CAkBU,wBAAA,EAlBV,+CAqBU,2BAAA,EArBV,6BrBpLE,0BAAA,EACA,uBAAA,EqBmLF,2CA4BU,uBAAA,EA5BV,8CA+BU,0BAAA,EA/BV,qDAoCQ,cAAA,EApCR,sEAAA,mEAwCU,cAAA,GhBnMR,yBgBiNF,cACE,qBAAA,EAAA,kBAAA,EAAA,aAAA,EACA,mBAAA,QAAA,gBAAA,QAAA,WAAA,QAFF,oBAKI,QAAA,aACA,MAAA,KACA,cAAA,QEhRN,YACE,QAAA,OAAA,KACA,cAAA,KACA,WAAA,KACA,iBAAA,QvBAE,cAAA,OwBHF,mBACE,QAAA,MACA,QAAW,GACX,MAAA,KDKJ,iBACE,MAAA,KADF,0CAKI,QAAA,aACA,cAAA,MACA,aAAA,MACA,MAAA,QACA,QAAiC,IATrC,gDAmBI,gBAAA,UAnBJ,gDAsBI,gBAAA,KAtBJ,wBA0BI,MAAA,QEnCJ,YACE,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KAEA,aAAA,EACA,WAAA,KzBAE,cAAA,OyBIJ,kCAGM,YAAA,EzBoBF,0BAAA,OACA,uBAAA,OyBxBJ,iCzBSI,2BAAA,OACA,wBAAA,OyBVJ,6BAcI,QAAA,EACA,MAAA,KACA,iBAAA,QACA,aAAA,QAjBJ,+BAqBI,MAAA,QACA,eAAA,KACA,OAAA,YACA,iBAAA,KACA,aAAA,KAIJ,WACE,SAAA,SACA,QAAA,MACA,QAAA,MAAA,OACA,YAAA,KACA,YAAA,KACA,MAAA,QACA,iBAAA,KACA,OAAA,IAAA,MAAA,K9BzBE,iBAAA,iB8B4BA,MAAA,QACA,gBAAA,KACA,iBAAA,QACA,aAAA,KChDF,0BACE,QAAA,OAAA,OACA,UAAA,QAKE,iD1BqBF,0BAAA,MACA,uBAAA,M0BjBE,gD1BEF,2BAAA,MACA,wBAAA,M0BfF,0BACE,QAAA,OAAA,MACA,UAAA,QAKE,iD1BqBF,0BAAA,MACA,uBAAA,M0BjBE,gD1BEF,2BAAA,MACA,wBAAA,M2BbJ,OACE,QAAA,aACA,QAAA,MAAA,KACA,UAAA,IACA,YAAA,IACA,YAAA,EACA,MAAA,KACA,WAAA,OACA,YAAA,OACA,eAAA,S3BVE,cAAA,O2BCJ,aAcI,QAAA,KAKJ,YACE,SAAA,SACA,IAAA,KhCNE,cAAA,cgCaA,MAAA,KACA,gBAAA,KACA,OAAA,QASJ,YACE,cAAA,KACA,aAAA,K3B1CE,cAAA,M2BkDJ,eCnDE,iBAAA,QjCiBE,2BAAA,2BiCbE,iBAAA,QDmDN,eCvDE,iBAAA,QjCiBE,2BAAA,2BiCbE,iBAAA,QDuDN,eC3DE,iBAAA,QjCiBE,2BAAA,2BiCbE,iBAAA,QD2DN,YC/DE,iBAAA,QjCiBE,wBAAA,wBiCbE,iBAAA,QD+DN,eCnEE,iBAAA,QjCiBE,2BAAA,2BiCbE,iBAAA,QDmEN,cCvEE,iBAAA,QjCiBE,0BAAA,0BiCbE,iBAAA,QCPN,WACE,QAAA,KAAA,KACA,cAAA,KACA,iBAAA,Q7BCE,cAAA,MKoDA,yBwBxDF,WAOE,QAAA,KAAA,MAIJ,cACE,iBAAA,QAGF,iBACE,cAAA,EACA,aAAA,E7BbE,cAAA,E8BAJ,OACE,QAAA,OAAA,QACA,cAAA,KACA,OAAA,IAAA,MAAA,Y9BHE,cAAA,O8BQJ,eAEE,MAAA,QAIF,YACE,YAAA,IAQF,0BAGI,SAAA,SACA,IAAA,QACA,MAAA,SACA,QAAA,OAAA,QACA,MAAA,QASJ,eCxCE,iBAAA,QACA,aAAA,QACA,MAAA,QAEA,kBACE,iBAAA,QAEF,2BACE,MAAA,QDmCJ,YC3CE,iBAAA,QACA,aAAA,QACA,MAAA,QAEA,eACE,iBAAA,QAEF,wBACE,MAAA,QDsCJ,eC9CE,iBAAA,QACA,aAAA,QACA,MAAA,QAEA,kBACE,iBAAA,QAEF,2BACE,MAAA,QDyCJ,cCjDE,iBAAA,QACA,aAAA,QACA,MAAA,QAEA,iBACE,iBAAA,QAEF,0BACE,MAAA,QCVJ,wCACE,KAAO,oBAAA,KAAA,EACP,GAAK,oBAAA,EAAA,GAFP,mCACE,KAAO,oBAAA,KAAA,EACP,GAAK,oBAAA,EAAA,GAFP,gCACE,KAAO,oBAAA,KAAA,EACP,GAAK,oBAAA,EAAA,GAIP,UACE,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,SAAA,OACA,UAAA,OACA,YAAA,KACA,WAAA,OACA,iBAAA,QhCTE,cAAA,OgCYJ,cACE,OAAA,KACA,MAAA,KACA,iBAAA,QAIF,sBCYE,iBAAA,yKAAA,iBAAA,oKAAA,iBAAA,iKDVA,wBAAA,KAAA,KAAA,gBAAA,KAAA,KAIF,uBACE,kBAAA,qBAAA,GAAA,OAAA,SAAA,aAAA,qBAAA,GAAA,OAAA,SAAA,UAAA,qBAAA,GAAA,OAAA,SE9BF,OACE,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,kBAAA,MAAA,oBAAA,WAAA,eAAA,MAAA,YAAA,WAGF,YACE,iBAAA,EAAA,aAAA,EAAA,EAAA,GAAA,SAAA,EAAA,EAAA,GAAA,KAAA,EAAA,EAAA,GCFF,YACE,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,mBAAA,SAAA,sBAAA,OAAA,uBAAA,OAAA,mBAAA,OAAA,eAAA,OAGA,aAAA,EACA,cAAA,EASF,wBACE,MAAA,KACA,MAAA,QACA,WAAA,QAHF,iDAMI,MAAA,QxCLA,8BAAA,8BwCUA,MAAA,QACA,gBAAA,KACA,iBAAA,QAbJ,+BAiBI,MAAA,QACA,iBAAA,QASJ,iBACE,SAAA,SACA,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,kBAAA,IAAA,KAAA,cAAA,IAAA,KAAA,UAAA,IAAA,KACA,kBAAA,OAAA,oBAAA,OAAA,eAAA,OAAA,YAAA,OACA,QAAA,OAAA,QAEA,cAAA,KACA,iBAAA,KACA,OAAA,IAAA,MAAA,iBATF,6BnCpCI,wBAAA,OACA,uBAAA,OmCmCJ,4BAgBI,cAAA,EnCtCA,2BAAA,OACA,0BAAA,OLLA,uBAAA,uBwC+CA,gBAAA,KArBJ,0BAA2B,0BA0BvB,MAAA,QACA,OAAA,YACA,iBAAA,KA5BJ,mDAAoD,mDAgC9C,MAAA,QAhCN,gDAAiD,gDAmC3C,MAAA,QAnCN,wBAyCI,QAAA,EACA,MAAA,KACA,iBAAA,QACA,aAAA,QA5CJ,iDAAA,wDAAA,uDAkDM,MAAA,QAlDN,8CAsDM,MAAA,QAWN,mCAEI,aAAA,EACA,YAAA,EACA,cAAA,EAJJ,2DASM,WAAA,EATN,yDAeM,cAAA,EC3HJ,yBACE,MAAA,QACA,iBAAA,QAGF,0BAAA,+BACE,MAAA,QADF,mDAAA,wDAII,MAAA,QzCQF,gCAAA,gCAAA,qCAAA,qCyCJE,MAAA,QACA,iBAAA,QATJ,iCAAA,sCAaI,MAAA,KACA,iBAAA,QACA,aAAA,QApBJ,sBACE,MAAA,QACA,iBAAA,QAGF,uBAAA,4BACE,MAAA,QADF,gDAAA,qDAII,MAAA,QzCQF,6BAAA,6BAAA,kCAAA,kCyCJE,MAAA,QACA,iBAAA,QATJ,8BAAA,mCAaI,MAAA,KACA,iBAAA,QACA,aAAA,QApBJ,yBACE,MAAA,QACA,iBAAA,QAGF,0BAAA,+BACE,MAAA,QADF,mDAAA,wDAII,MAAA,QzCQF,gCAAA,gCAAA,qCAAA,qCyCJE,MAAA,QACA,iBAAA,QATJ,iCAAA,sCAaI,MAAA,KACA,iBAAA,QACA,aAAA,QApBJ,wBACE,MAAA,QACA,iBAAA,QAGF,yBAAA,8BACE,MAAA,QADF,kDAAA,uDAII,MAAA,QzCQF,+BAAA,+BAAA,oCAAA,oCyCJE,MAAA,QACA,iBAAA,QATJ,gCAAA,qCAaI,MAAA,KACA,iBAAA,QACA,aAAA,QCrBN,kBACE,SAAA,SACA,QAAA,MACA,MAAA,KACA,QAAA,EACA,SAAA,OALF,0BAQI,QAAA,MACA,QAAW,GATf,yCAAA,wBAAA,yBAAA,yBAAA,wBAiBI,SAAA,SACA,IAAA,EACA,OAAA,EACA,KAAA,EACA,MAAA,KACA,OAAA,KACA,OAAA,EAIJ,gCAEI,YAAA,WAIJ,gCAEI,YAAA,OAIJ,+BAEI,YAAA,IAIJ,+BAEI,YAAA,KCjDJ,OACE,MAAA,MACA,UAAA,OACA,YAAA,IACA,YAAA,EACA,MAAA,KACA,YAAA,EAAA,IAAA,EAAA,KACA,QAAA,G3CaE,aAAA,a2CVA,MAAA,KACA,gBAAA,KACA,OAAA,QACA,QAAA,IAUJ,aACE,QAAA,EACA,OAAA,QACA,WAAA,IACA,OAAA,EACA,mBAAA,KCrBF,YACE,SAAA,OAIF,OACE,SAAA,MACA,IAAA,EACA,MAAA,EACA,OAAA,EACA,KAAA,EACA,QAAA,KACA,QAAA,KACA,SAAA,OAGA,QAAA,EAXF,0BtCGM,mBAAA,kBAAA,IAAA,SAAA,WAAA,kBAAA,IAAA,SAAA,cAAA,aAAA,IAAA,SAAA,WAAA,UAAA,IAAA,SAAA,WAAA,UAAA,IAAA,SAAA,kBAAA,IAAA,SAAA,aAAA,IAAA,SsCgBF,kBAAA,kBAAA,aAAA,kBAAA,UAAA,kBAnBJ,0BAqByB,kBAAA,eAAA,aAAA,eAAA,UAAA,eAEzB,mBACE,WAAA,OACA,WAAA,KAIF,cACE,SAAA,SACA,MAAA,KACA,OAAA,KAIF,eACE,SAAA,SACA,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,mBAAA,SAAA,sBAAA,OAAA,uBAAA,OAAA,mBAAA,OAAA,eAAA,OACA,iBAAA,KACA,wBAAA,YAAA,gBAAA,YACA,OAAA,IAAA,MAAA,evClDE,cAAA,MuCsDF,QAAA,EAIF,gBACE,SAAA,MACA,IAAA,EACA,MAAA,EACA,OAAA,EACA,KAAA,EACA,QAAA,KACA,iBAAA,KAPF,qBAUW,QAAA,EAVX,qBAWW,QAAA,GAKX,cACE,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,kBAAA,OAAA,oBAAA,OAAA,eAAA,OAAA,YAAA,OACA,iBAAA,QAAA,wBAAA,cAAA,cAAA,QAAA,gBAAA,cACA,QAAA,KACA,cAAA,IAAA,MAAA,QAIF,aACE,cAAA,EACA,YAAA,IAKF,YACE,SAAA,SAGA,iBAAA,EAAA,aAAA,EAAA,EAAA,KAAA,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,QAAA,KAIF,cACE,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,kBAAA,OAAA,oBAAA,OAAA,eAAA,OAAA,YAAA,OACA,iBAAA,IAAA,wBAAA,SAAA,cAAA,IAAA,gBAAA,SACA,QAAA,KACA,WAAA,IAAA,MAAA,QALF,iCAQyB,YAAA,OARzB,gCASwB,aAAA,OAIxB,yBACE,SAAA,SACA,IAAA,QACA,MAAA,KACA,OAAA,KACA,SAAA,OlCjEE,yBkCuEF,cACE,UAAA,MACA,OAAA,KAAA,KAOF,UAAY,UAAA,OlChFV,yBkCoFF,UAAY,UAAA,OC3Id,SACE,SAAA,SACA,QAAA,KACA,QAAA,MCHA,YAAA,cAAA,UAAA,mBAAA,WAAA,O/CqP4H,iB+CrP5H,MAAA,WAEA,WAAA,OACA,YAAA,IACA,eAAA,OACA,WAAA,KACA,YAAA,IACA,WAAA,KACA,WAAA,MACA,gBAAA,KACA,YAAA,KACA,eAAA,KACA,YAAA,OACA,WAAA,OACA,aAAA,ODPA,UAAA,QAEA,UAAA,WACA,QAAA,EAVF,cAYW,QAAA,GAZW,2CAAtB,qBAgBI,QAAA,IAAA,EACA,WAAA,KAjByC,kEAA7C,4CAoBM,OAAA,EACA,KAAA,IACA,YAAA,KACA,QAAW,GACX,aAAA,IAAA,IAAA,EACA,iBAAA,KAzBkB,yCAAxB,uBA8BI,QAAA,EAAA,IACA,YAAA,IA/B2C,gEAA/C,8CAkCM,IAAA,IACA,KAAA,EACA,WAAA,KACA,QAAW,GACX,aAAA,IAAA,IAAA,IAAA,EACA,mBAAA,KAvCmB,wCAAzB,wBA4CI,QAAA,IAAA,EACA,WAAA,IA7C4C,+DAAhD,+CAgDM,IAAA,EACA,KAAA,IACA,YAAA,KACA,QAAW,GACX,aAAA,EAAA,IAAA,IACA,oBAAA,KArDiB,0CAAvB,sBA0DI,QAAA,EAAA,IACA,YAAA,KA3D0C,iEAA9C,6CA8DM,IAAA,IACA,MAAA,EACA,WAAA,KACA,QAAW,GACX,aAAA,IAAA,EAAA,IAAA,IACA,kBAAA,KAMN,eACE,UAAA,MACA,QAAA,IAAA,IACA,MAAA,KACA,WAAA,OACA,iBAAA,KxC3EE,cAAA,OwCsEJ,uBASI,SAAA,SACA,MAAA,EACA,OAAA,EACA,aAAA,YACA,aAAA,MEvFJ,SACE,SAAA,SACA,IAAA,EACA,KAAA,EACA,QAAA,KACA,QAAA,MACA,UAAA,MACA,QAAA,IDNA,YAAA,cAAA,UAAA,mBAAA,WAAA,O/CqP4H,iB+CrP5H,MAAA,WAEA,WAAA,OACA,YAAA,IACA,eAAA,OACA,WAAA,KACA,YAAA,IACA,WAAA,KACA,WAAA,MACA,gBAAA,KACA,YAAA,KACA,eAAA,KACA,YAAA,OACA,WAAA,OACA,aAAA,OCJA,UAAA,QAEA,UAAA,WACA,iBAAA,KACA,wBAAA,YAAA,gBAAA,YACA,OAAA,IAAA,MAAA,e1CZE,cAAA,M0CJkB,2CAAtB,qBAyBI,WAAA,MAzB2G,kDAApD,mDAA7B,4BAA9B,6BA6BM,KAAA,IACA,oBAAA,EA9BwB,mDAA9B,6BAkCM,OAAA,MACA,YAAA,MACA,iBAAA,gBApCuB,kDAA7B,4BAwCM,OAAA,MACA,YAAA,MACA,iBAAA,KA1CkB,yCAAxB,uBAgDI,YAAA,KAhD6G,gDAAlD,iDAA/B,8BAAhC,+BAoDM,IAAA,IACA,kBAAA,EArD0B,iDAAhC,+BAyDM,KAAA,MACA,WAAA,MACA,mBAAA,gBA3DyB,gDAA/B,8BA+DM,KAAA,MACA,WAAA,MACA,mBAAA,KAjEmB,wCAAzB,wBAuEI,WAAA,KAvE8G,+CAAjD,gDAAhC,+BAAjC,gCA2EM,KAAA,IACA,iBAAA,EA5E2B,gDAAjC,gCAgFM,IAAA,MACA,YAAA,MACA,oBAAA,gBAlF0B,+CAAhC,+BAsFM,IAAA,MACA,YAAA,MACA,oBAAA,QAxF0C,+DAAhD,+CA6FM,SAAA,SACA,IAAA,EACA,KAAA,IACA,QAAA,MACA,MAAA,KACA,YAAA,MACA,QAAW,GACX,cAAA,IAAA,MAAA,QApGiB,0CAAvB,sBA0GI,YAAA,MA1G4G,iDAAnD,kDAA9B,6BAA/B,8BA8GM,IAAA,IACA,mBAAA,EA/GyB,kDAA/B,8BAmHM,MAAA,MACA,WAAA,MACA,kBAAA,gBArHwB,iDAA9B,6BAyHM,MAAA,MACA,WAAA,MACA,kBAAA,KAON,eACE,QAAA,IAAA,KACA,cAAA,EACA,UAAA,KACA,iBAAA,QACA,cAAA,IAAA,MAAA,Q1C7HE,wBAAA,kBACA,uBAAA,kB0CuHJ,qBAUI,QAAA,KAIJ,iBACE,QAAA,IAAA,KAQF,gBAAA,iBAEE,SAAA,SACA,QAAA,MACA,MAAA,EACA,OAAA,EACA,aAAA,YACA,aAAA,MAGF,iBACE,QAAW,GACX,aAAA,KAEF,gBACE,QAAW,GACX,aAAA,KCxKF,UACE,SAAA,SAGF,gBACE,SAAA,SACA,MAAA,KACA,SAAA,OAGF,eACE,SAAA,SACA,QAAA,KACA,MAAA,KCZA,8BDSA,e1CII,mBAAA,kBAAA,IAAA,YAAA,WAAA,kBAAA,IAAA,YAAA,cAAA,aAAA,IAAA,YAAA,WAAA,UAAA,IAAA,YAAA,WAAA,UAAA,IAAA,YAAA,kBAAA,IAAA,YAAA,aAAA,IAAA,Y0CGF,4BAAA,OAAA,oBAAA,OACA,oBAAA,OAAA,YAAA,QCVuC,qFDEzC,e1CII,mBAAA,kBAAA,IAAA,YAAA,WAAA,kBAAA,IAAA,YAAA,cAAA,aAAA,IAAA,YAAA,WAAA,UAAA,IAAA,YAAA,WAAA,UAAA,IAAA,YAAA,kBAAA,IAAA,YAAA,aAAA,IAAA,Y0CGF,4BAAA,OAAA,oBAAA,OACA,oBAAA,OAAA,YAAA,QAIJ,oBAAA,oBAAA,sBAGE,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KAGF,oBAAA,oBAEE,SAAA,SACA,IAAA,EC9BA,8BDmCA,uCAAA,wCAEE,kBAAA,mBAAA,UAAA,mBAGF,4BAAA,oBAEE,kBAAA,sBAAA,UAAA,sBAGF,2BAAA,oBAEE,kBAAA,uBAAA,UAAA,wBCxCuC,qFD4BzC,uCAAA,wCAEE,kBAAA,mBAAA,UAAA,mBAGF,4BAAA,oBAEE,kBAAA,sBAAA,UAAA,sBAGF,2BAAA,oBAEE,kBAAA,uBAAA,UAAA,wBASJ,uBAAA,uBAEE,SAAA,SACA,IAAA,EACA,OAAA,EAEA,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,kBAAA,OAAA,oBAAA,OAAA,eAAA,OAAA,YAAA,OACA,iBAAA,OAAA,wBAAA,OAAA,cAAA,OAAA,gBAAA,OACA,MAAA,IACA,MAAA,KACA,WAAA,OACA,QAAA,GhDlDE,6BAAA,6BAAA,6BAAA,6BgDwDA,MAAA,KACA,gBAAA,KACA,QAAA,EACA,QAAA,GAGJ,uBACE,KAAA,EAEF,uBACE,MAAA,EAIF,4BAAA,4BAEE,QAAA,aACA,MAAA,KACA,OAAA,KACA,WAAA,YAAA,UAAA,OAAA,OACA,wBAAA,KAAA,KAAA,gBAAA,KAAA,KAEF,4BACE,iBAAA,4LAEF,4BACE,iBAAA,8LASF,qBACE,SAAA,SACA,MAAA,EACA,OAAA,KACA,KAAA,EACA,QAAA,GACA,QAAA,YAAA,QAAA,aAAA,QAAA,YAAA,QAAA,KACA,iBAAA,OAAA,wBAAA,OAAA,cAAA,OAAA,gBAAA,OACA,aAAA,EAEA,aAAA,IACA,YAAA,IACA,WAAA,KAZF,wBAeI,SAAA,SACA,iBAAA,EAAA,aAAA,EAAA,EAAA,KAAA,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,UAAA,KACA,OAAA,IACA,aAAA,IACA,YAAA,IACA,YAAA,OACA,OAAA,QACA,iBAAA,qBAvBJ,gCA2BM,SAAA,SACA,IAAA,MACA,KAAA,EACA,QAAA,aACA,MAAA,KACA,OAAA,KACA,QAAW,GAjCjB,+BAoCM,SAAA,SACA,OAAA,MACA,KAAA,EACA,QAAA,aACA,MAAA,KACA,OAAA,KACA,QAAW,GA1CjB,6BA+CI,iBAAA,KASJ,kBACE,SAAA,SACA,MAAA,IACA,OAAA,KACA,KAAA,IACA,QAAA,GACA,YAAA,KACA,eAAA,KACA,MAAA,KACA,WAAA,OEhLF,gBAAqB,eAAA,mBACrB,WAAqB,eAAA,cACrB,cAAqB,eAAA,iBACrB,cAAqB,eAAA,iBACrB,mBAAqB,eAAA,sBACrB,gBAAqB,eAAA,mBCDrB,UACE,iBAAA,QCFA,YACE,iBAAA,kBpDgBA,mBAAA,mBoDZE,iBAAA,kBALJ,YACE,iBAAA,kBpDgBA,mBAAA,mBoDZE,iBAAA,kBALJ,SACE,iBAAA,kBpDgBA,gBAAA,gBoDZE,iBAAA,kBALJ,YACE,iBAAA,kBpDgBA,mBAAA,mBoDZE,iBAAA,kBALJ,WACE,iBAAA,kBpDgBA,kBAAA,kBoDZE,iBAAA,kBALJ,YACE,iBAAA,kBpDgBA,mBAAA,mBoDZE,iBAAA,kBCJN,UAAmB,OAAA,YACnB,cAAmB,WAAA,YACnB,gBAAmB,aAAA,YACnB,iBAAmB,cAAA,YACnB,eAAmB,YAAA,YAMnB,ShDVI,cAAA,OgDaJ,ahDPI,wBAAA,OACA,uBAAA,OgDSJ,ehDHI,2BAAA,OACA,wBAAA,OgDKJ,gBhDCI,2BAAA,OACA,0BAAA,OgDCJ,chDKI,0BAAA,OACA,uBAAA,OgDFJ,gBACE,cAAA,IAGF,WACE,cAAA,ExBlCA,iBACE,QAAA,MACA,QAAW,GACX,MAAA,KyBIA,QAAE,QAAA,eACF,UAAE,QAAA,iBACF,gBAAE,QAAA,uBACF,SAAE,QAAA,gBACF,SAAE,QAAA,gBACF,cAAE,QAAA,qBACF,QAAE,QAAA,sBAAA,QAAA,uBAAA,QAAA,sBAAA,QAAA,eACF,eAAE,QAAA,6BAAA,QAAA,8BAAA,QAAA,6BAAA,QAAA,sB5CyCF,yB4ChDA,WAAE,QAAA,eACF,aAAE,QAAA,iBACF,mBAAE,QAAA,uBACF,YAAE,QAAA,gBACF,YAAE,QAAA,gBACF,iBAAE,QAAA,qBACF,WAAE,QAAA,sBAAA,QAAA,uBAAA,QAAA,sBAAA,QAAA,eACF,kBAAE,QAAA,6BAAA,QAAA,8BAAA,QAAA,6BAAA,QAAA,uB5CyCF,yB4ChDA,WAAE,QAAA,eACF,aAAE,QAAA,iBACF,mBAAE,QAAA,uBACF,YAAE,QAAA,gBACF,YAAE,QAAA,gBACF,iBAAE,QAAA,qBACF,WAAE,QAAA,sBAAA,QAAA,uBAAA,QAAA,sBAAA,QAAA,eACF,kBAAE,QAAA,6BAAA,QAAA,8BAAA,QAAA,6BAAA,QAAA,uB5CyCF,yB4ChDA,WAAE,QAAA,eACF,aAAE,QAAA,iBACF,mBAAE,QAAA,uBACF,YAAE,QAAA,gBACF,YAAE,QAAA,gBACF,iBAAE,QAAA,qBACF,WAAE,QAAA,sBAAA,QAAA,uBAAA,QAAA,sBAAA,QAAA,eACF,kBAAE,QAAA,6BAAA,QAAA,8BAAA,QAAA,6BAAA,QAAA,uB5CyCF,0B4ChDA,WAAE,QAAA,eACF,aAAE,QAAA,iBACF,mBAAE,QAAA,uBACF,YAAE,QAAA,gBACF,YAAE,QAAA,gBACF,iBAAE,QAAA,qBACF,WAAE,QAAA,sBAAA,QAAA,uBAAA,QAAA,sBAAA,QAAA,eACF,kBAAE,QAAA,6BAAA,QAAA,8BAAA,QAAA,6BAAA,QAAA,uBCPF,YAAE,0BAAA,EAAA,cAAA,GAAA,eAAA,GAAA,MAAA,GACF,WAAE,0BAAA,EAAA,cAAA,EAAA,eAAA,EAAA,MAAA,EACF,gBAAE,0BAAA,EAAA,cAAA,EAAA,eAAA,EAAA,MAAA,EAEF,UAAE,mBAAA,qBAAA,sBAAA,iBAAA,uBAAA,cAAA,mBAAA,cAAA,eAAA,cACF,aAAE,mBAAA,mBAAA,sBAAA,iBAAA,uBAAA,iBAAA,mBAAA,iBAAA,eAAA,iBACF,kBAAE,mBAAA,qBAAA,sBAAA,kBAAA,uBAAA,sBAAA,mBAAA,sBAAA,eAAA,sBACF,qBAAE,mBAAA,mBAAA,sBAAA,kBAAA,uBAAA,yBAAA,mBAAA,yBAAA,eAAA,yBAEF,WAAE,kBAAA,eAAA,cAAA,eAAA,UAAA,eACF,aAAE,kBAAA,iBAAA,cAAA,iBAAA,UAAA,iBACF,mBAAE,kBAAA,uBAAA,cAAA,uBAAA,UAAA,uBAEF,uBAAE,iBAAA,gBAAA,wBAAA,qBAAA,cAAA,gBAAA,gBAAA,qBACF,qBAAE,iBAAA,cAAA,wBAAA,mBAAA,cAAA,cAAA,gBAAA,mBACF,wBAAE,iBAAA,iBAAA,wBAAA,iBAAA,cAAA,iBAAA,gBAAA,iBACF,yBAAE,iBAAA,kBAAA,wBAAA,wBAAA,cAAA,kBAAA,gBAAA,wBACF,wBAAE,wBAAA,uBAAA,cAAA,qBAAA,gBAAA,uBAEF,mBAAE,kBAAA,gBAAA,oBAAA,qBAAA,eAAA,gBAAA,YAAA,qBACF,iBAAE,kBAAA,cAAA,oBAAA,mBAAA,eAAA,cAAA,YAAA,mBACF,oBAAE,kBAAA,iBAAA,oBAAA,iBAAA,eAAA,iBAAA,YAAA,iBACF,sBAAE,kBAAA,mBAAA,oBAAA,mBAAA,eAAA,mBAAA,YAAA,mBACF,qBAAE,kBAAA,kBAAA,oBAAA,kBAAA,eAAA,kBAAA,YAAA,kBAEF,qBAAE,sBAAA,qBAAA,mBAAA,gBAAA,cAAA,qBACF,mBAAE,sBAAA,mBAAA,mBAAA,cAAA,cAAA,mBACF,sBAAE,sBAAA,iBAAA,mBAAA,iBAAA,cAAA,iBACF,uBAAE,sBAAA,wBAAA,mBAAA,kBAAA,cAAA,wBACF,sBAAE,sBAAA,uBAAA,mBAAA,qBAAA,cAAA,uBACF,uBAAE,sBAAA,kBAAA,mBAAA,kBAAA,cAAA,kBAEF,iBAAE,mBAAA,eAAA,oBAAA,eAAA,mBAAA,eAAA,WAAA,eACF,kBAAE,mBAAA,qBAAA,oBAAA,gBAAA,WAAA,qBACF,gBAAE,mBAAA,mBAAA,oBAAA,cAAA,WAAA,mBACF,mBAAE,mBAAA,iBAAA,oBAAA,iBAAA,mBAAA,iBAAA,WAAA,iBACF,qBAAE,mBAAA,mBAAA,oBAAA,mBAAA,WAAA,mBACF,oBAAE,mBAAA,kBAAA,oBAAA,kBAAA,mBAAA,kBAAA,WAAA,kB7CWF,yB6ChDA,eAAE,0BAAA,EAAA,cAAA,GAAA,eAAA,GAAA,MAAA,GACF,cAAE,0BAAA,EAAA,cAAA,EAAA,eAAA,EAAA,MAAA,EACF,mBAAE,0BAAA,EAAA,cAAA,EAAA,eAAA,EAAA,MAAA,EAEF,aAAE,mBAAA,qBAAA,sBAAA,iBAAA,uBAAA,cAAA,mBAAA,cAAA,eAAA,cACF,gBAAE,mBAAA,mBAAA,sBAAA,iBAAA,uBAAA,iBAAA,mBAAA,iBAAA,eAAA,iBACF,qBAAE,mBAAA,qBAAA,sBAAA,kBAAA,uBAAA,sBAAA,mBAAA,sBAAA,eAAA,sBACF,wBAAE,mBAAA,mBAAA,sBAAA,kBAAA,uBAAA,yBAAA,mBAAA,yBAAA,eAAA,yBAEF,cAAE,kBAAA,eAAA,cAAA,eAAA,UAAA,eACF,gBAAE,kBAAA,iBAAA,cAAA,iBAAA,UAAA,iBACF,sBAAE,kBAAA,uBAAA,cAAA,uBAAA,UAAA,uBAEF,0BAAE,iBAAA,gBAAA,wBAAA,qBAAA,cAAA,gBAAA,gBAAA,qBACF,wBAAE,iBAAA,cAAA,wBAAA,mBAAA,cAAA,cAAA,gBAAA,mBACF,2BAAE,iBAAA,iBAAA,wBAAA,iBAAA,cAAA,iBAAA,gBAAA,iBACF,4BAAE,iBAAA,kBAAA,wBAAA,wBAAA,cAAA,kBAAA,gBAAA,wBACF,2BAAE,wBAAA,uBAAA,cAAA,qBAAA,gBAAA,uBAEF,sBAAE,kBAAA,gBAAA,oBAAA,qBAAA,eAAA,gBAAA,YAAA,qBACF,oBAAE,kBAAA,cAAA,oBAAA,mBAAA,eAAA,cAAA,YAAA,mBACF,uBAAE,kBAAA,iBAAA,oBAAA,iBAAA,eAAA,iBAAA,YAAA,iBACF,yBAAE,kBAAA,mBAAA,oBAAA,mBAAA,eAAA,mBAAA,YAAA,mBACF,wBAAE,kBAAA,kBAAA,oBAAA,kBAAA,eAAA,kBAAA,YAAA,kBAEF,wBAAE,sBAAA,qBAAA,mBAAA,gBAAA,cAAA,qBACF,sBAAE,sBAAA,mBAAA,mBAAA,cAAA,cAAA,mBACF,yBAAE,sBAAA,iBAAA,mBAAA,iBAAA,cAAA,iBACF,0BAAE,sBAAA,wBAAA,mBAAA,kBAAA,cAAA,wBACF,yBAAE,sBAAA,uBAAA,mBAAA,qBAAA,cAAA,uBACF,0BAAE,sBAAA,kBAAA,mBAAA,kBAAA,cAAA,kBAEF,oBAAE,mBAAA,eAAA,oBAAA,eAAA,mBAAA,eAAA,WAAA,eACF,qBAAE,mBAAA,qBAAA,oBAAA,gBAAA,WAAA,qBACF,mBAAE,mBAAA,mBAAA,oBAAA,cAAA,WAAA,mBACF,sBAAE,mBAAA,iBAAA,oBAAA,iBAAA,mBAAA,iBAAA,WAAA,iBACF,wBAAE,mBAAA,mBAAA,oBAAA,mBAAA,WAAA,mBACF,uBAAE,mBAAA,kBAAA,oBAAA,kBAAA,mBAAA,kBAAA,WAAA,mB7CWF,yB6ChDA,eAAE,0BAAA,EAAA,cAAA,GAAA,eAAA,GAAA,MAAA,GACF,cAAE,0BAAA,EAAA,cAAA,EAAA,eAAA,EAAA,MAAA,EACF,mBAAE,0BAAA,EAAA,cAAA,EAAA,eAAA,EAAA,MAAA,EAEF,aAAE,mBAAA,qBAAA,sBAAA,iBAAA,uBAAA,cAAA,mBAAA,cAAA,eAAA,cACF,gBAAE,mBAAA,mBAAA,sBAAA,iBAAA,uBAAA,iBAAA,mBAAA,iBAAA,eAAA,iBACF,qBAAE,mBAAA,qBAAA,sBAAA,kBAAA,uBAAA,sBAAA,mBAAA,sBAAA,eAAA,sBACF,wBAAE,mBAAA,mBAAA,sBAAA,kBAAA,uBAAA,yBAAA,mBAAA,yBAAA,eAAA,yBAEF,cAAE,kBAAA,eAAA,cAAA,eAAA,UAAA,eACF,gBAAE,kBAAA,iBAAA,cAAA,iBAAA,UAAA,iBACF,sBAAE,kBAAA,uBAAA,cAAA,uBAAA,UAAA,uBAEF,0BAAE,iBAAA,gBAAA,wBAAA,qBAAA,cAAA,gBAAA,gBAAA,qBACF,wBAAE,iBAAA,cAAA,wBAAA,mBAAA,cAAA,cAAA,gBAAA,mBACF,2BAAE,iBAAA,iBAAA,wBAAA,iBAAA,cAAA,iBAAA,gBAAA,iBACF,4BAAE,iBAAA,kBAAA,wBAAA,wBAAA,cAAA,kBAAA,gBAAA,wBACF,2BAAE,wBAAA,uBAAA,cAAA,qBAAA,gBAAA,uBAEF,sBAAE,kBAAA,gBAAA,oBAAA,qBAAA,eAAA,gBAAA,YAAA,qBACF,oBAAE,kBAAA,cAAA,oBAAA,mBAAA,eAAA,cAAA,YAAA,mBACF,uBAAE,kBAAA,iBAAA,oBAAA,iBAAA,eAAA,iBAAA,YAAA,iBACF,yBAAE,kBAAA,mBAAA,oBAAA,mBAAA,eAAA,mBAAA,YAAA,mBACF,wBAAE,kBAAA,kBAAA,oBAAA,kBAAA,eAAA,kBAAA,YAAA,kBAEF,wBAAE,sBAAA,qBAAA,mBAAA,gBAAA,cAAA,qBACF,sBAAE,sBAAA,mBAAA,mBAAA,cAAA,cAAA,mBACF,yBAAE,sBAAA,iBAAA,mBAAA,iBAAA,cAAA,iBACF,0BAAE,sBAAA,wBAAA,mBAAA,kBAAA,cAAA,wBACF,yBAAE,sBAAA,uBAAA,mBAAA,qBAAA,cAAA,uBACF,0BAAE,sBAAA,kBAAA,mBAAA,kBAAA,cAAA,kBAEF,oBAAE,mBAAA,eAAA,oBAAA,eAAA,mBAAA,eAAA,WAAA,eACF,qBAAE,mBAAA,qBAAA,oBAAA,gBAAA,WAAA,qBACF,mBAAE,mBAAA,mBAAA,oBAAA,cAAA,WAAA,mBACF,sBAAE,mBAAA,iBAAA,oBAAA,iBAAA,mBAAA,iBAAA,WAAA,iBACF,wBAAE,mBAAA,mBAAA,oBAAA,mBAAA,WAAA,mBACF,uBAAE,mBAAA,kBAAA,oBAAA,kBAAA,mBAAA,kBAAA,WAAA,mB7CWF,yB6ChDA,eAAE,0BAAA,EAAA,cAAA,GAAA,eAAA,GAAA,MAAA,GACF,cAAE,0BAAA,EAAA,cAAA,EAAA,eAAA,EAAA,MAAA,EACF,mBAAE,0BAAA,EAAA,cAAA,EAAA,eAAA,EAAA,MAAA,EAEF,aAAE,mBAAA,qBAAA,sBAAA,iBAAA,uBAAA,cAAA,mBAAA,cAAA,eAAA,cACF,gBAAE,mBAAA,mBAAA,sBAAA,iBAAA,uBAAA,iBAAA,mBAAA,iBAAA,eAAA,iBACF,qBAAE,mBAAA,qBAAA,sBAAA,kBAAA,uBAAA,sBAAA,mBAAA,sBAAA,eAAA,sBACF,wBAAE,mBAAA,mBAAA,sBAAA,kBAAA,uBAAA,yBAAA,mBAAA,yBAAA,eAAA,yBAEF,cAAE,kBAAA,eAAA,cAAA,eAAA,UAAA,eACF,gBAAE,kBAAA,iBAAA,cAAA,iBAAA,UAAA,iBACF,sBAAE,kBAAA,uBAAA,cAAA,uBAAA,UAAA,uBAEF,0BAAE,iBAAA,gBAAA,wBAAA,qBAAA,cAAA,gBAAA,gBAAA,qBACF,wBAAE,iBAAA,cAAA,wBAAA,mBAAA,cAAA,cAAA,gBAAA,mBACF,2BAAE,iBAAA,iBAAA,wBAAA,iBAAA,cAAA,iBAAA,gBAAA,iBACF,4BAAE,iBAAA,kBAAA,wBAAA,wBAAA,cAAA,kBAAA,gBAAA,wBACF,2BAAE,wBAAA,uBAAA,cAAA,qBAAA,gBAAA,uBAEF,sBAAE,kBAAA,gBAAA,oBAAA,qBAAA,eAAA,gBAAA,YAAA,qBACF,oBAAE,kBAAA,cAAA,oBAAA,mBAAA,eAAA,cAAA,YAAA,mBACF,uBAAE,kBAAA,iBAAA,oBAAA,iBAAA,eAAA,iBAAA,YAAA,iBACF,yBAAE,kBAAA,mBAAA,oBAAA,mBAAA,eAAA,mBAAA,YAAA,mBACF,wBAAE,kBAAA,kBAAA,oBAAA,kBAAA,eAAA,kBAAA,YAAA,kBAEF,wBAAE,sBAAA,qBAAA,mBAAA,gBAAA,cAAA,qBACF,sBAAE,sBAAA,mBAAA,mBAAA,cAAA,cAAA,mBACF,yBAAE,sBAAA,iBAAA,mBAAA,iBAAA,cAAA,iBACF,0BAAE,sBAAA,wBAAA,mBAAA,kBAAA,cAAA,wBACF,yBAAE,sBAAA,uBAAA,mBAAA,qBAAA,cAAA,uBACF,0BAAE,sBAAA,kBAAA,mBAAA,kBAAA,cAAA,kBAEF,oBAAE,mBAAA,eAAA,oBAAA,eAAA,mBAAA,eAAA,WAAA,eACF,qBAAE,mBAAA,qBAAA,oBAAA,gBAAA,WAAA,qBACF,mBAAE,mBAAA,mBAAA,oBAAA,cAAA,WAAA,mBACF,sBAAE,mBAAA,iBAAA,oBAAA,iBAAA,mBAAA,iBAAA,WAAA,iBACF,wBAAE,mBAAA,mBAAA,oBAAA,mBAAA,WAAA,mBACF,uBAAE,mBAAA,kBAAA,oBAAA,kBAAA,mBAAA,kBAAA,WAAA,mB7CWF,0B6ChDA,eAAE,0BAAA,EAAA,cAAA,GAAA,eAAA,GAAA,MAAA,GACF,cAAE,0BAAA,EAAA,cAAA,EAAA,eAAA,EAAA,MAAA,EACF,mBAAE,0BAAA,EAAA,cAAA,EAAA,eAAA,EAAA,MAAA,EAEF,aAAE,mBAAA,qBAAA,sBAAA,iBAAA,uBAAA,cAAA,mBAAA,cAAA,eAAA,cACF,gBAAE,mBAAA,mBAAA,sBAAA,iBAAA,uBAAA,iBAAA,mBAAA,iBAAA,eAAA,iBACF,qBAAE,mBAAA,qBAAA,sBAAA,kBAAA,uBAAA,sBAAA,mBAAA,sBAAA,eAAA,sBACF,wBAAE,mBAAA,mBAAA,sBAAA,kBAAA,uBAAA,yBAAA,mBAAA,yBAAA,eAAA,yBAEF,cAAE,kBAAA,eAAA,cAAA,eAAA,UAAA,eACF,gBAAE,kBAAA,iBAAA,cAAA,iBAAA,UAAA,iBACF,sBAAE,kBAAA,uBAAA,cAAA,uBAAA,UAAA,uBAEF,0BAAE,iBAAA,gBAAA,wBAAA,qBAAA,cAAA,gBAAA,gBAAA,qBACF,wBAAE,iBAAA,cAAA,wBAAA,mBAAA,cAAA,cAAA,gBAAA,mBACF,2BAAE,iBAAA,iBAAA,wBAAA,iBAAA,cAAA,iBAAA,gBAAA,iBACF,4BAAE,iBAAA,kBAAA,wBAAA,wBAAA,cAAA,kBAAA,gBAAA,wBACF,2BAAE,wBAAA,uBAAA,cAAA,qBAAA,gBAAA,uBAEF,sBAAE,kBAAA,gBAAA,oBAAA,qBAAA,eAAA,gBAAA,YAAA,qBACF,oBAAE,kBAAA,cAAA,oBAAA,mBAAA,eAAA,cAAA,YAAA,mBACF,uBAAE,kBAAA,iBAAA,oBAAA,iBAAA,eAAA,iBAAA,YAAA,iBACF,yBAAE,kBAAA,mBAAA,oBAAA,mBAAA,eAAA,mBAAA,YAAA,mBACF,wBAAE,kBAAA,kBAAA,oBAAA,kBAAA,eAAA,kBAAA,YAAA,kBAEF,wBAAE,sBAAA,qBAAA,mBAAA,gBAAA,cAAA,qBACF,sBAAE,sBAAA,mBAAA,mBAAA,cAAA,cAAA,mBACF,yBAAE,sBAAA,iBAAA,mBAAA,iBAAA,cAAA,iBACF,0BAAE,sBAAA,wBAAA,mBAAA,kBAAA,cAAA,wBACF,yBAAE,sBAAA,uBAAA,mBAAA,qBAAA,cAAA,uBACF,0BAAE,sBAAA,kBAAA,mBAAA,kBAAA,cAAA,kBAEF,oBAAE,mBAAA,eAAA,oBAAA,eAAA,mBAAA,eAAA,WAAA,eACF,qBAAE,mBAAA,qBAAA,oBAAA,gBAAA,WAAA,qBACF,mBAAE,mBAAA,mBAAA,oBAAA,cAAA,WAAA,mBACF,sBAAE,mBAAA,iBAAA,oBAAA,iBAAA,mBAAA,iBAAA,WAAA,iBACF,wBAAE,mBAAA,mBAAA,oBAAA,mBAAA,WAAA,mBACF,uBAAE,mBAAA,kBAAA,oBAAA,kBAAA,mBAAA,kBAAA,WAAA,mBCzCF,YCHF,MAAA,eDIE,aCDF,MAAA,gBDEE,YCCF,MAAA,e/CiDE,yB8CpDA,eCHF,MAAA,eDIE,gBCDF,MAAA,gBDEE,eCCF,MAAA,gB/CiDE,yB8CpDA,eCHF,MAAA,eDIE,gBCDF,MAAA,gBDEE,eCCF,MAAA,gB/CiDE,yB8CpDA,eCHF,MAAA,eDIE,gBCDF,MAAA,gBDEE,eCCF,MAAA,gB/CiDE,0B8CpDA,eCHF,MAAA,eDIE,gBCDF,MAAA,gBDEE,eCCF,MAAA,gBCLF,WACE,SAAA,MACA,IAAA,EACA,MAAA,EACA,KAAA,EACA,QAAA,KAGF,cACE,SAAA,MACA,MAAA,EACA,OAAA,EACA,KAAA,EACA,QAAA,KAGF,YACE,SAAA,eAAA,SAAA,OACA,IAAA,EACA,QAAA,KCjBF,SCCE,SAAA,SACA,MAAA,IACA,OAAA,IACA,QAAA,EACA,OAAA,KACA,SAAA,OACA,KAAA,cACA,OAAA,EAUA,0BAAA,yBAEE,SAAA,OACA,MAAA,KACA,OAAA,KACA,OAAA,EACA,SAAA,QACA,KAAA,KCzBA,MAAE,MAAA,cAAF,MAAE,MAAA,cAAF,MAAE,MAAA,cAAF,OAAE,MAAA,eAAF,MAAE,OAAA,cAAF,MAAE,OAAA,cAAF,MAAE,OAAA,cAAF,OAAE,OAAA,eAIN,QAAU,UAAA,eACV,QAAU,WAAA,eCEF,KAAE,OAAA,EAAA,YACF,MAAE,WAAA,YACF,MAAE,aAAA,YACF,MAAE,cAAA,YACF,MAAE,YAAA,YACF,MACE,aAAA,YACA,YAAA,YAEF,MACE,WAAA,YACA,cAAA,YAXF,KAAE,OAAA,OAAA,iBACF,MAAE,WAAA,iBACF,MAAE,aAAA,iBACF,MAAE,cAAA,iBACF,MAAE,YAAA,iBACF,MACE,aAAA,iBACA,YAAA,iBAEF,MACE,WAAA,iBACA,cAAA,iBAXF,KAAE,OAAA,MAAA,gBACF,MAAE,WAAA,gBACF,MAAE,aAAA,gBACF,MAAE,cAAA,gBACF,MAAE,YAAA,gBACF,MACE,aAAA,gBACA,YAAA,gBAEF,MACE,WAAA,gBACA,cAAA,gBAXF,KAAE,OAAA,KAAA,eACF,MAAE,WAAA,eACF,MAAE,aAAA,eACF,MAAE,cAAA,eACF,MAAE,YAAA,eACF,MACE,aAAA,eACA,YAAA,eAEF,MACE,WAAA,eACA,cAAA,eAXF,KAAE,OAAA,OAAA,iBACF,MAAE,WAAA,iBACF,MAAE,aAAA,iBACF,MAAE,cAAA,iBACF,MAAE,YAAA,iBACF,MACE,aAAA,iBACA,YAAA,iBAEF,MACE,WAAA,iBACA,cAAA,iBAXF,KAAE,OAAA,KAAA,eACF,MAAE,WAAA,eACF,MAAE,aAAA,eACF,MAAE,cAAA,eACF,MAAE,YAAA,eACF,MACE,aAAA,eACA,YAAA,eAEF,MACE,WAAA,eACA,cAAA,eAXF,KAAE,QAAA,EAAA,YACF,MAAE,YAAA,YACF,MAAE,cAAA,YACF,MAAE,eAAA,YACF,MAAE,aAAA,YACF,MACE,cAAA,YACA,aAAA,YAEF,MACE,YAAA,YACA,eAAA,YAXF,KAAE,QAAA,OAAA,iBACF,MAAE,YAAA,iBACF,MAAE,cAAA,iBACF,MAAE,eAAA,iBACF,MAAE,aAAA,iBACF,MACE,cAAA,iBACA,aAAA,iBAEF,MACE,YAAA,iBACA,eAAA,iBAXF,KAAE,QAAA,MAAA,gBACF,MAAE,YAAA,gBACF,MAAE,cAAA,gBACF,MAAE,eAAA,gBACF,MAAE,aAAA,gBACF,MACE,cAAA,gBACA,aAAA,gBAEF,MACE,YAAA,gBACA,eAAA,gBAXF,KAAE,QAAA,KAAA,eACF,MAAE,YAAA,eACF,MAAE,cAAA,eACF,MAAE,eAAA,eACF,MAAE,aAAA,eACF,MACE,cAAA,eACA,aAAA,eAEF,MACE,YAAA,eACA,eAAA,eAXF,KAAE,QAAA,OAAA,iBACF,MAAE,YAAA,iBACF,MAAE,cAAA,iBACF,MAAE,eAAA,iBACF,MAAE,aAAA,iBACF,MACE,cAAA,iBACA,aAAA,iBAEF,MACE,YAAA,iBACA,eAAA,iBAXF,KAAE,QAAA,KAAA,eACF,MAAE,YAAA,eACF,MAAE,cAAA,eACF,MAAE,eAAA,eACF,MAAE,aAAA,eACF,MACE,cAAA,eACA,aAAA,eAEF,MACE,YAAA,eACA,eAAA,eAMN,QAAE,OAAA,eACF,SAAE,WAAA,eACF,SAAE,aAAA,eACF,SAAE,cAAA,eACF,SAAE,YAAA,eACF,SACE,aAAA,eACA,YAAA,eAEF,SACE,WAAA,eACA,cAAA,epDiBF,yBoD7CI,QAAE,OAAA,EAAA,YACF,SAAE,WAAA,YACF,SAAE,aAAA,YACF,SAAE,cAAA,YACF,SAAE,YAAA,YACF,SACE,aAAA,YACA,YAAA,YAEF,SACE,WAAA,YACA,cAAA,YAXF,QAAE,OAAA,OAAA,iBACF,SAAE,WAAA,iBACF,SAAE,aAAA,iBACF,SAAE,cAAA,iBACF,SAAE,YAAA,iBACF,SACE,aAAA,iBACA,YAAA,iBAEF,SACE,WAAA,iBACA,cAAA,iBAXF,QAAE,OAAA,MAAA,gBACF,SAAE,WAAA,gBACF,SAAE,aAAA,gBACF,SAAE,cAAA,gBACF,SAAE,YAAA,gBACF,SACE,aAAA,gBACA,YAAA,gBAEF,SACE,WAAA,gBACA,cAAA,gBAXF,QAAE,OAAA,KAAA,eACF,SAAE,WAAA,eACF,SAAE,aAAA,eACF,SAAE,cAAA,eACF,SAAE,YAAA,eACF,SACE,aAAA,eACA,YAAA,eAEF,SACE,WAAA,eACA,cAAA,eAXF,QAAE,OAAA,OAAA,iBACF,SAAE,WAAA,iBACF,SAAE,aAAA,iBACF,SAAE,cAAA,iBACF,SAAE,YAAA,iBACF,SACE,aAAA,iBACA,YAAA,iBAEF,SACE,WAAA,iBACA,cAAA,iBAXF,QAAE,OAAA,KAAA,eACF,SAAE,WAAA,eACF,SAAE,aAAA,eACF,SAAE,cAAA,eACF,SAAE,YAAA,eACF,SACE,aAAA,eACA,YAAA,eAEF,SACE,WAAA,eACA,cAAA,eAXF,QAAE,QAAA,EAAA,YACF,SAAE,YAAA,YACF,SAAE,cAAA,YACF,SAAE,eAAA,YACF,SAAE,aAAA,YACF,SACE,cAAA,YACA,aAAA,YAEF,SACE,YAAA,YACA,eAAA,YAXF,QAAE,QAAA,OAAA,iBACF,SAAE,YAAA,iBACF,SAAE,cAAA,iBACF,SAAE,eAAA,iBACF,SAAE,aAAA,iBACF,SACE,cAAA,iBACA,aAAA,iBAEF,SACE,YAAA,iBACA,eAAA,iBAXF,QAAE,QAAA,MAAA,gBACF,SAAE,YAAA,gBACF,SAAE,cAAA,gBACF,SAAE,eAAA,gBACF,SAAE,aAAA,gBACF,SACE,cAAA,gBACA,aAAA,gBAEF,SACE,YAAA,gBACA,eAAA,gBAXF,QAAE,QAAA,KAAA,eACF,SAAE,YAAA,eACF,SAAE,cAAA,eACF,SAAE,eAAA,eACF,SAAE,aAAA,eACF,SACE,cAAA,eACA,aAAA,eAEF,SACE,YAAA,eACA,eAAA,eAXF,QAAE,QAAA,OAAA,iBACF,SAAE,YAAA,iBACF,SAAE,cAAA,iBACF,SAAE,eAAA,iBACF,SAAE,aAAA,iBACF,SACE,cAAA,iBACA,aAAA,iBAEF,SACE,YAAA,iBACA,eAAA,iBAXF,QAAE,QAAA,KAAA,eACF,SAAE,YAAA,eACF,SAAE,cAAA,eACF,SAAE,eAAA,eACF,SAAE,aAAA,eACF,SACE,cAAA,eACA,aAAA,eAEF,SACE,YAAA,eACA,eAAA,eAMN,WAAE,OAAA,eACF,YAAE,WAAA,eACF,YAAE,aAAA,eACF,YAAE,cAAA,eACF,YAAE,YAAA,eACF,YACE,aAAA,eACA,YAAA,eAEF,YACE,WAAA,eACA,cAAA,gBpDiBF,yBoD7CI,QAAE,OAAA,EAAA,YACF,SAAE,WAAA,YACF,SAAE,aAAA,YACF,SAAE,cAAA,YACF,SAAE,YAAA,YACF,SACE,aAAA,YACA,YAAA,YAEF,SACE,WAAA,YACA,cAAA,YAXF,QAAE,OAAA,OAAA,iBACF,SAAE,WAAA,iBACF,SAAE,aAAA,iBACF,SAAE,cAAA,iBACF,SAAE,YAAA,iBACF,SACE,aAAA,iBACA,YAAA,iBAEF,SACE,WAAA,iBACA,cAAA,iBAXF,QAAE,OAAA,MAAA,gBACF,SAAE,WAAA,gBACF,SAAE,aAAA,gBACF,SAAE,cAAA,gBACF,SAAE,YAAA,gBACF,SACE,aAAA,gBACA,YAAA,gBAEF,SACE,WAAA,gBACA,cAAA,gBAXF,QAAE,OAAA,KAAA,eACF,SAAE,WAAA,eACF,SAAE,aAAA,eACF,SAAE,cAAA,eACF,SAAE,YAAA,eACF,SACE,aAAA,eACA,YAAA,eAEF,SACE,WAAA,eACA,cAAA,eAXF,QAAE,OAAA,OAAA,iBACF,SAAE,WAAA,iBACF,SAAE,aAAA,iBACF,SAAE,cAAA,iBACF,SAAE,YAAA,iBACF,SACE,aAAA,iBACA,YAAA,iBAEF,SACE,WAAA,iBACA,cAAA,iBAXF,QAAE,OAAA,KAAA,eACF,SAAE,WAAA,eACF,SAAE,aAAA,eACF,SAAE,cAAA,eACF,SAAE,YAAA,eACF,SACE,aAAA,eACA,YAAA,eAEF,SACE,WAAA,eACA,cAAA,eAXF,QAAE,QAAA,EAAA,YACF,SAAE,YAAA,YACF,SAAE,cAAA,YACF,SAAE,eAAA,YACF,SAAE,aAAA,YACF,SACE,cAAA,YACA,aAAA,YAEF,SACE,YAAA,YACA,eAAA,YAXF,QAAE,QAAA,OAAA,iBACF,SAAE,YAAA,iBACF,SAAE,cAAA,iBACF,SAAE,eAAA,iBACF,SAAE,aAAA,iBACF,SACE,cAAA,iBACA,aAAA,iBAEF,SACE,YAAA,iBACA,eAAA,iBAXF,QAAE,QAAA,MAAA,gBACF,SAAE,YAAA,gBACF,SAAE,cAAA,gBACF,SAAE,eAAA,gBACF,SAAE,aAAA,gBACF,SACE,cAAA,gBACA,aAAA,gBAEF,SACE,YAAA,gBACA,eAAA,gBAXF,QAAE,QAAA,KAAA,eACF,SAAE,YAAA,eACF,SAAE,cAAA,eACF,SAAE,eAAA,eACF,SAAE,aAAA,eACF,SACE,cAAA,eACA,aAAA,eAEF,SACE,YAAA,eACA,eAAA,eAXF,QAAE,QAAA,OAAA,iBACF,SAAE,YAAA,iBACF,SAAE,cAAA,iBACF,SAAE,eAAA,iBACF,SAAE,aAAA,iBACF,SACE,cAAA,iBACA,aAAA,iBAEF,SACE,YAAA,iBACA,eAAA,iBAXF,QAAE,QAAA,KAAA,eACF,SAAE,YAAA,eACF,SAAE,cAAA,eACF,SAAE,eAAA,eACF,SAAE,aAAA,eACF,SACE,cAAA,eACA,aAAA,eAEF,SACE,YAAA,eACA,eAAA,eAMN,WAAE,OAAA,eACF,YAAE,WAAA,eACF,YAAE,aAAA,eACF,YAAE,cAAA,eACF,YAAE,YAAA,eACF,YACE,aAAA,eACA,YAAA,eAEF,YACE,WAAA,eACA,cAAA,gBpDiBF,yBoD7CI,QAAE,OAAA,EAAA,YACF,SAAE,WAAA,YACF,SAAE,aAAA,YACF,SAAE,cAAA,YACF,SAAE,YAAA,YACF,SACE,aAAA,YACA,YAAA,YAEF,SACE,WAAA,YACA,cAAA,YAXF,QAAE,OAAA,OAAA,iBACF,SAAE,WAAA,iBACF,SAAE,aAAA,iBACF,SAAE,cAAA,iBACF,SAAE,YAAA,iBACF,SACE,aAAA,iBACA,YAAA,iBAEF,SACE,WAAA,iBACA,cAAA,iBAXF,QAAE,OAAA,MAAA,gBACF,SAAE,WAAA,gBACF,SAAE,aAAA,gBACF,SAAE,cAAA,gBACF,SAAE,YAAA,gBACF,SACE,aAAA,gBACA,YAAA,gBAEF,SACE,WAAA,gBACA,cAAA,gBAXF,QAAE,OAAA,KAAA,eACF,SAAE,WAAA,eACF,SAAE,aAAA,eACF,SAAE,cAAA,eACF,SAAE,YAAA,eACF,SACE,aAAA,eACA,YAAA,eAEF,SACE,WAAA,eACA,cAAA,eAXF,QAAE,OAAA,OAAA,iBACF,SAAE,WAAA,iBACF,SAAE,aAAA,iBACF,SAAE,cAAA,iBACF,SAAE,YAAA,iBACF,SACE,aAAA,iBACA,YAAA,iBAEF,SACE,WAAA,iBACA,cAAA,iBAXF,QAAE,OAAA,KAAA,eACF,SAAE,WAAA,eACF,SAAE,aAAA,eACF,SAAE,cAAA,eACF,SAAE,YAAA,eACF,SACE,aAAA,eACA,YAAA,eAEF,SACE,WAAA,eACA,cAAA,eAXF,QAAE,QAAA,EAAA,YACF,SAAE,YAAA,YACF,SAAE,cAAA,YACF,SAAE,eAAA,YACF,SAAE,aAAA,YACF,SACE,cAAA,YACA,aAAA,YAEF,SACE,YAAA,YACA,eAAA,YAXF,QAAE,QAAA,OAAA,iBACF,SAAE,YAAA,iBACF,SAAE,cAAA,iBACF,SAAE,eAAA,iBACF,SAAE,aAAA,iBACF,SACE,cAAA,iBACA,aAAA,iBAEF,SACE,YAAA,iBACA,eAAA,iBAXF,QAAE,QAAA,MAAA,gBACF,SAAE,YAAA,gBACF,SAAE,cAAA,gBACF,SAAE,eAAA,gBACF,SAAE,aAAA,gBACF,SACE,cAAA,gBACA,aAAA,gBAEF,SACE,YAAA,gBACA,eAAA,gBAXF,QAAE,QAAA,KAAA,eACF,SAAE,YAAA,eACF,SAAE,cAAA,eACF,SAAE,eAAA,eACF,SAAE,aAAA,eACF,SACE,cAAA,eACA,aAAA,eAEF,SACE,YAAA,eACA,eAAA,eAXF,QAAE,QAAA,OAAA,iBACF,SAAE,YAAA,iBACF,SAAE,cAAA,iBACF,SAAE,eAAA,iBACF,SAAE,aAAA,iBACF,SACE,cAAA,iBACA,aAAA,iBAEF,SACE,YAAA,iBACA,eAAA,iBAXF,QAAE,QAAA,KAAA,eACF,SAAE,YAAA,eACF,SAAE,cAAA,eACF,SAAE,eAAA,eACF,SAAE,aAAA,eACF,SACE,cAAA,eACA,aAAA,eAEF,SACE,YAAA,eACA,eAAA,eAMN,WAAE,OAAA,eACF,YAAE,WAAA,eACF,YAAE,aAAA,eACF,YAAE,cAAA,eACF,YAAE,YAAA,eACF,YACE,aAAA,eACA,YAAA,eAEF,YACE,WAAA,eACA,cAAA,gBpDiBF,0BoD7CI,QAAE,OAAA,EAAA,YACF,SAAE,WAAA,YACF,SAAE,aAAA,YACF,SAAE,cAAA,YACF,SAAE,YAAA,YACF,SACE,aAAA,YACA,YAAA,YAEF,SACE,WAAA,YACA,cAAA,YAXF,QAAE,OAAA,OAAA,iBACF,SAAE,WAAA,iBACF,SAAE,aAAA,iBACF,SAAE,cAAA,iBACF,SAAE,YAAA,iBACF,SACE,aAAA,iBACA,YAAA,iBAEF,SACE,WAAA,iBACA,cAAA,iBAXF,QAAE,OAAA,MAAA,gBACF,SAAE,WAAA,gBACF,SAAE,aAAA,gBACF,SAAE,cAAA,gBACF,SAAE,YAAA,gBACF,SACE,aAAA,gBACA,YAAA,gBAEF,SACE,WAAA,gBACA,cAAA,gBAXF,QAAE,OAAA,KAAA,eACF,SAAE,WAAA,eACF,SAAE,aAAA,eACF,SAAE,cAAA,eACF,SAAE,YAAA,eACF,SACE,aAAA,eACA,YAAA,eAEF,SACE,WAAA,eACA,cAAA,eAXF,QAAE,OAAA,OAAA,iBACF,SAAE,WAAA,iBACF,SAAE,aAAA,iBACF,SAAE,cAAA,iBACF,SAAE,YAAA,iBACF,SACE,aAAA,iBACA,YAAA,iBAEF,SACE,WAAA,iBACA,cAAA,iBAXF,QAAE,OAAA,KAAA,eACF,SAAE,WAAA,eACF,SAAE,aAAA,eACF,SAAE,cAAA,eACF,SAAE,YAAA,eACF,SACE,aAAA,eACA,YAAA,eAEF,SACE,WAAA,eACA,cAAA,eAXF,QAAE,QAAA,EAAA,YACF,SAAE,YAAA,YACF,SAAE,cAAA,YACF,SAAE,eAAA,YACF,SAAE,aAAA,YACF,SACE,cAAA,YACA,aAAA,YAEF,SACE,YAAA,YACA,eAAA,YAXF,QAAE,QAAA,OAAA,iBACF,SAAE,YAAA,iBACF,SAAE,cAAA,iBACF,SAAE,eAAA,iBACF,SAAE,aAAA,iBACF,SACE,cAAA,iBACA,aAAA,iBAEF,SACE,YAAA,iBACA,eAAA,iBAXF,QAAE,QAAA,MAAA,gBACF,SAAE,YAAA,gBACF,SAAE,cAAA,gBACF,SAAE,eAAA,gBACF,SAAE,aAAA,gBACF,SACE,cAAA,gBACA,aAAA,gBAEF,SACE,YAAA,gBACA,eAAA,gBAXF,QAAE,QAAA,KAAA,eACF,SAAE,YAAA,eACF,SAAE,cAAA,eACF,SAAE,eAAA,eACF,SAAE,aAAA,eACF,SACE,cAAA,eACA,aAAA,eAEF,SACE,YAAA,eACA,eAAA,eAXF,QAAE,QAAA,OAAA,iBACF,SAAE,YAAA,iBACF,SAAE,cAAA,iBACF,SAAE,eAAA,iBACF,SAAE,aAAA,iBACF,SACE,cAAA,iBACA,aAAA,iBAEF,SACE,YAAA,iBACA,eAAA,iBAXF,QAAE,QAAA,KAAA,eACF,SAAE,YAAA,eACF,SAAE,cAAA,eACF,SAAE,eAAA,eACF,SAAE,aAAA,eACF,SACE,cAAA,eACA,aAAA,eAEF,SACE,YAAA,eACA,eAAA,eAMN,WAAE,OAAA,eACF,YAAE,WAAA,eACF,YAAE,aAAA,eACF,YAAE,cAAA,eACF,YAAE,YAAA,eACF,YACE,aAAA,eACA,YAAA,eAEF,YACE,WAAA,eACA,cAAA,gBCjCN,cAAiB,WAAA,kBACjB,aAAiB,YAAA,iBACjB,eCJE,SAAA,OACA,cAAA,SACA,YAAA,ODUE,WAAE,WAAA,eACF,YAAE,WAAA,gBACF,aAAE,WAAA,iBrDsCF,yBqDxCA,cAAE,WAAA,eACF,eAAE,WAAA,gBACF,gBAAE,WAAA,kBrDsCF,yBqDxCA,cAAE,WAAA,eACF,eAAE,WAAA,gBACF,gBAAE,WAAA,kBrDsCF,yBqDxCA,cAAE,WAAA,eACF,eAAE,WAAA,gBACF,gBAAE,WAAA,kBrDsCF,0BqDxCA,cAAE,WAAA,eACF,eAAE,WAAA,gBACF,gBAAE,WAAA,kBAMN,gBAAmB,eAAA,oBACnB,gBAAmB,eAAA,oBACnB,iBAAmB,eAAA,qBAInB,oBAAsB,YAAA,IACtB,kBAAsB,YAAA,IACtB,aAAsB,WAAA,OAItB,YACE,MAAA,eElCA,YACE,MAAA,kBjEgBA,mBAAA,mBiEZE,MAAA,kBALJ,cACE,MAAA,kBjEgBA,qBAAA,qBiEZE,MAAA,kBALJ,cACE,MAAA,kBjEgBA,qBAAA,qBiEZE,MAAA,kBALJ,WACE,MAAA,kBjEgBA,kBAAA,kBiEZE,MAAA,kBALJ,cACE,MAAA,kBjEgBA,qBAAA,qBiEZE,MAAA,kBALJ,aACE,MAAA,kBjEgBA,oBAAA,oBiEZE,MAAA,kBALJ,gBACE,MAAA,kBjEgBA,uBAAA,uBiEZE,MAAA,kBFkDN,WGxDE,KAAA,EAAA,EAAA,EACA,MAAA,YACA,YAAA,KACA,iBAAA,YACA,OAAA,ECFF,WCDE,WAAA,iBDQA,cAEI,QAAA,ezDwDF,yByDrDF,gBAEI,QAAA,gBzDsCF,yByD7CF,cAEI,QAAA,gBzDwDF,yByDrDF,gBAEI,QAAA,gBzDsCF,yByD7CF,cAEI,QAAA,gBzDwDF,yByDrDF,gBAEI,QAAA,gBzDsCF,yByD7CF,cAEI,QAAA,gBzDwDF,0ByDrDF,gBAEI,QAAA,gBzDsCF,0ByD7CF,cAEI,QAAA,gBAGJ,gBAEI,QAAA,eAUN,qBACE,QAAA,eAEA,aAHA,qBAIE,QAAA,iBAGJ,sBACE,QAAA,eAEA,aAHA,sBAIE,QAAA,kBAGJ,4BACE,QAAA,eAEA,aAHA,4BAIE,QAAA,wBAKF,aADA,cAEE,QAAA"}
\ No newline at end of file
--- /dev/null
+/*!
+ * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
+ * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+ */
+/* FONT PATH
+ * -------------------------- */
+@font-face {
+ font-family: 'FontAwesome';
+ src: url('../fonts/fontawesome-webfont.eot?v=4.7.0');
+ src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');
+ font-weight: normal;
+ font-style: normal;
+}
+.fa {
+ display: inline-block;
+ font: normal normal normal 14px/1 FontAwesome;
+ font-size: inherit;
+ text-rendering: auto;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+/* makes the font 33% larger relative to the icon container */
+.fa-lg {
+ font-size: 1.33333333em;
+ line-height: 0.75em;
+ vertical-align: -15%;
+}
+.fa-2x {
+ font-size: 2em;
+}
+.fa-3x {
+ font-size: 3em;
+}
+.fa-4x {
+ font-size: 4em;
+}
+.fa-5x {
+ font-size: 5em;
+}
+.fa-fw {
+ width: 1.28571429em;
+ text-align: center;
+}
+.fa-ul {
+ padding-left: 0;
+ margin-left: 2.14285714em;
+ list-style-type: none;
+}
+.fa-ul > li {
+ position: relative;
+}
+.fa-li {
+ position: absolute;
+ left: -2.14285714em;
+ width: 2.14285714em;
+ top: 0.14285714em;
+ text-align: center;
+}
+.fa-li.fa-lg {
+ left: -1.85714286em;
+}
+.fa-border {
+ padding: .2em .25em .15em;
+ border: solid 0.08em #eeeeee;
+ border-radius: .1em;
+}
+.fa-pull-left {
+ float: left;
+}
+.fa-pull-right {
+ float: right;
+}
+.fa.fa-pull-left {
+ margin-right: .3em;
+}
+.fa.fa-pull-right {
+ margin-left: .3em;
+}
+/* Deprecated as of 4.4.0 */
+.pull-right {
+ float: right;
+}
+.pull-left {
+ float: left;
+}
+.fa.pull-left {
+ margin-right: .3em;
+}
+.fa.pull-right {
+ margin-left: .3em;
+}
+.fa-spin {
+ -webkit-animation: fa-spin 2s infinite linear;
+ animation: fa-spin 2s infinite linear;
+}
+.fa-pulse {
+ -webkit-animation: fa-spin 1s infinite steps(8);
+ animation: fa-spin 1s infinite steps(8);
+}
+@-webkit-keyframes fa-spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes fa-spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+.fa-rotate-90 {
+ -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";
+ -webkit-transform: rotate(90deg);
+ -ms-transform: rotate(90deg);
+ transform: rotate(90deg);
+}
+.fa-rotate-180 {
+ -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";
+ -webkit-transform: rotate(180deg);
+ -ms-transform: rotate(180deg);
+ transform: rotate(180deg);
+}
+.fa-rotate-270 {
+ -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";
+ -webkit-transform: rotate(270deg);
+ -ms-transform: rotate(270deg);
+ transform: rotate(270deg);
+}
+.fa-flip-horizontal {
+ -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";
+ -webkit-transform: scale(-1, 1);
+ -ms-transform: scale(-1, 1);
+ transform: scale(-1, 1);
+}
+.fa-flip-vertical {
+ -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";
+ -webkit-transform: scale(1, -1);
+ -ms-transform: scale(1, -1);
+ transform: scale(1, -1);
+}
+:root .fa-rotate-90,
+:root .fa-rotate-180,
+:root .fa-rotate-270,
+:root .fa-flip-horizontal,
+:root .fa-flip-vertical {
+ filter: none;
+}
+.fa-stack {
+ position: relative;
+ display: inline-block;
+ width: 2em;
+ height: 2em;
+ line-height: 2em;
+ vertical-align: middle;
+}
+.fa-stack-1x,
+.fa-stack-2x {
+ position: absolute;
+ left: 0;
+ width: 100%;
+ text-align: center;
+}
+.fa-stack-1x {
+ line-height: inherit;
+}
+.fa-stack-2x {
+ font-size: 2em;
+}
+.fa-inverse {
+ color: #ffffff;
+}
+/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
+ readers do not read off random characters that represent icons */
+.fa-glass:before {
+ content: "\f000";
+}
+.fa-music:before {
+ content: "\f001";
+}
+.fa-search:before {
+ content: "\f002";
+}
+.fa-envelope-o:before {
+ content: "\f003";
+}
+.fa-heart:before {
+ content: "\f004";
+}
+.fa-star:before {
+ content: "\f005";
+}
+.fa-star-o:before {
+ content: "\f006";
+}
+.fa-user:before {
+ content: "\f007";
+}
+.fa-film:before {
+ content: "\f008";
+}
+.fa-th-large:before {
+ content: "\f009";
+}
+.fa-th:before {
+ content: "\f00a";
+}
+.fa-th-list:before {
+ content: "\f00b";
+}
+.fa-check:before {
+ content: "\f00c";
+}
+.fa-remove:before,
+.fa-close:before,
+.fa-times:before {
+ content: "\f00d";
+}
+.fa-search-plus:before {
+ content: "\f00e";
+}
+.fa-search-minus:before {
+ content: "\f010";
+}
+.fa-power-off:before {
+ content: "\f011";
+}
+.fa-signal:before {
+ content: "\f012";
+}
+.fa-gear:before,
+.fa-cog:before {
+ content: "\f013";
+}
+.fa-trash-o:before {
+ content: "\f014";
+}
+.fa-home:before {
+ content: "\f015";
+}
+.fa-file-o:before {
+ content: "\f016";
+}
+.fa-clock-o:before {
+ content: "\f017";
+}
+.fa-road:before {
+ content: "\f018";
+}
+.fa-download:before {
+ content: "\f019";
+}
+.fa-arrow-circle-o-down:before {
+ content: "\f01a";
+}
+.fa-arrow-circle-o-up:before {
+ content: "\f01b";
+}
+.fa-inbox:before {
+ content: "\f01c";
+}
+.fa-play-circle-o:before {
+ content: "\f01d";
+}
+.fa-rotate-right:before,
+.fa-repeat:before {
+ content: "\f01e";
+}
+.fa-refresh:before {
+ content: "\f021";
+}
+.fa-list-alt:before {
+ content: "\f022";
+}
+.fa-lock:before {
+ content: "\f023";
+}
+.fa-flag:before {
+ content: "\f024";
+}
+.fa-headphones:before {
+ content: "\f025";
+}
+.fa-volume-off:before {
+ content: "\f026";
+}
+.fa-volume-down:before {
+ content: "\f027";
+}
+.fa-volume-up:before {
+ content: "\f028";
+}
+.fa-qrcode:before {
+ content: "\f029";
+}
+.fa-barcode:before {
+ content: "\f02a";
+}
+.fa-tag:before {
+ content: "\f02b";
+}
+.fa-tags:before {
+ content: "\f02c";
+}
+.fa-book:before {
+ content: "\f02d";
+}
+.fa-bookmark:before {
+ content: "\f02e";
+}
+.fa-print:before {
+ content: "\f02f";
+}
+.fa-camera:before {
+ content: "\f030";
+}
+.fa-font:before {
+ content: "\f031";
+}
+.fa-bold:before {
+ content: "\f032";
+}
+.fa-italic:before {
+ content: "\f033";
+}
+.fa-text-height:before {
+ content: "\f034";
+}
+.fa-text-width:before {
+ content: "\f035";
+}
+.fa-align-left:before {
+ content: "\f036";
+}
+.fa-align-center:before {
+ content: "\f037";
+}
+.fa-align-right:before {
+ content: "\f038";
+}
+.fa-align-justify:before {
+ content: "\f039";
+}
+.fa-list:before {
+ content: "\f03a";
+}
+.fa-dedent:before,
+.fa-outdent:before {
+ content: "\f03b";
+}
+.fa-indent:before {
+ content: "\f03c";
+}
+.fa-video-camera:before {
+ content: "\f03d";
+}
+.fa-photo:before,
+.fa-image:before,
+.fa-picture-o:before {
+ content: "\f03e";
+}
+.fa-pencil:before {
+ content: "\f040";
+}
+.fa-map-marker:before {
+ content: "\f041";
+}
+.fa-adjust:before {
+ content: "\f042";
+}
+.fa-tint:before {
+ content: "\f043";
+}
+.fa-edit:before,
+.fa-pencil-square-o:before {
+ content: "\f044";
+}
+.fa-share-square-o:before {
+ content: "\f045";
+}
+.fa-check-square-o:before {
+ content: "\f046";
+}
+.fa-arrows:before {
+ content: "\f047";
+}
+.fa-step-backward:before {
+ content: "\f048";
+}
+.fa-fast-backward:before {
+ content: "\f049";
+}
+.fa-backward:before {
+ content: "\f04a";
+}
+.fa-play:before {
+ content: "\f04b";
+}
+.fa-pause:before {
+ content: "\f04c";
+}
+.fa-stop:before {
+ content: "\f04d";
+}
+.fa-forward:before {
+ content: "\f04e";
+}
+.fa-fast-forward:before {
+ content: "\f050";
+}
+.fa-step-forward:before {
+ content: "\f051";
+}
+.fa-eject:before {
+ content: "\f052";
+}
+.fa-chevron-left:before {
+ content: "\f053";
+}
+.fa-chevron-right:before {
+ content: "\f054";
+}
+.fa-plus-circle:before {
+ content: "\f055";
+}
+.fa-minus-circle:before {
+ content: "\f056";
+}
+.fa-times-circle:before {
+ content: "\f057";
+}
+.fa-check-circle:before {
+ content: "\f058";
+}
+.fa-question-circle:before {
+ content: "\f059";
+}
+.fa-info-circle:before {
+ content: "\f05a";
+}
+.fa-crosshairs:before {
+ content: "\f05b";
+}
+.fa-times-circle-o:before {
+ content: "\f05c";
+}
+.fa-check-circle-o:before {
+ content: "\f05d";
+}
+.fa-ban:before {
+ content: "\f05e";
+}
+.fa-arrow-left:before {
+ content: "\f060";
+}
+.fa-arrow-right:before {
+ content: "\f061";
+}
+.fa-arrow-up:before {
+ content: "\f062";
+}
+.fa-arrow-down:before {
+ content: "\f063";
+}
+.fa-mail-forward:before,
+.fa-share:before {
+ content: "\f064";
+}
+.fa-expand:before {
+ content: "\f065";
+}
+.fa-compress:before {
+ content: "\f066";
+}
+.fa-plus:before {
+ content: "\f067";
+}
+.fa-minus:before {
+ content: "\f068";
+}
+.fa-asterisk:before {
+ content: "\f069";
+}
+.fa-exclamation-circle:before {
+ content: "\f06a";
+}
+.fa-gift:before {
+ content: "\f06b";
+}
+.fa-leaf:before {
+ content: "\f06c";
+}
+.fa-fire:before {
+ content: "\f06d";
+}
+.fa-eye:before {
+ content: "\f06e";
+}
+.fa-eye-slash:before {
+ content: "\f070";
+}
+.fa-warning:before,
+.fa-exclamation-triangle:before {
+ content: "\f071";
+}
+.fa-plane:before {
+ content: "\f072";
+}
+.fa-calendar:before {
+ content: "\f073";
+}
+.fa-random:before {
+ content: "\f074";
+}
+.fa-comment:before {
+ content: "\f075";
+}
+.fa-magnet:before {
+ content: "\f076";
+}
+.fa-chevron-up:before {
+ content: "\f077";
+}
+.fa-chevron-down:before {
+ content: "\f078";
+}
+.fa-retweet:before {
+ content: "\f079";
+}
+.fa-shopping-cart:before {
+ content: "\f07a";
+}
+.fa-folder:before {
+ content: "\f07b";
+}
+.fa-folder-open:before {
+ content: "\f07c";
+}
+.fa-arrows-v:before {
+ content: "\f07d";
+}
+.fa-arrows-h:before {
+ content: "\f07e";
+}
+.fa-bar-chart-o:before,
+.fa-bar-chart:before {
+ content: "\f080";
+}
+.fa-twitter-square:before {
+ content: "\f081";
+}
+.fa-facebook-square:before {
+ content: "\f082";
+}
+.fa-camera-retro:before {
+ content: "\f083";
+}
+.fa-key:before {
+ content: "\f084";
+}
+.fa-gears:before,
+.fa-cogs:before {
+ content: "\f085";
+}
+.fa-comments:before {
+ content: "\f086";
+}
+.fa-thumbs-o-up:before {
+ content: "\f087";
+}
+.fa-thumbs-o-down:before {
+ content: "\f088";
+}
+.fa-star-half:before {
+ content: "\f089";
+}
+.fa-heart-o:before {
+ content: "\f08a";
+}
+.fa-sign-out:before {
+ content: "\f08b";
+}
+.fa-linkedin-square:before {
+ content: "\f08c";
+}
+.fa-thumb-tack:before {
+ content: "\f08d";
+}
+.fa-external-link:before {
+ content: "\f08e";
+}
+.fa-sign-in:before {
+ content: "\f090";
+}
+.fa-trophy:before {
+ content: "\f091";
+}
+.fa-github-square:before {
+ content: "\f092";
+}
+.fa-upload:before {
+ content: "\f093";
+}
+.fa-lemon-o:before {
+ content: "\f094";
+}
+.fa-phone:before {
+ content: "\f095";
+}
+.fa-square-o:before {
+ content: "\f096";
+}
+.fa-bookmark-o:before {
+ content: "\f097";
+}
+.fa-phone-square:before {
+ content: "\f098";
+}
+.fa-twitter:before {
+ content: "\f099";
+}
+.fa-facebook-f:before,
+.fa-facebook:before {
+ content: "\f09a";
+}
+.fa-github:before {
+ content: "\f09b";
+}
+.fa-unlock:before {
+ content: "\f09c";
+}
+.fa-credit-card:before {
+ content: "\f09d";
+}
+.fa-feed:before,
+.fa-rss:before {
+ content: "\f09e";
+}
+.fa-hdd-o:before {
+ content: "\f0a0";
+}
+.fa-bullhorn:before {
+ content: "\f0a1";
+}
+.fa-bell:before {
+ content: "\f0f3";
+}
+.fa-certificate:before {
+ content: "\f0a3";
+}
+.fa-hand-o-right:before {
+ content: "\f0a4";
+}
+.fa-hand-o-left:before {
+ content: "\f0a5";
+}
+.fa-hand-o-up:before {
+ content: "\f0a6";
+}
+.fa-hand-o-down:before {
+ content: "\f0a7";
+}
+.fa-arrow-circle-left:before {
+ content: "\f0a8";
+}
+.fa-arrow-circle-right:before {
+ content: "\f0a9";
+}
+.fa-arrow-circle-up:before {
+ content: "\f0aa";
+}
+.fa-arrow-circle-down:before {
+ content: "\f0ab";
+}
+.fa-globe:before {
+ content: "\f0ac";
+}
+.fa-wrench:before {
+ content: "\f0ad";
+}
+.fa-tasks:before {
+ content: "\f0ae";
+}
+.fa-filter:before {
+ content: "\f0b0";
+}
+.fa-briefcase:before {
+ content: "\f0b1";
+}
+.fa-arrows-alt:before {
+ content: "\f0b2";
+}
+.fa-group:before,
+.fa-users:before {
+ content: "\f0c0";
+}
+.fa-chain:before,
+.fa-link:before {
+ content: "\f0c1";
+}
+.fa-cloud:before {
+ content: "\f0c2";
+}
+.fa-flask:before {
+ content: "\f0c3";
+}
+.fa-cut:before,
+.fa-scissors:before {
+ content: "\f0c4";
+}
+.fa-copy:before,
+.fa-files-o:before {
+ content: "\f0c5";
+}
+.fa-paperclip:before {
+ content: "\f0c6";
+}
+.fa-save:before,
+.fa-floppy-o:before {
+ content: "\f0c7";
+}
+.fa-square:before {
+ content: "\f0c8";
+}
+.fa-navicon:before,
+.fa-reorder:before,
+.fa-bars:before {
+ content: "\f0c9";
+}
+.fa-list-ul:before {
+ content: "\f0ca";
+}
+.fa-list-ol:before {
+ content: "\f0cb";
+}
+.fa-strikethrough:before {
+ content: "\f0cc";
+}
+.fa-underline:before {
+ content: "\f0cd";
+}
+.fa-table:before {
+ content: "\f0ce";
+}
+.fa-magic:before {
+ content: "\f0d0";
+}
+.fa-truck:before {
+ content: "\f0d1";
+}
+.fa-pinterest:before {
+ content: "\f0d2";
+}
+.fa-pinterest-square:before {
+ content: "\f0d3";
+}
+.fa-google-plus-square:before {
+ content: "\f0d4";
+}
+.fa-google-plus:before {
+ content: "\f0d5";
+}
+.fa-money:before {
+ content: "\f0d6";
+}
+.fa-caret-down:before {
+ content: "\f0d7";
+}
+.fa-caret-up:before {
+ content: "\f0d8";
+}
+.fa-caret-left:before {
+ content: "\f0d9";
+}
+.fa-caret-right:before {
+ content: "\f0da";
+}
+.fa-columns:before {
+ content: "\f0db";
+}
+.fa-unsorted:before,
+.fa-sort:before {
+ content: "\f0dc";
+}
+.fa-sort-down:before,
+.fa-sort-desc:before {
+ content: "\f0dd";
+}
+.fa-sort-up:before,
+.fa-sort-asc:before {
+ content: "\f0de";
+}
+.fa-envelope:before {
+ content: "\f0e0";
+}
+.fa-linkedin:before {
+ content: "\f0e1";
+}
+.fa-rotate-left:before,
+.fa-undo:before {
+ content: "\f0e2";
+}
+.fa-legal:before,
+.fa-gavel:before {
+ content: "\f0e3";
+}
+.fa-dashboard:before,
+.fa-tachometer:before {
+ content: "\f0e4";
+}
+.fa-comment-o:before {
+ content: "\f0e5";
+}
+.fa-comments-o:before {
+ content: "\f0e6";
+}
+.fa-flash:before,
+.fa-bolt:before {
+ content: "\f0e7";
+}
+.fa-sitemap:before {
+ content: "\f0e8";
+}
+.fa-umbrella:before {
+ content: "\f0e9";
+}
+.fa-paste:before,
+.fa-clipboard:before {
+ content: "\f0ea";
+}
+.fa-lightbulb-o:before {
+ content: "\f0eb";
+}
+.fa-exchange:before {
+ content: "\f0ec";
+}
+.fa-cloud-download:before {
+ content: "\f0ed";
+}
+.fa-cloud-upload:before {
+ content: "\f0ee";
+}
+.fa-user-md:before {
+ content: "\f0f0";
+}
+.fa-stethoscope:before {
+ content: "\f0f1";
+}
+.fa-suitcase:before {
+ content: "\f0f2";
+}
+.fa-bell-o:before {
+ content: "\f0a2";
+}
+.fa-coffee:before {
+ content: "\f0f4";
+}
+.fa-cutlery:before {
+ content: "\f0f5";
+}
+.fa-file-text-o:before {
+ content: "\f0f6";
+}
+.fa-building-o:before {
+ content: "\f0f7";
+}
+.fa-hospital-o:before {
+ content: "\f0f8";
+}
+.fa-ambulance:before {
+ content: "\f0f9";
+}
+.fa-medkit:before {
+ content: "\f0fa";
+}
+.fa-fighter-jet:before {
+ content: "\f0fb";
+}
+.fa-beer:before {
+ content: "\f0fc";
+}
+.fa-h-square:before {
+ content: "\f0fd";
+}
+.fa-plus-square:before {
+ content: "\f0fe";
+}
+.fa-angle-double-left:before {
+ content: "\f100";
+}
+.fa-angle-double-right:before {
+ content: "\f101";
+}
+.fa-angle-double-up:before {
+ content: "\f102";
+}
+.fa-angle-double-down:before {
+ content: "\f103";
+}
+.fa-angle-left:before {
+ content: "\f104";
+}
+.fa-angle-right:before {
+ content: "\f105";
+}
+.fa-angle-up:before {
+ content: "\f106";
+}
+.fa-angle-down:before {
+ content: "\f107";
+}
+.fa-desktop:before {
+ content: "\f108";
+}
+.fa-laptop:before {
+ content: "\f109";
+}
+.fa-tablet:before {
+ content: "\f10a";
+}
+.fa-mobile-phone:before,
+.fa-mobile:before {
+ content: "\f10b";
+}
+.fa-circle-o:before {
+ content: "\f10c";
+}
+.fa-quote-left:before {
+ content: "\f10d";
+}
+.fa-quote-right:before {
+ content: "\f10e";
+}
+.fa-spinner:before {
+ content: "\f110";
+}
+.fa-circle:before {
+ content: "\f111";
+}
+.fa-mail-reply:before,
+.fa-reply:before {
+ content: "\f112";
+}
+.fa-github-alt:before {
+ content: "\f113";
+}
+.fa-folder-o:before {
+ content: "\f114";
+}
+.fa-folder-open-o:before {
+ content: "\f115";
+}
+.fa-smile-o:before {
+ content: "\f118";
+}
+.fa-frown-o:before {
+ content: "\f119";
+}
+.fa-meh-o:before {
+ content: "\f11a";
+}
+.fa-gamepad:before {
+ content: "\f11b";
+}
+.fa-keyboard-o:before {
+ content: "\f11c";
+}
+.fa-flag-o:before {
+ content: "\f11d";
+}
+.fa-flag-checkered:before {
+ content: "\f11e";
+}
+.fa-terminal:before {
+ content: "\f120";
+}
+.fa-code:before {
+ content: "\f121";
+}
+.fa-mail-reply-all:before,
+.fa-reply-all:before {
+ content: "\f122";
+}
+.fa-star-half-empty:before,
+.fa-star-half-full:before,
+.fa-star-half-o:before {
+ content: "\f123";
+}
+.fa-location-arrow:before {
+ content: "\f124";
+}
+.fa-crop:before {
+ content: "\f125";
+}
+.fa-code-fork:before {
+ content: "\f126";
+}
+.fa-unlink:before,
+.fa-chain-broken:before {
+ content: "\f127";
+}
+.fa-question:before {
+ content: "\f128";
+}
+.fa-info:before {
+ content: "\f129";
+}
+.fa-exclamation:before {
+ content: "\f12a";
+}
+.fa-superscript:before {
+ content: "\f12b";
+}
+.fa-subscript:before {
+ content: "\f12c";
+}
+.fa-eraser:before {
+ content: "\f12d";
+}
+.fa-puzzle-piece:before {
+ content: "\f12e";
+}
+.fa-microphone:before {
+ content: "\f130";
+}
+.fa-microphone-slash:before {
+ content: "\f131";
+}
+.fa-shield:before {
+ content: "\f132";
+}
+.fa-calendar-o:before {
+ content: "\f133";
+}
+.fa-fire-extinguisher:before {
+ content: "\f134";
+}
+.fa-rocket:before {
+ content: "\f135";
+}
+.fa-maxcdn:before {
+ content: "\f136";
+}
+.fa-chevron-circle-left:before {
+ content: "\f137";
+}
+.fa-chevron-circle-right:before {
+ content: "\f138";
+}
+.fa-chevron-circle-up:before {
+ content: "\f139";
+}
+.fa-chevron-circle-down:before {
+ content: "\f13a";
+}
+.fa-html5:before {
+ content: "\f13b";
+}
+.fa-css3:before {
+ content: "\f13c";
+}
+.fa-anchor:before {
+ content: "\f13d";
+}
+.fa-unlock-alt:before {
+ content: "\f13e";
+}
+.fa-bullseye:before {
+ content: "\f140";
+}
+.fa-ellipsis-h:before {
+ content: "\f141";
+}
+.fa-ellipsis-v:before {
+ content: "\f142";
+}
+.fa-rss-square:before {
+ content: "\f143";
+}
+.fa-play-circle:before {
+ content: "\f144";
+}
+.fa-ticket:before {
+ content: "\f145";
+}
+.fa-minus-square:before {
+ content: "\f146";
+}
+.fa-minus-square-o:before {
+ content: "\f147";
+}
+.fa-level-up:before {
+ content: "\f148";
+}
+.fa-level-down:before {
+ content: "\f149";
+}
+.fa-check-square:before {
+ content: "\f14a";
+}
+.fa-pencil-square:before {
+ content: "\f14b";
+}
+.fa-external-link-square:before {
+ content: "\f14c";
+}
+.fa-share-square:before {
+ content: "\f14d";
+}
+.fa-compass:before {
+ content: "\f14e";
+}
+.fa-toggle-down:before,
+.fa-caret-square-o-down:before {
+ content: "\f150";
+}
+.fa-toggle-up:before,
+.fa-caret-square-o-up:before {
+ content: "\f151";
+}
+.fa-toggle-right:before,
+.fa-caret-square-o-right:before {
+ content: "\f152";
+}
+.fa-euro:before,
+.fa-eur:before {
+ content: "\f153";
+}
+.fa-gbp:before {
+ content: "\f154";
+}
+.fa-dollar:before,
+.fa-usd:before {
+ content: "\f155";
+}
+.fa-rupee:before,
+.fa-inr:before {
+ content: "\f156";
+}
+.fa-cny:before,
+.fa-rmb:before,
+.fa-yen:before,
+.fa-jpy:before {
+ content: "\f157";
+}
+.fa-ruble:before,
+.fa-rouble:before,
+.fa-rub:before {
+ content: "\f158";
+}
+.fa-won:before,
+.fa-krw:before {
+ content: "\f159";
+}
+.fa-bitcoin:before,
+.fa-btc:before {
+ content: "\f15a";
+}
+.fa-file:before {
+ content: "\f15b";
+}
+.fa-file-text:before {
+ content: "\f15c";
+}
+.fa-sort-alpha-asc:before {
+ content: "\f15d";
+}
+.fa-sort-alpha-desc:before {
+ content: "\f15e";
+}
+.fa-sort-amount-asc:before {
+ content: "\f160";
+}
+.fa-sort-amount-desc:before {
+ content: "\f161";
+}
+.fa-sort-numeric-asc:before {
+ content: "\f162";
+}
+.fa-sort-numeric-desc:before {
+ content: "\f163";
+}
+.fa-thumbs-up:before {
+ content: "\f164";
+}
+.fa-thumbs-down:before {
+ content: "\f165";
+}
+.fa-youtube-square:before {
+ content: "\f166";
+}
+.fa-youtube:before {
+ content: "\f167";
+}
+.fa-xing:before {
+ content: "\f168";
+}
+.fa-xing-square:before {
+ content: "\f169";
+}
+.fa-youtube-play:before {
+ content: "\f16a";
+}
+.fa-dropbox:before {
+ content: "\f16b";
+}
+.fa-stack-overflow:before {
+ content: "\f16c";
+}
+.fa-instagram:before {
+ content: "\f16d";
+}
+.fa-flickr:before {
+ content: "\f16e";
+}
+.fa-adn:before {
+ content: "\f170";
+}
+.fa-bitbucket:before {
+ content: "\f171";
+}
+.fa-bitbucket-square:before {
+ content: "\f172";
+}
+.fa-tumblr:before {
+ content: "\f173";
+}
+.fa-tumblr-square:before {
+ content: "\f174";
+}
+.fa-long-arrow-down:before {
+ content: "\f175";
+}
+.fa-long-arrow-up:before {
+ content: "\f176";
+}
+.fa-long-arrow-left:before {
+ content: "\f177";
+}
+.fa-long-arrow-right:before {
+ content: "\f178";
+}
+.fa-apple:before {
+ content: "\f179";
+}
+.fa-windows:before {
+ content: "\f17a";
+}
+.fa-android:before {
+ content: "\f17b";
+}
+.fa-linux:before {
+ content: "\f17c";
+}
+.fa-dribbble:before {
+ content: "\f17d";
+}
+.fa-skype:before {
+ content: "\f17e";
+}
+.fa-foursquare:before {
+ content: "\f180";
+}
+.fa-trello:before {
+ content: "\f181";
+}
+.fa-female:before {
+ content: "\f182";
+}
+.fa-male:before {
+ content: "\f183";
+}
+.fa-gittip:before,
+.fa-gratipay:before {
+ content: "\f184";
+}
+.fa-sun-o:before {
+ content: "\f185";
+}
+.fa-moon-o:before {
+ content: "\f186";
+}
+.fa-archive:before {
+ content: "\f187";
+}
+.fa-bug:before {
+ content: "\f188";
+}
+.fa-vk:before {
+ content: "\f189";
+}
+.fa-weibo:before {
+ content: "\f18a";
+}
+.fa-renren:before {
+ content: "\f18b";
+}
+.fa-pagelines:before {
+ content: "\f18c";
+}
+.fa-stack-exchange:before {
+ content: "\f18d";
+}
+.fa-arrow-circle-o-right:before {
+ content: "\f18e";
+}
+.fa-arrow-circle-o-left:before {
+ content: "\f190";
+}
+.fa-toggle-left:before,
+.fa-caret-square-o-left:before {
+ content: "\f191";
+}
+.fa-dot-circle-o:before {
+ content: "\f192";
+}
+.fa-wheelchair:before {
+ content: "\f193";
+}
+.fa-vimeo-square:before {
+ content: "\f194";
+}
+.fa-turkish-lira:before,
+.fa-try:before {
+ content: "\f195";
+}
+.fa-plus-square-o:before {
+ content: "\f196";
+}
+.fa-space-shuttle:before {
+ content: "\f197";
+}
+.fa-slack:before {
+ content: "\f198";
+}
+.fa-envelope-square:before {
+ content: "\f199";
+}
+.fa-wordpress:before {
+ content: "\f19a";
+}
+.fa-openid:before {
+ content: "\f19b";
+}
+.fa-institution:before,
+.fa-bank:before,
+.fa-university:before {
+ content: "\f19c";
+}
+.fa-mortar-board:before,
+.fa-graduation-cap:before {
+ content: "\f19d";
+}
+.fa-yahoo:before {
+ content: "\f19e";
+}
+.fa-google:before {
+ content: "\f1a0";
+}
+.fa-reddit:before {
+ content: "\f1a1";
+}
+.fa-reddit-square:before {
+ content: "\f1a2";
+}
+.fa-stumbleupon-circle:before {
+ content: "\f1a3";
+}
+.fa-stumbleupon:before {
+ content: "\f1a4";
+}
+.fa-delicious:before {
+ content: "\f1a5";
+}
+.fa-digg:before {
+ content: "\f1a6";
+}
+.fa-pied-piper-pp:before {
+ content: "\f1a7";
+}
+.fa-pied-piper-alt:before {
+ content: "\f1a8";
+}
+.fa-drupal:before {
+ content: "\f1a9";
+}
+.fa-joomla:before {
+ content: "\f1aa";
+}
+.fa-language:before {
+ content: "\f1ab";
+}
+.fa-fax:before {
+ content: "\f1ac";
+}
+.fa-building:before {
+ content: "\f1ad";
+}
+.fa-child:before {
+ content: "\f1ae";
+}
+.fa-paw:before {
+ content: "\f1b0";
+}
+.fa-spoon:before {
+ content: "\f1b1";
+}
+.fa-cube:before {
+ content: "\f1b2";
+}
+.fa-cubes:before {
+ content: "\f1b3";
+}
+.fa-behance:before {
+ content: "\f1b4";
+}
+.fa-behance-square:before {
+ content: "\f1b5";
+}
+.fa-steam:before {
+ content: "\f1b6";
+}
+.fa-steam-square:before {
+ content: "\f1b7";
+}
+.fa-recycle:before {
+ content: "\f1b8";
+}
+.fa-automobile:before,
+.fa-car:before {
+ content: "\f1b9";
+}
+.fa-cab:before,
+.fa-taxi:before {
+ content: "\f1ba";
+}
+.fa-tree:before {
+ content: "\f1bb";
+}
+.fa-spotify:before {
+ content: "\f1bc";
+}
+.fa-deviantart:before {
+ content: "\f1bd";
+}
+.fa-soundcloud:before {
+ content: "\f1be";
+}
+.fa-database:before {
+ content: "\f1c0";
+}
+.fa-file-pdf-o:before {
+ content: "\f1c1";
+}
+.fa-file-word-o:before {
+ content: "\f1c2";
+}
+.fa-file-excel-o:before {
+ content: "\f1c3";
+}
+.fa-file-powerpoint-o:before {
+ content: "\f1c4";
+}
+.fa-file-photo-o:before,
+.fa-file-picture-o:before,
+.fa-file-image-o:before {
+ content: "\f1c5";
+}
+.fa-file-zip-o:before,
+.fa-file-archive-o:before {
+ content: "\f1c6";
+}
+.fa-file-sound-o:before,
+.fa-file-audio-o:before {
+ content: "\f1c7";
+}
+.fa-file-movie-o:before,
+.fa-file-video-o:before {
+ content: "\f1c8";
+}
+.fa-file-code-o:before {
+ content: "\f1c9";
+}
+.fa-vine:before {
+ content: "\f1ca";
+}
+.fa-codepen:before {
+ content: "\f1cb";
+}
+.fa-jsfiddle:before {
+ content: "\f1cc";
+}
+.fa-life-bouy:before,
+.fa-life-buoy:before,
+.fa-life-saver:before,
+.fa-support:before,
+.fa-life-ring:before {
+ content: "\f1cd";
+}
+.fa-circle-o-notch:before {
+ content: "\f1ce";
+}
+.fa-ra:before,
+.fa-resistance:before,
+.fa-rebel:before {
+ content: "\f1d0";
+}
+.fa-ge:before,
+.fa-empire:before {
+ content: "\f1d1";
+}
+.fa-git-square:before {
+ content: "\f1d2";
+}
+.fa-git:before {
+ content: "\f1d3";
+}
+.fa-y-combinator-square:before,
+.fa-yc-square:before,
+.fa-hacker-news:before {
+ content: "\f1d4";
+}
+.fa-tencent-weibo:before {
+ content: "\f1d5";
+}
+.fa-qq:before {
+ content: "\f1d6";
+}
+.fa-wechat:before,
+.fa-weixin:before {
+ content: "\f1d7";
+}
+.fa-send:before,
+.fa-paper-plane:before {
+ content: "\f1d8";
+}
+.fa-send-o:before,
+.fa-paper-plane-o:before {
+ content: "\f1d9";
+}
+.fa-history:before {
+ content: "\f1da";
+}
+.fa-circle-thin:before {
+ content: "\f1db";
+}
+.fa-header:before {
+ content: "\f1dc";
+}
+.fa-paragraph:before {
+ content: "\f1dd";
+}
+.fa-sliders:before {
+ content: "\f1de";
+}
+.fa-share-alt:before {
+ content: "\f1e0";
+}
+.fa-share-alt-square:before {
+ content: "\f1e1";
+}
+.fa-bomb:before {
+ content: "\f1e2";
+}
+.fa-soccer-ball-o:before,
+.fa-futbol-o:before {
+ content: "\f1e3";
+}
+.fa-tty:before {
+ content: "\f1e4";
+}
+.fa-binoculars:before {
+ content: "\f1e5";
+}
+.fa-plug:before {
+ content: "\f1e6";
+}
+.fa-slideshare:before {
+ content: "\f1e7";
+}
+.fa-twitch:before {
+ content: "\f1e8";
+}
+.fa-yelp:before {
+ content: "\f1e9";
+}
+.fa-newspaper-o:before {
+ content: "\f1ea";
+}
+.fa-wifi:before {
+ content: "\f1eb";
+}
+.fa-calculator:before {
+ content: "\f1ec";
+}
+.fa-paypal:before {
+ content: "\f1ed";
+}
+.fa-google-wallet:before {
+ content: "\f1ee";
+}
+.fa-cc-visa:before {
+ content: "\f1f0";
+}
+.fa-cc-mastercard:before {
+ content: "\f1f1";
+}
+.fa-cc-discover:before {
+ content: "\f1f2";
+}
+.fa-cc-amex:before {
+ content: "\f1f3";
+}
+.fa-cc-paypal:before {
+ content: "\f1f4";
+}
+.fa-cc-stripe:before {
+ content: "\f1f5";
+}
+.fa-bell-slash:before {
+ content: "\f1f6";
+}
+.fa-bell-slash-o:before {
+ content: "\f1f7";
+}
+.fa-trash:before {
+ content: "\f1f8";
+}
+.fa-copyright:before {
+ content: "\f1f9";
+}
+.fa-at:before {
+ content: "\f1fa";
+}
+.fa-eyedropper:before {
+ content: "\f1fb";
+}
+.fa-paint-brush:before {
+ content: "\f1fc";
+}
+.fa-birthday-cake:before {
+ content: "\f1fd";
+}
+.fa-area-chart:before {
+ content: "\f1fe";
+}
+.fa-pie-chart:before {
+ content: "\f200";
+}
+.fa-line-chart:before {
+ content: "\f201";
+}
+.fa-lastfm:before {
+ content: "\f202";
+}
+.fa-lastfm-square:before {
+ content: "\f203";
+}
+.fa-toggle-off:before {
+ content: "\f204";
+}
+.fa-toggle-on:before {
+ content: "\f205";
+}
+.fa-bicycle:before {
+ content: "\f206";
+}
+.fa-bus:before {
+ content: "\f207";
+}
+.fa-ioxhost:before {
+ content: "\f208";
+}
+.fa-angellist:before {
+ content: "\f209";
+}
+.fa-cc:before {
+ content: "\f20a";
+}
+.fa-shekel:before,
+.fa-sheqel:before,
+.fa-ils:before {
+ content: "\f20b";
+}
+.fa-meanpath:before {
+ content: "\f20c";
+}
+.fa-buysellads:before {
+ content: "\f20d";
+}
+.fa-connectdevelop:before {
+ content: "\f20e";
+}
+.fa-dashcube:before {
+ content: "\f210";
+}
+.fa-forumbee:before {
+ content: "\f211";
+}
+.fa-leanpub:before {
+ content: "\f212";
+}
+.fa-sellsy:before {
+ content: "\f213";
+}
+.fa-shirtsinbulk:before {
+ content: "\f214";
+}
+.fa-simplybuilt:before {
+ content: "\f215";
+}
+.fa-skyatlas:before {
+ content: "\f216";
+}
+.fa-cart-plus:before {
+ content: "\f217";
+}
+.fa-cart-arrow-down:before {
+ content: "\f218";
+}
+.fa-diamond:before {
+ content: "\f219";
+}
+.fa-ship:before {
+ content: "\f21a";
+}
+.fa-user-secret:before {
+ content: "\f21b";
+}
+.fa-motorcycle:before {
+ content: "\f21c";
+}
+.fa-street-view:before {
+ content: "\f21d";
+}
+.fa-heartbeat:before {
+ content: "\f21e";
+}
+.fa-venus:before {
+ content: "\f221";
+}
+.fa-mars:before {
+ content: "\f222";
+}
+.fa-mercury:before {
+ content: "\f223";
+}
+.fa-intersex:before,
+.fa-transgender:before {
+ content: "\f224";
+}
+.fa-transgender-alt:before {
+ content: "\f225";
+}
+.fa-venus-double:before {
+ content: "\f226";
+}
+.fa-mars-double:before {
+ content: "\f227";
+}
+.fa-venus-mars:before {
+ content: "\f228";
+}
+.fa-mars-stroke:before {
+ content: "\f229";
+}
+.fa-mars-stroke-v:before {
+ content: "\f22a";
+}
+.fa-mars-stroke-h:before {
+ content: "\f22b";
+}
+.fa-neuter:before {
+ content: "\f22c";
+}
+.fa-genderless:before {
+ content: "\f22d";
+}
+.fa-facebook-official:before {
+ content: "\f230";
+}
+.fa-pinterest-p:before {
+ content: "\f231";
+}
+.fa-whatsapp:before {
+ content: "\f232";
+}
+.fa-server:before {
+ content: "\f233";
+}
+.fa-user-plus:before {
+ content: "\f234";
+}
+.fa-user-times:before {
+ content: "\f235";
+}
+.fa-hotel:before,
+.fa-bed:before {
+ content: "\f236";
+}
+.fa-viacoin:before {
+ content: "\f237";
+}
+.fa-train:before {
+ content: "\f238";
+}
+.fa-subway:before {
+ content: "\f239";
+}
+.fa-medium:before {
+ content: "\f23a";
+}
+.fa-yc:before,
+.fa-y-combinator:before {
+ content: "\f23b";
+}
+.fa-optin-monster:before {
+ content: "\f23c";
+}
+.fa-opencart:before {
+ content: "\f23d";
+}
+.fa-expeditedssl:before {
+ content: "\f23e";
+}
+.fa-battery-4:before,
+.fa-battery:before,
+.fa-battery-full:before {
+ content: "\f240";
+}
+.fa-battery-3:before,
+.fa-battery-three-quarters:before {
+ content: "\f241";
+}
+.fa-battery-2:before,
+.fa-battery-half:before {
+ content: "\f242";
+}
+.fa-battery-1:before,
+.fa-battery-quarter:before {
+ content: "\f243";
+}
+.fa-battery-0:before,
+.fa-battery-empty:before {
+ content: "\f244";
+}
+.fa-mouse-pointer:before {
+ content: "\f245";
+}
+.fa-i-cursor:before {
+ content: "\f246";
+}
+.fa-object-group:before {
+ content: "\f247";
+}
+.fa-object-ungroup:before {
+ content: "\f248";
+}
+.fa-sticky-note:before {
+ content: "\f249";
+}
+.fa-sticky-note-o:before {
+ content: "\f24a";
+}
+.fa-cc-jcb:before {
+ content: "\f24b";
+}
+.fa-cc-diners-club:before {
+ content: "\f24c";
+}
+.fa-clone:before {
+ content: "\f24d";
+}
+.fa-balance-scale:before {
+ content: "\f24e";
+}
+.fa-hourglass-o:before {
+ content: "\f250";
+}
+.fa-hourglass-1:before,
+.fa-hourglass-start:before {
+ content: "\f251";
+}
+.fa-hourglass-2:before,
+.fa-hourglass-half:before {
+ content: "\f252";
+}
+.fa-hourglass-3:before,
+.fa-hourglass-end:before {
+ content: "\f253";
+}
+.fa-hourglass:before {
+ content: "\f254";
+}
+.fa-hand-grab-o:before,
+.fa-hand-rock-o:before {
+ content: "\f255";
+}
+.fa-hand-stop-o:before,
+.fa-hand-paper-o:before {
+ content: "\f256";
+}
+.fa-hand-scissors-o:before {
+ content: "\f257";
+}
+.fa-hand-lizard-o:before {
+ content: "\f258";
+}
+.fa-hand-spock-o:before {
+ content: "\f259";
+}
+.fa-hand-pointer-o:before {
+ content: "\f25a";
+}
+.fa-hand-peace-o:before {
+ content: "\f25b";
+}
+.fa-trademark:before {
+ content: "\f25c";
+}
+.fa-registered:before {
+ content: "\f25d";
+}
+.fa-creative-commons:before {
+ content: "\f25e";
+}
+.fa-gg:before {
+ content: "\f260";
+}
+.fa-gg-circle:before {
+ content: "\f261";
+}
+.fa-tripadvisor:before {
+ content: "\f262";
+}
+.fa-odnoklassniki:before {
+ content: "\f263";
+}
+.fa-odnoklassniki-square:before {
+ content: "\f264";
+}
+.fa-get-pocket:before {
+ content: "\f265";
+}
+.fa-wikipedia-w:before {
+ content: "\f266";
+}
+.fa-safari:before {
+ content: "\f267";
+}
+.fa-chrome:before {
+ content: "\f268";
+}
+.fa-firefox:before {
+ content: "\f269";
+}
+.fa-opera:before {
+ content: "\f26a";
+}
+.fa-internet-explorer:before {
+ content: "\f26b";
+}
+.fa-tv:before,
+.fa-television:before {
+ content: "\f26c";
+}
+.fa-contao:before {
+ content: "\f26d";
+}
+.fa-500px:before {
+ content: "\f26e";
+}
+.fa-amazon:before {
+ content: "\f270";
+}
+.fa-calendar-plus-o:before {
+ content: "\f271";
+}
+.fa-calendar-minus-o:before {
+ content: "\f272";
+}
+.fa-calendar-times-o:before {
+ content: "\f273";
+}
+.fa-calendar-check-o:before {
+ content: "\f274";
+}
+.fa-industry:before {
+ content: "\f275";
+}
+.fa-map-pin:before {
+ content: "\f276";
+}
+.fa-map-signs:before {
+ content: "\f277";
+}
+.fa-map-o:before {
+ content: "\f278";
+}
+.fa-map:before {
+ content: "\f279";
+}
+.fa-commenting:before {
+ content: "\f27a";
+}
+.fa-commenting-o:before {
+ content: "\f27b";
+}
+.fa-houzz:before {
+ content: "\f27c";
+}
+.fa-vimeo:before {
+ content: "\f27d";
+}
+.fa-black-tie:before {
+ content: "\f27e";
+}
+.fa-fonticons:before {
+ content: "\f280";
+}
+.fa-reddit-alien:before {
+ content: "\f281";
+}
+.fa-edge:before {
+ content: "\f282";
+}
+.fa-credit-card-alt:before {
+ content: "\f283";
+}
+.fa-codiepie:before {
+ content: "\f284";
+}
+.fa-modx:before {
+ content: "\f285";
+}
+.fa-fort-awesome:before {
+ content: "\f286";
+}
+.fa-usb:before {
+ content: "\f287";
+}
+.fa-product-hunt:before {
+ content: "\f288";
+}
+.fa-mixcloud:before {
+ content: "\f289";
+}
+.fa-scribd:before {
+ content: "\f28a";
+}
+.fa-pause-circle:before {
+ content: "\f28b";
+}
+.fa-pause-circle-o:before {
+ content: "\f28c";
+}
+.fa-stop-circle:before {
+ content: "\f28d";
+}
+.fa-stop-circle-o:before {
+ content: "\f28e";
+}
+.fa-shopping-bag:before {
+ content: "\f290";
+}
+.fa-shopping-basket:before {
+ content: "\f291";
+}
+.fa-hashtag:before {
+ content: "\f292";
+}
+.fa-bluetooth:before {
+ content: "\f293";
+}
+.fa-bluetooth-b:before {
+ content: "\f294";
+}
+.fa-percent:before {
+ content: "\f295";
+}
+.fa-gitlab:before {
+ content: "\f296";
+}
+.fa-wpbeginner:before {
+ content: "\f297";
+}
+.fa-wpforms:before {
+ content: "\f298";
+}
+.fa-envira:before {
+ content: "\f299";
+}
+.fa-universal-access:before {
+ content: "\f29a";
+}
+.fa-wheelchair-alt:before {
+ content: "\f29b";
+}
+.fa-question-circle-o:before {
+ content: "\f29c";
+}
+.fa-blind:before {
+ content: "\f29d";
+}
+.fa-audio-description:before {
+ content: "\f29e";
+}
+.fa-volume-control-phone:before {
+ content: "\f2a0";
+}
+.fa-braille:before {
+ content: "\f2a1";
+}
+.fa-assistive-listening-systems:before {
+ content: "\f2a2";
+}
+.fa-asl-interpreting:before,
+.fa-american-sign-language-interpreting:before {
+ content: "\f2a3";
+}
+.fa-deafness:before,
+.fa-hard-of-hearing:before,
+.fa-deaf:before {
+ content: "\f2a4";
+}
+.fa-glide:before {
+ content: "\f2a5";
+}
+.fa-glide-g:before {
+ content: "\f2a6";
+}
+.fa-signing:before,
+.fa-sign-language:before {
+ content: "\f2a7";
+}
+.fa-low-vision:before {
+ content: "\f2a8";
+}
+.fa-viadeo:before {
+ content: "\f2a9";
+}
+.fa-viadeo-square:before {
+ content: "\f2aa";
+}
+.fa-snapchat:before {
+ content: "\f2ab";
+}
+.fa-snapchat-ghost:before {
+ content: "\f2ac";
+}
+.fa-snapchat-square:before {
+ content: "\f2ad";
+}
+.fa-pied-piper:before {
+ content: "\f2ae";
+}
+.fa-first-order:before {
+ content: "\f2b0";
+}
+.fa-yoast:before {
+ content: "\f2b1";
+}
+.fa-themeisle:before {
+ content: "\f2b2";
+}
+.fa-google-plus-circle:before,
+.fa-google-plus-official:before {
+ content: "\f2b3";
+}
+.fa-fa:before,
+.fa-font-awesome:before {
+ content: "\f2b4";
+}
+.fa-handshake-o:before {
+ content: "\f2b5";
+}
+.fa-envelope-open:before {
+ content: "\f2b6";
+}
+.fa-envelope-open-o:before {
+ content: "\f2b7";
+}
+.fa-linode:before {
+ content: "\f2b8";
+}
+.fa-address-book:before {
+ content: "\f2b9";
+}
+.fa-address-book-o:before {
+ content: "\f2ba";
+}
+.fa-vcard:before,
+.fa-address-card:before {
+ content: "\f2bb";
+}
+.fa-vcard-o:before,
+.fa-address-card-o:before {
+ content: "\f2bc";
+}
+.fa-user-circle:before {
+ content: "\f2bd";
+}
+.fa-user-circle-o:before {
+ content: "\f2be";
+}
+.fa-user-o:before {
+ content: "\f2c0";
+}
+.fa-id-badge:before {
+ content: "\f2c1";
+}
+.fa-drivers-license:before,
+.fa-id-card:before {
+ content: "\f2c2";
+}
+.fa-drivers-license-o:before,
+.fa-id-card-o:before {
+ content: "\f2c3";
+}
+.fa-quora:before {
+ content: "\f2c4";
+}
+.fa-free-code-camp:before {
+ content: "\f2c5";
+}
+.fa-telegram:before {
+ content: "\f2c6";
+}
+.fa-thermometer-4:before,
+.fa-thermometer:before,
+.fa-thermometer-full:before {
+ content: "\f2c7";
+}
+.fa-thermometer-3:before,
+.fa-thermometer-three-quarters:before {
+ content: "\f2c8";
+}
+.fa-thermometer-2:before,
+.fa-thermometer-half:before {
+ content: "\f2c9";
+}
+.fa-thermometer-1:before,
+.fa-thermometer-quarter:before {
+ content: "\f2ca";
+}
+.fa-thermometer-0:before,
+.fa-thermometer-empty:before {
+ content: "\f2cb";
+}
+.fa-shower:before {
+ content: "\f2cc";
+}
+.fa-bathtub:before,
+.fa-s15:before,
+.fa-bath:before {
+ content: "\f2cd";
+}
+.fa-podcast:before {
+ content: "\f2ce";
+}
+.fa-window-maximize:before {
+ content: "\f2d0";
+}
+.fa-window-minimize:before {
+ content: "\f2d1";
+}
+.fa-window-restore:before {
+ content: "\f2d2";
+}
+.fa-times-rectangle:before,
+.fa-window-close:before {
+ content: "\f2d3";
+}
+.fa-times-rectangle-o:before,
+.fa-window-close-o:before {
+ content: "\f2d4";
+}
+.fa-bandcamp:before {
+ content: "\f2d5";
+}
+.fa-grav:before {
+ content: "\f2d6";
+}
+.fa-etsy:before {
+ content: "\f2d7";
+}
+.fa-imdb:before {
+ content: "\f2d8";
+}
+.fa-ravelry:before {
+ content: "\f2d9";
+}
+.fa-eercast:before {
+ content: "\f2da";
+}
+.fa-microchip:before {
+ content: "\f2db";
+}
+.fa-snowflake-o:before {
+ content: "\f2dc";
+}
+.fa-superpowers:before {
+ content: "\f2dd";
+}
+.fa-wpexplorer:before {
+ content: "\f2de";
+}
+.fa-meetup:before {
+ content: "\f2e0";
+}
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ border: 0;
+}
+.sr-only-focusable:active,
+.sr-only-focusable:focus {
+ position: static;
+ width: auto;
+ height: auto;
+ margin: 0;
+ overflow: visible;
+ clip: auto;
+}
--- /dev/null
+/*!
+ * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
+ * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+ */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}
--- /dev/null
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg>
+<metadata>
+Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016
+ By ,,,
+Copyright Dave Gandy 2016. All rights reserved.
+</metadata>
+<defs>
+<font id="FontAwesome" horiz-adv-x="1536" >
+ <font-face
+ font-family="FontAwesome"
+ font-weight="400"
+ font-stretch="normal"
+ units-per-em="1792"
+ panose-1="0 0 0 0 0 0 0 0 0 0"
+ ascent="1536"
+ descent="-256"
+ bbox="-1.02083 -256.962 2304.6 1537.02"
+ underline-thickness="0"
+ underline-position="0"
+ unicode-range="U+0020-F500"
+ />
+<missing-glyph horiz-adv-x="896"
+d="M224 112h448v1312h-448v-1312zM112 0v1536h672v-1536h-672z" />
+ <glyph glyph-name=".notdef" horiz-adv-x="896"
+d="M224 112h448v1312h-448v-1312zM112 0v1536h672v-1536h-672z" />
+ <glyph glyph-name=".null" horiz-adv-x="0"
+ />
+ <glyph glyph-name="nonmarkingreturn" horiz-adv-x="597"
+ />
+ <glyph glyph-name="space" unicode=" " horiz-adv-x="448"
+ />
+ <glyph glyph-name="dieresis" unicode="¨" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="copyright" unicode="©" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="registered" unicode="®" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="acute" unicode="´" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="AE" unicode="Æ" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="Oslash" unicode="Ø" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="trademark" unicode="™" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="infinity" unicode="∞" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="notequal" unicode="≠" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="glass" unicode="" horiz-adv-x="1792"
+d="M1699 1350q0 -35 -43 -78l-632 -632v-768h320q26 0 45 -19t19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45t45 19h320v768l-632 632q-43 43 -43 78q0 23 18 36.5t38 17.5t43 4h1408q23 0 43 -4t38 -17.5t18 -36.5z" />
+ <glyph glyph-name="music" unicode=""
+d="M1536 1312v-1120q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v537l-768 -237v-709q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89
+t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v967q0 31 19 56.5t49 35.5l832 256q12 4 28 4q40 0 68 -28t28 -68z" />
+ <glyph glyph-name="search" unicode="" horiz-adv-x="1664"
+d="M1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -52 -38 -90t-90 -38q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5
+t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
+ <glyph glyph-name="envelope" unicode="" horiz-adv-x="1792"
+d="M1664 32v768q-32 -36 -69 -66q-268 -206 -426 -338q-51 -43 -83 -67t-86.5 -48.5t-102.5 -24.5h-1h-1q-48 0 -102.5 24.5t-86.5 48.5t-83 67q-158 132 -426 338q-37 30 -69 66v-768q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1664 1083v11v13.5t-0.5 13
+t-3 12.5t-5.5 9t-9 7.5t-14 2.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5q0 -168 147 -284q193 -152 401 -317q6 -5 35 -29.5t46 -37.5t44.5 -31.5t50.5 -27.5t43 -9h1h1q20 0 43 9t50.5 27.5t44.5 31.5t46 37.5t35 29.5q208 165 401 317q54 43 100.5 115.5t46.5 131.5z
+M1792 1120v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
+ <glyph glyph-name="heart" unicode="" horiz-adv-x="1792"
+d="M896 -128q-26 0 -44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600
+q-18 -18 -44 -18z" />
+ <glyph glyph-name="star" unicode="" horiz-adv-x="1664"
+d="M1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -21 -10.5 -35.5t-30.5 -14.5q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455
+l502 -73q56 -9 56 -46z" />
+ <glyph glyph-name="star_empty" unicode="" horiz-adv-x="1664"
+d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -50 -41 -50q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500
+l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46z" />
+ <glyph glyph-name="user" unicode="" horiz-adv-x="1280"
+d="M1280 137q0 -109 -62.5 -187t-150.5 -78h-854q-88 0 -150.5 78t-62.5 187q0 85 8.5 160.5t31.5 152t58.5 131t94 89t134.5 34.5q131 -128 313 -128t313 128q76 0 134.5 -34.5t94 -89t58.5 -131t31.5 -152t8.5 -160.5zM1024 1024q0 -159 -112.5 -271.5t-271.5 -112.5
+t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
+ <glyph glyph-name="film" unicode="" horiz-adv-x="1920"
+d="M384 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 320v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 704v128q0 26 -19 45t-45 19h-128
+q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 -64v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM384 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45
+t45 -19h128q26 0 45 19t19 45zM1792 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 704v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1792 320v128
+q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 704v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19
+t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1920 1248v-1344q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1344q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+ <glyph glyph-name="th_large" unicode="" horiz-adv-x="1664"
+d="M768 512v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM768 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 512v-384q0 -52 -38 -90t-90 -38
+h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
+ <glyph glyph-name="th" unicode="" horiz-adv-x="1792"
+d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 288v-192q0 -40 -28 -68t-68 -28h-320
+q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28
+h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192
+q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68z" />
+ <glyph glyph-name="th_list" unicode="" horiz-adv-x="1792"
+d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-960
+q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28
+h960q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68z" />
+ <glyph glyph-name="ok" unicode="" horiz-adv-x="1792"
+d="M1671 970q0 -40 -28 -68l-724 -724l-136 -136q-28 -28 -68 -28t-68 28l-136 136l-362 362q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -295l656 657q28 28 68 28t68 -28l136 -136q28 -28 28 -68z" />
+ <glyph glyph-name="remove" unicode="" horiz-adv-x="1408"
+d="M1298 214q0 -40 -28 -68l-136 -136q-28 -28 -68 -28t-68 28l-294 294l-294 -294q-28 -28 -68 -28t-68 28l-136 136q-28 28 -28 68t28 68l294 294l-294 294q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -294l294 294q28 28 68 28t68 -28l136 -136q28 -28 28 -68
+t-28 -68l-294 -294l294 -294q28 -28 28 -68z" />
+ <glyph glyph-name="zoom_in" unicode="" horiz-adv-x="1664"
+d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-224q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v224h-224q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h224v224q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-224h224
+q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5
+t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
+ <glyph glyph-name="zoom_out" unicode="" horiz-adv-x="1664"
+d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-576q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h576q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5z
+M1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z
+" />
+ <glyph glyph-name="off" unicode=""
+d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61t-298 61t-245 164t-164 245t-61 298q0 182 80.5 343t226.5 270q43 32 95.5 25t83.5 -50q32 -42 24.5 -94.5t-49.5 -84.5q-98 -74 -151.5 -181t-53.5 -228q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5
+t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5q0 121 -53.5 228t-151.5 181q-42 32 -49.5 84.5t24.5 94.5q31 43 84 50t95 -25q146 -109 226.5 -270t80.5 -343zM896 1408v-640q0 -52 -38 -90t-90 -38t-90 38t-38 90v640q0 52 38 90t90 38t90 -38t38 -90z" />
+ <glyph glyph-name="signal" unicode="" horiz-adv-x="1792"
+d="M256 96v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 224v-320q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 480v-576q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23
+v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1408 864v-960q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1376v-1472q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1472q0 14 9 23t23 9h192q14 0 23 -9t9 -23z" />
+ <glyph glyph-name="cog" unicode=""
+d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1536 749v-222q0 -12 -8 -23t-20 -13l-185 -28q-19 -54 -39 -91q35 -50 107 -138q10 -12 10 -25t-9 -23q-27 -37 -99 -108t-94 -71q-12 0 -26 9l-138 108q-44 -23 -91 -38
+q-16 -136 -29 -186q-7 -28 -36 -28h-222q-14 0 -24.5 8.5t-11.5 21.5l-28 184q-49 16 -90 37l-141 -107q-10 -9 -25 -9q-14 0 -25 11q-126 114 -165 168q-7 10 -7 23q0 12 8 23q15 21 51 66.5t54 70.5q-27 50 -41 99l-183 27q-13 2 -21 12.5t-8 23.5v222q0 12 8 23t19 13
+l186 28q14 46 39 92q-40 57 -107 138q-10 12 -10 24q0 10 9 23q26 36 98.5 107.5t94.5 71.5q13 0 26 -10l138 -107q44 23 91 38q16 136 29 186q7 28 36 28h222q14 0 24.5 -8.5t11.5 -21.5l28 -184q49 -16 90 -37l142 107q9 9 24 9q13 0 25 -10q129 -119 165 -170q7 -8 7 -22
+q0 -12 -8 -23q-15 -21 -51 -66.5t-54 -70.5q26 -50 41 -98l183 -28q13 -2 21 -12.5t8 -23.5z" />
+ <glyph glyph-name="trash" unicode="" horiz-adv-x="1408"
+d="M512 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM768 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1024 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576
+q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1152 76v948h-896v-948q0 -22 7 -40.5t14.5 -27t10.5 -8.5h832q3 0 10.5 8.5t14.5 27t7 40.5zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832
+q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" />
+ <glyph glyph-name="home" unicode="" horiz-adv-x="1664"
+d="M1408 544v-480q0 -26 -19 -45t-45 -19h-384v384h-256v-384h-384q-26 0 -45 19t-19 45v480q0 1 0.5 3t0.5 3l575 474l575 -474q1 -2 1 -6zM1631 613l-62 -74q-8 -9 -21 -11h-3q-13 0 -21 7l-692 577l-692 -577q-12 -8 -24 -7q-13 2 -21 11l-62 74q-8 10 -7 23.5t11 21.5
+l719 599q32 26 76 26t76 -26l244 -204v195q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-408l219 -182q10 -8 11 -21.5t-7 -23.5z" />
+ <glyph glyph-name="file_alt" unicode=""
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+" />
+ <glyph glyph-name="time" unicode=""
+d="M896 992v-448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="road" unicode="" horiz-adv-x="1920"
+d="M1111 540v4l-24 320q-1 13 -11 22.5t-23 9.5h-186q-13 0 -23 -9.5t-11 -22.5l-24 -320v-4q-1 -12 8 -20t21 -8h244q12 0 21 8t8 20zM1870 73q0 -73 -46 -73h-704q13 0 22 9.5t8 22.5l-20 256q-1 13 -11 22.5t-23 9.5h-272q-13 0 -23 -9.5t-11 -22.5l-20 -256
+q-1 -13 8 -22.5t22 -9.5h-704q-46 0 -46 73q0 54 26 116l417 1044q8 19 26 33t38 14h339q-13 0 -23 -9.5t-11 -22.5l-15 -192q-1 -14 8 -23t22 -9h166q13 0 22 9t8 23l-15 192q-1 13 -11 22.5t-23 9.5h339q20 0 38 -14t26 -33l417 -1044q26 -62 26 -116z" />
+ <glyph glyph-name="download_alt" unicode="" horiz-adv-x="1664"
+d="M1280 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 416v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h465l135 -136
+q58 -56 136 -56t136 56l136 136h464q40 0 68 -28t28 -68zM1339 985q17 -41 -14 -70l-448 -448q-18 -19 -45 -19t-45 19l-448 448q-31 29 -14 70q17 39 59 39h256v448q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-448h256q42 0 59 -39z" />
+ <glyph glyph-name="download" unicode=""
+d="M1120 608q0 -12 -10 -24l-319 -319q-11 -9 -23 -9t-23 9l-320 320q-15 16 -7 35q8 20 30 20h192v352q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-352h192q14 0 23 -9t9 -23zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273
+t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="upload" unicode=""
+d="M1118 660q-8 -20 -30 -20h-192v-352q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v352h-192q-14 0 -23 9t-9 23q0 12 10 24l319 319q11 9 23 9t23 -9l320 -320q15 -16 7 -35zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198
+t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="inbox" unicode=""
+d="M1023 576h316q-1 3 -2.5 8.5t-2.5 7.5l-212 496h-708l-212 -496q-1 -3 -2.5 -8.5t-2.5 -7.5h316l95 -192h320zM1536 546v-482q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v482q0 62 25 123l238 552q10 25 36.5 42t52.5 17h832q26 0 52.5 -17t36.5 -42l238 -552
+q25 -61 25 -123z" />
+ <glyph glyph-name="play_circle" unicode=""
+d="M1184 640q0 -37 -32 -55l-544 -320q-15 -9 -32 -9q-16 0 -32 8q-32 19 -32 56v640q0 37 32 56q33 18 64 -1l544 -320q32 -18 32 -55zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="repeat" unicode=""
+d="M1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l138 138q-148 137 -349 137q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5q119 0 225 52t179 147q7 10 23 12q15 0 25 -9
+l137 -138q9 -8 9.5 -20.5t-7.5 -22.5q-109 -132 -264 -204.5t-327 -72.5q-156 0 -298 61t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q147 0 284.5 -55.5t244.5 -156.5l130 129q29 31 70 14q39 -17 39 -59z" />
+ <glyph glyph-name="refresh" unicode=""
+d="M1511 480q0 -5 -1 -7q-64 -268 -268 -434.5t-478 -166.5q-146 0 -282.5 55t-243.5 157l-129 -129q-19 -19 -45 -19t-45 19t-19 45v448q0 26 19 45t45 19h448q26 0 45 -19t19 -45t-19 -45l-137 -137q71 -66 161 -102t187 -36q134 0 250 65t186 179q11 17 53 117
+q8 23 30 23h192q13 0 22.5 -9.5t9.5 -22.5zM1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-26 0 -45 19t-19 45t19 45l138 138q-148 137 -349 137q-134 0 -250 -65t-186 -179q-11 -17 -53 -117q-8 -23 -30 -23h-199q-13 0 -22.5 9.5t-9.5 22.5v7q65 268 270 434.5t480 166.5
+q146 0 284 -55.5t245 -156.5l130 129q19 19 45 19t45 -19t19 -45z" />
+ <glyph glyph-name="list_alt" unicode="" horiz-adv-x="1792"
+d="M384 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M384 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1536 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5z
+M1536 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5zM1536 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5
+t9.5 -22.5zM1664 160v832q0 13 -9.5 22.5t-22.5 9.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 1248v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47
+t47 -113z" />
+ <glyph glyph-name="lock" unicode="" horiz-adv-x="1152"
+d="M320 768h512v192q0 106 -75 181t-181 75t-181 -75t-75 -181v-192zM1152 672v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v192q0 184 132 316t316 132t316 -132t132 -316v-192h32q40 0 68 -28t28 -68z" />
+ <glyph glyph-name="flag" unicode="" horiz-adv-x="1792"
+d="M320 1280q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48
+t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="headphones" unicode="" horiz-adv-x="1664"
+d="M1664 650q0 -166 -60 -314l-20 -49l-185 -33q-22 -83 -90.5 -136.5t-156.5 -53.5v-32q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-32q71 0 130 -35.5t93 -95.5l68 12q29 95 29 193q0 148 -88 279t-236.5 209t-315.5 78
+t-315.5 -78t-236.5 -209t-88 -279q0 -98 29 -193l68 -12q34 60 93 95.5t130 35.5v32q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v32q-88 0 -156.5 53.5t-90.5 136.5l-185 33l-20 49q-60 148 -60 314q0 151 67 291t179 242.5
+t266 163.5t320 61t320 -61t266 -163.5t179 -242.5t67 -291z" />
+ <glyph glyph-name="volume_off" unicode="" horiz-adv-x="768"
+d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45z" />
+ <glyph glyph-name="volume_down" unicode="" horiz-adv-x="1152"
+d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 36
+t12 56.5t-12 56.5t-29 36t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142z" />
+ <glyph glyph-name="volume_up" unicode="" horiz-adv-x="1664"
+d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 36
+t12 56.5t-12 56.5t-29 36t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142zM1408 640q0 -153 -85 -282.5t-225 -188.5q-13 -5 -25 -5q-27 0 -46 19t-19 45q0 39 39 59q56 29 76 44q74 54 115.5 135.5t41.5 173.5t-41.5 173.5
+t-115.5 135.5q-20 15 -76 44q-39 20 -39 59q0 26 19 45t45 19q13 0 26 -5q140 -59 225 -188.5t85 -282.5zM1664 640q0 -230 -127 -422.5t-338 -283.5q-13 -5 -26 -5q-26 0 -45 19t-19 45q0 36 39 59q7 4 22.5 10.5t22.5 10.5q46 25 82 51q123 91 192 227t69 289t-69 289
+t-192 227q-36 26 -82 51q-7 4 -22.5 10.5t-22.5 10.5q-39 23 -39 59q0 26 19 45t45 19q13 0 26 -5q211 -91 338 -283.5t127 -422.5z" />
+ <glyph glyph-name="qrcode" unicode="" horiz-adv-x="1408"
+d="M384 384v-128h-128v128h128zM384 1152v-128h-128v128h128zM1152 1152v-128h-128v128h128zM128 129h384v383h-384v-383zM128 896h384v384h-384v-384zM896 896h384v384h-384v-384zM640 640v-640h-640v640h640zM1152 128v-128h-128v128h128zM1408 128v-128h-128v128h128z
+M1408 640v-384h-384v128h-128v-384h-128v640h384v-128h128v128h128zM640 1408v-640h-640v640h640zM1408 1408v-640h-640v640h640z" />
+ <glyph glyph-name="barcode" unicode="" horiz-adv-x="1792"
+d="M63 0h-63v1408h63v-1408zM126 1h-32v1407h32v-1407zM220 1h-31v1407h31v-1407zM377 1h-31v1407h31v-1407zM534 1h-62v1407h62v-1407zM660 1h-31v1407h31v-1407zM723 1h-31v1407h31v-1407zM786 1h-31v1407h31v-1407zM943 1h-63v1407h63v-1407zM1100 1h-63v1407h63v-1407z
+M1226 1h-63v1407h63v-1407zM1352 1h-63v1407h63v-1407zM1446 1h-63v1407h63v-1407zM1635 1h-94v1407h94v-1407zM1698 1h-32v1407h32v-1407zM1792 0h-63v1408h63v-1408z" />
+ <glyph glyph-name="tag" unicode=""
+d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5
+l715 -714q37 -39 37 -91z" />
+ <glyph glyph-name="tags" unicode="" horiz-adv-x="1920"
+d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5
+l715 -714q37 -39 37 -91zM1899 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-36 0 -59 14t-53 45l470 470q37 37 37 90q0 52 -37 91l-715 714q-38 38 -102 64.5t-117 26.5h224q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91z" />
+ <glyph glyph-name="book" unicode="" horiz-adv-x="1664"
+d="M1639 1058q40 -57 18 -129l-275 -906q-19 -64 -76.5 -107.5t-122.5 -43.5h-923q-77 0 -148.5 53.5t-99.5 131.5q-24 67 -2 127q0 4 3 27t4 37q1 8 -3 21.5t-3 19.5q2 11 8 21t16.5 23.5t16.5 23.5q23 38 45 91.5t30 91.5q3 10 0.5 30t-0.5 28q3 11 17 28t17 23
+q21 36 42 92t25 90q1 9 -2.5 32t0.5 28q4 13 22 30.5t22 22.5q19 26 42.5 84.5t27.5 96.5q1 8 -3 25.5t-2 26.5q2 8 9 18t18 23t17 21q8 12 16.5 30.5t15 35t16 36t19.5 32t26.5 23.5t36 11.5t47.5 -5.5l-1 -3q38 9 51 9h761q74 0 114 -56t18 -130l-274 -906
+q-36 -119 -71.5 -153.5t-128.5 -34.5h-869q-27 0 -38 -15q-11 -16 -1 -43q24 -70 144 -70h923q29 0 56 15.5t35 41.5l300 987q7 22 5 57q38 -15 59 -43zM575 1056q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5
+t-16.5 -22.5zM492 800q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5t-16.5 -22.5z" />
+ <glyph glyph-name="bookmark" unicode="" horiz-adv-x="1280"
+d="M1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
+ <glyph glyph-name="print" unicode="" horiz-adv-x="1664"
+d="M384 0h896v256h-896v-256zM384 640h896v384h-160q-40 0 -68 28t-28 68v160h-640v-640zM1536 576q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 576v-416q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-160q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68
+v160h-224q-13 0 -22.5 9.5t-9.5 22.5v416q0 79 56.5 135.5t135.5 56.5h64v544q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-256h64q79 0 135.5 -56.5t56.5 -135.5z" />
+ <glyph glyph-name="camera" unicode="" horiz-adv-x="1920"
+d="M960 864q119 0 203.5 -84.5t84.5 -203.5t-84.5 -203.5t-203.5 -84.5t-203.5 84.5t-84.5 203.5t84.5 203.5t203.5 84.5zM1664 1280q106 0 181 -75t75 -181v-896q0 -106 -75 -181t-181 -75h-1408q-106 0 -181 75t-75 181v896q0 106 75 181t181 75h224l51 136
+q19 49 69.5 84.5t103.5 35.5h512q53 0 103.5 -35.5t69.5 -84.5l51 -136h224zM960 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+ <glyph glyph-name="font" unicode="" horiz-adv-x="1664"
+d="M725 977l-170 -450q33 0 136.5 -2t160.5 -2q19 0 57 2q-87 253 -184 452zM0 -128l2 79q23 7 56 12.5t57 10.5t49.5 14.5t44.5 29t31 50.5l237 616l280 724h75h53q8 -14 11 -21l205 -480q33 -78 106 -257.5t114 -274.5q15 -34 58 -144.5t72 -168.5q20 -45 35 -57
+q19 -15 88 -29.5t84 -20.5q6 -38 6 -57q0 -5 -0.5 -13.5t-0.5 -12.5q-63 0 -190 8t-191 8q-76 0 -215 -7t-178 -8q0 43 4 78l131 28q1 0 12.5 2.5t15.5 3.5t14.5 4.5t15 6.5t11 8t9 11t2.5 14q0 16 -31 96.5t-72 177.5t-42 100l-450 2q-26 -58 -76.5 -195.5t-50.5 -162.5
+q0 -22 14 -37.5t43.5 -24.5t48.5 -13.5t57 -8.5t41 -4q1 -19 1 -58q0 -9 -2 -27q-58 0 -174.5 10t-174.5 10q-8 0 -26.5 -4t-21.5 -4q-80 -14 -188 -14z" />
+ <glyph glyph-name="bold" unicode="" horiz-adv-x="1408"
+d="M555 15q74 -32 140 -32q376 0 376 335q0 114 -41 180q-27 44 -61.5 74t-67.5 46.5t-80.5 25t-84 10.5t-94.5 2q-73 0 -101 -10q0 -53 -0.5 -159t-0.5 -158q0 -8 -1 -67.5t-0.5 -96.5t4.5 -83.5t12 -66.5zM541 761q42 -7 109 -7q82 0 143 13t110 44.5t74.5 89.5t25.5 142
+q0 70 -29 122.5t-79 82t-108 43.5t-124 14q-50 0 -130 -13q0 -50 4 -151t4 -152q0 -27 -0.5 -80t-0.5 -79q0 -46 1 -69zM0 -128l2 94q15 4 85 16t106 27q7 12 12.5 27t8.5 33.5t5.5 32.5t3 37.5t0.5 34v35.5v30q0 982 -22 1025q-4 8 -22 14.5t-44.5 11t-49.5 7t-48.5 4.5
+t-30.5 3l-4 83q98 2 340 11.5t373 9.5q23 0 68 -0.5t68 -0.5q70 0 136.5 -13t128.5 -42t108 -71t74 -104.5t28 -137.5q0 -52 -16.5 -95.5t-39 -72t-64.5 -57.5t-73 -45t-84 -40q154 -35 256.5 -134t102.5 -248q0 -100 -35 -179.5t-93.5 -130.5t-138 -85.5t-163.5 -48.5
+t-176 -14q-44 0 -132 3t-132 3q-106 0 -307 -11t-231 -12z" />
+ <glyph glyph-name="italic" unicode="" horiz-adv-x="1024"
+d="M0 -126l17 85q22 7 61.5 16.5t72 19t59.5 23.5q28 35 41 101q1 7 62 289t114 543.5t52 296.5v25q-24 13 -54.5 18.5t-69.5 8t-58 5.5l19 103q33 -2 120 -6.5t149.5 -7t120.5 -2.5q48 0 98.5 2.5t121 7t98.5 6.5q-5 -39 -19 -89q-30 -10 -101.5 -28.5t-108.5 -33.5
+q-8 -19 -14 -42.5t-9 -40t-7.5 -45.5t-6.5 -42q-27 -148 -87.5 -419.5t-77.5 -355.5q-2 -9 -13 -58t-20 -90t-16 -83.5t-6 -57.5l1 -18q17 -4 185 -31q-3 -44 -16 -99q-11 0 -32.5 -1.5t-32.5 -1.5q-29 0 -87 10t-86 10q-138 2 -206 2q-51 0 -143 -9t-121 -11z" />
+ <glyph glyph-name="text_height" unicode="" horiz-adv-x="1792"
+d="M1744 128q33 0 42 -18.5t-11 -44.5l-126 -162q-20 -26 -49 -26t-49 26l-126 162q-20 26 -11 44.5t42 18.5h80v1024h-80q-33 0 -42 18.5t11 44.5l126 162q20 26 49 26t49 -26l126 -162q20 -26 11 -44.5t-42 -18.5h-80v-1024h80zM81 1407l54 -27q12 -5 211 -5q44 0 132 2
+t132 2q36 0 107.5 -0.5t107.5 -0.5h293q6 0 21 -0.5t20.5 0t16 3t17.5 9t15 17.5l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 48t-14.5 73.5t-7.5 35.5q-6 8 -12 12.5t-15.5 6t-13 2.5t-18 0.5t-16.5 -0.5
+q-17 0 -66.5 0.5t-74.5 0.5t-64 -2t-71 -6q-9 -81 -8 -136q0 -94 2 -388t2 -455q0 -16 -2.5 -71.5t0 -91.5t12.5 -69q40 -21 124 -42.5t120 -37.5q5 -40 5 -50q0 -14 -3 -29l-34 -1q-76 -2 -218 8t-207 10q-50 0 -151 -9t-152 -9q-3 51 -3 52v9q17 27 61.5 43t98.5 29t78 27
+q19 42 19 383q0 101 -3 303t-3 303v117q0 2 0.5 15.5t0.5 25t-1 25.5t-3 24t-5 14q-11 12 -162 12q-33 0 -93 -12t-80 -26q-19 -13 -34 -72.5t-31.5 -111t-42.5 -53.5q-42 26 -56 44v383z" />
+ <glyph glyph-name="text_width" unicode=""
+d="M81 1407l54 -27q12 -5 211 -5q44 0 132 2t132 2q70 0 246.5 1t304.5 0.5t247 -4.5q33 -1 56 31l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 47.5t-15 73.5t-7 36q-10 13 -27 19q-5 2 -66 2q-30 0 -93 1t-103 1
+t-94 -2t-96 -7q-9 -81 -8 -136l1 -152v52q0 -55 1 -154t1.5 -180t0.5 -153q0 -16 -2.5 -71.5t0 -91.5t12.5 -69q40 -21 124 -42.5t120 -37.5q5 -40 5 -50q0 -14 -3 -29l-34 -1q-76 -2 -218 8t-207 10q-50 0 -151 -9t-152 -9q-3 51 -3 52v9q17 27 61.5 43t98.5 29t78 27
+q7 16 11.5 74t6 145.5t1.5 155t-0.5 153.5t-0.5 89q0 7 -2.5 21.5t-2.5 22.5q0 7 0.5 44t1 73t0 76.5t-3 67.5t-6.5 32q-11 12 -162 12q-41 0 -163 -13.5t-138 -24.5q-19 -12 -34 -71.5t-31.5 -111.5t-42.5 -54q-42 26 -56 44v383zM1310 125q12 0 42 -19.5t57.5 -41.5
+t59.5 -49t36 -30q26 -21 26 -49t-26 -49q-4 -3 -36 -30t-59.5 -49t-57.5 -41.5t-42 -19.5q-13 0 -20.5 10.5t-10 28.5t-2.5 33.5t1.5 33t1.5 19.5h-1024q0 -2 1.5 -19.5t1.5 -33t-2.5 -33.5t-10 -28.5t-20.5 -10.5q-12 0 -42 19.5t-57.5 41.5t-59.5 49t-36 30q-26 21 -26 49
+t26 49q4 3 36 30t59.5 49t57.5 41.5t42 19.5q13 0 20.5 -10.5t10 -28.5t2.5 -33.5t-1.5 -33t-1.5 -19.5h1024q0 2 -1.5 19.5t-1.5 33t2.5 33.5t10 28.5t20.5 10.5z" />
+ <glyph glyph-name="align_left" unicode="" horiz-adv-x="1792"
+d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45
+t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="align_center" unicode="" horiz-adv-x="1792"
+d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45t-45 -19
+h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h640q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="align_right" unicode="" horiz-adv-x="1792"
+d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45
+t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="align_justify" unicode="" horiz-adv-x="1792"
+d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45
+t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="list" unicode="" horiz-adv-x="1792"
+d="M256 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM256 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5
+t9.5 -22.5zM256 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344
+q13 0 22.5 -9.5t9.5 -22.5zM256 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5
+t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192
+q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5z" />
+ <glyph glyph-name="indent_left" unicode="" horiz-adv-x="1792"
+d="M384 992v-576q0 -13 -9.5 -22.5t-22.5 -9.5q-14 0 -23 9l-288 288q-9 9 -9 23t9 23l288 288q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5
+t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088
+q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
+ <glyph glyph-name="indent_right" unicode="" horiz-adv-x="1792"
+d="M352 704q0 -14 -9 -23l-288 -288q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5q14 0 23 -9l288 -288q9 -9 9 -23zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5
+t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088
+q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
+ <glyph glyph-name="facetime_video" unicode="" horiz-adv-x="1792"
+d="M1792 1184v-1088q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-403 403v-166q0 -119 -84.5 -203.5t-203.5 -84.5h-704q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h704q119 0 203.5 -84.5t84.5 -203.5v-165l403 402q18 19 45 19q12 0 25 -5
+q39 -17 39 -59z" />
+ <glyph glyph-name="picture" unicode="" horiz-adv-x="1920"
+d="M640 960q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 576v-448h-1408v192l320 320l160 -160l512 512zM1760 1280h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216
+q0 13 -9.5 22.5t-22.5 9.5zM1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+ <glyph glyph-name="pencil" unicode=""
+d="M363 0l91 91l-235 235l-91 -91v-107h128v-128h107zM886 928q0 22 -22 22q-10 0 -17 -7l-542 -542q-7 -7 -7 -17q0 -22 22 -22q10 0 17 7l542 542q7 7 7 17zM832 1120l416 -416l-832 -832h-416v416zM1515 1024q0 -53 -37 -90l-166 -166l-416 416l166 165q36 38 90 38
+q53 0 91 -38l235 -234q37 -39 37 -91z" />
+ <glyph glyph-name="map_marker" unicode="" horiz-adv-x="1024"
+d="M768 896q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1024 896q0 -109 -33 -179l-364 -774q-16 -33 -47.5 -52t-67.5 -19t-67.5 19t-46.5 52l-365 774q-33 70 -33 179q0 212 150 362t362 150t362 -150t150 -362z" />
+ <glyph glyph-name="adjust" unicode=""
+d="M768 96v1088q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="tint" unicode="" horiz-adv-x="1024"
+d="M512 384q0 36 -20 69q-1 1 -15.5 22.5t-25.5 38t-25 44t-21 50.5q-4 16 -21 16t-21 -16q-7 -23 -21 -50.5t-25 -44t-25.5 -38t-15.5 -22.5q-20 -33 -20 -69q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 512q0 -212 -150 -362t-362 -150t-362 150t-150 362
+q0 145 81 275q6 9 62.5 90.5t101 151t99.5 178t83 201.5q9 30 34 47t51 17t51.5 -17t33.5 -47q28 -93 83 -201.5t99.5 -178t101 -151t62.5 -90.5q81 -127 81 -275z" />
+ <glyph glyph-name="edit" unicode="" horiz-adv-x="1792"
+d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072q-16 16 -33 -1l-350 -350q-17 -17 -1 -33t33 1l350 350q17 17 1 33zM1408 478v-190q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832
+q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-14 -14 -32 -8q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v126q0 13 9 22l64 64q15 15 35 7t20 -29zM1312 1216l288 -288l-672 -672h-288v288zM1756 1084l-92 -92
+l-288 288l92 92q28 28 68 28t68 -28l152 -152q28 -28 28 -68t-28 -68z" />
+ <glyph glyph-name="share" unicode="" horiz-adv-x="1664"
+d="M1408 547v-259q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h255v0q13 0 22.5 -9.5t9.5 -22.5q0 -27 -26 -32q-77 -26 -133 -60q-10 -4 -16 -4h-112q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832
+q66 0 113 47t47 113v214q0 19 18 29q28 13 54 37q16 16 35 8q21 -9 21 -29zM1645 1043l-384 -384q-18 -19 -45 -19q-12 0 -25 5q-39 17 -39 59v192h-160q-323 0 -438 -131q-119 -137 -74 -473q3 -23 -20 -34q-8 -2 -12 -2q-16 0 -26 13q-10 14 -21 31t-39.5 68.5t-49.5 99.5
+t-38.5 114t-17.5 122q0 49 3.5 91t14 90t28 88t47 81.5t68.5 74t94.5 61.5t124.5 48.5t159.5 30.5t196.5 11h160v192q0 42 39 59q13 5 25 5q26 0 45 -19l384 -384q19 -19 19 -45t-19 -45z" />
+ <glyph glyph-name="check" unicode="" horiz-adv-x="1664"
+d="M1408 606v-318q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-10 -10 -23 -10q-3 0 -9 2q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832
+q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v254q0 13 9 22l64 64q10 10 23 10q6 0 12 -3q20 -8 20 -29zM1639 1095l-814 -814q-24 -24 -57 -24t-57 24l-430 430q-24 24 -24 57t24 57l110 110q24 24 57 24t57 -24l263 -263l647 647q24 24 57 24t57 -24l110 -110
+q24 -24 24 -57t-24 -57z" />
+ <glyph glyph-name="move" unicode="" horiz-adv-x="1792"
+d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-384v-384h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v384h-384v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45
+t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h384v384h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-384h384v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
+ <glyph glyph-name="step_backward" unicode="" horiz-adv-x="1024"
+d="M979 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 10 13 19z" />
+ <glyph glyph-name="fast_backward" unicode="" horiz-adv-x="1792"
+d="M1747 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 10 13 19l710 710
+q19 19 32 13t13 -32v-710q4 10 13 19z" />
+ <glyph glyph-name="backward" unicode="" horiz-adv-x="1664"
+d="M1619 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-19 19 -19 45t19 45l710 710q19 19 32 13t13 -32v-710q4 10 13 19z" />
+ <glyph glyph-name="play" unicode="" horiz-adv-x="1408"
+d="M1384 609l-1328 -738q-23 -13 -39.5 -3t-16.5 36v1472q0 26 16.5 36t39.5 -3l1328 -738q23 -13 23 -31t-23 -31z" />
+ <glyph glyph-name="pause" unicode=""
+d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45zM640 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="stop" unicode=""
+d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="forward" unicode="" horiz-adv-x="1664"
+d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q9 -9 13 -19v710q0 26 13 32t32 -13l710 -710q19 -19 19 -45t-19 -45l-710 -710q-19 -19 -32 -13t-13 32v710q-4 -10 -13 -19z" />
+ <glyph glyph-name="fast_forward" unicode="" horiz-adv-x="1792"
+d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q9 -9 13 -19v710q0 26 13 32t32 -13l710 -710q9 -9 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-4 -10 -13 -19l-710 -710
+q-19 -19 -32 -13t-13 32v710q-4 -10 -13 -19z" />
+ <glyph glyph-name="step_forward" unicode="" horiz-adv-x="1024"
+d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q9 -9 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-4 -10 -13 -19z" />
+ <glyph glyph-name="eject" unicode="" horiz-adv-x="1538"
+d="M14 557l710 710q19 19 45 19t45 -19l710 -710q19 -19 13 -32t-32 -13h-1472q-26 0 -32 13t13 32zM1473 0h-1408q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19z" />
+ <glyph glyph-name="chevron_left" unicode="" horiz-adv-x="1280"
+d="M1171 1235l-531 -531l531 -531q19 -19 19 -45t-19 -45l-166 -166q-19 -19 -45 -19t-45 19l-742 742q-19 19 -19 45t19 45l742 742q19 19 45 19t45 -19l166 -166q19 -19 19 -45t-19 -45z" />
+ <glyph glyph-name="chevron_right" unicode="" horiz-adv-x="1280"
+d="M1107 659l-742 -742q-19 -19 -45 -19t-45 19l-166 166q-19 19 -19 45t19 45l531 531l-531 531q-19 19 -19 45t19 45l166 166q19 19 45 19t45 -19l742 -742q19 -19 19 -45t-19 -45z" />
+ <glyph glyph-name="plus_sign" unicode=""
+d="M1216 576v128q0 26 -19 45t-45 19h-256v256q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-256h-256q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h256v-256q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v256h256q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5
+t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="minus_sign" unicode=""
+d="M1216 576v128q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5
+t103 -385.5z" />
+ <glyph glyph-name="remove_sign" unicode=""
+d="M1149 414q0 26 -19 45l-181 181l181 181q19 19 19 45q0 27 -19 46l-90 90q-19 19 -46 19q-26 0 -45 -19l-181 -181l-181 181q-19 19 -45 19q-27 0 -46 -19l-90 -90q-19 -19 -19 -46q0 -26 19 -45l181 -181l-181 -181q-19 -19 -19 -45q0 -27 19 -46l90 -90q19 -19 46 -19
+q26 0 45 19l181 181l181 -181q19 -19 45 -19q27 0 46 19l90 90q19 19 19 46zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="ok_sign" unicode=""
+d="M1284 802q0 28 -18 46l-91 90q-19 19 -45 19t-45 -19l-408 -407l-226 226q-19 19 -45 19t-45 -19l-91 -90q-18 -18 -18 -46q0 -27 18 -45l362 -362q19 -19 45 -19q27 0 46 19l543 543q18 18 18 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103
+t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="question_sign" unicode=""
+d="M896 160v192q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h192q14 0 23 9t9 23zM1152 832q0 88 -55.5 163t-138.5 116t-170 41q-243 0 -371 -213q-15 -24 8 -42l132 -100q7 -6 19 -6q16 0 25 12q53 68 86 92q34 24 86 24q48 0 85.5 -26t37.5 -59
+q0 -38 -20 -61t-68 -45q-63 -28 -115.5 -86.5t-52.5 -125.5v-36q0 -14 9 -23t23 -9h192q14 0 23 9t9 23q0 19 21.5 49.5t54.5 49.5q32 18 49 28.5t46 35t44.5 48t28 60.5t12.5 81zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
+t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="info_sign" unicode=""
+d="M1024 160v160q0 14 -9 23t-23 9h-96v512q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h96v-320h-96q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h448q14 0 23 9t9 23zM896 1056v160q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23
+t23 -9h192q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="screenshot" unicode=""
+d="M1197 512h-109q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h109q-32 108 -112.5 188.5t-188.5 112.5v-109q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v109q-108 -32 -188.5 -112.5t-112.5 -188.5h109q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-109
+q32 -108 112.5 -188.5t188.5 -112.5v109q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-109q108 32 188.5 112.5t112.5 188.5zM1536 704v-128q0 -26 -19 -45t-45 -19h-143q-37 -161 -154.5 -278.5t-278.5 -154.5v-143q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v143
+q-161 37 -278.5 154.5t-154.5 278.5h-143q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h143q37 161 154.5 278.5t278.5 154.5v143q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-143q161 -37 278.5 -154.5t154.5 -278.5h143q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="remove_circle" unicode=""
+d="M1097 457l-146 -146q-10 -10 -23 -10t-23 10l-137 137l-137 -137q-10 -10 -23 -10t-23 10l-146 146q-10 10 -10 23t10 23l137 137l-137 137q-10 10 -10 23t10 23l146 146q10 10 23 10t23 -10l137 -137l137 137q10 10 23 10t23 -10l146 -146q10 -10 10 -23t-10 -23
+l-137 -137l137 -137q10 -10 10 -23t-10 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5
+t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="ok_circle" unicode=""
+d="M1171 723l-422 -422q-19 -19 -45 -19t-45 19l-294 294q-19 19 -19 45t19 45l102 102q19 19 45 19t45 -19l147 -147l275 275q19 19 45 19t45 -19l102 -102q19 -19 19 -45t-19 -45zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198
+t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="ban_circle" unicode=""
+d="M1312 643q0 161 -87 295l-754 -753q137 -89 297 -89q111 0 211.5 43.5t173.5 116.5t116 174.5t43 212.5zM313 344l755 754q-135 91 -300 91q-148 0 -273 -73t-198 -199t-73 -274q0 -162 89 -299zM1536 643q0 -157 -61 -300t-163.5 -246t-245 -164t-298.5 -61t-298.5 61
+t-245 164t-163.5 246t-61 300t61 299.5t163.5 245.5t245 164t298.5 61t298.5 -61t245 -164t163.5 -245.5t61 -299.5z" />
+ <glyph glyph-name="arrow_left" unicode=""
+d="M1536 640v-128q0 -53 -32.5 -90.5t-84.5 -37.5h-704l293 -294q38 -36 38 -90t-38 -90l-75 -76q-37 -37 -90 -37q-52 0 -91 37l-651 652q-37 37 -37 90q0 52 37 91l651 650q38 38 91 38q52 0 90 -38l75 -74q38 -38 38 -91t-38 -91l-293 -293h704q52 0 84.5 -37.5
+t32.5 -90.5z" />
+ <glyph glyph-name="arrow_right" unicode=""
+d="M1472 576q0 -54 -37 -91l-651 -651q-39 -37 -91 -37q-51 0 -90 37l-75 75q-38 38 -38 91t38 91l293 293h-704q-52 0 -84.5 37.5t-32.5 90.5v128q0 53 32.5 90.5t84.5 37.5h704l-293 294q-38 36 -38 90t38 90l75 75q38 38 90 38q53 0 91 -38l651 -651q37 -35 37 -90z" />
+ <glyph glyph-name="arrow_up" unicode="" horiz-adv-x="1664"
+d="M1611 565q0 -51 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-294 293v-704q0 -52 -37.5 -84.5t-90.5 -32.5h-128q-53 0 -90.5 32.5t-37.5 84.5v704l-294 -293q-36 -38 -90 -38t-90 38l-75 75q-38 38 -38 90q0 53 38 91l651 651q35 37 90 37q54 0 91 -37l651 -651
+q37 -39 37 -91z" />
+ <glyph glyph-name="arrow_down" unicode="" horiz-adv-x="1664"
+d="M1611 704q0 -53 -37 -90l-651 -652q-39 -37 -91 -37q-53 0 -90 37l-651 652q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l294 -294v704q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-704l294 294q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" />
+ <glyph glyph-name="share_alt" unicode="" horiz-adv-x="1792"
+d="M1792 896q0 -26 -19 -45l-512 -512q-19 -19 -45 -19t-45 19t-19 45v256h-224q-98 0 -175.5 -6t-154 -21.5t-133 -42.5t-105.5 -69.5t-80 -101t-48.5 -138.5t-17.5 -181q0 -55 5 -123q0 -6 2.5 -23.5t2.5 -26.5q0 -15 -8.5 -25t-23.5 -10q-16 0 -28 17q-7 9 -13 22
+t-13.5 30t-10.5 24q-127 285 -127 451q0 199 53 333q162 403 875 403h224v256q0 26 19 45t45 19t45 -19l512 -512q19 -19 19 -45z" />
+ <glyph glyph-name="resize_full" unicode=""
+d="M755 480q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23zM1536 1344v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332
+q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="resize_small" unicode=""
+d="M768 576v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45zM1523 1248q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45
+t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23z" />
+ <glyph glyph-name="plus" unicode="" horiz-adv-x="1408"
+d="M1408 800v-192q0 -40 -28 -68t-68 -28h-416v-416q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v416h-416q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h416v416q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-416h416q40 0 68 -28t28 -68z" />
+ <glyph glyph-name="minus" unicode="" horiz-adv-x="1408"
+d="M1408 800v-192q0 -40 -28 -68t-68 -28h-1216q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h1216q40 0 68 -28t28 -68z" />
+ <glyph glyph-name="asterisk" unicode="" horiz-adv-x="1664"
+d="M1482 486q46 -26 59.5 -77.5t-12.5 -97.5l-64 -110q-26 -46 -77.5 -59.5t-97.5 12.5l-266 153v-307q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v307l-266 -153q-46 -26 -97.5 -12.5t-77.5 59.5l-64 110q-26 46 -12.5 97.5t59.5 77.5l266 154l-266 154
+q-46 26 -59.5 77.5t12.5 97.5l64 110q26 46 77.5 59.5t97.5 -12.5l266 -153v307q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-307l266 153q46 26 97.5 12.5t77.5 -59.5l64 -110q26 -46 12.5 -97.5t-59.5 -77.5l-266 -154z" />
+ <glyph glyph-name="exclamation_sign" unicode=""
+d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM896 161v190q0 14 -9 23.5t-22 9.5h-192q-13 0 -23 -10t-10 -23v-190q0 -13 10 -23t23 -10h192
+q13 0 22 9.5t9 23.5zM894 505l18 621q0 12 -10 18q-10 8 -24 8h-220q-14 0 -24 -8q-10 -6 -10 -18l17 -621q0 -10 10 -17.5t24 -7.5h185q14 0 23.5 7.5t10.5 17.5z" />
+ <glyph glyph-name="gift" unicode=""
+d="M928 180v56v468v192h-320v-192v-468v-56q0 -25 18 -38.5t46 -13.5h192q28 0 46 13.5t18 38.5zM472 1024h195l-126 161q-26 31 -69 31q-40 0 -68 -28t-28 -68t28 -68t68 -28zM1160 1120q0 40 -28 68t-68 28q-43 0 -69 -31l-125 -161h194q40 0 68 28t28 68zM1536 864v-320
+q0 -14 -9 -23t-23 -9h-96v-416q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v416h-96q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h440q-93 0 -158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5q107 0 168 -77l128 -165l128 165q61 77 168 77q93 0 158.5 -65.5t65.5 -158.5
+t-65.5 -158.5t-158.5 -65.5h440q14 0 23 -9t9 -23z" />
+ <glyph glyph-name="leaf" unicode="" horiz-adv-x="1792"
+d="M1280 832q0 26 -19 45t-45 19q-172 0 -318 -49.5t-259.5 -134t-235.5 -219.5q-19 -21 -19 -45q0 -26 19 -45t45 -19q24 0 45 19q27 24 74 71t67 66q137 124 268.5 176t313.5 52q26 0 45 19t19 45zM1792 1030q0 -95 -20 -193q-46 -224 -184.5 -383t-357.5 -268
+q-214 -108 -438 -108q-148 0 -286 47q-15 5 -88 42t-96 37q-16 0 -39.5 -32t-45 -70t-52.5 -70t-60 -32q-43 0 -63.5 17.5t-45.5 59.5q-2 4 -6 11t-5.5 10t-3 9.5t-1.5 13.5q0 35 31 73.5t68 65.5t68 56t31 48q0 4 -14 38t-16 44q-9 51 -9 104q0 115 43.5 220t119 184.5
+t170.5 139t204 95.5q55 18 145 25.5t179.5 9t178.5 6t163.5 24t113.5 56.5l29.5 29.5t29.5 28t27 20t36.5 16t43.5 4.5q39 0 70.5 -46t47.5 -112t24 -124t8 -96z" />
+ <glyph glyph-name="fire" unicode="" horiz-adv-x="1408"
+d="M1408 -160v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1152 896q0 -78 -24.5 -144t-64 -112.5t-87.5 -88t-96 -77.5t-87.5 -72t-64 -81.5t-24.5 -96.5q0 -96 67 -224l-4 1l1 -1
+q-90 41 -160 83t-138.5 100t-113.5 122.5t-72.5 150.5t-27.5 184q0 78 24.5 144t64 112.5t87.5 88t96 77.5t87.5 72t64 81.5t24.5 96.5q0 94 -66 224l3 -1l-1 1q90 -41 160 -83t138.5 -100t113.5 -122.5t72.5 -150.5t27.5 -184z" />
+ <glyph glyph-name="eye_open" unicode="" horiz-adv-x="1792"
+d="M1664 576q-152 236 -381 353q61 -104 61 -225q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 121 61 225q-229 -117 -381 -353q133 -205 333.5 -326.5t434.5 -121.5t434.5 121.5t333.5 326.5zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5
+t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1792 576q0 -34 -20 -69q-140 -230 -376.5 -368.5t-499.5 -138.5t-499.5 139t-376.5 368q-20 35 -20 69t20 69q140 229 376.5 368t499.5 139t499.5 -139t376.5 -368q20 -35 20 -69z" />
+ <glyph glyph-name="eye_close" unicode="" horiz-adv-x="1792"
+d="M555 201l78 141q-87 63 -136 159t-49 203q0 121 61 225q-229 -117 -381 -353q167 -258 427 -375zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1307 1151q0 -7 -1 -9
+q-106 -189 -316 -567t-315 -566l-49 -89q-10 -16 -28 -16q-12 0 -134 70q-16 10 -16 28q0 12 44 87q-143 65 -263.5 173t-208.5 245q-20 31 -20 69t20 69q153 235 380 371t496 136q89 0 180 -17l54 97q10 16 28 16q5 0 18 -6t31 -15.5t33 -18.5t31.5 -18.5t19.5 -11.5
+q16 -10 16 -27zM1344 704q0 -139 -79 -253.5t-209 -164.5l280 502q8 -45 8 -84zM1792 576q0 -35 -20 -69q-39 -64 -109 -145q-150 -172 -347.5 -267t-419.5 -95l74 132q212 18 392.5 137t301.5 307q-115 179 -282 294l63 112q95 -64 182.5 -153t144.5 -184q20 -34 20 -69z
+" />
+ <glyph glyph-name="warning_sign" unicode="" horiz-adv-x="1792"
+d="M1024 161v190q0 14 -9.5 23.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -23.5v-190q0 -14 9.5 -23.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 23.5zM1022 535l18 459q0 12 -10 19q-13 11 -24 11h-220q-11 0 -24 -11q-10 -7 -10 -21l17 -457q0 -10 10 -16.5t24 -6.5h185
+q14 0 23.5 6.5t10.5 16.5zM1008 1469l768 -1408q35 -63 -2 -126q-17 -29 -46.5 -46t-63.5 -17h-1536q-34 0 -63.5 17t-46.5 46q-37 63 -2 126l768 1408q17 31 47 49t65 18t65 -18t47 -49z" />
+ <glyph glyph-name="plane" unicode="" horiz-adv-x="1408"
+d="M1376 1376q44 -52 12 -148t-108 -172l-161 -161l160 -696q5 -19 -12 -33l-128 -96q-7 -6 -19 -6q-4 0 -7 1q-15 3 -21 16l-279 508l-259 -259l53 -194q5 -17 -8 -31l-96 -96q-9 -9 -23 -9h-2q-15 2 -24 13l-189 252l-252 189q-11 7 -13 23q-1 13 9 25l96 97q9 9 23 9
+q6 0 8 -1l194 -53l259 259l-508 279q-14 8 -17 24q-2 16 9 27l128 128q14 13 30 8l665 -159l160 160q76 76 172 108t148 -12z" />
+ <glyph glyph-name="calendar" unicode="" horiz-adv-x="1664"
+d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z
+M512 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h288v288h-288v-288zM1280 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64
+q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47
+h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+ <glyph glyph-name="random" unicode="" horiz-adv-x="1792"
+d="M666 1055q-60 -92 -137 -273q-22 45 -37 72.5t-40.5 63.5t-51 56.5t-63 35t-81.5 14.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q250 0 410 -225zM1792 256q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192q-32 0 -85 -0.5t-81 -1t-73 1
+t-71 5t-64 10.5t-63 18.5t-58 28.5t-59 40t-55 53.5t-56 69.5q59 93 136 273q22 -45 37 -72.5t40.5 -63.5t51 -56.5t63 -35t81.5 -14.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1792 1152q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5
+v192h-256q-48 0 -87 -15t-69 -45t-51 -61.5t-45 -77.5q-32 -62 -78 -171q-29 -66 -49.5 -111t-54 -105t-64 -100t-74 -83t-90 -68.5t-106.5 -42t-128 -16.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q48 0 87 15t69 45t51 61.5t45 77.5q32 62 78 171q29 66 49.5 111
+t54 105t64 100t74 83t90 68.5t106.5 42t128 16.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
+ <glyph glyph-name="comment" unicode="" horiz-adv-x="1792"
+d="M1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22q-17 -2 -30.5 9t-17.5 29v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281
+q0 130 71 248.5t191 204.5t286 136.5t348 50.5q244 0 450 -85.5t326 -233t120 -321.5z" />
+ <glyph glyph-name="magnet" unicode=""
+d="M1536 704v-128q0 -201 -98.5 -362t-274 -251.5t-395.5 -90.5t-395.5 90.5t-274 251.5t-98.5 362v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -52 23.5 -90t53.5 -57t71 -30t64 -13t44 -2t44 2t64 13t71 30t53.5 57t23.5 90v128q0 26 19 45t45 19h384
+q26 0 45 -19t19 -45zM512 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45zM1536 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="chevron_up" unicode="" horiz-adv-x="1792"
+d="M1683 205l-166 -165q-19 -19 -45 -19t-45 19l-531 531l-531 -531q-19 -19 -45 -19t-45 19l-166 165q-19 19 -19 45.5t19 45.5l742 741q19 19 45 19t45 -19l742 -741q19 -19 19 -45.5t-19 -45.5z" />
+ <glyph glyph-name="chevron_down" unicode="" horiz-adv-x="1792"
+d="M1683 728l-742 -741q-19 -19 -45 -19t-45 19l-742 741q-19 19 -19 45.5t19 45.5l166 165q19 19 45 19t45 -19l531 -531l531 531q19 19 45 19t45 -19l166 -165q19 -19 19 -45.5t-19 -45.5z" />
+ <glyph glyph-name="retweet" unicode="" horiz-adv-x="1920"
+d="M1280 32q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -10 7 -21
+zM1920 448q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5 -8t3 -11.5t1 -11.5v-13v-11v-160v-416h192q26 0 45 -19t19 -45z
+" />
+ <glyph glyph-name="shopping_cart" unicode="" horiz-adv-x="1664"
+d="M640 0q0 -52 -38 -90t-90 -38t-90 38t-38 90t38 90t90 38t90 -38t38 -90zM1536 0q0 -52 -38 -90t-90 -38t-90 38t-38 90t38 90t90 38t90 -38t38 -90zM1664 1088v-512q0 -24 -16.5 -42.5t-40.5 -21.5l-1044 -122q13 -60 13 -70q0 -16 -24 -64h920q26 0 45 -19t19 -45
+t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 11 8 31.5t16 36t21.5 40t15.5 29.5l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t19.5 -15.5t13 -24.5t8 -26t5.5 -29.5t4.5 -26h1201q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="folder_close" unicode="" horiz-adv-x="1664"
+d="M1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
+ <glyph glyph-name="folder_open" unicode="" horiz-adv-x="1920"
+d="M1879 584q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43zM1536 928v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5
+t-0.5 12.5v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158z" />
+ <glyph glyph-name="resize_vertical" unicode="" horiz-adv-x="768"
+d="M704 1216q0 -26 -19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45z" />
+ <glyph glyph-name="resize_horizontal" unicode="" horiz-adv-x="1792"
+d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
+ <glyph glyph-name="bar_chart" unicode="" horiz-adv-x="2048"
+d="M640 640v-512h-256v512h256zM1024 1152v-1024h-256v1024h256zM2048 0v-128h-2048v1536h128v-1408h1920zM1408 896v-768h-256v768h256zM1792 1280v-1152h-256v1152h256z" />
+ <glyph glyph-name="twitter_sign" unicode=""
+d="M1280 926q-56 -25 -121 -34q68 40 93 117q-65 -38 -134 -51q-61 66 -153 66q-87 0 -148.5 -61.5t-61.5 -148.5q0 -29 5 -48q-129 7 -242 65t-192 155q-29 -50 -29 -106q0 -114 91 -175q-47 1 -100 26v-2q0 -75 50 -133.5t123 -72.5q-29 -8 -51 -8q-13 0 -39 4
+q21 -63 74.5 -104t121.5 -42q-116 -90 -261 -90q-26 0 -50 3q148 -94 322 -94q112 0 210 35.5t168 95t120.5 137t75 162t24.5 168.5q0 18 -1 27q63 45 105 109zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5
+t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="facebook_sign" unicode=""
+d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-188v595h199l30 232h-229v148q0 56 23.5 84t91.5 28l122 1v207q-63 9 -178 9q-136 0 -217.5 -80t-81.5 -226v-171h-200v-232h200v-595h-532q-119 0 -203.5 84.5t-84.5 203.5v960
+q0 119 84.5 203.5t203.5 84.5h960z" />
+ <glyph glyph-name="camera_retro" unicode="" horiz-adv-x="1792"
+d="M928 704q0 14 -9 23t-23 9q-66 0 -113 -47t-47 -113q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9t9 23zM1152 574q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM128 0h1536v128h-1536v-128zM1280 574q0 159 -112.5 271.5
+t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM256 1216h384v128h-384v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM1792 1280v-1280q0 -53 -37.5 -90.5t-90.5 -37.5h-1536q-53 0 -90.5 37.5t-37.5 90.5v1280
+q0 53 37.5 90.5t90.5 37.5h1536q53 0 90.5 -37.5t37.5 -90.5z" />
+ <glyph glyph-name="key" unicode="" horiz-adv-x="1792"
+d="M832 1024q0 80 -56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136t56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56t56 136zM1683 320q0 -17 -49 -66t-66 -49q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26
+l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189 -131 -365l355 -355l96 96q-3 3 -26 24.5t-40 38.5t-33 36.5
+t-16 28.5q0 17 49 66t66 49q13 0 23 -10q6 -6 46 -44.5t82 -79.5t86.5 -86t73 -78t28.5 -41z" />
+ <glyph glyph-name="cogs" unicode="" horiz-adv-x="1920"
+d="M896 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1664 128q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1152q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5
+t90.5 37.5t37.5 90.5zM1280 731v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -11 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90q-37 -19 -77 -31q-11 -108 -23 -155q-7 -24 -30 -24h-186q-11 0 -20 7.5t-10 17.5
+l-23 153q-34 10 -75 31l-118 -89q-7 -7 -20 -7q-11 0 -21 8q-144 133 -144 160q0 9 7 19q10 14 41 53t47 61q-23 44 -35 82l-152 24q-10 1 -17 9.5t-7 19.5v185q0 10 7 19.5t16 10.5l155 24q11 35 32 76q-34 48 -90 115q-7 11 -7 20q0 12 7 20q22 30 82 89t79 59q11 0 21 -7
+l115 -90q34 18 77 32q11 108 23 154q7 24 30 24h186q11 0 20 -7.5t10 -17.5l23 -153q34 -10 75 -31l118 89q8 7 20 7q11 0 21 -8q144 -133 144 -160q0 -8 -7 -19q-12 -16 -42 -54t-45 -60q23 -48 34 -82l152 -23q10 -2 17 -10.5t7 -19.5zM1920 198v-140q0 -16 -149 -31
+q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20
+t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31zM1920 1222v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68
+q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70
+q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31z" />
+ <glyph glyph-name="comments" unicode="" horiz-adv-x="1792"
+d="M1408 768q0 -139 -94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224
+q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257zM1792 512q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7
+q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230z" />
+ <glyph glyph-name="thumbs_up_alt" unicode=""
+d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 768q0 51 -39 89.5t-89 38.5h-352q0 58 48 159.5t48 160.5q0 98 -32 145t-128 47q-26 -26 -38 -85t-30.5 -125.5t-59.5 -109.5q-22 -23 -77 -91q-4 -5 -23 -30t-31.5 -41t-34.5 -42.5
+t-40 -44t-38.5 -35.5t-40 -27t-35.5 -9h-32v-640h32q13 0 31.5 -3t33 -6.5t38 -11t35 -11.5t35.5 -12.5t29 -10.5q211 -73 342 -73h121q192 0 192 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5q32 1 53.5 47t21.5 81zM1536 769
+q0 -89 -49 -163q9 -33 9 -69q0 -77 -38 -144q3 -21 3 -43q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5h-36h-93q-96 0 -189.5 22.5t-216.5 65.5q-116 40 -138 40h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h274q36 24 137 155q58 75 107 128
+q24 25 35.5 85.5t30.5 126.5t62 108q39 37 90 37q84 0 151 -32.5t102 -101.5t35 -186q0 -93 -48 -192h176q104 0 180 -76t76 -179z" />
+ <glyph glyph-name="thumbs_down_alt" unicode=""
+d="M256 1088q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 512q0 35 -21.5 81t-53.5 47q15 17 25 47.5t10 55.5q0 69 -53 119q18 31 18 69q0 37 -17.5 73.5t-47.5 52.5q5 30 5 56q0 85 -49 126t-136 41h-128q-131 0 -342 -73q-5 -2 -29 -10.5
+t-35.5 -12.5t-35 -11.5t-38 -11t-33 -6.5t-31.5 -3h-32v-640h32q16 0 35.5 -9t40 -27t38.5 -35.5t40 -44t34.5 -42.5t31.5 -41t23 -30q55 -68 77 -91q41 -43 59.5 -109.5t30.5 -125.5t38 -85q96 0 128 47t32 145q0 59 -48 160.5t-48 159.5h352q50 0 89 38.5t39 89.5z
+M1536 511q0 -103 -76 -179t-180 -76h-176q48 -99 48 -192q0 -118 -35 -186q-35 -69 -102 -101.5t-151 -32.5q-51 0 -90 37q-34 33 -54 82t-25.5 90.5t-17.5 84.5t-31 64q-48 50 -107 127q-101 131 -137 155h-274q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5
+h288q22 0 138 40q128 44 223 66t200 22h112q140 0 226.5 -79t85.5 -216v-5q60 -77 60 -178q0 -22 -3 -43q38 -67 38 -144q0 -36 -9 -69q49 -73 49 -163z" />
+ <glyph glyph-name="star_half" unicode="" horiz-adv-x="896"
+d="M832 1504v-1339l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41z" />
+ <glyph glyph-name="heart_empty" unicode="" horiz-adv-x="1792"
+d="M1664 940q0 81 -21.5 143t-55 98.5t-81.5 59.5t-94 31t-98 8t-112 -25.5t-110.5 -64t-86.5 -72t-60 -61.5q-18 -22 -49 -22t-49 22q-24 28 -60 61.5t-86.5 72t-110.5 64t-112 25.5t-98 -8t-94 -31t-81.5 -59.5t-55 -98.5t-21.5 -143q0 -168 187 -355l581 -560l580 559
+q188 188 188 356zM1792 940q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5
+q224 0 351 -124t127 -344z" />
+ <glyph glyph-name="signout" unicode="" horiz-adv-x="1664"
+d="M640 96q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h320q13 0 22.5 -9.5t9.5 -22.5q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-66 0 -113 -47t-47 -113v-704
+q0 -66 47 -113t113 -47h288h11h13t11.5 -1t11.5 -3t8 -5.5t7 -9t2 -13.5zM1568 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45z" />
+ <glyph glyph-name="linkedin_sign" unicode=""
+d="M237 122h231v694h-231v-694zM483 1030q-1 52 -36 86t-93 34t-94.5 -34t-36.5 -86q0 -51 35.5 -85.5t92.5 -34.5h1q59 0 95 34.5t36 85.5zM1068 122h231v398q0 154 -73 233t-193 79q-136 0 -209 -117h2v101h-231q3 -66 0 -694h231v388q0 38 7 56q15 35 45 59.5t74 24.5
+q116 0 116 -157v-371zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="pushpin" unicode="" horiz-adv-x="1152"
+d="M480 672v448q0 14 -9 23t-23 9t-23 -9t-9 -23v-448q0 -14 9 -23t23 -9t23 9t9 23zM1152 320q0 -26 -19 -45t-45 -19h-429l-51 -483q-2 -12 -10.5 -20.5t-20.5 -8.5h-1q-27 0 -32 27l-76 485h-404q-26 0 -45 19t-19 45q0 123 78.5 221.5t177.5 98.5v512q-52 0 -90 38
+t-38 90t38 90t90 38h640q52 0 90 -38t38 -90t-38 -90t-90 -38v-512q99 0 177.5 -98.5t78.5 -221.5z" />
+ <glyph glyph-name="external_link" unicode="" horiz-adv-x="1792"
+d="M1408 608v-320q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v320
+q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1792 1472v-512q0 -26 -19 -45t-45 -19t-45 19l-176 176l-652 -652q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l652 652l-176 176q-19 19 -19 45t19 45t45 19h512q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="signin" unicode=""
+d="M1184 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45zM1536 992v-704q0 -119 -84.5 -203.5t-203.5 -84.5h-320q-13 0 -22.5 9.5t-9.5 22.5
+q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q66 0 113 47t47 113v704q0 66 -47 113t-113 47h-288h-11h-13t-11.5 1t-11.5 3t-8 5.5t-7 9t-2 13.5q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="trophy" unicode="" horiz-adv-x="1664"
+d="M458 653q-74 162 -74 371h-256v-96q0 -78 94.5 -162t235.5 -113zM1536 928v96h-256q0 -209 -74 -371q141 29 235.5 113t94.5 162zM1664 1056v-128q0 -71 -41.5 -143t-112 -130t-173 -97.5t-215.5 -44.5q-42 -54 -95 -95q-38 -34 -52.5 -72.5t-14.5 -89.5q0 -54 30.5 -91
+t97.5 -37q75 0 133.5 -45.5t58.5 -114.5v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 69 58.5 114.5t133.5 45.5q67 0 97.5 37t30.5 91q0 51 -14.5 89.5t-52.5 72.5q-53 41 -95 95q-113 5 -215.5 44.5t-173 97.5t-112 130t-41.5 143v128q0 40 28 68t68 28h288v96
+q0 66 47 113t113 47h576q66 0 113 -47t47 -113v-96h288q40 0 68 -28t28 -68z" />
+ <glyph glyph-name="github_sign" unicode=""
+d="M519 336q4 6 -3 13q-9 7 -14 2q-4 -6 3 -13q9 -7 14 -2zM491 377q-5 7 -12 4q-6 -4 0 -12q7 -8 12 -5q6 4 0 13zM450 417q2 4 -5 8q-7 2 -8 -2q-3 -5 4 -8q8 -2 9 2zM471 394q2 1 1.5 4.5t-3.5 5.5q-6 7 -10 3t1 -11q6 -6 11 -2zM557 319q2 7 -9 11q-9 3 -13 -4
+q-2 -7 9 -11q9 -3 13 4zM599 316q0 8 -12 8q-10 0 -10 -8t11 -8t11 8zM638 323q-2 7 -13 5t-9 -9q2 -8 12 -6t10 10zM1280 640q0 212 -150 362t-362 150t-362 -150t-150 -362q0 -167 98 -300.5t252 -185.5q18 -3 26.5 5t8.5 20q0 52 -1 95q-6 -1 -15.5 -2.5t-35.5 -2t-48 4
+t-43.5 20t-29.5 41.5q-23 59 -57 74q-2 1 -4.5 3.5l-8 8t-7 9.5t4 7.5t19.5 3.5q6 0 15 -2t30 -15.5t33 -35.5q16 -28 37.5 -42t43.5 -14t38 3.5t30 9.5q7 47 33 69q-49 6 -86 18.5t-73 39t-55.5 76t-19.5 119.5q0 79 53 137q-24 62 5 136q19 6 54.5 -7.5t60.5 -29.5l26 -16
+q58 17 128 17t128 -17q11 7 28.5 18t55.5 26t57 9q29 -74 5 -136q53 -58 53 -137q0 -57 -14 -100.5t-35.5 -70t-53.5 -44.5t-62.5 -26t-68.5 -12q35 -31 35 -95q0 -40 -0.5 -89t-0.5 -51q0 -12 8.5 -20t26.5 -5q154 52 252 185.5t98 300.5zM1536 1120v-960
+q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="upload_alt" unicode="" horiz-adv-x="1664"
+d="M1280 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 288v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h427q21 -56 70.5 -92
+t110.5 -36h256q61 0 110.5 36t70.5 92h427q40 0 68 -28t28 -68zM1339 936q-17 -40 -59 -40h-256v-448q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v448h-256q-42 0 -59 40q-17 39 14 69l448 448q18 19 45 19t45 -19l448 -448q31 -30 14 -69z" />
+ <glyph glyph-name="lemon" unicode=""
+d="M1407 710q0 44 -7 113.5t-18 96.5q-12 30 -17 44t-9 36.5t-4 48.5q0 23 5 68.5t5 67.5q0 37 -10 55q-4 1 -13 1q-19 0 -58 -4.5t-59 -4.5q-60 0 -176 24t-175 24q-43 0 -94.5 -11.5t-85 -23.5t-89.5 -34q-137 -54 -202 -103q-96 -73 -159.5 -189.5t-88 -236t-24.5 -248.5
+q0 -40 12.5 -120t12.5 -121q0 -23 -11 -66.5t-11 -65.5t12 -36.5t34 -14.5q24 0 72.5 11t73.5 11q57 0 169.5 -15.5t169.5 -15.5q181 0 284 36q129 45 235.5 152.5t166 245.5t59.5 275zM1535 712q0 -165 -70 -327.5t-196 -288t-281 -180.5q-124 -44 -326 -44
+q-57 0 -170 14.5t-169 14.5q-24 0 -72.5 -14.5t-73.5 -14.5q-73 0 -123.5 55.5t-50.5 128.5q0 24 11 68t11 67q0 40 -12.5 120.5t-12.5 121.5q0 111 18 217.5t54.5 209.5t100.5 194t150 156q78 59 232 120q194 78 316 78q60 0 175.5 -24t173.5 -24q19 0 57 5t58 5
+q81 0 118 -50.5t37 -134.5q0 -23 -5 -68t-5 -68q0 -13 2 -25t3.5 -16.5t7.5 -20.5t8 -20q16 -40 25 -118.5t9 -136.5z" />
+ <glyph glyph-name="phone" unicode="" horiz-adv-x="1408"
+d="M1408 296q0 -27 -10 -70.5t-21 -68.5q-21 -50 -122 -106q-94 -51 -186 -51q-27 0 -53 3.5t-57.5 12.5t-47 14.5t-55.5 20.5t-49 18q-98 35 -175 83q-127 79 -264 216t-216 264q-48 77 -83 175q-3 9 -18 49t-20.5 55.5t-14.5 47t-12.5 57.5t-3.5 53q0 92 51 186
+q56 101 106 122q25 11 68.5 21t70.5 10q14 0 21 -3q18 -6 53 -76q11 -19 30 -54t35 -63.5t31 -53.5q3 -4 17.5 -25t21.5 -35.5t7 -28.5q0 -20 -28.5 -50t-62 -55t-62 -53t-28.5 -46q0 -9 5 -22.5t8.5 -20.5t14 -24t11.5 -19q76 -137 174 -235t235 -174q2 -1 19 -11.5t24 -14
+t20.5 -8.5t22.5 -5q18 0 46 28.5t53 62t55 62t50 28.5q14 0 28.5 -7t35.5 -21.5t25 -17.5q25 -15 53.5 -31t63.5 -35t54 -30q70 -35 76 -53q3 -7 3 -21z" />
+ <glyph glyph-name="check_empty" unicode="" horiz-adv-x="1408"
+d="M1120 1280h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832
+q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="bookmark_empty" unicode="" horiz-adv-x="1280"
+d="M1152 1280h-1024v-1242l423 406l89 85l89 -85l423 -406v1242zM1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289
+q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
+ <glyph glyph-name="phone_sign" unicode=""
+d="M1280 343q0 11 -2 16t-18 16.5t-40.5 25t-47.5 26.5t-45.5 25t-28.5 15q-5 3 -19 13t-25 15t-21 5q-15 0 -36.5 -20.5t-39.5 -45t-38.5 -45t-33.5 -20.5q-7 0 -16.5 3.5t-15.5 6.5t-17 9.5t-14 8.5q-99 55 -170 126.5t-127 170.5q-2 3 -8.5 14t-9.5 17t-6.5 15.5
+t-3.5 16.5q0 13 20.5 33.5t45 38.5t45 39.5t20.5 36.5q0 10 -5 21t-15 25t-13 19q-3 6 -15 28.5t-25 45.5t-26.5 47.5t-25 40.5t-16.5 18t-16 2q-48 0 -101 -22q-46 -21 -80 -94.5t-34 -130.5q0 -16 2.5 -34t5 -30.5t9 -33t10 -29.5t12.5 -33t11 -30q60 -164 216.5 -320.5
+t320.5 -216.5q6 -2 30 -11t33 -12.5t29.5 -10t33 -9t30.5 -5t34 -2.5q57 0 130.5 34t94.5 80q22 53 22 101zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z
+" />
+ <glyph glyph-name="twitter" unicode="" horiz-adv-x="1664"
+d="M1620 1128q-67 -98 -162 -167q1 -14 1 -42q0 -130 -38 -259.5t-115.5 -248.5t-184.5 -210.5t-258 -146t-323 -54.5q-271 0 -496 145q35 -4 78 -4q225 0 401 138q-105 2 -188 64.5t-114 159.5q33 -5 61 -5q43 0 85 11q-112 23 -185.5 111.5t-73.5 205.5v4q68 -38 146 -41
+q-66 44 -105 115t-39 154q0 88 44 163q121 -149 294.5 -238.5t371.5 -99.5q-8 38 -8 74q0 134 94.5 228.5t228.5 94.5q140 0 236 -102q109 21 205 78q-37 -115 -142 -178q93 10 186 50z" />
+ <glyph glyph-name="facebook" unicode="" horiz-adv-x="1024"
+d="M959 1524v-264h-157q-86 0 -116 -36t-30 -108v-189h293l-39 -296h-254v-759h-306v759h-255v296h255v218q0 186 104 288.5t277 102.5q147 0 228 -12z" />
+ <glyph glyph-name="github" unicode=""
+d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5q0 -251 -146.5 -451.5t-378.5 -277.5q-27 -5 -40 7t-13 30q0 3 0.5 76.5t0.5 134.5q0 97 -52 142q57 6 102.5 18t94 39t81 66.5t53 105t20.5 150.5q0 119 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24
+q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-85 13.5q-45 -113 -8 -204q-79 -87 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-39 -36 -49 -103q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3q-21 0 -29 -4.5
+t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -88.5t0.5 -54.5q0 -18 -13 -30t-40 -7q-232 77 -378.5 277.5t-146.5 451.5q0 209 103 385.5t279.5 279.5t385.5 103zM291 305q3 7 -7 12
+q-10 3 -13 -2q-3 -7 7 -12q9 -6 13 2zM322 271q7 5 -2 16q-10 9 -16 3q-7 -5 2 -16q10 -10 16 -3zM352 226q9 7 0 19q-8 13 -17 6q-9 -5 0 -18t17 -7zM394 184q8 8 -4 19q-12 12 -20 3q-9 -8 4 -19q12 -12 20 -3zM451 159q3 11 -13 16q-15 4 -19 -7t13 -15q15 -6 19 6z
+M514 154q0 13 -17 11q-16 0 -16 -11q0 -13 17 -11q16 0 16 11zM572 164q-2 11 -18 9q-16 -3 -14 -15t18 -8t14 14z" />
+ <glyph glyph-name="unlock" unicode="" horiz-adv-x="1664"
+d="M1664 960v-256q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-192h96q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h672v192q0 185 131.5 316.5t316.5 131.5
+t316.5 -131.5t131.5 -316.5z" />
+ <glyph glyph-name="credit_card" unicode="" horiz-adv-x="1920"
+d="M1760 1408q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600zM160 1280q-13 0 -22.5 -9.5t-9.5 -22.5v-224h1664v224q0 13 -9.5 22.5t-22.5 9.5h-1600zM1760 0q13 0 22.5 9.5t9.5 22.5v608h-1664v-608
+q0 -13 9.5 -22.5t22.5 -9.5h1600zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" />
+ <glyph glyph-name="rss" unicode="" horiz-adv-x="1408"
+d="M384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 69q2 -28 -17 -48q-18 -21 -47 -21h-135q-25 0 -43 16.5t-20 41.5q-22 229 -184.5 391.5t-391.5 184.5q-25 2 -41.5 20t-16.5 43v135q0 29 21 47q17 17 43 17h5q160 -13 306 -80.5
+t259 -181.5q114 -113 181.5 -259t80.5 -306zM1408 67q2 -27 -18 -47q-18 -20 -46 -20h-143q-26 0 -44.5 17.5t-19.5 42.5q-12 215 -101 408.5t-231.5 336t-336 231.5t-408.5 102q-25 1 -42.5 19.5t-17.5 43.5v143q0 28 20 46q18 18 44 18h3q262 -13 501.5 -120t425.5 -294
+q187 -186 294 -425.5t120 -501.5z" />
+ <glyph glyph-name="hdd" unicode=""
+d="M1040 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1296 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1408 160v320q0 13 -9.5 22.5t-22.5 9.5
+h-1216q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5zM178 640h1180l-157 482q-4 13 -16 21.5t-26 8.5h-782q-14 0 -26 -8.5t-16 -21.5zM1536 480v-320q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v320q0 25 16 75
+l197 606q17 53 63 86t101 33h782q55 0 101 -33t63 -86l197 -606q16 -50 16 -75z" />
+ <glyph glyph-name="bullhorn" unicode="" horiz-adv-x="1792"
+d="M1664 896q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5v-384q0 -52 -38 -90t-90 -38q-417 347 -812 380q-58 -19 -91 -66t-31 -100.5t40 -92.5q-20 -33 -23 -65.5t6 -58t33.5 -55t48 -50t61.5 -50.5q-29 -58 -111.5 -83t-168.5 -11.5t-132 55.5q-7 23 -29.5 87.5
+t-32 94.5t-23 89t-15 101t3.5 98.5t22 110.5h-122q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h480q435 0 896 384q52 0 90 -38t38 -90v-384zM1536 292v954q-394 -302 -768 -343v-270q377 -42 768 -341z" />
+ <glyph glyph-name="bell" unicode="" horiz-adv-x="1792"
+d="M912 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM246 128h1300q-266 300 -266 832q0 51 -24 105t-69 103t-121.5 80.5t-169.5 31.5t-169.5 -31.5t-121.5 -80.5t-69 -103t-24 -105q0 -532 -266 -832z
+M1728 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q190 -28 307 -158.5
+t117 -282.5q0 -139 19.5 -260t50 -206t74.5 -158.5t85 -119.5t91 -88z" />
+ <glyph glyph-name="certificate" unicode=""
+d="M1376 640l138 -135q30 -28 20 -70q-12 -41 -52 -51l-188 -48l53 -186q12 -41 -19 -70q-29 -31 -70 -19l-186 53l-48 -188q-10 -40 -51 -52q-12 -2 -19 -2q-31 0 -51 22l-135 138l-135 -138q-28 -30 -70 -20q-41 11 -51 52l-48 188l-186 -53q-41 -12 -70 19q-31 29 -19 70
+l53 186l-188 48q-40 10 -52 51q-10 42 20 70l138 135l-138 135q-30 28 -20 70q12 41 52 51l188 48l-53 186q-12 41 19 70q29 31 70 19l186 -53l48 188q10 41 51 51q41 12 70 -19l135 -139l135 139q29 30 70 19q41 -10 51 -51l48 -188l186 53q41 12 70 -19q31 -29 19 -70
+l-53 -186l188 -48q40 -10 52 -51q10 -42 -20 -70z" />
+ <glyph glyph-name="hand_right" unicode="" horiz-adv-x="1792"
+d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 768q0 51 -39 89.5t-89 38.5h-576q0 20 15 48.5t33 55t33 68t15 84.5q0 67 -44.5 97.5t-115.5 30.5q-24 0 -90 -139q-24 -44 -37 -65q-40 -64 -112 -145q-71 -81 -101 -106
+q-69 -57 -140 -57h-32v-640h32q72 0 167 -32t193.5 -64t179.5 -32q189 0 189 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5h331q52 0 90 38t38 90zM1792 769q0 -105 -75.5 -181t-180.5 -76h-169q-4 -62 -37 -119q3 -21 3 -43
+q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5q-133 0 -322 69q-164 59 -223 59h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h288q10 0 21.5 4.5t23.5 14t22.5 18t24 22.5t20.5 21.5t19 21.5t14 17q65 74 100 129q13 21 33 62t37 72t40.5 63t55 49.5
+t69.5 17.5q125 0 206.5 -67t81.5 -189q0 -68 -22 -128h374q104 0 180 -76t76 -179z" />
+ <glyph glyph-name="hand_left" unicode="" horiz-adv-x="1792"
+d="M1376 128h32v640h-32q-35 0 -67.5 12t-62.5 37t-50 46t-49 54q-8 9 -12 14q-72 81 -112 145q-14 22 -38 68q-1 3 -10.5 22.5t-18.5 36t-20 35.5t-21.5 30.5t-18.5 11.5q-71 0 -115.5 -30.5t-44.5 -97.5q0 -43 15 -84.5t33 -68t33 -55t15 -48.5h-576q-50 0 -89 -38.5
+t-39 -89.5q0 -52 38 -90t90 -38h331q-15 -17 -25 -47.5t-10 -55.5q0 -69 53 -119q-18 -32 -18 -69t17.5 -73.5t47.5 -52.5q-4 -24 -4 -56q0 -85 48.5 -126t135.5 -41q84 0 183 32t194 64t167 32zM1664 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45z
+M1792 768v-640q0 -53 -37.5 -90.5t-90.5 -37.5h-288q-59 0 -223 -59q-190 -69 -317 -69q-142 0 -230 77.5t-87 217.5l1 5q-61 76 -61 178q0 22 3 43q-33 57 -37 119h-169q-105 0 -180.5 76t-75.5 181q0 103 76 179t180 76h374q-22 60 -22 128q0 122 81.5 189t206.5 67
+q38 0 69.5 -17.5t55 -49.5t40.5 -63t37 -72t33 -62q35 -55 100 -129q2 -3 14 -17t19 -21.5t20.5 -21.5t24 -22.5t22.5 -18t23.5 -14t21.5 -4.5h288q53 0 90.5 -37.5t37.5 -90.5z" />
+ <glyph glyph-name="hand_up" unicode=""
+d="M1280 -64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 700q0 189 -167 189q-26 0 -56 -5q-16 30 -52.5 47.5t-73.5 17.5t-69 -18q-50 53 -119 53q-25 0 -55.5 -10t-47.5 -25v331q0 52 -38 90t-90 38q-51 0 -89.5 -39t-38.5 -89v-576
+q-20 0 -48.5 15t-55 33t-68 33t-84.5 15q-67 0 -97.5 -44.5t-30.5 -115.5q0 -24 139 -90q44 -24 65 -37q64 -40 145 -112q81 -71 106 -101q57 -69 57 -140v-32h640v32q0 72 32 167t64 193.5t32 179.5zM1536 705q0 -133 -69 -322q-59 -164 -59 -223v-288q0 -53 -37.5 -90.5
+t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5v288q0 10 -4.5 21.5t-14 23.5t-18 22.5t-22.5 24t-21.5 20.5t-21.5 19t-17 14q-74 65 -129 100q-21 13 -62 33t-72 37t-63 40.5t-49.5 55t-17.5 69.5q0 125 67 206.5t189 81.5q68 0 128 -22v374q0 104 76 180t179 76
+q105 0 181 -75.5t76 -180.5v-169q62 -4 119 -37q21 3 43 3q101 0 178 -60q139 1 219.5 -85t80.5 -227z" />
+ <glyph glyph-name="hand_down" unicode=""
+d="M1408 576q0 84 -32 183t-64 194t-32 167v32h-640v-32q0 -35 -12 -67.5t-37 -62.5t-46 -50t-54 -49q-9 -8 -14 -12q-81 -72 -145 -112q-22 -14 -68 -38q-3 -1 -22.5 -10.5t-36 -18.5t-35.5 -20t-30.5 -21.5t-11.5 -18.5q0 -71 30.5 -115.5t97.5 -44.5q43 0 84.5 15t68 33
+t55 33t48.5 15v-576q0 -50 38.5 -89t89.5 -39q52 0 90 38t38 90v331q46 -35 103 -35q69 0 119 53q32 -18 69 -18t73.5 17.5t52.5 47.5q24 -4 56 -4q85 0 126 48.5t41 135.5zM1280 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 580
+q0 -142 -77.5 -230t-217.5 -87l-5 1q-76 -61 -178 -61q-22 0 -43 3q-54 -30 -119 -37v-169q0 -105 -76 -180.5t-181 -75.5q-103 0 -179 76t-76 180v374q-54 -22 -128 -22q-121 0 -188.5 81.5t-67.5 206.5q0 38 17.5 69.5t49.5 55t63 40.5t72 37t62 33q55 35 129 100
+q3 2 17 14t21.5 19t21.5 20.5t22.5 24t18 22.5t14 23.5t4.5 21.5v288q0 53 37.5 90.5t90.5 37.5h640q53 0 90.5 -37.5t37.5 -90.5v-288q0 -59 59 -223q69 -190 69 -317z" />
+ <glyph glyph-name="circle_arrow_left" unicode=""
+d="M1280 576v128q0 26 -19 45t-45 19h-502l189 189q19 19 19 45t-19 45l-91 91q-18 18 -45 18t-45 -18l-362 -362l-91 -91q-18 -18 -18 -45t18 -45l91 -91l362 -362q18 -18 45 -18t45 18l91 91q18 18 18 45t-18 45l-189 189h502q26 0 45 19t19 45zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="circle_arrow_right" unicode=""
+d="M1285 640q0 27 -18 45l-91 91l-362 362q-18 18 -45 18t-45 -18l-91 -91q-18 -18 -18 -45t18 -45l189 -189h-502q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h502l-189 -189q-19 -19 -19 -45t19 -45l91 -91q18 -18 45 -18t45 18l362 362l91 91q18 18 18 45zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="circle_arrow_up" unicode=""
+d="M1284 641q0 27 -18 45l-362 362l-91 91q-18 18 -45 18t-45 -18l-91 -91l-362 -362q-18 -18 -18 -45t18 -45l91 -91q18 -18 45 -18t45 18l189 189v-502q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v502l189 -189q19 -19 45 -19t45 19l91 91q18 18 18 45zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="circle_arrow_down" unicode=""
+d="M1284 639q0 27 -18 45l-91 91q-18 18 -45 18t-45 -18l-189 -189v502q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-502l-189 189q-19 19 -45 19t-45 -19l-91 -91q-18 -18 -18 -45t18 -45l362 -362l91 -91q18 -18 45 -18t45 18l91 91l362 362q18 18 18 45zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="globe" unicode=""
+d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1042 887q-2 -1 -9.5 -9.5t-13.5 -9.5q2 0 4.5 5t5 11t3.5 7q6 7 22 15q14 6 52 12q34 8 51 -11
+q-2 2 9.5 13t14.5 12q3 2 15 4.5t15 7.5l2 22q-12 -1 -17.5 7t-6.5 21q0 -2 -6 -8q0 7 -4.5 8t-11.5 -1t-9 -1q-10 3 -15 7.5t-8 16.5t-4 15q-2 5 -9.5 11t-9.5 10q-1 2 -2.5 5.5t-3 6.5t-4 5.5t-5.5 2.5t-7 -5t-7.5 -10t-4.5 -5q-3 2 -6 1.5t-4.5 -1t-4.5 -3t-5 -3.5
+q-3 -2 -8.5 -3t-8.5 -2q15 5 -1 11q-10 4 -16 3q9 4 7.5 12t-8.5 14h5q-1 4 -8.5 8.5t-17.5 8.5t-13 6q-8 5 -34 9.5t-33 0.5q-5 -6 -4.5 -10.5t4 -14t3.5 -12.5q1 -6 -5.5 -13t-6.5 -12q0 -7 14 -15.5t10 -21.5q-3 -8 -16 -16t-16 -12q-5 -8 -1.5 -18.5t10.5 -16.5
+q2 -2 1.5 -4t-3.5 -4.5t-5.5 -4t-6.5 -3.5l-3 -2q-11 -5 -20.5 6t-13.5 26q-7 25 -16 30q-23 8 -29 -1q-5 13 -41 26q-25 9 -58 4q6 1 0 15q-7 15 -19 12q3 6 4 17.5t1 13.5q3 13 12 23q1 1 7 8.5t9.5 13.5t0.5 6q35 -4 50 11q5 5 11.5 17t10.5 17q9 6 14 5.5t14.5 -5.5
+t14.5 -5q14 -1 15.5 11t-7.5 20q12 -1 3 17q-4 7 -8 9q-12 4 -27 -5q-8 -4 2 -8q-1 1 -9.5 -10.5t-16.5 -17.5t-16 5q-1 1 -5.5 13.5t-9.5 13.5q-8 0 -16 -15q3 8 -11 15t-24 8q19 12 -8 27q-7 4 -20.5 5t-19.5 -4q-5 -7 -5.5 -11.5t5 -8t10.5 -5.5t11.5 -4t8.5 -3
+q14 -10 8 -14q-2 -1 -8.5 -3.5t-11.5 -4.5t-6 -4q-3 -4 0 -14t-2 -14q-5 5 -9 17.5t-7 16.5q7 -9 -25 -6l-10 1q-4 0 -16 -2t-20.5 -1t-13.5 8q-4 8 0 20q1 4 4 2q-4 3 -11 9.5t-10 8.5q-46 -15 -94 -41q6 -1 12 1q5 2 13 6.5t10 5.5q34 14 42 7l5 5q14 -16 20 -25
+q-7 4 -30 1q-20 -6 -22 -12q7 -12 5 -18q-4 3 -11.5 10t-14.5 11t-15 5q-16 0 -22 -1q-146 -80 -235 -222q7 -7 12 -8q4 -1 5 -9t2.5 -11t11.5 3q9 -8 3 -19q1 1 44 -27q19 -17 21 -21q3 -11 -10 -18q-1 2 -9 9t-9 4q-3 -5 0.5 -18.5t10.5 -12.5q-7 0 -9.5 -16t-2.5 -35.5
+t-1 -23.5l2 -1q-3 -12 5.5 -34.5t21.5 -19.5q-13 -3 20 -43q6 -8 8 -9q3 -2 12 -7.5t15 -10t10 -10.5q4 -5 10 -22.5t14 -23.5q-2 -6 9.5 -20t10.5 -23q-1 0 -2.5 -1t-2.5 -1q3 -7 15.5 -14t15.5 -13q1 -3 2 -10t3 -11t8 -2q2 20 -24 62q-15 25 -17 29q-3 5 -5.5 15.5
+t-4.5 14.5q2 0 6 -1.5t8.5 -3.5t7.5 -4t2 -3q-3 -7 2 -17.5t12 -18.5t17 -19t12 -13q6 -6 14 -19.5t0 -13.5q9 0 20 -10.5t17 -19.5q5 -8 8 -26t5 -24q2 -7 8.5 -13.5t12.5 -9.5l16 -8t13 -7q5 -2 18.5 -10.5t21.5 -11.5q10 -4 16 -4t14.5 2.5t13.5 3.5q15 2 29 -15t21 -21
+q36 -19 55 -11q-2 -1 0.5 -7.5t8 -15.5t9 -14.5t5.5 -8.5q5 -6 18 -15t18 -15q6 4 7 9q-3 -8 7 -20t18 -10q14 3 14 32q-31 -15 -49 18q0 1 -2.5 5.5t-4 8.5t-2.5 8.5t0 7.5t5 3q9 0 10 3.5t-2 12.5t-4 13q-1 8 -11 20t-12 15q-5 -9 -16 -8t-16 9q0 -1 -1.5 -5.5t-1.5 -6.5
+q-13 0 -15 1q1 3 2.5 17.5t3.5 22.5q1 4 5.5 12t7.5 14.5t4 12.5t-4.5 9.5t-17.5 2.5q-19 -1 -26 -20q-1 -3 -3 -10.5t-5 -11.5t-9 -7q-7 -3 -24 -2t-24 5q-13 8 -22.5 29t-9.5 37q0 10 2.5 26.5t3 25t-5.5 24.5q3 2 9 9.5t10 10.5q2 1 4.5 1.5t4.5 0t4 1.5t3 6q-1 1 -4 3
+q-3 3 -4 3q7 -3 28.5 1.5t27.5 -1.5q15 -11 22 2q0 1 -2.5 9.5t-0.5 13.5q5 -27 29 -9q3 -3 15.5 -5t17.5 -5q3 -2 7 -5.5t5.5 -4.5t5 0.5t8.5 6.5q10 -14 12 -24q11 -40 19 -44q7 -3 11 -2t4.5 9.5t0 14t-1.5 12.5l-1 8v18l-1 8q-15 3 -18.5 12t1.5 18.5t15 18.5q1 1 8 3.5
+t15.5 6.5t12.5 8q21 19 15 35q7 0 11 9q-1 0 -5 3t-7.5 5t-4.5 2q9 5 2 16q5 3 7.5 11t7.5 10q9 -12 21 -2q8 8 1 16q5 7 20.5 10.5t18.5 9.5q7 -2 8 2t1 12t3 12q4 5 15 9t13 5l17 11q3 4 0 4q18 -2 31 11q10 11 -6 20q3 6 -3 9.5t-15 5.5q3 1 11.5 0.5t10.5 1.5
+q15 10 -7 16q-17 5 -43 -12zM879 10q206 36 351 189q-3 3 -12.5 4.5t-12.5 3.5q-18 7 -24 8q1 7 -2.5 13t-8 9t-12.5 8t-11 7q-2 2 -7 6t-7 5.5t-7.5 4.5t-8.5 2t-10 -1l-3 -1q-3 -1 -5.5 -2.5t-5.5 -3t-4 -3t0 -2.5q-21 17 -36 22q-5 1 -11 5.5t-10.5 7t-10 1.5t-11.5 -7
+q-5 -5 -6 -15t-2 -13q-7 5 0 17.5t2 18.5q-3 6 -10.5 4.5t-12 -4.5t-11.5 -8.5t-9 -6.5t-8.5 -5.5t-8.5 -7.5q-3 -4 -6 -12t-5 -11q-2 4 -11.5 6.5t-9.5 5.5q2 -10 4 -35t5 -38q7 -31 -12 -48q-27 -25 -29 -40q-4 -22 12 -26q0 -7 -8 -20.5t-7 -21.5q0 -6 2 -16z" />
+ <glyph glyph-name="wrench" unicode="" horiz-adv-x="1664"
+d="M384 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1028 484l-682 -682q-37 -37 -90 -37q-52 0 -91 37l-106 108q-38 36 -38 90q0 53 38 91l681 681q39 -98 114.5 -173.5t173.5 -114.5zM1662 919q0 -39 -23 -106q-47 -134 -164.5 -217.5
+t-258.5 -83.5q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q58 0 121.5 -16.5t107.5 -46.5q16 -11 16 -28t-16 -28l-293 -169v-224l193 -107q5 3 79 48.5t135.5 81t70.5 35.5q15 0 23.5 -10t8.5 -25z" />
+ <glyph glyph-name="tasks" unicode="" horiz-adv-x="1792"
+d="M1024 128h640v128h-640v-128zM640 640h1024v128h-1024v-128zM1280 1152h384v128h-384v-128zM1792 320v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 832v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19
+t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="filter" unicode="" horiz-adv-x="1408"
+d="M1403 1241q17 -41 -14 -70l-493 -493v-742q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-256 256q-19 19 -19 45v486l-493 493q-31 29 -14 70q17 39 59 39h1280q42 0 59 -39z" />
+ <glyph glyph-name="briefcase" unicode="" horiz-adv-x="1792"
+d="M640 1280h512v128h-512v-128zM1792 640v-480q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v480h672v-160q0 -26 19 -45t45 -19h320q26 0 45 19t19 45v160h672zM1024 640v-128h-256v128h256zM1792 1120v-384h-1792v384q0 66 47 113t113 47h352v160q0 40 28 68
+t68 28h576q40 0 68 -28t28 -68v-160h352q66 0 113 -47t47 -113z" />
+ <glyph glyph-name="fullscreen" unicode=""
+d="M1283 995l-355 -355l355 -355l144 144q29 31 70 14q39 -17 39 -59v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l144 144l-355 355l-355 -355l144 -144q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l144 -144
+l355 355l-355 355l-144 -144q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v448q0 26 19 45t45 19h448q42 0 59 -40q17 -39 -14 -69l-144 -144l355 -355l355 355l-144 144q-31 30 -14 69q17 40 59 40h448q26 0 45 -19t19 -45v-448q0 -42 -39 -59q-13 -5 -25 -5q-26 0 -45 19z
+" />
+ <glyph glyph-name="group" unicode="" horiz-adv-x="1920"
+d="M593 640q-162 -5 -265 -128h-134q-82 0 -138 40.5t-56 118.5q0 353 124 353q6 0 43.5 -21t97.5 -42.5t119 -21.5q67 0 133 23q-5 -37 -5 -66q0 -139 81 -256zM1664 3q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5
+t43 97.5t62 81t85.5 53.5t111.5 20q10 0 43 -21.5t73 -48t107 -48t135 -21.5t135 21.5t107 48t73 48t43 21.5q61 0 111.5 -20t85.5 -53.5t62 -81t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM640 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75
+t75 -181zM1344 896q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5zM1920 671q0 -78 -56 -118.5t-138 -40.5h-134q-103 123 -265 128q81 117 81 256q0 29 -5 66q66 -23 133 -23q59 0 119 21.5t97.5 42.5
+t43.5 21q124 0 124 -353zM1792 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181z" />
+ <glyph glyph-name="link" unicode="" horiz-adv-x="1664"
+d="M1456 320q0 40 -28 68l-208 208q-28 28 -68 28q-42 0 -72 -32q3 -3 19 -18.5t21.5 -21.5t15 -19t13 -25.5t3.5 -27.5q0 -40 -28 -68t-68 -28q-15 0 -27.5 3.5t-25.5 13t-19 15t-21.5 21.5t-18.5 19q-33 -31 -33 -73q0 -40 28 -68l206 -207q27 -27 68 -27q40 0 68 26
+l147 146q28 28 28 67zM753 1025q0 40 -28 68l-206 207q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l208 -208q27 -27 68 -27q42 0 72 31q-3 3 -19 18.5t-21.5 21.5t-15 19t-13 25.5t-3.5 27.5q0 40 28 68t68 28q15 0 27.5 -3.5t25.5 -13t19 -15
+t21.5 -21.5t18.5 -19q33 31 33 73zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-206 207q-83 83 -83 203q0 123 88 209l-88 88q-86 -88 -208 -88q-120 0 -204 84l-208 208q-84 84 -84 204t85 203l147 146q83 83 203 83q121 0 204 -85l206 -207
+q83 -83 83 -203q0 -123 -88 -209l88 -88q86 88 208 88q120 0 204 -84l208 -208q84 -84 84 -204z" />
+ <glyph glyph-name="cloud" unicode="" horiz-adv-x="1920"
+d="M1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088q-185 0 -316.5 131.5t-131.5 316.5q0 132 71 241.5t187 163.5q-2 28 -2 43q0 212 150 362t362 150q158 0 286.5 -88t187.5 -230q70 62 166 62q106 0 181 -75t75 -181q0 -75 -41 -138q129 -30 213 -134.5t84 -239.5z
+" />
+ <glyph glyph-name="beaker" unicode="" horiz-adv-x="1664"
+d="M1527 88q56 -89 21.5 -152.5t-140.5 -63.5h-1152q-106 0 -140.5 63.5t21.5 152.5l503 793v399h-64q-26 0 -45 19t-19 45t19 45t45 19h512q26 0 45 -19t19 -45t-19 -45t-45 -19h-64v-399zM748 813l-272 -429h712l-272 429l-20 31v37v399h-128v-399v-37z" />
+ <glyph glyph-name="cut" unicode="" horiz-adv-x="1792"
+d="M960 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1260 576l507 -398q28 -20 25 -56q-5 -35 -35 -51l-128 -64q-13 -7 -29 -7q-17 0 -31 8l-690 387l-110 -66q-8 -4 -12 -5q14 -49 10 -97q-7 -77 -56 -147.5t-132 -123.5q-132 -84 -277 -84
+q-136 0 -222 78q-90 84 -79 207q7 76 56 147t131 124q132 84 278 84q83 0 151 -31q9 13 22 22l122 73l-122 73q-13 9 -22 22q-68 -31 -151 -31q-146 0 -278 84q-82 53 -131 124t-56 147q-5 59 15.5 113t63.5 93q85 79 222 79q145 0 277 -84q83 -52 132 -123t56 -148
+q4 -48 -10 -97q4 -1 12 -5l110 -66l690 387q14 8 31 8q16 0 29 -7l128 -64q30 -16 35 -51q3 -36 -25 -56zM579 836q46 42 21 108t-106 117q-92 59 -192 59q-74 0 -113 -36q-46 -42 -21 -108t106 -117q92 -59 192 -59q74 0 113 36zM494 91q81 51 106 117t-21 108
+q-39 36 -113 36q-100 0 -192 -59q-81 -51 -106 -117t21 -108q39 -36 113 -36q100 0 192 59zM672 704l96 -58v11q0 36 33 56l14 8l-79 47l-26 -26q-3 -3 -10 -11t-12 -12q-2 -2 -4 -3.5t-3 -2.5zM896 480l96 -32l736 576l-128 64l-768 -431v-113l-160 -96l9 -8q2 -2 7 -6
+q4 -4 11 -12t11 -12l26 -26zM1600 64l128 64l-520 408l-177 -138q-2 -3 -13 -7z" />
+ <glyph glyph-name="copy" unicode="" horiz-adv-x="1792"
+d="M1696 1152q40 0 68 -28t28 -68v-1216q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v288h-544q-40 0 -68 28t-28 68v672q0 40 20 88t48 76l408 408q28 28 76 48t88 20h416q40 0 68 -28t28 -68v-328q68 40 128 40h416zM1152 939l-299 -299h299v299zM512 1323l-299 -299
+h299v299zM708 676l316 316v416h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h512v256q0 40 20 88t48 76zM1664 -128v1152h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h896z" />
+ <glyph glyph-name="paper_clip" unicode="" horiz-adv-x="1408"
+d="M1404 151q0 -117 -79 -196t-196 -79q-135 0 -235 100l-777 776q-113 115 -113 271q0 159 110 270t269 111q158 0 273 -113l605 -606q10 -10 10 -22q0 -16 -30.5 -46.5t-46.5 -30.5q-13 0 -23 10l-606 607q-79 77 -181 77q-106 0 -179 -75t-73 -181q0 -105 76 -181
+l776 -777q63 -63 145 -63q64 0 106 42t42 106q0 82 -63 145l-581 581q-26 24 -60 24q-29 0 -48 -19t-19 -48q0 -32 25 -59l410 -410q10 -10 10 -22q0 -16 -31 -47t-47 -31q-12 0 -22 10l-410 410q-63 61 -63 149q0 82 57 139t139 57q88 0 149 -63l581 -581q100 -98 100 -235
+z" />
+ <glyph glyph-name="save" unicode=""
+d="M384 0h768v384h-768v-384zM1280 0h128v896q0 14 -10 38.5t-20 34.5l-281 281q-10 10 -34 20t-39 10v-416q0 -40 -28 -68t-68 -28h-576q-40 0 -68 28t-28 68v416h-128v-1280h128v416q0 40 28 68t68 28h832q40 0 68 -28t28 -68v-416zM896 928v320q0 13 -9.5 22.5t-22.5 9.5
+h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1536 896v-928q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h928q40 0 88 -20t76 -48l280 -280q28 -28 48 -76t20 -88z" />
+ <glyph glyph-name="sign_blank" unicode=""
+d="M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="reorder" unicode=""
+d="M1536 192v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 704v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 1216v-128q0 -26 -19 -45
+t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="ul" unicode="" horiz-adv-x="1792"
+d="M384 128q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 640q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5
+t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1152q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z
+M1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
+ <glyph glyph-name="ol" unicode="" horiz-adv-x="1792"
+d="M381 -84q0 -80 -54.5 -126t-135.5 -46q-106 0 -172 66l57 88q49 -45 106 -45q29 0 50.5 14.5t21.5 42.5q0 64 -105 56l-26 56q8 10 32.5 43.5t42.5 54t37 38.5v1q-16 0 -48.5 -1t-48.5 -1v-53h-106v152h333v-88l-95 -115q51 -12 81 -49t30 -88zM383 543v-159h-362
+q-6 36 -6 54q0 51 23.5 93t56.5 68t66 47.5t56.5 43.5t23.5 45q0 25 -14.5 38.5t-39.5 13.5q-46 0 -81 -58l-85 59q24 51 71.5 79.5t105.5 28.5q73 0 123 -41.5t50 -112.5q0 -50 -34 -91.5t-75 -64.5t-75.5 -50.5t-35.5 -52.5h127v60h105zM1792 224v-192q0 -13 -9.5 -22.5
+t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1123v-99h-335v99h107q0 41 0.5 121.5t0.5 121.5v12h-2q-8 -17 -50 -54l-71 76l136 127h106v-404h108zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216
+q-13 0 -22.5 9.5t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
+ <glyph glyph-name="strikethrough" unicode="" horiz-adv-x="1792"
+d="M1760 640q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h1728zM483 704q-28 35 -51 80q-48 98 -48 188q0 181 134 309q133 127 393 127q50 0 167 -19q66 -12 177 -48q10 -38 21 -118q14 -123 14 -183q0 -18 -5 -45l-12 -3l-84 6
+l-14 2q-50 149 -103 205q-88 91 -210 91q-114 0 -182 -59q-67 -58 -67 -146q0 -73 66 -140t279 -129q69 -20 173 -66q58 -28 95 -52h-743zM990 448h411q7 -39 7 -92q0 -111 -41 -212q-23 -56 -71 -104q-37 -35 -109 -81q-80 -48 -153 -66q-80 -21 -203 -21q-114 0 -195 23
+l-140 40q-57 16 -72 28q-8 8 -8 22v13q0 108 -2 156q-1 30 0 68l2 37v44l102 2q15 -34 30 -71t22.5 -56t12.5 -27q35 -57 80 -94q43 -36 105 -57q59 -22 132 -22q64 0 139 27q77 26 122 86q47 61 47 129q0 84 -81 157q-34 29 -137 71z" />
+ <glyph glyph-name="underline" unicode=""
+d="M48 1313q-37 2 -45 4l-3 88q13 1 40 1q60 0 112 -4q132 -7 166 -7q86 0 168 3q116 4 146 5q56 0 86 2l-1 -14l2 -64v-9q-60 -9 -124 -9q-60 0 -79 -25q-13 -14 -13 -132q0 -13 0.5 -32.5t0.5 -25.5l1 -229l14 -280q6 -124 51 -202q35 -59 96 -92q88 -47 177 -47
+q104 0 191 28q56 18 99 51q48 36 65 64q36 56 53 114q21 73 21 229q0 79 -3.5 128t-11 122.5t-13.5 159.5l-4 59q-5 67 -24 88q-34 35 -77 34l-100 -2l-14 3l2 86h84l205 -10q76 -3 196 10l18 -2q6 -38 6 -51q0 -7 -4 -31q-45 -12 -84 -13q-73 -11 -79 -17q-15 -15 -15 -41
+q0 -7 1.5 -27t1.5 -31q8 -19 22 -396q6 -195 -15 -304q-15 -76 -41 -122q-38 -65 -112 -123q-75 -57 -182 -89q-109 -33 -255 -33q-167 0 -284 46q-119 47 -179 122q-61 76 -83 195q-16 80 -16 237v333q0 188 -17 213q-25 36 -147 39zM1536 -96v64q0 14 -9 23t-23 9h-1472
+q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h1472q14 0 23 9t9 23z" />
+ <glyph glyph-name="table" unicode="" horiz-adv-x="1664"
+d="M512 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23
+v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 160v192
+q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192
+q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1664 1248v-1088q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1344q66 0 113 -47t47 -113
+z" />
+ <glyph glyph-name="magic" unicode="" horiz-adv-x="1664"
+d="M1190 955l293 293l-107 107l-293 -293zM1637 1248q0 -27 -18 -45l-1286 -1286q-18 -18 -45 -18t-45 18l-198 198q-18 18 -18 45t18 45l1286 1286q18 18 45 18t45 -18l198 -198q18 -18 18 -45zM286 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM636 1276
+l196 -60l-196 -60l-60 -196l-60 196l-196 60l196 60l60 196zM1566 798l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM926 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98z" />
+ <glyph glyph-name="truck" unicode="" horiz-adv-x="1792"
+d="M640 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM1536 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1792 1216v-1024q0 -15 -4 -26.5t-13.5 -18.5
+t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5 18.5t-4 26.5q0 26 19 45t45 19v320q0 8 -0.5 35t0 38
+t2.5 34.5t6.5 37t14 30.5t22.5 30l198 198q19 19 50.5 32t58.5 13h160v192q0 26 19 45t45 19h1024q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="pinterest" unicode=""
+d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134
+q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5q8 35 26.5 93.5t30 103t11.5 75.5q0 50 -27 83t-77 33
+q-62 0 -105 -57t-43 -142q0 -73 25 -122l-99 -418q-17 -70 -13 -177q-206 91 -333 281t-127 423q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="pinterest_sign" unicode=""
+d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5q-104 0 -194.5 -28.5t-153 -76.5
+t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118q-60 0 -97 43.5t-23 103.5q8 34 26.5 92.5
+t29.5 102t11 74.5q0 49 -26.5 81.5t-75.5 32.5q-61 0 -103.5 -56.5t-42.5 -139.5q0 -72 24 -121l-98 -414q-24 -100 -7 -254h-183q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" />
+ <glyph glyph-name="google_plus_sign" unicode=""
+d="M917 631q0 26 -6 64h-362v-132h217q-3 -24 -16.5 -50t-37.5 -53t-66.5 -44.5t-96.5 -17.5q-99 0 -169 71t-70 171t70 171t169 71q92 0 153 -59l104 101q-108 100 -257 100q-160 0 -272 -112.5t-112 -271.5t112 -271.5t272 -112.5q165 0 266.5 105t101.5 270zM1262 585
+h109v110h-109v110h-110v-110h-110v-110h110v-110h110v110zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="google_plus" unicode="" horiz-adv-x="2304"
+d="M1437 623q0 -208 -87 -370.5t-248 -254t-369 -91.5q-149 0 -285 58t-234 156t-156 234t-58 285t58 285t156 234t234 156t285 58q286 0 491 -192l-199 -191q-117 113 -292 113q-123 0 -227.5 -62t-165.5 -168.5t-61 -232.5t61 -232.5t165.5 -168.5t227.5 -62
+q83 0 152.5 23t114.5 57.5t78.5 78.5t49 83t21.5 74h-416v252h692q12 -63 12 -122zM2304 745v-210h-209v-209h-210v209h-209v210h209v209h210v-209h209z" />
+ <glyph glyph-name="money" unicode="" horiz-adv-x="1920"
+d="M768 384h384v96h-128v448h-114l-148 -137l77 -80q42 37 55 57h2v-288h-128v-96zM1280 640q0 -70 -21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142t21 142t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142zM1792 384
+v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512q106 0 181 -75t75 -181h1152q0 106 75 181t181 75zM1920 1216v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45v1152q0 26 19 45t45 19h1792q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="caret_down" unicode="" horiz-adv-x="1024"
+d="M1024 832q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="caret_up" unicode="" horiz-adv-x="1024"
+d="M1024 320q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+ <glyph glyph-name="caret_left" unicode="" horiz-adv-x="640"
+d="M640 1088v-896q0 -26 -19 -45t-45 -19t-45 19l-448 448q-19 19 -19 45t19 45l448 448q19 19 45 19t45 -19t19 -45z" />
+ <glyph glyph-name="caret_right" unicode="" horiz-adv-x="640"
+d="M576 640q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19t-19 45v896q0 26 19 45t45 19t45 -19l448 -448q19 -19 19 -45z" />
+ <glyph glyph-name="columns" unicode="" horiz-adv-x="1664"
+d="M160 0h608v1152h-640v-1120q0 -13 9.5 -22.5t22.5 -9.5zM1536 32v1120h-640v-1152h608q13 0 22.5 9.5t9.5 22.5zM1664 1248v-1216q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1344q66 0 113 -47t47 -113z" />
+ <glyph glyph-name="sort" unicode="" horiz-adv-x="1024"
+d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45zM1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+ <glyph glyph-name="sort_down" unicode="" horiz-adv-x="1024"
+d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="sort_up" unicode="" horiz-adv-x="1024"
+d="M1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+ <glyph glyph-name="envelope_alt" unicode="" horiz-adv-x="1792"
+d="M1792 826v-794q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v794q44 -49 101 -87q362 -246 497 -345q57 -42 92.5 -65.5t94.5 -48t110 -24.5h1h1q51 0 110 24.5t94.5 48t92.5 65.5q170 123 498 345q57 39 100 87zM1792 1120q0 -79 -49 -151t-122 -123
+q-376 -261 -468 -325q-10 -7 -42.5 -30.5t-54 -38t-52 -32.5t-57.5 -27t-50 -9h-1h-1q-23 0 -50 9t-57.5 27t-52 32.5t-54 38t-42.5 30.5q-91 64 -262 182.5t-205 142.5q-62 42 -117 115.5t-55 136.5q0 78 41.5 130t118.5 52h1472q65 0 112.5 -47t47.5 -113z" />
+ <glyph glyph-name="linkedin" unicode=""
+d="M349 911v-991h-330v991h330zM370 1217q1 -73 -50.5 -122t-135.5 -49h-2q-82 0 -132 49t-50 122q0 74 51.5 122.5t134.5 48.5t133 -48.5t51 -122.5zM1536 488v-568h-329v530q0 105 -40.5 164.5t-126.5 59.5q-63 0 -105.5 -34.5t-63.5 -85.5q-11 -30 -11 -81v-553h-329
+q2 399 2 647t-1 296l-1 48h329v-144h-2q20 32 41 56t56.5 52t87 43.5t114.5 15.5q171 0 275 -113.5t104 -332.5z" />
+ <glyph glyph-name="undo" unicode=""
+d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5
+t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298z" />
+ <glyph glyph-name="legal" unicode="" horiz-adv-x="1792"
+d="M1771 0q0 -53 -37 -90l-107 -108q-39 -37 -91 -37q-53 0 -90 37l-363 364q-38 36 -38 90q0 53 43 96l-256 256l-126 -126q-14 -14 -34 -14t-34 14q2 -2 12.5 -12t12.5 -13t10 -11.5t10 -13.5t6 -13.5t5.5 -16.5t1.5 -18q0 -38 -28 -68q-3 -3 -16.5 -18t-19 -20.5
+t-18.5 -16.5t-22 -15.5t-22 -9t-26 -4.5q-40 0 -68 28l-408 408q-28 28 -28 68q0 13 4.5 26t9 22t15.5 22t16.5 18.5t20.5 19t18 16.5q30 28 68 28q10 0 18 -1.5t16.5 -5.5t13.5 -6t13.5 -10t11.5 -10t13 -12.5t12 -12.5q-14 14 -14 34t14 34l348 348q14 14 34 14t34 -14
+q-2 2 -12.5 12t-12.5 13t-10 11.5t-10 13.5t-6 13.5t-5.5 16.5t-1.5 18q0 38 28 68q3 3 16.5 18t19 20.5t18.5 16.5t22 15.5t22 9t26 4.5q40 0 68 -28l408 -408q28 -28 28 -68q0 -13 -4.5 -26t-9 -22t-15.5 -22t-16.5 -18.5t-20.5 -19t-18 -16.5q-30 -28 -68 -28
+q-10 0 -18 1.5t-16.5 5.5t-13.5 6t-13.5 10t-11.5 10t-13 12.5t-12 12.5q14 -14 14 -34t-14 -34l-126 -126l256 -256q43 43 96 43q52 0 91 -37l363 -363q37 -39 37 -91z" />
+ <glyph glyph-name="dashboard" unicode="" horiz-adv-x="1792"
+d="M384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM576 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1004 351l101 382q6 26 -7.5 48.5t-38.5 29.5
+t-48 -6.5t-30 -39.5l-101 -382q-60 -5 -107 -43.5t-63 -98.5q-20 -77 20 -146t117 -89t146 20t89 117q16 60 -6 117t-72 91zM1664 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 1024q0 53 -37.5 90.5
+t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1472 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 384q0 -261 -141 -483q-19 -29 -54 -29h-1402q-35 0 -54 29
+q-141 221 -141 483q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+ <glyph glyph-name="comment_alt" unicode="" horiz-adv-x="1792"
+d="M896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640
+q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 174 120 321.5
+t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" />
+ <glyph glyph-name="comments_alt" unicode="" horiz-adv-x="1792"
+d="M704 1152q-153 0 -286 -52t-211.5 -141t-78.5 -191q0 -82 53 -158t149 -132l97 -56l-35 -84q34 20 62 39l44 31l53 -10q78 -14 153 -14q153 0 286 52t211.5 141t78.5 191t-78.5 191t-211.5 141t-286 52zM704 1280q191 0 353.5 -68.5t256.5 -186.5t94 -257t-94 -257
+t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224q0 139 94 257t256.5 186.5
+t353.5 68.5zM1526 111q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129
+q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230q0 -120 -71 -224.5t-195 -176.5z" />
+ <glyph glyph-name="bolt" unicode="" horiz-adv-x="896"
+d="M885 970q18 -20 7 -44l-540 -1157q-13 -25 -42 -25q-4 0 -14 2q-17 5 -25.5 19t-4.5 30l197 808l-406 -101q-4 -1 -12 -1q-18 0 -31 11q-18 15 -13 39l201 825q4 14 16 23t28 9h328q19 0 32 -12.5t13 -29.5q0 -8 -5 -18l-171 -463l396 98q8 2 12 2q19 0 34 -15z" />
+ <glyph glyph-name="sitemap" unicode="" horiz-adv-x="1792"
+d="M1792 288v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320
+q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192q0 52 38 90t90 38h512v192h-96q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-96v-192h512q52 0 90 -38t38 -90v-192h96q40 0 68 -28t28 -68
+z" />
+ <glyph glyph-name="umbrella" unicode="" horiz-adv-x="1664"
+d="M896 708v-580q0 -104 -76 -180t-180 -76t-180 76t-76 180q0 26 19 45t45 19t45 -19t19 -45q0 -50 39 -89t89 -39t89 39t39 89v580q33 11 64 11t64 -11zM1664 681q0 -13 -9.5 -22.5t-22.5 -9.5q-11 0 -23 10q-49 46 -93 69t-102 23q-68 0 -128 -37t-103 -97
+q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -28 -17q-18 0 -29 17q-4 6 -14.5 24t-17.5 28q-43 60 -102.5 97t-127.5 37t-127.5 -37t-102.5 -97q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -29 -17q-17 0 -28 17q-4 6 -14.5 24t-17.5 28q-43 60 -103 97t-128 37q-58 0 -102 -23t-93 -69
+q-12 -10 -23 -10q-13 0 -22.5 9.5t-9.5 22.5q0 5 1 7q45 183 172.5 319.5t298 204.5t360.5 68q140 0 274.5 -40t246.5 -113.5t194.5 -187t115.5 -251.5q1 -2 1 -7zM896 1408v-98q-42 2 -64 2t-64 -2v98q0 26 19 45t45 19t45 -19t19 -45z" />
+ <glyph glyph-name="paste" unicode="" horiz-adv-x="1792"
+d="M768 -128h896v640h-416q-40 0 -68 28t-28 68v416h-384v-1152zM1024 1312v64q0 13 -9.5 22.5t-22.5 9.5h-704q-13 0 -22.5 -9.5t-9.5 -22.5v-64q0 -13 9.5 -22.5t22.5 -9.5h704q13 0 22.5 9.5t9.5 22.5zM1280 640h299l-299 299v-299zM1792 512v-672q0 -40 -28 -68t-68 -28
+h-960q-40 0 -68 28t-28 68v160h-544q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1088q40 0 68 -28t28 -68v-328q21 -13 36 -28l408 -408q28 -28 48 -76t20 -88z" />
+ <glyph glyph-name="light_bulb" unicode="" horiz-adv-x="1024"
+d="M736 960q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5q0 46 -54 71t-106 25q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5q50 0 99.5 -16t87 -54t37.5 -90zM896 960q0 72 -34.5 134t-90 101.5t-123 62t-136.5 22.5t-136.5 -22.5t-123 -62t-90 -101.5t-34.5 -134
+q0 -101 68 -180q10 -11 30.5 -33t30.5 -33q128 -153 141 -298h228q13 145 141 298q10 11 30.5 33t30.5 33q68 79 68 180zM1024 960q0 -155 -103 -268q-45 -49 -74.5 -87t-59.5 -95.5t-34 -107.5q47 -28 47 -82q0 -37 -25 -64q25 -27 25 -64q0 -52 -45 -81q13 -23 13 -47
+q0 -46 -31.5 -71t-77.5 -25q-20 -44 -60 -70t-87 -26t-87 26t-60 70q-46 0 -77.5 25t-31.5 71q0 24 13 47q-45 29 -45 81q0 37 25 64q-25 27 -25 64q0 54 47 82q-4 50 -34 107.5t-59.5 95.5t-74.5 87q-103 113 -103 268q0 99 44.5 184.5t117 142t164 89t186.5 32.5
+t186.5 -32.5t164 -89t117 -142t44.5 -184.5z" />
+ <glyph glyph-name="exchange" unicode="" horiz-adv-x="1792"
+d="M1792 352v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5q-12 0 -24 10l-319 320q-9 9 -9 22q0 14 9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h1376q13 0 22.5 -9.5t9.5 -22.5zM1792 896q0 -14 -9 -23l-320 -320q-9 -9 -23 -9
+q-13 0 -22.5 9.5t-9.5 22.5v192h-1376q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1376v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
+ <glyph glyph-name="cloud_download" unicode="" horiz-adv-x="1920"
+d="M1280 608q0 14 -9 23t-23 9h-224v352q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-352h-224q-13 0 -22.5 -9.5t-9.5 -22.5q0 -14 9 -23l352 -352q9 -9 23 -9t23 9l351 351q10 12 10 24zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088
+q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
+ <glyph glyph-name="cloud_upload" unicode="" horiz-adv-x="1920"
+d="M1280 672q0 14 -9 23l-352 352q-9 9 -23 9t-23 -9l-351 -351q-10 -12 -10 -24q0 -14 9 -23t23 -9h224v-352q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5v352h224q13 0 22.5 9.5t9.5 22.5zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088
+q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
+ <glyph glyph-name="user_md" unicode="" horiz-adv-x="1408"
+d="M384 192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 68 5.5 131t24 138t47.5 132.5t81 103t120 60.5q-22 -52 -22 -120v-203q-58 -20 -93 -70t-35 -111q0 -80 56 -136t136 -56
+t136 56t56 136q0 61 -35.5 111t-92.5 70v203q0 62 25 93q132 -104 295 -104t295 104q25 -31 25 -93v-64q-106 0 -181 -75t-75 -181v-89q-32 -29 -32 -71q0 -40 28 -68t68 -28t68 28t28 68q0 42 -32 71v89q0 52 38 90t90 38t90 -38t38 -90v-89q-32 -29 -32 -71q0 -40 28 -68
+t68 -28t68 28t28 68q0 42 -32 71v89q0 68 -34.5 127.5t-93.5 93.5q0 10 0.5 42.5t0 48t-2.5 41.5t-7 47t-13 40q68 -15 120 -60.5t81 -103t47.5 -132.5t24 -138t5.5 -131zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5
+t271.5 -112.5t112.5 -271.5z" />
+ <glyph glyph-name="stethoscope" unicode="" horiz-adv-x="1408"
+d="M1280 832q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 832q0 -62 -35.5 -111t-92.5 -70v-395q0 -159 -131.5 -271.5t-316.5 -112.5t-316.5 112.5t-131.5 271.5v132q-164 20 -274 128t-110 252v512q0 26 19 45t45 19q6 0 16 -2q17 30 47 48
+t65 18q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5q-33 0 -64 18v-402q0 -106 94 -181t226 -75t226 75t94 181v402q-31 -18 -64 -18q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5q35 0 65 -18t47 -48q10 2 16 2q26 0 45 -19t19 -45v-512q0 -144 -110 -252
+t-274 -128v-132q0 -106 94 -181t226 -75t226 75t94 181v395q-57 21 -92.5 70t-35.5 111q0 80 56 136t136 56t136 -56t56 -136z" />
+ <glyph glyph-name="suitcase" unicode="" horiz-adv-x="1792"
+d="M640 1152h512v128h-512v-128zM288 1152v-1280h-64q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h64zM1408 1152v-1280h-1024v1280h128v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h128zM1792 928v-832q0 -92 -66 -158t-158 -66h-64v1280h64q92 0 158 -66
+t66 -158z" />
+ <glyph glyph-name="bell_alt" unicode="" horiz-adv-x="1792"
+d="M912 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM1728 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q50 42 91 88t85 119.5t74.5 158.5
+t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q190 -28 307 -158.5t117 -282.5q0 -139 19.5 -260t50 -206t74.5 -158.5t85 -119.5t91 -88z" />
+ <glyph glyph-name="coffee" unicode="" horiz-adv-x="1920"
+d="M1664 896q0 80 -56 136t-136 56h-64v-384h64q80 0 136 56t56 136zM0 128h1792q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM1856 896q0 -159 -112.5 -271.5t-271.5 -112.5h-64v-32q0 -92 -66 -158t-158 -66h-704q-92 0 -158 66t-66 158v736q0 26 19 45
+t45 19h1152q159 0 271.5 -112.5t112.5 -271.5z" />
+ <glyph glyph-name="food" unicode="" horiz-adv-x="1408"
+d="M640 1472v-640q0 -61 -35.5 -111t-92.5 -70v-779q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v779q-57 20 -92.5 70t-35.5 111v640q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45
+t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45zM1408 1472v-1600q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v512h-224q-13 0 -22.5 9.5t-9.5 22.5v800q0 132 94 226t226 94h256q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="file_text_alt" unicode=""
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M384 736q0 14 9 23t23 9h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64zM1120 512q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704zM1120 256q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704
+q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704z" />
+ <glyph glyph-name="building" unicode="" horiz-adv-x="1408"
+d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M640 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M640 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M896 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M896 -128h384v1536h-1152v-1536h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM1408 1472v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="hospital" unicode="" horiz-adv-x="1408"
+d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M896 -128h384v1152h-256v-32q0 -40 -28 -68t-68 -28h-448q-40 0 -68 28t-28 68v32h-256v-1152h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM896 1056v320q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-96h-128v96q0 13 -9.5 22.5
+t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5v96h128v-96q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1408 1088v-1280q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1280q0 26 19 45t45 19h320
+v288q0 40 28 68t68 28h448q40 0 68 -28t28 -68v-288h320q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="ambulance" unicode="" horiz-adv-x="1920"
+d="M640 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM256 640h384v256h-158q-14 -2 -22 -9l-195 -195q-7 -12 -9 -22v-30zM1536 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5
+t90.5 37.5t37.5 90.5zM1664 800v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM1920 1344v-1152
+q0 -26 -19 -45t-45 -19h-192q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-128q-26 0 -45 19t-19 45t19 45t45 19v416q0 26 13 58t32 51l198 198q19 19 51 32t58 13h160v320q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="medkit" unicode="" horiz-adv-x="1792"
+d="M1280 416v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM640 1152h512v128h-512v-128zM256 1152v-1280h-32
+q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h32zM1440 1152v-1280h-1088v1280h160v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h160zM1792 928v-832q0 -92 -66 -158t-158 -66h-32v1280h32q92 0 158 -66t66 -158z" />
+ <glyph glyph-name="fighter_jet" unicode="" horiz-adv-x="1920"
+d="M1920 576q-1 -32 -288 -96l-352 -32l-224 -64h-64l-293 -352h69q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-96h-160h-64v32h64v416h-160l-192 -224h-96l-32 32v192h32v32h128v8l-192 24v128l192 24v8h-128v32h-32v192l32 32h96l192 -224h160v416h-64v32h64h160h96
+q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-69l293 -352h64l224 -64l352 -32q128 -28 200 -52t80 -34z" />
+ <glyph glyph-name="beer" unicode="" horiz-adv-x="1664"
+d="M640 640v384h-256v-256q0 -53 37.5 -90.5t90.5 -37.5h128zM1664 192v-192h-1152v192l128 192h-128q-159 0 -271.5 112.5t-112.5 271.5v320l-64 64l32 128h480l32 128h960l32 -192l-64 -32v-800z" />
+ <glyph glyph-name="h_sign" unicode=""
+d="M1280 192v896q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-512v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-896q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h512v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1536 1120v-960
+q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="f0fe" unicode=""
+d="M1280 576v128q0 26 -19 45t-45 19h-320v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-320q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h320v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h320q26 0 45 19t19 45zM1536 1120v-960
+q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="double_angle_left" unicode="" horiz-adv-x="1024"
+d="M627 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23zM1011 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23
+t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23z" />
+ <glyph glyph-name="double_angle_right" unicode="" horiz-adv-x="1024"
+d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM979 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23
+l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+ <glyph glyph-name="double_angle_up" unicode="" horiz-adv-x="1152"
+d="M1075 224q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM1075 608q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393
+q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+ <glyph glyph-name="double_angle_down" unicode="" horiz-adv-x="1152"
+d="M1075 672q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23zM1075 1056q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23
+t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
+ <glyph glyph-name="angle_left" unicode="" horiz-adv-x="640"
+d="M627 992q0 -13 -10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
+ <glyph glyph-name="angle_right" unicode="" horiz-adv-x="640"
+d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+ <glyph glyph-name="angle_up" unicode="" horiz-adv-x="1152"
+d="M1075 352q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+ <glyph glyph-name="angle_down" unicode="" horiz-adv-x="1152"
+d="M1075 800q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
+ <glyph glyph-name="desktop" unicode="" horiz-adv-x="1920"
+d="M1792 544v832q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1376v-1088q0 -66 -47 -113t-113 -47h-544q0 -37 16 -77.5t32 -71t16 -43.5q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19
+t-19 45q0 14 16 44t32 70t16 78h-544q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+ <glyph glyph-name="laptop" unicode="" horiz-adv-x="1920"
+d="M416 256q-66 0 -113 47t-47 113v704q0 66 47 113t113 47h1088q66 0 113 -47t47 -113v-704q0 -66 -47 -113t-113 -47h-1088zM384 1120v-704q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5z
+M1760 192h160v-96q0 -40 -47 -68t-113 -28h-1600q-66 0 -113 28t-47 68v96h160h1600zM1040 96q16 0 16 16t-16 16h-160q-16 0 -16 -16t16 -16h160z" />
+ <glyph glyph-name="tablet" unicode="" horiz-adv-x="1152"
+d="M640 128q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1024 288v960q0 13 -9.5 22.5t-22.5 9.5h-832q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h832q13 0 22.5 9.5t9.5 22.5zM1152 1248v-1088q0 -66 -47 -113t-113 -47h-832
+q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h832q66 0 113 -47t47 -113z" />
+ <glyph glyph-name="mobile_phone" unicode="" horiz-adv-x="768"
+d="M464 128q0 33 -23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5t56.5 23.5t23.5 56.5zM672 288v704q0 13 -9.5 22.5t-22.5 9.5h-512q-13 0 -22.5 -9.5t-9.5 -22.5v-704q0 -13 9.5 -22.5t22.5 -9.5h512q13 0 22.5 9.5t9.5 22.5zM480 1136
+q0 16 -16 16h-160q-16 0 -16 -16t16 -16h160q16 0 16 16zM768 1152v-1024q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v1024q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
+ <glyph glyph-name="circle_blank" unicode=""
+d="M768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103
+t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="quote_left" unicode="" horiz-adv-x="1664"
+d="M768 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z
+M1664 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z" />
+ <glyph glyph-name="quote_right" unicode="" horiz-adv-x="1664"
+d="M768 1216v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136zM1664 1216
+v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136z" />
+ <glyph glyph-name="spinner" unicode="" horiz-adv-x="1792"
+d="M526 142q0 -53 -37.5 -90.5t-90.5 -37.5q-52 0 -90 38t-38 90q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1024 -64q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM320 640q0 -53 -37.5 -90.5t-90.5 -37.5
+t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1522 142q0 -52 -38 -90t-90 -38q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM558 1138q0 -66 -47 -113t-113 -47t-113 47t-47 113t47 113t113 47t113 -47t47 -113z
+M1728 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1088 1344q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1618 1138q0 -93 -66 -158.5t-158 -65.5q-93 0 -158.5 65.5t-65.5 158.5
+q0 92 65.5 158t158.5 66q92 0 158 -66t66 -158z" />
+ <glyph glyph-name="circle" unicode=""
+d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="reply" unicode="" horiz-adv-x="1792"
+d="M1792 416q0 -166 -127 -451q-3 -7 -10.5 -24t-13.5 -30t-13 -22q-12 -17 -28 -17q-15 0 -23.5 10t-8.5 25q0 9 2.5 26.5t2.5 23.5q5 68 5 123q0 101 -17.5 181t-48.5 138.5t-80 101t-105.5 69.5t-133 42.5t-154 21.5t-175.5 6h-224v-256q0 -26 -19 -45t-45 -19t-45 19
+l-512 512q-19 19 -19 45t19 45l512 512q19 19 45 19t45 -19t19 -45v-256h224q713 0 875 -403q53 -134 53 -333z" />
+ <glyph glyph-name="github_alt" unicode="" horiz-adv-x="1664"
+d="M640 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1280 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1440 320
+q0 120 -69 204t-187 84q-41 0 -195 -21q-71 -11 -157 -11t-157 11q-152 21 -195 21q-118 0 -187 -84t-69 -204q0 -88 32 -153.5t81 -103t122 -60t140 -29.5t149 -7h168q82 0 149 7t140 29.5t122 60t81 103t32 153.5zM1664 496q0 -207 -61 -331q-38 -77 -105.5 -133t-141 -86
+t-170 -47.5t-171.5 -22t-167 -4.5q-78 0 -142 3t-147.5 12.5t-152.5 30t-137 51.5t-121 81t-86 115q-62 123 -62 331q0 237 136 396q-27 82 -27 170q0 116 51 218q108 0 190 -39.5t189 -123.5q147 35 309 35q148 0 280 -32q105 82 187 121t189 39q51 -102 51 -218
+q0 -87 -27 -168q136 -160 136 -398z" />
+ <glyph glyph-name="folder_close_alt" unicode="" horiz-adv-x="1664"
+d="M1536 224v704q0 40 -28 68t-68 28h-704q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68v-960q0 -40 28 -68t68 -28h1216q40 0 68 28t28 68zM1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320
+q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
+ <glyph glyph-name="folder_open_alt" unicode="" horiz-adv-x="1920"
+d="M1781 605q0 35 -53 35h-1088q-40 0 -85.5 -21.5t-71.5 -52.5l-294 -363q-18 -24 -18 -40q0 -35 53 -35h1088q40 0 86 22t71 53l294 363q18 22 18 39zM640 768h768v160q0 40 -28 68t-68 28h-576q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68
+v-853l256 315q44 53 116 87.5t140 34.5zM1909 605q0 -62 -46 -120l-295 -363q-43 -53 -116 -87.5t-140 -34.5h-1088q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158v-160h192q54 0 99 -24.5t67 -70.5q15 -32 15 -68z
+" />
+ <glyph glyph-name="expand_alt" unicode="" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="collapse_alt" unicode="" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="smile" unicode=""
+d="M1134 461q-37 -121 -138 -195t-228 -74t-228 74t-138 195q-8 25 4 48.5t38 31.5q25 8 48.5 -4t31.5 -38q25 -80 92.5 -129.5t151.5 -49.5t151.5 49.5t92.5 129.5q8 26 32 38t49 4t37 -31.5t4 -48.5zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5
+t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5
+t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="frown" unicode=""
+d="M1134 307q8 -25 -4 -48.5t-37 -31.5t-49 4t-32 38q-25 80 -92.5 129.5t-151.5 49.5t-151.5 -49.5t-92.5 -129.5q-8 -26 -31.5 -38t-48.5 -4q-26 8 -38 31.5t-4 48.5q37 121 138 195t228 74t228 -74t138 -195zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5
+t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204
+t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="meh" unicode=""
+d="M1152 448q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h640q26 0 45 -19t19 -45zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5
+t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="gamepad" unicode="" horiz-adv-x="1920"
+d="M832 448v128q0 14 -9 23t-23 9h-192v192q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-192h-192q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h192v-192q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v192h192q14 0 23 9t9 23zM1408 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5
+t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1920 512q0 -212 -150 -362t-362 -150q-192 0 -338 128h-220q-146 -128 -338 -128q-212 0 -362 150
+t-150 362t150 362t362 150h896q212 0 362 -150t150 -362z" />
+ <glyph glyph-name="keyboard" unicode="" horiz-adv-x="1920"
+d="M384 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM512 624v-96q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h224q16 0 16 -16zM384 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 368v-96q0 -16 -16 -16
+h-864q-16 0 -16 16v96q0 16 16 16h864q16 0 16 -16zM768 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM640 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1024 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16
+h96q16 0 16 -16zM896 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1280 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1152 880v-96
+q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 880v-352q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h112v240q0 16 16 16h96q16 0 16 -16zM1792 128v896h-1664v-896
+h1664zM1920 1024v-896q0 -53 -37.5 -90.5t-90.5 -37.5h-1664q-53 0 -90.5 37.5t-37.5 90.5v896q0 53 37.5 90.5t90.5 37.5h1664q53 0 90.5 -37.5t37.5 -90.5z" />
+ <glyph glyph-name="flag_alt" unicode="" horiz-adv-x="1792"
+d="M1664 491v616q-169 -91 -306 -91q-82 0 -145 32q-100 49 -184 76.5t-178 27.5q-173 0 -403 -127v-599q245 113 433 113q55 0 103.5 -7.5t98 -26t77 -31t82.5 -39.5l28 -14q44 -22 101 -22q120 0 293 92zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9
+h-64q-14 0 -23 9t-9 23v1266q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102
+q-15 -9 -33 -9q-16 0 -32 8q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" />
+ <glyph glyph-name="flag_checkered" unicode="" horiz-adv-x="1792"
+d="M832 536v192q-181 -16 -384 -117v-185q205 96 384 110zM832 954v197q-172 -8 -384 -126v-189q215 111 384 118zM1664 491v184q-235 -116 -384 -71v224q-20 6 -39 15q-5 3 -33 17t-34.5 17t-31.5 15t-34.5 15.5t-32.5 13t-36 12.5t-35 8.5t-39.5 7.5t-39.5 4t-44 2
+q-23 0 -49 -3v-222h19q102 0 192.5 -29t197.5 -82q19 -9 39 -15v-188q42 -17 91 -17q120 0 293 92zM1664 918v189q-169 -91 -306 -91q-45 0 -78 8v-196q148 -42 384 90zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v1266
+q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102q-15 -9 -33 -9q-16 0 -32 8
+q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" />
+ <glyph glyph-name="terminal" unicode="" horiz-adv-x="1664"
+d="M585 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23zM1664 96v-64q0 -14 -9 -23t-23 -9h-960q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h960q14 0 23 -9
+t9 -23z" />
+ <glyph glyph-name="code" unicode="" horiz-adv-x="1920"
+d="M617 137l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23zM1208 1204l-373 -1291q-4 -13 -15.5 -19.5t-23.5 -2.5l-62 17q-13 4 -19.5 15.5t-2.5 24.5
+l373 1291q4 13 15.5 19.5t23.5 2.5l62 -17q13 -4 19.5 -15.5t2.5 -24.5zM1865 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23z" />
+ <glyph glyph-name="reply_all" unicode="" horiz-adv-x="1792"
+d="M640 454v-70q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-69l-397 -398q-19 -19 -19 -45t19 -45zM1792 416q0 -58 -17 -133.5t-38.5 -138t-48 -125t-40.5 -90.5l-20 -40q-8 -17 -28 -17q-6 0 -9 1
+q-25 8 -23 34q43 400 -106 565q-64 71 -170.5 110.5t-267.5 52.5v-251q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-262q411 -28 599 -221q169 -173 169 -509z" />
+ <glyph glyph-name="star_half_empty" unicode="" horiz-adv-x="1664"
+d="M1186 579l257 250l-356 52l-66 10l-30 60l-159 322v-963l59 -31l318 -168l-60 355l-12 66zM1638 841l-363 -354l86 -500q5 -33 -6 -51.5t-34 -18.5q-17 0 -40 12l-449 236l-449 -236q-23 -12 -40 -12q-23 0 -34 18.5t-6 51.5l86 500l-364 354q-32 32 -23 59.5t54 34.5
+l502 73l225 455q20 41 49 41q28 0 49 -41l225 -455l502 -73q45 -7 54 -34.5t-24 -59.5z" />
+ <glyph glyph-name="location_arrow" unicode="" horiz-adv-x="1408"
+d="M1401 1187l-640 -1280q-17 -35 -57 -35q-5 0 -15 2q-22 5 -35.5 22.5t-13.5 39.5v576h-576q-22 0 -39.5 13.5t-22.5 35.5t4 42t29 30l1280 640q13 7 29 7q27 0 45 -19q15 -14 18.5 -34.5t-6.5 -39.5z" />
+ <glyph glyph-name="crop" unicode="" horiz-adv-x="1664"
+d="M557 256h595v595zM512 301l595 595h-595v-595zM1664 224v-192q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v224h-864q-14 0 -23 9t-9 23v864h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224v224q0 14 9 23t23 9h192q14 0 23 -9t9 -23
+v-224h851l246 247q10 9 23 9t23 -9q9 -10 9 -23t-9 -23l-247 -246v-851h224q14 0 23 -9t9 -23z" />
+ <glyph glyph-name="code_fork" unicode="" horiz-adv-x="1024"
+d="M288 64q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM288 1216q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM928 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1024 1088q0 -52 -26 -96.5t-70 -69.5
+q-2 -287 -226 -414q-67 -38 -203 -81q-128 -40 -169.5 -71t-41.5 -100v-26q44 -25 70 -69.5t26 -96.5q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 52 26 96.5t70 69.5v820q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136q0 -52 -26 -96.5t-70 -69.5v-497
+q54 26 154 57q55 17 87.5 29.5t70.5 31t59 39.5t40.5 51t28 69.5t8.5 91.5q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136z" />
+ <glyph glyph-name="unlink" unicode="" horiz-adv-x="1664"
+d="M439 265l-256 -256q-11 -9 -23 -9t-23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23zM608 224v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM384 448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23t9 23t23 9h320
+q14 0 23 -9t9 -23zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-334 335q-21 21 -42 56l239 18l273 -274q27 -27 68 -27.5t68 26.5l147 146q28 28 28 67q0 40 -28 68l-274 275l18 239q35 -21 56 -42l336 -336q84 -86 84 -204zM1031 1044l-239 -18
+l-273 274q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l274 -274l-18 -240q-35 21 -56 42l-336 336q-84 86 -84 204q0 120 85 203l147 146q83 83 203 83q121 0 204 -85l334 -335q21 -21 42 -56zM1664 960q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9
+t-9 23t9 23t23 9h320q14 0 23 -9t9 -23zM1120 1504v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM1527 1353l-256 -256q-11 -9 -23 -9t-23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" />
+ <glyph glyph-name="question" unicode="" horiz-adv-x="1024"
+d="M704 280v-240q0 -16 -12 -28t-28 -12h-240q-16 0 -28 12t-12 28v240q0 16 12 28t28 12h240q16 0 28 -12t12 -28zM1020 880q0 -54 -15.5 -101t-35 -76.5t-55 -59.5t-57.5 -43.5t-61 -35.5q-41 -23 -68.5 -65t-27.5 -67q0 -17 -12 -32.5t-28 -15.5h-240q-15 0 -25.5 18.5
+t-10.5 37.5v45q0 83 65 156.5t143 108.5q59 27 84 56t25 76q0 42 -46.5 74t-107.5 32q-65 0 -108 -29q-35 -25 -107 -115q-13 -16 -31 -16q-12 0 -25 8l-164 125q-13 10 -15.5 25t5.5 28q160 266 464 266q80 0 161 -31t146 -83t106 -127.5t41 -158.5z" />
+ <glyph glyph-name="_279" unicode="" horiz-adv-x="640"
+d="M640 192v-128q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64v384h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-576h64q26 0 45 -19t19 -45zM512 1344v-192q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v192
+q0 26 19 45t45 19h256q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="exclamation" unicode="" horiz-adv-x="640"
+d="M512 288v-224q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v224q0 26 19 45t45 19h256q26 0 45 -19t19 -45zM542 1344l-28 -768q-1 -26 -20.5 -45t-45.5 -19h-256q-26 0 -45.5 19t-20.5 45l-28 768q-1 26 17.5 45t44.5 19h320q26 0 44.5 -19t17.5 -45z" />
+ <glyph glyph-name="superscript" unicode=""
+d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3q-1 -3 -2.5 -6.5t-3.5 -8t-3 -6.5q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109z
+M1534 846v-206h-514l-3 27q-4 28 -4 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q83 65 188 65q110 0 178 -59.5t68 -158.5q0 -56 -24.5 -103t-62 -76.5t-81.5 -58.5t-82 -50.5
+t-65.5 -51.5t-30.5 -63h232v80h126z" />
+ <glyph glyph-name="subscript" unicode=""
+d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3q-1 -3 -2.5 -6.5t-3.5 -8t-3 -6.5q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109z
+M1536 -50v-206h-514l-4 27q-3 45 -3 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q80 65 188 65q110 0 178 -59.5t68 -158.5q0 -66 -34.5 -118.5t-84 -86t-99.5 -62.5t-87 -63t-41 -73
+h232v80h126z" />
+ <glyph glyph-name="_283" unicode="" horiz-adv-x="1920"
+d="M896 128l336 384h-768l-336 -384h768zM1909 1205q15 -34 9.5 -71.5t-30.5 -65.5l-896 -1024q-38 -44 -96 -44h-768q-38 0 -69.5 20.5t-47.5 54.5q-15 34 -9.5 71.5t30.5 65.5l896 1024q38 44 96 44h768q38 0 69.5 -20.5t47.5 -54.5z" />
+ <glyph glyph-name="puzzle_piece" unicode="" horiz-adv-x="1664"
+d="M1664 438q0 -81 -44.5 -135t-123.5 -54q-41 0 -77.5 17.5t-59 38t-56.5 38t-71 17.5q-110 0 -110 -124q0 -39 16 -115t15 -115v-5q-22 0 -33 -1q-34 -3 -97.5 -11.5t-115.5 -13.5t-98 -5q-61 0 -103 26.5t-42 83.5q0 37 17.5 71t38 56.5t38 59t17.5 77.5q0 79 -54 123.5
+t-135 44.5q-84 0 -143 -45.5t-59 -127.5q0 -43 15 -83t33.5 -64.5t33.5 -53t15 -50.5q0 -45 -46 -89q-37 -35 -117 -35q-95 0 -245 24q-9 2 -27.5 4t-27.5 4l-13 2q-1 0 -3 1q-2 0 -2 1v1024q2 -1 17.5 -3.5t34 -5t21.5 -3.5q150 -24 245 -24q80 0 117 35q46 44 46 89
+q0 22 -15 50.5t-33.5 53t-33.5 64.5t-15 83q0 82 59 127.5t144 45.5q80 0 134 -44.5t54 -123.5q0 -41 -17.5 -77.5t-38 -59t-38 -56.5t-17.5 -71q0 -57 42 -83.5t103 -26.5q64 0 180 15t163 17v-2q-1 -2 -3.5 -17.5t-5 -34t-3.5 -21.5q-24 -150 -24 -245q0 -80 35 -117
+q44 -46 89 -46q22 0 50.5 15t53 33.5t64.5 33.5t83 15q82 0 127.5 -59t45.5 -143z" />
+ <glyph glyph-name="microphone" unicode="" horiz-adv-x="1152"
+d="M1152 832v-128q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-217 24 -364.5 187.5t-147.5 384.5v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -185 131.5 -316.5t316.5 -131.5
+t316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45zM896 1216v-512q0 -132 -94 -226t-226 -94t-226 94t-94 226v512q0 132 94 226t226 94t226 -94t94 -226z" />
+ <glyph glyph-name="microphone_off" unicode="" horiz-adv-x="1408"
+d="M271 591l-101 -101q-42 103 -42 214v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -53 15 -113zM1385 1193l-361 -361v-128q0 -132 -94 -226t-226 -94q-55 0 -109 19l-96 -96q97 -51 205 -51q185 0 316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45v-128
+q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-125 13 -235 81l-254 -254q-10 -10 -23 -10t-23 10l-82 82q-10 10 -10 23t10 23l1234 1234q10 10 23 10t23 -10l82 -82q10 -10 10 -23
+t-10 -23zM1005 1325l-621 -621v512q0 132 94 226t226 94q102 0 184.5 -59t116.5 -152z" />
+ <glyph glyph-name="shield" unicode="" horiz-adv-x="1280"
+d="M1088 576v640h-448v-1137q119 63 213 137q235 184 235 360zM1280 1344v-768q0 -86 -33.5 -170.5t-83 -150t-118 -127.5t-126.5 -103t-121 -77.5t-89.5 -49.5t-42.5 -20q-12 -6 -26 -6t-26 6q-16 7 -42.5 20t-89.5 49.5t-121 77.5t-126.5 103t-118 127.5t-83 150
+t-33.5 170.5v768q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="calendar_empty" unicode="" horiz-adv-x="1664"
+d="M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280
+q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+ <glyph glyph-name="fire_extinguisher" unicode="" horiz-adv-x="1408"
+d="M512 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 1376v-320q0 -16 -12 -25q-8 -7 -20 -7q-4 0 -7 1l-448 96q-11 2 -18 11t-7 20h-256v-102q111 -23 183.5 -111t72.5 -203v-800q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v800
+q0 106 62.5 190.5t161.5 114.5v111h-32q-59 0 -115 -23.5t-91.5 -53t-66 -66.5t-40.5 -53.5t-14 -24.5q-17 -35 -57 -35q-16 0 -29 7q-23 12 -31.5 37t3.5 49q5 10 14.5 26t37.5 53.5t60.5 70t85 67t108.5 52.5q-25 42 -25 86q0 66 47 113t113 47t113 -47t47 -113
+q0 -33 -14 -64h302q0 11 7 20t18 11l448 96q3 1 7 1q12 0 20 -7q12 -9 12 -25z" />
+ <glyph glyph-name="rocket" unicode="" horiz-adv-x="1664"
+d="M1440 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1664 1376q0 -249 -75.5 -430.5t-253.5 -360.5q-81 -80 -195 -176l-20 -379q-2 -16 -16 -26l-384 -224q-7 -4 -16 -4q-12 0 -23 9l-64 64q-13 14 -8 32l85 276l-281 281l-276 -85q-3 -1 -9 -1
+q-14 0 -23 9l-64 64q-17 19 -5 39l224 384q10 14 26 16l379 20q96 114 176 195q188 187 358 258t431 71q14 0 24 -9.5t10 -22.5z" />
+ <glyph glyph-name="maxcdn" unicode="" horiz-adv-x="1792"
+d="M1745 763l-164 -763h-334l178 832q13 56 -15 88q-27 33 -83 33h-169l-204 -953h-334l204 953h-286l-204 -953h-334l204 953l-153 327h1276q101 0 189.5 -40.5t147.5 -113.5q60 -73 81 -168.5t0 -194.5z" />
+ <glyph glyph-name="chevron_sign_left" unicode=""
+d="M909 141l102 102q19 19 19 45t-19 45l-307 307l307 307q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
+t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="chevron_sign_right" unicode=""
+d="M717 141l454 454q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l307 -307l-307 -307q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
+t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="chevron_sign_up" unicode=""
+d="M1165 397l102 102q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l307 307l307 -307q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
+t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="chevron_sign_down" unicode=""
+d="M813 237l454 454q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-307 -307l-307 307q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
+t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="html5" unicode="" horiz-adv-x="1408"
+d="M1130 939l16 175h-884l47 -534h612l-22 -228l-197 -53l-196 53l-13 140h-175l22 -278l362 -100h4v1l359 99l50 544h-644l-15 181h674zM0 1408h1408l-128 -1438l-578 -162l-574 162z" />
+ <glyph glyph-name="css3" unicode="" horiz-adv-x="1792"
+d="M275 1408h1505l-266 -1333l-804 -267l-698 267l71 356h297l-29 -147l422 -161l486 161l68 339h-1208l58 297h1209l38 191h-1208z" />
+ <glyph glyph-name="anchor" unicode="" horiz-adv-x="1792"
+d="M960 1280q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1792 352v-352q0 -22 -20 -30q-8 -2 -12 -2q-12 0 -23 9l-93 93q-119 -143 -318.5 -226.5t-429.5 -83.5t-429.5 83.5t-318.5 226.5l-93 -93q-9 -9 -23 -9q-4 0 -12 2q-20 8 -20 30v352
+q0 14 9 23t23 9h352q22 0 30 -20q8 -19 -7 -35l-100 -100q67 -91 189.5 -153.5t271.5 -82.5v647h-192q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h192v163q-58 34 -93 92.5t-35 128.5q0 106 75 181t181 75t181 -75t75 -181q0 -70 -35 -128.5t-93 -92.5v-163h192q26 0 45 -19
+t19 -45v-128q0 -26 -19 -45t-45 -19h-192v-647q149 20 271.5 82.5t189.5 153.5l-100 100q-15 16 -7 35q8 20 30 20h352q14 0 23 -9t9 -23z" />
+ <glyph glyph-name="unlock_alt" unicode="" horiz-adv-x="1152"
+d="M1056 768q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v320q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45q0 106 -75 181t-181 75t-181 -75t-75 -181
+v-320h736z" />
+ <glyph glyph-name="bullseye" unicode=""
+d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM1152 640q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM1280 640q0 -212 -150 -362t-362 -150t-362 150
+t-150 362t150 362t362 150t362 -150t150 -362zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="ellipsis_horizontal" unicode="" horiz-adv-x="1408"
+d="M384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM896 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM1408 800v-192q0 -40 -28 -68t-68 -28h-192
+q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" />
+ <glyph glyph-name="ellipsis_vertical" unicode="" horiz-adv-x="384"
+d="M384 288v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 1312v-192q0 -40 -28 -68t-68 -28h-192
+q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" />
+ <glyph glyph-name="_303" unicode=""
+d="M512 256q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM863 162q-13 233 -176.5 396.5t-396.5 176.5q-14 1 -24 -9t-10 -23v-128q0 -13 8.5 -22t21.5 -10q154 -11 264 -121t121 -264q1 -13 10 -21.5t22 -8.5h128
+q13 0 23 10t9 24zM1247 161q-5 154 -56 297.5t-139.5 260t-205 205t-260 139.5t-297.5 56q-14 1 -23 -9q-10 -10 -10 -23v-128q0 -13 9 -22t22 -10q204 -7 378 -111.5t278.5 -278.5t111.5 -378q1 -13 10 -22t22 -9h128q13 0 23 10q11 9 9 23zM1536 1120v-960
+q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="play_sign" unicode=""
+d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1152 585q32 18 32 55t-32 55l-544 320q-31 19 -64 1q-32 -19 -32 -56v-640q0 -37 32 -56
+q16 -8 32 -8q17 0 32 9z" />
+ <glyph glyph-name="ticket" unicode="" horiz-adv-x="1792"
+d="M1024 1084l316 -316l-572 -572l-316 316zM813 105l618 618q19 19 19 45t-19 45l-362 362q-18 18 -45 18t-45 -18l-618 -618q-19 -19 -19 -45t19 -45l362 -362q18 -18 45 -18t45 18zM1702 742l-907 -908q-37 -37 -90.5 -37t-90.5 37l-126 126q56 56 56 136t-56 136
+t-136 56t-136 -56l-125 126q-37 37 -37 90.5t37 90.5l907 906q37 37 90.5 37t90.5 -37l125 -125q-56 -56 -56 -136t56 -136t136 -56t136 56l126 -125q37 -37 37 -90.5t-37 -90.5z" />
+ <glyph glyph-name="minus_sign_alt" unicode=""
+d="M1280 576v128q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h896q26 0 45 19t19 45zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5
+t84.5 -203.5z" />
+ <glyph glyph-name="check_minus" unicode="" horiz-adv-x="1408"
+d="M1152 736v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h832q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5
+t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="level_up" unicode="" horiz-adv-x="1024"
+d="M1018 933q-18 -37 -58 -37h-192v-864q0 -14 -9 -23t-23 -9h-704q-21 0 -29 18q-8 20 4 35l160 192q9 11 25 11h320v640h-192q-40 0 -58 37q-17 37 9 68l320 384q18 22 49 22t49 -22l320 -384q27 -32 9 -68z" />
+ <glyph glyph-name="level_down" unicode="" horiz-adv-x="1024"
+d="M32 1280h704q13 0 22.5 -9.5t9.5 -23.5v-863h192q40 0 58 -37t-9 -69l-320 -384q-18 -22 -49 -22t-49 22l-320 384q-26 31 -9 69q18 37 58 37h192v640h-320q-14 0 -25 11l-160 192q-13 14 -4 34q9 19 29 19z" />
+ <glyph glyph-name="check_sign" unicode=""
+d="M685 237l614 614q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-467 -467l-211 211q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l358 -358q19 -19 45 -19t45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5
+t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="edit_sign" unicode=""
+d="M404 428l152 -152l-52 -52h-56v96h-96v56zM818 818q14 -13 -3 -30l-291 -291q-17 -17 -30 -3q-14 13 3 30l291 291q17 17 30 3zM544 128l544 544l-288 288l-544 -544v-288h288zM1152 736l92 92q28 28 28 68t-28 68l-152 152q-28 28 -68 28t-68 -28l-92 -92zM1536 1120
+v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="_312" unicode=""
+d="M1280 608v480q0 26 -19 45t-45 19h-480q-42 0 -59 -39q-17 -41 14 -70l144 -144l-534 -534q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l534 534l144 -144q18 -19 45 -19q12 0 25 5q39 17 39 59zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960
+q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="share_sign" unicode=""
+d="M1005 435l352 352q19 19 19 45t-19 45l-352 352q-30 31 -69 14q-40 -17 -40 -59v-160q-119 0 -216 -19.5t-162.5 -51t-114 -79t-76.5 -95.5t-44.5 -109t-21.5 -111.5t-5 -110.5q0 -181 167 -404q11 -12 25 -12q7 0 13 3q22 9 19 33q-44 354 62 473q46 52 130 75.5
+t224 23.5v-160q0 -42 40 -59q12 -5 24 -5q26 0 45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="compass" unicode=""
+d="M640 448l256 128l-256 128v-256zM1024 1039v-542l-512 -256v542zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103
+t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="collapse" unicode=""
+d="M1145 861q18 -35 -5 -66l-320 -448q-19 -27 -52 -27t-52 27l-320 448q-23 31 -5 66q17 35 57 35h640q40 0 57 -35zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120
+v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="collapse_top" unicode=""
+d="M1145 419q-17 -35 -57 -35h-640q-40 0 -57 35q-18 35 5 66l320 448q19 27 52 27t52 -27l320 -448q23 -31 5 -66zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120v-960
+q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="_317" unicode=""
+d="M1088 640q0 -33 -27 -52l-448 -320q-31 -23 -66 -5q-35 17 -35 57v640q0 40 35 57q35 18 66 -5l448 -320q27 -19 27 -52zM1280 160v960q0 14 -9 23t-23 9h-960q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h960q14 0 23 9t9 23zM1536 1120v-960q0 -119 -84.5 -203.5
+t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="eur" unicode="" horiz-adv-x="1024"
+d="M976 229l35 -159q3 -12 -3 -22.5t-17 -14.5l-5 -1q-4 -2 -10.5 -3.5t-16 -4.5t-21.5 -5.5t-25.5 -5t-30 -5t-33.5 -4.5t-36.5 -3t-38.5 -1q-234 0 -409 130.5t-238 351.5h-95q-13 0 -22.5 9.5t-9.5 22.5v113q0 13 9.5 22.5t22.5 9.5h66q-2 57 1 105h-67q-14 0 -23 9
+t-9 23v114q0 14 9 23t23 9h98q67 210 243.5 338t400.5 128q102 0 194 -23q11 -3 20 -15q6 -11 3 -24l-43 -159q-3 -13 -14 -19.5t-24 -2.5l-4 1q-4 1 -11.5 2.5l-17.5 3.5t-22.5 3.5t-26 3t-29 2.5t-29.5 1q-126 0 -226 -64t-150 -176h468q16 0 25 -12q10 -12 7 -26
+l-24 -114q-5 -26 -32 -26h-488q-3 -37 0 -105h459q15 0 25 -12q9 -12 6 -27l-24 -112q-2 -11 -11 -18.5t-20 -7.5h-387q48 -117 149.5 -185.5t228.5 -68.5q18 0 36 1.5t33.5 3.5t29.5 4.5t24.5 5t18.5 4.5l12 3l5 2q13 5 26 -2q12 -7 15 -21z" />
+ <glyph glyph-name="gbp" unicode="" horiz-adv-x="1024"
+d="M1020 399v-367q0 -14 -9 -23t-23 -9h-956q-14 0 -23 9t-9 23v150q0 13 9.5 22.5t22.5 9.5h97v383h-95q-14 0 -23 9.5t-9 22.5v131q0 14 9 23t23 9h95v223q0 171 123.5 282t314.5 111q185 0 335 -125q9 -8 10 -20.5t-7 -22.5l-103 -127q-9 -11 -22 -12q-13 -2 -23 7
+q-5 5 -26 19t-69 32t-93 18q-85 0 -137 -47t-52 -123v-215h305q13 0 22.5 -9t9.5 -23v-131q0 -13 -9.5 -22.5t-22.5 -9.5h-305v-379h414v181q0 13 9 22.5t23 9.5h162q14 0 23 -9.5t9 -22.5z" />
+ <glyph glyph-name="usd" unicode="" horiz-adv-x="1024"
+d="M978 351q0 -153 -99.5 -263.5t-258.5 -136.5v-175q0 -14 -9 -23t-23 -9h-135q-13 0 -22.5 9.5t-9.5 22.5v175q-66 9 -127.5 31t-101.5 44.5t-74 48t-46.5 37.5t-17.5 18q-17 21 -2 41l103 135q7 10 23 12q15 2 24 -9l2 -2q113 -99 243 -125q37 -8 74 -8q81 0 142.5 43
+t61.5 122q0 28 -15 53t-33.5 42t-58.5 37.5t-66 32t-80 32.5q-39 16 -61.5 25t-61.5 26.5t-62.5 31t-56.5 35.5t-53.5 42.5t-43.5 49t-35.5 58t-21 66.5t-8.5 78q0 138 98 242t255 134v180q0 13 9.5 22.5t22.5 9.5h135q14 0 23 -9t9 -23v-176q57 -6 110.5 -23t87 -33.5
+t63.5 -37.5t39 -29t15 -14q17 -18 5 -38l-81 -146q-8 -15 -23 -16q-14 -3 -27 7q-3 3 -14.5 12t-39 26.5t-58.5 32t-74.5 26t-85.5 11.5q-95 0 -155 -43t-60 -111q0 -26 8.5 -48t29.5 -41.5t39.5 -33t56 -31t60.5 -27t70 -27.5q53 -20 81 -31.5t76 -35t75.5 -42.5t62 -50
+t53 -63.5t31.5 -76.5t13 -94z" />
+ <glyph glyph-name="inr" unicode="" horiz-adv-x="898"
+d="M898 1066v-102q0 -14 -9 -23t-23 -9h-168q-23 -144 -129 -234t-276 -110q167 -178 459 -536q14 -16 4 -34q-8 -18 -29 -18h-195q-16 0 -25 12q-306 367 -498 571q-9 9 -9 22v127q0 13 9.5 22.5t22.5 9.5h112q132 0 212.5 43t102.5 125h-427q-14 0 -23 9t-9 23v102
+q0 14 9 23t23 9h413q-57 113 -268 113h-145q-13 0 -22.5 9.5t-9.5 22.5v133q0 14 9 23t23 9h832q14 0 23 -9t9 -23v-102q0 -14 -9 -23t-23 -9h-233q47 -61 64 -144h171q14 0 23 -9t9 -23z" />
+ <glyph glyph-name="jpy" unicode="" horiz-adv-x="1027"
+d="M603 0h-172q-13 0 -22.5 9t-9.5 23v330h-288q-13 0 -22.5 9t-9.5 23v103q0 13 9.5 22.5t22.5 9.5h288v85h-288q-13 0 -22.5 9t-9.5 23v104q0 13 9.5 22.5t22.5 9.5h214l-321 578q-8 16 0 32q10 16 28 16h194q19 0 29 -18l215 -425q19 -38 56 -125q10 24 30.5 68t27.5 61
+l191 420q8 19 29 19h191q17 0 27 -16q9 -14 1 -31l-313 -579h215q13 0 22.5 -9.5t9.5 -22.5v-104q0 -14 -9.5 -23t-22.5 -9h-290v-85h290q13 0 22.5 -9.5t9.5 -22.5v-103q0 -14 -9.5 -23t-22.5 -9h-290v-330q0 -13 -9.5 -22.5t-22.5 -9.5z" />
+ <glyph glyph-name="rub" unicode="" horiz-adv-x="1280"
+d="M1043 971q0 100 -65 162t-171 62h-320v-448h320q106 0 171 62t65 162zM1280 971q0 -193 -126.5 -315t-326.5 -122h-340v-118h505q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-505v-192q0 -14 -9.5 -23t-22.5 -9h-167q-14 0 -23 9t-9 23v192h-224q-14 0 -23 9t-9 23v128
+q0 14 9 23t23 9h224v118h-224q-14 0 -23 9t-9 23v149q0 13 9 22.5t23 9.5h224v629q0 14 9 23t23 9h539q200 0 326.5 -122t126.5 -315z" />
+ <glyph glyph-name="krw" unicode="" horiz-adv-x="1792"
+d="M514 341l81 299h-159l75 -300q1 -1 1 -3t1 -3q0 1 0.5 3.5t0.5 3.5zM630 768l35 128h-292l32 -128h225zM822 768h139l-35 128h-70zM1271 340l78 300h-162l81 -299q0 -1 0.5 -3.5t1.5 -3.5q0 1 0.5 3t0.5 3zM1382 768l33 128h-297l34 -128h230zM1792 736v-64q0 -14 -9 -23
+t-23 -9h-213l-164 -616q-7 -24 -31 -24h-159q-24 0 -31 24l-166 616h-209l-167 -616q-7 -24 -31 -24h-159q-11 0 -19.5 7t-10.5 17l-160 616h-208q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h175l-33 128h-142q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h109l-89 344q-5 15 5 28
+q10 12 26 12h137q26 0 31 -24l90 -360h359l97 360q7 24 31 24h126q24 0 31 -24l98 -360h365l93 360q5 24 31 24h137q16 0 26 -12q10 -13 5 -28l-91 -344h111q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-145l-34 -128h179q14 0 23 -9t9 -23z" />
+ <glyph glyph-name="btc" unicode="" horiz-adv-x="1280"
+d="M1167 896q18 -182 -131 -258q117 -28 175 -103t45 -214q-7 -71 -32.5 -125t-64.5 -89t-97 -58.5t-121.5 -34.5t-145.5 -15v-255h-154v251q-80 0 -122 1v-252h-154v255q-18 0 -54 0.5t-55 0.5h-200l31 183h111q50 0 58 51v402h16q-6 1 -16 1v287q-13 68 -89 68h-111v164
+l212 -1q64 0 97 1v252h154v-247q82 2 122 2v245h154v-252q79 -7 140 -22.5t113 -45t82.5 -78t36.5 -114.5zM952 351q0 36 -15 64t-37 46t-57.5 30.5t-65.5 18.5t-74 9t-69 3t-64.5 -1t-47.5 -1v-338q8 0 37 -0.5t48 -0.5t53 1.5t58.5 4t57 8.5t55.5 14t47.5 21t39.5 30
+t24.5 40t9.5 51zM881 827q0 33 -12.5 58.5t-30.5 42t-48 28t-55 16.5t-61.5 8t-58 2.5t-54 -1t-39.5 -0.5v-307q5 0 34.5 -0.5t46.5 0t50 2t55 5.5t51.5 11t48.5 18.5t37 27t27 38.5t9 51z" />
+ <glyph glyph-name="file" unicode=""
+d="M1024 1024v472q22 -14 36 -28l408 -408q14 -14 28 -36h-472zM896 992q0 -40 28 -68t68 -28h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h800v-544z" />
+ <glyph glyph-name="file_text" unicode=""
+d="M1468 1060q14 -14 28 -36h-472v472q22 -14 36 -28zM992 896h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h800v-544q0 -40 28 -68t68 -28zM1152 160v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704
+q14 0 23 9t9 23zM1152 416v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1152 672v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23z" />
+ <glyph glyph-name="sort_by_alphabet" unicode="" horiz-adv-x="1664"
+d="M1191 1128h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1572 -23
+v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -11v-2l14 2q9 2 30 2h248v119h121zM1661 874v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162
+l230 -662h70z" />
+ <glyph glyph-name="_329" unicode="" horiz-adv-x="1664"
+d="M1191 104h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1661 -150
+v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162l230 -662h70zM1572 1001v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -10v-3l14 3q9 1 30 1h248
+v119h121z" />
+ <glyph glyph-name="sort_by_attributes" unicode="" horiz-adv-x="1792"
+d="M736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1792 -32v-192q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832
+q14 0 23 -9t9 -23zM1600 480v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1408 992v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1216 1504v-192q0 -14 -9 -23t-23 -9h-256
+q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23z" />
+ <glyph glyph-name="sort_by_attributes_alt" unicode="" horiz-adv-x="1792"
+d="M1216 -32v-192q0 -14 -9 -23t-23 -9h-256q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192
+q14 0 23 -9t9 -23zM1408 480v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1600 992v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1792 1504v-192q0 -14 -9 -23t-23 -9h-832
+q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832q14 0 23 -9t9 -23z" />
+ <glyph glyph-name="sort_by_order" unicode=""
+d="M1346 223q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23
+zM1486 165q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5
+t82 -252.5zM1456 882v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165z" />
+ <glyph glyph-name="sort_by_order_alt" unicode=""
+d="M1346 1247q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9
+t9 -23zM1456 -142v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165zM1486 1189q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13
+q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5t82 -252.5z" />
+ <glyph glyph-name="_334" unicode="" horiz-adv-x="1664"
+d="M256 192q0 26 -19 45t-45 19q-27 0 -45.5 -19t-18.5 -45q0 -27 18.5 -45.5t45.5 -18.5q26 0 45 18.5t19 45.5zM416 704v-640q0 -26 -19 -45t-45 -19h-288q-26 0 -45 19t-19 45v640q0 26 19 45t45 19h288q26 0 45 -19t19 -45zM1600 704q0 -86 -55 -149q15 -44 15 -76
+q3 -76 -43 -137q17 -56 0 -117q-15 -57 -54 -94q9 -112 -49 -181q-64 -76 -197 -78h-36h-76h-17q-66 0 -144 15.5t-121.5 29t-120.5 39.5q-123 43 -158 44q-26 1 -45 19.5t-19 44.5v641q0 25 18 43.5t43 20.5q24 2 76 59t101 121q68 87 101 120q18 18 31 48t17.5 48.5
+t13.5 60.5q7 39 12.5 61t19.5 52t34 50q19 19 45 19q46 0 82.5 -10.5t60 -26t40 -40.5t24 -45t12 -50t5 -45t0.5 -39q0 -38 -9.5 -76t-19 -60t-27.5 -56q-3 -6 -10 -18t-11 -22t-8 -24h277q78 0 135 -57t57 -135z" />
+ <glyph glyph-name="_335" unicode="" horiz-adv-x="1664"
+d="M256 960q0 -26 -19 -45t-45 -19q-27 0 -45.5 19t-18.5 45q0 27 18.5 45.5t45.5 18.5q26 0 45 -18.5t19 -45.5zM416 448v640q0 26 -19 45t-45 19h-288q-26 0 -45 -19t-19 -45v-640q0 -26 19 -45t45 -19h288q26 0 45 19t19 45zM1545 597q55 -61 55 -149q-1 -78 -57.5 -135
+t-134.5 -57h-277q4 -14 8 -24t11 -22t10 -18q18 -37 27 -57t19 -58.5t10 -76.5q0 -24 -0.5 -39t-5 -45t-12 -50t-24 -45t-40 -40.5t-60 -26t-82.5 -10.5q-26 0 -45 19q-20 20 -34 50t-19.5 52t-12.5 61q-9 42 -13.5 60.5t-17.5 48.5t-31 48q-33 33 -101 120q-49 64 -101 121
+t-76 59q-25 2 -43 20.5t-18 43.5v641q0 26 19 44.5t45 19.5q35 1 158 44q77 26 120.5 39.5t121.5 29t144 15.5h17h76h36q133 -2 197 -78q58 -69 49 -181q39 -37 54 -94q17 -61 0 -117q46 -61 43 -137q0 -32 -15 -76z" />
+ <glyph glyph-name="youtube_sign" unicode=""
+d="M919 233v157q0 50 -29 50q-17 0 -33 -16v-224q16 -16 33 -16q29 0 29 49zM1103 355h66v34q0 51 -33 51t-33 -51v-34zM532 621v-70h-80v-423h-74v423h-78v70h232zM733 495v-367h-67v40q-39 -45 -76 -45q-33 0 -42 28q-6 17 -6 54v290h66v-270q0 -24 1 -26q1 -15 15 -15
+q20 0 42 31v280h67zM985 384v-146q0 -52 -7 -73q-12 -42 -53 -42q-35 0 -68 41v-36h-67v493h67v-161q32 40 68 40q41 0 53 -42q7 -21 7 -74zM1236 255v-9q0 -29 -2 -43q-3 -22 -15 -40q-27 -40 -80 -40q-52 0 -81 38q-21 27 -21 86v129q0 59 20 86q29 38 80 38t78 -38
+q21 -29 21 -86v-76h-133v-65q0 -51 34 -51q24 0 30 26q0 1 0.5 7t0.5 16.5v21.5h68zM785 1079v-156q0 -51 -32 -51t-32 51v156q0 52 32 52t32 -52zM1318 366q0 177 -19 260q-10 44 -43 73.5t-76 34.5q-136 15 -412 15q-275 0 -411 -15q-44 -5 -76.5 -34.5t-42.5 -73.5
+q-20 -87 -20 -260q0 -176 20 -260q10 -43 42.5 -73t75.5 -35q137 -15 412 -15t412 15q43 5 75.5 35t42.5 73q20 84 20 260zM563 1017l90 296h-75l-51 -195l-53 195h-78q7 -23 23 -69l24 -69q35 -103 46 -158v-201h74v201zM852 936v130q0 58 -21 87q-29 38 -78 38
+q-51 0 -78 -38q-21 -29 -21 -87v-130q0 -58 21 -87q27 -38 78 -38q49 0 78 38q21 27 21 87zM1033 816h67v370h-67v-283q-22 -31 -42 -31q-15 0 -16 16q-1 2 -1 26v272h-67v-293q0 -37 6 -55q11 -27 43 -27q36 0 77 45v-40zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5
+h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="youtube" unicode=""
+d="M971 292v-211q0 -67 -39 -67q-23 0 -45 22v301q22 22 45 22q39 0 39 -67zM1309 291v-46h-90v46q0 68 45 68t45 -68zM343 509h107v94h-312v-94h105v-569h100v569zM631 -60h89v494h-89v-378q-30 -42 -57 -42q-18 0 -21 21q-1 3 -1 35v364h-89v-391q0 -49 8 -73
+q12 -37 58 -37q48 0 102 61v-54zM1060 88v197q0 73 -9 99q-17 56 -71 56q-50 0 -93 -54v217h-89v-663h89v48q45 -55 93 -55q54 0 71 55q9 27 9 100zM1398 98v13h-91q0 -51 -2 -61q-7 -36 -40 -36q-46 0 -46 69v87h179v103q0 79 -27 116q-39 51 -106 51q-68 0 -107 -51
+q-28 -37 -28 -116v-173q0 -79 29 -116q39 -51 108 -51q72 0 108 53q18 27 21 54q2 9 2 58zM790 1011v210q0 69 -43 69t-43 -69v-210q0 -70 43 -70t43 70zM1509 260q0 -234 -26 -350q-14 -59 -58 -99t-102 -46q-184 -21 -555 -21t-555 21q-58 6 -102.5 46t-57.5 99
+q-26 112 -26 350q0 234 26 350q14 59 58 99t103 47q183 20 554 20t555 -20q58 -7 102.5 -47t57.5 -99q26 -112 26 -350zM511 1536h102l-121 -399v-271h-100v271q-14 74 -61 212q-37 103 -65 187h106l71 -263zM881 1203v-175q0 -81 -28 -118q-38 -51 -106 -51q-67 0 -105 51
+q-28 38 -28 118v175q0 80 28 117q38 51 105 51q68 0 106 -51q28 -37 28 -117zM1216 1365v-499h-91v55q-53 -62 -103 -62q-46 0 -59 37q-8 24 -8 75v394h91v-367q0 -33 1 -35q3 -22 21 -22q27 0 57 43v381h91z" />
+ <glyph glyph-name="xing" unicode="" horiz-adv-x="1408"
+d="M597 869q-10 -18 -257 -456q-27 -46 -65 -46h-239q-21 0 -31 17t0 36l253 448q1 0 0 1l-161 279q-12 22 -1 37q9 15 32 15h239q40 0 66 -45zM1403 1511q11 -16 0 -37l-528 -934v-1l336 -615q11 -20 1 -37q-10 -15 -32 -15h-239q-42 0 -66 45l-339 622q18 32 531 942
+q25 45 64 45h241q22 0 31 -15z" />
+ <glyph glyph-name="xing_sign" unicode=""
+d="M685 771q0 1 -126 222q-21 34 -52 34h-184q-18 0 -26 -11q-7 -12 1 -29l125 -216v-1l-196 -346q-9 -14 0 -28q8 -13 24 -13h185q31 0 50 36zM1309 1268q-7 12 -24 12h-187q-30 0 -49 -35l-411 -729q1 -2 262 -481q20 -35 52 -35h184q18 0 25 12q8 13 -1 28l-260 476v1
+l409 723q8 16 0 28zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="youtube_play" unicode="" horiz-adv-x="1792"
+d="M711 408l484 250l-484 253v-503zM896 1270q168 0 324.5 -4.5t229.5 -9.5l73 -4q1 0 17 -1.5t23 -3t23.5 -4.5t28.5 -8t28 -13t31 -19.5t29 -26.5q6 -6 15.5 -18.5t29 -58.5t26.5 -101q8 -64 12.5 -136.5t5.5 -113.5v-40v-136q1 -145 -18 -290q-7 -55 -25 -99.5t-32 -61.5
+l-14 -17q-14 -15 -29 -26.5t-31 -19t-28 -12.5t-28.5 -8t-24 -4.5t-23 -3t-16.5 -1.5q-251 -19 -627 -19q-207 2 -359.5 6.5t-200.5 7.5l-49 4l-36 4q-36 5 -54.5 10t-51 21t-56.5 41q-6 6 -15.5 18.5t-29 58.5t-26.5 101q-8 64 -12.5 136.5t-5.5 113.5v40v136
+q-1 145 18 290q7 55 25 99.5t32 61.5l14 17q14 15 29 26.5t31 19.5t28 13t28.5 8t23.5 4.5t23 3t17 1.5q251 18 627 18z" />
+ <glyph glyph-name="dropbox" unicode="" horiz-adv-x="1792"
+d="M402 829l494 -305l-342 -285l-490 319zM1388 274v-108l-490 -293v-1l-1 1l-1 -1v1l-489 293v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284zM554 1418l342 -285l-494 -304l-338 270zM1390 829l338 -271l-489 -319l-343 285zM1239 1418l489 -319l-338 -270l-494 304z" />
+ <glyph glyph-name="stackexchange" unicode=""
+d="M1289 -96h-1118v480h-160v-640h1438v640h-160v-480zM347 428l33 157l783 -165l-33 -156zM450 802l67 146l725 -339l-67 -145zM651 1158l102 123l614 -513l-102 -123zM1048 1536l477 -641l-128 -96l-477 641zM330 65v159h800v-159h-800z" />
+ <glyph glyph-name="instagram" unicode=""
+d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1162 640q0 -164 -115 -279t-279 -115t-279 115t-115 279t115 279t279 115t279 -115t115 -279zM1270 1050q0 -38 -27 -65t-65 -27t-65 27t-27 65t27 65t65 27t65 -27t27 -65zM768 1270
+q-7 0 -76.5 0.5t-105.5 0t-96.5 -3t-103 -10t-71.5 -18.5q-50 -20 -88 -58t-58 -88q-11 -29 -18.5 -71.5t-10 -103t-3 -96.5t0 -105.5t0.5 -76.5t-0.5 -76.5t0 -105.5t3 -96.5t10 -103t18.5 -71.5q20 -50 58 -88t88 -58q29 -11 71.5 -18.5t103 -10t96.5 -3t105.5 0t76.5 0.5
+t76.5 -0.5t105.5 0t96.5 3t103 10t71.5 18.5q50 20 88 58t58 88q11 29 18.5 71.5t10 103t3 96.5t0 105.5t-0.5 76.5t0.5 76.5t0 105.5t-3 96.5t-10 103t-18.5 71.5q-20 50 -58 88t-88 58q-29 11 -71.5 18.5t-103 10t-96.5 3t-105.5 0t-76.5 -0.5zM1536 640q0 -229 -5 -317
+q-10 -208 -124 -322t-322 -124q-88 -5 -317 -5t-317 5q-208 10 -322 124t-124 322q-5 88 -5 317t5 317q10 208 124 322t322 124q88 5 317 5t317 -5q208 -10 322 -124t124 -322q5 -88 5 -317z" />
+ <glyph glyph-name="flickr" unicode=""
+d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM698 640q0 88 -62 150t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150zM1262 640q0 88 -62 150
+t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150z" />
+ <glyph glyph-name="adn" unicode=""
+d="M768 914l201 -306h-402zM1133 384h94l-459 691l-459 -691h94l104 160h522zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="f171" unicode="" horiz-adv-x="1408"
+d="M815 677q8 -63 -50.5 -101t-111.5 -6q-39 17 -53.5 58t-0.5 82t52 58q36 18 72.5 12t64 -35.5t27.5 -67.5zM926 698q-14 107 -113 164t-197 13q-63 -28 -100.5 -88.5t-34.5 -129.5q4 -91 77.5 -155t165.5 -56q91 8 152 84t50 168zM1165 1240q-20 27 -56 44.5t-58 22
+t-71 12.5q-291 47 -566 -2q-43 -7 -66 -12t-55 -22t-50 -43q30 -28 76 -45.5t73.5 -22t87.5 -11.5q228 -29 448 -1q63 8 89.5 12t72.5 21.5t75 46.5zM1222 205q-8 -26 -15.5 -76.5t-14 -84t-28.5 -70t-58 -56.5q-86 -48 -189.5 -71.5t-202 -22t-201.5 18.5q-46 8 -81.5 18
+t-76.5 27t-73 43.5t-52 61.5q-25 96 -57 292l6 16l18 9q223 -148 506.5 -148t507.5 148q21 -6 24 -23t-5 -45t-8 -37zM1403 1166q-26 -167 -111 -655q-5 -30 -27 -56t-43.5 -40t-54.5 -31q-252 -126 -610 -88q-248 27 -394 139q-15 12 -25.5 26.5t-17 35t-9 34t-6 39.5
+t-5.5 35q-9 50 -26.5 150t-28 161.5t-23.5 147.5t-22 158q3 26 17.5 48.5t31.5 37.5t45 30t46 22.5t48 18.5q125 46 313 64q379 37 676 -50q155 -46 215 -122q16 -20 16.5 -51t-5.5 -54z" />
+ <glyph glyph-name="bitbucket_sign" unicode=""
+d="M848 666q0 43 -41 66t-77 1q-43 -20 -42.5 -72.5t43.5 -70.5q39 -23 81 4t36 72zM928 682q8 -66 -36 -121t-110 -61t-119 40t-56 113q-2 49 25.5 93t72.5 64q70 31 141.5 -10t81.5 -118zM1100 1073q-20 -21 -53.5 -34t-53 -16t-63.5 -8q-155 -20 -324 0q-44 6 -63 9.5
+t-52.5 16t-54.5 32.5q13 19 36 31t40 15.5t47 8.5q198 35 408 1q33 -5 51 -8.5t43 -16t39 -31.5zM1142 327q0 7 5.5 26.5t3 32t-17.5 16.5q-161 -106 -365 -106t-366 106l-12 -6l-5 -12q26 -154 41 -210q47 -81 204 -108q249 -46 428 53q34 19 49 51.5t22.5 85.5t12.5 71z
+M1272 1020q9 53 -8 75q-43 55 -155 88q-216 63 -487 36q-132 -12 -226 -46q-38 -15 -59.5 -25t-47 -34t-29.5 -54q8 -68 19 -138t29 -171t24 -137q1 -5 5 -31t7 -36t12 -27t22 -28q105 -80 284 -100q259 -28 440 63q24 13 39.5 23t31 29t19.5 40q48 267 80 473zM1536 1120
+v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="tumblr" unicode="" horiz-adv-x="1024"
+d="M944 207l80 -237q-23 -35 -111 -66t-177 -32q-104 -2 -190.5 26t-142.5 74t-95 106t-55.5 120t-16.5 118v544h-168v215q72 26 129 69.5t91 90t58 102t34 99t15 88.5q1 5 4.5 8.5t7.5 3.5h244v-424h333v-252h-334v-518q0 -30 6.5 -56t22.5 -52.5t49.5 -41.5t81.5 -14
+q78 2 134 29z" />
+ <glyph glyph-name="tumblr_sign" unicode=""
+d="M1136 75l-62 183q-44 -22 -103 -22q-36 -1 -62 10.5t-38.5 31.5t-17.5 40.5t-5 43.5v398h257v194h-256v326h-188q-8 0 -9 -10q-5 -44 -17.5 -87t-39 -95t-77 -95t-118.5 -68v-165h130v-418q0 -57 21.5 -115t65 -111t121 -85.5t176.5 -30.5q69 1 136.5 25t85.5 50z
+M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="long_arrow_down" unicode="" horiz-adv-x="768"
+d="M765 237q8 -19 -5 -35l-350 -384q-10 -10 -23 -10q-14 0 -24 10l-355 384q-13 16 -5 35q9 19 29 19h224v1248q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1248h224q21 0 29 -19z" />
+ <glyph glyph-name="long_arrow_up" unicode="" horiz-adv-x="768"
+d="M765 1043q-9 -19 -29 -19h-224v-1248q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1248h-224q-21 0 -29 19t5 35l350 384q10 10 23 10q14 0 24 -10l355 -384q13 -16 5 -35z" />
+ <glyph glyph-name="long_arrow_left" unicode="" horiz-adv-x="1792"
+d="M1792 736v-192q0 -14 -9 -23t-23 -9h-1248v-224q0 -21 -19 -29t-35 5l-384 350q-10 10 -10 23q0 14 10 24l384 354q16 14 35 6q19 -9 19 -29v-224h1248q14 0 23 -9t9 -23z" />
+ <glyph glyph-name="long_arrow_right" unicode="" horiz-adv-x="1792"
+d="M1728 643q0 -14 -10 -24l-384 -354q-16 -14 -35 -6q-19 9 -19 29v224h-1248q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h1248v224q0 21 19 29t35 -5l384 -350q10 -10 10 -23z" />
+ <glyph glyph-name="apple" unicode="" horiz-adv-x="1408"
+d="M1393 321q-39 -125 -123 -250q-129 -196 -257 -196q-49 0 -140 32q-86 32 -151 32q-61 0 -142 -33q-81 -34 -132 -34q-152 0 -301 259q-147 261 -147 503q0 228 113 374q113 144 284 144q72 0 177 -30q104 -30 138 -30q45 0 143 34q102 34 173 34q119 0 213 -65
+q52 -36 104 -100q-79 -67 -114 -118q-65 -94 -65 -207q0 -124 69 -223t158 -126zM1017 1494q0 -61 -29 -136q-30 -75 -93 -138q-54 -54 -108 -72q-37 -11 -104 -17q3 149 78 257q74 107 250 148q1 -3 2.5 -11t2.5 -11q0 -4 0.5 -10t0.5 -10z" />
+ <glyph glyph-name="windows" unicode="" horiz-adv-x="1664"
+d="M682 530v-651l-682 94v557h682zM682 1273v-659h-682v565zM1664 530v-786l-907 125v661h907zM1664 1408v-794h-907v669z" />
+ <glyph glyph-name="android" unicode="" horiz-adv-x="1408"
+d="M493 1053q16 0 27.5 11.5t11.5 27.5t-11.5 27.5t-27.5 11.5t-27 -11.5t-11 -27.5t11 -27.5t27 -11.5zM915 1053q16 0 27 11.5t11 27.5t-11 27.5t-27 11.5t-27.5 -11.5t-11.5 -27.5t11.5 -27.5t27.5 -11.5zM103 869q42 0 72 -30t30 -72v-430q0 -43 -29.5 -73t-72.5 -30
+t-73 30t-30 73v430q0 42 30 72t73 30zM1163 850v-666q0 -46 -32 -78t-77 -32h-75v-227q0 -43 -30 -73t-73 -30t-73 30t-30 73v227h-138v-227q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73l-1 227h-74q-46 0 -78 32t-32 78v666h918zM931 1255q107 -55 171 -153.5t64 -215.5
+h-925q0 117 64 215.5t172 153.5l-71 131q-7 13 5 20q13 6 20 -6l72 -132q95 42 201 42t201 -42l72 132q7 12 20 6q12 -7 5 -20zM1408 767v-430q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73v430q0 43 30 72.5t72 29.5q43 0 73 -29.5t30 -72.5z" />
+ <glyph glyph-name="linux" unicode=""
+d="M663 1125q-11 -1 -15.5 -10.5t-8.5 -9.5q-5 -1 -5 5q0 12 19 15h10zM750 1111q-4 -1 -11.5 6.5t-17.5 4.5q24 11 32 -2q3 -6 -3 -9zM399 684q-4 1 -6 -3t-4.5 -12.5t-5.5 -13.5t-10 -13q-10 -11 -1 -12q4 -1 12.5 7t12.5 18q1 3 2 7t2 6t1.5 4.5t0.5 4v3t-1 2.5t-3 2z
+M1254 325q0 18 -55 42q4 15 7.5 27.5t5 26t3 21.5t0.5 22.5t-1 19.5t-3.5 22t-4 20.5t-5 25t-5.5 26.5q-10 48 -47 103t-72 75q24 -20 57 -83q87 -162 54 -278q-11 -40 -50 -42q-31 -4 -38.5 18.5t-8 83.5t-11.5 107q-9 39 -19.5 69t-19.5 45.5t-15.5 24.5t-13 15t-7.5 7
+q-14 62 -31 103t-29.5 56t-23.5 33t-15 40q-4 21 6 53.5t4.5 49.5t-44.5 25q-15 3 -44.5 18t-35.5 16q-8 1 -11 26t8 51t36 27q37 3 51 -30t4 -58q-11 -19 -2 -26.5t30 -0.5q13 4 13 36v37q-5 30 -13.5 50t-21 30.5t-23.5 15t-27 7.5q-107 -8 -89 -134q0 -15 -1 -15
+q-9 9 -29.5 10.5t-33 -0.5t-15.5 5q1 57 -16 90t-45 34q-27 1 -41.5 -27.5t-16.5 -59.5q-1 -15 3.5 -37t13 -37.5t15.5 -13.5q10 3 16 14q4 9 -7 8q-7 0 -15.5 14.5t-9.5 33.5q-1 22 9 37t34 14q17 0 27 -21t9.5 -39t-1.5 -22q-22 -15 -31 -29q-8 -12 -27.5 -23.5
+t-20.5 -12.5q-13 -14 -15.5 -27t7.5 -18q14 -8 25 -19.5t16 -19t18.5 -13t35.5 -6.5q47 -2 102 15q2 1 23 7t34.5 10.5t29.5 13t21 17.5q9 14 20 8q5 -3 6.5 -8.5t-3 -12t-16.5 -9.5q-20 -6 -56.5 -21.5t-45.5 -19.5q-44 -19 -70 -23q-25 -5 -79 2q-10 2 -9 -2t17 -19
+q25 -23 67 -22q17 1 36 7t36 14t33.5 17.5t30 17t24.5 12t17.5 2.5t8.5 -11q0 -2 -1 -4.5t-4 -5t-6 -4.5t-8.5 -5t-9 -4.5t-10 -5t-9.5 -4.5q-28 -14 -67.5 -44t-66.5 -43t-49 -1q-21 11 -63 73q-22 31 -25 22q-1 -3 -1 -10q0 -25 -15 -56.5t-29.5 -55.5t-21 -58t11.5 -63
+q-23 -6 -62.5 -90t-47.5 -141q-2 -18 -1.5 -69t-5.5 -59q-8 -24 -29 -3q-32 31 -36 94q-2 28 4 56q4 19 -1 18q-2 -1 -4 -5q-36 -65 10 -166q5 -12 25 -28t24 -20q20 -23 104 -90.5t93 -76.5q16 -15 17.5 -38t-14 -43t-45.5 -23q8 -15 29 -44.5t28 -54t7 -70.5q46 24 7 92
+q-4 8 -10.5 16t-9.5 12t-2 6q3 5 13 9.5t20 -2.5q46 -52 166 -36q133 15 177 87q23 38 34 30q12 -6 10 -52q-1 -25 -23 -92q-9 -23 -6 -37.5t24 -15.5q3 19 14.5 77t13.5 90q2 21 -6.5 73.5t-7.5 97t23 70.5q15 18 51 18q1 37 34.5 53t72.5 10.5t60 -22.5zM626 1152
+q3 17 -2.5 30t-11.5 15q-9 2 -9 -7q2 -5 5 -6q10 0 7 -15q-3 -20 8 -20q3 0 3 3zM1045 955q-2 8 -6.5 11.5t-13 5t-14.5 5.5q-5 3 -9.5 8t-7 8t-5.5 6.5t-4 4t-4 -1.5q-14 -16 7 -43.5t39 -31.5q9 -1 14.5 8t3.5 20zM867 1168q0 11 -5 19.5t-11 12.5t-9 3q-6 0 -8 -2t0 -4
+t5 -3q14 -4 18 -31q0 -3 8 2q2 2 2 3zM921 1401q0 2 -2.5 5t-9 7t-9.5 6q-15 15 -24 15q-9 -1 -11.5 -7.5t-1 -13t-0.5 -12.5q-1 -4 -6 -10.5t-6 -9t3 -8.5q4 -3 8 0t11 9t15 9q1 1 9 1t15 2t9 7zM1486 60q20 -12 31 -24.5t12 -24t-2.5 -22.5t-15.5 -22t-23.5 -19.5
+t-30 -18.5t-31.5 -16.5t-32 -15.5t-27 -13q-38 -19 -85.5 -56t-75.5 -64q-17 -16 -68 -19.5t-89 14.5q-18 9 -29.5 23.5t-16.5 25.5t-22 19.5t-47 9.5q-44 1 -130 1q-19 0 -57 -1.5t-58 -2.5q-44 -1 -79.5 -15t-53.5 -30t-43.5 -28.5t-53.5 -11.5q-29 1 -111 31t-146 43
+q-19 4 -51 9.5t-50 9t-39.5 9.5t-33.5 14.5t-17 19.5q-10 23 7 66.5t18 54.5q1 16 -4 40t-10 42.5t-4.5 36.5t10.5 27q14 12 57 14t60 12q30 18 42 35t12 51q21 -73 -32 -106q-32 -20 -83 -15q-34 3 -43 -10q-13 -15 5 -57q2 -6 8 -18t8.5 -18t4.5 -17t1 -22q0 -15 -17 -49
+t-14 -48q3 -17 37 -26q20 -6 84.5 -18.5t99.5 -20.5q24 -6 74 -22t82.5 -23t55.5 -4q43 6 64.5 28t23 48t-7.5 58.5t-19 52t-20 36.5q-121 190 -169 242q-68 74 -113 40q-11 -9 -15 15q-3 16 -2 38q1 29 10 52t24 47t22 42q8 21 26.5 72t29.5 78t30 61t39 54
+q110 143 124 195q-12 112 -16 310q-2 90 24 151.5t106 104.5q39 21 104 21q53 1 106 -13.5t89 -41.5q57 -42 91.5 -121.5t29.5 -147.5q-5 -95 30 -214q34 -113 133 -218q55 -59 99.5 -163t59.5 -191q8 -49 5 -84.5t-12 -55.5t-20 -22q-10 -2 -23.5 -19t-27 -35.5
+t-40.5 -33.5t-61 -14q-18 1 -31.5 5t-22.5 13.5t-13.5 15.5t-11.5 20.5t-9 19.5q-22 37 -41 30t-28 -49t7 -97q20 -70 1 -195q-10 -65 18 -100.5t73 -33t85 35.5q59 49 89.5 66.5t103.5 42.5q53 18 77 36.5t18.5 34.5t-25 28.5t-51.5 23.5q-33 11 -49.5 48t-15 72.5
+t15.5 47.5q1 -31 8 -56.5t14.5 -40.5t20.5 -28.5t21 -19t21.5 -13t16.5 -9.5z" />
+ <glyph glyph-name="dribble" unicode=""
+d="M1024 36q-42 241 -140 498h-2l-2 -1q-16 -6 -43 -16.5t-101 -49t-137 -82t-131 -114.5t-103 -148l-15 11q184 -150 418 -150q132 0 256 52zM839 643q-21 49 -53 111q-311 -93 -673 -93q-1 -7 -1 -21q0 -124 44 -236.5t124 -201.5q50 89 123.5 166.5t142.5 124.5t130.5 81
+t99.5 48l37 13q4 1 13 3.5t13 4.5zM732 855q-120 213 -244 378q-138 -65 -234 -186t-128 -272q302 0 606 80zM1416 536q-210 60 -409 29q87 -239 128 -469q111 75 185 189.5t96 250.5zM611 1277q-1 0 -2 -1q1 1 2 1zM1201 1132q-185 164 -433 164q-76 0 -155 -19
+q131 -170 246 -382q69 26 130 60.5t96.5 61.5t65.5 57t37.5 40.5zM1424 647q-3 232 -149 410l-1 -1q-9 -12 -19 -24.5t-43.5 -44.5t-71 -60.5t-100 -65t-131.5 -64.5q25 -53 44 -95q2 -5 6.5 -17t7.5 -17q36 5 74.5 7t73.5 2t69 -1.5t64 -4t56.5 -5.5t48 -6.5t36.5 -6
+t25 -4.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="skype" unicode=""
+d="M1173 473q0 50 -19.5 91.5t-48.5 68.5t-73 49t-82.5 34t-87.5 23l-104 24q-30 7 -44 10.5t-35 11.5t-30 16t-16.5 21t-7.5 30q0 77 144 77q43 0 77 -12t54 -28.5t38 -33.5t40 -29t48 -12q47 0 75.5 32t28.5 77q0 55 -56 99.5t-142 67.5t-182 23q-68 0 -132 -15.5
+t-119.5 -47t-89 -87t-33.5 -128.5q0 -61 19 -106.5t56 -75.5t80 -48.5t103 -32.5l146 -36q90 -22 112 -36q32 -20 32 -60q0 -39 -40 -64.5t-105 -25.5q-51 0 -91.5 16t-65 38.5t-45.5 45t-46 38.5t-54 16q-50 0 -75.5 -30t-25.5 -75q0 -92 122 -157.5t291 -65.5
+q73 0 140 18.5t122.5 53.5t88.5 93.5t33 131.5zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5q-130 0 -234 80q-77 -16 -150 -16q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5q0 73 16 150q-80 104 -80 234q0 159 112.5 271.5t271.5 112.5q130 0 234 -80
+q77 16 150 16q143 0 273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -73 -16 -150q80 -104 80 -234z" />
+ <glyph glyph-name="foursquare" unicode="" horiz-adv-x="1280"
+d="M1000 1102l37 194q5 23 -9 40t-35 17h-712q-23 0 -38.5 -17t-15.5 -37v-1101q0 -7 6 -1l291 352q23 26 38 33.5t48 7.5h239q22 0 37 14.5t18 29.5q24 130 37 191q4 21 -11.5 40t-36.5 19h-294q-29 0 -48 19t-19 48v42q0 29 19 47.5t48 18.5h346q18 0 35 13.5t20 29.5z
+M1227 1324q-15 -73 -53.5 -266.5t-69.5 -350t-35 -173.5q-6 -22 -9 -32.5t-14 -32.5t-24.5 -33t-38.5 -21t-58 -10h-271q-13 0 -22 -10q-8 -9 -426 -494q-22 -25 -58.5 -28.5t-48.5 5.5q-55 22 -55 98v1410q0 55 38 102.5t120 47.5h888q95 0 127 -53t10 -159zM1227 1324
+l-158 -790q4 17 35 173.5t69.5 350t53.5 266.5z" />
+ <glyph glyph-name="trello" unicode=""
+d="M704 192v1024q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-1024q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1376 576v640q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-640q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408
+q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="female" unicode="" horiz-adv-x="1280"
+d="M1280 480q0 -40 -28 -68t-68 -28q-51 0 -80 43l-227 341h-45v-132l247 -411q9 -15 9 -33q0 -26 -19 -45t-45 -19h-192v-272q0 -46 -33 -79t-79 -33h-160q-46 0 -79 33t-33 79v272h-192q-26 0 -45 19t-19 45q0 18 9 33l247 411v132h-45l-227 -341q-29 -43 -80 -43
+q-40 0 -68 28t-28 68q0 29 16 53l256 384q73 107 176 107h384q103 0 176 -107l256 -384q16 -24 16 -53zM864 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
+ <glyph glyph-name="male" unicode="" horiz-adv-x="1024"
+d="M1024 832v-416q0 -40 -28 -68t-68 -28t-68 28t-28 68v352h-64v-912q0 -46 -33 -79t-79 -33t-79 33t-33 79v464h-64v-464q0 -46 -33 -79t-79 -33t-79 33t-33 79v912h-64v-352q0 -40 -28 -68t-68 -28t-68 28t-28 68v416q0 80 56 136t136 56h640q80 0 136 -56t56 -136z
+M736 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
+ <glyph glyph-name="gittip" unicode=""
+d="M773 234l350 473q16 22 24.5 59t-6 85t-61.5 79q-40 26 -83 25.5t-73.5 -17.5t-54.5 -45q-36 -40 -96 -40q-59 0 -95 40q-24 28 -54.5 45t-73.5 17.5t-84 -25.5q-46 -31 -60.5 -79t-6 -85t24.5 -59zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103
+t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="sun" unicode="" horiz-adv-x="1792"
+d="M1472 640q0 117 -45.5 223.5t-123 184t-184 123t-223.5 45.5t-223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5t45.5 -223.5t123 -184t184 -123t223.5 -45.5t223.5 45.5t184 123t123 184t45.5 223.5zM1748 363q-4 -15 -20 -20l-292 -96v-306q0 -16 -13 -26q-15 -10 -29 -4
+l-292 94l-180 -248q-10 -13 -26 -13t-26 13l-180 248l-292 -94q-14 -6 -29 4q-13 10 -13 26v306l-292 96q-16 5 -20 20q-5 17 4 29l180 248l-180 248q-9 13 -4 29q4 15 20 20l292 96v306q0 16 13 26q15 10 29 4l292 -94l180 248q9 12 26 12t26 -12l180 -248l292 94
+q14 6 29 -4q13 -10 13 -26v-306l292 -96q16 -5 20 -20q5 -16 -4 -29l-180 -248l180 -248q9 -12 4 -29z" />
+ <glyph glyph-name="_366" unicode=""
+d="M1262 233q-54 -9 -110 -9q-182 0 -337 90t-245 245t-90 337q0 192 104 357q-201 -60 -328.5 -229t-127.5 -384q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51q144 0 273.5 61.5t220.5 171.5zM1465 318q-94 -203 -283.5 -324.5t-413.5 -121.5q-156 0 -298 61
+t-245 164t-164 245t-61 298q0 153 57.5 292.5t156 241.5t235.5 164.5t290 68.5q44 2 61 -39q18 -41 -15 -72q-86 -78 -131.5 -181.5t-45.5 -218.5q0 -148 73 -273t198 -198t273 -73q118 0 228 51q41 18 72 -13q14 -14 17.5 -34t-4.5 -38z" />
+ <glyph glyph-name="archive" unicode="" horiz-adv-x="1792"
+d="M1088 704q0 26 -19 45t-45 19h-256q-26 0 -45 -19t-19 -45t19 -45t45 -19h256q26 0 45 19t19 45zM1664 896v-960q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v960q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1728 1344v-256q0 -26 -19 -45t-45 -19h-1536
+q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1536q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="bug" unicode="" horiz-adv-x="1664"
+d="M1632 576q0 -26 -19 -45t-45 -19h-224q0 -171 -67 -290l208 -209q19 -19 19 -45t-19 -45q-18 -19 -45 -19t-45 19l-198 197q-5 -5 -15 -13t-42 -28.5t-65 -36.5t-82 -29t-97 -13v896h-128v-896q-51 0 -101.5 13.5t-87 33t-66 39t-43.5 32.5l-15 14l-183 -207
+q-20 -21 -48 -21q-24 0 -43 16q-19 18 -20.5 44.5t15.5 46.5l202 227q-58 114 -58 274h-224q-26 0 -45 19t-19 45t19 45t45 19h224v294l-173 173q-19 19 -19 45t19 45t45 19t45 -19l173 -173h844l173 173q19 19 45 19t45 -19t19 -45t-19 -45l-173 -173v-294h224q26 0 45 -19
+t19 -45zM1152 1152h-640q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5z" />
+ <glyph glyph-name="vk" unicode="" horiz-adv-x="1920"
+d="M1917 1016q23 -64 -150 -294q-24 -32 -65 -85q-40 -51 -55 -72t-30.5 -49.5t-12 -42t13 -34.5t32.5 -43t57 -53q4 -2 5 -4q141 -131 191 -221q3 -5 6.5 -12.5t7 -26.5t-0.5 -34t-25 -27.5t-59 -12.5l-256 -4q-24 -5 -56 5t-52 22l-20 12q-30 21 -70 64t-68.5 77.5t-61 58
+t-56.5 15.5q-3 -1 -8 -3.5t-17 -14.5t-21.5 -29.5t-17 -52t-6.5 -77.5q0 -15 -3.5 -27.5t-7.5 -18.5l-4 -5q-18 -19 -53 -22h-115q-71 -4 -146 16.5t-131.5 53t-103 66t-70.5 57.5l-25 24q-10 10 -27.5 30t-71.5 91t-106 151t-122.5 211t-130.5 272q-6 16 -6 27t3 16l4 6
+q15 19 57 19l274 2q12 -2 23 -6.5t16 -8.5l5 -3q16 -11 24 -32q20 -50 46 -103.5t41 -81.5l16 -29q29 -60 56 -104t48.5 -68.5t41.5 -38.5t34 -14t27 5q2 1 5 5t12 22t13.5 47t9.5 81t0 125q-2 40 -9 73t-14 46l-6 12q-25 34 -85 43q-13 2 5 24q16 19 38 30q53 26 239 24
+q82 -1 135 -13q20 -5 33.5 -13.5t20.5 -24t10.5 -32t3.5 -45.5t-1 -55t-2.5 -70.5t-1.5 -82.5q0 -11 -1 -42t-0.5 -48t3.5 -40.5t11.5 -39t22.5 -24.5q8 -2 17 -4t26 11t38 34.5t52 67t68 107.5q60 104 107 225q4 10 10 17.5t11 10.5l4 3l5 2.5t13 3t20 0.5l288 2
+q39 5 64 -2.5t31 -16.5z" />
+ <glyph glyph-name="weibo" unicode="" horiz-adv-x="1792"
+d="M675 252q21 34 11 69t-45 50q-34 14 -73 1t-60 -46q-22 -34 -13 -68.5t43 -50.5t74.5 -2.5t62.5 47.5zM769 373q8 13 3.5 26.5t-17.5 18.5q-14 5 -28.5 -0.5t-21.5 -18.5q-17 -31 13 -45q14 -5 29 0.5t22 18.5zM943 266q-45 -102 -158 -150t-224 -12
+q-107 34 -147.5 126.5t6.5 187.5q47 93 151.5 139t210.5 19q111 -29 158.5 -119.5t2.5 -190.5zM1255 426q-9 96 -89 170t-208.5 109t-274.5 21q-223 -23 -369.5 -141.5t-132.5 -264.5q9 -96 89 -170t208.5 -109t274.5 -21q223 23 369.5 141.5t132.5 264.5zM1563 422
+q0 -68 -37 -139.5t-109 -137t-168.5 -117.5t-226 -83t-270.5 -31t-275 33.5t-240.5 93t-171.5 151t-65 199.5q0 115 69.5 245t197.5 258q169 169 341.5 236t246.5 -7q65 -64 20 -209q-4 -14 -1 -20t10 -7t14.5 0.5t13.5 3.5l6 2q139 59 246 59t153 -61q45 -63 0 -178
+q-2 -13 -4.5 -20t4.5 -12.5t12 -7.5t17 -6q57 -18 103 -47t80 -81.5t34 -116.5zM1489 1046q42 -47 54.5 -108.5t-6.5 -117.5q-8 -23 -29.5 -34t-44.5 -4q-23 8 -34 29.5t-4 44.5q20 63 -24 111t-107 35q-24 -5 -45 8t-25 37q-5 24 8 44.5t37 25.5q60 13 119 -5.5t101 -65.5z
+M1670 1209q87 -96 112.5 -222.5t-13.5 -241.5q-9 -27 -34 -40t-52 -4t-40 34t-5 52q28 82 10 172t-80 158q-62 69 -148 95.5t-173 8.5q-28 -6 -52 9.5t-30 43.5t9.5 51.5t43.5 29.5q123 26 244 -11.5t208 -134.5z" />
+ <glyph glyph-name="renren" unicode=""
+d="M1133 -34q-171 -94 -368 -94q-196 0 -367 94q138 87 235.5 211t131.5 268q35 -144 132.5 -268t235.5 -211zM638 1394v-485q0 -252 -126.5 -459.5t-330.5 -306.5q-181 215 -181 495q0 187 83.5 349.5t229.5 269.5t325 137zM1536 638q0 -280 -181 -495
+q-204 99 -330.5 306.5t-126.5 459.5v485q179 -30 325 -137t229.5 -269.5t83.5 -349.5z" />
+ <glyph glyph-name="_372" unicode="" horiz-adv-x="1408"
+d="M1402 433q-32 -80 -76 -138t-91 -88.5t-99 -46.5t-101.5 -14.5t-96.5 8.5t-86.5 22t-69.5 27.5t-46 22.5l-17 10q-113 -228 -289.5 -359.5t-384.5 -132.5q-19 0 -32 13t-13 32t13 31.5t32 12.5q173 1 322.5 107.5t251.5 294.5q-36 -14 -72 -23t-83 -13t-91 2.5t-93 28.5
+t-92 59t-84.5 100t-74.5 146q114 47 214 57t167.5 -7.5t124.5 -56.5t88.5 -77t56.5 -82q53 131 79 291q-7 -1 -18 -2.5t-46.5 -2.5t-69.5 0.5t-81.5 10t-88.5 23t-84 42.5t-75 65t-54.5 94.5t-28.5 127.5q70 28 133.5 36.5t112.5 -1t92 -30t73.5 -50t56 -61t42 -63t27.5 -56
+t16 -39.5l4 -16q12 122 12 195q-8 6 -21.5 16t-49 44.5t-63.5 71.5t-54 93t-33 112.5t12 127t70 138.5q73 -25 127.5 -61.5t84.5 -76.5t48 -85t20.5 -89t-0.5 -85.5t-13 -76.5t-19 -62t-17 -42l-7 -15q1 -4 1 -50t-1 -72q3 7 10 18.5t30.5 43t50.5 58t71 55.5t91.5 44.5
+t112 14.5t132.5 -24q-2 -78 -21.5 -141.5t-50 -104.5t-69.5 -71.5t-81.5 -45.5t-84.5 -24t-80 -9.5t-67.5 1t-46.5 4.5l-17 3q-23 -147 -73 -283q6 7 18 18.5t49.5 41t77.5 52.5t99.5 42t117.5 20t129 -23.5t137 -77.5z" />
+ <glyph glyph-name="stack_exchange" unicode="" horiz-adv-x="1280"
+d="M1259 283v-66q0 -85 -57.5 -144.5t-138.5 -59.5h-57l-260 -269v269h-529q-81 0 -138.5 59.5t-57.5 144.5v66h1238zM1259 609v-255h-1238v255h1238zM1259 937v-255h-1238v255h1238zM1259 1077v-67h-1238v67q0 84 57.5 143.5t138.5 59.5h846q81 0 138.5 -59.5t57.5 -143.5z
+" />
+ <glyph glyph-name="_374" unicode=""
+d="M1152 640q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198
+t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="arrow_circle_alt_left" unicode=""
+d="M1152 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-192q0 -14 -9 -23t-23 -9q-12 0 -24 10l-319 319q-9 9 -9 23t9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h352q13 0 22.5 -9.5t9.5 -22.5zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198
+t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="_376" unicode=""
+d="M1024 960v-640q0 -26 -19 -45t-45 -19q-20 0 -37 12l-448 320q-27 19 -27 52t27 52l448 320q17 12 37 12q26 0 45 -19t19 -45zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5z
+M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="dot_circle_alt" unicode=""
+d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5
+t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="_378" unicode="" horiz-adv-x="1664"
+d="M1023 349l102 -204q-58 -179 -210 -290t-339 -111q-156 0 -288.5 77.5t-210 210t-77.5 288.5q0 181 104.5 330t274.5 211l17 -131q-122 -54 -195 -165.5t-73 -244.5q0 -185 131.5 -316.5t316.5 -131.5q126 0 232.5 65t165 175.5t49.5 236.5zM1571 249l58 -114l-256 -128
+q-13 -7 -29 -7q-40 0 -57 35l-239 477h-472q-24 0 -42.5 16.5t-21.5 40.5l-96 779q-2 17 6 42q14 51 57 82.5t97 31.5q66 0 113 -47t47 -113q0 -69 -52 -117.5t-120 -41.5l37 -289h423v-128h-407l16 -128h455q40 0 57 -35l228 -455z" />
+ <glyph glyph-name="vimeo_square" unicode=""
+d="M1292 898q10 216 -161 222q-231 8 -312 -261q44 19 82 19q85 0 74 -96q-4 -57 -74 -167t-105 -110q-43 0 -82 169q-13 54 -45 255q-30 189 -160 177q-59 -7 -164 -100l-81 -72l-81 -72l52 -67q76 52 87 52q57 0 107 -179q15 -55 45 -164.5t45 -164.5q68 -179 164 -179
+q157 0 383 294q220 283 226 444zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="_380" unicode="" horiz-adv-x="1152"
+d="M1152 704q0 -191 -94.5 -353t-256.5 -256.5t-353 -94.5h-160q-14 0 -23 9t-9 23v611l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v93l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v250q0 14 9 23t23 9h160
+q14 0 23 -9t9 -23v-181l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-93l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-487q188 13 318 151t130 328q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" />
+ <glyph glyph-name="plus_square_o" unicode="" horiz-adv-x="1408"
+d="M1152 736v-64q0 -14 -9 -23t-23 -9h-352v-352q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v352h-352q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h352v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-352h352q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832
+q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="_382" unicode="" horiz-adv-x="2176"
+d="M620 416q-110 -64 -268 -64h-128v64h-64q-13 0 -22.5 23.5t-9.5 56.5q0 24 7 49q-58 2 -96.5 10.5t-38.5 20.5t38.5 20.5t96.5 10.5q-7 25 -7 49q0 33 9.5 56.5t22.5 23.5h64v64h128q158 0 268 -64h1113q42 -7 106.5 -18t80.5 -14q89 -15 150 -40.5t83.5 -47.5t22.5 -40
+t-22.5 -40t-83.5 -47.5t-150 -40.5q-16 -3 -80.5 -14t-106.5 -18h-1113zM1739 668q53 -36 53 -92t-53 -92l81 -30q68 48 68 122t-68 122zM625 400h1015q-217 -38 -456 -80q-57 0 -113 -24t-83 -48l-28 -24l-288 -288q-26 -26 -70.5 -45t-89.5 -19h-96l-93 464h29
+q157 0 273 64zM352 816h-29l93 464h96q46 0 90 -19t70 -45l288 -288q4 -4 11 -10.5t30.5 -23t48.5 -29t61.5 -23t72.5 -10.5l456 -80h-1015q-116 64 -273 64z" />
+ <glyph glyph-name="_383" unicode="" horiz-adv-x="1664"
+d="M1519 760q62 0 103.5 -40.5t41.5 -101.5q0 -97 -93 -130l-172 -59l56 -167q7 -21 7 -47q0 -59 -42 -102t-101 -43q-47 0 -85.5 27t-53.5 72l-55 165l-310 -106l55 -164q8 -24 8 -47q0 -59 -42 -102t-102 -43q-47 0 -85 27t-53 72l-55 163l-153 -53q-29 -9 -50 -9
+q-61 0 -101.5 40t-40.5 101q0 47 27.5 85t71.5 53l156 53l-105 313l-156 -54q-26 -8 -48 -8q-60 0 -101 40.5t-41 100.5q0 47 27.5 85t71.5 53l157 53l-53 159q-8 24 -8 47q0 60 42 102.5t102 42.5q47 0 85 -27t53 -72l54 -160l310 105l-54 160q-8 24 -8 47q0 59 42.5 102
+t101.5 43q47 0 85.5 -27.5t53.5 -71.5l53 -161l162 55q21 6 43 6q60 0 102.5 -39.5t42.5 -98.5q0 -45 -30 -81.5t-74 -51.5l-157 -54l105 -316l164 56q24 8 46 8zM725 498l310 105l-105 315l-310 -107z" />
+ <glyph glyph-name="_384" unicode=""
+d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM1280 352v436q-31 -35 -64 -55q-34 -22 -132.5 -85t-151.5 -99q-98 -69 -164 -69v0v0q-66 0 -164 69
+q-47 32 -142 92.5t-142 92.5q-12 8 -33 27t-31 27v-436q0 -40 28 -68t68 -28h832q40 0 68 28t28 68zM1280 925q0 41 -27.5 70t-68.5 29h-832q-40 0 -68 -28t-28 -68q0 -37 30.5 -76.5t67.5 -64.5q47 -32 137.5 -89t129.5 -83q3 -2 17 -11.5t21 -14t21 -13t23.5 -13
+t21.5 -9.5t22.5 -7.5t20.5 -2.5t20.5 2.5t22.5 7.5t21.5 9.5t23.5 13t21 13t21 14t17 11.5l267 174q35 23 66.5 62.5t31.5 73.5z" />
+ <glyph glyph-name="_385" unicode="" horiz-adv-x="1792"
+d="M127 640q0 163 67 313l367 -1005q-196 95 -315 281t-119 411zM1415 679q0 -19 -2.5 -38.5t-10 -49.5t-11.5 -44t-17.5 -59t-17.5 -58l-76 -256l-278 826q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-75 1 -202 10q-12 1 -20.5 -5t-11.5 -15t-1.5 -18.5t9 -16.5
+t19.5 -8l80 -8l120 -328l-168 -504l-280 832q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-7 0 -23 0.5t-26 0.5q105 160 274.5 253.5t367.5 93.5q147 0 280.5 -53t238.5 -149h-10q-55 0 -92 -40.5t-37 -95.5q0 -12 2 -24t4 -21.5t8 -23t9 -21t12 -22.5t12.5 -21
+t14.5 -24t14 -23q63 -107 63 -212zM909 573l237 -647q1 -6 5 -11q-126 -44 -255 -44q-112 0 -217 32zM1570 1009q95 -174 95 -369q0 -209 -104 -385.5t-279 -278.5l235 678q59 169 59 276q0 42 -6 79zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286
+t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 -215q173 0 331.5 68t273 182.5t182.5 273t68 331.5t-68 331.5t-182.5 273t-273 182.5t-331.5 68t-331.5 -68t-273 -182.5t-182.5 -273t-68 -331.5t68 -331.5t182.5 -273
+t273 -182.5t331.5 -68z" />
+ <glyph glyph-name="_386" unicode="" horiz-adv-x="1792"
+d="M1086 1536v-1536l-272 -128q-228 20 -414 102t-293 208.5t-107 272.5q0 140 100.5 263.5t275 205.5t391.5 108v-172q-217 -38 -356.5 -150t-139.5 -255q0 -152 154.5 -267t388.5 -145v1360zM1755 954l37 -390l-525 114l147 83q-119 70 -280 99v172q277 -33 481 -157z" />
+ <glyph glyph-name="_387" unicode="" horiz-adv-x="2048"
+d="M960 1536l960 -384v-128h-128q0 -26 -20.5 -45t-48.5 -19h-1526q-28 0 -48.5 19t-20.5 45h-128v128zM256 896h256v-768h128v768h256v-768h128v768h256v-768h128v768h256v-768h59q28 0 48.5 -19t20.5 -45v-64h-1664v64q0 26 20.5 45t48.5 19h59v768zM1851 -64
+q28 0 48.5 -19t20.5 -45v-128h-1920v128q0 26 20.5 45t48.5 19h1782z" />
+ <glyph glyph-name="_388" unicode="" horiz-adv-x="2304"
+d="M1774 700l18 -316q4 -69 -82 -128t-235 -93.5t-323 -34.5t-323 34.5t-235 93.5t-82 128l18 316l574 -181q22 -7 48 -7t48 7zM2304 1024q0 -23 -22 -31l-1120 -352q-4 -1 -10 -1t-10 1l-652 206q-43 -34 -71 -111.5t-34 -178.5q63 -36 63 -109q0 -69 -58 -107l58 -433
+q2 -14 -8 -25q-9 -11 -24 -11h-192q-15 0 -24 11q-10 11 -8 25l58 433q-58 38 -58 107q0 73 65 111q11 207 98 330l-333 104q-22 8 -22 31t22 31l1120 352q4 1 10 1t10 -1l1120 -352q22 -8 22 -31z" />
+ <glyph glyph-name="_389" unicode=""
+d="M859 579l13 -707q-62 11 -105 11q-41 0 -105 -11l13 707q-40 69 -168.5 295.5t-216.5 374.5t-181 287q58 -15 108 -15q44 0 111 15q63 -111 133.5 -229.5t167 -276.5t138.5 -227q37 61 109.5 177.5t117.5 190t105 176t107 189.5q54 -14 107 -14q56 0 114 14v0
+q-28 -39 -60 -88.5t-49.5 -78.5t-56.5 -96t-49 -84q-146 -248 -353 -610z" />
+ <glyph glyph-name="uniF1A0" unicode=""
+d="M768 750h725q12 -67 12 -128q0 -217 -91 -387.5t-259.5 -266.5t-386.5 -96q-157 0 -299 60.5t-245 163.5t-163.5 245t-60.5 299t60.5 299t163.5 245t245 163.5t299 60.5q300 0 515 -201l-209 -201q-123 119 -306 119q-129 0 -238.5 -65t-173.5 -176.5t-64 -243.5
+t64 -243.5t173.5 -176.5t238.5 -65q87 0 160 24t120 60t82 82t51.5 87t22.5 78h-436v264z" />
+ <glyph glyph-name="f1a1" unicode="" horiz-adv-x="1792"
+d="M1095 369q16 -16 0 -31q-62 -62 -199 -62t-199 62q-16 15 0 31q6 6 15 6t15 -6q48 -49 169 -49q120 0 169 49q6 6 15 6t15 -6zM788 550q0 -37 -26 -63t-63 -26t-63.5 26t-26.5 63q0 38 26.5 64t63.5 26t63 -26.5t26 -63.5zM1183 550q0 -37 -26.5 -63t-63.5 -26t-63 26
+t-26 63t26 63.5t63 26.5t63.5 -26t26.5 -64zM1434 670q0 49 -35 84t-85 35t-86 -36q-130 90 -311 96l63 283l200 -45q0 -37 26 -63t63 -26t63.5 26.5t26.5 63.5t-26.5 63.5t-63.5 26.5q-54 0 -80 -50l-221 49q-19 5 -25 -16l-69 -312q-180 -7 -309 -97q-35 37 -87 37
+q-50 0 -85 -35t-35 -84q0 -35 18.5 -64t49.5 -44q-6 -27 -6 -56q0 -142 140 -243t337 -101q198 0 338 101t140 243q0 32 -7 57q30 15 48 43.5t18 63.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191
+t348 71t348 -71t286 -191t191 -286t71 -348z" />
+ <glyph glyph-name="_392" unicode=""
+d="M939 407q13 -13 0 -26q-53 -53 -171 -53t-171 53q-13 13 0 26q5 6 13 6t13 -6q42 -42 145 -42t145 42q5 6 13 6t13 -6zM676 563q0 -31 -23 -54t-54 -23t-54 23t-23 54q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1014 563q0 -31 -23 -54t-54 -23t-54 23t-23 54
+q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1229 666q0 42 -30 72t-73 30q-42 0 -73 -31q-113 78 -267 82l54 243l171 -39q1 -32 23.5 -54t53.5 -22q32 0 54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5q-48 0 -69 -43l-189 42q-17 5 -21 -13l-60 -268q-154 -6 -265 -83
+q-30 32 -74 32q-43 0 -73 -30t-30 -72q0 -30 16 -55t42 -38q-5 -25 -5 -48q0 -122 120 -208.5t289 -86.5q170 0 290 86.5t120 208.5q0 25 -6 49q25 13 40.5 37.5t15.5 54.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960
+q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="_393" unicode=""
+d="M866 697l90 27v62q0 79 -58 135t-138 56t-138 -55.5t-58 -134.5v-283q0 -20 -14 -33.5t-33 -13.5t-32.5 13.5t-13.5 33.5v120h-151v-122q0 -82 57.5 -139t139.5 -57q81 0 138.5 56.5t57.5 136.5v280q0 19 13.5 33t33.5 14q19 0 32.5 -14t13.5 -33v-54zM1199 502v122h-150
+v-126q0 -20 -13.5 -33.5t-33.5 -13.5q-19 0 -32.5 14t-13.5 33v123l-90 -26l-60 28v-123q0 -80 58 -137t139 -57t138.5 57t57.5 139zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103
+t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="f1a4" unicode="" horiz-adv-x="1920"
+d="M1062 824v118q0 42 -30 72t-72 30t-72 -30t-30 -72v-612q0 -175 -126 -299t-303 -124q-178 0 -303.5 125.5t-125.5 303.5v266h328v-262q0 -43 30 -72.5t72 -29.5t72 29.5t30 72.5v620q0 171 126.5 292t301.5 121q176 0 302 -122t126 -294v-136l-195 -58zM1592 602h328
+v-266q0 -178 -125.5 -303.5t-303.5 -125.5q-177 0 -303 124.5t-126 300.5v268l131 -61l195 58v-270q0 -42 30 -71.5t72 -29.5t72 29.5t30 71.5v275z" />
+ <glyph glyph-name="_395" unicode=""
+d="M1472 160v480h-704v704h-480q-93 0 -158.5 -65.5t-65.5 -158.5v-480h704v-704h480q93 0 158.5 65.5t65.5 158.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5
+t84.5 -203.5z" />
+ <glyph glyph-name="_396" unicode="" horiz-adv-x="2048"
+d="M328 1254h204v-983h-532v697h328v286zM328 435v369h-123v-369h123zM614 968v-697h205v697h-205zM614 1254v-204h205v204h-205zM901 968h533v-942h-533v163h328v82h-328v697zM1229 435v369h-123v-369h123zM1516 968h532v-942h-532v163h327v82h-327v697zM1843 435v369h-123
+v-369h123z" />
+ <glyph glyph-name="_397" unicode=""
+d="M1046 516q0 -64 -38 -109t-91 -45q-43 0 -70 15v277q28 17 70 17q53 0 91 -45.5t38 -109.5zM703 944q0 -64 -38 -109.5t-91 -45.5q-43 0 -70 15v277q28 17 70 17q53 0 91 -45t38 -109zM1265 513q0 134 -88 229t-213 95q-20 0 -39 -3q-23 -78 -78 -136q-87 -95 -211 -101
+v-636l211 41v206q51 -19 117 -19q125 0 213 95t88 229zM922 940q0 134 -88.5 229t-213.5 95q-74 0 -141 -36h-186v-840l211 41v206q55 -19 116 -19q125 0 213.5 95t88.5 229zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960
+q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="_398" unicode="" horiz-adv-x="2038"
+d="M1222 607q75 3 143.5 -20.5t118 -58.5t101 -94.5t84 -108t75.5 -120.5q33 -56 78.5 -109t75.5 -80.5t99 -88.5q-48 -30 -108.5 -57.5t-138.5 -59t-114 -47.5q-44 37 -74 115t-43.5 164.5t-33 180.5t-42.5 168.5t-72.5 123t-122.5 48.5l-10 -2l-6 -4q4 -5 13 -14
+q6 -5 28 -23.5t25.5 -22t19 -18t18 -20.5t11.5 -21t10.5 -27.5t4.5 -31t4 -40.5l1 -33q1 -26 -2.5 -57.5t-7.5 -52t-12.5 -58.5t-11.5 -53q-35 1 -101 -9.5t-98 -10.5q-39 0 -72 10q-2 16 -2 47q0 74 3 96q2 13 31.5 41.5t57 59t26.5 51.5q-24 2 -43 -24
+q-36 -53 -111.5 -99.5t-136.5 -46.5q-25 0 -75.5 63t-106.5 139.5t-84 96.5q-6 4 -27 30q-482 -112 -513 -112q-16 0 -28 11t-12 27q0 15 8.5 26.5t22.5 14.5l486 106q-8 14 -8 25t5.5 17.5t16 11.5t20 7t23 4.5t18.5 4.5q4 1 15.5 7.5t17.5 6.5q15 0 28 -16t20 -33
+q163 37 172 37q17 0 29.5 -11t12.5 -28q0 -15 -8.5 -26t-23.5 -14l-182 -40l-1 -16q-1 -26 81.5 -117.5t104.5 -91.5q47 0 119 80t72 129q0 36 -23.5 53t-51 18.5t-51 11.5t-23.5 34q0 16 10 34l-68 19q43 44 43 117q0 26 -5 58q82 16 144 16q44 0 71.5 -1.5t48.5 -8.5
+t31 -13.5t20.5 -24.5t15.5 -33.5t17 -47.5t24 -60l50 25q-3 -40 -23 -60t-42.5 -21t-40 -6.5t-16.5 -20.5zM1282 842q-5 5 -13.5 15.5t-12 14.5t-10.5 11.5t-10 10.5l-8 8t-8.5 7.5t-8 5t-8.5 4.5q-7 3 -14.5 5t-20.5 2.5t-22 0.5h-32.5h-37.5q-126 0 -217 -43
+q16 30 36 46.5t54 29.5t65.5 36t46 36.5t50 55t43.5 50.5q12 -9 28 -31.5t32 -36.5t38 -13l12 1v-76l22 -1q247 95 371 190q28 21 50 39t42.5 37.5t33 31t29.5 34t24 31t24.5 37t23 38t27 47.5t29.5 53l7 9q-2 -53 -43 -139q-79 -165 -205 -264t-306 -142q-14 -3 -42 -7.5
+t-50 -9.5t-39 -14q3 -19 24.5 -46t21.5 -34q0 -11 -26 -30zM1061 -79q39 26 131.5 47.5t146.5 21.5q9 0 22.5 -15.5t28 -42.5t26 -50t24 -51t14.5 -33q-121 -45 -244 -45q-61 0 -125 11zM822 568l48 12l109 -177l-73 -48zM1323 51q3 -15 3 -16q0 -7 -17.5 -14.5t-46 -13
+t-54 -9.5t-53.5 -7.5t-32 -4.5l-7 43q21 2 60.5 8.5t72 10t60.5 3.5h14zM866 679l-96 -20l-6 17q10 1 32.5 7t34.5 6q19 0 35 -10zM1061 45h31l10 -83l-41 -12v95zM1950 1535v1v-1zM1950 1535l-1 -5l-2 -2l1 3zM1950 1535l1 1z" />
+ <glyph glyph-name="_399" unicode=""
+d="M1167 -50q-5 19 -24 5q-30 -22 -87 -39t-131 -17q-129 0 -193 49q-5 4 -13 4q-11 0 -26 -12q-7 -6 -7.5 -16t7.5 -20q34 -32 87.5 -46t102.5 -12.5t99 4.5q41 4 84.5 20.5t65 30t28.5 20.5q12 12 7 29zM1128 65q-19 47 -39 61q-23 15 -76 15q-47 0 -71 -10
+q-29 -12 -78 -56q-26 -24 -12 -44q9 -8 17.5 -4.5t31.5 23.5q3 2 10.5 8.5t10.5 8.5t10 7t11.5 7t12.5 5t15 4.5t16.5 2.5t20.5 1q27 0 44.5 -7.5t23 -14.5t13.5 -22q10 -17 12.5 -20t12.5 1q23 12 14 34zM1483 346q0 22 -5 44.5t-16.5 45t-34 36.5t-52.5 14
+q-33 0 -97 -41.5t-129 -83.5t-101 -42q-27 -1 -63.5 19t-76 49t-83.5 58t-100 49t-111 19q-115 -1 -197 -78.5t-84 -178.5q-2 -112 74 -164q29 -20 62.5 -28.5t103.5 -8.5q57 0 132 32.5t134 71t120 70.5t93 31q26 -1 65 -31.5t71.5 -67t68 -67.5t55.5 -32q35 -3 58.5 14
+t55.5 63q28 41 42.5 101t14.5 106zM1536 506q0 -164 -62 -304.5t-166 -236t-242.5 -149.5t-290.5 -54t-293 57.5t-247.5 157t-170.5 241.5t-64 302q0 89 19.5 172.5t49 145.5t70.5 118.5t78.5 94t78.5 69.5t64.5 46.5t42.5 24.5q14 8 51 26.5t54.5 28.5t48 30t60.5 44
+q36 28 58 72.5t30 125.5q129 -155 186 -193q44 -29 130 -68t129 -66q21 -13 39 -25t60.5 -46.5t76 -70.5t75 -95t69 -122t47 -148.5t19.5 -177.5z" />
+ <glyph glyph-name="_400" unicode=""
+d="M1070 463l-160 -160l-151 -152l-30 -30q-65 -64 -151.5 -87t-171.5 -2q-16 -70 -72 -115t-129 -45q-85 0 -145 60.5t-60 145.5q0 72 44.5 128t113.5 72q-22 86 1 173t88 152l12 12l151 -152l-11 -11q-37 -37 -37 -89t37 -90q37 -37 89 -37t89 37l30 30l151 152l161 160z
+M729 1145l12 -12l-152 -152l-12 12q-37 37 -89 37t-89 -37t-37 -89.5t37 -89.5l29 -29l152 -152l160 -160l-151 -152l-161 160l-151 152l-30 30q-68 67 -90 159.5t5 179.5q-70 15 -115 71t-45 129q0 85 60 145.5t145 60.5q76 0 133.5 -49t69.5 -123q84 20 169.5 -3.5
+t149.5 -87.5zM1536 78q0 -85 -60 -145.5t-145 -60.5q-74 0 -131 47t-71 118q-86 -28 -179.5 -6t-161.5 90l-11 12l151 152l12 -12q37 -37 89 -37t89 37t37 89t-37 89l-30 30l-152 152l-160 160l152 152l160 -160l152 -152l29 -30q64 -64 87.5 -150.5t2.5 -171.5
+q76 -11 126.5 -68.5t50.5 -134.5zM1534 1202q0 -77 -51 -135t-127 -69q26 -85 3 -176.5t-90 -158.5l-12 -12l-151 152l12 12q37 37 37 89t-37 89t-89 37t-89 -37l-30 -30l-152 -152l-160 -160l-152 152l161 160l152 152l29 30q67 67 159 89.5t178 -3.5q11 75 68.5 126
+t135.5 51q85 0 145 -60.5t60 -145.5z" />
+ <glyph glyph-name="f1ab" unicode=""
+d="M654 458q-1 -3 -12.5 0.5t-31.5 11.5l-20 9q-44 20 -87 49q-7 5 -41 31.5t-38 28.5q-67 -103 -134 -181q-81 -95 -105 -110q-4 -2 -19.5 -4t-18.5 0q6 4 82 92q21 24 85.5 115t78.5 118q17 30 51 98.5t36 77.5q-8 1 -110 -33q-8 -2 -27.5 -7.5t-34.5 -9.5t-17 -5
+q-2 -2 -2 -10.5t-1 -9.5q-5 -10 -31 -15q-23 -7 -47 0q-18 4 -28 21q-4 6 -5 23q6 2 24.5 5t29.5 6q58 16 105 32q100 35 102 35q10 2 43 19.5t44 21.5q9 3 21.5 8t14.5 5.5t6 -0.5q2 -12 -1 -33q0 -2 -12.5 -27t-26.5 -53.5t-17 -33.5q-25 -50 -77 -131l64 -28
+q12 -6 74.5 -32t67.5 -28q4 -1 10.5 -25.5t4.5 -30.5zM449 944q3 -15 -4 -28q-12 -23 -50 -38q-30 -12 -60 -12q-26 3 -49 26q-14 15 -18 41l1 3q3 -3 19.5 -5t26.5 0t58 16q36 12 55 14q17 0 21 -17zM1147 815l63 -227l-139 42zM39 15l694 232v1032l-694 -233v-1031z
+M1280 332l102 -31l-181 657l-100 31l-216 -536l102 -31l45 110l211 -65zM777 1294l573 -184v380zM1088 -29l158 -13l-54 -160l-40 66q-130 -83 -276 -108q-58 -12 -91 -12h-84q-79 0 -199.5 39t-183.5 85q-8 7 -8 16q0 8 5 13.5t13 5.5q4 0 18 -7.5t30.5 -16.5t20.5 -11
+q73 -37 159.5 -61.5t157.5 -24.5q95 0 167 14.5t157 50.5q15 7 30.5 15.5t34 19t28.5 16.5zM1536 1050v-1079l-774 246q-14 -6 -375 -127.5t-368 -121.5q-13 0 -18 13q0 1 -1 3v1078q3 9 4 10q5 6 20 11q107 36 149 50v384l558 -198q2 0 160.5 55t316 108.5t161.5 53.5
+q20 0 20 -21v-418z" />
+ <glyph glyph-name="_402" unicode="" horiz-adv-x="1792"
+d="M288 1152q66 0 113 -47t47 -113v-1088q0 -66 -47 -113t-113 -47h-128q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h128zM1664 989q58 -34 93 -93t35 -128v-768q0 -106 -75 -181t-181 -75h-864q-66 0 -113 47t-47 113v1536q0 40 28 68t68 28h672q40 0 88 -20t76 -48
+l152 -152q28 -28 48 -76t20 -88v-163zM928 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM928 256v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM928 512v128q0 14 -9 23
+t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1184 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1184 256v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128
+q14 0 23 9t9 23zM1184 512v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 256v128q0 14 -9 23t-23 9h-128
+q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 512v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1536 896v256h-160q-40 0 -68 28t-28 68v160h-640v-512h896z" />
+ <glyph glyph-name="_403" unicode=""
+d="M1344 1536q26 0 45 -19t19 -45v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280zM512 1248v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 992v-64q0 -14 9 -23t23 -9h64q14 0 23 9
+t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 736v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 480v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM384 160v64
+q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64
+q14 0 23 9t9 23zM384 928v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 -96v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9
+t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM896 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 928v64
+q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 160v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64
+q14 0 23 9t9 23zM1152 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 928v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9
+t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23z" />
+ <glyph glyph-name="_404" unicode="" horiz-adv-x="1280"
+d="M1188 988l-292 -292v-824q0 -46 -33 -79t-79 -33t-79 33t-33 79v384h-64v-384q0 -46 -33 -79t-79 -33t-79 33t-33 79v824l-292 292q-28 28 -28 68t28 68q29 28 68.5 28t67.5 -28l228 -228h368l228 228q28 28 68 28t68 -28q28 -29 28 -68.5t-28 -67.5zM864 1152
+q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
+ <glyph glyph-name="uniF1B1" unicode="" horiz-adv-x="1664"
+d="M780 1064q0 -60 -19 -113.5t-63 -92.5t-105 -39q-76 0 -138 57.5t-92 135.5t-30 151q0 60 19 113.5t63 92.5t105 39q77 0 138.5 -57.5t91.5 -135t30 -151.5zM438 581q0 -80 -42 -139t-119 -59q-76 0 -141.5 55.5t-100.5 133.5t-35 152q0 80 42 139.5t119 59.5
+q76 0 141.5 -55.5t100.5 -134t35 -152.5zM832 608q118 0 255 -97.5t229 -237t92 -254.5q0 -46 -17 -76.5t-48.5 -45t-64.5 -20t-76 -5.5q-68 0 -187.5 45t-182.5 45q-66 0 -192.5 -44.5t-200.5 -44.5q-183 0 -183 146q0 86 56 191.5t139.5 192.5t187.5 146t193 59zM1071 819
+q-61 0 -105 39t-63 92.5t-19 113.5q0 74 30 151.5t91.5 135t138.5 57.5q61 0 105 -39t63 -92.5t19 -113.5q0 -73 -30 -151t-92 -135.5t-138 -57.5zM1503 923q77 0 119 -59.5t42 -139.5q0 -74 -35 -152t-100.5 -133.5t-141.5 -55.5q-77 0 -119 59t-42 139q0 74 35 152.5
+t100.5 134t141.5 55.5z" />
+ <glyph glyph-name="_406" unicode="" horiz-adv-x="768"
+d="M704 1008q0 -145 -57 -243.5t-152 -135.5l45 -821q2 -26 -16 -45t-44 -19h-192q-26 0 -44 19t-16 45l45 821q-95 37 -152 135.5t-57 243.5q0 128 42.5 249.5t117.5 200t160 78.5t160 -78.5t117.5 -200t42.5 -249.5z" />
+ <glyph glyph-name="_407" unicode="" horiz-adv-x="1792"
+d="M896 -93l640 349v636l-640 -233v-752zM832 772l698 254l-698 254l-698 -254zM1664 1024v-768q0 -35 -18 -65t-49 -47l-704 -384q-28 -16 -61 -16t-61 16l-704 384q-31 17 -49 47t-18 65v768q0 40 23 73t61 47l704 256q22 8 44 8t44 -8l704 -256q38 -14 61 -47t23 -73z
+" />
+ <glyph glyph-name="_408" unicode="" horiz-adv-x="2304"
+d="M640 -96l384 192v314l-384 -164v-342zM576 358l404 173l-404 173l-404 -173zM1664 -96l384 192v314l-384 -164v-342zM1600 358l404 173l-404 173l-404 -173zM1152 651l384 165v266l-384 -164v-267zM1088 1030l441 189l-441 189l-441 -189zM2176 512v-416q0 -36 -19 -67
+t-52 -47l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-4 2 -7 4q-2 -2 -7 -4l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-33 16 -52 47t-19 67v416q0 38 21.5 70t56.5 48l434 186v400q0 38 21.5 70t56.5 48l448 192q23 10 50 10t50 -10l448 -192q35 -16 56.5 -48t21.5 -70
+v-400l434 -186q36 -16 57 -48t21 -70z" />
+ <glyph glyph-name="_409" unicode="" horiz-adv-x="2048"
+d="M1848 1197h-511v-124h511v124zM1596 771q-90 0 -146 -52.5t-62 -142.5h408q-18 195 -200 195zM1612 186q63 0 122 32t76 87h221q-100 -307 -427 -307q-214 0 -340.5 132t-126.5 347q0 208 130.5 345.5t336.5 137.5q138 0 240.5 -68t153 -179t50.5 -248q0 -17 -2 -47h-658
+q0 -111 57.5 -171.5t166.5 -60.5zM277 236h296q205 0 205 167q0 180 -199 180h-302v-347zM277 773h281q78 0 123.5 36.5t45.5 113.5q0 144 -190 144h-260v-294zM0 1282h594q87 0 155 -14t126.5 -47.5t90 -96.5t31.5 -154q0 -181 -172 -263q114 -32 172 -115t58 -204
+q0 -75 -24.5 -136.5t-66 -103.5t-98.5 -71t-121 -42t-134 -13h-611v1260z" />
+ <glyph glyph-name="_410" unicode=""
+d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM499 1041h-371v-787h382q117 0 197 57.5t80 170.5q0 158 -143 200q107 52 107 164q0 57 -19.5 96.5
+t-56.5 60.5t-79 29.5t-97 8.5zM477 723h-176v184h163q119 0 119 -90q0 -94 -106 -94zM486 388h-185v217h189q124 0 124 -113q0 -104 -128 -104zM1136 356q-68 0 -104 38t-36 107h411q1 10 1 30q0 132 -74.5 220.5t-203.5 88.5q-128 0 -210 -86t-82 -216q0 -135 79 -217
+t213 -82q205 0 267 191h-138q-11 -34 -47.5 -54t-75.5 -20zM1126 722q113 0 124 -122h-254q4 56 39 89t91 33zM964 988h319v-77h-319v77z" />
+ <glyph glyph-name="_411" unicode="" horiz-adv-x="1792"
+d="M1582 954q0 -101 -71.5 -172.5t-172.5 -71.5t-172.5 71.5t-71.5 172.5t71.5 172.5t172.5 71.5t172.5 -71.5t71.5 -172.5zM812 212q0 104 -73 177t-177 73q-27 0 -54 -6l104 -42q77 -31 109.5 -106.5t1.5 -151.5q-31 -77 -107 -109t-152 -1q-21 8 -62 24.5t-61 24.5
+q32 -60 91 -96.5t130 -36.5q104 0 177 73t73 177zM1642 953q0 126 -89.5 215.5t-215.5 89.5q-127 0 -216.5 -89.5t-89.5 -215.5q0 -127 89.5 -216t216.5 -89q126 0 215.5 89t89.5 216zM1792 953q0 -189 -133.5 -322t-321.5 -133l-437 -319q-12 -129 -109 -218t-229 -89
+q-121 0 -214 76t-118 192l-230 92v429l389 -157q79 48 173 48q13 0 35 -2l284 407q2 187 135.5 319t320.5 132q188 0 321.5 -133.5t133.5 -321.5z" />
+ <glyph glyph-name="_412" unicode=""
+d="M1242 889q0 80 -57 136.5t-137 56.5t-136.5 -57t-56.5 -136q0 -80 56.5 -136.5t136.5 -56.5t137 56.5t57 136.5zM632 301q0 -83 -58 -140.5t-140 -57.5q-56 0 -103 29t-72 77q52 -20 98 -40q60 -24 120 1.5t85 86.5q24 60 -1.5 120t-86.5 84l-82 33q22 5 42 5
+q82 0 140 -57.5t58 -140.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v153l172 -69q20 -92 93.5 -152t168.5 -60q104 0 181 70t87 173l345 252q150 0 255.5 105.5t105.5 254.5q0 150 -105.5 255.5t-255.5 105.5
+q-148 0 -253 -104.5t-107 -252.5l-225 -322q-9 1 -28 1q-75 0 -137 -37l-297 119v468q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5zM1289 887q0 -100 -71 -170.5t-171 -70.5t-170.5 70.5t-70.5 170.5t70.5 171t170.5 71q101 0 171.5 -70.5t70.5 -171.5z
+" />
+ <glyph glyph-name="_413" unicode="" horiz-adv-x="1792"
+d="M836 367l-15 -368l-2 -22l-420 29q-36 3 -67 31.5t-47 65.5q-11 27 -14.5 55t4 65t12 55t21.5 64t19 53q78 -12 509 -28zM449 953l180 -379l-147 92q-63 -72 -111.5 -144.5t-72.5 -125t-39.5 -94.5t-18.5 -63l-4 -21l-190 357q-17 26 -18 56t6 47l8 18q35 63 114 188
+l-140 86zM1680 436l-188 -359q-12 -29 -36.5 -46.5t-43.5 -20.5l-18 -4q-71 -7 -219 -12l8 -164l-230 367l211 362l7 -173q170 -16 283 -5t170 33zM895 1360q-47 -63 -265 -435l-317 187l-19 12l225 356q20 31 60 45t80 10q24 -2 48.5 -12t42 -21t41.5 -33t36 -34.5
+t36 -39.5t32 -35zM1550 1053l212 -363q18 -37 12.5 -76t-27.5 -74q-13 -20 -33 -37t-38 -28t-48.5 -22t-47 -16t-51.5 -14t-46 -12q-34 72 -265 436l313 195zM1407 1279l142 83l-220 -373l-419 20l151 86q-34 89 -75 166t-75.5 123.5t-64.5 80t-47 46.5l-17 13l405 -1
+q31 3 58 -10.5t39 -28.5l11 -15q39 -61 112 -190z" />
+ <glyph glyph-name="_414" unicode="" horiz-adv-x="2048"
+d="M480 448q0 66 -47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47t113 47t47 113zM516 768h1016l-89 357q-2 8 -14 17.5t-21 9.5h-768q-9 0 -21 -9.5t-14 -17.5zM1888 448q0 66 -47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47t113 47t47 113zM2048 544v-384
+q0 -14 -9 -23t-23 -9h-96v-128q0 -80 -56 -136t-136 -56t-136 56t-56 136v128h-1024v-128q0 -80 -56 -136t-136 -56t-136 56t-56 136v128h-96q-14 0 -23 9t-9 23v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5t179 63.5h768q98 0 179 -63.5t104 -157.5
+l105 -419h28q93 0 158.5 -65.5t65.5 -158.5z" />
+ <glyph glyph-name="_415" unicode="" horiz-adv-x="2048"
+d="M1824 640q93 0 158.5 -65.5t65.5 -158.5v-384q0 -14 -9 -23t-23 -9h-96v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-1024v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-96q-14 0 -23 9t-9 23v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5
+t179 63.5h128v224q0 14 9 23t23 9h448q14 0 23 -9t9 -23v-224h128q98 0 179 -63.5t104 -157.5l105 -419h28zM320 160q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM516 640h1016l-89 357q-2 8 -14 17.5t-21 9.5h-768q-9 0 -21 -9.5t-14 -17.5z
+M1728 160q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47z" />
+ <glyph glyph-name="_416" unicode=""
+d="M1504 64q0 -26 -19 -45t-45 -19h-462q1 -17 6 -87.5t5 -108.5q0 -25 -18 -42.5t-43 -17.5h-320q-25 0 -43 17.5t-18 42.5q0 38 5 108.5t6 87.5h-462q-26 0 -45 19t-19 45t19 45l402 403h-229q-26 0 -45 19t-19 45t19 45l402 403h-197q-26 0 -45 19t-19 45t19 45l384 384
+q19 19 45 19t45 -19l384 -384q19 -19 19 -45t-19 -45t-45 -19h-197l402 -403q19 -19 19 -45t-19 -45t-45 -19h-229l402 -403q19 -19 19 -45z" />
+ <glyph glyph-name="_417" unicode=""
+d="M1127 326q0 32 -30 51q-193 115 -447 115q-133 0 -287 -34q-42 -9 -42 -52q0 -20 13.5 -34.5t35.5 -14.5q5 0 37 8q132 27 243 27q226 0 397 -103q19 -11 33 -11q19 0 33 13.5t14 34.5zM1223 541q0 40 -35 61q-237 141 -548 141q-153 0 -303 -42q-48 -13 -48 -64
+q0 -25 17.5 -42.5t42.5 -17.5q7 0 37 8q122 33 251 33q279 0 488 -124q24 -13 38 -13q25 0 42.5 17.5t17.5 42.5zM1331 789q0 47 -40 70q-126 73 -293 110.5t-343 37.5q-204 0 -364 -47q-23 -7 -38.5 -25.5t-15.5 -48.5q0 -31 20.5 -52t51.5 -21q11 0 40 8q133 37 307 37
+q159 0 309.5 -34t253.5 -95q21 -12 40 -12q29 0 50.5 20.5t21.5 51.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="_418" unicode="" horiz-adv-x="1024"
+d="M1024 1233l-303 -582l24 -31h279v-415h-507l-44 -30l-142 -273l-30 -30h-301v303l303 583l-24 30h-279v415h507l44 30l142 273l30 30h301v-303z" />
+ <glyph glyph-name="_419" unicode="" horiz-adv-x="2304"
+d="M784 164l16 241l-16 523q-1 10 -7.5 17t-16.5 7q-9 0 -16 -7t-7 -17l-14 -523l14 -241q1 -10 7.5 -16.5t15.5 -6.5q22 0 24 23zM1080 193l11 211l-12 586q0 16 -13 24q-8 5 -16 5t-16 -5q-13 -8 -13 -24l-1 -6l-10 -579q0 -1 11 -236v-1q0 -10 6 -17q9 -11 23 -11
+q11 0 20 9q9 7 9 20zM35 533l20 -128l-20 -126q-2 -9 -9 -9t-9 9l-17 126l17 128q2 9 9 9t9 -9zM121 612l26 -207l-26 -203q-2 -9 -10 -9q-9 0 -9 10l-23 202l23 207q0 9 9 9q8 0 10 -9zM401 159zM213 650l25 -245l-25 -237q0 -11 -11 -11q-10 0 -12 11l-21 237l21 245
+q2 12 12 12q11 0 11 -12zM307 657l23 -252l-23 -244q-2 -13 -14 -13q-13 0 -13 13l-21 244l21 252q0 13 13 13q12 0 14 -13zM401 639l21 -234l-21 -246q-2 -16 -16 -16q-6 0 -10.5 4.5t-4.5 11.5l-20 246l20 234q0 6 4.5 10.5t10.5 4.5q14 0 16 -15zM784 164zM495 785
+l21 -380l-21 -246q0 -7 -5 -12.5t-12 -5.5q-16 0 -18 18l-18 246l18 380q2 18 18 18q7 0 12 -5.5t5 -12.5zM589 871l19 -468l-19 -244q0 -8 -5.5 -13.5t-13.5 -5.5q-18 0 -20 19l-16 244l16 468q2 19 20 19q8 0 13.5 -5.5t5.5 -13.5zM687 911l18 -506l-18 -242
+q-2 -21 -22 -21q-19 0 -21 21l-16 242l16 506q0 9 6.5 15.5t14.5 6.5q9 0 15 -6.5t7 -15.5zM1079 169v0v0v0zM881 915l15 -510l-15 -239q0 -10 -7.5 -17.5t-17.5 -7.5t-17 7t-8 18l-14 239l14 510q0 11 7.5 18t17.5 7t17.5 -7t7.5 -18zM980 896l14 -492l-14 -236
+q0 -11 -8 -19t-19 -8t-19 8t-9 19l-12 236l12 492q1 12 9 20t19 8t18.5 -8t8.5 -20zM1192 404l-14 -231v0q0 -13 -9 -22t-22 -9t-22 9t-10 22l-6 114l-6 117l12 636v3q2 15 12 24q9 7 20 7q8 0 15 -5q14 -8 16 -26zM2304 423q0 -117 -83 -199.5t-200 -82.5h-786
+q-13 2 -22 11t-9 22v899q0 23 28 33q85 34 181 34q195 0 338 -131.5t160 -323.5q53 22 110 22q117 0 200 -83t83 -201z" />
+ <glyph glyph-name="uniF1C0" unicode=""
+d="M768 768q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 0q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127
+t443 -43zM768 384q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 1536q208 0 385 -34.5t280 -93.5t103 -128v-128q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5
+t-103 128v128q0 69 103 128t280 93.5t385 34.5z" />
+ <glyph glyph-name="uniF1C1" unicode=""
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M894 465q33 -26 84 -56q59 7 117 7q147 0 177 -49q16 -22 2 -52q0 -1 -1 -2l-2 -2v-1q-6 -38 -71 -38q-48 0 -115 20t-130 53q-221 -24 -392 -83q-153 -262 -242 -262q-15 0 -28 7l-24 12q-1 1 -6 5q-10 10 -6 36q9 40 56 91.5t132 96.5q14 9 23 -6q2 -2 2 -4q52 85 107 197
+q68 136 104 262q-24 82 -30.5 159.5t6.5 127.5q11 40 42 40h21h1q23 0 35 -15q18 -21 9 -68q-2 -6 -4 -8q1 -3 1 -8v-30q-2 -123 -14 -192q55 -164 146 -238zM318 54q52 24 137 158q-51 -40 -87.5 -84t-49.5 -74zM716 974q-15 -42 -2 -132q1 7 7 44q0 3 7 43q1 4 4 8
+q-1 1 -1 2q-1 2 -1 3q-1 22 -13 36q0 -1 -1 -2v-2zM592 313q135 54 284 81q-2 1 -13 9.5t-16 13.5q-76 67 -127 176q-27 -86 -83 -197q-30 -56 -45 -83zM1238 329q-24 24 -140 24q76 -28 124 -28q14 0 18 1q0 1 -2 3z" />
+ <glyph glyph-name="_422" unicode=""
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M233 768v-107h70l164 -661h159l128 485q7 20 10 46q2 16 2 24h4l3 -24q1 -3 3.5 -20t5.5 -26l128 -485h159l164 661h70v107h-300v-107h90l-99 -438q-5 -20 -7 -46l-2 -21h-4q0 3 -0.5 6.5t-1.5 8t-1 6.5q-1 5 -4 21t-5 25l-144 545h-114l-144 -545q-2 -9 -4.5 -24.5
+t-3.5 -21.5l-4 -21h-4l-2 21q-2 26 -7 46l-99 438h90v107h-300z" />
+ <glyph glyph-name="_423" unicode=""
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M429 106v-106h281v106h-75l103 161q5 7 10 16.5t7.5 13.5t3.5 4h2q1 -4 5 -10q2 -4 4.5 -7.5t6 -8t6.5 -8.5l107 -161h-76v-106h291v106h-68l-192 273l195 282h67v107h-279v-107h74l-103 -159q-4 -7 -10 -16.5t-9 -13.5l-2 -3h-2q-1 4 -5 10q-6 11 -17 23l-106 159h76v107
+h-290v-107h68l189 -272l-194 -283h-68z" />
+ <glyph glyph-name="_424" unicode=""
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M416 106v-106h327v106h-93v167h137q76 0 118 15q67 23 106.5 87t39.5 146q0 81 -37 141t-100 87q-48 19 -130 19h-368v-107h92v-555h-92zM769 386h-119v268h120q52 0 83 -18q56 -33 56 -115q0 -89 -62 -120q-31 -15 -78 -15z" />
+ <glyph glyph-name="_425" unicode=""
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M1280 320v-320h-1024v192l192 192l128 -128l384 384zM448 512q-80 0 -136 56t-56 136t56 136t136 56t136 -56t56 -136t-56 -136t-136 -56z" />
+ <glyph glyph-name="_426" unicode=""
+d="M640 1152v128h-128v-128h128zM768 1024v128h-128v-128h128zM640 896v128h-128v-128h128zM768 768v128h-128v-128h128zM1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400
+v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-128v-128h-128v128h-512v-1536h1280zM781 593l107 -349q8 -27 8 -52q0 -83 -72.5 -137.5t-183.5 -54.5t-183.5 54.5t-72.5 137.5q0 25 8 52q21 63 120 396v128h128v-128h79
+q22 0 39 -13t23 -34zM640 128q53 0 90.5 19t37.5 45t-37.5 45t-90.5 19t-90.5 -19t-37.5 -45t37.5 -45t90.5 -19z" />
+ <glyph glyph-name="_427" unicode=""
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M620 686q20 -8 20 -30v-544q0 -22 -20 -30q-8 -2 -12 -2q-12 0 -23 9l-166 167h-131q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h131l166 167q16 15 35 7zM1037 -3q31 0 50 24q129 159 129 363t-129 363q-16 21 -43 24t-47 -14q-21 -17 -23.5 -43.5t14.5 -47.5
+q100 -123 100 -282t-100 -282q-17 -21 -14.5 -47.5t23.5 -42.5q18 -15 40 -15zM826 145q27 0 47 20q87 93 87 219t-87 219q-18 19 -45 20t-46 -17t-20 -44.5t18 -46.5q52 -57 52 -131t-52 -131q-19 -20 -18 -46.5t20 -44.5q20 -17 44 -17z" />
+ <glyph glyph-name="_428" unicode=""
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M768 768q52 0 90 -38t38 -90v-384q0 -52 -38 -90t-90 -38h-384q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h384zM1260 766q20 -8 20 -30v-576q0 -22 -20 -30q-8 -2 -12 -2q-14 0 -23 9l-265 266v90l265 266q9 9 23 9q4 0 12 -2z" />
+ <glyph glyph-name="_429" unicode=""
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M480 768q8 11 21 12.5t24 -6.5l51 -38q11 -8 12.5 -21t-6.5 -24l-182 -243l182 -243q8 -11 6.5 -24t-12.5 -21l-51 -38q-11 -8 -24 -6.5t-21 12.5l-226 301q-14 19 0 38zM1282 467q14 -19 0 -38l-226 -301q-8 -11 -21 -12.5t-24 6.5l-51 38q-11 8 -12.5 21t6.5 24l182 243
+l-182 243q-8 11 -6.5 24t12.5 21l51 38q11 8 24 6.5t21 -12.5zM662 6q-13 2 -20.5 13t-5.5 24l138 831q2 13 13 20.5t24 5.5l63 -10q13 -2 20.5 -13t5.5 -24l-138 -831q-2 -13 -13 -20.5t-24 -5.5z" />
+ <glyph glyph-name="_430" unicode=""
+d="M1497 709v-198q-101 -23 -198 -23q-65 -136 -165.5 -271t-181.5 -215.5t-128 -106.5q-80 -45 -162 3q-28 17 -60.5 43.5t-85 83.5t-102.5 128.5t-107.5 184t-105.5 244t-91.5 314.5t-70.5 390h283q26 -218 70 -398.5t104.5 -317t121.5 -235.5t140 -195q169 169 287 406
+q-142 72 -223 220t-81 333q0 192 104 314.5t284 122.5q178 0 273 -105.5t95 -297.5q0 -159 -58 -286q-7 -1 -19.5 -3t-46 -2t-63 6t-62 25.5t-50.5 51.5q31 103 31 184q0 87 -29 132t-79 45q-53 0 -85 -49.5t-32 -140.5q0 -186 105 -293.5t267 -107.5q62 0 121 14z" />
+ <glyph glyph-name="_431" unicode="" horiz-adv-x="1792"
+d="M216 367l603 -402v359l-334 223zM154 511l193 129l-193 129v-258zM973 -35l603 402l-269 180l-334 -223v-359zM896 458l272 182l-272 182l-272 -182zM485 733l334 223v359l-603 -402zM1445 640l193 -129v258zM1307 733l269 180l-603 402v-359zM1792 913v-546
+q0 -41 -34 -64l-819 -546q-21 -13 -43 -13t-43 13l-819 546q-34 23 -34 64v546q0 41 34 64l819 546q21 13 43 13t43 -13l819 -546q34 -23 34 -64z" />
+ <glyph glyph-name="_432" unicode="" horiz-adv-x="2048"
+d="M1800 764q111 -46 179.5 -145.5t68.5 -221.5q0 -164 -118 -280.5t-285 -116.5q-4 0 -11.5 0.5t-10.5 0.5h-1209h-1h-2h-5q-170 10 -288 125.5t-118 280.5q0 110 55 203t147 147q-12 39 -12 82q0 115 82 196t199 81q95 0 172 -58q75 154 222.5 248t326.5 94
+q166 0 306 -80.5t221.5 -218.5t81.5 -301q0 -6 -0.5 -18t-0.5 -18zM468 498q0 -122 84 -193t208 -71q137 0 240 99q-16 20 -47.5 56.5t-43.5 50.5q-67 -65 -144 -65q-55 0 -93.5 33.5t-38.5 87.5q0 53 38.5 87t91.5 34q44 0 84.5 -21t73 -55t65 -75t69 -82t77 -75t97 -55
+t121.5 -21q121 0 204.5 71.5t83.5 190.5q0 121 -84 192t-207 71q-143 0 -241 -97l93 -108q66 64 142 64q52 0 92 -33t40 -84q0 -57 -37 -91.5t-94 -34.5q-43 0 -82.5 21t-72 55t-65.5 75t-69.5 82t-77.5 75t-96.5 55t-118.5 21q-122 0 -207 -70.5t-85 -189.5z" />
+ <glyph glyph-name="_433" unicode="" horiz-adv-x="1792"
+d="M896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 1408q-190 0 -361 -90l194 -194q82 28 167 28t167 -28l194 194q-171 90 -361 90zM218 279l194 194
+q-28 82 -28 167t28 167l-194 194q-90 -171 -90 -361t90 -361zM896 -128q190 0 361 90l-194 194q-82 -28 -167 -28t-167 28l-194 -194q171 -90 361 -90zM896 256q159 0 271.5 112.5t112.5 271.5t-112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5
+t271.5 -112.5zM1380 473l194 -194q90 171 90 361t-90 361l-194 -194q28 -82 28 -167t-28 -167z" />
+ <glyph glyph-name="_434" unicode="" horiz-adv-x="1792"
+d="M1760 640q0 -176 -68.5 -336t-184 -275.5t-275.5 -184t-336 -68.5t-336 68.5t-275.5 184t-184 275.5t-68.5 336q0 213 97 398.5t265 305.5t374 151v-228q-221 -45 -366.5 -221t-145.5 -406q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5
+t136.5 204t51 248.5q0 230 -145.5 406t-366.5 221v228q206 -31 374 -151t265 -305.5t97 -398.5z" />
+ <glyph glyph-name="uniF1D0" unicode="" horiz-adv-x="1792"
+d="M19 662q8 217 116 406t305 318h5q0 -1 -1 -3q-8 -8 -28 -33.5t-52 -76.5t-60 -110.5t-44.5 -135.5t-14 -150.5t39 -157.5t108.5 -154q50 -50 102 -69.5t90.5 -11.5t69.5 23.5t47 32.5l16 16q39 51 53 116.5t6.5 122.5t-21 107t-26.5 80l-14 29q-10 25 -30.5 49.5t-43 41
+t-43.5 29.5t-35 19l-13 6l104 115q39 -17 78 -52t59 -61l19 -27q1 48 -18.5 103.5t-40.5 87.5l-20 31l161 183l160 -181q-33 -46 -52.5 -102.5t-22.5 -90.5l-4 -33q22 37 61.5 72.5t67.5 52.5l28 17l103 -115q-44 -14 -85 -50t-60 -65l-19 -29q-31 -56 -48 -133.5t-7 -170
+t57 -156.5q33 -45 77.5 -60.5t85 -5.5t76 26.5t57.5 33.5l21 16q60 53 96.5 115t48.5 121.5t10 121.5t-18 118t-37 107.5t-45.5 93t-45 72t-34.5 47.5l-13 17q-14 13 -7 13l10 -3q40 -29 62.5 -46t62 -50t64 -58t58.5 -65t55.5 -77t45.5 -88t38 -103t23.5 -117t10.5 -136
+q3 -259 -108 -465t-312 -321t-456 -115q-185 0 -351 74t-283.5 198t-184 293t-60.5 353z" />
+ <glyph glyph-name="uniF1D1" unicode="" horiz-adv-x="1792"
+d="M874 -102v-66q-208 6 -385 109.5t-283 275.5l58 34q29 -49 73 -99l65 57q148 -168 368 -212l-17 -86q65 -12 121 -13zM276 428l-83 -28q22 -60 49 -112l-57 -33q-98 180 -98 385t98 385l57 -33q-30 -56 -49 -112l82 -28q-35 -100 -35 -212q0 -109 36 -212zM1528 251
+l58 -34q-106 -172 -283 -275.5t-385 -109.5v66q56 1 121 13l-17 86q220 44 368 212l65 -57q44 50 73 99zM1377 805l-233 -80q14 -42 14 -85t-14 -85l232 -80q-31 -92 -98 -169l-185 162q-57 -67 -147 -85l48 -241q-52 -10 -98 -10t-98 10l48 241q-90 18 -147 85l-185 -162
+q-67 77 -98 169l232 80q-14 42 -14 85t14 85l-233 80q33 93 99 169l185 -162q59 68 147 86l-48 240q44 10 98 10t98 -10l-48 -240q88 -18 147 -86l185 162q66 -76 99 -169zM874 1448v-66q-65 -2 -121 -13l17 -86q-220 -42 -368 -211l-65 56q-38 -42 -73 -98l-57 33
+q106 172 282 275.5t385 109.5zM1705 640q0 -205 -98 -385l-57 33q27 52 49 112l-83 28q36 103 36 212q0 112 -35 212l82 28q-19 56 -49 112l57 33q98 -180 98 -385zM1585 1063l-57 -33q-35 56 -73 98l-65 -56q-148 169 -368 211l17 86q-56 11 -121 13v66q209 -6 385 -109.5
+t282 -275.5zM1748 640q0 173 -67.5 331t-181.5 272t-272 181.5t-331 67.5t-331 -67.5t-272 -181.5t-181.5 -272t-67.5 -331t67.5 -331t181.5 -272t272 -181.5t331 -67.5t331 67.5t272 181.5t181.5 272t67.5 331zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71
+t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+ <glyph glyph-name="uniF1D2" unicode=""
+d="M582 228q0 -66 -93 -66q-107 0 -107 63q0 64 98 64q102 0 102 -61zM546 694q0 -85 -74 -85q-77 0 -77 84q0 90 77 90q36 0 55 -25.5t19 -63.5zM712 769v125q-78 -29 -135 -29q-50 29 -110 29q-86 0 -145 -57t-59 -143q0 -50 29.5 -102t73.5 -67v-3q-38 -17 -38 -85
+q0 -53 41 -77v-3q-113 -37 -113 -139q0 -45 20 -78.5t54 -51t72 -25.5t81 -8q224 0 224 188q0 67 -48 99t-126 46q-27 5 -51.5 20.5t-24.5 39.5q0 44 49 52q77 15 122 70t45 134q0 24 -10 52q37 9 49 13zM771 350h137q-2 27 -2 82v387q0 46 2 69h-137q3 -23 3 -71v-392
+q0 -50 -3 -75zM1280 366v121q-30 -21 -68 -21q-53 0 -53 82v225h52q9 0 26.5 -1t26.5 -1v117h-105q0 82 3 102h-140q4 -24 4 -55v-47h-60v-117q36 3 37 3q3 0 11 -0.5t12 -0.5v-2h-2v-217q0 -37 2.5 -64t11.5 -56.5t24.5 -48.5t43.5 -31t66 -12q64 0 108 24zM924 1072
+q0 36 -24 63.5t-60 27.5t-60.5 -27t-24.5 -64q0 -36 25 -62.5t60 -26.5t59.5 27t24.5 62zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="_438" unicode="" horiz-adv-x="1792"
+d="M595 22q0 100 -165 100q-158 0 -158 -104q0 -101 172 -101q151 0 151 105zM536 777q0 61 -30 102t-89 41q-124 0 -124 -145q0 -135 124 -135q119 0 119 137zM805 1101v-202q-36 -12 -79 -22q16 -43 16 -84q0 -127 -73 -216.5t-197 -112.5q-40 -8 -59.5 -27t-19.5 -58
+q0 -31 22.5 -51.5t58 -32t78.5 -22t86 -25.5t78.5 -37.5t58 -64t22.5 -98.5q0 -304 -363 -304q-69 0 -130 12.5t-116 41t-87.5 82t-32.5 127.5q0 165 182 225v4q-67 41 -67 126q0 109 63 137v4q-72 24 -119.5 108.5t-47.5 165.5q0 139 95 231.5t235 92.5q96 0 178 -47
+q98 0 218 47zM1123 220h-222q4 45 4 134v609q0 94 -4 128h222q-4 -33 -4 -124v-613q0 -89 4 -134zM1724 442v-196q-71 -39 -174 -39q-62 0 -107 20t-70 50t-39.5 78t-18.5 92t-4 103v351h2v4q-7 0 -19 1t-18 1q-21 0 -59 -6v190h96v76q0 54 -6 89h227q-6 -41 -6 -165h171
+v-190q-15 0 -43.5 2t-42.5 2h-85v-365q0 -131 87 -131q61 0 109 33zM1148 1389q0 -58 -39 -101.5t-96 -43.5q-58 0 -98 43.5t-40 101.5q0 59 39.5 103t98.5 44q58 0 96.5 -44.5t38.5 -102.5z" />
+ <glyph glyph-name="_439" unicode=""
+d="M809 532l266 499h-112l-157 -312q-24 -48 -44 -92l-42 92l-155 312h-120l263 -493v-324h101v318zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="uniF1D5" unicode="" horiz-adv-x="1280"
+d="M842 964q0 -80 -57 -136.5t-136 -56.5q-60 0 -111 35q-62 -67 -115 -146q-247 -371 -202 -859q1 -22 -12.5 -38.5t-34.5 -18.5h-5q-20 0 -35 13.5t-17 33.5q-14 126 -3.5 247.5t29.5 217t54 186t69 155.5t74 125q61 90 132 165q-16 35 -16 77q0 80 56.5 136.5t136.5 56.5
+t136.5 -56.5t56.5 -136.5zM1223 953q0 -158 -78 -292t-212.5 -212t-292.5 -78q-64 0 -131 14q-21 5 -32.5 23.5t-6.5 39.5q5 20 23 31.5t39 7.5q51 -13 108 -13q97 0 186 38t153 102t102 153t38 186t-38 186t-102 153t-153 102t-186 38t-186 -38t-153 -102t-102 -153
+t-38 -186q0 -114 52 -218q10 -20 3.5 -40t-25.5 -30t-39.5 -3t-30.5 26q-64 123 -64 265q0 119 46.5 227t124.5 186t186 124t226 46q158 0 292.5 -78t212.5 -212.5t78 -292.5z" />
+ <glyph glyph-name="uniF1D6" unicode="" horiz-adv-x="1792"
+d="M270 730q-8 19 -8 52q0 20 11 49t24 45q-1 22 7.5 53t22.5 43q0 139 92.5 288.5t217.5 209.5q139 66 324 66q133 0 266 -55q49 -21 90 -48t71 -56t55 -68t42 -74t32.5 -84.5t25.5 -89.5t22 -98l1 -5q55 -83 55 -150q0 -14 -9 -40t-9 -38q0 -1 1.5 -3.5t3.5 -5t2 -3.5
+q77 -114 120.5 -214.5t43.5 -208.5q0 -43 -19.5 -100t-55.5 -57q-9 0 -19.5 7.5t-19 17.5t-19 26t-16 26.5t-13.5 26t-9 17.5q-1 1 -3 1l-5 -4q-59 -154 -132 -223q20 -20 61.5 -38.5t69 -41.5t35.5 -65q-2 -4 -4 -16t-7 -18q-64 -97 -302 -97q-53 0 -110.5 9t-98 20
+t-104.5 30q-15 5 -23 7q-14 4 -46 4.5t-40 1.5q-41 -45 -127.5 -65t-168.5 -20q-35 0 -69 1.5t-93 9t-101 20.5t-74.5 40t-32.5 64q0 40 10 59.5t41 48.5q11 2 40.5 13t49.5 12q4 0 14 2q2 2 2 4l-2 3q-48 11 -108 105.5t-73 156.5l-5 3q-4 0 -12 -20q-18 -41 -54.5 -74.5
+t-77.5 -37.5h-1q-4 0 -6 4.5t-5 5.5q-23 54 -23 100q0 275 252 466z" />
+ <glyph glyph-name="uniF1D7" unicode="" horiz-adv-x="2048"
+d="M580 1075q0 41 -25 66t-66 25q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 66 24.5t25 65.5zM1323 568q0 28 -25.5 50t-65.5 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q40 0 65.5 22t25.5 51zM1087 1075q0 41 -24.5 66t-65.5 25
+q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 65.5 24.5t24.5 65.5zM1722 568q0 28 -26 50t-65 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q39 0 65 22t26 51zM1456 965q-31 4 -70 4q-169 0 -311 -77t-223.5 -208.5t-81.5 -287.5
+q0 -78 23 -152q-35 -3 -68 -3q-26 0 -50 1.5t-55 6.5t-44.5 7t-54.5 10.5t-50 10.5l-253 -127l72 218q-290 203 -290 490q0 169 97.5 311t264 223.5t363.5 81.5q176 0 332.5 -66t262 -182.5t136.5 -260.5zM2048 404q0 -117 -68.5 -223.5t-185.5 -193.5l55 -181l-199 109
+q-150 -37 -218 -37q-169 0 -311 70.5t-223.5 191.5t-81.5 264t81.5 264t223.5 191.5t311 70.5q161 0 303 -70.5t227.5 -192t85.5 -263.5z" />
+ <glyph glyph-name="_443" unicode="" horiz-adv-x="1792"
+d="M1764 1525q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-453 185l-242 -295q-18 -23 -49 -23q-13 0 -22 4q-19 7 -30.5 23.5t-11.5 36.5v349l864 1059l-1069 -925l-395 162q-37 14 -40 55q-2 40 32 59l1664 960q15 9 32 9q20 0 36 -11z" />
+ <glyph glyph-name="_444" unicode="" horiz-adv-x="1792"
+d="M1764 1525q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-527 215l-298 -327q-18 -21 -47 -21q-14 0 -23 4q-19 7 -30 23.5t-11 36.5v452l-472 193q-37 14 -40 55q-3 39 32 59l1664 960q35 21 68 -2zM1422 26l221 1323l-1434 -827l336 -137
+l863 639l-478 -797z" />
+ <glyph glyph-name="_445" unicode=""
+d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5
+t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298zM896 928v-448q0 -14 -9 -23
+t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23z" />
+ <glyph glyph-name="_446" unicode=""
+d="M768 1280q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103
+t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="_447" unicode="" horiz-adv-x="1792"
+d="M1682 -128q-44 0 -132.5 3.5t-133.5 3.5q-44 0 -132 -3.5t-132 -3.5q-24 0 -37 20.5t-13 45.5q0 31 17 46t39 17t51 7t45 15q33 21 33 140l-1 391q0 21 -1 31q-13 4 -50 4h-675q-38 0 -51 -4q-1 -10 -1 -31l-1 -371q0 -142 37 -164q16 -10 48 -13t57 -3.5t45 -15
+t20 -45.5q0 -26 -12.5 -48t-36.5 -22q-47 0 -139.5 3.5t-138.5 3.5q-43 0 -128 -3.5t-127 -3.5q-23 0 -35.5 21t-12.5 45q0 30 15.5 45t36 17.5t47.5 7.5t42 15q33 23 33 143l-1 57v813q0 3 0.5 26t0 36.5t-1.5 38.5t-3.5 42t-6.5 36.5t-11 31.5t-16 18q-15 10 -45 12t-53 2
+t-41 14t-18 45q0 26 12 48t36 22q46 0 138.5 -3.5t138.5 -3.5q42 0 126.5 3.5t126.5 3.5q25 0 37.5 -22t12.5 -48q0 -30 -17 -43.5t-38.5 -14.5t-49.5 -4t-43 -13q-35 -21 -35 -160l1 -320q0 -21 1 -32q13 -3 39 -3h699q25 0 38 3q1 11 1 32l1 320q0 139 -35 160
+q-18 11 -58.5 12.5t-66 13t-25.5 49.5q0 26 12.5 48t37.5 22q44 0 132 -3.5t132 -3.5q43 0 129 3.5t129 3.5q25 0 37.5 -22t12.5 -48q0 -30 -17.5 -44t-40 -14.5t-51.5 -3t-44 -12.5q-35 -23 -35 -161l1 -943q0 -119 34 -140q16 -10 46 -13.5t53.5 -4.5t41.5 -15.5t18 -44.5
+q0 -26 -12 -48t-36 -22z" />
+ <glyph glyph-name="_448" unicode="" horiz-adv-x="1280"
+d="M1278 1347v-73q0 -29 -18.5 -61t-42.5 -32q-50 0 -54 -1q-26 -6 -32 -31q-3 -11 -3 -64v-1152q0 -25 -18 -43t-43 -18h-108q-25 0 -43 18t-18 43v1218h-143v-1218q0 -25 -17.5 -43t-43.5 -18h-108q-26 0 -43.5 18t-17.5 43v496q-147 12 -245 59q-126 58 -192 179
+q-64 117 -64 259q0 166 88 286q88 118 209 159q111 37 417 37h479q25 0 43 -18t18 -43z" />
+ <glyph glyph-name="_449" unicode=""
+d="M352 128v-128h-352v128h352zM704 256q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM864 640v-128h-864v128h864zM224 1152v-128h-224v128h224zM1536 128v-128h-736v128h736zM576 1280q26 0 45 -19t19 -45v-256
+q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM1216 768q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM1536 640v-128h-224v128h224zM1536 1152v-128h-864v128h864z" />
+ <glyph glyph-name="uniF1E0" unicode=""
+d="M1216 512q133 0 226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5t-226.5 93.5t-93.5 226.5q0 12 2 34l-360 180q-92 -86 -218 -86q-133 0 -226.5 93.5t-93.5 226.5t93.5 226.5t226.5 93.5q126 0 218 -86l360 180q-2 22 -2 34q0 133 93.5 226.5t226.5 93.5
+t226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5q-126 0 -218 86l-360 -180q2 -22 2 -34t-2 -34l360 -180q92 86 218 86z" />
+ <glyph glyph-name="_451" unicode=""
+d="M1280 341q0 88 -62.5 151t-150.5 63q-84 0 -145 -58l-241 120q2 16 2 23t-2 23l241 120q61 -58 145 -58q88 0 150.5 63t62.5 151t-62.5 150.5t-150.5 62.5t-151 -62.5t-63 -150.5q0 -7 2 -23l-241 -120q-62 57 -145 57q-88 0 -150.5 -62.5t-62.5 -150.5t62.5 -150.5
+t150.5 -62.5q83 0 145 57l241 -120q-2 -16 -2 -23q0 -88 63 -150.5t151 -62.5t150.5 62.5t62.5 150.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="_452" unicode="" horiz-adv-x="1792"
+d="M571 947q-10 25 -34 35t-49 0q-108 -44 -191 -127t-127 -191q-10 -25 0 -49t35 -34q13 -5 24 -5q42 0 60 40q34 84 98.5 148.5t148.5 98.5q25 11 35 35t0 49zM1513 1303l46 -46l-244 -243l68 -68q19 -19 19 -45.5t-19 -45.5l-64 -64q89 -161 89 -343q0 -143 -55.5 -273.5
+t-150 -225t-225 -150t-273.5 -55.5t-273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5q182 0 343 -89l64 64q19 19 45.5 19t45.5 -19l68 -68zM1521 1359q-10 -10 -22 -10q-13 0 -23 10l-91 90q-9 10 -9 23t9 23q10 9 23 9t23 -9l90 -91
+q10 -9 10 -22.5t-10 -22.5zM1751 1129q-11 -9 -23 -9t-23 9l-90 91q-10 9 -10 22.5t10 22.5q9 10 22.5 10t22.5 -10l91 -90q9 -10 9 -23t-9 -23zM1792 1312q0 -14 -9 -23t-23 -9h-96q-14 0 -23 9t-9 23t9 23t23 9h96q14 0 23 -9t9 -23zM1600 1504v-96q0 -14 -9 -23t-23 -9
+t-23 9t-9 23v96q0 14 9 23t23 9t23 -9t9 -23zM1751 1449l-91 -90q-10 -10 -22 -10q-13 0 -23 10q-10 9 -10 22.5t10 22.5l90 91q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" />
+ <glyph glyph-name="_453" unicode="" horiz-adv-x="1792"
+d="M609 720l287 208l287 -208l-109 -336h-355zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM1515 186q149 203 149 454v3l-102 -89l-240 224l63 323
+l134 -12q-150 206 -389 282l53 -124l-287 -159l-287 159l53 124q-239 -76 -389 -282l135 12l62 -323l-240 -224l-102 89v-3q0 -251 149 -454l30 132l326 -40l139 -298l-116 -69q117 -39 240 -39t240 39l-116 69l139 298l326 40z" />
+ <glyph glyph-name="_454" unicode="" horiz-adv-x="1792"
+d="M448 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM256 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM832 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23
+v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM66 768q-28 0 -47 19t-19 46v129h514v-129q0 -27 -19 -46t-46 -19h-383zM1216 224v-192q0 -14 -9 -23t-23 -9h-192
+q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1600 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23
+zM1408 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1016v-13h-514v10q0 104 -382 102q-382 -1 -382 -102v-10h-514v13q0 17 8.5 43t34 64t65.5 75.5t110.5 76t160 67.5t224 47.5t293.5 18.5t293 -18.5t224 -47.5
+t160.5 -67.5t110.5 -76t65.5 -75.5t34 -64t8.5 -43zM1792 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 962v-129q0 -27 -19 -46t-46 -19h-384q-27 0 -46 19t-19 46v129h514z" />
+ <glyph glyph-name="_455" unicode="" horiz-adv-x="1792"
+d="M704 1216v-768q0 -26 -19 -45t-45 -19v-576q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v512l249 873q7 23 31 23h424zM1024 1216v-704h-256v704h256zM1792 320v-512q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v576q-26 0 -45 19t-19 45v768h424q24 0 31 -23z
+M736 1504v-224h-352v224q0 14 9 23t23 9h288q14 0 23 -9t9 -23zM1408 1504v-224h-352v224q0 14 9 23t23 9h288q14 0 23 -9t9 -23z" />
+ <glyph glyph-name="_456" unicode="" horiz-adv-x="1792"
+d="M1755 1083q37 -38 37 -90.5t-37 -90.5l-401 -400l150 -150l-160 -160q-163 -163 -389.5 -186.5t-411.5 100.5l-362 -362h-181v181l362 362q-124 185 -100.5 411.5t186.5 389.5l160 160l150 -150l400 401q38 37 91 37t90 -37t37 -90.5t-37 -90.5l-400 -401l234 -234
+l401 400q38 37 91 37t90 -37z" />
+ <glyph glyph-name="_457" unicode="" horiz-adv-x="1792"
+d="M873 796q0 -83 -63.5 -142.5t-152.5 -59.5t-152.5 59.5t-63.5 142.5q0 84 63.5 143t152.5 59t152.5 -59t63.5 -143zM1375 796q0 -83 -63 -142.5t-153 -59.5q-89 0 -152.5 59.5t-63.5 142.5q0 84 63.5 143t152.5 59q90 0 153 -59t63 -143zM1600 616v667q0 87 -32 123.5
+t-111 36.5h-1112q-83 0 -112.5 -34t-29.5 -126v-673q43 -23 88.5 -40t81 -28t81 -18.5t71 -11t70 -4t58.5 -0.5t56.5 2t44.5 2q68 1 95 -27q6 -6 10 -9q26 -25 61 -51q7 91 118 87q5 0 36.5 -1.5t43 -2t45.5 -1t53 1t54.5 4.5t61 8.5t62 13.5t67 19.5t67.5 27t72 34.5z
+M1763 621q-121 -149 -372 -252q84 -285 -23 -465q-66 -113 -183 -148q-104 -32 -182 15q-86 51 -82 164l-1 326v1q-8 2 -24.5 6t-23.5 5l-1 -338q4 -114 -83 -164q-79 -47 -183 -15q-117 36 -182 150q-105 180 -22 463q-251 103 -372 252q-25 37 -4 63t60 -1q4 -2 11.5 -7
+t10.5 -8v694q0 72 47 123t114 51h1257q67 0 114 -51t47 -123v-694l21 15q39 27 60 1t-4 -63z" />
+ <glyph glyph-name="_458" unicode="" horiz-adv-x="1792"
+d="M896 1102v-434h-145v434h145zM1294 1102v-434h-145v434h145zM1294 342l253 254v795h-1194v-1049h326v-217l217 217h398zM1692 1536v-1013l-434 -434h-326l-217 -217h-217v217h-398v1158l109 289h1483z" />
+ <glyph glyph-name="_459" unicode=""
+d="M773 217v-127q-1 -292 -6 -305q-12 -32 -51 -40q-54 -9 -181.5 38t-162.5 89q-13 15 -17 36q-1 12 4 26q4 10 34 47t181 216q1 0 60 70q15 19 39.5 24.5t49.5 -3.5q24 -10 37.5 -29t12.5 -42zM624 468q-3 -55 -52 -70l-120 -39q-275 -88 -292 -88q-35 2 -54 36
+q-12 25 -17 75q-8 76 1 166.5t30 124.5t56 32q13 0 202 -77q71 -29 115 -47l84 -34q23 -9 35.5 -30.5t11.5 -48.5zM1450 171q-7 -54 -91.5 -161t-135.5 -127q-37 -14 -63 7q-14 10 -184 287l-47 77q-14 21 -11.5 46t19.5 46q35 43 83 26q1 -1 119 -40q203 -66 242 -79.5
+t47 -20.5q28 -22 22 -61zM778 803q5 -102 -54 -122q-58 -17 -114 71l-378 598q-8 35 19 62q41 43 207.5 89.5t224.5 31.5q40 -10 49 -45q3 -18 22 -305.5t24 -379.5zM1440 695q3 -39 -26 -59q-15 -10 -329 -86q-67 -15 -91 -23l1 2q-23 -6 -46 4t-37 32q-30 47 0 87
+q1 1 75 102q125 171 150 204t34 39q28 19 65 2q48 -23 123 -133.5t81 -167.5v-3z" />
+ <glyph glyph-name="_460" unicode="" horiz-adv-x="2048"
+d="M1024 1024h-384v-384h384v384zM1152 384v-128h-640v128h640zM1152 1152v-640h-640v640h640zM1792 384v-128h-512v128h512zM1792 640v-128h-512v128h512zM1792 896v-128h-512v128h512zM1792 1152v-128h-512v128h512zM256 192v960h-128v-960q0 -26 19 -45t45 -19t45 19
+t19 45zM1920 192v1088h-1536v-1088q0 -33 -11 -64h1483q26 0 45 19t19 45zM2048 1408v-1216q0 -80 -56 -136t-136 -56h-1664q-80 0 -136 56t-56 136v1088h256v128h1792z" />
+ <glyph glyph-name="_461" unicode="" horiz-adv-x="2048"
+d="M1024 13q-20 0 -93 73.5t-73 93.5q0 32 62.5 54t103.5 22t103.5 -22t62.5 -54q0 -20 -73 -93.5t-93 -73.5zM1294 284q-2 0 -40 25t-101.5 50t-128.5 25t-128.5 -25t-101 -50t-40.5 -25q-18 0 -93.5 75t-75.5 93q0 13 10 23q78 77 196 121t233 44t233 -44t196 -121
+q10 -10 10 -23q0 -18 -75.5 -93t-93.5 -75zM1567 556q-11 0 -23 8q-136 105 -252 154.5t-268 49.5q-85 0 -170.5 -22t-149 -53t-113.5 -62t-79 -53t-31 -22q-17 0 -92 75t-75 93q0 12 10 22q132 132 320 205t380 73t380 -73t320 -205q10 -10 10 -22q0 -18 -75 -93t-92 -75z
+M1838 827q-11 0 -22 9q-179 157 -371.5 236.5t-420.5 79.5t-420.5 -79.5t-371.5 -236.5q-11 -9 -22 -9q-17 0 -92.5 75t-75.5 93q0 13 10 23q187 186 445 288t527 102t527 -102t445 -288q10 -10 10 -23q0 -18 -75.5 -93t-92.5 -75z" />
+ <glyph glyph-name="_462" unicode="" horiz-adv-x="1792"
+d="M384 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5
+t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1152 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5
+t37.5 90.5zM384 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1152 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 768q0 53 -37.5 90.5t-90.5 37.5
+t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1536 0v384q0 52 -38 90t-90 38t-90 -38t-38 -90v-384q0 -52 38 -90t90 -38t90 38t38 90zM1152 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5z
+M1536 1088v256q0 26 -19 45t-45 19h-1280q-26 0 -45 -19t-19 -45v-256q0 -26 19 -45t45 -19h1280q26 0 45 19t19 45zM1536 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1408v-1536q0 -52 -38 -90t-90 -38
+h-1408q-52 0 -90 38t-38 90v1536q0 52 38 90t90 38h1408q52 0 90 -38t38 -90z" />
+ <glyph glyph-name="_463" unicode=""
+d="M1519 890q18 -84 -4 -204q-87 -444 -565 -444h-44q-25 0 -44 -16.5t-24 -42.5l-4 -19l-55 -346l-2 -15q-5 -26 -24.5 -42.5t-44.5 -16.5h-251q-21 0 -33 15t-9 36q9 56 26.5 168t26.5 168t27 167.5t27 167.5q5 37 43 37h131q133 -2 236 21q175 39 287 144q102 95 155 246
+q24 70 35 133q1 6 2.5 7.5t3.5 1t6 -3.5q79 -59 98 -162zM1347 1172q0 -107 -46 -236q-80 -233 -302 -315q-113 -40 -252 -42q0 -1 -90 -1l-90 1q-100 0 -118 -96q-2 -8 -85 -530q-1 -10 -12 -10h-295q-22 0 -36.5 16.5t-11.5 38.5l232 1471q5 29 27.5 48t51.5 19h598
+q34 0 97.5 -13t111.5 -32q107 -41 163.5 -123t56.5 -196z" />
+ <glyph glyph-name="_464" unicode="" horiz-adv-x="1792"
+d="M441 864q33 0 52 -26q266 -364 362 -774h-446q-127 441 -367 749q-12 16 -3 33.5t29 17.5h373zM1000 507q-49 -199 -125 -393q-79 310 -256 594q40 221 44 449q211 -340 337 -650zM1099 1216q235 -324 384.5 -698.5t184.5 -773.5h-451q-41 665 -553 1472h435zM1792 640
+q0 -424 -101 -812q-67 560 -359 1083q-25 301 -106 584q-4 16 5.5 28.5t25.5 12.5h359q21 0 38.5 -13t22.5 -33q115 -409 115 -850z" />
+ <glyph glyph-name="uniF1F0" unicode="" horiz-adv-x="2304"
+d="M1975 546h-138q14 37 66 179l3 9q4 10 10 26t9 26l12 -55zM531 611l-58 295q-11 54 -75 54h-268l-2 -13q311 -79 403 -336zM710 960l-162 -438l-17 89q-26 70 -85 129.5t-131 88.5l135 -510h175l261 641h-176zM849 318h166l104 642h-166zM1617 944q-69 27 -149 27
+q-123 0 -201 -59t-79 -153q-1 -102 145 -174q48 -23 67 -41t19 -39q0 -30 -30 -46t-69 -16q-86 0 -156 33l-22 11l-23 -144q74 -34 185 -34q130 -1 208.5 59t80.5 160q0 106 -140 174q-49 25 -71 42t-22 38q0 22 24.5 38.5t70.5 16.5q70 1 124 -24l15 -8zM2042 960h-128
+q-65 0 -87 -54l-246 -588h174l35 96h212q5 -22 20 -96h154zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+ <glyph glyph-name="_466" unicode="" horiz-adv-x="2304"
+d="M1119 1195q-128 85 -281 85q-103 0 -197.5 -40.5t-162.5 -108.5t-108.5 -162t-40.5 -197q0 -104 40.5 -198t108.5 -162t162 -108.5t198 -40.5q153 0 281 85q-131 107 -178 265.5t0.5 316.5t177.5 265zM1152 1171q-126 -99 -172 -249.5t-0.5 -300.5t172.5 -249
+q127 99 172.5 249t-0.5 300.5t-172 249.5zM1185 1195q130 -107 177.5 -265.5t0.5 -317t-178 -264.5q128 -85 281 -85q104 0 198 40.5t162 108.5t108.5 162t40.5 198q0 103 -40.5 197t-108.5 162t-162.5 108.5t-197.5 40.5q-153 0 -281 -85zM1926 473h7v3h-17v-3h7v-17h3v17z
+M1955 456h4v20h-5l-6 -13l-6 13h-5v-20h3v15l6 -13h4l5 13v-15zM1947 16v-2h-2h-3v3h3h2v-1zM1947 7h3l-4 5h2l1 1q1 1 1 3t-1 3l-1 1h-3h-6v-13h3v5h1zM685 75q0 19 11 31t30 12q18 0 29 -12.5t11 -30.5q0 -19 -11 -31t-29 -12q-19 0 -30 12t-11 31zM1158 119q30 0 35 -32
+h-70q5 32 35 32zM1514 75q0 19 11 31t29 12t29.5 -12.5t11.5 -30.5q0 -19 -11 -31t-30 -12q-18 0 -29 12t-11 31zM1786 75q0 18 11.5 30.5t29.5 12.5t29.5 -12.5t11.5 -30.5q0 -19 -11.5 -31t-29.5 -12t-29.5 12.5t-11.5 30.5zM1944 3q-2 0 -4 1q-1 0 -3 2t-2 3q-1 2 -1 4
+q0 3 1 4q0 2 2 4l1 1q2 0 2 1q2 1 4 1q3 0 4 -1l4 -2l2 -4v-1q1 -2 1 -3l-1 -1v-3t-1 -1l-1 -2q-2 -2 -4 -2q-1 -1 -4 -1zM599 7h30v85q0 24 -14.5 38.5t-39.5 15.5q-32 0 -47 -24q-14 24 -45 24q-24 0 -39 -20v16h-30v-135h30v75q0 36 33 36q30 0 30 -36v-75h29v75
+q0 36 33 36q30 0 30 -36v-75zM765 7h29v68v67h-29v-16q-17 20 -43 20q-29 0 -48 -20t-19 -51t19 -51t48 -20q28 0 43 20v-17zM943 48q0 34 -47 40l-14 2q-23 4 -23 14q0 15 25 15q23 0 43 -11l12 24q-22 14 -55 14q-26 0 -41 -12t-15 -32q0 -33 47 -39l13 -2q24 -4 24 -14
+q0 -17 -31 -17q-25 0 -45 14l-13 -23q25 -17 58 -17q29 0 45.5 12t16.5 32zM1073 14l-8 25q-13 -7 -26 -7q-19 0 -19 22v61h48v27h-48v41h-30v-41h-28v-27h28v-61q0 -50 47 -50q21 0 36 10zM1159 146q-29 0 -48 -20t-19 -51q0 -32 19.5 -51.5t49.5 -19.5q33 0 55 19l-14 22
+q-18 -15 -39 -15q-34 0 -41 33h101v12q0 32 -18 51.5t-46 19.5zM1318 146q-23 0 -35 -20v16h-30v-135h30v76q0 35 29 35q10 0 18 -4l9 28q-9 4 -21 4zM1348 75q0 -31 19.5 -51t52.5 -20q29 0 48 16l-14 24q-18 -13 -35 -12q-18 0 -29.5 12t-11.5 31t11.5 31t29.5 12
+q19 0 35 -12l14 24q-20 16 -48 16q-33 0 -52.5 -20t-19.5 -51zM1593 7h30v68v67h-30v-16q-15 20 -42 20q-29 0 -48.5 -20t-19.5 -51t19.5 -51t48.5 -20q28 0 42 20v-17zM1726 146q-23 0 -35 -20v16h-29v-135h29v76q0 35 29 35q10 0 18 -4l9 28q-8 4 -21 4zM1866 7h29v68v122
+h-29v-71q-15 20 -43 20t-47.5 -20.5t-19.5 -50.5t19.5 -50.5t47.5 -20.5q29 0 43 20v-17zM1944 27l-2 -1h-3q-2 -1 -4 -3q-3 -1 -3 -4q-1 -2 -1 -6q0 -3 1 -5q0 -2 3 -4q2 -2 4 -3t5 -1q4 0 6 1q0 1 2 2l2 1q1 1 3 4q1 2 1 5q0 4 -1 6q-1 1 -3 4q0 1 -2 2l-2 1q-1 0 -3 0.5
+t-3 0.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+ <glyph glyph-name="_467" unicode="" horiz-adv-x="2304"
+d="M313 759q0 -51 -36 -84q-29 -26 -89 -26h-17v220h17q61 0 89 -27q36 -31 36 -83zM2089 824q0 -52 -64 -52h-19v101h20q63 0 63 -49zM380 759q0 74 -50 120.5t-129 46.5h-95v-333h95q74 0 119 38q60 51 60 128zM410 593h65v333h-65v-333zM730 694q0 40 -20.5 62t-75.5 42
+q-29 10 -39.5 19t-10.5 23q0 16 13.5 26.5t34.5 10.5q29 0 53 -27l34 44q-41 37 -98 37q-44 0 -74 -27.5t-30 -67.5q0 -35 18 -55.5t64 -36.5q37 -13 45 -19q19 -12 19 -34q0 -20 -14 -33.5t-36 -13.5q-48 0 -71 44l-42 -40q44 -64 115 -64q51 0 83 30.5t32 79.5zM1008 604
+v77q-37 -37 -78 -37q-49 0 -80.5 32.5t-31.5 82.5q0 48 31.5 81.5t77.5 33.5q43 0 81 -38v77q-40 20 -80 20q-74 0 -125.5 -50.5t-51.5 -123.5t51 -123.5t125 -50.5q42 0 81 19zM2240 0v527q-65 -40 -144.5 -84t-237.5 -117t-329.5 -137.5t-417.5 -134.5t-504 -118h1569
+q26 0 45 19t19 45zM1389 757q0 75 -53 128t-128 53t-128 -53t-53 -128t53 -128t128 -53t128 53t53 128zM1541 584l144 342h-71l-90 -224l-89 224h-71l142 -342h35zM1714 593h184v56h-119v90h115v56h-115v74h119v57h-184v-333zM2105 593h80l-105 140q76 16 76 94q0 47 -31 73
+t-87 26h-97v-333h65v133h9zM2304 1274v-1268q0 -56 -38.5 -95t-93.5 -39h-2040q-55 0 -93.5 39t-38.5 95v1268q0 56 38.5 95t93.5 39h2040q55 0 93.5 -39t38.5 -95z" />
+ <glyph glyph-name="f1f3" unicode="" horiz-adv-x="2304"
+d="M119 854h89l-45 108zM740 328l74 79l-70 79h-163v-49h142v-55h-142v-54h159zM898 406l99 -110v217zM1186 453q0 33 -40 33h-84v-69h83q41 0 41 36zM1475 457q0 29 -42 29h-82v-61h81q43 0 43 32zM1197 923q0 29 -42 29h-82v-60h81q43 0 43 31zM1656 854h89l-44 108z
+M699 1009v-271h-66v212l-94 -212h-57l-94 212v-212h-132l-25 60h-135l-25 -60h-70l116 271h96l110 -257v257h106l85 -184l77 184h108zM1255 453q0 -20 -5.5 -35t-14 -25t-22.5 -16.5t-26 -10t-31.5 -4.5t-31.5 -1t-32.5 0.5t-29.5 0.5v-91h-126l-80 90l-83 -90h-256v271h260
+l80 -89l82 89h207q109 0 109 -89zM964 794v-56h-217v271h217v-57h-152v-49h148v-55h-148v-54h152zM2304 235v-229q0 -55 -38.5 -94.5t-93.5 -39.5h-2040q-55 0 -93.5 39.5t-38.5 94.5v678h111l25 61h55l25 -61h218v46l19 -46h113l20 47v-47h541v99l10 1q10 0 10 -14v-86h279
+v23q23 -12 55 -18t52.5 -6.5t63 0.5t51.5 1l25 61h56l25 -61h227v58l34 -58h182v378h-180v-44l-25 44h-185v-44l-23 44h-249q-69 0 -109 -22v22h-172v-22q-24 22 -73 22h-628l-43 -97l-43 97h-198v-44l-22 44h-169l-78 -179v391q0 55 38.5 94.5t93.5 39.5h2040
+q55 0 93.5 -39.5t38.5 -94.5v-678h-120q-51 0 -81 -22v22h-177q-55 0 -78 -22v22h-316v-22q-31 22 -87 22h-209v-22q-23 22 -91 22h-234l-54 -58l-50 58h-349v-378h343l55 59l52 -59h211v89h21q59 0 90 13v-102h174v99h8q8 0 10 -2t2 -10v-87h529q57 0 88 24v-24h168
+q60 0 95 17zM1546 469q0 -23 -12 -43t-34 -29q25 -9 34 -26t9 -46v-54h-65v45q0 33 -12 43.5t-46 10.5h-69v-99h-65v271h154q48 0 77 -15t29 -58zM1269 936q0 -24 -12.5 -44t-33.5 -29q26 -9 34.5 -25.5t8.5 -46.5v-53h-65q0 9 0.5 26.5t0 25t-3 18.5t-8.5 16t-17.5 8.5
+t-29.5 3.5h-70v-98h-64v271l153 -1q49 0 78 -14.5t29 -57.5zM1798 327v-56h-216v271h216v-56h-151v-49h148v-55h-148v-54zM1372 1009v-271h-66v271h66zM2065 357q0 -86 -102 -86h-126v58h126q34 0 34 25q0 16 -17 21t-41.5 5t-49.5 3.5t-42 22.5t-17 55q0 39 26 60t66 21
+h130v-57h-119q-36 0 -36 -25q0 -16 17.5 -20.5t42 -4t49 -2.5t42 -21.5t17.5 -54.5zM2304 407v-101q-24 -35 -88 -35h-125v58h125q33 0 33 25q0 13 -12.5 19t-31 5.5t-40 2t-40 8t-31 24t-12.5 48.5q0 39 26.5 60t66.5 21h129v-57h-118q-36 0 -36 -25q0 -20 29 -22t68.5 -5
+t56.5 -26zM2139 1008v-270h-92l-122 203v-203h-132l-26 60h-134l-25 -60h-75q-129 0 -129 133q0 138 133 138h63v-59q-7 0 -28 1t-28.5 0.5t-23 -2t-21.5 -6.5t-14.5 -13.5t-11.5 -23t-3 -33.5q0 -38 13.5 -58t49.5 -20h29l92 213h97l109 -256v256h99l114 -188v188h66z" />
+ <glyph glyph-name="_469" unicode="" horiz-adv-x="2304"
+d="M745 630q0 -37 -25.5 -61.5t-62.5 -24.5q-29 0 -46.5 16t-17.5 44q0 37 25 62.5t62 25.5q28 0 46.5 -16.5t18.5 -45.5zM1530 779q0 -42 -22 -57t-66 -15l-32 -1l17 107q2 11 13 11h18q22 0 35 -2t25 -12.5t12 -30.5zM1881 630q0 -36 -25.5 -61t-61.5 -25q-29 0 -47 16
+t-18 44q0 37 25 62.5t62 25.5q28 0 46.5 -16.5t18.5 -45.5zM513 801q0 59 -38.5 85.5t-100.5 26.5h-160q-19 0 -21 -19l-65 -408q-1 -6 3 -11t10 -5h76q20 0 22 19l18 110q1 8 7 13t15 6.5t17 1.5t19 -1t14 -1q86 0 135 48.5t49 134.5zM822 489l41 261q1 6 -3 11t-10 5h-76
+q-14 0 -17 -33q-27 40 -95 40q-72 0 -122.5 -54t-50.5 -127q0 -59 34.5 -94t92.5 -35q28 0 58 12t48 32q-4 -12 -4 -21q0 -16 13 -16h69q19 0 22 19zM1269 752q0 5 -4 9.5t-9 4.5h-77q-11 0 -18 -10l-106 -156l-44 150q-5 16 -22 16h-75q-5 0 -9 -4.5t-4 -9.5q0 -2 19.5 -59
+t42 -123t23.5 -70q-82 -112 -82 -120q0 -13 13 -13h77q11 0 18 10l255 368q2 2 2 7zM1649 801q0 59 -38.5 85.5t-100.5 26.5h-159q-20 0 -22 -19l-65 -408q-1 -6 3 -11t10 -5h82q12 0 16 13l18 116q1 8 7 13t15 6.5t17 1.5t19 -1t14 -1q86 0 135 48.5t49 134.5zM1958 489
+l41 261q1 6 -3 11t-10 5h-76q-14 0 -17 -33q-26 40 -95 40q-72 0 -122.5 -54t-50.5 -127q0 -59 34.5 -94t92.5 -35q29 0 59 12t47 32q0 -1 -2 -9t-2 -12q0 -16 13 -16h69q19 0 22 19zM2176 898v1q0 14 -13 14h-74q-11 0 -13 -11l-65 -416l-1 -2q0 -5 4 -9.5t10 -4.5h66
+q19 0 21 19zM392 764q-5 -35 -26 -46t-60 -11l-33 -1l17 107q2 11 13 11h19q40 0 58 -11.5t12 -48.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+ <glyph glyph-name="_470" unicode="" horiz-adv-x="2304"
+d="M1597 633q0 -69 -21 -106q-19 -35 -52 -35q-23 0 -41 9v224q29 30 57 30q57 0 57 -122zM2035 669h-110q6 98 56 98q51 0 54 -98zM476 534q0 59 -33 91.5t-101 57.5q-36 13 -52 24t-16 25q0 26 38 26q58 0 124 -33l18 112q-67 32 -149 32q-77 0 -123 -38q-48 -39 -48 -109
+q0 -58 32.5 -90.5t99.5 -56.5q39 -14 54.5 -25.5t15.5 -27.5q0 -31 -48 -31q-29 0 -70 12.5t-72 30.5l-18 -113q72 -41 168 -41q81 0 129 37q51 41 51 117zM771 749l19 111h-96v135l-129 -21l-18 -114l-46 -8l-17 -103h62v-219q0 -84 44 -120q38 -30 111 -30q32 0 79 11v118
+q-32 -7 -44 -7q-42 0 -42 50v197h77zM1087 724v139q-15 3 -28 3q-32 0 -55.5 -16t-33.5 -46l-10 56h-131v-471h150v306q26 31 82 31q16 0 26 -2zM1124 389h150v471h-150v-471zM1746 638q0 122 -45 179q-40 52 -111 52q-64 0 -117 -56l-8 47h-132v-645l150 25v151
+q36 -11 68 -11q83 0 134 56q61 65 61 202zM1278 986q0 33 -23 56t-56 23t-56 -23t-23 -56t23 -56.5t56 -23.5t56 23.5t23 56.5zM2176 629q0 113 -48 176q-50 64 -144 64q-96 0 -151.5 -66t-55.5 -180q0 -128 63 -188q55 -55 161 -55q101 0 160 40l-16 103q-57 -31 -128 -31
+q-43 0 -63 19q-23 19 -28 66h248q2 14 2 52zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+ <glyph glyph-name="_471" unicode="" horiz-adv-x="2048"
+d="M1558 684q61 -356 298 -556q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5zM1024 -176q16 0 16 16t-16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5zM2026 1424q8 -10 7.5 -23.5t-10.5 -22.5
+l-1872 -1622q-10 -8 -23.5 -7t-21.5 11l-84 96q-8 10 -7.5 23.5t10.5 21.5l186 161q-19 32 -19 66q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q124 -18 219 -82.5t148 -157.5
+l418 363q10 8 23.5 7t21.5 -11z" />
+ <glyph glyph-name="_472" unicode="" horiz-adv-x="2048"
+d="M1040 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM503 315l877 760q-42 88 -132.5 146.5t-223.5 58.5q-93 0 -169.5 -31.5t-121.5 -80.5t-69 -103t-24 -105q0 -384 -137 -645zM1856 128
+q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5l149 129h757q-166 187 -227 459l111 97q61 -356 298 -556zM1942 1520l84 -96q8 -10 7.5 -23.5t-10.5 -22.5l-1872 -1622q-10 -8 -23.5 -7t-21.5 11l-84 96q-8 10 -7.5 23.5t10.5 21.5l186 161
+q-19 32 -19 66q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q124 -18 219 -82.5t148 -157.5l418 363q10 8 23.5 7t21.5 -11z" />
+ <glyph glyph-name="_473" unicode="" horiz-adv-x="1408"
+d="M512 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM768 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1024 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704
+q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167
+q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" />
+ <glyph glyph-name="_474" unicode=""
+d="M1150 462v-109q0 -50 -36.5 -89t-94 -60.5t-118 -32.5t-117.5 -11q-205 0 -342.5 139t-137.5 346q0 203 136 339t339 136q34 0 75.5 -4.5t93 -18t92.5 -34t69 -56.5t28 -81v-109q0 -16 -16 -16h-118q-16 0 -16 16v70q0 43 -65.5 67.5t-137.5 24.5q-140 0 -228.5 -91.5
+t-88.5 -237.5q0 -151 91.5 -249.5t233.5 -98.5q68 0 138 24t70 66v70q0 7 4.5 11.5t10.5 4.5h119q6 0 11 -4.5t5 -11.5zM768 1280q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5
+t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="_475" unicode=""
+d="M972 761q0 108 -53.5 169t-147.5 61q-63 0 -124 -30.5t-110 -84.5t-79.5 -137t-30.5 -180q0 -112 53.5 -173t150.5 -61q96 0 176 66.5t122.5 166t42.5 203.5zM1536 640q0 -111 -37 -197t-98.5 -135t-131.5 -74.5t-145 -27.5q-6 0 -15.5 -0.5t-16.5 -0.5q-95 0 -142 53
+q-28 33 -33 83q-52 -66 -131.5 -110t-173.5 -44q-161 0 -249.5 95.5t-88.5 269.5q0 157 66 290t179 210.5t246 77.5q87 0 155 -35.5t106 -99.5l2 19l11 56q1 6 5.5 12t9.5 6h118q5 0 13 -11q5 -5 3 -16l-120 -614q-5 -24 -5 -48q0 -39 12.5 -52t44.5 -13q28 1 57 5.5t73 24
+t77 50t57 89.5t24 137q0 292 -174 466t-466 174q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51q228 0 405 144q11 9 24 8t21 -12l41 -49q8 -12 7 -24q-2 -13 -12 -22q-102 -83 -227.5 -128t-258.5 -45q-156 0 -298 61
+t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q344 0 556 -212t212 -556z" />
+ <glyph glyph-name="_476" unicode="" horiz-adv-x="1792"
+d="M1698 1442q94 -94 94 -226.5t-94 -225.5l-225 -223l104 -104q10 -10 10 -23t-10 -23l-210 -210q-10 -10 -23 -10t-23 10l-105 105l-603 -603q-37 -37 -90 -37h-203l-256 -128l-64 64l128 256v203q0 53 37 90l603 603l-105 105q-10 10 -10 23t10 23l210 210q10 10 23 10
+t23 -10l104 -104l223 225q93 94 225.5 94t226.5 -94zM512 64l576 576l-192 192l-576 -576v-192h192z" />
+ <glyph glyph-name="f1fc" unicode="" horiz-adv-x="1792"
+d="M1615 1536q70 0 122.5 -46.5t52.5 -116.5q0 -63 -45 -151q-332 -629 -465 -752q-97 -91 -218 -91q-126 0 -216.5 92.5t-90.5 219.5q0 128 92 212l638 579q59 54 130 54zM706 502q39 -76 106.5 -130t150.5 -76l1 -71q4 -213 -129.5 -347t-348.5 -134q-123 0 -218 46.5
+t-152.5 127.5t-86.5 183t-29 220q7 -5 41 -30t62 -44.5t59 -36.5t46 -17q41 0 55 37q25 66 57.5 112.5t69.5 76t88 47.5t103 25.5t125 10.5z" />
+ <glyph glyph-name="_478" unicode="" horiz-adv-x="1792"
+d="M1792 128v-384h-1792v384q45 0 85 14t59 27.5t47 37.5q30 27 51.5 38t56.5 11q24 0 44 -7t31 -15t33 -27q29 -25 47 -38t58 -27t86 -14q45 0 85 14.5t58 27t48 37.5q21 19 32.5 27t31 15t43.5 7q35 0 56.5 -11t51.5 -38q28 -24 47 -37.5t59 -27.5t85 -14t85 14t59 27.5
+t47 37.5q30 27 51.5 38t56.5 11q34 0 55.5 -11t51.5 -38q28 -24 47 -37.5t59 -27.5t85 -14zM1792 448v-192q-24 0 -44 7t-31 15t-33 27q-29 25 -47 38t-58 27t-85 14q-46 0 -86 -14t-58 -27t-47 -38q-22 -19 -33 -27t-31 -15t-44 -7q-35 0 -56.5 11t-51.5 38q-29 25 -47 38
+t-58 27t-86 14q-45 0 -85 -14.5t-58 -27t-48 -37.5q-21 -19 -32.5 -27t-31 -15t-43.5 -7q-35 0 -56.5 11t-51.5 38q-28 24 -47 37.5t-59 27.5t-85 14q-46 0 -86 -14t-58 -27t-47 -38q-30 -27 -51.5 -38t-56.5 -11v192q0 80 56 136t136 56h64v448h256v-448h256v448h256v-448
+h256v448h256v-448h64q80 0 136 -56t56 -136zM512 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150zM1024 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5
+q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150zM1536 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150z" />
+ <glyph glyph-name="_479" unicode="" horiz-adv-x="2048"
+d="M2048 0v-128h-2048v1536h128v-1408h1920zM1664 1024l256 -896h-1664v576l448 576l576 -576z" />
+ <glyph glyph-name="_480" unicode="" horiz-adv-x="1792"
+d="M768 646l546 -546q-106 -108 -247.5 -168t-298.5 -60q-209 0 -385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103v-762zM955 640h773q0 -157 -60 -298.5t-168 -247.5zM1664 768h-768v768q209 0 385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="_481" unicode="" horiz-adv-x="2048"
+d="M2048 0v-128h-2048v1536h128v-1408h1920zM1920 1248v-435q0 -21 -19.5 -29.5t-35.5 7.5l-121 121l-633 -633q-10 -10 -23 -10t-23 10l-233 233l-416 -416l-192 192l585 585q10 10 23 10t23 -10l233 -233l464 464l-121 121q-16 16 -7.5 35.5t29.5 19.5h435q14 0 23 -9
+t9 -23z" />
+ <glyph glyph-name="_482" unicode="" horiz-adv-x="1792"
+d="M1292 832q0 -6 10 -41q10 -29 25 -49.5t41 -34t44 -20t55 -16.5q325 -91 325 -332q0 -146 -105.5 -242.5t-254.5 -96.5q-59 0 -111.5 18.5t-91.5 45.5t-77 74.5t-63 87.5t-53.5 103.5t-43.5 103t-39.5 106.5t-35.5 95q-32 81 -61.5 133.5t-73.5 96.5t-104 64t-142 20
+q-96 0 -183 -55.5t-138 -144.5t-51 -185q0 -160 106.5 -279.5t263.5 -119.5q177 0 258 95q56 63 83 116l84 -152q-15 -34 -44 -70l1 -1q-131 -152 -388 -152q-147 0 -269.5 79t-190.5 207.5t-68 274.5q0 105 43.5 206t116 176.5t172 121.5t204.5 46q87 0 159 -19t123.5 -50
+t95 -80t72.5 -99t58.5 -117t50.5 -124.5t50 -130.5t55 -127q96 -200 233 -200q81 0 138.5 48.5t57.5 128.5q0 42 -19 72t-50.5 46t-72.5 31.5t-84.5 27t-87.5 34t-81 52t-65 82t-39 122.5q-3 16 -3 33q0 110 87.5 192t198.5 78q78 -3 120.5 -14.5t90.5 -53.5h-1
+q12 -11 23 -24.5t26 -36t19 -27.5l-129 -99q-26 49 -54 70v1q-23 21 -97 21q-49 0 -84 -33t-35 -83z" />
+ <glyph glyph-name="_483" unicode=""
+d="M1432 484q0 173 -234 239q-35 10 -53 16.5t-38 25t-29 46.5q0 2 -2 8.5t-3 12t-1 7.5q0 36 24.5 59.5t60.5 23.5q54 0 71 -15h-1q20 -15 39 -51l93 71q-39 54 -49 64q-33 29 -67.5 39t-85.5 10q-80 0 -142 -57.5t-62 -137.5q0 -7 2 -23q16 -96 64.5 -140t148.5 -73
+q29 -8 49 -15.5t45 -21.5t38.5 -34.5t13.5 -46.5v-5q1 -58 -40.5 -93t-100.5 -35q-97 0 -167 144q-23 47 -51.5 121.5t-48 125.5t-54 110.5t-74 95.5t-103.5 60.5t-147 24.5q-101 0 -192 -56t-144 -148t-50 -192v-1q4 -108 50.5 -199t133.5 -147.5t196 -56.5q186 0 279 110
+q20 27 31 51l-60 109q-42 -80 -99 -116t-146 -36q-115 0 -191 87t-76 204q0 105 82 189t186 84q112 0 170 -53.5t104 -172.5q8 -21 25.5 -68.5t28.5 -76.5t31.5 -74.5t38.5 -74t45.5 -62.5t55.5 -53.5t66 -33t80 -13.5q107 0 183 69.5t76 174.5zM1536 1120v-960
+q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="_484" unicode="" horiz-adv-x="2048"
+d="M1152 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1920 640q0 104 -40.5 198.5
+t-109.5 163.5t-163.5 109.5t-198.5 40.5h-386q119 -90 188.5 -224t69.5 -288t-69.5 -288t-188.5 -224h386q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM2048 640q0 -130 -51 -248.5t-136.5 -204t-204 -136.5t-248.5 -51h-768q-130 0 -248.5 51t-204 136.5
+t-136.5 204t-51 248.5t51 248.5t136.5 204t204 136.5t248.5 51h768q130 0 248.5 -51t204 -136.5t136.5 -204t51 -248.5z" />
+ <glyph glyph-name="_485" unicode="" horiz-adv-x="2048"
+d="M0 640q0 130 51 248.5t136.5 204t204 136.5t248.5 51h768q130 0 248.5 -51t204 -136.5t136.5 -204t51 -248.5t-51 -248.5t-136.5 -204t-204 -136.5t-248.5 -51h-768q-130 0 -248.5 51t-204 136.5t-136.5 204t-51 248.5zM1408 128q104 0 198.5 40.5t163.5 109.5
+t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5z" />
+ <glyph glyph-name="_486" unicode="" horiz-adv-x="2304"
+d="M762 384h-314q-40 0 -57.5 35t6.5 67l188 251q-65 31 -137 31q-132 0 -226 -94t-94 -226t94 -226t226 -94q115 0 203 72.5t111 183.5zM576 512h186q-18 85 -75 148zM1056 512l288 384h-480l-99 -132q105 -103 126 -252h165zM2176 448q0 132 -94 226t-226 94
+q-60 0 -121 -24l174 -260q15 -23 10 -49t-27 -40q-15 -11 -36 -11q-35 0 -53 29l-174 260q-93 -95 -93 -225q0 -132 94 -226t226 -94t226 94t94 226zM2304 448q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 97 39.5 183.5t109.5 149.5l-65 98l-353 -469
+q-18 -26 -51 -26h-197q-23 -164 -149 -274t-294 -110q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q114 0 215 -55l137 183h-224q-26 0 -45 19t-19 45t19 45t45 19h384v-128h435l-85 128h-222q-26 0 -45 19t-19 45t19 45t45 19h256q33 0 53 -28l267 -400
+q91 44 192 44q185 0 316.5 -131.5t131.5 -316.5z" />
+ <glyph glyph-name="_487" unicode=""
+d="M384 320q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1408 320q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1362 716l-72 384q-5 23 -22.5 37.5t-40.5 14.5
+h-918q-23 0 -40.5 -14.5t-22.5 -37.5l-72 -384q-5 -30 14 -53t49 -23h1062q30 0 49 23t14 53zM1136 1328q0 20 -14 34t-34 14h-640q-20 0 -34 -14t-14 -34t14 -34t34 -14h640q20 0 34 14t14 34zM1536 603v-603h-128v-128q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5
+t-37.5 90.5v128h-768v-128q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5v128h-128v603q0 112 25 223l103 454q9 78 97.5 137t230 89t312.5 30t312.5 -30t230 -89t97.5 -137l105 -454q23 -102 23 -223z" />
+ <glyph glyph-name="_488" unicode="" horiz-adv-x="2048"
+d="M1463 704q0 -35 -25 -60.5t-61 -25.5h-702q-36 0 -61 25.5t-25 60.5t25 60.5t61 25.5h702q36 0 61 -25.5t25 -60.5zM1677 704q0 86 -23 170h-982q-36 0 -61 25t-25 60q0 36 25 61t61 25h908q-88 143 -235 227t-320 84q-177 0 -327.5 -87.5t-238 -237.5t-87.5 -327
+q0 -86 23 -170h982q36 0 61 -25t25 -60q0 -36 -25 -61t-61 -25h-908q88 -143 235.5 -227t320.5 -84q132 0 253 51.5t208 139t139 208t52 253.5zM2048 959q0 -35 -25 -60t-61 -25h-131q17 -85 17 -170q0 -167 -65.5 -319.5t-175.5 -263t-262.5 -176t-319.5 -65.5
+q-246 0 -448.5 133t-301.5 350h-189q-36 0 -61 25t-25 61q0 35 25 60t61 25h132q-17 85 -17 170q0 167 65.5 319.5t175.5 263t262.5 176t320.5 65.5q245 0 447.5 -133t301.5 -350h188q36 0 61 -25t25 -61z" />
+ <glyph glyph-name="_489" unicode="" horiz-adv-x="1280"
+d="M953 1158l-114 -328l117 -21q165 451 165 518q0 56 -38 56q-57 0 -130 -225zM654 471l33 -88q37 42 71 67l-33 5.5t-38.5 7t-32.5 8.5zM362 1367q0 -98 159 -521q17 10 49 10q15 0 75 -5l-121 351q-75 220 -123 220q-19 0 -29 -17.5t-10 -37.5zM283 608q0 -36 51.5 -119
+t117.5 -153t100 -70q14 0 25.5 13t11.5 27q0 24 -32 102q-13 32 -32 72t-47.5 89t-61.5 81t-62 32q-20 0 -45.5 -27t-25.5 -47zM125 273q0 -41 25 -104q59 -145 183.5 -227t281.5 -82q227 0 382 170q152 169 152 427q0 43 -1 67t-11.5 62t-30.5 56q-56 49 -211.5 75.5
+t-270.5 26.5q-37 0 -49 -11q-12 -5 -12 -35q0 -34 21.5 -60t55.5 -40t77.5 -23.5t87.5 -11.5t85 -4t70 0h23q24 0 40 -19q15 -19 19 -55q-28 -28 -96 -54q-61 -22 -93 -46q-64 -46 -108.5 -114t-44.5 -137q0 -31 18.5 -88.5t18.5 -87.5l-3 -12q-4 -12 -4 -14
+q-137 10 -146 216q-8 -2 -41 -2q2 -7 2 -21q0 -53 -40.5 -89.5t-94.5 -36.5q-82 0 -166.5 78t-84.5 159q0 34 33 67q52 -64 60 -76q77 -104 133 -104q12 0 26.5 8.5t14.5 20.5q0 34 -87.5 145t-116.5 111q-43 0 -70 -44.5t-27 -90.5zM11 264q0 101 42.5 163t136.5 88
+q-28 74 -28 104q0 62 61 123t122 61q29 0 70 -15q-163 462 -163 567q0 80 41 130.5t119 50.5q131 0 325 -581q6 -17 8 -23q6 16 29 79.5t43.5 118.5t54 127.5t64.5 123t70.5 86.5t76.5 36q71 0 112 -49t41 -122q0 -108 -159 -550q61 -15 100.5 -46t58.5 -78t26 -93.5
+t7 -110.5q0 -150 -47 -280t-132 -225t-211 -150t-278 -55q-111 0 -223 42q-149 57 -258 191.5t-109 286.5z" />
+ <glyph glyph-name="_490" unicode="" horiz-adv-x="2048"
+d="M785 528h207q-14 -158 -98.5 -248.5t-214.5 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-203q-5 64 -35.5 99t-81.5 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t40 -51.5t66 -18q95 0 109 139zM1497 528h206
+q-14 -158 -98 -248.5t-214 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-204q-4 64 -35 99t-81 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t39.5 -51.5t65.5 -18q49 0 76.5 38t33.5 101zM1856 647q0 207 -15.5 307
+t-60.5 161q-6 8 -13.5 14t-21.5 15t-16 11q-86 63 -697 63q-625 0 -710 -63q-5 -4 -17.5 -11.5t-21 -14t-14.5 -14.5q-45 -60 -60 -159.5t-15 -308.5q0 -208 15 -307.5t60 -160.5q6 -8 15 -15t20.5 -14t17.5 -12q44 -33 239.5 -49t470.5 -16q610 0 697 65q5 4 17 11t20.5 14
+t13.5 16q46 60 61 159t15 309zM2048 1408v-1536h-2048v1536h2048z" />
+ <glyph glyph-name="_491" unicode=""
+d="M992 912v-496q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v496q0 112 -80 192t-192 80h-272v-1152q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v1344q0 14 9 23t23 9h464q135 0 249 -66.5t180.5 -180.5t66.5 -249zM1376 1376v-880q0 -135 -66.5 -249t-180.5 -180.5
+t-249 -66.5h-464q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h160q14 0 23 -9t9 -23v-768h272q112 0 192 80t80 192v880q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" />
+ <glyph glyph-name="_492" unicode=""
+d="M1311 694v-114q0 -24 -13.5 -38t-37.5 -14h-202q-24 0 -38 14t-14 38v114q0 24 14 38t38 14h202q24 0 37.5 -14t13.5 -38zM821 464v250q0 53 -32.5 85.5t-85.5 32.5h-133q-68 0 -96 -52q-28 52 -96 52h-130q-53 0 -85.5 -32.5t-32.5 -85.5v-250q0 -22 21 -22h55
+q22 0 22 22v230q0 24 13.5 38t38.5 14h94q24 0 38 -14t14 -38v-230q0 -22 21 -22h54q22 0 22 22v230q0 24 14 38t38 14h97q24 0 37.5 -14t13.5 -38v-230q0 -22 22 -22h55q21 0 21 22zM1410 560v154q0 53 -33 85.5t-86 32.5h-264q-53 0 -86 -32.5t-33 -85.5v-410
+q0 -21 22 -21h55q21 0 21 21v180q31 -42 94 -42h191q53 0 86 32.5t33 85.5zM1536 1176v-1072q0 -96 -68 -164t-164 -68h-1072q-96 0 -164 68t-68 164v1072q0 96 68 164t164 68h1072q96 0 164 -68t68 -164z" />
+ <glyph glyph-name="_493" unicode=""
+d="M915 450h-294l147 551zM1001 128h311l-324 1024h-440l-324 -1024h311l383 314zM1536 1120v-960q0 -118 -85 -203t-203 -85h-960q-118 0 -203 85t-85 203v960q0 118 85 203t203 85h960q118 0 203 -85t85 -203z" />
+ <glyph glyph-name="_494" unicode="" horiz-adv-x="2048"
+d="M2048 641q0 -21 -13 -36.5t-33 -19.5l-205 -356q3 -9 3 -18q0 -20 -12.5 -35.5t-32.5 -19.5l-193 -337q3 -8 3 -16q0 -23 -16.5 -40t-40.5 -17q-25 0 -41 18h-400q-17 -20 -43 -20t-43 20h-399q-17 -20 -43 -20q-23 0 -40 16.5t-17 40.5q0 8 4 20l-193 335
+q-20 4 -32.5 19.5t-12.5 35.5q0 9 3 18l-206 356q-20 5 -32.5 20.5t-12.5 35.5q0 21 13.5 36.5t33.5 19.5l199 344q0 1 -0.5 3t-0.5 3q0 36 34 51l209 363q-4 10 -4 18q0 24 17 40.5t40 16.5q26 0 44 -21h396q16 21 43 21t43 -21h398q18 21 44 21q23 0 40 -16.5t17 -40.5
+q0 -6 -4 -18l207 -358q23 -1 39 -17.5t16 -38.5q0 -13 -7 -27l187 -324q19 -4 31.5 -19.5t12.5 -35.5zM1063 -158h389l-342 354h-143l-342 -354h360q18 16 39 16t39 -16zM112 654q1 -4 1 -13q0 -10 -2 -15l208 -360l15 -6l188 199v347l-187 194q-13 -8 -29 -10zM986 1438
+h-388l190 -200l554 200h-280q-16 -16 -38 -16t-38 16zM1689 226q1 6 5 11l-64 68l-17 -79h76zM1583 226l22 105l-252 266l-296 -307l63 -64h463zM1495 -142l16 28l65 310h-427l333 -343q8 4 13 5zM578 -158h5l342 354h-373v-335l4 -6q14 -5 22 -13zM552 226h402l64 66
+l-309 321l-157 -166v-221zM359 226h163v189l-168 -177q4 -8 5 -12zM358 1051q0 -1 0.5 -2t0.5 -2q0 -16 -8 -29l171 -177v269zM552 1121v-311l153 -157l297 314l-223 236zM556 1425l-4 -8v-264l205 74l-191 201q-6 -2 -10 -3zM1447 1438h-16l-621 -224l213 -225zM1023 946
+l-297 -315l311 -319l296 307zM688 634l-136 141v-284zM1038 270l-42 -44h85zM1374 618l238 -251l132 624l-3 5l-1 1zM1718 1018q-8 13 -8 29v2l-216 376q-5 1 -13 5l-437 -463l310 -327zM522 1142v223l-163 -282zM522 196h-163l163 -283v283zM1607 196l-48 -227l130 227h-82
+zM1729 266l207 361q-2 10 -2 14q0 1 3 16l-171 296l-129 -612l77 -82q5 3 15 7z" />
+ <glyph glyph-name="f210" unicode=""
+d="M0 856q0 131 91.5 226.5t222.5 95.5h742l352 358v-1470q0 -132 -91.5 -227t-222.5 -95h-780q-131 0 -222.5 95t-91.5 227v790zM1232 102l-176 180v425q0 46 -32 79t-78 33h-484q-46 0 -78 -33t-32 -79v-492q0 -46 32.5 -79.5t77.5 -33.5h770z" />
+ <glyph glyph-name="_496" unicode=""
+d="M934 1386q-317 -121 -556 -362.5t-358 -560.5q-20 89 -20 176q0 208 102.5 384.5t278.5 279t384 102.5q82 0 169 -19zM1203 1267q93 -65 164 -155q-389 -113 -674.5 -400.5t-396.5 -676.5q-93 72 -155 162q112 386 395 671t667 399zM470 -67q115 356 379.5 622t619.5 384
+q40 -92 54 -195q-292 -120 -516 -345t-343 -518q-103 14 -194 52zM1536 -125q-193 50 -367 115q-135 -84 -290 -107q109 205 274 370.5t369 275.5q-21 -152 -101 -284q65 -175 115 -370z" />
+ <glyph glyph-name="f212" unicode="" horiz-adv-x="2048"
+d="M1893 1144l155 -1272q-131 0 -257 57q-200 91 -393 91q-226 0 -374 -148q-148 148 -374 148q-193 0 -393 -91q-128 -57 -252 -57h-5l155 1272q224 127 482 127q233 0 387 -106q154 106 387 106q258 0 482 -127zM1398 157q129 0 232 -28.5t260 -93.5l-124 1021
+q-171 78 -368 78q-224 0 -374 -141q-150 141 -374 141q-197 0 -368 -78l-124 -1021q105 43 165.5 65t148.5 39.5t178 17.5q202 0 374 -108q172 108 374 108zM1438 191l-55 907q-211 -4 -359 -155q-152 155 -374 155q-176 0 -336 -66l-114 -941q124 51 228.5 76t221.5 25
+q209 0 374 -102q172 107 374 102z" />
+ <glyph glyph-name="_498" unicode="" horiz-adv-x="2048"
+d="M1500 165v733q0 21 -15 36t-35 15h-93q-20 0 -35 -15t-15 -36v-733q0 -20 15 -35t35 -15h93q20 0 35 15t15 35zM1216 165v531q0 20 -15 35t-35 15h-101q-20 0 -35 -15t-15 -35v-531q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM924 165v429q0 20 -15 35t-35 15h-101
+q-20 0 -35 -15t-15 -35v-429q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM632 165v362q0 20 -15 35t-35 15h-101q-20 0 -35 -15t-15 -35v-362q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM2048 311q0 -166 -118 -284t-284 -118h-1244q-166 0 -284 118t-118 284
+q0 116 63 214.5t168 148.5q-10 34 -10 73q0 113 80.5 193.5t193.5 80.5q102 0 180 -67q45 183 194 300t338 117q149 0 275 -73.5t199.5 -199.5t73.5 -275q0 -66 -14 -122q135 -33 221 -142.5t86 -247.5z" />
+ <glyph glyph-name="_499" unicode=""
+d="M0 1536h1536v-1392l-776 -338l-760 338v1392zM1436 209v926h-1336v-926l661 -294zM1436 1235v201h-1336v-201h1336zM181 937v-115h-37v115h37zM181 789v-115h-37v115h37zM181 641v-115h-37v115h37zM181 493v-115h-37v115h37zM181 345v-115h-37v115h37zM207 202l15 34
+l105 -47l-15 -33zM343 142l15 34l105 -46l-15 -34zM478 82l15 34l105 -46l-15 -34zM614 23l15 33l104 -46l-15 -34zM797 10l105 46l15 -33l-105 -47zM932 70l105 46l15 -34l-105 -46zM1068 130l105 46l15 -34l-105 -46zM1203 189l105 47l15 -34l-105 -46zM259 1389v-36h-114
+v36h114zM421 1389v-36h-115v36h115zM583 1389v-36h-115v36h115zM744 1389v-36h-114v36h114zM906 1389v-36h-114v36h114zM1068 1389v-36h-115v36h115zM1230 1389v-36h-115v36h115zM1391 1389v-36h-114v36h114zM181 1049v-79h-37v115h115v-36h-78zM421 1085v-36h-115v36h115z
+M583 1085v-36h-115v36h115zM744 1085v-36h-114v36h114zM906 1085v-36h-114v36h114zM1068 1085v-36h-115v36h115zM1230 1085v-36h-115v36h115zM1355 970v79h-78v36h115v-115h-37zM1355 822v115h37v-115h-37zM1355 674v115h37v-115h-37zM1355 526v115h37v-115h-37zM1355 378
+v115h37v-115h-37zM1355 230v115h37v-115h-37zM760 265q-129 0 -221 91.5t-92 221.5q0 129 92 221t221 92q130 0 221.5 -92t91.5 -221q0 -130 -91.5 -221.5t-221.5 -91.5zM595 646q0 -36 19.5 -56.5t49.5 -25t64 -7t64 -2t49.5 -9t19.5 -30.5q0 -49 -112 -49q-97 0 -123 51
+h-3l-31 -63q67 -42 162 -42q29 0 56.5 5t55.5 16t45.5 33t17.5 53q0 46 -27.5 69.5t-67.5 27t-79.5 3t-67 5t-27.5 25.5q0 21 20.5 33t40.5 15t41 3q34 0 70.5 -11t51.5 -34h3l30 58q-3 1 -21 8.5t-22.5 9t-19.5 7t-22 7t-20 4.5t-24 4t-23 1q-29 0 -56.5 -5t-54 -16.5
+t-43 -34t-16.5 -53.5z" />
+ <glyph glyph-name="_500" unicode="" horiz-adv-x="2048"
+d="M863 504q0 112 -79.5 191.5t-191.5 79.5t-191 -79.5t-79 -191.5t79 -191t191 -79t191.5 79t79.5 191zM1726 505q0 112 -79 191t-191 79t-191.5 -79t-79.5 -191q0 -113 79.5 -192t191.5 -79t191 79.5t79 191.5zM2048 1314v-1348q0 -44 -31.5 -75.5t-76.5 -31.5h-1832
+q-45 0 -76.5 31.5t-31.5 75.5v1348q0 44 31.5 75.5t76.5 31.5h431q44 0 76 -31.5t32 -75.5v-161h754v161q0 44 32 75.5t76 31.5h431q45 0 76.5 -31.5t31.5 -75.5z" />
+ <glyph glyph-name="_501" unicode="" horiz-adv-x="2048"
+d="M1430 953zM1690 749q148 0 253 -98.5t105 -244.5q0 -157 -109 -261.5t-267 -104.5q-85 0 -162 27.5t-138 73.5t-118 106t-109 126t-103.5 132.5t-108.5 126.5t-117 106t-136 73.5t-159 27.5q-154 0 -251.5 -91.5t-97.5 -244.5q0 -157 104 -250t263 -93q100 0 208 37.5
+t193 98.5q5 4 21 18.5t30 24t22 9.5q14 0 24.5 -10.5t10.5 -24.5q0 -24 -60 -77q-101 -88 -234.5 -142t-260.5 -54q-133 0 -245.5 58t-180 165t-67.5 241q0 205 141.5 341t347.5 136q120 0 226.5 -43.5t185.5 -113t151.5 -153t139 -167.5t133.5 -153.5t149.5 -113
+t172.5 -43.5q102 0 168.5 61.5t66.5 162.5q0 95 -64.5 159t-159.5 64q-30 0 -81.5 -18.5t-68.5 -18.5q-20 0 -35.5 15t-15.5 35q0 18 8.5 57t8.5 59q0 159 -107.5 263t-266.5 104q-58 0 -111.5 -18.5t-84 -40.5t-55.5 -40.5t-33 -18.5q-15 0 -25.5 10.5t-10.5 25.5
+q0 19 25 46q59 67 147 103.5t182 36.5q191 0 318 -125.5t127 -315.5q0 -37 -4 -66q57 15 115 15z" />
+ <glyph glyph-name="_502" unicode="" horiz-adv-x="1664"
+d="M1216 832q0 26 -19 45t-45 19h-128v128q0 26 -19 45t-45 19t-45 -19t-19 -45v-128h-128q-26 0 -45 -19t-19 -45t19 -45t45 -19h128v-128q0 -26 19 -45t45 -19t45 19t19 45v128h128q26 0 45 19t19 45zM640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5
+t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920
+q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="_503" unicode="" horiz-adv-x="1664"
+d="M1280 832q0 26 -19 45t-45 19t-45 -19l-147 -146v293q0 26 -19 45t-45 19t-45 -19t-19 -45v-293l-147 146q-19 19 -45 19t-45 -19t-19 -45t19 -45l256 -256q19 -19 45 -19t45 19l256 256q19 19 19 45zM640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5
+t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920
+q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="_504" unicode="" horiz-adv-x="2048"
+d="M212 768l623 -665l-300 665h-323zM1024 -4l349 772h-698zM538 896l204 384h-262l-288 -384h346zM1213 103l623 665h-323zM683 896h682l-204 384h-274zM1510 896h346l-288 384h-262zM1651 1382l384 -512q14 -18 13 -41.5t-17 -40.5l-960 -1024q-18 -20 -47 -20t-47 20
+l-960 1024q-16 17 -17 40.5t13 41.5l384 512q18 26 51 26h1152q33 0 51 -26z" />
+ <glyph glyph-name="_505" unicode="" horiz-adv-x="2048"
+d="M1811 -19q19 19 45 19t45 -19l128 -128l-90 -90l-83 83l-83 -83q-18 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83
+q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-128 128l90 90l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83
+q19 19 45 19t45 -19l83 -83zM237 19q-19 -19 -45 -19t-45 19l-128 128l90 90l83 -82l83 82q19 19 45 19t45 -19l83 -82l64 64v293l-210 314q-17 26 -7 56.5t40 40.5l177 58v299h128v128h256v128h256v-128h256v-128h128v-299l177 -58q30 -10 40 -40.5t-7 -56.5l-210 -314
+v-293l19 18q19 19 45 19t45 -19l83 -82l83 82q19 19 45 19t45 -19l128 -128l-90 -90l-83 83l-83 -83q-18 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83
+q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83zM640 1152v-128l384 128l384 -128v128h-128v128h-512v-128h-128z" />
+ <glyph glyph-name="_506" unicode=""
+d="M576 0l96 448l-96 128l-128 64zM832 0l128 640l-128 -64l-96 -128zM992 1010q-2 4 -4 6q-10 8 -96 8q-70 0 -167 -19q-7 -2 -21 -2t-21 2q-97 19 -167 19q-86 0 -96 -8q-2 -2 -4 -6q2 -18 4 -27q2 -3 7.5 -6.5t7.5 -10.5q2 -4 7.5 -20.5t7 -20.5t7.5 -17t8.5 -17t9 -14
+t12 -13.5t14 -9.5t17.5 -8t20.5 -4t24.5 -2q36 0 59 12.5t32.5 30t14.5 34.5t11.5 29.5t17.5 12.5h12q11 0 17.5 -12.5t11.5 -29.5t14.5 -34.5t32.5 -30t59 -12.5q13 0 24.5 2t20.5 4t17.5 8t14 9.5t12 13.5t9 14t8.5 17t7.5 17t7 20.5t7.5 20.5q2 7 7.5 10.5t7.5 6.5
+q2 9 4 27zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 61 4.5 118t19 125.5t37.5 123.5t63.5 103.5t93.5 74.5l-90 220h214q-22 64 -22 128q0 12 2 32q-194 40 -194 96q0 57 210 99q17 62 51.5 134t70.5 114q32 37 76 37q30 0 84 -31t84 -31t84 31
+t84 31q44 0 76 -37q36 -42 70.5 -114t51.5 -134q210 -42 210 -99q0 -56 -194 -96q7 -81 -20 -160h214l-82 -225q63 -33 107.5 -96.5t65.5 -143.5t29 -151.5t8 -148.5z" />
+ <glyph glyph-name="_507" unicode="" horiz-adv-x="2304"
+d="M2301 500q12 -103 -22 -198.5t-99 -163.5t-158.5 -106t-196.5 -31q-161 11 -279.5 125t-134.5 274q-12 111 27.5 210.5t118.5 170.5l-71 107q-96 -80 -151 -194t-55 -244q0 -27 -18.5 -46.5t-45.5 -19.5h-256h-69q-23 -164 -149 -274t-294 -110q-185 0 -316.5 131.5
+t-131.5 316.5t131.5 316.5t316.5 131.5q76 0 152 -27l24 45q-123 110 -304 110h-64q-26 0 -45 19t-19 45t19 45t45 19h128q78 0 145 -13.5t116.5 -38.5t71.5 -39.5t51 -36.5h512h115l-85 128h-222q-30 0 -49 22.5t-14 52.5q4 23 23 38t43 15h253q33 0 53 -28l70 -105
+l114 114q19 19 46 19h101q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-179l115 -172q131 63 275 36q143 -26 244 -134.5t118 -253.5zM448 128q115 0 203 72.5t111 183.5h-314q-35 0 -55 31q-18 32 -1 63l147 277q-47 13 -91 13q-132 0 -226 -94t-94 -226t94 -226
+t226 -94zM1856 128q132 0 226 94t94 226t-94 226t-226 94q-60 0 -121 -24l174 -260q15 -23 10 -49t-27 -40q-15 -11 -36 -11q-35 0 -53 29l-174 260q-93 -95 -93 -225q0 -132 94 -226t226 -94z" />
+ <glyph glyph-name="_508" unicode=""
+d="M1408 0q0 -63 -61.5 -113.5t-164 -81t-225 -46t-253.5 -15.5t-253.5 15.5t-225 46t-164 81t-61.5 113.5q0 49 33 88.5t91 66.5t118 44.5t131 29.5q26 5 48 -10.5t26 -41.5q5 -26 -10.5 -48t-41.5 -26q-58 -10 -106 -23.5t-76.5 -25.5t-48.5 -23.5t-27.5 -19.5t-8.5 -12
+q3 -11 27 -26.5t73 -33t114 -32.5t160.5 -25t201.5 -10t201.5 10t160.5 25t114 33t73 33.5t27 27.5q-1 4 -8.5 11t-27.5 19t-48.5 23.5t-76.5 25t-106 23.5q-26 4 -41.5 26t-10.5 48q4 26 26 41.5t48 10.5q71 -12 131 -29.5t118 -44.5t91 -66.5t33 -88.5zM1024 896v-384
+q0 -26 -19 -45t-45 -19h-64v-384q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v384h-64q-26 0 -45 19t-19 45v384q0 53 37.5 90.5t90.5 37.5h384q53 0 90.5 -37.5t37.5 -90.5zM928 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5
+t158.5 -65.5t65.5 -158.5z" />
+ <glyph glyph-name="_509" unicode="" horiz-adv-x="1792"
+d="M1280 512h305q-5 -6 -10 -10.5t-9 -7.5l-3 -4l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-5 2 -21 20h369q22 0 39.5 13.5t22.5 34.5l70 281l190 -667q6 -20 23 -33t39 -13q21 0 38 13t23 33l146 485l56 -112q18 -35 57 -35zM1792 940q0 -145 -103 -300h-369l-111 221
+q-8 17 -25.5 27t-36.5 8q-45 -5 -56 -46l-129 -430l-196 686q-6 20 -23.5 33t-39.5 13t-39 -13.5t-22 -34.5l-116 -464h-423q-103 155 -103 300q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124
+t127 -344z" />
+ <glyph glyph-name="venus" unicode="" horiz-adv-x="1280"
+d="M1152 960q0 -221 -147.5 -384.5t-364.5 -187.5v-260h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v260q-150 16 -271.5 103t-186 224t-52.5 292
+q11 134 80.5 249t182 188t245.5 88q170 19 319 -54t236 -212t87 -306zM128 960q0 -185 131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5z" />
+ <glyph glyph-name="_511" unicode=""
+d="M1472 1408q26 0 45 -19t19 -45v-416q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v262l-382 -383q126 -156 126 -359q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123t223.5 45.5
+q203 0 359 -126l382 382h-261q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h416zM576 0q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+ <glyph glyph-name="_512" unicode="" horiz-adv-x="1280"
+d="M830 1220q145 -72 233.5 -210.5t88.5 -305.5q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-217 24 -364.5 187.5
+t-147.5 384.5q0 167 88.5 305.5t233.5 210.5q-165 96 -228 273q-6 16 3.5 29.5t26.5 13.5h69q21 0 29 -20q44 -106 140 -171t214 -65t214 65t140 171q8 20 37 20h61q17 0 26.5 -13.5t3.5 -29.5q-63 -177 -228 -273zM576 256q185 0 316.5 131.5t131.5 316.5t-131.5 316.5
+t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+ <glyph glyph-name="_513" unicode=""
+d="M1024 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q126 -158 126 -359q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64
+q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-149 16 -270.5 103t-186.5 223.5t-53 291.5q16 204 160 353.5t347 172.5q118 14 228 -19t198 -103l255 254h-134q-14 0 -23 9t-9 23v64zM576 256q185 0 316.5 131.5t131.5 316.5t-131.5 316.5
+t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+ <glyph glyph-name="_514" unicode="" horiz-adv-x="1792"
+d="M1280 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q126 -158 126 -359q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64
+q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-217 24 -364.5 187.5t-147.5 384.5q0 201 126 359l-52 53l-101 -111q-9 -10 -22 -10.5t-23 7.5l-48 44q-10 8 -10.5 21.5t8.5 23.5l105 115l-111 112v-134q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9
+t-9 23v288q0 26 19 45t45 19h288q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-133l106 -107l86 94q9 10 22 10.5t23 -7.5l48 -44q10 -8 10.5 -21.5t-8.5 -23.5l-90 -99l57 -56q158 126 359 126t359 -126l255 254h-134q-14 0 -23 9t-9 23v64zM832 256q185 0 316.5 131.5
+t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+ <glyph glyph-name="_515" unicode="" horiz-adv-x="1792"
+d="M1790 1007q12 -155 -52.5 -292t-186 -224t-271.5 -103v-260h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-512v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23
+t23 9h224v260q-150 16 -271.5 103t-186 224t-52.5 292q17 206 164.5 356.5t352.5 169.5q206 21 377 -94q171 115 377 94q205 -19 352.5 -169.5t164.5 -356.5zM896 647q128 131 128 313t-128 313q-128 -131 -128 -313t128 -313zM576 512q115 0 218 57q-154 165 -154 391
+q0 224 154 391q-103 57 -218 57q-185 0 -316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5zM1152 128v260q-137 15 -256 94q-119 -79 -256 -94v-260h512zM1216 512q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5q-115 0 -218 -57q154 -167 154 -391
+q0 -226 -154 -391q103 -57 218 -57z" />
+ <glyph glyph-name="_516" unicode="" horiz-adv-x="1920"
+d="M1536 1120q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q76 -95 107.5 -214t9.5 -247q-31 -182 -166 -312t-318 -156q-210 -29 -384.5 80t-241.5 300q-117 6 -221 57.5t-177.5 133t-113.5 192.5t-32 230
+q9 135 78 252t182 191.5t248 89.5q118 14 227.5 -19t198.5 -103l255 254h-134q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q59 -74 93 -169q182 -9 328 -124l255 254h-134q-14 0 -23 9
+t-9 23v64zM1024 704q0 20 -4 58q-162 -25 -271 -150t-109 -292q0 -20 4 -58q162 25 271 150t109 292zM128 704q0 -168 111 -294t276 -149q-3 29 -3 59q0 210 135 369.5t338 196.5q-53 120 -163.5 193t-245.5 73q-185 0 -316.5 -131.5t-131.5 -316.5zM1088 -128
+q185 0 316.5 131.5t131.5 316.5q0 168 -111 294t-276 149q3 -28 3 -59q0 -210 -135 -369.5t-338 -196.5q53 -120 163.5 -193t245.5 -73z" />
+ <glyph glyph-name="_517" unicode="" horiz-adv-x="2048"
+d="M1664 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q76 -95 107.5 -214t9.5 -247q-32 -180 -164.5 -310t-313.5 -157q-223 -34 -409 90q-117 -78 -256 -93v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23
+t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-155 17 -279.5 109.5t-187 237.5t-39.5 307q25 187 159.5 322.5t320.5 164.5q224 34 410 -90q146 97 320 97q201 0 359 -126l255 254h-134q-14 0 -23 9
+t-9 23v64zM896 391q128 131 128 313t-128 313q-128 -131 -128 -313t128 -313zM128 704q0 -185 131.5 -316.5t316.5 -131.5q117 0 218 57q-154 167 -154 391t154 391q-101 57 -218 57q-185 0 -316.5 -131.5t-131.5 -316.5zM1216 256q185 0 316.5 131.5t131.5 316.5
+t-131.5 316.5t-316.5 131.5q-117 0 -218 -57q154 -167 154 -391t-154 -391q101 -57 218 -57z" />
+ <glyph glyph-name="_518" unicode=""
+d="M1472 1408q26 0 45 -19t19 -45v-416q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v262l-213 -214l140 -140q9 -10 9 -23t-9 -22l-46 -46q-9 -9 -22 -9t-23 9l-140 141l-78 -79q126 -156 126 -359q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5
+t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123t223.5 45.5q203 0 359 -126l78 78l-172 172q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l172 -172l213 213h-261q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h416zM576 0q185 0 316.5 131.5t131.5 316.5t-131.5 316.5
+t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+ <glyph glyph-name="_519" unicode="" horiz-adv-x="1280"
+d="M640 892q217 -24 364.5 -187.5t147.5 -384.5q0 -167 -87 -306t-236 -212t-319 -54q-133 15 -245.5 88t-182 188t-80.5 249q-12 155 52.5 292t186 224t271.5 103v132h-160q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h160v165l-92 -92q-10 -9 -23 -9t-22 9l-46 46q-9 9 -9 22
+t9 23l202 201q19 19 45 19t45 -19l202 -201q9 -10 9 -23t-9 -22l-46 -46q-9 -9 -22 -9t-23 9l-92 92v-165h160q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-160v-132zM576 -128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5
+t131.5 -316.5t316.5 -131.5z" />
+ <glyph glyph-name="_520" unicode="" horiz-adv-x="2048"
+d="M1901 621q19 -19 19 -45t-19 -45l-294 -294q-9 -10 -22.5 -10t-22.5 10l-45 45q-10 9 -10 22.5t10 22.5l185 185h-294v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-132q-24 -217 -187.5 -364.5t-384.5 -147.5q-167 0 -306 87t-212 236t-54 319q15 133 88 245.5
+t188 182t249 80.5q155 12 292 -52.5t224 -186t103 -271.5h132v224q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-224h294l-185 185q-10 9 -10 22.5t10 22.5l45 45q9 10 22.5 10t22.5 -10zM576 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5
+t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+ <glyph glyph-name="_521" unicode="" horiz-adv-x="1280"
+d="M1152 960q0 -221 -147.5 -384.5t-364.5 -187.5v-612q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v612q-217 24 -364.5 187.5t-147.5 384.5q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5zM576 512q185 0 316.5 131.5
+t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+ <glyph glyph-name="_522" unicode="" horiz-adv-x="1280"
+d="M1024 576q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1152 576q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123
+t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5z" />
+ <glyph glyph-name="_523" unicode="" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="_524" unicode="" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="_525" unicode=""
+d="M1451 1408q35 0 60 -25t25 -60v-1366q0 -35 -25 -60t-60 -25h-391v595h199l30 232h-229v148q0 56 23.5 84t91.5 28l122 1v207q-63 9 -178 9q-136 0 -217.5 -80t-81.5 -226v-171h-200v-232h200v-595h-735q-35 0 -60 25t-25 60v1366q0 35 25 60t60 25h1366z" />
+ <glyph glyph-name="_526" unicode="" horiz-adv-x="1280"
+d="M0 939q0 108 37.5 203.5t103.5 166.5t152 123t185 78t202 26q158 0 294 -66.5t221 -193.5t85 -287q0 -96 -19 -188t-60 -177t-100 -149.5t-145 -103t-189 -38.5q-68 0 -135 32t-96 88q-10 -39 -28 -112.5t-23.5 -95t-20.5 -71t-26 -71t-32 -62.5t-46 -77.5t-62 -86.5
+l-14 -5l-9 10q-15 157 -15 188q0 92 21.5 206.5t66.5 287.5t52 203q-32 65 -32 169q0 83 52 156t132 73q61 0 95 -40.5t34 -102.5q0 -66 -44 -191t-44 -187q0 -63 45 -104.5t109 -41.5q55 0 102 25t78.5 68t56 95t38 110.5t20 111t6.5 99.5q0 173 -109.5 269.5t-285.5 96.5
+q-200 0 -334 -129.5t-134 -328.5q0 -44 12.5 -85t27 -65t27 -45.5t12.5 -30.5q0 -28 -15 -73t-37 -45q-2 0 -17 3q-51 15 -90.5 56t-61 94.5t-32.5 108t-11 106.5z" />
+ <glyph glyph-name="_527" unicode=""
+d="M985 562q13 0 97.5 -44t89.5 -53q2 -5 2 -15q0 -33 -17 -76q-16 -39 -71 -65.5t-102 -26.5q-57 0 -190 62q-98 45 -170 118t-148 185q-72 107 -71 194v8q3 91 74 158q24 22 52 22q6 0 18 -1.5t19 -1.5q19 0 26.5 -6.5t15.5 -27.5q8 -20 33 -88t25 -75q0 -21 -34.5 -57.5
+t-34.5 -46.5q0 -7 5 -15q34 -73 102 -137q56 -53 151 -101q12 -7 22 -7q15 0 54 48.5t52 48.5zM782 32q127 0 243.5 50t200.5 134t134 200.5t50 243.5t-50 243.5t-134 200.5t-200.5 134t-243.5 50t-243.5 -50t-200.5 -134t-134 -200.5t-50 -243.5q0 -203 120 -368l-79 -233
+l242 77q158 -104 345 -104zM782 1414q153 0 292.5 -60t240.5 -161t161 -240.5t60 -292.5t-60 -292.5t-161 -240.5t-240.5 -161t-292.5 -60q-195 0 -365 94l-417 -134l136 405q-108 178 -108 389q0 153 60 292.5t161 240.5t240.5 161t292.5 60z" />
+ <glyph glyph-name="_528" unicode="" horiz-adv-x="1792"
+d="M128 128h1024v128h-1024v-128zM128 640h1024v128h-1024v-128zM1696 192q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM128 1152h1024v128h-1024v-128zM1696 704q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1696 1216
+q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1792 384v-384h-1792v384h1792zM1792 896v-384h-1792v384h1792zM1792 1408v-384h-1792v384h1792z" />
+ <glyph glyph-name="_529" unicode="" horiz-adv-x="2048"
+d="M704 640q-159 0 -271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5zM1664 512h352q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-352q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5
+t-9.5 22.5v352h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v352q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-352zM928 288q0 -52 38 -90t90 -38h256v-238q-68 -50 -171 -50h-874q-121 0 -194 69t-73 190q0 53 3.5 103.5t14 109t26.5 108.5
+t43 97.5t62 81t85.5 53.5t111.5 20q19 0 39 -17q79 -61 154.5 -91.5t164.5 -30.5t164.5 30.5t154.5 91.5q20 17 39 17q132 0 217 -96h-223q-52 0 -90 -38t-38 -90v-192z" />
+ <glyph glyph-name="_530" unicode="" horiz-adv-x="2048"
+d="M704 640q-159 0 -271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5zM1781 320l249 -249q9 -9 9 -23q0 -13 -9 -22l-136 -136q-9 -9 -22 -9q-14 0 -23 9l-249 249l-249 -249q-9 -9 -23 -9q-13 0 -22 9l-136 136
+q-9 9 -9 22q0 14 9 23l249 249l-249 249q-9 9 -9 23q0 13 9 22l136 136q9 9 22 9q14 0 23 -9l249 -249l249 249q9 9 23 9q13 0 22 -9l136 -136q9 -9 9 -22q0 -14 -9 -23zM1283 320l-181 -181q-37 -37 -37 -91q0 -53 37 -90l83 -83q-21 -3 -44 -3h-874q-121 0 -194 69
+t-73 190q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q19 0 39 -17q154 -122 319 -122t319 122q20 17 39 17q28 0 57 -6q-28 -27 -41 -50t-13 -56q0 -54 37 -91z" />
+ <glyph glyph-name="_531" unicode="" horiz-adv-x="2048"
+d="M256 512h1728q26 0 45 -19t19 -45v-448h-256v256h-1536v-256h-256v1216q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-704zM832 832q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM2048 576v64q0 159 -112.5 271.5t-271.5 112.5h-704
+q-26 0 -45 -19t-19 -45v-384h1152z" />
+ <glyph glyph-name="_532" unicode=""
+d="M1536 1536l-192 -448h192v-192h-274l-55 -128h329v-192h-411l-357 -832l-357 832h-411v192h329l-55 128h-274v192h192l-192 448h256l323 -768h378l323 768h256zM768 320l108 256h-216z" />
+ <glyph glyph-name="_533" unicode=""
+d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM768 192q80 0 136 56t56 136t-56 136t-136 56
+t-136 -56t-56 -136t56 -136t136 -56zM1344 768v512h-1152v-512h1152z" />
+ <glyph glyph-name="_534" unicode=""
+d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM288 224q66 0 113 47t47 113t-47 113t-113 47
+t-113 -47t-47 -113t47 -113t113 -47zM704 768v512h-544v-512h544zM1248 224q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM1408 768v512h-576v-512h576z" />
+ <glyph glyph-name="_535" unicode="" horiz-adv-x="1792"
+d="M597 1115v-1173q0 -25 -12.5 -42.5t-36.5 -17.5q-17 0 -33 8l-465 233q-21 10 -35.5 33.5t-14.5 46.5v1140q0 20 10 34t29 14q14 0 44 -15l511 -256q3 -3 3 -5zM661 1014l534 -866l-534 266v600zM1792 996v-1054q0 -25 -14 -40.5t-38 -15.5t-47 13l-441 220zM1789 1116
+q0 -3 -256.5 -419.5t-300.5 -487.5l-390 634l324 527q17 28 52 28q14 0 26 -6l541 -270q4 -2 4 -6z" />
+ <glyph glyph-name="_536" unicode=""
+d="M809 532l266 499h-112l-157 -312q-24 -48 -44 -92l-42 92l-155 312h-120l263 -493v-324h101v318zM1536 1408v-1536h-1536v1536h1536z" />
+ <glyph glyph-name="_537" unicode="" horiz-adv-x="2296"
+d="M478 -139q-8 -16 -27 -34.5t-37 -25.5q-25 -9 -51.5 3.5t-28.5 31.5q-1 22 40 55t68 38q23 4 34 -21.5t2 -46.5zM1819 -139q7 -16 26 -34.5t38 -25.5q25 -9 51.5 3.5t27.5 31.5q2 22 -39.5 55t-68.5 38q-22 4 -33 -21.5t-2 -46.5zM1867 -30q13 -27 56.5 -59.5t77.5 -41.5
+q45 -13 82 4.5t37 50.5q0 46 -67.5 100.5t-115.5 59.5q-40 5 -63.5 -37.5t-6.5 -76.5zM428 -30q-13 -27 -56 -59.5t-77 -41.5q-45 -13 -82 4.5t-37 50.5q0 46 67.5 100.5t115.5 59.5q40 5 63 -37.5t6 -76.5zM1158 1094h1q-41 0 -76 -15q27 -8 44 -30.5t17 -49.5
+q0 -35 -27 -60t-65 -25q-52 0 -80 43q-5 -23 -5 -42q0 -74 56 -126.5t135 -52.5q80 0 136 52.5t56 126.5t-56 126.5t-136 52.5zM1462 1312q-99 109 -220.5 131.5t-245.5 -44.5q27 60 82.5 96.5t118 39.5t121.5 -17t99.5 -74.5t44.5 -131.5zM2212 73q8 -11 -11 -42
+q7 -23 7 -40q1 -56 -44.5 -112.5t-109.5 -91.5t-118 -37q-48 -2 -92 21.5t-66 65.5q-687 -25 -1259 0q-23 -41 -66.5 -65t-92.5 -22q-86 3 -179.5 80.5t-92.5 160.5q2 22 7 40q-19 31 -11 42q6 10 31 1q14 22 41 51q-7 29 2 38q11 10 39 -4q29 20 59 34q0 29 13 37
+q23 12 51 -16q35 5 61 -2q18 -4 38 -19v73q-11 0 -18 2q-53 10 -97 44.5t-55 87.5q-9 38 0 81q15 62 93 95q2 17 19 35.5t36 23.5t33 -7.5t19 -30.5h13q46 -5 60 -23q3 -3 5 -7q10 1 30.5 3.5t30.5 3.5q-15 11 -30 17q-23 40 -91 43q0 6 1 10q-62 2 -118.5 18.5t-84.5 47.5
+q-32 36 -42.5 92t-2.5 112q16 126 90 179q23 16 52 4.5t32 -40.5q0 -1 1.5 -14t2.5 -21t3 -20t5.5 -19t8.5 -10q27 -14 76 -12q48 46 98 74q-40 4 -162 -14l47 46q61 58 163 111q145 73 282 86q-20 8 -41 15.5t-47 14t-42.5 10.5t-47.5 11t-43 10q595 126 904 -139
+q98 -84 158 -222q85 -10 121 9h1q5 3 8.5 10t5.5 19t3 19.5t3 21.5l1 14q3 28 32 40t52 -5q73 -52 91 -178q7 -57 -3.5 -113t-42.5 -91q-28 -32 -83.5 -48.5t-115.5 -18.5v-10q-71 -2 -95 -43q-14 -5 -31 -17q11 -1 32 -3.5t30 -3.5q1 5 5 8q16 18 60 23h13q5 18 19 30t33 8
+t36 -23t19 -36q79 -32 93 -95q9 -40 1 -81q-12 -53 -56 -88t-97 -44q-10 -2 -17 -2q0 -49 -1 -73q20 15 38 19q26 7 61 2q28 28 51 16q14 -9 14 -37q33 -16 59 -34q27 13 38 4q10 -10 2 -38q28 -30 41 -51q23 8 31 -1zM1937 1025q0 -29 -9 -54q82 -32 112 -132
+q4 37 -9.5 98.5t-41.5 90.5q-20 19 -36 17t-16 -20zM1859 925q35 -42 47.5 -108.5t-0.5 -124.5q67 13 97 45q13 14 18 28q-3 64 -31 114.5t-79 66.5q-15 -15 -52 -21zM1822 921q-30 0 -44 1q42 -115 53 -239q21 0 43 3q16 68 1 135t-53 100zM258 839q30 100 112 132
+q-9 25 -9 54q0 18 -16.5 20t-35.5 -17q-28 -29 -41.5 -90.5t-9.5 -98.5zM294 737q29 -31 97 -45q-13 58 -0.5 124.5t47.5 108.5v0q-37 6 -52 21q-51 -16 -78.5 -66t-31.5 -115q9 -17 18 -28zM471 683q14 124 73 235q-19 -4 -55 -18l-45 -19v1q-46 -89 -20 -196q25 -3 47 -3z
+M1434 644q8 -38 16.5 -108.5t11.5 -89.5q3 -18 9.5 -21.5t23.5 4.5q40 20 62 85.5t23 125.5q-24 2 -146 4zM1152 1285q-116 0 -199 -82.5t-83 -198.5q0 -117 83 -199.5t199 -82.5t199 82.5t83 199.5q0 116 -83 198.5t-199 82.5zM1380 646q-105 2 -211 0v1q-1 -27 2.5 -86
+t13.5 -66q29 -14 93.5 -14.5t95.5 10.5q9 3 11 39t-0.5 69.5t-4.5 46.5zM1112 447q8 4 9.5 48t-0.5 88t-4 63v1q-212 -3 -214 -3q-4 -20 -7 -62t0 -83t14 -46q34 -15 101 -16t101 10zM718 636q-16 -59 4.5 -118.5t77.5 -84.5q15 -8 24 -5t12 21q3 16 8 90t10 103
+q-69 -2 -136 -6zM591 510q3 -23 -34 -36q132 -141 271.5 -240t305.5 -154q172 49 310.5 146t293.5 250q-33 13 -30 34q0 2 0.5 3.5t1.5 3t1 2.5v1v-1q-17 2 -50 5.5t-48 4.5q-26 -90 -82 -132q-51 -38 -82 1q-5 6 -9 14q-7 13 -17 62q-2 -5 -5 -9t-7.5 -7t-8 -5.5t-9.5 -4
+l-10 -2.5t-12 -2l-12 -1.5t-13.5 -1t-13.5 -0.5q-106 -9 -163 11q-4 -17 -10 -26.5t-21 -15t-23 -7t-36 -3.5q-6 -1 -9 -1q-179 -17 -203 40q-2 -63 -56 -54q-47 8 -91 54q-12 13 -20 26q-17 29 -26 65q-58 -6 -87 -10q1 -2 4 -10zM507 -118q3 14 3 30q-17 71 -51 130
+t-73 70q-41 12 -101.5 -14.5t-104.5 -80t-39 -107.5q35 -53 100 -93t119 -42q51 -2 94 28t53 79zM510 53q23 -63 27 -119q195 113 392 174q-98 52 -180.5 120t-179.5 165q-6 -4 -29 -13q0 -1 -1 -4t-1 -5q31 -18 22 -37q-12 -23 -56 -34q-10 -13 -29 -24h-1q-2 -83 1 -150
+q19 -34 35 -73zM579 -113q532 -21 1145 0q-254 147 -428 196q-76 -35 -156 -57q-8 -3 -16 0q-65 21 -129 49q-208 -60 -416 -188h-1v-1q1 0 1 1zM1763 -67q4 54 28 120q14 38 33 71l-1 -1q3 77 3 153q-15 8 -30 25q-42 9 -56 33q-9 20 22 38q-2 4 -2 9q-16 4 -28 12
+q-204 -190 -383 -284q198 -59 414 -176zM2155 -90q5 54 -39 107.5t-104 80t-102 14.5q-38 -11 -72.5 -70.5t-51.5 -129.5q0 -16 3 -30q10 -49 53 -79t94 -28q54 2 119 42t100 93z" />
+ <glyph glyph-name="_538" unicode="" horiz-adv-x="2304"
+d="M1524 -25q0 -68 -48 -116t-116 -48t-116.5 48t-48.5 116t48.5 116.5t116.5 48.5t116 -48.5t48 -116.5zM775 -25q0 -68 -48.5 -116t-116.5 -48t-116 48t-48 116t48 116.5t116 48.5t116.5 -48.5t48.5 -116.5zM0 1469q57 -60 110.5 -104.5t121 -82t136 -63t166 -45.5
+t200 -31.5t250 -18.5t304 -9.5t372.5 -2.5q139 0 244.5 -5t181 -16.5t124 -27.5t71 -39.5t24 -51.5t-19.5 -64t-56.5 -76.5t-89.5 -91t-116 -104.5t-139 -119q-185 -157 -286 -247q29 51 76.5 109t94 105.5t94.5 98.5t83 91.5t54 80.5t13 70t-45.5 55.5t-116.5 41t-204 23.5
+t-304 5q-168 -2 -314 6t-256 23t-204.5 41t-159.5 51.5t-122.5 62.5t-91.5 66.5t-68 71.5t-50.5 69.5t-40 68t-36.5 59.5z" />
+ <glyph glyph-name="_539" unicode="" horiz-adv-x="1792"
+d="M896 1472q-169 0 -323 -66t-265.5 -177.5t-177.5 -265.5t-66 -323t66 -323t177.5 -265.5t265.5 -177.5t323 -66t323 66t265.5 177.5t177.5 265.5t66 323t-66 323t-177.5 265.5t-265.5 177.5t-323 66zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348
+t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM496 704q16 0 16 -16v-480q0 -16 -16 -16h-32q-16 0 -16 16v480q0 16 16 16h32zM896 640q53 0 90.5 -37.5t37.5 -90.5q0 -35 -17.5 -64t-46.5 -46v-114q0 -14 -9 -23
+t-23 -9h-64q-14 0 -23 9t-9 23v114q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5zM896 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM544 928v-96
+q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v96q0 93 65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5v-96q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v96q0 146 -103 249t-249 103t-249 -103t-103 -249zM1408 192v512q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-512
+q0 -26 19 -45t45 -19h896q26 0 45 19t19 45z" />
+ <glyph glyph-name="_540" unicode="" horiz-adv-x="2304"
+d="M1920 1024v-768h-1664v768h1664zM2048 448h128v384h-128v288q0 14 -9 23t-23 9h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288zM2304 832v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113
+v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160q53 0 90.5 -37.5t37.5 -90.5z" />
+ <glyph glyph-name="_541" unicode="" horiz-adv-x="2304"
+d="M256 256v768h1280v-768h-1280zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9
+h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+ <glyph glyph-name="_542" unicode="" horiz-adv-x="2304"
+d="M256 256v768h896v-768h-896zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9
+h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+ <glyph glyph-name="_543" unicode="" horiz-adv-x="2304"
+d="M256 256v768h512v-768h-512zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9
+h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+ <glyph glyph-name="_544" unicode="" horiz-adv-x="2304"
+d="M2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9h-1856q-14 0 -23 -9t-9 -23
+v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+ <glyph glyph-name="_545" unicode="" horiz-adv-x="1280"
+d="M1133 493q31 -30 14 -69q-17 -40 -59 -40h-382l201 -476q10 -25 0 -49t-34 -35l-177 -75q-25 -10 -49 0t-35 34l-191 452l-312 -312q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v1504q0 42 40 59q12 5 24 5q27 0 45 -19z" />
+ <glyph glyph-name="_546" unicode="" horiz-adv-x="1024"
+d="M832 1408q-320 0 -320 -224v-416h128v-128h-128v-544q0 -224 320 -224h64v-128h-64q-272 0 -384 146q-112 -146 -384 -146h-64v128h64q320 0 320 224v544h-128v128h128v416q0 224 -320 224h-64v128h64q272 0 384 -146q112 146 384 146h64v-128h-64z" />
+ <glyph glyph-name="_547" unicode="" horiz-adv-x="2048"
+d="M2048 1152h-128v-1024h128v-384h-384v128h-1280v-128h-384v384h128v1024h-128v384h384v-128h1280v128h384v-384zM1792 1408v-128h128v128h-128zM128 1408v-128h128v128h-128zM256 -128v128h-128v-128h128zM1664 0v128h128v1024h-128v128h-1280v-128h-128v-1024h128v-128
+h1280zM1920 -128v128h-128v-128h128zM1280 896h384v-768h-896v256h-384v768h896v-256zM512 512h640v512h-640v-512zM1536 256v512h-256v-384h-384v-128h640z" />
+ <glyph glyph-name="_548" unicode="" horiz-adv-x="2304"
+d="M2304 768h-128v-640h128v-384h-384v128h-896v-128h-384v384h128v128h-384v-128h-384v384h128v640h-128v384h384v-128h896v128h384v-384h-128v-128h384v128h384v-384zM2048 1024v-128h128v128h-128zM1408 1408v-128h128v128h-128zM128 1408v-128h128v128h-128zM256 256
+v128h-128v-128h128zM1536 384h-128v-128h128v128zM384 384h896v128h128v640h-128v128h-896v-128h-128v-640h128v-128zM896 -128v128h-128v-128h128zM2176 -128v128h-128v-128h128zM2048 128v640h-128v128h-384v-384h128v-384h-384v128h-384v-128h128v-128h896v128h128z" />
+ <glyph glyph-name="_549" unicode=""
+d="M1024 288v-416h-928q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1344q40 0 68 -28t28 -68v-928h-416q-40 0 -68 -28t-28 -68zM1152 256h381q-15 -82 -65 -132l-184 -184q-50 -50 -132 -65v381z" />
+ <glyph glyph-name="_550" unicode=""
+d="M1400 256h-248v-248q29 10 41 22l185 185q12 12 22 41zM1120 384h288v896h-1280v-1280h896v288q0 40 28 68t68 28zM1536 1312v-1024q0 -40 -20 -88t-48 -76l-184 -184q-28 -28 -76 -48t-88 -20h-1024q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1344q40 0 68 -28t28 -68
+z" />
+ <glyph glyph-name="_551" unicode="" horiz-adv-x="2304"
+d="M1951 538q0 -26 -15.5 -44.5t-38.5 -23.5q-8 -2 -18 -2h-153v140h153q10 0 18 -2q23 -5 38.5 -23.5t15.5 -44.5zM1933 751q0 -25 -15 -42t-38 -21q-3 -1 -15 -1h-139v129h139q3 0 8.5 -0.5t6.5 -0.5q23 -4 38 -21.5t15 -42.5zM728 587v308h-228v-308q0 -58 -38 -94.5
+t-105 -36.5q-108 0 -229 59v-112q53 -15 121 -23t109 -9l42 -1q328 0 328 217zM1442 403v113q-99 -52 -200 -59q-108 -8 -169 41t-61 142t61 142t169 41q101 -7 200 -58v112q-48 12 -100 19.5t-80 9.5l-28 2q-127 6 -218.5 -14t-140.5 -60t-71 -88t-22 -106t22 -106t71 -88
+t140.5 -60t218.5 -14q101 4 208 31zM2176 518q0 54 -43 88.5t-109 39.5v3q57 8 89 41.5t32 79.5q0 55 -41 88t-107 36q-3 0 -12 0.5t-14 0.5h-455v-510h491q74 0 121.5 36.5t47.5 96.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90
+t90 38h2048q52 0 90 -38t38 -90z" />
+ <glyph glyph-name="_552" unicode="" horiz-adv-x="2304"
+d="M858 295v693q-106 -41 -172 -135.5t-66 -211.5t66 -211.5t172 -134.5zM1362 641q0 117 -66 211.5t-172 135.5v-694q106 41 172 135.5t66 211.5zM1577 641q0 -159 -78.5 -294t-213.5 -213.5t-294 -78.5q-119 0 -227.5 46.5t-187 125t-125 187t-46.5 227.5q0 159 78.5 294
+t213.5 213.5t294 78.5t294 -78.5t213.5 -213.5t78.5 -294zM1960 634q0 139 -55.5 261.5t-147.5 205.5t-213.5 131t-252.5 48h-301q-176 0 -323.5 -81t-235 -230t-87.5 -335q0 -171 87 -317.5t236 -231.5t323 -85h301q129 0 251.5 50.5t214.5 135t147.5 202.5t55.5 246z
+M2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+ <glyph glyph-name="_553" unicode="" horiz-adv-x="1792"
+d="M1664 -96v1088q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5v-1088q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5zM1792 992v-1088q0 -66 -47 -113t-113 -47h-1088q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1088q66 0 113 -47t47 -113
+zM1408 1376v-160h-128v160q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5v-1088q0 -13 9.5 -22.5t22.5 -9.5h160v-128h-160q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1088q66 0 113 -47t47 -113z" />
+ <glyph glyph-name="_554" unicode="" horiz-adv-x="2304"
+d="M1728 1088l-384 -704h768zM448 1088l-384 -704h768zM1269 1280q-14 -40 -45.5 -71.5t-71.5 -45.5v-1291h608q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1344q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h608v1291q-40 14 -71.5 45.5t-45.5 71.5h-491q-14 0 -23 9t-9 23v64
+q0 14 9 23t23 9h491q21 57 70 92.5t111 35.5t111 -35.5t70 -92.5h491q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-491zM1088 1264q33 0 56.5 23.5t23.5 56.5t-23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5zM2176 384q0 -73 -46.5 -131t-117.5 -91
+t-144.5 -49.5t-139.5 -16.5t-139.5 16.5t-144.5 49.5t-117.5 91t-46.5 131q0 11 35 81t92 174.5t107 195.5t102 184t56 100q18 33 56 33t56 -33q4 -7 56 -100t102 -184t107 -195.5t92 -174.5t35 -81zM896 384q0 -73 -46.5 -131t-117.5 -91t-144.5 -49.5t-139.5 -16.5
+t-139.5 16.5t-144.5 49.5t-117.5 91t-46.5 131q0 11 35 81t92 174.5t107 195.5t102 184t56 100q18 33 56 33t56 -33q4 -7 56 -100t102 -184t107 -195.5t92 -174.5t35 -81z" />
+ <glyph glyph-name="_555" unicode=""
+d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9
+t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM874 700q77 29 149 92.5t129.5 152.5t92.5 210t35 253h-1024q0 -132 35 -253t92.5 -210t129.5 -152.5t149 -92.5q19 -7 30.5 -23.5t11.5 -36.5t-11.5 -36.5t-30.5 -23.5q-77 -29 -149 -92.5
+t-129.5 -152.5t-92.5 -210t-35 -253h1024q0 132 -35 253t-92.5 210t-129.5 152.5t-149 92.5q-19 7 -30.5 23.5t-11.5 36.5t11.5 36.5t30.5 23.5z" />
+ <glyph glyph-name="_556" unicode=""
+d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9
+t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM1280 1408h-1024q0 -66 9 -128h1006q9 61 9 128zM1280 -128q0 130 -34 249.5t-90.5 208t-126.5 152t-146 94.5h-230q-76 -31 -146 -94.5t-126.5 -152t-90.5 -208t-34 -249.5h1024z" />
+ <glyph glyph-name="_557" unicode=""
+d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9
+t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM1280 1408h-1024q0 -206 85 -384h854q85 178 85 384zM1223 192q-54 141 -145.5 241.5t-194.5 142.5h-230q-103 -42 -194.5 -142.5t-145.5 -241.5h910z" />
+ <glyph glyph-name="_558" unicode=""
+d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9
+t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM874 700q77 29 149 92.5t129.5 152.5t92.5 210t35 253h-1024q0 -132 35 -253t92.5 -210t129.5 -152.5t149 -92.5q19 -7 30.5 -23.5t11.5 -36.5t-11.5 -36.5t-30.5 -23.5q-137 -51 -244 -196
+h700q-107 145 -244 196q-19 7 -30.5 23.5t-11.5 36.5t11.5 36.5t30.5 23.5z" />
+ <glyph glyph-name="_559" unicode=""
+d="M1504 -64q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v128q0 14 9 23t23 9h1472zM130 0q3 55 16 107t30 95t46 87t53.5 76t64.5 69.5t66 60t70.5 55t66.5 47.5t65 43q-43 28 -65 43t-66.5 47.5t-70.5 55t-66 60t-64.5 69.5t-53.5 76t-46 87
+t-30 95t-16 107h1276q-3 -55 -16 -107t-30 -95t-46 -87t-53.5 -76t-64.5 -69.5t-66 -60t-70.5 -55t-66.5 -47.5t-65 -43q43 -28 65 -43t66.5 -47.5t70.5 -55t66 -60t64.5 -69.5t53.5 -76t46 -87t30 -95t16 -107h-1276zM1504 1536q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9
+h-1472q-14 0 -23 9t-9 23v128q0 14 9 23t23 9h1472z" />
+ <glyph glyph-name="_560" unicode=""
+d="M768 1152q-53 0 -90.5 -37.5t-37.5 -90.5v-128h-32v93q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-429l-32 30v172q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-224q0 -47 35 -82l310 -296q39 -39 39 -102q0 -26 19 -45t45 -19h640q26 0 45 19t19 45v25
+q0 41 10 77l108 436q10 36 10 77v246q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-32h-32v125q0 40 -25 72.5t-64 40.5q-14 2 -23 2q-46 0 -79 -33t-33 -79v-128h-32v122q0 51 -32.5 89.5t-82.5 43.5q-5 1 -13 1zM768 1280q84 0 149 -50q57 34 123 34q59 0 111 -27
+t86 -76q27 7 59 7q100 0 170 -71.5t70 -171.5v-246q0 -51 -13 -108l-109 -436q-6 -24 -6 -71q0 -80 -56 -136t-136 -56h-640q-84 0 -138 58.5t-54 142.5l-308 296q-76 73 -76 175v224q0 99 70.5 169.5t169.5 70.5q11 0 16 -1q6 95 75.5 160t164.5 65q52 0 98 -21
+q72 69 174 69z" />
+ <glyph glyph-name="_561" unicode="" horiz-adv-x="1792"
+d="M880 1408q-46 0 -79 -33t-33 -79v-656h-32v528q0 46 -33 79t-79 33t-79 -33t-33 -79v-528v-256l-154 205q-38 51 -102 51q-53 0 -90.5 -37.5t-37.5 -90.5q0 -43 26 -77l384 -512q38 -51 102 -51h688q34 0 61 22t34 56l76 405q5 32 5 59v498q0 46 -33 79t-79 33t-79 -33
+t-33 -79v-272h-32v528q0 46 -33 79t-79 33t-79 -33t-33 -79v-528h-32v656q0 46 -33 79t-79 33zM880 1536q68 0 125.5 -35.5t88.5 -96.5q19 4 42 4q99 0 169.5 -70.5t70.5 -169.5v-17q105 6 180.5 -64t75.5 -175v-498q0 -40 -8 -83l-76 -404q-14 -79 -76.5 -131t-143.5 -52
+h-688q-60 0 -114.5 27.5t-90.5 74.5l-384 512q-51 68 -51 154q0 106 75 181t181 75q78 0 128 -34v434q0 99 70.5 169.5t169.5 70.5q23 0 42 -4q31 61 88.5 96.5t125.5 35.5z" />
+ <glyph glyph-name="_562" unicode="" horiz-adv-x="1792"
+d="M1073 -128h-177q-163 0 -226 141q-23 49 -23 102v5q-62 30 -98.5 88.5t-36.5 127.5q0 38 5 48h-261q-106 0 -181 75t-75 181t75 181t181 75h113l-44 17q-74 28 -119.5 93.5t-45.5 145.5q0 106 75 181t181 75q46 0 91 -17l628 -239h401q106 0 181 -75t75 -181v-668
+q0 -88 -54 -157.5t-140 -90.5l-339 -85q-92 -23 -186 -23zM1024 583l-155 -71l-163 -74q-30 -14 -48 -41.5t-18 -60.5q0 -46 33 -79t79 -33q26 0 46 10l338 154q-49 10 -80.5 50t-31.5 90v55zM1344 272q0 46 -33 79t-79 33q-26 0 -46 -10l-290 -132q-28 -13 -37 -17
+t-30.5 -17t-29.5 -23.5t-16 -29t-8 -40.5q0 -50 31.5 -82t81.5 -32q20 0 38 9l352 160q30 14 48 41.5t18 60.5zM1112 1024l-650 248q-24 8 -46 8q-53 0 -90.5 -37.5t-37.5 -90.5q0 -40 22.5 -73t59.5 -47l526 -200v-64h-640q-53 0 -90.5 -37.5t-37.5 -90.5t37.5 -90.5
+t90.5 -37.5h535l233 106v198q0 63 46 106l111 102h-69zM1073 0q82 0 155 19l339 85q43 11 70 45.5t27 78.5v668q0 53 -37.5 90.5t-90.5 37.5h-308l-136 -126q-36 -33 -36 -82v-296q0 -46 33 -77t79 -31t79 35t33 81v208h32v-208q0 -70 -57 -114q52 -8 86.5 -48.5t34.5 -93.5
+q0 -42 -23 -78t-61 -53l-310 -141h91z" />
+ <glyph glyph-name="_563" unicode="" horiz-adv-x="2048"
+d="M1151 1536q61 0 116 -28t91 -77l572 -781q118 -159 118 -359v-355q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v177l-286 143h-546q-80 0 -136 56t-56 136v32q0 119 84.5 203.5t203.5 84.5h420l42 128h-686q-100 0 -173.5 67.5t-81.5 166.5q-65 79 -65 182v32
+q0 80 56 136t136 56h959zM1920 -64v355q0 157 -93 284l-573 781q-39 52 -103 52h-959q-26 0 -45 -19t-19 -45q0 -32 1.5 -49.5t9.5 -40.5t25 -43q10 31 35.5 50t56.5 19h832v-32h-832q-26 0 -45 -19t-19 -45q0 -44 3 -58q8 -44 44 -73t81 -29h640h91q40 0 68 -28t28 -68
+q0 -15 -5 -30l-64 -192q-10 -29 -35 -47.5t-56 -18.5h-443q-66 0 -113 -47t-47 -113v-32q0 -26 19 -45t45 -19h561q16 0 29 -7l317 -158q24 -13 38.5 -36t14.5 -50v-197q0 -26 19 -45t45 -19h384q26 0 45 19t19 45z" />
+ <glyph glyph-name="_564" unicode="" horiz-adv-x="2048"
+d="M459 -256q-77 0 -137.5 47.5t-79.5 122.5l-101 401q-13 57 -13 108q0 45 -5 67l-116 477q-7 27 -7 57q0 93 62 161t155 78q17 85 82.5 139t152.5 54q83 0 148 -51.5t85 -132.5l83 -348l103 428q20 81 85 132.5t148 51.5q89 0 155.5 -57.5t80.5 -144.5q92 -10 152 -79
+t60 -162q0 -24 -7 -59l-123 -512q10 7 37.5 28.5t38.5 29.5t35 23t41 20.5t41.5 11t49.5 5.5q105 0 180 -74t75 -179q0 -62 -28.5 -118t-78.5 -94l-507 -380q-68 -51 -153 -51h-694zM1104 1408q-38 0 -68.5 -24t-39.5 -62l-164 -682h-127l-145 602q-9 38 -39.5 62t-68.5 24
+q-48 0 -80 -33t-32 -80q0 -15 3 -28l132 -547h-26l-99 408q-9 37 -40 62.5t-69 25.5q-47 0 -80 -33t-33 -79q0 -14 3 -26l116 -478q7 -28 9 -86t10 -88l100 -401q8 -32 34 -52.5t59 -20.5h694q42 0 76 26l507 379q56 43 56 110q0 52 -37.5 88.5t-89.5 36.5q-43 0 -77 -26
+l-307 -230v227q0 4 32 138t68 282t39 161q4 18 4 29q0 47 -32 81t-79 34q-39 0 -69.5 -24t-39.5 -62l-116 -482h-26l150 624q3 14 3 28q0 48 -31.5 82t-79.5 34z" />
+ <glyph glyph-name="_565" unicode="" horiz-adv-x="1792"
+d="M640 1408q-53 0 -90.5 -37.5t-37.5 -90.5v-512v-384l-151 202q-41 54 -107 54q-52 0 -89 -38t-37 -90q0 -43 26 -77l384 -512q38 -51 102 -51h718q22 0 39.5 13.5t22.5 34.5l92 368q24 96 24 194v217q0 41 -28 71t-68 30t-68 -28t-28 -68h-32v61q0 48 -32 81.5t-80 33.5
+q-46 0 -79 -33t-33 -79v-64h-32v90q0 55 -37 94.5t-91 39.5q-53 0 -90.5 -37.5t-37.5 -90.5v-96h-32v570q0 55 -37 94.5t-91 39.5zM640 1536q107 0 181.5 -77.5t74.5 -184.5v-220q22 2 32 2q99 0 173 -69q47 21 99 21q113 0 184 -87q27 7 56 7q94 0 159 -67.5t65 -161.5
+v-217q0 -116 -28 -225l-92 -368q-16 -64 -68 -104.5t-118 -40.5h-718q-60 0 -114.5 27.5t-90.5 74.5l-384 512q-51 68 -51 154q0 105 74.5 180.5t179.5 75.5q71 0 130 -35v547q0 106 75 181t181 75zM768 128v384h-32v-384h32zM1024 128v384h-32v-384h32zM1280 128v384h-32
+v-384h32z" />
+ <glyph glyph-name="_566" unicode=""
+d="M1288 889q60 0 107 -23q141 -63 141 -226v-177q0 -94 -23 -186l-85 -339q-21 -86 -90.5 -140t-157.5 -54h-668q-106 0 -181 75t-75 181v401l-239 628q-17 45 -17 91q0 106 75 181t181 75q80 0 145.5 -45.5t93.5 -119.5l17 -44v113q0 106 75 181t181 75t181 -75t75 -181
+v-261q27 5 48 5q69 0 127.5 -36.5t88.5 -98.5zM1072 896q-33 0 -60.5 -18t-41.5 -48l-74 -163l-71 -155h55q50 0 90 -31.5t50 -80.5l154 338q10 20 10 46q0 46 -33 79t-79 33zM1293 761q-22 0 -40.5 -8t-29 -16t-23.5 -29.5t-17 -30.5t-17 -37l-132 -290q-10 -20 -10 -46
+q0 -46 33 -79t79 -33q33 0 60.5 18t41.5 48l160 352q9 18 9 38q0 50 -32 81.5t-82 31.5zM128 1120q0 -22 8 -46l248 -650v-69l102 111q43 46 106 46h198l106 233v535q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5v-640h-64l-200 526q-14 37 -47 59.5t-73 22.5
+q-53 0 -90.5 -37.5t-37.5 -90.5zM1180 -128q44 0 78.5 27t45.5 70l85 339q19 73 19 155v91l-141 -310q-17 -38 -53 -61t-78 -23q-53 0 -93.5 34.5t-48.5 86.5q-44 -57 -114 -57h-208v32h208q46 0 81 33t35 79t-31 79t-77 33h-296q-49 0 -82 -36l-126 -136v-308
+q0 -53 37.5 -90.5t90.5 -37.5h668z" />
+ <glyph glyph-name="_567" unicode="" horiz-adv-x="1973"
+d="M857 992v-117q0 -13 -9.5 -22t-22.5 -9h-298v-812q0 -13 -9 -22.5t-22 -9.5h-135q-13 0 -22.5 9t-9.5 23v812h-297q-13 0 -22.5 9t-9.5 22v117q0 14 9 23t23 9h793q13 0 22.5 -9.5t9.5 -22.5zM1895 995l77 -961q1 -13 -8 -24q-10 -10 -23 -10h-134q-12 0 -21 8.5
+t-10 20.5l-46 588l-189 -425q-8 -19 -29 -19h-120q-20 0 -29 19l-188 427l-45 -590q-1 -12 -10 -20.5t-21 -8.5h-135q-13 0 -23 10q-9 10 -9 24l78 961q1 12 10 20.5t21 8.5h142q20 0 29 -19l220 -520q10 -24 20 -51q3 7 9.5 24.5t10.5 26.5l221 520q9 19 29 19h141
+q13 0 22 -8.5t10 -20.5z" />
+ <glyph glyph-name="_568" unicode="" horiz-adv-x="1792"
+d="M1042 833q0 88 -60 121q-33 18 -117 18h-123v-281h162q66 0 102 37t36 105zM1094 548l205 -373q8 -17 -1 -31q-8 -16 -27 -16h-152q-20 0 -28 17l-194 365h-155v-350q0 -14 -9 -23t-23 -9h-134q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h294q128 0 190 -24q85 -31 134 -109
+t49 -180q0 -92 -42.5 -165.5t-115.5 -109.5q6 -10 9 -16zM896 1376q-150 0 -286 -58.5t-234.5 -157t-157 -234.5t-58.5 -286t58.5 -286t157 -234.5t234.5 -157t286 -58.5t286 58.5t234.5 157t157 234.5t58.5 286t-58.5 286t-157 234.5t-234.5 157t-286 58.5zM1792 640
+q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+ <glyph glyph-name="_569" unicode="" horiz-adv-x="1792"
+d="M605 303q153 0 257 104q14 18 3 36l-45 82q-6 13 -24 17q-16 2 -27 -11l-4 -3q-4 -4 -11.5 -10t-17.5 -13.5t-23.5 -14.5t-28.5 -13t-33.5 -9.5t-37.5 -3.5q-76 0 -125 50t-49 127q0 76 48 125.5t122 49.5q37 0 71.5 -14t50.5 -28l16 -14q11 -11 26 -10q16 2 24 14l53 78
+q13 20 -2 39q-3 4 -11 12t-30 23.5t-48.5 28t-67.5 22.5t-86 10q-148 0 -246 -96.5t-98 -240.5q0 -146 97 -241.5t247 -95.5zM1235 303q153 0 257 104q14 18 4 36l-45 82q-8 14 -25 17q-16 2 -27 -11l-4 -3q-4 -4 -11.5 -10t-17.5 -13.5t-23.5 -14.5t-28.5 -13t-33.5 -9.5
+t-37.5 -3.5q-76 0 -125 50t-49 127q0 76 48 125.5t122 49.5q37 0 71.5 -14t50.5 -28l16 -14q11 -11 26 -10q16 2 24 14l53 78q13 20 -2 39q-3 4 -11 12t-30 23.5t-48.5 28t-67.5 22.5t-86 10q-147 0 -245.5 -96.5t-98.5 -240.5q0 -146 97 -241.5t247 -95.5zM896 1376
+q-150 0 -286 -58.5t-234.5 -157t-157 -234.5t-58.5 -286t58.5 -286t157 -234.5t234.5 -157t286 -58.5t286 58.5t234.5 157t157 234.5t58.5 286t-58.5 286t-157 234.5t-234.5 157t-286 58.5zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191
+t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71z" />
+ <glyph glyph-name="f260" unicode="" horiz-adv-x="2048"
+d="M736 736l384 -384l-384 -384l-672 672l672 672l168 -168l-96 -96l-72 72l-480 -480l480 -480l193 193l-289 287zM1312 1312l672 -672l-672 -672l-168 168l96 96l72 -72l480 480l-480 480l-193 -193l289 -287l-96 -96l-384 384z" />
+ <glyph glyph-name="f261" unicode="" horiz-adv-x="1792"
+d="M717 182l271 271l-279 279l-88 -88l192 -191l-96 -96l-279 279l279 279l40 -40l87 87l-127 128l-454 -454zM1075 190l454 454l-454 454l-271 -271l279 -279l88 88l-192 191l96 96l279 -279l-279 -279l-40 40l-87 -88zM1792 640q0 -182 -71 -348t-191 -286t-286 -191
+t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+ <glyph glyph-name="_572" unicode="" horiz-adv-x="2304"
+d="M651 539q0 -39 -27.5 -66.5t-65.5 -27.5q-39 0 -66.5 27.5t-27.5 66.5q0 38 27.5 65.5t66.5 27.5q38 0 65.5 -27.5t27.5 -65.5zM1805 540q0 -39 -27.5 -66.5t-66.5 -27.5t-66.5 27.5t-27.5 66.5t27.5 66t66.5 27t66.5 -27t27.5 -66zM765 539q0 79 -56.5 136t-136.5 57
+t-136.5 -56.5t-56.5 -136.5t56.5 -136.5t136.5 -56.5t136.5 56.5t56.5 136.5zM1918 540q0 80 -56.5 136.5t-136.5 56.5q-79 0 -136 -56.5t-57 -136.5t56.5 -136.5t136.5 -56.5t136.5 56.5t56.5 136.5zM850 539q0 -116 -81.5 -197.5t-196.5 -81.5q-116 0 -197.5 82t-81.5 197
+t82 196.5t197 81.5t196.5 -81.5t81.5 -196.5zM2004 540q0 -115 -81.5 -196.5t-197.5 -81.5q-115 0 -196.5 81.5t-81.5 196.5t81.5 196.5t196.5 81.5q116 0 197.5 -81.5t81.5 -196.5zM1040 537q0 191 -135.5 326.5t-326.5 135.5q-125 0 -231 -62t-168 -168.5t-62 -231.5
+t62 -231.5t168 -168.5t231 -62q191 0 326.5 135.5t135.5 326.5zM1708 1110q-254 111 -556 111q-319 0 -573 -110q117 0 223 -45.5t182.5 -122.5t122 -183t45.5 -223q0 115 43.5 219.5t118 180.5t177.5 123t217 50zM2187 537q0 191 -135 326.5t-326 135.5t-326.5 -135.5
+t-135.5 -326.5t135.5 -326.5t326.5 -135.5t326 135.5t135 326.5zM1921 1103h383q-44 -51 -75 -114.5t-40 -114.5q110 -151 110 -337q0 -156 -77 -288t-209 -208.5t-287 -76.5q-133 0 -249 56t-196 155q-47 -56 -129 -179q-11 22 -53.5 82.5t-74.5 97.5
+q-80 -99 -196.5 -155.5t-249.5 -56.5q-155 0 -287 76.5t-209 208.5t-77 288q0 186 110 337q-9 51 -40 114.5t-75 114.5h365q149 100 355 156.5t432 56.5q224 0 421 -56t348 -157z" />
+ <glyph glyph-name="f263" unicode="" horiz-adv-x="1280"
+d="M640 629q-188 0 -321 133t-133 320q0 188 133 321t321 133t321 -133t133 -321q0 -187 -133 -320t-321 -133zM640 1306q-92 0 -157.5 -65.5t-65.5 -158.5q0 -92 65.5 -157.5t157.5 -65.5t157.5 65.5t65.5 157.5q0 93 -65.5 158.5t-157.5 65.5zM1163 574q13 -27 15 -49.5
+t-4.5 -40.5t-26.5 -38.5t-42.5 -37t-61.5 -41.5q-115 -73 -315 -94l73 -72l267 -267q30 -31 30 -74t-30 -73l-12 -13q-31 -30 -74 -30t-74 30q-67 68 -267 268l-267 -268q-31 -30 -74 -30t-73 30l-12 13q-31 30 -31 73t31 74l267 267l72 72q-203 21 -317 94
+q-39 25 -61.5 41.5t-42.5 37t-26.5 38.5t-4.5 40.5t15 49.5q10 20 28 35t42 22t56 -2t65 -35q5 -4 15 -11t43 -24.5t69 -30.5t92 -24t113 -11q91 0 174 25.5t120 50.5l38 25q33 26 65 35t56 2t42 -22t28 -35z" />
+ <glyph glyph-name="_574" unicode=""
+d="M927 956q0 -66 -46.5 -112.5t-112.5 -46.5t-112.5 46.5t-46.5 112.5t46.5 112.5t112.5 46.5t112.5 -46.5t46.5 -112.5zM1141 593q-10 20 -28 32t-47.5 9.5t-60.5 -27.5q-10 -8 -29 -20t-81 -32t-127 -20t-124 18t-86 36l-27 18q-31 25 -60.5 27.5t-47.5 -9.5t-28 -32
+q-22 -45 -2 -74.5t87 -73.5q83 -53 226 -67l-51 -52q-142 -142 -191 -190q-22 -22 -22 -52.5t22 -52.5l9 -9q22 -22 52.5 -22t52.5 22l191 191q114 -115 191 -191q22 -22 52.5 -22t52.5 22l9 9q22 22 22 52.5t-22 52.5l-191 190l-52 52q141 14 225 67q67 44 87 73.5t-2 74.5
+zM1092 956q0 134 -95 229t-229 95t-229 -95t-95 -229t95 -229t229 -95t229 95t95 229zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="_575" unicode="" horiz-adv-x="1720"
+d="M1565 1408q65 0 110 -45.5t45 -110.5v-519q0 -176 -68 -336t-182.5 -275t-274 -182.5t-334.5 -67.5q-176 0 -335.5 67.5t-274.5 182.5t-183 275t-68 336v519q0 64 46 110t110 46h1409zM861 344q47 0 82 33l404 388q37 35 37 85q0 49 -34.5 83.5t-83.5 34.5q-47 0 -82 -33
+l-323 -310l-323 310q-35 33 -81 33q-49 0 -83.5 -34.5t-34.5 -83.5q0 -51 36 -85l405 -388q33 -33 81 -33z" />
+ <glyph glyph-name="_576" unicode="" horiz-adv-x="2304"
+d="M1494 -103l-295 695q-25 -49 -158.5 -305.5t-198.5 -389.5q-1 -1 -27.5 -0.5t-26.5 1.5q-82 193 -255.5 587t-259.5 596q-21 50 -66.5 107.5t-103.5 100.5t-102 43q0 5 -0.5 24t-0.5 27h583v-50q-39 -2 -79.5 -16t-66.5 -43t-10 -64q26 -59 216.5 -499t235.5 -540
+q31 61 140 266.5t131 247.5q-19 39 -126 281t-136 295q-38 69 -201 71v50l513 -1v-47q-60 -2 -93.5 -25t-12.5 -69q33 -70 87 -189.5t86 -187.5q110 214 173 363q24 55 -10 79.5t-129 26.5q1 7 1 25v24q64 0 170.5 0.5t180 1t92.5 0.5v-49q-62 -2 -119 -33t-90 -81
+l-213 -442q13 -33 127.5 -290t121.5 -274l441 1017q-14 38 -49.5 62.5t-65 31.5t-55.5 8v50l460 -4l1 -2l-1 -44q-139 -4 -201 -145q-526 -1216 -559 -1291h-49z" />
+ <glyph glyph-name="_577" unicode="" horiz-adv-x="1792"
+d="M949 643q0 -26 -16.5 -45t-41.5 -19q-26 0 -45 16.5t-19 41.5q0 26 17 45t42 19t44 -16.5t19 -41.5zM964 585l350 581q-9 -8 -67.5 -62.5t-125.5 -116.5t-136.5 -127t-117 -110.5t-50.5 -51.5l-349 -580q7 7 67 62t126 116.5t136 127t117 111t50 50.5zM1611 640
+q0 -201 -104 -371q-3 2 -17 11t-26.5 16.5t-16.5 7.5q-13 0 -13 -13q0 -10 59 -44q-74 -112 -184.5 -190.5t-241.5 -110.5l-16 67q-1 10 -15 10q-5 0 -8 -5.5t-2 -9.5l16 -68q-72 -15 -146 -15q-199 0 -372 105q1 2 13 20.5t21.5 33.5t9.5 19q0 13 -13 13q-6 0 -17 -14.5
+t-22.5 -34.5t-13.5 -23q-113 75 -192 187.5t-110 244.5l69 15q10 3 10 15q0 5 -5.5 8t-10.5 2l-68 -15q-14 72 -14 139q0 206 109 379q2 -1 18.5 -12t30 -19t17.5 -8q13 0 13 12q0 6 -12.5 15.5t-32.5 21.5l-20 12q77 112 189 189t244 107l15 -67q2 -10 15 -10q5 0 8 5.5
+t2 10.5l-15 66q71 13 134 13q204 0 379 -109q-39 -56 -39 -65q0 -13 12 -13q11 0 48 64q111 -75 187.5 -186t107.5 -241l-56 -12q-10 -2 -10 -16q0 -5 5.5 -8t9.5 -2l57 13q14 -72 14 -140zM1696 640q0 163 -63.5 311t-170.5 255t-255 170.5t-311 63.5t-311 -63.5
+t-255 -170.5t-170.5 -255t-63.5 -311t63.5 -311t170.5 -255t255 -170.5t311 -63.5t311 63.5t255 170.5t170.5 255t63.5 311zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191
+t191 -286t71 -348z" />
+ <glyph glyph-name="_578" unicode="" horiz-adv-x="1792"
+d="M893 1536q240 2 451 -120q232 -134 352 -372l-742 39q-160 9 -294 -74.5t-185 -229.5l-276 424q128 159 311 245.5t383 87.5zM146 1131l337 -663q72 -143 211 -217t293 -45l-230 -451q-212 33 -385 157.5t-272.5 316t-99.5 411.5q0 267 146 491zM1732 962
+q58 -150 59.5 -310.5t-48.5 -306t-153 -272t-246 -209.5q-230 -133 -498 -119l405 623q88 131 82.5 290.5t-106.5 277.5zM896 942q125 0 213.5 -88.5t88.5 -213.5t-88.5 -213.5t-213.5 -88.5t-213.5 88.5t-88.5 213.5t88.5 213.5t213.5 88.5z" />
+ <glyph glyph-name="_579" unicode="" horiz-adv-x="1792"
+d="M903 -256q-283 0 -504.5 150.5t-329.5 398.5q-58 131 -67 301t26 332.5t111 312t179 242.5l-11 -281q11 14 68 15.5t70 -15.5q42 81 160.5 138t234.5 59q-54 -45 -119.5 -148.5t-58.5 -163.5q25 -8 62.5 -13.5t63 -7.5t68 -4t50.5 -3q15 -5 9.5 -45.5t-30.5 -75.5
+q-5 -7 -16.5 -18.5t-56.5 -35.5t-101 -34l15 -189l-139 67q-18 -43 -7.5 -81.5t36 -66.5t65.5 -41.5t81 -6.5q51 9 98 34.5t83.5 45t73.5 17.5q61 -4 89.5 -33t19.5 -65q-1 -2 -2.5 -5.5t-8.5 -12.5t-18 -15.5t-31.5 -10.5t-46.5 -1q-60 -95 -144.5 -135.5t-209.5 -29.5
+q74 -61 162.5 -82.5t168.5 -6t154.5 52t128 87.5t80.5 104q43 91 39 192.5t-37.5 188.5t-78.5 125q87 -38 137 -79.5t77 -112.5q15 170 -57.5 343t-209.5 284q265 -77 412 -279.5t151 -517.5q2 -127 -40.5 -255t-123.5 -238t-189 -196t-247.5 -135.5t-288.5 -49.5z" />
+ <glyph glyph-name="_580" unicode="" horiz-adv-x="1792"
+d="M1493 1308q-165 110 -359 110q-155 0 -293 -73t-240 -200q-75 -93 -119.5 -218t-48.5 -266v-42q4 -141 48.5 -266t119.5 -218q102 -127 240 -200t293 -73q194 0 359 110q-121 -108 -274.5 -168t-322.5 -60q-29 0 -43 1q-175 8 -333 82t-272 193t-181 281t-67 339
+q0 182 71 348t191 286t286 191t348 71h3q168 -1 320.5 -60.5t273.5 -167.5zM1792 640q0 -192 -77 -362.5t-213 -296.5q-104 -63 -222 -63q-137 0 -255 84q154 56 253.5 233t99.5 405q0 227 -99 404t-253 234q119 83 254 83q119 0 226 -65q135 -125 210.5 -295t75.5 -361z
+" />
+ <glyph glyph-name="_581" unicode="" horiz-adv-x="1792"
+d="M1792 599q0 -56 -7 -104h-1151q0 -146 109.5 -244.5t257.5 -98.5q99 0 185.5 46.5t136.5 130.5h423q-56 -159 -170.5 -281t-267.5 -188.5t-321 -66.5q-187 0 -356 83q-228 -116 -394 -116q-237 0 -237 263q0 115 45 275q17 60 109 229q199 360 475 606
+q-184 -79 -427 -354q63 274 283.5 449.5t501.5 175.5q30 0 45 -1q255 117 433 117q64 0 116 -13t94.5 -40.5t66.5 -76.5t24 -115q0 -116 -75 -286q101 -182 101 -390zM1722 1239q0 83 -53 132t-137 49q-108 0 -254 -70q121 -47 222.5 -131.5t170.5 -195.5q51 135 51 216z
+M128 2q0 -86 48.5 -132.5t134.5 -46.5q115 0 266 83q-122 72 -213.5 183t-137.5 245q-98 -205 -98 -332zM632 715h728q-5 142 -113 237t-251 95q-144 0 -251.5 -95t-112.5 -237z" />
+ <glyph glyph-name="_582" unicode="" horiz-adv-x="2048"
+d="M1792 288v960q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1248v-960q0 -66 -47 -113t-113 -47h-736v-128h352q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23
+v64q0 14 9 23t23 9h352v128h-736q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+ <glyph glyph-name="_583" unicode="" horiz-adv-x="1792"
+d="M138 1408h197q-70 -64 -126 -149q-36 -56 -59 -115t-30 -125.5t-8.5 -120t10.5 -132t21 -126t28 -136.5q4 -19 6 -28q51 -238 81 -329q57 -171 152 -275h-272q-48 0 -82 34t-34 82v1304q0 48 34 82t82 34zM1346 1408h308q48 0 82 -34t34 -82v-1304q0 -48 -34 -82t-82 -34
+h-178q212 210 196 565l-469 -101q-2 -45 -12 -82t-31 -72t-59.5 -59.5t-93.5 -36.5q-123 -26 -199 40q-32 27 -53 61t-51.5 129t-64.5 258q-35 163 -45.5 263t-5.5 139t23 77q20 41 62.5 73t102.5 45q45 12 83.5 6.5t67 -17t54 -35t43 -48t34.5 -56.5l468 100
+q-68 175 -180 287z" />
+ <glyph glyph-name="_584" unicode=""
+d="M1401 -11l-6 -6q-113 -113 -259 -175q-154 -64 -317 -64q-165 0 -317 64q-148 63 -259 175q-113 112 -175 258q-42 103 -54 189q-4 28 48 36q51 8 56 -20q1 -1 1 -4q18 -90 46 -159q50 -124 152 -226q98 -98 226 -152q132 -56 276 -56q143 0 276 56q128 55 225 152l6 6
+q10 10 25 6q12 -3 33 -22q36 -37 17 -58zM929 604l-66 -66l63 -63q21 -21 -7 -49q-17 -17 -32 -17q-10 0 -19 10l-62 61l-66 -66q-5 -5 -15 -5q-15 0 -31 16l-2 2q-18 15 -18 29q0 7 8 17l66 65l-66 66q-16 16 14 45q18 18 31 18q6 0 13 -5l65 -66l65 65q18 17 48 -13
+q27 -27 11 -44zM1400 547q0 -118 -46 -228q-45 -105 -126 -186q-80 -80 -187 -126t-228 -46t-228 46t-187 126q-82 82 -125 186q-15 33 -15 40h-1q-9 27 43 44q50 16 60 -12q37 -99 97 -167h1v339v2q3 136 102 232q105 103 253 103q147 0 251 -103t104 -249
+q0 -147 -104.5 -251t-250.5 -104q-58 0 -112 16q-28 11 -13 61q16 51 44 43l14 -3q14 -3 33 -6t30 -3q104 0 176 71.5t72 174.5q0 101 -72 171q-71 71 -175 71q-107 0 -178 -80q-64 -72 -64 -160v-413q110 -67 242 -67q96 0 185 36.5t156 103.5t103.5 155t36.5 183
+q0 198 -141 339q-140 140 -339 140q-200 0 -340 -140q-53 -53 -77 -87l-2 -2q-8 -11 -13 -15.5t-21.5 -9.5t-38.5 3q-21 5 -36.5 16.5t-15.5 26.5v680q0 15 10.5 26.5t27.5 11.5h877q30 0 30 -55t-30 -55h-811v-483h1q40 42 102 84t108 61q109 46 231 46q121 0 228 -46
+t187 -126q81 -81 126 -186q46 -112 46 -229zM1369 1128q9 -8 9 -18t-5.5 -18t-16.5 -21q-26 -26 -39 -26q-9 0 -16 7q-106 91 -207 133q-128 56 -276 56q-133 0 -262 -49q-27 -10 -45 37q-9 25 -8 38q3 16 16 20q130 57 299 57q164 0 316 -64q137 -58 235 -152z" />
+ <glyph glyph-name="_585" unicode="" horiz-adv-x="1792"
+d="M1551 60q15 6 26 3t11 -17.5t-15 -33.5q-13 -16 -44 -43.5t-95.5 -68t-141 -74t-188 -58t-229.5 -24.5q-119 0 -238 31t-209 76.5t-172.5 104t-132.5 105t-84 87.5q-8 9 -10 16.5t1 12t8 7t11.5 2t11.5 -4.5q192 -117 300 -166q389 -176 799 -90q190 40 391 135z
+M1758 175q11 -16 2.5 -69.5t-28.5 -102.5q-34 -83 -85 -124q-17 -14 -26 -9t0 24q21 45 44.5 121.5t6.5 98.5q-5 7 -15.5 11.5t-27 6t-29.5 2.5t-35 0t-31.5 -2t-31 -3t-22.5 -2q-6 -1 -13 -1.5t-11 -1t-8.5 -1t-7 -0.5h-5.5h-4.5t-3 0.5t-2 1.5l-1.5 3q-6 16 47 40t103 30
+q46 7 108 1t76 -24zM1364 618q0 -31 13.5 -64t32 -58t37.5 -46t33 -32l13 -11l-227 -224q-40 37 -79 75.5t-58 58.5l-19 20q-11 11 -25 33q-38 -59 -97.5 -102.5t-127.5 -63.5t-140 -23t-137.5 21t-117.5 65.5t-83 113t-31 162.5q0 84 28 154t72 116.5t106.5 83t122.5 57
+t130 34.5t119.5 18.5t99.5 6.5v127q0 65 -21 97q-34 53 -121 53q-6 0 -16.5 -1t-40.5 -12t-56 -29.5t-56 -59.5t-48 -96l-294 27q0 60 22 119t67 113t108 95t151.5 65.5t190.5 24.5q100 0 181 -25t129.5 -61.5t81 -83t45 -86t12.5 -73.5v-589zM692 597q0 -86 70 -133
+q66 -44 139 -22q84 25 114 123q14 45 14 101v162q-59 -2 -111 -12t-106.5 -33.5t-87 -71t-32.5 -114.5z" />
+ <glyph glyph-name="_586" unicode="" horiz-adv-x="1792"
+d="M1536 1280q52 0 90 -38t38 -90v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128zM1152 1376v-288q0 -14 9 -23t23 -9
+h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM384 1376v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM1536 -128v1024h-1408v-1024h1408zM896 448h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224
+v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v224q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-224z" />
+ <glyph glyph-name="_587" unicode="" horiz-adv-x="1792"
+d="M1152 416v-64q0 -14 -9 -23t-23 -9h-576q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h576q14 0 23 -9t9 -23zM128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23
+t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47
+t47 -113v-96h128q52 0 90 -38t38 -90z" />
+ <glyph glyph-name="_588" unicode="" horiz-adv-x="1792"
+d="M1111 151l-46 -46q-9 -9 -22 -9t-23 9l-188 189l-188 -189q-10 -9 -23 -9t-22 9l-46 46q-9 9 -9 22t9 23l189 188l-189 188q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l188 -188l188 188q10 9 23 9t22 -9l46 -46q9 -9 9 -22t-9 -23l-188 -188l188 -188q9 -10 9 -23t-9 -22z
+M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280
+q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+ <glyph glyph-name="_589" unicode="" horiz-adv-x="1792"
+d="M1303 572l-512 -512q-10 -9 -23 -9t-23 9l-288 288q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l220 -220l444 444q10 9 23 9t22 -9l46 -46q9 -9 9 -22t-9 -23zM128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23
+t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47
+t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+ <glyph glyph-name="_590" unicode="" horiz-adv-x="1792"
+d="M448 1536q26 0 45 -19t19 -45v-891l536 429q17 14 40 14q26 0 45 -19t19 -45v-379l536 429q17 14 40 14q26 0 45 -19t19 -45v-1152q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h384z" />
+ <glyph glyph-name="_591" unicode="" horiz-adv-x="1024"
+d="M512 448q66 0 128 15v-655q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v655q62 -15 128 -15zM512 1536q212 0 362 -150t150 -362t-150 -362t-362 -150t-362 150t-150 362t150 362t362 150zM512 1312q14 0 23 9t9 23t-9 23t-23 9q-146 0 -249 -103t-103 -249
+q0 -14 9 -23t23 -9t23 9t9 23q0 119 84.5 203.5t203.5 84.5z" />
+ <glyph glyph-name="_592" unicode="" horiz-adv-x="1792"
+d="M1745 1239q10 -10 10 -23t-10 -23l-141 -141q-28 -28 -68 -28h-1344q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h576v64q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-64h512q40 0 68 -28zM768 320h256v-512q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v512zM1600 768
+q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-1344q-40 0 -68 28l-141 141q-10 10 -10 23t10 23l141 141q28 28 68 28h512v192h256v-192h576z" />
+ <glyph glyph-name="_593" unicode="" horiz-adv-x="2048"
+d="M2020 1525q28 -20 28 -53v-1408q0 -20 -11 -36t-29 -23l-640 -256q-24 -11 -48 0l-616 246l-616 -246q-10 -5 -24 -5q-19 0 -36 11q-28 20 -28 53v1408q0 20 11 36t29 23l640 256q24 11 48 0l616 -246l616 246q32 13 60 -6zM736 1390v-1270l576 -230v1270zM128 1173
+v-1270l544 217v1270zM1920 107v1270l-544 -217v-1270z" />
+ <glyph glyph-name="_594" unicode="" horiz-adv-x="1792"
+d="M512 1536q13 0 22.5 -9.5t9.5 -22.5v-1472q0 -20 -17 -28l-480 -256q-7 -4 -15 -4q-13 0 -22.5 9.5t-9.5 22.5v1472q0 20 17 28l480 256q7 4 15 4zM1760 1536q13 0 22.5 -9.5t9.5 -22.5v-1472q0 -20 -17 -28l-480 -256q-7 -4 -15 -4q-13 0 -22.5 9.5t-9.5 22.5v1472
+q0 20 17 28l480 256q7 4 15 4zM640 1536q8 0 14 -3l512 -256q18 -10 18 -29v-1472q0 -13 -9.5 -22.5t-22.5 -9.5q-8 0 -14 3l-512 256q-18 10 -18 29v1472q0 13 9.5 22.5t22.5 9.5z" />
+ <glyph glyph-name="_595" unicode="" horiz-adv-x="1792"
+d="M640 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1408 640q0 53 -37.5 90.5t-90.5 37.5
+t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-110 0 -211 18q-173 -173 -435 -229q-52 -10 -86 -13q-12 -1 -22 6t-13 18q-4 15 20 37q5 5 23.5 21.5t25.5 23.5t23.5 25.5t24 31.5t20.5 37
+t20 48t14.5 57.5t12.5 72.5q-146 90 -229.5 216.5t-83.5 269.5q0 174 120 321.5t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" />
+ <glyph glyph-name="_596" unicode="" horiz-adv-x="1792"
+d="M640 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1024 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 -53 -37.5 -90.5t-90.5 -37.5
+t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5
+t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51
+t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 130 71 248.5t191 204.5t286 136.5t348 50.5t348 -50.5t286 -136.5t191 -204.5t71 -248.5z" />
+ <glyph glyph-name="_597" unicode="" horiz-adv-x="1024"
+d="M512 345l512 295v-591l-512 -296v592zM0 640v-591l512 296zM512 1527v-591l-512 -296v591zM512 936l512 295v-591z" />
+ <glyph glyph-name="_598" unicode="" horiz-adv-x="1792"
+d="M1709 1018q-10 -236 -332 -651q-333 -431 -562 -431q-142 0 -240 263q-44 160 -132 482q-72 262 -157 262q-18 0 -127 -76l-77 98q24 21 108 96.5t130 115.5q156 138 241 146q95 9 153 -55.5t81 -203.5q44 -287 66 -373q55 -249 120 -249q51 0 154 161q101 161 109 246
+q13 139 -109 139q-57 0 -121 -26q120 393 459 382q251 -8 236 -326z" />
+ <glyph glyph-name="f27e" unicode=""
+d="M0 1408h1536v-1536h-1536v1536zM1085 293l-221 631l221 297h-634l221 -297l-221 -631l317 -304z" />
+ <glyph glyph-name="uniF280" unicode=""
+d="M0 1408h1536v-1536h-1536v1536zM908 1088l-12 -33l75 -83l-31 -114l25 -25l107 57l107 -57l25 25l-31 114l75 83l-12 33h-95l-53 96h-32l-53 -96h-95zM641 925q32 0 44.5 -16t11.5 -63l174 21q0 55 -17.5 92.5t-50.5 56t-69 25.5t-85 7q-133 0 -199 -57.5t-66 -182.5v-72
+h-96v-128h76q20 0 20 -8v-382q0 -14 -5 -20t-18 -7l-73 -7v-88h448v86l-149 14q-6 1 -8.5 1.5t-3.5 2.5t-0.5 4t1 7t0.5 10v387h191l38 128h-231q-6 0 -2 6t4 9v80q0 27 1.5 40.5t7.5 28t19.5 20t36.5 5.5zM1248 96v86l-54 9q-7 1 -9.5 2.5t-2.5 3t1 7.5t1 12v520h-275
+l-23 -101l83 -22q23 -7 23 -27v-370q0 -14 -6 -18.5t-20 -6.5l-70 -9v-86h352z" />
+ <glyph glyph-name="uniF281" unicode="" horiz-adv-x="1792"
+d="M1792 690q0 -58 -29.5 -105.5t-79.5 -72.5q12 -46 12 -96q0 -155 -106.5 -287t-290.5 -208.5t-400 -76.5t-399.5 76.5t-290 208.5t-106.5 287q0 47 11 94q-51 25 -82 73.5t-31 106.5q0 82 58 140.5t141 58.5q85 0 145 -63q218 152 515 162l116 521q3 13 15 21t26 5
+l369 -81q18 37 54 59.5t79 22.5q62 0 106 -43.5t44 -105.5t-44 -106t-106 -44t-105.5 43.5t-43.5 105.5l-334 74l-104 -472q300 -9 519 -160q58 61 143 61q83 0 141 -58.5t58 -140.5zM418 491q0 -62 43.5 -106t105.5 -44t106 44t44 106t-44 105.5t-106 43.5q-61 0 -105 -44
+t-44 -105zM1228 136q11 11 11 26t-11 26q-10 10 -25 10t-26 -10q-41 -42 -121 -62t-160 -20t-160 20t-121 62q-11 10 -26 10t-25 -10q-11 -10 -11 -25.5t11 -26.5q43 -43 118.5 -68t122.5 -29.5t91 -4.5t91 4.5t122.5 29.5t118.5 68zM1225 341q62 0 105.5 44t43.5 106
+q0 61 -44 105t-105 44q-62 0 -106 -43.5t-44 -105.5t44 -106t106 -44z" />
+ <glyph glyph-name="_602" unicode="" horiz-adv-x="1792"
+d="M69 741h1q16 126 58.5 241.5t115 217t167.5 176t223.5 117.5t276.5 43q231 0 414 -105.5t294 -303.5q104 -187 104 -442v-188h-1125q1 -111 53.5 -192.5t136.5 -122.5t189.5 -57t213 -3t208 46.5t173.5 84.5v-377q-92 -55 -229.5 -92t-312.5 -38t-316 53
+q-189 73 -311.5 249t-124.5 372q-3 242 111 412t325 268q-48 -60 -78 -125.5t-46 -159.5h635q8 77 -8 140t-47 101.5t-70.5 66.5t-80.5 41t-75 20.5t-56 8.5l-22 1q-135 -5 -259.5 -44.5t-223.5 -104.5t-176 -140.5t-138 -163.5z" />
+ <glyph glyph-name="_603" unicode="" horiz-adv-x="2304"
+d="M0 32v608h2304v-608q0 -66 -47 -113t-113 -47h-1984q-66 0 -113 47t-47 113zM640 256v-128h384v128h-384zM256 256v-128h256v128h-256zM2144 1408q66 0 113 -47t47 -113v-224h-2304v224q0 66 47 113t113 47h1984z" />
+ <glyph glyph-name="_604" unicode="" horiz-adv-x="1792"
+d="M1584 246l-218 111q-74 -120 -196.5 -189t-263.5 -69q-147 0 -271 72t-196 196t-72 270q0 110 42.5 209.5t115 172t172 115t209.5 42.5q131 0 247.5 -60.5t192.5 -168.5l215 125q-110 169 -286.5 265t-378.5 96q-161 0 -308 -63t-253 -169t-169 -253t-63 -308t63 -308
+t169 -253t253 -169t308 -63q213 0 397.5 107t290.5 292zM1030 643l693 -352q-116 -253 -334.5 -400t-492.5 -147q-182 0 -348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71q260 0 470.5 -133.5t335.5 -366.5zM1543 640h-39v-160h-96v352h136q32 0 54.5 -20
+t28.5 -48t1 -56t-27.5 -48t-57.5 -20z" />
+ <glyph glyph-name="uniF285" unicode="" horiz-adv-x="1792"
+d="M1427 827l-614 386l92 151h855zM405 562l-184 116v858l1183 -743zM1424 697l147 -95v-858l-532 335zM1387 718l-500 -802h-855l356 571z" />
+ <glyph glyph-name="uniF286" unicode="" horiz-adv-x="1792"
+d="M640 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1152 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1664 496v-752h-640v320q0 80 -56 136t-136 56t-136 -56t-56 -136v-320h-640v752q0 16 16 16h96
+q16 0 16 -16v-112h128v624q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 6 2.5 9.5t8.5 5t9.5 2t11.5 0t9 -0.5v391q-32 15 -32 50q0 23 16.5 39t38.5 16t38.5 -16t16.5 -39q0 -35 -32 -50v-17q45 10 83 10q21 0 59.5 -7.5t54.5 -7.5
+q17 0 47 7.5t37 7.5q16 0 16 -16v-210q0 -15 -35 -21.5t-62 -6.5q-18 0 -54.5 7.5t-55.5 7.5q-40 0 -90 -12v-133q1 0 9 0.5t11.5 0t9.5 -2t8.5 -5t2.5 -9.5v-112h128v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-624h128v112q0 16 16 16h96
+q16 0 16 -16z" />
+ <glyph glyph-name="_607" unicode="" horiz-adv-x="2304"
+d="M2288 731q16 -8 16 -27t-16 -27l-320 -192q-8 -5 -16 -5q-9 0 -16 4q-16 10 -16 28v128h-858q37 -58 83 -165q16 -37 24.5 -55t24 -49t27 -47t27 -34t31.5 -26t33 -8h96v96q0 14 9 23t23 9h320q14 0 23 -9t9 -23v-320q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v96h-96
+q-32 0 -61 10t-51 23.5t-45 40.5t-37 46t-33.5 57t-28.5 57.5t-28 60.5q-23 53 -37 81.5t-36 65t-44.5 53.5t-46.5 17h-360q-22 -84 -91 -138t-157 -54q-106 0 -181 75t-75 181t75 181t181 75q88 0 157 -54t91 -138h104q24 0 46.5 17t44.5 53.5t36 65t37 81.5q19 41 28 60.5
+t28.5 57.5t33.5 57t37 46t45 40.5t51 23.5t61 10h107q21 57 70 92.5t111 35.5q80 0 136 -56t56 -136t-56 -136t-136 -56q-62 0 -111 35.5t-70 92.5h-107q-17 0 -33 -8t-31.5 -26t-27 -34t-27 -47t-24 -49t-24.5 -55q-46 -107 -83 -165h1114v128q0 18 16 28t32 -1z" />
+ <glyph glyph-name="_608" unicode="" horiz-adv-x="1792"
+d="M1150 774q0 -56 -39.5 -95t-95.5 -39h-253v269h253q56 0 95.5 -39.5t39.5 -95.5zM1329 774q0 130 -91.5 222t-222.5 92h-433v-896h180v269h253q130 0 222 91.5t92 221.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348
+t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+ <glyph glyph-name="_609" unicode="" horiz-adv-x="2304"
+d="M1645 438q0 59 -34 106.5t-87 68.5q-7 -45 -23 -92q-7 -24 -27.5 -38t-44.5 -14q-12 0 -24 3q-31 10 -45 38.5t-4 58.5q23 71 23 143q0 123 -61 227.5t-166 165.5t-228 61q-134 0 -247 -73t-167 -194q108 -28 188 -106q22 -23 22 -55t-22 -54t-54 -22t-55 22
+q-75 75 -180 75q-106 0 -181 -74.5t-75 -180.5t75 -180.5t181 -74.5h1046q79 0 134.5 55.5t55.5 133.5zM1798 438q0 -142 -100.5 -242t-242.5 -100h-1046q-169 0 -289 119.5t-120 288.5q0 153 100 267t249 136q62 184 221 298t354 114q235 0 408.5 -158.5t196.5 -389.5
+q116 -25 192.5 -118.5t76.5 -214.5zM2048 438q0 -175 -97 -319q-23 -33 -64 -33q-24 0 -43 13q-26 17 -32 48.5t12 57.5q71 104 71 233t-71 233q-18 26 -12 57t32 49t57.5 11.5t49.5 -32.5q97 -142 97 -318zM2304 438q0 -244 -134 -443q-23 -34 -64 -34q-23 0 -42 13
+q-26 18 -32.5 49t11.5 57q108 164 108 358q0 195 -108 357q-18 26 -11.5 57.5t32.5 48.5q26 18 57 12t49 -33q134 -198 134 -442z" />
+ <glyph glyph-name="_610" unicode=""
+d="M1500 -13q0 -89 -63 -152.5t-153 -63.5t-153.5 63.5t-63.5 152.5q0 90 63.5 153.5t153.5 63.5t153 -63.5t63 -153.5zM1267 268q-115 -15 -192.5 -102.5t-77.5 -205.5q0 -74 33 -138q-146 -78 -379 -78q-109 0 -201 21t-153.5 54.5t-110.5 76.5t-76 85t-44.5 83
+t-23.5 66.5t-6 39.5q0 19 4.5 42.5t18.5 56t36.5 58t64 43.5t94.5 18t94 -17.5t63 -41t35.5 -53t17.5 -49t4 -33.5q0 -34 -23 -81q28 -27 82 -42t93 -17l40 -1q115 0 190 51t75 133q0 26 -9 48.5t-31.5 44.5t-49.5 41t-74 44t-93.5 47.5t-119.5 56.5q-28 13 -43 20
+q-116 55 -187 100t-122.5 102t-72 125.5t-20.5 162.5q0 78 20.5 150t66 137.5t112.5 114t166.5 77t221.5 28.5q120 0 220 -26t164.5 -67t109.5 -94t64 -105.5t19 -103.5q0 -46 -15 -82.5t-36.5 -58t-48.5 -36t-49 -19.5t-39 -5h-8h-32t-39 5t-44 14t-41 28t-37 46t-24 70.5
+t-10 97.5q-15 16 -59 25.5t-81 10.5l-37 1q-68 0 -117.5 -31t-70.5 -70t-21 -76q0 -24 5 -43t24 -46t53 -51t97 -53.5t150 -58.5q76 -25 138.5 -53.5t109 -55.5t83 -59t60.5 -59.5t41 -62.5t26.5 -62t14.5 -63.5t6 -62t1 -62.5z" />
+ <glyph glyph-name="_611" unicode=""
+d="M704 352v576q0 14 -9 23t-23 9h-256q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h256q14 0 23 9t9 23zM1152 352v576q0 14 -9 23t-23 9h-256q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h256q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103
+t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="_612" unicode=""
+d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM768 96q148 0 273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273
+t73 -273t198 -198t273 -73zM864 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-192zM480 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-192z" />
+ <glyph glyph-name="_613" unicode=""
+d="M1088 352v576q0 14 -9 23t-23 9h-576q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h576q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5
+t103 -385.5z" />
+ <glyph glyph-name="_614" unicode=""
+d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM768 96q148 0 273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273
+t73 -273t198 -198t273 -73zM480 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h576q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-576z" />
+ <glyph glyph-name="_615" unicode="" horiz-adv-x="1792"
+d="M1757 128l35 -313q3 -28 -16 -50q-19 -21 -48 -21h-1664q-29 0 -48 21q-19 22 -16 50l35 313h1722zM1664 967l86 -775h-1708l86 775q3 24 21 40.5t43 16.5h256v-128q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5v128h384v-128q0 -53 37.5 -90.5t90.5 -37.5
+t90.5 37.5t37.5 90.5v128h256q25 0 43 -16.5t21 -40.5zM1280 1152v-256q0 -26 -19 -45t-45 -19t-45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-256q0 -26 -19 -45t-45 -19t-45 19t-19 45v256q0 159 112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
+ <glyph glyph-name="_616" unicode="" horiz-adv-x="2048"
+d="M1920 768q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5h-15l-115 -662q-8 -46 -44 -76t-82 -30h-1280q-46 0 -82 30t-44 76l-115 662h-15q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5h1792zM485 -32q26 2 43.5 22.5t15.5 46.5l-32 416q-2 26 -22.5 43.5
+t-46.5 15.5t-43.5 -22.5t-15.5 -46.5l32 -416q2 -25 20.5 -42t43.5 -17h5zM896 32v416q0 26 -19 45t-45 19t-45 -19t-19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45zM1280 32v416q0 26 -19 45t-45 19t-45 -19t-19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45zM1632 27l32 416
+q2 26 -15.5 46.5t-43.5 22.5t-46.5 -15.5t-22.5 -43.5l-32 -416q-2 -26 15.5 -46.5t43.5 -22.5h5q25 0 43.5 17t20.5 42zM476 1244l-93 -412h-132l101 441q19 88 89 143.5t160 55.5h167q0 26 19 45t45 19h384q26 0 45 -19t19 -45h167q90 0 160 -55.5t89 -143.5l101 -441
+h-132l-93 412q-11 44 -45.5 72t-79.5 28h-167q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45h-167q-45 0 -79.5 -28t-45.5 -72z" />
+ <glyph glyph-name="_617" unicode="" horiz-adv-x="1792"
+d="M991 512l64 256h-254l-64 -256h254zM1759 1016l-56 -224q-7 -24 -31 -24h-327l-64 -256h311q15 0 25 -12q10 -14 6 -28l-56 -224q-5 -24 -31 -24h-327l-81 -328q-7 -24 -31 -24h-224q-16 0 -26 12q-9 12 -6 28l78 312h-254l-81 -328q-7 -24 -31 -24h-225q-15 0 -25 12
+q-9 12 -6 28l78 312h-311q-15 0 -25 12q-9 12 -6 28l56 224q7 24 31 24h327l64 256h-311q-15 0 -25 12q-10 14 -6 28l56 224q5 24 31 24h327l81 328q7 24 32 24h224q15 0 25 -12q9 -12 6 -28l-78 -312h254l81 328q7 24 32 24h224q15 0 25 -12q9 -12 6 -28l-78 -312h311
+q15 0 25 -12q9 -12 6 -28z" />
+ <glyph glyph-name="_618" unicode=""
+d="M841 483l148 -148l-149 -149zM840 1094l149 -149l-148 -148zM710 -130l464 464l-306 306l306 306l-464 464v-611l-255 255l-93 -93l320 -321l-320 -321l93 -93l255 255v-611zM1429 640q0 -209 -32 -365.5t-87.5 -257t-140.5 -162.5t-181.5 -86.5t-219.5 -24.5
+t-219.5 24.5t-181.5 86.5t-140.5 162.5t-87.5 257t-32 365.5t32 365.5t87.5 257t140.5 162.5t181.5 86.5t219.5 24.5t219.5 -24.5t181.5 -86.5t140.5 -162.5t87.5 -257t32 -365.5z" />
+ <glyph glyph-name="_619" unicode="" horiz-adv-x="1024"
+d="M596 113l173 172l-173 172v-344zM596 823l173 172l-173 172v-344zM628 640l356 -356l-539 -540v711l-297 -296l-108 108l372 373l-372 373l108 108l297 -296v711l539 -540z" />
+ <glyph glyph-name="_620" unicode=""
+d="M1280 256q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM512 1024q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5
+t112.5 -271.5zM1440 1344q0 -20 -13 -38l-1056 -1408q-19 -26 -51 -26h-160q-26 0 -45 19t-19 45q0 20 13 38l1056 1408q19 26 51 26h160q26 0 45 -19t19 -45zM768 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5
+t271.5 -112.5t112.5 -271.5z" />
+ <glyph glyph-name="_621" unicode="" horiz-adv-x="1792"
+d="M104 830l792 -1015l-868 630q-18 13 -25 34.5t0 42.5l101 308v0zM566 830h660l-330 -1015v0zM368 1442l198 -612h-462l198 612q8 23 33 23t33 -23zM1688 830l101 -308q7 -21 0 -42.5t-25 -34.5l-868 -630l792 1015v0zM1688 830h-462l198 612q8 23 33 23t33 -23z" />
+ <glyph glyph-name="_622" unicode="" horiz-adv-x="1792"
+d="M384 704h160v224h-160v-224zM1221 372v92q-104 -36 -243 -38q-135 -1 -259.5 46.5t-220.5 122.5l1 -96q88 -80 212 -128.5t272 -47.5q129 0 238 49zM640 704h640v224h-640v-224zM1792 736q0 -187 -99 -352q89 -102 89 -229q0 -157 -129.5 -268t-313.5 -111
+q-122 0 -225 52.5t-161 140.5q-19 -1 -57 -1t-57 1q-58 -88 -161 -140.5t-225 -52.5q-184 0 -313.5 111t-129.5 268q0 127 89 229q-99 165 -99 352q0 209 120 385.5t326.5 279.5t449.5 103t449.5 -103t326.5 -279.5t120 -385.5z" />
+ <glyph glyph-name="_623" unicode=""
+d="M515 625v-128h-252v128h252zM515 880v-127h-252v127h252zM1273 369v-128h-341v128h341zM1273 625v-128h-672v128h672zM1273 880v-127h-672v127h672zM1408 20v1240q0 8 -6 14t-14 6h-32l-378 -256l-210 171l-210 -171l-378 256h-32q-8 0 -14 -6t-6 -14v-1240q0 -8 6 -14
+t14 -6h1240q8 0 14 6t6 14zM553 1130l185 150h-406zM983 1130l221 150h-406zM1536 1260v-1240q0 -62 -43 -105t-105 -43h-1240q-62 0 -105 43t-43 105v1240q0 62 43 105t105 43h1240q62 0 105 -43t43 -105z" />
+ <glyph glyph-name="_624" unicode="" horiz-adv-x="1792"
+d="M896 720q-104 196 -160 278q-139 202 -347 318q-34 19 -70 36q-89 40 -94 32t34 -38l39 -31q62 -43 112.5 -93.5t94.5 -116.5t70.5 -113t70.5 -131q9 -17 13 -25q44 -84 84 -153t98 -154t115.5 -150t131 -123.5t148.5 -90.5q153 -66 154 -60q1 3 -49 37q-53 36 -81 57
+q-77 58 -179 211t-185 310zM549 177q-76 60 -132.5 125t-98 143.5t-71 154.5t-58.5 186t-52 209t-60.5 252t-76.5 289q273 0 497.5 -36t379 -92t271 -144.5t185.5 -172.5t110 -198.5t56 -199.5t12.5 -198.5t-9.5 -173t-20 -143.5t-13 -107l323 -327h-104l-281 285
+q-22 -2 -91.5 -14t-121.5 -19t-138 -6t-160.5 17t-167.5 59t-179 111z" />
+ <glyph glyph-name="_625" unicode="" horiz-adv-x="1792"
+d="M1374 879q-6 26 -28.5 39.5t-48.5 7.5q-261 -62 -401 -62t-401 62q-26 6 -48.5 -7.5t-28.5 -39.5t7.5 -48.5t39.5 -28.5q194 -46 303 -58q-2 -158 -15.5 -269t-26.5 -155.5t-41 -115.5l-9 -21q-10 -25 1 -49t36 -34q9 -4 23 -4q44 0 60 41l8 20q54 139 71 259h42
+q17 -120 71 -259l8 -20q16 -41 60 -41q14 0 23 4q25 10 36 34t1 49l-9 21q-28 71 -41 115.5t-26.5 155.5t-15.5 269q109 12 303 58q26 6 39.5 28.5t7.5 48.5zM1024 1024q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5z
+M1600 640q0 -143 -55.5 -273.5t-150 -225t-225 -150t-273.5 -55.5t-273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5zM896 1408q-156 0 -298 -61t-245 -164t-164 -245t-61 -298t61 -298
+t164 -245t245 -164t298 -61t298 61t245 164t164 245t61 298t-61 298t-164 245t-245 164t-298 61zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+ <glyph glyph-name="_626" unicode=""
+d="M1438 723q34 -35 29 -82l-44 -551q-4 -42 -34.5 -70t-71.5 -28q-6 0 -9 1q-44 3 -72.5 36.5t-25.5 77.5l35 429l-143 -8q55 -113 55 -240q0 -216 -148 -372l-137 137q91 101 91 235q0 145 -102.5 248t-247.5 103q-134 0 -236 -92l-137 138q120 114 284 141l264 300
+l-149 87l-181 -161q-33 -30 -77 -27.5t-73 35.5t-26.5 77t34.5 73l239 213q26 23 60 26.5t64 -14.5l488 -283q36 -21 48 -68q17 -67 -26 -117l-205 -232l371 20q49 3 83 -32zM1240 1180q-74 0 -126 52t-52 126t52 126t126 52t126.5 -52t52.5 -126t-52.5 -126t-126.5 -52z
+M613 -62q106 0 196 61l139 -139q-146 -116 -335 -116q-148 0 -273.5 73t-198.5 198t-73 273q0 188 116 336l139 -139q-60 -88 -60 -197q0 -145 102.5 -247.5t247.5 -102.5z" />
+ <glyph glyph-name="_627" unicode=""
+d="M880 336v-160q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v160q0 14 9 23t23 9h160q14 0 23 -9t9 -23zM1136 832q0 -50 -15 -90t-45.5 -69t-52 -44t-59.5 -36q-32 -18 -46.5 -28t-26 -24t-11.5 -29v-32q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v68q0 35 10.5 64.5
+t24 47.5t39 35.5t41 25.5t44.5 21q53 25 75 43t22 49q0 42 -43.5 71.5t-95.5 29.5q-56 0 -95 -27q-29 -20 -80 -83q-9 -12 -25 -12q-11 0 -19 6l-108 82q-10 7 -12 20t5 23q122 192 349 192q129 0 238.5 -89.5t109.5 -214.5zM768 1280q-130 0 -248.5 -51t-204 -136.5
+t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5
+t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="_628" unicode="" horiz-adv-x="1408"
+d="M366 1225q-64 0 -110 45.5t-46 110.5q0 64 46 109.5t110 45.5t109.5 -45.5t45.5 -109.5q0 -65 -45.5 -110.5t-109.5 -45.5zM917 583q0 -50 -30 -67.5t-63.5 -6.5t-47.5 34l-367 438q-7 12 -14 15.5t-11 1.5l-3 -3q-7 -8 4 -21l122 -139l1 -354l-161 -457
+q-67 -192 -92 -234q-15 -26 -28 -32q-50 -26 -103 -1q-29 13 -41.5 43t-9.5 57q2 17 197 618l5 416l-85 -164l35 -222q4 -24 -1 -42t-14 -27.5t-19 -16t-17 -7.5l-7 -2q-19 -3 -34.5 3t-24 16t-14 22t-7.5 19.5t-2 9.5l-46 299l211 381q23 34 113 34q75 0 107 -40l424 -521
+q7 -5 14 -17l3 -3l-1 -1q7 -13 7 -29zM514 433q43 -113 88.5 -225t69.5 -168l24 -55q36 -93 42 -125q11 -70 -36 -97q-35 -22 -66 -16t-51 22t-29 35h-1q-6 16 -8 25l-124 351zM1338 -159q31 -49 31 -57q0 -5 -3 -7q-9 -5 -14.5 0.5t-15.5 26t-16 30.5q-114 172 -423 661
+q3 -1 7 1t7 4l3 2q11 9 11 17z" />
+ <glyph glyph-name="_629" unicode="" horiz-adv-x="2304"
+d="M504 542h171l-1 265zM1530 641q0 87 -50.5 140t-146.5 53h-54v-388h52q91 0 145 57t54 138zM956 1018l1 -756q0 -14 -9.5 -24t-23.5 -10h-216q-14 0 -23.5 10t-9.5 24v62h-291l-55 -81q-10 -15 -28 -15h-267q-21 0 -30.5 18t3.5 35l556 757q9 14 27 14h332q14 0 24 -10
+t10 -24zM1783 641q0 -193 -125.5 -303t-324.5 -110h-270q-14 0 -24 10t-10 24v756q0 14 10 24t24 10h268q200 0 326 -109t126 -302zM1939 640q0 -11 -0.5 -29t-8 -71.5t-21.5 -102t-44.5 -108t-73.5 -102.5h-51q38 45 66.5 104.5t41.5 112t21 98t9 72.5l1 27q0 8 -0.5 22.5
+t-7.5 60t-20 91.5t-41 111.5t-66 124.5h43q41 -47 72 -107t45.5 -111.5t23 -96t10.5 -70.5zM2123 640q0 -11 -0.5 -29t-8 -71.5t-21.5 -102t-45 -108t-74 -102.5h-51q38 45 66.5 104.5t41.5 112t21 98t9 72.5l1 27q0 8 -0.5 22.5t-7.5 60t-19.5 91.5t-40.5 111.5t-66 124.5
+h43q41 -47 72 -107t45.5 -111.5t23 -96t10.5 -70.5zM2304 640q0 -11 -0.5 -29t-8 -71.5t-21.5 -102t-44.5 -108t-73.5 -102.5h-51q38 45 66 104.5t41 112t21 98t9 72.5l1 27q0 8 -0.5 22.5t-7.5 60t-19.5 91.5t-40.5 111.5t-66 124.5h43q41 -47 72 -107t45.5 -111.5t23 -96
+t9.5 -70.5z" />
+ <glyph glyph-name="uniF2A0" unicode="" horiz-adv-x="1408"
+d="M617 -153q0 11 -13 58t-31 107t-20 69q-1 4 -5 26.5t-8.5 36t-13.5 21.5q-15 14 -51 14q-23 0 -70 -5.5t-71 -5.5q-34 0 -47 11q-6 5 -11 15.5t-7.5 20t-6.5 24t-5 18.5q-37 128 -37 255t37 255q1 4 5 18.5t6.5 24t7.5 20t11 15.5q13 11 47 11q24 0 71 -5.5t70 -5.5
+q36 0 51 14q9 8 13.5 21.5t8.5 36t5 26.5q2 9 20 69t31 107t13 58q0 22 -43.5 52.5t-75.5 42.5q-20 8 -45 8q-34 0 -98 -18q-57 -17 -96.5 -40.5t-71 -66t-46 -70t-45.5 -94.5q-6 -12 -9 -19q-49 -107 -68 -216t-19 -244t19 -244t68 -216q56 -122 83 -161q63 -91 179 -127
+l6 -2q64 -18 98 -18q25 0 45 8q32 12 75.5 42.5t43.5 52.5zM776 760q-26 0 -45 19t-19 45.5t19 45.5q37 37 37 90q0 52 -37 91q-19 19 -19 45t19 45t45 19t45 -19q75 -75 75 -181t-75 -181q-21 -19 -45 -19zM957 579q-27 0 -45 19q-19 19 -19 45t19 45q112 114 112 272
+t-112 272q-19 19 -19 45t19 45t45 19t45 -19q150 -150 150 -362t-150 -362q-18 -19 -45 -19zM1138 398q-27 0 -45 19q-19 19 -19 45t19 45q90 91 138.5 208t48.5 245t-48.5 245t-138.5 208q-19 19 -19 45t19 45t45 19t45 -19q109 -109 167 -249t58 -294t-58 -294t-167 -249
+q-18 -19 -45 -19z" />
+ <glyph glyph-name="uniF2A1" unicode="" horiz-adv-x="2176"
+d="M192 352q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM704 352q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM704 864q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1472 352
+q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1984 352q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1472 864q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1984 864
+q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1984 1376q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 192q0 -80 -56 -136
+t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 1216q0 -80 -56 -136t-136 -56
+t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 1216q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM2176 192q0 -80 -56 -136t-136 -56t-136 56
+t-56 136t56 136t136 56t136 -56t56 -136zM1664 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM2176 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 1216q0 -80 -56 -136t-136 -56t-136 56t-56 136
+t56 136t136 56t136 -56t56 -136zM2176 1216q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136z" />
+ <glyph glyph-name="uniF2A2" unicode="" horiz-adv-x="1792"
+d="M128 -192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM320 0q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM365 365l256 -256l-90 -90l-256 256zM704 384q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45z
+M1411 704q0 -59 -11.5 -108.5t-37.5 -93.5t-44 -67.5t-53 -64.5q-31 -35 -45.5 -54t-33.5 -50t-26.5 -64t-7.5 -74q0 -159 -112.5 -271.5t-271.5 -112.5q-26 0 -45 19t-19 45t19 45t45 19q106 0 181 75t75 181q0 57 11.5 105.5t37 91t43.5 66.5t52 63q40 46 59.5 72
+t37.5 74.5t18 103.5q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5q0 -26 -19 -45t-45 -19t-45 19t-19 45q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5zM896 576q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45
+t45 19t45 -19t19 -45zM1184 704q0 -26 -19 -45t-45 -19t-45 19t-19 45q0 93 -65.5 158.5t-158.5 65.5q-92 0 -158 -65.5t-66 -158.5q0 -26 -19 -45t-45 -19t-45 19t-19 45q0 146 103 249t249 103t249 -103t103 -249zM1578 993q10 -25 -1 -49t-36 -34q-9 -4 -23 -4
+q-19 0 -35.5 11t-23.5 30q-68 178 -224 295q-21 16 -25 42t12 47q17 21 43 25t47 -12q183 -137 266 -351zM1788 1074q9 -25 -1.5 -49t-35.5 -34q-11 -4 -23 -4q-44 0 -60 41q-92 238 -297 393q-22 16 -25.5 42t12.5 47q16 22 42 25.5t47 -12.5q235 -175 341 -449z" />
+ <glyph glyph-name="uniF2A3" unicode="" horiz-adv-x="2304"
+d="M1032 576q-59 2 -84 55q-17 34 -48 53.5t-68 19.5q-53 0 -90.5 -37.5t-37.5 -90.5q0 -56 36 -89l10 -8q34 -31 82 -31q37 0 68 19.5t48 53.5q25 53 84 55zM1600 704q0 56 -36 89l-10 8q-34 31 -82 31q-37 0 -68 -19.5t-48 -53.5q-25 -53 -84 -55q59 -2 84 -55
+q17 -34 48 -53.5t68 -19.5q53 0 90.5 37.5t37.5 90.5zM1174 925q-17 -35 -55 -48t-73 4q-62 31 -134 31q-51 0 -99 -17q3 0 9.5 0.5t9.5 0.5q92 0 170.5 -50t118.5 -133q17 -36 3.5 -73.5t-49.5 -54.5q-18 -9 -39 -9q21 0 39 -9q36 -17 49.5 -54.5t-3.5 -73.5
+q-40 -83 -118.5 -133t-170.5 -50h-6q-16 2 -44 4l-290 27l-239 -120q-14 -7 -29 -7q-40 0 -57 35l-160 320q-11 23 -4 47.5t29 37.5l209 119l148 267q17 155 91.5 291.5t195.5 236.5q31 25 70.5 21.5t64.5 -34.5t21.5 -70t-34.5 -65q-70 -59 -117 -128q123 84 267 101
+q40 5 71.5 -19t35.5 -64q5 -40 -19 -71.5t-64 -35.5q-84 -10 -159 -55q46 10 99 10q115 0 218 -50q36 -18 49 -55.5t-5 -73.5zM2137 1085l160 -320q11 -23 4 -47.5t-29 -37.5l-209 -119l-148 -267q-17 -155 -91.5 -291.5t-195.5 -236.5q-26 -22 -61 -22q-45 0 -74 35
+q-25 31 -21.5 70t34.5 65q70 59 117 128q-123 -84 -267 -101q-4 -1 -12 -1q-36 0 -63.5 24t-31.5 60q-5 40 19 71.5t64 35.5q84 10 159 55q-46 -10 -99 -10q-115 0 -218 50q-36 18 -49 55.5t5 73.5q17 35 55 48t73 -4q62 -31 134 -31q51 0 99 17q-3 0 -9.5 -0.5t-9.5 -0.5
+q-92 0 -170.5 50t-118.5 133q-17 36 -3.5 73.5t49.5 54.5q18 9 39 9q-21 0 -39 9q-36 17 -49.5 54.5t3.5 73.5q40 83 118.5 133t170.5 50h6h1q14 -2 42 -4l291 -27l239 120q14 7 29 7q40 0 57 -35z" />
+ <glyph glyph-name="uniF2A4" unicode="" horiz-adv-x="1792"
+d="M1056 704q0 -26 19 -45t45 -19t45 19t19 45q0 146 -103 249t-249 103t-249 -103t-103 -249q0 -26 19 -45t45 -19t45 19t19 45q0 93 66 158.5t158 65.5t158 -65.5t66 -158.5zM835 1280q-117 0 -223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5q0 -26 19 -45t45 -19t45 19
+t19 45q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -55 -18 -103.5t-37.5 -74.5t-59.5 -72q-34 -39 -52 -63t-43.5 -66.5t-37 -91t-11.5 -105.5q0 -106 -75 -181t-181 -75q-26 0 -45 -19t-19 -45t19 -45t45 -19q159 0 271.5 112.5t112.5 271.5q0 41 7.5 74
+t26.5 64t33.5 50t45.5 54q35 41 53 64.5t44 67.5t37.5 93.5t11.5 108.5q0 117 -45.5 223.5t-123 184t-184 123t-223.5 45.5zM591 561l226 -226l-579 -579q-12 -12 -29 -12t-29 12l-168 168q-12 12 -12 29t12 29zM1612 1524l168 -168q12 -12 12 -29t-12 -30l-233 -233
+l-26 -25l-71 -71q-66 153 -195 258l91 91l207 207q13 12 30 12t29 -12z" />
+ <glyph glyph-name="uniF2A5" unicode=""
+d="M866 1021q0 -27 -13 -94q-11 -50 -31.5 -150t-30.5 -150q-2 -11 -4.5 -12.5t-13.5 -2.5q-20 -2 -31 -2q-58 0 -84 49.5t-26 113.5q0 88 35 174t103 124q28 14 51 14q28 0 36.5 -16.5t8.5 -47.5zM1352 597q0 14 -39 75.5t-52 66.5q-21 8 -34 8q-91 0 -226 -77l-2 2
+q3 22 27.5 135t24.5 178q0 233 -242 233q-24 0 -68 -6q-94 -17 -168.5 -89.5t-111.5 -166.5t-37 -189q0 -146 80.5 -225t227.5 -79q25 0 25 -3t-1 -5q-4 -34 -26 -117q-14 -52 -51.5 -101t-82.5 -49q-42 0 -42 47q0 24 10.5 47.5t25 39.5t29.5 28.5t26 20t11 8.5q0 3 -7 10
+q-24 22 -58.5 36.5t-65.5 14.5q-35 0 -63.5 -34t-41 -75t-12.5 -75q0 -88 51.5 -142t138.5 -54q82 0 155 53t117.5 126t65.5 153q6 22 15.5 66.5t14.5 66.5q3 12 14 18q118 60 227 60q48 0 127 -18q1 -1 4 -1q5 0 9.5 4.5t4.5 8.5zM1536 1120v-960q0 -119 -84.5 -203.5
+t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="uniF2A6" unicode="" horiz-adv-x="1535"
+d="M744 1231q0 24 -2 38.5t-8.5 30t-21 23t-37.5 7.5q-39 0 -78 -23q-105 -58 -159 -190.5t-54 -269.5q0 -44 8.5 -85.5t26.5 -80.5t52.5 -62.5t81.5 -23.5q4 0 18 -0.5t20 0t16 3t15 8.5t7 16q16 77 48 231.5t48 231.5q19 91 19 146zM1498 575q0 -7 -7.5 -13.5t-15.5 -6.5
+l-6 1q-22 3 -62 11t-72 12.5t-63 4.5q-167 0 -351 -93q-15 -8 -21 -27q-10 -36 -24.5 -105.5t-22.5 -100.5q-23 -91 -70 -179.5t-112.5 -164.5t-154.5 -123t-185 -47q-135 0 -214.5 83.5t-79.5 219.5q0 53 19.5 117t63 116.5t97.5 52.5q38 0 120 -33.5t83 -61.5
+q0 -1 -16.5 -12.5t-39.5 -31t-46 -44.5t-39 -61t-16 -74q0 -33 16.5 -53t48.5 -20q45 0 85 31.5t66.5 78t48 105.5t32.5 107t16 90v9q0 2 -3.5 3.5t-8.5 1.5h-10t-10 -0.5t-6 -0.5q-227 0 -352 122.5t-125 348.5q0 108 34.5 221t96 210t156 167.5t204.5 89.5q52 9 106 9
+q374 0 374 -360q0 -98 -38 -273t-43 -211l3 -3q101 57 182.5 88t167.5 31q22 0 53 -13q19 -7 80 -102.5t61 -116.5z" />
+ <glyph glyph-name="uniF2A7" unicode="" horiz-adv-x="1664"
+d="M831 863q32 0 59 -18l222 -148q61 -40 110 -97l146 -170q40 -46 29 -106l-72 -413q-6 -32 -29.5 -53.5t-55.5 -25.5l-527 -56l-352 -32h-9q-39 0 -67.5 28t-28.5 68q0 37 27 64t65 32l260 32h-448q-41 0 -69.5 30t-26.5 71q2 39 32 65t69 26l442 1l-521 64q-41 5 -66 37
+t-19 73q6 35 34.5 57.5t65.5 22.5h10l481 -60l-351 94q-38 10 -62 41.5t-18 68.5q6 36 33 58.5t62 22.5q6 0 20 -2l448 -96l217 -37q1 0 3 -0.5t3 -0.5q23 0 30.5 23t-12.5 36l-186 125q-35 23 -42 63.5t18 73.5q27 38 76 38zM761 661l186 -125l-218 37l-5 2l-36 38
+l-238 262q-1 1 -2.5 3.5t-2.5 3.5q-24 31 -18.5 70t37.5 64q31 23 68 17.5t64 -33.5l142 -147q-2 -1 -5 -3.5t-4 -4.5q-32 -45 -23 -99t55 -85zM1648 1115l15 -266q4 -73 -11 -147l-48 -219q-12 -59 -67 -87l-106 -54q2 62 -39 109l-146 170q-53 61 -117 103l-222 148
+q-34 23 -76 23q-51 0 -88 -37l-235 312q-25 33 -18 73.5t41 63.5q33 22 71.5 14t62.5 -40l266 -352l-262 455q-21 35 -10.5 75t47.5 59q35 18 72.5 6t57.5 -46l241 -420l-136 337q-15 35 -4.5 74t44.5 56q37 19 76 6t56 -51l193 -415l101 -196q8 -15 23 -17.5t27 7.5t11 26
+l-12 224q-2 41 26 71t69 31q39 0 67 -28.5t30 -67.5z" />
+ <glyph glyph-name="uniF2A8" unicode="" horiz-adv-x="1792"
+d="M335 180q-2 0 -6 2q-86 57 -168.5 145t-139.5 180q-21 30 -21 69q0 9 2 19t4 18t7 18t8.5 16t10.5 17t10 15t12 15.5t11 14.5q184 251 452 365q-110 198 -110 211q0 19 17 29q116 64 128 64q18 0 28 -16l124 -229q92 19 192 19q266 0 497.5 -137.5t378.5 -369.5
+q20 -31 20 -69t-20 -69q-91 -142 -218.5 -253.5t-278.5 -175.5q110 -198 110 -211q0 -20 -17 -29q-116 -64 -127 -64q-19 0 -29 16l-124 229l-64 119l-444 820l7 7q-58 -24 -99 -47q3 -5 127 -234t243 -449t119 -223q0 -7 -9 -9q-13 -3 -72 -3q-57 0 -60 7l-456 841
+q-39 -28 -82 -68q24 -43 214 -393.5t190 -354.5q0 -10 -11 -10q-14 0 -82.5 22t-72.5 28l-106 197l-224 413q-44 -53 -78 -106q2 -3 18 -25t23 -34l176 -327q0 -10 -10 -10zM1165 282l49 -91q273 111 450 385q-180 277 -459 389q67 -64 103 -148.5t36 -176.5
+q0 -106 -47 -200.5t-132 -157.5zM848 896q0 -20 14 -34t34 -14q86 0 147 -61t61 -147q0 -20 14 -34t34 -14t34 14t14 34q0 126 -89 215t-215 89q-20 0 -34 -14t-14 -34zM1214 961l-9 4l7 -7z" />
+ <glyph glyph-name="uniF2A9" unicode="" horiz-adv-x="1280"
+d="M1050 430q0 -215 -147 -374q-148 -161 -378 -161q-232 0 -378 161q-147 159 -147 374q0 147 68 270.5t189 196.5t268 73q96 0 182 -31q-32 -62 -39 -126q-66 28 -143 28q-167 0 -280.5 -123t-113.5 -291q0 -170 112.5 -288.5t281.5 -118.5t281 118.5t112 288.5
+q0 89 -32 166q66 13 123 49q41 -98 41 -212zM846 619q0 -192 -79.5 -345t-238.5 -253l-14 -1q-29 0 -62 5q83 32 146.5 102.5t99.5 154.5t58.5 189t30 192.5t7.5 178.5q0 69 -3 103q55 -160 55 -326zM791 947v-2q-73 214 -206 440q88 -59 142.5 -186.5t63.5 -251.5z
+M1035 744q-83 0 -160 75q218 120 290 247q19 37 21 56q-42 -94 -139.5 -166.5t-204.5 -97.5q-35 54 -35 113q0 37 17 79t43 68q46 44 157 74q59 16 106 58.5t74 100.5q74 -105 74 -253q0 -109 -24 -170q-32 -77 -88.5 -130.5t-130.5 -53.5z" />
+ <glyph glyph-name="uniF2AA" unicode=""
+d="M1050 495q0 78 -28 147q-41 -25 -85 -34q22 -50 22 -114q0 -117 -77 -198.5t-193 -81.5t-193.5 81.5t-77.5 198.5q0 115 78 199.5t193 84.5q53 0 98 -19q4 43 27 87q-60 21 -125 21q-154 0 -257.5 -108.5t-103.5 -263.5t103.5 -261t257.5 -106t257.5 106.5t103.5 260.5z
+M872 850q2 -24 2 -71q0 -63 -5 -123t-20.5 -132.5t-40.5 -130t-68.5 -106t-100.5 -70.5q21 -3 42 -3h10q219 139 219 411q0 116 -38 225zM872 850q-4 80 -44 171.5t-98 130.5q92 -156 142 -302zM1207 955q0 102 -51 174q-41 -86 -124 -109q-69 -19 -109 -53.5t-40 -99.5
+q0 -40 24 -77q74 17 140.5 67t95.5 115q-4 -52 -74.5 -111.5t-138.5 -97.5q52 -52 110 -52q51 0 90 37t60 90q17 42 17 117zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5
+t84.5 -203.5z" />
+ <glyph glyph-name="uniF2AB" unicode=""
+d="M1279 388q0 22 -22 27q-67 15 -118 59t-80 108q-7 19 -7 25q0 15 19.5 26t43 17t43 20.5t19.5 36.5q0 19 -18.5 31.5t-38.5 12.5q-12 0 -32 -8t-31 -8q-4 0 -12 2q5 95 5 114q0 79 -17 114q-36 78 -103 121.5t-152 43.5q-199 0 -275 -165q-17 -35 -17 -114q0 -19 5 -114
+q-4 -2 -14 -2q-12 0 -32 7.5t-30 7.5q-21 0 -38.5 -12t-17.5 -32q0 -21 19.5 -35.5t43 -20.5t43 -17t19.5 -26q0 -6 -7 -25q-64 -138 -198 -167q-22 -5 -22 -27q0 -46 137 -68q2 -5 6 -26t11.5 -30.5t23.5 -9.5q12 0 37.5 4.5t39.5 4.5q35 0 67 -15t54 -32.5t57.5 -32.5
+t76.5 -15q43 0 79 15t57.5 32.5t53.5 32.5t67 15q14 0 39.5 -4t38.5 -4q16 0 23 10t11 30t6 25q137 22 137 68zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5
+t103 -385.5z" />
+ <glyph glyph-name="uniF2AC" unicode="" horiz-adv-x="1664"
+d="M848 1408q134 1 240.5 -68.5t163.5 -192.5q27 -58 27 -179q0 -47 -9 -191q14 -7 28 -7q18 0 51 13.5t51 13.5q29 0 56 -18t27 -46q0 -32 -31.5 -54t-69 -31.5t-69 -29t-31.5 -47.5q0 -15 12 -43q37 -82 102.5 -150t144.5 -101q28 -12 80 -23q28 -6 28 -35
+q0 -70 -219 -103q-7 -11 -11 -39t-14 -46.5t-33 -18.5q-20 0 -62 6.5t-64 6.5q-37 0 -62 -5q-32 -5 -63 -22.5t-58 -38t-58 -40.5t-76 -33.5t-99 -13.5q-52 0 -96.5 13.5t-75 33.5t-57.5 40.5t-58 38t-62 22.5q-26 5 -63 5q-24 0 -65.5 -7.5t-58.5 -7.5q-25 0 -35 18.5
+t-14 47.5t-11 40q-219 33 -219 103q0 29 28 35q52 11 80 23q78 32 144.5 101t102.5 150q12 28 12 43q0 28 -31.5 47.5t-69.5 29.5t-69.5 31.5t-31.5 52.5q0 27 26 45.5t55 18.5q15 0 48 -13t53 -13q18 0 32 7q-9 142 -9 190q0 122 27 180q64 137 172 198t264 63z" />
+ <glyph glyph-name="uniF2AD" unicode=""
+d="M1280 388q0 22 -22 27q-67 14 -118 58t-80 109q-7 14 -7 25q0 15 19.5 26t42.5 17t42.5 20.5t19.5 36.5q0 19 -18.5 31.5t-38.5 12.5q-11 0 -31 -8t-32 -8q-4 0 -12 2q5 63 5 115q0 78 -17 114q-36 78 -102.5 121.5t-152.5 43.5q-198 0 -275 -165q-18 -38 -18 -115
+q0 -38 6 -114q-10 -2 -15 -2q-11 0 -31.5 8t-30.5 8q-20 0 -37.5 -12.5t-17.5 -32.5q0 -21 19.5 -35.5t42.5 -20.5t42.5 -17t19.5 -26q0 -11 -7 -25q-64 -138 -198 -167q-22 -5 -22 -27q0 -47 138 -69q2 -5 6 -26t11 -30.5t23 -9.5q13 0 38.5 5t38.5 5q35 0 67.5 -15
+t54.5 -32.5t57.5 -32.5t76.5 -15q43 0 79 15t57.5 32.5t54 32.5t67.5 15q13 0 39 -4.5t39 -4.5q15 0 22.5 9.5t11.5 31t5 24.5q138 22 138 69zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960
+q119 0 203.5 -84.5t84.5 -203.5z" />
+ <glyph glyph-name="uniF2AE" unicode="" horiz-adv-x="2304"
+d="M2304 1536q-69 -46 -125 -92t-89 -81t-59.5 -71.5t-37.5 -57.5t-22 -44.5t-14 -29.5q-10 -18 -35.5 -136.5t-48.5 -164.5q-15 -29 -50 -60.5t-67.5 -50.5t-72.5 -41t-48 -28q-47 -31 -151 -231q-341 14 -630 -158q-92 -53 -303 -179q47 16 86 31t55 22l15 7
+q71 27 163 64.5t133.5 53.5t108 34.5t142.5 31.5q186 31 465 -7q1 0 10 -3q11 -6 14 -17t-3 -22l-194 -345q-15 -29 -47 -22q-128 24 -354 24q-146 0 -402 -44.5t-392 -46.5q-82 -1 -149 13t-107 37t-61 40t-33 34l-1 1v2q0 6 6 6q138 0 371 55q192 366 374.5 524t383.5 158
+q5 0 14.5 -0.5t38 -5t55 -12t61.5 -24.5t63 -39.5t54 -59t40 -82.5l102 177q2 4 21 42.5t44.5 86.5t61 109.5t84 133.5t100.5 137q66 82 128 141.5t121.5 96.5t92.5 53.5t88 39.5z" />
+ <glyph glyph-name="uniF2B0" unicode=""
+d="M1322 640q0 -45 -5 -76l-236 14l224 -78q-19 -73 -58 -141l-214 103l177 -158q-44 -61 -107 -108l-157 178l103 -215q-61 -37 -140 -59l-79 228l14 -240q-38 -6 -76 -6t-76 6l14 238l-78 -226q-74 19 -140 59l103 215l-157 -178q-59 43 -108 108l178 158l-214 -104
+q-39 69 -58 141l224 79l-237 -14q-5 42 -5 76q0 35 5 77l238 -14l-225 79q19 73 58 140l214 -104l-177 159q46 61 107 108l158 -178l-103 215q67 39 140 58l77 -224l-13 236q36 6 75 6q38 0 76 -6l-14 -237l78 225q74 -19 140 -59l-103 -214l158 178q61 -47 107 -108
+l-177 -159l213 104q37 -62 58 -141l-224 -78l237 14q5 -31 5 -77zM1352 640q0 160 -78.5 295.5t-213 214t-292.5 78.5q-119 0 -227 -46.5t-186.5 -125t-124.5 -187.5t-46 -229q0 -119 46 -228t124.5 -187.5t186.5 -125t227 -46.5q158 0 292.5 78.5t213 214t78.5 294.5z
+M1425 1023v-766l-657 -383l-657 383v766l657 383zM768 -183l708 412v823l-708 411l-708 -411v-823zM1536 1088v-896l-768 -448l-768 448v896l768 448z" />
+ <glyph glyph-name="uniF2B1" unicode="" horiz-adv-x="1664"
+d="M339 1318h691l-26 -72h-665q-110 0 -188.5 -79t-78.5 -189v-771q0 -95 60.5 -169.5t153.5 -93.5q23 -5 98 -5v-72h-45q-140 0 -239.5 100t-99.5 240v771q0 140 99.5 240t239.5 100zM1190 1536h247l-482 -1294q-23 -61 -40.5 -103.5t-45 -98t-54 -93.5t-64.5 -78.5
+t-79.5 -65t-95.5 -41t-116 -18.5v195q163 26 220 182q20 52 20 105q0 54 -20 106l-285 733h228l187 -585zM1664 978v-1111h-795q37 55 45 73h678v1038q0 85 -49.5 155t-129.5 99l25 67q101 -34 163.5 -123.5t62.5 -197.5z" />
+ <glyph glyph-name="uniF2B2" unicode="" horiz-adv-x="1792"
+d="M852 1227q0 -29 -17 -52.5t-45 -23.5t-45 23.5t-17 52.5t17 52.5t45 23.5t45 -23.5t17 -52.5zM688 -149v114q0 30 -20.5 51.5t-50.5 21.5t-50 -21.5t-20 -51.5v-114q0 -30 20.5 -52t49.5 -22q30 0 50.5 22t20.5 52zM860 -149v114q0 30 -20 51.5t-50 21.5t-50.5 -21.5
+t-20.5 -51.5v-114q0 -30 20.5 -52t50.5 -22q29 0 49.5 22t20.5 52zM1034 -149v114q0 30 -20.5 51.5t-50.5 21.5t-50.5 -21.5t-20.5 -51.5v-114q0 -30 20.5 -52t50.5 -22t50.5 22t20.5 52zM1208 -149v114q0 30 -20.5 51.5t-50.5 21.5t-50.5 -21.5t-20.5 -51.5v-114
+q0 -30 20.5 -52t50.5 -22t50.5 22t20.5 52zM1476 535q-84 -160 -232 -259.5t-323 -99.5q-123 0 -229.5 51.5t-178.5 137t-113 197.5t-41 232q0 88 21 174q-104 -175 -104 -390q0 -162 65 -312t185 -251q30 57 91 57q56 0 86 -50q32 50 87 50q56 0 86 -50q32 50 87 50t87 -50
+q30 50 86 50q28 0 52.5 -15.5t37.5 -40.5q112 94 177 231.5t73 287.5zM1326 564q0 75 -72 75q-17 0 -47 -6q-95 -19 -149 -19q-226 0 -226 243q0 86 30 204q-83 -127 -83 -275q0 -150 89 -260.5t235 -110.5q111 0 210 70q13 48 13 79zM884 1223q0 50 -32 89.5t-81 39.5
+t-81 -39.5t-32 -89.5q0 -51 31.5 -90.5t81.5 -39.5t81.5 39.5t31.5 90.5zM1513 884q0 96 -37.5 179t-113 137t-173.5 54q-77 0 -149 -35t-127 -94q-48 -159 -48 -268q0 -104 45.5 -157t147.5 -53q53 0 142 19q36 6 53 6q51 0 77.5 -28t26.5 -80q0 -26 -4 -46
+q75 68 117.5 165.5t42.5 200.5zM1792 667q0 -111 -33.5 -249.5t-93.5 -204.5q-58 -64 -195 -142.5t-228 -104.5l-4 -1v-114q0 -43 -29.5 -75t-72.5 -32q-56 0 -86 50q-32 -50 -87 -50t-87 50q-30 -50 -86 -50q-55 0 -87 50q-30 -50 -86 -50q-47 0 -75 33.5t-28 81.5
+q-90 -68 -198 -68q-118 0 -211 80q54 1 106 20q-113 31 -182 127q32 -7 71 -7q89 0 164 46q-192 192 -240 306q-24 56 -24 160q0 57 9 125.5t31.5 146.5t55 141t86.5 105t120 42q59 0 81 -52q19 29 42 54q2 3 12 13t13 16q10 15 23 38t25 42t28 39q87 111 211.5 177
+t260.5 66q35 0 62 -4q59 64 146 64q83 0 140 -57q5 -5 5 -12q0 -5 -6 -13.5t-12.5 -16t-16 -17l-10.5 -10.5q17 -6 36 -18t19 -24q0 -6 -16 -25q157 -138 197 -378q25 30 60 30q45 0 100 -49q90 -80 90 -279z" />
+ <glyph glyph-name="uniF2B3" unicode=""
+d="M917 631q0 33 -6 64h-362v-132h217q-12 -76 -74.5 -120.5t-142.5 -44.5q-99 0 -169 71.5t-70 170.5t70 170.5t169 71.5q93 0 153 -59l104 101q-108 100 -257 100q-160 0 -272 -112.5t-112 -271.5t112 -271.5t272 -112.5q165 0 266.5 105t101.5 270zM1262 585h109v110
+h-109v110h-110v-110h-110v-110h110v-110h110v110zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+ <glyph glyph-name="uniF2B4" unicode=""
+d="M1536 1024v-839q0 -48 -49 -62q-174 -52 -338 -52q-73 0 -215.5 29.5t-227.5 29.5q-164 0 -370 -48v-338h-160v1368q-63 25 -101 81t-38 124q0 91 64 155t155 64t155 -64t64 -155q0 -68 -38 -124t-101 -81v-68q190 44 343 44q99 0 198 -15q14 -2 111.5 -22.5t149.5 -20.5
+q77 0 165 18q11 2 80 21t89 19q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="uniF2B5" unicode="" horiz-adv-x="2304"
+d="M192 384q40 0 56 32t0 64t-56 32t-56 -32t0 -64t56 -32zM1665 442q-10 13 -38.5 50t-41.5 54t-38 49t-42.5 53t-40.5 47t-45 49l-125 -140q-83 -94 -208.5 -92t-205.5 98q-57 69 -56.5 158t58.5 157l177 206q-22 11 -51 16.5t-47.5 6t-56.5 -0.5t-49 -1q-92 0 -158 -66
+l-158 -158h-155v-544q5 0 21 0.5t22 0t19.5 -2t20.5 -4.5t17.5 -8.5t18.5 -13.5l297 -292q115 -111 227 -111q78 0 125 47q57 -20 112.5 8t72.5 85q74 -6 127 44q20 18 36 45.5t14 50.5q10 -10 43 -10q43 0 77 21t49.5 53t12 71.5t-30.5 73.5zM1824 384h96v512h-93l-157 180
+q-66 76 -169 76h-167q-89 0 -146 -67l-209 -243q-28 -33 -28 -75t27 -75q43 -51 110 -52t111 49l193 218q25 23 53.5 21.5t47 -27t8.5 -56.5q16 -19 56 -63t60 -68q29 -36 82.5 -105.5t64.5 -84.5q52 -66 60 -140zM2112 384q40 0 56 32t0 64t-56 32t-56 -32t0 -64t56 -32z
+M2304 960v-640q0 -26 -19 -45t-45 -19h-434q-27 -65 -82 -106.5t-125 -51.5q-33 -48 -80.5 -81.5t-102.5 -45.5q-42 -53 -104.5 -81.5t-128.5 -24.5q-60 -34 -126 -39.5t-127.5 14t-117 53.5t-103.5 81l-287 282h-358q-26 0 -45 19t-19 45v672q0 26 19 45t45 19h421
+q14 14 47 48t47.5 48t44 40t50.5 37.5t51 25.5t62 19.5t68 5.5h117q99 0 181 -56q82 56 181 56h167q35 0 67 -6t56.5 -14.5t51.5 -26.5t44.5 -31t43 -39.5t39 -42t41 -48t41.5 -48.5h355q26 0 45 -19t19 -45z" />
+ <glyph glyph-name="uniF2B6" unicode="" horiz-adv-x="1792"
+d="M1792 882v-978q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v978q0 15 11 24q8 7 39 34.5t41.5 36t45.5 37.5t70 55.5t96 73t143.5 107t192.5 140.5q5 4 52.5 40t71.5 52.5t64 35t69 18.5t69 -18.5t65 -35.5t71 -52t52 -40q110 -80 192.5 -140.5t143.5 -107
+t96 -73t70 -55.5t45.5 -37.5t41.5 -36t39 -34.5q11 -9 11 -24zM1228 297q263 191 345 252q11 8 12.5 20.5t-6.5 23.5l-38 52q-8 11 -21 12.5t-24 -6.5q-231 -169 -343 -250q-5 -3 -52 -39t-71.5 -52.5t-64.5 -35t-69 -18.5t-69 18.5t-64.5 35t-71.5 52.5t-52 39
+q-186 134 -343 250q-11 8 -24 6.5t-21 -12.5l-38 -52q-8 -11 -6.5 -23.5t12.5 -20.5q82 -61 345 -252q10 -8 50 -38t65 -47t64 -39.5t77.5 -33.5t75.5 -11t75.5 11t79 34.5t64.5 39.5t65 47.5t48 36.5z" />
+ <glyph glyph-name="uniF2B7" unicode="" horiz-adv-x="1792"
+d="M1474 623l39 -51q8 -11 6.5 -23.5t-11.5 -20.5q-43 -34 -126.5 -98.5t-146.5 -113t-67 -51.5q-39 -32 -60 -48t-60.5 -41t-76.5 -36.5t-74 -11.5h-1h-1q-37 0 -74 11.5t-76 36.5t-61 41.5t-60 47.5q-5 4 -65 50.5t-143.5 111t-122.5 94.5q-11 8 -12.5 20.5t6.5 23.5
+l37 52q8 11 21.5 13t24.5 -7q94 -73 306 -236q5 -4 43.5 -35t60.5 -46.5t56.5 -32.5t58.5 -17h1h1q24 0 58.5 17t56.5 32.5t60.5 46.5t43.5 35q258 198 313 242q11 8 24 6.5t21 -12.5zM1664 -96v928q-90 83 -159 139q-91 74 -389 304q-3 2 -43 35t-61 48t-56 32.5t-59 17.5
+h-1h-1q-24 0 -59 -17.5t-56 -32.5t-61 -48t-43 -35q-215 -166 -315.5 -245.5t-129.5 -104t-82 -74.5q-14 -12 -21 -19v-928q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 832v-928q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v928q0 56 41 94
+q123 114 350 290.5t233 181.5q36 30 59 47.5t61.5 42t76 36.5t74.5 12h1h1q37 0 74.5 -12t76 -36.5t61.5 -42t59 -47.5q43 -36 156 -122t226 -177t201 -173q41 -38 41 -94z" />
+ <glyph glyph-name="uniF2B8" unicode=""
+d="M330 1l202 -214l-34 236l-216 213zM556 -225l274 218l-11 245l-300 -215zM245 413l227 -213l-48 327l-245 204zM495 189l317 214l-14 324l-352 -200zM843 178l95 -80l-2 239l-103 79q0 -1 1 -8.5t0 -12t-5 -7.5l-78 -52l85 -70q7 -6 7 -88zM138 930l256 -200l-68 465
+l-279 173zM1173 267l15 234l-230 -164l2 -240zM417 722l373 194l-19 441l-423 -163zM1270 357l20 233l-226 142l-2 -105l144 -95q6 -4 4 -9l-7 -119zM1461 496l30 222l-179 -128l-20 -228zM1273 329l-71 49l-8 -117q0 -5 -4 -8l-234 -187q-7 -5 -14 0l-98 83l7 -161
+q0 -5 -4 -8l-293 -234q-4 -2 -6 -2q-8 2 -8 3l-228 242q-4 4 -59 277q-2 7 5 11l61 37q-94 86 -95 92l-72 351q-2 7 6 12l94 45q-133 100 -135 108l-96 466q-2 10 7 13l433 135q5 0 8 -1l317 -153q6 -4 6 -9l20 -463q0 -7 -6 -10l-118 -61l126 -85q5 -2 5 -8l5 -123l121 74
+q5 4 11 0l84 -56l3 110q0 6 5 9l206 126q6 3 11 0l245 -135q4 -4 5 -7t-6.5 -60t-17.5 -124.5t-10 -70.5q0 -5 -4 -7l-191 -153q-6 -5 -13 0z" />
+ <glyph glyph-name="uniF2B9" unicode="" horiz-adv-x="1664"
+d="M1201 298q0 57 -5.5 107t-21 100.5t-39.5 86t-64 58t-91 22.5q-6 -4 -33.5 -20.5t-42.5 -24.5t-40.5 -20t-49 -17t-46.5 -5t-46.5 5t-49 17t-40.5 20t-42.5 24.5t-33.5 20.5q-51 0 -91 -22.5t-64 -58t-39.5 -86t-21 -100.5t-5.5 -107q0 -73 42 -121.5t103 -48.5h576
+q61 0 103 48.5t42 121.5zM1028 892q0 108 -76.5 184t-183.5 76t-183.5 -76t-76.5 -184q0 -107 76.5 -183t183.5 -76t183.5 76t76.5 183zM1664 352v-192q0 -14 -9 -23t-23 -9h-96v-224q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v1472q0 66 47 113t113 47h1216
+q66 0 113 -47t47 -113v-224h96q14 0 23 -9t9 -23v-192q0 -14 -9 -23t-23 -9h-96v-128h96q14 0 23 -9t9 -23v-192q0 -14 -9 -23t-23 -9h-96v-128h96q14 0 23 -9t9 -23z" />
+ <glyph glyph-name="uniF2BA" unicode="" horiz-adv-x="1664"
+d="M1028 892q0 -107 -76.5 -183t-183.5 -76t-183.5 76t-76.5 183q0 108 76.5 184t183.5 76t183.5 -76t76.5 -184zM980 672q46 0 82.5 -17t60 -47.5t39.5 -67t24 -81t11.5 -82.5t3.5 -79q0 -67 -39.5 -118.5t-105.5 -51.5h-576q-66 0 -105.5 51.5t-39.5 118.5q0 48 4.5 93.5
+t18.5 98.5t36.5 91.5t63 64.5t93.5 26h5q7 -4 32 -19.5t35.5 -21t33 -17t37 -16t35 -9t39.5 -4.5t39.5 4.5t35 9t37 16t33 17t35.5 21t32 19.5zM1664 928q0 -13 -9.5 -22.5t-22.5 -9.5h-96v-128h96q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-96v-128h96
+q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-96v-224q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v1472q0 66 47 113t113 47h1216q66 0 113 -47t47 -113v-224h96q13 0 22.5 -9.5t9.5 -22.5v-192zM1408 -96v1472q0 13 -9.5 22.5t-22.5 9.5h-1216
+q-13 0 -22.5 -9.5t-9.5 -22.5v-1472q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5z" />
+ <glyph glyph-name="uniF2BB" unicode="" horiz-adv-x="2048"
+d="M1024 405q0 64 -9 117.5t-29.5 103t-60.5 78t-97 28.5q-6 -4 -30 -18t-37.5 -21.5t-35.5 -17.5t-43 -14.5t-42 -4.5t-42 4.5t-43 14.5t-35.5 17.5t-37.5 21.5t-30 18q-57 0 -97 -28.5t-60.5 -78t-29.5 -103t-9 -117.5t37 -106.5t91 -42.5h512q54 0 91 42.5t37 106.5z
+M867 925q0 94 -66.5 160.5t-160.5 66.5t-160.5 -66.5t-66.5 -160.5t66.5 -160.5t160.5 -66.5t160.5 66.5t66.5 160.5zM1792 416v64q0 14 -9 23t-23 9h-576q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h576q14 0 23 9t9 23zM1792 676v56q0 15 -10.5 25.5t-25.5 10.5h-568
+q-15 0 -25.5 -10.5t-10.5 -25.5v-56q0 -15 10.5 -25.5t25.5 -10.5h568q15 0 25.5 10.5t10.5 25.5zM1792 928v64q0 14 -9 23t-23 9h-576q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h576q14 0 23 9t9 23zM2048 1248v-1216q0 -66 -47 -113t-113 -47h-352v96q0 14 -9 23t-23 9
+h-64q-14 0 -23 -9t-9 -23v-96h-768v96q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-96h-352q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1728q66 0 113 -47t47 -113z" />
+ <glyph glyph-name="uniF2BC" unicode="" horiz-adv-x="2048"
+d="M1024 405q0 -64 -37 -106.5t-91 -42.5h-512q-54 0 -91 42.5t-37 106.5t9 117.5t29.5 103t60.5 78t97 28.5q6 -4 30 -18t37.5 -21.5t35.5 -17.5t43 -14.5t42 -4.5t42 4.5t43 14.5t35.5 17.5t37.5 21.5t30 18q57 0 97 -28.5t60.5 -78t29.5 -103t9 -117.5zM867 925
+q0 -94 -66.5 -160.5t-160.5 -66.5t-160.5 66.5t-66.5 160.5t66.5 160.5t160.5 66.5t160.5 -66.5t66.5 -160.5zM1792 480v-64q0 -14 -9 -23t-23 -9h-576q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h576q14 0 23 -9t9 -23zM1792 732v-56q0 -15 -10.5 -25.5t-25.5 -10.5h-568
+q-15 0 -25.5 10.5t-10.5 25.5v56q0 15 10.5 25.5t25.5 10.5h568q15 0 25.5 -10.5t10.5 -25.5zM1792 992v-64q0 -14 -9 -23t-23 -9h-576q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h576q14 0 23 -9t9 -23zM1920 32v1216q0 13 -9.5 22.5t-22.5 9.5h-1728q-13 0 -22.5 -9.5
+t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h352v96q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-96h768v96q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-96h352q13 0 22.5 9.5t9.5 22.5zM2048 1248v-1216q0 -66 -47 -113t-113 -47h-1728q-66 0 -113 47t-47 113v1216q0 66 47 113
+t113 47h1728q66 0 113 -47t47 -113z" />
+ <glyph glyph-name="uniF2BD" unicode="" horiz-adv-x="1792"
+d="M1523 197q-22 155 -87.5 257.5t-184.5 118.5q-67 -74 -159.5 -115.5t-195.5 -41.5t-195.5 41.5t-159.5 115.5q-119 -16 -184.5 -118.5t-87.5 -257.5q106 -150 271 -237.5t356 -87.5t356 87.5t271 237.5zM1280 896q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5
+t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM1792 640q0 -182 -71 -347.5t-190.5 -286t-285.5 -191.5t-349 -71q-182 0 -348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+ <glyph glyph-name="uniF2BE" unicode="" horiz-adv-x="1792"
+d="M896 1536q182 0 348 -71t286 -191t191 -286t71 -348q0 -181 -70.5 -347t-190.5 -286t-286 -191.5t-349 -71.5t-349 71t-285.5 191.5t-190.5 286t-71 347.5t71 348t191 286t286 191t348 71zM1515 185q149 205 149 455q0 156 -61 298t-164 245t-245 164t-298 61t-298 -61
+t-245 -164t-164 -245t-61 -298q0 -250 149 -455q66 327 306 327q131 -128 313 -128t313 128q240 0 306 -327zM1280 832q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5z" />
+ <glyph glyph-name="uniF2C0" unicode=""
+d="M1201 752q47 -14 89.5 -38t89 -73t79.5 -115.5t55 -172t22 -236.5q0 -154 -100 -263.5t-241 -109.5h-854q-141 0 -241 109.5t-100 263.5q0 131 22 236.5t55 172t79.5 115.5t89 73t89.5 38q-79 125 -79 272q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5
+t198.5 -40.5t163.5 -109.5t109.5 -163.5t40.5 -198.5q0 -147 -79 -272zM768 1408q-159 0 -271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5t-112.5 271.5t-271.5 112.5zM1195 -128q88 0 150.5 71.5t62.5 173.5q0 239 -78.5 377t-225.5 145
+q-145 -127 -336 -127t-336 127q-147 -7 -225.5 -145t-78.5 -377q0 -102 62.5 -173.5t150.5 -71.5h854z" />
+ <glyph glyph-name="uniF2C1" unicode="" horiz-adv-x="1280"
+d="M1024 278q0 -64 -37 -107t-91 -43h-512q-54 0 -91 43t-37 107t9 118t29.5 104t61 78.5t96.5 28.5q80 -75 188 -75t188 75q56 0 96.5 -28.5t61 -78.5t29.5 -104t9 -118zM870 797q0 -94 -67.5 -160.5t-162.5 -66.5t-162.5 66.5t-67.5 160.5t67.5 160.5t162.5 66.5
+t162.5 -66.5t67.5 -160.5zM1152 -96v1376h-1024v-1376q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1280 1376v-1472q0 -66 -47 -113t-113 -47h-960q-66 0 -113 47t-47 113v1472q0 66 47 113t113 47h352v-96q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v96h352
+q66 0 113 -47t47 -113z" />
+ <glyph glyph-name="uniF2C2" unicode="" horiz-adv-x="2048"
+d="M896 324q0 54 -7.5 100.5t-24.5 90t-51 68.5t-81 25q-64 -64 -156 -64t-156 64q-47 0 -81 -25t-51 -68.5t-24.5 -90t-7.5 -100.5q0 -55 31.5 -93.5t75.5 -38.5h426q44 0 75.5 38.5t31.5 93.5zM768 768q0 80 -56 136t-136 56t-136 -56t-56 -136t56 -136t136 -56t136 56
+t56 136zM1792 288v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1408 544v64q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1792 544v64q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23
+v-64q0 -14 9 -23t23 -9h192q14 0 23 9t9 23zM1792 800v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM128 1152h1792v96q0 14 -9 23t-23 9h-1728q-14 0 -23 -9t-9 -23v-96zM2048 1248v-1216q0 -66 -47 -113t-113 -47h-1728
+q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1728q66 0 113 -47t47 -113z" />
+ <glyph glyph-name="uniF2C3" unicode="" horiz-adv-x="2048"
+d="M896 324q0 -55 -31.5 -93.5t-75.5 -38.5h-426q-44 0 -75.5 38.5t-31.5 93.5q0 54 7.5 100.5t24.5 90t51 68.5t81 25q64 -64 156 -64t156 64q47 0 81 -25t51 -68.5t24.5 -90t7.5 -100.5zM768 768q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136z
+M1792 352v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM1408 608v-64q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h320q14 0 23 -9t9 -23zM1792 608v-64q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v64
+q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 864v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM1920 32v1120h-1792v-1120q0 -13 9.5 -22.5t22.5 -9.5h1728q13 0 22.5 9.5t9.5 22.5zM2048 1248v-1216q0 -66 -47 -113t-113 -47
+h-1728q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1728q66 0 113 -47t47 -113z" />
+ <glyph glyph-name="uniF2C4" unicode="" horiz-adv-x="1792"
+d="M1255 749q0 318 -105 474.5t-330 156.5q-222 0 -326 -157t-104 -474q0 -316 104 -471.5t326 -155.5q74 0 131 17q-22 43 -39 73t-44 65t-53.5 56.5t-63 36t-77.5 14.5q-46 0 -79 -16l-49 97q105 91 276 91q132 0 215.5 -54t150.5 -155q67 149 67 402zM1645 117h117
+q3 -27 -2 -67t-26.5 -95t-58 -100.5t-107 -78t-162.5 -32.5q-71 0 -130.5 19t-105.5 56t-79 78t-66 96q-97 -27 -205 -27q-150 0 -292.5 58t-253 158.5t-178 249t-67.5 317.5q0 170 67.5 319.5t178.5 250.5t253.5 159t291.5 58q121 0 238.5 -36t217 -106t176 -164.5
+t119.5 -219t43 -261.5q0 -190 -80.5 -347.5t-218.5 -264.5q47 -70 93.5 -106.5t104.5 -36.5q61 0 94 37.5t38 85.5z" />
+ <glyph glyph-name="uniF2C5" unicode="" horiz-adv-x="2304"
+d="M453 -101q0 -21 -16 -37.5t-37 -16.5q-1 0 -13 3q-63 15 -162 140q-225 284 -225 676q0 341 213 614q39 51 95 103.5t94 52.5q19 0 35 -13.5t16 -32.5q0 -27 -63 -90q-98 -102 -147 -184q-119 -199 -119 -449q0 -281 123 -491q50 -85 136 -173q2 -3 14.5 -16t19.5 -21
+t17 -20.5t14.5 -23.5t4.5 -21zM1796 33q0 -29 -17.5 -48.5t-46.5 -19.5h-1081q-26 0 -45 19t-19 45q0 29 17.5 48.5t46.5 19.5h1081q26 0 45 -19t19 -45zM1581 644q0 -134 -67 -233q-25 -38 -69.5 -78.5t-83.5 -60.5q-16 -10 -27 -10q-7 0 -15 6t-8 12q0 9 19 30t42 46
+t42 67.5t19 88.5q0 76 -35 130q-29 42 -46 42q-3 0 -3 -5q0 -12 7.5 -35.5t7.5 -36.5q0 -22 -21.5 -35t-44.5 -13q-66 0 -66 76q0 15 1.5 44t1.5 44q0 25 -10 46q-13 25 -42 53.5t-51 28.5q-5 0 -7 -0.5t-3.5 -2.5t-1.5 -6q0 -2 16 -26t16 -54q0 -37 -19 -68t-46 -54
+t-53.5 -46t-45.5 -54t-19 -68q0 -98 42 -160q29 -43 79 -63q16 -5 17 -10q1 -2 1 -5q0 -16 -18 -16q-6 0 -33 11q-119 43 -195 139.5t-76 218.5q0 55 24.5 115.5t60 115t70.5 108.5t59.5 113.5t24.5 111.5q0 53 -25 94q-29 48 -56 64q-19 9 -19 21q0 20 41 20q50 0 110 -29
+q41 -19 71 -44.5t49.5 -51t33.5 -62.5t22 -69t16 -80q0 -1 3 -17.5t4.5 -25t5.5 -25t9 -27t11 -21.5t14.5 -16.5t18.5 -5.5q23 0 37 14t14 37q0 25 -20 67t-20 52t10 10q27 0 93 -70q72 -76 102.5 -156t30.5 -186zM2304 615q0 -274 -138 -503q-19 -32 -48 -72t-68 -86.5
+t-81 -77t-74 -30.5q-16 0 -31 15.5t-15 31.5q0 15 29 50.5t68.5 77t48.5 52.5q183 230 183 531q0 131 -20.5 235t-72.5 211q-58 119 -163 228q-2 3 -13 13.5t-16.5 16.5t-15 17.5t-15 20t-9.5 18.5t-4 19q0 19 16 35.5t35 16.5q70 0 196 -169q98 -131 146 -273t60 -314
+q2 -42 2 -64z" />
+ <glyph glyph-name="uniF2C6" unicode="" horiz-adv-x="1792"
+d="M1189 229l147 693q9 44 -10.5 63t-51.5 7l-864 -333q-29 -11 -39.5 -25t-2.5 -26.5t32 -19.5l221 -69l513 323q21 14 32 6q7 -5 -4 -15l-415 -375v0v0l-16 -228q23 0 45 22l108 104l224 -165q64 -36 81 38zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71
+t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+ <glyph glyph-name="uniF2C7" unicode="" horiz-adv-x="1024"
+d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 60 35 110t93 71v907h128v-907q58 -21 93 -71t35 -110zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5
+t93.5 226.5zM896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192
+v128h192z" />
+ <glyph glyph-name="uniF2C8" unicode="" horiz-adv-x="1024"
+d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 60 35 110t93 71v651h128v-651q58 -21 93 -71t35 -110zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5
+t93.5 226.5zM896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192
+v128h192z" />
+ <glyph glyph-name="uniF2C9" unicode="" horiz-adv-x="1024"
+d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 60 35 110t93 71v395h128v-395q58 -21 93 -71t35 -110zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5
+t93.5 226.5zM896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192
+v128h192z" />
+ <glyph glyph-name="uniF2CA" unicode="" horiz-adv-x="1024"
+d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 60 35 110t93 71v139h128v-139q58 -21 93 -71t35 -110zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5
+t93.5 226.5zM896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192
+v128h192z" />
+ <glyph glyph-name="uniF2CB" unicode="" horiz-adv-x="1024"
+d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 79 56 135.5t136 56.5t136 -56.5t56 -135.5zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5t93.5 226.5z
+M896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192v128h192z" />
+ <glyph glyph-name="uniF2CC" unicode="" horiz-adv-x="1920"
+d="M1433 1287q10 -10 10 -23t-10 -23l-626 -626q-10 -10 -23 -10t-23 10l-82 82q-10 10 -10 23t10 23l44 44q-72 91 -81.5 207t46.5 215q-74 71 -176 71q-106 0 -181 -75t-75 -181v-1280h-256v1280q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5q106 0 201 -41
+t166 -115q94 39 197 24.5t185 -79.5l44 44q10 10 23 10t23 -10zM1344 1024q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1600 896q-26 0 -45 19t-19 45t19 45t45 19t45 -19t19 -45t-19 -45t-45 -19zM1856 1024q26 0 45 -19t19 -45t-19 -45t-45 -19
+t-45 19t-19 45t19 45t45 19zM1216 896q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1408 832q0 26 19 45t45 19t45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45zM1728 896q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1088 768
+q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1344 640q-26 0 -45 19t-19 45t19 45t45 19t45 -19t19 -45t-19 -45t-45 -19zM1600 768q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1216 512q-26 0 -45 19t-19 45t19 45t45 19t45 -19
+t19 -45t-19 -45t-45 -19zM1472 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1088 512q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1344 512q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1216 384
+q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1088 256q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19z" />
+ <glyph glyph-name="uniF2CD" unicode="" horiz-adv-x="1792"
+d="M1664 448v-192q0 -169 -128 -286v-194q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v118q-63 -22 -128 -22h-768q-65 0 -128 22v-110q0 -17 -9.5 -28.5t-22.5 -11.5h-64q-13 0 -22.5 11.5t-9.5 28.5v186q-128 117 -128 286v192h1536zM704 864q0 -14 -9 -23t-23 -9t-23 9
+t-9 23t9 23t23 9t23 -9t9 -23zM768 928q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM704 992q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM832 992q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM768 1056q0 -14 -9 -23t-23 -9t-23 9
+t-9 23t9 23t23 9t23 -9t9 -23zM704 1120q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM1792 608v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v640q0 106 75 181t181 75q108 0 184 -78q46 19 98 12t93 -39l22 22q11 11 22 0l42 -42
+q11 -11 0 -22l-314 -314q-11 -11 -22 0l-42 42q-11 11 0 22l22 22q-36 46 -40.5 104t23.5 108q-37 35 -88 35q-53 0 -90.5 -37.5t-37.5 -90.5v-640h1504q14 0 23 -9t9 -23zM896 1056q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM832 1120q0 -14 -9 -23t-23 -9
+t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM768 1184q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM960 1120q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM896 1184q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM832 1248q0 -14 -9 -23
+t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM1024 1184q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM960 1248q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM1088 1248q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23z" />
+ <glyph glyph-name="uniF2CE" unicode=""
+d="M994 344q0 -86 -17 -197q-31 -215 -55 -313q-22 -90 -152 -90t-152 90q-24 98 -55 313q-17 110 -17 197q0 168 224 168t224 -168zM1536 768q0 -240 -134 -434t-350 -280q-8 -3 -15 3t-6 15q7 48 10 66q4 32 6 47q1 9 9 12q159 81 255.5 234t96.5 337q0 180 -91 330.5
+t-247 234.5t-337 74q-124 -7 -237 -61t-193.5 -140.5t-128 -202t-46.5 -240.5q1 -184 99 -336.5t257 -231.5q7 -3 9 -12q3 -21 6 -45q1 -9 5 -32.5t6 -35.5q1 -9 -6.5 -15t-15.5 -2q-148 58 -261 169.5t-173.5 264t-52.5 319.5q7 143 66 273.5t154.5 227t225 157.5t272.5 70
+q164 10 315.5 -46.5t261 -160.5t175 -250.5t65.5 -308.5zM994 800q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5zM1282 768q0 -122 -53.5 -228.5t-146.5 -177.5q-8 -6 -16 -2t-10 14q-6 52 -29 92q-7 10 3 20
+q58 54 91 127t33 155q0 111 -58.5 204t-157.5 141.5t-212 36.5q-133 -15 -229 -113t-109 -231q-10 -92 23.5 -176t98.5 -144q10 -10 3 -20q-24 -41 -29 -93q-2 -9 -10 -13t-16 2q-95 74 -148.5 183t-51.5 234q3 131 69 244t177 181.5t241 74.5q144 7 268 -60t196.5 -187.5
+t72.5 -263.5z" />
+ <glyph glyph-name="uniF2D0" unicode="" horiz-adv-x="1792"
+d="M256 128h1280v768h-1280v-768zM1792 1248v-1216q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
+ <glyph glyph-name="uniF2D1" unicode="" horiz-adv-x="1792"
+d="M1792 224v-192q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
+ <glyph glyph-name="uniF2D2" unicode="" horiz-adv-x="2048"
+d="M256 0h768v512h-768v-512zM1280 512h512v768h-768v-256h96q66 0 113 -47t47 -113v-352zM2048 1376v-960q0 -66 -47 -113t-113 -47h-608v-352q0 -66 -47 -113t-113 -47h-960q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h608v352q0 66 47 113t113 47h960q66 0 113 -47
+t47 -113z" />
+ <glyph glyph-name="uniF2D3" unicode="" horiz-adv-x="1792"
+d="M1175 215l146 146q10 10 10 23t-10 23l-233 233l233 233q10 10 10 23t-10 23l-146 146q-10 10 -23 10t-23 -10l-233 -233l-233 233q-10 10 -23 10t-23 -10l-146 -146q-10 -10 -10 -23t10 -23l233 -233l-233 -233q-10 -10 -10 -23t10 -23l146 -146q10 -10 23 -10t23 10
+l233 233l233 -233q10 -10 23 -10t23 10zM1792 1248v-1216q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
+ <glyph glyph-name="uniF2D4" unicode="" horiz-adv-x="1792"
+d="M1257 425l-146 -146q-10 -10 -23 -10t-23 10l-169 169l-169 -169q-10 -10 -23 -10t-23 10l-146 146q-10 10 -10 23t10 23l169 169l-169 169q-10 10 -10 23t10 23l146 146q10 10 23 10t23 -10l169 -169l169 169q10 10 23 10t23 -10l146 -146q10 -10 10 -23t-10 -23
+l-169 -169l169 -169q10 -10 10 -23t-10 -23zM256 128h1280v1024h-1280v-1024zM1792 1248v-1216q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
+ <glyph glyph-name="uniF2D5" unicode="" horiz-adv-x="1792"
+d="M1070 358l306 564h-654l-306 -564h654zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+ <glyph glyph-name="uniF2D6" unicode="" horiz-adv-x="1794"
+d="M1291 1060q-15 17 -35 8.5t-26 -28.5t5 -38q14 -17 40 -14.5t34 20.5t-18 52zM895 814q-8 -8 -19.5 -8t-18.5 8q-8 8 -8 19t8 18q7 8 18.5 8t19.5 -8q7 -7 7 -18t-7 -19zM1060 740l-35 -35q-12 -13 -29.5 -13t-30.5 13l-38 38q-12 13 -12 30t12 30l35 35q12 12 29.5 12
+t30.5 -12l38 -39q12 -12 12 -29.5t-12 -29.5zM951 870q-7 -8 -18.5 -8t-19.5 8q-7 8 -7 19t7 19q8 8 19 8t19 -8t8 -19t-8 -19zM1354 968q-34 -64 -107.5 -85.5t-127.5 16.5q-38 28 -61 66.5t-21 87.5t39 92t75.5 53t70.5 -5t70 -51q2 -2 13 -12.5t14.5 -13.5t13 -13.5
+t12.5 -15.5t10 -15.5t8.5 -18t4 -18.5t1 -21t-5 -22t-9.5 -24zM1555 486q3 20 -8.5 34.5t-27.5 21.5t-33 17t-23 20q-40 71 -84 98.5t-113 11.5q19 13 40 18.5t33 4.5l12 -1q2 45 -34 90q6 20 6.5 40.5t-2.5 30.5l-3 10q43 24 71 65t34 91q10 84 -43 150.5t-137 76.5
+q-60 7 -114 -18.5t-82 -74.5q-30 -51 -33.5 -101t14.5 -87t43.5 -64t56.5 -42q-45 4 -88 36t-57 88q-28 108 32 222q-16 21 -29 32q-50 0 -89 -19q19 24 42 37t36 14l13 1q0 50 -13 78q-10 21 -32.5 28.5t-47 -3.5t-37.5 -40q2 4 4 7q-7 -28 -6.5 -75.5t19 -117t48.5 -122.5
+q-25 -14 -47 -36q-35 -16 -85.5 -70.5t-84.5 -101.5l-33 -46q-90 -34 -181 -125.5t-75 -162.5q1 -16 11 -27q-15 -12 -30 -30q-21 -25 -21 -54t21.5 -40t63.5 6q41 19 77 49.5t55 60.5q-2 2 -6.5 5t-20.5 7.5t-33 3.5q23 5 51 12.5t40 10t27.5 6t26 4t23.5 0.5q14 -7 22 34
+q7 37 7 90q0 102 -40 150q106 -103 101 -219q-1 -29 -15 -50t-27 -27l-13 -6q-4 -7 -19 -32t-26 -45.5t-26.5 -52t-25 -61t-17 -63t-6.5 -66.5t10 -63q-35 54 -37 80q-22 -24 -34.5 -39t-33.5 -42t-30.5 -46t-16.5 -41t-0.5 -38t25.5 -27q45 -25 144 64t190.5 221.5
+t122.5 228.5q86 52 145 115.5t86 119.5q47 -93 154 -178q104 -83 167 -80q39 2 46 43zM1794 640q0 -182 -71 -348t-191 -286t-286.5 -191t-348.5 -71t-348.5 71t-286.5 191t-191 286t-71 348t71 348t191 286t286.5 191t348.5 71t348.5 -71t286.5 -191t191 -286t71 -348z" />
+ <glyph glyph-name="uniF2D7" unicode=""
+d="M518 1353v-655q103 -1 191.5 1.5t125.5 5.5l37 3q68 2 90.5 24.5t39.5 94.5l33 142h103l-14 -322l7 -319h-103l-29 127q-15 68 -45 93t-84 26q-87 8 -352 8v-556q0 -78 43.5 -115.5t133.5 -37.5h357q35 0 59.5 2t55 7.5t54 18t48.5 32t46 50.5t39 73l93 216h89
+q-6 -37 -31.5 -252t-30.5 -276q-146 5 -263.5 8t-162.5 4h-44h-628l-376 -12v102l127 25q67 13 91.5 37t25.5 79l8 643q3 402 -8 645q-2 61 -25.5 84t-91.5 36l-127 24v102l376 -12h702q139 0 374 27q-6 -68 -14 -194.5t-12 -219.5l-5 -92h-93l-32 124q-31 121 -74 179.5
+t-113 58.5h-548q-28 0 -35.5 -8.5t-7.5 -30.5z" />
+ <glyph glyph-name="uniF2D8" unicode=""
+d="M922 739v-182q0 -4 0.5 -15t0 -15l-1.5 -12t-3.5 -11.5t-6.5 -7.5t-11 -5.5t-16 -1.5v309q9 0 16 -1t11 -5t6.5 -5.5t3.5 -9.5t1 -10.5v-13.5v-14zM1238 643v-121q0 -1 0.5 -12.5t0 -15.5t-2.5 -11.5t-7.5 -10.5t-13.5 -3q-9 0 -14 9q-4 10 -4 165v7v8.5v9t1.5 8.5l3.5 7
+t5 5.5t8 1.5q6 0 10 -1.5t6.5 -4.5t4 -6t2 -8.5t0.5 -8v-9.5v-9zM180 407h122v472h-122v-472zM614 407h106v472h-159l-28 -221q-20 148 -32 221h-158v-472h107v312l45 -312h76l43 319v-319zM1039 712q0 67 -5 90q-3 16 -11 28.5t-17 20.5t-25 14t-26.5 8.5t-31 4t-29 1.5
+h-29.5h-12h-91v-472h56q169 -1 197 24.5t25 180.5q-1 62 -1 100zM1356 515v133q0 29 -2 45t-9.5 33.5t-24.5 25t-46 7.5q-46 0 -77 -34v154h-117v-472h110l7 30q30 -36 77 -36q50 0 66 30.5t16 83.5zM1536 1248v-1216q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113
+v1216q0 66 47 113t113 47h1216q66 0 113 -47t47 -113z" />
+ <glyph glyph-name="uniF2D9" unicode="" horiz-adv-x="2176"
+d="M1143 -197q-6 1 -11 4q-13 8 -36 23t-86 65t-116.5 104.5t-112 140t-89.5 172.5q-17 3 -175 37q66 -213 235 -362t391 -184zM502 409l168 -28q-25 76 -41 167.5t-19 145.5l-4 53q-84 -82 -121 -224q5 -65 17 -114zM612 1018q-43 -64 -77 -148q44 46 74 68zM2049 584
+q0 161 -62 307t-167.5 252t-250.5 168.5t-304 62.5q-147 0 -281 -52.5t-240 -148.5q-30 -58 -45 -160q60 51 143 83.5t158.5 43t143 13.5t108.5 -1l40 -3q33 -1 53 -15.5t24.5 -33t6.5 -37t-1 -28.5q-126 11 -227.5 0.5t-183 -43.5t-142.5 -71.5t-131 -98.5
+q4 -36 11.5 -92.5t35.5 -178t62 -179.5q123 -6 247.5 14.5t214.5 53.5t162.5 67t109.5 59l37 24q22 16 39.5 20.5t30.5 -5t17 -34.5q14 -97 -39 -121q-208 -97 -467 -134q-135 -20 -317 -16q41 -96 110 -176.5t137 -127t130.5 -79t101.5 -43.5l39 -12q143 -23 263 15
+q195 99 314 289t119 418zM2123 621q-14 -135 -40 -212q-70 -208 -181.5 -346.5t-318.5 -253.5q-48 -33 -82 -44q-72 -26 -163 -16q-36 -3 -73 -3q-283 0 -504.5 173t-295.5 442q-1 0 -4 0.5t-5 0.5q-6 -50 2.5 -112.5t26 -115t36 -98t31.5 -71.5l14 -26q8 -12 54 -82
+q-71 38 -124.5 106.5t-78.5 140t-39.5 137t-17.5 107.5l-2 42q-5 2 -33.5 12.5t-48.5 18t-53 20.5t-57.5 25t-50 25.5t-42.5 27t-25 25.5q19 -10 50.5 -25.5t113 -45.5t145.5 -38l2 32q11 149 94 290q41 202 176 365q28 115 81 214q15 28 32 45t49 32q158 74 303.5 104
+t302 11t306.5 -97q220 -115 333 -336t87 -474z" />
+ <glyph glyph-name="uniF2DA" unicode="" horiz-adv-x="1792"
+d="M1341 752q29 44 -6.5 129.5t-121.5 142.5q-58 39 -125.5 53.5t-118 4.5t-68.5 -37q-12 -23 -4.5 -28t42.5 -10q23 -3 38.5 -5t44.5 -9.5t56 -17.5q36 -13 67.5 -31.5t53 -37t40 -38.5t30.5 -38t22 -34.5t16.5 -28.5t12 -18.5t10.5 -6t11 9.5zM1704 178
+q-52 -127 -148.5 -220t-214.5 -141.5t-253 -60.5t-266 13.5t-251 91t-210 161.5t-141.5 235.5t-46.5 303.5q1 41 8.5 84.5t12.5 64t24 80.5t23 73q-51 -208 1 -397t173 -318t291 -206t346 -83t349 74.5t289 244.5q20 27 18 14q0 -4 -4 -14zM1465 627q0 -104 -40.5 -199
+t-108.5 -164t-162 -109.5t-198 -40.5t-198 40.5t-162 109.5t-108.5 164t-40.5 199t40.5 199t108.5 164t162 109.5t198 40.5t198 -40.5t162 -109.5t108.5 -164t40.5 -199zM1752 915q-65 147 -180.5 251t-253 153.5t-292 53.5t-301 -36.5t-275.5 -129t-220 -211.5t-131 -297
+t-10 -373q-49 161 -51.5 311.5t35.5 272.5t109 227t165.5 180.5t207 126t232 71t242.5 9t236 -54t216 -124.5t178 -197q33 -50 62 -121t31 -112zM1690 573q12 244 -136.5 416t-396.5 240q-8 0 -10 5t24 8q125 -4 230 -50t173 -120t116 -168.5t58.5 -199t-1 -208
+t-61.5 -197.5t-122.5 -167t-185 -117.5t-248.5 -46.5q108 30 201.5 80t174 123t129.5 176.5t55 225.5z" />
+ <glyph glyph-name="uniF2DB" unicode=""
+d="M192 256v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16q0 16 16 16h112zM192 512v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16q0 16 16 16h112zM192 768v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16
+q0 16 16 16h112zM192 1024v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16q0 16 16 16h112zM192 1280v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16q0 16 16 16h112zM1280 1440v-1472q0 -40 -28 -68t-68 -28h-832q-40 0 -68 28
+t-28 68v1472q0 40 28 68t68 28h832q40 0 68 -28t28 -68zM1536 208v-32q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16h48q16 0 16 -16zM1536 464v-32q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16h48q16 0 16 -16zM1536 720v-32
+q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16h48q16 0 16 -16zM1536 976v-32q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16h48q16 0 16 -16zM1536 1232v-32q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16
+h48q16 0 16 -16z" />
+ <glyph glyph-name="uniF2DC" unicode="" horiz-adv-x="1664"
+d="M1566 419l-167 -33l186 -107q23 -13 29.5 -38.5t-6.5 -48.5q-14 -23 -39 -29.5t-48 6.5l-186 106l55 -160q13 -38 -12 -63.5t-60.5 -20.5t-48.5 42l-102 300l-271 156v-313l208 -238q16 -18 17 -39t-11 -36.5t-28.5 -25t-37 -5.5t-36.5 22l-112 128v-214q0 -26 -19 -45
+t-45 -19t-45 19t-19 45v214l-112 -128q-16 -18 -36.5 -22t-37 5.5t-28.5 25t-11 36.5t17 39l208 238v313l-271 -156l-102 -300q-13 -37 -48.5 -42t-60.5 20.5t-12 63.5l55 160l-186 -106q-23 -13 -48 -6.5t-39 29.5q-13 23 -6.5 48.5t29.5 38.5l186 107l-167 33
+q-29 6 -42 29t-8.5 46.5t25.5 40t50 10.5l310 -62l271 157l-271 157l-310 -62q-4 -1 -13 -1q-27 0 -44 18t-19 40t11 43t40 26l167 33l-186 107q-23 13 -29.5 38.5t6.5 48.5t39 30t48 -7l186 -106l-55 160q-13 38 12 63.5t60.5 20.5t48.5 -42l102 -300l271 -156v313
+l-208 238q-16 18 -17 39t11 36.5t28.5 25t37 5.5t36.5 -22l112 -128v214q0 26 19 45t45 19t45 -19t19 -45v-214l112 128q16 18 36.5 22t37 -5.5t28.5 -25t11 -36.5t-17 -39l-208 -238v-313l271 156l102 300q13 37 48.5 42t60.5 -20.5t12 -63.5l-55 -160l186 106
+q23 13 48 6.5t39 -29.5q13 -23 6.5 -48.5t-29.5 -38.5l-186 -107l167 -33q27 -5 40 -26t11 -43t-19 -40t-44 -18q-9 0 -13 1l-310 62l-271 -157l271 -157l310 62q29 6 50 -10.5t25.5 -40t-8.5 -46.5t-42 -29z" />
+ <glyph glyph-name="uniF2DD" unicode="" horiz-adv-x="1792"
+d="M1473 607q7 118 -33 226.5t-113 189t-177 131t-221 57.5q-116 7 -225.5 -32t-192 -110.5t-135 -175t-59.5 -220.5q-7 -118 33 -226.5t113 -189t177.5 -131t221.5 -57.5q155 -9 293 59t224 195.5t94 283.5zM1792 1536l-349 -348q120 -117 180.5 -272t50.5 -321
+q-11 -183 -102 -339t-241 -255.5t-332 -124.5l-999 -132l347 347q-120 116 -180.5 271.5t-50.5 321.5q11 184 102 340t241.5 255.5t332.5 124.5q167 22 500 66t500 66z" />
+ <glyph glyph-name="uniF2DE" unicode="" horiz-adv-x="1792"
+d="M948 508l163 -329h-51l-175 350l-171 -350h-49l179 374l-78 33l21 49l240 -102l-21 -50zM563 1100l304 -130l-130 -304l-304 130zM907 915l240 -103l-103 -239l-239 102zM1188 765l191 -81l-82 -190l-190 81zM1680 640q0 159 -62 304t-167.5 250.5t-250.5 167.5t-304 62
+t-304 -62t-250.5 -167.5t-167.5 -250.5t-62 -304t62 -304t167.5 -250.5t250.5 -167.5t304 -62t304 62t250.5 167.5t167.5 250.5t62 304zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71
+t286 -191t191 -286t71 -348z" />
+ <glyph glyph-name="uniF2E0" unicode="" horiz-adv-x="1920"
+d="M1334 302q-4 24 -27.5 34t-49.5 10.5t-48.5 12.5t-25.5 38q-5 47 33 139.5t75 181t32 127.5q-14 101 -117 103q-45 1 -75 -16l-3 -2l-5 -2.5t-4.5 -2t-5 -2t-5 -0.5t-6 1.5t-6 3.5t-6.5 5q-3 2 -9 8.5t-9 9t-8.5 7.5t-9.5 7.5t-9.5 5.5t-11 4.5t-11.5 2.5q-30 5 -48 -3
+t-45 -31q-1 -1 -9 -8.5t-12.5 -11t-15 -10t-16.5 -5.5t-17 3q-54 27 -84 40q-41 18 -94 -5t-76 -65q-16 -28 -41 -98.5t-43.5 -132.5t-40 -134t-21.5 -73q-22 -69 18.5 -119t110.5 -46q30 2 50.5 15t38.5 46q7 13 79 199.5t77 194.5q6 11 21.5 18t29.5 0q27 -15 21 -53
+q-2 -18 -51 -139.5t-50 -132.5q-6 -38 19.5 -56.5t60.5 -7t55 49.5q4 8 45.5 92t81.5 163.5t46 88.5q20 29 41 28q29 0 25 -38q-2 -16 -65.5 -147.5t-70.5 -159.5q-12 -53 13 -103t74 -74q17 -9 51 -15.5t71.5 -8t62.5 14t20 48.5zM383 86q3 -15 -5 -27.5t-23 -15.5
+q-14 -3 -26.5 5t-15.5 23q-3 14 5 27t22 16t27 -5t16 -23zM953 -177q12 -17 8.5 -37.5t-20.5 -32.5t-37.5 -8t-32.5 21q-11 17 -7.5 37.5t20.5 32.5t37.5 8t31.5 -21zM177 635q-18 -27 -49.5 -33t-57.5 13q-26 18 -32 50t12 58q18 27 49.5 33t57.5 -12q26 -19 32 -50.5
+t-12 -58.5zM1467 -42q19 -28 13 -61.5t-34 -52.5t-60.5 -13t-51.5 34t-13 61t33 53q28 19 60.5 13t52.5 -34zM1579 562q69 -113 42.5 -244.5t-134.5 -207.5q-90 -63 -199 -60q-20 -80 -84.5 -127t-143.5 -44.5t-140 57.5q-12 -9 -13 -10q-103 -71 -225 -48.5t-193 126.5
+q-50 73 -53 164q-83 14 -142.5 70.5t-80.5 128t-2 152t81 138.5q-36 60 -38 128t24.5 125t79.5 98.5t121 50.5q32 85 99 148t146.5 91.5t168 17t159.5 -66.5q72 21 140 17.5t128.5 -36t104.5 -80t67.5 -115t17.5 -140.5q52 -16 87 -57t45.5 -89t-5.5 -99.5t-58 -87.5z
+M455 1222q14 -20 9.5 -44.5t-24.5 -38.5q-19 -14 -43.5 -9.5t-37.5 24.5q-14 20 -9.5 44.5t24.5 38.5q19 14 43.5 9.5t37.5 -24.5zM614 1503q4 -16 -5 -30.5t-26 -18.5t-31 5.5t-18 26.5q-3 17 6.5 31t25.5 18q17 4 31 -5.5t17 -26.5zM1800 555q4 -20 -6.5 -37t-30.5 -21
+q-19 -4 -36 6.5t-21 30.5t6.5 37t30.5 22q20 4 36.5 -7.5t20.5 -30.5zM1136 1448q16 -27 8.5 -58.5t-35.5 -47.5q-27 -16 -57.5 -8.5t-46.5 34.5q-16 28 -8.5 59t34.5 48t58 9t47 -36zM1882 792q4 -15 -4 -27.5t-23 -16.5q-15 -3 -27.5 5.5t-15.5 22.5q-3 15 5 28t23 16
+q14 3 26.5 -5t15.5 -23zM1691 1033q15 -22 10.5 -49t-26.5 -43q-22 -15 -49 -10t-42 27t-10 49t27 43t48.5 11t41.5 -28z" />
+ <glyph glyph-name="uniF2E1" unicode="" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="uniF2E2" unicode="" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="uniF2E3" unicode="" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="uniF2E4" unicode="" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="uniF2E5" unicode="" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="uniF2E6" unicode="" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="uniF2E7" unicode="" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="_698" unicode="" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="uniF2E9" unicode="" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="uniF2EA" unicode="" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="uniF2EB" unicode="" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="uniF2EC" unicode="" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="uniF2ED" unicode="" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="uniF2EE" unicode="" horiz-adv-x="1792"
+ />
+ <glyph glyph-name="lessequal" unicode="" horiz-adv-x="1792"
+ />
+ </font>
+</defs></svg>
--- /dev/null
+module Alerts.Api exposing (..)
+
+import Alerts.Types exposing (Alert, Receiver)
+import Json.Decode as Json exposing (..)
+import Utils.Api exposing (iso8601Time)
+import Utils.Filter exposing (Filter, generateQueryString)
+import Utils.Types exposing (ApiData)
+import Regex
+
+
+fetchReceivers : String -> Cmd (ApiData (List Receiver))
+fetchReceivers apiUrl =
+ Utils.Api.send
+ (Utils.Api.get
+ (apiUrl ++ "/receivers")
+ (field "data" (list (Json.map (\receiver -> Receiver receiver (Regex.escape receiver)) string)))
+ )
+
+
+fetchAlerts : String -> Filter -> Cmd (ApiData (List Alert))
+fetchAlerts apiUrl filter =
+ let
+ url =
+ String.join "/" [ apiUrl, "alerts" ++ generateQueryString filter ]
+ in
+ Utils.Api.send (Utils.Api.get url alertsDecoder)
+
+
+alertsDecoder : Json.Decoder (List Alert)
+alertsDecoder =
+ Json.list alertDecoder
+ -- populate alerts with ids:
+ |> Json.map (List.indexedMap (toString >> (|>)))
+ |> field "data"
+
+
+{-| TODO: decode alert id when provided
+-}
+alertDecoder : Json.Decoder (String -> Alert)
+alertDecoder =
+ Json.map6 Alert
+ (Json.maybe (field "annotations" (Json.keyValuePairs Json.string))
+ |> andThen (Maybe.withDefault [] >> Json.succeed)
+ )
+ (field "labels" (Json.keyValuePairs Json.string))
+ (Json.maybe (Json.at [ "status", "silencedBy", "0" ] Json.string))
+ (Json.maybe (Json.at [ "status", "inhibitedBy", "0" ] Json.string)
+ |> Json.map ((/=) Nothing)
+ )
+ (field "startsAt" iso8601Time)
+ (field "generatorURL" Json.string)
--- /dev/null
+module Alerts.Types exposing (Alert, Receiver)
+
+import Utils.Types exposing (Labels)
+import Time exposing (Time)
+
+
+type alias Alert =
+ { annotations : Labels
+ , labels : Labels
+ , silenceId : Maybe String
+ , isInhibited : Bool
+ , startsAt : Time
+ , generatorUrl : String
+ , id : String
+ }
+
+
+type alias Receiver =
+ { name : String
+ , regex : String
+ }
--- /dev/null
+module Main exposing (main)
+
+import Navigation
+import Parsing
+import Views
+import Types
+ exposing
+ ( Route(..)
+ , Msg
+ ( NavigateToSilenceList
+ , NavigateToSilenceView
+ , NavigateToSilenceFormEdit
+ , NavigateToSilenceFormNew
+ , NavigateToAlerts
+ , NavigateToNotFound
+ , NavigateToStatus
+ , RedirectAlerts
+ )
+ , Model
+ )
+import Utils.Filter exposing (nullFilter)
+import Views.SilenceForm.Types exposing (initSilenceForm)
+import Views.Status.Types exposing (StatusModel, initStatusModel)
+import Views.AlertList.Types exposing (initAlertList)
+import Views.SilenceList.Types exposing (initSilenceList)
+import Views.SilenceView.Types exposing (initSilenceView)
+import Updates exposing (update)
+import Utils.Api as Api
+import Utils.Types exposing (ApiData(Loading))
+import Json.Decode as Json
+
+
+main : Program Json.Value Model Msg
+main =
+ Navigation.programWithFlags urlUpdate
+ { init = init
+ , update = update
+ , view = Views.view
+ , subscriptions = always Sub.none
+ }
+
+
+init : Json.Value -> Navigation.Location -> ( Model, Cmd Msg )
+init flags location =
+ let
+ route =
+ Parsing.urlParser location
+
+ filter =
+ case route of
+ AlertsRoute filter ->
+ filter
+
+ SilenceListRoute filter ->
+ filter
+
+ _ ->
+ nullFilter
+
+ prod =
+ flags
+ |> Json.decodeValue (Json.field "production" Json.bool)
+ |> Result.withDefault False
+
+ defaultCreator =
+ flags
+ |> Json.decodeValue (Json.field "defaultCreator" Json.string)
+ |> Result.withDefault ""
+
+ apiUrl =
+ if prod then
+ Api.makeApiUrl location.pathname
+ else
+ Api.makeApiUrl "http://localhost:9093/"
+
+ libUrl =
+ if prod then
+ location.pathname
+ else
+ "/"
+ in
+ update (urlUpdate location)
+ (Model
+ initSilenceList
+ initSilenceView
+ initSilenceForm
+ initAlertList
+ route
+ filter
+ initStatusModel
+ location.pathname
+ apiUrl
+ libUrl
+ Loading
+ Loading
+ defaultCreator
+ )
+
+
+urlUpdate : Navigation.Location -> Msg
+urlUpdate location =
+ let
+ route =
+ Parsing.urlParser location
+ in
+ case route of
+ SilenceListRoute maybeFilter ->
+ NavigateToSilenceList maybeFilter
+
+ SilenceViewRoute silenceId ->
+ NavigateToSilenceView silenceId
+
+ SilenceFormEditRoute silenceId ->
+ NavigateToSilenceFormEdit silenceId
+
+ SilenceFormNewRoute matchers ->
+ NavigateToSilenceFormNew matchers
+
+ AlertsRoute filter ->
+ NavigateToAlerts filter
+
+ StatusRoute ->
+ NavigateToStatus
+
+ TopLevelRoute ->
+ RedirectAlerts
+
+ NotFoundRoute ->
+ NavigateToNotFound
--- /dev/null
+module Parsing exposing (..)
+
+import Views.AlertList.Parsing exposing (alertsParser)
+import Views.SilenceList.Parsing exposing (silenceListParser)
+import Views.SilenceView.Parsing exposing (silenceViewParser)
+import Views.SilenceForm.Parsing exposing (silenceFormNewParser, silenceFormEditParser)
+import Views.Status.Parsing exposing (statusParser)
+import Navigation
+import UrlParser exposing ((</>), (<?>), Parser, int, map, oneOf, parseHash, s, string, stringParam, top)
+import Regex
+import Types exposing (Route(..))
+
+
+urlParser : Navigation.Location -> Route
+urlParser location =
+ let
+ -- Parse a query string occurring after the hash if it exists, and use
+ -- it for routing.
+ hashAndQuery =
+ Regex.split (Regex.AtMost 1) (Regex.regex "\\?") (location.hash)
+
+ hash =
+ case List.head hashAndQuery of
+ Just hash ->
+ hash
+
+ Nothing ->
+ ""
+
+ query =
+ if List.length hashAndQuery == 2 then
+ case List.head <| List.reverse hashAndQuery of
+ Just query ->
+ "?" ++ query
+
+ Nothing ->
+ ""
+ else
+ ""
+ in
+ case parseHash routeParser { location | search = query, hash = hash } of
+ Just route ->
+ route
+
+ Nothing ->
+ NotFoundRoute
+
+
+routeParser : Parser (Route -> a) a
+routeParser =
+ oneOf
+ [ map SilenceListRoute silenceListParser
+ , map StatusRoute statusParser
+ , map SilenceFormNewRoute silenceFormNewParser
+ , map SilenceViewRoute silenceViewParser
+ , map SilenceFormEditRoute silenceFormEditParser
+ , map AlertsRoute alertsParser
+ , map TopLevelRoute top
+ ]
--- /dev/null
+module Silences.Api exposing (..)
+
+import Http
+import Silences.Types exposing (Silence)
+import Utils.Types exposing (ApiData(..))
+import Utils.Filter exposing (Filter)
+import Utils.Api
+import Silences.Decoders exposing (show, list, create, destroy)
+import Silences.Encoders
+import Utils.Filter exposing (generateQueryString)
+
+
+getSilences : String -> Filter -> (ApiData (List Silence) -> msg) -> Cmd msg
+getSilences apiUrl filter msg =
+ let
+ url =
+ String.join "/" [ apiUrl, "silences" ++ (generateQueryString filter) ]
+ in
+ Utils.Api.send (Utils.Api.get url list)
+ |> Cmd.map msg
+
+
+getSilence : String -> String -> (ApiData Silence -> msg) -> Cmd msg
+getSilence apiUrl uuid msg =
+ let
+ url =
+ String.join "/" [ apiUrl, "silence", uuid ]
+ in
+ Utils.Api.send (Utils.Api.get url show)
+ |> Cmd.map msg
+
+
+create : String -> Silence -> Cmd (ApiData String)
+create apiUrl silence =
+ let
+ url =
+ String.join "/" [ apiUrl, "silences" ]
+
+ body =
+ Http.jsonBody <| Silences.Encoders.silence silence
+ in
+ -- TODO: This should return the silence, not just the ID, so that we can
+ -- redirect to the silence show page.
+ Utils.Api.send
+ (Utils.Api.post url body Silences.Decoders.create)
+
+
+destroy : String -> Silence -> (ApiData String -> msg) -> Cmd msg
+destroy apiUrl silence msg =
+ -- The incorrect route using "silences" receives a 405. The route seems to
+ -- be matching on /silences and ignoring the :sid, should be getting a 404.
+ let
+ url =
+ String.join "/" [ apiUrl, "silence", silence.id ]
+
+ responseDecoder =
+ -- Silences.Encoders.silence silence
+ Silences.Decoders.destroy
+ in
+ Utils.Api.send (Utils.Api.delete url responseDecoder)
+ |> Cmd.map msg
--- /dev/null
+module Silences.Decoders exposing (show, list, create, destroy)
+
+import Json.Decode as Json exposing (field, succeed, fail)
+import Utils.Api exposing (iso8601Time, (|:))
+import Silences.Types exposing (Silence, Status, State(Active, Pending, Expired))
+import Utils.Types exposing (Matcher, Time, ApiData(Initial))
+
+
+show : Json.Decoder Silence
+show =
+ Json.at [ "data" ] silenceDecoder
+
+
+list : Json.Decoder (List Silence)
+list =
+ Json.at [ "data" ] (Json.list silenceDecoder)
+
+
+create : Json.Decoder String
+create =
+ Json.at [ "data", "silenceId" ] Json.string
+
+
+destroy : Json.Decoder String
+destroy =
+ Json.at [ "status" ] Json.string
+
+
+silenceDecoder : Json.Decoder Silence
+silenceDecoder =
+ Json.succeed Silence
+ |: (field "id" Json.string)
+ |: (field "createdBy" Json.string)
+ -- Remove this maybe once the api either disallows empty comments on
+ -- creation, or returns an empty string.
+ |: ((Json.maybe (field "comment" Json.string))
+ |> Json.andThen (\x -> Json.succeed <| Maybe.withDefault "" x)
+ )
+ |: (field "startsAt" iso8601Time)
+ |: (field "endsAt" iso8601Time)
+ |: (field "updatedAt" iso8601Time)
+ |: (field "matchers" (Json.list matcherDecoder))
+ |: (field "status" statusDecoder)
+
+
+statusDecoder : Json.Decoder Status
+statusDecoder =
+ Json.succeed Status
+ |: (field "state" Json.string |> Json.andThen stateDecoder)
+
+
+stateDecoder : String -> Json.Decoder State
+stateDecoder state =
+ case state of
+ "active" ->
+ succeed Active
+
+ "pending" ->
+ succeed Pending
+
+ "expired" ->
+ succeed Expired
+
+ _ ->
+ fail <|
+ "Silence.status.state must be one of 'active', 'pending' or 'expired' but was'"
+ ++ state
+ ++ "'."
+
+
+matcherDecoder : Json.Decoder Matcher
+matcherDecoder =
+ Json.map3 Matcher
+ (field "isRegex" Json.bool)
+ (field "name" Json.string)
+ (field "value" Json.string)
--- /dev/null
+module Silences.Encoders exposing (..)
+
+import Json.Encode as Encode
+import Silences.Types exposing (Silence)
+import Utils.Types exposing (Matcher)
+import Utils.Date
+
+
+silence : Silence -> Encode.Value
+silence silence =
+ Encode.object
+ [ ( "id", Encode.string silence.id )
+ , ( "createdBy", Encode.string silence.createdBy )
+ , ( "comment", Encode.string silence.comment )
+ , ( "startsAt", Encode.string (Utils.Date.encode silence.startsAt) )
+ , ( "endsAt", Encode.string (Utils.Date.encode silence.endsAt) )
+ , ( "matchers", Encode.list (List.map matcher silence.matchers) )
+ ]
+
+
+matcher : Matcher -> Encode.Value
+matcher m =
+ Encode.object
+ [ ( "name", Encode.string m.name )
+ , ( "value", Encode.string m.value )
+ , ( "isRegex", Encode.bool m.isRegex )
+ ]
--- /dev/null
+module Silences.Types
+ exposing
+ ( Silence
+ , SilenceId
+ , Status
+ , State(Active, Pending, Expired)
+ , nullSilence
+ , nullSilenceStatus
+ , nullMatcher
+ , nullTime
+ , stateToString
+ )
+
+import Utils.Types exposing (Matcher)
+import Time exposing (Time)
+
+
+nullSilence : Silence
+nullSilence =
+ { id = ""
+ , createdBy = ""
+ , comment = ""
+ , startsAt = 0
+ , endsAt = 0
+ , updatedAt = 0
+ , matchers = [ nullMatcher ]
+ , status = nullSilenceStatus
+ }
+
+
+nullSilenceStatus : Status
+nullSilenceStatus =
+ { state = Expired
+ }
+
+
+nullMatcher : Matcher
+nullMatcher =
+ Matcher False "" ""
+
+
+nullTime : Time
+nullTime =
+ 0
+
+
+type alias Silence =
+ { id : SilenceId
+ , createdBy : String
+ , comment : String
+ , startsAt : Time
+ , endsAt : Time
+ , updatedAt : Time
+ , matchers : List Matcher
+ , status : Status
+ }
+
+
+type alias Status =
+ { state : State
+ }
+
+
+type State
+ = Active
+ | Pending
+ | Expired
+
+
+stateToString : State -> String
+stateToString state =
+ case state of
+ Active ->
+ "active"
+
+ Pending ->
+ "pending"
+
+ Expired ->
+ "expired"
+
+
+type alias SilenceId =
+ String
--- /dev/null
+module Status.Api exposing (getStatus)
+
+import Utils.Api exposing (send, get)
+import Utils.Types exposing (ApiData)
+import Status.Types exposing (StatusResponse, VersionInfo, ClusterStatus, ClusterPeer)
+import Json.Decode exposing (Decoder, map2, string, field, at, list, int, maybe, bool)
+
+
+getStatus : String -> (ApiData StatusResponse -> msg) -> Cmd msg
+getStatus apiUrl msg =
+ let
+ url =
+ String.join "/" [ apiUrl, "status" ]
+
+ request =
+ get url decodeStatusResponse
+ in
+ Cmd.map msg <| send request
+
+
+decodeStatusResponse : Decoder StatusResponse
+decodeStatusResponse =
+ field "data" decodeData
+
+
+decodeData : Decoder StatusResponse
+decodeData =
+ Json.Decode.map4 StatusResponse
+ (field "configYAML" string)
+ (field "uptime" string)
+ (field "versionInfo" decodeVersionInfo)
+ (field "clusterStatus" (maybe decodeClusterStatus))
+
+
+decodeVersionInfo : Decoder VersionInfo
+decodeVersionInfo =
+ Json.Decode.map6 VersionInfo
+ (field "branch" string)
+ (field "buildDate" string)
+ (field "buildUser" string)
+ (field "goVersion" string)
+ (field "revision" string)
+ (field "version" string)
+
+
+decodeClusterStatus : Decoder ClusterStatus
+decodeClusterStatus =
+ Json.Decode.map3 ClusterStatus
+ (field "name" string)
+ (field "status" string)
+ (field "peers" (list decodeClusterPeer))
+
+
+decodeClusterPeer : Decoder ClusterPeer
+decodeClusterPeer =
+ Json.Decode.map2 ClusterPeer
+ (field "name" string)
+ (field "address" string)
--- /dev/null
+module Status.Types exposing (StatusResponse, VersionInfo, ClusterStatus, ClusterPeer)
+
+
+type alias StatusResponse =
+ { config : String
+ , uptime : String
+ , versionInfo : VersionInfo
+ , clusterStatus : Maybe ClusterStatus
+ }
+
+
+type alias VersionInfo =
+ { branch : String
+ , buildDate : String
+ , buildUser : String
+ , goVersion : String
+ , revision : String
+ , version : String
+ }
+
+
+type alias ClusterStatus =
+ { name : String
+ , status : String
+ , peers : List ClusterPeer
+ }
+
+
+type alias ClusterPeer =
+ { name : String
+ , address : String
+ }
--- /dev/null
+module Types exposing (Model, Msg(..), Route(..))
+
+import Views.AlertList.Types as AlertList exposing (AlertListMsg)
+import Views.SilenceList.Types as SilenceList exposing (SilenceListMsg)
+import Views.SilenceView.Types as SilenceView exposing (SilenceViewMsg)
+import Views.SilenceForm.Types as SilenceForm exposing (SilenceFormMsg)
+import Views.Status.Types exposing (StatusModel, StatusMsg)
+import Utils.Filter exposing (Filter, Matcher)
+import Utils.Types exposing (ApiData)
+
+
+type alias Model =
+ { silenceList : SilenceList.Model
+ , silenceView : SilenceView.Model
+ , silenceForm : SilenceForm.Model
+ , alertList : AlertList.Model
+ , route : Route
+ , filter : Filter
+ , status : StatusModel
+ , basePath : String
+ , apiUrl : String
+ , libUrl : String
+ , bootstrapCSS : ApiData String
+ , fontAwesomeCSS : ApiData String
+ , defaultCreator : String
+ }
+
+
+type Msg
+ = MsgForAlertList AlertListMsg
+ | MsgForSilenceView SilenceViewMsg
+ | MsgForSilenceForm SilenceFormMsg
+ | MsgForSilenceList SilenceListMsg
+ | MsgForStatus StatusMsg
+ | NavigateToAlerts Filter
+ | NavigateToNotFound
+ | NavigateToSilenceView String
+ | NavigateToSilenceFormEdit String
+ | NavigateToSilenceFormNew (List Matcher)
+ | NavigateToSilenceList Filter
+ | NavigateToStatus
+ | Noop
+ | RedirectAlerts
+ | UpdateFilter String
+ | BootstrapCSSLoaded (ApiData String)
+ | FontAwesomeCSSLoaded (ApiData String)
+ | SetDefaultCreator String
+
+
+type Route
+ = AlertsRoute Filter
+ | NotFoundRoute
+ | SilenceFormEditRoute String
+ | SilenceFormNewRoute (List Matcher)
+ | SilenceListRoute Filter
+ | SilenceViewRoute String
+ | StatusRoute
+ | TopLevelRoute
--- /dev/null
+module Updates exposing (update)
+
+import Navigation
+import String exposing (trim)
+import Task
+import Types
+ exposing
+ ( Model
+ , Msg(..)
+ , Route(AlertsRoute, NotFoundRoute, SilenceFormEditRoute, SilenceFormNewRoute, SilenceListRoute, SilenceViewRoute, StatusRoute)
+ )
+import Views.AlertList.Types exposing (AlertListMsg(FetchAlerts))
+import Views.AlertList.Updates
+import Views.SilenceForm.Types exposing (SilenceFormMsg(FetchSilence, NewSilenceFromMatchers))
+import Views.SilenceForm.Updates
+import Views.SilenceList.Types exposing (SilenceListMsg(FetchSilences))
+import Views.SilenceList.Updates
+import Views.SilenceView.Types exposing (SilenceViewMsg(InitSilenceView, SilenceFetched))
+import Views.SilenceView.Updates
+import Views.Status.Types exposing (StatusMsg(InitStatusView))
+import Views.Status.Updates
+
+
+update : Msg -> Model -> ( Model, Cmd Msg )
+update msg ({ basePath, apiUrl } as model) =
+ case msg of
+ NavigateToAlerts filter ->
+ let
+ ( alertList, cmd ) =
+ Views.AlertList.Updates.update FetchAlerts model.alertList filter apiUrl basePath
+ in
+ ( { model | alertList = alertList, route = AlertsRoute filter, filter = filter }, cmd )
+
+ NavigateToSilenceList filter ->
+ let
+ ( silenceList, cmd ) =
+ Views.SilenceList.Updates.update FetchSilences model.silenceList filter basePath apiUrl
+ in
+ ( { model | silenceList = silenceList, route = SilenceListRoute filter, filter = filter }
+ , Cmd.map MsgForSilenceList cmd
+ )
+
+ NavigateToStatus ->
+ ( { model | route = StatusRoute }, Task.perform identity (Task.succeed <| MsgForStatus InitStatusView) )
+
+ NavigateToSilenceView silenceId ->
+ let
+ ( silenceView, cmd ) =
+ Views.SilenceView.Updates.update (InitSilenceView silenceId) model.silenceView apiUrl
+ in
+ ( { model | route = SilenceViewRoute silenceId, silenceView = silenceView }
+ , Cmd.map MsgForSilenceView cmd
+ )
+
+ NavigateToSilenceFormNew matchers ->
+ ( { model | route = SilenceFormNewRoute matchers }
+ , Task.perform (NewSilenceFromMatchers model.defaultCreator >> MsgForSilenceForm) (Task.succeed matchers)
+ )
+
+ NavigateToSilenceFormEdit uuid ->
+ ( { model | route = SilenceFormEditRoute uuid }, Task.perform identity (Task.succeed <| (FetchSilence uuid |> MsgForSilenceForm)) )
+
+ NavigateToNotFound ->
+ ( { model | route = NotFoundRoute }, Cmd.none )
+
+ RedirectAlerts ->
+ ( model, Navigation.newUrl (basePath ++ "#/alerts") )
+
+ UpdateFilter text ->
+ let
+ t =
+ if trim text == "" then
+ Nothing
+ else
+ Just text
+
+ prevFilter =
+ model.filter
+ in
+ ( { model | filter = { prevFilter | text = t } }, Cmd.none )
+
+ Noop ->
+ ( model, Cmd.none )
+
+ MsgForStatus msg ->
+ Views.Status.Updates.update msg model apiUrl
+
+ MsgForAlertList msg ->
+ let
+ ( alertList, cmd ) =
+ Views.AlertList.Updates.update msg model.alertList model.filter apiUrl basePath
+ in
+ ( { model | alertList = alertList }, cmd )
+
+ MsgForSilenceList msg ->
+ let
+ ( silenceList, cmd ) =
+ Views.SilenceList.Updates.update msg model.silenceList model.filter basePath apiUrl
+ in
+ ( { model | silenceList = silenceList }, Cmd.map MsgForSilenceList cmd )
+
+ MsgForSilenceView msg ->
+ let
+ ( silenceView, cmd ) =
+ Views.SilenceView.Updates.update msg model.silenceView apiUrl
+ in
+ ( { model | silenceView = silenceView }, Cmd.map MsgForSilenceView cmd )
+
+ MsgForSilenceForm msg ->
+ let
+ ( silenceForm, cmd ) =
+ Views.SilenceForm.Updates.update msg model.silenceForm basePath apiUrl
+ in
+ ( { model | silenceForm = silenceForm }, cmd )
+
+ BootstrapCSSLoaded css ->
+ ( { model | bootstrapCSS = css }, Cmd.none )
+
+ FontAwesomeCSSLoaded css ->
+ ( { model | fontAwesomeCSS = css }, Cmd.none )
+
+ SetDefaultCreator name ->
+ ( { model | defaultCreator = name }, Cmd.none )
--- /dev/null
+module Utils.Api exposing (..)
+
+import Http exposing (Error(..))
+import Json.Decode as Json exposing (field)
+import Time exposing (Time)
+import Utils.Date
+import Utils.Types exposing (ApiData(..))
+
+
+map : (a -> b) -> ApiData a -> ApiData b
+map fn response =
+ case response of
+ Success value ->
+ Success (fn value)
+
+ Initial ->
+ Initial
+
+ Loading ->
+ Loading
+
+ Failure a ->
+ Failure a
+
+
+withDefault : a -> ApiData a -> a
+withDefault default response =
+ case response of
+ Success value ->
+ value
+
+ _ ->
+ default
+
+
+parseError : String -> Maybe String
+parseError =
+ Json.decodeString (field "error" Json.string) >> Result.toMaybe
+
+
+errorToString : Http.Error -> String
+errorToString err =
+ case err of
+ Timeout ->
+ "Timeout exceeded"
+
+ NetworkError ->
+ "Network error"
+
+ BadStatus resp ->
+ parseError resp.body
+ |> Maybe.withDefault (toString resp.status.code ++ " " ++ resp.status.message)
+
+ BadPayload err resp ->
+ -- OK status, unexpected payload
+ "Unexpected response from api: " ++ err
+
+ BadUrl url ->
+ "Malformed url: " ++ url
+
+
+fromResult : Result Http.Error a -> ApiData a
+fromResult result =
+ case result of
+ Err e ->
+ Failure (errorToString e)
+
+ Ok x ->
+ Success x
+
+
+send : Http.Request a -> Cmd (ApiData a)
+send =
+ Http.send fromResult
+
+
+get : String -> Json.Decoder a -> Http.Request a
+get url decoder =
+ request "GET" [] url Http.emptyBody decoder
+
+
+post : String -> Http.Body -> Json.Decoder a -> Http.Request a
+post url body decoder =
+ request "POST" [] url body decoder
+
+
+delete : String -> Json.Decoder a -> Http.Request a
+delete url decoder =
+ request "DELETE" [] url Http.emptyBody decoder
+
+
+request : String -> List Http.Header -> String -> Http.Body -> Json.Decoder a -> Http.Request a
+request method headers url body decoder =
+ Http.request
+ { method = method
+ , headers = headers
+ , url = url
+ , body = body
+ , expect = Http.expectJson decoder
+ , timeout = Nothing
+ , withCredentials = False
+ }
+
+
+iso8601Time : Json.Decoder Time
+iso8601Time =
+ Json.andThen
+ (\strTime ->
+ case Utils.Date.timeFromString strTime of
+ Ok time ->
+ Json.succeed time
+
+ Err err ->
+ Json.fail ("Could not decode time " ++ strTime ++ ": " ++ err)
+ )
+ Json.string
+
+
+makeApiUrl : String -> String
+makeApiUrl externalUrl =
+ let
+ url =
+ if String.endsWith "/" externalUrl then
+ String.dropRight 1 externalUrl
+ else
+ externalUrl
+ in
+ url ++ "/api/v1"
+
+
+defaultTimeout : Time.Time
+defaultTimeout =
+ 1000 * Time.millisecond
+
+
+(|:) : Json.Decoder (a -> b) -> Json.Decoder a -> Json.Decoder b
+(|:) =
+ -- Taken from elm-community/json-extra
+ flip (Json.map2 (|>))
--- /dev/null
+module Utils.Date exposing (..)
+
+import ISO8601
+import Parser exposing (Parser, (|.), (|=))
+import Time
+import Utils.Types as Types
+import Tuple
+import Date
+import Date.Extra.Format
+import Date.Extra.Config.Config_en_us exposing (config)
+
+
+parseDuration : String -> Result String Time.Time
+parseDuration =
+ Parser.run durationParser >> Result.mapError (always "Wrong duration format")
+
+
+durationParser : Parser Time.Time
+durationParser =
+ Parser.succeed (List.foldr (+) 0)
+ |= Parser.repeat Parser.zeroOrMore term
+ |. Parser.end
+
+
+units : List ( String, number )
+units =
+ [ ( "y", 31556926000 )
+ , ( "d", 86400000 )
+ , ( "h", 3600000 )
+ , ( "m", 60000 )
+ , ( "s", 1000 )
+ ]
+
+
+timeToString : Time.Time -> String
+timeToString =
+ round >> ISO8601.fromTime >> ISO8601.toString
+
+
+term : Parser Time.Time
+term =
+ Parser.map2 (*)
+ Parser.float
+ (units
+ |> List.map (\( unit, ms ) -> Parser.succeed ms |. Parser.symbol unit)
+ |> Parser.oneOf
+ )
+ |. Parser.ignore Parser.zeroOrMore ((==) ' ')
+
+
+durationFormat : Time.Time -> Maybe String
+durationFormat time =
+ if time >= 0 then
+ List.foldl
+ (\( unit, ms ) ( result, curr ) ->
+ ( if curr // ms == 0 then
+ result
+ else
+ result ++ toString (curr // ms) ++ unit ++ " "
+ , curr % ms
+ )
+ )
+ ( "", round time )
+ units
+ |> Tuple.first
+ |> String.trim
+ |> Just
+ else
+ Nothing
+
+
+dateFormat : Time.Time -> String
+dateFormat =
+ Date.fromTime >> (Date.Extra.Format.formatUtc config Date.Extra.Format.isoDateFormat)
+
+
+timeFormat : Time.Time -> String
+timeFormat =
+ Date.fromTime >> (Date.Extra.Format.formatUtc config Date.Extra.Format.isoTimeFormat)
+
+
+dateTimeFormat : Time.Time -> String
+dateTimeFormat t =
+ (dateFormat t) ++ " " ++ (timeFormat t)
+
+
+encode : Time.Time -> String
+encode =
+ round >> ISO8601.fromTime >> ISO8601.toString
+
+
+timeFromString : String -> Result String Time.Time
+timeFromString string =
+ if string == "" then
+ Err "Should not be empty"
+ else
+ ISO8601.fromString string
+ |> Result.map (ISO8601.toTime >> toFloat)
+ |> Result.mapError (always "Wrong ISO8601 format")
+
+
+fromTime : Time.Time -> Types.Time
+fromTime time =
+ { s = round time |> ISO8601.fromTime |> ISO8601.toString
+ , t = Just time
+ }
--- /dev/null
+module Utils.Filter
+ exposing
+ ( Matcher
+ , MatchOperator(..)
+ , Filter
+ , nullFilter
+ , generateQueryParam
+ , generateQueryString
+ , stringifyMatcher
+ , stringifyFilter
+ , stringifyGroup
+ , parseGroup
+ , parseFilter
+ , parseMatcher
+ )
+
+import Http exposing (encodeUri)
+import Parser exposing (Parser, (|.), (|=), zeroOrMore, ignore)
+import Parser.LanguageKit as Parser exposing (Trailing(..))
+import Char
+import Set
+
+
+type alias Filter =
+ { text : Maybe String
+ , group : Maybe String
+ , receiver : Maybe String
+ , showSilenced : Maybe Bool
+ , showInhibited : Maybe Bool
+ }
+
+
+nullFilter : Filter
+nullFilter =
+ { text = Nothing
+ , group = Nothing
+ , receiver = Nothing
+ , showSilenced = Nothing
+ , showInhibited = Nothing
+ }
+
+
+generateQueryParam : String -> Maybe String -> Maybe String
+generateQueryParam name =
+ Maybe.map (encodeUri >> (++) (name ++ "="))
+
+
+generateQueryString : Filter -> String
+generateQueryString { receiver, showSilenced, showInhibited, text, group } =
+ let
+ parts =
+ [ ( "silenced", Maybe.withDefault False showSilenced |> toString |> String.toLower |> Just )
+ , ( "inhibited", Maybe.withDefault False showInhibited |> toString |> String.toLower |> Just )
+ , ( "filter", emptyToNothing text )
+ , ( "receiver", emptyToNothing receiver )
+ , ( "group", group )
+ ]
+ |> List.filterMap (uncurry generateQueryParam)
+ in
+ if List.length parts > 0 then
+ parts
+ |> String.join "&"
+ |> (++) "?"
+ else
+ ""
+
+
+emptyToNothing : Maybe String -> Maybe String
+emptyToNothing str =
+ case str of
+ Just "" ->
+ Nothing
+
+ _ ->
+ str
+
+
+type alias Matcher =
+ { key : String
+ , op : MatchOperator
+ , value : String
+ }
+
+
+type MatchOperator
+ = Eq
+ | NotEq
+ | RegexMatch
+ | NotRegexMatch
+
+
+matchers : List ( String, MatchOperator )
+matchers =
+ [ ( "=~", RegexMatch )
+ , ( "!~", NotRegexMatch )
+ , ( "=", Eq )
+ , ( "!=", NotEq )
+ ]
+
+
+parseFilter : String -> Maybe (List Matcher)
+parseFilter =
+ Parser.run filter
+ >> Result.toMaybe
+
+
+parseMatcher : String -> Maybe Matcher
+parseMatcher =
+ Parser.run matcher
+ >> Result.toMaybe
+
+
+stringifyGroup : List String -> Maybe String
+stringifyGroup list =
+ if List.isEmpty list then
+ Just ""
+ else if list == [ "alertname" ] then
+ Nothing
+ else
+ Just (String.join "," list)
+
+
+parseGroup : Maybe String -> List String
+parseGroup maybeGroup =
+ case maybeGroup of
+ Nothing ->
+ [ "alertname" ]
+
+ Just something ->
+ String.split "," something
+ |> List.filter (String.length >> (<) 0)
+
+
+stringifyFilter : List Matcher -> String
+stringifyFilter matchers =
+ case matchers of
+ [] ->
+ ""
+
+ list ->
+ (list
+ |> List.map stringifyMatcher
+ |> String.join ", "
+ |> (++) "{"
+ )
+ ++ "}"
+
+
+stringifyMatcher : Matcher -> String
+stringifyMatcher { key, op, value } =
+ key
+ ++ (matchers
+ |> List.filter (Tuple.second >> (==) op)
+ |> List.head
+ |> Maybe.map Tuple.first
+ |> Maybe.withDefault ""
+ )
+ ++ "\""
+ ++ value
+ ++ "\""
+
+
+filter : Parser (List Matcher)
+filter =
+ Parser.succeed identity
+ |= Parser.record spaces item
+ |. Parser.end
+
+
+matcher : Parser Matcher
+matcher =
+ Parser.succeed identity
+ |. spaces
+ |= item
+ |. spaces
+ |. Parser.end
+
+
+item : Parser Matcher
+item =
+ Parser.succeed Matcher
+ |= Parser.variable isVarChar isVarChar Set.empty
+ |= (matchers
+ |> List.map
+ (\( keyword, matcher ) ->
+ Parser.succeed matcher
+ |. Parser.keyword keyword
+ )
+ |> Parser.oneOf
+ )
+ |= string '"'
+
+
+spaces : Parser ()
+spaces =
+ ignore zeroOrMore (\char -> char == ' ' || char == '\t')
+
+
+string : Char -> Parser String
+string separator =
+ Parser.succeed identity
+ |. Parser.symbol (String.fromChar separator)
+ |= stringContents separator
+ |. Parser.symbol (String.fromChar separator)
+
+
+stringContents : Char -> Parser String
+stringContents separator =
+ Parser.oneOf
+ [ Parser.succeed (++)
+ |= keepOne (\char -> char == '\\')
+ |= keepOne (\char -> True)
+ , Parser.keep Parser.oneOrMore (\char -> char /= separator && char /= '\\')
+ ]
+ |> Parser.repeat Parser.zeroOrMore
+ |> Parser.map (String.join "")
+
+
+isVarChar : Char -> Bool
+isVarChar char =
+ Char.isLower char
+ || Char.isUpper char
+ || (char == '_')
+ || Char.isDigit char
+
+
+keepOne : (Char -> Bool) -> Parser String
+keepOne =
+ Parser.keep (Parser.Exactly 1)
--- /dev/null
+module Utils.FormValidation
+ exposing
+ ( initialField
+ , ValidationState(..)
+ , ValidatedField
+ , validate
+ , fromResult
+ , stringNotEmpty
+ , updateValue
+ )
+
+
+type ValidationState
+ = Initial
+ | Valid
+ | Invalid String
+
+
+fromResult : Result String a -> ValidationState
+fromResult result =
+ case result of
+ Ok _ ->
+ Valid
+
+ Err str ->
+ Invalid str
+
+
+type alias ValidatedField =
+ { value : String
+ , validationState : ValidationState
+ }
+
+
+initialField : String -> ValidatedField
+initialField value =
+ { value = value
+ , validationState = Initial
+ }
+
+
+updateValue : String -> ValidatedField -> ValidatedField
+updateValue value field =
+ { field | value = value, validationState = Initial }
+
+
+validate : (String -> Result String a) -> ValidatedField -> ValidatedField
+validate validator field =
+ { field | validationState = fromResult (validator field.value) }
+
+
+stringNotEmpty : String -> Result String String
+stringNotEmpty string =
+ if String.isEmpty (String.trim string) then
+ Err "Should not be empty"
+ else
+ Ok string
--- /dev/null
+module Utils.Keyboard exposing (keys, onKeyDown, onKeyUp)
+
+import Html exposing (Attribute)
+import Html.Events exposing (on, keyCode)
+import Json.Decode as Json
+
+
+keys :
+ { backspace : Int
+ , enter : Int
+ , up : Int
+ , down : Int
+ }
+keys =
+ { backspace = 8
+ , enter = 13
+ , up = 38
+ , down = 40
+ }
+
+
+onKeyDown : (Int -> msg) -> Attribute msg
+onKeyDown tagger =
+ on "keydown" (Json.map tagger keyCode)
+
+
+onKeyUp : (Int -> msg) -> Attribute msg
+onKeyUp tagger =
+ on "keyup" (Json.map tagger keyCode)
--- /dev/null
+module Utils.List exposing (..)
+
+import Utils.Types exposing (Matchers, Matcher)
+import Dict exposing (Dict)
+
+
+nextElem : a -> List a -> Maybe a
+nextElem el list =
+ case list of
+ curr :: rest ->
+ if curr == el then
+ List.head rest
+ else
+ nextElem el rest
+
+ [] ->
+ Nothing
+
+
+lastElem : List a -> Maybe a
+lastElem =
+ List.foldl (Just >> always) Nothing
+
+
+replaceIf : (a -> Bool) -> a -> List a -> List a
+replaceIf predicate replacement list =
+ List.map
+ (\item ->
+ if predicate item then
+ replacement
+ else
+ item
+ )
+ list
+
+
+replaceIndex : Int -> (a -> a) -> List a -> List a
+replaceIndex index replacement list =
+ List.indexedMap
+ (\currentIndex item ->
+ if index == currentIndex then
+ replacement item
+ else
+ item
+ )
+ list
+
+
+mjoin : Matchers -> String
+mjoin m =
+ String.join "," (List.map mstring m)
+
+
+mstring : Matcher -> String
+mstring m =
+ let
+ sep =
+ if m.isRegex then
+ "=~"
+ else
+ "="
+ in
+ String.join sep [ m.name, toString m.value ]
+
+
+{-| Takes a key-fn and a list.
+Creates a `Dict` which maps the key to a list of matching elements.
+mary = {id=1, name="Mary"}
+jack = {id=2, name="Jack"}
+jill = {id=1, name="Jill"}
+groupBy .id [mary, jack, jill] == Dict.fromList [(1, [mary, jill]), (2, [jack])]
+
+Copied from <https://github.com/elm-community/dict-extra/blob/2.0.0/src/Dict/Extra.elm>
+
+-}
+groupBy : (a -> comparable) -> List a -> Dict comparable (List a)
+groupBy keyfn list =
+ List.foldr
+ (\x acc ->
+ Dict.update (keyfn x) (Maybe.map ((::) x) >> Maybe.withDefault [ x ] >> Just) acc
+ )
+ Dict.empty
+ list
+
+
+zip : List a -> List b -> List ( a, b )
+zip a b =
+ List.map2 (,) a b
--- /dev/null
+module Utils.Match exposing (jaro, jaroWinkler, consecutiveChars)
+
+import Utils.List exposing (zip)
+import Char
+
+
+{-|
+
+ Adapted from https://blog.art-of-coding.eu/comparing-strings-with-metrics-in-haskell/
+-}
+jaro : String -> String -> Float
+jaro s1 s2 =
+ if s1 == s2 then
+ 1.0
+ else
+ let
+ l1 =
+ String.length s1
+
+ l2 =
+ String.length s2
+
+ z2 =
+ zip (List.range 1 l2) (String.toList s2)
+ |> List.map (Tuple.mapSecond Char.toCode)
+
+ searchLength =
+ -- A character must be within searchLength spaces of the
+ -- character we are matching against in order to be considered
+ -- a match.
+ -- (//) is integer division, which removes the need to floor
+ -- the result.
+ ((max l1 l2) // 2) - 1
+
+ m =
+ zip (List.range 1 l1) (String.toList s1)
+ |> List.map (Tuple.mapSecond Char.toCode)
+ |> List.concatMap (charMatch searchLength z2)
+
+ ml =
+ List.length m
+
+ t =
+ m
+ |> List.map (transposition z2 >> toFloat >> ((*) 0.5))
+ |> List.sum
+
+ ml1 =
+ toFloat ml / toFloat l1
+
+ ml2 =
+ toFloat ml / toFloat l2
+
+ mtm =
+ (toFloat ml - t) / toFloat ml
+ in
+ if ml == 0 then
+ 0
+ else
+ (1 / 3) * (ml1 + ml2 + mtm)
+
+
+winkler : String -> String -> Float -> Float
+winkler s1 s2 jaro =
+ if s1 == "" || s2 == "" then
+ 0.0
+ else if s1 == s2 then
+ 1.0
+ else
+ let
+ l =
+ consecutiveChars s1 s2
+ |> String.length
+ |> toFloat
+
+ p =
+ 0.25
+ in
+ jaro + ((l * p) * (1.0 - jaro))
+
+
+jaroWinkler : String -> String -> Float
+jaroWinkler s1 s2 =
+ if s1 == "" || s2 == "" then
+ 0.0
+ else if s1 == s2 then
+ 1.0
+ else
+ jaro s1 s2
+ |> winkler s1 s2
+
+
+consecutiveChars : String -> String -> String
+consecutiveChars s1 s2 =
+ if s1 == "" || s2 == "" then
+ ""
+ else if s1 == s2 then
+ s1
+ else
+ cp (String.toList s1) (String.toList s2) []
+ |> String.fromList
+
+
+cp : List Char -> List Char -> List Char -> List Char
+cp l1 l2 acc =
+ case ( l1, l2 ) of
+ ( x :: xs, y :: ys ) ->
+ if x == y then
+ cp xs ys (acc ++ [ x ])
+ else if List.length acc > 0 then
+ -- If we have already found matches, we bail. We only want
+ -- consecutive matches.
+ acc
+ else
+ -- Go through every character in l1 until it matches the first
+ -- character in l2, and then start counting from there.
+ cp l1 ys acc
+
+ _ ->
+ acc
+
+
+charMatch : number -> List ( number, number ) -> ( number, number ) -> List ( number, number )
+charMatch matchRange list ( p, q ) =
+ list
+ |> List.drop (p - matchRange - 1)
+ |> List.take (p + matchRange)
+ |> List.filter (Tuple.second >> (==) q)
+
+
+transposition : List ( number, number ) -> ( number, number ) -> Int
+transposition list ( p, q ) =
+ list
+ |> List.filter
+ (\( x, y ) ->
+ p /= x && q == y
+ )
+ |> List.length
--- /dev/null
+module Utils.String exposing (capitalizeFirst, linkify)
+
+import String
+import Char
+
+
+capitalizeFirst : String -> String
+capitalizeFirst string =
+ case String.uncons string of
+ Nothing ->
+ string
+
+ Just ( char, rest ) ->
+ String.cons (Char.toUpper char) rest
+
+
+linkify : String -> List (Result String String)
+linkify string =
+ List.reverse (linkifyHelp (String.words string) [])
+
+
+linkifyHelp : List String -> List (Result String String) -> List (Result String String)
+linkifyHelp words linkified =
+ case words of
+ [] ->
+ linkified
+
+ word :: restWords ->
+ if isUrl word then
+ case linkified of
+ (Err lastWord) :: restLinkified ->
+ -- append space to last word
+ linkifyHelp restWords (Ok word :: Err (lastWord ++ " ") :: restLinkified)
+
+ (Ok lastWord) :: restLinkified ->
+ -- insert space between two links
+ linkifyHelp restWords (Ok word :: Err " " :: linkified)
+
+ _ ->
+ linkifyHelp restWords (Ok word :: linkified)
+ else
+ case linkified of
+ (Err lastWord) :: restLinkified ->
+ -- concatenate with last word
+ linkifyHelp restWords (Err (lastWord ++ " " ++ word) :: restLinkified)
+
+ (Ok lastWord) :: restLinkified ->
+ -- insert space after the link
+ linkifyHelp restWords (Err (" " ++ word) :: linkified)
+
+ _ ->
+ linkifyHelp restWords (Err word :: linkified)
+
+
+isUrl : String -> Bool
+isUrl =
+ flip String.startsWith >> (flip List.any) [ "http://", "https://" ]
--- /dev/null
+module Utils.Types exposing (..)
+
+import Time
+
+
+type ApiData a
+ = Initial
+ | Loading
+ | Failure String
+ | Success a
+
+
+type alias Matcher =
+ { isRegex : Bool
+ , name : String
+ , value : String
+ }
+
+
+type alias Matchers =
+ List Matcher
+
+
+type alias Labels =
+ List Label
+
+
+type alias Label =
+ ( String, String )
+
+
+type alias Time =
+ { t : Maybe Time.Time
+ , s : String
+ }
+
+
+type alias Duration =
+ { d : Maybe Time.Time
+ , s : String
+ }
--- /dev/null
+module Utils.Views exposing (..)
+
+import Html exposing (..)
+import Html.Attributes exposing (..)
+import Html.Events exposing (onCheck, onInput, onClick, onBlur)
+import Utils.FormValidation exposing (ValidationState(..), ValidatedField)
+import Utils.String
+
+
+tab : tab -> tab -> (tab -> msg) -> List (Html msg) -> Html msg
+tab tab currentTab msg content =
+ li [ class "nav-item" ]
+ [ if tab == currentTab then
+ span [ class "nav-link active" ] content
+ else
+ a [ class "nav-link", onClick (msg tab) ] content
+ ]
+
+
+labelButton : Maybe msg -> String -> Html msg
+labelButton maybeMsg labelText =
+ case maybeMsg of
+ Nothing ->
+ span
+ [ class "btn btn-sm bg-faded btn-secondary mr-2 mb-2"
+ , style
+ [ ( "user-select", "text" )
+ , ( "-moz-user-select", "text" )
+ , ( "-webkit-user-select", "text" )
+ ]
+ ]
+ [ text labelText ]
+
+ Just msg ->
+ button
+ [ class "btn btn-sm bg-faded btn-secondary mr-2 mb-2"
+ , onClick msg
+ ]
+ [ span [ class "text-muted" ] [ text labelText ] ]
+
+
+linkifyText : String -> List (Html msg)
+linkifyText str =
+ List.map
+ (\result ->
+ case result of
+ Ok link ->
+ a [ href link, target "_blank" ] [ text link ]
+
+ Err txt ->
+ text txt
+ )
+ (Utils.String.linkify str)
+
+
+iconButtonMsg : String -> String -> msg -> Html msg
+iconButtonMsg classString icon msg =
+ a [ class classString, onClick msg ]
+ [ i [ class <| "fa fa-3 " ++ icon ] []
+ ]
+
+
+checkbox : String -> Bool -> (Bool -> msg) -> Html msg
+checkbox name status msg =
+ label [ class "f6 dib mb2 mr2 d-flex align-items-center" ]
+ [ input [ type_ "checkbox", checked status, onCheck msg ] []
+ , span [ class "pl-2" ] [ text <| " " ++ name ]
+ ]
+
+
+validatedField : (List (Attribute msg) -> List (Html msg) -> Html msg) -> String -> String -> (String -> msg) -> msg -> ValidatedField -> Html msg
+validatedField htmlField labelText classes inputMsg blurMsg field =
+ case field.validationState of
+ Valid ->
+ div [ class <| "d-flex flex-column form-group has-success " ++ classes ]
+ [ label [] [ strong [] [ text labelText ] ]
+ , htmlField
+ [ value field.value
+ , onInput inputMsg
+ , onBlur blurMsg
+ , class "form-control form-control-success"
+ ]
+ []
+ ]
+
+ Initial ->
+ div [ class <| "d-flex flex-column form-group " ++ classes ]
+ [ label [] [ strong [] [ text labelText ] ]
+ , htmlField
+ [ value field.value
+ , onInput inputMsg
+ , onBlur blurMsg
+ , class "form-control"
+ ]
+ []
+ ]
+
+ Invalid error ->
+ div [ class <| "d-flex flex-column form-group has-danger " ++ classes ]
+ [ label [] [ strong [] [ text labelText ] ]
+ , htmlField
+ [ value field.value
+ , onInput inputMsg
+ , onBlur blurMsg
+ , class "form-control form-control-danger"
+ ]
+ []
+ , div [ class "form-control-feedback" ] [ text error ]
+ ]
+
+
+formField : String -> String -> String -> (String -> msg) -> Html msg
+formField labelText content classes msg =
+ div [ class <| "d-flex flex-column " ++ classes ]
+ [ label [] [ strong [] [ text labelText ] ]
+ , input [ value content, onInput msg ] []
+ ]
+
+
+textField : String -> String -> String -> (String -> msg) -> Html msg
+textField labelText content classes msg =
+ div [ class <| "d-flex flex-column " ++ classes ]
+ [ label [] [ strong [] [ text labelText ] ]
+ , textarea [ value content, onInput msg ] []
+ ]
+
+
+buttonLink : String -> String -> String -> msg -> Html msg
+buttonLink icon link color msg =
+ a [ class <| "" ++ color, href link, onClick msg ]
+ [ i [ class <| "" ++ icon ] []
+ ]
+
+
+formInput : String -> String -> (String -> msg) -> Html msg
+formInput inputValue classes msg =
+ Html.input [ class <| "w-100 " ++ classes, value inputValue, onInput msg ] []
+
+
+loading : Html msg
+loading =
+ div []
+ [ i [ class "fa fa-cog fa-spin fa-3x fa-fw" ] []
+ , span [ class "sr-only" ] [ text "Loading..." ]
+ ]
+
+
+error : String -> Html msg
+error err =
+ div [ class "alert alert-warning" ]
+ [ text (Utils.String.capitalizeFirst err) ]
--- /dev/null
+module Views exposing (..)
+
+import Html exposing (Html, node, text, div)
+import Html.Attributes exposing (class, rel, href, src, style)
+import Html.Events exposing (on)
+import Json.Decode exposing (succeed)
+import Types exposing (Msg(MsgForSilenceForm, MsgForSilenceView, BootstrapCSSLoaded, FontAwesomeCSSLoaded), Model, Route(..))
+import Utils.Views exposing (error, loading)
+import Utils.Types exposing (ApiData(Failure, Success))
+import Views.SilenceList.Views as SilenceList
+import Views.SilenceForm.Views as SilenceForm
+import Views.AlertList.Views as AlertList
+import Views.SilenceView.Views as SilenceView
+import Views.NotFound.Views as NotFound
+import Views.Status.Views as Status
+import Views.NavBar.Views exposing (navBar)
+
+
+view : Model -> Html Msg
+view model =
+ div []
+ [ renderCSS model.libUrl
+ , case ( model.bootstrapCSS, model.fontAwesomeCSS ) of
+ ( Success _, Success _ ) ->
+ div []
+ [ navBar model.route
+ , div [ class "container pb-4" ] [ currentView model ]
+ ]
+
+ ( Failure err, _ ) ->
+ failureView model err
+
+ ( _, Failure err ) ->
+ failureView model err
+
+ _ ->
+ text ""
+ ]
+
+
+failureView : Model -> String -> Html Msg
+failureView model err =
+ div []
+ [ div [ style [ ( "padding", "40px" ), ( "color", "red" ) ] ] [ text err ]
+ , navBar model.route
+ , div [ class "container pb-4" ] [ currentView model ]
+ ]
+
+
+renderCSS : String -> Html Msg
+renderCSS assetsUrl =
+ div []
+ [ cssNode (assetsUrl ++ "lib/bootstrap-4.0.0-alpha.6-dist/css/bootstrap.min.css") BootstrapCSSLoaded
+ , cssNode (assetsUrl ++ "lib/font-awesome-4.7.0/css/font-awesome.min.css") FontAwesomeCSSLoaded
+ ]
+
+
+cssNode : String -> (ApiData String -> Msg) -> Html Msg
+cssNode url msg =
+ node "link"
+ [ href url
+ , rel "stylesheet"
+ , on "load" (succeed (msg (Success url)))
+ , on "error" (succeed (msg (Failure ("Failed to load CSS from: " ++ url))))
+ ]
+ []
+
+
+currentView : Model -> Html Msg
+currentView model =
+ case model.route of
+ StatusRoute ->
+ Status.view model.status
+
+ SilenceViewRoute silenceId ->
+ SilenceView.view model.silenceView
+
+ AlertsRoute filter ->
+ AlertList.view model.alertList filter
+
+ SilenceListRoute _ ->
+ SilenceList.view model.silenceList
+
+ SilenceFormNewRoute matchers ->
+ SilenceForm.view Nothing matchers model.defaultCreator model.silenceForm |> Html.map MsgForSilenceForm
+
+ SilenceFormEditRoute silenceId ->
+ SilenceForm.view (Just silenceId) [] "" model.silenceForm |> Html.map MsgForSilenceForm
+
+ TopLevelRoute ->
+ Utils.Views.loading
+
+ NotFoundRoute ->
+ NotFound.view
--- /dev/null
+module Views.AlertList.AlertView exposing (view, addLabelMsg)
+
+import Alerts.Types exposing (Alert)
+import Html exposing (..)
+import Html.Attributes exposing (class, style, href, value, readonly, title)
+import Html.Events exposing (onClick)
+import Types exposing (Msg(Noop, MsgForAlertList))
+import Utils.Date
+import Views.FilterBar.Types as FilterBarTypes
+import Views.AlertList.Types exposing (AlertListMsg(MsgForFilterBar, SetActive))
+import Utils.Views
+import Utils.Filter
+import Views.SilenceForm.Parsing exposing (newSilenceFromAlertLabels)
+
+
+view : List ( String, String ) -> Maybe String -> Alert -> Html Msg
+view labels maybeActiveId alert =
+ let
+ -- remove the grouping labels, and bring the alertname to front
+ ungroupedLabels =
+ alert.labels
+ |> List.filter ((flip List.member) labels >> not)
+ |> List.partition (Tuple.first >> (==) "alertname")
+ |> uncurry (++)
+ in
+ li
+ [ -- speedup rendering in Chrome, because list-group-item className
+ -- creates a new layer in the rendering engine
+ style [ ( "position", "static" ) ]
+ , class "align-items-start list-group-item border-0 p-0 mb-4"
+ ]
+ [ div
+ [ class "w-100 mb-2 d-flex align-items-start" ]
+ [ titleView alert
+ , if List.length alert.annotations > 0 then
+ annotationsButton maybeActiveId alert
+ else
+ text ""
+ , generatorUrlButton alert.generatorUrl
+ , silenceButton alert
+ ]
+ , if maybeActiveId == Just alert.id then
+ table [ class "table w-100 mb-1" ] (List.map annotation alert.annotations)
+ else
+ text ""
+ , div [] (List.map labelButton ungroupedLabels)
+ ]
+
+
+titleView : Alert -> Html Msg
+titleView { startsAt, isInhibited } =
+ let
+ ( className, inhibited ) =
+ if isInhibited then
+ ( "text-muted", " (inhibited)" )
+ else
+ ( "", "" )
+ in
+ span
+ [ class ("align-self-center mr-2 " ++ className) ]
+ [ text
+ (Utils.Date.timeFormat startsAt
+ ++ ", "
+ ++ Utils.Date.dateFormat startsAt
+ ++ inhibited
+ )
+ ]
+
+
+annotationsButton : Maybe String -> Alert -> Html Msg
+annotationsButton maybeActiveId alert =
+ if maybeActiveId == Just alert.id then
+ button
+ [ onClick (SetActive Nothing |> MsgForAlertList)
+ , class "btn btn-outline-info border-0 active"
+ ]
+ [ i [ class "fa fa-minus mr-2" ] [], text "Info" ]
+ else
+ button
+ [ onClick (SetActive (Just alert.id) |> MsgForAlertList)
+ , class "btn btn-outline-info border-0"
+ ]
+ [ i [ class "fa fa-plus mr-2" ] [], text "Info" ]
+
+
+annotation : ( String, String ) -> Html Msg
+annotation ( key, value ) =
+ tr []
+ [ th [ class "text-nowrap" ] [ text (key ++ ":") ]
+ , td [ class "w-100" ] (Utils.Views.linkifyText value)
+ ]
+
+
+labelButton : ( String, String ) -> Html Msg
+labelButton ( key, val ) =
+ div
+ [ class "btn-group mr-2 mb-2" ]
+ [ span
+ [ class "btn btn-sm border-right-0 text-muted"
+
+ -- have to reset bootstrap button styles to make the text selectable
+ , style
+ [ ( "user-select", "initial" )
+ , ( "-moz-user-select", "initial" )
+ , ( "-webkit-user-select", "initial" )
+ , ( "border-color", "#ccc" )
+ ]
+ ]
+ [ text (key ++ "=\"" ++ val ++ "\"") ]
+ , button
+ [ class "btn btn-sm bg-faded btn-outline-secondary"
+ , onClick (addLabelMsg ( key, val ))
+ , title "Filter by this label"
+ ]
+ [ text "+" ]
+ ]
+
+
+addLabelMsg : ( String, String ) -> Msg
+addLabelMsg ( key, value ) =
+ FilterBarTypes.AddFilterMatcher False
+ { key = key
+ , op = Utils.Filter.Eq
+ , value = value
+ }
+ |> MsgForFilterBar
+ |> MsgForAlertList
+
+
+silenceButton : Alert -> Html Msg
+silenceButton alert =
+ case alert.silenceId of
+ Just sId ->
+ a
+ [ class "btn btn-outline-danger border-0"
+ , href ("#/silences/" ++ sId)
+ ]
+ [ i [ class "fa fa-bell-slash mr-2" ] []
+ , text "Silenced"
+ ]
+
+ Nothing ->
+ a
+ [ class "btn btn-outline-info border-0"
+ , href (newSilenceFromAlertLabels alert.labels)
+ ]
+ [ i [ class "fa fa-bell-slash-o mr-2" ] []
+ , text "Silence"
+ ]
+
+
+generatorUrlButton : String -> Html Msg
+generatorUrlButton url =
+ a
+ [ class "btn btn-outline-info border-0", href url ]
+ [ i [ class "fa fa-line-chart mr-2" ] []
+ , text "Source"
+ ]
--- /dev/null
+module Views.AlertList.Filter exposing (matchers)
+
+import Alerts.Types exposing (Alert, AlertGroup, Block)
+import Utils.Types exposing (Matchers)
+import Regex exposing (regex, contains)
+
+
+matchers : Maybe Utils.Types.Matchers -> List AlertGroup -> List AlertGroup
+matchers matchers alerts =
+ case matchers of
+ Just ms ->
+ by (filterAlertGroupLabels ms) alerts
+
+ Nothing ->
+ alerts
+
+
+alertsFromBlock : (Alert -> Bool) -> Block -> Maybe Block
+alertsFromBlock fn block =
+ let
+ alerts =
+ List.filter fn block.alerts
+ in
+ if not <| List.isEmpty alerts then
+ Just { block | alerts = alerts }
+ else
+ Nothing
+
+
+byLabel : Utils.Types.Matchers -> Block -> Maybe Block
+byLabel matchers block =
+ alertsFromBlock
+ (\a ->
+ -- Check that all labels are present within the alert's label set.
+ List.all
+ (\m ->
+ -- Check for regex or direct match
+ if m.isRegex then
+ -- Check if key is present, then regex match value.
+ let
+ x =
+ List.head <| List.filter (\( key, value ) -> key == m.name) a.labels
+
+ regex =
+ Regex.regex m.value
+ in
+ -- No regex match
+ case x of
+ Just ( _, value ) ->
+ Regex.contains regex value
+
+ Nothing ->
+ False
+ else
+ List.member ( m.name, m.value ) a.labels
+ )
+ matchers
+ )
+ block
+
+
+filterAlertGroupLabels : Utils.Types.Matchers -> AlertGroup -> Maybe AlertGroup
+filterAlertGroupLabels matchers alertGroup =
+ let
+ blocks =
+ List.filterMap (byLabel matchers) alertGroup.blocks
+ in
+ if not <| List.isEmpty blocks then
+ Just { alertGroup | blocks = blocks }
+ else
+ Nothing
+
+
+by : (a -> Maybe a) -> List a -> List a
+by fn groups =
+ List.filterMap fn groups
--- /dev/null
+module Views.AlertList.Parsing exposing (alertsParser)
+
+import UrlParser exposing ((</>), (<?>), Parser, int, map, oneOf, parseHash, s, string, stringParam)
+import Utils.Filter exposing (Filter, parseMatcher, MatchOperator(RegexMatch))
+
+
+boolParam : String -> UrlParser.QueryParser (Maybe Bool -> a) a
+boolParam name =
+ UrlParser.customParam name
+ (Maybe.map (String.toLower >> (/=) "false"))
+
+
+alertsParser : Parser (Filter -> a) a
+alertsParser =
+ s "alerts"
+ <?> stringParam "filter"
+ <?> stringParam "group"
+ <?> stringParam "receiver"
+ <?> boolParam "silenced"
+ <?> boolParam "inhibited"
+ |> map Filter
--- /dev/null
+module Views.AlertList.Types exposing (AlertListMsg(..), Model, Tab(..), initAlertList)
+
+import Alerts.Types exposing (Alert)
+import Utils.Types exposing (ApiData(Initial))
+import Views.FilterBar.Types as FilterBar
+import Views.GroupBar.Types as GroupBar
+import Views.ReceiverBar.Types as ReceiverBar
+
+
+type AlertListMsg
+ = AlertsFetched (ApiData (List Alert))
+ | FetchAlerts
+ | MsgForReceiverBar ReceiverBar.Msg
+ | MsgForFilterBar FilterBar.Msg
+ | MsgForGroupBar GroupBar.Msg
+ | ToggleSilenced Bool
+ | ToggleInhibited Bool
+ | SetActive (Maybe String)
+ | SetTab Tab
+
+
+type Tab
+ = FilterTab
+ | GroupTab
+
+
+type alias Model =
+ { alerts : ApiData (List Alert)
+ , receiverBar : ReceiverBar.Model
+ , groupBar : GroupBar.Model
+ , filterBar : FilterBar.Model
+ , tab : Tab
+ , activeId : Maybe String
+ }
+
+
+initAlertList : Model
+initAlertList =
+ { alerts = Initial
+ , receiverBar = ReceiverBar.initReceiverBar
+ , groupBar = GroupBar.initGroupBar
+ , filterBar = FilterBar.initFilterBar
+ , tab = FilterTab
+ , activeId = Nothing
+ }
--- /dev/null
+module Views.AlertList.Updates exposing (..)
+
+import Alerts.Api as Api
+import Views.AlertList.Types exposing (AlertListMsg(..), Model, Tab(FilterTab, GroupTab))
+import Views.FilterBar.Updates as FilterBar
+import Utils.Filter exposing (Filter, parseFilter)
+import Utils.Types exposing (ApiData(Initial, Loading, Success, Failure))
+import Types exposing (Msg(MsgForAlertList, Noop))
+import Set
+import Navigation
+import Utils.Filter exposing (generateQueryString)
+import Views.GroupBar.Updates as GroupBar
+import Views.ReceiverBar.Updates as ReceiverBar
+
+
+update : AlertListMsg -> Model -> Filter -> String -> String -> ( Model, Cmd Types.Msg )
+update msg ({ groupBar, filterBar, receiverBar } as model) filter apiUrl basePath =
+ let
+ alertsUrl =
+ basePath ++ "#/alerts"
+ in
+ case msg of
+ AlertsFetched listOfAlerts ->
+ ( { model
+ | alerts = listOfAlerts
+ , groupBar =
+ case listOfAlerts of
+ Success alerts ->
+ { groupBar
+ | list =
+ List.concatMap .labels alerts
+ |> List.map Tuple.first
+ |> Set.fromList
+ }
+
+ _ ->
+ groupBar
+ }
+ , Cmd.none
+ )
+
+ FetchAlerts ->
+ let
+ newGroupBar =
+ GroupBar.setFields filter groupBar
+
+ newFilterBar =
+ FilterBar.setMatchers filter filterBar
+ in
+ ( { model | alerts = Loading, filterBar = newFilterBar, groupBar = newGroupBar, activeId = Nothing }
+ , Cmd.batch
+ [ Api.fetchAlerts apiUrl filter |> Cmd.map (AlertsFetched >> MsgForAlertList)
+ , ReceiverBar.fetchReceivers apiUrl |> Cmd.map (MsgForReceiverBar >> MsgForAlertList)
+ ]
+ )
+
+ ToggleSilenced showSilenced ->
+ ( model
+ , Navigation.newUrl (alertsUrl ++ generateQueryString { filter | showSilenced = Just showSilenced })
+ )
+
+ ToggleInhibited showInhibited ->
+ ( model
+ , Navigation.newUrl (alertsUrl ++ generateQueryString { filter | showInhibited = Just showInhibited })
+ )
+
+ SetTab tab ->
+ ( { model | tab = tab }, Cmd.none )
+
+ MsgForFilterBar msg ->
+ let
+ ( newFilterBar, cmd ) =
+ FilterBar.update alertsUrl filter msg filterBar
+ in
+ ( { model | filterBar = newFilterBar, tab = FilterTab }, Cmd.map (MsgForFilterBar >> MsgForAlertList) cmd )
+
+ MsgForGroupBar msg ->
+ let
+ ( newGroupBar, cmd ) =
+ GroupBar.update alertsUrl filter msg groupBar
+ in
+ ( { model | groupBar = newGroupBar }, Cmd.map (MsgForGroupBar >> MsgForAlertList) cmd )
+
+ MsgForReceiverBar msg ->
+ let
+ ( newReceiverBar, cmd ) =
+ ReceiverBar.update alertsUrl filter msg receiverBar
+ in
+ ( { model | receiverBar = newReceiverBar }, Cmd.map (MsgForReceiverBar >> MsgForAlertList) cmd )
+
+ SetActive maybeId ->
+ ( { model | activeId = maybeId }, Cmd.none )
--- /dev/null
+module Views.AlertList.Views exposing (view)
+
+import Alerts.Types exposing (Alert)
+import Html exposing (..)
+import Html.Attributes exposing (..)
+import Html.Events exposing (..)
+import Types exposing (Msg(Noop, MsgForAlertList))
+import Utils.Filter exposing (Filter)
+import Views.FilterBar.Views as FilterBar
+import Views.ReceiverBar.Views as ReceiverBar
+import Utils.Types exposing (ApiData(Initial, Success, Loading, Failure), Labels)
+import Utils.Views
+import Utils.List
+import Views.AlertList.AlertView as AlertView
+import Views.GroupBar.Types as GroupBar
+import Views.AlertList.Types exposing (AlertListMsg(..), Model, Tab(..))
+import Types exposing (Msg(Noop, MsgForAlertList))
+import Views.GroupBar.Views as GroupBar
+import Dict exposing (Dict)
+
+
+renderCheckbox : String -> Maybe Bool -> (Bool -> AlertListMsg) -> Html Msg
+renderCheckbox textLabel maybeShowSilenced toggleMsg =
+ li [ class "nav-item" ]
+ [ label [ class "mt-1 ml-1 custom-control custom-checkbox" ]
+ [ input
+ [ type_ "checkbox"
+ , class "custom-control-input"
+ , checked (Maybe.withDefault False maybeShowSilenced)
+ , onCheck (toggleMsg >> MsgForAlertList)
+ ]
+ []
+ , span [ class "custom-control-indicator" ] []
+ , span [ class "custom-control-description" ] [ text textLabel ]
+ ]
+ ]
+
+
+view : Model -> Filter -> Html Msg
+view { alerts, groupBar, filterBar, receiverBar, tab, activeId } filter =
+ div []
+ [ div
+ [ class "card mb-5" ]
+ [ div [ class "card-header" ]
+ [ ul [ class "nav nav-tabs card-header-tabs" ]
+ [ Utils.Views.tab FilterTab tab (SetTab >> MsgForAlertList) [ text "Filter" ]
+ , Utils.Views.tab GroupTab tab (SetTab >> MsgForAlertList) [ text "Group" ]
+ , receiverBar
+ |> ReceiverBar.view filter.receiver
+ |> Html.map (MsgForReceiverBar >> MsgForAlertList)
+ , renderCheckbox "Silenced" filter.showSilenced ToggleSilenced
+ , renderCheckbox "Inhibited" filter.showInhibited ToggleInhibited
+ ]
+ ]
+ , div [ class "card-block" ]
+ [ case tab of
+ FilterTab ->
+ Html.map (MsgForFilterBar >> MsgForAlertList) (FilterBar.view filterBar)
+
+ GroupTab ->
+ Html.map (MsgForGroupBar >> MsgForAlertList) (GroupBar.view groupBar)
+ ]
+ ]
+ , case alerts of
+ Success alerts ->
+ alertGroups activeId filter groupBar alerts
+
+ Loading ->
+ Utils.Views.loading
+
+ Initial ->
+ Utils.Views.loading
+
+ Failure msg ->
+ Utils.Views.error msg
+ ]
+
+
+alertGroups : Maybe String -> Filter -> GroupBar.Model -> List Alert -> Html Msg
+alertGroups activeId filter { fields } alerts =
+ let
+ grouped =
+ alerts
+ |> Utils.List.groupBy
+ (.labels >> List.filter (\( key, _ ) -> List.member key fields))
+ in
+ grouped
+ |> Dict.keys
+ |> List.partition ((/=) [])
+ |> uncurry (++)
+ |> List.filterMap
+ (\labels ->
+ Maybe.map
+ (alertList activeId labels filter)
+ (Dict.get labels grouped)
+ )
+ |> (\list ->
+ if List.isEmpty list then
+ [ Utils.Views.error "No alerts found" ]
+ else
+ list
+ )
+ |> div []
+
+
+alertList : Maybe String -> Labels -> Filter -> List Alert -> Html Msg
+alertList activeId labels filter alerts =
+ div []
+ [ div []
+ (case labels of
+ [] ->
+ [ span [ class "btn btn-secondary mr-1 mb-3" ] [ text "Not grouped" ] ]
+
+ _ ->
+ List.map
+ (\( key, value ) ->
+ div [ class "btn-group mr-1 mb-3" ]
+ [ span
+ [ class "btn text-muted"
+ , style
+ [ ( "user-select", "initial" )
+ , ( "-moz-user-select", "initial" )
+ , ( "-webkit-user-select", "initial" )
+ , ( "border-color", "#5bc0de" )
+ ]
+ ]
+ [ text (key ++ "=\"" ++ value ++ "\"") ]
+ , button
+ [ class "btn btn-outline-info"
+ , onClick (AlertView.addLabelMsg ( key, value ))
+ , title "Filter by this label"
+ ]
+ [ text "+" ]
+ ]
+ )
+ labels
+ )
+ , ul [ class "list-group mb-4" ] (List.map (AlertView.view labels activeId) alerts)
+ ]
--- /dev/null
+module Views.FilterBar.Types exposing (Model, Msg(..), initFilterBar)
+
+import Utils.Filter
+
+
+type alias Model =
+ { matchers : List Utils.Filter.Matcher
+ , backspacePressed : Bool
+ , matcherText : String
+ }
+
+
+type Msg
+ = AddFilterMatcher Bool Utils.Filter.Matcher
+ | DeleteFilterMatcher Bool Utils.Filter.Matcher
+ | PressingBackspace Bool
+ | UpdateMatcherText String
+ | Noop
+
+
+{-| A note about the `backspacePressed` attribute:
+
+Holding down the backspace removes (one by one) each last character in the input,
+and the whole time sends multiple keyDown events. This is a guard so that if a user
+holds down backspace to remove the text in the input, they won't accidentally hold
+backspace too long and then delete the preceding matcher as well. So, once a user holds
+backspace to clear an input, they have to then lift up the key and press it again to
+proceed to deleting the next matcher.
+
+-}
+initFilterBar : Model
+initFilterBar =
+ { matchers = []
+ , backspacePressed = False
+ , matcherText = ""
+ }
--- /dev/null
+module Views.FilterBar.Updates exposing (update, setMatchers)
+
+import Views.FilterBar.Types exposing (Msg(..), Model)
+import Task
+import Dom
+import Navigation
+import Utils.Filter exposing (Filter, generateQueryString, stringifyFilter, parseFilter)
+
+
+update : String -> Filter -> Msg -> Model -> ( Model, Cmd Msg )
+update url filter msg model =
+ case msg of
+ AddFilterMatcher emptyMatcherText matcher ->
+ immediatelyFilter url
+ filter
+ { model
+ | matchers =
+ if List.member matcher model.matchers then
+ model.matchers
+ else
+ model.matchers ++ [ matcher ]
+ , matcherText =
+ if emptyMatcherText then
+ ""
+ else
+ model.matcherText
+ }
+
+ DeleteFilterMatcher setMatcherText matcher ->
+ immediatelyFilter url
+ filter
+ { model
+ | matchers = List.filter ((/=) matcher) model.matchers
+ , matcherText =
+ if setMatcherText then
+ Utils.Filter.stringifyMatcher matcher
+ else
+ model.matcherText
+ }
+
+ UpdateMatcherText value ->
+ ( { model | matcherText = value }, Cmd.none )
+
+ PressingBackspace isPressed ->
+ ( { model | backspacePressed = isPressed }, Cmd.none )
+
+ Noop ->
+ ( model, Cmd.none )
+
+
+immediatelyFilter : String -> Filter -> Model -> ( Model, Cmd Msg )
+immediatelyFilter url filter model =
+ let
+ newFilter =
+ { filter | text = Just (stringifyFilter model.matchers) }
+ in
+ ( { model | matchers = [] }
+ , Cmd.batch
+ [ Navigation.newUrl (url ++ generateQueryString newFilter)
+ , Dom.focus "filter-bar-matcher" |> Task.attempt (always Noop)
+ ]
+ )
+
+
+setMatchers : Filter -> Model -> Model
+setMatchers filter model =
+ { model
+ | matchers =
+ filter.text
+ |> Maybe.andThen parseFilter
+ |> Maybe.withDefault []
+ }
--- /dev/null
+module Views.FilterBar.Views exposing (view)
+
+import Html exposing (Html, Attribute, div, span, input, text, button, i, small)
+import Html.Attributes exposing (value, class, style, disabled, id)
+import Html.Events exposing (onClick, onInput, on, keyCode)
+import Utils.Filter exposing (Matcher)
+import Utils.List
+import Utils.Keyboard exposing (keys, onKeyUp, onKeyDown)
+import Views.FilterBar.Types exposing (Msg(..), Model)
+
+
+keys :
+ { backspace : Int
+ , enter : Int
+ }
+keys =
+ { backspace = 8
+ , enter = 13
+ }
+
+
+viewMatcher : Matcher -> Html Msg
+viewMatcher matcher =
+ div [ class "col col-auto" ]
+ [ div [ class "btn-group mr-2 mb-2" ]
+ [ button
+ [ class "btn btn-outline-info"
+ , onClick (DeleteFilterMatcher True matcher)
+ ]
+ [ text <| Utils.Filter.stringifyMatcher matcher
+ ]
+ , button
+ [ class "btn btn-outline-danger"
+ , onClick (DeleteFilterMatcher False matcher)
+ ]
+ [ text "×" ]
+ ]
+ ]
+
+
+viewMatchers : List Matcher -> List (Html Msg)
+viewMatchers matchers =
+ matchers
+ |> List.map viewMatcher
+
+
+view : Model -> Html Msg
+view { matchers, matcherText, backspacePressed } =
+ let
+ maybeMatcher =
+ Utils.Filter.parseMatcher matcherText
+
+ maybeLastMatcher =
+ Utils.List.lastElem matchers
+
+ className =
+ if matcherText == "" then
+ ""
+ else
+ case maybeMatcher of
+ Just _ ->
+ "has-success"
+
+ Nothing ->
+ "has-danger"
+
+ keyDown key =
+ if key == keys.enter then
+ maybeMatcher
+ |> Maybe.map (AddFilterMatcher True)
+ |> Maybe.withDefault Noop
+ else if key == keys.backspace then
+ if matcherText == "" then
+ case ( backspacePressed, maybeLastMatcher ) of
+ ( False, Just lastMatcher ) ->
+ DeleteFilterMatcher True lastMatcher
+
+ _ ->
+ Noop
+ else
+ PressingBackspace True
+ else
+ Noop
+
+ keyUp key =
+ if key == keys.backspace then
+ PressingBackspace False
+ else
+ Noop
+
+ onClickAttr =
+ maybeMatcher
+ |> Maybe.map (AddFilterMatcher True)
+ |> Maybe.withDefault Noop
+ |> onClick
+
+ isDisabled =
+ maybeMatcher == Nothing
+ in
+ div
+ [ class "row no-gutters align-items-start" ]
+ (viewMatchers matchers
+ ++ [ div
+ [ class ("col " ++ className)
+ , style [ ( "min-width", "200px" ) ]
+ ]
+ [ div [ class "input-group" ]
+ [ input
+ [ id "filter-bar-matcher"
+ , class "form-control"
+ , value matcherText
+ , onKeyDown keyDown
+ , onKeyUp keyUp
+ , onInput UpdateMatcherText
+ ]
+ []
+ , span
+ [ class "input-group-btn" ]
+ [ button [ class "btn btn-primary", disabled isDisabled, onClickAttr ] [ text "+" ] ]
+ ]
+ , small [ class "form-text text-muted" ]
+ [ text "Custom matcher, e.g."
+ , button
+ [ class "btn btn-link btn-sm align-baseline"
+ , onClick (UpdateMatcherText exampleMatcher)
+ ]
+ [ text exampleMatcher ]
+ ]
+ ]
+ ]
+ )
+
+
+exampleMatcher : String
+exampleMatcher =
+ "env=\"production\""
--- /dev/null
+module Views.GroupBar.Types exposing (Model, Msg(..), initGroupBar)
+
+import Set exposing (Set)
+
+
+type alias Model =
+ { list : Set String
+ , fieldText : String
+ , fields : List String
+ , matches : List String
+ , backspacePressed : Bool
+ , focused : Bool
+ , resultsHovered : Bool
+ , maybeSelectedMatch : Maybe String
+ }
+
+
+type Msg
+ = AddField Bool String
+ | DeleteField Bool String
+ | Select (Maybe String)
+ | PressingBackspace Bool
+ | Focus Bool
+ | ResultsHovered Bool
+ | UpdateFieldText String
+ | Noop
+
+
+initGroupBar : Model
+initGroupBar =
+ { list = Set.empty
+ , fieldText = ""
+ , fields = []
+ , matches = []
+ , focused = False
+ , resultsHovered = False
+ , backspacePressed = False
+ , maybeSelectedMatch = Nothing
+ }
--- /dev/null
+module Views.GroupBar.Updates exposing (update, setFields)
+
+import Views.GroupBar.Types exposing (Model, Msg(..))
+import Utils.Match exposing (jaroWinkler)
+import Task
+import Dom
+import Set
+import Utils.Filter exposing (Filter, generateQueryString, stringifyGroup, parseGroup)
+import Navigation
+
+
+update : String -> Filter -> Msg -> Model -> ( Model, Cmd Msg )
+update url filter msg model =
+ case msg of
+ AddField emptyFieldText text ->
+ immediatelyFilter url
+ filter
+ { model
+ | fields = model.fields ++ [ text ]
+ , matches = []
+ , fieldText =
+ if emptyFieldText then
+ ""
+ else
+ model.fieldText
+ }
+
+ DeleteField setFieldText text ->
+ immediatelyFilter url
+ filter
+ { model
+ | fields = List.filter ((/=) text) model.fields
+ , matches = []
+ , fieldText =
+ if setFieldText then
+ text
+ else
+ model.fieldText
+ }
+
+ Select maybeSelectedMatch ->
+ ( { model | maybeSelectedMatch = maybeSelectedMatch }, Cmd.none )
+
+ Focus focused ->
+ ( { model
+ | focused = focused
+ , maybeSelectedMatch = Nothing
+ }
+ , Cmd.none
+ )
+
+ ResultsHovered resultsHovered ->
+ ( { model
+ | resultsHovered = resultsHovered
+ }
+ , Cmd.none
+ )
+
+ PressingBackspace pressed ->
+ ( { model | backspacePressed = pressed }, Cmd.none )
+
+ UpdateFieldText text ->
+ updateAutoComplete
+ { model
+ | fieldText = text
+ }
+
+ Noop ->
+ ( model, Cmd.none )
+
+
+immediatelyFilter : String -> Filter -> Model -> ( Model, Cmd Msg )
+immediatelyFilter url filter model =
+ let
+ newFilter =
+ { filter | group = stringifyGroup model.fields }
+ in
+ ( model
+ , Cmd.batch
+ [ Navigation.newUrl (url ++ generateQueryString newFilter)
+ , Dom.focus "group-by-field" |> Task.attempt (always Noop)
+ ]
+ )
+
+
+setFields : Filter -> Model -> Model
+setFields filter model =
+ { model
+ | fields =
+ parseGroup filter.group
+ }
+
+
+updateAutoComplete : Model -> ( Model, Cmd Msg )
+updateAutoComplete model =
+ ( { model
+ | matches =
+ if String.isEmpty model.fieldText then
+ []
+ else if String.contains " " model.fieldText then
+ model.matches
+ else
+ -- TODO: How many matches do we want to show?
+ -- NOTE: List.reverse is used because our scale is (0.0, 1.0),
+ -- but we want the higher values to be in the front of the
+ -- list.
+ Set.toList model.list
+ |> List.filter ((flip List.member model.fields) >> not)
+ |> List.sortBy (jaroWinkler model.fieldText)
+ |> List.reverse
+ |> List.take 10
+ , maybeSelectedMatch = Nothing
+ }
+ , Cmd.none
+ )
--- /dev/null
+module Views.GroupBar.Views exposing (view)
+
+import Views.GroupBar.Types exposing (Msg(..), Model)
+import Html exposing (Html, Attribute, div, span, input, text, button, i, small, ul, li, a)
+import Html.Attributes exposing (value, class, style, disabled, id, href)
+import Html.Events exposing (onClick, onInput, on, keyCode, onFocus, onBlur, onMouseEnter, onMouseLeave)
+import Set
+import Utils.List
+import Utils.Keyboard exposing (keys, onKeyUp, onKeyDown)
+
+
+view : Model -> Html Msg
+view ({ list, fieldText, fields } as model) =
+ let
+ isDisabled =
+ not (Set.member fieldText list) || List.member fieldText fields
+
+ className =
+ if String.isEmpty fieldText then
+ ""
+ else if isDisabled then
+ "has-danger"
+ else
+ "has-success"
+ in
+ div
+ [ class "row no-gutters align-items-start" ]
+ (List.map viewField fields
+ ++ [ div
+ [ class ("col " ++ className)
+ , style [ ( "min-width", "200px" ) ]
+ ]
+ [ textInputField isDisabled model
+ , exampleField fields
+ , autoCompleteResults model
+ ]
+ ]
+ )
+
+
+exampleField : List String -> Html Msg
+exampleField fields =
+ if List.member "alertname" fields then
+ small [ class "form-text text-muted" ]
+ [ text "Label key for grouping alerts"
+ ]
+ else
+ small [ class "form-text text-muted" ]
+ [ text "Label key for grouping alerts, e.g."
+ , button
+ [ class "btn btn-link btn-sm align-baseline"
+ , onClick (UpdateFieldText "alertname")
+ ]
+ [ text "alertname" ]
+ ]
+
+
+textInputField : Bool -> Model -> Html Msg
+textInputField isDisabled { fieldText, matches, maybeSelectedMatch, fields, backspacePressed } =
+ let
+ onClickMsg =
+ if isDisabled then
+ Noop
+ else
+ AddField True fieldText
+
+ nextMatch =
+ maybeSelectedMatch
+ |> Maybe.map (flip Utils.List.nextElem <| matches)
+ |> Maybe.withDefault (List.head matches)
+
+ prevMatch =
+ maybeSelectedMatch
+ |> Maybe.map (flip Utils.List.nextElem <| List.reverse matches)
+ |> Maybe.withDefault (Utils.List.lastElem matches)
+
+ keyDown key =
+ if key == keys.down then
+ Select nextMatch
+ else if key == keys.up then
+ Select prevMatch
+ else if key == keys.enter then
+ if not isDisabled then
+ AddField True fieldText
+ else
+ maybeSelectedMatch
+ |> Maybe.map (AddField True)
+ |> Maybe.withDefault Noop
+ else if key == keys.backspace then
+ if fieldText == "" then
+ case ( Utils.List.lastElem fields, backspacePressed ) of
+ ( Just lastField, False ) ->
+ DeleteField True lastField
+
+ _ ->
+ Noop
+ else
+ PressingBackspace True
+ else
+ Noop
+
+ keyUp key =
+ if key == keys.backspace then
+ PressingBackspace False
+ else
+ Noop
+ in
+ div [ class "input-group" ]
+ [ input
+ [ id "group-by-field"
+ , class "form-control"
+ , value fieldText
+ , onKeyDown keyDown
+ , onKeyUp keyUp
+ , onInput UpdateFieldText
+ , onFocus (Focus True)
+ , onBlur (Focus False)
+ ]
+ []
+ , span
+ [ class "input-group-btn" ]
+ [ button [ class "btn btn-primary", disabled isDisabled, onClick onClickMsg ] [ text "+" ] ]
+ ]
+
+
+autoCompleteResults : Model -> Html Msg
+autoCompleteResults { maybeSelectedMatch, focused, resultsHovered, matches } =
+ let
+ autoCompleteClass =
+ if (focused || resultsHovered) && not (List.isEmpty matches) then
+ "show"
+ else
+ ""
+ in
+ div
+ [ class ("autocomplete-menu " ++ autoCompleteClass)
+ , onMouseEnter (ResultsHovered True)
+ , onMouseLeave (ResultsHovered False)
+ ]
+ [ matches
+ |> List.map (matchedField maybeSelectedMatch)
+ |> div [ class "dropdown-menu" ]
+ ]
+
+
+matchedField : Maybe String -> String -> Html Msg
+matchedField maybeSelectedMatch field =
+ let
+ className =
+ if maybeSelectedMatch == Just field then
+ "active"
+ else
+ ""
+ in
+ button
+ [ class ("dropdown-item " ++ className)
+ , onClick (AddField True field)
+ ]
+ [ text field ]
+
+
+viewField : String -> Html Msg
+viewField field =
+ div [ class "col col-auto" ]
+ [ div [ class "btn-group mr-2 mb-2" ]
+ [ button
+ [ class "btn btn-outline-info"
+ , onClick (DeleteField True field)
+ ]
+ [ text field
+ ]
+ , button
+ [ class "btn btn-outline-danger"
+ , onClick (DeleteField False field)
+ ]
+ [ text "×" ]
+ ]
+ ]
--- /dev/null
+module Views.NavBar.Types exposing (Tab, alertsTab, silencesTab, statusTab, noneTab, tabs)
+
+
+type alias Tab =
+ { link : String
+ , name : String
+ }
+
+
+alertsTab : Tab
+alertsTab =
+ { link = "#/alerts", name = "Alerts" }
+
+
+silencesTab : Tab
+silencesTab =
+ { link = "#/silences", name = "Silences" }
+
+
+statusTab : Tab
+statusTab =
+ { link = "#/status", name = "Status" }
+
+
+noneTab : Tab
+noneTab =
+ { link = "", name = "" }
+
+
+tabs : List Tab
+tabs =
+ [ alertsTab, silencesTab, statusTab ]
--- /dev/null
+module Views.NavBar.Views exposing (navBar)
+
+import Html exposing (Html, header, text, a, nav, ul, li, div)
+import Html.Attributes exposing (class, href, title, style)
+import Types exposing (Route(..))
+import Views.NavBar.Types exposing (Tab, alertsTab, silencesTab, statusTab, noneTab, tabs)
+
+
+navBar : Route -> Html msg
+navBar currentRoute =
+ header
+ [ class "navbar navbar-toggleable-md navbar-light bg-faded mb-5 pt-3 pb-3"
+ , style [ ( "border-bottom", "1px solid rgba(0, 0, 0, .125)" ) ]
+ ]
+ [ nav [ class "container" ]
+ [ a [ class "navbar-brand", href "#" ] [ text "Alertmanager" ]
+ , ul [ class "navbar-nav" ] (navBarItems currentRoute)
+ , case currentRoute of
+ SilenceFormEditRoute _ ->
+ text ""
+
+ SilenceFormNewRoute _ ->
+ text ""
+
+ _ ->
+ div [ class "form-inline ml-auto" ]
+ [ a
+ [ class "btn btn-outline-info"
+ , href "#/silences/new"
+ ]
+ [ text "New Silence" ]
+ ]
+ ]
+ ]
+
+
+navBarItems : Route -> List (Html msg)
+navBarItems currentRoute =
+ List.map (navBarItem currentRoute) tabs
+
+
+navBarItem : Route -> Tab -> Html msg
+navBarItem currentRoute tab =
+ li [ class <| "nav-item" ++ (isActive currentRoute tab) ]
+ [ a [ class "nav-link", href tab.link, title tab.name ]
+ [ text tab.name ]
+ ]
+
+
+isActive : Route -> Tab -> String
+isActive currentRoute tab =
+ if routeToTab currentRoute == tab then
+ " active"
+ else
+ ""
+
+
+routeToTab : Route -> Tab
+routeToTab currentRoute =
+ case currentRoute of
+ AlertsRoute _ ->
+ alertsTab
+
+ NotFoundRoute ->
+ noneTab
+
+ SilenceFormEditRoute _ ->
+ silencesTab
+
+ SilenceFormNewRoute _ ->
+ silencesTab
+
+ SilenceListRoute _ ->
+ silencesTab
+
+ SilenceViewRoute _ ->
+ silencesTab
+
+ StatusRoute ->
+ statusTab
+
+ TopLevelRoute ->
+ noneTab
--- /dev/null
+module Views.NotFound.Views exposing (view)
+
+import Html exposing (Html, div, h1, text)
+import Types exposing (Msg)
+
+
+view : Html Msg
+view =
+ div []
+ [ h1 [] [ text "not found" ]
+ ]
--- /dev/null
+module Views.ReceiverBar.Types exposing (Model, Msg(..), initReceiverBar)
+
+import Utils.Types exposing (ApiData(Initial))
+import Alerts.Types exposing (Receiver)
+
+
+type Msg
+ = ReceiversFetched (ApiData (List Receiver))
+ | UpdateReceiver String
+ | EditReceivers
+ | FilterByReceiver String
+ | Select (Maybe Receiver)
+ | ResultsHovered Bool
+ | BlurReceiverField
+ | Noop
+
+
+type alias Model =
+ { receivers : List Receiver
+ , matches : List Receiver
+ , fieldText : String
+ , selectedReceiver : Maybe Receiver
+ , showReceivers : Bool
+ , resultsHovered : Bool
+ }
+
+
+initReceiverBar : Model
+initReceiverBar =
+ { receivers = []
+ , matches = []
+ , fieldText = ""
+ , selectedReceiver = Nothing
+ , showReceivers = False
+ , resultsHovered = False
+ }
--- /dev/null
+module Views.ReceiverBar.Updates exposing (update, fetchReceivers)
+
+import Views.ReceiverBar.Types exposing (Model, Msg(..))
+import Utils.Types exposing (ApiData(Success))
+import Utils.Filter exposing (Filter, generateQueryString, stringifyGroup, parseGroup)
+import Navigation
+import Dom
+import Task
+import Alerts.Api as Api
+import Utils.Match exposing (jaroWinkler)
+
+
+update : String -> Filter -> Msg -> Model -> ( Model, Cmd Msg )
+update url filter msg model =
+ case msg of
+ ReceiversFetched (Success receivers) ->
+ ( { model | receivers = receivers }, Cmd.none )
+
+ ReceiversFetched _ ->
+ ( model, Cmd.none )
+
+ EditReceivers ->
+ ( { model
+ | showReceivers = True
+ , fieldText = ""
+ , matches =
+ model.receivers
+ |> List.take 10
+ |> (::) { name = "All", regex = "" }
+ , selectedReceiver = Nothing
+ }
+ , Dom.focus "receiver-field" |> Task.attempt (always Noop)
+ )
+
+ ResultsHovered resultsHovered ->
+ ( { model | resultsHovered = resultsHovered }, Cmd.none )
+
+ UpdateReceiver receiver ->
+ let
+ matches =
+ model.receivers
+ |> List.sortBy (.name >> jaroWinkler receiver)
+ |> List.reverse
+ |> List.take 10
+ |> (::) { name = "All", regex = "" }
+ in
+ ( { model
+ | fieldText = receiver
+ , matches = matches
+ }
+ , Cmd.none
+ )
+
+ BlurReceiverField ->
+ ( { model | showReceivers = False }, Cmd.none )
+
+ Select maybeReceiver ->
+ ( { model | selectedReceiver = maybeReceiver }, Cmd.none )
+
+ FilterByReceiver regex ->
+ ( { model | showReceivers = False, resultsHovered = False }
+ , Navigation.newUrl
+ (url
+ ++ generateQueryString
+ { filter
+ | receiver =
+ if regex == "" then
+ Nothing
+ else
+ Just regex
+ }
+ )
+ )
+
+ Noop ->
+ ( model, Cmd.none )
+
+
+fetchReceivers : String -> Cmd Msg
+fetchReceivers =
+ Api.fetchReceivers >> Cmd.map ReceiversFetched
--- /dev/null
+module Views.ReceiverBar.Views exposing (view)
+
+import Html exposing (Html, li, div, text, input)
+import Html.Attributes exposing (class, style, tabindex, value, id)
+import Html.Events exposing (onBlur, onClick, onInput, onMouseEnter, onMouseLeave)
+import Views.ReceiverBar.Types exposing (Model, Msg(..))
+import Alerts.Types exposing (Receiver)
+import Utils.Keyboard exposing (keys, onKeyUp, onKeyDown)
+import Utils.List
+
+
+view : Maybe String -> Model -> Html Msg
+view maybeRegex model =
+ if model.showReceivers || model.resultsHovered then
+ viewDropdown model
+ else
+ viewResult maybeRegex model.receivers
+
+
+viewResult : Maybe String -> List Receiver -> Html Msg
+viewResult maybeRegex receivers =
+ let
+ unescapedReceiver =
+ receivers
+ |> List.filter (.regex >> Just >> (==) maybeRegex)
+ |> List.map (.name >> Just)
+ |> List.head
+ |> Maybe.withDefault maybeRegex
+ in
+ li
+ [ class ("nav-item ml-auto")
+ , tabindex 1
+ , style
+ [ ( "position", "relative" )
+ , ( "outline", "none" )
+ ]
+ ]
+ [ div
+ [ onClick EditReceivers
+ , class "mt-1 mr-4"
+ , style [ ( "cursor", "pointer" ) ]
+ ]
+ [ text ("Receiver: " ++ Maybe.withDefault "All" unescapedReceiver) ]
+ ]
+
+
+viewDropdown : Model -> Html Msg
+viewDropdown { matches, fieldText, selectedReceiver } =
+ let
+ nextMatch =
+ selectedReceiver
+ |> Maybe.map (flip Utils.List.nextElem <| matches)
+ |> Maybe.withDefault (List.head matches)
+
+ prevMatch =
+ selectedReceiver
+ |> Maybe.map (flip Utils.List.nextElem <| List.reverse matches)
+ |> Maybe.withDefault (Utils.List.lastElem matches)
+
+ keyDown key =
+ if key == keys.down then
+ Select nextMatch
+ else if key == keys.up then
+ Select prevMatch
+ else if key == keys.enter then
+ selectedReceiver
+ |> Maybe.map .regex
+ |> Maybe.withDefault fieldText
+ |> FilterByReceiver
+ else
+ Noop
+ in
+ li
+ [ class ("nav-item ml-auto mr-4 autocomplete-menu show")
+ , onMouseEnter (ResultsHovered True)
+ , onMouseLeave (ResultsHovered False)
+ , style
+ [ ( "position", "relative" )
+ , ( "outline", "none" )
+ ]
+ ]
+ [ input
+ [ id "receiver-field"
+ , value fieldText
+ , onBlur BlurReceiverField
+ , onInput UpdateReceiver
+ , onKeyDown keyDown
+ , class "mr-4"
+ , style
+ [ ( "display", "block" )
+ , ( "width", "100%" )
+ ]
+ ]
+ []
+ , matches
+ |> List.map (receiverField selectedReceiver)
+ |> div [ class "dropdown-menu dropdown-menu-right" ]
+ ]
+
+
+receiverField : Maybe Receiver -> Receiver -> Html Msg
+receiverField selected receiver =
+ let
+ attrs =
+ if selected == Just receiver then
+ [ class "dropdown-item active" ]
+ else
+ [ class "dropdown-item"
+ , style [ ( "cursor", "pointer" ) ]
+ , onClick (FilterByReceiver receiver.regex)
+ ]
+ in
+ div attrs [ text receiver.name ]
--- /dev/null
+module Views.Shared.AlertCompact exposing (view)
+
+import Alerts.Types exposing (Alert)
+import Html exposing (Html, span, div, text, li)
+import Html.Attributes exposing (class)
+import Utils.Views exposing (labelButton)
+
+
+view : Alert -> Html msg
+view alert =
+ li [ class "mb2 w-80-l w-100-m" ] <|
+ List.map
+ (\( key, value ) ->
+ labelButton Nothing (key ++ "=" ++ value)
+ )
+ alert.labels
--- /dev/null
+module Views.Shared.AlertListCompact exposing (view)
+
+import Alerts.Types exposing (Alert)
+import Html exposing (Html, ol)
+import Html.Attributes exposing (class)
+import Views.Shared.AlertCompact
+
+
+view : List Alert -> Html msg
+view alerts =
+ List.map Views.Shared.AlertCompact.view alerts
+ |> ol [ class "list pa0 w-100" ]
--- /dev/null
+module Views.Shared.SilencePreview exposing (view)
+
+import Alerts.Types exposing (Alert)
+import Html exposing (Html, div, p, strong, text)
+import Html.Attributes exposing (class)
+import Utils.Types exposing (ApiData(Failure, Initial, Loading, Success))
+import Utils.Views exposing (loading)
+import Views.Shared.AlertListCompact
+
+
+view : ApiData (List Alert) -> Html msg
+view alertsResponse =
+ case alertsResponse of
+ Success alerts ->
+ if List.isEmpty alerts then
+ div [ class "w-100" ]
+ [ p [] [ strong [] [ text "No silenced alerts" ] ] ]
+ else
+ div [ class "w-100" ]
+ [ p [] [ strong [] [ text ("Silenced alerts: " ++ toString (List.length alerts)) ] ]
+ , Views.Shared.AlertListCompact.view alerts
+ ]
+
+ Initial ->
+ text ""
+
+ Loading ->
+ loading
+
+ Failure e ->
+ div [ class "alert alert-warning" ] [ text e ]
--- /dev/null
+module Views.SilenceForm.Parsing exposing (newSilenceFromAlertLabels, silenceFormNewParser, silenceFormEditParser)
+
+import UrlParser exposing (Parser, s, (</>), (<?>), string, stringParam, oneOf, map)
+import Utils.Filter exposing (parseFilter, Matcher)
+import Http exposing (encodeUri)
+
+
+newSilenceFromAlertLabels : List ( String, String ) -> String
+newSilenceFromAlertLabels labels =
+ labels
+ |> List.map (\( k, v ) -> Utils.Filter.Matcher k Utils.Filter.Eq v)
+ |> Utils.Filter.stringifyFilter
+ |> encodeUri
+ |> (++) "#/silences/new?filter="
+
+
+silenceFormNewParser : Parser (List Matcher -> a) a
+silenceFormNewParser =
+ s "silences"
+ </> s "new"
+ <?> stringParam "filter"
+ |> map (Maybe.andThen parseFilter >> Maybe.withDefault [])
+
+
+silenceFormEditParser : Parser (String -> a) a
+silenceFormEditParser =
+ s "silences" </> string </> s "edit"
--- /dev/null
+module Views.SilenceForm.Types
+ exposing
+ ( SilenceFormMsg(..)
+ , SilenceFormFieldMsg(..)
+ , Model
+ , SilenceForm
+ , MatcherForm
+ , fromMatchersAndTime
+ , fromSilence
+ , toSilence
+ , initSilenceForm
+ , emptyMatcher
+ , validateForm
+ , parseEndsAt
+ )
+
+import Silences.Types exposing (Silence, SilenceId, nullSilence)
+import Alerts.Types exposing (Alert)
+import Utils.Types exposing (Matcher, Duration, ApiData(..))
+import Time exposing (Time)
+import Utils.Date exposing (timeFromString, timeToString, durationFormat, parseDuration)
+import Time exposing (Time)
+import Utils.Filter
+import Utils.FormValidation
+ exposing
+ ( initialField
+ , ValidationState(..)
+ , ValidatedField
+ , validate
+ , stringNotEmpty
+ )
+
+
+type alias Model =
+ { form : SilenceForm
+ , silenceId : ApiData String
+ , alerts : ApiData (List Alert)
+ }
+
+
+type alias SilenceForm =
+ { id : String
+ , createdBy : ValidatedField
+ , comment : ValidatedField
+ , startsAt : ValidatedField
+ , endsAt : ValidatedField
+ , duration : ValidatedField
+ , matchers : List MatcherForm
+ }
+
+
+type alias MatcherForm =
+ { name : ValidatedField
+ , value : ValidatedField
+ , isRegex : Bool
+ }
+
+
+type SilenceFormMsg
+ = UpdateField SilenceFormFieldMsg
+ | CreateSilence
+ | PreviewSilence
+ | AlertGroupsPreview (ApiData (List Alert))
+ | FetchSilence String
+ | NewSilenceFromMatchers String (List Utils.Filter.Matcher)
+ | NewSilenceFromMatchersAndTime String (List Utils.Filter.Matcher) Time
+ | SilenceFetch (ApiData Silence)
+ | SilenceCreate (ApiData SilenceId)
+
+
+type SilenceFormFieldMsg
+ = AddMatcher
+ | DeleteMatcher Int
+ | UpdateStartsAt String
+ | UpdateEndsAt String
+ | UpdateDuration String
+ | ValidateTime
+ | UpdateCreatedBy String
+ | ValidateCreatedBy
+ | UpdateComment String
+ | ValidateComment
+ | UpdateMatcherName Int String
+ | ValidateMatcherName Int
+ | UpdateMatcherValue Int String
+ | ValidateMatcherValue Int
+ | UpdateMatcherRegex Int Bool
+
+
+initSilenceForm : Model
+initSilenceForm =
+ { form = empty
+ , silenceId = Utils.Types.Initial
+ , alerts = Utils.Types.Initial
+ }
+
+
+toSilence : SilenceForm -> Maybe Silence
+toSilence { id, comment, matchers, createdBy, startsAt, endsAt } =
+ Result.map5
+ (\nonEmptyComment validMatchers nonEmptyCreatedBy parsedStartsAt parsedEndsAt ->
+ { nullSilence
+ | id = id
+ , comment = nonEmptyComment
+ , matchers = validMatchers
+ , createdBy = nonEmptyCreatedBy
+ , startsAt = parsedStartsAt
+ , endsAt = parsedEndsAt
+ }
+ )
+ (stringNotEmpty comment.value)
+ (List.foldr appendMatcher (Ok []) matchers)
+ (stringNotEmpty createdBy.value)
+ (timeFromString startsAt.value)
+ (parseEndsAt startsAt.value endsAt.value)
+ |> Result.toMaybe
+
+
+fromSilence : Silence -> SilenceForm
+fromSilence { id, createdBy, comment, startsAt, endsAt, matchers } =
+ { id = id
+ , createdBy = initialField createdBy
+ , comment = initialField comment
+ , startsAt = initialField (timeToString startsAt)
+ , endsAt = initialField (timeToString endsAt)
+ , duration = initialField (durationFormat (endsAt - startsAt) |> Maybe.withDefault "")
+ , matchers = List.map fromMatcher matchers
+ }
+
+
+validateForm : SilenceForm -> SilenceForm
+validateForm { id, createdBy, comment, startsAt, endsAt, duration, matchers } =
+ { id = id
+ , createdBy = validate stringNotEmpty createdBy
+ , comment = validate stringNotEmpty comment
+ , startsAt = validate timeFromString startsAt
+ , endsAt = validate (parseEndsAt startsAt.value) endsAt
+ , duration = validate parseDuration duration
+ , matchers = List.map validateMatcherForm matchers
+ }
+
+
+parseEndsAt : String -> String -> Result String Time.Time
+parseEndsAt startsAt endsAt =
+ case ( timeFromString startsAt, timeFromString endsAt ) of
+ ( Ok starts, Ok ends ) ->
+ if starts > ends then
+ Err "Can't be in the past"
+ else
+ Ok ends
+
+ ( _, endsResult ) ->
+ endsResult
+
+
+validateMatcherForm : MatcherForm -> MatcherForm
+validateMatcherForm { name, value, isRegex } =
+ { name = validate stringNotEmpty name
+ , value = value
+ , isRegex = isRegex
+ }
+
+
+empty : SilenceForm
+empty =
+ { id = ""
+ , createdBy = initialField ""
+ , comment = initialField ""
+ , startsAt = initialField ""
+ , endsAt = initialField ""
+ , duration = initialField ""
+ , matchers = []
+ }
+
+
+emptyMatcher : MatcherForm
+emptyMatcher =
+ { isRegex = False
+ , name = initialField ""
+ , value = initialField ""
+ }
+
+
+defaultDuration : Time
+defaultDuration =
+ 2 * Time.hour
+
+
+fromMatchersAndTime : String -> List Utils.Filter.Matcher -> Time -> SilenceForm
+fromMatchersAndTime defaultCreator matchers now =
+ { empty
+ | startsAt = initialField (timeToString now)
+ , endsAt = initialField (timeToString (now + defaultDuration))
+ , duration = initialField (durationFormat defaultDuration |> Maybe.withDefault "")
+ , createdBy = initialField defaultCreator
+ , matchers =
+ -- If no matchers were specified, add an empty row
+ if List.isEmpty matchers then
+ [ emptyMatcher ]
+ else
+ List.filterMap (filterMatcherToMatcher >> Maybe.map fromMatcher) matchers
+ }
+
+
+appendMatcher : MatcherForm -> Result String (List Matcher) -> Result String (List Matcher)
+appendMatcher { isRegex, name, value } =
+ Result.map2 (::)
+ (Result.map2 (Matcher isRegex) (stringNotEmpty name.value) (Ok value.value))
+
+
+filterMatcherToMatcher : Utils.Filter.Matcher -> Maybe Matcher
+filterMatcherToMatcher { key, op, value } =
+ Maybe.map (\op -> Matcher op key value) <|
+ case op of
+ Utils.Filter.Eq ->
+ Just False
+
+ Utils.Filter.RegexMatch ->
+ Just True
+
+ -- we don't support negative matchers
+ _ ->
+ Nothing
+
+
+fromMatcher : Matcher -> MatcherForm
+fromMatcher { name, value, isRegex } =
+ { name = initialField name
+ , value = initialField value
+ , isRegex = isRegex
+ }
--- /dev/null
+port module Views.SilenceForm.Updates exposing (update)
+
+import Alerts.Api
+import Silences.Api
+import Task
+import Time
+import Types exposing (Msg(MsgForSilenceForm, SetDefaultCreator))
+import Navigation
+import Utils.Date exposing (timeFromString)
+import Utils.List
+import Utils.Types exposing (ApiData(..))
+import Utils.Filter exposing (nullFilter)
+import Utils.FormValidation exposing (updateValue, validate, stringNotEmpty, fromResult)
+import Views.SilenceForm.Types
+ exposing
+ ( Model
+ , SilenceForm
+ , SilenceFormMsg(..)
+ , SilenceFormFieldMsg(..)
+ , fromMatchersAndTime
+ , fromSilence
+ , parseEndsAt
+ , validateForm
+ , toSilence
+ , emptyMatcher
+ )
+
+
+updateForm : SilenceFormFieldMsg -> SilenceForm -> SilenceForm
+updateForm msg form =
+ case msg of
+ AddMatcher ->
+ { form | matchers = form.matchers ++ [ emptyMatcher ] }
+
+ UpdateStartsAt time ->
+ let
+ startsAt =
+ Utils.Date.timeFromString time
+
+ endsAt =
+ Utils.Date.timeFromString form.endsAt.value
+
+ durationValue =
+ case Result.map2 (-) endsAt startsAt of
+ Ok duration ->
+ case Utils.Date.durationFormat duration of
+ Just value ->
+ value
+
+ Nothing ->
+ form.duration.value
+
+ Err _ ->
+ form.duration.value
+ in
+ { form
+ | startsAt = updateValue time form.startsAt
+ , duration = updateValue durationValue form.duration
+ }
+
+ UpdateEndsAt time ->
+ let
+ endsAt =
+ Utils.Date.timeFromString time
+
+ startsAt =
+ Utils.Date.timeFromString form.startsAt.value
+
+ durationValue =
+ case Result.map2 (-) endsAt startsAt of
+ Ok duration ->
+ case Utils.Date.durationFormat duration of
+ Just value ->
+ value
+
+ Nothing ->
+ form.duration.value
+
+ Err _ ->
+ form.duration.value
+ in
+ { form
+ | endsAt = updateValue time form.endsAt
+ , duration = updateValue durationValue form.duration
+ }
+
+ UpdateDuration time ->
+ let
+ duration =
+ Utils.Date.parseDuration time
+
+ startsAt =
+ Utils.Date.timeFromString form.startsAt.value
+
+ endsAtValue =
+ case Result.map2 (+) startsAt duration of
+ Ok endsAt ->
+ Utils.Date.timeToString endsAt
+
+ Err _ ->
+ form.endsAt.value
+ in
+ { form
+ | endsAt = updateValue endsAtValue form.endsAt
+ , duration = updateValue time form.duration
+ }
+
+ ValidateTime ->
+ { form
+ | startsAt = validate Utils.Date.timeFromString form.startsAt
+ , endsAt = validate (parseEndsAt form.startsAt.value) form.endsAt
+ , duration = validate Utils.Date.parseDuration form.duration
+ }
+
+ UpdateCreatedBy createdBy ->
+ { form | createdBy = updateValue createdBy form.createdBy }
+
+ ValidateCreatedBy ->
+ { form | createdBy = validate stringNotEmpty form.createdBy }
+
+ UpdateComment comment ->
+ { form | comment = updateValue comment form.comment }
+
+ ValidateComment ->
+ { form | comment = validate stringNotEmpty form.comment }
+
+ DeleteMatcher index ->
+ { form | matchers = List.take index form.matchers ++ List.drop (index + 1) form.matchers }
+
+ UpdateMatcherName index name ->
+ let
+ matchers =
+ Utils.List.replaceIndex index
+ (\matcher -> { matcher | name = updateValue name matcher.name })
+ form.matchers
+ in
+ { form | matchers = matchers }
+
+ ValidateMatcherName index ->
+ let
+ matchers =
+ Utils.List.replaceIndex index
+ (\matcher -> { matcher | name = validate stringNotEmpty matcher.name })
+ form.matchers
+ in
+ { form | matchers = matchers }
+
+ UpdateMatcherValue index value ->
+ let
+ matchers =
+ Utils.List.replaceIndex index
+ (\matcher -> { matcher | value = updateValue value matcher.value })
+ form.matchers
+ in
+ { form | matchers = matchers }
+
+ ValidateMatcherValue index ->
+ let
+ matchers =
+ Utils.List.replaceIndex index
+ (\matcher -> { matcher | value = matcher.value })
+ form.matchers
+ in
+ { form | matchers = matchers }
+
+ UpdateMatcherRegex index isRegex ->
+ let
+ matchers =
+ Utils.List.replaceIndex index
+ (\matcher -> { matcher | isRegex = isRegex })
+ form.matchers
+ in
+ { form | matchers = matchers }
+
+
+update : SilenceFormMsg -> Model -> String -> String -> ( Model, Cmd Msg )
+update msg model basePath apiUrl =
+ case msg of
+ CreateSilence ->
+ case toSilence model.form of
+ Just silence ->
+ ( { model | silenceId = Loading }
+ , Cmd.batch
+ [ Silences.Api.create apiUrl silence |> Cmd.map (SilenceCreate >> MsgForSilenceForm)
+ , persistDefaultCreator silence.createdBy
+ , Task.succeed silence.createdBy |> Task.perform SetDefaultCreator
+ ]
+ )
+
+ Nothing ->
+ ( { model
+ | silenceId = Failure "Could not submit the form, Silence is not yet valid."
+ , form = validateForm model.form
+ }
+ , Cmd.none
+ )
+
+ SilenceCreate silenceId ->
+ let
+ cmd =
+ case silenceId of
+ Success id ->
+ Navigation.newUrl (basePath ++ "#/silences/" ++ id)
+
+ _ ->
+ Cmd.none
+ in
+ ( { model | silenceId = silenceId }, cmd )
+
+ NewSilenceFromMatchers defaultCreator matchers ->
+ ( model, Task.perform (NewSilenceFromMatchersAndTime defaultCreator matchers >> MsgForSilenceForm) Time.now )
+
+ NewSilenceFromMatchersAndTime defaultCreator matchers time ->
+ ( { form = fromMatchersAndTime defaultCreator matchers time
+ , alerts = Initial
+ , silenceId = Initial
+ }
+ , Cmd.none
+ )
+
+ FetchSilence silenceId ->
+ ( model, Silences.Api.getSilence apiUrl silenceId (SilenceFetch >> MsgForSilenceForm) )
+
+ SilenceFetch (Success silence) ->
+ ( { model | form = fromSilence silence }
+ , Task.perform identity (Task.succeed (MsgForSilenceForm PreviewSilence))
+ )
+
+ SilenceFetch _ ->
+ ( model, Cmd.none )
+
+ PreviewSilence ->
+ case toSilence model.form of
+ Just silence ->
+ ( { model | alerts = Loading }
+ , Alerts.Api.fetchAlerts
+ apiUrl
+ { nullFilter | text = Just (Utils.List.mjoin silence.matchers) }
+ |> Cmd.map (AlertGroupsPreview >> MsgForSilenceForm)
+ )
+
+ Nothing ->
+ ( { model
+ | alerts = Failure "Can not display affected Alerts, Silence is not yet valid."
+ , form = validateForm model.form
+ }
+ , Cmd.none
+ )
+
+ AlertGroupsPreview alerts ->
+ ( { model | alerts = alerts }
+ , Cmd.none
+ )
+
+ UpdateField fieldMsg ->
+ ( { form = updateForm fieldMsg model.form
+ , alerts = Initial
+ , silenceId = Initial
+ }
+ , Cmd.none
+ )
+
+
+port persistDefaultCreator : String -> Cmd msg
--- /dev/null
+module Views.SilenceForm.Views exposing (view)
+
+import Html exposing (Html, a, div, fieldset, label, legend, span, text, h1, strong, button, input, textarea)
+import Html.Attributes exposing (class, href)
+import Html.Events exposing (onClick)
+import Silences.Types exposing (Silence, SilenceId)
+import Alerts.Types exposing (Alert)
+import Views.Shared.SilencePreview
+import Views.SilenceForm.Types exposing (Model, SilenceFormMsg(..), MatcherForm)
+import Utils.Types exposing (ApiData)
+import Utils.Views exposing (checkbox, iconButtonMsg, validatedField, loading)
+import Utils.FormValidation exposing (ValidationState(..), ValidatedField)
+import Views.SilenceForm.Types exposing (Model, SilenceFormMsg(..), SilenceFormFieldMsg(..), SilenceForm)
+import Utils.Filter
+
+
+view : Maybe SilenceId -> List Utils.Filter.Matcher -> String -> Model -> Html SilenceFormMsg
+view maybeId matchers defaultCreator { form, silenceId, alerts } =
+ let
+ ( title, resetClick ) =
+ case maybeId of
+ Just silenceId ->
+ ( "Edit Silence", FetchSilence silenceId )
+
+ Nothing ->
+ ( "New Silence", NewSilenceFromMatchers defaultCreator matchers )
+ in
+ div []
+ [ h1 [] [ text title ]
+ , timeInput form.startsAt form.endsAt form.duration
+ , matcherInput form.matchers
+ , validatedField input
+ "Creator"
+ inputSectionPadding
+ (UpdateCreatedBy >> UpdateField)
+ (ValidateCreatedBy |> UpdateField)
+ form.createdBy
+ , validatedField textarea
+ "Comment"
+ inputSectionPadding
+ (UpdateComment >> UpdateField)
+ (ValidateComment |> UpdateField)
+ form.comment
+ , div [ class inputSectionPadding ]
+ [ informationBlock silenceId alerts
+ , silenceActionButtons maybeId form resetClick
+ ]
+ ]
+
+
+inputSectionPadding : String
+inputSectionPadding =
+ "mt-5"
+
+
+timeInput : ValidatedField -> ValidatedField -> ValidatedField -> Html SilenceFormMsg
+timeInput startsAt endsAt duration =
+ div [ class <| "row " ++ inputSectionPadding ]
+ [ validatedField input
+ "Start"
+ "col-5"
+ (UpdateStartsAt >> UpdateField)
+ (ValidateTime |> UpdateField)
+ startsAt
+ , validatedField input
+ "Duration"
+ "col-2"
+ (UpdateDuration >> UpdateField)
+ (ValidateTime |> UpdateField)
+ duration
+ , validatedField input
+ "End"
+ "col-5"
+ (UpdateEndsAt >> UpdateField)
+ (ValidateTime |> UpdateField)
+ endsAt
+ ]
+
+
+matcherInput : List MatcherForm -> Html SilenceFormMsg
+matcherInput matchers =
+ div [ class inputSectionPadding ]
+ [ div []
+ [ label []
+ [ strong [] [ text "Matchers " ]
+ , span [ class "" ] [ text "Alerts affected by this silence." ]
+ ]
+ , div [ class "row" ]
+ [ label [ class "col-5" ] [ text "Name" ]
+ , label [ class "col-5" ] [ text "Value" ]
+ ]
+ ]
+ , div [] (List.indexedMap (matcherForm (List.length matchers > 1)) matchers)
+ , iconButtonMsg "btn btn-secondary" "fa-plus" (AddMatcher |> UpdateField)
+ ]
+
+
+informationBlock : ApiData SilenceId -> ApiData (List Alert) -> Html SilenceFormMsg
+informationBlock silence alerts =
+ case silence of
+ Utils.Types.Success _ ->
+ text ""
+
+ Utils.Types.Initial ->
+ Views.Shared.SilencePreview.view alerts
+
+ Utils.Types.Failure error ->
+ Utils.Views.error error
+
+ Utils.Types.Loading ->
+ loading
+
+
+silenceActionButtons : Maybe String -> SilenceForm -> SilenceFormMsg -> Html SilenceFormMsg
+silenceActionButtons maybeId form resetClick =
+ div [ class ("mb-4 " ++ inputSectionPadding) ]
+ [ previewSilenceBtn
+ , createSilenceBtn maybeId
+ , button
+ [ class "ml-2 btn btn-danger", onClick resetClick ]
+ [ text "Reset" ]
+ ]
+
+
+createSilenceBtn : Maybe String -> Html SilenceFormMsg
+createSilenceBtn maybeId =
+ let
+ btnTxt =
+ case maybeId of
+ Just _ ->
+ "Update"
+
+ Nothing ->
+ "Create"
+ in
+ button
+ [ class "ml-2 btn btn-primary"
+ , onClick CreateSilence
+ ]
+ [ text btnTxt ]
+
+
+previewSilenceBtn : Html SilenceFormMsg
+previewSilenceBtn =
+ button
+ [ class "btn btn-outline-success"
+ , onClick PreviewSilence
+ ]
+ [ text "Preview Alerts" ]
+
+
+matcherForm : Bool -> Int -> MatcherForm -> Html SilenceFormMsg
+matcherForm showDeleteButton index { name, value, isRegex } =
+ div [ class "row" ]
+ [ div [ class "col-5" ] [ validatedField input "" "" (UpdateMatcherName index) (ValidateMatcherName index) name ]
+ , div [ class "col-5" ] [ validatedField input "" "" (UpdateMatcherValue index) (ValidateMatcherValue index) value ]
+ , div [ class "col-2 d-flex align-items-center" ]
+ [ checkbox "Regex" isRegex (UpdateMatcherRegex index)
+ , if showDeleteButton then
+ iconButtonMsg "btn btn-secondary ml-auto" "fa-trash-o" (DeleteMatcher index)
+ else
+ text ""
+ ]
+ ]
+ |> Html.map UpdateField
--- /dev/null
+module Views.SilenceList.Parsing exposing (silenceListParser)
+
+import UrlParser exposing ((<?>), Parser, s, stringParam, map)
+import Utils.Filter exposing (Filter)
+
+
+silenceListParser : Parser (Filter -> a) a
+silenceListParser =
+ map
+ (\t ->
+ Filter t Nothing Nothing Nothing Nothing
+ )
+ (s "silences" <?> stringParam "filter")
--- /dev/null
+module Views.SilenceList.SilenceView exposing (deleteButton, editButton, view)
+
+import Dialog
+import Html exposing (Html, a, b, button, div, h3, i, li, p, small, span, text)
+import Html.Attributes exposing (class, href, style)
+import Html.Events exposing (onClick)
+import Silences.Types exposing (Silence, State(Active, Expired, Pending))
+import Time exposing (Time)
+import Types exposing (Msg(MsgForSilenceForm, MsgForSilenceList, Noop))
+import Utils.Date
+import Utils.Filter
+import Utils.List
+import Utils.Types exposing (Matcher)
+import Utils.Views exposing (buttonLink)
+import Views.FilterBar.Types as FilterBarTypes
+import Views.SilenceList.Types exposing (SilenceListMsg(ConfirmDestroySilence, DestroySilence, FetchSilences, MsgForFilterBar))
+import Views.SilenceForm.Parsing exposing (newSilenceFromAlertLabels)
+
+
+view : Bool -> Silence -> Html Msg
+view showConfirmationDialog silence =
+ li
+ [ -- speedup rendering in Chrome, because list-group-item className
+ -- creates a new layer in the rendering engine
+ style [ ( "position", "static" ) ]
+ , class "align-items-start list-group-item border-0 p-0 mb-4"
+ ]
+ [ div [ class "w-100 mb-2 d-flex align-items-start" ]
+ [ case silence.status.state of
+ Active ->
+ dateView "Ends" silence.endsAt
+
+ Pending ->
+ dateView "Starts" silence.startsAt
+
+ Expired ->
+ dateView "Expired" silence.endsAt
+ , detailsButton silence.id
+ , editButton silence
+ , deleteButton silence False
+ ]
+ , div [ class "" ] (List.map matcherButton silence.matchers)
+ , Dialog.view
+ (if showConfirmationDialog then
+ Just (confirmSilenceDeleteView silence False)
+ else
+ Nothing
+ )
+ ]
+
+
+confirmSilenceDeleteView : Silence -> Bool -> Dialog.Config Msg
+confirmSilenceDeleteView silence refresh =
+ { closeMessage = Just (MsgForSilenceList Views.SilenceList.Types.FetchSilences)
+ , containerClass = Nothing
+ , header = Just (h3 [] [ text "Expire Silence" ])
+ , body = Just (text "Are you sure you want to expire this silence?")
+ , footer =
+ Just
+ (button
+ [ class "btn btn-success"
+ , onClick (MsgForSilenceList (Views.SilenceList.Types.DestroySilence silence refresh))
+ ]
+ [ text "Confirm" ]
+ )
+ }
+
+
+dateView : String -> Time -> Html Msg
+dateView string time =
+ span
+ [ class "text-muted align-self-center mr-2"
+ ]
+ [ text (string ++ " " ++ Utils.Date.timeFormat time ++ ", " ++ Utils.Date.dateFormat time)
+ ]
+
+
+matcherButton : Matcher -> Html Msg
+matcherButton matcher =
+ let
+ op =
+ if matcher.isRegex then
+ Utils.Filter.RegexMatch
+ else
+ Utils.Filter.Eq
+
+ msg =
+ FilterBarTypes.AddFilterMatcher False
+ { key = matcher.name
+ , op = op
+ , value = matcher.value
+ }
+ |> MsgForFilterBar
+ |> MsgForSilenceList
+ in
+ Utils.Views.labelButton (Just msg) (Utils.List.mstring matcher)
+
+
+editButton : Silence -> Html Msg
+editButton silence =
+ let
+ matchers =
+ List.map (\s -> ( s.name, s.value )) silence.matchers
+ in
+ case silence.status.state of
+ -- If the silence is expired, do not edit it, but instead create a new
+ -- one with the old matchers
+ Expired ->
+ a
+ [ class "btn btn-outline-info border-0"
+ , href (newSilenceFromAlertLabels matchers)
+ ]
+ [ text "Recreate"
+ ]
+
+ _ ->
+ let
+ editUrl =
+ String.join "/" [ "#/silences", silence.id, "edit" ]
+ in
+ a [ class "btn btn-outline-info border-0", href editUrl ]
+ [ text "Edit"
+ ]
+
+
+deleteButton : Silence -> Bool -> Html Msg
+deleteButton silence refresh =
+ case silence.status.state of
+ Expired ->
+ text ""
+
+ Active ->
+ button
+ [ class "btn btn-outline-danger border-0"
+ , onClick (MsgForSilenceList (ConfirmDestroySilence silence refresh))
+ ]
+ [ text "Expire"
+ ]
+
+ Pending ->
+ button
+ [ class "btn btn-outline-danger border-0"
+ , onClick (MsgForSilenceList (ConfirmDestroySilence silence refresh))
+ ]
+ [ text "Delete"
+ ]
+
+
+detailsButton : String -> Html Msg
+detailsButton silenceId =
+ a [ class "btn btn-outline-info border-0", href ("#/silences/" ++ silenceId) ]
+ [ text "View"
+ ]
--- /dev/null
+module Views.SilenceList.Types exposing (Model, SilenceTab, SilenceListMsg(..), initSilenceList)
+
+import Silences.Types exposing (Silence, State(Active), SilenceId)
+import Utils.Types exposing (ApiData(Initial))
+import Views.FilterBar.Types as FilterBar
+
+
+type SilenceListMsg
+ = ConfirmDestroySilence Silence Bool
+ | DestroySilence Silence Bool
+ | SilencesFetch (ApiData (List Silence))
+ | FetchSilences
+ | MsgForFilterBar FilterBar.Msg
+ | SetTab State
+
+
+type alias SilenceTab =
+ { silences : List Silence
+ , tab : State
+ , count : Int
+ }
+
+
+type alias Model =
+ { silences : ApiData (List SilenceTab)
+ , filterBar : FilterBar.Model
+ , tab : State
+ , showConfirmationDialog : Maybe SilenceId
+ }
+
+
+initSilenceList : Model
+initSilenceList =
+ { silences = Initial
+ , filterBar = FilterBar.initFilterBar
+ , tab = Active
+ , showConfirmationDialog = Nothing
+ }
--- /dev/null
+module Views.SilenceList.Updates exposing (update, urlUpdate)
+
+import Navigation
+import Silences.Api as Api
+import Utils.Api as ApiData
+import Utils.Filter exposing (Filter, generateQueryString)
+import Utils.Types as Types exposing (ApiData(Failure, Loading, Success), Matchers, Time)
+import Views.FilterBar.Updates as FilterBar
+import Views.SilenceList.Types exposing (Model, SilenceTab, SilenceListMsg(..))
+import Silences.Types exposing (Silence, State(..))
+
+
+update : SilenceListMsg -> Model -> Filter -> String -> String -> ( Model, Cmd SilenceListMsg )
+update msg model filter basePath apiUrl =
+ case msg of
+ SilencesFetch fetchedSilences ->
+ ( { model
+ | silences =
+ ApiData.map
+ (\silences -> List.map (groupSilencesByState silences) states)
+ fetchedSilences
+ }
+ , Cmd.none
+ )
+
+ FetchSilences ->
+ ( { model
+ | filterBar = FilterBar.setMatchers filter model.filterBar
+ , silences = Loading
+ , showConfirmationDialog = Nothing
+ }
+ , Api.getSilences apiUrl filter SilencesFetch
+ )
+
+ ConfirmDestroySilence silence refresh ->
+ ( { model | showConfirmationDialog = Just silence.id }
+ , Cmd.none
+ )
+
+ DestroySilence silence refresh ->
+ -- TODO: "Deleted id: ID" growl
+ -- TODO: Check why POST isn't there but is accepted
+ { model | silences = Loading, showConfirmationDialog = Nothing }
+ ! [ Api.destroy apiUrl silence (always FetchSilences)
+ , if refresh then
+ Navigation.newUrl (basePath ++ "#/silences")
+ else
+ Cmd.none
+ ]
+
+ MsgForFilterBar msg ->
+ let
+ ( filterBar, cmd ) =
+ FilterBar.update (basePath ++ "#/silences") filter msg model.filterBar
+ in
+ ( { model | filterBar = filterBar }, Cmd.map MsgForFilterBar cmd )
+
+ SetTab tab ->
+ ( { model | tab = tab }, Cmd.none )
+
+
+groupSilencesByState : List Silence -> State -> SilenceTab
+groupSilencesByState silences state =
+ let
+ silencesInTab =
+ filterSilencesByState state silences
+ in
+ { tab = state
+ , silences = silencesInTab
+ , count = List.length silencesInTab
+ }
+
+
+states : List State
+states =
+ [ Active, Pending, Expired ]
+
+
+filterSilencesByState : State -> List Silence -> List Silence
+filterSilencesByState state =
+ List.filter (.status >> .state >> (==) state)
+
+
+urlUpdate : Maybe String -> ( SilenceListMsg, Filter )
+urlUpdate maybeString =
+ ( FetchSilences, updateFilter maybeString )
+
+
+updateFilter : Maybe String -> Filter
+updateFilter maybeFilter =
+ { receiver = Nothing
+ , showSilenced = Nothing
+ , showInhibited = Nothing
+ , group = Nothing
+ , text = maybeFilter
+ }
--- /dev/null
+module Views.SilenceList.Views exposing (..)
+
+import Html exposing (..)
+import Html.Attributes exposing (..)
+import Silences.Types exposing (Silence, State(..), stateToString, SilenceId)
+import Types exposing (Msg(MsgForSilenceList, Noop, UpdateFilter))
+import Utils.String as StringUtils
+import Utils.Types exposing (ApiData(..), Matcher)
+import Utils.Views exposing (buttonLink, checkbox, error, formField, formInput, iconButtonMsg, loading, textField)
+import Views.FilterBar.Views as FilterBar
+import Views.SilenceList.SilenceView
+import Views.SilenceList.Types exposing (Model, SilenceListMsg(..), SilenceTab)
+import Html.Lazy exposing (lazy, lazy2, lazy3)
+import Html.Keyed
+
+
+view : Model -> Html Msg
+view { filterBar, tab, silences, showConfirmationDialog } =
+ div []
+ [ div [ class "mb-4" ]
+ [ label [ class "mb-2", for "filter-bar-matcher" ] [ text "Filter" ]
+ , Html.map (MsgForFilterBar >> MsgForSilenceList) (FilterBar.view filterBar)
+ ]
+ , lazy2 tabsView tab silences
+ , lazy3 silencesView showConfirmationDialog tab silences
+ ]
+
+
+tabsView : State -> ApiData (List SilenceTab) -> Html Msg
+tabsView currentTab tabs =
+ case tabs of
+ Success silencesTabs ->
+ List.map (\{ tab, count } -> tabView currentTab count tab) silencesTabs
+ |> ul [ class "nav nav-tabs mb-4" ]
+
+ _ ->
+ List.map (tabView currentTab 0) states
+ |> ul [ class "nav nav-tabs mb-4" ]
+
+
+tabView : State -> Int -> State -> Html Msg
+tabView currentTab count tab =
+ Utils.Views.tab tab currentTab (SetTab >> MsgForSilenceList) <|
+ case count of
+ 0 ->
+ [ text (StringUtils.capitalizeFirst (stateToString tab)) ]
+
+ n ->
+ [ text (StringUtils.capitalizeFirst (stateToString tab))
+ , span
+ [ class "badge badge-pillow badge-default align-text-top ml-2" ]
+ [ text (toString n) ]
+ ]
+
+
+silencesView : Maybe SilenceId -> State -> ApiData (List SilenceTab) -> Html Msg
+silencesView showConfirmationDialog tab silencesTab =
+ case silencesTab of
+ Success tabs ->
+ tabs
+ |> List.filter (.tab >> (==) tab)
+ |> List.head
+ |> Maybe.map .silences
+ |> Maybe.withDefault []
+ |> (\silences ->
+ if List.isEmpty silences then
+ Utils.Views.error "No silences found"
+ else
+ Html.Keyed.ul [ class "list-group" ]
+ (List.map
+ (\silence ->
+ ( silence.id
+ , Views.SilenceList.SilenceView.view
+ (showConfirmationDialog == Just silence.id)
+ silence
+ )
+ )
+ silences
+ )
+ )
+
+ Failure msg ->
+ error msg
+
+ _ ->
+ loading
+
+
+groupSilencesByState : List Silence -> List ( State, List Silence )
+groupSilencesByState silences =
+ List.map (\state -> ( state, filterSilencesByState state silences )) states
+
+
+states : List State
+states =
+ [ Active, Pending, Expired ]
+
+
+filterSilencesByState : State -> List Silence -> List Silence
+filterSilencesByState state =
+ List.filter (.status >> .state >> (==) state)
--- /dev/null
+module Views.SilenceView.Parsing exposing (silenceViewParser)
+
+import UrlParser exposing (Parser, s, string, (</>))
+
+
+silenceViewParser : Parser (String -> a) a
+silenceViewParser =
+ s "silences" </> string
--- /dev/null
+module Views.SilenceView.Types exposing (Model, SilenceViewMsg(..), initSilenceView)
+
+import Alerts.Types exposing (Alert)
+import Silences.Types exposing (Silence, SilenceId)
+import Utils.Types exposing (ApiData(Initial))
+
+
+type SilenceViewMsg
+ = FetchSilence String
+ | SilenceFetched (ApiData Silence)
+ | AlertGroupsPreview (ApiData (List Alert))
+ | InitSilenceView SilenceId
+ | ConfirmDestroySilence Silence Bool
+ | Reload String
+
+
+type alias Model =
+ { silence : ApiData Silence
+ , alerts : ApiData (List Alert)
+ , showConfirmationDialog : Bool
+ }
+
+
+initSilenceView : Model
+initSilenceView =
+ { silence = Initial
+ , alerts = Initial
+ , showConfirmationDialog = False
+ }
--- /dev/null
+module Views.SilenceView.Updates exposing (update)
+
+import Alerts.Api
+import Navigation exposing (newUrl)
+import Silences.Api exposing (getSilence)
+import Utils.Filter exposing (nullFilter)
+import Utils.List
+import Utils.Types exposing (ApiData(..))
+import Views.SilenceView.Types exposing (Model, SilenceViewMsg(..))
+
+
+update : SilenceViewMsg -> Model -> String -> ( Model, Cmd SilenceViewMsg )
+update msg model apiUrl =
+ case msg of
+ FetchSilence id ->
+ ( model, getSilence apiUrl id SilenceFetched )
+
+ AlertGroupsPreview alerts ->
+ ( { model | alerts = alerts }
+ , Cmd.none
+ )
+
+ SilenceFetched (Success silence) ->
+ ( { model
+ | silence = Success silence
+ , alerts = Loading
+ }
+ , Alerts.Api.fetchAlerts
+ apiUrl
+ { nullFilter | text = Just (Utils.List.mjoin silence.matchers), showSilenced = Just True }
+ |> Cmd.map AlertGroupsPreview
+ )
+
+ ConfirmDestroySilence silence refresh ->
+ ( { model | showConfirmationDialog = True }
+ , Cmd.none
+ )
+
+ SilenceFetched silence ->
+ ( { model | silence = silence, alerts = Initial }, Cmd.none )
+
+ InitSilenceView silenceId ->
+ ( { model | showConfirmationDialog = False }, getSilence apiUrl silenceId SilenceFetched )
+
+ Reload silenceId ->
+ ( { model | showConfirmationDialog = False }, newUrl ("#/silences/" ++ silenceId) )
--- /dev/null
+module Views.SilenceView.Views exposing (view)
+
+import Alerts.Types exposing (Alert)
+import Dialog
+import Html exposing (Html, b, button, div, h1, h2, h3, label, p, span, text)
+import Html.Attributes exposing (class, href)
+import Html.Events exposing (onClick)
+import Silences.Types exposing (Silence, stateToString)
+import Types exposing (Msg(MsgForSilenceList, MsgForSilenceView))
+import Utils.Date exposing (dateTimeFormat)
+import Utils.List
+import Utils.Types exposing (ApiData(Failure, Initial, Loading, Success))
+import Utils.Views exposing (error, loading)
+import Views.Shared.SilencePreview
+import Views.SilenceList.SilenceView exposing (editButton)
+import Views.SilenceList.Types exposing (SilenceListMsg(DestroySilence))
+import Views.SilenceView.Types exposing (Model, SilenceViewMsg(ConfirmDestroySilence, Reload))
+
+
+view : Model -> Html Msg
+view { silence, alerts, showConfirmationDialog } =
+ case silence of
+ Success sil ->
+ if showConfirmationDialog then
+ viewSilence alerts sil True
+ else
+ viewSilence alerts sil False
+
+ Initial ->
+ loading
+
+ Loading ->
+ loading
+
+ Failure msg ->
+ error msg
+
+
+viewSilence : ApiData (List Alert) -> Silence -> Bool -> Html Msg
+viewSilence alerts silence showPromptDialog =
+ div []
+ [ h1 []
+ [ text "Silence"
+ , span
+ [ class "ml-3" ]
+ [ editButton silence
+ , expireButton silence False
+ ]
+ ]
+ , formGroup "ID" <| text silence.id
+ , formGroup "Starts at" <| text <| dateTimeFormat silence.startsAt
+ , formGroup "Ends at" <| text <| dateTimeFormat silence.endsAt
+ , formGroup "Updated at" <| text <| dateTimeFormat silence.updatedAt
+ , formGroup "Created by" <| text silence.createdBy
+ , formGroup "Comment" <| text silence.comment
+ , formGroup "State" <| text <| stateToString silence.status.state
+ , formGroup "Matchers" <|
+ div [] <|
+ List.map (Utils.List.mstring >> Utils.Views.labelButton Nothing) silence.matchers
+ , formGroup "Affected alerts" <| Views.Shared.SilencePreview.view alerts
+ , Dialog.view
+ (if showPromptDialog then
+ Just (confirmSilenceDeleteView silence True)
+ else
+ Nothing
+ )
+ ]
+
+
+confirmSilenceDeleteView : Silence -> Bool -> Dialog.Config Msg
+confirmSilenceDeleteView silence refresh =
+ { closeMessage = Just (MsgForSilenceView (Reload silence.id))
+ , containerClass = Nothing
+ , header = Just (h3 [] [ text "Expire Silence" ])
+ , body = Just (text "Are you sure you want to expire this silence?")
+ , footer =
+ Just
+ (button
+ [ class "btn btn-success"
+ , onClick (MsgForSilenceList (DestroySilence silence refresh))
+ ]
+ [ text "Confirm" ]
+ )
+ }
+
+
+formGroup : String -> Html Msg -> Html Msg
+formGroup key content =
+ div [ class "form-group row" ]
+ [ label [ class "col-2 col-form-label" ] [ b [] [ text key ] ]
+ , div [ class "col-10 d-flex align-items-center" ]
+ [ content
+ ]
+ ]
+
+
+expireButton : Silence -> Bool -> Html Msg
+expireButton silence refresh =
+ case silence.status.state of
+ Silences.Types.Expired ->
+ text ""
+
+ Silences.Types.Active ->
+ button
+ [ class "btn btn-outline-danger border-0"
+ , onClick (MsgForSilenceView (ConfirmDestroySilence silence refresh))
+ ]
+ [ text "Expire"
+ ]
+
+ Silences.Types.Pending ->
+ button
+ [ class "btn btn-outline-danger border-0"
+ , onClick (MsgForSilenceView (ConfirmDestroySilence silence refresh))
+ ]
+ [ text "Delete"
+ ]
--- /dev/null
+module Views.Status.Parsing exposing (statusParser)
+
+import UrlParser exposing (Parser, s)
+
+
+statusParser : Parser a a
+statusParser =
+ s "status"
--- /dev/null
+module Views.Status.Types exposing (StatusMsg(..), StatusModel, initStatusModel)
+
+import Status.Types exposing (StatusResponse)
+import Utils.Types exposing (ApiData(Initial))
+
+
+type StatusMsg
+ = NewStatus (ApiData StatusResponse)
+ | InitStatusView
+
+
+type alias StatusModel =
+ { statusInfo : ApiData StatusResponse
+ }
+
+
+initStatusModel : StatusModel
+initStatusModel =
+ { statusInfo = Initial }
--- /dev/null
+module Views.Status.Updates exposing (update)
+
+import Types exposing (Msg(MsgForStatus), Model)
+import Views.Status.Types exposing (StatusMsg(..))
+import Status.Api exposing (getStatus)
+
+
+update : StatusMsg -> Model -> String -> ( Model, Cmd Msg )
+update msg model basePath =
+ case msg of
+ NewStatus apiResponse ->
+ ( { model | status = { statusInfo = apiResponse } }, Cmd.none )
+
+ InitStatusView ->
+ ( model, getStatus basePath (NewStatus >> MsgForStatus) )
--- /dev/null
+module Views.Status.Views exposing (view)
+
+import Html exposing (..)
+import Html.Attributes exposing (class, style, classList)
+import Status.Types exposing (StatusResponse, VersionInfo, ClusterStatus, ClusterPeer)
+import Types exposing (Msg(MsgForStatus))
+import Utils.Types exposing (ApiData(Failure, Success, Loading, Initial))
+import Views.Status.Types exposing (StatusModel)
+import Utils.Views
+
+
+view : StatusModel -> Html Types.Msg
+view { statusInfo } =
+ case statusInfo of
+ Success info ->
+ viewStatusInfo info
+
+ Initial ->
+ Utils.Views.loading
+
+ Loading ->
+ Utils.Views.loading
+
+ Failure msg ->
+ Utils.Views.error msg
+
+
+viewStatusInfo : StatusResponse -> Html Types.Msg
+viewStatusInfo status =
+ div []
+ [ h1 [] [ text "Status" ]
+ , div [ class "form-group row" ]
+ [ b [ class "col-sm-2" ] [ text "Uptime:" ]
+ , div [ class "col-sm-10" ] [ text status.uptime ]
+ ]
+ , viewClusterStatus status.clusterStatus
+ , viewVersionInformation status.versionInfo
+ , viewConfig status.config
+ ]
+
+
+viewConfig : String -> Html Types.Msg
+viewConfig config =
+ div []
+ [ h2 [] [ text "Config" ]
+ , pre [ class "p-4", style [ ( "background", "#f7f7f9" ), ( "font-family", "monospace" ) ] ]
+ [ code []
+ [ text config
+ ]
+ ]
+ ]
+
+
+viewClusterStatus : Maybe ClusterStatus -> Html Types.Msg
+viewClusterStatus clusterStatus =
+ case clusterStatus of
+ Just clusterStatus ->
+ span []
+ [ h2 [] [ text "Cluster Status" ]
+ , div [ class "form-group row" ]
+ [ b [ class "col-sm-2" ] [ text "Name:" ]
+ , div [ class "col-sm-10" ] [ text clusterStatus.name ]
+ ]
+ , div [ class "form-group row" ]
+ [ b [ class "col-sm-2" ] [ text "Status:" ]
+ , div [ class "col-sm-10" ]
+ [ span
+ [ classList
+ [ ( "badge", True )
+ , ( "badge-success", clusterStatus.status == "ready" )
+ , ( "badge-warning", clusterStatus.status == "settling" )
+ ]
+ ]
+ [ text clusterStatus.status ]
+ ]
+ ]
+ , div [ class "form-group row" ]
+ [ b [ class "col-sm-2" ] [ text "Peers:" ]
+ , ul [ class "col-sm-10" ] <|
+ List.map viewClusterPeer clusterStatus.peers
+ ]
+ ]
+
+ Nothing ->
+ span []
+ [ h2 [] [ text "Mesh Status" ]
+ , div [ class "form-group row" ]
+ [ div [ class "col-sm-10" ] [ text "Mesh not configured" ]
+ ]
+ ]
+
+
+viewClusterPeer : ClusterPeer -> Html Types.Msg
+viewClusterPeer peer =
+ li []
+ [ div [ class "" ]
+ [ b [ class "" ] [ text "Name: " ]
+ , text peer.name
+ ]
+ , div [ class "" ]
+ [ b [ class "" ] [ text "Address: " ]
+ , text peer.address
+ ]
+ ]
+
+
+viewVersionInformation : VersionInfo -> Html Types.Msg
+viewVersionInformation versionInfo =
+ span []
+ [ h2 [] [ text "Version Information" ]
+ , div [ class "form-group row" ]
+ [ b [ class "col-sm-2" ] [ text "Branch:" ], div [ class "col-sm-10" ] [ text versionInfo.branch ] ]
+ , div [ class "form-group row" ]
+ [ b [ class "col-sm-2" ] [ text "BuildDate:" ], div [ class "col-sm-10" ] [ text versionInfo.buildDate ] ]
+ , div [ class "form-group row" ]
+ [ b [ class "col-sm-2" ] [ text "BuildUser:" ], div [ class "col-sm-10" ] [ text versionInfo.buildUser ] ]
+ , div [ class "form-group row" ]
+ [ b [ class "col-sm-2" ] [ text "GoVersion:" ], div [ class "col-sm-10" ] [ text versionInfo.goVersion ] ]
+ , div [ class "form-group row" ]
+ [ b [ class "col-sm-2" ] [ text "Revision:" ], div [ class "col-sm-10" ] [ text versionInfo.revision ] ]
+ , div [ class "form-group row" ]
+ [ b [ class "col-sm-2" ] [ text "Version:" ], div [ class "col-sm-10" ] [ text versionInfo.version ] ]
+ ]
--- /dev/null
+/elm-stuff/
--- /dev/null
+module Filter exposing (..)
+
+import Test exposing (..)
+import Expect
+import Fuzz exposing (list, int, tuple, string)
+import Utils.Filter exposing (Matcher, MatchOperator(Eq, RegexMatch))
+import Helpers exposing (isNotEmptyTrimmedAlphabetWord)
+
+
+parseMatcher : Test
+parseMatcher =
+ describe "parseMatcher"
+ [ test "should parse empty matcher string" <|
+ \() ->
+ Expect.equal Nothing (Utils.Filter.parseMatcher "")
+ , test "should parse empty matcher value" <|
+ \() ->
+ Expect.equal (Just (Matcher "alertname" Eq "")) (Utils.Filter.parseMatcher "alertname=\"\"")
+ , fuzz (tuple ( string, string )) "should parse random matcher string" <|
+ \( key, value ) ->
+ if List.map isNotEmptyTrimmedAlphabetWord [ key, value ] /= [ True, True ] then
+ Expect.equal
+ Nothing
+ (Utils.Filter.parseMatcher <| String.join "" [ key, "=", value ])
+ else
+ Expect.equal
+ (Just (Matcher key Eq value))
+ (Utils.Filter.parseMatcher <| String.join "" [ key, "=", "\"", value, "\"" ])
+ ]
+
+
+generateQueryString : Test
+generateQueryString =
+ describe "generateQueryString"
+ [ test "should default silenced & inhibited parameters to false if showSilenced is Nothing" <|
+ \() ->
+ Expect.equal "?silenced=false&inhibited=false"
+ (Utils.Filter.generateQueryString { receiver = Nothing, group = Nothing, text = Nothing, showSilenced = Nothing, showInhibited = Nothing })
+ , test "should not render keys with Nothing value except the silenced and inhibited parameters" <|
+ \() ->
+ Expect.equal "?silenced=false&inhibited=false"
+ (Utils.Filter.generateQueryString { receiver = Nothing, group = Nothing, text = Nothing, showSilenced = Nothing, showInhibited = Nothing })
+ , test "should not render filter key with empty value" <|
+ \() ->
+ Expect.equal "?silenced=false&inhibited=false"
+ (Utils.Filter.generateQueryString { receiver = Nothing, group = Nothing, text = Just "", showSilenced = Nothing, showInhibited = Nothing })
+ , test "should render filter key with values" <|
+ \() ->
+ Expect.equal "?silenced=false&inhibited=false&filter=%7Bfoo%3D%22bar%22%2C%20baz%3D~%22quux.*%22%7D"
+ (Utils.Filter.generateQueryString { receiver = Nothing, group = Nothing, text = Just "{foo=\"bar\", baz=~\"quux.*\"}", showSilenced = Nothing, showInhibited = Nothing })
+ , test "should render silenced key with bool" <|
+ \() ->
+ Expect.equal "?silenced=true&inhibited=false"
+ (Utils.Filter.generateQueryString { receiver = Nothing, group = Nothing, text = Nothing, showSilenced = Just True, showInhibited = Nothing })
+ , test "should render inhibited key with bool" <|
+ \() ->
+ Expect.equal "?silenced=false&inhibited=true"
+ (Utils.Filter.generateQueryString { receiver = Nothing, group = Nothing, text = Nothing, showSilenced = Nothing, showInhibited = Just True })
+ ]
+
+
+stringifyFilter : Test
+stringifyFilter =
+ describe "stringifyFilter"
+ [ test "empty" <|
+ \() ->
+ Expect.equal ""
+ (Utils.Filter.stringifyFilter [])
+ , test "non-empty" <|
+ \() ->
+ Expect.equal "{foo=\"bar\", baz=~\"quux.*\"}"
+ (Utils.Filter.stringifyFilter
+ [ { key = "foo", op = Eq, value = "bar" }
+ , { key = "baz", op = RegexMatch, value = "quux.*" }
+ ]
+ )
+ ]
--- /dev/null
+module Helpers exposing (isNotEmptyTrimmedAlphabetWord)
+
+import String
+
+
+isNotEmptyTrimmedAlphabetWord : String -> Bool
+isNotEmptyTrimmedAlphabetWord string =
+ let
+ stringLength =
+ String.length string
+ in
+ stringLength
+ /= 0
+ && String.length (String.filter isLetter string)
+ == stringLength
+
+
+isLetter : Char -> Bool
+isLetter char =
+ String.contains (String.fromChar char) (lowerCaseAlphabet)
+ || String.contains (String.fromChar char) (upperCaseAlphabet)
+
+
+lowerCaseAlphabet : String
+lowerCaseAlphabet =
+ "abcdefghijklmnopqrstuvwxyz"
+
+
+upperCaseAlphabet : String
+upperCaseAlphabet =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
--- /dev/null
+module Match exposing (..)
+
+import Test exposing (..)
+import Expect
+import Utils.Match exposing (jaroWinkler, consecutiveChars)
+
+
+testJaroWinkler : Test
+testJaroWinkler =
+ describe "jaroWinkler"
+ [ test "should find the right values 1" <|
+ \() ->
+ Expect.greaterThan (jaroWinkler "zi" "zone")
+ (jaroWinkler "zo" "zone")
+ , test "should find the right values 2" <|
+ \() ->
+ Expect.greaterThan (jaroWinkler "hook" "alertname")
+ (jaroWinkler "de" "dev")
+ , test "should find the right values 3" <|
+ \() ->
+ Expect.equal 0.0
+ (jaroWinkler "l" "zone")
+ , test "should find the right values 4" <|
+ \() ->
+ Expect.equal 1.0
+ (jaroWinkler "zone" "zone")
+ , test "should find the right values 5" <|
+ \() ->
+ Expect.greaterThan 0.688
+ (jaroWinkler "atleio3tefdoisahdf" "attributefdoiashfoihfeowfh9w8f9afaw9fahw")
+ ]
+
+
+testConsecutiveChars : Test
+testConsecutiveChars =
+ describe "consecutiveChars"
+ [ test "should find the consecutiveChars 1" <|
+ \() ->
+ Expect.equal "zo"
+ (consecutiveChars "zo" "bozo")
+ , test "should find the consecutiveChars 2" <|
+ \() ->
+ Expect.equal "zo"
+ (consecutiveChars "zol" "zone")
+ , test "should find the consecutiveChars 3" <|
+ \() ->
+ Expect.equal "oon"
+ (consecutiveChars "oon" "baboone")
+ , test "should find the consecutiveChars 4" <|
+ \() ->
+ Expect.equal "dom"
+ (consecutiveChars "dom" "random")
+ ]
--- /dev/null
+module StringUtils exposing (testLinkify)
+
+import Utils.String exposing (linkify)
+import Test exposing (..)
+import Expect
+
+
+testLinkify : Test
+testLinkify =
+ describe "linkify"
+ [ test "should linkify a url in the middle" <|
+ \() ->
+ Expect.equal (linkify "word1 http://url word2")
+ [ Err "word1 ", Ok "http://url", Err " word2" ]
+ , test "should linkify a url in the beginning" <|
+ \() ->
+ Expect.equal (linkify "http://url word1 word2")
+ [ Ok "http://url", Err " word1 word2" ]
+ , test "should linkify a url in the end" <|
+ \() ->
+ Expect.equal (linkify "word1 word2 http://url")
+ [ Err "word1 word2 ", Ok "http://url" ]
+ ]
--- /dev/null
+{
+ "version": "1.0.0",
+ "summary": "Test Suites",
+ "repository": "https://github.com/prometheus/alertmanager.git",
+ "license": "Apache-2.0",
+ "source-directories": [
+ "../src",
+ "."
+ ],
+ "exposed-modules": [],
+ "dependencies": {
+ "elm-lang/core": "5.0.0 <= v < 6.0.0",
+ "elm-community/elm-test": "4.0.0 <= v < 5.0.0",
+ "elm-lang/dom": "1.1.1 <= v < 2.0.0",
+ "elm-lang/html": "2.0.0 <= v < 3.0.0",
+ "elm-lang/http": "1.0.0 <= v < 2.0.0",
+ "elm-lang/navigation": "2.0.1 <= v < 3.0.0",
+ "elm-tools/parser": "2.0.0 <= v < 3.0.0",
+ "evancz/url-parser": "2.0.1 <= v < 3.0.0"
+ },
+ "elm-version": "0.18.0 <= v < 0.19.0"
+}
--- /dev/null
+// Code generated by go-bindata.
+// sources:
+// ui/app/script.js
+// ui/app/index.html
+// ui/app/favicon.ico
+// ui/app/lib/bootstrap-4.0.0-alpha.6-dist/css/bootstrap.min.css
+// ui/app/lib/bootstrap-4.0.0-alpha.6-dist/css/bootstrap.min.css.map
+// ui/app/lib/font-awesome-4.7.0/css/font-awesome.css
+// ui/app/lib/font-awesome-4.7.0/css/font-awesome.min.css
+// ui/app/lib/font-awesome-4.7.0/fonts/FontAwesome.otf
+// ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.eot
+// ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.svg
+// ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.ttf
+// ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.woff
+// ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2
+// DO NOT EDIT!
+
+package ui
+
+import (
+ "bytes"
+ "compress/gzip"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+)
+
+func bindataRead(data []byte, name string) ([]byte, error) {
+ gz, err := gzip.NewReader(bytes.NewBuffer(data))
+ if err != nil {
+ return nil, fmt.Errorf("Read %q: %v", name, err)
+ }
+
+ var buf bytes.Buffer
+ _, err = io.Copy(&buf, gz)
+ clErr := gz.Close()
+
+ if err != nil {
+ return nil, fmt.Errorf("Read %q: %v", name, err)
+ }
+ if clErr != nil {
+ return nil, err
+ }
+
+ return buf.Bytes(), nil
+}
+
+type asset struct {
+ bytes []byte
+ info os.FileInfo
+}
+
+type bindataFileInfo struct {
+ name string
+ size int64
+ mode os.FileMode
+ modTime time.Time
+}
+
+func (fi bindataFileInfo) Name() string {
+ return fi.name
+}
+func (fi bindataFileInfo) Size() int64 {
+ return fi.size
+}
+func (fi bindataFileInfo) Mode() os.FileMode {
+ return fi.mode
+}
+func (fi bindataFileInfo) ModTime() time.Time {
+ return fi.modTime
+}
+func (fi bindataFileInfo) IsDir() bool {
+ return false
+}
+func (fi bindataFileInfo) Sys() interface{} {
+ return nil
+}
+
+var _uiAppScriptJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xfd\x7d\x77\xdb\x36\xb2\x38\x8e\xbf\x15\x9a\xbf\x5e\x15\x58\x8d\x15\x29\x49\x77\xef\xa5\x8c\xf8\xe4\xb1\x4d\x9b\x38\x69\x92\x36\xbb\xab\xf8\x2a\x34\x05\x49\xac\x29\x40\x01\x41\x39\x8e\xad\xf7\xfe\x3b\x78\x24\x48\x51\x76\xda\xed\xd9\xbb\x9f\x73\xbe\xfe\xc3\x22\x41\x3c\xcc\x0c\x06\x83\x01\x30\x33\x40\xf3\x8a\x65\x32\xe7\x0c\xe1\xab\xb8\x2a\x69\x54\x4a\x91\x67\x32\x1e\xbb\xf4\x48\x22\x89\xaf\xfc\x9b\x40\x02\x5f\x09\x2a\x2b\xc1\x22\x5f\x94\xfa\x24\x89\x04\x50\xbc\xdd\xda\x57\x31\x48\x45\x2e\x2f\xc9\x5d\x10\x03\x95\x9b\x48\x10\xdb\xa0\xae\xdf\x51\xb3\x4f\x62\xcd\xc6\x80\xe1\xed\x4e\x7b\xf7\x3a\xdb\xa3\xff\x62\x7b\x3e\x89\xb7\x41\x00\xae\x80\x68\x43\x71\xbf\x13\x0a\xf6\xe7\x43\xe1\x93\xb2\x5d\xc0\x20\xd3\xa0\xb5\x61\xfb\xae\x13\x36\xfe\x6f\x81\xcd\x27\x55\x5d\xe0\x42\x65\x00\x6e\x43\xfc\xd7\x4e\x88\xb3\xff\x2b\x88\x7d\xd2\xb4\x1b\x09\x98\x5a\x34\xda\x78\xfc\xad\x13\x8f\xea\x3f\x08\x0f\x9f\x94\xef\x43\x0d\x72\x87\x5c\x1b\xbb\xff\xee\xc4\x6e\xfa\x9f\x8d\x9d\x4f\x4a\xf7\x23\x0c\xa9\x47\xb9\x8d\xf3\xff\x74\xe2\x9c\x23\x09\x4a\x18\xba\x1a\xef\x12\x42\xa4\x29\x71\x2c\x75\x7e\x2d\x2b\x13\x89\x04\x46\x14\xd7\x05\x53\x53\x10\x6a\xf4\xef\x75\x16\x05\xe6\x0b\x23\x16\x94\x2f\x5d\x79\xa8\xa9\x75\x7f\x4f\x0d\xc0\xc3\x3a\x10\x0f\xaa\x99\xd7\xd5\x40\x4d\xe3\xef\xf6\x56\x04\x59\xab\x2a\x94\x05\xb5\x15\x61\x6d\x50\x77\xd0\x5f\x6f\xa8\x0f\xaa\xdd\x1a\x51\x15\x54\x3a\x6b\x56\x0a\x75\x27\xff\xed\xc6\x6a\x61\xda\x59\x31\x9a\x06\x75\xaf\xdb\x75\x43\xcd\x2f\xff\x7d\x4b\xed\x90\xef\xab\x1f\xe5\x78\xbb\x49\x45\xb4\x24\xc1\xbc\x1b\x4e\x50\x20\xf0\x55\x3e\x47\xf2\x68\x78\x7d\x2d\x1f\x90\xe7\x48\x60\x2c\x97\x82\x5f\x44\x8c\x5e\x44\x4f\x85\xe0\x02\xc5\xcf\xd9\x8c\x7e\x8e\xe2\xbe\xec\xc7\x51\x5e\x46\xbc\x92\x11\x9f\x47\x22\x65\x0b\x3a\x88\x1e\x2f\x69\x76\x1e\xc9\x25\x8d\x0a\xca\x16\x72\xa9\x3e\x5d\xf2\x4a\x44\xa9\x10\xe9\x65\x34\xcf\x45\x29\x23\x2e\x22\x35\xd9\x2f\xa8\x7c\x99\x5e\x9e\x51\xf5\xbe\xa0\xf2\x7d\x2e\x97\x4f\xe8\x3c\xad\x0a\x39\x88\xf1\xd8\x62\xcb\x34\x54\x8d\x09\x4c\x41\x39\xe7\x02\x29\x54\x28\x11\x83\x25\xcd\x17\x4b\x39\xa6\x0f\x86\x63\x7a\x78\x58\x7f\x63\x44\x3e\x78\xf0\xdd\x5f\xe8\x58\x0c\x0c\x30\xe5\x84\x9d\x1e\x11\x39\xc6\xac\xdf\x1f\xb3\x07\xc3\x5e\x0f\xc9\x43\x12\x7c\x3d\x1c\x9d\x62\x10\x44\x0c\x64\x7a\x56\xd0\x09\x3b\xad\x07\x9b\x49\x91\xa7\x8d\xe9\xaa\x31\xc4\x34\xd5\x9e\x23\x8a\x8f\x88\x3c\xa6\x49\x66\x3f\x37\x66\x0b\x53\x20\x9f\xa3\x21\x21\x04\x51\xf2\x02\x51\x8c\x2d\x02\x98\xfa\x46\x88\x18\xd3\xa2\xa4\x57\x06\x8b\x57\x48\x02\xc5\x35\xc0\xb4\x05\x30\xf5\xe0\x12\xdb\x84\x4f\xc0\x0e\x01\xda\x10\xf6\x20\x02\xa8\xc9\xf0\xf8\xe7\x64\x8a\x04\xbc\x4c\xe5\x72\x30\x2f\x38\x17\x48\x3f\x16\x7c\x81\x24\xbe\xe3\x9f\xbf\x60\x0c\x43\x90\xb8\x21\x59\x9d\xb0\xb0\x38\x05\x5d\xc3\x89\x62\x9a\x87\xaa\xdf\x11\x62\x87\x14\xff\x17\xfa\xd2\x1f\x61\x0c\x19\x19\x8e\xb3\x23\x6e\xb1\x18\x67\xfd\x3e\xe6\x93\xec\x94\x48\x44\xfb\x99\xeb\xf8\xab\x4c\x72\x91\xc4\x53\x5d\x3e\x06\x43\xa2\x64\x08\x1a\xb3\x84\x6f\xb7\xae\x99\x8a\x68\x00\xd7\xfc\x02\x7d\x01\x81\x21\x6c\x56\x7f\xc9\x68\x5e\x18\x00\xee\x54\x18\x43\x1e\x7c\x77\x30\xec\x87\x49\x63\x78\x38\x02\xda\xcf\xfe\x52\x19\x0a\xad\x72\x86\x68\x1f\x65\xfd\x11\xfe\x4b\x05\x4c\x55\xa9\x72\x3e\x47\xaa\x00\xee\xa3\xec\xc1\xf0\x38\x9f\x64\x87\xa3\xd3\x64\x78\x33\x36\xc2\x61\x03\xb6\x43\x93\x7c\xdb\x90\xc4\x9a\xac\xf1\xe4\x34\xd6\x43\x5e\xd5\x81\x6d\xb7\xfd\x3c\x76\xf8\x8b\x00\x9f\x2f\x18\x28\x99\x9c\x02\x23\xc3\xb1\x2a\x76\xe0\x8a\x8d\xb1\x50\xec\x21\x07\xd3\x21\x48\xf5\x33\x82\x7e\x9f\x11\x42\xbe\xf4\x7a\xa8\x44\x9c\xdc\x4c\x6e\xb1\x05\xaa\x06\x46\xa3\x25\x46\x86\x78\x9c\xcf\x11\x7b\x30\xc4\x57\xa6\xc3\x6f\xa9\x65\x50\xae\x8b\x3c\xa3\x68\xa8\xd4\xe6\x71\x89\xb8\x1e\x1e\x16\x0f\xd3\x03\x8e\xb7\x0f\x47\xba\x0f\xe8\x24\x3b\x35\xcc\x6c\xd3\xd5\x18\x28\x91\x4a\x56\x43\xc2\xf4\x3f\x9d\xd4\xa5\x4e\x9d\xdc\xa8\xec\xa8\x52\x05\x46\x84\x90\xaa\x51\xcd\xb1\x7d\x9d\x0c\x4f\x93\xaa\x35\x79\x19\x64\x28\x91\x4e\xb0\xe4\x73\xe4\x64\x04\x21\x84\x62\x3b\x2c\xbb\x91\xa5\xfd\x91\x45\x77\x72\xea\xbb\x75\x72\xba\x1d\x8b\xc1\xba\x2a\x97\x6a\xae\x14\x13\xea\x90\xd2\x49\xd2\x20\xc2\xc9\x73\xf5\xa8\xbf\xda\x82\x01\xd2\x88\xf7\x49\xf8\x69\xd2\x91\xcf\x88\xaf\x30\x5d\xd7\xcf\x6d\x62\x48\x00\xdf\xf5\xea\x8b\x1a\x36\xea\xf7\x77\xa2\xd4\x9e\xae\x1d\xe1\xf4\x6c\x5b\x0b\xf0\xaa\x28\x0e\x08\xa1\xc7\x34\xf9\x05\x09\x78\xad\x3e\x3a\x89\xd7\x9e\xa2\x6b\x31\xe2\x72\x34\xe5\xaf\x05\xfe\xe8\xcb\x31\xba\x9d\x67\x6d\x91\x52\xb3\x1c\xde\xe2\x26\xc9\x95\xee\xa1\x40\x1b\xd7\x30\x7f\x52\xd3\x9d\xe6\x68\x0b\xb2\x6d\x1d\x71\xf2\x42\x7d\xb2\x2c\xc3\x1b\xb0\x1c\x8e\x4e\x09\x05\xee\xbb\x85\xef\xf6\x49\xbf\x0f\xdc\x30\x51\x13\x09\xc7\x48\x21\x49\x0e\x47\x4a\x82\xa9\xe6\x1c\xfd\x78\x08\x37\xc3\x75\x53\xb6\x73\x6f\x6c\xf9\x39\x52\xf2\x89\x6f\x83\xbe\x68\x28\x30\x7e\x1a\x58\xa3\x1f\x07\x27\x79\xd1\x90\xee\xeb\xdd\xa9\xb6\x89\xf9\x98\x3e\x20\x66\xce\x95\x24\xec\xb5\xe3\x1f\x07\x8f\x39\x2b\x1d\xc2\x8a\xc3\x24\x4e\x74\x75\x3e\xc5\xe3\x27\xeb\x06\x97\x21\x17\xed\x11\x99\xb6\x09\xdb\xc9\xb5\x40\x6a\xc2\x86\xd5\x78\xab\x05\x00\xf2\x53\x66\x3d\xdb\xe3\x71\xad\x27\x0c\xc7\xec\xa8\x59\xc1\x98\x29\xe9\x53\x4f\xac\x0d\xf4\x24\xaa\x35\x04\x9c\x2c\x03\xbc\x58\x8d\x57\x30\xe3\x6e\x1a\x33\xee\x4a\x4f\x9a\xc3\x80\xd0\x2b\xa7\x18\xdc\x24\x58\xfe\x20\xe6\xec\x26\xcc\x39\x19\x8e\x79\x1b\x73\xde\xef\x63\xe6\x78\xbd\x85\xb9\x5a\x56\xd0\x3e\xf7\xf8\xf2\x53\x9c\xac\x02\xfc\xf9\x29\x0c\x09\xe1\xc7\x34\xa1\xfd\x5a\xaf\xe2\x4a\x30\x79\x79\x50\xe3\xbd\x68\x29\x44\xd4\x8d\x7a\x05\x9f\xe9\x15\xba\xdb\x2b\x82\x68\x28\x3c\xc5\x95\xac\x51\xda\x52\xd4\xec\xcf\xce\x92\x8b\xb6\x7e\xe4\xa0\x0a\x96\x4e\x67\x37\x43\xd5\xae\xf7\xf0\x70\xfc\x35\x20\x75\x17\x3b\xfb\x0a\x78\x2e\x77\xf5\x4c\xa5\x07\xf6\x89\xd2\x35\x31\x08\xfd\x2a\xdc\xeb\x05\x92\xf0\x4e\xaf\xed\x02\x06\x7b\x57\xab\xf6\x84\x18\xb5\xde\xb5\x33\xee\x96\xb8\xfb\xc5\xab\x13\xa4\xa4\x29\x60\x95\x62\x08\xdc\x4a\xd3\x57\xba\x3d\x60\xe4\x1d\x92\x87\x88\x3e\x18\x1e\xd7\xcc\x40\x8d\x62\xd4\x10\x05\x8e\xd2\x0e\x2a\x36\xbe\x49\x9f\x68\x8d\x84\x36\x1c\x14\xfb\x49\xca\xb7\x1a\x7c\xdc\x7a\x46\xdc\x51\x2c\x10\xf7\x30\x11\x16\xc8\x74\xaa\xb4\x3b\x86\xfb\x1a\x13\xde\xc6\x44\xc9\x57\x4f\xe9\x8b\xc6\x34\x26\xff\x74\x32\xfb\xa1\x66\xa1\xe8\x8f\x3a\xa8\x7e\xf1\xd5\x54\xa7\x1a\xa4\xa6\x54\xff\x13\x3a\x81\x76\x40\xe9\xfa\x64\x9f\xe0\x3a\x54\x5d\xc3\xbd\x5a\x46\xd8\x38\xd0\x0c\xa1\x22\xc3\x71\x75\xd4\x9c\x7a\xc7\x55\xbf\x8f\x33\xc5\xf8\xae\x58\x75\x1a\xcc\x8f\x93\xea\x94\x64\x7e\x16\xad\xbb\xe8\xbc\xd9\x45\x4d\xe9\xb9\xdb\x5f\x5d\x9f\xa5\xa5\xf8\x5b\xa3\xe9\x28\x42\x4e\x86\x4d\x05\xab\x4f\x27\xa3\x66\xca\x11\xf9\x52\xcb\x94\x76\x76\x57\xb3\x2a\xe5\x87\x43\xbb\x86\x3a\xd3\xf0\xb4\xd9\x68\x58\x61\xc6\x59\x96\x4a\x54\x97\xc6\xa0\xbf\xba\x49\x21\x5c\x20\x3f\xd7\x75\x28\x95\x43\x4d\x04\xba\x48\x53\x89\xd0\xb3\x41\x98\x3e\xe1\xa7\x7d\xc2\xc6\xba\x46\x37\xb3\x84\x2f\x8d\xe6\xdd\x84\xb3\x0d\x00\xdf\x3a\xc0\x6b\x78\x4c\x27\x3f\x34\xc4\xcc\x1e\x7c\xaf\x26\x6c\xf2\x58\xe7\x02\x55\x0f\x64\xd8\x57\xf1\x4b\x9d\x1c\x08\xb8\xb7\xad\x3e\x35\x75\xf7\x7a\x1d\x43\x6e\x22\x41\x68\xea\x8d\x0e\xea\x9c\xd7\xd7\xea\xcd\xe7\x54\x82\xd2\x3e\x87\x15\x48\xf2\x42\x69\x8e\x42\xeb\x67\xf0\x19\x49\x40\x8a\x07\x3e\xa9\xc4\x67\x4a\xa8\x62\x05\x15\x3c\x52\xe2\x57\x91\xd5\xcc\x01\x41\x65\x0f\x7c\x55\x9f\x91\xad\xac\xae\x41\x60\xac\xfb\x42\x90\x27\x9a\x7a\x1a\x47\x9b\xbf\x3f\xc2\xf5\x8e\x80\xe1\xbb\x67\xc8\xc0\x81\xf5\x4a\xac\x8b\xa7\x8e\x87\xc9\x48\xf5\x2c\x21\x84\x1d\x8f\x92\xe1\xd8\x00\xc6\x4e\x31\x48\xdd\x06\x57\x6d\xf0\xa0\x8d\x6d\xe7\xa0\xb8\xbe\xde\x3b\x12\x0c\x31\x1b\xfd\x67\xfb\x29\x3b\x22\xdf\x1f\xeb\xcf\xc9\x63\x3d\x81\x85\xfb\x71\x9f\x9b\xeb\xac\x96\x56\x29\x6b\x29\x2c\x40\x36\xa5\xb0\xc0\x8d\x94\x3e\x51\x62\x4e\xb6\xc4\x5c\xdd\xd0\x23\xcf\x17\xa2\x25\xed\xf1\x95\xac\x65\x4d\xd8\xcc\xd0\x34\x33\xae\xd5\xde\xe7\xa8\xce\xaa\x88\x3d\x1a\xb3\x23\xd9\x1e\x27\x5a\x5f\xec\x07\x79\x35\x99\x83\x8d\x27\x42\xb7\xba\x07\x1d\xba\xe5\x32\x9f\x4b\x64\xda\xb9\xa1\xce\x46\x15\xe1\xcb\x61\x08\xf2\xb8\x2e\x6b\xeb\x0d\x36\x12\x1e\xb6\xf5\xf8\x21\x18\x15\x49\x76\xa8\xbc\x7d\x52\x23\xd0\xfc\x5c\x2b\x65\x5d\xaa\x72\x3f\xd8\x35\x6b\x7e\x76\x32\xb3\x29\x1e\x5b\xc2\x1f\x05\x9b\x4f\x88\x1e\x8e\xf0\x9d\x2f\x58\x31\xa4\x47\xe2\xa4\xa5\x05\x51\x4f\xae\x63\x39\xa1\xa7\x89\x98\x50\x4f\x91\x60\x93\xee\x4d\xbd\x43\xd5\x2a\x41\x58\xb3\x0c\x09\x14\xd3\xa7\x75\xa9\x37\xae\x43\xdd\x94\xa6\x93\xed\xd4\xa8\x87\xdd\xf5\x35\xd5\x43\xa6\xd9\x79\xc7\xc3\xe4\x04\xf9\xc4\x9a\x13\x40\x21\x37\x7e\x13\x7c\x12\xf5\x27\xe0\x66\xc5\x56\x43\xf2\xd2\x2e\x1d\x8c\x92\x47\x86\x78\x7c\xd3\xea\xa8\x63\x71\x50\xeb\x3b\xed\x95\x50\x98\x09\x43\xb0\x5c\x79\xec\x48\x5d\xcf\x13\x2f\xbd\x08\xab\xf7\xc0\xbe\xc0\xcd\x5d\xaa\xb4\x51\x1e\x96\x64\xad\x2e\xbf\xbd\x78\x46\x86\xe3\x93\x9d\x0e\xc8\x70\x23\xe7\x7f\x7d\x21\x64\x38\xc6\x6f\x90\xad\x1f\xb8\xcb\x07\x5d\x65\x31\xbc\xa9\x17\x45\xb5\xb6\x60\x73\xef\x76\x8a\x2a\x91\xf5\xfb\xe3\x7a\xbf\x31\x83\xa9\x26\x5e\x8d\xda\xe1\x08\x86\x18\x72\x32\x1c\x67\x87\xd5\x21\x9a\xb6\x64\x8d\x12\xbe\xf8\x88\x8e\x8d\xc4\x4b\x49\x17\x58\x50\x92\x9a\xb2\x87\xcd\x1a\x20\x6d\xca\x5e\x35\x7b\xd9\x1c\x64\xda\x9c\xf5\xd3\x86\x1e\x96\x43\x89\x31\x4c\xeb\xa9\xd6\x21\x31\x27\xd3\x16\xbf\x42\x41\xe6\xe3\xe2\x68\xde\x2f\x0f\xf3\x71\xd1\xef\x63\x9f\x61\x52\x28\x89\x68\xdb\x99\x14\xa7\xaa\xc2\xfa\x53\x9f\x14\x0f\x86\xc7\x41\x8a\x96\xc0\xe3\xbc\x4f\xca\x16\xd8\x47\xa4\xec\xf5\x50\xd6\xef\x2b\x42\xa9\x4a\x3a\xf6\xa3\x9e\x22\x06\x5c\x1f\x91\xc0\x94\xb4\xe9\xab\xd4\x3d\xbd\x5d\xd8\xa6\x6f\xb3\xa0\xca\x36\xce\x8e\x6e\xe4\xae\x31\x76\x05\xba\x59\x44\x41\x59\xf5\xfb\x76\xe8\x4c\x18\xf0\x40\xa6\x7c\x0a\xf6\x4d\x9c\xb0\x6c\x4f\x62\x41\xf6\x67\x1d\xd9\x87\xc1\x77\xa5\x06\x5c\x99\x9d\xdc\x3d\xa3\xba\xa9\x6a\xcb\xd6\xc6\x56\x2d\x60\x83\x65\xbf\xe7\xdf\x40\x30\xd9\x02\x38\x3c\x27\x7c\x1e\x00\x17\xaa\x4e\xc7\x4d\x84\x92\x7a\xb2\x69\x0b\xba\x06\xae\xaf\xda\x53\x8d\x3e\x81\xf1\x47\x34\xc1\x7a\xc4\x1c\xc4\x50\x4f\xe3\x70\xbf\xe4\x75\x63\xbf\x44\x2b\x1f\xc7\x37\x6f\xf6\x4d\xe4\xe9\x36\xb9\x79\x93\x7d\xf2\xda\x6c\xe5\xe3\x60\x0f\x73\x74\x1a\x4c\x93\x4f\x1a\xad\x8a\x06\x31\x6e\xab\xfb\xc9\x6e\xdd\x8a\xb2\x61\xf5\xbf\x84\xd5\xdf\xdc\xd1\xf5\x7e\xab\xd2\x9f\x9a\x55\x82\xfa\xd7\x57\x1a\x4a\x58\xf9\xaf\x35\x0f\xd5\x62\x5d\xe5\xf4\xfa\xd8\x7b\x24\xf4\xe1\x4d\xd8\xf9\xef\x77\x05\xfd\x9e\x9d\x93\x70\x1f\xe4\x58\x4e\x44\x5f\xe9\x33\x7e\xbe\x4f\x74\x45\x7d\x64\x34\xcd\x61\xb2\xff\x80\x2a\x98\xd9\x7e\xd8\xe1\x3c\x3b\x71\xfe\x9c\xfc\x86\x64\xf7\x61\x94\x13\x80\x3b\x67\x52\x7e\xf3\xcb\x57\xff\x5b\xc7\xd1\xd4\xd7\x9c\x2c\x49\xbf\x84\x65\x78\x1b\x6c\x94\x35\x0f\x99\xb2\x1b\x0e\x99\x38\xc6\x50\x05\xdf\x33\x07\x1c\x4c\xc9\x70\x3c\x3d\x72\xef\xe3\xa9\x5a\xbe\x4e\xa6\xa7\xe4\x37\x7f\xc8\x34\xfd\x0b\x6f\x1c\x32\x4d\xfb\x23\xfc\x17\xae\x0f\x99\x2a\x95\xf3\x39\x52\x05\x70\x1f\x4d\x1f\x0c\x8f\xab\xc9\xf4\x77\x1c\x32\x65\x9e\x8f\xaa\xad\x3e\x05\xfe\x42\xee\xdd\x85\xef\xc9\x5d\xf8\xf9\x96\x9d\x74\x7d\x7a\x61\x5a\xa0\xab\xb5\xbc\x4c\x7e\x86\xb9\xe0\xab\x17\x79\x29\x93\x14\x24\xd7\x0f\x33\xc8\x59\x2e\xf3\xb4\xc8\xbf\xd0\x44\xa2\x0a\x43\xba\x5e\x53\x36\x4b\x24\x3a\xc7\xb0\xae\xca\x65\x22\xd1\x1c\x83\xa6\x6e\x22\xd0\x25\x86\x05\x95\x89\x44\x14\x43\x49\x65\x22\x10\xc7\xb0\x4a\xd7\x89\x44\x4b\x0c\x39\x9b\xd1\xcf\x74\xf6\x52\xbf\x6f\x30\xcc\x79\x31\x2b\x12\x81\x16\xe6\x51\x24\x02\x9d\xb9\x2d\x85\xe4\x39\x48\xfe\xe3\x5b\x0d\x7b\xf2\xab\x06\xcd\xbd\xfd\xb0\xdd\x22\x0c\x9b\x9b\x8e\xbb\x9d\xf0\xbc\x23\xae\x87\x3b\xa7\xcc\xee\xe3\x7f\x89\xd6\xb1\x6f\xc0\x54\x3b\xe7\xe3\x8f\x53\xc6\xb8\x8c\xd6\x54\xcc\xb9\x58\x45\x2b\x3e\x8b\x86\x83\xe8\x49\xbe\xc9\x4b\xbd\xbd\x78\x19\x7d\xa1\x82\x47\x54\xe5\x1e\xc4\x4e\xa1\x93\xff\x25\xec\x3a\x4e\x1e\x0f\x13\xa1\x56\x35\x0f\xc8\xd0\x6c\xa4\x26\x87\x1c\x1d\x4a\x38\x0c\x0e\x55\xb4\x4c\x1c\x26\xac\x75\xba\xec\x41\xf6\x03\x44\x04\x83\x25\xdc\xdc\xaf\xea\xe1\x77\x28\x5b\xb6\x32\xf5\x46\xe3\xf1\xa1\x4c\x64\xcb\xaa\xa4\xde\xc8\x1e\x64\x2b\x73\x46\x70\x34\x3c\x96\x89\x68\x19\x91\x74\xe4\x7b\xd0\xca\x57\xb6\x94\x7a\x93\x93\x82\x34\x35\xba\x57\x5d\x50\x24\x74\xe7\xbc\x29\xe4\xfb\x77\x93\xba\x9d\x7e\x43\xb0\x17\xcd\xce\x54\x0b\xfd\xce\x43\x90\x03\xd9\x38\xfb\xa8\x4b\x10\x42\x46\x77\x86\xd7\xd7\xea\xe1\x70\x74\x67\xd8\x38\xb1\xa8\x85\xd8\xb5\x6c\x6c\xf9\xd7\xe5\xff\xa2\x7b\xe0\xf5\xf3\x3b\xa3\xff\x1e\x36\x76\xbf\x6b\xf3\x1c\x97\xe5\x2f\xb2\xb1\x11\xed\x84\xba\x3e\xb8\xa5\xfa\xe0\x76\xec\x69\xf5\xae\x5a\x17\xf4\x2e\x12\xa6\x6c\xc6\x4b\x35\x96\xec\x5b\xa9\xe4\x47\xb8\x90\xb8\xfc\xba\xca\x4c\xe1\x4f\x42\x22\xf1\x17\xd1\xa7\x7f\xa1\xd8\xc8\xa3\x54\xa6\xec\xae\xee\x0a\x63\x42\xf2\x8e\x4c\xe2\x17\xef\x62\x88\x9f\xfe\x1c\x43\xfc\xfd\xbb\xd8\x1d\xbc\x5e\xcd\xf2\x8d\x19\xd5\x82\xae\x12\x89\x18\x86\x15\x57\x52\x80\x63\x58\xe7\x89\x45\x13\xa8\x79\x7a\x0a\x19\x2f\x13\x07\x3f\x94\x39\x4b\x1c\xf8\x20\x53\xfb\x22\x53\x06\xa9\xcf\xa7\x9e\x20\xf5\x39\xd5\x13\xa4\x3e\x6f\xaa\x33\x2b\x60\x13\x89\x6a\xc8\x31\xcc\xe8\x42\x50\x5a\x26\x1b\x50\x50\x96\xc9\x42\x0b\x8a\xd7\xbc\x48\x45\x72\x06\x92\x9b\xa7\x4b\x50\xb8\x27\x9e\x0a\x50\xf0\xc5\xa3\xb4\x54\x12\x2d\xc3\xc0\xe8\x22\x95\x34\xa9\x20\x3d\x2b\x93\x29\xac\x72\x96\x48\x94\x2b\xb1\xf5\x39\x91\x28\xc5\x90\x15\xe9\x6a\x9d\x08\x54\x62\xc8\xf8\x6a\x9d\x0a\x6a\x84\xde\x67\x2e\x12\x89\x0a\x0c\x8c\x2b\x49\x29\x45\xa5\x94\x75\x9a\x2c\x41\xcd\x1b\x39\x5b\x24\x7e\x12\x01\x3d\xe7\x25\xf5\xf4\x07\x82\x57\x6c\x66\x12\xf4\x23\x48\xfe\xac\xe0\xa9\x4c\xbc\x54\x0b\x58\x6d\x0b\x79\x79\x92\x9e\x24\xfa\x3f\xe4\xe5\x73\x36\x57\x72\x99\x26\x6b\x2d\x0a\x57\x9d\xa2\x50\x34\xb5\x36\x06\x9c\x4c\x4e\x21\x23\xd4\x9c\x54\x01\xc7\xe3\xac\xd7\x43\x8c\xf0\xc1\x9a\xaf\x11\xc6\x63\xac\x3e\xb2\xc1\x67\x60\x83\x4b\x93\xc1\x6d\xfb\x6c\x9b\x02\xd6\xd8\x81\x69\x2b\x81\xd1\x70\x88\xfd\x99\xa6\x3e\xbb\xbc\xfa\x9c\x48\xb8\x4c\xc4\x16\xc3\xc1\x70\x6c\x4f\x27\xdc\x34\x6d\x52\x62\x7e\xf6\x1b\xcd\x64\x7c\x40\xe4\xe5\x9a\xf2\x79\x64\x6d\x22\x5c\x2b\x31\xa9\x3f\xb4\x25\xf1\xb7\xef\xc4\x65\xce\x16\x91\xe4\xda\xdc\xe8\x23\x22\x04\x7f\x8c\x78\x6d\x71\x57\x0e\xa2\x77\x4b\x2a\x68\x94\x97\x11\xe3\xd1\x45\x7a\xa9\xf2\x9e\x33\x7e\x11\xe5\xf3\x3a\x57\x94\x0a\x1a\xc5\x72\x49\xa3\x32\x5d\xd1\x38\xca\x99\x36\x70\x7a\x5a\xac\xa2\x92\xb2\x92\x0e\xa2\x37\x34\x9d\x45\x2b\x2e\x68\x94\x9e\xf1\x4a\x46\x72\x99\x97\x51\x2a\xa3\xa5\x94\xeb\xe4\xce\x9d\x75\x9a\x9d\xa7\x0b\x3a\xa0\xc5\xea\xb0\x48\xd9\x62\xc0\xc5\xc2\x25\x96\x77\x5c\xea\x9d\x8c\x0b\x7a\xa7\x48\x25\x2d\xe5\x9d\x47\x69\x99\x67\xe5\xff\x8f\x90\xe8\x62\x99\x67\xcb\x68\x46\xcb\x4c\xe4\x67\xb4\x8c\x2e\x96\x97\x51\x2e\x15\xc8\xba\x15\x05\x74\xca\x66\xd1\xc5\x32\x95\x1a\xac\x33\x2a\x25\x15\xd1\x86\x0a\x3d\xdd\x5c\xe4\x45\x11\x15\x9c\x9f\x47\x45\x7e\x4e\x07\xdf\xba\x9e\x3a\x18\x6d\xed\x49\xb7\x9a\x72\xae\xaf\xed\x93\xa7\xfe\x48\xf7\x47\x94\xb3\x52\xa6\x2c\x53\x04\x7e\x92\x4a\x7f\x40\x23\x07\x0b\x2a\xdf\xe5\x2b\x8a\xb0\xde\x1a\xf4\x6f\xaa\xd4\x01\x8a\x95\x44\x8e\x15\x9d\x70\xcd\x56\x99\x26\x1c\x56\x19\x28\x92\x93\xec\x14\x84\xfa\xc7\xfa\x23\xe0\xb8\x6e\xd6\xf5\xbe\x02\x2f\x7e\xf3\xe8\x84\xcf\xe8\x94\x16\xab\xe9\x59\x95\x17\x32\x67\xb5\x4d\x4b\xaf\x17\xbf\x79\xf4\x54\x29\x24\xdd\xdf\xaf\xaf\x91\x24\x2f\x84\xdd\xb1\x15\x7a\x97\x23\x7e\x4b\x65\x23\x37\xa9\x6b\x53\xb9\x99\xcd\xcd\x4c\xee\x24\x09\x2c\x6f\xae\xea\x1d\x00\x09\x53\x22\xc6\xf6\x73\xe5\xa0\x31\xaf\x53\x6b\x70\x73\x65\x10\xad\x94\xb0\x9d\xaa\x7f\x6d\x44\x2b\x52\x0d\xa6\x23\x98\x92\xe9\x60\x3a\xda\x7a\xb3\x15\x55\xda\x57\xa3\x89\x60\xd5\xb2\x00\x12\x05\x45\x4e\x96\x03\xaf\xf7\x28\xb0\xd3\x46\x82\x39\x96\xc8\xad\xae\x79\x40\x48\xda\xdc\xb9\x3d\x18\x79\xe5\xb6\x24\xc3\x71\x79\xe4\xb2\x8e\xcb\x7e\xdf\x76\x52\x3e\x29\x4f\x21\x55\xff\x6e\xea\x24\xd5\x9b\x1a\x2e\x10\xe6\xa7\x9d\xf9\x8f\x32\x40\x5b\x1b\xeb\x16\x07\xc1\x24\x2d\x8e\x57\x89\x3c\x12\xc7\x9b\x64\xb1\xc3\xbd\x6f\xa5\xc8\xd9\xa2\xde\x73\xde\xa4\x45\x45\x5f\xcd\x11\x06\x4e\x44\xfd\xe6\x57\xa3\x84\x10\x7e\xbc\x4a\xe8\x11\x57\xd5\xe9\x7e\x08\xb9\xe1\xfa\xba\x69\x96\xa5\x99\x63\xdc\xc8\xe2\x39\x42\x04\x1c\x81\x32\xc2\x90\x9e\x80\xc5\x60\x3a\xc4\xf8\x80\x90\x95\x43\x21\x1b\x5b\xd3\x2c\x41\x44\xc0\x12\xd2\xb1\x84\xa9\xe7\x78\x95\x34\x9a\xf6\xe0\x4d\xf5\x14\x5e\x7f\xf0\x67\x9e\x7f\xc5\xf6\x88\x05\xaa\xe6\xa7\xbf\xe2\xc3\xa1\x3b\x6c\xaa\x1c\x14\x2b\x95\x52\x3d\x20\xa3\xaf\x80\xd7\xe4\xbc\xdb\xc8\x39\x52\x39\x47\xdd\x39\xef\x35\x72\xde\x55\x39\xef\x76\xe7\xbc\xdf\xc8\x79\x4f\xe5\xbc\xd7\x9d\xf3\xbb\x46\xce\xfb\x2a\xe7\xfd\xee\x9c\x7f\x6d\xe4\xfc\x4e\xe5\xfc\xae\x3b\xe7\xdf\x3a\xb4\x7a\x3d\x9f\xe7\xa5\x9a\xd8\x54\x4a\x12\x65\x46\xcf\xb7\x13\x7d\x24\x15\xf5\xcb\xe8\x22\x97\x4b\x33\x15\xc8\x65\xca\xa2\xbf\x46\xb4\xa0\x2b\xca\x64\x39\x88\x9b\x9e\x05\xab\xed\xd7\xb4\x51\xa7\xe4\x65\xc4\x59\x71\x19\xcd\xe8\x3c\x67\x74\xa6\xe6\xb1\x9c\xc9\x12\xa2\xb9\x52\x06\x4a\x88\x64\xbe\xa2\x25\x44\xd9\x32\x15\x25\x68\x4f\x1a\xb6\x28\x21\x2a\xf2\x52\x96\x11\x9f\xdb\xba\xd4\x8a\x2e\xd2\xec\x5e\x82\x9e\x38\x2c\xdc\x5d\x19\x14\xc8\xed\x75\x4f\x73\xa9\x69\xb4\xc6\x18\xa6\xc3\x44\xc2\x74\x94\x88\x6d\xcb\x39\xc2\xad\x57\xe8\x85\x1d\x81\xfb\x16\x21\xd1\x59\xbf\xdf\x32\x2c\xf5\x96\x40\xf5\x3a\x9c\x19\x11\xa2\x4d\x72\xe4\x84\x9d\x36\x3f\x08\xf3\x41\xa8\x0f\xbb\xbb\x4a\x79\x07\x02\x49\xd2\x0d\x7b\x5a\x4b\x1c\x43\xc8\x50\xcf\x70\xe3\xb2\xaf\x4f\x89\x3b\xcd\x33\x85\x5d\xd5\xe5\x66\xec\x5c\x62\x60\x84\x6a\x60\xcd\x10\x6f\x5b\x67\xb2\xc1\x74\x14\x64\xb6\x72\x80\x11\x16\xe8\xe8\x3a\x8f\x08\x37\xea\xcb\xc6\xc2\x26\x74\x66\xd8\x61\xad\x37\xa9\x66\x17\x1e\xa5\xd1\xc7\x27\xf4\xac\x5a\x0c\x32\x91\x96\xcb\x8f\x8a\x6c\x2b\x3e\xab\x0a\x1a\x7d\xd4\x26\xdd\x1f\xa3\xb8\x5f\x20\x81\xfb\xf1\x07\xf6\x6e\x49\xa3\x15\x2d\xcb\x74\x41\xa3\xb5\xe0\x9b\x7c\x46\x67\x6a\xfd\xaa\xd4\x8c\x8c\xcf\x68\x94\x56\x72\xc9\x45\x94\x97\xc9\x07\xf6\x81\x45\x51\x14\xc5\x7d\x1a\x1e\x3d\xcd\x5b\x0b\xbc\xd0\xbb\xe2\x5f\x80\x51\xb5\xf6\xce\x68\x3f\x65\x94\xa5\x55\x59\xc3\xf5\x31\x4b\x4b\xfa\x31\xa2\x9f\xd7\x82\x96\x5a\x03\x72\xf8\x0c\x3e\xb0\x57\x8c\x2a\x46\xd7\x6a\x92\x48\x59\xb6\xa4\x65\x44\x99\xc2\x4a\x0f\xdb\x34\xd2\x0d\x9a\x61\xb1\xa4\xd1\x9c\x17\x05\xbf\x50\x2a\xa4\x1e\x0f\xd1\x82\x2b\x15\x4b\xf0\x6a\xb1\x0c\x10\x9e\x21\xaa\xa9\xf5\x07\xe9\xc5\x70\x73\xa9\x1a\xec\x15\x97\x32\x15\x72\x50\xe4\x8c\x2a\x4e\xa1\x6c\xa6\x9f\x8f\x63\x95\x31\x67\x34\x8a\xfb\x61\x9e\x24\x3e\xa3\xf2\x82\x52\xf3\xb1\x6c\x7d\xed\xc7\x1a\x2d\x95\xe8\x2a\x6a\x2d\x82\xed\xe2\xd0\x72\xf9\xb8\xa5\x65\x7b\xcd\x30\x3e\x72\xa9\x0f\x62\x9d\xe9\x8c\xf3\x82\xa6\x8d\x3c\x91\x3c\x8e\xdf\x89\x8a\xc6\x49\xfc\x2c\x2d\x4a\x6a\x32\xb2\x6a\x75\x46\x45\x33\x5f\x3f\x8e\xf7\x4d\xd5\xb6\xb9\x6f\xe3\xbe\x5a\xd4\x1f\x0c\x71\x3f\xfe\xd6\x54\xe4\x87\xa4\xaf\xe8\xdb\xf8\x5b\x93\x6b\x84\xfb\xdf\xc6\xdf\x8e\x03\xd5\xd6\xd5\xa3\xde\xe3\x70\x49\xa1\x8a\xf7\x7a\x81\xaa\xea\x75\x03\x33\x45\x56\x67\xa6\x1d\x34\x84\xef\xb4\x32\x65\xc4\x5d\x6c\x6c\x80\xa7\x64\x72\xda\x16\x4b\xa6\xae\x03\x42\x58\xaf\x37\x35\x4b\x9c\x19\x52\x62\xca\x6f\xc3\xc6\x28\xee\x4f\x07\xbf\xf1\x9c\xa1\x18\x62\xdc\x8f\x71\x6c\xe7\xee\xb4\x3c\x8f\x03\x13\xa8\xf8\x48\xa6\xe5\xb9\xa5\xf0\x8e\x02\x68\xf3\xe8\xe4\x81\xdb\x8b\xd3\xac\xb8\x94\x7a\xd3\x57\x95\x3a\x9a\x51\xc5\x74\xe2\xc1\x6e\xc1\xfa\x93\xa9\xff\xb5\xe0\x19\x2d\xcb\x8e\x8c\x6b\xf3\x25\x51\x7c\x93\xcf\xfa\xb1\x2d\xd1\x54\x8c\xa7\x24\x9e\xa8\xc6\x95\xf8\xc2\x0d\x29\x17\xe6\x1b\xe3\x69\x9f\xc4\xe0\x33\x5a\x29\xe7\xc4\xdb\xb4\x1f\x9f\x1a\x62\x74\x08\x54\x95\xa6\x1b\xde\xab\xbf\xbb\x8c\x6f\xa9\x6c\x52\x44\xeb\xf4\x86\x22\x1d\xab\x89\x50\xa1\xeb\x5a\x4d\xec\xd4\xff\x24\xcf\xda\x0d\x08\xdd\xc0\x94\xc4\x71\xbd\x5f\xec\x55\x5d\xcf\x13\xdc\xd9\xb9\x28\x96\xe0\xa7\x18\x2a\x92\x4d\x86\xa7\x63\x45\x94\x28\xee\xa3\xf8\x4a\x2f\x26\xae\xaf\x63\xe4\x1e\x8e\xec\xc3\xb7\xf1\xb7\xe6\x21\x1b\xe8\x8d\xd1\x57\x73\x14\x47\x31\x3e\x1a\x1e\x67\x89\xe2\xa8\x4c\xf1\x11\x6e\xea\x8b\xfd\xe9\xb6\xc5\xeb\xc6\xfe\x6f\xcf\x8a\x2e\x3e\x52\x3d\x2c\xb9\x9d\xa4\xb1\xeb\x69\xa9\x16\xad\xd3\x0b\x7a\x36\x2d\x79\x76\x4e\xfd\x68\x3a\xba\xa0\x67\x26\xe5\x41\xac\xe7\xba\xae\xf1\x60\xc7\x00\xeb\xc7\x11\xd1\xa4\x6a\x8c\x05\xbd\xeb\xef\x0e\x0e\x8f\xe3\xab\x6d\x9c\xc4\x57\x51\x30\x3e\x22\x35\x40\xa2\x6d\xbc\x75\x6d\xe6\x4c\x52\xc1\xd2\x42\x29\x37\x55\x26\x2b\x41\x1f\xc4\x3b\xe6\xca\x6e\x10\x0b\xba\x2e\xd2\x8c\xa2\x3b\x1f\x3e\xdc\x59\x40\xfc\xe1\xc3\x87\x0f\x31\x0e\x52\x99\x49\x65\x8d\x44\x69\x12\x65\x23\x51\x98\x44\xd1\x48\xdc\x98\xc4\x4d\x23\x71\x68\x12\x87\xb5\xfb\x92\x38\xa6\xc1\xf7\x6f\xcd\xf7\x6f\x63\x9c\x84\xc9\xf1\x9d\x05\x7c\xfb\xe1\x43\xfc\xad\xd9\x5b\xdb\x90\xc3\x11\xac\xc8\x10\x16\x64\x04\x67\x64\x08\x97\x6e\x83\x7e\x72\x1a\xd7\x5b\xf1\x9f\x12\x01\xd9\x6a\x9d\x30\xd0\x5a\xd8\x30\x69\x28\x65\xc3\x78\x6b\xd2\xef\x26\x1c\xb2\xa5\x48\x32\xa8\xd6\xb3\x54\xd2\x64\x0a\x8b\x2a\x9f\x25\x55\xbd\x41\x9f\x62\xd0\x13\x5f\x52\x9a\xdf\xc7\x69\x49\x93\x39\x38\x6e\x48\x66\x7a\xef\x68\x41\x64\xed\xaf\x1d\x90\x5a\x38\x5c\x8d\x0d\xec\x74\xa8\xfe\x8d\xf0\x16\xc3\x19\x41\xa2\x51\x24\xb4\x62\x45\x1d\x3a\xa4\x50\x7a\x18\xdd\xaa\xb2\x7b\x0b\xea\x56\x40\xe0\x2d\xc6\x70\xb9\x03\x92\xdf\x07\xc3\xf0\x8e\x74\x6f\x90\x5d\x90\x8b\xeb\xeb\xab\xed\xf8\x62\x12\x1f\x5d\xc7\xa7\x7b\xab\x40\xaa\x0d\x40\x36\x3b\x9e\xc4\xd7\x0f\xf6\xe7\x56\x32\xa0\x99\xfb\x81\xca\xbd\x17\x0b\x81\xa4\xde\x9f\x6d\x14\x39\x3a\xba\xa9\x88\x44\x62\xb7\x48\xbf\x1f\x9f\x92\xd5\xc0\x74\xa5\x1e\x88\xe7\x64\xe5\xc7\x31\xbc\x25\x68\x33\xa8\x77\x01\x41\xbd\x9c\xa4\x27\xb0\x19\xd8\x4d\x44\x0c\x9f\x55\x16\xbb\x0d\x09\x1b\xb3\xe7\x88\xe1\x91\x4a\x75\xfb\x94\xb0\x31\x3b\x8f\x78\xbc\x19\x30\x2e\x61\x33\xf8\xcc\xc5\x38\xa4\x8c\xa2\xe3\x66\xc0\x45\x08\x5a\xaf\xa7\x13\x53\x0b\xd7\x43\xb2\x19\xac\xd2\xcf\x70\xa2\x6a\x5e\xe5\x0c\x36\x03\xbb\x74\xc2\x61\x55\x0f\x88\x2e\xb5\xa0\x0d\xc2\x98\xc4\xa2\x91\xf8\xc0\x64\x94\x8d\x8c\x26\x5f\x23\xed\x8e\x29\xcc\xe8\xa7\x30\x95\x98\x54\xfa\x69\xbc\x19\x28\x04\xd7\xb9\x86\xf2\x0d\xd9\x0c\xf4\x2e\x2e\x3c\x55\x70\xda\xed\x5f\xd8\x0c\xd2\xb3\x12\xc3\x4b\x5d\xcf\x22\x95\x74\xbc\x31\xfb\xc3\x1b\xb3\xbf\x6c\x7f\xd5\x4f\xa9\x51\xd3\xbb\xd4\x9b\x81\x49\x2b\x2d\xb6\x65\x88\xe8\xff\x9a\xf6\x3f\xaf\x43\xa8\xfe\x4b\x27\xae\xf8\x6c\xbc\x19\x08\xba\x0a\xf3\xdf\xb9\xa3\xbf\xcd\xf2\x4d\x03\x39\x9d\xa8\x97\x80\x4f\x9a\x5f\xfe\x62\xaa\xaa\x8a\x30\xf1\x50\x27\x96\xd5\x59\x83\x87\x4c\x3f\xcd\x54\xa3\x76\x23\x5c\x31\x82\xdb\x1e\x57\x68\x54\x82\x29\x74\xec\x26\xba\xa6\xd4\xe3\x5b\xc4\x41\xfc\x63\x55\xea\x89\x87\x9a\x6d\x0a\x25\x19\x12\x35\x2e\x3f\x39\x69\x76\xc2\xe5\x52\xe9\x71\x5b\x78\xf6\x3b\xeb\x92\x48\xd5\x86\x93\x4f\x5b\x0c\x2f\x3a\x86\xb9\x6d\x40\x97\xd2\xeb\xbb\xed\x16\x9e\xff\xce\x36\x5e\x20\xdb\x8a\x69\xe6\x55\xc7\xc0\x6c\xba\x6b\xec\xca\x31\x57\xb3\xfb\x44\x08\x61\x6e\x6b\xc8\xb5\xc6\x06\xd3\x61\x47\xda\xc8\x01\xa1\xc4\x9d\xce\x33\x1d\x82\x4e\xf7\x10\xfd\x48\x10\x6d\x81\x04\xac\xed\x89\xa7\x5b\xbe\x17\x00\x05\xd3\xbb\x09\x6b\x41\x76\x4f\x35\xca\xdb\x50\xf0\x0e\xc8\xb8\x83\xac\x99\x76\xd7\x41\xab\xd6\xcd\xdc\x42\xcb\x0d\xb4\xa0\xbf\x7b\xa8\xd9\x0e\xc8\xe0\x35\xa3\x06\xd0\xf7\xdb\x40\xc3\xf4\x5e\xc2\x5b\x90\xdf\x57\x00\x64\x6d\x88\xb2\x0e\xc8\xb3\x0e\xc8\x33\x07\x79\x33\xed\x9e\xc3\x46\xad\xaf\x33\x8b\x4d\x66\xb1\xc9\x0c\x36\xa0\xf3\x79\xac\x78\x07\x56\x90\x19\xbc\xaa\x26\x5e\xdf\x75\xe2\x05\xd3\xfb\x49\xd6\x42\xee\xbb\xc6\xee\xb2\x03\xb0\xea\x40\xae\xea\x40\xae\xea\x40\xae\x72\xc8\x35\xd3\xee\x3b\x84\xd5\x72\xbd\xb2\x08\x57\x16\xe1\xca\x22\x5c\x19\x84\x41\xe7\xf7\x88\x77\x1d\x27\x65\xbf\x63\xa3\xc5\x44\x9e\xf0\xae\xac\x97\xfa\x5c\xd2\x6e\x44\x53\xe3\x23\x93\x21\x69\x7c\x14\x3b\x7c\x63\xa6\xcd\xe2\x93\xd3\x1d\xb7\x57\xeb\xef\xd7\xb1\xe0\x10\x3b\xf1\x01\x42\x43\x98\x29\xa2\x7a\x6b\x18\x32\xe2\xac\x05\xc7\x99\x02\x88\x6b\x5f\x1f\x36\xc9\x4e\x83\x63\x2f\xbe\x13\x16\x20\xac\xab\x06\x4b\x38\xea\x9b\x57\xea\xb7\x7f\x34\x94\x7a\x87\xca\x2a\x50\x43\x8c\xed\x3e\x30\x50\x42\x03\xb0\xab\x46\xb8\x85\x75\x3d\xf0\x6b\x5b\x95\x5b\xda\xf3\xaf\xcc\x36\x6f\x8f\xe3\xd2\xb0\x79\x2d\x74\xda\x30\xb4\x76\xa4\xaa\x46\xc8\x86\x65\x38\xa0\x6b\xdf\x8d\xdf\x07\x8c\x7f\xe5\x16\xb6\xcc\xc0\x56\xee\xc0\xa6\xe5\xcc\x1e\x00\x81\x6b\x49\x55\xc3\x19\x1a\x9f\x6f\x9a\x43\xd4\x41\x3a\xfd\xd7\x20\xf5\xaf\x99\x5b\xec\x1a\xc0\xe7\xdd\x80\x6b\xb9\x72\x33\xf4\x90\x69\xa1\x55\x23\x11\x06\x88\x58\x34\xb4\xcf\x0a\x4d\x91\xc0\x83\x92\x8b\x60\x8e\xdb\x35\xac\x90\xda\x7c\xde\x28\x91\xb8\xe5\xf0\xf6\x15\x75\xd9\x98\x0a\x26\xb4\x84\xc1\xd2\xca\xab\xa7\x3f\xc7\xd6\xf4\x2b\x7e\xf1\xce\x3c\x1e\x8e\x92\xd1\xd6\x1a\x0b\x74\xae\x5f\x4e\xf2\x22\xb9\x84\xc7\x9c\x95\x49\x06\x99\xfa\xd1\x67\xec\x92\x1b\xd3\x9d\xa9\x3e\x9f\x37\xcf\x95\x37\xfa\x29\xb4\x8d\xd0\xdd\x44\xa0\x99\x7e\xba\x97\x50\xb4\xd6\x4f\xf7\x13\x86\x96\xfa\xe9\xbb\x84\xa3\x0d\x06\x85\xc0\xa3\xcb\x44\xa2\x85\x79\x7e\x9f\xcb\x65\x22\xd1\x19\x56\x8b\x19\x0c\xaf\x09\xfa\x71\xe0\xd2\xc1\x3c\x3e\xba\xc4\xf0\x64\x47\x4d\xd0\x27\x3b\xe6\xf4\xc6\x59\x98\x0c\xf1\xd1\xa8\xbd\xd5\x1b\x6e\x06\xd3\xd6\x66\xb0\x24\xf2\x70\x04\x42\x77\xf2\x76\x8b\xe1\x17\xd5\xb8\x02\x15\xf4\xcf\x7d\xf3\x73\xcf\xfc\xdc\xc5\xf0\xeb\x5e\x20\x6e\x69\xcb\x1e\xdb\x5a\xc5\xc5\x1f\xa4\x4b\x22\x83\xd6\xdf\x13\xd4\xbd\x8a\x39\xc8\xd1\xaf\xb5\x44\xaf\x93\xf5\x52\x48\x2f\xb9\xe0\xc7\x81\xee\x0a\x0c\x3f\x74\xe8\x43\x21\x90\x8c\xd0\x00\x48\xd6\xb1\x3b\xce\x89\x84\x8c\x38\xfd\x46\xc9\x77\x49\x38\x08\x92\x01\xd5\xc3\x40\x81\xfa\x1b\xd9\x05\x27\x4a\xd1\x0f\xb0\x6f\x19\xd6\x1f\x6d\x31\xa8\xca\xb6\xf0\xe5\x77\x96\x95\x7d\xe1\xcb\x7e\xbf\x6f\x9d\xd7\x4d\xa1\x68\x35\xa0\x9f\x90\x00\xe9\xc8\xf4\x73\x87\x52\xda\xd8\xd7\xda\xc2\x3f\x1a\x59\xec\xe6\xab\x1b\x50\xe1\xc1\xe1\xf1\x0b\x24\xac\xb6\x0b\x3f\x91\x9f\xf4\xda\xf5\xa7\x89\xca\x72\x4a\x7e\x1c\xa8\x91\xa3\xc9\xf9\x4f\xb2\x67\xec\xa7\xe8\x7d\x13\x65\xda\x3d\x37\xeb\x93\x72\xad\xb7\x6e\x31\x04\x03\x16\xa8\xc2\xe8\xef\x3b\xd5\x3b\x71\xd0\x55\xb3\x5e\x0f\x1f\x77\xcc\xfd\x74\xab\xd6\xf7\xe3\x00\x34\xb6\xdb\xd6\x37\x7b\x75\x6d\x59\x3b\xc6\x07\xda\xb2\xa6\x52\xb3\x31\xcd\x52\xbe\x3d\x90\x72\x5f\x87\x2a\x10\xbe\x51\x98\x87\x50\xe8\x3e\x14\xf2\xf7\x31\x50\xb7\xa6\xb3\x53\x31\x50\xd9\xd8\x16\x69\xa8\xed\x6d\x6a\xba\x91\xd4\x60\x8b\x4e\x84\x73\xc5\x7e\x66\xd2\xb6\x78\x07\xed\xd6\x14\x17\x12\x29\x0c\x38\x34\x4b\x53\x55\x26\x2c\x00\x4c\xef\x34\x74\xb3\x54\x43\xf2\x1c\x8b\x64\x87\xc3\x6e\xa5\x89\xdb\xc0\x61\xb2\x6b\x93\x46\xd5\x47\x65\x83\x70\x6a\x64\xf1\xbd\x9d\xc8\x24\xca\xd1\x3f\x41\x6a\xf3\x34\x0c\x99\xfc\x4a\x66\xb5\xe4\x05\xae\x97\x61\x5a\xd5\x0b\xf4\xc3\x80\x85\xc3\xc5\x5d\x07\x4e\x7c\xab\xfe\x67\xdb\xa4\x23\x3b\x0f\x48\x1b\x96\xc9\xb6\xdb\x3d\x03\xa1\xa3\x31\x4d\x83\x76\x17\xe9\xb1\x52\xc9\x86\x34\x17\x21\xd7\xec\x91\xbf\xe1\x64\xdc\xcd\x76\x9d\xe2\x61\x0f\x1e\x54\xe1\x01\x19\x51\x28\xf0\x46\x9f\x29\x62\xb6\x6c\x93\x5b\xa3\x33\xdb\x76\xee\xf4\xdd\x32\xe3\xd2\xb1\x41\x50\xec\x9d\x60\xa8\x9f\x71\x99\xd1\xae\xf6\x09\x87\xad\x62\xc2\xe9\x5e\xbe\xd2\xa3\xa5\x92\x8a\xb1\x42\xcc\x34\x93\xe5\xb2\x43\x4a\x79\x88\x45\x08\x71\x9b\xe0\x37\xee\x19\xc8\x64\xc6\xaf\x84\xfa\x57\x1b\x75\xdc\xad\xd5\x4e\x7c\x26\x68\x7a\x6e\xcf\xe7\x1c\xee\x76\xf5\x57\xa3\x6f\xcf\x68\x0e\xec\x47\xf7\x5d\x55\x39\xb2\x9b\x0e\xb6\x22\x31\xb6\x15\x6e\xcb\x8b\x5c\x66\x4b\xa4\xbf\x5d\x65\x69\x49\xa3\x51\xe2\xf2\xe8\xd7\xbb\xc9\x9e\xbe\x1c\x59\x7a\x76\x7d\x68\x7d\xd3\x9c\xbb\x35\xf5\xdd\x4b\xea\xa3\x24\x9f\x79\xd4\xc1\xa9\x7f\xa8\xa5\xf6\xb7\x4e\x40\xb6\x0e\xfb\xf1\xcc\x44\x1e\xdb\x0f\x92\x37\xe7\x09\x6b\x1c\x05\x06\x59\x9c\x34\xdb\xca\x48\x00\x57\x45\x3c\xf4\xad\x0a\xa6\x43\x28\xdb\x49\x81\x5d\xae\x61\xff\x11\xbd\x87\x1f\x0c\x5b\x22\xbf\xda\xc5\x36\xdb\x4d\xea\x90\x3f\x53\x95\x94\xa3\xa9\x04\x71\x78\x1f\x4a\x6d\x97\x92\xfc\x99\x75\xa7\x28\x97\x20\xfb\xa3\xa0\xfe\xad\x63\xb3\xed\xc5\x32\x2f\x28\x3a\xd8\x2f\x1a\x3a\x7b\xaa\x5d\x2a\x52\xd3\x7a\x7a\xc3\xb4\x9e\x4b\x18\xea\x19\x61\x8b\xa1\xec\x1a\xab\x3b\x52\xa6\x31\x66\x23\x39\x96\xa4\x63\x92\x94\x5b\xb5\x66\x3b\xd4\x4b\x36\x25\xbd\xe6\x72\x9f\x36\x1d\xa5\xa8\x6c\x4d\x62\x56\xb1\xb8\x09\x94\x03\x14\x98\xd5\x8f\x70\x5b\xe6\x75\xc8\x64\x25\x33\xb4\x7e\x6f\xa0\x62\x5a\xa6\x15\x37\x50\x66\xbe\x2b\xd0\xb6\x18\x66\x37\x94\xf8\x05\x24\xe4\xa8\x50\x14\xfd\x0d\x09\x7c\x38\xc2\x06\x93\xb5\x24\x68\x69\x0f\x1f\x60\xe9\x3c\x09\x97\xc6\xbc\x4c\xfd\x52\xb9\x4f\xdb\x36\x58\x0e\x41\xe2\xa3\x51\xaf\xe7\x70\x76\x75\x20\x81\xf1\xd1\x50\x6f\x7f\x2e\x07\x0b\x2a\xcd\xd4\x9e\x7c\x52\xa8\x2d\x75\xa3\x6a\x71\x0d\xcb\x81\x76\x48\xd9\x51\x53\x6e\x57\x4d\x73\x57\x85\xfa\xd2\x54\x49\x97\x7a\x89\x53\x00\xf3\xd5\xeb\x89\xd6\x24\x0b\x70\x9f\x97\x83\xda\x49\x05\x96\x6a\xe1\x06\xcb\x81\x71\x86\xc1\xb0\x91\x64\xe9\x4f\x89\x61\xa5\xde\x6a\xf7\x18\x58\xec\xe7\x99\x1c\xad\x14\xb2\xda\x27\xb7\xb9\xbd\x66\x07\x8b\xaa\xf4\x31\x9f\xd1\x2e\xeb\xef\xd5\x20\x5b\x0a\x64\x8e\x7e\x74\xeb\x8f\x97\xa9\x50\x99\x91\xc4\x78\x0b\x92\xef\x2b\x28\x07\x99\xcd\xf9\x50\xa2\xa1\xce\xfa\xcb\x7a\x4d\xc5\xfe\x46\xe4\xc0\x66\x79\x9c\x96\x14\x99\xda\x5f\xf0\x8b\xdb\x8a\xe8\x2c\x8d\x22\x59\x5a\xd0\xaf\x68\x2b\xc8\xb8\x53\xfc\xab\xda\xf5\x19\x5d\x71\xb3\x0d\x70\x26\x09\x5a\x98\x03\x7d\x85\x3e\x2c\x54\x6e\xf5\x84\xe1\xd2\x7c\x6a\x14\x86\x45\x0b\x18\x97\xe0\xbf\xe9\x54\x0c\xef\xba\x24\x8e\x61\xcb\x33\x89\x28\x6e\x0a\x78\x06\x67\xda\x6e\xe3\xc1\xa1\x1f\x0b\x3a\x49\x8d\x02\xb5\xa0\xbd\x90\x24\x47\xef\x24\x18\x84\xe2\x87\x31\x76\x8f\xff\x8c\x31\x86\xf3\xe6\xe7\xb4\xfe\xfc\x45\x7d\x7e\xdb\xfc\x3c\xac\x3f\xff\x8f\xfa\xfc\x59\x12\xb4\xe7\xfb\xdf\xd4\xf7\x0e\xc2\xbe\x55\xd0\x5e\x5f\xa7\xdd\x8d\xce\x63\x0c\xed\xcf\x01\xc8\xcf\xf4\xe7\x2d\x86\x47\xb2\xd3\x1b\x41\x36\x7d\x19\x9f\xa4\x92\xea\xb8\x78\x76\x80\x94\x27\xe9\x09\x0a\x2c\xce\xf1\xf1\x6b\x89\xe2\x5f\x98\xb6\x5b\x94\x3c\x5a\xa7\xa2\xa4\xd1\xb7\xda\x50\xec\xdb\x28\x2d\xa3\x34\x9a\xa5\x92\x0e\x74\x45\x65\xb4\xaa\x4a\x19\x9d\x51\x67\xc4\xff\xfc\xed\xab\xe8\xbf\xff\x3a\x1c\x45\x73\x2e\x56\xa9\x1c\xc4\x38\x79\xa2\xb7\x3b\xec\x86\x72\xfc\xb6\x62\x31\xc4\x2f\xb9\xfa\xff\xae\xa2\x31\xc4\xef\xe9\x4c\x3d\x2f\xab\x18\xe2\x67\x22\x8f\x21\x7e\x9b\xca\xf8\x14\x28\x99\xc4\x3f\xa6\x2a\xdf\x33\x7a\xa6\xca\xa4\x22\x86\xf8\xe1\x5a\xe8\xe7\xcb\x18\xe2\x1f\x75\x5d\x3f\x56\x85\x4a\xaf\x16\xaa\x24\x5d\xc7\x10\xbf\xca\x64\x0c\xf1\x09\xdf\xc4\x10\x3f\xa1\x59\xed\x4b\xa3\xd8\xd2\x9e\xc1\x4b\xb8\xa4\x69\x27\x97\x6b\x5b\xfc\x67\x55\x51\xfc\x83\xa6\x02\xe1\x2d\xac\x38\x93\xcb\x8e\x9c\x46\xe0\xd3\x89\x2e\xf0\x52\x65\x42\xf8\x74\xbb\x85\x59\x7a\xb9\xb7\x5e\x4d\x7d\xbc\x85\x25\xaf\xf6\x37\xfe\x03\xaf\x44\xa9\x5b\xce\x59\x25\xf7\x48\x18\xd5\xa6\xfe\xac\x73\x96\x34\xe3\x6c\xb6\x37\xe7\x5b\xfd\xd9\xd6\x59\x14\xf9\x2d\xd9\x5f\xd6\x79\x74\x19\xc9\x15\x6f\xec\xcd\x6e\x18\x67\xab\x77\x18\xf7\x65\x0c\x58\x4f\x53\xe8\xd5\xfc\x3d\xa5\xe7\x7b\xa9\x2a\x26\x96\x5c\x97\x9a\xa6\xda\x60\xe2\x61\x37\x7f\x8b\x9d\x73\x4a\x6d\xfd\x35\x2d\xab\x2c\xa3\x8a\xb7\xb4\xb1\x61\x22\xb7\xad\xd8\xf1\x1d\x45\xe6\x69\x5e\x74\xe5\xdf\x3d\x0a\x35\xf9\x59\x2a\xf3\x0d\x7d\x94\xb3\x59\xce\x16\x31\x64\x69\x51\x9c\xa5\xd9\x79\x22\x21\x4b\x59\x46\x0b\x1d\x11\x71\x7b\x9b\xcd\xaf\xaa\x29\x65\xb3\x77\x4b\xca\x1a\x75\xc8\xb4\x3c\x6f\x5b\x00\xef\x29\xce\x99\xb6\xf9\xbc\xb9\x78\xb5\x07\x0b\x41\x33\x9a\x6f\x68\x58\x78\xdb\x3a\x12\x6a\xba\xd3\x3b\xf3\x36\xc8\x67\xc9\x6a\xb0\xa8\xf2\x19\xc2\x20\x38\x97\x89\x84\x52\xaa\x0a\x14\xde\xb0\x4a\xf3\xe2\x8c\x7f\x0e\xfc\x5d\xa3\x35\x12\xb8\x15\x56\xbb\xe6\x10\x14\x5a\xdc\x52\x24\x90\x6a\x5a\x4d\xdb\x3b\x76\xc4\x72\x60\xeb\x36\x67\x02\x02\xc3\xba\x61\x07\x5d\x36\x14\x94\xa0\x62\x86\xaf\x52\xfd\x0d\x18\x12\xc8\x7a\xe9\x0d\x9b\x6d\xcc\xf7\xc2\x64\xd5\xa0\x81\x42\x75\xdc\xc9\x02\xc1\x89\x34\x1b\x18\x1e\xa8\x9f\x10\x06\x53\x96\x68\xf2\xd0\xbd\x10\x14\xb7\x40\x50\x9a\x21\xc7\x2b\x19\x5e\xf8\xd0\xaa\x0f\x6a\x19\x1f\x64\xca\x0a\x9a\x0a\x57\x98\xe1\xed\xb6\x1d\x80\xdb\x2a\xcf\xf2\x68\x53\xef\x8e\x6b\xa0\xcd\x01\x85\x37\xae\xf4\xc3\x4b\x07\xf6\xac\x93\xf5\x10\x6a\xa5\x39\xe6\x6e\x25\x3b\xa6\xd5\xc9\x57\x75\xfa\x0e\x49\x55\x57\x5a\x18\x34\x21\x3d\x44\x96\x5f\x51\x43\x8a\x18\x12\x4b\x58\x6b\x83\x23\xb3\x20\xad\x8d\x42\x3d\xb7\xeb\x56\xdb\x36\xd3\x36\x06\x2e\x23\xc2\x71\x98\xf3\xe7\x70\x87\x96\x66\x99\x3f\xb6\xad\xb4\x01\x61\x2e\x5c\x10\x86\x7e\x5f\xea\x00\x45\x91\x18\xe8\x31\x41\x6e\x19\xb0\xad\xaa\x40\xd0\x52\x26\xb6\xec\x16\x9a\xed\xa9\xa1\xad\x1a\x18\xef\x6f\x60\x57\xa0\xfc\xe1\x06\x0c\x47\xd8\x9c\xbd\x5e\xab\x01\xbd\xaf\xae\x3f\xf9\x23\x62\x03\x8e\x4b\x55\xed\x04\x06\xc4\x36\xb9\x4d\x47\x5b\x83\x23\xa4\x85\x43\x8b\x62\x0c\x5d\x55\x7a\x02\x77\x83\xe7\x08\xfc\x7f\x0a\x9e\x37\x21\x3d\xda\x1c\xcb\xfe\x28\x41\x5a\xfe\xb5\x62\xc2\xe2\xab\x33\x1f\x44\x77\x71\x7d\x8d\x82\xd1\xbd\x84\x21\x86\x05\x39\x18\x36\x8e\x85\xeb\x33\x56\xb5\x4a\x1d\x8e\xc5\xd1\x46\x7b\xdb\x9d\x79\xe6\x1b\x63\x23\x68\x74\x8c\xa3\x99\x3e\x48\xc1\x63\x79\xdc\xaa\x39\x59\x90\x83\x91\xb5\x90\x1c\xd1\xfb\xaa\xa1\x11\x9c\x91\x89\x57\x97\xec\x10\x4f\x04\xa8\x51\x9d\x50\x68\x8c\xcc\x84\x81\xe5\x01\xe3\x8d\x6c\x29\x6e\x8e\x1d\xed\x28\x4b\x2a\x28\xd7\xe9\x05\x4b\x72\x38\xcf\x8b\x22\x99\x43\x59\x50\xba\x4e\x0a\x28\x8d\xa9\x64\x89\x41\xa4\x17\x6f\x75\x9e\xa9\x7e\x54\xe9\xa9\x9e\xef\x4f\xba\xe7\xfb\x60\xf2\x8e\x3a\x0e\x14\x5a\x1b\xec\x83\x0b\x2e\xce\xa9\x68\x1c\x3d\xe4\x73\xb4\xe1\xf9\x2c\x1a\x1e\x74\x06\x1c\x78\xb7\xd4\x8e\x11\xb4\x1f\x7f\x74\x7e\x12\x33\x4e\xcb\x88\x71\x19\x31\x4a\x67\xd1\xbc\x48\x17\xe5\xe0\x03\x7b\x9c\x16\x45\xa4\x33\xda\x56\x10\x36\x8e\x0f\x8c\x47\xa9\x58\x54\xda\x4f\x49\xbb\x09\x5c\xf2\x2a\x2a\x97\xbc\x2a\x66\x4a\x57\x56\xc5\x4a\x2a\x0f\x6a\xb3\xd6\x0a\x49\xbd\xa0\x05\x39\x30\x56\xa5\x20\xb5\xc1\x7c\x26\xf2\xb5\x82\xba\xb4\x77\xd2\x74\x69\x24\x37\x12\xc1\x44\xea\xda\x21\x02\x0d\x88\xd0\x1d\x75\xe1\xa1\xa0\x1a\x6a\xe9\x7d\x7e\x4b\x46\xd3\xf3\x28\x8d\x4e\xe8\x86\x0a\xeb\xc1\xa1\xdd\x4b\x9e\x16\xab\xe3\xe8\x9d\xc8\xb3\xf3\x52\x52\x71\xf0\x81\x3d\x97\xda\x43\xb6\xd4\x2e\xb2\x51\xdc\x67\xfd\x58\x89\x53\xed\x73\xe5\xdc\xad\x34\x9d\x3e\xae\x05\x5f\x88\x74\xf5\x3e\x97\xcb\x67\x8a\xa8\x1f\xa3\xb3\x4a\x46\xcb\xb4\x8c\xe4\xe5\x9a\x46\x1f\x5f\x9b\xef\xa6\xcd\x8f\x83\x0f\xec\x97\x92\xfa\x52\x1f\xb5\xed\x35\x4d\x67\x51\xae\x2f\x45\x88\x66\x5c\xf7\xd1\x45\xca\xa4\xed\x23\x1b\x0e\x22\x23\x39\xfa\x89\x0e\x44\xc5\xf4\xc2\x51\xcf\x62\x4f\x85\xa8\x8d\x9d\x76\xf0\x67\x75\x9f\x0e\x06\x03\x6c\x1d\x63\x8a\xc2\xbb\xb6\xb0\xa8\x62\xf4\xf3\x9a\x66\x92\xce\x7c\x67\x0f\x3e\xb0\xe7\x91\x14\x39\x9d\x29\x82\x65\x9c\x6d\xa8\x90\x51\x2e\xd5\x5b\xca\xb4\x87\xb3\xa6\x1b\x68\x34\x85\xf3\xcf\xd1\x8e\xc7\x6b\xc1\xcf\x0a\xba\xd2\x9e\x2c\x71\x5f\x9b\x33\xb4\xb9\x03\x65\xc6\xec\xe6\x2b\x79\x84\x77\xbb\x33\x49\x7c\xd5\xd0\x29\xbd\xe5\xde\xc6\xc4\xac\xc6\xc0\x88\x8f\x5f\xe0\x14\x0a\xa8\x97\xd8\x5f\x18\xba\x52\xd0\x24\x0c\x36\x39\xbd\xe8\xdc\x28\x48\x73\xb6\x75\xf6\xd1\xfb\xce\x98\xb6\x18\x1a\xe0\x77\x55\x44\x1b\x0a\x4a\x15\x18\xe7\x84\x48\xd6\x77\xab\x3c\x94\x83\x86\x8c\xaa\x9b\xf6\x46\x71\xf6\x60\x0f\x8f\x99\xb6\x6b\x83\x0a\xd9\xf0\x73\x53\x6d\x1e\x02\x25\xa1\x2a\xe5\x0c\xa5\x30\x85\x12\x03\x47\x0f\x15\x9d\xb5\x24\xd4\xb1\xe4\x70\xcb\x25\xef\xa1\x1c\x58\xb9\x85\x4a\x25\xdb\xb5\x8d\x1a\xa4\xe4\x6a\x0b\x25\x59\xa3\xfd\x20\xf9\x7d\x6e\x39\x98\x0e\xc7\x15\x61\x28\x03\xee\x60\xd1\x0e\x6b\x39\xa1\x88\x3b\x58\x72\x0c\x22\x84\x85\xeb\x1d\x2d\x8e\x61\x4e\xa6\x28\x85\xac\x56\xf7\x8e\xaf\xd6\x5c\xc8\x32\x99\x6f\x93\xab\x6d\xb7\x13\x60\xd3\xb5\xe0\xc4\x41\x72\x32\x61\xa7\x63\x3e\xc8\xcb\x67\x5c\xd0\x7c\xc1\x7a\x3d\x84\x28\xa1\xc6\xb0\x95\x9d\x92\x38\x5b\xcd\x8c\x8d\xa2\x4c\x17\xc7\x9f\x11\xc3\xc9\x43\xc4\x40\x60\x0c\x52\x7d\x9f\x23\x0e\xa2\xeb\x92\x0c\x1b\x60\x24\x14\xe2\xde\x21\x90\x16\xf3\x5d\x8f\xbf\x14\x55\xc0\x40\x5a\x4b\x06\xe7\x84\x30\x1d\x8e\xed\xb1\x0a\x37\x67\x2a\x1a\xa0\xc4\x97\xc9\x80\x01\x1d\x64\xab\x59\xa9\x43\x9f\xaa\x0c\x65\x75\xb6\x93\x41\xf1\x9d\xcf\x30\xff\xec\xbf\x97\x61\x05\x3e\x9b\x09\xef\xc3\xc8\x95\x62\xeb\x44\x80\x02\x38\x31\xb2\x73\x0b\x5c\xc7\x77\x5c\x40\x46\xe4\x80\xb3\xa7\xf3\x39\xcd\x64\xa9\x1d\x83\x39\x7b\x4b\x8b\xf9\xcb\x72\x01\x53\xb2\x76\xf2\xbd\x1e\x46\x6c\xa0\xea\x21\x53\x98\xee\x8b\xac\xb2\x9f\x73\xa8\x5d\x02\x29\x1e\x02\x1a\x32\x45\xf7\x82\x62\xd6\xda\x13\x55\x05\x28\x9b\x29\x01\x42\x8b\xb9\xdb\xb9\xd6\x1d\xa1\xb7\xc1\xb7\x1d\x51\xeb\x1b\xd3\xaf\xe1\x16\xc5\xf9\x66\x9e\x6f\x80\xe6\xf7\x85\xa9\xde\x97\xaa\xdd\x19\x18\x50\x25\xa3\x0c\x35\x1f\xca\x81\x55\x1f\x80\x13\xf3\xad\x5e\xb1\xd8\x31\xa5\xd4\x82\xb6\x4d\xdc\x0d\xd3\xde\x95\x9a\x34\x92\xb8\xa0\xe9\x3c\x86\x25\x5f\xd1\x44\xda\xc5\xbc\x08\xe5\x62\x10\x4b\xc6\x96\x60\x7c\x46\x63\x70\x2e\x8c\x8d\xe5\x6f\xc3\x30\xcc\x66\x5f\xa5\xeb\x18\x64\xba\x58\x50\xa1\xd6\xd9\x82\xd2\xc6\x3a\xfb\xac\x65\xcf\xbc\x1d\x5f\xa2\x83\xa1\x8e\xdd\xa1\x94\x4c\x0c\x97\xe8\x60\xa4\x0d\xe6\xf4\x6b\xdb\xc9\xc9\xca\x29\xfd\xc6\x8e\xd9\x84\x9f\x26\x57\x8a\x21\x13\x73\xa3\x80\x62\x4a\xf3\xb8\x1d\x07\xa2\x47\x4e\xf8\xa9\xeb\xc8\xf9\x67\x73\xc0\xb4\x0d\x5d\x21\x2f\x6b\xe1\x69\x87\x90\x18\x28\x74\xec\x38\xd2\x44\x4b\x4c\xbf\x8a\x81\x22\x1e\x64\xe4\x1d\x92\xc0\x81\x81\x75\xe8\xf7\xdd\xa3\x98\x5f\xc7\xbb\x25\x17\x48\x42\xa6\xa3\xde\x62\x3b\x9c\x34\x2d\x93\x3a\xb6\x83\x18\x38\xba\x3a\x6b\xc0\xca\x6a\xe2\x97\xd6\x3a\x56\x03\x05\x26\x7c\x83\x6d\xc1\x54\xa5\xe8\x9c\x04\x4d\x1a\x1c\x06\x8a\xe0\x40\xe1\xca\xf6\x80\x18\x98\x07\xb3\xa0\x61\x0d\xa4\xdf\x75\xcf\x18\xa1\x8d\x2b\x1d\x8b\x31\x96\xc4\xd5\x62\x02\x56\x08\xb3\x2c\x70\xea\xfb\xd6\xb3\xb0\x3c\x3e\x99\x88\x53\x25\x20\x5e\xa6\xeb\x44\x3f\x97\xd5\xd9\xcb\x74\xad\xe8\x84\x5b\x71\xcb\xc3\xf0\xaa\x5a\x88\x76\x77\x23\xc8\x63\x64\x64\x0e\x71\x17\x3d\x58\x19\x84\x81\xe2\x04\x19\x41\x14\x7e\x53\xef\xb8\x71\x17\xd2\xb9\xbd\xdc\x46\x1a\x71\xde\xa5\xd3\x0a\x1a\x65\x29\x33\x4e\xef\x67\x34\xe2\x8c\x46\x6a\x9a\x88\x58\xba\xa2\x33\xe7\x09\x6c\x34\x13\x7d\xc3\x94\xd5\xb2\xb4\x36\xb6\xaa\x0a\x99\xaf\x0b\xda\xf0\x60\x7f\xdb\x90\x2a\x0a\x02\x38\x99\xc8\x53\xa2\x3a\x26\xd1\x82\x19\x2c\x9d\xde\x80\xd5\x85\x54\x77\x81\x9f\x5d\x92\x83\xe1\x16\x96\x8d\x9d\x9b\xcf\x8d\xbb\xe5\x68\xe3\x40\xaf\x61\x4c\x3a\x0e\x0d\x82\x33\xe0\xa4\x32\x56\x5d\x3a\x6a\x68\x7e\xe4\x6d\x8c\xf3\x7e\x1f\xb3\x49\x7e\xaa\xe6\xd1\x66\x1c\x88\x69\x4b\x9b\xce\xdc\x2a\xac\x75\x83\xa2\x61\x13\x94\x91\xcc\x47\x7c\xf4\x6e\x83\x4a\x62\x3d\x20\xc3\x5e\x2f\x73\x77\xf1\x08\x18\x19\x09\x97\x91\xc9\x29\x54\x44\x51\x64\xe0\xb1\x87\x29\x09\xb5\x09\x3d\xfc\x2d\x38\x3a\xa3\x9a\x23\xc8\x54\x93\xb1\x9e\x4d\x88\x40\x14\xc3\x95\x55\x96\xce\x68\xc2\xa0\x62\xf5\x1b\xdf\xee\xc4\x67\xde\xd3\x25\x6a\x2a\x04\xc3\xae\xc9\xd3\xaf\xee\x92\x87\x66\x33\x2d\x24\x56\xdb\x20\xdb\x5d\xdd\x65\xaf\x7d\xf2\x01\x97\xb3\x7e\x1f\x4f\x51\x39\xc9\xea\x8b\x18\x4a\xb3\xf9\xb5\x26\x53\x98\x11\x0e\x6c\xff\xfd\x5f\x73\x22\x60\xd9\x71\xdb\x97\xfd\xec\xec\xc2\x5b\xfb\x9b\xe5\x6e\x2f\xb6\x8c\xda\xe7\x6d\x46\xa2\x9a\x73\x90\xf4\xe6\xc3\xe1\x7e\xa3\xd7\x8e\x73\x54\x31\x28\x6c\x78\x7a\xb7\x7a\xa0\xdd\xab\x87\xb8\x8e\x94\xa4\xe6\xd9\xd6\x6a\x41\x2f\x6d\xf8\xdc\x2e\xa1\xac\x03\xbc\x19\x8b\x76\x14\x26\x6a\x09\xa0\x6d\x4e\xc7\x6b\x63\x7b\xba\x35\x81\x65\x26\xa7\x30\x27\x46\x80\x14\x6d\xd6\x9a\x11\x06\x6b\x52\xc1\xf2\x2b\x58\x6c\xb9\xcb\x62\x99\x62\x31\xbb\xf8\x56\x8d\x9d\x28\x05\xf6\xcd\x5e\x4b\x9e\x2d\x86\xa7\xfb\x3e\x76\x28\x03\xce\xd9\xce\xab\x03\xba\xad\x77\xfc\xe1\x7a\x6d\x22\x79\x99\x57\xa5\x31\x25\x12\xcd\x30\x50\x0d\xd8\xcb\x94\xa5\x0b\x2a\xca\xe4\x04\x78\x25\x17\x3c\x67\x8b\xd7\x5c\xc8\xe4\x2d\xe4\x2c\xe3\x2b\xf7\xfa\x08\x96\x72\x55\xbc\xe3\x76\xb9\x98\x64\x60\x85\x57\x42\xa1\xbd\xc4\x4c\x58\x18\x59\xb1\x02\x35\xf1\x25\x4b\x38\x4b\x65\xb6\x4c\x36\x36\x64\xe2\x42\x5b\x35\xc3\x1b\x49\x4e\xe4\x40\x7f\x82\xa7\x92\xbc\xf1\x4e\x96\xfa\x90\x1f\x5e\x4a\xf2\x52\x6a\xfb\xd1\x97\x72\x12\x1f\xec\xf5\x66\xdc\x17\xdd\xe3\x8d\x3e\x19\xdb\x1a\xf5\xf6\xb1\x6e\x6b\x95\xae\xe1\x53\xd0\xea\x33\x49\x3e\xb5\x5a\x7d\x21\x09\xb2\x39\xeb\x8e\x86\x13\xa3\xd2\x19\x12\x62\x78\xae\xeb\xf0\x34\x86\x57\xa6\x50\x9b\x18\x50\xa7\x35\xce\x25\x5b\xe6\xb3\xaf\xce\x3b\xcd\x67\x31\xfc\xb8\x6b\xe4\xd0\xf2\x02\x33\x45\xdb\x3e\x6b\xaf\xbb\xec\x14\x2d\x96\x6a\x68\x39\x27\xb3\x27\x1d\x27\xfb\x37\x35\xe0\x1c\xd9\x5e\xdb\x87\x6d\xd7\x71\xab\x6d\xe7\xd5\xb9\x6b\x06\xc3\x2f\xbf\x0f\x8f\x27\xb2\x76\x66\x0b\x9a\xfa\x75\xff\x21\xf5\xed\x4e\x6d\xa6\x01\xef\xbe\x76\x5c\x27\x8c\x7c\xa3\xdd\xce\x6b\xaf\x25\x72\x2f\xf6\x79\x68\x01\x7a\x2f\xff\x04\x9f\x36\x03\x07\x6f\x03\xe6\x5d\xd7\x82\x84\xbb\x1e\xd2\x9b\x1d\xd7\x5e\x4b\xe4\x5e\xec\xf3\x28\x78\x76\xd0\xff\x59\xae\x6d\x06\xbc\xac\x8d\x40\xd6\x46\xc0\xbb\xaf\x05\x09\xf7\x3c\x46\x5f\xe7\xbc\xf6\x5a\x6f\xd2\xdc\x73\xd8\x64\x01\x96\x59\x80\x65\x56\x63\xf9\x27\xbb\xba\x19\xc8\xab\x36\xb2\x55\x1b\xd9\xaa\x8d\xac\xf7\x65\x0b\x12\xee\x7b\xec\x7f\x9f\x27\xdb\x6b\x89\xdc\x8b\x7d\xbe\x17\x3c\xdf\x0d\x9e\x47\xc1\xb3\xa5\x08\x86\x1f\x7e\xf7\x68\xf4\xa3\xde\x0d\xcb\x2d\x86\xdf\x6e\x97\x1d\x2d\x17\xd5\x46\x45\xaa\x8a\x87\x7a\x4d\xaf\xa6\x74\x0c\x5f\x64\xb8\x64\xfd\xfe\x36\x10\xd5\x12\x56\x6f\x7d\xa3\x1c\x7d\x91\xf0\x5c\xd5\x08\x1e\xb6\x9f\x75\x65\xf3\x34\x2f\xe0\x1f\x37\x19\x2f\xfd\x26\xbb\xbc\x23\x7e\x96\xda\xf5\xc8\x39\x47\xd4\xb3\x00\x86\x9f\xf6\x5a\x9d\x69\x30\x3a\x2a\xfb\x47\xb3\xb2\x7f\x76\xc9\xb0\x5b\xaa\x68\xa6\xd3\xb0\x6a\x77\x6f\x32\xd6\xe6\xd5\xa6\x89\xbf\xef\x91\x4a\x7f\xb0\x95\x66\x3a\x0b\x5b\xaf\x2f\x5f\xc6\x5b\xb5\x3c\xab\x61\xe8\x96\x2d\x7f\x32\x04\xcd\x74\x1e\x42\x16\x5e\xeb\x8c\xb7\xc0\xdb\xf0\xed\x93\x0a\xff\x26\x08\x9b\xe9\x59\x08\x79\xf3\x26\x69\xbc\x85\xac\x0b\xfe\xf6\x26\x67\x30\xe8\x1a\xce\x0e\xff\x68\x2a\x37\x49\x8a\xfe\xb9\xcf\xc4\x71\xaf\xef\x83\x92\x3d\x7f\xd7\x43\x77\xa4\x07\xd7\x37\x37\xb2\xf0\x4f\x72\xbf\x4a\xe0\x43\x7d\x6c\x55\x85\x39\xfa\x27\x7c\x2f\xed\x55\x42\xda\x7b\x43\x90\x7f\xb4\xe2\x6c\x0c\x95\x46\x26\xc4\xfe\x06\xbb\x0a\x28\xa0\x85\xd2\xcf\x94\xee\x89\x62\x1d\xab\x08\x03\x13\xfb\x75\xa2\xd7\x26\xf8\xb5\xd7\x8b\xb8\xd8\x37\xcc\xa9\x40\x4c\x20\x8d\xa6\x74\x70\x67\xb7\xe6\xee\x96\x33\x5a\x34\xbc\xd6\xd2\x01\x6f\xe1\x46\x01\xf2\xc4\xe5\x52\xff\xb5\x1f\xc5\xde\x36\x03\xf0\xac\x38\x1c\x9f\xc8\x41\x53\xdf\x1f\x28\x9a\x90\xab\xf5\xf9\x22\x89\x1b\xf1\x5c\x63\xad\xbc\x27\x52\x80\x5f\xbb\x24\xdf\x48\xf0\x7b\xad\x89\x10\xb0\xb3\xfd\x50\x09\xe3\x27\x30\x15\x37\x85\xeb\xb5\x7b\xcc\xfd\x38\x89\xe2\x7e\x1d\xf3\x03\xe9\x2b\xe0\x98\x56\xf3\xeb\xad\x5b\x39\xe3\x95\x3c\x76\x0f\x83\x0b\x91\x4b\x8a\x28\x4e\x32\xce\x4a\x5e\x50\x1d\x1e\x9c\x36\x4c\x5d\xf4\xbe\x69\x7b\xa1\x28\xdd\x5e\xf9\x95\x09\x18\x43\xa1\xe0\x8b\xc4\x2c\x0b\x10\x86\xbc\x1b\x60\xba\x27\xd4\xff\xde\x78\xeb\x7d\xd1\xb9\xa7\x21\x27\xc3\xd3\x3a\xb0\xce\x0b\x14\x9c\xfa\x64\x4b\x61\xee\x86\x32\x5b\x1e\x23\xac\xad\x85\xbb\x2d\x91\x9a\xf5\x87\x31\x08\x7f\x1c\x58\xf7\x53\x24\xb1\x8d\x42\x14\xb7\x17\xe6\xde\x90\xac\x8d\x43\x8a\x76\xae\x4b\x2d\xd7\x45\x2e\x55\x1d\xc0\x48\xf3\xea\x47\x13\xc1\xd0\x02\x4e\x1b\x61\x91\x68\x47\xcb\xcd\x48\x7f\x41\xc5\x6a\x59\x65\x6a\xc1\x83\x79\x5e\x48\xbd\x21\xd8\x51\xc1\xbc\x19\x58\xce\x17\x17\x74\x43\x45\x49\x51\x57\x99\x0e\xaf\x78\x7f\x23\x8d\xb9\x30\x8e\x8d\xfb\x7d\x6e\x6f\xbf\x74\xa8\xf0\x53\xdc\xed\xab\xdf\xe1\x18\xdf\x75\x8b\x66\x40\x92\xee\x7a\xd6\x0d\x5a\xfc\x38\xf0\x7e\xc2\xc8\xd1\xa5\x71\xb1\xf0\xb2\x95\xdd\xf5\xb0\xb0\x28\xcb\xb6\x6b\x78\xd8\x85\x71\x3c\x96\x0f\x86\x63\x3c\xea\xc9\x5e\x0f\xd1\x3e\x51\x3c\xf6\xe0\x01\x19\x81\xe8\xd7\xaa\x13\xed\xb8\xd2\xd4\x77\xa6\xbf\xb7\x71\xaf\xc7\xb5\x3c\x1a\x1d\xc7\x71\x22\x82\x9b\x34\x5b\xdb\xe0\xfb\xb2\x1e\xca\xdd\x4b\x3e\x83\x9c\xc2\x67\x94\xed\xad\xde\x3d\xf9\x86\xd0\xa8\xf2\xbc\xb9\x28\x44\xf2\xd0\xdf\x41\x74\xe7\xae\xdf\x5c\x0f\x6e\xc0\x60\xaa\xcf\xfa\xb4\xbf\x41\xc3\x6b\xd6\x40\xf9\x6d\x9b\x30\xfd\x4d\x50\x5d\x23\xeb\xe7\x56\xd6\x56\xc6\x3e\x6d\xec\x1f\x06\x6c\x2d\x45\xbe\x42\xcd\x9d\xc0\xe0\xab\x8f\xb7\xf5\xbf\x1f\xca\xfe\x1d\x68\xb0\xfa\x49\x77\xce\x0f\x65\xff\x9b\x56\xce\x37\x0d\x71\x51\xf3\x9e\x6b\xdd\xb2\xa0\x2a\x7a\x67\x11\xf2\xe1\xd3\xbd\x05\x5d\x09\xf1\x81\x5d\x7f\x10\xd7\x1f\x58\xb3\xe0\xcb\x26\x8e\xa1\xd9\x7d\xe3\xce\xae\x46\xa6\xc0\xd4\xbd\x71\x13\x51\x5b\x42\x85\xa1\x36\xb4\xe7\xb8\x15\xa5\x13\x7a\x8a\x03\x07\x72\xfb\x30\x6a\x5c\x1c\x74\x4b\x5d\x07\xdd\x95\x75\x05\x78\x7e\xd5\x12\x6f\xf5\x76\xf5\x83\xc3\xd1\x8d\xf7\x02\x05\x59\xf7\xde\xe4\xe3\xee\x89\xf2\xf3\x4e\xaf\x27\x06\x45\x5a\xca\xe7\xbe\xac\xae\xca\xde\x67\xb4\x2b\xd9\x7f\x69\x4c\xb8\x7e\xa7\x7e\x8e\x68\xed\x2e\xa4\x37\x39\xc3\x2b\xa5\x75\x10\xfd\x31\x62\x21\x8c\x4a\xb1\x7f\x70\x38\xf2\x11\x37\x18\x06\xd6\xf7\xee\xbd\x0d\xb6\x08\x4f\x11\x7f\x0d\xef\x6e\xa8\x5b\x0f\x2f\xb5\x89\xde\xbb\x6b\xe4\xa9\x99\x26\xf3\x39\x8a\x87\x5a\x71\xed\xf5\xe2\xcf\xfa\xbc\x7a\x32\x3a\x35\x1d\xc6\xc8\xdd\x31\x3b\x12\xe3\x7e\x9f\x61\x13\xaf\x7d\x18\x1f\x11\x44\x75\x48\x5d\xdc\xeb\xd1\x23\x12\xff\x4f\x7c\x7d\x1d\x3f\x8c\x8f\x54\x79\xf5\xfe\x4c\xbd\xa7\xf5\xfb\x3c\xc6\x8d\xa6\xed\xf3\x13\x89\xb4\x01\xfe\x73\x26\x91\x84\xd1\x5f\xb1\xbe\x53\x92\x3e\xd0\xf5\xd1\xa3\x78\x18\xf7\x7a\xf1\xa1\x36\x66\xec\xf5\xe2\x7e\x1c\x5c\xb3\x6e\xea\xa9\x29\x38\x0a\x61\x74\xc0\xa9\x1a\xae\xaf\xe3\xff\x89\x8f\xe8\x57\x34\x3f\x0c\xc7\xd1\xfb\x60\x88\xbc\x96\x28\xce\xb4\x79\x93\x09\xe1\x6c\x0c\x5f\x4c\xbc\x4f\xef\x3b\x60\x8c\x60\x9e\x33\x19\xb7\xaf\x2d\xf2\xd7\x64\xba\x0b\x32\xef\x4c\x3e\x94\x9f\xcf\xf8\xe9\x9d\x81\xa4\xa5\x9e\x80\x6c\x43\xbf\xb9\x6e\x11\xa4\xef\xcf\xe7\x74\x30\xef\x63\xad\x82\x26\xbf\x35\x38\xf7\xb7\x3f\x02\x63\xa4\x23\xb9\x85\x40\x7e\xb9\x45\xd6\x34\x15\x87\xa0\xe0\xf7\xb7\x2a\x43\x56\xfd\xcb\x4b\x1d\x2b\x33\xa1\x2e\x74\x07\xc3\x50\x31\xfd\xcc\xeb\xc0\x82\x19\x06\x73\x2f\x9d\xde\xb7\xd6\x97\xf5\x4c\xed\x8e\x75\x8a\xc1\xe8\x2b\xd6\xa8\xce\xe8\x21\xc9\xdc\x5f\xf5\x53\xd4\x57\xfd\xcc\x30\x68\xb8\x13\x89\xd6\x18\x14\x28\xe6\x96\x20\x41\xd7\x34\x95\xe6\x86\x20\x77\xaf\xd0\x02\x43\x41\xe7\x52\x47\xfa\x00\x61\xae\xd5\x42\x97\x18\x66\x82\xaf\x5f\x98\x0f\xef\xcc\xdb\x1b\xfb\xf1\x02\xc3\x3a\x9d\x25\x42\xdf\x53\x94\xce\x74\x26\x81\x3e\xeb\x17\x93\x47\xa0\xb7\x6a\x31\x95\xaf\x92\x47\xfa\x47\x67\x79\xa8\x1f\x4d\x86\x13\xb8\xe0\x62\x56\x26\x6f\x40\x87\xde\x4d\x9e\x7a\x07\xaa\x97\xde\x2f\xea\x31\xa4\xec\x32\x91\xe8\x19\x86\xb4\x28\x12\x89\x9e\x6b\xe2\xc8\x34\xd7\xf4\x7b\x85\x41\x07\xeb\x2d\x6d\x9c\x92\xd7\x18\x28\x9b\xb9\xb7\x27\xee\x4a\x24\x95\xf5\x17\x0c\x92\x3f\x67\x32\xf9\xd5\x5f\x05\xf2\x83\xbb\x86\xe9\x4b\x7d\x35\xd3\xf7\x5a\x25\x4f\x05\xc9\x45\xed\x8a\x56\xea\x57\x93\x19\xe6\xf6\x45\xd7\x01\x85\x7d\x7b\xce\x24\xcc\x04\x41\xb9\x15\x5c\xb4\x84\xe6\xa3\x83\x0b\xc3\x5a\x17\xa9\xe1\x86\xa5\x4e\x70\x68\xc1\xc6\x54\x93\x16\x85\x2a\x97\xb2\x4b\x30\x8d\x2b\x82\x60\x58\xd9\x06\xad\x23\x95\xc9\xab\x09\xa8\xb2\x69\x8a\x62\x38\x33\xc9\x9e\xd6\x60\x5f\x54\x1f\xb8\x67\x0c\x97\x26\x97\xeb\x31\x30\xcf\x2a\x0f\x86\x77\xfe\x9b\x4a\xf6\x3d\x8f\xe1\x42\xb7\xef\x18\x03\xce\xf5\xab\x66\x19\x78\x6b\x81\xb1\x8d\x68\xe6\xc2\xf0\xd9\xa4\x1a\xb6\x53\xe9\x8a\x15\x31\x3c\x32\x54\x50\x1c\x0a\x0f\x4d\x16\xe3\x2a\x68\x1f\x34\xf2\x96\xc1\x75\x9a\xe6\x7b\xf5\xb4\x4a\xd7\x90\x0b\x7f\x3f\xd8\x89\xa3\x5e\x96\x4a\x78\x63\x69\x67\x9c\x2b\x73\x31\x30\xc3\x0b\xc3\x53\x97\xab\x84\x97\x5d\x4b\xf0\x28\x47\x4f\x05\x48\xad\xb6\xc0\x63\x9d\xd9\x8e\x56\xf8\xd4\xb5\xf0\xef\x8a\xda\xb2\x27\x14\xee\xfe\x30\x2e\xa9\xd9\xe9\x1f\xa9\x7f\x77\x21\x45\x9f\x84\xf6\x31\x65\x3a\x18\x7f\x33\xb0\xcb\xbd\xed\x16\xc3\xb3\x4e\xc8\x75\xb9\x7d\x5b\x13\xdd\xb1\x07\xf0\x4e\x98\x88\x17\xff\x6a\xd5\xfb\x83\xdb\xef\x6d\xf3\xf9\xbf\x8d\xb0\xcf\x3d\x61\xef\xb5\x09\x7b\x5f\x41\xf6\x4a\x90\x60\x2f\xce\x6e\x7b\xe9\x8b\x31\xed\xad\x21\x2d\x38\xb3\x26\x9c\xe6\x76\xd3\xca\x18\xf3\x69\x63\x97\x39\xc9\x83\x58\x03\xf3\x0e\xf7\xfc\x90\x50\xb9\x71\xff\xe6\x1a\xc8\x29\x36\xfb\x18\x05\x99\xab\x0a\x67\xea\x67\xa8\x9e\xd6\xf6\x69\x38\x0e\x3c\x9e\xd7\xfa\xda\x2f\x3f\x73\xd6\x89\xb5\xe3\xfb\x4d\x2d\x75\x75\x5b\xa1\xf2\x94\x88\xc1\x1a\x66\x16\x1e\xeb\x2a\x0d\x59\xd7\x11\x57\x61\xea\xa4\x3a\xff\x14\xeb\xc8\x16\x73\xa2\x89\x9e\x77\x45\xe7\x78\xa1\x8f\xa1\xa7\xa3\x64\xba\x85\x0a\x83\xc6\x73\x68\xf0\x1c\xd5\x0e\xc5\xbb\x01\x63\xac\x63\x4e\x9d\x85\x9a\x18\x48\xba\xa3\xf5\x7e\xe4\x0c\x0a\x1d\x6e\x49\x90\x1b\x76\x9e\xa7\xc2\x44\xc8\x47\x27\x02\x35\x59\x38\x7e\xee\x42\x25\x0b\x3a\x3b\x3c\x2b\xd2\xec\x3c\x92\x82\xd2\x28\x67\x9b\x54\xe4\x29\x93\xd1\x26\xe7\x45\x2a\xe9\x0c\x22\x7f\xd0\x1f\xef\x09\xf1\xd1\xaa\x5b\x5b\x88\x2f\xb8\xec\xca\x7f\x8e\x04\xee\x28\x72\xa7\x23\x2b\xfd\xca\x7c\xac\x23\xdf\x07\xf6\xba\xa0\x69\x49\x23\x41\xb5\x1d\x82\xb6\x48\x3e\xab\xb4\x05\xc3\xd1\x52\xca\x75\x99\xdc\xb9\xb3\xc8\xe5\xb2\x3a\x1b\x64\x7c\xd5\xba\x63\x29\x2f\xcb\x8a\x96\x0f\xe2\xdd\x70\x10\xe6\x4f\x6f\x08\xbe\x16\x9d\x01\x9a\xa4\x8b\xcc\xd1\x1d\x4c\x5c\xd4\x81\x36\xe2\x47\x8f\x14\xdd\x4d\xaa\x3d\xde\xaa\x57\x54\x2e\x1c\x82\xca\xf8\xe2\xab\x72\xb6\x23\x20\x1c\x8c\xb6\xf0\x64\x77\xd7\xb2\x2b\x52\xd8\x1e\xa9\xd3\x0c\x53\x26\xc7\x92\xe4\xe8\x89\xd0\x81\x1b\xa8\x12\xdc\x26\x66\x98\x96\xd7\xbf\xec\x36\x24\x93\x3f\xdc\xd4\x27\x67\x15\x9b\xa3\x13\x90\x26\x5e\xb4\x25\x9c\x36\xa4\x7b\xf1\x2e\x4e\x7c\xcc\xb2\x7b\x63\xa5\x4f\xe4\xac\xa2\x91\x34\x76\x76\x4f\x7f\xf6\x66\x76\x2f\x10\x1d\x4c\xef\x62\x1f\xbe\xc3\x97\xba\x1f\x94\xd2\xe3\xf8\xd7\x7d\x1b\xbc\xfe\x54\x2d\x47\xbf\x68\xe1\x6a\x40\xd9\x62\x78\xff\x67\x4a\xf5\xfd\xb3\xca\x58\x9a\x30\x35\x3a\x5a\xcd\xdd\x40\x96\xff\xe0\x5d\x18\x4f\x0c\x83\x6c\xe1\x37\x9f\xf4\xc8\x25\x7d\xa9\x93\x6c\xca\xf7\xdd\xac\x7b\x3b\xd7\xba\x95\xfc\x74\x58\xfb\xa7\xd3\x4f\x88\xc2\x17\x81\xaf\xaf\xed\xf3\x6f\xde\x60\xfa\x60\xb8\x85\x9f\x7d\xeb\x6f\xe8\x2c\xde\xc2\x3f\x9a\x6d\xdb\x7e\x96\x61\xef\x1a\x30\x5d\x0f\xfe\x66\xa2\xcb\xe8\xe2\x2e\xed\x8b\x4d\x3b\x69\x66\xfd\x59\xf8\x7e\x6e\x4b\xc0\xf8\x71\xca\xbe\x95\xd1\x2a\x3d\xa7\x51\x1a\xcd\x78\x75\x56\xd0\xc8\xc8\x3d\xc6\x67\xd4\xdc\xc8\xa3\xdf\x0f\x62\xbc\xdd\xc2\x4f\x5f\x01\x66\xb3\x71\x07\xd3\x0e\x48\x3b\xd0\xff\xf0\xb5\x60\xea\x50\xd2\xf9\xa6\x01\x68\x41\xcb\x32\x04\xf4\x9f\x9e\xbe\x2f\x7c\x8f\xff\x3d\x48\xb3\x49\xdf\xdc\x70\x18\xd3\xc5\x9d\xee\x60\x46\x52\xf2\x8d\x40\x7f\x17\x6a\x31\x45\x6e\x3a\x64\xf4\x75\xed\xf0\x4f\xcd\xc9\x30\xbd\xab\xa4\xfa\x3d\x25\xb2\xef\x27\x5c\x1f\x76\xd1\x9b\xc2\xdc\xdd\xc4\x8d\xbd\x9e\x26\x6a\x28\x13\x8f\xe7\x48\x28\x5e\xd4\x37\x4c\xe9\xcb\xa3\xf4\xbd\x50\xe6\xca\xa7\x44\x6e\x81\xfd\xe1\xd6\x4c\xd5\x3f\x09\x6b\x94\xd9\xd9\x80\x21\xd4\x16\x38\xed\x52\x30\x3b\x4e\x9a\x3a\x0e\x36\x3b\xce\x34\x3b\x8e\x33\x3b\x4e\x32\x7d\x52\xb5\x9b\x34\xdd\x4d\xca\x77\x93\xd2\xdd\xa4\xb2\x4e\xb2\xe8\x4b\xac\x35\x46\x4f\x68\xa0\xc6\x93\xc3\x25\x28\x55\x32\x85\x12\xe3\x7a\xb6\xdc\x42\x76\x0b\xd9\x3b\x85\xa3\xa5\xbb\x21\x6a\x72\x53\xcf\x6e\xa1\xfa\x17\x1a\xa8\xc7\x5e\x16\x8e\xbd\x17\x34\x9d\x2b\xe5\x28\xb6\x6d\xff\xbc\xaf\xed\x69\x77\xdb\x75\x98\x2e\xaa\xfe\x31\xf5\x8f\xab\x7f\x99\xfa\x57\xdd\xa0\x25\x78\x4b\xce\x46\x28\xaf\x7d\xcc\x69\x8d\x5c\xf0\x8d\x79\x8c\xdd\x0b\xf6\x76\xf2\xda\x7c\x25\x94\x65\x5a\x3c\xd5\x9f\xef\x77\x7d\xbe\x05\x8a\x3a\x72\x74\x3d\x2c\xef\x85\x2d\x19\x6c\xaa\xdb\xb0\xb1\xc0\xb6\xeb\xb9\xdf\xaa\x27\xbb\xb9\x9e\xfb\x9d\xf0\xdc\xdf\x85\x87\xdf\x5a\x4f\x07\x3c\xf7\x77\xe1\x61\x3e\x52\x58\x63\x66\xfa\x4f\x24\x5a\x87\x36\xa9\xef\xca\xfc\x0a\x52\x86\x25\x43\x62\xde\x52\xfe\xfe\x9e\xf2\x6d\xf8\x68\x67\xb8\xb5\xff\x24\xfa\x39\x65\xbb\xd1\xc9\xff\xca\xc0\xf9\x3f\x60\xd4\x3f\xc0\x03\xf7\xf6\xf0\xc0\xbd\xaf\xe4\x81\x7b\x7b\x78\xa0\x83\xc6\x62\xff\x40\xea\x5a\x06\xdd\xb8\xd6\xfa\xf7\xf2\xee\x57\xf3\xea\xbf\x8b\x82\xdb\xae\xd1\xf4\xff\x40\xcf\x6f\x1d\xbc\xff\x8f\x0d\xac\xdf\xc3\xb8\xff\xb1\x12\xd7\xc7\x61\xd4\xb1\x38\x6e\x51\x19\xfe\x43\xc5\xf3\xbf\xdc\x03\xff\x27\xf2\xae\xdd\x03\x3a\x18\xc8\x4d\x4a\xa2\xd3\xeb\x5c\x05\xff\xdf\x70\xf9\x3f\x1c\x2e\xbb\x11\x48\xb9\x71\xc4\xc2\xc8\x33\xce\x28\x78\xbe\xeb\x9e\x7d\xa2\x49\x31\xaf\x77\x83\x9c\xf7\x82\xe7\xfb\xee\xd9\x3c\xdc\xc7\xb7\x36\xdb\xaa\xde\x70\xe0\x28\x78\xee\x6e\x36\xc8\x10\x3e\x7f\x5d\xb3\x61\x65\xf7\x03\x28\xee\x07\x80\xdc\x0f\x12\x6d\xb3\x41\x9e\xf0\xf9\xbe\x7b\xfe\x9d\xcd\xb6\xaa\xbf\xdf\x4c\xec\x68\x36\xf8\x14\x3e\x77\x35\x1b\xac\x47\x2d\x82\xf5\xe3\x5d\xb8\x61\xb5\x6a\xb1\x83\x39\xca\x83\x0a\x5c\xe9\xbb\x75\x9e\xfb\x50\x51\x8f\x37\xbe\x19\x84\x7b\x75\x25\xb6\x4f\xc3\xfa\xef\xd5\x9f\xee\xda\x4a\x0d\x0c\x41\x0f\xef\x01\xd9\x34\x6f\xef\xcc\xde\x05\x41\x6e\x21\xdf\xb7\x2d\x64\xfc\x5a\x74\xb5\x75\xaa\x2b\xf8\xbd\x40\x19\x3e\x9e\x52\x94\xe1\x24\xdb\x62\x48\x6f\xde\x5c\x8a\x5e\x0b\xc4\xf0\xf5\xf5\x6b\x81\x38\x3e\xd6\xa8\xfd\xc3\x78\x36\xab\x7c\x54\xdb\xc9\x50\xc4\xb1\x5d\xab\xd7\xe5\xb7\x18\xca\x9b\x01\xe4\xb7\xec\x12\x98\x78\x2a\xc7\x29\x9a\xab\x7a\x55\xc1\x64\x8e\xd2\xba\x8d\x39\x2a\xa9\xf6\xa3\xd1\x4e\x34\xda\x83\x46\xbb\xcf\xa8\x7f\xf7\x4d\x8c\x56\xfa\x47\xbc\xa8\xf6\x6d\x1b\x1f\x04\x3e\x55\x4e\xf9\xdd\xb3\xb9\xdc\x19\x7d\xda\xc6\x9d\x36\x8e\x2f\x5d\x2e\x53\x26\xf8\x3c\x4c\xef\xee\x5c\xa6\x75\x2f\x0e\xef\x9b\xf2\x92\x32\xbc\x70\xca\x4a\xfc\xf0\xbe\xa9\x17\x61\xc6\xbb\xcd\x7d\x3a\x66\xcf\xfb\xcc\xef\x5d\xfb\x7b\xcf\xfe\xde\xc7\x49\x89\x7e\x14\x60\x9a\xba\xf3\x86\xce\xee\xd8\xca\x40\xc2\x39\xca\x30\x9c\xeb\xa0\x21\x26\xc0\x88\xab\x23\xb7\x4f\xf7\xa1\x20\xae\xfe\x19\xd1\xdd\xe4\xf0\x2e\x60\xea\x9b\xca\x31\xac\x49\x8a\xde\x0b\x9d\x9a\x63\x58\x92\xb5\xca\xb3\x51\x3f\xa3\x7a\xac\xe9\x2e\x5f\xc2\x06\x66\x40\xb5\xcd\xd2\x0d\xbd\x13\xd2\x7d\xe5\xe9\xbe\xf0\x74\x3f\xdb\x4b\xf7\x85\xa2\xfb\xaa\x8b\xee\x67\x3b\x74\x3f\x0b\xe8\xfe\x22\x4c\x1d\xb5\x7a\xe3\xac\x8b\xee\x23\x4b\xf7\x91\xa5\xfb\xc8\xd2\x7d\xb4\x43\xf7\x17\x9e\xfc\x86\xee\x0b\x45\xf7\x15\xc6\xdb\xae\x4d\xf1\x70\x9f\xdb\x6c\xdd\x75\xed\x8a\x7f\x23\xd0\x3f\x05\xde\xbf\x0b\x6e\xaf\xce\x5f\xa6\x1b\x1a\x9d\x99\xcd\x6f\x2e\x22\x56\x6f\x83\x97\x51\x6a\x0f\xf5\xd6\x3c\xd7\x06\x58\x5b\x0c\x05\xdd\xeb\xc3\xf4\xd5\x27\x4f\x16\x66\x67\x7e\x1c\x72\x80\xa0\xf6\x8e\x26\xd0\x6e\x8b\xa0\x0f\x96\x20\x47\x05\x35\x47\x54\xf7\xc2\x17\x33\xf4\x67\xfe\x66\x81\xb7\xe9\x8a\xc6\x5b\x58\xd3\xfa\x34\x64\xc5\x37\x2a\x69\xe9\x93\x9e\xb3\x92\x0a\x19\x6f\x61\xb3\x5f\x62\x84\x5b\xc6\x66\x58\xdf\x78\xc2\xc4\x03\x4e\xcc\x88\x40\x9f\xfc\xed\x28\xee\x72\xc5\x5a\xc4\x75\x08\xa3\x99\x09\x69\x4e\x3b\x0f\xcf\x97\xfa\xa3\xdb\x1c\x35\xce\x84\x20\x29\x48\x6a\x23\xcc\x54\xda\x85\x12\xa6\xea\xe7\x3e\x94\xea\xe7\x1e\x14\xe6\xee\xaa\x99\x76\xc0\x6c\x1e\xf3\x15\x8d\x33\xbe\xa7\x3f\x9b\xf0\x1d\x6b\x22\xd0\x0b\x54\xe1\x2e\xc8\xd7\x7b\x21\x5f\x53\x73\x54\x3f\xa7\x30\x83\x72\xdf\xf9\xff\xac\x46\x61\x06\x05\xe8\x81\xaf\x33\x8f\xfd\x31\xa3\x02\x61\x49\x18\x2a\x31\x6c\xc8\x52\x65\x58\xa9\x9f\x91\x03\x7d\x13\xc2\xac\x7b\x39\xd9\x7b\x9e\xd7\x6a\xae\x82\x55\xdd\x96\xed\xfc\xfd\x85\x1d\xb9\xf3\x66\xe1\xe6\x18\xda\x4b\x09\x2d\xc0\x82\x72\x7e\x89\xad\xf0\x5b\x10\x86\xa6\x0a\xbf\x85\x91\x4e\x8b\x3f\x0b\xbf\x12\xce\xfe\x38\x7e\xa6\xf0\xef\xc7\x4f\x97\xdb\x6e\xb7\xc0\x89\x1a\x26\x90\x69\x56\x83\xca\x5c\xf9\x66\xd1\xca\xf6\xa1\x15\x55\x5d\xf0\x46\x94\xa2\x6a\x47\x60\x65\x2a\x51\x49\x9e\x55\xd7\x80\xf5\xc6\x1b\x1b\xaa\x23\xb6\xbf\x40\x02\x63\x13\x2b\x7e\x41\x6f\xb8\x14\x60\x65\x94\x0b\x49\x5b\x17\xec\x34\x73\x3d\x17\xb0\xa2\xa0\xaf\x94\xc2\x18\xce\xe8\x9e\xbb\x6b\x76\x2f\x12\xf2\x46\x60\x06\xcc\x63\xdd\xa0\xf9\x96\xb0\x30\xce\xfd\x73\x01\x4c\x8d\x67\x0d\xc7\x25\xdd\x77\x7d\x54\x8e\xce\xe8\x3e\x30\x73\xf4\xab\xd0\x11\xf4\xb7\xf6\x42\x80\x77\x5f\x0f\xa7\x55\x5a\x4c\xf7\x8d\x4c\xf7\x0d\xc7\x6d\xe8\x3b\x18\xc2\x23\x54\xe1\xfd\xb7\xee\x54\x46\x3c\xd8\x9c\x19\xde\xee\x60\xde\x75\x1e\xef\xc4\xa1\xc1\xe8\x82\x7e\xed\x05\x50\xd6\xee\x7a\x1c\xf6\xb1\xbf\x09\xdb\x50\x46\xea\x2b\x8f\xe0\x7c\x77\x0e\x6b\xf3\xd1\x27\x4b\xcb\xb7\xbb\xb4\x0c\x31\xb8\xc1\x65\xf0\x9c\xba\x4e\xb1\x3f\x9f\xe9\x4d\x8e\x64\xb6\xdc\x8d\xe1\xbb\x7c\x20\x5f\x6d\x58\xb4\x49\x8b\x30\x92\x6f\x18\xfd\x4a\xdc\x18\xc9\xd7\x97\x36\xa1\x7c\xed\xa0\x67\xfc\x22\xd9\xdf\xba\xc4\x57\x32\x0c\x19\xf6\x24\x95\x74\xc0\xf8\x05\x32\x8e\x7b\x01\x4c\xd3\xda\x13\xed\x11\x25\x9f\xe9\x20\xfc\x06\x0f\xf7\xcf\xba\xfb\x6f\x12\xfa\x87\x74\x31\x76\xfd\x1d\x51\x9d\x3c\xf1\x90\x82\xb5\xd3\xd3\x9d\xcf\x9d\x13\x71\x45\x02\xbf\xea\x47\xea\x43\x8e\x5e\x48\x90\xc0\x31\x0e\x22\x8d\x7d\x91\x90\x41\xa5\xd0\x39\xd9\xa7\xe4\x48\x30\x0a\x0b\x70\x42\x0d\x20\xda\x5e\x85\xd7\x4e\x52\x1d\x73\xbe\x05\x66\xbf\x41\x95\xb9\x49\x4a\xe0\x64\x7f\x4e\x35\xef\x5b\x2f\xd9\x37\x9a\xaa\x8c\x5f\xc0\xd3\xfd\xc4\xd4\x60\x09\xa0\x36\x40\x55\xd9\x05\x1e\xf3\xde\xb4\x14\x27\x4d\x47\x4d\x19\x3a\x6a\xd2\x1b\xfc\x38\xad\xc7\x6b\xc7\x21\x7b\x8e\x9e\x2b\x12\x53\xe3\x26\x6e\x2e\x32\xdd\xc2\x1b\x73\x79\xfa\x4b\x1a\x78\xb2\xe6\x2b\x1a\x63\x78\xbc\x6f\x50\xda\x90\x5d\x65\x22\x61\x6d\x62\x88\xd3\xd2\x38\xf1\x7e\xa2\x44\x7b\x8b\x3f\xa6\x56\x25\xc2\xf0\xac\x45\x92\x70\x11\x0a\xd5\x5e\x72\xd1\x71\xc7\xd4\x77\xaf\x71\x4f\x95\xe6\xab\xe9\xdd\xbd\x84\x62\x83\xe9\xdd\x2d\x3c\x94\x83\xf3\xbc\x28\x34\xd2\x5b\x0c\xd3\x4e\xcb\x41\xcb\xc9\xfb\xdb\xe4\xb6\x4d\x3b\x4f\x51\x1d\x0d\x03\xeb\xe5\xa2\x6a\x45\x0d\xb8\x3f\x82\x4a\x87\x55\x21\xd3\x7c\x15\xa0\xc7\x6c\x03\x73\xa2\x64\xec\x89\xa6\x2c\xc3\x30\x23\x05\x7a\x25\x94\xde\x06\x15\xcc\x21\x1b\xf8\xae\x80\xfd\x0d\xb9\x0b\xd3\xa4\x0e\x3c\xb1\xc7\xa9\x79\x4d\x66\x0a\xdb\xa5\xfa\x19\xc1\x46\xfd\xdc\x6d\x8c\xc9\x6e\xa6\xd4\xbd\x3e\x07\x79\x93\x93\xb1\x95\x08\x6b\x58\xe2\x2d\x6c\x34\xe3\xbd\xd8\xcb\x65\x06\xb4\xa7\x1b\x2a\x2e\x5b\xbe\xe2\xcf\xf7\x2b\x12\x2f\x29\xca\xd1\x0b\xea\x2f\xbd\xbb\x25\xbc\x83\xce\xab\x05\x47\x07\xb4\xc6\x19\xdd\xdc\x39\xb3\xc5\x9d\xfe\xcd\xf9\x8a\xde\xe0\xdf\xfc\x89\x06\xfe\xcd\xcf\x68\xe0\xdf\xfc\x94\xc2\x4e\x2c\xaf\xe7\xd4\xd8\x05\xbf\xa2\xf0\x23\x25\x8f\xe4\x20\xb8\xe3\x01\x5e\xeb\x14\xfb\xf2\xc4\x7e\x66\x95\xa4\xf0\x8b\x7e\x59\xf2\x4a\xc0\xaf\xfa\xd1\x5f\xcb\x00\xef\xdd\x3b\xfc\x60\x4a\x70\x26\x97\xf0\x9b\x7e\xbe\xa4\xa9\x80\x2f\xfa\xd1\x5d\xf8\x00\xdf\xeb\x57\x73\x4d\x04\xfc\x4c\x09\xb2\x1f\x8d\x0b\x35\x68\x7f\xef\x2f\x54\x89\x0c\xc7\x63\x6f\x2b\x16\x6f\x31\xfc\xc3\xaf\xe6\x7e\x4c\x59\xbc\x85\x9f\x28\x41\x6e\x5d\x0b\x53\x31\x28\xf8\xa2\xf3\x4e\xec\x7c\xc7\x2a\xeb\x68\x46\x33\x3e\xa3\xe2\x41\xec\x08\x64\xaf\x7f\x58\x95\x8b\x46\x44\xc7\xf4\xd6\xa2\xe6\x1a\x88\x76\xb9\xf2\xb6\x72\x61\xe6\x79\x07\x43\xb6\xb3\x83\x7d\x6f\x04\x8f\x2c\x6e\x85\x8e\x55\x45\xe7\x25\x15\xb3\xdb\x9b\x8c\xe7\x39\x2d\x66\x31\xe8\x9f\x3d\x00\xac\xbf\xa2\x1a\xed\xbc\x12\x1b\x17\x9a\x3d\xd5\x6c\x6e\xc5\xe3\x9c\x5e\x1e\x6a\x2c\x62\x5f\xc1\xfe\xc0\x9b\xdd\x55\xac\xd2\xf5\xe1\x2a\x65\x97\xb1\xe6\x91\x1a\x92\x72\x37\x1e\xe7\x2d\x35\xf9\x70\xf9\x1e\x97\xee\xdb\x30\x2e\x6f\x45\x8b\x33\xfa\x6a\x1e\xd7\x90\xc8\x76\x38\x4a\x2f\x25\x14\x86\x13\x71\x7a\x43\xd4\x48\x93\x03\xe8\xe9\xae\x0f\x71\xb0\x34\x71\xb9\x80\x9d\xee\x3a\x08\x37\xb6\x85\xeb\x9c\xc0\x4f\x77\x3d\x84\x5b\x41\x46\xc2\xdc\x90\x85\xf9\x1f\x85\xf9\xa1\xda\x53\x02\xaa\xd3\x56\x18\xc1\xe0\x13\x4c\xf7\x96\x82\xe9\x69\xd3\x95\xb8\x59\x0e\xf2\x1b\x4a\x42\x7e\xda\xed\x5c\x6c\x22\x20\xf2\xf3\xae\x91\xf3\xb4\xad\xa3\x24\xf1\x5a\xe4\xab\x5c\xea\x5b\x51\x74\xcc\xd7\x20\x90\x6c\xe8\x48\xdc\x2e\xd6\x1a\x18\xe6\x8a\x85\x6d\xc3\xad\xb8\x5d\xa4\x35\x24\x77\x8a\xfc\x81\x56\x9e\xed\xa0\x6d\x78\xd2\x86\x18\x6f\xf2\xe4\xf3\x76\xe6\x6e\xe9\xf7\xaa\x19\x44\x31\x9e\xc6\x63\x39\xc6\x7e\x4b\x53\xa6\x0b\xbb\x39\x50\x53\xce\x2e\xfb\xe3\xa7\xda\x1f\x22\x67\x8b\x28\xee\x4b\x1d\x73\xb6\x8f\xe2\xa9\x3e\x34\x3c\x8e\xe3\x24\x8e\x52\x19\xc5\x7d\x81\xfb\xb1\x0e\x3e\xea\x82\xba\x2f\xb8\x4c\xa2\xb8\xff\x1a\xb9\x7b\x16\xcc\x46\x83\x41\x3e\x11\x7d\x12\x4f\x54\x7d\xfa\xbd\x1f\x9f\xc6\x20\x89\x34\x61\x5b\xcd\xdd\x0d\x26\xb8\xb3\xa6\xae\xce\x3d\x50\xb9\xf5\x7b\x67\x4e\x43\xa3\xa4\x76\xc0\xd6\x91\xf1\x34\xbd\x80\x91\xe1\x98\x1d\xd5\xd1\x15\xfa\x7d\x13\x70\xe2\x95\x89\xab\xe0\x14\xf2\xe7\x61\x48\x77\x1a\xcd\x79\x51\xf0\x0b\x85\xb7\xab\x28\xde\x87\xb8\x8d\xfa\xee\x42\x55\x7c\x60\xb1\x0b\x4e\xad\x3a\x23\xd9\xad\x3f\x8d\x3e\xaa\x4f\x1f\x23\x2b\x67\xf6\xd7\xac\x89\xbe\x2a\x17\xdb\x86\xdf\x77\x1d\x0c\xc0\xdd\x01\x20\x8f\xe3\x8a\xd9\xe8\xfc\x71\xf2\xe3\xdb\x57\x27\x03\xe3\x1b\x9b\xcf\x2f\xbb\xbc\xc1\x4d\x18\x71\x29\x2e\xaf\x28\xd1\xb9\xb5\xa3\xb0\x5a\x2f\x66\xa9\xe6\x89\x86\xe3\xed\xf7\xf9\x86\xb2\x48\x43\xbf\x49\x8b\x7c\x16\xa9\x22\x16\x36\x5a\x96\xe9\x82\xfa\xa8\xe1\xbf\xe8\xb5\xf9\x1e\x6f\xf1\x5f\xf5\x8b\x23\x38\xb7\x61\xc0\x64\xba\x30\xc1\xbb\x0c\xa3\x24\xaf\x25\x7a\xa5\xc3\x4d\x86\x2e\xdf\xaa\x92\x0e\x7e\x3d\xe3\xbc\xa6\xb0\x7a\xa1\x29\x8b\x09\x51\x6c\xca\xe7\x91\x38\x7e\x83\x04\x4e\x9e\xa2\x38\x8d\x1e\xa9\x9c\x3e\x6c\x78\xce\xfc\x6e\x57\xcc\xaa\xd5\x19\x15\xf1\x41\x5d\x4a\x15\x30\xbe\xce\x6a\x31\x78\x78\x77\x74\xff\x6f\xf7\xff\xfb\xde\x5f\xef\xff\xed\x48\xf4\x7a\xe2\xa8\x7e\xef\xf5\xd0\xf0\x5a\x68\x87\x79\xd3\xd4\x41\x5e\x3e\x53\x3a\xa0\x22\xe5\xf5\xb5\xf8\xaf\x51\xab\x2e\x95\xc9\xf2\x86\x76\x53\x6e\xc1\xd0\x09\xb9\x71\x68\xae\x43\xa2\xeb\x7e\xf5\x25\xed\x6b\xbb\xa4\xd0\x23\x31\x65\x99\x4a\x33\x8a\x9c\xfa\xd0\x8f\x63\x5b\xab\x49\xab\xab\xd5\x8a\x89\xdb\xeb\x73\xd7\xa9\x1c\xbf\xf1\xe3\x57\x95\x32\xca\x8b\x2b\x61\xa6\x7f\x57\xa4\xc6\xac\xc8\x4b\xa9\x4d\x1b\x0e\x50\x03\x0a\xed\x3e\xed\x3d\xda\x34\x10\x2f\x54\x56\x55\x61\x3d\x70\x4d\x7c\x54\x56\x47\x50\xd0\xd1\x50\xf4\xd9\x1f\x3f\x8f\x0f\x08\x41\x1b\xc5\x47\x03\x3b\x74\x40\xe8\x70\x31\x9a\x25\xdc\x5a\x00\x31\xd8\xe0\x31\x75\x31\x97\x37\x06\x03\xa8\x99\xf4\x0d\x72\xf2\x28\x55\x30\x7d\x1d\xb0\xcc\xa4\x35\xc0\xe5\x1e\x4c\xc8\xf4\xfd\x7c\x2e\x5c\x01\x30\xc2\xff\x30\xe4\x99\x92\x4e\x16\xea\x1a\x64\x73\x85\xe6\x8f\x6f\x4d\x13\x99\x8b\xd8\xbd\x4a\x2f\xcf\xc2\x5e\xb0\xc3\xaa\xdd\x96\x69\xe8\xf8\x85\xa3\x06\x4e\x3e\xe1\x86\x90\x35\x67\x18\x56\xc6\xfa\x21\x7a\xf6\x1b\xcd\x64\xc0\x5c\xbd\x9e\xe2\x81\x03\x42\x44\xaf\x57\x45\x39\x8b\xc4\xf1\x9e\x06\x27\x95\x45\xee\x78\x93\x3c\x46\x15\x6c\x0c\xdf\xb1\xc8\xd4\x69\x2f\xe2\x88\x74\x73\x75\x14\xeb\xaa\x1f\x7f\x0c\x47\xa9\x9e\x2d\xdc\x9d\x0a\xfa\xd5\x87\x0d\xd8\xe9\xad\xe3\xe9\x03\xdf\x1d\x7a\xd8\x45\x05\x67\x0b\x2a\x22\xdd\xc9\x83\xe8\x84\xd2\x59\xa4\xeb\x88\xe2\xfe\xd4\xce\x57\x52\x87\xd6\x4e\x05\x35\xa1\xb5\xe3\xbe\xab\xa1\x1f\x47\x94\x49\x91\xd3\x52\x0f\xdc\x7d\x58\x4e\x6b\x2c\x5f\xa2\x69\x8d\x65\xea\x79\x45\x63\x52\xab\xcb\xda\xe6\xc7\xd2\xb5\x16\x39\xd7\xd7\x6e\xc8\x5d\x5f\x77\xf0\x61\x83\x0d\x6d\x61\x77\xb3\x42\x4e\x9a\xd1\x36\x52\xdd\x2d\x37\xf2\x5d\xda\xe2\xbb\xc7\x28\x55\x7c\x67\xa2\x14\xfb\x38\x52\x29\x38\x5e\x19\xe7\x6e\x2c\x95\x90\x07\xa3\x28\xf7\x3c\x68\x35\x79\x3f\x01\xcf\x15\x27\x55\x2c\x83\x82\xf8\x86\xdd\x4c\x5c\x84\x33\x71\x1b\xcc\x62\xc2\x4e\x1d\xb7\x3a\xf0\x36\xe3\x39\x99\x7b\xc6\xad\x9b\x9f\xbb\x41\x6c\xd5\xff\xa4\x9e\x58\x3a\xb0\xf6\xfd\xa4\x52\xfd\x5d\x50\x1b\x7f\x0d\x14\xee\xd4\x24\x66\x64\x72\x0a\xeb\x00\x09\x17\x7f\xda\x9c\xc6\x59\xd7\x37\xd5\xd4\xda\xde\x76\x61\x11\x22\x84\x6c\x9a\x48\xcc\x4c\x98\x93\x0d\x86\xb5\x3e\x6e\x77\x88\x3c\x43\xb3\x0e\x7d\x41\xa9\x76\x6a\xe6\xf7\x17\x61\x98\x05\x71\x3d\xd0\xcd\xd7\x6d\x23\xa4\x87\xbd\x95\x43\x06\xb1\x50\x0e\xb4\x5b\xb1\x9e\x33\xb5\x19\x5d\x0d\xd2\x81\x3f\x1f\x0a\x67\x54\xdf\xd0\x2e\x44\xba\x45\x6d\x2d\xb6\x2a\x17\xe3\x60\xfe\xad\xa7\xd4\x70\x6a\x6b\xcc\x56\xbb\x33\xc6\xc1\xb0\x63\xe2\xb1\xb3\x8d\x6e\x44\x3f\x85\x53\x4a\x28\xb1\x43\xd9\xd7\x1e\x61\xb6\xae\xf7\x61\xef\xbb\xa7\xa6\xd0\xf3\xad\xea\x77\xdd\xaa\x7e\xea\xf5\x6e\x2a\xec\x94\x58\x57\x58\xbf\xd7\xf1\x77\x6e\x2e\x5c\x8f\x95\xba\xf1\x8a\x65\xa6\xed\x8a\x65\xbd\xde\x0f\x28\x18\x32\xbe\x78\xd9\xcd\xec\x51\xcd\xcb\xc6\xcb\xc7\xbe\xdc\x0c\x84\x65\x72\x5b\xc5\xbe\x06\xb7\x8d\x40\x2f\x7b\x82\xfe\x1c\xd4\xc1\x82\x6a\xbe\x0a\x22\xff\x28\xd5\x5b\x8f\x74\x35\xc7\xbe\x47\x52\x8f\x6f\x3d\xf3\xf9\xdc\x8e\x1f\x1a\x91\x5f\xc2\x30\x65\x4d\x75\x56\xe8\x9b\x37\x1a\x71\xc1\xc2\x10\x2f\xb2\x15\xc0\xa5\x5e\xf6\x5c\x6d\xdd\xe0\x95\xe1\xe0\xb5\x57\xd3\x88\x09\x1d\x4c\x87\xa7\xe6\x58\x41\xea\x2b\x7c\xdc\x08\x15\xee\x6c\x86\x32\x45\x9a\x44\xa2\xdf\x30\x88\x8a\xbd\x62\xee\x3e\x5a\xf4\x44\x27\x98\x78\x24\x86\x80\x27\x55\x51\x24\x85\x7d\x79\xed\xd6\x55\x49\x69\x53\x1e\x9b\xb0\x20\x3a\xe4\xcb\xdc\x95\x79\x66\xd6\x91\x68\xe6\x12\x9e\x9b\x55\x22\x5a\x63\x58\xa5\xeb\x91\x89\xd7\xb2\x4a\xd7\x77\x13\x81\x2e\xf4\xd3\xbd\x84\xa2\x73\xfd\x74\x3f\x61\xe8\xad\x7e\xfa\x2e\xe1\xe8\xb3\x7e\xfa\x6b\x92\xa1\x47\xfa\xe9\x6f\x49\x85\x1e\xea\xa7\xff\x4e\xa6\xe8\xc4\x35\xf0\x13\xbd\xfc\x55\x8d\x9a\xd7\x69\x2e\xca\x64\x13\x5c\x0a\x77\x86\xcd\xc5\x71\x29\xb8\x9b\xe4\x72\xd0\x7c\x93\x5c\x42\x3e\xa3\x4c\xe6\xf2\x32\xf9\x02\x86\x24\x1a\x59\x73\x31\xa6\x7e\xd7\xd3\x56\xb2\x1c\x48\x6e\x15\x16\x9b\xae\x63\xb1\xf8\x58\x3a\x36\xf1\x95\x9e\xd0\x92\xef\x81\x7e\xaa\xd2\x42\x55\xfb\xde\xdc\x47\xfd\x4f\x4a\x7e\xa2\x83\xba\x24\xfc\x9d\x12\xe4\x53\x4c\x15\xfe\xd5\xd4\x82\xe1\x9b\x30\x8f\x82\x4b\x65\x71\x00\x63\x90\x4c\x7f\x76\x09\xb0\xe7\x19\x83\x60\x75\xe3\x40\x4d\xa9\xba\x67\xc1\xbf\xf9\xae\x45\x56\xbe\x61\x0c\x4c\x97\xf5\x37\xe4\xe8\x37\x1d\x2f\x38\xd3\x8f\x2e\xec\x7b\xa5\xdf\x44\xc5\x60\xea\x9e\x1c\x4b\x41\x6a\x5a\x54\xfd\x05\xe6\xf7\x6f\xf6\xf7\xaf\x18\x4a\xff\xf1\x3b\x9b\x78\x1f\xc3\x5c\xd7\xa1\x58\x02\x0a\xf7\x78\x17\x66\xee\x71\x04\x6b\x53\x4a\x77\x62\xd7\x6e\x7e\x5e\xa3\xe8\xb9\x13\xac\x90\x35\x97\x54\x2f\x43\x32\x68\xde\xac\xe9\xa0\x79\x17\xc3\x86\xed\x3f\xd3\x7d\x0f\x4b\x66\x4f\xf1\x61\xa5\xe1\xea\x60\x42\x58\xb0\xee\x38\x2e\x5d\xc0\xe9\x89\x41\x07\x1d\x39\x0b\x41\x0b\xfa\xc4\x4c\x46\xb8\xb3\xbf\xb4\x31\x15\x86\xcb\x00\x94\xe0\xab\x9e\xdb\x30\xbc\xeb\xfe\x6a\x27\x36\x0c\x17\xac\xf3\x38\x99\x75\x07\xd1\x9b\x1c\x7e\xb8\xf3\xe1\xc3\xff\x7e\xf3\x97\xfe\xf1\x00\xe1\xeb\xc9\x87\xd3\xab\xed\xe9\x9d\x05\xc4\x1f\x3e\x7c\xd3\x8b\xdb\xb7\x97\xb8\xe5\x18\xbd\x88\xde\xd0\xc5\xd3\xcf\x6b\x24\x07\x25\xaf\x44\x46\x21\x5e\xe4\x71\xfb\x32\xb3\x8e\xec\x10\x2f\xe2\xf6\x25\x6c\x75\x46\xab\xcb\x0f\x56\x76\xd1\xdf\xba\x6e\x0c\x28\xbe\x92\x24\x7e\x58\x14\xb1\xbf\xe2\xeb\x78\x74\x67\x98\x68\x81\xe9\x85\xbc\x0e\xee\x06\x19\x19\x42\x45\x28\x4c\x49\x10\x4f\x0e\x72\x72\x38\x1a\x67\xfd\xfe\x91\xec\xf5\x74\xf8\x37\xfa\x99\x66\xa8\xc2\xb8\xd7\xcb\xcd\xd4\xe1\xb2\x06\x77\xc2\xa4\xfe\xc2\xd6\xc3\x11\x94\xc1\xc2\x2a\xc5\xe3\xf4\xc1\xd0\xca\xed\x39\x61\x93\xf4\x74\x5c\x4e\x0e\x0f\xd3\x53\xe2\xb7\x42\xe6\xc7\x9f\x92\x17\x68\x8e\xb7\x36\xac\xdc\x95\x46\x2e\x61\x93\xe1\x29\x94\xd5\x99\x7e\xa3\x65\x12\x46\x02\x2b\x6d\x40\xa9\x84\x99\x19\x1c\xcc\x72\x5c\x1b\xeb\xe6\x21\x8c\x7e\x42\xa8\x93\xc8\x14\xf6\x45\xaa\xcb\x51\xd7\xfd\x45\x46\x45\xcb\xfa\xfd\x07\x44\xd6\x31\x6e\xea\x19\xd3\xdf\x3d\xe9\x48\x70\x0f\x78\x40\x02\x86\xc7\xcc\x93\xa0\xaa\x73\xeb\xbb\xdf\x26\x87\x87\x2c\x20\x45\xa5\x49\x51\xd5\x57\xba\x39\x62\x88\x7d\x94\xe0\x8e\x12\x75\xbd\x3b\xf0\xdc\x3d\x0d\xe8\xb3\xdd\xcf\x1f\xe6\xb4\x77\x58\xc7\xdd\x75\x83\x40\x00\x6f\xdf\x0a\x0d\xe6\x4e\x4b\xb4\xb7\x36\x4c\x08\x19\xdd\x19\xd6\x01\x06\x6b\x98\xa9\x8d\xe3\x26\x30\x6e\xf0\x24\x05\x7b\x8b\x4f\xc8\x8f\x0d\xee\x1c\xcb\xc3\xc3\x90\x2d\x39\xc6\x63\x6c\x6f\x12\xe2\x36\x08\x68\x05\x96\x29\x30\x6e\x56\xe5\xf0\x6a\xe7\xc7\x18\xf6\xb3\x47\xe6\xcd\x3c\x04\x5d\xd0\xcf\x49\x06\x4a\x1f\x7b\xce\x4a\xca\x4a\xa3\x1f\x70\xa0\x65\x96\xae\x69\xc2\xc2\x80\x68\x15\x86\x79\xce\x66\x89\x40\x53\x1d\xe9\x4d\xd1\x31\xa1\x28\x77\xb1\xe0\x04\x4a\x8d\xa9\xc7\xb9\xbe\x9b\xed\x3c\x2f\x0a\x78\xcb\x88\xb6\x14\x29\x28\x35\x97\x8d\xac\xd3\x0b\x86\xe1\xf3\xae\x80\x6e\x9e\x8e\x76\xd8\x02\x51\x7b\x0e\x6e\xe3\x74\x6f\xb7\x18\x1e\xb1\xdb\x02\xf4\x77\xd9\x14\x99\x10\xfd\xda\xea\x5b\xe9\x57\x9d\x37\x7c\x44\x5a\xf5\xc2\xf0\xb0\x73\x1e\x90\xfa\xa0\xfc\x84\x91\x0b\x66\xa3\x8c\xbd\xd1\xcf\x96\x28\xf0\x54\xbf\x29\x62\xc1\x4b\x46\xd0\x05\xab\x03\xb0\xa9\xe7\x26\xb5\x41\x17\x5c\xd0\xcf\x18\x1e\xeb\x72\x86\xf6\xf0\x89\xdd\x14\xe4\xde\x0e\x22\x19\x0e\x22\x61\xc7\x0d\x75\x63\x83\x75\x23\x67\x89\xf2\x50\xbe\xe4\x6a\xe6\x72\x57\x98\x3c\xf3\xe6\xf1\x8a\xfd\xb7\xf0\x82\x11\xd4\x30\x2c\xe8\xb0\x57\xd8\x89\xe2\xd5\x65\xf3\xc6\x74\xbc\x72\x7d\x9b\x87\xb6\x4b\xbb\xbd\xce\xe7\xbf\xb7\xce\x8e\x4e\x7a\x26\x90\xb4\x5f\x9f\xef\xd5\x07\xac\xbd\x9c\xb0\x19\x5f\x75\x75\xb7\x3b\x6f\xa6\xb2\x33\x60\xc7\x8f\x8c\xbc\x62\x48\x52\x0c\xaf\xf7\x36\xf3\x8a\x21\x6b\xbe\xd1\xb6\x7a\xf0\x21\xcc\xe1\x49\x27\xab\xa5\xe8\x07\x78\xcd\xe0\x47\xa6\x15\x8c\x5f\x3a\x18\xde\x66\x7c\xc2\xb4\xf1\x8d\x84\x17\x0c\xb9\x68\xf3\x7b\x81\xb1\x16\x69\xbe\xed\x5b\x4c\x15\x74\x89\x05\x35\x97\x69\xd2\xdf\x53\xe8\xf2\x8f\x14\x7a\x7b\x43\xa1\x0e\xe3\x16\x53\xa8\x6d\x13\x19\x5e\x23\xa9\x95\x3d\x76\x4b\x6d\xfa\x12\xc9\x77\x5f\x55\x4b\xcb\xc2\x75\xaf\xa8\x79\xc5\x6c\x34\xb2\x57\xcc\xda\xad\x76\x69\x69\xdd\xd7\x51\x37\x78\xfe\xc6\x5b\x69\x9b\xfa\x97\x59\x66\xea\xbb\xc6\xf4\x7d\x98\x8d\xab\x97\x7a\xbd\xd0\x32\x90\x21\xcb\x00\x5e\xac\xa5\xb3\xd9\xd3\x0d\x65\x52\x2d\x74\x28\xa3\x02\x09\xc8\x1a\x40\x2b\x2d\x72\xc5\x37\x74\x37\xd7\xb6\x71\x6d\x22\xfb\x7a\x43\xc6\xb3\xd0\x70\xd1\xf4\xc5\x8c\x67\xe6\x36\xe4\x05\x95\x4f\x0b\xaa\x1e\x1f\x5d\x3e\x9f\x21\x89\xc7\x14\x59\x85\x91\x1d\x07\x16\x88\x02\x31\x8c\x13\x7b\x21\x8a\xb3\x2c\x3a\xe1\xf2\x19\xaf\xd8\xcc\x8e\x54\x63\x4a\xb3\x47\xb9\x45\x9d\xa6\x45\x72\x30\xe7\x59\x55\x22\x0c\xee\x56\xd4\x9d\xbb\x7b\x6f\xab\xe0\xac\xa8\xc4\x9e\xf2\xd5\xd7\x94\x2f\x33\xc1\x8b\xe2\x1d\x5f\x6f\xdb\x8a\xf1\xef\x28\x4b\x44\x27\x00\xe9\xef\x02\x80\xb8\xe7\x1f\xa8\x8e\xc8\xd9\x55\x63\xf9\xf5\x35\xbe\xa0\x73\xb9\xc5\x7b\xec\x5d\xbe\xa6\xf0\x1e\xa4\x8a\xdf\x07\x82\xc7\xea\x7d\x3e\x93\xcb\xce\x1a\x67\x2d\xc8\x44\xc3\x60\xab\xcb\x27\x47\x2d\x0e\x69\x7d\xba\x17\x89\xb0\x0d\xb3\xfb\xf5\x6b\x5e\xe6\x67\x05\xdd\xcd\x99\x15\x39\x65\x72\x6f\xce\xf7\xb9\x5c\x3e\xe2\x62\x46\x45\x19\x14\xe2\xf3\x79\x49\xbf\xaa\xd0\x43\x36\x7b\x99\x8a\x45\xce\x4a\x73\xa6\x41\x89\x50\xa3\xec\x91\x1a\x28\x39\x5b\x3c\xd6\xad\xbf\xa1\x99\x44\xc1\xf5\x07\x3a\x04\xab\x8e\xf8\x3e\x97\xdb\x8e\xab\x7d\xff\x04\xd2\x18\xa6\xfa\x2a\xda\xec\xcf\x7a\x13\x71\xbe\xaa\xd4\x1f\xa2\xce\x19\x97\x92\xaf\x0e\xe9\x40\xf2\xb5\xa2\x8e\x71\x60\xb9\x6a\xcb\xd2\x24\x10\x73\x5b\xe8\x10\xa3\x8d\x0c\x5b\xd8\x10\x8a\x82\x03\x75\x7f\x4e\xe3\x84\xe3\xb1\x7b\x48\x96\x18\x16\x7b\x32\x5f\xe4\x6c\xc6\x2f\x8e\xcd\x8f\xca\x78\x46\xba\xb2\x09\xfa\xa9\xa2\xa5\x7c\xc8\xf2\x55\xaa\x20\x78\x26\xd2\x15\x3d\xee\x4c\x4d\x9a\x66\xe0\xd8\xb9\xce\x5d\x71\xf6\xc4\x01\x24\xd0\x06\x03\x67\xef\x4d\xab\x3a\x04\xb4\x16\xa4\x09\x07\x25\x0f\x93\x0c\x16\x54\xbe\x75\x82\x25\xa9\xa0\x0c\x5f\xa5\x5a\x5f\xf8\x0c\x3a\xb4\x73\x59\xe7\xb0\x21\xa3\xe7\x18\x24\x7f\xa4\x29\x9f\xa4\x20\xb9\x09\xfb\x5c\xc0\x92\xda\x20\xd2\x6b\x0c\x17\x6a\x3c\xe8\x9d\x4c\xb3\x95\xf7\x2b\x23\xe8\x17\xa6\x45\x32\xfc\xc2\x8c\x6c\xc7\xf0\x9e\x91\x5f\xd8\xc0\x41\x0b\x3f\x98\x4c\x35\x36\x9d\x73\x36\xdb\xb9\x01\x5a\xd2\xcf\x32\x06\xf5\xbf\x61\xf5\xc2\x1b\x46\x9d\x9d\x9a\x45\x86\x9c\xcb\x46\xc7\x5d\xa5\xf5\x9a\x7c\x89\x04\x56\xab\xf0\x01\x4b\x57\xb4\x5c\xab\x75\x46\x46\xd8\x60\x9e\x9a\xeb\xc2\x27\xa7\x30\x25\x43\xb7\xb9\x4c\xc3\xcd\xe5\x5c\xdb\xa7\x8f\xa7\x7d\x92\x0f\x66\xb4\xcc\x28\x9b\xa5\x4c\x96\x8f\x79\xc5\xe4\xf5\xf5\x10\x2a\xb3\x7a\xcc\x31\x50\xbd\xf3\xec\xef\xb7\xed\x93\xca\x1d\x2d\x37\xee\xb9\x36\xc6\x87\xba\x65\xb5\x7a\x5c\xe6\xc5\x4c\x50\x96\x54\xe0\x41\x4b\x38\xb4\x5b\x4a\xa6\xdb\x9d\x8b\xf8\xff\x7c\xfc\xa6\xa3\x7f\x15\xc5\x73\x7a\x49\x67\x87\x7f\x16\xa2\xd3\x56\x5c\x63\xd3\x46\x56\x95\x92\xaf\x62\x5b\xf3\x12\x49\x6c\xf1\x5c\xf1\x19\x2d\xd4\x42\x6e\xb5\x2e\x12\xba\xdd\x73\xdf\x8c\x63\x39\x6d\x0b\x1f\x5c\x24\xae\x80\x4e\xc4\x2e\x40\xa3\x3e\x12\x5d\x64\xc1\x6d\x7b\xd3\x1d\x40\xe5\xb2\x62\xe7\xde\x38\x32\x15\x0b\xb5\xca\xd4\x89\x6a\x95\xa9\x9a\xb3\xd7\xd8\xef\xbb\x82\x7e\x6e\x4c\x14\xc3\x41\xe4\x47\x83\xd8\xbd\x62\x3e\xbc\xbd\xd7\x99\x2e\x76\x94\x75\xde\x48\x3b\x73\x51\x43\x6b\x9e\xd7\x66\x8d\x1d\x75\xd4\x57\xbb\x6d\xdb\xf7\xc3\xfb\xe3\x1a\xa0\xfb\x0e\x6c\x98\x3e\xb0\xd1\xfc\x7a\x4e\x2f\xc7\xf9\x1c\x71\x42\xc8\x4c\x5e\x5f\xab\xdf\xb5\xfd\x2d\xfc\x65\xec\x74\xc2\x4f\xf5\x0d\x50\xd9\x44\x2d\xf7\xd3\xe2\x27\x7a\x79\x4a\x98\x33\x0b\x99\xf0\x53\x92\x99\x00\x30\xb6\xaa\x79\x00\x47\xe5\x8b\xc3\xd4\x95\x71\x50\x4d\x9b\x23\x61\xaa\x46\x42\x35\xc9\xf5\x31\x52\xae\xed\xf8\x55\xda\x68\xab\x9b\xa8\x7c\x13\xb1\xe7\x60\xed\xb5\x8a\x85\xaf\xd7\xe7\xc8\x8a\xb4\x2c\x4f\xd2\x95\xcd\x71\x65\x76\x45\x55\x3d\x63\x5d\x99\xdf\xe2\x4b\x8f\x6d\xd9\x24\xed\xc7\x51\xdc\xb7\x6f\xa6\x2d\x9d\xd5\xd5\xdd\x38\xd2\xba\x32\xdc\x4f\x83\xc1\xb4\xcf\xfe\xf7\x9c\x5e\x26\x73\xd9\x61\x78\xd9\xb4\xf1\x55\xd9\xba\xec\x2c\xcf\x76\x72\xcd\x24\xd8\x4e\xe8\x2c\x70\xd9\x1a\x0c\xaa\xc8\xba\x2e\x22\x6c\x91\x2b\xf3\x13\x62\x20\xb7\xbb\x97\xc7\x37\xaa\x29\x76\x5b\xbe\xe2\x6b\x95\xbd\xd4\x43\xd7\x18\x0f\xd3\xb0\x9a\xc6\xfd\x40\x48\x0e\x6c\x76\xbd\xaa\xb3\xcf\xd7\xd7\x3e\x79\x50\x4a\xbe\x7e\x2d\xf8\x3a\x5d\xe8\x59\x3b\xcc\xd6\xfe\xd6\xeb\xd5\xc5\xd6\x82\x2a\x6d\xe4\x89\xf1\xb8\x6c\x94\x6a\x7e\xc2\xbd\xde\x4f\x74\xe0\xce\xc9\x3a\x4f\x78\x5b\xc6\xc6\xf5\x22\x5a\x0d\x96\x03\x35\x2e\x8e\x45\xf2\x0e\x09\x37\x12\xc0\x9e\xb4\xbb\x16\x21\x47\x33\xa6\x37\x28\x4c\xb2\xab\x77\xf7\xee\xf8\xda\x7a\xe0\x72\x4d\xad\x8e\x69\x84\x56\x7d\x38\xad\xe4\xd4\xf5\x35\x32\x0f\x44\x0e\xf4\x77\xa5\x10\xbc\xb5\x69\xde\xf0\xc2\x4a\xd4\x86\x0d\xa7\xce\xa0\x86\xbb\xf9\x38\x76\x99\x8c\xdd\xe0\xe5\x9a\x8e\xf1\x8e\x2d\x0d\x3b\x66\x64\xc2\xbc\xc7\xd5\x69\xc2\xcc\xfc\xe3\x12\xcc\x34\xa4\x6a\xb6\x9e\x6c\xd6\xaf\x29\x61\xb0\x4e\x85\x56\xa1\x9c\x5e\x85\xa6\xe4\x2d\xa2\xc0\x31\x1e\xd0\x62\x35\xd5\x1d\x31\x55\x25\xa7\x82\xce\x09\x87\xa9\x85\x5c\xa9\x1f\x0e\xe5\xa5\x1c\x64\x82\xa6\x92\xbe\xa3\x9f\xe5\x09\x9f\x51\x45\x1f\xfa\x59\x3a\x33\x3b\x35\xb7\x25\x9f\xd1\x54\x61\xe7\x38\xf7\xd8\x17\xb2\x2b\xee\x13\x4d\x1d\x3f\x17\x1b\xfb\x8c\xa4\x9d\xcb\xda\x6d\x80\x00\x69\xa6\xb0\x7a\xff\x3b\x53\x12\xd3\x4e\x99\x50\x91\xe1\xb8\x3a\xca\xdc\xa9\x7d\xd5\xef\xe3\xa9\xbd\x4a\xe1\xb1\xca\x83\xde\xa2\x6c\x52\x69\xb3\x1b\xa7\x59\x4f\xbd\xd9\x92\x9b\x8f\xff\x33\x61\x36\x1e\xa5\x6d\xb0\xed\x14\x5f\x1b\x8e\xad\xd6\xc5\x40\x50\x36\xa3\x02\xc9\x81\x9e\xe7\x7d\x91\xcf\x68\x1a\x00\x03\xa1\xfe\xf0\x79\x47\x51\x8a\x72\x16\xd5\xb1\x08\x26\xec\xd4\x59\xd0\x30\xc3\xfe\xd1\x5c\x26\x8f\x90\x04\x8e\x03\xe3\xe4\xa8\x90\x89\xb1\x9f\x6f\x26\xcf\x64\xf2\x66\x27\xef\x5a\x26\x4f\xdb\x89\xce\x6e\x46\x4e\xd8\xe9\x01\x21\xbc\xd7\xd3\x66\x14\xc4\x67\xf2\xf1\xbe\x75\x6a\x28\xbe\x1e\x35\xed\x36\x4a\x79\x59\xd0\x71\x03\x1d\x61\x8c\xa1\xc5\x84\x9d\xee\x98\xfb\xd7\xd3\xad\x62\xff\x65\xca\x66\x05\x15\xa5\x9e\x4a\xbd\x05\x64\x40\x92\x8c\xb0\x09\x3f\x05\x33\x63\xaa\x69\xb9\x3e\x88\xc2\xdd\x9b\x57\x1c\x32\x0c\xac\x9e\xd0\xfc\x04\xe8\x4b\x66\xf8\x2a\x23\x27\x48\x40\x85\xc7\x1d\x7b\x64\x75\x05\x76\x06\xcf\x06\x39\x9b\x73\x52\x6d\x9b\x30\x13\xd6\xf2\x49\x68\xec\x01\xfa\x4b\x08\xa8\x2e\xad\x77\x23\xed\xc1\x3c\x0b\x0c\xc8\xb4\x69\x97\xbb\x2e\x3b\x0c\x35\xc1\x9c\xec\x1c\x67\xbb\x52\x5e\xb4\x93\x10\xd6\x6e\x7b\xa1\x58\x57\xb9\x9a\x29\xa8\x1e\x17\xc6\x19\x1c\xa6\x44\x8e\xa7\x63\xa7\x0a\x4c\x9d\x48\x54\x30\x39\x54\x6a\x43\xcd\x14\x57\x24\x45\x15\x36\x04\x75\x35\x95\x24\x75\x03\xaa\x3c\x3c\x1c\xab\x3c\x93\xf2\x54\x65\x53\x8a\x8a\x91\x7e\xdb\xad\x3f\x2d\x34\xa4\x14\x40\x1b\x3e\x19\x8d\x8b\xce\xac\xad\xa1\x75\x1c\x9e\xd0\xd3\xb1\xef\x39\x76\xec\xfa\xfc\xa1\x94\x22\x3f\xab\xcc\x1d\x9b\x72\x50\x52\x19\xa4\x28\x1d\x70\xc7\x99\x63\x7f\xfd\x1d\xab\x14\xa3\xde\xd4\x1c\xb3\xdb\xee\xc9\x5b\xc4\x61\xa7\x6d\x93\xaa\xb7\x4f\xdb\xfe\x1a\x66\xbc\x4c\xfc\xfd\x9a\x9f\xac\xbe\x3a\xc4\x21\x31\x1e\xb7\x54\x0c\x73\x02\x24\x9c\xcf\xc9\x2c\x95\x69\x42\x61\xc6\x57\x27\xb5\xb2\x0e\xba\x93\x4f\x3a\xb5\xf7\x4f\xb5\x16\x9d\xcf\x91\x3c\x20\xc4\x87\x33\x32\x73\x2c\x64\x44\x98\x69\xcf\x2a\xaa\x99\xf3\xe1\xc8\x9a\xd3\x6f\xcd\x3a\x72\xa0\x16\x0e\xfa\xd8\x53\x3f\xe4\xf5\x9a\x2b\x25\x3b\xa6\x67\x39\x51\x4a\xad\x65\x91\xb4\xd7\xcb\x15\x97\xa4\xa4\x9a\xe4\xa7\xea\xcb\x24\xd7\xc3\x3a\xf5\x36\x8d\x3c\x9f\x21\xe1\xa6\x76\xf5\x83\xc7\xf6\x55\xb8\x99\xde\x5a\x95\x36\x68\x69\x27\x7e\xf3\x53\x2a\xaa\xea\x9a\xdc\x09\xf3\x83\x61\xaf\x47\xcd\xa4\xfd\x18\xc5\xeb\x43\xbb\x10\x62\x50\x62\xbc\x47\x59\x98\x7b\x1d\x01\x0a\x63\xe4\xa8\x1e\x67\xe4\x60\xa4\x8d\x37\xf5\x6c\x1f\x28\x0f\x6b\xab\x3c\xcc\xc8\xc1\x10\x76\x34\x88\xf9\xf1\x9c\x4c\xe6\xb0\xf6\x1a\xc4\xdc\x00\xb3\xf6\x1a\xc4\x9a\xac\x4d\x9d\xae\xfd\x25\x11\x3b\x8d\x2c\x6f\x6c\xa4\x38\x2e\xc8\xa4\x80\xa5\x6f\xa4\x30\x8d\x2c\x7d\x23\x4b\xb2\x34\x75\x5a\xc2\xcd\x7a\xbd\xb9\xa5\x90\x52\xe3\x9c\xa5\xb3\x66\xa3\x90\x5c\x82\xce\x44\x7a\xa1\xe8\x25\x30\x4e\x10\x9a\x1d\x3f\x43\x73\x28\x70\x32\x57\xab\x22\x7c\x7d\xdd\xa0\xad\x5d\xc7\x32\x28\xb0\xe9\x86\xe8\x13\x5a\xc3\x52\xb1\x61\x7f\xe4\xc9\xad\x35\x1c\x63\x47\x4a\x3f\x4b\x63\x48\xaa\x94\x9a\x80\x11\x1a\x30\x98\x1d\x19\x06\x36\x9b\x9b\x6d\x43\x1d\xc8\xab\x88\x81\x65\xaa\x52\xa5\xfd\xe0\xd6\x89\xb5\xbe\x71\x1b\x9e\x66\x38\x19\xc3\xdf\x17\xc8\x4e\xe8\x20\xec\xc4\x8e\x9b\x2c\xa5\x13\x55\xd1\x8d\xc3\xfa\xb9\x1f\x7c\x78\x57\xf7\xf9\x0f\x83\xf5\x55\x1b\x56\xa7\xf0\xe8\x1e\x52\xda\x8e\x86\x47\x3d\xec\xed\xa1\x06\x44\x63\x63\xc4\xbc\x0b\xca\xd8\x43\xba\xd9\x0f\xd4\xd8\x84\xfe\x32\x0d\x0e\x66\xf9\xdc\x9c\x27\x28\x51\xb1\xda\xdb\xbe\xdb\x86\x61\xb0\xf2\xec\x61\x57\xad\xfb\xa0\xdc\xde\x70\x79\xe7\x70\x4c\x8f\xbc\x5d\x2a\x35\xe6\xa6\x72\x42\x95\xbe\xa4\x6f\xdc\xbc\xc1\xd8\xf4\x45\x43\xd9\x69\x6a\x36\x52\xd5\xc3\x0f\x08\x99\xcb\x5e\x8f\xeb\xd5\x93\xf9\x9d\xd9\xdf\xb5\xc9\x11\xcc\x53\x19\x91\x46\x0b\x12\x4a\x0b\x52\xd2\xb5\xea\xf5\xac\x0a\xa7\xb4\xb7\xeb\x6b\x4a\x4c\x3d\x17\x28\x83\x0a\x5f\x5f\x23\x64\xaf\xa8\xc6\x7a\x9f\x00\x6b\x32\x34\xd2\xfc\xe4\x46\x8f\x77\x1c\x7e\x54\x6b\xc7\x71\xac\xad\x2f\x13\xaa\x77\x2f\xd4\xab\x69\xc4\x34\x36\x93\x86\x23\x87\xc9\x55\xb0\x5a\x9e\xf0\xd3\x60\x26\x35\xcb\x61\x3b\x27\x69\xb5\xe1\xca\xa8\xcf\x2f\x90\xc6\x47\xb8\x5d\x10\x8e\xc7\xd3\x5e\xaf\x09\xf3\x14\x6f\x1d\xd9\x72\x43\x0a\xfd\x23\x1b\xb8\xe5\x4a\xcb\xcc\xbd\xc3\x5d\xc4\x5a\xf7\xa7\x86\xf6\x08\xc1\x4a\x40\xcd\x79\xc1\xb2\x80\xbb\xe9\x6b\x4a\xea\xd5\xc1\x83\xe9\x71\x93\x6b\xd4\xf4\x7f\x58\xa4\xa5\x16\x42\xd5\xe1\x14\xe3\xa4\x3a\x9a\x36\x59\xd8\xac\x26\x54\x86\xac\xb6\xdd\xa9\xd5\xae\x9c\x30\x48\x49\x75\x34\x3d\xae\x92\x29\x94\x64\x38\x2e\x8f\xd2\x71\xa9\x7d\x16\xfa\xfd\xb1\x99\x75\xf8\xa4\x3c\x1d\x7f\x42\x73\xc8\x26\xe5\x29\x50\xc8\x31\xe4\x7d\x32\xef\xda\xf0\xdb\xb6\x6e\x78\xb5\x86\x61\xde\x93\x48\x9b\xd0\x5d\x6d\xdd\x76\x6b\x40\x81\x3c\xa4\x40\xea\x27\x68\x28\x49\xee\x1e\xe7\x64\x08\x05\x19\xc2\x8c\xb0\xf1\xfc\x28\xed\xf5\x8a\xa3\xd2\xea\x8a\x6b\x32\x9d\xcc\x4f\x61\x49\xf2\x49\x71\x6a\x22\xfd\xd9\xb0\x5e\x43\x58\x68\x47\x04\x38\x33\x41\xbe\x94\xde\x7d\x40\xc8\xca\x94\xbb\x24\xf3\xfe\xe8\x28\x85\x77\xa4\xe8\x8f\x8e\x4a\xf5\xf5\x12\xab\x0f\x17\xaa\xc2\xfe\xe8\x14\xce\xc9\x85\xaa\xe4\xad\xfa\x19\xc1\x67\xb2\x22\x84\x9c\xab\x7c\xef\x74\xbe\x47\xaa\x45\x95\xef\x21\x79\xa4\xf2\x9d\xa8\x9f\x11\xbc\x21\x1b\x42\xc8\x43\x5d\x5f\xaf\xf7\xae\xd7\x7b\xd3\xeb\x7d\xc6\x9f\xd0\x02\x4e\x80\x43\xbf\x3f\xc3\xf0\x23\xca\x80\xc3\x06\xce\xa0\x80\x0a\xc3\xac\x4f\x16\x9d\x3b\xcb\xaf\x6d\xbe\xb7\xa6\xd8\xac\x4f\xde\x76\xe6\x9b\xf7\xc9\x5d\x28\xfa\xe4\xae\x5f\x5f\xa8\x66\xf1\xac\xdf\xb7\x4d\xad\x5c\x53\x0e\x8c\xd9\x0d\xad\xce\xfb\x64\xd4\xac\xed\x52\x61\xe0\x80\x59\x78\x60\xba\x8b\x7f\x42\x6f\xe1\xcc\x61\x7a\x2b\xc8\xa3\xb1\x0b\x8c\x7c\x70\x79\x7d\x7d\xf0\xee\xfa\xfa\xfc\x80\x90\x87\x26\x42\xef\xb8\xd5\x66\x0b\x99\x1b\x41\x38\xf9\x6a\x10\xee\xda\xe8\xd8\x8a\x36\x21\xe0\xfb\xa8\xd3\x87\xa2\xdf\xd7\xf2\x40\xb1\xe2\x18\x5f\xcd\xfa\xfd\xf1\x82\x20\xc3\x88\x58\x71\x9a\x81\x5b\x73\xe2\xe2\x16\x5a\xf7\xbd\x64\x79\x3a\xd6\x4c\xfd\x94\x3c\xbd\xbe\x9e\x9c\x5a\x64\x91\xe1\x6b\xac\x43\x97\xe8\xc0\x25\x46\xcd\x7e\x8a\x15\x14\x63\xc4\xbd\x4e\x79\x7d\x5d\x05\xcf\x7e\x5e\x7b\xda\x9a\x6d\x05\xd5\xc7\x91\x4a\x2c\x5c\xad\xad\x71\x17\x87\x5c\x07\x48\x2b\x93\x0a\x28\x9b\x3d\xb7\x2f\x4f\xb7\xe1\xa6\xd8\x8f\x4d\x37\x7c\xab\x7e\xab\x25\x51\x73\x25\x6c\xa5\x5f\x45\x9c\x3b\xb8\x0e\xbd\x06\x1b\xbd\xa3\xcf\xac\x19\x19\x37\xab\x07\x2b\x8e\xc1\xda\x18\x5e\xb9\x8f\x94\x49\x71\x99\x54\x5b\xab\x38\xab\x56\x48\x65\xd6\xa7\x46\xf6\x99\x08\xa4\xc6\xab\x67\x6f\x59\x9d\x81\xc4\x3a\xff\xd8\x08\xfb\x50\x4d\xaf\x06\x1b\xb3\xff\x06\x53\xa8\xac\x0d\xa4\x7b\x20\xdc\xb4\x5c\x0d\x14\x9c\xfa\x1f\xf1\xe4\x9a\xd6\x6d\x6c\x2d\x55\xfa\x1b\x69\x09\xd3\xba\xc0\xba\x19\x9f\x76\x87\x5c\x19\xbe\x9a\x92\x40\xa6\xc7\xc0\x6d\x0f\xd7\x97\xe1\x1b\xfc\xa6\x21\x2d\x0c\x69\x5d\x91\x4e\xd2\x4e\xb7\x26\xb0\xa9\xa5\xff\x01\x21\x99\xa6\xd7\xeb\x06\xc0\x66\x01\x7d\x95\xb5\x29\xa5\x84\xf4\xf8\x13\x52\x53\x87\x21\x52\xa5\xf2\x1a\x1a\xb6\xc0\xf5\x64\xa9\x2c\x59\xb2\xad\x5a\x25\x59\xa0\xb7\x2d\xd7\x6c\x33\x2b\xfc\xe2\xd6\x9b\x30\x84\xdd\xd3\x23\xb5\x64\x6e\x3a\x58\x87\xd1\x1c\xdc\x70\x99\xea\x0d\x2a\xc8\xc9\xd4\x3a\x4e\xaa\xc5\x1d\x0f\x37\x10\xec\x42\xd2\xaf\xb0\x08\x21\x29\xd6\x50\x98\x95\xd9\x54\xf7\x2b\xb8\x5d\x04\x93\xd5\x8d\x0f\x9d\x79\x3a\xb0\xab\x5b\x22\x61\x3a\xf0\x4b\x5b\x52\x01\x9a\x13\x53\x7c\x60\xd1\xc7\xc1\xe2\xce\xc0\x3c\x87\xa1\x85\xb9\x59\xbf\xe3\xdf\x14\x5f\xed\xad\xdf\xae\x2a\x4d\x13\x35\xc7\x1c\x10\x52\xe2\xab\x72\xa0\x09\x6d\xb8\x52\xda\x99\xba\x74\x80\x8c\xe7\x37\x40\x62\x45\xdd\xfe\x76\xf3\x39\x62\xfd\x3e\x1c\x20\x43\x5e\xa5\xbd\x79\x0a\xe3\x07\x19\xf6\xba\x8d\x0f\x4f\x1f\x6e\x8e\xb7\x56\xad\x45\xc7\xaa\xb1\xb0\xab\xc6\x82\x14\x8d\xd5\x9f\x82\xb4\x30\xfd\xdc\x1f\x41\x06\xb2\x63\x4b\xba\xb1\xc7\x5c\x7b\x30\x06\xda\xc3\xda\xe9\x15\x0a\x9d\x12\x96\x64\x38\x5e\x1e\xcd\x9c\x1e\xb5\x54\xca\xcd\x8a\xf4\xfb\xbc\x8f\xd0\x86\xcc\x26\xcb\x53\xdc\x79\x76\xa9\xf7\x1f\x8e\x48\xde\xeb\xe5\x47\x64\xa5\x4d\xa8\x7f\x41\xeb\xc9\xf2\x14\x36\x96\x15\x57\x6a\x02\xda\x4b\x25\x4f\xa6\x31\x27\xab\xad\x7f\xd9\x59\x77\xfd\x51\x1c\xb8\x55\xd0\x0c\x0e\x6a\x5a\x58\x11\xde\x47\x9b\x7f\x3b\x32\x66\xe1\x1c\x6e\xcd\xc8\xa5\xe0\x17\xda\x45\xe3\xa9\x10\x5c\xa0\xb8\x5c\x9a\x6b\xcd\xe9\x86\x8a\x48\x8a\x54\xdf\x8c\x1c\x7d\x54\x25\x3f\x46\x5c\x44\x1f\x75\xc1\x8f\x36\x12\x70\x91\x9f\x53\x1d\x0b\x38\x0e\x45\xc7\xaf\x3b\xe7\xaf\x7a\xb1\xe0\xb6\x08\x64\x82\x6a\xe1\x02\xef\xb5\x05\x04\xde\x71\x1c\x6d\x2e\xa6\x44\xb8\x98\x6a\x6f\xc0\xd9\xd1\x01\x19\xf9\x01\x71\x60\x78\xcc\x09\x21\xb2\xd7\x43\x92\x64\xb5\x49\xe3\x8e\xfb\x60\xd7\x98\xf0\x6b\x3c\x7f\x05\xa2\x16\x40\x5a\xf2\x88\x7a\xe8\x59\xd6\x76\x0b\xcf\xc4\xef\xde\xcb\x30\x97\x2d\x88\x41\xba\xec\x8d\xb3\x19\xef\x87\xf3\x24\x95\x29\x1a\x82\x5b\x30\x76\x14\x6b\x1c\x63\xbd\xf7\x20\x79\x30\xdc\x50\x0e\x97\xb7\x43\x7d\x50\xbd\x3b\x2c\x8f\xbb\x12\xed\x36\x0f\x31\xf5\x26\x5d\x59\xfc\xc9\x94\x25\x87\x3b\x9e\xaa\xf1\xdd\xd6\x10\x87\x6b\x1e\x3d\x6e\x98\xad\xda\x84\x21\x70\x7b\xa2\xe6\xf0\x44\x6a\x07\x05\xfd\x5c\x87\xb7\x77\x35\xd9\x75\x51\x70\x10\x67\xdb\xef\x08\xa4\x22\x5b\x67\x32\x7a\xca\x09\xbb\x6d\xb7\x7a\x2b\xe0\x13\x17\x3f\xa1\x29\xc1\xcd\x81\xb8\xeb\x2e\x83\xb1\xaa\xa8\x09\xbe\xea\x29\x1b\x4c\xd0\xc8\xfa\x71\xbb\x1f\x32\xe7\x8b\x7b\x53\x25\x99\x99\x22\x54\xf7\x72\x3f\x4f\x85\x24\x35\x53\x9d\xbf\xf4\xd2\x6c\x6b\xd8\xaf\xe1\x21\x53\xe5\xf0\x70\xca\x9d\x22\x4b\x71\xf9\xda\xb8\x55\x41\x65\x79\xc7\x9f\xd3\xb4\x65\xc0\x1b\x1f\x19\x86\x45\x15\x3b\x67\xfc\x82\x45\x1a\x9e\x83\xc6\x30\xff\xad\x7d\x2c\x53\xa3\x06\x9c\xbc\xd5\x26\xd5\x4d\x4a\xe8\xa3\x8a\x5d\xce\xea\xf5\x50\x57\x72\x27\xf7\x62\x60\x66\xab\x43\xf6\x7a\xde\xcd\xc2\x90\x90\x83\xc4\xc0\x1b\x6e\xb8\x81\x5d\xb9\x63\x9a\xef\x11\x1d\xd4\x5a\xb3\xa2\xa0\xd4\x24\xa7\x9e\xe4\x41\x3c\x0d\x3a\xb0\xaa\x36\x64\x64\x38\xce\x8e\x9c\xfe\x3e\xce\x9c\x18\xaa\x08\x9f\x64\xa7\xfa\x5e\x6e\xdd\xf5\x90\x5b\xc5\x4c\xef\x5d\xcb\x74\x71\x6c\xb4\x82\xe4\x2d\x9a\x5a\xe5\xac\x21\x47\xa4\x6d\xe1\x11\x9d\x73\x41\x51\x0e\xe1\x6c\x32\xb1\xfa\xed\xa9\x97\x62\x9e\xa3\xf4\x81\x7d\xc8\xed\x0c\x43\xd3\xd7\xd8\x7a\xdf\xd7\xb2\x20\x94\xa9\xfe\x20\xd4\xd9\xb6\x3d\x13\xe9\x42\x9f\x88\x62\x3b\xb0\x64\x23\x2e\x82\xdd\x07\x99\xb0\x53\xcb\xe1\xb4\xd1\xb8\x47\x99\x6b\x94\xb9\x43\x99\x77\xa0\x5c\xfb\x7f\x05\xbc\xf4\xf3\xed\xc6\x71\x3e\xb1\xeb\x7a\x4e\xa3\x6c\x1a\x45\x53\x28\x45\x18\x8f\x03\xbf\xb3\x6f\x10\xd5\x1a\xd5\x14\x27\x54\xa2\x5c\x8d\x01\xa0\xd8\x26\x6d\x1b\x76\xac\xff\x40\x9e\x65\x7c\xe8\x09\x67\x0a\x0c\x4f\x65\x10\x17\x76\x25\xe1\x15\x85\x2b\x1d\x63\x91\xc2\x26\xa7\x17\xc9\xae\x69\x91\xd8\x42\xb5\x9e\xa5\x92\x26\x12\xed\x7e\xa5\x5b\x0c\x65\x75\x56\x66\x22\xb7\x76\x1f\xbb\x79\x9e\xc9\xed\x16\xa3\x00\xc2\x9f\x9a\x56\x55\x2d\x07\x9a\x50\x74\xd1\xfa\xfa\xe8\xbf\xa3\xf8\xdd\x92\x46\x1f\xe3\xbe\xe8\xc7\x1f\xa3\x15\x9f\x55\x05\x8d\x66\x9c\x96\x11\xe3\x32\x62\x94\xce\xa2\x79\x91\x2e\xca\xc1\x07\xf6\x9c\xe5\x32\x4f\x8b\xfc\x0b\x8d\x72\x1b\x19\x85\xf1\xc8\x3b\xde\xe9\x2b\xc6\x2f\x79\x15\x59\x55\xe1\x8c\x46\x69\x51\x44\x25\x95\x07\x71\xf3\xf8\xec\x9f\xdd\x90\xba\x35\x96\x8f\x16\xd5\xeb\xfd\x1d\x55\x24\x7e\x28\xa8\xae\x57\x8a\xcb\x9c\xe9\xeb\xc2\x4b\x46\xd3\xf3\x28\x8d\x4e\xb4\x36\xa2\xf7\x04\x8d\x60\x7a\x5a\xac\x8e\xa3\x77\x22\xcf\xce\x4b\x49\xc5\xc1\x07\xf6\x5c\x46\x05\xe7\xe7\x56\x23\xd1\x58\x0e\x56\x69\xce\xa2\xbc\x8c\xac\x8d\xab\xc1\xe4\xe3\x5a\xf0\x85\x48\x57\xef\x73\xb9\x7c\xa6\x10\xfe\xa8\x03\xaf\x2c\xd3\x32\x52\x6a\x40\xf4\xf1\xb5\xf9\x6e\xda\xfc\x38\xf8\xc0\x7e\x51\xfa\x8f\x2d\xf5\xd1\x47\x14\xcb\xe7\x1a\xd6\x19\xd7\xf4\xbb\x48\x99\xb4\xf4\x8b\xdd\xd2\x2b\xab\x8f\x6d\xd5\x1a\x29\x38\xae\xcd\x1a\x61\x8c\x29\xca\x06\xd3\x21\xb6\x0b\xb9\xf8\x9d\xc7\x3e\xaf\xfb\x41\xee\xf6\x9d\x89\x58\xa3\x04\xb4\xbf\x23\x5e\x01\xa0\xfa\x2f\x92\x22\xa7\x33\x55\x45\xc6\xd9\x86\x0a\xa9\xfa\xd1\x88\xf3\xa7\xc5\xca\xd0\x11\x34\xda\x41\x8c\xb1\xbc\x74\xa1\xc5\x6c\x00\x31\x05\xd5\xf8\xef\x48\x2d\x25\x83\x3e\xfd\xbb\xe9\x53\x33\x67\x88\x5e\x0f\x89\x41\xce\x18\x15\x3f\xbc\x7b\xf9\x82\x7c\x7b\x34\xcb\x37\x91\x3e\xd6\x27\xf1\x3a\x9d\xcd\x72\xb6\x38\x2c\xe8\x5c\x26\x23\xba\x1a\xc7\x0f\x8e\x96\x77\xdd\xd7\x39\x67\xf2\xf0\xc2\x98\xe8\x32\x2e\x56\x69\xa1\xbe\x9f\x3d\x78\xc5\xd7\xe5\xc1\xd1\x9d\xb3\x07\xd1\x5b\xbe\xa2\x3a\x28\x71\x74\x41\x99\x8c\x2e\x04\x57\x8f\x4b\xca\xa2\x52\xa6\x42\xc7\x80\xbb\xe4\x95\xd0\x28\xd9\xee\x19\x1c\xdd\x59\xde\x7d\x70\xb4\x16\xf4\x06\x20\xbe\xed\xcb\x7e\x7c\x74\x67\x2d\xe8\x83\xa3\x3b\xb3\x7c\xf3\x20\xc6\x50\x4f\x7e\xa1\xd7\xf1\x37\x81\x1e\x3b\xa0\xab\x33\x3a\x23\x4d\x7f\x21\xbd\xab\x24\x6a\xed\x65\x8c\x45\x63\x52\x17\x1d\x8a\xcd\x89\x92\xf8\xae\x63\x11\x43\xe6\x15\x28\x08\x0c\x72\x60\x84\x05\xc8\x41\x43\x2c\x80\x94\x48\x80\x1c\x28\x21\x83\xf1\x16\xc4\x60\x5e\x15\x45\x99\x09\x4a\x59\x57\xcc\xeb\x3d\x6d\x08\xf0\xee\x34\x67\x7c\x76\x79\x73\x7b\x8d\xac\x75\xdb\x35\x75\xa4\xdc\x3b\xbc\xdd\x7c\xe1\x34\x46\xea\x94\x45\xbf\x83\xa4\x84\x34\x86\x8a\xbc\x45\x59\x70\x35\x51\x73\x46\xab\x30\x08\x89\x2a\x10\x90\x35\x79\x50\xc8\x4e\x57\x66\xaf\xd1\x57\x56\x99\x3f\x79\x35\x7d\xf3\xf4\xe7\x5f\x9e\xbe\x7d\xd7\xb1\xd0\xf9\xa5\x1e\x37\x4a\xe1\x8f\x5c\xa8\x92\xc1\x07\xf6\xba\xa0\x69\x49\x23\x41\xd7\x5c\xd8\xab\x4e\x24\x8f\x8e\x96\x52\xae\xcb\xe4\xce\x9d\x45\x2e\x97\xd5\xd9\x20\xe3\xab\x3b\x3e\xde\xee\x26\x17\xb2\x4a\x8b\xc3\x19\x5f\xdd\xc9\xcb\xb2\xa2\xe5\x83\x81\x8b\xbb\xf7\xfa\xe9\xc9\x93\xe7\x27\xdf\xd7\xb0\x9c\x49\xc4\x15\xf2\xf1\xd3\xbf\xbf\x7b\xf3\xd0\xa7\x8f\xad\xa6\x82\x32\x0c\x39\x79\x89\xa6\x81\xfe\x24\x75\xb4\xba\x29\xe4\x6a\xc9\xa4\x77\x96\xa6\xc4\xad\x42\x9a\xb5\x84\x6b\x00\x25\x55\x03\x22\xd8\xbb\x41\x32\x68\x26\xc3\xb4\x76\xa0\x0b\x4d\xfa\xc3\x3c\xe6\xdc\xc8\x03\xde\x46\x09\x32\x12\xda\x62\x52\x19\x8e\x9c\x3d\xbc\x6a\x59\x64\xc6\x33\x7f\xce\xf3\x07\xd9\xf7\xff\xcf\xde\x9b\xa8\xb7\x8d\x63\x09\xa3\xaf\xa2\x70\xaa\x32\x60\xf9\x48\x91\x9c\x54\xaa\x8a\x69\xb6\xc7\xb1\x9d\xc4\x89\x9d\xcd\xce\x5a\x55\xc3\x4b\x91\x90\xc5\x98\x22\x64\x10\xf4\x12\x9b\xf3\x1a\xf7\x81\xee\x8b\xdd\x0f\x1b\x57\x90\x92\x93\xea\x9e\xe9\xff\x9f\xea\xfe\x62\x0a\x3b\x0e\x0e\x0e\x0e\x0e\xce\x82\x12\x3e\x2e\xbb\x85\xc5\x84\x21\x5c\xaf\x03\x44\x61\xb2\xfa\xb3\x9f\xa8\x8f\x57\x19\x93\x1b\xab\xb5\xcd\x0b\x69\xe0\x2d\x46\x4a\xaa\x9b\x99\x8f\x2e\xe8\x1a\x1d\x15\xb2\x93\xee\x11\x55\xec\xe8\x58\xc5\x6e\xa9\xdb\x8c\xae\xa2\x5e\x15\x12\x11\x73\xb8\xb4\x6b\xac\x18\xd1\xa5\x8f\xaf\x76\xb4\x52\x2f\xb2\x42\x3c\xcd\xf8\x46\x1d\xa6\x51\x88\xa7\x3e\x1d\x2a\x3f\x8a\xa9\x65\xff\x3e\xfe\xf3\x51\x72\xf7\x2e\x4a\x2a\xe6\x5f\x49\xcd\x52\xc7\xce\x69\x35\x04\x80\x66\x96\xec\xba\x89\x1d\x33\xba\x85\x2d\x86\x2d\x7c\xb8\xca\x77\x2e\x4d\x34\xb2\x26\xd1\xf0\xbb\xb3\x52\x19\x45\x65\xe6\x1e\x09\x9f\x60\x8f\x68\x8d\x90\xcc\xe4\xe1\x1a\xbb\x94\xa1\x19\x24\xc0\x8b\x40\xe8\x12\xe4\xd9\x23\x6f\x02\x4b\xf7\x08\x85\xe0\x37\x6b\x2d\x65\xad\x39\xaf\xb5\x04\x8f\xa1\x08\x96\x40\x6c\xe0\x45\xe1\xdc\x0d\x18\xf2\x20\x00\x1f\xa4\xc9\x86\x69\x03\xc5\xfc\x56\x37\xe7\xff\x9c\xf3\x73\xa5\xb2\x98\x01\x33\x88\xe7\xc1\x33\x35\x22\x1f\xd1\xd3\x5d\xb5\x44\xaf\x96\x58\x72\x79\x77\x02\xbe\xc0\xa5\xfc\x5e\xc4\x64\x53\x94\x21\x63\x92\x23\x06\x7e\xe3\x9d\x33\x57\x14\x55\x81\x95\x44\x39\x4e\x5e\x32\xce\x94\x78\xee\x7b\xe4\x41\x06\x11\xe7\x87\x33\x37\x81\x39\x2b\x6c\x2e\xab\x03\xce\xba\x48\x2e\xe5\x4d\xab\x17\x61\xf0\x46\x41\x4c\x52\x8c\xa4\xe5\x53\xe0\xca\x5d\x3f\x12\xd6\x37\xc3\xdf\xc6\x63\xc8\x74\x92\x34\xce\x19\xde\x7f\x38\x06\xcf\x95\x36\x49\x23\xb2\xc4\x09\xb2\x2c\xe0\xff\x17\x55\x5c\x5e\x45\x96\x74\x79\x49\x7e\x88\xbb\xd6\x46\xb0\x61\x01\x23\x4b\xd7\xda\xc8\xc4\xec\xbc\x91\x1e\x31\xc8\xd1\xcc\x19\xcc\xd9\x88\x45\x8c\x73\x00\x1a\x70\x83\xe1\xc0\xda\x10\x19\x9c\x10\x48\xdd\xc3\xd1\x42\x98\x78\xb9\xd6\xd8\x6a\x64\x28\xbe\x81\xe7\x28\xb7\x76\x47\xe2\x60\x7b\x54\xea\xd5\x8a\xd2\x55\x84\x89\x6c\xde\x48\x4b\x29\xd0\x3a\xc5\x57\x21\xb9\x48\xac\x9a\x01\x22\x1b\x2d\x30\xf3\x5f\xe0\xab\xbb\x77\x7f\xdd\x14\x0e\x26\x2e\xe6\x51\x30\xbf\x7b\x57\x01\x23\x26\x81\x50\xcf\x1b\x51\x1c\x13\x3f\x44\x36\xdc\xff\xb5\x5a\x0c\x25\x4a\x64\xa3\x6d\x5c\xdf\x2d\xad\x9c\x13\x99\xa6\xe2\x9e\x0d\x0f\xc6\xbd\x15\x77\xf9\xd8\xcc\x55\x73\x1b\xd4\x70\xda\xb3\xca\x12\x3e\x2e\xce\xed\x82\xd7\x93\x5d\xbd\xd0\x54\x51\x45\xb5\x6b\x52\xc3\xac\x36\xdd\x1c\xec\x0e\xc7\x2f\x19\x21\xa0\x82\xa9\x10\x55\xcc\x6c\x58\x4d\x2c\x01\xc4\x4d\x19\xa2\x36\x04\xae\xf5\x52\xf0\x99\x16\x64\xa5\x7a\x96\x57\xf5\x96\x93\xb7\xf6\x1f\x2d\xcc\x8a\x78\x13\xbe\x1b\xe9\xb8\x6f\x8f\xaa\x3a\x38\x27\x98\x16\x8d\x0b\x23\x88\xcc\xf1\x20\xb8\xe3\xba\xfe\xdd\xbb\x28\x62\xfa\x15\xac\x36\x4b\x4b\x6c\x7c\xe0\xb9\x4d\xe0\xf1\x2c\xdf\x86\x4a\x8b\x81\x10\x03\xd7\x4e\x32\x85\xa7\xe4\x1c\xd3\x59\x4c\x2e\xa0\x2f\xd3\xb5\xe6\x51\x18\xe2\xc4\xaa\x35\xca\x07\xd7\x5b\x2b\xe1\x40\xf3\x6d\x88\x84\x6f\x8c\x02\xc0\x51\x01\x60\xc5\x6e\x69\xd9\xa9\x6a\xda\xa9\x2a\x57\xbd\xf6\xb3\xb4\xd4\x58\xf2\x65\xd5\x2b\xad\x7e\x7e\x28\x8f\x99\x66\xfe\x31\xab\x1e\x7c\x3e\x6b\x5b\x88\xb5\x24\x7f\xb5\x89\xfc\xce\xfe\x54\xa2\x3f\xb8\x33\xae\xda\x24\x33\xa3\x7d\xbd\xf4\xfa\xa8\x77\xa9\x54\xa8\xba\x5a\xe2\x9b\x9b\x3b\x54\x6f\xd2\x9b\x9b\x5f\x37\x45\x86\xd8\x44\x55\x41\x8a\x25\x8f\x42\x69\x58\x2f\xab\x59\x17\x73\x8c\x2b\x29\xc2\x7d\x2c\xf3\xe9\x09\x66\x8f\xb4\xc9\xba\xf2\xc4\xca\xf9\x47\x0e\xef\xd8\xbf\xd2\x67\xee\x30\xc4\xcc\x8f\xe2\x54\x85\x62\xd1\x87\xf4\xdd\xbb\xfa\x36\x2f\x1e\x7d\xe4\xb5\xf9\x4e\x91\x96\xb8\x49\x45\xfc\x96\x9b\xb4\x7c\xdb\x3a\xbd\xb9\xe4\x07\x39\x51\x3d\x3a\xfe\x74\xb0\x67\x41\xcc\x5c\x6b\xef\xfd\xde\xcb\x63\x0b\x42\xe6\x5a\xdb\xc7\xc7\x6f\x2d\x58\xaa\x2f\xef\xe5\x11\x27\x93\x46\xb3\xd1\xb6\x29\xea\x75\x0e\xe7\xcc\xb5\x3c\x1c\x2f\x3e\x3c\x7c\x7c\x60\xc1\x82\xb9\x6f\xd0\x0b\x1b\x4e\xf8\xdf\xcf\x36\x4c\xcd\x2d\x7d\xab\x01\x6a\x8a\xd9\x71\xb4\xc0\x44\x9c\x54\x13\x7c\xff\xde\xc3\xb1\x9d\xc3\x15\x73\x7f\xb7\x82\x38\x0a\x4e\x2d\xb0\xc2\x69\xac\x3f\x17\x24\x4b\xd5\x9b\xa8\xfc\xce\x96\xfa\x4b\xd2\x6a\xf9\x8d\x13\xc6\xf7\xa3\xfc\x11\x63\x5f\x94\x67\x24\x0b\xe6\xe2\x0e\xaa\x7f\x08\xc5\x1d\xf9\x19\xf8\x49\x80\x63\xfd\x4b\xf5\x20\x02\x25\x62\xaa\x5a\x56\xbf\x44\x8f\xea\x9b\xe3\x40\xe5\x57\xc6\xca\x1f\x7a\x08\xea\xa7\x1e\x84\xfa\x59\xef\xa0\xe8\x3c\xa4\xfe\x89\x1e\x21\xff\x56\x7f\xe4\x38\xe5\x97\x6c\x95\x7f\xab\xce\xf9\xa7\x6e\x3d\xa4\x84\x8f\xee\x14\x5f\x65\xea\xaf\x1a\xfb\x29\xbe\x5a\x52\x9c\xa6\x16\x58\x51\xb2\x14\xe3\x0c\xe6\x7e\x72\xc2\x2b\x09\x2b\x5a\x0b\xac\x69\x9c\x51\xeb\x4f\x38\x66\xee\x15\x1b\x05\x24\x09\x7c\x86\xd4\x9e\x00\xbd\x5d\xf4\x41\x7a\x2d\x1e\xc3\x89\xb4\x96\x4d\x40\x4a\xb1\x1d\x0f\x16\xfe\xd2\x61\x28\xb5\x81\x24\x0e\x45\xc7\x36\x08\xda\xe4\x9c\xc3\x92\x92\x25\xa6\xec\xca\x61\xe8\xc4\x06\x5f\x6b\x4f\x4b\x0f\x81\x7e\xa9\x4c\xed\x50\x74\x25\xfc\x0b\xbe\x2e\x2b\x9c\xda\x10\xfb\x5f\xf9\x57\x2c\xbf\x36\x1d\x8a\x42\xf9\x79\xdf\xc1\x68\x69\x83\x78\xee\x13\xfa\xd0\x94\xdf\x3f\x95\x5c\xc1\x59\x30\x68\xca\x8d\x9c\x13\x06\x29\xf3\x59\x14\x28\x89\x91\xf3\x49\xda\x16\x7f\xe9\x70\x18\xf7\x2c\x19\x35\xdb\xd0\xea\x21\xcc\xce\xe1\xeb\xca\x6a\xf0\x0a\x8b\x92\x4f\x13\xf7\x99\xb0\x35\x94\x23\x85\x37\xe2\xb7\x98\x04\x7c\x2a\xbe\x37\xe1\x45\xe2\x22\xf5\x03\xae\x1b\xf4\xc0\xb9\x33\x81\x3a\x39\x70\xee\x4c\x72\x1b\x3e\x8b\xfa\x24\x81\x8f\x3d\x8e\xf3\x3e\x27\xc0\xe0\x45\x22\xe3\x4e\xfd\x20\x6a\x88\xe5\x01\x46\x44\x8f\x15\xa8\xc3\xb3\x64\x54\x59\x95\xda\x4f\x1b\x28\x71\xe5\xf4\x64\x59\x2c\x7e\x2e\xfc\x25\x24\xe2\x8b\x23\x05\x10\xf1\x29\xa4\xc8\x01\xe9\xf2\x79\xd3\x9a\x1e\x6b\xce\x4e\x84\xec\xf9\x92\xd8\x90\x11\xf7\x6b\x02\x1e\x71\x31\x81\x88\xb8\x09\x01\x9f\xb8\x84\x40\x4a\x5c\xe4\x13\x64\xf1\x03\xc4\xb2\x81\x7f\xa6\x58\xda\x31\xc8\x5f\x89\x7f\x6e\xd9\x36\xcc\x54\x39\x9f\xb2\x28\x88\xb1\xca\xf4\xf9\xcd\x49\x7d\xcf\x27\xbc\x5c\x4c\x5c\xf1\x63\xd3\xb2\x61\xa9\xbe\xef\x5b\x36\xcc\x55\xfd\xf9\x03\x5d\xfc\x67\xfd\xf1\x50\x7f\x60\x3f\xc4\xd4\x12\xfa\xb5\xb2\xf0\x8c\x10\xbe\x5f\x55\x5f\x61\x28\xb6\xa0\xfc\xb5\xf0\x23\x3d\xc2\x25\xaf\xb2\xd0\xed\xeb\xe2\x4b\x2a\x9c\x40\x9e\xe8\xf9\xc5\x24\x38\x3d\xcb\x08\xd3\xc3\x25\x31\xcf\x9e\xca\x21\x66\xb1\x65\xc3\x95\xfc\x8e\x23\xcb\x86\x63\x55\x2d\x8c\x55\xf1\x90\xe9\x8f\x50\x7d\xcc\xa2\x93\x8c\xe2\xf2\x47\xe0\x2f\x2b\x60\x0b\x23\x01\xb6\x0b\xd9\xa6\x6f\xd9\x70\xaa\x9a\xc4\x0b\x0d\x67\x46\x49\x72\xc2\x4b\x1d\xc9\x52\xe9\xc2\xe7\x34\x02\x2e\x55\x49\x3d\xd7\x20\x2a\x46\x7d\xa6\x9b\x9f\xe9\x8e\xfc\xe9\x54\x4f\x99\xc9\xd8\x61\xa2\x0a\x09\xc5\xf4\x1f\xab\xa6\xce\x7d\x5d\x28\xf5\x17\x4b\xf5\x79\x3a\xd5\x73\x49\xb3\x69\xf1\xa5\x73\x23\x5e\x7f\x5b\x8e\x8c\xe7\xbe\x54\x4d\x65\xc5\x0a\xd0\x53\xf5\x49\xb3\xa9\x46\x1e\xaa\xe1\x44\x75\x3b\xd3\x30\x2a\xbe\x88\xee\x65\xe9\x27\xbc\xf9\xb7\x7a\x75\xf4\xe8\x2e\x8a\xaf\x28\xd1\xd3\x0f\xb1\x5e\x84\x68\x71\xa2\xbf\x66\xfc\x24\xe4\x4d\xec\x15\x60\x9d\x62\x3d\x1d\xa5\xe6\xaf\x10\xc1\xa7\xbe\x06\xf9\x79\x14\x62\x3d\x06\x3f\x0b\xa3\x62\x3c\xc2\x9d\xa3\x06\x23\xf5\x03\x3d\xb3\xc0\x4f\xce\xfd\x12\xe7\xd8\x5c\x97\xf1\xa7\xb1\xe8\xfe\x50\x75\x5f\x5f\xfd\x80\xc4\x27\x94\x14\xa0\x0c\x88\x9e\x01\xab\xec\x33\xc6\x11\x5e\x7f\x73\x54\x2f\xfa\xe7\x0d\xef\x48\xc8\x33\x5e\xe2\x4c\x7d\xf3\xde\x9f\x14\x7b\x83\x2e\x0a\xe4\xc3\x71\x98\x62\x5d\x3f\xc6\xe2\xc4\x53\x3f\xfc\x29\x16\x98\x7e\x20\xdb\x90\xc7\x97\x0d\xfb\x6a\x61\x33\xc6\xc4\xa8\x5f\x69\x9c\xc3\x71\x09\xba\xd0\x67\xbe\x70\xee\xa9\xc0\xba\x64\xd5\x59\x91\xea\x8c\x39\xd1\xf2\x29\xf6\x79\x57\xcf\x55\x5b\xa7\xf8\xea\x04\xeb\x02\x24\x63\xb2\x67\xb9\x39\xc9\x49\x75\x33\xe3\x72\x9b\x6b\x3e\x50\xa3\xe3\x62\xe1\xd3\xab\xa2\x5c\x92\x45\xac\xd8\x40\xfc\xa7\x65\x03\x23\x36\xbc\x26\xe6\x63\xe4\x39\x01\xbe\x56\xfb\x32\xdc\xcb\x29\x12\xe2\xae\xdd\x9e\xc2\x94\x1f\xd7\xc2\xd3\x18\x71\x29\x81\xf7\xa4\xdb\x71\xda\x3b\x02\x0c\x58\x22\x63\x94\xc1\x87\x8e\x46\xdf\x13\xa8\x18\x92\x8b\xa6\x9f\xf5\x14\x8d\x42\x59\xe6\x4b\x4f\x19\x71\xc5\x97\xc5\xbe\xf6\x14\x4b\x69\x20\x0b\x3d\xed\x6b\xeb\x6a\xa9\x9a\x7a\xd3\x53\x4a\x05\x99\xe2\xc5\x3e\xf5\x14\x9b\xb3\x45\xfc\x84\x50\x59\xf0\x45\x5f\x41\x8a\x67\xb2\xd4\xe7\xbe\xb1\x89\xcb\x83\x2c\xf7\x71\xd5\x42\xfc\x80\xd5\x42\xfc\xd0\xd1\xe2\x47\xbe\x10\x73\x1c\x9c\x62\x05\x62\x16\x74\x17\x0c\xa3\x94\xef\x70\x55\x92\x1a\x4b\x7e\x20\x28\x42\x97\x14\xac\x81\x05\x11\xfa\x0c\xdb\x09\x44\xe8\x23\x3c\x4e\x80\xd9\x36\xc7\x33\x1c\xb8\x3f\x24\x90\x04\x6e\x84\xe6\x89\x60\x22\x77\x84\x53\x8d\x69\x62\x03\xe1\xa9\xe7\x49\x23\xba\x65\x31\xe5\x32\x1c\xa6\xce\x29\x86\xde\x88\x94\x99\xc3\x15\xbf\xb1\xde\xb6\x39\xb5\xa2\xad\xc6\x8e\x39\xaf\x10\xb8\x2f\x12\xf0\x02\xf7\x63\x02\x51\x07\x90\xbc\xa0\xe0\x7c\x83\x44\x6e\x2b\xbf\xa7\xa8\x60\x8e\x8b\x92\x69\xe0\xa2\x85\x96\x13\x67\x01\x5c\x37\x79\xb2\xb1\xd9\xa3\xa1\x6c\x4b\x73\xde\xca\x44\x9e\x04\x62\xd9\x67\x3d\xbd\x2b\x9e\x5d\x55\x08\x78\x05\x88\x7b\xca\x57\xef\x3d\x7a\xcc\xe1\xaa\xf2\xea\x6e\xa1\xcb\x2f\x7b\xca\xab\xeb\x98\x2e\x3a\x0f\xbe\x93\xc1\x7b\x9a\xd8\x70\x1e\xb8\x68\x1e\x48\xbe\x06\xf8\x47\x26\xc8\xfe\x22\x70\xdf\x24\x70\x12\xb8\x9f\x12\x98\x06\x5d\x31\x77\xcb\xa7\x79\xe1\x69\xfb\xdd\xdb\xfd\x1d\xb2\x58\x92\x44\xd8\x8a\x57\x44\x09\xc2\x53\x1f\xa3\x57\xba\xf8\x01\x92\x86\xb9\x8d\x0a\xed\x00\x46\x67\xdf\xe6\x1a\x4f\x8a\x3d\x12\x7c\x31\xf8\x78\x78\xf0\x8c\xb1\xe5\x5b\x79\x21\x7e\x44\x10\xe7\xc3\x21\x31\x88\xe0\x30\xa5\x9c\x04\x55\x66\x8a\x51\xd3\x31\x1e\x66\x17\x84\x9e\x8a\x27\x31\x4b\xf8\xc5\x33\xb6\xc4\xe4\xc5\xba\xbf\x2d\x75\xfb\xee\x69\xa6\x25\x11\xc4\xc8\x43\x09\xb0\x91\x7c\x89\x1b\x51\x9c\x2e\x49\x92\xe2\x63\xf2\x16\xa7\x59\xcc\xc1\x67\x8b\xa8\x50\x89\x94\x0d\x0b\x99\xe9\x9c\x84\xc0\x46\x19\x8d\x85\x6c\x47\x82\xb7\x04\x62\x6b\x54\x8f\xfd\xf0\x1d\x8d\xa5\xe3\x3f\x5e\x2b\x2f\xf5\x4f\x02\xde\xb7\x0d\x99\x18\x82\x7c\x51\xaa\x8c\x2d\x19\xf9\x53\x42\x85\x94\xa4\xee\x2a\x90\x2f\x59\x11\x2f\xf7\x4e\xe9\x4f\xd1\x24\xfa\x2d\x8e\xf7\x86\xec\x57\x4a\xae\x38\xa6\x64\x82\x81\xaa\x7b\x63\xa4\x23\x6f\x8c\xae\xa7\x57\x0c\xa7\x0e\x1b\x71\xa8\xe1\x10\xc4\xcf\x3d\xf5\x64\xe9\xb0\x11\x23\xcc\x8f\x73\xbb\xed\x2b\xaa\x69\x4b\x2e\xcc\x8c\x15\xba\x3c\x13\x37\x0b\xd1\x01\x50\xe1\x3b\x97\xd3\x6b\x0c\x74\x24\xef\x1c\xa9\x0d\x95\x65\xb8\x5a\x62\xe1\x8b\xb8\xbe\x38\x57\x4b\x0c\x6c\x74\x11\xb1\xf9\x0e\xc5\xc2\x3f\xbd\x1f\xa7\x2e\x6d\xa6\x80\xf5\x3c\x4b\x99\x92\x82\x49\xd4\x50\x80\x42\x4c\x27\x54\xb2\xbc\x71\xdb\x2f\x78\xa1\xa0\x59\xf1\x1a\xb7\xb7\x58\xb2\xab\xc7\x9c\x77\xac\x29\x3b\xf2\x49\x26\x21\x52\x72\x45\xe9\xb4\xbe\x56\xca\x00\x05\xed\x81\x6e\x78\x2c\x8e\x7e\xe1\x01\x13\xaa\xad\x09\x08\xc9\x16\x9f\x10\xba\xd8\xf5\x99\xdf\xd9\xb3\xf4\x1b\xdb\x72\xcc\x28\x85\x84\x29\x62\xb6\x8c\x7b\x92\x32\x9f\x65\xe9\xdf\x36\xc7\xe3\x9b\x9b\xfb\xe3\xf1\xdf\x5c\x9d\x54\x68\x83\x08\x4c\x74\x2b\xf0\xe6\x97\xe0\x36\x52\x1f\x89\x5a\xd2\x1d\x72\x6e\x17\x6f\x3b\xc5\x43\x94\x52\x35\x51\xc1\x9c\x2b\xef\x73\xc2\x6d\xa9\x83\xd6\xed\xe7\xb5\x7f\x25\xb7\x6d\x25\xe6\x31\xae\x59\x9a\x54\x63\x99\xca\xb9\x38\xd7\x32\x2e\x85\x9a\x1a\x28\xc9\x66\x91\xc0\xbb\xca\x41\x61\x9c\xc3\xc1\x72\x82\xd9\x76\x1c\xbf\x55\x43\x91\xeb\x93\x22\xdb\x86\x8c\xc6\x4e\x39\xc6\x77\x6f\x0f\x80\x0f\xbb\x92\x54\xf7\x5b\xa5\x9d\x9e\x32\x61\x4a\x70\xc7\xe0\xd1\x5c\xf8\x9d\x10\x0e\xba\xad\x3f\xe8\x1f\x9c\x27\x4f\x5c\x5c\x0f\xee\x55\xfa\xd3\x10\xde\x5d\x85\x06\xde\xab\x19\xb2\x9c\x81\x25\x56\x31\xf8\xfb\xb8\xd0\xfd\x13\x6f\xba\x02\xdb\xd0\x18\x02\x1b\xbc\x5a\x52\xb0\xb1\x69\x3f\xa2\xae\x08\x1f\x9f\x99\xce\xf1\x03\x54\xec\x12\xe5\x61\xdc\xdb\xb0\x40\x84\xb2\xf3\xc6\x8e\x67\x8b\xd8\xde\x65\xdc\x8f\x62\xaa\xd5\xc8\xae\xd5\x8d\xa9\x9d\xcf\x35\x29\x69\x4f\x70\xd7\x5a\x75\x5a\xdf\xe6\xad\x66\xda\x47\x12\x6d\x51\xed\x12\x07\x39\x47\xca\x84\xf2\x53\x5e\x0f\x0a\x5b\x0d\x83\xc2\xcf\x34\xbd\xbb\x7a\x03\xa2\xa8\xb7\x36\x54\x04\xef\xb7\xeb\x71\x51\x14\xce\xd6\x76\x2a\xc7\x5a\xaa\x01\x78\xcd\xc8\xb1\x9f\x9e\x3a\x0c\x25\x36\x48\xaa\x26\x09\x85\xc6\x3b\x27\x86\x85\xbf\x94\x34\x56\x86\x3d\x59\x64\x31\x8b\x96\x3e\x65\xce\x52\x45\x07\x79\x47\xa3\xc2\x39\x13\xff\xc6\xc2\xcf\xf9\x55\x27\xe3\x32\x28\xd8\x3b\x0a\xd7\xb2\x53\x27\x42\xd3\x60\x54\xf4\x24\x9c\x1b\xc9\x1c\xe1\x97\x16\x82\x96\xab\xef\x7a\x68\xd4\x6b\x79\x0a\x3a\xac\xd8\x42\x54\xec\x13\x2c\xf7\x46\xa2\xe6\xe6\x10\x50\xc4\xd5\x09\xa0\x41\x9c\x9d\xac\xd7\x1f\xb8\xa2\x93\xa5\x43\xf0\xe3\xa0\x3f\x3e\x76\x85\xe0\xd6\x83\x64\x5f\x04\xda\x93\x78\x49\xb8\x73\x38\xed\xe6\xf3\x64\x61\x49\x01\x1a\x6d\x4d\x83\x51\x01\x77\x1b\x8e\x02\x77\x1a\x8c\x8a\x45\x81\x4b\xf9\xdb\xb0\xac\xf0\xd8\xc8\x81\x5e\x06\xc8\xa0\x3a\x15\x21\x4f\xba\x9b\x12\x0c\x41\x6e\xe7\xb0\x1d\xb8\xa8\x5a\xb6\x6c\x61\x97\x21\xa6\xcb\xf1\xd1\x15\xd8\x62\x66\xd9\x8f\x03\xb0\xfc\xe5\x32\x8e\xe4\xcb\xee\xbd\x2f\x29\x49\x38\x2f\x4e\x13\x18\x8b\x88\xe5\x36\xbc\x0c\xdc\x8b\x00\xde\x06\xee\x55\x00\x7b\x41\xc3\xe9\x7a\xd5\x25\xde\xdb\x00\x69\x34\xb0\x5e\xbf\x3a\x3a\xb6\x0a\x5c\xa8\x06\x59\x17\xd4\x53\x62\x05\xd5\x58\xf1\x38\x40\xd8\x2e\x30\xe3\xac\x85\x19\x77\x26\x79\x8f\xc7\xf0\x6a\xbf\x4f\xf7\x56\x77\xfb\x32\xa8\xf4\x4b\xd7\xe8\xb7\x0a\x39\x45\xcb\x4b\x6a\x32\x0d\x46\x72\x0f\x8b\xc3\x1a\xce\x78\x85\xc3\x2e\xd4\x1c\x44\x28\xa0\xc0\x60\x2f\x50\xf7\xe1\x9d\xa0\xd7\x8d\xbe\x1c\xb5\x3a\xc1\x68\x31\x31\xbd\xab\xf2\x4e\xa0\x98\x0f\xcb\x12\x6f\xd7\xd8\x39\xaf\xc5\x53\x4d\xad\x96\xe9\x82\xb2\xb6\x0a\xd0\x58\x2a\xc8\xcf\xa3\x94\x11\x7a\x35\x3a\x21\x88\xd9\xb0\x86\x9a\x0e\x5d\xb7\x03\xdd\xf2\x32\x4b\xe7\x9c\x15\xc1\xe8\x3a\x07\xcb\x82\x66\x37\x01\xb2\xeb\x3d\xe0\xdb\xf6\xa0\x54\xfc\x6f\xd5\x49\xb2\x6e\x27\xc5\xb3\x71\x53\xdd\x62\x3d\x70\x91\x75\xfb\xe1\x97\x98\x86\x62\x87\xcb\xca\xbb\x61\xe7\x30\xee\x4c\xd6\xd2\xae\x0a\x94\xbf\xf4\x52\x23\xa2\x68\x49\xbf\xb3\xcd\x29\x9e\x39\x6c\xc4\xff\xc0\x9c\xa4\x8c\x7f\x93\x94\x89\xef\xc4\x5f\x60\xf5\x9b\x7f\xc2\x92\x12\x46\x02\xc2\x39\x2f\xfd\x09\x84\x46\x27\x51\xe2\xb0\x91\xfc\x80\x25\xa1\xcc\xe3\x05\x08\x65\xb0\xf4\xd9\x5c\x35\xa2\x3f\x21\xc5\x3e\x0d\xe6\xc2\xc9\x11\xff\x80\xb9\x9f\xf2\x5f\xfc\x0f\x64\x29\xa6\xaa\xbc\xfe\x84\xa5\x9f\xa6\x17\x84\x86\xa2\x0d\xf9\x59\xf3\x12\xab\x01\x3d\x9c\xdc\x71\xb5\xc6\x50\xe2\x9f\x47\x27\x3e\x23\x54\x34\xb3\x7d\xc2\x27\x5e\xb0\x6b\xc7\x54\x44\xcf\xb2\x8a\x18\x27\x27\x84\xef\x6f\xcc\x0e\x14\x68\x1c\x02\x12\xcc\xaf\x39\x73\x9a\x40\x81\xcb\x0e\x85\x2a\xd6\x39\x18\x4e\x2a\xb5\x02\x88\xd2\xfd\x84\x61\x9a\x60\xb6\x77\xb9\x8c\x09\xc5\x74\x32\xe1\x27\x2a\x67\x58\xcf\x02\x77\x27\xa8\x21\x2d\x3c\x11\x49\x45\xeb\x70\x20\x7e\x9f\x10\xd8\x57\x65\xf5\x18\xe0\x95\x48\xa8\x0c\x11\x9e\x07\xee\xf3\x40\xb8\x38\x7b\x1e\xfc\x6e\xdd\xfd\xbb\xf5\x67\x37\xb5\xfb\x6a\x3c\x77\x68\x2e\x22\x5c\x89\x1b\xc2\xeb\xc0\x6d\x9f\x28\x92\x8f\x33\x1e\x85\xfb\x4c\x85\x86\x10\x01\x90\x4b\x3a\xac\xc7\x02\x1f\x99\x08\x35\x21\xfc\xa1\xc0\x27\x86\x9a\x31\x2d\x64\x38\x8b\xee\x5e\x71\xe1\xb1\xae\x7a\xc7\x7b\x9e\x2d\x96\xc5\x25\xeb\x20\x90\x57\x16\x79\x0f\x7b\x89\x4b\xd3\x3c\x31\xe3\x08\xbd\x0e\xf8\x20\x6d\x78\xa2\x0a\x6a\xdd\x12\x12\x46\xb3\xab\xae\xc2\x67\xf5\xc2\xef\xa3\x34\x2a\x0d\xf3\x5e\xe9\x2e\xb5\x85\x94\x4a\xdf\x57\xe9\x9c\x3c\xbf\xab\xf3\x14\xf5\xa3\xaa\xa2\x65\x23\x2f\xaf\x5b\xa7\x2a\xc2\x82\x53\x01\x9e\x4e\x53\x1f\x13\xdb\xce\xe1\xbd\x09\x56\x6d\xb8\xfb\x72\x22\x58\xdc\x35\xf8\x7c\x3e\x31\xb1\x44\x36\x7c\x08\xdc\x97\x6c\x14\x63\x7f\x86\xac\x97\x72\x7b\xc8\xb7\x89\x67\x5d\x19\x5f\x3a\x79\x3b\xde\xb8\xc3\x60\x49\x96\x1f\x84\x69\x14\x95\x27\xd3\xd7\xc0\xfd\xc4\xd7\xfd\x4b\x00\xd5\x53\xff\xcc\xb6\xe1\xa9\x89\xd3\x2a\x98\xca\xf2\x6c\xcc\x73\x78\x13\xb8\xe8\x59\x80\x9e\x06\x9c\xc8\xf1\xe1\x89\xcf\xb1\xdd\xc3\x96\xca\x55\x2a\x98\xd2\x4f\x3d\x9d\xa9\xd5\xd7\x9d\xbd\xe8\x29\xca\x51\x4a\x97\xfb\x6c\xe4\x14\x9f\x05\xe8\x45\x20\x25\x94\x1f\x7b\x1a\x12\x68\xab\x5b\xfa\xa1\x0d\x55\x1d\xe0\x44\xab\x4d\x75\xa2\xfc\xc7\x40\x06\x26\x6a\xa3\xfc\x8b\x5a\x4e\x03\xc5\x3f\xd5\x32\xeb\x28\xfd\x46\xe7\x35\x50\xfa\xa9\x4a\x17\x7c\x4a\xd6\x07\xcf\x24\x62\x84\x16\xd3\xa3\x59\x67\xbc\x25\xa1\x02\x8d\x38\x85\x2b\xe9\x98\x81\x30\x40\x85\xe6\x94\x38\x7e\x56\xd0\x10\x25\x9f\xff\x10\x20\x96\x71\xd8\xb7\x45\xf7\xb4\xae\x50\xcd\xd9\xda\xa6\x14\xbf\x24\x5a\x19\x41\x35\x53\x2d\x2a\x95\xae\x95\x71\x16\xd5\x86\x10\x75\x6b\xac\xc4\xc8\x0a\xcb\x79\xfe\x33\x07\x1f\xe8\xc1\x1b\xef\x15\x12\xe2\xc0\x60\x25\xcc\xf3\x5b\xcc\x1d\xf3\xb9\xdb\x80\xb3\x15\xf1\xb9\x06\x2c\x33\xdd\xa3\x64\x6c\x2d\xc9\x79\xe7\x36\x24\xed\x66\x6a\xf8\xd5\x3c\x50\x1b\xcc\x30\xe9\x41\x4d\xad\xd5\xa9\x30\x33\xc8\x0c\x84\xd9\x78\xba\x1d\xac\x07\x33\x3d\xcf\x9d\x60\x64\x3a\xf8\xdb\x55\xb6\x7c\xf4\x99\x41\x92\xc1\x51\x82\x7c\xf4\x21\x01\x6b\x49\x96\xfc\x5e\x81\x2d\xc0\xf2\xa8\x2c\x72\x38\x3b\xa4\x9f\x71\x64\x1e\x3f\x22\x5e\x30\x20\x3d\xd5\xed\x1c\xb2\xcc\x35\x5d\x65\xa4\xe8\x2a\x19\x95\x24\x1b\x6a\x4f\x1d\x12\x1a\xa6\x90\x6a\x1c\xd4\x24\x7f\xc4\x9c\x90\x08\xcd\xc4\xdf\xff\x94\xa7\x97\xd2\x77\x95\xea\x8a\xa5\x44\xd7\x9b\xd4\x6c\xd8\x2a\x47\xd3\xbb\x40\x1c\x66\xe2\x60\xd3\xc7\x04\xe6\x87\x83\x72\x0f\x3b\x60\xc2\xd1\x89\x16\xa0\x9b\x5b\x7b\xd1\x71\x85\x16\x6d\x1d\x48\x52\x1c\x88\x9d\x55\x34\x7a\x31\x8f\x62\xcc\xcf\x12\xbd\x5e\x65\xe7\xc4\xb6\x73\x64\x77\xb3\x2f\x11\xda\x15\xa7\xa9\x2d\xd6\x26\xe0\xdc\xd2\x4b\x36\xc2\xb3\x19\x0e\xd8\xa1\x9f\xf8\x27\x98\xa6\xa3\xf2\xcc\x74\xaf\x97\xa7\x27\x8e\x55\xd8\xfe\x24\xe5\x69\x0a\x62\x97\x7e\x0d\x80\x24\x7b\xa2\x7a\xea\x64\x19\x90\xe4\x08\xc7\xb3\xc3\xf4\xc4\x79\x1f\x88\x40\x02\xd6\xec\xd2\x82\x60\x11\x1e\xfa\x4b\xe7\x87\x80\x6f\x3c\xfe\x85\xb3\x5c\xfa\x6c\xc9\x8c\xaf\x53\x52\x0d\xb6\xee\xcf\xa7\x12\xfa\x58\xbb\x1f\x1b\xd2\xbf\x65\xa5\x69\xe1\x70\x22\xfd\xc6\x94\x6e\x58\xc6\x8f\xbc\xbf\x65\x8f\x3c\x6d\xd4\x1b\xb9\xec\x77\x4f\x78\xb9\x89\xee\xb8\x6e\xf0\x3b\xdd\xf0\xfe\x6c\x57\x8f\x66\xe8\xe7\x9f\x37\x7f\x7b\x78\xc7\x45\x0f\xef\x3f\xf8\xf5\xd7\xbb\xc1\x28\x98\xfb\x74\x87\x84\x78\x5b\x84\x3a\xb4\xad\x3f\x84\xea\x6c\xb4\x45\x36\x36\x1c\xe1\x94\x84\xb8\x13\xbb\x70\x17\xe5\x6d\x6c\x00\xef\xa8\xa7\x0f\xb2\xb1\x51\x3a\x7b\x45\x74\x23\x13\xc9\xb5\x9b\x63\xcd\xbf\x69\x15\x89\xef\x57\xe8\x05\x78\x9b\xb5\x78\x09\x41\x25\xa2\x23\xfd\x7b\x21\xec\xb5\xf5\x75\xa2\x98\x9c\xab\x27\x87\x9b\x93\x2b\x68\x9a\x87\xb0\x12\xef\x22\x0a\x9b\xb6\x6d\x6f\xd1\x8d\x4d\x67\x38\x51\xf2\x77\xfc\x3b\x2d\x3c\x16\xf1\xc2\x89\x6d\x6f\x71\xc0\x08\xff\xb3\xc3\x4d\x87\x6e\x4c\x9c\xe1\xa4\x19\xfb\xa2\x10\xef\xc9\x05\xca\x8a\x2b\x0c\x55\x66\xa3\xc3\x89\xeb\xba\x5e\x0d\x62\x1c\x09\x2a\xbe\xe1\xd8\x96\xe7\x78\x1b\x85\x93\x8c\xe4\x6f\xd1\x23\xbd\x22\xd9\xef\xc9\x9f\x5b\xf5\xc5\xcb\xaa\xf3\xe3\x63\x14\xeb\x15\x6c\x6c\xd8\x7c\xe5\xdc\xcd\xe2\x73\x03\x08\xcf\x70\xcb\x4d\x85\x91\xf2\x9b\x24\xc7\xba\x18\x05\xf3\x22\xc0\x62\x94\x1e\x65\x53\x15\x82\x3a\x11\x56\x26\x3c\x61\x67\xee\x53\x47\xd8\xb4\xcd\xa2\x24\x2c\x4b\x10\x11\x07\x0d\xd9\x10\x65\x2e\xf2\xb2\x51\x2d\x17\xbc\x6c\x54\xd4\xb6\xc1\xcf\x5c\x9d\xa0\xf2\x53\xd3\x81\x30\x58\x8c\xf0\x19\x62\x20\x46\x85\xac\x0d\xcb\xb6\x6f\x6e\xea\x69\x43\x8b\x93\x8e\xd9\x1a\xb5\xc7\xa2\x64\xbc\x46\x49\x6c\xe8\x67\x4f\xd4\x0e\xd7\xa8\x3d\x12\x25\x97\xc6\x92\x47\x0c\x31\xfb\xe6\xe6\x42\xfe\x39\x95\x7f\x4c\xd5\xe7\x99\xe1\xda\x20\xac\x53\x8b\x20\x15\x3e\x8a\x32\x90\x39\xc2\x15\xe6\x28\x58\x2c\x51\x02\x63\xfb\x6f\xe3\xf2\x95\x84\xb9\x0c\xa8\x9b\x00\x76\x31\x3f\x76\xcf\x4d\xcd\xea\xe6\xe6\x45\x73\xd5\x79\xf1\x03\x6a\xeb\x35\x47\x2b\x47\xfc\x16\xdd\x2e\xf9\x5e\xc6\x36\x0c\x27\xf6\xd6\xae\xc8\x13\x25\x72\x1b\x16\x5d\xec\x85\xa8\x17\x8b\x2e\xd4\x78\xf1\x19\xc2\xbc\x05\xbb\x22\x7d\xd5\x0f\x5f\xa2\x74\x9a\x49\x2b\x5a\xe2\xaa\x91\xf0\xee\xb0\x93\xd4\xc6\x27\x4a\xce\x32\x69\xa2\xc7\x0b\x94\xa9\x47\xac\x4c\x7d\xcd\x10\xb1\x1d\x1f\x9d\x17\xc9\x8e\x48\xca\x6d\x38\xe9\x1d\x72\xa8\x86\x5c\xed\x53\x0c\x7b\x2b\x42\x0b\x99\xe7\x88\x2f\x01\xc0\x23\x65\xf8\x2b\x34\x69\xa7\x99\x8b\x88\x51\xf6\x5f\xde\xc8\x84\x7a\x9e\xc3\x40\x46\xb2\x52\x71\x3e\x13\xce\xd5\x06\x24\x51\x4a\xd4\x94\x5c\x38\x04\x02\x12\x3b\x41\xaf\x94\xff\xb5\x4f\x53\x4c\xcb\xfb\xd4\xd5\x0a\x1e\xed\x71\x4b\xb2\x79\xbc\xa2\xc6\x53\x42\x9a\x55\x2e\x56\xf1\x93\x7a\x8e\x58\x87\x96\x56\x53\xc5\x2a\x7a\x57\x31\xe3\x91\xfc\x28\x26\xce\xc4\xc4\xf1\x88\x92\x0b\x31\x79\x3c\x0a\x48\xcc\xbb\x3c\x5d\xc9\xc2\x4e\xb3\x96\x01\x65\xe2\x52\x20\x22\x9a\x10\x52\xb6\xfb\x7c\xfa\xa5\xaf\xf5\x82\x99\xb8\xca\x44\xe8\x51\xfe\xcf\xc4\x2e\xdc\xc0\x78\x13\xc8\x5c\x1f\x1d\x51\x48\xf4\xb8\x03\xfd\x91\xa8\x99\x55\x38\x92\xe3\x0c\xa4\x57\x0a\x22\x83\x4a\x4a\xa6\xf9\xc8\x48\x14\x22\x74\x9a\xc1\x95\x50\xc7\xba\x34\xed\xcf\x62\x73\x53\x18\xdb\x7f\x1f\x4e\xca\xa1\x9e\x64\x72\xbf\x56\x76\xf0\x11\x93\x8c\x0f\x71\x45\xb6\xd8\xa5\x81\x4b\xc4\x84\xf7\x28\x6d\x7b\x2b\x20\xca\x4f\x81\xf0\x0e\x50\x45\xf2\x0c\x98\xd8\x36\x99\xed\x90\xdc\x86\xc7\x6b\x90\xbe\x4b\x41\xbb\xb6\xd7\x26\xc6\x2f\x4d\xd3\xad\x96\xa7\x62\xa3\xe9\x5d\xcb\x27\x56\x21\x42\x8f\xe5\xec\x1b\x9b\x7e\x59\x49\xdd\xe5\xa7\x3d\xdf\xe7\x54\x6d\xfd\x4b\x06\x6c\x63\x53\x44\x17\x82\xb7\x5d\xb8\x5e\xc3\x9e\x5a\x10\x51\xbd\xd0\x9c\x07\x47\x3e\xef\x28\x29\x71\x80\xa3\x69\x32\x12\xa2\x55\x1b\x24\x3c\x85\x13\x59\x6f\x02\x3e\xff\xb3\xd9\x80\xae\x24\x21\x57\x19\x08\x6b\xb6\x84\x53\x91\xe3\xac\x1d\x44\x56\x6f\x1f\xa2\xf7\x4d\xa6\x37\x4c\xd2\xdc\x30\x32\x16\x31\xbe\x94\x1b\xc7\x13\x9b\xc6\xcf\x25\xea\xed\x75\x53\x7e\xb1\x2f\x7a\x76\x0e\x76\x13\x79\xf3\xab\xee\x1a\xdc\xde\x35\xe2\x1d\x97\xea\x2d\x83\xe5\x96\xe1\xf8\x8f\x02\x59\x55\x50\x0f\xe1\x39\xb2\x5e\x57\x6d\x16\x51\x3f\x13\xfb\x25\x2b\xf6\x1e\x67\x9f\xbc\x31\xf8\xfc\xcf\xa4\x06\xc1\x40\x40\xdc\xe7\xff\xda\x77\xef\xaa\x24\x0e\x7e\x9f\xff\xab\x60\xeb\x49\xf2\x2c\xbe\x7c\x09\x89\xc3\xba\xa4\xa3\x8a\x73\x3e\xda\xcb\xba\x1e\xca\x68\x6e\xab\xb8\x54\xa6\x9b\xcc\xd4\x74\x67\x46\x63\x30\x48\x50\xf9\x04\x65\x7c\x2c\x1b\x76\xbe\x8d\x92\xa9\x9b\xb8\x16\x4e\xaa\x25\x51\xaa\x21\x62\xb6\x42\xb3\x23\xe1\x50\x74\xc4\x28\x84\x98\x53\xf4\x2c\x12\x45\xe7\x67\x9d\x1b\x40\xc6\xef\x82\x27\xff\x24\x9c\xc1\x75\x4a\x3b\x96\x51\xc0\x1b\xb3\x0b\x2a\xb3\x13\x7b\x2b\x10\xb3\xab\x63\x4f\x20\xa9\x6d\x31\xc5\x83\xcc\x3d\xc8\x84\xb4\xfd\x20\xfb\xdd\xba\x71\xbb\xa5\xed\x3e\x7a\x92\xc1\x99\x3c\xcf\x73\x1b\x50\x51\xd3\xfe\xdd\xba\x19\xad\xa8\x77\xa5\xaa\x89\x39\xec\xff\x25\x6b\xaa\xf7\x4a\xb1\xa8\xc7\x99\x5e\x46\xb5\xae\x8d\x75\x16\xf3\x7d\x65\x24\xbd\x46\xe4\x94\xfb\x4e\x8e\x3b\x87\xe7\x5d\x83\xd6\xe4\x87\x6a\xf2\x33\xd6\xe4\x67\x52\xd0\x9d\xaa\xd0\x98\x53\x9e\x89\xa0\x3c\x93\x1c\x64\x24\xb5\x8a\x0e\x53\x63\x56\xbb\x6a\x46\x9c\x44\x5f\xf3\x9a\x7c\x26\xc5\x79\x2f\x7e\xf0\x0d\x5d\x0c\x41\xfb\xb3\x11\xb3\x2e\xa9\x9e\x28\x26\x7e\x08\x20\xbc\xce\x5c\x94\x18\xd8\xae\x52\x43\x86\x5c\x38\x4c\x74\x41\x75\xdb\xb8\x6c\xbb\x68\x98\xe4\xcd\x88\xe6\xd5\xdb\x6a\xb5\x91\x10\x17\x72\x36\x7e\x53\xb5\x6d\xd8\xed\x16\xa7\xae\xe4\x51\x4a\x32\x1e\xb8\x11\xba\xc8\x1a\xaa\xcf\x3e\x7a\x9d\xd5\x8e\x1b\x66\x4b\x59\x0f\x08\x07\x2c\x58\x11\xdc\x06\xc4\xb3\x0a\x1e\x09\x8a\x2a\x5a\x26\x92\xd2\xda\xc2\x97\x6e\x0f\x67\xf9\xc4\x8f\xe2\x92\xaf\x7c\x77\x2b\x2c\xbb\xca\x60\x37\x13\xef\xaf\x02\xd3\xde\x67\x85\x02\x89\xd0\x23\x88\x92\x93\xf7\x3e\x8d\x84\xd5\x49\x0e\x1f\x7a\xe4\x82\x45\xf9\x17\xf8\xea\x82\xd0\xf2\xe5\xe1\x59\x07\x5b\xf5\x36\x83\x0f\x99\xb4\x39\x58\xa7\xd9\xa3\xab\xc5\x94\x94\x72\xc7\xaf\xdd\xad\x7e\x91\xad\x3e\x6d\x4f\x65\x2f\x09\xad\x1c\xde\x64\x6e\x15\x1a\x0d\x26\x68\x9b\x22\xa6\x39\x46\x60\x8a\x81\xb0\xb7\xcc\xc7\x3f\x53\x1b\xfd\xa9\xe8\xd2\x86\x4f\x45\x9f\x8f\xfd\xf0\x2d\x5e\x62\x9f\x59\x39\xbc\x30\x4b\x0f\xf5\x85\xb1\xe0\x20\x19\xbf\x1e\x4e\x6a\x27\x2f\x65\x08\x73\xf6\x43\x45\x2b\xa3\x9c\x3b\xbe\x2e\x4e\xeb\x3b\xeb\xf3\xc7\xc5\xa5\x4e\xe2\x66\x50\x3d\x98\x25\xa2\x8a\xe3\xd9\xae\xb5\xf4\x29\x83\xc0\xe6\xb7\xd4\xe1\x04\xa8\x2b\x82\x32\xd6\x90\x9d\x14\x1a\x8a\x90\xb8\x41\xce\xb1\xef\x73\xff\x5c\x57\x4c\xe3\xba\x32\xe0\xda\x35\xb7\x7f\xd0\x3c\xa9\x04\xe0\x56\x0d\x72\x4e\x09\x13\x25\x47\xc9\x4c\x00\xc9\xda\x6d\x67\x46\x80\x64\x6b\x03\x24\x13\x00\xf9\xd8\x79\xe0\x88\xc3\xa1\xd4\xb7\x99\x66\xc8\xda\xbb\xf4\x03\x16\x5f\x55\x88\xb0\x01\x4d\x53\xf4\x42\x1d\x2d\xb8\xf6\x22\xc8\xec\xdc\xf4\x62\x91\xa2\xcf\x5d\xc5\x85\xd9\x4a\xe6\x66\x1d\x1a\x70\xe0\xad\x87\xa4\x9d\x5c\x71\x71\x9b\x4c\xf4\xb1\x44\x0a\xfa\x1d\x88\xc3\x28\x13\x34\xda\xcb\x75\xa4\x20\x71\x49\xa0\xe2\x62\x54\x2c\x50\x5a\x15\x43\xe8\x65\xf8\x96\x2e\x2a\x0d\x6e\xda\xf6\x75\x75\x19\x31\x24\x6e\xb2\x31\x01\xe2\x12\x08\xdc\x00\x32\x37\xdb\x98\x80\xe7\x4e\xa4\x4b\xe8\x66\xd1\xb4\x5a\x10\x3c\xd7\xdb\x98\x88\x27\x3d\x6f\x2d\x58\xae\x9a\xea\xb5\x74\x5a\x7d\xfb\x29\x96\x7b\xa6\xb9\x1b\x5a\x4b\x34\x53\x1b\xe3\x53\x06\x33\xe1\x0b\xfd\x1f\x0b\x19\xea\x75\xec\x82\x2e\xf4\xc7\x6d\xf4\x57\x7e\x4f\x75\x85\x25\xfa\x41\xdf\x6a\x8a\x3b\x7e\xf5\xc6\xa7\xae\x5f\xe5\x79\x5d\x39\x95\x1b\x3b\xa5\xd5\x32\xf3\xbe\xbd\x65\xbe\xa9\x70\x7b\xba\x5a\xc6\x98\xa1\x08\x51\x4f\xb0\x76\xe2\xa5\xce\xab\x9c\x18\x4f\x62\x22\x0e\x0c\xe2\x35\x4f\x28\xa5\xf0\x00\x9c\x6c\xe8\x01\xb9\x54\x74\x4b\x5c\x5a\xc8\x3c\xc4\x73\xb0\x18\x5c\xe6\xd2\x62\x78\x9e\xf8\x8e\x81\xe3\xdc\x25\x67\x2b\x04\xea\x6d\xf3\x2f\x6c\x2b\xf4\xd3\xe2\x87\xb4\x42\x88\x67\x6e\x5a\x11\x3b\x48\x8e\xd6\x6b\xef\xbc\x99\x46\xcb\xa0\x40\xcb\x4c\xa0\x65\x22\xd1\x72\x03\xcd\x86\xc4\x56\xf1\xd9\x63\xd1\x26\x84\xee\x8c\x22\x21\xb0\x21\x10\x43\xe9\x29\x58\x0f\x23\x94\xcb\xbf\x18\x05\xd4\x4f\xe7\x3b\x7e\x8a\x51\x21\x40\xbb\x16\xae\x16\x9c\xeb\x38\x4a\xb0\xf3\xcb\xfd\xfb\xbc\x97\x6c\x91\x38\xbf\xe5\x80\x93\x50\xa7\x3f\xf8\x59\xa7\x4f\x1e\xe6\x39\x84\xb6\x72\xc9\x29\x5b\x19\xcd\x38\xa8\xff\x9f\xc1\x52\xfc\x1a\xa4\x18\x2f\x84\xd7\xb9\xb9\x7f\x8e\x07\xfe\x60\x9a\x9d\xb4\x1c\xd3\xf9\xc9\xe0\xe8\x68\x67\x67\xaf\xcf\x39\x1d\x23\x24\x4e\xef\xc9\x46\x2b\x8e\xe9\xe4\x3d\x28\xe4\x13\x6f\x41\x2f\x5e\x09\xbd\x58\x42\xcf\x86\xa0\x8a\x2b\xfb\x09\xc7\x94\xcc\x73\xd1\x3f\x0a\x55\x5e\x7e\x1f\xaa\x04\x7f\x19\xaa\xc4\x7f\x0d\xaa\x3c\xbc\xff\xab\x11\x55\x1e\xfe\x3c\xee\x45\x95\x28\xf9\x57\x43\x94\x4e\x6e\xfa\xb1\x1f\xbe\x4a\xf0\xab\x59\x79\x5b\xf0\xbc\x95\x4f\x19\x32\x4e\x84\x7c\xa1\x4e\xda\xec\x66\xe6\x21\x2a\xde\xed\x80\x69\x36\x95\x73\x1b\xfc\xa2\xc3\xea\x92\x25\xd2\x10\x6d\x0a\xbf\x6a\x52\xf2\x28\xd1\x53\xdd\x2f\xed\x9b\x1b\x9d\x2c\x04\x76\xea\xa6\x69\x97\x35\xe5\xc3\x89\x99\xf7\xa2\x39\x08\xf9\xc6\x44\xb0\x5f\x91\xb7\xfe\x6d\xc8\x47\x9e\x07\xb4\xcd\x24\x81\x6f\x6a\xa4\xb8\x5c\xc8\x33\x4b\x5f\x4c\xd2\x9e\xb2\xdb\xec\x00\xfb\xa5\xa2\x3f\xcc\x3c\x37\xf5\xd0\xd8\x86\x58\x7c\x4c\x6c\x08\x4d\xb5\xef\x8c\x73\x58\x7a\xae\x3c\x38\x66\x9e\x49\xc2\x55\x97\xdf\x0e\x0c\x4f\x64\x7f\x24\xa6\x44\x6a\xd9\x3d\xea\xe7\x94\x5f\x96\xe7\x9d\x67\x99\x90\xae\x2c\x3d\x2d\x95\x39\xf7\xdc\x73\x4f\x88\x73\xce\xbd\xdf\xad\x9b\xa1\xf5\xa7\x3b\xf7\x64\x78\x38\xcf\xed\xbb\xf2\x0f\x22\xaf\xa1\xc9\x13\xa1\x9d\x8a\x01\x4f\xc5\x81\x21\x5a\x78\xa0\xeb\xd7\xab\x04\xf2\x9a\x6d\xe7\x10\x21\x21\x4e\x1a\x59\x7f\x76\x7c\x8a\x37\xa0\xaf\x19\x4a\x6c\xa9\x82\xd0\xd2\x16\x8a\x90\x9e\x01\x2f\xc6\x6c\x78\x95\x71\x1c\x27\xb6\x6d\x52\x1b\xb2\xe1\xa4\x6b\x7e\xf2\x3a\x63\x9c\xc8\xc9\xca\x89\x94\xd4\x74\xce\xd1\xd2\x00\xa4\x62\x94\xf5\x01\x27\x7c\x5a\x20\x60\x18\x70\x82\xf9\x9d\x13\x14\x8f\x65\xdf\x30\xc3\xe9\xea\xa5\xca\xdc\xfa\x4a\x97\x08\x5d\x0c\x28\x97\x23\xb4\xbf\x17\x1a\x46\x14\xe3\xe0\x69\x43\x27\x33\xc0\x60\xbd\x52\xb9\x0d\x57\xdf\x8d\xeb\x4a\x61\x91\x54\x15\x16\x9f\x10\x3a\x95\x4e\xe5\x9c\x35\x31\xa8\x3a\x32\xa5\xa3\xf8\x4a\xc8\xc0\x4a\x9f\x71\x2b\xd7\xa8\xde\x46\x43\x97\xd1\x0c\xf0\xca\x27\x2d\xf7\x18\xac\xda\xb8\xb5\x9e\xec\x3c\x37\xae\x8b\x09\x6b\x2b\x15\x3b\x36\xe7\xb1\x67\x94\x48\xa8\x59\x1c\x56\x4e\x82\xca\x22\x71\x24\xd3\xe4\x96\x19\xb1\x67\xee\xf1\x41\x60\x1b\xd4\xeb\xf7\xc4\xde\x2a\x87\x53\xbe\x27\x38\x29\x3a\x2e\x66\xce\x2f\x77\xa6\x69\xc9\xb6\xa8\x0d\xd5\xc2\x1b\xdd\x85\xc5\xc8\x7c\x75\x60\xd4\x6b\x19\x80\x90\x2b\xa5\xc0\x0b\xaf\x4b\xea\x69\xd0\x50\x7b\x2b\x1c\x97\x7a\x13\xfe\x41\xed\xfc\x51\x43\x89\x0c\x17\x9a\x6a\x0a\x62\xef\x32\x54\xf1\xa5\x2e\x18\x9b\x81\x3f\x10\x26\x5a\x43\xce\x65\x0d\x02\xb2\x10\xbe\x23\x85\x23\x74\x36\xc7\xd2\xad\xf8\x80\x91\x53\x9c\x0c\x02\x3f\x49\x08\x1b\x4c\xa5\xeb\x75\xbc\x58\xb2\xab\x81\x34\xea\xbc\x23\x8d\x40\x1b\x7d\x4f\xbe\xb3\x6f\x9c\x84\x6b\xf5\xdc\x50\xd6\x2f\x4f\x64\x75\x8c\x62\xc9\xe8\x8c\xbc\xb1\x7d\xf7\x6e\x25\x71\xa2\x12\x2b\x34\xbc\x38\x7d\x24\xea\x8a\x35\x13\xa6\x6f\x30\xb1\x3b\x2c\xb1\x24\x0b\xbf\xf4\x03\x9c\x3e\xea\xdd\x74\x1c\x79\x46\x02\x9e\x9c\x47\x87\x19\xba\xf2\x80\x8e\x70\x12\x0a\x5b\xf3\x88\xe1\x05\xd0\x51\x8a\x97\x3e\xf5\x19\xa1\x40\x47\x8c\xfa\x51\x1c\x25\x27\xa2\xe7\x53\xcf\xed\xb6\x81\xac\xb2\x82\x5e\xa9\xd5\x42\x4a\x99\x85\x57\x11\xcf\xb4\x9e\x43\x69\x17\xd3\x8a\xe5\x23\x42\x5e\x6d\x46\x89\x1e\x80\xba\x74\x63\x02\xd8\xc5\x1b\x13\x48\xdc\x9a\xe8\xa1\x10\x3a\x00\x75\x3d\xb3\x74\x82\x73\x7d\x47\x26\xae\xd6\xc0\xfb\x95\x3a\x9c\x10\xb8\x44\x3c\x88\xaa\x2b\x93\xe7\x12\xc1\x93\xa6\x2e\xd1\x57\xa6\x99\xb2\x4e\x4e\x18\xc4\x9c\x97\x55\x57\xa6\xa5\x86\x4a\x0a\x59\x09\x95\x65\x4b\x68\xf5\x5e\x08\x53\xa5\x8f\x63\x5d\x64\xd3\xde\x0a\xd1\x29\x3f\xcf\xd2\x8d\x09\x78\x1b\x13\x98\x40\x06\x22\x5e\xb3\x4a\x5f\x82\x07\xbc\xaf\x78\x43\xe7\xc0\xb9\xd4\x74\x48\x61\xae\x47\x96\x55\x4e\xc7\xfd\x04\xce\x01\xab\x07\x56\xd1\xa7\xbc\x54\x9c\xc3\x5c\x92\x81\xcb\xe2\x16\x59\x1e\x2a\x39\x3c\x36\x10\x07\xd5\xe6\x85\x87\xd4\x3d\xca\xfa\xdd\x82\x02\x8d\x1c\x0b\x2c\x71\x8b\xb2\xfe\xb4\x40\x62\xa9\xc3\x80\x23\x9b\x43\x41\x23\x98\x73\xe9\xf5\xd9\x37\x56\x9a\xbe\x36\x36\x9d\xaf\x6c\xda\x86\xed\xb5\x86\x8e\x8c\xed\xdb\xdf\x3a\x74\xed\x06\x38\x49\x70\x2a\x7c\x4a\xec\x48\x1a\x73\x1b\x63\xc4\x97\xbd\x55\xdb\x8f\xb6\x11\x7a\x4c\xc1\x72\xad\x52\xe1\x89\x9f\x0a\x85\xb0\xec\xee\xdd\xe2\xa7\x22\x90\x77\xef\xaa\x6b\x9b\x24\x49\x32\x71\xcb\x47\xaf\xfa\xc7\x55\x3d\x07\xca\xf1\x9c\x2a\xdb\x05\xf5\x21\x54\x8e\x6d\xe7\x2c\xb7\xe1\xa5\xf1\x8e\x75\x81\x51\x84\x18\x83\x6d\x7e\x5e\xf1\x81\xdf\xb5\x20\x42\x17\x14\x26\xda\x4f\xd1\x5b\xcf\xa0\x3b\x2e\xcb\xde\xb3\x80\x35\x26\xa9\x1d\x7f\x58\x5a\x53\x7a\x8b\x8e\xe4\x75\x6f\xaf\xde\x4e\x95\x64\x51\x97\x3d\xaa\xea\x57\x57\x8f\x8d\xb3\x47\x35\x41\x3c\x1e\x65\xc9\x79\x94\x46\x0c\x87\x9d\x17\xde\x03\x84\x47\xc2\x83\x91\x3c\x94\x64\x01\x6f\x5c\xc0\x39\x69\x1e\x4d\x95\x0a\x4c\x68\x5e\xe7\x39\x1c\xf6\x10\xa7\x3d\x0f\x89\x47\xd9\x6b\x35\x92\xba\xa1\xaf\x1e\x9f\xf3\xd6\xe3\xdc\x82\xf0\x30\x97\x3a\x3a\x7c\xf3\xb1\x64\x40\x77\x7a\xee\x6b\x87\x9c\x4f\x50\x8b\x40\x85\x71\x20\x5f\x3d\x7e\x78\x08\xab\x41\x51\xff\xac\x7b\x3b\xa9\x06\x68\x69\x76\xd8\xac\xbc\x42\xd9\x4c\x8f\x1f\x8f\xd4\x57\x65\x4e\x15\xf8\x17\x33\x1b\xc9\x0f\x35\x41\x56\x00\x53\x70\xe4\x4f\xfa\x18\xbb\xa2\x2b\x56\xe9\x82\x36\x41\x26\xcc\x8c\x0f\x7a\x6e\xec\x75\xa5\x3d\xd8\x37\x62\xfa\x81\x67\xd0\xb0\xa0\xeb\xa1\x54\x65\x7d\x2b\xc2\x93\xda\xe3\x17\x01\x66\x6f\xd5\xb9\xc0\x14\x3d\xf1\x1a\x6c\x34\x11\xef\x4e\x1a\xae\xb9\x50\x3b\x80\x02\x80\x1a\x70\x4d\xe6\xb0\xce\x78\xe7\xf0\xaa\x13\x79\xaa\x93\x64\x85\xf4\xfe\x7b\x26\x29\xc2\x92\x90\x86\x07\x15\xa5\x48\xf2\xd7\x4c\x57\x86\xfa\x59\x35\x69\x1b\x9e\x7b\x6e\x84\x5e\x79\x60\x1d\x1d\xbf\xdd\x7f\xf9\xd4\x82\x5d\x66\xc3\x6b\x21\x71\xe1\xa9\x2f\xdf\x1d\x3e\xde\x7b\x6b\x41\x4c\x79\xaa\x50\x3b\x79\xf4\xda\xfb\xdd\xfa\xdb\x3d\x93\x81\x68\x09\x99\x42\x99\xa0\x01\xbb\xe2\xac\x26\x4c\x3d\xcc\x49\x61\x99\x38\x9f\x05\x80\x76\xbb\x9e\x4b\x8c\x4d\x96\xfa\x09\x25\x1b\xf0\x19\xce\x3c\x94\xe8\x55\xc7\x35\x9a\x92\x18\x76\x5f\xd2\xde\x7d\x49\x63\xf7\xe9\x7b\xc4\x3b\xcf\x35\x4e\xa8\xbe\x40\xac\x7d\x19\x7b\x84\x5e\x7b\xae\x02\xe0\xef\xd6\xdf\xb6\xfe\x51\xd0\x7b\xdf\xb3\xa1\xdf\x64\x98\x5e\x35\x76\xf5\x87\x4e\xa4\x7f\xef\x75\xea\x1a\x4a\xd8\x3c\x32\x4d\x5d\xa0\x6b\x09\xe4\x2a\x68\x09\xa8\x35\x41\x14\x45\xe8\x1d\x05\x06\xc4\xee\x12\x2b\x3d\x33\x52\x9b\x08\x7d\xe0\x44\xf8\xd8\xce\xe1\x8b\xe7\x9e\x37\x8d\xe0\x0c\x86\x1a\xd6\x73\x3f\xc9\x7c\x7a\x25\xdc\xee\xdd\x9f\x80\xb7\xe9\xdc\x9f\xe4\xed\xbb\xa5\xa9\xea\x13\x3c\xa5\x45\xdd\xcd\x5f\x79\xdd\xcd\xdf\xd6\xac\x7b\xc8\x8f\x85\x6f\xe9\x74\x7b\x49\x85\x46\xcb\xc4\xb9\x3f\x16\x15\xc7\x6b\xf7\xf8\x4d\x93\x7c\x9e\x25\xf8\x5b\xba\x7b\x9e\xc5\xdf\xd4\xdf\x76\x76\x92\xa5\xec\x5b\x6a\x1e\xe1\x25\xc3\x8b\xa9\x40\xde\x5b\x0f\xf7\x55\xc0\x48\x51\xf5\x76\xfd\xbe\x24\xe7\xdf\xdc\xed\x2e\x0e\x2a\x75\x0d\xfd\x2a\x31\x45\xf1\x9f\x0d\x5f\x4d\x9c\xa1\x38\x0c\x85\x6a\xd4\xef\xd6\x8f\xd6\x9f\xc0\xe0\xc1\x98\x53\x77\x6c\xc8\x99\x88\x9c\xa4\xf1\x44\x60\x68\xc1\x24\x63\xc1\x06\xfb\xd1\xf6\x70\x4b\xe3\x3d\xc9\x9f\x26\x8a\x3f\xbd\x33\x2e\xb9\x42\x9d\xa3\xb9\x42\xf1\xe2\x31\xd1\x49\xde\xd8\xae\xd5\x2f\x79\xf4\x3a\x43\x59\xa6\xdb\xfa\x41\xa0\x66\xdc\xd7\xae\x2f\x3b\x1a\x57\x1b\x50\x7d\xdd\xa2\xd9\xde\xa2\x93\xa2\x68\xf3\x6f\xd3\x32\xf0\xce\x24\x87\xa7\x5d\xe7\x59\x84\x96\x0c\xe8\x70\x02\x5f\xbc\x82\x11\xd0\x66\x8f\x4a\x05\xe0\xab\x87\x98\xbd\x25\x25\x2d\x9b\x8e\xfc\x3b\x71\xc6\xb9\x0d\x6f\xd6\x78\xbb\x1a\x46\xe8\xa9\x7c\xa1\x90\xcf\x4d\x15\x4b\x9c\xbf\x8f\x6d\xbb\xf3\xde\x43\xa5\x1a\xcf\xa3\xaa\x3c\x22\x11\xb8\xf9\xc9\x48\x95\xe5\x28\xef\x3f\x7c\xe8\xdc\x7f\xf8\x73\x0e\x2f\x3c\x93\x37\xa1\x8a\x32\xcd\x9d\x42\x9d\x86\x56\x06\x32\xc0\x4a\xe4\xc4\x80\x88\x4e\x03\xf7\x13\x67\xf5\x1f\x31\x37\x01\xea\x12\xc0\x6e\x87\x91\xc9\x20\x42\x3b\x30\x86\x57\x0c\xc5\x94\x1f\x86\xfc\xfc\xf8\x5c\xdc\xf4\xb7\x67\x0c\x53\x2b\x87\x8f\xe5\x0b\xb2\x08\x80\x6a\xe5\xf0\x83\x09\x88\xcc\xa9\x0c\x55\xd5\x2e\x9c\xa6\xd9\xd7\x1c\xae\x72\x5c\x35\xd3\xa6\xbf\x8f\xed\x6b\xe6\x7e\xf6\x4a\x80\x3d\x0a\x48\xc2\xa2\x24\xc3\x03\x96\xd7\xf4\xb9\x60\x5c\xb0\xb4\x35\xa8\x6f\x4c\x40\x2c\xae\xd3\xbd\x24\xb9\x5a\xd9\x8d\x62\x04\x77\xea\xe6\x55\x2b\x16\x55\x54\xdb\x10\x4b\xfb\x51\x0c\x75\xa8\xd6\xd6\x06\x16\x99\xbc\x4c\x8c\x52\x1c\x90\x24\x04\xec\xb2\xd1\x22\x4a\x32\x86\x85\xea\xec\x9c\x64\xb4\x61\x8b\xb5\xf9\xa0\x50\x45\xc3\x1b\xc2\x1e\x64\xbc\xf5\x9a\x21\x8b\x17\x1d\x44\xe9\x80\x64\x6c\x40\x66\x03\x2a\x0c\x90\x6d\xa7\x3a\xea\x9b\x1b\xfd\x6b\xf3\xc1\x5a\xd5\x70\xad\x1a\x86\x9f\x7f\xd3\xd5\xe4\x18\x3b\x2b\xd2\x5a\x45\x5a\xa9\x28\xe7\x69\xa8\x28\x6c\xbf\x72\xa0\x91\xd9\x74\x44\xe0\xf1\x68\x41\x12\x36\x87\x49\xa5\xed\x22\x6d\xb3\x18\x1a\xff\xdd\x39\x32\x36\x0a\xfd\xab\x46\x0b\x3c\x45\x6e\xe1\xd1\x15\xf6\x29\xa8\x36\x6d\xdd\x62\xe8\x5f\x19\xda\x63\x91\x18\x30\x8e\x5a\x21\xf0\x70\x8b\x10\xa9\xe7\x16\xa6\x5e\x5a\x36\x8a\xd7\x11\x2a\x5f\x4d\x86\x15\xa7\x26\x17\xbf\x5b\x1b\x1b\xe2\xe0\xa0\xad\xf7\x10\x21\x24\x49\x5c\x1f\xed\x25\x70\x96\xa0\x89\x0d\x87\x09\xb2\xd0\xef\xc3\x8d\x3f\x6d\xf4\xc7\x1f\xe1\x1f\x7f\x84\xb6\xb3\xa5\xbf\x2c\xf1\x40\x07\x96\x25\x5e\x20\x89\xcb\x39\x76\x03\x70\x45\x14\xbb\x85\x8c\x94\x2c\x54\x88\x03\x17\x89\x66\x3f\xdf\xa0\xdf\x37\x86\x7f\xfe\xf1\x47\x78\xbd\x99\x3b\x5b\xf2\xaf\x6d\x6f\x59\x36\x10\xbb\x79\x34\x05\x75\xf9\x50\xa0\x85\xf7\x77\xef\x16\xc4\x36\x50\x92\xec\x76\xc1\xf2\x48\xaa\x97\x9d\xd4\x8d\xd5\xeb\x35\xaa\xe7\x50\xbb\xde\xa4\xd2\x93\x3c\x65\xaa\x59\x93\x56\xd6\xc4\x70\x99\xac\xee\xeb\x17\x1e\x8a\x10\x86\xa0\x90\xc6\x43\x65\x88\xfa\x06\xf8\xc2\x43\xf5\x01\x08\xf9\x7c\xfb\xc0\xfb\xab\xfa\x1b\xe7\xad\x23\xb2\x79\x34\x1a\x9a\x1e\xcb\xaa\x39\x24\x46\x5a\xd4\x7c\x0b\xa9\x4b\xb4\xc6\x8f\xb4\x03\xd4\xb7\x55\x1c\xfc\x1d\x46\x7f\x5a\xa6\x43\xc3\x1a\x8f\xac\x5c\x79\x62\x4d\xdc\xe2\x04\x99\x51\x84\xed\xf2\xc5\xf5\x31\x9a\xe0\xfb\x3f\x25\x76\x0e\x24\x72\xa3\x1a\x7a\x97\x3b\xc2\xe2\x88\x7d\xfd\x20\xb7\xb7\x86\x5b\x16\x34\xd3\x37\x7b\xd2\x6b\xa9\xc7\x1d\x85\x9c\x5b\xa6\xd7\x53\x7f\x1f\x81\xd8\x29\x13\x68\x65\x7d\xbe\x31\x6c\xa3\x2d\x0b\x2c\x34\xfa\x89\xef\xa6\xf2\x3f\x08\xd6\xa1\x26\x0a\x66\x02\x43\x76\x80\x2a\x47\x83\xc9\x7a\xfb\x9b\x44\x88\xda\x0d\xb1\x67\x52\xdf\x92\x49\x6b\x93\x26\xf5\x4d\x5a\x4f\xec\x49\xef\xcf\x5a\x99\xbb\x4e\x81\x35\xcb\xac\x5f\xcc\xc0\x1e\x77\x97\x34\xf2\xd2\x82\xa5\x2c\x28\x52\x7f\x7d\x09\x68\x71\xcc\x54\xc2\x3e\x0b\x97\xaf\xb6\x43\x23\x74\xcd\x4f\x24\x87\x53\x02\xa5\xf0\x04\xd6\xd8\xb2\x41\x1c\x50\x95\xe4\x89\xc8\x99\x58\x36\x84\xfe\x55\x3d\xbd\xcc\xe2\x67\x7d\x2b\x6f\x52\xb6\x29\xce\x74\x53\x81\xb2\x8c\x3c\xbe\x3b\xca\x54\x9b\x8a\xe3\x48\x95\x4d\x22\xd4\x05\x82\xb1\x5d\x98\x02\x77\x17\x12\xe5\x72\x61\x21\x64\x65\xc9\x69\x42\x2e\x92\x81\xf4\x83\x6e\xe7\x90\x75\xb0\x0b\xe2\x91\x74\x6c\x6f\x59\x96\x3e\xf7\x61\xc2\x59\x92\xad\xca\xbe\x1c\x8d\xc7\x2a\x6c\x46\xa5\x4c\xbb\x90\x2e\x53\x4d\x2c\xc2\x6d\x78\x26\x0a\xca\xf3\x9a\x6a\xd2\xad\xde\xc7\xbc\x77\xda\xd7\x75\xb3\x00\xbe\xdf\x2c\x20\xf2\x69\x0e\x51\x1f\xd3\x64\xe8\x5a\x4f\xe9\x54\x70\x30\x7e\xe7\x29\x30\x56\xaf\x20\x77\xef\xaa\x2f\xad\x93\x6f\x7d\xb6\xea\x0f\x1b\x25\xbf\xf8\xf7\xe1\x64\x8b\x33\x38\xd6\xd0\x7a\xd4\xe2\x69\x92\x0a\x5d\x8c\x22\xb4\xc7\xcf\x00\xfe\x21\x7d\xa5\xd9\x39\xa4\xc6\x99\xc8\x50\x14\x56\x43\x3c\xeb\x45\x48\x32\x6c\x86\xeb\xb5\x35\x34\x04\x86\x88\x22\xcd\x2e\xde\xaa\x46\xe8\x5f\x99\xca\x1f\x77\x95\xe7\xdb\xcc\x54\xc1\xe9\x1c\x92\xd8\x78\xb7\xaa\x22\xf7\x96\x49\x63\x48\x36\x58\x6c\x3f\x43\x11\x9f\x17\x51\x36\x47\x3d\x12\x92\xdc\xce\x61\x16\xb9\x92\x00\x8d\x15\xc5\x99\x08\xfa\x32\x91\xa4\x64\xac\x49\xc6\x58\xd3\x85\x71\x6d\xe7\x8f\xf5\xee\xee\xe3\x41\x62\xf3\x7d\x48\xd6\xd4\x18\x74\xff\x21\xfe\xf9\x27\x8e\x6a\x1b\x0f\xf1\x83\x9f\xc4\x1b\x17\x84\xf5\x8a\x5a\xea\xa1\x99\x7a\xc1\xc9\x4f\x7e\xfb\x45\x1a\xcc\xab\x76\xbf\x0a\xe7\x40\x4f\xbd\x02\x71\x22\x14\x33\x98\x94\x1c\xbf\x0d\x58\x1c\xa3\x9f\x3c\x99\x25\xcb\x6d\x4c\x60\xf2\xdb\xc3\xdf\x0c\xd2\x9e\x5f\x1f\x3e\xc0\x3f\xff\xf4\x15\x99\x56\x4f\xe6\xa1\x4f\x45\x6f\x43\x13\x5a\xa8\x52\xa6\xfb\xc7\xb0\x0b\xf7\x7e\xdd\xfc\x15\xff\x3c\x14\x40\x91\xe8\xd6\x2e\x72\xff\xe7\x07\xf8\xc1\x90\x43\xab\xb8\x50\xb6\xca\x3c\xc4\x0f\x86\x9c\xed\x2a\x6e\x9f\xad\x12\x71\x84\xba\x70\x44\x2f\xcd\x78\x88\xbe\xa2\x84\x8f\xb5\x8a\x75\xb9\x7c\x82\xe9\x85\xb6\xd0\x54\xaa\x83\x9b\xaf\x97\x82\x82\xc8\xbd\x3d\xb8\xbf\x22\xd2\x0d\x64\x01\xcf\xe1\xc4\x50\xa0\x17\x96\xfd\x50\xec\x87\xe0\x70\xf2\xd3\x1a\x40\xe4\x10\xdc\xa8\x41\x30\x87\xa5\x69\x63\x94\x56\x37\x9c\xce\x7e\xf6\x9c\x8f\x9e\x00\x61\x29\x94\xc4\xf7\xe5\xbb\x71\x21\x50\xa1\x15\x15\xfa\xa4\x52\xf4\x1e\x9f\xf3\xcd\x18\x36\x1f\xc8\xbb\x61\x91\xfe\x10\x3f\xb8\x19\xc3\xc3\xb1\x2d\xad\x4f\x75\xf2\x04\xdf\x57\xc9\x99\xeb\xa3\x1f\x3c\xf8\xec\xa9\xf5\xba\x27\xc0\x7b\x33\xb6\x41\xd9\xea\xa7\xc2\x56\x1f\x66\xae\x8f\xde\x78\xe0\xc1\x04\xd2\x8d\x89\x0d\xb1\x3b\x53\x76\x19\x35\xdb\x3b\xe5\x4c\x7d\x16\xc1\xb5\x22\x1c\x81\x26\x2c\x44\x12\x9a\x44\x50\x9d\x50\xd1\xa0\x18\x04\x49\xf2\x6a\xb4\x06\x2b\x85\xfe\xa5\x5b\x0c\x07\xe6\x55\xc0\x88\x44\x1b\xce\xa5\x20\x77\xce\x99\x03\x31\x8b\x8f\x9e\xd8\xdb\xb0\xdc\x98\xd8\x4e\x3d\x85\xcf\xe7\x5c\xce\xe7\x9c\xcf\xe7\xa4\x32\x1f\x3e\x9b\x13\x39\x9b\x13\x9e\x57\x01\xd5\xbc\x02\x2a\x52\x4d\x2e\x01\x9b\x54\x93\xcb\x75\xf8\x07\xc0\x04\xe6\x91\x8b\xfa\x0c\xc6\xd4\x2d\x51\x54\x67\xaa\x35\x2a\xda\xc6\xba\xa3\xa2\xe3\xca\x50\xca\x5e\x32\x4d\xe5\xbd\x3c\xb7\xf5\x11\x7d\x94\x89\x00\xd4\xe7\x91\x8b\xba\x5e\x8f\x8e\xe7\x99\xd5\x2d\xdd\x7f\x42\xa3\x9e\xdc\x23\x61\xc2\xd4\xca\x9d\x47\x9d\x35\x0e\x49\xd2\xd3\xde\x71\x86\x7b\x72\x3f\xe0\xd0\xea\x78\x4b\x68\x6b\x23\xdc\x29\x7e\xda\xd7\x52\x96\x59\x73\x54\x77\x4c\x6a\xba\xff\x4d\xc5\xcb\x59\x6f\x36\x41\xd6\xf6\x94\x88\x48\x73\x4d\x7d\x56\x93\x16\x67\xd9\x97\x76\x5e\xa9\x63\x09\x0e\x55\x84\x87\xe8\x1c\xb7\xdb\x6a\x0d\xea\xed\x3a\xed\x0c\x55\xf0\xba\xd6\x38\xbe\x12\x44\xdb\xe4\xaf\x3a\xcd\xde\xd9\x94\x4f\x95\x2f\x49\xd3\x17\x27\x41\xd6\xd4\x0f\x4f\x0c\x73\xb0\xe1\xd8\x54\xfa\x02\x8b\x20\x94\xeb\x15\xfe\x92\x2d\xa6\x84\x51\xe1\x51\xb7\x55\xa3\x03\xba\x41\x8c\x7d\x3a\x8b\x2e\xbb\xa1\x2a\x27\x1c\xa1\x97\xc6\x95\x56\x3a\xc6\x8b\xc8\x45\xc6\x31\xcd\x08\x5d\x0c\x75\xa0\xc2\xf5\xa6\x41\xc9\x85\xa1\xac\x0d\x27\x51\x77\x80\x8b\xa8\xa5\x8a\x6c\x9e\x2d\x89\x87\x97\xe9\xf0\xa1\x61\xb6\x6c\x7d\x8c\xec\x69\xc5\x80\x38\x76\xd7\x3c\x03\x92\x30\x3f\x4a\x30\x1d\xce\xe2\x2c\x0a\xd7\x86\x4f\x51\xcf\x54\xc3\x47\x3e\x01\x2b\x8e\x92\xd3\xe6\xed\x63\x57\x44\x39\xbd\x8a\x71\x3a\xc7\x98\x99\x10\xff\x05\x41\x96\x36\xcd\x5a\xf8\x97\x41\x98\x8c\xa6\x84\xb0\x94\x51\x7f\xc9\x7f\x04\x64\x71\xaf\x48\xb8\x77\x7f\x74\x7f\xf4\xf0\x5e\x90\xa6\x65\x1a\x67\x39\x46\x81\x88\x24\xd9\xbf\x7d\xd4\x8f\x03\x3c\x63\xfc\xe7\x34\x2a\x5e\x60\x08\x63\x64\x61\xe5\x70\x55\x24\xbd\x8d\x4e\xe6\x9c\x78\x1e\x17\x29\xc7\x64\x69\xe5\x70\x11\xf5\xfb\xcc\x18\x18\x56\x8f\x06\x7d\x8a\x01\x92\xd1\xb7\x96\x64\x49\xce\x31\x1d\xcc\xfc\x50\x3e\x80\xdf\x59\xf9\xa8\xab\x6a\x46\x89\xa5\x8c\xad\xd6\x2a\xce\xc8\x52\x94\x57\xb7\xff\xe3\xc8\x5e\xb3\x22\x15\x20\xa9\x54\xbd\x5a\xbb\xea\x54\x02\xb8\x52\x77\xba\x76\xdd\x98\x2f\x57\xa5\xe6\x49\xbd\x66\x79\xca\x98\x9e\x8f\x83\x8a\x5c\x14\xc3\xea\xce\xc2\x28\x5d\xc6\x4a\x73\x41\x06\x0c\x6e\x1f\x69\x06\x15\x91\xd6\x59\x60\xdc\xc1\x3e\x35\x12\x99\x2e\x1a\xaf\x6a\x56\x0e\x4a\x19\xe9\x20\x69\xbe\xce\x32\xed\xb2\x64\x69\xea\x55\x21\xd6\x50\x86\x0c\x5d\x79\x8c\x11\xa1\xf5\xd8\xde\xe3\xce\x79\x94\xa3\xf5\xa9\x95\xee\x35\x90\x91\xc6\x56\xf6\x4b\x56\x1f\x6e\x82\xa6\x45\xe8\x59\x97\x06\xb3\x72\x84\x76\x66\x6f\x31\x87\xe6\x36\x9c\x75\xea\x3a\xb3\xad\x03\x44\xa5\xc2\x6c\x8f\x63\xa7\xee\x42\x4d\x05\x30\xd4\x7c\x28\xc7\x23\x6f\xec\x08\x37\x24\x5d\x7e\xa1\x0c\xc8\xa7\xdf\xb9\xd5\xea\xea\xac\xaa\xe0\xb9\x26\x2c\x6d\xa7\x29\x99\xea\x01\x8a\x10\x2b\x04\xa1\x49\x4d\x41\x98\x31\x74\xdc\x35\x21\xc3\x98\x94\xce\x71\xe9\xdd\xbf\x6d\x76\xb2\x75\xe6\x18\x4d\x42\xb6\xce\x9c\x03\x64\x68\x52\x19\x6a\x48\xa5\x41\x31\xb4\x3e\xb5\xf4\xaa\xce\x57\xe5\x79\x9d\x41\x84\xf6\x05\x3c\xa5\x02\xea\xa9\x49\x20\xd6\xd8\x20\x39\x1c\x75\x9e\xe5\xd7\x41\x4c\x52\x7c\xa8\xc2\xb5\xf1\xb6\x19\xd0\x51\x35\xd1\x86\xe2\x04\xdc\x89\xfd\x34\x75\xa4\xa5\x76\x99\xa0\xe2\xe6\x88\xca\x9e\x0c\x3b\xa3\x62\x0b\xda\x32\x90\x4e\x35\x43\x05\x5d\x14\xc1\xcd\x6b\x19\x32\xc9\xee\xd4\x2c\xf8\xb6\xc3\x65\x41\x42\x3f\x1e\x4e\xfd\xe0\x34\xa4\x64\x39\x50\x27\xc6\xa9\x7c\x9a\x5d\xb5\xf1\x6a\xf4\x29\xb7\xe1\xb2\x43\xf8\x68\xa4\x03\xb2\xe7\x22\x8a\x7b\x3f\x11\x68\x29\x2a\xda\x39\x3c\xbe\x7d\x6f\x2a\xc0\xf6\xed\xfb\xda\xee\xe8\x6b\xdf\xcc\xc3\x92\x14\x9b\x18\x9a\x65\x60\x12\x64\x18\x2e\x29\x06\xf6\xd7\xce\xe1\x65\xd4\xf5\x92\xa5\x0e\xc0\x33\xed\x1b\x47\xd0\xba\xf3\xa8\x8b\x04\x4b\x60\xe8\x90\xfa\x2b\xc0\xe1\xa3\x8b\x08\xce\x23\xd8\x8e\x3a\x78\xd2\x1d\x9e\xdb\xc1\x68\xbe\x35\x8a\xf7\xa3\x8a\x7c\x5f\x0c\xb1\x71\x92\x51\x37\x42\x4f\xcc\x2f\x71\xf5\x9d\x95\x57\x0c\x10\x5a\x0f\xae\x5b\x95\xd1\x38\x2d\x20\x50\xd3\x59\xc6\xcf\xb1\x95\x87\xd8\xfa\xfb\xea\xfb\xb9\x35\x05\x49\x23\xff\x72\x3b\x9e\x85\x6e\x29\xae\xc5\xb1\x12\x92\x60\x03\xf3\xf2\x8d\xbc\x8b\x44\xa6\x30\xf2\x63\x72\xb2\xc6\x5d\xb8\xa7\x8d\x6e\x8e\xa0\x85\x1f\xfd\x6f\xec\xf5\x0e\xce\xa3\x66\x7b\x95\xa7\x17\xa3\x6e\x70\x84\x5e\x46\x80\x6b\x44\x1e\x70\x41\xb2\xdb\xef\x01\x6a\x87\x3c\xe6\x95\x24\xfd\xee\x2c\x73\xc9\xcb\x28\x52\x6e\xe0\x55\x51\x9b\x85\x5c\x47\x54\x71\x64\x94\x90\xda\x39\xec\xad\xb8\x94\xd4\x4f\x37\xd6\x3a\xc9\xf4\xd1\x55\xc4\x51\x54\x07\x53\xbf\x63\xbf\x28\x7d\x8b\x4f\xf0\xa5\xc3\x40\x44\xb4\xa2\x4a\x39\x5d\xfa\xf5\x3b\xec\x3e\x6a\x99\xc3\x20\xed\xb5\xc9\x0a\xcb\x12\x9d\xda\xe3\x47\x59\x10\x88\xf8\xc2\xda\x7d\xc6\x8e\x89\x78\xab\xc2\x4f\xfc\x28\xce\x28\xd6\x85\xe1\xac\xb8\xd5\x1d\x10\x3f\xe4\xc8\x95\xc3\x93\x22\x6d\x3f\x89\x58\xe4\xc7\x56\x0e\x07\x51\x8f\x3d\xa6\xea\x41\x58\xad\x8a\x20\x08\xa9\xc3\x20\xf6\xa7\x38\xe6\x20\x4d\xa3\x18\x27\x01\xde\x0f\x1d\x2c\xc2\x66\xcd\xa3\xa9\xd4\xee\x07\x61\x05\x97\x6e\x33\x87\xc0\x09\x4e\xb0\x30\x83\x7b\x47\x63\x27\x80\x28\x94\xe1\x29\xf7\xbb\x8e\x80\x6b\x19\x3b\x0c\xa8\x00\xbc\x00\xd0\xab\x6e\x40\x47\x93\x5f\x13\x87\xc1\x8c\xd0\x85\xcf\xda\xe0\xd4\xda\x56\xb5\x68\x3c\x7e\x69\xd6\x3e\x51\x01\x80\xf1\xb4\x48\xda\x54\xe1\x77\x7c\x5a\x24\xdd\x97\x49\xdb\xcb\x32\xe9\x81\x2e\x55\x46\xe8\xf9\xf9\x91\x0a\xf6\x53\x36\xff\x50\x27\x95\x46\xf0\xbf\xa8\xb6\xb2\x93\x22\xe9\x57\x15\xd7\x18\x97\x41\x82\x7e\x53\x26\xf4\x41\x19\xe4\x67\x32\x56\x11\x83\xc8\x79\x99\x36\x69\xaa\x85\x4d\x36\x39\x08\x9e\x77\xbf\x85\xd7\xb4\x91\xa1\x34\x24\x6e\x68\x33\xc3\x58\x7b\xef\x68\x28\x40\xc3\xd8\xce\xe1\x75\x7b\xf1\x4c\xe1\x9c\xab\x90\xbe\x6f\x00\xf5\x73\xbe\xd9\xb7\x36\x7f\x73\x36\x7f\x35\x00\x7d\xd2\x86\xfa\xfd\x71\x1b\xec\xba\x5c\x15\xee\xba\x9c\x00\x7c\x0b\xde\xba\x46\x15\xe0\xba\x46\x15\xe2\xba\x5c\x15\xe2\xf7\xc7\x4d\x88\xdf\x17\x1e\xc7\x76\x8d\x10\xbf\x44\x4f\xb1\xd4\x0e\x78\x67\xcc\xff\x8a\xd1\x91\xcc\x7f\x5f\xcf\x37\xe1\xed\x21\x69\xe1\xed\x71\x86\x9b\x78\xfb\x01\x87\x4d\xbc\x3d\x9e\x67\x4d\xbc\x7d\x42\xa3\x26\xde\x1e\xf9\xac\x82\xb7\x8d\x49\xfe\x92\xe7\xf0\x21\x72\x2f\xd1\xc4\x86\x67\x91\x3b\xc1\xf7\x7f\xfa\x10\xc1\x97\xc8\x7d\x38\xfe\xe9\x59\x04\x5f\xc5\xc7\x97\x08\x9e\x46\xee\xe6\x83\x9f\xbe\x46\xf0\x26\x72\x7f\xf9\xe9\x69\x04\x9f\x0c\x5b\x57\x9e\x59\xcf\x39\x64\x86\xcf\xb1\x70\x78\xed\xbe\x16\xbf\x5e\x8b\x5f\xc4\xdd\x15\xbf\x76\xc5\xaf\xc0\x7d\x27\x7e\xbd\x13\xbf\x32\x17\xed\x46\x22\x33\x42\xd4\x1e\x06\x3f\x7d\x8d\x86\xe4\xa7\x2f\xd1\x30\xf9\xe9\x59\x34\xc4\x3f\x7d\x88\xec\x7b\x4f\xa3\x9b\x31\x78\xd5\x30\x2b\x85\xde\x70\x26\x75\x76\x95\x94\x61\x0f\x65\x3d\xba\x71\x87\x88\xdd\xfb\xe5\x46\xb2\x56\x87\xd5\x6d\xf0\x8b\x5d\x84\x6d\x36\x54\xcb\x78\x25\x5e\xa7\xa8\x91\xc1\x2f\x22\x18\x86\xee\xea\x02\xe3\x53\xc7\x13\x2f\x46\xfe\x15\xff\x50\x8f\xe8\x41\xeb\x79\x25\x69\x3c\xe2\xd4\x8f\xaa\xba\x6b\x89\x77\x11\xbf\x12\x77\x5c\xf5\x37\x68\x6e\x03\xfe\x89\xc2\x6e\x84\x12\xa1\xae\x6d\xc3\x0b\xb3\xb2\x87\x69\x23\x1f\x96\xa3\x28\x70\xe4\x43\xa4\x77\x51\x2d\xf9\x99\x4a\x3e\x14\x53\x29\x92\xbf\xa8\xe4\x67\x24\x2b\xb7\xf3\x57\x95\xb8\x5b\xd9\xce\x4f\x23\x8d\xc7\xf8\xb4\x0c\x70\x16\x15\x08\xd9\x62\x78\x06\x1f\xa2\x9f\x70\xf5\xbd\x74\xe3\x19\x4f\x50\xdf\x5f\x64\x26\x1f\xcb\xc6\x57\xfe\xcd\x21\xbd\xf1\x94\x7f\x85\xfe\xd5\xc6\x1b\xfe\xc1\xd7\x23\xcf\xe1\xb3\x71\x8b\x7e\x8a\xd0\x8b\x48\x85\x87\x8b\x56\x86\x70\x10\x4b\xcb\xc4\xba\x52\xb9\xa8\x58\x2f\x6a\xa2\x17\x95\xd4\x16\xb5\x3f\x8a\xc3\x2e\x8e\x99\x5f\x9e\xff\x3f\x14\xe7\xb7\x02\x6f\x0e\xcc\x2f\x93\xca\x45\xca\x81\xfa\x9d\xfe\xba\x11\x9a\xfc\x7c\xff\x27\x44\x37\x8a\x50\x02\x42\x63\x7a\x78\xdf\xf9\xcd\xb6\x37\x36\xed\x7b\x3f\xdf\x8c\xed\x0d\x3c\x9c\x00\x71\xd9\xb0\x52\xe8\x6f\x93\xad\x89\x23\x1e\x83\x55\x22\x51\xaf\xcf\xc4\x21\xc3\xfb\xbf\xfd\x66\xdf\x7b\x30\x1e\xdf\x8c\x21\x73\xc9\xf0\xc1\x78\xfc\x53\xa0\x97\x68\xf2\xe0\xe1\xf8\xb7\x5f\x7e\x0a\x36\xd0\xfd\x87\x3f\xff\x94\x6d\xa0\xec\xde\x83\x9b\xb1\x3d\x44\xd9\xbd\x09\xaf\x61\x6f\x24\xf6\xf0\x97\xc9\x6f\x0f\x1e\xfe\xca\xf1\xd4\xef\xe1\x48\xa4\x67\x88\x57\x91\xf0\x5f\x52\x79\x04\xff\xdb\x78\x8b\x5f\x78\x67\xae\x8f\xde\xc2\x04\x22\xf4\x3a\x02\x11\x3c\x11\xdb\x10\xbb\x3e\xa2\x3e\xa4\xe0\xc1\xac\xb8\xae\xbd\x88\xd0\xc7\x08\x5d\x57\xd7\x82\x57\x1d\xc3\x6f\xbf\xfd\x06\x59\xa1\xdf\x26\xd3\x7e\xfe\x0d\x82\x42\x2d\xae\x48\x22\x4a\x91\x4e\x26\x6c\xde\x87\x44\x2a\xdd\xc5\x20\xf0\x60\x2c\x2d\xa4\x13\xdf\x84\x57\x21\xc2\x3e\x7c\xe1\x94\x0d\x9e\x89\x7f\x3f\x88\x7f\x05\xad\x03\x41\xff\x40\xd0\x44\x78\xae\x4e\x10\xe2\x1b\xb6\x6b\xe2\x97\x17\x50\xa4\x4f\x9b\x21\xb5\xef\x7d\x89\x6e\xc6\x39\x04\xbe\xdb\xe1\xdd\x7e\x35\xb5\xa0\x9c\x9e\xef\x46\x42\x37\x37\xb7\x21\xf3\x7b\xec\xb4\x3f\x47\xf0\x43\x04\xc4\xe7\x24\x99\xf8\xda\xbf\x33\x7c\x89\x6c\xf0\x7c\xf7\x55\x04\x91\xef\xbe\x8f\xc0\x37\xb4\xa1\x0c\x73\x7c\x79\x0c\x44\x7e\x4b\x61\x2e\x01\xcc\x17\xf7\x97\x8d\x64\x88\x9d\x64\x88\x73\x1b\xbe\x62\x34\xb6\x6d\x48\xfd\x66\xf4\x33\xc6\x8f\xa1\x77\x18\xf9\xbe\xbd\xb1\x2b\xfe\xd4\x4c\x26\xbe\x88\x24\xa9\xc0\xb3\x35\x1e\x22\x36\x9c\x3c\x78\x30\xb6\x9d\xf1\x90\xf1\xfb\xf2\xcc\x77\x89\x0f\xb1\x09\xce\x62\x8a\xcc\x07\xb6\x91\xfa\x3f\x65\x3e\xf0\x66\xb0\x3b\xf3\x51\x2b\x18\x4c\xea\xdb\x5b\x1c\x23\x24\x48\xf0\x30\xf5\x39\x2c\x20\xf4\x5d\xe4\xa3\x55\x8c\xf6\x20\xf6\x91\x40\x8c\x7a\x2e\x87\xa5\xd0\xaf\xf8\x84\x61\x62\x83\x64\x7a\xaf\x43\xff\xea\x68\x4e\x68\x3d\x6e\xe0\x0a\xc6\x41\x7c\xb7\x78\x07\xf1\xdd\x62\x1f\xc4\x77\x8b\x83\x10\xdf\x2d\x26\x42\x7c\xb7\xf8\x08\xf1\xdd\x60\x25\xa4\x3e\x00\x07\xc8\xd5\x4b\xce\xe8\xdf\x72\xf0\xa1\x7f\x65\x1e\x7f\x5a\xe6\x34\xe6\x90\x54\xf3\x1a\x33\xa1\x95\xac\xc6\x74\xca\x8c\xc6\x8c\x32\x2a\xb2\xda\xd3\xe2\xc9\x79\x2e\x15\x27\xd6\x5b\x99\x0a\x83\x2c\xbe\x5b\x2c\xb2\xf8\x6e\xf1\xc6\xe2\xbb\xc5\x1d\x8b\xef\x16\x7f\x2c\xbe\x5b\x1c\xb2\xf8\x6e\x5d\x4e\xc4\x77\xeb\x7e\x22\xbe\x5b\x1c\xb3\xf8\x6e\xf1\xcc\xe2\xbb\xc5\x35\x8b\xef\x26\xc0\x76\x71\x50\x40\x6b\x2d\x4c\x68\x00\x4b\x98\x09\x1b\x01\x46\x2b\x59\x0d\xa8\x05\x73\x33\xdc\xa2\xf8\x36\x90\xc3\x66\xd0\x5d\x99\x61\x97\xa5\xcc\x0c\x3e\x65\x5a\x6b\x04\x22\x29\x73\x1a\x80\x54\x95\xda\xd0\x94\x19\x72\x6b\xbd\x9a\x1d\x72\xb8\x7e\x88\xd8\xfc\x28\x9b\xcd\xa2\x4b\x67\x45\x9c\xd3\xf2\x02\x27\xa1\x3d\x98\xe8\x96\x27\x7a\xf8\x83\xcd\x22\x6d\xb3\x92\x58\xa4\x25\xa1\x4e\x2a\xd3\xca\xc4\xfb\x3a\xed\x3e\x2d\xca\x15\x69\x9b\x65\xe2\xfd\xa2\x93\xfb\xa2\x93\x96\x1b\x38\xfd\xd4\x79\xca\x4f\x0c\x8b\xcd\xad\x2a\x6f\x3d\x60\x5b\x3e\xba\xa2\xf0\xa0\xe2\x9b\x12\xb0\x2d\xf5\x9f\x94\x90\xe0\x5a\x04\x46\xb5\x7e\x1c\x2e\xee\xfd\x38\x0c\xef\xfd\xf8\xc9\x82\x98\x24\x27\xbb\x32\x75\x1b\x06\x3f\x3e\x1e\xfc\x18\xc2\x80\x67\xb0\x68\x21\x8a\x3e\x73\x7e\x3c\x1c\xfc\xb8\x94\x25\x8f\x2b\x89\xce\x8f\x47\x22\x9d\xb7\xa9\xd3\x75\xbb\x83\x1f\x87\xfb\xba\xde\x2c\xa2\x29\xdb\xe5\x0b\xc3\x19\x5b\xe7\x8d\xe0\xe5\x97\x26\xce\xc0\xf4\x42\x75\xef\xe1\xb8\x71\xa7\x60\xf0\x70\x6c\xe7\x39\xcc\xfd\x2e\x49\xba\xe1\x55\x49\x80\x86\x1f\x2d\xa7\x48\x3e\x2a\xc1\xb9\x91\x37\xa9\xda\x9d\x54\xab\x6e\x02\x13\x60\xe7\x1d\x2f\x8c\x35\x5b\xa2\x84\x4d\x1b\xc6\xf6\xd6\x64\xd3\xa9\x27\xe6\x70\xd2\x1e\xb8\x44\xc9\xa5\x8f\xf6\x84\x7f\x57\x19\x06\x45\xc6\xe9\x9a\xb4\x15\xc8\x2b\xe6\x85\x85\x9a\x79\x55\xa7\x1c\x9d\xfb\x95\x00\x53\x9c\x35\xab\x1a\xd4\x35\xb3\x85\x5b\x84\xdc\x86\xa9\x71\x5a\x11\x7a\x02\xc7\x22\xcc\xc3\x95\xdf\x13\x9a\x55\x98\xd8\x0d\x2c\x98\xfa\xe8\x13\x4a\x2a\xb6\x36\xb6\x6d\xeb\x7b\x15\x51\xd4\xec\x53\x71\xb9\xf1\xd1\xdc\x2f\x11\x96\x0f\xe6\x0b\xe6\xeb\x23\x77\x7f\x35\xc8\xf9\x29\x5f\x02\x51\x7c\xb3\x5d\x5c\x95\x5f\x54\xca\xd7\xa7\xe8\xf9\xe8\x59\xb5\xa4\x67\x2e\x3a\x30\x14\x1d\x96\x45\x4f\x51\x33\xf3\x71\x91\xc7\x46\x9c\x33\x19\x15\x24\x5d\x95\x93\xc5\xfe\xb3\x2c\xb7\xa0\xa8\xa3\xa8\x2a\x3b\x35\x36\x29\xce\xd4\x7a\x9b\xd3\xae\x36\xab\x65\x55\xe1\xb0\x13\x32\x1f\x2a\x4d\x0e\xc3\xca\x54\x6b\x19\xff\x51\x6d\x40\xf5\x65\x22\xb5\x70\x67\x52\x6b\x11\x77\x82\xb9\x5a\xea\x3f\xf0\xba\xad\x8f\x6b\xf5\xb6\x9b\xa0\x52\x8c\x15\x7a\x5f\x85\xd3\xb6\x01\x4e\xf5\x82\xaa\xa4\x6f\x68\x4e\xc2\xb2\xd6\x9e\x6f\x6e\xaf\x5a\x52\x15\x7d\xd6\x09\xf5\x77\x55\xe0\x3e\xab\x40\xbd\x9a\x71\xda\x09\xbc\x6a\xa9\xfd\xce\x4e\x16\xbe\x6a\x4e\x77\xb4\x5f\xe9\xa8\x99\x19\x77\x76\xd6\x2c\x59\x0a\x0e\x25\x19\x12\x99\x9c\xb0\xfd\x6d\xbc\x65\x6d\x1f\x5a\x8e\xf5\xfa\x50\x1d\xdf\xaf\xfb\x8a\xfa\x0b\xcb\xb1\x96\x0b\xcd\x7c\x74\x4e\x63\xb7\x32\xd9\xa3\xce\x52\xaf\x2b\xa5\x0e\xea\xf4\xe5\x7e\xb5\xdc\xf3\x4a\xb9\x1f\x8b\x72\x44\x26\x7c\xad\x34\x7f\xe2\x4b\x93\x61\x99\xe3\x34\xb3\x1c\xab\x6d\x98\x6c\x49\xf5\x3a\xdf\x3d\x4c\x90\xf5\x23\xba\xba\xf9\x74\xb3\xb8\xf1\x16\x37\xc3\xc5\xcd\xe3\x9b\xff\x7c\x7c\x33\xbd\xf9\xcf\xe9\x4d\x78\x33\x0c\x6f\x86\xff\x11\xde\xe0\x9b\xff\xc0\x37\xdb\x37\xff\xb9\x7d\xe3\xdf\xfc\xa7\x7f\xf3\xec\x66\xf8\xec\xe6\xf4\x66\xff\x66\xb8\x7f\x13\xdf\x2c\x6f\x5e\xdf\x1c\xde\x1c\xdd\xfc\x78\x73\x70\xf3\xf5\xc6\xf9\x6a\x5b\x36\x5c\xf4\xd1\xdf\x99\x8f\x92\x82\x13\x10\x56\xa9\x4f\x12\x38\xf6\xc1\x47\x57\xf2\x4a\x15\xa1\xc0\x07\x32\xa4\xc2\x71\xa9\x08\xdf\x76\x6a\x12\x93\x14\x2d\x5c\xf0\x6a\x33\x9f\x2f\x98\x0a\xf7\x76\xb4\xba\xfc\x58\x97\xbd\xf4\x5d\x14\xa1\x53\x1f\x42\x1f\xac\x1f\x3f\x0d\x7f\x5c\x0c\x7f\x0c\x8f\x7f\x54\x6c\xc3\xe8\xc7\x83\x1f\x9d\xaf\xc2\x30\xbb\xa7\x88\xd1\x90\x56\xbf\x92\x5b\x96\x08\xca\x68\x1d\xcd\x49\x16\x87\x03\xe5\x59\x54\x78\x15\x15\xce\xdd\x9f\x31\xb8\x42\xd6\x07\x4a\x92\x93\xc1\xfe\xd1\xab\x5f\x1f\x8e\x27\x03\xc9\x04\x89\x6e\xdf\x19\xe3\x70\x1f\xa1\x50\xc9\xbb\x82\x48\xbb\x76\x78\x6c\x3c\x15\xd3\x08\x2d\x23\xf4\x58\x16\x82\x6d\x63\x19\x1f\x1d\xa9\xc9\xa9\x39\x59\xfc\xf6\x2e\x9a\x7f\xb9\xa2\x82\x82\x46\x59\xe1\x6d\xc7\xd9\xac\x4f\xf5\x97\x42\xf2\x50\xb1\x6e\x1b\x58\xb0\xed\xab\xe1\xed\xad\x31\x85\x43\xdf\x5d\xfd\x14\xad\x5d\xf0\xfc\xfc\xf3\xc3\xdf\x36\x1f\xe2\xfb\x6b\xbe\x89\x87\xa2\x9a\x30\x3d\x58\xb3\x86\xf2\x65\xf4\x70\xed\x0a\x52\xf9\xf0\x21\x7e\xb0\x66\xf9\x54\x94\x9f\xd4\xa7\x50\xe8\x1a\xc2\x8e\xef\x56\xfc\xc8\x0a\xef\xeb\x5d\x02\xa3\x9f\x68\x6e\x03\xf1\x20\xf2\x50\xd3\xf2\x58\x8b\x95\x8b\xd5\x2a\x5a\x7c\x95\x49\x63\x3f\xe9\x4f\xd6\x1b\xcb\x15\xb0\x6d\xbb\x74\x85\xdc\xab\x23\x42\xed\xdc\x46\x15\x17\xf4\xb6\x0d\x67\xbe\x6b\xe0\x5d\x6b\x01\x53\xb7\x0e\xd0\x94\xa2\xed\x04\xf9\x06\x2d\xbb\xaa\x9b\x39\x6f\x02\xc4\xa5\x20\xa3\x10\x42\x56\x8d\x12\x65\x00\xa6\x8c\xe3\x79\x2f\xb9\x19\x73\x7e\x37\xa8\x98\x88\x06\x50\xbd\xb3\x88\x22\x55\x24\x15\x3c\xae\x1c\x7f\xe3\xd1\x20\xb1\x2b\x56\x14\xb5\x85\x13\xeb\xf6\x18\x51\x0d\x30\xdb\x39\xcb\xe1\x49\x6d\xb9\xd4\xa7\x2b\xe1\x1c\xa1\x0f\x9d\x6b\x27\x84\x7d\x63\x01\xf5\x8f\x19\x87\xfa\x8e\x6f\xdb\xf0\x26\xb3\xe1\xa0\x63\xbf\x55\xc9\x4a\x98\x51\xf1\x2e\x5c\xa5\x2b\xcf\x33\x78\xe2\x0b\x53\x74\xd8\xf7\xdd\x7d\x5f\x38\xe9\xdf\xf7\x7f\xb7\x6e\x1c\xeb\x4f\x77\x8a\xe2\xa4\x4b\x92\x48\x11\xb3\x73\x7e\xc8\xf2\x85\x78\x65\x12\xc4\x45\x28\xd4\xfe\x3a\xb7\x22\x74\x2c\xdd\x7b\x3a\xac\x7d\x3d\xe0\xa5\xfc\x65\x74\xef\x7c\x62\xd9\x39\x3c\xe7\xc0\x49\x12\x03\x66\x5e\x56\x24\x8e\xca\x29\xa0\x52\xba\x09\x12\x89\x96\x0e\xa9\x79\x1e\xd8\x29\x68\x6d\x88\x03\x12\xe2\x01\xbf\x23\x0e\xac\xc6\xed\xa2\x28\xee\x0c\x2c\xe9\xf2\x40\x50\x98\xe3\xc4\x86\xd7\x7e\xbf\xcb\xf6\xb7\x01\xba\x5e\x60\x36\x27\xa1\xc3\x94\xd6\x42\xea\x50\xc8\x68\x5c\x2a\x2f\x48\xf3\x70\xe7\x71\x80\x88\x2d\x2e\xa9\x24\x63\xce\x19\x5c\x44\x6c\xbe\x43\x71\x88\x13\x16\xf9\x71\xea\xdc\x99\x08\xdd\xa5\xdd\xee\x4b\x22\x7a\xed\x83\xb5\xbb\x77\xb0\x77\xbc\x67\xd5\x43\x51\xc0\xcb\x40\x4a\x71\xdf\xf5\x1c\x79\xb2\xfe\xeb\x57\x47\xc7\xcd\xda\xea\x0c\x7c\xbf\xa2\xeb\xa7\x7b\xad\x9a\xba\xdf\x0f\x46\xf4\x7b\xc5\x50\x84\xbc\x04\x22\x34\x4f\xc0\x92\xd6\xdf\x02\xac\x02\xdf\x9e\x99\x70\xc6\xfc\xa6\x75\x2c\xa1\x56\x4a\x03\xe5\xef\x01\xbe\x0c\x30\x0e\x0b\xd1\xe7\x4b\xcc\x2e\x08\x3d\xdd\x13\x1d\x15\x62\x18\x99\xa8\x8c\xcf\xd5\x35\xc8\x0f\x8f\x98\xcf\xb2\xd4\x32\xbc\x51\xf1\x9b\x61\x95\x0c\xe0\x51\x2a\xca\x8e\x38\x06\x35\xcf\xac\x22\x73\xa1\xd4\x32\x39\x2c\x90\x52\xc8\xb1\x8b\xde\x5e\xfb\x57\x31\xf1\x43\x83\xbf\x18\xeb\x5d\xe9\x3f\x40\x99\xe5\xe0\xc1\x8c\x92\xc5\xc0\x5f\x46\x05\x42\x76\x8b\x56\xac\x43\x3f\xe6\xfb\x19\x87\x03\x8e\x75\xba\x42\x9e\xc3\x17\xdf\x3d\x0c\x4c\xf1\x7f\x1a\x51\x72\xd4\x16\xda\x89\xd0\x33\x5f\x11\x77\xe7\x30\x92\x5f\xb9\x0d\x5f\x3b\x1f\x02\xb4\xc2\x71\xa1\xfb\xd2\x54\x38\xee\x51\x55\x56\xab\x8c\xab\xab\xac\x9b\xd1\x93\x3c\x8c\x10\x93\x8e\x85\xf5\xd5\x41\x29\xc2\xe8\x02\x4f\xd4\xfb\xa3\x56\x9a\xd1\xe9\x67\x51\x13\x5e\x3b\x91\x6c\x48\xe8\x02\x3d\xf5\x5d\xec\x21\xe1\x24\xdf\x86\x37\x46\xcc\x3d\xad\xc5\xfb\xaf\x47\x46\xf1\x44\xb4\x94\x23\xe9\xf8\xe8\x93\xf1\x14\x8b\xd0\x7e\x06\x97\x14\x59\x56\x49\xaa\x0d\x81\x02\x0a\xb2\x5f\x3f\x01\x3a\x36\x61\xdd\xc7\x90\x9c\x48\x67\xac\xca\x32\x8e\xcb\x1f\x96\xdd\x5d\xf8\xce\xd8\x18\xc0\x22\x42\xd8\x83\xd8\x14\x4e\xe6\x4e\x71\xa0\x97\x5e\xed\xeb\x3d\xb5\x15\xc2\xf8\x66\x7f\xc1\x89\xfa\xf7\xc4\xa8\x61\xb2\xf1\xcf\xbe\xc1\xd3\x0a\x35\xea\x83\x07\x6d\x6f\xb1\x96\x1f\x63\xca\x12\x7f\x81\xad\xe6\x30\x9d\x08\x7d\x04\xe3\x52\x76\x72\x36\xda\x49\xdb\xdf\xc6\xfc\x54\x86\x6d\x2a\xc4\x6d\xca\xa5\x35\x58\x80\x15\xa3\xf4\xd1\x88\x62\x6f\x10\xb3\xb7\x0e\x38\x8a\x68\x4b\x92\xb5\xc7\x6a\x0b\x5d\x76\xe9\x5e\x01\x2c\x49\x4d\x7f\x30\x53\xd3\x42\xe2\x2d\x35\xcf\xdb\x9e\xb2\xcf\x1c\x96\x03\x4b\x4d\x58\xbc\x8f\x8c\xda\xee\x6b\xa2\x27\xd4\xce\x77\xd7\xb2\xe1\x28\x10\xa2\x4c\x3b\x07\x9a\x9a\x56\x51\xd8\xd7\x32\x06\x27\x88\xa5\x4d\x8d\x58\x23\x4f\x2c\x55\xda\x24\xb7\x7e\x80\xce\x29\x3a\x15\xae\x75\xee\x4c\x38\x59\x9e\x93\x8b\x23\x55\x40\x9e\xe7\x6b\xaa\xc3\x2a\xc5\xb8\xce\x46\x0b\xd5\xb9\x5b\xb4\x3a\x8b\x62\xa6\xbc\x5c\xfe\xc0\x4f\x07\x86\x2f\xd9\xda\x66\x4e\x38\xc0\xd1\x79\xb5\xb6\x4e\x59\xb7\x05\x69\x78\x28\x0d\x1c\xc4\xb7\xf1\x0e\xd1\x78\xca\xfd\x82\x12\x5b\xba\xa9\x5b\x7f\xc5\x2d\xe1\x41\xe9\x52\x3a\x74\x4f\x6c\xdb\xb1\xac\x1c\x70\xea\x5e\x8b\xe8\x0e\x67\x20\x3a\x77\xce\x40\x4f\xc0\x39\x83\xea\x32\xa9\x9f\xa5\x6e\xe2\x59\x0e\x49\xda\xcb\x80\xc9\x96\x99\x6a\x99\x96\x2d\xe3\x7a\xcb\x49\xa3\x65\xa1\x49\x4a\xd2\x4e\x66\xe9\xfa\x14\x5f\x39\x0c\xc8\xb2\xa6\x46\x0a\x41\x5a\xd8\xe3\xe1\x13\x7c\x79\xe8\xb3\x60\x6e\xe5\x90\x15\xc9\x7b\x67\x56\x0e\x5e\xba\xc6\xd5\xd4\xfd\x2f\xb1\x22\x41\xba\xe6\x22\xde\xf9\xaf\x2a\x19\x78\x49\x58\x75\x04\x6b\xb6\xe1\x8a\x26\xb2\xb5\xbb\x74\x1b\x5d\xf2\xd9\x99\x70\x07\x22\xe3\x7e\x6e\x33\xfa\x78\x74\x8a\xaf\x6a\x82\x7f\xe1\xe7\x2e\x42\xfb\xb0\x9d\xc0\x27\x74\x7b\x1a\x5c\xdc\x2e\x01\x8f\xc8\x12\x1e\x27\x92\x06\x7b\xa9\x2d\x2f\xa7\xba\xa7\x7f\xb7\xfe\xbd\x76\x91\x13\x8b\xca\x53\xe5\x2e\xf6\xfb\x26\x50\x44\x4a\x10\x27\x8a\x65\x39\xd5\x09\xac\xbd\x37\xae\xf5\xde\x00\x71\x01\xf9\x0c\x51\x0a\x98\x0f\xd2\xca\xf9\xad\x27\x4d\x5d\x33\x43\x50\xe7\x0d\x48\x6a\x83\x8f\x8e\x3c\x78\xe3\xf3\xff\x3f\x4f\x6c\xfb\x1b\x6f\xf2\xcf\xca\x9b\xbc\x80\x96\xd9\xbe\xc7\x74\x49\xad\xb7\x76\x2c\x84\x02\x87\xd2\xb5\x28\x7c\x12\x32\x9c\x4a\x4a\xae\xae\xfd\x12\xd4\x30\x4b\xbb\x6f\xbe\xc7\x7c\xc1\x1e\x7b\xf0\xc2\x87\x34\x55\xf7\xda\x38\xed\xbc\x58\x3c\xcf\x60\x96\xca\xc3\x2f\x34\xb5\xba\x6a\xd4\x2f\x7c\x9b\xf7\x23\xfe\xf2\xae\x96\xbd\x5d\x85\xaa\xab\x79\xea\x86\xc8\x4f\xe0\x20\x82\xd6\x2d\x55\x55\x09\x12\x71\x62\xd4\x6e\x4a\xbc\xea\x92\xa7\xf3\x9b\x50\x45\x45\xdb\x82\x45\x82\x8e\x13\x85\xad\x3c\x53\x6a\x6c\x17\xe9\xb2\xd6\x79\x33\x34\x96\x25\xaf\x1d\x06\x47\x43\xc5\xb1\xf8\xf8\xca\x94\x3b\x6e\x71\x13\xb9\xb8\xea\xf2\xee\xc3\xa4\x43\xf2\x70\xa7\x2a\xc6\x39\xfb\x86\x31\x15\xc7\xea\x2d\x07\xa5\x81\xa2\x75\xd4\x2d\x78\xee\xeb\xb4\x52\x59\xfd\xed\x81\x25\xa7\x70\xce\xf1\x80\xe7\x85\x3e\xf3\x2d\x39\xa3\x90\x99\x02\x3a\xf6\x0a\x35\x90\x7c\x38\xb5\xe1\x24\x41\x73\xb1\x37\x16\x69\xa7\x97\xe2\x4b\x29\xe3\xe8\xb6\xe6\x2a\x78\xea\xe2\xca\x26\x38\xbb\xd4\x02\x9a\x22\x6a\x72\xf0\xae\xb7\xed\x17\x1f\x45\xe8\xbd\x0f\x18\xce\x53\x39\x1e\x23\x8a\xea\x62\x55\x9a\x63\xdd\xd3\x47\x61\x6a\x69\x80\x49\xa0\x9c\xf0\xb5\x0b\x8d\x88\x1b\xa1\xfd\x08\x18\xec\x24\x52\x86\x2b\xd1\xd2\xce\x61\x6a\x64\x0f\x85\xb7\x79\x0a\xfb\x26\xf0\x76\xd1\xc5\x2a\x22\x81\x35\xf3\xe3\x14\x5b\x70\x2e\x19\x67\xde\xd3\x15\x5f\xc0\x5d\x0f\x92\x14\x22\x24\x02\x29\x6c\xfd\x5d\xec\xdd\xdb\x7d\xef\x7b\x48\x03\xd9\x86\x67\x1e\xd2\x0c\x98\x2d\x7f\x29\x4f\x0c\xf2\x47\xc1\x5f\xd9\x36\x4c\x53\x54\x72\x95\xea\x77\xc9\x11\x72\x44\x38\x56\x03\x34\xbd\xc4\xa3\x24\x05\x06\x67\xf2\x7f\xe2\x22\x50\x1f\x91\x6a\xb9\x35\x26\x1b\x2e\x78\xab\x45\xdc\x88\x66\xe1\xe7\x9e\x0d\xa7\xbd\x25\xaa\x59\xcf\x3d\x91\x8b\xc3\x88\x89\xb6\x8f\xba\x47\xdc\xa4\x52\x11\x7a\x02\xb1\xa2\x73\xab\x7b\x2b\xe6\x95\xe0\x8b\xd6\x94\x6c\xb8\xec\x40\x9a\xb5\x0f\xcc\x7f\xbb\xa7\xfb\xbc\x97\xe0\x8b\x2d\xd9\xb6\x6b\xf1\x6b\x84\x9f\xae\x3a\xf1\x7c\x44\x52\x21\x09\x81\x4c\xfc\x9d\xf0\x5b\x87\xc4\xe6\xc7\xa9\x2b\x26\x24\x89\x95\x0d\xdb\xa9\x7b\x2d\xdf\xfe\x69\x5a\xdd\x88\x30\xf5\x83\x53\x11\x02\xea\x35\xc5\x69\x8a\x43\xe7\xce\x04\x54\xc1\x63\xce\x76\x72\xee\xf6\x65\x6a\xf2\xe6\xad\x98\xc8\xa2\x55\xd6\x6e\x8b\xd6\x9a\xc2\x15\xf1\xf1\x4b\x42\x96\x56\x6e\xc3\x5b\xd3\x66\x57\x65\xde\x09\x47\x43\x87\x65\x0b\x85\x29\xd1\x5e\x4f\x2d\xd1\x77\x94\x9c\x3c\xd6\x83\x29\x6a\x1d\xb6\xe9\x5b\xad\xe6\x2e\x8e\x31\xc3\x4f\xc4\x12\xa8\x5e\xab\xf6\xd8\xb9\x0d\x3b\x2b\x5a\xd8\x0e\xc3\xbe\xea\x67\xa9\x7b\x1d\x47\x29\x73\x9e\x27\x30\x8b\x70\x1c\x2a\x08\xcb\x1f\xf5\x75\x51\x8a\x1a\xb5\xb4\x19\x09\x32\xb5\x44\x14\xa7\x59\xcc\xd2\x67\xe4\x1c\x53\x99\x62\x5e\xc8\xab\x29\x3e\xc2\xb1\x90\xbc\x89\x31\x09\xc1\x7c\xba\x96\xdb\x25\x31\x52\x56\x19\x28\xd5\xe3\xc4\xc5\xe8\x92\x76\xb7\xa4\x18\x66\xd0\x1c\x65\x66\x1a\x90\x67\xc0\x8a\x83\x95\x58\xf1\x44\x8f\xaa\x58\xdd\xfd\x9e\x3a\x6f\x6b\xe3\x28\xaa\xbc\xea\xa9\xf2\x84\x4f\xa2\x28\xf9\xfc\x9b\x10\xee\x75\x4f\x2d\x09\x84\xa2\xe8\xee\x9a\xb8\x89\xe3\xb0\x81\x54\xef\xd6\xc1\xc9\x76\xb5\xf7\xa9\x7b\x5d\x9c\x9e\xab\x31\xaf\x8a\xad\xa9\x5a\xbf\xb7\xf5\x1b\xee\xdb\xa2\x35\x13\x7e\xe6\xf0\x21\x5d\x69\xad\x50\x0e\x88\x15\xc3\xa0\x95\xce\x71\xbb\xef\xa4\xd1\x37\x69\x76\x1d\x18\xf0\xeb\x59\x71\x79\x7d\x1c\x67\x54\x57\x96\x60\xca\xe1\xcb\xed\x31\xe9\xeb\xfa\x2b\xfd\xb4\x0f\xe9\x04\xf1\x78\x7c\xf5\xb6\x14\x87\xc8\x4a\x6f\xca\xcb\x77\x18\xb1\x62\xb6\x56\x0e\x9f\x56\x6e\x95\x56\x63\x2f\x7a\xe7\xa7\x9a\x7e\x82\x39\xf8\xcb\x19\x7e\x5e\xbd\x7a\x92\x19\x11\x96\x92\xb2\x91\xc7\x3e\x75\xa8\x14\x5b\xf0\x4f\x0c\xf2\x78\xe3\xdf\x09\x30\x7f\xea\x10\xf0\x03\x16\x9d\xe3\xfd\x55\x66\x27\x47\x98\x1d\xfb\xd3\xd2\xee\xe4\x63\x2f\xbc\xd9\xb6\x68\xb5\x18\xfb\x0f\x3d\xa5\x8f\xc9\xc9\x49\x8c\xf7\x2b\x12\x31\x59\x87\xcd\x56\xd5\x39\x2a\x25\x73\xb2\x0a\xed\xa9\x72\x98\x9e\x3c\x21\xf4\xa9\x02\x45\x51\x05\xaf\xac\xf2\x44\x83\xac\xa8\x93\xac\xac\xf3\xb6\x84\x7f\x51\x8b\xcc\x8a\xb0\x97\x7c\x65\xb7\x25\xe3\x98\x43\xd0\xd3\x9a\x2c\xd4\xc4\x84\xac\x68\x49\x4c\x87\xaf\x4b\x0e\x5e\xd9\xbc\x18\xb0\x4c\xf5\x67\xae\xc6\x8a\x27\x51\x0d\x2d\xde\xa7\x25\x5e\x9c\xa5\x15\xc4\xd8\x4e\x05\x66\x78\xb3\x12\x35\xce\x72\x48\x67\x2b\xad\x11\xd5\x9a\xeb\x17\x31\x59\x5b\xab\x3c\xe1\xa4\xfa\x76\x62\x2d\xd5\xef\xa6\xaa\x10\xbe\x5c\x46\x7c\x5b\xe7\x39\xcc\x66\xae\x8f\xf6\x22\xb8\x33\x01\xcb\x02\xcb\xb2\x21\x9e\xb9\x6b\x9c\x9a\x51\xe8\x30\x08\x28\xf6\xc5\x3d\xd0\xa1\xa0\x82\xef\x72\xda\xa5\x6d\x90\x13\xc0\x49\x28\x8d\x91\xa5\x33\xc5\x70\x9b\x39\x01\x14\x9c\x54\x06\x92\x6f\x93\x67\x63\x68\x5c\x21\x5e\x02\x8b\xf5\x58\x16\xa0\xdf\xd3\xc3\x87\xf9\xcc\xe5\x23\xb1\xac\xca\x50\xf8\x0f\x35\x16\x4e\xc4\xf5\x60\xc6\x7a\x30\xe3\xca\x60\xc6\xd0\x64\x16\xb5\x63\xa4\x59\xcb\x83\x80\x1a\xab\x1a\xd1\x72\x96\xe7\x70\x5e\x0c\x49\x43\x3e\x87\x45\x91\xa6\x56\x2a\x87\x93\x99\x7b\xad\xd9\x5f\x8e\x20\x2d\x2c\x58\xcc\x04\x75\xdf\x21\xc9\x2c\xa2\x0b\x21\x4c\xd8\x15\xde\x10\x38\x4e\x4c\x67\x3d\x5c\x69\xd1\x2c\x13\x0d\xf1\x65\xc8\x12\xc5\x82\xf6\x44\x4d\xac\x54\x2b\x07\x43\x45\x13\xb8\x6b\x28\xc9\xad\x28\xd7\xd5\x37\xec\xf8\xe3\xfa\xde\x3d\xd2\xb7\x94\x1c\x2e\x7a\x5a\xd3\xc5\x44\x9d\xa2\xad\xd3\xd9\x2a\x46\x23\x65\x94\x5c\xa9\xca\x0d\xa6\xe1\x68\x45\x65\x05\x9d\xde\x36\x2e\xcb\x45\xe7\x6b\x5e\x92\x87\x0e\xf0\x72\xd6\xe1\xf1\x1a\x4b\xed\x30\xdd\x16\xed\x6a\x0a\xf7\xae\xd4\x5b\x2c\x5e\xaf\x8b\x95\xda\xfe\x0b\x26\xfb\xb2\x67\x7d\xf6\x93\x88\xa9\x5a\xef\x23\x7c\x51\xac\xd0\xdb\x55\x14\x59\x90\xdd\xf4\x35\xc5\xe7\xd5\x6a\x7b\xab\x51\xa1\x49\xc9\x0f\x4d\x55\x06\x3b\x14\x4d\x85\x58\xb3\x47\x95\x4f\x45\xc4\xd9\x99\x75\xfa\x41\x50\x41\x13\xe1\xdc\x8f\xa3\x50\x2c\xc2\x91\xa0\x0f\xfd\x0e\x26\xf6\x13\x51\xbe\x5c\x84\xb3\x02\xf5\xdf\x8b\x8c\x1c\x9e\xcc\xfa\xde\x00\x6b\x0a\x33\x67\x33\x67\x67\xa6\xde\xf8\xe1\xa0\x6b\x39\x4b\x97\xb6\x14\xae\x9b\xc3\x7d\x32\x43\x0c\x51\x15\x47\x52\xc6\x7f\xdc\x9f\xb5\x7d\x56\xbc\x32\x02\xbf\x0b\x06\xfb\x9c\x46\x3e\x5f\x77\x3c\x5d\x4d\xf0\xb1\xbc\xee\x03\x86\x74\x5c\xf1\x8a\x43\x80\x7f\xd9\xea\x91\x47\x24\xa8\xc0\x98\xda\x9d\x08\x1d\xa9\x2f\x7e\x15\xe9\x6b\x73\x10\xa1\x7d\x93\x94\x45\x9c\x95\x0c\xa8\x78\xfb\xd0\xcd\xd7\xbc\xcb\x14\x2a\x2f\x64\x59\x3d\xb6\xf7\xce\x0a\x8d\x86\x03\x11\x1a\x46\xa4\x56\xde\x7d\x2a\xb9\x6d\x15\x91\x33\xe1\xd7\x25\x87\x77\xb3\xfe\xb7\x99\xf7\xac\x3f\xe4\x73\x55\xa2\x49\xa5\x73\xcd\xf7\x0c\xf6\x22\x84\x35\x60\x6c\x38\x9c\x21\x2c\x00\xa9\x81\xb7\x5b\x04\xe4\xd5\xf8\x61\xe7\xf0\x9e\x9f\xbc\x0a\xaa\x77\x26\xa0\x97\x80\x33\x10\x05\xf8\x2d\xcb\xce\xe1\x83\xe1\x88\x56\x05\xf5\x31\xad\x7e\x16\x47\xb5\xfa\xad\xce\x6b\xf5\x4b\x2b\xbc\xe9\xdf\x26\x29\x4f\x0e\xcf\x66\xdd\x3a\x53\x05\xbe\x7d\x98\xc1\x75\xb5\xb3\x3d\x5f\x04\x41\x28\xfb\xe3\x09\x1b\xbf\x6c\xe2\x9f\xed\x7a\xbf\xea\x89\xeb\xcc\x47\x32\xd3\xae\xcf\x89\x55\x46\xf5\x06\xd1\x66\x34\xdf\xf7\x2d\x9e\xc2\x11\x4f\xe4\x66\xe1\x2d\xbc\x9e\xc1\xee\x4c\x0a\x6f\xa9\xdc\x91\x5f\x56\xef\x82\x08\x1d\xcc\xe0\x70\x06\xf5\xad\xa0\x10\xd5\xb8\x0d\xbe\xb6\xf7\x67\xa7\xc7\x3e\xa1\xb3\xc7\x27\x71\xe9\x23\x6a\x8b\xa0\xfe\x8a\x12\xe1\x8a\xd3\xc0\x22\x65\x52\x73\x7b\xae\x1c\xf2\xd5\x5f\xa6\xb5\xc3\xbe\x44\x07\xfa\xda\xf1\x93\x7f\x17\x24\x38\x4a\x06\x6c\x8e\x07\x4b\x3f\x65\x92\x10\x27\xb6\x8e\x2d\xc7\x5b\xca\x6d\x78\x6a\x04\x07\x60\x97\x8e\xf4\xea\x3e\x2a\xb9\x55\x3a\x8a\xc2\xca\x72\x95\x80\x2a\xd2\x4a\x84\xac\x64\xca\x94\x0a\x72\x8a\xbc\x4b\x1f\x70\x81\x30\x22\xe5\xeb\xac\x88\x5a\x0d\x74\x24\x73\x2a\xc8\x23\xca\x1c\xf8\x40\x47\x3a\xa9\x82\x2b\x11\xfa\x0c\x5f\x78\x6f\x3a\xc5\xe6\x57\xe1\xd5\xb3\x83\xc4\xd5\x5d\x75\x4f\x54\x90\x41\xc3\x1c\x65\x7a\x6b\x7a\x1d\xdb\x21\xe9\xdc\x09\xc9\x50\x3c\x7c\xd6\x26\xf3\xba\x39\x99\x4f\x6b\x2f\xd5\xe0\x15\x43\x31\xfa\xc0\xa0\xa6\x29\xd0\xb8\x82\x97\x5b\x79\x3e\x83\x72\xce\x6a\x66\xac\x1c\x0c\xae\x00\xa2\xe6\x1c\x49\x4d\x2e\x10\xfb\xea\xb0\x02\x0a\xbd\x86\x3e\xfa\x00\xef\x66\x9c\xf6\x55\x36\xac\x5d\x9d\x96\xaa\xa6\xdb\xd7\x15\x2f\xfd\x12\x11\x22\xf4\x75\x56\xbc\x4f\xeb\xa5\xaa\x10\xd1\x17\x33\xf7\x7a\x46\xe8\xc2\xf9\x30\xab\xf8\x74\xaa\x72\x8b\x39\x7c\xee\xe3\x09\x45\x65\x56\xa9\x4b\x75\x55\xa9\xe2\xb0\xca\xbf\xd4\x2d\x6f\x71\x05\x06\x54\x2f\x71\xbd\x7e\xbc\x94\x4f\x29\x45\x86\x0a\x02\xd4\xcf\xa1\x2a\x36\x6e\x47\x8c\xab\x22\x0c\x59\x93\xf3\x2b\xe5\x21\xdd\x87\x81\x16\x94\x61\xad\x56\xf2\x84\x92\x85\x92\x66\xa7\xdb\x49\x78\x1c\x2d\xaa\x3c\x2e\x78\x9b\x72\xcc\x2c\xee\x67\x96\xcd\x0d\x36\x0e\x5d\x1a\xf7\x88\xc6\x2a\x37\x9f\x52\x7c\xd2\x53\xa1\x87\x55\x4e\x62\xb7\x94\xdd\xf2\x1c\xdd\x6e\x0e\xa4\xc8\x92\x50\x2e\x73\x82\x9e\xbe\x2a\x32\xe9\x52\x4c\xb2\x02\x22\xb5\xd7\x0d\xb1\xfa\x0d\x68\x78\x3d\x1d\xbe\x97\xec\xa0\xae\xfe\x9e\xa3\x51\xd1\x73\x74\x9b\x9e\x2b\x55\x4b\xe6\x67\xfd\x9e\x5f\xfa\x8b\xb2\xe3\xf4\x36\x1d\x97\x35\x8b\x7e\x67\xb1\xdb\xe8\x65\x47\x6e\x3b\x2b\x87\x78\x25\xf8\x75\x59\x3d\x9a\xb0\xdd\x9a\xde\xd0\x56\x0e\xcb\xd5\xed\x15\xa5\x75\x8b\xf3\x56\x8b\x62\x3b\xe4\x70\xbe\xb2\xb1\x5d\x45\x21\x8a\xb6\x16\x2b\xab\xec\x09\xea\x52\x54\x38\x59\x59\xe1\xa8\xd0\x1f\x50\x55\xa6\x3d\x55\xe4\x83\x42\xed\x9d\x2a\xcf\xe1\xaa\x98\xe1\x76\x18\xea\xcc\x1c\x8e\x63\xa3\x91\x9b\x6e\x90\x5f\x84\x4f\x1c\x06\xd9\x52\x98\xa7\x53\x38\xc7\x34\x8d\x48\xb2\x9f\xcc\x08\x3f\x6a\xe2\x2c\x65\x98\x4a\x65\x74\x29\x2e\xb9\x88\xdd\x15\xc2\xe4\x29\xf5\x93\x60\xee\x30\x98\x66\x51\x1c\x0a\x5b\x78\x2a\xbf\xdf\xa5\x42\xf5\xed\x84\xbc\x97\xbd\x38\x09\xf0\x5d\x2c\x3e\x89\xee\x5a\xca\x93\x4f\xe3\x6e\x42\xa7\x28\xb0\x92\x5e\x51\x58\x62\x71\x30\x0a\x31\x47\x27\x1e\xab\x4a\x7e\x18\x52\x9c\x2a\x6f\x89\x97\xb1\x7b\x2d\x5b\x11\xf3\xe5\x67\xd3\xe3\xb8\x7a\x45\x94\x13\x17\x77\xfc\x1c\xb6\x7b\xd6\x84\x13\x49\xad\x5d\x22\xd7\xe3\xa5\xa9\xb4\xc9\x1c\xde\xa0\xc4\x5a\x24\x25\xed\x24\xd2\x4e\x0a\xda\x49\x59\x3b\xc9\x6b\x27\x45\xed\x24\xbf\x9d\x94\xb6\x93\x66\xed\xa4\xb8\x29\xd5\x39\x90\x8f\x90\x69\x29\x27\x29\xdd\x3c\x3e\xe1\x87\x3c\x96\x07\xbb\x28\x97\x00\x25\xd2\x5d\x99\x14\xde\x39\x81\x5e\xde\x0c\xa6\x7e\x8a\x5f\xfb\x6c\xee\x78\xe0\x2f\xa3\x77\x34\x76\x22\x88\xa3\x29\xff\xf0\xa1\x08\x6b\xb0\x73\x74\xe4\xa4\x30\x23\x09\xdb\xbe\xc0\x29\x59\x60\x9e\x30\x03\x75\xeb\x14\x14\x81\x50\x27\xae\x07\x23\x83\xb7\x3d\x6b\x7a\x84\xd9\x6e\xad\x76\x29\xb0\xe9\x3b\xed\x6a\x23\x38\x20\x7e\x58\x15\xdb\xf4\x54\x7c\x5c\x99\x49\xa3\xda\x4e\x5c\xea\x75\x86\x11\xc5\x01\x2b\x1e\x01\xce\x8a\xac\x97\xfe\x79\x74\xc2\x09\x1b\x51\x98\x98\xc3\x93\x3e\x8c\x2d\x8b\x97\xeb\x55\xf4\x78\x70\x9b\x9a\x7c\x35\x5f\x56\x0e\xe9\xfd\xdb\x56\xde\x0b\xa3\xb2\xeb\x57\xb7\xa9\x5d\x13\xbf\x3d\x37\xc0\xe2\x25\x61\x4f\x48\x26\xdc\x98\xbd\x5e\xab\x61\x05\xd9\xe2\x75\xb7\xa7\x92\x14\xfa\x36\xf6\xfd\xbb\xd5\x15\x0c\xf0\x7e\xbf\x6e\x2d\x0e\xae\xa2\xd6\x87\x75\x6b\xd5\xc0\xf4\x6c\x65\xad\x6d\xbd\x2f\x8b\x3a\x5f\xe2\x4a\x5c\x8f\x03\x7c\x8e\xe3\xb7\x44\x3a\x8d\xfb\x5a\xe4\x48\x40\xe8\xf4\xa7\x7d\x3b\xab\x1c\x95\x2c\x5e\x3c\x96\xae\xae\xc4\x87\x55\xaf\xf4\x69\x75\x25\x85\xa1\xf5\x7a\x2f\xd6\xab\x27\x9e\x6d\x6b\x15\x3f\x97\x78\xa6\xb0\x4b\x4f\xfa\xe3\x2a\xae\x36\xad\xb7\xf4\x83\xf1\x90\x38\xf0\xcc\x3a\x6b\xc4\x28\x58\x61\x23\x6f\x2c\xec\x37\x99\x9d\xdb\x79\xcb\x88\x67\xd7\x83\x37\x31\x1c\xa7\x46\x33\x9a\x5d\x0f\xbe\xc6\xf0\xb8\x33\xf3\x53\x0c\x47\x9d\x99\x4f\x63\xb8\xe8\xcc\x7c\x11\xc3\x69\x67\xe6\xc7\x18\xae\x3a\x33\xbf\xc4\xf0\xce\xeb\x88\x6c\x67\x03\x0b\x8d\x2e\xd5\x5e\x56\xa3\x46\xff\xf1\xc7\x96\x65\x03\x1b\xcd\xfd\x74\x2e\x7c\xab\x95\xa2\x4c\xe9\xd9\xed\x53\xe9\x6b\xad\x19\x15\x84\x43\xd3\xb1\xac\x1c\xd9\x90\xb4\xdc\x7e\xe2\x33\xf4\x05\x51\x1b\x36\xed\x4a\x4b\xac\x1a\xf9\xb8\x15\x63\xa4\x50\xaa\xdc\xb2\x40\x44\x0a\xe1\x8d\xab\xc2\xa2\x17\xe1\xea\xc5\x83\x1f\x62\x28\x24\x00\x0c\xae\x53\xec\xd3\x60\xee\x24\xc0\xe7\xe0\xe0\xbc\xdd\x03\x91\x3d\x10\x3e\xde\xcf\x71\x0e\x34\x34\x9b\xc0\x4f\xe1\x7d\x53\x0f\x76\xce\xd8\xd2\xb9\x77\xcf\xa4\xe9\xaa\x23\x0b\xb5\x15\x5e\x21\x42\x53\x58\xca\xb0\xd0\x80\xc3\x16\x9b\xc5\x9c\x19\xa1\xe8\xd1\xa3\xc2\xf2\xf9\x51\x19\x98\x1c\xd7\x62\x7d\xd3\x47\x85\xf4\xac\x70\xc9\x13\xcd\x10\x0d\x51\xa2\xe0\x1a\xb8\xf4\x51\x33\x06\xbc\x0c\xc8\xae\x6c\x02\x83\x32\x82\x3b\x73\x09\xd0\x86\x41\x83\x10\xad\xb5\x67\xf7\x9a\x55\x8c\x6f\x03\x1d\xf8\x78\x60\x49\x1d\xd7\x60\xe4\x4d\xf2\xfc\x51\x40\x12\x16\x25\x19\x1e\xb0\xfc\x76\x4d\x4b\x6f\x37\xe2\x3e\xb4\x76\x23\x34\xcf\x71\x9c\x62\x31\xe9\xac\x9c\xf4\x1d\xd7\xcd\xe4\xf4\x4c\xb5\x5f\x97\xb5\x1f\x89\xda\x15\xc0\x64\xfd\x80\xa9\x41\x20\x53\x10\xa8\x5b\x8c\x26\xca\x7a\x3c\xe3\xe0\x58\x35\x91\x5a\x7b\xaa\xb6\x9a\x97\xd8\xad\x89\x11\x29\x29\xaf\x85\x43\x38\xa1\x88\xd9\xf5\x18\x65\x39\x10\xd3\x06\x7f\x4b\x51\x5f\x4c\x03\xe6\x44\x68\x8f\xc2\x15\x13\x2f\x46\x22\x86\x81\xfc\x98\xd8\x39\x04\xc6\x31\x74\xc5\x1c\xe2\x44\x7a\x20\xfe\x1d\x5e\xf8\x34\xe1\xfd\xac\x11\x03\x88\x84\xc2\xac\xa0\x1d\x9d\x22\x0b\xdd\x95\xd1\xf9\x1e\x9b\x06\x32\xf3\x07\x33\x7f\x18\x90\x13\xfe\x27\x5d\x46\x09\xff\x7b\xff\x92\xff\x3b\xbb\x7d\x50\xa4\x6a\x60\xb8\x4a\x27\x29\x1d\x92\x24\x5e\x1d\xfc\x23\x22\x48\x1b\xb1\x8e\x46\xa3\xfe\x38\x81\x45\x70\x86\xb0\x5b\xc8\x37\x88\xd0\x81\x61\x3c\x15\x54\xba\x18\x4e\xc6\xe3\x81\x05\xd4\x64\xfe\xf9\x86\x20\x53\xd0\x8d\x59\x50\x8f\xe0\xaa\x15\xf5\xab\xa0\xe9\xd5\x21\x18\x44\xe8\xa2\x7f\x58\x16\x60\xd3\x80\x5e\x34\x82\x11\x96\x91\x4d\x92\x9e\x01\xf5\x22\x40\xad\x53\x03\x6e\xf5\x47\x3a\x5c\x35\x4d\x13\xee\x57\x7a\x0c\x87\xb3\x18\x5f\x0e\xf8\x3f\xc3\x80\xc4\xd9\x22\x19\x34\x67\x6e\x8e\x63\xf1\xa4\x1f\xd3\x4f\x57\xc4\xa1\x6c\x87\x6b\x58\x2f\x24\xe5\xab\xe6\x74\xde\x98\x17\x64\x66\x5c\x90\x5e\x50\xfe\x5f\x07\xcb\xd6\xc6\xfc\x8b\x61\xd9\x25\x3c\x92\x47\x60\x30\x6a\x3c\x97\x6b\x4b\xfc\xac\xfa\xf2\x2c\x15\x0a\x9c\xef\x58\x82\x32\xe2\xe5\x60\xee\xa7\xc3\x54\x9a\xf6\xff\x73\x56\xa6\x1d\xe3\x64\xbd\x95\x69\x5a\x60\xbf\x21\x28\xd0\xcf\x32\x2b\x97\x47\x47\x5c\x09\x8c\x91\xac\x8b\x20\xa0\xfc\xbc\xa7\x24\x1e\x54\x7f\x68\xe8\x18\x02\x46\xae\x5c\x70\xb3\x63\x84\xef\x5c\xb1\xff\x5d\x25\xb9\x30\xdf\xb4\x20\x2d\x4f\x1d\xdf\xbd\x79\x42\x3f\x39\xc1\xf4\x7f\x57\xc5\xb8\x77\x24\x70\x6e\xb5\x52\xfd\x51\xa1\x6a\xad\xcf\x30\x0e\xa7\x7e\x70\xba\x0e\x07\x97\x19\xe3\x54\xb6\xc7\x25\x9d\x90\x44\x61\xb7\xd6\x49\x75\x15\xab\x23\x7b\x38\x08\xa3\xe9\x60\x31\xdd\x1c\x2c\xe8\xe6\x40\x21\x8e\x1f\x47\x27\x89\x08\xe3\x9c\x0e\x03\x9c\xac\x13\xd7\xce\x70\x08\x3d\x25\xc8\x0a\xe6\x38\x38\x9d\x92\x4b\x53\x10\xb9\x1f\xcc\x87\x54\xba\x06\x4b\xb8\x36\xb7\xbc\x8c\x87\x9b\xeb\x00\xba\x7e\x23\x32\xdd\x0b\x8c\x07\xa3\xdf\x0b\x71\x13\x63\x6a\x62\x82\x97\xc6\x19\xdf\x96\xe5\x94\xb7\x8f\xfb\x2d\x06\x7c\x3d\xd6\x33\xed\xb8\x71\x99\x2d\xe2\x4a\x8d\x1b\x5a\x51\xae\x69\xfa\x3c\x6a\xcd\xff\x05\x41\xa6\xbd\xfb\x99\x20\xcb\x9b\xc6\x7e\x62\xd8\x13\x86\xb5\x6a\xc3\xaa\x50\xc9\x89\x88\xd6\x3f\x4c\x42\xa9\xb3\x34\x6b\x4b\x3d\xb4\xac\xa3\x7d\x35\xc5\x5a\x02\x64\xc4\xa5\x29\x4b\x06\x53\x96\x0c\xd3\xc5\x60\x7a\x32\x9c\xf9\x21\x0e\xe5\x6f\x11\x29\xc2\xa7\x57\x83\x05\x1d\x6e\x0e\x16\xd3\x06\xca\xa9\x26\xd6\x0a\x74\x97\xa5\x98\x0e\x53\x6d\xc2\x32\x71\x2c\x86\x2f\x8d\x01\xee\x4d\x95\x87\x0b\xf2\x75\xf8\x7d\x2d\x5c\xe0\xe9\x69\xc4\xd6\x68\x44\x13\x9e\x35\xd6\xcb\x40\xff\x9d\x8e\x80\x93\xdf\x09\x62\xbe\x91\x8c\xd1\x10\x5b\x7b\xc9\xb8\xc0\x7c\x92\xc3\x45\x26\xec\x72\x57\x93\x8c\x75\x8e\xb5\xdc\x86\x38\xec\x79\xcc\x1d\x44\xe8\xca\x34\x92\xc4\x3f\x6f\x47\xd1\x37\x8d\xa3\xb0\x7d\xee\x42\x5a\xde\x52\x1c\x25\xa7\x03\x65\xa1\xd1\x6e\x30\xe1\xab\x61\x22\x55\x45\xdd\x2e\x50\x9b\xe4\x27\xbc\x3d\x13\x18\xc2\xb0\x2b\x14\x89\x8f\xde\xf5\x6b\x8b\x1a\x82\xf5\xe6\x85\x43\xd6\x65\x4f\xbb\x35\xa7\x87\x55\xa8\xfb\xe8\x1c\x03\xe5\x84\xc4\x20\xb3\x3f\xa8\x7a\x5a\xd0\x7b\xb7\x05\x35\x11\x3f\xf7\x36\x3a\xae\xc2\x89\xac\x50\xb7\x4a\x44\x2c\x60\x2c\xc7\x3f\x37\x89\xce\x98\x56\x8c\xdc\xb2\xdc\xff\xb2\x1c\xcb\xb5\x4a\xa2\x7a\x49\x81\x36\x3d\x03\x08\x2d\xcb\xf6\x1a\x9d\x22\xd6\xe6\x97\x8a\x88\x8a\xe7\x1d\x14\x5f\x79\x80\xe2\xa4\x7f\x1e\x4a\xd1\xf1\xa2\x76\xcc\x35\x31\x38\x6c\x68\xfb\x26\x15\xfd\x38\x11\xc2\x95\xd9\x5b\x18\x25\xb6\x93\xe4\xb6\x9c\xfc\x49\xbf\x9c\xa9\x72\xe6\x94\xc9\x0c\x61\x7b\x8b\x3a\x38\x97\x70\x8b\xd0\x33\xd3\xc3\xca\x15\x3a\x90\x74\xff\xcc\xb6\x61\xda\xa6\xfd\x75\x79\x37\x7d\x74\x5d\x4a\x6f\xeb\x02\xef\xb3\x52\xe0\x2d\x24\xdd\x32\xbc\xcb\xc8\x1b\x73\x88\xa8\x32\x9f\x50\x62\x3f\x62\x2e\x03\xea\x26\x82\x16\x5e\x75\x80\xd4\x0b\xc0\x3a\xc5\x57\xd9\x52\xf9\x8f\x60\x90\x04\xc2\x1b\x42\x7f\xf9\x90\x5c\x24\x8d\x1a\x17\xa1\x7b\x5d\xd8\x00\x3b\xbf\x82\x60\xce\x9c\xc9\x7d\xc8\x96\xce\xfd\x5f\x81\xd7\x70\x1e\x8c\x73\x38\xbd\x8d\x00\x35\x20\xf1\x20\x20\xf1\xd0\xcf\x18\xf9\xd6\xc0\xa7\x9c\x4a\xcb\xeb\x85\x99\x42\x9b\x9b\xea\x3d\x04\x48\xc6\xe2\x28\xc1\xc3\x28\x99\x91\x0e\x12\x14\xa1\xc3\x14\xee\x8c\x4d\x0c\x9b\x89\xc9\x4b\x8d\x12\x5f\x13\x33\xb9\xd6\xc0\x0c\xf7\x84\xe6\xd0\x26\x6b\x0e\xcd\xfa\xff\xfe\xdf\x35\x45\xb4\x2d\x71\xf5\x51\x27\xe7\x76\x1a\x8a\x98\x05\x97\x1d\x38\x93\xc3\x63\x23\xf1\x11\xfa\xb0\x5a\xb1\x52\x28\xf7\x56\xdc\x0a\x00\xe9\x8c\xfb\xc0\xe0\x32\x1c\x15\x1d\xd9\x5b\x7b\x29\xba\x33\xb1\x9d\x97\x69\x0e\x81\x7b\x12\x72\x02\x98\xb9\xcb\x54\xdc\xd3\xaa\xcf\x74\xd5\x36\x12\xe1\xd4\xda\xb2\x9c\xe2\xcd\x2c\x53\x2e\x92\x2a\x22\x1f\xcb\xb1\xca\x3b\xac\x78\x90\xab\x3b\xaa\xd3\xdb\x55\x0c\x48\xcc\xb6\xd8\xb2\x9c\xb4\xbf\x4c\x05\xf5\xde\x49\xd1\x9d\xb1\x0d\x99\x6d\x3f\xaa\x55\x28\x67\x50\xb6\x24\x86\xd5\xa3\x91\x4e\x47\x4d\xc3\x7c\xf1\x3a\x65\x0a\x74\x8f\x95\x7e\xfa\x9d\x89\xd2\x57\xaf\xc4\xb7\x2f\x03\xcb\x6b\xc4\x56\xda\xea\x02\x8a\x6a\x0a\x7b\x62\xdc\xfa\x17\x87\x6e\xea\x0a\x7c\x33\xcc\xcc\x86\x99\x2b\x5d\x13\xc3\x59\x3d\x50\x75\x1b\xbb\x29\xb9\x18\x24\x64\x78\x92\x31\x86\x69\x5a\xbb\x03\x0a\x25\x5c\xc3\x76\x2e\x6f\x1f\x47\x62\x79\xd7\xa1\x14\x95\x1b\x0b\xa7\x3b\x16\x78\x26\xe9\xfc\x5a\xcc\xf2\x22\x4a\x86\x17\x51\xc8\xa4\xa7\x6c\x6b\x73\x3c\x5e\x5e\xfe\x75\xe1\xa0\xa3\x64\x99\xb1\xa1\xf2\xeb\x72\xfb\xdb\xef\x33\xa2\x7d\x97\x0c\xa7\x3e\x1d\xaa\x2d\x64\x22\x16\xbd\x22\xa2\x52\xf6\x61\x12\x6f\x1c\x87\xc8\x37\x24\x5f\x85\x46\xa9\xc7\x2c\x40\x6f\x53\xf3\x2b\xfd\xb7\xdd\xae\x2b\x20\x1a\x4e\x59\xf2\xbd\x04\x7f\x49\xa3\x85\x4f\xaf\x4c\xf3\x67\x01\x9a\x99\x64\x05\xab\x5f\x6a\x08\xb2\x36\xd6\x20\xad\xfd\xb4\xb6\x18\xff\x51\xa7\x78\x87\x5f\x1e\x06\xb7\xbb\x41\x58\x3b\x59\xca\xc8\x62\xa0\x70\x03\x06\x78\x74\x32\x32\xcd\x7e\x05\xdc\x04\x7f\xaf\xae\x4d\x72\xdb\x4e\xfd\x14\xf3\x23\xaa\xe3\x6c\x7a\x9b\xa2\x7f\xc7\xc9\xb9\x6b\x2d\x29\x09\x33\x41\x37\xad\x7f\x5f\xeb\x9c\x32\x54\xfb\x86\x53\xcb\x00\x7e\x3b\x87\xed\x8e\x83\xcc\x78\x37\x31\x31\x09\x83\x29\xa1\x21\xa6\xc3\xb1\x69\xda\x2f\x6a\xa4\xa7\xe2\x08\xc8\x28\xee\x31\xad\x96\x50\xc8\x32\x9d\xc0\x2f\xdb\x7c\x66\x61\x32\xaf\x5c\x39\x0b\x6b\xed\x9a\x21\x9e\x32\x1e\x77\x4a\xc9\x85\x65\xe9\x98\x2e\x35\xdb\xfa\xc1\xad\xb8\x91\x5e\x18\x2c\x03\xf4\x2e\x46\x11\x3a\x9a\x09\x8f\x48\xeb\x4d\x5b\x8e\xd4\x30\xf1\xb6\x58\xfa\xbf\x75\x9c\x52\xc5\xda\xb4\x40\xb9\x0d\x6f\x4d\x9c\x4e\x53\xba\xd5\x7d\xeb\x2c\x2e\x58\xea\x42\x95\xe7\xc0\x4a\x13\x1c\x21\x0e\xd3\x0b\x2a\x14\x89\xda\xab\xfe\xd7\x63\xf3\xa5\xd9\xd3\x9b\x01\x32\x6f\xb1\xb4\xad\x31\xad\x61\xaf\xcb\xb9\xca\x36\x31\x28\x1e\xb1\x51\x14\xb6\x53\xa5\x97\x30\x83\xa4\xa8\x47\x2e\xf8\xad\x20\x58\x43\x6a\xca\x11\x58\xb8\x2d\x33\xec\xdb\xbd\xfe\xbb\x77\x90\x3a\x59\x0a\xd8\x7d\x17\xa3\x2b\x61\x6a\x26\xf8\x79\xe9\xc6\x55\x22\x44\xc5\x97\xab\x46\x0c\xdb\xae\x4c\x74\x16\xc2\x01\x1f\xe4\x5c\x09\x23\x0f\xdb\x84\xa2\x28\xbb\x42\x22\xa5\x08\x7b\x8a\xe3\x99\x12\xc9\x8b\x8b\xd6\xed\x64\xdb\xac\xa1\x37\x54\xfe\xda\x16\x01\x58\x2b\xb9\x30\xb0\xe0\x25\x4f\x14\xff\x99\x24\x3a\x3b\x5d\x93\xb9\x0e\x62\x92\xe2\x43\xe9\xbc\xde\x39\xe0\x5b\xf9\x78\x66\xdb\xc0\xd9\x1b\x3f\x4a\x30\xdd\x89\xfd\x34\x75\xce\x54\x70\x03\xe1\x76\x7a\xb9\xe2\x0d\x49\x6d\xaf\x81\x36\x10\x32\x1c\x20\x32\x36\xc2\x01\xe2\xa5\xb7\x29\x1e\x5c\x91\x6c\x90\x66\xea\xe3\xc2\x4f\xd8\x80\x91\x81\x74\x39\x32\x60\xf3\x28\x1d\x28\xd4\xde\xb2\x38\x9b\x4c\x08\x53\x43\xe9\x17\x4c\x1a\x9e\x55\x1b\x44\xeb\xf4\x36\x44\x4b\x79\x35\x30\xcd\x47\xd8\xe3\xf7\x20\x4c\x4b\x70\xb8\x16\xcf\xbc\x24\x69\xa4\x2c\x63\x26\xd2\xbb\x66\x14\xf4\xf3\xcc\x15\x28\xb4\xee\x04\x83\x38\x4a\x35\x03\xc8\x93\x8b\x0d\x3b\x58\x0e\xc7\x83\xc5\x74\xf8\x60\x0d\x89\xbe\x99\xfd\x96\xda\x44\x8b\xe9\xd0\xf8\x2a\xd5\x75\x23\x69\x30\xbc\x06\x7b\xf8\xae\x03\xb9\x75\xe8\x1e\x86\x60\xed\x25\x61\x6a\x95\x86\xb4\x46\xf7\x36\xaa\xa8\x34\x07\xe2\x85\xb5\xc9\xa2\xe1\x80\x14\x6d\xaa\x83\xa2\x6c\x36\xe7\x57\xd8\x16\xc0\xb7\x43\x44\x47\x51\x68\xc8\x79\x1b\x1a\x1f\xce\x22\xf4\x32\x04\x0a\x77\x26\x26\x16\x7f\xfd\xc7\x4a\xe3\x3d\xef\x33\xec\x85\x55\xab\x53\xd3\xa8\x22\xc4\xb6\x84\xf0\x54\x8d\xc2\x76\xce\x8c\x4f\x95\x36\x3c\x09\x1b\x3a\x89\x8b\x59\xbb\xbd\x73\x43\xda\xb2\x65\xbb\x9e\xe7\x70\x60\x92\x4e\xca\x88\x60\x49\x11\x76\xb1\x2f\x28\x84\x81\xeb\x14\x9e\xf4\x83\x10\x59\x2f\x89\xa6\x13\xe9\x60\x26\x8c\x12\x6c\x27\x42\xe7\x81\x01\x70\xe5\x5e\xe8\x00\xe1\x9a\xbc\x86\x3c\x55\x23\x74\x16\x82\x12\xa0\x1e\x20\x9e\x6a\xdb\xc0\x71\x45\x88\x64\x5b\xde\x80\x3b\x1c\x45\xb0\x91\x1e\x7d\xfe\xbd\xbe\xb0\xcd\xcd\x33\x7f\x9a\x4b\xff\xd8\x44\x45\xb9\x51\xbb\xe4\x89\x1f\xc5\x19\x2d\x37\x54\x10\x22\x62\x0a\x3b\x92\x85\x1c\x39\xf7\x7b\x1e\x52\x53\x14\x87\x80\xc1\xa8\x48\xff\x2e\x46\x53\xe5\x9d\xa0\xa5\x31\x5e\x38\xa4\x18\x73\x9e\x6c\xab\x45\x7c\x49\x88\xd2\x99\x08\xea\xd7\x5c\xad\xe6\x46\xe9\x28\xdb\x7f\x39\x9e\xfa\xe1\x09\x1e\x88\x7f\x87\xcb\x28\x8e\xc9\x85\xfa\xa1\x00\xa0\xe8\x99\x38\xe2\x19\x59\x0e\x16\x6b\x3e\x55\x9f\xae\x12\x62\xaa\x7d\x81\x84\x7b\xdf\x57\x5d\xef\x9f\x3d\x91\x56\x22\x34\xed\x78\x0e\x1a\x24\xfe\xf9\x90\xf9\xd3\xb4\x83\xb6\xd7\xd1\xbc\xed\x1a\xc4\x47\xfb\x21\x30\xc0\x23\xe1\x1f\x0a\x30\x47\x1f\x3b\x57\x51\x2d\x9c\xef\xec\x37\x92\x8d\x8f\x39\x7d\x11\x73\x7f\xde\x2d\xde\x64\xfe\x54\x48\x36\xf5\xee\x30\xc9\xc6\x8c\xca\x2e\x46\x92\xd9\x31\xa8\x66\x5d\xa3\x06\x46\xd7\x5b\xe6\xa7\xd5\xf2\xa3\x4e\xae\xe2\x89\xf2\x99\xbb\x96\xa8\xdb\x23\x1d\x1b\xeb\x4a\x6d\xac\xc7\xfc\x20\x2a\xfc\x73\x99\x9c\x4b\xb7\x9b\xf5\xd1\x49\x00\xaf\x42\x41\x8b\x0d\x62\x1b\xb4\x08\xe0\x80\x1f\x28\x66\xd7\x51\xcd\x6a\xc5\xd1\x01\xaf\x3b\x64\x04\xc6\x57\xd4\xc5\x74\x73\x70\x31\xfc\x75\x3c\x8c\x07\x82\x9b\x18\x9a\xde\x53\x57\xba\xb9\x9f\x85\x70\x56\x0d\x3c\xd2\x50\xbf\x77\x2d\xe9\x0b\x98\x43\x8a\x8d\xa4\xa7\x75\xfe\xbd\xdb\x31\xd2\x13\xd3\x48\xf9\xd1\x31\x58\xfa\x63\x39\xce\x8e\x51\xbe\x56\xaf\x71\xef\x8c\x68\x6d\x0c\x72\x55\x9c\x74\x6d\xf5\x8c\x37\x08\x8b\x10\x6a\x9d\xbc\xd7\x1a\x08\x7d\xfe\x7d\x8a\x61\x95\xc3\x35\x1c\x14\xbe\xb5\x6f\x2d\xa9\xb3\x7b\x59\xc8\x7f\xfc\x34\x2a\xc8\x70\x54\x9f\x8d\x33\xb0\xe0\x14\x7d\x11\xe7\xc6\xed\x26\xa6\x5a\xdf\x0d\x4d\x77\xdc\x2e\x0d\xcd\x8a\x08\xa9\x19\xbe\x2a\x0b\xd7\x53\x22\xfc\x56\x63\x0a\x6a\x54\x54\xcb\x73\x78\x6f\x3a\xd8\xd5\xd3\x6a\xb9\xc7\x3c\x02\x41\x0c\xdd\x0f\x13\xdf\xfa\x2a\x19\x90\x78\xf8\xf3\xca\xca\x31\xf2\x42\x38\x20\xd2\xf3\x24\xa4\x31\xe7\xae\x7d\xf1\x6f\xa2\xfc\x17\xad\x43\x47\xff\xb2\x01\x44\xa2\x6b\x4f\x0d\xc0\xfc\x80\x7f\xbb\x11\x7c\x8f\x62\x9f\x8f\xa2\x10\x2c\xe5\x31\x23\xd1\xc2\x11\xc8\x62\x64\xb4\xf3\x60\x5b\x3e\xf2\x43\x28\x2f\xcc\xa5\xe6\x8e\x7a\x60\x06\x6b\xe6\x0f\x19\xf5\xd3\xf9\x90\x58\x30\x15\xed\x38\x91\xf1\xe2\x61\x54\x75\x14\xb1\x01\x43\x77\x4d\x69\x63\xff\x85\x3d\x89\xd7\x3a\x4f\x95\xdf\x92\xc1\x76\x27\x8d\x7a\x66\xa2\xc9\xad\x37\xce\xa6\xa9\xa1\xf2\x24\x61\x69\xf7\x27\x56\x8e\x2a\xd2\x23\xe3\xfc\x38\x97\x38\x58\xe3\xc1\x64\x19\x20\xb2\xd6\xe4\x0c\x6a\x4c\x39\x7c\xe9\xd6\x9a\x5b\x27\xca\x5e\x95\x12\x35\xa9\xd4\x3b\x7e\x79\xed\xbc\x22\xe0\xee\x2b\xc2\xd7\x5e\x5d\xcb\x15\x4f\x8d\x94\x5c\x0c\x2c\xb0\x16\x8c\xef\xc6\xb5\xb7\xa3\xb8\xd3\x5b\xa0\x76\xb1\x31\x2e\x4b\x8c\x4e\x62\x15\x2e\x39\x46\xf3\x98\x5f\xd1\xda\x8b\x51\x34\x58\xfa\x25\x91\xfb\xb2\xab\xcd\xf3\x7a\x9b\x26\xa5\xc9\xa2\xcd\xbd\x24\x5c\x35\xc4\x45\xbd\xb9\xf6\x92\xcb\x6b\xf9\xd3\xdb\x28\x8d\x48\x50\xde\x82\x2c\x1b\xcf\xd6\xef\x54\x2d\xb7\xb4\x6b\xa3\xc1\x9a\xcc\xae\xf1\xa6\xb6\xd6\x5b\x9d\xdc\xfb\x03\x7f\x36\x93\x81\x35\xa7\x57\x35\x29\xe2\xba\x16\x76\x6b\x52\xed\xf5\xce\x3c\xe3\x85\x62\xbd\x23\x47\xb0\x5f\xfe\xc2\x24\x49\x35\x0d\xf2\x3b\x7b\x92\x6e\x8f\xbe\xfb\xa9\xb0\x0b\xab\x84\x0e\xda\xfb\x10\xe9\x30\x73\xcc\x86\x89\xfd\xf7\xb1\xdd\x78\xd9\x2b\x4e\x34\xe3\x01\x25\x0f\xa6\x65\x9c\xa5\x16\xdf\x28\x57\xb1\xe1\xa6\xc3\x69\xe3\x9b\xef\xa1\x43\xfc\xa6\xb8\x3e\x21\xfa\x60\x78\x5f\x79\x16\x1a\x75\xc8\xd7\x39\x2e\x7a\xf5\x95\xd6\x7b\x4b\x79\x8b\x53\x6c\x7a\x4c\x31\x13\x94\x4f\x66\xdd\x57\x25\x9b\x13\xb1\xb5\x67\x84\x2e\x20\x6b\x9a\xfb\x27\xed\x30\x93\x49\x2d\xf8\x66\x4d\xa6\xbd\x17\x46\x6c\x50\x3a\x2b\x9b\x38\x34\x46\x89\x50\x03\x37\x8a\xc0\x5f\xe2\x8b\x5a\xe9\x08\xb1\x18\x30\x50\x25\x87\x15\xf6\xd8\x90\xf2\x3f\x93\xb5\xc5\x02\xb3\x15\x84\xaa\xed\x1c\xc1\x88\x98\x5f\x43\x08\x4a\xbf\x8a\x81\x12\x10\x43\x50\x71\xd7\xd8\xaa\xf5\x34\x44\x41\xc5\x1d\x60\xf7\x41\x51\x78\xc4\x91\xd8\xd7\x71\x56\x2c\xcb\xb3\x22\x8c\x6d\x08\xaa\x4e\x1b\xcd\x6d\xbf\xe2\x6d\x6b\x6f\x60\xbd\x6d\xc7\x65\xdb\x33\xd9\xb6\x76\xfc\xb8\x2e\x5d\x5c\xf3\xd4\xf9\x12\x02\x19\x15\xee\x08\x81\x8c\xe4\x7d\xcc\x08\xf3\x37\x21\x30\x08\xc0\xa0\x18\x63\x92\xa3\x4b\xc4\x7e\xd1\xc5\x1f\x29\x89\xe9\x01\x67\x6a\xb7\xda\xc3\x0f\x29\x59\x86\xe4\x42\xb2\xe0\x9d\x2a\xd9\x86\x97\x97\x5a\xc5\x6f\xb6\x2e\x08\x32\x9a\x12\x19\xf5\xd3\x5a\x92\x48\xf0\xff\xeb\xbc\xfd\x2c\x03\xf4\x34\x45\x74\x44\x85\x6b\x5e\x03\x58\x6a\xfb\x04\x9b\xae\x87\xe6\x7b\x54\x6e\xc3\xe7\x6e\x21\x5d\x33\xfa\x48\x45\x17\x31\x05\xe2\xd2\x51\x11\xaa\x04\x02\x37\x42\x3b\x70\x12\xa2\xc4\x16\xa2\xf0\x08\x4d\x61\x1a\x02\x65\xc2\x65\x28\xb6\x6d\xc8\x44\x89\x4f\x8d\x02\x89\xcc\xf4\x7a\x94\x1a\x2f\xc2\x11\x87\xbc\xbd\xf5\x35\x45\x59\x11\x58\xf7\x22\x1c\x65\x4b\x91\x16\x54\xd3\xa4\xb6\xe1\xd6\xd3\x54\x08\xe8\x49\xb7\x58\x5e\x80\x32\x17\xd1\x1a\x9d\x0f\x69\x05\x80\xbd\xf6\x00\xfa\x12\x35\x58\xd0\xe1\x83\x01\xff\x0a\xc8\x62\x19\x63\x86\x87\x0b\x9c\x64\x83\x74\xde\xe0\x1b\x54\x1b\x61\x80\xbe\x08\xa5\x40\xd3\x1e\x96\x79\x93\x6f\x56\xc3\xab\x3f\x29\x52\x1c\xfb\x2a\xe0\x40\xab\x39\x53\x6d\x75\x51\x93\x95\x13\x92\x60\x83\x99\x89\x69\x23\xae\xa7\x81\xa7\x83\x60\x0c\x05\xaa\x74\x68\xd6\x99\x74\xe5\xfc\x00\x3d\x33\xd1\x8b\x59\x80\x3e\x99\xd2\x8f\xc3\x3a\x8d\xaf\xd2\x2c\xda\x90\x0e\xdf\x06\xb8\x61\x94\x2e\x63\x5f\x46\x38\xb4\xa6\x31\x09\x4e\xd7\x05\x6c\x45\x33\x72\x32\x1e\xff\xb8\x26\x58\xbf\xd9\xc6\xb1\xa0\x50\x02\x11\x6b\xbf\x86\x34\x3a\x99\x9b\xf5\x47\x3f\xc3\x0b\x21\xe2\x4a\x4c\x62\xe5\x1c\x3e\xb6\xad\x3b\x24\x7b\xc0\x77\x17\x15\x2f\x5a\xa6\x67\xb5\xc1\x81\x29\x88\xb9\x54\xda\xc8\x91\x8a\x45\xf7\xd1\x64\x65\xb0\xd6\x53\x18\x85\x8e\xf6\xe5\xa6\x46\xd2\xab\xae\x10\xfa\xdd\x72\x5f\x9b\xd0\xe4\x35\x41\x93\x7f\xa9\xad\xb9\x5a\x34\xb7\x0c\xd0\x1b\xd3\x26\x52\x27\xfc\x64\xf0\x5d\x5b\xe6\xd6\xa7\x5c\xa7\xe6\x68\x85\x71\x2f\x22\x60\x09\xb5\x99\x1d\xb0\xb6\xe3\xb8\x74\xbc\xd3\xdb\x32\x47\x99\x1f\x3a\x15\x39\xe4\x1b\x48\x11\x08\xea\xe6\x86\x1f\xb3\xd5\xa8\x57\x5b\x9f\x43\x44\x6d\x27\x42\x1f\x43\xe1\xf2\xbf\x88\xda\x25\xcc\x88\x96\xff\x60\x9d\xc9\xb6\x4b\x8a\x5b\x39\xc3\x11\xfd\x04\x73\x9f\xb2\x15\xea\x4a\x5d\xc4\x86\x20\xeb\x88\x64\xd4\xa4\xf2\x23\xa2\xbe\x2f\x8d\x2a\x5c\x05\xeb\x67\x0e\x56\xbf\xb5\x26\x80\xd6\x50\x55\xec\x51\x2b\x95\xa1\x90\xbf\x0b\x7c\x53\x1c\xc7\xc3\x34\xf6\xd3\xf9\x77\x80\xaf\x08\x3e\xda\x06\x60\x97\xe5\xdf\x37\xea\x23\x96\xef\x5f\x7f\xd1\xac\x87\xe4\xbb\xe7\x6d\xc6\x1b\x6c\xc4\x1b\x4d\xad\x9f\xc5\x08\x37\x34\xfe\xc4\xb3\x1f\x59\x3a\x59\x5a\x04\x33\xf0\x26\xb9\xb4\xe7\x33\xb6\x25\x38\x58\x6f\x22\x78\xd6\xaa\x51\xf4\x5f\x68\x3d\xb5\xd2\x4a\x59\x2e\x98\x38\x7d\x87\xe3\x2e\xe5\xf4\xdb\x90\xd6\x96\x5d\x70\x54\xc4\x64\x59\xeb\x44\x31\x5b\x28\xdf\xb6\x91\x2e\x23\xe5\x5b\xb6\xa3\xc0\x13\x90\x58\x9f\x16\xff\x16\x04\x06\x65\xb8\x35\xcd\x9c\x4b\x32\x90\x54\x83\xc4\xbb\xf5\x28\xf1\x3a\x3e\xfc\x5a\x52\xb7\x5b\xd9\x48\x17\x2f\x1e\x85\x40\xab\x43\xd0\xb3\x44\x06\x68\x24\xbc\x2c\xce\x4d\x97\x80\x2f\x85\x46\x41\x21\xf4\x14\xdb\xdc\xe4\x20\xe3\x1b\xad\x2f\xf8\x96\x24\xbd\x5b\x32\x42\x87\xfd\x12\x98\xb3\x4e\xfd\xd9\x84\x5c\x50\x7f\x0d\x1b\x9e\xea\x12\x8a\xed\x6e\x39\x06\x11\x9d\x71\xa1\x76\x6e\xf3\xfc\x9c\x86\x32\x5c\xbe\x11\x0a\xc1\xb2\x3b\x4e\x91\x16\x2d\x08\x5d\xb0\x2d\x03\x7a\x2c\x03\xf4\x2c\x46\x1f\x53\x74\x66\x54\x54\x5a\x49\xd9\x3b\x25\x12\xb7\x22\xdf\x8b\x28\xc9\xd2\x6f\xa7\xdb\xfb\x4d\x73\xcf\xf2\xac\xea\x9e\xb0\x86\xca\x37\x4d\xfb\x3b\xe7\xbb\x8c\xff\x11\xd3\xcd\x6d\xc8\xba\x0f\x96\x5a\xec\x95\x28\x2d\x02\x6a\x1a\xe5\xa3\x15\xc2\x2f\xc8\xdc\x00\x15\x01\xc8\x6d\xcb\x2c\x23\x95\x05\xad\x1c\x88\x9b\xf0\xad\x10\xf0\x3f\x15\x71\xa8\xe9\xe8\xa9\x45\xa3\x37\x29\xab\x0f\x2c\x20\xab\xdd\x0d\x55\x1b\xda\xf6\x11\x6e\xa9\xa5\x97\x3f\x5f\x8a\xec\xc0\xac\xa1\x0e\xde\xb2\x53\x2f\x34\x42\x27\x1d\xd6\xfb\xed\xa0\xe1\x11\x0a\xd8\x37\x6b\x4d\x4a\x7d\x8a\x44\x04\x5f\xd8\x4e\xa4\xa2\x64\xed\xea\x59\x30\xed\x77\x7c\x34\x85\xa7\x40\x85\xc9\x6e\x52\x30\x52\x7d\x37\xc8\xff\x55\xf8\x6e\x36\x9d\x2d\x8d\x66\x92\xfa\x5d\x28\x19\xf9\x49\x42\x98\x90\xa4\xa7\x36\x8c\xed\xbf\x8f\xb7\x22\x14\x2c\x05\x6a\xb4\x75\x10\x54\x6d\xb6\x44\xc9\xe8\x04\x27\x98\xfa\x8c\xd0\x77\x34\x36\x94\xa1\x4b\xa3\xdb\x48\x13\x5c\xa5\x27\x01\x38\x40\x89\xa6\xe3\x7b\xc6\xa3\xcb\x9f\xc6\x78\x50\x00\x65\xd2\x21\x3e\x21\x4b\xa8\xcf\xaa\x7b\x1e\x86\x67\xb3\xcf\x90\x2c\x4d\x7b\x52\xd2\x9f\xa8\xe3\x72\xf9\x7f\x9c\x13\x81\xdd\x5b\x38\x11\xe8\xf7\xd1\x78\xbb\x41\xad\x70\x20\xb0\xfb\xcf\x71\x20\xe0\xb7\x59\x0e\xc3\x63\x86\x0e\xf1\xeb\x58\x56\xbf\x8a\x4a\xd5\x0f\x5d\xed\xb9\xa3\xc3\x11\xab\x98\xea\x3b\xb1\x02\xeb\xd9\xb3\x99\x34\x56\x6c\x48\xbb\x0f\x4b\xfd\x64\x90\xb8\x77\xe8\x48\x85\xcb\xbf\x7b\xf7\x4e\x53\xd0\x72\x73\x23\x74\x22\x2d\xcb\xb1\x84\x1c\xbd\xff\xce\x56\x3d\xed\x5a\x72\x78\xab\x21\xd0\x2c\xc5\xf0\xfb\x3d\x62\xf8\xfd\x96\x18\x7e\x6d\x89\x5a\x4b\x02\xdb\x41\x2e\xfc\x25\xe2\xf0\xb8\x9a\xe2\x23\xf5\xb8\x22\x34\x28\x6c\x93\x1f\x40\x3b\x87\x59\x17\x6a\x50\x48\x5c\x6c\x68\x48\xf8\x06\xd7\xf0\x0e\x5c\x5c\x79\xa2\xc9\xfa\xdf\x58\x2a\x8e\x23\x9e\x4b\xc7\x11\x4f\xd2\x1c\x3c\xfd\xae\x43\x9a\xef\x3a\x9c\x6a\x71\x20\xfb\xea\x5d\xa7\x5e\x80\xc8\xcc\xb4\x16\xa7\x52\x7b\x73\xa0\xc5\x9b\x8e\x36\xcb\x7c\x9d\x22\xbf\x74\x03\x41\xd5\xeb\x4e\x25\xd7\x6b\xe4\xd6\xbd\x4a\xb0\x2d\x3e\x86\x27\xd2\xfb\xc2\x3b\xe9\x7d\x21\x11\x0a\xed\x12\xaf\x83\x46\x6d\x93\x8b\x89\xa0\x74\x31\x41\x4c\x2e\x26\x4e\x42\xa4\xa0\x29\x25\xa7\xb8\xe5\x72\xc2\xe4\x6d\x82\xe8\x68\x88\xa5\x0b\xfa\x22\x42\xa2\xf0\x40\x41\x46\xde\x64\x4b\x53\x40\xa2\x3c\x71\x73\xd0\xab\xa9\x3d\xaf\x79\x9b\xe0\x4b\x32\x73\xd9\xd6\x93\xb4\x3a\xb7\xfe\x83\xe1\x2f\xf0\xa3\xa0\x3c\x0c\x5c\x75\xbf\xe2\xac\xe9\x43\x21\x30\xbf\xdc\x98\x64\xd1\x57\x21\xca\xcc\xef\x3f\x07\xc6\x30\x08\x01\x7a\xd5\xb5\xb5\x7d\x99\x67\xdc\xda\xff\x2a\xde\x17\x3a\xfc\x16\xce\xfe\x3a\x19\x80\xf9\x0e\x14\x77\xf0\x20\x4f\x6b\xac\x35\xe3\x6c\xd4\x5f\xeb\x9b\xe1\x80\x33\xe0\x83\x53\x7c\x35\x98\x11\x3a\x10\x50\x8e\x92\x93\x6e\x35\xf5\xbf\xdc\x39\x44\xef\x00\xfe\x79\xbe\x22\x0e\x52\x54\x81\xf4\x7a\xbc\x48\xa5\xfc\x5a\xa2\x9f\xb0\xf3\xec\x16\xf7\x5b\x49\xf5\x5a\x2f\xfe\x77\x22\xb4\x9f\x00\x01\x3a\xe2\x97\x12\xfb\xe6\x86\x63\x05\x81\xc4\x86\xcc\xdd\xa1\x88\x88\xa3\x3c\xd8\xaa\xfa\x0a\x72\x6a\x6e\x84\xfe\x91\x0e\x71\x84\x41\xd2\x92\x0f\x66\x9d\xb3\xbb\xe5\x14\x27\xfb\xef\x77\x8a\x33\x5b\x42\x60\xd6\x3c\x35\x5f\xb2\xd2\xa5\xd1\x6f\x6b\x1b\x03\xec\x1c\x96\xcb\x7e\xa7\x88\x6b\x1b\x61\x89\xec\xb6\x9e\xb5\x0c\x61\x42\x6b\x2a\x63\x6b\x8a\xcd\xab\x9e\x26\x27\xfc\x0a\x72\x7f\x3d\x5d\x4a\xc2\xe4\x1e\x35\xed\xee\x56\x82\xd3\x61\x75\xf4\xed\x8f\x06\xeb\x0e\xb5\x7b\xf6\xff\xfb\x3c\xb0\xf2\x79\xe0\xe7\x69\x30\x0e\x4d\xaf\xe0\xff\x33\x5f\x08\xd6\xb8\xfb\xfe\x4f\x7d\x0c\xa0\x76\x8e\xcc\xb6\xb6\x46\x13\xd1\x52\x2a\xd5\x6f\x20\xea\x2d\x85\x80\xad\x43\xdd\xc4\x86\x79\x8d\x2e\xa9\x48\x07\x3a\xbe\x51\x22\x74\xc8\x96\xa1\x39\x52\xba\x49\xa6\x27\xf8\x14\x26\xe4\xa7\x9a\x75\xcf\xcd\xea\x60\x52\xdc\xa7\x74\x53\x88\x91\xa5\xae\x93\xba\x86\xa9\x7a\x1d\x24\xca\x70\x5d\xb2\x0a\xda\x6c\xbd\x45\x83\x58\x8e\xfa\x02\xbf\xfb\x68\x29\xa0\x05\x42\x02\xfb\x8e\x7f\x65\x52\x7c\x79\x4b\xd9\xa9\xb9\xf0\x9d\x8a\x98\xb4\x1e\xdc\xfa\x09\x45\x99\x74\x3b\x92\xdb\x70\xbe\xec\xd3\xb6\xfe\x3e\xe7\xb9\x5d\x16\xb9\x42\x03\x25\x1e\x4e\x06\x81\xf0\xcf\x55\x38\x89\xd7\x3f\x4d\x3e\xcd\xd7\xbc\xcd\xac\xf2\x89\x2e\x24\x69\xb5\x5e\x87\x82\xcd\x37\x95\xfd\x81\x08\x25\xc3\x3b\x13\x73\xc4\x9d\x34\x30\x29\x29\x3d\x8b\xa5\xdf\xde\x5e\x9d\xba\xdb\xdd\x43\x5a\xe3\x0d\xa3\x40\x28\x1a\xdf\xfa\x39\x64\xad\xf6\x43\x9c\x06\x34\x5a\x0a\x99\xf6\x1a\x27\xf3\x1a\x31\x55\x3a\x74\x76\x16\x5d\xc2\x0f\x26\x84\x1f\xcc\x9f\x0a\x69\x87\x20\x3b\x8f\x7d\xfa\x7d\x26\xe4\x81\x4f\x43\x4e\xbb\x6e\x67\x53\xd3\x68\x60\x28\x3d\xea\xac\xd1\xc4\x6a\x43\xfb\x4a\x7b\x22\x61\x65\xa3\xc2\x4d\x83\x37\x83\xc4\x44\x50\x9e\xc5\xe8\x73\x2a\xa9\x5b\xfb\x50\xb8\x85\xb9\xba\xe8\x24\xfb\x96\x4e\x9e\x9a\x05\x10\x46\x34\x34\x9b\xc4\x3f\x8b\x51\x32\xd3\xda\x83\x3f\x84\x15\x55\x2c\xc0\xc5\x67\xd3\x42\x5e\x8b\x00\xd0\xf9\xb2\x34\x0f\xb6\x94\xe5\xbb\xfe\x0d\xcc\xe4\xdc\x50\xd6\x29\x9e\xf6\x74\xa5\x22\x01\x7e\x30\x3b\x73\x5c\x6f\x8e\xdd\x48\x24\xb5\x4c\x57\x2d\x77\x9b\xe9\x96\xcb\x78\xec\x4f\x2b\xe6\x1a\x3d\xb0\xc4\xa5\x7b\x01\x5c\x75\x2f\xd0\x07\x7f\xaa\xea\x84\x4b\x44\x6c\xbb\xee\x36\x67\x0d\x89\x77\x7b\xe8\xd2\x53\x08\x56\xf6\x01\x8f\x0a\xb7\x7d\x41\xb7\x71\x63\x8a\xe6\x4b\xc0\x23\x29\x0e\xdf\x0f\x81\x02\x91\x51\x22\x1b\x96\xd7\x46\xeb\xc7\xb6\x1d\x76\x10\x22\x51\x3b\x37\xcc\x46\x90\xa1\x93\x36\x19\xfa\x1f\xeb\x5d\xf0\x43\x8c\x22\xb4\xfd\x3f\xdf\xbb\xe0\xed\xc7\xd9\xeb\x5d\x70\xda\xa9\xb4\xd1\x17\x10\x46\xf2\xab\xdf\x69\xe9\xb7\x29\x1e\xdd\x44\x7b\x1d\x7c\x78\xab\xad\xed\x15\xb6\x4a\xdf\x1a\x85\xac\xd3\xfc\x7c\x32\xfe\x0e\xfb\x73\xba\x9e\x9c\xf0\xaa\x6b\x09\x9a\xde\xe8\x3e\xc4\xe8\xf1\x4c\xf9\x53\xfa\x5f\x9f\x74\xdf\xe0\x93\xee\xb8\x97\x23\xff\x4e\x3b\x39\xa3\xd6\x66\x3f\x7b\xb8\x88\xd7\x90\x7b\x74\xba\x4c\x3b\x59\x76\xb8\x4c\x5b\xeb\x24\x89\xd0\x94\x1f\xd1\xbb\x16\x08\x23\x27\xe1\xa3\xab\xa3\x90\xf4\x0f\x37\xf0\x99\x28\xfb\xd6\x47\x15\x47\x71\xdd\xb5\xf6\x92\xb0\x5e\x47\xb9\x8c\xeb\xae\x21\x5d\x0a\x84\xb5\x4a\x32\x46\x71\xd8\x5b\x4f\x7a\x20\x08\x07\xd3\x2b\x35\x99\xd2\xee\xaf\xbb\x8e\xb6\xfa\x93\x15\x94\x31\x5f\x1f\x08\x18\x16\x85\xd3\x59\xc3\x13\x5f\xcf\xc0\xb4\x89\xb7\x05\x46\x05\x06\xe3\xed\x55\xf8\xec\xd1\x5e\x37\xab\x6e\xeb\x3a\x7b\xd9\xd6\x76\xdd\x4a\xc0\x0f\xef\x9a\xe1\x61\x35\x26\x45\x08\x0b\x37\x77\x57\x02\x73\xc6\x1d\x6e\xee\xf2\x8a\xb5\xe0\x45\xf7\xd3\xb4\x92\xe6\x57\x5c\x51\x69\x1e\x24\xe9\xf4\xe3\x23\x55\xb2\x1e\xd5\xec\x07\xda\x3e\x94\xb6\x7c\x74\xbc\x04\x0c\x84\x8f\xd1\x29\x7f\x4c\x9a\x7e\x19\xd6\xf4\x17\x13\x84\xca\xa6\x36\x87\xd3\xe5\xea\x00\xb9\x2b\x37\x7a\x42\x58\x97\x64\xc2\x90\x70\xd4\xf1\x0c\xf4\xb2\x7f\x14\xf1\xaa\x51\xbc\xc7\x34\x8d\x48\x32\xd8\x4f\xf8\x11\xea\x9b\x2f\x95\xeb\x9f\x76\xb7\x3e\xd7\xb7\xbb\xce\xcc\x74\xb1\x9e\x37\x38\xeb\x31\xf5\x93\x60\xee\x7c\xcf\xa8\x55\x7f\x93\x35\x7c\x25\x11\xc4\x46\x53\xd1\xe3\xb7\xb1\xde\xff\x83\xe0\x96\x45\x71\xb8\xeb\x33\xfc\x4f\x05\x9d\xee\xf4\xff\x08\xe8\xbd\x4b\x31\xfd\xa7\x43\x8f\x77\xfa\xaf\x0e\xbd\xa7\x44\xd1\x9d\x7f\x26\xf4\x4e\x74\xa7\xff\xea\xd0\x7b\x8b\xcf\xa3\x7f\x36\xf0\xa8\xea\xf3\x5f\x1d\x76\xff\x0d\x78\x77\xfe\x4d\x58\x57\x61\xa3\xec\x1c\x2e\x3b\x8e\xff\xab\x6f\x90\xb4\x7e\x2b\x9c\xd7\x76\xa9\xe3\xac\xe9\x8c\x88\x03\xc7\xe8\x16\xe1\xfb\x9c\x35\xff\x75\x93\xd9\x0e\x43\x8a\xd3\xf4\x36\xf3\xf1\x65\x95\xb5\xae\x53\x39\x3c\x36\x9b\xfc\x44\x33\xd4\x30\xd8\x34\xc7\x17\xfd\x5e\xe6\x6f\x27\xce\x52\x86\xe9\xe0\x48\x5c\x44\xfe\xc5\xf8\x3e\x81\x69\xff\xb4\x6d\x8c\x57\x3b\x42\xfc\x17\xa0\x7e\x72\xa1\xff\x59\x50\x6b\x8b\x2b\xe8\x3a\x4a\x14\xc2\x49\xb4\x50\x38\xb8\x33\x5e\x57\x55\x41\xf8\x95\xd6\x72\x20\x5e\x47\x85\x2b\x94\x57\x6c\xb0\x28\xf6\xc3\x2b\xcb\xbe\x55\x73\xda\xfb\xa7\xa1\xb9\x14\x33\x16\x0b\xcf\xa0\xeb\x84\x84\x35\x61\x93\x6c\xe9\x76\x82\xc6\x7f\x01\x04\x7b\x8d\x31\x5d\x1b\xbf\x8c\x6f\x70\x7d\xf8\x15\xa1\xcf\x70\xb9\x04\x3c\x5a\xe2\xa6\x0f\xfe\xee\x03\xb4\x8c\x8d\xfc\xdd\xf4\xf2\x10\xa7\xf3\xff\x0e\x62\xf9\xfd\xe4\x4b\x0e\x3d\x21\x6c\x10\x90\x64\x16\x9d\x64\x74\x2d\x35\x2d\xe3\xa1\xb5\xbd\xd2\x2a\xe6\x1b\x4f\x23\x31\xb2\x35\x01\xbb\x30\x81\x64\xf9\x1d\x4e\x33\xa6\x7e\x70\xca\xd7\x24\x51\x36\x82\xff\x36\xfb\x65\xf6\xcb\xec\xb7\xff\x9f\xba\x6b\x71\x8e\x13\x47\xfa\xff\x0a\xe1\xae\x12\x69\xd3\x9e\x78\xf6\x76\xbf\xaf\x0e\x17\x95\xf2\x33\x9b\xc4\x76\xb2\x7e\xe5\xb1\xb5\x35\xc7\x80\x30\x24\x0c\x60\xd0\xf8\x11\x87\xff\xfd\x2b\xbd\x40\x80\x18\x33\xde\xdc\xd5\x77\x55\xbb\xb1\x0d\xa2\xd5\x6a\xb5\x5a\x2d\x75\xeb\xa7\xb1\xc9\x52\x61\x96\xd2\x8d\xd0\x5b\xc4\x89\x84\xaa\x59\x64\x69\xc6\x93\xd3\x47\x61\x86\xf4\xa4\x75\xfb\x63\x63\x14\x75\xe7\x1d\x3f\xae\xf3\x1e\xde\xb6\xfe\x6f\x74\x21\xce\x73\x1a\xff\x27\x9d\x08\x3a\x59\xf2\x1a\x1f\x67\xe5\x77\x72\x44\x27\xbe\x70\xd9\x4e\x7b\xd3\x87\x2c\x74\x9a\x37\x2b\x8e\xd7\x69\x68\x42\x76\xda\xe6\x74\xf8\x60\x33\x2e\x38\x70\x05\x27\x03\xa8\x22\xbc\x56\x46\x76\x35\xd8\xba\xd4\xaa\xe3\x5c\xc0\x62\x3f\x7a\xbf\xb5\x90\xfb\xad\xfb\xb9\x7b\x9f\xc4\xe9\x57\xc7\xb6\x21\xe5\x6e\x9f\x5d\xc1\x51\xfd\xf0\x6f\x2f\x04\x63\xea\xa5\xd4\xc5\x0a\x76\xf5\x22\xf5\x3d\x5e\xb2\x90\xfa\xbb\x82\x2b\xad\x98\xda\xfd\x16\x85\x24\xde\x71\x05\x07\x79\xe7\xc2\x96\xab\xbc\x2f\xd8\x5d\xc3\xb3\xa3\xbc\x2f\x62\x38\xcc\xdd\x81\xb3\xb3\x82\x0f\x2a\xaa\xe7\xd7\x7c\xeb\xfd\x60\x8a\xce\x0b\x16\x4f\xb2\x25\x6d\x42\xda\x57\xb9\x10\xf9\x71\x46\x0f\x98\x45\x6b\xbf\xdd\x97\x6f\xa5\x04\x0e\xb2\x62\xb1\x1f\xc4\x54\x16\xea\xbe\x3a\x26\x37\x86\x37\x87\x71\x69\xfa\xe0\x22\xae\x4b\xcb\xca\x76\x55\x65\xbc\x4f\xda\xef\x8e\xf2\x6e\x9f\xef\xe7\xfc\x2e\x94\xd5\x10\x00\x87\x39\xb3\x7e\x05\x7e\x69\x5b\xcd\x91\xbc\x0a\xc3\xbb\x15\x41\x68\x53\x9e\x9c\x96\x73\x5e\x67\xcc\x41\x8c\x5e\xe7\x03\xa1\xc2\x9e\x01\x5a\xfb\xce\xf8\xb7\x19\x2a\x26\xec\xa5\xe1\xdd\x97\x41\x90\x40\x33\xdc\xfc\xb8\xe5\x08\xbf\x05\x64\xc0\xe4\x7f\x86\x77\x5c\x92\x07\x39\xae\xe0\xfd\x40\xa1\x68\xa0\x8d\x73\xaf\xb0\xc4\x8f\x0d\x9a\x5d\x5e\x26\xc4\x9b\x27\x64\x63\x11\xa8\x87\x49\x7c\x19\xd1\x06\x9f\x63\x31\xdf\xf8\xd5\xca\xe9\xc6\x3f\xac\xbc\x9b\xa5\xbd\xd6\x24\x2d\xb2\x1a\xe6\x19\xa5\xd9\x42\x42\xbb\xe5\xb7\x56\x99\x25\x71\x60\x15\x97\x73\x0f\x6d\x82\x25\xfe\x9b\x4c\x7f\xfe\x15\x3f\x2a\xef\xbf\x34\xdb\x79\x19\x27\x1f\x31\x31\x0d\xe9\x05\x93\xcb\xbc\xf0\x52\x63\x7e\xf9\xdb\x0c\xd9\x7f\x1b\x71\x76\x5c\x21\x31\x2f\xbc\xd4\xeb\x9e\x9d\x5d\xd3\xd5\x96\x2c\xa5\xde\xb5\xa1\x51\x6f\x72\x73\xf8\xaf\x7f\xa5\x58\x3b\x59\x68\x4d\xa3\xd2\xce\xcf\x19\x77\x45\x03\xf7\x14\xe2\x34\x89\x53\x62\xc4\x8d\x5b\xa3\x57\xc6\x66\x8a\xf3\xde\x69\xb0\xad\x52\xd3\x45\xa8\xc6\x4d\x0a\x0d\x6a\x77\xcc\x68\x35\xe5\x40\x19\xcf\x2c\xef\x99\x67\xe8\x82\x49\xd5\x3c\x39\x1b\x0c\xf0\x49\x5e\xa7\x50\xe1\xad\xd5\x76\xfc\x86\x17\x6d\xde\xaa\x5c\x2a\xc3\xec\x13\xa3\x45\x0e\x54\x44\x76\xd9\x3c\x01\x9a\x13\xd0\x9f\x3e\xd4\x31\xcb\xa0\xa1\xcf\xde\xe2\xde\x1c\xd5\xd7\x19\x34\xcb\xe0\x22\x81\x12\x7d\x0a\xe0\x4a\x20\xd6\xd0\x89\x54\x21\x89\xf5\x0b\x35\x51\x46\x02\xf7\xa9\x6a\x4a\x6a\x22\x7b\x28\x2f\xf6\xd0\x9d\x5f\xdb\x36\x53\x3d\xcb\xf2\x43\x72\x4d\x92\x36\xb9\xbe\x63\xf3\x35\xaf\x2a\x38\x1f\x9c\xac\x3c\xe4\x65\x60\xf3\x29\x04\x7a\x4a\x68\x3a\x85\xb8\x97\x21\xbb\xa4\x77\x09\x29\x23\x42\x8c\x89\xd2\x31\x9a\xf9\x60\x27\x99\x17\xd8\xe0\xa7\xa8\x40\x47\x31\x1b\xdc\xe6\x64\x00\x56\x94\x14\x45\x56\xc8\xb2\xbb\xb1\x3e\x53\x1e\x78\x71\x42\x02\x8b\x66\x16\x23\x67\xed\x9e\x9e\x5a\x61\x91\x2d\x1c\x8b\xdf\x22\x6c\x4a\xb0\xe9\x64\x3d\x57\x18\x2e\x1e\xb7\x06\x39\xcf\x41\xcf\xaf\xb7\x93\x78\xfe\x62\x9e\x65\xb4\xa4\x85\x97\x6f\xfc\x32\xd9\x9c\x6c\x6e\x78\x49\x1e\x79\x93\xff\xd9\x08\xe2\x92\xbe\xf0\xcb\xb2\x29\x30\x59\xc4\xe9\xc4\xe7\x59\x42\x47\x26\x00\x0b\x33\x7d\xbe\xac\xf3\x6e\x48\x99\x2d\xc8\xc6\x2f\x93\xff\x9d\x6c\x72\xaa\xfa\x63\x8d\xf0\xbe\xe1\xc2\x09\x5c\xc1\x87\x51\xd9\x71\xe3\x36\xf0\xc7\x41\x9e\x78\x41\xa0\x76\xae\xec\x5f\xba\xe7\xdf\x56\x7c\xa8\x9d\xf5\x29\x48\x30\x66\xe5\x6a\x70\x4d\xc6\xcc\x48\xef\x99\x39\xe1\xc6\x6a\x9d\xa5\x96\x9c\x82\x99\x0f\xf1\xf0\x75\x63\x7b\xf9\xc8\xd4\xf7\x0a\xc3\x6f\x8f\xd1\xc8\x0b\xd6\x86\x24\x9e\x9b\x01\x51\x3a\x39\xb6\x85\xe9\x48\x3b\x9d\xd4\xea\xb9\x7b\x7a\x0a\xfc\x7a\x65\xa6\x5a\xdb\x42\xb3\x76\x4f\x4f\xab\x2d\xea\x04\xd9\x7d\xc1\xfe\x89\x43\x54\x7f\xfd\xa4\x0e\x0c\xcc\x0b\xe2\x7d\xb5\xb4\xdb\xaf\xe4\xf1\xf6\xee\x9a\xac\x79\x3f\x5d\x79\x73\xc9\xea\x36\xff\xff\xe9\xb7\xee\x15\x2a\x42\x0e\x45\x6d\x6c\xa5\x5c\x2a\xe3\x45\x2b\x31\xfa\xc0\xbd\x7c\x79\xdc\xbf\xfe\x88\x89\x58\x95\xe5\xb1\x17\x25\x2c\x45\x5d\x51\xad\x6e\xa2\x38\x21\xe8\xc9\x54\x3b\xa9\xa4\x48\x4e\xf9\xaa\xb5\x5f\x80\xbb\x38\xe6\x24\x67\xf8\xb2\x62\xc9\x23\x92\xd7\x50\x01\xf7\x2a\x8d\xcb\xe9\x5f\x7e\x79\x00\x49\x09\x74\x42\xc9\x2d\x3f\xdb\x52\x61\xf8\x66\x4a\x53\x14\xe0\xc1\x3a\x4d\xf6\x85\x73\x88\xbc\x12\x11\x2d\x4d\xac\xbe\xad\xda\xa0\xb5\xf5\xd7\x44\xe3\xa8\xd7\x59\x27\xb4\x63\xa8\x3e\xfb\xad\x8b\x98\x8b\x12\xa5\x03\x33\x90\x5f\xc0\x1d\x3a\x2e\x31\x5c\xa4\xe6\x2b\x00\x4d\x22\xac\x30\xbc\x5a\x79\x78\x4d\x8d\x10\xbf\xb5\x7a\x0e\x02\x91\xb5\x2f\x93\xec\x44\x82\xd9\xd2\xf5\x35\xb0\x2f\x0f\x7d\xcb\xf9\x01\xdd\xba\xe1\x59\xab\x2b\x5e\xc1\x12\xb2\x46\x76\x2f\x9b\xdf\x9d\xa6\xc1\xcd\xc3\x8e\xba\x2f\xfb\xaa\x2e\x4b\x9e\xb1\x9e\xf1\x27\xb3\xcd\x97\xb6\xed\xd4\xdf\xb3\xa7\x95\x72\x39\x44\x52\xb6\xa1\x05\xb3\xb5\x5a\xf0\x71\xcc\x11\xb5\x19\xd6\x5b\xd9\x67\x32\x2e\xd1\x0c\x0f\xf0\x29\x72\x32\x8f\x9a\x37\x6a\x24\xae\x52\xaf\x86\xc7\xba\x12\xa1\x5a\xfb\xb4\x92\x17\x11\x17\xa4\x2c\xe3\xf4\x72\x47\x01\x81\x8c\x24\xdb\x05\x0e\xe9\xd0\x6e\xfb\x6b\x06\x5a\x99\x2c\xc9\x3a\xeb\xf7\x41\x84\x18\x25\xfd\x2f\xa8\x7b\x38\xb2\x0d\xed\xf8\x44\x06\x97\x66\x9b\xc2\x53\x7e\xfa\x54\x3d\x98\x8a\x9b\x15\xc5\x8d\xb7\x18\x3e\x0d\xe3\xb9\x89\xbb\x44\xf4\xd8\xf0\xe3\x2f\xba\xcd\x58\xc5\x3b\x35\x56\x9b\x47\xc1\x7f\x5e\x40\x8c\xf6\xc0\xdf\x28\x36\xa6\x1c\xd7\xbb\xc2\xf0\xd6\x64\x5f\xa8\x13\x66\x05\xda\xda\x52\x96\xc6\x34\xe9\x31\xe1\x15\xd5\x56\x77\x3e\x13\xf9\x9e\xdf\xbf\xb3\x81\xc1\xff\x94\x13\x99\xfe\x44\x5a\x63\xc9\x34\xd9\xaa\xb3\x41\xa7\x8c\x67\x5f\x7c\x34\xdb\xdc\x6a\x30\x65\x52\x69\x8f\xf1\x3d\x95\x6f\xa7\x50\xb8\x19\x10\x57\x3f\x71\xdc\x1e\x92\x7e\x6f\x48\x6e\xb1\x39\x2c\x4e\x97\xc4\xa2\x15\xa7\x2d\xe0\xd4\x88\x80\x50\x6b\xf8\xa1\x2e\x95\xd4\x09\x57\x8e\xcf\x0f\x81\x59\xda\x36\xfe\xfe\x5d\xe2\xe2\xd8\x36\x07\x6c\xa8\xbb\xe2\x25\x75\xbc\x02\x79\xe8\x6d\x0e\x65\xc1\xe6\xc4\xb2\x60\xce\x95\xee\x4c\xb3\x7e\xf8\x68\xea\x07\x25\x80\x5e\x0d\x8a\xd7\x46\x46\x7c\xb3\x4b\x3e\xad\x2d\x06\x79\x3e\xf9\xf9\xd7\x9f\x4e\xd1\x76\x81\x62\xf4\x59\xed\x88\xfd\x84\xa6\x1b\x84\xa3\x79\xe7\x3d\x58\xfa\x06\xdf\x87\x68\xe4\x84\x16\x6c\x17\x4c\x54\x99\xcb\xe3\x77\x29\x9a\x53\x0c\x31\x0a\x02\x88\x51\x42\x61\x0a\x29\x6f\x1a\x4f\x81\xf6\x59\xd9\x02\xc3\xd2\x45\x31\xda\x06\x1f\x52\xfc\xe2\xe7\xef\x9b\x78\x63\xca\x91\x90\x32\x0a\x31\xfa\x94\x33\x83\x8b\x61\x80\x9a\x2f\x05\x85\x39\x36\xd2\x17\x66\xb7\x4a\xf7\x14\x79\xf8\xc5\x29\x4a\x31\x84\xee\x37\xd4\xbd\xa4\xf7\xa1\xd1\x41\x7f\x2a\x2a\x0c\x93\x5f\xe1\x14\xc5\xe8\xf7\x1c\x32\x2e\x8d\x0a\x66\x18\x43\xe2\x22\x46\x7c\x23\x64\xf4\x3d\x0c\x81\xaa\xab\xc1\x05\xe2\x72\xf1\x60\x13\xbf\xdc\x74\xa6\x2f\xfe\xf1\x13\x0a\x9e\x97\xcf\x13\x8e\x5e\x1e\xad\xa9\x1f\x9b\x9a\x7a\x4c\x1d\x0f\x7d\xe4\x5d\x03\x31\xfa\xbb\xec\xa3\x0a\x43\x11\x19\x9c\xd9\x55\x16\x91\x2a\x43\x5b\x3a\xbb\x05\xa2\x0d\xc6\x48\x7d\xac\x9a\x29\x9b\x13\xa3\xa8\x00\x9b\x2d\xf4\xf4\x12\x54\xa1\x5d\x39\xdc\x54\x4c\x37\xa1\xa0\x28\x46\xef\x81\x46\x2d\x52\x60\x36\x49\x12\xf5\x91\x2a\x8c\x93\x02\x57\x70\x98\x72\xc7\xba\x94\x0b\xca\x3e\xc8\x96\x73\x55\x1b\xeb\x0a\xc8\x0a\x19\x36\x6e\x8e\x20\xef\x7c\xf6\x10\x15\x07\x56\x85\x93\x94\x46\xa3\x9c\x24\xfe\x85\xf3\xd1\x6b\x10\xa8\x56\x39\x48\xe4\x47\xf8\x3f\x07\xd2\xff\xe9\x42\x3f\x0d\xf8\x3e\x59\xf4\x38\xdf\x87\xd1\x74\x6a\x37\x21\x8d\x7a\x6e\x82\x14\x9c\xee\xc9\xc8\xae\xea\x18\x4d\x66\x59\x07\x5c\x99\x96\x7b\x08\xb5\x4e\x68\xce\x4d\xfd\xac\xe7\xda\x70\x06\x4d\x4e\xd9\x2a\x5e\x47\x39\x34\x4b\x5c\xb7\x65\x14\xa3\x4b\x23\x9f\x42\x31\x47\xfb\x33\x3d\x55\x36\xb8\x35\x07\x99\xbf\x2c\x47\x52\x94\x68\x7e\x9c\xcc\xea\x91\x22\x68\x9f\xb4\x10\xff\x46\x56\xd2\x86\x09\xfc\x0f\x7a\x62\x9a\xf3\x78\xa0\x24\x5f\xab\x6b\x11\xa1\x5e\xe7\x6b\x9e\x62\x77\x37\xf9\x01\x3f\xce\x37\x59\x4d\x2b\x46\xbb\x14\xde\x96\x70\x29\x8f\x55\x2f\xd7\x1f\x66\xf5\xcd\x16\x07\x84\xa9\x58\x2d\x73\xfd\xde\x79\x5f\x39\x3b\x26\xf8\xe2\x76\x4f\x48\x62\xbc\x91\xba\xac\x4c\xfb\x39\x59\x4b\x8e\x7c\xab\x53\x7d\x3f\xb2\x7f\x5a\x57\x73\x38\x4f\x36\xb5\x31\x61\xdb\xd0\x58\xfe\xa1\xa3\x87\xba\x85\x90\x8e\x5f\x85\xe1\x5e\x45\x57\x13\x1b\xf8\x95\x31\x3c\xa0\xab\xe6\x8f\x4c\xbb\xe1\x03\x43\xf7\x0e\x2c\xa5\xd1\xd2\x4c\x7e\x90\x66\xb2\x7b\xcf\x11\xfe\xf7\xea\xbb\xd0\x49\xc5\x93\x66\xa0\x36\xb9\x9f\xf2\x23\xc5\x21\xa7\x53\xa3\x72\xd2\x08\x96\x66\x3c\x15\xed\xa6\x9f\x96\x3c\xf1\x98\x85\x7d\x6b\x34\x2d\xeb\x6e\x9e\x75\x84\xb0\x93\x2c\x0b\x25\x82\xd6\x4c\xb2\x9e\x52\x4d\x3b\x64\xd7\xb2\xa8\x3d\xf5\x30\xd9\x53\x71\xb6\xfe\xae\xdd\x5d\x1e\xef\xae\x71\xd2\xe8\x72\x0c\x1d\x0d\x51\x6d\x68\xcd\xf1\x05\x9b\xe3\xf5\xcd\x12\xd5\x0d\x8e\x74\x08\x99\x43\x77\xe5\x1c\x22\x0f\x57\x1c\xec\x65\x3d\x83\x35\x8b\xdc\xb4\x07\x21\xd6\x18\xa3\x02\x96\xae\x0f\x33\xd7\xaf\xf1\x39\x80\xb5\xb8\xc6\x19\x80\x50\x5b\x01\x65\xd0\xa4\x3e\x30\x97\xb6\xde\x4e\x4c\xfa\xa9\x06\xb5\x19\x63\xf5\x04\x6e\x32\x4e\x88\x4b\xb8\x97\x57\xc2\x07\xa0\x18\xea\xe3\x10\xd4\xd7\xd5\x68\xb6\x51\x5e\x15\x5d\x53\x9a\xc1\x3d\xf3\x0d\x9d\xbd\x94\xfb\xf1\xdb\x29\xf0\x75\xc1\x2a\x54\x21\x01\x4f\xc0\x9c\x63\x67\x56\x21\xdc\x55\x0f\xd6\x20\x99\xe9\xc1\x1b\x95\xbb\x31\xfa\x92\x03\x01\x0f\x43\xe4\xc6\x88\x44\x40\x60\x36\x66\xe0\x34\xad\xbc\x8a\xa1\x16\xb5\x93\x37\x4d\x8e\x40\xe1\x26\x28\x43\xd6\x73\x14\xf9\x9c\x63\x86\x7f\xf0\x6b\xf8\x8d\x45\x09\xa9\x19\x4e\x78\xc5\xe7\x0a\xbd\xc3\x8f\x90\x19\x00\x4a\x05\xb2\x2e\x2f\x13\x52\x63\x75\x0c\xab\xe3\xb2\xa7\xf3\x61\x57\xe7\x75\x94\x0f\xe7\x10\x25\x7c\x6f\x54\x68\xbb\x56\x57\x83\xf1\xf1\x97\x2b\xab\x49\x99\x6a\x3b\x25\xf4\xcc\x9b\x8f\x31\x2d\x4b\xb8\xa7\xde\xdc\x49\xfa\xd6\xe4\xa8\xbc\x3c\xc8\x8a\x03\xd5\xb9\x42\x65\xae\xdd\x12\xbd\xca\x21\x04\x02\xec\x13\xa6\x39\xb9\x7b\xcd\x7e\xbb\x64\x3f\xa6\xe3\x74\x47\xd7\x18\x56\xfb\x2c\x54\x73\xdd\x60\x97\x2a\x10\x91\x4b\xdc\x62\xef\x95\xd4\x37\xc1\xdd\xdc\x2d\x51\x16\x35\xdc\xcd\x98\x5e\xcf\x05\x77\xf3\xd1\xdc\x35\x3a\xfc\x20\x57\x85\x99\xab\x93\x06\x23\x46\x30\x76\xe7\x96\x68\xa9\x31\xe6\xb7\x60\x64\xe0\xcc\xbd\x13\x4c\xde\x8d\x66\x52\xfb\xde\x39\x7b\x90\xcf\x54\xe3\xf3\x41\xe3\xdb\x1a\xe5\x6a\x10\xb7\x14\x84\x99\xe5\x38\x72\x4b\x14\xa6\xb0\x1f\x43\x8c\xa2\x14\xec\xb8\x3c\x61\x73\xba\x0d\x77\xfc\xe6\x4d\xf6\x48\x60\xb6\x9e\xd5\x7f\xf3\x0b\x95\xf8\x03\x0c\x5e\xdb\x0f\x55\x39\x16\xd2\x04\x7b\x6d\xec\x12\x3f\x45\x8b\x50\x2e\x44\x72\x92\xb6\x32\xea\xfc\x14\x5d\xab\x77\xa4\x03\x87\xe2\xa7\x28\x0f\x7b\xe9\x16\x59\xaa\x47\x7a\xe5\xa8\x6d\x9d\x52\xb7\x16\xcb\x92\x5a\x73\x62\x65\x29\xb1\xb2\xd0\x7a\x26\xf8\x79\x06\xd6\x33\x59\xfd\x33\x2b\x2b\xac\x67\xb2\xbe\x67\xd6\x7c\x49\xad\x1b\xaf\x7c\x66\xb7\x43\xab\xcf\x26\x36\x1b\x94\x15\x94\xcc\xbe\xbe\xf6\xfe\xb0\xbf\x3b\xf6\x9f\xe0\xa7\x28\x08\x99\x50\xd2\x14\xbc\x48\x0a\xa7\x14\x87\xe6\xcf\xf8\x6a\x39\x6c\x95\xff\xa1\xbf\xfa\x29\x4a\x42\xd5\x23\x71\x20\xbb\x43\xfc\x59\x43\x01\xd4\x4f\x53\x23\x00\x93\x9f\x72\x44\x32\x9b\x07\xc3\x2b\xc8\xd9\x9f\xfc\x7b\x85\x13\xc0\x5b\x81\x9b\x96\x71\xf8\x03\x1b\xde\x78\xf5\x43\x81\x6f\xd0\x7a\x54\xa3\x17\xb4\x9e\x2e\x6a\x58\x80\xcb\x14\xc5\x51\x8b\x2c\x4f\x86\x2c\x23\x8c\x21\x61\x02\xbb\x4e\x3b\x8b\xf5\xba\x4c\x37\x14\xc7\x74\x32\x30\x7f\x12\x78\xd4\xb3\xfb\xd3\x8d\x5d\x5f\x35\xd7\xa3\x26\xc8\xe5\xe3\xc8\x89\xfa\x2f\x53\x14\x32\xb6\xa3\x75\x3e\x0a\x23\x0c\xd7\xc6\xe5\xdb\x47\x32\x22\x5a\x2e\x46\xe3\x6c\xea\xd0\x54\x1d\x48\x1b\x19\x2e\x97\xe3\x56\x7d\xca\xff\x1c\xfb\x6d\x6d\x16\x66\x53\xe7\xef\x04\xd1\x89\x7c\x60\x3c\x51\x52\xc1\xe2\xf1\xed\x8b\x83\x86\xc5\x38\x18\xcb\x9f\xa6\xf2\xea\xe3\x06\x10\x63\x74\x3a\x81\x54\xfb\x9a\x82\x44\xc8\x18\xf9\x7d\x33\x40\x04\x81\x1d\x4f\xe4\x2b\x49\xd0\x90\x91\x54\xd4\x88\xd2\x68\x28\x10\x91\x91\x14\x9a\xa1\xc6\x5c\x10\xc2\xfd\xce\xeb\x08\xa8\x1e\x30\x35\x65\x52\xb3\x8e\xbb\x1c\xde\x61\x4c\x22\xbe\x27\x7e\x5b\x80\xfd\xa2\x9b\xeb\x43\x87\x47\x9a\x61\x10\x16\x93\x38\x30\xa8\xcd\x96\xbe\x8b\x41\xe0\x8b\x87\x62\xb4\xe7\x71\x88\x68\xbe\x53\x3c\xef\x6f\x9d\x8a\xd8\xd5\xb6\x8f\x16\x11\x2a\x30\x86\xf4\x11\x0c\xf6\xed\x4a\xc3\xca\x17\x0f\x79\xe8\xdc\x63\xce\x2b\x04\x11\xe7\xe2\x6e\x58\x42\x3f\x46\x38\x23\x25\x73\xc1\xb8\x8a\x22\x21\x9a\xb3\x1f\xc1\x94\x36\x9b\x36\xa2\x29\x4a\x64\xba\xe6\x63\x98\xa5\x5c\xb2\x74\x13\x0d\xdc\x05\x5c\x18\x21\x53\xb6\x83\xa0\x0e\x09\x77\x37\xc4\x49\x2b\xfc\x5b\xc7\xc1\x86\x62\xd4\x17\xa1\x21\xaf\x58\xdf\x08\x39\x55\x03\x55\xc3\x67\x01\xdf\xbd\xf5\x10\x91\x63\x4d\x1a\x47\x58\xb2\x87\x59\xeb\xc2\x71\x15\x0f\xf5\xd0\xc5\x10\x56\xaa\x45\x37\x8a\x0a\x83\x0f\x4b\x7e\x91\x84\xfd\xee\x6b\xf7\x68\x6c\xea\x5e\x79\xf2\xb4\x81\x5c\x42\xaa\x03\xb4\x12\x88\x8f\xb1\xe4\x90\x49\xb0\x2c\x38\xc8\x89\xe0\x47\x1d\x0d\xeb\x3d\x47\x5a\xf0\x46\x5b\x5f\xc8\x66\x3a\x31\x7a\x13\x42\x06\xa4\x31\x46\xa0\x08\x88\x77\x33\x68\x48\x76\x64\xb5\x2f\xcc\x11\x97\x54\x29\x24\xb5\x14\x92\x52\xc4\x94\xac\xb8\x00\xcb\xff\x52\x59\x89\x6e\x17\xd2\x28\x41\xa9\xc1\x1a\x72\xda\x93\x8f\x85\xa4\xc2\x95\x92\x4a\xdc\x43\x0f\x85\x18\x82\x35\x25\xf5\x9c\x49\x6a\x09\x49\x2d\x08\x5d\x58\x2f\xf7\xa5\x94\x9c\xb6\x12\x8f\x68\x70\x30\xd8\xe0\xd0\xd4\xe0\x0b\x2f\x89\x19\x99\xb3\x78\x41\x8c\x83\x55\x53\xbc\xc3\x10\x6e\xbd\x96\xe6\xd5\x15\x1f\x86\xf0\x2d\x34\x48\xc7\xc8\xcb\x61\x08\x87\xde\xb0\xf4\x77\xeb\xe9\xdf\xc4\x4f\xed\x09\x88\x46\xf1\xae\x21\xba\x7f\xd0\x69\xd8\x78\x6a\x87\x21\x1c\x85\x46\x5a\x92\x2f\xe9\x52\x18\xe9\x88\x77\x6d\x9e\x94\xc7\xd1\xe5\x68\x14\x9d\x9a\x9b\x0e\x15\x11\x9c\x6a\x65\xdc\xe4\x2d\x50\xaa\x07\x2c\x2d\xdf\xdb\xcd\x35\x83\x8b\x79\x7e\x45\xfe\x7c\x0a\x9d\x2c\xac\x7e\xfa\xcc\x31\x73\x57\x9d\xc8\xf5\xd0\x22\x10\xad\x34\x5e\x2b\xd4\xc4\x76\xf9\xee\xb2\x92\xc9\x14\x94\x8b\x8b\x2b\xbd\xae\x95\x8c\x47\x5d\xe9\xfd\x45\x56\x84\x58\xff\x0a\x23\x2d\x89\x5c\x70\x37\x7c\x1d\x3e\xc4\x0d\xc6\xba\x4c\xa4\xef\xfe\x03\x84\xf2\x58\x6e\x94\x75\x59\x93\x05\xb5\x86\x67\x3a\xb8\x46\x9d\x72\xb5\xe1\xa4\xfc\x16\xe7\xb5\xaa\xac\x2a\x0c\x5f\x23\xf7\x98\x4e\xb2\x25\xbd\xcc\xe2\xf4\xf2\x7d\x56\x50\x64\xe7\xa4\x28\xe3\x92\xee\xb5\x12\xf0\x6d\xe3\xc6\x6c\x85\xe1\x34\x32\xde\x80\x21\xfc\x87\x7a\xff\x39\xd3\x3d\x1a\x61\x45\xd4\x71\x0a\x47\xec\x73\x7f\x0a\x51\x31\x09\xb3\x62\x81\x5b\xb0\x19\xbe\x36\xdf\x2d\xc7\xee\xf4\x17\x70\x5f\xaf\x66\x9d\xab\x78\xcd\xfd\xd9\x8b\x04\x7d\xae\xf7\x67\xe7\x11\xa4\xe6\x4b\x4c\xbe\x46\x68\xa9\x99\x37\x93\xd7\x98\x15\x70\x92\xc0\x27\xda\x2a\x68\x4c\x5d\xae\xd6\x6c\xd4\x6e\x8c\xec\xdd\x6c\x99\x04\xfc\x2c\x78\xb9\x9c\x2f\x62\x6a\xd1\x88\x58\x4c\x82\xa0\x8e\xaa\x58\x71\xc9\xdf\xdf\x11\x6a\x5d\x33\xed\x9e\xd8\x18\x58\x09\xe7\x55\x2d\xed\x6e\xd0\x46\x7c\x29\xba\x48\xe5\x20\x66\x4c\x11\xcb\xee\x9c\x4c\xdd\xd9\xf0\x36\x7f\x6b\x83\x97\xc0\xd0\xd5\xf2\x72\x43\x9f\xd5\x8f\xc6\x6c\xcc\xb7\x84\x20\xe3\x58\xa5\x64\xfd\x98\xa8\x1d\xea\x83\x22\x5b\xd4\x68\x8b\xc3\x1b\x81\x85\xd8\x55\xcc\x8a\x01\x2d\xf0\xd0\xdf\x43\x7e\x95\x98\x48\xa5\xe3\x1a\x71\x42\xf0\xca\xea\xb6\xd3\x40\x9f\xfd\x0d\xb5\xde\xf3\x0e\xf0\xd0\x6f\x3a\xed\x6c\x32\xfb\x19\x83\x8c\x39\x1c\xc4\xd0\x34\xf2\x20\xae\xfa\x51\x8e\x7a\xec\xac\x6e\x9b\x87\xee\x98\xfa\x66\x03\x76\xe4\x22\x41\x1f\x85\xa2\xe3\x76\xef\xf3\x3a\x4c\xf1\xed\x6c\x54\x7c\xbb\x00\xd1\xc6\xdf\x43\xa4\x2e\x62\x53\x3b\xb8\x59\x01\x67\x6c\x40\x5c\x24\x28\x4d\xd8\x72\xc8\xb4\x4e\x2f\xba\x29\x09\xd7\x71\x2d\x6b\xe5\x45\x6a\xe6\xa2\xe3\xfb\x86\xa3\x18\xac\xc3\x3b\xab\xf7\x96\x2f\x12\x44\x92\x56\xac\xa6\xb1\xa6\x65\x9d\x74\x7d\x1d\xa0\x90\x35\x54\x9f\xf1\x07\xda\x66\xe0\x81\x8f\x65\x2f\xe5\x23\x35\x88\xcb\x3c\xf1\xee\x2c\x4f\xa1\x78\x6e\xcb\x5b\xb2\x1e\x3f\xa2\x39\x05\x1e\x47\x28\xa5\x28\xc7\xc4\x4d\x1a\xf6\xb2\xf5\x72\x6a\x45\xd7\xc7\xe8\x26\x12\x7a\x27\x99\x7a\x40\xb7\xd9\x5c\x74\x1b\xb9\x86\x64\xbe\x8f\xcd\xe4\x42\xd6\xcb\x7f\x35\x0e\x6b\x71\x4e\x8e\x54\xa6\x2b\x25\xd4\x19\xba\x0a\x89\xd4\xd8\x0a\x76\xa2\xce\x71\xf1\x45\xd8\xb7\xf3\xd7\x86\x67\x79\x6f\xa5\x5d\x55\xb0\x3d\xb4\x4d\x13\xa3\xdb\x88\xdf\xe7\xa2\x2c\x20\xf5\xe6\x4e\xa1\x04\x55\x3a\x04\xfc\x6c\x99\x52\xe7\x0b\x22\x7c\xd6\x3e\x5e\x1d\x32\xa6\xc6\xfc\x15\x75\x50\xbe\x35\xb8\xc7\xd9\x5a\xe6\xf2\x7e\xf3\xcc\xa9\x0b\x9f\x61\x3b\x42\x14\xc3\x4e\x84\x2b\xf0\x9b\xb1\x6e\x34\x58\xa3\xd2\x55\x0a\x3d\x80\x26\x23\xb8\x85\x06\xac\xdf\xc8\xe5\x2a\x06\x33\x66\xac\x8a\xc9\x7a\xe8\x2c\x62\xeb\x7b\xb8\x09\x95\x89\x93\x85\xf7\x48\x49\x8b\xec\xee\x61\x43\xda\x12\x87\xb9\xb2\x43\xc4\x93\x78\xe2\xa0\xdb\x74\x73\x25\x56\x8c\x8e\xe8\x1f\xf6\x13\xfb\x4f\x30\xca\x7a\x75\xab\xda\x7a\xe6\xa1\x4b\xd6\x40\x9e\xb0\x72\x87\xce\x42\x93\xa3\xe2\x4f\x66\xd3\xf6\x7c\x9c\xea\xb3\xb0\xcd\xa7\xdf\xa1\x73\x39\xc6\x28\xe9\x52\x44\x49\x07\x09\x02\x11\x1c\xb5\x7a\x6d\xe6\x2e\xf9\x3c\xc4\x7e\x8c\x09\x02\xb6\xd4\x60\xa6\x99\xe9\xbb\x10\xc2\xb5\xe2\x7c\x85\x88\x01\xfb\xdd\x10\xdf\xc9\xf0\xde\x20\x35\x6e\xc5\xad\x3d\xf7\x12\xe1\xc3\xef\xd7\xda\xf7\x57\x8d\x71\xda\x8f\x63\xff\x1b\x14\xfa\x49\xb7\x0e\xdd\x2f\x20\x81\xcd\xcf\x57\x69\x6e\x41\xda\x1c\x56\x6b\xf6\x0d\xd7\x75\xd5\x9d\xa3\x18\x65\xf5\x3c\xd1\x9a\x98\x4f\x42\x31\xfb\x92\xa1\xd9\x57\x3b\xd0\x82\xa1\x93\xaa\xf0\x44\xa4\x0e\xac\xe7\x62\x73\x41\x37\x73\x56\x47\x1c\xaf\xd3\x98\x6a\x27\xac\xff\xa2\xb0\xa7\xca\x56\x75\x14\x66\x2d\x05\x7f\x80\x78\x6b\xf8\xb7\x5d\x70\x0e\x86\x8d\xf9\x80\xd8\x67\x0b\xcf\x24\x85\xd3\x64\x20\xc0\x2d\x51\x11\x65\xf4\xf4\x48\x86\xc8\xbf\x0e\x15\x57\xd1\xc9\xe6\x09\x07\xfc\xe2\x91\xce\x7d\x1e\xe9\xdc\x8d\xdc\x00\x79\x29\xdc\x28\x12\x02\x93\x59\xff\xa4\x86\x1a\xee\x3d\x3c\x2f\x49\xa1\x3f\xac\x81\x61\xf5\x87\x0a\xf0\xb4\x15\xa7\xd7\x8a\x61\xb8\x8a\xdc\x10\x95\x29\x9c\x29\x1e\x04\xa6\xce\xa7\xed\xa3\x43\xfd\x23\x01\xf9\x63\x20\xf3\x3a\x0d\x33\x1b\x76\xa3\x3a\xc8\xac\x43\xfb\xd8\x90\xa7\xe8\x88\xb7\xf5\x20\x72\x45\x01\x11\xfd\xbc\x8a\x30\x1c\xae\xf0\x08\x46\x07\x4c\xcc\x21\xe0\x4a\xc4\x7c\x2e\x3c\x20\x70\x10\xb5\xa3\x12\x05\x7c\xf1\x50\xca\x83\x11\xaf\x57\xd9\x40\xe9\x59\xb3\x95\x8e\xa8\xa4\xd9\x5a\x7e\x48\x1d\x05\x40\xe1\x7d\x83\x34\x24\x4c\xd7\xca\x34\x57\xb9\x1e\x3b\x64\xc3\xc0\xe0\x6b\xec\x25\x68\x3b\x91\xcb\x95\x0a\xc3\xbb\x21\xd9\xf1\x2b\xbd\xf9\x8d\x56\x73\xaf\x24\xef\x3d\x1a\xf1\x0b\xbc\xbd\x3c\x3e\x2f\x12\x58\x36\xb6\x7d\xa9\xdb\xf6\x63\xef\x3a\xbe\xf4\x28\x39\xcb\xf4\x14\x32\x39\x69\x25\x6e\x88\x66\x11\x64\x21\xa4\x1a\x1e\xc2\x0c\x7c\xc8\x30\x88\xdc\x39\xc8\xd9\x8f\x31\x13\x5b\x2a\xad\x39\xa3\xe1\x04\xc0\x4f\xe1\x3a\x1f\x13\x34\xc3\x32\xd5\x4c\xcd\x76\xb9\x5a\x69\xd6\xac\x69\xb0\x0b\xb6\xdc\x29\xe2\xfc\x5d\xbb\x21\x3a\x8e\xe0\x8c\xf1\xa7\x81\x2f\x00\xf7\x0d\xb0\xc8\x5d\xda\x14\x99\x4c\x23\x39\xd4\xa8\x38\x97\x92\xc7\xdf\x13\x14\xd5\x3c\xea\xc9\x43\xe7\x09\xe4\xb8\xcf\xac\xd0\x99\x11\xf6\x2b\x85\x7b\x51\xc3\xb7\xa4\xbb\x50\xdc\x4b\xd0\x4e\xd2\x24\x7e\xf5\x44\x21\xec\xaf\x48\x8e\xe2\xa2\xb8\x73\x3d\x74\x12\xc1\x71\x88\xe6\xb8\x91\x06\x2b\xc6\x24\xf1\x55\x64\x22\xe5\x63\x33\x91\x6a\xce\x5e\x25\x8c\x9e\x46\xcd\xf9\xaa\x09\xe0\x83\x59\x00\x2d\xd0\x0b\xc1\xe5\x29\xe7\x72\x9d\x9a\x3f\x25\xe8\x54\x5f\x3f\x9b\x57\xa9\x31\xa2\x09\xa4\x3d\xd4\x0c\xb6\x70\xfd\x44\xd1\xe9\xb0\x00\x15\x78\x86\x60\xef\x76\x6d\xf6\xde\x26\xe8\xd6\xb4\xbc\x2f\xd8\x73\x53\xc7\x29\x30\xab\xb5\x14\xe3\x73\xd2\x3b\xff\x10\xc4\x05\xf1\xa9\x1a\xac\x83\xb4\xd2\xde\xf4\xd7\x4a\x92\xc5\x9d\xc3\x09\xfc\x02\x37\x2e\x8a\x1d\xa1\x4f\xdb\x6e\x2a\xbd\x58\x38\x76\xf9\xf2\x72\x5e\xa0\x1d\x5c\x27\xfd\xee\x8c\xd9\xb6\x4a\x95\x2f\xdb\x3c\xda\x96\xfe\xcb\x71\xd5\x5d\x35\x1c\x67\x59\xfe\x50\x83\x3a\x59\x8c\xed\xa1\x66\x79\xe8\x75\x04\x9c\xfb\x14\xfc\x96\x23\xbf\xad\x0c\x8f\x68\xe3\x89\xb0\x6b\xa2\xa8\x66\xd9\xea\x26\x4b\x03\x77\x22\x06\xcd\xc9\x63\x0c\x5c\xdb\x96\x49\x7e\xbb\x76\x6c\x5f\x18\x30\xc9\x88\x6e\xc2\x6a\x56\xa4\x25\xdb\x17\xac\xec\x3f\xce\x92\x0d\x18\xad\x16\x57\x8d\x49\x39\x12\xb6\xa4\xcd\x55\x63\x4a\x8e\x04\x2b\x47\xeb\xb2\xb2\xd2\x7c\xb4\x58\x61\x83\x53\xb0\xb2\xeb\x96\xe8\xb4\xcb\x0a\x7b\x2d\xe4\x72\xe0\xee\x0a\x66\x76\xd7\x65\x86\xd1\x70\x0e\xda\x9d\xb4\xa3\xa1\x59\x1c\x66\x5e\x30\xee\xc0\x45\x0a\xf7\x3a\x0c\x86\xb3\x34\x9d\x88\xd2\x41\x31\xd6\x22\xdd\xc6\xd3\xe8\x10\x1f\xef\x2a\xa7\x70\xdf\xb6\x91\x6d\x4a\xcc\xb1\x78\x13\x99\x20\x99\x02\x44\xb1\x19\x90\x69\x08\x0a\xe9\x20\x41\x7d\xc4\xa4\x3e\x22\xd3\x3b\x53\x31\x33\xa4\xd1\xeb\xa1\xa2\x3d\x4c\xa5\xc3\x56\x49\x13\xba\xd3\xfb\x36\x2d\x03\xaa\xd4\x55\xb2\x0a\x0f\x69\x37\xe9\xa6\x9d\xbe\x49\xaa\x0a\xde\x0f\x7b\xb4\x6f\x28\xd8\x36\xc4\x68\x99\x4a\x47\x39\xe8\x44\x98\x98\x67\x4d\x65\xae\xd2\x1b\x0a\x4f\xa6\x7a\xe1\xbc\xc8\x82\x25\xa7\x2a\x32\x70\x59\xc1\xcc\x7d\xe7\xa1\xf4\x65\x31\xc9\x3d\x1a\x89\xc3\x37\x11\xa5\xb9\xf3\xe2\x45\x92\xf9\x5e\x12\x65\x25\x75\xfe\xb9\xf9\xcf\x7f\xbc\xb0\x31\xf8\x6e\xbb\xe0\x0b\x9b\xb9\x82\xe2\x36\xad\x7e\x64\x63\x69\xbc\x41\xb1\x25\xc7\xd5\x9d\x4f\xd9\x34\xda\x11\x10\x29\x2b\x2d\xe7\x20\x46\xef\x22\x78\x13\x31\x06\x8e\x13\x74\x19\x62\x74\x1b\x62\xf4\x36\xc4\xc8\x0b\x31\x5a\x62\x34\xc3\xe8\x36\xc1\xa8\x61\x1a\xa3\x0c\x23\x1f\xa3\xab\x58\xfc\x4f\xb8\x07\xbf\xc7\x96\x15\xc5\x12\xde\x44\x70\x1f\xa7\x31\x75\xde\x47\x20\x94\xdd\x79\x17\xc1\x35\xb3\x35\xbf\xe5\x50\x2e\xe7\xf5\x6d\xb3\xa5\x73\x87\x0e\x28\xae\x30\x22\x29\x86\xf3\xc8\xbd\xaf\xb6\xe2\x10\x9d\x47\x93\x23\x2f\x4e\x5d\xf9\xf3\xfb\xf7\xfb\x0a\xae\xb3\x38\xb0\x36\x9f\xb8\xee\x5e\xf4\xf4\xe9\x5e\xa4\xca\x80\xcd\xfe\xb5\xe5\x6b\x0c\xb6\x12\xa0\xed\xba\xf4\x2e\x27\x59\x68\x05\x24\x8c\x53\xf2\xf4\xa9\xf8\x39\xf1\x16\x01\x16\xbf\xa2\x3f\xfe\xec\x5f\x74\x6f\x9d\x47\x15\xde\x22\x49\x49\xac\x38\x44\x76\x36\xff\x42\x7c\x6a\x3f\x51\xc4\x16\x59\xb0\x4c\xe4\xc2\xe4\x22\x72\x69\x14\x97\x93\xfd\x64\xc1\xb8\xae\x39\xbc\x88\x70\x98\x15\x88\x15\xf9\x10\x59\x31\x23\xc9\x4f\xb3\x8b\x3f\x2e\x22\x4c\xa3\x22\xbb\xb1\x52\x72\x63\xed\x17\x45\x56\x20\xfb\x2c\x22\x05\xb1\xbc\x82\x58\xf4\x26\xb3\xf6\x93\x85\xac\xa7\xb4\x7c\x2f\x49\x48\x60\xfd\xcb\x7e\xfe\x21\x7a\x6e\xff\xcb\xca\x52\x71\xab\x5d\xee\x5d\x92\x27\xd6\x09\x61\xbd\xa1\x72\xa7\x69\x44\x16\x13\x1b\x6f\x5d\x44\x7f\x7c\x88\xfe\x74\xcf\xf9\x8f\x8a\x37\x45\xf1\xe9\x9e\x47\xe2\x81\xa0\x3f\x21\xb7\x79\x56\xd0\x92\x3d\xc6\x13\x56\x17\x62\x25\xf1\xd6\xff\x05\x00\x00\xff\xff\x74\xa0\x08\xe0\xce\xea\x02\x00")
+
+func uiAppScriptJsBytes() ([]byte, error) {
+ return bindataRead(
+ _uiAppScriptJs,
+ "ui/app/script.js",
+ )
+}
+
+func uiAppScriptJs() (*asset, error) {
+ bytes, err := uiAppScriptJsBytes()
+ if err != nil {
+ return nil, err
+ }
+
+ info := bindataFileInfo{name: "ui/app/script.js", size: 191182, mode: os.FileMode(420), modTime: time.Unix(1, 0)}
+ a := &asset{bytes: bytes, info: info}
+ return a, nil
+}
+
+var _uiAppIndexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x53\xc1\x6e\xdb\x30\x0c\xbd\xf7\x2b\x58\x5f\xe2\x60\xb6\x8c\xde\x86\xce\x0e\x30\xb4\x3d\xf4\x30\x6c\xc0\x7a\xd9\x91\x91\x68\x5b\xab\x2c\x19\x22\xdd\xa0\x28\xfa\xef\x83\xec\xa1\x89\x33\x04\xd3\x25\xa2\x48\xbe\x3c\xbe\x67\xd6\xd7\xf7\xdf\xef\x9e\x7e\xfd\x78\x80\x5e\x06\xb7\xbb\xaa\xd3\x0f\x38\xf4\x5d\x93\x91\xcf\x76\x57\x00\x00\x75\x4f\x68\x96\xeb\x1c\x0e\x24\x08\xba\xc7\xc8\x24\x4d\x36\x49\x5b\x7e\xce\xce\xd3\x1e\x07\x6a\xb2\x17\x4b\x87\x31\x44\xc9\x40\x07\x2f\xe4\xa5\xc9\x0e\xd6\x48\xdf\x18\x7a\xb1\x9a\xca\x39\x28\xc0\x7a\x2b\x16\x5d\xc9\x1a\x1d\x35\x37\x05\x70\x1f\xad\x7f\x2e\x25\x94\xad\x95\xc6\x87\x53\x78\xb1\xe2\x68\xf7\xd5\x51\x94\x01\x3d\x76\x14\xeb\x6a\x79\x5b\xc8\x56\x47\xb6\xf5\x3e\x98\xd7\x93\x56\xd6\xd1\x8e\x72\x7c\x48\xa7\xaa\xe0\xb1\x05\xe9\x29\x12\x58\x06\x1f\x40\x22\x5a\x67\x7d\x07\xec\x90\x7b\x40\x49\x59\x20\x6f\x20\xcc\x85\x30\xa2\xf4\x60\xfd\x7c\x9f\xa2\x2b\xce\xf1\xd0\x18\x08\x9e\x14\x3c\xf5\x96\x81\x3c\x4f\x91\x18\x90\x99\x84\xc1\xd9\x67\x82\x85\x88\xfa\xcd\x80\x91\xc0\x05\x34\x64\x60\x8c\x61\xa4\xe8\x5e\x57\x70\xb6\x85\xfc\x60\xbd\x09\x07\xe5\x82\x46\xb1\xc1\xab\xf4\xff\x49\x5f\xc5\xd3\x9e\x25\xe6\xe5\xcd\x16\xae\x1b\xd8\x54\x9b\x2d\xbc\xad\xba\xd3\xb9\xd4\x0d\xcd\xe5\xd4\xa7\x04\xf6\xe5\x1f\x28\x1d\x3c\x07\x47\xca\x85\x2e\xdf\xa0\x49\xa4\x67\x8d\x36\xdb\x75\xed\xfb\x51\xf2\xea\x5c\xf3\xbf\x26\x00\x47\xdd\x64\x1f\x3a\x64\xbb\x8b\x95\x6b\xbb\x5e\x30\x02\x8e\x23\x34\xf0\xe0\x06\xf5\x0d\xad\x57\x34\xec\xc9\xe4\x26\xe8\x69\x20\x2f\x2a\x79\x5e\xc0\x5b\x92\xd3\x4c\x3a\xcd\x75\x0b\x12\x27\x2a\xc0\x50\x8b\x93\x93\xbb\x48\x28\x21\xde\x9e\x8e\xef\x7e\x4a\x88\xd8\x91\xea\x48\x1e\x85\x86\x7c\xb3\x2e\xde\x6c\xe1\xfd\x6c\x48\x1c\x47\x95\xbe\x6d\x56\x23\x45\xb6\x2c\xf7\xab\x8e\xd9\x1c\x1d\xed\x9e\xf2\x76\xf2\x33\x8f\x3c\x69\xfb\x1f\x8b\x3e\x88\xf0\x05\x22\xc5\xbc\x5a\xe7\x82\x9f\xc4\x6b\x21\xeb\x6a\xd9\x81\xba\x5a\x16\xfc\x4f\x00\x00\x00\xff\xff\x28\x2e\x82\x1a\xf1\x03\x00\x00")
+
+func uiAppIndexHtmlBytes() ([]byte, error) {
+ return bindataRead(
+ _uiAppIndexHtml,
+ "ui/app/index.html",
+ )
+}
+
+func uiAppIndexHtml() (*asset, error) {
+ bytes, err := uiAppIndexHtmlBytes()
+ if err != nil {
+ return nil, err
+ }
+
+ info := bindataFileInfo{name: "ui/app/index.html", size: 1009, mode: os.FileMode(420), modTime: time.Unix(1, 0)}
+ a := &asset{bytes: bytes, info: info}
+ return a, nil
+}
+
+var _uiAppFaviconIco = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x5b\x09\x90\x54\xc5\x19\xee\x75\x51\x52\x49\x2a\x50\xb1\xd4\xc4\x4a\x0a\xa2\x52\xae\x8b\xe2\x62\x84\x12\x63\xc4\x44\x4a\xc5\x83\x63\xb9\x2f\x05\x05\x01\x21\x20\x82\xa0\x08\xb8\x01\xc1\x8b\xa0\xd1\x35\x8a\x28\x02\x1e\x1c\xde\x8b\x88\x68\x8c\x8b\x80\x1a\x4e\x2f\x64\x41\x81\x15\x99\x99\x9d\x6b\x67\x76\x76\xae\x9d\x99\x37\x5f\xea\xef\xe9\x1e\xde\xbc\x9d\xf7\x5e\xcf\xb0\x5a\xf9\xaa\xfe\x7a\xbb\x33\xaf\xbb\xff\xee\xfe\xef\xee\x61\xac\x84\x95\xb2\x8e\x1d\xe9\xd9\x99\x4d\x6a\xc7\x58\x4f\xc6\x58\xe7\xce\x99\xff\xd7\x75\x64\x6c\x65\x3b\xc6\x2a\x2a\xc4\xff\x5d\x18\xbb\xe6\x0c\xc6\xca\x18\x63\x1d\xe9\x3d\x96\xf9\x9c\xa3\x1d\xb3\x04\x80\xf6\x00\xfa\x02\x58\xa7\x69\x38\xee\x0b\x68\x49\x7f\x50\x4b\x6a\x1a\x8e\x01\x78\x09\x40\x1f\x00\xa7\x99\xb4\xfd\x2d\x80\x6a\x00\x81\x58\x4b\x1a\xcf\xbe\xd6\x8c\x01\xd3\x3d\x18\x38\xc3\x83\x55\x6f\x87\xd1\x92\x48\x03\x80\x1f\xc0\x3f\x00\x9c\x91\xa7\x6d\x0d\x04\xea\x8e\x26\x30\x66\xae\x0f\x95\x33\x3c\x9c\xc6\xce\xf7\xe1\xc8\xf1\xa4\xfc\x9a\x3a\xda\x20\xfb\x20\x7e\x00\x3c\x49\x5f\xa4\x34\x60\xe3\xd6\x28\x1e\x7f\x29\x84\x07\x9f\x6f\xca\x21\xfa\x6c\xf3\xf6\x28\xb4\x74\xb6\x8f\x87\x01\xb4\x03\x70\x3d\x80\x46\xfa\x30\x91\x4c\x63\xd1\xb3\x41\x0c\xbe\xcb\x8b\x61\x77\xe7\xd2\xa0\xbb\xbc\x78\xe4\x85\x26\x3e\x86\x80\x1b\xc0\x55\xb4\x56\xf2\x83\xe6\x48\x1a\x6b\x37\x87\xf1\xd4\xba\x10\x9e\xde\xd0\x9c\x43\xf4\xd9\xfa\x2d\x11\x44\xa2\x69\xe8\xb0\x02\xc0\x0f\xf2\x9f\xd5\x35\x61\x5c\x3a\xdc\x85\x8a\x21\x4e\x74\x1d\x98\x4b\x97\x0c\x73\xe1\x8f\xc3\x5d\x78\xe5\xdd\xb0\xbe\xfd\x41\x00\x49\xc9\xfb\xbb\xdb\xa2\x78\xf3\xc3\x08\xfa\x4d\xf3\xa0\x7c\xa0\x13\x17\x56\x66\xa8\x7c\x80\x13\x93\x16\xf9\xf9\xda\xd0\x3b\xc9\x54\xb6\x7d\x48\xb6\x97\xd8\xb5\xbf\x05\x3d\x46\xba\xd0\xb5\x32\xb7\xfd\x8d\x53\x3d\xf0\x34\xa6\x60\x00\xb5\x3f\xa6\xff\x60\xc7\xbe\x38\xba\x0f\x33\xb4\x1f\xe8\x44\x9f\xdb\xdd\x70\xb8\x5b\xb5\xaf\x03\xf0\x8a\xfe\x83\x1f\x1a\x52\xb8\x76\x92\x1b\x17\x0d\xca\xcc\xfb\xb2\xd1\x2e\x74\x1f\xea\xc2\xad\x0b\x7c\x88\xc6\xd2\xc6\xf6\xcb\x01\x5c\x0b\xc0\x27\x3f\xa0\xfd\x99\xfb\x44\x00\xe3\xab\xfc\x7c\xcd\x06\xcf\xf4\x72\xde\xdf\xf8\x30\x62\x6c\xeb\x02\x70\x25\x80\x53\x01\x3c\xa6\xff\x82\xd6\x88\x64\xe5\xea\x09\x6e\x3c\xb4\xb2\x09\x8f\xbd\x18\x82\xc3\x93\xc3\x3b\x31\xb2\x18\x40\xa9\x90\xc1\xb3\x00\xbc\x2e\x3e\x47\x24\x96\x86\xb7\x51\xc3\xcd\xf7\xf9\xb0\x7b\x7f\x0b\xbe\x77\x26\xf5\xbc\x93\x04\xbd\x0c\xe0\x74\x83\x0e\x9c\x09\x60\x99\xd0\x11\xbe\x47\xaf\xff\x3b\x02\x7f\x50\xd3\x8f\xeb\x01\xf0\xa0\xb1\xad\xae\x8f\xd3\x84\x8e\xae\x01\x70\xa4\x25\x91\x8e\xa6\x34\xd0\xc4\xbf\x03\xf0\xbc\x90\xd7\x53\xf5\x6d\xe2\x9d\x18\xab\x6f\xcf\x58\x6d\x29\x63\x55\x25\x19\x32\x83\xfc\x9e\xde\xa5\x36\xd4\xb6\x4c\xd8\x98\xab\xf4\x76\xa6\xa3\xb5\x9d\x31\x83\xd0\xc7\x72\x00\xd3\x00\xbc\x01\xe0\x90\x90\xb1\x94\xa0\x20\x80\x03\x42\xe7\x26\x02\x38\x4f\xee\xc1\xc9\x40\x8c\x7b\x19\x80\x67\x00\xd4\x8b\xb1\x38\xc8\x6e\x35\x36\x69\x08\x84\x34\x24\x93\x39\xf2\x97\x00\xf0\xad\x90\x9d\x0a\x00\xa7\x14\x39\xf6\xef\x84\x4d\xf4\xea\x3b\x8f\xc6\xd3\xa8\xa9\x8d\x62\xca\x12\x7f\xc6\x8e\xde\xe9\xc1\x8c\x47\x1a\xf1\xc1\xa7\x31\x69\x4b\xf5\x70\x00\xa8\x32\xda\x55\x85\xb1\x69\xce\x3b\xa4\xdc\x4a\x90\xfd\x26\xb9\x27\x3b\x54\xd6\x3f\xa3\xff\x44\xf4\x37\xd9\x27\xb2\x67\xc9\x56\xaa\xcc\xe5\xfa\x3d\x00\x17\x2a\x8e\xdd\x47\xac\x5f\x2b\xbc\xff\x49\x0c\xdd\x06\x67\xc6\xbb\xc0\x40\xe7\xf7\x73\xa0\xc7\x08\x17\x76\x7e\xd5\x92\xaf\x29\xe1\x73\x00\x3d\x15\xe6\x9d\x77\x6c\xc2\xab\xef\x47\x70\xcb\x3c\x1f\xb7\x39\xf9\x88\xfc\xd1\x96\x4f\x62\x66\xcd\x09\x7b\x01\x74\xb5\xd8\xef\xed\xc6\x06\xcd\xd1\x34\xdc\xfe\x14\xb7\xb1\x64\x6b\x8e\xb9\xac\xc9\xe9\xc9\xbc\xeb\xf1\xa7\xb8\xbd\xc9\x83\x8d\x00\x7e\x6d\x18\xbb\x14\xc0\xd2\x7c\x2f\x3f\xff\x66\x33\xb7\xbb\xd7\x4f\xf1\xe0\x06\x45\xa2\x77\xfb\x4e\x76\x73\x3b\x95\x07\x24\x0f\x73\x0c\xe3\x5f\x2e\x6c\x58\x2b\x90\x6f\x3d\xf7\x06\x07\xdf\xdf\x42\xa8\xcb\x8d\x0e\xce\xbb\x09\x8e\x92\x3d\xd1\xcd\x7d\xb9\xd9\x8b\x34\x87\xdb\x17\xfa\xb9\x9f\x2c\x84\x26\x2e\xf4\x73\x9d\xb4\xc0\x03\x62\xfc\xae\x82\x9f\xbc\x20\x7d\x27\x1b\x53\x0c\x91\xbe\x5a\xe0\x0b\x21\x73\xd3\x8c\xbe\x5e\xc2\xdf\xa4\x61\x5e\x75\x00\x23\xe6\x78\x31\xea\x9e\xc2\x88\xda\x2c\x5e\x11\x44\x28\xac\x99\x4e\x0d\xc0\x50\x61\xcf\x5b\x41\xd3\xc0\xfd\x2b\xf9\xfa\xac\x9e\x0f\x28\x80\xfa\x67\x62\x8c\xe5\xaf\x35\x23\x6d\xbe\x0c\xd5\x22\x56\x6a\x85\x9d\x5f\xb7\xf0\x18\x83\x64\x89\x78\xa0\x58\x83\x62\x8f\x0b\x2b\xad\xe9\xe2\x21\x4e\x5c\x3c\x38\xc3\x03\xb5\xed\x3d\xae\x01\xfb\x0f\x27\xcc\xc6\xdf\x26\xfc\x58\xee\xdc\xd3\xc0\xd2\x55\x4d\xa8\x9c\xe1\xc5\xbd\xff\x0c\xe0\xc5\x77\xc2\x98\x5f\x1d\xb0\x1d\x9f\xf8\xec\x33\xc1\x8d\x35\x1b\xc3\x78\xe2\x95\x10\xa6\x3e\xd8\x88\x9b\xfe\xe6\xc1\x33\x1b\x4c\xf5\xe0\x88\xd0\xc7\x56\x6b\x4f\xb6\x26\xd8\xac\xf1\xb5\xf3\x06\x34\x1e\xeb\x92\xad\xb7\x9b\x3f\xf1\xf8\xc2\x5b\x99\x58\x34\x99\x4a\xc3\x17\xd4\x78\x5f\x26\x7b\xe0\xd5\xfb\x54\x33\xbc\xb7\x23\xc6\xd7\xd4\x6e\x6c\x22\x5a\xf7\xd1\xf7\xfa\x78\xcc\xad\x00\x1a\xbf\xc9\xee\xa5\xea\xb5\x21\xde\xaf\xca\xf8\xb4\x07\x14\x1f\x92\x2d\x56\xc0\x61\x11\xb7\x58\x62\xd9\x9a\x50\x56\x9e\x55\xc6\xef\x7d\x6b\x83\x3e\x2f\xb2\x42\xad\xc8\x99\x2c\xf1\xf2\xa6\x30\xef\x57\x65\x7c\x92\x91\xeb\x26\xbb\xd1\xe0\x53\x9a\xff\xe3\x00\xee\x30\xb3\x3f\x12\x7b\xbe\x69\x41\xcf\x51\xae\xbc\x3c\x50\x3e\xd1\x6b\xb4\x8b\xc7\xf4\x7c\xff\xfb\x3b\x31\xe1\xef\x7e\xc4\xad\x6d\x1f\x81\x9c\x53\x25\x80\x32\x11\x07\x9b\xa2\x29\xac\x61\xe4\x3d\x5e\x2e\x03\xa4\xdf\xdd\x06\xe7\xe6\x30\x43\x67\x79\xb9\x9e\x4b\xfe\xd6\xd4\x84\x55\xe6\x4e\xb1\xc0\xd9\x14\x1f\xca\x3c\xd5\x0a\xff\x5a\x1f\x42\x59\x7f\x07\xcf\x5b\x28\x07\x96\xba\x48\xcf\x99\x4b\x33\x7a\x4e\x71\x11\xc5\x84\x4e\x8f\xd2\xda\x2f\xd0\xf9\xdf\x1e\x22\xef\x31\xc5\xbe\xba\x16\x1e\x5f\xcd\x5e\x16\xc0\xda\xcd\x11\x5c\xa4\x9b\x3f\xe5\xb0\x94\x57\x11\x2f\x64\x7b\x14\x40\x31\x56\x17\xdd\xf8\xa7\x88\xbc\xc9\x14\xe4\xcf\x28\xd6\x7d\xe1\xed\x30\xaf\x03\x5c\x7e\x73\x66\xbd\x29\xf7\xa5\xdc\x92\x7c\xcd\x5f\xc6\xbb\x79\x4e\x65\x03\x7a\xe1\xce\x3c\xf1\xd7\x6f\x00\x7c\x68\xd6\x88\xec\xc9\x7d\x4f\x06\x70\xf8\x87\x24\x7c\x01\x0d\x37\x4c\xf5\xa0\xac\x9f\x03\x43\x66\x79\xb9\x7c\x6c\xda\x16\xe5\x3e\xdf\xc6\xe7\x12\x5e\x05\xd0\xc1\x24\x06\xec\x0e\xe0\xeb\x7c\x8d\x48\x9e\xeb\x9d\x49\x1e\x90\x87\x22\x1a\x86\xde\xed\xe5\xfe\x85\x6c\x13\x81\xe2\x3d\xf2\x75\x36\x72\xff\x29\xe5\x46\x36\x31\xf0\x15\x66\x3c\x64\x79\x49\xa4\xf9\x7e\x93\x7f\xfc\xfa\xdb\x13\xbe\xcd\xe5\x4d\xe5\xcb\x41\x24\x3e\x03\x70\xb1\xd5\xd8\x3a\x1e\x28\x6f\xfa\x20\x9f\x6f\x92\x20\x9f\x46\x31\x46\x73\xd4\x76\xbd\x93\x22\xc6\xe8\xa2\x32\xb6\x8e\x87\x33\x45\xee\xe4\xc8\xd7\x29\xe9\x58\xf5\xba\x90\x9d\x9f\xa1\xb8\x6e\x26\x80\xa2\x32\x5f\xa1\x17\x15\x22\xff\xa7\x38\x25\x27\xb9\xa1\xf8\x3e\x4f\xbe\x15\x13\xfb\xb7\x58\xd8\x36\x8b\xcc\xbd\x20\x3e\xce\x01\x30\x16\xc0\x4a\x00\xbb\x85\xbd\x08\x09\xff\xe9\x10\xfb\x4b\x79\xf2\x08\x00\xbf\x57\x1d\x17\xc1\x0e\x40\x55\x09\xd2\x8c\xdd\x9f\x62\xac\x77\x9c\xb1\x4e\x41\xc6\x3a\xd4\x33\xd6\xbe\x36\x43\xa5\x55\x8c\x95\x48\xb2\xeb\x4f\xf7\x6e\x69\x6d\x86\xda\x53\x5f\xd4\x27\xf5\x4d\x63\xa4\x69\x4a\x55\x25\xa0\xb1\xcb\x18\x63\x15\x8c\xb1\xb1\xfa\x3a\x85\xa5\x86\x14\x07\x00\xbf\x02\xd0\x0b\xc0\x74\x51\xdb\xda\x43\x62\x24\xe2\x60\x59\xc7\x08\x8b\xba\xdf\x67\x62\x9d\x6f\x17\x36\xe1\xe7\x6d\xcf\x91\x12\xcf\x94\x1b\x5d\x00\x60\x16\x80\xff\xa8\xc6\x6b\x06\xdd\xa3\x39\xbe\x03\x60\x12\x80\xce\x6d\x21\x8f\x0a\x7c\x4b\xbd\x79\x42\xac\xa7\xa9\x92\x92\xbd\x24\xdf\x42\xb1\xae\x85\xed\x82\xb0\x45\x87\x00\x2c\x12\xf5\xa5\x1f\x65\x1e\xa2\xe6\xbd\xd0\xcc\xee\x40\xd4\x00\x3f\xaf\x6b\xc1\xb2\x35\x4d\xb8\xed\xfe\x4c\x3d\x7c\xd0\x5d\x5e\x9e\x77\x3e\xbd\xbe\x19\x07\xeb\x13\xb2\x9e\x9d\x0f\x69\x31\x8f\xe9\xc5\xda\x25\x13\xbe\x4b\x00\xf4\x16\x39\x8d\xa9\xdd\xa6\x75\xa6\x78\xf6\x4f\x37\x37\x64\xf3\x34\x59\x47\x92\x7f\x5f\x3d\xde\xcd\xcf\x06\x62\x71\xcb\xfd\x20\xd9\x7a\x1b\x40\xb7\x36\xe0\xfd\x54\x00\xb7\x59\xad\x39\x44\x2e\x5e\xf5\x74\x30\x1b\x67\x5b\xc5\xc0\x15\x43\x9c\xbc\x1e\x96\x32\x5d\x89\x2c\xea\x00\xdc\x58\xac\x3c\x89\xda\xee\xec\x7c\x79\xa4\x11\xef\x7c\x1c\xe5\x79\xac\x4a\x2c\x4f\xef\x50\x8c\xb5\x7b\xbf\x69\x3d\x4d\x8f\x06\x00\x63\x0a\xad\x75\x8a\x75\x9f\x2d\x62\x71\x4b\x90\xcc\x4f\x7b\xa8\x91\xd7\x75\x28\xce\x55\x21\x7a\xf7\xe1\x95\xb6\xe9\x9d\x84\x0f\xc0\xe8\x42\xf6\x01\xc0\xad\x2a\xeb\x4e\x20\x59\x7e\xec\xc5\x10\xa6\x3f\xdc\xc8\xeb\xb5\x2a\x44\xf3\xa5\x5c\x5a\xb3\x97\x21\x09\xb2\xb5\xd7\x29\xf2\x4e\xba\x7a\x5c\xb9\xe7\x9f\x0e\x5f\x91\xcf\xb1\xe1\x9d\x62\xf5\xad\x56\x9d\x50\xfe\xbb\xba\x26\xcc\xed\xc8\x6a\x49\x35\x45\x92\x68\x4f\x7d\x51\x2e\xec\xf6\xdb\xba\xc0\xb5\x00\x7e\x61\xc2\x7b\x89\x88\x2b\x2d\x8d\xdb\xbb\xdb\xa2\x59\x5b\x42\x39\x56\x9b\xd0\x00\x27\xcf\xe1\xf6\x1e\xb0\xd5\xe9\x38\x80\x71\x26\xfc\x77\x57\x91\x1b\xe2\xbf\x9b\x62\xcd\x46\x95\xc8\x26\xf5\x1c\xe5\xc2\x3e\x7b\xfe\x09\xfb\x28\x0e\x35\xf0\x7e\x8a\xa8\xf9\xd9\x62\xd3\xc7\x51\xbe\x66\xaa\xb6\x46\x8d\x1c\x3c\x5f\x55\x58\x7f\x08\xf9\x98\x65\xe0\xbf\x5c\x7f\x2e\x6c\x85\x2f\x0f\x25\xb0\xe0\xa9\x20\xe6\x57\xb7\x1d\xcd\xab\x0e\xf0\x73\x70\x85\x1c\x5b\x82\x62\xdc\xb3\x74\xfc\xdf\xad\xda\xf0\xff\x04\xb4\x51\x43\x04\xef\x1d\x44\x0c\xac\x84\x63\xae\x24\x6a\x77\xc5\x50\xbb\xbb\x0d\x69\x57\x0c\x5b\xf7\xc4\x55\xec\x8f\x1e\xab\x44\x1c\xdf\xcb\xec\x8c\xc5\x08\xca\xe3\xc7\xce\xf3\xf1\x9a\x2b\xc5\x0b\x6d\x45\x15\x43\x5d\xbc\x7e\x46\x3e\xb0\xb1\x49\xd9\xa9\x1d\x00\xd0\x09\xc0\x9d\x2a\xb9\x47\x3c\x91\x89\xd1\xca\x15\xeb\x95\x05\xdb\x20\xf1\xa4\xd8\x3b\xa5\xb6\x0d\x94\xd3\xdd\x24\xce\xf6\x6d\x41\x31\x1a\xd9\x08\xd5\x7a\x6b\xb1\x76\xb4\xd7\x68\x17\xb6\xef\x8d\xab\xb0\x44\x76\x68\x81\xd0\x65\x4b\xc8\x73\x02\x8a\xeb\xf9\xb9\x8d\xee\x1c\xa6\x58\x5f\x70\xd1\xa0\x4c\x5b\x7d\xae\x20\xcf\x84\x26\x2e\xf2\x23\x6c\x5f\xff\x81\xb8\x17\x60\x59\xdf\x24\x6c\xd8\x12\xc9\x9e\xf5\xfc\x75\xbc\x9b\x9f\xf5\x2e\x5e\x11\xe4\xb5\xa6\x6b\x26\xba\x8b\xda\x93\x4b\x86\xb9\x78\x1f\xd5\xeb\x42\x98\xba\xc4\xcf\xeb\xb4\x97\x8d\xce\x9c\x25\xd1\x38\x1f\xed\xb4\x3c\x23\x94\xf8\x44\xd4\x09\x4c\x41\x31\xe2\xfa\xf7\x22\x3c\xff\x23\x3b\x71\xd4\x91\xcc\x9e\xff\xae\x7c\xb3\x59\xf9\xfc\x24\x5f\x2e\x43\xeb\x1c\x0a\x6b\xfc\x3c\xc7\xd3\xa8\x71\xdf\x42\x72\x4a\x79\x1c\x3d\x15\x70\xd0\x2a\x27\xcc\xce\x21\xcf\x56\x92\x1d\xed\x7b\x87\x5b\xe9\xec\xc9\x8c\x28\x17\xdb\x64\xc2\xa7\x62\x6c\xfd\xbd\x0a\xff\xf9\xb0\x7e\x4b\xe4\xa4\xf5\x95\x64\x7d\xe6\xd2\x46\x55\x7b\x63\xc6\xbf\x6d\x8e\x65\x44\x3a\x0d\x7e\xfe\x58\xa6\x78\xf6\x64\x25\x43\xfd\xa6\x79\xb8\x7d\x28\x12\x75\x76\xb9\x79\x3e\xc4\x5a\xd2\x18\x37\xdf\xa7\x7c\x76\x66\x65\x2f\xaf\x1c\xd7\xc0\x6b\xff\x45\x62\x3b\x80\x9d\x85\x36\x22\xfd\x1d\x33\xd7\xa7\x7c\xf6\x68\xc5\xff\x15\xb7\x34\xf0\xba\x50\x91\x20\xdf\xb5\xba\xd0\x46\x89\x64\x1a\x93\x1f\xf0\xb7\xc9\xfa\x5f\x75\x5b\x03\xb7\x69\x45\x80\xac\xca\x5c\x00\x53\xec\xce\x19\xf3\x61\xc9\x73\x4d\x27\xcd\xff\x49\xca\x7f\x48\xdc\xbd\xbd\x54\xc5\x87\x19\x51\x53\x1b\x45\x37\x85\x7b\x0b\x92\xc8\x37\x55\x0c\x6d\x6d\x7f\xa6\x2c\xf1\xf3\xfd\x2c\x02\x5f\x89\x7b\x26\xbf\x14\xf7\xc0\x0a\x02\xed\xf9\xd5\x13\xd4\x7c\x2f\xbd\x33\x62\x8e\x17\x97\x8f\x69\xc8\x79\x9f\xfe\xa6\xdc\xbd\x48\x3c\x2b\xeb\x5a\xa2\x66\x5a\x10\xc8\x67\x92\xed\x96\x32\x44\x7e\x9f\xe2\x3b\xb3\x39\xcc\x79\x3c\xc0\x63\x0f\xc9\x7f\xb9\xb8\xd3\xf1\x5d\x71\xb6\x87\x82\x8b\xfe\xba\xfc\xab\x8b\xb8\xf3\x51\x10\x36\x6e\x8d\xf2\xf8\x81\x62\xdf\x4b\x87\xbb\x78\x1e\xd8\x63\x64\xeb\x39\xd0\xdc\xaa\xd7\x86\xd0\x7f\x9a\x27\xe7\x7c\xfa\xd1\x55\x4d\x56\x77\x70\xac\xf0\xa9\xfe\x4e\xab\xa8\x9d\x3c\x5a\x68\x27\x0e\x4f\x0a\xd7\xdf\xe1\xe6\x76\x94\xc7\xbd\xfb\xe2\x3c\xb6\x33\xda\x55\x8a\x13\x48\x5f\xc6\xce\xcf\x7c\x47\x6b\xdf\x77\xb2\x5b\xf5\x2e\x85\x11\xe4\xad\xa7\xe4\xa9\x9f\x94\x17\xba\x07\x9a\xb8\xbb\x7c\x7e\x3f\x07\xbf\x8b\xd7\xe0\x4b\xf1\x98\x54\x1f\x13\xc9\x3b\xd1\x9f\xd7\xb5\xf0\x73\x6a\xf2\xd9\xf4\x99\x3c\x1f\x2e\x02\x9f\xe9\x73\x77\xc3\x1c\x66\x17\x78\x0e\xc4\x63\x53\xd2\x01\xf2\x07\x14\xc7\xec\xd8\x17\xcf\xd1\x03\x9a\xcb\x80\xe9\x1e\x9e\x17\xae\x7c\xab\x99\xaf\xff\x9f\xc7\x36\xe0\x1b\xf3\xbb\x53\x56\xa0\x58\x67\xb8\x45\xfd\xf0\xf4\x42\x6d\xd1\xb6\xbd\x71\x1e\xaf\xbf\xbc\x29\x63\x47\xbe\x77\x26\x73\xf4\x94\xe6\xb6\x68\x79\x90\x7f\xf7\xdf\x2f\xe3\x3c\xee\x27\x19\x33\xb9\x83\x69\x87\xe7\x00\xfc\xcc\x8c\x7f\x76\xe2\xce\xc6\x61\xd5\x0e\x3f\xda\x15\xe3\x72\x2d\x6b\x07\xc1\x90\xc6\xcf\x8c\x78\x3e\x55\x99\xb1\x49\x5b\x77\x67\xf2\xc1\x80\xf8\x8e\xe4\xa8\x08\x90\xdc\xfc\xc1\x8a\x77\xdd\x1c\x86\xc8\x7b\xed\x76\x38\x70\x24\xc1\x49\x22\x1a\x4f\x67\x75\x98\x68\xe4\x3d\x5e\x7e\xb6\x24\xb1\xe2\xf5\x66\xee\xbb\x0b\x04\xe9\xe5\x15\x2a\xbc\xb3\x13\xf5\xc4\x49\x2a\x77\xc8\x8c\x20\x5f\x3a\x71\x61\x26\x36\x22\x19\x7a\xee\x8d\xdc\x3b\x7a\x2e\x5f\x8a\xff\xa6\xa3\x00\x9f\x4b\xf1\x71\x3f\x55\xde\x75\x73\x68\x27\xee\xcc\xfb\x0a\x9d\xc3\x82\xa7\x82\xd9\x3b\x8e\x75\x47\x5b\xeb\x29\xc9\x18\xf9\x3f\x05\x1c\xd5\xfb\xa9\x22\xe6\x40\xfb\x30\xc8\xee\x1e\x97\x11\x94\xbb\x92\xee\xf2\xdf\x90\x58\x9f\x35\x5a\x61\x37\x80\x2b\x8b\xe5\xdd\x30\x8f\x4b\xc4\x59\xb9\x92\xc3\x21\x5b\x39\xea\x5e\x1f\x66\x3c\xda\x58\xc8\x19\x91\x44\x54\xd4\x06\xcf\x6d\x0b\xde\x75\x73\xe8\x28\xee\x14\x1f\xb2\x3b\xe3\x80\xb8\xdb\x47\x7a\xaa\x78\x5f\x13\x22\x0f\xdf\x23\xce\xea\x7e\x94\x7b\x11\x22\xce\x38\x4f\x9c\xf5\x1f\xb4\xf3\x75\x64\x77\x14\xf4\x34\x21\x7e\x83\x30\x13\xc0\xd9\x3f\x06\xdf\x26\xf3\xe8\x04\x60\xbc\xb8\x03\x55\x2f\xce\x76\x54\x90\x16\x7e\xf4\x90\xf8\x8d\xdf\x08\xb3\x78\xe0\x27\x9a\x4b\x7b\x71\x17\x65\xa4\xf8\x5d\xcc\x66\x71\xcf\xe9\xb8\xb8\x97\xe2\x15\x67\x23\x5f\x88\x7b\x01\x4b\xc4\xfd\xce\x73\x8c\xbf\x6d\x2a\x6e\xfc\xfa\xf6\x00\x3d\x05\xc5\x19\xeb\x44\xcf\x7a\xc6\x3a\xd0\xb3\x96\xb1\x52\x7a\x56\x31\x56\x42\x4f\xde\x88\xb1\x34\x3d\xef\x67\x2c\x45\xcf\xde\x8c\xc5\xe9\xd9\x89\xb1\x20\x3d\x3b\x30\x56\xaf\x7f\xb6\x67\xac\x56\xff\x2c\x3d\xf1\xac\x62\xfc\x82\x52\xab\x27\xd3\x3f\x4f\x16\x79\xfa\x97\x4f\x23\x3f\x92\x4f\xc9\xb7\x9c\x8f\x7c\xca\x79\xca\x79\xcb\x75\x90\xeb\x92\x5d\x27\xb9\x6e\x41\xb1\x8e\x71\xc6\x7a\xeb\xd7\x59\xac\xfb\xff\x02\x00\x00\xff\xff\xeb\x12\x88\x54\xee\x3a\x00\x00")
+
+func uiAppFaviconIcoBytes() ([]byte, error) {
+ return bindataRead(
+ _uiAppFaviconIco,
+ "ui/app/favicon.ico",
+ )
+}
+
+func uiAppFaviconIco() (*asset, error) {
+ bytes, err := uiAppFaviconIcoBytes()
+ if err != nil {
+ return nil, err
+ }
+
+ info := bindataFileInfo{name: "ui/app/favicon.ico", size: 15086, mode: os.FileMode(420), modTime: time.Unix(1, 0)}
+ a := &asset{bytes: bytes, info: info}
+ return a, nil
+}
+
+var _uiAppLibBootstrap400Alpha6DistCssBootstrapMinCss = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x5b\x93\xe3\x36\x92\x30\xfa\x7e\x7e\x05\xb7\x27\x3a\xda\x6d\x8b\x6c\x8a\xba\x95\xa4\xb0\x63\x76\x26\xf6\x8b\x6f\x22\xec\x79\xd8\xd9\x3d\x2f\xfe\xfa\x81\x22\x21\x89\xd3\xbc\x7d\x24\x55\xc5\xb2\x56\xe7\xb7\x9f\x20\x2e\x24\x2e\x09\x80\xaa\xae\x8b\xda\xe3\xf1\xd8\x45\x01\x89\xcc\x44\x22\x91\x48\x24\xc1\xc4\xa7\xef\xff\xed\xff\x71\xbe\x77\xfe\x52\x14\x4d\xdd\x54\x61\xe9\xdc\xcf\x3d\xdf\xf3\xdd\x30\x2d\x8f\xa1\xb7\x74\xbe\x3b\x36\x4d\x59\x6f\x3e\x7d\x3a\xa0\x66\xc7\x80\xbc\xa8\xc8\x3e\x76\xcd\xfe\x5a\x94\x8f\x55\x72\x38\x36\x4e\xe0\x4f\xa7\x6e\xe0\x4f\x57\xce\x7f\x1d\x11\x87\xee\xdf\x4f\xcd\xb1\xa8\x6a\x2d\xf0\x43\xd2\x34\xa8\x9a\x38\x7f\xcb\x23\xaf\x03\xfa\x39\x89\x50\x5e\xa3\xd8\x39\xe5\x31\xaa\x9c\x5f\xfe\xf6\x5f\x1c\x0b\x49\x73\x3c\xed\x3a\xe2\x9f\x9a\x87\x5d\xfd\xa9\xe7\xe7\xd3\x2e\x2d\x76\x9f\xb2\xb0\x6e\x50\xf5\xe9\xe7\xbf\xfd\xf5\x3f\xfe\xfe\x8f\xff\xe8\xf8\xfb\xf4\xe9\xfb\x7f\x73\xf2\xa2\xca\xc2\x34\xf9\x0d\x79\x51\x5d\x3b\xf7\x8b\xae\x7b\xce\xff\x60\xcc\x94\x98\xf3\x3f\x0e\x87\x3a\x47\x51\x91\x86\xf5\x27\xb1\xdd\xf7\x9f\x8e\x4d\x96\x9e\xf7\x45\xde\xb8\xfb\x30\x4b\xd2\xc7\x4d\x1d\xe6\xb5\x5b\xa3\x2a\xd9\x6f\xd3\x24\x47\xee\x11\x75\x9d\xdb\x4c\xbd\xe9\x62\xeb\x66\xb5\xdb\xa0\xb6\x71\xeb\xe4\x37\xe4\x86\xf1\x3f\x4f\x75\xb3\x99\xfa\xfe\xfb\xad\xfb\x80\x76\x5f\x92\x06\xae\xbd\xec\x8a\xf8\xf1\x9c\x85\xd5\x21\xc9\x37\xfe\x25\xac\x9a\x24\x4a\xd1\x24\xac\x93\x18\x4d\xf6\x45\xd1\x89\xea\x88\xc2\x18\x55\x93\x3c\xbc\x9f\xd4\x28\x6a\x92\x22\x3f\xc7\x49\x5d\xa6\xe1\xe3\x66\x97\x16\xd1\x97\xcb\x71\x4a\xd8\xec\x90\x6f\x02\x94\x6d\x29\x3e\x6f\xb9\x42\x99\xe3\x5f\xf6\xc9\x21\x0a\xcb\xae\xe1\x64\x9f\x1c\x4e\x15\x9a\x64\x61\x22\x23\x21\x35\x8c\x95\x29\xca\x9c\xb9\x5f\xb6\x97\x63\x75\x66\x1d\xd8\x15\x6d\x47\x22\xc9\x0f\x9b\xa8\xc8\x1b\x94\xe3\xa2\xad\xa6\x98\x0a\xc7\xdf\x16\xf7\xa8\xda\xa7\xc5\xc3\xe6\x3e\xa9\x93\x5d\x8a\x2e\x65\x85\x04\xb1\x66\x45\x5e\xd4\x65\x18\xa1\x49\xff\xb4\x1d\xfa\x33\x45\xd9\x25\x3c\xef\xc2\xe8\xcb\xa1\x2a\x4e\x79\xec\x46\x45\x5a\x54\x9b\xa6\x0a\xf3\xba\x0c\x2b\x94\x37\xa2\x84\x63\x14\x15\x55\xd8\x75\xd6\xad\xbf\x24\xe5\xa6\xd8\xfd\x13\x45\x4d\x7d\x09\x37\x61\xd4\x24\xf7\x68\x12\x6e\x8e\x1d\x4b\xe7\xe2\xd4\xe0\x51\x7c\x48\xe2\xe6\xd8\xc9\x7e\xb7\xab\x7e\x6d\x92\x26\x45\x9f\xcf\xbb\xa2\x8a\x51\xe5\xee\x8a\xa6\x29\xb2\x4d\x5e\xe4\x68\x2b\x21\xdf\x60\x75\xed\x10\xe8\x6b\x9c\xb8\x68\x1a\x14\x5f\x76\x93\xba\xa9\x8a\xfc\x40\x7a\xfd\x40\x04\x93\xe4\x47\x54\x25\x0d\x5c\xb9\x2b\xd2\x18\x55\x97\xa8\x88\xd1\xe4\xcb\x2e\x9e\xd4\x61\x56\x5e\x29\xb3\x78\x9f\x53\xad\x68\x1e\x53\xb4\x49\x9a\x30\x4d\xa2\x4b\x16\x56\x5f\x54\x61\xfe\x69\xbf\xf7\xb7\xf4\xd1\xf7\xfd\x4b\x9d\x85\x69\xca\xe9\xd4\x9d\xff\xfe\x52\x9f\x76\x93\xfa\x54\x72\xa5\xab\xc5\x7b\x61\x1e\xf8\xdb\xb2\xa8\x13\x2c\x82\x0a\xa5\x61\x27\xec\xed\x3d\xea\x34\x3a\x4c\xdd\x30\x4d\x0e\xf9\x66\x17\xd6\xa8\x6b\xd2\x61\x3b\x53\xe9\xba\x5e\xb0\x40\xd9\xa5\xc3\xdd\x14\xe5\xc6\xf5\xba\x5f\xe1\x29\x4e\x8a\xc9\x7d\x12\xa3\xa2\xd7\xd3\x24\xc7\xd4\x88\xba\x62\x80\x4d\x5e\x34\xdf\xfd\xda\x69\x5d\x55\xa4\xf5\xe7\x8f\x3d\x28\x1e\x31\xc6\xd6\x25\xc9\x0e\x6c\x44\x89\x30\xba\xea\x4b\x7d\x7f\xc0\xed\x37\x55\x51\x34\x1f\xcf\xbd\x9a\x1e\x93\x38\x46\xf9\x65\x77\x6a\x9a\x22\x9f\x24\x79\x79\x6a\x26\x45\xd9\x74\x02\x2b\x27\x35\x4a\x51\xd4\x4c\xba\x21\x0f\x2b\x14\xea\xcc\x03\x37\x14\x9d\x09\x50\xac\x45\x3f\xe1\x79\x2a\x67\x65\xa6\xd0\x5a\x42\xf4\x8c\xf5\x0c\xeb\xfd\xbe\xa8\x88\x56\x5e\x7e\x6d\x1e\x4b\xf4\x63\x85\x6a\xd4\x7c\x9e\x90\x1f\xf5\x69\x97\x25\xcd\xe7\x09\x6d\xdc\x59\x31\x87\xd4\x90\x92\xcf\xfd\x84\x0e\xcb\x12\x85\x55\x98\x47\x68\x43\xaa\x2e\x02\xdc\x66\xe3\x66\xc5\x6f\xee\xbe\x88\x4e\xb5\x9b\xe4\x39\xaa\x26\x3c\x39\x6d\x35\x65\x00\xa8\x27\x88\xd5\x0a\x75\x74\xb6\x65\x18\xc7\x9d\x49\xf1\x25\x9e\x86\xa6\x55\x92\x1f\x44\x86\xc0\x3a\xc6\x8d\x54\x49\x59\x11\x4b\x99\x4d\xd8\x4c\xcb\x96\x4e\x5e\xe7\x2f\x18\xf0\xbf\x50\xdb\x5c\xf6\x09\x4a\xe3\x1a\x35\x94\x5d\x0c\x55\x17\x69\x12\x3b\x75\x92\xde\xa3\xaa\x1f\x56\x27\x28\xdb\xbe\x07\xde\x6c\x81\x32\xc7\x5b\x06\xf8\xcf\xaa\xd3\xee\x14\x1d\x50\x1e\x43\x86\xb5\x37\x3c\x82\x5d\xe5\x4a\xc9\x2c\xa5\xc6\x63\xcb\xf4\xbd\x09\x77\x29\xda\x66\x61\x4b\xad\x19\xd6\xba\x5e\x84\xdb\x87\x63\xd2\x20\x17\x5b\x89\x0d\x59\xe5\x2e\x65\x55\x1c\x2a\x54\xd7\xe0\xec\xd2\x4e\xdb\x5e\xef\x7b\x55\x0d\x4f\x4d\x41\x87\x28\x3a\xa2\xe8\xcb\xae\x68\x99\x22\x56\x61\x9c\x14\x9f\x9f\xd4\x4b\x79\xf4\xf3\x53\xb6\x43\x55\xa7\x52\x14\x19\x56\x1b\xb7\x2e\x93\xdc\xa5\x7a\xae\x01\x2c\x4e\x8d\x08\x78\xa6\xf3\x90\x63\xbc\x46\x61\x15\x1d\xc1\x79\xd1\x75\x18\x0f\xfb\x96\x2d\x17\xc5\x7e\x5f\xa3\x66\xe3\x06\x65\x2b\x36\x1f\x68\x92\x02\x37\xea\x30\xa4\x22\x7f\x3a\xd8\x61\xf9\x80\xb8\xc0\x53\x7d\x68\xb3\x4f\x52\xe4\x9e\xca\xb4\x08\x63\xd6\x29\xed\x94\xc6\xa6\xa8\x5f\x6c\x62\xd4\x84\x49\x5a\x4f\x32\x94\x9f\xa4\xf5\xbf\x3e\x65\x59\x58\x3d\xf6\xa5\x69\x52\x37\x6e\xd2\xa0\xec\x12\x85\xf9\x7d\x08\x2b\xca\xa5\x41\x59\x99\x86\x0d\x12\x2c\xef\xe5\x57\x62\x43\x3f\x8b\xa5\x7f\xce\x50\x9c\x84\x4e\x59\x25\x79\x73\xfe\x7e\xb2\xd9\x84\xfb\xce\xbd\xd9\x6c\x76\x68\x5f\x54\x68\x82\x31\xfe\xdf\x53\xd1\xa0\xcd\x66\x9f\x54\x75\xe3\xa6\x08\xfb\x8a\x40\x45\x92\xa3\x49\x9c\xdc\x4b\x80\x7c\x49\x07\x91\x26\x12\x00\x57\xd0\xd5\x97\x52\x75\xc9\xd7\x12\x7b\x5b\x1f\xc3\xb8\x78\xc0\x1d\xf8\xb7\x24\x2b\x8b\xaa\x09\x39\x8f\x03\x6b\x2f\x08\xa1\xad\xb9\x84\x93\x10\x1b\xf8\x06\xc5\x67\xad\xeb\xc0\x7b\x23\x54\x50\x67\xea\x5d\x6d\xde\x39\xdf\xbd\x73\xc2\xa6\xa9\xbe\xc3\xf5\x1f\x9d\x77\x1f\xdf\x61\xa7\x8a\x9f\xe6\x65\x85\xdc\x87\x2a\x2c\x39\xc2\x83\x18\x27\x1d\xb4\x62\xc4\xfe\xb4\x5e\xaf\xb7\x65\x78\x40\xee\xae\x42\xe1\x17\x37\xc9\x3b\x2f\x74\x13\xde\x17\x49\x7c\x69\x3a\x2f\xf4\x2c\xd8\x1b\x97\x38\xa6\x2e\x5e\x19\xbb\x45\x76\xd2\x54\x67\x5d\xfb\x63\x30\x39\xce\x26\xe5\xb9\xa8\xca\x63\x98\xd7\x9b\xd9\xf6\x21\x89\x8b\x87\x7a\x33\x23\x55\x7c\x43\xdc\x5d\xda\xce\xcb\xc3\xfb\x5d\x58\x89\x9a\xe4\xed\xc2\xf8\x00\xf5\xa0\x73\x5e\x3c\xcc\x1c\x5b\x52\xa2\x22\x4d\xc3\xb2\x46\x1b\xf6\xc0\x09\x84\x40\x3a\x4d\x3c\x61\x4f\x47\xd0\x37\xda\x2b\x6d\x5c\x82\x1d\xc5\x43\x63\xae\xe8\x08\x70\x16\xc7\x31\x87\xe5\x82\xf7\x16\x4f\xb0\x8c\x17\x75\xde\x40\x68\xd8\xfa\xa0\x16\x5d\xfe\xdc\xed\x54\xee\x13\xf4\xd0\xf1\x72\x26\xcb\x45\x8c\xee\x93\x88\x7a\xc2\x94\xb5\xac\x76\x99\x8d\xa7\xcb\x72\x1d\x55\x45\x9a\xee\xc2\x6a\xf0\xb7\xc3\xd2\x3d\x26\x87\x63\xda\x19\x54\xd5\x2f\x27\x7b\x1b\xde\x43\xea\xcc\x53\x8a\xdc\xfa\xb1\x6e\x50\x36\x21\x7f\xdc\x53\x32\xf9\x4b\x9a\xe4\x5f\x7e\x09\xa3\x7f\xe0\x92\xff\x55\xe4\xcd\xe4\xdd\x3f\xd0\xa1\x40\xce\x7f\xff\xed\xdd\xe4\x3f\x8b\x5d\xd1\x14\x93\x77\xff\x1b\xa5\xf7\xa8\x5b\x96\x9c\xbf\xa3\x13\x7a\x37\xf9\xf7\x2a\x09\xd3\x09\xec\x75\x55\x28\xdb\xf2\x0e\xf5\xdc\xf7\x25\x2f\x6c\xc1\x1c\xde\x60\x1d\xec\x82\x68\x0b\x0e\xfc\xe5\xd7\x26\xdc\x25\x79\x8c\xda\x1f\xdf\xb9\xd3\x77\x9f\x37\xd8\x55\xe8\xdd\x04\x9f\x1b\xd2\xe3\x74\x42\x74\xfc\x38\x9f\x1c\x17\x93\xe3\x92\x6e\xa5\xdc\xce\xa9\xf5\xa9\x6b\xc0\x76\x14\xde\xa2\x42\xd9\xa5\x34\x81\x74\x5d\x20\x56\x20\x0e\x9b\xd0\x2d\xaa\xe4\x90\xe4\x61\xea\x12\x9b\x30\xe1\x77\x2b\xd1\xa9\xaa\x8b\x6a\x73\x44\x69\x79\x09\xe3\x18\x2f\xeb\x2a\xb2\x2d\xb7\x1b\x20\x4e\x80\x20\x91\x7e\x89\x48\x27\x45\x3a\x39\xa5\x56\xde\x8a\xd4\x29\x3a\x58\xe7\xd4\x81\x3b\xb8\x91\x33\xb4\xa3\xa0\xfe\x25\x6e\x84\xad\xcd\xca\xf7\x2f\x71\x7c\x06\xe4\xc1\x88\xa4\x68\xdf\x79\xed\x83\xb9\xea\xf7\xc7\x8e\xef\x10\xb1\x9c\xd9\x66\x25\x58\x2d\xe2\x3b\x65\x07\x86\x8d\x44\x48\x06\xab\xdf\xef\xb1\x26\xd3\x79\x74\x17\xe9\x37\x6d\x97\x90\xec\x2a\x8e\x15\xda\x7f\xfe\x48\x9e\x99\x12\x7c\xfe\x78\x16\xfd\x2f\x0d\x61\x03\x82\x9e\x29\x13\x0c\xcf\xf0\xd7\x92\x1a\x94\x15\xaf\x11\x96\x51\xdd\x8a\x8e\x9d\x18\x14\xe8\xe5\xdf\x6d\xa8\x24\x17\x31\x4b\xe2\x38\x45\x97\x5f\xab\x22\x1d\x36\x1a\x54\x31\xcb\x22\xc9\x1b\x54\x89\x95\x93\x70\xd2\x79\x92\x13\x61\x9f\x95\x86\x3b\x94\xb2\x4d\x16\xf5\x48\x86\xcd\x16\x8e\xb1\x14\xa7\xe8\xe8\x86\x38\x0c\xb2\xc9\xc2\x3c\x29\x4f\x29\x16\xc8\x56\x5b\x73\x31\x2f\x08\xea\xcc\xe7\x6d\x18\x0d\x9c\x9c\xa9\x47\x8a\x05\xe7\xad\xb0\xba\xb2\x22\xa6\xc3\xa4\x94\xaa\xd9\x72\xb6\x8c\x56\x01\x19\x35\x22\xa1\x4e\xad\xb7\x14\x9d\x8b\x57\x46\xd2\xf0\xd2\x1c\xcf\x12\xd8\x05\xcb\x01\x76\xcd\x21\x43\x42\x37\x33\xe2\x78\x0f\x7b\x18\xe6\xbb\x6e\x16\x65\xeb\x74\xe3\xea\xf4\x9e\x24\xde\x83\x75\x5b\x1f\xd2\x75\x71\xd7\x2b\x6f\x76\x21\x73\x81\x21\x25\xff\x7f\x13\x27\x75\x27\xf2\x78\xc2\xd5\x92\xdd\x40\x5f\xc5\x74\x23\x2f\xba\x8e\xa7\xc5\x03\x8a\x79\x5c\x71\xd8\xa0\xcf\x7c\xf3\x26\xc9\xc4\x82\x0e\xa2\x2b\x74\xd3\x22\x0a\x53\xa1\x2a\x2b\xf2\x06\x76\xe7\x3b\xa7\xb6\x5b\x45\xfb\x2e\x55\x08\xaf\x17\x4c\x99\x87\x2d\x5e\x96\xe4\x2c\x32\xc4\x6d\xa4\xd8\x44\xd8\xd2\x05\xde\x67\x5b\x39\xc1\x97\xde\x82\x9b\x30\xc8\xe2\x71\x2b\x16\x29\xb0\x88\xd8\xb0\x53\xc1\xf6\xa0\x38\x35\xe5\xa9\x81\x5d\x75\xd0\x29\xe7\x3d\x9b\xe3\x74\xe2\x1d\x83\x89\x77\x9c\x4d\xbc\xe3\x7c\xe2\x1d\x17\x13\xef\xb8\x9c\x68\x17\x36\xb5\x27\x74\x99\x67\x26\x8b\x37\xfb\x0b\x65\x01\x9e\x8a\x7b\x59\x4c\x5f\x8c\x64\x12\xe5\xee\x78\x3a\x06\x7c\x39\x29\x9d\x75\x5e\x23\x2f\xc0\x15\x05\x9f\x4f\x8e\xf3\xb3\x2c\xd9\x4b\xd7\x9d\xe3\x42\x28\x0f\x68\xc5\xb2\xeb\x94\xe8\x3c\x5c\xbc\xb4\xf3\x77\x15\x68\xa1\x4f\xb3\xce\xdb\xa4\xd2\x74\x79\xce\x97\x00\xa4\xdc\xfb\xa1\x25\xdf\xb7\x85\x07\x51\xd1\xb7\xe5\x25\x30\xbf\xb2\x2d\x2f\xa4\xd9\xb8\xb6\xc7\x8a\x5f\x40\xa6\xdc\xa2\xcd\xaf\x21\x6c\x72\xd0\x07\x02\xdb\xbb\xc2\xd5\x61\x17\x7e\xe7\x4f\xba\x7f\xbc\xe9\xc7\x8b\x87\x83\x8d\x13\x20\xe4\x28\x3b\x70\x17\x2f\x0b\xab\x2f\x13\x1c\xc2\xec\x83\x2b\x41\x47\x4f\x75\xdd\xa2\xfd\x1d\x9a\x5d\x3c\xbc\x89\x3d\xe5\xd8\xe9\x89\x7b\x1b\x4e\x1c\x8c\x2d\xae\xe4\x02\x82\x04\x9a\xcc\x99\x6b\x60\xf1\x2e\x19\x9e\x73\x0a\x18\x89\x38\xa6\x61\xdd\xb8\xd1\x31\x49\xe3\x8f\x4c\x9e\x15\x99\x25\x65\x7b\xf1\x92\x3c\x69\x92\x30\x4d\xea\x8c\x93\xc7\xda\x7f\xbf\x95\x02\x80\xa7\xb2\x44\x55\x14\xd6\xdd\x7e\x68\xf0\x95\x7a\xc9\x74\x03\xea\xe8\x86\x48\x55\x6c\x3a\x56\xb8\xbf\xa4\x88\x6d\x5d\x50\x84\x10\xda\xf3\x44\x5c\xf2\x66\x42\xb2\x7a\xe2\xe0\x09\xeb\x20\xd0\xb8\xdf\xbe\xf4\xdb\xda\xff\x13\xf8\xd3\xb9\xf3\x7f\x7c\xff\xdf\xfd\x77\x42\x83\x0a\xdd\xa3\xaa\x1e\xc6\x84\xc8\x6a\xca\xaf\xc1\x74\x98\xb8\x75\x14\x03\xb1\x5e\x91\x16\x50\xb7\x84\x7e\xfb\x10\x59\x67\x0c\xef\x20\xc3\x60\x4b\x69\x2f\x8f\xbb\xeb\xe0\xae\xbf\xbb\x78\x49\x76\x70\xf7\xe9\x29\xe9\xfc\x63\x21\x96\xc7\x07\xad\x30\x54\x73\x3c\x65\xbb\x3c\x4c\x52\x6e\x2a\x90\x71\x84\xf6\x31\x5b\x70\x43\xda\x4b\x27\x8c\x93\x53\xcd\x10\xf4\xbb\xbb\x4e\xd1\x48\x38\x3f\x4c\x53\xc7\x0b\x6a\x07\x85\x35\x72\x93\xdc\x2d\x4e\xcd\xd6\x2d\x6c\x10\x96\x6a\x53\x0f\xa9\xdf\x09\xcf\x29\x52\xe9\x76\x4e\x28\xb4\x12\x09\x36\xab\x87\x66\x7e\x9c\x38\xa3\x44\x25\xed\x5f\xb7\x94\x15\x52\x5f\xb9\xfc\x82\xf2\xb4\x98\xfc\x52\xe4\x61\x54\x4c\xfe\x5a\xe4\x75\x91\x86\xf5\xe4\xdd\xcf\xc9\x0e\x11\x97\xdc\xf9\xa5\xc8\x8b\x77\x93\x77\x7f\x2d\x4e\x55\x82\x2a\xe7\xef\xe8\xe1\xdd\xf0\x7a\x06\x63\xe7\x06\xab\xd3\x44\x6f\x2e\xce\x45\x8e\xa5\x5d\x3c\x9f\xce\x57\xd0\x68\xae\xf6\xab\xfd\x1a\x1c\xba\x4b\xf8\x93\x40\xc4\x97\xa2\xc5\x0a\x32\xb6\xf4\x7e\xd9\xc5\xe3\x39\xc3\xea\xa4\xb0\xc5\x76\xd1\x12\x5b\x1d\x57\x5f\x76\xb1\xc3\x53\xf0\xe5\xd7\x23\xf2\xf6\xb0\xe4\x86\x5e\x70\x7a\xb5\xbb\x16\x90\x51\xc2\x52\x87\xcd\x91\xc4\x32\x80\x33\xd1\x58\x04\xc5\xbf\x6d\x14\xbb\xe8\x5f\xbc\xb2\x42\x2e\x09\x8e\xe0\x7d\x46\xa7\xd7\x54\xfd\x66\x73\xbf\x6c\xfb\x2d\x95\xfb\x48\x63\x28\x17\xaf\x9b\xfe\x61\x92\xa3\xea\xac\xbe\x32\xe3\x77\xc1\xdd\x6c\xd8\x0a\x2b\x04\x2e\x91\x0c\xe1\x62\x78\xdb\x40\x9a\x75\x25\x2c\xdc\xfa\xdd\xe0\xc9\x2e\x56\xcb\xb2\xfd\x78\xe6\xa9\x8f\x41\x04\x60\x5a\x2d\xef\x9e\x09\xd3\x7a\x1d\x3c\x13\xa6\x69\xe0\xfb\xcf\x84\x4a\x15\x14\x2d\xc7\xe3\x29\x1a\xae\x71\xe2\xa1\xe5\xc1\xb8\xf6\xaa\x50\x68\xf9\x72\x5c\x7b\x40\x14\xb4\x62\x0a\xf6\x60\x80\xa3\xab\xcf\x9b\x6a\x25\xe3\xe1\xb9\x74\xf3\x2b\xf1\x29\x83\xf1\x95\xf8\xd4\xc1\xb9\x0a\xa1\x57\x15\x0f\xbd\x75\xe4\x42\xbf\x5b\xb9\x6c\x9f\x22\xae\x30\xab\x71\x01\x0f\x88\x01\x78\x68\xfc\xc2\x60\xd3\xfd\x67\xcb\xe0\xb9\x22\xe9\xa7\x30\xfe\x2e\xe6\x96\xd7\x11\xd7\x32\xda\x5d\x2f\x46\xa1\x30\x8c\xf0\xd7\xe0\x60\xa3\xfa\x35\x38\xfa\x91\x1c\x8f\xc4\xcb\x0b\xf7\x70\x6a\x1a\x54\xd5\x62\x0b\x5f\x8a\x7e\x72\x80\x3f\x79\x51\x91\x4e\xf8\x82\x5f\xa3\x34\xac\xeb\xef\x7f\x8c\x8a\xd4\xfd\x2c\xe9\x8d\x2f\xf9\xc4\x17\xd2\xba\x03\x9d\xd2\x3f\x3e\xfd\xcb\x7e\x07\xe4\x2f\xfd\x33\x23\x7f\xe6\xe4\xcf\x82\xfc\x59\x92\x3f\x2b\xf2\xe7\x8e\xfc\x59\x93\x3f\xe9\x81\xfd\x65\x14\xba\x27\x7f\x78\xe4\x4a\x83\xfe\x71\x78\x9a\xf5\x4f\xf3\xfe\x69\xd1\x3f\x2d\xfb\xa7\x55\xff\x74\xd7\x3f\x51\x16\xb2\x98\xfd\x65\x2c\x74\x4f\xfe\xf0\xc8\x95\x06\xfd\xe3\xf0\x34\xeb\x9f\xe6\xfd\xd3\xa2\x7f\x5a\xf6\x4f\xab\xfe\xe9\xae\x7f\xa2\x2c\xd4\x19\xfb\xcb\x58\xe8\x9e\xfc\xe1\x91\x2b\x0d\xfa\xc7\xe1\x69\xd6\x3f\xcd\xfb\xa7\x45\xff\xb4\xec\x9f\x56\xfd\xd3\x5d\xff\x44\x59\x68\x53\xf6\x97\xb1\xd0\x0e\xa3\xdd\x0e\x03\xde\x0e\x63\xde\xf6\xc3\xde\xf6\x23\xdf\xf6\x83\xdf\xf6\xe3\xdf\xf6\x2a\xd0\xf6\x5a\xd0\xf6\x8a\xd0\xa6\xee\x1a\x58\x33\x38\xef\xbe\x9b\x34\xcc\x27\xe7\xec\xda\x93\x97\x8a\x3f\x34\xfa\x0f\x8d\x7e\x79\x8d\xfe\x6a\x0f\xe4\x0f\x35\xfd\x43\x4d\x6f\x56\x4d\x07\xc7\xf6\x0f\x35\xfd\x43\x4d\x6f\x56\x4d\xb9\xfd\xd2\x1f\x7a\xfa\x87\x9e\xde\x88\x9e\x76\xf0\x67\x61\xf3\xbc\x0b\xeb\xa4\xde\xf8\xc3\xd6\xb9\xac\xd0\x1e\x55\x15\x8a\x49\xa8\xd1\xdf\x8a\x60\xdc\xa9\xad\xae\x62\x33\x15\xf7\xe2\x87\xaa\x78\xe8\xca\x7a\x6c\xd8\xbd\xbe\x47\x9b\xe9\x96\xaf\x97\x42\x39\xb8\x1b\xe1\xa9\x29\xce\x0a\x7e\x5f\xc0\x8f\x0f\x73\xe0\xb0\x0d\xa3\x30\x94\x88\xbf\x08\x76\x12\x97\xc7\xd3\x6c\x14\xea\x3b\x6f\x86\xff\xf7\x5e\xc4\x3f\x14\x03\x45\x43\x5f\xfa\x32\x42\x32\x18\x45\x72\xba\xf4\x96\xdd\xff\x56\x12\x4d\xae\x1c\x2a\xe3\x24\xd8\x17\x12\xb2\xb3\x51\x64\x83\x85\x44\xaf\x2b\x10\x7e\x0c\x14\x82\x05\x45\x3d\x1f\x85\x7a\x36\x83\xa5\xc8\x95\x43\x65\x03\xbd\xa1\x90\x90\x5d\x8c\x22\x3b\x9f\xc2\x82\xe4\xca\xa1\xb2\x81\xec\x50\x48\xc8\x2e\x47\x91\x5d\xf8\x12\xbd\xae\x40\xf8\x31\x50\x58\x30\x5d\x5f\x8d\x43\xad\x51\xc7\x05\xa0\x8f\x0b\x48\x21\x17\x92\x46\xde\x8d\x22\xbb\xd4\x68\xe4\x12\xd0\xc8\x25\xa4\x91\x4b\x49\x23\xd7\xa3\xc8\xae\x64\x8d\x5c\xf1\x1a\xb9\x12\x34\x72\xc5\x34\x72\xea\x8f\x9b\xd7\x1a\x95\xbc\x03\x54\xf2\x0e\x52\xc9\x3b\x49\x25\xa7\xe3\xec\xc9\x5a\xa3\x93\x6b\x40\x27\xd7\x90\x4e\xae\x25\x9d\x9c\x8e\x34\x2a\xbe\xac\x95\xe4\x95\x95\xf0\x4b\x36\xc2\xe5\x29\x4d\x5d\xff\x5c\x71\x6f\x34\x71\xd1\x94\x16\x71\xca\x84\xcb\x03\x5a\xce\x1b\x20\x5c\x31\xa3\x15\xd8\x6e\xe0\x92\x39\x2d\xe1\x67\x36\xae\x58\xd0\x0a\x7e\xee\xe1\x8a\x25\xad\x58\xf4\x9c\xad\x58\x89\xcc\xc7\x1d\xad\x58\xca\x7c\xac\x69\xc5\xaa\xe7\x63\xca\xba\x77\x27\x33\x32\x65\xbd\x5c\xcb\x9c\x4c\xfb\x7e\x52\x29\xd5\x47\xd7\x3f\xf7\xaf\x14\x68\xc9\x94\x94\x08\xbc\xd5\x47\x37\x20\xc5\xa2\x88\xea\xa3\x3b\x23\xe5\x54\x42\xf5\xd1\x9d\x93\x02\x51\x40\xf5\xd1\x5d\x90\x72\x51\x3e\xf5\xd1\x5d\x92\xf2\x45\xcf\xd2\x8a\x16\xc8\x1c\xdc\x91\xf2\xa5\xcc\xc1\x9a\x94\xaf\x7a\x0e\xa6\xb4\x53\x77\x32\x0b\x53\xda\xb7\xb5\xcc\xc3\x94\xf5\x0e\x0b\x86\x7c\x62\xe2\x4e\xcf\x7c\x48\x98\xe3\x86\xd6\x07\x42\x3d\x2f\x18\x0a\x30\x13\x00\xb0\x84\x68\xcd\x5c\xa8\xe1\x45\x45\x01\x16\x02\x00\x2f\x33\x0a\xb0\x14\x00\x16\x1c\xdb\x2b\xb1\x46\xe5\xfb\x4e\x00\x58\xaa\x7c\xaf\x05\x80\x15\xc7\xf7\xd4\x17\x65\xa2\x32\x3e\x15\xa5\xc6\x49\xda\x18\x4e\x74\xeb\xec\x56\xbd\xb9\x3a\x7b\x61\x87\xae\xf3\xe4\x5f\xdf\xa7\xeb\x36\x0d\x6f\xe3\xd6\x75\x9b\x94\x97\xf3\xec\xba\x8d\xcf\xdb\x38\x77\xdd\x46\xeb\x6d\xfc\xbb\x6e\x63\xf7\x72\x2e\x5e\xb7\x59\x7c\x1b\x2f\xaf\xdb\x9c\xbe\x8d\xa3\xd7\x6d\x86\x5f\xce\xd7\xc3\x3b\xfa\xb7\x71\xf7\x70\x04\xe1\x6d\x3c\x3e\x1c\xb1\x78\x61\xa7\xaf\xce\x20\xbf\x0f\x5b\x58\xd8\xf5\xc3\x66\x50\xe3\xfd\x61\x43\x25\x3b\x80\xd8\xbe\x68\x7c\x40\x6c\x01\x34\x6e\x20\x9e\xa3\xb2\x27\x88\xa7\x96\xc6\x19\xc4\xca\xaf\xf1\x07\xb1\x7a\xca\x2e\x21\xd1\x2a\x8d\x57\x48\xc6\x5d\xe3\x18\x92\x91\x51\x7c\x43\x2c\x4c\xd9\x3d\xc4\xb2\x04\x3d\x44\x2c\x4a\xd8\x49\xc4\x92\x94\xfc\x44\x2c\x48\xd8\x55\xc4\x72\x84\xbd\x45\x2c\x46\xc9\x61\xc4\x52\x84\x7d\x46\x2c\x44\xd8\x6d\xc4\x32\x94\x3c\x47\x22\x42\xd8\x79\x24\x12\x84\xfd\x47\x22\x40\xd5\x85\xc4\x12\x94\x0e\x16\x0c\x55\x36\x07\x13\x0b\xd4\xe2\x63\x62\xc9\xea\xdc\x4c\x2c\x62\x8b\xa7\x89\x65\x6d\x71\x36\xb1\xd0\x75\xfe\x26\x96\xbe\xc5\xe5\xc4\xc3\x60\xf1\x3a\xf1\x78\xe8\x1c\x4f\x32\x30\x16\xdf\x93\x8c\x90\xc6\xfd\x34\xbf\x27\x74\xb3\xf8\x56\xfd\xcf\x2c\x7e\x61\xff\x33\x8b\xdf\xc2\xff\xcc\xe2\xb7\xf2\x3f\xb3\xf8\x25\xfd\xcf\x2c\x7e\x2b\xff\x33\x8b\xdf\xca\xff\xcc\xe2\x97\xf4\x3f\xb3\xf8\xad\xfc\xcf\x2c\x7e\x2b\xff\x33\x8b\x5f\xd2\xff\xc4\x2f\xb5\xde\xc6\xff\xc4\x2f\xd1\xde\xc6\xff\xc4\x2f\xed\x5e\xd8\xff\xcc\x62\xc8\xff\xc4\x16\x16\xf6\x3f\xb1\x19\xd4\xf8\x9f\xd8\x50\xc9\xfe\x27\xb6\x2f\x1a\xff\x13\x5b\x00\x8d\xff\x89\xe7\xa8\xec\x7f\xe2\xa9\xa5\xf1\x3f\xb1\xf2\x6b\xfc\x4f\xac\x9e\xb2\xff\x49\xb4\x4a\xe3\x7f\x92\x71\xd7\xf8\x9f\x64\x64\x14\xff\x13\x0b\x53\xf6\x3f\xb1\x2c\x41\xff\x13\x8b\x12\xf6\x3f\xb1\x24\x25\xff\x13\x0b\x12\xf6\x3f\xb1\x1c\x61\xff\x13\x8b\x51\xf2\x3f\xb1\x14\x61\xff\x13\x0b\x11\xf6\x3f\xb1\x0c\x25\xff\x93\x88\x10\xf6\x3f\x89\x04\x61\xff\x93\x08\x50\xf5\x3f\xb1\x04\x61\xff\x13\xcb\xd1\xec\x7f\x62\x81\x5a\xfc\x4f\x2c\x59\x9d\xff\x89\x45\x6c\xf1\x3f\xb1\xac\x2d\xfe\x27\x16\xba\xce\xff\xc4\xd2\xb7\xf8\x9f\x78\x18\x2c\xfe\x27\x1e\x0f\x9d\xff\x49\x06\xc6\xe2\x7f\x92\x11\x1a\xef\x7f\x72\x07\x80\xdc\xf4\x70\xab\xfe\x67\x7a\x78\x61\xff\x33\x3d\xbc\x85\xff\x99\x1e\xde\xca\xff\x4c\x0f\x2f\xe9\x7f\xa6\x87\xb7\xf2\x3f\xd3\xc3\x5b\xf9\x9f\xe9\xe1\x25\xfd\xcf\xf4\xf0\x56\xfe\x67\x7a\x78\x2b\xff\x33\x3d\xbc\xa4\xff\x89\xcf\x75\xbd\x8d\xff\x89\xcf\x91\xbd\x8d\xff\x89\xcf\xad\xbd\xb0\xff\x99\x1e\x20\xff\x13\x5b\x58\xd8\xff\xc4\x66\x50\xe3\x7f\x62\x43\x25\xfb\x9f\xd8\xbe\x68\xfc\x4f\x6c\x01\x34\xfe\x27\x9e\xa3\xb2\xff\x89\xa7\x96\xc6\xff\xc4\xca\xaf\xf1\x3f\xb1\x7a\xca\xfe\x27\xd1\x2a\x8d\xff\x49\xc6\x5d\xe3\x7f\x92\x91\x51\xfc\x4f\x2c\x4c\xd9\xff\xc4\xb2\x04\xfd\x4f\x2c\x4a\xd8\xff\xc4\x92\x94\xfc\x4f\x2c\x48\xd8\xff\xc4\x72\x84\xfd\x4f\x2c\x46\xc9\xff\xc4\x52\x84\xfd\x4f\x2c\x44\xd8\xff\xc4\x32\x94\xfc\x4f\x22\x42\xd8\xff\x24\x12\x84\xfd\x4f\x22\x40\xd5\xff\xc4\x12\x84\xfd\x4f\x2c\x47\xb3\xff\x89\x05\x6a\xf1\x3f\xb1\x64\x75\xfe\x27\x16\xb1\xc5\xff\xc4\xb2\xb6\xf8\x9f\x58\xe8\x3a\xff\x13\x4b\xdf\xe2\x7f\xe2\x61\xb0\xf8\x9f\x78\x3c\x74\xfe\x27\x19\x18\x8b\xff\x49\x46\x68\xbc\xff\xc9\x9f\xec\x75\xdb\x9b\x3d\x4e\xd9\xbe\xf4\x89\xca\xf6\x4d\x0e\x55\xb6\x6f\x76\xae\xb2\x7d\xd1\xa3\x95\xed\x9b\x9d\xae\x6c\xdf\xec\x80\x65\xfb\xa2\x67\x2c\xdb\x37\x3b\x66\xd9\xbe\xd9\x49\xcb\xf6\x45\x0f\x5b\xb6\x6f\x77\xde\xb2\x7d\xbb\x23\x97\xed\x2b\x9c\xba\x6c\xc1\x83\x97\xad\xfe\xec\x65\x6b\x38\x7e\xd9\x42\x27\x30\x5b\xc3\x21\xcc\xd6\x70\x0e\xb3\x85\x8e\x62\xb6\x86\xd3\x98\xad\xe1\x40\x66\x0b\x9d\xc9\x6c\x4d\xc7\x32\x5b\xd3\xc9\xcc\x16\x3e\x9c\x89\x85\x29\x3b\xa0\x58\x96\xa0\x03\x8a\x45\x09\x3b\xa0\x58\x92\x92\x03\x8a\x05\x09\x3b\xa0\x58\x8e\xb0\x03\x8a\xc5\x28\x39\xa0\x58\x8a\xb0\x03\x8a\x85\x08\x3b\xa0\x58\x86\x92\x03\x4a\x44\x08\x3b\xa0\x44\x82\xb0\x03\x4a\x04\xa8\x3a\xa0\x58\x82\xb0\x03\x8a\xe5\x68\x76\x40\xb1\x40\x2d\x0e\x28\x96\xac\xce\x01\xc5\x22\xb6\x38\xa0\x58\xd6\x16\x07\x14\x0b\x5d\xe7\x80\x62\xe9\x5b\x1c\x50\x3c\x0c\x16\x07\x14\x8f\x87\xce\x01\x25\x03\x63\x71\x40\xc9\x08\xe9\x1c\x50\x9a\x18\x9a\xff\x2a\x5d\x4c\x41\x05\x24\xb9\x85\x52\x44\xf7\x99\x92\x48\xc2\x4f\x29\x11\x6a\x53\x94\x70\xde\xbb\x3e\x8f\x1a\x43\x84\x42\x9c\x2b\x5a\xce\xb5\x8f\xa9\x6f\xc5\x1b\x48\x02\x2d\x96\x5d\x11\x3f\xfe\x80\xff\x7b\xe6\xa8\x6a\xe1\x59\x72\x6c\x30\xd9\x31\x4d\x64\x5d\x67\x5c\x56\xeb\xee\x07\xd7\xe5\xd9\x20\x94\x3e\xe1\x35\x90\xed\x5a\x20\x7a\x7d\xb2\x6c\x5d\x73\x22\x32\x08\x09\x95\xa5\x20\x35\xe6\x18\x96\x6d\xdf\xb3\xa6\x4a\xca\x0e\xbe\x93\x97\xd3\x54\x9b\xbc\x39\xba\xc5\xde\x6d\x1e\x4b\xf4\x5d\x11\xc7\x1f\x55\xc1\xf0\xd9\x0a\xfd\xc5\x47\x86\x09\x67\xe8\x1d\xf0\x90\x84\xbd\xe6\xc6\xab\xa1\x35\xbd\x89\x46\xf8\xf5\xd3\xd0\x2f\x56\x00\x64\x23\xd7\x61\x24\xfc\x08\xed\xaf\x65\x4a\x8b\x82\xe3\xcc\x00\x73\x05\xb3\xf5\x29\x8a\x50\x5d\x4f\xc4\x9f\x1c\x99\xbe\x04\xca\xc7\x1e\xef\xf7\x7e\x7c\x07\x72\x4d\xdb\xe9\x7a\xfe\xa7\xd8\x47\xeb\x68\x69\x6f\xaa\xeb\xb1\x04\x04\x72\x27\x90\x48\xf2\x7d\x31\xe1\x9e\x39\xc4\xe4\x27\x88\x62\x8d\xe2\xfd\x0a\xe4\xb2\x6b\xa4\xed\x5d\x34\x47\xb3\xfd\xcc\xd2\x4e\xd7\x35\x1e\x02\x62\x4a\x44\xfe\x10\x56\x79\x92\x1f\x26\xe2\x4f\x0e\x77\x5f\x02\x66\xd4\xa7\xd9\x39\x01\x36\x68\x3b\x6d\x1f\xf7\xe1\x3e\x88\x22\x7b\x53\x5d\x37\x25\x20\x90\x3b\x81\x44\x1c\xe6\x07\x54\x4d\x84\x5f\x1c\x72\x56\x00\x22\x0a\x62\x14\x23\x90\x57\xd2\x4c\xdb\x4b\xb4\x8b\x22\x4d\x2f\xf9\x96\xba\x4e\x8a\x30\x10\x6b\x3d\x81\xce\x70\xba\x49\x4e\xd2\x55\x36\xc7\xf3\x88\x1c\x7f\xac\x55\x8c\xf6\xe1\x29\x6d\xb8\x56\xf3\xe5\x3c\x9c\x43\x99\xf4\x45\x7b\x4e\xc9\x8d\xa4\xc5\x37\x71\xf8\xe9\xc3\x78\x56\x4b\xc4\xc5\x40\x5d\xe0\x28\xa4\x66\x19\x63\x37\x48\xb8\x15\xaa\xcb\x22\xaf\x93\x7b\x39\x1b\x21\xe7\x32\xf4\xb9\xfd\xda\x4d\x1f\xfa\x91\xee\x4d\xe8\x8a\xba\xba\x63\x82\xbf\x21\xee\xaf\x51\x50\xc9\xe8\x19\xda\x17\x55\xe6\xd2\x7b\xae\xec\xb9\xa6\x49\xea\x57\xea\x9e\x48\x97\x22\x88\x19\x7d\x83\xfe\x16\x04\xed\xd8\x49\xc3\x93\x64\xe1\x81\x5e\xd1\xd4\x6f\xe4\xb8\x36\x69\x52\x6e\x86\xbc\xe8\xed\xd6\x58\x27\xaf\xfb\x42\x66\xe0\xc5\xc7\xd1\xe9\x49\xf9\x81\xe6\x53\x8c\x3a\xde\x74\x51\x4f\xf8\xfd\x26\xb9\x91\x45\x81\xd9\x3e\x2b\x32\x31\x33\xaa\x19\xdf\xb3\x30\xf5\xd2\x48\xc6\xf4\x5a\xd4\xd1\x0d\xd6\x7a\xd4\x96\x61\x1e\x9b\xef\xee\x83\x75\x9c\xa6\xb2\x1f\xa5\x9b\xc2\x2c\x5f\x44\xbb\xd9\x7e\x48\x78\x2f\xa3\xe5\xee\x8f\x2a\x4f\x8d\x5b\xa6\x61\x84\x8e\xf8\xae\xbd\xb3\x98\xb7\xbf\x28\xc3\x28\x69\x1e\x71\x02\x59\xa9\x5f\xc5\x6f\x4f\x68\xd7\x89\xe3\xc9\x34\xaf\x6f\xd2\x27\xe0\x17\x8a\x7f\xad\x50\x18\x17\x79\xfa\xf8\x19\x5a\x12\x48\x3a\x64\x1b\x46\x28\x6f\x3f\xb9\x27\x40\x84\xc7\x77\x51\x74\x66\x87\xdd\x4b\x91\x9d\xd2\x26\x29\x53\xf4\xf9\x23\xbb\x81\x2b\x0a\xd3\xe8\xbb\x80\x26\x65\xfe\xc1\x09\xca\xf6\x23\x88\x0a\xeb\x02\xd1\xa8\xfb\x30\x3d\xa1\x31\x6a\x21\x72\x8f\x6f\xcc\x12\x65\xe1\x56\xdd\x22\x29\xdd\x81\x85\xa3\x54\x18\x8a\x5c\xc0\xc0\x5f\xfa\x80\xb9\x25\x96\xd5\x75\x3a\x9b\xf5\xbd\x13\x7c\x94\xef\x80\x80\x81\xe4\x1b\x51\x24\x32\x6e\x7a\x00\x28\xad\x46\x91\x52\xa0\x80\xfc\xf6\x12\xb5\x3a\x03\xa8\x05\xa3\xa8\x29\x50\x03\x35\xef\x6e\x25\x53\x23\x37\x23\x08\x17\x67\x80\xf7\x66\x2c\xd4\x1c\xe5\xfe\x56\x4e\xc7\x2f\x8c\x5d\xdd\x84\x4d\x12\x3d\x15\xb5\xb2\x04\x52\x1b\x44\x16\x21\x20\xd5\x2f\x5d\x62\xcb\xd6\xf1\x41\x46\xc4\xb2\xf4\x30\xb1\x03\xd5\xd9\xc4\x23\xf6\x00\xdf\x9e\xe5\xa6\x87\x9f\xac\x8d\xc6\xb5\xe0\x61\xc2\x38\x2e\x72\xb5\x19\xff\x7b\xd7\xe4\x30\x9e\x5d\x23\xb5\xac\xb3\x6b\x59\xd4\xb5\xb0\xb0\xd8\x35\x1b\xcb\xa2\x35\xf9\xa5\x51\xea\x32\x83\x66\x3e\xc6\xb2\xca\xb1\xc5\x52\xce\xcb\xb7\x7d\xd0\xd9\x02\xa6\xcb\xb6\x12\xa0\x36\x72\xd7\xe4\x26\x2b\xab\x30\x7a\xa5\x95\xd6\xb5\x57\x24\x62\x44\x02\x10\x75\xeb\x6c\xcc\xea\x30\xf5\xee\xa6\xd4\x80\x29\xd3\xcb\x34\x0f\xcc\xea\x3e\x76\x46\x08\x63\x48\x8c\xec\x54\xbd\xb2\x25\x80\x06\x71\xa6\x0c\x22\x44\xe1\x29\x83\x98\x1e\xbe\x6e\x10\x87\xf6\x5f\x3f\x88\xe9\x61\xcc\x20\xce\xbc\x29\x8e\xbe\x0e\xc3\x88\x69\x02\xb7\x93\xd1\xea\x06\xb5\x8d\x3e\xf7\xbb\x27\x28\xc4\x11\x45\x5f\x80\xac\xa3\x60\x6b\xe1\xba\x24\xae\xbd\xc7\xfc\x1a\x87\x2b\xa4\xab\xbf\xe8\x6a\x01\x7e\x8f\xda\x44\x4c\x14\x45\xf5\x43\x5e\x7f\xa4\x5b\xb1\x78\x2c\xe4\x1e\xe0\xbe\x4f\xe1\xae\x2e\xd2\x53\x83\x54\x19\x48\xb9\x85\x55\xc1\x10\x54\x9b\xce\xdb\x23\x37\x8d\x0c\x58\x89\xf5\x94\x80\xf1\xa5\x27\x9a\xfb\x16\x64\x38\x40\x56\xf0\x6d\x60\x6a\xd3\x1f\x00\xaa\x7c\x57\xd8\x25\x3e\xa2\xf7\x86\x50\xdc\x79\x79\x67\xad\x2a\x50\x40\x16\xac\x11\xcd\x0d\x8b\x36\x0a\xa5\x34\x10\x24\xad\x1f\x81\x7a\x89\x46\x85\x4a\x14\x36\x9b\xbc\xa0\x4f\x7c\x5d\x2f\xd2\x08\x75\x43\xe9\x90\xcb\xee\xbd\xc5\x52\xdc\xaa\x72\x2d\xa8\xe1\x20\x96\xcd\x61\x0f\x5b\x2b\xc4\xc5\x3b\x86\x35\xeb\x8a\x23\xb9\x74\x13\xa9\xf2\x54\x37\x05\x67\x0f\x85\x4a\x79\xe4\xc0\x6a\x49\xee\x26\x18\x61\xaa\x2c\xa2\xdd\xdd\x22\xba\xe8\xc1\xcf\xca\x6e\x4d\x85\x57\x6c\x93\x88\x5d\xdd\xf0\xe1\x42\x75\x3f\x13\xee\x97\x28\x34\xf0\xc2\x4a\xcf\x4a\x74\xe3\x54\xa5\xdf\xbd\x8b\xc3\x26\xdc\xe0\xdf\x9f\xea\xfb\xc3\x0f\x6d\x96\x6e\xa3\x63\x58\xd5\xa8\xf9\xf1\xd4\xec\xef\x26\xef\x67\x7f\xad\xef\x0f\x4e\x9b\xa5\x79\xfd\xe3\x87\x63\xd3\x94\x9b\x4f\x9f\x1e\x1e\x1e\xbc\x87\x99\x57\x54\x87\x4f\x81\xef\xfb\x5d\xcb\x0f\xce\x7d\x82\x1e\xfe\x52\xb4\x3f\x7e\xc0\xef\xe8\x9d\xbb\x0f\xef\x67\xff\xf1\x7e\xf6\xd7\x32\x6c\x8e\xce\x3e\x49\xd3\x1f\x3f\xbc\x0f\x66\xa4\x1f\x1f\x9c\xf8\xc7\x0f\xbf\x04\xde\xcc\x59\x7a\xab\xd9\xcf\xde\xd2\x99\x7b\x8b\x59\xe4\x7a\x73\x77\xea\xf9\x73\x6f\xbe\x74\xa7\xde\xbc\xd3\x0a\xd7\xbb\x4b\xa7\xde\xd4\xe9\x7e\xce\xbc\xb9\x3b\xf3\xee\x22\x6f\xe9\x7a\xcb\x99\x33\xed\xfe\x06\x2b\x67\xea\x05\xde\x2a\x75\xe7\xce\xdc\x5b\x76\x28\x66\xde\xc2\xf5\xee\x30\xaa\xa9\x37\xfd\xed\xc3\x27\xc2\x47\xc7\xe4\xfb\xd9\x7f\xbc\xfb\x48\x64\x45\x27\x06\xac\x63\x43\x25\xa0\x63\x7d\x25\xac\x63\x52\x35\xa8\x63\x30\x8c\xa0\x63\x7b\x3f\x8c\xe7\xe8\xa2\x07\x97\xe3\x7e\x10\xbc\x56\xc7\x08\xf4\x16\x42\xa1\xdb\x68\xea\xf9\x66\x36\xe6\x26\x14\x8c\x74\x82\x28\xd8\xdc\x9b\x3b\x0b\x6f\x16\xcc\x8f\xae\x77\x77\xef\x06\xde\x7c\x79\xf4\xee\x7e\xcb\xfc\x4e\x9d\x82\xae\xf0\xff\x5d\x78\x77\xeb\xae\xec\x97\x99\xb7\x5a\x7a\xcb\xd9\xcf\x9e\x3f\x77\x56\x9e\xbf\x5a\x44\xae\x37\x9d\x2e\xbc\xc0\xf3\xa7\x4b\x6f\x1e\x2c\xbc\xa0\xfb\xb3\x3c\xae\xbc\xd9\x7a\x15\x79\xc1\x3c\x70\x7c\xc7\x9b\xad\x02\xd7\x0b\x82\xa5\x17\x2c\xee\xdc\xae\xfe\xaf\x4b\x6f\x15\x74\xfa\xbc\x0e\x3a\xe2\xf3\x95\x13\x78\xab\xb5\x33\xf7\x82\xc5\xcc\x5b\xce\x30\xd6\x99\xeb\x4d\x57\x73\xd7\x9b\xad\xe9\xc3\x7c\x3d\x77\x7c\x9d\xa6\x12\x6b\x0f\x2b\x6a\x5f\x07\xe8\x29\xab\x83\xd5\x54\xac\x05\xb5\x14\x04\x11\x94\x34\x5e\x2f\x66\xf3\xfd\x45\x0b\x2d\xe9\x28\x04\xae\x55\x51\x02\xbc\x85\x30\x40\x2a\x1a\xef\x57\xfb\x95\x9e\x13\x5a\xf8\xe2\x3a\xda\xeb\x21\xe1\x94\x53\x5a\x37\x70\xdc\xc0\x59\x39\x2b\x5e\x6d\xeb\xa6\x2a\xbe\x20\xa1\x41\xa7\xb8\xbe\xe3\xa7\x33\x67\x96\xf9\xee\xec\x67\xdf\x99\x31\xc5\x88\x92\x2a\x4a\x91\x53\xfd\xf8\xc1\x5b\x48\x65\x51\xfb\xe3\x87\xd9\x07\xb8\xea\x51\x5f\x45\x5a\x41\x10\x9c\x12\x62\x39\x4a\xae\x13\x17\x2a\x7d\x8e\x1b\x39\xf0\x55\xac\x55\xf1\xe0\x88\xb7\x72\x88\xc5\x10\x24\x17\xb1\x25\x2e\x19\x71\x51\xfa\x0a\x5c\x88\xaf\xa4\xab\xfb\x2a\x86\x5d\x68\xa0\x02\x0a\x1d\xe7\xa7\x11\x77\xb4\xc2\x90\x6d\x8b\x6f\x2c\xde\x73\xfa\x7c\xb2\x7b\x89\x6e\x0b\xc8\xcb\x30\xfa\x22\x97\xff\xf3\x54\x37\xc9\xfe\xd1\x65\x77\xbb\xc9\xf8\xf9\x36\x1a\x58\x25\x52\xa8\x4a\x9a\x6c\xa0\x5e\x46\x64\x5f\x75\xaa\xf9\xe6\xf5\x76\x8c\x74\xe5\x77\x6c\xc2\xd5\xbb\xc3\xb9\x6d\xf9\xd0\x8f\xb0\xdf\x81\x10\xb2\x90\xa5\x61\x87\xc5\x9a\x71\x86\xff\xcc\x9f\x14\xd7\xe3\x26\xb3\x48\xde\x66\x8e\x67\x11\xcf\xdd\x3f\x26\x21\x2b\xe6\x86\xd9\x70\xef\x1c\xac\x3e\xba\x58\x80\x01\x5a\xda\xf3\xcb\x37\x6e\x09\xb4\xf9\x7b\x2c\xe5\x0b\x83\x04\xfc\xa2\xdf\xf3\xc7\xe0\xf6\xb0\xc6\x51\x11\xa5\xe6\x26\x79\x9c\x44\x61\x53\x54\x72\xec\x64\x6b\xba\x99\x5b\x18\x23\xf9\x70\x20\x6a\x1b\xaa\x40\x12\xe9\xce\x3f\x63\x5e\xa6\xc6\xf9\x3c\x63\x55\xb8\x5c\x70\x70\x12\xe4\x40\xba\x30\x57\x7d\xd3\xc1\xdd\x8f\xca\x94\xfd\x98\x34\xc8\xc5\x37\x54\x6e\xf2\x02\xdb\x60\xd0\x70\xf4\x63\x70\xaa\x51\xe5\x92\x88\x20\x3d\x06\x90\x15\xbf\x41\xa5\xb5\x5a\xa8\x14\x28\x47\x00\xf8\xb7\x2f\xc0\x4d\xb6\xd2\x61\x86\xb7\xbc\xbf\x14\x0f\x03\xbd\xcd\x1f\x3f\x92\xc3\x3c\xe0\x35\xfd\x5d\xbd\xc7\x81\x4a\x17\xf3\x6f\xd5\xf7\xeb\x78\x59\xf5\x9d\xa0\x6c\xc9\xa9\x88\x60\x32\x9d\xae\x26\xc1\x74\x39\xf1\x02\x7c\x32\x62\x1c\x20\xa1\x3c\xbc\x0d\xee\x88\x1b\xde\xe4\xf6\x6f\x7f\xbd\xe5\x82\x34\x65\x27\x15\xbb\x86\xe4\x59\xdd\x29\xe0\x2e\x86\x22\x25\x76\x8f\xfa\xaf\xac\xe4\xb3\x13\x92\xa0\x3a\x89\x7a\xba\xe8\x1e\xe5\x4d\x3d\x88\xc7\x2d\xab\x24\x0b\xab\x47\xf3\xa9\x20\x3f\x58\x2d\xe2\x3b\x69\xef\x43\x0a\x05\x2c\x74\x30\x2c\xb8\x16\x61\xb8\x90\x71\x4d\x17\xf3\xf5\x4e\xc0\xc5\x0d\x5c\x8f\x9e\x0c\xe0\x55\xc3\x36\x76\xd4\xe8\xa0\xf5\xd4\x85\xc1\xeb\x19\xe8\x07\xf1\xe9\x32\xe2\xc7\xb6\xc7\xcb\xca\xea\x63\xf1\xf0\x93\xc8\x47\x55\x94\x71\xf1\xd0\x2d\x48\x87\x43\x6a\x39\xbd\xc5\x64\x0b\x9e\x1b\xd2\x4b\xbc\x46\x51\x91\xc7\x9c\x16\xb0\x5b\x65\x47\x9c\xfc\xc0\xe7\xd9\x04\x24\xa2\x12\x68\x51\xa1\x65\xf7\x8f\x84\x2d\x8c\xbb\x7f\x24\x84\xbc\x26\x0c\x54\x46\xeb\x82\x3f\x9f\xb0\x7f\x2d\xda\x20\x42\xca\x5c\x88\x1a\x31\x30\x62\xd0\x89\x31\xe2\x12\xf4\x61\xc0\xaa\x6a\x04\xc7\x09\xac\x13\x56\x51\x8f\x50\x0b\x7e\x00\x92\x7c\x5f\x98\xf5\x6d\xb1\x8b\xfc\x58\x46\x41\x0a\x07\x14\x63\x8c\xc2\x6c\xba\xf3\x63\xd9\x28\x04\x61\xb8\x8b\x83\x01\x11\xaf\x07\x18\xf1\x58\x15\x58\x4f\x27\xd3\x75\x30\x09\x82\xc0\xa2\x01\x22\x20\x47\x59\x1c\x7b\x4c\xdc\x30\xec\xa3\xc4\x22\x8c\x3b\xc6\xa8\x0e\x39\xa1\x7d\x8d\x05\x60\x82\x1c\x31\xd4\xbc\x78\x59\x4c\xde\x3c\xda\xfa\x17\x01\x02\x96\x31\x03\x3e\x9f\xaf\xe3\xf9\x5c\xc2\x35\x9f\xae\x97\xf3\xa9\x80\x4b\x98\xfb\x14\xfd\xe8\x61\x0f\x26\xd3\xbb\xf9\x64\x6d\x1d\x75\x1e\x4e\xa4\x2e\xcd\x79\xca\x80\x69\xe8\x47\xca\x48\x9c\xf5\x14\x2f\x30\xe7\x19\x1f\xd7\xe8\x00\x93\xed\x08\x1d\xe0\x25\xce\xc2\xe6\x46\xdc\x86\x40\xbd\x80\x65\x8c\x0e\xa0\x68\xbd\x9a\xca\x06\x12\xed\xd6\xb3\xe9\x52\xc0\xc5\xeb\x00\x43\x3f\xda\xfa\xcf\xfd\xc9\x74\x35\x9b\xac\xee\x6c\xc6\x5f\x00\x14\xe9\x8b\x5a\xc0\x58\x30\xd9\xfd\x91\x52\x12\xb4\x80\xe1\x55\xb5\xa0\xe7\xe3\x1a\x2d\x60\xd2\x1d\xa1\x05\xbc\xcc\x69\x5c\xda\x88\xda\x10\x0a\xe7\x91\x8c\xd1\x81\x68\x3d\xf3\x03\x79\xbe\x44\xd3\x00\x05\x21\x8f\x8a\x57\x01\x8a\x7c\xb4\x06\x4c\x57\x93\xbb\xd9\x64\xb5\xb6\x29\x00\x0f\x27\xd0\x16\x87\x9f\x92\x37\x8c\xfe\x48\xf1\x08\x83\x4f\xb1\xaa\x63\xcf\x78\xb8\x66\xe8\x99\x50\x47\x0c\x3d\x2f\x6a\xba\x31\x92\xb7\x04\xcc\xb1\x85\xb1\x8d\xb8\xb2\x1f\xf0\x85\x25\x52\xe3\xf6\x0d\x16\xff\x5a\xc2\xc9\xab\x8c\x4c\xee\x15\xf6\x11\x32\x37\xa2\x12\xc9\x0c\x0d\x9b\x43\x9d\xcc\x15\xe9\xc2\x64\x78\x9d\x92\x89\xa8\xca\xa5\x30\x79\xdd\x66\x63\xe4\x80\x28\xdb\x8b\x28\xd2\x2a\xe7\x78\x75\xea\x3d\x69\x85\xcc\x28\xbb\x13\x29\x46\x47\x8b\x0f\xd2\xa4\x57\xdf\x87\xa8\x5c\xc1\x1a\x05\xec\x4b\x60\xa9\x5b\x14\x0a\xde\x9f\xa8\x54\xf4\x4a\x65\xdd\xaf\x3c\x79\x64\xf8\x8d\x09\xf3\xb5\xbf\x56\x9d\x78\xf7\x9c\xa7\x33\x46\x99\xac\xfe\x3e\x8f\x10\xd2\xa6\xd7\xdb\xcd\x08\x9c\xc0\x1a\x24\xee\x6e\xb4\x62\xb6\xe8\x8f\xb2\xc5\x11\xd0\xeb\xb5\xe6\xfa\x2d\xcf\x68\xe9\x4b\x9b\x1c\xf5\x08\xd3\x13\x35\x87\xf3\xee\x25\x52\xa3\x94\xc7\xb6\x63\x90\x70\x82\xd6\xe8\xf5\x76\x46\x32\x37\x1a\x2b\x24\xef\x94\x2c\xc7\xc6\xf4\x66\x08\xd8\x2e\xc9\x44\x0c\x26\xe8\x29\xdb\xa7\xd1\x03\x22\x6f\x98\x94\xe3\x4a\x4f\xd3\x27\x7e\x9f\x20\x91\x1a\xa3\x4f\xd6\xbd\x87\x84\x13\xd2\xa7\x57\xdd\x65\xc9\xfc\xc0\x1a\xa5\xec\xba\x2c\x87\xc4\xb4\x1a\x05\x6d\xbd\x64\x22\x7a\x8d\x7a\xd2\x56\x6c\xf4\x90\x88\x9b\x2f\xf5\x70\xd1\xd3\x14\x8a\xdf\x7a\x88\x94\xc6\xe8\x93\x75\x37\x23\xa2\x84\xd4\xe9\xf5\x76\x6c\x12\x2f\xb0\x2a\xc9\x3b\x38\xad\xb8\x2d\x9a\x04\x6c\xe3\x24\x12\x7a\x3d\x7a\xca\xb6\xce\x3a\x12\x69\x92\x7f\x39\xcb\x2f\x23\x41\x6f\x9d\xbe\xba\xf3\x87\x76\x93\xfe\x49\xe8\x50\x57\xb0\x51\x0a\xf4\x9b\x5f\x45\x58\x22\x6e\x15\x15\x51\x0a\xa1\x4f\x20\x0e\xf6\xd1\xbe\x1d\x90\x53\x40\xae\x61\xff\xda\x63\x1e\xdd\x45\x5b\xf9\x75\xe1\x29\x8f\x51\xd5\x0d\xcc\x88\xe1\x17\x25\x40\xf1\x92\xaf\x15\x00\x00\x85\x9d\xbe\xc2\xf2\xe2\x92\xfb\x88\x05\x7f\x13\x86\x11\x1c\xbe\xee\xeb\x98\x01\x6d\x9d\x71\x68\x87\x4f\x13\x9f\xf4\xe1\x54\x87\x02\xbf\x08\xd7\x7e\x22\xcf\xc1\xfc\xc0\x81\xf3\xdf\x15\xe0\xd3\xf6\xf8\x4c\xc6\xaf\xcd\x63\x89\x7e\xdc\x9d\x9a\xa6\xc8\x3f\x0f\xd0\x13\xae\xb2\x42\x35\x6a\x34\x75\xf5\x69\x97\x25\x7c\x25\x7f\x3c\xce\xdb\x87\x31\x3a\xb3\xd7\xad\x3e\xf4\xd2\x9a\x56\xe2\xaf\xab\x9d\x4e\x25\xc2\x4a\x7a\x69\x0d\x41\x98\xab\x09\x5d\x6c\x06\xce\xdc\x97\xbe\x51\x91\xa6\x61\x59\x0f\xa7\x18\xc9\xe0\xb3\x62\x02\x2f\x7e\x2a\xdb\x54\x9a\x6a\x9a\xd4\xa0\x78\xb8\xe0\xec\x38\x36\x28\xa2\x06\x3d\x2d\xfc\x49\x86\x72\x14\x86\x1e\x61\xf0\xfb\x74\x0b\x9b\x63\x12\xc7\x28\x87\xc4\x46\x60\x1d\x6f\xb6\x20\xaf\xeb\x25\x99\x29\xd5\x86\xba\x4b\x6f\x16\x27\xf8\xe9\x54\xaa\xbc\x5d\x64\xd3\xb9\xd9\x84\xfb\x06\x55\xa6\x13\x64\xfe\xd0\x21\xe1\xdb\x97\x99\x7a\x60\x84\x1e\xbe\x60\x87\x58\xde\xbd\xe3\x73\x4b\x75\x0d\xc8\xb9\x89\x7e\x3e\x90\xb3\x27\x7d\x39\xf4\x35\x6b\x4f\x4b\x05\x51\x3b\x23\x9d\x54\xb8\x50\x39\x38\xba\x5e\x73\xdc\xf9\x52\x0e\xab\x81\x24\x47\x26\x43\xf9\x09\xf8\xde\x09\x67\xce\xf2\xfd\xf7\x5b\x72\x4c\x67\xfb\x9b\x9b\xe4\x31\x6a\xbb\x32\x7f\xcb\x2b\xe9\x76\x9f\x16\x61\xb3\xe9\xc0\xb6\x5c\x62\x59\x9f\xfb\x18\x98\x9e\x1f\x61\xb2\xde\xb0\x4f\x6b\x7c\x47\xfe\xca\x78\x2b\xbe\xbf\xe4\x0e\xcb\x60\xfc\x69\x52\x37\x34\xa7\x07\xec\xf9\xe0\xe5\xf2\x4d\xb2\x62\x70\x12\x8d\x93\xfb\x24\x46\x55\xff\x19\x65\xd9\xf6\x1d\xa7\x72\x90\x27\x91\x3e\x5f\x4b\x8f\x34\x69\x50\x66\xcf\x3b\x32\x2b\x5b\xb6\x0e\x44\x29\x0a\xab\xcd\xae\x68\x8e\xca\xa1\x24\xad\x90\x93\xfc\x88\xaa\xa4\x81\x8e\x24\x0d\x2c\x76\xbe\x17\x97\x34\x42\xe0\x90\x2d\x71\x62\xa1\xb0\xec\x4e\xe3\x29\x9a\xee\x95\x65\x57\x37\x9e\xab\xfd\x6a\xbf\x96\xa8\xf4\x6e\x89\x48\x86\x9e\x8e\xe1\x34\x61\x24\x11\x16\xa9\x14\x89\x0c\x1e\xa3\x48\x06\x5e\xef\x81\xaf\x13\x2d\x0e\x04\xf1\x04\xc5\x79\x28\x25\x43\xc0\x20\xa1\x3c\xf9\x7b\x70\x62\x6c\xce\xec\xc3\x6b\x2e\x4d\xa4\x08\xd6\x55\x70\x19\x39\xb7\xec\xe4\x5d\x0f\x75\x44\x61\xcc\x19\x4c\xa2\x5e\xd2\xe1\x2f\x5b\x92\x00\xe6\x17\x88\x52\x51\x35\x89\x23\xdb\xc9\xa7\xfb\x31\x98\x9f\x7d\xd2\xa2\x78\x4b\x6c\x17\xeb\xd6\x90\x35\x40\xb4\x44\xeb\x35\x64\x0c\xb1\x18\x3b\x04\xb8\xa7\xec\xf3\x56\x35\xb7\x60\xff\x55\x5f\xef\x08\x4d\x38\x9f\x88\xad\x01\x86\x8f\x5b\x87\x3c\x26\x64\x75\x01\xce\x73\xd2\x2a\xe5\x58\x27\x57\xce\x37\xe3\xc1\x35\x47\x87\x55\x0e\x39\xdf\x0d\x57\xd0\x0f\xa7\x15\xb6\xed\x87\xcc\xa7\xca\x21\xf3\xa9\x70\xc8\x9c\xfc\xd2\xf2\x40\x66\xb9\xcc\x09\x9d\xfb\x6c\xcc\x02\x6d\x73\x61\xab\x01\xa1\xb7\xd5\x73\xce\xf5\x40\x5e\xc5\xaa\x41\xc6\xe1\x00\x99\x75\xba\xc7\x1f\x24\x59\x0f\x85\x8a\x06\x39\xc3\x23\xd8\x8a\xab\xd2\x6b\x1f\x48\x14\xa8\xb5\x60\x80\xd9\xd0\xc2\x88\x1f\x88\xd3\xcf\x9b\xcb\x96\x08\xa3\x29\x8a\x74\x17\x56\x2f\x74\x9c\x19\x9f\x1e\xae\x9b\xb0\x6a\xb4\x07\x8e\xf1\x29\x63\x0a\x22\x1c\x3a\x26\x65\x7a\x70\x81\x7f\xfd\x19\x7f\x49\x23\xf2\xa2\xf9\x6e\xb3\x4f\xaa\xba\x21\xdf\x70\x93\xef\xec\x37\x69\x28\x16\xc8\xce\xd8\xc7\x33\xb8\xbb\xe6\x55\x6d\xc0\x29\x67\xa7\xd5\x43\x5e\x49\x9c\x26\xe1\xc4\x86\xb4\xe7\x84\x73\x5f\xa5\x1a\x85\xf2\x40\x48\x95\x83\x30\x77\x64\x57\x54\x81\x96\x38\xea\x7a\x0a\x32\x24\x54\xc8\xfc\xd0\xd1\x1a\xfc\x4d\x18\x60\xc4\x98\x11\x23\x69\x19\x22\x8a\xcd\x24\x7e\x59\x4c\xb2\x41\x19\x85\x42\x0e\xfc\x3c\xcf\xe0\x51\xd2\xa6\x21\x54\x15\xf1\x2b\x47\x49\xdd\x93\x28\x76\xd6\x2b\x4a\x94\x2b\x70\xbc\x87\x83\x8d\x9a\x54\xef\xd6\x65\x9a\x34\x52\xa6\x00\x9a\x5d\x4f\xf8\x9c\x80\x25\x2f\xd0\x23\x61\xdb\x24\xdd\x9c\x63\xe1\x10\x4d\x73\x16\x25\x19\xc9\xe2\x0c\xe2\x71\xb6\x92\x3c\x0f\x16\xd9\x31\xd2\x4c\x0f\xe3\x68\xf6\x19\x0d\xa4\x4c\x18\x8a\xbf\x33\x38\x39\xaf\xe3\xd2\xf0\x86\xbe\xa8\x92\xce\x3a\x33\x0e\x84\xba\x38\xa9\x50\x44\xdd\xf5\x2a\xe3\x2a\xb1\x2d\x1f\x6a\xa3\x22\x3d\x65\xf9\xb0\x0a\x28\x35\x1a\x78\xe5\xf3\x19\x71\xc1\xe1\x3f\x8a\x81\x16\x1b\xbe\x8d\x0e\xf6\xc5\x3f\xa2\x81\x86\xd1\x19\xb1\xc0\x9f\xe5\x40\x1c\xe0\x49\x69\x1d\x85\x9f\x46\x38\x1c\x3f\x8d\x70\x38\x64\x18\xd1\xe1\xe8\x7c\x77\x77\xd8\x33\x03\x33\x54\xf4\xfb\xec\xd6\xde\x60\xe8\x65\x1f\xd2\x60\xa8\x47\xd9\x65\xc8\x72\xea\xc9\x99\x8c\xf3\x59\x6b\xe9\xc7\x58\x62\x48\xd6\xcf\xb0\x2e\x82\x68\x9f\xb8\x40\x3e\x01\xd7\x53\x56\xca\xab\x46\xe4\x6b\x16\xcd\x6b\x06\xea\xd7\x38\x6c\x42\xda\x0b\x1a\xde\xae\x3f\x63\xcc\x0e\x17\xbe\xc6\x1f\x27\xee\x8a\xf6\xf3\x64\x1c\x7c\x87\xbe\x30\x01\x73\xee\xc1\xb5\x74\x34\x4d\x09\x49\x20\x7c\x88\x83\x6a\x9d\xe5\xa5\x71\x33\xff\xe3\x16\xfc\xee\x88\x77\xc3\xed\x7b\xed\xa7\xef\x32\x78\xbb\xc7\xd1\x94\xbe\x39\x56\x39\xe8\xf7\x82\xb6\xeb\xad\x36\x53\x65\x03\x3d\x15\x36\xd0\xfd\x2f\xca\x8a\x1c\x90\xf0\x0d\x8c\xf5\x7e\x94\x1e\x82\x6e\x7f\xf5\x00\xe2\x46\x7c\x66\xa0\x36\xb1\xe5\x6b\xe3\xbf\x7e\x7c\xde\x0d\xe0\x8d\xf8\x05\x2f\xb5\x68\xeb\x47\xc7\x6e\x9b\x81\x51\xb9\xba\xd5\x53\xd7\xcb\x11\xfa\x30\xf6\x2b\x56\x00\xd9\x19\xcc\x9a\x6d\x4e\x47\x6a\xff\xd0\x96\x7d\xd6\x40\x52\xd4\xaa\x9f\xdd\x6a\xf3\xef\x3e\x31\xfc\xaf\x74\xcb\x9e\xf8\xf2\x29\xa9\x2d\x55\x32\xcf\x99\xec\x12\x60\x1c\xca\xf6\xf8\x94\x7c\x8e\x16\xc6\xbf\x36\xc3\x23\x46\x09\xaf\x6a\x66\x38\xba\x84\xf1\xdf\xfa\x5b\x27\xea\x98\x69\x79\xdd\x24\x54\xfc\x34\xd9\x89\x1a\x8b\x63\x64\x88\x48\x83\x6e\x24\x55\x19\x8c\xf3\x0e\xc6\xb4\x78\xae\x88\x87\x5d\xf2\x67\xe1\xad\xac\x7d\x60\xc5\x08\xd7\x08\x83\x3b\x76\x58\xae\x53\x81\xf1\x4d\x24\x51\x5e\x35\x5e\xd7\xb1\xaa\x78\xf5\xcf\x15\xe4\xe3\x47\xe1\x87\x31\x32\x3f\xf3\xaf\xd1\x25\x35\x80\x5f\x7e\x0c\xf6\xc4\x07\xdf\x48\xc1\xc9\x67\xed\xef\x50\x00\x17\x90\xbf\x35\x8f\xfe\xe6\x9e\x61\x52\x78\x17\x0c\x04\xdc\x21\x58\xc8\x15\x1c\x2a\x55\x2f\x70\xa8\x33\x39\x80\xcf\x64\x01\xce\x42\x02\x0e\xb0\x13\xcf\x32\x3f\x86\x57\x34\x5b\xab\xd4\xcc\xb6\x56\x23\x4d\x73\x23\x58\xca\xe6\x36\xf4\xed\xd8\x48\x23\x7e\x1d\x5b\xd7\x31\xa4\x2a\x82\x94\xaa\xe6\xad\xde\x79\x66\x49\x3e\x78\x70\x50\x08\x93\xf7\x0b\x69\xb0\x13\xbf\x71\x96\xb2\xf9\x2a\x39\x64\xe0\x8c\xbe\x4c\x00\xee\xb4\x4f\xba\xe1\xc3\x8d\x37\xd8\x97\x40\xf1\xff\xa7\x4f\x4f\x33\xe2\xf3\x28\x0d\x6e\x3c\x76\x06\xcc\xda\x43\xb2\x9d\x83\xda\x11\x9c\x90\x9f\xb3\xee\x67\x7f\xb4\x73\x34\xac\x86\x2b\xa2\x80\x4f\xed\xf0\xdd\x3e\x0a\xf7\x48\x83\x9a\x9d\x9f\x30\x21\x1f\x71\x96\xa2\x3f\x22\x73\x1d\x91\x18\xd5\x51\x95\x94\x9d\x2a\x8c\x48\x2f\x6d\x4f\x47\x24\x1c\x98\xa2\xce\x2a\x3d\xa8\x00\x9e\xd6\xe9\xea\x99\x92\x63\x15\x57\xa3\x22\x2f\x94\xe8\x47\x3d\x44\x1c\xc7\x4f\x4d\xb3\x2c\x67\x8b\x92\x92\x27\x2f\xfc\xf7\xf8\x26\x63\x4d\xf9\x20\x57\xea\xa3\x1b\xf2\x3e\xc1\x9b\x2d\x7b\xfb\x71\xd3\xf6\x36\xf2\xc2\xee\x69\x6e\xcd\xa5\xb7\x58\xce\xbd\xd5\x22\x75\x67\xde\x62\xed\xcc\xbc\xe5\x34\x70\xa7\xde\x62\x76\xd7\xfd\x77\xf1\xb3\xef\xcc\xbd\x60\xe9\x04\xde\x7a\x35\x77\x56\x5e\xb0\x70\xee\x9c\xc0\x9b\xae\x67\x50\x7e\xd6\x71\x22\xea\x4c\x60\x83\xaa\x2c\xc9\xc3\xc6\x34\xdd\xf5\xdf\x7c\xbe\xa6\x04\xe7\xce\x5c\x93\xa2\xb4\x97\xa1\xef\x04\xc7\xb9\x5e\x1c\x78\xb7\x37\x5a\xdd\x78\x5d\xd5\xb5\xbc\x31\x45\x73\xe7\x8e\x3b\xe7\x54\x6d\x48\xcc\x3a\xfb\x20\xaa\x9c\x5e\x65\x08\xf7\xb5\x5b\x37\x61\xd7\xad\xdf\x5d\xac\x4f\xdb\x53\x25\x6b\x9f\x74\x66\x4c\xb2\x3e\x96\xd6\x3f\x68\xb0\xb1\x7d\x0b\xad\x25\x46\x1a\x3e\xad\x2c\x5d\x8f\xab\xbf\xb6\x69\x38\xad\x37\x63\x91\x14\xf2\x97\xfd\xa6\x51\x35\x4b\x98\x0c\x3e\xfb\xcc\x9d\xfd\xec\x16\x7c\xe7\x65\xa7\xf8\x02\x34\x92\xb3\xd9\x8c\xa6\x66\x77\xfc\x9f\xf1\x24\xff\x2d\xf3\x9d\xce\x26\xce\x8e\x73\xd5\xfe\x39\xfd\x32\xc6\xae\x04\x20\x62\xb0\x2c\x5c\x77\x65\xeb\x4c\xfd\xb2\x55\x56\xae\xa1\xe2\x69\x57\xe6\x75\x0b\x77\x58\x96\x28\xac\xc2\x3c\x92\x6e\xef\x93\xca\x25\xc5\x80\x3e\x8b\x01\x2e\x59\x03\xda\x5c\x7d\x61\x97\x88\xe3\x2b\xce\xb9\xca\xbe\x19\xc5\xc8\x5f\x49\xa7\xba\xdc\x04\x48\xbe\x1c\x4b\x3e\x42\xd1\x1f\x65\x97\xef\x56\x24\x37\xfb\x13\x54\xfb\x24\x45\x86\x6d\xcc\x88\x29\x16\xc0\xc7\x5d\x35\x5b\x8d\x8e\x1e\xdd\x67\x70\x47\xe0\xe7\x04\x83\x15\xfd\xc6\xdf\xee\x93\xb4\x41\xd5\x26\x4c\xcb\x63\xf8\x1d\x15\xcd\x8f\xfe\x47\x60\x63\x82\x49\x29\x3b\x35\xc1\x0b\x1d\x8e\xce\x4a\x27\x66\x17\x12\x79\x20\xbd\xa3\x68\x1f\x64\xf3\xf0\x86\xce\xea\x90\x3f\xed\xea\xc8\x3c\x20\xb9\x4d\x1a\xe6\x87\xef\x50\xfe\x91\x1d\x07\xea\x3f\xef\xf8\xeb\xb1\x28\x6a\xd4\xd9\x1d\xe4\x79\xde\x3b\xb8\xf5\x66\x87\xf6\x45\x85\x34\xf2\xc7\xa7\x17\x86\x10\x08\x3b\x84\x8c\x9f\xd9\x50\x2c\xa5\xdd\xc1\x57\x0e\xcc\x73\xbd\xcc\xf0\x1d\xf6\x06\x81\x7e\xa1\x61\x93\x1e\x15\x44\x2f\xbe\xbf\x54\xc5\x43\x8d\xde\x5d\xbc\x3c\xbc\x7f\x46\xbf\x41\xcc\x19\x0b\xdc\x27\x27\x7c\x17\x82\xa9\x93\x4f\x20\x75\x47\xda\x3b\xb1\x76\xba\xc1\x00\x59\x08\xa5\xff\x6d\xfa\x24\x8f\x01\x79\xa3\x4d\x24\x69\xd3\x84\xbb\x5a\x0c\x92\xf2\x57\xae\xc7\x31\x07\xe6\xe0\x27\xfc\xd1\x87\xd8\x59\x12\xe3\x12\xc1\x70\x4f\x8d\x89\x5c\x75\x41\x74\xf1\xed\x8a\x1c\x9c\x65\x13\x48\xa5\xc6\x8b\x4b\xaa\x01\x3e\xce\xa4\xca\xe8\xf4\x7f\x81\xae\x9a\xe4\x39\xfe\x03\x67\xe1\x03\x0b\x55\x96\xf8\x83\x8a\x81\x1e\xc4\xbf\x27\x7e\x45\x72\xc5\xc5\xa7\x71\x4c\x06\xd1\x21\x8b\xe9\x80\x5a\xfc\x36\x41\x3e\xe6\xf4\x94\x73\x3e\x1d\xee\x32\x49\x53\x75\xfc\xa1\xa1\xe3\x20\xb5\x42\x90\xb0\x79\xea\xb7\x34\x54\xa9\xe9\x9d\xd3\x86\x28\x57\x87\xa3\x73\xdb\x38\x15\x7e\xb6\xb3\x13\xca\x6b\x5c\x42\x8e\xbc\x6f\x4f\x3a\x17\xfc\x2a\x9a\x78\x49\x16\x68\xe2\x12\xf1\x17\x40\xb3\x09\x77\xec\xdd\xfe\x4f\xf8\x47\x19\xe6\xf2\xa7\x9b\x02\x0c\x15\xa7\xf4\x79\x4f\x1e\xde\xef\xc2\xea\x45\xcf\xbd\xdc\xc6\x86\x0b\x58\xd0\x58\xef\xdd\x5d\xd5\xb9\x83\xa0\x6b\x26\xf8\x81\x01\xe8\x06\x06\x9a\x98\xb0\xfa\x06\x99\x5f\x40\xf5\xdf\xb9\x89\x6c\x71\x66\x6e\x28\xb3\xac\x0c\x1d\xe0\xf3\x2e\x7e\xb7\x35\x86\xd7\xac\xc1\x54\x16\x9c\x95\xb2\x5d\x16\x4a\x1b\x09\x97\x10\xea\x75\x62\x0e\x2b\xc5\x7c\x30\x7e\x18\x19\x7e\x35\x3a\x44\xd2\xc9\xa9\xdd\x1a\xa5\x7b\xf0\x80\x6f\x67\x3d\x80\x53\xbe\x32\xbc\x7c\xe4\x42\xb9\xeb\x1d\xd0\xbb\xa9\xe6\x33\x4a\xe3\xa2\xad\x5a\x74\xae\x53\x92\x86\xb2\xd2\x11\x3a\x4a\x41\xdd\x24\x2a\x34\xb9\xec\xe9\xb6\xa5\x73\x96\xb6\x83\xe7\x39\xea\x0b\xe9\xa1\x97\xc3\x3e\x7c\x5c\xe8\xb8\x33\xb9\xc4\xee\x6a\x6b\x94\x2e\xe0\xef\x1b\x55\x5f\x9c\xbc\x35\x02\x84\x46\xbf\x9b\x54\x5b\x0c\x06\x64\xb8\x3d\xa7\xdf\xbf\x2d\x56\x0b\x7c\x7b\x8e\x80\xab\x73\x57\x1c\x41\xd5\x35\x1f\x56\xd3\x6b\x0b\xc8\xc7\x2b\xc0\x40\x74\x88\x7e\xf2\x3a\x19\x86\x49\x8e\x2a\xdb\x44\x31\xdc\xee\xa3\xa0\x3d\x03\x06\xe4\x58\x54\xc9\x6f\x1d\xb1\xa7\x99\x90\xaa\x78\x80\xec\x47\x57\x0c\x41\xf2\x48\x3a\x2b\xcb\x4e\x88\xf5\x28\xf8\x42\x15\xea\x45\x6f\x52\x32\x0e\xe7\x5b\x8b\xce\xc2\x9e\xd6\xb0\x02\xaf\x4f\x3d\xc0\x7c\xc8\x4a\xf7\x42\x57\x68\x7d\x3b\x43\xae\xa4\xe1\xe0\x18\xf9\xb7\x24\x2b\x8b\xaa\x09\xf3\x06\x94\x09\x54\x3d\x48\x07\xa8\x95\x1a\xf1\x27\x94\xf5\x0c\xb2\xb5\x4c\xf0\x35\x01\x63\xb5\x5a\xae\x60\x63\xe0\xd6\xd9\xb3\xd9\x2b\x7c\x42\xf1\x6b\x4c\xd6\x6a\x79\xa7\xe5\xf2\xad\xa7\xde\x37\xa6\xc2\xd2\xb8\xbe\xb5\xf4\xec\x1c\x3e\x87\xed\x92\x14\xf0\x5f\xd5\x7c\xf1\x92\xbd\x55\x0b\xc6\xf3\x38\xd6\x88\xad\xd7\x53\x8d\x79\xc8\xe2\xe7\x33\x62\x59\xfc\x75\x46\x6c\xbd\x0e\xb4\x5c\xbe\xf5\x34\xfc\xd6\x14\x59\x1c\xd7\xb7\x96\x9e\x9d\xc3\x67\x31\x62\xa2\x02\xfe\xcb\x1a\x31\x4e\xb2\x37\x6b\xc4\x38\x1e\xc7\x1a\xb1\xe9\x74\xbd\xd6\xd8\x87\xf4\xf0\x7c\x56\x2c\x3d\x7c\x9d\x15\x9b\x06\xbe\xaf\x65\xf3\xad\x27\xe2\xb7\xa6\xca\xe2\xc0\xbe\xb5\xf4\xec\x1c\x3e\x8b\x19\x13\x35\xf0\x5f\xd6\x8c\x71\x92\xbd\x59\x33\xc6\xf1\x08\x9b\x31\xa0\x4d\x9b\xbe\xb5\x1e\x7f\x6b\x9a\xd0\xa6\xcf\x67\xde\xdb\xf4\x0a\xf3\x6e\xe5\xe5\xad\x47\x72\x8c\xb4\x9e\xc1\x22\x89\x42\xfb\x97\xb5\x48\x9c\x64\x6f\xd6\x22\x71\x3c\x82\x16\x89\x55\xa6\xe4\x30\x1f\xff\x42\x6e\x02\xd7\x31\x34\xe4\xed\x34\x7f\xec\x65\xfd\xd1\x84\x4e\x7a\xa3\x02\x41\xd0\x6f\x79\x4c\x64\x8d\x58\xc4\xb7\x34\x57\x30\x28\x4e\x0c\xb5\xe1\x62\x54\x43\x23\x6f\x22\xa4\x8e\xc3\xd5\x28\x42\xf2\x79\x0e\x1e\xc3\xcc\x88\x81\xbc\x2f\xff\x49\x3c\xa4\x60\xa3\xc6\x3e\x9a\x1a\x01\x5a\x94\x28\x37\x01\x76\xf5\x3f\x99\x24\xad\x1d\x22\xa6\x76\xc2\xd9\x10\xe1\xd0\x95\xa5\x25\x79\x21\xf7\x55\xe7\xc5\x85\x03\xb5\xb3\xc0\x99\x05\x1f\x46\x9c\xc3\x05\x0e\xd6\x53\xbe\x1d\xfa\x7f\x6f\xf1\xf1\x03\xad\x23\xbb\x86\x1f\x3f\x04\x7d\x41\x9a\xe4\x28\x0a\xcb\x1f\x3f\x60\xae\xfb\xe2\x2c\x69\x50\x95\x26\x59\xd2\xfc\xf8\x61\xea\x93\x23\xbc\x73\xe7\xee\x18\xcc\x7f\x99\x3b\xd3\x25\xf9\x1b\xcc\x8f\x01\x74\x68\x1f\x96\x13\x6a\x1b\xb3\xee\x27\xf9\x3d\xaa\x6a\xa4\x31\x13\x72\xad\x68\x28\xfa\xc3\x3b\x5a\x44\xd2\xf4\x81\x61\x44\x13\xa1\x21\x69\xc1\x04\x99\x09\x23\x7b\x5a\xf3\x10\x2c\x16\x13\xf6\xaf\x49\x50\x26\x33\x61\x86\x55\x0c\x85\x40\x72\x35\x96\x26\x68\x31\x04\x54\x81\x0d\x95\xd6\x74\x98\x09\x4b\xc6\xc3\x0c\x2c\x98\x0f\x10\x14\x34\x20\xc6\xc1\xd3\x1b\x0e\xa1\xff\x53\x7d\xf7\x6f\xd5\x80\x74\x7c\x3b\xc3\x7f\xde\xcc\x8c\x28\xf2\x92\x0c\x89\x32\x4b\xa2\xb0\x8a\xff\x15\x4e\x67\x3d\xe5\xb4\x75\xa0\x3f\x6e\x1d\x56\x31\xbd\x6e\xe1\xd9\xce\xfd\xb1\xc3\x36\x53\x81\x48\x93\x34\x29\x92\xbf\xd1\x59\x71\x00\xf5\x69\x27\xc0\xe0\x43\x97\xec\xd3\x01\x25\xfd\x12\xc1\x89\xda\x86\xfb\xba\xfd\x0c\x43\x59\x8f\x08\xf7\x50\x3f\x0c\x8f\xc2\xf7\x3f\x42\x4f\x7e\xf2\xf0\xe9\x29\x25\x07\x9a\xc3\x95\xd3\xfc\xea\x23\x12\x8f\x8d\x3b\xd4\xab\xd0\x1d\x3a\xad\x92\xe5\x04\x62\x48\xd6\x21\x12\x06\xd2\x40\x08\xa3\x47\x93\x8e\x2b\x19\x60\x02\xf0\xcb\x0b\x5d\x6a\xf8\xad\xee\x3c\xb5\xac\xad\x02\x55\x48\x8e\x94\x47\xfc\x71\x15\x3d\xd4\xe5\x3a\xd3\xb2\xfd\xe8\x00\x45\xbe\xc3\x54\x61\x5f\x14\x8d\xbe\x1b\x36\xb6\xf1\x35\x0b\x36\x9e\x09\x09\x60\x10\xfa\x53\xfb\x3e\xc4\xa3\x5a\x24\xc8\x80\x1c\x47\x17\x33\x36\x78\x4b\x48\xfa\xae\x98\x92\x89\xe4\x5a\x60\xa0\xa2\xfc\x7d\x91\x04\x3e\x56\x6c\xa6\x21\x60\xa3\xad\xd9\xb5\xb3\x57\xde\x34\xca\xb7\x75\x78\xd1\x4d\xa0\x2a\xaa\x7f\xe6\x24\xfd\xd4\x8c\x90\xdb\x02\xaf\xbc\x20\x8e\x6f\x0b\xb1\x23\x56\x8d\x67\x07\xdf\x79\x79\xe5\xe5\x87\x7d\x43\x88\x11\xae\x7c\x3c\x17\xec\xca\xbb\x2b\xef\x38\xe3\xdb\x42\xbc\x88\x55\xe3\xd9\xa1\xf7\xa5\x5d\x79\x55\x16\xd7\x14\x62\x46\xa8\x19\xcf\x8b\x7c\x7b\xf2\x13\x6e\x46\x16\xf0\x0c\xb7\xe6\x5e\x7b\x29\xae\x80\x06\xd6\x1b\xfb\x3d\xa8\x22\x2f\xba\xb9\x60\xbf\x15\x53\xc0\xa3\x55\x1f\xfb\x6d\x88\x02\x1e\xdd\xb8\xdb\xef\xc0\xa3\xaa\x8f\x7d\x42\xad\x1b\xb8\xec\x8d\x70\xef\x3d\x42\xf3\x87\xaf\x1a\xa1\x27\x5b\x8b\x93\x1f\xc0\x44\xb1\x53\xf5\x7f\x4f\x45\x83\x40\xc2\x56\x9e\xc0\x2a\xe2\x20\x09\x9f\x81\x9a\x28\x3b\xde\xf0\x6c\xa2\x48\xb6\x5e\x40\x05\xf3\xc9\x60\x66\x4c\x2e\xb9\x6e\x2c\xf8\xcd\xaa\xae\x5a\xdd\x43\x4b\xfd\xea\x17\x70\xf5\x64\xbb\x94\x6e\x8a\x90\xc8\x0e\x56\xbf\x61\x00\x75\x3b\xea\x69\xf8\x68\xfd\x60\x53\xbe\xeb\x04\xf6\x7b\x3b\x8c\x4d\x51\x6a\x1d\x40\x95\x15\x9d\x33\x68\x64\x9a\x30\x63\x72\xf8\xf4\x84\x00\xe7\x0f\xa0\xa5\x3f\xc4\x4c\xcc\x2f\xe2\x2e\x92\x7b\xe6\xb0\x3d\xbe\x7e\xa9\x2a\x1e\x1c\x31\x70\x2f\x16\xab\x45\x97\x81\x33\xa2\x5e\x2f\xf4\x9d\x07\xbc\x5b\xf2\xa5\xf4\x62\x3e\x97\x5e\x8c\xd4\xdd\xc4\x86\x52\x11\x12\x90\xc3\x4d\xd8\x0b\x2d\xca\x56\xd3\x86\xcf\xe5\x27\x7e\xe5\xd3\xb5\xb1\x29\x10\x49\x16\x76\x93\x1a\x44\x53\x10\x62\x15\xfa\xfa\x81\x57\x91\x92\x7d\xa7\x98\x72\x02\xb4\x64\x5c\x1b\xc3\x5d\x10\xe3\x93\x32\x9a\x90\x3a\xe3\xec\xd7\x78\x2c\x76\x13\x05\xe1\xd2\xee\x66\xc7\xa6\x2c\x34\x60\xd4\x77\xf1\x49\x38\xc0\x0e\xda\x30\x3d\x25\xc5\xef\x13\x90\x28\x6c\x4e\xbe\x12\x0b\x27\xb0\x9e\x31\xdb\x14\x27\x16\x67\xb8\x4b\x98\xfc\x76\xa3\xe2\x94\x37\x9b\x19\x49\x42\x20\x95\xc9\x20\x62\xcb\x43\x58\xf6\xdf\x6e\xf1\xad\xf9\x72\xb5\xe8\x22\x70\x23\x2d\x0d\xd0\x57\x55\xc0\x8d\x64\x24\x72\x75\xf1\x76\x15\x0a\xe3\xa8\x3a\x65\x3b\x25\xaa\xa0\xee\xcd\x69\x72\x00\xdb\xbd\x88\x42\x3a\x00\x39\x1c\x33\x10\x94\xaf\xce\x24\x2c\x73\x5f\x76\x0d\xb7\x0a\xf2\xcd\xc8\x17\xb7\xc2\xc5\x3c\x62\xdd\x0f\x72\x41\x9f\x39\xc0\xf8\x91\x9f\xf9\x95\xbf\x74\xd5\x5c\xcf\xe5\xa7\x77\x23\xe8\x63\x87\xb0\xe7\x42\x7b\x09\xf0\x57\x63\xa2\x97\xf8\x8a\x6d\xa4\xcf\xab\xd9\x8d\xc1\x65\x78\x48\x72\xdc\xec\xe5\x52\x27\x28\xaa\x02\x6a\x44\x19\x1e\x90\x12\x70\x74\x48\xb1\x12\xca\x34\xdd\xb5\x30\x2e\x16\x39\x90\xe3\x8d\xe0\x40\x6d\x74\xcc\x51\x13\x0b\xe5\x28\x50\xd1\xf3\xd8\x87\x64\xa2\x23\xb2\x38\x6a\xf6\xeb\x03\x7e\xf6\x06\x8b\xa7\x20\x2a\x2a\x94\x45\x65\x54\x56\x1d\x30\xe7\xc0\x85\xa3\xa3\x7f\x57\x01\x5d\xe9\x08\x45\xf5\xa6\x65\xab\xcd\x11\xa5\x66\x7c\x33\xbd\x2d\x90\x78\x63\x1b\xb4\xa1\x60\xcc\x65\xdc\xa3\xac\x99\x24\x0b\x3a\x85\xf0\x21\x37\x4e\x34\xe3\x12\x8d\xc3\x18\x4c\x33\xc1\xa0\xfb\x33\x93\xea\xcf\xcc\xd4\xae\x9f\x08\x32\x35\xb5\x56\x20\x57\x67\xa0\x78\x8c\x09\xe4\x61\x04\x4f\x94\x4e\x60\x34\x0c\x66\x6a\x4f\x30\x13\x66\x2b\x41\xd6\xc1\x30\x3e\x98\x57\xa4\x4e\x3e\x9d\x78\xe6\x72\xea\x29\xe1\x3e\x82\x95\x7c\x1f\xc1\x56\xbe\x93\x56\x38\xc5\x65\xbf\x3a\x61\x17\xd6\x88\x5c\x49\x0f\xaf\xdf\x1d\xdf\x1b\x94\x95\xcd\xa3\x74\x6a\x6a\xd7\xe4\x0e\xed\x96\x6a\x1b\x58\x0a\x92\x4b\x48\x31\x90\x29\xca\x7e\xc9\x21\x13\x78\x72\xca\x19\xb1\x70\x5b\x1c\xf7\x97\x0f\xee\x2d\x95\x45\x7c\xa9\x24\xf6\xc7\xd7\x46\x33\x24\x34\xd5\x08\x10\xd3\xed\xaf\xd8\xe7\xe1\x7e\x3d\x56\x68\xff\xb9\xbf\x07\x14\xa8\xa2\xa9\x69\x14\x74\xf3\xdd\x22\x58\xac\x7a\xde\x2d\x2f\x1f\x24\x38\x88\xac\x58\xa5\x23\xeb\x07\x8b\x30\x5c\x30\x74\xb6\x97\x0c\x12\x1c\x44\x56\xac\xd2\xf6\x76\xbe\x8e\xe7\x73\x86\xce\xf8\x32\x81\x07\x82\x08\x72\xe5\x3a\x6a\xb3\xe9\xce\x8f\xfb\x4e\xda\x5e\x1a\x48\x70\x10\x4d\xb1\x4a\x47\x16\x45\xeb\xd5\x74\xdf\x6b\x88\xf9\xe5\x80\x08\x06\xea\x11\x5f\xa3\xa3\x19\xad\x67\x7e\x10\x5d\xbc\x7f\x9e\xb2\x5d\xd1\x54\xdc\xc5\x26\x81\xc6\x79\x0f\xe0\x57\x84\xb0\xb3\x3e\x13\xd2\x12\x28\xbb\x21\x95\xea\xbc\xa3\x1a\x90\x3d\x45\x5f\xeb\x1e\xf9\x2b\xe2\x7b\x39\xf8\x31\xd6\xec\x01\x6c\x9f\x9e\x92\xd8\x72\xd0\x58\x4e\x1e\x76\xf1\xc2\x14\x55\xcd\xb8\x57\xba\xd3\xc1\x20\x5f\x95\xff\x02\x93\xc0\x01\xed\x4e\x91\x08\xff\x34\x9f\x0b\xab\xc4\x8b\x81\x64\x90\x59\x5d\x9c\xd4\x59\x52\xd7\x09\xfe\xa8\x3a\x4a\x8b\x5a\x6b\x19\xa9\x7b\xc4\x12\xb9\x89\x09\x68\xe4\xbe\x81\x7c\xe8\xa7\x74\xbc\xdf\xfb\x8a\x2f\x19\xfb\x68\x1d\x2d\xd9\x5a\x31\x8b\x56\xcb\x59\x2c\xa1\x72\xc0\xd1\x8b\xa6\x28\xd8\xcd\x64\x50\x5e\x18\xec\xc6\xf7\xdd\x62\xde\x69\x28\xa9\xd1\x4c\xfd\x78\x8d\xe2\xfd\x4a\xe2\x6d\x17\xc5\xfb\x7d\xbf\x8e\xcd\xa6\x2b\xff\x6e\xcf\xe3\x81\x19\x0b\x97\xf1\x02\x09\xf4\x40\xae\xe6\x8b\x60\xb9\x66\x50\x06\x13\x11\xed\xef\xd0\x4c\x7e\x29\x14\xee\x83\x28\x62\x8c\xdd\x85\xcb\x78\xb6\x93\x50\xc1\xbc\xed\x57\x28\xda\x2d\x64\x50\x80\xbd\xe5\x72\x31\x1d\x84\xa6\x35\x25\xfb\x20\x46\xca\xeb\x57\xb4\x8b\xa2\x81\xbb\x70\x3d\x9f\xcf\x03\x11\x13\xcc\x1c\x9a\xef\xd6\xbb\xb5\x04\x09\xf0\x76\x37\x9f\x2d\x66\xf3\xcb\x9f\xd9\x96\xf0\x0b\x7a\xdc\x57\x61\x86\x6a\xa7\xac\x8a\x43\x85\xea\xda\xdd\x85\x95\x5b\x37\x55\x52\xa2\xfa\xbc\xaf\x8a\xec\x0c\xa5\xf5\x9e\x92\x64\x7f\x4d\x01\xd6\xfa\x8e\x7f\xb9\xfc\xd9\x2d\x5e\x14\xfd\x0b\xe2\xf6\x18\xc6\x67\xdc\x56\x77\x6b\x00\x8e\xeb\x1e\x93\x38\x46\x39\xef\x2b\x03\x99\x76\xbb\x82\xab\xaf\xa0\x52\xf6\xb0\x9c\x5c\xce\x3c\xe6\x11\xdb\x56\xb1\x35\x95\x6a\xac\x9e\x12\x64\x42\xe8\xb8\x0f\x2b\xf7\xd0\xb1\x80\xf2\xe6\xbb\xf9\x22\x46\x87\x09\x70\x1c\x71\xf1\xd1\x09\x16\xef\x27\x9c\xdd\x56\x7e\x2f\xfc\xf7\x9a\x96\xfa\x9a\x95\x84\x43\xfa\xfd\x51\xcd\x3b\xee\x16\xdf\x20\xd3\x37\xcf\xb1\x36\x4d\x53\xef\xd1\x68\x6b\x24\x95\x0b\xf3\x24\x0b\x1b\x34\xbc\xed\x20\x05\xdd\x24\x85\x26\xbc\x33\xad\x1d\x22\x1d\x27\xc9\xf7\x49\x9e\x34\x68\xeb\x16\x4f\x68\x74\x75\x8b\x8b\x87\x7d\xac\x17\x7a\xb1\xf7\x32\x57\x0e\x53\x9e\xdd\x5d\x11\x3f\x8e\x3a\x75\x69\xbb\xa6\x68\x38\x00\xf8\xaf\x96\xc8\xee\x22\x1f\x7e\x74\x43\xdc\x9a\xbb\x3a\x59\x7f\xb7\x60\xef\x00\xc2\x38\x94\x83\x95\x92\x1f\xfb\xa7\x60\x1d\xec\x3a\x5f\x03\x6e\xce\xf6\x24\x9a\x5a\x61\xc3\xce\xf3\x66\x0f\xa8\x91\x43\x89\x5a\xba\x62\xb8\x9a\x30\x69\xc8\xfa\x2d\x61\x79\x95\x23\xd4\x5f\xf3\x4a\xf6\x45\xbf\xc8\xd3\xed\x18\xd4\xb4\xbe\x4f\x3d\x87\xad\x08\xfc\x19\x4f\x09\x1b\x0e\x02\x6b\x8e\xc9\x7c\xd5\xc1\x60\xa5\x23\xa0\xc2\x1b\x4f\x5e\x4b\xb0\x7d\x3c\x5e\xc5\xf2\x35\x09\xee\xf1\x11\x22\x1d\x29\xed\x34\xd7\xf3\x60\xb3\x0c\x3a\xc3\x62\xa0\xd9\x89\xe7\x1a\x82\xdc\xd9\xab\x3e\xc0\x26\x53\xa3\x86\xe0\x39\xde\x98\xc0\xa8\xc7\x8b\xce\xd6\xe0\x27\xaf\xce\xc2\x34\xbd\xbe\x1d\x6e\x66\x13\xbb\x0e\x09\x2f\xc4\x38\x44\x48\x52\x93\x7d\x7a\xaa\x8f\x4a\x2b\xe9\x96\x4a\xf1\x98\x86\x1a\x64\x91\xf1\x3d\xe5\x8b\x01\x10\xcf\x53\xbe\x00\x80\x16\x4c\x16\xf7\x10\x22\x19\xd0\x05\x54\x38\x0a\x72\x09\x75\x08\x26\xe4\x0a\xf2\x71\xf8\xf5\x68\xf4\x3a\x65\xc6\x3f\x76\x4e\x6a\x09\xf7\x01\x75\x5d\x3d\xf9\x4a\xd0\xcc\x05\x45\x62\x01\x12\xd6\x7e\xbd\xc0\x71\x84\x49\xcf\x30\xfb\x0a\xce\x4c\x0c\x48\x0e\x0e\xc4\x7d\x29\x0f\xc2\xdc\x67\x31\x2d\x19\x31\x8e\x44\x09\xb1\x25\x88\x79\x1c\x97\x02\x98\xef\x5a\xeb\x58\x56\x31\x6b\x10\x5c\xad\x24\xc6\x46\x56\x0d\xe9\x5a\x6b\xd5\x03\x57\x1a\x75\x83\x6b\x6e\x82\x10\xb5\x42\x27\xd8\x68\x8e\x66\xfb\x99\x86\x49\x8b\x4a\x70\x20\x16\x7d\xa0\xd4\x45\x7d\xa0\x71\x44\x19\x2b\x8b\x01\x0a\x51\x3d\x68\x15\xc6\x11\x41\x80\x73\x8a\x40\xc7\x35\x88\x5f\x8f\xe6\x6a\xdd\xb0\xb5\xb3\xaa\x07\x45\xa0\xd5\x10\x56\x6f\x54\x12\x11\x89\x05\x48\x50\x15\xbd\xc0\x71\xb4\x55\xcf\xb0\x45\x5b\x44\x28\xcb\x1d\x92\x94\x07\x41\x61\x58\x7c\x57\x46\x4c\xa3\xb2\x42\x9c\x15\x62\x1f\xc7\x68\x01\xf6\x49\x7b\x1d\xdb\x10\x76\x2d\x92\xab\x95\xc5\xd2\xcc\xaa\x2b\xa4\xbd\x56\x55\x68\xb5\x51\x53\x04\x14\x66\x18\x41\x4f\xb4\x82\x26\x71\x6f\x2d\xb3\x16\x35\x11\x80\xcc\x5a\xc2\x38\x10\xb4\x84\xc5\xd9\x51\xb6\x43\xb1\x5b\xa1\xba\x2c\xf2\xba\x43\x65\x3b\x1f\xc3\x6d\xf1\x87\xcf\x01\xa4\x48\xaf\x8a\x56\x39\xcb\x26\x9f\x9a\x53\x9b\x38\x4a\x09\xee\xf9\x44\x05\xc4\x05\x40\x79\x82\x83\xe5\x40\x45\xb1\xfb\x27\x8a\x1a\xa0\xe2\x3e\x89\x51\xa1\xfd\x02\x41\xfe\xf2\x40\xbd\xb3\x8a\x24\x65\x27\x9b\x51\x5f\xed\x92\x1b\x4c\x77\x8f\xeb\xe1\x6a\x24\x2e\x4f\xff\x3c\xf0\xee\x16\xab\xe9\x7c\xf6\x1e\x68\x36\x5d\xea\x9a\x2d\x96\x5e\xb0\x80\x9a\xcc\x77\x8f\x33\xb0\xc5\x0a\x04\x9f\xee\x1e\xa7\x20\x38\x49\x46\x43\x5e\x02\x92\xc3\x8b\xd8\x03\x17\x4e\x05\x0d\x07\x61\x6c\x87\x3b\x7c\xdf\x27\xe1\x96\xfe\xe6\xdd\x6e\xcb\xee\xe3\xeb\x60\xfa\x8b\xbc\xbc\x05\x25\xd8\x7f\xb0\x82\x7f\x88\x67\xa1\x18\x22\xf3\x59\x8b\x01\xe7\x6a\x71\xa1\x33\x89\xbe\xd0\xec\x75\x57\x6a\x01\xdf\x3e\xe0\xeb\x6f\xa2\xcb\x8a\x38\x4c\xdd\xa2\x44\xf9\x59\x99\x06\xb8\x6e\xd0\xa7\x7d\xd2\xa2\xd8\xf2\x39\x0b\xdb\x37\x4e\xfd\xc5\x70\x3d\x2e\xee\x9a\xfc\x3a\x85\xbb\xd9\x0e\xd3\xf1\xf6\x61\x8c\x1c\xca\x4f\x9c\x84\x69\x31\x24\x25\xc4\x01\x6b\xc2\x84\x50\xb4\x2f\xaa\xcc\xf1\x66\xb5\x83\xc2\x1a\xb9\xc5\xa9\xd9\x8e\x87\x74\x0b\x01\x6d\x31\x02\xe3\x53\x21\x26\x66\x56\x26\x7a\xe2\x4a\x43\x42\x21\x0d\x1b\xf4\x9d\x3f\x71\x83\xc5\xfb\x8f\x5b\xbe\x35\x50\x6d\xa8\x63\x92\x27\xd7\x05\xe9\x25\xaf\xb4\xf6\x0d\x54\x7d\x1d\x49\xff\x23\xaf\x6d\x94\x5e\xaf\x74\x6e\xdb\x2b\x06\x2b\x79\xdc\x84\xa7\xa6\xb8\x88\x8c\xa9\x06\x9e\xd8\x31\x9c\x44\x80\xde\xb6\x37\xf5\xcb\x96\x35\xa3\x36\xfa\x5f\x37\xc9\x03\xf0\x7e\x27\x4a\x93\x72\x33\x5c\xa9\x22\x86\x25\x95\x3a\x53\x70\x32\x50\x52\x44\xe0\x33\x8a\xf2\xdc\xc6\xc4\xe3\xaa\x28\x9f\x6a\x4c\xe6\x50\x7a\x00\xdf\x57\xf0\x63\x23\xc2\xdf\x3c\x29\x55\x77\x9a\x7e\xe6\x2d\x35\xa9\xa7\x1f\x74\xbe\xe4\xfb\xa0\x67\x0c\x37\xf3\xc8\xcb\x30\xfa\xb2\x21\x97\x63\x3d\xf6\x15\xf4\x37\xd3\xfd\x0d\x3e\x78\xe8\xee\x50\xf3\x80\x10\xa7\x56\x42\x5b\x73\x9b\xfe\x2b\xc5\xc5\x70\x9f\x99\x7a\xbf\x1d\x7b\x3b\x40\x84\x0a\xe5\xee\xf0\xe5\x5b\x0e\xfb\x11\x2a\xe2\x47\x60\x8e\x3e\x7f\x7a\x91\xc5\x60\x1a\x68\x5e\x87\x6f\x75\xd4\x51\x1e\x6b\x47\x1c\x63\xc4\x00\xc2\x60\x77\x25\x5a\x50\x68\x8c\xc5\xe4\x15\xd2\x00\x13\xf9\xfd\x64\xf9\xf4\x8f\x05\xfe\x81\x36\xda\x4f\xff\xc4\x36\x75\x54\x15\x69\xba\x0b\x2b\x37\x43\x61\x7d\xd2\xdf\xca\xb9\x5e\xaf\xd7\x65\x4b\x17\x84\x85\x5f\xb6\xcc\xb1\xc5\xcf\xbd\x03\x42\xf0\x19\x0e\xda\x09\x0b\x0e\x77\x3d\x90\xdf\xa1\xa1\x6b\xcc\xcc\x2f\x5b\x87\x5f\x9f\xea\x8c\x03\x9d\x75\xa0\xa6\x54\xf2\xa4\x4d\xca\xa3\xbf\x23\x6d\xbc\xa6\x28\xd2\x26\x29\x81\x4e\x0e\xf6\x70\xe5\x4b\xfb\x1a\xec\xbf\xee\xc3\x2c\x49\x1f\x37\x9d\x93\x97\x22\xb7\x7e\xac\xbb\x0d\x07\xf9\xe3\x9e\x92\xc9\x5f\xd2\x24\xff\xf2\x4b\x18\xfd\x03\x97\xfc\xaf\x22\x6f\x26\xef\xfe\x81\x0e\x05\x72\xfe\xfb\x6f\xef\x26\xff\x59\xec\x8a\xa6\x98\xbc\xfb\xdf\x28\xbd\x47\xdd\xda\xe5\xfc\x1d\x9d\xd0\xbb\xc9\xbf\x57\x49\x98\x4e\xea\x30\xaf\xdd\x1a\x55\xc9\x9e\xfa\xce\xf4\xfb\x12\xbc\x8c\xf1\xce\xf3\xbc\x73\x9e\x51\xd3\xa0\x0a\x9f\x77\xee\x14\x8a\x42\x91\xb3\xd6\x15\x0a\xbf\x90\xc5\x5a\xbe\xef\x94\x7b\xc9\xda\x29\x0e\xff\x9b\xbc\x18\x07\x3d\x66\xde\x1f\x1f\x0a\x06\x0f\x04\x97\x89\xe7\xaf\x31\x37\x0f\x45\x15\x53\x6e\xf8\x12\x89\x67\xe5\x7c\x3c\x81\xc2\xb9\x3e\x71\x63\xb7\xfb\xcd\x5f\xe2\x4b\x47\x4f\x5a\x69\xd6\x43\xc5\xae\x76\x1b\xd4\x1c\x51\xe5\xa2\x14\x65\x28\x6f\xdc\xb0\x69\xc2\xe8\x88\xe2\xfe\x1b\x3b\x06\x4a\xff\xe2\xaf\xe6\xd8\xec\x5c\x74\x3b\x8e\x2d\x9f\xed\x68\xd6\x59\xb4\xd1\xd8\x9d\x1e\x6b\x92\xe7\xc3\x57\x4d\x20\x51\x0d\xec\x59\x5c\xa7\x17\xc3\x77\x6e\xe4\x0b\x93\xce\x7e\xf0\x57\x85\x11\x53\x42\xe7\x50\xd9\x3a\xa4\x0b\xea\x91\x38\xbc\x9e\x8f\xe8\x48\x47\x45\xe5\x97\xde\xf8\xc5\x36\x46\x1d\x15\x81\xad\xb1\x62\xea\x80\x47\x0b\x89\xde\x3c\x0e\x8b\x09\xef\x70\xfd\xf7\x5b\xf1\x14\x02\x1e\xb3\x31\x22\x12\xc4\x44\x5e\xb6\x5e\x29\xa8\xa6\x28\x55\x96\xe9\xf7\xa6\x5a\x7d\x1a\x2b\x27\xbd\x7e\xe8\x68\x9a\xe4\xf4\x14\x5d\xf2\x99\x98\xa4\xd7\xce\x57\x4a\x09\x8b\x56\xe5\x99\x5c\x39\xa7\x55\xa7\xd1\xd3\xce\xa4\x22\x30\x55\x9b\x3e\x31\x77\xf9\x1a\x85\x52\x64\x85\xdf\xcd\x03\x92\x22\x34\xb9\x65\x09\xdf\x1a\xd0\x3b\x07\xb3\xb2\x75\xee\x30\x2d\xc3\xe7\x2e\xa0\xab\xae\x39\xf2\x08\x77\x55\x5d\xfb\xe8\x90\xb3\x15\xdd\xd7\xde\x0a\xcc\x2a\xc8\x0a\x85\x1d\x97\x8b\x57\x16\x25\x8e\xbf\xe8\x62\x63\xca\x86\x63\x29\x2f\xb0\x9c\x40\x3a\x2f\x61\xf0\x96\xca\xf6\x8f\xc5\xf7\x4d\x17\xdf\x9b\xd9\xf6\xf6\x6a\x36\x66\x8d\x67\xa0\xf4\x2f\x5e\xe3\x85\x8b\xa3\x71\x0c\x63\x34\x42\xfa\x59\xf7\xe4\x9a\x16\xcc\x06\x01\xac\x28\xe8\x84\x3a\x3a\x49\x7b\x8b\x2d\x9a\x5f\x3a\x53\xaf\x62\xde\xc8\x8a\xe8\x75\xb8\xd3\xa9\x6c\x8a\xa7\xd2\x2d\xdb\x5c\x7a\x21\x36\x60\x8b\x8f\x5f\x23\x4c\x55\x32\x03\x37\xbe\xc2\x8d\x0f\x71\x43\xce\x13\x8d\x60\x81\x78\x37\x32\x65\xe2\xdd\x08\x29\x55\xc6\x2a\x08\x86\xbe\x42\x3d\x08\xbc\x6e\x44\xc8\xe2\xa3\x13\x10\xad\x95\x16\x2c\x7e\xc9\xb9\x46\x3b\x46\x71\xc2\x2b\xa3\xa0\x1b\x64\x1a\x71\xaa\xc1\xfb\x50\x4f\x51\x0e\x50\x90\x90\x5c\xce\x9c\x22\xc8\x73\x1a\x74\xe8\xc6\xea\x06\x76\xe8\x64\xca\xd4\xa1\xe3\x08\x8d\x56\x0d\x68\xa6\xdb\xc0\x75\xc3\x61\x99\x3a\xe2\x4c\x57\x6c\x47\x37\x51\xae\x51\x8d\x51\xac\x70\x6a\x68\xb1\x1a\x82\xe7\xf8\x14\xdd\x30\xd9\x4c\x41\x32\xe7\x41\x13\xb4\x56\x43\xf4\x63\xf1\xc9\xdd\xd5\x58\x2e\x9c\xc1\x58\x25\x4d\x8a\x6c\x42\xd2\x80\x9b\x1d\xa5\x6e\xdc\xa0\xd7\xaa\x01\xdc\x2b\xd5\x2f\x55\x43\x87\x57\x74\x92\xfa\xeb\x72\x7f\xb0\xbf\xae\x10\x1f\x8f\xf1\x9a\x89\x20\x98\x1e\x98\x15\xad\x36\xf0\x46\x4d\xb6\x90\xc4\x28\x5c\x33\x0f\x46\x71\x42\x89\xb1\xef\x1c\x4d\x36\x92\xdb\x16\x3c\x65\x1a\x98\x57\x07\x4e\x2e\x3d\x33\x26\x1b\xc9\xef\x51\x78\x13\x49\x43\xcb\xcc\x05\xbf\x2b\x5b\x67\x3a\x1f\xf0\xf4\xe1\x09\xee\x2d\xaf\x21\x53\xef\xca\x10\xd0\xde\x75\xff\x68\x93\x0a\x90\x7c\x77\xb3\xb1\x49\xf8\x66\x7c\x0e\x3e\x71\xda\x41\x5f\xf6\x33\x88\xfe\x0d\x16\xed\xee\x9a\x76\xb7\x87\x90\xe5\x6d\x98\xc4\xd0\xac\xfd\xca\x3d\x55\x4f\x4d\xb7\xfd\xec\xd4\x4b\xe6\x55\x0f\xec\xd3\x44\x71\xc5\xa9\x46\xa9\xfa\x46\x60\xa8\xa3\x1b\x55\xdd\xfb\x40\x7c\x96\x41\x79\xa3\x3d\x34\x36\x7f\xb5\x40\x36\x2e\xc3\x7d\x36\x2c\x90\xab\xbc\x16\x75\x67\x31\xc9\x53\xc5\xa1\x1d\xf7\xd6\x7a\x49\x5f\xf3\x26\xf9\x88\x17\xd7\x12\xb0\xe9\xdd\xb5\x1e\xef\xd7\x01\x41\x2f\xb1\x65\x08\x13\x23\xfc\x86\x6c\x1f\x46\xc8\xbd\x4f\xea\x64\x97\xa4\x49\xf3\xc8\xde\xfc\x1a\xaa\x58\xeb\x12\x55\x75\x89\xf0\xb1\xa1\x6e\x64\x70\x68\x42\x29\xba\x5c\xfe\x5c\x9f\xca\xb2\xa8\x9a\xda\xf9\x4e\x1d\xb3\xe1\xad\xf4\x2c\x26\x06\xee\xe3\x47\xa7\xa8\x9c\xef\x8c\x10\x7f\x0c\xf3\xed\x0d\xb3\x38\x22\x6e\x8e\xbf\x87\x10\xcb\xca\x0a\xdd\x4b\x65\xec\xd8\xd9\xb3\xbd\xf8\x1b\xcb\x87\xce\xab\xba\xca\xbc\x60\xec\x52\x11\xd9\x33\xaa\x04\xa5\x22\xb2\x89\x1c\x33\x1f\xa0\x23\x1c\x7d\xe5\x85\x0a\x10\xc2\x2e\x73\xd1\x31\x6b\xa1\xd8\x19\x58\x13\xd1\xbe\x5e\x43\x57\xd7\x79\x0b\x59\xd7\x46\x77\x00\x78\x15\x7b\xf2\xc7\xb8\xbe\xc1\xb8\x0e\xe8\x3b\x87\xa4\x2a\x52\x79\xee\xb2\x62\xd3\xf4\x1d\xce\xad\x7c\xab\x47\x09\xa4\x72\xf9\x88\x80\x8c\x9f\x6f\xa3\x81\xa5\xbe\xd3\xe2\xbd\xf9\x4d\x81\x70\x68\x12\x1a\x0a\x2e\xeb\x37\x50\x49\xef\xe0\x02\x47\x4b\xdb\x12\x57\x8e\x4b\x7d\xd5\x9f\x63\xda\xf2\x6f\x72\x61\xe5\xe0\x52\xee\xaa\x9c\xd2\xed\x8e\xae\x1a\x5f\xe8\xa4\x61\x95\x5c\xf6\x64\x48\x34\x1a\x70\x07\x1d\xf0\x33\x77\x06\x94\xff\xf2\x3f\x2f\xdc\x0a\x95\x28\x6c\x1c\x22\x7c\x47\xd6\x06\xf9\x33\x7f\xdf\x7f\xef\x90\x23\xc1\xba\x1a\x8d\x2c\x9e\xe1\x7e\x2a\xfb\x5d\x54\xce\x3e\x49\xd3\x1f\x3f\xbc\x0f\x66\xfb\xfd\xfe\x83\x78\xa1\xd5\x9d\x73\xc7\xdf\x55\x45\xae\x92\xf2\x53\x77\xee\x90\x7f\xa6\xde\xc2\xed\xfe\x0d\xc8\xbf\x0e\xfd\xeb\xd2\xf2\xdf\x80\x1b\xa6\xf4\xe3\x76\x63\x1d\x9d\x7a\x8b\xae\xab\xdd\x9f\x29\xe9\x9a\xc3\x75\xd3\x61\xe5\x73\x17\xff\x63\xec\x6a\x92\xc7\x49\x14\x36\x45\x55\x03\xa6\x4f\x3a\xb4\x87\xf7\xed\xf2\x6b\xb4\xc5\x0b\x59\xc4\x17\x32\x5a\x70\xda\x00\x96\x8d\x5c\x7c\x33\xdd\xfd\x96\x32\xad\x82\x92\x73\xd2\xe4\x49\xe7\xda\x7c\xe5\x5c\x9b\x2f\x9c\x6b\xa3\xbf\xf8\x23\x47\x83\x19\x98\x0d\xc1\x90\x4a\x2e\x60\x87\x21\x88\xc5\xeb\x06\x2a\x6f\xf0\xd1\xa9\xb2\xd5\x1f\x26\xd7\xde\x63\xb1\x80\xf5\xc5\x49\x13\x4b\x28\xd1\xe5\x15\xc6\x96\x46\xb9\xff\x3e\x41\x88\x26\xea\x29\x93\x18\x83\x4a\x58\x78\x69\xf3\x02\xb4\xd9\xce\x42\xf3\x35\xf9\x60\x43\xc2\x12\x27\x9c\xd0\xcd\xaa\x4e\xb9\x58\x02\xb9\x9e\xd5\xae\x70\x78\x41\xbd\xe5\x3f\x73\x08\xb8\x57\xf4\x2e\xdf\xd0\xb4\xf8\x5e\x3c\xe2\x1a\xb0\xd4\x93\x67\x4d\x4a\xca\xe1\x86\x5f\xd6\xa2\x29\x4a\x19\xb8\x29\x4a\x15\x2e\x4b\xe2\x38\x55\xf0\x92\x52\x15\x9a\xbe\xc7\x90\xb9\xc0\xa5\x00\x0f\x5d\x77\xe0\x26\x5c\x95\xa6\x1d\xd4\x01\x5a\xce\xb7\xd8\x1d\xdc\x7d\x18\x8b\x49\x94\xa4\xa0\xfc\xee\x60\xcd\x26\xc9\x61\x0c\x39\xf8\x21\x17\xe7\x50\x64\xce\x23\x29\xb1\x66\x4b\x27\x29\xd3\x95\x3f\x59\xe6\x8a\xcc\x89\x24\x25\xba\xc6\x7c\x92\x32\x51\xe1\x2b\x58\xf6\xdb\x9c\x49\x52\x22\x67\x4b\x28\x29\x53\x94\x3f\xac\xe4\x8a\xcc\xa9\x24\x25\xba\x96\x8c\x92\x32\x59\xe9\x1b\xbd\xa1\xc4\x9c\x4b\x52\x91\x2d\xb9\xac\x48\x05\x27\x29\x59\x54\xf1\x62\x78\x51\xc2\xa4\x48\x47\x77\xea\x4f\xa7\xd3\x40\xa0\x4b\x02\xb0\xfe\x99\x7d\x2d\x04\x54\x36\x45\xd9\x03\x90\xec\x02\x00\x10\x09\x8e\xfb\x52\xb2\x03\x00\x90\xbe\xe0\xf2\xe5\x44\x03\x00\x28\x0e\xa3\xf7\x80\xc4\x66\xf3\x60\xb8\x6f\x48\xbe\x2f\x8f\x9d\x2e\xa2\xb5\xc6\xbb\x28\xc6\xa5\x49\x61\x98\xc8\x5e\xfb\xeb\xd3\x95\x33\x7c\xf6\xfb\x2d\x46\xa7\x56\x61\x28\xf1\x9b\xb0\xaf\x4d\xd8\xce\x90\x45\x49\x15\xa5\x48\x12\xef\xa2\x73\xfd\x19\x84\x0f\x5c\x35\x91\xa2\xb0\xda\x27\xed\x55\x97\x0d\xc4\x6e\xe7\x44\x09\x2f\x41\xf8\x81\x8e\x5d\xb2\x42\x4b\x5b\x21\x08\x84\xde\x4d\x0a\xad\xec\x22\xb8\x08\x07\x00\x34\xe1\x2e\x1d\x28\xe2\x5f\x00\x80\x1b\xa1\x34\x15\xa1\x70\x91\x08\xda\x39\x6e\xaf\x7f\x2b\x3f\x27\x15\x90\x01\x26\x1c\x23\x1f\x1c\x02\x0d\x3b\x1c\x04\x8c\x0a\x44\x61\x38\x83\x1f\xbb\x75\x66\x53\x88\x3a\x1b\xa3\x13\x3d\xd4\x68\xb5\xa8\x33\xbb\x66\xd4\x99\x5d\x39\x18\xcc\x38\xfd\xa8\xb3\x37\x54\x91\x41\x48\x37\xa8\x25\x80\x9a\xac\x96\x77\x54\x4d\x32\xab\xdd\xc8\x46\x99\x8e\xec\x6a\xeb\x91\x8d\x30\x20\xd9\x08\x1b\x92\x5d\x65\x46\xb2\xb7\xb4\x24\xd9\x2d\x1b\x13\xc3\xe7\x36\xb1\x9b\x1e\x6c\x6a\x92\x1e\xc6\xa8\x49\x0f\x35\x5a\x4d\xd2\x83\x5d\x4d\xd2\x83\x5d\x4d\x18\xcc\x38\x35\x49\x0f\x6f\xa8\x26\x83\x90\xbe\x0d\x35\x99\xe2\x43\xee\x58\x4f\xda\xd4\xa6\x27\x6d\x3a\x46\x4f\x7a\xa8\xd1\x7a\xd2\xa6\x76\x3d\x69\x53\xbb\x9e\x30\x98\x71\x7a\xd2\xa6\x6f\xa8\x27\x83\x90\x6e\x51\x4f\x3c\x92\x47\x32\xa9\xea\xe6\x2c\x7e\xe2\x1d\x27\x79\x98\xd2\x4b\xd5\x87\xdc\x0a\x64\xf7\xe4\x4e\x87\x98\x63\x5f\xc2\x1e\x28\xce\x34\x34\xa2\x0c\x24\x94\x0a\x46\x86\x90\xe1\x3b\xe5\xf8\x37\x8a\x0d\x48\xa7\x12\x52\x5f\x46\xea\x6f\xfb\xcc\x1f\xb8\xb4\x2a\x1e\xce\xc0\x97\xed\xc7\xa2\x4a\x7e\x2b\xf2\x26\xe4\x14\xc9\xf8\x95\x3b\x00\x26\x7d\xbf\x5e\x15\x0f\x3c\x90\xfa\xd9\xbb\x08\x60\xaa\xa4\xbc\x93\x2f\xe2\x21\xf6\x59\xd8\xe7\xd9\x98\x27\xa4\xcc\xfc\x2b\x30\x96\xfa\x61\x04\xdc\x0a\x91\x88\xc0\xd7\x8d\x04\xc5\x32\x6a\x28\x5c\x00\x18\x1c\x12\x00\x70\x0c\x90\x30\x44\xa6\xfe\x8d\x1e\xaa\xd1\xbd\x13\x69\x8e\x19\x33\x7b\x1f\x75\x70\xb4\x9b\x0f\x55\x58\x9e\x05\x76\xf0\xf7\x2b\xdd\x7f\x20\xfa\x50\xa5\xae\x82\x52\x20\x17\x0a\x01\x34\x48\x85\x96\x8a\x52\xad\xaf\xe2\xfa\xa2\x0c\x98\xc8\x9d\x49\xb6\x26\x20\x1b\xc0\xc5\x93\xde\xd9\x90\xac\xd8\x67\xe5\xad\x10\x2e\x06\x34\x01\xfc\xec\x5d\x01\x16\x5e\x16\xc9\xb5\x63\x50\xa8\x7c\xa2\x3c\x56\xb9\x44\x79\x3c\x96\x47\x09\x54\xfe\x9e\xdf\xc6\x9f\x00\xa2\x72\x47\x5e\x05\xa8\x0c\x92\xf2\x11\x3c\xaa\x80\xc0\x0b\x37\x03\x93\x32\x80\xca\x22\xcd\x41\xa1\xf2\x48\x01\x47\x30\x29\x24\xb3\xd0\xf2\xaa\xe2\x1b\x89\x47\xe5\x39\xc4\xc1\xb1\xb3\x99\x1f\x02\xa4\x65\x27\x4e\xea\xa6\x4a\x76\xa7\x06\x59\x39\x92\x31\xb1\x97\x1d\xf8\xd4\x07\x30\x53\xb8\x0f\xfb\x00\xe9\xc1\x09\xe8\x21\x3e\x61\x3c\xb6\xf6\x22\x77\xf2\xfc\x20\x38\xe1\x09\xa2\x60\xd6\x4c\x0e\x08\x87\xb9\xad\xc8\x13\x30\x2b\xf8\x37\x67\x16\xce\xf4\x53\x42\x83\xc4\xd4\x58\x64\xac\x7f\x57\xa7\xb2\xa6\xbe\xae\x03\x99\x83\xc0\x44\xf6\x00\x08\x33\x02\x59\xdb\x2a\xd4\x44\x47\x50\xdf\x70\x8d\x85\x41\x00\x4a\x56\x37\x19\xc0\xd8\x9c\x71\x07\xaf\x1b\x42\x9d\x45\xdb\xf1\x26\x01\x5c\x19\xec\x58\x64\x2e\x78\xad\x07\x5a\x6b\xf4\x7a\xe0\x00\xd2\x6d\x93\xdd\x17\xa9\x4b\xfa\x2d\x36\xd7\xab\xef\x40\x5e\xa3\xc2\x7a\xa3\x2e\xd2\x97\x4d\xba\xd8\xda\x6a\xad\x07\x3e\x54\x93\x3d\x0a\x95\xcc\x8f\x64\xae\x21\x1c\x7a\x63\x3d\x70\x03\x5a\xec\x31\xc8\x54\x1d\x15\xe7\x90\x84\x43\x3f\x43\x78\x15\x85\x67\x89\x16\x09\xe3\xa1\x46\xe9\xde\x0d\x4f\x4d\x21\x51\xef\xca\xf1\xb7\xe3\x10\x5d\x72\x95\x04\x9e\x9e\x00\xc8\xa1\x4a\x62\xbc\x99\x01\x21\xb4\xe8\x05\x8e\xa0\x69\x8b\xdb\x98\xe7\x2c\xc7\x18\x3c\x69\xb5\x38\x04\xea\xea\x74\x1d\xda\x69\xe6\x2a\x47\x19\x9a\xac\x9a\xf6\x02\x55\x70\x9a\xe2\x86\xfa\x39\xca\x91\x05\x81\xa4\xb1\xd0\x4c\x64\x90\x88\xc0\x9b\xb2\x12\x71\x0d\x4d\x6b\x0c\xc7\x9f\x76\xa1\xd1\x20\x91\xf4\x01\x9a\x22\xb8\xa5\x61\x7e\x08\xea\x00\x41\x49\xe2\xd1\xcd\x22\x98\x8e\xe1\x75\x16\xd1\xb0\xec\x45\xa2\x49\x75\xf6\xec\x01\xa5\x3a\x7b\x99\x98\x52\x9d\x7d\xd3\x61\xa5\x3a\xfb\x9d\x44\x96\xc8\x38\xfc\x7e\x83\x4b\xfd\x40\xfd\xee\xe3\x4b\x75\xf6\x0a\x21\x26\xfc\x2a\xfe\xb5\xa2\x4c\xb4\x47\xb7\x13\x68\xca\xbe\x99\x58\x53\x9d\xdd\x78\xb8\xa9\x9b\x97\xb7\x1f\x71\xaa\xb3\x6f\x32\xe8\x54\x67\x37\x16\x77\x82\x26\xce\x2d\x85\x9e\x80\xe9\x72\x0b\xd1\x27\x78\x92\xdc\x46\x00\xaa\x9b\x1a\xdf\x40\x0c\x2a\xbb\xfd\x30\x94\x3c\x39\xde\x2a\x12\x25\x4d\x82\xd7\x0f\x46\xa9\xea\xfe\xea\xf1\x28\xc0\xe0\xbf\x75\x48\x4a\x35\xe6\x6f\x1f\x95\x52\x67\xd5\xab\x07\xa6\x3a\xb1\xdc\x5e\x6c\x0a\x9e\xcb\xaf\x17\x9e\x02\xe7\xf0\x6b\x44\xa8\x74\x73\xf7\x46\x82\x54\xd0\x6a\xf5\xda\x71\x2a\xdd\xa4\x79\xe3\x50\x95\xe1\x4c\x2d\x26\x9f\xc5\x2f\x12\xab\xca\xe2\x67\x8f\x55\x65\xf1\xcb\xc4\xaa\xb2\xf8\x9b\x8e\x55\x65\xf1\xef\x24\x56\x45\xc6\xe1\xf7\x1b\xab\xea\x07\xea\x77\x1f\xab\xca\xe2\x57\x88\x55\xe1\xef\x01\x5e\x2b\x56\x45\x7b\x74\x33\xb1\xaa\x2c\xfe\x66\x62\x55\x59\x7c\xe3\xb1\xaa\x6e\x5e\xde\x7e\xac\x2a\x8b\xbf\xc9\x58\x55\x16\xdf\x56\xac\x0a\x9c\x38\xb7\x14\xab\x02\xa6\xcb\x2d\xc4\xaa\xe0\x49\x72\x1b\xb1\xaa\x6e\x6a\xdc\x7e\xac\x0a\x6b\xde\x6d\xc7\xaa\x94\xc9\xf1\x56\xb1\x2a\x69\x12\xbc\x7e\xac\x4a\x55\xf7\x57\x8f\x55\x01\x06\xff\xad\x63\x55\xaa\x31\x7f\xf3\x58\x15\x30\xab\x5e\x3d\x56\xd5\x89\xe5\xe6\x62\x55\x9a\xb9\xfc\x7a\xb1\x2a\x70\x0e\xbf\x46\xac\x4a\x37\x77\x6f\x24\x56\x05\xad\x56\xaf\x1c\xab\xd2\x4e\x9a\xdb\x8b\x55\xb1\x0f\x7b\xc9\x84\x3d\xbc\xcc\x57\x7a\x87\x67\x8f\x55\xa5\x87\x97\x89\x55\xa5\x87\x6f\x3a\x56\x95\x1e\x7e\x27\xb1\x2a\x32\x0e\xbf\xdf\x58\x55\x3f\x50\xbf\xfb\x58\x55\x7a\x78\x85\x58\x15\x4e\x4a\xf0\x5a\xb1\x2a\xda\xa3\x9b\x89\x55\xa5\x87\x6f\x26\x56\x95\x1e\x6e\x3c\x56\xd5\xcd\xcb\xdb\x8f\x55\xa5\x87\x6f\x32\x56\x95\x1e\x6e\x2b\x56\x05\x4e\x9c\x5b\x8a\x55\x01\xd3\xe5\x16\x62\x55\xf0\x24\xb9\x8d\x58\x55\x37\x35\x6e\x3f\x56\x85\x35\xef\xb6\x63\x55\xca\xe4\x78\xab\x58\x95\x34\x09\x5e\x3f\x56\xa5\xaa\xfb\xab\xc7\xaa\x00\x83\xff\xd6\xb1\x2a\xd5\x98\xbf\x79\xac\x0a\x98\x55\xaf\x1e\xab\xea\xc4\x72\x73\xb1\x2a\xcd\x5c\x7e\xbd\x58\x15\x38\x87\x5f\x23\x56\xa5\x9b\xbb\x37\x12\xab\x82\x56\xab\x57\x8e\x55\x69\x27\xcd\xed\xc5\xaa\xfa\xec\x62\x98\x7e\x9b\xbe\x48\xb0\xaa\x4d\x9f\x3d\x58\xd5\xa6\x2f\x13\xac\x6a\xd3\x6f\x3a\x58\xd5\xa6\xbf\x93\x60\x15\x19\x87\xdf\x6f\xb0\xaa\x1f\xa8\xdf\x7d\xb0\xaa\x4d\x5f\x21\x58\x85\x33\x23\xbe\x56\xb0\x8a\xf6\xe8\x66\x82\x55\x6d\xfa\xcd\x04\xab\xda\xf4\xc6\x83\x55\xdd\xbc\xbc\xfd\x60\x55\x9b\x7e\x93\xc1\xaa\x36\xbd\xad\x60\x15\x38\x71\x6e\x29\x58\x05\x4c\x97\x5b\x08\x56\xc1\x93\xe4\x36\x82\x55\xdd\xd4\xb8\xfd\x60\x15\xd6\xbc\xdb\x0e\x56\x29\x93\xe3\xad\x82\x55\xd2\x24\x78\xfd\x60\x95\xaa\xee\xaf\x1e\xac\x02\x0c\xfe\x5b\x07\xab\x54\x63\xfe\xe6\xc1\x2a\x60\x56\xbd\x7a\xb0\xaa\x13\xcb\xcd\x05\xab\x34\x73\xf9\xf5\x82\x55\xe0\x1c\x7e\x8d\x60\x95\x6e\xee\xde\x48\xb0\x0a\x5a\xad\x5e\x39\x58\xa5\x9d\x34\x6f\x1d\xac\xf2\xf6\x69\x11\x36\xe4\xc6\x20\xfc\xb8\xe9\x1e\xc5\xdd\x58\x07\x40\x6e\x3d\x22\x10\xf8\x59\x05\xc1\x59\xf3\x09\x84\x94\x33\xdf\x94\x15\xab\x6b\x59\x67\x76\x06\xea\x6c\x0c\x0f\xec\xca\x18\x90\x0d\xe3\x17\x8f\x5d\xeb\x2c\xb6\xf3\x91\xc5\x63\xf8\x60\x77\x92\x8c\xe5\x63\x38\xcd\x86\x47\xe3\x60\xe7\x23\x3d\x8c\xe1\x83\x5d\x7a\x31\x96\x0f\x2e\x52\xd9\x35\x6f\x53\x3b\x23\x6d\x3a\x86\x11\x76\xab\x02\xcc\x88\xb7\x4f\x5a\x7a\x49\x57\x7f\x23\x22\x2e\xa2\xf7\x2b\xb3\xab\x46\xe5\xeb\x45\xfd\x99\xcf\xda\xd2\x6b\xb4\xa4\xe6\xd2\x1d\xa5\x1a\x0c\x75\x93\x44\x5f\x1e\x45\xf2\x6c\x9a\x92\xba\x6d\x5f\x4e\x7f\x13\xbe\x24\x34\x95\x5b\xe4\xe9\x23\x70\xa9\x23\x15\xee\x70\x3f\xe7\x74\xb8\xae\xb1\xbf\x67\x74\xe3\x76\xa5\xc5\x3d\xaa\xf6\x69\xf1\xc0\x2e\xc4\x8f\xd2\xa4\xdc\x54\x28\x6a\xc8\x1d\xdd\x13\xff\xe3\x76\xd7\x47\x53\x29\x45\x17\xdf\xfe\x16\xee\x52\xb4\x21\xf7\x4f\x4e\x80\x1a\xfc\x74\xe6\xfa\x11\x36\x49\x44\x39\xc3\x37\x89\x52\xd6\xe8\xad\xa2\x98\x23\x7f\x60\x07\x5f\xd5\x9f\x22\xc2\x4f\x07\x73\xf1\x1e\xdc\x60\x71\xa6\x57\x10\x2f\xde\xf3\x63\xfe\xe0\x2e\x7c\x5a\xb3\xf0\xa5\x9a\x15\x6b\xb3\x92\xdb\x4c\x7d\xd6\x68\xea\x8b\xad\x8e\x1d\x25\x76\xc3\xf1\x42\xaa\x5a\xf8\xac\x6a\x21\xb7\x5a\xf5\xad\x56\x72\xab\x8e\x58\x7f\xb3\xa7\xd8\x2e\x23\xac\x0c\x37\xab\x2a\x00\xc7\x1e\x40\x87\xc2\xed\xaa\x89\x0c\x1d\xe1\xba\xba\xac\xe9\xab\xd4\x6b\xf4\xb2\x6a\xa8\x04\x2e\xcf\xcb\x76\x43\x35\x74\x63\x5e\x96\x0e\xf5\xea\x45\x79\x59\x6b\x40\xbe\xd5\x37\x7b\xd4\x32\xbc\x35\xf1\xe2\x4e\x99\x04\xc8\x8d\x72\x0e\xf9\x23\xc9\x62\xca\xa3\x06\x20\xaa\x01\x82\xf0\x0c\xc0\xec\x06\x18\xca\x09\x00\x94\x0e\x40\xb8\x8f\x00\x48\x6b\xa3\xb5\xb5\x20\x78\x34\x77\x67\x6b\x65\xd2\x0d\x7a\x99\x11\x91\x01\x12\x0b\x04\x12\x80\xc0\x02\xa9\x13\x80\xbc\x02\x59\x5e\x80\xb8\x02\x51\x5c\x80\xb4\xcc\x84\xb6\xe6\xe6\x8f\xc6\x8e\xc8\xa2\x52\x25\x35\x63\x92\x9a\x76\x82\x9a\xaa\x72\x9a\xf1\xe8\x95\xfa\x6a\xa8\xa7\x37\xee\xaa\x52\x9a\x49\x52\x52\x40\xd2\x01\x84\x5c\xd0\xab\xca\xc8\x48\x65\x6b\x6c\xfc\x68\xea\xc2\xd6\xc2\x9a\x3b\xef\xe5\x43\x54\x69\x0a\xe9\xd2\x5c\x20\x00\x29\xd3\x5c\xe2\x1f\xd2\xa6\xb9\x2c\x27\x48\x9d\xe6\xa2\xa4\x20\x7d\xb2\xd0\xda\x5a\x10\x3c\x9a\xbb\x23\x4b\x0c\xd0\xa9\x05\x93\xd9\xac\x93\xd8\x4c\x95\xd7\x82\x27\xa0\xd4\x57\x43\x3d\xbd\x74\x5b\x95\xd5\x42\x92\x95\x02\x92\x0e\x20\xe4\xa2\x6e\x55\x4e\x46\x2a\x5b\x63\xe3\x47\x53\x17\xb6\x66\xd6\x4a\xd7\x3f\xf7\x3e\x8b\xb8\xa8\x95\xcd\x50\xa7\xae\x6a\x65\xc5\xd5\x02\xcb\x5a\xb9\xe3\xea\xa1\xb5\xa4\x4c\x39\x00\x75\x85\x2a\x5b\x13\xfe\xad\xa1\xe1\xa3\x9e\x6d\xf9\x36\x6d\xb1\xa1\x3b\xed\x45\xa1\x5d\xdd\xca\x66\x80\xd2\x2c\x6f\x65\xc5\x81\xe8\xd6\xb7\x72\xc7\x01\x69\xd7\x8e\x32\xe5\xa0\x34\x0b\x54\xd9\x5a\xc9\x6d\x6d\x28\x1e\x2d\x9d\x92\xe5\x06\xa0\x70\x83\x41\x78\xf0\x32\x57\x36\x03\x0c\xbc\xce\x95\x15\x07\xa1\x59\xe8\xca\x1d\x07\xa3\x5b\x49\xca\x94\x03\x82\xd7\xaa\xb2\xb5\xd1\xda\x5a\x10\x3c\x9a\xbb\xa3\xc8\x4c\x15\xd9\xac\x17\x19\xb8\xde\x95\xcd\x00\x01\x2e\x78\x65\xc5\x01\xc0\x2b\x5e\xb9\xe3\x40\x34\xeb\x4a\x99\x72\x30\xe0\xb2\x55\xb6\x16\x42\x5b\x73\xf3\x47\x63\x47\x64\x49\x29\xcd\xdd\xf9\x20\x28\xdd\xc2\x57\x36\x03\x94\x66\xe5\x2b\x2b\x0e\x44\xb7\xf4\x95\x3b\x0e\x48\xbb\xac\x94\x29\x07\xa5\x59\xbb\xca\xd6\x4a\x6e\x6b\x43\xf1\x68\xe9\x94\x22\x3a\x40\xcb\x16\xbd\xf0\xc0\x15\xb0\x6c\x06\x08\x70\x09\x2c\x2b\x0e\x00\x5e\x03\xcb\x1d\x07\xa2\x5b\x69\x52\x0e\x06\x5c\xc8\xca\xd6\x42\x68\x6b\x6e\xfe\x68\xec\x88\x2c\x2a\x65\x19\x25\xd1\x67\xea\x2c\xc8\x21\xe1\xac\xe1\xab\x31\x7a\x05\xa4\x12\x40\xaa\x7e\xe3\x2d\x79\x0b\x3c\x10\xe5\x45\x81\x4a\x05\x28\xdc\x5d\x05\xa6\xb5\x92\xdb\x1a\xdb\x3f\x5a\x7a\xb4\x35\xf2\xa8\x0f\xff\x65\x6e\x6d\xdc\x29\x73\xb5\xe0\x66\x99\xaf\x87\xf7\xcb\x3c\x84\x66\xcb\xcc\x83\x80\xbb\x66\x23\x15\xe3\xc6\xd9\xc0\xbf\x79\xef\x5c\x8f\xdc\x3e\x73\x70\xfa\x1d\x34\x0f\x64\xd8\x44\xf3\x60\xa6\x7d\x34\x0f\xa7\xdf\x4a\xdb\x89\xda\x77\xd3\xb6\xde\x8d\xd8\x50\xd7\xa3\xf6\xd4\x1c\x94\x76\x5b\xcd\xc3\xe8\x77\xd6\x3c\x94\x61\x73\xcd\x83\x69\xf7\xd7\x56\x8a\xd6\x2d\xb6\xa5\x5f\xf6\x5d\x76\x3d\x62\xa3\xcd\xc1\xe8\xf6\xda\x3c\x88\x76\xbb\xcd\x03\xe9\x77\xdc\x3c\x94\x6e\xd3\x6d\x23\x67\xdb\x77\x9b\x7b\x64\xdd\x7a\xd7\x23\x77\xdf\x1c\x9c\x7e\x03\xce\x03\x19\xf6\xe0\x3c\x98\x69\x1b\xce\xc3\xe9\x77\xe2\x76\xa2\xf6\xcd\xb8\xad\x77\x23\xf6\xe3\xf5\x88\x2d\x39\x07\xa3\xdb\x95\xf3\x20\xda\x8d\x39\x0f\xa4\xdf\x9b\xf3\x50\xba\xed\xb9\x8d\x9c\x6d\x87\x6e\xee\x91\x75\x93\x8e\xd7\x1c\xfd\x3e\x9d\xaf\x06\xb7\xea\x02\x00\xbc\x5b\x17\x40\x34\x1b\x76\x01\x06\xdc\xb3\x9b\x09\x99\xb7\xed\xa6\x5e\x58\x76\xee\x78\x51\x19\xb3\x79\xe7\x01\xf5\xfb\x77\x01\xca\xb0\x85\x17\xe0\x4c\xbb\x78\x01\x50\xbf\x91\x1f\x41\x77\xc4\x5e\xde\xda\xc7\x31\xdb\x79\xbc\xca\xd8\x77\xf4\x3c\x98\x76\x53\x2f\x00\xe9\xf7\xf5\x02\x98\x61\x6b\x2f\xc0\x69\x77\xf7\x76\xa2\xf6\x0d\xbe\xad\x77\x23\xf6\xf8\x78\xd9\xb1\x6d\xf3\x79\x20\xdd\x4e\x5f\x80\xd1\x6e\xf6\x05\x28\xfd\x7e\x5f\x00\xd3\x6d\xf9\xad\x14\xad\xbb\x7e\x4b\xbf\xec\x1b\x7f\xbc\xde\x8c\xd9\xfb\xf3\x80\xfa\xed\xbf\x00\x65\x88\x00\x08\x70\xa6\x20\x80\x00\xa8\x8f\x03\x8c\xa0\x3b\x22\x14\x60\xed\xe3\x98\x68\x00\x5e\x88\x6c\x01\x01\x1e\x48\x17\x13\x10\x60\xb4\x61\x01\x01\x4a\x1f\x19\x10\xc0\x74\xc1\x01\x2b\x45\x6b\x7c\xc0\xd2\x2f\x7b\x88\xa0\xb6\x46\x09\x44\x08\x5d\xa0\x40\x82\xd2\xc6\x0a\x24\x38\x7d\xb8\x40\x02\xd4\x45\x0c\x46\xd0\xb5\x05\x0d\xac\x1d\x34\xc7\x0d\x0c\xe7\x75\x32\x37\x8b\x4d\x81\x03\xae\x16\x0c\x1c\xf0\xf5\x70\xe0\x80\x87\xd0\x04\x0e\x78\x10\x30\x70\x60\xa4\x62\x0c\x1c\x18\xf8\x37\x07\x0e\xb2\x78\x5c\xe0\x80\x83\xd3\x07\x0e\x78\x20\x43\xe0\x80\x07\x33\x05\x0e\x78\x38\x7d\xe0\xc0\x4e\xd4\x1e\x38\xb0\xf5\x6e\x44\xe0\x20\x8b\xc7\x04\x0e\x38\x28\x6d\xe0\x80\x87\xd1\x07\x0e\x78\x28\x43\xe0\x80\x07\xd3\x06\x0e\xac\x14\xad\x81\x03\x4b\xbf\xec\x81\x83\x2c\xb6\x07\x0e\x38\x18\x5d\xe0\x80\x07\xd1\x06\x0e\x78\x20\x7d\xe0\x80\x87\xd2\x05\x0e\x6c\xe4\x6c\x81\x03\x73\x8f\xac\x81\x83\x2c\x1e\x17\x38\xe0\xe0\xf4\x81\x03\x1e\xc8\x10\x38\xe0\xc1\x4c\x81\x03\x1e\x4e\x1f\x38\xb0\x13\xb5\x07\x0e\x6c\xbd\x1b\x11\x38\xc8\x62\x7b\xe0\x80\x83\xd1\x05\x0e\x78\x10\x6d\xe0\x80\x07\xd2\x07\x0e\x78\x28\x5d\xe0\xc0\x46\xce\x16\x38\x30\xf7\xc8\x1a\x38\xc0\x6b\x8e\x3e\x70\xc0\x57\x83\x81\x03\x01\x00\x0e\x1c\x08\x20\x9a\xc0\x81\x00\x03\x06\x0e\xcc\x84\xcc\x81\x03\x53\x2f\x2c\x81\x03\xbc\xa8\x8c\x09\x1c\xf0\x80\xfa\xc0\x81\x00\x65\x08\x1c\x08\x70\xa6\xc0\x81\x00\xa8\x0f\x1c\x8c\xa0\x3b\x22\x70\x60\xed\xe3\x98\xc0\x01\x5e\x65\xec\x81\x03\x1e\x4c\x1b\x38\x10\x80\xf4\x81\x03\x01\xcc\x10\x38\x10\xe0\xb4\x81\x03\x3b\x51\x7b\xe0\xc0\xd6\xbb\x11\x81\x03\xbc\xec\xd8\x02\x07\x3c\x90\x2e\x70\x20\xc0\x68\x03\x07\x02\x94\x3e\x70\x20\x80\xe9\x02\x07\x56\x8a\xd6\xc0\x81\xa5\x5f\xf6\xc0\x01\x5e\x6f\xc6\x04\x0e\x78\x40\x7d\xe0\x40\x80\x32\x04\x0e\x04\x38\x53\xe0\x40\x00\xd4\x07\x0e\x46\xd0\x1d\x11\x38\xb0\xf6\x71\x4c\xe0\x00\x2f\x44\xb6\xc0\x01\x0f\xa4\x0b\x1c\x08\x30\xda\xc0\x81\x00\xa5\x0f\x1c\x08\x60\xba\xc0\x81\x95\xa2\x35\x70\x60\xe9\x97\x3d\x70\xc0\xb2\x86\xeb\x03\x07\x22\x84\x2e\x70\x20\x41\x69\x03\x07\x12\x9c\x3e\x70\x20\x01\xea\x02\x07\x23\xe8\xda\x02\x07\xd6\x0e\x5e\x1d\x38\x60\x1f\xd8\x64\x6e\x7a\x30\x05\x0e\xb8\x5a\x30\x70\xc0\xd7\xc3\x81\x03\x1e\x42\x13\x38\xe0\x41\xc0\xc0\x81\x91\x8a\x31\x70\x60\xe0\xdf\x1c\x38\x48\x0f\xe3\x02\x07\x1c\x9c\x3e\x70\xc0\x03\x19\x02\x07\x3c\x98\x29\x70\xc0\xc3\xe9\x03\x07\x76\xa2\xf6\xc0\x81\xad\x77\x23\x02\x07\xe9\x61\x4c\xe0\x80\x83\xd2\x06\x0e\x78\x18\x7d\xe0\x80\x87\x32\x04\x0e\x78\x30\x6d\xe0\xc0\x4a\xd1\x1a\x38\xb0\xf4\xcb\x1e\x38\x48\x0f\xf6\xc0\x01\x07\xa3\x0b\x1c\xf0\x20\xda\xc0\x01\x0f\xa4\x0f\x1c\xf0\x50\xba\xc0\x81\x8d\x9c\x2d\x70\x60\xee\x91\x35\x70\x90\x1e\xc6\x05\x0e\x38\x38\x7d\xe0\x80\x07\x32\x04\x0e\x78\x30\x53\xe0\x80\x87\xd3\x07\x0e\xec\x44\xed\x81\x03\x5b\xef\x46\x04\x0e\xd2\x83\x3d\x70\xc0\xc1\xe8\x02\x07\x3c\x88\x36\x70\xc0\x03\xe9\x03\x07\x3c\x94\x2e\x70\x60\x23\x67\x0b\x1c\x98\x7b\x64\x0d\x1c\xe0\x35\x47\x1f\x38\xe0\xab\xc1\xc0\x81\x00\x00\x07\x0e\x04\x10\x4d\xe0\x40\x80\x01\x03\x07\x66\x42\xe6\xc0\x81\xa9\x17\x96\xc0\x01\x5e\x54\xc6\x04\x0e\x78\x40\x7d\xe0\x40\x80\x32\x04\x0e\x04\x38\x53\xe0\x40\x00\xd4\x07\x0e\x46\xd0\x1d\x11\x38\xb0\xf6\x71\x4c\xe0\x00\xaf\x32\xf6\xc0\x01\x0f\xa6\x0d\x1c\x08\x40\xfa\xc0\x81\x00\x66\x08\x1c\x08\x70\xda\xc0\x81\x9d\xa8\x3d\x70\x60\xeb\xdd\x88\xc0\x01\x5e\x76\x6c\x81\x03\x1e\x48\x17\x38\x10\x60\xb4\x81\x03\x01\x4a\x1f\x38\x10\xc0\x74\x81\x03\x2b\x45\x6b\xe0\xc0\xd2\x2f\x7b\xe0\x00\xaf\x37\x63\x02\x07\x3c\xa0\x3e\x70\x20\x40\x19\x02\x07\x02\x9c\x29\x70\x20\x00\xea\x03\x07\x23\xe8\x8e\x08\x1c\x58\xfb\x38\x26\x70\x80\x17\x22\x5b\xe0\x80\x07\xd2\x05\x0e\x04\x18\x6d\xe0\x40\x80\xd2\x07\x0e\x04\x30\x5d\xe0\xc0\x4a\xd1\x1a\x38\xb0\xf4\xcb\x1e\x38\x60\x29\x9c\xf5\x81\x03\x11\x42\x17\x38\x90\xa0\xb4\x81\x03\x09\x4e\x1f\x38\x90\x00\x75\x81\x83\x11\x74\x6d\x81\x03\x6b\x07\xaf\x0e\x1c\xf4\x19\x31\x32\xb7\x4d\x4d\x91\x03\xae\x16\x8c\x1c\xf0\xf5\x70\xe4\x80\x87\xd0\x44\x0e\x5a\xdb\x17\xfe\x46\x2a\xc6\xc8\x81\x81\x7f\x73\xe4\xa0\x4d\xc7\x45\x0e\x38\x38\x7d\xe4\x80\x07\x32\x44\x0e\x78\x30\x53\xe4\xa0\x1d\xf5\xd9\xbf\x9d\xa8\x3d\x72\x60\xeb\xdd\x88\xc8\x41\x9b\x8e\x89\x1c\x70\x50\xda\xc8\x01\x0f\xa3\x8f\x1c\xf0\x50\x86\xc8\x41\x3b\x26\x17\x80\x95\xa2\x35\x72\x60\xe9\x97\x3d\x72\xd0\xa6\xf6\xc8\x01\x07\xa3\x8b\x1c\xf0\x20\xda\xc8\x01\x0f\xa4\x8f\x1c\xb4\x23\x12\x04\xd8\xc8\xd9\x22\x07\xe6\x1e\x59\x23\x07\x6d\x3a\x2e\x72\xc0\xc1\xe9\x23\x07\x3c\x90\x21\x72\xc0\x83\x99\x22\x07\xed\xa8\xac\x01\x76\xa2\xf6\xc8\x81\xad\x77\x23\x22\x07\x6d\x6a\x8f\x1c\x70\x30\xba\xc8\x01\x0f\xa2\x8d\x1c\xf0\x40\xfa\xc8\x41\x3b\x22\x95\x80\x8d\x9c\x2d\x72\x60\xee\x91\x35\x72\xd0\xa6\xc6\xc8\x01\x5f\x0d\x46\x0e\x04\x00\x38\x72\x20\x80\x68\x22\x07\xad\x35\xbf\x80\x99\x90\x39\x72\x60\xea\x85\x25\x72\xd0\xa6\x23\x23\x07\x3c\xa0\x3e\x72\x20\x40\x19\x22\x07\x02\x9c\x29\x72\xd0\x8e\x4b\x3a\x30\x82\xee\x88\xc8\x81\xb5\x8f\x63\x22\x07\x6d\x3a\x2a\x72\xc0\x83\x69\x23\x07\x02\x90\x3e\x72\x20\x80\x19\x22\x07\xed\xa8\x4c\x04\x76\xa2\xf6\xc8\x81\xad\x77\x23\x22\x07\x6d\x3a\x22\x72\xc0\x03\xe9\x22\x07\x02\x8c\x36\x72\x20\x40\xe9\x23\x07\xed\x98\xf4\x04\x56\x8a\xd6\xc8\x81\xa5\x5f\xf6\xc8\x41\x9b\x8e\x8c\x1c\xf0\x80\xfa\xc8\x81\x00\x65\x88\x1c\x08\x70\xa6\xc8\x41\x3b\x2e\x67\xc1\x08\xba\x23\x22\x07\xd6\x3e\x8e\x89\x1c\xb4\xe9\x88\xc8\x01\x0f\xa4\x8b\x1c\x08\x30\xda\xc8\x81\x00\xa5\x8f\x1c\xb4\x63\x12\x19\x58\x29\x5a\x23\x07\x96\x7e\xd9\x23\x07\x6d\x6a\x8b\x1c\x88\x10\xba\xc8\x81\x04\xa5\x8d\x1c\x48\x70\xfa\xc8\x41\x3b\x2e\xbb\xc1\x08\xba\xb6\xc8\x81\xb5\x83\x96\xc8\x81\xd7\xa0\xb6\x4f\xb5\x7f\xc6\x3f\x48\x46\x56\x25\x13\x34\x05\xa5\x57\x69\x3c\x1c\x93\x06\xb9\x38\xf5\x32\x70\x15\x06\x86\x6c\xaa\x53\x1e\x85\x0d\x3a\xcb\xb9\x21\x71\x6d\x5f\x88\xd2\x34\x29\xeb\xa4\xde\xaa\x28\x29\xa2\xae\xef\x3c\x6b\xa9\x94\xd0\x13\x57\x61\xe1\xf1\x50\xb8\x40\x01\xa3\x09\x7f\x39\x38\x25\x07\xaf\x3e\xef\x03\x6e\xc5\xb2\xbe\xda\x18\xea\x33\xbf\x5a\x79\xaa\xb3\x31\x6c\x19\x3e\x2b\xc1\xcd\x58\x16\x58\x1b\x5f\x7d\x26\x58\x2b\x5f\xc3\xc5\xf3\x57\xf2\xc5\x4e\xad\x90\xd1\x3b\x8c\xe3\xab\xcf\x0c\x6b\xe5\x6b\xb8\x64\xec\x4a\xbe\xfa\xa0\x18\x6e\xc7\xb2\xc4\xda\x18\xeb\x33\xc5\x5a\x19\x1b\x12\x4a\x1b\x19\xa3\xbd\x28\x1e\x50\x15\x85\x35\x3a\xd3\xd9\x12\xe6\xf5\xbe\xa8\xb2\x4d\x5f\xa1\xe0\x3f\x95\x25\xdc\xa4\xaf\x50\xf5\x3d\x2c\x93\x26\x4c\x93\xdf\x94\x36\x43\x0d\xdf\x68\x5f\xe4\x8d\xfb\x80\xb3\x83\xba\xe4\xaa\xa7\x33\x57\xb4\x99\xfb\xbe\x08\xb3\x2b\xd2\x58\x80\x58\xf5\x10\x18\x7b\x44\x2a\xeb\xe6\x31\x45\x1b\x52\x42\x39\xc3\xd3\xfd\x1c\x15\x69\x51\x6d\xfe\xb4\xdf\xef\x55\xf5\x3b\x35\x28\x66\x00\xcb\xd9\x32\x5a\x05\x1c\x4c\xc8\x01\x91\x24\xb1\x13\xa1\xe8\xd8\x19\x18\xd6\x7a\xbe\x5b\x04\x8b\x95\x42\xa1\xac\x92\x2c\xac\x1e\x19\x94\x1f\xac\x16\xf1\x9d\x4a\x83\x82\x89\x54\x58\xa1\x40\xc7\x0f\x16\x61\xb8\x50\x27\xf8\x29\x8a\x50\x5d\x33\xa8\x45\xb4\xbb\x5b\x44\x2a\x1d\x0a\x26\xd2\x61\x85\x62\x7f\xe6\xeb\x78\x3e\x57\xe8\x24\xf9\xbe\xe8\x89\xec\x22\x3f\x46\x2a\x91\x0e\x46\xa4\x80\x4b\x04\xf4\xb3\xe9\xce\x8f\xd5\x6e\x3c\x84\x55\x9e\xe4\x87\x7e\xcc\xfc\x30\x9e\x03\x14\x28\x98\x48\x84\x15\x0a\x74\x50\xb4\x5e\x4d\xd5\x81\x8f\xc3\xfc\x30\x00\xc5\xeb\xc5\x6c\xbe\x57\xc9\x10\x28\x91\x0a\x2d\x13\x88\x44\xeb\x99\x1f\x44\x0a\x91\x43\x15\x3e\xba\x71\x58\x7d\x61\x70\xc1\x3a\xd8\x05\xc0\xa8\xf4\x80\x22\xa9\xa1\x58\xa0\x36\xf5\xa7\xd3\x69\xa0\x50\x3b\x26\x31\xc2\x33\x61\xe3\x7f\xf2\x9d\x70\x4b\xa0\xf1\x64\x2c\xc3\x0a\xe5\x0d\x59\x14\xeb\x63\x18\x17\x0f\x38\xcf\xf4\x76\x17\x46\x5f\x0e\xf8\x52\x03\x57\x85\x1e\x72\x29\x27\x39\x4d\x71\x7c\xc6\x7f\x93\x34\x69\x1e\xe9\x42\xcb\x73\x41\x4a\xdc\xb6\x76\x4f\xe5\x39\x4e\xea\x32\x0d\x1f\xb5\xf9\xce\xfb\x0c\xc2\x8b\xd5\x02\xdb\xcb\xa1\x75\x5c\x3c\xe4\xba\xf6\x86\x95\x93\x22\xa8\x33\x03\x79\x80\xfe\x6a\xb9\x92\x9a\x5f\x49\x9f\xad\x90\x14\x41\x16\x5f\x47\x7f\xbd\x9e\x4a\xcd\xaf\xa4\xcf\x56\x42\x8a\x20\x3d\x5c\x47\x7f\x3a\x5d\xaf\xa5\xf6\x57\x32\xd0\x2f\x79\x6c\x08\x53\x13\x07\x1c\x94\x89\x8e\x47\x55\xae\x33\x82\x79\xe3\xee\xd2\x22\xfa\x62\x51\x2a\x0c\x79\x36\x36\xc4\xbf\x04\x6e\x44\xe8\x24\xc7\x57\x21\x3c\x81\x8e\xd4\x92\xfc\xb4\x52\x7a\x7a\xbf\xc0\xf6\x7c\x21\x30\x66\x14\x11\x1d\x00\xf2\x4b\x37\x4c\x9f\xbe\xff\x93\x53\x17\xa7\x2a\x42\xbf\x84\x65\x99\xe4\x87\xff\xfe\xcf\x9f\x7f\xdc\x15\x45\x53\x37\x55\x58\x7a\x59\x92\x7b\x51\x5d\x7b\x59\x58\x3a\xdf\x7f\xfa\xff\x03\x00\x00\xff\xff\xae\xba\xa2\x3e\xd4\x4d\x02\x00")
+
+func uiAppLibBootstrap400Alpha6DistCssBootstrapMinCssBytes() ([]byte, error) {
+ return bindataRead(
+ _uiAppLibBootstrap400Alpha6DistCssBootstrapMinCss,
+ "ui/app/lib/bootstrap-4.0.0-alpha.6-dist/css/bootstrap.min.css",
+ )
+}
+
+func uiAppLibBootstrap400Alpha6DistCssBootstrapMinCss() (*asset, error) {
+ bytes, err := uiAppLibBootstrap400Alpha6DistCssBootstrapMinCssBytes()
+ if err != nil {
+ return nil, err
+ }
+
+ info := bindataFileInfo{name: "ui/app/lib/bootstrap-4.0.0-alpha.6-dist/css/bootstrap.min.css", size: 150996, mode: os.FileMode(420), modTime: time.Unix(1, 0)}
+ a := &asset{bytes: bytes, info: info}
+ return a, nil
+}
+
+var _uiAppLibBootstrap400Alpha6DistCssBootstrapMinCssMap = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\x6b\x57\xdb\x3a\xd3\xe8\x7f\xe9\x57\xbc\x37\xe1\x5a\xfa\x9c\x4f\x92\x2c\x1b\xdb\x38\xc1\x75\xd3\xec\xf4\xac\x77\x75\xb9\xc1\x75\x4c\x6e\x24\x21\x84\x70\xd6\xf9\xef\xef\xd2\x5d\x96\xe5\x10\x28\xdd\xed\xde\x4f\xf8\x10\x6c\x69\x74\x1b\x8d\x66\x46\xd2\xcc\xf8\xff\xbd\x7b\xc8\x17\xcb\x72\x36\x7d\xf7\x9f\x13\xe7\xdd\x72\xb6\x5a\x0c\xf2\xe5\xbb\xff\xfc\xdf\x77\x7f\xfe\x79\xf8\xe7\x9f\x87\xcb\xc1\x72\x79\xf8\x75\x3a\x5b\x4c\xb2\x71\xf9\x94\xff\x49\xde\xdf\x39\xef\xbe\xcd\x66\xf7\xcb\xfb\x45\x76\xf7\x27\x7b\xd7\x81\xef\x16\xe5\xf4\x5e\x00\xea\x19\x8b\x9c\x14\xb3\xe5\x3c\x64\x8b\x32\xfb\x36\xce\x97\x96\xcc\x49\xf9\x58\x4e\x97\x87\x5f\x87\xb3\x87\x7c\x61\x2b\x7c\xbf\xb9\xcb\xb7\x94\x1b\x97\xcb\x7b\x5b\xbd\x5f\xcb\x49\x56\x6c\x6d\x91\x02\x6c\xc9\xff\x36\x5b\xdc\xe4\x8b\x3f\x16\xd9\x4d\xb9\xb2\xb6\xc0\x00\x6d\x39\x83\xd9\x8d\xad\xe6\xaf\xc5\xa2\xbc\xd9\xd2\xe2\x33\xd9\xdf\x16\x79\x36\xba\x9b\x95\x53\xeb\x80\xf5\x4a\xfe\xf8\xbe\xc8\x26\xf9\x7a\xb6\x18\x59\x31\xfa\xdc\x5c\x50\x80\x3f\x16\xb3\xb5\xad\xf4\xf7\xd9\x62\xb2\xad\x70\x53\xfe\xd7\x6f\xab\xfb\xfb\x99\x15\x5f\x72\x80\x8d\x10\x5f\xef\x17\xd9\x74\x59\xde\x97\x0d\xd9\x37\x8b\xd9\xdd\xcd\x6c\x3d\xdd\x52\xf9\x34\x7b\xf8\xe3\xa6\x7c\x28\x6f\xec\x64\xc6\xda\xfe\xa3\x58\xcc\x56\x77\x56\x72\x9a\xde\xad\xee\x9b\xb3\x07\xab\xe5\xfd\x6c\xf2\x47\xe3\xe0\xa7\xd9\x43\x43\xf2\xb7\xcc\xda\x9f\x41\xb6\xd8\x46\x0b\x24\xdb\x8e\xe5\x45\x9e\xdd\x0c\x16\xab\xc9\xb7\x6d\xa5\xc7\x79\xb6\xf8\x5e\x3e\xda\x2a\xb8\xcb\x8a\x72\x9a\x11\x4c\x6f\xa9\x60\x2b\xd0\xd7\x6f\xd9\xcd\xf6\x95\xd5\x90\xff\xf5\x76\x35\xf9\x36\xbb\x5f\xd8\x6b\xcd\xc6\xf9\xc2\xc6\x5e\x44\xad\x4d\xf9\x5f\xef\x16\xb3\x62\x91\x2f\xb7\x2f\x9a\xec\xa6\xcc\xed\x0b\xeb\xeb\x24\xbf\x29\x33\x5b\x06\xe1\x3d\x8d\x24\xa1\x33\xa8\x66\xba\x59\xe4\xcb\xbb\xd9\x74\x59\x3e\xe4\x7f\xe4\x93\x6f\xb9\x6d\xca\xbf\x0e\xc6\xb3\xa5\x15\x5d\x93\xd9\x4d\x36\xb6\xae\x96\xd9\x6c\x7c\x5f\x6e\xeb\xd5\x22\x5f\xe6\xf7\x7f\xdc\xe7\x8f\x76\x8c\xcd\xee\x9a\xd8\xf1\x20\x5b\xcc\x56\xcb\xdc\xd6\xac\x64\x1f\x64\xad\x36\xad\x84\xd5\x7d\x39\x2e\xef\xcb\x9c\x4e\x58\x59\xd8\x66\x5a\x03\xf9\x96\x0d\x46\x04\x77\xd3\xad\x7c\x51\x02\xfd\x41\x25\x8d\x55\x3c\xe9\x95\x52\xc6\xfe\x4c\xe7\x6e\xca\xe5\xdd\x38\xdb\x6c\x07\xfa\x3e\xce\x6d\x6b\xa8\x02\x31\xcb\xb6\x11\x6d\x53\xbe\x56\xc5\xdd\x8c\x31\xbe\xed\x50\xcb\xc1\x22\xcf\xa7\x64\xf1\xdb\x87\x26\x1a\x64\x70\x7f\x30\xc0\x67\xaa\x2c\x9f\xca\x69\xf1\x0c\xcc\x5d\x36\x78\x16\xa8\x81\xcc\x24\xbd\xe4\x8f\xf7\x7f\xdc\x2f\x56\xd3\x41\x76\xbf\x8d\x6d\x50\xb8\x7c\x72\x37\xcc\x96\xe5\x56\xf1\x45\xe0\x86\xa5\x55\x04\x6b\xbd\x7a\x28\x97\xe5\x37\xf2\x66\x9b\x64\x51\x97\x09\xf4\x3f\xce\xbb\x69\x36\xa1\x2a\xd4\xff\x38\xef\x26\xd9\xdd\x5d\x39\x2d\x96\xef\xfe\xf3\xee\xff\x90\xbf\x53\x0c\xfa\xc0\x89\x00\xc2\x4e\x1f\x00\xe0\xf4\x00\x02\xec\x29\x22\x4f\x73\x28\x1f\x37\xfc\xb1\xeb\x31\xf0\x0e\x79\xc5\xa0\xe3\x39\x09\x79\x8a\xc9\x4f\x47\xfe\x04\xe4\x27\x01\x31\x16\xb9\x89\xe7\xf8\xa4\x58\x97\xe5\x22\x0e\x17\xb3\x5a\x7a\x9e\xd3\x93\x65\x23\xe0\xcb\x62\x1d\xcf\xe9\xc8\xd6\x02\x96\x2b\xaa\x9a\xd0\x1e\xf1\x6e\xd3\x27\x51\x2b\x26\x4f\x29\xeb\x42\xe2\x91\xe6\xf8\xf0\xba\xec\x07\x01\xd1\x8f\x9e\x47\x80\xb1\x53\x42\x59\xc3\x39\x94\x05\x79\x15\x18\x3b\x03\x56\x6d\xe2\x11\x18\xfe\x4a\xd1\x52\x40\x59\xa5\x78\xa4\xe3\xe8\x90\x8a\xe9\x13\xe6\x6d\x27\x96\xb4\x0e\xa9\x31\xd2\xc6\xe6\x37\x75\xb4\xc3\x87\xd1\x93\xd5\x47\xaa\xdf\xb4\x27\x31\x7b\xea\x78\x4e\xac\x21\x9a\x0e\x9f\x3e\x61\x1d\xf9\xfd\x2a\x9a\x52\xf2\x94\xb3\x27\x9f\xb7\xc4\x27\x53\xbc\x06\x6c\x42\xba\x1e\x6b\x28\x26\xf5\xd1\x49\xca\x48\x93\x4b\x48\x60\x12\xd9\x19\x45\x1d\xb4\x70\x26\xfb\x96\x93\xd7\x94\x55\xdd\xf3\x34\x22\x48\xe5\xfc\xa7\x20\xd2\xa9\xb1\x2b\x2b\xed\x9b\xd5\x27\xb2\x02\x8c\xb5\xf9\xee\x48\x24\xe7\xac\x44\xea\xb1\x1e\x0c\x64\x1b\x13\x08\x02\x41\x41\x14\x9b\x05\x22\x8f\x07\x34\x81\x3d\x6f\x28\x48\x26\xdb\x4c\xe4\x90\x18\x85\x9c\xd2\x5f\xf6\xbc\xa4\xb0\x89\x9c\xc8\x0e\xeb\x7d\x87\x90\x50\x85\x7a\xf9\x32\x51\x43\x10\x13\x62\x2c\x22\x8a\xe8\x8e\xa2\xf2\x9e\xf6\x23\xe6\x3a\xd1\xca\x55\xf0\x94\xc8\xc9\x55\x44\x96\xca\xf9\xc9\xb4\xb9\x16\x1d\xa4\xb8\x8b\xd0\x61\xe8\x71\x2a\xce\xdc\x4d\xd4\xd0\x36\xab\x1d\xdd\x45\x9e\xb3\x61\x88\x42\xee\x79\xc4\x07\x19\xa1\xc7\xc8\x73\x06\x6e\x79\x25\x4a\x77\x65\x73\x11\x7a\x1f\x79\xce\xa9\x28\xb3\x94\x20\x74\x49\x9f\x43\x35\x5a\x8a\xa0\x88\x8d\xb1\xe7\x09\xb2\xc2\x3a\x57\x48\xe4\x78\xba\x12\x55\x8a\x1c\xd5\x68\x23\xf4\x3e\xf6\x9c\xd4\x5d\xb7\x45\x02\x1e\x0e\x28\x12\x30\xc3\x7e\x22\x89\x8f\x71\xb8\x15\xfd\x1d\x31\x42\xa0\xbf\x6c\x8d\xe5\x2a\x61\x00\x06\x9c\x40\x73\x80\x01\xef\x73\x2e\xb1\x94\x93\x35\x83\x59\xd7\x30\x96\x6c\x21\xf1\x08\x24\xeb\xd7\x39\x24\xc3\x7b\x0f\x49\x2d\xe7\xd0\x09\xc0\xe0\x10\x6a\x6c\x6a\x02\x01\xe6\x1c\x91\xae\x5b\x83\x7e\xe8\x24\xb3\x1e\x52\xc6\x1a\xcb\xd1\x4e\x20\x5b\xaf\x00\x38\x3e\x29\x28\x80\x7c\xc2\x32\x69\x22\xa5\x0c\xc1\x5f\xb1\x46\x88\x0a\x04\x0b\xb6\x12\x83\x58\x47\x74\x44\x3a\xd5\xb1\xd0\x73\x44\x0a\xd3\x0c\x36\xd6\x09\x04\xae\x27\x58\x58\x14\x48\x04\xfa\x21\xc7\x15\xe9\x66\x60\xd6\x52\x40\x74\xe2\x7d\x64\x6c\xad\x4e\x78\x02\xa5\x7c\xba\x7c\x01\x93\x48\x98\x04\xcc\x20\x5d\xe2\x05\x64\x15\x66\x20\x19\x13\x3c\xf7\x15\x29\xfa\x62\xd9\xf6\x49\x85\x4a\xec\x0d\x80\xe0\xb9\x5a\xcb\x1d\x74\x1c\x9d\x5e\x3a\x25\x74\x4f\xa2\xb3\x4b\x56\xa7\x8d\x23\x05\xda\x13\x96\x6b\x13\x0b\xc2\x89\xbc\x49\x42\x18\x24\x3e\xba\xe6\x88\xec\x83\x3e\x45\x76\xd0\xf0\x83\xc6\x90\xf5\x80\xce\xcf\x40\xd2\x3c\x96\x02\x40\x65\x44\x20\xf0\x9c\x96\x18\x13\x96\x12\x94\x4f\x9c\x12\x54\x3d\xb9\xb0\xb8\x34\xaa\xd0\x84\x4f\xca\xd6\xaa\xf6\x25\xb3\x57\x3f\x81\x14\x86\x3e\x97\xc3\x7c\xe8\xe2\x75\x20\x39\x52\x5f\xc2\xf5\x34\x8d\x41\xfc\xd0\x55\x4f\x87\xa4\xb8\x19\xa3\x9f\x08\x0f\x43\x8e\xaa\xc4\x9b\x84\xa0\x06\xd0\x05\xdd\xd0\xb9\x80\x0d\x65\x23\xec\xcc\x28\x93\x99\x21\x6f\x12\xd5\x4b\x47\xa0\x1d\x12\x88\x6e\x20\x56\x41\x1a\xb2\x75\xc6\x11\x80\x25\x02\x30\x67\x0d\x11\x13\x2b\xbe\x7d\x10\x01\xc9\xa0\xeb\xbf\xe3\x5d\xc4\x9e\x33\xc0\xb7\x31\x87\x4c\xc0\xc0\x13\xf8\x02\x9c\xa7\x75\xaa\x28\xed\x68\x64\x9d\x8a\xa5\x97\x69\x3f\x74\x85\x4b\x46\x92\x2a\xca\xea\xcb\x69\xee\xcb\xc9\xcd\xe5\x93\x1a\x76\x4f\x12\x41\x06\x84\x4c\xf7\xe5\x78\x23\xd9\x80\x12\x0f\x8a\xe6\x32\xb9\xfc\x03\x59\xb3\x7a\xa5\xe3\xd9\x40\xb6\xfe\x2b\x03\x4a\x89\xee\xa7\x28\xed\x82\x76\xf8\x18\x82\x98\xaf\xfb\x3e\x88\x42\x3e\x8c\x52\xe4\x31\xbe\x9b\xaa\xa5\xed\x13\x4e\x2e\xf8\x5f\xca\x5e\x63\xae\xc6\xd0\x69\xaa\x71\xb1\x0a\x3f\xeb\x68\x22\x03\xe9\xbc\x33\x31\x17\x17\x92\x7a\x5b\x65\x7d\x4c\x20\x88\x94\x90\x0a\x2a\x62\xc6\xbb\x08\x3c\x27\xc5\xf7\x42\xee\xe7\xfe\xe1\x5f\x94\xf5\x46\x4d\x3f\x4f\x70\xdb\xa2\xc7\x63\x68\x2e\x9d\xc4\xca\x62\xd4\xd4\xfa\x54\x2b\x0b\x49\x0d\x5d\xd9\xff\xb6\x99\x16\x59\xd2\x12\x4b\x9a\xad\xac\x0d\x2e\x02\xf8\xb3\xa6\x62\xea\x9d\x0c\xf8\x4a\xdf\xc6\x20\x75\x90\xce\x4f\x04\x11\xbb\x04\x45\xfc\x8a\x17\x2a\x62\xe9\x81\x8a\x0c\xca\xab\x2a\x65\xd7\xac\x54\x30\x44\xa5\x8c\xd0\xfa\x4a\xb5\x65\xc8\xd1\x7b\xcc\xb5\x46\xd5\x40\xe4\x96\x9e\xe7\x64\x68\xec\x59\xb2\x66\x9e\x47\xc8\x5e\xe9\x2f\xae\xe7\x4c\x10\x08\x02\x06\x1a\x10\x5e\xd7\xaf\x6e\x9d\x72\xc6\x04\x03\xbe\x1b\x51\xba\xa3\x31\x4e\x63\x82\xd4\x12\x15\xd4\x8d\xb0\xa9\x40\xea\xf4\x75\xe9\xf1\x15\x9b\x00\xb0\x24\xd4\x19\x1d\x41\x67\x06\xab\x72\xc5\x18\x4f\xac\xb1\x19\xa0\x33\x21\x25\x0c\x0e\x10\xc0\xb4\xce\x9e\xe3\x03\xef\xbb\x73\x81\x88\x92\xc0\xdb\xc0\x8b\xe0\x08\x3a\x3d\x14\x48\x2a\xf2\xc5\xb6\xd0\x75\xf9\xf6\x21\x91\xb3\xae\x6d\x7f\x4c\x9d\x04\x7f\xe1\xbd\xec\xa0\x9e\x58\xc3\x81\xfc\x51\x52\xdf\x48\xeb\x19\x69\x5e\x18\xd6\x3b\x92\x7b\x6c\x57\xc8\x27\xcc\xd7\x77\x85\x86\xe4\x2b\x60\x75\xea\x18\x42\x82\x47\xa4\xef\xfb\x38\x2f\x0d\x38\xc7\xd4\xb9\x28\xe5\x89\x1f\x27\xd7\xc7\x9e\x33\x48\xa6\xd7\x27\x1e\x9b\xf7\xa8\x3a\xef\xf6\xf9\x53\x94\xe9\x7d\x12\xc8\xc0\x99\xce\xc5\xb0\x15\x9a\xb0\xe6\xe0\xf9\x06\x74\xd2\xf7\x9e\xa0\x18\x3f\x9e\xc3\xd0\x49\x40\x1a\x68\x4d\xd4\x18\x42\x5c\x6d\x41\x50\x0f\xb6\xd0\xaf\x3e\xa2\x2b\x22\x01\xea\x35\x27\xb6\x61\xf4\x65\x5d\x98\x0c\x88\x4d\x44\xaf\xda\x5e\x07\x3d\xb9\xc0\xe9\x21\xa0\xef\x83\xfb\x55\xda\x8e\x08\x75\x1a\xf4\x1e\xa1\x63\xe4\x39\x1b\xe8\x4d\x5d\xcf\xe9\xa1\x4e\x0d\x20\x7e\x23\x80\xd6\xce\x35\x8c\x60\x60\x4e\x55\x8c\x8a\x37\x82\x68\xd5\x20\x3a\x0a\xc2\xbd\x26\x92\x1c\x7d\x79\x2d\x0e\x1f\x90\x47\xca\x5f\x35\x8f\xf0\x87\x21\x5a\xdb\x20\xdc\x41\xe8\x44\x28\x03\x42\x39\x17\xea\x58\x26\x9f\x54\x9a\xb6\xf5\x8a\x24\x0b\x89\x00\x90\x24\x1e\x71\xb6\xad\xd8\x40\x8c\x52\xda\xc5\xf7\xd0\x73\x22\x34\x81\x35\x80\xce\xdb\x00\xb4\xb6\x01\xb8\x37\x5c\x88\x28\x76\xcd\x79\x94\xe7\xf1\xf5\xd2\xa2\xac\x7e\x20\xf3\x19\xa4\x7f\x8b\x42\x4d\x6d\x4d\xaa\x3f\x9d\x1d\x7f\x12\x89\xa1\x5e\xf5\xa7\xbb\xe3\xcf\x3f\xbd\x02\x71\xc6\x92\x56\xb9\x27\x93\x36\xde\x0a\xd6\x24\x6a\x84\x96\x90\x4c\x3a\xba\x75\xbd\x3d\xfe\x7f\xb4\x02\xaf\x05\x2d\x9c\x61\x8f\xe1\x3d\x86\xff\x39\x15\x34\x63\xb8\xb5\xc7\xf0\xcf\xc3\x30\x0e\x81\x7e\x26\x49\x8f\x71\xd6\xea\x51\xa9\xad\xa5\x4a\x1c\x59\x1f\xbb\xc0\x50\x87\xb1\xc7\x24\x83\x56\x32\x03\xc6\xf1\x92\xd0\x4c\x8d\xb4\xc8\x4c\x53\x62\x25\x00\x4e\xc7\x3b\x87\xed\x2d\xd5\x76\x2d\xd5\x76\x2d\xd5\x76\x41\x24\x70\x83\xc7\x28\x7e\xb6\xde\x9e\xa5\xde\x9e\xa5\xde\x9e\xac\xb7\xb7\x53\xbd\x81\xa5\xde\xc0\x52\x6f\x20\xeb\x0d\x7e\x69\x7f\xf7\x78\xf8\x3d\xf1\x90\xfc\xa4\xfe\xfe\xaa\x7a\x77\x67\x0f\xa2\xde\x08\x9f\xc0\xc4\x49\xbc\x15\xfa\x28\xce\x49\x1e\x50\x25\xa1\x6b\x26\xf4\xcc\x84\xe0\x59\x88\xb7\x2b\x92\x9a\x10\xdb\x12\xc4\x58\x26\xe8\x23\x47\x03\x9e\x56\x13\xba\x66\x42\xcf\x4c\x08\x9e\x85\x78\xbb\x22\xa9\x09\xb1\x2d\x21\xc2\x47\x30\x71\xba\xde\x12\x7e\xe4\x26\x02\xf8\xbe\x9a\xd0\x33\x13\x82\x67\x21\xde\xae\x48\xcf\x84\xd0\x13\xd0\x03\xc4\x44\x0f\x3c\x82\x98\xdd\x57\xfc\x14\x59\x9a\xfd\x14\x59\xda\xfd\x49\xb2\xf4\xb9\x7a\x5f\xcb\x33\x9e\xab\xf7\xb5\xbc\xf3\x57\xf5\x77\x8f\x87\xdf\x13\x0f\xbd\x9f\xd4\xdf\x5f\x55\xef\x6b\x65\x69\xcf\x94\x3f\x3d\x53\x96\xf6\x4c\x91\xd5\x33\xa5\xdc\x36\x88\xb7\x2b\xd2\x37\x21\xb6\x25\x88\xb1\x18\xb2\xb4\x67\xca\xd2\x9e\x29\xb2\x7a\xa6\x94\xdb\x06\xf1\x76\x45\xfa\x26\xc4\xb6\x04\x26\x4b\x33\x25\xa1\x30\x15\x59\x99\x29\x5c\x33\x53\xa8\x65\xa6\xd8\xdb\x06\xf1\x76\x45\x06\x26\x84\x96\xd0\xdf\x0b\xd7\xbd\x70\xfd\xb7\x08\x95\x3d\x1e\xf6\xc2\x75\x2f\x5c\xf7\xc2\x75\x2f\x5c\xf7\xc2\x75\x2f\x54\xf6\x78\xd8\x0b\xd7\xbd\x70\xdd\x0b\xd7\x7f\xb5\x70\x6d\xed\x85\xeb\x5e\xb8\xfe\xf3\x85\xca\x1e\x0f\x7b\xe1\xba\x17\xae\x7b\xe1\xfa\xdb\x08\x57\xff\x44\x78\x6b\x2a\x73\xd3\xae\x7c\xe2\x56\x4e\x97\xd2\x4d\xb3\x13\x68\x6e\x15\x39\x10\x76\xf7\x3d\x50\xf1\xaa\x48\xc0\x27\x6a\x49\x9f\x05\x9a\xa3\xd9\xc0\x84\xb9\xa1\x7e\x9e\x23\x18\xd4\x8b\x8f\x61\xe8\x0c\xc0\x12\x06\xd2\x75\x23\x0d\x85\x9f\x9b\x1f\x08\x77\x80\x54\x98\xeb\x77\xcc\xf2\xae\xa7\x5c\x48\xa3\x9a\x0b\x69\x02\xae\x42\xee\xc6\xbb\x81\xa0\x17\x3b\x33\xee\xf6\xd1\x6d\x3b\x1b\xea\x75\xc2\x5a\x2d\x20\x69\xe2\x14\x02\x3f\x96\x3e\x68\xe8\x3d\x0e\xd9\x50\xa4\x57\x5a\x10\xa8\xe7\x38\x74\x4a\x04\x22\x05\x0f\xae\xda\xd2\xcd\x10\xa4\x89\x4a\x9f\xc2\x8f\x0c\x39\x23\xe1\xd1\x26\xeb\x49\x48\x35\x23\xad\x9a\x84\xd4\x32\xa7\xb5\xcc\xb5\x5a\x12\x5a\x09\xf7\x30\xa6\x3f\xd5\x2a\x0e\xa0\x51\xc5\x88\x56\x31\xaa\x55\xf1\x26\xfd\x68\x40\x4a\x62\xe2\x24\xb1\xa3\x24\x71\x4b\xef\x33\x69\x1e\x07\x75\xbf\x11\x10\x84\x7a\x56\x62\x64\xe5\x55\xfa\x15\x39\xcc\x63\x4a\x0e\x6d\x0d\x09\xf9\x72\x47\x83\x6b\xea\x19\xda\x0b\x84\x93\x57\x3f\xd4\xbd\xab\x62\x8b\xfd\x35\x7d\x9a\x08\xaa\x09\x3d\x32\xa8\x44\x94\xc7\xc3\x90\x90\x85\xad\xbc\x5f\xf5\xda\x6f\x08\x55\x60\x8e\x2b\xd2\x3c\x83\x49\xea\x9a\x3b\xab\x48\xef\xf2\xbe\xc5\x9b\xa9\xa0\x8e\x88\xcc\x83\xe7\xe3\x27\xa1\x28\x67\xb2\x64\x04\xa4\xeb\xb2\x7a\xef\xed\x00\x33\xb0\xc0\xf4\x9e\xaf\xe6\xe5\x20\x7a\xc3\xc9\xa7\xb6\xd3\x82\xe0\x5c\x72\x01\x2d\x72\x07\x4a\x3d\xee\x62\x56\x47\x1c\x92\x3e\x19\xd2\x87\xd3\x3d\x41\x21\x59\xda\x4b\x14\x68\x8e\xd7\xdc\x3d\xe8\x11\x85\x4e\xb1\x25\x6f\xb6\x25\xef\x18\x36\xe7\xad\x20\x00\x6b\x48\x66\x6e\xe4\xde\x41\x49\x95\x0a\xe8\xce\xa5\x40\x6b\x57\x3a\xbb\x06\xa1\x53\xb8\xd2\xe9\x7d\x06\xc1\x65\x48\x56\x5a\xbf\x4e\xf7\x11\x88\x84\x9b\xfc\x0c\x6a\x0e\xac\x5d\xe1\x4b\x46\x71\xb8\x84\x92\x4f\xb3\x47\xe5\x93\x3d\x51\x50\x2b\x05\xc5\x1e\xb9\x8d\xec\x6e\x50\x5d\xea\x19\x82\xa4\x53\x9a\x00\x8a\xb5\xf6\x14\xd1\xa7\x9e\x33\xdf\x01\xda\x88\xe1\x11\xcb\xe9\xcf\x24\xc5\x63\xd0\x3e\x77\x29\x37\x3a\x64\xff\xe6\xbe\x33\x72\x01\x58\xf8\xce\xca\x25\x00\x2d\x17\x80\x25\xa2\x69\xf7\x48\xa5\x75\xeb\xde\x2b\x20\x63\x4e\xc6\x23\x48\x3d\x90\xc7\xd0\x99\x50\xfe\xb4\x44\x9a\x1f\x61\xc5\xdf\x29\xf9\x74\x16\x0a\x4f\xb6\xb4\x88\x42\x67\x8d\x01\x98\xb9\x4e\x81\x01\xb8\x73\x9d\x39\x55\xf6\x26\x2e\xe1\x58\xb4\x64\x97\x4c\xed\x2e\x4d\x74\xb4\x26\x1e\x23\xd9\xc4\xe9\xf3\x4d\xf4\xa5\x07\xa8\x72\xcb\xef\x59\x9c\xe7\x3a\x32\x3c\x8d\x72\x35\x49\xaa\x53\x10\x13\x89\xbf\x42\xa0\x13\x6b\x74\x27\xfc\xb1\xdb\x9c\x51\xaa\x35\xa6\xd0\xd9\x91\x84\xc3\x60\x54\x0b\x3d\x50\x71\xc1\x4d\x49\x0b\xe7\xd4\x95\x88\x47\x74\x61\xe4\x5c\x71\x6f\x9d\x53\xf7\x56\xae\x41\x84\x21\xc1\x55\x12\x08\x1f\xd5\x94\xae\x1d\x15\xea\xc6\xf7\x78\x18\xa2\xa5\xf8\xf5\x39\x26\x12\xe5\x8c\x45\xa3\x8c\x30\x69\xaf\x87\x94\x91\xfc\x35\x95\x3f\x85\xf6\x8e\xce\xae\x45\x04\x17\xf6\xcb\xe2\xbf\x30\x19\x46\x44\x9b\xe4\x42\x01\x75\x85\x55\xc8\x49\x68\xc4\x98\x0a\x97\xca\x8c\x85\x9c\xb8\xc7\x9d\x90\x7b\xf2\xb2\x94\xf5\x35\xba\x4b\xbc\x9f\xd6\x60\xe4\x4e\xae\xab\x0d\x96\x5d\x74\x96\x78\x3c\xe4\x05\xfb\x65\x8e\xf8\x8c\x44\x0b\xa3\xc1\x96\xd1\xe0\x01\x7c\x76\x84\xd7\x54\x05\x90\x0d\x8e\x52\x30\x08\xb5\x98\x01\x3b\x3b\xd3\xa9\xad\xe5\xa0\xfa\xda\xd5\x5e\x25\xb4\x60\xa2\xe2\x31\x97\x4f\x9c\x86\x2e\x3d\x22\xca\x53\xa1\x70\x84\x47\xd7\x44\xb6\x07\xe5\x35\x65\x7c\x79\xf0\xc2\xde\x3d\xdb\x9e\x44\x09\x4d\x5c\xab\x47\x15\x71\xa8\x80\xa0\xa2\x30\x63\xaa\x0b\x6f\x20\x58\xc1\xdd\xbb\xf3\x46\xc7\x58\x3f\x05\xe7\x6a\x60\x27\x90\xca\xcf\x02\x05\x5a\x48\x09\xa5\x74\xf1\x92\x63\x44\x75\xd0\x95\x82\x7a\x40\x21\xa1\xc1\x63\x24\x15\x45\x22\xdd\x4b\x04\x0e\x90\xce\xda\x79\xf9\xa1\x4b\xd1\xb7\x74\x7f\xf1\x6c\x1a\xda\x24\xd6\x11\xe1\x52\x5d\xfd\xc2\x0d\xc4\x74\x7d\x60\x29\x25\x0e\x4c\x16\xaa\xa4\x56\x47\xf3\xce\xbc\xc3\x21\xe1\x14\x1b\xfc\x8b\x07\xc9\xbb\x7f\x86\x43\x22\x3e\x0e\xb0\xe4\xee\x08\x68\x73\xac\xba\x9f\xb3\x96\xc6\x5e\x48\xc4\xf4\xca\x0b\x78\x50\x22\x7c\xf4\x57\x5b\x73\x5e\xcf\x40\x3d\x74\x83\x2d\x5a\x8d\x11\xda\x64\x06\x25\xad\x96\xea\xb1\x50\x8f\x86\x96\xa1\x14\xe9\x3e\x9a\x61\x60\x06\x4c\x60\x1a\xcc\x97\x43\xfc\x26\x11\x03\xda\x11\x0f\xdd\xd4\x23\x1d\x92\xbd\xba\x49\x48\xea\x17\xa7\x47\x37\xc6\xca\x81\x5d\x3b\xf3\x36\x4e\xda\xd8\x28\x7b\x5b\xb2\xa7\x74\x37\x0d\x72\x67\x00\x36\xf0\x2f\x31\xbd\x2a\x42\xcb\x11\x4c\x49\x1f\xbf\x39\x7d\xba\x18\x05\xae\xe2\x90\xe1\x72\x03\xb5\x18\x69\x89\xe7\x64\xe8\xbd\x75\xbb\x25\x59\xff\x2d\x74\x09\x62\x4a\x18\x5b\x42\x00\x68\x12\x02\x6b\xbb\xf4\x38\xd8\x32\xc4\xc9\xf6\x21\x92\x4d\x7e\xa8\xe4\xbe\x0c\x4c\xa5\xb7\xe5\x7b\x1c\x51\x33\x21\xd9\xfc\x86\x31\xd4\xb6\x11\xee\x20\x74\x72\x34\x74\xb7\xed\x35\x22\x3a\xe6\xb9\x36\xe6\xa4\x71\xcc\x4c\x4d\x99\x3f\x33\xe6\xf9\xf6\x31\xcf\xe9\x98\xd7\x62\x63\x8b\x71\xbd\x4b\x64\xcc\x4b\x4d\x25\x9a\xab\x31\x9b\x9d\xab\x8f\xb9\x84\xa1\xd3\x45\x53\xf7\xf9\x89\x2e\x76\x9a\xe8\x42\x9c\xa8\x6c\x1d\xf4\xf3\xb4\x1c\x69\xc1\xc1\x9a\x26\x5a\x1e\x42\x30\xe5\x65\xf7\x89\x9e\xc1\xd0\xc9\xd0\xfd\x0e\x83\xfe\x17\x51\xf7\x8a\x0e\xfa\xe9\x6f\x1e\xf4\x4e\x33\xfd\xf3\x06\xdd\x82\xa1\xd3\x47\x67\x3b\x0c\x7a\xb4\xd3\xa0\xe5\x39\xd3\x8f\xcf\xb4\x64\x0f\x4d\x83\x96\x08\x66\x67\x79\xbb\x0f\xfa\x00\x92\xda\xd1\x13\x6c\xe0\x64\xda\x29\x8b\x40\xc0\x11\xc2\xce\x31\x2c\xe1\xb9\x2d\x9a\x4b\xb5\x5b\x2c\x32\xd7\x31\xed\xf7\x8f\xa0\x40\x86\x01\xbb\xa0\x55\x99\x3d\xa5\xd1\xcc\xf4\xad\xca\x71\x33\x0a\xf8\xb8\xe9\x59\x0c\x3a\x83\x75\x28\xeb\xb0\x23\x36\xec\xf3\x86\x61\x1b\x1c\x56\x6e\xd3\xb6\x0e\xfb\x79\x6e\xee\x8b\xe0\xa2\x05\x92\xc3\x8e\x8c\x61\x5f\x68\x7b\xb3\x73\xeb\xb0\xb5\xce\xb9\xf4\xcc\x14\x1d\xbe\x70\xb6\xd7\xbb\xcd\xb6\x2e\x79\x7e\x64\x95\x1b\x84\x63\x9d\x6d\x79\x54\x4f\x5a\x7c\x76\xb6\x3b\x94\xc8\xc7\x4d\x47\x83\xff\x56\x22\xef\xd2\x61\x2f\x7e\xe5\xb0\x77\x9a\xed\x37\x1e\x76\x16\x3a\x33\x88\x1e\x5f\x38\xec\xd6\x6e\xc3\x66\x01\x33\x5b\x6f\x31\xdb\x3a\x9b\xb0\x0e\x5b\xa2\x98\xb4\xf8\xec\xb0\x89\xd0\xee\x6a\x51\x35\x2b\x37\x08\x7c\x5b\xc9\x6e\xed\xce\xd9\xc9\xf3\x98\xfd\x9b\x21\xd2\x9f\xf4\x04\xc9\xa6\x3f\xd1\xc0\x65\xa7\x2c\xfb\x16\x12\x15\x2d\xbf\xe6\xa7\xf4\x43\xf8\xe8\x13\xa5\xad\x80\xc7\x3e\x90\x69\xb7\x3e\x90\xea\x5c\x01\x67\xbe\x2d\xf0\xa6\x36\xb6\x07\x48\x55\xb6\x96\x08\x09\x95\x0c\xe1\x93\x0f\xe4\xa2\x2e\xe0\xa9\x8f\xe5\xf6\xa7\xeb\x53\x74\x7e\x72\x12\xf4\xe8\x36\x9c\x8b\xaa\x1d\x58\xdc\x6b\x05\x91\x2c\x70\xe6\x36\x9c\xd5\xea\x05\x66\x61\x68\x9e\x8a\x0a\x6b\x1d\x11\x9e\xba\xc7\x72\x82\x5a\x04\xe7\x20\x90\xb7\xdb\x51\xa8\x85\xd3\xc5\x5f\x06\x81\x1e\x67\x36\x02\x95\x4d\xb2\x91\xd6\x33\xd2\xfa\xdf\xdb\x4e\x8f\x87\xb6\x23\xd3\x16\xf0\x99\xe5\x20\x34\x9a\x9d\xba\xf3\x64\xc7\xc8\x62\x9f\x4f\x8f\x95\x67\xea\xbd\x80\x24\xc1\x38\xdc\x55\x61\x0c\xd9\x66\xfc\xcb\x10\x06\x32\x82\x72\xe5\xfc\x67\x60\x49\xeb\x19\x69\xd9\x4d\x5b\x9c\xfc\x63\xd9\x0a\x13\x08\x7e\xed\x20\xc7\x88\xb9\xa9\xf6\xdb\x6a\x93\xce\x03\xfc\xa1\xbf\x34\x3b\x8c\x58\x13\xb1\x95\xd3\xff\xbe\x99\xf6\x17\x3d\x05\x2e\xa0\x8e\x3d\xa2\xf2\xc7\xe6\x29\x0b\x2f\x14\xb7\xb5\xd0\xe2\x14\x3b\xea\x00\x2b\x92\x25\xd4\x29\x89\x7a\x32\xce\x01\x62\x50\x89\xc6\xad\x9f\x7e\x2b\x16\x50\xb9\xeb\x53\x8b\x44\x5d\x27\xf6\x80\x45\x7c\xef\x78\xd5\x77\x43\x76\xa4\x6c\xc6\x06\x4b\x97\xca\xfa\x85\x2b\xef\xc2\x8d\xc8\xf9\x72\xf2\x35\x76\xe2\x6e\x2a\x91\x12\x6d\xc1\x4f\x55\x30\x57\x95\x61\xe3\x38\x3d\xf9\xa4\xce\x61\x7a\xd5\x8e\xe0\x29\x7c\xa0\x5b\x64\x40\xf5\x9d\x09\x6c\xb9\xb6\x98\xbb\x1a\xb7\xfb\xce\x36\x00\x2b\x48\xfe\xcd\xe0\x14\x6a\x9d\xb0\x80\xdf\x43\xb6\x1f\xde\xd0\x2b\xb7\x63\xb8\x80\xf5\xcb\x0b\x8d\x2d\xa5\x54\xd3\x56\x0b\xeb\x32\x74\x12\x90\x48\x3a\x4a\x42\x7e\x4f\xa5\x10\xc8\xd7\x84\x5f\xb9\x79\xd4\x29\x27\x10\x37\x61\x89\x85\x42\xf4\x93\xcf\x86\x80\x84\x1c\x77\x81\xb8\x76\x4b\x65\x35\x81\x2c\x67\x5b\x56\x06\xe1\xd2\xaf\x00\xac\xe8\xd8\x14\x71\x77\xe4\x13\xe3\x49\xf8\x84\x32\x42\x79\x7d\x68\xdc\x05\x69\xdc\x6c\xa6\x1e\xb5\xd4\xbe\xb6\x8a\x43\xa1\xa2\x15\xf4\x86\x5d\x55\xf5\x16\xe7\xd0\x1f\x43\x7e\xfb\xb1\x84\x20\x8b\xc5\xf4\x7c\x6b\x2b\x6d\x99\xdf\x8f\x4c\x5c\x7a\xe3\x7a\x04\xe9\xbf\x27\x4a\x35\x23\x28\x4b\x8c\x61\x9b\x13\x9f\x2e\x69\x4b\x5a\x9c\xe9\x24\xd2\x26\x81\x49\xe0\x63\x18\x08\x7e\x13\xbd\xf0\xb2\x82\x8d\x9b\x4e\xd5\x5a\x29\x07\x03\x6d\xf1\xb2\x44\x8f\xaa\x18\x91\x3c\xc7\x0e\x42\x67\x83\xe5\x0d\x1e\x25\xa8\x53\x75\x59\x8a\xa9\x59\x0b\x1e\xc2\x21\x0a\x78\xf7\xb1\xe2\x17\xb8\x80\x2b\x14\x92\x6d\x01\x19\x10\x1a\xc2\x23\x18\x70\x05\x86\x42\xad\x04\x14\xd9\x05\x2e\x75\x02\xc6\x9e\x73\xe1\x6a\xad\x92\x3d\x3c\x45\xfe\x0c\x0f\xe1\x9d\x6b\x6f\x6b\xe3\x86\x34\xff\x0c\xd9\x5b\x29\xdc\x90\x5f\x1f\x95\x48\x5e\x4f\x63\x50\x40\x31\xa4\x01\xa8\x1c\x1a\x77\x08\x32\x26\x34\xc4\x2b\x1f\x6c\x70\x01\xc9\x34\x80\x31\xe2\x37\x4c\xea\x32\x4f\x68\x68\x05\xb2\x40\xa4\x12\x22\x05\x33\x28\x16\xeb\x0b\xa8\x9a\xbd\xa7\x40\x1e\x9c\xd1\xb5\xb3\x52\x8f\x9a\xec\x54\x72\x6c\xa4\xe6\x5c\xd3\x83\x73\xa0\x64\x15\x4d\x7b\xc1\x79\xba\x5c\x56\x07\x90\x30\xa6\x58\xae\x07\x2b\xb9\xe6\x81\x26\x4d\x04\x0a\x43\xe7\x94\x5e\x10\xf3\x99\xf5\x42\x67\xe9\x0e\xe1\x38\xa8\xcc\x69\x4b\xcc\x59\x19\xb0\xfc\x61\x18\x48\xc3\x6a\x7d\x4e\x5b\x61\xe8\xac\x70\x95\x52\x4e\x29\xa5\x9c\x63\x56\xca\x56\xeb\x3c\x0c\x69\xfe\x5d\x64\xab\xf5\x53\xab\xf0\xa9\xd1\x03\xdb\xd2\x92\x85\x49\x9f\xd7\xee\x06\xde\x1e\x79\xb1\xc6\x4d\xb8\x8a\xa2\xbe\x13\x31\x8e\xdb\x6c\x5d\x1a\xcc\x6b\x87\x15\xca\x91\xc9\x42\x17\x27\x81\x59\x83\x69\x46\xfe\x6a\xee\x25\x94\x63\x5f\xe3\xfe\x37\x17\x90\x5a\x62\x8d\x11\x65\x3f\x73\x4c\xfe\x8d\xe0\xa1\x2b\xda\x8e\xda\x1c\x91\x8c\xd0\x4a\xf5\xd5\x90\x1d\x46\xf6\x3a\xea\xdd\x95\x26\xdb\x94\x57\x90\xba\xe9\xef\xcc\xbd\x85\x0f\x22\x1a\x1a\x2e\xe1\x0c\x85\xaa\xd3\xd8\x12\x70\x7e\x03\x8d\x80\xd2\x0d\x92\xd1\x16\x15\xdc\xa6\x45\x75\x8c\xed\x51\x4d\x4b\xba\x85\x4f\xf2\xbe\xa6\x84\x05\x16\x5c\x89\xfd\xae\x5d\x30\x08\xec\x9b\x86\x5b\x78\x28\x02\xfc\xc7\xd6\x82\x13\x18\xd8\xf7\x27\xb7\xf0\xce\xab\x96\x5c\x0b\x93\xb9\x53\x61\xec\x88\x41\x37\xe4\xdf\x38\xe1\xeb\x98\x12\xcc\x01\xfd\x5d\x31\x33\x3d\x8a\xe1\x89\x7b\x0b\x9f\x3c\x1b\x0f\x2e\x61\xe9\x53\xe3\x24\x15\xae\x15\x7b\x7c\x0d\x31\x1b\x3d\xd6\xec\x84\xcf\x94\x6a\x65\x43\x66\xcd\xb3\xf1\xed\x12\x1e\x78\x21\x29\xa1\x64\x4e\x47\x28\x35\x42\xd5\xd7\xdd\x27\xf8\xfc\x5e\xd1\xad\x53\x57\x2e\x23\xbc\x6d\xf1\xf8\x96\xc5\xe3\x5b\x16\x8f\x0f\xbe\xd0\xfb\xe1\x3c\x16\xd3\xff\x7d\x03\xe9\x96\xec\x10\xd2\x3d\xd9\x81\x4b\xfe\xcd\xe0\x93\x5c\x38\x77\xb0\xcd\x91\x77\x4e\x70\x1d\x8b\x3d\xc4\x19\x6c\x73\x64\x5c\x20\x30\x42\xb1\xb6\xc8\x79\xd5\x53\xd4\x76\xe6\x3a\xa2\x5c\x00\x4a\xd7\x39\x40\x00\xdc\xba\xa4\x14\x98\xf8\xe4\xdf\x12\x9d\xf0\x0f\xcd\x60\x34\x8e\x3e\x72\x5b\xab\x57\x29\x4f\x8a\x7e\xb3\xea\x53\x04\x2a\x96\x34\x4b\x5b\x13\xbe\xc6\xaa\x2e\x3d\x42\x8e\xb1\xcd\x6c\xf2\x9a\x30\x74\x90\x6d\x3b\x93\x8e\x9a\x32\x68\xed\x8d\xa7\x1a\x5b\x8a\x7d\x0b\x9d\x95\x0b\x4a\x68\xeb\x10\x35\x66\x70\xc1\x1a\xc6\x35\x95\x3c\x01\x4f\xb0\x4d\xb8\xff\x39\xb4\x98\x1d\xa5\x6d\x6e\x77\x62\xec\xdc\x3a\x16\x05\xd8\xd8\xc9\x28\xd5\x37\x97\x4f\x2f\xb8\x1a\xd6\x76\x66\x76\x23\xa2\x8e\x5a\x94\xea\x7e\xb7\xd0\xdf\x13\xcf\x39\x46\x63\x78\x22\x24\x71\x67\x04\x8f\x31\xd5\xf5\x62\x71\xdd\xba\x89\x41\x3b\x24\xeb\xbf\x1b\xd4\x0f\xf1\x97\x21\xd9\xae\xac\x91\x14\xe5\x01\x15\xe5\x5a\xf1\x49\x48\x18\xca\x06\xbe\x44\x4b\x7d\x85\xa4\xf0\xe8\xc7\x9c\x44\x90\xee\x0e\xb5\xa3\x76\x41\x12\x0b\x66\xd1\x6f\x6b\x1b\xca\x4c\xe3\xe6\x58\x99\x1a\x88\x59\xaa\x45\x1f\x6d\xe0\xf3\x4a\x48\xa9\x03\x82\x99\x32\x40\x89\x1b\xe7\x21\x32\xe6\xc1\x76\xd1\x5f\xc0\x31\xfc\x20\xbe\x55\xd3\x19\xc1\x52\x7e\xda\x4a\x43\x51\x04\xbe\xd3\x5b\xdb\x91\x88\x98\xad\x59\x96\xd2\xcb\xf5\x82\x71\x9b\xfa\x09\xe4\x7b\xc2\x78\x20\x18\xa1\x60\xcb\x5e\x34\x01\x77\xcc\x92\x74\x83\xf4\x63\x8c\x91\xd2\xfc\x15\x1e\x12\xa0\xe2\xdd\x67\x9e\x55\xfb\xc9\xaa\x42\x54\xa1\xc6\x66\xa6\x37\x51\xdf\x1d\x88\x9b\xca\x75\xaa\xe5\x4a\x08\x2a\x9f\x39\x9b\xdb\x96\xa5\xb1\x57\x35\x16\x28\xae\x36\x60\xd8\x59\xd8\x0e\x18\x7e\x74\xe5\x5a\xa6\x7d\xda\x51\xd3\xbe\x6c\x53\x3b\xdb\x09\xd9\x2e\x3e\xc2\x8b\x74\x04\x9d\x12\xae\xe1\x6d\xf7\x91\x4a\x9c\x35\x0c\xac\x27\x46\x36\x1e\x93\x58\x78\xd1\x8b\x86\xba\x4d\x9b\x19\xc3\xa7\x6b\xa0\x7d\x28\x48\x05\xe5\xc5\x6c\x10\x4b\x04\x36\x88\x0e\xe2\xf8\x63\xd7\x49\x37\xf0\x69\x08\x87\x50\x33\xa5\xd9\x81\x2f\x64\xa0\x72\x72\xa6\x7d\x84\x84\x50\x4c\xd7\x72\xc0\xc1\x3c\x69\x1e\x61\x8c\xe5\xc1\xf0\x1a\x5e\xaa\x59\xb9\xa2\x5a\x61\xd7\xb2\x08\x52\x7e\xd8\x69\x38\x87\xd0\x63\xcf\x19\x3d\x71\xe5\xa7\x77\x21\x3d\xe7\x4c\x6a\xbe\x1c\xfd\x29\xfc\x00\x95\xd2\x2a\x55\x99\xce\x04\xce\x21\xb5\x13\x03\xc7\x90\xfc\xeb\x2f\xa0\x36\x64\xde\xed\x2f\x6d\x32\xbd\x85\x65\xed\xaa\x2b\x83\x3e\x3d\x3a\x60\x6a\xdf\x31\xa3\x85\x2d\x76\x20\xda\xcf\x11\x33\xdc\x3b\x10\x3a\x5f\x34\x85\x0b\x17\x58\xf6\x40\x13\x78\xe0\x86\xce\x1c\x4e\xe1\xbd\x94\x10\x13\xb8\xc4\x21\xd7\x0d\x4f\xe9\xb1\x8a\x41\x6c\x15\x5a\x49\xc5\x29\xf0\x1b\x59\xfe\x71\xdd\x24\xa0\x03\x78\xf3\x6a\x99\xe9\xae\x38\xb3\x8e\x88\x2c\x9b\x43\x79\x02\x1e\xa3\xa9\x1f\x32\x47\xdf\x97\xef\xeb\x5e\xb7\xfb\xd1\x57\x65\xe2\x69\x7e\x1c\x19\x68\x30\x2d\x53\x8a\x9a\x3a\xc8\xeb\x57\x9f\x3a\x4f\x70\x08\xb1\x34\x51\xd8\xc0\x09\x54\x2b\x22\x0d\xb5\x6f\xf2\xfc\xb4\x71\x6d\x59\xc9\x4c\x65\x4f\x2c\xb6\xf0\xa9\x7e\xd8\x95\x55\x07\xc6\x65\x90\x74\x32\xd0\xae\xbe\x66\xea\xfc\x83\x99\xb5\x49\xc4\x9a\xfb\x23\x50\xf9\xb0\xa8\x71\x4c\xac\xad\xec\x3b\x78\xeb\x09\x16\x7d\x55\x40\x65\xd9\xbd\x81\x73\xac\x50\x19\x8b\x93\x5a\xe3\xee\x41\x71\xde\x18\x6c\xbb\x71\xe8\x02\x8b\x02\xa1\x48\xb8\xd0\xdf\xa3\xba\xb8\xe3\x39\xb8\xae\xa8\x33\x82\xfa\x7e\x86\xb0\xb3\x81\x79\xe9\x7a\x64\x03\x91\x76\xb5\x83\x78\x4e\x72\x9f\x3f\x3b\x17\x10\xe4\x89\x39\x17\xfe\xf7\x0f\xb8\x4d\xca\x5e\x30\x7f\xb6\x39\x8c\x75\x8c\xd7\x08\x41\xbb\x8d\x0c\x24\x21\x04\xa0\x6a\xec\xa9\xf6\xf4\x5d\x50\x3d\xbb\x7a\xd6\x16\xf4\x01\xb6\x9d\x03\x08\x5a\x30\x79\x4d\x37\x8e\xe0\x47\xa2\x3c\x9e\xc3\xae\xf6\x05\xa4\x8c\x3d\x7d\x80\x14\x05\x33\x94\xbc\xc6\x7e\xf5\x07\x86\x74\x8f\x3e\x12\x26\x7b\x2c\x1a\x5e\xaa\x4d\xda\x4a\x3d\x6a\xa9\xb9\x36\x6f\x67\xe8\x23\x91\x0b\xa5\xcb\x0b\xc7\xdf\xc7\x3e\x9d\xaf\xa5\x0b\x9c\xd2\x05\x41\x52\x9f\xeb\xab\x8f\x4e\x89\x40\x37\x6e\x9c\xeb\x09\xa6\xed\x15\xf2\x8e\xee\xd7\xcc\x35\xd9\xa8\x8d\xd0\x6b\x49\x6e\x01\xdb\xce\x29\x02\x6b\x98\xd4\xe7\xfa\x09\x52\x14\x1c\x88\xa3\xf9\xbf\x6d\xae\x6f\x11\x3d\x1d\x58\x8a\xfd\xff\x8b\xe6\xfa\x01\xb5\x89\x72\x75\x2a\x0a\xef\xe7\xfa\xbf\x6d\xae\x5b\x3f\x30\xd7\xad\xfd\x5c\xff\x53\xe6\x1a\x9c\x91\x94\xdf\x63\xa2\x5e\x48\x6b\x18\xfc\xd5\xde\x4f\xee\x96\xc9\x8d\x40\xf6\x59\x39\xb8\xf9\x7c\x4f\x95\x83\x4b\xba\x26\xc0\x04\xd1\x7f\x53\xa4\xee\xd6\xe2\x58\xc0\xb4\xa9\xd3\x7a\x5f\xbe\x7f\x69\xd3\xbb\xc7\x63\x7a\x05\x99\x4f\x91\x48\xff\xfe\xd1\x39\x47\x60\x02\x13\x91\x30\x85\x1f\xf9\x49\xff\x31\xff\xa6\x39\x10\x17\xcc\xb2\xb2\x13\xd8\x26\x3d\x2a\x10\x3f\x60\xca\xc1\x10\xd1\x0b\x87\x99\xf4\xc7\x98\x5d\x8b\x63\xa2\x35\x92\x1d\x8f\xc4\x65\x60\x81\xe4\x70\x22\x32\x1c\x32\x80\x39\x1b\xc7\x02\x11\x1c\x30\x57\x53\x31\x9c\x88\x0c\x67\xa9\x86\x33\x87\x64\x3c\xa4\x97\xe7\x88\xfc\xcb\x17\x7c\x3c\x4b\x48\x06\x74\xa0\x0d\x68\xc9\x42\x17\x5c\x88\x63\x76\x39\xae\x53\x6d\x44\x11\x1d\x51\x81\xd4\x88\xe6\x90\x0e\x69\xae\x0f\xa9\xc5\x86\x74\xae\x0d\x69\x0e\xd1\x22\xe1\xb6\x55\x7f\xd7\xee\xaf\xf9\x98\xa8\x84\x0b\x78\x25\xb6\x20\x73\x48\x37\x6d\xfe\x9b\x45\x89\xe2\x07\x11\x95\xcf\x82\x52\x3f\xd6\x5c\x5a\xa1\xa5\xa0\xe2\xb3\xbd\x54\xb7\xdc\xf8\x08\xde\x41\xd2\x95\x16\xdc\x68\xfb\x4a\x8f\xde\xed\xc7\x81\xc0\x4c\x10\x3a\xc7\xee\x02\xde\xa2\xc0\x72\x44\x32\x87\x05\x0a\x9d\x8d\xbb\x80\x53\x28\x6e\x98\x68\x7e\x4b\xe4\xcf\x91\xbe\x19\x54\xe7\x0e\x8a\xf1\x68\xa7\x55\x03\x13\x79\xec\x06\x7b\x01\x8f\x5c\xbe\xcd\xd4\x2d\xd7\x19\x32\xe6\x70\x8e\xed\x4d\x68\x15\xf7\x6a\x15\x5f\x7a\xce\x1a\x2e\xe0\x42\x5d\x6d\x8b\x1f\xd1\xc4\x1c\xce\xbc\x50\xf7\x54\x56\xa8\x54\x1b\x50\x03\xbd\x13\x03\x9a\xc3\x24\x9e\x33\x40\xf7\xbe\xcd\x1a\x1f\x83\x8a\x69\x2c\x3f\x3a\x72\x67\x7e\xe8\x0c\xd0\xd3\x4b\x8a\xac\xfc\xd0\xe9\xa1\xb3\xa6\x22\x75\x47\x9f\xbe\xdb\xa2\xad\x1c\xbe\xa4\x95\x73\x3f\x74\x32\x34\xbe\x6c\x28\xa2\xdb\xbb\x8a\x22\xa3\x4b\x42\x52\xe8\xbd\x6c\x46\x33\xa6\x75\x0f\xa8\xe1\x1f\x1a\x5e\xd6\x33\x23\x77\x74\x49\x50\x8a\xa6\x96\xcc\xc4\x9d\x5f\x12\x72\x46\xf7\xd6\xcc\x35\xcb\x7c\xb2\x66\x1e\x5f\x92\x4d\x38\x3a\xb3\x66\x4e\x02\x32\x59\x27\x97\x58\x32\x2b\x3b\x26\x64\x91\x39\x24\x5b\xf7\x03\x01\xa1\x4c\x70\xe9\xa5\xbb\xb2\x90\x61\xb7\xb1\xcc\x1e\x83\x99\x85\x6e\x14\xc4\x52\xab\xe4\x40\x8b\x60\xe2\x5e\xf8\x6d\xdd\x24\xcc\x38\x8a\x11\x56\x1a\x9e\xd3\x5d\xc0\xb3\x50\x2e\x92\x39\x2c\xa2\xb0\xe6\x41\xff\x22\x1b\xb0\x04\xc4\x9e\x33\x58\xc0\x7b\x69\x74\x31\x81\x6a\xe5\x93\x26\xd6\xf4\xc3\xea\x0b\x78\x22\xcd\x36\x18\x44\x8b\x3f\x47\x07\x90\x99\xe7\x4e\x02\x3d\x8e\xc0\xdb\xba\x6a\xb3\xaf\x8a\x46\x6f\xe1\xd9\xbc\xfb\xb5\xf2\xeb\x04\x05\xf3\x99\xef\xb7\xa0\xb8\x60\xf8\x72\x44\xcd\x38\xb2\x0d\x3f\x57\x8e\x87\x70\x18\x3e\x40\x8a\xb3\xe3\xd0\x7b\xd9\xf9\xde\xcb\x70\x36\xa2\x38\x7b\x0b\x5c\x5c\x51\x9b\x49\x75\x81\xa7\xa8\xf2\x13\xd1\x48\x16\x70\x1c\x63\x8b\xed\xc1\x1c\x96\xb1\x47\x24\xfe\x08\x76\xe5\x81\xf6\x18\x7e\x26\x9a\xc2\x1c\x76\x65\x89\x05\xfc\xec\x9c\xc3\x05\xbc\xbb\xc2\x16\x6b\x83\x39\x9c\x5c\x79\x44\x7b\x38\x85\x5d\x91\x06\xce\xe0\x67\xa2\x5c\x1c\xc0\xae\x2c\x71\x08\x3f\x3b\x73\x97\x9e\x0e\xf1\xc5\x73\x87\x3e\x3a\x4b\xc6\xef\x31\x58\x23\x7e\xa2\xe4\x0f\xe1\x34\xfe\x48\x27\xa0\x6c\xf3\x63\xdc\xb9\x42\xd2\xa8\x86\x2f\x54\xb9\x95\x2f\xd4\x23\xb7\x67\xf5\xe8\x25\x44\x64\xf7\x4f\xe7\x76\x94\xc3\x8f\x6d\x6d\xaa\x0d\x33\x4b\xab\x91\x6f\xf2\x00\x81\x10\xf7\x6b\x78\x59\xff\xc2\xba\x3a\xa0\xe4\x6c\x84\x2e\x55\xcd\x62\xcf\xf5\x88\xfe\x58\xe9\x57\x4d\x63\xaf\xdc\x29\x25\x00\x94\xc8\x09\xc0\xa7\x05\x72\x0a\x66\xba\x22\x2c\xf5\xe9\xfd\xa5\x4b\x63\x6d\x09\x25\x82\x5b\xd2\x2a\x8b\x7d\x3c\x45\x2f\x39\xaf\xc6\x3a\x82\xd9\xe8\x9f\xd4\x90\x37\x30\xa0\xea\xb6\x2f\x88\xee\x09\xce\xa0\xf0\xb5\xd0\xd5\x93\x0d\x7c\x24\x7b\x20\xf4\x04\xd3\x8a\x76\xb2\x16\xd9\x9f\xa9\xee\x38\xd0\xdd\xa4\xb7\x39\x74\xdc\x42\x6a\x4a\x3a\xaf\x5c\xe0\xa8\x8b\x45\xf3\x5a\x56\xbf\xd4\x09\xb8\xd3\x80\x2d\x62\x8a\xba\x3c\x30\xae\xb0\xb7\x05\x77\xb2\x7c\x89\xfe\x03\x7c\x82\x58\xfa\xae\x5e\xc0\x53\xf8\x8c\x7d\xb4\xfa\x06\xf0\xd0\x15\x51\x39\xec\x07\xee\x11\x76\x4a\xf7\x08\xce\x25\x9a\x63\x85\xe6\xb8\x05\x6f\x21\x76\x0a\xf7\x08\x62\xe1\x85\x12\x2b\x34\xc7\x2d\xf8\xbd\x5e\x79\xfc\x46\x95\x1f\xc3\x6f\xa1\xf6\x9d\xf9\x0c\xd4\xaf\x48\x39\xeb\xab\x9b\x83\x19\xf3\xdd\x18\x0a\x20\x3d\x81\x9f\x05\xed\x1d\x43\xaa\xd0\x0e\xe4\xd5\x53\x54\xf3\x96\x60\x5c\x76\x88\xda\xbc\xcc\xa0\x40\x19\xb0\x5b\x9e\x73\x65\x35\xad\x86\xdd\x91\xd3\x72\x42\x5d\x8d\x06\x7c\xa0\x23\x37\x74\x72\xea\x50\xcd\xe7\xef\x16\x95\x10\x4b\x9d\xa3\x44\xdf\x64\x8e\x3b\x71\xdb\x4e\x8e\x1e\x76\x82\x5d\x51\xd8\x93\x9d\x60\x8f\xdd\xb6\xd3\x47\x87\x26\xac\x50\x2e\x2b\xb0\x07\xb4\xde\x29\xde\xa9\xbf\xb8\xed\x0c\xd0\x83\x09\x2b\xd4\x49\x1d\x16\x5d\xb7\x35\x6d\x22\xb2\xb0\x4b\x0e\xf8\x1e\x4a\xe4\x45\x33\x97\xa8\x22\x6b\xf8\xe8\x12\x55\xa4\xa3\x17\xa6\x1e\x31\x03\x15\xbb\x57\x38\x80\x2b\x23\x55\x79\x3a\xf2\x1e\x7e\x13\x89\x17\x10\xe8\x74\x67\x6c\x6c\x6c\xcb\xb3\xff\x01\x5e\x0a\x2a\xba\x80\x49\xe8\xe4\x9a\x27\x57\xc0\xa5\x3d\xa7\xd0\x84\xae\x04\xbf\x66\x33\xa0\xcc\xfd\x15\x0b\xe9\x54\x33\x28\x35\xe5\xd4\x9f\xad\xce\xc0\x14\x10\x06\x5c\x3d\x14\x40\x58\xc4\x01\x8a\xf9\x8c\x10\x86\x8d\x4e\x9e\xaf\x26\x37\x6a\x59\xeb\xb5\x2c\x11\xe9\xcc\x87\x1f\xed\xcc\x06\x91\x8d\xca\xad\xfb\x6c\x35\xa5\x59\x4d\x4b\xab\x06\x7d\xa6\x26\x50\x08\x93\x89\xef\xe8\x76\x20\x18\xa0\x6b\xa2\xdf\x44\x3c\x91\xeb\x36\xde\x35\xd1\xd8\x5e\x04\x5f\xbc\x04\x3e\xb8\xd6\x8c\x21\x76\xd0\xf1\xd2\x2a\x5b\x36\xa4\x45\xcd\x9c\x75\x88\x3e\x09\x82\x2b\x50\x9f\x13\xb9\xd2\x2f\xea\x92\x8e\x3a\xb0\xa1\xbe\x40\xe0\x46\xb3\x91\x99\x69\xcf\x65\xe4\x7e\x7e\xe6\x9a\x33\xf0\x78\x6c\x2d\xa6\x32\x31\x1d\xca\x97\xe4\x9a\xca\x61\x5a\x73\xba\xd6\x1c\xfc\x01\x7a\xda\x92\xdb\x59\x27\x7e\xd6\xa2\x5e\x9c\x9f\xbc\x81\x3a\x8c\xbc\x17\xaa\xed\xaf\xd8\x47\xf8\x96\x6b\xf9\xb4\xb2\xee\x6c\x76\xce\x09\xb8\xf4\x9c\x52\x59\x79\x26\x8f\xe8\x0a\x48\x5f\xda\x35\xea\x3e\xa3\x2b\x7c\x63\xf1\x84\x2c\xb6\x2b\x94\xe3\x94\x36\x1b\xd3\x5f\x15\x95\xcb\x60\x8d\xb8\x2e\x1c\xec\x67\x75\xe0\x93\xe7\x9c\xc3\x29\xba\xb3\x1e\x76\x4d\x10\xe1\x89\xa7\xec\x60\x9f\xe1\x7d\x8a\xee\x11\xb0\x9c\x7b\x5d\x5d\x89\x52\x2b\xb8\x46\x07\x1a\x46\x17\x15\x93\xa2\x16\x7c\xd8\xe6\x63\x16\x81\x33\x48\x8d\xa9\xc1\xcc\x25\xff\x0a\xf4\x01\x09\xf0\x21\x6a\x53\xa7\x87\xd2\xa5\xfa\x38\x3a\x91\x39\x53\x44\x4d\x06\x35\x5b\xc0\x67\xd4\xda\x33\x44\x2f\x0a\x98\x51\x3a\xe9\xb3\x0b\x46\xae\x34\x68\x1a\xbb\x6d\x6a\xb7\xac\x52\x7a\xd4\x98\x09\x07\x1a\x19\xf6\x4d\x82\x0c\x43\xe7\xd8\x05\xa9\xf4\xa2\xfc\xd4\x76\x36\x2e\xc8\xc5\x8d\x03\x3a\xb9\x14\xc6\xa6\x75\x72\x92\x7e\xd3\x95\xb8\x70\xae\xc7\x0d\xd1\xd7\xae\xf4\xa3\x4d\x9e\x50\xe2\x55\xfc\xb8\x44\x6c\xd9\x0d\x0a\x6d\x55\x7f\x0a\xb9\xc3\xd6\x12\x81\xcc\x66\x5e\xac\xb0\x72\x57\xf5\x72\x32\x7b\xc8\xa6\xf7\xd4\xe8\x21\x73\x43\x99\x9b\x3d\xd4\x23\xf1\x89\x10\xba\xcd\x3d\x94\xa1\xf3\x76\xe8\xe1\xef\x8f\xc3\x75\x73\x0f\x37\x9c\xfb\x54\x7b\x38\x12\x44\x58\xed\xa1\x3c\x1c\xd3\x3c\x97\x9a\x7b\x28\x47\xb2\xbd\x87\x68\x01\xdb\xb5\x73\x32\xb5\x33\x53\x25\xd5\x4a\xe2\x42\xf8\x8a\x22\x38\x09\xea\xbb\xee\x4f\xdf\xf9\x0d\x0d\x63\x21\x95\xd8\x13\x8c\x83\xda\x8e\xe4\x6c\x07\x71\x36\xeb\x50\x0e\xc7\xbc\x94\x71\x20\x64\x58\xf5\x9d\x1a\xde\xb1\x73\x44\xae\x51\x56\xdf\x23\x74\xeb\x86\x5a\xd0\xee\xd8\xa2\x53\x34\xee\x93\x78\x9a\x8a\xa2\x5a\xc1\x91\x7f\x82\x32\x7e\x04\x9e\x1d\xa3\xcf\xdb\x37\x3e\xca\xe1\xb4\xab\x9f\xe1\xe3\x2a\x88\xe9\x07\xac\xe4\x66\x84\x16\x50\x0f\x45\x4a\x5d\x5f\x3b\x3f\xe0\xf9\x6a\xb8\x6c\xf3\x4a\x7d\x39\xff\x7f\x91\x59\xbf\x47\xbe\xb8\x1e\xd5\xc4\x57\x0a\x84\x82\x61\x26\xaa\xd8\xc7\x06\x60\xf7\xf9\x34\xb3\x2e\xad\x9a\x25\x2a\x60\x35\x3e\x75\xa6\x1e\xbb\xfc\x71\xca\xe4\xcd\x1c\x6e\x20\xcf\xc9\x25\x64\x2e\x01\x73\x80\x9f\x20\x3f\x45\x52\x6a\x24\x3f\x76\x0a\xf8\x41\x98\x69\x97\xa6\xd1\x65\xe0\x99\x4e\xf1\x7f\xdb\x85\xdb\x4e\xbe\xee\xf9\x03\x1a\x0b\x5f\xf7\x78\x85\x96\xae\x70\xc1\x21\x3d\x2f\x7e\xc4\x55\xba\xa2\x53\x5c\x53\xe3\xbe\x6e\x4f\x54\xfe\xf9\x2f\xf2\xde\xe3\xef\x3e\x88\xfe\xd2\x2c\x43\x7f\x42\x84\x45\x5a\x92\x21\x64\x00\x2a\xc1\x23\x0a\x9e\x58\xe9\x76\x2d\x9e\x7e\xc0\xfd\x01\x8c\x0b\x86\x00\x44\xd5\x78\xbf\xfe\xdb\xb8\x36\xaa\xce\x04\xde\xcf\x45\x4c\xa0\x10\xa3\x56\xa4\xe6\x65\x93\x56\x11\x53\xfb\x9a\xc0\x15\x8b\xd5\xbe\x81\xa2\xe6\x8f\x4f\x90\xf0\xdb\x74\x0d\x85\xef\x55\xf0\x08\xb9\x30\x6e\xdc\xb3\x1b\x9c\x9c\x31\x97\x31\xba\xc5\xd8\xd9\xc0\x11\x5a\x61\x8e\x05\xe5\x4c\xd1\xd1\x90\xd7\xa1\xc1\x58\xfa\x9c\x4d\x8f\xd1\xd0\xfb\x4c\x8b\xcd\xbc\x4a\x06\x3a\x09\x6e\x48\xeb\xb5\xc5\xa8\xf0\x1d\xa3\x4b\xa0\x85\x99\xec\x82\x6a\x08\x9a\xce\x21\x9a\x5f\x9f\x5e\x3a\x25\x3c\x40\x8b\xeb\xb3\x4b\x61\x92\x8b\x6b\x47\x64\x94\x27\xd7\xbc\x6b\x2a\xb9\x46\xa4\x8a\xd8\x90\x03\x46\x3c\x0f\x95\xd6\x01\x16\x07\x37\xf7\x5a\x9e\x19\x62\xf1\x71\x15\x4d\x38\x7f\x26\xf8\xeb\xcb\xd5\xf6\xa5\x47\xed\x0a\xee\x21\x59\x84\x32\xc0\x87\x5a\xdd\xbc\x6b\xb7\x70\x83\x9c\x11\x06\xe0\x3d\x35\x5c\x98\x09\xc7\x32\xb5\xda\x0d\x07\x52\x75\xb8\xae\x98\xb1\xaa\x55\xf0\x82\x27\x38\x82\x54\x0f\x78\xa4\xe1\x04\x2e\x54\x80\x11\xe3\x34\xf2\x10\x1e\x23\x1a\x92\xfb\x10\x09\xe7\xc2\x40\xc2\x44\x66\x6f\xb7\xb5\xaf\x3a\x21\xbc\x8e\x1e\xd0\x04\x52\xbf\xc5\x27\x1a\xd2\xe2\x14\xd9\x91\x10\x80\xf7\xe8\x14\x39\x07\x2e\x00\x43\xea\xb2\x58\xb8\xb1\x06\xb3\x03\x12\xb0\xd6\x09\xcd\xc5\x66\xe1\x96\xcc\x05\xff\x81\x06\x53\x68\xb9\x76\x24\x44\xe0\xc4\x6d\x21\xa7\xc4\x00\x7c\x40\xce\x39\x02\x17\xae\x8e\x84\x78\x47\x24\x18\x9d\x18\xf1\x4e\x88\x88\x2d\x46\xd4\x15\xa3\x7e\xeb\x11\x4a\xf4\x88\x4e\xa4\xf3\xef\x1a\x2d\x31\xf5\x3b\x48\x03\x53\x16\x1a\x32\x82\x7b\x7d\xc8\xab\x14\xfc\xe0\x85\xe6\x9a\x34\xd0\x6b\x53\x41\x94\x56\xa6\xf5\xda\x6d\xff\x33\xd7\x2e\x0a\xed\x6b\xf7\xc5\xa2\xfc\x08\x7d\x11\x92\xbc\x85\xc2\x11\xd4\x16\xf9\x46\x38\xca\xc4\xe0\x09\x1e\xb3\x60\xfe\x77\x74\xe7\x0c\xde\x33\x8f\xdf\x0f\xd4\x1b\xeb\x1c\xc6\x1a\x51\x8b\x23\xb9\x0f\x70\x0d\x29\x2c\x03\x22\x0b\x51\x5d\x55\xf4\xe5\x13\xeb\x70\x01\xc1\x1d\x5a\x41\xda\x04\xab\x7b\xbd\x15\x3e\x02\x47\xa8\xc2\x10\x0a\x57\x06\x07\x19\xba\xe7\x3e\xdd\x39\x8e\x5d\xba\x0f\x3f\x64\x11\xfe\x87\x34\x28\xc5\xac\xb2\x14\xc4\x0d\xe4\xc2\x6d\x41\x0a\xcb\x80\x36\x6e\xac\xc5\x3d\x52\xb3\x35\x11\x7d\x3d\x71\x37\x90\x36\xc1\xea\x3e\xd8\x0a\x1f\x81\x5b\x5c\xe1\x1b\x2b\x2c\x43\x43\x3c\xe0\x0b\x5f\x38\x35\x17\xb2\x7d\x70\x8b\x88\x38\x3c\xc6\x3a\x5e\x85\x8a\x70\x86\x8f\x59\xdb\x0c\xa8\xf0\x62\x31\x9d\x15\x3c\xcd\x44\x5f\xc7\x5e\x0b\xd2\x26\x58\xdd\xcb\xad\xf0\x09\x78\xf4\x5a\x3a\xeb\x3a\xaf\x44\x7c\xb0\x31\x31\xdb\xf6\xae\x0f\xea\x57\xa7\x35\xf5\xe8\xce\xaf\x72\x33\x3f\x10\xe5\x8e\xfc\x53\x9f\x4e\xc7\xd4\xa5\x14\xf1\x41\xba\x99\x5f\x40\x70\xe1\xeb\x33\x28\x6c\x97\x0e\xfd\x0d\xa3\x1e\x06\x34\xb9\x8c\xb5\xad\x98\x9a\x91\x91\xc0\xca\xe2\x72\xcd\x66\x9c\xd5\xbd\xd9\x0a\x1f\x81\x8e\xee\x47\xab\x0e\xd0\x6c\x41\x12\x9a\x0d\xb0\x92\x23\xf4\xfe\x52\xdc\xee\x8c\x34\xf3\x8f\x11\x6c\xa1\xd5\x25\x75\x9b\xe9\xca\x9b\xb0\x20\xd4\x2d\x55\x78\x9b\x89\xf0\x86\x2d\x6d\x41\x82\xe2\x5d\x39\xa8\xba\x93\x31\x18\x7f\xc4\x43\x03\x5b\x72\xd0\x63\xc4\x9d\x0d\x55\x8c\x31\xd3\xdb\x5e\x51\x80\xd8\xea\xd9\x77\x32\xda\x81\x39\xfa\x02\x9c\x0b\xe8\xa6\x94\x15\x05\x41\x7d\x23\xd8\x07\x96\x8d\xa0\x62\xd9\x99\x05\xb0\xfb\x7c\x9a\x59\x97\x56\x4d\x0b\xc9\xa0\x87\x15\x95\xb8\xea\x64\xce\x54\x68\xf4\x79\x85\x9c\xb9\xe7\xe2\x27\xf4\x8f\xec\x3f\x0f\x57\x27\xa1\xd8\x57\x3a\x76\xda\x37\xe8\xd1\x7e\x71\x5d\x14\xa3\x0f\x90\x4e\xec\x04\x89\xf8\x19\x6b\x1a\x77\x88\x75\x7c\xa2\x76\xd5\x2c\x1c\xe3\xa9\x56\xd5\x48\x74\x45\x80\x2c\xb5\xb0\xa4\x3a\xc8\x4a\x81\xac\x21\x7a\x44\x6c\x2e\x4e\xe1\x13\xfa\x7b\x9a\xe4\x8e\x93\x2c\xd9\x82\x03\x6d\x11\xe2\x97\x9e\xe1\xef\xbe\x1b\xeb\x80\x5d\xbf\x76\xd0\xa8\x9e\x31\x15\x7f\xe8\x92\x5d\xbd\x7e\xb8\x2a\x7e\x0b\x77\xed\x36\x1c\x3d\xa9\x13\x26\xbe\x4f\xf0\xc5\x77\x60\xb8\x22\x86\xc5\xdd\x15\x67\x4c\x81\x16\x51\x14\xd7\x9c\x04\x8d\x4d\x9d\xfa\x1a\xd5\x4b\xbc\x02\xb1\x88\x69\xc5\x10\x74\x7a\x65\xa6\x5c\x5c\xa9\xef\x1e\x35\xea\x9e\x91\x45\x9b\x54\x61\x3e\x76\xb6\x8d\xdb\x69\x7a\x32\x49\x25\x19\xa8\x9b\x57\x70\x65\xe1\x0b\xbd\x95\xca\xdf\x3a\xa0\x5b\x3d\xca\x40\x00\x90\xbd\x23\x8a\xf4\x4c\xbb\xe0\x39\xa4\x71\x45\x0b\x66\x73\x6e\x2c\x84\xd8\x82\xc9\xc6\x29\xe7\x72\xe7\x16\xdd\x42\xaa\xb0\xa1\xd8\x0c\x9d\xf9\x9a\xea\x8e\x48\x75\xe7\x90\x7e\x92\x44\xa8\x90\x69\xdd\xa6\x53\x2d\x13\x83\x04\x82\x2a\x09\xd8\x94\x75\x73\x61\xe1\xe1\x15\x93\xd6\x73\xc8\xa0\x26\x10\xa0\x05\x24\xb9\x22\x65\x40\x13\x06\x2a\xa1\x84\x0d\x29\x13\xad\x9e\x25\x4b\xaa\x56\x8d\xdc\x05\x64\xe2\x59\x18\x76\x78\x40\xbf\x87\x1d\xc1\x3b\xb7\x80\xca\x1e\x7b\xe6\x7e\x51\x59\xe0\x2a\x7c\x11\x6c\x5a\x87\x15\x71\x06\x7e\xa8\xde\x5e\x1d\x56\x1c\xc8\xbe\xba\x5e\x14\xd2\xf8\xa8\x13\x28\xef\x03\xa7\x14\xc1\x13\x28\xb8\x0b\x49\x20\xdd\x9f\x40\xa9\x28\x4d\x59\xf8\xdd\x09\x64\xcb\x95\xa5\xe4\x34\xa1\xcf\x12\xe2\x29\x74\xd2\xa1\xfb\x59\xc4\x07\x28\xdc\x2c\x74\xb2\xa1\x7b\x6d\xbb\xeb\x2c\xdc\x34\x74\xf2\xa1\x7b\x69\xb3\x9b\x2b\xdc\x28\x74\x0a\x38\x74\x91\xcd\xe6\xbf\x70\x51\xe8\x0c\x86\x6e\x14\x58\x2c\xf2\x0a\xd7\x13\x9f\xdc\xe4\xba\xa6\xf8\xc6\x18\xd3\x4c\x1f\xe1\x18\x01\xc7\x12\x03\xb3\x62\xce\xb8\x81\x01\x4d\xe4\x30\x39\x40\xf4\x08\x8c\xbf\x92\xd2\x8c\x8e\x79\xc2\x8a\x26\xa4\xf2\xbd\xb0\xbe\x0f\xe4\xfb\x9c\xbe\xab\xfa\x77\xf1\x18\x22\x6a\xa3\x80\x3f\x57\x39\x17\xea\xf1\x5c\x2f\x7a\x86\x36\xc8\x73\x36\xf0\x14\x0d\x5d\xba\xfc\xf4\xa1\x64\xc6\x50\x26\xe6\x50\xfa\x46\xd7\xcd\xf7\x12\x1a\x63\xe9\xbd\x70\x2c\x23\xb8\xfb\x60\x56\xfb\xc1\xfc\xe6\x83\x69\xfd\x3b\x06\x83\xae\x79\x17\x5a\x4a\x87\x60\x56\xdb\x40\xa8\x9b\x3e\x10\x5b\x57\x5f\xf6\xc7\x84\xc6\x12\x1a\x03\x2d\xbc\xb1\xe0\x18\xbb\x81\x63\xce\x70\x26\x42\x97\x90\xa3\x2b\x35\xad\x5b\x73\x59\x1a\xc8\x6a\x06\x12\xf7\xba\x33\x53\xbd\x70\xa9\xe5\xb2\xe7\x5c\xcd\x15\xc3\x5c\xbd\x75\x5d\xe7\x5f\xd6\xaa\x97\xc2\x98\x7d\x42\xc8\xd6\x03\xbd\x82\x8d\x96\xbb\x51\x15\x6c\xa8\xaf\x0a\xc5\xad\x76\xa3\xa8\x06\xd8\xad\x52\xd8\x48\x1b\xc1\x40\x3d\x76\x4d\xc2\x1b\x99\x88\xd3\x76\x2e\x2b\xc8\xb5\x72\x80\xd5\xf9\x9b\xd4\x52\xe7\xaa\x4c\xa1\x65\xce\xb5\x81\x6a\xcd\xaf\xa1\x31\x2b\x5a\xc1\x09\x2d\xb2\xd6\x8a\x94\x5a\x3b\xb5\x31\xc8\x93\x0d\xc4\x6c\x19\x34\x79\x0f\x34\x8f\x2b\x51\x68\x54\xed\xb9\x6c\x69\x6d\x8e\x7c\xae\x01\xb2\xa1\xeb\x28\x62\xe9\x33\x6d\xe8\x39\xd0\x8e\x4c\xe5\xc8\x4b\xad\xcc\x40\x15\x99\x18\x73\xd6\x57\x03\x9f\x41\x73\xc2\x66\x16\xf2\x13\x65\xd8\xb8\x97\x5a\x99\x09\xb4\x36\xa3\x7d\x92\x77\xa2\xcd\x89\x7e\x73\x3d\xd3\x9e\xb5\x6f\x49\x8b\x93\x03\x2c\xca\x2c\xb5\x51\x4f\x34\x6c\x0c\xd4\xb0\x27\x1a\xe0\xc4\x3a\xd7\x13\xad\xe3\xcb\x86\xb5\x36\x50\x23\x5c\x69\x80\x3a\xf1\x8c\x2a\x34\x65\xd4\xb8\xd2\x00\xe7\x15\x9a\x36\x6a\x1c\xd9\x6b\x64\x83\x2e\xb5\x55\x9a\x2b\x3c\xe5\x06\x82\x7b\xa0\xca\x51\xf5\x66\x67\x1a\x96\x7a\x0a\x4b\x45\x6d\xfd\xcf\x54\xe3\x3d\x85\xa5\x89\x06\x57\x27\x09\x3d\xbd\xa7\x30\x56\x67\x2e\x3a\x4d\xf4\x4c\x82\x9b\x34\x10\x82\x9e\xce\xcf\xa3\xde\xa3\x1e\x59\x6a\xe7\x54\x9e\xe5\x2f\x12\x06\x83\x17\x09\x83\xc9\xcb\x84\x41\xf6\x23\xc2\xa0\x3e\x17\x2f\x94\x06\xf3\x1f\x95\x06\xeb\x1f\x95\x06\x83\x1d\xa4\x41\x51\xe3\x2e\x76\x71\xb0\xdc\x51\x1c\xb4\x5e\x23\x0e\xd6\x2f\x17\x07\xc7\xaf\x11\x07\xa7\xaf\x11\x07\xc7\xbb\x8a\x83\xe5\x2b\xc4\xc1\xec\xc5\xe2\x60\xf5\x0a\x71\xb0\x79\x85\x38\x58\xbf\x42\x1c\xac\x77\x15\x07\xcb\x1d\xc5\xc1\x66\x57\x71\xd0\xda\x55\x1c\x6c\x76\x15\x07\xad\x5d\xc5\xc1\xec\xa5\xe2\xa0\xce\x18\x1a\xc4\xc1\x64\x47\x71\xb0\x7c\x8d\x38\xa8\x73\x97\x06\x71\xb0\x7a\x99\x38\x98\xec\xc5\x41\x7d\x39\xee\xc5\xc1\x5e\x1c\xec\xc5\xc1\x5e\x1c\xa8\xc7\xbd\x38\xd8\x8b\x83\xbd\x38\xd8\x8b\x83\xbd\x38\xd8\x8b\x83\xff\x3e\x71\xd0\xda\x8b\x83\xbd\x38\xd8\x8b\x83\xbd\x38\xd8\x8b\x03\x13\xab\xff\x65\xe2\x00\x3d\x21\xcf\xe9\xa3\x4b\x8f\x3b\x12\xb8\x01\x76\x32\xe4\xf2\xd7\x02\xba\x18\x3b\x7d\x84\x44\xf6\x21\x2a\x5d\xec\x6c\xe0\x05\xba\x23\xe2\xa3\x5a\xae\x80\x46\xc1\x5c\x16\x2c\xe0\xaf\x2b\xd9\x7a\x45\x49\x74\xe5\x69\xa1\xa9\x1a\x3d\x20\x6b\x5e\x2a\xbe\xee\x16\xda\x68\xc8\x6d\x2b\xa6\x5c\x09\x59\x78\x25\x20\x8c\x84\x02\x03\x18\xdd\x42\xcf\x49\xd1\x36\x83\xb7\x00\xd4\x3f\x09\x64\xc4\x4a\x51\x5f\x7d\xe4\xdd\xea\x0a\x5b\xa5\x8d\x32\x82\xed\x34\x99\xe3\xa9\xa1\x50\xb8\x44\xd6\x18\xa1\x27\x16\x5f\x8b\x1b\x8a\x0e\x00\xf0\x9e\x79\xed\xc8\xd7\x5c\xe6\x76\xaa\xc0\x8d\xaf\x1d\xf9\x9a\x83\xa0\x4d\x86\xdc\x95\xe2\xf2\x33\x7b\x65\x4b\x19\x61\x8f\x74\x10\x8b\x9e\x33\x6b\x30\x5e\x5f\xaf\xfa\x9a\x55\x5f\x07\xd5\xd7\xbe\xf6\x8a\xb0\x66\x93\xcf\x33\x30\xcf\xe8\xc9\x0c\x5e\xc1\x5f\x7a\x0f\x3a\x6a\x6d\xab\x2e\x68\xef\x99\xf1\x3e\x30\xde\xfb\xfa\x3b\xd2\xe0\x95\x28\xa9\x74\x84\x65\x89\x5a\x2a\x5d\xe1\x14\x5f\xed\x4a\x61\x74\xa5\x30\xba\x52\x18\x5d\x29\x8c\xae\x14\xaa\x2b\x85\xd1\x95\x42\x75\xa5\x30\xba\x12\x49\xb6\xab\x7a\x92\x57\x3b\x92\x57\xfb\x91\x57\xbb\x91\x57\x7b\x91\xcb\x4e\xe4\xd5\x3e\xe4\xb2\x0b\xf9\x6f\x3b\x2f\xbf\x14\x19\x89\x65\x99\xf4\xb7\xae\x8b\xbc\x79\x11\x21\x05\x2c\x9d\x58\x44\x0f\xfa\x32\x23\xaf\x2e\x93\xc4\x36\x1d\xfd\x67\xd0\x9f\x6f\x9b\x2e\xa4\xc1\x03\x99\x55\xe9\x08\xcb\xca\x8d\xe9\x48\x6c\xcb\xa4\xff\xcc\xb2\xc8\xb7\x2d\x23\xa4\xc1\x03\x99\x55\xe9\x4a\xa1\xba\x52\x18\x5d\x89\x9a\x27\xbb\x4e\x0a\x79\x33\xdd\x20\x05\x2c\x83\x1f\x54\xfa\x90\xcb\x2e\xe4\xbf\xed\xbc\xfc\x12\x64\xc4\x6d\x66\x09\xdb\x91\x15\xa4\xd5\x35\x9a\x56\xab\x4f\xab\x7d\x49\xab\x3d\x4d\x9b\xd6\x68\x6a\x5b\xa3\x77\x6e\x09\x89\x6a\x3c\x73\xdf\x33\xcf\xe5\x9a\x50\x4b\xab\x42\x2d\xad\xae\xc7\xb4\xba\x78\xd3\xea\xd2\x4e\x9b\x84\x5a\xda\x24\xd4\x12\x1b\xf3\x4c\x0d\xe6\x99\x1a\xb3\x9e\x1a\x54\x92\x1a\x54\x94\x36\x33\xcf\xb4\x99\x79\x26\x36\xa1\x96\x1a\x42\x2d\x35\x56\x63\x6a\xac\xde\xd4\x58\xdd\x69\xb3\x50\x4b\x9b\x85\x5a\x62\xe1\xe3\x7f\x1f\x8d\xfc\xb6\xf3\xf2\x4b\x91\x91\x58\x96\x49\x7f\xeb\xba\xc8\x9b\x17\x51\x83\x50\x4b\x9b\x84\x5a\x62\x63\x9e\x75\xf4\x5a\xd0\x9f\x6f\x9b\xae\x46\xe6\x99\x36\x33\xcf\xc4\x26\xd4\xea\x64\x6f\x59\x16\xf9\xb6\x65\xd4\x28\xd4\xd2\x66\xa1\x96\x58\xf8\x78\x6d\xb2\xeb\xa4\x90\x37\xd3\x4d\x03\x1f\x4f\x9b\x84\xda\x6f\x39\x2f\xbf\x04\x19\x71\x9b\xd9\x2f\x2b\xa1\xd6\xaf\xae\xd1\x7e\xb5\xfa\x7e\xb5\x2f\xfd\x6a\x4f\xfb\x4d\x6b\xb4\x6f\x59\xa3\x05\xdc\x4b\xb5\xbd\x54\xdb\x4b\xb5\xbd\x54\xdb\x4b\xb5\xbd\x54\xdb\x4b\xb5\xbd\x54\xdb\x4b\xb5\x5f\x3e\x2f\x7b\xa9\xf6\x5b\x71\xcf\xbd\x54\xfb\x3d\xe7\xe5\xbf\x55\xaa\xb5\xf6\x52\x6d\x2f\xd5\xf6\x52\x6d\x2f\xd5\xf6\x52\x6d\x2f\xd5\xfe\x05\x52\x0d\xdd\xa2\x36\x79\x2e\xa1\x8c\xf3\x87\x6e\x69\x2c\xa1\x12\x2a\x74\xdd\x42\x27\x47\xa1\x6e\x1f\x43\x8b\xab\x0f\xdb\x76\xdc\x2e\x66\xa3\xe8\x59\x46\xc1\x28\x35\xd3\x78\xe0\xc2\x5d\x52\x4b\xb7\xb9\xfb\xc8\x2a\xd3\x0b\xe6\x46\x41\x66\x00\xca\xbb\xf7\xeb\x4a\xb6\x5e\x51\x92\x4c\x2e\x0f\xcf\x24\x0c\xef\xb4\x88\x4d\x7a\x52\xa9\x25\xcd\x21\x08\xa6\x90\x1a\xb1\x2d\xf9\x2c\x04\x00\xdd\xb3\xb0\xfd\xd5\x94\x8c\x26\xf0\x68\x78\xc1\x3d\x64\xd3\xcc\x0c\x8b\xf0\x98\x4e\x8f\x78\x1f\xc1\x5b\xac\x47\x9a\x2a\xf1\x17\x99\x03\xae\xf8\x37\xa1\x2a\x90\x73\x6e\x00\xf8\x7a\xc8\x5e\x0d\x52\x98\x6b\xbe\xbe\xce\xac\x06\x29\x62\x39\x9a\x90\x05\xac\x81\x8a\x90\x87\x3a\xa8\x37\x72\xdb\x4e\xcf\x7f\x74\xb1\x19\x60\x4e\x19\xbe\x29\xad\x4c\x0b\x8f\xa7\x82\x12\x63\xe4\x79\x4e\x0f\xb9\x92\xc0\xdd\x84\x10\x0a\xe6\x11\x51\xf3\x27\x77\xed\x12\xda\xdb\xb8\x0b\x97\x92\x88\xc8\x29\xe0\x13\x27\xcb\x8d\xfb\x9e\x5a\x9b\xeb\x39\x7f\x6f\xa1\x56\x73\xa1\x96\xa5\x10\xf0\x43\x1d\x34\x07\xdd\x36\x0f\x4b\xc8\xdf\x69\x44\xc0\x4b\x46\xce\x2a\xbc\x90\x2f\xbe\xa5\x63\x40\x2d\x15\xd4\x88\x42\x9d\xda\xa0\x4e\x15\xd4\x1a\x82\x88\x70\x15\x97\x62\x9a\x25\xbe\xfb\xff\xff\x1b\x00\x00\xff\xff\xb4\x36\xa3\x31\xcc\x09\x01\x00")
+
+func uiAppLibBootstrap400Alpha6DistCssBootstrapMinCssMapBytes() ([]byte, error) {
+ return bindataRead(
+ _uiAppLibBootstrap400Alpha6DistCssBootstrapMinCssMap,
+ "ui/app/lib/bootstrap-4.0.0-alpha.6-dist/css/bootstrap.min.css.map",
+ )
+}
+
+func uiAppLibBootstrap400Alpha6DistCssBootstrapMinCssMap() (*asset, error) {
+ bytes, err := uiAppLibBootstrap400Alpha6DistCssBootstrapMinCssMapBytes()
+ if err != nil {
+ return nil, err
+ }
+
+ info := bindataFileInfo{name: "ui/app/lib/bootstrap-4.0.0-alpha.6-dist/css/bootstrap.min.css.map", size: 68044, mode: os.FileMode(420), modTime: time.Unix(1, 0)}
+ a := &asset{bytes: bytes, info: info}
+ return a, nil
+}
+
+var _uiAppLibFontAwesome470CssFontAwesomeCss = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd4\x7d\x51\x8f\xeb\xb8\xb1\xe6\xfb\xf9\x15\xda\x19\x64\xe7\xcc\xa0\xd5\xa7\x25\xbb\x6d\x77\x5f\xdc\xbd\x99\xdd\x20\xd8\x00\xc9\x26\x40\x26\xc0\x3e\xec\x0b\x45\x95\x2c\x1e\x53\xa2\x86\xa4\xdc\xed\xb3\x98\xff\xbe\x90\x64\x5b\x9f\x64\xb3\xd4\x0b\xcc\xcb\x6d\x04\x39\x63\xe9\x63\x89\x14\x8b\xc5\xaa\xe2\x47\xea\xcb\x4f\xff\xe5\x53\xf4\x53\x14\xfd\xd9\xd4\x3e\xfa\xf9\x8d\x9c\xa9\x28\x5a\x3f\x6e\x1f\x9f\xa2\xec\x14\xfd\x31\x17\x47\xda\x8b\x3a\x3f\x45\x71\x54\x7a\xdf\xbc\x7e\xf9\x52\x98\xda\x8b\x01\xf8\xa8\x4c\x14\x47\x7f\x84\x2b\xbd\xac\xbf\x2a\x49\xb5\xa3\x50\x91\x2f\xfa\x7c\xff\x73\xf7\xd0\xd7\xe8\x9f\x7f\xf9\x6b\xf4\xf7\x3f\xff\x35\x4a\x1e\x93\x87\xe8\x7f\xfc\xf3\x9f\xaf\xd1\xdf\xfe\xf2\xcb\x45\xc8\x8f\x9f\xa2\x9f\xbe\x7c\xfa\xf2\x53\xf4\xe7\xbf\xff\xaf\x5f\xa2\x7f\xfc\xfc\xcb\xff\xec\x1e\x11\x07\xff\x3a\x74\x5f\xa1\xb8\x10\x92\xa2\xff\xfb\x29\x8a\xce\xbf\x2a\xa5\x4f\xaf\xd1\x0f\xdd\x33\xcf\xed\xfc\xe1\xdf\x3e\x45\x91\xb3\xf2\x35\x6a\xad\xfe\xfc\xc3\xe3\x63\x5f\x51\x87\xd5\x8d\xdf\x28\xeb\x7e\x3e\x92\xf1\xff\x71\xfc\xf7\xfe\xc5\xfc\xf0\xe3\xff\x67\xb9\xef\x15\x15\xea\xfd\xbf\x5e\x8b\x47\x85\xb1\x95\xf0\x9f\x7f\xa0\x2a\xa3\x3c\xa7\x3c\x36\x0d\xd5\xfe\xd4\xd0\x0f\x3f\x3e\x7c\x40\xe6\x9b\x29\x8a\xf4\x3f\x6e\xc5\xf5\xd7\x3f\x2e\x22\x20\xe1\x63\x02\xbc\xbf\x57\xde\xdb\x96\x3e\xde\x0e\x77\xdc\x5f\x64\x7c\x0f\xf7\x2d\xed\x5b\x2d\x2c\x88\x75\xc7\xfd\xf0\xd2\xfb\xae\x7c\x23\xb5\x2f\xfd\x6b\x54\x77\x77\xf5\xf5\xb2\xf3\x27\x4d\xe3\xd5\xdf\x3e\x3d\x16\xa2\xef\xff\x5c\xb9\x46\x8b\xd3\x6b\xa4\x6a\xad\x6a\x8a\x33\x6d\xe4\xe1\x52\xec\x52\x60\xf6\x4f\xb2\x6e\xde\xbf\x24\x11\x28\xcb\xf8\x1c\xf5\x8d\x3a\x59\x25\x59\xe5\xbb\xab\x9e\xde\x7d\x6c\xa9\xce\xc9\xaa\x7a\xff\x1a\x89\xd6\x9b\xee\x7a\xd7\xce\x83\xf2\xf1\x50\xaa\x32\xc6\x97\xc3\xfd\xda\x2b\xa1\x95\x70\x94\xf7\xb0\xca\x7c\x8b\x8d\x7b\xbf\xc1\xed\xad\x38\x39\x29\x34\x75\x8d\xf9\xf2\x53\x54\x89\x03\xb9\xc8\x97\xd4\xd7\x23\x5a\xad\xfe\x10\x69\x61\xf7\x64\x23\x4b\x5a\x78\x75\xa4\xc8\x9b\xfe\xbe\x92\xa6\x8e\x64\xf7\x46\x55\x4d\xb6\x1b\x12\x8f\x85\x88\xf5\x7e\x1c\x0e\x43\x23\x92\xc7\xd5\xf9\x8f\xaa\xae\x2a\xfd\xeb\x29\xcf\xaf\xf7\xe9\x71\xfb\x3c\x5c\x3e\x92\xf5\x4a\x0a\x1d\x0b\xad\xf6\xf5\x6b\x14\x27\xcf\x7f\x38\xbf\xe0\x38\x7d\x9f\x0b\x4d\xbb\x42\xc3\xcd\xd5\xcd\xcd\xd5\x78\x73\x7d\x73\x73\x3d\xde\x7c\xbe\xb9\xf9\x3c\xde\x2c\xde\xfa\x9b\x6f\x2a\xf7\x65\xd7\x88\x74\xf7\xbc\x4d\xd6\xe9\xcb\x50\xdb\xbe\x3b\xce\x35\x95\x54\x7b\xb2\x97\x72\xad\xee\xcb\x35\x22\xcf\x55\xbd\x8f\x35\x15\x5d\x33\xbb\x32\x95\xb0\x7b\x55\x9f\xaf\xa4\x8f\xc9\x7a\x10\x79\x79\x2b\xee\xac\x5d\x71\xa7\xdb\x9d\xc6\xd4\x04\x32\xff\x5b\xa4\xd5\x20\xd8\x38\xe5\x95\xa9\x5f\xaf\x1d\x72\x41\xdd\x00\x44\xe6\x8c\x6e\x7d\xaf\x55\xc3\x53\xe3\xf9\x63\xcf\xcd\x9b\x5f\xf6\xa6\xe9\xfa\x66\x76\x31\xd8\x66\xad\xa0\xeb\xcf\x4f\x4a\x1e\x87\x17\xb6\xdb\x8c\xef\x34\x33\x36\x27\x8b\xef\xe7\x35\x7a\x4c\xa9\x8a\x1e\xd3\xe7\xee\xff\x93\xb3\x2e\x0c\xb8\xd7\xc8\x19\xad\xf2\xe8\xe9\xf1\x69\x47\x55\xf4\x3d\xf5\x7f\xe3\xfd\xd8\x8a\x5c\xb5\xee\x35\x7a\x4c\xc6\x47\x34\xad\xd6\xfd\x2b\x1e\xba\x56\x1b\xe1\x5f\xfb\x2a\x4d\x00\xb6\xd3\x3e\x44\xf4\x17\xce\x90\x5b\x31\xe7\x9e\xb3\x83\xce\x3e\x8e\xfa\x75\x47\xe0\xa4\x97\x2f\xd0\x2f\x3f\x45\x7f\xa2\xc6\x92\x14\x9e\xf2\x48\xb8\xc8\x14\xd1\xfa\x71\xfd\xf8\xd4\x0f\x9b\xa5\x2a\x2d\xb5\xe9\xf1\xa3\xb5\xfd\x48\x55\xbb\x26\xb9\x46\xd5\x3d\xe2\x62\x5d\x44\xad\x2a\x31\x28\xd5\xe5\x76\xea\x22\x55\x17\xaa\x56\x9e\xfa\x21\x2d\x6c\xd7\x33\x1f\x04\x5e\xbb\xc2\xd1\xd2\x73\x12\x28\xee\x3c\x35\xee\xf3\xee\xc7\xc0\x93\xee\x43\x7f\xfb\xf4\xc7\x8b\xf8\x03\x9d\x0a\x2b\x2a\x72\x11\x36\xf2\xe9\x0f\xfd\x3f\x63\x2d\xbc\x15\xb5\xeb\xa6\x85\xd7\xc8\x1a\x2f\x3c\x7d\x7e\xca\x69\xdf\x3f\x35\x8a\x98\x9b\xbf\x7d\x8a\xa2\xe4\xe9\x03\xe2\x56\xcf\x2f\x9c\x40\xb8\xfd\x5b\x57\xfd\xff\x9c\xd5\xee\x7a\x78\xb8\x13\xbf\x3c\x0d\xbd\x5c\xb9\xb8\x50\xda\x77\x43\xfb\xbb\xc6\x9a\xbd\xca\x5f\xff\xf4\xbf\xff\x52\x89\x3d\xfd\x72\x91\xf6\xf8\x37\x25\xad\x71\xa6\xf0\x8f\xff\x5d\x38\x25\xfb\xbb\x9f\x7b\x39\xca\xd4\xff\x9e\xfc\xf8\x1d\xce\x7a\xb7\x95\x78\xb9\x36\xab\x7b\x1a\x77\x3f\x7c\x6f\x52\xf7\x64\xf7\xbb\x55\x3e\x5d\xaa\x7c\xb2\x5b\xa8\x3d\x00\x98\x9b\x93\xfa\xa7\xdb\xdf\xad\xfe\xab\xa5\xfa\xa7\xdb\x85\xfa\x03\x80\xb9\x79\x9e\x80\xb5\x6a\xe2\xd2\x58\xf5\xad\xf3\x31\xf4\xef\xd5\x88\xa7\x87\xa8\x52\xd6\x1a\xcb\xe8\x52\xef\x10\x7d\x8e\x93\x87\x28\xb9\xd7\x98\xf9\xed\xe0\x2d\x68\xc8\xc5\xbd\xf9\xdd\x74\xe9\xc3\xcd\x48\x1e\xa2\x98\x69\xc6\x78\x3b\x78\xeb\xb7\x4f\xaf\xd6\x18\x1f\x4d\x46\xf4\xc3\xed\xc5\x64\x77\xef\x6a\xba\x9d\x5c\x9d\x75\xeb\xcd\xad\xc9\x8b\xba\xbc\x24\x74\x86\x9c\x17\xf2\x10\x74\x85\x18\x4f\xfc\xe2\xeb\x0c\x3e\xc6\xc5\x03\x4d\xef\x78\xa5\xe9\x7d\x97\xb4\x52\x79\xae\xa7\xf5\x88\x93\xf7\x07\xf8\x75\x76\x54\x39\x17\xec\x09\xaa\xd2\x59\x5d\xde\xb3\xba\x3c\x64\xf0\xac\xb0\x8e\xd7\xd8\xe0\xb7\xdb\xe7\xdf\x77\x94\x55\x7d\x24\x7b\x9e\x70\xa5\xd1\xc6\xbe\x46\xdf\x17\xfd\xdf\xd9\x45\x99\x84\xe7\xad\x3b\xc7\x01\xff\xaa\x95\x34\x39\x45\xff\xb0\xea\x28\x3c\x45\xff\x72\x14\xfd\x6c\x49\x44\x9f\xff\xf1\xaf\x9f\x7f\xec\xa2\x01\xaa\x5d\x6b\x29\x72\xd2\x12\xd5\xdd\xe4\x60\x49\xe4\x64\x5d\x94\x9b\xa8\x36\xbe\xff\x19\x99\xa2\x88\xac\xa8\x73\x53\x45\xb2\x14\x56\x48\xdf\x21\x7c\x29\xba\xfb\x8d\x25\x47\xb5\xef\x63\x0a\x77\x09\x25\xf6\x5a\x38\xf7\x9a\x51\x61\xec\xa5\xd2\xb5\xa7\x2e\x9a\xfa\xee\xff\x14\x4f\x4f\x4f\xdf\x5d\x1a\x56\xb5\x4e\xc9\x30\x30\xb9\x02\x1d\x09\x2b\xcb\x30\x32\xbd\x22\xa9\x3e\x92\x36\x0d\xc5\x26\x8c\x5e\x5d\xd1\x25\x09\xeb\xc3\xc0\xf5\x77\xd0\x4b\x36\x8c\x7b\x9e\xe0\xb8\x47\x6f\xae\xc8\xd6\x11\x23\x71\x7b\xc5\x15\x4a\x57\x61\xdc\xee\x8a\xf3\x65\xdc\xc7\x7b\x61\xec\x0b\x60\xc3\x28\x31\x91\xa8\x1c\xf3\x7a\xb2\x2b\x54\x96\x24\x0f\x61\xa0\xbc\x02\x2d\x55\xe6\x78\xa9\xe3\x30\x00\xa5\x36\x6e\x7a\xc5\xab\x8a\x18\xfd\xc9\x67\x6a\x11\x37\xba\x65\xe0\x34\x87\x57\xaa\x66\xf0\xc9\xa8\x9e\x8d\x79\x23\x1b\x9b\xa2\x08\x83\x41\x45\xd5\xbe\x16\x3a\x8c\x1c\x55\x74\x4f\x57\x5d\x3a\xbf\x01\xb3\x0f\x97\x1b\x95\xd5\x5b\xe1\x4a\x46\xb9\x92\x51\x5d\x4b\x53\x85\x15\x21\x79\x46\xe5\xe2\x46\x4a\x32\xaa\xab\xec\x8c\x31\x07\x1d\x35\xd6\x1a\x91\x87\x71\xa3\xc6\xe6\xe6\xad\xd6\x2c\x76\xd4\x58\x61\xad\x79\x8b\xa5\xb2\xb2\xab\x70\x5f\x34\x5c\x4c\x84\x8a\xb5\x4d\xb8\xd0\xa8\xcc\xaa\xce\xcc\x7b\x18\x38\x2a\x73\x37\x5b\x5d\x85\x87\x0b\xe4\xdf\xcd\x3c\xbb\x21\xc0\x43\x0d\xb0\xd4\x90\x08\x8f\xb4\x84\x60\x00\x15\x96\x5c\x78\xfc\xa6\xa3\x46\xf6\x99\x09\xa1\xc3\x62\xd3\x51\x27\xbb\xde\x0d\xe3\x46\x1d\x2c\xb4\x08\xeb\x6a\xba\x46\xc3\x9a\x37\xa5\xa9\x99\x71\x9c\x8e\x6a\x78\x34\xba\xad\x88\x1d\x69\xe9\x66\x8e\x66\x75\x20\xdd\xce\xe1\x4c\xdf\xa7\xa3\x4e\xfe\x6a\xbb\x29\x33\x8c\x1c\x35\x32\x13\x0b\x50\x30\xa4\xdc\x3b\xcb\x10\xc6\xbc\xad\x51\xed\x32\x63\x98\xbe\xca\x27\xb8\x4a\x58\x06\x3b\xaa\x55\x63\x55\xcd\x28\x4a\x31\xda\x01\x51\x91\x15\x41\xe4\x6a\xb4\x9e\x7d\xfe\x34\x88\x4b\xa0\x9a\x3a\x6c\x02\x56\xa3\x8a\x2a\x2f\x34\xe3\x2d\xac\xc0\x50\x76\x5e\xd9\xd9\xdd\x0a\xc2\xd7\x53\xf8\xe0\xd8\x05\xd1\xa3\xae\xf6\xde\xde\x90\x7a\x09\xa2\x37\x33\xf4\xe0\x1a\x86\xf1\xdb\x19\xde\xf2\x55\xdf\xcd\xe0\x5f\x5b\xe7\x55\x71\x0a\x17\x78\x99\xd8\x84\x30\x6e\x54\xd9\x9c\x72\xaa\xa7\x36\xca\xb4\x1e\xae\xdd\x29\x8d\x16\x94\x47\x8e\xba\x7c\x54\x39\x99\x45\xa5\x1a\x75\xba\x29\x8d\x37\x93\x6a\xa9\x2e\xbc\x9a\x5c\x69\x94\xf4\xad\xe5\x4c\xf2\x0a\x14\x9f\x6a\xa9\xc2\xd3\xf6\x1a\x9c\x55\xd1\xc4\xdd\x70\x62\x3a\x72\x3d\x6a\xb5\xc8\xbb\x5e\x09\x23\x47\xbd\xf6\xdc\xc8\x5b\x8f\x5a\x4d\xb9\x9a\x76\xc8\x50\xf5\xd8\xfd\xda\x0a\xb6\xb5\x6b\x70\x63\xcb\x0e\xba\x5c\xe2\x79\xea\xd9\x7d\xa0\xc4\x66\x3a\xe7\x86\x0d\xd9\x7a\x0b\xce\x32\x35\x71\x26\xe4\xe1\x4d\xd8\xb0\x09\x58\x8f\xea\x5e\x08\xe7\x3f\x50\x00\x8d\xf4\x12\x56\x4c\x66\xf3\x30\x6e\x54\xee\x46\xb4\x2e\x6c\xf6\xd7\x12\x9a\x67\xc2\x73\xce\x3a\x07\x43\x69\xf9\x3a\xd2\xf4\x05\x2c\xe1\x9f\x9f\xa6\x6f\x78\x11\x3f\x6a\x2d\x7d\x25\x19\x56\xc6\xe7\x14\xd5\xe2\x68\xcd\x82\x1d\x7c\x5e\xdd\xe0\x79\xcb\xf6\xbc\x86\xde\x68\xdd\xd9\xb7\x0a\xc3\x47\x35\xed\x7d\xfa\x45\xfc\x06\x06\x5d\x45\xcb\xf8\xed\x6c\x18\x2c\xe1\xc1\x8f\x68\xc9\x79\x65\xea\xc5\x22\x2f\x60\x34\x0b\xb3\x08\x1f\xd5\x55\x5a\xe3\x5c\x29\x94\x0d\x0f\xb5\xe7\xec\x6e\x7b\x99\x61\xfc\x2c\xef\xb6\x98\x2b\x01\xfe\x86\x08\xfb\x63\xcf\x34\xf3\xc9\x59\xc5\xd9\x3c\xcd\xd0\xbc\xda\x6c\x92\x19\x9c\xf1\xf5\x36\xe9\x0c\xcb\xba\x91\x9b\x15\x98\x7f\xa5\x67\x43\xe9\x61\xb4\xa9\x61\x09\xa3\x4a\xd3\x7b\x23\xea\xf0\x30\xdc\x80\xd1\x35\x55\x63\x89\xc9\xa1\x6c\x36\x93\x81\x12\xc6\x6d\xa7\x23\x24\x0c\x04\x9f\xc2\x79\xb2\xca\x85\xdd\xc6\xcd\x0b\x34\x49\x6a\x31\xac\xe6\x2c\xa9\xee\x66\x54\xdd\xbd\xe2\xfa\x7e\x54\x5a\x4d\x22\x1c\x10\x6c\x24\x44\xb1\x5c\x07\x8c\x0a\x4a\x27\x06\x46\x08\x8b\x9d\x16\x4c\x90\xb5\x1d\xf5\xf3\x4d\xd8\x5a\xd5\xfb\x89\x46\xe0\x5b\xf1\x56\x89\x7a\xcf\xbc\x97\x6d\x82\x33\x50\xcd\x00\xc1\xfa\x0a\x4d\x75\xce\x64\xa4\xb6\xa3\xde\x0e\xa9\xbb\x30\x72\x8d\x5a\x57\x71\x6e\xdb\x16\xcc\xad\xd8\xd7\xc4\x20\x37\x37\x86\x9f\x19\x92\xdb\xed\x0d\x9a\x1d\x94\xdb\x1d\x44\xc3\xfe\x8d\xb8\x8a\xbc\x80\xeb\x63\x9a\x46\xd5\xfb\x58\x72\x29\xbf\xad\x80\x69\x59\xe7\x8c\xaf\xb7\xcd\x66\xc8\x9e\xa6\x13\x86\xcb\x99\x83\x14\x1f\xc3\xd8\x7c\x8e\x65\x54\x91\x30\x22\x8d\x65\x29\xac\x8f\xa7\x1e\xf2\xf5\x7a\x50\xc8\x6e\xd4\x67\xff\xa6\xbc\x27\x7b\xf6\xf8\xc2\x25\x12\xf0\x49\x24\x75\xa1\xe6\x62\x91\x74\x16\x44\x76\xbd\x67\xc3\x33\xcb\x6e\xd4\xe1\x03\x85\x3d\xb3\xdd\x7a\x92\x58\x73\xf3\xcc\x5a\xd8\xe6\xed\x9e\xe7\xaa\xcf\x60\xc1\x75\x28\xdb\x2a\x73\x7c\x36\x69\xb7\xbd\x85\xb3\x3a\xbd\xdb\x4d\x53\xc8\xa5\xd0\x61\xd3\xb7\x7b\x99\x26\xb0\x99\xe9\x79\x27\x26\x09\xca\x2e\x88\x0b\x63\xc1\xf2\xaa\xfa\x40\xb9\xaa\x17\xfb\x54\x4e\xdb\x19\x7b\xc1\xe4\x91\x76\x60\x8a\xdf\x3d\xd9\x5a\xe8\xfe\x49\xe1\x02\x34\xad\xbd\x0a\xbf\xc0\x17\x50\x61\x6b\x9a\x32\xac\x30\x2f\x09\x4c\x44\xbe\x6c\xb3\xa5\x46\xbe\x8c\x8a\xdb\x36\x6c\xc2\xf2\x65\x05\x73\x57\x65\x6a\xa6\x63\x5e\xd6\x18\xd3\x32\x66\xff\x05\x16\x17\x96\xa2\xb0\x97\xcd\x4d\xf2\x87\x43\x6f\xa7\x55\x58\x7c\x0f\xbb\xb9\x95\x08\x43\x5f\x6e\xcd\x43\x31\x19\x99\x97\xcb\x61\x11\x62\xd6\x4d\x61\xe4\xa8\xb7\x6d\xcd\x26\x32\x5f\xc0\xbd\xb5\x5d\x3c\xdd\x4d\x06\x4c\x77\x42\x8c\x46\x34\xf5\xfa\x2c\xe3\x9d\xbd\x8c\x6a\x5b\xe6\x39\xd3\x03\x62\x54\xda\xac\xd5\xba\x34\x36\xac\xe0\x02\x32\x66\xa4\xc3\x19\x8b\x02\x82\x2e\xb2\x5e\x15\x4a\x0a\x1f\xee\x54\x01\x8b\x61\xa2\xce\x63\xb3\xe0\x6b\x8b\xf5\x1c\xcf\x7a\xf2\xe2\x79\x0e\x67\xac\xa6\xd8\xcc\xc1\xac\xcd\x14\xdb\x99\x2b\x7f\x0e\x56\xf8\x0a\xed\xee\x17\x5a\x68\x75\x60\x25\x82\x6b\x4c\x60\x15\x82\x6f\xd2\xa8\xca\x7b\x6d\x32\xa6\xdb\x46\x4d\x7e\xb3\x54\x33\x6b\xa3\x22\x87\x04\xb3\x3b\x84\xb5\x56\x40\x9a\x61\x58\xbd\x0f\x21\x33\x50\x5b\xab\xa8\x90\x82\x49\x88\x64\xc9\xdc\x99\xe1\x96\x24\x32\x58\x26\xb3\xe6\xfa\x7a\x87\x31\xd7\x3a\x62\xa2\x5d\xf9\x04\x6e\xa4\xb8\x4e\x15\x0f\xd7\x09\x2d\x5c\x72\xac\xa2\xd4\xa6\x0d\x1b\x04\x39\xd6\xae\xd0\x82\x09\x91\x24\x0c\xc2\x76\x9a\xb5\x73\x52\x39\x67\xb8\x76\xa0\x47\xde\x9c\xa6\x56\x53\x69\x72\x8c\x41\x91\xcf\x90\xa6\x6a\xc8\x4a\xad\xc2\x1a\x2a\xc7\xe1\xe6\xc4\x6c\x51\xb6\xd0\xa6\x69\x4e\xdc\x93\xb6\xb3\x69\x29\x8c\x1c\x47\x5c\x2d\x8e\x4a\x9a\x69\xcf\x58\x1a\x38\xa3\x33\x8f\x95\x79\x3f\xd3\x6c\x76\xdc\x86\x6d\xa1\x14\x53\xa8\x61\xa0\x19\x38\x60\x56\x1d\xc8\x97\xd6\xb4\xfb\xf0\xb8\x92\x12\x66\x9d\x9c\xac\x56\xcc\x24\x2e\x71\x10\x66\x4c\x34\x28\x09\x63\x2c\x66\xb9\x23\x47\x7f\xa7\x65\xe6\xbc\x1c\xe2\x4b\x55\x7b\xb2\xc4\xa4\xa5\xf3\xf4\x16\xbc\xd4\xbf\xf9\xa8\xeb\x7b\x63\xf6\x9a\x86\xdc\xdd\x52\xa9\xf5\xbd\x52\x61\x38\xc4\x9e\xa6\x66\xc2\x81\x1c\x42\x4f\x61\xc9\xf3\xf6\x36\xdf\xce\xd0\x8c\x41\xcf\x77\x33\x2c\x3b\xcf\xe4\x2f\x33\x34\x3f\xc1\xe4\x90\xd8\x33\xba\xad\x6a\xe6\x55\xa0\xbb\xe3\x8c\xf5\x33\xcf\xa4\xbb\x14\x2e\x0c\xe9\x69\x63\x27\x6f\xe7\x01\xae\x92\x63\x34\x2f\x9f\x8a\x98\x19\xe9\xfe\x9a\xe0\xca\x43\xa6\xe5\x4c\xd6\x09\x62\xe9\xe9\x26\x24\x09\x63\x47\x45\x3f\xaf\xb3\x43\x07\x3d\x5c\x06\x6a\xd8\xa2\x11\xac\x86\xd3\xfe\x4a\xe5\x18\x4a\xee\xc5\x91\xc2\xc6\x83\xc6\x21\x90\x0b\x57\x66\x66\x9e\x23\xf4\x42\x96\xa6\x22\x6e\x52\xa5\x9b\x44\x0c\x63\x7d\xe9\x36\x74\xe5\xd0\x9b\xc9\xb4\x55\x4e\x6d\xad\x61\xa6\x63\x02\x2b\xaf\x3c\x55\x22\x3c\x3c\x68\x1c\x1e\x6d\x95\x59\xd2\x3a\xbc\xa0\x47\x2f\x30\x4d\x39\x3f\xe7\x03\xa9\x06\xdf\xe0\x9d\xe2\x68\xd6\xf7\xa5\xcf\x5a\x9d\x71\xcd\xcf\x30\x5f\x59\x8a\x9a\x21\x49\x91\x9c\xba\x02\xcb\x24\x15\xca\x67\x25\x16\x62\x44\x1a\xd5\xbf\xf3\x67\xe2\x2a\x0c\x2d\x26\x0b\x39\xbe\x34\x4e\x72\x83\xa5\x00\x32\x52\xab\x3c\xeb\x95\x15\xe9\x24\x9a\xe0\x62\x14\x48\xdb\x98\xa2\x20\x46\xe6\x1a\x9d\x1e\x4d\x36\x6c\xa5\x8b\x19\x05\xa9\x5f\x82\x0f\xd7\xa1\x80\xb8\xb6\x55\xba\xdf\x9f\xc3\xa0\x47\xa5\x2d\x8d\x6b\x94\x17\x5c\xfb\x0a\x08\x08\xaa\xac\xd5\xa2\x96\x4c\x13\x47\xc5\xad\x28\x3f\xa8\xf0\xc8\x29\x20\x91\xd8\xe9\x28\xd9\xf8\x2b\x93\xa8\x2c\x32\xe8\x0f\xc6\x4a\x14\xa3\x7e\x96\x4b\x53\x6c\x01\xcb\xe6\x1f\x98\x91\x0b\x58\xa2\xa9\xf7\x7d\xa4\xd2\x66\x0b\xe1\x54\x02\x64\xce\x49\x21\x76\xb6\x4b\x80\xd9\x39\x29\x15\x9e\x7d\x13\xa0\x78\x4e\x8a\x70\xd3\x7b\x02\x4c\xcf\xa1\x10\xdf\x96\xf5\x0c\xbd\xd0\x88\xe7\x19\x9c\xab\xfd\xe6\xa6\xf6\x5c\xb5\x47\x05\xce\xc9\x1d\x98\x65\xe4\x04\x08\xa0\x5a\x34\x2c\xf2\x65\xea\x82\x32\x0d\x13\xe0\x6b\x65\xdd\xf0\xc4\x0c\xd5\x03\xdc\x08\x8b\x00\x6a\xe8\xc2\x0a\x62\x02\xec\xd0\x5f\x5b\xe3\x97\x3a\x29\x9f\xa1\x17\x3a\x09\x32\x88\x8d\xaa\xeb\xf0\xd0\x4a\x80\xf8\xc9\x2f\x65\x25\xc0\xfa\xec\x57\x05\x2d\x35\xfa\x34\x0b\x6a\xc6\x2b\x77\xca\xa7\xf3\x0c\x24\x13\x12\x27\xc0\x00\xbd\x2c\x34\x84\xb1\xeb\x1b\x6c\x43\x4c\x1a\x32\x01\x2e\xa8\xab\x58\x32\x68\x02\xcc\xcd\xc2\x9a\x37\x56\x2a\x9a\x49\x86\xb2\x9a\x00\x55\x73\x2f\x2a\x6a\xc2\xf3\x66\x02\x04\xcd\x03\x9d\x7a\x07\x81\x13\x2c\xd1\xe5\x61\x66\x8b\x04\xe8\x99\x3d\xb2\x5f\xf7\x26\x4b\x4c\x4d\x46\x9d\xf2\x64\x2b\xc5\xd0\x7e\x93\x14\x94\x8a\x61\x0b\x26\xe9\x3d\x95\x8a\x85\xd6\xb7\x6a\x05\x57\xef\xc8\x49\xc1\x65\x38\xaf\x23\xc4\x54\x35\x7e\xaa\x9f\xe3\xbd\xa2\x9d\x3d\x63\xbc\x15\x7e\x67\x40\x08\xd5\x46\x0e\x0b\x9d\x7d\x72\x27\x5c\x02\x7c\x03\xcb\x58\xa9\xf4\x79\xf2\xbe\xe2\xc2\x84\xf9\x8b\x09\x70\x42\xdb\x1a\x32\x3c\x0f\x63\x12\x28\xce\xac\x39\x84\x97\xe5\x12\xe0\x89\x5e\x28\x1b\x61\xec\x38\x00\x54\x5d\x30\x6f\xe7\xee\xfa\x78\x18\x0e\x4b\x34\x6d\x43\xd6\x49\xab\x9a\xb0\x39\x00\xc2\xa8\x6b\xb3\x25\xf0\x38\x0c\xc8\x0a\x66\xc7\x41\x02\xbc\xd1\xa6\xfd\xf6\xad\x33\xfa\x8a\xc2\x9e\x50\x02\xdc\xd1\x4a\x75\x5d\xca\x2d\x62\x24\x40\x0b\x1d\xd1\xfc\x22\x7b\x02\x14\x51\x57\x2a\x0a\x93\x44\x93\xd5\xed\xca\x38\xa3\xbc\x40\x14\x2d\x94\xa5\x98\xde\xbd\xaa\xf7\xad\x72\x25\xf3\x7a\x80\x2e\x6a\x8d\x3c\x30\xb3\xe7\x0a\x57\xc9\xdf\x65\x1e\xee\xf8\xd5\xed\x2a\xf9\x07\x32\xd8\xc9\xea\x76\xb9\xfc\x23\x39\xec\x04\x68\xa3\xb3\x72\x8c\xe3\x02\xd4\xd1\x59\x21\xd6\x83\x01\x26\x69\xe9\x2b\xfd\x1c\x06\x82\xa3\xe0\xdc\x2a\x8c\x83\xe5\xf3\x5a\x96\x86\xe9\xa9\x1c\x8d\x82\x91\x07\x76\x72\x05\x26\x68\xd6\x6a\xed\x18\x8a\x48\x02\x5c\x50\xd2\x5a\x35\x4e\x31\x0b\xf3\x09\x70\x41\xaf\xe8\xe0\x92\x7f\x02\x7c\x50\xeb\x96\x5c\xf5\x04\x58\xa1\xb0\x07\x21\x0c\x07\xae\xb3\x62\x95\x77\x3d\x67\xd4\x2d\x55\x64\x73\x17\xcf\x8c\x3e\xa0\x7f\x6a\x3a\x92\xe6\x94\x0f\x98\x9f\x03\x96\xd5\xb9\xf5\x44\x55\xe5\x12\x1f\x21\x41\xea\x27\x32\x69\xc3\x05\x30\x8f\x00\xcb\xd7\x8b\xe5\x20\xe7\x06\xfc\xdb\x30\x3e\xc7\xe4\x4e\xc3\xec\xa5\x4b\x80\x1a\xea\xcd\x7e\x16\x58\x3c\x40\xf6\xf1\xd2\x2f\xfc\x2b\x04\xe6\xe8\x59\xdc\x2c\xb9\x37\x13\xc6\xf4\x1d\x90\x4a\xcf\xa2\x6e\x77\xbd\xcc\xa4\xf1\xe6\x0b\xc8\xa7\xd4\xda\x29\xc3\x85\xda\xb0\x3d\x00\x12\xea\x3e\x63\xea\x3b\x8e\x91\xdc\x68\x3d\xdb\xa1\xd5\xba\xf0\xec\x03\x2c\x54\xdb\x36\x34\x8d\x93\x54\xcd\xd4\x0c\xec\x7f\x3d\x8b\x1f\xaa\x6c\xf2\xfb\x44\xd3\x4e\xfd\xda\x84\xa3\x0b\x60\xad\xda\x76\x5c\x6b\x38\x0b\x36\xb7\x97\xc2\x4b\xeb\x09\x30\x5a\xdf\x66\xeb\x36\x07\x1b\xf6\xf6\x80\xd5\x9a\x29\x2f\xcd\x6c\x31\x2e\xf3\xc1\xec\x70\xf2\x2c\x26\x99\xa1\x30\x2e\xbb\xcd\x20\x85\xc1\xb3\xac\xb7\xd0\x4d\x29\xb8\x24\x75\xf2\x9c\xdf\x2b\xc1\xe5\xc5\x13\xa0\xb8\x0e\x45\x2a\xd3\xd6\x6c\x2a\x3c\x01\x9e\x2b\x16\x61\x1f\x03\x64\xd7\xbe\x4c\xdd\x56\x64\x95\xe4\x9f\x93\xde\x2f\xc3\x3f\x08\x36\xd4\x0c\x1c\x26\x66\xb8\x03\xcd\xf5\x0c\x66\x0d\x0d\x70\x5d\x4f\xa6\xf5\x6d\xb6\x68\x14\x81\xf1\x7a\x2e\x11\x86\x8e\x03\xe0\x7d\xa4\x66\xde\xc1\xed\x26\xb8\xc5\x1a\xbc\xdc\xd4\x99\xdb\x32\x90\x00\xe1\x35\xb7\xa6\x61\xf6\x14\x26\x1b\x5c\x7c\x14\xf2\x10\x9b\x23\xd9\x42\x33\xf1\x14\xb0\x5f\x55\xed\xbc\xd8\x5b\x11\xe4\x78\x26\x1b\x0c\x71\x95\x3c\x84\x4d\x12\xb0\x60\x05\xe3\xb9\x02\xff\x35\x53\x3e\x6b\x59\x9f\x02\x08\xae\x57\xf0\xd2\xbb\x06\xae\xab\x6f\xab\x4c\x87\x6b\x0c\x4c\xd7\x01\xb9\x28\x7a\x0d\xb1\x6b\xbd\xff\x00\x0b\x3c\x01\xe2\x2b\x14\x61\x46\x03\xf0\x5f\xa1\x00\xeb\xd5\x03\x09\x16\x8a\xf0\x53\x22\x10\x61\x45\xd3\x30\xc6\x12\x68\xb0\x6f\xaa\xce\x99\xed\x39\x09\x10\x60\x45\x9d\x5b\xa3\xc2\x13\xdf\x76\xc2\x17\x6c\xc3\xea\x0d\xdc\xd7\xdc\xaa\x2c\x63\x16\xc0\x13\xe0\xbe\xba\xc3\x29\xbc\xda\x91\x00\xf1\xb5\x30\xad\x5d\xe8\x75\x64\xb8\x5a\xd2\x3a\xec\xa0\x22\xb3\x95\x2a\xc1\x54\x15\x08\xad\x3c\x6e\x85\xe9\x3e\xaf\xa6\x2e\xd5\xde\x0a\xaf\x1a\xc6\x8e\x00\xc1\xd5\xb5\x5c\xd6\x6d\x87\x6b\xe4\x1c\xf9\x30\xd9\xe1\x6e\x2d\x59\xaa\x23\x53\xf9\x2d\x04\x48\x61\x5b\x0a\xfc\xd5\x63\x38\x61\x03\xc4\xd5\x37\x52\x19\x53\xc1\x51\x0b\x2d\xd5\x96\x49\xe0\xec\x70\x63\xd6\x9e\xb4\x62\xb6\x1c\x27\x3b\x39\xb3\xb3\x4b\xeb\x81\xc9\x6e\x46\xc5\x1e\xf7\x92\xf3\x43\x73\x37\xdf\xef\x72\x2d\xc7\x5a\x81\x97\x1b\x07\xfc\x66\x0d\x7b\xe6\x34\xf3\xe2\x12\x70\x6a\xfd\x72\x2a\x1e\x98\xae\x6f\x25\x91\x96\xa5\x50\x61\xd3\x0b\x6c\xd7\xa3\xaa\xc8\x2c\x59\x5e\xa0\xbc\xfa\xd6\x1e\x94\x2b\x63\xad\xae\xdb\x3e\xcf\x0b\xe5\xe1\x45\xc3\x04\x98\xb0\xb0\x9e\xc5\x35\x07\x08\x4e\x8d\x90\x14\xbb\xb2\xf5\x9e\x19\xa9\xc0\x88\x75\x9a\x61\x32\x27\x40\x85\xbd\x1e\x38\xb2\xd4\x7a\xd0\x7d\x63\x73\x76\x7f\x4f\x02\xe4\x57\xd3\x50\xcd\x18\xe1\x97\x6c\xe2\x08\x28\xdf\x42\xb2\xf1\xc2\xa6\x9a\x65\x46\xdb\x5a\x1d\xc9\x3a\xe5\x99\x77\x2d\xc1\x96\x58\x2f\x6c\x7c\x4b\x6a\xd8\x5b\x91\xb7\xe7\xbd\x3f\x61\x62\x40\x02\x2c\xda\x93\x28\x0d\xd3\x5d\xe3\x98\x19\x28\x41\x41\x24\xf0\x66\x2d\xe5\x79\x78\x19\x36\x01\xd6\xec\x80\x5c\xea\x26\x81\x09\xf4\xce\xa1\xa0\xb6\x59\xdc\xdc\x94\x00\x8b\x16\x4a\x85\xe1\x10\x6c\x92\x56\x52\x99\x30\xf5\x29\x01\x0a\x6d\xae\xf6\x61\x13\x0c\xec\xd9\x46\x51\x1e\x37\xaa\x21\x1b\x37\xe1\x8e\x01\xfe\x2c\x14\xe0\xb2\x65\x40\x9e\xcd\x6d\xdb\x30\xeb\x1e\x40\x98\xfd\x6a\x4c\x15\xe6\x82\x24\xc0\x93\xd5\xa2\xde\xb7\x82\xb1\xc6\x40\x8f\x2d\x44\xd8\xdf\x00\x72\xec\x85\x2e\x10\xc6\x42\xb2\xa5\x54\x4c\x92\x19\xe8\xb1\x8d\x08\x3b\xe6\xc0\x8d\x75\x8d\x61\x74\x00\x78\xb1\x92\x8b\x66\x80\x11\xdb\xe1\xc2\x7a\x92\x8d\x3a\x98\x51\xc9\xd1\x18\x92\x6c\x3d\x87\x2e\x0d\x8b\x0c\x8f\x38\x22\x26\xd6\xc8\x36\x53\xe0\xa2\x60\xc8\x56\x90\x3c\x71\x83\x2c\x03\x77\xb7\xf5\x66\xb2\x04\x7d\x9d\x1b\xc3\xa5\x91\x90\x37\xcd\xae\x78\xf1\xae\xc2\xe5\x04\x7a\x8e\x4c\xed\x32\xec\x78\xee\x3c\x86\x24\x03\x7f\x98\x8e\x4a\xd4\x9e\xd9\x9c\x95\x64\x98\x8a\x68\xeb\x9c\xa5\x28\x27\xd9\xa8\xa6\xb9\xf0\x22\x63\x48\x40\x09\x30\xa6\xfb\x1c\x4a\x93\x73\x8b\x7e\xc0\x92\xee\xd1\xdd\x2c\xc6\xc1\xd3\x29\x9c\xde\x25\x31\x3c\x9c\x44\xae\x66\x95\x31\x6f\x64\x1b\xa3\x38\x1e\x5c\x02\x5c\xe9\xe2\x4c\x54\xf0\x66\xb6\xfd\x6d\xb8\x31\x3b\x13\x02\x6e\xf5\x07\x48\x70\xcf\x98\x71\x95\xbe\xa9\xe6\x9e\x98\xb3\x23\xcd\x09\xda\x4c\x05\xf5\xbd\x79\x57\x54\x9b\x2b\xc3\x09\xda\x4e\x05\x55\xe6\xa8\xee\x36\x6d\x38\x5d\x83\x11\xb4\x9b\x0a\xea\x97\x5c\x19\xf8\x0b\x38\x7c\xcc\x6a\x9f\x44\x32\x6b\x4e\xcc\xb6\xc8\x04\x68\xd7\x5f\x5d\xd1\x1f\xd3\x17\xc6\x4a\x88\x37\x0b\x8a\x33\xd3\x4e\xb3\xa6\xc3\xd5\xd6\xdc\xb9\xea\xc4\x71\xc6\x31\x77\x6d\xd3\x8c\x4c\x59\x80\x5a\x6e\xba\x00\x22\xf7\xd5\xa3\xaf\x8d\x0f\xef\xbf\x48\x80\xd1\x3d\xf3\x75\x2d\x39\xe5\x3c\x18\xea\xcb\xe5\x2c\x4c\x35\x4d\x80\xf7\x3d\x3b\xf6\x84\xaa\x86\xd9\x07\x9d\xe4\x93\x6d\x6f\x4b\x66\x39\x9f\x50\x54\xc2\xb0\x71\xd0\x9e\x62\x69\xaa\x4c\xd5\xc2\x9b\x59\x0e\xe6\x9c\xc2\x96\xf7\xae\x96\x42\x1e\xc8\xc6\x35\x31\x29\x89\x1c\x8f\xea\xa9\x25\x0d\x87\xbc\x33\xd1\x23\x90\xc5\x7f\xfd\x35\x8c\xda\x40\x30\x2a\x4b\x31\x55\x85\x37\x52\xef\x61\xb2\x71\x02\xc4\x71\x47\xf5\xd4\x2f\xee\x77\x5e\xf0\x9b\xb9\x13\x20\x93\x77\xe5\x67\x83\x17\x24\x30\xc3\x11\x28\xe6\xa5\x72\xde\x30\xa1\x13\xd2\xcb\x07\xb5\xf5\x25\xd7\xba\x71\x54\x96\xfd\x89\x90\x61\x24\x9c\x86\x26\xac\xd8\x5b\xd1\x84\x87\x02\x32\xc7\xb5\xca\x99\xcd\x3c\x09\x90\xc4\x87\x35\x33\xce\x2d\x05\x96\xf8\x15\xbc\xa4\xe0\x84\x07\x50\x55\xe1\x15\x10\xc2\xd4\xb9\x94\x64\xe3\x4c\x00\x5f\xf6\x6c\x6c\x5b\x9f\x19\x6e\x72\x03\x82\xb8\x67\xa2\x2e\xe0\x80\x67\xaa\x36\xb2\xd5\xcc\x46\x98\x84\x26\xf1\x70\xd8\x66\x01\xfd\xbb\x7f\xed\xec\x81\x15\x09\x50\xbe\xfd\x9b\xe2\x2c\x1b\x30\xbe\x4f\xa4\xc3\x71\x06\xb0\xbd\xbb\x71\x3e\x28\x37\xf3\xae\x04\x24\x2b\x8b\xb0\x63\x06\xb4\x6e\x29\x74\xf7\xae\x3c\x43\x0b\x20\x54\xd4\x13\x17\xba\x00\xa1\xfb\xbc\x33\xe5\x4d\x68\x8e\x2f\x09\x8c\x6e\x29\xe3\xa3\x72\xe1\x60\x07\x18\xdd\x52\xc6\x55\x7f\xd4\x06\xb7\x05\x35\x01\x4e\xb7\x94\x71\xae\x9c\x34\x47\x66\x38\x02\xad\x5b\xca\x58\x54\x14\x0e\x92\x70\x9f\xa8\x5c\x7a\x27\x48\xed\x96\xfd\x06\x29\x26\x33\x0b\xe4\xee\x9e\x5b\xce\xd3\x7c\x90\xdb\x7d\x45\x33\xea\x01\xec\xee\xfe\x40\xcc\x30\x10\xf8\x2e\xa6\x39\xf1\xf9\x3a\x20\x76\x87\xcf\x61\x4c\x80\xd4\x4d\x27\xca\xad\x69\x1a\xae\x33\x30\x35\xd9\xf9\xb1\x99\x6d\xb9\xfa\x42\xd4\xaa\xac\x2f\x73\x71\x8a\xa5\x38\x30\xef\x19\x73\x93\x24\xf8\x33\x1e\x12\xa0\x77\x37\x8a\x78\x70\xfa\x34\xd9\x77\xb3\x88\x86\x33\x27\x85\xf3\x45\x30\x3a\x4c\x81\xc5\x3d\x20\x17\xcc\x74\x0a\x0c\xee\x73\x42\x94\x39\x24\x32\x05\x06\xf7\x05\x1d\x9c\xe4\x52\xe0\x6f\x67\x8a\x8d\x3c\xd3\x27\xdc\x7f\x10\x34\xc8\x29\xf0\xb6\x95\x79\x2f\x4d\x78\xa3\x5d\x0a\xbc\x6d\x51\xef\x49\x73\xe7\xf2\xa5\x40\xdd\x96\xc1\xf5\xda\x14\x68\xdb\xae\xa4\x03\xcd\x68\x9d\x25\xfd\x3a\xbb\xa4\x34\xd3\x94\x51\x77\x2b\x12\x75\x23\xc2\x87\x23\xa6\x4f\x98\x6e\x39\x39\xd2\x5a\xe4\x8c\x64\x64\xb7\xd4\x35\x49\x9f\x53\x9f\x41\x0d\x97\xc0\x90\xd6\x95\x5c\xb6\x24\x4d\xf0\xfc\x49\xdb\x56\x59\x38\x62\x4f\x81\xc6\xad\xbb\x36\x86\x79\x10\x29\x30\xb6\xbb\xf6\xb9\xe0\x14\x9e\x02\x5b\xdb\x95\xca\x7a\xa7\xea\xac\xd5\xc1\x4c\x72\x0a\x8c\x6d\xa7\xaa\x46\x9f\xb2\x56\x85\x5d\x9d\x14\xf9\xda\x87\x93\xf0\x5a\x84\xdf\x74\x32\xd9\x0a\xe9\xd9\x0d\x96\x69\xb2\x9d\x82\x97\x97\x45\x53\x3c\xca\x57\x89\xca\x84\xcf\xb6\x4a\x13\x3c\x87\x27\xbc\x25\x39\x05\x3e\x78\xbf\x39\xca\x91\xb4\xe1\x99\x37\x05\x4e\x78\x65\xbc\xb1\xfc\x28\x4e\x70\xf5\xc7\x12\xf9\xf8\xa8\x28\x98\xc9\x4b\x81\x18\xde\x9f\xb2\x92\x31\x27\xf4\xa6\xc0\x09\x3f\x12\x73\xd0\x56\x3a\x21\x7a\x87\x9d\xbb\x14\x88\xdc\x15\x59\xd9\x86\x9d\xfb\x14\xd8\xd8\xfd\x9e\x5d\x77\x9d\xf5\x2f\x6b\x2a\xa2\x76\xfb\xfe\x0b\x54\x61\x19\x6b\x9c\x55\x2f\x70\xce\xeb\x4e\xf1\xfc\xde\xae\xc9\xe7\x1d\x39\x61\xfc\x66\xd2\xf2\x45\xf8\x76\x26\x9e\x7f\x5d\xbb\xa9\x70\xe7\xad\x09\x4f\x9d\x29\x50\xb4\x01\x1e\xe6\x67\xa6\x40\xd2\xc6\x02\x61\xa3\x08\x34\xed\x9a\x5a\x66\xe3\x67\x0a\x1c\xed\xe1\xad\x6b\x66\x65\x28\x05\x9e\xf6\xf5\x64\x15\x53\x14\x4a\xaa\xb0\xfb\x96\x02\xfd\x7a\xdc\xd6\x1d\x1e\x85\xc0\xbc\x7e\x2b\x85\x77\x22\xbc\x88\x90\xae\xd0\x32\x5a\xc6\x37\x4d\x81\x77\xdd\x8f\x6d\xd6\x1c\x01\xdf\xba\x07\xb3\x47\xc2\xa7\xc0\xb9\x2e\x8d\x9f\x4d\x73\x59\x78\x2b\x47\x0a\x14\xec\xa3\x12\x40\x54\xbb\x03\x9d\xf8\x9d\x1c\x10\x42\xfb\x36\x7b\x0b\xaf\xec\xa7\xab\xc9\x6e\x42\xd5\x86\xfd\x26\xe0\x53\x9f\xe4\x34\xad\x02\x69\x97\x70\xf1\x51\x19\x4d\xe3\x55\x1d\x57\xa6\x76\x9c\x4e\x02\xdd\xda\x34\x54\x73\x47\xa6\xa5\x2b\x3c\xd5\xa9\xa1\x5c\x79\xca\x9d\x63\x94\x11\x4f\x2c\xf3\x9e\xec\x29\x5e\x4f\x3b\x6c\xb8\x7a\xef\x1a\x6e\x57\xb9\x95\x0c\x04\xed\x0b\x7e\x75\x57\x8a\x2f\x2d\x51\xdc\x79\x9e\x9e\x49\x42\xa4\x40\xe1\xbe\x94\x4c\xef\xca\xe3\x4e\xeb\x4a\x81\xda\x7d\xc1\x27\x77\xa5\x9c\xeb\x13\x16\xb4\xba\x11\xf4\x74\x57\x10\xee\xf7\xb9\x23\x66\x0d\x93\x66\xeb\x28\xee\x93\xec\xdc\x73\xc7\xd1\xa5\x62\xd9\x5a\xc7\x68\x1a\x10\xc2\x4d\xf6\x95\xa4\x9f\x1c\xe3\x72\x07\xbf\x9d\xe3\xdb\x7a\xa1\x04\x9e\x94\xa6\xe4\xe1\x14\xd7\x26\x7c\xbe\x51\x0a\xac\x70\x80\x87\xe3\xcb\x14\x68\xe1\x52\xc6\x5f\x65\xd8\x29\x04\x3e\x78\x1f\x9b\xd7\x64\x5d\x2c\x35\xe3\x46\xae\x27\xbb\xcb\xc3\xe9\xc1\x74\x8d\xa7\xaa\xea\x61\x81\x4e\x32\x1c\xa3\x14\x88\xe0\xa5\x69\x6d\xff\x05\x16\xa6\x91\x40\xf4\x1e\xe1\x53\xad\x1c\xaf\x3b\x6e\x79\x2a\x05\xa2\xf7\x58\x24\x0d\x88\x62\x07\x0a\x30\xbc\xc7\x12\xab\x80\x24\x62\xbc\x4d\xa0\x7c\x5f\x0b\x84\xc1\xb3\x03\xad\xf6\x56\x64\xb3\xf4\x5e\x7f\xdd\xb2\xdf\xbf\x48\x9f\x67\x07\x5d\x39\x6f\xe6\xcb\x44\xfd\xf5\x85\xec\x57\xfa\x3c\x3b\x03\xeb\x72\x5c\x10\x57\x64\x3b\x2d\xa2\xd5\x37\x76\x73\x64\x0a\xac\xee\xe1\x19\xcd\x42\xdb\x5e\xa6\xf8\xb3\xc1\xe0\x4a\x88\x59\x09\x12\x92\x1b\x74\x78\x52\xb1\x15\x39\x71\x9f\x2d\x48\x9f\xf1\x73\x32\x7b\xd5\x4d\x64\xcc\x14\x0f\x4c\x6e\x69\xa9\xff\xd8\x54\x7f\x66\x86\x09\x1f\xb1\x92\x02\x95\x3b\x4c\xb8\x48\x81\xbd\xbd\xdf\x2f\x30\x44\x52\xa0\x6d\x7b\xab\x1a\x91\x1f\x15\x67\x47\x81\xb1\x6d\xf2\xda\x1c\x3a\x15\xae\xd5\x21\x98\x0d\x4d\x81\xad\x3d\x29\xb0\x94\x60\xd9\xe0\xf1\x99\x3e\x6e\xd8\xcd\x6d\x29\xf0\xb6\xdf\xd4\x41\x75\xb3\xbd\x88\xc3\x21\xd4\x06\x4f\x98\x2a\x84\x65\xaa\x8f\x9b\xda\x2c\xf3\xf5\x9a\x74\x83\x6b\x96\x96\x8a\x30\xad\x3a\x05\xc6\xb6\x69\x98\x0f\x0c\xa4\x40\xd5\xee\x35\xbb\x26\xdf\xf9\x32\xda\x58\x66\x5a\x04\xd2\xb6\x3f\x4e\x03\x2e\xd2\x74\x54\x8e\xd9\xf4\x99\x02\x7f\xbb\xbb\x2e\xc2\x43\x03\xc8\xdb\xcf\x4f\x4f\x0d\xd3\x5a\xa0\x1c\x56\xe2\x1b\xf3\x70\xa0\x6f\x5f\xf7\x4b\xf6\x8c\xba\x70\x2d\x80\xc4\x7d\x2d\x32\xec\xf8\x62\xca\xdc\xd9\x96\x39\x9c\x43\xce\x94\x59\xdd\x96\x19\x76\x73\x31\x65\xd6\xd0\x7b\x79\xeb\x18\x0e\x61\x3a\x39\xc3\xb8\xe9\xa2\xa1\x30\x74\x33\x81\x3a\xb5\x67\x2c\x06\xd0\xb7\x3b\x30\x53\x59\x0c\x54\xc3\x5e\x0e\x30\xb6\xcf\x07\xfc\x30\xab\xd2\xe9\x56\xdc\x41\x73\x95\xc8\x70\x82\xfc\xf6\x2d\x0c\xc4\x2f\x75\x54\xc4\x48\x04\x87\x45\x0b\x79\x88\xbd\x0a\x0f\xe1\x09\x75\xbb\xf6\xfd\xb7\xe3\x82\xe0\xdd\x9c\xeb\x17\x0b\xad\xc2\x8c\x82\x14\xf8\xdb\x94\x87\xb9\x64\x29\x1e\x47\x3c\x9e\x05\xca\x66\x3c\x80\xc8\x2d\x4d\xae\xa8\x61\xda\xb8\x43\x2f\x3b\x0f\x8f\x5a\x20\x6d\x17\xfd\x16\xa0\xe1\x2b\x7e\x61\x3c\x7e\x41\x2e\xec\x69\x02\x6d\xbb\xb1\x26\x6f\xa5\x8f\xcb\x36\x7c\xb6\x77\x0a\xfc\xed\x4a\xbd\xb3\x14\xa3\x14\x58\xdc\x4e\x5a\x95\x31\x48\xd8\x62\x29\xba\x50\x63\x61\x92\xdc\x65\x77\xf1\x8c\x26\xef\xa6\x9f\xdb\x58\x7c\x40\x7e\x0f\xce\xc9\xc7\x75\xe8\xf3\x01\xe2\x59\xf8\x73\x4e\xe9\xcb\xd3\x3d\xbc\xe3\xe6\x54\x20\x69\x97\xc2\x95\xcc\xc7\xa2\x52\xe0\x67\x67\xba\x25\x6f\x0c\x93\x96\x07\x7a\xf6\x15\x1c\x87\x35\x06\x0f\x24\x26\x2b\x89\x51\x16\x20\x62\xef\x95\xd7\x82\x11\x0a\x1c\x8b\x26\xa3\x3d\x7b\x02\x4b\x0a\xf4\xeb\xb7\xa6\x30\xb6\x0a\x5b\x85\x29\x01\x5b\x31\x73\x3b\xf0\xae\xcf\xbc\x67\xa1\x63\x21\x25\x97\x64\x03\xfa\xf5\xc8\x83\x67\x4d\x03\xd0\xb0\x67\x9f\xfe\x60\x94\x0b\x48\xd6\x99\x56\x4c\x40\x03\x14\xea\x81\x1b\x96\xd3\x70\xf0\x03\xe7\x62\x00\x9d\xfa\xfc\x09\xb4\xee\xb6\x35\x9a\x3f\x70\x3a\xc5\x43\x89\xad\x50\x9a\x19\x4e\xc0\xae\x16\xce\x29\xd7\x3b\xd7\xba\xf3\xc8\xeb\x7e\x43\xdd\xc9\x79\x62\x3a\x11\xb8\xd6\xc2\xe9\xc1\xf5\x6a\x2c\xf9\xf9\xf7\x14\x44\xbf\x5b\x51\xd4\xc3\x21\xe0\x17\x96\xf0\x3d\xfc\x9d\x67\xc0\xd1\x7c\x24\x8a\x7a\xec\xf6\x4b\x50\xd6\x85\x4a\x45\x9f\xe2\x9f\x3f\x37\x67\xbe\x3f\x91\x02\x87\x7b\xaf\x55\xf8\x68\x97\x14\xf8\xdb\x3d\x30\x66\x2a\x0b\xfe\xb2\xda\xdf\x7c\x57\x62\xd2\xfc\xb0\x10\xdc\x49\xf6\x16\x2f\x38\xa2\x40\xe9\x3e\x2a\x91\x33\x53\xbc\x78\x99\x21\x97\x42\x0b\x60\x76\xbb\x5a\x34\x40\xb1\xba\x83\xcd\x6e\xb0\xf1\x9e\x5d\x41\x05\x92\xf7\xb5\xc4\x52\x85\xe0\x8c\x93\x2b\xe1\x3d\x8c\xc6\xf3\x90\xad\xf3\x31\x9e\x53\x7b\x0b\x07\xe2\xf7\xc9\x08\xa6\xe2\x40\xfc\xf6\x25\x55\xa4\x1c\x33\xc2\xf0\x3c\x64\x38\x5c\x75\x32\xcd\x3d\xdc\xdc\x5e\x5c\x10\x00\xae\x78\x31\x25\x25\xf6\x5f\x20\x5e\x72\x42\xb2\x69\xce\xc4\x95\xe2\xc0\xd9\x39\x20\x8f\x8f\x9f\xe7\x65\x58\xa1\x29\x90\xc8\x27\x05\xb8\x67\x80\xd6\xab\x9a\x39\x6a\x29\x45\x1a\x79\x9e\x5b\x72\x8e\xfd\xa2\x62\x0a\xc4\x71\xc4\x73\x75\x19\x15\xff\x28\xe7\xbb\x66\x2e\x32\x38\xda\x4f\x0a\x64\xf2\x5e\xc2\x2c\x93\x84\x32\xb8\x7a\xc8\xe9\x22\xca\x82\x73\x04\x44\x73\x80\x73\xf2\x67\x47\x59\x86\x91\xc0\x34\x57\x79\x9c\x09\xce\x31\x07\x9e\x79\x6e\xfb\x09\x3b\xd6\x4a\x52\x3d\xfb\x48\xb0\xca\xf9\x57\x08\xfc\xf3\x99\x98\xd9\xcb\x3c\x0b\xe2\x6a\xbf\x82\xc9\xdd\x30\xbe\x06\xd2\xd1\x2d\x9d\xf9\xd4\x52\x54\xe1\x38\x0f\xc8\xe5\x9e\x34\x71\xdb\xb8\x53\x89\xdf\x20\x21\x5b\x0d\x07\xca\xce\x16\x4f\xe0\x4e\xe8\x3a\xbf\x88\x22\xb7\x77\x9f\xb2\x0a\x4a\xfb\xe0\x62\x8a\xdc\xdd\x95\x9b\x06\xe5\xb2\xb9\x62\xf9\x72\x57\x5a\x12\x94\xb6\xb4\xb8\x22\xc5\x5d\x81\x4f\x41\x81\xfc\x22\x0b\x1e\x27\x5e\x9a\x37\xee\xc1\xe0\x04\x0a\x5f\xfa\x76\xba\x37\xc5\x25\xcf\x93\xdf\x19\xc7\xc4\x01\x76\x7a\x63\x72\xc9\xcd\x42\x40\x4b\x1f\xb6\x84\xc7\x95\x78\x57\x95\xfa\x16\x1e\x98\x40\x3d\xbf\x14\x51\xf5\x42\x91\x64\x5e\xc4\x92\xf3\x86\x99\xa3\x73\xfc\x30\x66\x45\x2e\xb6\x24\x3d\x7e\x41\xeb\x01\xa5\xe1\xb7\xc3\xef\xc8\x5a\x85\x64\xcd\x4c\x00\x4a\x63\xec\x00\x10\xd1\x33\x51\xe7\xec\xc0\x06\x0e\xfa\xde\x8a\x30\xb1\x00\x58\xe8\xe4\x19\x5e\x11\x10\xce\x55\x95\x87\x23\x2e\x20\x96\x5b\x71\x24\xcd\xe4\xc2\x80\x3f\x4e\x64\x59\x6d\x01\xfe\x78\x7f\x7e\x9b\xe4\x48\x3c\x39\xfa\x72\xe6\xad\xd0\xbc\x77\x80\x47\x92\xb7\x0d\xd9\x7e\xe3\x4f\xd8\x8e\x00\x89\xfc\xad\x59\x4c\xd2\x02\x8f\xbc\x22\xf2\xcc\xba\xe2\x85\x44\xee\x6c\x6c\x6a\x7d\xea\x01\x8d\x71\xaa\x8f\xb1\x22\x91\x39\xa3\x5b\x4f\xff\xf6\x29\x8a\x86\x4f\x05\x47\x49\xf3\xde\xfd\x3a\x7f\x67\xf8\xf2\xb3\x11\x79\xbf\xdf\x30\x7a\xea\x7e\x55\xc2\xee\x55\xfd\x1a\xc5\xe7\xbb\xd7\x73\x3d\xa2\x52\xe5\x39\xd5\xdd\xb5\xfe\x1b\x0d\x51\xa7\x9a\x9f\x9f\x1e\xa2\xf3\xff\x7e\xec\xee\x64\x83\xc7\xd9\x89\x1a\x2b\x16\x17\x46\xb6\xae\xff\x88\x80\x90\x5d\xc0\xf5\x70\xef\x56\xff\x5f\xb3\x36\x38\x2f\xbc\x92\xd0\x02\xd1\x7a\x83\x4d\xb8\xfc\xbe\xd4\xfa\x69\x5a\xe5\x2e\x92\xc8\x34\x8d\x75\x1e\xf0\xbf\x7d\xfa\x7f\x01\x00\x00\xff\xff\xa2\x10\xca\xbc\x26\x92\x00\x00")
+
+func uiAppLibFontAwesome470CssFontAwesomeCssBytes() ([]byte, error) {
+ return bindataRead(
+ _uiAppLibFontAwesome470CssFontAwesomeCss,
+ "ui/app/lib/font-awesome-4.7.0/css/font-awesome.css",
+ )
+}
+
+func uiAppLibFontAwesome470CssFontAwesomeCss() (*asset, error) {
+ bytes, err := uiAppLibFontAwesome470CssFontAwesomeCssBytes()
+ if err != nil {
+ return nil, err
+ }
+
+ info := bindataFileInfo{name: "ui/app/lib/font-awesome-4.7.0/css/font-awesome.css", size: 37414, mode: os.FileMode(420), modTime: time.Unix(1, 0)}
+ a := &asset{bytes: bytes, info: info}
+ return a, nil
+}
+
+var _uiAppLibFontAwesome470CssFontAwesomeMinCss = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x7d\x4d\x8f\xe4\xb8\xd1\xe6\xdd\xbf\x22\x77\x06\xde\xe9\x36\x4a\x35\x45\xe5\x77\x15\xbc\x9e\xfd\x80\x01\x03\x36\xf6\x60\x1f\xf6\xb0\x17\x8a\x0a\xa5\xd8\x49\x89\x1a\x92\xca\xac\xec\x46\xff\xf7\x17\x92\x18\x4c\x2a\x2b\x28\xcf\x0b\xcc\xe1\x35\x0c\xbb\x8b\x7c\x48\xf1\x23\x18\x11\x0c\x3e\x64\xfe\xfc\xa7\xff\xf6\x87\xd5\x9f\x56\xab\xbf\xea\xd6\xad\xfe\xe7\x15\xac\x6e\x60\xb5\x79\xde\x3f\xbf\xac\x8a\xdb\xea\x97\x92\x5f\xe0\xc4\xdb\xf2\xb6\xca\x56\xb5\x73\xdd\xeb\xcf\x3f\x57\xba\x75\x7c\x02\x3e\x4b\xbd\xca\x56\xbf\x44\x29\x63\x5d\x7f\x97\x02\x5a\x0b\xa9\x22\x3f\x2b\x9f\xff\x69\xf8\xe8\xeb\xea\x9f\x7f\xfb\xfb\xea\xff\xfe\xf5\xef\x2b\xf6\xcc\x9e\x56\xff\xfb\x9f\xff\x7c\x5d\xfd\xe3\x6f\xff\xc2\x4a\x3e\xff\x61\xf5\xa7\x9f\xc7\x2f\x64\x15\x17\xf0\xcd\xff\xab\x91\xea\xf6\xfa\xd3\x50\xde\xb7\xf9\xa7\x37\x6b\xc4\x6b\x6f\xd4\xa7\x9f\x9e\x9f\xc7\x0f\xda\xf8\xb3\xd9\x15\x8a\xe1\xcf\x67\xd0\xee\x2f\x97\x3f\x8f\x1d\xfc\xe9\xf3\x7f\xa2\xcc\x8f\x12\x2a\xf9\xfe\xdf\x43\xd1\x55\xa5\x4d\xc3\xdd\xa7\x9f\xa0\x29\xa0\x2c\xa1\xcc\x74\x07\xad\xbb\x75\xf0\xd3\xe7\xa7\x7f\x5f\xe5\x55\x57\x55\xfe\x97\x8f\xb5\x8d\xe9\xbf\xb9\x86\x44\x05\xbf\xa9\xbc\x73\x54\x71\x67\x7a\xf8\xcd\x9d\xb0\x97\x13\x56\xf1\x63\x94\x6f\xe0\xd4\x2b\x6e\xa2\x5a\xed\xe5\xf4\xd3\xe7\xb7\x71\xea\xae\x20\x4f\xb5\x7b\x6d\x87\x1c\x35\x25\x59\x77\x53\xe0\x53\xbe\x3f\x57\xfc\x5b\x29\x6d\xa7\xf8\xed\x55\xb6\x4a\xb6\x90\x15\x4a\x8b\xf3\x08\xf5\xa0\xd5\xfc\xff\xd8\xa6\x7b\xff\x99\xad\x22\x61\xf0\xf5\xca\xaf\xf0\x2a\xdb\x1a\x8c\x74\x6f\x0e\xde\x5d\x66\xa0\x2d\xc1\xc8\xf6\xf4\xca\x7b\xa7\xdf\x86\x8e\x9c\xa5\xcb\x26\x74\xa3\xb5\xab\xc7\xbc\xd6\x49\xae\x24\xb7\x50\xbe\x65\x8d\xfe\x9a\x69\xfb\xfe\x88\x39\x19\x7e\xb3\x82\x2b\x18\x1a\x9c\xa9\xd3\xb7\xfb\x17\xd9\xf3\xda\xff\x07\x9a\xb7\xb1\x03\xf5\xd4\xe7\xe7\xfd\x16\x9a\xb7\x0b\x18\x27\x05\x57\x19\x57\xf2\xd4\xbe\x66\x6c\xfb\xc7\xb1\x8e\xfc\x3d\xaa\x23\x87\x66\x4c\x5c\xc7\x89\x6b\x9f\xb8\x89\x13\x37\x3e\x71\x1b\x27\x6e\x7d\x62\x75\xfd\x76\x95\xa5\xab\x5f\xd9\x73\x7e\xd8\xee\xd9\x26\x3f\x42\x33\x0d\xc5\xf4\x75\x01\xad\x03\x33\x62\x7b\xf5\xad\xe3\x65\x29\xdb\x53\xa6\xa0\x72\xaf\x2f\x6f\x0d\x37\x27\xd9\x4e\x7f\xe5\xcf\x6c\x33\x55\x31\x76\xca\xfa\x59\xcb\x06\x59\x79\x6d\x75\x0b\xbe\x8e\xff\xa1\xe4\xb7\x4e\x5b\xe9\xa4\x6e\x5f\x0d\x28\xee\xe4\xc5\x8f\x51\x94\xc1\x0b\xab\x55\xef\xe0\x6d\xac\x3b\x9b\x55\x3e\x35\x78\x96\xe4\x74\xf7\x3a\xfb\x9b\xec\x80\x92\x7e\x2a\xa6\x4a\xd9\xf3\xd4\xe3\xc3\xce\x0f\x46\xa1\x4d\x09\x06\x3b\xf9\xfa\x9c\x43\xb3\x7a\xce\xb7\xc3\xff\xb2\x61\x62\xa6\xfc\x57\xab\x95\x2c\x57\xcf\x2f\x07\x68\x56\x3f\x02\x80\x4f\xcf\x0c\x2f\x65\x6f\x5f\x9f\x99\xaf\xae\xeb\x95\x1a\xc7\xe6\x5b\xa5\x34\x77\xaf\xc3\x3f\xef\x19\x66\x98\x71\x9f\x33\xfe\x7b\xc8\x9a\x17\xf3\xc3\x6b\x26\xd9\xf0\x93\xfb\x50\x41\x3c\x05\x13\x24\x55\x7b\xaa\x39\xcf\xff\xee\x83\x8b\x5f\xab\x78\x66\x3b\xd9\x7e\xc3\x95\xc2\x5b\xd9\xf0\x71\x0a\x7d\xce\x2a\xb7\x2b\xd9\x56\xb2\x95\x0e\x56\x83\xb0\x73\xf3\xf6\x5b\x40\x38\x52\x16\x16\xea\x66\x51\x31\xeb\xa0\xb3\x9f\x0e\x9f\x89\xda\x29\xd8\xf7\x5f\xb0\xda\x33\xdc\x2a\xc3\x1b\xb0\x2b\xec\xcc\xcb\x1f\xc3\x37\x9d\xe1\xad\x1d\xb4\xd4\xab\xd1\x8e\x3b\xf8\xf4\x52\xc2\xe9\xf3\x1b\x9d\xfc\x9d\xbd\x2c\x15\x5d\x6f\x8f\x74\x61\x9f\xf1\xfd\xfb\x2f\xff\x85\xda\x32\x8c\xff\x94\x96\x1d\x5f\xbe\x65\x8d\xcd\x2a\xa9\x1c\x98\xd7\x1f\x3a\xa3\x4f\xb2\x7c\xfd\x3f\xff\xef\x6f\x0d\x3f\xc1\xbf\xb0\x86\xe7\x7f\x48\x61\xb4\xd5\x95\x7b\xfe\x5f\xdc\x4a\x31\xe6\x7e\x1a\xab\x90\xba\xfd\x33\xfb\xfc\xc3\x5b\xb2\x39\xc7\xa9\x2b\xc3\x57\x52\x79\x89\xf4\xb8\x9d\xec\xf0\x7b\x34\x34\x5f\x6a\x28\x3b\x2c\xb4\x14\x33\x53\x19\x71\x5b\xf3\xfd\xef\xd1\xd6\xf5\x52\x5b\xf3\xfd\x42\x5b\x31\x33\x95\x31\x99\x07\x25\xbb\xac\xd6\x46\x7e\x1d\x8c\xb7\xfa\x1d\x1a\xfc\xf2\xb4\x6a\xa4\x31\xda\x24\xe4\x61\x34\x99\x9f\x32\xf6\xb4\x62\x8f\x0d\x9f\x65\xd1\xc9\xf7\x46\xa3\x11\xfd\x3d\xe4\xe1\x37\x35\x99\x3d\xad\xb2\x44\x93\x7d\x16\x9d\xfc\xfd\xd5\x68\xed\x56\xb3\xd5\xf6\xf4\x21\x8d\x1d\x88\xc4\x7c\x1f\x27\x3e\xcc\xd5\x63\x4e\x18\x10\x3f\x18\xc1\x24\x5b\xc7\xc5\xf9\xa3\x49\x7e\x23\x7d\x2c\x6f\x7b\xa1\x79\xf3\x2e\x4b\xfe\xe0\xc2\xe4\x1f\x1d\x98\x46\x96\xa5\x8a\xbe\x95\xb1\xf7\xa7\xfb\x1f\xf9\x7b\xca\xea\xbf\xf8\xaf\x0d\x8a\x2c\x61\xd1\xb1\xbe\x6f\x71\x13\xbc\x43\xf7\x7d\xf6\x8d\x8f\x9e\x93\x6c\x2f\x60\x2c\x7c\x13\x5a\x69\xf3\xfa\x63\x55\x55\x63\xf2\x49\x71\x6b\x5f\x0b\xa8\xb4\x19\xf2\x5a\x07\xad\x7b\xfd\xe1\xff\x57\x2f\x2f\x2f\x3f\x8c\x80\xa6\xb7\x52\x90\x00\x36\x01\x2c\x70\x23\x6a\x12\x91\x4f\x08\x68\x2f\xa0\x74\x07\x99\x26\x51\xeb\x09\x55\x03\x37\x8e\x04\x6c\x7e\xc0\xce\x19\x32\x7f\x7b\xcf\x4f\x7c\x62\x37\x21\x7a\x0b\x74\x0d\xfb\x29\xbf\x92\xaa\x21\xf3\x0f\x53\xbe\xab\x33\xc5\xcd\x09\x48\xcc\x11\x31\x64\x2e\xbf\xd7\x20\x2d\xdd\xcd\x62\x82\x88\x1a\xc4\x99\x04\x88\x09\x60\xa0\xd1\x17\x6c\xc3\x28\x5a\x42\x69\x3b\x4b\x70\xb2\x01\x7a\x56\xcb\x78\xd2\xb2\x4e\xf5\x34\x0c\x66\xb0\x46\xb6\x34\x8e\x79\x21\xe9\xf4\x15\x4c\xa6\xab\x8a\x04\xa1\xa0\xc8\x53\xcb\x15\x89\xf0\x82\x72\x82\x30\xc3\x53\xbf\xf4\x89\x84\x7b\x89\x71\x86\xdb\x9a\x9e\x71\xe6\x65\xa6\xd6\x0d\x39\x5b\x6c\x1b\x66\x3c\x21\x96\xcc\xcb\x8c\x18\x14\x41\x02\xe2\xc5\xc6\x68\x5e\x92\xf9\x5e\x6c\x4a\x7d\x6d\x55\x0a\xe3\xc5\x86\x1b\xa3\xaf\x99\x90\x46\x0c\x0d\x1a\x8b\x90\x70\x4e\xc2\xfb\x8e\x04\x7b\x89\x92\x6d\xa1\xdf\x49\x80\x97\xa8\x41\xf1\x85\xca\x48\x60\xf9\x43\x6c\xcc\x27\x8f\x39\x9a\x28\x03\x1d\x70\x52\xaa\x19\xa0\xd0\x56\x06\x2c\xb9\x36\x72\x2f\x1f\xe3\x2e\x8a\x2b\xb2\x9a\xdc\x4b\xc8\x30\x19\x64\xbe\x17\x89\x4a\x71\x52\x64\xf2\x4d\x50\x32\x65\x57\xeb\x96\x5e\x1d\xb9\x97\x8a\x8b\x56\x7d\x03\x29\x79\xce\x77\x33\x54\x6a\xaa\xf2\xfd\x0c\x46\x4f\x51\xee\x45\xe4\x57\x23\x74\x49\x4a\x6a\xee\x05\xa4\xe0\x69\x08\x2a\x97\x44\xdf\x8b\x90\x4d\xf7\xda\x4b\x41\xa1\x35\x3d\xb6\xe5\x3d\xbf\xe1\x86\xc6\xf8\x69\xee\x8c\x6c\xe9\x09\xac\xfc\x72\xe2\x0d\x18\x4e\x21\xd6\x5e\x97\x8c\x71\x0d\x2a\x9f\x61\x33\x14\xb9\x92\xd6\x5e\x44\xa4\xe3\x8a\xb6\x58\x6b\xd4\x1b\x83\x71\xf5\xd6\x93\x82\x6d\x22\xd8\x64\x93\x29\x94\x97\x95\xd1\x48\x4f\x5b\x44\x0a\xb5\x8b\x51\x93\x29\x27\x71\xfb\x18\x67\x92\x4d\x3b\xc4\xb0\x2f\xbd\x75\xb2\xba\x91\xc0\xe3\x7d\x4d\x91\xf9\x5e\x64\x4a\x28\xa1\x9d\x2d\x65\xdd\xbb\x28\x69\x5e\x28\xe8\x93\x24\xc2\x8b\xd2\x45\x96\xa0\x97\xe6\xda\x8b\x54\x57\x6b\xa7\xe3\xaf\xcb\xc1\x17\x8d\x13\x3a\x29\x5c\x6f\x12\x6a\x69\x8d\x52\x07\xad\x90\xa4\x65\xd9\xa0\x17\xc3\xbb\x6c\x90\x5d\x7a\xf4\x37\x5e\xb4\x78\x39\x0c\x29\x89\xf0\xc2\xe5\x12\xe2\xbd\xf1\xa2\x05\xa5\x9c\x8d\xe6\xd4\xb2\xcc\xfe\xda\xf3\x54\x27\x36\xe8\xde\xd4\x03\x64\x11\xb9\x8d\x3c\x84\x65\xe4\x2e\x32\x13\xe4\xa2\xdf\xec\xd1\x69\x82\x2e\x2b\xb8\x38\x5f\xb9\x21\x97\xd5\xc6\x8b\x5c\xc5\xad\x5b\x06\x06\x45\xb5\x80\xe1\x77\x83\x43\xe6\x7b\x09\xeb\x78\x6f\x49\x55\xb7\x11\xd8\x6c\x4d\xea\xd3\x4d\x89\x4a\xc4\x24\xdb\x00\x51\x87\x16\x70\xdb\x97\x68\x84\x96\x70\x5e\x78\xe0\x0b\x08\x52\x36\xb6\x79\x98\xb6\x8b\xd1\x69\x5d\xb1\x5d\xcf\x71\x49\x2d\xb0\xdd\xe0\x28\xf6\xd6\x9b\x6d\x12\xe6\xc5\x65\xf4\xde\x96\x70\x3b\x94\xed\x06\x16\x71\xfb\x58\xfc\x16\x70\x68\xd3\x7a\xb0\xc3\x3e\x67\x09\x7a\x44\x8d\x52\xe9\x25\x98\x17\x9b\x61\xdb\x6a\x6b\x2e\x0d\x29\xd2\xdb\xe2\x63\x3f\xe8\xe5\xb1\x15\x1f\x7b\x92\x40\xa2\xed\xe3\xa4\x8d\xdf\x42\xec\x8e\xa5\x26\x76\xf7\x12\xa3\x92\xd3\xba\x63\x31\x8c\xf6\x17\x76\x79\x8c\x49\xb9\x1e\xbb\x35\x6a\x3d\xa9\x1e\x44\xf7\x29\xa8\x1a\xb2\xa0\x97\x2c\x78\xef\x78\x4b\x4a\xfb\x0e\x75\x90\x6e\x3a\x03\xf4\xd6\x71\xb7\xbb\xcb\x27\x99\xbf\x8f\x04\x93\x04\xa0\x99\xb3\x0e\x8c\xb4\xa4\xc7\xb1\x3b\x62\x53\x85\xe2\x53\x00\x74\x41\x82\x76\x5e\x82\x4e\x32\x31\x45\x5e\x76\x14\x70\xd2\xe7\xdb\x09\xdc\x2f\x24\x06\xce\xcb\x09\xdc\xe8\x6c\x08\xd9\x99\x55\x9c\xf6\x83\xf7\x5e\x4c\xae\xdc\xb4\xb2\x3d\xc5\x13\x16\x77\xd2\x19\xc9\xdb\x13\xdd\xcd\x3d\x0b\xfa\xb5\xa5\x01\xa8\x8b\xb8\x82\xb6\xa4\xf7\xd3\x7b\x2f\x3d\x86\xb7\xa5\x26\xf7\xc3\xfb\x4d\x10\x82\x26\xe1\x09\xec\x51\xf9\xf0\x53\x0b\x34\x62\x37\x57\x77\xb4\xc0\xef\xf7\x73\x54\x4a\xe4\xf7\x07\xdc\x67\xb8\x2b\x24\x3e\x78\x44\x43\xab\xbb\x4e\xb6\xa7\x4c\x24\x02\x0e\x7b\x8e\x46\x44\x95\xb4\xc3\xb0\x2f\x62\xc4\x78\xd2\x49\xc2\x44\x6c\x86\xb3\x0b\x89\x29\x67\x18\x5a\x32\x20\xec\x01\x32\x51\x73\xe3\xb2\x99\xd3\x14\x92\xa9\xb2\x07\x2f\x55\xee\x2a\x9d\x03\xe3\xdd\x06\x12\xc9\xd0\x30\x0a\x18\x7c\xfd\x25\x68\x1e\x7b\xf3\xc3\xa0\x1b\x52\x7d\x1e\xbc\x28\x9d\x81\x34\xf7\x87\xcd\x7d\xdf\x6f\x1f\x36\xfe\xa4\x62\x38\x6c\x67\x82\x47\x63\xd0\x9c\xd5\x7d\x53\xd8\xe4\xe6\xf8\xb0\x7f\x80\xa5\x24\xeb\x70\x88\xc2\x4b\x35\x57\xa4\x7e\x38\x1c\xa3\x20\x16\x6d\x4a\x0e\xfc\x1e\x06\x19\xbc\x6c\x12\x83\x6a\x48\xb6\x67\x28\x65\xbb\x34\x05\x22\x6a\x7f\xe6\x38\xbd\x2f\x3e\xa0\x5e\x7a\x77\x60\x5a\xae\xc6\x9a\x49\x20\x44\xad\x93\xe4\x40\x1c\x51\x92\x8c\xee\x6a\x72\x3e\x8f\x0c\xb5\xac\xab\xfb\x62\xa1\xf1\x47\x2f\x3f\x7d\x97\x8a\x8b\x1c\xd7\xa8\x90\x1b\xdd\xd2\x03\x7a\xdc\x84\x4d\x04\xad\xec\x8e\x18\x18\x5c\xf0\x94\x8f\xbb\xf9\xe6\x36\x81\xda\x47\x9f\x5a\xea\xd7\x61\xb6\xd8\x48\xc8\xf1\x61\x95\x55\xb1\xe0\x63\x2a\x59\x92\xc7\xa3\x4b\x22\xbc\xf8\xf4\x6d\x2a\x4e\x72\x44\xcf\xc7\x0c\x3b\x95\x41\x03\xd2\xa3\x8f\x6e\x34\xc0\xcc\x71\x30\xb4\xc1\x3f\x7a\xe1\xa9\xcb\x92\x1e\x3f\xee\x45\xa7\xe8\x95\xaa\xb5\x21\xc5\x8b\xe3\xfe\x1e\x14\xb9\x95\xab\xd0\x3d\x06\xe3\x64\x25\x05\x77\xe4\x14\x70\x0c\x27\xf3\xb6\xcc\x74\xda\xdb\xe2\x9b\x19\x2e\xe5\xbb\xf1\xed\x0c\x46\xeb\x12\xbe\x9b\x81\x52\x9a\x84\xef\x63\xe7\xcd\xbb\x9d\xc9\x0f\x1f\x08\x70\xba\x37\x54\x18\x31\xd1\x58\x2a\x84\x98\x6c\xb2\x97\xa8\x93\xd2\x05\x3d\xdc\x5e\xa0\xae\x06\x5a\xfa\x14\x80\x97\x18\x7e\xb2\x67\x52\x7a\x38\x6e\xc8\xa6\x93\x1a\x02\x51\xa0\xf8\x18\x09\x95\xe0\xf4\xd6\xb0\x60\x33\x43\x9a\x08\x24\x16\x18\x6a\x36\x3a\x0c\xcf\x28\xda\xbd\x05\x7a\x5b\x21\x5e\xd0\x03\xe1\x41\x2f\x3e\xa1\x92\x26\x0b\xf8\x86\x08\xa5\x7b\x72\x75\x09\xdf\x86\x4a\x71\xda\xb7\x15\x28\xea\xfd\x2c\x98\x60\x85\xb4\x56\x27\x5a\x19\x5c\xb2\xee\x36\x53\x28\x52\x81\xa5\x17\xa5\xd8\xe2\x66\xbb\x03\x23\x94\x24\xa5\x45\x78\xd1\xb6\x7c\x7e\xe4\x50\x29\xdd\x75\xb7\x44\xc5\xfb\x58\xef\x92\x08\x2f\xdc\x2d\xbf\x48\xa1\x67\xa3\x6a\x60\xa2\x9d\xcc\xfd\x1b\xba\xcf\x51\x90\x2b\xeb\x49\xa5\x21\x78\x04\xd1\x34\xa4\x40\xfb\x6e\xe4\x19\x5c\x6d\x74\x7f\x22\x05\x59\x08\xd4\xae\x25\x18\x25\x69\x9b\x23\x82\xb4\x17\xb4\x8b\x2e\x20\x38\xc6\x74\x94\xb2\x0c\x66\xb6\xa7\x75\x78\x89\x4e\xbe\x6c\x1d\x18\xa0\x03\x56\x65\xfe\x00\x5a\x98\x8d\xd2\x8b\xdb\x49\xeb\x93\x82\x29\xac\xb0\x80\xde\x7c\x40\x93\x30\xdc\x00\xe8\x96\x76\xfe\x4a\xf4\xff\xb9\x01\x97\x54\x40\xe5\x3e\x46\xd1\x1a\xad\x3c\xc4\x98\x94\x42\x2d\x8f\x31\x2a\xa9\x49\x4b\x8c\x35\x68\xd5\x37\x2d\xdd\xb5\x60\x66\xad\x36\x6e\x6e\x21\x87\x14\xb2\x0c\x06\xae\xb4\x99\x75\xf6\xe9\x9e\x08\x96\x96\x87\x32\x2a\x39\xd7\x59\x63\x12\x4f\x14\xc3\x2d\xa7\x3f\x7c\xa5\x30\xf0\x32\x77\x37\x49\x8c\x97\x36\x7f\xf4\x13\x8d\xee\x93\x5f\x0c\xa4\x0e\x00\x3c\xb0\x81\x53\x38\xf3\x1b\x0b\x9c\xf8\x05\xc8\x75\x08\x5e\x0a\x4b\x6e\xeb\x42\x3f\x44\x2c\x1c\x17\xb5\x6e\x20\x61\x1f\x60\xbe\x1f\xa5\xb5\x12\x3c\xec\x1d\x12\xa8\xdd\x5d\x37\xd7\x33\x25\xa4\x69\x83\x02\xa8\xec\xa4\x83\x86\x93\xf2\x09\x5e\x3e\xfb\xa6\x30\xa0\x14\x19\x11\x87\x23\x2a\x63\xeb\x1e\xce\x76\x65\x17\x0f\xc7\xbc\x54\x50\x6f\xa7\xda\x15\xbd\x2a\x12\x9d\x2a\x42\xac\xa4\xe6\x2d\x7d\x7e\x0d\x22\xb2\x5a\x8b\x47\x96\x50\xc6\xc8\xb4\x0b\x0f\x5e\x02\x07\xcb\x9a\x35\x24\xa4\xba\xc7\x58\x5d\xad\xad\x48\xc8\x69\x85\x27\xc8\xbd\x74\x29\xf3\x5f\xe5\x77\xf7\x31\xe1\x84\xe2\xa6\x55\x57\x15\xd0\x75\x6c\x82\xdd\x55\x60\x48\xad\x55\xc5\x07\xc7\xe3\x09\x11\xf9\xad\x0a\xb7\x15\xbd\x54\x23\x85\x94\x46\x79\xd9\xa9\xb5\xed\xa4\xe3\x89\x76\x57\xe8\x09\x36\x45\xaf\x78\x2b\xe8\xa6\x7b\xf9\x69\xa0\x3c\x4b\x52\x50\x2b\x8c\x6a\x0c\xb2\x02\x26\xfb\x42\x47\x49\xaa\x02\xc7\x91\x5e\x6b\x95\x97\x93\x7a\xc1\x44\x54\x78\xbc\xb3\x6c\x49\x2a\x8c\x9e\xb6\xa7\xd1\x05\xed\x8b\xb4\x3f\xcc\x90\x8f\x32\x03\xa7\xb4\x38\x43\x72\xca\x0c\x4d\x5a\x0f\x86\x2c\x95\x19\x34\x61\x8e\x18\x92\x55\x26\x70\xb2\xad\x9b\x18\x95\x6e\xe4\x36\x86\x25\x5a\xb7\x9b\xb7\x2e\xd1\x2c\x2f\x48\x25\xd8\x33\x7d\x32\xc2\x90\xc3\xa2\x78\x97\x42\x1c\x23\xd7\x85\x6e\x30\x47\x9b\x5e\x0c\xe2\x1f\x6f\xbc\x9f\xee\xe9\x64\x49\x24\xb7\xa4\x63\xed\x0c\xf9\x2d\xbf\xf6\xda\x2d\x8c\x6d\x19\xa3\xd2\x63\x8b\xf1\x8c\x4e\xb6\x2d\x29\xc9\x0c\xc9\x2b\xc9\xa8\x31\x43\xe6\xca\x18\x47\x37\xd0\xa9\xdb\xdc\x53\xbd\x27\xcc\x8b\xe5\xb3\x30\x08\xbd\x13\x61\xc8\x62\xc1\x18\x22\x89\xd9\xcc\x31\x1d\xd0\xb1\x10\x86\x7c\x16\xdb\xa4\x08\x2d\x0c\xd9\x28\x95\xd1\xd7\x54\x2d\x41\x89\xd0\xb4\x1a\x86\xf4\x93\x13\x6f\xa0\x23\xb5\x3e\x43\xd2\xc9\x19\x6e\xa3\xd9\x4a\x54\x24\x82\x99\xa5\x75\x23\x43\xca\xc9\x88\x18\x0f\x6a\xc0\x00\xfd\x45\x3f\xd5\x0e\x4c\x23\x69\x86\x11\xcb\x71\xae\x69\x0a\x05\xcb\x3f\xcc\x74\xc6\x95\xfa\x30\xdb\x51\xe2\xbc\x78\x8e\x76\xcc\xc7\x08\x33\x68\x3a\x37\x93\x96\x7b\x56\xd5\xcf\x6b\xbe\xe7\x90\x03\x81\xd4\x16\xa5\xc5\x74\x00\x30\x6e\x70\x49\x24\x9a\x2f\x43\x2f\xf0\x7c\x7b\x1f\x84\xac\xd2\x24\x93\x83\x21\xbb\xa5\x6f\xa3\xfd\xed\x53\xd8\x00\x67\x85\xd1\x67\x32\xda\xcd\x90\xf0\x82\xe7\x7e\x24\xc6\x0b\xa1\x6c\x2b\xba\xb3\x1f\x4f\x75\x48\x18\xc6\x52\xfb\x0e\x8c\x15\x46\x76\xe4\x12\x43\xe6\x8b\xed\x8b\x05\x90\x17\x45\x30\x9c\xa6\x07\x32\x24\xc0\x74\xfd\xd7\xaf\x83\xda\x93\x40\xda\x60\x86\x24\x98\x46\x0e\x33\x90\x88\x4a\x32\xe4\xb9\xdc\x51\xc9\x23\x21\x86\x9c\x17\x5b\x4b\x20\x59\x2f\x6c\xfd\x70\xa0\x43\xcb\x10\x32\x5f\x2a\x69\x20\x83\x77\x27\xdb\x53\x2f\x6d\x4d\x77\x17\xf9\x2f\x46\x8b\x33\x6d\x07\xd6\xe1\x70\xe7\x5d\x94\xe4\x04\xad\x1f\x0e\x77\x96\x83\x5d\x6c\xbd\x27\xe1\x49\xed\x8e\x3c\x98\x07\x3c\x6d\x42\x91\x0b\xf3\x00\x4e\xd9\x52\xa4\xc6\xd4\xae\x51\x5b\x12\x80\xb6\xcc\xda\x35\x99\x8f\xa7\x3e\xad\xa8\x35\x3d\xc2\x65\x58\x63\x5a\x9c\x53\x06\x02\xd9\x2d\x45\xaf\x94\xa5\x0f\x16\x19\xf2\x5b\x40\x29\xd9\x59\x49\x9f\x1f\x31\xe4\xb7\x04\x14\x75\x12\xc5\x90\xe3\x62\xec\x82\xd3\xc6\x90\xe9\x12\x71\x06\x49\x18\x92\xa8\x64\x4a\x88\x36\x33\x7a\xc2\xc2\x07\x77\x1f\x71\xb4\x94\x23\xa7\x45\xc1\x05\x54\x42\x18\x90\xce\x32\x61\x52\x32\xb0\xb9\x8b\x8c\x58\x38\x07\x63\x81\xcf\x12\xd3\x7c\x48\x60\xd8\x81\x45\xe7\x30\x4b\x78\x0c\x17\x44\xa4\x20\x12\x57\x86\x4d\x6d\x47\x13\xb9\x19\xf2\x5d\x9c\x3e\x3d\xb8\x90\x4f\xf7\x70\x08\x0e\x6b\x72\x44\x90\x0d\xe3\x6b\x99\xc7\x21\x1e\xea\xa0\x47\x1e\x79\x32\xbe\x86\x0f\x1c\xd2\x87\x4a\x92\x6b\x1f\xe9\x34\xd0\x9b\xd9\x29\x28\xf4\xe4\x5a\x43\x56\xcd\xa9\xa0\x5b\xe5\xe5\xb4\xd4\x4a\xcd\xc9\xc7\xbd\x25\x15\x2e\xb2\x6a\x4c\xdf\xc1\xcc\xf9\x95\x2d\xfd\x7d\xd4\x84\xed\xdc\x79\x6c\x8a\xf8\xcf\x1b\xcc\x26\xe5\x4b\x47\x3a\x96\xc8\xc0\x31\xfd\x3d\xb8\x38\xd5\xa6\x3f\xa4\x90\x27\x44\x0c\xb9\x39\xd7\x79\xd0\xf5\x6c\x48\x87\x02\xe9\x39\x85\x74\x42\xcf\x83\xdf\x85\xa3\xa2\x4e\x6c\xcb\xef\xdb\x63\x32\xbf\x78\xd8\x3e\x93\xa0\x38\x56\xc6\x55\x57\xf3\x44\x90\x8b\x6d\xcb\x0f\xc8\x44\x18\x8d\x21\x55\x67\x82\x36\xba\x6f\x53\xa1\x33\x86\x7c\x9d\x18\x9a\xaa\x16\x49\x3b\x23\xb6\xed\x1b\x30\x52\x24\xeb\xcd\x09\x6c\xb2\x62\x24\xab\x4e\xe7\xd3\xf4\x9a\x42\xbe\x8e\x07\xa5\x16\x2f\x92\x76\x6e\xba\x77\x7d\xb1\xa4\x4f\x90\xba\xe3\x91\x24\xc4\x0b\xe1\xfb\x9d\xa3\x32\xcf\x3f\xdc\xf3\x97\xbe\x74\x9c\xb7\x29\x41\x09\x64\xc8\xdc\x29\x8d\xee\x68\x1a\x3b\xdb\x85\x08\x3e\x17\xe7\x4c\x5f\xc0\x54\x8a\xf6\x90\x91\xc6\x23\x5b\xeb\xf8\xc9\x70\x8a\xdd\xc2\x76\x61\xe7\x21\xc5\x99\x5c\xd3\x48\xe7\xe1\xb4\xf3\x83\x44\x9e\x42\xba\xa2\x4f\x99\x3f\xa4\xea\x04\xd0\xc2\x58\x21\x6b\xc7\xf5\x4d\xa1\xc8\x16\x21\x67\x67\x42\x2c\x55\xb5\xc1\xdd\x44\x7b\x5a\x66\x91\x31\xa4\xf0\x44\x50\x5a\x0a\x91\xc9\x13\x01\x53\x8e\x1e\xd2\x79\x22\x68\x52\xd1\x23\xa5\x87\x77\x1d\xad\x4c\x90\xd0\x73\x95\x6d\x49\xd3\x5c\x19\x52\x79\x78\x5b\x1a\x2d\x49\x85\xbe\xbf\x73\x2e\x7a\x52\xbc\x90\xc5\x53\x1a\x59\x14\xf4\xa9\x0e\x43\x16\x8f\x3d\xdf\xc8\x10\x26\x43\x0a\x4f\xa5\x7b\x93\x9e\x9d\x40\xd6\x31\xa0\x14\xe9\xe3\x04\x92\x0e\x34\x9c\x6e\x0a\x72\x73\x92\xf9\xeb\x10\x9d\x70\x72\x66\xc6\x4f\x86\x3b\xd9\xd1\xcb\x10\xa9\x3a\xb6\x4f\xc4\x0e\x0e\xe1\xbc\x27\xc1\xd7\x60\x87\x40\x4a\x16\xb5\xbc\xd0\x6d\xdb\xa3\xcb\x4b\xaa\x16\xa4\xe2\x5c\xc8\x9d\x2b\x72\x70\xae\x20\x0b\xba\x01\x5e\x18\x0c\xb4\x86\xde\xc2\x1e\x02\xff\xf8\x04\x4a\xd2\xb7\x44\xd8\x41\xc4\xea\x66\x21\xa6\xce\x0e\x31\xb7\xeb\x7e\x5b\x27\x29\xf1\x07\x20\xf1\xa9\xc5\x74\x9c\xfb\x64\x8f\x47\x33\x0f\x0e\x55\xb2\x16\x86\x1e\x90\x5b\x0c\xcf\x21\x67\xe7\x5a\x03\x28\x51\x73\x49\x2a\x22\xe4\xed\x5c\x64\x03\x7a\x41\x0f\x21\x79\xc7\xf5\xe6\x2c\x6d\x9d\x29\x19\x6e\x0a\x4c\x07\x3e\x64\xf8\x9d\x21\xa5\x27\x8a\x2c\x27\x5a\x8b\xe7\xd6\x1d\x17\x90\xd9\xba\x77\x8e\x5e\x0e\x48\xed\xb1\x8a\xa6\x50\x31\xe4\xf4\x84\x5b\x8c\x0b\x9d\x42\x09\xd4\xa6\x4c\xb1\x63\x19\xd2\x78\x74\x07\x2d\xad\x91\x8e\xc5\xdd\x4a\x49\xd7\x47\x41\x10\x7f\x1c\x3e\x8f\xcb\xf4\xad\xbc\x80\xb1\xd2\xd1\x23\x26\x70\x5d\x1a\xc7\x4d\xf6\xe1\x64\xed\x64\x78\xd9\x7b\xfa\x2c\x79\x7c\xc5\x90\x0c\x74\xe3\xb5\xa6\xc7\xda\x8b\xed\x74\x22\x4c\x21\x90\xff\x63\xa0\x2c\xc9\xd3\x09\x86\xec\x9f\x09\xb1\x30\xc6\x3c\x84\xda\x06\x53\x07\x7d\xb7\xc4\xfb\x65\xc8\x06\x8a\xd0\x24\x0c\x77\x01\xa0\xa4\x90\x9a\x3c\xd1\x66\x48\x05\x2a\xe5\x89\xd4\x4e\xc8\x02\xea\x24\x94\x59\x27\x3b\x30\x59\x47\x0e\x28\xf2\x80\x22\x60\x22\x04\x80\x24\xa0\xd2\xf4\x1d\x1d\xd8\x44\xe2\xcf\x17\xad\x1b\xf2\x64\x91\x21\xdf\x47\xf1\xf6\xd4\x73\x5a\x51\x21\xcd\xa7\xe2\xa4\x05\x44\x92\x0f\x9e\x66\x91\x18\xdc\x89\xd6\x92\x8e\x54\x21\xcd\xa7\xe3\xa4\x6b\x86\x1c\x1f\xdb\x69\x7a\x8e\x90\xdf\x23\x12\x7e\x29\x32\x7b\x86\x7c\x72\xfe\x0a\x2f\x0b\x05\xd4\x89\x53\x34\x56\x6c\x66\x90\x05\x31\x2c\xc2\xa5\x63\xa0\xbd\xc8\x62\x17\x01\x96\x2a\xc2\x3d\x1d\x88\x5b\x42\x88\x0b\x74\x84\x7a\xa7\x67\x47\x2c\xa8\xe6\xc9\x42\x81\xee\x30\xdb\x68\x3a\xfe\x2e\x49\x38\x0f\x9e\x07\xdd\x86\x22\x4c\x4f\xe2\xce\x19\x2b\xd0\x4f\x82\x8b\xe4\xad\xa3\xf9\xc8\xac\x08\x5b\xb6\xbe\x2d\x53\x14\x29\x56\x78\x61\x29\xb9\xe3\x05\x7d\xe2\xcb\x90\x98\x35\xee\x25\xbb\x32\x11\x3e\x47\x36\xd6\x88\x1a\x14\x73\x02\x96\x47\x30\x78\x17\x40\x1f\xc6\x32\xb1\x8e\x3f\xaa\xaf\x60\x3a\x2d\x13\x94\x03\x86\xa4\xac\xca\x9f\x96\x39\x3d\x27\x6e\x4f\xe9\x0f\x37\xdc\xee\x39\xe3\x65\xb8\x44\xcd\xf1\x31\xf4\x57\xd9\x11\xa5\xbd\x9b\x95\x28\xbf\x8b\xca\x8f\x53\x41\xd5\xd0\x97\x52\x27\xca\xef\xa3\xf2\x8d\xbe\x48\xaa\xfd\xd3\x2d\x40\xba\xfc\x21\x2a\x3f\x9e\x47\xd0\xb0\x23\x7a\x13\x74\x2c\x5d\x04\xb2\x4e\x09\x34\x07\x9f\x21\xbd\xeb\x8b\xad\xc6\x87\x19\x48\x8c\xc0\x2d\x40\x05\x59\xa1\xfb\x59\xa4\x66\x4a\xec\xf5\xc7\x44\xcb\x2f\x73\xa2\x9a\xed\xbb\xee\xce\xff\xb9\x03\x4d\x42\x67\x22\x59\x2c\x78\x7a\xad\x76\x24\x89\x92\x21\x6b\x6c\xee\x24\x19\xb0\xd2\xba\x48\x99\xf9\xd4\x82\x64\xd8\x30\x64\x96\xcd\x6f\x58\x42\xd3\xd1\x97\x5a\x58\x79\xa7\x73\x2f\x28\xb0\xf2\x7e\xda\x49\x66\xfb\x05\x73\xcb\x84\x6e\x0a\xd9\x72\xa7\x1f\xf6\xa7\x53\x00\x4c\x10\x89\x35\x17\x67\x30\x59\x0b\xf4\xe6\xae\x0c\x17\x75\x5b\x01\xd3\x53\x6a\xb4\xe3\x8f\x5c\xb4\x5f\x7f\x25\x73\x77\xb8\x6f\x10\x35\x9f\x4d\xde\x15\xe4\x3b\xc9\x8a\x62\x48\x4b\xb3\xd0\xce\xbc\xa9\x91\x4b\x99\xbc\x7e\xc3\x90\xa9\x36\x14\x9b\x2f\x98\xa8\x20\xbd\x14\x90\xbe\x56\x4b\xeb\x34\xed\x1c\x07\xea\xda\x24\x4e\xae\x4e\xb4\xdd\xaf\x88\x1a\x38\x7d\xbd\x85\x21\x59\xad\xe3\x86\x9f\x0c\xef\x48\x91\x0c\xbc\x34\x25\x4b\x9a\x3a\xcb\x90\x83\x36\x45\xb1\x13\x3e\x0e\x92\xd0\x02\x68\x41\xd6\x20\xdc\x01\x6f\xc8\xf0\x26\x84\x08\x9b\x10\x60\xb2\x82\x47\x5c\xa0\x49\x2f\xf5\xae\xd0\x09\xd5\x8e\x04\x34\x47\x3b\xd2\x48\x32\x2b\x64\xab\x45\xaf\x68\x4e\x2a\x83\xfb\x06\x85\x5c\xf2\xc8\x2f\x1b\x47\x2d\x75\x0f\x8f\x21\xa9\xcc\x5d\x65\x42\x21\x20\xa7\xec\x06\x8a\xf4\x31\x91\x4f\x36\xac\x9d\x49\xb6\xe8\x3e\x73\x0c\xa1\x54\xa4\x5b\x80\xcc\x31\xc1\xd5\xd0\x67\x47\x9f\x67\x41\x90\x97\x5b\xc2\x4d\x45\xce\x98\x27\x8d\x5e\xb9\x4a\x50\x4c\x90\x34\x26\x44\x76\x91\x96\x74\x68\x91\x34\x26\x44\xd6\x8c\x37\x04\x13\xb7\x18\x18\xd2\xc6\x84\xc8\x4a\x69\x85\xbe\xd0\xd2\x8e\xcc\x31\x21\x32\xde\x00\xe9\x00\x87\xbb\x07\x62\xa1\x8f\x81\x3d\x26\x46\x2e\x31\x1d\x07\x42\xfe\xd8\x48\x53\x4b\x9e\xfb\x06\xfa\x58\x40\xd1\xd3\x87\x04\xb2\xf1\x25\x14\x12\x80\x07\xa5\xba\xbb\x25\xc3\x0e\xc8\x1d\x23\x5f\xf0\x60\xc8\x1b\x83\x1b\x94\x46\x77\x5d\x62\x10\x43\xe4\x64\xf0\x86\x0a\xd3\x27\xda\x83\x3b\x09\x69\x5c\x5d\xf2\x5b\x26\xf8\x99\x1e\xa7\x10\x3a\x01\x9e\xbc\xdc\xc6\x90\x41\xd6\x49\x48\x82\xf2\x97\x3b\xcb\x75\x09\x85\xaf\x90\x70\xeb\x2a\xca\xa3\xcf\x91\x28\x36\x21\xd2\x5a\x2a\x47\x92\x98\x8f\xcb\xd0\xcf\x88\xe4\x48\x12\x43\x14\xa5\xab\x73\xa4\x88\x15\x32\xb5\x3b\xc8\x5f\x02\xd5\x90\x52\x48\x39\x52\xc3\xa4\x7e\xaf\x35\xc9\x15\xcf\x91\x1a\xc6\xdb\x13\xa8\xc4\x8b\x11\x39\xb2\xc3\x04\x75\x5a\x91\x23\x33\xcc\xd6\x70\x86\x39\xbb\xa5\x86\x5f\xe7\x29\x52\xd1\x0d\xf5\x12\xd4\x00\x6f\x3b\x4e\x3e\xba\x91\xbf\x84\x8d\xe8\xcd\x82\x52\xbc\xa4\x6b\x0a\x87\xa2\x6d\x0b\xc2\x95\x30\x06\x6e\x48\x64\xd8\x66\xd8\x3a\xb1\xaf\xcc\x59\x78\x97\xc4\xf4\x4d\x41\xee\x8e\x72\x24\x8a\xa9\xa1\xed\xe4\xc9\x5b\x8e\xa4\xb0\xa1\xdd\x96\x32\x30\x39\x12\xc2\x6c\x2d\x8d\xb3\xb2\x2d\x7a\x45\x05\xa4\x72\x24\x85\x59\xd9\x74\xea\x36\xec\xc9\xc9\x09\x0b\x94\xb0\xf3\x8d\x3b\xc5\xc9\x91\x62\x77\x0e\xbe\x4b\x31\xf9\x73\xb6\x8f\x40\x8b\x47\x06\x79\x78\xf1\x48\xf2\x46\x93\x17\xc8\x73\x16\x6e\xe1\x92\x17\x4e\x72\xa4\x98\x8d\xac\x61\x0b\xc2\x90\x76\x22\x47\x9a\x59\xa3\x9d\x36\xc9\xb5\xc1\x42\xa8\xd6\x00\xb8\xec\x22\x81\x8a\x3d\xe4\xc8\x35\x1b\x6f\x6f\x16\xf4\x4b\x46\x39\xd2\xcc\x2e\x40\xdf\x5a\xcf\xef\x1c\x32\xd2\x35\xc8\x91\x24\xd6\x80\x11\x3d\xe9\xc1\xe5\xc8\xf5\x1a\x2f\x6d\xd8\x60\x8b\x7c\x44\x94\xb7\xf6\x34\x3e\xd8\x4b\x16\xdd\x04\x53\x80\xb0\x84\xc7\x95\x87\x67\x8e\x86\x9e\x78\xc6\x2b\x89\xdb\xdd\x3b\xb4\x04\xdb\xc7\xd5\x25\x7b\x7f\x88\x2a\xb3\xce\x68\x52\xef\xe7\x48\x00\x8b\x60\x24\x5b\x25\x47\x0a\x58\x0c\x24\x75\x06\x92\xc0\x5a\xe8\xe9\xeb\x03\x39\x32\xc0\xa6\x51\x53\x74\xdc\x36\x47\x16\x58\xb8\xb8\xa9\xab\x4a\x0a\x49\xfa\x02\x39\x92\xbc\xee\xd7\x6f\x48\x61\x47\x7e\xd7\xb5\xe6\xce\x72\x32\x5a\x98\xaf\x83\xe2\x30\xb4\x03\x93\x23\xbb\x6b\x5c\x32\xa9\x55\x8c\xac\xae\x11\x94\x7a\x1f\x2e\x47\x66\x57\xad\xdd\x5c\x69\x17\x24\xf7\x32\x47\x9e\xd7\x45\xf2\x88\x21\x30\x87\xdc\x7d\x94\x04\x00\x37\x45\x7d\x71\x25\x0f\x9f\xf2\xf5\x9d\xdc\x2e\x7b\xd2\x36\x23\x69\xeb\x26\x66\x9b\xca\x68\xcf\x49\x96\xf2\xa2\xa1\x3b\x27\xdb\xac\xd1\xad\x4d\x48\x08\x52\xba\x74\x07\x6d\xe2\xd5\x80\x7c\x1d\xae\x5a\x77\x50\x4a\x07\xa5\xb5\xb4\x68\x84\xcb\xfc\xce\x81\xb9\x65\x9b\xd9\x30\x4f\x89\x44\x52\x4c\x1b\x9d\xd5\x87\x14\x30\xc4\xad\xa9\xc2\xae\x36\x00\xd9\xe0\xb1\x38\x7a\xaf\x96\x23\x47\x0c\x4b\xe4\x54\x35\x89\xeb\xef\x39\x52\xc7\x10\xc7\xa8\xc2\xfe\xeb\x64\xf9\xf5\xbc\xfc\x0b\x55\x3e\xa6\xd4\xce\x4b\x6f\xd0\x16\xf4\x16\xb2\x31\x1e\x97\xf8\x8c\x97\x6e\x99\x89\xde\x58\x5a\x26\x90\x6e\xa6\x8b\x2f\x20\xdc\xec\x9e\xe8\x1c\xb7\x9f\xe1\xfa\x36\x8d\x0c\x0f\x08\x48\x71\xbe\x65\xad\x26\x2f\x2e\xe7\xc8\x39\x8b\x60\xa4\xd3\x9f\x23\xe9\x4c\x88\xec\x8b\x20\x7d\x0d\x64\x9b\x8d\x1b\x9f\x16\x8c\xcd\x84\xa2\xbd\x92\xcd\xfd\xd6\x0f\x19\xb1\xc8\x37\xe1\x01\x1c\x35\x45\xc4\x05\x7d\xac\x9c\x23\xcd\xac\xd6\xbd\x19\x1f\x15\xa5\x1b\x8f\x3c\xb2\x3b\x6c\x26\x2b\xf7\x64\x9b\x08\x20\xe7\xc8\x23\xbb\x43\x73\xba\x86\x94\xb0\x22\x81\xec\x8e\x5c\xd3\x15\x00\xed\xc1\x20\xa3\x2c\x00\x49\x50\x7c\xbd\xfc\x64\x78\x31\x8f\x43\x8c\xc9\x26\xf5\xb2\x64\xbe\x8d\x6f\x9d\x5b\xa7\x3b\xa2\x74\x7a\x57\x9f\x6f\xe3\xfb\xe8\x78\x6b\x38\x01\xdd\x47\x50\x25\xbf\xa6\x18\xfb\x39\x32\xc7\xa6\x3a\xbb\x74\xd3\x8f\x11\xce\xaf\xc5\x04\x92\xc7\x48\xe0\x22\x21\xef\xe1\x5d\x27\xc3\x4b\x48\x3c\x40\x98\x6f\xc3\xe3\xa8\x27\x39\x68\x71\xda\x5c\x21\x5f\x4c\x18\x18\x5f\xfd\x1d\x2f\x03\x6a\xf2\x96\x67\x8e\x84\x31\xf2\xb0\x2f\x47\x8e\xd8\xe9\x94\x3e\x7d\xcc\x91\x1c\xe6\x8c\xec\x78\x79\x91\x09\x95\x83\xbc\x30\x5d\xb6\xfa\x3c\x08\x54\x2b\xcf\x54\x34\x26\x47\x4e\xd8\x0c\xb8\xb0\x11\xdd\x85\xf7\x55\x5c\xd6\xa5\xd8\xdc\x39\xb2\xc3\xae\xf2\x2c\x07\xd3\xc5\x33\xd2\x49\xde\x85\x9b\xe0\x15\x37\x74\xf3\x02\x8b\xdb\xd0\xcf\xae\xe6\xbb\x10\xf6\x37\x50\x91\x64\xae\x1c\x79\x61\xba\xa3\xdf\x0e\xcc\x91\x10\x36\x4a\x56\x0b\x6e\x30\xb8\x4a\x1b\x5a\xe3\x23\x35\xcc\x5d\x66\xae\x34\x28\xb8\x48\x4b\x5f\x2e\xc8\x91\x24\x36\xa4\x71\x52\x22\x91\x21\xb6\x7d\x79\xe9\xe8\x4e\x20\x91\xa3\xe1\x5f\xe9\x8f\x20\x47\x2c\xf0\xf6\x47\x46\x03\xf9\x35\x64\x8a\x05\xe8\xc4\x84\xa6\xb1\x8f\xd7\x01\xa6\xc7\xd0\x68\xec\xfa\x01\x3b\xb1\x9d\x69\xec\x06\x07\xbd\xec\x2d\xcd\xcd\xc8\xef\x4f\x3e\x75\x83\xdf\x4b\x42\x76\x77\x88\x95\x27\x7a\xe1\x21\x47\x6c\x00\xd1\x8d\x09\x5b\x09\xd2\xde\x22\x2d\xcc\x5f\xf4\xa5\xcf\x5e\xf2\x3d\x7f\x44\x25\x3e\x56\x04\x6d\xff\xf5\x2b\x09\x08\x6f\x5e\x36\x40\xd7\x80\x26\x54\x71\x71\xce\x9c\x24\x57\xc6\x9d\x1f\xd6\x3a\x29\x12\x2a\xe9\x30\xa3\x51\x64\x5c\x49\xf2\xcc\x2b\x47\x92\x18\x94\xe4\x71\x7f\x1e\x9e\x6f\xba\xbf\x02\x93\xda\x2b\x22\x5b\x4c\xe8\x52\x42\x47\xb7\xfd\x10\xfc\xaf\x92\x5c\x0d\x48\x0d\xab\x46\x3e\xed\xf4\x8b\x34\x24\x2e\x3c\xd3\x4d\xfa\x2a\x48\x0e\xeb\x8c\x2e\x7b\xe1\xb2\xba\x27\x9f\x1e\xcb\x91\x25\xd6\xc8\xf7\xd4\xf9\x72\x8e\x5c\x31\x2b\x8c\x2c\x68\x04\x52\xfb\xf9\xe0\x54\xa6\x75\xfc\xa1\xf8\x88\xa3\x25\xe9\x10\xbd\x5d\xb9\x54\x61\xf9\x01\x96\xa8\x2f\x9c\xae\xf8\xf7\xcc\x0a\xf2\xfd\xdf\xfc\xf8\xf2\x01\x67\x13\xa6\x00\xb9\x60\x35\xb7\x35\xfd\x9a\x70\x8e\x34\xb0\x42\xf5\xe0\xb4\xa6\xe3\x74\xc8\x02\x0b\xa0\x8c\x9c\xd1\xf0\x82\x13\x18\x01\xf4\x64\x22\xe1\xeb\x24\x9d\xe2\x74\x25\x78\x7c\xd7\x15\x70\x4a\x5d\xf6\xcc\x91\xe6\x75\xed\x2a\x6d\x1a\x72\x75\x45\x44\x2f\x49\x9b\x1e\xe4\x77\x79\xc6\x15\x57\x19\x17\x22\x11\x2e\x40\x9a\xd7\x9d\x2e\x97\x5a\x62\x48\xf7\x7a\x78\x2f\x93\x9e\x74\xa4\x73\x15\x4a\xd2\xde\x29\xb2\xb5\xa6\xc3\xfb\x12\xa6\x8b\x6f\x09\x53\x87\xcc\x2d\xff\x46\xf5\x90\x65\xb4\x4a\xbe\xa8\x95\x87\x77\x9c\x0c\x97\x8a\x16\x5f\x24\x72\x71\x6b\xa5\x1d\x7d\x2c\x35\x38\x64\xed\xc8\x06\xbf\x59\x07\xf4\xe0\x23\xad\x8b\x5b\x35\x59\xf6\xce\x80\x7b\x78\x05\x91\x8f\x8c\x79\xde\x4e\x8f\x94\x21\x9f\x89\x82\xcf\xab\xc6\x87\x25\x80\x57\xed\x7d\xb6\xbc\x27\x3d\xf8\xbb\xd5\x18\xf9\x7b\xf8\x5a\x49\x3f\x05\x99\x23\x57\xec\xa4\x24\x79\x97\x34\x47\x9e\xd8\x08\xc8\xe8\x26\xa1\x2f\x25\x4f\x8f\x4f\x3d\xce\xfa\x46\x96\x0d\x14\xea\x6b\x96\x76\x62\x90\x39\x76\x91\xbc\xa4\xcd\x12\x3f\xc6\x88\x05\x2f\x12\x09\x64\xb6\xe5\x5d\x74\x42\x3e\xc7\x14\x73\x4c\x76\x4a\x1d\x36\x20\x97\x2c\x20\x17\x3e\x8c\xf7\x2e\x03\x4f\x8e\x44\x85\xe7\xa3\x8c\x75\x59\xfc\x78\xd0\x0c\x86\xfc\xb2\x9b\xe6\x74\xc3\x90\x5f\xe6\x6a\x68\x40\x5a\x5a\xba\xc3\xf3\x51\xd1\x53\x39\x33\x55\xfe\xf4\x98\xbb\x14\x25\x44\x46\x5a\x35\x63\x75\x8c\xbf\xdd\xb1\x60\x26\x8b\x68\x6b\x69\x6b\x7e\x4e\x68\x0a\x64\xa8\xdd\x7f\x7d\x83\x66\xc8\xe4\xc8\x54\x9b\x01\x13\x75\xa2\xec\xc9\x96\xbe\x48\x9d\x07\xae\x5a\x59\x1a\xb0\x36\xf5\xa8\x7c\x8e\xf4\xb4\x18\x97\xf8\xa6\x17\xbf\x8b\x78\x60\xae\x62\xd1\xc4\xf1\x6f\x8e\x94\xb5\xb1\xe0\x7c\x03\x1d\x17\x4d\x7c\x55\x44\xe1\xd2\xb4\xb1\x46\x36\x5b\x04\x4b\xd4\x17\x3f\x86\x42\x22\x90\xce\x26\xcb\xac\xe0\x09\xc7\x0d\xc9\x6c\xa5\x19\x0d\x50\xe6\x7f\x38\x32\xee\x9a\x2c\x93\x03\x82\x1c\xb7\x87\xd2\xf3\xa1\xf1\xe5\x13\x6d\x5c\xa3\xa9\xd2\xb4\x85\x0c\x8c\x37\x03\x9e\xd7\x25\x78\x43\x7a\xe9\xc8\x60\x1b\xf6\x62\x89\x9b\x38\xb9\x08\x4f\x79\x82\x69\xa6\xe7\x7f\xe6\xe1\xd2\x28\x23\x91\x9c\x0c\x9b\x8a\xfd\xc7\xba\xd7\xa9\x4a\xfe\x7d\xf8\x54\x1c\x3e\x56\x97\xa7\xaa\x4b\x45\xa6\xc4\xf1\x63\x25\x2c\x55\xc9\x42\x38\x55\xf0\x8f\xf5\xbc\xa4\xea\x49\x86\x55\xc3\xc3\x68\xb5\xbe\x26\xbe\x83\xce\x08\x77\xb5\xeb\x67\x3c\x53\xcb\xb6\xf1\x9f\x45\xe2\x40\x17\x19\x70\x9d\x2e\x45\x42\x2f\x23\xf5\x6d\xba\xe5\x93\x35\xfc\x5d\x36\xf2\x2b\xb9\x3c\x90\xe0\x86\x50\xd9\xa6\xa1\x6c\x06\x35\x60\x9d\xa6\xad\x50\x19\x9e\xfe\x1f\x76\xd2\x06\x84\x8b\x9f\x5f\x7e\x8a\x2a\x89\x7f\x86\x67\x5e\xc5\x9a\xac\x62\xbe\xf0\xe2\x4a\xe8\xd5\x87\x7c\xb7\x82\xb7\x65\x6a\x59\x21\xd5\xed\x64\x38\x79\x6c\x86\x64\x37\x70\xf4\x21\x34\x12\xdb\x64\x53\x92\xde\x36\x32\xd8\x0c\xbf\x80\xa2\xe3\x00\xc8\x54\x03\x30\xa9\x39\x45\xa6\xda\xf8\x06\x82\x48\x9c\x04\x97\xc1\xa7\xd0\xd7\x4a\x25\xed\x5c\x78\x59\xad\xef\xc0\x8c\x8c\x5c\x72\x81\x22\x5d\xed\xda\x2d\xc5\x8b\x90\xb1\xd6\x00\x38\x3a\x9a\x3f\xd2\xd5\xac\xc9\x74\xab\x6e\xc4\x4f\x79\xf9\xdf\xf0\xea\xde\xf1\x17\xc3\x86\x7f\xe2\x4f\x6c\xe2\x4f\x88\xbe\x66\x43\x6a\xb8\xa8\x58\xcb\xb2\x84\xf6\x6d\x7c\x82\x71\x10\x8e\x4f\x2f\x4f\x2b\xff\xdf\xcf\xf8\x2b\x9c\x2f\xe1\xa3\x59\xa5\x45\x6f\xc7\xe7\x05\xb9\x18\x1c\xec\x27\x22\x67\xfc\xd7\xbd\x79\xd6\x71\x27\x85\x6f\xdc\xf8\x53\xaf\xbe\x75\xe3\xbf\x7d\xa3\x5e\xee\x2d\x1a\xfc\xca\x42\xc1\xd4\xa4\x01\xf3\xfd\x0f\xff\x11\x00\x00\xff\xff\xdc\x38\xf5\x02\x18\x79\x00\x00")
+
+func uiAppLibFontAwesome470CssFontAwesomeMinCssBytes() ([]byte, error) {
+ return bindataRead(
+ _uiAppLibFontAwesome470CssFontAwesomeMinCss,
+ "ui/app/lib/font-awesome-4.7.0/css/font-awesome.min.css",
+ )
+}
+
+func uiAppLibFontAwesome470CssFontAwesomeMinCss() (*asset, error) {
+ bytes, err := uiAppLibFontAwesome470CssFontAwesomeMinCssBytes()
+ if err != nil {
+ return nil, err
+ }
+
+ info := bindataFileInfo{name: "ui/app/lib/font-awesome-4.7.0/css/font-awesome.min.css", size: 31000, mode: os.FileMode(420), modTime: time.Unix(1, 0)}
+ a := &asset{bytes: bytes, info: info}
+ return a, nil
+}
+
+var _uiAppLibFontAwesome470FontsFontawesomeOtf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x9c\xfa\x79\x7c\x93\xc5\xfa\x07\x0c\xcf\x34\xc9\x9d\x74\x26\x4b\x97\xa4\xd2\x26\x77\x02\xc8\xa2\xb2\xb5\xd9\xda\x0a\x28\x50\x16\x05\x41\xc4\x88\x2c\xc2\x4d\xda\xa6\x4d\x68\x9a\x84\x24\x5d\xa1\x74\x87\x42\xa0\xd0\x36\xa5\x94\x52\x5a\xa0\x2a\x9b\x2c\x82\xe0\x7a\xac\xc7\xa3\x22\xb8\x13\x3d\x8a\xfb\xf6\x73\x45\x3d\x1e\x74\xd2\x4c\x8a\xef\xe7\x4e\xc0\xa3\xef\xf3\xc7\xfb\x7e\x1e\x42\x73\x5d\x33\x99\xb9\xbe\x33\xd7\x5c\xdb\xe4\xce\xbd\x16\xcb\xbd\x00\x81\x3a\x20\x00\x23\xf3\xe6\xce\x1d\x99\xeb\xfb\x2a\x1b\x00\x70\x0c\xc0\xc8\x73\x73\x16\xcf\x5c\x02\x58\x70\x0b\x80\xd4\x09\x00\xc8\xbc\xf7\xfe\x29\xfa\x16\x7d\xf5\x6a\x00\xe9\x5e\x00\xc0\x9a\x82\x52\xab\x07\xbe\x72\xc0\x02\x20\x8d\x02\x20\xd0\xd8\x6d\xd6\x42\xf1\x9e\x9f\x8f\x01\xf8\xc7\x08\x00\x80\xd9\x6e\xb7\x59\x15\x02\x74\x06\xc0\x3f\x16\x03\x00\xc6\xd8\x4b\xfd\x95\xf3\x27\xdc\x74\x1e\xc0\x3f\xfc\x00\xa0\xef\x4b\xad\x95\x9e\x84\x17\x16\x03\x90\x80\xd6\x00\x00\x18\x97\xb5\xd4\x76\x47\xd2\x98\x9b\x41\x02\xb2\x03\x20\x94\x79\xdc\x3e\x3f\x10\x00\x00\x12\xe4\x95\x00\x80\x91\x10\x08\x05\x00\x42\x28\x9d\xeb\x76\xf9\x67\x56\xd8\x7c\xee\x52\x1b\xdf\xce\x0b\x27\x81\xc8\x9b\x30\xf2\x56\x42\xe4\x2d\x41\x38\x5d\x18\x90\x0a\x02\x52\xe1\x56\xda\xa9\x49\x84\x1a\x06\x8a\xb4\xfd\xe0\x81\x3a\xf3\x1f\x81\xc0\x9f\x8c\x54\xac\xd1\x9f\x53\x68\xf4\x9f\x26\x1f\x67\x01\xfc\x4c\x96\x92\x70\x36\x01\x40\xc0\x00\x0c\x92\x41\x3a\xd0\x82\xd1\x60\x22\xc8\x04\x46\x30\x0d\xdc\x01\xe6\x80\x79\x60\x21\xb0\x80\x87\x00\x07\x6c\xc0\x0e\x4a\xc1\x3a\x50\x05\x6a\x40\x3d\xd8\x0e\x3a\x41\x0f\xe8\x07\x47\xc1\x29\xf0\x24\x18\x04\xff\x02\xe7\xc1\x3b\xe0\x23\xf0\x0d\xf8\x05\xfc\x0e\x86\x21\x80\x42\x28\x81\x49\x50\x05\xd5\x50\x07\x6f\x86\xb7\x42\x23\xbc\x03\xde\x05\x2d\x90\x83\x4e\xe8\x81\xeb\xe1\x66\xd8\x09\xf7\xc2\x03\xf0\x18\x7c\x1c\x9e\x85\x4f\xc3\xe7\xe1\xbf\xe0\x79\xf8\x2e\xfc\x02\x7e\x0f\x7f\x82\xff\x85\x04\x5e\x4b\x40\x09\x69\x09\xea\x84\xf1\x09\xc6\x84\xe9\x09\xf3\x12\x96\x24\x2c\x4f\x28\x4a\x70\x27\x54\x25\x6c\x4a\xd8\x91\xd0\x9d\x70\x30\xe1\x78\xc2\xd9\x84\xc1\x84\x57\x13\x42\x09\x9f\x25\xfc\x92\x70\x35\x21\x9c\x10\x15\x08\x05\x32\x41\xba\x40\x2b\x18\x27\x98\x28\x30\x08\x72\x05\x79\x82\x7b\x05\x4b\x05\x05\x02\xb7\xa0\x5a\xb0\x45\xb0\x47\x70\x50\x70\x42\xf0\xac\xe0\xbc\xe0\xa2\xe0\x4d\xc1\xbf\x05\x5f\x09\xfe\x2b\x88\x0a\xc5\x42\xb9\x50\x2d\x1c\x2d\x9c\x22\x34\x09\xa7\x0a\xe7\x0a\x17\x0b\x1f\x10\xae\x10\xda\x84\x3e\x61\x8d\xb0\x49\xb8\x4d\xd8\x2e\xdc\x2d\x3c\x28\x7c\x44\x78\x58\x78\x4a\xf8\x84\x70\x50\x78\x41\x78\x49\x78\x59\xf8\xa5\xf0\xaa\x88\x11\xa9\x44\xe3\x44\x13\x44\x59\x22\xb3\x68\x9a\x68\x8e\xe8\x5e\xd1\x83\x22\x4e\x64\x17\x95\x8a\xd6\x89\xca\x45\x1b\x44\xb5\xa2\x46\xd1\x76\x51\x9b\xa8\x47\x74\x40\x34\x20\x7a\x44\x74\x5a\xf4\xac\xe8\x05\xd1\xcb\xa2\x8b\xa2\x90\xe8\x0b\xd1\xaf\xa2\x61\x26\x81\x91\x32\x4a\x46\xcb\xdc\xca\x64\x32\x46\x66\x3a\x33\x9b\x59\xcc\x2c\x63\x1e\x62\xac\xcc\x5a\xa6\x8c\xa9\x67\x9a\x99\x6d\x4c\x90\xe9\x66\x0e\x32\x47\x99\xa7\x98\x97\x98\xd7\x98\x7f\x33\x9f\x32\xdf\x30\x57\x98\xff\x30\xd7\xc4\x8c\x58\x2e\xbe\x49\xcc\x8a\x6f\x11\x4f\x14\xeb\xc5\x66\xf1\x3c\xf1\x72\xb1\x5d\x5c\x25\x6e\x14\xb7\x8a\x77\x89\xfb\xc5\x8f\x8a\x1f\x13\x9f\x16\x3f\x2f\xbe\x28\x7e\x57\xfc\x99\xf8\x1b\xf1\x15\xf1\xaf\xe2\xa8\x44\x2a\x51\x4b\xc6\x4a\xb2\x24\x66\xc9\x54\xc9\x1d\x92\x39\x92\x85\x92\x07\x24\x05\x92\x12\x89\x5b\x52\x29\xd9\x2c\xe9\x94\x74\x4b\x0e\x48\x0e\x49\x8e\x49\xce\x49\xfe\x29\xb9\x28\x79\x53\xf2\xa1\xe4\x6b\xc9\x7f\x25\x43\x89\xe2\xc4\x11\x89\xda\xc4\x31\x89\xa6\xc4\x79\x89\x4b\x13\x8b\x13\x9d\x89\x9e\xc4\xf2\xc4\xba\xc4\x96\xc4\x9e\xc4\x63\x89\x27\x13\x9f\x4a\x7c\x3e\xf1\xf5\xc4\xf7\x13\x3f\x4b\xfc\x3e\xf1\x6a\xe2\x30\x82\x08\xa3\x14\x94\x81\xc6\xa1\xdb\xd0\x24\x94\x89\x0c\xc8\x8c\x72\xd1\x34\x74\x27\x9a\x85\xe6\xa2\x7b\x11\x87\x0a\x50\x19\x0a\xa0\xdd\xe8\x30\x7a\x0c\x9d\x42\xcf\xa1\x7f\xa1\xf3\xe8\x6d\xf4\x31\xfa\x0a\xfd\x07\x45\x30\xc0\x02\x2c\xc6\x2a\xac\xc6\xe3\xb0\x09\xcf\xc2\xf7\x61\x2b\x2e\xc2\xa5\xd8\x8f\xab\x70\x1d\x6e\xc6\x3b\x70\x27\xee\xc1\x7d\xf8\x61\x7c\x08\x1f\xc3\xa7\xf1\x59\xfc\x24\x7e\x0e\xbf\x88\x5f\xc1\xef\xe2\x0f\xf0\x4f\xf8\x57\x29\x90\x0a\xa5\x49\x52\xa5\x74\x94\x74\xac\xf4\x56\xe9\x24\x69\x96\xd4\x24\xcd\x95\x4e\x97\xce\x94\xde\x25\xbd\x47\xba\x58\x6a\x91\x2e\x93\x3e\x24\x5d\x23\x2d\x94\xda\xa5\x4e\xa9\x47\xea\x97\x56\x4a\x37\x48\xeb\xa4\x9b\xa5\x01\xe9\x0e\x69\x87\xb4\x4b\xda\x23\xed\x93\x1e\x94\x3e\x2a\x3d\x2a\x3d\x21\x3d\x2d\x3d\x27\x7d\x46\xfa\xbc\xf4\x65\xe9\xeb\xd2\xb7\xa5\xef\x4a\x3f\x90\x7e\x2c\xfd\x5c\xfa\xb5\xf4\x3b\xe9\x15\xe9\x7f\xa4\xbf\x49\x87\xa4\xc3\x32\x28\x93\xc8\x14\xb2\x34\x59\x86\x4c\x2b\x1b\x2b\x9b\x28\x33\xc8\xb2\x65\x53\x65\x77\xca\xf2\x64\xf3\x64\x0b\x64\xf7\xca\x96\xca\x56\xc8\x56\xcb\xf2\x65\x45\xb2\xb5\x32\x97\xcc\x2b\x2b\x97\x55\xcb\x36\xca\x1a\x64\x9b\x64\x5b\x65\xad\xb2\x4e\x59\xb7\xac\x57\xb6\x5f\xf6\xb0\xec\xb0\xec\x31\xd9\x29\xd9\x13\xb2\xa7\x64\xcf\xc9\x5e\x90\xbd\x24\x7b\x55\xf6\xba\xec\x6d\xd9\xbb\xb2\x0f\x64\x1f\xcb\x3e\x97\x7d\x2d\xfb\x4e\x76\x45\xf6\x1f\xd9\x6f\xb2\x21\xd9\xb0\x1c\xca\x45\xf2\x44\xb9\x4c\x9e\x2c\x57\xc9\xd3\xe5\xac\x7c\x94\x7c\xac\xfc\x56\xf9\x24\x79\x96\xdc\x24\xcf\x95\x4f\x97\xcf\x94\xcf\x91\xcf\x97\x2f\x92\x2f\x91\x2f\x95\xaf\x90\xaf\x96\xe7\xcb\x8b\xe4\x6b\xe5\x2e\xb9\x57\x5e\x2e\xaf\x96\x6f\x94\x37\xc8\x37\xc9\xb7\xca\x5b\xe5\xed\xf2\x5d\xf2\x3d\xf2\x7d\xf2\x03\xf2\x47\xe4\x47\xe4\xc7\xe5\x8f\xcb\xcf\xca\x9f\x96\xff\x43\xfe\x4f\xf9\xcb\xf2\x0b\xf2\x37\xe4\xef\xc8\xdf\x93\x5f\x96\x7f\x22\xff\x42\xfe\x7f\xf2\xef\xe5\x3f\xc9\x7f\x95\xff\x2e\x8f\xc8\xaf\x29\x12\x14\x8c\x02\x29\xe4\x8a\x14\x45\x9a\x22\x43\xa1\x55\x8c\x56\x8c\x53\xdc\xa6\x98\xac\xd0\x2b\xcc\x8a\xdb\x15\x77\x28\x66\x29\xe6\x2a\xe6\x2b\x16\x29\x96\x28\x96\x2a\x56\x28\x56\x2b\xf2\x15\x45\x8a\xb5\x0a\x97\xc2\xab\x28\x57\x54\x2b\x36\x2a\x1a\x14\x9b\x14\x5b\x15\xad\x8a\x76\xc5\x2e\xc5\x1e\xc5\x3e\xc5\x01\xc5\x23\x8a\x23\x8a\xe3\x8a\x27\x14\xcf\x2a\x06\x15\xff\x52\x9c\x57\xbc\xa9\x78\x4f\x71\x59\xf1\x89\xe2\x0b\xc5\xff\x29\xbe\x57\xfc\xa4\xf8\x55\xf1\xbb\x22\xa2\xb8\x96\x94\x90\xc4\x24\xa1\x24\x79\x52\x4a\x52\x5a\x52\x46\x92\x36\x69\x74\xd2\xb8\xa4\xdb\x92\x26\x27\xe9\x93\x72\x93\x66\x24\xcd\x4b\x5a\x94\xf4\x40\xd2\x43\x49\x05\x49\x6b\x93\xd6\x25\x55\x26\xd5\x26\x6d\x4a\xda\x9e\x14\x4c\xea\x49\x3a\x90\x74\x38\xe9\x64\xd2\xb9\xa4\x7f\x24\xbd\x94\xf4\x5a\xd2\xa5\xa4\xcb\x49\x9f\x27\x7d\x9b\xf4\x73\xd2\xef\x49\xc3\xc9\xc2\x64\x9c\x9c\x92\x9c\x9e\x3c\x32\x79\x7c\xf2\xe4\x64\x53\xf2\xb4\xe4\xbc\xe4\xf9\xc9\xf7\x25\x2f\x4b\xe6\x92\x8b\x92\x4b\x93\xfd\xc9\xeb\x93\x1b\x92\xb7\x24\xef\x4c\xee\x4a\xde\x97\xfc\x70\xf2\xb1\xe4\xd3\xc9\x4f\x27\xbf\x90\x7c\x3e\xf9\xcd\xe4\xf7\x92\x3f\x4e\xfe\x2a\xf9\x87\xe4\x5f\x93\x87\x52\x40\x8a\x38\x45\x9e\x92\x92\x92\x9e\x32\x32\x65\x7c\xca\xe4\x14\x53\xca\xb4\x94\x92\x94\xf2\x62\xa7\xd5\xe7\x2b\x2d\xf3\x39\x0a\x7c\x36\xab\xb7\xc0\x6e\x73\x95\xdb\x9c\x6e\x8f\xcd\x6e\xb3\x7a\xfd\x3e\xbf\xd5\xcb\xff\x71\xb6\x52\x8f\xbf\xaa\xcc\x67\xf3\x16\x39\x9c\xa5\x7e\x3b\xe7\xb4\x7a\x8b\x6d\x7e\x3b\xcf\x39\x7c\x7e\x77\x89\xd7\x56\xea\x2e\xb7\x55\xbb\xdd\xa5\x9c\xc3\x15\x23\xee\x32\xbf\xbb\xa8\xc8\xe7\x28\x76\x59\x9d\x05\xee\x62\xbf\xd7\xea\xb3\xdb\xdd\xa5\xb6\x22\x87\xd3\xc6\x59\x9d\x7e\xbf\xa3\xd4\xe6\x75\x5b\x0b\x0b\xdd\x15\x2e\xa7\xdb\x5a\xc8\xf7\xdd\xe0\xcb\x3c\xfc\xbb\xc3\x95\xef\xae\xf4\x38\xad\x55\x5c\x81\xc3\x5b\xe0\xb4\x79\x6d\x1e\x9b\xd5\xef\xb5\x15\x79\x6d\x3e\x3b\x0f\xcb\x4f\x71\xba\x0b\x4a\x8a\x9c\xd6\x62\x3e\xe5\x79\xec\x6e\x97\xcd\x57\xee\x76\x96\x95\xda\x38\x77\x51\xd1\x75\x8e\x97\x7a\x9d\x2d\xf3\xac\xf3\x16\xb8\x0b\x6d\xf9\xd6\x18\xf1\x5b\x8b\xfd\xd6\x62\x5f\xbe\xdb\x5d\xc2\xff\x95\x5a\xbd\x25\x1e\xaf\xc3\xe5\x2f\xb0\x96\xda\xbc\xd6\x22\xb7\xcb\x9f\xef\x76\x16\x3a\xfc\x56\xa7\xa3\xc0\x6f\xab\xf4\x73\x76\x9b\xa3\xd8\xee\x8f\xb1\x15\x8e\x42\xbf\xdd\xea\x74\x14\xbb\x38\xa7\xad\xc8\x1f\xe7\x0a\x6c\x2e\xbf\xcd\x1b\xe7\xbd\xfc\xd0\x38\xbb\xb6\xcc\xe7\x77\x14\x55\xf1\x6b\x76\xb8\x0a\x6d\x2e\x7f\x6c\xca\x75\x36\x36\xae\xc8\x5a\x60\xe3\x35\xc2\x95\x3b\x0a\x6d\x6e\x8f\xa3\xc0\x5f\xc6\x6f\xd7\x55\xe0\x70\x96\x5a\x3d\x1c\xbf\x32\x9b\xd7\x5a\xc8\x0b\xf2\x3b\x5c\x7e\x5b\xa1\xc3\xef\xb3\x5b\xbd\xb6\x02\xbb\xad\xa0\x84\x57\xbd\xcf\x6f\xf3\x70\xf9\xd6\x82\x92\x0a\xab\xb7\xb0\xc8\xea\xf3\xff\xd9\xb8\x41\x79\x4d\x7a\xac\x65\x3e\x9b\xcf\xef\xf6\x14\xb9\xbd\x7f\x0e\xbc\xce\xc7\x24\x5c\xe7\x6d\x6b\x6d\x05\xfe\x02\xbb\xad\xdc\xeb\x8e\x6f\xef\x06\x1f\x5b\xac\xc7\x59\xe6\xe3\xf8\x93\x2d\x75\xb8\xae\x73\xf1\xf3\x8f\xb1\xee\x92\x18\x59\x57\x66\xf3\xf9\x1d\x6e\x57\xac\xe1\x70\x15\xb9\x63\x8c\xaf\xc0\x6b\xb3\xb9\x7c\x76\xb7\xff\xfa\x8c\xf8\xd1\xba\x4b\xae\x33\xf9\x56\xd7\x75\xce\xea\xf5\xba\x2b\xe2\xaa\x8d\x71\x71\x75\xc6\xd8\x32\x4f\x9c\xf2\x07\x1b\xd3\x02\x6f\x08\x5e\x9b\xcf\x51\x6d\xe3\x8a\xca\x9c\xce\xeb\xac\xaf\xd4\xea\x74\xda\x2a\x0b\x9c\xd6\x52\xeb\x9f\x2b\x29\x76\x14\xf9\x9d\x36\x6b\x51\x91\xc3\x6b\xb3\x55\xd9\x38\xb7\xc7\xe6\xe2\x69\x81\xd3\xed\xb3\x55\x58\xbd\x2e\x87\xab\x38\x36\xd0\xe3\xb4\xba\x6c\x05\x56\xa7\xcd\x55\x68\xf5\x7a\xad\xae\x42\x77\x69\x81\xbb\xb4\xd4\xe6\xf2\x97\x5a\x8b\x5d\xb6\x3f\x35\x52\xe6\xb9\xc1\xf1\xcb\xf1\xda\xfc\x15\x36\x9b\xdf\x67\x77\x7b\x3c\xbc\xa4\x02\xab\xd7\x5f\xe4\x76\x16\xda\xbc\x71\x84\xeb\x3c\x8f\x7a\x7d\x95\xe5\x36\xaf\xdf\x51\x60\xbd\xb1\x68\xbb\xdb\xeb\xa8\x76\xbb\xfc\x56\x67\xbe\xd5\xcb\x15\xd8\xad\x5e\xbf\xbf\xc2\xe1\xf7\xdb\xbc\xb1\x55\xf1\x76\xc2\x9b\x6a\xac\x11\x37\x53\xce\x6b\xf3\x7b\xdd\x25\xb6\xaa\x02\x77\xb1\xef\xfa\x12\x7d\x7e\x7b\x59\x69\xbe\x8f\x2b\xf3\xc4\x5c\x2d\xde\xe0\xd7\xc7\x37\x63\x0e\x6d\xb7\x3a\x8b\x62\x2e\x1e\x77\xed\xd8\xc1\x95\xf9\x9d\x0e\x57\x89\xad\xd0\x11\x57\x95\xa7\xcc\x67\xf7\x38\x5c\xb6\x4a\xbf\xcd\xeb\xb2\x3a\x39\xfe\xc3\xf8\x61\xfa\xbd\x6e\x8f\xbd\xaa\xd8\xe1\xb7\x97\xe5\xc7\x86\xc6\x1d\x36\xe6\x8f\xb6\x52\xb7\x2b\xe6\x88\x31\xd3\x8c\x4b\xbf\xe1\x5c\xf1\x56\xec\xd3\xd8\xb4\xeb\x3b\xbb\xb1\xa9\xb8\xc0\x32\x17\xef\xd3\x05\x5e\xde\xc6\x79\xfd\x15\x7a\x7d\x3e\x7b\x61\x61\x7e\x99\xd3\x69\x77\x7b\x5d\xf9\x36\xa7\xb3\x80\xd7\x59\x91\xa3\xc0\xea\xb7\xd9\xad\xae\xc2\xb8\x6d\xc4\x38\xde\x5e\x62\x4c\x99\x27\x46\xf8\x3d\xc7\xed\x89\xfb\x9f\x41\xfd\xad\x23\x36\xf7\x6f\x3d\x65\x9e\xbf\x35\x79\x11\xc5\x4e\x77\xbe\xad\xc2\x6b\x73\x15\xd8\xfd\x56\x5f\x89\xaf\xc8\xe1\xf4\xdb\xbc\xf9\x5e\x87\xad\xa8\xc0\xea\xb3\xf1\x46\x17\xb7\x6c\x97\xdb\x6f\x5b\x57\x66\x75\x3a\x5c\x45\x0e\x97\xc3\x5f\xe5\xb4\xf9\x7c\xb1\x8e\x62\xaf\xbb\xcc\xc3\x6b\xb0\xc0\xe9\x2e\x2b\xcc\xb7\x59\x4b\x6c\xde\x82\x32\x7f\x81\xdb\x53\xe5\xb1\x7a\x62\xe6\xe1\xf0\xf8\xac\xe5\x36\x5e\x2f\x5c\xbe\xd3\xea\x2a\xf1\xda\xdc\xde\x42\x9b\xb7\xcc\xe9\x76\xfa\xfc\x5e\x47\x89\xcd\x6f\xf7\xba\xcb\x8a\xed\x65\xae\x42\x9b\xd7\xe9\x70\xd9\xfc\xd6\x7c\xa7\xad\xd4\x5a\xec\x28\xf0\x7b\xcb\x0a\x4a\x3c\x7c\x60\xf0\xda\x7c\xfe\x3f\x99\xb8\xc5\xbb\xdd\xc5\x4e\x1b\xf7\xa7\xd3\xfe\xa5\x5d\xea\x76\xd9\xaa\x0a\xac\x5e\x9b\x3f\xae\xa8\x18\x57\xe6\x89\xd3\x98\xa6\x62\x5c\x5c\x45\x7c\x04\x75\xf9\x7c\x6e\xaf\x9f\xff\x8b\x3b\x1f\xcf\x94\x79\x6e\xa4\x8c\xd8\xf9\x5f\xb7\xa0\x32\x57\xa1\xdb\x69\x2b\xb6\x3a\x0b\xad\x3e\x7b\xbe\xdb\xea\x2d\xbc\x6e\x9a\xfc\xa0\x1b\x56\xca\xf3\xf9\x6e\xa7\xdf\xe7\xf0\xdb\x4a\xad\x9e\xb2\xd2\x7c\xaf\xcd\xe9\xb4\x7a\xac\x3e\xbf\xcd\xc9\x83\x72\xf9\x65\xce\x7c\x5b\x65\x81\xdd\xea\x2a\xb6\xc5\x34\xc7\xdd\xc8\x11\xf1\x56\xdc\xf0\xf8\xc4\xc4\x95\xf2\x11\xcc\x6f\x77\xfb\x0a\xdc\x1e\x9b\xaf\xcc\xe1\xe7\x4f\x86\xb7\x96\x38\x62\x51\x91\xcd\x56\xe4\x76\x17\xc6\xf2\x4f\x2c\x82\xf3\xe0\x65\x0e\x67\xa1\xc3\x55\x6c\x77\xfb\x3c\x7c\x98\xb7\x96\xe6\x97\x39\xad\xae\x02\x5b\xa9\xad\xb0\xc4\xe1\x2f\xe2\xd7\x60\xf3\x72\x6b\x6d\xfe\x7c\x9b\xcd\x6b\x8f\xbb\x60\x66\x91\xad\xd0\x5d\x96\xcf\x1b\x88\x8b\xd7\x24\xaf\xa8\xbf\x75\xc4\xf4\xf5\xb7\x9e\x32\xcf\xdf\x9a\xfc\x1e\xfe\x37\xf7\x2f\x93\x6e\x8c\xfe\xdf\xb0\x42\x9b\xaf\xc4\xef\xf6\x38\xad\x1e\xbf\xdb\x13\x3b\x70\x7f\xa9\x3b\x9f\xdf\x43\xdc\xc9\xe2\x96\x1a\xb3\x97\x75\x65\x6e\x7f\x5c\x62\x9c\x8b\x49\xf4\x79\x1c\x2e\x97\xcd\xfb\x67\x06\x75\xde\x70\x5b\xab\xf3\x6f\x81\xe9\x2f\x6d\x3e\x38\xf1\x4d\x5b\xa5\x87\x77\xa1\x98\xf6\xf8\x53\x89\x0f\xf2\x95\x3a\x9c\xb6\x22\xaf\xbb\xc2\x55\x6a\xb3\x17\x5b\x4b\x6d\x1e\x6b\x61\x89\xad\x2a\x76\xc4\x7c\x22\x8e\x09\xe2\x69\xcc\xff\x6d\x5e\x5b\xa1\xdf\xe6\x2d\x75\xc4\xaa\x80\xc2\xf8\x0a\x38\xab\xd3\xf9\x67\x10\x8a\xc7\x04\xa7\xbb\x20\x1e\xa3\x63\x3e\x57\xe0\x75\x7b\xf8\xd1\x7c\x3a\x2a\x29\x73\xf1\x36\xc5\xe9\xb3\x73\xff\x12\xcb\x7d\x65\x1e\x9b\xd7\x57\xe0\x75\x78\xfc\xbe\xb2\xfc\x38\xc3\xe9\x73\x0c\x9e\xb2\xea\x6a\x5e\x37\x0e\x5b\x81\xad\xd4\xc1\xcb\xe1\xb5\xf4\x3f\x8e\x2f\x0b\x7c\x76\x87\xcd\x59\x78\x23\xb4\xc7\xf1\xf9\x74\xc0\xd9\x2a\xfd\x0e\x57\x71\x99\xc3\x67\xb7\x79\xbd\xee\x82\x12\x9b\xbf\xd4\x5a\x59\x50\xe8\xba\x11\xe0\x7d\x37\x92\xfd\xdf\x3a\xe2\xde\xf1\xd7\x9e\xff\xa5\x84\x58\x93\x3f\x46\xbb\xbf\xd4\x69\x2a\xf0\xf9\x0c\x56\x57\x81\xdd\xed\x8d\xc7\xb8\xb8\x05\x3a\x9d\x3e\x5b\x95\xcd\xe6\xe4\xfd\xdf\xe1\xfb\x4b\x02\xf8\xb3\xeb\x46\x8a\xe0\x0c\x99\x86\x58\x3d\x14\x8b\x9d\x8e\xd8\x02\xff\xcc\xc0\xb1\x73\x8a\x85\xdc\x58\x9f\xd3\x56\x6e\x73\xf2\xee\x11\xa3\x31\xef\x8e\x7d\xc8\x0f\x8d\x45\xd6\xd8\x1c\x43\x96\x3e\x9e\x40\x63\xe9\xc4\x5d\xea\xb1\xfa\x7c\x37\x0e\xfb\xcf\x43\xf7\xbb\x3d\x9c\x21\x2b\xdb\x56\xe6\x2d\xce\xf7\x94\xf9\x0a\x1d\x2e\xef\x5a\x4f\x95\xb7\x2c\xbf\xc4\x5b\x91\xef\x2f\xe0\x1d\xea\x4f\xa7\x8a\x45\x84\x7c\xfe\x84\x3d\x76\x6b\xbe\xcd\xcf\x19\xf4\xb9\x7f\xf6\xf9\xfd\x5e\x47\x7e\x99\xdf\xe6\xfb\x7f\xf6\xc4\x2c\xeb\x7a\x6f\x2c\xea\xfd\xad\xc1\x7f\xca\x19\x0c\x46\xce\x60\x30\x55\xb9\xcb\xfc\x65\xf9\xf1\x15\x5f\xe7\x2b\x1d\xae\xe2\xca\x1b\x79\xfb\xc6\xe7\xbc\xa2\x0a\xbd\x6e\x4f\xbe\xbb\xd2\xe7\xb7\x16\x94\xdc\x88\x22\x0e\x97\xcf\x6f\x2d\xf6\x5a\x4b\x8b\x9c\x8e\x82\x12\xaf\xb5\xd0\x55\x94\x95\x9d\x95\xef\xf0\xe7\x97\xf1\x0a\x8d\xeb\xb6\xac\x34\xdf\xe9\x8d\xbf\xc7\x3a\x9c\x6e\x57\xf1\x5f\xd2\xc1\x5f\x9a\x7c\x00\xfa\xb3\xc1\xdb\xc6\x5f\x9a\x71\x97\xf6\x78\x9c\xb6\x0a\x87\xab\xd0\x5d\xe1\xb3\xba\x0a\xbd\x6e\x47\xa1\xd3\xe1\x2a\xab\x2c\xf4\x3a\xf2\xf3\x9d\x36\x5f\x49\x95\xc7\x56\xe4\x2e\xf3\xfa\xd6\x95\xf1\xc1\x96\x0f\x80\xee\x22\x5b\xa9\xd5\x19\xfb\x2b\x76\xf8\xfd\x0e\x8f\xaf\xcc\xc5\x19\xcc\x66\xbe\x3c\x77\x94\xdb\xf2\xcb\x8a\xcb\x4b\x2a\x6c\x8e\x7c\xb7\x97\xaf\x22\x5c\x9c\x21\x5b\x1f\xdb\x22\x77\x63\x8f\x9c\x21\xdb\x18\x5f\xc2\x8d\x4c\xe6\x8c\xc7\x73\xce\x90\x6d\x2e\x74\xfb\xff\xda\x6d\xc8\xce\x29\x77\x94\xda\xdc\x5c\x7c\x01\x9c\x21\x27\x33\x9e\x2a\xe2\x4d\x37\x67\xc8\xd1\x73\x86\x1c\x03\x67\xc8\x31\x72\x86\x1c\x13\x67\xc8\x31\x73\x86\x9c\x6c\xce\x90\x93\xc3\x19\x72\x72\xcb\x5c\x8e\xb9\x59\x33\x33\x8b\xb2\xac\x59\x9c\x21\x57\xcf\x19\x72\x0d\x45\x59\x56\x23\x67\xc8\x35\x71\x86\x5c\x33\x67\xc8\xcd\xe6\x0c\xb9\x39\x9c\x21\x37\x97\x33\x66\xf2\xe3\xf2\x39\x63\xa6\x9e\x33\x66\x1a\x38\x63\xa6\x31\x36\x7d\x56\x16\x67\xcc\x34\x73\xc6\xcc\x6c\xce\x98\x99\xc3\x19\x33\x73\x39\x63\x56\x26\x67\xcc\xca\xe2\x8c\x59\x7a\xce\x98\x65\xe0\x8c\x59\x46\xce\x98\x65\xe2\x8c\x59\x66\xce\x98\x95\xcd\x19\xb3\x72\x38\x63\x56\x1c\x3d\x2f\x33\x4e\xb2\x38\xa3\x5e\xcf\x19\xf5\x06\xce\xa8\x37\x72\x46\xbd\x89\x33\xea\xcd\x9c\x51\x9f\xcd\x19\xf5\x39\x9c\x51\x9f\xcb\x19\x0d\x99\x9c\xd1\x90\xc5\x19\x0d\x7a\xce\x68\x30\x70\x46\x43\x7c\x01\xb3\xe3\x12\x66\x67\xc5\x09\xff\x61\x0e\x67\x34\xc4\xc5\xcf\x36\xc5\x89\x39\x4e\xb2\x39\xa3\xd1\xc0\x19\x8d\x46\xce\x68\x34\x71\x46\xa3\x99\x33\x1a\xf9\xbe\x1c\xce\x68\x8c\x4f\x98\x93\xc9\x19\x4d\x59\x9c\xd1\xa4\xe7\x8c\x26\x03\x67\x34\x19\x39\xa3\xc9\xc4\x19\x4d\x66\xce\x68\xca\xe6\x8c\xa6\x1c\xce\x68\xca\xe5\x8c\xe6\x4c\xce\x68\xce\xe2\x8c\x66\x3d\x67\x34\x1b\x38\xa3\x39\xbe\x98\xb9\x7c\xb7\x99\x33\x9a\xb3\x8b\xb2\x8a\xf8\xee\x5c\xce\x98\x9d\xc9\x19\xb3\xb3\x38\x63\xb6\x9e\x33\x66\x1b\x38\x63\xb6\x91\x33\x66\x9b\x38\x63\xb6\xb9\x28\xab\xa8\x80\x33\x66\xe7\x70\xc6\xec\x5c\xce\x98\x93\xc9\x19\x73\xb2\x38\x63\x8e\x9e\x33\xe6\x18\x38\x63\x8e\x91\x33\xe6\x98\x38\x63\x8e\x99\x33\xe6\x64\x73\xc6\x9c\x1c\xce\x98\x93\xcb\x19\x73\x33\x39\x63\x6e\x16\x67\xcc\xd5\x73\xc6\x5c\x03\x67\xcc\x35\x16\xe9\x79\x8d\xe7\x9a\x8b\xf4\xbc\xc6\x73\x73\x38\x63\x6e\x2e\x67\xca\xcc\xe4\x4c\x99\x59\x9c\x29\x53\xcf\x99\x32\x0d\x9c\x29\xd3\xc8\x99\x32\x4d\x9c\x29\xd3\xcc\x99\x32\xb3\x39\x53\x66\x0e\x67\xca\xcc\x2d\xb7\xf1\x51\xc8\x94\x95\xc5\x99\xb2\xf4\x9c\x29\xcb\xc0\x99\xb2\x8c\x9c\x29\xcb\xc4\x99\xb2\xcc\x9c\x29\x2b\x9b\x33\x65\xe5\x70\xa6\xac\x5c\xce\xa4\xcf\xe4\x4c\xfa\x2c\xce\xa4\xd7\x73\x26\xbd\x81\x33\xe9\x8d\x9c\x49\x6f\xe2\x4c\x7a\x33\x67\xd2\x67\x73\x26\x7d\x0e\x67\xd2\xe7\x72\x26\x43\x26\x67\x32\x64\x71\x26\x83\x9e\x33\x19\x0c\x9c\xc9\x60\xe4\x4c\x06\x13\x67\x32\x98\x39\x93\x21\x9b\x33\x19\x72\x38\x93\x21\x97\x33\x19\x33\x39\x93\x31\x8b\x33\x19\xf5\x9c\xc9\x68\xe0\x4c\x46\x23\x67\x32\x9a\x38\x93\xd1\xcc\x99\x8c\xd9\x9c\xc9\x98\xc3\x99\x8c\xb9\x9c\xc9\x94\xc9\x99\x4c\x59\x9c\xc9\xa4\xe7\x4c\x26\x03\x67\x32\x19\x39\x93\xc9\xc4\x99\x4c\x66\xce\x64\xca\xe6\x4c\xa6\x1c\xce\x64\xca\xe5\x4c\xe6\x4c\xce\x64\xce\xe2\x4c\x66\x3d\x67\x32\x1b\x38\x93\xd9\xc8\x99\xcc\x26\xce\x64\x36\x73\x26\x73\x36\x67\x32\xe7\x70\x26\x73\x6e\x91\xde\x9c\x59\xa4\xe7\xc7\x65\xeb\x8b\xf4\xfc\xb8\x6c\x23\x67\xca\x36\x71\xa6\x6c\x33\x67\xca\xce\xe6\x4c\xd9\x39\x9c\x29\x3b\x97\x33\xe5\x64\x72\xa6\x9c\x2c\xce\x94\xa3\xe7\x4c\x39\x06\xce\x94\x63\xe4\x4c\x39\x26\xce\x94\x63\xe6\x4c\x39\xd9\x9c\x29\x27\x87\x33\xe5\xe4\x72\xa6\xdc\x4c\xce\x94\x9b\xc5\x99\x72\xf5\x9c\x29\xd7\xc0\x99\x72\x8d\x9c\x29\xd7\xc4\x99\x72\xcd\x9c\x29\x37\x9b\x33\xe5\xe6\x14\xe9\xb3\x6d\xbc\x7d\xe8\x73\x32\xe3\x24\x8b\x33\x67\xea\x39\x73\xa6\x81\x33\xc7\xfd\x48\x9f\x63\x8a\x13\x33\x67\xce\xcc\xe6\xcc\x99\x39\x9c\x39\x33\x97\x33\x67\x65\x72\xe6\xac\x2c\xce\x9c\xa5\xe7\xcc\x59\x06\xce\x9c\x65\xe4\xcc\x59\x26\xce\x9c\x65\xe6\xcc\x59\xd9\x9c\x39\x2b\x87\x33\x67\xe5\x72\x66\x7d\x26\x67\xd6\x67\x71\x66\xbd\x9e\x33\xeb\x0d\x9c\x59\x6f\xe4\xcc\x7a\x13\x67\xd6\x9b\x39\xb3\x3e\x9b\x33\xeb\x73\x38\xb3\x3e\x66\xe2\xfa\x99\xf1\x35\xcc\xcc\x8a\x13\x7d\x9c\x18\xe2\x24\xbe\x98\x99\xf1\xc5\xcc\x34\xc7\x49\x76\x9c\xe4\xc4\xc9\x75\x29\x33\xe3\x64\x56\x9c\xe4\xc5\xc9\xec\x38\x99\x13\x23\xb3\xe2\x40\xb3\xe2\x40\xb3\xe2\x40\xb3\xe2\x40\xb3\xe2\x40\xb3\xe2\x40\xb3\xe2\x40\xb3\xe2\x40\xb3\xe2\x40\xb3\xe2\x40\xb3\xe2\x40\xb3\xe2\x40\xb3\xe2\x40\xb3\xe2\x40\xb3\xe2\x40\xf1\x20\xa2\xcf\x8b\x03\xe5\xc5\x81\xf2\xe2\x40\x79\x71\xa0\xbc\x38\x50\x5e\x1c\x28\x2f\x0e\x94\x17\x07\xca\x8b\x03\xe5\xc5\x81\xf2\xe2\x40\x79\x71\xa0\xbc\x38\x50\x5e\x1c\x28\x1e\x6b\xf4\xf1\x58\xa3\x9f\x1d\x07\x9a\x1d\x07\x9a\x1d\x07\x8a\x47\x1c\x7d\x3c\xe2\xe8\x67\xc7\x81\x66\xc7\x81\x66\xc7\x81\x66\xc7\x81\x66\xc7\x81\x66\xc7\x81\x66\xc7\x81\x66\xc7\x81\xe6\xc4\x81\xe6\xc4\x81\xe6\xc4\x81\xe6\xc4\x81\xe6\xc4\x81\xe6\xc4\x81\xe6\xc4\x81\xe6\x64\x73\xe6\xdc\x38\xca\x9c\x38\xca\x9c\x38\xca\x9c\x38\xca\x9c\x38\xca\x9c\x38\xca\x9c\x39\x79\x6e\x4f\x55\x2c\xc7\x8d\x9c\x6d\x2d\xb7\x8d\x9c\x67\x75\x15\x56\x8d\xd4\x67\x66\x99\x27\x8f\x9c\xe9\x74\x8e\x8c\xd7\x9f\x23\xbd\x36\x9f\xcd\x5b\x6e\x2b\x9c\xfc\x97\x87\x05\xf0\x4a\x02\x80\x40\x0a\x56\x02\x0e\xb4\x82\x76\xd0\x05\x0e\x80\x47\xc0\x49\xf0\x31\x1c\x0d\x27\xc0\x29\xd0\x00\xb3\xe1\x54\x68\x81\xcb\x20\x07\x0b\xa1\x1d\xba\xe0\x76\xd8\x06\x3b\xe1\x29\x78\x0e\xbe\x0c\x5f\x87\x6f\xc3\x77\xe1\x47\xf0\x73\xf8\x0d\xfc\x0f\xfc\x0d\x46\x12\xb4\x09\x37\x27\x8c\x4f\x58\x9c\xe0\x4d\xa8\x4e\xa8\x4f\x38\x98\x70\x38\xe1\x6c\xc2\xab\x09\x6f\x26\x7c\x96\xf0\x55\xc2\xb7\x09\xbf\x24\x0c\x0b\x12\x04\x49\x82\xc9\x02\xbd\xc0\x2c\xb8\x5d\x30\x43\x30\x5b\x70\x97\x60\xa1\xa0\x5f\x70\x52\xf0\xac\xe0\x9f\x42\x2c\x4c\x17\x6a\x85\x63\x85\xb7\x09\x27\x0b\x8d\xc2\x1c\xe1\x0c\xe1\x1c\xe1\xa2\xd8\x77\xee\xab\x85\x35\xc2\xcd\xc2\x80\x70\xa7\xf0\x15\xe1\x4f\x42\x2a\x02\x22\xa1\x48\x22\x1a\x21\xd2\x88\xa6\x88\x0c\xa2\x9d\xa2\x2e\xd1\x7e\xd1\x71\xd1\x13\xa2\x67\x44\x83\xa2\x57\x44\xaf\x8b\xde\x16\xfd\x20\x22\x22\xca\x2c\x66\x1e\x64\x56\x33\x05\x4c\x31\xe3\x64\x6a\x99\x66\x66\x0b\x73\x9c\x39\xc7\x3c\xcb\x5c\x11\xe7\x88\xa7\x89\xe7\x8a\xe7\x8b\xbb\xc4\x7b\xc5\x07\xc5\x47\xc4\x8f\x8b\x9f\x14\x3f\x27\x7e\x41\xfc\x8a\xf8\x2d\xf1\xd7\xe2\x9f\xc5\x61\x89\x46\x92\x27\x79\x40\x62\x95\xac\x95\xb8\x25\xe5\x92\xf5\x92\x5a\x49\xb7\x64\x40\x72\x4c\x72\x46\xf2\xbc\xe4\x35\xc9\xa5\xc4\xc4\xc4\x19\x89\xf3\x13\x57\x24\x6e\x4d\xdc\x91\xd8\x97\x78\x38\xf1\x85\xc4\x97\x12\xdf\x4b\xfc\x2e\xf1\xbf\x89\x43\x89\x7f\x20\x09\x92\xc5\xbe\xdf\x9e\x8c\x6e\x47\x33\x91\x05\x95\x22\x2f\xaa\x41\x0d\xa8\x19\xed\x45\xc7\xd0\x13\xe8\x19\xf4\x25\xfa\x16\xfd\x88\xc5\x38\x15\x4f\xc5\xb3\xf0\x5c\x7c\x0f\xb6\xe0\x65\x98\xc3\x05\xd8\x81\x5d\xd8\x87\xab\x71\x3f\x7e\x18\x1f\xc3\x8f\xe3\xa7\xf0\x20\x7e\x1b\x5f\xc6\x5f\xe3\x2b\xb1\x6f\xad\x47\x4a\x27\x4b\x0d\xd2\x1c\xe9\x0c\xe9\x5c\xe9\x02\xe9\x62\xa9\x47\xba\x41\xda\x22\xdd\x2e\xed\x92\xee\x95\x3e\x22\x3d\x29\x7d\x4e\x7a\x51\xfa\x96\xf4\x43\xe9\xe7\xd2\xef\xa4\x3f\xc9\xc4\xb2\x71\xb2\x39\xb2\x42\x59\xa9\xac\x5a\xb6\x59\x16\x90\xb5\xcb\x1e\x96\x9d\x93\xbd\x28\x7b\x43\xf6\x6f\xd9\x47\xb2\xcf\x65\xff\x27\xfb\x49\xf6\x1f\xb9\x4c\xce\xca\xc7\xca\xb3\xe4\xd3\xe5\xb3\xe4\xf3\xe4\x8b\xe4\x0f\xc8\x57\xca\x6d\xf2\x5a\x79\xb7\xfc\xb4\xfc\x69\xf9\x0b\xf2\x97\xe4\xaf\xc9\xdf\x91\xbf\x2f\xff\x8f\x02\x29\x6e\x56\xdc\xaa\x98\xa4\xc8\x56\x4c\x57\xe4\x29\xe6\x2b\xee\x55\xac\x52\x94\x28\xbc\x8a\x3a\xc5\x66\x45\x87\x62\xaf\xe2\x61\xc5\x71\xc5\x69\xc5\x53\x8a\x7f\x28\x5e\x51\xbc\xa9\xf8\xb7\xe2\x43\xc5\xaf\x8a\xb0\x62\x38\x29\x35\xe9\xd6\xa4\xdb\x93\x16\x27\x3d\x90\x94\x9f\xe4\x4c\x5a\x97\x54\x9e\xb4\x21\xa9\x31\x69\x6b\xd2\xce\xa4\xce\xa4\xde\xa4\xc7\x93\xce\x26\x5d\x4c\xfa\x2c\xe9\xb7\x64\x90\x2c\x4f\x1e\x9d\x3c\x31\xd9\x94\x7c\x7b\xf2\xac\xe4\xf9\xc9\xf7\x26\x5b\x92\x8b\x93\xab\x93\xb7\x27\xf7\x24\xf7\x27\x3f\x92\xfc\x58\xf2\x13\xc9\xcf\x26\xbf\x90\x7c\x21\xf9\x8d\xe4\x4b\xc9\x97\x93\x3f\x49\xfe\x32\xf9\xb7\x14\x71\x4a\x7a\xca\x98\x14\x73\xca\x5d\x29\x2b\x52\x56\xa5\xd8\x53\x7c\x29\xeb\x53\xea\x53\x9a\x53\xb6\xa6\xf4\xa4\xf4\xa7\x9c\x4a\xf9\x67\xca\xa5\x94\x0f\x53\x7e\x4c\xf9\x4f\xca\x6f\x29\x91\x54\x94\x3a\x22\x75\x64\xea\xb8\xd4\x89\xa9\xe6\xd4\x19\xa9\xf3\x53\x2d\xa9\xcb\x52\xd7\xa4\xda\x53\x5d\xa9\xfe\xd4\x0d\xa9\x8d\xa9\x5b\x52\x5b\x53\x3b\x53\x7b\x52\xfb\x52\x1f\x4e\x3d\x92\x7a\x32\xf5\x4c\xea\x53\xa9\xff\x48\x7d\x3d\xf5\x83\xd4\x6f\x53\x49\xea\x35\xa5\x4c\xa9\x51\xde\xaa\xcc\x51\xce\x50\xde\xab\xbc\x5f\xb9\x4c\xf9\x90\x32\x5f\x69\x57\x7a\x94\x1b\x95\xcd\xca\x0e\x65\xaf\x72\x40\xf9\x98\xf2\x71\xe5\x33\xca\x17\x94\xaf\x28\x5f\x53\xbe\xad\x7c\x5f\xf9\x89\xf2\x4b\xe5\x77\xca\x9f\x94\x57\x55\x50\x25\x57\xa9\x55\xa3\x55\x53\x54\x46\xd5\x54\xd5\x9d\xaa\xb9\xaa\x7b\x54\xf7\xab\x1e\x54\x3d\xa4\xb2\xab\x4a\x55\x7e\x55\x9d\x6a\x9b\x6a\xb7\x6a\x40\x75\x5c\xf5\xa4\xea\x9f\xaa\x57\x54\x6f\xaa\xfe\xad\xfa\x54\xf5\x8d\xea\x27\xd5\x55\x55\x58\x75\x2d\x4d\x90\x26\x49\x93\xa5\xa5\xa4\xdd\x94\xa6\x49\x1b\x9f\x36\x31\x4d\x9f\x36\x3d\xed\xae\xb4\xfb\xd3\x56\xa7\xd9\xd2\x9c\x69\x15\x69\xb5\x69\x4d\x69\x5b\xd2\x5a\xd3\x3a\xd2\x76\xab\x6e\x43\x64\x26\x8a\x58\xc6\xb1\x72\x8d\xe8\x59\x8d\xb0\x49\x45\x5f\x23\xaf\x89\x4e\x16\xcd\x3c\xb2\x54\x7d\x4d\x79\x11\x69\x86\x06\x2d\x2c\x79\x9a\x1d\x74\xbe\x5b\x74\x52\x1b\x5d\x4c\x5a\x54\x7b\x9b\xf7\x36\xb4\x37\x91\xd7\xe9\xeb\x23\xda\x9b\x82\xd5\x6d\xd5\x92\xa8\x94\x09\x2b\xc9\x27\x48\x43\xc1\x62\x34\x14\x8c\x1a\x3f\x66\xb1\x6a\x14\xc2\xaa\x48\xd0\xcf\x5e\x0b\x8a\xaf\x05\x35\xc2\x41\xd5\x76\x34\x14\x4c\xdb\x8e\xc2\xca\x8b\x5f\xb3\x54\xf9\x03\xb3\x0e\x45\x95\x3f\x88\xd7\x21\xaa\x14\xe7\xb3\x7e\xf6\x3d\x56\x3c\x0e\xe1\xaa\x9a\x9a\x2a\xcc\x10\x03\x51\x11\x15\x31\xe8\xf0\x58\x56\x87\xa9\x81\xaa\xa8\x8a\x1a\x74\xf8\x4b\xa4\x11\xad\xa9\x66\x35\x91\x7e\x6a\x11\x6f\xac\x6d\xac\xdd\xa4\xdb\x54\xdb\xba\x31\x58\x4f\x42\x34\x34\x82\x30\x6c\x47\x47\x6b\x5b\xbb\x8e\x5c\x22\x97\x44\x58\x45\x8c\x44\xc7\x6a\xc2\x83\xab\xd0\x35\x4b\x31\xab\x11\xcf\x58\x81\x88\x51\x9c\x1a\x21\x12\xa4\x0b\x2b\xc5\xe4\x1c\x4a\x8d\x46\x83\xc2\xd4\xcb\x54\xc9\xa4\x46\xc9\x12\xa4\x09\x0f\x4e\x64\x23\x96\x95\xfc\x58\x52\x8f\x88\x52\x2c\x0f\x4f\xa3\x3f\x92\x1f\xa3\xd3\x30\x63\x44\x78\x22\xd2\xe2\xd5\xec\x71\x2c\xd6\x23\x1c\x6d\x8c\x8e\x8d\x8e\x8d\x36\x46\x1b\xc3\x63\xa3\x63\xc3\x8d\xe1\xc6\xf0\xd8\xf0\xd8\x70\x23\x36\xb0\x5a\x7c\x11\x51\xcb\x34\x84\x8f\xbb\x0e\xd9\xf1\x0c\x56\x87\xa7\xb2\xd4\x22\xc6\x8b\x78\xdd\x58\xee\x66\xc3\x41\x6a\x59\x84\x48\xf0\xa2\x2a\x0f\x2d\x60\xe6\xb2\xba\x05\x25\xec\x45\x06\x33\x66\x84\x99\x3b\x59\xac\x22\xf5\x2c\x1d\xa4\x2d\xb4\x85\x0e\xce\x47\xba\xa1\x60\xf4\xcc\x25\x36\x40\xb6\x22\x22\x63\x6f\x47\x0b\x26\xb2\xf8\x76\x44\x43\x4c\x55\x4d\x77\xaf\x8e\x58\xd6\x22\x6c\x42\x54\x39\x85\xc5\x0f\x22\x2d\x5e\x30\x86\xc5\xe3\x59\x6a\x19\xc3\xe2\xe3\x87\x0e\x1d\xc7\x4b\xd1\x3d\x48\x87\xcb\x11\x79\x1a\x11\x09\xd2\x62\xbe\x65\x46\x45\x08\xab\x78\x45\x6b\xa9\xf2\xba\x18\xa5\xb8\xb7\xbb\xbb\x57\x4b\x94\x4c\x6f\x77\x4d\x95\x8e\x28\x85\x4e\x16\x57\x6f\xd8\x50\x8d\x55\x63\x11\x1e\xae\x25\x59\x68\x48\x79\x02\x05\x88\xf2\xc6\x2b\x40\x94\x0b\x88\x25\x75\xf8\xad\x21\x25\xb1\xa8\x3e\x5c\x1e\x9a\xfe\xa8\x16\xab\xf6\x6e\xd8\x53\xad\x5d\xc0\xf0\x33\x75\x0b\xc4\xd5\x7b\x36\xec\xd5\x5e\x64\xf6\xee\xd9\xb3\x57\x47\x83\x24\xb4\x08\xe1\x23\x68\xd4\xe7\xa6\x5e\x84\xc9\x28\x22\xde\x87\xf0\xbf\x51\xb4\x28\x5a\x44\x6e\x41\x61\x96\x7f\x45\x59\x51\x73\x5b\x70\x73\x87\x3a\xd8\x41\xe6\xa1\xe7\x9e\xeb\x44\xf8\x3e\x64\x60\x75\x78\x03\x4b\x2c\xc2\xeb\x6f\xb8\x87\xbd\x66\xa9\x43\x11\x4b\x08\x45\x2c\xcc\xde\x3d\x1b\xaa\x7d\x6c\x33\x5a\xf2\xaf\x77\x70\x27\x4b\xce\xb1\x44\x45\x55\xc4\xa0\x1d\x0a\x8d\x63\xb1\x6a\x3c\xc2\xe2\xf1\x08\x4f\x43\x1a\xd1\x8c\x99\x08\x5f\x97\xde\x11\x24\xf3\x10\x0e\x2b\x89\x12\x8b\xda\x9a\x1b\x76\x34\xaa\x1b\x1b\x36\x37\x37\xeb\xf0\x6a\x44\x46\x30\x21\x96\x68\x56\x92\xe4\xe9\x57\xb4\xa4\x9d\x74\x88\x48\x32\x8a\x5a\x34\x74\xe4\x14\xa4\x32\x20\x5c\xc0\x06\xb0\x78\x12\x8b\x07\xd7\x9c\x5d\xaa\xc5\xdd\x35\xbd\xd8\x7e\xc8\x85\x47\xb3\x34\x88\x87\x43\xaa\x59\x6c\x44\x99\x56\x8e\xb4\xa9\x8f\x90\xdf\xd9\x48\xa8\x18\x69\xe8\xbd\xcc\x33\xf5\x5b\x3f\x9c\xa7\xa6\x41\xa6\x1e\x91\x35\x0c\x99\x33\x7c\x51\x54\xe3\x7a\xe8\x0e\x27\x29\x46\x91\x20\xf3\x25\x7b\x6d\x22\xd3\xd9\xd7\xdd\x7f\x20\xe3\x40\xc3\xc0\xe6\xfd\xda\xc8\x21\x22\x17\x1d\xdb\x71\xf0\xd1\xa3\x19\x72\x62\x27\x3f\xb2\x27\x59\x6a\x27\x33\xe8\x0c\x62\xc7\x8f\xb0\x1a\x0a\xc4\x73\x5e\xba\xef\x6d\x2d\xa6\xca\xc5\x08\x5e\xd7\xb8\x66\x68\x46\x5c\xe7\xd4\x12\x57\xba\x86\x19\x8c\xab\x3d\x1c\x12\xc6\x46\x5c\x0b\xfd\x7d\x40\x24\xf4\x26\x1b\x16\xb2\xd9\x88\x1f\x39\x17\xe9\xe4\xaa\x03\x2c\x49\x65\x49\x25\x4b\x54\x48\x8b\x07\xcf\x9e\x1d\xc4\x62\xc3\xa5\xbc\x2f\xb5\x78\xf6\x92\x25\xb3\x31\x33\x9b\xc5\xe4\x23\xb6\x8c\xc5\x55\x48\x8b\xa7\x22\xa2\x14\x4e\x45\x98\xf2\x2a\x54\xfd\x66\xfa\x7c\xd4\x7c\x56\x8b\xf3\x59\x8d\x04\xbc\xc7\x5e\x66\xbf\x46\x58\x6c\x47\x78\x28\xa8\x11\xf6\xab\xbe\x45\xf4\x73\xfa\xb9\x88\xee\x31\xa1\xa8\x72\x0a\x4b\xf6\x30\xe4\x73\xfa\xf9\xab\x08\xeb\xae\x59\xc4\x24\x18\xb1\x8c\x64\x35\xa2\x3a\x3c\x01\x4d\x62\xb1\xbf\xba\xac\xb2\x41\x47\xcb\xa2\x2b\xa3\x5b\x67\x89\xbc\x9b\x9d\xb5\xa5\x19\x55\xbb\xab\xbb\x36\x6a\xc3\x80\xfe\x6e\x8a\xb6\x88\xb6\x36\x6d\x6d\x6e\xca\x58\xb7\xdb\x77\xa8\x7b\xf7\xce\xf6\xdd\xda\xf0\x03\xa4\x0e\xab\xec\x2e\x97\x9d\x37\x66\xbb\xeb\xd0\x71\xde\x98\x79\xdb\xe7\x8d\xf9\xf8\x21\x97\x5d\x47\x95\xe2\xb0\x52\x78\x34\xb6\x5a\x7f\x24\x44\xfc\x30\x40\xfc\x98\x19\x60\x75\x58\x6c\x41\x58\x23\x06\xb1\xa8\xa3\x5d\x10\xf7\x85\x8b\x77\x22\xac\x5a\xcb\x62\x43\x5e\x1e\x79\x12\x91\x7e\xa4\x1b\x0a\x89\xbf\xbc\x74\xe9\x4b\x2d\x56\x99\x58\x4c\xa6\xd2\x04\x72\x0b\x9d\xfe\xad\x76\xcf\x8a\x8e\x65\x0f\x66\xd0\x79\x53\x68\x2e\x9d\x4a\xe5\x5a\x2a\xa4\x53\x28\xb7\x90\x96\xa8\x5d\xa5\xdb\xb7\xbb\x74\xb9\x24\x99\xdc\xbe\x9c\xdc\xad\x3e\xff\x72\x5b\xe7\x8b\xba\x4f\x16\x7f\xb7\xe6\x97\x75\x8f\x34\x1d\xda\x74\x78\x73\xcf\x96\x3d\xbb\x77\xf4\x4a\x88\x84\xdd\xb1\x6f\x63\x57\xdd\xee\xc2\x73\xdc\xe3\x8e\x4f\x24\xd8\x3b\x50\x10\xf0\x7a\xb1\x3a\xea\x08\x44\x1d\x51\x47\x06\x26\x97\x59\x18\x20\xc1\x48\x90\x04\x05\x98\x54\xb1\xa4\x05\xe1\x19\x2c\xb9\x8b\xc5\xbf\x7d\xfe\xf9\x6f\x78\x12\x4b\x94\x4b\x10\x86\x64\x3c\x12\x60\x8d\x08\xe0\xf0\xe1\x00\x79\x02\xf1\x96\x4d\x2c\x64\x24\xab\x11\xd7\xc5\x3c\x35\x75\x0f\xce\x62\x35\x91\xba\x69\xac\x9f\xcd\x44\xb8\xbb\x57\x87\x55\xce\x6b\xae\x80\x53\xbd\x61\x43\x4b\x73\x8d\x8e\xab\x76\xe7\xaf\xce\xd0\x44\x88\x78\xf5\xa3\xf9\xe7\xaa\xb5\xcd\xdd\x7b\x5a\xf6\xa8\x8f\x1c\xea\xea\x3f\xa0\x0b\x2f\x0c\x4f\x0b\x2f\x8c\x4e\x13\x95\x1f\x38\x54\x77\x44\xbd\x67\xcf\xf6\xb6\x6e\xdd\xb9\xbd\x8f\x9e\x79\x32\x43\x23\x4a\x14\x3f\xe9\x3e\xc3\xed\xd5\xb6\xd5\x6c\x68\xdd\xa0\x96\x7b\x51\x38\xf4\x2e\xc2\x53\x58\xa2\xcc\x44\x98\x04\xc8\x2a\x1c\xa8\x41\x98\x06\xe8\x2a\x7c\x19\x45\x83\xbf\xa0\xa8\x32\x6e\xbe\xe1\x60\x15\x8b\xbb\x51\xf9\xab\x2c\x66\x6e\x61\xb1\xea\x63\x44\x19\xc2\x3c\xc8\xd2\xcf\xe8\x67\xe4\x29\x74\x9e\x8d\x5a\xa6\xb0\x61\x0b\xf9\x89\x25\x4f\x21\xf2\x19\xf9\xac\x13\xe1\xf0\xda\x40\xd8\x11\xb6\x67\x60\x1a\x5c\xcf\x62\xe2\x17\x0c\x05\xc9\x6d\x28\x3a\x8d\xfe\x48\x7f\x8c\x4e\x8b\x4e\x23\x3f\xd2\x1f\xc9\xe3\x88\xfc\x18\x9e\x36\x81\xd5\x69\x22\x9f\x09\xc9\xac\x3f\x23\xa9\x0e\x47\x42\xa4\x0f\x0d\x2b\x99\x76\x36\x9c\xc0\xea\xae\x29\xc5\x74\x26\xb9\x9f\x8e\x24\x4d\xcd\x5a\xea\xa0\xab\x45\x15\xe5\xdd\xf6\x43\xea\xc8\x19\xe6\x50\xf7\xf1\xbe\x72\x1d\x75\x90\xd5\x22\xd2\xd4\x46\xee\x27\x23\xc9\xcc\x8c\x88\x52\x4c\xe6\xd0\x55\xe4\x66\x1a\xd0\x62\x55\x2f\x8b\xc7\xa3\x05\xb7\xa0\x68\x68\x36\xc2\x73\x59\x2d\x56\x91\x52\xaa\x24\x69\xd4\x40\xc7\x8f\xa2\x22\xaa\xa5\x69\xdf\x53\x86\x8c\x7d\xf9\xe5\xfe\xc3\x8f\x6a\xb7\x33\x37\x57\x2e\x1c\x4f\xa5\x6a\xd7\xba\xb6\xf6\x0a\x5d\x5d\x6b\xdd\x8e\x86\x1d\x85\x54\x34\xa2\x6b\x53\xf7\xa6\x9e\x4d\x92\x86\x87\x4f\x36\x3d\xa9\x26\x0d\x24\x81\xb8\xc9\x6a\x1d\xa6\xab\x68\x00\xab\x7e\x45\x69\x7e\x84\x2b\x11\xc9\x62\x75\x7c\xbc\x7c\x86\xa5\xa3\x70\xb0\xbd\x3d\xa8\xc3\x6f\xbf\xf4\xd2\xdb\x58\x74\x8a\xc5\x73\xee\xbb\x6f\x8e\x0e\x9b\xd8\x70\x30\xaa\xac\x65\x71\x47\x0b\x71\xb0\x94\xcf\x7e\x6d\x4d\x8d\x3b\x1a\xd4\x7c\x2a\xc0\x55\xdd\x35\x24\x8d\xe5\xcf\x9c\x28\x61\x2c\x82\x63\x72\x0a\x51\x3f\xb3\x74\xcd\xd9\x41\xdd\x51\xf2\x2b\x22\x2f\xa2\x05\x0c\x39\x82\x86\x2d\xe4\x49\x56\x1b\x56\x32\xe4\x1a\xe2\xc7\x44\x95\xcc\x11\xa4\x8b\x2a\xf9\x5e\xe2\x27\xdf\xa0\x12\x71\x3e\xd2\x2e\x98\xc6\x5e\x64\xc8\x71\x52\x1d\x16\x22\x1d\x56\x2d\x43\x9a\xc8\x0c\xc6\x90\x97\x67\xd0\x69\xe8\x0c\xd2\xc6\x92\x9b\xd9\xc5\x28\x1a\x52\x91\x14\x16\xab\xf8\x14\x78\x1f\xd2\x62\x6a\x6f\x62\x71\x6d\x57\x4f\xd3\x5e\x35\xef\x87\x41\xac\x61\xea\x30\x99\xc2\x0e\xdd\x2e\xe6\x87\x68\xa9\xf2\x73\x44\x76\xa1\x43\xc7\x75\x43\xb7\xbf\x84\xb0\x8a\x06\x5b\x11\x09\x92\xa9\x2c\xae\x64\x79\x9f\x15\x60\x1a\x20\xcf\xb2\x24\x80\xcb\x58\xe2\x64\x89\x65\xc1\x33\x88\xb7\xe9\xa1\xba\x56\xa4\x61\xea\x32\x11\xfe\xe4\x93\x4f\x72\x9e\x63\xb1\x23\x87\x2b\x2c\xe4\xea\x36\x6e\xac\xdd\x51\xc9\x3b\x58\x75\x6b\x77\xed\x9e\x6d\xdb\x02\xdb\xd4\x87\x77\x1c\xda\xf9\x48\xfb\x2f\x0f\x7f\x77\xf6\x93\x97\x25\xf5\x2f\xbe\xdc\x7c\x5e\x1d\x4e\x27\x6f\x92\x2a\x72\x02\x87\x47\x93\x5c\x32\x82\xdc\x0b\x03\x24\x97\x8c\x25\x8d\x61\x21\x49\x26\x1f\x93\x5c\x41\xe4\xd6\x21\xac\xa2\x6e\x3a\x9e\x66\xd2\x75\xd4\x41\xef\x24\x33\x88\x9d\xd8\x09\x4f\x1d\x78\xc0\x7b\x3a\x30\x30\x90\xfe\x16\x8b\xf3\xd0\x35\xcb\xf5\x54\x1e\xb1\x78\x11\x5e\x8c\x86\x94\xaa\xf0\x54\x7a\x85\x5c\x89\x4e\xa5\xcb\xe9\xfd\xd3\x68\x3a\x1d\xa5\xa5\x69\x44\x55\xb5\xcf\xbd\xd3\x5f\x9f\xee\xab\x5f\xef\x5f\x97\x11\x37\x73\x06\x67\x9c\xe3\x8d\x88\x8a\x8b\x89\x98\x21\x4a\x96\x98\xc8\x07\x2c\x5e\xd9\xc3\x04\x10\x99\x8b\x98\x58\xa0\x45\x30\x40\x7c\x48\x23\x1a\xe4\x8d\xde\x98\x85\x48\x37\x83\x5f\x67\xb5\x78\x2f\x79\x8a\xd5\x92\x10\x09\x89\xda\xda\x5a\x83\x1d\x19\x58\xdc\xd2\xbe\xb9\xad\xb9\x6d\x78\xc5\xd0\x8a\x11\xde\x81\x8a\x06\x7b\x06\x56\x91\x5b\x59\xd2\xc5\xde\x8f\xf0\x63\x68\x12\x5f\x11\x04\xca\x1b\x58\x4c\x8f\xd3\x6a\x5a\x4d\x8f\x63\x12\xd8\xc9\x62\xd5\xed\x88\xfa\xa9\x9f\x21\x6f\xb3\xc4\x4f\xfd\x62\xf2\x26\x4b\xfc\xc4\xcf\x60\xd5\xdb\x08\x67\xa1\x1f\x70\x2b\x7b\x2d\xc4\x64\xa3\x48\xa8\x95\x8d\x69\xfb\x43\x84\xc3\xc1\x34\x22\x67\xb5\x01\xf1\x7c\x56\x17\x0d\x86\x83\x2e\x16\xd3\x77\xe8\x2e\xba\x8b\xbe\x43\xdf\x21\xbb\xe8\x2e\xf2\x0e\x79\x87\xec\x22\xbb\xc8\x3b\x58\x35\x81\xd5\x62\x72\xe6\x28\xf1\x93\x16\xf2\x6c\x06\x2e\x65\x89\x12\x57\xb1\xf2\xdf\xa6\x12\xb4\x52\x4b\x73\xa8\xf2\x28\x4d\xca\x20\x4f\xa3\x77\xfe\xf5\xc2\x6f\x5a\x4c\x82\x24\x18\x37\xd8\xef\x11\x51\x0a\x30\x51\xf2\x6d\xa2\xc4\x76\x17\xb9\x83\xc5\xaa\xae\xdd\x81\xbe\xda\xdd\x1b\xbb\x2a\x02\x1b\x6b\x69\x90\x06\x47\xd4\x6e\x0c\x54\x74\x6d\x94\xfc\xaf\x0a\x0c\x92\xa0\x08\x2f\x60\x3f\x40\x98\x99\xce\x62\xed\x04\xe2\x67\x96\x21\x0d\x9d\xb1\x8a\xb7\xd8\x62\x56\x23\x1c\x5c\x81\x88\xff\x07\x31\x16\x2f\x5d\xb3\x66\xa9\x2e\x1a\x22\x53\x11\x8e\xa8\xc8\x54\x15\x85\x0c\x5d\x43\x9e\x25\xf7\x90\x3e\x11\x49\x26\xd3\x68\x27\x43\x47\xd2\x4a\xaf\x75\x53\xd3\xe6\xa6\x2d\x4d\xe9\x2d\x0c\xfe\x18\x2d\x7f\xee\x41\x16\xab\x7e\xe2\x03\x32\x5f\xa2\x10\xc5\xb8\x5f\xa8\x42\x8b\x55\x97\x11\xde\xb8\x31\x50\xb1\x7b\x23\x9e\xc1\x97\x82\x2a\xf2\x11\x8b\xc5\x44\xc0\xe2\x0f\xf8\x0d\x93\x5d\xec\xe7\xa6\x51\x58\xd5\x7f\x51\xd4\xdb\xb6\xaf\x7b\xaf\x3a\x7c\x95\xe9\xed\xac\xa9\x6a\xd6\x95\x2f\x10\x55\x35\x57\xd6\x54\xab\xa3\x57\x99\xaa\xfa\xee\xde\x36\x1d\x76\x21\x7e\x86\x32\x40\xb6\xb1\x98\x58\xd8\x6c\x16\x7b\xbd\x81\x82\x01\x2f\xde\xbd\x3b\xd0\xb7\x71\x37\x2e\x46\x9a\x48\x1d\xc3\x67\x3f\x9d\x26\x52\x47\x76\x22\xbe\x8a\x59\xbe\x7c\x1e\xc2\x64\x27\xdd\xb9\x18\xd1\x9d\x64\x27\xde\xbd\xb1\x2f\xb0\x7b\x77\x3a\x56\x85\x6f\x23\x9f\xd0\x4f\xa2\xb7\x45\x6f\xa3\x7f\x52\xf2\x49\xf8\x36\xbe\x9f\xa7\x3a\xac\x9a\x8e\x30\x31\x92\x6f\xd8\x68\xe8\x22\xa2\x46\x2c\xaa\xed\x6a\xee\xd9\x9b\xb1\xb7\xad\xa7\xab\x4b\x8b\xc9\xad\x48\x8b\x27\xb3\x33\x58\x4c\x5a\xc8\x20\xb9\x85\xc5\xcd\xed\xe4\x55\x16\x93\x95\x48\x87\x89\x1d\x69\xb1\xa8\xa5\xa3\x63\x4b\x87\x7a\xd7\xae\xd6\x9d\x41\xdd\xde\xce\xae\x9e\xd6\x7d\x24\xb8\x18\x8d\xd8\x31\x50\x7f\xb0\x7c\x8f\x04\x13\x0b\xd9\xc8\x56\xb3\xd1\xd0\x18\x16\x93\xb5\x6c\x00\x4d\x60\x62\x93\x05\x24\x89\xc5\xe1\x69\xe4\x47\x3e\x76\xeb\xe4\x7c\x41\x81\xef\x46\x61\x25\x35\x92\x66\x16\x6b\x84\x9f\x91\xd8\x3d\x05\xe7\xa1\x1b\x35\x8b\x97\x6f\x68\x22\x83\x4c\x36\x5f\xda\x79\x11\xce\x47\x74\x14\x26\xe6\x13\xd7\x7d\x08\x93\xf7\x79\x6d\xf7\x6a\x89\x85\xe9\xed\xc6\xc7\xc8\x1c\x16\x8f\x24\x14\x0d\x85\x2e\x06\x88\x32\x25\x70\x9a\xaf\xa4\x48\x30\x0c\xd9\x54\x3b\x26\x86\x8f\xa6\x6c\x6e\xd5\x05\xeb\xb6\xad\x6f\xac\x5d\x3a\x7d\xc4\xa6\xc6\x86\x4d\xf5\x5b\xeb\xb7\x36\xec\x68\x6a\x97\x04\xb0\x2a\x44\x5c\xed\x7d\xdb\xf6\xb4\x76\xa5\xb7\xf6\x89\x76\x30\xcd\xdb\x9a\xb7\x35\x6a\xbb\x1e\xba\x44\x5d\xa2\x61\x29\xce\x20\x57\x56\xa9\x68\x02\x4d\x20\xb1\xbf\xf8\x8b\x26\x10\x48\x13\xc4\x24\x17\xbf\x14\x73\xd9\x72\x56\xfe\xf0\x81\x9e\x83\x9d\xba\xce\x03\x9b\x1e\xad\xec\xc5\xb5\xb5\xeb\x9b\xab\xd5\xd5\xeb\xdb\xba\x6a\x75\x58\xbc\x0c\x61\x7e\x51\x44\x89\x0f\x93\xbc\x15\x24\xfb\x56\xa2\xe0\x6b\xcf\x11\x34\x63\x36\xc2\xd4\x12\x0e\xa9\x7a\x6b\xba\xab\xb4\xd4\x92\xc3\x12\x0b\x83\xf3\x10\xb5\x30\xd9\x88\xf0\x81\x86\x04\xe8\x2a\xb2\x8a\x06\x56\xf2\xe1\x90\x34\xf2\xb7\x29\xfc\x33\x0a\x2b\x31\xd9\xc2\x1e\xc2\x64\x90\xb4\x60\xd2\x8f\xf8\xfa\x05\x67\xb3\xf2\x14\xde\x29\xc2\x37\x91\xd3\xf4\x01\x22\x25\xbb\xc9\x19\x5a\x44\x64\xa9\xc3\x33\x34\xc2\x47\x71\x7f\x29\x1b\x20\x6d\xb1\x1a\x3f\x48\x46\xb2\xf8\x22\xaf\xdf\x69\x08\x0f\xad\x18\x5a\xd1\xd6\xb6\xa3\xad\xb5\x3d\x1d\x0f\xaf\x18\x5e\xd1\xdc\xbc\xb9\xb9\xa5\x29\x1d\xb7\xb0\xeb\x59\x4c\x95\xb3\x10\x1e\x18\x08\x9c\xf6\x0e\x60\xef\x40\xe0\xf4\xc0\x00\xae\x6e\x5f\xdf\x55\x8b\xc9\x5b\x68\x02\xd2\x11\x0b\xc2\xaa\x69\x1f\xad\x20\x09\x44\x9e\x41\xe4\xcf\x92\x84\xcb\x1f\x69\x2f\xdf\xfe\x2c\x4d\xa0\xf2\x0c\x7c\x68\x5f\xc7\xe9\x8a\xc3\x74\x16\xd9\x3d\x62\xcf\xa9\xd3\xc1\xb3\x6a\x32\x9b\x8c\xa1\x63\xe8\x6c\x9c\x16\xd8\x4c\x36\xd1\x5b\xc8\x74\xed\x1a\x86\x68\xa8\x7d\x0b\x5d\x11\xc8\x08\xb4\xd0\x9d\xf8\x7b\x36\x16\x04\x3e\x66\x23\x96\x99\x08\x33\xef\xf3\xd5\x46\x38\x98\x89\xf0\xde\x9e\xf6\xae\x2e\x1c\xab\x03\x71\xb4\x21\x3a\x2e\x3a\x2e\xda\x10\x6d\x08\x8f\x8b\x8e\x0b\x37\x84\x1b\xc2\xe3\xc2\xe3\xc2\x0d\x58\xd7\x59\x5b\xd7\xbe\x5e\x4d\x9f\x5a\x4a\x7f\xa6\xe5\x34\xfb\xf7\x09\xc4\xa8\x1b\xba\xc6\x60\xbd\xb8\xaf\xaa\x6b\x9d\x27\x83\x8f\x04\x7c\x5e\x7c\xa4\xeb\xe1\xbe\x5e\xed\x57\x62\x3c\x1f\x91\x7a\x16\x93\xe5\x48\x2e\x5e\xf8\xdc\xf2\x57\xc9\x7e\xa4\xc5\x35\x61\x01\xea\xe6\x03\xd2\x1d\x08\xc7\x2e\x20\x3a\xcc\x57\x9a\x58\x54\x55\x55\xef\xf5\x66\x78\x3b\xbd\xbd\x55\x5a\xac\xf2\xf8\xfd\x1e\xed\x38\xc6\xe3\x3f\xf0\x88\x0e\x67\xb1\x34\x68\x42\xd8\xdf\x55\xde\x57\xab\xdd\xd4\xb9\xab\x65\x97\x7a\x17\x66\x62\x45\x04\x0e\xa7\xb0\x6d\xe4\x07\xd4\x5c\xdb\xa5\x8b\x87\xbd\x20\x09\xe2\xf0\x54\x72\x85\x5c\x09\x4f\xc5\x0c\x51\xfc\xf2\x0b\x51\xe8\x70\x38\x58\x8c\x70\x3b\x4b\xba\x10\x1e\xc3\x12\x23\x26\xbf\x91\xd3\xf4\x34\xfd\x0d\x8b\xaa\x7a\x07\xea\x07\xd4\x18\x06\x22\x41\x41\x24\x88\xc5\x1b\x59\x4c\x16\x12\x15\x11\x90\xfb\xb6\xe8\x1e\x7f\xae\xff\xe2\xc5\x8c\xee\xad\x7b\xb6\x74\x6b\x71\xff\x65\x35\xf1\xb1\xe4\x34\xf9\x0d\xdf\xf7\xd6\x6c\x97\xbf\xb9\xae\x4a\x4b\x0f\x8b\xeb\x7b\x0f\x6c\x3a\xa4\x7e\xe7\xa5\xb7\x70\x7b\x47\x47\xb0\x2d\x98\x1e\x16\x85\x1f\x11\x7d\x15\xbd\x48\xab\x88\x94\x88\xb1\x8a\xf8\x49\x33\x7f\xeb\x9c\xcb\xea\xa8\x3f\xaa\xc4\x21\x1b\xc1\x59\x59\x36\x8a\x67\xcd\x3a\x45\xf1\xd7\x5f\x9f\x22\x38\xa4\xc5\xd7\x2c\x9d\x6c\x2c\x5e\xc5\x62\x75\x20\x16\xbc\x62\x25\x87\x1e\x61\x22\xe4\xc3\x7f\x03\xab\xe5\x9d\x72\x1f\xc2\x6d\xed\x3b\x3a\x82\x19\x78\x60\xe0\x74\x60\xc0\x8b\x61\x6c\xcf\xc1\xe6\x36\x2d\x26\x77\xf3\x39\x4f\xcc\xef\xaa\xfe\xe0\xc3\x19\x03\x9d\x07\x7b\x7b\xb5\x64\x3c\x19\x27\xda\xdb\x8b\x17\xfc\x17\x61\xaa\x6e\xaf\xd8\xc3\xf5\x70\x07\x0a\x0e\xb4\x1e\x68\xdf\xdf\x21\x69\x3b\xbe\x95\x0f\x5b\x21\x62\x0c\x2b\x49\x10\x06\x88\x51\xc3\x0c\x12\xa3\x00\xf7\xf4\xb4\x75\x75\xe9\x86\x04\xe1\x1f\x45\xc1\x20\xf1\x90\x55\xa4\x29\x03\x2f\x61\xe9\x19\x12\x42\xe4\xaa\x18\x93\x79\x2c\x7f\x09\x51\x46\x2c\xaa\x65\x08\x6f\x69\x6f\x69\x6f\x6e\x6f\xda\xdd\xb4\xa7\xa1\x9b\xea\x48\xe5\x08\x7a\x28\x56\xc3\xd2\x55\xe4\x0a\x92\x8f\xcc\xd1\x30\x06\xf2\x35\xc2\x81\xb0\x84\xc5\xe2\xe3\x15\x41\xaf\x57\x8b\xc5\xf6\xbe\x86\x81\x01\x2d\x26\x62\x2a\xc6\xd4\x4e\x67\xe0\x17\xa9\x98\x6a\xce\xd3\xa9\x6a\x5a\x44\xcb\x69\xb2\x6d\x81\x0e\x3f\x54\x59\xe0\x28\xd1\x76\x95\xb7\xf9\x7c\x19\xab\xfc\x4b\xac\x7e\x2d\xce\x88\xdb\x9e\x76\xe8\x1a\x43\x8c\xbf\xff\x40\xb2\x75\x98\xa1\x8a\x71\xe3\xa8\x42\x37\x1c\x22\x1f\x22\x9c\xcd\x86\x43\x98\xc8\xd9\x23\x7c\x68\x58\xca\xc2\x00\x26\xb7\xb0\x7c\x21\x8b\x27\x21\xfe\x9a\x83\xdf\x8d\x65\x93\xd9\x64\x0c\x19\x43\x66\x63\x55\x00\xe1\x1f\xc4\x13\x11\x7e\xac\xe6\x98\xff\xa0\x16\x07\x16\xf3\xf3\xc4\xc7\xf1\x9a\xe9\xf4\x3f\xd1\x6b\x85\x19\x01\x31\xcd\x27\xa7\x72\x49\x36\x26\xb3\xe8\x6e\x51\x65\x57\x5f\x7d\xbf\xba\x6b\x77\x6b\xc7\x2e\x5d\xfc\xc4\xfe\xfa\x1f\x93\xc7\x59\x3f\x3b\x74\x86\x18\x10\x26\x5a\x52\x47\xb4\xe1\x20\xd1\xde\x49\xee\x21\x4a\xa2\xc5\xe7\x8a\x4f\x70\x5c\x71\x31\xc7\x9d\x28\x3e\x77\xee\xc4\x89\x73\x5a\x9c\x41\x84\x01\x22\xdc\x42\x84\xda\x86\xfa\x6d\x0d\x6a\xeb\x56\xfc\x02\x92\xef\xec\x6a\xdd\xdd\x9d\xc1\x5f\x94\x71\x2c\x73\xc7\xfe\x78\xaf\xe9\x64\xb7\xf0\x56\xc2\x27\xf5\x4d\xec\x6f\xf8\xcb\x4b\x79\x06\x1c\x4b\xde\xb5\xe9\x4f\xad\xea\xaa\xed\x0b\xec\xee\x4a\xc7\x44\x59\x83\x70\x34\x9d\xbe\x49\xab\xe8\x09\x6a\xfe\x2f\x1d\x4b\xcc\x93\x30\x79\x87\xee\x22\xb1\xe2\x22\x5e\x64\xe0\x77\x48\x22\xe1\xde\x23\x63\xd4\x44\xf1\x61\xc1\xb2\x5f\x74\x98\x6c\x44\x43\x96\x25\x2c\x26\x4b\x89\x9e\xe8\xc9\x52\x9e\x52\x3d\x5d\x8a\x35\xa2\x41\x06\x9f\x66\x19\x4c\x82\x34\x88\x17\xcf\x78\x41\xd7\x55\x1d\xac\xda\x55\x2d\xa9\x6b\xef\x68\xc6\xd5\x61\x80\xb4\x34\x44\x43\xa2\xe6\xe6\x16\xac\x11\xf9\x54\x64\x0a\x8b\x67\xb2\xf4\x8c\x18\xf7\xf7\x97\xb7\xb0\x78\x4b\xfd\xf6\xfa\xb6\xc6\xf4\xa6\x36\xdc\xc4\x07\xee\x76\x3e\x70\xef\xae\xed\x0b\x74\x75\xa5\x3f\xf5\x14\xbe\xfe\x95\x08\x09\xe2\x7c\x3e\x19\x9e\x21\x67\xf8\x99\xf0\xfd\x48\xb5\x20\xf2\x0a\xa6\x21\xf1\x24\x84\x55\x44\x8c\xb4\xbc\x47\xc4\x22\x98\xf0\x24\x11\x17\x31\x18\x06\xfc\xac\x00\x87\x01\xab\xc5\x54\xa5\x61\x12\x20\xa6\xca\xd3\x2c\xc4\xcc\x38\x84\x87\x43\x62\x6a\xc0\xe2\x70\x02\xc2\x1d\xc1\xd6\xb6\x36\xbc\x09\x89\x31\x15\x13\x31\xe6\x8d\x92\x2f\x17\xe7\xcc\xa3\x4c\xe5\x8a\x4e\xd7\x66\x6d\x15\xf6\xb3\x42\x4d\x04\x2c\x46\x8b\x91\x18\x77\xf5\x74\xee\xed\xd8\x27\xe9\xdb\x4e\x54\xdd\x7b\x32\x30\x61\xc9\x84\x0c\x32\x61\x31\x61\x27\xfe\xaa\x3d\x81\xa9\x52\x4c\x7e\x67\x71\x46\x77\x47\x67\x77\xab\xf6\x9b\xbe\x37\x2e\x3c\xfe\xa9\x04\x37\x36\x77\x74\x6c\xd3\xbd\x16\x9e\x28\xda\xb5\xad\xb3\x83\xdf\xd1\x66\x14\x73\xde\xcd\x08\x73\xf6\x33\xba\xd2\xc7\x0e\x54\xfe\x43\xfd\x8f\xfd\xfb\x0e\x63\x46\x8f\x48\x1a\xd2\xe1\x8e\xb6\x5d\xed\xba\x5d\x7b\x83\xbd\x5d\x7b\x25\xef\xbd\x80\x37\x21\x15\xee\x68\xe9\x50\xe3\x2d\xac\x0a\x5f\x0c\x90\x9f\x10\x3e\x80\xce\xf1\x7b\x2e\x64\xc3\x46\xf1\x71\xdc\xbd\x37\x83\x28\xc5\xc1\x1d\x1d\x6d\x6d\xda\x36\x6c\x44\xc4\xb2\x92\xc5\x74\xcd\xb5\x85\x22\xf2\x05\x43\xd6\x44\x16\x8a\xe2\x57\x71\x6a\x99\xc8\xc6\xcc\x9e\x04\x71\x74\x2a\xb9\x42\xf9\x38\x18\xe6\xef\x94\xe1\x86\xe8\xb8\xf0\xb8\x68\x03\x5f\x4a\x34\x23\x4c\x43\x31\x13\x8d\xa2\x00\x3e\x41\xc2\x2c\x7e\x9c\xe5\xaf\xca\x98\xfa\xc5\xe3\x59\x3c\x19\x8d\xe5\xa5\x5c\x24\x4a\xac\x89\xcc\x10\x63\x0f\x22\xb7\xb2\x78\x9d\x7f\xbd\xbf\x5e\x57\xef\xdb\xe9\xde\x57\x85\x75\xcd\xcd\x9b\x1b\x1b\x32\x7c\x64\x2c\x1d\x83\xff\xf7\xe5\x56\xcc\x4e\x53\xc8\x11\x16\x1b\x0c\x9b\x0d\xea\x72\xba\x60\x7b\x6b\x13\xef\x27\x27\xf9\xfa\x88\x0f\x30\x98\x79\x88\xc5\x1b\x6b\x03\xe5\xbb\x6b\x71\x3f\xf9\x18\x41\x5c\xb3\xd6\x91\xe1\xe8\xc6\xe2\x3c\x16\xd3\x19\x64\x06\xa6\x2c\xd5\xd6\xd5\x6d\xad\xec\xdc\x98\x8e\x19\x92\x87\xf8\xbb\xfc\x82\x8a\x14\x6c\x1a\x39\xca\xf8\xf9\xef\xbf\x7d\xf1\xc5\x6f\xbf\xe3\x8a\x12\x1d\xad\x16\x6f\x68\x6a\xda\xa0\xc5\xda\x89\x63\x16\x53\x96\x4e\xc8\xa0\x13\xb0\x8a\xca\x28\xa6\xdb\x98\xda\x86\x00\xd6\xb6\x36\x36\x6c\x6f\x50\x4f\x42\x37\xd6\xc7\x87\xd8\xf8\xd7\x79\x44\x89\x55\xe4\x2c\x7f\x5b\x62\x8a\x09\xc3\x60\x91\xef\xc0\xb1\x9a\xc7\xd4\x98\xd9\xdb\x53\x53\xb5\x4d\x87\x45\xbd\xdb\x7a\xba\x63\x17\xae\xb0\x88\x37\x7c\x65\x38\xa4\xc2\x03\xac\x16\x17\x51\xf1\x49\x06\x8b\xc9\xd3\x08\x0f\xf1\x9b\xa5\x37\xd3\x39\xbc\x93\x5a\xb0\x66\x68\x06\x83\xa3\xca\xb0\x12\xdf\xfa\xe0\xb9\xe3\xf9\xba\xc3\x0e\xff\x3e\x4c\x8e\x22\x7e\x36\xb9\x1f\x61\x2a\xb9\x42\x6f\x22\xc6\x65\xe4\x1f\xb8\xa2\xb4\x52\x77\xb8\x6a\x6d\x9f\x5d\x8d\xd5\x74\x04\x05\x14\xd0\x11\x3a\xac\x7a\xdc\x7d\xa0\x68\x85\xad\x70\x45\x21\x16\x3f\x88\x8a\x58\x2d\xd6\x6a\x84\x7c\xb9\xe6\xad\xf7\x55\x55\x69\xe9\x78\x3a\x0e\x93\x91\x2c\x1f\x0d\x30\xe5\xcf\x4a\xd4\xd5\xd5\x83\xa9\x92\x2a\x31\xb1\x93\x19\xb8\xbf\x1c\x06\x30\x04\x10\x00\x0c\xc1\x48\x00\x6a\x00\x68\x04\x60\x2b\x00\xdb\x01\xe8\x06\xe0\x61\x08\x8e\x00\xb8\xf9\x8f\x84\xcd\x7f\x08\x36\x9f\x4e\x78\x41\x00\xf8\xa1\x26\x00\x72\x01\x78\x11\x80\xdf\x00\xec\x00\xb0\x13\xc0\x2e\x00\xbb\x01\xec\x01\xb0\x17\xc0\x3e\x00\x4f\x03\xf8\x04\x80\x11\x90\xa0\x07\x09\x77\x83\x84\x2f\x80\x40\x02\x04\x39\x40\xd0\x0a\x04\x17\x80\x30\x1d\x08\x73\x80\xb0\x01\x08\xdf\x04\xa2\x51\x40\xd4\x03\x44\x5f\x03\x26\x19\x30\x3b\x01\xf3\x06\x90\x30\x40\xb2\x11\x24\x4a\x40\x62\x06\x48\xbc\x1b\x24\x5e\x05\x68\x21\x40\x3b\x01\xfa\x18\xe0\x3b\x01\xae\x02\xf8\x13\x20\xdd\x0d\xa4\xdf\x01\xd9\x6d\x40\xf6\x18\x90\xcf\x02\xf2\xc5\x40\xde\x0e\x14\x1b\x40\x52\x0e\x48\xce\x01\xc9\x53\x41\x72\x23\x48\x71\x82\x94\x5a\x90\xf2\x0b\x48\x5d\x05\x94\x26\xa0\xd2\x02\xd5\x71\x90\xd6\x0a\x6e\x2a\x05\x37\x75\x83\x9b\x9e\x05\x37\x7d\x0b\x6e\x8a\x80\x11\x13\xc0\x88\x87\xc0\x88\x9d\x60\xc4\x07\x20\x7d\x1a\x48\x7f\x1e\xa4\x53\x90\xa1\x00\x19\x9d\x40\x9d\x0f\x34\x93\x80\xe6\x7b\xc0\xce\x03\x2c\x07\xd8\x2a\xc0\x3e\x0c\xd8\x10\x60\x7f\x07\xec\x1f\x40\x3b\x1e\x68\xef\x00\xda\x07\x80\x76\x13\xd0\x9e\x07\x3a\x08\x74\x77\x00\x5d\x01\xd0\x45\xc0\xc8\x25\x60\xe4\x47\x60\x54\x26\x18\xf5\x2e\x18\x3d\x11\x8c\x5e\x0d\x46\x9f\x07\x37\x67\x82\x9b\xfb\xc1\x18\x29\x18\xb3\x0e\x8c\xf9\x08\x8c\xf9\x01\x8c\x15\x80\xb1\x1b\xc1\x38\x13\x18\xf7\x25\x18\x3f\x13\x8c\xff\x11\xdc\xca\x80\x5b\xdb\xc1\x6d\xf3\xc1\x84\x9b\xc0\x84\x41\x30\x51\x0b\x26\x96\x82\x89\x87\xc1\xc4\xcf\xc1\xa4\x76\x30\x39\x05\x4c\xce\x02\x93\xbb\xc0\xe4\x8f\xc0\xe4\x6b\x60\xca\x62\x30\xe5\x0a\xc8\x14\x83\xcc\x56\x90\x95\x0b\xf4\x97\x80\x9e\x02\xa3\x1a\x98\xd6\x01\xd3\x56\x60\xfa\x1d\x98\xa7\x01\xf3\x20\xc8\xce\x02\xd9\x95\x20\xfb\x19\x90\x63\x07\xb9\x11\x70\xfb\xfd\x60\x6a\x25\x98\xc6\x82\x69\x16\x30\xad\x1e\x4c\x67\xc0\xf4\x13\x60\xfa\x10\xb8\xb3\x19\xdc\xf9\x14\x98\x31\x0a\xcc\x78\x0f\xcc\x5c\x0b\x66\xfe\x04\x66\xed\x06\x79\x3d\x60\x76\x2b\x98\xf3\x28\x98\x3b\x08\xe6\x5d\x01\x77\xcd\x07\x77\x9d\x06\x77\x8b\xc0\xdd\x16\xb0\x48\x0d\x16\x75\x82\x45\x9f\x81\x7b\x47\x83\x7b\x2b\xc1\xe2\x54\xb0\x58\x05\x16\xdf\x04\x16\xa7\x83\xc5\xef\x82\x25\x93\xc0\x92\x72\xb0\xe4\x0d\x60\x79\x18\x3c\x30\x0f\x2c\xd5\x80\xa5\x8f\x82\xa5\x27\xc0\xd2\x57\xc1\x83\x2c\x58\x96\x05\x96\x2f\x03\x2b\x5e\x02\x2b\x27\x80\x95\x2f\x80\x87\xf2\xc0\xaa\x24\xb0\x6a\x10\xac\x8a\x82\xd5\x41\xc0\x4d\x00\x5c\x2e\xe0\xe6\x01\xce\x0d\xb8\x0e\xc0\xbd\x03\xb8\xaf\x00\xf7\x1f\xc0\xfd\x01\xd6\xb4\x01\xeb\x08\x60\x9d\x07\xf2\xcd\x20\xff\x79\x90\xff\x15\x28\x58\x0c\x0a\x5e\x01\x85\xe3\x41\xe1\x65\x60\x5b\x04\x8a\xe6\x81\xa2\xbd\xa0\xe8\x0a\x28\xbe\x03\x14\x7f\x08\xec\x2d\xc0\xfe\x26\x70\x4c\x02\x8e\x3a\xe0\xf8\x0a\xac\x1d\x09\xd6\x5e\x06\x25\x15\xc0\x39\x16\x38\xbb\x41\x69\x36\x28\xed\x03\xa5\x2f\x83\xd2\x9f\x81\x6b\x0c\x70\x4d\x05\xae\x7b\x81\xab\x00\xb8\x9a\x80\xeb\x39\xe0\x7a\x0d\xb8\x3e\x04\xee\xd1\xc0\xdd\x0e\xdc\xff\x02\x1e\x16\x78\xc6\x01\xcf\x1d\xc0\xb3\x0c\xac\x83\x60\x1d\x02\xeb\x6a\x80\xf7\x6e\xe0\x6d\x07\xbe\x1c\xe0\xbb\x1d\xf8\xa6\x01\xdf\x76\xe0\xfb\x04\xf8\x22\xc0\xbf\x15\x94\x6d\x05\xe5\xd3\x40\xc5\xdd\xa0\xc2\x0e\x2a\x42\xa0\x72\x1e\xa8\x7c\x03\x54\x8d\x04\x55\x8d\xa0\x7a\x1c\x58\x6f\x06\xeb\xcb\xc0\xfa\x27\xc1\x06\x1d\xd8\xd0\x00\x36\xbc\x07\x6a\xfe\x01\x36\x8a\xc0\xc6\x3d\x60\xe3\x2f\x60\x63\x14\xd4\x3e\x01\xea\xf2\x40\xdd\x5e\x50\xf7\x3e\xa8\x4f\x06\xf5\x0b\x41\x7d\x33\xa8\xff\x0e\x34\xe4\x82\xc6\x24\xd0\x98\x07\x1a\x37\x80\xc6\x1e\xd0\x78\x16\x34\xe9\x41\x53\x2b\x68\xce\x01\xcd\x4b\x41\xf3\x0e\xd0\xfc\x33\xd8\xb4\x18\x6c\x6a\x01\x9b\x13\xc1\xe6\x02\xb0\xf9\x33\xd0\xa2\x04\x2d\xf7\x83\x96\x76\xd0\xf2\x05\xd8\xf2\x02\xd8\x7a\x2f\x08\xa4\x82\xc0\x49\xb0\xed\x6e\xb0\xed\x75\xb0\xfd\x3b\xd0\xfa\x25\xd8\x71\x33\xd8\xb1\x01\xec\xb8\x00\x76\xde\x04\x76\xde\x03\x76\xb6\x81\x9d\xe7\xc0\xce\x4f\x40\x5b\x2f\x68\x5f\x03\x82\x4f\x80\xae\x74\xd0\xf5\x02\xd8\x5d\x0a\xba\x11\xe8\xee\x00\x7b\x20\xe8\x59\x0c\x7a\xdc\xa0\xa7\x1f\xec\x1d\x04\xbd\xff\x06\xfb\xb2\xc0\xbe\xad\x60\xdf\x65\xd0\x77\x1b\xe8\xab\x04\x7d\x2f\x83\xfe\x9d\xa0\xff\x0d\xb0\xff\x35\xf0\x88\x11\x3c\x5a\x04\x0e\x4d\x06\x87\x05\xe0\xf0\x5d\xe0\xf0\x7b\xe0\x88\x1a\x1c\x79\x00\x1c\x7d\x08\x1c\xfd\x05\x1c\xcb\x02\xc7\xbe\x07\x8f\x7d\x03\x4e\xec\x00\x27\x93\xc1\xc9\x0b\xe0\xd4\x78\x70\x2a\x0f\x9c\xaa\x00\xa7\x8e\x80\x53\x4f\x82\xc7\x57\x82\xc7\x87\xc0\xe9\x07\xc1\xe9\x7e\x70\xe6\x11\xf0\x44\x0b\x38\x2b\x01\xe7\x6e\x01\xe7\xf6\x80\x27\x59\xf0\xe4\x15\xf0\x54\x3e\x78\xea\x4d\xf0\xf4\xeb\xe0\x99\x13\xe0\xd9\xa9\xe0\xd9\x8f\xc0\x73\x4a\xf0\xdc\x31\xf0\x8f\xf9\x60\x70\x3d\x78\xe1\x29\xf0\xe2\x64\xf0\x52\x12\x78\xa9\x17\xbc\x7c\x1f\x78\xf9\x31\xf0\x4a\x11\x78\xe5\x38\x38\x7f\x1b\x38\xff\x3e\x78\xf5\x3c\xb8\xd0\x03\x2e\x76\x81\xd7\xb6\x80\xd7\xb7\x81\xd7\x2f\x80\x37\xd2\xc1\x1b\x1b\xc0\x9b\x6b\xc0\x9b\x47\xc1\x3b\x2b\xc0\x3b\xbd\x20\x74\x0b\x08\xfd\x13\xbc\x3b\x1f\xbc\xfb\x3c\x78\x0f\x82\xf7\x7e\x02\xff\x7e\x06\xbc\xaf\x05\xef\xbf\x0f\x3e\xf0\x80\xcb\xb9\xe0\xc3\x11\xe0\xc3\xcf\xc1\x47\xb3\xc1\xc7\x0a\xf0\x69\x2e\xf8\x6c\x2b\xf8\x3c\x0c\x3e\x1f\x06\x5f\xbc\x06\xbe\x7c\x0e\x7c\x35\x00\xbe\xfa\x03\x7c\x5d\x0c\xbe\x7e\x02\x7c\xfd\x6f\xf0\x7f\x7f\x80\x6f\xfc\xe0\x9b\x8f\xc0\xb7\xc5\xe0\xdb\x30\xf8\x7e\x22\xf8\xfe\x23\xf0\xc3\x31\xf0\xe3\x08\xf0\xe3\x66\x70\x65\x1d\xb8\xf2\x05\xf8\xf9\x4e\xf0\xf3\x55\xf0\xcb\xa7\xe0\x3f\x6e\xf0\xeb\x2a\xf0\x5f\x2d\xb8\x9a\x05\x86\xac\x80\xce\x87\x20\x0f\xc2\x73\x50\xd0\x0f\x85\x42\x28\x3c\x0a\x45\x99\x50\xf4\x36\x64\x3e\x81\xe2\x62\x28\xfe\x12\x4a\xb6\x40\xc9\x00\x94\x7c\x0a\x13\xc7\x40\x84\x21\xfa\x02\xe2\x45\x10\xef\x82\xd2\xdd\x50\x36\x17\xca\x27\xc3\xa4\x74\x98\xcc\xc0\xe4\x2a\x98\xb2\x0e\xa6\xbc\x0b\x55\x1f\xc0\x34\x23\x4c\xfb\x0a\xde\x14\x81\x23\xce\xc1\x8c\x5d\x50\x3d\x01\x6a\xb4\x50\xb3\x10\x6a\xf6\x40\x76\x1a\xd4\x36\x43\xdd\x0e\x38\xf2\x2c\x1c\x75\x07\x1c\xf5\x39\x1c\x3d\x15\x8e\xb6\xc3\xd1\x9f\xc0\x9b\x53\xe1\xcd\xdb\xe0\x98\x7c\x38\xb6\x18\x8e\x9b\x0d\xc7\xb5\xc1\xf1\x0c\x1c\xbf\x1d\x8e\x3f\x0d\xc7\x7f\x08\xc7\x7f\x0c\xc7\x7f\x0a\x6f\xd1\xc0\x5b\x9e\x83\xb7\x3e\x07\x6f\x1b\x0d\x6f\x3b\x08\x27\x74\xc2\x09\x9f\xc0\x89\x77\xc2\x89\x1e\x38\xf1\x2c\x9c\x34\x17\x4e\x7a\x00\x1a\xef\x80\xc6\x43\xd0\xb4\x11\x9a\x7e\x81\x66\x31\x34\xb3\xd0\x6c\x80\xe6\x3b\xa0\x79\x27\xcc\x4e\x84\x39\xa3\x61\xee\x6e\x98\xfb\x3a\xbc\x7d\x12\x9c\x3a\x17\x4e\xfd\x16\x4e\xcb\x85\xd3\x28\x9c\x3e\x1e\x4e\x7f\x08\x4e\xef\x86\xd3\x9f\x87\x77\xa4\xc1\x3b\x97\xc3\x19\x4b\xe0\xcc\xb7\xe0\xac\x67\xe0\x6c\x25\x9c\x33\x13\xce\x3d\x0f\xe7\x6d\x85\x77\xdd\x02\xef\x3a\x00\xef\x16\xc1\xbb\x4b\xe1\x82\x79\xf0\x1e\x0d\xbc\xe7\x7d\xb8\x70\x35\x5c\xb4\x02\xde\xfb\x1c\x5c\x5c\x09\xef\x9b\x01\x97\xc8\xe1\xfd\x63\xe1\xfd\x4e\x78\xff\x1f\x70\xe9\x51\xf8\xe0\x69\xb8\xec\x76\xb8\x6c\x09\x5c\xf6\x30\x5c\xf6\x15\x5c\x2e\x81\xcb\x57\xc1\xe5\xef\xc0\x15\x75\x70\xc5\x0b\x70\xe5\x04\xb8\xd2\x05\x57\x9e\x87\x0f\x15\xc2\x87\xda\xe0\xaa\x62\xb8\x7a\x39\x5c\xfd\x0d\xe4\xf4\x90\xfb\x12\xae\x31\xc1\x35\x17\xa1\x75\x3f\xb4\xfe\x04\x0b\x66\xc1\x42\x01\x2c\x9c\x0a\x0b\x1f\x84\x85\xe5\xb0\xb0\x07\xda\x46\xc1\xa2\x11\xb0\xe8\x1b\x58\xec\x86\xc5\xaf\x43\xfb\x22\x68\xff\x27\x74\x94\xc0\xb5\x33\xe0\xda\x0f\x60\xc9\x25\xe8\xfc\x18\x96\x36\x40\x57\x1f\x74\xf7\x43\x4f\x14\xae\xb3\x43\xef\x4e\xe8\x7f\x0a\x96\x95\xc0\xf2\xe5\xb0\xa2\x08\x56\xfe\x08\xab\x97\xc2\xf5\x5e\xb8\xa1\x01\xd6\x4c\x81\x1b\x19\xb8\xf1\x49\x58\xdb\x08\xeb\xa2\xb0\xfe\x24\x6c\x7a\x00\x36\x6d\x87\x4d\xd7\xe0\xa6\x32\xb8\x59\x07\x5b\x94\x70\xcb\xab\x70\xeb\x4a\xb8\x95\xc0\xc0\x05\xb8\xad\x1b\x6e\x97\xc1\xed\x7e\xd8\x9a\x06\x5b\xf7\xc1\x1d\xf3\xe1\x8e\x1f\xe0\xce\x93\xb0\x7d\x23\x6c\x7f\x1b\xb6\x7f\x08\xdb\xbf\x86\xed\x3f\xc3\xf6\x21\xd8\x71\x14\x06\x77\xc2\xce\xf3\xb0\xeb\x26\xd8\x65\x80\x5d\xf3\x61\xd7\x21\xb8\xfb\x66\xb8\xbb\x0d\xee\x3e\x0e\xf7\xbc\x08\x7b\x76\xc0\xbd\x05\xb0\xf7\x0f\xb8\xef\x1b\xd8\xf7\x06\xdc\x3f\x06\xee\x3f\x0c\x0f\x4c\x85\x03\x17\xe0\xc0\x6b\x70\xe0\x0d\x38\xf0\x16\x1c\x78\x07\x0e\x84\xe0\xc0\x7b\x70\xe0\x7d\x38\x70\x19\x0e\x7c\x04\x07\x3e\x81\x03\x9f\xc1\x81\x2f\xe0\xc0\x57\x70\xe0\xff\x86\xff\x08\x10\xa1\x46\xa4\x23\x42\x48\x84\x44\x18\xb6\x10\xa1\x80\xf8\x89\x50\xa5\x11\x8d\x0c\x5b\x34\x91\xcf\xa2\x16\x31\x15\x52\xa1\x6a\xc8\xb8\x18\x0d\x1b\x35\x11\xc0\xc8\x35\x91\x77\xe5\x23\x0b\x58\x82\x34\xa2\xa0\x40\x23\xba\x10\xae\x56\xd1\x7d\x64\x32\xd9\x47\x26\x9f\x3f\xde\x7f\xd9\x7e\x3e\x7d\x01\x49\xb0\x9f\x9f\xd6\xbf\xc8\x9e\x4e\xf7\xd1\x49\x22\xf2\x8a\xf8\x32\xa2\xca\x5f\x10\x7d\x45\x4c\xf7\x91\x49\x8b\x8e\x4f\x2b\xb7\x2f\x4a\x5f\x40\x13\xec\x8b\xfa\xa7\x9d\xb7\xa7\x93\x7d\x74\x32\xdd\x47\x27\x2f\xb2\x97\x4f\x3b\xbe\x28\xfd\x22\x4d\x38\xbe\xe8\x72\xf9\xf9\xe3\xe9\x64\x1f\x99\x24\xa2\xaf\x90\x41\x44\x5e\x11\x93\x7d\x74\xd2\x79\xfb\xe5\xfe\xe3\xe7\xd3\x2f\x92\x84\xe3\xe7\xcb\x2f\x2f\x3a\x9e\x2e\xa7\x7f\xf4\x97\x93\xed\x6c\xd4\x18\x36\x92\x6f\x58\x6a\xb9\x88\xa2\xc6\xa8\x31\xfe\xcd\x26\xb5\x4c\x43\x61\x63\xd4\xf8\x31\x4b\x2c\x33\x51\xd8\x18\x36\x8a\x17\x22\xf9\x70\x6d\x80\x84\x86\x32\xc9\x93\x30\xac\x24\x21\xc1\x90\x85\x1c\x53\xed\xaf\xea\x2d\xd3\xd2\x26\xa6\xac\xaa\xaa\x4c\x47\x9b\xc4\x65\xbd\x55\xfb\xb5\xa4\x89\xd9\xdf\xdb\xbb\x5f\x47\xde\x1a\xfa\x48\x45\xaa\x68\x13\xb9\x93\xae\xa5\x6b\xe8\x44\x23\x9d\x47\x81\xb6\xae\x6a\x47\xd9\xde\x8d\x24\x87\x26\x8f\xd8\xd4\xd1\xd1\x12\x54\xef\xea\x6a\xeb\xec\xd0\xbd\xfc\xee\xc1\x83\x07\xf7\x4a\xf6\xec\x3f\xd3\xfd\xa4\xfa\xa3\xd0\xf2\xfb\x17\x94\xac\xbd\xc3\xae\x33\x14\x50\xe9\xcd\x54\x96\xb1\x5a\x5c\xd6\xed\x88\xc9\x3e\xb0\xf7\xe1\xfd\xba\x80\xf8\xd0\xc9\xb7\x5e\x7e\x4c\xfb\xfd\x20\x51\x85\xc8\x92\x0c\x79\xff\x5f\x5e\xf4\x8f\x70\x30\xac\x24\xdb\x59\x0d\x9d\xa1\x67\x35\xc2\xc1\x99\x48\xde\x2f\x27\x46\x04\x87\x82\x24\x28\xd0\x30\x07\x35\xa2\xb9\xaa\x67\x17\x06\x8b\xb4\x9a\x48\x1d\x53\xb4\xb0\x61\x85\xeb\x80\xab\xaf\x42\x37\x24\x1d\x96\x8a\x86\x83\x34\x24\xae\x47\x11\x25\xf3\x25\x4b\x43\x43\x41\x66\x48\x3a\x24\x15\xf5\xf5\x1d\x38\x74\x28\x43\xde\x5f\x0e\xc9\x33\x88\x54\x22\xc1\x62\xa4\x11\x8d\x54\xf1\xd7\xd5\xfa\x86\xad\x2d\x0d\xda\xe1\x10\x0d\x8a\x0a\x36\xba\x8b\xac\x19\xd7\x56\x92\x51\x68\x68\xb9\x78\x28\x48\xea\x45\xd1\xc7\xc8\x28\x24\x1f\x19\x20\xc1\x88\xf2\x14\x8a\x28\x49\x50\xb0\x09\x0d\x59\x66\xa0\x01\x56\x27\xef\xa7\xca\xf8\x4d\x77\x28\x48\xf2\xd9\xd3\xec\xd1\x1e\x56\x13\x99\x51\x87\x86\x82\xe2\x7e\xdf\x81\xb2\x81\x0a\x72\x33\x4d\x20\x63\xa8\x90\xe8\xa8\x44\x72\xcf\x7b\xdf\xde\xf1\x5f\xf5\x36\x66\x1b\xf3\xdf\x6f\xdf\xbf\xf0\x9e\x8e\xe8\x88\x84\x8c\x21\x42\x72\x33\x49\x18\xe8\x3b\xb0\xbf\xff\xa0\x64\x38\x28\x8e\x9c\x10\x9a\x73\xa9\x60\xfe\x32\x2d\xcd\x18\x4d\x33\x46\xd1\xf4\x51\x92\x35\x4b\x27\x4c\x99\xa3\xde\xca\x6c\x65\xe6\x4c\xf8\xe6\xec\x52\x1d\x4d\xff\x8d\x66\xfc\x46\x33\xae\x4a\xb2\xde\x59\xf2\x13\x61\x32\xe6\x22\x2d\xe9\x63\x4f\x35\x73\x5e\x1d\x51\x9e\xfc\x1d\xf5\xaf\x60\x35\x62\x20\x88\x28\xa9\x52\x45\xdc\xec\x71\x44\x9b\x88\x87\xae\xea\x68\xd2\x0d\x09\xa3\x3f\x89\x6a\xbb\x7a\x9a\x7b\xd4\x72\xe2\x67\x4f\xb3\x11\x99\xea\x70\x49\x97\x6f\x87\x36\xba\x35\x44\xcb\xc2\x2b\x45\xfb\x1a\xaa\xf7\xfb\xd5\xe5\x6c\xf8\x01\x5a\x27\x6a\xea\xea\xde\xd4\xad\x3e\xd4\x75\xf0\x61\xb2\x02\x11\x3f\xab\x11\xae\x0b\x1f\x52\x5d\x8a\xe6\x46\x65\x64\x65\x54\x4e\x57\x86\xc2\xb9\xf4\x65\xf2\x5c\xf8\xf6\x57\xc9\x7d\xe1\x14\x72\x5f\x34\x25\x7c\xfb\x42\x11\x59\xf7\xca\xff\x3f\x52\x0f\x3c\x42\x56\xa0\x68\xed\x0a\x76\x0b\x2b\xd8\xc2\x12\x56\x45\x7a\xe6\x93\x7f\xd1\x3d\x5a\xd2\x83\xe8\x9e\xf9\xf4\x5f\xb4\x87\x8e\xfb\x81\x62\x92\xa8\x1b\xfa\x9e\x21\x89\x3f\x10\x4c\xc6\xe9\x68\x30\x82\x55\x56\x76\x3f\xd2\xca\xc9\xad\x34\x48\x36\xc4\xef\xad\x41\xe2\x43\x61\xe5\x82\x0a\x36\x12\x1c\x0e\x12\x80\xae\x05\x35\xc2\x3a\x02\x58\x3f\xab\xa1\x3c\x8d\xf2\xa7\x04\x50\x58\x19\x55\x56\xb0\x44\x49\x8c\xaa\x65\x48\x33\x34\xb8\x0a\x69\x22\x83\xc5\xac\x86\x99\x71\x01\x8d\xec\x2f\x27\x5f\xa3\xa1\x60\x38\xa8\xea\x60\x37\x21\x61\x07\x1b\x51\x46\x95\x37\x78\x39\x79\x84\x0d\x07\xc9\x99\xe5\xec\x90\x45\x68\x40\x43\x4a\x1a\x5a\xce\x0e\x2b\x35\xc2\xc1\x98\x1d\x69\x69\x88\xb9\xee\x7f\xe2\xa5\x67\xd7\x0c\x6a\x49\x88\x19\x3c\x7b\x76\x50\xc7\x0f\x3c\x8d\x62\x03\x4f\xa3\xd8\xd4\xff\x2f\x49\x5b\x58\xf2\x6f\xf6\x9a\xe5\xc6\x6c\x32\x15\x69\x28\xd0\x08\x07\x97\xb3\xff\xcf\x4f\x86\x2c\xc2\x87\xfe\xde\x23\xef\xef\xd6\x08\x07\x20\x91\x69\x18\xb9\x40\xc3\x6c\x8e\xac\x56\x0d\xd4\x0f\x54\xf5\x6a\xa9\x86\x68\x48\x02\x1a\x1e\x33\x3c\x96\x3e\x4d\x9e\x21\x09\x88\x6a\xa8\x86\xdc\xcd\x92\x6b\xf4\x1a\xe1\xd9\xa5\xec\xc0\x40\x67\x6f\xaf\x8e\x68\x88\x66\xc8\x3e\x64\x17\xf5\xf6\x76\x0e\x0c\x64\xc8\xe9\x1f\xad\xe5\x90\x24\x68\x84\x03\x02\x8d\x28\x85\xac\xbd\x21\xf0\x69\x12\x7b\x5d\x1f\xf6\x37\x14\xfa\x34\xff\x22\x4f\xff\x05\xe5\xe9\xeb\x7d\x77\xb3\x7f\x07\x8b\xc9\xa0\x4f\xff\x0d\xfd\x06\x32\xef\x68\x4b\xd9\xb0\xf2\x14\xe2\xdf\x49\x50\x19\x8d\x04\xc9\x25\x44\xfd\xc4\xcf\x5c\xff\xf9\x0c\xf5\x53\xbf\x38\xfe\xec\x8d\xf8\xa9\x9f\x79\x1c\x69\x2f\x7a\x11\xf1\x13\xbf\xf8\x0e\x44\x94\x47\x67\xf0\x97\x65\xdd\x5f\x24\xf1\x4e\xab\xfc\x2c\x26\x27\x1a\xba\xfe\xd4\x2e\x1c\xf2\xfe\x65\x2c\x8d\x7f\x8f\xc8\x47\x9d\x6f\x91\xd2\x13\x7b\x9a\x47\x36\x53\x21\xf1\xd3\x07\xc9\x38\xed\xfd\x67\x6f\xaf\xb3\x2e\x59\x73\x7f\xd7\xed\x2f\x5a\x25\x24\xed\xd6\xf7\xe8\xad\xd4\x9c\x71\x81\xa5\xc7\x69\x75\x58\x88\x88\xf9\x3d\x72\x2b\x49\xbb\xa2\x7d\xf1\x89\xae\x8f\xd6\xbc\x68\xfd\xd7\xd4\x5d\x4b\xd6\x48\xe8\x83\x74\x1c\x15\x52\x3f\xdd\x9c\x41\x2e\xb1\x64\x31\xab\x1d\x56\x0e\x05\x55\x6f\xdf\xf7\xd2\x9c\x39\xf7\xdd\x37\x47\x3b\x1c\x7f\x34\x4e\xae\xb1\xb1\x30\x12\xc3\x27\xdd\xac\x80\x04\x7f\x58\x8e\xf8\x10\x4d\x72\x10\x0d\x91\x71\x6c\x98\xe7\xa2\x3c\x17\xb1\x90\x1c\x74\xcd\x42\xc6\xb1\x1a\xd1\x20\xc9\x41\x9a\xc8\x8c\x9f\x91\xdc\x86\x22\xc1\x21\xe5\x7a\x14\x0e\x12\xa8\xda\x5b\xdb\x53\xdd\xaa\xa5\x0b\x1e\xad\x3f\x56\x73\xac\xfa\x68\xfa\x63\x4f\x9f\x3c\xf7\xd8\x53\x92\x9d\xed\xad\xed\xc1\x8c\x8e\x2d\x1d\x9b\xda\xb4\xd6\x97\xe7\xbc\xba\xf4\x59\x49\x5b\x53\xc3\x8e\x06\x75\x43\x43\x4b\x73\xb3\x8e\x8e\x1e\xe9\xda\x53\xda\xe5\xec\x4c\x77\x93\x7b\x44\x7b\xb7\xac\xdf\x5d\xa5\xa6\x5e\xa6\xaa\xa6\x76\xfd\x66\xdd\xfa\x7b\x9b\xe7\x37\x2d\x72\xd6\x3b\x37\xba\x36\x50\xed\xef\x23\xda\x1a\xf9\x89\x0e\xaa\xa6\xe3\xd6\xfa\x74\x9b\x9a\x36\x37\x35\x64\x34\xec\x68\x6c\x6b\xd2\x9e\x5c\x7d\x62\xf5\x63\x2b\xd7\x97\x6e\x2c\xad\x2f\xa1\x8b\xdc\x23\x36\xb4\xd4\x56\x6d\xc8\xa0\x5e\x71\x75\xd7\xfa\xbd\x2d\x5a\xb2\xc0\xd3\xe9\xe8\x5e\xbb\xb7\x24\xdd\xf1\x50\x11\xe7\x58\x25\xd9\xd4\xd4\xd2\xd4\x90\xd1\xb8\xbd\x71\x67\x93\xf6\x89\xfb\xde\x5e\x38\xb8\x52\xd2\xd4\x1e\xdc\x1c\x54\x07\x83\xb1\x27\x7a\xa3\x7e\x3f\xb4\xe1\x70\xed\x91\xfa\xf4\x47\xe9\x3d\xa2\xea\xed\x3d\x1b\x7b\xd5\xc4\xcb\xf4\x76\x77\xf5\xec\xd0\xf5\xbc\xd2\xf6\x5a\xfb\xf9\x23\x9d\x47\x76\x1f\xda\x43\xb4\x14\x8c\xd8\xd4\xc1\xcf\x7c\x8c\xa8\xc9\xf8\xa3\x07\x75\x6d\xb1\x0d\x07\x37\x07\x9b\xdb\xb5\x45\x4f\x16\x9f\x73\x3c\xdb\x73\xa8\xeb\xf0\xae\xa3\x64\xe1\xa3\x23\x7a\x5a\xbb\x7a\xf7\xf0\x46\x5e\xca\x46\x62\xcf\x18\xc9\x49\xf6\xfa\x97\x2d\xbf\xb1\xe1\xe0\xd0\x19\xd5\x5e\x96\x04\xc3\xa1\xbf\x10\x25\xbd\x45\xb5\xd2\xe3\xde\xa4\x1d\x0e\x31\x9b\x3c\x8f\x3e\xa3\x8b\xdc\x15\x51\x5e\xbb\x4b\x3c\x6c\x8c\x9c\xff\x14\x3d\x5b\x71\xef\xe9\xa5\x6a\xde\xfd\xef\x2d\x58\x51\xa1\x9b\x43\xa7\x8a\xe8\xab\x6f\xb0\xd7\xee\x61\x68\xc2\xa5\xac\x2f\xb5\x43\x21\xe6\xcb\x4b\xdf\x91\x04\x5d\xe4\x2e\x52\xc6\x07\x19\xb8\x09\x91\xa0\xc0\xcf\x86\xcf\xa8\xb6\x07\xb6\x6f\xdd\xae\x8d\x5e\x0a\xbb\xa2\x97\xa2\x2e\xd1\x96\xad\x5b\xb6\x64\x44\xfd\x53\x58\x72\x1e\x91\x60\x54\x49\x42\x2c\xf1\x85\x9f\x52\xed\xda\xbd\xa5\x7f\xe3\x2e\xea\x26\xf3\x47\x84\x27\x56\xb3\xf4\x41\x31\x6d\x21\x6b\xac\xc7\xe7\x05\xac\xf6\xf4\xe1\x82\xe8\x0f\x1b\xeb\xb6\x94\xef\xda\x98\xfe\xea\xcc\x9d\xcd\x1d\x9b\x3b\xb6\xa6\x07\xb7\x76\xb4\xb6\xef\x1c\xba\x2b\xfc\xee\x88\xa1\xbb\xa2\xef\x8a\x36\xb5\xb5\x6f\xe9\x88\x3d\x18\xef\xd8\xd6\xb1\x63\x67\xdb\xab\xef\x8e\x90\xb7\xa0\x48\x90\xa4\xa2\xa1\x20\xa9\x40\xa3\xd8\xb0\x91\xe1\x1d\xc1\x1f\x36\x12\x65\xf8\x4c\xfc\x77\x33\xe1\x33\x44\x19\x36\x12\xbf\x20\xa2\x8c\xf8\xc9\x6b\x88\x5e\xa5\x7e\x37\x22\x16\x14\x36\xfe\xa0\xba\x19\x91\x5b\xfb\xcb\x49\x88\x58\x96\xb2\xf0\x39\x8d\x58\x23\x88\xfc\x10\x3e\xa9\x5a\xbf\x6d\x43\xed\x06\x35\x6d\x61\x36\x6c\xe8\xea\xd9\xa6\xdb\x21\x3e\x48\x42\x84\xb2\x64\x11\x89\xb0\x07\x69\x48\xb4\x59\x3c\x14\x88\x16\xab\x4e\xd7\x9d\xde\x70\x42\x1b\x35\x45\x0e\x89\x06\xea\x3d\xfb\x3d\x6a\xfa\x0d\x89\xb0\x7b\xa8\x45\x54\xb5\x6d\x63\x4d\x95\x9a\xde\xce\x54\x6d\xec\xee\xdd\xa6\xdb\x43\x2c\x84\xb2\xf4\x1b\xc6\xe3\x29\xf3\xd6\xeb\xa2\xa6\x6b\x87\x44\x1b\x8a\xeb\x0a\x0a\x32\x5c\x1d\xdc\x29\xed\x90\x85\xa9\xae\xe1\xc7\xf5\x91\x20\x0f\x33\x40\x22\x6c\x1f\x0d\x8a\xaa\xb6\xd5\xd4\x54\xab\x87\x2c\xcc\xa9\x8e\x73\x87\x62\xe1\x20\xc2\x07\xda\x20\x4b\x2c\xff\x42\xd1\x42\x86\x8f\x52\xa2\xe2\xa2\x95\x15\xcb\xd4\xcb\x56\xf6\x9d\x28\xd2\x51\x35\xd1\x88\xa2\x36\x62\x46\x11\x99\xea\x40\xbd\xbf\x67\x9d\x9a\x06\xc3\x16\x86\x2c\x60\xa3\x16\x1a\x14\x93\xcf\xd8\xb0\x25\x6a\x19\x41\xb4\x28\x6c\x09\x5b\xf6\xf5\xee\x7c\xb4\xfe\x60\xba\xbc\x92\x0d\x1b\x49\x90\x57\x92\x32\x27\x72\x35\x7c\xf5\x4b\x44\xae\x56\xb3\xf4\xea\xff\xef\x9f\x2c\x92\x22\x96\x5e\x0d\x87\x72\xd9\xbf\x89\xf8\x75\xe8\x16\xd5\xce\xae\x96\xdd\x0d\x9d\x34\x44\x42\x23\xda\x9a\x1a\x5b\x1b\xd5\x8d\x8d\x2d\xcd\x4d\x3a\x7a\x89\x5e\x12\x35\x37\x6d\x6e\x6c\xc8\x18\x87\x02\xc4\x42\xaf\xfe\x8c\xc8\x55\x62\x11\xef\xee\xea\xe8\xda\xa9\xa3\xbf\x86\xfb\x73\xd9\xfe\xf2\x48\x88\x58\xbe\x42\x91\x8e\x70\x48\x35\x91\x5a\x44\x34\xc4\x4c\x24\x16\x11\x7d\x8b\xd9\xbe\x73\x5b\xdb\xf6\x9d\xc4\x1e\x6e\x1a\x31\xb4\x8c\x21\xf6\x68\xd3\xf6\x4d\xdb\x9a\xb7\x6f\x4a\x27\xcb\x4b\x55\x27\xea\x06\x6b\x1e\xd3\xd2\x86\xf0\xb3\xa2\x63\x35\x05\x0f\xdb\xd5\xc3\x21\xc6\x5e\xb0\x6e\x6d\x8d\x8e\x36\x44\x9f\x15\xd5\x38\xea\x96\x16\x67\x44\xcb\xc9\x4e\x74\x96\xd5\x08\xfb\x87\x94\xaa\x03\xb5\xfd\x15\xbb\xb4\xd1\x33\x24\x54\xd9\xe5\x0d\x54\xd4\xa5\x57\xd4\xd6\x96\xfb\x33\x86\x95\x62\x72\x0f\xbb\xab\xb5\xad\x53\x17\x3e\x43\x42\xa2\xbe\x5d\x5d\xfd\x07\x32\x88\x32\xed\x66\x44\x7e\x66\x03\x24\x98\x7a\x72\x31\x22\x17\x58\xc2\x22\x9a\x46\x55\x23\x48\x3a\x1d\x45\xef\xbf\x4c\x97\xab\xc9\x1e\x44\xaa\x88\xf3\x17\x32\x9b\x8c\xd3\x75\xee\x0e\xec\xab\xdd\x45\x59\xa2\x1d\xd1\xd6\xd4\xd0\xda\xa0\x6e\xd8\xda\xb0\x79\x53\x93\x84\xa6\xde\x4a\xc7\xe7\x51\x83\x9a\x8c\x41\xe4\x26\x92\xb4\xdc\xf8\x9d\x2e\xf5\x2d\xaa\xa5\x5a\xb2\x00\x85\x2d\x0e\x1e\x84\xb4\xb0\xa9\x27\x35\xa2\x6f\xc2\x7e\xd5\xde\x9a\x3d\x55\x5a\x6a\x61\x36\xd4\x37\xd4\x6c\xd2\x55\x17\xd4\xda\x7c\x85\x12\x3a\x71\x32\xcd\x9d\x42\xe7\xaa\xa9\x8a\x26\x3f\xf7\xe5\x24\x1d\x61\x09\xfb\x06\xca\x62\xa3\x16\x13\x8a\x5a\xc4\xa9\x6f\x5d\x42\x44\x45\x54\x22\xaa\x26\xa3\xc9\x7d\x77\x90\x07\xd5\x61\x11\x79\x92\x04\xc8\xef\x9f\xe9\xb6\x6d\x0f\xb4\x6e\xcf\x18\x18\x3a\xa3\xfa\x36\xb6\x01\x11\xc9\xa0\xa3\xe9\xfd\x1f\xd0\x65\xea\xa8\x88\x3e\x43\xb7\x52\x62\xd2\x6d\x09\xb4\x6c\xc9\xa8\xee\xde\xd0\xab\x25\x2b\x99\x3d\x9d\xc1\xee\x9d\xba\xbd\xa7\xbb\x4e\x1d\x7c\x5c\x42\x26\x7e\x4b\x72\xbf\x21\x73\xd5\x44\x45\x92\x57\x18\xbe\xd7\xf1\x4b\x0f\xc6\x56\xde\xff\xbf\x1f\x5c\xe6\xf2\xb6\xaa\x14\x84\x95\xe4\xea\x68\x96\x84\x84\xa3\x50\xec\x6d\x13\x8a\x5a\x54\xff\xe0\x3b\x6e\xbc\x29\x87\x95\x37\x8a\xce\x50\x28\xf6\xec\x79\x1e\x3b\x1c\x12\x13\x65\x24\xf4\x3b\x8a\xfe\xd1\x5f\xae\x11\x0e\x12\x0b\x24\x0e\x3e\x3f\x58\x04\x24\x34\x14\x54\x11\x8b\x98\xa4\x20\x6a\x11\x93\xd0\x04\x62\x40\x25\xc4\xc2\x90\xad\x74\x35\x59\x4d\xb7\xd2\xad\x74\x35\x5d\x4d\xb7\x6a\xa9\xa5\xe4\x53\x56\xde\x5f\xc0\x92\x4e\x96\x84\xc8\x05\xb6\x1c\xad\x1a\xc8\x7f\xdc\xaf\xd5\x50\x79\x09\x7b\xd1\x8b\x34\xc2\x5f\xc5\x8f\x1f\x18\x38\xf3\x54\x86\x46\x34\xb8\xa0\x18\x71\x74\x3a\xd5\xd0\x2c\xb5\xd3\xb5\xb3\xdb\xad\x7b\x8d\xea\xa8\xe2\x79\x9a\xa5\xa6\xa3\xe9\xa4\xfb\x17\xd0\x14\xdd\xba\x8d\xae\x1a\xdf\x7a\x49\x65\x4d\x6d\xb5\x2f\x63\xb8\x5a\x3c\x99\xed\xea\x6c\x6d\xdb\xa5\x7d\x97\x68\xc9\xd4\x4b\xc4\x40\x5c\x5f\xd2\x91\xe4\x1e\x35\xb9\x89\x24\xff\xf3\x3c\x11\xe9\x0e\xed\x39\xd0\x7d\x32\x43\x3e\xf2\xc6\x16\x02\xc4\x42\x42\xb1\xa7\x04\x21\x62\x11\x9c\x66\x87\xb4\xaa\xf0\x94\x68\x32\xf9\x39\xfa\x60\xf4\xc1\x68\x32\xfd\x39\x3a\x85\xc2\xbe\x51\xa7\x6f\xd1\xf6\xad\x20\x0b\xd7\x8a\x28\x3c\xf4\xd3\xed\x04\xab\x4b\x66\xa3\x70\x88\xdc\x83\x4a\xc4\x13\x72\x96\x4e\xe7\x74\xf3\xba\x44\x95\xaf\xd6\x5f\x7c\x23\x83\xfc\x93\x3c\x4f\xf6\x92\xef\xc8\x77\xe4\x79\xba\x97\xfe\xf3\xae\xfa\x05\x95\x0b\xb5\xf3\x6a\x45\x1f\x70\x39\x83\x13\xd4\x47\xc5\x7b\xd9\xa3\x62\x82\x7f\xfa\x88\xc0\x43\x3a\xb2\xf0\x58\xdf\xb3\xa2\xd3\x3f\xf5\xfd\x46\x60\x86\xfc\x5a\xed\x51\x8d\x70\x10\x06\x86\x82\x02\x2f\x2b\x8f\xfe\x11\x6b\xf1\xc9\x44\xe0\x65\xc3\xca\xf0\x19\xd5\xcf\x8b\xae\x4c\x3a\xa9\xdd\xd1\xd8\xb0\xad\x51\x6d\x77\xb9\x8b\x75\x77\x12\x49\x3f\x95\x51\x19\x95\xf4\xdf\x99\x51\x7c\xc8\x7d\xbc\x23\xb8\x6d\x47\x87\xf6\xbb\x53\xe7\x7f\xfc\x39\x43\x3e\x52\x23\x9a\x57\xc1\x0b\xe0\xd0\xff\x2b\x01\x24\x98\x46\x38\x2a\x27\xf7\xd1\xc5\x97\xc9\x55\xd6\xdd\x53\x79\xa0\x56\xf7\x48\xcd\x40\xed\xc1\x2a\xc9\x4f\x79\x2f\x51\x31\x95\x67\x50\xf9\x7d\x54\x7c\x4b\x9e\xd6\x57\xe5\xad\xf5\xd4\x48\xfc\xb5\xeb\x2b\xdd\x19\xab\xd9\x13\x1d\xc1\xed\xad\x1d\x5a\xb2\xf8\x32\x91\x93\xfb\x08\x17\x93\xf5\x0a\x5d\x40\x8e\xd0\xe3\x44\x46\xae\xb2\xae\x3d\xeb\x0f\xd6\xe8\xba\x1b\x7b\x36\xed\x69\x7c\x74\xc3\xa3\xd5\x0f\x57\x4a\x48\x0e\x95\xfd\x48\xef\xa7\x6b\x32\xe8\x9a\xdb\xe8\xfd\x34\x87\xca\xb4\xeb\x2a\xdd\xd5\xee\x0d\x1b\x1a\xd7\x6f\xaa\x69\x94\xf8\x6a\x36\xac\x77\x65\x4c\x66\x83\x71\xd9\xbc\xa0\x05\xe4\x08\x79\x85\xcf\xba\x01\xa2\x22\xa9\x44\xc9\xd7\x3c\x81\x13\xe8\x2f\x4f\x61\xfe\x7c\xa5\x7e\x1a\x26\xe7\x91\x8a\x7c\x87\x98\x88\x52\xc8\x13\x52\x19\x6f\x5e\x0b\x5e\x4b\x55\x85\x53\xc3\xca\x68\xaa\x38\xaa\x1c\xea\x50\x91\xf3\x28\xaa\x14\x87\x95\x69\x71\x66\x58\x49\x83\xaa\x61\xe5\xb0\x72\x48\xc9\x90\x67\xe2\x73\xf8\xfb\x99\x2a\x9c\xca\x32\xa9\x23\x47\x10\x25\x33\xa4\x14\xc6\x1a\x3b\x33\x4b\xd9\xa8\x72\x58\xc9\xa4\x8e\xcc\x21\xca\xb0\x92\x49\xfd\x34\x1c\x86\x28\xac\x64\x86\x83\xe4\x3c\x7b\x5d\xc8\x50\x70\x48\x79\x43\xa0\xbc\xbf\xbf\x7c\x7f\x79\x4a\xe0\xc2\x91\xa3\x17\x8e\x90\x94\x23\xdf\xbf\xfa\xfd\x91\xa3\x47\x8e\x1e\xf9\xee\xc2\x77\x17\xf8\x7f\x47\x2e\x7c\xff\xdd\x91\xa3\x47\x2e\xa4\xd6\xfe\x31\x78\x21\x2d\x5c\x12\xff\xf9\x62\x79\x79\xa0\x3c\xf6\x0b\xcf\xb5\x51\x47\x46\x7f\x5f\x60\xbf\xfa\xc2\x36\x55\x17\x5b\x57\x1f\xa8\x6b\x60\xbb\x82\x81\x5d\xea\xef\x3a\xd0\xae\xce\x40\xa7\x9a\x64\x75\xa0\xae\x20\xf9\x27\xaa\x78\x95\xdd\xdf\x17\xe8\x53\x93\x94\xeb\x9f\x5c\xf8\x1f\x4d\xed\x07\xe0\xfa\xe8\x20\x9b\xba\x7c\xb0\xee\xc0\xbe\x40\x7f\xac\x71\x20\x3e\x25\xc8\xcf\xed\xff\x1f\xf3\x5d\x90\x8d\x0f\xb9\xaf\x1b\x95\x38\x03\xce\x06\x36\xb5\x0e\x0c\x1e\x3d\x12\x38\xa2\xbe\xd0\x8d\xe2\xcb\x48\x9d\x7b\x27\x88\x2f\x65\xab\x2a\xfc\xff\xe1\xeb\x4d\xe0\x9b\xa8\xb6\xc7\x71\x6a\x3b\xc9\x38\x3e\xab\x92\x19\x6c\x67\x32\x33\x55\x10\x54\x10\x41\x22\xfa\x50\x04\x51\x41\x65\x97\x80\xec\x94\x7d\x29\x94\xd2\x86\xee\x6d\x9a\x34\xfb\x9e\x74\xda\x74\xdf\xa1\x40\xcb\x56\xaa\xec\x5a\x04\x14\xa9\x0a\xfa\xaa\x3e\xb7\xf7\xf0\xa9\xa8\x0f\x77\xd1\x33\xc9\x49\xf0\xff\x49\x0a\xbe\xef\xf6\xff\x25\x9f\xcf\x2c\xf7\x9e\x7b\xee\xb9\x67\xe6\xde\x39\xe7\xde\x73\xce\xdd\xe8\x94\x37\xc9\x1b\xff\x43\xf7\xc6\xc8\x26\x36\x8e\x3b\xb9\x90\x4a\x86\xfb\x0a\xa9\x18\xb7\xad\x7c\x74\x45\x68\x39\xf1\xca\xc2\xfb\x0f\x3d\xcd\xa1\x4e\xf1\xde\x77\xab\x17\xbe\x22\x86\x56\x44\x97\x13\xad\x39\x35\x9b\x36\xb2\x1b\x4b\x36\xe9\x74\x42\x64\x53\x64\x13\xb1\x61\xef\x8e\x9c\x57\xb9\xbd\x5d\x35\xad\x6d\xa2\xac\x97\xcb\xe0\x45\x2a\x39\x6d\x0b\x1f\xa6\x21\x4c\xc5\xe7\x61\x4e\xfc\x33\x51\xad\x58\x1f\x7e\x99\x29\x6e\xca\xad\xd1\x49\xae\x02\x67\x9e\x39\x1f\x7b\xaf\x6d\x4d\x59\x5f\x96\x9e\xbb\x8e\xbb\xf6\xa0\x42\x3b\x35\x78\x36\x4f\x2c\x6f\x71\x49\x15\x41\x32\x28\xd5\x79\xaa\xb9\x50\x48\x01\xaa\x1d\x7b\x61\xf4\x31\x11\x76\x86\x85\x9a\x63\xe6\x63\xdb\xf6\xa7\xee\xcb\x5e\xd9\xbc\x94\x8b\xba\x15\x85\x85\x16\x6b\xa1\xe8\xf2\xa0\x6a\x7f\x39\xf2\x2b\x67\xa6\x16\xe9\x72\xf2\xac\xf9\xb6\x82\xca\x42\x7b\xa1\x79\xc1\xea\x51\x39\x9b\x8a\xf3\xb6\x1b\x4c\x3a\x73\x51\xa5\xce\x9e\x6b\x59\xba\xe1\xa1\xac\x65\x86\x82\xfc\x12\x4b\x3e\x69\x29\xac\xdc\x6e\xc9\x2f\x7b\x71\xe3\x84\x2d\x8b\x8a\xb2\x72\x0b\xad\x39\x76\xbd\x54\xea\x28\x72\xe4\x58\xf3\xec\x79\x25\x6b\x9d\x2b\xea\x96\x93\x43\x0f\x40\xc2\x84\x9f\xb9\xf0\x83\x8a\xcf\xbf\x78\xfb\x52\xbb\x08\x1d\x61\xa1\xe6\xa8\xe9\x58\xf6\xfe\xd4\x6b\x27\xec\xdf\xf1\x8f\xa2\xf4\x1d\x9f\x1c\xd1\xdf\xad\x26\xbe\x4d\x70\xda\xf9\x44\x75\x92\x4b\x4d\x94\xb9\xf9\x34\xa4\x81\x0e\xd1\x70\x99\x4a\x88\xaf\x92\x5b\x29\xa8\xe4\x63\x4c\x95\xc2\x34\x4a\xca\x6b\x74\x88\x66\x42\x74\x88\x46\xcd\xe3\x14\x68\x22\xb4\x02\xa4\xe9\xdf\xf3\x43\xae\x6a\xfe\x75\xb7\x30\x1d\x24\x45\xef\x96\xfe\xb5\x07\x05\x1c\x05\xa3\x88\x83\x6b\xa7\xec\x5e\xc0\x45\x35\x7d\x54\xa4\x67\xba\xf2\x6e\x8d\xe6\x6e\x31\xa2\x89\xeb\x45\x1a\x98\xc0\x83\x26\xae\x13\x25\xc3\x7d\xdd\x7c\x82\x53\xad\x2c\x4b\x0c\x6b\x43\x57\x99\x1b\x0e\x16\x38\x6e\xc0\x78\xfe\x86\xfb\x05\x8c\x43\x06\x18\x1c\x27\x86\xb4\xb2\x86\x41\x9d\x62\x21\xa8\x89\xb7\xb3\x27\x9e\x7a\x86\x8b\x48\x8a\x67\x26\xce\x7f\x2e\x5b\x5c\x88\x6a\x02\x75\x0a\xe8\xe4\xaf\xd1\x4a\x13\x25\xe8\x78\xc5\x74\x5e\x0c\xd3\x32\x45\x45\xb5\x6a\x2c\x7b\x90\x4a\x43\xfa\xbb\x51\x97\xe4\xb9\x70\xcb\x60\xe7\x21\x5e\x75\x20\xb4\x31\xbc\x96\x51\x65\xbd\x87\xf7\x9c\xc3\x07\x5f\xc5\x51\xa4\x23\x3f\xdf\x91\xcf\xdd\x7b\xaf\xc7\x75\xaf\x18\x79\x35\x3a\x94\x39\xff\xa6\xa7\xea\xbc\xe8\xae\x69\xf2\xd7\x00\x09\x37\xe7\x01\xc9\xb9\x24\x97\x24\xb1\x4d\xce\x46\x47\xa3\xf0\x42\x05\x8e\xf0\xfc\x9d\x3d\xf8\x13\xd4\xee\x38\x2b\xc8\x0b\xec\x44\xdd\x2a\x60\xf0\xe4\x7a\x76\xdd\x02\x53\x96\x59\xc0\x3b\xb7\x12\xb6\x6d\x8e\x6d\xdb\x58\x2f\xdc\x09\x77\x56\xc1\x9d\xa0\x02\x55\x11\xa8\x38\xc9\x55\x21\xb1\x8d\xb6\x46\x5b\xa3\xb0\xb4\xe1\x41\xff\xa6\x1d\x25\x55\x25\xbb\x4d\x75\x8b\x7e\xde\xf0\xfb\xf2\x5f\x49\xd5\x81\x49\xf0\xf4\x54\x98\x36\x19\x9e\xc1\x95\xb2\x2e\xc5\x16\xb0\x06\xac\x01\x72\x81\x62\xb2\x02\xbb\xa2\x1b\xd0\x10\x89\xac\xc4\x41\xf7\x34\x3d\x90\x99\x6a\x7f\x9c\x48\xc6\x3f\x30\xf1\xdb\xd0\xc3\xdf\xcb\xc7\x7f\x19\x0c\x39\xf0\xae\xbc\x1a\x3e\xc4\x0a\xf8\x4a\x25\xcb\xaf\xd6\x32\x39\x67\x25\x98\x7d\xf1\xaa\xeb\xb7\xdf\xd8\xca\x8e\x97\x9d\xbb\x39\x78\x18\xd8\x72\xbc\xff\x1b\xb1\x6b\x41\xc5\xf3\x33\x59\xb4\xe1\xbd\x63\x30\x7f\xc9\x92\xea\xc6\x15\x42\x49\xa8\x94\x51\x5d\x75\xb4\x3a\x63\xff\x5e\x57\x6f\xef\x5f\xee\x51\xc9\x3f\x95\xff\xf4\x13\x1b\x78\xf9\x65\xff\x61\x0e\x1e\x83\x27\x9f\xc5\x17\xb1\x08\x47\xcc\xc5\x55\xeb\xd7\xb9\xfc\xeb\xc5\xc8\xc1\x6b\xb7\x32\x01\x98\x0a\xcf\xd5\xc1\xb4\x2f\xbe\x30\x7f\xc1\xc1\x51\x78\x1b\x14\xf0\x1d\xac\xc3\x89\xc0\xe0\x0b\x2f\x8b\x70\x57\x1f\xa8\xdf\x81\x69\x2c\x54\xa3\x1b\x06\x61\xae\xa0\xba\xba\x7c\x99\x6b\x39\x87\x06\x34\x16\x5a\xd1\x28\x7a\x1f\x25\x54\x72\x97\x15\x46\x98\x6a\x33\xc9\xb6\xa5\xf6\x6b\x73\xb6\xb3\xcf\xfa\x86\x6e\x98\x23\xcc\xdc\xf6\xbc\x63\x7a\x91\xfd\x81\x94\xe4\xa8\xfe\xae\x7f\xd6\xe7\x0e\x76\x86\x25\x55\x3a\x0e\x4e\xf2\x7d\xf1\xaf\xda\x2f\x39\x55\xf3\x85\x8b\x0e\xc7\x45\xd1\x71\xe6\xf5\xfc\x33\x2d\xcd\x9e\x16\xae\xa2\xcb\xdf\xe5\xee\x9a\x59\x39\x33\x30\xab\xc6\xd1\x90\x62\x7d\xe9\x04\x2c\xa9\x3c\xde\x0b\x95\x7d\x10\x3c\x0e\xc1\xca\x33\xbe\xd7\x5b\x4e\x5d\xd8\xd9\x5f\x75\xb1\xad\x62\x57\x60\xb7\x77\x37\x69\xbe\xeb\x2e\xc3\x5d\x1c\x0e\xc1\x3b\x2b\xfd\xc8\x88\xf9\xc3\xde\x30\xbc\x53\xf1\xda\x96\x54\x55\x7a\xb6\xd2\xf3\x18\x66\x5e\xdb\x58\x3a\xcd\xb4\xa1\x6c\x9d\x2e\x73\xf6\xe6\xa9\xe5\xd3\xf3\x48\x55\x73\xe1\x78\x22\xb9\x19\x6f\x03\x6f\x58\x02\x2f\x3e\x00\x34\xde\x0e\x77\x0c\x76\xc2\x2d\x72\x0a\x54\x85\x82\x40\xab\xf6\xa9\x15\x17\x81\x66\x1e\x0b\x4b\x9f\x28\x0e\xd7\x74\xec\xcb\x12\x55\xef\xe0\x60\x18\x9f\xb5\x6f\x85\x33\x6b\x43\x2a\x0e\xc6\xf1\xc4\x86\xac\x9a\xad\x87\xb9\x4f\xae\x49\x8f\x29\x56\x94\x6c\xdd\xb0\x53\x84\xc1\x38\x7e\xe7\x86\xc3\xce\x9d\xfb\x52\x61\x30\x8c\x27\x54\xfb\xf6\xed\x2c\xe9\x58\xc1\xa9\x43\x06\x75\xd2\x1f\xf0\x0e\x45\xaa\x1a\xdf\xf0\x3a\x61\xe9\xf1\x2e\xb2\x79\xd7\xef\xf5\x07\xb8\x7a\xb8\xd3\x53\x5c\x23\x06\x4b\xac\x4f\x15\xb0\x78\xb3\x12\x97\xfb\x63\x82\x12\x3b\xc3\x83\x6d\xdb\x17\x1f\xa1\x60\xaf\x0d\xf6\x3a\x60\xaf\xa0\xda\xe7\x38\xe2\x3d\xe6\x3b\x4c\x56\x7d\xf5\x6f\xeb\x65\x6e\x4f\xab\x6f\x5b\xb3\xe8\xb6\xb7\xc1\x16\xbe\x7b\x1f\xf8\x78\x62\x6d\x96\x4e\x5a\xcd\xe1\x51\xc5\x53\x4f\xbb\x9e\x82\x2f\xf9\xe4\x2d\xbc\x3a\xe9\x5f\xc0\x24\xc4\x5a\xd5\x00\xfe\xc4\x4f\xd5\x84\x1e\xde\xa1\xde\xf0\xb9\x60\xd9\xb1\x3d\x64\x5d\x1b\xe8\x5b\x5e\xba\x41\x40\x6d\xa1\x09\xf5\xab\x8a\x7d\xc5\x25\xec\xb8\x40\x64\x4b\xf6\xbc\x23\x14\x8c\xb7\xc3\x78\x07\x3c\x22\xbc\xa8\x74\xc0\xa8\x81\xda\x53\x6b\xe0\x56\xb8\xdb\x04\xb7\x71\x95\xc7\x5d\xb6\x0a\xb1\x2a\xa6\x08\x1b\x5d\xf6\x76\xd8\xc2\x1f\xdc\x0f\x3e\xbe\xb4\x20\xb7\x64\xbb\x2b\x55\xc2\x06\x6c\x36\x63\x03\x7c\xc9\xab\x93\x82\x6a\x4c\x65\x96\xd5\xa5\x15\x88\xd7\x24\x45\x43\xdd\xef\xcb\x36\x60\x2a\xde\x92\x9b\x25\x14\xeb\xcb\x0a\xf3\xd8\xbc\xaa\xc2\x5a\xbd\x90\xbb\x13\x52\xf1\x96\x7d\xdc\xd1\xa2\xdf\x1b\xc4\xb0\xa4\x28\x28\x4a\x3b\xba\x0f\x52\xe1\x96\xe6\x9d\x42\x6d\xb0\xaa\xbe\x89\x6d\x2a\xab\x2f\x0e\x0a\xcd\x59\x98\x0a\xb7\x6c\xe0\x92\xb7\x50\x11\x1a\x5e\xe0\xd5\x38\xe8\x71\xde\xce\x8f\xa1\x40\x8a\xdd\x85\x07\x3d\xce\xcf\xa1\xc6\xdc\xc8\x2b\x7b\x9c\xb7\x50\x1b\xa9\xeb\xb0\xd7\xe8\xc7\xf9\x30\x1d\x03\x95\x25\xc6\xc9\xc7\xd3\xa2\xf4\xe3\x7c\x88\x8e\x81\xc8\x52\xd2\xd8\xff\xa0\x1b\xb8\xbb\x81\xee\x7a\xde\x9f\xe8\x64\x29\xe9\xd9\xff\x72\x48\x6e\xf6\xc7\x1d\x2c\x12\x41\x02\x1d\x03\x43\x79\xb9\x3f\x69\xe0\xb8\x2f\x86\x43\x4d\x4c\x66\xf6\xc5\xd3\x06\x5f\x3f\x26\xe7\x51\x32\x1d\xd6\x31\x4b\xa9\xb8\xc1\x50\x0f\xf6\x10\x66\xb3\xcd\x58\xce\x96\x7b\x8c\x7e\xb3\x00\xf1\x04\xbf\x64\xab\xe0\x9e\xa0\x74\x3c\x6a\xd7\xf0\x79\x14\x5c\x0d\x69\x99\x01\xd3\xfc\x1e\xe8\x21\xfc\x66\xa3\xa7\x9c\x9b\xca\x8b\x91\xfe\x02\x2a\x6e\xbb\x1d\x4f\x8d\xdb\x6e\xab\x89\xe6\x88\x6e\x0d\xdf\xdc\x9c\x0b\x63\x62\x4a\x15\xb3\xa3\xa8\x55\x57\x19\x37\x01\x29\xe7\x0a\x8b\xcc\xa5\x7a\x31\x32\x22\x32\x9c\x80\xbf\x2a\xef\xa7\xa2\xda\x4a\x3e\xaa\x55\xde\x18\xb5\x85\x90\x76\x38\x0f\x13\x94\xf2\x88\xc8\x08\xa2\x34\x58\x67\x7e\x3b\x36\xd0\xbf\xcf\x83\x36\xac\x1d\x30\xc3\x3b\x14\xd3\x20\x42\x74\x58\x9b\xc9\x87\xa5\x08\xcd\x44\x34\xb2\x26\x22\x45\x24\xd4\x80\x26\x6e\xfb\x84\x5a\x1d\xaf\xbc\x02\xe7\xf8\xb8\x51\xa3\x1a\x27\x2b\x1b\x78\xd8\x4d\xa9\x93\x7a\x65\x25\x0f\x9a\x0c\x66\x21\xe5\x54\x87\x7a\x95\xf3\x28\x35\x4e\xbe\x3e\x45\xba\x25\xc6\x40\x3a\x11\xfe\x18\x92\x26\x27\x50\xbf\x2b\x2e\x5f\x06\x3d\xea\x09\xf9\xe9\xd0\x47\x8c\xd9\x6e\xb6\x58\x84\x48\x77\xa4\x9b\xb0\x58\xcc\x76\x33\x57\x6a\x94\xaa\xfd\x6e\xbf\xcf\x27\xca\xdd\x72\x37\xe1\xf3\xf9\xdd\x7e\xae\x5a\x32\x96\x8a\xf3\x41\xcb\x44\xfb\xa3\xfd\x44\x8c\x28\x65\xa8\x3f\xd4\x4f\x40\x13\xf4\x33\x60\xe5\x51\x0f\xa5\x44\x5b\xce\xa6\x9a\x8d\xdc\xc6\x4d\x25\x39\x3a\x11\x27\xe0\x5f\x65\x4d\x44\x03\x13\x60\x42\x4c\x76\x88\xea\x2d\xd4\x41\x0a\x3e\xa3\x12\x43\x52\x98\x2e\xa2\x62\x02\xab\x89\x02\x82\x9a\x15\x98\xb1\x43\x2b\xc8\x09\xd1\x5a\x62\x45\xd3\xd1\xac\xe3\xdc\xf1\xa3\x3b\x0f\x37\x8b\xf2\xa0\x50\x2d\xb1\xe3\xb5\xc0\xf9\x73\x6c\x72\x3e\x9f\x18\x92\xae\x30\xcf\x53\xe2\xb5\x7e\x65\x48\x92\x7b\x98\x34\x2a\xaa\x77\x82\x84\xfa\xdc\xc1\x4e\x68\xe1\xc3\x92\x6a\x8e\xca\x27\x4b\x32\xcd\xcc\xe1\x05\x55\x73\x7b\x45\x5b\xb0\x49\xa8\x6e\xea\xbd\xd0\xfc\x0e\x59\xe5\xa9\xf4\x55\x70\x15\x95\x96\x32\x8f\xd8\xfc\x6c\xef\xb4\xea\x3c\x32\x98\x57\x91\x93\xcd\xaa\xe6\xc4\xa4\xcd\x9f\xb6\x7c\xbb\xf0\x13\x61\xe1\x27\xb8\x09\xda\x26\x40\x2b\xf9\xb2\x7e\x55\x73\x06\x97\xb1\x3a\x37\xbd\x54\x9c\x80\xad\xb8\x09\xdb\x16\x3e\x46\xaa\xd2\x17\x3d\xb6\xf9\x81\xe1\xac\x6a\x0e\xee\x87\x02\x2c\x80\xfd\x30\x97\x12\x92\x07\x94\xbf\x2b\x61\xcd\xc0\xc3\x93\xa5\x2b\x72\x0f\xd0\x89\xe1\xbf\xc0\x55\x66\xde\x95\x91\xa7\x15\x40\x02\x09\xa3\x70\x14\x01\x7f\x97\x7f\x62\x24\xa3\xa3\xd8\x68\xc4\x5f\xf0\x97\x14\xa3\xb1\xd8\x61\x94\x8c\x92\xab\x56\x92\xe0\x17\xf8\x25\x45\x92\x6a\x5d\x92\x91\xfc\x24\x72\x99\xa9\x2e\xaf\xd2\xfb\x04\xbd\xaf\xd4\x6e\x30\x4c\x9f\x9e\x62\x36\xdb\xca\xcb\x59\x1c\x0c\x0b\xf9\x50\xbf\xa2\xb6\xd6\x6e\xad\x15\xab\xac\x41\x8f\x24\x9d\x38\x91\x52\x51\xe1\xa9\xb4\x57\xd9\x2b\x4d\x92\xd1\x4b\xd6\xaf\x5b\x5d\xb1\x9a\x8b\xf6\xcf\xe5\x47\x86\x35\x4c\x54\x13\xd5\x10\xb1\xd7\x59\x19\xd2\x84\x34\x04\x8c\x81\x31\xcc\x81\x03\xce\x37\xd7\x1d\x88\x89\x21\x29\xeb\x0e\xcc\x74\xae\x5b\xf7\xe0\x83\x29\xb1\x0e\xf1\xf5\xd7\x44\x72\x9a\x13\x68\x0b\xb5\x87\x87\xf5\xa1\x53\x40\x27\xea\x78\xf9\x30\x53\x6d\x1c\x20\xa5\xc4\x6a\x34\x16\x15\x17\x94\xe6\x19\xc9\x32\xb3\xa9\x4c\xcf\xe2\x26\x58\xc8\x43\x92\xc2\xef\x73\xbb\x7d\xe2\xc1\xd6\x23\x4d\x27\xeb\xc9\x5a\x4f\x55\x75\x1d\xdb\x50\x5c\x53\x28\x38\x9d\x4e\xd8\x40\xfd\xe5\x6e\xac\x98\xcb\x83\x21\x64\x65\xe0\x21\x5e\x26\xf8\x94\xa0\xbe\x28\x50\xc8\x95\x1b\xed\xb6\x72\x51\x17\x77\xaf\x40\x2d\x6a\x94\xd1\xb4\x47\xf0\x1c\x36\xe3\x52\x18\x87\xdb\x03\x06\xb1\xdc\x5f\x69\xa9\xe4\xbc\x5e\x97\xcb\x2b\x56\xfb\xa5\x1a\x7b\xcd\x66\x28\x6c\x83\xfb\x3f\xfd\x86\xfc\xf2\x23\x48\x7b\x09\xb2\x38\xd0\xa0\x56\xb1\xad\x4e\xd7\x6a\x10\x6c\x15\x92\xbd\x82\xab\xaf\xf3\x57\x07\x45\x38\x47\xdd\x68\x0a\xd0\xcf\xe7\x0d\xbe\x7e\xa5\xfa\xbb\xea\x88\x8e\x97\x7f\xb9\xce\x5c\xb7\xd5\xea\xb2\x72\xe5\xe5\x36\x93\x49\x9c\x3e\x9d\xb8\xce\xe2\x80\x72\xc0\xa3\x4c\xf5\xf7\xff\xea\x53\xf6\x27\xd3\x1d\x1e\x8f\xc3\x33\xe0\x99\x78\xe2\xc4\x00\xe3\x53\xff\x17\xe7\xa1\x28\x74\x9c\xe9\xec\x74\x9e\xcc\xe8\xc4\x9b\xe0\xa6\x94\x8c\xce\x45\xce\x8c\x8c\x28\x17\xe5\x52\xb0\x0e\xea\x06\x6e\x53\xf1\x26\xbc\x29\x23\xc3\xb9\xa8\x33\x23\x55\x9e\x12\x99\xd2\x99\x71\xd2\xd9\xd9\x99\x1a\x7a\x2d\xf4\x1a\x91\x0c\xdf\xf2\x21\x09\x24\xb8\x8d\x8a\xd0\x32\x0d\xb4\x12\x9e\xa2\xe4\x3b\xf8\xbd\x14\xdc\x49\x89\x28\xa1\x24\x51\x40\x47\xe8\x08\x0d\xb4\xe2\x62\x7c\x69\x04\x69\xe5\x03\x14\x68\x78\x11\x5a\xf8\x1d\x3c\x4c\xe4\xe3\x8e\x15\xef\x50\x63\x79\xa4\xe1\x1c\x85\xb4\xe2\x6f\xd4\x40\x4a\x72\x54\x0f\x3d\x7c\x6c\x34\x0d\xaf\x57\x13\x39\x4c\x0f\x7f\xdd\xf2\xbd\xf9\x7a\xb2\x5a\xf1\x37\x68\xe7\x43\x8b\x21\x97\xef\x89\x9d\xd4\x7c\x1a\xf4\xf0\x90\xac\x56\x28\x12\xd5\x8a\x79\x37\xf2\xa2\x8b\xa3\x8b\x7f\xe2\x53\x43\x8b\xa3\x8b\x89\xf6\xec\x26\x69\x1f\x1b\x87\xc5\x3f\x50\xad\x56\xdc\x9e\xe0\x54\x13\xfa\x44\x35\xb1\x41\xfe\x8d\xd9\x53\xef\xec\xd8\x5c\xaf\x0e\x5f\x0c\xe5\xa6\x6c\xae\xcf\x2e\xde\xc0\xc2\x3f\xf8\x0d\xed\xc5\x7b\xea\x85\xe4\xb5\xd4\x1c\x4a\x4d\x4c\x5e\x4f\x45\xa4\xcf\x29\x59\x52\x4c\xe6\xc5\x6b\xb4\x9a\x28\xbb\x91\xb0\x91\xba\x0e\xf1\x4b\x9c\x0a\xa7\x5a\xa1\x80\x1a\x2a\xba\x18\xf2\xf8\xd0\xe2\xd0\x62\x78\x88\x4f\x8d\x2e\x0e\x2d\x26\x06\x3c\x68\xa2\x8b\x41\x4d\xc5\xda\x31\x27\xd6\xd8\xeb\x70\x3d\x54\x3c\x39\xde\xec\xf8\x4a\xe4\x11\x54\x32\x3d\x94\x3a\x3c\x19\xf2\xf8\x64\x2c\x91\x19\x5e\xad\xb8\x29\xb1\x46\x3e\xc5\x64\x67\x4b\x79\xfb\x38\x68\xe2\xf7\x49\x4d\xed\xd9\x62\x0c\xb3\x81\x4f\x0d\x19\xd4\x78\x2b\xf3\x77\x4a\x1d\x2e\xf3\x50\xc9\x11\xfd\x3d\x6a\xc5\x8c\x04\x18\x1d\x6e\x4e\x54\x27\x55\xa8\x93\xfe\x16\x7b\xb1\x71\x02\x4c\x48\x31\xf0\xd1\xc2\x68\x61\xca\x4f\x7c\x28\x76\x1a\x70\x3b\x8a\x8d\x7e\x29\xf0\x10\x1f\xe9\x90\x3b\x52\xe4\x0e\xb9\x83\xb8\x81\xe1\xab\x70\x73\x62\xf8\xeb\xd0\x88\x58\xf1\x68\x61\xa8\x30\xc5\xc0\xe3\x04\x9c\x90\xf2\x13\x2f\x77\x44\x3a\x52\x22\x1d\x91\x8e\x9f\xf8\x54\x98\x80\x13\x76\x50\xa1\xc2\x50\x21\x91\x8c\x34\xf4\x87\x69\xe8\x4f\x70\x0e\x9c\x13\xd5\x49\xbd\x50\x46\xc5\x5e\x08\x45\x16\x0f\x2d\xbc\x12\xde\xe2\x63\x4f\x59\xb1\x21\xf6\xba\x28\xe1\x59\x5e\x44\x5a\x09\xfd\x7d\x4c\x1a\xb5\x98\xff\x6f\x85\xa2\xd2\x0d\x3f\x4c\x38\x45\xfd\x09\xb4\x96\x52\x27\x95\xc8\x0f\x31\x85\xa6\x42\xbd\x5e\x18\x3b\x96\xd0\xeb\x0b\x61\x17\x8f\xcf\xc1\x73\xf8\x1c\x3e\x47\xe8\xf5\x45\xa6\x42\xae\xb0\x30\x10\xd4\x8b\x63\xbf\x22\xf4\x41\x53\x7d\x3d\x5b\x1f\xa8\x0b\x06\x05\x88\xc3\xc0\x73\xb1\xc4\xba\x58\x62\x7d\x30\x28\x7c\xf5\x15\x11\x0c\xd6\x07\xe0\x0a\x65\xd2\x07\xc5\x01\x00\x78\x4e\x1e\xcc\x07\xea\xb9\xfa\xfa\x58\xda\x57\x63\x89\xa0\x3e\x50\x58\xc8\x16\x9a\x8a\xf4\x7a\x01\x9f\x1b\xa8\x2b\x96\x58\x54\xc8\xca\x77\x42\x2e\x93\x46\x21\x3d\x87\x1a\xec\xbc\xca\xab\x9a\xd5\x44\x52\xe8\x65\x00\x3e\x72\x28\x72\x28\x46\x9c\xa9\x90\x2b\x8a\x53\x83\xd7\xe0\xda\x9f\x8e\x30\xb1\xaa\x2f\x7f\x05\x33\x29\xc8\xc5\x5c\x79\x94\x3c\x12\x66\x52\x97\x63\x15\xf9\x0b\x0b\x59\xf0\xe1\xf8\x33\xbc\xea\x22\xdc\xca\x77\xf3\x20\xf5\x85\xb4\x20\x7d\x49\x85\x69\xd0\x5c\x77\xb7\xd6\xde\xf0\xda\x86\x57\xe3\xb3\x6d\x52\x48\xc3\xe0\xa8\xa1\x73\x27\xa5\x0b\x4b\xb3\x32\x17\xeb\x58\xa7\x12\xde\xe5\xf7\x2b\xbf\xfb\xee\x1f\xef\x75\x0a\xe7\x3a\x76\xee\x78\x95\x3d\x3c\xa7\x67\xfa\xfa\x4d\x7a\x7d\xa1\x90\x5f\x92\x57\xb0\x74\x36\x59\x6e\x36\x58\x8d\x9c\xc9\xe4\xf6\x5a\x44\x4c\xf9\xb1\xb4\xd2\xda\x20\xd5\xa4\xc2\xd0\xcf\x21\xf9\x5d\x78\x84\x83\xc9\xa0\x45\x1e\xa7\x8b\x32\x8d\x5a\x26\x8d\xea\xe6\x41\x07\xfd\xa0\x03\x1a\x74\xa0\xf9\x92\x0a\x4b\xa0\x61\x26\x50\x11\x2d\xbc\x4e\x5d\x81\xfe\x91\xd7\x49\xd2\x6c\xa2\x22\xd2\x15\xb8\xc2\xa3\x46\x89\x74\x98\xfe\x1f\x14\x6b\x62\x14\x6b\x94\x21\x3a\xa2\x61\xd2\x62\x9f\xda\x04\x39\x21\xa6\xc0\xee\x95\x25\x26\x1d\x87\xa1\x02\x15\x38\x2c\x9d\x84\x84\x16\x1e\x13\x94\x38\xec\x65\x54\x80\x22\x1d\x86\x91\x90\x00\xa7\x29\x4c\x50\xbc\x0c\xc3\x40\x01\x0a\x18\xf6\x32\x89\x09\x5e\x1e\x12\x94\x30\x2c\x1d\x14\xa8\x78\x19\x87\x91\x98\xf0\x38\x0f\x09\x0a\xf8\x1a\xb4\xeb\x29\x1c\xaa\x58\x0c\x19\x38\x11\x26\x62\xc6\x09\x12\x86\xb6\xf0\x38\x54\x89\x19\x8b\x71\x22\x4e\x5c\x8c\x19\x24\x0e\x7d\x9c\x87\xa1\x8a\x13\x98\x01\x13\x71\x22\x64\x2c\x26\x71\xa8\x97\x87\xa1\x4a\xc8\x38\x01\x13\x61\xe2\x09\xc8\x20\x61\xe8\x46\xea\x65\x3e\xfc\x99\xbc\x8c\xf9\x99\x47\x1e\xf8\x14\xe0\x81\xff\x99\x4f\xc5\xe1\x30\x1c\x14\x54\x2a\xf2\x18\x4f\x8f\x5f\x0f\xc7\xe1\x97\xf9\x54\xe0\x07\x12\x63\x97\xc3\x71\xf8\x6f\xb1\x5c\x3e\x96\xf8\x1b\x0f\xc3\x61\x38\x01\x19\x30\x9d\x19\x1a\x9f\xec\xae\x08\xad\x8f\xf5\xad\x7b\x7e\x8e\xf5\xac\x0e\xec\x48\xc1\x11\x30\xc2\xc0\xa7\xde\x73\x4f\xac\x5f\x1d\xc3\x63\x3b\x28\x79\x82\x3c\x81\x80\xbb\x1e\x65\x86\x52\x71\xbf\xe3\x8f\xe4\x64\x2a\x51\x4d\xa4\x85\xee\x64\xf0\x35\xb4\xa1\x1d\x7b\x31\xe1\x9e\xae\xd3\x0f\x0b\x21\x4b\xc8\x4c\xbc\x36\xbe\x73\x38\x26\xb0\xd7\x8a\xf0\x55\x66\xde\xe7\x9b\x7e\x86\x44\x16\x4e\x81\x0d\xec\xd0\x0b\x89\xbf\x6c\x9a\xfb\xb9\x20\x6f\x88\x2c\x61\xe4\x89\xf8\x1d\x7c\x1f\x79\x3c\xee\xf4\xfa\x7d\x64\x62\xe4\x09\xf8\x0e\xbf\x87\x6e\x0a\xbe\x97\x9f\x10\x92\xd5\xc4\xf4\xbc\x84\x3e\x35\xd1\x9b\x18\x5f\xb1\xbc\xb0\xfc\x8d\xa7\x84\xa8\x56\x01\x47\xe1\x28\xd1\xd6\x56\xd3\xb5\x97\xdd\x5b\xd2\x95\xd3\x26\x4c\x7e\x9f\x68\xcb\xc9\xb8\x2e\x4f\xe5\x88\x51\x31\x2a\x10\x3a\xc8\xa5\x36\xb5\xea\x84\x90\x18\x4d\x83\xb7\xa9\x0f\x3e\x24\xda\x5a\x6f\x94\x68\x15\xf0\x28\x1c\x23\x42\x5a\xc5\xdf\x8e\xbc\x71\x41\x1c\xa8\xc7\x19\xab\x47\x4d\xf4\xca\xfd\xcc\xde\xd2\x18\x4c\x54\x0c\x89\x37\xe4\xb4\x8c\x18\xde\xc9\x93\x89\x1c\x1d\xfc\x9b\xdf\xd4\xa6\x13\xe0\x28\x1e\x23\xa2\x5a\xc5\x53\xcb\x67\x4f\x8b\x0d\x1d\xd3\x8e\xcc\xfe\x9b\x10\xd2\x2a\xf0\x28\x1e\x25\x72\x62\x75\xb7\xe5\x08\x1f\x4c\x26\x74\x6d\x9d\xf0\x0c\xdf\xda\x26\x86\xe2\xd8\xda\xaa\xbb\xf6\xc6\x67\x43\x27\xe7\x25\xf4\xaa\x15\x43\x12\xd5\x8a\xe9\xf2\x9b\x31\xa9\xf0\x46\x6d\xd5\xb1\x56\x94\xe6\xe8\x62\xad\x10\xe3\x98\x32\x06\x30\xe5\xb4\xc2\x9d\x7c\x5b\xab\x08\xc7\xe0\x28\x11\xd5\x2a\x9f\x7a\x63\xf9\x05\x01\x68\xc5\x85\x37\x8e\xfc\x4d\x0c\x69\x95\x70\x2c\x56\x73\x1c\xa8\x4d\xfc\xe0\x03\xa2\xb5\xad\xa6\x33\x56\xd7\x64\x35\xd1\xf7\x67\x5d\x21\x6d\xac\xae\xc9\x1f\x10\xad\x37\xe4\x4f\x9d\x4e\xc4\x63\x18\x63\xc6\x75\x6b\x9e\x98\x08\x7e\x0c\x8e\x11\xad\xba\x1b\x10\x39\xe2\x93\x93\xaf\xb7\x69\x80\x9f\x84\x2e\x56\xcd\x40\xa3\xd2\x62\x12\x6b\x33\xd2\x6a\xc5\xe4\x04\x27\x6c\x4a\x2c\xe2\xc3\x34\xec\xe7\x23\x92\x2c\x9d\xe3\x51\x42\x9d\x12\x3f\x8d\x8c\x9a\x8b\xdf\xa3\x28\xae\xbc\xab\x0c\x95\x98\xc4\x62\xda\xbb\x38\xfd\x0c\xd2\x42\x95\xae\x2a\xa3\x36\x97\x34\x04\x02\xa6\x1a\xae\x29\x58\xd7\x58\x67\x6d\x70\xd4\x89\xb6\x1e\x7b\x4f\x0f\x2b\x6f\x83\xfd\xff\x90\x9f\x12\x40\x87\x92\xe2\x6f\x94\x2c\xc9\xb1\x8f\xf2\x5a\x2a\x64\x95\x75\x55\x7c\xa8\x25\x74\xb5\x8e\x4a\x46\xa5\x9a\xb8\x9c\x50\xad\x26\x2e\x27\x86\x24\xb9\xbf\x8e\x0a\x59\xc3\x57\xab\xf8\xe4\xd8\x80\x75\x25\xa4\x89\x0d\x58\xff\x4f\xb7\x6a\xa0\xd5\x78\x17\x53\x50\x52\x5c\x08\x7f\x50\xc5\xb5\x0d\x22\xbc\xa0\x6c\xa8\xad\x8d\x3b\xda\xd5\xd7\x14\x17\x88\x76\x18\xcd\x94\x38\x8a\xcb\x0a\x38\x9c\xa9\xc8\x2f\xae\xaa\x11\x0b\x43\x09\x44\xc0\x13\x08\x78\x05\x9f\x5f\xf2\x48\x1c\x64\x29\x24\xc9\x66\xf1\x8b\x01\xab\xc7\x64\x62\x93\x9d\x71\x73\x99\x97\xa8\x04\x70\x01\x7d\x05\xd4\xd0\x0f\xea\x2b\x31\x49\x57\x03\xcf\x32\x1b\x32\x0b\x37\xc4\x86\xa1\x0d\x99\xf5\xfb\xc4\xd3\x4a\x79\x83\x12\xb4\xd0\x8f\x5a\x65\x64\x83\x72\x9e\x32\xb2\x34\x74\x89\x59\x90\xfe\x72\xef\x3a\x7e\x6f\x5b\x41\x69\x55\x4c\x91\x7f\x98\x90\x0d\x57\x98\x05\xe9\xe9\x0b\x04\x5c\xa0\x80\x3b\xe0\x61\xa2\xba\xaa\xad\x61\x2f\xd7\xfb\x72\xfa\x02\x51\xfe\x0b\x4a\x2f\xf0\x91\x19\x0a\xb8\xfd\xc7\x1f\xe1\x76\xb8\x7d\xc4\x8f\x78\xfb\xb3\x33\xb7\x2e\x5e\x23\x22\x8d\x7f\x45\x1a\xfe\x4a\x9c\x58\x33\xb3\xe3\x59\x0e\x6f\x1f\x31\x02\x6f\x87\xb5\x94\x18\x99\x71\x2f\x85\xfd\xc3\xf8\x2b\x11\xcd\x67\x7c\xb8\xff\x49\x4a\xd6\xc0\x76\xaa\xb9\x39\x37\x4c\xc3\x3f\x6d\xbc\x9d\x07\x99\x42\x07\x3e\xf8\x3c\x3e\x82\xcf\x09\x4b\x96\xaf\x58\xb2\x78\x05\xa9\x2f\x2d\x31\x15\x70\xb1\x2f\x61\x43\xa0\x26\x58\x2d\x42\x05\x14\x41\x3e\xdc\x0b\xbf\x73\xb1\xaf\xa7\x2c\xc1\x62\xe6\xd2\x3a\x38\x8a\xc4\x23\x59\x4b\x17\x6a\x05\x14\x31\x25\xf2\xec\xc7\xb8\x72\x1a\x89\x07\x1e\x40\x3f\xe6\xe1\x7b\xec\x06\xcf\x06\xff\x46\xc1\x9b\xb7\x63\x81\x71\x2e\x2e\x9e\x30\x94\xcd\x0d\x98\xa5\x42\x61\xd9\xce\xc6\xcd\xe7\xff\xf5\x06\xa4\x9f\xe4\x0e\x5d\x99\x51\x74\x5c\xdc\x7c\xf9\x87\xa2\x2b\x1c\x8c\x82\x91\x87\x2e\x00\x27\xc2\x1e\x10\x60\x29\x2c\xef\x83\x3e\xb2\xba\x2f\xf0\x56\x1f\x9b\x8c\x7f\xc0\x58\x2a\xee\xd6\x83\x1a\x66\xc0\x75\x72\xc0\xf0\x21\xee\x3e\x89\x52\xf8\x2a\x03\x97\xb1\x0c\x9e\xc2\x5d\xa0\x12\x5c\x0e\x9b\x8b\xd8\x33\x6b\xdf\xe8\x67\xb0\x22\xa2\xdd\x18\x51\xb1\x78\x19\xca\xf0\x29\xd8\x85\x2a\xc1\xe1\xf2\x3a\x88\x8c\x73\x1b\xbe\x79\x17\x2a\x64\xed\x5e\x59\xc5\xc6\x75\x95\x70\x12\x0c\x4b\x90\xb5\x30\x2c\xf1\x10\x2f\xf7\x33\x58\x8f\x93\x70\x17\xce\xc0\xf7\x39\x7c\x1f\x77\xc1\x0c\xa8\xc7\x49\xe2\xbf\x61\x04\x0c\x81\xc1\x30\xe6\x13\x72\xf5\xb4\xdc\x89\x8f\xb3\x87\x79\xd8\x49\xe5\x7e\xb4\xfa\x82\x00\x63\x1e\x83\x21\x38\xf8\xdf\x38\x82\x8c\xae\x91\x69\x66\xdb\xf6\xed\xdb\x50\xf1\xc0\x03\xa8\x80\x65\x54\xe8\xcb\x08\xcd\xb4\x97\xb7\xea\x9b\x05\x78\x0d\x67\xe0\x57\xb0\x12\x81\x43\xc0\xaf\x70\x25\xbe\x86\x33\x44\x7d\x6e\xb9\x2e\x9b\xcd\xae\xd0\x05\x73\x05\x7c\x0d\x66\xc0\x57\xb8\x12\x80\x03\x80\xaf\x20\x1d\x4e\xc3\x0c\x31\xd8\x5c\xd1\xda\xce\x26\xc7\x1e\x9b\xe9\x06\xa5\xf2\xab\xb0\x8c\xc1\xa7\x3f\xc6\x11\xc0\x0d\x85\x87\xff\x17\x75\x38\xf4\x22\x72\x40\x3e\x22\x40\x9f\x7c\xed\x06\x45\xa3\x51\x09\xcb\x28\xf8\x03\xe6\x31\x55\xe6\x4a\x83\x5f\x08\xe6\x3e\x70\xb6\x80\xd3\x1b\xcc\x06\xb3\x38\xff\x7e\xa2\x6a\xce\x2c\xff\x6c\x2e\x42\xe0\x9b\xb8\x02\xcf\xe0\x62\xb1\x34\xcf\x94\x9d\xc3\x66\x07\x72\xaa\xf3\x04\x50\xe2\xb3\xf0\x08\xde\x0f\x0b\xc6\x91\x86\xc2\x8d\xf3\x8b\x58\xbd\xdf\x50\x69\x16\xf4\xcd\xff\x9e\xdb\xc0\x55\x55\xf9\x2b\xfd\xe2\x89\x2f\x61\xbd\x7c\x2b\xac\x95\x6f\x8b\x9d\x53\x5d\x6e\xa7\xcf\xcd\x1e\x88\xcc\x63\x3a\x6c\x1d\x96\x0e\x01\xbb\x22\x0e\x02\x9e\x7c\x1b\x94\x30\x01\x66\xb1\xb2\x16\x69\x66\x87\xa9\xb9\xb4\x45\x98\x08\x0c\xde\x01\x77\xe0\xed\xff\x98\x81\x49\x29\x40\x4c\xfc\xf7\xf0\xf7\x51\x89\x63\xd0\x82\x4e\x7c\x06\x0f\x67\x3f\x89\x29\x29\x70\x0a\x5a\x81\x87\xed\xb0\x50\xec\x3e\xd2\x7d\x62\xcf\x2b\x64\x75\x4b\xa0\x79\x07\x9b\xdc\xdc\x1d\x77\xcb\xb0\xf1\x61\x09\x1e\x8e\x75\xf1\x02\xf8\x83\x2a\xb9\xde\xc5\x6b\x6a\x61\x08\x5f\x5c\x20\xe2\x0b\x4a\xbb\x4c\x31\xa5\x8e\x62\xc3\xf5\x1e\x5e\x59\x2d\x16\xca\xcb\x08\xbf\xa7\x32\xe0\x8b\xf5\x70\xff\xf5\x1e\x6e\x8e\xf5\x70\x8b\xa7\xdc\xcc\x66\xc8\x5b\x99\x9e\xed\xe9\x3b\x96\x72\x4b\xd3\xb7\xad\xda\x2e\x46\x25\x75\xb8\x6c\xfb\x1a\xd7\x92\xd6\x35\xa9\x6b\x5a\x5f\xca\x39\xc2\xcd\xa1\x14\x47\x5e\x6a\xeb\x6e\x15\x5b\xbb\x5d\xc7\xb7\x77\x93\xc9\xf8\x47\x4c\x78\x26\x0a\x13\xd5\x44\xba\x9a\x48\x67\xa6\xf7\xa1\x66\xfa\xc8\x91\xa8\x41\x4d\x4a\xf4\x01\x18\x67\xf0\xe8\xad\xe5\xa6\x54\x59\xc5\x9b\x4c\xb6\x32\x97\x31\xd5\x6d\xf0\x1b\x25\x8b\xec\xc3\xce\x14\x0c\x62\x10\x17\xf4\x12\x2e\xbb\xcd\x69\xe3\xe4\x41\x94\x38\xf2\x7e\xb3\xc9\x6a\x74\x19\x53\x5d\x46\xaf\xb1\xc2\x02\x3e\x9c\x9b\x02\x73\xd1\xe7\x2f\xaf\xb0\x56\x3a\x52\x5d\x4e\xa7\x8b\x83\xa3\xbc\x78\xe5\x4a\x85\xe4\xa9\xb2\x55\xa5\x2e\x80\x05\x10\x84\x20\x74\x46\x7c\xb1\x02\x92\x3d\xd5\xe1\x71\x3b\xdd\x5c\x20\xe0\xf6\xfa\x44\xa0\xaf\x54\x56\xf8\xaa\x6d\xc1\x54\xd4\x84\x66\xc0\xc3\xf0\xf0\x95\x2b\x7d\xa0\x99\xde\x97\x9a\x9c\x66\xa3\xa0\xa7\x0f\xfa\xfb\xa0\x07\x34\x70\xf5\x55\xaa\xb3\xaf\x13\x68\xd0\xf4\x81\x06\xe8\x81\xeb\x4a\x5e\x4e\xa0\x18\xe8\xe2\xfb\x86\xc0\x01\x2a\xaa\x81\xab\x0c\xf4\x43\x0f\xf6\x2b\xfb\x86\x40\x3f\xf4\x63\xbf\x32\xaa\x91\xe9\x18\x84\xac\x8d\xea\x98\x18\x90\x36\x14\x3f\x0f\xdc\x77\xf1\x37\x0a\x0d\xc0\x86\xae\xd6\xf1\xd3\xcb\x28\xe8\xe9\xa7\xfa\x60\x1a\x8f\x3d\xca\x90\x2e\xfa\x27\xd2\x01\x5c\x07\xa8\xbe\x21\xd0\xc5\xa3\x24\xeb\xfe\x27\xf0\xff\x7f\x40\xa6\x66\xa0\xe3\x2e\xd2\x36\x3e\x34\x3a\x7c\x88\x81\xbb\x87\xe3\x9d\xff\xc0\xa9\x1c\xea\x1e\xe5\x41\xa7\x80\x91\x7d\x78\x2b\xde\x7a\x56\x3c\xf4\x6d\xcf\x37\xa7\x3f\x27\xc3\xe1\xe8\x21\x66\x17\x8f\x92\x12\x47\x4e\x87\x5b\xe1\xd6\xb9\xe2\xea\x07\x56\x8d\xd6\x3e\x4c\x62\x35\xcc\x84\xe9\xfb\xe0\x24\x37\x10\x7f\xe6\x2c\x1f\xa6\x93\x06\x20\x3f\xc2\x21\xd8\x8c\x55\x98\x28\xe6\xbc\x90\x3d\x37\x73\x1e\x89\x83\xe6\xcd\x18\x83\xa9\x7f\x56\xf2\x11\x0c\x81\x66\xa8\x82\x44\xb1\xed\x4c\xfb\xd9\x5d\xa7\x49\x18\x74\xfa\xfc\x65\x48\xe5\x40\x8a\x49\xa7\xb5\x25\x67\xf9\xe4\x81\xf9\xb2\x10\xcd\xc0\xef\x91\x7b\xa0\x3b\x52\x1e\x29\x8f\xdc\x83\x87\xf0\x37\x5c\x01\x29\xf8\x1c\xac\xc2\x9b\x85\xa5\xf8\xd8\x53\xb3\x67\x3c\x5d\x5c\x50\x58\xec\xcb\x26\x9d\x4e\xa7\x83\xf5\xe5\x34\x17\xb5\xb8\xbb\x7d\xdd\x81\xfd\x95\xf0\xe4\x61\x18\xf3\x19\xdc\x09\x24\x69\x39\x76\xc2\x76\x82\x93\xcb\xe5\x7b\xa0\x1b\x7e\x17\xe3\x9a\x64\x4c\x0e\xb8\x87\xc7\xe9\xb8\xd1\x98\x9e\x8e\x1b\x25\x98\x2e\xc4\x94\xe7\x7b\xf8\xc8\x28\xf8\x10\x4f\xc8\x73\xe5\xb9\xf0\x21\x9c\x90\x47\x09\xd7\xa4\x90\xb4\x9e\x82\xf2\x81\x68\x37\xfd\x7c\x58\x92\xe9\xff\x7a\x9f\xdc\xdc\x0c\x57\x29\x58\xc9\xb4\xb7\x3b\x7b\xb2\xdb\xa3\x85\xa1\x82\x01\xf5\xae\x20\x25\x3b\xdb\xb9\xaa\x3d\x1b\x26\xe0\x5f\xaf\xab\x78\xf2\x80\x6a\x17\xe9\xd8\x41\xc1\x04\xf8\x2b\x91\xdc\x9c\x01\x57\xa9\xd0\xe6\xeb\x65\x71\x02\xfc\x35\xc5\xc0\x47\x06\x94\x3a\xb9\xc3\xc0\xa7\xe2\x04\xfc\xeb\x00\x9a\xd4\x50\x61\xb4\x20\xae\xdf\x15\x10\xc9\x70\x1f\x7c\x39\x60\xab\x6a\xe7\x3b\x99\x80\xad\xc2\xea\x17\x50\x03\x5a\x22\x60\x36\x78\x8d\x5c\xa4\x5f\xa6\x41\xab\x98\xcc\xd7\x5a\x6a\x0d\x55\x22\xf6\xcb\x34\x51\xa3\x2f\xa8\xc8\xe7\xf2\x0b\xca\x4b\xf4\x22\xf6\x47\x68\xc2\x50\x66\x29\x2e\x86\xf5\x14\x68\x23\x1a\x05\x6a\x94\xd9\x96\x35\x07\x84\xb0\x36\x9b\x0a\xd1\xb2\x66\x3d\x85\x5a\x59\xa3\x00\x8d\xb2\xdd\xd7\xbd\x4e\x88\x07\xc3\x30\x79\xca\xbd\x16\x11\x34\xa8\x25\xca\xfd\x95\x56\x89\x93\xfb\x23\x34\x6a\xa7\x50\xc5\xbe\xe2\xca\x32\x11\x62\x48\x4b\x82\x0d\xc6\x46\xae\xb1\x41\xaa\x09\x8a\x10\xab\xb6\xb2\xca\x57\x5b\xcb\x26\xa7\x01\x52\x60\xa5\xfe\x74\xd4\x57\x65\x85\xe8\x21\x37\x4c\xe5\xae\x9b\xc9\x85\xff\x7b\x8a\xa0\xda\xd5\x1e\x93\x4f\xfe\x13\x77\xc9\xfe\xc9\xb3\xff\x3d\xee\x52\xd1\xe6\xe5\x93\xff\x77\xdc\xa5\xb6\xf2\x56\x4b\xeb\x40\xdc\x25\xd5\x86\x4e\x6f\x7b\x47\x67\xdc\xc8\x00\xbe\xa2\x0e\xf1\x61\x0d\xe8\xa9\xa8\xe6\x25\x0a\x6f\xfb\x69\x38\xdc\x26\xc4\x54\xdc\xb9\x7c\x32\xdc\x17\x1b\x9e\x94\x2f\x26\xaa\x95\x2f\xca\x9f\x32\x47\x16\x56\xad\x17\xae\xf5\x2b\xc6\x21\x35\x7f\xda\x5c\x11\xbf\x8c\xa4\x11\x45\x05\xc5\x39\x39\xec\xf2\x57\xca\xf6\x0b\xe1\x7e\xc5\x17\x40\x9d\xba\x70\x56\x84\x2f\xe5\x34\xa2\xae\xa1\xb6\xad\x8d\xc5\x2b\xf0\x1d\xe8\xa9\x48\xcf\x4b\x54\xb9\xcb\x58\xce\xfa\xfc\xf0\x95\x9c\x46\x5c\xf9\x14\x1e\x7c\x0f\xee\xe0\x42\xfd\x8a\xe4\x6b\x7a\x10\xe3\x73\x2b\x89\x21\x6d\xac\xe2\xfd\xfc\xff\x9a\xaa\xb9\x26\xc1\x58\xfe\xff\x67\x76\x26\x2c\x01\xbd\x91\x6a\x96\x25\x90\x12\x9c\x6a\xe5\x20\xb8\x8d\xba\x26\x01\xad\xbc\x48\x85\x25\xa4\x95\x7f\x4e\xdb\xc0\xee\x81\x39\x5c\x90\x4a\xa8\xc4\x10\x1d\xa2\x19\x94\x22\x31\x5d\x5f\xa6\xc3\x12\x83\xd2\xb5\xd8\x75\xac\x08\xa3\x96\xcb\x74\x3c\xd2\xea\xf0\x20\x35\x39\x48\x11\x1d\xc8\x8e\x0e\x80\x42\x4c\x7a\x55\x63\x19\x48\x71\xab\xb1\xfe\x04\x27\xf4\x24\xda\xf9\xf0\x43\xcc\xd6\xf4\xf5\xeb\x56\x65\x92\x2e\xa3\xd3\x68\x64\x71\x0f\x6e\xc0\xfe\xc8\x10\xbc\x05\x6f\xda\xf7\xfa\x68\xc1\x5e\x57\xef\xa8\xe7\x7e\xf8\x6a\xef\xe9\xbf\x89\x0f\xba\x9f\x38\x97\xf5\x0f\xd2\x5e\x5d\x6d\xaf\xe6\x1a\x6b\x3c\xbe\x06\x71\x64\xe3\x13\x97\x7e\x66\x5d\x4e\x97\x53\xe8\x2c\xee\x32\xec\x73\x90\x2f\x1c\xdc\xd8\xd7\xcf\x1e\xac\x3a\xd0\xb0\x47\xf8\x15\x69\x78\xf0\x51\x78\xca\x48\x5a\x6b\x1d\xf5\x75\x2c\x90\xdf\x7e\x0b\xe4\x1b\xaf\x65\xaf\x3a\x28\x1c\x97\x8e\x34\xf4\xb4\x15\x2d\xde\xb4\x72\xc5\xb6\x97\xfd\x87\xaa\x0e\xd6\x93\x20\xc1\x82\x34\x3e\x34\x1b\xaa\x61\x0b\x14\x27\xa8\x89\x3b\xa0\x1c\xfe\xc2\xcb\xbb\x4e\x53\x30\x07\x9e\xe2\x9b\xdf\xe7\xdf\x94\x5f\xfe\x16\xe8\xb7\xe1\x33\xbe\xef\xfa\xa4\x6b\x58\x13\x17\x45\x43\x5a\xe6\x1e\x3e\x26\x54\xc2\xa7\xf1\x68\x0a\x33\xa8\x98\x9c\x3d\x64\x2d\x7f\x4d\x8a\xbc\xc7\x00\x3d\x27\x36\x6c\x46\x68\xf9\x3d\x46\x4f\x5d\x93\x42\x43\x18\xa0\x65\x3a\x96\x24\xa1\x96\x01\x3a\x94\xa2\xec\x03\x9a\x08\x5d\x44\x41\x81\x94\x32\xc6\x6c\x06\x0e\x53\xea\xf0\x20\xc5\x06\x5e\x8c\xbd\xe2\x87\xf8\x39\x94\x22\x6e\x7c\xda\x1c\xeb\x8c\x21\x7a\xc0\xc2\x25\x76\x4e\x0c\xf5\x87\x25\x66\x0f\x95\xb9\x35\x10\xdc\x26\x04\xb7\x05\xb6\x66\xb2\xf0\x77\xea\xb7\xcf\x3f\xff\x6d\x57\x87\x49\xbf\x43\xd0\xef\x30\x75\xec\x62\xaf\xf0\x42\xe8\xeb\xa8\x96\xd9\x85\x9d\x50\xb7\xee\x80\x30\x10\xda\x4c\xf7\xe0\x83\xba\x6d\xdf\x4e\x68\xce\x15\x47\x8e\x44\x00\x20\x3e\xba\xda\x0b\x34\xa4\xb0\x90\x89\x23\xe1\x7e\xdc\x82\x9f\x5e\xff\x6f\x81\xfb\x71\x24\x64\x42\x0a\xd0\xbd\x1f\x5d\x15\x42\xe3\xa2\xe3\x60\x01\x7f\xba\xaf\xef\x74\xdc\xb0\x57\xc4\x2c\xc8\xba\x72\x85\xc8\x6d\xfe\xf4\x81\x1d\x5c\xeb\xd7\x5f\xb7\x8a\xc9\x70\xdf\x16\xde\x9a\x7b\x34\x17\x24\xb8\x1c\x7b\x9d\xe8\xc1\x16\x0a\x24\xd5\x13\x61\x3a\x44\x17\x51\x21\x29\x22\x31\xcf\xbc\x30\xf7\xe9\x67\xe6\x9e\x79\x0f\x56\x53\x61\x29\xe9\xcf\xbb\x6b\xbc\x2a\xf0\xee\xd9\xb9\xcf\x88\x11\x3a\xf2\x57\xa6\xc6\x50\x5d\xe2\x11\x70\x54\xab\xb1\x43\xbf\xb3\x74\x67\x6a\x47\xf7\xee\xfd\xbb\xba\x49\xaf\xdf\xe3\x0f\xb0\x1d\x48\xc1\xa0\x6d\x6d\x82\xcf\x6c\xf2\x94\x73\x26\x93\xdd\x62\x16\x91\x7a\x28\x27\x98\x5d\xb5\xad\x22\x55\x07\x0f\x10\x35\xf6\x92\xaa\x12\x0e\x67\x29\x4a\xf4\x86\x12\xab\x58\xba\xd8\xa2\xb5\x2c\xca\x32\x66\x1b\xb2\x4b\x51\xf9\x55\x8a\x37\x5e\x30\x13\x93\xf0\xd6\xac\x3c\xd1\x62\xb6\x9b\x4c\xac\xc9\x63\xf2\x9a\x85\xce\xb5\xbb\xd7\x75\xac\x2e\xcd\x2e\xcb\x2e\xdf\x86\x0f\xe6\xa4\x94\xda\x0d\xc5\xa5\x2c\xce\x54\x96\x54\x96\xd6\xd8\x05\x18\x95\x23\x6d\x0d\x66\xd5\x64\xa5\x66\xae\xd9\xb2\x2e\x73\x2d\x69\x35\xdb\xcc\x26\x36\x13\xa8\xb4\x1d\x39\x82\xc5\x1f\xb0\x55\x70\x81\x0a\xb7\xcf\x27\x02\xf5\x65\x9b\xbe\xbd\x6c\x47\x79\x6a\x2b\x3e\x40\x94\xb8\x6b\xca\x6a\x38\x98\xa5\xa8\x09\x56\xd6\x78\xc5\xea\x13\xbe\xd7\x7c\xaf\xec\xac\x68\xaf\x6c\xaf\x06\xe5\xd8\x14\x6b\xbc\xe0\x2e\x48\x82\xe4\x9d\x4d\xa2\xcf\xe7\x0e\x04\xd8\x0a\x9b\xdf\xea\x17\x32\x0e\x6e\x39\xb0\xf5\x50\x75\x7b\x55\x7b\xc5\x0e\x78\xb0\x2d\xa5\xda\x5d\x59\x5b\xcd\x86\x68\xfc\x89\x81\x93\x54\x3a\x05\x5f\x50\xaa\x27\x1a\x56\xfe\x68\x6c\x12\xe0\x55\x5e\x9d\xe4\x4a\x82\x93\x94\x6a\x4a\x3a\xa5\x32\xc2\x17\xd4\x40\x86\x6a\x16\xbc\x1a\x37\x4d\xd7\xf1\x21\x89\x81\xfd\x78\x01\x0a\x22\xa9\x50\xcb\x0b\xc7\x79\x51\xa6\x51\x62\xca\x78\x18\xff\xed\xaf\x30\x0c\x1e\x61\x93\xb7\xf0\x4e\x98\xca\x3b\xbf\x1d\xb0\xbb\x79\x03\xee\x80\x35\x40\xc3\x73\x40\x8f\x06\x7a\x1c\xd0\xaa\x17\x7d\xaa\x17\x9b\xe5\x44\x9e\x79\x80\x12\x54\xc1\xde\x98\x3e\x63\xe6\x45\x0b\x25\xf7\x33\xeb\xb6\x8e\x5d\xea\x10\x9a\x73\x6a\x96\x66\xb0\xaa\xad\x3e\x28\xe2\x3d\x05\xee\xfc\x7c\x16\x93\x1f\x5f\x8e\x84\x80\xb7\x2a\x90\x42\xc5\xbe\x83\x78\x93\xd8\x38\xff\xc1\xfd\xf3\xb8\x8c\x10\xdd\xa9\x50\xbd\xe8\xfb\x18\x6e\x81\x49\x67\x8f\x88\xed\x7b\xda\xf6\x74\xec\xfa\xee\xe7\x4d\xf0\x40\xdf\x5b\x24\xf0\xad\x93\xf1\x66\x11\xa9\x91\xe3\xf1\x66\x16\xae\x2a\xde\x39\x37\x7b\x9a\x08\xb4\x8b\x89\x21\x17\x90\x82\x9b\x51\x10\xf0\x69\xc5\xee\x37\x1b\xde\x78\x97\x7d\xc7\x7a\x76\xf3\x39\xe1\xbb\xc5\x23\x0e\x0c\xe5\x36\x66\xc4\x94\xee\x11\xf7\x75\xe2\x43\xb3\xa7\xaf\x5d\xb5\x21\x7d\xe3\x0a\x52\x15\xec\xdd\xb2\x66\xda\xd8\x35\xdb\x48\xdc\x19\xeb\x63\x51\x1a\x0e\xf1\xd0\xa3\x50\xbd\xd8\xdc\xf1\xe9\x16\xc3\x2e\x71\x19\xa4\x40\xca\x4a\xb8\x9b\x53\xbd\xe8\xfb\x46\xb1\x5f\x01\x8b\xf8\xf6\xc3\xd5\x27\x4f\xb2\xad\xb6\x36\x73\x8b\xd0\x79\xbc\xfe\xcc\x59\x36\xd9\x46\x2d\x18\xe0\x10\xa4\x0d\xd8\x04\xbf\x0e\x77\xc0\x5a\xa0\xe1\x56\xa0\xa7\xfd\xc9\xa5\xd9\xbd\xaa\x0f\x6d\x20\x85\xfb\xe3\x6c\x7a\xe4\x3f\x6c\x8a\xf4\x33\xd3\x66\xcd\x7e\x56\xc0\xab\x0a\xbc\xf9\xca\x78\xa4\x58\xbc\x59\x37\x19\x79\x61\xfa\x5b\x5d\xf0\xc0\xfd\x3f\x6f\xdd\x95\xb3\x27\x7b\x0f\x79\x76\x39\xde\x02\x93\x1e\xe7\x32\x14\xaa\xd9\xbd\x21\xba\x53\x79\xfa\xeb\xfd\x8d\xa7\xc4\x83\x70\x13\x28\xf6\x01\xc5\x01\xad\x50\xcd\x6e\x86\xc4\xf7\x17\xe1\xcd\xa2\x6a\xb6\x2f\xdf\x9e\x6f\x2b\x10\x5e\xd2\xb5\xbe\xb0\x8c\x55\x7d\x68\xcb\x31\xe7\xe8\x73\x85\xbd\x19\x8d\xab\x97\xb2\x19\x25\x4b\x73\x73\x04\xd5\x6c\xdf\x31\x47\xc7\xd8\x75\x2c\xd0\x0e\x46\x35\xbb\xf9\x6c\xe1\x99\x8c\xe3\x82\xbf\xc5\xd3\xd6\xca\xaa\x66\xf7\x9e\x2c\x3d\x99\x7d\x58\x70\xd7\xb8\x6a\x6b\xd8\xbe\xdc\xbe\x35\x27\x05\x9f\x52\x75\xb8\x17\x66\xbb\xf0\x4e\x18\x84\xcf\x73\x98\xa4\xc0\xd1\x78\xc7\xda\x45\x38\x4c\x34\x64\x4e\xd8\xb2\x95\xc3\x9e\x18\x6d\x7f\x32\x72\xa7\xa2\x7b\xdb\x85\xb1\xbb\xd7\xec\x5d\xb1\x2f\xfd\xe0\xea\xd7\x9f\xdf\x8c\x0f\xfd\x78\x1f\xa9\x6b\xeb\x2c\xd9\xcb\xfd\xfa\xe3\x81\xef\x4e\x88\x7b\xde\xf0\xbe\xf1\x36\xfb\x6e\xc1\x1b\x5b\xde\x14\xe0\x69\x45\x8c\x41\x02\x50\x70\x33\x08\x62\x72\xf4\x8f\x47\xd5\x8a\x71\x09\xce\x50\x7f\x62\xa8\x5f\x4d\x5c\x62\x9c\xca\x5c\x9e\x70\x2a\x93\x9b\xd5\xc4\xa0\xb8\xe7\x4c\x78\x32\x83\xd3\x71\x26\x3e\x61\xb3\x09\x91\xbf\x47\x4e\x47\x3e\x92\xcf\x10\x76\x37\xce\x84\x27\x60\x3a\x0b\x7b\xe1\x85\xd7\x41\x03\xf7\xc1\xe3\xf8\xf0\xcc\x57\x85\xb6\xcc\x93\xce\xb6\x5d\xe4\x9b\xaf\xc2\xe3\xf0\x30\xdc\xc7\x81\x06\x5e\x98\x83\x7b\x45\xa0\x87\xfc\xdf\xae\x2e\xb0\x95\x4f\x4e\x83\xed\x7c\x62\x88\xbe\xc2\x1c\x58\x63\xc9\x16\xb0\x47\x11\x5f\x98\xd1\x0e\x2c\xcc\x40\xbf\xe2\x48\xe9\x85\x8e\xa5\x94\x88\xfd\xff\x7d\x99\xf5\x7a\x8e\x18\xd6\xc8\x3d\x5d\x54\xec\x5b\xe7\x09\x3d\xff\x2d\x98\xa0\x2a\xc1\x09\x06\x28\x02\x15\x14\x81\x05\x8a\xc0\x90\x08\x06\x48\x66\x42\xcf\x43\x51\xf4\x79\x65\x6d\x38\x8d\x79\x6e\xd1\xfc\x09\x82\xd3\xa1\x9c\xb8\xe8\xd4\xdb\x17\x5e\x7d\xf5\xe3\x8f\x4f\xbc\x38\xcd\x25\xca\x9f\x5d\x4b\x63\x64\xa5\xf2\xdb\x4d\xe7\x1f\x9d\xbe\x36\x7d\x55\xa1\x60\x2e\x76\xe4\xe6\xb1\x91\x14\x2c\x72\x2a\x3d\xa1\x9b\x6d\x6f\x39\x59\x28\x1a\x6e\x57\x1c\xdf\xfd\xda\x45\xb8\x3d\xa6\xe7\x2b\xee\xc5\x8d\x62\xe4\x6e\x25\x18\xc2\x85\x69\x7c\xe4\x8f\xd8\xb0\x9b\x00\x12\x68\x12\x65\x5d\x48\xc3\xc0\xa7\x94\x20\x6b\x95\xa3\xa8\x19\x94\x10\xd1\x2a\x43\x1a\xbc\xca\xc0\xa3\x78\x3b\x8c\xc1\x14\x41\x96\x94\xed\x7c\x4c\x72\x12\xa3\xb4\xe2\x86\xf4\x24\x46\x24\x25\xa6\xe0\xed\x38\x06\x1f\x1d\xcd\x8b\xf2\xbd\x8a\x0f\x23\x05\x44\x91\xa7\xba\xac\x8e\x73\xba\x9c\xce\xba\xea\xea\x3a\xb7\xf0\x8a\x9c\x47\xc8\x4f\x0e\x18\xa6\x5a\x28\xf8\x9c\xd2\xf1\xf2\x55\x78\x8b\xc2\x7e\x58\xc8\x87\xb4\x1b\xf9\xa8\x76\x2e\x2f\xd3\xea\xa4\xe6\xf5\x54\x44\x9a\x32\xb0\x6e\xf4\x34\x3e\x1d\x4d\x8b\xa6\x4d\xa3\x40\x81\x8a\xf9\x7c\x28\x2d\x94\x16\x4b\x83\x37\x28\x27\xc4\x85\x94\x04\x1d\x0f\x74\x62\xdc\x86\xb8\x8b\x82\xab\x70\x95\xb9\x9f\xc2\x7e\xc5\xf2\xea\x69\x5b\xd7\x75\xfb\xda\x45\xe8\x51\x40\x90\x17\xa3\x5a\x65\x16\x25\x5c\xcf\xe8\xa6\x44\xe8\x1f\xce\x27\xa7\x75\xf3\xd7\xe3\x54\xc8\xfd\x20\xc9\xfd\x40\xd3\x8f\xca\xcb\x43\x77\x31\xb8\xa8\x07\x53\x41\xfd\x3d\x7b\x05\x24\x25\x8e\xed\xc4\xe4\x97\x1e\x14\xc2\xe7\xa1\x83\xb9\x0f\x53\x51\x8d\x8b\x56\x09\x2f\x7d\xdd\x09\xc9\x30\x96\x05\x69\xa4\x22\xde\xb7\xc7\x51\xd8\x73\x45\xb1\x90\x8a\xf4\x2f\xa3\x46\x62\xcf\x75\xef\x39\x5a\x89\x2f\x40\x21\xae\x83\xb7\x8a\x85\x43\x0b\x0f\x6c\x69\x28\x21\x7b\x97\xd4\x2c\x9a\xce\x4e\xcf\x98\x3e\x72\xe4\xc8\xe9\x23\x85\x27\xf8\x50\xff\x23\x7c\x9f\xf2\xca\xc8\xbe\x91\x23\x33\xfa\xfa\xfa\x6a\x4e\xf6\x1e\x17\x1a\x6a\x0e\xec\x3e\xf4\x0a\x09\x6f\xd5\x42\x21\xac\x83\x17\xd8\x64\x68\x39\xff\x4d\x5d\x68\xc9\x41\x0a\x1e\xdc\x01\xe9\x50\x21\xc7\x24\x72\xb9\x0e\xbe\x64\x6c\x36\xb3\xcb\xe2\xb5\x7a\x1d\x7e\xb7\xc7\xe3\xf1\x3b\x7c\x56\xaf\xd5\x65\xb6\xdb\x48\xa7\x72\x6b\x0f\xe3\xb1\x38\xcd\x36\x3b\xe9\x54\xda\xec\x16\xb7\xd5\x67\xf3\x3a\xfd\x1e\xb7\xd7\xed\xb3\x7b\xac\xe4\xaa\x43\x8c\xc3\x66\x75\x5a\x5d\x56\xb7\xdd\xe3\xf6\xb8\x3c\x5e\xa7\xc7\xe1\xb5\xbb\xad\x8e\x58\x81\x66\x1d\x63\xb3\x59\xdc\x36\x8f\xcd\xeb\xf0\x7a\x3c\x6e\xb7\xcf\xe1\xb1\x7a\x6d\x4e\x8b\x3d\x96\xfb\xf9\x64\xc6\x6e\xb5\xd8\xcd\x6e\xb3\xdb\xea\x73\x79\xdd\x5e\x9f\xdb\x6f\xf7\xdb\xbd\x16\x87\x95\x74\x2a\x5f\xb2\x31\x56\x8b\xd5\x6c\xb6\x78\x63\x3f\x7f\xc0\x67\xb5\x0a\x4e\x65\x77\x80\xb1\x5a\x2d\x66\x87\x60\x76\x58\x3c\x0e\xaf\x23\x96\xe5\xf2\xbb\xfc\x76\x57\xac\x4c\x68\x08\xbc\xcb\x60\x2e\x8e\x40\x2d\xae\x98\x26\x6c\xb3\x18\xeb\x6a\xea\x5d\xaf\x5d\x60\x8f\x17\xee\x29\xa8\x13\x40\x51\x0d\x7f\x79\x19\x16\xb1\xa7\xf3\x8e\x6c\xda\x2f\xf8\xaa\x1b\x5e\xdd\xfa\x1e\x99\x5e\x7d\xdf\x73\x4e\x36\xb8\x2a\xdd\xb7\x82\x5b\x91\x6e\xd1\xaf\x12\x9d\xf7\xbd\x9d\x5e\x2a\x6c\x7d\xba\xe1\x45\x5f\x29\xb9\x69\x7d\xde\xf2\x79\x2c\x2e\x84\xbf\xac\x00\x45\xa9\x50\x5c\x5a\xaa\xb3\x6c\xca\x2c\x9d\xac\x5b\xfe\x31\xb9\xf5\xc4\x22\xaf\x93\x5d\x74\x34\xc3\x29\xee\x2d\x6e\x9d\xe3\x64\x77\x3f\x08\x77\xef\x71\xb2\xae\x74\xe7\x6a\x3d\x5b\x62\x2c\xda\xe6\x13\x70\xc5\x05\x1c\x01\x5a\xc8\x65\x61\x2e\x05\xf1\x25\x76\xdc\x2f\x80\x24\xeb\xd2\xe2\xa6\x77\xd7\xdd\x00\xfa\xce\x50\x91\x49\x8a\x27\xb3\x9e\x9e\xff\x68\x4c\x6b\x78\xf4\xe9\x53\xef\x67\x89\x91\x49\x30\x9e\x0a\x2f\x65\x06\xc2\x76\x45\xb4\xb2\x36\xa5\x5a\x5f\xe8\x2f\xe2\x8a\x0a\xe3\xc6\x18\xda\x88\x16\xa6\x53\x20\x45\xb4\xf0\x3a\x2f\x6b\x41\x52\x0e\x84\xf9\x8a\x0d\x0b\xb1\xe1\x42\xc0\x04\xb8\x53\x9d\x74\x40\x4e\xa0\x40\x18\x0b\x69\x3c\xde\x01\xf4\x5d\x40\xab\x93\x8e\x02\xfd\x28\xd0\xaa\x40\x9a\xea\xa1\x34\x35\xa1\x0f\x2d\x66\x70\x17\x2e\xc6\x33\x58\x37\x5a\xc8\x7c\x14\x93\x4c\x0f\xa1\x02\x13\xf7\xa0\x62\xd1\xd2\xed\x8b\x39\xd5\xdc\xb4\x2d\x45\xad\x1d\xe2\xe1\x96\x97\x8e\xb2\x2a\x5f\xf3\xa7\xd9\x1f\x7f\xca\x82\xf9\x5d\xe8\x82\xe5\xf0\x80\xf0\xfa\xe1\x0f\x3a\x2f\xec\x24\xf7\x7e\xfe\xd5\xbe\x6f\x38\x95\x25\x0d\x6e\x01\x62\x09\xdc\xd2\xdd\x2d\x75\x73\x5e\x9f\xd3\xe1\x15\x55\x81\xc9\x52\x91\x2b\x2f\x7f\xb9\x61\xf9\x32\x76\x7e\x55\x56\xe3\x12\xa1\x6e\xb5\x84\xb7\x2d\x65\x81\x76\x33\x7d\x65\x90\xaa\x3b\x2b\xa8\x02\x69\xfa\x4e\x63\xcd\xfe\x23\x95\x47\x8f\xb0\xbf\xae\xfa\x14\x15\xc2\x9a\xb5\x86\xb5\x78\x33\x12\xc7\xf1\x16\x4e\xe5\x98\x8c\x89\xc3\xd6\xad\xba\x47\x54\x05\xd2\x1e\xdf\x3c\x7e\xdd\xb4\x17\x49\x2c\xc3\x69\x1a\x7c\x07\x0f\xb0\x2a\x4b\xda\x5f\xdb\x1f\x9f\xb0\x6c\xfb\xca\xa5\xac\x6a\x6e\xda\xa8\x0f\x1e\xfa\x41\x38\x79\x7c\xd7\x71\x20\x20\x29\x13\x14\xdc\xaf\x70\x9b\xb4\xef\x07\x11\x2e\x42\x12\x14\xc1\xaf\xf0\x39\x9b\x2c\xdf\x46\xe9\x78\x38\xc1\x04\x9c\x01\x5b\x40\x30\x35\x2f\x6e\xc9\xab\x7c\xa1\x73\xee\x9e\x79\x5d\x64\xdd\xb6\x8c\xdd\x9b\x67\x3d\x84\xcf\xcd\xe7\xb2\x36\xb4\xd7\xe4\x88\xf8\xfc\x4f\x38\x18\x06\x0f\x87\xe7\xc9\x92\xb6\xec\x7d\x3b\x4f\xc1\x73\x5f\x9e\x63\xf7\x6c\xe9\x2c\xda\x21\x6c\x3a\xbd\xf9\x6c\xc6\x19\x43\xd3\xf6\x13\xb9\x01\xd2\x63\x32\x39\x4d\xdc\xfa\x67\x8a\x8a\x37\x89\x8b\x73\x33\xe6\x65\x2f\x27\x33\xe6\xe4\xcf\x7e\x96\x1d\x7d\xf0\x91\x3d\xe3\x85\x96\x59\x3b\xe7\xec\xd5\x5e\xc5\x27\x60\x25\xae\x84\x27\xee\x7e\x6d\xe3\xeb\x59\xe7\xb6\x93\x9b\x2f\xfd\x73\xed\x37\xdc\x3b\x6f\x34\x76\xbe\x2e\x1e\x69\x3f\xdd\xd9\x7c\x82\xac\xed\xaa\x7b\x77\xff\x80\x81\xf2\xc0\x60\x17\xbe\x0a\xe7\xf9\xf8\x48\xd4\x3f\x60\x2f\x01\x3d\xa8\x61\xee\xa7\x9c\xd1\x7e\xe5\xbd\xff\x23\xf6\x70\x72\x44\x0f\x7b\xa9\x81\xf1\x2d\xd1\x42\xc1\x79\x5e\x8d\xc3\x95\x91\xc7\xe4\xfb\x1f\xba\xf4\xd0\xf8\xc8\x63\x91\xfb\x09\x75\xd2\xc7\x61\x49\x19\x04\xda\xcd\x97\xf3\x76\x1e\xae\x30\xdb\xf4\x0b\x0d\x39\xc2\x73\x5b\x70\xf0\x92\xa9\xdc\xb3\xb3\x76\xb6\xce\x14\x71\xeb\x27\x68\x04\xe3\x63\xb0\x95\xd4\xbd\x99\x75\xee\x1d\xf6\xe2\x71\x18\xfc\xf6\x6e\xa1\xb2\xed\x95\xe0\x0e\xce\xe7\x77\xda\x7d\x62\x83\xf9\x7d\x1c\x5e\xb7\x95\xac\xca\x6f\xd1\xe9\x56\xe0\x9d\xcf\xaf\x61\xf3\x1a\xb2\x2b\x0b\x84\xf7\x31\xe5\xf2\x18\x48\x79\x92\x34\x34\xb4\x17\x34\x75\xbf\x05\x77\x1e\xe6\x5a\x5b\xb7\x97\x35\x8a\x1d\x45\x30\xfc\x49\x7f\x01\xe9\xb6\x38\xcd\x16\x16\xa4\x50\x43\x1a\x9f\xd6\x9c\x9b\x70\x58\xad\xb8\x37\x51\xad\xd0\x86\x23\xcc\xdc\xec\x19\x05\xcf\x9b\xde\x39\xf4\xca\xf9\xb6\x0f\x66\xae\x7b\x26\x6b\x4a\x09\x79\x7e\xce\x23\xdd\xa3\x39\x9c\x86\xc3\xf0\x1e\x9c\x9a\xed\xc9\xf6\xe5\x88\xd8\x5c\x83\xe5\x40\xe3\x38\x58\x48\x6e\x5d\x52\xa4\x9d\xcd\x62\xd2\x99\x7b\xff\x35\x57\x58\xe0\x5e\x54\x9b\xde\x46\x3a\x9c\x76\x07\x8b\x63\x21\x11\x87\xc0\xbd\x5b\x04\x53\x56\xa6\x35\x93\xcb\xcd\x73\x7b\xf2\xc4\x1e\xa4\xe1\x96\xd1\x70\xb7\x8d\xd4\x60\x22\x8a\x0b\x71\x24\x97\x95\xed\xf2\x6c\x13\x1f\x84\xa1\xf0\xc4\x02\x98\xce\xc9\x97\xe1\x23\xb9\x4c\x9e\x54\xe3\xac\x71\xd4\x88\xe7\x8f\xbe\x76\xe6\x70\x1f\x99\x1c\xd5\x87\x6e\x81\x13\xf0\x39\xec\x4a\x80\x5f\xe0\xf5\xc4\xf0\x3c\x35\x71\x95\xf1\x66\x8d\xae\xc0\x41\x1c\xe6\xe2\x83\x28\xa0\x5f\xc4\x4c\xac\xc0\x13\x50\x11\x75\xc2\xeb\x21\x27\x04\x94\xdd\x70\x82\xc0\xa3\x30\x57\x71\xa9\xf5\x75\xb8\x4d\x80\xb1\x8a\xe4\xb1\x6a\xe2\x63\x75\x78\x04\x3c\x39\xd8\x09\x7b\xa0\xac\x2f\xf4\x38\xec\x51\x1d\xf9\x6f\x0b\x20\xa2\x2a\x1f\xbf\x86\x2c\xec\x81\xb3\xf7\x08\xdd\xa6\x9a\xb6\xa6\x46\xc7\x1b\x7d\xac\x13\x37\x2d\x5b\x0e\xbc\xe0\xdc\xf0\xe5\xa2\x56\xc1\xf9\xcc\xf1\x0f\x1c\x82\xf3\x43\xf3\x4b\x53\x84\x77\x90\x82\xa4\xbd\x87\x9b\x02\x27\x9a\xf6\xb6\x34\x91\x38\xa9\x11\xa7\xbd\x0d\xc7\xd8\x7f\xee\xbe\x70\xe2\x94\x50\xde\xb4\xed\xa3\x97\x7e\x23\xfb\x9a\x60\xc4\xbd\x4e\xb6\xfe\xdc\xdb\xd2\x5b\xdc\x5b\x6f\x1b\x0b\xcf\x89\x4e\x18\xf1\x43\x5f\x9e\xf0\xd2\x5d\xdb\x26\x96\xe7\x91\x27\xe6\xef\x9e\xf6\x08\x8b\xc7\xf1\xd9\xe7\x71\x52\xbe\xd0\x91\xd3\xb6\xec\xa9\x61\x8e\x47\xb3\xd9\xbc\x9a\x9c\xee\x80\x00\x67\x7f\x86\x2c\xe8\x81\xaf\x59\xd5\x91\x91\xbc\x10\xd9\x76\xed\x0b\xc6\x6e\x8d\x0d\xc9\x66\x8f\xcd\xe7\xf6\xba\x3d\x3e\x97\xdf\xee\xb7\x79\x2c\x76\x2b\xb9\x67\x23\x63\xb5\x9a\xdc\x16\x9f\xc5\xef\x08\x78\x3d\x5e\x6f\xc0\xee\xb3\xf8\xcc\x2e\x93\xd5\x46\xee\x5e\xce\x58\x6d\xe5\x1e\x4b\xc0\x12\x70\x56\xf8\x3c\x3e\x6f\x85\xcd\x6b\xf2\x99\x9c\xe5\x16\x2b\xf9\xd2\x4a\xc6\x6a\x31\xba\x4c\x01\x93\xdf\x2e\xf9\xbc\x5e\x9f\xe4\x08\x98\xfc\x66\xb7\xd1\x6a\x25\xcf\x64\x33\x76\xb3\xd1\x56\xee\x31\xba\xcd\x01\xb7\xdf\xed\x97\x3c\x15\x76\xc9\xe6\x37\xd9\xcd\xe4\x79\x0b\x63\x36\x59\x8c\x82\xc1\x61\xf2\x05\x58\x7f\xc0\x27\x09\x92\xab\xc2\x62\x62\xcf\x56\x32\x2e\xb3\xd9\x6c\xb4\x1b\xed\xe5\x5e\x87\xdf\x11\xf0\xfb\x25\xb7\xe4\xaa\xb0\xba\xcc\xe4\x7f\xfc\x3a\x42\x12\x68\xe3\xbe\x29\x87\xf8\xb0\x96\x81\x61\xbc\x80\xda\xa8\xe6\x9f\xbc\xdc\xaf\x5c\xca\x8f\x04\xad\x02\x06\x53\x28\x3d\xc8\xf7\x6d\xa4\xe0\xbe\xb8\xc3\x35\x2d\x93\x31\xe1\x5c\x8a\xbb\xc8\xa8\x15\x97\xe0\x7e\x4a\x1d\xea\xdd\x4c\xa9\x15\x93\x17\x53\x31\xa4\x22\xaf\x0e\xf5\x22\xcd\xa8\x15\x93\x61\x1a\x8f\x3a\x75\xa8\x0c\x74\xd0\x49\xa9\x71\x10\x03\xbb\x29\xf9\xea\x21\x3e\x72\x55\xd9\xc0\xab\xc3\x69\x40\x33\x31\x45\x16\x25\x45\x4c\x7f\x67\x16\xf0\x11\x5a\x11\x1b\xa8\x62\x4a\x79\x26\x2f\x4b\x78\x1b\x53\x08\x1b\x47\xc3\x32\x1c\x05\x23\x71\x24\x8c\xc2\x65\xdf\xe0\xc6\x7a\xd2\xee\x70\xda\xb9\xa2\x22\x73\x59\x99\x58\xa2\x37\x15\x16\xb0\xc8\x29\x37\xb5\x67\x75\xd9\x04\x38\x9b\x09\x16\xb4\xec\xc2\xb3\xe4\x26\xcf\xce\xec\x2e\x0e\x38\x45\x43\x7d\xa0\x26\x28\x06\xab\xfd\xf5\x8e\x06\x52\x96\xec\x4c\x01\xfc\x82\x23\xe0\x33\x74\x83\x0b\x5d\xe0\xc6\xcf\x60\x04\xfe\xd2\x40\x3a\x1c\x4e\x47\x0c\xab\x5e\x2f\x96\xea\x4d\x45\x05\x2c\x0e\x55\x6e\xda\xb1\x75\xaf\x5d\x90\x3f\xda\x28\xaf\x8e\xac\xee\x8a\x7c\x44\x6e\x74\x77\x6c\xdb\xcb\xc1\x50\x45\x43\x5d\xa0\x3a\x28\x56\xc7\xb0\xd6\x93\xc9\x4e\xa0\x21\x09\x34\x90\x04\x97\xe3\x02\x52\xc8\x04\x9a\x2b\xf1\x7b\x3a\x31\xdc\x0e\xfd\x0c\x78\x79\x90\x86\xc4\x8e\x49\xa8\xa9\xe3\xd5\x38\xb9\x8c\x82\xfe\xfe\x38\xc7\xa6\xf1\xd8\xaf\x54\xe3\x43\xb2\x8e\x81\xb1\x72\x2e\x51\xef\x6b\xac\x6e\xe0\x42\xad\x8a\x86\xc6\xd2\x42\x9f\x08\x63\x23\xb9\x04\x4c\x45\x0d\xb3\xb3\xbc\xb5\xbc\x5d\xc0\x45\xf2\x2f\xc4\xbb\xba\x67\x4f\x3c\xc9\x45\x5b\x15\x4f\x3e\xbb\xf8\x19\x9d\x88\x8b\x22\xbf\x10\xe5\xd9\xe5\xba\x2c\x16\xfb\xe3\xf1\x56\xcf\x53\xcd\x61\x0e\x6e\x4d\x80\x87\xa8\x43\x7c\x98\x66\x64\x5a\xf9\x31\x85\x1a\xd4\x62\x3f\xea\x22\x34\x17\xd1\x2d\xa3\x50\xbb\x9e\x87\x64\xc5\x33\xb8\xfd\x73\x9c\x7a\x16\xa7\x7e\x3d\x1e\xaa\xdc\x6f\x42\xf2\x5d\xff\x18\xfb\xe9\xbb\xa0\x9c\xf8\x49\x0f\x88\x70\xcb\x21\xf8\x31\x13\x0e\xe1\x0a\x98\x8a\xf7\x92\xed\x7c\x3c\x9e\x3f\x49\xbd\xf7\xc2\x99\xa7\x45\xa4\x23\x3f\x31\x58\x03\x4b\xd1\x0f\x04\x06\x3a\x48\x68\x55\x42\xa0\x03\xfc\xa0\x84\x1a\x58\x4a\x26\x37\xa3\xf4\x09\x3c\x0d\x34\x26\x41\x52\x4c\x6e\x1e\xbc\x80\x07\xfa\x93\x4f\x40\x0b\x3d\x40\xab\xde\x0e\x0f\x43\x0d\x03\x4b\xa8\xef\x29\x21\x3a\x1a\x7a\x18\x98\x06\xcb\xff\x05\x3b\x41\x66\x81\x81\x64\x98\x07\xb5\x50\x0b\xc9\x38\x0f\x19\x94\xff\x85\x3b\x61\x1a\x2e\x17\xe0\xf9\x21\x78\x2f\xdc\x81\x93\x41\x27\xe7\xb1\xa0\xc5\x71\xb0\x0e\x1b\xba\x05\x08\xf0\x82\x6a\x6f\x4c\x8c\x2c\xf1\x94\xfa\xf4\x22\x36\xac\xc1\x71\xb8\x0e\xb5\xac\xea\xed\x48\x1e\x4e\x46\x1d\xde\x8b\x77\x08\x03\x21\xb1\xb5\x0a\xd5\x3f\xf1\x2e\x50\xa2\x12\x98\x98\xf8\xfe\x01\xbf\x96\x52\x13\xe9\x21\x9a\x01\x01\xb8\xc6\x86\xc0\x4e\x73\x7b\xaa\xa9\x3d\xaf\x29\xdb\x8f\x73\x8e\xa7\xf4\xc2\xac\x40\xbb\x69\x67\x7e\x43\x6a\x41\x63\x56\x20\xdb\x84\xb3\x16\xa4\x2c\x81\x39\xe6\x38\x40\xea\xb6\xc0\x36\x53\x41\x3e\x72\x28\xa6\x20\x07\xe2\x00\x48\x6a\xb6\x39\x2f\xcf\x9c\xbd\x04\xe7\xa4\xe0\xac\xde\xec\x40\x96\xa9\x20\x3f\x35\xbf\xc0\x94\x15\xc8\xee\xc5\x59\x29\x38\x67\x49\x0c\xc0\x94\x9d\x6a\xce\x0e\x64\x35\x16\x80\x80\x5c\x0a\x0a\xc8\xc5\x40\xfc\xd9\xa9\x81\xec\xa6\xbc\x76\x33\xcc\x59\x92\xb2\x00\x67\x99\xe2\x20\xa9\x0d\xf9\x3b\x4d\xed\x01\x98\xd5\x9b\x72\x1c\xe7\xf8\xb3\x1b\xf3\x76\x98\x52\xdb\xcd\x3b\x03\x0d\x8d\xc0\x81\x90\x02\x1c\x0a\x44\x49\x75\x63\x79\x23\xe7\x0f\xb8\x5c\x7e\xb1\x3d\xd0\xd4\xe4\x6f\x3f\x0e\x73\x52\x60\xd6\x82\x76\x53\x0c\x30\x35\xd6\x34\x53\xfb\x02\x98\x95\x02\x73\x8e\xb7\xfb\x9b\x9a\x02\xed\xa9\xfe\x78\xd3\xc8\x64\x18\x15\x57\xbb\x43\x1a\xa0\x9b\x63\xea\xb6\x0a\x4e\x02\xad\xda\x7a\x40\x4e\xe4\x19\xd5\xfe\x8b\xf3\x29\x55\xde\x01\x1d\x2f\xf7\x33\x53\xe7\xcc\x99\x2a\xe0\x3f\x15\x03\xf3\x11\x50\xc4\xab\xb6\x1e\xb8\x3e\x1f\xf1\x97\x27\x96\x62\x92\x80\x0b\x70\x12\xd0\xf8\xd4\xc0\x34\xc4\x6f\xef\x7d\xd5\xdf\x27\xf6\x1c\x3d\x78\xb4\xab\xb7\xba\x39\xd8\x12\x6c\x21\x5b\xab\x5e\x01\xb2\x83\x53\xe5\x1d\xb8\xf4\x41\xc6\x48\x11\xe9\x91\xcf\xcf\x60\xe5\xfe\xff\xcc\x43\xfc\x39\x09\x11\xa1\x14\xb5\x3d\x81\x97\x0f\xb3\x30\x11\x99\x7f\xe1\x38\x41\xb5\xff\x22\xb2\xe9\x38\x69\xf4\x5c\x71\xcb\xd2\x8d\xab\xd6\xaf\x22\x37\x65\x4e\x7b\x78\x49\x4c\x69\xde\xc0\x8b\xaa\xad\x07\x6e\xcc\x3e\x9c\xff\x61\xdd\xf6\x73\xe2\xda\x5f\x7f\xdb\x0c\x49\x1c\x2c\xe2\x9b\x0f\x54\x1f\xf2\xbc\x44\xc2\x44\x05\xa4\x01\x09\x37\x43\x9a\x18\x6f\xf2\x49\x50\x8d\x06\x7a\x1a\x30\xab\x07\xda\x1e\xf7\x82\xca\x7c\x54\x4d\xa4\x03\xcd\xa8\xf6\x2d\xc4\xa7\xf0\x09\xa4\x71\x09\x87\x89\x53\x4e\x00\x25\xaa\x32\x8f\x34\xba\x1a\x3d\x0d\xc2\xca\x56\xdd\x99\xa3\x6c\x9b\xbf\x2d\xd8\x2c\xa8\xb6\x3e\xba\xb1\x33\xff\xd0\x31\xb6\xb3\xe6\x58\x73\x5b\x8c\x39\x53\xe7\xbc\x7e\xf1\xc2\xb9\x37\xde\x11\xe5\x7e\x85\x2a\xf7\xd1\xf3\x23\xdf\x02\x9a\xbd\xf2\x41\xe7\xa5\x9d\x27\x91\xd0\x05\x85\xa0\x2e\xa8\xab\xd9\xde\xb5\xe0\xe0\xb2\x9e\x65\xe4\x94\xbe\xf7\xc6\xfe\xc6\x75\x46\x69\x05\x48\x7d\xdf\xc7\x78\x0c\x87\x29\xd5\xd6\x47\xb1\x47\xb1\x64\xda\xe7\x5d\x99\xe2\xfa\x9e\x8d\x3d\x5b\x8e\x91\xdf\xcc\x4d\x87\x49\xc8\x72\x38\x0e\x19\x0d\x4e\x5c\x11\x48\xaf\x5d\x25\x46\x28\x05\x0a\x48\xe1\xcd\x28\x60\x1a\x90\x18\x6b\x19\x4c\x54\x78\x56\x56\xaf\x6e\x5e\x47\xaa\x32\x8f\xd8\x4b\x1c\xc5\x25\xec\xf4\xe6\xe9\x87\x16\x09\xaa\x7d\x0b\x1d\x16\x02\xe7\x39\x80\x1d\x0a\x33\x38\xb8\xe9\x6a\xe7\x81\x9f\x45\x55\xe6\xa3\x2d\xe7\x7e\x38\x70\x9e\x8b\xe9\x7f\x24\x25\x26\xdb\xa8\xff\xf5\x2a\x4c\xa1\x54\x5f\xa7\xdb\xf9\xe9\xdf\xf3\x21\x1f\xa3\xfa\x7a\x0e\x2e\x40\x1a\x27\xe1\x53\x6c\x46\x94\xee\x54\xfe\x36\xf6\xbd\x29\x7d\xc2\xb2\x9e\x65\x07\x17\x74\xe5\x56\x6f\x0f\x6e\x0f\x92\xba\x2a\x24\x5f\xe9\x60\x2f\x75\x7e\x70\x45\x50\x5d\xbe\x04\xf4\x5b\x23\xcf\x73\x72\xbf\xf2\x9d\x37\xce\x5d\x10\x54\x3f\xa6\x5f\x7c\x7d\xce\x54\x11\xff\xa9\x54\x41\x7a\x73\xdb\xb1\x9a\x4e\xee\xd8\xa1\xfc\x8d\x9d\x62\xb0\xb9\xcd\xdf\xc6\xa9\xbe\x9e\x73\xf4\x8c\x6e\x65\xab\xe8\x69\x68\x74\x37\x72\x70\xeb\xd1\x49\x48\x88\x40\xfb\x18\x98\x89\x89\xc0\xe0\x5c\xbb\xd0\xbd\x68\x7a\xf3\x74\xae\xa4\xd8\x61\x2f\x11\x55\x30\x67\x5d\xf3\xea\xea\x95\x1e\x12\x26\x2a\x21\x0d\x6f\x06\x12\xd3\x50\xc0\x9b\x91\x8a\xbf\x45\xca\xda\x55\xe9\x81\x15\x1c\x4e\xd4\xc4\xdd\x6f\x58\x98\x94\xfe\xcd\x5c\xf1\xd8\x96\x9e\x8d\x3d\xeb\x49\xd5\x8f\xe9\x5d\x99\x9f\x4f\x5b\xc2\x62\x8f\x32\x46\xe9\x31\x4a\x08\xd1\x71\x46\x40\x8f\xf2\xfc\x81\x1f\x5a\xce\x09\x07\x7f\xdd\xf3\x1b\x24\xb1\x31\xc6\xfc\x1f\x2f\xcc\x14\x4a\xe5\x1d\xe8\x1b\x98\xb8\x78\x0a\x52\x82\x2a\xb8\x2b\x3f\xdf\xe5\x29\x10\x57\xea\x5e\xd0\x2d\xe3\x72\x72\xfc\xc1\x5c\x71\x63\xc6\xea\xfc\xa5\xdc\xa6\x15\xb5\x4d\xdb\xe2\xed\xde\x7f\x20\xd6\x93\xa6\xcd\x3e\xf7\x8e\x20\xf7\x2b\x67\x3c\x3f\x12\x69\x6e\x64\xc6\x07\x97\x76\x02\x71\xb2\x35\x28\xb6\x06\x5b\x83\x2d\x35\xbd\x5d\x47\x0f\x1e\xed\x21\xfb\xfb\xbe\x7a\xef\x37\xb6\x53\xa9\xba\x70\x20\x44\x67\x28\x54\xde\x2c\x7c\x0a\x68\x7c\x02\x97\xb0\x48\x87\x24\x06\x8c\xfc\xd7\xbc\x2a\xb8\x0b\x9e\xe5\x45\x95\xf7\x00\x48\x51\x1f\x03\x37\x65\x5c\x5d\xf7\xb3\xb0\xfd\xdc\xba\x1f\xce\xb3\xd0\x13\xdf\x86\x25\xb8\x2b\x4a\xc7\x3a\x0a\xf6\x28\x97\x3c\x3c\x6d\x53\xa6\xb0\x6a\xfd\xaa\x8d\x4b\xb7\x90\xa3\xe7\xe2\xa4\x74\x64\x59\x1c\xf7\x05\x32\xf0\xf8\x4b\xc7\xfc\x75\xdd\x31\xb6\xa1\x00\x37\x23\x05\x02\xa4\xc1\xcd\x40\x42\x9a\xa0\xf2\x66\xc1\x44\x65\xb7\xf7\x68\xcd\xde\x46\x52\x75\xe1\x80\xbd\xa6\xd6\x51\xc3\xf5\xf5\x35\x1f\x3a\x29\xfa\x1c\x84\x6a\xff\x01\x98\xe7\xf8\x15\x58\x98\xc1\x26\x23\x7d\x95\x1f\xec\x04\x6f\xb8\x06\x24\xd5\xb3\x76\x1e\xca\xa8\x88\x43\x01\x73\x71\x2e\xa1\x3a\x12\xd4\xfb\x8b\x0a\x59\xd5\xb3\xf0\x32\x35\x66\x0c\xf4\x51\x78\x0d\xae\x8d\xb9\x0c\x37\xf1\x97\x2f\xc3\x35\xb8\x06\xa3\xa8\xeb\xf6\x83\xd7\x8d\x0a\x63\xa5\x64\x87\x42\x75\x04\x02\x54\x5f\xdc\x9e\xf0\x2a\x2f\xdf\x4e\x85\x6b\xc0\xab\x5a\xa8\x26\x88\x10\x0d\xc0\x8f\x19\x83\xd7\xf0\x1a\xa1\x3a\x32\x10\xf5\x59\xb5\x70\x20\xee\xf3\x98\xcb\x7f\x5a\x34\xc6\xcd\x1c\xe7\xc2\x5c\x22\x46\xc9\x5b\xbc\xec\x50\xe0\x5c\x98\x3b\x50\xed\xac\x78\x78\x8e\xcb\x63\x88\x01\xda\xc0\x3b\x44\x75\x24\x8d\xea\xe6\x63\x75\xc4\x4d\x17\x7d\x6a\x22\x29\xc4\xc4\xeb\x21\xf4\xfa\x22\xd8\xc5\xe3\x00\x2a\x65\x16\x2f\x3b\x94\x31\x1a\xa1\x8d\x82\x9b\xf8\x58\x0b\x2e\x5f\x86\x51\x54\x0c\xe1\x0d\x74\x3e\xc7\x19\x5e\xf5\x0d\xdc\xca\x23\x3d\xc0\x93\x38\xce\x39\x31\x9c\x2a\x00\x3e\x46\xf9\x98\x31\xd0\x16\xe7\xc4\x00\x41\x33\x29\x18\x68\xf6\x36\x3e\xe2\x50\xc6\xc8\x1e\x60\xcb\x00\x3a\xd7\x7f\xd0\x09\x60\x7b\x0d\xee\x01\x95\x5d\x02\xbe\x16\x06\xd7\x36\x34\xd6\xd7\x1e\x85\xb9\xa8\x81\x84\xd1\x35\xce\x1d\xbf\xd7\xbb\x5a\xf6\xc2\xf0\xc1\x4e\x38\x0e\xcf\x74\x7d\xfc\x99\xb1\xe5\x58\xc7\x0e\xe9\x78\x53\xc5\xab\xb9\x4d\x40\x4a\xaa\xcf\x46\xec\x2d\xfb\x7f\xda\x22\xa9\xfe\x39\x62\x6f\x19\xec\x8c\x34\x30\x55\x81\x06\xa9\xc6\x5a\x65\x93\xac\xa5\x46\x52\xf5\xfd\x88\xbd\x65\x66\xab\xd1\x6b\xb2\x4b\xf6\x6a\xab\xd5\xb8\xa3\x78\x63\x41\xa1\x9b\xac\x70\x64\x17\xbb\x58\xa3\x45\xef\x34\x19\xcb\xcb\xaa\xf2\x8b\xbd\xe6\x52\x5d\xc0\x50\x52\xa5\xdf\x5e\x58\x56\x6b\xb0\xfa\xca\x0c\x66\xaf\xd9\x65\x36\x59\xdd\xae\xa0\xc1\xe3\x20\x2d\x76\xab\xd5\xc2\xf9\x4a\xcb\x4a\x8c\xe5\x86\x72\x5d\xb9\xcd\x5e\x50\xa8\xcf\xee\x34\x91\x2e\xe7\x26\x87\x4b\x74\xeb\x7d\x1b\x72\xab\x0d\x3e\x73\x87\xad\xca\x16\x74\x38\xcb\x83\xa5\xc5\xf6\xaa\xb2\x00\x19\xa7\xbc\xcc\x5f\x64\x37\xfb\x8b\xcb\xca\x3c\xb6\x7a\x6b\x79\x85\xde\x61\xb3\x18\x8c\xee\x72\x7f\x69\xe5\xd6\xc2\xe2\x00\xe9\xf2\x5a\xed\x1e\xd1\xa6\x37\x05\xcc\xd6\x01\x8a\x4d\x16\xb3\xc1\x6c\xa9\xce\x2e\xc9\x71\x65\x91\x79\xd5\x1b\x1a\xcb\x04\xc9\xb2\xdb\x2e\x79\x6b\xfc\xf6\x2a\x5f\xd0\x57\xed\xf7\xd7\xba\x5e\x76\x6f\xda\x60\x29\xb0\x95\x3a\x8a\xed\x7a\xd2\xee\xf3\xb9\x7c\x9c\xd7\xe3\xf3\xb0\x7e\x43\x93\xcd\x1f\x0c\xe8\x6b\x8c\xee\x12\xb2\xc4\x5d\x5d\x9c\xcf\x95\xd4\x6d\xb5\xb8\xc5\xaa\xbc\x86\xf2\xa6\x4a\xb2\xdc\xb6\xbd\xcc\x2e\x18\xec\xf9\xcd\xde\x2a\x87\xd5\x66\xb3\xd9\x0d\xc1\x42\xbf\x31\x68\xf7\x64\xf5\xf8\xdd\x25\xe6\xad\x95\xa5\x81\xdc\x2a\xdb\xae\x6d\xd6\x02\x9b\xc5\x94\x5b\x41\x96\xf8\xf4\x95\x25\x81\x22\x69\xab\x64\x6e\x32\xd7\xb9\x1b\x8d\xb5\x64\xa5\xb9\xa0\xa9\x94\x0b\xea\x76\x7b\x6c\x62\x59\xf5\xea\x7d\x15\x4d\x6e\xcf\xf6\x0a\xab\xcb\x6b\x70\x95\xf9\x8c\x3e\x83\xdf\xe8\x37\x54\x15\xd4\x6e\xb7\x6f\x2f\xb5\x7a\x1b\xad\x15\xa6\xea\x7c\xa7\xa5\x86\x74\xbb\x5c\x4e\xb7\xcb\x55\x9f\x5d\xe3\x0d\x96\x54\x39\x9b\x0d\x35\xc6\xea\x62\x7f\xa9\x64\xf1\xac\x3f\x5a\xed\xc9\xb3\x18\x8e\x79\x82\xa4\xd3\xee\x74\xb1\xde\xa0\xe9\xcd\x3a\x57\x99\xc3\xb6\xd3\xe3\x73\x7b\x6b\x8b\x5d\x76\xbf\xc7\x5f\x61\x0f\xd8\x2a\xca\x02\x26\xbf\xcd\xbd\x7a\x87\xc3\xe1\x0d\x38\x02\x66\x1f\x99\x5f\x5c\xb9\xcb\xe0\xb1\xba\xac\x1e\xab\xf7\xec\xd7\x9f\xfe\xfd\x4a\x2f\xe9\xf2\x57\x38\x2b\xb8\x06\x7b\x65\x71\xb5\xd1\xed\xb3\x56\xd8\x7c\x9e\x8a\xa0\x3b\xe0\x96\x5c\xd5\xee\x0a\xab\x59\x32\x55\x98\x2a\x1c\x0e\x9b\xdd\x61\x2f\x93\x72\xf5\x06\x2b\x59\x6e\x35\x59\xca\x6d\x16\xbb\xcd\x69\x75\xc5\x9e\xd9\x67\x65\xbb\xeb\xf6\xd4\x74\x55\xf9\xad\x7e\x93\x64\x32\xfb\x9c\x3a\xb7\x95\xac\x2a\x6e\xab\xac\x75\x1c\x31\x1b\xff\x32\x2c\x60\x70\x16\x4b\x46\x49\x2a\xad\xf4\x4b\x6e\x6f\x83\xcf\xef\x09\xf8\xf4\x01\x9b\xdb\xe0\x5f\xe3\x69\x6c\x0d\x54\xb4\x5b\x2b\x2c\xa4\xea\xb3\x91\xaf\x94\x55\x99\x83\x65\xc5\x86\x80\xa3\xcb\x68\x29\x25\xfd\x1e\x9f\x54\xc1\x49\x0e\x77\xae\xd7\x52\x93\xdd\x76\xd2\x6b\x2f\x08\xec\x95\x24\x5b\xc0\x56\x95\x53\x1a\xab\xd8\xba\xaf\xac\xca\xe0\xda\x9e\xe7\x2a\x71\x15\x35\x96\x16\x93\xaa\xcf\xa6\xed\x2d\x33\x1a\xac\xc5\x46\x63\x49\x49\xbe\xab\xd0\x1d\x70\x6c\xd7\xd9\xad\x66\x93\xb5\xdc\x5e\x6e\x37\xb8\xcb\x2c\x86\x7a\x9f\xb4\xd9\xe4\x68\xf6\xd4\x3b\x9b\x4c\x03\x18\x6a\x2c\xcd\x66\x7f\xb1\xd7\xdf\x68\xf3\xdb\x83\x66\x57\xa9\xa7\xcc\x5b\x5c\x9d\x5d\x5f\xe1\x71\xb7\x54\x96\xfb\x49\xd5\x67\x77\xee\x2b\x2b\x0f\x18\x1b\x2a\x2a\x2b\xaa\x1a\x3d\xbe\x1a\xb2\xa2\x35\xc3\x56\xcf\x56\x56\x7b\x1c\x41\xa1\xb2\xb8\x29\x18\x10\x2a\xfd\xc7\x0d\x92\x59\x32\x77\x94\xbb\x8d\x03\xea\x4c\xbc\x83\x55\x98\x02\xc5\x25\x56\xc9\xbd\xc3\x50\x60\xf6\x7b\x7c\x76\xbf\x37\xe0\xf5\x06\x24\x8b\xdb\x51\xd5\xe2\x77\x48\x0e\x77\xa9\xd7\xec\x35\x56\xd9\xbc\x46\x32\x50\x68\x2b\x6a\x35\x07\xec\x8d\x55\x8e\x62\xd2\xeb\x75\x7b\x5c\xac\xab\xc4\x5f\x54\xef\x26\x9d\xce\x7c\xbb\x4d\x30\x1b\x8b\xdd\x46\x8b\xcd\x91\x93\xeb\xb1\x95\xd6\xe6\x3a\x0b\xad\x05\xb6\x42\x7b\xa1\xa9\xdc\x5a\x6e\x35\x9b\x6c\x56\x4b\x81\xc5\x51\xe9\xf6\x55\x55\xf8\x07\xfa\x10\x3e\x72\x2d\x81\x71\xf8\x1c\x95\x2e\xd6\x51\x57\x5f\xe5\xa8\x2d\xf3\xd8\xaa\xdc\x41\x77\x7d\x6d\x30\x58\x15\xac\xf2\xb4\xda\x6a\x2c\x6d\xce\x76\x6b\x9b\xcb\x5c\xef\xf6\x94\x7b\x03\x6e\xc9\x17\x20\xbd\xfe\x80\xdb\xef\xab\xf4\x37\xb7\x06\x4b\x2a\xf5\xd9\xa5\xd5\x65\xde\x0a\x6b\xb0\xa2\xa2\xae\xa1\x2a\xaf\xce\x52\x6f\xf1\x9b\xab\xcb\xac\xde\xa6\x80\xdb\x45\x36\x7a\x2b\xca\xaa\x0d\x35\x86\x16\x93\x3d\xaf\xd2\xee\xb7\x55\xd8\x2a\xac\x55\x6e\xbf\xf9\xc1\xfb\x31\x79\x1a\xf2\x39\x64\x72\x1a\xea\xd5\x8a\x8c\x84\x66\xb5\x62\x63\xa2\x4c\xf7\x65\x52\xa1\x14\xf9\x51\x06\xef\x7c\xf5\xee\xab\x2f\xc2\x9d\xd1\x89\xd1\x89\x29\x37\x2c\x3d\x7f\xc3\x41\xf0\x36\x15\x7a\x22\xf4\x04\x11\x4a\x96\xa7\x31\x4d\xfa\xda\xbc\x3c\x2c\xc6\xe1\xf9\x9b\x04\x9c\xff\x3b\x01\x3a\x25\x1c\x85\x89\x84\xe4\x0f\x54\x55\xb1\x41\xb3\x64\x08\x08\x3d\xb3\x46\xb5\x4c\xe1\x96\x50\x87\x79\x98\x0b\x93\xe0\x36\x98\x7a\x5e\xac\xea\x0c\xf6\x74\xb1\xc9\xff\x25\xf8\xc3\x8d\x7f\x84\x8a\xbb\x70\x85\xa5\x98\x92\x4a\x87\x68\xa4\x95\xd7\x24\x59\x02\x23\x15\xa1\x65\xe9\xc6\x92\x33\xd0\xd1\x7e\xe6\x28\x1f\x92\x92\xae\x1f\x92\xf1\x0f\xa4\x75\x3c\x74\xf3\x6a\xa2\x48\x9d\xf4\xd1\xf5\x60\x26\x6a\x1c\xa4\x80\x4b\xbc\x6c\x88\x18\x52\x22\x85\x4a\xd0\xf0\x02\xb4\xf0\xd7\x5d\xc7\x42\x85\x4a\xd9\x20\x1b\x6e\x04\x35\x69\x6e\xce\x1d\x88\x93\x96\x00\xc7\xa9\x8f\x78\x5a\x1d\xa2\xe1\x3c\x0f\xb4\x2c\x21\xad\x0c\xd1\x51\x9a\x89\x6a\x50\x33\x85\x12\xb0\xff\x2b\x0a\x34\x51\x4d\x44\x77\x8a\x8a\x4a\xb2\x8e\x41\xa9\x9b\x57\x84\x24\xf9\x2a\xb3\x90\xc2\xab\x90\xc0\xe3\x55\xe5\x3c\x2a\x42\x17\xf1\xca\xe4\x98\x7e\x93\x18\xce\x63\x60\x18\x0e\x23\xf4\xc1\x3a\xd3\xdb\x94\xac\xcd\xa7\x22\x5a\xc5\x36\x5d\x51\x8e\x41\x34\xe8\x7c\x5b\x1b\x0b\x62\xb9\x29\x08\xb1\x3f\x00\x0c\x83\x61\x71\xa2\x5a\x53\xdb\xe2\xad\x18\x88\xd0\x01\x59\x54\x3c\x12\x3a\x5c\x87\x3b\x4a\xfd\x5f\xdb\xac\x00\xcf\xc3\x51\x2a\x05\xe2\x3f\x04\x1c\x86\xc3\xe2\x31\x42\xc6\x50\xb2\x56\x09\x3c\x85\x03\x35\x01\x10\xd7\x23\xcf\xc1\x7d\x20\x52\x71\x47\x69\xf9\xab\x10\xcd\xbc\xf8\x41\xe6\x57\x97\xd9\x16\x77\x8b\xa7\x45\x28\x4e\x5f\x51\xbe\x0c\xb9\xa1\x97\x72\x39\x54\x79\xb0\x7d\x02\x26\x7e\xbb\xe4\x47\x11\x58\xc5\x3b\x9f\x7c\x7b\xe4\x57\x0f\x19\x3e\x1d\xbd\x83\x81\xdc\x05\xf0\x23\x1e\x15\x36\xe2\xed\x28\xe2\x52\x5c\x8a\xb7\x83\xb8\xf1\xcf\x0d\x08\xc6\xff\x7e\xff\xc0\x06\x04\xa0\xf9\xfd\x3b\x18\x2f\x5e\x93\xd4\x49\xd1\xb5\x7c\x48\x1b\xa1\x07\x02\x9a\xc9\xfd\xb8\x9d\xf9\xd4\x03\xed\xa8\x12\x72\x87\x8e\x47\x8e\x5b\xb6\xa2\xa2\x36\x5d\xf4\x6c\x77\x6f\xdf\xce\x8e\xc9\x1c\xfb\xe2\x64\xe1\x57\xdb\xb7\xcb\xdf\x79\x8c\x04\x56\xf1\xe3\xb7\xc7\x21\x51\x44\x5a\xfe\x6d\x2d\x9f\x9c\x86\x49\x30\x1f\xe7\xab\x15\xe9\xd7\x34\x30\x1f\x1f\x1e\x98\x54\x19\x5c\x07\x5a\xd4\x0e\x24\xce\xc3\x87\x60\x9e\x6a\xca\x20\x95\x71\x90\x9a\x38\x00\xfd\x8c\x7c\x1b\x4f\x14\x16\x64\x1b\xb3\xb9\xec\x6c\xa9\xa1\x40\xc4\x55\xb0\x9a\x28\x68\x30\xb4\xb7\xb3\xbb\x83\xad\xcd\x4d\xc2\xa6\xae\x8e\x35\xaf\x70\x33\x29\xd5\x1d\x83\x5e\x59\xd3\xb1\xa9\x4b\x68\x6e\x6a\xad\xda\xc5\xb5\xb7\x1b\x0a\x1a\x44\x58\x83\x6b\x88\x86\x82\xca\x9c\x6d\x6c\x74\x5e\x68\x3e\xb3\x45\xaf\xcb\xcd\x13\xba\x36\x6d\xed\x5e\xc8\xc5\x54\xe0\x85\xdd\x5b\xbb\x36\x89\xb9\x79\x3a\x43\xe6\x75\xfc\xaa\x29\x83\x70\x0d\xac\x81\x0c\xbe\xbd\xb2\xfd\x06\x96\x55\xb8\x3a\x86\x25\x3b\x9b\x0d\xab\xa2\xf3\x99\xbf\x67\xfe\x4d\xfb\x9a\x10\x03\x23\x4e\xcd\x7f\x72\xf7\x24\xee\xf1\x27\x33\xe6\x69\xc5\x71\x5f\x10\xa7\x5f\xeb\xfc\xe0\x63\xf6\xc3\xcc\xfe\xf9\xa7\x84\x38\xa5\xaa\x51\x65\xaf\xcd\x9f\xb2\xfb\x09\x4e\xa5\x2e\x9b\x34\x25\x73\xfe\x7c\x11\x47\xe0\x70\x62\xfe\x82\xcd\x4f\x4e\x62\x9f\xd8\xf5\xd4\x6b\x5a\x21\x4e\xe3\xfc\x53\xef\x6f\xf9\x90\xfb\xf8\xfd\xce\xd3\xaf\x89\x5f\x8c\x23\xe6\x69\x33\x26\x3f\xce\xaa\x5a\x06\x4d\xda\x35\xe5\xd4\x7c\x21\x4e\x80\xf6\x54\xff\x96\xbf\x73\xaa\x51\x65\x1f\xf6\xef\x3a\x75\x4a\x8c\x6f\x3f\x70\xaa\x77\xcf\xfb\x1f\xb2\x37\x6c\x7f\xca\x12\xd5\xca\x32\x99\x66\xe0\x79\x54\xc1\x28\x7c\xe2\x90\xb0\xe3\x50\xed\xb1\x57\xa0\x83\x9a\x3e\x57\xb7\x66\x85\x00\xb3\x9f\xc0\xe9\x70\x27\x6e\xe2\x80\xa0\x4a\x5c\xc5\xae\x12\x11\x47\x3d\x7d\x17\x3e\x88\xd3\x7a\xf9\x70\xbf\xe2\x5f\x54\x9a\x9d\x07\x3a\xe1\x0a\x95\xa8\x26\xe0\x0b\x26\xe2\x0c\xed\x25\xe4\xa1\x7d\xca\x2f\xf8\x88\xa4\x30\x50\x7d\x91\xa1\x8a\x88\x33\xba\x97\xc0\x5b\x26\xf7\xde\x0f\x77\x71\x16\x4a\x01\x77\xf5\x7e\x07\xb7\x4c\x16\xa3\x4d\xa1\x8d\x4c\xd3\x1e\xe2\x80\x52\x1e\x0a\x74\x64\xa8\x72\x9d\xb2\x69\x33\xb4\x47\x9e\x24\xa2\x4b\x15\xf1\xe8\x61\x9a\xb2\x5c\xb8\x0a\x9a\x78\x38\xff\xf8\xce\x08\x83\x5d\x30\x4e\xd6\xc2\x38\x57\x5f\x5f\x4c\x7f\x9e\x1c\xd6\x86\x68\x66\x26\x0f\xbd\xd3\x19\xd9\x2b\xdf\xdd\x50\x2d\xb5\xd8\x9b\x53\x6d\x2d\xa5\x8d\xf9\x95\x48\xf7\xa5\xf8\x8c\x06\xb7\x81\x2b\x2b\xb3\x59\x8c\x62\x74\x6a\xe4\x4e\xbc\xe9\x6d\xab\xdb\xea\xb6\xba\x52\xa5\x3d\xde\x2e\x5b\x97\xf1\x97\xa9\x3f\xe0\x4d\x17\xc9\x53\xe3\xef\xdb\xfd\x00\x37\x76\x52\xd6\x8b\xf3\xc4\x17\x5e\xcc\x9c\x14\x98\x28\xdd\x73\xf1\x5e\x48\x78\x86\x9c\x7f\xe9\x87\x2d\xdf\x72\xa7\x5f\xa9\x6a\x3a\x2c\xfa\x8d\x01\x93\x64\x86\xe4\x29\x29\xaa\xf2\x41\x98\x3c\xc5\x68\x36\x99\xcc\xc6\xd4\xa6\x15\x0b\xab\xe6\x71\x0f\xdc\xbb\x65\xfe\x78\x11\x13\x9e\x99\x7a\xaf\xf1\x1e\xd3\xc4\x5d\x93\xce\x2c\x20\x17\x9e\xfe\x30\xeb\x2b\x4e\x35\x7b\xd0\xb7\xdf\xef\x3e\x75\x49\x84\x9b\xde\xbd\xf8\xbd\xf4\x8b\xa7\xcb\xda\x65\xdc\xe3\x75\x79\xdd\x5e\x37\xdc\xf4\x76\x4a\x68\x6a\xe4\x4e\xc2\x22\x55\xd9\xaa\xb8\xca\x4a\xb7\x4f\x12\x81\xee\x6b\xac\xac\x6e\xf4\xb4\xa4\xba\x9b\x8d\x2d\x05\xd5\xa4\x1a\x97\x86\x86\x33\x39\xdb\x56\xe9\x97\x71\xaa\xb6\x41\xb3\x9e\x69\xea\x9e\x25\xe2\xa0\x0b\x6b\x7f\x3a\x77\x9a\x6c\xdb\xd1\x13\x3c\xca\xbd\xf1\x5e\xde\x9a\x73\x22\x0c\x9a\x76\x70\xf8\xac\x79\xe4\xf8\x68\x09\xb3\x66\xd6\xd3\x79\xb3\x39\xd5\xed\xbd\xcb\x56\x05\xdb\xb6\x89\xb3\x4e\x1f\xfc\x09\x06\x5d\x20\xbb\xcf\xbd\xdb\x74\x8e\x3b\xda\xa3\xcf\xd9\x21\x9e\x9b\xb7\x76\x38\x0e\x9a\x46\xc2\x54\x39\xc4\x48\x92\xdb\xed\x76\x79\x3c\xa9\x15\x01\x7f\x45\x45\xc5\x8e\x1d\x29\x1f\x2f\x2d\x29\x27\xf2\xf4\xa5\xb9\x3a\xb6\x4c\x09\x34\x4e\x60\x50\x33\x72\xdb\x8e\xf2\x0a\x73\x45\x79\x45\xaa\xcd\x6d\x77\xd9\x3d\xc6\x8a\x14\xd0\x5c\x21\x80\x50\x86\x24\xf9\x29\xa0\xa7\x47\x75\x91\x7e\x42\xbe\x1a\xa1\x99\xc8\xc7\xf0\x89\xcf\xed\x73\x79\xbc\xa9\xf0\x0c\x08\x72\x7d\x64\x14\x91\x0c\xde\x3f\xf7\x66\x91\x69\x58\xc9\x2f\xe0\x55\x3f\x1c\x50\x2b\x9a\xe1\x1c\x1f\xd1\x28\xd6\x2c\x2a\xd4\xad\x11\xe1\x53\xa5\x0a\xe6\x2c\x8d\x25\x2c\x78\x72\xf3\xba\x75\x62\x64\x54\x64\x14\xb1\x6e\xdd\xe6\x27\x17\xb0\x51\xcd\xe3\x94\xea\x87\x03\x72\x0f\xf6\xc0\x04\x5e\x9d\xd4\xab\x5c\xca\x47\x7a\x70\x23\xa3\xfa\xe1\x22\xbe\x8a\xaf\x2a\xf1\xdb\xd0\x24\x26\x7e\x25\x97\xe3\x4f\xcc\x40\x29\x94\x22\x52\x88\x8e\x47\x0c\x95\x35\x32\x1d\xd1\x28\x55\x3f\x1c\x08\xd1\xd7\xae\x32\xd7\xe8\x58\xba\x42\x05\x63\x06\xb2\x94\xb1\xcf\xcc\xed\xa0\x0a\x0f\x01\x06\x3c\x70\x7b\x82\x17\x68\x70\x00\x1d\x0a\x82\x2a\x51\x4d\x14\xc3\x48\xe6\x8b\x75\x97\x66\xbc\x29\x44\x3e\x92\x3f\x22\x0e\xad\x99\xdf\x3a\x8f\xc3\x9b\x1e\x7e\x18\x6f\xd2\xb6\x6a\x0f\xad\x11\xe5\xd1\x91\xd1\x84\xd9\x5f\x61\xad\xe0\x9a\xcf\x9c\x69\xae\x80\x28\x15\x19\x2d\x8f\x26\x8a\xeb\x0c\xcd\x2d\x6c\xf7\xae\x8e\x83\x2d\x2d\xc6\xe2\x3a\x41\xfe\x28\xf2\x11\x71\x70\x6d\xfb\x8b\x5a\x76\xfc\x8c\x19\xe3\xe7\x2f\x68\x3f\xb8\x56\x88\xd6\x87\x1a\x88\x25\xc7\xb7\xbe\x75\x81\x85\xbb\xe0\x26\x50\xc2\xdd\x17\xde\xda\xb2\xf4\xb8\x20\xff\x12\xf9\x35\x8e\x55\xe2\x9a\x4f\x9f\x1e\xc0\xfa\xb3\xfc\x0b\xf1\xb7\x29\xf7\xf5\xdc\xc3\xe1\x06\x7c\x0c\x27\xe2\x86\xe1\x2f\xdd\xf7\xde\x53\x62\xa8\x21\x5a\x4f\xcc\x7c\xf3\xd2\xda\x2f\x38\x18\x03\xb7\xc0\x2d\x30\x26\xbe\x90\x17\xf7\x94\x04\x29\x76\x7e\x95\x92\x25\xf8\x8d\x97\xe9\x21\x32\x1d\x92\x22\xb1\x8f\xed\x10\x59\xa3\x5c\xca\x47\xfb\xfb\xa8\x88\x06\xe9\x58\x9f\x8e\x68\x1e\xa7\xe4\xb8\x9b\x80\xb2\xa9\xbb\xa8\xa4\x46\x84\xbd\xb8\x97\xa8\x2e\xad\x5f\x95\xcf\x5e\xa3\x95\x11\x29\xac\xa9\xe3\x51\x3b\x30\xd9\x0a\xda\x81\xb9\xd6\x10\x9d\xc1\x5c\x0f\xe4\xd1\x05\x5d\xd7\x03\x79\x5c\xd3\x0c\xc4\x75\x54\x87\x7b\xb5\x7c\xdc\x10\x35\x7c\x35\x8d\x77\xfe\x9b\x82\xe1\x14\x7d\x69\x0e\x05\x5a\xc6\xc9\x87\xe8\xa4\xeb\x87\xe4\x66\xe7\xbf\xa9\xbe\x3c\x1b\xbf\x80\xcf\xe4\x65\x29\xe9\xfa\xce\x8c\x3a\x3e\xa2\x61\x9e\xa2\xe0\x4d\xea\x11\x4a\x9d\x14\xdf\xef\x51\x1d\x2e\x0b\x5f\xcd\xe4\xff\x8f\x9c\x90\xf6\xfd\xff\x76\x9f\xdc\x8c\x12\x24\xc0\x08\x90\xee\xfb\x1e\xe8\x1f\x76\x81\xd4\x08\x09\x40\xff\x30\xb8\xf3\xb7\x46\xb8\x65\x03\x0c\xc1\x9b\x41\x35\xec\xaa\xea\xf9\x32\xf9\x8e\x47\x98\x8b\x2b\x5e\x7d\xb6\x4e\xf8\x37\x28\x89\x2f\xf0\x73\x1c\xf5\x9b\x52\x75\x2a\xad\x57\xa9\x6a\x49\xeb\xec\x72\x77\x72\x0e\x65\xfa\x9a\x4d\x0b\xd7\x2f\xdb\x31\x2f\xa5\xc7\xd3\x67\x9b\xc7\xae\x5e\x57\xb8\x61\xed\xaa\xa6\xf6\x2c\xe1\x85\x71\x84\xea\x54\xda\xf2\x23\x7d\xb9\xe7\xb9\x5f\x3f\x7f\x13\x6e\x12\xdd\x21\x25\x73\xb7\x42\x75\x53\xda\x6c\x54\x29\x3d\x1f\xc1\x96\x2e\xb8\x97\xfd\xe1\xb1\xd7\x46\x4f\x9a\xb6\x66\xea\x26\xe1\xd2\x1c\xa2\xa3\x7e\xd7\xee\x7d\x5c\x57\x73\xc1\x46\xf1\x11\xcc\xdd\x8a\x33\xd9\x02\x4f\x81\xa7\x40\x80\x6b\x0a\x35\x61\x40\x0d\xdc\x42\xc5\xda\xf9\x21\xa3\xba\xa9\x0c\x07\x29\x54\xb7\xdf\x2e\xdf\x7b\x97\x12\xd5\xa8\x7a\x6f\x52\x63\x7d\x53\x6d\x55\x4b\xaa\x5b\xaf\x98\xe0\x98\x30\x81\x4d\x53\xa8\xe8\xc9\xf7\xc2\x17\x4a\x1d\x8f\x3d\x70\x0b\x15\xe3\x82\xea\xf6\xdb\xd5\x38\x19\x0e\x51\xa8\x55\xc6\x23\x77\xc5\x38\xa2\x22\xcb\x9e\x88\xfb\xef\xfc\x26\xef\x01\x3a\x34\x0c\x92\x6c\xbc\x5a\x71\x29\x44\x33\xea\xd0\xe4\xb1\x94\x5a\xd1\xbb\x91\x57\x63\x62\x1f\x13\x2a\x52\x64\x35\x64\xd4\xaf\xaf\x9f\xb6\xfb\x85\x96\x25\x35\x78\x77\xcf\xe8\x97\x57\x1c\x21\x57\x1c\xd9\x7e\xf4\x04\x7b\xb6\xe5\xc4\x91\x6e\xa1\xfb\xc8\xb9\xa6\x0f\xb9\x4f\xde\xdb\x32\xeb\x75\x71\xef\xfa\x7d\xd3\xf6\x0e\xaf\xb1\xa7\xfc\xd3\x1c\xf4\x10\x9e\x3a\x77\x6d\x0d\xfb\xb2\xe5\x9c\xf1\x63\xc1\xf4\xaa\xe9\x90\x69\xc7\x93\x6d\x73\xea\x56\x54\x90\xc1\x27\xb5\x81\xb5\x1c\x3e\x89\x77\xae\x1c\xff\x90\xf8\xd0\xf8\xe5\xf7\x60\x32\x3b\xbb\x6e\x46\xe7\xf3\x42\x6d\x66\x7d\x56\x63\x0e\x29\x7b\x51\x62\x2e\x6e\x3d\x9a\xd3\x92\x4f\x9e\x5a\xbc\xf3\xc5\x79\xec\xb2\xa2\xf4\xcd\xab\x85\x2d\xab\x57\x65\x2e\x2c\x24\x0b\x16\x2d\x35\xae\xe4\x96\x2e\x0f\xd4\xae\x16\x57\xd5\x6c\x68\xcc\x6c\xcb\x6c\xcb\xda\x93\xd3\x5d\xd6\x50\xf8\xca\xba\x4b\xf7\xd8\x53\x56\x28\xf3\xac\x1b\xdc\x8b\x04\xef\x48\xfb\x8b\xe5\x6c\xa9\xb2\xcc\x6b\xf2\x5a\x85\xca\xf2\x56\x63\x77\x19\xa4\xad\x4e\xc9\x7d\xff\x6d\xfb\x6b\xdc\x3f\xde\x09\xd4\xf4\x8a\xbd\xd5\x27\x5b\x4f\xee\x3e\xb1\x67\xff\xce\xb6\xd6\xae\xae\xd6\xbd\xb5\x07\xc8\x8e\x8b\xd5\xef\xfd\x8d\xed\xb2\xef\xb1\x74\x08\xc9\x4e\xb0\x21\x09\x64\xf8\xe4\xb7\x63\xbf\x79\xf8\x8b\xc1\xb0\x01\x8e\x84\x72\x21\xe9\xaf\xbf\xab\xdc\xaa\xf9\xc7\xd5\xc4\x5d\xcc\x67\xf6\x13\x25\x75\x3a\xb2\xaa\xc8\xff\x34\x0e\x66\xf1\x73\xe5\x30\xdf\xe3\x55\x5a\xa1\xf6\xb1\x8e\xe7\x0f\x2d\x3a\xb4\xe8\x8d\x55\x1f\x6f\x26\x37\x7f\xfc\xef\x62\xb8\x89\xfb\xee\x52\x55\x4b\xbf\xd8\xdf\xf2\xc6\xee\x13\x07\x8e\x1f\x3c\xd8\xb3\xe3\x70\xfd\xee\x9a\x9e\xca\x57\x2a\x5f\xa9\xfc\xd9\x02\x23\x49\x95\xa7\x44\x4e\x2e\x6f\x70\xb2\x8e\x76\x7b\x53\x35\xdb\xe8\xaf\x96\x24\xc1\xe7\xdb\xe9\x3b\x16\xd8\xe5\xea\xf0\xed\x0c\x90\xee\xa0\xbb\x52\x62\x25\x7b\xbd\xb5\x5d\x28\x70\xcf\x30\x3d\x6f\x9e\xe6\x49\xc5\x95\x95\xc4\x23\x0a\xfb\xc3\x35\xb6\x1f\xdd\xbb\x5c\x3b\xf4\x2d\xba\xd4\x9a\xe2\xc0\x16\x4f\xba\x77\x4e\x8a\x6a\x47\x2d\xe6\x56\x5b\x70\x1a\x3b\xd4\x34\xa9\x64\xb1\x60\xd8\x50\xb8\x66\xdb\x6a\x7d\xde\xf6\xdc\xcd\xba\xcd\x39\x9b\x8a\x36\x94\x91\xf9\x73\xa6\x1b\xa7\x71\x73\xe7\xd4\x76\xce\x16\x57\xb5\x64\xec\xd1\x75\x6f\x3e\x55\xf4\x8e\xf5\xd3\x12\xe8\x4a\x71\x40\x01\x51\xeb\x68\x6c\x63\x3f\xf2\x1e\x96\x2a\x85\xfa\xea\x1d\x15\x87\xb8\x97\x7b\x3c\xfe\x43\xa2\xa4\xb4\xf7\xb9\x6a\x08\x47\x71\xa6\x63\x25\x97\xee\x58\x6c\x9f\x6f\x27\x55\x95\x76\xed\x3c\xc7\x0b\x5c\xd1\x3c\xb7\xef\x01\xd1\xb3\x66\xad\x6b\x03\x57\x52\xea\x74\x94\x8a\x9e\x71\x84\x6a\x7e\xd0\x56\xeb\x6c\x70\x90\x6a\xe2\xa2\x3a\xac\x67\x26\xc4\xb7\x5d\x54\xb9\x35\xd4\x76\x4a\x4d\xf4\xbe\x10\x0f\x49\x4c\x43\xfa\x80\x29\x0c\x0d\x3f\xc7\x06\x2a\x8d\x9e\x97\xe9\xa4\x0e\x3e\x22\x85\xa4\xeb\x0e\x9d\x7f\x6e\x1c\x7c\x7d\xc7\xdf\xfe\x81\x1d\x7f\x51\xab\x94\xa5\x08\xbd\x93\x8a\x81\xee\xa4\x64\x3a\xe9\x61\x1e\x68\xe8\x8f\x6f\xef\xd8\xbb\x8c\xba\xd6\xbf\x9e\x57\x13\x93\xcf\x53\x69\xc3\xd5\x8a\xb5\x09\x3b\xd5\x8a\xb5\x89\xea\xa4\x9d\xe1\xd9\x4c\xda\xef\xf0\xff\x31\xf6\x26\xf0\x4d\x54\xdd\xff\x70\x6b\x9b\x99\x3c\xf3\x68\x51\x92\xe1\x69\x33\x99\x99\xb2\xca\xa6\x82\x14\x10\x41\x44\x41\x11\x2b\xc8\x12\x64\xdf\x97\xb6\x14\x4a\x0b\xe9\xbe\x25\x69\x9a\xb6\x99\xb4\x4d\xda\x49\xba\xef\x50\x28\xa5\xac\x95\x45\x41\x40\x59\xd4\x02\x22\x44\xf4\x51\x50\x14\xc1\xa5\x3e\x0a\x8a\x9e\x49\x4e\x52\xde\xcf\xa4\xe8\xe3\xef\xfd\xbd\xff\xf7\x7d\x3f\x4a\x27\x77\xe6\x9e\x7b\xcf\xdc\x99\x7b\xee\x39\x77\xce\xf9\x9e\xa3\x70\xf4\x8f\x48\x05\x3c\xd9\xaf\x36\xbf\x26\xb7\x82\xc3\xc5\xb0\x58\x51\x91\x9b\xe9\xc8\x60\x32\x02\x5f\xae\xb4\x5e\xaf\xd6\xeb\x55\xe4\xe6\xe6\x67\x66\x68\x32\x1c\x99\x15\xb9\x1c\x2c\xc6\xc5\x01\x57\x2c\xe8\xa6\x1c\x15\x15\xbc\x56\x41\x68\x15\x84\xa2\xa2\xc2\x51\x53\xab\xd1\x7a\x8f\xc2\x5c\x18\x4c\x81\x1d\xc3\xe9\xd7\x61\xe1\xeb\xb8\x10\x17\xca\xc7\x73\xb8\xf0\x1c\x2c\x84\x85\xe7\x14\x9e\x2d\xbe\x71\x30\x98\xf2\xa7\x78\x9e\x86\xc1\x54\x58\x23\xe4\xb1\x1e\x35\xdc\x64\xa5\x7f\x50\x2a\x80\xc9\xd4\xd9\x5e\x8b\xa8\x8d\x2c\x75\x54\x97\x94\x70\xb0\x00\x16\x28\x4a\x4a\xaa\x1d\xa5\x0c\x3c\x4d\xa8\x7e\x41\x91\xf4\xaa\x7d\xe2\x59\x0a\x44\xaf\x3b\x86\xea\x11\xc7\x52\x01\xa8\x80\x98\x25\xa9\x5b\xb6\xf0\x2a\x40\x99\x3d\x9d\xce\x39\x69\x9a\x06\xf6\xb0\x2f\xfc\xdb\x79\x9c\xef\x22\xfe\xf6\x6d\x46\xfd\xb7\xc2\xf1\x7f\x1b\x3f\x09\x2c\x13\x5d\x9e\xd1\x30\x11\xfe\x15\xf0\x03\x2b\x86\x61\x30\x0c\xec\x70\x1c\x66\x83\xbd\x37\x1a\x73\x04\xfb\xe7\x3e\x16\x7e\x04\x73\xb0\x19\x5a\xf0\x9f\x5c\xd1\x29\xdb\xf9\xaa\x33\x4a\xa1\xfa\x83\xaf\x40\xe2\xb6\x1c\x13\xdc\x82\x06\x88\x0b\x37\xae\x7f\xdc\xf1\xc6\x6b\x2f\x2d\x1f\xa0\x1f\xce\x4d\x48\x3b\x37\xe3\x0b\x06\x86\xfc\x07\x5e\x87\x24\x78\x0e\x09\xe8\x8b\xab\x31\x1b\x07\xe3\x8b\xf8\xc6\x2b\x0d\x4b\x77\xad\xe7\xab\x32\x8a\xf3\x2d\xa9\x05\xd9\x79\x71\x05\x39\x96\xd4\x4c\x73\x46\x99\x32\xf2\xf0\x22\xa0\x02\x5e\xbe\xf0\x1a\x54\x4b\x41\xf0\x16\xcc\xc7\x38\x4c\xc5\x77\x71\x12\x26\xa3\xf0\xcc\x73\x47\xde\x49\xe2\x96\xe3\x4b\xa6\x38\x41\x93\x39\x7b\xc3\xec\x84\x65\xca\x94\x8f\xaf\x18\x3e\x65\x7a\xf7\xee\x3e\xf3\x0c\x83\x09\xd0\x6f\x3f\x05\x43\x61\x28\xd8\xe0\x2d\x98\x05\x22\x3c\xcc\x42\x34\x91\xff\xae\xe9\x8f\xa6\xef\x64\x9e\xbf\x84\x7b\xdc\xd6\x63\xc2\x15\x41\x03\xa1\xe7\xbf\xba\x76\x69\xf7\x82\x99\x2f\xaf\x18\xa8\x1f\xc1\x3d\x9b\x76\x6e\xc6\xe7\x0c\x0c\xfa\x09\x66\xc2\x66\x98\x88\xa1\xf0\x28\xae\xc4\x0c\x1c\x84\xcf\xa3\xee\x95\x86\x65\x6d\xeb\xf9\xaa\xcc\x62\xb3\x25\x4d\xe6\xb9\x30\xc7\x92\x16\xe0\xb9\xff\xe1\x45\xa0\x84\x7e\x1a\xd8\x08\xaf\x42\x05\xf8\xe1\x10\xcc\xc3\xf5\x98\x8c\xef\xe0\xb3\xb8\x15\x0b\x27\x4c\x3e\xfc\x4e\x22\xb7\x02\xa7\xca\x3c\xa7\x4c\x98\xff\xec\x86\xa5\x4a\x4f\x1c\x4c\x65\x8f\xb1\xbf\x7e\xb3\x6e\xe6\x45\x6e\xe0\x10\xc5\x8e\x84\x45\xbb\x5e\x60\x30\x3c\x12\x83\x50\x83\x9a\x3f\x30\x08\xc2\x61\xe4\x69\x08\x7e\xaf\x9c\xc7\x4d\x10\x4e\x08\xd0\x43\x96\xa4\x95\xa4\x6e\x01\x86\x95\xda\x23\x59\xa9\xed\x49\x68\x86\x4b\x60\xc7\xf5\xb0\x1e\xbc\xd0\xdc\x57\x80\x76\x2d\xf1\x32\xac\x57\x5d\xd3\x2a\xea\x3c\x21\xf4\xdb\x96\x7d\xe6\x7d\x9c\xff\x15\x81\x40\xbb\x14\x45\x46\x66\x60\x30\xae\xc3\x43\x0c\x96\xe0\x4a\x58\x13\x48\xd7\x26\x1f\x4b\x60\xe0\x8f\xb3\x16\x9c\xe2\x61\x09\xcc\x53\xc0\xc3\xa8\xc6\x09\x57\x70\x31\xa3\x3a\xe6\x1b\x86\xd7\xf0\x9a\x6f\x98\x6f\x18\x5c\xc3\x6b\xd2\x30\x69\x22\x74\xc0\x71\x69\x3c\xef\x01\x08\xa3\x71\x1d\xac\xc3\xf5\xb8\x0e\xd7\xe1\x7a\x58\x87\xeb\x60\x3d\xac\x83\x75\x44\x18\x0c\x13\x40\xdd\x0d\x51\x52\xa7\x7c\x50\x07\xc3\x6e\xea\xf2\xe9\x80\x1a\xf2\x36\x15\xe2\x11\x25\x35\xdd\x0d\x6a\xe8\x2c\x22\x33\xb7\x64\x19\xb6\xa6\x4c\xfe\x22\x1c\x86\x02\xab\x00\xc2\xa7\x03\x75\xc0\x9f\x4d\x94\x6d\x93\x87\x20\x07\xd7\xe3\x7a\x7c\x08\x73\xf0\x55\x7c\x15\x1e\xc2\x1c\x90\x6f\xf4\x21\xc8\x81\x57\x39\x49\x44\x91\x86\x76\x56\x8b\x06\xa2\x99\xe5\x24\x91\x8c\x66\x79\x0b\x45\x98\x29\xce\x27\x92\xa0\xf6\xb8\x63\x28\xad\x27\x68\x2c\xa5\x45\xc3\x53\x6c\x26\x1b\x47\xf9\x73\xc1\x2d\xb9\x61\x01\xeb\x71\x9b\x02\x88\x0f\x62\xa0\x04\x6e\x3a\x87\xea\xb9\x0f\x6a\xaf\x18\xdc\x25\xb9\x43\x3c\x6a\xaf\x9b\xfe\x9e\xf2\xe9\x7c\x3a\x45\x6e\xae\x39\x33\x43\x03\x51\x2c\x27\xe9\x7c\x3a\x38\xf7\x67\x3d\x41\x72\x87\x48\x6e\x4f\x20\xfa\x55\x27\xe9\xde\x67\x7b\xd4\xe4\x95\x00\x94\xea\xc5\x00\x1e\x5c\xc0\xa7\x51\x08\x20\xa3\xbd\xcc\xaa\x9f\x81\xa8\x7e\x2d\x94\xf7\x9e\x47\xad\x45\x03\xe9\x11\xdb\x6b\x58\xdf\x3d\x0b\x25\xab\xa2\x04\x04\x30\xb7\x03\xa2\x6a\x23\x15\x10\x53\xfe\x5c\xad\x62\x4a\x2a\x2c\x60\x25\x9d\x49\x96\x66\x39\x94\x3f\x37\x3a\xc0\xa9\x7c\x22\xec\xaf\xcb\x1e\x99\xef\xc6\xc0\xee\xc8\x28\xd6\x73\x91\xde\xb4\x21\x2e\x21\x66\x0b\x4e\x44\x05\x4e\x42\x02\xc7\x23\xa5\x9c\x39\x7e\xe0\xf3\x18\x1c\x00\x5b\xc7\xe0\x81\x9f\x7e\x30\x9e\xc7\xf1\xf0\x4f\x9c\x04\x0a\x7c\x16\x14\xeb\xb7\xc5\xed\xdc\xb4\x5b\xe9\xdf\x73\x8a\xf2\xba\x43\x6f\xbe\x78\x25\x8a\x93\x05\x73\xe4\x1b\xe3\x87\x8d\xba\x83\x8a\xcb\x4b\x78\x78\x0a\x83\x60\x34\x06\xc1\x53\x18\xac\x5c\x7e\x1e\x1e\x7a\xea\x5a\x00\xf3\xfd\x1a\x3c\xf4\xdd\x91\xf3\x3c\x3c\x05\xc1\x30\x1a\x82\x60\x14\x04\x29\x6f\xbe\xff\xe5\x1d\x08\xd5\x84\x79\xc6\x41\x25\x4e\x84\x41\x7d\xeb\xe1\x4b\xcf\xcf\x70\x5d\x95\x08\x77\xbd\x03\x69\xfc\xb2\x67\x2b\x7c\x49\x34\x6a\x15\x8f\xd1\xaa\x7d\x3f\x59\x5f\xfa\x04\x15\x0c\x86\xbe\xf0\xc2\xf0\x91\x97\x9f\x87\x10\xbe\x58\x20\x80\xbc\xf2\xe9\x8f\x56\x5e\x1b\x5a\xe2\xdf\x44\xc3\x69\x1c\x07\x03\x70\x13\xa7\x4a\xc4\x97\x9f\x1b\x3a\x7d\x25\xaf\xda\x57\x0c\x83\xf0\x3a\x21\x94\x3e\x59\xd0\xd3\x8f\x13\xe0\xba\x74\x9c\x6c\x2b\xd9\x59\xde\xc4\x9d\x6d\x39\xf5\xfe\x6d\x06\xfe\xf9\xf6\x28\x8c\xe0\x7d\xad\x70\x9d\x0c\x83\x5f\xd8\x22\x16\x44\xd5\x3e\xd5\xa5\x13\xac\x6a\x1f\xb0\x6c\x00\x7e\xf5\x23\x4a\x75\x09\xfe\xc3\xaa\xf6\xe1\x34\x18\x02\x1b\x87\x40\x3a\x03\xb3\x03\xe8\xf7\xb9\x5a\xe2\xbd\xe0\x83\x5a\xe2\xbd\x10\x2d\xd1\xdd\x0f\x0a\x58\xbc\x0f\xf7\x1f\xc4\x4e\xaf\xdb\x98\x99\x98\xc8\x4b\x8f\xb1\xd0\x17\xfa\x2a\x44\xd1\x5e\x51\xa9\xa9\xb4\x54\x98\x44\x6e\x53\x5b\xd3\xe6\xa3\xcc\xf6\x66\x67\x5d\x3d\xbf\xb7\xe3\xed\xbd\xa7\x1e\x20\x89\xfb\x46\x4a\x23\x15\x75\xe9\x5b\x9c\x5b\x98\xf9\x31\x4b\x62\xe2\xf8\xf4\x34\xa3\x3e\x49\xb3\x6c\x47\x72\xdb\x26\x4e\x34\xe5\xda\x73\x98\x9c\x5c\x8b\xc9\xc4\xe3\x1d\xbc\xa3\x30\x99\x2c\xb9\x39\x9a\x1c\x7b\xae\x68\xe2\xda\x36\x25\xef\x58\xc6\x24\xe9\x8d\xe9\x69\x7c\x4c\xdc\x92\x98\xf9\x0f\x92\x32\x4a\x23\x7d\x23\xe1\x0d\xf6\xd4\xde\xb7\xf7\x76\xf0\x75\xf5\xce\xe6\xed\x9a\xa3\x9b\x9b\x36\xb5\x71\x26\xb1\xc2\x52\xc9\x54\x56\xd8\x45\x91\x97\xf9\x83\x26\x56\x91\x98\x98\xb9\x71\x9d\x26\xae\x2a\x10\xbe\x7e\xdf\x17\xf4\x57\x14\xf7\x1f\x10\x14\x08\xe2\x0e\xbc\xa2\xab\x59\x78\x9f\x9a\xce\x82\x4e\xd2\x4d\x67\xa5\x29\xbe\x64\xfa\xfc\xf2\x8e\x09\x29\xcf\x26\x0e\x1e\x30\x73\x50\xeb\xe0\xd6\x99\xf7\x5a\x7f\x6d\xba\x76\xe9\xdd\xcf\x1d\x77\xa4\xbe\xe1\x62\xc7\x9e\xc6\x0e\x93\x52\x20\x3b\x4c\x0d\xb1\x79\x71\x4a\xe9\x3d\xbc\x3b\x9d\xf5\xab\x3d\xea\xe9\xac\xa4\x43\xdd\x74\x16\xdc\x3e\x1d\x0d\x9f\xb0\x7f\xe6\xb0\xc4\x29\xc7\x70\xe2\x77\x38\x88\x4b\xaf\x68\x30\x34\x31\x5a\x45\x06\xd1\xd4\xe0\xaa\xab\xe0\xbf\x83\xc1\xc7\xe0\x59\x98\xf2\x20\xfa\x56\x84\xd5\xac\x57\xad\x0d\x35\xec\xa0\xfe\x8c\x82\xe3\x04\x32\x10\x08\x77\x00\xff\x68\xa0\x1a\x1b\x53\x1e\x24\x26\xf8\x9a\xf2\xe8\xe0\x7d\x16\xce\x43\x2d\x4e\xc3\xb5\xb8\x16\xe5\xe3\xf9\x05\x0b\xed\xe2\x22\xfe\x0d\xe7\x8a\x8d\xa9\xd9\x29\x39\x29\xb9\x11\x7b\xbe\x1a\xfe\x9e\x02\xd5\x9f\xbc\xf0\x3b\x3c\xa4\x81\xb5\x50\x0b\xd3\xe0\x3c\x07\xea\x50\xa8\x66\xf9\xb7\xd9\x3f\x23\x0b\x78\xcf\x87\x5a\xdc\x4c\xff\x15\x52\x60\x60\xc3\xfc\xf7\x51\x3c\xc8\x06\x0b\x5e\x55\x88\xf7\x1f\xde\xe5\xb4\x68\xca\x75\xe4\x30\x05\x05\x56\x6b\x01\xef\x8b\x1c\x06\xcf\x4b\x6b\x14\x25\x8e\x62\x87\x43\xd3\x9c\x5a\xbf\x85\x13\xf0\x1a\x99\x92\x9e\x93\x66\xe1\x71\x99\xff\x42\x61\x76\x69\x56\x85\x31\xc2\x5c\x5e\x51\xe0\x62\x4a\x4b\x05\x5b\x29\x2f\x0d\xbf\x83\x8b\xfc\xc7\x2c\x29\x95\x29\x4d\xe6\x08\xab\xdd\x6e\x2d\x65\xea\x6a\x9c\xd5\xe5\xbc\xb4\x4f\x1b\x9a\x5f\x56\x5d\x58\x6b\xa8\x88\x08\x6b\x94\xdc\xb2\xa0\xd4\x81\x5a\x12\xe1\x36\xa5\x4e\xcc\x64\xa1\x13\xc6\x50\x23\x40\x47\x7c\x4e\xf9\x44\xd0\x75\xbf\x40\x81\x9b\x5c\xca\xa2\xbb\x8b\x42\xf7\x24\xaa\x1b\x75\x3e\xf1\x0e\x85\xba\x11\xe4\x8d\xde\x2b\x23\x40\x27\x89\xa8\x1b\x41\xfc\xef\xb2\x2c\x93\xb4\x8a\x48\x88\x0a\x96\xd4\x00\x94\x57\xed\x59\x48\x97\xa5\xa4\x94\x26\x33\xc9\x29\x05\xe6\x14\xde\xf7\x19\xf9\xca\xac\x59\xaf\xbc\x32\xeb\xfd\x8b\x30\x8c\x42\x1e\xfe\x81\xff\x00\x1e\x78\xf8\x07\xfc\x03\x78\xce\x23\x4a\xc7\xe9\x92\x00\xba\xb7\x14\x36\xda\xa7\x80\x0d\x3e\x25\xe3\xa3\x7c\xc1\xb8\xc1\x17\xf6\x14\x6f\x2d\x12\x8a\x0a\x35\x07\x28\xb1\xac\xd4\x51\xc6\x9d\x3a\x73\x6a\xff\x97\xcc\x8f\xd7\xa1\x99\xad\x64\xaa\xe0\x1c\x7b\xed\xec\x8f\xcc\x8f\xd7\xa0\x99\xad\x62\x2a\xe1\x1c\x7b\xfd\xec\x8f\xcc\x97\xa7\xd6\xcd\x3f\xc3\xe7\x97\x95\x15\x88\xcc\x64\xca\x2f\x7a\xe2\x69\x08\x61\x87\x91\x8d\xb6\x26\x5b\x63\x63\x93\xb5\xf1\xe1\x41\x61\x8d\x30\x9a\x82\xb7\x29\xe9\x41\xf2\xe4\x07\x98\xf6\x77\x29\x8f\x88\x6a\xda\x42\x49\xbd\xb6\x6a\x94\x5f\x4d\xf8\xd5\x5a\x45\x63\x0d\xeb\xd7\x19\xa8\x2e\xb7\xfc\x86\x4c\x67\xa3\x49\x10\xfd\x51\x34\x9c\x20\xe1\x04\x9e\x50\x40\x1c\xaa\x1f\x98\xa8\xf2\xcc\x34\xb8\x72\xc5\x9c\xf2\x08\xb8\x46\x2e\x65\x7b\xdc\xf0\x04\x2b\x75\x06\x40\x26\xc3\xfc\xb9\xde\xce\x2e\x88\x82\x48\x16\x06\x82\x0a\xd2\x40\xf5\x6c\x20\xfc\x55\x75\x5b\xe5\xf5\xe8\xbd\x3a\x1a\x42\xf0\x5f\xc7\x9e\x7c\x99\x3d\x40\x9d\xfc\x23\xf1\xe5\x03\xd4\xcb\x14\x07\x51\xfd\xa2\x93\x5e\x59\xb5\x98\x4b\x4b\x4e\x4e\x49\xd5\x4f\x1b\xf7\xfa\xe3\x46\x54\x28\x31\x8d\x30\x82\xe2\xf5\x5f\xa6\xdd\x48\x6d\x4e\x6e\x4c\x6b\x52\xae\x3a\x96\x74\xb1\x4b\x03\x4b\x61\x05\x3c\x0c\x33\x38\xd5\x6d\x98\x01\x2b\xf0\x61\x5c\xca\x83\xba\x1f\x6c\xc3\x0a\x98\x86\x0e\x74\x60\x05\x4e\xc3\x6d\x83\x3a\x9e\xbe\xf4\x3c\xa7\xf2\x5e\x7a\xfe\x76\x64\x79\xa4\x32\x21\x23\x3d\x7e\x83\x66\xab\xa8\xaf\xc9\xe0\x32\x33\x4c\xfa\xad\x9a\x0d\xb5\x9b\x76\xa4\x73\x79\xd9\x96\x8c\x4c\x8d\xea\xf6\xab\xef\x6c\x3c\xc3\xcd\xd9\x7e\x66\xdd\x87\xcc\x87\x67\xf6\x9f\xd9\xce\x9f\x79\x67\xd7\xf9\x1a\x4b\x6d\x5e\x15\xbf\xa3\xae\xb6\x6d\xb7\xa6\xc5\xd4\x9c\x59\xcb\xd5\xd4\x8a\xcd\x2d\x9a\xdd\xe9\xed\x09\xb5\x5c\xf9\x1f\xb7\xff\xb8\xf4\xa9\xf2\xd2\xa7\x1d\xdf\xfe\xaa\x09\x6b\x04\x35\x7c\x4f\xc1\x28\x16\xee\xd1\x01\xa0\x2a\xad\xb7\x11\x74\x44\x5d\x56\x15\xb4\xb0\x79\x26\x4d\x5e\x49\x9e\x23\x9f\x83\x2b\xe8\x56\xe4\x97\x95\x17\x88\x4c\x5d\x55\x75\x2d\x0f\x3a\xad\x62\x25\x39\x99\xf2\xe8\x43\x77\xb2\x5a\x6f\x23\x39\x9e\xd2\x2a\x56\xa2\x8e\x08\x04\xca\x06\xf4\x00\x7d\x2f\x58\x67\x11\x2b\xdd\xa3\x4d\x05\x79\xf9\x66\x0e\x7f\xc3\xdf\x14\xf9\xf9\xa6\xc2\x3c\xc6\x94\x57\xe2\xc8\xe7\xf1\x1e\xdc\x53\xe4\x3b\x0a\xc5\x72\x4d\x6d\x55\x75\x1d\x07\x7a\xb8\x47\xc8\x03\x1b\xd8\x5e\xb8\x07\x7a\xe8\x66\x3d\x6a\xd4\xdb\x28\xb9\x41\xf1\xcf\x06\x3d\x51\x74\x46\x76\x56\x3a\x87\x7a\xbc\x47\xd4\xf5\x6e\x4a\xdc\x43\x3d\x29\x1b\x09\x62\x69\xb9\xa3\x8c\x87\xdf\xe0\x37\x85\xc3\x21\x96\x94\x33\x62\x79\x61\xbe\x83\x87\x7b\x78\x4f\xe1\xc8\x2f\x31\xe5\x69\x3c\x6a\xec\xb4\x51\x78\xbf\xd7\x09\x0f\x56\x53\xbd\x49\x3e\x51\x0f\xba\xc0\x03\xff\x4d\x52\x83\x6e\x2f\xab\xfa\xdd\x2b\xce\xa2\x61\xc9\x1a\xb8\x88\xa6\x13\xdc\xce\xe9\xe6\xe7\x5e\xd4\x7c\xbe\xfc\xd8\xb8\x51\x1a\x78\x81\xfd\x2b\x01\x02\xbc\xc0\x46\xb3\x5c\x17\xb9\xbb\x70\x77\x72\x2b\xa7\xc2\x19\xe3\x07\xae\x8b\x64\x22\x07\xee\xbf\x30\x9e\x4f\x4e\x2c\xdc\xb0\x41\x83\x2b\xc8\x4f\x13\x4f\xbc\xf8\xac\x46\xf5\x1b\x7c\x46\x5d\x7b\xc7\xfd\x59\x2b\x07\x2b\xc8\x4e\x47\x67\xcd\x7e\x0e\x4d\x0b\xd6\xe0\x45\x5c\x02\x59\x2c\xba\xbd\x8f\x3d\x48\x08\x82\xf7\x37\xb1\x50\x40\x81\x3b\x80\xd6\x05\xe2\x8f\x6c\x6f\x8a\x53\xd5\xf1\x20\x55\x8f\xa1\x88\xf5\xb8\xff\xc3\xf6\x83\x5c\x76\xfc\xc9\x97\xae\x26\x72\x3e\x1e\x32\x29\x08\x27\x61\x53\x2b\x4c\x84\x28\x98\xaf\x91\x44\x72\x0c\x9b\x6f\xb1\x5a\x2d\xdc\x81\xe4\x55\xad\x4b\x98\x7c\xea\xf4\xdc\xcb\xcd\x4d\x65\xae\x7a\xde\x37\x04\x32\x29\x69\x08\x69\xa8\x6f\x32\x37\x33\x0f\xfc\xcf\x96\xac\x4a\x5c\x9b\xcc\xab\x8e\x07\xd9\x2c\x16\x5b\x3e\xf3\x04\x15\x88\xac\x98\x0f\x13\x31\x0a\x36\x25\x72\x18\x4e\x62\x2c\x2c\xc3\x29\x5d\x2c\x4c\x81\x58\x4e\xe2\x49\x55\x8f\xe1\x6a\xeb\xc9\x8f\xbf\x92\x5f\xa0\x0e\x0a\x3a\x41\x0f\xb7\x29\xd0\x43\x67\x88\x47\x2d\xcb\xe9\xde\x8f\x2c\xfe\x7b\xfd\xa2\x21\x9b\xed\x22\x02\x5e\xc8\xa8\x86\x60\x16\xd5\x5a\x0c\xf2\x8a\xa4\xa4\xf6\x76\x42\x2e\x15\xad\xc5\xa0\x2e\x98\xc3\x86\x35\xfe\xcd\x85\xcd\x73\x1a\x3a\xe9\xff\x93\x6f\xda\x5f\x8e\x69\xdc\x7f\x1d\xd3\xfe\x1f\xdc\xd2\xfe\xa7\x53\x1a\x0c\x3b\xc0\xca\xcf\x55\xfe\x17\x7c\x90\xed\xf5\xd3\x54\xd3\xbb\x28\x2e\x5a\x52\x77\x11\xbf\x7f\x3d\xb6\x3f\xaf\xf5\x18\xfc\x22\x6d\xa6\xb8\xa2\x00\x1c\x6c\x97\x47\xa4\x21\x16\x7e\x62\x31\x96\xd3\xa2\x61\x2c\xe5\xd7\xc3\x17\xb2\x8c\x99\xc3\xb6\x77\x91\xdf\x50\x78\x1f\x78\x4a\x80\x15\x94\x47\xad\x55\x9c\x94\xa5\x98\x2f\x8a\x84\x0b\x6c\xc2\xce\xd8\xd8\x84\x84\x58\xee\x7f\x96\xfc\x6a\xf2\xd9\x13\x2f\x7e\x9a\xc8\xf9\x1b\xe0\x24\xe5\x69\x20\x3f\x6d\x3d\xe1\xbe\xa6\xf1\x88\x1e\x75\x0c\x85\x22\x01\xf3\x29\xde\xdf\x19\xcf\x82\xde\x27\x12\x81\x7b\x00\xf5\x55\x16\x45\x98\x20\x9b\xb4\x7f\x4f\x6f\xd0\x23\x62\x14\x3d\xf9\x41\xe0\xca\x50\xca\xa3\x47\x3d\xed\xd7\x8d\xa6\xe4\x13\x28\x86\xfe\xf9\x33\x0c\xef\xff\x49\xdd\x0b\xc5\xfe\xdf\xe4\x10\x6a\xd0\xff\x09\xc7\x2e\x76\xcd\xa2\x3c\xa2\x4f\x47\xd7\x66\x55\x67\x70\xd1\x44\x46\x56\x56\x06\x1f\x4d\x66\x54\x67\xd5\x72\x5d\x44\x6d\x75\x75\x2d\x8f\x22\xb8\x67\xb0\xff\x3f\x2a\xfd\x7f\x5c\x1e\xc7\xbe\x4c\xf1\x28\x6a\xbd\x37\x60\x39\x3b\x9b\xb2\x50\x5a\x6f\x10\x09\x6a\x2d\x31\x25\x86\xd2\xa2\xac\xae\x7b\x0c\x4f\xb1\x45\x6c\x1c\x15\xe0\x5c\x16\xfe\x45\x54\x60\xe7\x18\xd4\x3f\x07\x6e\x43\x05\xf3\xff\x27\xef\xe3\x58\x95\x72\xda\x64\x0a\x45\x7f\x27\x2c\x0f\xa8\xde\xf1\x93\x28\x49\xf7\x02\xa5\x32\x2b\xda\x41\x94\x75\x6e\x9f\x5a\x1b\xda\x18\x40\x0f\xe8\x46\xf5\x08\xb2\x2e\x80\x23\xe0\xee\xc5\x11\x18\x01\xea\x6e\x37\xa5\xa2\x74\x5d\xbd\xbb\x99\xaa\x82\x97\x24\xb1\x3d\x86\x42\x37\x74\x12\xaa\xc4\x5d\x4b\x59\x9f\xae\x8b\xc2\x4e\xd8\x13\x88\x76\xed\x65\x0e\x86\xf5\x9a\xed\x32\x7f\x37\x59\x50\xf7\xe2\x4f\xf4\xa6\x8e\x16\x55\x9e\x46\x98\x4c\x4d\x67\x1f\xd8\xf1\x36\x87\xdd\x55\x62\x97\xed\xf8\x70\xd5\x1f\x27\xed\xa5\xae\x52\x87\x4d\x09\x4f\xa3\x48\xc8\x86\xfc\x74\x16\xd4\x9e\xa8\xf3\x2c\x04\x07\x32\xc3\x40\x37\x1b\x80\xd7\x92\x3a\x69\x95\xa7\x31\x00\x00\x3a\x96\x42\x37\x46\x91\xb1\x8b\x03\x06\xfe\x1f\x27\x03\x16\xfe\x96\x2d\xa9\x8b\x63\x35\xbe\x28\xd2\x48\x41\xc0\xa4\x27\x90\x84\x01\x30\x00\x88\xfa\x80\x91\x6f\xa6\x1e\xfc\x06\x5d\x1c\xd5\x78\xa0\x17\x3a\x4f\x0d\x6a\xe9\x51\xaa\x1b\xa2\x60\x37\x25\x40\x54\xb7\xcc\xaa\xa1\x88\x95\xa2\xce\xb3\xaa\x3f\x0c\xff\xe5\x40\xe5\x31\xa0\x8e\x54\xfd\x61\xf0\xab\x3d\x7a\xfa\xc1\x2c\x56\x79\x0c\x3d\xea\x7e\xf1\x90\xcd\xb6\x13\xda\xd0\x46\x79\x26\x47\xc9\x33\x39\x4a\x9e\xc9\x6e\x12\xee\x05\x66\x72\xbc\x16\x83\xda\x7b\xe3\xcc\x85\x76\xd0\x81\x18\x0f\x62\xbc\x14\xc2\xb6\xf7\x95\xc5\xb6\x6a\xb7\x96\x34\x48\x6e\x5a\x10\xda\xb1\xb3\x8b\xc3\x7b\xed\xa8\xef\x52\x44\x13\x78\x14\xee\x29\x2e\x49\x8f\x50\x23\x08\x8c\x22\xa2\xe3\xbb\x7c\x51\x84\xea\x1a\x46\x11\xa8\x03\xbd\x62\x04\x11\x1f\xaf\x40\x5d\x7b\x3c\xa8\xf3\x48\xd4\x6d\x55\xa0\x9a\x04\xdd\x56\x45\x1e\xaa\xe3\xe3\x51\x47\xb6\xc7\x2b\x54\xbb\xbb\x09\x90\xeb\x42\x94\x2f\x2a\x3a\xbe\x8b\x80\x28\xa2\x5b\x7a\x84\x7a\x99\x00\xb9\xe9\x2e\x02\xf4\x5d\x70\xaf\x5d\x01\x9d\x5d\x42\xbb\x10\x08\x92\x0f\x24\xc8\x09\x96\x1f\x5a\x6f\xe4\x78\x56\x8c\x30\x99\x99\x36\xf7\xf4\x65\x5e\x08\x7c\xbe\xd6\x80\xe8\x53\x13\x5e\xf9\x8d\x47\x35\xe8\x14\x9e\x4e\xb2\xab\x3d\x1e\x74\x8a\x1e\x1d\x11\x8f\x6a\x85\x4f\x2f\x1f\xba\xa2\x15\xe8\x96\xe5\xe2\x14\x94\x65\xa2\xeb\x77\xc1\xc5\xa0\x1a\x75\x0a\xd4\xc1\x5b\x6c\x58\x20\x3a\x42\x47\x27\xca\xba\xb1\x88\x6e\x32\x91\xf5\xaa\x93\x58\x74\x4b\x22\xb8\x93\x64\xab\x11\x44\x6f\x54\x64\x6f\x10\x85\x41\x7e\xce\x6e\x42\xae\x8b\xee\x00\x6a\x9d\x1b\xdc\x44\xac\xfc\x22\xba\x49\x28\xa3\xa4\xce\x48\xd6\x9f\xfb\x99\x37\x23\xf8\x88\x77\x71\x88\x87\x84\x28\xfa\x3a\xe5\x63\xa5\xc0\x7f\x4e\xaa\xbc\x40\x8c\xa7\x24\x75\xbf\xff\x75\x2e\xac\x97\xa8\xd2\xbb\x38\x44\xfa\x4e\x72\xd3\x76\xb9\x96\x9d\x0a\xf3\xdd\x87\xfe\xde\xc5\xd0\xc1\x82\x9e\x7e\x8d\x95\xd4\xa1\xaf\xb1\xf2\xb9\x17\x02\xe7\x3c\x51\x74\xb4\x6c\x7d\x46\x53\x61\x3d\xf7\x03\x7d\x4a\x9f\x87\x78\x48\xaf\x9e\x16\x0b\xca\xe3\xa9\xbf\x77\xf2\xa0\x42\xa5\xf4\x79\x6f\xfb\x9f\x52\x8b\x16\x29\xf2\xf3\x0b\x4c\x79\x9a\xbc\x52\x93\x23\x9f\x93\x58\x1f\x2b\xa9\xa8\x07\xe7\x4c\xa5\xb2\x2a\x71\x7c\xd1\xce\x00\x07\x4d\xd2\xe7\x32\x07\xf7\xe8\xde\xce\x4f\x05\x8a\x9e\x4e\x3a\x9a\x0a\x83\x61\xb0\xb6\xd7\x6b\x20\x93\x95\x3a\x6b\x58\x68\xa3\x3c\x6e\x89\xec\x45\x78\x0d\xe4\x85\xf0\xb8\xff\xcc\x7b\xd5\xe3\x8e\x61\xa5\x4e\x22\x2a\x7a\xfa\x7a\x88\xa1\x24\x71\x14\xb5\x27\xfa\xca\x0d\x8d\xd4\xf9\xa1\xac\x34\x74\x8f\x00\x5d\x74\x57\x17\xa8\x21\x8d\xea\x2b\xcf\x83\x00\xf4\xe5\x72\x29\x0a\x44\xda\xeb\x5e\x2c\x8b\x73\x9e\xed\x71\x2f\xa3\xfc\xba\x18\x36\xde\x73\x8f\x7e\x99\xe2\xbc\x6e\x98\xce\xfa\x75\x64\x1d\xdb\xe3\x36\x04\xd4\x1a\x3d\xad\xf5\x9c\x24\x30\x6a\x04\xf1\xc6\x95\x95\x37\x39\x2d\x31\x85\xb8\x79\xe5\xd0\x49\xbe\x9b\x54\xbd\xd3\x13\x3a\x82\x86\x2d\x14\x90\xf2\x5d\x08\x5d\xa0\xee\x82\x79\x14\x14\x50\x21\x30\x99\x4a\x90\x75\xd8\xa8\x1a\xd6\xef\x36\x50\x5e\x9d\x9b\xf2\xb8\x21\x89\xf5\xbb\x7b\x99\xf6\xb8\x3f\xa4\x7a\x72\x85\xb7\x21\xea\x6d\x8f\xd8\xdd\x2e\xeb\xb9\xdd\x92\xbb\x3b\x44\x5a\x0b\x6a\x7a\x45\x4c\xcc\x0a\xf8\x8a\xe2\x60\xad\x4c\xef\x13\x0d\x94\x47\xe7\xa6\x24\xb1\x97\x33\xd4\x79\xbe\x95\x97\x4a\x0e\xb6\x50\x3c\x74\xd6\xdc\x62\x65\x83\xa0\x47\x24\x7b\x17\x3f\xf1\x2a\x7b\x88\xf5\x88\xda\xd0\xc6\x09\x6c\x64\x63\x8a\x85\xda\x4f\x49\xc1\x6c\x00\x3a\xab\x9d\xf5\xaa\x25\x75\x3b\x1b\x48\x2c\x15\x0c\xd7\x1f\x5c\xd0\x86\x9e\xdc\xcd\x7a\xd5\x1e\xdd\x6e\x36\xac\x11\x75\x20\x2e\x02\x11\x2c\x20\x4a\xb7\x53\xfb\x76\x41\x13\x7b\x90\xd5\x7a\x67\x3d\x38\xa5\x03\x51\xa5\x0f\x92\x9a\x61\x00\x2d\xab\x0e\x2f\xcd\x99\x3b\x4d\xee\xf6\xf2\xe9\x33\x1f\x73\x92\x05\x57\xd3\x2f\xb2\x7e\x9d\x47\x47\xbf\xc8\x6a\x43\x0f\xf8\x2c\xf4\xe5\x39\xa7\x5f\x8a\x65\x5f\x3a\x3d\xe7\x32\xf4\xb0\x3d\x0b\xbd\x69\xf4\xcd\xa9\x57\xc6\x24\x52\x63\xae\x4c\xbd\xc9\xa9\x5e\x0c\x5a\x43\x69\x43\xcb\x7c\x16\x99\x4c\xed\xd1\xd1\x70\x83\xe2\x54\x6d\x41\xd0\x43\x49\xad\xb8\x9a\x86\x3e\x43\xee\x60\x1f\x7c\xf4\xf1\x21\xd8\x07\xd6\x51\x9c\x2a\xd1\x00\x7d\xee\xfc\x02\x8f\x3e\x80\x38\x51\xd3\x91\xd4\x03\x60\x32\x2d\x31\x3c\x00\x4d\x26\x45\xd1\x10\x6a\x00\x72\xd5\xef\x1c\xfc\x07\x79\xdf\xc8\x33\x78\x8d\x41\x3d\x88\xc4\xf7\x94\x4f\xf4\x89\x7f\xdf\xdb\x11\x7d\xe2\x07\xf2\x22\xa3\x27\xa5\xa9\xb0\xf7\x19\x5f\xd2\xea\xa2\xd5\x85\xab\x79\x6b\x66\x41\x7a\xa6\x26\xad\x22\xb3\xa1\xaa\xac\xcc\x59\xc6\x55\x37\xba\xda\x5d\xcd\xca\xd3\xa0\xfe\x18\xa2\x21\x52\x13\x16\x89\xea\x1f\x83\x05\xd0\x43\x94\xac\x3c\x47\x81\x5e\x56\x7b\xdc\x34\xac\x60\x3d\xea\x7e\xb0\x82\x85\xa8\x7e\x78\x16\x77\x2f\xc5\x42\x0e\x27\x11\x58\x88\xbb\xdf\x82\xb3\xf0\xc4\xf7\xc0\xc0\xf8\x0b\x5d\xb9\xa6\xf3\x7c\xde\x89\x13\x85\x27\x99\x93\x27\x4a\xca\x4f\xf0\xe2\x85\x0f\x2b\x2e\x30\x30\xfe\x7b\x64\xf0\x09\x1e\xf4\x30\x8d\x86\x21\x6b\x80\x1f\x01\x0a\xae\xee\x94\x78\xfa\xb4\xe6\x6a\xc6\xd5\xb8\x8f\x38\x1c\x35\xe4\x95\x27\xf1\x9f\x7c\xd3\xa8\x91\xce\x27\x98\x81\x03\x0d\x5b\x87\xf0\x3f\xe0\xc3\x43\x2e\xe1\xd3\x4c\xdc\xf4\x8c\x29\x53\x34\x73\xc5\x39\x75\x3a\x6e\x04\x86\xae\x41\x0e\x87\x68\x30\xc4\x85\xff\x7c\x67\x08\x87\xcd\xc0\x4a\xb4\x1e\x6a\x19\xa8\x84\xfb\xdb\xa1\x01\xc2\xf9\xe3\x77\x5d\x40\x41\x48\x20\x5b\x99\xda\xab\x06\x9a\x95\xc4\xc0\x3c\x09\x99\x4d\x81\xbe\x17\x8b\x0c\x3e\xa0\xde\x58\x79\xe8\x24\xef\xd5\xc1\x72\x79\xae\x7c\x47\xf9\x75\xf2\xec\xd3\xfd\x1f\x00\x46\x02\xe8\x13\x81\xd5\x30\xd0\xda\xcb\x2c\x14\x05\x82\x5b\x7e\x97\xee\xd2\x59\xa6\x1c\x93\x81\xc3\xb7\xf0\xbe\x62\x55\xdc\x4b\x1b\xde\x60\x7a\xdc\x44\xf2\xc6\xb2\x1d\xd5\x62\xa5\x58\xc1\xc3\x5b\x70\x5f\xd1\xd9\xf1\xf1\xee\x93\x8c\xd7\x4d\x34\xed\x32\x6f\xe6\xb5\x28\xc0\x78\x7a\x54\xe4\xc2\x69\x73\x78\x14\xf1\x23\x85\xe7\x07\x58\x4e\x49\x6e\xf8\x8e\xc2\x28\x52\x2a\xc2\xf1\x74\x8b\xa5\xd9\xd8\xc8\x75\x6d\x9a\xbe\x6b\x3a\x83\xb2\xfa\x9e\x1d\xc0\x26\x79\xc0\x96\xd7\x4d\xdc\x82\xe0\x13\x1f\x9f\xe6\xe1\x6d\xb8\xaf\x68\xed\xa8\x7f\xf3\x70\x6f\x92\x46\x54\xc3\x9b\x94\xa4\xfb\x8c\xd5\x86\x26\x48\xab\x68\x57\x47\xda\x9e\x0d\xae\x38\x57\x4c\x9a\x21\x4e\x19\xb9\x61\xe8\x54\x0c\x65\x30\x74\xe8\x95\x3f\x36\xf0\x86\x8e\x98\xfa\x0d\x86\x38\x43\x5a\xac\x2b\x4e\x89\x63\x8f\xc3\xe3\x18\x04\xcf\x31\xf0\x1c\x3c\x0e\x41\x30\xf6\x38\xef\x33\x49\xd3\x9f\xa1\x36\xb1\x92\x0e\xe2\xa8\x40\x83\x70\x8e\x86\xb1\x8b\xf0\x71\x08\xc2\xe7\x18\x7c\x0e\x1f\xc7\x20\x1c\xbb\x88\x37\xc4\xd5\xc7\x76\x18\x76\x1b\xf6\xd6\xbb\x3a\x94\x7f\xec\xfe\xf9\x0a\x84\x32\x10\xfa\xf3\xd4\xc8\xdd\xbc\x2b\x6e\x6f\x5a\x87\x6b\xb7\xab\x7e\x8f\xa1\x43\xe9\x33\x49\x5f\x3f\x43\xa1\x1a\x2e\xb3\x9f\xb1\x16\x4a\xd2\xc5\x50\x7e\x35\x61\xa4\x3c\xea\x51\x94\x4f\x94\x74\xcf\x04\x8c\x21\x5d\x34\x74\x4a\x51\xa0\xeb\x2b\xc8\xa6\xd8\x49\x10\x55\x47\x3c\x6e\x49\x47\x3f\x4b\xa1\x0e\x75\x84\x2a\xad\x80\x02\x1d\xea\xc8\x28\x4a\x75\x04\xd4\x4b\x58\xd0\x81\x8e\x28\x60\x51\x07\x3a\x59\xd1\x50\x93\x92\x3b\x7a\x7a\x00\x1d\x95\x56\xa5\xcd\x66\x41\x49\x71\xaa\x23\xf0\x08\xc5\x83\x6c\x64\xab\xd2\xc0\x2c\x9f\xe8\x51\x13\xa0\xa0\xfe\x42\x78\xee\x07\xd4\xb1\xcf\x6f\xf1\x90\x48\x4c\xba\x05\xd4\x62\xe8\xc7\xc0\x1c\x8a\xef\x7d\xee\xa0\xee\x4d\x83\x12\xc8\x88\xf2\x33\xfb\x57\x16\x94\x9e\x76\x83\xa4\x96\x42\x69\xd1\x5c\x66\xe2\x66\xc8\x55\xee\x41\x3e\x8b\x7a\x02\x48\x76\x04\x69\x2a\x33\x8b\x1c\xe8\x6f\xcb\xf7\x7b\xef\xcf\x3a\x5e\xd1\x17\x05\xf9\xac\xaa\x7f\x50\x90\xff\xde\xdf\xea\x79\xee\xdd\xa6\xfc\x7f\xab\xf7\x5f\x1a\xe8\xc3\xaa\xb6\x4c\x09\xfa\xbf\x9f\x1a\x65\x0f\x82\x3e\xec\x0c\x79\xd8\xfe\x22\x02\xb1\x5b\x6e\x3b\x71\x70\xd0\x5f\xbf\x47\xfd\x33\x08\x46\x51\x68\xc6\x50\xf2\x7f\x32\x05\x6a\xdf\x20\x5a\xeb\x31\x78\xd5\xd0\xc8\xca\xb6\xfa\x61\x59\x49\x25\x62\x59\xbe\x27\x10\x1a\xd1\xc8\xf6\x62\x9f\x40\x0b\xa8\x2b\x40\x2d\x25\x81\xba\x1c\xd4\x7d\x41\x0d\xd7\x59\x79\x4e\xa8\x55\xcb\x0f\xb2\x52\x2e\xbd\x61\x26\x3e\x3c\x1b\x43\x98\xb5\x71\xe5\x55\x9b\xf9\xcd\x55\x8a\x93\x91\x8f\xbf\x83\x4f\x32\xaa\x2f\x31\x02\x27\x2d\x98\x85\xe1\xbc\xd4\x4d\x76\x81\x12\x9e\xfe\x10\x68\x06\x78\x50\x2e\x7c\xe3\x0f\x3e\xf9\xd0\x31\xe3\x49\xb8\x43\xf9\x7c\xa4\xd6\x7b\xd2\xd3\x46\xab\x96\xa7\x50\x9c\x2a\x67\xe9\xf6\xd5\xfb\x93\x39\x2d\x86\x4d\xa3\x54\x5f\x6a\x43\x7f\x25\x41\x43\xc1\x69\x4a\xb5\x1c\x32\x58\xd5\x97\x69\xb9\xb9\x29\xc9\x1a\x7f\x06\xa9\xca\x81\xd7\xd8\x8a\x12\x87\x93\x87\x5a\x56\xb5\x1c\x9e\xa7\x54\x5f\x36\xba\xaa\x9a\x5a\x34\x7f\x72\xfc\xd8\xbb\x95\xd2\x28\x50\x97\x01\xfd\x77\x9e\xf7\x7a\xdc\xd2\x6e\x1a\x1f\x35\xe2\xa0\x65\xa8\x9c\xaf\x84\x99\x24\x90\xa7\xe1\xf1\x63\x10\xe6\x52\xa2\x8e\x94\xc6\x85\xe2\xa3\x16\x1c\xb0\x00\xa9\x59\x4a\x98\x43\xc2\x43\xef\xc3\xd0\xb3\xd0\xd7\xa1\xc4\x45\xa4\xc7\xed\x5b\xf3\xd7\xfd\xc6\x6d\x72\xb8\x12\x79\x98\x4d\xe6\x94\xe6\xd8\x73\x1c\xca\xd3\x48\xe2\xa3\xa7\x70\x44\x7e\xbe\x60\x66\x60\x0b\x59\x5c\x5b\x63\xab\x61\x60\xc4\x0f\xf3\xe7\x00\xc9\x57\xe6\x57\x5a\x2a\x0b\x94\xa8\x27\x41\xb3\x1a\xc6\x5c\xbc\x7d\x44\x89\xaf\x91\xd2\xf3\xa1\xa3\x16\xe2\x98\xc9\xa8\xd9\xaf\x84\x85\x64\xfe\xb6\xed\x45\xad\x70\x87\x52\xf5\xc5\x39\xf2\xa8\x40\x0f\x9d\x42\xfd\x6d\x40\xe4\xe1\x50\xbd\x0a\x1a\x4a\x65\x84\xd3\x14\x64\xb0\x7f\x0d\xc7\x9f\x83\xa1\x7a\x55\x1e\x8e\x37\xe1\x79\xea\xc1\x60\xc8\xf2\x2f\xb8\x52\x4b\x6c\x0d\x91\xae\x4b\xc7\x8f\x52\xde\x2e\xdf\xb2\xb9\x6c\x8f\x6e\x34\xe5\xd5\xc1\x70\x16\x86\xe1\x43\x5a\xc5\xd2\xe0\x23\x5a\x72\x48\x88\xe4\x07\x96\xbe\x2b\x6b\x35\x6c\xb8\xac\x03\xdd\x65\x23\x16\x1d\x07\x82\x8a\xf0\xad\xf7\xad\xbf\xcd\x46\x48\xeb\x7d\xeb\x7f\x67\x8f\x1f\x57\x48\x37\xbd\x27\x68\x7b\xad\xb1\x2e\xc3\x3e\xb3\x36\x3c\xd3\x9e\x6e\xb4\x64\xf8\xfe\xa1\xf5\xfe\x1e\x6e\xc9\x70\xa6\xd7\x5a\x3e\xc8\x08\xaf\xb1\xd4\x39\xed\xb5\xd2\x3f\xb4\x8a\x7f\x86\x7b\x06\xfb\xf9\xa3\x7f\x83\xd8\xd4\x6b\x15\xaf\xc2\x86\x10\x8f\x5a\x5a\x4c\xfb\xfa\x4b\xfd\x61\x0c\x1b\x21\xf5\x97\x06\x28\x2e\x9d\xa7\x2c\x54\x3b\x0d\x83\xd2\x61\x3d\x8e\x80\xa7\x38\xec\x0b\x34\x2e\x72\xe3\xce\x7a\x25\x54\x9f\xa7\xa0\x94\x84\xf8\x0c\xe0\x16\xde\x18\x79\x07\x43\x3b\xf0\x95\x04\xdc\x6e\xcd\x12\xb3\xab\x2d\x4a\x6b\x49\x89\x50\xc2\x54\xb8\x1c\x2e\x3b\x5f\x56\x09\xa3\xe1\x2c\xac\xd5\x84\x05\xd2\xa1\x36\x4b\x9f\xd2\x8b\x97\x56\xcc\x38\x87\x80\x97\x61\xd2\xec\x5d\x0a\xef\x02\x12\xc6\xe0\xd5\xb6\xd7\x2f\x18\x41\x5a\xa0\x80\x05\x15\xf4\xe1\x43\xd9\x6f\xbe\x2e\xfa\xac\xee\xf0\x40\x2e\xd4\xd6\xec\x8c\xaa\x74\x46\x20\xd3\xd3\xb3\x13\x73\x78\x4c\xf6\x2d\xf1\x59\x5f\x7c\xdd\x94\xbd\xea\xd0\xca\x08\x29\x08\xff\x18\xeb\x2b\x54\xac\x30\xd7\x24\xed\x62\x5c\x55\xa5\xe5\xd5\xbc\x34\x1f\x0c\x81\xbc\xa9\x79\xd5\x55\x05\x2e\x66\x57\xcd\xf6\xc3\x66\x7e\xac\x54\x08\xf7\xe1\x0f\xc5\xdf\xbd\x3d\xd3\xb5\xa1\x2d\x74\xe5\x36\x4b\x5b\x6a\xbd\xb2\x32\xf0\x45\xd6\x68\x2c\xb2\x98\x64\x13\xcc\xaf\x4e\xca\xc9\xde\x54\x96\x10\x91\x50\xb6\x2d\xb5\x8d\x91\xdc\x3e\x37\xb1\xa9\x61\xcb\x4e\x33\x67\xb5\xdb\xad\x76\xa6\xa5\xa9\xb2\xc9\xc5\x7b\xd4\x45\xac\x22\x2c\x12\xbe\x0d\x68\x37\xd2\x29\x10\x69\xe9\x3b\xe9\x3b\x85\xef\x3b\xd2\xaf\x3e\x12\xf8\x4d\x4a\xa7\xfc\x51\x73\x59\xd4\x7b\xbe\x23\x40\x00\x6b\x45\xa5\xd0\x90\x5b\x19\x91\x53\x91\x2a\xe4\xe4\xa2\x15\x85\x70\xff\x77\xa0\x27\x74\x54\x20\x4f\xe7\xf3\x2c\xe8\xfd\xf7\xe0\x10\xeb\xb9\x87\x7a\xa2\x8d\x0d\xa4\xe9\x1c\x27\xab\xd7\xa8\xee\xd6\x86\x9e\xec\x6e\xef\xee\x2b\x74\x0b\xa0\x13\xba\x65\x91\xa2\xeb\x56\x75\x43\x67\x17\x5d\x4b\x59\xa8\xd0\x5a\xca\x13\x08\xc9\x94\x97\x53\x15\xc8\xab\xe9\xc9\x43\x52\x5f\x6a\xe5\x1b\x7c\x77\x3f\x08\x63\x39\x55\xf7\x2e\x6a\xda\x81\x99\xa7\x37\xf0\x45\xb8\xae\xff\x0a\x9c\x35\x7b\x71\xd6\xfc\x8c\x85\x5b\x94\x2a\x90\xf2\xc9\xd3\xbb\x0f\x7c\x70\x59\xa3\xea\x86\x5c\x36\x50\x89\xf3\xbf\x4f\xaa\x60\xee\x86\xb5\x33\xa7\x69\xfa\x7f\x3d\xb6\x8e\xba\xbc\xf6\x83\xb9\xbb\xb9\xed\xe4\x4f\x27\x5a\x60\xcc\x71\x0e\x26\x9f\x02\xf1\x8b\x12\xf0\x2b\x7b\x29\x03\x0e\x95\xba\xd9\x29\x52\x54\x97\xa4\xeb\x82\x6f\x7b\x7d\x29\xe1\xdb\x3f\x4b\xaa\x4c\x83\x14\x0d\x75\x5f\xb0\xf0\xdc\x6a\x1a\xae\xb1\x1c\xba\xc9\x64\x16\xf5\x52\x27\x8c\x65\x55\x06\x83\x36\xf4\x0e\xaa\xe9\xcf\x36\x5d\x99\xff\x2e\x87\xdf\xc2\xb7\x19\xb5\x69\x95\xa9\x15\x11\xe9\x98\x07\xad\xb8\xe3\x81\xe3\xa4\xd4\x87\x8d\x89\x89\xb6\xc5\xec\x8d\xc0\xed\xd0\x8a\x79\xe9\x15\xa9\x95\x69\xb5\x19\x11\xaa\x4c\x03\x7c\x83\x37\x1f\xf8\x25\x7e\x76\xe5\x2f\xa7\xc4\x77\x4f\xb5\x5d\xf9\x4c\xe3\xf3\x7b\x62\x69\xd5\xc3\x41\xb9\x0d\x39\xf5\x19\xb5\xf8\x0d\xdc\x0c\xef\xf5\x84\x9c\x3c\xf5\x2f\x37\x48\xdd\xfc\x4d\x53\x27\x6b\x26\xb7\x4d\x3d\xa5\xe3\xe0\x5b\xfc\xb6\x36\xa3\x3e\xa7\x21\x57\x6e\xb9\x0e\xcc\xd8\x0a\xad\x10\xcf\xb6\x38\xb7\x33\xdb\x5b\x02\x6e\x98\xdb\xb1\x15\xf2\xea\x14\x9e\x47\xc6\xc3\x58\xd6\xd7\x29\x75\xfe\xf7\x9e\xa4\x11\xf0\xdc\x17\x6c\x58\xcf\x7d\x41\xd6\xd8\x74\xe0\x0e\x16\x3c\x6a\x59\x6b\xd3\xc5\x50\xd1\x92\x9b\x80\xc1\xec\x93\x2c\xd7\xe5\x53\x47\x13\xb1\x09\x09\xb1\x3c\xaa\x61\x12\x8b\x6a\xad\x22\x88\x86\x68\x16\x75\x4f\xb1\x20\xc6\x51\x3d\xf7\x1b\x53\x82\xff\x23\xcd\x0e\x91\x44\xe8\x0c\x5c\xd0\x3f\xc5\x42\x3f\x8a\x6f\x83\x0f\xd9\x3d\xb6\xcd\x3b\x63\x19\x74\x13\xb1\x9b\x13\x62\x6d\xfc\x0e\xbf\xa8\x88\xb5\xb5\x25\xec\x61\xe0\x27\xaa\x6d\xe7\x1e\x1b\xbf\xc3\x23\x2a\xc2\x04\x98\x28\x6d\x82\xbe\x31\x30\x09\xba\x61\x48\x5f\xad\x62\x1e\x8c\x41\x02\xfa\xaa\x4e\xab\xb6\xdd\x60\x55\xa7\x61\x0b\x4b\xa8\x3e\xc3\x49\xc0\x92\xc7\x29\xcf\x63\x9e\x6f\x68\xec\x3b\x11\xb3\x88\x2a\x18\x08\x37\x1a\xc0\xac\x81\x88\x21\x37\x70\xf0\xb8\x59\xf1\x1b\x20\x9e\xea\xa8\xdb\xcf\x9c\x7c\x2b\x76\x01\xaf\x3a\x2d\x91\x54\x5a\x71\x36\x57\x92\xa8\x90\x5c\x44\x18\x8a\xd0\x17\xfa\xc1\x44\x78\x19\x86\x40\x1e\x4c\xea\xab\x55\xcc\x7f\xd0\x91\x5b\x25\xdd\x60\x55\x6e\xd8\xc2\xca\xbd\x10\xc7\x29\x8f\x6a\xd1\x5f\x9d\x0c\x92\x3b\xc9\xfb\xab\x93\x8d\x71\x10\x4f\xed\xae\x3b\xd0\xdb\x89\x44\x52\xe9\xb6\x2c\xae\xb4\xb7\x8b\xc0\xba\xdf\xbb\x29\x0b\x05\x14\xed\x17\x09\xf8\x56\x52\x2b\x3c\x22\xe1\x99\xe0\x99\x41\x1f\x4d\x59\xb6\x73\x11\xe3\x17\x89\xf5\xb1\x99\x9b\xb7\xf2\x3d\xea\x1e\x71\xc3\xba\xbc\x37\x1a\x96\x45\x2c\x6b\x3c\x9a\x70\x9c\xf1\x88\xc4\xbe\x3d\x35\x3b\x5a\x78\xaf\xda\x2b\xee\xde\x5f\x7e\x32\xf5\x68\x44\x58\x64\x6d\xca\xf6\x14\x40\x88\xee\x2b\x25\x43\xb4\x2a\xf1\x20\x2b\xbd\x4a\xdf\x9b\xf3\x13\x92\x1c\xaa\x74\xc3\x5f\x66\x62\x37\x36\xb5\xe8\xf9\x84\x5d\xf9\x87\xdf\xd4\x5c\x77\x5d\xaf\xbc\xc6\x15\x3b\xcb\xce\x96\x94\x2a\x8b\x49\xd5\xbe\x7c\x24\x90\x48\x42\x92\x99\xf6\xc2\x8e\xeb\x3c\x3c\x04\x21\xed\x10\xa6\x81\xe0\xb1\x67\x07\xf7\x1f\x3e\x27\xd0\xc6\x4f\xba\x97\x35\xb1\xc9\x1b\xb7\xea\xb9\x84\x8d\x2b\xf2\x57\x31\x13\x26\xb8\x2a\x9f\xe5\x8d\xc5\xb3\xcb\x0a\x4a\x94\xaa\xc4\x1e\x91\xb4\x96\x08\xc5\x56\xae\xb2\xa8\xae\xb0\xbe\xa8\xae\x30\x22\xe7\xda\x75\xc3\x75\xe6\xcd\xc3\x8e\x9d\xbb\xf8\x96\xe6\xa6\x5d\x7b\x2e\x0d\x7f\x17\x54\x1a\x20\x7f\x3a\x73\xef\xd7\xaf\x67\x63\x30\x87\x61\x18\x12\x8f\x0f\x69\x26\x7c\xb2\xf9\xf2\x6f\xbf\x35\x38\x7f\xe5\x6c\x2e\x97\xe0\x62\xec\xa4\xed\xb3\xf8\xab\xff\xd6\x7c\xd2\x76\xfc\x0b\x0e\x1e\x6a\xc7\x10\x08\x63\x20\xf8\xec\xd7\xbf\xf2\x61\xbe\xfb\x9b\xd8\x60\x61\x1f\xa5\x4e\xb4\x50\x1e\x37\x0d\x21\xb2\x4e\xb6\x84\x82\x79\x2c\x07\xea\x1f\xe4\x02\x4c\xa3\xbe\xa4\x50\x94\x44\x1a\xa6\xc1\x51\x0a\xa7\xc1\xfc\xc0\x07\x6e\x9c\x06\x83\x70\x10\x4c\x03\x33\xfb\x60\xa7\x38\x1c\x1e\x0d\x86\x5b\xac\xfa\x19\x68\x91\x6e\xd2\xa6\xbd\xf9\xfb\x0f\x68\x1e\x34\xf2\x7c\xf5\xd4\xd6\x19\xdc\x9d\x3b\x0a\xef\xcf\xd2\xcf\xf4\x5d\x76\xc2\xf5\x70\x20\x28\x2d\x3e\xa9\xc5\x27\xc3\x6f\xb3\xd7\x27\x84\x57\xe6\x34\x08\x95\x95\x50\x06\x65\xe1\x1f\xaf\xfc\x22\xe1\x86\x49\xf9\x25\xf5\x80\x78\x09\xf5\xc2\x4b\xf5\xed\xb3\xb8\xee\x6e\x45\x6e\xc7\x3e\xf3\x7e\x06\xcc\x2c\x0f\x6a\x12\xfc\xe0\x57\xf8\x1e\x85\x70\x1a\xc2\x96\x23\xf5\x2d\x72\x0c\xcc\x0f\x6c\x19\x7b\x82\x3d\xc1\x8a\x30\x5f\x6e\x6f\x4c\xbc\xd7\x0d\xba\x10\xaf\x5b\x72\xd3\x38\x18\xd5\xf8\xaf\xc8\xf1\xdc\xc4\xd7\x26\x2c\x5d\x98\xa8\xd4\x86\x26\x49\x3a\xbf\x9a\x04\x9d\x47\x8c\xa1\x7a\x77\x57\x45\xd2\x37\x41\xfa\x1a\xeb\xb7\x19\xb8\xf2\x02\xb1\x48\x14\xc5\xe2\xf2\x87\x07\x6d\x73\x49\x5f\x43\xbd\x34\x41\x13\x16\x59\x48\x79\x45\x2b\x25\x05\x53\x03\x59\xbc\x6f\x09\x28\x9b\xdd\x7d\xa1\xb3\xbb\x1b\xa2\x50\xdd\xad\xda\x27\x89\x5a\xc5\x94\x04\xca\xab\x6e\xa7\x9d\x05\x62\x9e\x83\xb3\xe7\x9b\x8b\xcd\x4c\x51\x91\x60\x2d\xe4\x7d\xba\x11\x8a\xec\x42\x43\x4e\x96\x06\xdf\x25\xc4\x06\x7b\x63\xb3\xa6\xd7\x0c\x8d\x77\x26\x54\x6f\xe1\x54\xdf\xe3\xb2\x57\x1f\xc7\x37\x2c\xc6\xcc\xf8\xca\x75\xbb\x32\x95\x16\xd1\x59\xe4\x64\x9a\x9b\xe5\xf5\xa4\xd8\x06\x04\x6c\x86\x58\xa6\x1d\x43\x08\xec\xb7\xe6\x09\x0c\xc3\x81\x1a\x7f\x27\x4c\x62\x3d\x9d\x24\x3c\x85\x0f\x01\x8d\x43\xda\xb8\xbb\x20\x92\x59\xae\x9c\xaa\x42\x4e\xd2\x8d\x50\xfc\x05\xbe\x6a\x77\xf0\xaa\x7d\xe5\x8e\x52\xd1\x29\x8b\x63\xbd\x96\x58\x19\xdc\xae\x25\x56\x86\x68\x15\x8d\x5e\x37\x5d\x1b\xd8\x35\xa7\xeb\x32\xab\xd2\xf1\x0e\xce\x9b\x88\xc5\x58\xc2\xcd\x9d\x33\x7b\xc6\xeb\xd3\x7c\x7d\x52\xc3\x8d\x56\x63\x7e\xbe\x09\xf5\x3e\x75\xb8\x39\xb7\x38\xd3\x69\xe8\x8a\x0e\xef\xcd\xd5\x53\x52\x22\xd8\x4a\x78\xd8\x79\x03\x3a\xb0\x63\x1c\xee\x2c\x34\x94\xe4\x96\x9b\x22\xba\xa2\x15\x40\xb0\x0e\xbb\xad\xc4\xce\x4b\x6a\xd0\x8b\x0e\x87\xd3\xe6\x8c\x68\x90\xfa\x5c\x3e\x77\xe1\xec\x99\xd3\x11\x60\x04\xd3\x77\x90\x04\x37\x7a\x61\x85\x67\xc2\x17\x7d\x05\x2d\xf1\x05\x7e\x0e\x9f\xab\x6e\x68\x89\x8f\x3d\xa5\xf4\x0e\x08\x4f\x80\x88\x89\xff\x51\xfe\x67\x12\xf6\x79\x0f\x19\x46\x8b\xa1\x04\x3c\x81\x5f\xc0\x25\x16\x0e\x10\xf2\xdf\xe7\x88\xbd\x6d\xb9\x29\xb5\x7c\x5d\x8a\x3d\x3e\x2f\x16\x5f\xf6\xbb\xc3\xe1\x1b\x42\x75\x09\x9e\xf1\x94\x06\x52\x33\x94\x78\x1b\xa1\xe4\x5b\xca\xdb\x1f\xfa\xd3\xb0\x9e\xf2\x2d\x96\x16\x87\xc3\x18\x56\x0a\x1c\x63\xd8\xbb\x83\xc3\xe1\x25\x0a\xcf\xe1\xb9\x70\x38\x87\xe7\xe0\x25\x2a\x42\x6a\x92\xfa\x07\xa2\x11\xff\xa4\xf5\xac\xea\xa5\x1d\x7c\x57\xa6\x84\x73\x70\x2e\x1c\xcf\xc1\x39\x59\x17\xba\x7b\x17\x62\xd8\x08\x69\xb1\x6f\x71\x80\x32\xf8\x48\x6f\x4a\x87\x00\x61\x88\x36\xb4\x58\x0a\x10\x62\x2f\x09\x9e\x83\xf5\x54\xc4\xe0\xbb\x01\x25\x6a\xb1\xb4\xf8\xef\xa4\xd0\x04\xfd\xff\x4e\xeb\x39\x05\xc6\xbf\xf3\x7b\xf7\xae\xcc\x2d\xf4\xf2\x09\xe7\x64\xd2\xbb\x83\x7b\x09\x17\xca\xcc\xde\x97\x0c\x37\xe1\x65\x98\x01\x53\xe1\x2d\x38\xc0\x7a\x7b\xbc\xcf\xd3\xfe\x71\x44\x35\xce\x50\x78\xc2\x89\x45\xbe\x4e\xc4\xa1\x0a\x6b\x01\x89\x3d\xbf\x24\xc3\x2e\x05\x4c\x25\x2a\x31\x12\x16\xbe\x01\x8b\x4e\x36\x41\x9a\xc2\x27\x11\x4b\xa5\x5d\x0a\xaf\x92\xd0\xa2\x05\xde\xa2\x41\xad\xf5\xae\x96\x2e\xe3\x38\xe9\x2a\x8c\x03\xb5\x56\x51\xaf\x08\x6b\xf4\x84\xc0\x71\x98\x07\xc7\x83\x2b\xb4\xc4\xf7\x21\xb0\x03\x86\x53\xb3\xf1\xb8\x42\x1b\x7a\x84\x58\x87\xf3\x14\x5a\x9c\x4e\xcc\x79\x50\x9e\x8e\xdf\xf9\x32\x70\xac\xef\x59\x18\xbb\x13\x1e\x57\xe0\x71\x62\x1a\x4a\x9e\x59\xd8\xe0\x39\x02\x0d\x50\xaf\x55\x8c\x55\x84\x35\x4a\xc1\xb2\xb5\x2a\x9b\x8e\x43\x25\x83\x6c\x49\x8a\xd1\xa0\x93\x0c\x30\x54\xf5\xbe\x57\xa7\x55\x04\x25\x50\x1e\x77\x8f\xac\x1d\xdd\x23\xfe\x9e\xfc\xf7\x97\xc7\xc3\x47\xe3\x23\xf8\xc2\x18\x5c\x9c\xa8\xf4\x30\xa0\x23\xa3\x58\xb8\x4a\xa1\x0e\xc6\x13\x9f\x1e\x3e\x71\xfd\x47\xd8\x41\xad\xa6\x46\x9e\x98\xf0\xe9\x0a\x0e\xc7\x93\xaa\xab\xa8\x1b\x4b\xa1\x9a\x54\xbd\xff\x34\x05\x3a\x3f\x43\xe0\xe2\x56\x7c\xe1\xe6\x68\x78\xe4\x97\x5f\xc2\x45\x67\x49\xa5\xa5\x42\x59\x61\xc9\x2d\xcf\x61\xf0\x1e\xa1\x72\x3f\xce\xe2\x3d\x32\xa7\x3c\xb7\xc2\xc2\x59\x4b\x4b\xad\xa5\x01\x70\xe3\xef\xbf\x57\xe0\x1c\x18\x0d\x7b\xf0\x11\xf8\x80\x81\x0f\x02\x49\x38\xe7\xc0\x68\xfe\xfb\x27\x15\xf9\x65\xe5\xb0\x93\x52\xfd\x58\x61\x2f\xaf\xa8\xd4\x84\x05\xd2\xc4\x2a\xa6\xfc\x2d\x4d\xac\xb7\xd3\x23\xd2\x7e\x3d\xb8\x89\x6b\xec\xd3\x54\x17\x31\x85\x85\x41\x2c\x8f\xee\xf8\x07\xb0\x1c\x61\x90\xc7\x7a\x44\x98\x40\xc1\xe7\x54\x88\x57\xf4\xa8\xd7\xc9\x46\x5e\x2e\x25\x5b\x7a\x81\x54\x4c\x7f\x4f\x6d\x04\xea\x7e\xab\x28\x98\x2f\x8b\xe7\x61\xf2\x63\x17\x25\x35\x1c\x60\x25\xb5\xa7\x93\x5e\x11\xe8\xee\xbf\x87\x30\xad\xd7\x29\xd1\xac\x14\xc8\x7c\x2b\x5f\xf6\xe8\x42\x1f\xfc\x09\x3b\xc0\x7a\xb7\xc2\x9b\xc1\x02\x88\xf2\x31\x04\xae\x53\xd3\x59\xf8\xed\x09\xda\x66\x2a\x30\xe5\xc3\x47\x54\x65\xad\x95\xcf\x82\x55\x38\x01\x26\xe0\xaa\x6a\x65\x86\x2d\x07\x2e\xb2\x0e\xb1\x54\xb4\xc2\x87\x19\x60\x45\x6b\x2d\x7e\xa8\x94\xd4\x56\xda\x66\x2a\xcc\x33\xc3\x47\x54\x95\x4c\x20\x8d\xc1\xdb\x70\xdb\x37\x46\x26\xc8\x86\x8b\x6c\x59\x59\x89\xd3\x2a\xd5\x66\x48\x13\x7c\x13\x6a\x7d\xb5\x4a\x78\xd3\x3b\x2f\x92\x5d\xf7\xff\x8e\x92\x2f\xa9\xfd\x5d\xb4\xaf\x13\xdd\x8a\x7c\xa3\xa1\xd0\xc0\x18\x0c\x25\x76\x23\x9f\x5a\x91\xdb\xd8\xac\xf1\xa8\xc9\xe6\x8a\xc6\x86\x0a\xae\xc1\xb5\x4d\xa8\xcf\x95\x3a\xd1\x1d\xde\x60\xa8\x48\xd1\x6b\xf4\xb9\x29\xa9\x06\x2e\xac\x11\x57\x68\x09\x27\xbe\x09\x6f\xf6\x3d\x05\x9d\xd8\xf9\xa0\xa0\xb2\x7b\x45\xef\x25\xda\x77\xc9\x77\x09\x2e\xe1\x25\xe9\x92\x74\x49\xe1\x6b\xf1\x8f\xa0\x81\x63\x03\xc1\xb9\xf2\x94\xec\x91\x7a\x5a\x5a\xde\x14\x5a\xb6\x46\x04\x72\xfa\xcb\x93\xab\xa5\x9e\x3e\x76\x4c\xb8\xbe\xf8\x38\xf6\x85\xc7\xc2\xa7\x4c\xc1\x30\x61\xca\xd5\x29\x57\x05\x08\xbb\x7a\x55\xa9\x6a\xc4\xc7\xe0\xb1\x45\xc7\x27\x08\x8b\x17\x45\xa8\x62\x7b\xf8\x1e\x6e\xd1\x22\x61\xc2\xf1\xc5\x11\xf0\x18\xf6\xbd\x7a\x15\xc2\x84\xab\x53\x22\xae\x4e\x11\x30\x6c\xca\x14\xe8\x8b\x7d\xc3\x8f\x2d\xbe\x2e\x1c\x3f\xe6\xe5\xbd\x91\xe1\x61\x8b\x59\x10\xbd\x62\x00\x55\x18\x0c\x54\x8f\x9a\x80\xf3\xac\x57\x4d\x3c\xd8\x66\xc7\xfb\xa0\x0f\xb8\xa3\xca\x0b\x8c\xfa\x86\x85\xf2\xe8\xe7\xb2\x7e\xf7\x68\xca\xe3\x86\xcb\x94\x4f\x4d\xe7\x04\x30\x94\x02\x78\x4a\xbd\xfb\xd0\xc3\x29\xbf\x7b\x0e\x1b\x16\xc8\xbf\x15\x0c\xd7\xa9\x10\x6f\x89\x77\x02\xed\x6a\x2a\x68\xcd\xac\x47\xb7\xa4\x0e\xdf\xba\x73\x91\xb0\x35\x01\xdd\x3e\x75\x78\x66\x5a\x61\xa2\x33\x59\xa9\x77\x35\x65\x6f\x63\x40\xe7\x57\xa3\x9b\x30\x19\x0b\xcc\xf9\x3c\x46\xa1\x2e\xcf\x68\xcd\xb1\xe7\x46\x18\xec\x15\xe6\x0a\xc6\xa3\x1b\xcf\x7a\xee\x81\x8e\xdc\xd6\x54\xd5\xec\xe2\xc3\xfc\xb9\x32\xd3\x81\x0e\xda\xe1\x43\x36\x37\x37\xcf\x60\xe1\x2d\x06\x5b\x76\xb9\x09\xa2\x50\x17\xde\x9b\x73\x1e\xdc\x7e\x35\xea\x88\x2d\xc9\x59\xc9\x06\xde\xa8\x2f\x49\xac\x49\x03\xb9\xe3\x5e\xac\x41\x90\xd9\xa9\xa9\x2f\x6d\x35\x34\x2b\x9b\x0c\xc9\xd5\x5b\x18\xd4\x79\x7e\x23\xea\xb2\xab\xd3\x39\x79\x5c\x12\xbc\x37\x20\x21\xc4\xf3\x42\xaf\x08\x44\x2f\x78\xff\x26\x02\x63\x30\x26\x5c\x8a\x91\x62\xfe\x26\x02\x8d\xd0\x14\xc9\xa2\x5a\x0a\x61\xdf\xf3\x88\x50\x1b\x2c\xfc\xf9\x2b\x44\x1a\x2a\x4d\xa1\x17\x2c\x50\xcc\xeb\x1e\xf1\x1e\x79\xe2\x84\x02\xaa\xa5\x03\xb4\xb9\x3c\xbb\xc8\x64\xc2\xc3\x78\x38\xdc\x64\x2a\xca\x2e\x37\x97\xe5\x55\x15\x8b\x22\x1c\x86\xc3\xe1\xa2\x58\x5c\x95\x57\xa6\xc4\x56\xff\xcb\x34\x76\x42\x27\x21\x75\x4a\x9d\x81\xcc\x74\x5d\x5d\x81\x13\xdf\x7d\xb7\x6f\xdf\x07\xc2\xbe\xf5\x11\x30\x12\x47\xee\x5b\x2f\xcc\x5c\xbf\x3e\x02\x8e\xc0\x11\x99\x01\xd8\xe3\xcd\x08\xb8\xdd\x05\x8e\xbd\x2e\x07\x49\x99\x7a\xbd\x91\x2b\xcc\x33\x15\xe5\x31\x19\x99\x8e\xca\x5c\x1e\x8e\x52\xbe\x5d\xbe\x5d\x7f\x5b\x0b\x76\x49\xbb\xe0\x28\x95\x56\x67\xd9\xe1\x6c\x89\x68\x76\x36\xd7\x6c\x67\x24\x7d\x35\xe5\xd3\x93\x20\x4a\x62\xa0\xe5\x28\x59\x95\x89\x0a\xcc\xd7\x7b\x10\x15\xe2\x35\x4a\xd3\xe9\xde\xb4\x3f\x79\xa6\xe2\x12\x33\xbf\xd5\x99\xd9\xbc\x5d\x03\x51\x24\xbe\xde\x7f\xd3\xcb\xb3\xf8\x17\x27\xa4\xe1\xf0\x36\xcc\x2f\xce\xce\xcb\xce\xb1\x28\x8b\x0a\x2c\xd6\x02\xc6\x64\x2a\x2d\x37\xf3\xf9\xe5\x38\x16\x16\xc0\x32\x0d\x08\x17\xe0\xba\x74\x99\x83\x28\x72\x7b\x4d\x73\x8b\x93\x6b\x76\xee\xb0\xd4\xa5\xc1\x3d\xbc\x27\x2f\x8a\x4a\x98\x0e\x5f\x47\xb2\x69\x2c\x74\xf6\x7e\x58\x84\xce\xc0\xfe\xb2\xa4\xa3\x41\x24\x41\x44\xb5\x02\xd4\xd2\x1a\xda\x27\xa2\xa8\xf0\x1d\x20\xe1\x3a\xa5\x80\x4e\x18\x48\x0f\xa4\xf2\x58\x6d\x68\xba\xe7\x2e\xdd\x64\x48\xae\xdc\xca\xf8\xd5\xc4\xd6\xe4\x9c\x64\x03\x6f\x48\x29\x4e\xaa\x92\x5f\x04\x5d\x78\x46\x45\xbd\xb1\x91\x69\xac\x77\xd6\x06\xb0\xab\x75\x55\xf5\xc5\xdb\x0d\x8d\x11\xc0\xf8\xe7\xbc\xce\x06\xc8\xa5\xf1\xb4\xab\xb1\x68\x7b\xb6\xfc\xf2\xea\xc2\x6b\x73\xd3\x9c\x29\x4c\x4a\x9a\x31\x23\x80\xa8\xad\xcb\x4e\x2b\x4a\x72\xa5\x44\x24\xbb\x9a\x72\x5a\x18\x8f\x9a\xe8\xb5\xb8\x81\xc1\x0a\x99\xdc\xeb\xf6\xa8\xe9\x46\x63\x7d\x46\x05\xe7\xd3\x81\x3b\xad\x2a\xa9\x38\xc5\x10\x91\x6c\xc8\x49\xde\xaa\xf1\xab\xc9\xad\x95\xc9\x4d\x06\xae\xd1\xb0\xbd\xb8\xbe\x4a\xd2\x81\x3b\xbc\xb6\xc2\x59\xdf\xa8\x01\x9d\x4f\x4f\x3f\x4b\xf5\xe8\x46\xb2\x5e\xdd\x12\xd6\xab\x0b\xb8\x77\x6f\x65\xe5\x29\x95\x06\x65\xf0\xd2\x3d\x78\x19\xcc\x90\x12\xfc\x33\x94\x86\x78\xd7\x42\x3a\x5d\x54\x6e\x29\xcf\xb3\xe7\x95\x1a\x6d\x79\x85\x4a\xeb\xb4\xad\x51\x0c\x4e\xc6\x41\xff\x81\x51\xd1\xbc\xf4\x2f\xa2\xba\xd2\x55\x5d\xc2\xb7\x40\x68\xb1\x58\xe4\xcc\x2f\x8f\x28\xcb\x37\xd9\x8d\x8c\x6f\x05\x51\x74\xc0\xda\x51\xd2\xae\x94\xb2\x88\x9a\x07\x55\x88\x62\xb1\xd0\x99\x5f\x16\x51\x9e\x6f\x2a\x35\x32\xbe\x58\x02\x86\x5d\x84\xfe\xb7\x61\xd2\xe5\x8f\x32\x6c\x4c\xad\xa5\xd6\x59\x5a\x7b\x08\xc6\x84\x17\x97\x5b\xc5\x82\x32\x4b\x99\xd9\x91\x57\xac\xb4\x15\x8c\x6d\x1a\xc8\xe0\x09\x14\x71\x16\xee\x7e\x9a\x1f\x36\x94\x42\x62\x10\x7b\x91\x28\x8a\x15\xd6\xd9\xe2\x95\x33\xe0\x20\x85\x8a\xde\xf0\x8b\x1f\x09\x7c\xeb\x2b\x28\xc5\xd9\x70\x9e\x81\x87\xbf\x6f\xb7\x95\xf2\xd5\x76\xb1\xa6\xa0\x46\x19\x90\x18\x1b\x70\x03\x24\x48\x7d\x60\x81\x44\x43\x66\x5f\xa0\xa1\x54\x7a\x1a\x52\x54\x59\x5e\xbb\x34\x70\x2e\x8b\xe3\x08\xd5\xb1\xc7\x59\x9c\xe1\x7b\x9a\x54\x65\x49\x7d\xe0\x0c\x39\x8e\x82\x7f\xcd\x63\xf1\x0c\xc4\x13\x77\x3f\xfd\x08\x14\x77\xbe\x9e\x6e\xb5\x71\x0e\x8b\x58\x58\x6e\x13\x6d\x65\xa5\x8e\xb2\x5f\x41\x15\xee\xac\xb4\xd6\xe7\xba\x94\xf6\x7c\xa4\xe1\x61\x5c\xca\x60\x19\xbe\x86\x13\x30\x8d\xc7\xad\x23\xc9\xc7\x59\xfc\xd7\x20\xf6\x47\x9f\x6a\xb8\xcc\xe7\xf0\x41\xac\x77\x36\x0c\x67\xfd\xb9\xc0\x53\x1f\x41\xd9\xcf\xb0\xe4\x1e\x38\x42\xbc\xeb\xe1\x37\x1a\xf2\x71\xed\x35\x7c\xed\x32\x87\x03\xde\xc5\xb0\xb7\x7e\xd7\xdc\xbe\xf9\x21\xa8\x60\x38\x3c\x12\x69\xb5\x71\xe5\xf9\x62\xa1\xb3\xd8\x69\x2b\x77\xd8\xc5\x6b\x30\x24\xbc\xac\xa2\xa8\xda\xe8\x2a\x28\xc5\x20\x78\x08\x57\x34\x2b\x61\xda\x3c\x16\x19\x22\x23\x2b\x3b\x9d\xc7\x57\x48\x5c\xb7\x06\x07\xe1\x48\x7c\x4d\x83\xa5\xa0\x1f\x0d\xaf\x4c\xe3\x80\x99\x0f\xd4\xd2\x11\x1a\x54\xf4\x5f\x30\x0c\x5f\xc2\x48\xd0\xd8\x8a\xb8\xfc\x32\x53\x89\xc9\xda\x9b\x28\x7f\x10\x32\xe1\xa6\x5c\x5b\x86\x33\xd7\x9e\x0f\x6a\x8c\x84\x9c\x0d\x4a\x9c\x4a\xa6\x57\x67\xd7\x72\xc0\x8c\x67\x61\x2a\x09\xb1\x7b\x60\x08\x8c\x85\x95\x9a\x30\xbf\xbf\x31\xc5\xfb\x0c\x3c\x0b\x83\xe0\xd9\x60\xc1\xdb\x2f\xc4\xdb\xcf\xfb\xce\x5c\x16\x9f\x27\x0c\xef\xa6\xbc\x1d\xdf\xa9\x84\xec\xf1\xec\xdd\x79\xac\xdf\x3d\x94\xc2\x88\xde\x07\x04\x83\x09\x88\xbc\xb5\x6e\xca\x7e\xde\x37\x7a\x28\x35\x78\x10\x2b\x3d\x4f\x60\x70\x02\x3e\x34\x1b\xa7\x31\x18\x2a\x0f\x91\x8a\x7c\xe0\x04\x35\x07\x97\xc1\x50\x7c\x09\xc6\xe2\x7c\x65\x9e\x43\x2c\x70\x32\xb0\x80\xa8\x74\x95\xb9\xec\xbc\xc3\x55\x54\x95\x27\xe2\x08\x98\x89\x63\x40\x87\xc3\x60\x0c\xa4\xb6\xc2\xe3\xf0\xd8\x2e\xd0\x29\x61\x92\x3c\xc0\x59\x8d\x29\xd0\x03\x13\x6f\xc0\xa4\x60\x69\x20\x18\x42\xa4\x5f\xfa\xd5\x56\xdb\x58\xf8\x12\x0e\x91\xe3\xa8\x5f\xe7\xb1\x78\xe8\x06\x1c\x1a\xcf\xfe\x46\xf6\xa6\xfb\x8f\x27\xe0\x82\xf4\xa9\xdd\x29\x54\xe4\x8b\x11\xce\x7c\xa3\xc3\xc0\xe0\x3c\x22\x37\xd7\x9c\x6b\xe1\x71\x9e\xef\x99\xb4\x15\xc9\xab\x32\x56\x46\x64\xee\xcf\x3c\xb8\xf5\x2d\x8c\x97\x9e\x0b\x77\xe5\x1b\xca\x72\x19\x7c\x83\x30\x18\xf2\x8d\xf9\xbc\xc5\x28\xe4\xda\x8d\xf0\x89\xef\x6a\x38\x6e\x80\x83\xd4\xc0\x41\x2c\x74\x8e\x83\x50\x6a\x90\xfc\x03\xbf\x84\x43\x2c\x4c\x21\xc2\x7c\xb9\x8d\x29\xa0\x07\x1d\x50\x10\x27\xe9\x20\x2e\x18\x44\xc8\x94\x4e\x82\x31\xc4\xbb\xc3\xbb\x82\x46\xcd\xc8\xd1\xd8\x9f\x93\xa5\x01\x21\x80\x9b\x84\xfe\x3f\x8e\x46\x0d\x0f\xc6\x7e\xe0\xc4\x59\xf0\x0a\x36\x70\x82\x6f\x2f\xf9\x38\xeb\xff\x07\x7c\xc1\xe2\xb0\x41\x2c\xe8\x91\x42\xfd\x50\x0a\xd5\x81\xdf\x3a\xb9\x9f\x89\xe3\x59\xd0\x49\xc5\xf2\xfb\xab\x9e\xc7\xfa\x8a\x81\x82\xef\x09\x68\x80\x59\xf0\x0a\x38\x79\xd9\x12\xf1\xa8\xe1\x33\x56\x4b\x06\x85\x48\x2e\xf8\x81\x2e\xb2\x16\x16\x69\xac\xc5\x42\xb1\xb5\x78\x0a\x9c\x0c\x87\x31\xc4\x1e\x50\xd3\x98\x4c\xc4\x83\x5a\x01\x47\x08\x18\x8d\x6a\xba\x03\xd4\x8a\x8f\x89\x3d\xb2\x40\xfc\xd0\x37\x85\x2e\xb2\x16\x3d\xa0\x29\x79\x16\x4e\x84\xc3\x38\x62\xb7\x4c\x93\x41\xc4\xc9\x34\xc7\x09\xe9\x11\x94\xb5\xda\xe9\x84\x4c\x07\x83\xe3\x58\x0c\x21\x6e\xc3\x4f\x25\x62\x91\x2b\x20\x25\x8c\x76\x23\x83\x2c\x91\x95\x63\xcc\x2e\xe4\x9f\x44\x9f\xc2\x17\x4c\x0c\x03\x9f\xa2\xaa\x20\xd7\x99\xc5\x60\x5f\x22\x3b\xc7\x98\x5d\xc0\x0f\x47\x9f\x02\x91\x18\x2d\x5f\x29\xcc\x91\xaf\xb0\x84\xd1\x68\x31\xe7\xf3\xf9\x79\x45\xc6\x12\xe3\xb7\xf8\x53\x38\x06\x8f\xa6\x60\x00\xb1\x1b\xd5\x0a\x9c\x3a\x9a\x82\xb5\x04\x44\xf9\x7c\x8a\xec\x92\x4a\x63\x15\x03\x63\x88\xea\x00\xc6\x36\x4c\x94\x7c\x0a\x58\x47\xc0\xb3\xf2\xb5\xd2\x07\xd7\xaa\x2a\x03\xd7\x9e\x91\xaf\xc5\xc1\x70\xd6\x97\x6b\x81\xd7\xf1\x55\x88\x86\x5b\xf0\x24\x9c\x83\x57\xf1\x79\x18\xdf\x17\x44\xa8\xc7\xd1\xf0\x24\x84\xc1\x93\xaa\x68\x6d\x68\xa9\x57\x4d\x67\xc0\xab\x38\xfa\x7d\x5c\x5c\xab\x04\x3b\x3e\x49\xaa\xe6\x61\x11\xb9\x66\xb5\xd5\xba\x9a\x07\x41\x2e\x47\xa3\x9d\xb4\x6e\xd8\x20\x6c\x64\x04\x12\x63\x6d\x0a\xd5\x4c\x7c\x86\x04\x45\x71\x51\x91\xa0\xf9\xb0\x21\x26\xde\xc1\xe3\x41\xb2\xd4\x21\x58\x1d\xbc\x25\x5f\xb0\x30\xbe\x21\x64\x6a\x61\xee\xc6\x95\x8c\x50\x5c\x84\x8a\x62\x6e\x23\x46\x2b\x54\xd1\xb0\x94\xd8\xb7\xd7\xba\x97\xc1\x72\x52\x25\xc0\x93\x60\x27\xac\x6f\x76\x0a\x07\x18\x2c\x25\x55\xd1\xf0\x24\x94\x13\xe0\xaa\x82\x57\xce\x37\x43\x41\x1d\x2c\x78\xea\x1b\x1c\xb2\x47\xa9\x7a\xf3\xe6\x91\xf7\xbe\xc8\x81\x08\x25\xc6\xfb\xde\xa4\x71\x1e\x7e\xde\x34\x90\x83\xdb\xe4\x6f\xf0\xf9\x4e\x5c\xcc\x4f\x93\x12\x69\x7c\x01\xb7\x35\x44\x71\x70\x8e\xfc\x06\xb6\xb5\xe2\x0c\x3e\x0c\x45\x2d\x19\xf4\x2d\xe5\x15\xbd\x22\x2d\x6d\x24\x4c\x55\xa6\x0a\xa3\xd3\x37\x52\x1a\x19\x6e\x74\xe6\x8a\xd9\xa2\x12\xd5\x3e\x1b\x2d\x75\xfa\x1f\xa0\xde\x6a\x3d\x27\x75\xac\xb7\xd3\x27\x17\x0f\x9d\xe4\xc3\x7a\x1d\x5f\xe4\xd7\x8a\x08\x52\xdf\xd0\x2a\x8e\x79\x8f\xd0\x32\x79\x2f\x75\x84\x6f\xa3\xb4\x91\xec\x6d\x54\xe9\x4b\xc4\x67\x02\x49\x99\xf8\xff\xd5\x1c\xe9\x53\xfb\xf5\xb4\x8b\x02\x5d\xe8\x83\x3f\x61\x91\x28\x02\x21\xed\x03\x02\xc4\xdf\x61\x10\x3c\x04\xfb\xa1\x0f\x8c\x60\xbd\x3e\xd0\xb0\x3d\xb5\xc3\x58\x55\x8f\x01\xd6\xb3\x9e\xcf\xf0\x9f\xf0\x1b\x5b\x64\xe2\xb3\x8b\x14\xc5\xa4\xcb\x05\xcb\x58\xc8\x22\xe1\x51\xea\x5b\x6f\x0f\x64\x50\x84\xca\x3f\x05\x96\x06\x5a\xfb\x6f\x2b\x7f\x36\x3c\x82\xfd\x0d\x34\x6c\xde\x9f\x6d\x79\x47\xa3\x15\x32\x28\x58\x4a\x3d\xad\x0d\xfd\x01\x7e\x63\xad\x26\x3e\xbb\x50\x51\x42\xba\x9c\xb0\x8c\x25\xe5\x96\xb2\x08\x78\x94\x0a\x83\x11\x94\x47\xdf\x3d\x8c\x95\x69\x3a\x51\x2d\x2b\xaf\xcf\xb0\x1e\x37\xd4\xb1\x7e\xf5\x33\xac\x47\x0d\x75\xac\x4f\xf7\x8c\x6c\x00\xd6\xb1\x28\x3e\xc3\x82\x08\xc3\x59\x18\x41\x69\x43\x4f\xc6\xcf\x7d\x70\x66\x3c\xeb\xd3\x83\x3b\xd0\x86\x27\x4a\x52\xcf\x7d\x40\x21\x4f\x61\x8f\x6e\xee\x83\x86\xfe\x2a\xf5\xb6\x3f\x9c\x45\x51\x52\x52\x01\xfe\xe3\x52\x21\x89\x82\xad\xb0\x81\x42\x55\x6f\x2b\xa6\x4b\xf5\xec\x26\xcf\xaa\xab\x54\x98\x3c\x72\xde\x01\x72\xcd\x24\x4a\x1b\xfa\x15\x6c\xa0\xb4\x68\xec\xad\xb4\x16\x4d\x57\xa9\x36\xad\x62\x7b\x3d\x1b\x16\x29\xec\x62\x21\x2a\x44\x0a\x61\xe9\x98\x84\xcd\xb1\x31\x9b\x77\xec\xdd\xb3\x63\xe7\x5e\x78\x85\xe5\x20\x0a\xe6\xb2\xd8\x39\x96\xf2\xab\x9f\x62\xa1\x73\x14\x15\x00\x61\xa6\x7f\x1b\x73\x73\x20\x87\x6d\x44\x79\xbb\xd3\xe9\x6a\x52\xb6\x9e\xd8\x79\xe6\xba\xe6\x33\x01\xa6\xa3\x1e\xfe\x45\x71\x2b\x57\xe5\xce\x34\xcc\xce\x9d\x63\x78\x7d\xed\xda\x8d\x1b\xe3\x56\xc6\x2c\x5b\x31\x67\x04\xfe\x73\x7d\xa1\x72\x43\xe1\xe6\xcd\x1b\x34\x7e\x9a\x8c\x6d\xdb\xdc\x61\xe5\xf6\x58\xcf\xa5\x7c\x98\xac\x5c\x0f\x41\xc0\x2c\x85\x81\x4c\x2d\xf1\x29\x51\x57\x25\x94\x32\x37\x6d\x17\xb6\x1f\x7a\x67\xff\x91\xda\xf7\xf3\xaf\x6e\x6b\xa9\xdf\xed\xdc\xe7\x3a\x28\x1c\x34\xec\x6b\x3b\x58\xfd\x56\xd1\x71\x65\x55\x41\x9b\xa1\x9d\xeb\x38\xd0\x78\xfa\xa4\x26\x2c\xd2\xab\x86\x7d\x6c\x08\x88\x5e\x1d\xbd\x37\x61\x47\x6c\xcc\xe6\xcd\x31\xb1\x3b\x12\xf6\x7e\xc7\x42\x94\x4f\xa4\x9f\xa0\x38\xec\xbc\x45\x79\xd4\xd0\x49\x41\x67\x35\xe5\x57\x93\x5e\x3f\x0c\xa3\x5d\xed\xa5\x6d\x55\x9a\xe2\xe3\x59\x6f\x6d\x3a\xe8\xda\x27\x1c\x34\x1c\x34\xee\x4b\xdb\xbd\xa5\xc5\x71\x35\xe3\xfd\x75\x47\x56\xbe\x33\x63\xfb\x18\x9b\xb2\x20\x5b\x48\x67\x9e\x27\x32\x08\x1c\x88\xcc\xd2\xf5\x18\xc4\xbf\x96\xfc\x7a\x4a\xac\x55\x19\x67\xdd\xb4\x39\x56\xbe\x91\x0d\x3b\x36\xef\x2e\xe4\xf6\x15\x76\xe3\x3f\x0f\xcf\xd9\xbb\xac\x63\xe5\xae\x8d\x07\xd6\xba\x5e\xaf\x98\xe3\x9a\x5d\x31\xf3\xd0\x2a\xe5\x7e\x16\xf4\x02\x4c\xff\xec\xfa\xa6\x33\x49\x27\x78\x43\x93\xd1\x99\xd7\xae\x84\x36\xe2\xb7\x6f\x6e\xfe\x66\xe3\x4f\xa6\x9c\x89\xdb\xcf\x85\xa1\x1a\x42\x20\xf2\x7d\x50\xbe\x7b\xe3\xdc\x3b\x1f\x83\xfa\xa2\x94\xff\x63\x5f\x01\x12\x20\xea\x93\x5b\x17\x96\xdf\xae\xb8\x98\xdb\x65\xbf\x68\x79\xb7\xe2\x82\xe1\x6c\xe9\x85\x0b\x17\xaf\x43\x82\x6a\xaf\x7b\x9f\x77\x04\x64\xd3\x1b\x8c\x99\x69\x06\x83\xdd\x65\xe0\x40\x4f\xba\x5c\x2e\xbb\x8b\xa9\x77\x66\x6c\xe0\x71\x34\xa9\x2a\x18\x60\x87\xd7\x20\x8c\xee\x20\x3b\x5c\xb5\x4d\x4d\xae\x8c\x38\x2e\x8e\xf4\x3f\x06\xf5\x34\x66\xbd\xf4\x6f\xdf\xc4\x4f\xa4\x89\x5f\x10\xb0\x6c\x1e\xfd\x0a\xee\x26\x52\x64\x59\xcc\x98\x2c\x76\xa7\x95\xb7\x16\x0b\x62\xb5\x06\x9a\x67\xe0\x21\x32\xa9\x38\xa3\xd4\xc0\xa5\x39\xaa\x4d\x8d\xcc\xb6\x6d\xd5\x6d\xdb\xf9\x35\x17\x49\xb0\x83\x48\xef\x29\x6a\xb1\x54\x73\x3b\xf2\xd2\xab\x12\x99\xad\xfa\xec\xa4\x14\x1e\xc6\xbe\xe2\x33\x5e\xdc\x4b\x26\x36\x35\x67\x37\x33\xad\x75\x55\x3b\xca\x79\x7b\x75\xf1\xb6\xdd\x1a\x28\xad\xa5\xa7\x13\x49\xd6\xac\x02\x4d\x46\x81\xd1\x94\xc9\xe8\x0d\xb5\x1d\xfc\x79\x88\xf8\x94\x3c\x60\xde\x91\x5d\xcf\x6d\x4b\x4f\xac\xdc\xc0\xc4\x25\xe6\x6c\x49\xe3\xb3\xd3\xf2\x37\xaf\xd5\x20\x4d\xae\x2d\x4b\xa8\x4a\xe7\xb6\xd4\xb7\xe6\xec\x61\x3a\x76\x54\xb6\xd6\xf1\xe5\x15\xf6\xca\xe2\x6a\xa5\xad\xcc\x56\xd5\xa4\xf1\x2d\xf0\x7c\x42\x77\x18\xea\x52\x92\x8d\xe9\x71\x1c\x8e\x22\xe3\x9c\x19\x4d\x8d\xae\xda\x0e\x4e\x6a\xf3\x9d\xa2\x55\x69\x9f\xac\x1c\x27\x8c\x4a\x1d\xcf\xe5\xcc\x59\xb2\x72\xae\x59\x99\x85\x2c\x72\x02\xb2\x4c\xe0\x58\x8d\x2c\x3f\xb7\x6c\xc9\xa1\x9c\x33\xca\xd4\xaf\x84\xdb\x37\x34\x02\xf9\xb5\xed\x76\xfd\x97\x5c\xe5\xd9\xb7\x0f\x9d\x71\x28\xab\x41\x0b\x9c\x00\x2c\x03\x1c\x70\x42\x16\x68\xf9\xd3\xf9\x6f\xaf\xac\x9a\xad\xac\x7f\x46\x18\x35\x56\x23\x90\xfe\x02\x0f\x4f\xe3\xb2\x17\x60\x19\x69\xde\x9b\x75\x62\xeb\xc7\x59\x47\x33\x8e\x66\x1d\x55\xfe\x9b\x38\x89\x0b\xde\x81\x05\x8a\xab\x04\x2c\xf1\x3d\x42\xaf\x35\x6f\xca\x4e\xe7\xb6\xa4\x25\xe5\x6c\x60\xe2\x92\x2a\xb7\xa5\xf3\xd9\xf5\xe6\x9d\x07\x34\xd0\x8f\x3c\x50\xb6\xb3\xaa\x9e\xdb\x56\xb7\xbd\xb2\x83\xd9\xbd\x3d\x67\x4b\x3d\x5f\x95\x56\x96\xb0\x56\x83\xfd\x48\x98\x81\x0f\xd3\x07\xc9\x4d\x89\x5b\xb2\xb6\x30\x29\x59\x62\x9d\x99\x2f\xa8\x28\xaa\xdd\xae\x81\xa3\x17\x71\x1b\xa9\x7a\x48\x19\x94\x29\xe4\xd9\x8a\x38\x83\xcd\x61\x11\x99\xca\x2a\x67\x63\x35\x0f\x7b\x2f\xfa\x08\x52\x7a\x05\x4e\x47\xb2\x28\xc2\x42\x78\xfe\xec\x55\x20\xae\x5e\xfd\x01\x5e\xf8\xf2\x3a\xdc\xbd\x96\x9f\xda\xb7\x15\x36\xfe\x02\x0f\x4f\xfb\xe5\xdc\xe7\x19\xb7\x6a\xfe\x9d\x77\xdb\xf1\x55\xe6\xed\xaa\x8f\x2d\xb7\x4b\x6e\xde\x86\x10\x95\xdf\xbd\xd3\xbb\x02\x8e\xd0\x87\x73\x9a\x93\xb2\xb2\xcc\x59\x59\x1c\x9e\x22\xb3\xaa\xab\xcd\xd5\xcc\xf6\xca\xa6\x23\x3c\xdc\x86\xf5\xf4\x91\xac\xe6\x4d\x9b\xb2\xf4\xcb\xb9\x65\xb7\xc8\x9e\xc5\x50\x4b\xfb\x2e\x3c\x4e\xaa\xa4\x4f\x16\x4a\x17\x06\xfc\x00\xe7\x9f\x20\x61\x86\xef\x02\x7d\x8a\x5c\x1d\x13\x97\x1a\xcf\x24\xa4\x54\x6c\xcb\xe3\x2d\xd5\x85\xcd\x7b\x34\x12\xf3\xad\x2f\x88\x4c\x11\x0c\xb6\x42\x2e\xbb\xb8\xcc\x5c\xc1\xd4\xd5\x57\xed\x68\xe0\xa5\xb0\x6f\x7d\x26\x12\xbe\x87\xa1\xf4\xb2\xa2\x0d\xe6\x14\x2e\xc6\xb0\x25\x2d\x96\x89\xdf\x58\xb7\x6f\x13\xbf\xe4\x69\xcf\x88\x6f\x49\x15\x31\x3c\x08\x37\x91\x7b\x77\xee\xaa\xdb\xcd\xec\xd9\x96\xb6\xde\xc5\x97\xa5\x16\x6f\x58\xa6\xc1\x45\x24\xdc\x76\xd2\x09\x42\x6a\x91\x89\x2b\x4a\xcd\x4b\x37\x64\x2a\x63\xb7\xae\x4f\x5f\xca\x2c\x8d\xad\xed\x48\xe2\xd3\x5a\x8c\x07\x4e\x6a\xe0\x05\xf2\xa4\xb8\xbf\x7e\x1b\xd7\xb1\x7d\x4f\xed\x51\xe6\xc8\x9e\x8c\xb8\xed\x7c\xdd\x16\x71\xdd\x1b\x9a\x41\x38\x3d\x8a\x5c\x56\xad\xdf\xd5\x54\x59\xd1\x62\xe7\x6c\x76\x5b\xc3\x5e\xcd\xed\x1c\xc2\x77\xcf\x3b\x98\x5e\x96\xb3\x75\x53\x42\x76\xcb\x51\x0e\xd6\x93\x47\xab\x9a\x77\xb6\x55\xea\x97\x71\xb8\x9e\xf4\xac\xf1\xe7\xd1\xa0\x14\x20\x2c\x09\x42\xb9\xf4\xcf\x5f\x3d\x33\x59\x54\x36\xe0\x6b\x38\x4b\xc0\x99\x0c\xce\xc4\x59\x42\x2a\x46\xf3\xcf\x99\xa2\xe7\xa4\x4d\x52\x6e\xc1\x50\x2b\x86\xa1\x52\x23\x90\x48\x0a\xd8\x67\x3b\x86\x72\x75\x93\xce\xcf\xf9\x2c\x4f\x99\x02\xaf\xc1\x2c\x01\x66\x32\x30\x13\x66\x09\x8d\xf0\x1a\xff\x59\x79\xd7\x99\xfa\xcf\x95\xdb\x20\xd4\x06\x7d\x80\xd4\xf4\x64\x68\x43\x7d\xf4\x74\xac\x99\x06\x35\x8a\xfe\x44\xe3\xcc\xa6\xd7\x9a\x66\xb6\x3f\xd9\xf0\x92\xb8\x58\x89\x2d\xbf\x40\x0b\x09\x8f\x48\x03\x15\xd0\x88\x5f\xd3\x27\x4d\x07\xd2\xb6\x71\x1d\x5b\x62\x6b\x97\x31\xcb\x63\x33\xe2\xb6\xf0\x69\x5b\x4c\x6b\xdf\xd0\xe0\x54\xf2\x0d\x71\x6d\x7d\x12\x17\xb7\x6d\x4f\xc6\x11\xe6\xe8\x9e\xda\x8e\x6d\x7c\xfd\x36\xf1\xe0\x49\x0d\xdc\x84\x5b\xf4\x28\xdf\x63\x44\x42\x6a\x5a\x76\x3a\x93\x6b\x2e\xaf\x2a\x92\x25\x40\x45\xa3\x46\x0a\x19\xe5\xe3\xc8\x98\x92\xad\xf6\x2c\x6e\x8b\xd8\x98\xbb\x93\xd9\xdd\xd1\xf0\xe6\x5e\x5e\x47\xaa\x14\x41\x8d\xb7\x89\xc0\xa7\x64\x2d\x91\x02\x07\x58\xe9\x07\x8f\x87\x16\xac\x36\x1c\x0f\xfb\xb9\xc6\xdc\xf4\x96\x18\x06\xf3\x88\xec\x5c\x8b\x31\x9f\x37\x1b\x6d\xd9\x65\x39\x30\x16\xdb\xc3\xad\x36\x41\xb0\x32\xe8\xf0\xe9\xcc\x39\xb6\x1c\x87\x31\xc2\xe8\x70\x99\xab\x18\xc8\x23\xf6\xd4\xb6\x34\x55\xf2\x20\x48\xd1\xce\x5a\x41\xe3\x79\xcb\xd3\x8f\x76\xe6\x1b\xec\xd9\x0c\xe6\x13\x31\x59\xc9\xfa\x1c\xde\xe7\xea\x19\x94\xb1\x49\xd0\x08\x82\x15\xbe\xf3\x07\x73\x29\xae\xfa\xad\x7b\x65\xd2\x2a\x97\xdd\x59\xc6\x3b\x9c\x42\x95\xb9\x12\xbf\x95\x30\xdc\x2a\xd8\x6c\x8c\xb4\xcd\xfb\x6c\x59\xa5\x50\x65\x76\x46\x84\xc1\x53\x14\x6c\xf5\x5e\x85\xad\x21\x9e\x17\x3c\x15\xb4\x60\xce\x41\x1d\x7e\xc7\x65\x98\xb2\xd3\x12\x19\x9c\x49\x18\xf2\xec\xe5\x16\xde\x52\x6e\x75\x3a\x9c\xb0\x10\x7e\x0e\xb7\x09\x82\xc0\xe1\x63\xb0\xd1\xe2\xb4\xba\xec\xe5\x11\x65\x76\xb1\xb4\x82\x81\xd7\x88\x1d\x55\xe9\x99\x4e\x1e\xfa\x62\x92\x60\x15\x34\x9e\x50\x29\x9f\xb6\xe7\x09\x46\x8b\xd1\xf7\x84\x3f\x26\x5c\x10\xac\x02\x07\x95\xbe\x44\x87\x51\x30\x5a\xf2\x22\xf2\x2c\xa6\x02\x03\x83\xaf\x11\x09\xd9\xf5\x35\x26\x1e\xab\x25\xbd\x60\x13\x34\x42\x65\xb3\x34\xc0\xf3\x06\x57\xe7\xac\xa8\x6d\x65\xe0\x75\xc2\x55\x5e\x90\x67\xe7\x21\x15\x87\x46\xb2\x8d\x4e\x6d\xe8\x4f\x85\xac\x67\x89\x34\x92\x96\x04\x52\x4a\x43\x87\x2f\x0d\x4b\x14\x30\xd3\xf3\x2b\x2d\x90\xbe\x47\xb0\x24\x5d\xe0\x63\x0b\x26\x0b\xd3\xa7\x2a\x05\xdd\xfc\x4c\x7c\x94\x4b\xc3\xc1\x36\x1c\x2c\x68\x50\x4b\x0a\x56\x1c\x5c\x8f\x83\xb9\x1a\xec\xf3\xae\x4e\xd0\x7c\x34\xed\x56\xf1\x41\xb3\x52\x80\x81\xd9\xd2\xfa\x02\x4e\x20\xa5\x47\xa0\xa4\x5e\xe0\xf7\x94\x7e\x26\x7c\x74\x59\x29\xbc\xfb\x6e\x0d\xf4\xe1\xea\x61\xb0\x15\x06\x0b\x1a\xd0\x92\x82\x0d\x06\xa7\xc1\x60\x2e\x13\x1e\xd5\x9d\x12\x34\xd3\xaf\x4c\x16\x62\x4b\x95\x02\x96\xd4\xf9\x1e\xe1\x7a\xbd\x26\xa8\xe0\xae\x83\x6c\x88\x34\xc4\xf3\x31\x8d\xb7\xb1\x45\xca\xc1\x2b\xf0\x23\xec\x57\x48\x06\x2c\xa1\xf1\xf1\x11\xd8\x0d\xfb\x14\xc5\xa4\xd5\x6a\xb5\x29\x8a\x48\xfc\x11\xf7\xe1\xe3\xdd\x0a\x0c\x22\xa5\x6c\x3c\xaa\xb0\x92\x36\x9b\xcd\xaa\xb0\x91\x52\x0e\x1c\x55\xf8\xaf\x6a\x43\xbf\xa5\x7d\x72\x13\xb7\xb1\x59\x32\xc1\x69\x85\x64\xc2\xd3\xb4\xcf\x84\x67\xa0\x1b\xf7\x4b\xd9\x70\x45\xe1\xcb\xf6\xdc\xa1\x51\x2e\x99\xf0\x34\xdc\x86\x66\x45\xd8\x79\x18\x13\xec\xed\x81\x31\x21\x5a\xc5\x3f\x46\xd0\x92\x1e\xa2\xfc\x6a\xad\x77\xb5\x47\x0d\x51\x3e\x3d\x09\xd3\xa4\x46\xda\xd3\x82\xcf\xec\x86\x51\xfe\x16\x98\xa0\xf8\x18\x36\xd1\x9e\x38\xbc\x7d\x11\x06\xfb\xe3\xe0\x3b\x05\x68\x60\x3d\x2d\x79\x7d\xce\xbb\xd0\xc7\xe7\x95\x9c\x0a\x78\x1b\xca\x69\x54\x8f\x90\x92\xfc\x34\xa8\xbb\x15\x5a\x9c\xef\xbf\x4c\x7b\x3a\x61\x8c\xbf\x33\x90\xb0\xaa\x84\xed\x2b\x40\x09\xab\xfa\x65\x8a\x57\xf4\xa8\x69\x50\xb1\x48\x42\x20\xe8\x41\xf5\xe5\xc9\x7f\x53\x3c\x70\xfd\x20\x01\xa7\xc1\x34\x4c\xc0\x04\x9c\x86\x81\x63\x20\x8f\x45\x02\x24\xc0\x34\x98\x06\x09\x1c\x04\x49\x4f\xd2\xef\xac\xee\x5c\xb8\x70\xf5\xea\x85\x0b\x3b\x57\xbf\xf3\x4e\x67\xe7\x3b\x9c\xcf\x0a\x89\x34\x84\x82\x59\x5c\x73\x87\xdf\x93\xbd\x3d\xa3\x35\xb1\x35\xb1\x36\xa9\x2a\x56\x79\x70\x88\x09\xcd\x18\xaa\xc1\x50\x11\xcd\x6b\x86\x70\xd9\xb1\x19\x49\x89\x89\x89\x89\x49\x19\xb1\xd9\xca\x35\x43\xd0\x2c\x06\xbc\xe7\xd0\x6c\x3a\x38\x84\x8f\xad\x4a\xaa\x4d\x6c\x4d\x6c\xcd\xd8\x9e\xbd\x47\xb9\xe6\x8e\x08\x66\x08\xd5\x40\xa8\x09\xcc\x07\xef\x70\x55\x7b\x6a\xb7\xb7\xb6\xb6\xb6\x6e\xaf\xdd\x53\xa5\x3c\x78\x07\xcc\x26\x08\x65\x3c\xa2\x9f\xa2\x7f\xb7\xdd\xcb\xff\x9d\xcb\x87\x3e\x9b\x21\x78\xf4\xad\xd1\xb7\x30\x78\x07\xf6\x71\x28\xfb\x3b\x06\x58\xfb\xf7\x1f\x60\xeb\xff\xf0\x20\xec\x93\x8f\xc1\x9b\x47\x8f\x1e\x3d\x7a\x33\x06\xe7\x63\x1f\x65\x7e\x7f\xdb\x00\xa1\xbf\xd0\xdf\x3a\xa0\xff\xc3\x83\x1d\xd8\x67\x07\x06\xdf\x1a\x7d\x6b\x34\x04\x6f\x86\x3e\xf9\xca\xdf\xf3\xef\xd9\x7e\xff\xfd\x9e\xf5\xf7\x87\x07\x41\x1f\x07\x04\xef\xb8\x75\xeb\xd6\xad\x1d\x10\xec\x80\x3e\x4a\xc7\xef\xd6\x7b\xbf\x6b\xc2\x16\xb3\xd0\x2a\x4d\x82\x48\x69\x12\xb4\xaa\x13\xb7\x52\xbe\xb7\xfc\x22\x0d\xe3\x29\xe9\xfd\x7e\x30\x3e\x90\x92\x56\xf4\x0e\xa1\x71\x19\x9e\x55\x48\x43\x08\x78\x06\xf5\xf4\x40\x88\x52\xf8\xea\x89\x81\x18\xa5\x78\x82\x90\x56\x78\xa6\x4b\x2b\xfc\xd3\x15\xf0\x01\x88\x81\x4f\x43\x38\x15\x6e\xc1\x63\x30\x06\x42\x20\x19\x42\xc0\x01\x0b\x21\x34\x58\xba\x05\x5b\xa4\xc8\x96\x10\xcf\x7b\x9e\x09\xf4\xbf\x87\x9f\x7a\x65\x35\xf7\x5c\x8c\x80\xaa\x2f\x62\x2f\xaf\xbc\x7b\xc1\xf0\x95\x12\x42\x1a\xe9\x6a\x0c\x1b\x89\xff\xc4\x30\x83\xfc\xbf\xf2\x17\x0b\x84\x15\x7c\xff\xde\xcd\x2f\xf7\xc1\xbf\xce\xc2\xd8\x27\xea\x70\x80\x12\xf2\xa4\x03\xf4\xcc\x99\x4f\xe5\x3d\x63\xc4\xa1\x69\x38\xd2\x86\x43\xeb\x27\x38\x47\x89\xd1\xe7\x0e\xbc\xf7\xb1\xeb\x03\x27\xbc\xbe\x1b\x74\x56\x78\x7d\xd3\x05\xc3\x55\xe3\xe1\x39\xca\xd3\x3d\x0d\xb4\xad\x63\xcf\xe9\xa5\x55\x78\x02\x17\xf9\xc6\x0a\xf8\x0e\x2c\x4a\x37\x85\xe7\x67\xd6\x0c\xab\x19\xb6\x6d\x44\xc4\xe9\x61\x10\xb6\xe1\xb7\x34\x58\x14\x0b\x9b\x5c\x30\xfd\xe7\xdf\x4e\x67\x42\xf8\x8e\xff\x28\x61\x86\x77\x3e\x6d\xdf\x53\x7e\x60\xeb\xae\x37\x2e\x8e\x6f\x7f\xae\x19\x37\x77\x61\x66\x39\xa6\x24\xf7\x37\x46\x66\x3c\xbe\x7e\xca\xe6\x21\x6b\x73\x47\x6f\xc3\x35\x07\x71\xd5\x1e\x5c\xe5\x9c\x2d\xbc\x74\x72\xb5\x12\x14\x51\x30\x60\x3d\xf0\x59\xb0\x2a\x19\x12\x6a\xe0\xf5\x1f\x4e\xb4\x7e\xb0\xd7\xd5\xb5\x1f\x12\x0e\x40\x42\x07\x6c\x56\xca\xaf\xef\x0c\xb0\xdc\x06\xe2\x0b\x18\xff\x05\xbc\x0a\xfd\xaf\xc1\x8c\x60\x01\x2a\xe1\x97\x2f\x60\xec\x17\x70\x07\x2a\x43\x3c\xdf\x7a\x9e\xa4\xcb\x5f\x7f\x71\xe9\x82\x5d\x73\x5a\x84\xef\x4e\xb7\x2a\xdf\xde\xf9\xf1\xda\xb9\x9a\x2f\x6a\xe8\x9c\xbb\xa8\xfc\xe8\x89\x55\xaf\x27\xae\x8e\x2e\x99\x51\xfa\xf4\x97\x53\x6f\x96\xdf\x2c\xbf\xf4\xb5\xe1\xa6\x12\xa6\x48\x0c\xbd\xb1\x73\x7e\xf9\x92\x32\x64\x9a\x90\xb3\x21\xb3\x75\xb9\x79\x51\xde\xe6\x35\x47\x57\x9e\x37\x9f\xcd\x83\xa0\x1c\x08\xb6\xfe\x51\x75\xb6\xec\xa2\xe3\xf0\x11\xe5\x9b\xfe\x1c\x3a\x65\x5a\xc5\xc8\x29\xab\x90\x9e\x86\xa3\xf3\x70\xc0\xf6\x29\x95\x63\x5a\x56\x5f\x4e\xbf\x64\xb8\x9c\xfb\xb1\xbd\x22\xbc\xc2\x01\x1b\x71\x00\x9c\x14\x20\x1e\x06\x44\x74\x18\xb7\xac\xde\xaa\x81\x7e\x9e\x19\xf4\x16\x1c\x93\x88\xa3\x37\xe3\xe8\xbc\x65\x2b\x92\xd6\xa5\x22\x33\x1d\x47\x1b\x70\x68\xcd\xe3\xae\x41\xad\xcf\x7e\xb0\xae\x4d\x38\x9e\xf7\xe6\x16\x18\x96\x00\x8f\xa7\xc3\x70\xb1\xcb\xbd\xe3\x54\xa3\xf2\xca\xf6\xcf\x2a\x3f\x2b\x83\x71\x35\x30\x31\x1f\x9e\x5e\x76\x3a\xe3\x9c\x7e\xff\x92\xda\x64\x4b\x42\xc1\x56\x25\xd4\xfe\x12\xc9\xfa\x73\x3d\x77\xc0\x1e\xfc\x91\x77\x76\x88\x77\x1a\xac\xa1\x37\x66\xcd\xce\x59\x61\x55\xa2\xa6\x30\xe9\xa7\x8f\x35\x52\x35\x7c\x03\x76\xfc\x5a\x9a\x44\xa2\xb9\x40\x10\xf8\x02\x73\x41\x9e\x95\xcf\xc6\x7e\xb3\x30\x0d\xed\xa3\x94\x18\x0f\x93\x7c\x9d\x24\xce\x02\x16\x6b\xe1\xbe\x83\x83\xb0\x62\xd0\xbe\xd3\x76\x44\x29\xaf\x37\x5a\x22\x28\x44\x1b\x9a\x78\x95\xd6\xc7\x0d\x58\xfb\x44\x91\x12\xdb\x2d\x03\x60\x25\x0c\xd4\x48\xe3\xb0\x1f\x4c\x20\xe1\x8d\x8f\xdf\x82\x69\xae\x9f\x95\x65\x36\x7b\x49\x09\x23\x94\x08\x30\x93\xc3\xcf\x41\xc4\x37\xd0\xe9\x1b\x40\xea\x1a\x5f\xb8\x5b\xc2\x75\x1c\x71\x56\xb4\xf0\x1f\x60\xb4\x42\x1a\xe4\x6d\x8b\x64\x7b\x72\x51\xa7\x25\x4e\x42\x2c\x1b\xe2\x71\x80\x91\xae\xb0\x18\xca\x72\x18\xd4\x6b\x43\x6f\x10\x3a\x4a\x8b\x91\xa8\x27\x73\x0c\x81\xef\x15\xb9\xc5\x39\xe5\x46\x00\x9f\x3a\x3c\xdf\x11\xf8\x5e\x11\x4b\x89\xe5\xa5\x0e\x07\x07\xbf\x4a\xea\x72\x67\x71\xa5\xa5\x22\x22\xac\x27\x17\xc5\xbf\xda\xf3\xee\xa0\xed\x15\x45\x95\x79\x4e\x04\x49\x1d\xee\xc8\x37\x95\x9a\x64\x2a\x53\x5e\x41\x7e\x3e\x87\xbf\xfa\xd4\x79\xc6\xa2\x1c\x7b\x6e\x44\xae\xdd\x65\xae\x64\x40\xaf\xc5\x48\xa2\x8d\xd5\x86\xde\x00\x3d\x59\xe9\x2a\x77\xd9\xf9\x30\xf8\x81\xed\xd2\x12\x27\x43\x32\x59\x8f\x7e\x2e\xab\xc5\x48\xd0\x13\x95\x79\x2e\x83\x9d\xcb\xb5\xe7\x14\x19\x4d\x3e\x35\xfe\x11\x9e\x9f\x5f\x60\x32\x69\x40\xc9\xf6\x46\x29\x48\x6a\xfc\xd5\x99\x57\x59\x54\x61\x8f\xa8\xb0\x97\xb9\x2a\x35\x20\xdf\x0e\x39\x8e\x92\x5b\x13\xe4\xd6\xb4\xc4\x49\xcf\xbf\x68\x50\xb2\x62\x41\x79\xbe\x83\xf3\xa9\xe1\x57\x63\x79\x4e\x71\xae\x25\x22\xd7\x62\x36\xe4\x68\x50\x66\x85\x7c\x5e\x66\x05\xf5\x44\x4e\xb9\xc1\x65\xe1\x2a\x2c\x95\xc5\x4e\x51\x52\xc3\x1f\xe1\x0e\x47\xa9\x28\x06\x52\x1c\xef\xa1\xb4\x8a\xa4\x10\xad\x22\x09\x3e\xa1\x67\xd7\xbd\xf1\xe6\xb2\x0b\xca\x65\x17\xf4\x57\xaf\x6b\x3e\x6d\xba\x74\xe8\x03\xae\x65\xcf\xfe\x03\x27\x0e\xc7\xbd\x19\xdb\x11\xdb\xa2\x3c\x34\x73\x5a\xd3\x44\x66\xf1\x9c\xdc\xe4\x19\xbc\x7e\xc6\x12\x43\x02\xa3\x5f\xe6\x6c\x78\x99\x6f\x78\x69\x8e\x73\x31\x83\xe4\x13\x4b\x46\x4c\xe1\xa7\x0c\x5f\x87\x8f\xe2\x13\x1a\x7c\xe6\x38\x4e\xfc\x09\xa7\x70\x38\xe5\xe7\x9f\xa3\x7e\x65\x76\x1f\x76\x35\xbf\xcb\x37\x9d\x7a\xdb\x75\x90\xe9\x7c\xc7\x98\x7c\x96\x4f\x39\x77\xd4\xd0\xc1\xdc\xf8\xfa\x3c\xfc\xeb\x6b\xfe\xcc\x37\x07\xbf\xda\xf6\xb9\xd2\xf7\xb0\x36\xd4\x49\x97\x59\x1d\x65\x1a\xab\xa3\xa8\xac\x48\x44\x65\xe2\xf8\xc5\x8b\xa6\x2e\x9a\x9a\x34\xb6\x68\xe8\x5b\xa5\x1d\x8e\xe6\xb2\xbd\x15\x7b\x5b\xf6\xee\x7d\xf3\xcd\x5d\x47\x1b\x8e\x2b\xeb\x8f\x39\x8f\x76\x6a\xc2\x22\xf3\x53\xe0\x16\xe5\x99\x2c\xb5\xd2\x82\x7f\xb2\xef\x14\xe9\x99\xfc\x84\x42\xab\xd8\x12\xea\x9f\xfc\x84\xc2\xf7\x81\x67\x32\xe9\xdd\x30\x9e\xee\xe1\xfd\xc3\x08\x2f\x8f\x8f\x29\x0e\xb2\xa1\x3d\xf2\xd1\x3f\xda\xcb\x93\x61\x78\xdf\x4b\xc1\xc4\x60\x01\x56\x41\x32\xac\x02\x0e\x56\x83\x1e\x56\x85\x48\x46\xef\x7e\x3a\x25\xa3\xae\xb1\xb1\xb6\xae\xb1\xa9\x36\x3d\x25\x25\x23\x3d\x99\x97\x9e\xed\x97\xdc\x7b\xae\xa9\xb1\xf7\x5c\x0a\xef\x3f\x89\xaf\xd1\x73\x97\x2d\x9b\xc7\xfb\x5e\x24\xe7\x1e\x5d\x76\xfa\xf4\x91\xa3\xa7\x39\xe9\x45\xf2\xbd\x65\x47\xe7\x71\xde\x23\x69\x74\xcf\x70\xff\x93\xc4\xac\x63\x8b\xdf\xe7\x3e\x21\x6c\x98\xaa\x98\x7b\x74\xd9\x7b\xa7\x8f\x1e\x3d\xcd\x41\x2a\x70\x98\xda\x4b\xd4\x5b\xbe\x4a\x9e\x3b\x76\xec\x7d\x1e\xb3\xbc\xef\xd1\x97\xe1\x5f\xa5\x65\x45\xa2\xb9\x34\xc2\x5c\x62\x2a\x2a\x30\x4f\xc5\xf0\xf0\xd6\x59\xd3\xab\xa7\x32\x53\xa7\x67\x25\xce\xe2\xa7\x42\x78\x41\x99\xa9\xd8\x5c\x18\x61\x2e\x28\x32\x95\x9a\x2f\xe3\xbf\xc2\xb1\xff\xd4\x91\xc8\xe1\x18\x8d\x77\x34\x01\x63\x46\x02\x87\x91\x57\x38\x29\xc9\x97\x45\x9f\x5e\x76\x64\xee\xbc\x65\xcb\xe7\x72\xbd\x5c\xf6\x32\x10\x86\xe2\xb1\x15\x9d\x6f\x35\xa6\x76\xc3\xd7\xb5\xd2\xf1\x8b\x87\x1b\x80\x6c\x28\x6e\xc8\xae\x36\xb7\xbd\xdd\x98\x55\xd7\xb7\xac\x2d\xb5\x5e\x68\x87\x41\x3f\xfc\xf4\xad\xf8\x76\xfc\x2e\x67\x67\xdc\xfe\xf3\x5f\xb7\x9e\xe8\xa8\xd9\x73\x66\x6f\x13\xcc\x80\xf1\xa6\x6a\x78\xac\x51\x55\xff\xea\x07\x3f\x79\x46\x78\x3d\x74\x7c\x71\x91\xde\x69\x53\xba\xcc\x75\xc5\x0d\xbc\x40\x7e\x93\x4d\x3b\x4b\x8d\x0d\x09\x39\x4a\x81\xac\xb3\xdb\xd2\x9c\x25\x4a\xfc\xcd\xf7\x3c\x5d\x5e\x68\x31\x59\x32\xf2\xb3\xb3\x73\x2d\x36\xa5\x40\x66\x17\xd7\x39\xcb\x2a\xc5\xaa\xa2\x3a\xb1\x50\xe9\xe9\x46\xa4\x57\xef\xc6\x3e\x8e\xc2\x89\xca\xe4\xcc\xa2\xcc\x1c\x5e\x35\x34\x28\x68\xd4\xa2\xd9\x47\x91\xb2\x44\x2b\x55\xfd\x82\xde\x0f\x2a\x98\x97\xa9\xcb\x9b\xb7\xc9\x56\xd2\x28\xee\x52\xaa\x1e\x0a\x7a\x34\x48\x6c\xad\xdc\x6d\x6b\xb7\xb5\x15\xd6\xe5\x95\x9a\xed\x06\x53\x66\x52\x9c\xee\x85\xad\x2f\xe7\x4d\x37\x45\x97\xc5\xed\x37\x54\xa6\x66\x14\x15\x16\x5a\xaa\x4c\xae\x54\xa5\x2a\x68\x14\x11\x54\xb3\xb9\x7a\xc5\xba\x54\xdb\x9d\x78\xc7\x86\x0f\x94\x02\xa9\xfa\x87\x72\xc0\xa5\xae\x32\xf1\xa3\x8d\x3b\xb7\x6e\x43\xee\x6e\xec\xc1\x8c\x3a\xbd\x68\x6a\x4c\x7e\x3b\xeb\x52\xeb\x31\xbb\x58\x5a\x50\x90\xae\x0c\xf0\x91\x3c\xe0\xa3\xb1\xd5\x87\x5d\x6d\xc6\x53\x8e\xc3\x4a\x55\xd0\x94\x17\x83\x9c\x9f\x5e\x82\xc7\x77\x95\x2f\xbd\x79\xf7\x23\xeb\x67\xd6\xe3\x47\x30\xe4\xc8\xd6\xe3\x49\xef\x7e\xfa\xef\xfd\x4d\xae\x1d\x15\x45\x4e\xb9\xc3\xd0\x29\xa6\x23\x4f\x0e\x19\x5f\xb8\xce\x9a\x2d\x66\x55\xad\x38\x74\x2c\xe6\x42\xc5\x4e\xbb\xd3\xbe\xab\xb2\xbd\x62\x4f\xfd\x1e\xa7\x52\x55\xa8\x0c\xde\xbd\xcd\x51\x54\x6f\xb4\x5b\x4a\xf2\x04\xb3\x21\x2b\x69\x5a\x56\xb2\x39\xc1\xb4\x31\x6f\x55\x71\x74\x71\x75\xdb\xb2\xed\x39\x65\xa5\x0d\xb5\x75\x4e\x71\x9b\xa3\xb2\x51\x59\x5c\x52\x53\x5b\x29\x96\x96\x08\xff\x5e\x6b\x93\x47\x20\xf2\xd1\x38\x9b\x31\xc9\x96\xa4\x4c\x2a\xae\x4a\x16\x99\x3a\x5b\x46\xaa\xb1\x30\xcb\x92\xfa\x61\x49\x5b\x71\x7b\xcd\x7b\x07\xad\x7b\xad\xdb\x97\x5b\x9f\x53\xe6\x9c\xa9\x6f\x48\xe1\xaa\xb2\x67\xc2\x48\xe0\x5c\x7b\xcd\x7b\x72\xab\xc6\x5b\xf2\xaa\xe6\x24\x9b\x13\x4d\x19\xce\x9a\xed\xce\xed\xc6\x0b\xba\x82\x79\x85\xe5\x43\xab\x8b\xaa\x8b\xf6\x27\xb6\x5a\x94\xdf\x64\x44\x2f\x72\xcd\x52\xaa\x1e\x0d\xb2\x07\x55\x4e\x3f\x52\xd7\x89\xaf\x96\x1b\x3a\x8c\xbb\x31\x72\x27\x3e\xb6\xfa\xa9\x8f\xcb\x6b\x6c\x2d\x76\xe7\xde\xed\xdf\xad\x81\x90\x35\x57\xf5\x87\x93\x77\xe6\x3a\x8f\x26\x9e\x8d\xaa\x8a\x56\xd6\x8d\xab\x88\x49\x1c\xad\xac\x31\x1f\xc8\x48\xd7\xf8\x95\x9e\x8f\xe8\xc2\x22\xc1\xca\xa9\xa6\x84\x16\x06\x99\xac\xe5\x15\xc5\xbc\x58\x6c\x71\x14\x30\x02\x99\x5f\x54\x54\x57\x51\xe8\x28\xaa\x48\x2f\xd8\xa2\x94\xc6\xe3\x22\xba\x24\xdb\x94\x99\x5b\x9c\x5a\xba\xf4\xed\xc6\x66\xa5\x4a\x19\x1c\x14\x24\x90\x2a\xe5\x43\x41\x41\x65\x65\xa5\xa9\xf5\xb9\x35\xc6\xaa\xb2\xd2\x34\x25\xbe\x0c\x71\x74\xa1\xb1\xa0\x58\x53\x54\x9d\x57\x95\x57\xac\x14\xc8\xfc\xe2\x02\x47\xa5\xcd\x6e\x6b\xcc\xb5\x6e\x55\x9e\x82\x6c\xda\x62\xd0\x97\x58\x8a\xd2\xcc\xf9\xe9\xa6\x32\x63\x79\xb5\x58\xea\x52\x0a\x64\x89\xd3\xd8\xd8\x50\xac\x2c\x2f\x37\xe7\x95\xf3\xa2\xb9\x32\xdf\x6a\x51\x4a\x1f\x68\xbd\xef\xd1\x9b\xeb\xa6\xd7\xe7\x43\xbf\x24\x7d\x09\x3e\x72\x65\xeb\x17\x89\xc7\x97\xe3\xb0\x85\x4a\xd5\xa3\xc1\x41\x41\xc3\xe2\x32\x8c\xcf\xbd\x3a\x69\x06\x52\xdb\x1b\x81\x73\xb9\x1d\x67\xd3\x3f\x34\xb5\x15\x1c\x74\xb4\xba\x4e\xed\xac\xd9\xb9\xb0\x6e\x83\x63\x5d\x57\xa1\x52\x35\x3b\x34\x28\xe8\x97\x82\x86\x3b\xed\xf6\xc6\x92\xa6\xf7\x33\xff\x93\x7e\x6f\x26\x4c\x98\xf4\x95\x52\x65\x08\x0a\x0a\x9d\xf1\xf1\xea\xf7\x93\xbe\x49\xfe\x24\xf7\x72\xe9\x25\xc7\xcd\xc5\xd0\xe7\xb9\x33\x8b\xf7\x4e\x6e\x78\xd9\xaa\x5c\xbb\x3e\x3f\x6b\x33\x8f\xca\xd7\x32\x47\x17\x0f\x2a\x1e\x51\x82\x0f\xb9\x06\xe6\x2c\x99\x3e\x6a\xe5\xbc\x39\x73\x13\x30\x64\xdd\xf0\xd4\x85\x1b\xb6\x16\xce\xb0\xa6\xd9\x96\xd4\x56\x7d\x74\xe2\x06\x86\x03\x8d\xcb\x95\x02\xd9\xb2\xf6\x1b\x1c\x8f\x23\x53\x16\x9a\x27\xec\x9d\xd4\x30\xad\xf6\x45\xd7\x1a\xd7\x96\xff\x8b\xb0\xff\x80\x6e\xe2\x0a\xfe\x86\x61\x1b\x7b\xa5\x45\x21\x0e\x20\x2d\x58\xbb\xd2\xae\x09\x01\x42\x09\xd5\x94\xd0\x21\x21\xf4\xd0\x4c\x33\x1d\x8c\x6d\xdc\x31\xee\x4d\x92\x65\xcb\x92\x56\x92\x65\x59\xee\x1d\x1b\x17\x6c\x6c\x8a\xe9\x25\x74\x12\x4a\x68\x0e\x21\x81\x84\x96\x46\x48\xa7\xcc\x4a\x23\xf3\xff\x8e\x4c\xf2\x3c\xdf\xf3\xbc\xe7\xbc\xef\x39\xbb\x3b\x77\xe7\xce\xcc\xbd\x77\xcf\xd5\x6a\x67\x77\xee\xfc\x6c\x1a\xbb\xa1\x20\xbb\xbe\x6d\x9f\xa9\xd9\xdc\x9c\x51\xae\xde\xa5\xde\xa5\xaf\xb2\x17\x92\x79\xf6\x12\xcb\x4e\x43\xa3\xbe\x35\xaf\xb2\x68\x77\x65\xe9\xfe\xf4\xe3\xe4\xda\xd4\x94\xad\xf1\x6c\x48\x62\x40\xf9\xf6\xb8\xc8\xed\xed\x9f\xe8\x57\xe9\xb7\x6e\xd9\x50\x11\xf4\x66\x5a\x56\x04\x3d\xd4\x3d\x49\x86\xde\xdb\x3b\xd6\x5d\x30\x3c\xd4\x17\x3f\x04\x5f\xcb\x7e\xd3\x3e\xf3\x3e\x13\x79\xe8\x10\x6f\x3c\xcc\x3d\xd1\x47\xae\x3b\x1f\x75\x22\xf6\x71\x41\x75\x55\x43\xfd\xd7\x57\xce\x37\x92\x52\x0f\xb5\xc7\xf4\x8e\xbd\x30\xe5\x32\xbe\xf3\x75\xd7\x33\x97\xb7\xf0\xe4\xef\x54\x10\x09\x15\xe0\xdd\x9b\x07\x6f\x05\xe1\x07\xde\xd2\xfb\x4e\x7b\x1b\x15\x36\x79\x6c\xd2\x48\x06\xc7\xe0\x80\xf3\xbf\xa0\x88\xe3\xed\xd9\x79\x3a\x16\x7a\x43\xbd\x20\x07\x05\x4f\x9b\xcc\x26\x13\xf3\x33\x66\xed\xc3\xb5\x05\x4b\x48\x5c\x28\x3c\xa7\xb4\xfa\x4c\x43\xa6\x9e\xe4\xf1\x15\x8a\x70\x36\xde\x66\x81\x54\xf6\x07\x72\x3e\x0c\x87\xc9\xb4\xf4\x7d\x1b\x6f\x33\xd9\xd8\x42\xb8\xab\xfd\x0b\x7e\xe2\x2a\x83\x2b\x82\xcb\x82\x49\x3f\x08\xa5\xa4\xf7\x27\xe0\x75\xac\xb7\xa4\x30\x87\x60\x03\x28\x60\x0a\xcc\x7f\x64\x57\xc1\xdb\x38\x01\x44\xb8\x9e\x74\x4c\xc7\xdb\x54\x24\xce\xef\x8f\xa3\x71\xd0\xfb\x59\xfb\x43\x61\xf9\x58\xd0\x40\x68\x0b\xcc\x5f\x52\x92\x43\x76\x1e\x75\x24\x53\x46\xa3\x91\xe7\x4c\x5d\x20\xe8\xc2\x63\x1c\x40\x19\xf4\xc3\xf1\x5d\xe4\x47\xa0\x37\x6c\xc6\x9e\x30\x5e\x53\x4c\x16\x9d\xfc\xcc\x76\x9a\x91\xbe\x07\x13\x61\xd8\xc2\x01\x20\xe6\x60\x87\x2b\x99\xd2\x9a\x70\xc7\x09\x4c\x88\x22\xa5\xab\x74\x85\x39\x45\xba\xc2\xf4\xe6\xb4\xe6\xb4\xdd\x50\xf4\xf2\x05\x0c\x33\x9b\x7f\x46\xef\xb3\xd8\xdf\x8c\x23\x48\xf0\xce\xa2\xfc\x24\xf3\x21\xcb\x39\x05\x52\x7b\x83\x5e\xa9\x70\x4e\x87\xab\x8e\x7d\xf0\x99\xf4\xa1\xc2\xbb\x40\x88\xa4\x70\x03\xae\xfa\x00\x17\x63\x3c\x2e\xfe\x13\xde\x39\xbb\xfb\xe4\x4d\xf6\x55\x01\x0e\x87\x85\xcc\x93\xf3\xfb\x4f\x5d\x09\x28\x18\x5d\xc3\xe1\xc0\x36\x02\x07\xb6\xa2\xf7\x25\x98\x4c\xc3\x06\x58\x77\x07\x66\xc0\x12\x58\x36\x1d\xc5\x4b\x82\x56\xcd\x63\x87\xe8\x41\x8c\xa3\x98\x31\xcb\x76\xac\x58\x72\x3e\xe3\xeb\x64\xee\xf9\x0e\x02\xde\x0d\x87\x29\x8b\x70\x26\x0d\xff\x83\x91\xd4\x93\xc8\xfb\xab\xaf\xb2\x05\xc7\xf3\x4e\x9d\xa2\x05\x39\x5e\x87\xeb\x2e\xf9\xaa\x55\xd9\x9a\x35\xec\xc9\x79\x13\x9b\xc6\x30\x59\xca\x31\x4d\x13\x4f\xce\xe3\x34\x6b\xb2\x57\xad\xa2\x5d\x72\xb8\x8e\xd7\x05\xf9\xa9\x53\x79\x05\xc7\xd9\xd5\x57\xef\x47\x3e\x61\xa4\x77\x1f\x4b\x5c\x2a\x61\x30\x2c\x84\x63\x5d\x71\x6a\xf3\x3d\x0f\xc3\x7c\x67\x9a\xdd\xcb\x99\xe6\x7c\x4c\x25\xe4\xc4\xc4\xef\x60\xf8\x58\x1e\xbf\x0a\x8a\x8e\x09\x62\x37\x89\x83\x1a\xa2\xf7\x43\x65\x03\xcf\xb3\xf5\xf5\x91\x51\xd9\x5c\x76\x54\x34\x0e\xd4\xa7\x92\xa9\xfa\xa4\xe8\x30\x86\x8f\xe1\x31\x74\x83\x2a\x3b\x34\x92\xe5\xa3\x82\xb1\x14\xaf\xb3\x7a\xbd\xde\x64\xa1\x9d\x8f\xc4\x75\x35\x8d\xcd\x8e\x19\xf5\x6e\xcd\xda\xd8\xf0\x2c\x0e\x96\x36\x50\xc0\x36\x84\x7e\x85\x7d\x98\xce\x3c\x7c\x87\xe7\x39\xf4\x09\x19\xb1\x84\xe3\xf9\x25\x0a\xe7\x11\x7a\x6e\xeb\x8e\x2a\x2d\x5b\xa5\x3d\x93\xd5\xb2\x8f\x14\xc6\x0b\x29\xb6\x7c\x9e\x2e\x2c\x30\x19\x0b\xab\x61\x1c\xff\x84\x01\x51\xc5\x77\xc7\x8a\xb8\x82\x76\xf0\x12\xae\xed\x85\x39\x24\xef\x1d\x8c\x73\xd0\xcb\x75\x4d\xb3\xb9\x6b\x3a\xb7\x3b\x3b\xe0\x27\xa5\xd0\x0e\x32\xa1\x1d\xfc\x65\x13\x1c\x01\x10\x40\x4d\x94\xb8\xe2\x86\x29\x9d\xf6\x35\x4a\x21\x6e\xa9\xe4\xb5\x5d\xec\xf0\x17\x64\xff\x72\x1d\xb2\x37\xdc\x4e\x99\x18\xfc\x1d\xf6\x7f\x94\x2e\x95\xa3\x0b\x6c\xda\xa0\xf4\x32\x28\x85\x38\xaa\x32\xbb\x52\x53\xca\xa2\x5d\x90\x11\x17\xb7\x2c\x3c\x3e\x83\x71\xc9\x44\x33\x16\xae\x59\xbc\x85\x43\xbb\x4b\x46\x68\xd2\xb2\x93\x92\xe8\x95\x92\xe6\xa6\xb2\xfa\x0a\xf7\xa3\xc3\x53\xe2\x08\xfa\x8a\x90\x77\x8d\x20\xb2\x35\x7a\xb5\xaa\x0b\x6d\x1c\xeb\x44\x0b\x4f\xad\xfe\x9c\x05\x7f\x11\xd4\x48\x38\xa8\x83\x00\xf1\x74\x65\x91\xbe\x30\xbb\x80\x43\x5e\x18\x41\x80\xef\x11\x31\x24\xe2\x53\x22\xa6\xa2\x29\xb5\x99\x59\x28\x71\xf9\x3b\xda\xd3\x24\x3e\x9d\xff\xf6\x06\x02\xae\x40\x5c\xd7\x16\xe0\xe5\xb4\x3b\x3a\x60\x9f\xa4\x53\x26\xda\x2d\xe1\x5c\xfe\xc2\xdb\x4a\x78\x71\xe5\xf5\x7b\xf0\xb1\x52\x08\xba\xe2\x0a\x82\x8f\x95\xce\xf7\xae\xe0\x0b\xe1\x6d\x25\xb6\x3b\x5e\xa4\x75\xf9\xaa\x25\x90\x41\xe1\xdf\x42\x64\xcc\xde\x70\x78\xeb\xaf\x2f\xe5\x8f\xcf\x7d\xb7\xf1\xd0\x6a\x32\xb9\xac\x3e\xfe\x33\xe6\xb3\x86\x9a\x8a\x32\xee\xd0\xc9\xef\x0e\x3d\x5a\xf6\xf7\x9c\x70\x7c\x2b\x26\x98\x14\x46\xcd\xe9\x5a\x4a\x69\x57\x88\xfe\x07\x6f\xc3\xed\xde\x90\xf4\xb3\x4e\xf2\xb3\x74\xaf\x82\x38\xed\x90\x51\x78\x0b\x0b\xb1\x10\x6f\xb9\x29\x14\xc2\x2d\xb8\x05\xff\x8b\xba\xf9\x2c\x34\x62\x13\x65\x29\x30\x16\x66\xe7\xe3\x1c\x30\xf9\xc2\x1c\x30\xe5\xd9\x4d\x05\xfa\x02\xb9\xbe\x40\x6b\xcb\xb4\xe0\x91\x67\xbe\x70\x51\x5c\xa0\x2b\xd0\xe6\xb1\x99\x79\x1a\xb3\x26\x07\x8f\x7c\xe0\xeb\x16\x56\x95\x45\xf3\xaa\x54\x39\xce\x41\x13\x1e\x79\xaa\xc9\xd5\x18\x32\xb3\xe5\xda\x6c\x9d\x46\x43\xe3\x45\x31\x1e\x19\x9a\xa9\xd7\x66\xe9\x35\x72\xbd\xc6\xa4\xc9\xcb\x84\x39\x68\xf2\x75\xcb\x66\x6b\x8d\x6a\x8b\x46\x6e\xd1\xe4\x67\xd9\xf5\x70\x64\xa8\x2f\x5e\x14\x6b\xac\x9a\xfc\x6c\xd6\x9e\x5d\x60\x28\xc8\x85\x23\x4f\x7d\xdd\xc2\x84\x36\xaf\x40\x57\xc0\x14\x14\x58\xf3\xf3\x38\x77\xbf\xe0\xc8\x07\x05\x39\x05\x66\x7b\x9e\x3c\x3f\xcf\x5a\x50\x40\xc3\x45\x31\x1c\x79\x46\x48\x63\xec\x96\x7c\x9b\xa5\x80\xf4\x89\x54\x42\x5c\x57\xe2\x19\x19\xbc\xe8\x42\xf9\xfc\x03\xd2\x29\x1c\x80\x3d\x70\xee\x18\x5c\xce\xe0\x4b\x3c\x00\x6b\x94\x70\x08\x96\x82\x1e\x2a\xbf\xe5\xe6\xf4\x0b\xc6\x9e\x28\xa5\x5d\x62\x38\x83\x67\x04\xf1\xde\xbd\x96\xbc\x36\x16\x36\x3c\xa4\x0a\x6b\x75\x8d\x49\x95\x49\x95\xd1\xd6\x58\x35\xb9\x6d\xe6\xb4\x94\xc9\x0c\x9e\x46\x3d\xe8\xe1\x34\x0c\xbf\x0c\xef\x82\xe8\x39\x57\x59\x61\x6b\x54\xd7\x69\x6a\xe3\xca\xa2\x8d\xa4\x6b\x74\x1a\x7e\x83\x3f\xba\xc6\xd0\x70\x5b\x09\xa7\xa0\x1e\x3e\x82\x5a\xe8\xc5\xfa\x54\x3b\xec\x10\xd0\xf5\x92\xcb\xd9\xe1\x08\xe8\xfa\x84\x64\x17\x85\x46\x35\xb6\xfa\x2b\xc1\x5e\x2a\x11\x3a\x20\x20\x44\xa2\x70\xaa\xc7\x4a\x5e\x07\x8c\x50\xc6\x29\x47\x4a\xae\x28\x08\xb5\x9b\xe5\x61\x91\x2c\x96\x6c\x93\xf8\x55\x27\x08\xf6\x6f\x94\xd0\xe1\xd9\xac\x10\x4d\xf7\x52\x88\x36\x0a\x1d\x21\x12\x8c\x13\x81\x8c\xff\xf3\x1a\x0d\x33\x60\x06\x8c\x56\xca\x35\x4a\x9c\x81\x33\x7c\x3b\x1f\x8a\x70\x06\xcc\xd0\x28\xe5\x7f\x29\xc1\xcd\x98\xcb\x0f\x42\x19\x8d\x71\x22\x8d\x04\xe2\x44\x48\xee\x1c\xdd\xfa\x09\x8b\xeb\x31\x31\x2e\xc6\xbc\x65\xd7\x0e\xb9\xba\xb8\x54\x57\xca\x54\x94\xdb\x4a\x8a\x39\x98\x0f\x5b\x08\x1e\x7c\xd1\x17\xe6\xb2\x90\x23\x79\x2d\x13\xc3\x54\xe8\x0b\x3d\x78\x0e\x02\x71\x35\x01\xac\x04\x46\x2b\x31\x08\xb6\xfa\x1e\xb8\x55\xff\x14\x7a\xd1\x10\x37\x52\xe2\x8a\x13\x3a\x28\x98\x25\xc8\x24\x38\x0b\x67\x61\x7f\xa1\x9b\x92\x75\xc8\x44\x3e\x30\xb8\x26\xc1\xc9\x37\x6a\x6d\xbd\x15\xe2\xe8\x52\xe9\x0d\x85\x38\xdd\x69\xa2\xf8\xf4\x03\xfe\x6a\x16\xdb\x0d\x44\xbc\x25\x35\x93\xa7\xf9\x94\x4c\x6d\x3c\xbb\x16\xdf\x5e\xd4\x9f\xa7\x51\x86\x51\x2b\x55\x09\x25\x64\xe0\xee\xe2\x5f\xaf\xd3\x10\xda\xfc\x64\xd8\x4e\x36\xc2\x16\x67\x9d\x68\x7a\xcf\xe4\x6f\x0c\xdc\x11\x96\x1a\x1b\x52\x6a\xa8\xd4\x1f\xca\xdc\x19\x41\xf2\x75\x9b\x73\x47\xb1\x85\x68\x5e\x15\xc1\xd3\x41\x09\xb3\x5b\x07\xc1\x66\x92\x5f\xf2\xf7\x7a\xf0\x66\xb5\xd5\xa9\x85\x3c\xcd\x27\x97\x6c\xcf\x65\xa5\x7b\xb1\xde\x40\x6c\x4a\x4b\xe2\xf9\xb4\xd4\x92\x30\x0e\xc2\x5c\x3c\xe8\xd1\xca\xd3\x3c\xec\xc0\x74\xc8\x2b\x63\x79\x10\x8b\x5b\x2d\x15\x95\x3c\xcd\x97\x55\x18\x5b\x58\x03\x0c\xbf\xbd\x93\xa7\x6f\xd6\xfc\x88\xd3\x9e\xcd\x25\xf9\x8e\xd5\x67\x0b\x59\xb0\xe7\x12\xc0\x98\xe6\x83\x37\x4f\xeb\xec\xe1\x37\x70\x38\xf4\x27\xa5\x37\xd0\x1f\x06\x57\xef\x80\x15\x50\x08\x12\x18\x75\xec\x59\x5a\x3b\xe9\x53\x3d\xf6\xef\x0e\xe8\x06\xb3\x61\x0b\x0c\xe8\xca\xc8\x36\x03\x1a\x41\xd9\x5b\xf0\xfb\x0d\x56\x15\x7e\x05\x4b\x85\x60\x90\xbc\x04\x56\x0a\x0f\x1d\xe3\xc1\x4a\x45\xad\x5b\x98\xb8\xae\x7a\x7d\x75\xfa\xe9\xc6\x23\x0d\x87\x2f\x55\x1d\x49\x3a\x96\x58\xba\x22\x7a\x1d\xf9\x14\xde\xa6\x34\xc9\x71\xda\x64\x5b\x72\xbe\xae\xb2\xa0\xa2\xa0\xbc\x26\xbf\x22\xbb\x22\x2b\x2f\x51\x93\x4c\xc2\x4c\x3f\xea\x12\xd0\x33\x80\xc5\x41\xfb\xb0\x5f\x1b\x8e\x99\xb5\x10\x7b\x2e\x44\xe9\x25\xec\x07\xfd\xd7\x91\x52\x52\x0d\xef\xaf\x81\x99\x5f\x5d\x02\x05\x09\x57\xc1\x9f\xaa\xc4\x95\x18\x87\x73\xf1\x64\x24\x29\xb5\x4e\xc7\x93\x51\x68\x07\x3a\x09\x56\x26\xc1\x4a\x88\x83\xb9\x70\xb2\x09\x4e\x36\x82\x1d\xe9\x4a\x5c\x49\xc2\xe7\x39\x14\x28\x50\x74\xf7\xbd\x66\x36\x36\x3f\xc5\x5a\xdc\xd2\x70\xdb\xf2\x45\xc4\xe1\x25\xdf\xe3\x98\x1c\x9c\x37\x95\x34\x2d\xdd\x5e\x72\x94\x6d\xf8\x31\xe7\xeb\x0d\x87\xde\xff\x03\xcb\x06\x60\x02\x26\x90\x52\x78\x88\x53\x70\xca\x60\x9c\x8d\x23\x68\x3c\x29\xf4\xc4\x39\x02\x29\xa4\xc2\x5d\x68\x83\x78\x76\x86\xc3\x9b\x5a\x7a\x65\x5c\xed\x94\x14\x52\x4a\x4e\x0f\xcf\x4a\x8c\xb0\x85\xe7\x85\x37\x27\x36\xdb\xdc\x8a\xbc\x78\x5f\x7e\xbb\xaa\x21\xa2\x21\x22\x7f\x93\x6a\x2b\xc9\x8b\x35\x11\xe5\x61\xbb\x35\xbb\x35\x2d\xe5\x05\xbb\xeb\xbe\x4e\x7d\xbc\xf4\x32\xe9\xf6\x9c\x28\x94\x40\x5f\x9c\x71\x02\xc7\x6e\x23\x79\x71\xb0\x76\x47\x48\x7e\x70\x7e\xf0\xde\x1d\x7b\xf3\x41\x54\x0b\xef\x84\x3e\x18\xfe\x60\x44\x0d\x4a\x43\xd0\x8b\xe4\xc5\xea\x90\xaa\xad\x6d\xaa\x36\xd5\xbe\xaa\xa2\x36\x12\x48\xe5\x49\x18\x19\x01\x9f\xa0\x04\xfa\xb8\xff\x8b\x14\xc4\x3f\x3f\x48\x14\xde\x91\xdb\x28\x9c\x05\xde\xd8\x1f\xa6\xac\x81\xc0\xb5\x18\x88\xfd\x71\x0a\xce\x42\x6f\x72\x11\x78\x42\xaf\x6d\x20\x67\x80\x86\x5e\x7b\x2e\x81\x27\xe7\xd2\x2a\x08\x3b\x85\xaf\x3f\xc5\x46\xbc\xee\xea\x49\xe3\x92\xeb\x38\x1d\x08\xa4\x59\xa8\x86\x3e\xb0\x04\x8e\xc1\xaf\xb4\xb3\x0f\xd6\x52\x42\x4f\x6c\x84\xeb\xf8\xfa\x73\xd6\x95\x2c\xc6\x5f\x61\x09\x1e\x83\x6a\xec\xc3\x02\x01\xf4\x75\x98\x0e\x4b\xe8\xae\x84\x2f\x3f\x28\xbc\x6b\x0e\xc4\xd4\xf5\x76\xec\x7c\x28\xdd\x2b\xbd\xa1\x20\x52\x84\x59\x14\x7e\x03\xa5\x78\x0e\x9f\xf0\x74\xf3\x93\xba\x5f\xcb\xfe\x24\x79\x81\x1f\x58\x2a\xa4\xb3\xf8\x08\xc4\xf8\x21\x7e\xc3\xd3\xe6\x56\xfe\xbe\x21\x8f\xe4\x21\x55\x98\xe3\x5a\x03\xa3\x58\x34\xe3\x63\xc1\x17\x6b\x78\x5a\x9f\x8d\x7d\xb3\x3f\x65\xa5\x7b\x79\xf4\x11\xd6\xb8\x66\xe3\x47\x6c\x9b\x6b\x9e\x60\xbb\xc7\xd3\x29\xef\x6e\x1f\x12\x32\x7a\x16\xf4\xc2\xf9\xb0\xc9\xf5\x2e\x4e\x80\x51\xae\x81\xd0\x76\x18\x86\x5c\x40\x1a\x8d\xb8\x09\x47\xa0\xca\x48\xc6\x26\x26\xc5\xc6\x56\x25\xd6\x71\xd0\x6a\x02\x3d\x04\xc0\xfb\xf0\x19\xc9\x0b\x09\x78\x16\xd6\x09\x39\xac\x8f\x4b\x55\x0c\x3b\x6f\x41\x7e\x87\x7b\xdb\xe9\x59\xad\xf0\xbe\xe3\xa5\xf0\x7e\x06\x6d\x94\x02\x87\xcc\x15\x21\xf1\x64\x24\x78\xb0\xc2\x2e\xac\x11\x41\x31\xd4\x10\xe7\x45\xe0\xf1\xe4\x27\x20\x38\x41\x21\xf4\x90\x08\xf7\xdc\x07\xce\x1b\xbc\xc7\xfc\x84\x1e\x6c\xe7\x63\x11\x7a\x8c\x19\x89\xde\xdc\x1c\x85\xf7\x1d\xb1\x0f\x8c\x95\x38\x64\x54\xa3\x12\x5f\x88\xc7\x4b\xe0\xc5\x7f\x29\xaa\xc0\xbf\x4f\x7f\x09\x8c\x95\xc0\x6d\x09\xbe\x80\x00\x51\x79\x5a\x29\xd4\x2a\x33\xb5\xb4\xd6\x92\xf9\x26\xdf\xd5\xed\x7f\xf3\x5d\x8d\x93\x40\x00\xbc\x10\x4f\x95\x80\xff\xb3\xae\x10\x4b\xa7\xdd\x19\x40\x8d\x51\x66\x64\xe4\x68\xd5\xac\x2b\x00\x3b\x88\x14\x95\x26\x31\x91\x4e\x28\x48\x2a\x57\xb1\x82\x9b\xa1\x2d\x2c\xce\x29\x66\xdc\x37\x66\xf4\x5f\xa4\x3c\xa4\x7c\x13\x5c\x8e\x76\xa1\xfd\x43\xa5\x1f\x8c\x92\x08\x76\xa0\x94\x5e\xce\x7c\xf8\x9b\xc2\x82\x0a\x0c\xc2\x18\x2c\x60\x60\x99\x12\x3e\x79\x01\xfe\x30\xfe\x36\x97\x02\x7d\x09\x4c\x9c\x80\xc3\x30\x02\x75\x34\xde\x84\x22\x2c\x82\x9b\x60\x81\x58\x18\x0f\x99\x77\x59\x61\xe9\x73\x0a\x03\xdf\xc7\x24\x61\x0d\x51\xad\x89\x2b\xd9\xc1\xb8\xd6\x88\x52\x41\x46\x08\x43\x41\xe6\x9a\x24\x0a\x86\x83\xc4\xcf\x9a\x7b\xdf\xfc\xd4\xb5\xca\xe5\xe3\xf9\xeb\x3f\x49\x62\xf5\x9a\x9c\x78\x93\xe6\x59\x67\x95\x6f\x78\x6e\x43\x6c\x33\x23\x44\x88\x40\xeb\xda\x4e\x24\x14\xec\x4c\xaf\xfd\x2f\x17\xbd\x1d\x64\xc4\x9b\xe7\xaa\x00\x68\xf7\xe4\x61\xbe\xf3\x29\xe8\xbd\x14\x44\x0f\x67\x1f\x2a\x07\x3d\xa6\xe1\xfb\x38\x10\x17\x93\xb8\x0a\x87\xa2\x6c\x70\x7f\x66\xde\xf2\x4b\xf0\xd6\x7a\x2e\x12\xba\x45\x82\x67\x24\x74\x23\xe1\xad\xb0\x90\x4b\x5b\x19\x6d\x54\xf2\xb6\xd5\xdc\xca\x2f\xcf\x1e\x3f\x7d\xe2\xcc\x31\xf9\xed\x2b\xe7\x9a\xdb\x72\x1f\xe7\x9f\x5e\x5c\x85\xbd\x6b\x50\x59\x3a\x3e\x7f\x1b\x89\xc4\xae\x5d\xcb\x9a\x98\x9d\xad\x6d\x5f\x1d\xe3\x8e\x76\xd4\x9d\xb3\xec\x23\xaf\xd8\x62\x9b\x97\x31\x31\x31\x59\xaa\x68\xee\x0c\xcc\x7e\xfe\x18\x86\xeb\x40\x94\x73\x66\x66\x16\x0e\x20\x41\x0f\xb1\x7e\x4a\xd7\xff\xf0\x10\x8f\x1b\x13\x7a\x83\x1d\xe2\x84\x00\x88\x93\xc6\x48\xf7\xea\x24\x8e\x80\xa5\x4a\xf4\x17\x0d\x50\xa2\x0d\x03\x31\x08\x2d\x29\x9c\x90\x0a\xdd\x25\xbf\x40\x77\x09\xcc\x5d\xa6\x44\xff\xf7\x25\x68\x81\x1e\x12\x08\xbf\x46\x0c\x87\x1e\x12\x69\x8c\xbb\xe4\x02\x08\x50\x8a\x04\x5f\xb8\x01\x37\x04\x5f\xce\xe7\x4d\x00\x38\xc4\x49\x64\xae\x37\xc1\xdf\xf8\x02\x5e\xc0\x42\x25\xbe\xc0\x17\xd1\xee\x09\xf4\x42\xa4\xed\xc2\xfb\xee\x0a\x65\xfb\x7f\x09\x08\x17\x06\x43\xc7\xbd\x32\xe8\xc0\x65\x5f\xc0\x80\x7b\xbd\x79\x05\xa9\x96\x16\x4b\xef\x3a\x3c\x04\x7f\xca\xf9\xbb\xe8\xab\xe2\x2f\x0b\x8f\xe6\x93\x10\xd0\x7c\xe5\x4a\x33\xdd\x3c\xff\x0a\x06\x34\xb3\xeb\xf2\xe7\x14\xce\x28\x26\x5f\xff\x2e\x3a\xf0\xc9\x07\xb5\xef\x32\x28\x9b\x5f\x2c\x09\xd9\xc0\x49\x8f\x24\x5b\x52\x72\xd3\xd9\xa9\x86\x25\x19\xa9\x74\xea\x85\x8c\xbb\x06\x56\x7a\x37\x27\x5d\x9f\x92\x4c\x6f\x28\x09\xa9\x60\xaf\xcc\x07\x99\xe8\xc5\xd3\xda\x03\x37\x38\xe7\x73\xb0\x52\xf7\x9b\x88\xf6\xa8\xfa\x0d\x81\x74\x60\xcc\x86\xcd\x51\xec\xc4\x26\xa2\xb9\xa6\xba\x65\x2f\xbd\x37\xa1\x25\xbc\x86\x95\x16\xbf\xfe\x03\xab\xa9\xcd\x33\x86\xc4\x0d\x60\xa2\x44\xbf\xb8\x82\x88\x96\xcb\x3c\xcf\x5d\xbe\xda\xdc\xdc\xcc\x35\x37\x83\x3f\xf8\x3f\x7b\x46\xf2\xcf\x9e\x81\x8c\x05\xed\x41\x88\xdc\xc7\xd3\x0a\xa7\x20\xf8\x53\x7f\xff\x16\xb7\xf9\x2b\xce\xc9\x8b\x78\x8c\xdc\x87\xda\x83\x2c\xca\x86\x3e\xe3\xb9\xa1\xcf\xd0\x1f\xfc\xc3\x9b\xc9\xe6\xf0\x05\xcd\xf3\x18\x7e\x1e\x1f\xc1\x0e\x77\x05\x11\x3e\x7e\xd0\x2a\x39\xa0\xf4\x52\x10\x7f\x3a\x4c\x54\x5a\xaa\x5e\x97\xc6\xe1\x84\x65\xef\xc2\x0d\x18\x75\x86\x38\x57\x79\xfc\xb3\x2f\xe8\x7b\x73\x2e\x4c\x49\x4b\x37\xe4\xa4\xb3\x38\x2e\x60\x05\x8c\x25\x2e\x26\x2e\x3b\xb0\x80\x99\x3c\x6f\xee\xe4\x54\x4b\xaa\x35\x8d\x3b\x83\xfe\x78\xf9\xdd\xe5\xe0\x4f\x5c\x4a\x0c\xd8\xbf\x80\x99\x34\xff\xbf\x9a\xd3\x38\x06\x47\xad\x20\x16\x27\x6e\x59\xb6\x90\x9e\xf4\xc5\xa7\xf7\xca\xca\x2c\xd6\x32\x16\x46\x9e\x79\x81\xd7\x70\xe4\x7f\x35\x13\x3f\x5f\x74\xbf\xbc\x3c\xd7\x5d\xf3\xc1\xe9\xb3\x38\x9e\x58\x54\x75\x36\xe8\x32\x73\xef\xca\x97\xdf\x94\xe9\xcb\x74\xa5\x5c\x00\x4c\x80\xcb\x2f\xcf\xe2\x87\xc4\xa2\xaa\x73\x41\x97\x99\x6f\xaf\x5c\xfb\xb6\xcc\xe0\xae\x59\x06\x93\x60\xfa\x45\xe2\x52\x75\xcb\x91\x2b\xf4\x77\x0b\x2e\x7d\xc8\x76\xb6\x62\x29\xf5\x2e\x5c\x83\xcb\xaf\x5e\xe0\x75\xc2\x47\x88\xbb\xd2\x15\x1e\x6e\x07\xbb\xd7\x0e\x49\xf3\xeb\xf6\x37\x6b\x7d\x3b\x3b\x44\x6f\xc2\xc9\xe6\x88\x77\xa6\x54\xc4\xef\x4c\xfb\x65\xfe\xef\x4b\x7f\x99\x4f\x86\x1d\xbb\x10\x72\x91\x81\x6f\x24\x17\x2f\xb4\xb5\x1c\xe3\x7e\xb9\xf2\xdb\x85\xa7\x5f\xd4\x96\x56\x57\x56\x56\x93\xa0\xf4\x5e\xbd\x78\x51\xd0\x76\x76\xf4\xe2\xd1\x4b\x47\x2f\x21\x63\xb7\x2e\x58\xb7\x8e\x59\xb7\xe0\x68\xdd\x56\x6e\xcc\x85\x91\x67\xc7\x5c\x24\x37\x35\x2c\xbb\x78\x86\x0e\x56\xb2\x8e\x0e\xd1\xb9\x03\xeb\x97\x77\xa5\xba\x6f\x87\xd0\x04\x05\xf1\x67\xbb\x27\xdf\x2e\xe8\xff\x11\xa2\x60\xb4\x10\xdd\xee\x05\x52\xf7\x73\xfb\x79\x98\x85\x65\x50\x80\xbd\x58\x97\x97\x53\x43\x6c\x1c\xba\xa3\x1f\x7a\xd1\x0a\x82\xdc\x4f\xfd\x1a\x76\x2d\xf2\x14\x1b\x74\x25\xf8\xf4\x65\xfa\xd6\x99\xab\x77\x58\x4b\x2e\x6f\x61\xa0\x17\x2a\x71\xde\x5d\x5c\xcb\x60\x0d\xaa\x91\xc5\xad\xa8\xe4\x2a\xca\x8d\x25\x0c\x7f\xdf\x04\x3d\x61\xa7\x04\x5a\x3a\x3b\x60\xb2\x60\xc2\x1e\x70\x9f\xe0\x37\xe7\x06\xe5\xb2\x9b\x2c\xd6\xcb\x07\xf5\x24\x48\x33\xef\x18\x79\x9a\xbf\x67\x82\x5e\x6e\xc1\xdd\x9d\x5f\x7e\x0d\x76\xa2\xf9\x55\xfd\xd7\xd7\x68\x97\xa5\x1f\x85\x29\x9d\xa3\x89\x84\x1b\x1d\xea\x3b\xcc\x8f\x0f\xcb\x1a\xee\x71\x06\x8b\x21\xd7\x98\x4b\x0a\x93\x9d\xd7\xa9\xdc\x58\xf3\xf6\x68\x7a\x4a\xe2\xd8\x20\xf4\x66\x51\xd5\x39\x91\x80\x64\x90\xc3\x70\xe0\x61\x2f\x0d\x74\x28\xf4\x5a\x04\xdd\xd8\xce\x71\x42\x2d\x05\xd3\x94\xf0\x95\x92\x53\x38\x06\x7b\xbb\xc2\x05\x42\x29\x84\x0b\xe1\xf0\xb9\xc4\x4d\x04\x99\x4b\xe6\x0a\x77\x85\xbb\xba\x28\xe7\x53\x2d\x50\x4a\xa8\x15\x0e\x40\x9d\x97\xf3\x16\x54\x49\xb0\x0e\xe5\x84\xc2\xb9\x57\xcc\x8b\xf1\x8b\xfd\x98\x01\x53\x60\x23\x0d\xcb\x21\x18\xc6\xc1\xfe\x93\x2c\x4c\x17\xbb\xe6\xae\xc0\xef\x31\x13\xf7\xd3\x78\x12\x5e\xa1\x41\xd8\xb8\x99\xe5\xc5\x50\x07\x32\xc2\x31\xca\xf9\x29\x85\x7e\x93\xb1\xcf\xb7\x38\xf1\x1c\x2e\xac\x91\xe3\x74\xf1\xcb\xa4\x67\xdb\xbe\x59\x87\x83\x26\xf8\x0a\x35\x28\x22\x7c\xa0\x09\xed\x6e\xff\x4d\x06\x39\x12\x4f\xb0\xa7\x4b\xbc\x9c\x01\x50\x25\x79\x1d\xe0\x92\x11\x91\x4a\x71\xe8\xee\xa8\x7d\xac\x82\x78\x25\xda\xb7\xbb\xb1\x95\x03\x19\xc8\x44\x0a\x87\x1a\xed\x54\xa7\x7d\xb1\x78\x6b\x44\x54\x28\x37\xff\x80\xf2\x8a\xb8\x35\xa2\x71\x2b\xbb\xd8\x61\x47\x7b\xa7\x1d\x65\xff\x4f\x2a\x52\x10\x93\x5e\x07\x50\x0a\x87\x44\xd4\xa5\x84\x32\x85\x58\x0d\x06\xa5\x5b\xcd\x47\x68\x0a\x54\x2a\xba\x7b\x78\x29\x44\x7f\x38\x16\x53\xae\x5b\x38\x97\xd0\xa5\xa6\x1a\x52\x99\xd4\x54\xb3\x35\x95\x73\xdd\x82\xb9\xc9\x78\x83\xc0\x7e\x5a\x38\x8e\x62\x78\xc9\xc0\x4b\x38\x5e\x29\xd1\x72\x82\xdd\x21\xa3\x4a\x32\x8b\x32\xac\xec\xeb\x17\xf0\x82\xc8\x31\xe9\x79\xbd\x5e\xcf\xe7\xf4\x78\xef\xf5\x0b\x7c\x41\x64\xe8\x32\x55\xe9\x74\xba\x5d\x55\xac\x63\xe1\x51\xff\x85\xfe\x91\xd8\x3b\x1b\xbb\xcb\xb7\xc6\xc7\x6c\x5e\x43\xaf\xdf\x19\xd4\x1a\xc7\x2e\x71\xcd\x32\x66\x5a\x32\xf3\xb2\xe4\x59\x6f\x3e\xf2\x04\x88\xec\xf6\x5c\x5b\x1e\x97\x67\xb3\xd8\x8d\xf6\x25\xc2\x2c\xdf\xd6\x9d\x3b\xf7\x1f\xa1\x8f\xc5\x1e\xd8\x5a\xc3\xe6\x03\x73\x00\xba\x9d\x3f\xe2\xf0\xc3\xcd\xbe\xb9\x46\x0b\x6f\xb1\x58\xf8\xdc\x1e\xef\x39\xdd\xed\x17\x5b\xed\x45\x25\xb4\x0f\x1c\x54\x3a\x46\xc2\x6a\x2f\xc7\x9f\xc2\xd7\x14\x74\x87\x8d\xd0\x1d\x36\xc0\x5b\xb0\xe1\x06\x74\xbf\x06\x3d\xee\x41\x37\x92\x17\xf3\xe2\xcc\xe0\x20\xdd\x56\x26\x24\xc4\x6a\x0f\xe5\x90\x46\x0b\x8e\xc2\x6c\x7c\x1f\x75\x38\x08\xf4\x38\x0c\xb2\xd1\x0f\x4c\xa4\x36\x64\x6b\x56\x30\x13\x1c\x92\x67\x0f\xe5\x60\x13\x7e\x01\x1f\xe1\x3d\xf8\x14\xbf\xca\xe8\x5c\xe9\x9b\xd7\xda\x6a\x6d\x65\xda\x5a\x75\xd9\x7b\xba\xd2\xa3\xb7\xc1\x03\x28\x17\xde\x82\x36\x4f\x1e\x8e\x78\x39\xec\x8e\x4c\x0a\xcb\x85\x39\x62\x24\x92\x51\x84\x51\x78\x9e\xc1\x52\x0c\x83\x48\xa8\x86\x6a\x70\xd3\x52\x18\xfc\xe7\xfc\x80\xf3\x1c\x6c\x85\x75\x04\xf4\x42\x1a\x67\x7e\x8d\x5b\x18\xd7\x14\x7c\x86\xcf\x5c\x53\x5c\x53\xe0\x19\x3e\x13\xa6\x08\x8b\xe0\x18\x5c\x15\xe6\x9d\xd2\xed\xcb\xda\xcf\x75\x6e\x13\xf9\x54\x43\xe3\x61\xe8\x07\xb3\x61\x30\x6c\xf5\x14\x5e\xc2\x6c\x88\x80\xd9\x5e\xce\x7b\x02\x41\x69\xf3\xd3\x79\xad\x96\x0c\x0e\x9e\xaa\x0a\x60\x02\xa6\x14\xed\x0d\xe1\xde\xb0\x32\x33\xf9\x74\xbb\x96\x5c\x7a\x1e\xba\xe9\x9a\x99\x66\xe8\x66\x3d\x7f\x9e\xb3\xe7\xf3\x25\x99\x76\x12\x2f\xc1\x5c\xea\xe4\x96\x03\x81\xab\xb7\x6c\x59\x1d\x78\x60\xcb\xc9\x13\x07\x0e\x9c\x60\x05\xae\xcf\xc9\x2d\x07\x56\x07\xbe\xe1\x9d\x38\xe9\xe6\x41\x2e\xf4\xa0\xd6\xc6\x6c\x09\x4a\x64\xad\xc9\xe6\xc4\x24\x1a\x97\x62\x18\x0e\xc7\x72\x2c\xc3\x30\x18\x0e\x4b\x2b\xcd\x95\xb9\x15\xec\x96\xaa\xe8\x03\xc7\xe9\x6b\x67\x4e\x5f\xdb\xb3\x3b\x3d\xae\x86\xbd\x7f\x0e\x3c\xda\xa0\x87\xf5\x06\x5c\xf5\xb5\x14\x16\xe6\x17\xea\x61\x7b\xa0\x6f\x63\x69\x53\x75\x2b\x73\xf2\xc0\xe6\xc0\xc0\x2d\x9b\x57\x07\x6e\x39\x70\x82\xc3\xb5\x47\x16\x60\x1b\xbc\x9d\x03\x9e\x21\xf7\x97\xc9\x6b\x6a\x9a\x4a\xf6\x30\xd7\xce\xac\x98\xcb\x81\x33\x92\xca\x95\x8c\x54\xb2\x3e\x70\x7f\x2f\xbc\x0d\xc3\x41\x06\xb3\x61\x38\x5c\xf2\xe4\xe1\x12\x84\xc3\x70\x58\x00\xc3\x21\x1c\x2e\x79\x39\xa7\x09\x43\xa9\xac\x7c\x15\x9f\xa5\x25\x23\x22\xe6\xa8\xd7\x32\x6b\xe7\x14\xee\x8e\xe0\xde\xb0\xb2\xb2\x78\x95\x2d\x8b\x0c\x3c\xf1\x34\xa7\x81\x69\x78\x9a\x7b\xe2\x04\x67\xb3\xf1\x45\x59\x36\x12\xcb\x60\x24\x05\x16\x09\xfc\xd4\xc7\x7d\x0c\xff\x87\xda\x12\x17\x1a\x96\xc2\xe6\xa6\x9a\x53\x53\x68\x1c\x8f\x0b\xd0\xd7\xed\x6b\xe0\x7c\xf0\x85\xf1\x65\xe6\x72\x4b\x29\xbb\xad\x7c\x47\x6b\x3b\x7d\xee\xe8\xd1\xf3\x8d\xbb\x54\x89\x95\xec\x8d\xe3\xbf\xec\xfe\x27\xf7\x12\x54\xfb\x9a\xed\x76\x5b\x81\x1e\x96\x6c\xf2\xdd\x55\xbc\xab\xbc\x89\x39\xd8\x1a\xba\x69\x53\x68\xe8\xa6\x4d\xdb\xf6\x1c\x34\x72\x38\x6d\xff\x72\xcc\xf9\x47\xff\x34\xe2\xe6\x1a\x79\x65\xe5\xae\xa2\x06\xe6\xfc\xd1\x75\xcb\x38\xb8\x24\x04\xfa\x29\x03\x95\xd0\x01\x43\x7f\x81\xc1\xbf\xc0\x90\x5f\x60\x08\xfc\xe8\xe5\x78\xe5\x58\x48\x2d\x6a\x20\xce\x88\x77\x25\x54\xc7\x6e\x4f\x48\xd8\xce\x62\x8b\xd8\x6f\xf4\x58\x3f\xf4\x1c\xf3\x18\x3c\x59\x9e\x37\xc1\xdb\x34\x0c\xc5\x1e\xa2\xed\x55\x09\xbb\x76\x55\x57\xef\x62\xa1\x4d\xfc\xf2\xc7\x07\x2f\x5f\xfe\x38\xae\x1f\xbb\x50\x0c\x39\x18\x4b\xa1\xe7\x18\x7f\xf4\x40\x8f\xd1\x8f\x5f\xb1\xf0\x8e\xf8\x52\xf4\x8f\xbb\x08\x7c\x47\xbc\xbd\x3a\xa1\xee\x8d\x4a\x6f\x18\x22\xc6\xb7\xbb\xa2\x80\x7e\x04\x96\xf2\x93\xc0\xe0\xe1\x0a\xe2\x98\x27\x0f\xf7\x61\x23\x7c\xfb\xef\x7e\xdf\xcb\x79\xcc\x71\x95\x82\xbe\x9f\xc2\xca\x0b\x04\x28\xc4\x90\x8a\x2b\x61\x21\xa6\x63\x1a\xae\xc2\x05\x98\xcc\x76\x7a\x88\x97\xae\x5b\xbf\x6c\xd9\xba\x23\xe7\x59\x28\xc5\xfb\x62\x2c\xe3\xf5\x3c\x8b\x1a\x08\xc0\x00\xd0\x80\x0a\x56\xc0\x12\xc8\x60\x05\x41\x7c\xee\xe8\xd1\x73\xe7\x8e\xae\x5b\xc6\x0a\xf5\xf8\x0b\x85\x0d\xe2\x65\x6f\x14\xcf\xb1\xb0\x53\x8c\x2b\x97\x60\xdf\xcf\x09\xac\x16\xa3\x0a\x96\xe3\x52\x50\x83\x06\x02\x20\x00\x34\x2c\xcf\x5b\xa0\x8c\xf6\x41\xd9\x95\x38\xe5\x15\x4f\xde\x7d\xf4\x52\x10\xa7\xc1\x9f\xc2\x9e\x83\x06\x61\x4f\xd6\x15\xe7\x08\xe8\x0c\x10\xe2\x44\xd0\xf3\xcf\x3f\xa1\x27\x2b\xc4\x75\x06\x38\x02\x5c\x71\xa2\x2b\xce\x00\x3f\x25\x34\xed\x82\xf1\xdf\xc1\x04\x81\x80\x09\xfc\x77\xbd\x79\xd8\x04\xef\xc0\x46\x81\xe8\xa2\x9b\xbe\x83\x8d\x6e\x22\xfd\xf3\xb4\x74\xbd\x07\xdc\x57\x78\xff\x44\xe1\x7e\xbc\xdf\xb9\x50\x68\x74\x86\x8b\xa5\x11\x1e\xb8\xb1\xf3\x12\xdc\x94\xc0\x7e\x98\x40\xc1\xa6\xce\x85\xb8\x49\xe4\x0c\xf7\x86\x4d\x22\xe9\x4a\x0f\xdc\x88\x9b\xc4\x70\xe0\x43\xaa\x73\xa1\x58\xfa\xe4\x34\xdc\xff\x10\xef\xe3\x78\xa1\xc9\x39\x53\x84\x9b\x5c\x4d\x6e\xb5\x03\x30\x81\xea\x5c\x08\xf7\x3e\xc4\x7b\x38\x5e\x68\x74\xce\x14\xff\x5b\xe3\x83\xb2\x1f\x1c\x3d\x2b\x05\x01\xe6\x78\xf2\x70\x14\x42\xc0\x17\x42\x60\x0d\x44\x43\xad\x97\x73\xb7\x50\x4c\x3d\x82\xb5\xca\x87\x1c\x3e\x13\xa6\x53\x0f\x61\xad\xf2\x11\x27\x5c\x74\x7d\x44\xe1\x6c\x64\x70\x00\x4e\xdc\x18\x94\x57\x1c\xca\xe2\x66\x31\x86\x6c\x26\x1c\x3d\xc5\xf7\x72\xef\xb4\x9d\xfb\x7c\xef\xfe\x5d\x47\x4b\x4f\x91\xe6\xe2\x62\x53\x31\x03\x13\xc1\x2d\x3a\xdb\x6d\x63\xda\x7f\x8a\x93\x36\x05\xd9\x8a\xfe\xb7\xe2\x7d\xf8\x54\xbc\xf3\xd0\x89\xe2\x13\x0c\x4c\xfa\x57\x5a\x70\xc2\x1c\x3f\x25\x54\xd9\x12\x0e\x95\xc1\x08\xe8\x03\xe9\x87\x2d\x97\xc1\x06\x7d\x7a\x0b\xc7\x60\x3c\xfc\xd5\x96\x05\x7d\xa5\x37\x3d\x14\xde\x17\x85\xe7\x94\xb1\x3a\xe7\x18\x48\x96\xe4\xc3\x5b\xf2\xd5\xb1\x04\x8c\xf9\x64\x7f\x13\x06\x32\xab\x36\x65\x6b\x56\x71\x96\x24\xf7\x8d\x63\x83\x6a\x73\x44\x38\x7b\x3d\x89\xc8\x56\xe7\xa8\x55\xb4\xb4\xa7\x7a\x26\x0c\xbe\xec\x47\xcf\x47\x19\x0e\x58\x10\x8d\x63\x60\x66\xab\x89\x35\x95\xc1\xbc\x03\x44\x55\x6e\x51\x79\x25\xbd\x33\xb1\x2c\x3e\x03\x95\xe1\xba\x78\xb6\x22\x2b\x69\x77\x3c\xa3\x56\xab\xf5\x6a\x4e\x3a\x44\x1d\x9e\x39\xcd\xd8\xb2\xc8\x95\xd2\xcf\x37\x29\x47\x95\x9c\x44\x27\x54\xa6\x54\x37\x08\x33\xfe\x28\x3e\xc7\xda\xd5\x36\x75\xa1\x96\x5c\x7d\x13\x58\x34\x5f\x60\x1e\x80\xe4\x9b\xeb\x47\xb9\xc2\xd2\xe2\xc2\x4a\x83\x79\x0d\x7a\x7f\xac\x0b\x23\x73\x22\x4d\xa1\x11\x74\x1a\x9f\x6a\x4e\x65\xb3\x76\xd6\xea\xeb\x98\x2f\xaf\xd6\x18\xbe\xe4\x4a\x3b\x6a\x3a\xf4\x77\x8c\x2d\xbe\x3a\x78\x2b\xac\x74\xc2\xcd\x9c\x5c\x9d\x35\xc7\x9a\x97\xeb\x5b\x60\x26\xe0\x73\xf4\xee\x94\xe2\x58\x08\xe0\x80\xfc\x0c\x94\x47\xc0\xe3\xcb\x81\x3f\x7c\x78\x73\x16\xbc\x85\x12\x08\xc4\xf7\x20\x0c\x8b\x35\xe4\x25\x50\x51\x36\x6b\x65\x71\x11\x2d\xed\xe5\x51\xbe\xb9\x51\xb7\x87\xdd\x5f\x75\xc2\x74\xa8\x00\x34\xe7\x61\x32\x48\x5f\x42\x6c\xf5\xe1\xaa\xa3\xe6\x13\x59\x99\xbe\xef\xe3\xcc\xd4\x75\x38\x19\x65\xe8\x35\x0e\xfb\x04\x60\x9f\xd5\xa4\xb4\xa7\x3a\xde\x44\x7c\x2d\x56\x19\x03\xf5\x69\x97\xb6\xd5\xca\xe7\x7d\xb4\x7e\xd6\xb0\x90\x0d\x29\x3b\x92\xe3\x37\x93\xcd\xd7\xbf\x2a\xbc\xc3\xdc\xde\x6d\x51\xd7\x72\x3b\x35\xe5\xf1\xfb\xd7\x93\x52\xc2\x03\xb7\xbf\xfe\x80\xaa\xc5\x51\x44\x56\xfb\xc1\x9c\x83\xcc\x83\xef\xca\x1a\xbf\xe1\x5a\x53\xe6\xc1\xa8\x30\x66\x2e\x8e\x0a\x0b\x09\xe0\x50\xeb\x60\xa8\x07\xb8\xad\xe3\x38\x21\xed\xa9\x46\x4f\x98\x45\x08\xab\x5d\xbb\xa8\x74\xd1\x42\xd3\x27\xa9\x0b\xb3\x6c\x1b\x7d\x77\x5b\x61\x7a\xc5\x2e\xda\x6a\xc8\x33\x5a\x59\xd7\x3a\x07\x49\xd9\xd4\x6a\x4b\x06\x13\x97\xa0\x36\xc4\x71\x79\x29\x04\x1c\x76\x39\xa9\x61\xe2\xf6\x22\xcd\xf7\x84\xe3\x0f\x05\x71\x8b\x32\x89\x8d\x62\x5e\xcc\x7b\x1b\x72\x8c\x7a\xb3\x99\x30\x59\x29\x93\x89\xf0\xc1\xcc\xef\xcf\x40\xef\x79\xd7\x81\x80\xb7\x7a\xf3\xf0\x48\xe1\x9d\x71\x5a\x5a\x27\x3d\xaf\xf0\xce\x5d\x4d\x99\xb3\x2c\x1a\x95\x8a\x94\xd6\x69\xb5\x53\x96\x8f\xc8\x1c\xa9\xc5\x9e\xd9\x33\xae\xab\x8a\x72\xcb\xf3\x6d\xa4\xcd\x9e\x67\x2d\x64\x0a\x0c\x7c\x8e\x95\xdb\xbe\xe7\x54\x1c\x78\x30\xe0\xf1\xf5\xee\xba\x3d\x9c\xb4\xa3\xac\x28\x4f\x63\xce\x22\x83\x40\x4c\xd9\x52\xb2\x34\xe9\x59\xaa\x6c\xa3\x45\x55\x43\xd6\xa8\x34\x35\x8b\x99\xc5\x49\x09\x71\x51\x5c\xf4\x0e\xb5\x56\x53\x4c\x4a\xeb\x34\x25\x96\xe2\xca\xf2\xca\xf2\xa6\xfa\xc6\x22\xb2\xa8\xb1\xd4\x50\xcf\xd4\x37\x1a\x32\xaa\x38\xe9\x89\xaa\xf4\xa2\x48\x5b\x0a\x09\x00\x7b\xa8\x15\x29\x1f\x6c\x59\xc4\x6e\x5e\x1c\x1b\xbf\x26\xf7\xd3\x5c\x7c\x1b\x96\x4d\xb1\x90\x96\xc1\xb8\x0d\x83\x70\x32\x33\x30\xa2\x64\xe7\x36\x4e\x5a\xb7\xaa\x75\xc7\x59\xd3\x57\x66\xf0\x85\x77\xa0\x27\x8c\x34\x41\xa0\x19\x94\x18\xf8\x87\x99\x34\x3d\x84\x71\x30\xf1\x1e\x23\x6d\x79\xb8\x73\xcc\x4a\xce\x7d\x23\x12\x96\xe3\x43\xd8\xb0\xbc\x85\x1d\x7d\x6e\x5c\xcd\xb8\x73\x2b\x5b\x67\x3e\xfc\xb4\x83\x94\xd6\xa9\xb1\x7b\xe8\x9a\x4d\x61\xe3\x66\x2f\x4f\x98\xbe\x85\x5c\x10\x86\xbf\xe0\x7a\xd7\x1c\xda\x35\x57\xf0\xc2\xaf\x84\x61\xc2\x50\x78\x05\x27\x84\x00\xd6\xa7\x06\xc2\x1c\xad\x10\xee\x09\xef\x43\x98\x63\x0f\x84\x79\x39\xcf\x0a\x5b\x28\x1c\x0a\xc3\x70\x2c\xfa\xe3\x50\x1c\x16\x19\x19\x18\x38\x89\x0f\x3c\x21\x0f\x3c\x69\xbc\x77\xf2\x44\x61\xa1\xaf\xbb\x56\xa5\x1a\x33\x26\x12\x7b\x36\x22\x21\x1f\x99\x30\xe7\xc3\x21\x34\x8a\x7e\x1e\x01\xc4\xef\xdf\x5d\xff\xb9\x9a\x05\xef\x68\x78\xa7\xe9\xc9\xe3\xa6\x26\x5f\x18\x0a\xc3\xdc\x1e\x1c\x81\x4f\x1d\x53\x29\xff\x47\xf8\xf6\x6e\xf4\xda\x4e\xfe\x96\x3a\xfe\xce\x7b\x0c\x12\x23\x46\xa0\x68\xf0\xf5\x0f\x7f\x4e\xe4\x42\xb1\x7b\x03\xf6\xfd\x79\x64\x53\xa4\x2f\x2f\x86\xa1\x38\x0c\xc6\xa2\xbf\x5b\xdb\xed\xcb\xe1\x30\x18\x16\xd5\x18\x78\x82\xbf\x7f\xe2\x84\xfc\xc4\x89\x7b\xfc\x89\xc0\x22\x95\x2f\x0c\x83\x61\x84\xa3\xed\xf5\x01\xea\xf9\xd4\x87\x83\x4a\xd8\x06\xf0\x8e\x80\x77\xfc\x1f\x47\x35\xf9\xba\x15\xde\x28\xe2\x30\xf0\x47\x7f\x18\x86\xc3\x9a\x22\x4f\x04\xf2\x93\x02\x03\xe5\x6f\xc6\xa3\x2a\xf2\x75\x0f\xaf\x50\xf5\xf3\x08\x90\x47\x03\xd9\x26\xe7\xc5\x1f\x54\x7e\xff\xf1\x9f\x0c\x10\x3f\xff\x0c\x22\xce\xe0\x14\x28\x10\x8d\xf8\x19\x89\xfe\x63\xa7\x0e\x4a\x67\x91\xdc\x83\x7d\xa2\x46\x8e\x8c\x8a\xf4\x75\x9b\x75\x5f\x1f\x82\x17\x43\x57\x0b\xe0\xef\xee\x4c\x53\xd3\x9b\xbe\xc9\xdf\x34\xa4\x52\xf9\xba\x07\x52\x54\xf4\xd3\x4f\x8d\x40\x85\x81\x58\xfe\x67\xc9\x37\x8f\x9e\xd3\x3e\x68\xdf\xe7\x1c\x7a\x0c\x24\x57\x3d\xf9\xfd\x8e\x79\x87\x85\x9b\xfb\xbd\x1c\xef\x0a\xeb\x29\x73\xbe\xfa\x68\xb6\x39\xdb\x8c\x6f\x9d\x4c\xc9\x4f\xb7\x6d\x2b\x49\xb5\x1d\xb9\xd9\x70\x3a\x37\xdf\x56\x7a\xfc\xa9\xc9\x6a\xca\x33\xd5\x18\xad\x46\x6b\x8a\x66\x87\x96\xdc\xa1\x5d\x1f\x99\xac\x4f\xc9\x59\x96\x10\xa5\x89\xd2\x2c\x4f\x8d\xcf\x8e\xcf\x4e\x34\xaa\x72\x48\x53\x4a\x6e\x36\x4f\x5b\x74\x45\x19\xc5\xfa\x92\x9c\x9d\xa6\x02\x4b\xa1\xb9\xc2\x6e\xce\x35\xe7\xea\x8b\x72\x73\x73\x2d\x67\x8b\xab\xf2\xaa\x6d\xdf\xd6\x17\x18\xf5\xaa\x05\xd8\x3b\x61\x2b\x99\xb8\x15\xdf\xc2\x89\xb1\x51\x89\x71\xeb\x96\xa6\xaa\x72\x0d\x8d\x16\xab\xa5\xa5\xfa\xcc\xf5\x8a\xea\xcf\x3e\x3f\x7a\xb5\xed\x2c\xc9\x8b\x6d\xfa\xf3\x6b\x4b\x35\xa5\x9a\x8b\x61\xc5\xd9\xc5\xba\x13\x71\x66\x1b\x89\x9b\x84\x14\xaa\x58\xaf\xcd\xd5\x30\x1a\x63\xa4\x36\x4d\x97\x9e\x13\x91\x99\xa1\xcf\xd0\x47\xe5\xe6\xe4\xe6\xe4\xda\x43\x8b\x32\x6a\xe2\x2b\xf4\x76\x23\x59\x55\x97\x97\x57\xca\x95\xe6\xd5\x15\x17\x54\x9a\x73\xad\x36\x7d\x39\xe9\xf8\x14\x29\x6a\x1a\x2e\x04\x6e\x13\xa1\xc0\x48\xd7\x4d\xca\x59\x26\x76\xcc\x83\x74\xe2\x75\xb9\x58\x38\xfc\x90\x0a\x06\x06\x43\xae\xae\xc7\x6e\x03\x76\x43\x84\xd0\xf2\x67\x04\xcc\xed\x1c\x40\xb8\xfe\x76\xc6\x53\xc2\x4d\x58\x45\xb8\x7a\x8a\xb1\x54\x81\x66\xea\xd0\xcc\x88\x94\xa8\xa4\xb0\x34\x79\x20\x8a\xc6\xa5\x62\x2f\x66\x20\xf6\x6e\x3f\x32\x8a\xcb\xcb\x58\xdb\x98\xc9\x68\xb4\x5a\x75\x96\x39\x27\x4f\xc7\x7d\xfa\x00\x96\x2f\x78\xc9\x3c\x10\x35\xb6\xe4\xe5\x35\x72\xbf\x96\xfd\x79\xe0\xfe\x67\x07\xe6\xfa\x9e\x01\x7f\x02\x0e\x39\xef\x52\x38\xe8\x18\x21\x8c\x13\x17\x67\xe6\xab\x33\x3b\xbb\x61\xb8\x21\x8b\x75\x9d\x85\x40\xc2\x25\x13\x8f\x8b\xfa\x34\x51\x6f\xcc\x36\x68\x0d\xd9\x59\x06\x83\x51\x67\xd4\x93\xaf\x2f\x8b\x8d\x26\xa3\x91\xd6\x5a\x6c\xba\x7c\xa6\xc0\xb1\x09\x74\xb6\x32\x8e\x37\xf1\x8e\x12\x34\xb2\x5d\x90\x6f\x71\x6e\xb7\xcb\xbd\x41\x1c\x1c\xef\x82\x7d\x85\xf6\x2e\x46\x3b\xc8\xbc\xa0\x1d\x3e\x57\xa2\xec\x4d\xf6\x55\x90\x05\x4a\x9c\x1d\xc0\x29\x15\xc4\x46\x1c\x4f\xc1\x78\xf1\xe9\x88\xaf\x82\xf7\xb2\xee\x59\x4c\xec\x0d\x9e\xb1\x7b\x05\xd3\xe9\x7f\x45\xa2\x70\x7a\x84\x28\x1d\x2f\x44\xf3\x95\x9c\xc3\x2e\x7e\xba\xf2\xfb\x69\x87\xd9\xce\xb8\xd7\xdb\x67\x29\xc1\xde\x29\xfb\xef\xf8\x0c\xec\xd4\x6b\x99\xdb\x75\x42\xff\xef\x94\xe0\x2f\xf2\xd1\x4b\xc0\x0e\xf6\xae\x14\xf3\xe5\x12\xa1\xa7\x04\xca\x25\xd2\xcf\xfe\x52\x10\xd3\xa1\xea\xff\x48\x76\x3d\x52\x72\x40\x99\x24\xe9\xec\xc0\x76\x6a\x86\x52\x3a\xa3\x7a\xfe\x29\x09\x06\x78\xaf\x90\x48\x47\x9d\xfe\x48\xf9\xe6\x64\xc6\xff\xa2\xd2\x0d\x0f\xdd\x45\x19\xfe\x8b\x8b\x35\xff\x0d\x2c\xd6\x95\x37\xa8\x58\x57\xde\x80\x62\x41\x80\xf7\x87\x12\xc1\xae\x70\x9e\xa6\x26\x29\xa1\xc3\xfb\x43\x89\x74\xea\x48\xb0\xbf\xee\xf8\xff\xd2\xf1\x71\xa9\x30\x4b\x21\x5a\xec\x29\xc8\xba\xbe\x3c\x7a\x29\xbc\xeb\x9c\x31\xd4\xde\x7d\xfc\xa5\xe0\x7d\x5b\xf7\x2e\xe2\xb7\x06\x63\x12\x26\xf9\xba\xbc\x45\x98\x04\x49\x6f\x38\xf2\xe0\xad\xfc\xa2\xbd\x5b\xe1\x08\x1e\xf1\xed\xbc\x0a\x1f\x2b\x05\xd9\x15\x97\x0c\x3e\x56\x3a\xae\x8a\xe1\x08\x1c\x21\xf0\x2e\x4c\x48\x93\xf8\xf8\x05\x2a\x0f\x28\xbd\x1c\xd5\xce\x13\x14\xf8\x0d\x81\x8d\x38\x1e\xa9\x25\x28\x47\x6f\xf4\xfb\x1d\x37\xc2\x38\xa0\x2e\x80\x1c\xbc\x59\xfc\xd5\x95\x48\xc1\x00\xec\x0e\xab\xd1\x1f\x3d\x57\x0e\x18\x82\x03\xa0\x3b\xae\x02\x7f\xe8\x76\xea\xaf\xdf\x58\x81\xad\xa7\xd0\x80\x0f\xf0\x05\x6a\x90\x78\x14\xf6\x1b\x07\x03\x40\xf4\x03\xd0\x20\x03\x8f\x51\x40\x33\x7f\x3f\xaf\x02\x29\xa8\xf1\x01\xbc\x44\x03\x07\x5a\x08\xa1\x60\xdc\xef\xb0\x11\xfc\xc0\x7b\x09\xc8\x91\xc2\xf1\x43\x70\x23\xfa\xa1\xf7\x05\x94\x03\xc5\x09\x1f\x3f\xa7\xd0\x1f\xbb\xe3\x6a\x1c\x30\xe4\xd4\x40\xe8\x06\xfe\xd0\x1d\x56\xc1\x80\xdf\x56\xfe\x8d\x9e\x9c\xcf\x6b\x15\x70\x92\x2b\x0e\x99\x97\x23\xc0\x99\x45\x81\x1d\xfb\x43\xdd\x9b\xaf\x53\x58\x87\x76\x5c\xfb\x18\xfb\x82\xcf\x1a\x76\x7d\xe7\x17\x44\xa8\xa1\x3e\xaa\xd5\xed\xec\xb6\xd6\x37\xb6\x1a\xb8\xf5\x8e\x2f\x08\xf0\x39\xfe\x18\xfa\xc2\x5a\xda\x3d\x3b\x0f\x28\x3d\x79\xa0\x15\x44\x0a\xc8\xbc\x9c\xb2\xe1\x94\x23\x4b\xec\x90\x41\x3a\xd1\xd9\x53\xdc\x19\x20\x14\x53\x9d\x9f\x82\xcd\xd1\xb5\xa3\x8d\x00\xda\x40\x9d\xd9\x76\x7c\x75\x05\xdb\x19\x00\x76\xc2\x9a\x9e\x66\x49\x63\xd2\xd2\xf4\xba\x74\xae\x33\x00\xed\xc4\xea\xe4\x6d\x6b\x96\xd3\x9d\x76\xf1\xda\x5d\x1b\xdb\xe3\x59\x47\x80\x4b\x46\xa8\x2b\xab\x75\xd5\x4c\x75\xb5\xb5\xb0\x92\x73\x04\x08\x32\xa2\xbd\x66\xd7\xa1\x63\xb4\x8f\xd0\x64\x4b\xf0\x14\xec\xc0\x08\x6f\xc3\xdf\x12\x87\x6c\x28\xf8\x4a\x1c\xd3\x3b\xc5\xe0\x2b\xe9\xfc\x05\x7a\x50\x50\x25\x16\x64\x30\x81\xc0\x4a\xb1\x2b\x00\xc2\x28\xd7\x42\x58\x22\x74\xed\xb8\x84\x70\x30\x9d\x2b\xa9\x53\x91\x47\xd7\x54\xb3\xae\x4f\xe0\x53\x42\x78\x4f\x7c\x2a\xe2\xe8\xda\x6a\xd6\x15\x00\x01\x84\x2d\x35\xc5\x92\xc2\xa4\xa4\xe8\xb3\x52\x39\x57\x00\x06\x10\x6b\x13\x22\xd6\xad\xa2\x5d\xef\x89\x5d\x9f\xe0\xa7\xff\x9d\xf9\x8b\xd7\xd4\xaf\x3f\x9c\xc0\x0a\x01\x18\x47\x40\xb1\xc4\x62\x32\x9b\xcc\x66\xb9\xd9\x60\x36\x5a\x8c\x6e\xa6\x2f\x14\x4b\x88\xc3\xd5\xf5\x47\x8e\xd3\x3e\xd0\x64\x80\xc5\x38\x01\xc2\x60\x1e\x8c\xb6\xc1\x52\x03\x2c\x79\x05\xe1\xbd\x79\x68\x12\x56\xc0\x4e\x8c\x86\xa6\xef\x20\x57\xda\xea\xa1\x10\x4f\x50\x78\xef\xa1\xb0\xa7\x2b\x1f\x7a\x8a\xa1\xc8\x35\x95\x82\xde\x97\x67\xe0\xdb\x85\x9c\x6b\x98\x08\x7a\xe4\xdf\xbb\x03\x3d\x98\x32\xd7\x77\x14\x0e\x9a\xfa\x08\x06\x72\x8e\x81\x22\x53\xa9\xa9\xac\x8c\x86\x9d\x38\x1a\xe2\x71\x3f\xee\xc6\x25\xb8\x15\xeb\x71\x2f\xcc\xc6\x95\xd0\x0e\x51\xd0\xef\x77\xd8\x7a\x9d\xc5\xed\xa2\x29\x3b\x06\x6f\x9e\xc6\x28\x9c\x5f\x9c\xa4\xa4\x2b\xd4\xf0\x27\x9c\x15\x4b\x57\x7a\x80\xcf\xdd\x55\x48\xa1\x74\xc4\x16\x24\x38\x3c\x21\xec\xa1\xe0\x18\x14\x8b\xa5\xd3\xd5\x7f\xfe\x18\x8d\xa4\xdf\xac\x8d\xef\x73\xae\xb3\x42\x1e\xa5\x40\x99\x00\x62\x48\x86\x70\xe8\x06\x76\x18\x3d\x1d\xba\xe3\x88\xc3\x1c\x10\x67\x2e\x7e\x07\x52\x5a\xba\x67\x3a\xe4\xe2\xa2\xcf\x31\x82\xf5\x11\x7c\x21\x12\x3f\xba\xf5\x07\xf8\x98\x60\x41\xee\xdd\x2e\xc4\x87\x19\xd0\x8a\xad\x70\x0d\x66\x9c\x12\xbe\x04\x99\x34\xe2\xf4\x0e\x49\xa7\xc6\xe5\x45\x01\x03\xdd\xb7\xe2\xa8\xc9\xc1\xab\x66\x6d\xe3\x9e\x45\x1f\x9b\xf9\x3e\x8d\xfe\x48\xcf\xc6\xfe\xac\xab\xb7\xa3\x41\x04\x7f\xe3\x2d\xea\x8b\xc3\xf5\x5f\x76\x2c\x2d\x5f\xc8\xb9\xdd\x5b\x11\x2c\xc4\x27\xd4\xad\xf3\xb5\xf7\xee\xad\x69\x99\xc6\xe1\x12\x8c\x14\x39\xbe\x0e\xa7\x8e\x7d\xbe\xeb\x78\x29\x07\xac\x08\xfb\x6c\x1a\xf3\x29\x2a\x19\xa9\xcd\x03\xe7\xa0\x37\xbc\x0d\x9f\xc0\x34\x78\x0b\xfa\xc2\x0c\x98\xfd\x07\xf6\xc3\xc9\x1a\x5e\x63\xd4\x70\xae\x11\xa2\x91\xc7\x97\xff\xcc\x4a\x35\x1e\x1a\xa1\x1b\x35\x7d\xf5\xda\xe9\x3a\x0e\x6c\xa2\x3b\x59\x41\xc7\xa6\x30\x52\xbf\xe9\x38\x0e\x2a\xa9\xa9\x70\xfb\xae\xd8\xa7\x1a\x65\x3f\x0a\xfa\x1f\x97\xc3\x10\xe1\x15\x0c\xe9\xad\x10\x85\xc1\x10\xe9\x11\x85\x68\xb8\xf3\x53\x0a\x18\xec\x06\x9e\x48\x23\x83\x9e\xe8\x89\x0c\x32\xe0\x89\x9e\xc0\x00\x0d\xdd\xc0\x13\x18\x56\x7a\xb7\xb3\xb0\x33\x85\x42\x0e\xbd\xd0\x0b\xb9\xa1\x13\xce\x7c\xbb\x89\x95\x1e\x69\x4f\x6d\x4f\x69\x4f\xfd\x7b\x13\x90\x27\xdb\xff\x6e\xff\x7b\x35\x88\x07\xb4\xf7\x3f\xe8\x9b\x5b\x51\x61\xae\x60\x80\x83\x2e\x61\xce\x71\xcb\x91\x4c\xe1\x14\x54\xa2\x02\x27\xbb\x69\x57\x74\xd1\x64\x50\x82\x12\xa6\xb0\xd2\xbb\xee\x22\x2a\x71\x32\x07\x43\xfa\x48\x8f\x40\x2e\x6e\x84\x8d\x98\x8b\x16\xdc\x88\xeb\xd1\x6c\x60\x71\xaf\x6b\x28\x61\x52\xab\x4c\x2a\x66\xc1\xe2\x94\x88\x55\x9c\x4b\x0e\xa3\x08\xd7\x0c\x31\xa4\x8c\x20\xa4\x77\xf1\x83\x16\x50\xa2\x18\xc6\x31\xf0\x31\x0c\x04\x06\xa6\x97\x71\xc2\x5c\xb8\x4d\x40\x2e\x6c\x84\x0d\x60\xed\x7a\x69\xe4\x7f\xeb\xac\x90\x76\x52\xe8\x73\x0c\xde\x02\x7f\x4f\xe1\xe6\x45\x98\x79\x42\xe8\xeb\x3e\x93\x79\x29\xbc\xbf\x75\xbe\x4d\xf9\xf9\xc3\x5f\xca\xc7\xfe\xfd\x58\xd7\x2b\xd7\x43\x0a\xba\x8d\x79\x82\xdd\xd2\xd3\x0c\xfa\x0c\xf6\xbb\xb0\xfb\xe1\xfb\x47\x84\x4f\x92\x87\x4d\x1c\x11\x34\xa9\x39\xac\x24\xbc\x38\xac\x98\x5c\xd0\x72\x6d\xe3\xd7\x0c\x74\x7b\xf2\x04\xba\x71\x4e\x85\xe3\x12\x35\x44\x02\x1b\x95\xae\x50\x31\x9c\xc4\xb7\x88\xda\x03\xc7\x8a\x4f\x32\x05\x76\xde\x68\xe7\x20\x1e\xee\x10\xb0\xda\x0c\x63\xc1\x1f\x56\x33\xb0\x16\xc6\xe2\x58\x5c\x8b\x81\x38\x16\xc7\xe1\x5a\x0e\x7f\x47\x2b\x81\x8a\x0c\x14\xfb\xa1\x1f\x83\x32\xf4\xf8\x09\xde\xde\xce\xe1\xf4\x1b\x04\x7e\x20\xc6\x31\x40\x21\x05\x63\x58\x67\xc0\x40\x25\xf2\x8e\x70\x0a\x68\xf4\x00\x0f\xa4\x51\x8e\x1e\x5d\xf0\x74\x72\xf0\x40\x0f\x90\x03\x0d\x1e\xe0\x01\x72\xd6\xa7\xda\x90\xb0\x2f\x41\x41\xac\x4a\xec\x5d\xa6\x10\x3d\x94\xc6\x38\xee\x0a\x5e\x94\xeb\xe3\xb2\xa9\x45\x3c\x1d\x39\x7a\x25\x76\x3b\x30\xbc\x72\xc3\xa1\xc0\xcf\x72\x84\x09\x51\xbe\xe6\x9a\x52\xc1\x9b\x70\xf5\x15\xbe\xa7\x5c\xb3\xca\xc1\x6f\x2c\x31\x19\x7b\x85\x2e\xe0\x69\x3e\x74\xc1\xfe\x25\x2c\x2c\x45\x07\xc1\x57\xc3\x32\x88\x87\x02\x16\x06\x8d\x20\x9c\x6d\xc8\x52\x3c\x4e\x1d\x89\x3f\xb7\xb3\x59\x30\x03\x43\xf0\x35\xa4\xb8\xbc\xb4\x30\x81\x80\xf7\xad\xb7\x6c\x3c\xcd\xdf\xce\xdb\x75\x95\x85\xc5\x80\x44\xe7\x2e\xe7\x48\x6a\xfe\x8d\x8f\x7e\x1b\x64\x0f\xb4\x2e\x48\x8d\xde\x80\xf1\x28\xf8\x56\xaa\xe0\x26\x2e\x22\x20\x4a\xe8\x7e\xec\x0b\x9e\x76\xf4\xc7\x4b\x54\x92\x1a\xaf\xe1\x4a\x02\x52\x5d\x9e\x7b\x3e\xe6\xe9\x1f\xeb\xa0\x47\xd5\x99\x07\xbb\x0e\x96\x5d\x8e\x39\x42\x22\x08\x8f\x28\xa9\x75\x26\x50\x41\x9f\xf3\x34\xbf\xf5\xd2\xac\x6c\xd6\x35\xd8\x44\x48\x63\x78\x18\x83\xdd\xa0\x07\xde\x66\x71\xe8\x58\x61\x7c\x22\xc4\x08\xdd\x09\x1f\x68\x02\x19\x44\x29\x85\x38\x21\x00\x92\x25\x6d\xd0\x01\xd3\x25\x20\x60\x07\x24\x77\x7d\x35\x84\x9e\x83\xfe\xc4\x9e\x2c\xec\x92\x74\xda\x45\xe0\x23\x41\x99\xe8\xac\x04\xda\x24\x67\x25\x20\x83\x78\x09\x34\xf1\x10\xa5\x54\x88\xfd\x1c\x32\x0a\x76\x49\x50\x06\x71\xa2\x41\x12\x57\x00\x74\x48\x50\x26\x06\x1f\xc9\x7c\xd1\x59\xc9\x15\xa7\x7d\xbe\xf8\xac\xe4\x0a\xac\x90\x08\x32\xf1\xbf\x16\x15\x4e\x3f\x57\xdc\x25\x25\xac\x12\xe2\xdc\x2d\xae\x72\x9f\xf8\x54\x27\x78\x36\x2b\x88\xd3\x5e\x0a\xe2\xe1\x15\x68\x53\xba\x06\x0a\x83\x08\x48\x86\x3f\xfe\x2d\xad\x86\x3f\x94\x02\xa1\xdc\x23\x81\xbe\x12\xce\x25\x73\xc9\xec\x12\x58\x2d\x72\x0d\x74\x0d\xb2\x4b\x20\xf9\xdf\x82\xb0\x59\xa4\x9f\xaf\x9d\x33\x8f\x0e\xab\x8f\xd9\xc3\x42\x87\x68\x4f\x7d\x7d\xcb\x55\xed\x97\xfa\x2b\x9c\xb0\x79\x9b\x44\x50\x43\x6f\xe8\x05\x62\x4f\x1e\x34\xce\x6f\x61\x93\x97\x13\xe1\x5b\x2a\x3a\x3e\x31\x36\x43\x9b\x6b\x53\xb1\x5f\xba\x7f\x8c\x6d\x38\x88\x99\xf0\xa1\x3a\x75\x0a\xa7\x57\xa5\xea\x32\x99\xc8\xa4\xda\xba\xe6\xca\xd2\x9d\x56\xae\xfa\xd7\xa7\xc5\xbf\x33\x30\x19\x86\x6c\x9d\x0a\x14\x57\xa9\x2a\x54\x47\xd3\xcf\x20\x9c\x0a\xdb\x1e\xb3\x2d\x55\x6d\xcb\x53\xb3\x5f\x61\x2f\x9c\x71\x12\x97\x32\x43\xc6\xa7\x27\xcd\xe2\x72\xd2\xb4\x39\xe9\x4c\x58\x4c\x7d\x4b\x4b\x59\x4d\xb3\x9d\xab\x7d\xf4\xa4\x02\x28\x06\xd6\xc1\x8a\xd5\x23\xe1\x03\xae\x2e\xad\x20\x29\xc6\x3d\x23\x4d\xd4\xa6\x6d\x91\x5b\x53\x35\xb9\xf9\xe9\xec\xf7\xc8\x61\xc4\x51\x0c\x62\xde\x7d\x57\x13\x33\x84\xd3\xab\xd3\x75\x69\xcc\xe6\x88\xe6\xf6\x83\xbb\x6a\x1b\xf2\xb9\x66\xf0\x04\x9f\x52\x90\x33\x90\x00\x9a\xb5\x03\x61\x06\x57\x9b\x5e\x96\x14\x4c\xc3\x26\x1c\x4c\xf9\x49\x3a\x55\x28\x53\x88\xd4\xb0\x52\xa9\xf0\xbe\x49\xc1\x39\x3c\x23\x36\x18\x62\xa2\x8d\x0c\xbe\x8b\xbb\x36\x44\x12\xae\x5c\xd7\x18\x68\x16\xd5\x46\xe2\x39\xd7\x3d\x02\xcf\xc1\x19\xb1\xd9\x5c\xdf\x60\x62\xe0\x5d\xd8\x75\xb8\x89\x10\x72\x85\x31\xd8\x2c\xda\xb1\x9b\xf0\x11\x9a\x04\xe1\xd7\x6f\x2a\xae\x57\x7a\x0a\xfb\x8f\x9d\xfd\x0c\x98\x93\xfb\x7e\x7a\x71\xd3\xcb\x51\x07\x13\xa8\x0c\xa3\x46\x93\xc1\xa8\x34\x05\xc5\x46\x2e\x1d\xb2\x4b\x84\x2a\xa2\xb8\xb0\xb0\xa8\xb8\x40\x9d\x61\x62\xcb\x5c\x55\x04\xb4\x60\x28\x65\xdc\x41\x68\xf5\x59\xd9\x3a\x56\xa7\xcb\xca\xd1\x32\x99\xda\x5c\x5b\x36\x97\x63\x35\xe4\xe5\xd1\x5d\xab\x02\xd5\xa0\xe2\x4d\x3c\x5d\x20\x7c\x6d\xca\x23\x0a\xac\xf6\x7c\x2b\x6b\xb5\x58\xcd\x79\x79\x56\x83\xb5\xc7\x7b\xf9\x3a\x6b\xa6\x86\x2e\x72\x7d\x4f\xbc\x6e\x07\x8a\xb2\x1a\xf5\xb9\x3a\x46\xa7\xcf\xd1\x19\xb9\x14\x94\x95\x63\x6f\x42\x67\xb2\xe4\x58\x19\xab\x25\xd7\x6a\xe2\xaa\xa0\x37\x71\x0d\xb6\x50\x56\x63\x8e\x5b\x2c\x27\x47\xc7\xf3\x7c\x1c\x6e\xe1\x76\xe2\x7a\x22\x3b\x37\xc7\x6a\xcd\xcd\xb5\x9a\xd8\x5d\xb0\x81\x00\x1b\x1a\x29\x5e\xcc\x8b\x71\xb1\xa0\xa2\x6c\x3a\x6b\x76\xb6\x4e\x97\x65\x64\x13\xd0\x50\x8d\x1a\x22\xdb\x64\xd5\xe5\x31\x79\x56\x6b\x1e\x57\x07\x1a\xe2\x06\x58\xa9\x7c\x63\xb6\x35\x8b\xc9\xca\xd6\x69\xb9\x04\xb4\x56\xa3\x9e\xd0\xe6\xe9\x6c\xb6\x3c\x6b\xbe\x89\xdd\x09\x7a\xe2\x16\x64\x50\xf9\xc6\x2c\x9b\x96\xd1\x66\x65\x69\xb9\x44\xcc\xa8\x42\x23\x91\x69\xcb\xca\xcf\xb7\xd9\xec\x26\xb6\x1a\x8c\x04\xbc\xc6\xec\x37\xad\x1e\x74\x78\x52\x05\xda\xfc\x4c\x4d\x96\x56\x63\x64\x79\x9e\x4f\x76\xf5\x64\x2b\xd0\x48\x68\x4c\x36\x6d\x01\x63\xcf\xcf\x2f\xe0\x78\xb1\x5b\xa7\x43\x08\xa6\x0a\x33\xf3\x35\x6a\xad\x56\xdd\x25\x99\xea\x0a\x65\xcb\x50\x4f\xa8\x4d\xf9\xda\x42\xa6\xc0\x9e\x5f\xc8\xf1\xe2\x4a\xd0\x13\xdf\x0a\x56\xaa\xc8\x98\x59\xa0\x62\xd4\x1a\x8d\x8a\x4b\x75\x59\xca\x50\x47\xa8\x4c\xf6\xcc\x42\xa6\xc8\x6e\x2f\x32\x71\xbc\xb8\x02\x74\x84\x20\x41\x35\xc5\x8b\xe1\x1b\x09\x90\x4a\x0c\x74\x64\x50\x25\xea\xc2\xf4\x74\xb5\x3a\x9d\x4d\x77\xd9\x4a\x50\x4b\xa4\x9b\x0a\xd4\x25\x4c\x49\x61\x61\x09\xc7\x8b\x4b\x41\x4b\x3c\x10\x54\x54\x99\x51\x5d\x94\xc6\xa4\xa9\x54\xa9\x46\x4e\xe5\x52\x17\xa1\x9a\x48\x33\x15\xa9\x4a\x99\xd2\xa2\xa2\x52\x8e\x17\x97\x80\x9a\x80\xc0\x3e\xe9\x0e\xa9\xb1\x30\xbb\x20\xd3\x2a\xb7\xe4\x64\x9b\x75\x8c\x36\x4b\x9f\xa3\xe3\xb2\xb2\x73\x32\x8d\x99\xa4\x5e\xac\xea\xec\x99\x87\xdd\xf3\x50\x44\xa4\x98\x4a\xd2\xcb\x99\xf2\x92\x92\x72\xce\x7d\x49\x4a\x20\x95\x70\xfe\x56\x49\xc1\x28\x94\x82\x14\x47\x06\x05\x6b\xd3\xb7\xb1\x90\x1f\x87\x61\xb0\x16\x4b\x98\xf9\x0b\x55\xf1\x01\x5c\xbc\x36\x5b\x9b\x42\xbf\xee\x2b\x4e\x2e\xc9\x28\x37\xb0\x6e\x1f\x6a\x17\x8c\x04\x29\xf4\x86\x91\xac\x0f\xda\x21\x5f\xd9\x05\xd6\xed\xb0\x3b\xec\x54\x9e\xa4\xd3\xee\x9d\x27\x11\x64\xde\x79\x12\x9d\xc4\xbb\x2b\x7d\x9c\x18\xfb\x71\x28\x13\x63\x3f\xf8\x0d\xc5\xb0\x5f\x52\x29\x61\x41\x26\x86\x7e\xf8\x1b\x88\x5d\x93\x59\xb7\xff\x23\x3b\x13\x96\x00\x75\xa7\x1b\x2e\x0b\x71\x4f\x25\x42\xf9\xa5\xbc\xe3\x91\x6d\x5d\xe9\x38\x22\x0e\x74\x25\x86\x6f\xb3\xf7\x53\x4a\x7b\xea\x05\x7f\x91\xab\xd0\xf5\x11\xb5\xf8\xf8\xca\x87\xa1\x2f\x8a\x6e\x98\x2e\x99\x2e\x93\x05\x7c\x41\x01\x2d\x25\x49\x0b\x6f\x36\x5a\x58\xb3\xd9\x64\x31\x59\xf2\x9a\xf5\x35\xaa\x12\x52\xda\x66\x2f\xd0\xaa\xac\x69\x8c\x51\x94\x20\x4a\x4c\x4b\x8b\xcd\xe2\x92\xe7\x16\xa0\x77\x33\x7a\xee\x18\x1f\x3a\x66\xfd\xa8\x2d\x13\x43\xe6\x45\xac\x22\x4d\x46\xb3\xd1\xc4\xea\xf2\x35\x16\xad\x0e\x7b\xce\x5b\x3e\x55\xb3\x4e\x9f\x98\xab\xb6\xea\xba\x70\xec\x8d\xb5\x2a\x5f\x9d\xdd\x6e\x28\x60\x2e\x7d\xfb\x08\x3e\xfe\x87\x7b\xb5\x17\x06\xee\x06\xae\x94\xdc\xf0\xe0\xb7\xa8\x2b\xcc\xe9\xd2\xaa\x0a\x0b\xc7\xf3\x26\x9e\x35\x99\x4c\x66\x93\xa9\xb0\x36\xbb\x22\xab\x80\x6c\x8f\x1d\x97\x3f\x87\x09\x09\x32\xe8\x36\x71\x11\x15\xd1\x15\xb1\x55\xa4\x74\xba\xda\xd5\xe1\x1a\x41\x95\xee\x39\x76\xed\xce\x85\xf9\x03\x37\x6e\x8c\x4c\x27\x85\x77\x9d\xc3\x28\xb7\x26\x2d\xf5\xf6\xcb\xcb\xca\x53\x9b\x92\x4d\x06\xde\x60\x32\x1a\xf4\x46\x83\x51\x4f\x4a\xbd\xa7\x1b\x54\xfa\x74\x43\x8a\x21\xc3\x90\xa6\x4f\x75\x1b\xd1\x9e\xe3\x8f\x17\x34\x90\x52\x92\xc4\x9e\x9d\x83\xa9\xd2\xfa\xd2\x86\xd2\x06\x52\xda\x93\x6c\xbb\xd5\x70\xb5\xf2\xf3\x3d\x33\x0f\x2f\x3a\xb1\x91\x94\x92\xde\x76\x6d\x41\x56\x81\xd6\x2d\x38\x38\x79\x70\xf4\x98\x50\xd2\x41\x97\x51\xa6\x2e\xd7\xd8\x98\xa3\xe3\x33\x99\xc8\xf5\x05\x15\x81\x1c\x78\xee\x4a\xd2\x59\x39\x1f\xbd\xc4\x69\x07\xa9\x44\x98\x68\x83\x9f\xff\xc3\x90\x52\xe0\x36\x94\x51\x70\xda\x6f\x94\xe8\x0f\xd7\xbc\xdc\x54\x73\x8a\x29\x43\x6e\x4e\x20\x72\x45\xb9\xd5\x96\x62\x53\x79\x6e\x99\x1c\xde\x13\x0e\x12\x20\x12\xc1\x7b\xae\x83\x6e\x01\x4b\x86\xdc\x94\x65\xd6\x66\xd3\xb9\x22\x73\xb5\xa9\xd8\xec\x96\xf9\x43\x98\x47\x8c\x7a\x05\xa7\xfd\x66\x89\x70\x42\xe7\x60\x02\xc7\x88\x50\x26\x24\xeb\xca\x8c\x65\xfa\x12\xb9\xbe\x96\xc8\x11\x69\x8d\x5a\xa3\x96\x35\xa4\xea\xd3\x74\x69\x28\x73\x25\xfb\xba\x65\x26\x38\x06\x13\xb3\x44\x5d\x3d\x7b\x2a\x11\xbe\x7d\x3e\xea\xf9\x75\x90\xad\x50\x4a\xe1\x0d\xc0\x55\x48\xe7\x6e\xea\xba\x08\x56\x40\x1b\x2e\x81\x3a\x62\xf6\x2b\x38\xe4\x37\x4d\xf4\x12\xc7\xe4\x67\x5a\xb3\x72\xb3\xe4\x66\xbd\x59\x6f\xca\x21\xcd\x22\xa3\xbd\xb4\xa8\x92\xfd\x07\xc6\x10\x33\x5e\x41\xb3\xdf\x1c\x11\xae\xc4\x56\x08\xc0\x5d\xc4\xf5\x7e\x22\x29\xe2\xe1\x97\x5f\x8b\xfc\x60\x6c\x56\x41\x76\x5e\x4e\xbe\xdc\x60\x31\x58\x8c\xb9\xa4\x41\xa4\xcf\x4e\x4b\x52\x71\xef\xe1\x58\xe2\x4e\x3f\xdc\xd3\xe5\xac\x67\xc0\x24\x20\xa0\x1a\x74\x4f\x25\x42\x25\x14\x65\x74\x75\xa7\x53\xfd\xa6\x3f\x71\x9d\xbb\xa9\x9f\x85\xcf\x46\xbc\x12\xbc\x45\x47\x8f\xe6\xa4\xed\xe3\xbe\x0f\x3d\x33\x1e\x3d\x69\xf4\x5c\x36\x7c\x54\x04\x9b\x11\x12\x64\xd8\xc8\xa0\x12\x27\xfd\xd2\x0f\xef\x89\xe0\xa5\xd0\x87\x92\xbe\x56\xef\xde\x65\x2d\xa8\xe6\x0e\x56\x57\x1d\x3a\x47\x9f\x4e\x6c\x0f\xa9\x66\x8b\x12\x62\xf2\x42\x19\xec\x81\xd5\x5d\x8d\x6e\x93\xe0\xb4\x04\xa7\xec\xa9\x04\x92\x24\x2b\x94\xd2\xcf\xba\x5a\x43\x99\xab\x83\xc2\x0e\xe8\x70\xff\x35\x47\x2a\x09\xe9\x03\x0c\xe8\x02\x15\x72\xda\xc5\x9d\x1d\x82\x9d\x7a\xf9\xe8\xd1\x4b\x78\x28\xe1\xba\x7e\x63\x5d\x80\x1d\xfc\x9b\x34\x71\xbd\x79\xf8\xc0\x5d\x5e\xa1\x94\xfe\xb6\xd7\x21\x53\x78\xab\x61\xb1\x04\x64\x68\x87\xc5\x5d\x2f\x0d\xfe\x3d\xa3\xa4\xe5\x7b\xbf\x52\x8a\x1c\x8b\xa1\x98\xc2\xab\x70\xf5\xdf\xb7\x1d\xaf\x65\x57\x24\x5d\x09\x6f\xe0\x98\xf2\xcd\xab\x10\xd7\x62\xd0\x53\xe5\xd9\xe5\x99\xb6\x2c\xb8\x86\xd7\x7c\x6d\x59\xf6\x94\xbc\x14\xd2\xd5\x43\x24\xed\xe7\x27\xc8\xe0\x7b\x89\x02\x3d\x16\x4b\x04\x3b\x68\x95\x2e\xff\xef\xdc\x9d\xef\x14\xe3\x39\xaa\x41\x1b\x5b\x19\xc5\x4c\x06\x99\x20\x55\x8a\xa4\x33\xa7\xbf\x8f\x8f\x13\x16\xf2\xb4\x2e\x45\x9f\x92\x4c\xa3\x17\x78\x4c\xec\x82\x67\xf6\xb8\x0f\x5e\x15\xfa\x72\x5d\x39\x2b\xed\xe7\xc7\xc7\x7f\x31\x0e\x0e\xb0\xd2\x99\xd3\xb1\x9f\x6b\x2b\xf5\xf1\xd2\xc6\xd6\xd6\xf3\x8d\xb7\x6e\x9d\x8f\x0a\x0d\x5d\x1a\xf5\xb1\x7b\xb0\x82\x0c\xec\xc2\x9b\x8b\x35\x1f\x64\xd0\x01\x32\xe9\xc9\xae\x2b\x26\x9d\xd9\xd9\x88\xc1\x94\xca\x9a\xa1\xd7\x64\xe2\x44\x9c\xe4\x8b\x7d\x27\x28\xa1\xaf\x08\x26\xe2\xa4\x7f\xb3\x84\xbe\xc9\x11\x2a\xb4\x8b\x8b\xb5\x45\x2a\x2b\x2b\x8c\xed\x9c\x45\xa5\xa7\x5b\x0b\x54\x5c\x74\x4d\xce\x81\x9d\x0d\xe4\xd5\x7b\xad\xbf\x3f\xa7\x9f\x87\xfe\x3e\xef\x1e\x1b\xd7\x90\x7b\xa0\x61\x67\x7d\x4d\x7b\x4e\x4d\x34\xf9\xfd\x80\xa3\x48\xa1\x2f\x8d\xbe\xeb\x90\x9a\x30\x80\x4d\xcd\x48\xd6\x26\x31\x18\x02\xef\x53\x69\xa9\x79\x85\x19\x5c\x6c\xad\xa1\xbd\x6e\x17\xd9\xd2\x56\x79\xf4\x04\x7d\x22\xe9\x68\x58\x1b\x1b\xbb\xcb\xdc\x5e\x57\xbb\xab\xb6\xdd\x58\xbb\x9d\x3c\xb7\x68\xf7\xd4\x0f\xe9\x0f\x23\xa6\x2e\x5b\xc4\x66\x64\xa4\x64\xa5\x30\xff\x4e\xfc\xae\x81\x74\x74\xdd\x0b\x9d\x5d\x03\xe9\x94\xa1\x8c\x72\xc9\xfe\x92\xb8\x64\xff\x22\xf9\xc8\x92\x95\x82\x4c\xfc\xad\x44\xfa\x4a\x50\x1b\x28\x53\x4e\x8e\x29\x87\x11\x3c\x24\x1c\x56\x60\x25\x31\x4a\x0c\x6e\x92\x9d\x67\xff\xdf\x03\xec\xf8\x77\x80\xee\xc9\x31\x20\xc1\xe9\xfb\x7f\x22\xc7\xf9\xa3\x8c\xc2\x04\x3c\xa3\x55\xf3\xa9\xf9\x6a\x39\x24\xe0\x99\xc2\xf4\x2a\x7d\x49\xa1\xfc\xd4\xbe\x92\x42\x4b\x95\xba\x44\x8e\xf3\x20\x07\xe6\x41\x4e\x61\x89\xbe\x2a\xbd\x50\xbe\x6a\x5f\x7a\x61\xa2\x5e\x9d\x2e\x77\x1c\xc2\x33\x14\x26\xc0\x19\x75\x49\xa2\x25\x5d\x2d\x5f\xb5\x35\x5d\xad\x4f\x2c\x4c\x97\xc3\x3c\xcc\xc1\x79\x98\xa3\x4e\xb7\x24\x96\xa8\xe5\xa7\xb6\x96\xa8\xab\x2c\x85\x25\x72\x48\x80\x33\xf9\x85\x7c\x99\xb6\x50\xde\xe9\xe1\xda\x44\x5d\xd6\x94\xeb\xcb\x0b\x2d\x15\x72\x60\x1d\xb7\x2d\xe5\xea\xf2\x64\x8b\x7c\x41\x41\x8a\x25\x45\xad\x4f\x96\x23\xdb\x79\x5b\x9f\x52\x98\x52\xa1\x97\xfb\x08\x69\xb0\x45\x78\x02\x16\x4f\x47\x32\x94\x41\x3c\x54\x7b\x29\x88\x6f\x1c\xab\x29\xcd\xa6\x4d\x39\xc1\x0c\x06\xe3\x38\x18\x08\xf9\xd0\xeb\xf8\xd5\x1b\x57\x0f\x2d\xc1\xb7\xe6\x24\xcf\xc8\xd8\xc8\x5d\x45\x02\x3e\x6e\xe5\xe9\x7d\xdf\x57\x81\xc7\xaf\x34\xe4\x63\x1f\x78\x1f\x33\xd1\x80\xfd\x71\x31\x9a\xd1\x08\x62\x0c\x81\x25\x43\xd9\xc9\x38\x66\x00\xf6\xeb\xd7\x0f\x97\x41\x1a\xce\x84\xcb\x1f\x0b\x7f\x91\xd8\x26\x82\x3e\xaf\x33\x05\x1a\x3b\xfe\x59\x78\x31\xf4\xa4\xf9\x74\xd3\x83\x63\x90\x0b\x56\xf0\x83\x63\xe4\x85\x9b\xb6\xb2\x9b\x9c\x0f\x2c\x92\xc0\x70\xc7\x07\x6f\x76\x59\x0c\x44\x08\x5e\x14\xd4\xc0\x1c\x78\x8c\x3b\x08\x44\x71\xe7\x07\xc2\x21\x0a\x0a\xc5\xb0\x1c\x29\xc2\x21\xea\x1c\x4f\x01\x8a\xe1\x31\xec\x80\x1a\x9c\x43\x74\x4e\xfe\x89\xc2\x3a\x98\x07\x5d\x3b\xce\x23\x3a\xa7\xfd\x42\x61\x0d\xcc\x11\xfe\x14\x06\xba\xd5\x1d\x22\xbc\x41\xc1\x72\xa0\x08\x2c\x14\xe3\x03\x88\xa5\xf0\x31\xec\x20\x00\xc5\xc2\x9f\xae\x81\x04\x44\xf4\xa9\xcb\xa8\x4b\x28\x61\x3b\x2f\x09\x87\x88\xfc\x8c\x34\x6b\x1a\x93\x96\xa6\xd3\x66\x70\x9d\x97\x5c\x87\x88\x84\xf4\x8c\xd8\x58\xda\x75\x48\x1c\x5b\x1c\x5b\x9d\xce\x3a\xdc\x3c\x6d\x57\x40\x76\x69\xa9\x35\xbf\x98\x73\xb8\xb5\xaa\x4b\x8a\xeb\xea\x68\x1f\x68\x32\x41\x1a\xbc\x0b\x3a\x4f\x5e\x41\x7a\x78\x29\xc4\xa4\xc3\x4a\x15\x99\x8a\x8a\x68\x78\x80\x75\x50\x83\x3f\x62\x0e\x06\xa1\x1f\xae\x1f\xcc\xb6\xad\x59\x54\x33\x9f\xc1\x91\xd8\x0b\x7b\xe2\x07\x51\xb9\x31\xf9\xdb\x39\x7c\xfb\xe3\x89\xd8\x07\x07\xd3\x18\xdb\x95\x8b\x2c\x2e\x83\xb5\x8a\xcc\x22\x93\x48\xe1\x7d\x54\x64\xb3\x19\xf3\x19\x88\x85\xb9\xf0\x09\x44\xc3\x87\xef\xc1\xbb\x38\xe0\x12\xa7\x70\x5e\xc5\x4a\x0a\x3e\x04\xe5\xaf\x30\x82\x85\xab\xe7\x5d\x32\xd8\xc6\xdc\x39\x77\xe2\xee\xcd\xb9\xc7\xe6\x2e\x5d\x1f\x1b\xb4\x85\x8b\x68\x8b\xdc\x1b\xde\x4a\xde\xb8\xd9\xd1\xf0\x3b\x03\xa3\x41\x3e\x04\x27\xe2\x04\xf4\x1d\x8c\x23\x39\xec\x58\x2b\xc8\x30\x86\xf9\xe4\xd3\x35\x33\x67\x7c\xbe\xf6\xd6\x85\x23\x75\x07\xda\xb9\xa6\x90\xe6\xd0\xc6\x10\x72\xf6\xc7\x1f\x47\x0c\x66\x70\x0c\xca\x7f\x85\x29\x9c\xcf\x4b\x89\x53\x06\x55\x92\x91\xca\x5c\x09\x87\x32\x6f\xe8\x03\xef\x84\x2d\x05\x0f\x0e\x57\xe0\x0a\xa2\x62\x45\x40\xc1\x62\x66\xc9\x32\x4d\xf2\x0a\x0e\x57\xc0\x0a\xe2\x3c\x78\xc0\x3b\x2d\xd0\x87\xe9\x9c\xf8\xba\x93\x5a\x0a\x1e\x61\xf0\x0e\xf4\xa1\xa1\x4f\x0b\xbc\x73\x1e\x3c\x58\x70\x6b\x25\xaf\xd0\x04\x2c\xa6\x97\x14\x2c\xab\x58\xc1\x0a\x49\xae\xdf\x29\xec\x83\xef\xb4\x9c\x47\x0f\x0e\xdc\x36\x92\x4f\x9f\xd3\x5c\x60\x2e\x9e\x2d\xa8\x38\xcd\x75\xc9\x2f\x45\x0f\x7c\x27\x0c\xfb\x30\x82\xcc\x1b\x43\xe1\x37\x25\x84\xd6\x48\x04\x99\x12\xa7\xef\x55\x72\x42\x12\x44\x52\x15\xa7\x0b\xce\x5d\xa0\x2f\x68\xce\x25\x9f\x66\xbb\x6c\x9c\x47\x8f\x16\x7c\x07\xfb\xd0\xd8\x27\x0c\xdf\x59\x8a\x1e\xac\x4f\x35\xc6\x41\x9c\x67\x33\xc4\x19\x94\x10\xe7\xa5\x10\x3d\x74\xc8\x28\xe1\x13\xec\x00\x74\xf9\x7f\xc1\x62\x92\x18\x8e\x2c\x86\x18\x2c\xc2\x2f\x68\x7c\x89\x07\xf0\x00\xbe\xfc\x6f\x61\xc2\x17\x10\x03\x45\x70\xe4\x22\x0b\x49\x62\x97\xff\x42\xec\x40\x74\x7d\x42\xbb\xb6\x0b\x7d\x5d\x7d\x85\xed\xc2\x76\xa1\xaf\xd0\x57\xd8\xce\xfa\x54\x2b\x88\xb9\x89\x35\x89\xbd\x2b\x21\x41\xd8\x0d\x69\xc2\x6e\x48\x96\x26\x49\x8f\x54\x3a\x86\x50\x2e\x5d\x9a\xc0\xb8\x26\x08\x3c\x23\x14\x09\xde\xc2\x5b\xc2\xce\x2c\x2e\x5b\x98\x8d\xe9\x30\x03\xe7\x82\x2f\xc9\xc7\x16\xd4\x24\xb2\xbc\xf0\x81\x2b\xde\x25\xc6\x87\x2c\x8f\x6b\x71\x1a\x76\x87\xb1\xec\x20\x50\xb6\x43\xcc\xf9\x7f\x48\xfe\x2a\x78\xff\xd1\xcc\x4a\x93\xde\x03\x31\xc1\xfb\x2d\x5e\x3d\x81\xe5\xad\xe0\xf3\xd5\x73\x16\xfd\x61\x2e\x8e\xc5\xf9\x04\xff\x1d\x8a\xf5\x7e\x2c\x3f\xfb\xef\x31\xfb\xd8\xfe\x28\x26\x78\xa0\x02\xda\x46\xb1\x3c\xf4\xc3\x7a\xe4\x70\x2e\xcb\xe3\x00\x9c\x8a\x73\x60\x36\x8b\xcf\xe1\x6f\xa1\x97\xb0\xbc\xba\x8a\xb4\x5a\xb2\x0d\x46\x06\x2b\x70\x26\x0e\xc4\x72\x0d\xee\x27\x7d\xaa\xd1\x7e\xf8\xf0\x35\xe8\x91\xa0\x20\xd6\x26\xb6\x5c\x3b\x7c\xb8\x37\x7f\xf8\x10\x7c\xa0\x20\xfc\xe0\x83\x43\x87\xa5\x70\xda\xf1\x7a\x00\xb5\xd9\xb4\xd9\x1a\x64\x2b\x7f\xe4\x8b\x03\x1b\x51\xf6\xf5\x07\xaf\xe6\x2d\xf5\x8d\xd9\x1d\xdb\x92\xd0\x4a\xf2\xe2\x25\xdb\x80\xc3\x78\xe0\x71\x18\xb4\x6a\xe5\xae\x5f\x85\x5f\xa8\xb8\x6b\x19\xb7\xbf\xa2\xbf\x2a\xba\xbd\xf3\x1a\xfb\x61\x43\xf1\xfe\xf2\x7d\x95\xad\xf2\xa5\x2d\xc4\x42\x14\x85\xa0\x2f\x72\xb4\xdb\xcb\xf5\xfd\x02\x45\xec\xf9\x96\xa4\xb6\xd4\xbd\xe9\xfb\xe5\xdf\x37\x10\x0a\xef\x1f\x70\x16\x95\x10\x1a\x1b\x16\x13\x31\xef\xbc\xef\x07\x7e\x28\x9b\x86\x03\xa3\x48\x69\x77\x8f\xf2\xb1\x41\x59\x9b\x75\x9b\x8d\x72\x69\x2f\x8f\xb9\x62\x68\xcd\x07\x1e\x86\x01\x07\xf1\x24\x6e\x15\x1e\x52\xf1\x97\xb7\x9d\xdf\x78\x02\x17\xe2\x38\x5f\x29\xa9\x0e\x3e\xb4\x6a\xf7\xe2\xa2\xe3\x90\xe5\x6b\x8b\x08\xb3\x6c\x63\xb6\x85\xe9\xb3\x22\xb8\xe3\x98\xb5\x58\xb5\x2a\x22\x78\xa3\x1c\x17\xc2\xb8\x8d\x81\xdb\x96\xc6\x2f\x90\x43\xfa\x24\x22\x33\x46\x17\x1d\x49\x47\x5a\xa3\xed\x31\x2c\xa6\x4d\xaa\x5e\xb0\x67\xe9\xa1\x40\x39\x2c\x84\x71\x7b\x37\x9e\x8a\xbc\xa8\x92\xaf\xc1\x6c\x22\x7b\x77\x4b\x8e\xe0\x25\xc9\xcd\xdb\xcd\xad\x81\xec\x8b\x45\xa7\x9a\xf6\x1e\x92\xc3\x42\x1c\x77\xe8\xc4\x9e\xf3\xd5\x97\xe5\x98\x76\x8f\xb0\xd7\x5b\x1b\x9a\xe8\x26\x5d\x43\x66\x3d\x0b\xe9\xf7\x08\x17\xef\xe8\x4b\xf1\x62\x6c\xd5\xa2\x11\x87\x22\x87\x09\xe7\xc3\x7c\x6b\x5a\x6b\x5b\xea\x9b\xae\x2e\xf3\x7d\xfa\x0a\x64\x5f\xc3\xc0\x86\x94\x47\xbe\xfb\xf3\xdb\x73\xdb\x4d\xa4\xe3\x76\x67\x0a\x05\x5c\x08\xf8\x2e\x04\x11\xbb\x34\xac\x32\xb4\x7c\x6b\x71\x90\xfc\xc3\x68\x62\xe7\xdc\xa2\x8f\x66\xd0\x33\x32\x3e\x8a\x9b\xcb\x7e\x1f\x9d\x1e\x94\x1a\x9c\x14\x22\x3f\x1f\x46\x7c\x01\xa2\x36\xf0\x05\x8e\xc6\x1e\xc2\x24\x0a\x39\x48\x40\x23\x0c\xc5\xd6\x7c\x72\xae\xb8\xdd\xd8\x9e\xb3\x5f\x9b\x32\xd6\x17\x06\x46\x83\x6c\xda\x53\xbf\xab\xe7\x7c\xeb\x23\x6b\xc3\x6a\x42\xcf\xb7\xf8\xc2\x78\xd7\x24\xca\x15\xe6\xea\xed\xea\xed\x0a\x73\x53\xa1\xb7\x10\x26\x84\x09\x5d\x94\xe5\xc5\xee\xa2\xbb\x8a\x3b\xdc\x27\x57\xc2\xf2\xe2\x91\xca\xae\x37\x74\xf3\x5f\x81\x14\x3a\x60\xe6\x8b\x5f\x61\x0e\x18\x84\x9e\x12\xe8\x0d\x6b\x71\x11\x0c\x85\x89\x5f\x80\xef\x25\xf8\x12\xec\xd2\xce\x87\xc2\xb7\x90\x44\x9d\x59\x64\xdb\xb4\x61\x79\x66\xc0\xb2\x2b\x59\x87\x58\xe9\x4c\x8f\xc3\x27\x8a\xce\x70\x21\x42\x30\x75\x2c\xee\xe0\xaa\xa5\x89\x5b\x57\xae\xac\x09\x3f\xcb\x4a\xfb\x79\x9c\xa9\x6a\x3d\xc9\xc1\xc4\x3b\x54\xaa\x2e\x25\x27\x35\x87\xcc\x4b\xc9\x4d\x49\xa6\xdf\x9d\x37\x79\x40\x22\x1b\xa1\x4b\x4e\x0f\xa3\x43\x8f\x27\x36\xe8\xd8\xef\xd3\x7e\x8a\x1c\x44\x63\xbf\xa1\x6b\x51\xd6\x0f\xdf\x6e\x03\xe9\x57\x47\x0e\x5d\xaf\x61\x2d\xe2\xa8\x72\x55\x7d\x0b\xdd\x9c\xb7\xbf\xb9\x84\xb5\x88\x17\x56\x6f\x7e\xf4\x05\x0d\xe4\x8f\x0f\x40\xb4\x7f\x9f\x26\xa9\x85\x3d\x7a\xb4\xb8\xec\x10\x87\xbd\xc4\x17\x5d\xe3\x29\x4b\x1d\x5f\x57\x47\x0b\x0a\xf1\x4e\xbe\x4e\xbf\x93\x05\xa5\xc8\x10\xc7\xc7\xc5\xd1\xae\xbe\xe2\x18\x3e\xda\x1c\xc3\x0a\x64\x19\x95\x1c\xb6\x35\x3b\x98\x41\xdf\xd4\xe7\xe0\xc1\x41\xa4\xd9\x2c\xd6\x6a\x4d\x59\x4c\x86\xca\x60\x54\x71\xd0\xfd\xd2\x31\x71\xa5\xb1\x42\x5f\xc1\x82\x9f\x48\xb7\xcd\xbc\x6d\x1b\xfd\x02\xbb\x8b\x92\x53\xcc\xc9\xcc\x4a\x8c\x17\x05\xe7\xaf\x3f\x52\x5b\x6b\x2b\xa9\x62\xf1\x6d\x31\x0a\x8e\x15\xd4\xba\x90\x8d\x6b\xd6\x04\x1f\x3c\x76\xbc\xed\xd0\x89\x13\xad\x1b\xd6\xb2\x82\x70\xdc\x4f\x59\x8d\x76\x98\x01\x87\x60\xbd\x90\x05\x9f\xe2\x34\x98\xdb\xfb\x3a\x6c\xc4\xe5\x10\x86\xdd\x20\x18\xfa\xc3\x66\x1c\x04\xeb\xc1\x03\xc2\x20\x00\x22\xa5\xbf\x3c\x14\x7e\xae\xa1\xfc\xa7\x24\xcf\xfc\xe4\xbd\xc2\x1f\x7f\x78\x5c\x7a\xeb\xfa\x6f\xaa\x31\xec\x62\x47\x0e\x35\x31\x7c\x99\xff\x98\x90\xcf\xbe\x7f\xd0\xfc\xf9\xcf\xdf\xb7\xcd\x9e\xce\x42\x0d\xdc\xa5\x62\x3e\x99\x91\x38\x9d\xd9\xbd\x7c\x61\x59\x57\x0e\xab\x01\xa8\xc4\x45\x03\xaf\x21\xf7\xd7\x36\x2e\x47\xbc\x32\x4e\xbd\x60\x15\xbd\xbc\x7a\xc3\xd1\x68\x36\x47\x8c\x9e\x21\x33\x3f\xc1\x1e\x34\x6e\x86\x95\x4b\x61\x1a\x04\xc1\x88\x3b\x90\xcc\x4a\x65\x6a\x68\x75\xbd\xdf\x1f\x3e\xa0\xcf\x34\x56\x9f\x2c\x60\x61\xe2\xee\xe7\x40\xc1\x14\xba\x31\xbb\x41\x53\xcf\xd6\xe7\xed\xb2\xed\xb2\x93\x70\xab\x73\x12\x95\x73\x84\x3f\x7c\x84\x16\x1c\xe2\x76\xe3\x41\x6b\x3b\x8b\xb1\x22\xeb\x26\xe3\xc6\x8d\xb4\xeb\xa5\x78\x3d\xbf\x21\x67\x3d\x0b\xb1\x22\xe1\x77\x88\xa5\xe2\xc3\xb7\xaa\x83\x98\x19\x19\xb7\x2f\x72\xd2\x4c\x0f\xc1\xf3\xa1\xb8\xa1\x31\xa7\x91\x81\xa5\x38\x4d\x2c\xd5\xab\xcf\x1a\xce\xe6\x9f\x65\x31\x51\x64\x8d\x32\x45\x46\xd2\xd2\x77\xd5\xd3\x86\x8a\xa5\x1a\x0f\x5c\x2a\xb6\x54\x56\x59\xaa\x8a\x8a\x0c\xc5\x8c\x54\xaf\xce\x31\xe0\x73\xb1\x74\xf9\x46\x9c\x59\x87\x53\x20\xec\xd2\xe7\x05\x8d\xa7\x59\x57\x87\xc2\x3b\x91\xba\xb3\xec\xf6\xe4\x49\x4b\x66\x4d\x9d\x76\xf1\x93\x6f\x59\xe9\x46\xbf\xbb\x17\x6e\xde\xe1\x7c\x8e\x49\x7e\xf0\x53\xba\x54\x82\xf8\x1f\xe7\xd2\xe7\xbd\xcf\x3f\x5f\xf5\xdc\xa9\x7c\x2e\xbd\x2b\xfd\xc5\xf1\xbd\x73\x15\xf5\xca\xff\x51\x3f\xbf\xb1\x63\xfd\x62\xac\xdb\x0b\x77\xb0\x9b\x36\xac\x5f\xbe\x7e\x0e\xbe\x83\xf3\x91\xc3\xcb\xfb\x5d\xf3\xc8\x18\xcb\xce\xc4\x5d\x66\x13\x6f\x66\x1a\x2c\xd5\x75\x86\xc6\x48\xf8\xe6\x06\x1c\x84\xf1\x60\xd8\x7f\xe1\xc0\x89\xb6\xfd\x64\x7c\xf3\xbe\x8c\x76\x46\x7a\xf7\xe5\xe3\xc7\x2f\x39\xa1\x97\x9a\x82\x3b\x58\x02\x25\x78\x07\xbf\xc2\x52\x2c\xc1\x3b\x23\x6a\x46\x1c\x9c\xc8\x16\x6f\xdf\xad\xd9\x55\x5c\x57\x5c\xb0\x3b\x63\x17\xb9\xed\x7a\x72\xc7\x5d\x1a\xca\x21\x1c\xc2\xa1\xdc\x4d\x31\x1c\xcb\xb1\x1c\xbb\x68\x48\x70\xae\x3d\x94\x8d\xce\x8b\x49\xce\x8a\xc9\x8e\x2e\x8f\x6e\xc8\x22\x33\x0f\x1d\xd6\x1d\x66\xe0\x0e\x94\x40\x09\x7c\xc5\xf9\xbc\x90\x54\x28\x44\xf7\xbd\x60\xa7\x23\x8a\xc2\x91\x28\x19\x8a\xef\xe3\x5a\x3a\xd8\x1e\x59\x12\xc6\x1a\xf2\xf4\xda\x7c\xc6\x24\xba\x90\xf7\xd9\xd9\x9a\x53\xa4\xd5\x6c\x29\xb5\x31\x56\x7d\xe9\x47\xbf\xe1\xcc\x1b\xa9\x72\xb3\x9e\xd0\x1b\x79\xa3\x91\x35\xea\x72\x8c\x3a\x26\xc4\x10\x97\x12\x91\x4d\x06\x85\xa8\x52\x97\xd1\xd8\x07\x8e\xe9\xbe\x7e\x04\x83\x2b\xbe\xfc\x9c\xdd\xa5\x6f\xcb\xad\xcd\x22\xb7\x81\xf8\x8f\x70\xf0\x61\x7e\x86\x0f\x0a\x1f\x9d\xe7\xf2\x0b\x0d\x45\xd6\xc2\x94\x5f\x47\xe8\x96\x9e\xbd\xfa\x45\xeb\x37\xcd\xdf\x5b\x73\x7d\x4d\x26\xde\x68\xe2\xb6\x97\x1c\x1a\xb6\x9f\x39\x57\x09\x3e\xad\x30\x7a\x0a\xb0\x63\x41\xca\x19\xcd\xd9\xf9\xe6\xda\x8a\xfa\x7a\xfa\xcc\xf6\xcf\xa2\x0e\xb3\x46\xeb\x6a\x50\xad\x80\x05\xa8\xfa\x43\xbe\xe7\xc3\xa1\xd5\x63\x18\x24\xd0\x23\x25\xf0\x3d\x0e\x27\x4d\xc2\xfe\x98\x8e\x0b\xe9\xc4\x14\xf5\x0a\xd3\x76\x32\x25\x21\x79\x7d\x34\x9d\x6c\x4a\xb1\xa5\xb0\x3e\xd0\x94\x9f\xe0\xe8\x07\x87\xde\x3c\x82\x09\x77\x9d\x97\xa8\xe5\x21\x21\x01\xcb\x03\xda\xce\x9c\x3d\xdb\x76\xe6\x6c\x5b\x48\x00\xeb\x48\x75\xe5\x52\xc1\x21\x21\x01\x21\x21\x6d\x7b\xdb\xda\xda\xda\xce\xb6\x85\x84\xb0\xa8\x16\x72\xdd\xb2\xcb\x03\x96\xb7\x9d\x39\x7b\xa6\xed\xec\x99\x2e\xd9\x77\xdc\xb2\xc1\x21\xcb\xff\x93\x3d\xb3\xd7\x2d\x5b\x29\xf4\xa3\xe0\xc8\x42\xbc\x06\x91\x28\x30\xae\xfe\xf8\x2d\xd6\xe2\xef\xb8\x06\x3c\x71\x02\xcc\x45\x29\xf7\x11\x46\x41\x1e\x48\x89\xe4\x9f\x6e\x27\xff\xc4\xec\xac\x31\x99\x77\x72\x69\xc7\xb5\xa7\x4e\xd3\x70\x03\xea\xa0\x00\x7e\xab\xdd\x69\xd4\xef\x64\x85\x1f\x5c\x17\x28\x38\x84\x87\x40\x8d\xdf\xe2\xef\x58\x8b\x6a\x74\x9f\xd5\xa2\x1a\x7e\xbf\xdd\x51\x59\xd1\xc1\xc2\x1a\xf4\x0c\x80\xb9\x04\x0c\x04\x4f\xf0\x80\x01\x30\x9e\x76\x3f\x33\x2b\x44\xff\xe3\xa5\x10\xfd\xa0\x20\x5e\x52\x36\x4d\x46\x6e\x06\xa3\x56\xeb\xb3\x35\x9c\xc2\xa1\x7e\x1d\x90\xa0\x52\xc5\x99\x76\xc8\xcd\xb1\xa5\x09\x3b\x33\x05\x0e\xc7\xf9\x3a\xcf\x38\x47\x75\xbe\x78\x7d\x98\xc0\xbf\xc5\x31\xe5\x3b\xea\x32\x59\xbd\x2d\xdf\x68\x63\x2a\x2b\xf2\x4b\x8b\x38\xd0\xc1\x71\x61\x35\x2e\x84\xee\xca\xff\xcb\x74\x62\x49\x8c\x29\x21\xa3\xcb\xa8\x6f\x82\x2a\x23\xce\xbc\xe3\x5f\xa3\x11\xb8\xdc\xd7\xb5\x4a\xbc\xbd\x6c\x47\x9d\xa6\xcb\x56\x7e\xd7\x12\xc5\x22\x0e\x4e\xc1\x3d\xa1\x16\xc3\xa1\xbb\x12\x7f\x55\x38\x07\x50\x2e\x35\xac\x13\x62\x1d\xfb\x3a\x9f\x77\x4a\xf1\x07\x50\x2a\x88\x52\xc7\x75\xc2\x67\xbf\xd2\xed\xa3\x09\x1d\x60\x9f\x9f\xd8\x1b\x92\xba\xdc\x50\xe9\xfd\xcf\x94\xa0\x54\x92\xd2\xdf\x50\x09\x2c\x71\x5d\x02\xbf\x2b\xa5\xf7\xf1\x63\x18\x08\x11\x03\x21\x99\x81\xc5\x4a\xae\x53\x06\xed\x70\x55\x82\x2f\xe0\x9e\x52\xfa\xdb\x54\xa5\xf4\x3e\x04\x48\xba\x72\xbe\xc9\x0c\x4a\x90\x79\x39\xec\x70\x59\x09\xcb\x95\x9b\x24\x9c\xc3\xde\x29\xbb\xad\xe4\xc1\x28\x81\xb7\x95\xd5\x28\x83\xbe\xd8\x13\x7a\x62\x4f\x90\x0a\xf7\x60\x8c\x50\x0f\x3e\xbd\xa1\x00\x2c\x8e\x6a\x30\x4b\xd7\x2b\x44\x36\x94\x51\xad\xc5\xed\x8d\x8f\xd1\x63\xf3\xaa\x66\x2e\xbc\xca\xf0\xb8\x85\x96\x4e\x35\x3a\x3f\x22\xda\x4c\xff\xec\xa9\x61\x4f\xee\xfe\x67\xc3\x63\xba\x29\xfd\x40\x08\x3b\x76\x6c\xd6\xd8\x31\x63\x6c\x63\x98\x90\xf4\x2d\x91\xe3\xfe\x3c\x70\x32\x92\x6b\x4d\xe0\x07\x04\xd3\x46\xec\x20\xd4\xbc\xc6\xa8\x66\xf5\x19\x19\xbc\x8a\xe9\x5c\x24\x92\x56\x66\x64\xf0\x96\x0c\xce\x58\xc8\x17\x14\xd2\xd2\xf5\x46\xe8\x20\xda\xf8\x7f\x5a\xab\xd9\x13\xbb\xff\xd8\xf4\xe8\x8d\xc1\xf1\xe3\xb2\xc6\x8f\x18\x6e\x1b\xc1\x84\x66\x6c\x8e\x1a\xf5\xea\xf8\xc9\x08\xee\x48\x4c\x16\x0e\x5f\x43\x77\x9e\x11\x9b\x96\x12\xa1\xc6\xb1\xe1\xf1\x6c\xe0\xb6\x11\x6d\xfe\x74\x74\xe9\xd6\x16\xf6\xe1\x43\xdb\xc3\x9f\x7f\xc9\xfa\x85\x69\x2d\x39\xd0\xf4\x23\x4a\xd6\xaf\x6c\xe6\x82\x6b\xf8\xe7\xfb\x68\x93\x20\x26\x0a\xf9\x02\x53\x01\x6b\x2d\xab\x30\x96\x33\x8e\xf1\xa2\xb2\x0a\x93\xae\x8c\x33\x69\x78\x8d\x9a\x36\xb9\x18\x22\x94\x1f\x1f\x96\xc0\xae\xdc\x36\x68\xdf\x68\x3a\xaa\x2c\x78\x0f\xfb\xe4\x89\xed\xc9\x0f\x3f\x64\x3d\x61\xba\x40\x86\x54\x50\xe0\x29\xd4\x40\x0a\xf4\x87\x14\x2f\x85\xf7\x6b\x05\xf1\x11\xb5\x27\xa6\x7e\x1b\xeb\xda\x21\xc2\x05\x38\x5a\x15\x3b\x9d\x9b\x14\x33\x6b\xc5\xe2\xc9\xe4\x92\xc9\x91\x43\xd1\x8b\x1e\x56\xe3\x7f\x70\x2a\x7b\x78\xd2\x95\x45\x0f\x82\xae\x46\x7c\x9f\xf8\x9b\x96\x74\x65\xc1\x09\x89\xc2\xfb\x2c\xf4\x57\xe0\x54\x38\x21\x81\x63\xca\x6a\x43\xad\xb5\x92\xcd\x2d\x2b\x2a\x2c\xcb\x25\x73\xcb\xab\xf4\xe5\xcc\x9e\xfa\x8b\x7b\x38\x1f\x7e\xaf\xc4\x93\x87\x38\x67\x07\xc4\xc9\x1e\xc2\x0b\x90\x51\xf8\x02\x65\xf0\x42\x04\x2f\xc0\x7e\x50\x09\xfe\x82\x8c\xea\x7c\x81\x32\xc7\x0b\x51\xa7\xcc\x21\xa3\x30\xae\xeb\x63\x8e\x82\xf0\x7b\x2d\xa3\x3a\xe3\x50\xe6\x88\x13\xbd\x0e\x50\x10\x1e\x07\x95\x0e\x99\xcb\xad\xd1\x81\xff\x4b\xca\x21\xf3\xfe\x57\xd7\x67\xab\x44\xe1\x7d\x5a\xb0\x53\xe3\xa7\x86\xad\x58\xca\xa1\x0b\xe6\x10\xa6\x42\x53\x11\x5f\xc8\x17\x1a\x8b\x0a\x7b\x0c\x00\x37\x67\xc5\xf9\xbb\x61\x0f\x18\x98\x05\xfd\xa1\x3f\xcc\xfa\x3f\xd7\xcd\xaa\x4d\x2a\x93\x9a\x43\x17\xce\x21\x4e\x2f\x9d\xda\x32\x9e\xf9\x97\x8f\xb3\xa0\x3f\xf6\x87\x59\x0f\xee\xb6\x9c\x3e\xcf\x81\xbb\xde\xa8\x36\xaa\xd4\xf4\x7f\x15\xff\x97\x39\xd6\x67\xbf\x52\x98\x06\x53\x85\x69\xfb\x24\x4e\x3b\xd8\x65\x0f\x0d\x4a\x78\x4a\x61\xf7\xa1\x43\xb1\x3b\x4a\x86\x3e\x83\xee\xf9\x26\x9b\x29\x9f\xc5\x6c\xe8\x41\x84\x6e\x5d\x15\xbf\x8c\xc1\xee\x43\x7f\x05\x09\x48\x9e\xfd\x0a\xdd\xcf\x9d\x8a\x0f\xdd\xc7\x81\xbb\xd2\x98\x6f\xb4\xe5\xd3\xd0\xfd\xd9\x33\x90\x40\xf7\x67\x6f\xf4\x87\x62\xf7\x65\xab\x6a\xda\xb6\xb2\x98\x8d\x3d\x08\x93\xd6\x94\xc5\x6b\x79\xad\x31\x4b\xdb\x63\x00\xb8\x39\x6d\xfb\x4e\xd5\x9c\x63\xba\xc4\x25\x1c\xd8\x1d\x55\x7e\xca\x6a\x67\x34\x7c\x08\xb2\x2b\xcd\xe0\xdf\x9b\x87\x0f\x15\xde\xc7\x61\x84\xf5\x8a\x15\x46\xa0\x0c\xfc\xa5\x1d\xc2\x75\xe7\x6c\xaa\x24\x2c\x35\x38\x2c\x1d\xbd\xd7\x8f\x1a\xb5\x1e\xbd\xc9\x58\x75\x5c\xda\x76\x46\xab\x35\x5b\xb4\x5c\x58\x71\xda\xde\xe2\x96\x0b\xf0\x1e\x90\x40\xc2\x7b\x17\x48\xe9\xbc\x96\xe2\xbd\x69\xc5\x61\xa4\x73\x26\x08\x14\xe6\xa0\x7e\xf6\xf5\xd8\xba\xcd\x7c\x6c\xac\x7c\xfe\x7c\xe2\xdc\x40\xec\xde\x82\xbd\x18\x97\x1c\xaf\xe3\x75\x97\xfc\xbf\xfc\x0a\x82\x1c\xae\xc3\x75\x41\x0e\xbd\xc2\xa0\xfb\xb2\xbf\xb8\x2b\x57\xea\xea\xf8\xf6\xd8\x3a\xb9\x74\xeb\xec\xeb\xa0\x87\x1c\x62\xeb\xdf\x54\x71\x11\x5f\x9d\x51\x34\xea\x27\xdf\x37\xb8\x82\xaa\x0c\x3e\xb1\x28\xe3\xa7\x51\xbe\xd9\x79\xf9\x39\x76\x26\x3f\x1f\x66\x4b\x20\x05\x53\xa8\x37\xe8\x83\x23\x7f\xf4\x55\x15\x27\xf0\xaa\x0c\xf8\x45\xf9\xe3\x48\x5f\xe9\x4c\x10\x29\xf3\xf3\x2d\x79\x36\xae\x1d\xe6\x2f\x55\x0e\x15\x0d\x50\x0e\x95\x70\xcf\x20\x43\x02\x01\x5d\xb8\x76\x43\xc5\xf1\x4a\x18\xda\xfe\xaf\xfa\x9b\x36\x46\x8d\xf4\x85\x5f\x94\xe4\xff\x5f\x0b\x3f\xfd\x48\xf8\x80\xbf\x04\xa8\x84\xae\xf5\xec\xa3\x25\xc2\x4b\x47\x10\x05\xdd\xf0\x07\x02\x40\x04\x9e\xf0\x03\x1e\x80\x20\x42\x78\xe1\xdd\xe5\x32\x0b\xff\xa3\x70\x1e\xa3\x22\xc1\x17\xbf\xdd\x82\x1c\x9e\x02\xf2\x13\x22\x76\xfa\xc4\xf4\xf1\xcc\xf8\x89\x25\x75\xd3\x39\x20\x6f\x20\x07\xa7\xfe\x7f\x8c\xbd\x07\x78\x14\x55\xf7\x30\x3e\x21\x99\xe2\x08\x79\x21\xb3\x13\x93\x9d\x9d\x99\xd0\xa4\x89\x08\x46\x9a\x20\x01\xe9\xbd\xac\x48\x0f\x2d\xd4\x24\x84\xf4\x9e\x25\x7d\x4b\xfa\xa6\x12\xd2\x13\x48\x20\x24\x40\x68\xa1\x4a\x11\x31\xe8\xab\x10\x41\x50\x10\xec\x8a\x80\xaf\xa2\x67\x76\xcf\x24\xef\xff\xd9\x8d\xbe\xbf\xf2\x7d\xdf\xf3\xfc\x9f\xdd\x9d\x7b\xee\xb9\xa7\xdd\x76\xee\xdd\x3b\x33\xf7\xe2\xbd\x63\x41\xe8\x45\x8e\x04\x8d\x1e\x5e\x83\xb7\x2c\x66\x8b\x45\xfb\xaf\x31\x90\x0a\xe1\x0b\xe0\x0e\x0a\x49\x3f\xc3\x4b\xa0\xfb\x15\xc6\x9c\xf3\x5e\x8e\x7d\xe1\x18\xbe\x0e\xc7\xe0\xf5\xe5\xd0\x17\xc6\xac\x04\xdd\xcb\x3f\xe3\x4b\xde\xa8\x2d\x9e\x8f\x77\x20\x15\xc3\xff\xf5\x2d\xe9\x18\xc1\xb5\xf8\x96\x1e\x5f\x1b\x89\x1a\xc9\xbd\xca\xfc\xf7\xa1\xfa\xb0\x1c\x46\xc2\x69\xa5\x2f\xeb\x3c\xa5\xe8\xff\xf2\xe5\xec\x07\x14\x3d\x84\xaf\x64\x51\xaf\x74\xae\x64\x95\x4e\xd4\xaf\x64\x61\x80\xc8\xa5\x12\x63\x59\xf5\x26\x3c\xe7\x15\x8e\x6a\x39\x70\xa0\x45\x06\x5e\x2d\x42\x9e\xde\x7a\x20\xb8\x55\xd2\xb9\x25\xaa\x6d\x2b\x59\xee\x3a\xf1\xbf\xd9\xbe\xf6\x1b\xcb\x2a\x1a\xe5\x17\xfe\x63\xec\x03\x77\xbb\xf6\x76\x95\x63\x6f\xbc\x3b\x5b\x4a\x54\x8a\x0a\xe9\xd6\x83\x1d\xf0\x9b\x45\x82\xdf\xb2\x0e\xce\xde\xa2\xdd\xa3\x14\xd1\xaa\xec\xa6\x67\x51\x4f\x73\x17\x73\x1b\x45\xe5\x84\x9b\x43\x05\xb5\xf5\x40\x70\x8b\xa4\x68\x28\x2e\x64\xa8\x53\xb3\x7b\x95\x51\x04\xab\x8b\xa2\x81\xce\x0e\xb0\x76\x40\xa7\x26\xc4\xa6\xd7\xb9\x5d\xe4\xd5\x49\x54\x42\x62\x72\x42\x86\x8c\x59\x5d\x5d\xa4\x6a\x85\x49\xa2\xd2\x49\x9b\x69\x5f\x11\x3a\x6d\x56\x1e\xad\x5d\x7a\xb0\x52\x36\x2b\xea\x79\xcc\xb2\x75\x91\xa5\x19\x89\xd6\x04\x41\x9d\xd4\x65\xa5\xc6\xb0\x66\x5a\xed\x84\x49\x62\x77\x9b\x8e\xaa\x82\x10\xd1\xe6\x0b\xe1\x10\x22\xba\x9f\x60\x75\xd4\x17\xf6\x7f\xf2\x2b\xcf\x4d\x34\xaf\x5c\xa9\x0e\x56\x07\x79\x61\x22\x24\x2a\x83\x94\xc1\xe7\xce\x9a\xef\xaf\x3c\xe7\xbd\xf2\xec\x44\xf3\xca\x55\xea\x20\x75\xb0\x17\x0e\x87\xe1\xe8\x8b\xbe\xb8\x0b\x77\x05\xe2\xd7\x30\x1e\x2d\xde\xd8\x8d\xdd\x24\xce\x81\x39\x34\x74\x43\x37\x58\x70\x3c\x7c\xdd\x04\xbb\x60\x97\x37\xf8\x82\xaf\x83\x43\x19\xac\x0c\x3a\x7b\xce\xfc\xe5\xaa\x73\xde\xee\x55\x3a\xb2\xf6\x47\x97\x3f\x1f\xeb\xc8\x88\x47\xae\xb6\x2e\x5b\x2b\x0f\x6e\xc3\xbf\xc3\x17\xe1\x6b\x16\x5e\xfc\xe5\x7b\x70\x95\x14\x93\x27\xb8\x8d\xf8\x0e\x7b\x3b\x50\xbd\x1f\x3b\x50\x10\x81\xb3\x79\x4c\xc3\x97\x70\x73\x35\x92\xb9\xe3\xb3\x03\xb7\x65\xe8\xa3\xca\xa2\xf6\x46\x56\x66\x64\x67\x66\x67\x66\xc7\x54\x04\x59\xd7\x98\xd0\x35\x03\xfd\x23\x70\x0f\xf4\x65\x6c\x6f\xd0\xe0\xde\x74\x04\x5c\x25\xfb\x2f\xd4\x1f\xad\xeb\x90\x96\xbb\x46\xd1\x30\x2e\x97\x3f\x78\x66\xdb\xf9\xe5\x5b\x52\xd3\x1d\x1f\xc6\x36\x97\x7e\xfc\xf6\xdd\x31\x92\x0e\x5f\xa2\xc6\xbc\x3d\x79\x84\xdc\x35\x97\x4e\xcd\x4d\xc9\x4d\xcd\x5d\xde\xba\x6d\xc5\xc1\xd5\x1d\x93\xc0\x7d\x38\x2c\x9c\x82\x2b\xbb\x5e\xb7\x4d\xf4\x31\xc0\x2f\x4c\x9a\x05\xd6\xc2\x40\xed\xbe\x8c\xb2\x8c\xb2\x4c\x06\x07\x58\x70\x59\x9e\xd6\x80\xbf\xd8\x26\xfe\x89\x2b\x6d\xaf\xc3\xc2\x3b\xe0\xfe\x4b\xc7\x3d\xc6\xbd\xea\x5b\xc8\xb3\x37\xc3\x60\x97\x67\x90\x07\x83\x61\xce\x2d\x18\xec\x04\xf2\x60\xb0\xab\x5d\x63\xff\x9a\xc7\xc1\xea\x4c\x18\x4c\x29\x03\x94\x99\x7f\xc3\x78\xcf\x4d\x1d\x40\x61\x10\x06\x91\x10\x84\xf7\xec\xcd\x3a\xb7\xa6\xae\x16\x1a\x06\xdb\xfd\x78\x9d\xfd\x0d\x0a\x5d\xf0\x38\xa9\xc3\x58\x65\x00\x06\x41\x10\x0d\x41\x10\x44\xc2\x3d\x4a\x99\xa9\xcc\x24\xdd\x41\x66\x1f\xea\xc8\xe5\xae\xb6\x52\x08\xe2\x2d\x8d\x31\xfb\x77\x94\xec\x28\xde\x9a\x12\x15\xca\x2c\x9e\x61\x32\x9b\xb5\xb8\x16\x93\x93\x0d\xe9\x09\x99\x29\xc6\x64\x4b\x72\x56\x52\x6e\x62\xa1\xa1\x7d\x19\x44\x8c\xbf\x55\x5c\x97\xbb\xaf\xb4\xa0\x2a\xb7\xc4\x5c\x68\x81\xc3\x0c\xf4\x33\x67\x99\x25\x1c\x06\x39\x7c\x56\x4b\x74\x53\x50\x31\x33\xf6\x90\xc5\x62\xd6\x02\x8b\x27\x92\xf2\xe2\x85\x08\x4b\x94\x21\x21\x22\x78\x6d\x22\x0e\x29\x1a\x96\xbd\x33\x2f\xa4\x20\xae\x38\xa2\x32\xb1\xda\xc4\x94\x5a\xb3\x1e\x41\xb5\x0c\xbd\x8f\x9a\xcd\x66\x6d\xa3\xb5\xb2\x3e\xeb\x30\x63\xfb\x18\xcf\xf1\x39\xf5\x29\x55\x31\xa5\x06\x6b\x72\x36\x56\x7f\xc3\x20\x7b\xd4\x64\x31\x6b\x83\x0b\x77\x26\x47\x84\x84\xef\xca\xdc\xba\x6f\x57\xfb\x5b\x5e\xe0\x8b\x25\xc5\x31\xc5\xc9\xe5\x09\x35\xc6\x1a\xeb\x3f\x1b\x60\x18\x2c\x29\xbc\xc5\x74\xf9\xda\x7a\xf3\x69\xd0\x67\xab\xd2\x92\x51\x97\x56\x13\xb3\x37\x34\x6f\x72\x25\x5e\x18\xa7\x5f\x1a\x13\x93\x16\x9e\x1b\xc9\x98\x0b\x63\x15\x37\xf5\xae\x74\xf9\xf5\x93\x25\xa5\x39\x65\xb9\x27\x4b\xd2\x7f\x67\x6c\xc3\x91\xe0\x9d\x7e\x26\xe5\x36\xbe\x04\xef\xce\x6d\x0a\x2f\x0a\x37\x47\x27\x26\xa5\xa4\x18\x70\x3c\x86\x33\x53\x5f\x36\x99\xcc\xda\x98\x30\xd3\x8e\x8a\xa0\x8a\xa0\xe6\x84\xc6\x02\xc6\x64\x74\x98\x5d\x96\xdb\x90\x7f\xb6\x08\xae\x7e\x56\x9c\x53\x5c\x50\x51\x62\xad\x32\xd6\x31\xee\xd0\xe8\x3c\xb4\x1a\x8c\xac\x19\x26\xb2\xcb\x45\x88\x66\x39\xfc\xd5\x79\xd4\x80\xaa\x51\x35\xf0\x01\x4b\x83\xa6\x4b\xc3\x77\x69\x50\x63\xd3\x50\x76\x8d\x9b\xb9\x4b\xe3\x18\xd4\x69\xe7\x79\xae\xaa\x15\x35\x8a\x95\x52\x34\x6e\xff\x2f\x88\xe2\x48\x83\x62\xa5\x74\x76\xa2\xab\x93\x87\xcd\xa2\x5d\x0f\x1a\x9a\xc3\x5f\xbb\xf5\xf4\x31\xd1\x73\x24\x2b\x39\xea\x3f\xbf\x32\xa7\xba\x5a\x6b\xef\x5c\xcc\x76\x77\xd2\xa0\x71\xf8\x04\x9d\x8d\xa0\xb8\xb4\x5c\xd4\xa0\x95\xe6\xa2\xd7\x77\x77\xc2\x29\x51\x82\x2a\x11\xba\x59\x77\x68\x54\x34\x50\x20\xba\x1c\xd7\xd1\x87\x34\x0f\xed\xd6\x12\xbe\x1e\x7c\xc0\xa7\xe1\x2c\x6a\x1a\x02\x02\x50\x13\xb2\x2a\x04\x7c\xd0\xa7\x5e\x86\x1a\xa8\xe5\x6b\x61\x30\x0c\xaa\xb5\x42\x17\xfb\x87\x0f\x4e\x7b\x1f\x87\x0a\x38\x14\xa7\x2d\xee\xef\x03\x8f\xc4\x5a\xa9\xec\xcf\x67\x30\x14\x86\x80\xcb\x90\x52\x01\xea\xa1\x8e\xaf\x81\x41\x30\xa8\xb6\x00\xba\x58\x98\x85\xb3\xb0\xe6\x29\xe6\x08\x98\x83\x35\x43\x71\x16\xce\x92\xd3\xd2\x32\x52\x52\xb4\x61\x30\x08\x07\xd5\x48\x45\x10\x0b\xdb\xe0\x92\x00\x81\x20\x4f\x41\x0d\x4c\x90\x33\xf2\xac\x19\x05\x02\xd4\x42\x2d\x5f\xf3\x1f\xb5\x90\x83\x79\xaa\x0b\xc8\xf8\xa7\x80\x7f\xaa\x2e\x28\x63\x0e\xe6\xc1\x23\xb1\xa6\xa0\x20\x27\x37\x4f\x02\x7f\x88\x83\x2c\x20\xe1\x86\x00\x37\x20\x0b\x49\xf4\x87\x38\x39\x3d\xaf\x20\xa3\x40\x70\x87\x1c\x76\xb9\xe8\x62\x86\x78\xd6\x55\xd1\x78\x42\x10\x3b\x98\x55\x48\x71\x96\x68\xb3\xaa\x9a\x59\xa2\x13\xfc\xdf\x71\x9b\xb5\xcb\xca\xcf\x58\xb2\x64\x86\x64\xa6\x67\x2c\xb9\xfa\xa9\xac\x68\x68\xe8\x16\xcd\xf4\xa7\x57\x97\xcc\x90\x55\x0d\xad\x6a\x6c\xd6\x59\xa2\xc3\x0d\xf3\x8e\xf2\x47\xe2\x3b\x16\xac\xd0\xc6\x1a\xc5\x32\x16\xad\x34\x76\xba\x0d\x66\x41\x63\xd3\x7c\x27\xea\xec\x86\x5f\x59\x9d\x9d\xe8\xb9\x0f\x13\x2e\xde\x16\x4b\x44\x9d\xfd\x37\x28\xf5\xb0\xea\xc8\xa7\xc8\x02\xcb\x55\xe9\xc8\x67\x76\x77\x3e\xe9\xa3\xc0\x4b\xfa\xb6\xd4\xdc\xcc\x2c\x63\x52\xca\xba\x24\xff\x78\xff\x1d\x23\x57\x8d\x9b\x36\x6b\xe2\x94\x61\xfe\x48\x84\x4d\x8c\x19\x9f\xf1\xb6\x85\xb1\xac\xd8\x64\xda\x24\x84\xc5\x25\x86\x65\xca\x31\xe8\x16\x83\xae\xce\xab\x5b\xac\xf3\xca\xec\xca\xd8\x17\xbe\x5f\x80\x1c\xaa\x79\x7f\x5d\x73\xbe\x9c\x55\x76\x09\x9e\xe6\x54\x90\xcd\x79\xfb\xeb\x9a\x85\x93\x14\x34\xc3\x2e\xa0\xe0\xc1\x0d\xb9\xf4\x76\xf6\x27\x89\xd7\x18\x33\x8d\x7e\x70\x98\x87\x57\x26\x83\x1b\x0e\xb8\x24\xd5\xcf\x1e\x5a\xb1\x5e\x50\x7f\xa6\x36\x6f\x0f\x0e\x48\x93\x31\x5e\x67\x9f\x4a\x06\x67\x54\xef\x6e\x14\xe0\x0c\x55\x90\x9d\x9d\x6f\x91\xf7\x3e\xbb\x04\x7f\x96\xde\x61\x3a\x8a\xdb\x0e\xde\x10\xae\x5d\x33\x59\xae\xc9\x8f\x2c\x0f\x8b\xbf\x3c\x00\xaf\x5c\x7e\x02\xc4\x05\x18\xc1\x70\x8b\x1b\xee\x54\xdc\xbd\xaf\x75\x7f\xce\xb6\x38\xfe\x90\x2b\x0b\x6c\xcf\x79\xf5\x05\x6a\x77\x5c\x50\xe4\x5e\x19\x26\x63\x10\xb0\x98\xff\x05\x36\x31\xca\x52\x6a\x2e\x1c\x44\x77\xb0\xe2\xdb\x90\xc2\xec\x4d\x8a\x2a\x8c\x12\x94\xcb\x68\xe3\xc7\xc1\x26\x74\x83\x40\xec\x0f\x51\x99\x38\x2a\x1e\x87\xed\xc6\xc1\xc0\xe2\x92\x87\xb8\xe2\x22\x06\x9c\x03\xee\x38\xbc\x74\x08\x04\xe6\xa9\x6d\x25\xaf\xce\xa2\xa0\x41\x9d\x0e\x26\x35\xfb\x90\xda\xc4\x28\xef\x52\xab\x95\xb3\x18\xaa\xe4\xe2\x05\xe5\x35\xc6\x36\x47\xed\xe4\xa1\x7d\x33\x1c\x9d\x02\x35\x52\x43\xea\xee\x8a\x5d\x02\x22\x15\x19\x1f\x15\x99\x2b\x5f\xc4\x85\x2d\xb8\xa2\x1c\xd7\xc1\x3b\xf8\x04\xdc\x55\xb7\x93\x2a\xc5\x7c\x08\xe9\x47\xe0\x14\x34\x69\x9d\x2f\xc0\x02\xaf\xa3\xff\x0d\x1a\x57\x1d\x7d\x52\x39\xc1\x9b\x53\x0f\x06\xc2\x48\x29\xe9\x52\x4a\x58\x7c\x80\xc5\xe2\xfd\x2e\x0e\x48\xd8\x62\xd6\x1e\xba\x67\xae\x17\x74\xf6\x35\x37\xf8\x59\xb0\x04\x47\x3c\xc3\xf9\xed\x59\x25\x5e\x50\x45\xb5\x34\x25\x6e\x2c\x90\xaf\xe2\x19\x12\x66\xc1\xbf\x78\x98\x4e\x61\x69\x17\x4f\xe2\xdb\x14\x0a\x4a\xfe\xe3\xcd\x0f\xdf\x38\xfc\xaa\x77\xf9\x18\x18\xab\xcc\x25\x41\xee\xf2\xe4\x7f\xb7\x79\x92\x30\x91\x1a\xd8\xe5\x49\xe2\x44\xca\x66\xb5\x51\x7c\x38\xca\xf1\x05\x41\xa5\x9b\x8a\xde\x31\x79\xcf\x0d\xda\x15\x12\x74\x38\xf2\x6a\xb0\xfc\xf3\xda\x53\xfa\x69\x5a\x23\x7a\x23\xe9\x8b\xd3\x2c\x8c\xdf\xf4\xbd\xfb\x36\xcb\x35\x30\xa8\xda\x40\x86\x5e\x6c\x49\xf9\x58\x68\xbf\x50\x71\x62\x7f\x64\xd5\xdc\x26\x79\x7e\xd3\xf8\xf3\x96\x1f\x18\xe8\x67\x01\xfa\x6b\x18\x2f\x74\x5c\x48\x48\x3c\x24\x2b\x93\xf7\xf2\xa0\x75\x28\x7a\x95\x8a\xff\x2c\xbd\xda\xac\x0d\xc3\xc9\xe6\x68\xc1\x9c\x1a\xbb\x6b\x92\x84\xd3\x28\x30\x29\x0f\xc9\xe3\xe5\x8d\xc5\xc7\x04\xd0\x50\x50\x06\x9d\x9b\x59\xa5\x11\x35\x20\x64\x94\x96\x1c\x0a\x7c\x30\xfe\x51\xe0\xc1\x06\x78\x01\xd6\x14\xda\xce\x38\xef\x1c\xdf\x07\xfa\xc3\x03\x1f\x36\xd6\x37\x7e\xb9\xbf\xf9\xfb\xa3\xd1\x35\xd1\xed\x8d\xb7\x9a\x3e\x6d\x6c\x6c\xbc\x61\x3c\xfa\xc9\x81\xa6\x2f\xf7\x1f\x3d\x70\xa3\xf1\x8b\x03\x27\x13\x8b\xb2\xcb\x2a\xe1\x3e\x97\xfa\x78\xc4\x3b\xf6\xdf\x75\x6e\x07\x79\xac\xc0\x60\xa3\x3a\x0a\xaa\x30\x98\xd1\x8f\x1f\x16\x34\x44\xe0\x7a\xbd\x47\x10\xd8\x8c\xd1\x10\x0d\xcd\x70\x08\x9c\xa1\xec\x64\x79\xf6\x24\x48\xff\x40\x3e\x14\xc6\x43\x11\xfa\x5b\x54\x09\x8b\x71\x1d\x16\xc3\x3a\x8b\x22\x41\x11\xf8\x33\x87\x6a\xf9\x4b\x0f\x9e\x34\x3e\x13\xa0\x19\xa2\x31\x1a\x0f\xc9\x5c\x32\xd3\x23\x0c\xa3\xb1\x79\xe8\xd0\xc6\x4b\xe3\x25\xa8\x86\xa0\x0c\xe5\x35\xdc\x07\xc1\x8c\x2d\xa6\x6b\x0b\x1f\x9b\x59\x9e\x4a\x73\xbd\xdc\x08\x22\xbb\x3c\x93\xae\x8e\xe5\xcb\xe8\xf4\x44\x32\x83\x4a\x2b\x21\xe3\x33\x2b\x73\xe9\xbc\xc4\xbc\x12\x32\x37\x8a\x4a\x52\xe7\xf3\xce\x67\x3a\x4c\x66\xb3\x49\xc8\xcc\xcc\xa6\x9c\x1b\xc8\x39\x2e\xda\x64\xb7\x8c\x5c\xd2\x94\x9e\x59\x92\x47\x71\xc9\xbd\xfc\x88\x2c\x8b\xc9\x22\x58\x4c\xe6\xbf\x3e\xa6\xde\x83\x4d\x66\x93\x51\xc8\x49\x27\xb9\x01\xbd\x0c\x84\x0e\xff\xf1\x4f\x3e\xac\x2c\xba\x5e\xe2\xdc\x08\x3f\xa2\x76\xef\xbe\xba\xda\xb8\x8a\x30\xd9\xc9\xbb\x3b\x3e\x3a\x4c\xe6\xfa\x12\x7e\x84\x12\x74\x92\xe7\x3c\x88\x2a\x22\x2a\x29\x31\x3a\x53\xe6\xdc\x08\x1f\xe2\x53\xaa\x2a\x33\xb1\x28\x5a\xe0\xfa\x12\x3e\x04\x28\xfe\x0e\x31\x75\x75\x3d\x02\x42\x43\xe3\xa3\xc3\x24\x27\x2b\xd4\x79\x86\xed\x8d\xae\x93\x9c\x12\x6b\xcb\xf7\xd5\xd5\xc6\x3a\xe4\xfb\x10\x43\x89\xd0\xb8\x68\x27\xd4\x97\x80\x31\x6f\xf3\x59\x8e\x41\x51\xce\xb2\x58\x2c\x16\xd9\xe2\x80\x2d\x8c\x39\xcb\x01\x98\xb3\x4c\x16\x4b\xef\xc1\xa6\x2c\xb3\xc5\xe4\xf8\x98\x8d\x16\xc6\x19\x98\x4c\x66\x63\xef\x41\x26\x93\x23\x5f\x8c\xc9\x64\x32\x19\xb5\x0e\xd8\x6c\x74\xe4\xd4\xd8\x7b\xb0\x93\x5a\x32\x59\x1c\x45\x60\x72\x88\x17\x74\xf6\x0b\x39\xfc\x6d\xba\x66\x4f\x49\x94\xc4\x19\x08\x1f\x22\x3a\x21\x29\x4c\xf6\x0b\xee\x41\x45\x25\x26\x85\x49\x7e\x41\x20\xd0\x4e\xf3\x1a\xe3\xa8\xb2\xa2\xd2\xdc\x52\xa1\xaa\x2c\x39\xde\x2a\x57\x14\xef\xcb\x2d\x17\x0e\x99\xaa\x22\x77\x6a\x39\x03\xe1\x46\x8c\xa5\x41\xe7\x59\x4e\x27\xee\x49\x48\x8d\x16\x02\x82\x1b\xdb\x64\xce\x40\x30\x44\xdb\x81\xc6\x23\x15\xa5\x29\x49\x85\xd2\x5e\x9a\x73\x23\xdc\x88\x03\xb3\x29\x27\xfd\x2c\x1a\x86\xb5\xf1\xbb\xc3\x63\x36\x47\x44\xe5\x15\xc5\x49\x25\x35\x64\x6a\x61\x59\x6a\xa5\xc0\x25\x13\x24\x51\x59\x94\x57\x94\x9f\x9a\x13\x9b\x2d\x73\x0c\xe1\x42\x24\x66\x91\x81\x39\x71\x25\xd5\x0e\x55\x24\xd1\x50\x5d\xde\x5c\x5d\x91\x9e\x5c\x2a\x25\x85\x91\xb9\xc9\x71\x79\x31\x42\x5c\x72\x5a\x72\x72\x61\x66\x89\x51\x76\xb2\x97\x1a\xc9\x03\x19\xfb\x92\xc2\xb4\xe0\xb9\x9d\xe7\x92\x0d\xae\x7b\xd2\x92\xe3\x33\x92\x84\x6d\x49\x15\x4d\xf2\x07\xbb\x1a\xf6\xb7\x35\x6e\x3c\x13\xb2\x7a\x21\xcd\x25\x13\x84\x5f\x62\x4e\x72\x99\xe4\x80\x7c\x0a\xac\x59\xb9\x56\xb9\x20\x94\x74\xe2\x1f\x81\x17\x7f\xa4\x3e\x78\x83\x9c\x61\xce\xc8\xd0\xbe\x4c\x85\xe5\x96\x27\x57\x08\x5c\x2f\x82\xf0\x29\x29\xcb\xb3\x16\xc9\xa5\x11\x64\x42\x5c\x74\x7a\x94\xe0\x64\xde\x14\xbc\xff\x84\xec\x48\xed\x7b\x7c\xff\x81\xa3\x12\xbc\xee\xe9\x40\x33\x79\x05\xa6\xcc\x7c\x39\x79\x17\xc9\x19\x08\xa2\x57\x76\x5a\x9a\x25\x4d\x88\x4a\x4e\x8c\x90\xa7\x04\x81\xd0\x48\x3b\xb0\x4c\x9c\x33\xe8\x55\x9c\x5f\x54\x50\x2e\x34\x4e\xe7\xdb\xf6\x37\x9e\x94\x38\x3f\x97\x5e\xbd\x2a\x4b\xd3\x0d\xa5\x72\x42\x18\x59\x60\x30\xe4\x24\x0a\x9c\xc1\x8d\x20\xc2\x62\x63\x77\xef\x2e\x8f\xad\x95\x4b\x4c\x45\xb9\x45\x05\x0c\xc7\xb8\x11\x44\x69\x18\xe9\x4c\x4c\x4a\x48\xc8\x88\x12\xb8\x54\xa2\xaf\xc1\x7f\x57\x63\x9b\x0c\xc6\x59\x3c\xc7\x10\x84\xa1\x9c\x4e\x4c\x76\xd6\x4d\x50\x63\x5b\x5b\x63\x4f\xad\x58\xe5\xbd\x4e\xcd\x86\xc6\xd9\xd4\x2c\xda\xc9\xf4\x1b\xc8\xbc\x03\xd5\x37\xcf\x6a\xca\xcc\x73\xd8\xdd\x63\x72\xf4\x9e\xc4\x08\x47\x65\x10\x7d\xa7\x04\x83\x70\xa0\xc7\xe2\xbe\x3d\x16\x83\x0f\xca\x7c\x8f\xfc\x28\x61\x4b\x8f\xfc\xd6\x4a\xa7\xfc\x9b\x34\x67\xe8\x4b\x10\x07\xd0\x9d\x9a\x45\x9f\xad\xe4\xb3\xb2\x4c\x59\x82\xf3\x31\x2e\x13\xc3\x19\x86\x12\x8c\xc5\x64\x31\x5a\x4c\x8c\xc5\x68\x36\x3a\x9b\xaa\xd1\xd1\x54\x4d\x26\xa3\xc9\xc4\x70\x2e\x04\xe1\xe6\x04\x4d\x8c\xd1\x64\x34\x3b\x7f\xbd\x07\x19\x9d\x0d\xdf\x99\xda\xcb\x68\x31\x65\x59\x9c\xc7\x83\x39\x7a\x86\x39\x2b\xab\xf7\x60\x8b\x25\x2b\xcb\x22\x39\x79\x2d\xce\xc7\xbc\x98\xac\x2c\x8b\x45\x00\x55\xe7\xf6\x5d\x8f\xbf\xec\x50\xbe\xf9\xe8\x3c\xc4\x62\xc4\x77\xa3\x21\xfc\xe5\x5f\xa6\x7e\xe6\x61\xfe\xe3\x06\x0c\xf8\xb8\xf1\xc6\x71\xd8\x5e\x05\x85\x15\xb6\x97\x0f\xc0\xfc\x13\x37\xac\xc9\x0f\x60\x44\x07\xf7\xd9\xbf\xfd\xe0\x23\x9b\x99\xe7\x98\x8b\xc4\xc1\xc4\xa6\xf0\x4a\xa9\x32\x72\x77\xfe\x06\x21\x16\x43\xca\xa9\xe3\x0d\x05\xfb\x2a\x65\x07\x4d\x4d\x55\x49\xd3\x41\xad\x8e\xfa\xf5\x06\xcf\x31\xae\xc4\xc1\x88\xf2\x8d\x52\xd4\xcb\x15\xd4\xf1\xea\x7d\xcd\x32\xe7\x36\xde\x4f\x67\x5b\x36\x97\x5f\x15\xb1\x26\x60\xa7\xc4\xf9\x78\x11\x21\x3b\xb7\x18\x56\x0a\x8e\x84\x57\xe0\xd1\xcf\xd4\x1f\x9d\x33\x87\xc9\x8d\x38\x91\x87\x47\x37\xf0\x11\x0d\x05\xbf\xf2\x73\xd7\xac\x9b\xb5\x6a\x6b\xe5\xc9\x20\xe9\xf8\x31\x92\xf3\xa0\x88\xe0\xb2\xba\xf8\x26\x81\x73\x23\x0c\x07\xaa\x2a\x1b\x4a\xd3\x8a\x13\x0b\xe4\xd4\xdc\xc4\xdc\x50\x2b\xb3\xb0\x3a\xb2\xf6\xb4\xf6\xbd\x53\x6d\xef\xb7\x34\x27\x85\xee\x97\xb6\xfb\x93\x1c\x43\x18\x2a\x62\xe3\x0a\xa2\x84\x5d\x51\x71\x91\x31\x45\x7b\x8e\x26\xc8\x9f\x85\x54\x87\x2d\xd7\x42\xd3\x68\x3e\x21\x38\x2c\x7d\x97\x30\xf4\xad\x3b\x4f\x7e\xb9\xf7\xf9\x93\xfd\xb5\x69\x09\xfb\xe5\xb7\xe8\x86\x90\xf0\xa2\x40\x61\xe1\xea\x15\xf3\x66\x9f\x5e\xfd\xd1\x81\x9a\xa2\xfa\x7a\xf9\x2d\x5a\xe7\xf6\x89\xfa\xab\x73\x76\x65\xfb\x8a\xb2\x0f\x80\x29\xca\x35\xe8\x04\xdf\x67\x8c\x5a\x4b\x77\xfd\x60\x33\xf2\x43\x26\x4e\x1c\xe2\xf0\x99\x86\x21\x13\xbf\x7c\xf6\xec\x4b\xc7\x6f\xe2\x10\x19\x5e\xc1\xa9\xfc\x36\x0a\x07\xc0\xcf\x24\xe7\xc6\x10\x37\xa9\x6f\x31\xfc\x3b\x08\x27\x6f\x52\x07\xf0\x11\x0f\x8f\x60\xfe\x52\x7c\x71\x2a\xd0\xcb\x90\x1e\x0d\x2f\x2e\xa3\x61\x93\xe7\x68\xf0\x26\x93\xd1\x7b\x2e\x3c\xa2\x1c\xf2\x7e\xa1\x6e\x9f\xd8\x3a\x7f\x45\xc8\x8e\x55\x7b\x64\xce\xcf\x8d\x78\x8e\x3e\x24\xbc\x68\x9b\xcc\x7f\xb6\xf8\xda\x34\x49\xa7\x30\xd4\xb4\xc5\x8b\xa6\xca\x3a\xec\x4d\x4f\x7d\x7f\x51\xa7\xa4\xa3\x15\xaa\xf3\xfd\x6b\x9f\xc9\xee\x4a\x23\xd4\xb6\x6c\xbd\x7a\xe8\xd2\x9a\x4b\x6b\x2f\xbd\x7b\xe9\x0c\xac\xc6\x55\x97\xdf\xfb\xe6\x75\x18\x96\x7a\x79\x19\x30\xc8\x40\x0d\x6e\x81\x2d\xe8\x77\xd9\xff\xd2\x91\x7f\x2e\xbd\xe2\x61\xbe\x39\xfd\x2e\x4c\xae\x7e\xef\xc6\xe9\x8a\x8e\x8e\xf8\xca\xf6\x8f\xce\xdc\x80\x05\x37\x96\x77\x9c\x06\xd7\x41\x95\x47\x3f\x59\x72\x6b\xd6\x8d\xca\x1b\xeb\x3e\x3a\x58\x19\xf5\x91\x3f\x4c\xc3\x7e\x37\x67\xdd\x78\x49\x47\xbd\x7a\x03\xc4\x9a\x9a\x8f\x17\xc1\x7a\x9c\x73\xe3\xe3\xba\xa8\x7f\x16\x7c\xb4\xf4\x9f\xed\x7f\xea\x2f\x71\x33\xa6\xcb\x3b\x56\x7c\x5f\x05\x2f\xda\x7e\xe6\x4f\x02\x71\x0a\x09\x52\x39\xa0\xd6\xf0\xf8\xfa\x7b\x30\xe0\x12\xc5\x19\x0c\xbd\xdc\x18\xa6\x2f\x0e\x38\x0b\xe3\xa8\x4f\x27\x91\x1c\x91\xea\x45\xf4\x1a\x50\xf5\x95\x89\x7f\xfa\x27\x89\x41\x34\x2c\x81\xd1\x3c\x47\xf8\x11\x04\xe1\x47\x84\xc6\x18\xc2\x25\x8e\xc8\xec\x95\x4c\x10\xc4\xf8\x4f\xbe\xa2\xaa\xf7\x25\x87\xc9\x70\x3c\x87\x0f\x89\x4c\x8f\x90\x26\x52\x1c\xe1\xd7\x97\x20\x08\xe2\x83\xfb\x74\x65\x75\x46\xa8\x8c\x4d\xca\x16\x7e\xb7\x33\xed\xda\x7d\x8a\x23\x72\x37\xfb\x11\x44\x5f\x67\x92\xe2\x3f\x93\xe7\x08\x37\xc6\x41\x7e\x0a\x88\x93\x48\x90\xdd\x4d\x30\x8a\xe7\x88\xbe\xd3\x1d\xda\x90\xa0\xde\xc2\xf9\x63\x61\x3e\xd9\x1f\x0b\x29\x8e\xf0\x71\xda\x80\xbd\xa0\x90\x1c\x41\x71\x84\x1b\x41\x10\x6e\x06\x64\xb0\x96\xfc\x94\xaa\xbb\x46\x82\x40\xd5\x2d\x22\xc1\x0b\xb6\x51\x3f\xe1\x36\xf2\x0a\xf5\x13\x6c\x23\x71\xdb\x47\xb4\x72\x11\x8f\xf0\xff\x5c\x5d\xb5\x50\xe2\x88\xbe\x7e\x0e\x3e\xdc\x44\x39\xc1\x5e\x04\x31\x61\xcc\x9b\xdf\x92\x58\x82\xb5\xd4\xdf\x89\x60\xa5\x1e\x7c\xf7\xc5\x68\xb2\x47\x83\x0f\x01\x1e\xdf\x53\x9f\xc1\x8b\x31\xe0\x22\xe3\x49\xf8\x89\xc7\x57\x1c\xa4\x06\x87\xf2\xf7\x60\xe8\x25\x1c\x7a\x16\x5e\xa1\xff\xce\xc7\x15\x0c\xc2\x5a\x08\xa2\x75\xe4\x24\xd5\xcc\x27\x04\x6f\xcf\xdc\x29\xe0\xa4\x5a\x2a\x26\x7c\x6b\x5a\xb0\xa0\xd6\x7f\x4d\x15\x19\x2d\x7b\xa4\x94\xa1\x38\xed\x5f\x54\x52\x70\xa0\x29\x48\x88\xa4\xb8\x0d\x7d\x5d\x5c\x08\x82\x18\x83\x5b\xe9\x77\xdf\x27\x39\x37\x82\x70\x94\xa1\x7e\x31\xc9\xf9\xf4\x80\xf8\x58\x71\x87\x7f\x51\xe7\x96\xbc\x77\x95\x84\xc4\xff\x30\x34\x9c\x30\x46\x55\xc9\xd5\x10\x40\xef\x3f\x9c\x1e\x5b\x2b\x57\xc3\x27\x34\x97\x47\x10\x44\x7f\x82\x88\xa0\xb9\xc5\x0e\x8b\x0c\xc4\xbe\x8a\xe6\x9c\x3a\xe1\x6f\x3c\xcc\x88\xa0\xca\x6b\x1a\x73\xf7\x0b\x5c\xbf\x1e\xe1\xd0\xdb\x36\x91\xea\x5c\xfc\xc1\xdf\x0d\x79\xe1\x34\x59\x15\xe8\xbb\x30\x8b\x84\xc9\x54\xb5\x3f\xc9\xf5\xef\xef\x37\x9a\x20\x88\x93\x34\x47\xf4\xf2\x63\x0c\x04\x01\xab\xa8\x13\xc3\x4f\xfc\x42\xda\x18\xaa\xbe\x21\x23\xa6\x52\xae\xa6\x39\x82\x21\x9c\x49\x7e\x11\x14\x47\xf4\x22\x18\x3f\x82\xd8\x77\xe8\x68\x4e\xab\x00\x59\x54\x8d\x3f\xe9\x48\x77\xd4\xdf\x49\x58\xf0\x1f\xda\x3a\x7f\xf2\x24\xcc\x56\xdd\x69\x6e\x86\xc3\xd2\x25\x04\xce\xa5\xb6\x5f\x25\x97\x60\x14\x1d\xfa\x01\xb9\x8c\x0a\x5d\x48\xce\x1a\x63\x68\x9e\xeb\x1c\xcd\x08\xa2\x1f\x11\x8e\x07\x69\x6e\xaa\xc1\x09\x3f\xa2\xf3\x4d\xf9\xc9\xd2\x1e\x13\x39\x54\x3d\xd2\x4e\x73\x8e\xb6\x41\x30\x44\xd4\x1a\x12\x49\xea\x6f\x81\xd1\xa7\xc9\xb5\x18\xec\x90\xa6\x77\x48\x43\xd7\xae\x89\xd4\xb4\xf7\x17\xfe\xdd\x41\x3f\xe8\x94\xbb\x4c\xca\x26\xbe\x43\x6f\x5d\x21\xe1\xab\x58\x7b\xc3\xc1\xe9\x28\x59\xe2\xe9\x27\x34\xd7\xaf\xaf\xb3\xc4\x4e\x94\xa5\xac\x95\xd7\xdd\x78\x8f\x3e\x9c\x5a\xbb\xb5\x44\x6a\x2c\xde\xdb\xd8\xa8\xc5\x46\x65\x2b\xdf\xa1\x2f\x78\x57\xc2\x91\x16\x12\x6b\x3b\x9e\x7c\x4a\xdf\x8a\xdf\xb4\xc4\x22\xdf\xa0\xfe\x6e\x39\x17\xe9\x96\xb4\x9a\x2d\x25\x12\xc7\x3a\xbb\xc4\xe2\x03\xc5\xe5\x8d\x4d\x5a\xa5\x5e\xfd\x83\xc7\x11\x16\xf2\xef\xd6\x33\xe2\x32\x06\x62\x2d\x04\xd2\xea\x5b\xb6\x48\x7e\x0e\xd6\x7e\x44\xd9\xe6\xa8\xfd\x78\xf0\xc4\x49\x6f\xbc\xaf\xad\xae\xc8\x2e\x97\xe0\xc5\x2b\xe8\x49\xad\xdc\xb0\x5b\x2f\x23\x0f\x6f\x7e\xb1\x44\x1b\x19\x93\x11\x27\xa1\xc7\x12\xf0\xa0\xae\x9e\xac\xee\x90\x21\xe5\x1c\xdf\x53\x4e\xc4\xfa\x8d\xef\x21\xb9\xea\x8c\xb6\x7a\x5f\xf6\x3e\x09\xd8\x2b\xc8\x53\x2b\xd7\xff\xc5\x79\x6f\xa9\x36\x2a\x36\x3d\x4e\xc2\x7e\x4b\xa0\x1f\x75\xb0\x35\x7f\x7f\x85\x8c\x13\x6c\x4b\xf9\x39\xb8\x98\x42\x0a\x16\x93\x43\xd1\x4a\xa1\x0b\x58\xc9\xe1\xd4\x28\xdc\x4e\x06\x53\xef\x1a\x0e\x9e\xfe\xf1\x7a\xfc\x3f\x4d\xf2\xfb\xf3\xe9\x51\x1b\xd7\xbc\xe6\x7b\x6c\xed\xb7\xf2\x6d\x67\x9f\xd3\x52\xf5\xce\x3e\xe7\x4f\x81\x3b\xfa\x93\x9c\x9f\x63\x34\x26\x16\xff\x40\xb9\x2b\x8d\x4a\x1b\x0c\x2d\x83\x17\x3c\xcc\xa0\x51\x02\xe0\x15\x7b\x20\xbc\x02\x67\x40\xc3\xc5\xdb\x12\x6c\xac\xd2\x5b\x6c\x88\x6c\x3d\x7b\xb4\xf5\xac\x64\xab\x87\x61\x3c\x97\x7b\x22\x20\x6b\xbb\x14\x43\xa5\xa6\x67\xa4\x9a\xe4\x58\x9f\x83\x16\xf2\x42\x4b\xf1\x35\x19\x7e\xc7\x61\x4a\x6f\x71\x7f\x64\xeb\x19\x07\xb1\xce\x7e\x00\xa6\xc0\x39\x11\x7b\x91\x06\xd3\x9e\x14\x83\x30\x85\x82\xcb\x62\xa1\x00\xbe\x60\x61\x67\x52\xc9\x19\xf9\xd6\xbc\x2c\x6b\x56\x9e\xbc\x2b\x74\x5d\xdc\x56\x61\xf2\xaa\xf3\x77\x7f\xbe\xfd\xe8\xc9\x91\xe6\xb4\xed\x35\x32\x5c\x65\x95\xe1\x59\x7c\xa6\xd9\x68\x34\x4a\x58\xa0\xba\x91\x69\x19\xa9\x19\xa9\xc2\x5b\x54\x6a\x5a\x5e\x7e\xf1\xcd\x1f\x8b\xca\xe4\xd4\xaa\xc9\x10\x99\xab\xcd\xcf\xcb\xcf\x97\x6e\x53\x85\xd6\xd4\xe4\x6c\xf9\x24\x0e\xff\x03\x5e\x23\xf3\x72\xf2\x73\xf2\x85\xcf\xa9\xfc\xbc\xd4\x54\x59\xe9\x7b\xd6\x61\x06\x43\xa6\x1a\xd3\xd2\x52\x84\x09\x14\x37\x1b\x2e\x8b\x45\x02\xbc\x0e\x16\x96\xcb\xfc\xcb\x94\x6c\xab\x25\x4f\xde\x15\xb6\x2e\x6e\x8b\xd3\x14\x99\x5b\xec\xb0\xe6\x68\x73\xda\xf6\x6a\x09\xae\xb2\x30\x03\x86\xf2\x73\xd5\x91\xce\xbc\xec\x11\xe6\x50\x29\x69\xf9\xf9\xb2\x25\xeb\x86\xe2\x4b\xe6\x59\xf2\x72\xf3\x84\xcf\xa8\xfc\xbc\xb4\x14\x59\x67\x63\x50\xe0\xdf\xb3\x6e\xcf\x5b\x27\x44\x53\x69\x69\x3d\x65\x74\xc8\x42\x9e\x6c\xce\x3b\x5f\x20\xeb\xe8\x68\xa5\xc4\x31\xab\x50\x92\x1e\x8d\x85\x8a\x31\x4f\x7e\x3c\x0d\xaf\xc3\x63\x0f\x33\x68\xe1\xe7\x4f\x21\xf1\x2c\x14\xb5\xc2\xf0\xf7\x61\x38\x50\x30\xac\x09\x86\x42\x2f\xe8\x0f\x1a\xee\xc2\x73\x1d\x35\xd9\xd6\x87\xff\x22\xfa\x78\x40\x4a\x78\x66\xc8\x6e\x89\x5b\x4a\x60\x38\x9d\x56\x5c\x9a\x59\x26\x54\x55\x94\x54\x17\xcb\xa5\x75\xf9\x87\x4f\x6b\x95\xb9\x2d\xfc\x47\xc6\x98\x83\xdb\x85\xed\x31\x81\xb3\x33\x64\xe8\x45\xe9\x6c\x3f\xa1\xc0\xaf\x88\xdd\xbc\x3d\x44\x0a\x0b\xf4\x4f\x7c\x47\x98\x35\xb7\xaa\x72\x9b\xbc\x0f\x48\x32\xac\xed\xc3\xe8\x23\x42\x53\x79\x51\x65\x55\x4c\xc9\xbb\x15\xf2\x84\x03\x2b\x5b\xee\x6b\x4f\xed\x3d\x72\xb0\x5e\xaa\x6b\x3c\x5e\x72\x5e\xb8\x75\x21\x2a\xa9\x4e\x8e\x41\x37\x72\xef\xce\xb5\xe5\x6b\x85\xb0\x84\xe4\xd8\xa8\xda\xc4\x93\x71\xb2\x99\x7e\x10\x74\x7e\xdb\x38\x2d\x9c\x81\x9d\xfc\x5b\xb8\x92\xda\x5e\x12\x77\xa0\xb4\x2a\x37\xcb\x2a\x21\x4b\x67\xc4\x86\xa7\x6e\x16\x56\x6e\x2d\xac\x0c\x95\x83\x6b\xe3\x8f\x5e\xd1\xc2\xae\x05\x74\xf9\x6f\xa7\x0b\xf6\x01\x05\x7c\x15\x89\xc2\x63\x1a\xce\xa1\x8e\xcf\xda\x93\x62\x4e\x11\xb6\x86\xa4\x84\x47\xcb\xf8\x3e\x0e\x57\x76\xc2\x4b\x74\xe1\x32\xf2\x58\x49\x73\xf5\x71\xc1\x6a\x35\x19\x0b\x65\x94\xe9\x56\xfc\x86\x57\x76\xc2\x70\x75\x27\xad\x04\x42\x16\x3f\x3a\x6a\xd6\x46\x7f\x69\xed\x06\xfd\x9e\x2d\x42\x64\x58\x4e\x7e\xb8\x8c\x23\x68\x1c\x1e\x4a\xda\xbc\x69\xee\xc2\x73\xf0\xa2\x0a\xd6\x90\x47\x5a\x8e\xec\x3b\x21\xb4\xb7\xc6\x6e\x6b\x90\x1b\x03\xca\x16\xbe\xa9\x55\xb7\xc1\xaf\xbc\xff\xb6\xad\xfe\x12\xe7\xa7\xf1\xdf\xd6\x72\xf2\xe4\xe1\xc3\x27\x4f\x1e\xde\xe6\x2f\xdb\x3d\xd1\xc6\x1b\x4c\xdb\x4d\xa9\x12\x5a\xa8\xec\x40\x6b\xc4\xde\x44\x86\xbb\xf0\x3c\xb1\xb4\x32\xed\x80\x70\xe6\x44\x51\x65\xab\xbc\x77\x10\x19\xba\x65\x71\xfc\x3c\x61\xc6\x3b\xfb\x5a\xb7\xc8\x5c\x15\xb3\xe1\x58\x64\xc7\x57\x5a\x78\xe5\xde\x4f\xa0\xb9\x7e\x36\x62\xc3\x21\xe9\xe0\x86\xbd\x8b\xfd\xb4\xa0\xb1\xc9\x9b\x59\x68\x44\xeb\x17\xb0\x22\xb2\x3a\xd2\xc3\x66\xfd\xe2\x0b\xd0\x73\xad\x3a\xca\xd3\xe6\xc7\x73\x9f\x74\x35\x75\x4d\x25\xb1\xbf\x05\x1c\xbd\xb9\xbf\xc0\xb5\xce\x13\x65\x45\x1f\x23\x2a\x2f\x88\x8c\xda\xd4\xf5\x2b\xff\x84\x05\x5a\xb4\x27\xea\x28\x3f\x7e\xdc\x63\x43\x69\xa4\x25\xd1\xe0\xad\x8e\xc5\x7f\x93\xdc\xa9\x7c\x96\xe4\x5a\x4b\x8a\x2d\x95\x86\x52\xc6\xbd\x47\xc7\x74\xd0\xa0\x1b\xb8\xa5\xb3\x60\xf5\x80\x33\x2c\x68\x9c\xda\x1e\xd8\xeb\xd0\x97\x87\xd5\xec\xf0\x49\xf7\x7e\xb1\xe6\xe7\x5b\x25\xee\xbc\x35\x3f\x35\x79\xd2\x8d\xb9\xf7\x1c\xa1\xcc\x3d\x50\x9b\x95\x5d\xfc\x0f\xf0\xf6\x29\xd8\x01\x56\x2d\xf0\xe0\x0e\xcb\xa0\x0c\x96\x02\x33\x64\xc0\x39\x49\x09\xe9\x9e\xc5\x2b\x2f\x88\xe8\x3a\xdc\xab\x0d\xe7\xde\xc6\x57\xc0\x15\xfb\x31\x5d\x46\x0a\x87\x21\xff\xdf\xec\xff\xcb\xfa\x47\x3a\x32\x84\xef\x31\xd6\x61\xab\x57\x3e\xdb\x63\xa6\xb7\x3b\xfe\xfb\xa8\x68\xb3\x82\x15\x52\x44\x0f\x98\x20\x82\x95\xbb\xc0\x7d\xa5\x58\xc1\x97\x9f\x28\xda\xf4\xab\x45\xee\x42\xc7\x52\xb6\x4b\x4f\x73\x5f\x81\xd5\x73\xa2\xc8\x5d\xb0\xe9\xa7\x38\xe2\xce\xd8\x5f\xb0\xda\x66\x0f\xff\x8a\xe5\xbe\x3a\x1b\xb5\xe8\xd8\x72\x01\x3b\xa9\xe5\x8b\x36\xad\x8a\x92\x67\xe0\x9b\x24\x5e\x1f\xca\x72\x17\xe6\xd1\xdc\x57\x2f\xb3\x8f\xbb\xe7\x53\xd8\xeb\xd6\xe8\x6f\x24\xee\x82\xad\x93\xfa\xe6\xd6\x4f\xd0\x4b\xb6\xcf\x86\x08\x36\x48\x04\x5f\x18\x60\x9b\x00\xfd\xc1\x17\x7c\x44\x98\x0e\xe3\x94\x72\x18\x8e\x22\x0c\x87\x22\xd0\x70\xdd\x06\x9d\x5b\xa2\xb2\x91\xb7\xa6\xe4\xa7\x48\xf8\x22\x95\x92\x9a\x9a\x2c\xcf\xa0\xe7\xa3\x2e\xe4\x6d\x5c\x82\x3a\x18\x02\x6b\x61\x39\x78\x82\x00\x8b\xee\x43\x9f\xe0\xf9\xd2\x0c\x3a\x39\x3f\xd5\x2a\x71\x5d\x06\x60\xbf\x67\xc1\x85\x86\xd7\xb1\xf8\xf0\x50\xac\xc5\xf5\xb8\x1e\x6b\xf1\x00\x6c\xc4\x00\x68\x80\xfe\x10\x71\x01\xfa\x4b\xaa\x87\xfd\x75\x1e\xde\x11\x65\xae\xdb\xb0\x81\x95\xfe\xeb\xae\xbf\xec\x90\xd0\x47\x0c\x12\x61\x11\x48\xd8\x1b\x78\xdb\x60\x90\x61\xb8\xc3\xc8\x97\x61\xa4\x92\x08\x2f\xc3\x13\xd0\x70\x0f\x0c\xdc\x05\x83\x7d\xbd\x2d\x8b\xc7\x8d\xe8\x83\xb1\xb8\x16\x3d\xa7\x3e\x84\x61\x12\xf7\x95\x01\x2a\x61\x26\x4c\x80\x89\xe0\x71\xfb\x0d\x1c\x24\x71\x17\x0c\xca\x07\xd8\x87\x57\xfc\xf1\x3a\x5c\x57\xfd\xa1\xcc\xe1\xc6\xa6\x5e\x07\x57\xd0\x49\xf9\x79\x39\x05\x96\x02\x8b\x35\xb3\x20\x3d\x7f\xe3\x59\x2f\x43\x69\x54\x56\x42\x12\xf3\x2a\x52\x38\x68\x05\x0e\xf9\xcf\xe6\xd6\x7f\x80\x23\x90\xb9\x07\x06\xc5\x1b\x72\x30\x47\xf5\xc6\x03\x18\xb2\x6b\x96\x51\xde\x18\x57\xf4\x5e\xa9\xa5\x2c\xa7\x42\x86\xde\x8a\xdd\x92\x6b\x2a\xc8\xcc\xf6\xce\xc9\x4c\xcf\x4f\x17\x90\xa5\x52\x53\xf7\xa4\x98\x64\xc3\x32\x63\x34\xf9\x70\xe5\xc8\x73\xf8\x82\x80\x35\xb8\x1b\x8b\xf1\x16\xc6\xc3\x3f\xd0\x1b\x76\x82\x00\xc4\x9d\xbb\xd7\xe5\xec\x1d\x45\xbb\x2a\x22\x98\x6d\x4d\x67\x63\xae\x97\xe6\x5a\x4a\x04\x58\x9a\x07\xa1\xf0\x02\x74\x68\xdd\xab\x50\x03\x7a\x17\xd8\xce\xba\xea\xa8\x1a\x1d\x59\xc3\x63\x3f\xe8\x87\xfe\x16\xec\x8b\x1e\x18\x86\x11\x5e\x03\x7f\x07\x8a\xf5\xc6\x2d\xb8\xe5\x7b\xd1\xfb\xf9\x00\xf5\x99\xfa\x8c\x0c\x0b\x4b\xdc\xb9\x5d\x8b\xfe\x34\x6a\xd0\xda\x31\xcf\xb9\x99\x29\xf8\x53\xcd\x07\x4b\x6a\x6b\x65\xe5\x99\xf2\xec\xf9\x80\x3f\x44\xd8\x02\x5b\xfe\x25\x7a\x0f\xfc\x1d\x22\x20\x0c\x3c\xa0\xaf\x09\xfc\x1d\xc2\xbd\x75\xb8\x4e\x67\xaf\xe0\x51\x0f\x7a\x4a\xe9\x54\x3a\x41\x8f\x7a\xb2\xe7\x39\x93\x6e\x57\x1d\xb5\x08\x2a\xd9\x55\x6b\x23\x76\x6e\x93\xbb\x3c\xd4\x3b\xe4\xe2\x77\x76\x4c\x7e\x53\x8b\x93\x40\xc2\x41\x30\xf9\xe1\xad\xe6\x2b\x1f\x48\xd0\x0f\x68\x28\x53\x12\xee\xc2\x50\xa6\xb6\xbd\xea\xfc\x45\xed\xcf\xe3\xfe\xf9\x9a\xd4\xdd\xbf\xbb\x82\xc7\x88\x3d\xe8\xbd\x69\x2c\x86\x32\xe1\xc9\x91\x09\xa1\xc2\x06\xe4\x7f\xab\xdb\x22\xe3\x35\x18\x82\x35\xf0\x03\x1c\x85\x55\xb0\x02\x8e\xa4\x49\xa6\x9b\xd8\xeb\xc0\x2b\x77\xde\xfd\xd5\xdb\xbd\x4a\xd1\x80\xd5\x05\x36\xb0\x9a\x90\x38\x11\x34\xbc\x42\x89\x2b\xe1\x43\x56\xa1\xc4\x15\xc2\x8a\x88\xe8\xa0\xed\xf2\xb6\x0d\x2b\xfc\x87\x09\x43\x57\x9c\x3c\xbc\x51\x6e\xdc\x16\x51\xb1\x02\x3e\x64\x55\x4d\x9c\x48\xdb\xf4\x6e\xe0\x2e\x4a\xf3\x14\x3d\x5a\x55\x3d\x5a\xff\x67\x38\x8f\x6a\x62\x65\xd4\xd3\xe7\x6b\x2a\x1a\x9b\xe5\xc3\x6d\xe7\x4f\x3e\x15\x9e\x5c\x80\xab\x62\xb3\x7c\xf8\xf8\xf9\x93\x4f\x84\xa7\xe7\xe1\xaa\x78\xf8\xef\x94\xf3\xfe\xdb\xda\xe4\xa0\xc3\xd5\xd1\xe7\x05\x1d\x12\xf6\x36\xfe\x8e\xa8\x58\x3d\xff\xba\xb8\x83\x37\xab\x6a\xe0\x03\x51\xd5\x60\xa7\xda\xa9\x74\xaa\x7a\xb5\x93\x54\x3b\x8f\x89\xb4\x7b\x15\x1c\x66\x75\xd4\x45\x57\x9b\xd5\xa6\xe5\x6d\xd9\x60\x62\x61\x3b\x2c\xff\x1a\xfa\x83\x2c\x23\x2a\xad\xbc\x72\x5c\x3d\x41\x3a\xa2\x5f\xc3\x72\xd8\xae\x9d\x07\x9a\x5b\x62\x97\xd5\x66\xa5\x1d\x52\x51\xa3\x23\xd7\x2f\x15\xd5\x59\xd4\xae\xf8\xed\x91\x55\x32\xf4\xc1\x3e\xea\x66\x75\x33\x26\x40\x82\xa3\xf2\xd5\xfb\xea\x7d\x47\x25\x29\xbe\x8a\x2f\x24\x60\xc2\x1f\xa2\xad\x8f\xad\x8f\x83\x8a\xac\x8a\x6c\x2e\xdb\xaf\x75\xaf\x32\xc3\x78\x5b\x1d\x8c\x73\x31\xc3\x78\xfb\xbb\x30\x01\xbe\x83\x71\xae\x3a\xb2\xb7\xad\x93\xff\xf8\xbd\xb3\x37\x1a\x4f\x58\x22\x6a\x25\x13\x5d\x17\x5d\x1a\x5e\xb6\x0b\xf8\xa7\x5e\x91\x07\xa2\x9a\x43\xea\x18\x0b\x35\xe3\xfa\xf2\xec\xd7\xb3\x19\x1c\x92\x8b\x32\x72\x38\x54\x6b\xb0\x18\xb2\x0c\xd2\x75\x55\x50\xe6\xc0\x58\x4c\xd6\x62\xaf\x51\xb3\x07\x22\xe5\x07\xc4\x0f\xfe\x12\x3c\xc2\xb1\x61\xca\x18\x35\x54\xc0\x36\xb4\xe0\x3e\x3c\x82\xed\x10\x89\x95\x70\x09\x86\x81\x74\x18\x5e\xf8\x55\x36\x59\xca\xab\xf6\xd6\x16\xd5\x79\x8f\x83\x57\x22\xd6\x07\x05\x04\x6e\xf3\x36\xd3\x7e\xf3\x86\x46\xbd\x22\xe0\x4e\x1c\x05\x7a\xd8\x04\xef\xc2\x34\x58\x0a\xab\x20\xec\x4b\x64\x70\xd5\xe7\x32\xa6\xfe\xf8\x4c\x95\xe0\xb6\x00\xcb\x61\x22\xf8\xc0\x6a\x58\x81\x63\xbe\xc5\x37\xdb\x65\xbf\xaa\xf9\xe5\x21\xf7\x19\x63\x7e\xca\xfe\x3c\xe7\xd1\x75\x03\x74\x24\xfb\xbb\xab\x8e\x2c\x51\xa2\x79\x1c\x88\xbd\x5f\x46\x19\xe3\xdf\x86\x56\xf0\x9b\x2d\xc1\xc0\x65\x4b\x1e\xa0\xaf\x80\x3e\xa8\x41\x2d\xca\x38\x02\x5c\xd0\x07\xc6\x40\xef\x4f\x4e\xff\x71\x59\xbe\x86\x2e\x29\x31\x86\xd8\xa4\x38\x6f\x33\x3d\xf6\xed\x21\xa1\x3e\x02\x46\xe2\x10\x58\x02\x3b\x52\x65\x0b\x0d\x1b\x52\x61\x21\x2c\x83\x4d\x02\xfc\xb2\x0f\x2f\x60\x0a\x30\xf2\x9c\x83\x17\x27\xdf\x17\x6e\x7f\x7c\xe6\x0b\x93\x9c\x4b\x9b\x3e\x1b\xdb\xb0\xa8\x1c\xdd\x0f\xcf\x3c\x1e\x01\x3a\xe6\xaf\xe7\x3c\x5c\x9e\x3e\x7a\x7e\xfd\x64\xea\x86\x76\xc9\x4c\x57\xc4\x94\x85\x96\x45\xbe\x3a\xdd\xcb\x50\x95\xbc\x37\xba\x94\xb1\x50\x7b\x63\x02\x4d\x11\xc2\x9a\x80\x6d\xab\x33\x72\xa3\x2d\xe9\x72\xe5\xa2\x53\x89\x97\xe2\x19\xe8\xbd\x1d\xa8\x79\xd8\x5f\xfb\xbb\xad\xaf\x8f\x08\x8d\x10\x21\xda\xad\x30\x53\x74\x4d\x67\x6d\x1a\xfe\x43\x11\x06\xb1\x70\x18\x62\x31\x16\x0f\x4b\x36\xab\xe7\x87\xa2\xa4\x7a\x52\xf0\x1a\xbc\xf0\x2f\x58\x08\x01\x5a\x08\x18\x0c\x0b\xf1\x35\x78\x41\x52\x3c\xa9\xbf\x09\x65\xd0\x78\x82\xc3\xa7\x1d\xc3\x3f\xa4\x2e\x2b\xf5\x5f\xcf\xca\xc3\x31\x3c\x06\x7f\xc8\xf0\x3b\x2b\xf7\xdc\x0e\xb4\x5b\x41\xe3\xa2\xa3\x0d\xa0\x71\xb5\x69\xdc\xfe\x26\x90\xe0\x77\xf6\x6f\x01\xf2\x7f\x13\x20\x87\x8b\xaa\x95\xff\x6f\x26\x41\x13\xeb\xae\x34\xf6\xbc\x8d\x35\x92\x75\xcc\xa9\x8d\x22\xcc\x14\xb9\x3b\x06\x5b\xb6\xe2\xe8\xbd\x2c\x4e\x87\xd3\x2c\x4c\x87\x54\xf1\xec\x69\x43\xd4\x71\x19\x17\x63\x0e\xb9\x61\x67\xe3\xa2\x8b\x02\x7c\x4c\xe1\x42\xd0\xf0\xe0\x0a\x43\x49\xee\x07\x43\xeb\xc6\xfa\x15\xc5\xcb\x18\x68\xf7\xc4\x09\x54\xc2\x93\x75\xdf\xcc\xfe\xe8\x29\x78\x79\x29\xe1\x94\xad\x53\xd5\xf3\xf0\xce\xdf\xc2\x24\xee\x8e\xe1\x9b\x96\x7b\x57\xae\x4a\x60\x16\xb9\xc7\x06\x18\x27\xca\xdc\x1d\x83\x23\xd7\x66\x5c\x0b\x6b\xd1\x3c\x73\x6e\xdc\xae\x25\x12\x56\x2a\x83\xc8\xf2\xa4\xa8\xa2\x48\x01\xad\xd4\x1e\x16\x42\xa9\x87\xa8\x21\xd5\x59\xa0\x51\x35\x3d\x9b\xfa\x73\x3f\x18\x50\xc4\x79\xe4\xe1\x79\xd3\x2a\x27\x0b\xdc\x1d\xc3\x6a\xf6\xa4\x08\x91\xb0\x10\xde\x84\xa0\x26\x19\x56\x52\x95\x15\xd6\xf2\x62\x19\xfe\x50\xb6\xdf\x18\x46\xbe\x36\x61\x09\xbe\x88\x5e\x5a\xee\x07\xc3\x49\x11\xcc\xb0\x16\x8a\x59\xc9\xdd\x0c\x7a\xc5\x55\x84\x33\xec\x63\xe7\x03\x3a\x1a\x33\x58\x1d\x63\xbf\x19\x34\x9c\x4d\xd1\x40\xe7\x2c\xd1\x6e\xf5\x1c\xcc\xae\x55\x7c\xf8\x4d\xf9\x41\x5b\x37\x09\xdc\x9f\xdd\xed\xd4\xa6\xa0\x96\x63\xf9\xf2\x2d\x45\x43\x36\xe6\xd5\x57\x37\x09\xf6\xe1\x54\x53\x7d\x44\x50\x9e\x7c\x4b\xd5\x90\x18\xa9\x28\x7c\x48\x64\x64\x88\xd4\xa5\xa1\x38\xdb\xee\x88\xaa\x86\x86\xea\xaa\x7a\xd9\xa6\xa1\x1a\xaa\x22\x43\x64\x65\x50\xd7\x76\xfe\x7e\xfa\x07\x31\x5f\x48\x03\x94\x55\x24\xf8\x46\xe3\xa1\xc7\xf8\x93\x80\x3f\xe1\xa1\x11\xe8\x1b\x2d\x0f\x52\x57\x91\x31\x6f\xa6\x2e\x9c\xa0\x55\x9f\x81\x06\xde\x73\xcc\x46\xde\x13\x41\x43\x3b\x66\x50\xbd\xc1\x0f\x3a\x60\xca\x57\xe0\xf7\x15\x4c\x81\x0e\xf0\x73\x81\xb5\x30\x45\x47\x7a\xc3\x14\x57\x1d\x79\xd2\xa6\xe7\xdb\x03\x8e\xae\x96\xba\x96\x52\xab\x03\x36\xaf\x59\x73\x64\xf3\x19\xd9\xb6\x94\x3a\x73\xe4\x68\xbb\x0c\x3b\x3c\x51\xc5\xd3\x78\x0a\x11\x93\x70\x23\xf4\x85\x45\x48\x4b\x76\x1f\xea\xcc\x91\x23\x67\xda\x03\x8e\xac\x96\xbb\x77\x50\xf1\x97\x52\x2e\xbf\xaf\x05\x15\x4e\xc3\x29\x50\x21\x11\x36\x62\x5f\x5c\x04\xb4\xd4\xed\x43\xad\x0e\x08\x58\xbd\xe6\x48\xc0\x19\xd9\xbe\x83\x2a\xd3\x17\x2c\x5b\xac\x55\x68\x28\xe0\xcf\x04\x1c\x59\x2d\xe1\x62\x0a\x8e\xa0\x27\x1e\x83\x55\xf8\x50\x50\x57\xab\xa4\x4a\xa9\xab\x96\xe4\x2d\x2d\xd2\xcb\xe8\xe5\x60\x5d\xb3\xda\xc1\x0a\x4b\x28\x3c\x02\x9e\x70\x0c\x57\xc1\x23\x41\x59\xa5\x90\x0a\xa5\xac\xba\x9a\x76\xc5\x70\x49\x86\x97\x1c\xa6\xb4\xcb\xee\x6a\x12\x5a\x81\x01\x19\xfa\xd6\x40\x6f\xc5\x17\xfa\x2c\x06\x37\xa5\x16\x7a\x4f\x04\xca\xa3\x08\xa8\x56\xe8\x13\x08\xbd\x3a\xe0\xc5\xa3\xc0\x28\x13\x80\xf6\x85\xde\xdc\x47\xe1\xf6\x05\x3a\xb7\x74\xfe\x44\xe9\x35\x98\x7b\x59\x68\x2c\x08\x0c\x9d\x8d\x82\x4a\x06\x4d\x90\xf1\x85\x2a\x12\x17\x20\xf2\xcd\x86\xc3\x99\x87\x53\x77\x47\x87\x87\x47\x84\xee\x69\x4c\x3a\x60\x38\xc0\xe0\x29\xbb\x86\xaf\x29\x3e\xd8\x70\xe1\x2a\xce\x0d\x28\x91\xa0\x0f\xfe\x4e\x66\x85\x85\x64\x87\x09\x9c\x1b\x13\x1b\x63\x4c\x49\x90\x03\x7e\xc5\x3e\x70\xf3\x5f\xda\x49\x5d\x66\xbe\xe1\x64\x7b\xc3\xfd\x9f\x71\xd3\xec\x7a\xc9\x1a\x51\xb3\x34\x5c\x1b\x13\x1b\x11\x25\x71\x1e\x7e\xd3\x70\x05\x54\x77\xca\x5c\x5f\x03\x8e\xc1\x6f\xf8\x0b\xcd\x0f\x3e\x3c\x06\xe3\x71\xeb\xba\xd8\x90\xa4\x84\x77\x56\xde\x38\x1a\x2c\x45\xd7\x47\xd6\x45\xd5\x31\x51\x51\x89\xb1\x41\x5a\xec\x05\x03\x91\x03\xe2\xd3\x1b\x17\x3b\xf3\xcd\xf9\xc6\x7c\xa9\x64\xaf\x29\xbb\x58\xce\x79\x65\x3f\x92\x40\xa5\x30\xd9\xf9\xd5\x96\x0f\xb6\x5c\xbc\xae\x7d\x7a\xe7\xf1\xe7\x97\xa5\xfd\x55\x07\x4b\x0e\x15\x37\x97\xb4\x94\xd5\xd7\x1b\x2b\x33\x2a\x12\xf7\x32\xdc\x47\xe1\xa5\x49\xc9\xb9\xd1\xc2\x70\xbc\x93\x00\x23\x8b\xcc\x15\xc5\xb9\x72\x61\x51\xad\xa5\x54\x00\x12\x8e\xec\x9a\xfa\x95\x7c\x72\x93\x69\xcc\x32\x2d\xbe\xee\x8f\x43\x91\xc0\xde\x12\xba\x0d\x46\xcd\x12\x7c\x45\xc0\xcd\x38\x13\x28\x78\x77\x92\x9c\x78\x28\xe9\x70\x8b\x96\x6b\xf4\x45\x2a\x99\xc7\xad\x30\x03\xdf\x85\xa5\x6f\x4b\xdc\x47\xe1\x21\xb7\x6e\xc7\xdf\x11\x94\xd1\x50\x00\x1f\x2a\x83\x60\x44\x18\xe8\x70\x52\x9b\xdc\x06\x14\xb0\xf0\xe0\x0f\x2d\xc7\xfa\xfd\xa8\xbf\x3b\x0c\x5f\x43\x49\xdd\x80\xbd\xfc\xa5\x67\xdb\xf1\x75\xc5\x82\x3e\x02\xe7\x9b\x89\x2e\x2b\xde\x7c\x19\x49\xe8\x83\xdf\x1c\xc7\x17\xe5\x82\x88\xb0\xfc\x30\x61\xc2\xcb\x83\x27\x04\x96\xfb\x17\x05\xcb\xc8\x6f\x5b\xf9\x06\x7a\x6a\x1d\x4d\x5a\x03\x6b\x81\x81\x35\xca\x06\x58\x03\x93\x60\xa9\x8b\x19\x96\x83\x04\x3b\x61\x0f\xf8\x5f\x81\x9d\x60\x80\xf5\x30\x1a\xf4\xae\xb6\x7a\xa5\x8e\x9f\x94\xb2\x73\xd1\x4c\x01\x5d\xa2\x80\x00\x1a\xc6\x9c\xfa\xe2\xf6\x3f\x8f\xaf\x1a\x9b\x2f\x83\x3f\x0c\x60\xa1\x0f\x68\x60\x6b\x85\xac\x64\x79\x4e\x4a\xd9\xe1\xa4\x8b\xfe\x0f\xdd\xc7\x27\x56\x8d\xcd\x93\x61\xbd\x83\xae\x77\x0f\x1d\x8c\x84\x17\x79\xac\x4e\xc4\x17\xe6\x4f\x90\x92\xa2\x22\x52\x62\x13\x99\x35\xf3\xf1\x74\x4c\x4f\x6f\xbc\x56\x71\x7a\x81\x1c\x53\x1a\x59\x90\x50\xc1\x2c\x7c\x90\x00\x0c\x54\x6b\xa1\xaa\x04\x5e\xb8\xfe\x40\x2a\x29\xaf\x2e\xdc\x57\xc2\x9c\xbe\x0e\xd7\xca\xe1\x27\x01\x7e\x82\xd3\xb1\x6b\x3f\x94\xcb\x93\xaa\x0c\x25\xb1\xcc\xf5\x71\xa5\xc8\x60\x95\x16\xf4\xb6\x2c\x5e\xa7\x10\x3a\x3b\xa1\x63\x08\xca\xdd\x0c\xe1\x76\x3d\x84\xbb\x98\x21\x1c\x7c\xff\xeb\xe7\x6a\x0f\xb7\x0f\xe2\xa1\x01\x43\x21\x14\x1b\x24\x75\xf3\x50\x56\x67\xbf\xf8\x4c\x4c\x67\xa1\x8e\x86\xe1\xe0\x8e\xee\x38\x5c\x56\x53\x9f\x89\x8a\xc6\xee\xdc\x38\x7e\x28\xdb\xed\x46\xe3\x70\x74\xa6\x48\x58\x67\xb3\x52\x43\x58\x27\x5a\x3f\x48\x54\x36\x53\xd0\x00\xa1\x10\x0a\x0d\xb2\xbb\x52\x07\xc1\x2e\x66\xf0\x7c\x02\xab\x7e\x81\x35\x4f\xbe\x7e\x02\x57\x9f\x82\x87\xab\x8e\x94\x6d\x73\xf9\x83\xd1\x95\x3b\x25\x5c\x47\xed\x8c\x8a\xda\x29\x23\x45\xef\xac\x8c\x3a\x28\xc1\x3a\xea\x60\x45\xe5\x41\x59\x4d\x44\x86\x8f\x4f\x4d\x4d\x90\xf4\x54\x7c\x6a\x7e\x99\x0c\xb1\xb4\x93\x61\x38\xb5\x33\x0a\xfe\x25\xbe\x43\xc5\xa7\xfd\x85\x8d\xaa\xdc\x29\x8d\xa4\x76\x44\xc3\xbf\x44\x3d\x95\xe0\xa4\xcd\xa6\x6f\x9e\x69\xff\x54\x02\x4f\xea\xd4\xa1\xe8\x1d\xfb\xe4\x43\xfb\x0e\x55\x9c\x12\xc0\x9b\xba\xd9\xbe\x66\xba\x8c\xd9\xb4\xf2\xe8\x31\x3f\x63\xf5\xea\xe9\x12\x2e\xa3\xd6\x05\xed\xad\x8f\x96\x71\x36\x1d\x9f\x96\x16\x2f\xe9\xa9\x84\x94\xbc\x32\x59\x79\xd5\x21\xe2\xa6\x04\xe5\xd4\xcd\x33\x0e\x9e\x57\x69\xf0\x50\x54\x1e\x34\x03\x7f\x47\x8d\xd4\x7d\x85\x42\xcd\xc0\x81\xa8\x91\xbb\xaf\xd0\xa8\xf9\x7d\x20\x68\x24\xfb\x15\x0a\x34\xbf\xff\x0e\x1a\xd9\x1d\xee\x89\xdf\xb2\xf6\x21\xca\x72\x1e\x87\x28\x67\x70\x88\x7a\x86\x54\xfa\xe2\x6d\x7e\x3c\x7c\xac\x72\xf8\x31\x69\xc6\x0e\x1a\x3e\xb7\x5b\x49\x65\x3e\x05\x9f\x77\x5b\x49\x08\xb7\x87\xf3\x30\x06\x3d\xc1\x13\xc7\x48\xdd\x7a\x0a\xc7\xa0\x27\x7a\xe2\x18\xb9\x5b\x4f\xe3\x18\xf0\x44\x4f\x18\x23\xd9\xf5\x14\x8c\x01\x4f\xf0\x84\x31\x8e\x61\x18\x0d\x77\xe1\xcf\x46\x9d\xdb\xd9\xcf\x3d\xcc\x40\x82\x17\x50\xf0\x0f\x60\x90\x7a\xb2\xa8\xd1\xce\x01\x3b\xec\x29\x0c\x02\x0a\x7a\x01\xc5\x3d\x6a\xd5\x31\x84\x8d\xe7\x1b\xa2\x6b\x42\x73\x25\x5c\x04\x9f\x93\x39\x05\xd9\xd6\x42\x6d\x63\x68\x5d\x90\x45\xc2\x4d\x60\x27\xb3\xf2\xb2\xf2\xf2\xb4\x07\x77\xd7\x05\xc6\xc4\xa7\x24\x1a\x24\x75\x00\x55\xb2\x27\xbe\x20\x46\x70\x44\xf7\xc8\x5c\xbb\x9f\xea\x43\x95\x18\x1c\x98\xc0\xdd\xa1\x3b\xd3\xb2\x52\xb3\xd2\x65\x0c\xc0\x7f\x93\x51\xc9\x09\xd1\xe1\x46\x8b\xd1\xa8\xc5\xd5\xf8\x0b\x19\x92\x1e\x15\xbe\x4b\x1b\x52\x11\x5e\x9f\x26\xc1\x46\x54\x48\x63\x9a\x29\x3d\xd5\x89\x48\x97\xe0\x1d\xfc\x86\x34\xa6\x19\x53\x53\xb5\x3b\xeb\x43\x9b\xf6\x95\x15\x14\x17\x4a\xca\x40\x2a\xa9\x70\x6f\x0a\x3c\x66\x0b\x8a\x0b\x65\x65\x10\xc5\x19\x72\x0d\x85\x65\xa9\x7b\x85\x83\x75\xf5\x4d\x79\xa6\x5c\x63\xae\x0c\xef\xc0\x77\x64\x7d\x6e\x45\x4d\x83\x36\xcf\x94\x67\xcc\x93\x60\x03\x28\x24\xf7\xa8\xb5\x3e\xb7\xb2\x66\xbf\xb6\x3b\xa8\xeb\x18\x6f\xdd\x93\x90\x1f\x2f\xc4\x27\xa4\x26\xef\x91\xb9\x4b\x06\x54\x29\xf8\x19\xfe\x24\x61\x20\x05\x3f\xe3\x9f\xa4\xce\x7e\xc5\x76\x91\x87\xe5\xf0\x6d\xa1\xa5\x30\xdb\x9a\xe7\x0d\x8b\x70\x39\x89\xcf\x68\xce\xe6\x87\x8b\x71\x75\x7a\x56\x7a\x76\xba\xc5\x1b\x37\x83\x4a\x66\xe5\x9a\x73\x73\xb5\xb9\xe6\x1c\x53\x8e\x64\xeb\xb6\xd5\xf1\x7b\x0a\x4b\xd2\xca\x84\xb2\x92\xbc\xc2\x42\x19\x0e\x51\xea\x79\x5c\x83\x4b\x61\x0d\x69\xbf\xa3\xc3\xe9\xfc\x14\xaa\xfc\x5e\xc7\x2c\x63\xa6\x31\xc3\x94\xe1\xdd\xdf\x53\xdd\x44\xcd\xef\x80\xb3\x70\x0d\x72\xb1\x82\xc4\x5e\x6a\x10\x9f\x6e\xca\x30\x66\x18\xf1\x11\x3c\xf6\x52\xa6\x50\x73\xf1\x43\xb2\x7b\x82\x3f\x9f\x96\x97\x9a\x93\x9c\x9d\x91\xe7\x05\xdf\x28\x2f\xd0\xe8\xb0\x32\x50\xd1\xf0\xb0\x9b\x86\xd1\x30\x11\xae\xe3\x67\xf3\xe6\x90\xea\x0f\x9e\xa6\x1c\x63\x8e\x31\x07\x26\xc1\x0c\x2f\x5c\x42\xe3\x78\xdb\x47\x3c\x8c\x7f\x9f\xc4\x6a\x1a\xa7\xc0\x0c\x32\xb7\x20\xbb\xb0\xc8\x79\xd3\x8e\xdb\x4c\xc0\xf2\x4f\x79\x88\xba\x0f\x61\x68\xc0\x73\xf8\x31\x8e\x84\xd1\x64\x8e\x82\x3c\xb7\xa1\x35\xc7\x92\x6d\xc9\xb6\xc0\x32\x5c\xeb\x85\x1b\xa6\x92\x50\x4e\xdb\xb9\x2a\x5e\x9d\xa4\xbe\x83\xdb\x21\xc2\xe6\x02\xe1\xa4\xfa\x8a\x6a\xe0\xe1\x43\xfc\x02\xcf\xe2\x35\xec\x80\x5b\x64\x40\x36\x8f\x3a\x1c\x48\x42\x2b\xad\xc4\xaa\x59\xfc\x09\x7f\x72\x2c\xa5\xb8\x2b\x3a\x5e\xe9\xa5\xfc\x83\x34\x5b\x4c\x66\x29\x3b\x1d\xbd\xba\xdc\xc8\x3f\x6c\x32\xaf\x12\xaa\x3b\x7e\x08\x5f\x28\x73\x94\x4d\x0e\xab\x73\x4d\xde\x10\xa8\xf6\x26\x4d\x66\xb3\x49\x6b\xc8\xde\x93\x9b\x22\xe9\x50\x0f\x7d\x79\x1c\xb7\x18\xc6\xc1\x61\x52\x87\xbb\xdc\xb0\x85\xc6\x71\xd0\x42\xea\xdc\x1e\x7a\xde\xa7\xd0\x13\xa3\x48\x78\x0b\xce\xf1\xe9\xc6\x74\x63\x7a\xe6\x5b\xf7\xbd\x80\x57\x14\x98\x82\x67\x49\x53\xba\x31\x3d\x4d\x9b\x6e\xc9\xb0\xa4\x4b\xee\x20\xb3\x3a\xb7\x4f\x60\xba\xab\xed\x17\xb7\xae\x26\x1a\xa7\x81\x84\x43\x61\xba\x64\xab\xa2\x60\x3a\x48\x30\x14\xa6\xc9\x3a\xf2\x3c\x8d\xcf\xd1\x4e\x76\xc5\x52\x38\x1d\x25\x1c\x86\x53\x65\x9d\xdb\x27\x5d\xe9\x7c\x57\x11\xb5\x70\xd5\x85\x0f\x64\xc5\x40\x7f\x70\xf6\xfc\x07\x92\x12\x4d\x7d\x70\x76\xc5\x42\x59\x9d\x4c\xbb\x17\x45\x7e\xcb\xda\x27\xea\xc8\x1d\x7c\xb1\x7e\x69\xfe\x52\x41\x7d\x13\x7f\xc6\xc7\xea\x9b\x8b\xf3\x17\x97\x2c\x91\x61\x8c\x32\x09\x1e\xc1\xf7\xca\x9b\xf0\x06\x03\xd5\xf8\x22\xaf\x16\xe2\x2b\xea\x20\x75\x28\x0e\x53\x8b\x4e\x2c\xb8\xf8\xce\xfb\x6b\x61\xa8\xb2\x57\x19\xa6\x8c\x50\xca\x60\xc4\x9a\x6b\xfa\x0b\x0b\x4e\x30\x5d\xbb\x75\xf6\x0f\xf9\xeb\xbb\x6f\xc4\x7e\x9c\x0c\xaf\x2b\x02\x7c\x08\x37\x14\x2d\xf8\x26\x7f\x1c\xf3\x51\xc8\x75\x35\x08\x47\xab\x8c\xca\xe2\xab\xea\x2e\xc6\x7e\x7e\x09\xbf\x13\xfa\x05\x40\xdf\x75\xd0\xe7\xc2\xa3\xc3\x4f\x4a\x9f\x61\x1d\x0e\xc1\x08\x8c\xc4\x97\xb1\xfe\xb7\xb2\xa7\xad\xdf\x5c\x82\xde\xeb\xe0\x1f\x01\xd0\x77\x27\xd3\x33\x94\x8d\x8b\x07\xd1\x1e\x00\xa2\x87\x59\xc7\x10\x5c\x88\x8e\x0e\xd0\xb9\x45\xf3\x5f\xe2\x40\x9c\x76\x1a\x27\x08\x28\xa0\xbc\x6b\x32\x92\xf2\x5d\x24\x51\xde\x8f\x82\x80\x13\x70\xda\xda\x89\x38\x50\xe6\x5a\x71\x94\x0e\x19\x32\x97\xfa\xf6\x7e\x55\xcb\x97\x32\x17\x72\x05\xfa\x81\x67\x33\x48\x02\x0c\x80\x97\xd6\xbc\xfc\xab\xfc\xeb\xaf\xf0\x52\x3b\x0c\x10\x40\x02\xcf\xed\x4b\xa1\x9f\xcc\xb5\x06\x7c\xf5\x45\xf4\x8f\x02\x17\xd2\x25\xc1\x11\x1e\x45\xec\xb3\x6d\x1a\x32\x72\x27\x32\xd8\xe7\x30\x8a\x02\x2e\x45\xcf\x15\xd3\xd1\x4f\xe6\x5a\xa1\xaf\x3d\x8f\x3c\x0f\x6e\xe0\xdd\x00\xff\x10\xc0\x07\x5e\xf2\x1f\xfe\x9b\xfc\xcb\x6f\xf0\xd2\x49\xf0\x11\xe0\x1f\xe0\x1d\xb2\x02\xdc\x64\xe8\xdb\x9d\x47\xde\x44\x3f\xf4\x3c\x8f\x4b\x05\x2e\xe4\x58\x33\xbf\xc9\x82\x5e\xd9\xc8\x6f\x43\x72\x86\xf7\xa7\x48\x22\x7f\x10\xbd\x04\x9c\x88\xde\x9b\x17\xe0\x08\x19\x28\xfb\x54\xf2\xc4\xef\xd0\xbb\x06\xdc\x04\x18\x0e\x2f\xae\xf6\x79\x2e\xff\xfa\x1b\x50\x67\x61\x50\xb6\xa3\x54\x5e\x83\x8d\x3a\xb7\x1f\xa3\x5c\x60\x37\x6c\x81\xb5\xdf\xff\xf5\x7d\x07\x0a\x5c\x75\xe4\x97\x30\x81\x0f\x09\x0f\x0f\x91\x5e\xa5\x42\xc2\x6b\x1a\x64\xdb\x6e\x7a\x7f\x4d\x4d\x83\xf4\x23\xd5\x50\x13\xbe\x4b\xc6\xd6\xae\xdd\x30\x57\x54\xf6\xc3\x42\x16\x4f\xa9\xfb\x1d\xf0\xd4\x1e\x78\x2a\xcc\x15\xa1\x1b\x16\xb2\x3a\x32\x13\x03\x79\x98\x8f\x1c\x8c\xc5\xd9\x27\xa5\xc2\x63\x39\x6d\x6d\x5a\xb8\x84\x26\x30\xe1\x25\xcc\xc5\x10\x9c\x8a\x99\x8b\xa4\x13\x2b\xe7\xd5\xce\x11\x70\x04\xfe\x03\xff\x81\x23\xc2\xb2\x43\xf3\xc3\x64\xf4\x99\xf3\x1a\x0e\xc0\x51\x5a\x0c\x85\x39\x38\x1b\x76\x4b\x3a\xb7\x2f\x29\xd8\x0d\x73\x60\x36\x84\xca\xee\x99\x91\x90\x0f\xf4\x9b\x30\x74\x1b\xd0\xbb\x7f\xd8\x01\x74\xc4\x97\xbb\x81\xde\x0e\xba\x99\x40\x83\x5b\xcb\xb9\x67\xc0\xb6\xb4\x3f\xf3\x30\x3f\x3b\xd9\xba\x15\xa8\x76\xa0\xeb\x61\x28\x72\x40\xb7\x03\x35\x0e\xd6\xce\x04\xaa\x06\x06\x61\x6f\x47\xdc\x81\xda\xda\x7a\xf2\x19\xd7\x74\x61\xd8\x8a\xc5\xac\x9b\xce\x9e\x4b\xdb\x2c\xf8\xbd\xad\x1c\xbe\x27\x75\x64\x08\x3d\x44\x67\xff\x94\xef\x1a\x87\xed\x5d\xc3\xa0\x9d\xb4\x8f\xd1\x91\xe3\xe9\x67\x6e\x3a\xfb\x07\xb0\x56\x47\x8e\xa7\x74\xe8\xad\x66\xf0\xf0\x6f\x71\x87\x1b\x37\xdc\x30\x98\x70\x42\xff\xe3\xc2\x7d\x36\x95\x20\xea\x77\xf1\xcf\xd7\x96\x1d\x1a\xd0\x4e\x42\x9f\x91\x0e\xb0\x79\xc0\x69\x12\x7a\xff\x17\xd8\xe7\x55\xfe\xf7\x35\x65\xcd\x03\x4f\x93\x30\x69\x2d\x5f\xb6\xfd\x79\x7b\xfc\x21\xb2\xb1\xd4\x01\x9d\x8e\x6f\x26\x9b\xfe\x03\x35\x96\xf0\x65\x3b\x9c\x50\x77\xb3\xce\x6d\x0f\x28\x22\x8c\x6d\x79\x4f\x84\xb1\x70\x57\xe4\x08\xe6\xde\x43\x67\x54\x87\x33\xf1\x0a\x7f\xb7\x05\x69\xa4\x5b\x29\x48\x05\xda\x41\xd2\xc2\x23\x45\x71\xef\x6c\x58\xf5\xc9\x56\xa0\x68\xd0\x88\x8e\x6f\xbf\x49\x7c\x2b\x44\x8b\x5b\xef\x52\x18\x05\x47\x44\xdc\xfb\x7f\x5e\xd4\x1f\xde\xe4\x61\x2a\xf8\x80\x0f\x4c\x05\x3f\xf4\x81\xfe\x38\x15\xfd\xb0\x3f\xf6\x47\x3f\x9c\x0a\xfd\xd1\x07\xfc\x64\x9c\xa0\xf4\xe3\xbf\xfe\xb5\xfa\x93\xab\xc7\xa3\x22\x2f\x48\x41\x4b\xc8\x4c\xaa\x39\x62\x7e\xd1\x16\x21\x70\x7a\xda\x3a\x79\x2a\x54\x83\x0b\x4e\xd0\xfa\x22\x11\x35\x7b\xc1\xaa\xc2\x83\x2b\xa4\xa6\x0f\xc9\x6c\x6a\x43\xd5\xb5\xe4\xe3\x42\xe3\xfd\x9c\x53\xf2\xb7\x58\x81\xae\xf0\x8a\x73\xf2\xd9\x5f\x47\x69\x5d\xcc\x70\x5b\x47\xc6\xc3\x6d\x57\xdb\xef\x8a\x85\xc7\x61\xd8\x07\xfb\xe0\x70\x47\x08\x7d\x60\x18\x0c\x87\xff\x84\x0e\xbc\x64\xfb\xdd\xc2\xe3\x70\x27\xd1\x30\x47\x08\x7d\x60\x38\x0c\x83\xff\x84\x0e\xbc\x04\xb7\x6d\xe7\xf8\xf7\x57\x9f\x59\x24\xa9\x6f\x53\x8b\x57\xad\x5e\x2c\xe3\x1b\x5d\xe9\xf0\x06\xfd\xfe\xaa\x33\x8b\x1d\xb8\x45\xab\x57\x2f\x96\x75\xf6\xb3\xf4\xe2\x33\xab\xaf\x49\x3a\x7a\x28\x75\xed\xcc\x99\xf7\x1d\xb3\x8a\x63\xd0\x1b\x7b\xc3\xab\xca\x32\x20\xbe\x83\x01\xf0\xda\xef\x1e\x66\xf0\xd3\x91\x9e\xcf\xe1\x32\x4c\xe4\x92\x74\x64\x91\x7d\x01\x6f\xa6\x4d\x16\x8b\xc9\xac\x85\x12\x5c\xcf\x07\x6c\x4e\xdf\x13\x20\x67\x57\x5b\xaa\xab\xb5\x90\x8f\xcb\x60\x11\xe6\xa3\x3b\x7a\xac\x1e\x35\x51\x4a\x4a\x4c\x8c\x8f\xd1\x46\xed\x8d\xab\x94\xf6\x3f\x02\x16\xde\x12\x60\x2b\x8c\xc3\x57\x71\xbb\xbc\x29\x76\xf3\x16\x6d\x48\x6d\x78\x83\x74\xe4\x72\xeb\x65\x01\x3c\x9e\x8c\x40\x0e\xc5\x97\x7d\x51\x2b\xab\x4b\xf1\x45\xdb\x7e\xf5\x3b\x81\xbb\x80\xf5\x18\x88\xeb\x70\x3f\xee\x87\x48\x5c\x02\x95\x30\x0d\x96\xde\x07\x0a\x5e\x92\xf7\xed\x3d\xde\x52\xa7\xad\x88\xdb\x1b\x1d\xbd\x75\x73\x62\x8c\x34\x09\x7b\xe1\xa8\xa5\xa8\x13\x70\x13\xfa\x02\x0f\x3b\x64\x2e\x09\x36\xc1\x10\xe0\x61\x9d\xa4\x54\x3c\xe9\x3a\xa6\xec\x17\x60\x33\x4c\x82\x51\xb0\x15\x56\xe1\x78\x18\x8c\xcb\x65\x77\xf0\x12\x75\x6e\x17\x6d\x9d\xfc\x3d\x11\x35\x14\x6c\x16\x15\x17\x96\xae\x61\xb9\x15\x3f\x88\xce\x13\x47\xd2\x44\x09\x35\x30\x44\x0c\xde\x26\xab\x9d\xeb\x45\xf0\x12\x8d\xa2\xad\x93\x8f\x4d\x8d\x4b\x4a\x92\xd0\x8a\x56\x32\x29\x29\x0e\x0e\x88\x4a\x3f\x91\x4c\x2a\x4e\xdd\x5b\xae\xf5\x13\xcb\xf7\xa6\x26\x15\x4b\xdc\x0a\x18\x82\x2f\x93\x70\x9a\x76\xc8\x38\x4d\xc3\x10\x78\x59\xf1\x10\xf3\xcb\x05\x98\x2d\xca\x5d\x9a\xf5\x22\x34\xda\xac\x60\x10\x75\x0c\xe1\x0a\xdb\x6c\x56\x1e\xee\x50\x70\xb1\x6b\x24\x09\x4b\x7c\x78\xfc\x97\xad\x84\xb4\x2d\xa4\xba\xee\x80\x86\xc7\xa7\x14\xb4\x29\x1a\x12\xca\x28\x65\xa7\x0e\xb7\xf2\x70\xd1\x36\x92\x84\x3b\x94\x0e\x93\x40\xc3\xc3\x7a\x47\x5a\x03\x05\xeb\x55\x0d\x09\x83\x3d\x71\x7d\x0f\x2d\xb4\xa9\x1a\xd2\xb9\x17\x72\x79\x52\xb4\x35\x4a\xd0\xa1\x81\x8a\x8a\x4e\x8e\x4d\x92\x55\x8d\x6a\x8d\x0e\xcb\xda\x56\x15\xee\x6d\xd7\x77\x5b\xc9\xc4\xe2\xf2\xd4\x7d\xc2\xbe\xf2\xfc\x92\x62\xd9\xae\xb7\x5b\xab\x6a\xb2\x0e\x47\xd7\x7a\xf7\x9c\xd0\xe2\x82\x2e\x30\x24\x00\x86\xa0\x0b\xb8\x98\x1d\x5f\x27\x04\x19\xac\x19\x34\x1e\x70\xc6\x11\xdc\x15\xcd\xa0\xe1\x4c\x57\xb8\xfc\x2b\x3a\x9a\x8b\xe6\xb9\x01\x57\xc6\x8f\x1f\xff\x60\x8f\xe8\xfd\xff\x23\xe0\xf2\x9d\xc4\xa3\x47\x2b\x2e\x6c\x5d\xe8\x31\x73\x5d\x9d\x77\xbb\x48\x72\x73\xaf\x3c\x18\x4f\x82\xc4\x72\xf9\x57\x1e\x3c\x78\x30\xfe\xbb\xef\x82\x44\x07\xb1\x79\xba\xce\x76\xef\x08\xdf\x2e\xf6\xa4\xfe\xb7\xa4\xf1\x13\xc6\xdf\xdf\x23\x7a\x47\xc7\x38\xca\x1c\xb6\xc0\xc7\x35\x87\xe3\xce\x6c\x2a\xf5\xc6\x19\x57\x49\xb8\x40\x73\xe6\xd9\xa8\xa1\x38\xd3\x29\xd0\x64\xb2\x68\xed\x79\x6e\xdc\x3c\x08\x35\x34\x97\x36\x1d\x35\x78\x81\xc2\x19\x4b\x36\x25\xc4\xad\xae\xd9\xe6\x0d\x5b\xf0\x63\x12\x4f\xd3\xf3\xe6\x39\x45\x72\xa6\x2b\x0e\xe1\x4e\x0b\x49\xce\x3c\xbd\xc7\x4a\x46\x19\xa2\x73\x0b\xe2\x39\xf3\x20\x70\xc8\x3d\x00\x1a\xc5\xda\xa3\x85\xe6\xcc\xd3\x15\x17\x96\x52\x35\xa0\x51\x35\xa8\x21\xdd\x83\x44\x17\xe8\x7c\xa2\xdc\xfc\xc9\x55\xe9\xf4\x44\x0d\xbc\xc5\xce\x7b\x8c\x1a\x12\x7c\x55\x3d\x3f\x42\xd1\x3f\x76\xb4\xb5\x0e\xf2\xa0\x42\xf1\xa6\x64\x53\xb2\x31\x39\x2d\x25\x3d\x3b\x23\x89\x99\xbe\x3b\x49\x3f\x1a\xf9\x16\x78\x71\x83\x90\x44\x6d\x68\xc1\x17\x91\x17\x46\x27\x5d\xba\xb9\x5b\xce\x28\x4e\xcf\x4c\x2b\x30\x5a\x4d\x56\x93\xd5\xb9\x4d\x6c\x16\x93\x6f\xbd\x65\x29\x13\xae\xbc\x97\x62\xb8\x2c\xe7\x1b\xf3\xcd\xf9\xf9\xf9\xe6\xfc\xde\x83\x8a\x2e\xbf\x57\x70\x45\x28\xbb\x65\x4a\xb5\xca\x59\x46\x8b\xd1\x62\x64\x14\xdf\x6e\x57\x1e\x66\x06\x42\x35\xce\xfa\x51\xba\x0f\x11\x24\xee\xa0\xf6\x5d\xc8\x7f\x2f\xfd\x3d\xe6\x68\x01\x8c\x3a\x78\x59\xfb\x3e\xbe\x75\x70\x53\x81\x14\x79\x7b\x25\x50\x2b\xde\x67\x6a\xa2\x42\x4b\x03\x17\xad\x5e\xb0\x68\xd1\xea\xeb\x8b\x84\xc0\xd0\x84\xf0\x28\x79\xc5\xe2\x95\x48\x45\xfa\x31\x9b\x52\xf0\xad\x9d\x8b\xb5\xcb\x60\xd4\xce\xa3\x29\x92\x69\x8f\xc9\x60\xd0\xfa\x17\xac\x2f\xdd\x28\xe1\x0e\xea\x3b\x0c\x21\x71\xe1\xe8\x9d\xd8\x80\x73\x20\x5e\xec\x59\xf8\x43\x0e\xb8\xc7\xec\x51\x11\x35\xe0\x23\xf6\x2c\xfe\xed\x37\x70\x3b\x0d\x3a\xa6\x4b\xc9\xe4\x23\xe0\x1d\x1c\x06\xbe\xb8\xec\xf0\x90\x8a\x91\x71\x13\x37\x23\x0d\x7e\x5e\x30\x0b\x2e\xb3\x2f\x53\xb1\xb1\xa9\x49\x49\x32\x52\x48\x91\xdc\x7e\xc3\x8c\xe7\x7f\xaf\xd4\xe5\x51\x81\x41\x11\x81\xe9\xf2\xa6\xd4\xa6\x6d\x47\x85\xbf\xd6\xec\x90\xa6\x54\x2b\xc5\x1d\x33\xb4\xac\x45\xea\x07\x0c\x17\x50\x43\xed\x61\x3b\x28\xf0\xf8\x75\xe3\xcc\xcf\xe5\xb0\x75\x64\xf9\xea\x15\x85\xcb\x85\xff\xb9\x7c\xf7\x89\x19\xac\x54\xcb\xfe\xc6\x16\x98\xfe\x05\x8c\x06\x8f\xe7\xf2\x4d\x1f\x92\xdb\x6a\x18\x3c\x6a\x11\x8a\x7b\xf1\x15\x86\xdb\x69\xa8\xc6\x1d\x30\x13\xa7\xc0\x8e\x04\x86\xdb\x6f\x80\x83\x31\x10\x03\x86\x9d\xd0\xcc\xe8\x94\xcb\x2a\xc3\xff\xd7\xfa\xe5\xc1\xc6\xf4\x94\x03\x32\x0e\xc1\x46\x43\x94\x25\xac\x28\xda\x3b\xba\xb8\x2a\xa9\x5a\x80\x8f\x29\x85\x62\xc3\x45\xcf\xbf\x28\x9d\x0b\x93\x32\x98\x45\x18\x27\xc2\x3b\xac\xec\x0e\xa3\x59\x17\x33\x68\x5c\xc3\x45\x4f\xd0\xa1\x7f\x07\xbe\x75\x40\xda\x96\xb7\x23\x3c\x6d\x5b\xda\xb6\x9a\x1d\x87\xd3\x60\xe3\xd6\xab\xcb\xb2\xf7\x30\x5b\xf7\xa0\xfe\x55\x95\x15\x54\x16\xf5\x3f\x36\xef\x91\xb3\x8b\xaf\x5e\x86\x8d\x2d\x87\xf3\x6a\x0e\xa5\x1d\x4e\x3b\xbc\xa3\x66\x5b\x1a\x83\x6f\x05\xa3\xff\x3c\xd4\x69\x71\xba\xe2\xf2\x26\xfc\x00\x3f\x28\x2e\x5f\xc0\x74\x49\xd5\xd8\x35\x3c\x9c\x64\x55\x0d\xb5\x4d\x94\x55\xcd\x28\xb1\x43\xd5\xc0\xfb\xa2\xa2\xe9\xa0\x7d\xc5\x11\x36\x6b\x3c\xeb\x5e\xb5\x4a\xd4\xd1\x84\xab\x51\x54\xac\x7c\x58\x44\x69\x95\x41\x5e\x06\x6e\xf8\xb2\x1a\x43\x86\xa4\x84\x46\xef\x12\x60\x1b\x1b\x1c\x5a\xd1\x90\x22\xe1\x52\xdb\xa8\x19\xd8\x4c\xee\x4a\xdd\x1d\x15\x2c\xa8\x24\x55\x94\x54\x90\x9a\x65\xb2\xb9\xa9\x4f\xbd\x92\x8a\xf7\xa6\xed\x15\xf6\xee\xcd\x2b\x2e\x96\x6d\xae\xca\x2f\x59\x59\x05\xf9\xc5\x25\xde\xb0\x49\xf1\xe3\x0f\xb3\x48\x9f\x1b\x70\xf1\x4d\x59\x79\x93\x02\x46\xd9\x4c\xee\xcf\xaf\xab\x3c\x20\x34\xd6\x45\x87\x14\xc8\xb0\xa2\x6b\x1a\xf0\xca\xb4\xfc\xfa\xea\xf2\x86\x6c\xef\xba\xac\xfa\x84\xa2\x70\x70\xc5\xdd\x5e\x0a\x49\x5d\xfc\xe2\xdc\x73\xa0\xb5\xee\x6a\x52\xcf\x0a\xb2\xc6\x45\xb1\x42\x14\x9b\xce\xda\xf5\x3c\xfc\x88\xed\x50\x8b\xbf\x6e\x96\xb0\x26\x08\x03\x31\x2c\x02\xeb\x42\xf1\x53\x88\xc7\x6a\xb8\xbc\x83\xc1\x12\x0c\xdf\xc5\x42\x38\x86\x53\x29\x2c\x84\x43\x38\x3d\x5d\xc4\x70\x28\xa1\x3a\xc5\x6e\xab\xe7\x0c\x76\x35\x0b\xcb\x44\xc9\xfd\xb2\xa8\x7a\xa8\x1e\xe4\xbd\x61\xd8\xaf\x1d\x75\xc2\x4d\x11\x74\x6b\xa0\xdf\xa4\x27\xb2\xe2\xa1\x70\x24\x96\x4d\x67\x15\xdf\x68\xb6\x5b\xa3\xb3\x1b\x46\xb1\x6a\x52\x90\x98\xce\x82\xc6\xc5\xdc\xca\x6a\xc6\xdb\x6e\xea\xdc\xae\xf0\xcf\x3f\xb8\xff\xb8\x0d\x18\xa6\xaa\x20\xae\x3a\x42\x58\x48\x45\x1a\x52\x92\xd2\x65\x94\x97\xa0\x38\x1c\x5f\x17\xf0\x75\x14\x7f\x01\x79\x89\x5c\x9c\x6e\x28\x48\x14\x66\x52\x11\x71\x11\x91\x05\x72\x1b\x32\xf7\x47\x3c\x5f\xc8\xe0\xd2\x91\xe8\x85\x2b\x30\x52\x0b\xd3\xd9\x75\x2c\x78\x51\x9d\x22\x44\xa2\x17\xac\xc0\xa5\x3f\x49\x98\xdf\xbd\x62\x14\xeb\xd4\xa9\xb2\x8a\x15\xf2\x58\x57\xbb\x55\x47\x3e\xfc\x5a\x44\xea\x7b\x1c\x7e\x0e\xc7\x46\x7b\x63\x4d\xa0\x23\xf3\x91\x8e\xcc\x7f\x02\x09\x58\x0d\x97\x76\x30\x2b\xc4\x2a\x27\xd7\x04\x56\xd1\x80\x46\xd1\x80\x55\x74\xb2\x91\x77\x87\x61\xbf\x33\x8e\x11\x54\x87\xfd\x56\x4f\x1e\x26\x2f\xbd\xfc\xdd\xd3\xe2\x12\x53\x55\x62\x91\xf7\xea\x93\x89\x45\x51\xa6\xa4\x44\xef\x37\x46\xf6\xff\x93\x04\xef\xed\x22\xb6\xbd\xc1\x62\xdb\x74\x16\xb4\x34\xb8\xa2\xdb\x00\xa4\x93\x12\x2d\x91\x25\x06\xef\x33\xfe\x25\x86\x4a\x4b\x71\x89\xf7\xaf\xe0\x7a\x61\x39\x39\x79\xd8\x6a\xec\x87\x3a\x47\x16\x56\x88\x55\x66\xd0\xe8\xdc\xae\x45\x7d\x0e\x1a\x0f\xc5\x0a\x1b\x44\xee\x37\x1d\xd5\x6d\x4f\xe1\x23\x60\x3f\xee\x86\x08\x6c\xa8\x47\x9f\x52\x7c\x69\x4b\xff\xe9\xfd\x6f\xe2\x4b\xad\xe8\x93\x80\x0d\xbb\x71\x37\x46\x44\xe0\xfe\xff\x77\xfd\x29\x56\x0c\x9f\xfe\x3f\xea\x11\x2e\x1f\x82\x78\xa8\x0e\x85\x4f\x99\x6e\x0f\x54\x61\xac\xc8\xfd\x8c\xee\xab\xb0\xd7\xa4\x89\x12\x76\xa2\xc0\x73\xbf\xc1\x32\x51\xe6\x7e\x81\x06\xf6\xb3\xc8\xad\x37\xe0\x37\xf1\x2a\x8a\x8f\x07\x49\x5b\xe7\x4e\x8d\x9c\x24\x28\x9d\xaa\x86\x57\xad\x50\x42\xfd\x54\xf8\x75\xf3\xed\x73\xb7\x57\x7e\xbd\xfd\xa7\x3d\x4c\x07\xf4\xe5\x27\x4d\xad\x6a\x99\x2b\x73\xbf\x3d\xfe\xed\x2a\x5c\x14\x6f\x7c\x06\xab\x44\x18\x86\x05\xc0\x39\xea\xbe\xe7\x55\x29\x8d\x87\x05\x38\x45\x03\x79\x3d\x1b\xcf\x69\x40\xc3\x7d\x75\x71\x31\x6b\x7f\xfe\xb5\xf8\xda\x2d\x24\x4f\x63\xdf\x3c\xef\x88\xeb\x81\x57\x36\x9d\x83\x7c\x28\xf0\x82\x7e\xec\x53\x96\xe4\x2e\x5c\x44\xda\x59\x6f\x6f\x44\x63\x7d\x20\x06\x61\x74\x0c\x36\x44\xe2\x5d\xc8\xc2\x3a\xf8\x24\xee\x6b\xcc\x82\x3c\x9c\x02\x47\x8f\x41\x66\x33\xac\x82\x65\xc7\x21\x03\xfa\x8b\xdc\x57\x17\xbf\x64\x55\xab\xea\xcb\x3b\x04\x84\xe3\x04\x5c\x80\x3b\x77\x48\xc6\x0a\x63\x45\xa5\x16\xc2\x61\x02\x2c\x80\x9d\x87\xa4\xac\xe8\xac\xe8\x28\x2d\xf7\xd5\xc5\x6e\x8d\x67\xae\x08\xc5\x2c\xcc\x85\xd1\xe8\x82\xa3\x3f\x95\xb0\x7a\x15\xae\xc7\x24\x3c\xac\x8d\xb2\x44\x65\x45\x4b\x18\xdc\x88\x93\x61\x11\x44\x6a\xed\xfa\xae\x4e\x1e\xe7\xe2\x68\x70\x81\xd1\x33\x64\xa8\x3e\x0b\xeb\x21\x09\x0e\x6b\x2b\x4d\x95\xc6\x0a\x09\x82\x83\x60\x32\x2e\xc2\x48\xed\x6a\x56\x72\x87\xc6\x20\x11\x78\xe0\xb0\x2f\xf4\xb5\x6b\x80\x03\x1e\x7c\xc4\xe5\x62\xcf\x5d\x9e\xef\x9d\x25\xc1\x3d\x78\x78\xec\x7f\x37\x35\x16\x7b\x6d\x5d\x38\x4a\x46\xea\x0e\x0e\x6c\xc5\x91\xe1\x68\x09\xc0\x55\xb8\x66\x3b\x66\xad\xc1\xaf\x20\x05\xdb\xe0\xe3\x6d\xcc\x3a\x96\xe2\xce\x3f\x04\x2f\xfa\xa7\xc2\xaf\x0f\xdd\x3e\xc7\x70\x0f\x1e\x02\x35\x05\x06\x6e\x81\x57\x6a\x20\xad\x05\xde\x75\x94\x46\x6a\x23\xbc\xbd\x0a\xc6\x0d\x83\x7f\xfc\x5d\xaa\xdc\xb9\x87\x5d\xd6\xee\x27\x30\x56\xfc\xbb\xea\xbb\xac\xf0\x11\x0f\x0d\xec\xed\xc8\xad\x1d\xf0\x9b\xf8\x3e\x8a\x3f\x0f\x92\xb6\xce\xf3\x8b\x9c\x24\x38\x9b\xc3\x83\x87\xf6\x4e\x55\xcf\x4f\xf2\xab\x6a\x99\x27\xff\xfc\xdb\xfb\x70\x51\xec\xb8\x0d\xab\xc4\xcb\x22\x6e\xc7\xed\xf0\x8b\x08\x03\x59\xf0\x43\xbf\xc9\x93\xff\x2f\x4e\xe1\xee\x3d\xf0\xc1\xfe\xd0\x28\x16\x17\x9b\x2b\x93\x4a\xbc\xd1\xf1\x67\x62\x3b\xec\xf8\x3f\x1d\x45\x26\xeb\x74\x14\x4e\x77\x65\xd3\xd8\xfb\xf2\xe0\x05\xbe\x8e\xa6\xeb\x0b\x13\xa8\x1f\x46\xfd\x37\x11\xeb\x60\xed\x1e\xd1\x1b\xd7\xe1\x5a\x28\x11\x7f\xf8\x81\xc4\x09\xe8\xbb\x8b\x05\x5f\xf4\xa2\xf0\xf2\x0e\x8c\xc7\xea\x3a\xfc\xb4\x1a\xeb\x20\x10\xc3\xa0\x26\x88\x81\x5f\x37\x43\x3b\xd4\xc2\x8f\x5a\x38\x8b\xe1\x90\x89\x6d\x07\xa5\x79\xdd\xb9\xa3\x9c\x7b\x27\x3b\xfa\xfa\x23\x56\x47\x07\xd9\x5c\x78\x6c\x87\xf6\x9e\xb7\xa8\xbd\xd7\xad\x83\x1f\x45\x6f\x58\x80\x0b\x48\x6c\x87\x70\x58\x20\x62\x38\x7a\xd1\x3b\xe0\x32\x56\x43\x3c\x7e\x1a\x8a\x75\x11\x18\x86\x81\x41\x58\xc3\xe0\xaf\x9b\xa1\x16\xdb\xe1\x47\x01\xce\x42\x26\x84\x43\xdb\x41\x19\xbc\xfe\x76\xa3\xed\x34\x2e\xc0\x05\x0e\x69\xa7\xd6\x15\x27\x56\x99\x1d\x3e\xbe\x1d\xda\x61\x8c\xe8\xad\xb3\xdf\x52\xf7\x38\xf2\xae\x23\x0d\x7f\xf9\xc8\x10\x87\xa7\x06\x33\x0b\xd3\x59\x55\x99\xce\x2a\x0a\xdd\x29\xaa\x9d\xaa\xde\x41\x65\x86\x2b\xa2\xab\xdd\xaa\x74\xf2\xab\x59\x74\xde\x9e\x03\xf3\x0c\x56\x02\x8d\x27\x38\x0f\x56\xc7\x9b\x37\x45\xc9\xbd\xca\xbd\xca\xdd\xb6\x08\x4a\x20\x08\xe2\x5d\x74\x64\x3f\x48\x71\xd5\x91\x07\x61\x38\xab\xb3\x37\x51\x6b\x02\x02\xd6\xc8\x3a\x7b\x13\xbd\xe6\x48\x40\xbb\x64\x0b\xbb\xcc\x2a\x02\xd5\x7e\xe4\x48\xbb\xac\x23\x97\xd3\xed\x01\x47\xd6\x48\xee\x6a\x12\x3c\x82\x09\xb6\x7f\x3b\xef\x7c\x2f\xb0\xfd\x0e\xf1\xae\xf6\x29\x6e\xf8\xd2\x05\x5c\x06\x03\xd7\x4b\xa6\xdc\x7c\x63\xae\x70\xa8\xe2\x87\x7a\xb9\x69\xd2\x47\xc0\x6b\xa1\x0a\xd6\xc3\x52\x28\x87\x28\x98\x84\x3c\xee\xc1\x19\xd3\xf1\x21\xc6\x8e\x9f\x7e\xed\x91\x04\x1e\xdf\x80\x3b\x78\x6a\xef\xad\xeb\x18\x87\xd4\x0c\xd4\xbc\xbc\x2c\x7f\x41\xdd\x0a\x69\x2d\xae\x1a\x89\x67\x70\xbd\x76\xbe\x75\x41\xde\x7c\xc9\xba\xa7\x34\x17\x26\x41\x6c\xda\xa9\x3b\xf0\x9e\xf7\xe4\xb6\x3f\x36\x7c\x25\xc0\x9f\xf0\x3a\x3c\x81\x0e\xf8\x0a\x8f\x42\x20\x7e\x8c\x3f\xe3\xf7\x18\xad\x92\xb2\xfb\x48\xf0\x30\x44\xea\x48\x06\x3c\x3c\xf6\x83\x87\xce\xed\x47\xf0\xe0\xa2\xed\x41\xca\xfb\xfc\xee\x95\xc3\x83\x84\x94\xd4\xec\x9c\x54\x79\xd9\xfe\x55\x07\xd6\x9e\x0c\x68\xd9\xf0\x5e\x44\x3b\x93\x99\x6b\xcc\xcd\xad\xf9\xe4\xc4\x11\x6d\xe1\x0a\xd0\xa5\x96\x4b\xf5\x7b\xd2\x0b\x42\x12\x93\xb2\x93\x84\xc8\xb8\x94\x84\x78\x79\xf5\xba\xb0\x35\xc6\x39\x4c\x0a\x6d\x9a\xd9\x3c\xf3\xc8\xb2\x47\xc8\x7d\x8b\xae\x30\x70\x2e\x13\x75\xe2\xe9\x86\x33\xc2\x95\x1f\x5b\x2e\xd7\xc8\xd6\x9a\x82\xfd\x75\xda\x1c\x73\x9e\x31\x57\x2a\x4e\xc5\x71\x0f\x63\x05\xee\x14\xfa\xab\x0d\x3c\xba\x63\x9f\xd6\x8f\x07\xcb\x98\xfe\xd6\x3d\x48\x20\x27\xff\xb9\x01\x78\xf0\xd2\xc2\x53\x38\x0c\x87\xe1\xa9\x23\xc4\xc3\xf8\x14\x9f\xa2\x33\x94\x74\xe4\x16\x37\xd5\x17\xbf\xc7\xef\x55\x5f\x14\x5b\x51\xb8\x89\x2f\xc8\xa8\x53\x87\x91\x5c\xb4\xf2\x06\x68\x49\xee\xd4\x02\x70\x03\x8f\x9d\xc0\x09\x8a\x2f\x7c\x0f\xdf\x2b\xbe\x8a\x2f\x7e\x0f\xdf\xab\xbe\xb2\x7b\x95\xf9\xf1\x88\xbf\x9d\x68\x0b\xab\xa3\x7c\x1e\x73\x49\x06\x67\x34\x99\xed\xb6\x2a\x56\x48\x66\x95\x36\x55\xcf\x97\xb3\x3a\xdb\x43\xbb\xfe\xbf\xa2\x8a\xd5\xad\x9c\x7d\xdc\xd5\xc9\xeb\x6c\x84\xaa\xa1\xb8\x0b\x86\x38\x91\xb2\x6b\xdc\x9c\xd1\xff\x09\xf6\xac\x9e\xb5\x3d\x06\xeb\xe3\xc7\x2e\xe1\x22\x58\x5d\x6d\x7a\x9b\x86\xaf\x66\x37\x88\xb2\x5d\x8f\x1a\x1e\x9e\x43\x1a\x8b\x7a\x6a\xa6\x28\xe3\xf3\xbf\xcf\x47\x7e\x4e\x1d\x65\x25\xd0\x87\xf6\x9c\x71\x0b\x73\xd9\xee\x4e\x0c\xe7\x41\x4f\x43\xb7\x08\x61\x54\xc7\x52\xbf\x83\x63\x85\x38\x43\xea\x9e\x24\xd9\x6f\xd8\x2b\x6b\xd0\x43\x40\x8f\x57\xda\x6f\x0f\x03\x3f\xf1\xda\xf5\xd2\x96\xb3\x32\x24\xa3\xb5\xe7\xf5\x4b\x77\x68\x74\xcc\xb2\xe0\xbf\xeb\xbd\x8e\x9d\x3c\x64\x41\x16\x99\x97\x97\x5d\x60\xd5\x16\x64\x16\xa4\xe5\x49\xa8\x03\x1d\x99\x97\x96\x92\x9d\x22\x24\xa7\x64\xa6\xa5\xc9\x98\xe5\xf8\x38\xa8\xd2\x52\xb2\x93\x85\x94\x1e\xa4\x0e\x75\x64\x5a\x5a\x66\x4a\x8a\x36\x39\x3b\x25\x2f\x4d\x82\xac\x1e\x3a\x27\x32\x59\x9b\xd2\x83\x74\x52\xe5\xc1\x75\xd1\x5a\x90\x9d\x97\x27\x3b\x94\x81\x93\x28\xaf\x20\xd3\x2a\x14\xf4\x20\x9d\x0a\xf3\xb2\x0b\x0a\xb4\x56\xa7\x05\x5d\x49\x90\xc5\xe3\x1c\x98\x43\x86\xd5\x26\x1e\x6a\xd6\x9e\xa9\xaa\x3f\x74\x50\xca\x89\x8e\xce\x8a\xfe\x2b\xb3\x53\x46\x0c\x5b\x8b\xfd\x04\xec\x37\xec\xf4\x9d\x11\xe0\x27\x96\x95\x59\xb2\x4a\xe5\xf1\x0f\x9c\x0c\x87\xb4\xcd\x25\x87\x6a\x6b\x1d\xa3\x45\x55\x24\x58\x8f\xb0\x4a\x67\x87\x5d\x03\x56\x57\xb0\x2a\x56\xde\xa6\xaf\x16\x75\xe8\x07\x56\xb0\x2e\x66\x95\x7e\xa2\xa2\x8f\x66\x75\x68\x80\xce\x38\x56\xe7\x76\x11\xad\xbc\x0e\x0d\x8a\x86\xfa\x41\xb4\xe9\x29\x45\x23\x42\x26\x2b\xbb\x2b\x9d\xa0\x87\xed\xec\xb7\xec\x62\x16\x2a\x59\xb4\x52\x78\xa7\xcb\x4a\xaa\xee\x14\xde\xb1\x59\x49\xb4\x52\xa0\x57\xf5\x24\xea\x51\x0f\x0d\xd4\x25\xc7\x7f\x82\xfb\xa8\x57\x46\x51\x60\xeb\xea\x04\x9b\xad\x93\x54\x46\x81\x1e\xef\x53\x97\xc0\xf1\x17\x1a\xf4\xa8\xa7\xd4\xce\x2e\x2b\x8f\x04\x58\x49\x08\xa4\xdc\xab\x23\x95\x5b\xa0\x87\xfb\x8e\xe9\xb8\x3e\x9d\x05\xbd\x6b\x99\x88\x9d\x3a\xfb\x45\xbe\xff\x1b\x8f\xfe\x78\x2c\x36\xb1\xb2\xd2\xa9\x74\x3a\x6d\xb3\xa6\xb3\x94\xbb\x05\xc2\x70\x5d\xa4\x72\x0c\xc2\xe1\x3e\xeb\x61\x06\x5f\xa5\xcd\xb9\x2f\x8e\x86\x4b\x2c\x13\xbb\xda\x74\xf6\x87\xd7\x44\xc5\x57\x69\xe3\xd5\x36\xc5\x4a\x71\xe7\x95\x36\x4a\x69\xeb\x6e\xbb\x26\x82\x13\xd9\xa9\x58\x95\x4e\xca\xbd\x0a\x59\x1d\xf9\x4b\xa6\xa8\xfc\x64\x7f\xc6\x5b\x8c\xd9\x26\x8b\xa4\x16\x80\x95\xcc\x4f\x48\x28\x88\x13\x42\x92\xc2\x43\x65\x1d\x5a\xe8\xa0\xea\xad\xfb\x13\x24\x25\x00\x13\xc8\xf4\xc2\xa2\xcc\x62\xa1\xb9\xec\x40\x93\xdc\x61\xbf\xc2\xab\xbf\xd0\x4a\x13\x56\x90\xca\x4f\xb6\x6f\x79\xb5\xb5\xdb\x45\x59\x80\x21\x64\x4a\xe9\xde\xf4\x72\xe1\x50\x45\xcd\x21\x39\x53\xe7\x56\xc4\x67\x1b\xb3\x8c\x16\x49\x3d\x02\x35\x64\x4e\x4a\x72\x56\xb2\x10\x19\xb5\x27\xc6\x20\xe3\xe7\x6a\xad\xa2\xed\x72\x27\x8f\x75\x28\xa5\xb6\x2f\x72\xb4\xee\xed\xac\xd2\x87\xd7\xd9\x09\x9d\x9d\x58\xcc\x52\xee\x4a\x35\x66\xd7\x9d\x3b\xbf\xe2\x7a\x38\xec\x58\x73\xb1\xe9\xfc\x46\x20\x60\xc8\x89\xcd\x27\x77\x1c\xcf\x39\x76\xf4\xbd\x4f\x8e\x6d\xbd\x0d\xab\x8f\x7d\x75\x19\xe6\x7f\xf9\xe0\x6b\x8f\x6f\x2e\xde\x69\xbb\x03\x43\xb1\xcf\xa1\xe4\xa6\xec\x4b\x2d\x0d\x20\xb6\xc2\xc0\x36\x88\x6a\x87\xa0\x33\x70\xff\x42\xd1\x85\x9c\xc6\xe4\xe6\xaf\xae\x6d\x3c\x52\x7d\x22\xfc\x1b\xae\x6e\xd6\x6f\x5d\x43\x39\x0f\x82\x20\xfa\x2a\xa1\x28\xf3\x45\xf5\xf1\x67\x76\xa6\xed\x48\x7b\x6b\x59\x56\x20\xc3\xb9\x39\xf0\x59\x61\x27\xc2\x0f\x17\xd7\x15\x1e\x38\x50\x58\xc5\x70\xbd\xbc\x89\x5e\x3e\x3a\x72\xb2\xa7\xa1\xbe\xec\x4c\x53\xda\xa1\xb4\xbb\xcb\x32\x03\x4d\x61\xfe\xe1\xdb\x8b\x77\x17\x06\x1f\x48\xae\x62\xce\x80\x0b\x1f\x79\xa2\xe5\xee\xa5\x54\xe6\x6a\x1a\xf4\x7b\x7d\x8e\x76\xfd\x92\xe0\x85\xe5\xd2\xba\xe2\xe9\x17\x63\x5a\x18\x9d\x7d\x83\x67\xf5\x89\xad\x77\xf5\xa9\xcc\x92\x34\x74\x26\x5f\x0d\xfe\xa0\x5c\x3a\x55\xfc\xe9\xc5\x7d\x2d\x8c\x2d\xd8\xae\xf0\x7f\x3c\x7a\x73\xe8\xd0\x37\xde\xec\xdf\x7f\xec\x17\x4f\xcb\xb2\x4a\xb2\x4b\xe5\xd0\xbd\x8d\x31\xcd\xc2\xf9\xb6\x23\xed\x32\x47\x08\x56\xc2\xd0\xba\xfb\xe0\xb6\x22\xa9\xb0\xa6\x3e\xb7\x41\x80\xcb\x10\xcc\x27\x40\x25\xe2\xfe\x57\x71\x33\x4c\xf8\x0e\x26\xef\x04\x2f\x1c\xcc\xd8\x92\x75\x38\x8c\x4f\xcf\x4b\x32\x27\xa4\x1b\xf6\xc5\x97\xc7\xef\xcd\x2d\x37\x95\xa5\xe5\xa5\xe6\xc5\x1b\xe3\x52\x62\x8b\x23\x8b\x23\x0b\x99\x7d\x69\xa5\x29\xb9\x92\x21\x2f\x22\x23\x26\x26\x32\x3b\xd2\x1c\x9d\x9e\x90\x99\x94\x9a\x94\xcc\x58\x6a\xcd\xb5\x75\xda\xdc\x7c\x8b\x25\x57\xbe\x51\x74\xf3\x74\xf9\xed\xdc\x3a\x4b\x7d\x6a\xa3\xe1\xdc\x86\x03\x9b\xf6\x66\x56\x87\x36\x85\xe4\x85\xe4\x45\x87\xa5\x45\x31\xe9\x19\xe6\x0c\x21\xd6\x18\x9c\x9e\x10\x67\x34\x1a\x33\x4d\x99\x51\x59\x91\xd9\x91\x59\x85\xf9\x85\x79\x45\x39\x95\xcd\xcd\x05\x6d\x16\x26\xc7\x9c\x9d\xad\xe5\x7a\x11\xfd\x08\xe2\x56\xd6\xd7\x95\xc7\x4e\xb5\x9f\xcf\xff\x3a\xe5\xa3\xe4\x8e\x90\xdb\xfa\xa3\x81\xd5\xab\xa2\x33\x02\x8c\x31\x99\x4b\xe3\x92\x19\x13\xc5\xb9\x11\xaf\x11\xc4\xae\xf8\x77\x2d\x1b\x73\x03\xbe\x59\xfe\xf9\xec\x2b\x58\x04\xbb\xf1\xdf\x11\xd8\xb2\x88\xe1\xf2\x09\x1f\x82\xe8\x8c\xbd\x17\xff\x49\xf0\xf0\xe4\x61\x3b\x7c\xfd\x97\x05\x2f\x0c\x58\xeb\xbf\x66\xad\xd7\xa5\x82\x0b\x45\x97\xd2\xb7\x46\xed\x0c\x0d\x0a\x66\xb8\x8b\x04\x41\x30\xc1\xa6\xe0\x9c\x18\x6b\x9c\x35\xf3\xaa\xb1\x3c\xe3\xe8\xaa\x7d\x81\x91\xfa\xcd\x21\x7e\x29\x73\x19\xae\xaf\x23\x39\x79\x4e\x81\xef\xe9\x15\x4c\x4f\x13\x38\xb6\xee\xbb\xe8\x4e\x23\xc3\x11\xb9\x84\x1f\x61\xca\x30\x67\x66\x6a\x8f\x19\x0f\xa6\x54\xec\x28\xca\x28\x4c\xb3\xa6\x46\x19\x23\x33\xa3\x8c\xa6\x2c\x63\xb6\x31\x8b\xe1\x08\x3f\xa2\x2f\x91\x58\x1e\x9c\x13\xe3\x88\xf8\x10\x0c\x91\x91\x6e\xce\x10\xd2\xaa\x62\x6a\x77\xa5\x86\xa6\x86\x04\x65\x46\x04\xc4\xad\x0f\x4e\x5a\xc9\x70\x2e\x7d\x09\x03\x91\x16\x6c\x0e\xc9\x0b\xdd\xeb\x77\x73\xdd\x8d\x24\xc6\x98\x9f\x6b\xce\x13\x42\xcd\x61\x61\xda\x24\x6b\x62\x7e\x62\x76\x74\x6e\xa4\x39\x32\x33\x66\x5f\x64\x4e\x52\x1a\x93\x92\x9e\x9e\x10\xa3\xed\x31\x23\x62\x4f\x54\x52\x6c\x12\xc3\x11\xd3\x89\xf1\x44\x5c\x41\x5c\x56\x6a\x5a\x5a\x9a\x39\x3e\x27\x36\x3e\x2e\x21\x2e\x29\x3a\x21\x37\xd1\x9c\x91\x96\x9e\x9a\x17\x53\x18\x9b\x91\x68\x4c\x34\x25\x18\xf1\x05\x78\x13\x7b\xff\x99\xc1\x70\xc4\x20\xc2\x8b\xe8\x30\x76\x1c\x6a\xba\xac\x8c\x8b\x51\xc6\x67\x2b\xe3\xcb\x1a\x97\x75\x6c\xef\xc8\x06\x22\x07\xde\x84\xde\x99\xf0\xc2\x5f\x92\x4b\x33\x4b\x32\x4a\x24\xce\xc5\xcd\xb0\x8d\x28\x2c\xcf\xdb\x97\x9e\xcf\xe0\x7e\xfb\x7c\xbe\xba\xae\xa0\x21\x44\x6a\x5b\x5f\xea\x93\xb1\x39\xfe\xdc\x8e\x2b\xf3\xea\x98\x9c\xa2\xdc\xca\x1a\xed\xe4\x21\x3c\x30\xe2\xbe\xec\xea\xbc\xe2\xe2\x5b\xe1\xcd\x93\x72\x26\x65\xec\x49\xdd\x93\x9a\x12\x19\xb1\x35\x7e\x53\x0a\xc3\x11\x06\x62\x3d\xb1\xf7\x5e\xfc\xe3\xd5\x57\x19\x60\xc4\x1e\xc9\x5b\x32\x9c\x2f\x44\xb9\x11\xe7\xfd\x6b\x5e\x8e\x18\xcd\x18\xe3\xe3\x4d\x89\x82\xa3\x9f\xf5\x22\x52\xbf\x8c\xb9\xbf\xeb\x0e\x63\x2a\xdd\x6b\x2e\x15\x74\xb6\x6f\x27\xf0\x19\x47\x4b\xfe\x3c\x7e\x82\xa9\x6f\xa8\x4f\x89\xd0\x86\xe7\x46\xe5\x18\xa4\x79\xa1\x3b\x96\xc6\xaf\x64\x5a\x06\xf3\x9c\x0f\x41\xb8\x11\xa9\x05\x69\x85\xe9\x85\xb9\xf7\x0e\xfd\x7f\x6c\xfd\x07\x58\x14\x57\xf7\x38\x8e\x83\x30\xc5\x89\x41\x65\x76\x0c\xec\xec\xcc\x68\x62\x47\xac\x68\x34\x6a\xc4\xde\x0d\x1a\xc4\xde\xc0\x02\x22\x2a\x45\x40\xe9\x9d\xdd\xa1\x33\xf4\x22\x62\x45\xec\x62\x6f\x18\x93\x58\xb0\x8b\x31\xcd\x44\x63\x34\x05\xa3\x26\x31\x9e\xd9\x3d\xb3\x7c\xfe\xcf\x2e\xbe\x79\xdf\xe7\xff\xfd\x3d\xb3\x3b\x77\xee\xb9\xe7\x9e\x7b\xe7\xce\xcc\xb9\xe7\xcc\x9c\x7b\xce\xb7\xf7\x6a\x69\x56\x61\x06\xa7\x4d\x29\x49\xd8\x96\x56\x95\x69\x6b\x53\xa6\x80\x16\x16\xcd\x8e\xf5\xa8\x18\x15\x50\xb8\xa6\x2c\xb2\x96\x86\x89\x73\xb9\xd8\xd8\xac\xec\x2d\xd2\x96\xdb\x45\x5f\xed\xba\x40\x9b\xa8\x93\xd5\x55\x05\x55\x05\xd5\xb9\xee\x2b\xc7\x85\x8d\x4c\x1e\x41\x5b\xe6\xad\xe4\xce\x9a\xce\xca\x67\x32\x4d\x53\xc3\x90\xf2\x09\xd9\x94\x98\x9a\x97\x51\x9b\x74\x23\xfd\x46\xfc\x0d\x5a\xa6\xf0\x80\x99\xe3\x60\x00\xb0\xe8\x8a\x03\x70\x20\xb6\xa5\x03\xd0\xee\xa6\xdf\x06\x07\x57\x18\x20\x41\xb4\x95\xe5\x72\x36\x17\xe3\x7b\x51\x69\xcb\xe3\xdf\xcf\xf4\xdf\x1a\x5b\x6c\x04\x97\xac\x6a\xda\x44\xdd\xc9\xba\x2b\xdf\x31\xd1\x58\x83\x8b\xb8\x45\xf1\xdd\x8c\x8b\x6a\xc2\x8b\x8a\xa0\x57\xc1\xfe\xbb\xd9\x77\xe5\x7b\x59\xb4\x89\xca\x5d\x57\x88\x43\xb6\x24\xd3\x9a\x08\xb3\xb9\x93\x39\xa7\xb2\x4f\x66\xd1\x32\x95\x3c\xc7\xf8\x41\x6a\x70\x46\x58\x82\x1c\xa5\x7c\x74\x30\xf2\xb7\xad\xcd\xb4\xad\x75\xce\x94\x63\xca\x35\xe6\xec\xc9\xdd\x93\xb3\x27\x27\x3f\xa2\x30\xb2\x24\x92\x66\xbb\x3a\x38\x26\x3a\x1c\x9a\x01\xae\x93\x72\xff\xa9\xf5\x05\x5d\xd1\x85\xbc\x2f\xf2\xea\xe4\xe2\x33\xa7\x62\x6e\x65\x9d\xcd\x3d\x96\x73\xc0\x54\xb6\x37\x37\x3a\x27\xbc\x28\xfa\xe8\xa8\x3f\xee\x1f\x00\x17\xba\x3e\x73\x5f\xc6\xbe\x4c\xba\x6d\x29\xb6\x6d\xe4\x4c\x99\x26\xa3\x29\x03\xde\x30\xc6\xd8\xb2\x84\xaa\x54\x9c\x80\xe3\x70\x12\x7a\x60\xce\x04\x8c\xff\x1a\xa7\xc2\x07\x38\x0c\xc6\x6d\x2d\xa8\x28\x36\x56\xd1\x1f\x5a\x69\x2e\x6e\xea\x94\x65\x53\x73\x68\x96\x76\xa0\x1d\x1c\x26\xe4\xf4\xbc\xbc\xf8\x5e\x12\x50\xe0\x0d\xce\x3f\x84\xd9\x9e\xb6\x76\x0e\x0e\x9f\xc5\x9c\xe9\x53\x33\x14\xde\x30\x89\xa6\x24\x63\xb2\x98\x03\x63\xb8\xe4\x6d\x09\x3b\xe3\x76\xd0\xac\x83\xb3\x43\x27\x07\xe3\x39\xf9\x5c\xd6\x39\x3a\x8b\x2c\xca\x2f\x2e\x2c\x2c\xda\x9e\xbf\xbd\xb4\xb0\xbc\xa0\x3c\xa1\x64\x4b\x51\x56\x8e\x9c\x93\x95\x03\x6f\x98\xa2\xdc\xe2\xdc\xc2\x3c\x9a\xed\xea\xe8\xeb\x50\x63\x0f\x7b\xe3\xd8\x13\x3e\x18\x83\x86\x15\xe8\xf6\x09\x76\x1a\x9f\x79\x2c\xe1\x44\xc2\x3e\xfa\x36\x7e\xc4\x99\x64\xd9\x24\x66\x51\x59\xb2\x2c\x4b\xd0\xe5\x3b\x10\xae\x43\x9f\xe3\xc7\xa3\x8f\xc5\x9c\x88\x2b\xcc\x94\xe5\xc2\x9c\xc6\xf2\x0b\xd5\xe7\x6b\xa1\xff\x72\x10\xc7\x82\x61\x94\xd6\x39\x5e\x73\x35\x6a\xae\xe5\xb4\xc1\xb9\xe6\x14\x87\xee\xf7\x50\xb8\x82\xdd\x8f\x43\xb7\xfb\xd0\xf9\x15\xb4\x07\xc7\xc2\x74\x25\xa3\x38\x93\xce\xcc\xca\xc8\x32\x8a\x5b\x92\x12\xe2\x0b\x62\x0b\xe3\xb6\xc7\x6d\x4f\x57\x92\x8a\x92\x8b\xd3\xe8\xf9\xa6\xf9\xc6\xf9\x62\x56\x56\x5c\x78\x62\x58\xca\x26\xf7\x84\xb5\xf1\x4b\x33\x57\xd0\xaa\x21\x82\x5b\x3c\xbe\xe7\x27\x13\x32\xa7\x66\x4e\x39\x11\x77\x83\x36\x2a\xa6\xa2\x62\x7d\xcd\xe3\xb3\x7f\x5c\xac\xf8\x71\x07\x78\xa3\x73\x22\x52\xb4\x8b\x5a\x67\x99\x06\xc3\x1c\x65\x7b\x90\x70\xe2\x75\x18\xf7\x6c\xdc\xfd\x81\x03\xc7\x8e\x1d\x38\xf0\xfe\xb8\x67\xcf\x9a\x9b\x9f\x89\xd6\xa4\x2e\xcf\xc6\xde\x1f\x38\x70\xdc\xd8\x81\x03\x9b\xc7\x3d\x7b\x76\xdf\x06\xab\x30\x10\x5f\x71\xd0\x09\x67\xdd\xc2\xbf\x0c\xce\x09\x95\x06\xe7\x43\x55\xd6\x8d\xf8\x3d\x06\x69\x24\xad\x3e\x37\x7b\xa9\x61\x90\xde\xda\xcc\xb7\x36\x63\xdd\x29\x68\xc2\x33\xf6\xf8\xf4\x4d\x4d\xa0\x98\x75\xf5\x6a\x04\xe8\x9a\x9a\x1c\x65\x5b\xb6\xa9\xc9\xee\x56\xcf\xd7\x76\xe4\x64\xd1\x19\x88\x46\x4e\x5d\xa6\xb6\xd7\xda\x6b\xcb\xb4\x65\xda\xbf\xa9\xda\x5e\x5d\x66\x83\xdb\x52\xa9\xa9\xcd\x43\x95\xd6\xdd\xda\xcc\x05\x93\x40\x09\x5a\x44\x9b\x05\x7e\xfd\x33\x46\x8d\xa0\x64\x46\xed\x3e\x9d\x0b\x14\x16\xef\xf4\x3f\xbc\x49\x42\x72\x02\x03\x24\x75\x78\xdb\xce\x86\xd3\x7a\x38\xc1\x98\x95\xb6\xc8\x15\xcf\xb5\x51\xda\x28\x78\x8e\xcf\xe1\x08\x03\xcf\xd5\x51\x1e\x36\xe1\x57\x8b\xe0\xa0\x5a\x10\x3d\xce\x33\x2d\x6f\x43\xeb\xbc\x0d\x37\xec\x71\x9e\x31\xbf\xb6\xea\x38\x4f\x46\x6c\xd5\x3d\x65\x54\x05\x1a\x18\x8b\xae\xfc\x3f\x76\x9e\x41\x8c\xaa\x03\x5f\xd0\x41\x57\xc1\x6e\x36\x2a\x83\x8e\xb5\x18\xa8\x44\x8b\xc2\x19\xcc\x89\x56\x05\x6a\x04\x08\x62\x38\x98\xc3\x18\xd4\xc6\x7e\x02\xab\x59\x7c\x17\x09\x06\xca\x7b\x0e\xc3\x5a\xb0\x01\x74\x9a\x8e\xb2\x69\xaf\x1c\x9c\x60\xc0\x0b\x24\xc1\xa0\x36\x2e\x61\x5a\x7d\x29\x56\x1b\x72\x6f\xfc\x13\xd1\x40\x79\x2f\x64\xc0\x8b\x02\x9a\x91\x5c\x4c\x82\x4d\x80\xe4\x8c\x82\x59\x31\xa0\x03\xc9\x6a\x06\x2a\x71\x7a\x5f\xe1\x2d\xd8\xa2\x33\x2b\xad\xba\xff\x7f\xa8\xaa\x98\x15\x4d\xf9\x1f\x28\xab\x19\xe8\x44\x8b\x6f\x5f\x41\x4b\x00\x89\x91\xd3\x19\x27\x83\x73\x88\x9a\xc4\xb5\x2a\x16\x85\x28\x4d\x88\xc9\xdf\xc2\xa7\x24\x1b\x33\x53\xa5\xf0\xa4\x98\x88\x50\xbd\xc1\xd2\x15\x36\x32\x70\x1d\xae\xc3\xa7\xda\xfc\xb2\xe0\x43\x31\xfb\xca\xdc\x61\xe2\x57\xf5\x65\x15\x87\xe2\xf6\xb9\xe3\x12\x75\x23\xa1\xba\x92\x20\x08\xb4\x8b\x35\x21\x93\x31\x2b\x30\x49\x70\xf4\x13\x9c\xcc\xcd\xd0\x97\x69\x02\xdd\x74\x12\xa7\xa0\xdb\x3c\xcf\xf1\xd2\x6f\xe3\xd1\xed\x02\x4e\xe1\xa7\xa3\xae\x89\x84\x40\x70\xf0\xc6\x3e\x92\xe6\x05\xbf\x31\x5a\x03\x85\x7d\xd0\xc1\x1b\x03\xc5\xb6\xc2\x29\xe0\x76\xe1\xb7\x7b\x92\xe7\x3d\x70\x9b\x07\x53\xf8\x36\x32\x81\xe8\xf0\x15\xf4\x91\xec\x42\xa7\x23\xa3\x7a\x51\xd0\x07\x1c\xbe\x82\x40\x9b\xcc\x9d\xc9\xd8\xed\x4c\xdb\x5e\x53\xfd\x2e\xfc\x27\xd3\x55\xf8\x2f\x58\x79\x6b\x95\xcb\x1e\x28\xa9\x61\x1d\xbd\x7d\x0c\xb4\x03\x5c\x11\x54\xdb\x15\x60\x1d\x32\xbd\x51\x67\x40\x07\x8a\x75\x0c\x74\xb0\x5d\x14\x1b\xb0\x5b\x27\x07\xd0\xb5\x2a\x24\x5b\xd3\xdb\x01\x34\x81\xf5\xa6\xbd\x41\x67\x14\x28\xb6\xc6\xc1\x07\xed\xee\x81\xd8\x6e\x0e\x5d\x51\x67\x51\x48\x5b\xd9\x11\x81\x03\x1d\xc9\x76\xa5\x1d\xb0\xad\x32\xda\xa3\xfa\x83\x8e\x63\x1d\x69\x07\x5b\x91\x43\xa6\xb7\xca\x0a\x14\xeb\xe8\xe0\x0d\x3a\x83\x25\x91\xb3\xd5\x0f\x11\x48\x76\x67\x90\x0f\xe8\xc8\x08\xa1\x8b\x01\x1d\x54\x47\xc6\x62\xeb\xaa\xce\x28\x84\x08\xad\x0a\xea\x48\xd8\x26\x80\x0f\x63\xd5\x59\x74\x1c\x2b\x52\x89\xa0\xb4\xea\xac\x8a\xaa\x43\xc5\x76\xc5\x29\x03\x26\x6a\x3a\xdb\x65\xd6\x69\x0a\x65\x83\x72\x56\x9b\x12\x79\x85\x01\x85\x74\x51\xff\x1d\x98\x23\x42\x88\x20\xc3\x0a\x41\xb6\xdb\xe1\xfe\x77\x64\x6c\xc3\xf2\xbf\x47\x2b\xec\xdf\xbb\x0a\x76\xce\x61\x1d\xbd\x09\x43\x7b\x07\xb3\xc2\xbd\x1d\xa2\x44\x1d\xb6\x1d\x78\x77\x02\x5b\xe2\xd3\xdb\x76\xe3\xda\x34\x50\x87\xf7\xbb\xa2\xae\xd5\x06\x5b\xf8\xef\xe0\xb5\x9b\xe0\x00\x3a\xab\x8e\x64\x19\xc6\x3e\x78\xdd\xdb\x25\xda\xd0\x6d\x43\x53\xe3\xe8\x6d\x1f\x4e\x87\x09\xa0\xb3\xd8\xf2\x0e\xc4\xdb\xe1\xec\xd1\xae\x9d\xdd\xd5\xd2\x11\x81\x63\xdb\xb5\xb3\x8f\x59\xbb\x09\x0e\xf6\x31\x73\x18\xe7\x60\xd5\xa9\x0a\x67\x6b\x4c\x75\x64\x48\xd6\xc1\xbb\x2b\xda\xca\xbd\x3b\x19\xd0\x01\x74\xf6\xb1\x6f\x67\xbb\x1c\x14\xdb\xdd\xe1\x7d\xdb\xb0\xe9\x5a\x15\xdb\xc4\xed\x6c\x43\xb3\x37\x66\xeb\x76\x57\x07\x6f\xa3\xd0\x85\xed\xee\x50\x03\xbf\x31\x14\xcb\x38\xf4\x6e\x55\xba\xa8\x8e\x0c\xc5\xb6\x4b\xd4\xc1\xc7\x8c\x0d\xc7\xd1\xc1\xd9\xa2\x23\xd9\xc2\x77\xd6\x86\x08\x56\x9d\xad\x79\x4d\xa7\x29\xe0\xc3\x18\x05\xd4\x81\x0f\xc3\xe6\x2f\xf4\x0c\x11\x38\x95\x15\x5a\x75\xa0\x0b\x11\x6c\xa7\x05\x57\x18\xfb\x2e\x44\x20\x5d\x56\xd9\xae\x60\x03\xb7\x5a\x10\x55\x2f\x8b\x17\xfc\x22\x18\x2c\x8d\xe0\x29\x58\xbc\x48\xfb\xa3\xae\x75\xa6\xce\x28\x17\x77\xd6\xd5\xc1\x0c\x98\xe1\x56\x57\xb7\xf3\xa2\x72\x86\x76\x09\xb1\x3d\xaf\x9f\xdb\x76\x3a\x27\x03\x11\x0d\x0a\x97\xb6\x25\x79\x4b\x6a\x2a\xce\xc4\x99\x6e\xa9\xa9\x5b\x92\xb7\xa4\xd1\x90\x05\x59\x14\xee\x03\x1d\xe7\xb7\x7c\xb9\x9f\x84\x0d\xad\x3a\xa3\x60\x14\x5a\x6d\x3c\xc4\xe2\x05\x43\x98\xb7\x0d\x29\x64\xe3\xfd\xbd\x87\x0e\x49\xb6\x06\x88\x43\x87\xf6\xde\x6f\xd4\xbb\xa8\x75\xea\x62\x98\x8b\x53\xa1\xeb\xb7\xc0\xd9\x57\x7b\x3e\xbf\x68\xee\x7d\x1f\x56\x43\x00\x64\x80\x8e\x8d\x33\x50\x5b\xd5\x03\xdc\x81\xf0\x5d\x21\xf9\x62\x56\x46\x72\x56\x3a\x8f\x9e\xd8\x15\x3c\xc9\x3c\x25\x2b\x2b\x57\xaa\xcb\xdf\xbe\xf3\xa0\x7e\x33\x04\x71\x07\xc2\xb7\xaf\xcf\x13\x33\x53\x6d\x18\x12\x72\x20\x91\x79\x05\x72\x56\x8e\xc4\x66\xee\xc9\xdb\x5e\x7b\x40\x6f\xc0\xe9\x38\x9c\xc3\x0e\x63\xfb\x62\x81\x28\x63\x3f\x19\x3b\xec\x13\xc1\x99\x5a\x73\xff\xeb\x88\x6f\xf8\x5f\xce\x5f\xfa\x4a\x82\x2b\x10\x8d\x57\x28\xf3\x52\x9c\xc1\x75\xdd\xd8\x33\x43\xd6\xe3\xeb\x98\x5e\x20\x41\x0f\x3d\xf4\x78\x09\x12\xbc\x8e\x11\xe5\x57\x19\x6f\x36\x8a\xe8\x4c\xf9\xed\x9a\xb6\x63\x44\x3e\x8d\xdd\x8b\x87\x4e\xc4\x4e\x7a\xec\xf4\x78\x22\x74\x2f\x16\x1f\xe6\xdf\xd8\x79\x61\x17\xcd\xc6\x21\x41\x99\xc3\x80\xe2\xd8\x6d\x1f\x8d\x9f\xd7\x57\xd4\x12\xd4\x02\x75\x11\xa9\x14\x9b\xf2\xf9\x47\x19\xd7\x96\x8d\xd1\xfb\x2c\x9f\x3f\x3a\x51\xcc\xa4\xd8\xb8\xc7\x69\x37\x16\x8d\xd5\x83\xce\x9c\xf3\x54\x30\xa8\x0e\x24\xeb\xbf\x41\x50\xeb\x60\x00\x03\xcf\xaf\x40\x30\x24\x43\x35\x24\x43\xb0\xca\xc2\x73\x27\xf3\x0b\x38\xc3\xa1\xd4\xd8\x1b\x78\x18\xac\x87\xc1\x2f\x80\x07\xe9\xa2\x68\x9d\x4a\xa9\x59\xf0\x82\xc3\xc1\xbd\x91\x47\x69\xae\x68\x9e\x46\x81\x34\xf7\x05\xf2\x38\x58\x0f\xc1\x5d\xe0\x6b\x2c\x87\x72\xfc\x1a\x1f\x60\x05\xda\x53\xa8\xc0\x0a\x78\x00\x5f\x43\x39\x54\xc0\x03\x51\x65\x53\x39\xfc\x13\xef\xe1\x61\xfc\x4b\xc4\x8b\x24\xbe\xc1\x93\x70\x18\xfe\x54\x5d\xe1\x24\x54\xc2\x1b\x09\x2e\x92\xf0\x17\xdc\xc3\x4a\xcd\x55\x82\xe7\x66\xfd\x4a\xe6\x1f\xe6\xa8\xe0\x51\x21\xb4\x36\x27\x32\x96\xe6\x66\xc6\xd2\x0c\x93\x05\xbb\xb3\x30\x4b\x33\x37\x9f\x69\x6d\x6e\x8b\x67\x6b\x69\x5e\xc8\x68\xf6\x69\xf4\xbf\x30\xf0\x02\x1d\x7a\xfd\x4f\x35\xf4\x02\x1d\x65\x67\x0b\x10\x01\x0d\x90\xc1\x54\x80\xb3\xab\xdc\x64\x56\x9a\xda\xde\x44\xd9\x8e\xd8\x97\x89\x06\xb2\xd1\xd2\xcc\xa9\x3a\xab\x2f\x61\x55\xc8\x56\x9d\xd9\xf7\xdf\x8c\xc1\xf9\x98\x45\xc7\xa9\x09\x41\x82\x96\x40\x7e\xb5\x71\x62\xe3\x87\xfc\x87\x13\xfd\xbc\x37\x4a\x5a\xc2\x20\x46\x4d\x20\xab\xe7\x9e\x58\x76\x31\x9a\x36\x58\xfe\xd1\x5e\x6f\x60\x60\x0a\xc3\xba\x3a\x0c\x63\xd8\x5a\x87\xd5\x8c\xf6\xda\x40\xbc\x43\x5e\xac\x3e\x71\xa2\xfa\x22\x8d\x53\x63\x38\xf8\x91\x59\xb6\x66\xcd\x32\xc9\xd2\xdc\xea\xcc\xc9\x14\xac\x67\xc0\x24\x88\xec\xcb\x44\xf8\x10\x0e\x3f\x04\x7f\xc9\x80\x0e\x5d\x58\x57\x07\x58\xcf\xd8\x80\x26\xe1\x2d\x5c\x74\xe9\xce\x68\x7b\xad\xf3\xb9\xb0\xe4\x2d\xe1\x1b\xf5\x6d\x6e\x82\x61\xe9\x18\x58\x8e\x5b\x35\x47\x7d\xab\x42\xaa\x8e\xb0\x1c\xb6\xc2\xd2\x07\xe2\x73\xa6\x3b\x83\xba\x2e\xcb\x32\x97\xa7\xf9\x8b\xad\xc9\x64\x5a\x43\xe6\xf1\x13\x7a\x8b\x62\xb0\x38\x70\xad\x0a\x09\x08\x0b\xa1\x0a\x16\x7d\x27\xc2\x16\x12\x16\x8d\x84\x85\x58\x85\xa8\x77\xb1\x57\xc2\x9e\x6b\x91\x9b\x87\x8e\xa2\xf5\x77\x72\x1e\x38\xae\x05\x0e\x7a\xea\x2d\x8b\x0c\xe8\xcd\xb5\xbe\x4f\xde\x87\xb9\xe0\x0e\x02\xb8\x5f\xa4\x6d\x75\xdd\xe7\x82\x3b\x0a\xf7\x71\x2e\xfd\xff\xd5\xbb\xc7\xc1\x3f\x4d\xbe\xeb\x41\x5b\x7d\xc8\xbb\x2d\x3f\xdd\x7a\x5c\x4f\x3f\x67\x50\x01\xdf\x47\x91\x06\xc2\x1b\x7c\x7f\x66\x0c\xc4\xa3\xe9\x7f\x32\x06\x4b\x6d\x13\x67\x70\xd6\xc8\x68\x78\x8a\xbb\x61\x2a\xce\x00\x17\xb0\xfd\x77\xc3\xd4\x6a\x78\x4a\x1b\xd0\x99\xac\xc6\xa7\xb0\x1b\xa7\xc2\x0c\x74\x41\xdb\x7f\x37\x4e\x8d\xc6\xa7\xb4\x81\x58\x6a\x20\x1d\xfe\x64\x5c\x42\x04\x8b\x33\xe8\xea\x41\x37\x1d\x74\x1e\xf6\x75\xa1\x5d\x05\x88\xa8\x97\x41\xd7\x52\x0f\x4a\x3d\x44\xd4\xb7\xb4\x89\x29\x4f\x22\xd8\xcb\x11\x66\x05\xae\x08\xb9\xb9\xb2\x29\x4f\xba\x99\x7a\xc6\x67\x8a\x1e\x5d\xea\x6d\x3c\xb0\x29\x02\xb6\x31\x85\x85\x26\x53\x81\xd8\x98\x78\x70\xa1\x9f\x1e\x3b\xd7\xd7\x53\xec\x13\x1b\xb8\xe9\xcc\xbc\x19\x22\x9a\xa8\xd0\xcc\xd0\xd4\x30\x91\xfd\x49\x45\x07\x6d\x0a\x91\x1a\x96\x19\x1a\xaa\x0f\xa3\x3c\x19\xd1\xaa\x23\x03\xd7\xef\x39\x70\x34\x69\xdf\xfa\x3d\x12\x5e\x83\xb3\xc4\xa6\x6d\xf1\x7b\xf6\xea\x21\x82\x82\x6d\x8c\xc8\xde\x8b\xb0\x91\x90\xd0\x9b\xaa\x0f\x21\xd4\xb1\xd4\x7f\x68\xf6\xb7\x37\x7d\x39\x02\x68\x46\x04\x9d\xf3\xb4\x99\xe1\x4b\x17\x4b\xec\xbd\x88\xb2\x75\x6b\x0b\x82\x78\x74\xed\xd6\x07\xd9\x14\x29\x2b\x3d\x5d\x4e\x53\xdf\x11\x30\x82\x9a\xba\x67\xfa\xe9\xa5\xb6\x1e\xc0\x15\x3c\x4b\x60\xbb\x6f\x06\x02\x29\x9a\x75\x64\xba\xb0\x5d\xae\xcd\xdf\x2e\xd9\xfa\xeb\xa8\x4e\x21\x0a\x0f\xe4\x1d\x3a\xa8\x07\x13\x05\xee\xdd\xa0\x1d\xea\xa3\xa2\x8c\xe9\xd1\x22\xdb\x14\x71\x7d\xe9\xb8\xc3\xa3\xf8\xe5\xcb\x13\x36\xad\x96\xd8\xcb\x11\xfb\x96\xcf\xab\x9c\xcb\xdb\x9d\xa5\x46\x33\xa0\xd8\xbf\xf5\xe8\x64\xb5\x93\x6d\x00\xff\xf3\x03\x1d\xfb\xf7\x23\xb6\xe5\x91\xc5\x19\xfa\x32\x57\xcf\x2d\x98\x29\x59\xbb\xd7\xab\x3b\x28\x16\x1e\xc1\x36\x3b\x40\xd4\x76\xd4\xc3\x0e\xea\xdf\x5c\x3a\x15\x65\x8c\xca\x8c\x16\xc7\x68\x7d\x88\xa5\xc9\x01\x6b\x97\xf0\xd6\x09\x64\xc0\xaa\xea\xfa\x70\x09\xfe\x61\xee\x7c\xfe\xc5\xdd\xa3\x87\xa3\x83\xb7\x8b\xd0\x1f\x57\x10\xa0\x50\xea\xff\xd4\xdd\x51\x6f\xee\x4e\xb1\x2d\x36\xd2\xb6\x21\x19\x34\x7c\xfe\x47\xfe\x12\x0b\x8f\x72\xe2\xe2\xb2\xe2\xd4\x77\x04\x6d\x12\xb5\x3d\x70\x7e\xd1\x0a\x1e\xdf\x47\x12\x29\xec\x06\xd9\x8c\x79\x02\x09\x0e\xbf\x7e\xfd\x4f\xb5\xf4\x40\xed\x4d\xe4\xed\xca\xd9\xbd\x5b\xaf\xa6\x53\xd0\x15\xdb\xbf\x41\x29\x45\xac\xa4\xc0\xcd\x1e\xd2\xd3\x2d\x2e\xce\x94\x19\x27\xb2\x2d\x8f\xbe\xf7\x1f\x7e\x7e\x10\xef\x52\x63\x9b\xcc\x76\x6f\x80\x11\x82\x6d\x86\xa8\x07\x9d\xed\x74\x0b\x40\x07\xd9\xb6\x73\xaf\xaf\x87\x06\xd0\xb1\x17\xce\x5a\xbe\x40\x1d\x77\xed\x5a\x61\xf9\x65\x09\x7e\x79\x44\x00\xb9\xfb\xbb\x3f\x81\xd1\x9b\x07\xaa\x0c\xa3\xf5\x20\xad\x34\xa4\x10\xc5\xeb\xd7\xe5\xaf\xe3\xfd\x99\x6e\x37\x3c\x5e\xac\x96\x4e\x6c\x21\x90\x20\x81\x15\x20\x5a\x80\x6e\x12\x94\x91\xe9\x49\xf2\xc6\x44\x3d\xfb\x63\xec\x80\xc6\x0f\x1f\x06\x88\xe9\x54\x60\x61\x60\x79\xb0\xe8\x71\xfc\xdb\xa5\x7f\xf3\xa0\x33\x2f\xe2\x7c\xa9\x29\xa7\x7d\xae\xc7\x89\xf8\x0c\xfb\x13\xa9\x71\x31\x99\x31\xfc\xcc\x05\xe7\xae\x9e\xd8\x79\xf4\x68\x95\x04\x1f\xde\x27\xd4\x0d\x98\xca\x2d\x0b\x0d\x08\xd8\x2c\xe2\x6b\xf4\x22\xd2\x93\x62\x32\x12\xf8\x29\x4b\xce\xdc\x78\x70\x65\xfb\xe5\x5d\x12\x1c\x07\x37\xa2\xa0\xac\x22\xa7\x82\xb7\x5f\x27\x8c\x35\xa7\x72\xb7\x49\x74\xea\x41\xac\xdf\xb8\x65\x65\x80\x1e\x17\x52\x18\xd7\x8d\xd0\xea\xc9\x09\x73\x3e\xbf\x2b\xb1\x3f\x9e\xb5\xdd\x79\x66\x5d\x13\xa9\xd5\xc2\x62\x62\x61\xf5\xda\x33\x8d\xfa\xbb\x5f\x7c\x7e\xa7\xa2\x3c\x33\xbd\x5c\x64\x7f\x8c\x55\xc1\x80\x34\x37\x90\x84\x6b\xd0\x8d\x38\x5f\xbb\xef\xc2\x25\x3d\xfb\xe3\xd9\x3b\xf3\xaf\x4c\x2c\x16\xd9\x0b\x67\x0f\xec\xda\x76\xec\xa4\x1e\x56\x06\xe3\x4a\x6a\xd6\x02\xdf\x99\xb3\xe6\x9f\xba\x2a\xc2\x59\x6a\x6f\x69\x5d\x6d\x8d\x08\x06\x70\x25\xe0\x0a\x09\xef\x32\x92\x75\x20\xe5\x13\x30\x7f\x4e\x9c\x88\xbf\x0c\x23\xe2\x17\xf8\xa5\xcd\xe3\xdb\x6c\x92\x74\xaa\xee\x77\xfb\xed\xa6\xbb\xc0\x58\x74\xf0\xcc\x26\x9f\x27\xc0\x56\xa6\xf5\x53\x72\x2f\x23\x05\x53\x53\x6b\xa7\x1d\x9b\x2f\xa2\x5b\x31\x38\xf5\x00\x77\xde\x3c\x8e\x5c\x81\x3a\x42\x1b\x5e\x24\x04\xc3\x49\x41\x54\x8f\x93\x70\x04\x3f\x20\x70\xa2\x3d\xa7\x23\xa1\x95\x01\xa0\xa0\x8b\x3f\x74\xfe\xf8\x6f\x51\xbb\x6d\xde\x46\xdc\x58\x34\xfa\xc8\x47\xbc\xb9\xc8\x60\x6e\xb4\xa9\x35\x9a\xee\x29\x03\x0b\xa8\x83\x91\xfb\x82\x2b\x45\xbc\x03\x83\x89\xbc\xe4\xa4\xec\x24\x5e\xfb\xe2\x29\x53\x4f\x3d\xb9\x77\xef\x89\xa8\x7e\x42\x36\x1c\xda\x75\xa4\x54\x6a\x02\x5f\x22\x47\xc9\x2e\x2e\xd2\x2f\x16\x06\x92\x56\x1d\xf9\xc9\xdc\xe3\x5f\x26\x4a\x19\xd5\x59\x5b\xab\xf5\xbf\x08\xe6\xe6\x7a\x6b\x33\xb9\x62\xf5\x06\xff\x78\x29\xf0\xb8\xe9\x50\xa3\xfe\x17\xc1\xf2\x29\xd9\x70\x38\x2a\x78\xbb\xa4\xde\xb1\x6e\x23\x2e\x8f\xd8\xd7\xb3\xa7\xbe\xed\x54\x27\x09\xe6\x09\xa0\x5b\x64\x53\x9d\x88\x4e\xa0\x83\x54\xd0\xb1\x3f\xa8\xcb\x50\xe1\xcc\xd3\xc8\xcf\x2e\x56\xed\x3b\x21\xa9\xb9\x6a\x27\xe2\xc6\xb9\x86\x6f\x7e\xd4\x43\x57\xa4\x81\x40\xe9\xfd\xd9\xb3\x3f\x19\x29\x42\x47\x55\x21\x72\xb7\xe6\x6c\xad\xd6\x43\xc7\xc1\x7f\x63\xc7\x32\x11\xe8\xe8\x3e\x8f\xf1\x1d\x1e\x9d\x3c\xc6\xa0\x43\xa8\xd4\x5d\xf3\x1e\x0e\xaf\x08\xf6\x05\x38\x84\x7a\x3c\x40\x27\x1e\xe9\xbe\x23\x91\xd8\x24\x61\xc7\x78\xcf\x1e\xd8\x49\x1f\x9d\x1d\x9d\x17\x2d\x02\xad\x85\x12\x79\x9b\xe4\x4d\x11\xfa\x35\x79\xab\x0b\x03\xc5\x57\x5a\x0f\x82\xfd\xa1\xd7\x8e\x9f\x27\xfe\xc5\x9b\xdd\x8f\x0a\xdc\xf5\x53\x7e\x33\x92\x4d\x49\xc6\x64\x09\xfb\x5a\x9d\x89\x9d\x24\xd0\x6a\x24\x71\xae\xe4\xe4\xc1\x0b\x7c\xd3\x69\xbf\x99\x49\x46\x5b\x59\xd2\x72\xe4\xb4\x5d\x29\x7a\x8c\xa2\xe0\x32\x6c\x21\x2a\xb7\xed\x52\x76\xf3\xb7\xbf\xf0\x9d\xb8\x7c\x93\x7f\x50\xa8\xa4\xe5\x6a\x1d\x89\x2d\x9b\x36\x26\x6f\xe4\xad\xd3\xc8\x65\xab\xea\x8e\x27\x4a\xbd\xd4\x1e\xb1\x5f\x14\x7d\x11\xf7\x85\x3b\xd2\x6a\x18\x61\x2c\x34\x29\x8a\xfe\xea\xf9\x73\x57\x2f\x9c\x5c\xb9\xb0\x44\x7c\xa1\xf5\x23\x76\x92\xe8\xa6\x9e\x20\x8c\x8a\x49\x29\xd2\xb3\x2f\xae\x9e\x39\xdf\x74\xfe\xe4\x9a\x05\x25\x22\xf4\xd0\x5e\x10\xc0\x92\xec\x0f\x30\xdc\xfc\xb1\xbd\x3b\xe7\xff\xc3\xba\xea\x6d\xc3\xaa\x1b\x09\x3a\x78\x6d\x63\x5e\x4a\x7d\xb0\x9d\x75\xa1\xaf\x9d\x85\xf9\x82\x8e\x7d\x5a\xc9\x3e\x5d\x67\xd6\x41\x5f\xa6\xf9\xb3\x99\xe3\x25\xed\x66\x7d\x8b\x4d\xc9\xb4\x65\xc4\x41\xf5\x4d\xff\xb2\xe4\x59\x14\x7b\xa3\xb2\x9e\x5c\x2d\x7c\xd6\xb0\xc8\x4f\xc4\x10\x6a\x5a\xca\xb4\x98\xe9\xe2\x00\xcd\xf9\xad\x3d\x8c\xd5\xff\x2d\x2b\x63\xef\x57\xc2\x3f\x0c\xfb\x4b\xe5\xed\x4b\x5f\xde\x39\x76\x34\x72\xed\x0e\x11\x3c\x70\x29\xa1\xea\x28\x55\xa1\xde\xb2\x74\xa8\x17\xb4\x13\x54\xed\xca\xa5\x25\x4b\x78\xec\x8a\x24\xd2\xd8\xd5\xc6\xb1\xfc\xc9\x27\x5f\x5f\x7e\x54\x23\xfd\xa2\x3a\x13\xec\xd3\x75\xd5\xf7\x95\x07\x5f\xe9\xd9\x5f\x2a\x21\x84\x82\x4e\x7d\x5e\xa3\x6b\xf4\x66\x1b\xc7\xfe\x6c\xe9\x94\xfa\xf1\x7c\x50\x50\x6a\xdc\x3a\xe9\xc4\xe2\x59\x3b\xa6\xf1\x89\x49\x26\x53\xa2\x04\x1b\x29\x78\x1f\x09\xe8\x80\x1f\x88\x6d\xaa\x55\xb0\xaa\xab\x27\x41\xd1\x74\x5c\x30\xc9\xde\xaf\x54\x75\xf5\xb6\x13\x69\x03\xa8\x3a\x92\xfd\xa5\xb2\xde\x1e\x81\xaf\xc1\xc6\xd5\x22\xea\x21\xbb\x8d\xcf\x45\xd8\xb8\xde\x47\x36\xd6\xaf\xdb\xb0\xdb\x4f\x60\x21\x82\xc5\x08\x03\x41\x5b\xde\xe5\x58\x78\xfd\x30\xe0\xc3\xc6\x01\x7c\x4c\x8c\x31\x33\x46\x82\x32\xaa\x56\xf0\x67\x44\x24\xa8\x2d\x27\x88\x17\xab\x3d\x6e\x74\xe3\xfd\x99\x75\xf9\xeb\x8a\xd7\x4b\x90\x62\xa5\x09\xad\x07\x95\xca\x88\xe6\x81\x24\x30\x7f\x7e\x07\xe4\x6e\xe9\x11\xfc\x42\x94\x5f\x2e\xbc\x76\x4d\x0f\x13\x29\x16\x23\xfe\x5e\xfa\xad\xc7\x71\xb1\x62\xed\xea\x82\xd5\x3c\x0b\xeb\x70\x5d\x01\x67\x63\x53\x31\x99\x31\xa9\x71\x12\xf6\xc7\x67\xc4\xf5\x38\x9f\xd3\x53\x78\x5f\xf2\x2e\x0c\xb8\x0f\x1f\x12\x47\xab\x8e\xee\x3c\xc1\x43\x28\xf2\xdc\x8d\x33\x4b\xa6\x24\x64\xc4\xa4\x27\x49\xe8\x85\xaf\x89\x80\xcd\x01\xa1\xcb\xec\xdc\xb1\x22\xa7\xa2\xa0\x4c\x02\x37\x38\x4e\x5c\xde\xb5\xfd\xca\x03\xde\x80\xe1\x80\x9c\x6d\x92\x69\x3c\xb3\x76\x61\xb5\x08\x8b\xb5\x5a\xa2\xc9\xac\x23\x81\x66\xe0\x5d\x46\xd4\xea\xa9\x6e\x18\x47\xe0\x42\x92\xc5\xe7\x01\x2b\xb7\xac\xdf\x28\xf5\x40\x27\xe2\x36\x85\x59\x66\x91\x48\x2f\xcf\x2c\xaf\xd0\x5b\x0e\x19\xb0\x2b\x67\x1d\xd8\xc6\x26\xe1\x0a\x05\xae\x60\x20\x6a\x6b\xea\x4a\xf7\xf2\x70\x96\xbc\x7a\x6a\xfe\xac\x99\xbe\x0b\x66\x49\xb8\x32\x98\x64\xe1\x35\xac\x24\x4f\x1e\xdb\x76\x60\x97\x34\xb1\xf8\xca\xfc\x3b\xfc\xa5\x0b\xfb\xce\xd7\x4a\xd0\x0d\xae\x11\x03\xa9\x79\x69\x7e\xf1\x0b\xc4\x61\xf8\x0b\xc1\xe2\xf3\x39\x71\xf3\x03\x7c\x78\x17\x58\x5a\x13\x69\x7e\x04\x53\x1c\xe1\x21\x2c\x74\x32\xff\x61\x89\xe0\xaa\x62\xcb\xb6\x88\xd6\xfd\xbd\x19\x6c\x4f\x6d\x59\x22\x88\x70\xce\xda\x08\xc7\x05\xe0\xc9\xca\xb2\x2c\xc1\xdc\x08\xe7\xa9\xca\xf2\xb2\x4a\xc9\x52\x0b\x1d\xb8\x0a\x53\x5c\xe9\x16\x1e\xbb\x91\xf1\x89\x29\x89\xe9\x12\x86\x6a\x95\xa9\x31\x69\x9b\x53\xb7\xb8\xa7\x55\xa6\x56\xa5\x56\xe0\x46\xb5\xd2\xad\xd8\x6e\x88\x84\xef\x93\x31\x71\xf1\x31\x26\x69\x74\xeb\x5c\x22\x39\x27\x25\x3f\x55\x6c\x73\x94\x0e\x3c\x59\x51\x56\x5a\x91\x25\x9d\x54\x7f\x02\x1f\x6d\x0c\x91\x90\x5f\x9c\x5a\xc2\x43\x07\xb2\xb4\xb8\xa0\x24\x4f\x82\xd9\xea\xe8\x53\xda\x23\x22\x26\xab\x2c\xbe\x82\x07\x3d\xa9\x14\xc2\x64\x26\xbf\x20\xa7\xd0\xa4\xd8\x43\x4f\x81\x97\xfa\x17\x4c\x85\xfd\x30\x05\x22\xe0\x99\xa0\xea\x60\x21\x34\xc2\x12\xd5\x1d\xbc\x9c\x2c\xbb\xcc\xf7\xb9\x41\x0b\xe6\x0d\x11\x71\x18\xec\x87\x8e\xe4\xed\xdd\xa9\x89\x5b\xa5\xa3\x9b\xb6\xfa\xcf\xd6\x5f\xc0\xc3\x5c\x66\x7e\x66\x5e\x66\x1e\xfd\xfc\xcc\x95\xbf\xa1\xa3\x1e\x0c\x13\xc1\x09\x89\x63\x62\xf9\xca\x25\xca\xfb\x3c\x9e\x6e\x5b\x82\x06\xfa\x0f\x05\xf8\x0b\x06\x50\xe0\xa7\x39\x12\x89\x79\xc5\x69\x25\x3c\xf4\x23\x8b\x8b\xf3\x8b\xf2\xa4\x7c\x45\x2e\x49\x2f\xa2\xb5\x5e\x06\xe7\xc3\x6f\x04\x8b\xce\x1a\xc1\xfd\x1b\xee\xc8\xde\x3b\x03\xd1\x08\xcf\x04\xdb\xde\xcb\x49\xfd\x13\x2e\x71\xea\x3b\x0c\xf4\x82\x1e\xb0\x00\xdc\x05\xdf\x4b\xc3\x61\x1d\x53\x64\x2c\x4a\xcb\x4d\x3e\x39\xc2\xad\x20\xd1\x18\x9b\x92\x44\x67\x64\x0c\xee\x85\xc3\x79\x33\xd3\xc5\x86\xdb\x1b\x7a\xc0\x7c\x70\x17\xe6\x5e\xfa\x10\xd6\x31\xc5\x46\x25\x2d\xcf\x86\x9b\xff\x1f\xdc\x21\xbd\x70\x04\x8f\xbf\x58\xbe\x78\x23\x80\x57\xdb\x7b\x3a\x17\xa8\x0b\x36\x10\xde\x8e\x4d\x06\x2a\xd1\xc9\x1c\x61\x8e\xe0\x3c\x3c\xe0\x18\x1e\xc5\xb9\x38\x57\x8b\x50\xed\xdb\xbd\xf1\x2d\x2d\x38\x0a\x46\x59\xbd\xac\x5e\x66\x2f\xab\x17\x5c\x61\x08\xf0\xb5\xf8\x72\x9a\x4e\x25\x04\x4d\xd7\xd2\x82\xc7\xe0\x28\xcc\x85\xb9\x6a\x84\x66\xdf\xc6\xdf\xf3\xf0\x80\x51\x38\xca\xec\x65\xf6\x22\x5c\x8e\x33\xe6\x15\x30\x8d\xd3\x16\xaa\xf6\x0d\x58\xd4\x79\x79\x05\x1c\xc5\x7a\xac\x87\x7a\xac\x6f\x69\x41\x5f\xf8\xf4\xc9\x13\x42\xa6\x6c\x59\xe2\x27\xac\xe0\x90\x05\xf6\xa7\x27\x47\x03\xc0\x8e\x01\xf5\x1e\x1e\xe0\x8b\x9f\x12\x32\x35\x64\x08\x21\x53\x36\x08\x6c\x87\xed\xea\x42\x6d\x21\x01\x15\x19\x5c\x2e\x33\x50\x10\x5d\xd4\xba\x35\xe0\x34\x3b\x12\xaa\x1f\xbd\x80\x4f\x5e\x3c\xfa\x1c\x36\x7f\x00\xce\xd0\xee\x77\xd7\x3c\x70\x86\x09\x8f\x1f\xc1\x27\x40\x3e\x82\x39\xe0\x2c\x83\x33\x4c\x7f\xf4\x08\x7c\x80\x78\x0c\xd3\xc1\x99\xdd\xff\x6d\xa3\x59\x52\x0f\x72\xe7\x57\x1c\x9b\x3f\x6f\xc5\x8a\xf9\xf3\x8e\xad\xb8\x70\xfe\xd8\xb1\x0b\xa2\xc1\x39\x39\x8b\xbb\xb0\xa2\x61\xde\xbc\x15\xfe\xf3\x6c\xd0\x0b\x36\x68\xeb\x0e\x13\xd7\xd5\x6b\x68\xb7\xae\x43\x1f\xbf\xf9\xe7\xf1\x4f\x6f\xfe\xf9\xc9\xab\x9b\x68\x70\x4e\xca\xe2\xba\x0e\x85\x57\xc2\x63\xaf\x6e\x62\x6b\xa3\x89\x03\x4f\xec\x04\x9d\xb1\x3f\xf6\xc7\xce\xd8\x19\x3d\xb1\x3f\x74\xc6\xce\xd0\x1f\xfa\x43\x27\xe8\x0c\xfd\xdb\xa8\x43\x7f\xec\x0c\x9d\xb0\x3f\x7a\xda\xe3\xf7\xf5\xb7\x63\x75\x02\x4f\x91\x75\xa2\x1d\xa0\x3f\x74\x86\x4e\xd0\x5f\x62\xd3\x12\x1d\x5a\xe7\x67\x72\x58\x88\x01\x18\x80\x85\x22\xeb\xed\x90\x88\x05\x18\x00\x01\x50\x08\x85\x60\x4b\x0b\x6c\xa9\xad\x50\x32\x0f\x54\xef\x70\x78\x35\x19\x65\xcc\xc7\x26\x3d\xdc\x51\x3b\x0b\x78\x27\x4b\xbc\x0b\xc3\x61\xf9\x11\x58\xc1\xb3\xa9\x0e\xde\xb0\x02\x66\xad\x1c\x0f\x23\x24\x35\x5c\xbb\x63\x23\xec\x6f\xab\x6b\x6b\xc0\x46\x53\x64\x93\x33\xbd\xdf\x12\xb6\x35\xe0\xdf\xd6\x6a\xb2\xb3\x03\x56\xab\xd7\x38\x78\x0f\xe7\xe3\xd6\x87\xf8\x25\x8f\x5f\xe2\xe1\x11\xf8\x1e\xce\x97\x34\x47\xf2\xf2\xc4\x13\x9e\xc5\xd3\xe8\x49\xfd\xfc\x91\x46\x57\x3d\xde\x81\x22\x54\xe0\x36\x4c\x81\xa1\x0f\xa1\xcb\x6b\x3b\xd1\xe3\x0b\xee\xf6\x2c\x5b\x4f\x3f\x84\x8e\xa7\x2f\xc9\x7a\xe4\x5e\x83\xd7\x08\x98\xc2\xc3\x6d\x28\x02\x05\xee\x80\xab\x3f\xd0\x93\x7e\x97\xd8\xe1\xe1\x89\xc5\xd7\x4f\xfc\x76\xf9\x0e\xed\xa2\x25\xc0\x4e\xd8\xf8\xea\x68\x3a\x6c\x51\x3f\x85\x2d\xae\x30\x0b\x62\xd4\x39\x10\xc3\x8e\x32\xeb\xcc\xed\x39\xc8\xb1\x07\xf6\xcf\x81\x5c\x5c\x0e\xcb\x30\x07\x73\x70\x39\x2e\xc3\x5c\xcc\x81\xe5\xb8\x0c\x72\x24\xf3\x08\x67\xe8\xf8\xb2\x17\x76\xc2\x8e\xbd\x7a\x61\x47\xec\xd8\xeb\x25\x74\x84\x4e\x2f\x5f\x42\x47\x89\xfd\x5e\xdd\x6a\xdd\xc8\x85\x9e\x9f\x70\xdc\x73\x2c\x2d\x23\xdb\x13\x57\xe0\x0a\x64\x5f\xc9\xa2\xe7\xfd\x09\xcb\x43\xe7\x2f\x1b\x74\x6e\x39\x90\x63\x9f\xcf\x04\x7d\xc4\xe3\xe4\xf1\xe3\xdd\x7a\xf4\xec\xdb\x67\xf2\x64\x7f\x7f\x79\x6a\x43\x40\x49\xbc\xdb\xd1\x80\x1b\x72\xc3\x51\xd8\x0a\x35\x6e\x7f\xf6\xf8\xa3\xcf\xcd\xc9\x0d\x76\x40\x49\xa9\xdb\xd1\xa3\xf2\x8d\x80\x06\xdc\x0a\x5b\xdd\xc6\xdd\xfb\x49\x01\xb7\xed\x2d\x57\xdc\x81\xbc\x7f\xee\xf8\xb2\xa7\xb4\x4b\x88\xa0\xd6\x3f\x37\x1b\x40\xf7\x33\x63\x19\x62\xf1\xe1\x9e\x4c\xb8\x3b\x64\xc8\x84\x09\x43\x86\xdc\x9d\xf0\xe4\xc9\xdd\xbb\x4f\x44\x58\x8b\xff\xc7\xd5\x4f\x5f\xb3\xee\x23\xbf\x49\xcb\x3c\xb7\xcc\x4c\xbb\x30\xcf\x0d\x3e\xc5\x39\x7b\xd6\xcb\x8b\xd7\xaf\x77\x4f\x4e\x5e\xbf\x7e\xb1\xbc\x7e\x8f\xfb\xc2\x33\x13\xef\x8c\x6f\xc6\x4f\xf1\x53\xb7\x36\x48\xb2\xe2\xb6\x7e\x8f\x7c\x7a\xcf\x9e\xb3\x67\xee\xdc\xb9\x77\xef\xfc\x05\xb7\x59\xf9\x1e\x95\x93\x4e\x7c\xd4\xb8\x66\x6f\x7d\x53\xd5\xc1\xf3\x7b\x6f\xfa\xd1\xf2\xb3\xf1\xd0\x13\x7a\x3e\xbb\x27\x8b\x37\x1b\xcf\xaf\xab\x5a\x43\x2f\x84\xff\xe3\x70\x32\xf6\xc0\x1e\x38\xd9\x96\x42\x0f\x98\x0c\x93\xe1\xdf\xd4\x06\x17\x55\x1f\x18\xde\x55\x98\x8f\x3a\x1f\xc6\x55\x86\x5f\xf0\x17\x03\x79\x12\x7f\x86\x9f\xd9\x1a\xf6\xb6\x81\x14\xec\xf6\x4f\x09\xe4\xb0\x09\x13\x86\x49\x5a\x05\xa5\x85\xab\xac\xe6\xaa\x86\xa9\x1b\x55\x56\x75\x55\xc3\x45\xb5\x82\x7a\x3c\xf9\x8e\x97\x68\xf5\x6d\x3d\xcb\x85\x84\x94\xd4\x44\x4a\x5a\x1f\xd5\x8d\x88\xd8\x16\xbf\xb7\x5e\x7f\xbd\xb1\xf1\x7a\xdd\x9e\x84\xc8\x6d\x22\x3c\xc0\x6b\xf0\x00\xae\x11\x35\xdb\xf6\x94\xec\xe5\xaf\x37\xfa\x4d\x0b\x8e\x5b\x17\xb1\x49\xd2\x7a\x6b\x6e\x44\xe4\xa6\x90\x84\x10\xde\x45\xad\x33\x10\x5e\x67\x17\x9d\x73\x95\x0d\xed\x1d\xd8\xe5\x6c\x8d\x81\xf8\xaa\x3b\x27\x9f\x95\x65\x11\x3e\x51\xc7\xc0\x01\x73\xf7\xa7\xb0\xf2\xc8\x93\x2b\x17\x5f\xe5\x64\x9d\x70\x63\x97\x9b\xb2\xb5\xe5\xb9\xc4\x16\x39\x2a\x5e\x7f\xc4\xf4\x72\xf3\xde\xe1\xda\xcc\xd6\x6c\xb7\xc8\x73\xb8\x42\x5d\x1c\xf1\x05\x04\xa9\xb3\xdc\x4e\xdc\xfa\xf1\xf8\xf7\x39\xf4\x59\x6a\xb9\x09\x53\x65\xf4\x32\x99\x12\xb2\xc2\x4d\xf1\xd0\x39\xf3\xd4\xfa\xe0\xb1\x34\x5b\xb3\x08\x89\xf7\x71\x4d\xd4\xca\x19\xe0\xb6\xe2\xd5\x64\xe8\xbe\xee\xc6\xcd\x9d\x77\xb2\xe9\xd3\x94\x56\x94\x45\xb0\xcb\x23\xe5\xf8\x18\xfd\x5d\xd3\xef\x69\x07\xa6\x9f\xf7\x84\xa1\x5a\xa7\x73\x3d\x66\xe0\xbb\xd8\x1f\x8f\xcc\xed\x3a\x0a\xc6\xe1\x69\xf3\xb8\x51\x30\x39\xe8\x2b\x78\xf7\xc4\xed\x5c\x9a\xad\x39\xa7\x7d\x47\xc5\x66\x85\x25\xea\xd9\xe5\xbf\x65\x81\x80\x03\x1b\x3c\x60\xb4\xd6\x15\x26\x6a\x06\x18\xad\x49\xb4\xa9\xd1\x94\x95\x25\x82\x13\x44\x01\x07\x29\xd0\x1e\x36\xc3\x19\xeb\x74\x37\xdb\x8c\xd1\x62\x8e\x02\x17\xf3\xfb\x51\xaf\x5b\x1c\xe5\x16\xf3\x06\x70\x31\x27\xb4\x38\x59\xa6\x9a\xdf\xe3\x0e\xac\xab\x0d\x0e\x0c\x5f\xb7\x36\x68\x6f\xf8\xbe\x03\xb5\x7b\xf7\x89\xe5\xb3\xb9\xc4\x68\x6d\xba\xd6\x67\xc9\x72\xf8\x53\xfd\xda\xad\xa4\x46\x9d\xa6\xf6\x3a\x7d\x82\x86\x73\x5a\x2d\x77\x3a\xfd\x74\xf2\x29\x71\x4e\x3c\x91\x6e\x4a\xca\x2d\xd0\x17\x66\xe5\x2b\xd9\xe2\xa5\x12\x7f\x18\xd7\x0d\x3c\xb1\xf7\x4b\xf7\x84\xd4\x8d\xf3\xe2\xf8\xd4\xf4\xfc\x82\xc2\xfa\xd3\x05\x45\xd2\x5d\x24\xf1\xbd\xc3\xa8\xe7\x65\x6a\xe9\xd2\xf4\x94\x65\x52\xf9\x54\x22\x2d\x2b\x23\x29\x95\x4f\x4d\xcb\x2e\x34\x4a\xb1\x37\x71\x42\x00\x0e\xe8\xda\x03\xfb\xb8\x97\xa4\x34\x6e\x8c\xd3\xa7\xa6\xa5\xa7\xa6\x2c\xda\x97\x9f\x24\x4e\x40\x62\x15\xba\xa1\x5e\xbf\x38\x6f\x89\xb2\x44\xbc\x55\x4e\xe4\x67\x15\x65\xa4\xea\x53\x8d\x69\x29\x46\x71\x52\xec\x31\x9c\x08\x8e\x38\x00\x3c\x7a\xb9\x97\x28\x75\x97\xcb\xf8\x82\xfc\xb4\xd4\x94\x55\xbe\x69\x49\xd2\x64\x70\x06\x6e\x35\xbc\xc7\x9f\x3d\x9b\x57\x74\x46\x8a\xb9\x45\xe4\x99\x72\x8b\x0a\xf8\xc2\x7c\x53\x72\x96\x54\x31\x05\xc6\x1d\x07\x4f\x70\x78\x01\x7d\xdd\x13\x0a\x16\x6f\x2f\xd5\x17\xe4\xe7\x17\x14\x1e\x0b\x49\x2f\x12\x6f\x81\xd3\x41\xe0\xe0\x3d\xfd\xa3\x2e\xda\x2c\xb4\xa0\x45\x9b\x65\x4b\xc1\xa2\xce\x52\x67\xc1\xbf\xa9\x0d\x2e\xb6\x74\x69\x9b\x4f\x8e\x33\x96\xce\xb0\x95\xc1\x4a\x13\x16\x23\x83\xde\xb8\x16\xf6\x68\xa3\xdc\x6e\xc3\x42\x58\x0c\x0c\xac\x4e\x30\x6f\x59\xe9\x36\x06\xfa\xe2\x3b\xf0\x1e\x0e\x7a\x86\xef\x3f\xc4\x81\x47\xd0\xd3\x44\x5b\x13\xb4\x3e\xdc\x00\xec\x36\x17\x47\xe3\x54\xbd\xe6\x0b\xdf\x6b\x94\x3a\x76\xaa\x08\x5b\xd4\x79\xb8\x72\x25\x2e\x01\xb2\x1f\x7c\xe2\x8e\x4f\xcd\x1e\x84\x81\x1c\x8c\xa3\x39\x2d\x3b\x14\x04\xf4\xca\xc6\x18\xa4\x70\xa2\xbb\xd6\xc7\xea\x04\xa3\x92\x61\xec\x21\x18\xf4\xcc\x5d\x75\x83\x08\x18\xa4\xae\xc5\x41\x6a\x6f\xda\xfa\x75\x14\x87\x23\x91\x47\x1e\x47\xe2\x48\xe0\x91\x87\x91\x30\x12\x78\xb0\xa7\xc8\x03\x8f\x23\xed\xf2\x84\x81\xbc\xaa\x1d\x83\x77\x5d\x2d\xed\xeb\xd5\x4d\x7f\xb0\x87\xd8\x8d\x16\x1e\x15\x4e\x2d\x50\x39\x75\x8e\xea\x9d\x26\xa5\xa9\xde\xb8\x06\x6a\xf0\xc5\x2b\x98\x81\x7d\xfe\xc2\x82\x28\x8c\x58\xf5\x6a\xfc\xa9\x0f\x4e\x3e\x19\xf7\x35\x96\x0c\xc1\x71\x43\x70\x3c\xbe\x42\x3f\x2c\x86\xb5\xf0\x71\xec\xeb\xcf\xbe\x85\xce\xf4\xaf\xc9\x65\x17\x65\x3d\x7b\xa8\xf8\x64\xd0\x99\xa1\x79\x5e\x79\xcb\x3e\xc2\x4e\x91\xe8\x1c\x8d\x0e\xaf\x4e\x02\x09\xd2\x14\xb7\x58\x98\x4d\x00\x5b\x7b\xfa\xba\xac\x3f\x78\x2e\xe7\xca\xe6\x22\x9f\x5c\x74\xce\x1a\x57\x9b\xf8\x33\xb8\xc1\xf8\xcf\xcf\x60\xdf\x4c\xfc\x64\xf8\x6c\x74\xda\x52\xdb\x35\x3d\x6e\x73\x31\xec\x77\xc3\xfd\x58\x80\xae\xda\x3d\x18\x8c\x48\xe3\x03\xe8\x06\x97\x31\x52\xed\xc2\xdb\xe5\x22\xc6\x40\x7c\x17\xf5\x35\x30\x99\x82\x81\xb8\x6f\x20\x0c\x1c\x0e\x86\x6e\xb8\xf2\x31\x46\x67\xd1\x26\x93\x6c\xe2\xb5\x14\xad\x87\xd6\x43\x4b\xd1\x36\xa9\x2e\x9a\x41\xdd\xb0\x49\x32\x95\x95\xcb\x65\x3c\x6c\x86\xd5\x8f\xe1\x7d\x18\x2c\x4d\x7c\x1f\x3b\x06\xe0\x7b\x3c\x06\xa1\x0f\x38\xc2\x70\x74\x93\x3c\xa0\xc3\x14\xf8\x38\x1d\xfc\x68\x59\x3e\x26\x8b\x79\xe0\x77\x13\x3e\x6e\x81\x0e\x34\x0c\x07\x37\xb0\x61\x05\xf1\xf0\x1e\x74\x0c\x98\xf8\x5a\x82\x0b\xd6\x81\x1c\x94\x60\x3b\x88\xc3\x09\x30\x5c\x3c\x36\x69\x4c\xed\x47\xfc\x80\xa1\x21\x7e\x63\x24\x58\xe6\x0d\x7d\xb0\x08\xbf\xd4\xe3\x65\xec\x8b\x45\xb8\x6c\xac\x38\xf7\xc1\x4f\x21\xbf\xf0\xdf\x7e\xb5\xad\xe1\x96\x04\x93\x60\x38\x38\x43\x3c\x94\xe9\x5d\x6a\x30\xf5\x9a\xd9\x0b\x36\x9a\x3b\x46\x3d\x7d\xe9\x28\x83\xce\x40\x7e\x74\xc2\x29\x46\x50\x5b\x38\x30\x04\x02\x3f\x15\xde\x11\x0f\x3f\x3e\xf4\x77\x8b\x1e\xa6\xa3\x74\x15\x87\xa1\x01\xc7\x7e\x32\x07\x3b\x89\x59\xb1\xb1\x72\x2c\xaf\xbd\x83\xdf\x62\x89\xd6\xee\x43\x09\x1c\xc0\x05\x3e\x82\x8f\xc0\xf3\x06\xce\xc1\xd1\x38\x0c\xd7\x62\x47\x0c\x5f\xef\x37\x1d\x99\x98\xd9\x74\xd8\xe0\xa8\xfe\xfd\xf5\xe8\x75\xbb\x3b\x8c\x82\xce\x30\xe8\xcb\xcf\xc1\x59\x9c\x0b\xed\xa0\xe3\x7a\xe8\xc8\xc3\xaf\xf0\x05\x04\xc3\x7d\x20\x25\x6d\x24\x89\xc4\x14\xec\x3c\x1d\xbb\xf0\xe8\x8b\xe3\xa1\x3b\x2c\x92\x0c\xce\x09\x64\xde\xfe\xec\x03\x07\xf4\x13\xcd\x3a\x6e\x62\xe8\xc8\xb0\xa9\xe2\x00\xe8\x8d\x12\xd0\x38\xec\x1a\x7d\xf0\xab\xdf\xf7\xff\xc8\x43\xbb\xef\x26\xa1\xb3\x64\x30\x7f\x69\x40\x0f\x0e\x1c\x2e\x80\xee\x54\x8b\x78\x15\x27\x83\x2b\x7a\xc2\x87\x1e\xf4\xf2\xd1\xbd\x03\x06\xf3\x48\x4e\xba\x06\xb4\xa4\x66\x99\x97\x70\x30\xb7\x00\x46\x83\x04\x3e\x3c\x7c\x02\x1f\xa3\x84\x73\x0b\x24\xeb\xba\xb7\x26\x90\x3a\xd0\xa9\xb4\x00\xd1\x36\xdd\x58\x67\x88\x11\xa0\xa1\x42\x80\x3a\xc6\xe2\x4b\x55\x96\x97\x57\x8a\x06\xd2\x1b\x42\x05\x83\xd9\xfe\xe9\x75\x8d\x60\x8e\x40\x1d\xbe\x1e\xc4\x98\x9b\x83\x04\x7c\x0d\x3a\x73\xc4\x35\xa6\x26\x40\xd8\xf6\xd4\x40\xba\xfd\xe1\x04\x22\xf4\x65\xa6\xcf\x9b\x37\x5d\x32\x58\x7e\xa5\xa6\x5f\x98\xd7\x24\xc2\x0e\x12\x3f\x80\x41\xfe\xb0\x7e\x21\x6c\xfe\x04\x0e\xcc\x80\x72\x18\x00\x29\x87\x2e\x1d\x3b\x77\xfa\x38\x6d\xc9\xe8\xd2\x3c\xee\x8a\xc7\x29\x64\xb4\xc0\x5e\x6e\xf3\x5f\x8c\xfe\x01\x3d\x83\x3f\xdc\xfc\xe9\xa2\xb0\x79\x21\xd3\x63\xc7\x37\x63\xcb\x3d\xfc\xfd\xf8\x27\x17\x97\x9c\x58\x75\x27\xea\x51\x15\xf4\xab\x3f\xfc\x26\x1f\x9c\xd4\xa0\x57\x6e\xc5\x98\xe9\x8d\x73\xd0\x0d\xdf\xa3\x61\x12\xd9\x74\xe1\x42\x93\x64\x20\xdc\xa8\xa6\x79\x17\xa6\x8b\x2e\xa8\xbc\x06\x67\x70\x98\x16\x09\xab\xc1\x41\x8d\x05\x27\x70\x05\x87\x37\x7f\x3d\x84\x76\xae\x65\x7f\x43\x9f\xbf\x7f\x82\x76\x6a\x1c\x38\x41\x47\x70\x4c\x2f\x65\x2f\x44\x1b\x88\xcd\x89\x5c\xa1\x52\x50\x11\xbc\x8f\x96\xa9\xf8\x92\xc4\xc2\xe4\xec\xa4\x9c\x14\x63\x6a\x6a\x5a\x9a\xdb\xb4\x69\x63\xe6\x7f\xb8\x86\x5e\x3d\xa4\x7f\x74\x3f\xde\xa3\x7f\xf5\x21\x2f\x69\xd8\xc1\x31\xe7\xa7\x5d\x9f\x7c\x6b\xfe\x83\xb5\x0f\x83\xbf\x4d\xba\x9c\xb1\x95\xb6\xfb\x91\x17\x33\x6a\x23\xb3\xd7\xa5\xc7\x1b\x57\xa6\xe5\x6e\xa0\x65\x4a\x99\xb6\x75\xc6\x8e\x59\x0d\x7d\xbf\xf4\xfa\x6a\xec\x7d\xef\x27\x3e\xcf\xfd\xe9\x15\x2f\xdf\x6c\x82\x76\x3c\xb4\xfb\x67\xdb\xb1\x57\xd2\xf3\x86\x9f\xbe\xfc\xea\x2b\x5a\xce\xcd\xcd\xce\x16\xb5\x75\x2a\x72\x65\xe5\xf1\x95\x09\x25\xd1\xd5\x9b\xf3\x12\x13\xa7\x4d\x73\x9b\x76\x83\xc8\xc9\xc8\xc8\x4e\xe7\x93\x93\xd2\x12\x12\xa4\xa8\xa8\xf4\xb8\xe2\xc4\x1b\x53\xdd\xa6\x4e\x23\xd2\xd3\x32\xd3\xd3\xf4\x09\xc5\x89\x05\x69\x62\xb6\x91\x48\x2c\x2e\x4e\x57\xf8\xc2\xbc\x9c\xec\x6c\x29\x2f\xef\xd2\xa5\xbc\xbc\xab\xb3\xdc\x52\xf3\xf3\x33\x0b\xf8\xa2\xe2\xfc\xe2\x62\x69\xd7\xae\xf8\xf2\xd4\x82\x19\xd7\xdc\x6e\xdc\x20\xd4\xe0\x39\xdc\x77\x31\x0f\x42\x9a\xc5\x90\x3b\x2b\xae\xce\xbd\x38\xf7\xe2\x8c\x63\x13\xeb\xe8\xbd\xe3\x3f\x2e\x1f\xc5\x8f\x1c\x19\x13\x32\x41\x9a\x13\xde\x77\xe6\xa7\x3e\xb4\x49\x8d\x32\x5f\x20\xeb\xe4\x86\xb2\x52\xf9\x58\x88\xd4\xea\x48\x86\xc7\x45\x6d\x96\xac\xa3\xa8\x4d\xbb\x62\x77\xa4\x89\xe7\x12\x8b\x2b\x4a\x2a\xb3\xb3\xdd\xaa\x77\x7d\xfe\x65\x56\x16\xfd\xf4\x29\xbc\x7b\x0e\x38\x1e\x38\xe8\xb0\x60\xd0\x53\xe9\xd9\xc0\x73\xd8\x01\x75\x7a\x64\x17\xe0\xbb\x83\x06\x89\xec\x85\xd7\x83\x07\x63\xa7\xf9\xa8\xe3\xbd\x86\xd7\x9e\x18\x2f\xa9\x83\xa8\xcf\xb6\x5f\x3e\x7a\x52\xbc\x70\xea\xda\xee\xdb\xfc\xcd\xab\x61\x4b\x4e\x49\xa7\x96\xee\x9c\x35\x4d\x8f\x22\x3a\xa2\x03\x4a\x62\xe8\xc2\x12\x23\xbf\xa1\x30\x61\x55\x46\x7c\xec\xc2\xda\xa4\x3c\x23\x1d\x7f\x62\x4f\xe6\x11\x1e\xe6\x81\x17\x0c\x81\xf9\xe0\x87\x43\x60\x30\xce\xf7\x18\xb4\x7a\xea\x14\x69\xda\x8c\xc0\x61\xc6\x0f\x69\x23\x95\x24\x63\xd6\x47\x7a\x13\xb9\xa6\x61\xf5\xd5\xf0\xa6\xe4\x1d\x9b\x32\xd6\x27\x27\x64\x04\x24\x28\x1b\xe8\x2c\xd2\xa8\x84\xe5\xc7\x8b\x7b\x26\x1e\x9b\x79\x71\xee\xc5\xb9\xd7\x56\xdc\x09\xa1\xd7\xdd\xfb\x3a\xf6\x5b\xfe\xdb\xaf\xcb\xf7\xde\x93\xee\xd4\x5d\x3b\x76\xf1\xe2\xc5\x8b\xc7\xae\xd6\xdd\xa1\xeb\xee\x55\x7c\xfd\xad\x7e\x9d\xfa\x0d\x37\xf9\xba\xf7\x99\x01\x47\xe8\x63\xbd\xba\x6e\x43\x47\xfe\x7d\x74\x8e\x5c\x33\x42\x4a\xce\x4c\x4f\x35\x26\x99\x92\x73\xe2\xf3\x63\xf2\xe2\xcb\x82\x76\x16\xd1\xf5\x3f\xfe\x5a\xf9\x88\x6f\xf9\x75\xf3\xaa\x9f\xa4\x3b\xeb\xaf\xaf\xb8\x37\x93\x4e\xcf\xcb\x33\xe6\xf3\x65\xa5\x65\x25\x25\x12\xfb\x63\x74\xf5\xb6\xd2\xaa\xe8\xca\x36\x05\xb9\x1f\x24\xdf\x8c\x82\x02\x55\x80\x99\x50\x07\x26\x57\xf8\x1b\x7e\x83\xa7\xf0\x04\x6e\x3e\x66\x7f\x34\x90\x1d\x2f\x73\xd6\x28\xfc\x4b\x5b\x0a\xa7\xf0\x14\x4c\xda\x5c\xb2\x2e\x6e\xd7\x3a\x1a\x99\x3f\xa0\x19\x8f\xa8\xc3\x78\x75\x18\x64\x43\xf4\xd1\xbd\xd2\xde\xa3\x11\xb5\x21\xb1\x34\x04\x00\xc5\x45\xed\xec\x99\x3b\x23\x75\x46\x8a\xc7\x4a\x25\x82\x66\x2f\xe4\x26\x2b\xb9\xc7\x73\x4f\xe4\x82\x4b\xc5\xce\xb5\x3b\x83\xa6\xa1\x57\x42\x68\x42\x68\x45\xea\xb6\x2a\x9a\xfd\xb1\xa6\xf2\xf0\x89\x9d\xd7\x68\xf6\xc2\xce\xa6\xf2\x27\xb1\x5b\x69\x4d\x54\x3f\xe1\xd4\xc7\xd4\xab\x3e\x10\x8d\x7f\xe3\x6b\xfc\x04\x37\xe2\x02\x11\x4e\x6f\x24\xae\xc3\x42\xe8\x27\xcb\x7a\xe8\x97\x84\x1d\x37\x4a\xc8\x52\x38\x2f\x55\x8b\xf2\xd5\xfa\xe9\xd9\x1f\xb5\x69\xea\xb9\xcd\x30\x15\x0e\x8a\x05\x89\x85\x09\x45\x49\xb4\x7c\x73\xe2\xcf\x1f\x8a\x10\x05\x11\x84\x8c\xdc\x2b\x68\xa7\xb7\x7a\x45\x72\x30\x1b\x96\x1e\x06\x3e\x57\xc4\x61\x14\x36\xe3\xd3\x33\xb0\x4c\xef\x02\x5e\x8c\xea\x6b\xb7\x7a\xf1\x82\xd7\x17\xfe\x5d\x45\x03\x3a\xf8\x47\xf0\x61\xe0\x9a\x80\xba\x16\x32\x94\xd1\x74\x2d\x54\x28\x83\x3a\xca\x5f\x88\x10\x36\x0b\x46\x81\xfa\xd6\x06\xe3\x60\xa7\xd0\x43\x10\x4b\x99\xb2\x2a\xc9\xaa\x40\xc3\xff\xe6\xd3\x19\x03\x7a\x73\x06\x4b\xa2\x45\x89\x10\x48\xab\x4e\xf3\xe5\x20\x02\x66\x30\x18\xf1\xff\x2e\x08\xfb\x6f\x37\x4c\x4c\x3a\xa3\x7a\x41\x57\xa6\x55\xd1\x22\x3e\x10\xc0\x8b\xb1\x28\x26\xc6\xd2\x02\x1e\x5c\xdb\x42\x0d\xf4\x01\x1f\xdb\x8c\xe5\x63\x0f\x31\x57\xe2\xbe\xe4\x54\x82\x3d\xca\x9c\x3b\xfa\xd8\x36\xf0\x81\x0f\x18\x98\x8d\x3e\x38\x1b\x7d\xa0\x54\x00\x1f\x98\x0d\x3e\x38\x1b\xea\x04\xa2\x35\x18\xeb\xff\x25\x69\x20\xde\x53\x6f\xb7\xc5\xa9\x2b\x59\x72\xca\xad\x8d\x88\xe6\xa3\xf9\xb8\xe1\x46\xd8\x68\x23\xd2\x80\x0d\xa5\x09\x5b\xe5\xd2\x12\x77\x55\x51\x15\xc2\x80\x41\x56\x9f\x0f\x84\xe3\xb6\x8e\x6e\x65\x20\x85\x31\x98\x13\x07\x08\x06\x32\x71\x20\x63\x70\x4e\x84\x2a\x46\xed\x08\x55\x8c\xa5\x63\x34\xe3\x62\x4d\x30\x10\xcb\xe1\x99\x00\x11\xa0\x38\xa9\x8a\xea\xcb\x2d\x5b\x9e\x57\xe4\x2f\x59\x3f\xc8\x15\xcc\x1f\x50\x49\xfe\xcb\xd3\x97\xf1\x96\x66\x67\x20\x18\x3c\x08\x9b\x71\x33\x1c\x84\xd9\x0c\xa4\x32\x12\x46\x38\xe3\x10\xe4\x90\xc3\x21\xf0\x3d\x03\x7e\x30\x18\x06\x83\xdf\x0c\xa6\x97\xe0\xf2\x9a\x31\x2b\xa0\x38\x19\xc8\x3b\x06\xe7\x07\x1c\x76\x83\x6e\x44\xd5\xe6\xb0\xa2\x30\x5e\x53\x9a\xc8\x41\x02\x0c\x12\xa4\xe9\x5a\x33\xe5\xc9\x48\xa8\x0c\x10\x60\x0a\xb3\x63\x47\x51\x55\x95\x04\xdd\xa0\xdb\x9f\x82\x7b\xeb\xaa\x56\x0f\x4e\x53\x72\x05\x55\xa1\xd4\x66\xd5\x97\xd3\x9a\xc1\x17\x15\xf4\xd5\x14\x32\x2c\x2c\x69\xf3\x66\x09\xbb\x61\xb7\x67\x82\x3b\x74\xc3\x6e\xe0\x27\x18\x08\x6f\x18\x29\xb8\x40\x5d\x85\x3d\x46\x9f\xda\xd0\xa4\x36\x37\xa9\x0d\xf6\xd0\x35\xf6\xf0\xa6\x9b\x4b\x36\x65\x47\xa5\x68\x1a\x9a\xdc\x34\x0d\x4c\x31\x05\x31\x72\x4c\xaa\xbb\x55\x87\x0a\x11\x9e\x1c\x13\x1e\xaa\x37\x58\x12\xa9\xc8\xe2\xa8\xca\x04\x31\xb5\xb8\x24\xa3\x94\x2f\x2c\xcc\xca\x2d\x94\x54\x0d\x4c\xaa\x86\xa6\x8a\xd4\x0a\xb9\xa2\xc0\x5d\x75\x14\x88\xed\x4a\xc5\xf6\x9d\xfa\x08\x81\xaa\x49\xdc\xba\xa5\x44\x34\x58\x34\xe4\x39\xb5\x19\xb7\x10\x06\x64\x28\xad\x19\xb6\x10\xda\x6b\xcb\x61\x4e\x6d\x80\x90\x36\x50\x03\x86\x10\x31\x02\x2c\xe7\xec\x47\x06\xe7\x37\x94\xbd\xcc\xe5\x38\xa3\x2a\xb0\x95\x69\x64\x0c\xce\x8f\xba\x34\x32\xad\xaf\xbb\x4c\x12\x24\xf8\x41\x48\x28\x48\x2c\x4e\x13\x55\x05\x15\xc2\x98\x9b\x67\xca\xe3\x3f\x66\x0c\x44\x23\x55\x92\x5a\x9c\x98\x2f\x6a\x0a\x28\x44\x76\x46\x7a\x56\x3a\xef\x52\x53\x13\xe9\x68\xd6\x01\x30\x66\x9d\x59\xc7\x41\x08\xf3\xf6\xf7\x46\xeb\x01\x47\xb4\x14\x9b\xe8\x85\x47\xf0\x0d\xce\x03\x17\x1c\x07\x9f\x62\x7b\x31\x14\xd7\x78\x2f\x9e\xe1\x93\x90\x98\x90\x94\x1b\x43\x03\x2d\xe4\xc6\x96\x27\x56\x64\xd7\xe5\xec\xc9\xdb\x95\x07\xde\x87\xa0\xcf\x37\x40\x02\x49\x27\xdc\xbc\x9b\xd6\xcc\xab\x29\x6a\x0f\x38\x02\x6f\x24\x97\x9a\xb6\x35\x42\x8a\x3d\xa0\x94\x0e\x14\x58\xce\x80\x4e\xf7\xc8\xde\xee\x38\x41\xd5\x75\x79\xbb\xd3\x14\x55\xd9\xcd\xc0\x3f\x5a\x0f\x38\xaa\xa5\x88\x32\x65\xef\xc3\x51\xfc\x67\x2b\x63\x4d\x40\xd9\x40\xbe\x70\x94\x2d\xb6\x9b\x0c\xfe\xe0\xb4\x9f\x29\x55\x81\xb3\x84\xfa\x84\xd2\x14\x3c\x43\x68\x0a\x9c\xe1\x64\x4a\x55\xf0\x8c\xa6\xa0\x1d\xae\x2a\x96\x77\x38\x7b\x46\x7b\xf2\x5f\xe4\x27\xce\xea\xdb\x72\x7b\x3d\x97\x1a\x03\xe1\x1d\xe5\xf8\xd0\x40\x2e\x76\x32\x90\xfb\x2d\x39\x5c\x11\x04\x8e\x02\x47\x1c\x99\x87\x91\x05\xe8\x89\xec\x48\x2c\xa7\x2b\x8f\x1d\x55\x8e\xf0\x0f\x0f\x2e\xe9\x9f\x2c\xa5\x7f\xba\x66\xc4\x64\x74\xa0\xd1\x61\xd2\x7c\xbf\x20\x7e\xd9\xca\x1f\xe0\xa3\xd5\x52\xc2\x99\x08\xe8\xbc\x0e\x16\x87\xc0\xcc\x8f\x1f\x23\x9b\x30\x37\xfd\xa3\xc5\xdd\x3c\x47\x4d\x1a\x35\x7e\xe4\x84\xaf\xfb\xb8\x9d\x6f\x3e\xb6\xa3\x84\xbf\xd4\xe8\x85\xe3\xcf\x48\x27\x70\xa8\xfd\xe7\x45\xe3\xf8\xeb\xdf\x0d\xf9\x9d\x87\xfe\x30\x0b\xba\xc3\x51\x08\x93\x60\x2d\xec\x01\x27\x08\x29\x80\xc1\xb4\x0b\xea\xa0\xbd\xc1\xf9\x36\x7c\xf2\x33\x03\xe7\x05\x6d\x5e\xeb\x4b\x0e\xef\xe0\xe7\x78\x07\x3e\x87\x50\xf3\x3b\x18\x0a\xe7\x08\xb3\x0b\x89\xa1\x78\x8e\xb0\x21\x47\x98\x75\xcf\xfb\xc2\x6c\x28\x81\x08\x57\x19\x1a\xa0\x01\xde\x3d\x62\xe3\x75\xd0\xc0\x5e\x80\xf3\x82\x95\xc6\x66\xee\x77\xb2\xb1\x85\xa8\x27\x1b\x3d\x88\xdf\xc9\x92\xb5\xde\xc3\x09\xf6\xc7\xbd\x48\x86\x85\x75\xfd\xbc\xeb\x9c\xb0\x1d\x7b\x81\xf4\xfe\x81\xc0\x42\xec\xc2\xcd\x30\x06\x7d\x22\x8d\xa4\x52\x12\x52\x8b\x44\x88\x21\x57\xa1\x8e\xc0\x4f\xb5\xf7\xc8\xa8\xd4\xcc\x2a\xa3\x08\x7d\xe2\x88\xa1\x9a\xef\x13\x8a\xbd\xd0\x5c\x40\x54\x65\xe7\xe5\x57\xeb\x55\x57\xaa\x30\x49\x4e\x12\xc7\x80\xae\xe5\x1e\x09\x1f\x3f\xbb\x03\xe3\xa0\xfd\xeb\x0d\xe8\x29\xe2\xb8\x48\xa2\x29\x2b\xa6\xdc\x9f\x57\xff\xb6\xde\xe1\xf0\xf5\x63\xf2\x8e\x42\x54\x65\x17\xe6\x56\xeb\x55\x92\x2a\x4b\x52\xe2\x73\xc5\xe1\xdb\x6a\x5f\x11\xb0\x5b\xab\x24\xa3\x92\x8d\xd5\x99\xe2\xc5\x64\xc2\xa5\x06\x07\xc2\x1c\x18\x0e\x1f\xc0\x40\xc1\x3c\x89\x83\x76\x83\x7f\xc6\x76\x9f\xce\x8f\x58\xb5\x46\x44\xc3\x6f\x38\xed\x32\x2e\xc9\xff\x5b\x5d\xe7\x06\x3f\x8d\x25\x46\xdc\x9c\xf2\xf0\x87\x9b\x37\x7f\x78\x38\xe5\xe6\xf0\xd9\xf3\x83\x16\x85\x8b\x1a\xf1\xfd\xe6\xdc\xe8\x84\x8c\xcd\xee\x48\x6b\x55\xb8\x38\x15\xa7\xcc\x42\xde\xd3\xfd\xc8\xea\xf9\xdb\xe7\xf0\xd8\x6e\xf0\x60\x6c\x37\xea\xd4\xe4\x9b\x6b\xa5\xd4\x90\x8c\xe0\x60\x3d\xde\x06\x33\x2a\xea\x74\x75\x06\x98\x41\x81\xdb\xfb\x32\xea\x53\xf6\x8a\xd7\xf7\x9d\xb8\xf9\x8d\xde\x60\xa9\xc5\x45\xdc\xc3\x9b\x37\x1f\xfe\x70\x73\xca\x88\xe1\x53\xa6\x0c\x1f\x31\xe5\xe6\x0f\xa2\xf9\x3c\x02\xd7\xaf\x1f\x4e\x4f\x9d\xcb\xcf\xc5\xe9\x05\xbf\xf7\x93\x62\xcb\xe5\xda\xf2\xb2\xb2\xb2\x5a\xb9\x2c\x8e\x9e\x75\x19\xb8\xc8\x5f\xf8\x5f\x80\xab\xb9\x72\x59\x6a\x03\x96\xc7\xca\x9b\x62\x63\xe9\x4c\x58\xc1\x0d\x9f\x72\xf3\x87\x87\xb6\x3e\xb7\xd1\x1c\x21\xb9\xd4\xa8\x69\x70\x57\xed\x08\xbf\xbb\xde\x36\x90\x91\x06\xcb\x22\x68\x66\x1f\xb1\xb7\x6f\x9b\x37\x73\xe0\x09\x61\x50\x0b\xeb\x55\xa6\x94\x96\xd5\xae\xf2\x6a\xad\xa3\x68\xed\x48\xd6\x02\x7f\xe2\x9b\xcf\xef\xe1\x76\x74\xc5\xd1\x18\x9a\x8b\x8f\x73\xb0\x18\x26\x61\x15\x14\xf6\x81\x8b\x48\xa9\x5d\x7e\x86\x31\x7f\xd1\xea\xbb\x14\xfb\x08\x4f\xe2\x72\xeb\x88\x98\x74\x75\x25\x6d\x31\x83\x0f\x09\x43\x36\x40\xcf\x31\x20\x88\x50\x85\xbd\x31\x1f\xba\xe3\x65\x5e\xcb\xc9\xc2\x83\x9a\xeb\x3c\x6d\x30\xed\xa2\xd6\xa1\xee\xb0\xfd\x93\x8c\x53\xbd\xf3\x5b\xab\xc8\xc6\x85\x8c\xfa\xda\x00\x0e\x94\x59\xa7\xe9\x38\xd5\x6e\x9a\x66\x77\x4a\xc0\x81\xdd\xff\x01\x69\xa0\x96\xc3\x35\xc1\xa0\x7a\x2f\x61\x30\xc2\xd0\xde\x01\x22\x40\x12\x6c\x62\xc8\x5f\xe6\xfd\xe0\xab\xfe\xf1\x97\xa3\xfc\x97\x81\x70\x6f\x71\x32\x90\x03\xc1\xc4\xa1\x8c\xdd\xb0\x02\xfb\xe1\x21\x5e\x9b\x86\x00\xa0\x4e\x53\xa7\x81\x3d\x85\x6d\x90\x8d\x3c\x46\x42\x2f\x09\x83\xb1\x33\x01\xdd\x7b\xe2\xf0\x47\x38\x9e\xc7\xf3\x98\x86\x69\x78\x1e\xcf\x41\x1a\xa6\xc1\x79\xf0\x81\x71\x7f\x80\xd7\x1f\x12\xac\x47\x27\x42\x3b\xaf\x76\xe3\xcc\x5e\xaa\x40\xc0\x97\x38\x1c\x8f\x83\x1f\xbe\xfe\xaf\x32\x99\xa2\xf6\xd0\x7a\xa8\x29\x2a\x69\x57\x96\x1e\x41\x3f\x09\xa7\xc0\x9f\x1c\xb8\x24\x81\x2f\x3a\xf1\x68\xc0\xd7\x2d\xe0\x45\xda\x58\x83\x6f\x94\x63\xbd\x81\x6c\x74\x32\x10\x85\xe6\x5b\x1c\x3c\x56\xf7\x13\xd6\x16\x72\x00\x7a\x10\x5a\x3f\xab\xc4\x59\x62\x20\xc6\x80\x2b\xcc\x31\x84\xf5\x05\x65\x70\x3e\x5a\xcd\x69\x9c\xd6\xaa\xee\xc1\x27\x84\xf9\x05\x85\x33\x80\xe6\x5a\x63\x30\x06\x55\xed\x16\x61\x6e\x21\x5d\x6a\xcc\xca\x5b\xb9\x63\xf4\x29\x18\x0d\xff\x08\x66\x9d\xba\x83\x03\x86\xe9\x02\x0c\x13\xcc\x5d\x61\xd0\x19\x75\x66\x67\x78\x47\x80\x49\x0c\x55\xb3\x21\x3d\x5e\x04\x77\xaa\x60\xcf\xde\xbc\xba\xc3\x07\x62\x0f\xf1\x15\xdf\xe7\x6e\x97\x60\x35\x25\x33\x9b\x03\x63\xd7\x05\xad\x2c\xf7\xe7\x37\x6c\xc8\x48\xdb\x28\x55\x52\xd5\x4a\xe9\xd6\x1a\xbb\xef\xb5\x90\xb0\xb0\x90\xc8\xd2\xa8\xea\x64\x51\xe3\xa9\xf8\x0d\x79\x91\x12\x4c\x62\xe0\x1d\xc1\xea\x8c\x3a\x70\x86\xa9\x8c\x35\xd5\xac\x83\x66\xaa\x45\x10\xb1\xd9\x6c\xb7\x48\xaa\x89\x84\xa7\xc2\x5b\x6b\x64\xfa\x95\x79\x03\x87\xcd\xe0\x9b\x9c\x1f\x9f\x95\x94\xe6\x9e\x94\x96\x96\x94\xa0\x47\x5d\xeb\x0b\xaa\xfe\xdc\xae\x2f\xb7\x5f\xa2\xc1\xe1\xcc\x59\x70\xba\xc3\xbf\x21\xbd\x77\xdd\xf1\xfb\x91\x87\x62\x61\xe8\xe3\x6e\x6d\x86\x48\x5d\x49\xf4\x9c\x84\x83\x50\x9c\x29\x75\x5d\xbc\x10\xdb\x4d\xe6\x3f\x20\xa1\xdd\xfa\x5e\x0f\xf1\x1d\xfe\x3f\x16\x08\xf0\xce\xcb\x87\xd0\x6e\x8f\x04\x1a\x79\xeb\x2c\xb6\xeb\x7a\x5a\x42\xf1\xea\x6d\x1c\x04\x9e\x7c\x8b\x07\x1c\x17\xc0\x97\x81\xe6\x4f\x05\x6c\xee\xcd\x78\x78\x50\x13\x17\x82\x13\x38\x2c\x92\xc2\x2f\x6d\xfc\x32\xf8\x1c\x6d\x7e\x81\x3a\x32\x21\x3f\xa9\x28\x4d\xcc\xcc\xcb\x37\xe5\xf1\xf9\x79\xd9\x39\x79\x12\x34\x83\x2f\x51\x94\x97\x5f\x5c\xac\x2f\x4e\x2b\x4e\xca\x13\x5d\x6a\xcc\x3a\xd8\x96\x29\x18\x9c\xe3\xcd\xe5\xdc\x57\x9f\x5c\xf6\x16\x65\xcc\xc7\x6d\x90\x2f\x53\x5f\x5d\xbe\x7c\x5f\x82\xc9\x5d\x70\x2c\x76\xc5\xae\x38\xae\xad\x04\xa7\x58\x74\xea\x44\x99\x82\x71\x60\x87\x4a\x6a\x00\xea\xff\xfd\x00\xd1\x02\x9e\x6a\x01\x0c\x80\x3c\xf0\x74\x94\xc1\xd3\x40\x34\x83\xe7\x73\xf0\xfc\x0b\x3c\x9d\x0c\x64\x88\x3a\x8d\xfb\x60\xd8\xb0\xf7\xc5\xd6\xbd\x24\x76\x43\x0a\x48\x9b\x28\x02\xf6\xf4\x56\xd3\xc6\x45\x67\xa4\xba\x90\xb3\x72\x5d\x5d\x5d\x9d\x7c\x36\xa4\xce\xef\xc2\xb4\x83\x13\xab\x68\xf0\xba\x07\xc3\xde\xc0\x14\x1e\x72\x61\x39\x2e\xc7\x9c\x85\x29\x8b\x62\x97\x48\xf1\x01\x35\xcb\x1b\xe2\x68\x63\x61\xa1\xa9\x90\xaf\xaf\xdb\x5a\x5f\x24\x15\xd5\x15\xee\xcd\xdb\x4b\xdf\xd9\x78\x7e\xf2\x48\x3d\x78\x76\x81\x0f\x91\x06\x01\x3d\xf7\x89\x70\x39\x04\x4b\x21\x0d\x6f\xf1\x58\x86\x31\x38\x0a\x33\x87\x4b\xb8\x60\x3d\xf6\xc3\xd1\xb8\x42\x8f\x9b\x60\x3a\x4e\x87\x48\xd1\xb2\x97\x84\xd9\xd0\x1f\x3c\x61\xb6\x04\x39\x5d\x80\x5c\x0b\xed\xa6\xff\x26\x86\x1f\x58\x54\x14\x18\x1e\x18\x9e\xbc\x78\x7b\x20\x7d\x7a\xd2\xf6\x8f\x86\xeb\x3f\x0c\x1f\xb9\x78\x92\x18\x1e\xa8\x2c\x3a\x10\x41\x27\x97\x96\x67\x94\xf3\x32\xb5\x63\x7b\xf1\xb6\x72\xa9\xe9\xf7\x7d\xd0\x0e\x48\x3d\x28\x5d\x60\xc8\x12\xf0\x1c\x02\x5d\xc4\xf0\x83\x8b\x95\xc0\xf0\xc0\x88\xa4\x45\xdb\x03\xe9\x3b\xef\x1f\xc6\x4e\x36\x45\x4c\xb7\x0a\x3b\x4d\xec\x26\x86\x07\x16\x2d\x3e\x10\x6e\xa7\x52\x66\xa7\x52\xb2\xad\x5c\x7a\x02\xef\x9d\x02\x4f\x18\xa2\x77\x41\x05\xae\x1a\x9c\x6b\xe0\x82\xe3\x41\x03\x71\xd2\xc9\x40\x7c\x1f\xcf\x41\x07\x8f\xe7\xd8\x01\x3b\xf4\xed\x8b\x1d\xf0\x9d\xe7\x7d\xa1\x03\x74\x68\x79\x0e\xef\x88\x18\x07\xfb\x39\x98\xb9\x05\x96\x68\x01\xd0\x5f\xc4\xcf\x5e\x6e\xfc\xf1\x96\xfe\x66\x13\xb4\x83\x1e\xa2\x0c\xdd\xe5\x7d\xab\x45\xdc\x0b\x33\x2b\xcf\x9d\x07\xe1\x28\x0c\x85\xa1\x38\x18\x12\xb4\x0f\xb5\x0f\x71\x14\x16\x62\x1e\xe6\x42\xbb\x9e\x70\x12\x45\x11\x4e\xa2\x00\xba\xb9\xe8\xa4\xc7\x76\x48\x8e\x45\x0f\x51\x46\x0f\x79\xfa\x65\xb1\xf6\xb4\xbc\x5f\xd6\xef\x0b\x85\xa1\x36\xe1\x3a\x04\x47\xce\x5f\xf0\x83\xd6\x41\xdd\x03\x23\xc1\xa5\xee\xcc\x53\x31\xb2\x21\xe1\xcc\x59\x3d\x0c\x06\x06\xba\x40\xbf\xad\xa2\x4b\x80\x60\xf6\x05\x9d\x93\xd9\x17\x5e\x73\x1f\x31\xa8\xf4\x13\xd4\xe6\x45\x02\x28\x73\x18\xad\x99\x52\x7d\xbb\xfc\xbf\x30\x1d\x34\x70\x5d\x99\x68\xbb\xb0\x6c\x97\x84\x22\xca\x84\x16\x88\xe0\x80\x11\x34\x5d\x17\x60\x04\x97\x55\x8c\xa5\xd9\x4e\x4e\x6b\x6e\xab\xaa\x36\xbf\x25\x67\xaf\x6a\x9b\xe4\x2d\xcd\x6d\x0e\x37\x2d\xcd\x65\x02\x36\x40\x04\xa7\x36\x43\xbc\xf0\xa9\xa0\x35\xf7\x66\xb4\xe6\xee\x82\x4b\x4d\xc4\x5b\xaf\x15\xcf\x18\x27\x03\xf9\x10\x74\x9c\xc1\x3c\x89\x0c\xc4\x1b\xc6\xcd\xf9\x9b\x4b\xe2\xdc\xe3\x4b\xaa\x52\xaa\x78\xa8\x11\xaa\xaa\x0a\x4b\x4b\xa4\x92\xb2\xfc\x2a\x63\x15\x8d\x3a\xb8\x22\xd4\x67\x6c\xdc\xb1\x96\x47\x05\x75\xa4\x8f\x20\xb6\xb9\x99\xa1\xec\x47\xa8\x50\x6b\x37\x86\x05\x67\x48\x43\xad\x15\x84\x81\xdc\x47\x6a\x6b\x2d\xbe\x1c\x04\xc2\x73\xe1\x90\x20\xa2\x42\x41\x80\x00\x0a\x05\xae\x4c\xdb\x71\x9b\x95\x49\x84\xda\x00\x8a\xda\x6c\xeb\x4e\x03\x44\xd8\x4e\xd9\xc9\x40\x25\x9a\x15\x7b\x98\xd5\x34\xe6\xf3\x39\x77\xa5\x72\x12\x28\x6b\x5f\x62\x56\x71\xe3\xd2\xab\xbc\x51\x20\xaf\x36\x9e\xbc\x52\x2c\x01\x65\xee\x4b\x94\x93\x40\x33\x77\xe7\x7c\x3e\x41\x32\x58\x56\x59\x1b\x38\xa3\x49\x36\xf2\x6b\x37\xec\xdc\x97\x29\x05\xab\x5e\x99\x07\x76\xed\x3d\x90\xe3\x7e\x20\x67\xef\xc6\x9c\xc0\x7a\xcd\xcb\x2d\x27\x70\xe3\xba\xc0\x4c\x5a\x1d\xd0\x04\xf3\x19\x55\xa7\x79\xc1\x7c\x06\x5e\x6b\x23\xb8\xb5\x99\x1b\x42\xd7\xda\x2b\x07\xe6\x6c\xdc\x9b\x73\xa0\x5e\xf5\x72\xcb\x39\xb0\x77\xd7\x81\xcc\x03\x99\xbb\xd6\x65\x06\xd2\x06\x5c\x6c\x3e\xc6\x7d\x59\x76\xbe\xe1\x32\x0f\x23\xc9\xc1\x0c\x34\x0b\x30\x92\xbc\x7c\xde\xdf\xa7\x4c\xfa\x55\x1b\x48\x80\x1b\xd9\x53\x9d\x49\x40\xfb\xd0\xee\x0f\xb1\x03\x8f\x23\x6d\x5a\x48\x0a\x83\x23\x49\xec\xd0\x7d\x04\xb6\x0f\x95\x7a\x6a\x33\x6d\x58\x2e\x35\x76\xdb\x4e\x05\x1a\xda\x26\x0e\x4b\xb8\xaa\x70\x58\x40\x36\x81\x42\x40\x01\x69\xf6\x85\x2c\x2e\xbb\xc8\x58\x94\x56\x48\x17\xa4\x25\xe7\x25\xf1\xd8\x04\x3c\x83\x05\xb6\xdd\x77\x64\x6c\x7c\x52\x5c\xa6\xf4\x29\x46\x64\x26\xe5\x24\xe5\xa7\xb8\xa7\xe6\x2b\xe9\x45\x3c\x34\x91\xd3\x51\x21\x6c\xe5\x09\x49\x71\x19\xb6\x72\xd8\x2d\xbc\x2d\x19\x8d\xd7\x61\xb7\x50\x94\xae\xf0\xb0\x89\x2c\x2b\x2d\x2a\xcb\x95\xbe\x87\xef\x6d\x6d\xfd\xa7\xa4\x88\x87\x88\xff\x2d\xf9\x8e\x2c\x2f\x2d\x2a\xcb\x91\x2e\x41\x44\x4e\x51\x66\x51\x5a\xa1\xfb\x7f\x7a\xd2\xd6\xcb\xef\xc8\xf2\x12\x1b\xf2\x25\x88\x20\x6c\x0f\xa9\xab\x81\x74\x06\x57\xc7\x37\x06\xa2\xaf\x93\xf9\xa1\x1a\xc5\x99\xf0\x1c\x21\x53\xd0\x07\xfa\x10\xd8\xc7\x2c\x73\x32\x95\x85\xe7\xa0\x37\xf4\x26\xb0\xbe\xf5\x32\xa7\x02\x85\x85\x58\xd8\xff\x57\x68\x86\xfb\x84\x4c\x61\x33\xdc\xff\xf5\x57\x28\xc4\x42\x42\x05\x4a\x5d\xa9\xad\xc4\x2f\xf1\x4b\xf8\x12\xbf\x24\xa0\x10\xbe\xe4\xcc\x0b\xb1\x16\x66\x69\xbc\xc6\x63\x2d\xce\xb2\x2e\xb4\x2e\x84\x5a\x9c\xa5\xf2\xa2\x4c\xa9\x3c\xd4\xc2\x2c\xf3\x42\xc9\xc5\x9a\x00\x12\xa3\xce\x06\x0f\x27\xf5\x57\x20\x38\x99\x82\xe7\x14\x8c\x45\x6f\x02\xc7\xaa\x07\x38\x78\x4e\xc9\x6f\xb3\xdd\x10\x38\x50\x41\xd5\x0e\xaa\x87\x08\xeb\x22\x0a\xcf\xc1\x59\x74\x40\x07\x95\xd6\xda\x13\x32\xa5\xd1\x5a\x7b\xfb\x52\xa2\x73\x70\xd6\x56\xac\xda\xd0\x6c\xb2\xf3\x36\xc1\x87\x69\xb5\x3b\xca\x56\x6c\x9b\xab\x6c\x87\x58\x95\xb6\x2c\x3b\xce\xc1\x28\x80\xf2\x25\x63\x55\xcc\xca\x97\x8c\x45\xb1\x2a\xdc\x0a\x61\x1b\x23\xb2\x75\x89\x1e\x96\x66\x8e\x35\x38\x0c\x12\xd0\x8b\x8c\x8a\x4e\x8a\x49\x90\xd8\xba\xc4\xd6\x06\x83\x25\x91\x48\x49\x4c\x8f\x8f\x83\x35\x0c\x78\x91\x5b\xab\x8b\x2a\x4a\x24\x4b\x43\x84\x40\x14\x16\xe7\x95\x96\xe9\xad\x5e\xd8\xcc\xad\x10\x44\xd6\xe0\xf0\x13\x53\x83\x33\x0d\x64\x58\xa6\xf0\xb7\xf9\x2e\x27\x53\x32\xd5\x13\xaf\x24\x6f\x28\x5a\xb7\x7d\xb3\xbb\x59\xb5\x32\x04\xfe\x60\x91\x39\xf8\xa1\x55\x26\x6c\x85\xf0\x83\x45\x26\xac\x2f\x54\x95\x4b\xdc\xbb\x4c\x4e\x5c\x87\x0b\x35\xd5\x4d\x56\xfd\x29\xcb\x9b\x2e\xb6\x72\xeb\xbe\x56\xd9\xac\x9a\x99\xed\x55\x45\x7b\x93\x77\xbb\xf7\x84\x2b\x1c\x2e\x54\xd5\x36\x64\x77\x1b\x36\xa1\xfa\x93\x2e\x35\xea\xc7\xb0\xd7\x51\x6d\x68\x71\x52\x75\x66\xfb\x0b\x0b\x2f\x8c\xa0\xcc\x23\xf0\x11\xb7\x6e\xd2\x88\xcd\x5e\x3c\xae\x34\xe1\xc8\x6f\xd0\xf1\x85\xa9\xc5\x0d\xe8\x41\x30\x66\x24\xcc\xcd\x7a\x9c\x75\xb7\xe0\x71\x1d\x3d\x80\xd2\xbe\x81\x47\x9c\x4d\xe5\xc0\x08\x4a\x55\xea\x39\x75\x94\xd6\x03\x9e\xbf\x55\x1c\x9f\x6b\xa3\x90\x3d\x88\x1d\xae\xbd\x2f\x7e\x3a\x7d\xed\xa8\xa1\x7a\x5c\x05\x0b\xf1\x63\x30\xc2\x47\xd0\xfd\x1b\xa0\x1e\x88\xd5\xa6\x6a\xb9\xba\xba\x5a\xae\xee\xd0\x1d\xa9\x07\xd0\x7d\x34\x7c\xc4\x83\x11\x16\xc2\xc7\xb0\xea\xf1\xda\x6f\x3f\x6d\x92\xae\xbd\x3e\x08\x1d\x80\xd5\xbb\x84\x08\x90\xf6\xef\xab\x1a\x56\xed\x0e\x3a\xbb\x1e\xc9\x43\x9e\x3a\x14\x7e\x03\x1e\x74\x4e\x6a\x89\x99\xe0\x30\x0f\x75\x90\x47\xaa\xac\x33\xe6\x21\x0b\x79\xa4\xd9\xa4\xe9\x38\xfc\x4d\x26\x51\x07\xbf\x51\xaa\xce\xd9\xea\x85\x3a\xb3\x97\x0d\xc3\xea\x85\xac\xd9\x8b\x04\xde\x1a\xca\x25\x26\x27\x27\x8a\x06\xec\x4d\x26\x26\x2b\xc5\x92\xc1\xf9\x6b\xaa\x58\x51\x8a\xc5\x7a\x52\xb5\xdd\xfe\xab\x61\x0c\xac\xc6\x31\xaa\x0b\x28\x84\x5c\x4f\x15\x2b\xc9\x89\x92\x01\x7b\x53\xd6\x16\xcb\xef\x1c\x86\x42\x5f\x42\xed\x4b\x82\x11\xfb\x72\x38\xf3\x6d\xe6\x51\x14\xf7\x70\xea\x8d\x11\x76\x9a\x23\xa6\x4e\x1d\x61\xc7\x1f\x71\x63\xea\x43\xd1\xe0\xfc\x35\xf9\xf0\xc6\x8d\x87\x92\x4b\x4d\x22\x50\x06\xa2\x1d\xf4\x75\x85\x5e\x8c\xc1\x1c\xf5\xda\xe0\x9c\x03\x2e\xec\x23\x8b\xce\xbc\x92\x7b\x86\x63\xc1\x0b\x2b\x80\x18\x06\xc4\x87\xd0\x71\x26\x96\x82\x33\x96\x81\x33\xce\x81\xbb\xe8\x0a\x69\x7d\x61\xe6\x70\x18\x8d\x53\xa1\x33\x2d\xe3\x24\x78\x0f\x16\x79\x8a\xec\xd7\xf0\x18\x07\x43\x7b\x8c\x07\x16\x53\x69\xf6\x11\xbe\xd4\x8e\x72\xa0\xe1\x11\xf8\x1d\xde\x85\x81\x95\xb0\x1f\x0f\xbb\xfd\x4d\xe2\x03\xf8\x8e\x60\xbf\x86\xf9\x46\xd5\xc7\xe0\xfc\x8f\x41\x35\xf2\xb0\xd2\xba\x21\x0a\x7f\x07\x2b\x1e\xa1\x5d\xc0\x8b\x69\x02\x2f\xb3\x52\xaf\x3a\x09\x4d\xe0\x2f\x18\x88\xa5\x16\x27\xae\x30\x30\x32\x28\x28\xa5\x5b\x58\xef\x4d\x7d\x12\x73\xf1\xd9\x21\xcf\x63\xe8\xa0\x44\xba\x95\xae\xdd\xb2\x7a\x6d\x3c\x9d\x99\x9a\x62\x4a\xe1\x43\xc3\xcb\x77\x26\x49\x29\x5b\x37\xdc\x0b\xbd\xb9\x05\x3a\xb8\xaf\x20\xb7\x60\x87\xd0\x29\x1b\xc6\xa7\x44\xb9\x85\x26\x85\xc7\x86\xf2\x29\x29\x59\x39\xa9\xd2\xda\xd2\x2d\x87\x4a\xf7\x29\x35\x6e\xc7\xc0\xe1\xd0\x6f\xb9\xf0\xac\x4f\x71\xef\x6d\xdd\x76\x04\x15\x46\xee\x2f\x3c\x50\xb8\x7f\x7f\xcd\x81\x14\x3a\x08\x3e\x80\x2e\x1b\x40\xc7\x83\x0e\xba\xec\xde\x0f\x1f\x48\x07\x0a\xf7\x47\x16\x06\xd1\xf8\x17\xf4\x98\x2c\xd8\x3d\xe9\xa8\xee\x78\x0b\x6e\x69\xee\x9a\x3b\xde\x42\x7b\x0a\xb7\xf0\x96\xea\xae\xba\xc3\x2d\xb8\xa5\xba\x8b\x56\x5f\xb3\xc2\xa9\x23\xe1\x0f\xfc\x43\x1b\xa9\x8d\xc4\x7f\x53\xf8\x43\x1d\x09\x3e\x82\x64\xd1\x59\x95\xff\x9a\xea\xa0\x02\x7e\x5f\x45\xaa\x87\x20\xc8\xf1\x16\xcc\x33\xfb\x80\x9f\x93\x81\xa8\x36\xaf\xe1\x36\xd5\x86\x14\xaf\x33\x6a\x54\x94\x1b\xac\x80\xd8\x3d\xfb\x0b\x4e\x24\x1d\x71\x4f\xdd\x15\xbb\x33\xb4\x9c\x96\x4d\xb2\x16\x03\x07\xc5\x80\xed\x0b\xd2\x83\xd6\x61\x0a\x06\xb9\x2d\x5f\x99\x31\xe5\xc8\xb2\x23\xcb\x6e\x66\x9c\x38\x0a\x53\x61\xa8\x1b\xf4\xf1\xc2\x4a\x6c\x44\xc7\xcd\x7d\x16\x7c\x3c\xce\x1d\x04\x14\x89\xcf\xaf\x3d\x3c\xf0\x8c\x87\xb9\x30\x08\x07\xa1\xdf\xa0\xc0\xe1\x9f\xce\x94\x40\x40\x81\xf8\xe5\xf9\x25\x78\x0f\xba\xeb\x1f\x47\x3d\x0c\xbc\x27\xc2\x07\x85\x81\xda\xd8\x8c\xd9\xc7\xe7\x7d\x99\xe1\x6e\xca\xc9\x91\x73\xf8\xcf\x4e\x1d\xbb\x94\x27\x9d\x50\xcf\xe4\xd4\x25\xd6\x45\x6e\x73\xc7\x85\xea\x12\xee\xc5\x77\xdf\xbe\xf8\x63\xe4\x77\xbd\xfb\x8c\x1c\xd9\xa7\xf7\x77\xa3\xfe\x90\xac\x94\x01\x7b\x72\x38\x17\x07\xc1\x20\x98\xdb\xbc\xed\xd6\xe1\x4b\x12\x4a\x20\x11\xe3\xfa\x2f\x47\x1a\x59\x3d\x36\x42\x26\x66\xc2\x45\x70\x85\xf6\xc7\x9b\x7f\x11\xed\x85\xab\x3e\x9d\x1c\x31\x9e\xb7\x3d\x71\xdd\x21\x42\x6d\x82\x25\xf0\xf6\x69\x53\x77\xb4\xd9\x5f\xef\x00\x9d\x93\xc5\x19\x7e\x9e\x23\xc8\xe8\x45\xf5\x12\xd0\xeb\xa5\x00\x8a\xb9\x3b\x07\xe3\x70\x06\x74\xc1\xe1\xa2\x4c\x61\x3f\xa4\x66\x20\x37\x42\x4a\x8e\xcb\x89\x2e\x4d\x02\x87\x11\x6e\x19\x79\x05\xc6\x02\xbe\x48\xc9\x2d\xcc\x97\x0e\x9d\xaa\xd9\xb6\xad\x9c\xae\xa8\x3d\x54\x7c\x80\xbf\xd1\xbc\x7c\xf6\xd2\xd5\xd1\x9f\x6c\x90\x26\x04\x0f\x59\x89\x1d\xf5\x93\x5f\x0a\xf5\x54\x7d\x7d\xf5\x85\x3a\xb1\xb9\xe1\xc5\x25\x78\x5f\xaf\x39\xab\xbe\x1c\xcc\x15\x56\x30\xd2\x7f\x83\xf6\xc0\xbb\x02\xfe\x5f\x7e\xa4\x5a\x55\xaa\x86\xc3\x7c\x47\xd8\x01\x09\x30\xfb\x84\xfa\xfb\x5e\x27\xb5\x9d\xc1\xf9\x2a\xf7\xf8\xf6\x9d\xc7\x8f\x26\xdd\x19\x3a\x74\xe2\xc4\x61\x43\xef\x4c\x7c\x2c\xa9\x67\xac\x5d\xb8\x22\x63\x51\xba\x22\x66\x65\x65\xe6\x64\x14\x64\xe4\xa7\xe5\xba\x6b\xa3\xd4\x2a\x42\xa6\xb6\x47\x07\x55\xcc\xe5\x67\xad\x49\x0a\x8f\x91\x64\x4a\x36\x19\xd1\xa6\x5a\x9f\xc2\x0b\x84\xb1\x6c\xd4\xad\x62\x51\xbe\x5b\x1c\xff\xa3\x18\x08\x61\x8f\x60\x78\xba\xe6\x45\xe0\x3c\xed\x85\x31\x46\xd6\x67\x86\x94\xcc\x3f\x16\x5d\x1f\x5b\x97\xde\x50\xb3\xbf\xe2\x08\xd0\xa7\x41\x4f\xcb\x5f\x41\xc0\x63\xc8\x11\x4d\xf0\x06\x5d\x40\x22\x12\x4b\x0b\x0a\x65\xbd\x5c\x52\x52\x11\x2a\xaa\x4e\xda\x34\x62\xe7\x32\xa0\xc2\xc1\x41\xaf\xf5\xc2\xbe\xdc\x40\xcc\x87\x4e\xf8\x77\x76\x72\x4e\x4a\x4e\x8a\x7b\x96\x4c\x56\x04\x7d\xb1\xf0\xde\xb1\xe6\x63\x0b\xfe\x59\x7f\x9f\x96\x87\xc2\x5c\x0f\x28\x14\xcd\xd7\xb5\x9f\x39\xf9\x7d\x18\x8f\x57\x54\x59\x4c\x49\x4c\x96\x45\x39\x31\x39\x2d\x5b\x84\x6b\x5a\x3c\x10\x38\x46\xd6\xd7\x04\xe5\x07\x56\x97\x14\x17\x6c\xde\x1e\xb9\xcf\xa6\xb7\x43\x34\xac\x47\x17\x58\x0f\x27\x61\xbd\xab\x79\x18\xec\xbf\x0f\x39\x90\x0b\xf9\x2d\x97\xa1\xe3\x15\xe8\x70\x85\x4d\x48\x54\xb3\xd4\x23\x1c\x7c\x0c\x55\x59\x58\x45\x98\x5b\x5e\x70\x1f\x8c\x1d\x88\x9d\xc5\x79\xaa\xdb\x45\x12\xdc\x9b\x46\xa0\x93\xa4\xdd\x55\xdf\xe5\xaa\x63\xcb\xa3\x45\x7c\x44\x26\x26\xa5\x27\xa7\x49\x5a\xa3\xd5\x48\x6c\xda\x52\xb1\x6e\x37\x0f\x5b\xc9\xe2\xe2\x7c\x25\x5f\xfa\xec\x7b\x02\x4e\xcc\x24\xa3\xcb\x63\xab\x44\x58\x47\x56\x95\x97\x57\x4b\xe6\x9b\x6a\x47\x0e\x2a\xd0\x17\x7a\x63\xa9\x88\x35\x64\x74\x6c\x6c\xb4\x64\xcd\xa4\xd8\x7d\x0e\xd1\xe5\xb1\xd5\x22\x9b\x90\x08\xb5\x24\x14\x83\x2f\xf4\x85\x0a\x09\x06\x9a\x38\x39\x03\xd2\xb1\x37\x8c\x16\xd9\x83\x89\xcb\x49\x10\x30\xd0\x88\x0b\x65\xbd\x9c\x89\x79\x68\xc0\x61\xe2\x79\x12\xfa\x81\x99\x81\x19\x30\x5c\xf8\x0f\xc0\xd3\x06\x98\x6a\x03\xf0\xff\xc5\x70\xc1\xff\x43\xc5\x40\xfe\xe5\x68\x56\x60\x19\xa3\x5a\xd1\x93\x0b\x1a\xb4\x60\x7d\xa2\x98\x16\x1b\x6b\x8c\xe5\xd7\xae\x55\x94\x60\x09\x87\x9f\x5d\xf9\x72\x1a\x74\xa3\x27\x82\xc7\x16\xe8\x0e\x23\xf4\x30\xa2\x12\xba\xdf\x01\x0f\xf1\x3a\x74\x3b\xf2\x12\x86\x9f\xa5\x95\xfa\x7d\xca\x3e\xbe\xbc\xdc\x98\x56\x2e\xed\x49\x7c\xba\x20\x48\x1f\xee\x87\x1f\x27\x06\x88\x69\x61\x46\xff\xe8\xcd\x74\x42\x7c\xa4\x71\xcb\xe2\xc5\xc5\x8b\xf9\xb8\x48\x53\x52\x82\x14\x13\x9f\xb2\x34\x2d\x8a\x0e\x1f\x1e\x3f\xcc\x4b\xef\x55\x3a\x6c\xfb\x70\x31\x3f\xaa\x70\x69\x45\x3c\x9d\x54\x52\x63\x2a\x3b\x7d\xba\xf8\x34\x5f\x59\x63\x4c\x28\x95\xaa\x37\x67\xfb\xe7\x87\xd1\xc5\x01\x8d\xf8\x71\xb8\x1e\x86\x58\x7a\x70\x15\x15\x05\x25\xa5\xd2\x99\x33\xbb\xae\xdf\xd2\xdf\xda\x78\x7d\xd1\x19\x31\x49\x08\x0b\x33\x05\xec\x0c\xa3\xb7\x87\x95\x06\x07\xe9\x83\xe2\x83\xc3\xc3\xc5\xd0\xb0\x2c\xff\x1d\x61\xf4\x61\x01\xa6\xe2\x54\xae\xa2\x32\xbf\xb4\x44\x7a\xfe\xbc\x11\x74\x20\xe8\x41\xf0\x03\x5d\xdf\xe7\x62\x92\xf0\x4a\xa0\xef\x8d\x3b\xea\xd1\x5d\xdf\x3d\xc0\x63\xfc\x38\xf1\x95\x40\xc7\x97\x54\xa4\x55\xf2\xff\x53\x09\x7a\x40\x8f\xef\x60\x2e\xac\xd0\xc3\x8a\x91\x30\x17\x7b\x40\x8f\xb6\x8a\xd0\x01\xdf\xbd\x89\x43\x71\x8c\x1e\xc7\x4c\xc1\xa1\xd8\x01\xdf\xfd\x2f\x01\x17\xb5\x8f\x5c\x0f\xcd\xf5\x36\x71\x9e\x71\x94\x41\x61\x54\xdb\x91\x13\xf8\xc2\xeb\x1a\x41\x55\x9c\x23\x18\xb3\xa2\x29\x35\xf6\x17\xba\x6f\x01\x06\x73\xa3\x01\x97\x1b\x19\x1b\x88\xfb\x67\xe8\xe3\x6e\xd3\x04\xd1\x28\xb4\x2a\x70\x98\x91\xa9\x69\x82\x64\x55\x2c\xca\x7a\xe1\x7f\x21\x36\x4c\x23\x63\xff\x78\xf5\x50\x00\xfb\xae\x01\x74\x2d\xa0\x7b\x10\xe5\x2a\xc3\x43\x61\x16\xe8\x7e\x05\x5d\xb0\x0d\xae\xb3\x2f\xb6\x79\x01\x3a\xf6\xff\x42\x40\x87\xbe\x07\x05\xf0\x05\xdf\x83\xc2\x49\xd5\x91\x1b\x34\x08\xb6\x09\x4f\x9f\x12\x3f\xc0\xee\x83\x82\x79\x1e\x34\x83\xcc\x80\xb3\x30\x91\x41\xc6\x6f\xd6\xcc\x09\xe2\x94\x8f\x3f\x1e\x82\x43\xf5\xfe\x8c\xc8\xae\xcc\xf7\x64\x24\x36\x75\x62\x7f\x61\x1b\x03\xc4\xb9\xcf\xaf\xdd\x13\x6f\x7d\xfb\xcd\xcf\xf0\x91\x5e\x2b\x41\xdd\x41\x7b\xfb\x1c\xf8\xe1\x60\x18\x8c\x7e\xe8\x87\x83\x71\x30\xfa\xd9\xaa\x81\xb3\x00\x9d\x5e\xb5\x19\x9e\xf5\xc2\x4e\x10\x20\xa8\x22\x1c\xe3\xe6\x82\x34\x00\x5c\xb0\xc3\xd3\x0d\x35\x01\x69\x9b\x36\x44\x6e\xc8\x0f\xd8\x1d\xf9\x6a\xcc\x37\x3d\x4e\x62\x7b\x3a\x54\xd9\x11\xbb\x83\x2f\x2c\xcc\xca\x29\x90\xf6\x95\x56\x1e\x8a\xdf\x47\xc3\xea\xef\xb9\x49\x30\x09\x19\x18\x88\xfd\x81\xa2\x59\x7d\xdf\x0d\x35\x01\xe9\x91\xeb\x23\x37\xe4\x05\xec\x89\x04\x7d\xcf\xbf\xd0\x70\x19\x07\xd2\xa1\x45\xdb\x63\x77\xf2\x85\x05\x59\x39\x85\xd2\xbe\xd2\x8a\x43\x09\xf6\x07\x5e\x75\x12\xa6\xdb\xbd\xd6\x4c\x07\x5f\x74\x06\x5f\xd7\x2c\x03\xfd\x7f\xec\x4a\x4b\xa5\xda\xcc\x05\x9a\xd6\x46\xc5\x04\xd1\x4b\x37\x2d\xdb\xb0\x80\x5f\xb7\xbe\x78\xeb\x26\x29\xa9\x90\x08\xdf\x96\xb0\x6f\xbf\x1e\x68\xe6\xdc\x89\x0d\x4b\xb7\x89\x15\x41\xfb\xa2\x0e\x98\x68\xf5\x3a\xe8\xb8\x40\x61\xc1\xb2\xdd\x27\x37\x89\x31\xfb\xd7\x6e\x0d\xcc\x3a\x90\xb5\x6f\x6b\xc5\x7e\xfa\xe4\xb6\x13\xbb\xcf\xf1\x7b\xf7\x24\x46\x6d\x93\x8a\x52\x88\xed\x9b\x4a\xd6\x06\xe9\xb5\x8f\x21\x94\xdb\x7e\x26\xea\xf3\x45\xdb\xe9\x7d\x93\xc7\x56\x8e\xe1\xd9\x1d\x41\x6b\x33\x53\x83\xa5\xd3\xbb\x2f\x6e\xfd\xa2\xa0\x31\xff\xd0\x99\xd4\xc6\xb4\xc6\x45\x87\xfc\x52\x7b\x27\x0c\x5a\x33\xda\xaf\xfe\xf4\xd1\xe3\x27\x0f\x37\xec\xcf\xbf\x1c\xd4\xb0\xb6\x61\x56\xbe\x7f\x10\x8d\xc3\xd0\xbd\x07\xce\x8e\x40\x7f\xec\x8d\x5b\xdd\x70\x15\xbe\xb3\x7e\x4b\xe2\xea\xf2\x75\xee\xe0\x85\xcd\xc4\xa6\xe2\xda\xf8\x5a\xbe\x48\xc9\xce\x2b\x92\xd8\x95\x90\x02\x1d\x08\x76\x1f\x1c\xdf\x58\x6e\x2a\x33\x95\x1b\xdd\x65\x2a\x3b\x5b\xce\x96\x65\xb9\xc3\xfb\xd0\x11\x88\x7b\xe0\xd4\x28\xd5\x9e\x89\xfc\x7c\x51\x2d\x9d\x9f\x10\x9f\x13\xc7\x97\x95\xe6\xe4\x97\x48\xec\xca\x33\xb5\x35\x9f\x47\x9c\xa1\xc1\xc9\x0f\x89\x7b\xd8\x91\x67\xd7\xa5\xa5\x9a\xd2\xf8\xe2\xbd\xfb\xf2\x0f\xf0\xec\xca\xd3\x27\x93\x22\x8f\x49\xa7\x23\xbe\xd8\x5a\x7b\x9a\xb6\xcc\x03\x2f\x6e\x5b\x62\x44\x69\x04\x9f\x94\x6c\x4c\x4f\x92\x30\x05\x3b\xe0\x89\x5d\x71\x59\x71\x59\x71\xd9\xee\x26\xd2\x68\x94\x8d\xf6\x36\xb1\x23\x12\xe3\xd1\xc9\x4f\x8a\x58\x54\x33\xe7\x4c\x04\x9d\x56\x52\x9a\x59\xc6\xc7\xc5\x67\xa6\x25\x48\x8b\x22\x22\xe7\xd4\x2e\xa2\xd1\xa9\x11\x88\xf1\xd0\x31\xbf\x20\x2b\x9f\x4f\x5c\xb7\x36\x2d\x90\x5f\xbc\xb4\xa8\x66\x85\xb4\xb8\x76\x76\x54\xc4\xe2\xf0\x45\x5b\xe7\x9c\x09\xa7\xd7\xde\xba\xbf\xe5\x01\xbf\x7f\x5f\x4e\x41\xbd\xb4\x78\xc3\xdc\xa8\xd9\xa9\x7e\x69\xab\x17\x15\xf8\xd1\xac\xef\xa2\xfc\x86\x35\x67\xf8\xdc\x5c\x39\x2b\x57\x62\x57\xbe\x28\x79\x7a\xf0\x9b\xc6\xe0\xc5\x01\xcb\x97\xae\xf2\x0f\x4a\xfb\x64\xbf\x3f\x1d\x51\xbd\x2b\x61\x37\x5f\xb3\xad\xa0\xbc\x4a\x82\x61\xe0\xfe\x27\xcc\xae\x05\x7f\xe8\x0d\x5b\xdd\x58\x5f\x58\x05\xef\xec\xa9\x2c\x3e\x14\xbb\xd7\xdd\xa5\xc6\xd2\xd0\xe2\xa8\xbe\xf7\xab\xd9\xf7\x85\x93\xa5\xc1\x26\xf8\x77\xea\xf9\x12\x3b\x62\xc7\x9e\xb6\x5b\x37\x59\x80\x6a\x01\x56\x0a\x18\xaa\x36\x73\x70\x17\x8a\xb1\x18\xef\xe2\x47\xa3\x07\x4f\x1e\x25\xcd\x18\xbf\x60\x0e\x12\xfa\x54\x21\x70\xfd\x9e\x03\xde\xc2\x74\x01\x86\x7e\xfd\xe4\xe6\xd7\xe2\xd5\xbb\x8d\x57\x80\xd1\x43\x77\xc1\x56\xfd\x2e\x14\x43\x31\xdc\x15\x31\xd3\x1a\xc0\x69\x0f\xb4\x07\x31\x31\x72\x68\x45\x8c\x3b\x8c\xc2\x51\x15\x31\x3b\xe5\x8a\x0a\x77\xf5\x81\xfa\x80\x30\x1f\x34\x38\xef\xe4\x62\x2a\x42\xe5\x2d\x31\x18\x80\x01\x6e\x03\x07\x3e\x9e\x78\x63\xc8\xf1\x5e\xee\x77\xef\xee\xdc\x01\x71\x10\x57\x51\x29\xef\x8c\xa9\x70\xb7\x69\x67\x3e\x06\xe7\x74\x98\xe3\x68\x20\xa6\xc0\x0c\x27\xf3\x1b\x4b\x3e\xb7\x3f\xa3\xce\x7f\xf3\x96\xb4\x94\x18\xb1\xaf\xaf\x3f\x4a\x1f\xe8\x27\x6e\xef\xff\xb8\xa8\x38\x2b\xab\x48\x2c\xcf\x92\xe5\x9c\xb2\x9a\x97\x5b\x5f\xd6\xbc\xa4\xf3\xf7\x16\xec\xad\xd7\xab\x5b\xb4\x51\x5c\x5a\x4a\x6a\x9a\xc9\x28\x67\x99\xc4\xa2\x65\x2b\x0b\x97\xf1\x1f\x79\x87\xaf\x99\x20\x25\xa7\x67\x66\x18\x93\x13\x97\xa5\x2c\x4d\x5c\x46\x63\xdf\x95\xe8\x8a\xd3\x70\x2c\x8f\xed\xc7\x7d\x07\xf4\xd5\x06\x70\x79\x70\xec\x7c\xc4\x86\xbd\x52\xb6\x31\x2f\x23\x43\x6f\x4c\xef\x35\xcf\x4b\xbf\xb1\x34\x6a\xcf\xcd\x0b\xbf\x7f\x56\x2e\x16\x1d\x2a\x39\x96\x7b\x98\xce\xca\x96\xb3\xb2\xf5\x79\x91\xc6\x0c\x9c\x87\x04\x38\xc0\x7c\x98\x09\x1d\x60\x13\x2c\x38\x20\xe6\x6c\xab\xcd\xa9\xe5\x61\xd0\xa3\xb1\x38\x04\x9d\xd6\xf4\x8b\xe9\x2a\x65\x1b\x89\xa3\x77\xee\x1f\x7a\xc8\x2b\x95\xe9\x99\x85\x52\x65\xea\x7d\x6c\xbf\x59\x0f\x33\xd4\xad\x5d\x05\x4c\x44\x05\x16\xaa\xa3\x21\x3a\x11\xc2\xd5\xad\xb0\xc2\xf5\x10\x44\xe2\x52\x78\x00\x1a\x34\xb0\xdf\xb2\x5f\x99\x63\x0d\xce\xb7\xb8\x85\xc9\x0b\x93\x16\x89\xc1\xd8\x3f\x18\x07\x04\x63\x7f\x3a\x30\x65\x55\x61\x08\x8f\x6e\xab\xa1\x3b\x38\xc0\xb0\xab\x10\x0c\x1e\x3f\x48\x65\xdb\x77\x29\xbb\xf8\xa6\xbc\x25\x7e\x92\x39\xdd\xda\x9d\xdb\x8d\x14\x4c\x0d\x2d\x12\xf3\x12\x36\x14\xc6\xf3\xa8\x43\x72\xf6\x2c\x74\x90\xd8\x6f\x33\x73\x88\xed\xf0\xe1\xe7\xd0\x1f\x46\xea\x41\x46\x37\x20\x30\x5d\x64\x8f\xaf\x09\xcc\x4c\x0b\x94\xf0\x0b\x3f\x9c\x85\x7f\xe2\x11\x3d\x5e\x82\x09\x38\x0a\x2e\xe6\xd7\xe7\xa6\x88\xc9\x14\xba\xc4\x8c\xc3\xe3\x38\x84\x5f\x1a\x55\xdf\x00\x3c\x0c\xf8\x2e\xbb\x50\x62\xbf\x3a\x66\xc2\xa1\x8d\xfe\x3c\xb6\x9f\x81\xb3\xfb\x4a\xec\x69\x9c\x0c\xce\xd8\x09\xa6\xc1\x56\x98\x07\xfb\x21\xee\xb2\x58\x79\xab\xe4\x4e\xd5\x2d\x9a\xfd\x36\xb7\x2c\x27\xbf\xac\x80\xbe\x04\x4e\x40\x1d\x82\xce\xfc\xed\xcb\x9b\x93\x6e\x49\xf9\x26\xa2\xa8\xb4\xa8\x48\x72\xe9\x1a\x0c\xbe\x8e\x06\xe2\x38\xcc\x75\x32\xdf\x33\xff\xcd\xad\x5f\x1f\x1f\xb6\x59\x5a\xbb\xac\x78\xe6\xa9\x75\x30\x0b\x3b\xbb\x6d\xde\x15\xeb\x1f\x62\x34\x66\x19\x79\x0c\x39\xa4\xf9\xb6\x10\x59\xa9\x69\x59\xa9\xfc\x12\xff\xb5\x8b\x52\xa4\x94\xf9\x87\x97\x9c\x8b\x87\xbf\x3d\xdd\xb4\x4d\x97\x89\xcc\x0c\x39\x93\x5f\xb4\x2c\xd8\x56\xe0\x7b\x64\xe1\xc5\x34\xb5\x6a\xba\x9b\x36\xcb\x44\xcc\x5b\xb2\x72\x5e\xa6\xe4\x9b\x79\x62\xc9\x67\xbc\xea\x4b\x62\x69\x30\xb1\x20\x6d\x45\xc0\x02\xfd\xdc\x13\x2b\x2e\x88\x76\x99\x1b\x5e\xd7\xab\xdb\x2f\x1d\xcf\xdb\x5f\x5f\x78\xcc\xfd\x9e\x3a\xa8\xe0\x70\xe2\x91\xb0\x3d\xee\xd8\x13\x3e\x0e\x3e\xb4\x7a\x9f\xff\x2e\x77\x0c\x83\xde\x44\xc9\xe6\xa8\xfc\x48\x7e\x22\x2e\xe5\xd6\x6f\x8d\xda\x9b\xb6\x3f\xed\x40\xe1\x81\x9a\x3d\x39\x39\x39\xd9\x39\x39\xf8\x3e\xf4\x72\x0b\x3c\x34\xa7\x28\x60\xdd\xf2\xb5\xa9\x9f\xec\xf5\xcf\x36\x66\x65\x66\x1b\x21\x19\xcb\xdd\x0e\xae\xca\x33\xc2\xfa\xff\x1f\x73\xff\x1d\x17\xc5\xf5\x3d\x8c\xe3\x0b\xec\xcc\x0e\x73\x75\x05\x76\x87\xc0\xee\xce\x0c\x2a\x62\xef\xe4\x6d\x43\x83\x35\x1a\x62\xc3\xd5\x88\x68\xec\x02\x0a\x2a\x4d\x7a\xef\x2c\xb0\x94\xa5\x49\x6f\x76\xb1\x61\x49\x14\x45\x63\x8a\xd1\x14\x95\x14\x4d\x8c\xa9\x9a\xa8\x49\x34\xd1\x9c\x59\xce\xe2\xfb\xf7\xda\xc5\xbc\x9f\x77\x7e\xcf\xf3\x7c\x5e\xdf\x3f\xbe\x7f\x7c\xb7\xcc\xbd\xf7\xcc\xdc\x3b\xf7\xde\x73\xee\xb9\xe7\xb6\x73\xb6\x50\xe6\xa5\xd2\x17\xdc\x85\xdc\xf5\xa7\xdf\xd0\xea\xf3\xd7\xad\x29\xd2\x57\x62\x94\x5b\x61\xc8\xea\xe4\x84\x03\x5e\xb0\xd2\x0d\x97\x4b\x13\xa3\x3a\x17\x37\xae\x0a\x77\x5f\x13\x99\xbc\xb4\x3e\x10\x74\xf8\x93\x1b\x66\x49\x93\xc3\xcf\x2c\xad\x5f\x13\xe9\xbe\x2a\x3c\x61\xd1\xde\xd5\xb0\xdb\x12\xe8\x86\xf5\xf0\x74\xdb\xc9\x25\xd5\xeb\xc2\xdc\xd7\x84\xa6\x2d\x3c\xb4\x16\x52\xf0\x9a\x5b\x73\xf3\x81\xea\xc3\xda\xbd\x6d\x19\x89\x4d\x22\x44\xe0\xb0\xd3\xdb\x8f\x07\x1f\xde\xe4\x0e\x5e\x38\x63\x4f\x68\xd5\xe6\xfc\x8d\xee\xcf\x2e\xb6\xd7\xb5\x1c\x28\x3b\xe6\x7e\x16\x76\x94\x9f\x35\x76\xe6\x9e\x73\x57\x36\x36\xee\xea\x99\x03\x9b\xec\x74\xf2\xa3\xe0\xe9\x00\x3f\xc0\x7c\xae\xb8\xb8\xb8\xb8\x04\xff\x05\x67\x93\xda\xc4\xd4\x86\xf8\x86\xe4\xfa\x96\xa3\x6d\xed\x7b\x0f\x43\x94\x65\xbc\xdb\x33\x0c\xa0\xd2\x8b\xc1\x7d\x43\xad\xb6\xa4\xb8\xb0\xac\xc4\xe2\x62\x5e\x16\x7d\x5c\x6c\x6b\xd9\xd3\xbc\xaf\x51\x5a\xdd\x7b\xc7\x2d\xdd\x78\xa6\xb0\x42\xdb\xb4\x37\xaf\xb8\x49\x2c\x2e\x30\x16\x15\x6b\x4a\x2d\xe1\x3d\xb2\x94\x66\xe1\x60\xdd\xa1\xdd\x87\xab\x33\x33\xdd\xa4\x25\xbd\x1f\x5c\x45\x02\x4e\x18\x47\xa5\x95\x54\x64\x55\x6a\x6b\x7f\xea\xaa\x68\x10\x2b\x4a\x4a\x2a\x2a\x35\x75\xa3\x60\x6a\xe2\x1e\x01\xd6\x7d\x0f\xb3\x60\x2c\x10\x58\xcc\x54\x35\x94\xb6\xb4\x6a\x5a\x33\x5b\x92\x1b\x04\xb8\x84\x7a\xfc\x1c\xd6\xe3\x73\xad\xdf\x6b\x59\xc9\xaf\x8b\xe8\x04\x71\x54\x79\x56\x6a\x49\xaa\x36\x6e\xfc\x8a\xd4\x18\x31\x2d\x2b\x33\x35\x45\x13\xf7\x00\xa7\xee\xde\x29\xe0\x82\x19\x38\x16\x5d\x91\xc1\x09\xcc\xf6\x4d\x41\xeb\xdf\xd0\x44\x94\x46\x56\xc7\x08\x9f\x21\x01\x47\x54\x83\xe3\x74\x26\xbf\xb0\x30\xbf\x50\x6b\xbe\xf1\x84\x03\xea\xee\x47\xe0\x0e\x03\x35\x30\x20\x00\x1c\x27\x7c\x2b\x80\xff\x2b\x30\x01\x07\x81\x03\xbe\x82\x76\x38\x1d\xc7\xa0\x07\x2e\x7e\x85\xb1\xd8\x9b\x97\x73\x6d\x4d\x4d\x6d\xe0\x03\x3a\xd4\xa1\x4f\x78\x74\x74\x78\x78\x74\x53\xdb\xa5\xe8\xae\x4d\xc7\x85\xe3\x9b\x56\x34\xe9\xb5\xd6\xb0\x28\xd9\x5f\xe3\xf2\x72\x33\x4b\x29\xa5\x25\x65\x10\x38\x9b\xaf\x00\x27\x39\xc7\xd8\x19\xe0\x25\xf3\xc8\x0b\x37\xc1\x0d\x74\xf7\x1d\x7a\xda\xa5\x59\xdc\xcd\xe4\xee\x1d\x1f\x0b\x5b\xa2\xd6\xc7\xaf\x4d\x67\x9a\x56\x94\x2f\xf3\xd7\xd8\x94\xb3\xfa\x61\x2c\xc6\xe2\x54\xf0\x83\x28\xd8\x09\xd3\x60\x05\xc4\x9c\x3b\x97\x1e\x7b\x46\x28\x3e\x5d\x7d\xaa\xe1\x38\xd3\xb8\x74\x61\xf9\x42\x2d\x5e\xc4\x28\xcc\xc1\x4e\x1c\xdc\x89\x2e\x8f\x06\x89\xe8\xf0\x18\xb8\x00\x18\xa6\x85\xe1\xa0\x3e\x0f\xf6\x8f\xc5\x47\x4f\x3b\xc1\x05\x06\x6b\x70\x1d\x2c\xe5\xc0\x21\x16\xec\x83\x9e\x0a\x45\x21\x86\xe0\x10\x0d\x36\xae\xb0\xf8\xe1\x49\xb4\x17\x72\x1b\x1a\xf3\x1a\xb5\xd5\x05\x14\x84\x82\xee\x09\x6c\x81\x62\x8d\x1e\xbe\xe6\x52\x61\xe8\x3c\xd8\x80\x2e\xdf\xde\x41\xf1\x26\x0e\xbb\x80\xa3\x19\xc8\xc5\x35\xdc\x5f\x9f\xff\xf2\xd3\x51\xb1\xf6\x54\xe9\x9d\x33\x9a\x1f\xa3\x7f\x7a\xe3\x33\x21\xd8\xf7\xb5\x85\xd3\xa2\xf5\x89\x8b\x62\x36\x6c\x62\x82\x82\x23\xfd\x02\x35\x1b\xaa\x36\x37\x85\x08\x20\x1c\x84\x61\x4f\xde\x05\xd7\xbc\x84\x94\xf0\xcc\xa4\x25\x83\x91\xf3\x1e\xb2\x8c\x59\x7f\xea\xd2\xd6\x2b\x5a\xe5\x71\xde\xc5\x00\x5f\x4b\x6b\xbf\xcf\xab\xd8\x73\x0e\x0a\xe0\x8e\xea\xd3\x9e\x76\x29\x83\xc3\x75\x38\x16\x27\xe1\x06\x41\xf5\x33\x6e\xc0\xb1\xf0\x2f\x58\x0f\xeb\xad\x8c\x0c\x36\x9e\x3a\x99\x99\x74\x42\x4c\xda\x99\x16\x96\x1b\xc6\x54\x85\x6e\x2d\x09\xd1\xe2\x38\x54\xa0\x3b\x8e\xc4\x31\x40\xa3\x0b\x8c\x17\x55\x9f\xc2\x38\xa0\xc1\x05\xc6\x1c\xcf\x3a\x9e\x70\x44\xdc\x5f\xb2\xaf\xb2\xad\x86\xa9\x5f\x6d\x0a\x08\xd0\xe0\x3c\x00\xae\x75\x76\xd5\x2b\x33\x34\x38\x73\x0e\x7a\xe2\xb0\xd1\x42\x1a\x9d\x94\x54\x50\x98\x24\x42\xe0\x17\x47\xe0\x22\x2c\xd4\x34\x1b\x5a\xf2\x5a\x04\x83\x3c\xe8\x69\xc0\x93\x65\x0f\xee\xe8\x2f\xe1\x88\xe2\x11\x0c\xfc\xf0\x94\x0b\xcd\x5e\x96\x12\x26\x2c\x8c\x78\xe3\xb5\x59\xda\x75\x9b\x9b\xf7\x6d\x17\x55\xdd\xef\x1e\x84\xe1\x8f\x4a\xbe\x62\x54\x3f\x6f\x1c\xef\x35\x77\x54\x34\x93\xd8\x9c\xbe\x67\x8f\xe6\x97\xeb\x47\x6f\x37\x09\x97\x76\x9f\x39\xd5\x72\x9e\x39\xb2\x72\xf7\xc2\x45\x1a\xb8\x03\x53\xb8\x11\xec\x73\x3d\xad\xfa\x74\x18\xff\x5c\xaf\xc0\x89\xc0\x21\x07\x13\x85\x1e\xbd\x17\x6f\xed\x16\xcf\xf5\xac\x80\x03\x3f\xb2\x3a\xf9\xbf\x25\x37\x6e\xcd\xc0\xf8\xd0\x6c\x21\x2a\xdd\xb8\x3e\x38\x3c\xa2\x6c\xe7\xc0\xc8\x51\xa8\x42\xe5\x8e\x07\x83\x76\x46\xa4\x47\x68\x83\x8c\x27\x5b\xd2\xc5\xd0\xe2\x81\xb5\x6f\xc1\x25\xbe\xa8\xcc\x58\x66\x3a\x83\xce\x19\x57\x34\x7b\x0f\xd4\xb4\x0a\x8d\x75\x89\xcd\xda\xe2\x62\x43\xa1\x51\xcc\x3b\x96\x7b\xec\x98\xa6\xbd\xf0\xec\xee\x03\x02\x90\x4b\x0f\xde\x02\x67\x2d\xd0\x3f\x2f\x1a\x7c\x56\xdc\x1d\x5a\x18\x18\xac\xd9\x9c\xbb\x39\x6f\xb3\x90\x6f\x34\xe6\x1b\x9b\xea\x6a\x9a\xb5\x2d\x87\xe2\x77\x8a\x7e\xe8\x6c\x7a\x53\x93\x6e\xcc\x28\xca\x10\x8e\x4d\xfa\xf4\xf5\x7b\x31\x4c\x75\x6e\x59\x5a\x92\x06\xca\xa1\x98\xf3\x60\x3d\x36\xf2\xbb\x75\xf4\x06\x07\xf3\x8f\x30\x82\xc5\xc0\x3c\x1c\x3e\x6f\x22\xfa\x33\x51\xab\x72\x66\x2c\xd7\xf8\x15\xbf\x6e\x7c\x5d\xc8\x4e\x4b\xcd\x4b\xdd\x14\xda\x16\xaa\x0d\x5e\x13\xb1\x49\x1c\x03\x6f\xd6\x4c\xd2\x24\x66\x25\x65\x25\x09\xab\x07\x8d\x19\xe2\xb1\x36\x3c\x35\x3c\x6b\x47\x16\x13\x97\x93\x96\x1c\xa7\x79\x15\x66\xee\x78\x2b\x53\xd8\xd6\x18\x3f\xf3\x9d\x23\xa7\x76\x9f\xd1\x36\x36\xe6\xe7\x34\x8a\x31\xc0\x9c\xb1\xca\x0b\x5a\x78\xe3\x04\xa8\x1b\x80\x88\xc6\x86\xc6\x82\xc6\xd3\x1d\xc9\x1d\xda\xae\xc4\xee\x03\x0d\xe2\x5b\xa5\x30\x73\xef\x27\x9a\xba\xb4\xaa\x38\xa3\xb0\xa3\x24\xbc\x24\xbc\x02\x65\x67\xc6\x3d\x0e\x7c\xca\x64\x55\x67\x55\xef\xbe\x0b\x6b\xe2\x1e\x6a\x4e\xac\x6a\x09\x11\x82\xc2\x76\x06\x69\xd3\x53\x8b\x8c\x19\xa2\xf1\x6a\xf1\x87\x57\x35\x17\x73\xbe\x88\x3a\x27\xf8\xc2\xbf\x70\xf8\x63\x9c\x9f\xc7\xf4\xe1\xe0\x0d\xd8\x6f\x1d\x05\xf5\x98\xc0\xe4\x90\xc7\x4b\x6e\xdc\xea\x81\xf1\xdb\xb2\x85\xa8\x8c\xa2\xf5\x21\xe1\xe1\xa6\x70\x8f\xbf\x31\x31\x30\x3c\x22\x2d\x5c\x1b\x6c\xc3\xc4\xb6\xe2\x81\xb5\x6f\xc3\x25\xde\x58\x56\x64\xc5\x84\x93\x15\x13\xfb\x6b\x5b\x85\xc6\xfa\x84\x26\x6d\x71\x71\x41\x41\xb1\x98\xdb\x87\x89\xa2\xb3\xbb\x0f\x0a\xc0\x5e\x7a\xf0\xb6\x15\x13\x8a\xfb\x36\x4c\x6c\x2b\x0c\x0c\xd1\x6c\xce\xdb\x94\xfb\x02\x13\xcd\x75\x35\x4d\x7f\x63\xc2\xc9\x8a\x89\xa2\x0c\xa3\x0d\x13\x7e\xf7\x62\xff\xc6\x84\xc9\xbc\xd3\x83\x97\xf6\x43\x3b\x6b\x5b\xe8\x75\x94\x41\x03\x3b\x78\x1d\x7a\xf8\xe3\x22\x4c\x60\x0c\x0a\x5c\x88\x09\x1e\x98\x1b\x1b\xc2\x18\x62\x42\xa6\xe0\x60\xe1\x55\x88\xc4\x0a\x83\x41\x83\xe5\x98\x8a\x73\x2d\x85\x58\x27\x62\x92\x1e\x05\x83\x41\x93\x93\x97\x97\x23\xe6\x17\xe4\xe7\x6b\x9a\x43\xef\x8f\x84\x94\x22\xc6\x08\x07\x21\xe1\x7b\x38\xaa\x85\x95\x60\x9f\x98\x7e\x56\xac\xcf\xa9\x37\x99\x6a\x61\x05\xfc\xea\x56\x56\x9d\x5d\x9b\x54\xc6\x14\xe4\xe6\x16\xe6\x68\x27\x54\x62\x70\x13\x4e\xde\x89\x21\xc1\x73\x03\xb1\xd6\x8b\x31\x04\x44\x0c\x0c\x16\x20\x08\x5c\xee\x77\x19\x34\xe0\x0f\x14\xec\xb8\x08\xe1\xe9\xe7\x7e\x79\x1f\xec\x4e\xee\x3d\xb5\x17\x46\x7f\x7c\xf2\xdb\x93\x77\xeb\x60\x66\xcb\xe9\xd6\x53\x07\xc0\x03\x4e\xc3\x72\x46\x29\x7d\x02\xa2\x9d\xe1\xfd\xf3\xdd\x52\x25\xf0\x52\x55\xf7\xf9\xf7\x1d\x74\xd4\x08\xb3\x9a\x6b\xcb\x6f\xcb\x69\x15\x30\x2d\x09\xa2\x6e\x25\x77\xc6\x9e\x0d\x3f\xe5\x8e\x21\x83\x61\x2e\x4c\x0c\xed\x08\x3a\xb2\xf1\x80\x3b\x4e\xc0\x79\x7f\xc0\xd6\x75\x6d\xab\x1b\x02\xaa\xdc\xa7\x63\x74\x35\xa4\x51\x11\xc6\x88\xc2\xf0\x88\xf0\xbc\xc8\x7e\x9e\x55\x98\x3a\x03\xa2\x02\x92\x57\xc7\xac\x8b\x70\xff\x03\xb7\xe1\x04\x98\xb7\x31\x34\x28\x28\x74\x83\x3b\xcc\xc5\x89\xb8\xf5\xcf\x88\x75\x31\xab\x93\x03\xdc\x21\xda\x07\xd3\xab\xa9\xdc\x88\xbc\x70\x43\xb8\x21\xbc\x30\x22\xa2\xdf\x10\x48\xab\xc6\x28\x9f\xaa\x80\x86\xd5\xad\x6b\xdd\x61\xeb\x9f\x38\x0f\x27\x1c\xd8\x70\x64\x4b\x47\x98\x3b\x8c\x87\x79\x9e\xb8\xed\x54\xf8\xdb\x31\x9d\xc9\xee\xb7\x60\x57\x12\xa6\x53\xad\x39\x6d\x79\xad\x6d\xad\x85\xad\xfd\x3c\x93\x20\xf3\x36\xc6\x76\x56\xbf\x5d\x7f\xaa\xcd\xdd\x13\xb6\xc1\x78\x9c\xd7\x71\xe0\xc8\x91\xfd\x1d\xee\x38\x17\x26\xc0\x56\xcf\xd6\x53\x0d\x6f\x57\x9d\x77\x37\x28\x30\xea\x16\xa4\x26\x51\xc6\xd6\x82\xd6\x36\xcd\x7e\x57\xfc\x12\x77\x63\x0d\x7e\x8e\x5f\x60\x35\xd4\xc0\x97\x70\x0b\xac\xee\x17\xf0\x39\x58\xe1\xb7\x84\x6e\x49\xc5\xf5\x0e\x91\x54\xbd\x43\x2c\x2a\xaa\xb7\x54\x61\x1e\x62\x51\x99\x87\x48\x2a\xaa\x77\x88\xe5\x75\xae\x77\xa5\x34\x8e\x32\x5f\x55\x98\x57\x4a\x63\xcd\x2b\x2d\x63\xa9\xde\xab\x8a\xf7\xcd\xbf\x73\xbd\x26\x49\xdf\x6b\xb2\xe8\xa9\xe7\x6a\x85\xd9\x64\xd1\x9b\x4d\x92\x9e\x52\x7a\xa0\x7b\xb7\x8e\xd2\xdc\xb4\x33\xdc\xd4\x51\x8f\x6f\x3a\xc0\x7d\x1d\xe5\xc5\xe1\x62\x1c\x85\xa3\x71\xb1\xd8\x5b\xa9\xc0\xc5\x30\x0a\x47\xc3\x62\xe1\xcc\x4d\x7a\xeb\xd6\xbc\xd2\x6d\x22\x3a\xb5\x8d\x07\x07\x70\xd1\x98\x2b\x15\x30\x14\xfa\x41\x7f\x18\x2a\x98\x47\xd3\x6d\x37\x29\xf0\x86\xed\x9c\xc5\xe9\x79\x07\x2e\x96\xee\x50\x18\x4b\xc3\xb1\xde\x70\xaa\x2a\xa4\x34\x28\x48\x13\x94\x19\x9c\x1c\x22\x6c\xf6\x9c\xb3\x08\x1d\xe2\x18\x7c\x43\x01\xe7\xca\xc0\x0e\x8a\x7e\x82\x4c\x69\x97\x8e\x52\xba\x41\x8c\xe5\x12\x07\x83\xc7\x83\x1b\xea\xde\x12\x22\xe6\x53\x7f\x6d\xbe\x39\x04\x69\xcd\xf3\xe6\xde\xa9\x8a\x94\xf0\xf8\xa8\x84\x48\xc6\x7c\x84\x56\x36\xa2\xe9\x10\x54\x1f\xfe\x13\x32\x20\xf0\x50\xc6\x21\x29\x12\x46\x9d\x88\xd9\x07\x4e\x2e\x06\xd8\x07\xe9\x87\x60\xe0\x01\x13\x38\xc5\x1c\xca\x3e\x08\x83\x0e\xc2\xa0\xfd\x3f\x1c\x80\x71\xfb\x54\x37\xee\x77\x99\x7f\xd6\xc9\xaf\x72\xed\x51\x1d\x9b\x36\x46\x6f\x08\x0e\x6a\xda\x78\xe2\x78\xf3\x89\x23\x02\x4e\xd6\xf5\x34\x72\x1b\x43\x43\x36\x6e\x0c\x6b\x3f\x2e\x00\xad\x50\xa5\x5d\x4c\x3d\xbe\xff\xf0\x09\xc1\x1a\xeb\xc4\x81\x90\x4d\x22\xd2\x0a\xf0\x75\xdd\x14\x16\x0c\x3b\xd8\xfd\x21\x9b\x04\xa4\x15\xaa\x71\x8c\x0c\x66\xb9\xaa\x18\x59\xea\xc6\xd0\x10\xd8\xc1\x1e\x78\x01\x67\x64\x5d\x30\xcb\x75\x53\x68\xf0\xc6\x8d\xa1\x7d\xe9\x1d\x3f\x70\xf8\xc4\x89\x17\xb7\xa1\xd1\xec\xcb\xa5\x61\xc0\x44\x7c\x03\x47\xa1\x8a\x39\x14\x1f\xdc\xbc\x59\x1b\xbc\x35\x26\x2c\x4e\xdc\x1f\xbb\xb5\x21\x58\x1b\xbc\x55\x62\xf9\xa0\x6d\x12\xcb\x6f\x0a\x89\x0a\x89\x13\x71\x12\xf0\xde\xb0\x0d\x82\x34\xa0\x3b\x0c\xba\xeb\xc0\x0a\x49\xfe\x99\x4b\x97\x68\xf0\x73\x88\xc2\x73\x70\x0f\x32\x60\x13\x8c\x82\x8d\x20\x13\x70\xc4\x3e\x6e\x67\x56\x78\x66\xb8\xb0\x6e\xd1\xcc\x9d\xbe\x5a\x5c\x87\xfd\xe0\x35\x58\xfa\x68\xff\xa3\xae\xaf\xc5\xf8\xf9\xc9\xaf\xce\xd3\xe0\xc8\x4f\xc6\xc2\x84\xce\x73\xa6\xf2\x4e\xa1\x68\x77\x4d\x51\x8d\xb6\xb3\x29\x22\x40\xb4\x2c\x32\x0f\xe5\xfc\xd6\x2e\x98\x37\x6f\xed\x47\x57\x3f\x3c\xfd\xd1\xa7\x9f\x9e\x5e\xf0\xba\x60\x76\xc4\xfb\x1c\xea\x96\xa0\xe8\x35\x4e\x28\xda\x5d\x50\xb3\x5b\xf3\x49\xf0\x89\x79\x71\xf1\xb9\xb9\x71\x42\xda\xea\xd5\xe9\x81\x5a\xf4\x58\xf1\x25\xb8\xff\xd0\xfc\xa8\xf5\x1b\xf1\x8b\x1b\xbf\x75\x3d\xd3\xaa\x9c\x18\x19\xac\x85\xfe\xf8\x1a\x2e\x11\x6d\xf5\x71\x10\xc3\xb8\x9f\xe3\xa1\xff\xac\x6b\x42\xcb\xce\xa0\xd6\x2d\xda\xc8\x5d\x29\x71\x89\x62\x24\x0c\x7e\x1d\x04\xb4\x7f\xc4\x94\x94\x96\x97\x95\x6b\xea\x36\xd6\x27\x16\x0b\xa6\xf2\x23\x87\xab\x34\xc6\xbc\xe2\xdc\x22\xe1\x48\xd0\x8a\xc6\x95\x5a\xfd\x8a\xa8\x0d\x9b\xc5\xa2\x98\x5d\x05\xbb\xb4\xb8\x08\x67\x0e\x43\x4f\xa4\xc4\xe0\x37\x93\xc3\x76\xac\xcd\x4e\x4b\x4e\xcb\x4c\x4f\x8c\x4f\x8a\x4b\x8e\x65\xda\x13\xb7\xd7\x6e\xd1\x62\xc2\x1c\x8b\x2b\xce\x0a\x30\xbe\xde\xb0\x5a\x3c\x39\x14\xfa\x23\xf7\xe5\x0c\x26\x6c\x95\x7f\xc2\x52\x6d\x64\x64\x61\x71\x94\x78\x7a\xd1\xb5\x35\xdd\x31\x21\x29\x41\x99\x41\xf9\xcc\xca\xf7\x3e\xdf\xfe\xa5\xb6\xfb\x93\xd6\x53\x97\xc5\xc5\x47\xf5\x1f\xb5\x1f\x6a\xd8\x5f\x27\x84\xd5\x1f\x8c\x39\xa2\xb5\xf9\xc5\xb0\xfa\x43\x31\xed\x5a\x15\xe5\x24\xb3\x86\xeb\xc5\xb0\x3a\x6b\xf8\xdd\xd3\x9d\x97\x45\xa0\x15\xc6\x02\x70\x3c\x04\xbb\x40\xf5\xd5\xf7\xee\xdf\x3f\x3c\x01\x89\xe0\xa2\x51\x9e\xe3\x1f\xfd\x18\xb2\xe0\x86\x30\xd8\x8b\x3a\xb1\x61\x59\xfd\x32\x2d\xba\x0f\x44\x7b\x74\x43\xb7\x67\x68\x0f\xee\x8f\x7f\x7f\xef\x59\x8d\x88\x61\xe0\x06\xcf\x69\xe3\xae\xc2\x5d\xd1\xa0\xe5\x2f\x71\x1e\x2c\x88\x2c\xcc\x01\x6f\x87\x25\x6c\x8f\x89\x9b\xc8\x87\x8c\xde\x96\xb1\x41\x48\x5d\xbe\x2c\x53\xaf\x9d\xe8\xbd\xbf\xea\x65\xb1\x7c\xc1\x82\xe2\x05\x5a\x54\x20\x13\x17\x8e\x72\xf1\x13\xc5\xdd\x43\x97\xee\xfc\xa4\x81\xfe\xc3\x7f\xc5\xfe\xd8\x7f\xf8\x70\xec\x3f\xfe\xd2\x94\xbb\x5b\x05\x5d\xcf\x3e\xf0\x86\x7b\x8a\xbd\xd0\x0f\x54\x0d\x30\x00\xa6\x82\x6a\x09\x8c\xd0\x82\x03\xf4\x6b\x38\xf8\x97\xb8\xaf\xac\xa1\xf9\x80\x46\x29\xed\xc7\xd9\xa0\x9e\x08\x6a\xa8\x79\xb1\x2e\x67\xb2\xcd\xc1\x3d\x04\xb5\x8b\x01\x38\x70\x01\x4e\xf2\x03\xb5\x39\xc9\x0a\xb2\x05\x55\xa7\x25\xd0\x4b\x6a\x0e\x7e\x67\x75\xd4\xc5\x77\xb9\xd1\xdd\x0b\xd1\x19\x89\x36\x25\xba\xc0\x94\x2e\x16\x6d\x0d\x5b\x1f\xb5\x2b\x78\xeb\xda\xc4\x40\x63\xd4\x0c\xef\xf5\xbe\x6d\xcc\xb6\x6d\x81\x89\x6f\x6a\xbd\x7d\x2e\xbc\xb7\x48\xc4\x4e\x38\x43\x1d\x0e\xde\x98\xb5\x56\x2b\x75\xc0\x58\x85\xea\xac\x04\x13\x60\x02\x75\xf2\xe4\xe5\x96\xf7\xb4\x1f\x7f\x5e\xb1\xed\x8a\x88\x73\x71\xc3\xf4\x71\x06\x74\xfb\x62\xac\xfb\x5f\xa8\x86\x80\x5c\xb0\x07\x67\xc6\xfa\x5e\x67\xf0\xf8\x69\xf4\x97\x83\x6e\x7b\xba\xc3\xc4\xa5\x5c\xd6\x85\xa8\xb3\xa1\x27\x56\x7d\x18\x78\x2d\xe0\xca\x96\xd3\x1b\x4e\x6d\x3e\xdd\x78\x6d\xd2\xd9\x35\x2b\x71\x39\x6e\x77\x5b\xb2\x60\x50\x81\xff\x27\x41\xa7\x0d\x57\x8e\x9e\x86\xcd\x90\xe3\x76\xf2\xc8\xc5\xd6\x77\xb4\x30\x8d\xbe\xfa\xe1\x8e\xc0\x93\x22\x8c\xc7\xf9\x94\x2a\x46\xfa\xd9\x62\xa2\x41\xef\x0a\xbf\xb3\xa0\x97\xba\x83\x58\x04\x1a\xdc\x50\xe1\x03\x4e\xe8\xaf\x55\x9d\x96\x70\x1a\xfd\xda\xeb\x31\x41\x2b\xc4\x23\x2b\x5e\x6f\x78\x4d\x8b\x8e\x34\xce\x9a\x86\x32\x64\x90\x11\x2d\x53\x5e\x66\x7b\xbd\x15\xaa\x18\x69\x02\x0b\x3d\x34\x9c\xc0\x76\x18\x80\xfd\x61\xd1\x54\x98\xf2\xb3\xfb\x8f\x59\x3f\x9e\xbc\x74\xfd\xb3\x9a\x8f\xce\x9e\xfa\xf0\x7e\xd5\xed\x77\x8f\x7c\xcf\x48\xf3\x68\xd5\x59\xc9\x9b\x57\xc2\x62\x16\x36\xea\xa8\x0d\xb0\xd1\x21\x81\xef\xa1\x39\x53\x8e\x29\xb3\x44\x18\x74\x3f\xbf\xc2\x52\x2f\x39\x33\x67\x16\xa2\xfc\xf1\x64\xed\x64\x74\x18\xba\xe6\x75\xd1\x52\x6f\x71\xce\x4f\x1d\x34\x96\xc9\xcc\xca\x49\x4f\xd7\x3c\xdf\x72\x91\xb5\x7c\x20\xf1\xdc\xf2\x99\xe8\x82\x0a\x74\xd3\xe2\x4b\x38\x00\xa8\x77\xa6\x8b\x38\x0e\x28\xb4\xbb\x3d\xed\xfd\xa4\xf2\xdc\x86\x8a\xea\x63\x17\xdc\x2a\xaa\x1b\x8a\xaa\x53\x6f\x2f\x05\x99\x0f\x8c\x43\x8a\x79\xf3\x0a\xc8\x87\x7e\xa3\xfd\x06\xe4\xbf\x9f\xb9\x22\xc2\x38\x90\x83\xec\xab\xdb\xef\x56\x57\x34\xe4\x56\x24\x1d\x7b\xc3\xad\x22\x29\x37\x26\x29\x6d\xda\x62\xb4\xf3\x41\xeb\xf3\x36\x55\x18\x26\x50\x67\xb3\xb6\x15\xc4\x4b\x66\x07\x2e\xb5\x3a\xa6\x28\x29\xf5\xd5\xe5\xc3\x7d\x71\x28\x52\xcc\xe6\x80\x61\x63\xe6\x6a\x0d\xf9\x06\x83\x21\xdf\xd0\x6f\xd0\xdc\x61\x3f\x1f\x0b\x10\x71\x10\xd8\x8d\xfc\xec\xd5\xae\xa4\xca\x5d\xb9\xa9\x89\x5b\xde\x70\x4b\x4d\x2a\x8a\xad\x4e\xfd\xf5\x15\x88\xc0\x57\x2a\xd2\x99\xa5\x37\x1e\xfa\xfc\xa9\x35\x14\x18\x0c\x42\x01\xfd\x67\xfe\xc3\xaf\x6e\xbc\x5b\x5e\x06\xf1\x30\xf7\xf7\x5b\x55\x15\x45\xf5\xa9\xd5\x0c\x8c\xec\x1d\x57\xc3\xeb\x7a\x7c\x53\xd9\x1e\x6f\xc5\xef\x3f\x27\x66\x48\x1b\xa1\x87\x39\xde\xf9\xdb\x2f\xd7\x6d\x11\x0d\x05\x86\x7e\x83\xae\xff\x36\x7a\x53\xa7\x28\x6d\xc4\x9e\xc4\xb2\xdf\xc7\x30\xcf\xbd\x6d\x3a\xdc\xb8\x23\x89\x87\xc3\x5b\x04\x5c\x0d\x8b\xd0\x08\x73\xd1\x0d\xec\x98\x77\xe7\x8e\xf8\x6a\xb0\xd6\x96\x49\x6b\x36\x07\x8f\x98\xb6\x74\xae\x88\x83\xd0\x11\x53\x71\x0a\xae\x47\x7f\x26\x3c\x32\x31\x24\x48\xf3\xdc\x1b\x4a\xf8\xea\x5d\x2e\xe6\xc6\x03\x59\xd5\xc5\x6d\xdf\x37\xdd\x6d\x00\xc7\x2a\xd5\xc7\xf0\x4d\x01\x17\x08\x29\x10\x8a\x21\x87\x31\x95\x6a\x49\xe1\xb6\x40\x01\x74\xc1\xb6\x0a\xcc\xa3\x2c\x77\xa4\xc9\xdc\x02\xb8\x01\x79\xb8\xee\x2c\x7e\x45\x35\xa7\x72\xab\xe0\x1e\x3c\x85\xd5\xd5\xf8\x25\x75\x00\xa3\x39\x55\x63\x65\xd1\x27\x69\x65\xc2\xbf\xae\xdf\xba\x40\x95\x95\xe4\x54\x97\x69\x54\x5d\x7f\xf8\x14\x62\x06\xd5\xdb\x61\xee\xe6\xc6\x49\xaf\xc1\x41\x9c\xf9\x89\x65\x33\x65\x6e\xb0\x6c\xe4\x30\x04\x67\xe4\x41\x26\xc4\xc3\x64\xaa\xb7\x12\xc2\xb9\x79\x52\xa8\x34\x0d\x26\xd5\x5b\x16\x52\x52\x94\xe5\x1d\x6e\xfe\xdb\xa5\x40\x0a\x8a\xf2\x8c\xb9\x85\xee\xe8\xf9\xa0\xf0\x29\xec\xc2\x41\x14\xbc\x32\x9a\xc3\xe9\xa8\x69\x80\x58\x78\x15\xd4\x14\x6e\xb7\xb8\x73\xc6\xdc\x62\x83\xb1\x08\x96\xc1\x68\xb7\xc2\x82\xc2\xa2\x22\x4d\x51\xf3\x21\x88\xce\x2b\xcd\x2f\xca\x2b\xcc\x2b\xc4\x3c\xd0\xba\xa9\xea\x73\x0b\x73\x0c\x39\x79\xb8\x01\x5d\xdc\x72\xf3\xf2\x72\x72\x35\xb9\x68\x3f\xe9\x9d\xdc\xc2\x6c\x43\x6e\x9e\x3b\xf6\x9f\x99\x0d\x03\x28\xeb\xdb\x0a\x04\x74\xf9\x16\xd8\x0f\x28\x63\x61\xa1\xd1\xa8\x89\x91\x36\x52\x45\xb9\xc6\xdc\x42\x01\xaf\xc3\x68\xaa\x20\x37\xd7\x90\xa7\xb5\xcc\x45\x6d\x76\x5e\x6e\x76\x41\x96\xfb\x43\xcb\x96\xa2\x14\x60\x26\xd5\xa4\xb8\xab\x1a\x47\xbf\x99\x9d\x9b\x97\x5d\x90\xe3\x7e\x13\xff\x2c\x4c\xfb\x7a\x4e\x65\xaa\xbb\xaa\x6b\xd1\x96\x5c\xeb\xa3\x39\xee\xc5\x11\xe7\xd0\x50\x9c\x0d\xb1\x98\xed\x56\x98\x57\x64\x28\xca\x67\x0a\x0b\x0b\x0a\x0a\x45\x78\x0b\x92\xa9\xa2\xc2\x82\xa2\x22\x4d\x26\xbc\xfc\xeb\x64\x63\x6e\x89\xc1\x58\xe4\x0e\xc9\xb0\xf8\x05\xb8\x0c\x1c\x29\xa5\xc7\xdf\xea\x29\xd1\xef\x2c\xd4\xd8\x76\x7e\xfc\xa0\xda\xa7\x93\x1f\x83\xf3\xdc\xb0\xd7\xe6\x4c\x13\x2c\xdd\xf4\xb4\xd7\x6e\xfc\x06\x73\x4f\x41\x00\xcc\x13\xb7\x5d\xfa\x5c\x7f\x47\x7b\xe7\xf3\x4b\x07\x2f\x89\x30\xef\x14\x06\xe0\x5c\x11\x67\x4a\xf7\x38\x1c\x8c\x8e\xc8\xe0\x60\xab\x0b\x0c\x0c\x06\x4f\xe8\x73\x07\x83\x15\xee\x29\x98\x9d\x2c\x47\xfd\x79\x2b\x97\x9c\xc4\x83\x7e\x19\x3f\x92\x56\x7d\x09\x6a\x58\xc1\x82\x5e\x51\x97\x54\x1d\xf7\x0d\x5f\x57\x5d\x5d\x27\x2a\x3d\x72\xd9\x17\x9b\xe4\xed\x5e\x98\x20\x72\xe8\xa9\xea\x71\xe2\xc0\xd3\x9a\x70\xdf\x0b\xac\x09\xa2\x2d\xe1\xbe\x17\x58\x5f\x24\x04\xe2\x4e\x6e\xd3\x82\xf9\x81\x3e\x5a\x9f\xf9\x67\x8f\x2f\x10\xb3\x69\x5c\x14\x86\x49\x38\x70\x52\xd7\xcb\xf7\x45\xa9\x9b\xbe\xdf\xf5\xdd\x5d\x18\x1a\x06\x31\xb8\x4c\x34\xfb\x82\x89\x03\xbd\xa2\x36\x71\x77\xfc\x37\x3c\xbc\xc6\x5a\x33\x46\xbf\x70\x23\x58\x34\x3d\x37\xd5\xf0\x3a\xf4\x4d\x65\x75\x54\x57\x37\xab\x93\x77\xc1\xab\xbc\xcd\x50\xbf\xc9\x5a\x5f\x35\x27\xaf\xdb\x2a\xce\x24\x39\xb1\x10\xcb\x4a\x76\xbc\xea\x6e\x8f\x49\x1a\xce\x79\xfb\x2f\x9c\x23\x58\x4c\xf4\x1c\xff\x2b\xdf\xc3\xd8\x63\xe0\x0b\x13\xc4\x1d\xe7\x3e\x0a\xec\xd6\x76\x7f\x74\x76\xef\x39\x11\x26\x1c\x43\x5f\x1c\x2b\xe2\x78\xa9\x96\x53\x79\xa2\xcb\x10\x2f\x74\x46\xe7\x21\x8f\xc1\x05\x9c\x9f\x3c\x01\x67\x41\x75\x17\x9c\x9f\x0c\x41\x67\xb1\x67\xbc\xa5\xc4\xb6\x15\x6e\x3f\x2b\x75\xfb\xb3\x7e\x0a\xa8\x92\xc7\x24\x24\xc4\x08\x96\x6b\x74\x4c\x42\x4d\x83\xf8\x8e\xa2\xa1\xa6\xa6\x41\x90\xae\xd1\x0d\x35\x09\x31\xe2\x32\x05\x14\xcb\x55\x53\xfb\x36\xcf\xa9\xee\x46\xff\x1d\xcb\x04\xdd\xdc\x4a\x56\x67\xf6\x0d\x65\xe1\xe9\x43\x7a\x26\x3f\xd2\x6c\x7a\xf8\x0a\x3b\x12\x9e\x2a\x36\xb2\x2f\x0e\x29\x4a\x6a\xf8\x9e\xef\xab\xf1\x15\xbc\xd9\x04\x31\xac\xad\x34\x30\x76\x33\xf8\xe2\x04\x61\xc7\xaa\x05\x81\xb3\xb4\xb3\x16\x9c\xdd\xbb\x4a\xc4\x09\x9b\xad\x25\xf0\xbe\xbc\xf0\x86\x28\x99\xe8\x1b\x97\xaf\x7c\xdf\x57\x1a\x70\x1e\xf2\xc4\x56\x96\x21\xe8\x8c\x2e\x4f\xbc\xc0\x19\x9c\x9f\x3c\x06\x17\xa1\x67\xbc\x65\x29\x78\xb0\xf0\xa9\xbc\x21\xa1\xe6\x45\xf6\x6d\xf9\xb5\x19\x31\xb4\x65\xbf\xa6\x41\x84\x4f\xe5\x43\x59\x4b\xf7\x78\x56\xea\x86\x1b\xec\x73\x75\x0d\x8f\x4f\x1f\xc2\x42\x7e\x64\xaf\xe9\x21\xbc\xce\x8e\xc4\xa7\x8a\x16\x2b\x1e\xba\x59\x1d\x6d\x45\x86\x0e\x7d\x15\xa0\xd6\xc9\xbb\xfe\x2e\x9c\x8e\xee\xfa\x90\x05\x6f\x56\xea\x78\x68\x36\x81\x29\x97\xd7\x51\x7f\x42\x00\x87\x2b\x51\xc4\x38\xe4\xb0\x52\x8b\x95\x18\x07\x1c\xac\x44\x51\x6c\x83\xc5\x5f\xc0\x54\x98\xd1\xcc\x8c\xfc\x01\x54\x8b\xc0\x43\x0b\x1e\xa0\xfa\xe0\xe1\x0f\x22\xcc\x88\xfa\x02\xa7\xb6\xe1\x62\x06\x73\xcc\x8b\xb9\x14\x56\x32\xa1\x89\x33\xb2\xff\xd9\x40\x9d\x2e\x0d\xb1\x78\x49\x19\x52\xa6\xe4\x29\x0d\x95\xd2\x04\x65\xa3\x8e\x4a\x85\x0d\x7c\x8f\x1a\x1a\xfe\xd7\x53\x69\x92\xa7\x65\xa8\x94\x29\x65\x49\x83\xa5\x61\x52\xaa\x91\x15\xa5\x7f\xeb\x7a\xde\xe2\xe0\xd5\x20\x6f\x18\x86\x7e\x5a\xa8\x61\xd1\xcf\x1b\x87\xe1\xab\x41\xe2\x18\x50\x2f\x83\xf1\x30\x43\x03\x4b\xf8\xbf\x77\x6c\xe0\x8c\x65\x38\x7e\x0c\xaa\x05\x4c\x31\x6b\xb9\x14\x56\xd9\xa7\xb6\xca\x74\x81\x85\xdb\xac\x83\x4e\x7e\xcc\x9c\xc9\x75\xde\xde\xf7\xf3\xef\x1a\x68\xc7\x78\x88\xc7\xf6\x0f\xf9\xa1\xfb\xc6\x74\xfa\x08\x38\x70\x03\xae\x40\xd1\x12\xa8\xc1\x0d\x30\x1a\xa7\xc1\x12\xc1\xfc\x80\x86\x25\x30\x1a\xa6\xc1\x06\x29\x10\x57\x80\x88\x03\x3b\x44\xcb\x5c\xb3\x27\x27\xa9\x79\xf4\x3d\xca\x63\x30\x3c\xe2\x21\x18\x1c\x58\xe9\x15\x5d\x8f\x8c\xeb\x7d\x40\xa3\xe3\x48\xb0\x03\x1d\x7c\xf2\x0c\x02\x60\x55\xb9\xe8\xf3\x13\x38\x06\xf6\x9d\x3c\x74\x3c\x7b\xfb\x27\x11\x56\xa5\x3d\xc3\x00\xfc\x44\x83\xba\x91\x68\x87\x8e\x82\xd2\x92\x92\xcb\xc2\x26\x9b\x12\x59\x87\x1e\x13\x1c\xe0\x60\xdc\x26\x98\x89\xe3\x85\x35\xab\x16\x6c\xb7\xd2\xcf\xbe\xb7\x56\x89\x38\x7e\x13\xce\xc4\x71\x2f\x5f\xf6\x7b\x41\x3f\x57\xbf\x13\x71\x8c\x54\xc3\x81\xb3\xe7\x13\x54\xa1\xca\xd3\x46\x3f\x7f\x78\x81\x0a\x54\x7f\x58\xe9\x07\xda\x9f\x3b\xd7\xf0\xcf\xf5\xd6\xb6\xb8\xae\xc7\xa4\xeb\x69\xb4\x22\xde\xa6\x6d\x12\x9f\x8e\xa4\xe1\x3a\xff\x10\x9f\x2a\x96\xb1\xba\x1e\xdf\x20\xbe\x47\xff\x21\x6b\xa3\xe9\x6e\xd0\x83\xfa\xe0\xc1\xab\xa0\xbe\x65\x3b\x79\x63\x36\xc1\x13\xb6\x47\x0d\x5f\x72\xb3\x02\x97\x2c\x11\x2c\x33\xe8\x25\x81\xef\x75\x83\xdb\x41\x18\x05\x6e\xe2\xc6\x13\x97\x22\x3f\xd0\x7e\x70\xa9\xe5\xc4\x09\x11\xdc\x0e\xe2\x28\x74\x13\x51\x2d\x2d\xe1\xe0\x4b\xf6\x21\x2f\xf4\x98\x2c\x51\x5c\x05\xeb\xa7\xb0\xa8\xc1\xc4\x4d\x65\xb1\x9b\x8e\x4b\xaa\xae\x13\xaf\x6e\x65\xfd\x14\x92\xda\x35\x2e\x29\x29\x4e\x40\xfd\x0b\x20\x5c\xb0\xb5\x3b\xb9\x35\x82\xce\x9c\x0a\x4f\xb9\x87\x81\xbc\x8e\xee\xf2\x67\x47\x2a\x40\xfd\xf0\x9f\x04\x6b\xcd\xeb\x14\x9b\xc6\x64\x6b\x2e\xa3\xac\xbe\x72\xde\x96\x4f\x70\xdb\x06\xa3\xd0\x4d\xd8\xb8\x51\x1f\xb9\x48\xbb\x48\xdf\x72\x62\xa3\x88\x6e\xdb\xac\x79\x9b\x75\x76\xc9\x7b\xa2\x34\x83\x7e\xef\xec\x7b\xdd\xb6\x7c\x6e\xe7\x7b\x4c\x16\x6f\x7f\xbe\x57\x3f\x9e\x35\xeb\x27\xf1\x16\x35\x74\x73\x56\xb6\x2a\x60\xf7\x78\x16\xf4\xac\xa4\xbe\x0a\x93\x59\xbf\xdf\x59\xe8\x96\x0f\x65\xfb\x1e\x83\x1b\x6c\xaf\x95\xcd\x99\xad\xf2\xc2\xd3\x04\xfe\xf9\xd3\xff\x43\x8b\x6a\x44\x13\x14\xed\x80\x71\x28\xdb\x25\x69\xc1\xd7\x7c\x0d\xc6\xb9\xec\xd3\xd1\xef\xa9\x7c\x74\xf2\xfb\xe6\x34\x0e\xa7\x45\xa3\xf6\xcd\xa1\x82\x6a\x35\x38\x4e\x1f\x71\x1f\x97\x69\x55\x3e\xa8\x1c\xb5\x71\xe5\x12\xf1\xdc\x08\x4a\x55\x5b\xd9\xba\xc7\xb8\x47\x0b\x83\xba\x71\x00\x2a\xaf\x88\x06\x45\xca\xc6\x75\xd9\x81\x5a\xec\x42\x57\x08\x96\x26\x8a\xaa\xd5\xd2\xcb\xe0\x0a\x5b\xa1\x0b\xde\x05\x57\xdc\x6a\x79\x59\x50\xf9\x48\x9a\xde\x7e\xdc\xf2\xac\xa0\x79\xe3\xb5\x53\x96\x5c\xfe\xce\x5f\x54\xd5\xc2\x5c\xe0\x41\x09\x21\xb0\x5b\x23\x6d\xb5\xbc\x04\xd7\x2d\x23\x2d\x83\x2d\x3a\xbc\x69\x09\xb6\x6c\x92\xb4\x78\x53\xf2\xbc\x7e\xdd\x54\x77\x4d\x30\x28\x50\x73\xfb\x4f\x54\xc0\x2a\x2d\x7c\x75\x04\x2e\xde\xcc\x14\x95\xd2\xfe\x60\x70\xd3\xc9\x7f\x8a\xb1\x33\x80\x93\x79\x04\xf8\x41\x0d\x38\xde\x85\x61\xd2\x2f\xe0\xe2\x20\x05\x78\x71\x87\x57\x9d\xd9\xd5\x2c\xac\xb8\xf8\xe6\xc5\xcd\xd7\x98\xf1\x30\x66\x2b\x78\xc3\x5c\x0d\x4c\x39\x0c\x83\xbe\x85\x41\x42\xc7\xa7\xe7\xdf\xbd\x74\x99\xa9\xaf\x3f\xdd\xb1\x5f\xd3\x16\xde\x10\xb1\x74\x38\x52\xeb\xb6\x0a\x38\x18\xfd\xe6\x62\x20\x26\x6a\xb0\xf0\x53\x8c\x87\x71\x18\x20\x1c\x5e\x77\x73\xd2\x3b\xc9\x8c\x41\x91\x6f\x2c\xce\x33\x6a\xf7\xb6\xb6\xed\x15\x75\xd4\x2b\xa0\x09\x62\x9f\x7f\x44\x6f\x8a\x08\xdd\x32\x86\x17\x7b\x3e\xa2\x8f\xb7\x1e\x38\x2a\xe2\x36\x09\x38\x10\x83\x7e\x1f\xf1\x87\x50\x9b\xf0\x46\x57\x84\x36\x2b\x27\x37\x53\x8c\x38\xb1\xea\x4d\x4d\x58\xcc\xae\xd0\xc0\x94\xa7\x87\xb2\x84\x48\xf0\xd8\xfe\x18\xc5\x8f\x98\x9a\xad\x1b\xaa\x82\xb4\x29\xdb\x73\xe3\xd3\x2a\x32\xcb\x72\xc4\xba\xd4\x3d\xc1\x15\x71\x4c\x7d\x68\x49\xf8\x16\x5c\x86\x19\x38\x0b\x03\x35\xe8\x03\x8e\xa8\x81\x31\xcb\x04\x83\x22\xaf\xb8\x39\xbd\x58\x6b\x32\x15\x57\x54\xa4\x17\xa4\x17\x89\xc1\xd5\x51\x75\xbb\x0e\x30\x21\x9d\x19\x9d\xef\x83\x3b\xf8\xb5\x80\xfb\xf9\x6d\xbb\xab\x35\xa6\x22\x83\xe9\xd0\x5b\xfa\x9d\xd5\x82\x29\xb6\x20\x6b\xd7\xf6\xdc\xb0\xed\x9a\x75\xf5\x5b\xdf\xde\x73\xbc\xe6\xa0\xd0\x9a\xd8\xdc\xa2\x29\x32\x14\x16\x55\xb7\x6e\x4b\x2b\x15\x5a\xb6\x54\xac\x5a\x8b\x1a\x54\xce\xdb\xae\x49\xdf\x9d\x5e\x66\x2a\x2f\x2e\x2e\x13\xba\xf6\x7c\xfc\xe1\xa1\x73\xcc\xd9\x1b\xf5\xb7\xee\x6a\xcc\x41\xdb\xb9\xc6\xfc\xa6\xfc\x46\x21\x11\x22\xfc\x61\x21\x6a\x60\x3e\xf3\x76\xf0\x28\x50\x2e\xd0\x46\x84\xef\x8c\x08\xea\x7c\xb3\x39\x52\xbc\x31\xf3\xed\x85\x67\xc6\x32\xdd\x38\xbc\x01\xdd\x71\xb2\x06\x03\x97\xe0\x1c\x74\xc2\x71\xc2\xf6\x2d\xe8\x88\x76\x21\x9a\x5d\xad\xe1\x8d\xf7\x40\x80\x95\xd7\x4f\x0a\xf7\x60\xe4\xdb\x30\x07\xe6\x68\x94\xa7\x58\x9d\xbc\x0d\xe2\xb8\xd4\x55\xdb\x53\x36\x34\x63\x14\x4c\x71\x43\xd9\x60\x2a\x25\x25\x2d\x2d\x4a\x5b\x03\xb1\x14\xdc\x62\xa5\x89\x12\xa9\xab\x89\x36\x45\x26\xb8\x5b\xca\xf1\x0b\x0c\xff\x34\x70\x77\xfe\xa1\xf7\x9a\xdd\xcd\x4f\xe1\xbb\x13\xbb\xdb\x23\x93\x17\xb9\x4b\xab\xb1\xfd\xc5\x11\x87\xf9\x7c\x8f\x88\xea\xe7\xe2\x20\x76\x3e\x6f\x16\x51\xdd\x6b\xf3\x49\x22\xaa\x2d\x36\x1f\x88\xa8\x46\x71\x10\xdb\x9b\x02\xe3\x59\xb3\xfa\x08\x6b\xeb\x29\x0d\xa0\xf6\x03\xbd\xaa\xb7\xd1\xac\x06\x3d\xf7\xe7\xbf\x7e\xf0\xf0\xf8\x97\xf7\xa0\x4b\x2c\xa8\x5d\x71\x2e\x0e\x96\xec\x79\x9c\x2b\xa9\x59\x98\xfb\xb4\xf3\xfe\xad\xf7\x04\xb3\x49\xf1\x90\x17\x7a\x4d\x8a\x5b\x4b\x3a\xc7\x0e\xd2\xa8\xd2\x7d\x41\xed\xaa\xa2\x52\x41\xb9\x0a\xec\x7d\xbe\x16\xcc\x81\x0a\x2b\xcc\x1a\x05\xe7\xbe\x48\x40\xe8\x0d\x54\xf8\x4c\x5d\x85\xf6\xa8\xec\xe2\x55\x54\xaa\xcd\xd0\x9c\x08\xbd\x3c\xea\x69\x55\xba\x0c\xd5\xa0\x57\x48\x6a\x39\xea\x51\x4d\x5b\x23\xeb\xe9\xff\x84\x62\x3d\x40\x4f\x2b\x61\x38\xa8\x7f\xe3\x5f\xc8\x2a\x66\xd3\x6f\xbc\xea\x60\xb9\x8e\xaa\xd6\x51\x0a\x6e\xca\x1d\xa0\x59\xf7\xb5\x6b\xd1\xfe\x7b\xf4\xaa\x47\x97\x95\xee\x0f\xc7\xa0\xeb\xfb\xe8\xa9\x85\x03\xac\x0e\x65\x60\xca\xe3\x15\x7e\xfc\x27\x57\x76\xae\x7d\x4b\x98\x89\xee\x95\x38\xed\x11\x2a\xd7\xae\x75\xbb\xc7\xdf\x99\xe2\x56\x95\xdc\x60\xa8\xaa\x32\xd3\x66\xda\xed\x09\xcf\x4c\xc0\x1a\x6e\x21\x0f\x26\x54\x73\xbe\x7c\xfb\xf6\x7d\xc1\x69\xb6\x21\x10\xb7\x90\x57\xc9\x47\xf4\xaa\xcf\xb1\xa0\xf7\xe3\x40\xce\x83\x03\x0f\xdd\x57\xad\x60\x46\x6f\x03\xff\x9f\x62\x38\x0d\xb3\xa8\xd1\xf4\xbf\x81\x3d\x96\x58\x6c\x31\x5c\x17\xf2\x2a\x5f\x0f\x54\x9f\x63\x55\xa9\xbe\x56\x47\xd9\x28\x99\x20\x84\x85\xab\x3c\xa8\xe1\x07\xde\xea\x76\x83\x5a\x95\xea\xeb\x71\x82\x97\xf4\x9c\xae\x47\x86\x7a\x1a\xe9\x4e\xaf\x5b\x73\x04\x5c\xa4\x88\xae\x8e\x83\xcd\x7c\x5d\x93\xa8\x4a\xf5\xf0\x00\x7b\x45\xd2\x89\x53\x19\x67\xb4\x66\x13\x7d\xe6\x54\x59\xf5\x09\x11\x59\x85\xaa\xeb\x53\x59\x06\x0b\x2b\x14\xb7\x6e\x74\x3e\x06\x5a\xa3\xf2\x60\x64\xcf\xf5\xd2\xd3\x24\x5e\xe5\xa4\x96\x5d\xfd\x93\x55\x31\x8c\x0c\x42\x79\x95\xdc\x49\x06\x6a\xd7\xad\xbc\x8a\xb1\xef\x0b\xcb\x6d\x8e\x3d\x23\xeb\xe9\xb6\x98\xfc\x79\x5d\x8f\x47\x9f\xc2\x3b\x41\x25\xb7\x93\x1d\x3e\x90\x1c\xdd\x2c\x6e\x99\x5f\x32\xe9\xec\xa2\xe8\x68\xb7\xac\x2c\x43\x5a\x49\xd6\xc9\xf5\x6e\x25\x59\xe5\x86\x92\x12\xf8\x18\x3e\x76\x2b\x29\x31\x94\x67\x95\xac\x3f\xe9\x96\x55\x92\x66\xc8\xca\x62\x54\xf6\xf6\xb2\xe8\x68\xfd\xa9\x99\xa6\x85\x11\xee\x67\x57\xbf\xb6\x7f\xb6\x16\x0e\xf2\xbd\x6a\x85\xca\x4e\x2e\x1b\x39\xde\xca\xa3\x27\xf1\xcf\xd5\x92\xc9\xc6\xed\xad\xfd\x50\x5c\x75\x52\x9d\x55\x94\x16\xfc\xae\xfe\x07\x76\x86\x17\x54\xf6\xb2\xd4\x33\xfc\x48\x76\x14\x2b\xa8\xec\xec\x7c\x6d\xb9\x56\x82\xc8\x16\x80\x0a\x5c\xc1\xd5\x5c\x0a\x6a\x70\xb1\x76\xdc\xbb\xe0\x11\x07\x5a\xb4\x3b\x84\x0a\x54\xa0\xdd\x56\xd4\x2e\x28\x5d\x50\xfe\x9a\xb0\x7b\xf0\x6e\x8f\xd6\x21\xcc\xac\xba\x4f\xe2\x3f\xd2\x7e\xf4\x49\x6d\x77\x9d\xd8\xfa\x64\xf7\x5f\xbb\xff\x64\xca\xaf\x95\x7e\xf4\x91\x46\x3a\x2e\xf9\x70\xd2\xeb\x16\x05\xfc\x65\xf1\xdf\x21\x58\x5e\x8a\xc4\x6b\x78\x3d\xd6\xf2\x52\x3c\xfe\x02\x1b\xf1\x1c\x74\x22\x53\x91\x5d\x55\x9e\x57\x99\xd3\x94\xdb\x94\xd3\x92\x57\x93\xb7\x3b\xaf\x3a\xbf\x38\xb7\x38\xbb\x10\x37\xff\x89\x43\x60\x5b\x1e\x14\x32\x79\x70\x0f\x9a\xa0\x03\xee\xd5\x31\x12\xd5\x00\xef\xe1\xdb\x16\x3b\x0d\x16\xa2\x27\x86\xe2\xa6\x81\x42\x76\x5e\x6e\x4e\x7e\x56\x5e\x62\x5e\x42\x5e\x42\x4e\x54\x6e\x74\xee\xae\xbc\x94\xca\xb4\x0a\x23\x03\x47\x81\x82\xd5\xb0\x1f\xbe\xd4\x58\x8e\x1f\x4c\x64\xa1\x63\x1b\x07\xa7\x31\x07\x92\xf1\xed\x24\x01\xeb\x52\x30\x14\x23\xb2\xb0\x3e\x17\x67\xdc\xc6\x91\xe0\x34\xb2\x3c\xa3\xba\xb4\xb0\xb2\x68\x5f\xd9\xa1\xba\x03\xc6\x92\xfc\xb2\xac\x92\x7f\xdd\x0a\x00\xa6\x0a\x5c\x6a\x61\x1e\x78\x82\x17\xcc\x6d\x60\x20\xa1\x15\x02\x70\x01\xee\xd2\xa0\x3c\x70\xe8\x2b\x73\x85\xac\xac\xfc\x0c\x63\x56\x5d\x68\xd9\xd6\xa2\x1d\x85\xc9\xd5\x99\xe5\x65\x0c\xf4\xff\xf9\x36\x0c\x83\x29\x1a\x65\x23\xaa\x8f\xb1\x79\xbc\xcd\xf6\x16\xa8\x39\xb3\x29\x8f\xef\x35\x29\xc0\xd4\xf3\xf4\x30\xdf\x88\x6a\xc9\x04\xe3\x78\x88\xb2\x76\xaf\x3d\xbe\x6b\x58\xd4\x43\x09\x0f\xfb\x25\x67\x5b\xeb\x34\xbf\x18\x4d\xdc\x61\xad\x63\x8c\x3b\xac\xea\x2f\x30\xb9\x4a\x26\xb3\x49\xa1\xea\xb1\x58\x13\x91\x4c\x1c\x3c\x05\x91\x1f\x69\x7d\xb6\xd7\x44\x83\xc9\xfc\x94\x5b\xc9\x3e\xd7\xaf\x61\xf1\xa9\xe5\xa9\x42\xf5\xd7\x32\x9b\x0e\x91\x1e\xfd\x2a\x16\x9e\x4a\x36\xe9\xbe\x11\xd5\xf0\x9d\xb9\x07\xbe\xcb\xe5\x75\xf2\x4a\xd8\xc6\x25\x27\xc7\x18\x92\xab\x30\x09\x92\xdc\x30\x09\x93\xfa\x82\xee\xe8\x05\x5e\xc9\x55\x86\x86\xaa\x2a\x77\x48\x82\x24\xeb\xed\xbf\x83\x5e\xe0\x55\x55\xd5\x60\xa8\x4a\x76\xef\x83\x43\xd2\xdf\x41\x2f\xf4\xaa\x4a\x36\xc4\x24\x27\xbb\xa3\xed\x0e\x26\xbd\x08\x4a\xdb\x7a\xc8\x61\xbe\x11\x6e\x5b\xe5\x2e\x93\xad\x3a\x74\xf2\x5f\xa4\xe9\xdc\x13\x1e\xa7\xc3\x74\x37\x98\x0e\xd3\x9f\xf0\xb6\x97\x5a\xf9\x0f\x4e\xb7\x7e\x61\xba\xcd\xef\x85\x5e\xf7\x78\x77\x98\xde\x07\xb4\x7a\xbd\xd0\xeb\x19\x6f\x8d\x62\x05\x3e\xe3\xad\x19\xa2\x9e\x27\x61\x27\xd7\x63\xca\xe3\x9f\xff\x5d\xbb\xa7\xd8\x9e\x4b\xd0\xc3\xf5\x0e\xa2\xe1\x3d\xe9\x03\xca\x3c\x88\x96\xbc\xff\xc3\xdc\x9b\xd1\x04\x6b\xcd\x49\x30\x01\xc7\xd6\x3c\xe8\x2a\xba\xb8\x01\xa8\x6f\xe0\xa5\x8b\x87\xae\xc7\xbc\x07\x82\x8b\xf4\xfd\x1e\xa0\x3f\xb8\x7c\xb1\xa8\x6b\x2d\x8c\x1f\x71\xac\x19\x96\xdd\x7d\x57\xb5\xd7\xec\xab\xa3\x48\xcf\x19\xee\xfd\xf9\x13\x22\x77\x1e\xda\x71\xe8\xc2\x07\x07\x83\x18\x8b\x07\xe6\x73\xe5\xe5\x86\xda\xb4\x72\x46\x45\xcb\x52\x53\x2b\xe2\x0d\x69\xa9\xa9\x69\x86\xf8\x8a\xb4\xf2\xd4\x5a\x43\x45\x05\x03\x53\x66\x72\x35\x35\x86\x3d\x09\x35\x9b\x8f\xbb\xc5\xd7\xec\x34\x24\x24\x04\x07\xbb\x25\xc4\x1b\xc2\x6b\xe2\x19\x6b\xb2\xc7\x36\xd7\xc6\xef\x31\xd4\xd4\xba\xb7\xb7\x53\x68\x07\xae\x5c\x45\x85\xa1\x36\xb5\x9c\x51\x65\xfb\x76\xa5\x55\xc4\x1b\x52\x53\xd3\xd2\x0c\xf1\xe5\xa9\x15\x69\xb5\x86\xf2\x72\x46\x1a\xfa\x2b\x77\xfa\xee\xeb\xe7\xd6\x75\xcc\xbb\x36\x6f\xef\xf4\xf1\x3e\xe3\x3b\x07\xdf\x7c\xe3\xe6\x4a\x60\xdb\xcf\x7c\xcb\xd8\xa6\x8d\xd7\x58\x76\x71\xbb\x50\x8d\xf5\xf0\xfa\x34\x98\x18\xea\xe7\x3b\x12\x9d\x7d\x5f\xc7\x15\x78\xde\xe2\x38\xb2\xcb\xe7\xf4\x33\x20\x1f\x5e\x67\x0a\xc3\xdb\x97\x1b\x34\x6b\x60\x08\x0c\x80\x79\x87\xde\x67\x0c\x17\x6a\x8b\x3e\x12\x8c\x8f\x17\x7f\xf6\xe6\x69\xe6\xe0\xe6\xb2\x25\x2b\x34\x06\x03\x0a\xdb\xab\x85\x75\x05\x11\x69\x43\x23\x99\xe3\x85\x8d\x71\x06\x4d\xe4\x96\x95\xab\xfd\xc3\x27\x6f\x8a\xfc\xf2\x54\x67\x79\x65\x79\x79\x79\x59\x56\x69\x8e\x29\xbf\x82\x01\x86\x8f\xfc\x13\xe6\xc1\x90\x27\xc7\x19\x03\x38\x83\xdf\xad\x76\xa1\xba\xba\xa5\xd6\x54\xfc\x1a\x50\x49\x30\xb1\xee\x54\x5e\x5e\x7e\x5e\x7e\xee\x9e\x2b\xd7\xb3\x1a\x36\x30\x15\x91\x85\xa1\x51\x1a\x43\x60\xd1\x3a\xbd\x70\xbc\xbe\xd3\x60\xd0\x54\xa5\xd6\xec\x32\x68\xa2\xd7\x87\x78\xb7\x8c\x69\x9c\x7a\x73\xf3\x85\xec\x57\x8e\x4d\x00\x87\xbb\x30\xe4\xd8\xb5\x5b\x47\xbf\x4a\x07\x79\xf2\xd7\x43\x92\x51\x9e\xf1\xea\x06\xff\x65\xa1\x8c\xa1\x2a\x28\xe9\x4d\xe1\xf0\xba\x82\xc8\xfc\x28\xc6\xb0\xae\x74\xfd\x76\xe1\x51\xf3\xf9\x35\xe7\xbc\xeb\xb6\x7e\x93\x97\xbe\x94\x51\xf9\xda\xcb\x20\x03\xc6\x70\x52\x86\xc5\x4b\x1a\x62\xc9\x10\x54\x8c\x5c\x66\xc9\xb0\x78\xbd\x38\xf6\xea\x65\x3b\xf6\x9a\x21\x79\x49\x43\xa4\x0c\x51\x89\xb9\xe0\x68\x0e\x00\xc6\xfc\x1a\x38\xda\x41\x31\xd4\x3b\x48\xbb\x75\xd4\x02\xae\xb5\xb0\xba\x43\x90\xce\xd0\x0f\x2f\x4c\xc6\xb1\xc7\xc5\x83\xe8\x44\xfd\x4c\x1b\x6a\xe1\x59\x35\x8c\x16\x30\x65\x27\x8a\x06\x83\xa6\xd7\x9f\xb6\xf4\xab\xa4\x86\x28\x40\x15\xf9\x63\x7c\x6b\x4c\xd1\x64\xf7\x0a\xcc\xc9\xb5\x78\x19\x34\x86\x3c\xcb\x90\x2c\xcc\x16\xf2\x67\xed\x0c\x9f\x10\x8f\xaa\x08\xb7\x21\x0a\xa9\x5f\x25\x65\x66\x68\x03\x0c\x34\xc0\x9d\x14\xa1\xf4\x87\xb3\xd2\xc0\xd2\x53\xcc\x04\x7a\x0c\x86\x52\xf8\xca\x4c\x94\xa5\x60\x3f\x2d\x9a\x69\xec\xe7\x7f\xee\x4f\x51\xea\x52\x40\xfd\x77\x19\x06\xf1\xe3\xfc\x8e\xa8\xc6\x51\xfb\x50\xe5\xf6\x07\x9d\x09\x37\xab\xe1\x73\xca\x93\xde\x8a\x83\xa2\xc7\x26\x45\x8e\xce\x75\x37\xa0\x32\x05\x13\x0b\x05\xe5\x2a\x1e\xe6\x83\xb2\xe3\x2f\x98\xfc\xec\x24\x28\x8f\x81\x63\x87\xf5\xc7\xc2\x7c\x87\x9e\x31\xe6\x18\xee\x48\x49\xf3\x5a\x01\xaf\x28\xce\xe4\x67\x1e\x3a\xa2\x81\x4f\xbf\xe3\x1a\x8c\x7b\x76\x46\x1b\xb7\x26\xe5\xe5\xa0\x67\x59\xac\x90\x55\x54\x9c\x5b\xa2\xdd\x97\x75\xa8\x41\x7c\x7e\x0a\x15\x9c\x14\x0a\x4a\x4b\xa8\x02\xae\xb9\xc2\x4d\xc5\x3a\xbc\x49\xbd\x42\xbf\x09\xd7\x28\xbc\xe6\x21\x85\xc2\x04\x45\xe5\xac\xf2\x99\xe5\x33\xf7\x42\xb8\x1b\x4c\xb4\x84\xd2\x70\x13\xde\xe5\xf0\xab\x8e\x26\xbc\x21\x48\xa1\xf7\x14\xd7\x7e\x2f\x99\x5c\x23\x96\xec\xc8\xdf\x16\xa6\x81\xeb\x18\xc0\x2d\x4d\x5f\x36\x6b\x6b\x54\x45\xeb\x2e\x21\x33\x8c\x42\x7b\x29\x14\x1c\x71\x0c\xdd\xd2\xd4\x54\x7e\x48\x7b\xbb\x68\xb5\x9f\x88\xee\x0a\x98\x6f\x0e\xb7\x32\x46\xb4\x8e\x3b\xe4\x5d\x1f\xb2\xd2\x70\x2c\xfd\xcb\x1c\xdd\x28\xcd\x04\x1a\x76\xc2\xbf\xec\xa0\xe7\x41\xcf\x1f\x3f\x49\x6e\xb7\x1c\x74\xf2\x18\x0c\xe0\xb0\xf3\x6d\xcc\x86\x50\x6f\x38\xc2\x18\x14\xef\x27\xdf\x8a\x3b\x9a\xc5\x80\x03\x5e\x83\x3b\xb8\xdc\xa0\x31\xe6\x15\xe5\x1b\xf3\x99\x5e\x4e\xfa\x83\x4b\x3f\x9a\x7d\x2c\xf7\x38\x63\x50\xd4\x5d\x3f\xf2\xe3\xc7\xd7\x18\x43\x29\xbe\x71\x19\x5f\x11\x96\x9a\x9d\x39\x43\x76\x40\x61\x98\x90\x94\xb6\x33\x6a\x6b\x70\xe3\x85\xd6\xce\x03\x6f\x31\x06\x85\x8e\xaa\xb3\xcc\xe3\xf0\x0a\xce\xc5\x46\x34\xa1\xab\x60\x50\x2c\x89\x9d\x98\x88\x4c\x3d\x63\xb0\xd0\xbf\xe0\x30\x78\x24\xc0\xd8\xdc\x77\x8d\x7f\xee\x06\xef\x66\x78\xf9\x14\x78\x7d\x72\xb6\x29\xf7\x72\xd6\xc9\x8c\x0b\x5b\x72\xd7\x87\x31\x06\xfc\x0e\xd3\x2d\xaf\x35\x08\xaf\x80\xeb\x56\xe8\x36\x68\xc0\x07\x06\xc3\x8c\xdf\xe0\xb7\xed\x05\x6d\x15\x77\x47\x19\x19\x83\xc5\xe9\x0c\x86\xe0\x02\xa1\xfc\xe3\xea\x0b\x8d\x1d\x0c\x38\x83\x08\xaf\x7d\x01\xab\xb5\xd2\x1c\x78\x8a\x7f\x59\xe6\x8b\x9f\x1d\xe5\xda\xe1\x7b\xf4\x86\xcf\xf1\x2c\x8c\x61\x0c\x0a\xfc\x00\xbc\xb1\x2b\x08\x2f\xe3\xa0\x35\xbb\xe2\xa3\xe3\x42\xd6\x4f\x8f\x9c\x99\xb8\xf0\xe5\xc1\x0b\xd1\x69\x07\xf2\xeb\x66\xad\x1f\x95\x8e\x4a\xc6\x90\x1b\x5a\x90\x2f\xe0\xe0\x3a\x9c\x7a\xcf\xa0\x39\xba\x04\x82\x67\x7f\x10\xc5\x18\x4a\x2d\x83\xa0\x0c\xb5\xc2\x9a\xeb\x19\x95\x06\x8d\x01\xdd\x21\xa7\x19\xe6\x0b\x45\x45\xf9\x45\x5a\x84\x47\xf0\x39\x56\x49\xce\xda\xd6\x96\x82\xc2\x16\xf1\x72\xd6\x25\xe3\xf9\xba\xbd\xa6\xbd\xb5\x6d\x75\x70\x0c\x26\x82\x33\xcc\xfa\x09\x1a\x9a\xae\x55\xdc\x2e\xfd\x84\x51\x36\x62\x01\xd8\xe9\xe4\x1f\x5c\xfa\xb1\x0a\x5e\x82\xb1\x76\x47\x4f\x3c\x3c\xa5\x93\x87\x83\x1c\xa2\xaf\x39\xe8\xa8\xe9\xe6\x4c\x2e\x78\x79\x1e\x2c\xc7\x5d\x77\x91\x3f\xef\x1b\xd2\xde\x75\xe4\x22\x8c\x2d\x81\xfe\x53\x41\x39\xb5\x03\xf9\xe0\xe5\x0c\xfc\xdb\x72\x83\x33\x35\x67\x17\xc6\x45\x58\x62\x7a\x67\xe8\x30\x48\x32\x40\x90\xf9\xe9\x56\xb4\xdf\x36\x23\x17\x15\x3b\x9f\x6b\x75\x72\xc4\x39\x70\xc4\xfc\x3a\x83\x19\xd2\x72\x0e\x8e\x60\x2c\xc4\xe3\x61\x3c\x8c\xb1\x18\x8f\x47\xf0\x08\xc4\x62\x3c\x1c\x86\xc3\x10\x0b\xf1\x70\x44\x80\x13\xd0\xc1\xe5\x5e\x0e\x04\xf9\xfa\xab\x96\x4a\x73\xab\xae\xc7\x68\x29\x84\x7b\xcf\xbf\xc3\x49\x3d\x77\x75\xd4\x79\x38\x0f\x52\xef\x39\x66\x21\x3e\xe0\xe2\xf1\x3e\x36\xa1\x3f\xee\x79\xc5\x7c\xa7\x7a\x87\x4e\x7e\xa3\xb7\xaa\x8d\xc9\xd9\xd0\x94\x5e\xac\x85\x4f\xbd\x21\x19\x13\xe2\xf1\x1e\xa3\xb4\xed\xad\xbe\x0a\xde\xff\xe7\xab\xcb\x55\xdb\x14\xbf\x5a\x75\xe0\x28\xe8\xc1\xc4\xa1\x9c\x56\xf9\x7a\x34\xb2\xaa\x46\x8f\x1b\xac\xca\xc9\xea\x1b\x66\xf5\xc9\xad\x3e\xd6\xea\xb3\xb3\xfa\xec\x1b\x6f\xb0\x2a\xd9\xba\x46\x56\xe5\x7b\xf4\x6c\x02\x6d\x33\x22\x05\x72\xba\xa7\x1b\x3a\x60\x22\xdb\xdb\x7d\xd5\x2a\x1d\xf8\xb0\xe6\xee\x99\x56\xc1\x37\x13\xb2\x78\x55\xaa\xd3\x25\x5e\xb5\xc4\xa9\x85\xaf\x39\xab\x68\xe1\xa1\x43\x6e\x60\x55\x1e\x56\x98\xfa\x9f\x30\xc6\x0a\xa3\xfe\x09\xb3\xb7\xc2\xec\x96\xfc\x03\x26\x2b\xbe\xc4\xab\x64\x7f\xc3\x94\x1e\x20\xb2\x10\xcb\x3a\xe8\x68\x41\x9a\xc4\x7d\x53\x1b\x01\xce\x93\x13\xf0\xc3\x85\x6e\xd8\x02\xe3\xc1\xfa\xff\x70\x21\x95\x6f\x2c\x36\x18\xb5\x5f\x54\x80\x7c\xb7\xaf\x88\xd3\x0e\xc1\xa2\xbf\xf6\xd7\x56\x9c\x88\xdb\xef\x1e\xb7\x7f\x53\x45\x58\x1c\x2e\x1a\xe8\x76\x09\xbc\xf7\x7e\x85\xca\x8e\x9d\x3e\xee\x43\xb0\x0b\x5b\x70\x1c\x05\x1f\x29\x60\x13\xa4\xbf\xf3\xe1\x88\x6f\xf5\x7e\xee\x28\x47\x35\x05\x5b\x7f\xe1\x71\xab\x02\xe5\xa0\xd6\x5f\x1d\xf1\xaf\x77\x5e\x77\x87\x4d\x98\x4e\xe1\x47\x0a\x6c\x81\x71\x43\xa0\x6b\xe7\x6d\x54\x6e\xd8\x3b\xcd\xfd\x12\x7a\xe3\xa2\x67\x61\x75\x9b\xd2\xe2\x42\xdd\xe3\xc2\x2a\x36\xee\x8f\x87\x45\x1e\x6e\x38\x6d\x2b\x95\xe8\x5b\x81\xf2\x2f\xb4\xc6\x62\x43\x81\x51\x84\x0f\xaf\x40\x0b\x8e\x47\xeb\xff\xc3\x2b\x93\x6b\x22\xd0\xf9\x9b\x78\x77\x98\xb6\x15\x17\x79\x84\xc5\xa7\x6e\xac\x0b\x73\xaf\x0b\x3b\x9e\xba\xbf\x0e\x16\x3d\x73\xd3\xa3\xf7\x8e\x69\xa0\xdc\xb0\xe7\xb6\xfb\x13\xe8\x82\x16\x18\x67\x7b\xf3\x26\x4c\x5f\xf6\xfa\xa3\x7f\x5d\xba\xea\x0e\x72\x50\x53\xb8\xd5\x76\xa4\x77\xab\x02\xe4\xa8\xbe\xe4\xf7\xe8\xdb\x65\x1f\xba\xe3\x26\x48\xb7\x95\xa7\x05\xc7\x3d\xc1\xae\x3d\x3e\xa0\xec\xd8\xf1\x95\xbb\x1e\xbc\x61\xd1\xc0\xfd\x71\xc7\x2b\xea\xf6\xbb\xd7\xed\x4f\x3d\x11\x56\x8b\x8b\xfe\x72\x53\x3e\x65\x81\x81\x35\x3a\x79\x26\xac\x71\xd0\x51\x17\xa5\x3f\xb9\x78\xbc\x81\x07\x31\x03\x3f\xa9\xc7\x1b\xf5\x98\x07\x75\x75\xd0\x5d\x07\xd7\xe1\x20\x64\xc2\x27\xb1\x70\x3d\x16\xf2\xb0\x2e\x0e\xbb\x19\xb8\xd9\xf3\x32\x87\xdf\xad\xc5\xef\xd7\xe2\x77\x6b\x2d\xf2\x00\x3c\x86\x9d\x51\x16\xc7\x64\x8c\xf8\x16\x43\x61\x22\x8e\xc5\xdf\xf1\x77\x37\xf8\xee\x74\xdf\x4f\x72\xe8\x84\xe3\xd0\xd9\x24\x31\xd5\x10\xf1\x32\x84\xe2\x44\x18\x0b\x4f\xe0\xb1\x4d\x9d\x26\xc8\x75\xb4\x07\xc8\xed\x0c\x2f\x3c\x0e\x3d\xf3\xa5\x62\xee\xdd\x88\xc6\x4e\xcc\x7c\xb2\x6b\xd5\xad\xad\xf8\xaa\x85\xa5\xce\xd1\xf0\x0a\xfc\x01\xb3\xf1\x0f\xea\x3c\x6d\x39\xd3\x33\x9a\x43\x57\xbc\x0c\x97\xd1\x15\x5c\xe1\x32\x75\x42\xcf\x0d\xc1\x4c\xc8\x18\xf2\x07\x64\x50\x1d\xab\xb9\xa9\xe8\x0f\xfe\x53\xef\x80\x3f\x05\x17\xd7\x72\x96\x39\xf8\x14\x9f\x5a\xe6\x58\x5d\x78\x2a\xcd\xb1\xb2\xb0\xbf\x5d\x2b\x5c\x00\xb9\x2b\x7c\xc6\xc3\x2b\xbc\xa0\x84\xe1\x68\x7a\x9c\x08\x93\xa5\x3f\x61\xc7\x6c\x13\xcc\x04\xb7\x8f\x81\xbd\x0b\x63\x5d\x8e\xc2\xe8\x4a\x28\xf2\x04\x46\x1a\xf4\xdb\x41\x18\x05\xb3\xe0\xe5\xfb\xc0\xa9\x1a\x12\x75\xd4\xbf\xe0\x12\x57\x3d\x1a\x5f\x6d\xdf\xd8\xe0\x77\x70\x53\x77\xcd\xcd\xaa\x8b\xc0\xc2\xce\xe2\x43\x4c\xbb\x31\xae\x28\x55\x9b\x58\x90\x9a\x99\x18\x9d\x1c\x83\x43\xf1\x42\x72\xc4\x06\x9f\x81\x55\x95\x5f\x15\xb5\xfc\x02\x5b\x8d\x87\x8b\x1a\x72\x9a\x62\x2a\x62\xca\x23\x13\x32\x53\xd2\xe2\xd1\x0d\xff\x4c\x0a\x67\x22\xde\x8c\x48\xda\x94\x37\x2e\xfb\xd5\x2f\xf7\xff\x5c\x75\xf2\x07\xf8\xf4\xcc\x57\xfb\x2f\x7e\xd3\x71\x39\x62\x7f\xf2\xc9\x5d\x95\x59\x7b\x93\xf7\xb7\x57\x96\x1f\xd8\x53\x5f\x7d\x2a\x93\xd9\x97\x53\x1b\xd3\xb4\xab\x2e\xae\xaa\xa2\xbc\xa4\xc6\x54\x59\xf6\x76\xfe\xb9\xfc\x77\xe2\x2a\x27\x55\x8d\xc6\xc9\x98\x5d\x81\xf2\x32\x1f\x70\x7b\xa7\x62\x36\xf3\xdc\x0f\x43\xb9\x9c\x86\x98\xca\xd8\x9c\xd8\x9c\x94\x18\x63\xac\x31\xa6\x3e\xa5\xde\xc8\xa8\x9c\x52\x1b\x8c\x95\xf5\x39\x0d\x8c\xf4\x31\xd6\x70\x89\xcd\xa1\x25\x51\x09\xd1\x09\x59\xa1\xbb\xa3\x6a\xa2\x0e\x64\x35\xd7\x34\xd5\x94\x1c\x48\x68\x66\x7a\x6b\xcd\x5d\x5c\xcb\x91\xf4\xb3\xc1\xad\xc1\x2d\x81\xe9\x91\x41\x91\xc1\xa6\x55\xed\x91\xed\x11\x67\x4d\x2d\x47\x18\x5b\x3d\xb0\xbd\x53\x38\x95\x53\x6a\xf8\xd1\x80\xf2\x2d\xe1\x41\xe1\xe9\x2b\x5b\xb7\x58\x6f\xb4\x6e\xe9\x4c\x3f\xda\x7a\xb4\xcd\x74\x3e\xe2\x28\xa3\x1a\x28\x03\xb9\xf4\xd8\x5a\x71\xc0\xfc\xb6\x01\xfc\xd1\xf3\x74\x3d\x18\x31\x0b\x16\x60\xea\x74\x5c\x09\xa3\xf0\x24\xda\x4f\xc4\x44\x5c\x18\xee\x85\xc1\xbf\xe1\x64\x46\xe5\x21\xc7\x57\xd0\xfb\x3b\x3c\x0d\x71\x9b\x0b\xfd\x6b\xfd\x0f\x07\x3c\x40\x11\x16\x85\x00\xff\xc0\x68\x2c\x2e\x32\x16\x81\x33\xca\x61\xcd\x07\x27\x61\xca\xa7\x79\x9f\xd6\x7f\x70\x8a\x51\x39\xc9\xad\x92\x1f\x04\x8e\x85\x91\xcc\x73\xc9\x3c\x8c\x8b\xdb\xb3\xa5\x24\x3c\x6e\x67\x6c\xd6\x96\xba\x9d\x75\x3b\x8f\x66\xb5\xd5\xed\xa9\x2f\x39\x1a\xb7\xc7\x9a\x41\x98\x08\x87\xb9\x9c\xe6\xe8\xea\xe8\xec\xe8\xec\xa4\x68\x63\x74\x71\x54\x53\x52\x53\x71\x53\x71\x75\x53\x76\x13\xa3\x93\x37\x3f\x9f\xcf\x65\xb7\x85\xd7\x86\x67\x87\x67\xc5\x87\x97\xec\x2c\x0e\x6f\x8b\x6f\x2b\x69\x2b\xae\x6d\xcb\xda\xc3\xf4\x8e\xea\x71\xe6\x54\x8b\x56\x47\x1f\x5d\x5d\x19\x14\x1d\x14\x9d\x12\xd8\xb4\xa5\x31\xe8\xed\x94\x23\x4d\x47\x9b\x2a\xce\xee\x3a\xc2\x98\x93\x7b\x3d\xb9\x9c\x86\xd8\xca\xd8\x9c\x18\x6b\xc5\xc7\x18\x63\xeb\x93\x1b\x8c\xf5\xc5\x55\xf5\xd9\x0d\x0c\x2e\x83\x2c\x2e\x66\xff\x86\xb2\xed\xbb\xc2\x76\x65\x6e\x68\x08\x6b\x08\xeb\xc8\xdc\xdf\xb0\xaf\xb1\xb4\x23\x66\x3f\x63\x33\x77\xfe\x7f\xfb\xee\xdc\xa3\xa3\x7c\xf7\xd0\xa0\x66\x41\x4d\xac\x7d\x41\xbf\x7e\xb6\x6b\x7f\x1d\x2d\x53\xeb\xe8\x87\x5c\xbb\xca\xee\x91\xbd\xcc\x4e\xd6\x5f\xa6\x95\x1d\x95\x75\xd9\xb9\xdb\x0d\xb6\x1b\x6a\x37\xd2\x6e\xac\xdd\x04\x3b\x1f\x3b\x5f\xbb\xb9\x76\xaf\xd9\x2d\xb6\xdb\x68\x17\x64\xb7\xcd\x6e\x87\x5d\xbc\x5d\x8a\x5d\x86\x5d\x8e\x9d\xd1\xae\xcd\xee\x5d\xbb\x2b\x76\xd7\xed\x3e\xb3\x7b\x60\xf7\x9b\xdd\x1f\xf6\xb3\xec\xe7\xd9\xbf\x66\xbf\xc8\xde\xdf\x3e\xc0\xfe\x4d\xfb\x50\xfb\x38\xfb\x1c\xfb\x32\xfb\x76\xfb\x13\xf6\xa7\xed\xcf\xdb\xbf\x63\xff\xbe\xfd\x27\xf6\x37\xed\xbf\xb0\xff\xce\xfe\x67\xfb\x5f\xed\xff\xb0\x97\x1c\x88\xc3\x00\x07\xb5\x83\xbb\x03\xef\x30\xc6\x61\x8a\x43\x97\xc3\x17\x0e\xdf\x3a\xdc\x73\xf8\xcd\xe1\x99\x83\xd9\xa1\x57\x2e\x97\x2b\xe4\x4a\xb9\x97\x7c\x8c\x7c\x8a\x7c\xba\x7c\xa6\x7c\x9e\x7c\xa1\x7c\xa9\x7c\x95\x7c\x83\x7c\x8b\x3c\x4c\x1e\x29\x8f\x91\x27\xc8\xbb\xe4\x1f\xcb\xef\xc9\x1f\x52\x0e\x94\x2b\xa5\xa1\x04\x6a\x0a\x35\x8b\x7a\x8d\x5a\x44\xf9\x53\x01\xd4\x9b\x54\x34\x95\x45\x19\xa8\xf7\xa8\x4f\xa8\xcf\xa9\xbb\x34\x4d\x8f\xa6\xe3\xe9\x0c\xba\x90\x2e\xa7\x1b\xe9\x36\xfa\x00\xdd\x4e\x77\xd0\xb7\xe8\x07\xf4\x6f\xf4\x9f\x0a\x1f\xc5\x42\xc5\x72\x45\xa0\x62\xbd\x22\x48\xb1\x43\x11\xa9\x78\x4b\x71\x49\xf1\xbe\xe2\x9a\xa2\x5b\x01\x8a\x7f\x33\x83\x98\x09\xcc\x14\xc6\x97\x99\xcb\x2c\x62\xde\x64\x76\x32\xb1\x4c\x32\xf3\x36\x73\xd7\x51\xed\xa8\x71\xf4\x70\x5c\xe1\xb8\xca\x71\xad\x63\xa1\x63\xb9\x63\xad\xe3\x27\x8e\xdf\x38\x3e\x71\x7c\xce\x3a\xb0\x8e\xac\x92\x75\x66\xdd\xd8\xb1\xec\x0c\x76\x1e\xbb\x83\xcd\x65\x6b\xd8\xc3\x6c\x07\xfb\x16\xdb\xc9\xfe\xc2\xfe\xc1\x9a\x89\x1d\x51\x10\x81\x78\x91\x51\xc4\x97\x6c\x26\x91\x24\x81\xa4\x90\x2c\x92\x4f\x8a\x48\x29\xd9\x4d\x9a\xc8\x7e\x72\x84\x9c\x26\x5f\x91\xc7\xa4\x87\x3c\xef\x67\xdf\xcf\xa5\xdf\x4b\xfd\xb4\xfd\x3c\xfa\x8d\xee\x37\xb5\x9f\x5f\xbf\xe5\xfd\x36\xf6\x0b\xea\x17\xda\x2f\xba\x5f\x62\xbf\xf4\x7e\x39\xfd\xf6\xf5\x7b\xbf\xdf\x9d\x7e\xcf\xfb\x3b\xf4\x17\xfb\x8f\xed\xbf\xb8\xff\x8a\xfe\xab\xfa\xaf\xeb\xbf\xb5\xff\x8e\xfe\xd1\xfd\x13\xfa\xef\xee\x7f\xaa\xff\x67\xfd\x9f\xf6\xef\x55\xb2\xca\x97\x94\x5a\xa5\x97\x72\x8e\x72\x83\x32\x52\x99\xac\x34\x2a\x4d\xca\x2a\x65\x83\xb2\x55\xb9\x4f\xf9\x96\xf2\x82\xf2\x13\xe5\x4d\xe5\x2d\xe5\x5d\xe5\x4f\xca\x87\xca\xdf\x95\x7f\x0e\xa0\x06\xa8\x06\x8c\x1e\x30\x7e\xc0\xe4\x01\x33\x06\xcc\x1d\xe0\x37\x60\xf1\x00\xfd\x80\xb0\x01\xd9\x03\x2a\x06\xec\x19\x70\x78\xc0\x99\x01\x17\x06\xbc\x37\xe0\xea\x80\x4f\x07\x74\x0f\xb8\x3d\xe0\xe7\x01\xbf\x0d\xe8\x71\x62\x9c\xfa\x39\x39\x3b\x69\x9c\x3c\x9c\x86\x3b\x8d\x71\x9a\xe4\xe4\xe3\x34\xc7\x69\xa9\x53\x80\xd3\x76\xa7\x48\xa7\x3c\xa7\x06\xa7\x43\x4e\x6f\x39\x5d\x70\xba\xec\xf4\xb1\xd3\xe7\x4e\x77\x9d\xee\x39\xfd\xea\xf4\xc4\xe9\x2f\x27\x74\x76\x72\x1e\xe2\x3c\xd5\xd9\xd7\x79\xb9\x73\x88\x73\x82\x73\xa1\x73\xbd\x73\x8b\xf3\x41\xe7\x23\xce\x1d\xce\x6f\x3b\x5f\x70\xfe\xc0\xf9\x2b\xe7\x47\xce\x7f\x38\xff\xe5\x8c\xce\xff\x76\xa1\x5d\x88\x8b\x93\x0b\xe7\x22\xb8\x0c\x72\x19\xea\x32\xca\x65\xbc\xcb\x6c\x97\xe5\x2e\xab\x5c\x42\x5d\x92\x5d\x8a\x5d\xaa\x5c\xea\x5d\xf6\xba\x1c\x73\x39\xed\x72\xc9\xe5\x7d\x97\x6b\x2e\xd7\x5d\xbe\x77\x79\xe8\x02\x2a\x46\xe5\xa4\x12\x55\x9e\xaa\x61\xaa\xd1\xaa\x09\xaa\x59\xaa\xf9\xaa\x25\xaa\x75\xaa\x20\xd5\x36\x55\xb4\x2a\x41\x95\xa2\xca\x52\xe5\xab\x4a\x54\x15\xaa\x7a\xd5\x1e\xd5\x21\xd5\x09\xd5\xdb\xaa\xf3\xaa\xcb\xaa\xab\xaa\xeb\xaa\x2f\x54\x5f\xab\xbe\x53\xdd\x53\x3d\x53\xcb\xd5\xfd\xd4\xce\x6a\x9d\xda\x53\x3d\x4a\x3d\x41\x3d\x53\xbd\x44\xfd\x86\x7a\x95\x7a\xad\x7a\x93\x3a\x42\x1d\xa3\x4e\x52\xe7\xa8\xcb\xd5\x2d\xea\x83\xea\x0e\xf5\x5b\xea\x0b\xea\xcb\xea\x6b\xea\xeb\xea\x5b\xea\x6f\xd5\xbf\xa8\x9f\xa8\x7b\x38\x3b\x8e\xe6\x08\xe7\xc6\x89\xdc\x48\x6e\x32\x37\x97\x5b\xcc\x2d\xe7\x02\xb9\x0d\x5c\x08\xb7\x9d\x8b\xe2\xe2\xb8\x64\x2e\x93\x2b\xe6\x6a\xb9\x7d\xdc\x21\xee\x38\xd7\xc9\x5d\xe1\x3e\xe3\xee\x70\x3f\x71\x0f\xb9\x3f\x39\x74\xb5\x73\x75\x74\x1d\xe0\xaa\x72\x75\x77\x15\x5d\x3d\x5d\x87\xbb\x8e\x71\x9d\xe8\x3a\xd9\x75\xb6\xeb\x22\xd7\x00\xd7\xb5\xae\x9b\x5c\x77\xb8\xc6\xbb\x66\xb9\x16\xbb\x56\xb9\xd6\xb9\x36\xbb\xee\x75\x3d\xe4\x7a\xec\x3a\x2b\xf9\xc0\x23\x78\x24\xf9\x08\xca\xd9\xac\x1f\x3d\x8f\x17\xfd\xb6\xf1\x57\x23\x58\xa2\x98\xbe\x23\x60\xd6\x34\xcd\xff\xf3\x99\x5e\x0f\xdb\x4c\xaf\xef\x3f\x66\x7a\x3d\xfe\xc7\x99\x5e\xdf\xff\x79\xa6\xd7\xe3\x1f\x33\xbd\xc5\xa0\xa7\x95\xd8\x85\xb9\x98\x8b\x5d\x30\x8b\x17\x20\x6a\x38\x9b\xcb\x2e\x61\xe1\x28\x6f\x5b\x8e\x8b\xe2\x61\x04\xfb\x30\x84\xd7\xf5\xf8\x7e\xcc\xd3\x16\x1a\xe6\x62\x23\xac\x44\x57\x01\x57\xa2\xb5\x04\x8d\x16\x5a\x33\x92\x8e\x4b\x4a\x8a\x13\xfd\xa0\x95\xbd\xaa\x18\xc3\x0a\x23\x69\x89\xc6\xb9\xd0\x88\x2b\xc1\x55\x80\x95\xe0\x0a\x73\xa1\x51\xa2\x35\x64\x09\xff\xc2\x82\x07\x19\xc9\x0a\x64\x0c\x2b\x10\x7a\x28\x4f\x5c\x3d\x58\x98\x88\x1c\x70\x38\x51\x20\x71\x6b\x78\x52\x57\x5d\x5d\x47\x82\xb7\x6f\x0f\x26\x75\x49\xd5\x71\x84\x43\x03\xae\x81\x35\x60\x00\x03\xf4\xb9\x91\x3c\xed\xcd\x13\xfa\x7d\x96\x8c\xe1\x05\xb2\x9a\xc7\xee\x09\x3c\x74\xcf\x64\x49\x5c\x52\x01\x4f\x66\xb1\x22\x19\xc5\x8a\x64\x1e\x2f\xa2\x7e\x1b\x4f\xb8\x59\xbc\x64\x72\x9d\xc5\x43\x13\xcf\xad\x67\x61\x39\x2f\x80\x7a\x38\x6b\x5b\x79\xf3\x7b\xb1\xf0\xa6\xb0\xcd\x7b\x5e\xa5\xeb\xaa\x93\xe2\x44\xd0\xcb\x17\xf1\x64\x08\x2f\x90\x1c\x16\xd4\x8a\x1c\x9e\x28\xa6\xf3\xb6\xfc\x08\xd8\x67\x25\x4c\x04\x75\x38\x8f\x6a\x05\x99\xc7\x8a\x44\x31\x93\x27\x5c\x20\xfb\x77\x26\xe7\xb2\x82\x64\xea\xed\xe6\x0e\x27\x1d\x8a\x6a\x16\xf0\x21\x3c\xa4\xbe\x06\xc7\x53\xe0\x01\x83\x34\xff\xb7\xa3\xf7\x30\x08\x3c\x4e\x7d\x0d\x8e\x02\x3c\xc4\x07\x60\xe6\x09\xbd\x90\x25\xf4\x68\x96\xac\x66\x05\xa2\xc8\x60\x49\x31\x5f\xc9\x36\xf0\xa4\x76\xf7\xee\x5a\x42\x65\x65\xe5\xa4\x67\x68\x32\x8c\xe9\x25\x59\x02\x19\xcf\xeb\xcc\xa9\x3e\x7d\x4a\x26\x09\x8c\x63\x47\xf6\x19\x97\x7d\x78\x8f\x25\x56\xb4\x02\xc5\x43\x2e\x74\x91\xef\x78\x0b\x2f\xa9\x58\x89\xa7\x4a\xb2\xd2\x8d\x19\xda\xf4\x8c\x3f\x79\x69\x8b\x65\xcb\x3e\x96\x58\xcb\x4c\xb6\xf0\x22\x59\xcb\x43\xf7\x20\x9e\x8c\x66\xc7\xf0\x44\x47\xcb\x6c\x25\x06\x39\x4f\xe8\xd9\x3c\xd9\xc9\x8a\xa4\x6f\x55\x50\x3f\x8c\x25\x90\xce\x67\xf1\x02\x19\xcd\x5f\xa5\xc9\x8a\x53\xeb\xba\xc8\x0f\xb3\x6f\x4e\x14\xc8\x8b\x75\x43\x7d\x1f\x39\xa0\xfe\x77\x96\xd0\x1b\x59\x52\xca\x5b\xb3\x9e\xb8\x3b\x9e\xd0\xcb\x58\x82\x6e\x23\x77\xb0\x0f\x47\xd2\x19\xec\xc3\x87\x8a\x39\xfc\x48\x2b\xfa\xf4\x13\x78\xd0\xcf\x64\x89\xa9\xe1\xe4\xef\x75\x9a\xc2\xfc\xa2\xdc\x42\xa1\x34\xc5\xe3\xc3\x6c\x6d\x56\x5e\x48\x48\xd8\xa6\x1d\x9b\xdc\xd3\x0a\xd2\x0a\xd2\xd2\xd2\xf2\xd3\xfa\x79\xee\x4e\xf3\xfd\x2d\x59\x9b\xed\xe1\x97\x95\x22\xe6\xe6\xe5\xe7\xe6\x69\xe2\x4f\x7a\x99\x62\x84\x94\x84\xb4\xb8\x8c\x38\x26\x26\x0f\xb9\xa4\x44\x0d\x7a\x28\x12\x81\x4b\x6a\xc8\x13\xca\x62\xcb\xe3\x2b\x13\x98\xf4\x98\xf5\x5e\xf1\x9a\xbc\x82\xdc\xa2\x3c\x21\xb3\xf2\x2f\xbf\x62\x6d\xd5\xe7\xbf\xef\x2e\x17\xcb\xf3\xcb\xf3\xcb\xcb\xcb\x0b\xca\xfb\x79\x26\x96\x7f\x3e\xb4\x4a\x4b\xf0\x19\x9e\xc0\x13\xf8\xcc\xea\x42\x20\x0f\xcf\xc0\xea\x10\x1c\x68\x9b\xd8\x1e\x48\x7e\xb8\x79\xf3\x07\x91\xf4\x99\x63\xdc\xc1\xaf\xe2\x75\xb4\xcc\x81\x5c\x5d\xc6\x13\x6e\x3c\x4f\xee\xf3\xa0\xde\xcd\x92\x71\xac\x32\x90\x87\x6e\x7f\x96\x64\x95\x08\x01\x9d\x6f\xf0\x96\x2d\x96\x2d\xaf\xb2\xd6\x3a\x5f\xce\x77\x76\x96\xb3\x64\x0d\xab\x43\xdf\x20\x9e\xc4\xb0\x3a\x85\x0c\xf4\xdc\x7c\x96\x70\xcb\x59\xa2\x78\x9f\x25\x13\x67\xcf\x9e\x48\x56\xb2\x7e\x6b\xd8\x91\x84\x9e\xc1\x12\x70\xe2\x7b\xf4\x10\xc0\x12\xa8\xe4\xe1\x2e\x2f\x92\xab\x81\x3c\xb9\xe1\x7f\x79\x4e\x30\x4f\x1a\x4b\xf8\x5c\x9e\x28\xc6\xf3\x44\x71\x9c\x25\x3a\x79\x17\xe8\xed\x0c\xa0\x77\x90\xf4\x3d\xdd\xaf\xf2\x3d\x17\x2c\xdd\x1c\xe4\xf0\xbd\x6b\xcd\x6f\x52\xe7\x57\x8e\x38\x31\x47\x6b\xf1\x7e\xcc\x5a\xbc\x15\x73\x4e\x8c\x38\x1f\x20\x98\xd7\xf6\xae\xa3\xa2\x9a\xe1\x25\xbe\xb9\x45\x94\x52\xa4\x54\x78\x83\x25\x1c\xa8\x78\x54\x80\x02\x06\x82\x8b\x35\xf4\x5f\xb6\x85\x61\x33\x6b\x33\x13\xe1\x24\x10\x30\xb5\xb2\x04\x14\xac\x60\xd1\x4b\xfa\xc3\x2c\xbc\xc4\x8a\x16\xbd\x45\x6f\x62\x7b\xd4\x21\x6c\xe6\xdf\x1b\x03\x9a\x58\x49\xcd\x43\xae\xb5\xa9\xb7\xb0\x64\x31\x2b\x92\x20\xf6\xb9\x7a\x16\x0b\xde\xbc\x28\xe9\x2d\xfa\x36\x1e\xa6\x5b\x7d\x92\xfe\x63\x96\xc4\x55\x27\xd5\x09\x57\x27\x59\xab\xda\xa6\xf2\x8c\x04\xf3\x73\x88\x4e\x9e\x4a\xa6\xb2\xa8\x1e\xc5\x13\x34\x59\xe5\xa9\x17\x27\x9d\xaf\x5b\x5b\x35\x28\x79\xc1\x16\x22\xff\x4b\x3b\xad\xa4\x86\x67\x3c\x31\x65\x96\xa6\x0b\x84\x83\x79\x38\x00\xc6\xe2\xac\x0e\x61\x4f\x47\xf5\xd9\x73\xb0\x97\x5d\xb4\x24\x7a\xe3\x1a\x01\xf4\x3e\xb8\x18\x5c\x70\x93\x16\x28\x36\xa9\x20\xa9\x20\x51\xc4\xf1\xb3\xbc\x70\x02\xce\xea\xe2\x7b\xba\xe9\xef\xd9\xa9\x3c\x74\x28\xa0\x8d\x27\x2f\xb3\x68\x1a\xcb\x13\x29\xc3\x32\x44\x1a\x62\xc9\x20\x5f\xb0\x01\x01\xff\x68\x84\x52\x5f\xe3\x82\x61\xac\xb4\x45\xda\x42\x95\x94\x18\x4d\x65\x1a\x82\x17\xf1\xd2\x45\x60\x70\x8a\x88\x33\x14\x38\x10\x1e\xa1\x02\x8e\xb3\xf5\xac\x00\x33\x14\xc8\xe0\x14\xbc\xb4\x1c\x2f\x6a\xc9\xab\xc0\xa2\xea\x11\xfa\xb6\x32\x50\xca\xaf\x58\xb7\x6e\x45\x52\x51\x72\x71\x8a\x80\x75\x9b\x70\x22\x6e\x41\xbd\xc6\x12\x83\xbe\x18\x85\xc3\xd0\x59\x88\x2c\x8d\xae\x8c\x11\x70\x11\xbe\x9c\x9c\x9a\x1f\x53\x91\xe4\x7e\x77\x64\x45\x52\x63\x7e\x55\x85\xbb\x4e\xb1\x44\x47\xaf\x20\xd5\x6c\x5a\xaa\x21\x2d\x9d\x27\x54\x4a\x4a\x66\x42\x3c\x04\xb1\xe4\xef\xec\x4c\x65\x7b\xf5\xfb\x59\xb3\xde\x9f\x25\xb0\xe6\x2a\x4f\xac\xac\x8f\xb8\x56\xf2\x84\x86\xf9\xbc\x15\x2b\x16\x7d\x1f\x56\xc0\x13\x3d\xf1\x5b\xfc\xf6\x55\x16\x68\xa4\x97\xf3\xf0\x2d\x7c\x6b\x85\x5d\x61\x89\x35\x7b\x2b\xd6\x9d\xea\xea\x3a\x25\xb9\xb0\xeb\x56\x08\xe4\x59\x36\x4f\xac\x74\x42\x70\x2d\xb8\xe1\x02\xd8\x80\x8e\xe2\x6a\x9c\x36\x7b\xf1\xeb\x73\x12\xe3\xe2\x13\x8b\x23\x18\x83\xc1\x90\xaf\x89\x2e\xae\x4b\x68\x28\x28\x34\x14\x6a\x8f\x17\x1f\x2f\x3d\x52\x0e\x33\x4f\xc3\xb8\x3b\xf0\x12\x30\x4c\xf6\xdb\xe7\x72\xcf\xfd\x97\xd6\x53\x50\xf0\x09\x81\x0a\x50\xf0\xdb\xfa\x18\x19\xb1\x92\x8f\x2f\x04\x13\x1b\xdf\x25\xf1\x89\xbb\x6b\x45\xab\x48\x5d\xc6\x93\xd6\x88\x13\x86\xd6\x56\x77\xc2\xed\xe5\x09\x27\x79\xc3\x53\x4c\xc6\x03\x78\x00\x9f\x62\xb2\xc5\x7b\xdd\xda\xa2\xe2\x75\xa2\x7f\xc9\xba\xcd\x53\x66\x8f\xf5\xf7\x5a\xef\xde\xf6\x56\xeb\xa5\xfa\x1b\x7b\x1e\xba\x79\x77\x52\x38\xf3\xd7\xa1\x30\x08\x86\x6b\xe0\x00\x3c\x85\x64\xc9\x5b\xe8\x51\x5b\x4c\x1c\x59\xce\x5b\x11\x58\xce\x92\x51\x7c\x34\x4b\x06\xbe\xfc\xf2\x40\x32\x9d\x95\xd4\xf2\xe9\x2c\x81\x23\xbc\xa5\x43\xea\xf8\x80\xc7\x0e\x8b\x5e\x31\x9a\x15\x2d\xea\xb1\xbc\xa4\xc7\x0e\xfa\x26\x2b\x75\x48\x1d\x1f\xb3\x84\xaa\x4c\x49\x28\x8d\xd7\x12\x78\x0b\x5f\x85\xd9\x78\x01\x67\xe3\x64\x14\xa6\xfb\x08\xb7\x7c\x70\x32\x08\x38\x5b\x8b\x17\xf0\x55\x9c\x8d\x6f\x91\xff\x52\xa2\xac\x06\x0f\x9e\x80\x7a\x05\xbf\x82\x27\xb6\xad\x1c\x26\x12\xbf\x3b\xb1\x96\x04\xf0\x66\x35\x76\x07\xf0\x04\xc6\xf0\xbd\x53\x8d\x7c\x14\xdf\xc4\xf7\x4e\x7d\x8f\x27\x07\x21\x89\xc5\x6e\x1a\x07\x78\x79\xe1\x00\xf1\xb9\x5e\x41\x60\xb1\x95\x85\x38\x10\x18\xca\xef\x6b\x27\xc2\xeb\x5b\x90\xcf\xdf\xbc\x88\x49\x57\xc4\x17\xc6\x15\xc4\x0b\x8f\x1f\xd7\x3d\xd6\xc2\x60\xf0\x88\x36\xc2\x20\xf1\x70\x01\x55\x58\x5e\x50\x6e\xd2\xd4\xe6\xd6\xe6\xd5\x08\xd3\xdb\xc7\x97\xbc\x72\x9c\x89\xfe\xac\xf2\xeb\x2f\x35\x84\x7b\xc2\x5b\xb6\x48\x5b\xdc\x80\x66\x03\x02\xdc\xee\xf1\x56\xca\x76\x93\x54\xec\x3d\xde\xbd\x33\xe0\x99\xad\x76\x28\x82\x6a\x78\xf0\x23\x6b\xee\x94\xf6\x71\x78\xc3\x0b\xbe\x54\x60\x8d\x94\x46\x41\x3f\x1a\xc6\xe2\x35\xca\xd0\xbc\xa6\x7e\x8d\xd0\x70\xba\xe5\xac\x41\x03\xe3\xe1\x1a\x05\x72\x5a\x5a\x4f\x92\x78\x18\xc3\x12\x54\x73\x0b\x79\x02\x0b\xb1\x15\x03\xf0\x34\x85\x6a\x9c\x06\x15\x34\x8c\x85\xa2\xf2\x1a\x53\x4d\x49\xa5\x7b\x51\xa9\xb1\xb4\xb0\x94\x29\xa2\x0b\x33\x8b\x32\x4b\x32\x5b\xd6\xbb\xc1\x44\x2c\xa6\xa0\x80\x26\x8a\xa9\x3c\x39\xc0\x83\x9a\x64\x67\xe7\xe7\x66\x8b\x96\x28\x34\x51\x69\xd9\x99\xa9\x29\x1a\x5d\x8f\x6f\x1c\x5b\x5c\x5c\x50\x54\x2c\x48\x51\x60\xa2\xca\x8b\x4b\x2b\x2a\x35\x3a\xaa\x0b\xb2\x58\x12\xc4\xeb\xa8\xae\x55\x2c\x19\xf8\xdd\xcb\x75\xac\x40\xa4\xfb\xb8\x1a\x12\x61\x35\xbc\x42\xc3\x2a\x50\x82\x0c\xe6\xde\xed\xce\xca\x6d\x14\x70\xa3\x02\x95\xf9\xd4\x88\xb8\x37\xe7\x8b\x38\x0c\xe2\x14\x61\x98\x48\x61\xa0\xe5\x3e\xd9\xce\x82\xc9\x75\x39\x6b\x33\xb5\x36\x91\x25\x8a\xa2\x4c\x63\x56\x49\x96\x79\x55\xef\x2a\xb7\xd6\x88\x06\x53\xbb\x86\x70\x73\x97\x2e\x9d\x3b\x77\xe9\xbb\xd7\x61\x23\x4b\x86\xf2\x33\x78\x62\x60\x61\x1c\x4b\xda\x78\x6f\x9e\xac\x62\x95\xb4\xcd\xf6\x31\x51\x00\xcf\x5a\x4c\x16\x93\xdb\x63\x5e\xb2\x3a\xc9\x95\x35\x59\x1f\xb1\xa4\x56\x5b\x66\x2a\x2c\x2a\x13\x9b\xcb\x6b\x9a\xdb\x34\x84\xaa\xac\x2c\xad\xa9\xd5\x90\xef\x7f\x06\xa7\x4e\x78\x49\x0b\xed\x10\x8f\xb6\x5d\x5a\x38\x11\x87\xde\x04\xd5\x70\x31\xbb\x34\xdd\x98\x5e\xc0\xa4\xa7\xe7\x66\x65\x8a\xe4\x67\x16\x4d\x68\xea\x6b\xf1\x1a\xf0\xe6\x05\x68\xe2\xaf\x58\x47\x9e\x23\xf9\x7f\x1a\x8f\x97\x7c\xc8\x7f\xcd\x1b\x5a\x85\x40\x39\x4d\xc6\x58\x19\xb0\x40\x60\x3a\x2b\x10\xf9\x6c\x96\x70\x38\xc5\x3c\x08\x07\xd0\xa8\xc7\x85\x77\x5e\xbe\xf2\x6e\x55\x55\x59\x79\x71\x99\x7b\x69\x25\x55\x98\x40\xa7\xe5\x27\x27\x6b\x2c\x73\x70\x1a\xd2\x52\x88\x82\xdc\x61\xad\xd4\xf2\x06\x4f\xbc\x79\x30\xc5\xb2\x04\xac\x6c\x1b\x07\x92\xeb\x4b\xdf\x9d\x2b\x90\x36\xf6\x9b\x6f\xbe\x99\xfc\xff\x7f\x25\xd0\x11\xcb\x82\x9c\x25\x65\x39\x10\xc2\x13\x74\x43\x93\x22\x8d\x35\xab\xe9\x1f\x78\x34\x81\x1b\xdd\xcd\x13\xee\x1c\x38\x16\x19\xcb\x4a\x4a\x0a\xdc\xe1\x3a\x5d\x9c\x6f\xca\x2a\xca\x39\x8b\x8e\x6e\x52\xd4\x36\x7f\x1e\xaf\xd0\x73\x61\x1a\x45\xfa\xcc\x49\x77\xfb\xb0\x36\xc1\xef\x65\x56\xd7\x93\x3a\x96\x27\xe0\xc0\x2a\xfd\x79\x03\xea\x09\x78\xb1\x0e\x84\x6e\x66\x09\xdd\xc2\x93\xb3\xac\x6d\xfd\x9a\x4c\xe4\xe1\x25\x56\x20\xb6\x3e\xc2\xda\xec\x4c\xb0\x98\x27\x36\x13\xda\xa0\x26\xad\xa6\xda\x96\x3d\x9a\x3d\xf1\x2d\x11\x26\x01\xdf\xfc\x02\xd7\x41\x83\x64\xa7\xe9\x31\xd1\x16\x3b\x5c\x87\x0d\xf8\xe6\x2b\x82\x72\x84\xcf\xed\x47\xa6\xd2\x52\x93\xa9\x34\x33\xdd\xe7\xda\x6b\xb7\xad\x2e\x99\xc1\x83\x86\xc6\x32\x2c\x25\x8a\xfd\x3c\xa1\xf7\xf0\x84\xd3\xf5\xf8\x0e\x63\x51\x0d\xad\x2c\xa8\x97\xf1\x24\x8a\x95\x4c\xe4\x6a\x12\x4f\x1a\x41\x64\x49\x23\x9a\xe0\x3c\x6b\x67\x80\xf3\xac\x03\xf9\x7b\x51\xf7\x79\x37\x94\xf0\xdc\x68\x56\xe8\x35\xd9\x4c\xf6\x5f\x64\x2d\x26\x85\x55\x14\x06\x57\x3e\x29\x4e\x24\x2f\x54\x79\xf7\x69\xe2\x26\x4d\xac\x48\xb0\x63\x18\x4b\xf0\x08\xc6\x61\x1c\x1e\x21\xc9\x55\x31\x86\xe4\x64\x52\x9b\x59\x93\x52\x49\x6e\x5c\xbe\x7c\x83\x28\x24\x1e\xfa\x53\xd5\xc5\xa6\xca\x6a\x0d\xa8\x15\xe5\xd9\xe5\x19\x25\x42\x46\x49\x6a\x61\x7a\xae\x85\x20\xe3\x46\x20\x90\x15\x24\x8a\x2d\x35\x89\x10\xa5\xb0\x96\x4a\x78\x48\x5b\x0b\x24\xda\x74\x93\x91\x3e\x8b\x76\x3a\xb4\x96\x44\xaf\x88\xaf\x4e\xac\x93\x94\x3c\x51\x60\xd2\x1c\x2a\x29\x3b\x3d\x25\x49\x83\x6a\x45\x5a\x71\x5a\x59\x96\x90\x53\x52\x92\x57\xaa\x2d\x2a\x32\x14\x14\x89\xe4\xc6\x65\xff\x39\x04\x5d\x51\x39\x0a\x5d\x42\xc5\x41\x96\x49\xd4\x0e\xba\x4f\x78\x10\x2d\x6a\x4f\xfe\x21\x71\x48\xe0\xcd\x6a\x38\xc2\x4b\xce\xfc\x07\x3c\xaa\x49\x65\x79\x41\x61\x99\x58\x62\x2c\x30\x6a\x73\x15\xa9\xe9\xd9\xd9\x19\x69\x19\x29\xee\x16\xca\xd2\x46\x8d\x97\xbe\x56\x10\xd4\xcc\x61\xbf\x66\xc9\xd7\x56\x2a\x4d\xe5\xfb\x66\x54\x72\x6c\x7b\x3b\x08\x0c\xf4\xe3\x09\x94\xb3\xfb\xda\x49\x7c\x42\x66\x4a\x0a\xe1\xe0\x81\x42\x52\xc3\x64\x0a\x3f\x56\x58\xf4\xb0\x9b\xb3\x0c\x83\x99\x92\xed\x8f\x33\x29\x02\xfb\xc3\x6c\x7b\xfa\x1c\x74\x8c\xcc\x55\x27\xa5\x46\xf1\xa8\xd6\xf5\xc8\x74\x8c\x8c\x26\xc7\x9a\xda\x3a\xde\xb6\x72\x0d\x3f\xae\x29\xa5\x31\xb6\x52\x88\xad\x88\x2a\x88\x49\xcb\xcc\x49\xcd\x4a\xce\x64\x08\x7d\x0b\xae\xf5\xa9\x20\x74\x2f\xcd\x4a\x2b\x4e\xd7\x62\x94\x4d\xf1\x60\x8e\x38\x15\xbf\xa6\xc8\x7b\xd6\x11\x12\xc4\xf0\xca\xb6\x84\xe6\xa8\x72\x21\xb2\x7c\x47\x76\x5c\x2c\x49\xae\xac\xcd\xaa\xd1\xf6\x69\x8d\x21\x55\xbc\x1d\xf1\xe7\xfb\x76\xaa\x4e\xe2\x89\x62\xcf\xe2\x05\x95\x0b\xb4\x68\x87\x41\x2b\x71\x20\x0e\x84\xa0\x95\x60\x07\x76\x10\x74\x1e\x06\x8a\x84\x86\x2d\xf1\x28\x07\x27\x5c\xad\xc5\xd7\xd0\x13\xa7\x60\x2d\xd6\xc3\x4b\x38\x15\x42\x61\x26\x49\xae\x8c\x31\xa4\xa4\xb8\xaf\x59\x93\x92\x62\x88\xa9\x4c\x76\x27\xd8\x8e\xf1\xf0\x19\x2b\xc9\x59\xc2\x85\xfd\x1a\x36\x7c\x78\xd8\xaf\x61\xfb\x87\xef\xff\xf5\xd7\xfd\x14\xb1\x83\x5c\x9e\x18\x12\x78\xf2\x2a\xdb\x19\xb0\x9c\x27\x13\xf9\xd1\x2c\x89\xe2\x39\x1b\x1d\x9a\x60\x3d\x0b\xc1\xbc\xa4\x86\x6e\x07\x02\x8b\xf8\x7b\xe3\xc8\x7f\x5b\xd8\x37\x80\x9a\xf8\xfd\xcc\x93\x30\x1e\x0e\xb3\x64\x24\x0d\x0a\x9e\xe4\xb2\x30\x7c\x17\x59\xc2\x82\xda\x81\x70\xab\x79\xd2\x98\x6b\x65\xec\x10\x25\x79\x83\x49\xf2\x96\x94\xac\xfa\xdb\x6c\x96\x5c\x65\xad\x8d\x53\x47\x75\xcd\x64\xf1\x16\x41\xc7\x51\xa3\xd0\x11\x1d\x47\x3d\x00\x47\x70\x7c\xd0\x77\x1d\x85\x8e\x02\xe1\xf4\xac\xad\x3b\xbc\xc0\x12\xd8\x60\xe5\x5a\x3e\x6c\x8f\x75\x2c\x00\xdd\x74\x5d\x35\x51\xcc\x63\x89\xd9\xda\x38\xf7\x26\x51\x51\x6f\x75\xa5\xbc\xa7\x85\x31\x30\xf2\xce\xe1\xab\x62\xa9\xb1\xa4\xc8\x58\xc8\x10\xee\x47\x30\x53\x15\x45\x0d\x35\x95\x5a\xb3\x89\xae\x6c\x48\x48\x2d\x12\x7f\x44\x33\x45\x60\xdd\x3f\x0e\xff\x12\xc9\x89\x37\xf4\xf5\xb8\xb6\xfd\x57\xc4\x97\x07\x85\xb5\x15\x9d\x83\x28\xcc\x85\x8e\x6d\x02\x69\x8d\x30\x6c\x8c\x88\x20\x68\xd3\xf8\x4b\x8c\x25\x25\x22\xd1\x51\xbe\x34\x51\x7c\xc0\x92\x19\x2c\x7c\xce\x93\xd8\xb8\xec\x1d\xe5\x51\xee\x91\xe5\xcd\x09\x6d\x5a\xb2\x8c\xf7\x1b\xc6\x12\xc9\x85\x2f\x85\x87\x6c\x66\x4a\xa5\x48\x14\x7b\x9a\x9b\xf7\x08\x8f\xe9\x3d\xcd\x51\x3b\x45\xf2\x94\x35\x10\xee\x33\x9e\x26\x70\x04\xe2\x20\x0e\x8e\x10\xec\x50\x4c\x65\x89\x75\x60\x6d\xa5\x42\x02\x56\x3a\xc0\x39\x68\x95\xb8\xe6\x10\xc8\xe6\x45\x42\x35\x37\x57\x1f\x3a\xac\x21\x1c\x7c\xc4\xef\xdb\xd7\xde\xbe\x6f\x7b\xb0\x40\xbc\xf8\x1e\xbd\x62\x04\x4b\x4a\x0d\x25\xf9\xa5\xe2\xcb\x52\x2e\xfc\x1b\xfe\xa2\xaa\xaa\xaa\x6a\xeb\x34\xca\xf4\xcc\xcc\x74\x02\x27\x9e\xf9\xd2\x6f\x83\x27\x05\x39\xf4\xdb\xe8\x49\xf9\x0e\x84\x0e\x9a\xfc\x7d\x74\x1e\xa6\x01\x0f\x3c\x4c\x6b\x6b\x8a\x0e\x17\x88\x62\x0b\x2f\x40\x37\xdc\x67\xfd\x7c\xd8\xff\x92\x44\xd4\x3b\x09\x94\xf1\x60\x22\x60\x7a\xc0\x12\xf0\xe0\xfb\xc0\xa4\x95\xbf\xfe\xee\xd2\xb9\x02\x89\x7a\xb1\xcf\x9b\xa0\xd3\xef\x43\xc1\x89\x44\x44\x6c\x34\x44\xb4\x12\xcd\x04\x96\x18\x0c\x06\x83\x35\x25\x3d\xe1\x96\xe9\x37\xbd\x36\x6a\xcd\x07\x37\x3f\x3b\x7d\xf9\xfa\x57\x1f\x7b\x4f\x11\x2c\x7f\x91\xf5\x42\x44\x4c\xcc\xae\xb8\x88\xa7\x63\xdd\x2a\xaa\x2a\xab\xab\x2a\x98\xc6\x56\x32\x6c\xce\xac\x21\x9e\xdd\x33\x1f\x0b\xf7\x3f\xfc\xb8\x40\x5b\x5a\x56\x6e\x2c\xcf\x27\x43\x58\x49\xed\x4a\x8e\xe3\x13\xe9\xf9\xba\x5b\x42\x43\x6a\x74\x55\x94\x36\x2a\x3a\x39\x26\x55\x24\x1b\x05\xd5\xcf\xf7\x53\x37\x86\xb6\x1f\x17\xff\x3e\xe6\x47\x14\xe1\x35\x51\x2d\x69\x42\x6e\xa9\x29\xaf\x4c\x6b\x1d\x47\x10\x2b\x29\xcf\x03\xf1\x53\xe0\x2f\x81\x87\x83\x8e\x9a\x45\xd0\x9b\x4e\xcf\x2c\x35\xb5\xf0\xe0\x6d\x63\x6e\x04\xd4\xac\x03\x81\x43\x56\x1e\xab\x26\xb0\x82\x55\x46\xc2\x83\x3e\x09\xcc\x81\x98\xad\x30\x0e\xee\xf2\x50\xc9\x0b\x84\x9b\x4b\x63\xbc\x79\x04\x85\xff\xa2\x31\xbe\x77\x04\x35\x77\x20\x51\xe0\x40\xf4\x44\x05\xce\xb1\x62\xad\xde\xda\x95\x54\x5b\x39\x12\xfd\x23\x4f\x26\xf1\xa8\x27\xdc\x8f\x3c\x91\xba\xad\x6c\x9c\xf8\xb3\xd8\x41\x38\x38\xc2\x12\x8b\xfa\x65\xab\x00\x89\x71\x60\x65\xd4\x8a\xd9\x2c\xb9\xca\x8d\x61\x49\x8f\xb5\x76\xd1\x17\x83\xff\x29\x0e\xda\xda\x9c\xe2\x7f\xeb\xb9\x39\xa8\xe1\x09\xfd\xd9\xb5\x1d\x93\x44\xb8\x82\xd7\xb8\xd4\xbc\xf4\x8c\x54\x2d\xd1\xd7\xe9\x0f\xad\x15\x25\xb5\xc5\x44\xbd\x7e\xf6\xcb\x4d\x5f\x69\xc9\xa9\xe0\xc3\xeb\xd7\x07\x87\xac\x5b\xdf\x1e\x7c\xf2\x64\x7b\xfb\x49\xc1\xda\xce\xad\xfd\x10\x19\xcb\x47\xf1\x21\xac\xb5\xa4\x36\xc4\x5a\xe5\x7e\x54\x2b\xac\x18\x57\xc3\x17\x2c\xe9\x53\x4e\x65\xbd\x12\x78\xc4\xee\x23\x92\x33\xbb\x8f\xc0\x1a\x30\x90\xb4\xba\xfa\x9c\x06\x6d\x43\xbd\xb1\xbc\x4e\x94\xf4\x10\x45\x1c\xce\xa0\x82\x83\x31\x3c\xf9\x5b\x3d\x20\xdc\xe4\x89\xcf\x54\xb4\x5f\x85\x4a\x2d\x2a\xd1\xfe\xdc\xed\xa9\x62\x5f\xb1\xbe\xe7\x89\x62\x22\x9f\x94\x98\x9d\x9e\x2a\x58\x0e\x59\x66\x52\xe4\xaa\xb5\x61\x2f\x61\x39\x32\x71\xf6\xcd\x1f\xc8\x95\xce\xce\x2b\xc4\x24\x74\x14\x15\x2f\xda\x90\xcd\xac\xcf\x5e\x93\x6b\xd0\x10\xb8\xca\x8e\xbb\x47\x3c\xad\xa2\xdb\x24\x9e\xec\xa0\x07\x49\x93\x28\x70\x09\x45\xe5\x03\x74\xd5\x12\xdb\x04\xd7\x6d\xa2\x69\xe6\x49\x6e\x99\xd6\x68\x2c\x28\x30\x8a\x44\x67\xee\x4a\x65\xc9\x87\xbc\x48\xba\x59\x1d\xed\x4b\x0c\x70\x8f\x25\x79\x36\x9a\x25\x70\x92\xb7\xd2\x67\x8f\x09\xd5\x0a\x02\x1d\xd0\x8d\x1d\x0a\xc2\x59\xc7\x8e\x44\xf2\x91\x7c\xe0\x11\xa1\xe3\x92\x12\xe3\x45\xa2\xb8\xcf\x13\xb0\x56\x11\x89\xcf\x4a\x48\x49\x11\x6c\x83\x6c\x81\x4c\x14\x7a\xbb\x69\x82\x9e\xe0\x49\xe6\x5c\xf6\xbf\x41\x6c\xa4\xa3\x08\xd9\xb3\xf3\xb0\x00\x32\xfa\xf0\x9e\x3d\x87\x45\xb2\x1b\xb9\xea\x98\x42\x21\xa3\x2e\xad\x2e\xa5\x86\x21\x50\xd6\xd7\x43\x29\xc0\x8e\x25\x8a\xb9\xef\x2e\xbd\x2e\x80\x3a\x8e\x27\xd0\xc1\x9a\x4d\xbb\x59\x62\x28\xd7\xc2\xf8\x6a\x96\x8c\x63\xe1\x73\x96\x6c\x59\x88\xae\xbe\xc8\x6a\xb7\x86\x95\x54\x85\x8b\xa4\xa2\xa0\xa0\x69\xb7\xf6\x0b\xba\xac\x24\x23\x23\x5f\x24\xa3\x78\xf0\x0e\xe4\xc9\x15\x56\x29\xa9\x25\x35\xd1\xa1\x2f\x4d\xb4\x2b\xa3\x62\xc3\x42\xc4\xe0\x0d\x6f\xac\x1d\xae\x25\x14\x08\x3c\xf1\xb7\xb1\x23\x2a\xaa\xc5\x3a\x9a\x6f\x16\x09\x37\x35\x9f\xb2\xa8\x14\x55\xf1\xad\x09\x75\xa9\x24\x8b\xc9\xca\xca\xc8\x49\xd7\xa2\x9a\x8e\x4f\x22\xfe\x3c\x76\xd3\x43\x78\xc2\xe1\x00\x89\x82\x01\x34\x99\x64\x25\x63\x73\x14\x37\x9b\x25\xc3\x58\x8c\x22\x92\x9c\xb5\x0a\x9e\x04\xd4\x56\xb9\xce\x04\x6a\x88\x65\xc9\x01\x76\xe0\xcb\xdf\x3d\x23\x06\x45\xdf\x97\x40\x6c\x9f\xe4\xa4\xc0\x01\x8f\xbd\x60\x80\x40\x86\xf0\x71\x49\xd5\x75\xd6\xfa\x31\x11\x1d\xa6\x72\x64\x6d\xd0\x91\xd3\xa7\x8f\x58\xff\x41\x6b\x09\xa4\xf0\x92\xbd\x95\xe5\x58\xd9\x48\xb6\xad\xff\x40\x32\x62\x3c\xca\xd1\xe1\xd1\x38\x20\xa4\xf8\xaf\xab\xa5\x95\x62\x51\x61\x41\x61\x91\x86\x18\xc0\x24\xd9\xf1\x10\xcc\x13\x3b\xc3\x09\xde\xc1\x4a\x4c\x67\x59\x42\x77\x9d\xb2\x4a\xd2\x60\x92\xd4\x60\x22\xa8\x0e\xe3\x49\x81\x75\x9c\x4e\x6a\xb5\xb5\x35\x04\x4c\x74\x3b\x41\x43\x20\x2b\x92\xab\x86\xff\x7c\xc9\x24\x03\xa8\xef\xde\x35\xa0\x7a\x92\x96\x68\x0d\x0a\xa0\x41\x7e\xf6\xd4\x57\x22\x39\xca\x3a\x10\x85\x1f\x2f\x5c\x25\x66\x13\xfd\xf7\x2c\x4f\x4f\x83\xdd\x4f\x3a\xfa\x75\x07\x1d\x5d\x46\x2c\x6a\xc9\x44\xc5\x37\xa5\xef\xd9\xab\x21\x8c\xca\x49\xc6\xc8\x64\x2f\x7a\x47\x07\x62\xb6\xb6\x72\x02\xa3\x73\xa0\xca\x4a\xb0\xb6\xc3\x9c\x76\xe4\xb8\xad\x6b\xe9\x6b\xc7\x76\x24\xa7\x2c\xab\x44\x24\x56\xb6\x6e\x9b\x15\x23\x19\xe9\xb9\x59\x59\x04\xd4\xa8\xb6\x0e\x47\x9e\x91\xc3\xda\xc3\x87\x08\xc4\x43\x3b\x19\x49\xa7\x67\x12\xf4\x0a\x43\x0e\xed\x71\xac\x96\xe0\x10\xfc\x23\x0a\xdb\x34\xc9\x85\x04\xfa\xc1\x68\x70\x80\x5a\xe8\x47\xe0\x86\x15\x4b\x8a\x66\x5e\x20\xb8\x1a\x3d\x61\x10\xbc\x01\x7a\x22\xd7\xe1\x08\x2c\xd3\xc9\x3f\xa7\x09\xdd\xbe\xaf\xd4\x64\xda\x5e\x1a\x2c\x92\xbf\xb5\x5d\x43\x14\xc1\x7f\x37\xee\x82\xe3\x3c\x71\x31\xd8\xda\x3a\xdd\x4e\xac\x43\x78\x62\xe1\x2d\x3c\xc1\xc1\x30\x98\xc8\x64\x32\x99\x9d\xcc\x45\xe6\x20\xfb\xef\x0f\x23\x53\x58\x9d\x7f\xff\x5b\xc6\xfe\xc7\xe7\xf8\x1f\x9f\x03\x1d\x6c\x57\x2c\xa3\x64\x32\x79\x81\x7c\xa2\x4c\x26\xcb\xee\x73\xed\x23\x65\x32\xbb\x7c\xd9\xff\xf0\xd9\x19\x17\x11\x29\xf3\x95\x79\x3c\x93\xd1\xb2\x7f\xcb\x64\x32\x5a\x66\xd7\xf7\xfe\xbf\x3f\x1e\x32\x0f\x9b\xeb\xd0\xf7\xb7\x1b\xf4\xe2\x9e\x4e\xe6\x60\xf5\xd9\x0d\x92\xc9\xec\xe8\xff\x4a\xd0\xee\x1f\xb1\xff\x01\xfe\xff\xc2\x87\xed\xe7\x48\xd1\xc7\x15\xcc\x89\xff\xb7\x13\x96\xdb\xf5\xc8\x64\xb2\x58\x99\xaf\x8c\x92\x4d\x96\x79\xc8\xf6\xcb\xda\x65\x1d\xb2\xf7\x64\x5f\x0e\x1c\x34\x48\x18\xf4\xff\x63\xbd\xda\x62\xe3\xb8\xca\xf0\x37\xb3\x73\xad\x63\x9f\xa1\x34\xa5\x6a\x21\x4c\x21\x51\xd2\xa8\xd9\xdd\x44\xbd\x80\x15\x45\xeb\x36\x71\x1f\x28\xf6\xd6\x72\xab\xaa\xa2\x69\x36\xf6\x6c\xbc\x64\xbd\xb3\x9a\x9d\xb8\x32\x42\xd1\x88\x77\xa2\xbc\xf0\x02\x52\x14\xf1\xc4\x53\x14\xa1\x22\x2e\x0f\x25\x48\xbc\x55\x44\x11\x14\x4a\xa1\x98\x94\x5b\xb9\x9a\x73\x06\x02\x3c\x65\xd0\x9c\x39\x33\x7b\x66\xbc\x49\xfb\x50\x4b\xbf\xcf\x3f\xff\xfd\x7a\x66\xf6\x14\x9d\xa1\x7b\xe8\x31\xba\x40\x4f\xd2\x2e\xed\xd1\x01\x3d\x4f\x2f\xd0\x4b\xf4\x0a\xfd\x36\xbd\x4e\xb7\xe8\x36\xbd\xcd\x66\xd8\x1e\xb6\x9f\x1d\x60\x75\x76\x8c\x2d\xb0\x93\x6c\xc0\xce\xb3\x0b\xec\x12\xbb\xc2\x5e\x67\xd7\xd9\x16\xdb\x66\xb7\xe3\x99\x78\x4f\x7c\x2c\x5e\x88\x4f\xc6\x83\xf8\x7c\x7c\x21\xbe\x14\x5f\x89\x5f\x8f\xaf\xc7\x5b\xf1\xf6\xad\x74\x0e\xd2\x7e\x7d\xab\xe2\x19\xd4\xa1\x0f\xd3\x16\x6d\xd3\x53\xf4\x0c\xfd\x22\x1d\xd2\x88\x5e\xa4\x97\xe9\x55\x7a\x8d\xde\xa0\x37\x29\x65\x60\x0e\x73\xd9\x01\xf6\x08\x6b\xb2\x16\x6b\xb3\x53\x6c\xc8\x22\x76\x91\x5d\x66\x57\xd9\x35\x76\x83\xdd\x64\x34\x46\xec\xc4\x0f\xc7\xad\xb8\x1d\x9f\x8a\x87\x71\x14\x5f\x8c\x2f\xc7\x57\xe3\x6b\xf1\x8d\xf8\x66\xea\x39\x79\x17\x48\xbe\x90\x3c\x97\xcc\x25\xcd\xad\xf7\xb6\xbe\xb6\xb5\xe4\x4c\x3b\xbb\x9c\x7b\x1c\xdb\xb1\x1c\x13\x70\x34\xa7\xe6\xa8\x8e\xe2\x80\x24\xe4\x16\xf9\x37\xf9\x17\x89\x09\x23\x94\xfc\x73\xe6\x1d\xb2\x4d\xfe\x41\xfe\x4e\xfe\x46\xfe\x4a\xfe\x42\xfe\x4c\xde\x23\x7f\x22\x7f\x24\x7f\x20\xbf\x27\xbf\x23\xef\x92\x9b\xe4\xb7\xe4\x37\xe4\x1d\xf2\x6b\xf2\x2b\xf2\x36\xf9\x25\x79\x8b\xfc\x82\xfc\x9c\xbc\x49\x7e\x46\x7e\x3a\xf5\x1a\x1f\xab\x8d\xbb\x74\xe5\xe4\x87\xdd\xe6\xe2\xcf\xc0\x2e\xd4\x30\x05\x95\xc7\xa0\x29\x6f\xbc\xb5\xef\xcb\x3f\x79\x85\x1c\xbd\x85\x1a\x5f\x4a\xbc\xb1\x78\xb4\x99\x9e\x6f\x1e\x5e\xfb\x7e\x92\xdc\x4e\x6c\xc5\x50\xf8\x0e\xa9\xc2\x82\x02\xb1\x73\x76\x5a\xbf\xc4\x56\xaa\x4b\xa2\xbe\x56\x8b\x30\x54\xae\x01\x46\x84\x0d\x3d\x02\x34\xe0\x95\xd4\xfa\x24\x48\xf9\x02\x7f\x39\x5d\x48\x63\xfc\xcc\xf1\x14\xf4\xf4\x39\x2a\xf3\x4c\x60\x53\x8f\x30\xc8\x65\x8c\x5c\x47\xd8\x34\x22\x3c\x68\x88\x67\x33\xc2\x91\x5c\x66\x12\xa4\x7a\x5a\x66\xbb\x95\xca\xd5\xc4\x33\xf7\x1d\x8d\xed\x66\x31\x24\x89\x9e\xc7\x29\xc9\x68\x92\xff\x3b\xe5\x5a\x80\x88\x45\xc3\xf8\x94\xf3\x35\xcb\xb4\x2f\xe9\x72\xec\x12\xdf\x50\x79\x2c\x5f\xd7\x81\x97\xee\x94\xdb\x04\x68\x09\x3b\x8f\xa7\x60\x8e\xe9\xd3\x72\x3d\xf4\x68\x67\x9f\x4a\xbd\xc9\xce\x97\x38\x44\x52\xec\x59\xfd\x5a\x26\xbf\xfc\xcb\x35\xce\x73\x97\x7c\xa2\x16\x49\xb9\x8f\xfb\x50\xe4\x2a\x9f\xba\xa8\xb5\x3e\xe6\x3f\x9a\xce\x96\x21\xf5\x43\x8f\x4a\xfe\x5a\x06\x92\x44\x8e\xf9\x8e\x10\x61\xb7\x9c\xf7\x8e\x3e\x66\xf9\x39\xe2\xec\x4a\x75\xd1\xaa\xb3\x64\x02\xa4\x94\x43\x84\x87\xcc\xbc\xee\x02\x6c\x61\x53\x13\xbd\x54\x23\xb4\x54\x51\xc3\x9c\xa6\x55\xe2\x36\x81\x03\x72\x4c\x72\xed\xe4\x99\x31\xa5\x5a\x48\x7d\x6c\xc9\xf5\x29\x78\x51\xd6\x2b\x91\x57\x11\xa3\x06\x1c\xd2\x80\x69\x2d\xc2\xe7\x53\x50\x23\x1c\x52\xa3\xf1\x73\xee\x43\x13\xfb\x62\x94\xe7\xb7\x65\x54\x67\xba\x32\x3b\xd2\x6e\xe6\xbc\x96\xd8\xbf\x69\x33\xc2\xa1\x5c\x57\x97\x6a\x92\x9e\x6a\x06\xa7\x0d\x40\x4f\x21\x9f\x3d\x2d\x93\x9d\xd6\xcb\x7a\xee\xa4\xbe\x8b\x9a\xec\xca\xf7\x3e\xa7\x29\x51\xa9\xd6\x8f\xe7\x74\x4d\xda\xd5\xbb\x81\xd4\xb7\x43\xb5\xaf\x00\x5a\x4d\xdc\x5d\xe0\xe7\x67\xa4\x59\xfb\x64\x0a\x26\x32\x30\x72\x90\xee\x32\x03\x78\x68\xe7\x2c\x63\xaa\x9a\x87\xf0\x7b\xdc\x18\x7f\xec\xe4\xb5\x2c\x6a\x27\xe4\x8c\x42\x0f\x78\x54\x9c\x45\x5e\x26\x70\xd0\x40\x71\x07\xba\x66\x94\xed\x4d\x31\x2b\xc0\xee\x09\x3b\x53\xec\x6c\x2a\x63\x55\xee\xe2\xfc\x0e\xb0\x33\xf9\x75\xa3\x3a\xcf\x42\x36\xbf\x27\xcc\xff\xe0\x91\xea\x2e\x89\x38\xf3\x7b\x99\xe7\x65\xcb\x3a\xe3\xd3\xb1\xc6\x74\x37\xef\x87\xfd\xc1\xef\xc5\x14\xf6\xe7\x31\x8b\xf8\xd3\xf9\xb9\x57\xf2\x71\x5c\xc4\xf3\xd9\x94\x3e\x96\x4b\x12\x29\xe6\x63\x3a\xf0\xc0\x84\x3b\xa1\x0a\xe9\x07\xc6\xaa\x01\x3c\x2f\xe2\x3e\x28\xfc\x58\x26\xf0\x69\x5b\xc4\x5e\x05\x0b\x98\x49\x41\x8f\x26\xdb\xb7\x2a\x67\x5e\x5f\xa9\x0f\x1c\xd7\x81\x29\xab\x92\xbf\x55\xc1\xad\x2a\x2e\xfa\x2b\x9e\x3f\x6a\x48\x36\xc5\x8c\xe7\xfd\xaa\xdc\xf9\x49\x62\x49\x3c\xe1\xbf\xd8\x0d\x73\x82\x9e\x55\x89\xa1\x3a\x13\xd6\xff\xb0\x64\x8b\xe7\x49\x75\xca\x67\xdb\xaa\xcc\x40\xce\x37\xdf\x67\x36\xcc\x4a\x1c\xc5\x0c\x7c\xa7\xc4\x2b\xe6\x51\x07\x3c\xae\xfb\xbd\xb1\xfd\x2a\x08\x3b\xf7\xa7\xef\x5a\x13\xf8\xf8\x24\x19\x71\x87\xef\xb3\x26\xd3\x97\x2a\xf1\x9d\xb0\xcb\xb3\x5a\xcd\x6d\xef\xce\xbc\xb2\x5e\x98\xd9\x8e\x9c\xd5\x80\x03\x39\xbd\xfa\xde\x33\xf2\x79\x8f\xb0\xdf\xc6\x78\xc7\x65\x3f\x9c\x9f\x60\x5f\xfe\x0e\xd2\xcb\xf7\x03\x91\x67\xc4\x28\xbf\xfb\xf7\xd9\x65\x5f\xf7\x55\xe6\x6b\xc7\x6c\x48\xf4\x4f\xd8\x52\x5d\xaa\x60\x4e\x78\x87\x57\xeb\x69\xaa\xd2\xac\x47\x68\x9a\x79\xad\x22\xd4\xa5\x77\xfe\x5e\xf3\x7d\x3f\xa9\xdb\x50\x7f\xc4\x91\x8f\x29\x0f\x16\xdf\xc2\x8d\xe2\xc7\xa3\x82\x29\x34\x04\x5e\xc3\x47\x30\x2b\x70\x4d\xa2\xeb\xb8\x17\x9f\x13\xb8\x21\xd1\x4d\x3c\x87\x97\x05\x6e\x61\x17\xae\x08\xdc\xc6\x3d\xf8\x81\xc0\xa7\xb0\x1b\x3f\x16\xf8\x0c\xf6\xe0\xed\xf4\x17\xae\x66\xf3\x5f\x11\xff\x15\xb8\x82\xfb\x95\xe7\x05\xae\x62\x46\x39\x2b\xf0\x1a\x3e\xa5\x6c\x0a\x5c\x93\x64\x74\xec\x55\xbe\x21\x70\x43\xa2\x9b\xf8\xa6\xf2\x43\x81\x5b\x78\x40\xed\x08\xdc\xc6\x7d\x6a\x6e\x67\x0a\x07\xd5\xaf\x0a\x7c\x06\x47\xd5\xef\x3e\xed\x0f\x37\x83\xde\x99\xb5\xd0\x3d\xde\xd9\xf0\xdc\x67\x3a\x83\xd5\x4d\xf7\x48\xf3\xf0\x13\x75\x77\xae\xdf\x77\x39\x6b\xe4\x06\xde\xc8\x0b\x36\xbc\xd5\xfa\xbc\x3f\x08\xe7\x5e\xf5\x46\xfe\xba\x37\xbf\xb8\xb0\xfc\xec\xdc\x53\xb3\x8b\xcb\xf3\x27\x5e\x6c\x2f\x2e\x2d\xbf\xe0\x05\xa3\x9e\x3f\x70\x1f\xab\x3f\x59\x6f\x72\x1b\xed\xbe\xd7\x19\x79\x6e\xe0\x75\xbd\xc0\x0d\x7d\x37\x5c\xf3\xdc\xb1\xc3\x91\xb7\x12\xa6\xf2\x5d\x3f\xe0\x9c\xae\x3f\x08\xdd\x30\xe8\xac\x7a\xeb\x9d\xe0\xac\xdb\x09\xc3\xa0\x77\xfa\x1c\x17\x19\xf8\x61\x6f\xc5\x1b\xd5\xe7\xfd\x20\x74\x85\xff\x71\xbc\x6b\x61\x38\x9c\x6d\x34\x52\xfd\x4e\xc6\xab\xf7\xfc\x89\xc4\x46\xbf\xb7\xe2\x0d\x46\x5e\x03\x4f\xc3\xc7\x10\x9b\x08\xd0\xc3\x19\xac\x21\x84\x8b\xe3\xe8\x60\x03\x1e\x5c\x3c\x83\x0e\x06\x58\xc5\x26\x5c\x1c\x41\x13\x87\xf1\x04\xea\x70\x31\x87\x3e\xfa\x70\x25\xad\x11\x7f\xf2\x30\x82\x87\x80\x6b\xaf\xa2\x8e\x79\xf8\x18\x20\xc4\x1c\x5e\xe5\x3c\x1f\xeb\xf0\xb0\x04\x0f\x67\x70\x0e\x7d\x74\x10\x60\x1e\x8b\x58\xc0\x32\x9e\xc5\x1c\x9e\xc2\x2c\x16\xb1\x8c\x79\x9c\xc0\x8b\x68\x63\x11\x4b\x58\xc6\x0b\xdc\xe6\x08\x3d\x6e\xcd\xc5\x63\xa8\xe3\x49\xd4\xd1\x94\xa2\x6a\xa3\x0f\x0f\x1d\xee\x3f\x8b\xa4\xcb\xb5\x5c\x84\xf0\xf9\xff\x35\xce\x99\x94\x6f\xaa\xb3\x82\xb0\xb0\xdf\x85\x2f\x34\x33\x9d\xae\xc8\x22\xa5\x04\xe8\x60\x15\x1e\xd6\x79\xec\x67\xe1\xa2\x83\x90\xd3\x7b\x38\x8d\x73\x92\x95\x01\x7c\xfe\xb4\xc2\x33\xcf\x6a\x11\x70\x2b\xe5\x6a\x4c\xaa\xf6\x1a\xb7\x39\xc4\x2c\x1a\x68\x14\xfe\x3b\x25\xbd\x3a\xf7\xf4\xc1\x25\x1b\xe8\x8b\x68\x06\x3c\xe3\x06\xc4\x87\xd8\x5d\xfe\xfe\x1f\x00\x00\xff\xff\x31\xa1\x82\xc2\x98\x0e\x02\x00")
+
+func uiAppLibFontAwesome470FontsFontawesomeOtfBytes() ([]byte, error) {
+ return bindataRead(
+ _uiAppLibFontAwesome470FontsFontawesomeOtf,
+ "ui/app/lib/font-awesome-4.7.0/fonts/FontAwesome.otf",
+ )
+}
+
+func uiAppLibFontAwesome470FontsFontawesomeOtf() (*asset, error) {
+ bytes, err := uiAppLibFontAwesome470FontsFontawesomeOtfBytes()
+ if err != nil {
+ return nil, err
+ }
+
+ info := bindataFileInfo{name: "ui/app/lib/font-awesome-4.7.0/fonts/FontAwesome.otf", size: 134808, mode: os.FileMode(420), modTime: time.Unix(1, 0)}
+ a := &asset{bytes: bytes, info: info}
+ return a, nil
+}
+
+var _uiAppLibFontAwesome470FontsFontawesomeWebfontEot = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\xbd\x0b\x7c\x54\xd5\xb5\x3f\xfe\x5d\xfb\xbc\x66\x26\xf3\x3e\xf3\x48\x26\x93\x64\x9e\x67\x02\x89\x01\xe6\x19\x79\x24\x23\x22\xaf\x04\x44\xa5\x8a\x88\x18\x29\x28\x0a\x28\x2a\x08\x52\x1f\xc7\x4a\x2d\x2a\x55\x44\xb4\xd4\x5a\x1b\x9f\x85\x7b\xad\xe5\xb6\xda\xab\x2d\x7a\xa7\x2f\x6b\x5b\xb5\xb6\x72\xad\xb5\xb6\x37\x6d\xb5\xf5\x56\xf4\x06\x6a\xbd\x0a\x99\x93\xff\xe7\x9c\x33\x93\x4c\x02\x68\x7b\xef\xef\xf7\xfb\xfc\xe7\x93\x73\xce\x7e\xef\xb5\xd7\x5e\x7b\xef\xb5\xd6\x5e\x7b\xe7\xb2\xcf\x33\x3c\x76\x33\x03\x81\x61\xec\x8f\xb0\x83\xf4\x6f\xef\x22\x1c\x13\x63\xfe\xce\xdd\xfc\xf3\x1d\xe3\xe3\x80\x00\x66\xe3\x72\x5c\x86\x0d\x38\x05\x9b\xb0\x0a\x57\xe1\x72\xac\xc3\x2a\x00\x4e\x9c\x89\x55\xb8\x18\x1b\xb1\x16\x17\xe2\x4a\x00\x09\x9c\x8d\x55\xb8\x12\x57\xe1\x12\x23\x4f\x04\x59\x74\xa0\x80\x0e\x4c\x46\x04\x69\x4c\xc6\x14\xe4\x3f\xb6\xcc\x0a\x38\x0e\xa8\xe0\xb0\x68\xf6\xec\xc5\x0b\xd6\x3c\x3b\xe7\x69\xb0\x9b\x75\xc8\xc2\x73\x66\x9d\x36\x9b\x0d\x82\x07\xbb\x79\x3d\x80\xc8\xe9\x67\x4d\x4a\x6f\x4b\x6f\x29\x02\xb4\x04\x40\xdf\xa7\xd7\x5d\xb8\xde\xf6\x6f\x53\x6f\x00\xec\x7b\x00\x76\xf8\xe2\x0b\xaf\x5a\x3f\x3c\x0c\x0e\xec\xe6\xd5\x00\x2c\x17\xaf\xbd\xe6\xa2\x3b\xfe\xfb\xf1\x05\x40\xe8\x31\xb0\xde\xfd\xab\x57\x5d\xb8\xd2\x7d\xcb\x5b\x27\x01\x78\x03\x40\x7e\xf5\xea\x55\x17\xba\x38\xdb\x93\x00\xf9\xf4\xe6\xac\x5e\xb7\x61\xf3\x69\xd7\xd4\x7f\x0e\xa0\xa7\x00\xdb\xe0\xda\xcb\x3f\x7d\x21\xfb\xdb\x83\xcb\x00\xd7\x7d\x40\x9d\x7b\xdd\x85\x9b\xd7\x73\xed\x2c\x0c\x50\xa7\x0e\xcf\x65\x17\xae\x5b\xf5\xc7\x2f\xde\xf6\x18\xd8\xc5\xab\x01\xfe\xe6\xf5\x97\x5f\xb5\xe1\x1b\x77\x7c\xf9\x01\xb0\x35\x83\x40\x68\xa3\xd1\x36\x9e\x7e\xb6\xe3\xe7\x9b\xcf\xbd\xc0\x35\xfd\x6f\xa8\x93\x8c\x26\x1f\xc8\xbc\x98\xae\x7e\x87\x87\x87\x61\x25\x51\xf7\x5a\xc0\x2a\x9d\x43\x80\x88\x61\x00\x56\x0c\x0f\x0f\x0f\x5b\x69\xa4\xd3\x2a\x3f\xf6\xa4\x1e\xc2\x7e\xc0\x1a\x90\x32\x03\x8c\x5c\x7a\xaa\x62\x25\x09\x27\x5e\x42\x3b\x20\x00\xfc\x76\x3e\x03\xe0\x66\xf3\xcb\xae\x02\xe8\xd6\x63\xfb\x7d\xf4\xb7\xfe\x9a\x2b\xaf\x42\x11\x91\xbf\x55\x60\x10\xcd\xca\x6b\x21\x88\x80\x38\x15\xeb\x8d\x8a\x3f\x05\x50\x09\xd0\x5b\xf6\x77\x3c\xe7\xeb\x2d\x15\xd5\xd1\x30\xdd\xad\x3f\x82\xee\x57\xc7\xc6\x49\xc0\x35\x82\x8a\xcb\xaa\x69\xc4\x6a\x1e\x00\x82\x19\x16\x12\x2b\x7e\x49\x45\xba\x9a\xe6\x78\x8f\x9e\x8f\x37\xcb\x2e\xea\xe9\xb8\x8a\xdf\xa8\x5b\x1d\x2d\xb7\x02\x83\x4d\xa8\xc2\x59\x93\x86\xaf\xa9\xff\x13\xdb\x5a\x81\x85\xc7\xe8\xb7\xb6\xbd\xd2\xd8\xb0\x2d\x42\x2d\xec\x35\xf1\x22\x03\x09\xc0\xbd\x02\xb0\xf4\x44\x6d\x3b\xce\x53\xac\x94\x93\xd3\x1f\x69\x34\xdc\x21\xa8\x23\xb8\xdb\x52\x8b\x1b\x61\x2c\xde\xdd\xc2\xb8\xbe\xa8\xa4\x5b\x6a\x3c\x6a\x4d\x3b\x4c\x5c\x16\x25\x83\x80\xc7\xe2\xbb\x8a\x87\x9a\xfa\xc1\xa9\x35\x78\x18\xed\x93\x91\x76\xd7\x7e\xab\xb0\x0a\xa3\xf1\xed\x3c\x70\x81\x58\xd3\x37\x82\x3a\xa6\x3e\xbd\xdd\xac\x16\xe6\x13\x3e\x2a\xfc\x95\x76\x0b\xe3\xfa\xde\x5d\xf9\x5e\x25\x01\x54\x49\xc3\x8f\xa7\x25\x09\x70\x8d\x81\x5b\x45\xa3\x54\xc5\x7b\xe5\xb1\x56\xca\xe4\x2b\x7d\xc9\x54\x14\x59\x05\x6f\xd5\x30\x7e\x1c\xac\x12\xd0\x5a\x4b\x47\x9c\x6a\xc2\x30\x9e\x66\xa4\x9a\xf6\xd7\xf4\x5d\xb1\x16\x27\x23\x71\xaa\xd9\x3f\x95\x76\x8d\xc0\xc8\x03\x27\xf1\x80\x83\x57\xb1\x40\x7f\x98\x8a\x93\x98\x3a\xea\xaf\xd6\xc1\x57\xc6\x8b\x38\x96\x7e\x8b\xe2\x78\x9a\x1e\x47\x2f\x35\x63\xb3\x1a\x57\xac\x8c\x3f\x87\xa4\xe2\xa4\x4a\x5e\x26\xa8\x60\x55\x9c\x54\xbe\x7d\x3a\x9e\x98\x8a\x15\x22\x20\xe8\x8f\xa4\x82\xc4\x0a\x2c\x82\x0a\x47\x75\x7c\x0a\x2a\x38\x51\x45\xe2\x78\xfd\x5d\xc1\x8b\xbd\x3a\xf6\xab\x61\xa4\x8e\xc1\x77\xbe\x1a\xce\x03\x9c\xfe\x7c\xd2\xf8\xaa\xe9\xbb\x2c\xf7\x59\x80\xe7\xc0\x0b\xd5\x71\x04\x74\xd6\xd0\x58\x4c\x7f\x24\x98\x8f\x58\x7d\x6a\xe6\x33\x11\x68\xd4\x69\x70\x1c\x0d\xd7\x8d\x6f\x47\xa5\xde\x59\xc6\x18\x02\x38\xfd\xa9\xe0\xb3\x3a\x9e\xab\xe9\x46\xf2\x0a\x40\x7b\xe5\x3b\x32\x0f\x49\x95\xb0\x4a\x3f\x44\x24\x75\x78\xb8\x76\x4e\x15\x00\xff\x71\xc6\xca\xc8\x58\xd5\xd3\x58\xc6\xcd\xc7\xd5\xb1\x6f\x35\xd3\xaf\x13\xc7\xd3\x74\x25\x6d\x75\x7e\x90\x3e\xc0\x84\xf1\xe3\xa9\x02\x67\x75\x6e\x36\xda\x65\xad\xcd\x33\xfa\x75\x5b\x46\xc3\x23\xd5\xfe\xb0\xfe\xfd\x73\xa3\xfe\xa4\xaa\x30\x57\xe0\x8f\x48\x80\x5c\x53\xc7\xac\x0a\x3c\x27\x4b\x80\xb7\x26\x5d\x2d\xcc\x5d\x02\x50\x7f\x9c\x79\x61\xfc\xd3\x20\x01\x2b\x45\xe0\xdc\x0a\xdc\x13\x2b\xe5\x58\x25\x20\x65\xad\xc0\x3e\xfe\xb1\x00\x4e\xfd\x11\xd4\xe3\x97\x6f\x19\xf7\xad\xe2\xb7\xa6\x1f\x0c\xb7\x00\xd4\x59\xc6\xb5\xdf\x32\xce\x6d\x19\xef\xae\xf4\x6f\xc5\x2f\x8b\x35\x65\x56\x68\x9c\x55\xe9\xaa\x66\xbe\x65\xfa\x18\xb5\x00\x62\x25\x8e\x59\x60\x8e\x0b\x61\x1c\xfe\x84\x9a\xb2\x2c\xe3\x60\x18\x4f\x13\x96\x0f\xb1\xd8\x5a\xf1\x1f\x0f\x4f\x55\xda\xb6\x8c\xa3\x81\x6a\xbc\xf4\x09\xb4\x21\x8d\x83\x63\x84\x06\x9e\x1c\x13\x37\x42\x8f\x02\x70\x91\x91\xf7\xa9\xd1\xf2\x47\xda\x3f\xb6\x4f\x02\x22\xe0\x94\x80\xa6\xe3\xd1\x45\x65\x1e\x4f\x5a\x8e\x1f\x7e\xe6\x38\xf8\x4e\xb3\x8e\xa5\xd5\xf1\x6d\x4b\x1c\xaf\x5d\x95\xb2\xa3\x22\xb0\x86\x07\x5a\x2b\xe1\xdc\x78\x1e\x46\xac\xd2\xbb\x6a\xd0\x23\x57\x1d\xe3\x95\xf2\x47\xd2\x0b\xc3\x48\x8a\x95\xf5\x48\x18\x3b\x3f\xb8\x6a\x69\x44\x1c\xbb\xe6\x27\xad\x63\xeb\xf2\x8f\xa3\xaf\x63\x68\xa3\x26\xbc\xc9\x5a\x83\x97\xf1\x4f\x0d\x6f\x41\xe3\xc7\xc5\xc8\xc3\x6a\x68\x5d\xc5\x64\x1d\xe7\x15\x18\x27\xd5\xf0\x28\x8a\xf4\x71\x2c\x71\x85\xa3\xae\x3c\xe1\x0a\x43\x7c\x10\x9c\xe1\x0a\x83\xa7\x97\x75\xc6\x19\x45\x08\x86\xe8\xb3\x17\x8f\xe3\x09\x3c\x87\xd7\xa2\xb1\x58\x73\xac\x6f\xd0\x39\xd8\x3c\xd8\x35\xb8\x70\x70\xf9\xe0\x65\x83\xd7\x0f\xde\x3e\x78\xff\xe0\xe3\x83\xdf\x1c\x7c\x69\xf0\x77\x83\xef\x0d\x6a\x87\x9c\x87\x9a\x0f\x75\x1c\xea\x3a\xb4\xf0\xd0\xf2\x43\x97\x1d\xba\xfe\xd0\xed\x87\xee\x3f\xf4\xf8\xa1\x67\x0f\xbd\x74\xe8\x77\x87\xde\x3b\xa4\x1d\x76\x1e\x6e\x3e\xdc\x75\x78\xe1\xe1\xe5\x87\x2f\x3b\x7c\xfd\xe1\xdb\x0f\xdf\x7f\xf8\xf1\xc3\xcf\x1e\x7e\xe9\xf0\xef\x0e\xbf\xf7\x37\x0c\x0f\x1b\xfc\xf8\x9e\x71\x35\x62\xd0\x3d\x18\x1d\x2c\x0e\x2e\x1a\xec\x1b\x5c\x3f\xa8\x0e\xee\x18\xec\x1f\xdc\x37\x58\x1a\x7c\x79\x70\x60\x70\xf0\x10\x0e\xb9\x0f\x45\x0e\x4d\x3e\x54\x3c\xb4\xe8\x50\xdf\xa1\xf5\x87\xd4\x43\x3b\x0e\xf5\x1f\xda\x77\xa8\x74\xe8\xe5\x43\x03\x87\x06\x0f\xe3\xb0\xfb\x70\xf4\x70\xf1\xf0\xa2\xc3\x7d\x87\xd7\x1f\x56\x0f\xef\x38\xdc\x7f\x78\xdf\xe1\xd2\xe1\x97\x0f\x0f\xe8\x35\x0e\xff\x71\x78\xd9\xf0\x92\xe1\xb3\x86\x67\x0e\x4f\xf9\xdd\xdb\xbf\x7d\xf7\xb7\x8f\xb9\x1d\x6e\xbb\xdb\xe6\xb6\xba\x2d\x6e\xc9\x2d\xba\x05\x37\xef\xe6\xdc\xcc\xf5\x37\xd7\xfb\xae\xbf\xba\x0e\xbb\x0e\xb9\x06\x5d\xff\xe5\x7a\xcf\xf5\xae\xeb\xa0\xeb\x1d\xd7\x5f\x5c\xff\xe9\x7a\xdb\xf5\x67\xd7\x9f\x5c\x6f\xb9\xde\x74\xfd\xd1\xf5\x07\xd7\xef\x5d\x03\xae\xdf\xb9\x7e\xeb\x7a\xc3\xf5\x1b\xd7\xeb\xae\x5f\xbb\x5e\x73\xfd\xca\xf5\xaa\xeb\xdf\x5d\x07\x5c\xaf\x38\xbe\x3f\x5e\xf6\xf9\x7f\xf1\xd3\x05\xb2\x6a\xb5\xc4\x2a\xf2\xd5\x98\x04\x26\x29\xfc\xff\xe1\x27\x0a\x36\x89\xb7\x5b\xac\x75\xff\xb7\x2a\x68\xff\x1f\x3c\x3b\x4c\x99\x9a\x76\x03\x6c\x03\xc0\x5e\x06\xb8\x5e\x80\x1b\x04\xf8\xc5\x80\x98\x00\xc4\x01\xc0\xb2\x16\xb0\x6e\x06\xac\x2f\x03\xb6\xc5\x40\x5d\x2b\x50\x77\x00\xb0\x6f\x05\x1c\x2b\x01\xe7\x1e\xc0\x75\x00\x70\x6f\x05\x3c\x00\x3c\xf7\x01\xde\xb5\x80\xdc\x0e\xc8\xaf\x01\x3e\x15\xf0\x0d\x01\xfe\x1d\x40\x20\x0b\x04\xdd\x40\xfd\x4a\xa0\xfe\x05\xa0\x61\x3d\x10\x9a\x0b\x84\x76\x01\x8d\x09\x20\xbc\x12\x68\x6a\x07\x9a\x2d\x40\xf3\x06\xa0\xa5\x15\x88\x6c\x07\x22\x83\x40\xb4\x1f\x88\x4d\x06\xe2\x11\x20\xd1\x0e\x24\x06\x00\x65\x16\x90\x7a\x13\x68\xbd\x0f\x98\xb0\x18\x98\xa8\x2f\xdd\xfb\x81\x76\x37\xd0\xfe\x3e\x70\xd2\x6b\x40\x47\x11\xe8\x78\x0d\x98\xd4\x07\x4c\xda\x0f\x4c\xf6\x01\x93\x1f\x06\xa6\xec\x02\xd2\x3b\x80\xcc\x4a\x20\x9b\x05\xb2\xbb\x80\x5c\x04\xc8\xa9\x40\xee\x29\x20\x1f\x01\xf2\xcb\x80\xfc\x7e\xa0\x30\x17\x28\xec\x01\x3a\xed\x40\x67\x1f\xd0\xf9\x04\x70\x72\x2f\x70\xf2\x13\xc0\xd4\xd5\xc0\xd4\x83\xc0\xb4\x12\x30\x7d\x3d\x30\x63\x3d\xd0\x35\x1d\xe8\x7a\x13\xe8\x5e\x0d\x74\xbf\x06\x14\xe7\x02\xc5\xfd\xc0\x29\x93\x81\x53\x9e\x02\x66\x2e\x01\x66\x7e\x08\x9c\xba\x12\x38\xf5\x3e\x60\x56\x2f\x30\xeb\x4d\xe0\xb4\xa7\x80\xd9\xf7\x01\x73\x26\x03\x73\xde\x00\xe6\x1e\x04\xe6\x6d\x07\xe6\x77\x02\x3d\x8f\x01\xbd\x6f\x02\x0b\x56\x02\x0b\xdb\x81\x85\x2a\xb0\xf0\x00\x70\xfa\x3e\x60\x51\x1f\xb0\x68\x0f\x70\x46\x16\x38\xa3\x1f\x38\xd3\x0e\x9c\xb9\x16\x38\xab\x1d\x38\x6b\x37\xb0\xb8\x0f\xf8\xd4\x64\xe0\x9c\x41\x60\xc9\x1b\xc0\x52\x0b\x70\x5e\x11\x38\x6f\x3b\xb0\x6c\x3a\xb0\xec\x43\xe0\xfc\xdd\xc0\xf2\x56\x60\xf9\x9b\xc0\x05\xfd\x40\xdf\x7a\x60\x45\x3b\xb0\xe2\x7d\x60\x25\x0f\xac\x3c\x08\xac\x5a\x04\xac\x7a\x19\xb8\xe8\x87\xc0\xc5\x7d\xc0\xc5\x7b\x80\x4b\x7a\x81\x4b\x4a\xc0\xa5\xb3\x80\x35\x76\x60\xcd\x01\x60\xad\x0a\xac\x2b\x02\x97\xb5\x03\x97\xf7\x02\xeb\xb7\x02\x57\x3c\x0c\x5c\xf9\x06\x70\xd5\x66\x60\x83\x1b\xd8\xb0\x07\xd8\x38\x0b\xf8\x4c\x1f\x70\x2d\x80\x6b\xf7\x03\xd7\xb9\x81\xeb\x1e\x06\xae\xdf\x06\xdc\xb0\x0b\x50\xf7\x03\x37\xd6\x03\x37\x6e\x07\x6e\x9a\x0b\x6c\xf5\x01\x5b\x0f\x00\x9f\xdb\x03\x7c\xee\x4d\xe0\xe6\xb5\xc0\xe7\x8b\xc0\xb6\xdd\xc0\x2d\x25\xe0\x36\x37\xb0\xfd\x79\xe0\x0b\xdb\x81\xdb\xd7\x02\x77\xcc\x05\x76\x44\x80\x1d\x25\xe0\xce\xc5\xc0\x4e\x3b\xb0\x73\x2e\xb0\x73\x2b\xb0\xb3\x04\xec\x1c\x02\xee\xea\x03\xee\x7a\x1e\xd8\xc5\x03\xbb\x8a\xc0\xae\x41\xe0\x6e\x15\xb8\x27\x01\x7c\x71\x19\xb0\x7b\x09\xf0\xa5\x30\x70\xef\x2c\xe0\xde\xa7\x80\x2f\xef\x06\xee\xeb\x07\xbe\xb2\x18\xb8\x7f\x09\x70\xff\x87\xc0\x57\xef\x03\xfa\x67\x01\x0f\x2c\x02\x1e\x6c\x07\x1e\x7c\x18\x78\xa8\x13\x78\x68\x0f\xf0\xf0\x4a\xe0\x91\x65\xc0\x9e\x1d\xc0\x3f\x5b\x80\xc7\xc2\xc0\x63\x07\x81\xaf\xef\x00\xbe\xfe\x36\xf0\xb8\x0a\x7c\xa3\x1e\xf8\xc6\x3e\x60\xdf\x5c\x60\xdf\x00\xf0\x2f\x9b\x81\x7f\x79\x01\xf8\x66\x04\xf8\xe6\x06\xe0\x9b\xcf\x03\xdf\x5a\x02\x7c\xeb\x7d\xe0\x89\xf5\xc0\x93\x00\x9e\x5c\x09\x7c\x3b\x0c\x7c\xfb\x00\xf0\xaf\x4f\x00\xff\x3a\x08\x3c\xb5\x19\x78\x7a\x03\xf0\xf4\x87\xc0\x77\x5e\x18\x7d\xbe\xbb\x07\xd8\xbf\x15\x78\xa6\x08\x3c\xcb\x03\xff\xf6\x3c\x50\xfa\x21\xf0\x7d\x3b\xf0\xfd\xed\xc0\x0f\x96\x01\x3f\x8c\x00\x3f\xdc\x0f\xfc\xc8\x0d\xfc\xe8\x29\xe0\xb9\x5d\xc0\xf3\x93\x81\xe7\x07\x80\x9f\xac\x04\x7e\xf2\x02\xf0\xd3\x3d\xc0\xcf\x54\xe0\x67\x03\xc0\x0b\xef\x03\x2f\xee\x02\x5e\xda\x0c\xbc\xf4\x36\xf0\xf3\x7d\xc0\xcb\xdb\x81\x5f\xb4\x03\xbf\xd8\x06\xfc\xd2\x02\xfc\x72\x1b\xf0\x8a\x1d\x78\x65\x3b\xf0\xca\x41\xe0\x40\x27\xf0\xef\xed\xc0\xbf\xdf\x07\xbc\xda\x07\xbc\xfa\x36\xf0\xab\xb5\xc0\x6b\x73\x81\xd7\x9e\x00\x7e\xdd\x07\xfc\xfa\x87\xc0\xeb\x8b\x81\xd7\x9f\x02\x7e\x53\x0f\xfc\x66\x17\xf0\x46\x11\x78\xe3\x79\xe0\xb7\x6b\x81\xdf\x0e\x02\xbf\xdb\x0a\xfc\x47\x3d\xf0\x1f\x8f\x01\x03\xfb\x81\xdf\xaf\x05\xfe\xb0\x1e\xf8\x63\x04\xf8\xe3\x9b\xc0\x9b\x2a\xf0\xd6\xf3\xc0\x9f\x4a\xc0\x9f\xeb\x81\x3f\x1f\x04\xde\x7e\x13\xf8\xcf\xd7\x80\xbf\xbc\x06\xbc\xf3\x1a\x70\xf0\x00\xf0\xee\xcb\xc0\x7b\x6f\x00\xff\xf5\x26\x70\x98\x07\xfe\xfa\x3e\xf0\xbe\x0a\xfc\x2d\x0b\x7c\xe0\x06\x3e\xb8\x0f\xf8\xef\x7a\xe0\xc3\x25\xc0\x87\x25\xe0\xa3\x04\x70\x64\x2d\x70\x74\x3f\x30\xd4\x0a\x0c\x3d\x05\x94\xed\x40\xb9\x0f\x28\x3f\x01\x68\x16\x40\x7b\x0a\x18\xb6\x80\xe0\x03\x09\x4f\x80\xc4\xf7\x41\xd2\x87\x20\xcb\xcb\x20\xeb\x4a\x90\xcd\x0d\xb2\xed\x06\xd5\xd5\x83\xec\x3c\xc8\xfe\x30\xc8\xd1\x0e\x72\x02\xe4\xda\x06\xf2\xb4\x83\x3c\xfd\x20\xef\x0b\x20\xb9\x13\x24\xbf\x09\xf2\xed\x00\xf9\x5b\x41\xfe\x87\x41\x81\x25\xa0\xc0\x10\x28\x58\x02\xd5\x6f\x05\x35\x6c\x06\x85\xae\x05\x35\x2e\x06\x85\x0f\x80\x9a\x8a\xa0\xa6\x03\xa0\xe6\x1d\xa0\x16\x1e\xd4\x72\x2d\x28\xf2\x30\x28\x5a\x02\xc5\x36\x83\xe2\x16\x50\x7c\x2d\x28\xc1\x83\x12\x2f\x80\x52\xab\x41\xad\x6f\x83\x26\xf6\x82\xda\x17\x83\x3a\x7a\x41\x53\x36\x80\xa6\xbc\x0f\x4a\x0f\x80\x32\x93\x41\x99\x7d\xa0\xec\x1e\x50\x6e\x03\x28\xbf\x18\x54\x48\x80\x3a\xed\xa0\x93\xe7\x82\xa6\xba\x41\x53\x07\x41\xd3\x76\x80\xa6\x6f\x05\x4d\x7f\x0d\xd4\xbd\x04\x54\x0c\x83\x4e\x29\x81\x66\x3e\x0f\x3a\xf5\x79\xd0\xac\xfb\x40\xa7\xcd\x05\xcd\x9e\x0b\x9a\xb3\x1e\x34\x77\x2e\x68\xde\x66\xd0\xfc\x08\x68\xfe\x9b\xa0\x9e\x03\xa0\xde\x7e\xd0\x82\x7a\xd0\xc2\x22\x68\x51\x11\x74\x46\x3f\xe8\xcc\x01\xd0\x59\xb3\x40\x8b\x23\xa0\x4f\xf5\x82\xce\xee\x03\x9d\x7d\x00\x74\xce\x12\xd0\x92\x2c\x68\x49\x3f\x68\x29\x0f\x5a\xba\x0d\x74\xde\x4a\xd0\x79\x03\xa0\x65\xd7\x82\xce\x7f\x0d\xb4\xbc\x1f\xd4\xb7\x0b\x74\xe1\x5c\xd0\x85\xfb\x41\x2b\x06\x41\x9f\x5e\x02\x5a\xf9\x18\x68\xd5\x06\xd0\x45\xab\x41\x17\xbf\x01\x5a\xfd\x04\xe8\x92\x65\xa0\x4b\x37\x83\x2e\xdb\x0a\x5a\x5f\x04\x5d\x35\x00\xba\xda\x0d\xda\xf4\x3c\x68\xf3\x0e\xd0\x35\xdb\x40\x5b\xb6\x83\x3e\xb3\x1a\x74\xed\x76\xd0\x75\x61\xd0\x75\x0f\x83\x6e\x58\x06\xba\x61\x37\xe8\x86\x0f\x41\xea\x5a\xd0\x8d\x1b\x40\x9f\xdd\x01\xba\x29\x0b\xba\xe9\x61\xd0\xd6\xe7\x41\x9f\xdb\x07\xba\xf9\x61\xd0\xb6\x0d\xa0\x5b\xb6\x83\x6e\xed\x04\xdd\xa6\x3f\xfd\xa0\xdb\x7b\x41\xb7\xef\x01\xdd\xb1\x18\xb4\xc3\x0d\xba\xd3\x07\xba\x6b\x07\x68\x97\x0f\x74\x37\x0f\xba\x7b\x08\x74\xcf\x87\xa0\x2f\xf6\x83\xbe\x74\x2d\xe8\xde\xe7\x41\xf7\xb9\x41\x5f\xb1\x80\xbe\xf2\x1a\xe8\xfe\x6b\x41\x5f\xad\x07\x7d\xf5\x6d\x50\xff\x0f\x41\x0f\xda\x41\x0f\x65\x41\x0f\x6f\x06\x3d\xb2\x0f\xf4\xa8\x0a\xfa\x5a\x2f\x68\x4f\x18\xb4\x67\x07\x68\xcf\xc1\xd1\x67\xef\x12\xd0\x3f\xb5\x82\xfe\x39\x02\xfa\xe7\x17\x40\x8f\x3d\x06\xfa\xfa\x1e\xd0\xe3\x11\xd0\xe3\xdb\x40\xdf\xe0\x41\xdf\xd8\x03\xda\x57\x04\xed\xdb\x06\xfa\xf6\x7e\xd0\xbf\xae\x05\x3d\x35\x00\x7a\x7a\x03\xe8\x3b\x3c\xe8\x3b\xbb\x40\xdf\x4d\x80\xbe\xfb\x30\x68\xbf\x05\xb4\x7f\x33\xe8\x99\x5e\xd0\xb3\xfa\xf3\x30\xe8\xdf\x22\xa0\xd2\x5c\xd0\xf7\xea\x41\xdf\xfb\x21\xe8\x07\x3c\xe8\x07\x6f\x82\x7e\xd8\x0f\xfa\xd1\x62\xd0\x73\xad\xa0\xe7\x0e\x82\x9e\xb7\x83\x7e\x62\x07\xfd\x74\x1b\xe8\x67\xfd\xa0\x17\x3e\x04\xbd\x14\x06\xfd\x7c\x17\xe8\xe5\xb5\xa0\x5f\xac\x04\xfd\xf2\x0d\xd0\x2b\x8b\x40\xaf\x7c\x08\xfa\xf7\xad\xa0\x57\x37\x83\x7e\xb5\x1e\xf4\xab\x21\xd0\x6b\xef\x83\x5e\x7f\x0c\xf4\x9b\xc5\xa0\x37\x16\x83\x7e\x6b\x07\xfd\x76\x10\xf4\xbb\x6d\xa0\xff\xe8\x05\xfd\x5e\x05\xfd\xe1\x43\xd0\x9b\xf5\xa0\xb7\xec\xa0\x3f\x4d\x07\xfd\x79\x2e\xe8\xcf\x7b\x40\x6f\x27\x40\x6f\x1f\x00\xfd\xe7\x5a\xd0\x5f\xc2\xa0\xbf\x1c\x00\xbd\xf3\x26\xe8\x60\x16\x74\xf0\x29\xd0\xc1\xf7\x41\xef\x0e\x82\xfe\xcb\x02\xfa\xaf\x87\x41\x83\x3c\x68\xf0\x05\xd0\xa1\x08\xe8\xf0\x22\xd0\x5f\xd7\x82\xfe\xfa\x36\xe8\x6f\x76\xd0\x07\xed\xa0\x0f\x4a\xa0\xff\xde\x0c\xfa\xef\x01\xd0\x87\xeb\x41\x1f\xb5\x83\x8e\x6c\x06\x1d\xdd\x00\x1a\xb2\x83\x86\x56\x82\xca\x76\x50\x79\x3b\x48\xcb\x82\xf4\xf9\x62\xf8\x65\x30\xca\x82\xb1\x30\x18\xd7\x0e\xc6\xaf\x06\x13\x0e\x80\x49\x8b\xc0\xac\x59\x30\xdb\x01\x30\xfb\x00\x98\x63\x10\xcc\x55\x0f\xe6\xce\x82\x79\xde\x04\x93\xa7\x83\xf9\xda\xc1\xfc\xed\x60\x81\x2c\x58\x70\x32\x58\x7d\x27\x58\x43\x02\x2c\xb4\x0d\xac\xb1\x13\xac\xe9\x09\xb0\xe6\xc5\x60\xcd\x2f\x80\x45\xae\x05\x8b\xae\x06\x8b\x3d\x06\x96\xe8\x05\x4b\x4e\x06\x53\xe6\x82\xa5\xb6\x81\xb5\xbe\x0f\x36\x61\x3b\xd8\xc4\xc9\x60\x13\xdf\x00\x6b\xdb\x05\xd6\xfe\x06\x58\x47\x02\xac\xe3\x20\xd8\xe4\x83\x60\x53\xb6\x82\xa5\x8b\x60\xe9\x21\xb0\xcc\x53\x60\xd9\x0d\x60\xb9\x04\x58\xfe\x7d\xb0\x93\x23\x60\x53\xb7\x83\x4d\x3d\x00\x36\xcd\x0e\x36\x6d\x1b\xd8\xf4\x56\xb0\xe9\xaf\x81\xcd\xc8\x82\x75\x3f\x05\x56\xdc\x0d\x76\xca\x00\xd8\xa9\xfd\x60\xb3\x86\xc0\x66\xef\x06\x9b\xdb\x07\x36\xf7\x7d\xb0\x79\x2f\x80\xf5\xee\xff\xdf\x3d\x58\x0f\x70\x6e\x51\x67\xfe\x25\xa0\x10\xf5\x44\x39\x4f\xd4\x33\x40\x25\xad\xb8\x9e\xf5\xaf\x17\x22\x47\xd6\x8b\x38\x62\x70\xcd\x84\xf3\x87\x21\x3e\x24\xa8\x68\xd2\x79\x61\x89\x3c\xd1\x74\xc0\x27\xc6\xa3\x31\x25\x9b\xcf\x44\x3d\xa4\xe4\xb2\x5d\x94\x89\xa6\x9b\x49\x7c\xa8\xad\xbc\x8d\x8a\x21\x45\x09\x0d\xa9\xfa\x9b\x8a\xe5\x6d\x6d\x89\xd6\xa0\xa0\x06\x5b\x13\xc2\xec\x78\x5b\x79\x5b\x19\x4a\x56\x51\xb2\x0a\x07\xb6\xb9\x2d\x1e\x6c\xb4\x58\x1a\x0d\x29\x64\x18\xa2\x2e\xb7\xb7\x01\xe4\xf1\x39\x59\xac\x83\x65\xbb\x58\x26\x1d\xf4\x08\x63\xbd\xd9\x7c\x81\xf2\x99\x74\x40\xc4\xac\xd5\x17\x2f\xbd\x78\xf5\xac\x59\xab\x2f\x3e\xe9\x92\x73\xca\x63\xbd\x4a\x33\x57\xb4\xbb\x5b\x3b\x85\xc8\xd1\xfe\xf4\xc2\x36\xbf\xbf\x6d\xe1\xca\x85\x6d\xfe\x14\x6b\x78\xb7\x3c\xad\x36\x80\xfb\x71\x4b\xc6\x46\xe0\x3b\x75\xc9\x68\x18\xa2\x2a\xa8\x90\x10\x05\xe0\x46\x44\x7f\xc8\x27\xc6\x63\x29\x12\xe3\xb1\x84\xc2\xdc\xde\x7c\x22\xc2\x07\xbc\x7e\x9f\x44\x01\x5e\xd5\x3e\xd2\x6e\xd7\x3e\x22\x89\xae\xe4\xa4\xde\x6c\x3e\xa1\xed\xfd\xd6\x1b\x77\x68\x47\x9f\xb9\xfc\xf2\x67\x48\xa0\x66\x12\x9e\xb9\xfc\x5a\x3a\x27\xc9\x24\xba\x92\x24\x33\xb1\xa6\x66\x7b\x15\x3a\xfb\xda\xd1\x14\x97\x3f\xa3\x1d\xbd\xe3\x8d\x6f\x69\x7b\x93\x86\x28\x36\xac\x4a\x10\x80\x10\x66\x60\x01\x90\xf4\x88\x12\x2f\x39\x59\x1b\x8b\x75\x50\x4a\x49\x2a\x29\x8f\x2f\x90\x89\xa6\xf3\x9e\xe9\xac\x83\x8b\x47\x63\xa2\xdf\x17\x0c\x04\x9b\xf9\x69\x2c\xdd\xc5\x15\xf2\x85\x2e\x2a\x78\xcc\xce\xc9\x79\xf4\xee\x49\x07\x44\x35\x92\xd4\xde\xbf\x3f\x53\x5c\x37\x99\x68\xf2\xba\x62\xe6\x7e\xed\xfd\x64\x44\x76\x08\x25\x87\x4c\x82\x68\xb7\x1c\x29\x3a\xe4\xbb\xbe\xf7\xb2\x38\x35\x56\xe8\xf0\x11\xf9\x3a\x0a\xb1\xa9\xe2\xcb\xdf\xcb\x9f\xaf\x2e\x9f\x79\xa4\x38\x73\xf9\xf2\x99\x42\x69\xe6\xf2\x08\x87\x44\xf3\x4b\x5b\xdb\x26\x4f\x99\x32\xb9\x6d\xeb\x4b\xcd\x89\x32\x1c\xb2\xcc\xb7\x32\xaf\xd5\x63\xb1\x09\xb2\x63\xcf\x86\xdd\x8f\x08\x53\x42\x49\xaf\x37\x19\x9a\x22\x3c\xb2\xbb\xed\xce\xbe\xa3\x25\x3d\x37\xaf\x97\x61\xf6\xb1\xde\x36\x15\x61\x80\x8f\xa5\xa8\x83\xcf\x65\xf3\x99\x74\x33\x0b\x76\x71\x99\x74\x40\xc7\x29\x77\x6f\xd6\x5b\xde\x61\x8b\xf7\x4e\x9f\xa4\x0d\x74\xdd\x78\xf9\xa2\x44\x62\xd1\xe5\x37\x76\x0d\x68\x6f\x95\xef\x54\xbd\x6c\xa9\x25\x71\xc1\xca\xdb\x4f\x7d\xe3\xc3\xb6\x79\xc5\x44\xa2\x38\xaf\xed\xc3\x37\x7e\xfb\x56\x79\x8f\x59\xf6\xd7\x45\x55\x18\x40\xcc\xa4\x51\x39\xe0\x37\xfa\x2d\x29\x88\xf1\x98\x92\xcb\x16\x64\x9d\x4c\x0b\x49\x39\x9f\x0e\xca\x42\x40\x54\x43\xda\xdd\x67\x93\xdf\x27\xfb\xb5\x6e\xad\x3b\xe0\xf5\xfb\xd9\xd9\xda\xae\x86\x4e\xfa\xe0\xf7\xf2\x74\xf9\xf7\xf4\x41\x27\x77\x4d\x20\xa4\xdd\xaf\xd9\x25\x87\xbf\xc9\x7e\xf0\xa0\xbd\xc9\x2f\x3a\xe9\x7d\x5a\xd1\xe8\x4f\x5a\xe7\xd1\x8f\x27\x4c\xd0\x4e\x9e\x67\x85\x29\x51\x57\xea\xb6\xea\xd4\x6b\xa5\x64\x1d\x09\xc4\x25\x85\x2a\x1c\x27\x06\x83\xbf\x82\xd2\xda\xd2\x67\x9e\xd1\x96\x52\x7a\x1e\x6d\xa1\x6b\xe8\xc7\x06\x5c\x13\x4e\x0c\x16\xf3\xd1\x84\x2e\xba\x5e\xfb\x6c\x97\xf6\x2b\xed\xbc\x1f\xff\x98\xb3\x55\xc1\x4c\x7f\x0c\x94\x3a\x8c\xaa\xa0\xe3\xde\xaf\x8f\xe2\x64\x85\x42\xb2\x5d\x5c\x26\x10\x29\xa4\x9b\x39\xb8\xc5\x88\xe2\xce\x47\x04\x5c\xb7\x64\xe8\x9f\x96\x5c\xe7\xe9\x98\xb3\xb1\xf7\x26\x5a\x7b\x53\xef\xc6\x39\x1d\x9e\x61\xfc\x5e\xfb\xfe\xef\x7f\x4f\x5d\xb7\xac\xbb\xef\xbe\x75\x9f\xfa\xe2\x97\xd6\x9d\xa6\xaa\xa7\xad\xfb\xd2\x17\xb9\xef\x99\xe1\xbf\x07\x50\xa7\x8f\x1f\x49\x1f\x3f\x2e\xb4\x60\x12\xba\x71\x3a\x2e\xc0\xe5\xb8\x01\x77\xe0\xab\xf8\x06\x20\xe4\xb2\x4a\x1b\xc5\xc4\x26\xf2\x05\xa6\x51\x3a\xef\xf9\x04\x3f\x79\xb2\x8a\x41\xe1\x15\x92\xa7\xf1\xf1\xff\x60\xfa\x4f\xaa\x6f\xfc\xc0\x21\x55\x09\x19\xb3\xd8\x09\x5e\x3c\x94\x50\x19\xba\x87\x43\x48\x19\xc2\x68\x8c\x50\x93\x53\x53\x6b\x53\x7d\x52\x99\xea\xf2\x99\x1f\x19\x83\x46\x2c\xce\x5c\x5e\x1c\x89\xa2\x7b\x8f\xe7\x2c\x87\x98\x51\xb0\xa6\xbf\xf9\xd1\xf0\xa3\xa3\x4e\xae\x36\x89\x76\xdc\x52\x6a\x9c\xdf\x39\x62\xd4\x2d\x18\x03\x96\x37\x74\x32\xb5\xfd\xa9\xcf\xcc\x63\x30\xd4\x40\xe3\x30\xf6\x09\xf1\x1c\x7a\xb3\x1a\xb2\xbd\xbd\x59\x66\xbc\x47\xdd\x9c\x7a\xa2\x18\x06\x7d\xca\xec\xcd\x92\xfe\x66\x2f\xd4\x78\x86\x5e\x38\x51\x8c\xa1\xc0\x85\x31\xd7\x1c\x4b\x8b\x20\xbf\x09\xd5\x0c\x32\xa1\xf2\x8c\xf3\x8f\x8f\xff\x3f\xed\x1f\x5f\x1f\x43\x67\xab\x56\x6a\xed\xec\x6c\xa5\xa2\xfe\x1e\x75\x33\xb5\xd6\x57\x56\x4f\x1c\xf7\xf7\xa7\xac\x75\x53\xc4\x70\xea\x2f\x7a\x6d\xc4\x59\x1e\x75\x72\xc7\x0d\xfd\xc4\x04\x35\x85\x99\x0a\xeb\x63\xfb\xe2\xff\x78\x2f\xfc\xfd\x58\x15\xd0\xd9\x3a\x64\x84\x71\xa5\xd6\xce\xa3\x38\x71\x5c\xad\xfb\x7f\x88\xab\x31\xa8\x00\xe1\x1a\x38\xc5\xcf\xf3\xdf\x44\x00\x80\x4f\x22\x49\x8c\x4d\x22\x52\xb2\xdd\x94\x4f\x07\xad\x94\x4f\xb7\x90\xf8\xf9\x70\xb9\x7d\x5b\x78\x51\x78\x9b\x76\x4f\x38\xac\x3b\x48\x61\x3b\x74\x3f\x77\x78\x91\x11\x15\xde\x46\x97\xea\xfe\x70\x58\xfb\x35\xbb\x33\x1c\xde\x06\xc2\x65\xc3\xef\x09\x5e\x7e\x27\xe2\x40\xc2\xe7\x22\x31\x96\xb2\x92\x5e\xb6\x92\x2d\x58\xc7\x96\x1f\xf0\x49\x56\x12\xbc\x46\xc9\xda\xeb\xda\xeb\x66\x49\xa4\x68\xaf\x57\x6b\x23\xa5\x52\xfa\xeb\xa4\x68\x1f\x1b\x1b\x1e\x29\xc5\xe4\x5d\xcc\xf9\x22\x8e\x36\xcc\x32\x7b\xb8\xcd\x7c\xe9\xdd\x12\x37\xfb\x66\x1a\xe5\xf4\x57\x3a\xd0\x44\x99\x74\x33\x55\xb8\x2c\x9c\x88\xcb\xe2\x21\x3b\x06\x64\x47\xd1\x21\x0f\x38\xe4\x1a\xe7\x18\xde\xab\x27\x77\x22\xde\x8b\x0d\x1c\x93\x53\x77\xfe\xa9\x86\x21\x7b\xf2\xd2\x9e\x13\x30\x64\xb5\x6d\x72\x21\x88\xc9\xc7\x50\xed\xdf\x07\x7f\xb9\xa4\xd7\xca\x8a\xff\x18\xd4\x06\xbc\x7f\x37\xa4\x95\x35\x5e\xd4\x87\xdb\x04\xe4\x74\x2e\x88\x89\x7c\x24\xa1\xb0\x5c\xd6\x5b\xc8\x07\x82\x01\x51\x72\x92\xdf\xd7\xcc\xd2\x5d\x2c\x97\x55\x52\x1d\x54\xe8\xa2\x60\xc0\xab\xcf\xd9\xe6\x0c\xad\xf3\xd4\x5b\x5e\xd2\xde\xd4\x9e\xd7\xde\x7c\x69\xcb\x03\x3b\xdb\x2e\x69\x89\xb8\x26\xae\x58\x73\xc6\xad\xcf\xbc\xfc\xcc\xad\x67\xac\x59\x31\xd1\x15\x69\xb9\x74\xe2\xce\x07\xca\x6a\xef\xea\xde\xde\xd5\xbd\x4c\xbd\x4f\x4f\xb9\xe5\x25\x0a\xdf\xf7\x6d\x9a\xb9\x2e\xe2\x6c\x9b\x78\x49\x64\xfe\xab\xd7\xac\x7e\xe6\xd6\x33\xce\xb8\xf5\x99\xd5\xd7\xbc\x3a\x3f\x72\xc9\xc4\x36\x67\x64\x9d\xf6\x2c\x9b\x5f\x36\x26\x68\x66\x4c\xd0\xe6\x06\x59\x85\x1f\x1c\x9d\x17\x90\x1c\x21\x17\x93\x48\x92\x1e\xd3\xaf\xc3\x77\x3c\x3f\x7d\x92\x1f\x5e\x67\xc9\xe9\x35\x5e\xa4\xfe\x63\xee\xbe\xaa\xc3\x7b\xa5\x66\x38\xa9\xe8\xf4\x7a\x0f\x97\x0d\x37\xd3\xdd\x74\xe5\x90\xfe\x71\x72\x7a\x10\x1d\x3e\x62\x78\x04\xdd\x33\xda\x1f\x86\x3c\x71\x19\x80\xac\x12\x13\x7d\x81\xb4\x4e\x41\x2e\x12\xa5\x40\x30\xe0\x93\x9c\x14\x8f\x4d\x22\x51\x12\x25\x03\xea\x49\xa4\xa4\x24\x9d\x90\x94\x94\xce\x26\x76\x51\x41\x99\x44\x1d\xa4\x23\xa3\x9b\xf2\x85\x6a\x68\x26\xdd\x42\xf9\x42\xbe\x60\xb4\xb0\x85\x02\xc1\x42\x3e\x93\x0e\x06\x82\x3a\x0b\xed\x24\x29\xd0\x42\xcd\xc4\xe3\x9e\x03\xf7\xdc\x73\x80\xdd\xe3\xb6\x3f\x2d\xfb\xe2\x73\x6d\xd6\xc6\x1d\x01\xbb\xf3\xd6\xf6\x49\x6e\x87\xd4\xf4\x3b\xa7\x9f\xc2\x53\x26\x7c\xc1\xe6\x72\xd6\x5d\x9f\x92\x2c\xae\xb9\xde\x46\xe7\xbf\x3a\xdc\xee\xba\xef\x38\x1b\x5a\x4f\xb5\x59\x43\x77\x06\x1c\x8e\xb1\x89\x6f\xb7\xba\x1c\xf6\x1b\x13\x46\xe2\x90\xeb\x5f\x1d\x6e\x16\xd0\x6b\xb8\x87\xd6\xfd\xce\x1e\x60\xe1\x7c\x32\xbd\xc4\x1e\xb2\x25\x6f\xb7\xae\x0d\xba\xb6\xa5\xc3\x1e\xc7\x53\x6e\xff\x1a\x6b\xdd\x95\x79\x9b\xc3\x5e\xe7\x3f\xaf\x21\x3d\xa5\x91\xf9\x1d\x46\xda\x8e\x8e\x93\xcf\xb0\xdb\x6d\x8e\xc4\x1d\xb6\x35\xb5\x89\x6d\x9b\x32\x16\xa7\x99\x78\x72\x98\xf9\x8d\xb5\x63\x58\x15\x46\x79\x90\x69\x38\x15\x17\x9b\x7c\x48\x6d\x2f\x0b\x9f\xe0\x97\x3d\x51\x8f\xaf\x59\x97\x51\xbb\x88\xa2\x29\x25\x15\x15\x25\xc1\xa0\xb4\x11\x86\x25\x5e\x1d\xd3\x05\x43\x96\x0d\xb4\x90\xb1\x86\x78\x9d\x46\x9f\x16\x9d\x5e\x3a\x81\x5b\x1d\x52\x9d\x2e\x8e\x2b\x72\x2e\x67\xb9\x8f\x4a\x93\x25\x9b\xf6\x03\x9b\xc4\x5d\xee\x75\xf6\x2d\x9f\x39\x54\x9a\xb9\xbc\xcf\x20\x9d\xdc\x6c\xd7\x42\x7d\x85\x59\xe8\x9a\x4d\x39\xa7\x97\x8b\xd4\x90\x91\xf3\x04\xee\x72\x33\xf7\xc4\x50\x6f\x20\xe9\xf1\x24\xf9\xf9\x1b\xad\x8c\x59\xef\x2e\x3a\xbd\x43\xbd\x67\x5d\xb3\xf1\x2c\xee\x29\xa3\xf6\xaf\x25\xb3\xd9\xe4\xd7\xbc\xe6\xf8\x0f\x01\xe2\x45\x02\x07\xd9\x18\xff\x46\xd3\x3c\x51\x4f\x85\xff\xca\x59\x29\x50\x90\x44\x29\x6e\xac\x0c\x29\x9d\xd6\x74\x49\x3a\xdd\x52\x9d\x8f\xfd\x9e\x60\x33\xe9\x9c\xab\xa6\x0e\x43\x53\x43\x0a\xb1\x6e\xd6\x4d\xff\xd1\x65\x71\x70\x0e\x4b\xb9\xb7\xdc\x6b\xb7\x3b\x2c\x5d\x16\x66\x63\x3f\x8f\x2c\x89\xbc\x6f\x0c\x8d\xdf\xd8\x18\x8b\x68\x11\x9d\xb1\xd5\x19\x5d\x1a\x20\x9e\xe8\x75\x4d\x61\xa7\xcc\xb7\x32\x89\x9d\x52\xfe\x37\x0b\x31\xeb\x7c\x5b\xa3\x85\x9d\x13\x0a\xbd\xf0\x03\xbd\x6d\xda\xea\x6f\xeb\x32\xbf\x39\xb7\xea\x5d\x2c\x23\xa4\xaf\x5b\xd4\x4c\xfe\x71\x0c\x64\x50\xf2\x44\x95\x14\x29\x64\xb6\x22\xea\x11\xf6\x87\x5b\x3b\x5b\x8f\x18\x6b\x2a\xa7\xb6\xf6\x85\xb7\xd2\x66\x9b\x5d\xfb\xb1\x9d\x3e\xad\xf5\xb5\x76\x96\xc1\x6f\x0d\xf7\xb5\x1e\x55\xf5\x78\xb1\xd8\xda\xd9\x1a\x9e\xa5\x6d\x6b\xb2\xd3\xc9\xf6\x23\x5e\x1e\x9d\xad\xd4\x6f\x28\x35\xb8\x91\xb1\xe9\x43\x04\xed\xa3\x9c\xad\x39\xef\x54\xc8\x06\xee\x0e\x8a\x38\xc9\xdd\x4c\x91\x3c\xdc\x8c\x8f\x24\x98\xdb\x9b\x88\xf0\x9c\xea\x75\x9a\x33\xc2\x80\x49\x0e\xfd\x3b\x8f\x68\xaf\x1d\xd9\xb9\xf3\x08\xb5\x1e\xa1\x2b\x5f\xd2\xbe\xaa\x2d\xd7\xbe\xfa\xd2\x4b\x74\x21\x3d\x48\x17\x72\x03\xda\x08\xdd\xe8\xb4\x50\xd6\xa8\x55\x4f\x6b\xe4\x60\x17\xd4\x26\x7d\xe9\x25\xa3\x1f\xd3\x80\xb4\x50\x00\x3c\x38\x15\xa0\x1c\xd7\x41\xba\x98\x22\x71\x7e\xd1\x94\x73\x7c\xf1\x68\x3a\x9f\xe2\x3a\x48\x97\x76\x24\x4e\x0c\x64\xa2\xb1\x5c\xb6\x40\x3a\xe5\xc6\xf4\xc9\xc5\x48\xa6\xcf\x1c\x71\x1d\x87\x14\xe0\xcf\xa9\x27\x9f\xe3\x3b\x0e\x1f\xd5\x93\xd7\xfe\xbe\xdd\xcb\x3e\xe8\x28\x17\x1d\x5e\xf2\x91\xcf\xa1\x0d\x3a\x7c\xe4\x23\xaf\xa3\x5c\xec\x08\xd1\x03\x96\x84\x8f\xce\x72\xf8\xc8\x45\x5e\xc7\xa3\x0e\x2f\xb9\xc8\xe7\xa0\xb3\x7c\x09\x0b\x3d\x10\x62\x61\x9e\x8c\x95\x49\x2b\xf1\x76\xb7\x5b\x3b\x79\x9e\xec\x20\xe8\x01\xc3\x70\xc8\xf3\xf2\x5d\xbc\x4f\x0e\xcb\x0e\x73\xde\x74\xc8\x61\xf9\xe8\xc1\xae\xaa\x1c\x21\xea\x4c\xa0\x0b\x49\xcc\x00\x12\x95\xb9\xb0\xfa\x95\xc7\x74\x7b\x30\x90\xee\xd6\x47\x1f\x05\x24\x9d\x8f\x21\xa5\x90\xcf\x44\x2b\x04\xe1\xf7\x44\xd3\x82\xa9\x41\x22\xc5\xf8\x3c\xda\xd9\x7a\xc4\x60\xd2\xe8\x17\x9f\x9f\x7a\xdf\xd4\x6d\xf4\x72\x6b\xa7\xf6\x5d\x4f\x8b\x56\xf4\xe6\xbd\x5a\xb1\xc5\xe3\x99\x48\x50\x42\xa4\x0b\x5f\x98\xf8\x68\xd6\xcc\xa5\xff\x51\x64\x94\xef\xdb\xd6\xd9\xb9\xad\x93\x79\x26\x34\x69\x45\x59\xa6\x52\xd3\x84\x14\x95\x0c\xb9\xa9\x58\x43\x2b\xf5\x48\x18\x3c\x80\x6f\x04\xae\x11\x52\xf1\x7b\x32\xe9\x00\xab\x10\x4b\x17\xb9\x15\xbe\x86\x5e\xf8\x3e\x9b\xf6\xbd\xba\xfa\x3a\xad\xe4\xb2\x58\x02\x25\x63\xe0\x94\x9c\xde\x17\x46\x68\x66\xe7\xce\x63\xa8\x86\xf5\xd9\xed\xda\xf7\xac\x56\x2a\xba\x65\x9f\x41\x37\x4e\xad\xdf\xcb\xd2\x35\x94\xf6\xcc\x31\xa4\x73\x1c\x58\xcd\x39\xce\x9c\x0c\x4d\x15\x84\xce\x09\xd2\x89\x61\x5d\x5e\x03\xa1\x8d\xba\xeb\xea\xeb\xa8\xe8\xfa\xe5\xc7\x82\xba\xcb\xa7\xf5\x1b\x93\x5c\x9f\xd7\x69\xb7\x53\xb7\xd5\xaa\x95\xdc\xf4\xd1\xc7\x80\x6a\x58\x21\x88\x3a\x0b\xe0\x30\x46\x7e\xb4\x83\x52\x5c\x94\x73\x92\x14\x0d\x46\x93\xa3\xd4\x50\x90\xcd\xd9\x38\x28\x07\xb8\x61\x9a\x4e\x1c\x1d\x28\x4f\x3f\x40\x1c\xd1\xf4\x0b\xa8\xc8\xfa\x94\xd0\x11\x35\xa4\x34\xbc\x67\xcb\x85\xb8\x62\x28\x67\x7b\xaf\x81\x15\xb9\x3a\x46\x83\x9a\x9b\xab\x63\xa5\x07\xb5\x66\x43\x0b\xf9\x87\xae\x19\xac\xb5\x21\x16\x6b\x28\xbf\x36\xa3\x06\x47\x2e\x34\x1a\x56\xe7\x7a\x7f\xea\x8b\xae\x5e\x61\x3e\x48\x81\x13\x0c\x7b\xbe\x3f\x52\x1e\x70\x79\xdc\xee\x48\x24\xda\xc2\x22\x1f\x3b\xe8\xd9\x23\xf3\xbd\x5a\xc9\x6a\x91\x93\x4c\x4d\xca\x5e\x59\x2b\xfd\xec\xe3\x46\x3d\x8d\xc0\x94\x19\x99\x8b\x52\x4a\x37\x29\xf1\x98\x93\xf9\x9a\x59\x26\xad\xaf\xf7\x69\x7d\x61\x97\x44\x7e\x84\xc9\xcc\xa4\xf9\x60\x21\x1f\x0c\x88\xd0\x29\x75\xa2\xc7\xd3\x72\xeb\xae\x9f\x54\x99\xaf\x4d\x07\xe6\x49\x6e\x97\xed\x16\x2b\x59\xd6\x69\x3f\x7d\x6c\x94\x55\xbb\x8b\xe4\x35\x9f\x6d\x9a\x90\x12\xa0\x15\x43\x4a\x6b\xaa\xf9\xd6\x5b\x2a\x2c\xde\xea\x0b\x6c\xcc\x7a\xab\xa5\xc1\xb6\xf5\x4e\x3d\x25\x75\x52\xf8\xa5\x2d\x97\xaf\xba\xb1\xc5\xe3\xa9\xe5\x67\x12\x98\x63\x8c\x02\x86\x68\x2c\x91\x92\xc4\xd1\xf9\xda\xe7\xa2\x66\x32\x81\xad\x2c\xbc\x15\x45\xb1\xd1\x94\x11\x3e\x67\x06\x79\x11\x35\x60\x4f\x07\x84\x3f\x53\x51\x5b\xad\xbd\xb7\x53\xfb\xaf\x35\x37\xca\x59\xbd\xbb\x4a\x21\x45\xbe\x65\xce\x13\x17\xde\xfc\xf6\xec\xba\x89\x96\x40\xc9\x21\x37\xe8\xed\x0b\x29\xf2\xad\xbb\x7e\x52\x09\xfc\xb1\x43\x3e\x85\xee\x25\x79\x27\xf9\xd6\x7c\x56\xce\x2a\x34\x20\x30\xed\x7d\xed\x5b\x97\x5d\x74\xa3\x6c\x16\xa1\x64\xe5\x5b\x66\xce\xfd\xec\x95\x9e\x95\x41\x99\x93\xf5\xec\x4a\x56\xbe\xf5\x16\x33\xc0\x21\x91\x9d\x16\x5c\xbe\xea\x46\x59\x41\xc5\xd8\xea\xf8\xfa\x02\xd0\x38\x8e\x34\xf7\x09\xfe\xf1\x72\x69\xee\x13\xfc\xf2\x38\xad\x95\x7c\x8c\x16\xca\x14\x04\x4e\xf4\xe2\x55\xd9\x31\x64\x78\x38\x43\xcc\x38\xbe\x5b\x95\x1d\x47\x0c\x8f\xa0\x7b\x6a\xf5\xba\xd4\x37\x52\xdc\x5f\x8f\xe3\x2a\x1f\x2f\xb0\x26\x3a\xc3\x19\xee\x21\xbd\x3e\x7e\x41\xad\xc2\xd7\x18\xe3\xbc\xa9\x4f\x6f\xd1\xc7\x78\x4e\x9f\xed\xfd\xb5\x3a\x22\x5d\x16\x44\x04\xba\x24\x18\xa0\x22\xd3\x59\x56\xae\x58\x15\xba\x23\x64\xa1\xf5\x64\x89\xb4\x76\x72\x28\x5d\x7a\xcf\x3d\x97\x6a\x03\x65\x63\xbe\x66\xc5\xd6\xce\xd2\x53\x64\xd1\x3e\x7c\xaa\xd4\xa9\xd3\x65\xb1\x22\x47\x78\x50\x30\xe8\x72\x64\xc2\x53\x72\xba\x54\xa3\x73\x83\x3a\x57\xdd\xc1\xe2\x31\x53\x0f\xab\x8f\x73\x9d\x67\x0e\x04\x03\x99\x74\x17\x33\x6a\x2f\x1a\x0d\x2a\xf6\x5c\xda\x23\x94\x1a\x1a\x7f\x75\xef\x8c\xeb\x96\xdd\x36\xaf\xa4\x0d\x7a\xdc\x21\xa5\xc5\x3f\xf5\xe0\xd3\x6b\xbe\x73\xbd\x92\xce\xdf\x70\xfe\x59\x8e\x90\x22\x60\xae\x72\xd4\xa9\x37\x9c\x3f\xac\xcc\xcd\xf5\xf4\x6c\x2c\x0b\x0d\x8d\xce\x0d\xed\xd9\xf6\x9d\x56\x25\xc4\xfe\x14\x09\x3a\x9b\x36\x4f\x9d\x26\x4f\xcc\x4e\x54\xaa\x67\x4e\x0c\x39\xb2\x47\x87\xd0\xc5\x9c\x14\xf7\x8f\xe5\x51\x9b\x28\xad\x33\xf2\xb9\x2c\x4b\x44\x78\xe6\xf7\xb5\xe8\xcb\xf9\x08\x6b\x56\xa5\xb1\x98\x32\x89\x29\xb9\x6c\x45\xc0\x14\xd5\xe9\xbe\xa7\x03\xb7\x2c\x19\xe5\x46\xe7\x5c\x1d\x9b\xd5\xb4\x4f\xfb\x95\xf6\x4d\xed\x57\xfb\x9a\x66\xc5\xae\x9e\x33\x1a\xb7\xe4\x96\xc0\xd3\xbe\xe9\x37\x0f\x50\x96\x7a\x29\x3b\x70\x33\xbb\xf5\xd1\x5d\x53\xa2\x67\xad\x89\x8c\x32\x9f\x91\x39\xd3\xed\x17\xac\xd8\x45\xe2\x7d\xf7\x69\x47\x76\xad\xb8\xc0\x3e\x7d\x4e\x64\x94\x29\x8d\xac\x39\x2b\x3a\x65\xd7\xa3\x5f\xa4\xfa\x17\xb7\x6c\x79\x51\x7b\xdb\x6c\x57\x84\x03\x3f\x00\xd9\x9c\xb7\x62\x29\x1a\xa1\x5d\xca\xa7\x03\x1c\x94\xac\xac\x7d\x4b\x3b\x62\xcc\xc3\x22\x2d\x90\xb3\x0a\xdf\x7f\x54\x1f\xe1\xb4\x40\x09\x91\xce\x66\x2e\x30\xc7\xa0\x4e\x2f\x11\x5e\x35\xca\x3a\xe9\xf8\xa5\xc1\xec\x48\x43\x71\x9d\xed\xe0\x8c\xed\x83\xe0\x71\xeb\x20\xf5\x53\xb3\x6d\xae\x90\x52\x1f\x8b\xd5\xeb\x8f\x12\x72\xd9\x66\x1f\xa7\x62\xcd\xbb\xfb\xa6\xb0\x90\x6c\xf4\x37\xf9\x1b\x26\xcd\x9c\xd4\xe0\x6f\xf2\x37\x26\x85\x46\x98\x86\x99\xc3\x4f\x8b\xaa\x30\xc7\x80\x67\x1e\xd6\xfc\x23\x30\xf1\x6e\x56\x09\x35\xf6\x64\xb2\x8a\x29\xd2\x8d\x8f\xeb\x22\x9d\x10\xbd\x6e\x96\xd2\x05\xf2\x91\x14\x7f\x77\x8b\xe8\x53\xff\xb4\xdd\x61\x6f\x54\x52\x9d\xbe\xf9\x67\x9d\x35\xdf\xd7\x99\x52\x42\x0e\xc7\x76\xfa\x27\xed\x15\x87\x23\xa4\xa4\xa4\x16\xa9\x23\xf1\x99\x5b\x6f\xfd\x4c\xa2\x43\x6a\x91\x8c\xc8\x57\xfe\x7e\x2c\x14\xb4\x97\xb4\xf2\x34\x41\x09\xa5\x7c\x4d\xae\xfc\x43\x4f\x3d\x94\x77\x35\xf9\x52\x21\x45\x98\xf6\x6d\x2d\xab\xdd\x70\x9e\xa0\x84\x12\x41\xde\xc1\x37\x84\xce\x23\x37\xa5\xc9\x7d\x5e\xa8\x81\x77\xf0\xc1\x44\x48\x11\xce\x83\xdd\x10\xf2\x75\x9a\xe7\x20\xa1\x0e\x2e\xc8\x08\xa2\x11\x2d\x88\x63\x12\x32\xc6\x58\xf5\xc7\x73\xb2\x3f\x9e\x8b\xfa\xe3\x39\x32\x64\x15\x4f\x54\xff\x92\x27\xea\xa1\x4a\xb8\xec\x89\xe6\xe2\x9e\xb8\x27\xea\xcf\xe4\xc8\x4c\xe2\x21\x55\x55\x55\x4e\x55\x87\x54\x5d\xec\xd0\x1f\x0e\xfa\x7b\x18\x65\x95\x57\x55\x3d\x5a\x53\x8d\x6f\x59\x2d\xab\x82\x5a\x36\x82\x38\xe8\xd9\x86\x88\x6e\xa0\x4a\x3e\x3d\x96\xa9\x9a\x11\xce\xa0\xe9\xb9\x98\x91\x50\x0f\xd6\x1f\x18\xfb\x80\xd5\xb5\xe1\xd8\x76\xa4\xd0\x56\x69\xcb\x34\x74\x03\x99\xb8\x27\x23\xff\x2f\x9e\xee\xee\xee\xee\x48\x64\x79\x4b\xcb\x57\x5a\x5a\xbe\xd2\xd5\x75\x7d\x4b\x4b\xb7\xf1\xf7\x95\xee\xee\xaf\x74\x77\x5f\x6f\xfc\x2d\xef\xee\x7e\x66\xf9\x72\x3d\x59\x77\xb7\xa0\x1e\xb9\x51\xb8\xe1\x7f\xf4\xe8\xfd\x62\xae\xe9\x77\x0b\xef\x18\x73\x74\x53\x8d\x8e\xa2\xc2\x11\x51\x07\x8d\x48\x62\x14\xa0\x52\xcf\xa5\x3d\x3d\x97\xf2\x57\x27\x35\x7f\x2a\x9b\x4b\x96\x73\x4a\xae\x37\x4b\xfd\x39\x55\x61\x3f\x4b\xf2\x75\x7a\x64\x8f\x56\xcc\x25\x35\x5f\x32\xc9\x5e\x48\xaa\x39\xea\xcf\xf6\xe6\x94\x72\x3e\x55\xe5\x4d\xef\x96\xd6\x54\xea\xca\x7d\x52\x6d\x82\x19\xaa\xa4\x28\x9f\xcb\xea\x71\xf1\xcc\xdf\x01\x05\xa9\x46\x70\xa2\xa3\x99\x5e\x4d\xea\x71\x6a\x6e\xe0\xef\x80\x2f\x6b\x04\x86\x5b\xe8\xd5\x64\x2e\x9b\x62\x3f\x55\x72\x26\xd8\x1c\x6c\xc3\xaa\x78\x8d\xa0\x62\x31\x56\x62\x03\xa0\xcb\x24\x4e\x5d\xee\x52\x52\x4a\x21\x9b\x2f\xe4\x95\x42\x17\x33\x86\xb1\xa2\xbf\xc7\x3b\x58\xa1\x4b\x0c\x4a\x46\x93\x2a\xf9\x24\x31\x68\x2c\xf3\x05\xca\xa7\x02\x82\x68\xb8\xbb\x29\xaf\x8c\x8a\x72\x35\x7e\xf1\xe2\xd6\x80\xf6\xae\x7c\xd5\x29\x43\xab\x16\xdc\x11\xae\x0f\x88\x44\x16\x62\x76\xbf\x18\x6c\xb7\x70\x02\xe3\xc2\x9c\x7f\x22\x4f\x12\xcf\x27\x78\x79\x12\x4f\x16\xc6\x9c\x01\xd1\xe2\x71\xc8\xbe\x68\x2a\x4c\x8a\x83\x7d\x34\x7f\x51\x40\x7b\x2f\x31\xe7\xfc\xa1\x2f\x37\xd6\xd5\xd9\xea\x37\x73\x5f\x6e\xca\x5b\xa8\x5d\x62\xca\xd1\x77\x79\xbb\x93\xf5\x39\x1a\x78\x3f\x6f\x77\x96\xfb\x1d\x0d\xfc\xea\x63\x42\xf8\xd8\xc9\x73\x87\xae\x2e\x9e\xb3\x66\xe1\xa9\xd3\xf9\x0e\xa7\xa5\x51\xac\xf3\x35\xda\x94\x35\x8a\xad\xd5\x52\x17\x13\x13\xeb\x63\xd6\x0e\xc1\x11\x17\x42\x1b\x15\x4b\xdc\x6a\xf1\x85\x2c\xf6\x64\x34\xd5\x10\x20\x91\xb3\xae\x9f\x3f\x74\xf5\xa6\xd3\x5c\xee\xc6\xd9\x2d\x21\xee\x37\x81\xb8\xab\x79\x84\x6d\xd1\x4a\x23\x4e\x73\xef\xf6\x8b\x42\x65\x5f\x98\xd2\x41\x53\x0b\x60\xa8\xc1\xac\x06\x5d\x98\x64\x51\xc8\x67\xf8\xed\x41\x7f\x34\x95\x8a\xca\x0d\x93\xe3\xda\x1c\x6d\x4e\x62\x92\xe9\xf7\x07\x05\xd5\xea\xe8\x8c\x1d\xf9\xef\x58\xa7\xc3\x12\xa1\x3d\xda\x92\xa8\xee\x17\xac\xb1\x4e\x87\xb5\x3a\x97\xab\xa2\x39\x17\xd9\xe1\xc3\x74\x60\x82\x39\x99\x18\x7a\x9f\x68\x95\x14\x0b\x9e\x8a\xca\xda\xe4\xd0\xe2\xd5\xe5\xb9\x42\x96\x2d\x86\x8a\x42\x67\x17\x54\x4e\x1d\x52\x39\xb5\xbf\xb5\x53\x9f\x71\x4c\x41\x54\x76\x0c\x98\xbc\xcb\x80\x43\xbe\xe2\xf4\x62\x67\x2b\xeb\x6f\xed\x0b\xef\x0e\xb7\x16\x4f\xbf\x82\xa0\xcf\x39\x9d\xad\xfd\x65\x53\xf6\x2c\x6a\x7d\x0e\xb9\x5f\xe7\x66\xfa\x65\x07\xf5\x9f\x7e\x05\x8b\xb4\x76\xb6\x86\x77\x87\xfb\x5a\x87\x71\x45\xc5\x0e\xc0\x94\x99\xa3\x98\x00\x20\x1d\xf0\x89\x31\x25\x5b\x61\x06\x46\x19\xa8\x11\x75\x55\x45\x0f\xed\xe6\xe6\xbd\xb7\x77\xef\x7b\x7b\xb9\x01\x9d\x65\x3a\xa2\xea\xef\x81\x8c\xbc\x2a\xc7\x90\x5b\x25\x67\xca\x17\x8f\xea\x93\xb9\xbe\xbd\x7a\x52\x36\xef\x9e\x4b\x87\x8c\x74\x9c\x7a\xe9\x3d\xdb\xa6\xcc\x99\x33\x65\xdb\x51\x95\x46\x6c\x16\x46\x75\xcb\x26\x2f\xb7\x08\x20\x2e\x1d\xc8\xa4\x0b\x0a\x15\xba\xf8\x82\x4c\xd3\x48\x17\xd0\xbc\xc1\x66\x0a\x06\x8c\x97\xdf\x27\xfa\x63\x4a\x3c\xc6\x4b\xd9\x6e\x4a\x77\x09\xb9\x6c\x07\xa5\x92\x22\xf3\xfb\x9a\xb9\x4c\xc0\xef\x93\xf4\x48\x31\x2e\xb2\x7f\xff\xa7\xe8\xcf\x4f\x96\x95\x73\x86\x7e\xca\x82\x33\x27\x67\x14\xfb\xbb\x54\xdf\x93\xb3\x70\x2f\x46\x77\x4e\x70\x9d\xdd\xe4\x73\xc9\xb7\xba\x44\xea\xd6\x8a\xbd\xda\x5f\x52\xfc\x4d\x14\xb4\xf8\xad\x0e\xa1\xeb\x4c\xd2\xba\x42\xab\xc2\xd3\x94\x5e\x8e\xd8\xd4\xff\x9c\x6a\x49\x72\x8b\xb8\x5f\x68\x5d\x3c\x2b\x0f\x5d\x7d\xba\x54\x67\x93\x53\x2d\x6c\x35\x3b\xe0\x94\xb4\xc8\x42\xed\x4b\x17\xc4\x7e\x3b\xf5\x24\xbb\xab\x49\x54\x64\xc1\xc3\xbb\x9d\xd4\x16\x0f\x0b\x4c\x12\x6d\x76\x8b\xfb\x81\xef\x73\x6c\xaa\xf6\x6e\x43\xa0\xc5\x6b\xb5\xc8\x29\xab\xd7\x67\x71\x56\xe4\x68\x63\xed\xf2\xa3\x0d\x17\x02\xc9\x40\x26\xe2\xc9\xa6\x3a\xf8\x78\x4c\xf2\x89\x7e\x9f\xd8\x4c\x9c\xc1\x3b\xe6\xb2\x3a\x5b\x29\xf9\x8c\x36\xfb\x8c\x81\xdf\xc5\x4f\xa7\x9c\x3b\xd5\xc1\x4f\x22\x5d\x44\x0b\x64\xd2\xcd\x9c\xdf\xe7\xe4\xa4\x66\xd2\x3f\x71\x03\x33\xac\x6d\xfe\x4c\xda\x3c\xa1\xf1\xb4\x99\x17\xcc\x9b\x3a\x2f\x4c\x8c\x2c\xe2\xc4\x53\xcf\xdc\xb2\x22\x33\x75\xe5\x86\x99\xe9\x45\x16\x2a\xbf\xc9\x5c\xdb\x13\x52\x9d\x28\x50\x80\x4f\xe4\x3a\x32\x02\xbf\x82\xde\xbc\x29\xb8\x34\x38\xfb\x73\xd7\x2e\xeb\x8c\x9e\xb4\xb8\x2b\x77\xef\x8b\xb3\x37\x7e\x75\xcf\xb2\xf6\x7d\xed\x97\x6a\x97\xb9\x22\x74\xfa\x95\x33\xdb\xa7\x47\x3d\xbc\x2d\x77\x20\x6b\xd9\x34\xff\x7c\xf6\xaa\x14\xea\xde\xb0\x78\xf6\x25\xd3\xc2\x8e\xf4\x4f\x33\x8d\x97\x86\x3a\x86\xd6\x2f\xe7\xeb\x5d\xf6\xe6\x64\x78\x92\x3f\x2d\x70\xaf\xb6\x59\x1c\x56\x81\xa7\xb3\x98\x4c\xa1\xa9\x8b\xaf\xeb\xc9\x9e\x73\xf2\xd4\x48\x7d\xfc\xb9\xbb\x57\x7e\xf5\xa2\xd3\xc2\x62\xc0\x94\x4d\x79\x7d\x7c\x4e\x05\xfc\xfa\x9c\x96\x2f\xe4\x43\x94\xca\x75\xb0\x54\x41\x17\x4d\xbb\xa8\x20\x4a\x4e\x92\x9c\x9c\x24\x32\xc9\xc9\xb5\x50\x20\x28\x4a\x31\x7d\xf2\x8e\xeb\xfd\xec\x09\x9c\x7e\x4a\x63\xd8\x41\x5b\x2e\xa5\xfa\x19\x0b\x65\x39\xfa\xf8\x75\x53\x27\xaf\xfa\x42\x58\x70\x36\xdf\x91\xb4\xd8\x45\x2b\x6b\xbc\xc6\xc3\x02\x5e\x27\x91\x67\x0f\xe7\xa8\x6b\xab\x6b\xda\x10\xbe\x75\x56\xe6\xa9\xeb\x3f\x25\xc9\xb2\x33\x3e\x53\x62\x59\x56\x17\x6f\x70\xd4\x09\xdc\xc5\xcc\x2a\x08\x56\x96\x4a\xdb\x92\x2e\x79\x52\x74\xaa\x63\x57\xf9\xf7\x8b\xad\x2b\xce\xfc\x94\xcb\xcb\x37\xb6\x17\x38\x1f\xf3\x8e\xd2\xeb\x11\x41\x45\x23\xae\x03\x92\xe9\x80\xcb\xdc\x0d\xd3\xc7\x72\x3c\xa6\x74\x9b\x3b\x61\x62\x1b\x79\x48\x97\x01\x74\x59\x40\x1f\x46\x5d\xac\x9b\xd2\x01\x83\x44\x45\x49\x49\x75\xb0\x54\x07\xa7\xb7\x43\x9f\x8b\x83\x3e\xaf\xdf\x27\x56\x09\xdc\x45\x62\x42\xa7\x61\x65\x06\xe9\x18\xf1\x64\x99\x2e\xd0\xe9\x74\x6e\x08\xba\x4e\x26\x29\x29\x8f\xf8\x72\xd4\xeb\xbb\xde\x37\xd5\x77\xbd\xcf\x1b\x5d\xb4\xa8\xd6\xf3\xd1\x2f\xf2\xf6\x1f\xb7\xef\x6b\x4f\xdc\x91\xa0\xa4\xd8\x5c\xe7\x77\x5a\x26\xf2\x3e\x9e\x09\xa9\xa6\x86\x26\xce\xed\x20\xd1\x2e\x4b\x4d\xcc\xf3\xe9\xf4\xc2\x88\x95\x78\x41\xb0\xb5\xee\x49\x08\x5c\xac\x57\x7b\xf3\x94\xf4\x4f\x33\x9c\xe7\xdc\xb5\xf5\xb2\x48\x8c\xe7\xea\xbe\x18\xdd\xec\x93\x9b\xa3\xa1\x89\x4e\x35\x19\x7a\x30\x14\x7a\x30\x94\xe4\x51\x75\x0d\x81\x1f\x6e\x14\x78\x22\x12\x1c\x75\x44\xeb\x07\x16\x35\x39\xf9\xf6\xc5\xd6\x85\xa7\x91\xc5\xca\x31\x22\x9e\x3f\xa3\xb0\xbc\xfc\xc4\x03\xee\xcb\xe7\x46\xfd\x6d\xee\x56\x9b\xd3\x45\xcc\xe7\xcd\x90\xb5\x31\x12\x72\x4e\xa4\x4f\xad\xa2\x5d\xab\x36\xb2\xc6\x60\xd8\xc7\xdb\xeb\x9d\x8e\x4d\x17\xb3\x90\x97\x6e\x30\x71\xcc\x19\xfa\x80\x0b\x71\x37\x20\x57\xf0\x98\xe0\x83\x81\x71\x48\xcc\x29\x3a\x52\x0c\x24\xb6\x50\xce\xa7\x0f\x83\x13\xe0\xb1\x8b\x65\x95\x5c\xd6\x30\x28\x1b\x8b\x49\x4a\x37\x33\x63\xc3\x84\x8b\xc7\x3a\x28\x9b\xcf\x45\x7d\x01\x9f\x93\x74\xa1\x2e\xa5\x64\x0b\x5d\x5c\x26\xdd\x4c\x3e\xd1\x1f\xcd\x2a\xd9\x2e\x3a\xc3\xc4\xed\x6c\xba\x90\xb0\x29\x1a\xac\x45\xac\xd3\xe6\x11\x66\x34\x5f\xbf\x68\xed\x44\x2b\x11\xa3\xe3\xe2\x55\xb2\x72\x24\xe8\x18\xe3\xeb\xbe\x38\xe1\x7d\xb7\x89\x5b\xa1\xd9\x3e\xbd\x50\xe4\x43\x21\xbe\x58\x98\x6e\x77\xb8\x04\x6e\x08\x9c\xe0\x72\x8c\x0f\xe5\xf5\x50\xe1\x86\x46\x81\x67\xc4\x53\xa4\x06\xe5\x0b\x66\x93\x43\x64\x8c\x17\xce\x28\xec\xce\x16\x9e\x7b\x70\xee\xf1\x51\xee\xde\xf0\x8d\xcf\x3f\xc6\x49\x4d\x16\x69\xfe\xdc\x33\xf2\x82\xbd\xb1\xce\xbe\x69\xb5\x81\xf3\x23\xc3\xa9\xf6\x3c\xe7\xef\xf4\x73\xf9\xf6\x94\x3f\xd1\x12\x67\x2c\xde\x92\xf0\x1f\x37\xd0\x3c\x58\x36\x56\xa7\x61\xec\xae\xfd\x6f\xf6\xd8\x25\x28\xa1\x8f\x0c\x6b\x11\xb1\x62\xd9\x72\xd4\xb0\x2e\x11\x0c\xe5\xaa\x12\x3a\x62\xf8\x44\x54\xe2\x8c\x94\xbc\x1a\x52\x4a\xa3\xc6\x26\x17\x7d\x82\xf3\xff\x11\xdc\xa6\x79\x22\xa7\x56\xe0\x36\x7c\x42\xd5\x5a\xc7\xf0\xb1\xff\x0b\x70\x8f\xb7\x51\xf8\x24\xff\x58\xb8\x6b\xb1\x5d\x8b\xeb\xff\x31\xa6\xff\x9f\xc0\xfc\xc9\xee\x7f\x10\xe6\x8f\xd1\xd5\x8d\xdf\x3d\xf6\x7c\x82\xff\x78\x74\xf3\x71\xf1\x9f\xd4\x76\x82\xec\x30\x58\xdb\x13\xbc\x44\xc8\x8e\x23\x86\x47\x28\x3a\xe4\x23\x38\x51\xcc\x89\xdc\x03\x23\xa5\xd1\x55\xc7\x73\x0e\xfd\x75\xc4\xc9\x1f\x37\xf4\xf8\xd9\xcc\xc3\xaa\xe3\x71\x6a\xea\xa1\x63\x29\x52\xb2\xa6\xc5\xed\x3f\x8a\x8d\x63\xb0\xa3\xca\x0e\xa7\x55\x1b\xb0\x5a\x29\x62\x75\x3a\x64\x41\x95\x1d\x1f\x19\x2d\x14\x0d\x50\x8e\x1a\x6f\xbe\x38\xde\x3d\x9a\x86\x1b\x28\x97\x1c\xb2\x9e\x3d\xac\xbf\x3e\xb9\x65\xb5\x8d\x3c\x6e\x1b\x2b\xba\x7f\x53\x9f\x93\x0e\x5a\xff\xd7\x6d\xec\xd3\x1b\x68\x68\x06\x9d\x56\x8a\x08\x7b\xff\xd1\x26\xb2\x97\xc2\x7a\x09\xa6\xb9\x88\x55\x1b\xd0\xac\xff\x40\x13\x4d\x3d\xa3\x61\x3f\xdc\x62\xf4\x9f\x21\x45\x55\xdb\x54\x15\xae\x9b\x88\x0c\x2d\x93\x84\x94\xc3\xde\xe8\xd5\xd6\xed\xdd\x54\x2e\x6e\xda\xbb\x77\x13\x2b\x6d\xda\x4b\x77\x79\x1b\xed\x8e\x14\xdf\x7f\xb4\x34\xd1\x23\xc8\x74\xd7\xa3\xd5\x98\xbd\x9b\x1e\xa1\x9d\xb2\xe0\x19\x91\xa7\x24\x53\x1e\x70\xa2\x19\x1d\x3a\x26\x75\xf9\x24\x9f\x26\x4f\x34\x47\x41\x2b\xd5\xa8\xb4\x73\x9e\xac\x12\x1c\xa7\xd6\x66\xea\xfa\xfe\xf5\xeb\xfb\xf9\xf5\x47\x54\x2a\xf6\x33\x30\x7c\x64\xb4\x43\xd4\x31\x71\x57\xad\x15\x24\xef\xd6\x13\xae\x2f\x97\xb4\x62\xc9\x48\x4a\x11\xd9\x71\xd4\x40\x18\x5f\x72\xc8\x91\xa3\x86\x2a\x9b\x2f\x55\x6c\x16\x87\x55\xe1\x1d\x61\x0d\x44\xf8\xd0\x80\x24\x10\x2d\xa4\x24\x7f\xc6\x4f\xd9\x78\x4c\x22\xd1\xef\xcb\xa4\x75\xd1\xdb\x4a\x51\x0f\xf9\x5c\x44\x85\x7c\x46\xe7\x04\x69\xcd\x79\xef\x9c\xa7\xb2\xab\x03\x36\xa9\xfc\x07\x29\x60\x93\x58\xb3\x94\xa7\xfe\xa1\x92\xd6\x27\xbc\x93\x7c\x54\xeb\x7b\x34\x91\xcf\x29\xef\x24\xcf\x7b\xe7\xbc\x35\x2a\xd7\x1f\xd0\x53\xd9\x02\x7a\xaa\x9f\x6a\x7d\x43\x25\xea\x67\x03\xb9\xe4\xa3\xd4\xff\x88\xa2\xfc\x25\x55\xe1\x3f\x79\xd3\xf6\x23\x38\x56\xd3\xe1\xa4\x98\x92\x22\xc5\x50\x7c\x73\xa6\x91\x06\xdd\x13\xd5\x76\xb9\xbb\xe7\x76\xbb\xb4\xbb\xa2\xd4\x4e\x7b\xa8\x9d\xab\xd8\x56\x60\xdd\xec\xa1\x23\x51\x45\x89\x72\xe2\xec\x75\x07\xa8\x5d\x3b\x30\xc6\xae\x44\x06\x92\x9e\x98\xb1\x57\x35\x66\x83\x1a\xbb\x8e\xec\xdc\x79\x84\xdb\x35\x6e\x57\xaa\x8f\x2f\x9a\x3b\x50\xec\xd0\xb1\x7b\x87\xa6\xbe\x1e\x42\x09\x7e\x43\xff\x9a\x4d\x75\x70\x29\x25\x66\xb0\xf5\x7e\x5f\x20\x9d\x4f\xfa\x10\x41\x4e\x67\xb6\x0a\x5d\x94\x0e\x04\x9b\xb9\x60\x80\xc1\x47\x4d\x81\xb0\xc4\xc7\x78\x29\x1c\x68\x22\x5f\xcf\xa5\x3d\x0c\xda\x01\x6d\x89\x76\xe0\x0c\xf1\x8a\x73\x2f\x0b\x5b\xd3\xd9\x8c\x25\x7c\xd9\xb9\x57\x88\x67\x90\x9a\x88\x52\x5b\xb4\x10\x74\xbb\x83\x85\x68\x1b\x45\x13\xb9\x9e\x9e\x27\x0f\x68\x07\xa8\xfd\xc0\x9d\x9f\xb5\x3e\x74\xdb\xaf\xcf\x6f\x8e\xc5\x9a\xcf\xff\xf5\x6d\x0f\x59\x6f\x30\xc7\xab\xf8\xa1\xa0\x42\x84\x13\x27\xa3\x0b\x73\x01\x32\x7b\x13\x8a\x44\x62\xa0\x40\xf2\x58\xd2\x0e\x06\x82\x3a\xa3\x9f\x1a\xb3\xa1\x32\x83\xb2\xdd\x94\x0f\x70\x46\x97\x4b\x54\x30\x6d\xe0\xb8\xcd\x1b\x76\x6f\xe8\x63\x88\x78\xb4\x07\x3d\x11\x0f\x2d\x3f\x63\xef\xa6\x21\x83\xca\xb9\x62\x77\xde\xc5\x71\xf6\x29\x4e\x6f\x30\x30\x64\x90\x21\x57\x9c\xb9\xdc\x5a\x74\xb5\xf6\x51\xa4\xdc\xa7\x0d\xf0\xcb\x96\x69\x03\xcb\xc2\x8b\xc2\xbb\xc3\xd4\xb7\x61\xf7\x86\xce\x3e\x56\x1a\x29\xa7\xfc\xf3\x67\xcd\x52\x36\xed\x6d\x90\xdc\x1e\xfb\x14\xa7\x28\x9a\x86\x20\xcb\x67\x5e\xef\xb0\x16\x5d\x6e\xf6\xa2\x36\x50\xee\xa3\x08\x0b\x2f\xa3\xc8\xb2\x70\x78\x77\x78\xd1\x08\xfe\x8d\x7d\xf2\x36\x2c\x1d\x6f\x6b\x3b\x25\x6d\xb2\xd3\xfa\xf2\x54\xdb\x32\x5d\x16\x0b\x06\x64\x73\xff\x72\x06\xc5\x23\x92\x28\x07\x8c\x51\xdf\xc1\xe7\xb2\x5d\xd2\x34\xca\x65\x0d\xeb\x20\x0a\xf8\x04\xb5\xda\x44\x0c\x3b\xe4\xd0\x82\x4e\x9b\xb8\xbe\xda\x3a\x6f\x38\xe4\x96\xfd\xef\x6a\xaa\x31\xfa\xfb\xb5\x67\xae\xda\x74\x12\x17\xb4\xf0\x6e\x9b\x2d\x70\xf2\xc4\xb8\xe4\x8f\x4f\x5b\x78\xf9\xad\x4f\x5e\xda\x9f\x72\xd8\x43\x32\xa9\x32\x8b\x6b\xe5\x6a\x3b\x65\x47\xa3\x10\x8a\xf1\xd5\x56\xbe\x2a\xdb\x1c\xf5\x6e\x8b\x95\xde\xd0\x54\x59\xf0\x4c\x2c\xdd\x74\x8b\xb6\x2f\x58\xc7\x1c\xce\xd8\xc5\x7d\x5b\x3b\xa7\x2c\xee\x5b\x74\xd6\x29\x53\x53\x01\x63\x82\xd1\x54\x39\x5b\x6d\xfb\x0d\x82\x8a\x49\x86\xe5\xa0\xe7\x78\xdd\xaa\x37\xf1\xd8\x8e\xd5\x67\x32\xd9\xdc\x8f\x1f\x6b\xe5\x38\xda\xdc\x91\x1e\xb5\x39\x38\x71\x6c\x9f\xda\x1c\xa2\xe8\xfb\xf3\xd0\x2f\xeb\x67\xd6\x6b\x67\xd6\xd7\x5f\x56\x3f\xb3\x9e\x24\xf6\xf9\xfa\x99\xf5\x97\xd5\xb3\xe5\xda\xf7\xc7\x76\xa5\x8d\x8d\x74\xa5\xe6\xb0\x16\x6d\x9c\x85\x0e\x0c\xfd\xb2\xbe\x9e\x1e\x37\x32\xd4\x6b\x1f\xb1\xcf\x1b\x85\x98\xe7\x66\x30\x0c\x09\x22\x70\x6a\x65\x9d\x31\x54\x4d\x9e\x4c\x3a\x50\x35\x20\x30\x54\x4b\x51\xbf\x4f\xac\xae\xb2\xfa\xe4\x6c\xe8\xa4\xaa\xdb\xf4\x86\x8d\x52\x34\x97\xd5\x3d\x12\xe4\x61\xc8\x59\x45\x53\xd5\x90\x62\x38\xf5\x97\x12\x52\x35\x55\x31\x9c\x32\xc1\xd8\x28\xd0\xa3\x75\xa7\xfe\x52\x42\x2a\xe9\xd1\x04\x76\xef\x3f\x96\x5e\x1e\x5b\x5b\x8d\x1e\xa0\x09\xa0\xbc\xa1\x87\x4a\x91\x92\x1a\x67\x6b\xe5\xf7\xe4\x0b\xdc\x2b\x72\x28\x24\x97\xa7\x5a\xf9\x1a\x6b\x79\xab\x70\x95\x6c\x0f\x1d\x29\x86\xec\x32\x7b\xce\x6a\x2b\x2f\xad\xf2\xdc\x4a\xa8\xbc\xd4\x66\xad\x39\x1f\xd2\x36\xbe\xfc\x13\x54\x63\x24\xca\x17\xc4\x91\xda\x8e\xad\x93\x3d\x27\x87\x8e\xa9\x79\xea\x09\x40\x60\xcf\xc9\xf6\x50\x79\xaa\x01\xcb\x96\x8a\xbe\xab\xe1\x38\xb0\x64\x47\x6a\x3e\xab\xb6\x66\x59\xfe\x98\xda\xe4\xac\x3c\x5a\xbc\xd1\xd6\x6b\x85\x1b\x84\xad\xa8\x03\xac\x24\x1a\xcd\x32\xc6\xe8\xea\x23\x2f\x07\xa3\xd1\xa0\x30\x39\xc8\x2e\x2c\x37\x3b\x7c\x21\xa1\x14\xf2\x39\xca\xcd\x8e\x04\xc6\xd8\x14\xba\x2a\x2b\xfc\x98\x45\x55\x18\x7f\xf4\x07\x15\xcb\x7f\xe3\x14\xc0\x90\x5a\xeb\x13\x8a\xa3\x52\x4f\xad\x04\xa4\x54\x69\xb7\x5a\xcf\x31\xb5\x88\x63\x24\xa6\x31\xe5\x8c\xe6\x15\x4d\xdc\x05\x47\x9a\x16\xac\xb4\x50\x32\x5a\x2b\x4a\x27\xe9\xa8\x63\xcf\xe9\xa8\x63\xcf\xc9\x3a\xfa\x42\xbc\x55\xc7\x9c\x50\x0a\xd9\x75\x9c\xda\xd8\x73\x86\x43\xce\xea\x2f\x7b\x88\x3d\x67\xb3\x8e\x94\x5f\xa5\x93\x63\xca\x0f\x7a\xc6\x6e\x99\xea\x55\x1d\xaf\xc6\xb1\x64\x72\xe2\xda\xad\x36\xf6\xe8\x28\x82\xd8\xa3\x36\x6b\x2d\x30\x63\xc6\xc4\x58\x58\xc6\x03\x31\x52\x7b\x6d\xbd\x63\x6b\x1c\x57\x91\xd1\xdf\x04\x88\x24\x88\xa8\x43\x23\x20\x9b\x93\x82\xd1\x1b\x54\xd3\x23\x7a\x3d\xce\x51\x1a\xd3\x69\x4f\x78\xae\xa6\x5b\xd8\x49\x55\x14\x87\xca\x7f\x32\x6d\xa1\x94\xd0\x30\x42\x95\xfe\xba\x77\xf8\x5e\xfe\x51\xe1\x4f\xf0\x01\x56\x16\x30\xad\xc7\x2b\xf3\x91\x3e\x91\xf2\x77\x95\xdf\x65\xb2\x2c\x3f\xaa\xf7\x44\x48\x96\xd9\x9f\xe4\xac\xfc\xa8\xcc\xbf\x52\x7e\xb7\xfc\xae\xe1\x34\x83\xd8\x9f\x8c\x34\x66\x99\x4b\x87\xef\xe5\x2f\xaa\x94\x79\x8c\x21\xba\x5e\xe8\x59\xe5\x50\x25\xaf\x5c\x7e\xd7\x2c\x9c\xfd\x49\x66\x77\xe9\x35\x18\x1e\x99\xc9\x66\x02\x3d\xe1\x18\xda\x8f\x63\x12\x40\xb9\xac\x12\x8f\x7a\xcc\x23\x3c\x7e\x4f\xd4\x3c\xc7\x93\x89\x7a\xcc\xc3\x3c\x39\x4f\x34\x3d\xd6\x7a\xa7\xa4\x37\xd9\xc0\xfb\xb0\xd1\x7e\x32\x3d\x86\x61\x58\x71\xbc\xf9\x4e\xb1\x12\x73\x6c\x1e\x6a\x3b\xd6\x96\xa9\xc6\x9e\xa8\x02\x57\x15\x9a\x63\x61\xa8\x39\x0b\x74\xdc\x5a\x2b\x32\xef\xf8\x5a\x6a\xdb\xdf\x66\xec\x9d\x66\x27\x51\x21\x9f\xcb\x4e\x22\x25\x1e\x73\x19\xca\x32\x97\xce\xdf\xb6\x90\x64\xbc\x03\x99\x74\xb7\xa1\xdb\xec\xa6\xb1\x30\x5c\x27\x3f\xf9\xa4\x2c\x2f\x95\x1b\x43\xba\x23\xd4\x28\x2f\x95\x8f\x0d\xa1\x9b\xc6\xc1\x46\xf7\x7f\x5c\xf2\x4a\x08\xbd\x74\x42\xdc\x04\x0d\x3b\x2f\x1d\xda\x98\x44\x29\xc5\x84\x35\xa8\x43\x59\xa0\x2e\xaa\x81\x4f\xe0\xbd\xe7\xc9\x59\x59\x5b\xfd\x07\x39\x2b\x9f\xe7\xf5\xd2\xa5\x7a\x15\xac\xc5\x3b\x34\xde\xae\x32\x16\xf6\x2e\x95\x65\xed\x92\x3f\xc8\xf2\x52\x6f\xb8\xd1\xab\xdd\x23\xeb\xe9\xe6\x8f\x83\xa1\xd6\xde\x6b\x2a\x66\x03\xc9\xf1\xe7\xc6\xb2\x1d\x14\x8f\x49\xa2\x81\xb3\x8a\x61\x88\xdf\x27\x4a\x4e\xaa\xa6\xc8\x65\xf3\x85\x2e\x3e\x31\xce\x04\x74\xc4\x66\x1c\x97\x3f\x7a\xce\x5f\x55\x57\x70\xab\x64\x77\x5b\x73\xd1\x58\x76\x72\x4f\xeb\xe4\xee\x4b\x8c\xc8\xb6\x68\x24\x36\xb5\xa5\x81\xd4\x71\xd0\xf7\x8f\x18\x97\xb3\xc7\x97\xdc\x73\xe6\xbf\xd7\x7b\x57\x8a\xf6\x59\xf5\xf5\xd9\xa8\xd2\x11\x08\x6f\x3c\x35\xa1\x47\xcb\x33\x64\xaf\x7f\xca\xa4\xf9\x33\xc6\x13\xc3\x68\x9b\x74\xd9\x6b\x6a\xb5\x4d\x9e\x51\xd2\x33\xf4\xdc\x23\x44\xc8\x8d\x6b\xf2\x18\x8b\x3f\x78\x9d\x7d\x55\x83\xd6\x3e\xd3\x5a\xb9\xe4\xf4\xd6\x34\x90\x1d\x03\x7c\xbf\xd3\xcb\xa0\xc7\xf6\x3b\xbd\x5a\xc9\xf8\x78\xb9\xdb\xfb\x2b\x21\xde\xef\x8d\x87\x77\x94\x0e\x26\x19\x67\x7f\x46\xce\x82\x74\x50\x6a\x44\xe7\xe2\x24\x29\xa3\x33\x40\xba\xbf\x99\x82\x23\xc7\x44\xba\xc8\xd4\xcb\x38\x49\x1a\x49\xdb\x41\xa9\x91\x32\xba\xa8\x30\x92\xb6\x99\x82\x99\x74\x80\xff\xfa\x3a\x7d\x20\xad\x8b\x3c\xb0\xd6\x18\x4e\x6b\x1f\x88\x8c\x0f\xa0\xab\x94\xd0\x1d\xc9\x77\x1e\x30\xbc\x0f\xbc\x93\xbc\x43\x8f\x1f\x17\xc0\x70\xa2\xdc\x23\x01\xd4\x7e\xe2\xec\x95\x80\xb1\x76\x99\x71\xc3\x8a\x1d\xe6\xc1\x1f\xc9\x9c\x18\xbb\x29\x65\x4e\x8c\x2d\x55\xe9\xc4\x45\xc1\x80\x2f\x7f\x22\x3b\xc4\x79\x3b\x6d\x21\xdb\x2d\xb7\xd8\x42\xb6\x9d\x36\xfd\x6b\x1b\xe7\x7f\xf1\xe3\x2c\x13\xe9\x27\xc7\xcf\x34\xe2\x6f\xf8\x78\xf3\xe4\x63\x6d\xa7\xad\x35\xdc\x77\x0b\x55\x16\x8d\x13\x1a\x51\xde\xa5\x2d\xd5\x87\xf7\xeb\xb2\x7c\x91\x9c\x95\xef\x22\x7d\x92\xbf\x48\xde\xf2\xb1\xc6\x94\xaf\x68\x4b\x65\x99\x14\x23\xa5\x91\x45\xcf\x7b\xe4\xef\x84\xf3\x73\xb0\xc2\x6b\x9c\x0b\xce\xa6\xc8\xd8\xb3\x13\x0c\xbb\x4a\xf2\xfb\xe0\xae\x9c\x91\xa9\x9c\xd8\x11\x22\xe7\x94\x9d\xb7\xf4\x5f\xfe\x93\x9d\x67\x0f\x35\xb0\xbf\x7e\xfe\x91\x5d\x47\x76\x0a\x91\x2d\x2f\x6a\x7f\xd4\x9e\xd7\xfe\xf8\xe2\x96\x2d\x2f\x52\x13\x75\x52\xd3\x8b\xec\xa6\x07\x6e\x2e\xbb\xce\x3d\x67\xe7\xcf\xf6\xb3\xc3\xe7\xed\x1c\xda\xf5\x20\x75\x6b\xcf\x69\x7f\x30\x2c\x2c\x9b\x69\x2a\x35\xe9\x2e\x7d\x1d\x2c\x0e\xe7\x44\x08\x3d\x88\x54\xcf\x0e\x19\xbd\x6b\xea\xd5\x72\xa6\x62\xcd\x38\x92\x45\x06\x63\x75\x4a\xb6\x5c\xa4\xa4\xa2\xf4\x24\x73\xd9\x54\x79\x63\x32\xc9\x6e\x53\x72\x59\xa5\x47\x51\xb4\xdf\xb0\x52\xf6\x14\xa6\xaa\xb9\x1e\xed\xf5\xc4\xda\x44\x6f\x32\xc9\xb6\x1b\xc6\x0a\xb7\x2a\xca\x7c\xe5\x52\x45\xfb\x4d\x8f\xc9\x8f\xe4\x84\x52\xa5\x3e\x53\xb7\x65\x2c\xbd\x34\xa2\xa3\x32\x3b\xca\x90\x08\x85\x52\xb2\xbc\x31\x95\xcd\xa4\x7a\x14\x85\x92\xe5\x62\xf6\x94\x53\xb2\xac\xa4\xfd\x46\x51\x7a\x94\x6c\x4e\x61\xb7\x25\x59\x31\x9f\xd4\xc1\xe8\x51\x2e\x55\x28\xd9\x93\x53\x73\x3d\xa4\x24\xd6\x26\x7a\x14\xa5\xbc\x51\x9f\xd0\x91\x1b\x56\xc5\x1e\xa1\x88\xa8\x61\xd7\x66\x36\x6c\x84\xeb\x31\x17\xfe\x4a\x33\x75\xc6\xa5\x27\xd9\xa3\xe4\xf2\x09\xed\x75\xa3\x28\xa3\x21\x3d\x8a\xc2\x6e\x8b\x17\xf2\x49\xbd\xba\xdc\xc7\xc0\xa2\xc3\x6a\xf2\x16\xb9\xe1\x27\xc5\x1e\x41\xad\x9e\xf5\xae\x22\xb3\xd2\xac\x11\xde\xab\x82\x5b\xb1\xc7\x68\x65\x2e\x59\xde\xa8\x28\xf3\x75\x07\x29\xbd\x59\x35\xdb\x4b\x8a\x8e\xbf\x9e\x24\x2b\xe5\x92\xe5\x0d\x3a\x3e\x13\xf9\x9c\xd2\x93\x4c\x6a\xaf\xb3\x52\xb6\xb7\x57\xef\x0b\x25\x99\xec\x49\x8d\xf2\x9c\x25\xe3\x4e\x30\x53\x96\xcb\x79\xe2\x31\xa7\xe0\xf7\x05\x7d\x95\xb3\xe6\x1d\x2c\xc5\x72\xd9\x82\x37\x9a\xf1\x54\xe5\x35\x4d\x97\xa0\x06\x56\x7c\xf9\x4b\x57\xac\xe8\x8a\x0b\x82\xc7\xe5\xb6\x4b\x76\x17\x77\x43\xee\x41\xf6\x93\x01\x25\x2b\x33\x70\xf7\x66\xf5\x54\x3a\x6b\x61\x6f\xc9\x7f\x6a\x63\xff\xaa\xc2\x2c\x31\x6e\x75\xf9\x3c\xd6\x50\x4c\xa2\xa6\x47\x7f\x7c\x33\xdd\xa5\x73\x22\xb2\x36\x86\x07\x08\xea\x3c\x90\x0e\x49\x30\x30\xca\x9d\x57\x87\x9f\x61\xa7\x36\x89\xaa\x7c\x97\x3e\xbd\x98\x4a\xb7\xbf\xda\xb4\x27\x76\xc8\xa6\x31\xad\x92\x95\x77\x50\xaf\x2d\x64\xbb\x92\x0b\xea\x6e\xed\x09\xdd\x6d\xb3\x51\xef\x8e\x8a\x05\x2d\xbd\x1b\x32\xd2\x8f\x18\xe5\xea\xe9\x6d\x57\x72\xf3\x0c\x5b\x5c\x3d\x83\xed\x4a\x5b\xc8\xc8\x90\x55\x2a\x36\x7c\x8e\xe1\x2f\x08\x7f\x15\xae\x32\xe1\x3b\x11\x1c\x27\x82\xdb\xb0\x7b\x3b\x0e\x20\x27\x80\x9b\x15\x8f\x0b\x08\xbb\xeb\xb8\x60\xa3\x6a\x87\x29\x98\x67\x14\x2b\xe3\x71\x84\x58\x47\x46\xc8\x08\x01\xe9\x12\x95\xda\xd9\xaa\xf5\x19\xe7\x37\xb5\x3e\xe3\xb0\x40\xbf\xe1\xa1\xfe\xd6\x4e\x2e\x72\xbc\x50\x23\x7d\xa5\x2e\x06\x41\xe5\x4c\x19\x6a\x9c\x9e\x58\x2f\xf7\xa8\x61\xe6\xca\x97\x2a\x25\x55\x0f\x89\x9a\xb2\xa7\x2e\x3f\xe5\x8c\x33\x31\x2e\x72\x52\x6a\xf4\xdc\x9b\x20\x9a\x47\x77\x4e\xa2\x0e\xea\xa6\x2e\x0a\x0a\x23\xf0\x26\xf3\x01\x9d\xde\x25\x41\xf8\x69\x47\x63\xa8\x18\xba\xb8\x43\xfb\xc0\xa0\x74\xed\x83\x8e\x8b\x43\xc5\x50\x63\x07\xd9\xb4\x0f\x2a\x51\x64\x33\x07\x81\xad\x12\xa5\x7d\x40\x7f\x0a\x5d\xdc\x71\x59\x47\x63\xe8\x4b\xda\x8b\xc6\x51\xea\xcc\x97\x42\x8d\x1d\x97\x75\x5c\x1c\xba\xf7\xde\x6a\x0c\x65\x8c\xd3\xd9\x2f\x8e\xc4\xd4\xae\x07\xba\x8c\x72\x92\x61\xc5\xe9\xad\xce\xf8\xe3\xcf\xe0\x73\x72\x36\xa5\x07\x48\xa2\x5f\x36\x43\xd8\x24\x73\xca\xae\x4e\xf9\xec\x9b\x5e\x47\xc9\xe1\xf3\x39\x4a\x0e\x2f\xf3\xda\x6c\xce\x37\x9c\x36\x9b\xc7\xe7\x7c\xda\x29\x0b\xe3\xf9\x90\xa3\xff\xf5\xac\x53\xf6\x39\x9e\x75\xf8\x64\xba\x88\xad\xb3\x8b\x16\x8b\x68\x2f\xdf\x65\x73\xb9\xaa\x7b\x5b\x22\x84\x22\x1c\x08\xa0\x05\xf3\x75\x2e\xc9\x93\x8b\xfa\x3d\xfe\x0a\xdf\x97\x31\x76\x98\x7d\x81\x44\xd6\x60\x9e\x33\x69\xf3\xdc\x58\xed\x99\x30\x53\xc2\x32\x6e\x3a\x31\x56\xe7\x8c\x79\xf5\x49\x3a\xc0\xf5\x6b\xa5\x44\xb8\x14\x4e\x68\x9d\x3f\xb8\x3e\xd4\xd6\xda\xd9\xc9\x5e\xeb\x6c\x6d\x0b\x5d\xf7\xfd\x56\xda\xe7\x75\xf6\x75\xb6\x1e\x2d\xb5\x76\x9a\xdc\xd4\x53\xe7\xdf\x74\xd3\xf9\x6b\x66\xa8\xea\x8c\x35\xba\x8b\x9e\x72\x7a\x9f\xe8\xa4\x03\xa5\x92\xd6\xde\xd9\xd0\xd8\xc8\xad\x7a\xa0\xa5\x73\x51\x67\xe7\xa2\xce\x96\x07\xfa\x75\x36\xac\x4a\x53\xe6\x89\xc3\x9b\xbe\x73\xd3\x82\x47\x1e\x59\x70\xd3\x77\x6e\xf2\x9a\x7a\x32\xc9\xbc\xc7\x61\xa1\xa1\x57\x8e\xc7\x78\xd1\xd0\xcf\x66\xd2\x86\xd1\x59\x22\x93\x26\x9f\x24\xc2\xd4\x01\x52\x3c\xe6\x64\xf1\x98\x92\xea\xe0\x72\x59\xf3\xdc\xa7\xa2\x3b\x0a\x5d\x7c\xa1\x8b\xcf\xa4\x9b\x99\x00\x25\xf4\x98\xf6\xc6\x1f\xb7\xc8\x4a\xa8\xde\xdf\xb8\xdc\x77\x0b\x49\xdf\x0e\x31\xc5\xd7\xa1\xbd\xf3\x9b\x57\x07\x76\xdd\xea\xda\x19\x74\x4f\x6a\xeb\x6a\x6a\x9b\xd0\xc0\x2c\x1c\xd7\x35\xbf\x2b\xcc\xac\xe7\x7c\xf1\xd9\x75\x85\x27\xbe\xf5\xcd\xbb\x53\xb6\x94\x2f\x96\xaa\x4f\x75\x47\xdc\x9c\x92\x55\x3e\xbd\xf7\xf3\xfe\xfa\x90\x22\xd7\x2f\x97\xaf\x5d\x4d\xe2\x05\x2b\x06\xb4\xef\xaf\x5b\x3b\x49\x98\x5f\xec\x2d\xc6\x27\xf2\x4e\xd1\x21\xc5\x17\xe4\xa7\xca\xfc\x2c\x5b\x26\x77\xd5\x2f\xbf\xba\x29\xe1\x75\x71\xd6\x54\xd2\x96\xf2\x04\xad\xcb\xb6\x6e\xa8\xea\x38\x20\xa8\x22\xe0\x42\x06\x10\xc6\xef\xb0\xf8\x8c\x49\x37\x15\x34\x14\x9c\x42\x2e\x9b\x0a\xa6\x9a\x79\x41\xad\xdd\x27\x1b\xc6\x94\xd3\xfb\xfa\x4e\x9f\x72\x2a\x4f\x4b\xb7\xdf\xb2\xb4\x60\xfa\x66\x72\xa6\xaf\x7f\xc4\x7a\x9d\x97\x17\x6e\x3d\xff\xac\xb9\x73\xcf\xcb\xf4\xa9\x44\x13\x16\x6f\xb8\xf1\xb1\x15\xd5\x90\xe5\x9f\xad\x84\x54\x78\x09\x1d\xef\xbc\x0a\x0f\xa2\x98\x02\x90\x92\x0a\xf8\x2b\xfa\x70\x51\x0a\xf0\x91\x84\xd1\x17\xa6\xa2\xdc\xb0\xe2\x85\xde\x0b\x11\xa4\x94\x6c\x21\x8f\x08\x82\xa2\xba\xfb\xad\x19\xa6\xe1\xd5\x8c\xb7\x76\x7f\x8e\xee\xa4\x03\x74\x67\xf9\xc9\xb0\xef\xba\x6f\x85\x5b\xc3\x5b\xce\xf6\x71\x6b\x7d\xdb\xb5\x54\xf9\xb0\x96\xda\xee\xf3\x6d\xa7\x5f\x33\x27\xfd\x7a\x3b\x2b\x1e\xdc\xb8\xfa\x9a\xa7\xb5\x8f\x48\x7a\xfa\x9a\xd5\x1b\x0f\xbe\xf8\xd7\xbf\xb2\x93\x5b\xc3\xdf\xba\xce\x17\x0e\xfb\xce\xde\xa2\xfd\x72\x56\xfc\x4f\xda\x3b\x14\x78\x2b\x3e\x2b\xfe\x16\x05\xb4\xbf\xbc\x65\x9c\xab\xed\x97\xc0\x0f\xc0\x8a\x06\xcc\xc0\xa9\xf8\x14\x90\x2c\x74\x90\x01\xaa\x77\x3c\x9c\x49\x1d\xce\x8a\x76\x35\x97\x2d\x74\x90\x09\x71\x34\x6d\x9c\x2a\x6d\xe6\x82\x01\xd9\x27\x4a\x14\xe0\x0d\xf5\x33\x1f\x2f\xe4\x13\x05\x25\x55\x68\xa6\x20\x6b\x5b\x78\xce\x8a\x19\x6f\xed\xfe\x1a\xbb\x65\xb4\x15\xf4\x79\xba\x54\x5b\x76\xc9\x14\x9b\xd7\xbe\xc5\xdd\x7e\xc7\xa1\x25\x3e\xdf\x97\xe8\x39\x72\x9c\x7b\x5e\xde\xe6\x15\x42\x89\xe6\x28\xe7\x4e\xde\xff\x59\xaa\xb7\x50\xc9\x97\x9a\x7d\x8f\xb6\xf1\x77\xf3\x0f\xd0\x25\xd7\x5c\xf5\xb5\xee\x0b\xbe\x71\xf2\x4f\xbe\xd0\x5d\x5a\xa3\xb7\x53\xd3\xd8\x65\xa3\xcd\xfc\x2f\x89\x3d\x53\xb6\xef\x3f\xd7\x3d\xdb\xe6\xb5\xf7\x9c\xf2\xda\x2d\x2d\xbd\x2d\xef\x90\xdb\x73\xa1\xdb\x2e\x7b\x65\x66\xd3\x26\xdf\xf6\x56\x9a\x3e\x38\x69\xeb\xec\x58\xf1\x8c\xc7\x9e\xdd\xea\x7d\x6f\xff\xb7\xae\x5a\x5f\xfc\xe6\x05\x66\xdf\xb9\x87\x55\x71\xd0\xa0\xa7\xa8\x4e\x51\xe3\xe5\xbf\x63\xe7\x24\x8e\x02\xd2\x88\x95\x27\x75\x51\x3a\xc0\xd7\xec\xd5\x32\xaf\xcd\x51\xf7\x46\x9d\xa3\x32\x2b\x39\x38\xc4\x93\x9e\x69\xb1\x23\x88\x4d\xf3\x24\xe3\x1c\x3c\xd3\x67\x4f\x7f\xe0\x59\xa7\x2c\x3b\xf5\x17\x6d\xa5\x9f\xd9\xa5\xba\x3a\xc9\xa9\x15\x6c\x0e\x07\xb7\xef\x88\xda\xdd\xdd\x14\x8b\x35\x75\x77\x0b\x6a\x4b\x22\x51\x59\x93\xd6\x0a\x6b\x91\x06\x28\x20\xba\x48\xae\x6a\xbb\x53\x56\x32\x34\xdf\x6d\xa4\x4c\x62\x4a\x4a\xe9\x36\x59\x1a\x2b\x99\xee\xa0\x50\xe8\x22\xa1\xaf\xbd\xd8\xfb\x40\xbf\xe0\x51\x25\x3b\xcf\xb9\x44\xed\x3f\xb5\x72\x4e\x70\xf4\x59\x9d\xcc\x65\x7d\x66\xa8\x8e\x91\xad\xcf\xea\x14\xd9\xf7\x89\xd3\x78\x27\xc7\xea\x54\xa7\x9b\x7d\xa9\xbf\xb7\x24\xf4\x65\x4b\xbd\x0f\x94\xe7\xca\xce\x3e\x91\x38\x07\x0d\x69\xe5\xef\x7b\x9c\x7d\x56\x56\x37\xf4\x8c\xe4\x76\xd8\x2f\xb4\x52\x8e\x38\x0a\x5a\xdc\xee\x3a\xd5\x21\x7c\xb5\xbf\xb7\xa8\xaf\x64\xc3\xe6\x1e\xc5\xb1\xb6\xd0\x55\x2b\xe8\xd3\x71\x15\x10\xac\x58\x72\x27\xc7\x7d\xa9\xd6\x3f\xa2\xbc\xa9\xcc\xc7\x35\xe9\x0a\xe3\xe2\x92\xe3\x4e\x8d\x54\xc4\xbd\x68\xcd\x5d\x02\x01\x95\x22\xda\x00\xf5\x51\x51\x2b\x69\xfd\xe3\xdd\x6c\xc0\x70\xab\xfa\x9b\x83\x1e\x62\xba\xb5\xfe\xd1\xa3\x34\x6c\x60\x34\x9c\x8c\xd2\x22\xa3\x91\xa4\xf6\x66\x8f\x18\x27\xd8\xd5\xe5\x33\x8b\x33\x97\x93\xf9\x51\xb3\xbd\x66\xbd\x91\xa2\x91\xad\x58\xa4\xc8\x10\x28\x42\x25\xf3\x5b\xa4\x22\x8b\x50\xc4\xb0\x7a\x1d\x70\xc8\xf2\xd0\xd7\x8d\x24\x7a\x86\x52\x4d\xf0\x82\xa3\xc6\x85\x27\x02\xb2\xbd\x7d\x33\x97\x2f\x9f\xd9\x67\xbe\x7b\x2b\x72\x4c\xbf\x04\x61\x00\x5e\x14\x70\x05\x40\xa2\xd4\xc1\xd7\x98\x29\x54\xf7\xb0\x67\x50\xcc\x49\x1d\x62\x2a\x5f\x68\xe6\x33\x51\xf3\x28\x01\x79\x47\x22\xa3\x31\x27\x93\x44\xc9\x59\x6b\xe1\x60\x18\xf3\x75\x89\x23\xa9\xd9\xbd\xd3\x17\x04\x9a\x33\x99\x9e\xf6\x01\xe3\x78\xeb\x11\x41\xb4\x6a\x25\xab\xd3\x21\x47\x2e\xed\x5c\x9a\xed\x4d\xcf\xcc\x4e\x6d\x9c\x56\x49\x42\x18\x3d\xee\xa7\x27\x19\xc6\xe4\x85\xd3\x27\xd6\x47\x3a\x9a\x26\x9c\x3a\xe3\x9c\xf3\x37\xcf\x32\xcb\x18\x17\x58\xcd\xc5\xb7\x2c\x7b\xf2\xa4\xc2\xdc\x09\x4d\x86\x8a\x61\xc8\x19\xd6\x4b\x91\x1d\x25\x22\x4e\x72\x06\x63\x1d\x33\x52\xe7\x3f\x61\xc4\x97\x9c\x5e\x9b\xf6\x3d\x6e\x53\x35\x41\xf3\xf4\xee\x8e\xae\x75\x33\x97\x6e\x5e\x74\x76\x26\x6a\x64\x1e\x13\x62\x26\x1f\xdd\x7f\x11\x00\x9d\x35\x75\x33\x3e\x1e\x4b\x89\x82\x28\x89\x4a\x2a\xa7\xe4\x15\x7d\x11\x14\x0a\x0a\xcb\x65\xbb\x28\x91\x49\xf3\x12\x06\xb5\x95\xef\xcf\xee\x79\x4e\x3b\x32\xe5\x14\x4f\x23\xcf\x09\x64\x63\x76\x26\x4d\xf6\x4f\xa8\x6f\xae\xfb\xca\x93\xb7\x0f\x52\xef\xb7\xdf\xa7\xfb\xb8\x0e\xed\x61\xed\xd7\xff\x6c\xf9\xc6\xa9\x4e\x0b\x0b\x78\x89\x77\xf3\x2e\xce\xc9\x2c\xb9\x60\x67\xc7\xdc\xd6\x73\x49\xbc\xe7\xb3\xef\x3e\xb6\xea\x9f\xc7\xca\xfc\x19\xe3\x24\xaf\xdf\x67\x70\x45\xd5\x95\xac\x89\x7c\xcd\x5c\xba\x8b\x1b\x59\xd9\x3e\x51\x9b\xff\x23\xed\x01\x6d\xae\xf6\xc0\x8f\xcc\x93\x1b\x93\xa6\x9f\xd9\x31\xb1\xe3\xcc\xe9\x93\x4c\xef\x10\x94\x90\x66\xde\xba\x56\xb9\x9c\x68\xd4\xc7\x4a\xea\x4f\xb4\x67\x9f\x7c\x92\x66\xfe\xc4\x54\x31\x66\x7b\x95\x00\xcf\x07\x74\x41\x28\xa4\x28\xec\xa2\xd1\xa4\xb5\xd9\x2a\xfa\xe1\xa5\xf0\x8b\x8f\xf2\x11\xf8\x80\xa4\x54\x7b\xb3\x48\x75\x8f\xea\x2e\x43\x35\x7c\x8c\x36\xf8\xc5\x47\xaa\xda\xdd\x47\xe4\x9c\xcc\xde\x92\xe5\x72\xa3\x9c\xab\xea\x87\x07\xc4\x47\xb9\x77\xaa\xfa\xe1\x63\x76\xef\xc4\xbb\x0c\xfd\xf0\x31\xda\x60\xf6\x5a\xb9\x51\xd6\xcb\xca\xc9\x8f\xc8\xb2\xa9\x98\x7e\xc4\x28\xd4\xe4\x8d\x54\x5e\x45\x12\x3d\xd5\x3b\xae\x3a\xb8\xe9\x34\x83\xc6\x9c\x7c\x35\xcf\xfd\x47\x8d\x5d\xff\xea\x46\x5c\xce\xdc\x89\x33\xa5\x55\xe3\x62\x0f\x2e\x4c\x4d\xe4\xc9\xa4\x03\x02\x64\xc7\x50\xd1\x52\x27\xf1\xac\x14\x52\x5c\x54\x94\xa7\xcb\x54\x74\x29\xa1\x12\x2b\xba\xad\xfd\x12\x53\x5d\x5a\xc9\x37\xd5\xa7\x95\xf4\xb0\x72\x49\x0f\x93\x1d\x5c\xa9\x9a\x23\xe2\x90\x79\x9b\xe8\x11\x7d\xd4\x4f\xfd\x4a\xa8\xde\x43\x6a\x20\xa0\xa9\x9e\xfa\x90\xa2\xa9\x75\x25\x1b\xdd\x5d\xef\xd1\xd4\x60\x90\x8c\x20\x52\xed\x25\x6b\xdd\x68\x16\xad\xaf\x46\x7f\xa4\x0a\xe6\x19\xea\xa9\x40\xa2\x62\x6d\xc1\x57\xbe\xb2\xc7\x27\x4a\x42\xc0\xef\x93\x46\x2e\xe7\x33\xf8\x3c\x2e\x6e\xde\xd2\x97\x6e\xe6\x83\x86\xd5\x85\x71\x73\x07\xf7\x82\xf1\x79\x21\x5a\x7f\xf4\xa0\xa3\x9e\xdb\x6d\x5c\xd8\x87\x90\xe2\x76\x37\xb2\x7f\x79\xc1\x54\x74\xbb\x1b\x9c\x76\x5e\x22\xfe\x5f\x42\x4a\xd6\xb8\xed\xc3\xfc\xe3\x4a\x1a\xea\x93\xdc\x96\xe9\x36\xf7\x64\x45\x97\xb0\xea\x26\xb4\x4c\x11\xb8\x82\x92\x55\x1c\xde\x16\xbf\x22\x29\x18\x73\xde\xcd\x77\xec\xfe\x51\x93\xa1\xeb\x50\xb7\x2e\x3b\x5a\x5c\xb6\x75\xeb\x32\x2a\x2e\xdb\xca\xfa\x97\x6d\xe5\xfa\xcb\x86\x9f\x2b\xe9\xef\xc8\xd6\x91\x3d\x71\xe9\x1c\x41\x85\x8c\x89\xa6\xb4\x6f\xae\xcb\xd5\xe3\xee\xe9\x00\xf9\xa3\x31\x51\x22\x29\x3b\xb6\x7c\xe9\x9c\x16\x6d\x5f\xdb\x97\x67\x1e\x2d\xc5\x72\x2d\xb4\xa8\xed\xcb\x33\xf9\x62\x2c\xa7\xed\x1d\x2a\x2d\x7f\x69\x86\xf6\x0d\x81\x2a\x15\x47\x96\x6d\x65\x73\x5b\xe2\xda\x86\xcc\x9c\x50\x73\x4b\x9c\xb6\x67\xe6\x84\x68\x6a\xff\x05\x73\xb5\x0d\x22\xef\xe1\x6b\x80\x21\x14\x87\xc1\x4a\xa2\x61\x5b\x03\x83\x88\xc6\x6f\xe5\x8e\x6e\xdc\xb2\x92\x12\x1a\xbf\x4d\x5b\xb3\xcd\xca\xbf\x9e\xd5\xc7\x6b\xcd\x2e\x2c\x8f\x91\x4d\x57\x13\x7f\x54\x94\xc0\x95\xcc\xba\xaa\x7b\xc7\xe3\x77\x8a\xc7\xee\x0b\x1f\xb7\xc0\xd1\x5d\xdf\x71\xbb\xbc\x95\x5d\xdd\xca\x3d\x2c\x96\xea\xf9\x26\x07\x3c\xf0\xeb\x7d\x16\xf5\x98\xa7\xb0\xa2\x9e\x8c\xa7\xea\x63\xea\x30\xf4\x47\xc0\x87\x50\x05\x98\x1e\xa6\x6a\x60\x60\x18\x02\x8f\xa3\xaa\x2a\xe2\x88\xca\xa9\x65\x70\x20\xf5\xa8\x3e\x1a\x47\x75\x16\x93\x51\x34\x56\xaf\x7c\x41\x94\x4c\x26\x34\xd8\x41\x29\xfd\xa3\xa4\xfc\xbe\x40\x50\xe7\x79\x9a\xc9\xf8\x04\x32\xe9\x2e\x2e\x97\x4d\xe5\x8f\x99\x14\xd1\x79\xca\xac\x86\x53\x4e\x9b\xb1\xec\x9c\xcf\x08\x37\xfe\xe1\xf4\xa6\xf3\x26\xe5\x56\xce\x6b\x0a\x38\x42\xfe\x35\xb3\x36\xdc\x19\xaa\xdf\xf5\xf8\xfa\x1f\x6e\x5f\x35\x85\xba\x69\xe2\xde\x4d\x43\x86\x5d\x13\x57\xda\xb4\x97\xbb\xbf\xc1\xda\xba\x40\x71\xcc\xfc\xcc\x39\x4d\xb2\xb4\xe1\xc2\x74\xe7\x95\x33\xa8\x81\xf5\x6c\x74\x5a\xf8\xee\x33\x69\x29\xb7\x7c\xce\xa6\x2f\xef\x5d\xec\xb5\x9e\x44\x6c\x34\xd7\xde\x31\x7b\xa1\x09\x60\x64\x53\xcf\x93\x29\xc4\xf5\xa9\xa2\x90\x53\x0c\x3d\x7b\xdc\x9f\xa9\xde\xb4\x91\xe1\x07\xf4\xfc\xfb\x7f\xdc\xfc\xd6\xa4\x59\x5b\xba\xaf\xda\xf6\xd0\xf3\xcf\x97\x0f\xea\x41\x86\x49\x42\x71\xd3\x5e\x76\xd6\xdb\xbb\x3a\x3b\xe9\xe7\xd6\xfe\x9d\xff\xfc\x76\xf9\xeb\x66\x5d\xa6\x88\x31\x7a\x27\x8e\xce\x57\xc5\x91\x42\x07\xba\x2a\x92\x5e\x0d\xd7\x9e\xaf\x5a\x5b\x45\x73\x51\xb8\x95\x88\xe8\x0e\x44\x74\x37\x17\x9d\x41\x51\xa9\xf6\x08\xbd\x79\xf1\x5a\xbf\xd7\x39\x73\xb9\x37\xec\xed\x6c\x75\x1e\x36\x6c\x8e\x86\xee\x11\x71\x04\xbc\x5a\xb9\xd8\x6f\xe8\xf7\xa4\x6a\x7a\xe7\x0d\xfd\xb0\x58\xbe\x56\x54\x7b\x72\x47\x90\xeb\xe9\xc9\x89\xc8\xf5\xb0\x6f\x86\xbd\xcb\x67\xea\x6b\x79\x6b\xa7\xc5\x30\x4b\x1a\xfa\xbe\x4a\x2d\xd4\xf5\x7b\x3d\x33\xcf\x54\xad\x74\xf5\xad\xaa\x7a\xd4\xc8\x20\xe8\x6f\xa3\xcf\xe7\x8a\x77\x19\x72\xea\x9c\x8a\xfd\x93\xde\xcd\x86\xb8\xad\x37\x41\xef\x60\xe3\x66\xcd\x0e\x96\x92\x82\x15\x05\x9a\x69\x89\x97\xf5\x26\x2a\xb7\x41\x16\xaa\xc7\x29\x9b\x79\xae\xb8\xbe\x7f\xbd\x3c\x61\xe2\xa2\xf5\x95\x2f\xf7\x83\x15\x1e\x6b\x2a\xd6\xc6\xf5\xbd\x11\x5e\x38\xb1\x35\x5c\xbe\x70\xdf\x33\x0f\xbd\xf8\x2c\xa5\xfb\x1f\x7a\xf1\x26\xfa\x74\x1f\xd7\x11\x8b\xac\xf0\x38\x6c\xe2\xa2\xc5\xe7\x9e\xcc\xed\xeb\x5f\xbf\x7e\xd1\xc4\x09\xf2\xfa\xca\x57\x83\x67\x45\x24\xd6\xa1\x67\x6e\x9d\xb8\x30\xcc\xbe\x7a\xd3\x8b\x0f\xf5\x53\xfa\xd9\x17\x1f\x7a\x66\x9f\xf6\x95\x3e\xae\x2d\x96\xb2\x7a\x56\xd8\xc4\x05\x67\x2e\x9d\x69\xaa\x11\x30\xec\x92\x54\x61\x10\x12\x3c\x68\xc4\x0d\x78\x06\x47\x6b\xec\xba\xcc\xf6\x05\xd2\x79\xcf\x88\xab\xe6\x9e\x1f\xff\xc7\x5c\xf4\xf3\x8f\x5f\xf3\x53\x73\xc9\x0f\x19\x36\x41\x86\x65\x90\x2e\xe4\x8b\xb1\x94\x5e\x8f\x91\x5d\x49\x29\xa6\x79\x90\x51\x16\xcb\xa4\x03\xc1\x7c\x3a\x98\xef\x26\xb3\x84\x40\x30\xe0\xf9\xdf\x64\xe6\x54\x83\x8a\xb8\x7b\x7a\x57\xf7\xf6\x5c\xda\x63\xbe\x35\xd5\x69\xfd\x72\x9d\x3f\xd6\x29\x49\xc1\x4d\x72\x9d\xed\xaa\x64\x6b\x9d\x5d\x0a\x7e\xa7\xce\x4b\xc1\xd8\x84\xab\x25\x47\x9d\x6d\x87\x64\xeb\x72\x07\xed\xbb\x6d\xce\x91\xa4\x81\xcd\x7a\xd2\x58\x5b\x6d\x52\x8b\x5d\x4f\x6a\x9f\xee\x0a\xd6\xed\xb6\x39\x99\x7a\xb7\xdd\x9b\xe1\xb7\x30\x4b\xaf\xd3\xe7\xf3\x39\x7b\x2d\x6c\x0b\x9f\xf1\xda\xef\xbe\xdb\xe1\xc9\xf0\x7c\x57\x67\x25\x22\x33\x41\xe4\x37\xf3\x19\x8f\xe3\xee\x7f\x34\x7d\xe5\x2a\xa3\x61\x83\x09\xcf\xf5\xf4\xf0\xb9\x8a\x43\xdb\xf1\xb4\x4d\xa6\xfa\xf8\x84\xc9\xa7\xd6\x59\xed\x52\xf3\x26\x69\xa9\x6c\x5f\x3b\xa9\xde\x65\xfb\x92\xcd\x7f\xae\x64\xf9\x5c\xa3\xd5\xe6\x5c\x18\x68\x57\xea\xc9\x53\x57\x9b\xd4\xd2\x7c\xb5\xb4\xd4\xeb\x5c\xdb\x51\x93\xd4\x52\xe7\xee\x0d\x4c\x8e\x05\x99\xa7\x3c\xb0\xdd\xed\x6a\x6c\xb8\xa2\x81\xe7\xe6\x2c\xf7\x33\xe6\x5f\x3e\x87\xe3\x1b\xae\x68\x68\x74\xb9\xb7\xbb\x5d\x4d\x41\x3d\x82\x25\x22\xe7\xfb\x19\x9b\x33\x81\xcd\xd6\xe3\x82\x4d\x2e\x6e\xf0\x7f\x92\x6b\xc4\x6e\xc4\xe0\x85\x93\x86\xd5\xab\x5b\x34\xb8\x61\xe3\x3a\x20\x25\xa5\x64\xbb\x84\x42\x17\x6f\xa8\x08\xf2\x89\x08\x4f\x3e\x51\x6a\xe6\x83\xcd\xa2\x4e\x69\x29\x25\xa5\xa4\xc4\x78\x44\x1f\xb1\x89\x42\x17\xe5\xb2\xa9\x66\x12\xd4\xfd\xda\x77\xff\xed\xec\xa5\xd7\xde\x9b\x48\x73\x75\x32\x23\xe2\x98\xc0\x89\x24\x24\xdc\x4d\x7e\xdb\xb5\xb7\xef\xa7\xd3\xe8\x7a\x3a\x8d\x4d\xbf\xfd\x5a\x9b\xbf\xc9\x9d\x10\x48\xe4\x04\xc6\x11\x71\x3e\x7b\x3a\x71\xef\xb5\x4b\xcf\xd6\x0e\xfd\x64\x6a\xf3\x03\xd4\xba\xe1\xba\x9b\x83\x37\xde\xc3\xdd\xa6\xfd\xe5\xe0\x2d\xee\x25\xad\x56\xc9\xed\xe0\x24\x51\xe4\x25\x4e\x22\x51\xf1\x27\x5b\xeb\xe7\xfe\x72\xd3\x6d\x07\x6f\xb9\xa5\x7c\xcb\xe6\x5f\xcc\xad\x6f\x4d\xfa\x15\x91\x24\x4e\xe2\x45\x51\xe2\x9c\x6e\x92\xac\xad\x4b\xdc\x5b\xf9\xa5\x8b\x97\x0d\xde\xbc\xa0\x67\xce\xab\x23\x7c\xb7\x71\x76\x6e\x3a\xd6\x8d\xde\x36\x43\x59\x25\x1e\xcd\xe6\x73\x59\x25\x3e\x22\x09\x79\x32\x3a\x67\xa4\x8b\x98\xb9\x6c\xaa\x8b\xb2\x29\x3d\x3a\xd5\x45\x05\x9f\x31\x32\x8c\x47\x6c\x63\x3a\x92\x46\xe7\x53\x7d\x50\xea\x92\x53\x26\xdd\xac\x8f\xc0\x4c\x3a\x40\xe6\x95\x34\xfc\xa3\x0b\xd3\x5a\x7f\x5f\xb1\x2f\x54\x9f\x9c\x10\x28\xf0\x4a\x43\x7b\x62\x42\xca\x1d\x89\x38\x92\x4d\x93\x82\x93\x85\x57\x6e\xba\xa6\x24\x34\xc7\xbd\x39\x9f\x2b\xd2\xa6\x4e\xb1\x2a\xdc\x74\x7a\xec\x0b\x89\xf3\xfb\xbe\xfb\x99\x0d\x01\x6d\x40\x9f\x3f\xc9\x9b\x58\x35\x75\x4a\x7d\x50\x69\x4b\x65\x16\xdf\x3c\x7b\xf2\xbe\xd5\xbb\xcd\x3b\x6b\x98\x9a\x59\x30\xf5\x67\xd3\x56\x2c\x0f\x5d\xfd\xb9\xb6\xe0\x2c\x21\x1d\xc9\xc5\x13\xde\xb2\x2a\x4a\x2e\x8b\x87\xcd\xfb\x5a\xa8\xd9\x3d\x6f\x7e\x24\x7d\x5a\xc3\x0c\x0f\x2d\x4b\x9c\x3b\x3f\x9a\x58\x70\xaa\x3f\xb0\x6a\xc1\x6d\x0f\x9c\xd4\xd6\xda\x93\x63\x6a\xae\xa7\xfe\xa6\x9e\x5c\xc3\x35\x5b\x27\x26\x4f\xb9\x75\xe3\xf9\x9f\xde\x8d\x91\x3b\x98\x0c\x5b\xd2\x2e\x5d\xb6\xac\x99\xd1\x52\x46\x5f\x1b\xf8\xc8\x9b\x1a\x13\xc9\x29\x98\x18\x13\x82\x81\x60\x33\x0b\xea\x13\xb9\x92\x8b\xa6\xf3\x05\x7d\x45\xac\x4e\x73\x86\xd9\x68\x4a\x49\x8d\x2e\x3f\x85\x2e\xd2\xa7\x30\xc9\x3f\x82\xd2\x11\x7c\xb5\x45\x5c\xbe\x9c\x37\xde\x2c\xac\x38\x47\xbd\xe9\x15\x61\x72\x70\x52\x53\xd2\x11\x89\xb8\x53\x13\x12\xed\x0d\x0a\x5f\x08\x4c\x48\xd6\x87\xfa\x8a\x7d\xd4\x97\x5e\xa8\xee\x5e\xbd\x6f\x72\x3c\x7e\xf3\xe2\x4c\x2a\xd6\x5a\x57\x2f\x4f\x9e\xb6\x2a\xa1\xbd\x67\x20\x2d\x12\xd8\xa0\x3e\x7b\xc9\xfa\xed\x5f\xa7\xe9\x9c\x62\x9d\xc2\x9b\x87\x2c\x35\xc4\x97\x91\x67\x46\xc3\x69\xe9\x16\x25\x39\xcf\xdd\x1c\xfa\xd4\x99\xf3\x98\xc7\xe2\x92\xc4\xb2\xea\x4d\xc4\x73\x91\xb4\x30\x2b\xd8\xf6\xb9\xab\x43\xcb\x57\x4c\xfb\xd9\xd4\x05\xe9\x8b\x77\x7f\xfa\xfc\xab\x67\x9d\x76\x4a\x32\xba\xe2\xac\xb3\xfd\xe9\x05\x37\xd5\x9b\x78\x6b\x6d\x6f\xbf\xff\x16\x61\xc1\xaa\x80\xff\xd4\x05\x89\xe8\xbc\x0a\x4f\xf0\x75\xae\x68\xc8\xe4\x20\xcf\x31\xb7\xfb\x72\xc5\xf1\xb7\xf7\x0a\x03\x47\x7e\x74\xec\xf5\xbc\xb5\x63\x53\x45\x18\x27\x03\x94\xed\xe0\x0c\x49\x5d\x47\x64\xcc\xc9\xf9\x7d\xba\x4c\x54\xa8\xf0\x99\xe3\xee\x4c\x16\xd5\xb6\x53\xfb\x96\xad\xde\xbc\x6a\x6e\xbd\xb7\xcb\x5b\x3f\x77\xd5\xe6\xd5\xcb\xfa\x4e\x6d\xfb\x2e\x3b\x8d\xcd\xda\xaf\xbe\x55\xbe\xd3\x7b\x82\xfb\x94\xb9\xc7\xce\xb8\x76\x5e\x87\x3b\xb3\xe0\xd4\x70\x20\x10\x3e\x75\x41\xc6\xdd\x31\xef\xda\x33\xf6\x7c\xb7\xfc\x32\x9b\xb4\x7f\xcf\x6f\xdf\x2a\xef\xf1\x1e\xef\xba\xe5\x51\x3b\xd5\x88\x00\xb4\xea\xfc\x5c\xd2\x17\x70\xb2\x5a\x5e\xc3\x5f\x09\xa8\xd8\x69\x4e\x65\xcd\xdc\xc8\x8e\xd9\x48\x32\x73\x87\x8c\xa9\x8c\x04\x97\x43\x33\xac\x34\xa9\xe8\x90\x2b\xde\x99\xcb\x97\xcf\xa4\x08\xf9\x44\x8f\x68\xe3\xb9\x7e\xb9\x3c\x20\x67\x15\x63\xef\x27\x44\x25\x25\x2b\xb3\x48\x1f\x1f\xf1\x87\x1c\xa6\x61\xba\xec\x30\x3c\xcb\x67\x96\x8b\x33\x97\x33\x5e\xaa\x63\xe9\xac\x9e\x45\x09\x51\xa4\x72\xc7\x41\x24\xa4\xc8\xe5\x81\xea\x39\x60\x93\xd7\x75\x21\x89\x1c\x50\xc8\x78\xe2\x85\x0e\x32\x56\x6d\x73\x57\xc0\xa3\xf3\x5a\x52\x26\x17\x0f\x70\x19\x8f\xb9\x10\xfb\xc7\xb3\xa1\xef\xfe\xf9\xcf\x1f\xd0\xec\x0d\xf3\xe6\x9c\x4c\xd3\xe6\xb2\x79\x7f\xde\xb9\x79\xdb\x3c\xf6\x67\x8e\xfb\xb3\xe4\x9a\xde\xbe\x81\x0e\xd4\xb2\x9e\x5b\xd8\xb7\x5f\xcd\xce\x9a\x95\xcd\x9c\x76\xda\xd0\xd7\xe8\xf6\x7b\xef\xdf\xb8\x6a\x66\x79\x3b\x6d\x55\xbc\xf1\x29\x5f\x61\x57\xd5\x72\x9b\x86\xee\xdb\xb8\x33\xa5\x0e\x1d\x3a\x65\x19\xec\x84\xc7\xe0\x27\x74\x00\x38\x27\xb5\x51\x2c\xc5\x19\x12\x50\x3e\xe3\xa9\x08\x77\xba\xc4\xe7\x49\x07\x68\xc0\x1b\xf6\x7a\xc3\x5e\xd6\xaf\x84\xb4\xb3\x32\xcc\x63\xa7\x46\xa1\x57\x5b\x1b\x52\xbe\xf2\xe9\x91\xab\x17\xb3\x9f\xfe\x0a\xeb\x27\xc3\xb4\xc3\xb8\x97\x4c\x7b\x3c\xa4\x68\x4d\x76\x4f\x23\xbd\xa5\x84\x3e\xf3\x23\x06\x53\xce\xd3\xf0\xa3\x11\xf9\xcb\xf8\x3f\x83\xc7\xbb\xff\xb7\xc9\xbc\xdf\xb7\xd6\xd0\x7f\xe4\x16\xc6\xe3\xed\xfb\x8d\x9a\xe4\x32\x03\x80\x72\x71\xc4\xfe\xd8\xb8\x1e\x4d\x55\xb2\xf2\xbe\xf2\x06\x73\xfb\x8f\x6d\xdf\x27\x9b\xa6\x8a\xac\x4f\x2b\x55\x0d\x71\x8d\x84\x55\x23\x5c\xe3\x42\x46\xee\x4c\x0d\x21\xc5\xc8\x67\xec\x02\xea\xf9\xb2\x8a\x52\x73\xc7\x54\xd0\xf8\x5f\xc2\xc7\xa7\x41\xeb\x48\x9b\xb2\x4a\x17\xab\x9e\x56\x88\x47\x27\x32\x9d\xf9\x34\x83\x02\xfc\xf1\x48\x90\xae\xda\xbb\x49\x2b\x55\x68\x96\x8c\x96\x68\x03\x15\x9a\xad\x84\x6d\xda\xab\x8b\x5f\xc7\x23\x45\xca\x94\x8b\x35\x94\xcb\x4a\x26\xe5\x5a\x4c\xb2\x1e\x91\xf7\x55\x88\x70\x60\x1e\x40\x4a\x2e\xea\xf7\x05\x92\xb9\xa8\x4f\xea\xa2\x82\xdf\x67\xae\x60\x64\x6c\xfc\x54\xfb\xc1\xdc\x23\x31\x66\xe5\x94\x92\xea\xa8\x28\x96\x72\x35\x52\x31\xfd\x74\xfe\x30\x9e\xe1\x7f\x30\x8c\xf9\x5f\x78\x46\x3d\xeb\x0b\x2f\x5e\x31\x31\xa7\x34\xcd\x38\xb5\x67\xa3\xd7\x39\x54\x72\x7a\x37\xf6\x9c\x3a\xa3\x49\xc9\x4d\xbc\xe2\xc5\x2f\x9c\xd5\xd9\x4a\x91\xe5\x33\x59\x71\xe6\x72\x8a\xb4\x76\xb2\x2f\x3c\xf8\x8b\xbe\x85\x7b\x3e\xe8\xfb\xc5\x83\x4d\x7b\x5e\x52\xe7\xec\xd8\x70\xba\x90\x9f\x10\x5b\x90\xc9\xcf\x3f\xef\x34\xf3\x86\x99\xd3\xce\x9b\x9f\xcf\x2c\x88\x4d\xc8\x0b\xa7\x6f\xd8\x31\x47\x6d\xed\x34\x75\x98\x9d\xe6\x3f\xd4\x1b\x39\xb3\xa0\x4b\x36\x2d\x48\xa1\x1d\x69\xdc\x88\x3b\x01\xca\xa7\x14\x49\x0c\x06\xcc\x77\x21\x9f\xaa\xf8\x83\x79\x25\xa5\x18\x5f\xc3\xdf\x4c\xd9\x78\xcc\x57\xd0\x43\xf2\x94\x45\x04\x7e\x9f\x37\x18\xd0\x65\x09\x27\xeb\x20\xa3\xc1\xc6\x8a\x1c\x6c\x26\xe3\x02\x2a\xbd\xff\x0a\x4a\x21\x1f\x68\xd1\x25\xf2\x2e\x16\x0c\xe8\x6b\x8f\x93\x93\xcc\xa3\xda\x81\x42\xde\x3b\x9e\x9e\x99\xc4\x4b\x56\x81\x97\xac\x41\x41\x12\x45\x49\x10\x27\x31\x49\x22\x4e\xb2\x04\x18\x71\xa2\x45\x10\xcf\x63\x75\x56\x9e\xd5\x59\x3b\xec\xb6\x19\x2c\xc0\x98\x8f\x7d\xd6\x3c\xeb\xf0\xc3\x7b\xbd\x1e\x12\xe5\x6c\x7b\x9b\x25\x18\x63\x42\x1d\x57\xe7\x14\xbd\x13\xed\xee\xb6\xf6\x88\x53\x0a\x4d\x99\x3f\x37\x95\xab\x6f\x92\xe7\x34\x84\xa6\x6e\x9f\x5a\x17\xef\x95\x9b\xea\x73\xe1\xb6\xe2\x0c\x25\x4e\x1e\xef\xbd\x3f\x24\xd4\xce\x17\xb4\x48\x94\x24\x41\x94\xa4\x0e\x89\xe3\x2d\x16\x8e\x9f\xc2\xf3\x8c\x17\x38\x26\x93\xc4\x24\x8b\x24\xce\x91\x78\x4e\x92\x78\x8e\x77\xbb\x5d\x12\x2f\x59\x78\x3a\xcd\x38\x1a\x72\xe0\x6b\xda\xdf\xb2\x9c\xdb\x9e\x6d\x23\x8e\xac\x2d\xa1\x69\x2e\x12\xea\x2c\x12\xdf\x18\x08\x87\x25\x71\x52\x40\x6c\xc8\x7d\x7a\xf6\xe9\x53\xbb\xe6\x8b\x8d\x6e\xb7\xe7\xff\xe3\xed\x4d\xe0\xe3\x28\xce\xbc\xe1\x7a\xaa\xfa\x98\xab\x7b\x66\xba\xe7\xd2\x68\x34\x9a\xd1\x68\x0e\xdd\xf6\x9c\x92\x75\x8d\xe5\xdb\x92\x6d\xf9\xc4\x60\x63\x0b\x5f\x18\x71\xd9\x80\x31\x87\x8f\x0e\x38\x80\x6d\xc2\xe5\x60\x1c\x12\x62\x41\x48\x80\x10\x36\x84\x6c\x0e\x12\x93\xcc\x26\x84\xe4\x5d\x02\xc1\x2c\x6c\x2e\x92\x15\x49\x36\x4b\x12\x48\x78\x93\x25\x09\x96\xa6\xf5\xfd\xba\x7a\x2e\x8d\x65\x4c\xf6\x7b\xdf\xd7\xd6\x74\x57\x57\x57\x75\xd7\xd5\x55\x4f\x3d\xc7\xff\xb1\xf3\x2e\x3f\xb7\xb4\x6f\xce\x8a\xae\x0b\x52\x8d\x36\xa6\x3e\x1b\xdb\x82\x2d\x36\x92\x04\x33\xbe\xbd\x72\x4e\x2a\x62\x27\xe4\x68\xdf\xd1\x79\xe0\x83\xf1\xfb\x28\xd0\x66\x3a\xa3\x0d\x37\x5d\xbe\xae\xdf\x0a\x36\x44\x23\x05\x16\xdc\xb9\x10\xfc\x9e\x74\x6e\xed\x05\xd4\xbb\xd5\x09\x4f\x52\x10\xbf\xe6\x29\xa4\xeb\xa9\x4e\xa1\x66\xbb\xbd\x1e\x72\x52\x5a\x82\x5c\x7d\xe4\x1c\x20\x7e\x9d\x8b\x17\x77\x76\xe2\x91\x58\xf1\x33\x8d\x45\xfd\x90\x93\x65\x35\xeb\x2f\xad\xb3\xec\x14\xab\xa0\xd9\x68\xab\xb6\xce\x52\xd3\x64\x8d\x1e\xa4\x62\x60\x6a\x96\x2f\x82\xf6\x55\x61\x27\x55\xe9\x70\x14\x0d\xc3\x35\x02\x46\xca\x38\xb0\x0e\xf4\xa3\xa7\xa5\x19\x75\x1e\x9b\xae\x31\xa8\xa7\xa5\x43\xcb\x8f\xdd\x7e\x60\x0f\x8a\x66\x8b\xc9\x60\x32\x31\x46\x79\xb9\xa3\xe7\xad\xee\x96\x4b\xe7\x75\x1e\x9e\x3b\x72\x70\x76\x8d\xcb\xe3\xf2\x5c\x52\xd3\xf5\x66\xd7\x57\x2e\xfd\xc8\xeb\x7b\x95\x3b\x27\x3f\xb9\xef\x5f\xbb\x7e\xd5\xe9\xb9\xa4\x66\xc9\x76\x57\x4d\xe3\x12\x65\xdd\xf2\x07\xbf\x73\x53\xcf\x7f\xcd\x91\x87\x1c\x2b\x97\x9a\x18\x62\xc1\x36\x09\xbf\xd0\x7a\xb4\xd6\xef\x6b\xf3\xba\x37\xb8\xc2\x12\x18\x67\xb9\x3d\xae\xf4\xec\x25\xbf\xfb\xd3\x47\x62\x63\x4d\xee\x0b\x5a\xeb\x5c\xf5\x8d\x6d\x3f\x06\xc7\xd1\xcf\xaa\xdf\x9c\xc8\xb4\xd6\xd5\x5d\xbd\xc4\xb3\xde\x1d\x7b\xb8\xe9\xea\xd7\x5f\xfe\xea\xdc\xee\xde\xe5\xb3\x4c\xdb\xd7\xb8\x2f\x72\x0b\x1e\x63\x80\x89\x3d\x54\xa9\x0b\xb1\x02\x21\x8d\xe4\xd7\x41\xb2\x28\xf1\x86\xb4\xcf\x89\x29\x80\x17\x51\x6c\x59\xad\x4e\x58\x9b\x76\x0a\xd5\x73\xfb\x89\x0e\x9d\xa5\x05\xb1\xdb\xe5\x76\xb1\x8a\xc3\xec\xdc\xbe\x69\x63\x6d\xb2\xbf\x7e\xd8\xb8\x65\xd9\x41\xf5\x8f\x2b\x66\x85\x88\xdf\x2c\xf1\x89\xce\x78\xcd\x05\xb5\x22\x2f\x85\xcc\x91\x80\x95\xd4\x89\x5d\xf3\xba\x4c\xbc\x13\x86\x9e\x3f\x8c\x1b\xc4\x5a\xa3\xd4\x19\xef\x71\x88\x75\xcd\x4c\x4d\xd7\x42\x79\x21\x47\x20\x56\x7b\x41\x4d\xbc\x33\xc1\x4b\x66\x3f\x09\xcd\x5a\x01\xd2\xc1\x65\x5b\x8c\xc3\xf5\xfd\xc9\xda\x8d\x9b\xb6\x3b\xcd\x0e\xc2\x2d\x94\x17\x76\xd5\x30\xcd\x75\xa2\xa3\x27\xde\x29\x19\x6b\xc5\x06\x7c\xf8\xf9\x21\x70\xf2\xa6\xae\x79\x5d\x62\x1d\xb1\x06\x22\xe6\x90\xc4\x17\xd7\xb0\x12\x86\x2c\x3a\x9f\x61\x1a\x33\x52\xb6\x0f\xd9\xf4\xcb\xb2\x09\xc9\xde\x27\x58\x54\x5c\x77\xb4\x7b\x63\xe5\x1b\xfa\xba\xad\x63\x98\x70\x3a\x9e\xa1\x1d\x32\x6e\x90\x3f\x10\xcc\x44\x99\x44\xf0\xd8\x85\x17\xc2\x63\x96\x73\xa2\x9a\xa0\x89\x08\x1c\x5f\xbb\x56\x1d\x65\x2f\xfa\x60\x7c\x93\x32\x8f\x6d\x11\xba\x80\xd2\x90\x4c\xb4\x1d\xeb\xc2\xff\x76\x1c\x6d\x87\x92\x02\x80\x16\x64\x43\x0d\x3a\x16\x34\xe3\x76\x21\xb7\x9f\xa5\x80\x7d\x67\x33\xda\x98\xc0\xec\xf6\x36\x8e\xf5\xb9\x4c\xd6\x96\xc6\x26\x81\x97\x2d\x2e\xb2\xf5\xae\x4e\x2c\x70\x7c\xd3\xec\x26\x93\x83\x10\x8f\xb7\xd6\x6d\x32\xcf\x4a\xb5\xcf\x67\x59\x81\x97\x70\x0f\x74\x3d\xca\xcd\x92\x9a\x6a\x1a\x6d\x5d\xc7\x9c\xae\xaa\x69\xed\x02\xb3\xc9\x5d\xeb\xf5\x10\xe2\x30\x35\xcd\x6e\xe2\x39\x01\x67\xee\xde\x4a\x5c\x16\x99\x17\x9a\x1a\x5b\xac\x26\x97\x8f\xe5\xda\xda\x67\x07\x18\x97\xf3\x58\x97\xad\xb1\xa6\x49\x9a\xc5\x3d\xaa\x7e\xbf\x07\x4b\xbc\xc0\xb2\xf3\xdb\x53\xa4\xab\x72\x5e\x02\xd4\x8a\x10\xb7\x86\x45\x54\x1e\x4f\x39\x19\x58\x04\x46\xdf\xa9\x66\xda\xa1\x70\xea\x05\x97\x9b\xca\xbe\x5d\x8c\xbb\x80\xaf\x95\xce\x70\x7c\x9a\x5b\x33\x6f\x33\x0c\x7d\xf2\xdf\xd5\x57\xbf\xa0\xfe\xef\x37\x43\x2d\x6f\x3e\x7d\xd9\xe7\xea\x83\xbe\x96\xe6\x5d\xc7\xe6\x2f\x1f\x58\xde\x7a\x23\x6c\x78\xc1\xf0\xdc\x6d\x77\x8e\x5c\x39\x12\xbe\xec\x62\x66\xe7\x96\x05\xa2\xef\x16\x35\xff\xc7\xaf\x5d\x79\x2f\x73\x04\xef\xbf\x84\x35\xbb\xbf\xb4\x87\x89\x90\xd6\xbb\x56\xaf\x1f\xbc\xff\xcb\xa6\x48\xe3\x6d\xcf\xed\x70\x76\x5d\xdb\x6f\xa2\xfb\x83\xcd\x53\x0a\xf9\x36\x87\x74\xfe\x37\xe5\x10\x06\x49\xc8\x1e\xb4\x87\xec\xba\xac\x8d\x7c\xfb\xa1\x75\x3d\x10\x8e\xaa\xea\xcb\x53\x68\xea\x95\xa7\x8e\xb1\xff\xad\xfe\x7d\xf1\xe2\xe7\xd4\x9f\xe4\x8d\xf8\x6f\x10\xfb\xd9\x37\x5e\xd2\x6d\x9d\xa7\x1e\xa3\xfd\xba\x06\x6d\x44\xdb\xd0\xe5\xe8\x5a\x74\x13\xba\x05\xdd\xa1\x6b\xd9\x38\x1d\x88\xe7\xf4\xa9\x28\xda\xc7\x68\xbb\xb5\x68\x84\xb3\x42\xa4\x81\x6f\xc7\x3c\xe7\xd6\xa6\x22\xe2\xd6\xc8\x84\x86\x48\xb4\x1d\x3a\xa0\x81\xf3\x43\x3d\xd0\x1f\xe9\x07\x3a\xc9\x45\x23\x28\x95\x94\xe4\xd2\x92\x5b\x79\x9e\x76\xa9\x2d\xcd\x49\xbe\xc1\xe9\xc8\xc4\x33\xda\xbd\xa2\xe2\x8e\xfa\xf3\xb7\x6a\xbd\x90\xec\xda\x70\xc9\xdc\xa6\x15\xe1\x36\xdf\x68\x34\x72\xf1\x0b\x17\xdb\x52\xd7\xf8\xda\xc2\x2b\x9a\xb2\x97\x6c\xe8\x8a\x9a\x9c\xb3\x06\xe6\xba\xe5\x6e\x87\xc3\x69\xe3\x2c\x3c\xef\x6a\x31\x99\x84\xbe\xc5\xf3\x5c\x6e\xf0\xd6\xbe\xa5\xfe\xfc\xe5\xb5\xc4\x64\x22\xc4\x64\x0c\xf1\x46\x13\xc7\x1b\x4d\x8d\x46\xa3\xc1\x68\x94\xe2\x06\x8b\xc5\x60\x14\x2c\x73\x89\xcd\x6a\xb0\x5b\xe7\xd9\x6d\x76\xdb\x1c\x6c\xb3\x31\x01\xaa\x09\x74\x7a\x42\xbd\x7a\x19\xeb\x91\xc8\xb1\xde\x4b\xda\x38\x4f\x7a\xc5\xad\x6b\xf7\x5e\xb0\x61\xb7\x31\xe6\xf1\x78\xbd\xe6\x40\x9b\x71\xf7\x86\x0b\xf6\xae\xbd\x65\x38\xed\xe1\x1a\xe7\x99\x4c\x2d\x4d\x81\x18\x43\x8c\xa2\xc8\xb2\xa6\x4e\xb7\x3b\xd2\x21\x00\xc3\x44\xb6\x33\x92\x87\x5d\x06\xf7\x4e\x9c\x86\x4b\x26\x0f\xf2\x2c\x61\x79\x96\xf3\xb2\x66\x23\xc7\x9a\x4d\x11\xde\x22\xf0\xac\xb7\xd1\x60\xb6\x18\x0d\x66\x8b\xcd\xcc\x32\x2e\x86\xe3\x05\x6c\x16\xb0\xd3\x8c\x89\xc7\x30\x4d\xd6\x11\x9e\x86\x4c\x1d\xd1\x3a\x3d\x31\x1d\xaf\x47\xa3\xc6\x50\x00\x71\x4a\xc4\x9b\xf5\x46\x8e\xbf\x76\x7c\xa4\xec\x64\x00\x8f\xe9\x98\x3b\x24\x57\xb4\x35\x18\x3d\x7e\x7c\x34\xd7\x19\xab\x40\x3d\x7c\x16\x78\xf5\xfd\x12\x76\xba\x3e\xa7\xd5\x14\x70\xc8\x50\x15\x36\x50\xc2\x49\x47\x5d\x2a\x19\x09\xd9\xa9\x3d\x84\x36\xe9\x65\x52\x41\x67\x22\x15\x74\x72\xe3\xda\x3c\xa6\x1b\xd9\x0a\x32\xa7\xc8\x82\x20\xbf\xaf\xc8\xc2\x08\x20\x05\x14\x56\xd9\x34\x50\x36\xab\x55\x64\x61\x7c\x5c\x90\x27\x90\x2c\xe0\x91\xfc\x98\x20\x2b\xda\x3f\x5d\x27\x86\x2d\xfa\x4b\xea\xad\xb0\x00\x76\xe9\x4c\x4e\x6d\x19\xa1\x5c\xcd\x4c\xba\x1b\x5c\x8c\xdb\x25\xb1\xa5\x3b\x18\x35\x96\xef\x59\x28\x0e\xbd\x6e\x10\x8c\x77\x61\x59\xaa\xbb\xbd\xa6\x11\xbb\xd4\x6f\xfe\x67\x4d\xd0\x69\xf7\xb2\x63\xd0\xb8\xfb\x9a\xdb\xb1\x80\x1d\x92\xef\x6e\x6f\x18\x2c\xcf\xa8\xbf\x56\xf7\xff\xb8\x26\xe4\x90\xbc\x04\x38\xf8\x8f\x6f\x7c\xf3\xdf\x41\xb7\x12\x56\xbf\xe7\x73\x38\x83\x35\xff\x09\x0b\x5c\xb8\xb1\xe6\xf6\x3a\xc9\x2e\xdc\x7e\xcd\x6e\xf5\x8d\x47\x6a\x1d\x8e\x50\xcd\x8f\xe1\x56\xa8\x7b\x46\x80\x70\xcd\xdd\x3e\x49\x12\xfe\xfd\x9b\xdf\x50\x83\x05\x3b\x53\x54\x90\xad\xd5\xa3\x26\x8d\xc2\x41\x55\xf2\x35\x77\xb5\x6f\x99\x60\x11\x7e\x19\x66\x44\xab\x65\x6c\x1d\x03\x1d\x1d\x03\xd0\x41\x4f\x27\x2b\x0d\x96\x27\xe2\xcc\xa7\x1e\x62\x3c\xe2\xe4\x9f\x45\x0f\xc3\x7c\x49\x6f\x69\xdb\xf7\xec\x1b\x33\x44\xcc\x6c\xb4\x7f\xcf\x06\x97\x0c\xe8\xd9\xb4\xbf\x77\xa1\x8c\x98\x05\xef\xc0\xaf\x04\xbb\x5d\xc8\x1f\x28\x6c\x91\xb3\x35\x71\xbc\x29\x35\x30\x90\xca\x3f\x12\xa7\x6b\xc0\xad\x94\x8f\xd0\x8e\x92\x74\x34\x68\xbb\x42\x07\x17\x42\x61\x11\x5c\x6e\x11\xfc\xd8\x2d\x82\xb6\xae\xa7\x33\x25\xb4\xf3\x80\x36\x68\x88\x1d\xb1\x76\x86\x53\x52\x83\x83\xa9\xa1\xa4\xba\x59\xdd\x33\x67\x80\x89\x38\x38\x69\x76\x47\xa4\xee\xb3\x5f\x68\xe7\xdb\xe4\x5a\x62\xb2\xdf\x44\xdf\x39\x0e\x5f\x86\x97\x92\x43\x8a\x7a\xbd\x7a\x04\x6e\x24\x0a\xe5\xfb\x26\x87\x60\x43\x50\xde\x74\x79\x34\x38\x37\xd1\xdd\xe4\x9f\x13\xaf\x6d\x76\x7f\xa4\xe7\xfa\x35\xbb\xd3\x9b\x06\x72\x03\x9b\x40\x19\x4a\x4e\x36\x92\x6f\xa8\xaf\x36\xa9\x7f\x6e\xa6\x7c\xa7\xec\x14\xe2\x72\x1c\x42\x66\x54\x83\xe6\x22\xc4\x24\x29\x4d\xd5\xa0\xed\x67\x20\x88\xec\xc9\x76\xdc\x20\x62\xa7\x8d\x6e\x6c\xa8\x83\x02\xad\x89\xb5\x39\x4e\xca\xe8\xa8\x9e\x4e\x07\xef\x92\xb4\x09\x8e\xdc\x63\xeb\x5e\x1b\xb8\x74\x49\xfe\x7a\xd6\xa1\xfe\x75\xd6\x45\x9f\xf8\xc6\x27\x2e\x9a\xc5\xe4\x86\x92\x6a\xf6\xf8\x6b\xc7\xd5\x6c\x72\x28\xbe\x6a\x7d\x6f\xf4\xf7\xdf\x32\x74\x0e\x77\x1a\xbe\xf5\xfb\x68\xef\xfa\x55\x4f\x07\xd6\x76\xdb\x6c\x4b\x2e\x85\x59\xd0\x8a\x1d\x89\x2b\xb6\xf4\xf7\x6f\xb9\x22\x91\x7f\x5b\x7d\x2d\x39\xa4\x7d\x75\x43\xc9\xe6\x8d\xc7\x3e\xff\xe7\xa3\x27\x80\xf5\xc9\x0e\xed\xf3\x73\xc8\x3e\x75\xe2\xc4\xd1\x3f\x7f\xfe\xd8\x46\xfa\xcd\xe3\x29\x85\x55\xd9\xfd\x74\x6f\xe6\x76\xf1\x9c\x95\x1e\x3b\x40\xa7\xa2\xb4\x73\x34\xa2\x1f\xfb\x29\x0b\x55\x3b\x66\xd2\xfa\xb1\x9e\xa2\x3e\x6a\x47\xb7\x4b\x3f\x6a\xb9\xdd\x2e\x9e\x1d\x39\xe2\x37\x59\x62\xa7\x52\x96\xfa\xba\xa6\x6f\xcc\x32\x35\x59\xf8\x7a\xc7\xed\xb7\xfb\x9a\x9b\x4c\xb3\xbe\xd1\x54\x57\x6f\x49\x9d\x8a\x59\x4c\xfe\x23\x55\xa9\x9a\xea\x6e\xbf\xbd\xae\x69\x7a\x1a\xac\x54\x65\xc3\x2e\x2d\x9b\xb9\xa9\x9c\xad\xd9\x37\xfd\xd1\x4d\x26\x4b\xfd\xd1\xa3\x7e\xb3\x69\x5a\x9a\x92\x4f\x32\xed\x3b\x4f\xa1\x9d\xd5\xfc\x54\xaa\x55\x18\x6a\xe0\x39\xbe\x20\xdd\xb0\x6b\x34\x61\x62\x1a\x3f\xb5\xc8\x22\xe4\x0a\x0c\xd5\x82\x25\x6f\x91\xd6\xe8\x63\x35\x3a\x93\xd1\xa5\x3e\xc1\x12\x37\x95\xfd\xdc\xf2\x78\x3e\xe7\x6f\xf4\x5f\xb8\xc8\x33\xe0\x11\x62\x8b\x17\xf9\x17\x2c\x0a\x04\x16\x7f\xeb\x7b\x2b\x9f\x2b\x70\x51\x61\x30\x39\xa4\x3c\x70\xd9\x13\x4c\x90\x72\x52\x3f\xfa\xdc\xa3\xdd\x05\x36\x6a\xc0\xe4\xf6\x38\x6b\x45\x0f\x9e\x1b\x12\x62\x0d\x1d\xfd\x91\xfd\x9f\x71\xc1\xf5\x95\xcc\x54\x47\x57\x6a\x75\xcb\xbc\xde\xa3\xad\xce\xec\xca\x95\x35\x5d\x79\x25\x9b\xad\x64\xa2\x0e\xa5\x2e\x3b\xd1\xd7\xa5\x73\x50\x17\x74\xeb\x8c\x40\xa3\x6c\xf7\x59\x7d\x64\x69\xc6\xb9\xaa\x2f\x1b\xba\xed\xa6\xf9\x3d\x27\x50\x45\xfb\xa4\x50\x2f\xda\x8d\x50\x38\x61\xd7\x71\x89\xe8\xff\x76\x86\x0a\xee\xfc\xd8\x49\x9d\xb5\xb9\x12\x41\x8d\xf4\x72\x73\x0e\x97\x5b\x57\xdb\xec\x83\xaa\x6d\x14\xdd\x65\xf4\x83\x2e\x88\xd1\xb7\x1a\x89\xa0\x4e\xba\xf8\x89\x46\x8a\x73\x94\x3e\x1b\x09\x04\x42\x73\x7b\x62\x75\x06\x66\x71\x4c\xf4\x80\x2c\xb9\x9c\x86\x45\x17\xfa\x1b\xfd\xf9\x5c\x7c\xf9\x50\x12\x06\x75\xce\x2a\x73\xc9\x05\x6b\x5e\xf8\x16\xec\xd4\xb7\x5a\x83\x29\x75\xbc\xfb\xd1\x6f\x1d\xbc\xeb\x69\x80\x5e\x12\x64\x9e\xb8\xec\x81\x13\x3b\xe1\x7a\xd7\x67\xf6\x47\xfa\x3b\x1a\x62\x42\x68\x2e\xf6\x88\xb5\x4e\x8f\xdb\x04\x81\xd4\xa0\x82\x15\x4f\xbc\x39\x68\x64\x57\x66\x5d\xed\x24\x1a\x8c\xb8\x7b\xe7\xb5\xac\x4e\x75\x39\x96\x25\x92\x43\x94\xb1\x1a\x58\xba\xc4\xe6\x09\xac\x5d\x95\xcd\x46\x0a\x0d\x9b\x57\x52\x83\xdd\x0b\x3e\x79\x27\x3b\xb4\xc3\xe5\xec\xea\x3b\x71\xd9\xa5\x27\x7a\xe6\xdf\x74\x5b\x28\xdb\xb7\xca\x99\x59\x4a\x7c\x56\x9f\x5d\x36\x0e\xa2\x4a\xfc\xff\xc2\xb8\x62\x8a\xcd\x90\x0c\x35\xf0\xed\xd0\x40\x65\xc4\xbc\x5d\x97\x7c\xda\x29\x7c\xaf\xee\xed\x8e\xfe\xa7\x4b\x1b\x65\xd4\x73\x15\xab\x5e\x3b\x5b\xd8\xb9\xa4\x75\x5f\x81\x94\x39\xe2\x72\x53\xaa\xaf\xb8\xed\xfc\xdc\xb4\x6e\x4e\x9e\x35\x12\xb0\x92\xcd\x2a\x5a\x97\xe7\x67\xee\xf2\x4b\xcb\x03\xe3\x22\xdd\x95\x61\x4f\xe5\x78\x3c\xd7\xa0\x5d\xf7\x21\x46\x67\x69\x28\x4f\x6b\x9f\x24\xea\x41\xbb\x28\x55\x0f\x54\x09\x80\xf2\x7e\xb4\xff\x22\xa3\x8f\x20\x9c\xb0\xd3\xcd\x6a\xca\xae\xd1\xbc\xae\x78\x3a\xa3\x5d\xe1\x12\xea\x04\xd7\x41\xf7\x1e\x1c\x4f\xe5\xac\x91\x94\xbd\x08\x58\x4b\xb5\xbf\x2a\xac\x48\xb5\x5d\x5c\x36\x9b\xff\x80\x5e\x6f\xef\x2a\x77\xba\x52\xd8\xc5\x17\x3a\x3b\x3d\x57\xeb\xec\xf4\xd2\x1b\x6f\xaf\xea\x6c\xfa\xed\x74\x2f\xc0\xd9\x35\x2f\x7c\x6b\xf1\xf9\x46\x6d\x48\x1f\xb4\xa4\x97\x36\x6d\x7e\xbe\x3e\x52\xfd\xfc\x07\x8f\xd4\xc2\xb8\x9e\xbe\x17\xaa\xa7\x54\x11\xb5\xc7\xcc\xa4\x0b\xa6\x87\x3c\xe7\xa8\x07\x70\xc5\xfb\x41\x8b\xa9\xb2\xcf\x64\x51\xc4\xab\x9a\x9e\x93\xe5\x0d\x52\x5a\x52\x8f\x6f\x90\xa4\x0d\x30\x2a\xa5\xa5\x0d\x92\xf4\x1c\xfc\xd5\x1b\x01\x34\x93\xc5\xe6\x73\xba\xa1\xa2\x96\x3e\x2d\x6d\x50\x8f\x4b\x92\x16\x78\xee\x83\x6d\x38\x69\xd9\x50\xb2\x03\x80\xda\x42\x3a\xea\xa1\x64\x33\x4a\x8b\xe8\x8a\x67\x20\x53\x69\x71\xc8\xb2\xf4\xd9\x7a\x61\x54\x13\xa5\x10\xff\x5a\x28\x2a\x8c\x6e\x00\xa1\xba\x68\xdb\xd3\xb4\xf4\x85\xc2\x78\xcb\x05\x85\xd1\x0d\xea\x39\xed\x34\x0b\xe5\x8a\xea\x36\x9a\xa0\x17\xa5\x1f\x4a\x56\xb5\xd4\x39\x43\xe3\x74\x7b\xcd\xb3\x6a\x5e\x7a\x19\x88\xd5\xa5\xda\x41\x4b\x2b\x9d\xa3\x2e\xf9\xf3\x95\xab\x83\x36\x57\x49\x39\x54\x37\x24\x75\xb8\x81\x16\x6b\x1a\x06\x0a\xcb\xcc\x58\x73\x89\xb6\xca\xd9\xe5\xda\x56\xee\xe5\x19\xc6\x00\x9a\xfa\x20\x3b\x38\x33\xfc\x04\x7b\xaa\xec\x1e\x44\xe0\xe3\x3a\xba\x73\x26\xed\x8e\xa4\x33\x7d\xd0\x0f\x5c\x24\xea\xe0\x93\x11\x2e\x5a\xdc\x92\x37\x88\x10\x8a\x88\x98\x17\x81\xd7\x76\x5a\xe9\x48\x34\x41\x6f\xf1\x9c\x1f\x9c\x2e\x6d\x79\xd0\x6e\x71\x2e\xb7\x4b\xc4\x56\x2d\x7b\x24\x1a\xe1\xb5\x9f\x96\xba\x0f\x52\xe9\x4c\x1f\x0e\xb9\xa8\xde\xbf\x1f\x12\xae\x74\xd4\x45\x53\x70\xee\x88\x08\xda\x1b\x1a\xb4\x47\xa6\xb5\x07\x52\xea\xcf\xc5\x6b\x33\x87\x8b\xd7\xf6\xc6\xda\x66\x30\xa2\x11\x23\x54\x05\x87\xd7\x1f\xe2\xce\xb8\xdc\x11\x9e\xe3\x5d\x7c\x3b\x8e\x6a\x4b\xba\xcb\xed\xc7\x19\x17\x9f\xa6\xd4\x89\x56\x2e\x57\xa6\x81\x73\xf0\x6e\xce\x95\xe1\x0a\x4c\x21\x70\x73\x2e\xbe\x81\x0b\x51\x3e\x50\x26\xad\x03\x59\xc7\xfd\x98\xe7\xe8\xdd\x50\xdc\xa5\x73\x8b\x28\xde\x5f\x3c\x4d\x5d\x51\x65\xf4\x7b\xda\x46\xdc\x95\x49\xa7\xb8\x68\xb2\x1d\xa7\x13\xf1\x34\xcd\xab\xb5\x12\xe7\x6c\x88\xf6\x41\xa6\x8f\x44\x28\x3f\x8e\xe7\xb4\x3b\xda\x74\x4f\x63\xc1\x45\x95\x24\x42\xae\xb4\xb6\x27\x8d\x64\x5c\x19\xfa\xf2\x74\x86\x2e\x0c\x7d\x10\xe9\x80\x64\x2a\xda\x0e\xba\x94\x36\x1a\xcf\x34\xb4\x43\x28\xad\x65\x75\x65\xf4\x53\x3a\x49\x3b\x24\x1d\xa2\xec\xe6\x48\x34\xad\x9d\x23\x24\x4d\xd5\xdf\xa3\xe9\x02\xee\x23\x2f\x12\x77\x24\xda\x8e\x29\xba\x65\x24\x1d\x8d\x88\x8c\x16\x6a\x87\x94\x9f\x52\x7b\x3c\xe7\x76\x70\x6e\x47\xb5\x05\x0b\x99\x8f\xad\x1c\x66\x59\xe0\x6c\x62\xa4\xc1\x8e\xdd\x84\x78\x08\xb6\x98\x81\x33\x8a\xd8\x64\xe2\x00\x5b\x31\x10\xc2\x72\x06\x1e\x08\x47\x38\x4c\xcc\xc4\x6a\x33\x71\x46\xc2\xb3\x60\x75\x10\x43\x92\x67\x81\x07\xc1\xc7\x10\x2f\x61\x79\x1e\x03\xc7\x32\xc4\x2c\x33\xbc\xd1\xcd\xb1\x8d\x35\x41\x8e\xe3\x2d\x04\x13\x23\x58\x78\x12\xb2\xb2\x02\x63\x34\xc9\xac\x48\x8c\x16\x23\xc3\x58\xac\x06\x13\xd8\x6d\x06\x30\xb2\x06\x03\xf1\x99\xe4\x5a\xbe\x96\x63\xc1\x6c\x12\xb0\xc8\x61\xc1\x04\x84\x63\x59\x03\xe1\x03\x26\xc6\x63\x67\x19\x06\x08\x23\x92\xf6\x59\x1c\xc7\xda\x70\x83\x81\x15\x39\xde\xed\xc0\x3c\x66\xac\xa2\xc1\xc6\xdd\x77\x21\xcf\x32\x98\x98\x8c\x1c\xb4\xc8\x98\x08\x60\x03\xc2\xf3\x3c\x0b\x98\xd8\x05\x21\xc8\x61\x22\x59\x18\xc6\x62\xc0\x6e\x00\x02\xa4\x86\x00\x66\x38\xec\xb5\x62\xc2\x62\x6c\x30\x72\x40\x4c\xa2\x03\x73\x36\x83\xd1\xc5\xb1\x1c\xc6\x82\xc5\x41\xd8\x5a\x83\xc9\x62\x67\xad\x3e\xbe\x51\xc6\xac\x99\xc7\xac\x97\xe5\x80\x38\x0c\x62\xbd\xc4\x12\x8c\x19\x23\xe6\x00\x1c\x98\x75\xb1\x44\xc0\x40\x30\x18\x39\x6c\xb6\xc8\x3c\x30\x1c\xc7\x37\xf0\x82\xcc\x02\x47\x2c\x0c\xd6\x0a\x0f\x84\x00\xdf\xc2\x59\x79\x16\xb3\x1e\x52\xc3\x12\x03\xe1\x59\x13\x36\x1b\x78\x03\x68\xff\xac\xbc\xc9\x04\xa2\x9d\x71\x72\x3c\x03\x06\x1e\x8c\x3c\xcb\xb2\x46\x8b\x81\x67\xeb\x09\x8f\x09\xe3\xc2\x76\x42\x24\xc1\x64\x23\x16\x23\xb1\x63\xab\xcb\xfe\xdc\xcb\xf7\x12\x99\x48\x1c\xf0\x46\x1b\xc1\x26\xc6\xcc\xf1\x5a\x57\x61\x70\x5a\x59\x8b\xd1\xcc\xb1\x18\x78\x91\x25\x56\xa3\xc8\x08\x98\x70\x18\xcb\x98\x21\xbc\x5c\x8b\x19\x9b\x0d\xce\x32\x50\x52\xbf\x07\x76\x30\x59\x80\x37\x70\x9c\x41\xc6\x2e\xc0\x2c\xeb\x02\x9b\x80\x39\x1e\x33\x40\x8c\x1e\xc2\x5a\x18\xcc\x73\xac\xc9\x84\x01\x58\xc0\x18\x58\x8e\x01\xc6\xc6\x31\x46\x03\x66\x8d\x0c\x67\x94\x09\x27\xb2\xbc\x5d\x30\xd8\x18\x83\x93\xa3\x72\x00\xcc\xba\xac\x35\xac\xc1\x28\x08\x46\x16\x44\x2b\xe1\xdc\x5a\xc7\x5a\x2d\x8c\x95\xf5\xb0\x1c\x98\xc0\x63\x00\x89\xc7\x8c\x91\x61\xc0\x6d\x31\x43\x0d\x58\x0d\x22\x58\xac\x0c\x66\x79\x23\xcf\x30\x60\x62\x80\x65\x30\xe3\x60\xd8\x1a\xc6\x48\x80\xc1\xbc\xc1\xc2\x60\x22\x60\xab\x17\x30\x36\x82\xc8\xb3\x36\x23\x43\x38\xce\xc2\x11\xd1\x00\x30\x7c\x17\x0f\x60\xe3\x38\x83\x19\x7c\x76\xc6\xcc\x63\x91\xb0\xb5\x10\x88\x32\x60\x69\x23\x24\x66\x00\x6c\x36\x72\x6c\x88\xe3\x7c\x46\xcc\x8b\x5a\x1e\xec\x68\xae\x61\x58\x27\x43\x18\x06\x78\xa7\xcd\x85\xb9\x5a\xa7\xd1\xd0\xc8\xf1\x02\x67\xc2\xd8\x4e\x18\x16\x70\x03\x23\x1b\x40\x90\xcc\x84\x93\x38\x86\x35\x78\x30\xa9\xb3\x06\xc1\x68\x30\x72\xbc\xc4\x18\x3c\xc4\x88\x0d\x60\xc4\x40\xea\x0c\x8c\x4d\xb0\xf0\x00\x32\xb1\x1a\x08\xc1\x8c\xa1\xd9\x66\x0a\xda\x6d\xd8\x4a\x00\x80\x61\x00\x13\x62\xe4\xcc\x02\xd8\xd9\x5a\x89\x30\x04\xf3\x98\xb0\xa2\x29\xc6\x10\x6c\x37\xf3\x06\xa3\xd1\x40\x24\xd9\x08\xac\x81\x91\x6d\x46\x8e\x61\xcd\xc4\x86\x2d\x26\x83\x81\xe7\x39\x6c\xb0\x31\xac\x01\xcc\x0c\x16\xcc\x46\x8e\xc7\x00\xd8\xc4\xb1\x93\xb7\x34\x7e\x82\x10\xcc\x03\x6f\xd1\x4a\x6b\x20\x1c\xd6\x46\x1a\x01\x3b\x0b\x46\x16\x73\xac\x83\xb0\x35\x1c\x47\x38\x33\x36\x12\xc6\x46\x18\x96\x98\xe2\x42\xbd\xbd\xc6\xea\x62\xf8\x5a\x03\xb5\x8e\x70\x4e\x39\xb9\x03\x74\xcf\xe4\x44\x1d\xe5\x3d\x93\xb1\x60\x91\x9b\x4a\x66\xc0\x0f\xa0\x6b\x4c\x20\x1b\xa2\xbe\x28\x1c\x3c\xeb\x74\xeb\xee\x28\x74\xd2\x0a\x7f\x3e\xbf\x2e\x9c\x4a\x46\x47\x23\x11\xfc\x44\xf4\x01\xfc\x86\xbb\xe3\x0f\x1f\xd3\x8d\x81\xe6\x1c\x6c\xb5\xd9\xd4\x9f\xff\x0b\xfb\xf1\x9b\x8d\x56\x7b\x41\x16\xf2\x9b\xfc\xba\x70\xf8\x8a\xc6\x74\x2a\x82\x9f\xd8\xf2\x00\xdc\x19\x9d\x77\xdb\x63\x3a\x53\x29\xe8\x37\x37\x98\x9f\x18\xbf\x9c\x6c\x58\xe4\x40\x95\x3e\x39\x75\x3b\x8e\x5a\xd4\x82\xba\x11\x0a\x07\x53\x41\x28\xfe\xce\xe3\xcb\xb5\xfa\x9a\x41\x1a\xed\xaf\x2a\x0c\x9a\x44\x98\xe2\xeb\xe3\x0f\x85\x04\x49\x61\xfa\x41\x51\x26\xb3\x45\xb6\x97\x37\x12\x81\xdf\x9e\xeb\x42\xdb\x7b\xb3\x53\x0a\x7b\x33\x8b\xa8\x9e\xaa\x8b\x2f\xc1\xdc\x45\x52\x76\xdd\x57\x54\x9c\xbd\xd9\x5e\xaf\xca\x14\xdd\x6e\x0a\xc9\xaa\x5c\x6f\xb7\x37\xb3\xa8\x99\xf9\x69\x53\x9d\x2a\xe7\xbd\x14\xd8\x0e\xc9\x5e\xf8\x2d\xbc\x53\xd7\x14\x2d\xe3\x60\xd2\x9e\x73\xa3\x5a\x6a\xbb\x3a\xad\x0d\x82\xce\x22\xe6\x54\xc8\x19\xa4\x7e\x08\xaa\x45\xab\x58\xc1\x48\x45\x4c\xc1\xb7\x0a\x1e\x8b\x78\x21\xeb\x8d\x8c\x4c\x21\x06\xbd\x8f\x36\x0d\xc0\x88\xce\xc2\x83\x91\x81\x4d\x2c\x52\xf2\x48\x0d\xe8\xec\x94\x31\xad\x6a\x63\x8a\x02\xe3\xaa\x02\xca\xc0\x26\x1d\x14\x7c\x53\xa5\xde\xe9\x22\x84\x8c\x38\x93\x76\x17\xd9\x7b\xd1\x48\x3f\x18\xe9\x0a\x54\x64\x3c\xa5\xeb\xc1\x08\x7c\xd1\x89\x91\x8e\x99\x65\x05\x23\xe5\x36\x14\x48\x7b\x7a\x97\x25\xea\x43\xb0\xf5\x9e\xba\xa6\x68\xd1\x61\xd0\x3d\xea\x43\xea\x43\xf7\x68\x0d\x54\x70\x06\x74\x0f\x6c\x55\x1f\xba\x47\xf6\x5a\x2c\xb1\x88\x17\x72\x34\x0d\x6c\x85\xad\x34\x0d\xe4\xbc\x11\x8a\x00\x46\x7e\x3d\x73\x3e\x7f\xb4\x2a\x97\xcc\xea\xb9\xb4\x14\xf4\xdd\x34\x85\xf6\x6e\x56\xd6\xf5\x2a\x11\xc5\x39\xb7\xa3\xd9\xa8\x0b\xcd\x45\xab\xd1\x06\xca\xcd\xd7\x36\x28\x36\x9d\x93\x90\xe1\x9c\x0e\x28\xe9\xb4\xb3\x89\x38\xf5\x61\x99\x88\xfb\xd9\x22\x97\xae\xe8\xbd\x9a\x42\x47\x50\x75\x25\xaa\x40\x0c\x89\x38\x2e\xa4\xc0\x2b\x1f\xb9\xf4\xb6\x55\xbb\xf6\x71\x83\x37\x74\xcf\x1b\x60\x19\xe5\xbe\x1b\x27\x8f\xdf\x78\x1f\xef\x0c\xa4\x17\x6e\xef\x35\x0d\x0c\xdf\x76\xc7\x6d\xc3\x03\xa6\xde\xed\x0b\xd3\x01\x27\x3f\xa9\xe3\xf2\x91\x75\x05\xed\x58\x12\xdc\xb5\xea\xb6\x4b\x1f\x59\xc9\x0e\xcc\xeb\xbe\x61\x90\xdb\xa7\x2b\x3f\x62\x85\xbd\x79\xe5\x72\xb8\xa4\xb9\xc5\x1d\xae\x3b\x9a\x17\x6f\x38\x7a\xf4\x86\xd4\xf6\x3d\xdb\x36\xcf\x8b\xb5\xa4\x5a\x5a\x52\x2d\xb1\x79\x9b\xb7\xed\xd9\xce\xc6\xa9\x6e\xa1\x5a\x5f\x70\x95\x9d\x3f\xb9\x7c\xe5\xcd\xec\x9e\xa3\x75\x61\x77\x4b\x33\x8c\xd2\x9b\x45\x3b\xb5\x7b\xb8\x5d\xec\xbb\x28\x88\xe6\xa1\xcb\x0a\x68\x29\xa1\x06\xde\xcf\xd0\x6d\x5b\x3b\x89\x96\x81\x5d\xd2\x50\x04\x7e\x29\xc6\x65\x8a\xaa\x41\xc4\x9d\x46\xba\x25\xbe\x3e\xcf\x44\x0b\x18\x00\x05\xe3\x31\x97\xd3\xc1\xbb\x69\x88\x7d\xda\xf7\x8a\x2f\xd6\xec\x27\x01\xb3\xcc\x77\xc6\xac\x35\x5e\x4b\x3d\x09\xfa\x5e\xae\x6d\x8a\xf9\x8e\xf9\xf2\x73\x7d\x2f\xfb\x62\xd1\xba\x63\x3e\xdf\x2b\xb5\x4d\xd5\xa9\xc8\xc1\xb5\xc7\x56\xdf\x70\xe3\xea\x97\x57\xaf\x5f\xbf\xee\xa6\x1b\xd6\xbc\xb2\xa6\xea\x1a\xb2\x31\xdf\x2b\xbe\x00\xa9\xb7\x78\x6b\xac\xb1\x4e\x5e\x36\x07\x48\x7d\x73\xcc\xf7\xa3\x5a\xef\x7d\x3e\xfc\x56\xcc\xf7\x23\x5f\xed\x7d\xbe\x68\xcc\xf7\x4a\x6d\xfd\xf4\x44\xf9\x37\xdf\x5d\x7d\xdf\xea\xb5\x3f\x5a\x7d\xc3\xcd\xeb\xd6\xaf\x5f\xf3\xca\x9a\xe9\x97\x05\x8c\x4b\x85\x62\x7b\x23\x7d\x5c\xa0\x54\x92\xea\xaa\xa2\x44\x9c\x71\xeb\x62\x58\xde\x0f\xbc\xf2\xe6\xc9\x89\xdc\xb3\xea\xfb\x77\x5d\x87\xa1\xf5\xb5\x4f\x03\x74\x2f\x1c\x19\x3d\xde\xf4\x91\xc7\x41\x39\xf9\x26\xf0\xcf\x1e\xfa\x79\xda\x67\x7d\x0d\x5a\x9f\xbe\xab\xef\xf8\xe8\x60\xbf\xff\x34\xc2\xe8\xda\x29\x85\x13\xa8\x7d\x7d\x10\xa1\xb0\x0e\xb5\x94\xd1\x35\xfb\x0b\x9a\x36\x2d\xda\x32\x10\x84\x68\xca\x1e\xb2\x3b\xd9\xbf\x75\x2e\x18\x9d\x50\x46\x17\x74\xc2\xdf\xb2\x45\x68\xad\x88\x37\xab\xbe\xad\xbe\x8b\x7f\xa0\xbe\xeb\x50\xd6\x5f\x78\xf0\xe0\x85\xa4\x06\xee\x2e\xe8\xa4\xed\x9e\xaf\xae\x86\xa7\xea\xc3\x70\xb7\xba\x3b\xac\x4f\x3b\x50\xd0\xcd\xe4\xd1\x72\xb4\x11\x8d\xa2\x1b\xd0\x6d\xe8\xce\x32\xe6\x3f\x0b\x94\xbf\x48\xe7\x38\x4a\x9c\x8b\x85\x4f\x9d\xd2\xec\x09\xaa\x98\x4b\x75\x34\x1b\xa8\x0f\x19\x2a\x8e\xa6\xd4\x36\xef\xaa\x87\x42\xa7\xbb\x5d\x3c\x9b\xa6\x30\xdc\x74\x3b\x91\x88\x93\x3e\x0a\x19\xc4\x8b\x14\x23\x08\xdc\xa9\x64\x3f\x44\x29\x8a\x3b\xf0\xf5\x00\x51\x70\xf2\x14\xcc\xbf\x1e\x20\xa3\xbd\x95\xe8\x8c\x33\xb8\x02\x26\x7c\x84\xf5\x2b\x82\xcd\x2e\xe6\x97\x5f\x65\x60\x44\x86\xdf\xb2\xfa\xd0\xbd\x77\xac\xbb\xc8\xcc\x6f\x59\x75\xe8\xbe\xd5\xf3\x8d\xc2\x4d\x37\x09\xc6\xf9\xab\xef\x3b\xb4\x6a\x0b\xcf\x36\xb5\xac\x3d\x7c\xef\xa1\xd5\x5b\x78\x46\x64\x0c\x57\xe1\x67\x44\xbb\x4d\x50\xfc\x2c\xf1\x4d\x6c\x6c\x8f\xaf\xdc\xb8\x6d\x69\x54\x3f\xb5\xaf\x8c\xb7\x47\x97\x6e\xdb\xa8\x9f\x40\x1c\x09\x8a\x2b\xbc\x44\x64\x31\x03\x3f\x1e\xc1\xe3\x4a\x1e\x8d\x19\x31\xcb\x88\x8c\x97\x8c\x28\xf9\xbf\x7f\x09\x9b\xb1\xbe\x48\x7a\xd5\x6b\x1c\x8d\x21\x5b\x96\x37\xc0\xad\x03\x0c\xcc\x9e\xb5\xec\x63\xa9\x35\xcb\xd7\xdc\x3c\x74\x57\x6a\x4d\xbd\x60\x5c\xb2\xc4\x28\xd4\xaf\x49\xdd\x35\xd4\x7d\x45\x74\xc5\x9a\xe4\x5d\xcb\x66\xcd\x06\x66\x00\x6e\x35\xf0\x59\x5b\xa8\xd1\x71\xa4\xf9\x50\xa2\xbb\x51\x3b\xe4\xbb\x13\x87\x9a\x1b\xe9\x01\x8f\xcd\x31\x37\x3a\x0c\x1d\x5e\x62\x63\x30\x81\xdf\x05\x70\x36\xab\xae\xdc\x3d\x62\xc0\x0c\x63\x63\xbc\x6a\x2e\x0b\x27\x8e\x10\x46\x97\xc3\xe8\xeb\x46\x3d\x6a\x40\x61\x94\x40\x3d\x55\x72\x98\xc2\x0a\x59\xb4\x56\x71\xda\xd3\x09\x1e\x82\x46\x08\xca\xda\x22\x52\x70\xd1\x99\x4c\x97\x2e\xb8\xb1\xa2\x44\x28\x3f\x1e\xeb\x8c\xf9\xe0\x84\x6f\x24\x06\x63\xb1\xce\xf9\x3d\x8a\xfa\x3a\xb4\xe4\xe9\xf1\x79\xe8\x51\x29\x32\x01\x46\x31\xf2\x13\x3d\xc8\x94\x20\x05\x20\x50\xf0\x3d\x01\x27\x7c\xb1\xce\x98\xfa\xf5\xd8\xeb\xea\xeb\xf8\x49\xf5\x75\xf5\x51\xe8\x81\x31\xea\x28\x53\x01\x14\x1b\x99\xfc\x3b\xa3\xe8\x57\x94\xa7\xcd\x4c\x1d\x62\xf7\xb1\xfb\x28\x0a\xb4\xa3\x88\xaa\xa1\x23\x77\x14\x14\xf4\x0b\x56\x1b\x40\x99\x4d\xc9\x8a\x6b\x67\x55\x7a\x76\xdf\xa7\xf7\xdc\xbe\x6d\xf2\x6f\xbb\xdf\x38\xf9\xe9\x6b\xf1\xc5\xa6\x5e\x9b\x60\xca\x3f\xb2\x62\xc7\xe8\x7d\x43\xc4\xd0\xbf\x2a\xbb\xa6\x3f\xff\x4d\x6f\x43\x5d\xa4\x06\x1e\x34\xf5\xd9\x2c\x26\x75\x47\xff\x35\xab\xd6\xf7\xe2\x05\xdb\x1e\xd8\xf3\xe9\x6d\xc4\x70\xed\xa7\x4e\xfe\x72\x77\xfe\x11\x93\xc5\xd6\x6b\xc2\x9b\x97\x1d\x1f\xbd\x6c\x68\xf2\x6f\xfd\x6b\xb2\xab\xfa\xf1\x02\x4f\xa4\x2e\x50\xab\xee\x30\x59\x6c\x7d\x26\x78\xb0\x77\xfd\xaa\x6b\xfa\xf3\xdf\xdc\x32\x4d\xb7\x2f\x88\x66\xa3\x05\xba\x8f\x0f\xaa\xcf\x47\xfd\xc7\x94\xed\xfa\xed\x89\x22\xcb\xab\xda\x06\xb5\xda\xe6\xce\xad\x51\x69\x0a\x41\x79\x44\x14\xc5\x61\x52\xff\xcb\x34\xcb\xaa\x4b\xe4\x14\xa5\x33\x46\xb2\xb1\x4e\x55\xa9\xb0\x0c\x56\x4a\xbe\x49\x69\xf3\x7b\x7c\x31\xea\x9c\x48\x11\x67\x9b\xa0\xc6\xe4\x28\x1a\xf6\x4f\x20\x1d\x29\x02\xa3\x0a\xe9\x8e\x3c\x49\xef\xb2\xd4\x6b\xa9\xfa\x96\x6f\xe4\xfc\x38\x7c\x95\xe2\x75\x66\x64\xba\xd9\x8a\x2e\x9f\xa3\x72\x2d\x1d\xef\xf8\x1f\x46\xf6\x9e\x8e\xf3\x77\xae\x70\x05\x7a\xf7\x6f\x67\x0a\xd2\x35\x3e\xc7\x23\x36\x5b\x90\xaf\x45\x51\x46\xa3\x68\x8a\x16\x6c\x52\x51\x6a\x58\xf5\x76\x74\x8e\xf8\xb3\x51\xa5\xa9\xdc\x50\xff\x63\xdf\xad\x94\xb4\x9d\x51\x66\x88\xac\x0c\xbf\x42\xb3\xc1\x3d\x3a\xc0\xf0\x58\x09\x48\x99\xfc\xba\x3a\x06\xfe\x52\x81\xb2\xac\x35\xab\x95\xda\x96\xfe\x0d\xf9\x51\x0f\x1a\x42\x1b\xd1\x15\x68\x1f\x42\x2c\xfd\x0a\x32\xfa\xd7\xc1\x47\xfb\x70\x26\xd5\xc0\x85\xa8\x23\x2b\xde\x0f\xb2\x33\x48\x99\xae\xba\xbc\x24\xda\x47\x85\xc3\x0e\x11\xf3\x89\xd4\xd9\x40\xe4\xc1\x54\x22\xa9\x51\x9b\x1c\x1f\xcd\x24\xec\xe7\x6d\x84\xfd\x57\xae\x1c\x1d\xe8\x9a\xdd\x55\xd7\x72\x99\xd7\x30\xbb\x51\xb6\xcd\xb5\x8d\xc2\xb2\xcd\x89\x1e\xac\x1e\xe7\x3a\x06\x06\x3a\xea\x6a\xda\x43\x6b\x3d\x9b\xe7\x2c\xd9\x36\x7f\xd5\x02\x38\xc8\xfe\x5e\x6f\x07\x49\xd4\x1b\x4a\xfd\xd2\xe5\x80\x0d\xcd\x8b\xee\x18\x65\xdf\xae\xbc\x53\xd9\x5a\x6b\x86\x37\x0e\xac\x6f\xab\xf3\x65\x0d\x9d\xa6\x79\x4d\x12\xe0\xd4\x89\xf5\xd7\x5a\x96\xe2\xec\xc9\x46\x29\xb1\x26\xd9\xd2\xea\xae\xa9\x9d\xd3\x9d\xe8\x5a\xbd\x28\xbe\xba\x3d\x53\xd3\xa3\xfe\x8b\xde\x66\xa2\x24\x93\xeb\xb7\x6e\x6d\x7a\xb8\xc9\x62\x0f\x0f\x1d\x54\xaf\x50\xf7\x97\x6e\x54\xb5\x2b\xa9\xb0\x7f\x4a\xa1\xed\x74\x2e\x9d\xa6\xdc\x18\xd6\x8d\x63\xd2\x3a\x28\xac\xee\x40\xa2\x03\x0a\x0b\x5b\x49\x38\x40\x82\x05\xb4\xdc\xa2\x34\x4e\x37\x68\xd1\xe8\xe6\x54\x46\xd7\x56\x72\x17\xb0\xde\x52\xc9\x68\x84\xa3\x86\xca\xef\x53\x2d\x46\xf8\xae\xcf\x3d\xeb\xb6\x8f\x02\x13\xdf\x33\x70\xb5\xc9\x2c\xb2\x96\x35\x62\x3c\xb5\xfe\xa6\x6b\xe6\xcf\x1b\x18\x78\x7d\xc1\xce\x39\xe1\xb7\xe1\x93\x7c\x93\x7b\x56\x78\xf1\xf0\x92\xe1\x9b\xaf\x59\x79\x67\x97\xd5\xa0\xed\x1b\x77\x58\xfd\x56\x36\xd4\xd6\xd2\xd7\xbd\x24\x3b\xb8\xac\xad\x63\x65\x03\x56\xca\xbe\xf7\xb2\xa1\xb6\x2d\x17\x7d\x45\x39\x28\x5b\x1a\x23\xc3\x37\xf7\x48\xb5\x84\xc3\xf7\x77\x6e\xe8\x9e\xb3\x7e\xc9\xbc\x79\x7d\x8e\x76\x9f\x67\x0a\x45\x53\x57\x6f\xef\x9c\x15\x6a\x9f\x25\x39\xdd\x31\x9b\xc5\x20\x0a\x57\xcc\xf2\x47\xc2\xad\xb8\x61\x69\xc4\xd0\x15\x6e\x74\xba\x6a\xbd\x3d\xbd\xf3\xd7\x2c\xa9\xab\xe0\x8b\x6e\x45\xd7\x22\x24\x47\x3a\x74\x20\x5c\x5a\xa7\x78\x86\x77\x3b\x39\xbd\x41\x5c\x4e\xb7\x5c\x51\x5b\xbd\xc6\xed\x7a\x93\x59\x21\x9a\x49\xb8\x5d\x19\x77\xa9\xb1\xb4\xf4\x2e\xd9\x55\x6e\x39\x5d\x86\x95\xb2\x27\xa3\x91\x6a\x5c\xc3\x59\x61\x03\x11\x6a\x7b\x92\x87\x1a\xd6\xad\xba\xce\xdf\xe9\x07\xdc\x93\xed\x91\x05\x00\x91\x6b\x0b\xf5\xae\xbf\x70\xe7\x05\x9d\x2d\xb3\xec\x8d\x76\x27\x6f\xe5\x18\x56\x6e\x68\xd9\x26\xe2\x35\x2f\x0d\xdd\x20\x71\x4c\x5b\x74\x09\x67\x25\x06\x91\x73\x5a\xbd\x91\xa5\x83\x97\x5f\x79\xdf\x63\x7b\xf6\xf6\xf4\xba\x6c\xf6\x1a\x76\x9d\x24\x96\xdd\xa8\xb3\x41\x8c\xd7\x03\xc3\x13\x06\xb0\x98\x35\x1a\x6b\xc4\xeb\x85\x28\xf7\x9f\xea\x5b\xfb\x96\x77\x07\x3b\x7c\x52\xb0\xd1\xd7\x39\x67\xc9\xa7\x56\x6c\x39\xb6\xae\x7b\x9e\x33\x04\x98\xac\x33\x11\x01\x47\x04\xde\x63\x01\x33\x67\xf5\xf2\x31\xb3\xac\xde\xfe\xdd\x2b\x87\xda\xe7\xce\xe9\x0a\x04\xdb\x3b\x06\x87\xf6\x0e\x3f\x04\xcb\x4e\xd5\x34\x9e\xb9\xa5\xd8\x37\x12\x42\xa6\x92\x0e\x47\xb5\x4f\x81\xbb\xd1\x49\x1d\x31\xa2\xb2\xee\xf6\xaa\xeb\xea\xb6\xf9\x3f\x7d\x5d\xfd\xbe\x6a\x1f\xa1\x18\x15\xf1\xfb\xa8\x46\x74\x45\x78\xfa\x1d\x15\x9d\xfb\xde\x87\x4f\x59\x19\xd6\xb6\xbb\x54\x17\x81\xcd\x0e\x6c\x2a\x63\x1a\xc2\x5d\xa5\xa0\x5a\x0e\x12\x71\xa6\xd8\xf3\x26\xa8\x78\x18\x2c\xaf\xf4\x30\xaa\xcd\xc3\xb5\x53\x9f\x2c\xe0\x51\xc8\xd4\x5e\xb2\x05\x25\x10\x32\x42\x14\x1a\xa9\xbe\x77\x47\x09\xc7\x34\xec\xd6\x66\x8a\x7e\x80\x73\x9c\x99\xcf\x41\xf8\x72\xf5\xe7\xb8\x59\x3a\x73\x46\x4a\x4b\x2f\x48\x12\xcb\x69\xe7\x33\x2f\x6e\xd9\xe2\xf7\x6f\xd9\xe2\x87\x7d\xcf\x3f\xdf\xd3\xf3\xfc\xf3\x3d\xe4\x97\x85\x98\xfc\xa7\x0b\x01\xf2\x4d\x9a\xf7\xf5\xb4\x96\x57\x7a\x41\x4a\x6b\x79\xa5\x17\xee\xa5\x37\xfd\x5b\xd4\x49\x9a\xaf\xe7\xf9\xfc\xa6\x42\x0c\xf6\x17\x02\x94\xf7\x90\x2d\xd1\xff\x36\xe4\x41\xcb\x2a\x24\xec\x41\xbb\xbe\xc5\x2b\x99\xe5\xd8\x1d\x22\x13\x09\xe9\x0a\x11\xf4\x18\x6a\xe0\xf4\x8d\x9f\x3d\x19\xe9\x23\xfd\xd0\x07\x14\x1e\x23\x51\x36\xf6\x56\x7f\x08\xca\xa7\x05\xe3\x77\x8d\xac\xae\xda\x0f\x43\x06\x59\x0c\x5a\xa2\x44\xdb\x94\x6a\x3b\xd9\x2c\x89\x5a\x82\xa2\x6c\x88\x78\x01\x18\xa3\x2c\xbc\x20\xf7\xd7\x8e\x45\xbc\x0c\xf2\x46\x74\x5b\x00\xac\x00\x32\x7e\xd7\x28\xe4\xff\x89\x5e\x32\xb9\x49\x64\x75\x8b\x46\x02\x30\x7a\xfc\xf8\xa8\xf6\x03\x20\x46\xd1\x6d\xf5\x46\x20\x6b\x48\xbb\x3a\x6a\x1b\x84\x17\x64\x6f\x4e\x07\x10\x28\xd3\x30\x4b\x4b\x38\x0c\xda\x44\xa4\x6d\xed\xfb\x20\x45\xc1\x37\x45\xe2\x74\xb8\xdc\xba\x10\xa2\xe0\x05\x53\x27\x29\x23\x99\x82\x7e\x81\x36\xb9\x13\xce\x1d\xc1\xa9\xa4\xd4\x18\x60\x38\xf4\xb2\x7a\xf2\xf4\xd5\x97\x77\xcb\xc6\x36\xc7\x68\xef\x8d\xdf\xda\xb9\xf7\x57\x77\x5d\xf6\xd5\x83\x1b\x5a\x86\x97\xf9\x0d\xd8\x82\x39\x7b\xe2\xf4\x13\x0f\x3c\x71\xf8\xf2\xde\xa5\xa2\x21\xec\x4e\xc7\xfb\xd6\xd5\x6c\xb5\x33\x2f\xab\x45\xf4\xd0\x95\x94\x4f\x1b\xb8\x78\x51\xc3\x97\xa2\x5d\x87\xdf\x3d\x7e\xcd\x0f\x0e\xcc\x19\xd9\x7f\xdb\xbc\x9d\x9f\x0e\x58\x02\xfc\x2c\xce\xed\xe8\xbd\xe8\x81\x9f\x3e\x7a\xeb\xe7\xff\x78\x41\x6f\x68\xcf\x85\xf5\xf1\x81\x6b\xd6\x2e\x99\xad\x6e\x5a\x78\xf9\x06\xd8\xf7\xbb\xd3\xba\x14\xa8\x5c\xb7\xa1\x0a\xba\xbf\x58\x3b\x49\x77\x0e\x56\xa8\x1c\x9d\x7c\x3f\xb0\x72\xa1\x69\xf6\xc3\xf9\x96\xb5\x6e\x63\xab\xf3\xb2\x9e\xaf\xfc\xe7\xc2\x9b\xbf\x3a\xba\xf3\x2b\xfb\x2f\x6a\x59\xb1\x4c\x70\x32\x26\x96\xb3\xc7\x7f\xf4\xd8\xfd\x8f\xdd\x3e\xda\xa3\x55\xce\x95\x9a\xdd\xbb\xd6\xb3\xc5\x63\xff\x5a\xa5\x8d\xf1\x4d\xeb\x1b\xbe\x18\xed\x84\xe8\xaf\xd6\x3c\x74\xe3\x92\xae\x91\x9b\x3f\x3a\xb0\xe3\x53\x01\xd6\x24\xb6\xda\xdd\x72\xdf\xfa\xe3\xaf\x3f\xf2\x91\xc7\xdf\xbe\xa0\xa7\x61\xcf\x05\xf5\xb3\xe7\xee\x5e\xbd\x78\xb6\xba\x65\xdb\x83\x25\x43\xe4\xb2\x6c\xab\x96\xd2\x6b\x08\x92\xd1\xa0\x33\x21\x16\xe0\x04\xe2\xee\x8c\x56\x6a\x9b\x46\xe8\x84\x13\xa9\x50\x2a\xe4\x0c\x39\x13\xce\x44\x35\x85\x4a\xee\xe7\xd4\xe3\x3f\x25\xb5\xb3\xd6\xa6\xb7\xde\x79\xe7\xd6\x8d\xbd\x3b\xaf\xb8\x7f\x6c\x7c\x7c\xec\xb3\x2f\xc2\x85\x57\x5e\x79\xd5\x55\x57\x5d\x05\x52\x25\x0d\x8b\xf7\x7a\x23\x87\x3c\xc9\x74\xe8\xae\x1f\xdc\xd5\xbd\x7d\xdb\x9b\xea\x77\xde\x7c\x75\xaf\x96\xec\x2a\xfc\xd1\x69\xd4\xad\xb6\xfe\x7d\xc6\x88\xd8\x8b\x0b\x58\xc0\x0e\x5c\xe1\x14\x3b\xe0\xe6\xa9\x2a\xb7\x83\x8e\x30\x92\x09\xa6\x82\xae\xb0\x53\x23\xc3\x42\xa9\x44\x2a\xe1\x64\x1f\xfa\x27\xf5\x5b\xaf\xdc\xaf\xbe\xfb\xfc\x75\xd7\x3d\x0f\xb6\xfb\xc1\xff\xd2\xf7\xf7\x7c\xf1\xe6\xd3\x37\xdd\x74\xfa\xe6\xd5\x47\x2f\x9a\x57\xcf\xa9\x23\xf8\x9f\x2d\x64\xeb\xe9\x57\x4f\x9f\x7e\x15\x5f\xfd\x8a\xfa\xcd\xaf\x69\x09\xa1\x19\x6c\xcf\x5f\x97\xfb\xf6\xee\x7d\xaf\x4f\xbe\xbe\xaf\x7d\xc1\xfa\xe5\xa1\xc9\xfe\x7e\x2d\xcd\xe9\xd3\x25\x1e\xa2\xc2\x22\x64\x41\x3e\xd4\x4a\x77\x82\xd4\x75\x29\xef\x4e\x67\x12\xf6\x50\xa3\x43\xc4\x0d\xed\x38\xd9\x87\xe3\x7e\x00\xbb\xfe\x05\x87\xec\x71\x97\x33\x98\x3c\x6b\x46\x27\x08\x14\xe5\x9a\x8f\x2f\x6b\x16\xb0\x82\x51\xf3\xb2\x03\xc7\x0f\x2c\x6b\xd6\x4f\xb8\x79\xf4\xf8\x84\xa2\x7d\x77\x8c\x72\xfc\xf7\x11\xef\xfb\x94\xe3\xc0\x23\x6f\x04\x94\x11\xc8\x1d\x1e\x0e\x3b\xd4\xf1\xdf\xde\x79\xcf\xbe\xe5\xcb\xf7\xdd\xa3\x9f\xd4\x66\x8c\xb4\x0c\x2a\x3d\x92\x6c\xd9\x5f\x50\xa4\x80\x35\xc0\x20\xa2\x20\xa1\x68\x25\x43\xf1\x0c\x12\xc1\x38\x83\x64\x35\x2b\x27\xb5\x03\x75\x96\x44\x2e\xa2\x61\x19\x72\x72\xb2\x88\xf3\x00\x88\x41\x24\xab\xe7\xd5\x7d\x7d\xeb\x4a\xfe\x0c\xd2\xbd\x2c\xd1\xc4\x32\xe4\x80\xea\x4a\xc8\xba\x42\xbe\x9e\x37\x8b\x14\xac\x30\xf4\xbd\x05\xcf\xba\x05\x68\x03\x6d\x67\x5f\x7e\x11\x93\xad\x7c\x8e\x5c\xf4\xa7\xac\xe0\x2c\x53\x51\x66\x1d\x48\xd0\x0d\x38\x4b\xcb\xac\xbf\x0b\x3f\x58\x2e\x7c\xa4\xf0\xde\xe9\xb6\x35\x75\x08\x25\x82\x54\x37\x32\x6c\x0f\xda\x67\x58\x5b\xc7\xf0\x48\x5e\x91\xd9\x2b\xf3\x0a\x1e\xd1\x5d\x67\x97\xd6\x3b\x46\x99\x18\x13\xe4\x00\x33\x32\xa1\xc8\xcc\x4b\x95\x7e\x48\xb4\xf1\x99\x63\x74\xec\xb9\xda\xea\x56\x95\xaa\xda\x69\x7a\x1b\x47\xaa\x9a\xed\x67\x15\x2d\x31\x43\x1b\xd2\xf7\x60\x74\xfe\xbe\x9b\xf6\xa0\x42\x5e\x82\x0a\x65\x3c\x4f\xdf\x91\xea\xf7\x96\xed\x89\xbd\x68\x4e\xe5\xce\xd4\xe5\x66\xdc\x7e\xdc\x8d\xa9\xec\x3b\x9c\x96\x1d\x1c\x8f\x78\x91\x69\xc1\xd4\xb0\xa0\x91\x4a\x71\x0b\x6e\xa2\x74\x46\x79\x6b\x17\x8c\xde\xde\xb5\xe8\xfa\x04\x40\xe2\xfa\x45\x5d\x9f\x87\xc5\x5d\x2d\x5b\x96\xa8\x77\x6c\x34\xcd\x6d\xe9\x4d\xbb\x01\xdc\xe9\xde\x96\xb9\xa6\x0d\xea\xe7\x1b\xfa\xae\x5a\xbd\x8c\xcd\xcd\xdd\x4c\xe6\x4c\xfe\x96\x6a\xe1\x7b\x67\x47\xfe\xba\xb5\xb9\x63\xf6\xec\x8e\xe6\x9b\x7f\x19\x85\x75\x2b\xee\x49\xa8\x13\x59\xbe\xa3\xae\x51\x92\x1a\xeb\x3a\xf8\xec\x3b\x9e\xe6\x63\xfd\xcb\x77\x6e\xa2\x7d\xfe\x34\x87\xd8\x2b\xa8\xdd\x5f\x4b\x01\xdf\xc2\xa5\xab\xea\x26\xd3\x71\x17\xe5\xe8\xeb\x2e\xea\x9d\xf6\xa0\x64\xeb\x80\xa0\x33\x44\x4d\x2c\xe1\x62\xf5\xab\xb0\x19\x2e\x5d\x83\x57\x6d\xbb\xf4\x73\xdb\x98\xbb\xd5\xaf\xad\x5c\xd7\xbf\xd6\x69\x56\xbf\x86\x01\x60\x09\x76\x34\x2f\xba\xb4\xff\xc9\x57\xc8\xdd\x93\x41\xf2\x1f\x10\x5f\xb2\x65\xcb\x92\xa5\x97\x5c\x32\xf9\x8b\xfc\x0f\xb0\x74\xd9\xde\x05\x09\x7f\x22\xff\x63\xb8\x1b\xde\x9d\x35\xeb\x9e\xc0\xac\xce\xfa\x5f\x4f\xc7\xd7\x4f\xd2\x35\x91\xfa\xf4\x8f\x46\xd2\xfd\x90\x4e\xb8\xdc\x74\xde\xc2\x74\xed\xe0\xf8\x2a\x36\x3f\x75\xfa\xef\xe2\xd0\x4d\x2f\xab\xbf\xf9\xd4\x17\xd4\x7f\xbd\x92\x07\xc3\x61\x93\xd5\xc6\x2f\x79\x6d\x6f\xd1\xf3\xff\x96\x7f\x5e\x78\xb8\x82\x33\x7f\xcb\xe5\x20\x1f\xfb\x14\xf8\x5e\x26\x3e\xf5\x07\xea\x6f\x5e\xbe\xe9\xde\x43\xa6\x1a\xc3\x11\x23\x36\x6d\xde\x59\x70\xfc\xbf\x68\xe0\x48\x05\xe7\xfe\x23\xdb\xaf\xbe\xe9\x65\x04\x28\x36\xe5\xe4\xfe\xc0\xfe\x04\xed\x46\x28\x38\x0d\xb4\x96\xe7\x1a\xa2\x7e\xce\xe9\xe0\x45\xb6\x10\xd7\xc7\x50\x73\x68\xd6\x5d\x18\x42\xed\x5c\x2a\x99\xe9\x63\x0b\xbc\x23\x91\xa1\xa6\x25\x6c\xd4\xe5\xb0\x42\x11\x0b\xf6\x0f\xe1\xcb\xa9\xdf\xdd\xfb\x23\x2d\x53\xe8\x80\x18\x13\xb1\x93\xb1\x31\x06\xe2\x23\xb5\x66\xaf\xe4\x15\x62\x3e\x75\xa7\xcf\x68\x74\x99\xfd\xc4\x1f\x31\xd9\xec\x26\x3b\xe7\xc0\xa2\x08\x1b\x67\x4a\x0a\x27\x66\x48\x7a\x00\x50\x4b\x2a\x19\x85\xcb\xc3\xa9\xf0\x15\xe1\x30\x5c\xd1\x98\x4e\xb5\x00\x3a\x20\x8a\xd8\xc1\xd9\x4d\x76\x9b\x29\xe2\x27\x7e\xb3\xcb\x68\xa4\x9c\x32\xc1\x2b\x79\xcd\xb5\xc4\x47\x0c\x8c\x8d\x71\x62\x31\xa6\xbd\xeb\xec\xa4\xea\xce\x99\x92\x1e\x98\x42\x2d\x61\xf5\xfe\x68\x19\xc3\x43\xd7\x27\x0e\xa2\x26\x2a\xd9\x18\x2c\xdb\x56\x97\x88\x39\x39\xdd\x0e\x1c\x4f\x44\xaa\xef\x91\xce\xa4\x23\x8d\x55\x29\x8a\x1a\x71\x60\xe3\x75\xb9\x8f\xbd\xe8\xf9\x1d\x14\xea\x05\x19\xcc\xfa\xe9\x6f\xdb\xb9\xda\x78\x3b\xbf\xbd\x67\x93\xcd\x31\xfc\xe0\x11\x87\xad\x15\x6f\xa1\x77\xf2\x2f\xd2\x13\x2e\xa4\x3b\xfa\x31\x39\x74\xe6\xb6\x90\xfc\xb1\xbb\xde\x85\x21\xb8\x02\x86\xde\xbd\x0b\xe8\x9d\x41\x5c\x70\x8f\x7c\x12\x0e\x78\xdb\xc4\x5a\xaf\x7a\x0b\xbb\xac\x67\xd9\x91\xd8\xf0\xb2\x9e\x6b\x44\x3d\xc5\x8b\xf4\xb4\x47\x4f\x97\x53\x27\x7e\x59\x57\xf7\x0b\xe0\xbe\xaa\x3d\xe4\xae\x77\xd5\x7f\x2e\x61\x37\xd2\xba\xbb\xb4\xf5\x0f\x05\x18\x6d\x4f\x59\x0f\x3c\xc7\xa7\x75\x34\xfa\xc6\xb4\x2d\xc2\x94\xc1\xb8\x42\x0d\xd5\x68\x5c\x14\x24\x7a\x48\xdd\xa9\x3e\x74\xfa\xee\x5b\x2e\xa8\xf5\xb4\x9f\xb8\xb9\xa5\x6b\x41\xef\x0f\x61\xeb\xe9\xd3\xb0\xb2\x02\xa3\x8b\xb5\x7a\xce\x02\xe9\x7a\x17\x3e\x05\x6f\xc1\xa7\x18\xe5\xe8\xdb\x87\x77\xbd\xb8\x34\x3e\xb2\x61\x65\xff\x15\x11\xce\x70\xf4\x6d\x90\xde\xfe\x7e\x19\xb8\xcb\x69\x9f\x01\xb7\xeb\x9f\x20\xfa\xe4\x93\x65\x1e\x04\x42\x0e\x34\x07\x6d\xab\xac\x45\xa9\x0e\xc9\x88\xd6\x0b\x1f\x80\xa2\x00\x1f\x8c\x9f\xe0\x74\x70\xe4\x42\xf5\x65\xf5\xaf\x0f\x8d\x8e\x5c\x12\x6a\xf0\xb5\xa6\x96\x0f\x7e\x02\x4c\x0f\x3d\x94\xff\x34\x1c\x80\x05\xa7\xce\x83\xae\xc0\xce\xf9\x50\xa8\x0a\x77\x31\xca\xce\x67\x76\xac\x3a\xd1\xd9\xb9\xc6\x21\xd7\x9b\xc4\x9d\xcf\xfc\xf0\x99\xb7\x0e\xbf\x7d\x1e\xa8\x85\x89\xbf\x9f\x1f\x65\xe1\xe6\x1b\x4e\x23\x40\x30\x85\xc8\x3e\x56\xa1\xd8\xcf\x2e\xbe\x60\xde\x94\x91\x59\x5d\x38\x51\x50\x86\x77\x3a\x78\x12\x4e\x27\xe2\x64\x8f\x64\xce\xff\x46\xa8\x63\x4c\x76\x3b\xf3\x3d\x75\x94\x31\x48\x82\xc4\xfe\x2f\xc6\x63\x83\xc5\xb2\x97\x7d\x12\xee\x34\x30\x32\xf9\x57\x87\x67\xe2\xe6\x1a\xcc\xfa\x6c\x24\xb6\x1d\xcc\x56\x0f\xe9\x12\xa5\x1a\xbb\xc1\xa4\xce\xde\x82\x2b\x7d\x7f\xac\x9d\xce\x0f\xed\x86\x54\xd0\x99\xa8\x76\x8e\x3c\x63\x1c\x15\xdc\x86\xa6\x3b\xcf\x68\x01\x67\xb0\x80\x22\xc8\xa3\xce\x98\x6e\x52\x38\xa2\x22\xca\x91\x9d\xf1\x6a\x28\x89\xf5\x6b\x6a\x78\x18\x1b\xc1\x28\x39\x34\x12\xeb\xac\x34\x47\xcc\xe5\x8a\xa9\x67\xb8\x4a\x0e\xe5\x8a\x79\xb5\xd8\xdc\x50\x32\xd7\x59\xa6\x4d\x72\x48\x46\x2b\xd0\x85\x05\xba\xa8\xa8\xf0\xee\x8a\xa7\x53\xf6\x74\x5c\xe7\x32\x6a\xdb\x26\xae\x28\x0a\x6a\x87\x68\x3b\x54\x5d\xd2\xc5\x4c\xc7\x25\x48\x23\x6d\xd5\xf0\x83\xdb\x05\xce\x48\x03\x4f\x1f\x47\x94\x13\xaf\x9c\x88\x24\x23\xcb\xb7\x2d\x0f\xf6\x91\xa0\x2c\x98\x2d\xb3\xd7\xcf\x99\x7f\x43\x0b\xef\x64\xcc\x76\xc9\xcc\x38\xf9\x96\xbd\x77\xec\xa5\x97\x92\x9d\x5e\xde\x30\x7f\xce\xfa\xd9\x16\xb3\x20\x43\x1b\x9a\x82\xb5\xdf\xba\x13\x84\xf1\xcf\x06\x21\x8f\x9a\x5b\x9b\x23\xc9\x08\x7e\x3e\x7f\x6a\xe7\x89\x13\x3b\x35\x12\x26\xbe\x7c\x79\x1c\xcf\x37\x47\x04\xd9\xd4\xde\xbe\xb4\xc7\xd4\xc8\xd9\xed\x5c\xa3\xa9\x67\x69\x65\xb8\xbd\xdd\x24\x0b\x2c\xfe\x1a\xd8\xef\x18\x3e\xf6\xeb\x23\x18\xbf\xba\x05\xe3\x2d\x1a\x51\xca\x94\xe4\x2a\x06\xe4\x41\xb5\xda\x0e\x84\x0d\xea\xb2\x94\xe0\x59\xcc\x92\x60\xc9\x86\xbb\x77\xba\x53\x14\xca\xbd\x27\x88\x50\x19\x87\xaa\x00\x92\x85\x3c\xe5\x66\xe2\x9c\x20\x03\x82\x16\xf5\x75\x8c\xca\xc2\x96\xce\x18\x93\x8d\x75\x3a\xad\xda\x5a\xa0\x60\xa5\x33\x06\x63\x10\x28\x61\xc5\xe6\xaf\x84\x16\x75\x6d\x9e\xf6\xf9\x98\xce\xa6\xef\x8c\xa9\x5f\x17\xac\xea\x4e\xca\xaa\xd7\xfb\x8e\xfa\x82\xb1\xa1\x18\xda\x48\x65\x93\xd4\xac\xbc\xb0\x67\xf2\x83\xbb\x60\xd5\xe0\xd0\x3d\x65\x27\xd2\x74\xbf\x9b\x71\xf0\x22\x2e\xa3\x8d\x68\x3b\x43\x6a\xb0\x45\x7b\xae\xf8\x6b\xc7\x3a\x70\x6f\xdc\x8f\xf1\xb8\xec\x95\xaf\x48\x6a\xe5\x8a\x6f\x1d\x1c\x5b\x70\xf5\xed\x47\x6e\xbf\x7a\xc1\x7c\x53\x93\x49\x11\x7e\x23\x28\xa6\x26\xd3\x7c\xe5\xd2\xb6\xee\x1e\xa6\xa3\xa6\xa6\x4d\xe8\x6f\x77\x0c\x6f\x1a\x76\xb4\xf7\x0b\x6d\x35\x35\x1d\x4c\x4f\x77\xdb\xa5\x17\xde\xfb\xb5\x6f\x7d\xed\xde\x0b\x09\xe5\xbc\xb6\xc7\x65\xaf\x1c\x18\x4a\x2e\xde\xb7\xa2\xad\x6d\xc5\xbe\xc5\xdb\x57\x98\x5b\xcd\x9f\xb8\xf7\xde\x4f\x98\x5b\xcd\x2b\xb6\x7f\x72\xf7\xec\xa1\x6b\xe3\xbe\x74\xb8\xb6\x36\x9c\xac\x73\x7b\xda\xe3\xad\xc9\x64\x6b\xbc\xdd\xe3\xae\x4b\x6a\x71\x69\x5f\xfc\xda\xa1\xd9\xbb\x3f\xb9\xf5\xc9\xdd\x73\xe7\xee\x7e\x92\xce\xff\x3a\xf6\xac\x97\xda\xa0\x50\x36\x75\x59\x36\xa4\xfb\x91\xa4\xea\x12\xb6\x0a\x5c\xca\x48\xd9\x50\x5d\x87\x33\x13\xce\x8c\xc9\x82\xc5\xa2\xfe\x8b\xd1\x08\x59\xea\x2a\x72\x44\x90\x0b\x28\x93\x67\xc6\x28\xca\xef\x88\x8e\x22\x09\x23\x39\x41\xce\x09\xb2\x09\xb2\x46\x41\xd4\x52\xcb\x42\x4e\xc6\xc1\x22\x58\x24\x65\x2d\x97\x20\x21\x8b\x18\x81\xd4\x37\x51\x8a\xda\x00\xb7\x94\x25\x40\x45\x59\x56\x3c\x03\x69\xf6\x03\xe4\xca\x2c\x92\xc4\x71\xfa\xe0\x71\x41\x36\xc2\x88\xd1\x67\x84\xcd\x26\x5c\x94\x36\xdf\x79\x3d\x86\xd6\xd7\x3e\x05\xa4\x7b\xd1\xe6\xd1\xe3\x4d\xb7\x3c\x86\x47\x44\x09\x46\xa8\x9c\x67\x8c\x7a\xc0\x1c\x33\x1a\x61\xb3\xe5\x35\x2a\x83\xbe\xe5\x8d\x8c\x5f\x78\x0d\x5a\xff\xe9\x9e\xbe\xe3\xa3\x43\x7d\xf5\xa7\xcf\x2e\x63\x94\x2a\x2e\xeb\xf8\x14\x25\x3d\xdc\x44\x01\x11\xe2\x9c\x65\xd4\x5e\xe3\x33\xaa\x0f\x9b\x2a\x0a\xfb\x01\x65\x1c\x13\xb5\x9a\x18\xd5\x87\x2d\x16\x51\x52\x69\x1b\xc3\x88\xac\xbe\x73\x8e\x42\xa2\x4a\x1f\xe9\x3c\x5a\x8f\x46\xca\x12\x1d\xb6\xa4\xab\x41\x32\x5c\x1d\x50\x90\x02\x1d\x94\x20\x95\xcc\xb8\x02\x19\x57\x1d\x05\xdf\x2d\xa2\x99\x45\xe9\x74\x34\xed\x3a\x12\x4d\xa6\xdb\x71\xd4\xcf\x94\x14\x3b\x74\x51\x2f\x13\xd1\xd5\x36\xcc\xe1\x39\x3b\xe7\xbb\xe6\x2c\xdc\x35\xb6\x6b\x51\x57\xcd\x21\x58\x78\xa8\x66\xf4\x78\xa0\x73\xb8\x33\x30\xb4\x73\x88\x9e\x17\x74\x03\x30\x26\xc3\xfc\x9d\x73\xc2\x66\x35\x57\x50\xe3\xf8\x19\x15\x61\xef\xbf\xf1\xc8\x91\x1b\xe7\x1f\x38\x7e\xed\x06\x6b\x72\xfe\x8b\x8e\x6d\xbd\xc3\xbb\x76\x0d\xf7\x6e\x73\xbc\xd8\x57\xbf\x73\x67\x7d\x5f\xf6\xf8\xe8\x85\x75\xcd\xda\xc7\xdd\x5c\x77\x61\x72\x68\x28\x59\xbe\x9a\xbf\xb7\xc1\x34\xb7\x3e\xd9\x2c\x5b\x37\x5c\x7b\xfc\x00\xf9\x49\x41\xa1\xa3\x64\x5b\xae\xb7\xc5\xb2\x32\xa5\x97\x71\x70\xbc\xdd\xc1\x04\x1a\x7b\x41\xb7\xfb\x4d\xc4\xdd\x54\xec\x43\xbf\x08\xbb\xc3\x15\x48\xeb\xba\xf8\x94\x27\xa4\xf7\x9e\xdd\xc1\xf1\x4e\xfd\x0e\xa5\x24\xe2\x25\xb3\x85\x45\x5d\x3a\x7c\xf4\xa3\x6f\x44\xbc\x9c\xc9\xde\x13\x4a\x0d\x0e\xa6\x82\xf5\xa7\xc0\x70\xaa\x3e\xa8\x85\x43\x3d\x76\x13\xe7\x8d\xbc\xf1\xa8\x16\xd5\xb5\x68\xd7\xd8\x2e\xa2\x2b\x1d\x64\xfb\xb6\x38\xd5\x3d\x27\xdf\x7c\xf3\xe4\x21\xc7\x4f\xee\xa1\x90\x1a\xfe\xc6\xc1\xd1\x41\x49\xbd\x8a\x72\xef\xee\x93\x06\x47\x07\x1b\xfd\x38\xe2\x55\xd1\x3d\x3f\x71\x1c\xa2\x91\x47\x9d\x5b\xfa\x86\x77\xed\x2a\xf8\xfa\xd4\xe5\xaa\xda\x6e\x36\xac\xeb\x46\xb1\x65\x78\x74\x7b\xd0\x9e\x28\xa9\x42\x15\x30\xd4\x13\x45\x8d\x28\x75\x8c\xa2\x3a\x32\x63\x93\x48\xd1\x55\xa0\x30\x3a\xb4\x31\x9b\xdd\x78\x88\x51\x14\x65\x02\x1d\xda\x48\xb2\x1b\x0f\x4d\x20\x16\xe9\x9a\x4f\xe3\x93\xb9\x8d\x87\x58\x74\x08\xe1\x0a\x1b\xb1\x44\x95\x85\xd8\x87\xb7\x0a\x23\xd9\x0f\x69\x08\xf6\xa1\x0c\xbf\x74\xda\x30\x5b\xa0\xed\x1b\x68\x4f\xd3\xca\x42\x50\x1f\xf4\xc8\xa6\xd1\x12\xd3\x38\x08\x9c\xb2\x6b\x38\x9b\x1d\x7e\xff\x5d\x1e\x1d\x1f\x9d\x40\xa3\xc7\xf9\xec\x9b\x27\xb3\x87\x36\xe6\xb3\x1b\x0f\x45\xbc\x8c\x72\x92\xcc\x1a\xdb\xa5\x2a\xf9\xdc\xe8\xf1\xe3\x8c\x51\xfd\xce\x9b\x01\xad\xbd\xf0\xb8\x37\x52\x89\x85\xde\x86\x06\x74\x6a\x80\x2f\x59\x98\xea\x43\x8a\x0e\x19\x97\x8e\xbd\x32\x3d\xcc\x96\x52\x86\x2a\xfd\xae\x2e\xea\xa2\xc0\xff\x5d\x8b\x2a\x61\x14\x22\xc9\x08\x41\x34\x7e\x5c\x90\x4f\x1d\x02\xe4\x8d\xb0\xb9\xbc\xd2\xbb\xcd\x31\xf9\x9e\xf6\x11\x10\xb3\x63\x5b\x2f\xd6\xe1\x61\x47\xa8\x32\xde\x58\x75\xf8\x7d\xea\x33\x03\x23\x59\x20\x81\x43\xa7\x74\xb9\xaf\x6e\xbf\x22\x23\x6f\x01\x03\x77\x35\xf5\x68\xe0\xac\x16\xb2\xf3\xf6\x60\x24\x0a\x11\x28\xac\xf0\x76\x98\x06\x2f\x13\x49\xb1\x55\x52\xc0\x6a\xa9\x20\x7b\xca\x17\x2b\x49\xde\x95\xd8\x88\xef\x10\xdc\x60\xb2\xa8\xdf\xb7\xc0\x56\xaa\xde\x80\x00\x49\x62\x11\x72\x46\x94\xf0\x78\x31\x54\x19\x2b\x89\xcc\x21\xdf\x48\x6c\x42\xd1\x9e\xc2\x51\x29\xfc\x7c\xf5\x8e\x3a\x0b\x74\x59\xce\x48\x0c\xd2\xc8\x81\x33\x88\x8c\x14\x85\x46\xe2\x58\x59\xba\x37\x85\xca\x61\xe4\xa8\xc0\xaf\x3f\x5b\x96\xf4\x45\xf4\x6d\xf4\x23\xf4\x1f\xe8\x4f\x68\x0a\xac\x50\x0f\x6d\xd0\x7b\xb6\xdf\xea\x54\xd5\x35\x5b\x75\x5d\x9d\xbe\xda\x6f\x75\xf5\xfd\xf3\x5d\xff\xbf\xce\x7f\xbe\xf4\xd5\xf5\x05\x6d\x8a\x29\x6a\x5b\x9e\x85\xc5\x04\x4a\x19\xa5\xbb\x02\xaf\x1b\x95\xc3\x53\x15\x61\x72\x8e\xf8\x73\x85\xff\x6f\xa4\xc7\xe7\x88\x9f\x5e\x66\x50\x26\x14\xad\x6e\x14\x18\x0b\x55\x7a\x7f\x1f\x2f\xd5\xf4\x2f\x67\x57\xbc\x22\x2e\xff\x97\x19\x22\x67\x0a\xfd\x9f\x4a\xa8\xce\x14\x59\x3e\x9c\x39\xc6\xa1\x33\x68\x5c\x27\xe0\x2a\xd4\x81\x91\xf0\x81\xdf\xcc\xd7\xd0\xcf\xd1\x7b\xff\xef\xbf\x92\xff\xc9\x28\x2d\xe9\x65\x54\x8c\xd7\x1a\x28\xfa\x1b\x08\xa5\xa6\x6b\x1b\xf5\x42\xc2\x79\x36\xbe\x7d\x22\x58\xda\xc1\xfc\x5f\x19\xdd\x1f\x76\xf4\x4d\x69\x3b\xe1\x6c\xac\x53\x0b\xeb\xa3\x90\xde\xaa\x28\x8f\x52\x78\x5e\x71\x6c\x42\xb6\x33\x06\xb9\x58\x27\x64\xff\x8f\x8d\xd1\xf3\x8c\xa8\xc9\x63\x8c\x12\xd0\x26\xec\xc0\x84\x42\xc7\x15\xc9\xe9\x05\x1d\x19\x29\x29\x56\xe9\xe1\xb6\xf2\xe7\x03\x34\x87\x3a\x1e\x41\x2c\x95\xbd\xea\x74\x9b\x0d\x79\x50\x0f\xda\x3a\x5d\xfa\x4a\x21\x5c\x8b\xe4\x9c\x4c\xbb\xaf\xe4\x3d\x22\x54\x74\x21\xe1\x2c\xf5\x66\x3c\xad\x03\x40\x4c\x13\xd0\x46\xa8\x74\x36\xad\xcb\x66\x4b\xcb\x30\x65\xbb\xa9\x2f\x82\xf2\x69\xd1\xf0\x5d\x1e\xb3\x88\x46\xbc\x28\x89\xe3\x54\xd4\xad\x63\xe7\x17\x83\x80\x22\xde\x5c\x51\x5e\x4b\xbf\x1b\xaf\xfc\x82\x9c\xf5\x8e\xe9\x52\x9c\x02\x0b\x4f\x01\x84\xf9\xef\x5a\x4c\xf9\xa7\xe8\x35\x09\x9c\xf5\x1c\x2d\x88\xdb\x27\x14\x6f\xa4\x28\xb9\x8d\x24\x23\x30\xe6\xcd\xca\x2f\xc8\x54\x5f\x3d\x52\xc4\x96\xd0\x71\xeb\xa3\x68\x36\xea\xa7\x36\xee\x1f\xa6\xea\x1f\x8a\x2a\xa4\xbb\xa7\x19\xaa\x98\xd7\xa9\x45\x85\x52\x3f\x4c\x6e\x22\x37\x56\xa6\x16\x03\x81\x8d\x87\x60\x6c\xe6\xda\xfc\xf1\x03\x89\xc8\x22\x3e\x07\xc5\x85\x9f\x83\x10\x70\x02\xf0\x21\x9d\x04\x6f\x21\xa9\x84\x3d\xc4\x87\xa2\xa9\x44\x2a\x91\x8a\xa6\x32\xa9\x50\x2a\x94\xca\x24\xdc\x09\x7b\x28\xd5\x8d\x75\x5d\x5f\x48\xb8\x59\x3f\xb8\x79\x05\xd4\x37\xd5\xb1\xf1\xac\xfa\xf3\x05\x5a\xf3\x8f\x8c\x65\xb3\x63\xb9\x91\x40\x40\xc9\xe5\x94\x40\x60\x24\xa7\x5d\x53\x62\x68\x01\x84\xb3\xe3\x30\xa2\xdc\x63\xc0\xd9\x40\x36\x90\x55\xc7\x8c\xa2\x31\x00\x63\xe3\x81\x5c\xc0\xe0\x51\x3c\x86\x40\x2e\x30\x0e\x63\x01\xa3\xb6\x11\xcc\x06\x7c\xb3\x4c\x74\xff\x90\x2d\xe8\x9f\x70\xc8\xa3\x4b\x27\x34\x32\xd7\x19\x4c\x65\x68\x7b\x46\x33\xc1\x4c\xd0\xcd\x53\x00\xee\xc1\x14\xa3\x4c\x28\x8a\x72\xf2\xcd\x6c\x00\xc6\x03\x24\x17\xc8\x62\x45\xfb\x5a\x53\x83\x6a\x36\x97\xcb\xbd\x79\x12\xb2\x59\x45\xc9\x05\x26\xc7\xa7\xf9\x4c\x4d\x20\x14\x2e\xbb\x4b\xad\xd2\x7b\xd4\xe1\x41\x28\xfe\xe1\x59\x38\x40\x54\x8f\x4f\x45\x65\xbf\xb5\xb8\xe8\x39\xb5\x52\x76\x9b\xd3\x65\x57\x6a\x8e\x0e\x23\x2a\x3e\xd2\x26\x04\x35\xe7\x8d\x44\xc8\x37\xaa\x74\x13\xab\xca\xf5\x61\x7c\xb9\xce\x54\x2e\x35\xa7\x97\x2d\xa7\xbf\x4b\x2f\x55\xb6\xba\x64\xba\x33\xd7\xac\x5e\xba\xe9\x19\xf0\x9c\xe9\x05\xc3\xa8\x0d\x2d\x23\x7f\x61\x12\xc8\x81\x9a\xb4\x1d\x6d\xb5\x2f\x5c\xde\x08\xcc\x4c\x91\xf8\x5a\x53\xdc\xe4\x35\xa9\xed\x26\x13\xbc\x6a\xf2\x9a\xe2\x26\x93\xba\x17\x0e\xc3\x91\x19\xa3\x9f\xa2\x21\x1a\x03\xaf\x9a\xf4\x24\x7b\xd5\xbd\xa6\x99\xa3\x75\xbf\x6a\x68\x19\xf9\xb7\x62\xb9\x50\x59\xb7\xa5\xec\x53\x97\x99\x29\x12\xaf\xd6\x5e\xae\x3f\xf7\xb0\xba\x57\x7f\x28\xbc\x0a\x47\x66\x8c\xc6\xcb\xf4\xb2\xd2\xab\xc3\x70\xb8\x50\xe2\x76\xd3\xcc\xd1\x5a\xb9\x96\xa1\x8f\x31\x09\x66\xf5\xb4\xf6\x9a\xee\x1f\x42\x9a\x29\x92\x49\x9c\xaf\xd6\xd3\xa2\xdf\x39\xab\xa8\xda\xfb\xe1\xfa\x19\xa3\x91\x5e\xae\xa7\x98\x04\x73\x6d\x65\x7b\x55\xf9\x98\x90\x66\x8a\x64\x12\xe7\xae\xee\x0c\xd1\xf8\xa9\xb3\x3b\xd7\x64\x8a\x6b\x05\x9b\x21\x5a\x9b\x8b\xda\xd0\x32\x7c\x2d\xed\x47\xad\x54\x46\xa8\x76\xb7\x8c\xaf\x2d\xa6\x9e\x36\x6e\xc8\x3b\x33\x37\x16\x9d\xdf\x04\xb4\x0c\xaf\x2e\x3d\xf3\x43\x0f\x82\x73\xf5\x36\x7d\xe6\x32\x10\x98\x04\x59\xad\x3f\xf3\x1f\xe8\x40\xb8\xf2\x5c\x7d\xa2\x3d\xb3\x8d\x49\x90\x6b\xcb\xe5\xfc\x90\x8d\x4f\xda\xce\xd1\x9c\x05\x39\xb4\x4e\x37\x76\xe8\x78\xa9\x95\x28\x3d\xba\x2c\xdf\xe1\x2f\xed\xc8\x93\x7d\x90\xaa\x98\x43\x78\x24\x0b\xef\x53\x12\x81\xcb\x52\xd9\x7e\x7e\x3c\x10\xd0\x9d\xa4\x07\x02\x79\x0a\x91\xc4\x65\x07\x36\xe1\x00\xa1\x34\xc5\x24\xd5\x0d\x5e\x36\x91\x1b\xd8\x14\x5e\xd9\x2b\x68\x73\x88\xd8\x33\x1c\x29\xab\xa3\x55\xe8\x80\x58\xa9\xc5\xba\x36\xb7\x4d\x97\x34\x84\xa0\x02\x7b\x4e\x2b\xab\x46\x02\x16\x68\xc6\x04\x1b\x4f\xb6\x40\x83\x23\x01\x63\x25\x25\xb7\x81\x89\x31\x59\x60\xe8\xeb\x27\x72\x82\xcc\x8e\x8c\xe9\xb0\x4d\x63\x64\x97\xcd\x36\x66\xb3\x01\xd2\xd1\x43\x75\xf4\x5b\x32\x52\x66\x70\xcb\x93\xab\x29\xb3\x7a\x64\x24\x10\x28\xe9\x83\x33\x3a\xad\xe3\x46\xd1\x32\x9d\x13\x9e\xb1\xd5\x2a\x59\x06\x3a\xce\xc3\xe7\x0a\x2d\x20\x10\xbd\xb1\xca\x58\x78\x3b\x28\x03\x61\x5c\xe7\x28\x4f\x6a\x25\x20\x2f\x4d\x53\xd4\x63\xf4\x02\x50\xbe\x89\x5b\xd7\x46\x3f\xd7\xdb\x31\x6d\x82\x6e\xa8\x76\x61\x00\xaf\x50\x40\x24\x34\x25\x0b\x2a\xa2\x75\x44\x82\x9c\xd3\x9a\x60\x0c\x66\x0d\x25\x55\xa4\x73\x1f\x92\x43\x9b\x75\xdc\x24\xda\x04\x3a\xbf\x9f\x2c\x0b\x04\x02\x93\x34\x01\xa3\x1d\x2b\xd7\x1f\x33\x72\x23\x84\x0a\x9e\x6a\xfb\x40\x17\x4e\x96\xbc\x3c\x7f\xbc\xe4\x94\xf6\xbe\xfb\xce\x72\x4b\xcb\x8c\x55\x38\xad\x7d\x6e\x26\xac\x87\xc2\x9a\x1e\xa4\xde\x7f\xca\xf5\xe9\xc3\xdd\x50\x74\x74\x5c\x72\x43\x56\xe9\xee\x67\xe6\x04\x04\xed\x1a\x56\x95\xe1\x5d\x2b\x8f\x3c\xb7\x93\xae\x66\xd9\xd1\xe3\x9d\xb1\xf1\xe1\x5d\x44\x39\xc7\x0d\x9c\xd5\xa2\x77\x0d\xe3\xdc\xce\xe7\x8e\xac\xa4\x4b\xdf\xf1\xd1\x40\xac\x53\x4f\x3e\x43\x3c\x9a\xb1\xdc\x22\xae\xd8\xe6\xa4\x7b\xf5\xed\x4c\xa5\x9b\xa2\x0f\x4e\x40\xd0\x59\x05\xdb\x35\x0c\x8a\x56\xee\x73\xdc\x60\x72\xf9\x6c\x75\x89\x81\x96\xf8\x1c\xf1\x88\x62\xe5\x65\xa7\xb2\x94\x5f\x68\x44\x76\x8a\x8a\xa6\x7d\x7f\xdd\x05\x5b\x03\x1d\x47\x27\x5e\xb2\x18\x2c\x5a\x17\x38\x74\xf6\x6b\xd9\xde\x60\xe6\x14\xba\xd6\x1e\x16\x07\x53\xc9\xa1\xc1\x51\xdc\xab\x0b\xd7\x8f\xd2\x13\x93\xa7\xae\x02\x46\x07\x27\x7b\x36\x1d\xda\xb4\xe9\x10\xf3\x6e\x41\xf4\xae\x03\x9a\xdd\x72\x68\xe3\xc5\xb7\xde\x7a\xf1\xc6\x43\xdf\x1d\x1d\xd4\x12\xaa\xff\xa5\x53\xeb\xba\x20\x3d\x7f\x97\xf6\xc0\xc1\x41\xf2\xbf\xb5\xac\x9b\xf2\x9f\xd1\x6f\xea\x26\x09\xea\x35\x7a\xce\x43\xd3\x75\x46\xcc\xba\x1e\x65\x71\x94\x72\xd5\xa8\x24\x05\xdd\xc6\x8a\xc1\x38\xcd\x7f\x2d\x38\x88\x88\xf9\x22\x88\x69\x3a\x95\x6c\x67\x5b\xa6\xeb\x5f\x39\xed\x89\x80\xec\xe2\xd1\x41\x62\xb5\xf0\x16\x9b\xd5\xce\xb2\xa1\xbe\x2d\xbb\x3f\xf1\xc9\x2d\xe3\x11\xea\xae\x56\xdb\x43\x26\x23\xe3\xf8\x7f\x3d\x92\x82\xb1\xcf\xa9\xbf\xe6\x1b\xbc\x46\xbb\xc3\x6a\x0c\x71\xf3\x33\xdb\xc7\xf6\xac\x4d\xd7\x5b\xa6\x90\x37\x42\x93\x69\x87\x88\x77\x0a\xa9\x57\xde\x56\xc2\x92\x45\xf4\xbb\x9b\x8d\xd6\x6b\x2b\x81\x08\x0d\xed\x90\xa4\x5e\xf6\x2a\xc2\x6e\x1d\x55\xaa\x21\xaa\xeb\x47\xfa\x49\x37\xc4\xfb\x88\xec\xe0\x45\x26\xd4\xd0\xce\x44\x8b\x92\x31\x9d\x6f\xee\xee\x83\x04\x65\xfe\x62\xa5\xa6\x77\x4d\x6f\x8d\x76\xc0\x9f\x28\x05\x9f\x3d\x72\x7d\xd3\x83\x8b\xbe\xb0\xe8\x44\xcb\xf5\x47\xb2\x5b\xee\xbb\x6d\xd5\xe3\xab\x6e\xbb\x6f\x4b\x76\xbc\x37\x72\xfb\xb1\x7f\x39\xbe\x71\xb9\xf2\xd8\x91\x3b\x46\x83\x7d\x77\xd4\x26\xae\x78\xf4\xf2\x63\x8f\x7c\xfc\xd0\x65\x8f\x5e\x9e\xa8\xbd\x03\x76\x0e\xaf\x99\x3f\x7f\xcd\xf4\xc3\xbe\x1b\x1e\x77\x9a\xcd\xce\xc7\x6f\x58\x7f\xeb\x60\x9b\x28\xb6\x0d\xde\x0a\x86\x1f\xed\x5b\xb6\xab\x27\x64\xe4\xe4\xa6\xbe\x6d\x73\x6f\x7e\xe5\x9d\x93\xab\xd6\x5f\xb7\x63\xc5\x9a\x50\x60\xd5\xf2\x1d\xd7\x5d\xb0\x72\x6c\xfa\x77\xe5\xd6\x7a\xa1\x30\xef\x69\x5f\xcd\x07\xce\xbe\xba\xb7\x24\xd4\x19\xcb\x67\xcb\xe2\x67\x26\x17\xeb\x3c\xcb\x81\xd2\x38\xa6\xf7\xb2\x25\x48\x41\xfc\x56\xb5\x47\x25\xdd\x8f\xe5\x1e\x56\x41\x76\x14\x45\x0b\x10\x82\xa4\x0e\x62\xc7\x39\x1d\x14\xb4\x17\xd2\xe1\x60\xaa\xba\x60\xd0\x07\x6c\xd9\xf3\x52\x65\xb9\xa8\xc4\xdc\xed\xe2\xde\x4b\x4d\xe4\x62\x1b\xbc\xea\xcf\xa4\x14\x93\x8d\x6d\xac\x81\x88\x34\x71\x94\xa0\x22\x76\xa1\x56\x68\x40\xad\xf7\xb0\x5d\xed\xea\x4f\x5b\xee\x9b\x37\x91\x2b\x95\x3b\xb0\xf1\x50\x2e\x7d\x91\xcb\x8a\x2f\x0e\xb5\xd4\xab\xf7\x7b\x6c\xa1\xd6\x7a\xb8\xdc\xf5\xcf\x63\xe5\xaa\x3c\x09\xdd\xa9\x05\x9f\xe9\x9b\xa3\xde\x9f\x5a\x50\xae\xcc\xc6\xb1\xd9\xed\x81\x92\xff\xa2\x82\x3f\x72\x1f\x6a\x44\x49\xea\x65\x88\x8a\x50\x23\x14\x6e\x84\xe2\x41\xf7\x81\x1f\xaa\x41\xfd\x90\xad\x1d\x07\x44\x6c\xf3\xe3\x40\x1f\x48\x95\x4e\xca\xaf\x0a\xff\xab\xfa\xaf\x61\x83\xc7\x5b\xd3\x61\xa8\xb9\xfd\xf1\xdb\x6b\x0c\xb3\xe2\x1e\xd5\xa4\xeb\xd2\x0c\xea\xba\x34\x83\x3b\x9e\x7c\x47\x9d\x7c\xe7\xc9\x1d\x3b\x9e\x7c\x07\x98\x77\x9e\xfc\x6d\xb5\xa3\xf5\x97\x6e\xfc\xf8\xc7\x6f\xac\xe9\x30\x18\x3c\xde\xe1\xad\x5b\x87\xbd\x1e\x5b\x07\xfc\x68\x54\xcf\x4d\x3f\x7d\x55\xcb\xb6\xa3\xfc\x18\x9c\xad\xfe\x6e\x67\xae\x9b\x8b\xc2\xf8\xe9\xf2\xfe\x68\x3b\x64\xb4\xcf\xe5\x1f\xa8\x9b\xc1\x13\x9f\x55\xa8\x55\x47\x8d\xd7\x63\xd0\xea\xaa\x66\xfe\xb1\xba\x25\x6a\x3a\x6c\xc5\x6a\x19\x0c\x1d\x35\x37\x7e\xfc\xe3\xd8\xf8\x3f\xad\x9b\x99\xea\xee\xb7\xa0\x4c\x59\x0f\x51\x1b\x62\x1f\xbe\x4a\x4a\xc4\x9b\xa7\xfb\x4d\xac\x78\xd5\xc8\x3f\x56\x13\x5d\x28\x08\x5f\xf9\x87\x0a\x5f\xa0\xf3\x18\x54\x58\x65\xe6\x7d\x38\x0e\x09\x53\xa5\xdf\xd5\x68\x43\xa1\x86\x68\x88\xd3\x21\x20\x82\x71\x92\x95\xc4\x9c\x24\x2a\xa2\xa4\x5b\x3c\x14\x83\x38\x5b\xa8\x4c\xe1\xa4\xbe\xf6\x5a\xee\xbe\x37\xee\xcb\xbd\xa6\xbe\x06\xad\xaf\x11\xe5\x35\xc8\x9d\x95\x47\x0b\x5e\x4a\xab\x53\xd0\xf0\xa2\x38\xe5\x8a\x02\xad\xf0\x38\xb4\x22\x8d\x42\x2d\xf2\x45\xb4\xb9\x38\x84\x3a\xe8\x5a\xb9\x1a\x6d\x46\x97\xa3\xbd\xe8\x56\xca\x79\xfd\x0c\xfa\x32\x95\xe2\xb7\x40\x43\x2f\x24\xbb\x21\x9e\xa9\x08\x47\x2b\xc2\xe0\x74\x84\x82\x5a\x38\x11\x8c\x87\xcf\x9d\xe6\xbc\xf1\xe7\x0a\xb3\x95\x61\x7b\x29\x9c\xd2\xae\x65\xea\x9d\xac\x5a\x26\x60\x1b\xb1\xd9\x46\x6c\x8a\x6d\xdc\x66\x1b\xb7\x15\xae\x18\x64\x9b\x1c\xb3\xd9\xc8\x88\x2d\x5f\xba\x4f\x4f\x30\xf3\x65\xf1\xac\xa2\xc2\x75\xf9\x3c\x6e\xb3\xed\xd2\x32\xbc\xaf\xf0\x68\x30\xf5\x3e\xc5\xce\xe4\x94\xd4\x20\xec\xa2\x29\xde\xad\x38\xe6\xdf\x3d\x2b\x4a\x9d\xe1\xa2\x70\x02\xfd\x54\xf8\x53\xc7\x68\x3a\x5b\x1e\x11\x65\x52\xd1\x7e\xda\x8b\x88\x76\x44\x05\x1c\x4d\x9d\x57\xe7\x42\xcd\x68\x9d\x46\xad\x15\x75\x83\x78\x3b\xf5\x13\x42\xb1\x01\xa0\x4a\x6c\x58\x90\x0e\x16\xad\xe3\xda\x71\xa8\x81\x29\xa1\x47\x64\xa8\xda\x6b\xd1\x62\xcc\xed\xe2\x94\x27\x0e\xaf\xea\xdf\xf6\xf8\xa6\xa7\x7e\xfb\xde\xa9\xcc\x25\x5b\x33\x19\x5f\x6b\xd7\x0d\x13\x57\x86\xea\xa8\xbc\xab\x2e\x34\x38\x3a\xc8\xe6\x42\x26\xfe\x67\x0f\xac\x5f\xe8\xcb\x2e\xdc\x35\x67\x87\xfa\xde\x66\xab\x64\xb3\x05\xea\x43\x17\x7c\xec\xd1\x25\xbb\xbe\xb3\x2b\x92\xb8\xe9\x94\xcb\x58\x5f\x5f\x0f\x7f\xc0\x3b\x37\x04\x66\x67\x0e\xe6\x9f\xd8\x6d\x0d\xd7\xd4\x8a\x2e\xb2\x3b\x34\xc7\x3e\x21\x52\xf9\xdb\x9f\xed\x73\x42\xa9\xc1\xc1\x3d\x79\x36\x2a\xb1\xcc\x75\x21\x31\xe8\xf7\xad\x9f\x63\x34\xc8\x61\xfc\xdb\x90\xc3\xd9\xd2\x1b\xe9\xcb\xc8\xbb\x2c\xac\x4d\x72\x20\xc4\x95\xea\xce\x22\x33\x6a\x46\x71\xb4\x10\x5d\xa3\x7d\x87\x1c\xef\x4c\xcb\xf4\x08\x29\x2e\x9a\x8a\x44\xdb\x8d\xa1\x06\xde\x49\x2b\xe5\x76\xba\x12\x71\x39\xa5\xd5\xd5\xe9\xfa\xff\xd5\x2c\x24\xfb\x95\x17\x5f\xfa\xf2\x17\x5e\xfb\x31\xf9\xdd\x1f\xee\x77\xc8\x6c\xa7\x10\x97\xdb\xbd\xad\xa1\x56\x97\xdb\x2b\xef\xf8\xca\xe5\xb2\xa3\x79\xf6\x0d\x4f\x3d\x71\xb8\x2d\xf8\xf1\x89\x2f\xfc\x8f\xda\x0a\x7b\x72\xb6\xed\xcf\x8e\xc0\xd3\xdf\x33\x5c\xff\xdc\xd5\x6a\xe7\xd7\xaf\x6b\x1b\xe7\x8c\xc4\xc7\x79\x78\x99\x33\x33\x0c\xf9\xe5\x9c\x94\x91\x3b\x65\xc7\xfc\x73\x1b\x0c\xcf\x37\xc3\x1f\xff\x67\x0d\x89\x91\xa0\xd1\x25\x94\x7f\xd0\xa8\x7b\xe3\xac\xe2\x1f\xb8\x1c\xd5\xf6\xa7\x78\xc9\x4c\x0c\x05\x13\xd3\x26\x89\x93\x54\x10\x4a\xb4\x59\xab\x69\x66\x2e\x8a\xda\x56\x61\x79\xa7\x8d\xe1\xb6\xa9\x63\xfc\x6a\xe6\x1d\xfa\xfe\xae\x82\x8f\xd1\xe9\xec\x35\x97\xc3\x08\x22\x74\x40\x3b\x64\xa0\x8f\x42\x58\xcf\x58\x4c\x7c\xd9\x4c\xdc\x36\x13\x5e\xa0\x1e\x65\xdc\x96\x3e\x41\x60\x60\x8f\x1e\xc0\x1f\x9b\xb1\x02\x87\x67\xe6\x44\x31\xc1\x33\xef\x09\x02\x63\x67\xdc\x02\x6b\xd6\x03\xf9\x9d\x33\x57\xae\xac\x1b\xff\x4d\xe4\x44\xdd\x74\xf6\x2c\xc0\xd3\x68\x15\x72\xbb\xea\x80\x02\xd6\x39\x44\x52\x00\x71\x90\xa2\xed\x10\xad\x4a\xe4\xb4\x33\x6e\x17\x56\x28\x82\x8d\x4e\x6e\xd7\x35\x45\xd5\x6b\x65\x99\x13\x1a\x5a\x52\x3e\xce\xe0\xe0\x48\x0d\x6e\xb9\x3f\xfb\xfa\xc3\xd3\xd3\xc0\x27\x4f\x3d\x01\x2f\x2c\x6c\xb6\xb3\x45\xda\xbb\xde\x6e\x6f\x5e\xa0\x5e\x23\x27\x65\x75\xd9\x9c\x07\xf6\xef\xef\xb4\xd8\xc1\xe0\x85\x7b\x3e\xbb\x68\x85\x30\x51\x95\x4e\x3d\xe3\xfb\x97\xa7\x74\x5a\x15\x4f\x3d\xc5\x1d\x60\xc7\x91\x09\xc5\x10\x82\x36\xe8\x00\x62\x77\xb3\x24\x6a\x04\x99\xe2\xb7\x86\xa9\xcf\xa3\x8c\x0c\x91\x74\x26\x2c\x6b\x14\xb8\xcc\xfa\x81\x79\x04\x40\xfd\xd4\x80\xff\x64\x37\xf4\xf5\x58\xe0\x3d\xf5\xfe\x75\xac\xcb\x6d\x77\xab\xfd\x6a\xbf\xdb\xee\x76\xb1\xeb\xd4\x8f\x07\xa4\x36\xf8\xeb\x9b\x8e\x3a\x9f\xf3\x4d\xf8\x6b\x9b\x84\xe7\x9d\x49\x9a\x7a\x60\x60\xb2\xb7\xfe\x71\xd8\x3a\x00\x29\xf5\xd3\xaa\x25\x18\xb6\xbc\xfd\xb6\x25\x1c\x84\xff\x86\x2d\x81\x0c\xbf\x04\xbe\xdf\xd4\xa4\x76\x2d\xe1\x33\x25\xec\x5d\x85\xea\x18\xa3\x32\xa8\x7e\xb0\xa1\x1d\xd2\x54\xc1\xcc\xed\x07\xf6\xc6\xbc\x62\x8f\xb1\x26\x57\x6d\x3e\xe7\x0a\x99\x24\x07\x8b\x04\x5b\xad\x64\xe5\x99\xcf\x4c\xa0\x10\x66\x43\x2e\x9c\xad\x6d\x8d\x99\xb0\xc2\xcb\x62\x53\x11\x6b\x53\xa3\xcd\x31\x62\x51\x27\x45\xf0\x37\x42\x50\x97\x00\x96\xc4\x7c\xc1\x82\x2e\x85\xbe\xd1\x2d\x3b\xa1\xce\xa4\xe3\x6e\x97\xc3\xaa\x2b\xbd\xb4\xe1\xd5\x79\x05\xaf\xce\x3f\xc5\x28\x45\x51\xc5\xe4\xd8\x34\xc9\x05\x59\xfd\x57\x93\xd7\x64\x34\xfe\x8d\x0a\x76\xf0\xea\xfc\xcf\xf0\xea\xfc\x48\x85\x74\x83\x8c\x54\x48\x38\xfe\x66\x34\x9a\xbc\xa6\xbf\x4e\x3e\x25\xa1\x82\xff\x22\xa6\xec\x47\x65\xb0\xcc\x47\x91\xaa\x74\xc6\x33\x0e\x8e\xd7\x7d\xc4\xd4\x01\x65\x80\xd1\xed\x5e\xa6\x38\xcf\x39\xb5\xb9\x2f\x9d\xe9\x63\x53\x85\x08\x08\x74\x0e\x77\x16\xff\xf0\xd7\xe9\xe9\x44\xb2\x15\x8f\xcf\xbb\x43\x59\xdd\x9a\xdc\x35\xb6\x2b\xd9\x5a\x38\xa5\xb7\x65\xe6\x0e\x35\x47\xed\xf4\xd2\x43\xb3\x30\x5f\xa7\xa7\xc5\xf4\x38\x92\xbc\xb0\x46\x7d\xf3\x60\xa4\x25\xd6\xb7\xc0\x5b\x73\x61\x52\xdb\xb8\x27\x2f\xac\x21\xc9\x72\x58\xb5\x7a\xeb\xed\x35\xe1\xe6\x9e\x15\x85\x48\x1d\xeb\x5e\xa1\xb6\x9c\x02\xaa\x41\x61\x94\x45\x1b\xd1\x4e\x74\x1d\xba\xa5\xe0\x21\xb8\xc0\x79\x74\x39\xdc\xba\x4e\x2c\xd5\x71\x89\x54\xd0\x8b\x6c\xc9\x46\x21\x9a\x01\x3f\xf4\x03\x85\xa8\xc8\xb8\xdc\xe0\x02\xbe\x04\x96\xe3\x06\x3e\x42\x95\x11\xfb\x0b\x86\x08\x4c\xc5\x23\xa0\xe2\xd1\xec\xb4\x97\xc2\xd7\xa6\x90\xd9\x63\x36\x1a\x01\x69\x9d\x37\xa6\x7b\x5a\x1a\xaf\xb0\x85\x65\xb1\x0e\x81\xa3\x3e\xe3\x74\xfe\x09\xec\xb5\xab\x6a\x8f\xf9\x7c\xea\x1f\xa5\x90\x13\x86\xd7\xe4\x1f\xf8\x93\xfa\xa7\x02\x9c\x0e\x48\x52\xc8\xa9\x3e\x5d\x40\xcc\x81\xe5\x4e\x7c\x57\xc5\x63\xf2\x7f\xd6\x1f\x0d\x0f\x4c\x7b\x21\x18\xa7\x10\x1d\x09\x40\x4f\x89\x0a\x73\xdc\x71\x9a\x7e\xec\x86\xd5\xf7\xad\x5e\x0b\x2b\x9c\x21\x49\xfd\x63\x2d\xe8\xe0\x3a\x20\xff\xc9\xe9\x54\x9f\x5e\x87\x37\x49\x20\x15\x00\x77\xd4\x3f\xbe\xeb\x74\xc2\xf0\xba\xeb\x69\x06\xf5\x4b\xce\xcb\x74\xa7\x51\xa8\xe2\x91\x9f\x9d\xf6\x32\x6d\x3e\x18\x41\x88\x4c\x52\xbe\x66\x8f\xae\xd7\x39\x4d\xf2\xad\xcd\x66\x62\x65\x2c\x55\x74\x2f\xc0\x42\xd3\xb5\x14\x32\x52\x30\xee\xc7\x38\xe7\xb1\xbd\x6b\xf3\xd0\x03\xf4\xd4\x47\x17\xb5\x46\x9b\x32\x1e\xdb\xbb\x56\xe7\x2d\xcb\xbb\xe3\x17\xf7\xce\x6d\x09\x2d\x16\x24\x8b\xf0\xa8\xc0\x1a\xc6\x60\xd6\xf0\x23\xb7\xac\x02\x4f\x31\x83\x07\x2f\x4e\x6f\xea\xee\xa9\x75\xb9\xd7\xd4\xd8\xeb\xc3\x72\xdb\xea\x63\xa1\xda\x39\x1d\xcd\xd9\xba\x9a\x8b\x6c\x86\xfd\x26\xbf\x00\xa6\xbe\x9d\x0f\x14\xf7\xda\x58\xfb\x9e\xfd\xa8\x7d\x3a\xf2\x85\xee\xa6\xb7\xb8\x90\x39\xb5\x6f\x96\x54\xaf\x6e\x8a\xce\x03\x8e\x78\xb3\xd9\xa2\x2b\xec\xac\x37\xa2\xe8\xbe\x68\x74\x20\xb2\x12\xec\x05\x28\x05\xc1\x58\x3e\x17\x61\x76\x50\xc1\x92\x6e\xf8\x8a\xd1\x16\x84\xb0\xbf\xe4\x77\xa4\xea\x25\x32\xd1\xf7\xd3\x51\x12\x29\xd8\x70\x57\x3e\xde\xef\x83\xa8\x76\x19\x05\x1f\x84\xbd\x90\xf5\x86\x21\x30\xae\xdd\xd4\x0e\x0c\x97\xa7\x09\x09\x05\x44\xd3\x66\x2c\xc4\xaa\xec\xe5\x28\x8c\x96\x6a\x75\x0d\x75\x40\x24\x4a\x5d\x1c\x5a\x21\x98\x4a\xc8\x24\x94\x0a\x52\xc8\x83\x44\xba\x1f\x07\x9d\x21\x22\x83\x33\x48\xd5\x89\x99\x62\x1f\x45\x75\x1f\x36\xd4\x52\x27\x91\x22\x1f\xf9\xfb\x49\x8f\x81\x10\x20\x0c\x98\xac\x9f\x54\x55\xe5\x7b\xcf\x1e\x06\xc7\x51\xec\x34\x10\x42\x0c\x35\x77\x02\xec\xff\xfa\x0f\xf1\xef\xf3\x2a\x61\x92\xcb\x2f\x5a\x9e\xec\x6e\x4a\xb4\x8b\xae\xcb\xbc\xe1\xd5\x97\x5d\x75\xc7\xec\xc1\xf5\x43\x19\xf2\xd6\x63\x8f\x4d\x36\x1b\x2d\x84\x37\x62\x87\xe7\xcc\x63\x10\x02\xdb\xe3\xbf\x61\x22\x46\x8b\xd1\xd2\xfc\x9b\xc7\xd5\xf7\xd4\x9f\xe0\xc7\x5e\xae\xf5\x49\xd9\xd1\x79\xfd\xed\x7d\xc1\xc8\xec\xa8\xb9\x76\x63\xb8\x6e\xee\xde\xad\x9d\x9b\xba\xe7\xb4\xf4\x04\x87\xf5\x75\x88\x9d\x42\x1c\x22\xb7\xa0\x30\x5a\xf2\xe1\xea\xc6\x9e\xbb\x6e\xe4\xc3\xd7\xed\xed\xbc\xca\x90\xe9\x75\x1b\xbe\xe2\xaa\x3b\x16\x6c\xdd\xb6\x94\x39\x7f\xd5\x7e\xfa\x72\x6d\x1b\x9c\x5d\xb3\x81\xcb\xe6\xcd\x99\x1f\x1d\xa6\xf5\x02\x84\xf8\x83\xac\x8e\x37\x87\xc2\x10\x34\x82\x8b\xe3\x81\x8e\x90\x68\x84\xae\x63\xc1\xb8\x8b\x28\x30\x9c\x47\xea\xd3\xdc\x7b\x56\x73\xcd\xa4\x12\x99\x93\x47\x91\x7e\x9b\xd5\x5c\x43\x94\xc8\x1c\x82\x22\xfd\x14\x67\x8f\x49\x35\x0c\xfa\x26\x51\x6b\x53\x43\xc3\xa0\x8f\x41\xad\x4d\x3a\xbf\xef\x0d\x3a\x97\xee\xd4\x31\xb2\x28\x7a\xb6\xd3\xe1\xe2\x9d\x0d\xbc\x88\x75\xf4\xe7\x92\xed\xb1\x1f\x17\xc8\x0f\xea\x23\x24\xda\x90\xb2\xfb\xb1\x4e\xe8\xa6\x92\xd4\x45\x52\x01\xa8\x84\x82\x4d\xa7\x33\x4e\xad\xf9\x9d\x0e\xb7\x8e\x3c\x1d\x77\x71\xca\x85\x2b\x9a\x96\xb4\xcd\x0f\x5f\x15\x00\x97\xb9\xe1\xe0\xce\xf6\xde\x35\xa1\xa6\xd0\x15\x2b\xd7\x5c\xef\x0f\xfb\xdb\xc3\xc3\x9b\x8f\x1b\xc3\x46\x01\x30\xc6\xf5\x61\x72\x7c\xf3\x70\xb8\xdd\x1f\xf6\x5f\xbf\x76\xf8\x8a\x50\x53\x68\x4d\x6f\xf6\xad\x0e\x60\x59\xf0\x84\x5a\xdb\x5c\x5d\xb3\x87\x5b\x56\x6d\x80\xaf\xae\xd4\x6e\xed\x8b\x9e\x88\xb2\x40\xec\xa6\x54\x57\x78\x7e\xdb\x92\xa6\x15\x17\x6e\x58\xd5\x32\x3c\xbb\xcb\xd5\xd6\x1a\xf2\x60\x06\x63\x00\x06\x55\x65\x2d\x94\xa4\x2b\xe5\xaf\x7a\x5b\x81\x2e\x63\x14\xea\xcb\x2e\x41\xbf\x47\xc4\x3b\x4b\xde\xd2\xa9\x02\x7a\x04\x69\x5f\x27\xe5\xbc\xa3\x40\x21\xac\x2d\x09\x01\xba\x24\x04\x5c\x8c\xa2\xfe\xf4\xa7\x14\x86\xb0\xc0\x6f\x00\xf4\x53\xf5\xa7\x91\x64\x44\x07\x59\x8c\x24\x23\x53\xe8\x94\xfa\xf7\x53\xa7\xc0\x70\x8a\x64\x95\x5f\xa8\xcf\x7a\x0e\xe9\xca\x95\x87\x3c\xb0\xe8\x17\xfa\x94\xa1\xe3\x37\x52\x94\x9c\x1d\x2a\x3a\x74\xea\xd4\x21\xac\x1d\x11\x41\xc2\x94\xc2\x5e\x4b\xf5\x5d\xe7\x69\x2b\x3b\xf0\x91\x52\x71\x8c\xa0\x6b\xd1\xf3\xae\x44\xbc\xa2\x90\x67\x55\x20\xca\x57\x62\x1e\xb8\x1c\x61\xd0\x41\xd0\xc1\xba\xbd\x39\x92\x8c\x30\x97\xa9\x0f\x9c\x3a\x94\x49\x8f\x5c\x72\xc5\xb3\xb4\xbc\x67\xd5\x67\xff\x55\xaa\xc9\x6b\x5a\x65\x32\x31\xaf\xd2\xb3\x7a\x53\xfe\xd8\xa9\x43\x3b\x3e\x8b\x57\x6c\xbf\xf4\x6a\xbd\x02\x29\xec\x57\x1f\x50\x0e\x9d\x92\x47\x12\x85\x8a\x78\xa7\x55\x55\x98\xaf\x9a\x4c\xab\x4c\x5e\xed\x11\xda\xf9\xa6\xfc\x31\xad\x86\xd7\x97\xf4\xa4\x75\x3f\x49\x0d\xba\x9e\x43\x3a\x93\x96\xed\x0e\x91\xa5\x0e\x2f\x4b\x58\xe4\x4c\x56\xcd\xee\xdd\xf4\x87\xdc\xbc\xad\x87\xaf\x3b\x90\xb2\x59\x7c\x16\x5b\xea\xc0\x75\x87\xb7\xce\xd3\x15\x5e\x70\x16\x2b\x13\x77\xf7\x2f\xfd\x3a\x79\x3a\x8f\xd6\x3d\x71\xeb\xbe\x55\x4b\xbc\x3c\xc7\xf1\xde\x25\xab\xf6\xdd\xfa\xc4\x3a\x7d\x62\x2c\xd0\x4b\xa8\x84\x0f\x11\x42\x8b\x10\x72\x07\xed\xc1\x70\x95\xf6\xc3\xd9\xd7\x55\x16\x43\x05\x42\xaf\x14\x4a\xc4\x5d\x0a\xab\x9c\x51\xa0\x02\xe2\x85\x54\x28\x81\x82\x32\x94\x3c\x43\xbd\x2d\x2a\x9b\x06\xb2\x03\x9b\x40\x3f\x29\xc9\x21\x85\x41\x39\x08\x50\x10\x0d\x4a\xdf\x55\x84\x97\x4f\x50\x11\x15\x8b\x92\x43\xba\xe7\x3c\xfd\x38\x44\xdb\x8d\x50\x9a\x77\x1c\xf1\x68\xa8\xac\x5f\x1e\x2e\xc0\x3a\x86\xdb\x21\x15\x74\x4e\x57\xac\xcd\xa4\x42\x0d\x85\x3d\x46\x3b\x64\xfa\x98\xb2\x82\x74\x30\x99\xce\x84\x29\x5c\x0c\xd6\x35\xcb\xc9\xe7\x2c\x06\x0b\x43\xd4\xac\x59\x9c\x42\x57\xdf\xab\x2f\x7e\xfb\xb7\x06\xba\x77\x2d\xea\x75\x30\xf6\x98\x4d\x70\xdb\x2d\xac\xdc\x39\xf7\xb2\xce\x9a\x4d\x87\x36\x89\xd0\x2e\x9a\x21\x47\x18\x8b\xc1\xc2\xea\x7d\x3e\xa2\xe6\x6c\x46\x1e\x46\xb0\x64\xde\xe1\x7e\xfa\xda\x49\xba\x54\x91\xc0\xe8\x13\xfe\xab\x3b\xba\x97\x06\x0d\x21\xde\x12\xf7\x98\x02\x83\x73\x17\x48\xcd\xad\x5a\xad\x82\xf5\x66\x09\x8f\x00\x6f\xd4\xea\xd6\x38\x15\xe0\x74\xb9\x64\x5b\x85\x07\x5a\x87\x46\xbd\x12\x8e\x67\x75\x04\x9f\x8c\x0c\xa5\x90\x56\xfe\x4c\xba\x31\x18\x77\xb1\x63\x94\x50\x05\xcf\x03\xcf\xac\xbc\xc6\x81\x45\x55\xe1\x8d\x16\x73\x56\x60\xd7\xaa\xff\xa5\xbe\x4d\x38\xd1\x98\xb5\x5b\xc6\x4d\x36\xb8\x79\x64\xf8\x14\xac\x01\x56\x74\x30\x3a\xc5\x0a\xca\xfb\xea\xfd\x5f\x1e\x1e\x51\x3f\x6a\x33\x8d\x33\x46\xad\xd3\x1c\x50\xb3\x16\x8c\x59\xd9\x01\x8a\x88\x1d\xd7\xac\xfc\xe6\x5d\x72\xc9\xbf\xcf\x69\x7d\xbf\x01\x24\x28\xa7\xa3\x91\x16\xed\x1c\x24\x41\x99\x04\x29\xbe\x35\x77\xfa\x51\xf5\x99\x67\x04\x5f\x6d\xe7\x13\x3f\x54\x9f\xf9\xa1\xfa\x2b\xed\xf8\x09\x66\x72\xfb\x97\xba\x7b\x9a\xf1\x44\x9e\x25\xd9\xce\x40\x70\x72\x11\x79\x56\xfb\xc1\xa2\x95\x4b\x96\x7c\x7b\xba\x1e\x8c\x36\xe1\xa0\x70\x26\x9d\x8c\x1a\xa1\x88\x55\xcf\x51\x6b\x94\x4a\x51\x0f\xf9\xd8\x0e\x59\x56\x5f\x82\x84\x2c\xef\xd0\x76\x74\x73\x64\x19\x5e\x90\x93\xf8\xb6\x2a\xae\xe6\xc7\xb4\xbb\x90\x80\x84\x9c\x94\xb5\x1c\x73\xf4\xc4\xf8\xc7\xe7\xc4\x57\xd7\xdf\x0f\x69\x6a\x6d\x42\x31\xd5\x8d\x05\xf0\xf7\xca\xf7\xe3\x97\xe0\x85\xc2\xe3\x76\xc8\x32\x24\xd4\x97\x68\x41\xc8\xc2\xea\xf7\x6b\xa5\xd2\x8a\xa6\x17\xf3\x25\xf5\x25\x9a\xe3\x7c\xef\x87\x4c\xba\x68\xed\xa2\x43\xe0\x1b\xab\xde\xcf\x7c\xac\xa2\x36\x72\xb9\x92\x50\xdd\x00\xa0\xb7\x40\x75\x61\xa1\xba\x00\x33\xf4\x41\xb1\xf9\x8d\xc5\x86\xa8\xee\x83\xb6\xb3\xea\xa5\x77\x42\x35\x6b\xf9\x1d\xda\x08\xd5\x1d\x86\xf7\xce\xd0\x06\x59\x6a\x3b\x62\xa7\x23\x2c\x13\x94\x83\x56\xe8\x80\x90\xcc\x26\x52\x61\x39\x18\x85\x20\x61\xc3\xcc\xa8\x6d\xf2\xce\x0e\xbc\xcd\xf5\xbd\xe7\x85\x2f\xba\x60\x94\x81\x4b\xe3\xf9\x7d\x56\xb5\x93\x55\x94\xfc\xb7\xf2\xdf\x21\x4f\x7e\x31\xff\xfb\xdf\xa4\x52\x77\xaa\xbf\xdf\x06\x5b\x71\xe0\x2b\xf0\xfa\x99\x2d\x8f\x3c\x42\xc7\xaf\x65\x2a\xcb\xfd\x77\x01\x43\x2e\x68\xc4\x72\x90\x67\xc3\x72\x50\x0e\x66\x82\x20\xb3\x6f\xaa\x7f\x9d\x7c\x23\xbf\x70\x11\x34\xd5\xc1\xe7\xe0\xb7\xf3\x27\x16\xcf\x61\x9e\x8d\x4c\x2c\x66\x95\x33\x2f\xaa\xef\x81\x19\xb6\x1d\x7b\xf8\x61\x58\x0d\x4d\xdf\x2e\xb4\x95\x8d\xd7\x7d\x76\xac\xad\xf8\x56\xf5\x79\xa8\x03\x38\x26\xd0\x18\x3d\x0b\x87\xd6\x0f\xee\x8a\x6d\x73\xc5\x06\xd4\x99\x28\x4a\xb9\xed\x7d\x90\x29\x82\xd5\x92\x9c\x3e\x2b\xed\x70\x18\x18\x8b\xf9\xe2\xbd\xea\x6e\x35\xa9\xee\xde\x7b\xb1\x51\x64\x0c\x0e\x49\x84\x11\x97\xc1\x60\xdd\x36\xef\xbd\xfb\x75\x62\x7b\xce\xc2\xe3\xaf\x1d\x5f\x38\x47\xbf\xb8\xff\xbd\x79\xdb\xac\x06\x83\x0b\x46\x44\x89\xf9\x2d\x9d\x9b\x26\xc7\xd4\x31\x97\x01\x1b\x2f\xbe\xfb\xb1\xc7\xee\xbe\xd8\x88\xf5\x9b\x0e\xd9\xb6\x6d\xc3\x7e\x07\xbe\x9d\x52\xef\x9f\x69\xd8\xb3\x70\xf4\xf8\xf1\xd1\x85\x7b\x1a\x3e\x43\x23\xf2\x37\x3a\xf6\x6f\xd8\x66\x93\x1d\x92\xfe\xfd\x53\xba\x21\x74\x96\x8f\xad\x6e\xb0\xeb\x9e\x48\x0b\x48\x02\xd4\x5b\x2f\x13\x28\x3b\xf5\x0a\x14\x28\x83\x82\xbb\xaf\xb2\x48\x8c\x62\x01\x67\xa9\x3f\xaf\x67\xb5\x92\x6b\x6f\x57\x73\xd3\xe5\x59\xfa\x1e\x9f\x52\x2b\x65\xa4\xdb\x48\x80\xb3\xb9\x02\xc8\x86\x0a\xbf\x73\xc9\x44\x74\x08\x5b\x70\x15\x6c\x9f\xe0\x12\xdd\x51\x29\x65\xff\x7f\xe1\x3c\x42\x11\xfc\x7b\x1d\xb2\xf6\x12\xe8\x7b\x53\xcb\x8f\xd7\x94\xb2\xb6\xe6\x0f\x9c\x57\xb2\x43\xf9\x29\x18\xb1\x0a\x29\xe2\x69\x9d\xb5\x63\xac\xd6\x9d\x3e\x4b\x97\x5a\xe9\x8c\xd1\x76\xca\xc5\x3a\x31\x9a\x39\x4c\x02\xc5\xd0\x8c\x87\x92\xce\x0b\x94\x71\xbd\xce\x2a\x87\xfd\x3c\xd7\x95\xe5\x98\xe9\x00\xe5\x32\xc0\x4f\x66\x0a\x56\xfa\x9c\xe6\x51\x2d\x4a\xa1\x05\x15\xba\x2f\x11\x14\x8d\x50\x39\x11\xf5\x91\x00\x94\xf6\x88\xe0\x76\x68\x8c\x46\x78\x3d\xde\xc5\x48\xfa\x8d\xb3\x3d\x34\x62\x5d\x65\x18\x3e\x2f\xa8\xcf\xfe\x4e\x74\xd8\x85\x07\xdf\x30\x83\x24\x28\x82\x03\x0e\xb2\x3b\xbe\xf4\x3b\xf5\xcd\x07\x45\xa3\x49\x12\x7e\x08\x1b\x4f\xf3\xf4\x86\xc9\x0c\xf5\x95\x9a\x91\xba\x45\x7f\xc3\xef\x60\x91\x00\x0e\x41\x11\x24\x30\xbf\xf1\xa0\x60\x77\x08\x0f\x42\xfd\xef\xbe\xb4\x83\x05\x93\x89\xc6\xf2\xa7\xd5\x47\x7f\x28\x48\x26\x23\x79\xa9\x5a\x5f\xb2\x2c\xc3\xab\xad\xf2\x80\x41\xa7\x72\xea\x9c\x87\xee\x25\xce\xf2\x92\xf0\x4c\x20\x90\x1f\xaf\x0f\x06\x02\x36\x9b\xdd\x7a\x16\x72\x7e\xfe\x01\x69\xa9\x04\x59\x59\x92\xc3\x79\x25\x2c\x1b\x8c\x88\xa0\xf4\x54\x8a\x7b\x91\xfd\x57\x4a\xcb\x75\x20\x64\x64\xcb\xab\x85\x36\x49\xeb\x2c\xe1\x74\x32\xd2\xc0\x47\x8b\x14\x30\xe5\x84\xb9\x5d\x0e\x06\x41\x4f\xfe\x79\xf5\x79\xb8\x0c\x8f\xca\x32\xf5\x3d\x92\x3f\x2e\xcb\x30\x2a\xa5\xc9\xd1\xc9\x3d\xe1\xcb\xc3\x07\x3a\x77\x8d\x75\xee\x0f\x87\xc9\xd1\xf0\xe5\xe1\xfd\xda\xc5\x81\x30\xd3\xa3\x3e\x9f\x7f\x1e\x7a\x54\x2d\x57\x52\x4b\xad\xe5\x4a\x6a\xf9\xf1\xdd\x93\xd7\x85\xc3\x07\x3a\xc7\x76\x75\x1e\x08\x5f\x1e\x26\x47\xc2\xe1\xfd\xda\xc5\xfe\xf0\xe5\xd3\xda\x45\xdf\xfb\x57\x9b\x2c\xcf\xa0\xcb\xaa\x2b\xcc\x92\xb3\xf4\x6a\xa9\xf6\xaa\xce\x62\x98\xae\xad\x4a\xa6\xf9\x35\xed\x98\x81\xc3\x70\x1e\xbd\x2e\x46\xd1\x9d\x3e\x4b\x22\xd1\x91\xdc\xca\x0a\x5d\x4a\xa5\xdf\x53\x3c\x5e\xe2\xd7\xab\x71\xea\x16\x55\x4f\x49\x6e\xa9\x74\x81\x8a\x40\x2b\x11\x39\xc3\x1e\x44\x3e\x84\x80\x6b\x81\x32\x58\x79\x3a\x11\xb4\x87\xca\xee\x7f\xc9\x19\x29\x96\x93\xc4\x7c\xd6\x69\x30\x58\xc6\x8c\x36\xc8\xe6\x62\x92\xdd\x0b\x59\xa9\x4f\x82\x6c\x2d\xf9\x6c\x78\x72\x4c\x94\x24\x87\x35\x67\xc6\x4a\x38\x5c\x0f\x8a\xcb\xa5\x2a\x01\xba\x96\x91\x29\x85\x9c\x61\x91\x36\xda\xe4\x22\xff\xa6\xa0\x4a\x98\xd1\xa6\xe3\x20\xa5\x10\xd3\x01\x9c\x13\xe4\x5c\xac\xb1\x56\xcd\x49\x7d\x92\x9a\xf3\xda\xa5\x58\x4e\xcd\x89\xe6\x31\xc1\x68\x64\x91\x2c\x4e\x3e\xbc\x34\xa0\x2a\x2e\x17\x28\xf5\x91\x30\x56\xcc\x39\xd1\x21\x4f\xa7\x05\x1a\x2b\x68\x01\x88\x96\x69\x81\xb3\x3e\xc3\xa7\xf0\x8e\xc2\xea\xde\xf6\x6f\x05\x72\x40\xa3\x89\x76\x54\xf6\xe2\x3b\x78\x47\x81\x16\x68\xfb\xb7\x42\xe2\x07\x65\x72\x5b\x65\x7f\x96\xe7\x7d\x0e\xd9\x90\xb3\xd0\xa7\x6e\x3e\x94\x0a\xa5\x28\xbc\x02\x6d\x3f\x23\xb1\x43\xc1\x99\x91\xf5\x6c\x1d\xb9\x8f\x9f\x48\x76\x8e\xc0\xab\xa2\x5d\xfd\x85\x5d\x10\xed\x10\xb2\xab\x13\x38\xa0\x8e\xe7\xc7\x89\xb2\xd1\xe7\x3b\xe1\x1b\xf6\x6d\xc4\x63\xd3\xbc\xb2\x7e\xe1\x44\x72\xa4\x13\xbe\x21\x68\x59\x44\x41\xcb\x92\xcf\xe2\x00\x04\xf2\xe3\xea\x38\x1e\xd9\xe8\x1b\xf6\x9d\xf0\xf9\x36\x8e\x9c\xeb\xbb\xaf\x41\x4d\x25\xbd\x4b\x9e\xab\x2f\x7a\x0c\xca\x80\xce\x40\x98\x51\x6b\x3b\x40\xe1\xe1\xf3\xbf\xd7\x1b\x02\xbb\xee\x91\x6a\x2d\x42\xb4\x6a\xd8\x8f\xc0\xb8\x37\x12\x6d\xaa\xd3\xd2\xd1\x96\xc3\xae\x7b\x64\xd6\x8e\x9b\xab\xfd\xe5\xeb\xe5\xa0\xbe\xfc\x8d\xc5\x49\xa7\x0e\x1a\x44\x56\x67\x51\x64\xd2\x51\x9c\xe9\x83\x84\x7e\x75\x16\x42\xd9\x3b\x30\x22\xcb\xea\x98\x3f\x1a\xdb\xfb\x9d\x5b\x2f\xe9\x0c\x9a\x1e\x33\x8b\x3c\xe7\x22\xad\xa3\xed\x8f\xdf\x19\xb3\x58\xbc\x38\x32\xad\xb9\xbe\x0c\x23\xda\x4c\x30\x52\x6f\xb7\x37\x8f\x45\xfb\x37\x8f\xdc\xb4\xbd\xe7\x2b\xff\x61\x21\x46\x0f\x6c\xd9\x9b\xec\x18\x6b\xb6\xb3\x38\x37\xad\xb1\xca\xf3\x3f\x46\x1c\x92\x90\x9f\xca\x53\xc0\x0e\x76\x64\x6b\x87\x82\xe6\xe1\x34\x37\x54\x58\x01\x34\x85\x40\x51\x11\x09\x54\xa8\x18\x9e\xa5\x80\x08\x39\x45\x81\x15\xf9\x5f\x4d\x21\xec\x57\x7f\x41\x95\x14\xf5\xd4\x78\x73\xd5\x92\x5c\xc6\x73\x13\x50\x9d\xb6\xcb\x82\xf2\x47\x93\x08\xc6\xab\x67\x8a\xea\x56\x62\x6e\x94\xdc\x6a\x4e\x1e\x90\xd5\x9c\x5b\xb2\xc7\xb0\x12\x3b\x51\xd0\xf3\x14\x08\x85\x52\xa8\x6c\x22\x72\x71\xa8\x5e\xcd\xd6\xd6\x42\xae\x3e\x14\xca\x07\xa6\x29\x85\x56\xcd\x5f\x55\x65\xd2\xa7\x8b\xc2\x24\x71\xfe\x32\xd9\x63\x79\x25\x66\x97\xdc\x90\x95\x07\x64\xc8\xba\xf7\x9c\xbb\x4c\xf0\x99\x50\x28\x54\x0f\xb9\xda\x5a\x35\x5b\xaf\xfe\xec\xc3\x97\x89\xea\x29\xeb\xf2\xdf\xb4\x1b\xce\x5b\xa6\xac\xf6\xfc\x90\xfe\xae\x9f\x57\xca\x42\xab\x06\xf7\xc3\x15\x4d\x69\xd7\xda\x36\xff\x36\xa1\x33\x31\xcd\x41\x5e\x9e\xee\xe7\x58\x23\x64\xfe\xc2\x2a\x68\x04\xa1\xb0\xdb\xc5\x59\x41\xe4\x43\x0d\x28\x5a\x22\xa9\x23\x99\x52\x30\x8d\xa8\xb7\x6e\x97\x55\x17\x97\xb2\xa1\x06\x8e\xd7\x89\x70\x2e\x14\xe4\xdc\x7a\x50\x84\x50\x90\x62\x4c\x31\xfd\x90\x76\xbb\xc8\x2b\x21\x62\x31\xb3\x8c\x20\x7b\x6a\x83\x0d\x51\xf9\xf7\xea\x23\xfd\x9b\xb5\x06\x1a\xc0\x64\x9e\x56\xa8\x2d\xf3\xe0\x92\xf1\x1d\x1b\xcd\x46\x8e\xb4\x10\x97\xc0\x30\x56\x47\x4d\x6d\xbd\x78\xe0\x07\x71\x78\xcd\x66\x34\x11\x0f\x5b\xab\x7a\x08\x81\x17\xad\x26\x23\xf1\x60\xc9\xac\xee\x9f\xf5\xe2\x41\xa9\xb1\xde\xe7\xb4\x31\xac\x20\x58\xfe\xf3\xa4\xc5\xc9\x00\x26\x1c\xcb\xb2\x0c\x06\xf6\x17\xb2\xb0\x5b\x90\xbb\x66\x49\xe2\x35\xa2\xf4\x2a\x20\x37\xb1\x98\x85\x93\x82\xc0\x00\x10\x86\x10\xac\xec\xb2\x58\xc4\x6b\xbc\xe1\xf9\x16\x8b\x75\x97\xd9\xba\xe7\x30\x61\x58\x96\x01\xcc\xf2\x7c\x61\x3f\x4e\x26\x59\x05\xf5\x97\xb5\x6a\xa7\x73\xf6\x75\x94\x97\xb8\xdb\x0f\x56\xe0\x78\x8e\xba\xc2\xe6\x0a\x0a\x6b\x3a\xe4\x7a\x81\x93\x43\x26\x25\x71\x72\xbe\x28\xc9\xc2\x25\x9b\xb5\x9a\x6e\xfe\xdb\xb7\x9f\x3d\x6e\xc4\x86\x4b\x8d\x82\x60\x62\x9b\x47\xda\xd6\xee\x84\xd9\xd4\x90\xec\x47\xf0\x69\x49\x7c\x44\x94\xe0\x6e\xf5\x5e\x2d\xe5\x71\x41\x86\x83\xb2\x70\xab\x28\xfd\xc7\x93\xbf\xdc\x6f\xa8\x31\x1d\x34\x03\x36\xb2\xbe\xc6\x4d\x43\x3f\x96\xc4\x5b\x05\x59\xfd\xe8\x57\x74\x50\x63\x40\xc9\x29\x44\x5e\xe5\x10\xda\xa2\xfb\x59\x2f\x91\x98\xed\x0c\x5d\x1c\x33\x69\xf7\x2c\x1d\xa2\x37\x9d\x4a\xb6\x93\x68\xbb\x21\x95\x4c\x67\x4a\xbc\x26\x3f\x43\xbb\x4f\xab\x46\xc1\x95\x24\xe3\xf6\x73\xe4\xd5\xef\x9f\x94\xc4\xdb\x05\x79\xe0\xe6\xe1\xf9\x35\xac\xdd\x7a\x29\x6f\xb3\x1a\xf1\xee\x5b\xc2\xe1\x95\x37\xfb\xc3\xc3\xc9\x74\xb4\x6d\x79\xc7\x40\x53\x7b\x8d\xfd\xf9\x87\x64\xe1\x76\x51\xea\xba\x7c\x5e\x8f\xc4\xd9\x2d\x2b\x0d\x56\x51\x20\xee\x4c\xdf\x05\xcd\x9b\x6f\xb0\x37\x87\x07\xdb\x3b\x52\x9d\x23\x99\x05\x61\x2f\x6c\xfe\xc4\x2f\xbc\x5f\xd4\x5a\xe3\x8b\xc6\xd6\xb6\x84\x87\x73\x3a\x6e\x37\x61\x6c\xc6\x5b\xbd\x86\x75\x2b\x7c\xf1\x86\x26\xb7\xd3\x26\x85\x6a\x5b\x9b\xba\xba\x97\x36\x1d\x79\xc5\xff\xcf\x82\x2c\x89\x4f\x73\x0d\xc1\x66\x1b\x27\x39\xee\xb3\x02\x31\x11\x29\x54\xe7\x5e\x37\xdf\xdb\x1a\xad\x0d\xc9\x92\xc3\xdd\x11\xe9\x9b\xbb\xbe\xd0\x67\xb7\xb0\x0a\xea\x2b\xd2\xe0\x22\xf0\xae\x82\xa7\xe0\x28\x8a\x96\x94\x87\x33\x25\x02\x26\x52\xa4\xc3\x8b\xa6\xe0\x2d\xe0\x72\x27\xe2\x2e\x72\x8b\x24\x3e\xee\x7e\xed\xf3\x8f\x41\xa3\x68\x32\x38\xbf\x6b\x33\xaa\x2f\xe7\x8c\xb2\xb0\xeb\xd0\xc3\x2e\x75\x2d\xe5\xa9\x3d\xd4\xf5\x6f\xf7\x6a\x45\x23\xf4\xfb\xfb\x5d\x87\xfd\x49\x51\x62\x9a\x77\x88\xd2\x3d\xff\xec\x78\x46\x7d\xd0\x26\x49\x16\xb8\xfa\x87\x46\xe1\xa0\x20\xaf\x5b\x25\x89\x3b\x44\x69\xb7\x2c\x7c\x54\x4b\xbb\x43\x94\x7a\x57\x4b\x14\xd4\x10\x91\x29\x56\xd1\xa8\xf5\x60\xa8\x00\xe4\x5f\x80\x29\x29\x0d\x37\x9d\xe4\x88\xbb\x65\x97\xbb\x0f\x32\x32\x0d\xbb\x78\x48\x14\x87\x99\xb3\x3c\xe0\x1c\x1c\xde\xf0\x05\x41\x56\xa9\x8d\x22\x04\xf4\xf3\xbf\xab\xdf\x36\x18\x4c\xd2\x77\x64\xd3\x8f\xe5\xb0\xa9\x89\xff\xb6\xc1\xf9\x6d\xbb\xc9\x68\x50\xbf\xff\x63\x3a\xe6\x7e\x09\x0d\xfa\x59\x96\x44\x58\x2a\x89\x97\x0a\xf2\x5a\x49\xdc\x29\xc8\x78\xc0\x66\xb3\x49\xea\x05\x91\x0b\x3c\xeb\xed\xf0\xa8\x6c\x13\xed\xf9\xe7\x64\x61\xa7\x28\xad\x95\x85\x4b\x45\x49\xfd\xaa\x20\x17\xfc\xde\xeb\xfb\x8e\x4e\xba\x57\xd7\x06\x7e\x1c\xd9\xa6\x95\xac\x34\x18\xcb\x9f\x4e\x29\xa4\xcf\x6a\x8c\x7c\xcb\xa8\x9a\x83\xec\x28\x5c\x9d\xff\x81\xfa\x05\x78\x9f\x32\x2c\x79\x59\x78\xac\x28\xa2\x2e\xca\xad\x71\xed\x0f\xc8\xa5\x3f\xd8\xa7\x66\xe1\x61\xf5\xc0\x7f\x5f\x5f\xad\xc8\x76\xbd\x24\xde\x2f\xc8\x78\x8f\x28\x55\xf8\x1f\x32\x20\x0b\xb2\xa1\x1a\x54\x87\xae\x42\x08\xe4\x90\xec\x72\xb8\x93\x69\x39\x13\x74\x07\x13\xd1\x90\x16\xe1\x70\x15\x22\xf4\x3d\x22\xa1\x23\x86\x84\x88\xee\x49\x9a\x94\x4a\x5b\x9e\x0f\x49\xb1\x5f\x82\xf2\xb4\xb3\x8b\x27\x25\x86\x03\x9f\x88\xbb\x30\x5e\x79\x72\x10\x00\xae\x0b\xa9\x6f\x04\xe0\xe1\xa3\xa1\x85\x70\x72\xf9\x23\x2b\x01\xe0\xea\xa0\xfa\x63\x8a\xdf\xfd\xfa\xa3\xbc\xe7\xa4\x87\xff\xdc\xe9\xc7\x78\xcf\x49\xb3\x1d\x8f\xbd\xa2\xd5\xe7\x8b\xc1\xbb\xb4\xd3\x95\x17\xb2\x26\x93\xed\xb0\x97\xbd\x08\x2e\xbd\x84\xf7\x1c\xf0\xf0\x5b\xe0\xca\x8b\x59\xef\x61\x9b\xc9\xc4\x6e\xb8\x5a\x4b\x72\x6f\xc3\x97\x45\x09\xd6\x42\x8b\xfa\x1a\x30\x00\x2c\x7c\x41\x51\x94\xfc\x6b\xd0\xaa\xbe\x0e\x2c\x00\x03\x4f\x29\x4a\x20\x2b\x4a\xf9\x13\x1e\x0f\xde\x99\x3f\xe1\x11\x4d\x78\x27\xa5\xb5\x75\xce\x32\xac\xb7\x0a\x16\x8f\x7a\x02\x76\x7a\xf4\xa3\x45\xb0\xaa\x8f\x17\x12\x68\xfb\xdb\xce\x29\xc4\xbc\xc5\x2a\x28\x81\x16\x53\xcc\x21\x17\xef\x07\x5e\x64\x78\x67\x28\xd5\x10\x75\x86\xec\x0d\x91\x16\xc8\x24\xe2\x19\x7b\x22\x12\xb2\x47\x5a\x20\xe5\x8e\x67\x52\x09\x67\x3a\x91\x4a\x38\xfd\x84\x24\xdb\x99\x06\x0a\x42\x1a\xef\xe3\xb4\x0b\x11\xb4\x8b\x3e\x8e\xb9\x5b\xba\x7f\xcf\x75\x02\x9f\x58\x7e\xdd\xc1\x55\x0f\x0e\x37\x3f\x28\x2d\x96\x7f\x50\x7f\x75\xdc\x60\xe3\x4c\xc2\xd0\xd5\xaf\x65\x83\x0f\xae\x8a\x3d\xb8\xe2\xa6\x9d\xbd\xa7\xfd\xad\x8b\x7a\xd6\xc7\x57\x18\x0c\x73\x22\xf3\x67\xcf\x6d\x9f\xed\x97\x17\xd5\x34\xf6\xc4\x97\xb4\xcc\xe5\xd9\xee\x86\x81\xd6\xee\x48\xa3\x44\x94\xaf\x0e\xf9\x8e\x1f\x5d\x74\xc5\xc2\x0e\x17\x33\x35\x01\x93\x68\x0a\xbe\x96\x80\xfb\x00\xea\xe7\x3f\x0a\x30\xf9\x37\xfc\xde\x24\x5f\xdf\x7d\x49\xfe\xa1\xc6\xce\xc6\x1a\x0b\x87\xd5\x7f\x02\xc2\x5a\x6c\xde\x86\x76\xf8\x7b\x30\x11\x74\x9b\x38\x00\xf5\x25\x00\x62\x10\xdd\xf5\xed\x3a\x2e\x06\xc5\x96\x28\xd8\x4b\xba\xdc\xe0\x72\xb3\xba\xcd\x60\xc5\x92\xcc\x20\x97\x08\x27\x44\x31\xff\x78\x67\x0c\x07\x4a\x10\x11\x01\x06\xc1\x4f\x44\x51\xdd\x29\xba\x02\xb1\xce\x89\xf1\x22\xe2\x83\xee\xcf\xa3\xf4\xdc\x18\xea\x44\x8b\xb5\x36\x75\x07\xed\x2e\x37\x99\xfe\x68\xbb\xc3\x25\x9f\x07\xa6\xbb\xfa\x9a\x3d\x25\x8a\x6a\xcc\x25\xce\xaf\x2c\x4a\xe7\x0f\x66\x82\xa2\xa8\x0e\x33\x8d\xa2\x4b\x2b\x72\xfe\xf9\x72\x69\xf3\xe3\xb1\xce\x7c\xa0\xb4\x37\x03\x71\xa6\xa0\x46\x7f\x36\x4c\x21\x6e\x3f\x87\x90\x09\x35\xa2\x01\xb4\x0a\x21\x48\x74\x40\x24\x15\xe2\x1d\x1c\x0f\x3a\x0e\x53\x71\xfb\xa4\x2f\x3a\x74\x57\xc5\x3a\x83\x29\x48\xf7\x43\xaa\x81\x0b\x71\x2d\x40\xbd\x18\x00\x67\x05\xa7\x96\x30\x25\x3b\x83\xa9\x44\x34\xc4\x27\xb4\xb3\x9c\x90\x99\xc7\xbe\xb4\xd8\x82\x19\xc2\x33\xf9\x77\x4d\xea\xbf\x98\x04\x8b\x59\xcd\x59\x0d\x06\x57\x8e\xea\xb2\xe4\x44\x89\xcc\xcf\x7f\x1d\x76\x5b\x8c\x66\x6c\x24\x16\xe9\xad\x1b\x70\x46\xbd\x9b\xb3\x9a\x45\xa3\xf3\xef\xaf\xaa\xe3\x83\x1d\x7f\xe9\x18\x54\xdf\x5c\xf8\xdb\xff\x8f\xb6\xff\x80\x8f\xa3\x38\xff\xc7\xf1\x79\x66\xdb\xd5\xbd\xdb\xdb\xbd\xdd\xd3\xdd\xe9\xfa\xed\xaa\x9e\xa4\x6b\xab\xde\x5d\x24\xcb\xb6\x2c\xdc\x8b\xac\x50\x5c\x01\x37\xc0\x15\x73\xb6\x21\x01\x12\x0c\x98\xde\x05\x18\x08\xc5\x09\xa1\x3b\x94\x28\x10\x08\xe1\x13\x4a\x42\x08\x21\x81\xe0\x24\x86\x04\x42\x4f\x01\x6c\xdd\xfa\xff\xda\xbd\x93\x2d\x17\x4a\x5e\xdf\xff\x0f\xac\xdd\x99\x6d\x37\xcf\xec\xec\xcc\xf3\xcc\x3c\xcf\xfb\x7d\xdb\xbb\xe4\xb2\x3f\xd6\x38\x49\x01\x22\xb6\x83\x81\x31\x10\x28\x27\x2f\x50\x06\xf4\xc6\x81\x61\xd7\x05\xef\xcd\xc7\x9c\xcb\x6c\x26\x80\x58\xf7\xce\xbc\xfc\x47\x26\x97\x15\x63\xbc\x9e\xd8\xb6\x62\xc5\x65\x97\xad\x58\x81\xaf\xce\xaf\x28\xac\xfd\x8c\x97\x3b\xad\xcb\x1d\x3f\x22\x37\xf5\x95\x72\xc3\x31\x92\x11\x5f\x5b\x0f\xdf\x42\xee\x9b\x8e\x92\x8e\xff\xca\x5a\x38\x2c\xf6\x5f\x4f\x24\xb5\x36\x7a\x44\x3c\xf2\xbc\xe3\xaa\xc0\x42\x10\xb0\x1e\x51\xba\xcc\xc6\xfc\xac\x6e\x97\x35\xa0\x1e\x34\x0f\xa1\xf8\xd7\xbc\xe2\xa3\x67\x0c\x8e\x75\x84\xf8\xa6\x3c\xde\x77\x62\x91\xc9\xd0\xf8\x99\x05\xdd\xd4\xcf\x19\x0d\x39\x67\x64\xb4\x02\xd1\xc2\x88\x91\x39\x84\x8c\x0c\x62\x5d\x43\x27\x92\x7a\x1c\xf4\xfb\x67\xdf\x90\x2c\x0c\x77\x63\xf2\x3b\x8e\xc8\x7f\xac\x94\x5f\x5d\x1f\xc7\xcd\xa0\x7c\x43\x9e\x3c\x4a\x00\x2d\x74\xe2\xda\xc0\xc3\xc7\xc8\x7c\x54\x6d\x1c\xa9\xa7\xd0\x61\x51\xd6\x9e\xa8\x2a\x60\xed\x37\x57\x80\xd1\xe6\xa9\x97\x8a\x6d\xbe\x0b\xcd\x46\x28\x6e\x2c\xf2\x1b\x2b\xf7\x5f\xdd\xe6\xe3\x02\x4b\x18\x6c\x0f\x6a\x41\x0f\x55\xa3\x2c\x1c\x8e\x7a\xd2\x3f\x80\x14\x67\xb0\x91\x30\xb4\x41\x1a\xc1\x51\x9d\x73\x9b\xd2\xad\x3d\xdd\xc9\x89\xf9\x9b\xbf\x42\xe8\x8f\xbc\xf5\xfd\x67\x4f\x68\x4d\x78\x5c\x8a\xc3\x19\x97\x67\x9e\xe6\xc4\xee\x19\x55\x2b\xbe\x7b\xd9\x19\x9b\x77\x07\xb4\xca\xbb\x00\x33\x26\x57\xeb\xc0\xc8\xe6\xb7\xdb\x56\xf4\xae\xed\xcb\xce\x3e\x91\xcc\x6a\xeb\xfa\x33\x06\xea\x9c\x26\x66\x0d\x43\xda\xcf\x9e\x23\xf9\x2f\x3d\x6d\xf9\xae\x27\x71\xcd\xda\xb5\x70\x3f\xe3\xa1\x9c\x36\xbb\xab\x71\xf6\xde\xfc\x5a\x74\x9c\xec\xaa\xe1\x0d\x7d\x44\xf6\xaf\xef\xe7\x8e\x11\x8f\xff\xba\xea\xf8\x16\xb2\xbf\x32\x5e\xbe\x67\xbe\xa6\x22\xc8\xa2\xf0\x07\xef\x39\x91\xf4\xa3\xc7\x8a\x49\xa5\x4e\x58\x1f\x63\xb8\x91\xed\xc5\x79\xd8\x85\x63\x6f\xbd\xe0\xb0\x71\xec\xbc\x1f\x25\x30\xa2\x5b\x64\x44\x83\x4b\x8c\x66\x2a\x71\xc4\x60\xbd\x2d\xc0\x49\x15\x20\x09\x5b\xb1\x41\x9d\x9b\x4a\x06\x28\xb7\xc0\x02\xc3\xe2\x22\x2f\xbf\xd7\x17\x8f\xfb\xbc\xf2\xb0\xec\xd5\x8c\x35\x5e\x08\x79\x65\x72\x58\x75\x10\x09\x8e\x73\x28\xe6\xc6\xf6\x0b\x62\x7d\x5c\xe7\x8d\x73\xa6\x6e\x8e\x7a\xe5\x58\x89\x67\x59\x5d\x77\xd8\xe5\x35\x9b\x19\xab\x5f\xe0\xbd\x89\x9e\x9a\xb0\xc3\x0c\x3c\xef\x22\x58\x13\x09\xee\x69\x6b\x8d\x55\x1b\x5f\x3c\x8e\x7d\x87\x03\x38\x64\xd9\x3b\xbb\xad\x2a\xd4\xd7\x52\xdf\xd2\x10\x5f\x3d\xa1\x0f\x07\x7d\xde\x4a\x80\xb8\x17\x6f\x2b\x89\x63\xbc\xb6\x7d\x4e\xd8\xd5\x1c\xaf\x50\xaa\x9a\x05\xde\x1d\x4c\x96\x35\x07\x3c\x72\x5f\x55\x84\xf6\x08\xec\x5a\x74\x98\x37\xbd\xdd\x88\x31\xf3\x15\x71\x18\x0f\xbf\xbc\x63\x2d\xf8\xb8\xe8\x36\xac\x61\x2c\x05\xb0\x5b\x30\xe0\x8c\x13\x58\x31\xc8\xfb\x0d\x10\x4d\xa3\x4a\xf4\xfa\x68\x22\x44\x49\x64\x8c\x3f\x46\xf8\xaa\x8a\x58\xae\xc2\x9a\x69\xda\x3f\x49\x13\x4b\xb8\x5c\x02\x98\x1d\xe1\x9a\x9e\x84\x97\x17\xfc\x56\xc6\x6c\xf6\xba\xc2\xdd\x75\xcb\x3c\x25\x31\xd9\x1b\xdd\x3c\x75\xce\x8d\x9d\x5c\x5f\xec\x82\xf6\x46\xb3\xe2\xe0\xb8\x04\x41\x8c\xd5\x44\xfe\x9d\x42\x1d\x18\xf5\xf1\xe3\x96\xb9\xd3\xd6\xb2\x82\x87\x8e\x97\x4d\x95\x3d\x81\xe6\xb2\x64\xd0\xcd\x0b\xcd\x55\x4a\x45\xbc\xd9\x15\x9e\xd3\xbe\x16\xe3\x78\x09\xde\xe6\x8d\x03\x54\x7a\x7d\x41\xdc\x37\x61\x75\xbc\xa1\xa5\xbe\xa5\x2f\x84\x90\xed\xf0\x5c\x86\xd9\x58\x47\xaa\x44\x2d\x68\x21\x3a\x15\x9d\x87\x7e\x80\x6e\x46\x0f\xa0\xa7\x0d\x5e\x93\x68\x84\x71\x8b\xa9\xa4\x9a\xca\xa4\x23\xee\xb8\x3b\xca\x45\xb9\x68\x86\xe2\xa2\x99\xe2\x22\x5e\xaa\x38\x7d\xcf\x51\x45\x1f\x21\x77\x94\xd3\xd5\xc7\xa4\x24\x4a\x6e\x61\x8c\x25\xa6\x05\xd2\x86\x13\x6c\x29\x44\xdd\x42\x2a\xa9\xa6\xb3\xe9\x0c\xb8\x85\x48\x0b\xa4\x93\x90\x36\x68\xe9\xc2\x21\x03\x9d\xb4\x08\x7e\x19\x32\xda\x19\xf0\x51\x46\x89\x1a\x60\x98\xee\x54\x3c\x93\x2e\xd0\xf8\x94\x42\x71\xe2\x4e\x4a\x71\x51\xae\x58\x8e\x68\xb1\x1c\xc7\x4d\xe0\x5d\x53\xca\x39\x9d\x5c\xe9\x63\x9d\x9d\xf9\x67\xfb\x7b\xa7\xc1\x4f\xba\x94\x78\xd8\x4c\x77\x02\xb0\x82\x08\x6d\x8c\xad\x3c\x1a\xee\xea\x0a\xc5\xca\x6d\xcc\x41\x4c\xd8\x7c\x99\x74\xa9\x5b\x28\x5d\xe2\x73\x5f\x10\xf1\xd0\xa0\x6d\x6b\x6f\xc7\x6e\xde\xd2\x59\x79\xa1\xf6\x81\xf6\xe1\x85\x55\x1d\x16\x41\xb0\x74\x54\x5e\x84\xe5\x8b\x2a\x3b\x2c\x42\xde\x3e\x7f\x4a\x2a\x33\x8d\x09\x99\xa2\xd6\x5e\x08\xbb\x4b\xeb\x52\x3e\xb7\xdb\x97\xaa\x2b\x75\x3f\xdc\xd5\x65\xc0\x59\x77\xd1\xd6\x50\xac\x1c\x3e\x1f\x3f\xc1\xf3\xde\x4d\x49\xe7\x3e\xe7\xbd\x91\x54\xea\x1f\x13\xb5\x79\x70\xd7\xc4\xad\xda\xe5\x65\xd5\x7e\x2e\x0e\x11\xed\x33\x0f\x76\x04\xc1\xb3\x6a\x57\xda\x5d\x51\x1e\x83\x0f\x6f\x2d\xab\x70\x3f\x62\x2e\x65\x45\x57\x99\xec\x6b\xda\xd6\xe4\x93\xe5\xd2\x86\xbe\x8e\x94\x17\x6c\x6e\x2b\x51\x7f\x63\x2a\x75\x63\x3a\x4f\xfc\xe4\xa4\xaa\x26\xca\xe1\xa0\x9a\xaa\xe6\xec\xb9\x7f\x66\x65\xb3\x9e\x6e\xae\x9c\x49\x34\x41\xd9\x33\xcf\x48\x0b\xa5\xa5\xea\xaf\x36\x6c\x6f\x2c\x95\xe5\xd2\x46\x63\xe7\x6b\x86\xb5\xda\x3b\x41\x27\xf6\x80\x53\xfb\x53\xdc\xe5\xab\x06\xd3\xd1\x73\xb8\x56\xe4\x3b\x84\xa8\x77\x8c\x78\xd9\xb1\xf6\xb1\x00\x9d\x82\xce\x45\x17\xa1\x1b\xd0\x8f\x0d\x3b\x3d\x1a\x51\xb8\x6c\x2a\x49\xb9\xa3\x99\x74\x32\x9e\xca\x84\xdd\x29\x2e\x15\x3e\xc1\x6b\x19\x7b\x79\x99\x28\x97\xca\x18\x2f\x2f\x9e\x89\x1a\x0d\xa6\x05\x52\xc7\xbd\x58\x35\x0b\x99\x74\xa4\x14\x84\xa4\xc1\x80\xcb\xd0\x21\xa3\x89\x64\xd2\x46\xab\x08\x19\x2d\x04\x52\x04\x17\xe5\x64\x45\x56\x52\xfc\x58\xdb\x2b\xb4\x33\xbd\xed\xc5\x4f\xd0\x42\x89\xff\x53\x24\x51\x94\x14\x18\x98\x3f\x7f\xb4\x71\xa5\xf6\xfc\xf2\x53\x21\x34\x6f\x5e\xc0\xe7\x22\x60\x9e\xc9\x96\xa8\xcd\xc2\x1e\x33\x97\x4d\x56\xce\x9b\x57\x5d\x9b\xe5\xcc\x30\xb0\x00\x33\xe1\xc4\x83\x3e\xa5\xab\x5b\xf1\x97\x2a\x13\x26\xc7\x5c\x04\xce\x0f\xcf\x9e\x8d\x5f\xf6\xb2\x73\x1b\x1f\xcb\x7b\x1f\x6b\x9c\x67\xf7\x7a\xd9\xb9\x4d\x8f\xe2\x77\x8d\xf4\xa8\x77\xc9\xc6\x53\xd9\x9a\xb8\x7f\xc5\x24\x78\xc4\x2f\x77\x77\xc9\x7e\xbf\xdc\xd5\x2d\xfb\x61\xfa\x82\x4c\x32\x61\x37\x2d\x00\xc2\xe5\x0b\x40\xec\xd5\x2e\x11\xaa\xc5\xee\x44\xa2\xfb\xea\xc1\xc1\xfc\x2f\xe1\x23\xed\xbb\x15\x6e\x22\x04\xa7\x6b\x1b\xeb\x3c\xf1\x96\xc1\x67\x7b\xbc\xf5\xd9\x37\xf2\xcb\x6b\x55\xd5\x77\x92\x3d\x65\x89\x4d\x98\xb3\x74\x7a\x3c\x95\x8a\x4f\xdf\x33\x3d\x9e\xca\xf8\x7c\x66\xe2\xe9\xdf\x4e\x98\xf0\xdb\x89\xf9\x39\xef\x9f\xd5\xd4\x4f\xbb\xdd\x74\x7f\xd3\xea\x8f\xf4\x34\x23\x08\x4c\x7f\xd3\x6a\x92\xd5\xd6\x68\x9f\x82\xa3\xf7\xe2\xa5\x33\xb5\x2f\x27\xfe\x78\x46\x3c\x95\x92\xfb\x7f\xdc\xaf\x3f\x64\x40\xb3\xab\xad\x71\x4f\x0a\x2e\xd6\x2e\x0f\x63\xb1\x12\xce\x2d\xf8\x52\xe6\xa8\xcd\xd4\x7f\x11\x8f\x14\x84\x80\x2e\x58\xd0\x2a\x9f\x54\xc6\x0c\x66\x10\x19\x70\x8f\x4d\xca\x40\x16\xf4\x83\x78\x96\xe5\x73\x9f\xfc\xb1\x5b\xb0\xe4\x01\x6e\xb5\x59\xcd\xd2\xc7\x65\x5e\xe2\x05\xab\x35\xff\x09\xf4\x5b\x2d\x16\xf1\xe3\x0a\x8f\xb6\xc7\x85\xa1\x44\xf9\x54\x24\x4e\x73\x69\xbd\x89\x08\x0f\x23\x00\x92\xe8\x70\x54\xc3\xa9\x4e\xf7\xe8\x7c\xc8\x5f\x27\x70\x8e\x6a\x7c\x66\x88\xd8\x59\x7d\x34\x77\x3e\x7f\x98\x5f\x44\xae\x04\x63\x05\xc1\x4d\xd0\x92\xd8\x04\x49\x15\x8c\x23\x20\x82\x91\xcb\x2a\x90\x81\xac\x74\xdc\xe2\xcb\x56\x77\xf0\x31\x97\x89\x31\x9d\xfb\x0b\xb3\xd9\xe4\xdc\x1b\xe4\x09\x95\xe1\x1e\x0f\xf0\xda\x69\x00\x94\x10\x7a\xcc\xc5\x98\xcc\xda\x28\x5c\x67\xfa\xd3\x51\x93\xd4\x04\xbc\x15\xb1\xda\xb8\x3f\x80\x76\x27\xcb\xda\x63\xc4\x0c\x5b\x34\xaf\x60\x2d\x1c\xb5\xd9\x1d\xf0\x26\xe0\x57\x9d\x17\x1e\x8f\x59\x83\x2c\x0c\x22\xff\x8b\xb0\x81\x88\x54\x0d\x7c\x92\x0c\x42\x32\x40\x15\x79\xf0\x4b\x41\x64\x58\x70\x00\x4b\x47\xe9\xb0\x1c\xab\xc1\x85\x91\x24\x01\x4a\x0b\xc8\x06\xdf\x7c\x2b\x9d\xca\xe2\x5f\xc2\x7e\xcd\xbf\xf7\x87\xd0\xd0\xd3\x03\x21\x36\xec\x09\x05\x58\x9a\x57\x18\x93\x19\x80\x67\x62\x2c\xcb\x06\x42\x9e\xb0\x23\x08\x07\xb5\x0b\x5f\xd6\x5e\xae\xad\x8b\xc5\xe2\x1d\x9e\xe3\xaf\x60\x43\x70\x10\xae\x3d\x90\x87\xa5\x66\x8a\x24\x08\xda\xe2\x94\x1c\x74\xc9\x42\xb5\xfd\xf2\xf2\xb2\x0b\x2f\xbf\x5c\x9d\xc7\x71\x0e\xc9\x61\xa1\x09\x82\xc7\x66\x82\x24\x29\x4b\xa8\xe4\xb8\xf3\x4e\xfd\xbc\x0b\x15\x70\xb0\xe8\x11\xea\x62\x63\x6d\x55\x42\x3e\x14\x44\xc8\x4c\xba\xc1\xad\x30\x19\xc8\x48\x90\x91\x54\xb7\xd9\x06\xbb\xe0\x23\xed\x1e\x4d\xa4\xaa\x34\x11\x40\x93\xae\x80\xd9\x00\x30\x27\x3f\x03\x66\x6b\x2e\xed\x47\x54\x02\x06\x34\x49\xbb\x1b\xe6\xc0\x7b\xda\x8f\x34\x17\xd1\xa2\xbd\xac\xfd\x0d\xda\xb4\xfd\xa7\x6b\x7f\x32\xf8\xd8\xe3\xa7\x0f\x81\x1f\x03\x60\x6d\x3f\xf9\x07\xed\x6f\xda\x2b\xc0\x6a\x9f\x69\x9f\x6a\x3f\x87\x52\x62\xab\xf6\x73\xed\x33\xa8\x45\x34\xb2\x1e\x42\xd4\x7f\x0c\x1f\x13\x2b\x72\x14\xcb\x83\xa8\x30\x17\xe5\xc2\x5c\x34\xae\x52\x0c\xa8\x60\xfc\x11\xc0\x98\x21\x13\x76\x53\xe6\x83\xb7\x0d\x53\x37\x0f\x8f\x0e\x84\x09\x47\x38\x3f\xb7\x0b\xbf\xd6\x95\xff\xf7\x12\xbc\x64\xc9\x1b\xf0\x56\x4e\x8b\xe6\x1f\x20\x42\x43\xb0\x2f\x9f\xc3\xb9\xaa\x9b\xee\xb8\x11\x7b\x77\x69\x7b\x2e\xc7\x8f\x6c\xce\x1f\xda\x4c\x6c\xce\x9f\x37\x84\xb7\x1d\xb8\xf5\x96\x5b\x4e\xe0\x7b\x31\x1d\x2d\x1d\x87\xdb\x5f\x04\xa3\x1d\xc3\xb9\x8d\x45\x64\x16\x1b\x94\xa9\x84\x28\xd0\x85\x36\x10\x20\xb2\x49\x51\xd7\x9e\x40\x6d\x25\x64\x03\xc5\x56\xd7\x23\x08\xe4\x1c\xd7\xcf\x39\x8f\x74\x73\x63\x6e\x1a\xa1\x77\xb5\xc7\xde\x7d\x17\x26\xc3\x40\xb6\x2f\x9b\xed\xd3\x26\xb1\xdf\x9f\xbc\x71\x56\x69\xb2\x4f\xb0\x3a\x28\xbd\xe6\x28\x87\x55\xe8\x4b\x96\xce\xda\x38\xf9\xfb\x5f\x7d\x0a\x9f\x49\x59\xf6\xbf\x32\x57\xcb\xce\x7d\x65\xbf\x85\x32\xd2\xf0\x82\x9e\xc6\xa2\xe1\xd0\x01\xbb\x0b\xbf\xf2\xae\xf1\x23\xd9\xdc\xb7\x7c\xec\xd1\xa7\xb4\x33\x8f\x7f\xbe\x91\x3e\xea\xbb\x76\x18\x38\x1f\xc7\xfa\xcb\xa4\x0e\x47\xbe\x8e\x45\xab\x18\x54\x47\x85\x2f\x0d\xae\xdf\x72\xff\x96\x2d\xf7\xe3\xfb\x8d\xdd\x18\x8f\x51\xe1\x0b\x1c\xfd\xa1\x7e\xac\xf8\x6f\xfc\xef\x60\x64\x36\x78\xc0\xf9\x30\x95\x32\x43\x4a\x0d\x1f\xe5\xaa\x85\x7e\xa5\x9d\x89\xb3\x83\x5a\x46\xcb\x0c\x2e\xc3\x16\x38\x78\x2c\x52\xc2\x2e\xed\xa5\x7d\xf8\xc1\xfc\xd4\x61\xa8\x3b\x51\x7c\x72\x3f\xb5\x8d\xba\x1d\x59\x8c\xe8\xca\x2e\xbd\x2d\x80\x48\x2b\x09\xc8\xaa\xd9\x00\x48\x09\x60\x58\x90\x02\xa0\xb6\x02\x9f\xc0\x4a\x8c\x62\x31\x13\xc0\x92\xa8\xb6\x62\xde\x88\x87\x90\x95\x04\xa1\xc8\x4a\x1b\x88\x21\x35\x00\x34\x4f\x1b\xb8\x0b\x71\x59\x49\x90\xfa\x99\x56\x52\xcd\xaa\x31\x4a\x94\x02\x40\xd4\x98\xce\xce\x28\xa5\x7e\x39\xd6\xa3\xae\x62\x9f\x3b\xb9\x6d\x0a\x41\x5e\xb1\x70\xc1\xa6\xfd\xc2\xe4\xaa\x3a\xed\x2d\xed\xc3\xca\x44\xbb\x2b\xb0\x50\x6d\xde\xff\x66\x5b\x66\xe1\x6c\x93\xc3\x5e\x15\x9b\xfd\xf2\xb3\x4b\x13\x93\x06\xda\x85\x92\x10\xed\x7a\x1b\xab\xfb\xdc\xb4\xf3\x61\xef\x2c\xaa\xaa\x32\x3c\xaa\x5d\xff\xc5\x2e\x87\xdb\x4e\x31\xd8\x1c\x75\x7b\xcd\x44\x69\xa4\x3e\x16\x38\xf7\x09\xd8\x0c\xe5\x37\x34\x3b\x01\xdf\xd1\xd6\x17\xe2\x06\x06\x38\x97\xad\x89\x5b\xb9\xb6\xca\xbf\x71\xc2\x82\x9c\xc9\x74\x2d\xde\xe4\x8b\x9a\x4d\x35\x75\x8c\x25\xe2\xf5\x47\xcd\x4c\xa9\xdf\x64\x8a\x8e\xba\xbc\xa7\x75\xf5\x08\xb5\x35\x04\x67\x12\x22\x99\xe8\xd0\x2f\x9c\xe6\x2b\xaf\xa4\x23\xf5\xc4\x63\x77\x69\x9e\x40\xda\xcf\x6d\x95\x7d\xab\x6d\xa5\xe5\xbe\xb4\x39\xf9\xfc\xe6\xfb\x26\x7b\xab\x03\x01\x87\x35\xe1\x8a\xcf\x49\xf4\x09\xad\x06\x0e\x6c\xe1\x5d\x99\x8c\xde\xbe\x11\xcd\x2b\xb0\x5b\xcb\x06\x15\x71\x56\x35\xc2\xd9\x8d\x50\x7d\x5e\xaf\x1f\xbd\xcf\xd4\x8d\x0f\x29\x80\xf9\x74\x56\x56\xe8\x90\xe2\x00\x83\xc3\x50\xaf\xd8\xac\x22\x2b\x32\x45\x33\x85\xba\x0e\x10\x92\x28\x91\xba\xad\xe2\x3a\x4e\x31\xec\x1f\x88\x55\x42\xa5\x32\xb3\xd7\x34\xf7\xfc\x15\x04\x56\xab\x27\x5e\xfa\x88\xd0\xa5\x54\xdd\x70\x77\x95\xdc\xe5\xb6\x27\x22\x81\xe7\x7e\x1b\x8e\x25\xeb\xad\x94\xe3\x56\x6d\xd9\x6d\x36\xca\xeb\xa8\xb9\xe9\xcb\x07\x23\x01\xc7\xf7\xcc\x5c\xe5\xea\x3f\x68\x9f\x9e\x3f\x28\x57\xa6\x48\x93\x18\xa3\xc1\x44\xbb\xec\xcb\x1f\x04\xe2\x61\x4f\x30\x48\xd6\x42\xd9\x51\xab\x79\xd7\x57\x26\x44\x61\xb9\x4b\xca\xb6\x74\x9e\x69\x5b\xd8\x55\x37\x57\x08\x0e\x40\xa3\xdb\x4b\x53\x82\x40\x33\x25\x02\xef\x61\xa8\x68\x84\x62\x4a\xf2\x04\xa3\x94\x90\x2b\x56\xd0\xb6\xeb\xeb\x67\xf8\x12\xa7\xf0\x1d\x2b\xf0\x2f\x33\xa2\x1a\x6e\xf3\xd9\x22\x0e\xa1\x36\xd0\xfd\x83\x17\x62\x54\x5a\x88\x58\xfb\x05\xff\x02\xbb\x20\xbb\xc1\x0a\xc9\x63\xc6\x21\x40\xdd\x87\x72\xa4\x5e\xad\x11\x84\xe2\x92\xde\xad\x24\x88\x0c\x17\xcd\xb4\x92\xaa\x81\x30\x18\x76\x87\x39\x21\x80\xd5\x2c\x71\x7f\xbf\x74\xff\xbc\x65\x7b\x56\x4f\x0b\xff\x70\xf2\xda\xee\x5a\x81\x02\x86\xfc\x37\x4c\xd5\x1e\xb0\x87\xba\x6a\xa7\xbd\xfc\x61\xb4\x15\x70\xfd\xc2\x0d\x1b\x1a\x71\xe8\x75\xef\x9c\x45\xab\xe6\x54\x53\x8c\x36\x77\x34\x7f\x20\x90\xce\x04\x00\x8f\x5f\xe7\x2f\x30\xc8\x2a\x74\x94\x4e\xe0\x0c\x17\xce\x84\xb9\x68\x84\x61\x09\xc6\x9d\x32\x7e\xab\x15\x8e\x5b\x0b\x5d\xdd\x5a\xd5\x14\x4b\x97\x58\x00\x0e\xa1\x27\x4c\x40\x95\x64\x4e\xeb\xde\x5e\x39\xe7\x86\x53\x26\x7c\x0f\x6e\x1b\x5f\x7f\x53\x1e\x15\x41\x2a\x2b\x97\x60\xe7\xd3\x30\xd1\x52\x35\x7b\xd9\xec\x92\x3b\xb4\xc1\x86\xb3\x56\x74\x60\xa8\x25\x6b\x8e\x5e\x0b\x25\x0e\xb5\xe3\x3c\x8d\x0c\xd4\x1e\xf1\xc4\x26\x3d\xfe\x8f\xd3\xae\xdd\x66\xb1\xb3\x16\xed\x26\xbb\xc9\x2c\x14\xf1\x02\x01\xc9\x4e\x2d\x67\xb1\x40\xce\xc9\xf3\xa4\xb1\x66\x71\x70\xcc\xa7\x04\xe1\x3c\x35\xa2\x3f\xb3\xe8\xb7\x72\x18\x36\x59\x2d\x06\x89\xe1\xfc\xe1\xe7\xb8\x9d\x76\x18\xd4\x9f\x0e\xa7\xd8\x49\x9e\x3f\x68\x38\x70\x93\xfb\x64\x27\xe4\x2c\x16\x2d\xe7\x2c\x72\x5b\x01\xc1\x20\x22\x6f\x3c\x73\x0c\x05\x7f\x0c\x03\x5f\x2a\x80\x67\x30\x48\x2f\xc1\x31\x85\xc2\xfb\x8e\xfe\x8d\x93\x59\x43\x82\x22\xd7\x16\x41\x8f\x14\x9f\x59\x58\x97\x3e\x1a\x3d\x5f\x02\x91\x1e\xd1\x8b\x70\x4c\xa9\xf0\x0e\xd6\xa2\xdd\xcc\x9a\xc6\x8b\xa0\xdd\x66\x39\xec\x8f\xbf\x86\x46\x48\x36\xa2\x1e\x8b\xe6\x9c\xae\xac\x47\x23\x04\xce\x14\xb5\x6d\x5d\x67\x37\x2c\xbe\x02\x47\x28\x8c\x71\xab\x16\x88\xee\x24\x41\xa4\xd6\x28\x33\xb7\xe5\xea\x16\xcc\xee\x68\x99\x31\x23\x75\xed\x55\x57\xac\x59\x73\xef\xe4\xe5\xcb\x22\xd5\x27\x2f\x99\xb4\x7e\x30\x9d\x9e\x1e\xed\xb8\x58\xfb\x4b\x69\xa0\x2d\x9b\x8d\x77\x11\x53\x7a\xef\x07\x02\x00\x3a\xce\x3d\xf7\x17\xa1\x50\x38\x02\x04\x50\x9f\xed\xdf\x75\x59\x20\x10\x89\x74\xc4\xda\xbb\x52\x83\x6b\xb6\x3c\x47\x6e\x6a\x99\x32\xa5\x2d\xeb\xb2\xd2\x57\x9d\xbe\xb2\x9c\x70\x12\xa4\xed\xb0\x3f\xbf\x81\x45\x5e\xd0\x0e\x10\x70\x71\xce\x60\x73\x2a\xee\xf1\x3d\xf9\xd9\xfa\x1f\x9d\x1b\x3d\x9b\xf8\xfe\xe8\xd9\xd8\x95\x3f\x7b\x10\x57\xe3\xbf\xe7\xcf\xc0\x99\xfc\xfa\xd1\x8f\xce\xc5\x57\x11\x67\x8e\xbe\x8b\x6f\x32\xf8\x23\x0d\xdc\x59\x6a\xab\x31\xde\xfb\x91\x8a\xa6\xa2\x05\x08\xa1\x64\xd6\x18\x9f\xc8\xe2\x9e\x2a\x8c\x62\x85\xc6\x5d\x80\xb2\x34\x02\x2a\x5b\x74\x73\xd7\x98\x5c\x50\x8c\x35\x42\x08\x80\x3b\x9c\xce\x1a\x9e\xac\x41\xc8\x26\x25\x35\x2b\x89\x8c\xf1\x65\x14\x3f\x8c\xa4\x08\x6f\x85\x24\x29\x24\xc2\x13\x21\x51\x0c\x49\xa3\x07\x2b\x9a\x9b\x66\x37\x37\x93\xd3\xdb\xab\xa7\x34\xcf\x6e\xbe\xb8\xb9\xb2\xa2\x19\x7a\x13\xed\xf8\x47\x2b\x73\xa3\xa7\xe4\x4e\x9f\xc4\xd8\xec\xcc\xe4\xc5\xbf\x5b\x3c\x99\xb1\xdb\x18\xb8\x5a\x3f\xdf\x5c\x51\xd9\x4c\x96\x4a\xfa\x73\x0a\xff\x5e\x6e\xae\xd0\x06\x2a\x9b\x9b\x2b\xe1\x47\x15\xcd\x7c\x7e\x49\xa2\xfd\x6f\x7a\xee\x6f\x85\x6d\x7b\x02\x5f\x0f\x57\xa9\xcf\x9e\x7d\xf6\xb3\xea\x0e\x3b\x43\xdb\xce\xaf\xa8\x38\xdf\x46\x33\xf6\xfc\x55\x63\x77\x55\x36\x35\x21\xb3\xa1\x77\x7d\x69\x70\x6e\x38\x50\x04\x4c\xe0\x86\x38\xa4\xa0\x07\x3e\x35\xf0\x54\xa2\x74\x26\xad\x26\x25\x5a\x66\xb2\x92\x08\xb2\xde\xef\x30\xb4\xde\x7f\xb7\x12\xcd\x20\x43\x5a\xd1\x15\x9e\x82\xbe\x23\x4a\x06\x87\xac\xae\xf9\x18\x23\x9d\x9c\x2d\x4e\xa7\xe8\x9d\x3c\x43\x8b\x6a\x36\x9d\x49\x10\x0a\x2d\x09\xd1\x04\xd0\x4a\x56\x56\x64\x9a\xa1\x03\xa0\x5b\x86\x8c\x11\x00\x25\x25\x45\xda\x08\x5e\x35\x86\x58\x42\xef\xfb\x09\x7d\x48\x80\x02\xc7\x09\x43\x2b\x72\x61\x44\xa0\x44\x49\x60\x29\x86\xc5\xfa\xb8\xa0\xb7\x4e\x16\x1b\x5d\xa2\xa8\x5f\xa2\xbf\x07\xa3\x94\x86\x77\xa5\x71\x77\x00\xbb\xb3\x4a\x42\xef\xb0\x24\xb1\x10\xc8\xaf\x5f\x60\x2c\xe0\x66\x0d\xea\xfc\x56\x10\x41\x2f\x90\x5b\x94\x92\x0c\x9d\x4a\x52\xba\x48\x64\x61\xa8\x52\xd2\x09\x60\x22\x7a\x52\x12\xd4\xac\x9a\xd6\x95\xb9\x28\xab\xab\xfd\x58\x12\xf5\x27\x24\xb3\x10\xc0\x7a\x71\xc0\x80\x66\x21\x0c\xf0\x22\x86\x25\x94\x42\x55\xe8\x3f\xa0\x57\x82\xae\x1d\x42\xc6\x28\xa2\x5e\x38\x82\x11\x68\xa9\xe0\x02\x8a\xd5\x56\x6c\xcc\xc6\xc9\xfa\x49\x63\x1e\x8e\x50\xb3\x6a\x61\x7c\x4c\x19\x60\x36\x4c\xf1\x5a\xd1\xd0\x3c\x8d\xc7\xb2\xa0\x8b\x21\x16\x1f\x5c\xac\xe9\x00\x85\xaf\xb1\x9a\x49\x8a\xa7\x16\x92\x0e\x8b\xc7\x44\x68\x37\x90\x24\x45\x10\x8c\xc5\x4c\x72\x24\x60\x0c\x98\x98\xa5\x92\x0c\x41\x60\x06\xcc\x60\xe9\x8d\x7a\xc2\x73\xc2\x56\x25\xe8\x00\xab\xd9\xed\xb2\xdb\x81\x8d\x94\x88\x24\x29\x58\x15\x47\x13\x6d\xa2\xc5\x92\xb8\xdf\x62\x75\xb9\xed\x14\x57\x22\x3a\x57\xba\xc0\x5c\x5e\x42\x40\xc4\xef\x2b\xc5\x60\xe6\x18\x0b\x4d\x5a\x19\x0e\x40\xf0\x70\x02\x80\x68\x36\x29\x60\xa7\x2c\xac\x68\xf1\x89\x35\x2a\xae\xf0\x85\x28\xb3\x95\x22\xcc\x36\xa1\xc7\x5c\xe5\x2d\xc9\x5a\x00\x9c\x25\x15\x9c\x1c\x09\xfb\x44\x3b\xc6\x34\x6d\x65\xec\x84\x7f\x7a\x56\x74\x57\x88\x04\x04\x4a\xed\x2e\x69\xba\x09\x03\x6d\x72\x87\x48\x4c\x93\x14\xc6\xb1\x04\x55\x46\x0a\x3f\x34\x3b\x89\x60\xc0\x54\xc1\x26\x14\xd2\x4e\x03\x21\x58\x12\x1b\x2e\xa8\x92\xac\x36\x0c\xa2\x99\x76\x13\x12\xc6\x1c\x16\x1d\x31\xe8\x9a\x96\xbf\x95\xb0\xd2\x66\x4c\x58\x08\xc2\x4a\xc0\xed\xd8\xcc\xd1\x94\x99\xa2\x31\xc1\x56\xb8\xcc\xd6\x87\x2c\x36\x82\x26\x49\x82\x25\x4d\x38\x4b\xd9\x09\x87\xd9\x4c\x11\x18\x2c\x98\x24\x4d\xac\x09\x9c\x2c\x56\x05\x11\x33\x1e\x29\xee\x95\x4d\xf2\x62\x3f\xb7\x44\x76\x49\x96\x48\xa0\x6a\x36\xdf\x27\x54\x4d\x8a\xa5\xfc\xa5\xbb\xdb\xf9\xf6\x58\xa5\x87\xb2\x44\x00\x2c\x16\xb0\xb0\xb3\xb9\x80\xc7\x9d\x09\xa5\x22\x66\xbb\x0b\xdb\x28\x12\x22\x04\x11\x11\xb6\x45\x3d\xa7\x76\x48\x95\x95\x84\x4b\xb0\x6c\xac\xed\xae\xb6\x92\x04\x80\x2b\xc0\x98\xe2\xa2\x2c\x9c\xc9\xda\x48\x9c\xee\x57\x3a\x32\x2b\x62\x0d\x13\x28\x2a\x1a\x39\x45\x9d\xe7\x30\xd1\x2e\xab\xc5\xe7\xcb\x46\x5c\x3e\x97\x99\xc5\xa2\xec\x72\x0a\xbc\xa5\x7e\x7e\x59\x53\x4b\x4f\xa6\xd6\xaa\x84\xc2\x61\x82\x05\xd6\xe1\x75\xfa\xc8\xd3\x80\x07\xda\x46\xb0\xe0\x20\xac\x76\x5a\x1b\x00\x13\x47\x51\x26\x2b\x80\xd3\x42\x98\xf4\x17\x8e\xb5\xeb\x5d\x1e\x47\x89\xcf\x59\x6a\x89\x30\x95\x54\xed\x99\x82\xd0\x76\xdb\x59\x65\x98\xac\xde\x94\x50\x9a\x83\x2e\x1b\xb4\x0e\x04\x62\xa2\xbb\x23\x62\x22\x02\x00\xc9\x34\x10\x9d\x25\xbc\x83\x21\xdb\xa9\x40\x99\xdb\x4c\x98\xb6\x3a\xcc\x04\xc9\x34\x74\x02\x34\x04\x1d\x55\x41\x4c\x58\xcd\x50\xca\x8b\x01\xa8\x88\x91\x0e\xd6\x26\x01\xeb\xa5\x4c\x92\xc3\x0a\x98\x03\x9b\x99\x33\xb3\x34\x61\xb5\x13\x74\x90\xe4\x49\x8a\xc1\x24\xe9\x90\x00\x6c\x4e\xde\x61\x26\xcd\x98\xa2\x48\x9a\x60\x80\x6d\xf6\xda\xac\xad\x41\x33\xc1\x94\xb4\xd5\x76\x97\xd2\x3f\x6c\x70\x2d\x31\x79\xdc\xc1\x36\xbf\x9f\x07\x20\x3b\x4e\xb3\x85\x48\xe9\x7b\x66\x47\xa2\x8c\x70\x34\xd5\x25\x3c\xdd\x26\xa7\x09\x53\x66\x26\xed\x74\x4c\x96\x4d\x74\xa2\xa4\x4b\x2a\x05\xfe\xac\x90\x7b\xf9\x3c\xaf\x2b\x1e\xb2\x12\x15\x9c\x17\x63\x33\x05\x0e\xe1\x69\x13\x43\x90\x84\x85\x66\x00\x3b\x55\x12\x5c\xfb\xac\x9c\x09\x48\x12\x48\x1f\x41\xe1\xf7\x31\x6d\xc2\x0e\xb0\xdb\x69\xd2\x4e\xd1\x04\x6d\x23\x80\x3c\xf0\xbc\xad\x44\x12\x45\x4e\xb0\xbb\x48\xbe\xd7\xe7\x64\x5c\xe6\x52\x91\x03\x7d\x88\xf2\x87\x4a\x00\x9a\xed\xa4\x95\xb1\x71\x56\x69\x8e\xd5\x59\x1b\x8f\x99\x6d\xa4\xc5\x15\x89\xf4\x84\x05\x8a\xb0\x3b\x2a\x68\x8f\x4d\xb4\x3a\xba\x59\xce\x4c\x97\x98\xe8\x10\x4b\xd0\x55\xe9\x0e\x85\x7b\x2a\xdd\x1b\x31\x7b\x9c\x62\x69\xa2\xd6\xe5\x5e\x92\xed\x16\x2e\x4d\xaf\x7e\x6e\xfe\xe6\x4a\x37\x94\xfa\x2a\x6e\xe9\x5e\xbc\x7e\xcd\xf2\xa6\x57\xe6\xd4\x4d\x2a\xc3\x38\x12\x0f\x00\x98\x78\x5b\x29\x15\x67\x67\xaa\x13\xcf\xed\x98\x44\x85\xeb\xa2\x25\xae\x78\xa8\xc4\x6a\xed\x9d\x64\x0b\xa6\x02\x3e\xab\xa3\x18\x1f\xaf\xeb\x62\x2c\x0a\x21\x05\x25\x50\x12\xb5\xa2\xd9\xe8\x64\x84\xe2\x32\x11\x65\x58\x92\x51\xc4\x54\x92\x90\x15\x32\xac\x8f\xd2\x52\x81\x0e\x58\x91\x15\x16\x98\x10\x25\x33\x7a\x27\x07\x11\x26\x4b\xe9\xe3\xbb\x28\xb5\x92\xbc\xac\xe8\x77\x19\xbd\x49\x2b\x24\x03\xa4\x94\x3d\x2a\x82\xa0\xe2\x64\x8c\x9d\xd9\x2b\xb7\x5e\x18\x75\x3c\xf6\xfe\xf9\x2d\xee\x90\xf6\x2b\xed\x6a\x98\xdb\x9f\xbc\xe2\xe2\xcd\x72\x9c\x74\x2d\xdd\xb0\xe5\xe2\x91\x10\x24\x88\x37\x7f\xfb\xcb\x39\xe5\xab\xae\x1c\xfd\x14\x00\xf0\xf4\xbd\x5f\xf4\x4d\xdf\xb1\x6e\xc2\xa6\x49\xcd\x8e\xfd\xc4\x2e\x30\x0b\x5d\x53\xce\x9d\x50\xc2\x63\x33\x11\x9b\x3a\xb1\xbb\x39\x53\x19\xb0\x6c\x3a\xc6\x0e\x8b\xe9\x77\xd2\xee\xa9\x73\x76\x4e\xb5\x5e\x8d\xaf\xa8\x6b\x5d\xc4\xb0\x5b\xfe\x32\x6f\xde\x0d\x83\xdd\xac\x1d\xa8\xdf\xbf\x76\x47\xc7\x67\xd7\x7c\xdc\x1c\xfc\xf8\xdd\x29\xef\x10\x67\x00\x5c\xbe\x9b\xbf\xe7\x77\xde\x09\xd9\x66\xb7\x16\xf9\xc7\x03\x60\x2b\x69\x6f\xe8\xf1\x67\x2a\x28\x0f\x45\x91\x04\x45\x33\x14\x7e\xfe\x44\x78\x8c\xc5\xfa\x6b\x45\x83\xba\xfd\x91\x20\x6a\x20\x41\x66\xd2\xa9\x64\x80\x28\xf8\x5e\x41\xd4\xa0\x67\x32\x50\x73\xa4\x02\x47\x6f\x82\x18\x5b\x47\x69\xc5\x05\xe2\x2d\xda\x60\x9a\x2d\xa0\xcf\xe9\x5a\x51\x36\x95\x24\x45\x97\x5b\x60\x44\xf2\x2a\xa5\x71\xee\xd4\xba\x65\x01\x7f\x85\xcb\x71\x59\x65\x77\x59\xac\xca\x5b\xd3\xb0\xfa\xbe\xa1\xee\xdc\xaa\x2e\xb9\x77\x76\xf3\xae\xf9\x62\xa8\xbf\x23\x35\xa3\xae\x22\x59\x9a\x4c\xfd\xfb\xee\x9e\xef\xae\xea\x84\x95\x7f\xb9\x65\xfb\xb2\xa9\x3d\x97\x6a\x07\x9f\x5c\xe5\xec\x2f\x66\x80\xd2\x33\xf0\x46\xf2\xa4\x6c\x95\xc7\xea\x61\x18\xa7\xd3\xcb\x4d\xf5\x84\x23\x9e\xf6\x6a\x75\x5e\x22\xd8\xb6\xaa\xa7\x65\x41\x73\x9c\x8d\x89\xac\x50\xa6\xa4\x42\xd5\xd5\xa1\xe6\xea\x85\x3b\xe2\x13\xcf\xbe\xec\x96\xbf\xf4\x3b\x57\x3d\x09\xd4\xa5\x3d\x53\x97\x6d\x2f\x64\xb4\x83\x7a\xc6\xb0\xcf\xab\x0e\xe5\xc8\xff\x33\x62\x59\xda\x50\xb7\x11\x71\x35\xb6\x1e\xa2\x1a\xf8\xe4\x49\x83\xa6\x58\x1e\xb7\xca\x99\x55\x69\x0b\x30\x2c\x69\x38\xf8\x02\x0b\xca\x11\xf8\x54\x22\xeb\x05\xe2\x1f\x71\xca\xef\xce\xd7\x4b\x41\x1a\xa2\x52\x20\xfc\xb1\x18\x20\x3c\x76\x32\xe8\xd6\xfe\x58\x2a\xcb\xa5\x30\xdf\x15\x79\xd7\x31\xb5\x95\xa4\x69\xd1\x97\x0c\x6b\x9f\xda\xcd\x26\x6d\x50\xec\xb1\xa9\x7d\x03\xc4\x86\xc5\xed\xe2\xcd\x64\xeb\x54\x72\xda\xd3\x52\x24\x22\x1c\x7c\x90\xa1\x61\xc8\xeb\x28\x75\x6c\x6f\x71\xcb\x72\x69\x45\x69\xdc\xf7\x51\x8f\x76\xae\xf6\x4b\x4e\x74\x57\x89\x82\xc5\xac\xf9\x4a\x18\xb3\xd8\x47\x6d\x57\x17\xaf\x58\x31\xfa\x3e\x07\x0d\xb0\x03\x1d\x33\xef\x50\xb0\x54\x8e\xf3\xd4\xfc\x06\x8c\xd3\x11\x17\xab\x19\x3a\x33\xec\x2b\xae\xd8\x1e\xce\x0d\xcb\xde\x03\xc6\x92\x0c\x95\xf3\xca\x23\xa4\xb1\xde\x3b\x8a\x0c\x62\x72\x6c\xac\xe4\x1a\xeb\xb9\x04\x7b\xe4\x22\xf9\x30\x17\x22\x85\xa8\x7d\x06\xff\x63\x61\x15\x4a\x21\xa2\x6e\x5e\x34\xfc\x98\x8e\x22\x67\x49\xab\x7c\x26\x4a\x14\xd9\xda\x8c\xd8\x6f\x09\x0e\x43\xba\x51\xa8\xbe\x2c\x55\xfa\xb7\xea\xcf\xcd\xb2\x77\xa4\x33\x31\x9c\xe8\x1c\xf1\xca\xe6\xcf\xab\xff\x56\x9a\x2a\xab\x77\x02\xea\x59\x0a\xb9\xa5\x3d\x80\x9c\xda\xd0\x8e\x9f\xee\xd8\xf1\x53\xd8\x57\x56\x5f\x09\xb3\xce\xd7\x4e\x73\xb8\xbc\xb2\xf6\x49\xa2\xb3\x33\x01\x4e\xd9\xeb\x72\xc0\x0d\xe7\x6b\xf7\x56\xd6\x97\x95\x7a\x20\xb7\x72\xa5\x96\xf3\x10\x43\xfa\x0d\x3b\x0a\x65\x25\xf5\xb2\xc6\x0d\x4f\xdc\xa2\xb2\x1b\xfd\x8a\x7d\xa1\xce\x0e\xe3\xb3\xa1\xfa\xfe\xfa\xf6\xce\x85\x9d\xc6\x5f\x7d\x7f\xfd\xea\x7e\x9c\xeb\x5f\xad\xed\x33\x4a\x43\xb4\x6b\x05\x9e\xbc\xa1\xd1\xd5\x46\x49\x5e\xd1\x6a\xf5\x3d\x71\x99\x66\x60\xfc\xc1\x70\xff\xea\xd5\xf0\xe2\x91\x72\x14\xde\xa3\x1b\x85\x11\x8a\x43\x2b\xc8\x8a\x3c\xc6\x6a\x87\x19\x16\x44\x29\x36\x7e\x82\x87\x82\x41\x27\x57\x5a\x53\x36\xbb\xc5\x13\x6b\x6e\x8a\x79\x5a\x66\x97\x27\x4a\x39\x27\x39\xf7\x98\x0e\xe6\x7d\x78\x43\xec\x1d\x0a\x7a\x21\xe2\x2f\x2b\xf3\x47\xc0\x1b\x1c\xea\x15\x77\x9e\xa0\x8f\xa8\x3a\x84\xe8\xdf\x51\x87\x90\x03\xf5\x20\x84\x0a\x84\x6d\x42\x00\x27\x5b\x21\x4e\x33\x06\x38\x94\x12\x37\x62\xac\x29\xc3\x2d\x38\x2e\x2b\x72\x1b\xe8\x7a\xa6\x1a\x37\x7c\x84\x29\xd5\x20\x9b\x37\x30\x7c\x28\xc3\x11\x57\x12\xa9\x91\x05\x37\xbc\xf6\xfe\x6b\x37\x2c\x28\xec\x60\x15\xe9\xd4\xde\xb4\x3b\x58\xed\xcd\x87\x2c\x21\xcb\x43\xda\x9b\xac\xc3\xae\xbd\xe9\x24\x29\xf3\x43\x0f\x99\x29\xd2\x09\x31\xbb\x83\x85\xd8\x43\xe6\x88\xf9\x21\x88\xb1\x0e\x3b\xc4\x8a\x27\xb1\xf5\xc8\x63\x16\x2c\xb8\x21\xe3\xa0\x86\xb4\x97\x9c\x16\x0b\x3d\xf8\x85\xdd\xfe\xc5\x20\x6d\xb1\x38\x21\x39\x44\x39\x38\xdb\x17\x5f\xd8\x9d\x0e\x6a\x08\x92\x85\xb3\x36\x5b\xe1\xac\xf6\xd2\x10\xe5\x70\xda\xbf\xf8\xc2\x56\xb4\xfd\x9e\xa2\xce\x43\x2e\x54\x87\x50\x5c\xef\xd7\xf4\x6e\x8d\x36\x7a\xc0\x54\x32\x16\xa7\xc9\x62\x57\xe7\xca\xc6\x0c\x4d\x99\x05\xb7\x41\xaa\x6d\x68\xe2\xe4\x47\xd9\xfa\x47\xb4\x17\x1e\x5a\xf6\xab\x43\x4b\xee\xfd\x70\xfb\x65\x40\x80\x3c\xa8\x5d\xb0\xef\x46\x6d\xff\x4b\x9b\xd6\x3d\x0b\xae\xeb\xaa\x38\x57\x78\xf6\x82\x5d\x07\xae\x3c\xe7\xcc\xf2\x20\xcb\xbc\x67\x7e\x08\xb2\x8f\x8c\xdc\xd1\xac\xfd\xe8\xf5\xed\x1f\xde\xbb\x64\xf3\x33\xff\xf7\xaf\x4d\x2f\x81\xff\xc6\xeb\x40\xfa\xf5\xb9\x34\x2e\x2f\x0f\x4e\x7b\x79\xdd\x95\x07\x76\xa5\x5c\x41\xb6\xac\x80\x6d\x46\x8f\x14\xd7\xb4\x2b\x8b\x1e\x8c\xc6\x72\x7e\xf8\x38\x3f\xfe\xe3\x62\x5b\xda\xc7\xa1\x69\xe0\x25\xe3\xbf\xe0\x76\xd9\x7b\xc0\x38\x43\x23\xaf\x8c\xef\x2c\xc0\xff\xa1\x51\x03\xe9\xc3\x58\x85\x85\x3b\x8f\xe0\x70\x18\x38\x1e\xa1\x43\xc3\xf4\x10\x35\x82\x3a\xd1\x64\x23\x12\xaf\x12\x04\x46\x12\x05\xa3\x19\xb0\x64\x94\x8b\x72\x91\x04\xae\x19\xa3\x5e\x6c\x83\x22\xe9\x43\x13\x70\x8a\xfe\x7d\x04\x0d\x84\xa0\x22\x40\x10\x84\xd3\xd9\x90\x48\x0f\xc9\xde\x7d\x5d\xaf\xf0\xbc\x2b\xeb\x7a\x8e\x12\xda\x3b\x4f\xae\xcd\xa5\x4e\xeb\x69\x62\x1d\x8f\x0a\x7e\x0f\xcf\x13\xdc\x0b\x8d\x05\xb8\x8f\x3d\xbc\x9c\xe6\xf7\x10\x7d\x7b\xf8\xb4\xcc\xef\xd9\xe7\xd5\x26\xe6\x73\x8f\x83\xe5\x71\x3c\x3f\x2d\xdf\xbb\xfe\x37\x7c\x9a\xe7\xf9\x67\x29\x67\x79\xc8\x4b\xe4\x46\x73\x3e\x45\xb1\xb3\x2f\xbb\x9d\xae\x8c\xf0\xb7\xb5\xc3\xba\x60\x72\xe1\xc6\xc2\x63\xb4\x3f\x62\x74\xc1\xe3\x8f\x23\x04\x87\x0e\x21\x60\xce\x25\x27\xa1\x0b\x0c\x9f\x41\x9a\x61\x71\x00\x1b\x40\x1a\x01\xcc\x42\x94\xa2\xe5\x1a\x48\x10\x0c\x4b\x4a\x82\x41\x81\x11\xa5\x75\x09\x13\x04\x56\x0c\xb4\xad\x54\x3c\x00\xfa\x18\xa9\x6f\x03\x44\x52\x6d\x25\x0d\xec\x08\xc3\xe0\xd2\x5b\x8a\x14\x20\x04\x03\x0f\xc6\x98\x15\x6f\xc5\x6a\xb6\xb0\xfe\x81\xa5\x78\x56\x94\x98\x73\xa5\x3d\x9e\xf2\xb2\x40\x90\xe1\x13\x11\x12\x2e\x49\x12\x0c\x63\xaa\x90\x0f\x21\x4f\xbb\x20\x04\xfa\x1b\x3a\x3c\x84\xc5\xc3\x3b\x80\x21\x49\x57\x74\xdd\xa4\xab\xd7\x2c\xf2\x94\x58\xa2\xa7\x2f\xbb\xa4\x99\x26\x48\x47\x05\xb8\x6c\x22\x45\x39\x4d\x42\xda\xe1\x2c\xcd\x56\x96\xf9\xed\x98\x76\x99\x2d\x14\x66\x19\xba\xa4\xd9\xee\x72\x8a\x99\x9f\x0e\x64\x04\x1f\xcb\x60\x02\x03\xcd\xb1\x26\x57\xa4\xa2\x35\xde\x5c\x43\xda\x28\x12\xd3\x82\x05\x42\x4a\x92\x26\xbe\x68\x7f\x37\x94\x49\x55\x34\xf8\x2a\xaa\x82\x18\xef\x98\x4f\x39\xe4\x40\x09\x49\x09\x36\x9b\x7b\xf6\x84\x1a\x13\x50\x9e\xe8\x84\x4a\x47\x09\x4d\xf1\x04\x59\xde\xd1\xe5\xf1\x58\xca\x76\x0e\x03\x7d\x89\x53\xa4\x68\x1e\x63\x33\x49\x58\xdd\xc9\x95\xfe\xd2\xe6\xb9\x75\x7e\x0a\x4c\xb1\xc6\x65\x3d\x65\x9d\x76\x5b\xc4\x8c\x45\xde\xea\xc5\x60\xa3\xb8\x60\xb8\x31\x3d\x4f\xb6\xb6\x46\x6a\x82\x66\x4c\x7a\x2b\x17\xb4\x2e\xdb\x68\x71\x10\x04\x10\x04\x60\xca\x61\x36\xb8\x82\xef\xa1\x3f\xa7\xa6\x20\x8b\xd1\xe3\xd5\xa0\x59\x68\x39\x3a\x0f\xa1\xf8\x61\x9b\x58\x1f\x8d\x8d\xa4\x24\x66\xa5\x31\xbc\x4f\x29\x00\xf1\x04\xc4\x18\x9a\xd4\x3f\x44\x35\x1b\x8b\x0b\xac\xde\x2b\x26\x20\x93\x76\xa9\xd9\x98\x6e\x0e\x06\x20\x6b\xe0\xa2\xe9\x9f\xad\x61\x5a\xe2\x00\x14\x01\x43\xb3\x32\x43\x17\x4c\xca\xb8\x71\xcc\x38\xa4\x24\x40\x37\xd9\x75\x13\x1d\xdf\xee\x16\xa2\x91\x69\x6e\xd1\xd5\x3d\xe3\x2c\x93\xd9\xce\x96\x32\x5c\x80\x0d\x3c\x5c\xfd\xd7\x55\x2b\x67\xd4\xd4\xfc\x66\xc5\xaa\xc5\x60\x35\x0f\x6b\x87\x76\xbd\xad\xfd\x89\x35\x0f\x03\xec\x7a\x1b\xe2\x20\xf7\x5e\xf6\x73\x2d\xaf\xbd\xab\xfd\xfb\xb5\xed\xdf\xcf\xdd\x0d\xf3\x7a\x3b\xaa\x49\x9a\x75\xd0\xf4\xf7\x7f\x9f\xa8\xae\xc6\x14\x6b\xb1\x35\x2c\xec\x3e\x6b\x66\x09\x6f\xaa\x94\x24\x91\x11\xe6\xb6\x79\x2a\x48\xca\xeb\x69\x86\x59\x73\x52\x8a\x39\x99\xf5\x9a\xfc\xb1\xd6\xd6\xfb\xe6\xf8\x6b\x6d\x41\xff\xe6\xcf\x46\x23\x13\x1d\xac\x37\x1c\x99\x10\xf2\xdd\x60\xf7\x51\x94\xd5\x1e\x64\x29\xeb\xe0\x92\xa1\x58\x64\xef\xe2\x45\x0b\x7d\xa5\x0f\x37\x0f\x5d\x39\x91\x95\x3e\xdc\x55\xd8\xed\xec\xbe\x74\xc7\xb2\xd6\xae\xf5\x8f\x9e\xbe\x0e\xc8\xdc\xdd\xdf\xed\x6d\xbf\x9c\xb5\x61\x02\xe3\xa6\x96\xb6\x75\x76\xd6\x4a\x92\xae\xc6\xe5\x78\xf1\xe0\xe6\x7a\x49\x64\x4c\x95\x52\xdb\x90\x9d\xf2\x7a\x3c\xe5\x94\x7d\xfa\x50\x7e\x9d\xcf\xeb\x4a\xfa\x06\x1e\xea\x9e\x90\x71\xd1\xc1\xfa\x1a\xda\x3b\x65\xbc\x6e\xb1\x16\x99\x11\x8f\x4a\x11\x32\xf8\x6d\x5b\x41\x0d\x00\x70\x02\x66\x64\x2e\xed\x8a\x81\x93\x91\x71\x86\x13\x49\x17\x79\xc6\xbd\xcf\xfe\xe2\xde\x8b\x9f\x89\x44\x9f\xd1\x6e\xc8\xff\xfa\xe1\xbb\x20\x46\x66\x1e\xfe\x75\xfe\x41\x88\xdd\x15\x19\x1c\x9c\xf3\xc5\x65\x97\x7d\x41\xb5\x68\xbe\x51\xed\x3b\xa7\xbc\x0e\x9e\xc7\x61\xc2\xef\xf3\x15\xda\x3f\x5e\x3f\x05\x6e\x19\x85\x77\x02\xbf\xd7\x1e\x2f\x62\x3d\x23\x6a\x13\x8d\xd0\x4a\x84\x80\x25\x74\x55\x95\x46\x8c\x81\xf2\x91\x8d\xa9\x2c\x4e\x10\x4a\x2b\x04\xb0\x94\xd5\xd3\x94\x9e\xa6\x82\x90\xcd\x24\xa8\xac\x1a\x20\x59\xec\x00\x51\x60\x5a\x29\x51\x62\xf5\x0f\x99\xd6\x93\xd4\xa6\xd0\xdc\xc1\x65\xa7\x0c\x4e\x6f\x76\x72\x6b\xb4\x5b\x5e\xe1\xbd\x5e\x7e\x0f\x54\x2e\x89\x4d\x1e\x9c\x7b\xf2\xec\x93\xc2\x6b\x9f\xff\xde\xda\xb6\x92\x8c\x97\x11\x27\x75\x2f\x1e\x98\xdd\x5e\x4d\x4f\x3c\xef\xe4\xd9\x2d\xa9\xb0\x48\x91\x36\x93\x6f\x52\x7d\x9a\x95\x53\x3d\x67\x34\xc7\x28\x5a\x70\x99\x18\x00\x82\xad\xc9\xce\x5d\xbc\xad\x1b\x2b\x2d\xd3\x66\xcd\xec\x6b\xe2\x38\x29\x49\x7b\xa6\xf4\xaf\x3f\x6b\x27\xfc\xa4\xff\xac\x96\x10\xc1\x06\x4a\x2c\x96\xfd\xda\x97\xe0\x95\x4b\xe0\xb5\x27\x58\x97\xc9\x5e\xd5\xbb\xf5\xa4\x1a\x21\x3a\xad\xaf\x6a\xc7\x30\x10\x98\xe0\x4a\xeb\x7b\xd7\x4d\xf4\x73\x7c\x79\x53\x5b\x5b\x9d\xc3\xb9\xa9\x87\x16\x26\xf4\xae\x5e\x73\x49\x77\x49\x4f\xff\xfc\xb9\x27\x4d\xcc\x3a\x1c\xe4\x42\x2f\x23\xb5\x65\x1a\x83\x58\x9a\x76\xde\x40\x4b\xc0\x05\x04\x41\x5c\x71\x21\x23\x35\x25\x64\x5c\x87\x48\xe4\x3e\x84\xc8\x7f\x52\xc8\xf0\x24\x17\x8c\xf8\x2a\x43\xc3\x82\x82\xcf\x3e\xb8\xc3\x9c\xfe\x17\x77\x8f\x31\x32\x91\xff\x5c\x37\xa3\x41\x1b\xcd\x7f\x3c\x63\x1d\xf9\xfb\x83\x15\x63\x7f\xeb\x66\x10\xd3\x66\xac\x03\x5f\xe7\xac\xf5\xda\xbf\xc0\xbe\x7e\x56\x27\x4c\x3c\x84\x0e\xc1\xe4\x43\xe8\xd0\x0f\xba\xba\x66\xae\x5f\x3f\x4e\xcf\x2c\x41\x71\x7d\xd4\x44\x5f\x49\x63\x2a\x7e\x45\x70\x17\x99\x2b\x12\x99\x8e\x91\x6c\x16\x88\x4c\xef\xfe\xba\x40\x2f\xbc\xf3\x04\x7c\xa6\xf7\x7e\x5d\xc0\xd7\x51\x3a\x71\xb1\xac\x47\xb3\xb1\x8e\x27\x63\x75\x7d\x65\x59\x79\xbb\x36\xac\x17\xf0\x08\x15\x2b\x0c\xd9\xf9\xe1\xaf\x2d\xec\xbe\x62\x11\xa1\xcd\xec\x1f\x63\x64\xd5\x0e\x7d\x6d\x69\x8f\xd3\xdf\x0b\x73\xa6\x47\x8a\x79\xac\xfe\x7e\xdc\x6a\x03\x92\xbd\x02\x57\x08\x3b\xe3\x04\xaf\x0c\xe8\x6b\x02\xd4\x46\xf2\x39\xaf\x6c\x2b\x86\x8d\xd9\xe4\xd1\xe7\xbe\x45\x3c\x18\x83\x78\x14\x3c\x12\x87\xef\xfa\x0a\xc6\x80\xe2\x7a\x6e\xc5\xd7\xf1\x06\x14\xa3\xeb\x21\xf4\xb5\xf4\x01\x45\x1f\xf7\x45\xd4\x3e\xe4\x46\x59\x84\x40\x32\xd4\x31\x5d\x1b\x53\x25\x7d\x6c\x45\x29\x5d\x29\x95\x8c\xde\x88\x28\x00\x89\xa9\x06\xb9\xa8\x5b\xa0\x15\x3e\xec\x0e\x4b\xe1\xa4\xc4\x13\x87\x96\x34\x6a\xaf\x3c\x7e\xa3\xf6\xf9\x0d\xbf\xb9\x87\xdb\xb4\x0b\x98\xbd\x5b\x5f\x3b\x1b\xfb\x1a\x0f\x21\xbb\xb3\x8c\xfb\x58\x2b\xf3\xc4\x89\x21\x6c\x62\x67\x67\x3b\x07\x97\x75\xc7\xe1\x2e\x6d\xb9\x13\x7e\x59\xc6\xed\x87\x45\xbf\x7e\xf0\xcf\x37\x80\xf9\xc6\x87\xa1\xa2\x75\x47\xf6\xed\x0b\xf6\x6a\x5f\x6e\x7f\xcb\xbb\x36\xc7\x44\xe1\xad\xb0\x87\xb0\x72\x25\xa9\xb6\xc1\xce\x09\xdf\x61\xb4\xb7\x73\xb9\xa8\xd6\x70\x02\x5e\x9f\xac\x22\x13\xd9\x54\x92\x61\xc1\x70\xa7\x94\x0b\x53\xba\x52\x21\x36\x4b\x12\x53\x49\xde\x75\x9c\x77\xa2\xcd\x72\xef\xdf\x67\x54\xc9\xb3\xac\xe4\x0f\xa2\x95\x8a\x3d\x14\xd8\xde\xb4\xdc\x77\xba\x2f\xdd\x67\x6d\x48\x3a\x9a\x1d\xdd\x43\x37\xfd\xf5\xcd\x03\x47\xbd\xcf\xed\x7f\xa0\x4d\xda\xbf\xf8\xa1\x86\x37\xef\xce\xfe\xea\x49\x1b\xb3\xc8\x33\xe4\xe9\x4a\x3f\xa8\xfe\x49\x7d\x10\x64\xf0\xc1\x79\x47\xad\xa0\xc1\x61\x1e\x0c\xdd\xfe\x15\x30\x59\x30\xc3\x0e\x3b\x18\xb5\x41\x66\x7c\x7a\x2c\x0c\x2b\x9e\x15\x4b\x41\x60\x28\xf7\x58\x82\xcb\xa2\xe2\x49\x32\xf7\xa4\xf6\xc4\xcf\x86\x59\xd7\xeb\x04\x6d\x31\xdb\xa5\xf7\xc6\xf6\x2e\x76\x98\x75\xc1\x7a\x87\x57\xd2\xd6\x17\x77\x4f\x00\x69\x1c\xc5\x23\x3f\xd3\x9e\x78\xd2\xc5\xe2\x53\x3a\x81\xb6\x38\x73\x92\x69\xd2\xa2\xc3\xa9\x03\xba\x55\xf9\xf0\x59\x94\xa0\xe7\x36\x2e\x1a\x4b\x68\x25\x76\x10\x9e\x62\x5d\xae\x71\xb1\xdf\xd1\x22\xfa\xb4\xbb\x18\x66\x54\x10\xe6\x70\x67\x74\x78\x55\xec\x5b\xc6\x83\x6b\x05\x56\x4b\x6d\xd8\x30\x7e\x87\x0a\x31\x28\x43\xdf\x18\x1d\x7e\xdc\xf5\xc6\x93\xbe\x2e\x5a\xbc\x18\x17\x6b\xca\x51\x08\x29\x06\xe3\x5f\x7f\x61\xf5\x2d\x53\x30\x82\x13\x50\xa0\x35\xce\x36\x41\x26\x95\x94\xc2\x86\x06\x63\xb8\xa2\x02\xa3\x8a\x02\x23\x65\xd3\x0a\x84\x69\x26\x42\x3b\x00\x58\xa8\x04\x22\x95\x24\xa2\x7c\x2a\x29\x4a\x10\x20\x53\x54\x58\xc6\xa7\x9f\x79\x73\xae\xdd\xce\x33\x8d\x53\xa7\x36\x32\xbc\xbd\x3d\x77\xf3\x99\xe4\xbc\x8a\x6d\xce\x79\x9b\xaa\xab\x37\xcd\x73\x6e\xab\xa0\x33\x99\x19\xdd\xdd\x07\x67\x11\x9f\xbf\xf1\x71\xc3\x6a\x9f\x5f\xdb\xe7\x9d\x57\x3d\xb4\xa8\xf4\xa6\x9b\x4a\x17\x0d\x25\xe6\x7a\x21\x44\xb2\x35\xc9\x9e\x18\x3c\x3f\x6a\x3e\x0b\x86\xdb\xdb\x6b\xc2\x9e\x12\xcc\x79\x38\x5c\xe2\x09\xd7\xb4\xb7\x33\x22\xe1\x48\x55\xc5\xaa\x52\x0e\x42\x64\x46\x63\xab\x63\x81\xda\x2b\x6b\xb5\xdf\xcb\x15\xb5\x1e\x8f\xb6\xcf\x2b\xc3\x2b\xb0\x0f\x5e\x91\xbd\xda\x3e\xd2\x1e\x2e\x71\xf7\xb7\x17\xbf\x8f\x1c\x8d\xd0\x80\xe1\x9f\xac\x7f\xac\xba\x85\x58\x58\x45\xaa\x01\xea\x48\x72\x8c\xa0\xa1\x0d\x88\x23\x49\xa5\xe8\xc6\x1a\x84\xf8\x91\x64\x11\xde\x8e\x76\x00\xaf\x66\x21\x4e\x50\xd4\xc7\xad\x27\x2d\xba\xaf\x9e\x99\xd9\x54\x33\xd5\xa1\x6a\x2f\xa8\xa6\x99\xcd\x35\x7d\x0e\xf5\xba\x52\x77\xcb\x0c\xb5\xea\xc6\xe5\x37\x7a\xc5\xe6\x01\xb5\xea\xa6\x4c\xe1\x44\x16\xb2\x59\xd3\x2c\xfd\xe2\xcc\x6d\x6e\xb1\x79\x56\x73\xd5\x4d\xcb\x77\x7b\x46\x47\x21\xbb\x5c\x7b\x01\x7f\x31\xa3\xe5\x3b\xe1\xa6\xbb\xdc\xde\xa6\xd9\xd9\xea\x3b\x56\xec\xf6\x48\x7a\xe2\xf6\x8c\xb9\xbf\xa5\xa6\xcf\x91\x81\x86\xac\x69\x86\xfe\x94\xcc\x2d\x1e\xa9\x79\x56\xb6\x7a\x78\xf9\xb0\x7e\x89\x5a\x75\xab\x4a\x4f\x6f\xaa\xee\x71\x64\xb5\x5f\xd4\x9b\xb4\x03\xcb\xa1\x69\xe5\xb1\x73\x35\xe5\x86\x27\xd5\x31\x3e\x22\xc0\x15\x89\xec\x1b\xa0\x48\x65\xaf\x14\x5b\xec\x58\x03\x2e\xe2\x65\xd0\xc9\x56\x4a\x8d\xb7\xc2\x78\x27\x12\x62\x5f\x30\x1c\x79\x36\x73\x72\x67\xe7\xc9\x35\x4f\xd5\xd8\x2a\x2c\xf5\x65\x44\x7b\x59\xbd\x5a\x3e\x3a\x52\x56\xdf\x12\xaf\x79\x58\x21\xfc\xac\x9f\xf7\xb8\x05\xb7\x87\xf7\xb3\x7e\x02\xac\xd1\xb6\xa3\x7d\x4d\x0e\xee\x83\x87\xa2\x82\xb8\x35\x36\x61\x42\x68\x63\xc8\x24\x9b\xb4\xbe\xb2\xfa\x7a\x7c\x5a\x79\x63\x7d\x59\x7c\x7a\x49\x68\xad\x17\xf3\x66\xce\x6c\xa1\x28\x8b\x99\x33\xf3\xf8\x47\xd2\x74\x34\xb6\x96\x68\xc4\x1e\x50\xa8\x0d\x4d\x42\x33\xd0\x77\xd0\x1a\x84\xf8\xb4\x0a\x32\x36\x10\x32\x09\x63\xe9\x47\x76\x14\xe6\x34\x74\xdb\x89\x3f\x7c\x28\x22\x47\xb3\xb1\x54\x92\x94\x0a\x21\x9e\xb4\x24\x52\xbc\x28\x19\x63\xa0\xe8\x16\x30\xc3\x67\x33\x69\x14\x22\x45\x97\x13\xd3\x64\x28\x26\x63\xa7\x2b\x8b\x42\xb1\xac\xcb\x89\xe5\x58\x88\xa4\xb1\xd3\x25\x9e\xd7\x05\xab\x7e\xf1\x11\x65\xa2\x1c\x26\x1f\xd9\xa7\xbd\x9f\xa8\xe0\x59\x9e\x7f\x71\xca\x79\x36\x8e\x26\x1c\xb6\xfe\x0d\x3f\xd4\xfe\x51\x3c\xc6\x84\x2c\xcb\xe1\xa4\xe7\xae\x00\xeb\x72\x8b\xda\x4b\x92\x36\xda\xc5\x88\x44\x9b\x46\x7f\x08\xe4\xd6\x6d\xab\x97\x13\x9b\x17\xbf\xf2\xe3\x7f\x36\x8d\xde\x06\xa7\x43\xdf\x27\x3b\x77\x7e\xa2\x3d\xa4\x5d\xa9\x3d\xa4\xa7\x60\x16\xcc\x87\x96\x77\x2e\xbc\xf0\x1d\xed\x19\xed\x4e\xed\x19\x3d\x85\x73\xb7\x5f\x3d\xca\x2f\x86\xb3\xc0\xc4\x2b\xcd\xfe\xf9\xf6\x43\x88\x68\x24\x28\x1c\x2e\x05\x0b\x98\xc1\xe6\xe2\x59\x30\x69\x8f\x69\x26\xa2\x7d\xec\xe8\xf0\xe3\x2b\x86\x66\xa8\x36\x0f\xef\x73\x04\x6c\x31\x6a\xe5\xab\xf9\x8d\x34\x55\x15\x22\x07\x7e\xf4\xcc\x6f\xb4\x5b\x96\xe0\x3b\xef\x5e\x59\x81\xd3\x47\xfd\x70\x9f\x51\x98\x2f\x1f\xbd\xf0\x1d\x68\x39\xa6\x0c\x87\xb9\xa0\xf4\xfa\x77\x21\x9f\xae\x41\x50\x72\x4c\xff\x46\x62\xaa\x9b\x26\xdd\x02\x29\x71\xc0\xc7\x55\x59\xc9\x90\x12\xd9\xaa\x7d\xb2\x5f\xfb\xc1\xef\x7f\x05\x8b\xde\x78\x43\x7b\x0f\x32\xef\x13\x7b\xe2\xf9\x7f\x5d\xb1\xfe\x56\x70\xff\x9a\x46\x07\x50\x4e\xd8\x9d\xdf\xf5\x83\xcf\x77\x7b\xef\x93\xf7\x5d\x7a\xed\xbb\x01\xaa\x5f\x6b\xd3\x36\xad\x3d\x69\x62\xe9\x7d\xe1\x2d\x63\x3e\xe6\x06\xef\x94\x0d\xc9\xa8\x16\x21\x33\xb8\xa3\xc5\x26\x1c\xcd\x40\x98\x4b\x71\xe3\xfe\x8e\x60\xc7\x51\x63\xc9\x14\x31\x42\x8c\xe4\xca\xfd\x07\x2c\xfe\xf2\x1c\x20\x40\xb9\xb1\x7f\x4d\xfe\xf2\x2f\x73\xe5\xfe\x26\xba\xc9\x5f\xfe\x45\xae\xdc\x4f\x23\x2d\x57\x40\x00\x39\x84\xf2\x88\x18\xf7\x57\x80\x27\x1d\x91\xbd\xfa\xf9\xa2\xfc\xe6\x42\xec\xba\xae\x2f\xf0\xa2\xd1\x50\x54\x9e\x12\x93\x6a\x91\x6f\x2b\xce\x02\x23\xba\x05\x86\x2f\xfa\x78\xca\x2a\xaf\x77\xb6\x59\x35\x3e\xc6\xeb\x45\x7f\xe4\x22\xef\xd3\x7e\xaf\xed\xd6\x7e\x7f\x1f\xe9\xc2\xad\x62\x5a\x24\xfb\xc5\x83\xc3\xa4\x8d\xcc\x9f\x55\x59\x4f\xb7\x35\x36\x62\x8b\xd9\x31\xe2\x30\x5b\x70\x63\x63\x87\x75\x8e\xf6\xa0\x28\x92\x43\xa4\x8d\x24\x87\xf0\x13\xda\x2f\x26\x9c\x33\x61\xc2\x39\x13\xa0\xf9\x61\x86\xc1\xce\x84\x49\x1b\x06\x78\x29\x72\xc3\x69\xb1\x9e\x09\xb2\x36\x9d\xb5\x5a\xad\x56\x16\x7e\x22\x4f\xe8\x91\x5f\xde\xbc\xcc\x94\x30\xc1\x10\x80\x36\x8c\x00\x9d\x71\x28\x47\x5d\x51\xf0\x69\x01\x5e\x8e\x46\x18\x5e\x46\x58\x11\x53\x49\x35\x00\x2e\xa9\x95\x50\xf5\x64\x1d\x4b\x30\x34\xb1\xc0\xde\x5a\x59\xde\x6e\x2f\xd3\x0e\xdd\xbf\xa8\x31\x59\xd5\xd5\x76\xc9\xcf\x2b\xe2\x97\xcf\xdf\x50\x93\xcd\xd4\x37\xfa\xdb\xa3\xd3\x2c\xbb\x70\x57\xbe\xc5\x6a\xc5\xcf\x4c\x80\x67\xa1\xec\xfb\x0e\xc7\xaa\x0f\xb5\x5f\x4c\x68\x79\xef\x8a\x17\xe7\xb0\xac\x72\x4a\xe3\x77\xb9\x2f\x8a\x9c\x38\xd4\x5f\x8c\x31\x14\x41\x58\xff\xca\x0a\xf3\x5d\x4e\x57\x36\x96\x0a\x49\x8c\x1c\x8d\x18\x4a\x5e\x2a\xd9\x4a\xa8\x61\x02\xe1\xd7\x6c\x8f\x68\x3f\xfe\xe3\x4d\xda\xfe\x97\x36\x6e\x7c\x09\xfc\x37\x41\xd5\xeb\xbf\xd9\xfc\xe8\xb6\x3f\xe5\x72\x7f\xda\x36\x67\xd7\xe0\xc4\x30\xad\xf5\xe1\x8f\xba\x5a\xde\xd0\xee\x1d\xd1\x2f\x80\x46\xf0\xbf\xb4\xf1\x57\xbf\x5a\xbf\xfd\x6d\xed\x8b\xb7\xb7\xd7\x4e\x5e\x38\x10\x2f\xf8\x95\x15\xfa\x09\x27\x2a\x41\x11\x34\xcd\x58\x8d\x10\x19\x3a\xa4\xc8\x86\x13\x7d\x2a\xa9\x66\x93\xb1\x22\x60\x73\x92\x2a\x6a\x9c\xa2\x9a\x96\x23\x8c\xac\xf0\x92\x20\x26\xb3\x06\xb6\xa9\x22\x33\x04\xcd\x14\x03\x3d\x24\xda\x2d\x90\xa9\x64\x2c\x93\x56\x5a\x21\x36\xae\x97\x88\x85\x48\x91\x9c\xe4\x74\xb6\x6a\x1f\xb5\x3a\x9d\xb4\x8b\xae\xdd\xb8\xa1\x8e\x76\x69\xaf\xa6\x7b\x33\x99\x5e\xf8\x59\xa6\x37\x9d\xee\xcd\x1c\x9c\x78\x6a\x6c\xfb\xc3\x6d\xcf\xeb\x07\xe3\x59\xef\x5b\x3c\x3d\xe1\xa1\x6d\xd1\x74\x72\x62\x3c\x48\x83\xe7\xd9\xe7\xc0\xc3\x04\x62\xb0\xe4\x04\xdf\x23\xac\x71\x3a\x5a\x5b\x1d\x4e\x9a\xae\xab\xa3\x7f\xd7\x9b\x4e\xc7\xe5\xf4\xfc\xb8\xfe\xcc\xf4\x40\xdd\xc4\xd8\x7c\x1a\x7c\xd5\xf1\x74\xa6\x37\x93\xac\xa3\xdc\xda\xf3\xcc\xfc\xf8\xc4\xba\x68\xa3\xc3\x57\xba\xf3\x85\x17\x76\x86\x4a\x1c\x0d\x8f\x1f\xf3\xc0\x9d\x3b\x3f\x39\x1a\x07\xcb\x61\xb0\x39\xe9\xfd\xa9\x51\x4f\x91\x62\x3d\xe9\xd5\x14\x1f\xab\x26\x91\x3a\x9c\x52\x8d\xca\x91\x15\x55\xd2\xdf\xdd\x57\x54\x55\x21\xda\x5e\x39\xde\x6f\x89\xb8\xd7\x6e\xcf\x7c\x90\xb1\xdb\x29\x27\x55\xf1\x52\x05\xe5\xd4\xb4\x44\x6b\xa2\xba\xbd\x1a\x06\x0a\xfb\xd7\x9b\x2b\x2b\x82\x6b\xae\xcf\xde\x0b\xd5\xc1\x50\x75\x75\xa8\xd6\xfd\x24\x47\x36\x5f\xbf\x2a\x50\x55\xd9\x1c\xf2\x52\x9f\xdc\x7d\xcf\x27\x74\x49\x10\x52\x47\xe1\x4f\x5c\x63\xb7\x67\x32\x76\x3b\x4d\x57\x54\xd0\x57\x07\x13\x09\xe3\xce\xe2\x7e\x52\x45\x73\x70\x1a\xf9\x2f\x25\x54\x55\xdd\x5e\x5d\x59\x41\xb9\xb4\x7f\xd3\x53\x43\xcd\x15\x81\xa4\xbd\x44\xda\xb4\x67\xcf\xa6\x12\x8f\xbd\x0e\xf6\x9f\xd8\x2e\x09\xa0\x5a\x03\x91\x59\x2d\x82\x8f\x1d\x76\x4b\x31\x04\x2c\xb8\x9c\x94\x02\x95\x29\x3a\xaa\xb4\x00\xa3\xb8\xf5\x06\x74\x94\x9b\xe4\xc9\xf3\xcf\x1a\x3e\xcb\x2f\xfb\xae\x59\x37\x30\x63\x9d\x4f\xe0\x7d\x70\xd1\xd5\xfa\x6e\x7e\xf3\x59\xb7\xad\x83\x19\xc7\xda\x2f\x7b\x7d\xad\xd3\x57\xaf\x9a\xae\xbd\x23\xf8\x7c\xc2\x86\x4d\x03\x6b\xd7\xf4\x83\x87\xf7\xfb\xf9\xec\xdb\x9b\xb6\x0a\x3e\x3f\xbf\xd9\xeb\xdf\xdc\xbf\x76\x2d\xec\x39\xd6\xaa\xd1\xfb\xa8\xdb\x99\x1c\xb5\xc8\x28\xb7\x81\x8b\x54\x28\x74\x21\xc4\xfe\x30\x79\xbd\x51\x68\x86\x0a\x8f\x9d\x91\xd4\xc2\x29\x52\x6e\x9e\xd9\x3c\xfa\x93\x07\x0e\xc2\xe4\xe6\x99\xcd\xf9\x1f\xdf\x3f\xfa\x0c\x5c\x0a\x93\x0f\x3e\xf0\x93\xd1\x1d\xcf\x34\xcf\x6c\x26\xea\xcf\xa9\x68\x6e\xae\xc8\xdf\xf8\xe3\x2f\x0e\x3e\x00\x16\xed\x40\x65\x53\x53\x25\x3e\xfd\xde\xcf\xfe\x7d\xdf\x85\x8d\xb7\x6a\xff\x7d\xe0\xe0\x97\xf7\x83\xad\xa5\x51\xfb\xac\xa2\xa9\xa9\x62\xbc\xbd\x62\x47\xa5\x08\xc5\xb9\x30\x17\x2e\xd0\xa3\x9e\x40\x3f\xa6\x46\xf2\xed\x5a\x68\xd1\x0e\x3c\x02\xfb\x16\xed\x68\x1f\xff\x7e\x87\x61\x1f\x1e\xd9\xb1\x48\x0b\xe5\xdb\x77\x90\xa5\x47\x3b\xec\x99\x10\x42\x5e\x13\x22\xdf\x45\x14\x32\x23\xbb\xc1\x4d\x56\x8a\xe2\x06\x6e\x8e\x3e\x3c\x84\x4b\x20\xca\x01\x97\xe2\x08\x77\x2a\xc3\x87\xb9\x70\x26\x9c\x09\xc7\xb9\x28\x07\xe3\xd3\x93\x7f\x9d\xff\x00\x26\x6f\x86\xeb\x5e\x7c\xf1\xc5\x01\xec\xce\xff\x13\x26\x6b\x8f\xe9\x07\xae\xc7\x42\xfe\x03\x98\xa4\xed\x85\x49\x9b\xc9\x77\x47\xcb\xf1\xde\xfc\x3f\x61\x8d\x76\x29\x76\xe7\x27\xe1\xbd\x10\xf8\xf5\xaf\xb5\xbf\x8e\x0e\xdc\x3e\xb0\xbb\x70\xf0\x70\x72\xdc\xf7\x65\x36\xb0\x51\x6b\x51\x7b\x81\x7f\xa7\x10\xf3\x31\x2e\xe5\x2c\x02\x79\x33\x9c\x9a\x11\x53\x49\x6c\xe4\xa3\x85\xcc\x71\x86\xb8\xd8\x97\xa9\xf4\xf9\x2b\x32\xda\x7f\x8a\x09\xbc\xf5\xfe\x73\x05\x5e\x52\xe7\x6c\x79\x35\xd5\x79\xee\x5d\x3f\x39\xb7\xb7\xeb\xa7\xaf\xaa\x2d\xe7\x12\xd2\x51\x4e\x94\xdd\xb9\xf9\x0e\x70\x73\x30\x23\xb7\x40\xdf\xe7\xeb\xc0\xf6\x14\x31\xad\x71\x31\x9d\x3f\xbf\xfc\x25\x1e\x2f\x07\xdb\x53\xb1\xd1\xc7\xca\x5f\xe2\xe1\x8b\xa3\xeb\xd7\x82\xca\x0f\x99\x99\x17\x69\x84\xb6\xa3\x27\xd0\x0b\xe8\x25\xf4\x26\xfa\x1b\xfa\x3b\x7a\x0f\x7d\x88\x3e\xd6\x6d\xd0\x00\x21\x05\xb0\xc4\x62\x26\x41\x45\x1d\x20\x4a\x01\x26\x08\x22\x8b\x19\xb9\x10\x40\x92\x56\x5b\xb1\x22\x1b\x26\xaa\xe1\x79\x43\x16\x94\x6d\x7d\x48\x6c\x25\x0a\x16\xb5\x34\xa6\x61\x63\xba\x88\xd2\x81\x33\x69\x55\xd1\x3b\x10\x23\x46\x4e\x52\x59\x42\x52\x13\x8c\x92\xc0\x15\x10\x8d\x30\xad\x94\x1a\xc0\x6d\xe0\x96\xb2\x6a\xab\xa9\xad\xe0\xb3\xc4\x62\x26\x00\x6e\x81\xd0\x1f\x18\x20\x0a\x9a\x9d\x2a\x31\x50\x00\xa6\x56\x5a\x71\x0a\x18\x45\x3f\xc9\xa7\x24\x06\x32\x6e\x07\xb4\x61\xf2\xb9\x29\x17\x9d\xb2\xb4\xa3\x32\xbc\xa0\x79\x42\xed\xc6\x1b\x63\x55\xcd\x3e\x25\x71\x4a\x8f\x85\x26\xcd\x74\x15\x13\xa4\x5c\x04\x0d\x00\x8c\x89\x23\xa2\xe7\x87\x94\x30\x26\x70\x93\x0a\x1e\x3e\x76\x4d\x4b\xc9\x69\xab\xfd\xb4\x5b\x0b\x04\x9d\x1e\x8e\x85\x77\x4d\x56\x37\xef\xa3\x48\x89\x76\x78\x99\xdb\xcd\x5c\x09\xe7\x78\x04\xe0\x0e\xb1\xe6\xb2\x1a\xb5\xc6\xd2\x5d\x49\x0d\xb4\x56\xa9\x15\x82\xdb\xe2\xb1\x25\x89\xb2\xea\x28\xb4\x50\x1c\xc3\xd2\x16\xc6\x4c\x32\x0e\xaf\xab\x86\xdd\xba\xc0\x59\xd6\xdd\x56\x3a\xc9\x64\x0b\x85\x44\x9b\xf8\xf9\x16\x7f\x55\x79\x49\x84\x8d\x5a\x2b\x4d\x0c\x2e\x9f\x3e\xfa\x10\x5b\x5f\xc5\x11\x95\x9f\x2b\x7b\xb3\x66\x5f\xa9\x54\x82\x37\x6e\x6e\x69\xd7\xbe\xac\x3d\xa3\x07\x6e\x25\xa2\x0d\xa9\x7a\x92\x71\x4f\xef\xf0\x6b\x13\x86\x68\x4b\xb5\x8d\x7f\x35\x68\x29\x27\x36\x02\xd6\xff\x5f\x4c\xd4\x4c\x5c\xff\x9d\xc9\xf5\x2b\xd4\x96\x80\xda\xe6\x8c\xdf\xb8\xe7\x89\xab\xbe\x83\x49\xca\x4c\xc5\x99\x52\x5b\xa0\x24\x2e\x86\xbd\x6d\xe5\x7d\x0e\x70\x5b\x9c\xc1\x5e\xd1\xde\xd0\xe2\xc6\xde\xcc\xa2\xad\xd7\x09\xa4\x77\xb5\xe8\x74\x48\xc4\x0a\x56\xb4\x5b\x48\x0a\x83\x3d\xc4\xc5\x45\xce\x21\x12\x65\x4e\xef\xa3\xc3\x75\xb1\x08\x21\x78\x9c\x2e\xbe\xaa\xc7\x1b\x72\x12\xac\x3d\x16\x6c\xf7\x97\x94\x95\x61\xab\xe3\xf7\x94\xdb\xe4\xa0\x2d\x14\x85\x09\x12\x2a\x03\x61\x6f\xc2\x77\x92\xd9\x5c\xed\x07\xe8\x83\xc5\x8b\xdd\x31\x45\xaa\xe6\x1a\xf8\x3e\x87\x39\x33\xfb\x8e\xe7\x2a\x09\xb3\xc5\xcc\x67\x19\xeb\xe8\x4c\x6f\x65\x30\x9b\xa8\xa7\xaa\xad\x44\xcc\xf6\x93\x5a\xed\x15\x07\x30\x0e\xab\x89\x81\x4a\x6c\x67\xf0\x59\x02\x07\xb6\xfc\x96\x93\x6c\x74\x1d\x80\xf1\xe4\x82\x8d\xeb\xa2\x11\xf5\x11\x92\x50\x16\x2d\x42\x3b\x10\xa2\xe4\xe2\x6c\x48\x34\x52\x70\x1f\x37\xa2\x2d\x0d\xb7\xe6\xc2\x57\x66\xb8\xd4\x31\xa9\xa4\xe1\xb0\xa6\x66\x21\x9d\xc0\xba\x22\x12\xa5\x13\x84\x61\x16\x19\xa3\x5a\x6b\xc1\xf7\xd9\xf0\xf8\x12\x8a\x63\x7d\x26\xdd\x4a\xa9\x46\x93\x55\x8b\xf6\x11\x79\x29\xc5\x07\xd6\xf6\x6e\x6b\xa7\x4c\x56\x07\x03\xa6\xc8\xca\x93\x93\xe5\x73\x2a\x19\x5b\x15\x2f\x48\x99\x1a\x4f\x69\x9d\x97\x35\x73\x12\xe1\xa0\x59\xb3\x93\xe5\xad\xbe\xa8\xd5\x64\xa1\x2c\x12\xcc\xb7\x48\xd5\x81\x70\x6e\x7b\xcc\xd7\x33\x7d\xee\x6a\x75\xdd\x6e\x8c\xfb\x4a\xbb\x26\x36\x5c\x7d\xce\xa6\x90\x77\x5a\xc7\x24\x21\x5a\x13\xf2\x97\x66\xb6\xbc\xa2\xfd\x53\x7b\x45\x7b\xf7\xb5\x9c\xd2\x34\x30\x65\xa0\x86\x67\x7b\xa3\x2d\x81\x58\x95\x69\x5b\x43\xd5\x7d\x95\xee\xd8\xac\xae\x93\x54\x25\xc9\xb3\x62\xa4\x8e\xb4\xd1\x82\x25\xe4\x27\x08\x32\xec\x63\x6c\xe7\xd7\xb0\x0e\x8b\xad\xca\x23\x98\x18\x01\xdb\x49\x0b\x49\x13\xd8\xc1\x3a\x38\x9a\xb4\x41\x8d\x58\x5d\xed\x3f\x69\x26\x94\x35\x36\x96\x01\xdc\x70\xda\xea\xb4\xc0\x75\x4c\x6d\x07\x68\xe9\x69\x05\x22\x92\x28\xdf\xf0\xd2\x6e\xed\xef\x3f\x3b\x7d\xdd\x2f\xc1\x3f\x3c\xef\xae\x2d\x6b\xa6\xb4\x97\x5a\x4c\x71\xa1\xcc\xe3\x9f\x37\xe3\x06\xb9\x74\x9a\xcf\xee\x99\x30\xf9\x9c\xad\xf7\xa2\xf1\xd8\x5b\x01\xd4\x8c\xe6\xa3\x0d\x08\x81\x03\xb3\xa0\x8c\xc5\xf3\xaa\x72\xb6\x0d\x24\x86\x16\x24\x31\xd9\x46\x10\x12\xa3\xc8\x11\x5a\x08\x12\x4c\x0d\x4e\x80\x9a\x28\xe0\x08\x89\x52\x56\x2c\x04\x91\x2a\xb4\x5c\x03\xaa\xa4\x2b\x60\x35\x84\x1a\xc4\x01\x60\x02\x40\x08\x34\x23\x1a\x91\xc3\xd9\xb4\x1c\x71\x10\x4a\x1b\x6e\x05\xc9\xe8\x38\xc8\xc4\xf0\x35\x81\x8e\x3d\xb3\x9c\xab\x7b\x66\x6d\x98\x37\x41\x4c\x74\xd8\xae\xb1\xc6\xe3\xf1\x65\xf1\xc0\x35\xb7\x3e\x65\xbb\xd6\x16\x5f\xd6\x1b\x2f\xbd\x76\xf8\x9a\x5b\xaf\x09\x74\x57\xf9\x26\xce\xdf\x30\xab\x6f\x9d\x6d\xe6\xbd\xc4\xd2\x0d\xb3\x7a\xd7\xb2\xb3\x1f\xef\xb6\x5e\x63\x5c\x13\xb8\x76\xf8\xda\xe1\x6b\x4b\xdb\x6b\xdc\x7d\xa7\xe1\x25\x7d\xde\x44\x97\xed\x1a\x5b\xbc\x77\x99\x71\xe2\xd6\x6b\x4b\xbb\x1e\x9b\x6d\x5d\x37\x6d\xd6\x06\x78\x79\xf8\xda\x40\x7b\xc2\x3d\x71\xfe\xc6\x59\x93\x57\x3b\x67\xff\xa8\xc3\x76\xad\x35\xbe\x4c\x8e\xeb\x17\x62\x97\xfe\x8b\xbd\xcb\xf5\x5f\xbc\x76\xf8\xda\x40\xd7\xde\x39\x8e\xd5\x3d\xb3\x36\x9e\xdc\x2b\xd4\x1c\xbc\x6a\xd6\xc6\xc1\x49\xfe\xaa\x6e\xe3\x92\x65\xc5\x1f\x0c\xb4\xef\x99\x65\x5d\x47\x4a\x53\xcf\xb2\xce\x7a\xb4\xab\x58\xde\xe2\xa9\xae\x6a\xef\x94\x25\x1b\x0b\xbc\x1d\x05\xcc\x8c\x09\x68\x2e\x5a\x80\x16\xa3\xa5\x68\x05\xba\x08\xdd\x8e\x10\xe8\xd5\x65\xb8\x7e\x16\x9c\x39\x95\xa2\x87\xa2\x2a\xeb\xdd\x21\x2d\x14\x1c\x39\x15\x59\x31\x82\x8e\xb3\x29\xfd\x24\x96\x44\x46\x30\x7c\x3c\x0b\x2e\x9b\x84\xe1\xa0\x19\xd5\xaf\x52\x8d\xd5\x30\x35\x49\x49\x0a\xc4\x39\x0a\x24\x42\x21\x24\x55\x02\x8a\x03\x89\xd1\x7f\xc2\x40\x84\x29\xcc\x8b\x18\xf7\xa6\x92\xc6\xc7\x05\x9c\xb1\x94\xad\xa4\x15\xce\xf0\x6e\x51\x39\x2a\x59\x05\xa9\xa4\x9b\xc3\x3b\x41\x12\x84\xaa\x4a\xa6\x9b\xec\xea\x9a\xe1\x21\x83\x04\xdd\xe7\xde\xc6\x72\xdd\xd8\xb4\xc4\xa4\x04\x30\x06\xca\x2b\x79\x5c\x16\x12\xe8\xb8\xb5\xb1\xe6\x54\x6c\xe9\xb4\x9a\x4b\x48\x12\x13\x25\x7e\xa2\x24\xdd\x6e\x3b\x97\x22\xed\x2f\x13\x8c\x4d\x0e\x04\xbc\x12\x4b\x02\x11\x16\x6a\x63\x3c\x87\x9f\x6a\xfb\xfe\xc1\x2f\xf0\x23\xf9\x5e\xf2\x8d\x25\x0f\x9f\xfa\x87\x25\xd5\xaf\x6a\x09\xdc\xa2\x1d\xb8\x39\x5b\xb6\x7d\x57\x63\x78\xe6\xf4\x4f\xdb\x4c\x16\x13\xe9\x0f\x93\x3d\x7b\x26\x2d\xbe\x6c\x96\x23\x18\xb7\xc0\x55\xa3\x07\xd8\x7c\x82\xb1\x53\x40\x00\xe5\x58\x59\x81\x13\x18\x5a\xa0\x89\x14\xe0\x05\x82\x31\x99\x85\x52\x2a\x83\x97\x4e\x5b\xec\xc0\x24\x26\xe7\x7a\x1e\xf1\x05\x2e\x32\x43\x04\x5b\x4d\x80\x39\xb0\x50\x0c\x43\x72\x34\x87\x69\xc2\xe9\x8c\xe2\x28\x49\x58\x00\x6c\x6e\x9c\x6c\xa0\x92\x33\xfc\x74\x1a\x43\x1d\xec\x73\xd8\x25\x87\x8d\x90\x1c\x5e\x82\x20\x49\xd6\x86\x77\xfd\xad\x22\x7f\xdd\x3f\x48\xd3\x7b\xf9\x6c\x10\x5f\x1e\xcc\xff\x23\x78\x66\x07\xd1\xf4\x18\x6c\x39\xc0\xd9\x87\x3b\x4f\x2a\xb1\x4d\x4b\x30\x66\x93\xd5\xe1\xc2\xf1\xba\xd2\x18\xc3\xb9\x69\x32\x77\xf0\x57\xff\xa5\xff\x65\x07\x4c\x66\xcd\x40\x53\x31\x16\x72\xcf\x9d\xb9\xd2\xad\x0d\x1a\xf1\xc6\x63\xd8\x0b\x0a\x52\xd1\x24\x34\x07\x2d\x45\xeb\xd1\xf7\xd0\x35\xe8\x2e\xf4\x28\x1a\x39\x3c\xd3\x73\x98\x1c\x96\x3a\x1a\xb2\x5c\xd7\x1f\x82\x10\x00\xf7\x11\x1a\xbd\x02\x1e\x3b\xf7\x0d\xf9\xff\xaf\xaf\xe7\x0b\xc0\x62\x61\x0e\x42\x9d\x83\x83\x9d\x39\x7d\x43\xed\x6b\x9c\x78\xf5\x8a\xd1\xe1\xce\xc1\xfa\x32\x3c\x5c\x36\xe4\xbf\xd6\x5f\x96\x0f\x19\x40\x47\x5f\xb9\x01\xf4\xff\x76\x7e\x68\xb8\xac\x3e\x9f\x23\x73\x83\x9d\x47\xd8\x95\x6f\x8f\x9c\x33\x21\x8f\x56\x5c\x3d\xd8\x49\xa3\xb2\xfa\x32\xff\xb5\xfe\xa1\xb2\x83\xb9\xc3\xb7\x01\x7b\xa2\xa4\x76\xc2\xa3\xff\xcb\x05\xb0\x13\x50\x7d\xd9\xb0\x86\x90\x50\xf0\xa1\xa7\x51\x71\xed\xa6\x0d\x4d\x47\x8b\xd1\x2a\x74\x9e\xc1\x20\xf8\x63\xf4\x33\xf4\x32\x7a\x1b\x7d\x8c\x0e\x81\x03\x82\x50\x03\x6d\x27\x98\xf1\x3b\x4c\x92\x58\xa8\x77\xee\x7f\xcc\x13\xff\xe3\xfb\xfc\x36\xed\xe3\x58\x20\x9f\xff\xd7\xe7\xfd\xff\xb3\x7c\x94\xe1\xac\x72\xb0\xe0\xa5\x32\x72\x84\x76\xe0\xeb\x37\xb9\x6f\x7b\xe1\x91\x0d\x46\xe3\x98\x89\xbe\xf5\x5d\x80\xfe\xf7\x5f\xa2\x91\xec\xfd\xd2\x98\xe7\xa2\x73\x5e\x59\x1b\x07\x39\xfb\xd9\x37\x25\x1f\xf8\x06\x08\xa4\x13\x27\x0f\xb2\x87\x81\x53\xf0\xff\x70\xdb\xe8\xff\x70\xed\x51\x30\x4c\x08\xa3\xf6\x43\x4e\x72\x84\x1a\x42\x41\xa4\x20\x64\x3e\xd6\xc9\x0e\xe4\xb4\x3a\xe6\x2c\x24\x89\xc2\x58\x94\x29\xb9\x5b\x7b\xb3\xe8\x5b\xa7\xbd\xe9\xf7\x97\x4e\xf7\xef\x87\xd5\xfb\xfd\xfd\x7e\xbf\x36\x5c\x70\xb0\x7b\x53\x7b\x73\xf4\x79\xc3\xb5\x2e\xa7\xe5\x0c\xd7\xba\x7a\x88\xe9\x17\xf8\xf7\xef\xd7\x6f\x78\xa7\xe0\x5b\x47\x15\xb9\x97\x73\xc8\x81\x4a\x8d\x55\xa3\x19\x08\x81\x50\xb0\x7b\x32\x69\xc3\x2e\x81\x02\x57\x0c\x14\x87\x50\x2a\x49\xba\xdc\x82\xc1\x17\x13\x8d\xd0\xd1\x48\x26\xdd\x8a\xe3\xe3\xae\x76\x0b\x2c\xc4\x0d\x6e\x98\x82\x3a\xd5\x0a\x84\x4d\x9e\xdb\xd2\xb7\xa5\x59\x9e\xdb\x32\x75\x73\xb3\x76\xcf\xcc\xa9\x7d\x3b\x26\x1a\x1b\xb8\xf8\x1c\x70\x3d\x16\x69\xeb\xac\xec\xfe\xb8\xad\x33\xdf\xfb\xe8\xea\xbb\x5e\x81\xc9\x2d\x73\xe5\xe6\xcd\x53\xf5\xed\x16\x38\x75\xea\xcc\x89\x3b\xfa\xf4\x0d\x59\xd6\xbc\x72\xda\xba\x1b\x7b\xf4\xed\x0d\xf9\x57\xfb\xcf\x59\x75\x63\x6f\xff\xfa\x55\x37\xd5\x3c\xa3\xbd\xb7\x2e\xd1\x52\x6a\x9d\x3f\x6f\xd7\xec\x57\x7f\x74\xce\xab\xd3\x56\x36\xf7\xde\xb0\x6e\xda\xca\xe6\x9e\x1b\xd7\x2d\x5b\xdf\xdf\x7b\xe3\xaa\x73\xfa\x7b\x6f\x5a\x85\x00\xb5\x1f\x42\x78\x84\x46\x46\x6c\xa8\x40\x33\xbc\x58\x0c\x76\x2f\x14\x3e\x19\x00\x3c\xb2\x76\x71\x35\x8e\x79\x47\xbc\x31\x5c\xbd\x78\xed\xac\xab\xef\xb9\x7a\x16\xf1\xc9\xe5\xcf\xc6\x47\xff\xcf\xf0\x04\xcb\xc4\x9f\xbd\x3c\xf7\xaf\x9b\x6e\xfa\xd7\x11\x4c\x91\xb1\xb8\xa3\x20\x42\x14\x70\x94\x52\x0d\x76\xfd\x25\x16\x90\x54\x8b\x58\x21\xc6\x24\x6a\x00\x88\x1c\xce\xe5\x73\xed\xf8\xa7\xf9\x89\xf9\x89\xd4\x81\x58\x30\xdf\xee\xef\xf4\xe7\xdb\x83\xb1\x84\x8c\x47\xc4\x2a\x11\x8f\xc8\x89\x45\xb0\x08\x6f\x79\x6f\x8d\xa6\x69\x38\x8f\xa2\xcd\x9c\x96\x73\x3a\x21\xc7\x35\x47\x09\x54\xd6\xc9\x02\x32\x99\x0e\x21\xb6\xb3\x00\x95\x87\x0e\x21\x53\x81\xc7\xe4\x48\x54\x74\x27\x42\x54\xdc\x28\x07\x05\xc5\xbd\x32\x96\xd7\xcb\x45\xd1\x11\x25\x2e\x2b\xc5\x44\xb1\x80\x71\x63\x93\x4d\x4a\xc6\xe0\x4b\x05\x00\x1b\x24\x42\xed\x70\xa5\x76\xba\x76\x3a\xf5\xbb\x71\x99\xaa\x42\x7a\xaf\x36\x49\x9b\x44\x7d\x29\x87\xb5\xf6\x92\xf6\x12\xad\x9d\x24\x30\x55\x4c\x86\xe5\xca\x28\x3c\x50\x19\x85\x11\x29\x2b\xc1\x48\xb4\x12\x1e\x88\x55\x0c\x8d\x40\xe3\xee\xd5\x7b\xf6\xec\xc9\x5f\x32\x96\xda\x70\x07\x58\x76\xaf\x7e\xf2\xc9\x27\xf3\x2d\xda\x50\xac\xd5\xb9\x8f\x65\xf7\x61\x8c\xb1\xbe\x77\xb6\xc6\x60\x58\x6e\x77\xfe\x14\x2e\x93\xdb\x9d\x23\x16\xcb\x88\xb3\x5d\xd6\x56\xff\xd4\xd9\x5e\x58\x53\xd1\x4c\x88\xc2\x88\x40\x66\x14\x44\x32\x4a\xa0\x0e\x84\x20\xec\x0e\x13\x11\x9a\x09\xcb\x44\x32\xab\xa6\x70\x38\x82\x33\x69\x54\x68\x91\x4c\x58\x10\xe3\xe1\x64\x26\x1d\x0d\x67\xc2\xba\xad\x1e\x0d\xc7\xc3\x49\x83\xe2\xc8\x68\xb0\x44\x34\xcc\xd4\x6b\x00\x87\x46\xe7\xaf\xa6\xe1\x5a\xd7\x9d\x6d\xe7\x70\x6f\x9d\xaa\xed\xfd\x7d\x1e\xa8\x97\x2e\x7e\xf1\x34\x9c\x3f\x73\xdd\xc1\x2c\x94\xbd\xf8\x4b\xed\xb7\x50\x32\x6d\xc1\x53\xda\xa8\xf6\x4f\x3c\x30\xe7\xc2\xb3\xdb\xee\x5b\x7b\x56\xdd\x49\x6b\x73\x13\xf3\x37\x91\x7b\xb6\x68\xbf\x5d\x3e\xff\x99\xfc\xa3\xed\xaa\xf6\x22\x98\x5e\x7f\x05\xf8\x0b\xff\x7c\x11\x17\x58\xb5\x31\x79\xd7\x43\x4f\xf5\x4c\xbd\xec\x75\x7f\xd7\xd6\x05\x0f\x0f\x84\xee\xdc\x38\x65\xf3\xcc\x46\x6f\xf1\x1d\x8e\xcd\x67\x06\x50\x1c\x55\xa1\x0e\x34\xc9\xe0\xf9\x39\x66\x34\xe4\x8d\xd9\xa7\x4c\x5a\x31\x26\x1a\x88\x68\x26\x95\x74\x0b\xc5\x1d\x15\x91\x33\xe1\x6c\xe6\x08\xba\x8f\x1a\x65\x81\x48\x4a\xd1\x56\x20\xc2\xee\xf0\xf8\x95\xb0\x57\xb5\x4b\x60\xeb\xd9\xc3\x97\xae\x54\x7a\x67\x4e\xbd\xff\xf6\xf5\xdf\xd9\xfb\xe4\x16\x6c\xe9\x9e\x0c\x37\xc0\x55\xdb\x72\xbb\x6f\xfe\xee\x8b\xad\x17\x5b\x7b\xea\xd6\x58\x35\x72\xe2\x0a\x68\xd3\x7e\x7e\xf4\x2a\x98\x76\xf9\xe8\x87\xeb\xd6\xdc\x5c\x91\x5e\xdd\x30\xbd\x82\xd3\x9e\x7e\x6c\xfe\xa0\xf6\x93\x37\xd6\x2c\x0b\xf5\x4d\xb0\x08\xe7\xff\xe4\xbe\xed\xdf\xdb\xfd\xb3\x48\x19\x9c\xb9\xa9\xbe\x13\x2c\x53\xc7\x6c\x2d\x66\x0c\xe7\x5e\x41\x6d\xe3\x58\x0b\x8c\x39\x58\x69\xcc\xff\x4c\xd1\x35\x73\x18\x87\x50\xa4\x0a\x28\x0a\x46\x1f\x52\x03\x1c\x65\xb8\xcf\x64\x51\x2a\x89\xe8\xc4\xa5\x2f\x5c\x7a\xe9\x0b\xf9\x4b\x76\x2d\xf3\xf9\x96\x4d\xed\x08\x06\xaf\xed\x73\x0f\x08\xa1\x73\x26\x2d\x23\x5e\x79\x70\xeb\x79\x0f\x3e\x78\xde\xd6\x07\xaf\xd6\xfe\xf3\x84\x36\xc5\xf6\xf4\xf9\x1b\x7f\x5a\xf2\x2e\x5c\x30\x7d\xd0\x2e\x82\x1f\x83\xf5\xf1\x27\xc0\x4a\x06\xf5\xfb\x2f\x3d\xf8\xd4\x2b\xbb\xe8\x8a\xe0\x35\x7d\x53\xdb\x83\xa6\xb0\xa9\xb9\x87\x78\x7b\xeb\x83\x0f\x6e\x3d\xef\x81\x07\xce\x7b\x52\xfb\xaf\xf6\xf3\x6d\x0f\x5c\x7b\xd6\x42\xd8\x73\x53\x2d\x86\x6b\x1e\x07\x93\xf6\x1f\x74\x94\xed\x68\x42\x3e\xd4\x85\xa6\x16\x91\x00\xdc\x82\x58\x98\x1c\x93\x15\x23\x7c\x39\x2b\xd7\x40\xf6\xc8\x44\x58\xcb\x98\xe1\x11\x4f\x16\xdf\x13\x43\xe8\xd2\xc7\xc7\xe6\x97\x0b\x75\xa2\x1b\x87\x7f\x5c\x3b\xbc\x66\xcd\xb0\xe6\x3c\x6b\xa0\x7e\xb0\x24\x9d\x68\xde\x50\xe2\x49\xb5\x0c\x88\xc2\x00\x31\x5a\x78\x13\xf7\x09\x57\x2c\x5e\x76\xbd\x05\xe6\x5d\xfd\xea\xab\x57\x5f\xf9\x5b\xfc\x17\x33\x3f\xa5\x55\x7b\xbd\xf0\x82\x3e\xdf\xf9\xfc\x25\x97\x9c\x7a\xda\x25\x44\xf9\xf0\x9a\xb5\xd3\xfb\xd7\x68\xcf\xdf\xb9\xae\xb1\x56\x10\x3c\xa9\x96\xe6\x0d\x9e\x30\x85\xcf\x28\xbc\xcc\xeb\x26\x2c\xdc\xf0\x83\xa5\xa3\xaf\x5e\x75\xf5\xab\xbf\xb9\x52\x7b\x0a\xe2\xeb\xe1\x77\xeb\xef\xbe\x5b\x1b\x3e\xf5\x92\x4b\x9e\xdf\x79\x09\xa2\x91\xf3\xd0\x6c\xfa\x63\xea\x10\xb2\xa3\x00\xaa\x46\xcd\x68\x8a\x81\x9a\x44\x30\x71\x63\xf1\xb5\x15\xab\xa2\x0f\x14\x96\x70\x00\x91\x80\x36\xc8\xaa\x0a\x10\xac\x81\xac\x2b\x11\xbc\x5e\x03\x40\x13\x71\x85\x6f\x05\x29\x40\x01\x2f\xd2\x0c\x4b\x31\x32\x11\x57\x54\x22\xae\x26\x88\x1a\xa0\xb2\x62\x10\x44\xa2\xdb\x81\xb5\x85\xb1\x56\xa7\x95\x71\x98\x23\x78\x5a\xd5\x43\x57\xb4\x7d\xa7\x36\x48\x90\x4f\x71\x98\x31\x45\xa7\xff\x80\xce\x3d\x61\xab\xe3\x5d\x93\xae\x34\xbd\xfb\x2a\x73\xcf\x5f\x1b\xf2\x4a\xcd\x1f\xb5\x67\xf8\xbf\x08\xfd\x65\x9e\xba\x68\xad\xa7\x16\x5f\xf3\x3b\x97\x55\xb4\x97\xc5\x5a\xc2\x13\xad\x91\xbf\x43\xc3\x96\x9d\x6f\x6a\x8b\xae\x89\x0c\x4c\x68\xe6\x38\xb8\x2a\x98\xb5\x59\x15\x58\xa5\x5d\x26\x96\x12\x0d\x71\x5f\x7d\x6f\x6c\x21\x63\xc3\x8d\xda\x05\x0b\x27\x5f\xbe\x7c\xa6\xdb\x0d\xa7\x79\x9b\x39\x57\xdb\xb9\xb3\xf3\xef\x6b\xd7\x95\x46\x09\x92\xa1\x76\xc3\x2a\x58\xb1\xc7\x29\x8a\xc4\x03\x6d\xda\x0f\x1e\xb7\xc1\xa9\x41\x3f\x89\x05\xb1\xaa\x24\xab\x3d\xab\x5d\x15\x9f\x16\x15\x22\xa2\x68\x71\x11\x93\xe1\xf4\x67\x3e\x3c\x49\xfb\xbe\x30\x7b\xde\xf5\x8b\xba\xec\x76\x20\x7c\x0e\x47\x4b\xa1\x8d\xb4\x9b\x0a\x6d\x9e\x43\x25\xa8\xeb\x08\x5a\x04\x1f\x26\x12\x60\x90\xeb\x1f\x3e\x32\x3e\x70\x34\x3c\x16\x40\x3a\x46\x24\xc2\xb7\x82\xde\x3c\x24\x3e\x95\x14\x61\xdf\xe0\xf9\x83\x83\xe7\x6f\x27\xbe\x98\x87\x3d\xe6\x3c\x32\x7b\x30\x45\x18\x87\x34\x17\x3b\xb4\x7a\x78\xf5\x28\x5a\x3d\xbc\x7a\x88\x75\xed\x58\xe4\x5f\x2e\xdd\x76\x32\x81\x4e\xbe\x4d\x5a\xee\x5f\xb4\x03\xb6\xea\x17\x0d\xc2\x3e\x38\xcd\xc4\xf3\xa6\x7c\x49\x21\x8b\xb4\x1c\xeb\xca\xf5\xaf\x5e\xdd\x9f\x2b\x6c\x5d\x2c\xe4\x16\xed\x80\xdb\x07\xcf\x3b\x6f\x50\x5b\xb4\xa3\x10\x57\x6b\xd2\xbb\xdb\x14\x6a\x42\x13\xf4\xb6\x7e\xd8\x56\xfb\x9a\x02\x17\x70\x96\xc3\x45\x46\x2c\x89\x1f\x8b\x9b\x85\x23\xb2\x17\x8f\x30\xa1\x45\x3b\x4e\x58\xf4\x5c\x01\x15\x2f\xa7\x0b\xf0\xe5\x81\x42\x71\x4f\x1d\x27\x37\x19\x36\x8e\xe1\xdc\x8e\x45\xba\x10\xed\x7a\xf1\xdb\x0b\xdb\x23\x42\x14\x00\x68\x75\x51\xb4\x90\x51\x4d\xb0\xbd\x50\x01\xa3\x8f\x1b\x59\x04\x28\x74\x08\x51\xfb\x0c\xf9\x50\x4c\xff\x50\x03\x63\x58\x7f\x99\xb4\x81\x39\x9c\x56\x75\xc9\x0e\x6f\x0b\x7c\xc2\x74\x25\x14\xb7\xd4\x3e\xd9\xab\x25\xc1\x12\x2b\xd1\x46\x4a\x62\x16\xd0\x92\x5e\x99\x87\x5d\xef\x18\xdb\x67\xf5\x6d\x8e\x4f\xeb\x1b\xd9\xfb\x2c\xec\xe2\x65\xef\x3b\xb0\x6b\x7e\x5a\xe6\x2e\x91\x4b\xa2\xd1\x12\xf9\x12\x4e\x4e\xf3\x70\xc5\xe1\x4d\x8e\xe7\xb5\x1c\x9f\x96\xb5\x33\x8c\xcd\xb8\xbe\xc6\x8d\x2a\x51\xb7\xe1\x0b\x53\x04\x4d\x2a\xf4\xf2\xc5\x30\xec\xac\x9a\x56\xe4\xf0\xb8\xa3\x21\xe3\x28\x9f\x56\xe4\x98\x31\x9f\x78\xf8\x6a\xd2\xa0\xe7\x83\xf1\xae\x69\x4b\x03\x3f\xd7\x2e\xb8\xbe\xc2\x27\x52\xa1\xf3\x57\xfd\xf5\x5e\x9e\xe5\xfd\x43\xd1\x0f\xb5\x5f\x5d\x77\x75\x6d\xb4\x84\x09\x6c\xda\x06\xd2\x6f\x3c\x6c\x49\xf4\xf4\xb2\xad\xda\x03\xf7\xff\x7a\x58\x0a\x96\x07\xad\xa5\x17\xfc\xe8\x16\xa8\x5e\xea\xe6\x4b\x2b\x5f\x3c\x16\x7e\x7e\x62\x88\x5f\x17\x31\x57\x0a\xa5\x26\xdf\x52\xab\xef\x83\x32\xf7\x25\x15\xf6\x54\x49\xd4\x14\xde\x62\x8f\x02\x57\x23\xf5\x4c\xa9\x61\xe2\x81\x60\x85\x29\xde\xdd\x62\x2b\x5f\x70\xcc\x62\x10\x14\xb8\x6c\x69\x84\x78\x5d\x1b\x96\xc2\x5c\x98\x21\x98\x30\x07\x4a\x98\x0b\xab\xbc\x1a\x26\x91\xf6\x1b\x0f\x48\x1a\x55\xb5\x33\xa0\xbd\x0a\x35\x1e\xed\x3d\x38\x58\xb5\x33\x00\xd5\xe4\x6f\xf2\x3f\x0d\x6a\xdf\x09\x68\x1f\x07\xa0\x06\x4f\x0a\xc0\x2d\x01\xe0\x02\x08\x21\x0e\x21\xf4\x03\x33\x22\xcf\x42\x2c\x8a\x1b\x8c\xf6\xcd\x68\x32\x9a\x89\x4e\x46\xa7\xa0\x35\xe8\x3c\x74\x09\xba\x0c\xdd\x8c\xee\x43\x23\xe8\x77\x08\xc5\x55\xbd\x95\x46\x68\x37\x61\xf4\xd8\x71\x95\x48\x2b\xb2\x5e\xb7\x0c\x21\x48\x63\xe4\x01\x19\x90\x0c\x3f\x7f\x35\x9b\x54\x25\x46\xd7\x81\x15\x35\x9d\x4a\x02\x21\x31\x42\xd4\x38\x9e\x4a\x06\xe1\xc8\x89\x60\xd1\x71\x47\x51\xf5\x3e\xde\x0c\x3c\x23\x18\xcc\x48\xbc\xde\xe3\xab\xc7\xe6\x0a\x99\x42\x5c\x78\x03\x10\xfa\x69\x7d\x0c\xe4\xd3\x59\xfd\x73\x1a\xcb\xb5\x42\x52\xe4\x99\x3a\x23\x87\xf9\x4c\xb6\x18\x8c\x6f\xe0\x37\x1b\x5a\x9d\x7e\x00\x19\x8b\x14\x84\xd3\xe9\x04\xbb\xc5\xcc\xb2\x2c\xd8\xcd\x22\x54\x58\x6d\x76\x93\xd3\x64\x07\x8b\x95\x36\xb3\x56\xb3\xf9\xe0\x07\x82\x80\x59\xcc\x71\x98\x9d\xeb\xf5\x62\x93\x59\x92\xcc\x26\xf0\x3e\x51\x52\x62\xb5\x60\xb7\x1b\x5b\xac\x83\x92\x84\x6d\x76\xb7\xdb\x6e\x1b\x72\xbb\x31\x4b\x9b\x05\xc1\x4c\xb3\xb0\x4d\x7b\xdb\xed\xb6\x30\x4e\xec\x72\x61\x27\x63\x19\xe4\x79\xab\xc9\x85\x9d\x4e\xec\x32\x59\x4f\x76\xb9\xb0\xc0\x63\xa7\xd3\x6e\x32\xdb\xe0\xa2\xe7\x1c\x0e\x87\xc0\x02\xcb\x3a\x04\xc7\x29\x2c\xeb\x14\x9d\x60\xb3\x81\x53\x74\xbc\xc6\xba\xbc\x2e\xa0\x69\x1b\xb6\x98\xad\x26\x86\xc5\xe4\x92\x3b\xcf\x1e\xfd\xc8\xee\xf2\xcf\x1a\x7a\x06\x02\x5c\xa6\xe1\xec\x3b\x77\x7f\x8a\xad\x16\x96\xb5\xe4\xff\xf3\xa9\xc5\x9e\x7e\x15\xf7\x3a\x4d\x14\x65\x72\xd2\xf9\x27\xe1\x9f\x60\x61\xac\x66\xc6\x0e\xa7\xe7\xb6\x9a\xcd\x5b\x73\xe6\x89\x2f\xff\x9f\xd9\xf2\xc2\xcb\x66\x2d\x09\xff\xfc\xcf\x87\x56\xeb\x87\xff\xb1\x51\xa3\xff\xb6\xdb\xff\x3d\x6a\x0f\xbe\xff\x5f\xa7\x99\xf9\xef\xfb\xb4\x59\x13\xf1\x19\xda\xf9\xff\x65\xac\xae\xff\xc2\x16\x97\x75\xba\x56\xf5\x6f\x93\x95\xff\x37\xfc\x8e\xb7\x86\x34\xfa\x33\xb7\xfb\x33\x38\x60\xb6\xdb\xf3\x1c\x7e\x5f\xc3\x1f\x5b\x1c\xac\xf5\x63\xd0\xac\x2c\x1b\xd0\x84\x0f\xac\x4e\xa7\xf5\x03\xf8\xc0\xe6\x74\x6a\xa6\xbf\xdb\x5d\x2e\xfb\xda\xb3\xf1\x16\xc2\x61\x66\x28\x93\x2b\x7f\xe5\xd9\x77\x60\x97\x9d\xd8\x21\x59\x22\xda\x97\x23\xe2\x9d\x87\xf9\x06\x91\xc1\x61\xec\x33\x10\x48\x11\x0a\xc5\x54\xb7\x60\xcc\xd0\xb7\x80\xf8\xf5\x39\xd2\x00\xa7\x2e\x64\xd3\x59\xcc\xc3\x1f\xe1\xc6\xf5\x2f\x69\x37\x6b\x43\xda\xcd\x2f\xad\x87\x1b\xbf\x21\xbf\x17\x86\xe1\xe4\x97\xc6\xf2\x2f\x11\x68\xf6\xcc\x7b\x0a\xfe\x18\xf7\xcc\x1c\xbd\x67\x5c\x06\x2a\xc6\x65\xc8\x8a\x09\xe7\x4c\xc8\x15\x72\xb9\x09\xe7\x8c\x9b\xcf\xe5\x91\x17\x45\xd1\x20\x3a\x05\x9d\x85\xce\x43\xdf\x43\x08\x8e\x9f\xaf\x93\x18\x2e\x2c\x2b\x20\x1b\xce\xd6\x19\x2e\xcc\x81\xb1\x5a\x26\x89\x8c\x40\x33\xee\xc2\x9c\x39\x83\x0d\xde\x3e\x45\x36\x70\x8f\x24\xd1\x9d\x55\xb3\x6a\x02\xd4\x6c\x13\x4e\x1a\xf1\xf7\x62\x29\xd0\x8c\x08\x59\x95\x05\xa0\xa5\xac\x9a\x56\xb3\xaa\x9c\x91\x33\xb2\x22\x30\x84\x7e\xa9\xa2\x3f\x85\xa6\xe4\xa8\xfe\x4d\xa6\xa9\x27\xfc\x65\x87\x01\x94\x73\x65\x43\xfe\xf3\x61\x83\xc5\xa6\xfd\xd2\x06\xa7\x68\x43\x65\xf5\x79\x84\xb5\x70\xaa\xa9\xf1\x8a\x80\x93\xc5\x40\x77\xd4\x7e\xb7\xed\xad\x7b\xaf\x9b\xe7\xb0\x7b\x80\xb2\x90\xe6\xc1\x59\xac\x19\xa7\xd5\xee\x98\xc7\x6e\xb7\x06\xdd\x20\xd9\x5c\x66\x8c\x01\xdb\x54\xcd\x97\x9e\x95\xea\x81\x6d\x0e\x3b\xd0\x8c\x81\x50\x61\x83\x2d\xdf\xbb\x0a\x8b\x54\x5f\xca\x57\x1f\xc0\xeb\x3d\x67\xf5\xd5\xb2\x24\x79\xbe\x31\xc5\x36\x06\xc3\x5c\xe6\xef\xd6\x2e\x2c\xb5\x41\x83\xed\x80\x8b\x44\xf5\x65\x30\x7c\x00\xe1\x19\xde\x00\x53\x27\x06\x00\x03\xc8\x65\x61\x4f\x93\x76\x80\xb1\x01\x69\xf1\x96\x2d\xad\x36\x3b\x30\x9e\xb5\xfa\xc2\xad\x03\x37\x24\xcb\x1c\xee\x1a\x1a\x13\x54\x60\xf3\x84\xdd\x9a\xcf\xf3\xdd\xb2\xb9\xc4\xa6\x8a\xf9\x4c\x9c\x28\x23\x49\x00\x0c\x22\x0b\x90\x5f\x9e\xf5\x01\x47\x75\x9d\x31\x7b\x55\xbd\xd5\xe3\x07\x40\x47\xb5\xb3\xc2\x3b\x9a\xf9\xed\xde\x0d\xef\x4e\xf1\x29\x3e\xab\x66\x33\x29\x29\x00\x12\x9f\xe2\x0d\x48\x3f\x82\x76\x40\x34\x9d\x80\x4c\x02\x14\x22\x6a\xe8\x76\x51\x45\x56\x88\x54\xe6\x1b\x6b\x7a\xf9\xc4\xdd\xb7\xe4\x18\x02\x93\x04\x50\x44\xee\x96\xdd\x13\xb5\xdf\xcd\x3f\x85\xc2\x98\x04\x0c\x34\xbe\x6c\xed\x65\x98\x02\x92\xc4\x98\x3a\x65\xfe\xb7\xa8\x36\x22\xb7\x32\xbf\x12\xde\x11\xbc\x4e\x93\x87\x88\x98\x35\x1f\xbe\x6a\xe5\x4a\xad\x57\xf0\xba\x09\xc6\x8c\xa9\x90\x19\x87\xf3\x6f\x9b\x83\xb4\xdb\xed\x15\xe0\x91\x95\xc7\xd7\xc3\x49\xdf\xae\x1e\xe2\xee\x70\x26\xaa\xb6\xe2\x26\x10\xa5\x00\x0e\x42\x54\xcf\x13\x85\xca\x30\x20\xdc\xa2\xb2\x22\xd7\x80\x91\xe7\x89\x6f\xac\x04\xa8\x86\x92\x29\x4b\x29\x0b\x05\x18\x48\x4c\x31\xc4\xca\x3e\x88\x76\x8f\x3c\xd3\xa5\xbd\xd7\xbb\x94\xb4\x11\x18\x03\x49\x5b\x57\xf4\x69\x7f\xee\x7e\xf2\xe9\x6f\x51\x0d\xef\xaf\x58\x71\x2b\xc3\x9b\x48\x9a\x64\xcc\xe4\xad\x2b\x56\x00\x07\xde\x95\x2b\x6f\x61\x78\x92\x20\x69\xab\xed\x96\x95\x2b\xb5\x4f\xb4\x77\xc6\x7c\x64\xc6\xcb\x5f\x6f\xf8\x02\x7f\xdb\x1a\xc8\xa4\x92\x05\x9e\x6e\x45\x8e\x86\xdd\x29\x0e\xa2\x9c\xfe\xe5\xba\x05\x86\xfe\x66\x99\x43\x30\x69\xd1\x45\x7d\x15\x5d\xd3\x7b\xdb\x6a\x07\xb4\xcb\x16\x02\xb5\x7e\x43\x3a\x58\xdf\x1a\xfc\x76\x02\xde\xe5\x90\x72\x03\x33\x36\xf8\xf8\x95\xf9\xd7\xc0\x03\x36\x57\x78\x60\x5e\xd0\x71\x22\x99\x2a\x50\xf2\x5b\xf6\x3c\x5c\x38\xa3\x4a\x40\x16\xdc\xa5\x84\x6f\x14\x81\xcc\x8d\xa2\x91\x1c\xe4\xb4\xfe\xe1\xd5\xab\x87\x57\x7f\x8b\x72\xc3\x88\x36\x32\xa2\xdf\x92\x5b\xad\xdf\x82\x90\xf9\x70\x59\xc7\xe6\x65\xf4\xf2\xaa\xa8\xd7\x40\x59\xcf\x44\xdd\x54\x26\x5a\x5a\xdc\xbb\xbf\x59\x86\xa8\x3b\x9a\x09\x73\x60\x44\x08\x1b\x5e\xd0\x59\x3e\x93\x72\xa7\x92\x22\x2e\xaa\xd1\x38\x97\x03\x64\xfc\x11\xcd\x5f\x2b\x5d\x2e\xa7\x21\x7c\xc9\x4a\xd3\xe5\x7f\xbe\xdc\xe4\x3e\x25\x37\x5d\x8c\x3c\x61\x70\xbd\x91\xb9\x71\xff\xc1\x37\x49\x9c\xcb\x1d\x40\xf8\x37\xda\xed\xbe\x92\x93\xce\x38\xe3\xa4\x12\x5f\x1b\x4c\xcd\xe5\xbc\x9a\xd7\xe0\x67\x3c\xec\xf3\x3a\xee\x5d\x35\xa0\x3e\xc3\x9b\xed\x5b\x8d\x13\xee\x31\xd6\xc8\xc3\xc4\x0d\x6a\x16\x92\x6a\xd6\xa9\x14\x90\xd5\x44\xa7\x81\xba\xa2\x24\xd5\x6c\x5a\x49\x80\x7e\x44\x30\x8e\x7c\x73\xe3\xfc\x40\x30\xb8\x23\xef\xdc\xa1\x1b\x06\x3b\xee\x74\xc2\x43\x41\x7e\xdb\x36\x67\x56\x70\x53\xdc\xa9\xa7\x72\x94\xdb\xf5\xa4\x4f\x98\x33\xc7\x95\x95\x31\x9f\x4e\xf3\x98\x17\xbe\x4d\xef\x94\x30\x89\xf9\x7d\xa2\x09\x9b\xef\x32\xe6\x8d\xef\x72\xe4\x27\x79\x6e\x81\x6b\x6f\x71\xd3\x1c\x97\x71\x6f\xd6\x9e\xde\xec\xce\x38\x1d\x57\x0a\x8b\x46\x17\xf1\x38\x96\x11\x1a\xae\x6c\x10\x32\x2e\xee\x04\x6d\x3a\xf5\x6d\xbf\xd3\x63\xe7\x86\xa8\xb1\x5a\x33\xd0\x30\x53\xc9\x6f\x1e\x0a\x0d\x16\x62\xcd\xd8\x12\xa7\xeb\xd5\xc2\x9a\xb5\xcf\xc1\x6c\xfe\x56\xe3\x18\x91\x1b\xbb\x17\x72\xe9\x3e\x6c\x12\xf3\x23\xba\xfc\x60\x99\x0f\x16\xf3\x09\xde\xbf\x8a\xa6\xa0\x05\xdf\x52\xb2\x56\x08\x42\x00\x1c\x60\x30\x1a\xd1\x46\xf8\x4a\x58\x64\x08\x83\xb7\x08\xda\x40\x91\xb3\x6d\x90\x15\x25\x48\x80\xca\x17\xae\xd5\x4f\x2a\xdf\xfc\xf2\x87\x4c\x5e\x6b\xca\x4a\x98\x1e\x79\xc4\x44\x58\x53\x56\xaf\xe9\xaf\x2c\x4b\x92\x2c\xfb\xd7\x63\x8f\x6b\xe7\xd8\x1d\xf8\x62\x2c\xda\xdb\x8a\xfb\x6f\x55\x23\x56\xc2\x24\x9b\xbc\xd6\x7f\xfd\xcb\xea\x35\xc9\x26\xc2\x0a\xd5\x3c\xcf\xf3\xda\xab\xc7\x1e\xcf\xd3\x58\xb4\x13\xfa\xa3\x2d\x58\xb4\x8f\xfe\xdc\xee\xc0\x08\x90\x72\xe8\x1a\xea\x0d\x1a\x19\x1e\xba\x6e\x3a\x4a\xe3\x02\xb1\x8f\x05\x94\xb0\xe8\xd5\x75\x27\x55\x3e\xcc\xb8\xce\xb0\x10\x49\x80\x32\x7e\xba\x8f\x7a\xe3\xb4\xef\x74\xfc\xea\xb6\x9a\xfe\x01\x7f\xc7\xf2\x53\xd7\x0d\xcd\xf1\x81\xcf\x3b\x77\xe3\xa6\xe9\x77\x9f\xb3\xf3\xb6\x57\x1e\x7a\xe0\xa9\x46\xa6\xa4\xab\xa9\xc3\x15\x6c\x4c\x66\xda\x7f\x7b\x5b\x2b\x7e\xf6\x39\xe9\x42\xed\xb3\x5b\xbd\xd5\xb5\x5c\x66\xed\xa5\x7f\x01\x06\xce\x7c\xf9\x8f\xda\x35\xda\xc7\xcf\x0d\xdd\xfd\xe1\x64\x28\xdb\x3b\xf2\x9f\x57\x47\x6e\x39\x0f\x48\x9b\x12\x5a\x3a\x63\xce\xfc\x53\x16\xfc\xf4\xf5\xe2\x9a\x3e\x53\xe8\xd7\x68\x64\x41\x2c\x72\x21\x37\x2a\x41\xd5\x08\xf1\xc0\xc5\x29\x55\x31\x43\x7c\x6c\xc2\xd9\x0c\x12\x47\xc5\x81\xa3\x38\xa1\x48\x2a\xa6\x9b\x24\x05\x13\xfa\x0f\x78\x81\xf6\x80\xf6\xf0\xcf\x7f\x4e\xa4\xf0\x02\xed\x5f\xda\x03\x53\xc1\xa9\x7d\xa2\x7d\xf2\x7d\x98\x96\xbf\x83\x7c\xf1\xe7\xda\xc3\x60\xcf\xdf\x41\xa4\x22\xa3\x2f\xba\xab\xdc\xa3\x2f\x46\x22\x44\xca\x5d\xe5\x26\x52\x11\x58\xa5\x9d\x09\x4b\xdf\x8e\x6d\xdb\x36\xfa\x26\xec\x7a\xe8\xed\xef\x3e\xf2\xc8\x23\x8b\xde\x86\xa5\xda\x99\xda\xc7\xdb\x00\xc7\x1e\x82\x5d\xda\x75\x95\xf9\x3f\x97\x4b\xf9\x3f\xdb\xed\x38\x22\x95\xe3\x48\xb9\x84\x23\x76\x7b\xfe\xcf\xd2\x18\x5e\x2b\x32\x21\x6a\x03\x8a\xa2\x39\x85\x36\x69\xcc\xda\x45\xc3\x95\xd8\x58\xe1\x38\x0c\xe0\x11\x4b\x19\xeb\x1c\x34\x18\xc6\x73\x02\x94\xc3\x78\xe1\x01\x2a\x55\x9c\xc5\x63\xc6\x7c\xc0\xa2\x91\x02\xab\x96\x69\xd5\x45\x1f\xdc\x45\x3a\x88\x83\x93\x00\x53\xf7\x7c\x70\xe6\x42\xdb\xee\xb3\x17\x4f\x9d\x02\xca\x83\x77\x82\xe7\x76\x38\xf0\xeb\x1f\x6e\xb9\x68\xa9\xb3\xcd\xd6\x35\x55\x9d\x3a\x35\x53\x35\xa3\xa3\xa3\x67\xc6\x9a\x8e\x8d\x77\xfd\x70\xf3\xa5\x27\x2f\xea\xec\x4b\xf7\xf7\x36\x54\x4e\xef\xe8\xec\x19\x58\xd5\xb6\xe9\x1e\x3c\x9a\xf8\xe5\xa6\xdd\xef\x81\xe5\xef\x77\x9c\xf9\xd3\xac\x52\xb9\xee\xb6\xc6\xeb\x9f\xb8\x55\xfb\xe0\x76\xda\xa3\x7d\xb2\x69\xe7\x29\x42\x0f\xdb\xd1\x95\xcd\x74\x57\x74\x0f\x0c\x74\x57\x5c\xba\x7e\xe3\xce\xef\x9c\xde\xde\x99\x6a\x98\x50\x38\x70\xc9\xd1\xf1\x07\x05\xec\x4d\x05\xd5\x20\xd5\xe0\xe4\x3c\x2a\x68\x20\x16\x62\xa4\x6c\x52\x52\x41\x95\xd3\xaa\x42\x3b\x51\x48\x55\xe8\x88\xc2\xb8\x42\x59\x83\x5b\x96\x92\xb2\x4e\x85\x11\x05\xfc\xc2\xf1\xae\xff\x78\x44\x3b\xff\xde\xa7\x07\xee\x19\x78\xfa\xe0\xa7\x4f\xfb\xfd\x4f\xcf\xc7\x9d\xb0\xa5\x70\xe0\x85\x22\x55\x2c\x71\xea\xd3\xf3\xe7\x3f\xed\xa7\xd1\x09\x3c\x85\xd9\xf9\xfa\x4d\x07\x3f\x35\x6e\xb8\x57\x3b\x3f\xff\x94\x71\x00\xe4\xbf\x14\x6e\x36\x3d\x7d\x6f\xe1\x71\xc6\x7c\x4d\x88\xde\x47\xbd\x8e\xc2\x46\x8c\xd6\x98\x83\x93\x2b\xa6\xba\x69\xe4\x16\x02\x38\xd4\x8a\x33\x69\xa4\x64\x44\xd2\x45\xef\xbb\xe8\xef\xda\x88\x36\xac\x8d\xfc\xfd\xa2\xa7\xa1\xff\xa5\xb7\xb4\xb7\x8a\xbc\xb6\x4b\xb4\xb7\xde\x7a\x09\xfa\x9f\xc6\xb9\xfb\xf5\x93\x17\xfd\x1d\xda\xef\x7f\x0d\xd6\x7d\x12\xdc\x5f\xad\x0d\xbf\xbb\xbd\x40\x63\xbb\xfd\x5d\x18\xaa\xde\x1f\xfc\x44\xbb\x04\x21\x40\xfc\x21\x44\x7f\x44\x23\x74\x0a\x42\x7c\xd6\xa5\x26\xeb\x04\x86\x25\x0d\x67\x12\x23\x80\x1d\x12\x7a\xf7\x44\xd4\x80\x1a\x80\x20\x64\x0d\x6f\x20\x5d\x61\xd4\x4f\x1a\x09\xd6\x88\x8a\x2f\x04\xbb\x27\xc8\x1a\x90\x53\x62\x5d\xc0\x24\xb9\x8a\xbe\xe5\xbc\xe9\x0f\xcf\x52\x60\x2a\x6b\xaf\x0f\x53\x3d\x93\x93\xcb\xa6\xb6\x3a\x9d\x8a\xdf\xe1\xb3\xb3\x96\xf2\xea\x0a\xd6\xbe\x4c\x99\x26\xf0\xa0\xb8\x85\x5b\x87\xc3\x0a\x41\x8a\xd3\xfd\xfe\xa5\x55\x03\x3c\x1f\x8c\x08\x35\xe1\x79\x33\x26\x89\xee\xe6\x1e\x0f\x19\xaa\xa8\x2b\x67\xed\x2c\x63\x29\xab\x9e\x5e\xd7\x5d\x59\xeb\xe7\x81\xf8\xb3\x76\xe6\xa1\xbd\xda\x43\xff\xbc\x00\x5f\xfd\x06\x6c\xda\x06\xd8\x94\x5a\xb2\xfe\xda\xab\xee\x9c\x94\x54\x9c\x41\xce\x99\xda\xb1\xf6\xd4\x40\x69\x49\x5d\xd8\x4b\xd3\xeb\xb8\x89\x5e\x5f\xed\xaa\x50\xf0\xd1\x87\x13\x6b\x22\xe1\xf8\x24\x8e\x5b\xc7\x4e\x2e\x2d\xad\xbf\x61\x6f\x7b\x75\x50\x08\x73\xce\xcc\x96\xf5\x5b\x56\x2f\x3d\xa9\x85\xe3\xec\x44\x69\xa4\x33\xd9\xdf\xbb\x64\xd9\xf6\x49\x5a\x5e\x3b\xf5\xdd\x2b\xbf\x80\x81\x82\xde\x63\xb4\x35\x1b\xf2\xa1\x32\xd4\x8f\x16\xa1\xd3\xd1\x46\x74\x11\xba\x0e\x21\xca\x2d\xc7\x14\x55\x94\x54\x51\x62\x44\x60\x44\x89\x91\x9d\xaa\x44\x33\x12\xed\x16\x40\xa2\x49\x26\x93\x55\x95\xac\x2a\x65\x09\x46\x14\x18\x89\x66\x14\xfd\x5c\x44\x51\x65\x85\x91\x15\xa3\x59\xea\x67\x55\x25\x9b\x94\x18\xfd\x31\xe0\xa6\x8b\x97\x29\xd9\x18\x72\x32\x4a\xb6\xe0\x7b\xa9\xca\x8a\xaa\xdf\x62\xdc\xa5\x37\x05\x34\x2e\x18\x86\x2c\x04\xc7\x1c\xe5\x06\x4f\xac\x78\x45\xbb\x79\x45\x63\x69\x55\xc7\x95\x6f\x72\x1d\xf9\xbf\x9e\x24\xfa\x1a\x4e\x3e\xb9\x21\xc0\x0f\x44\x29\x53\xe3\x0a\xed\xe6\x57\xea\x3b\xb8\x37\xaf\xec\xa8\xda\xf4\x1e\xcb\xfe\x23\xd8\xb5\xb7\x61\x7e\x6d\x7a\x61\xba\x76\x7e\xc3\xde\xae\xe0\x3f\x58\xf6\xbd\x70\xe7\xde\xa6\xb9\xb5\x55\xa7\x57\xd5\xce\x6d\xda\xdb\xa9\x55\x74\xd4\xeb\x97\xcb\xd1\x86\x15\x30\x44\x3a\x4f\x6e\xf0\x89\x27\xc5\xa2\x03\x7c\xa0\x41\x6c\x88\xca\xfa\x8f\xd4\x77\xfc\x06\x86\xc0\xfe\xbd\xfd\xda\x2f\xb4\x3b\xb5\x5f\xec\xff\xde\xf7\xf6\x43\x33\xcc\x87\xe6\xfd\x0f\x9e\xe0\x03\x59\xd2\x49\xbf\xfc\xff\xe3\xec\x3b\xe0\xa4\x28\xd2\xbe\xeb\xa9\x4e\x33\xb3\x3b\xb1\x67\xba\x27\xef\x4e\xea\xd9\xbc\xec\xc4\xcd\x3b\xc0\xb2\xa4\x25\xe7\xbc\x20\x39\x48\x92\x28\xc2\x90\x04\x45\x3d\x45\xc5\x80\x81\xd3\x03\x11\x39\x14\xf5\x54\x14\x75\xf5\xce\x33\x60\xba\x3b\xbd\xf7\xf0\xd4\xc3\x3b\xef\xde\xd3\xf7\x82\x7a\x49\xd8\x9d\xe2\xfb\x75\xf5\x6c\x00\xf5\xee\x7b\x5f\xd8\x9e\xae\xae\xaa\xee\xae\xaa\xae\x7a\x2a\x3c\x4f\xfd\xff\xc7\x83\x35\xb1\xba\xa3\x15\x93\x0b\xb1\xd5\xdb\x98\x08\x3c\x09\x77\x3f\x19\xa8\xad\xf5\xce\x5f\xb5\x82\xfc\x31\x78\xfc\x1d\x7e\x10\x14\x4e\xae\x38\x5a\x17\xc3\x33\xc6\x96\x4d\x2e\x1b\x3b\x73\xd4\x03\x83\x6d\x5f\x1a\x0c\x5f\xda\x06\x3f\x30\x6a\x26\xf5\x9a\xd5\xfe\x40\xab\xed\x0b\x83\xe1\x0b\x5b\xeb\x03\xed\x58\x19\x84\x0b\x26\x97\x3d\x5c\x5b\x56\x1b\x38\xfe\x4e\xee\x11\xb2\xf0\xc9\x40\xa2\xd1\xbb\x68\xc5\xaa\xf9\xde\xda\xda\x80\x12\xa8\x2d\xab\x7d\xb8\x6c\x72\x01\x1e\xc4\xbf\x93\x43\x34\x65\x7b\xfa\xa7\x16\xdf\xff\x6d\xd6\xf9\x42\xbf\x7d\xb1\x16\x54\x87\x86\xa0\x25\x68\x2d\xda\x89\x50\xc4\x1e\x0a\x26\x13\xf1\x18\x93\x3f\x4b\xe9\x24\x1f\xea\x31\xbb\x77\xf0\x0e\x3b\xfd\xf1\xe3\x78\x4c\x9d\x76\xa8\x62\x98\xce\x40\xa2\x29\x31\x4e\x7b\x8d\x90\x3a\xbe\xe1\x92\x1a\x6e\x7c\x4c\x8a\x27\x43\xaa\x9f\x0f\x42\x0e\x55\xfc\xc6\x1d\x21\x87\xdd\xcf\x50\xe5\x91\xa6\x88\x49\x5d\x4e\x81\x8a\xdb\x66\x2d\x9b\xb7\x30\x3c\x62\xd4\xa8\xb0\x72\x64\x74\x5d\xac\x71\xf2\xfa\x86\x0a\xa5\x74\x75\x49\x6b\x7b\xf9\xb9\x8e\xd1\x9e\x9a\x9a\x51\xd3\x0d\x91\xa1\xd7\x61\x7c\x1d\x03\x17\xfc\x4a\x32\xa1\x0f\xe9\x97\x30\x37\xb0\x8d\x61\x60\x2c\x2c\xe6\x6c\x45\xb5\x4a\x86\xbc\x36\x60\x58\x4d\xac\xad\x06\xcf\xef\xaf\x12\xfb\x74\x50\x4b\x06\x6e\x9f\x34\x71\x7a\x3c\x72\x8d\xcf\xb7\x66\x72\x6c\xb1\x99\xb1\xb6\x26\x9d\x4c\x64\x61\xe5\xe0\x90\xe5\xf4\xe0\x8c\x89\x2b\x72\x56\xe8\xcc\x57\x8e\x71\x7a\xf5\x64\xae\x27\x0d\x3b\xab\x64\x79\x00\xd9\x18\xd3\x6f\x72\x8c\xff\x04\xaf\x1b\x6f\x77\x16\x55\xaf\x63\x00\x9f\x8d\xa4\x1a\x14\x27\xfe\x20\x9c\x4e\x45\xc2\xc9\xd4\x84\xcb\x30\x5e\x79\xd4\x7a\x11\xf1\xa7\x29\x06\xb6\x85\xae\x61\x2e\x47\x1b\x10\x8a\x24\x42\x41\x87\x3d\x1e\x63\xd4\x1e\x49\x75\xa8\x2d\x83\x32\xa9\x53\x64\x16\xce\x61\x09\x04\xa9\x69\x72\x52\x9d\x3c\x24\xf3\x7a\x7c\x39\x06\xa1\x54\xd2\x9a\x88\xc6\x79\x87\xd5\x1e\x71\x50\x54\xab\xa4\x35\x9e\x0c\x52\xc4\xfe\x78\x92\x86\xc4\x1d\x41\xa5\x1c\xac\xf6\xbc\xe5\xb7\xd6\xff\xe1\x09\x87\xef\x3b\x7e\x47\x43\x63\xc3\x96\x2d\x1b\xc0\x18\x2e\xb7\xec\xdf\x52\x12\xad\x1c\x3a\x79\xf2\xd0\x4a\x72\xfb\x90\xcd\x57\x0e\x7c\x6a\x70\xcb\xb0\x39\x2f\xdc\xd0\x31\x7e\x1e\x3c\xf5\x31\xcb\x7e\xcc\xe2\x59\x43\x17\x35\x4f\x8f\xf9\x74\x58\x70\xf2\x0e\xa5\x83\xff\x1d\xff\x88\xb9\xce\x34\x69\x4a\x53\xee\x8b\xd1\x75\xf5\x63\xc7\x34\xd4\x4b\xf3\x17\x2f\x60\x66\x36\x8d\xbf\x65\x0f\xbc\xf5\x46\xa1\xa1\xbc\x74\xdb\x13\xb2\x4e\x89\x16\x95\xca\x0e\x7f\xe5\x84\x3a\xf2\xae\xab\x6e\xd9\x88\xc3\x8d\x6c\xe9\xa4\x15\x5e\xd6\xf9\xf0\xb8\x7d\xa7\xaa\xbb\x5f\xa8\x9c\x86\xe7\xce\x0e\x06\x66\xe4\x0e\x4e\x3b\xf9\x93\x68\x49\x63\xc7\xd4\x06\x98\xc3\x62\xfe\x85\xf6\x54\xa8\x74\xcb\x0b\x2c\xb9\x75\x27\x6b\xba\x6a\xca\x94\xfa\x86\xa9\xdf\xe4\xa5\xd6\x43\x88\xe1\x85\x28\x13\x02\x6b\xfc\x1b\xfb\x3d\x4a\xc1\xb0\xea\x5e\xa7\xbd\xec\xe0\x46\x10\x16\xe0\xff\xba\xc4\x28\xdd\x0e\x7f\x23\xaf\x0d\xa8\x98\x09\xb5\x44\x24\xa7\x99\xeb\x2f\xe5\x9e\xad\xbb\x88\xd8\x57\x79\x84\x7c\x14\x2b\x48\x03\x07\x13\xb0\x28\xf1\x42\x28\xa8\x44\x15\x0d\xb9\x31\x99\x48\xc5\x58\x8b\x2a\xfe\xf3\xd0\x1d\x14\x4a\x4c\x03\x16\x72\xd8\x65\x0d\xfc\x38\x99\x68\xc6\xf1\x18\xcb\x8c\x58\x33\xa6\x31\xde\x9c\xfc\x57\x25\x78\x1c\x9c\xdd\x8f\x4d\x0e\xa5\xad\xb5\xa4\x69\xa8\x65\xf5\x21\xf8\xcb\x3d\xe4\x6f\xf7\x65\x06\x3b\x64\x8e\x0b\x3b\xe2\x75\x73\x1f\xcf\xb6\xb7\x67\x1f\x7f\xf9\xf1\x6c\x7b\xc2\x60\x54\x4a\x0d\x99\x59\xf7\xfc\x6a\xfd\x7d\x60\x64\xed\x87\x56\x87\x06\x8f\x21\x37\x12\xa7\x14\xc0\x1e\xfb\xd6\xbf\xbd\xf8\xa3\x1d\x8d\xd3\x47\x86\xca\xc6\xae\xae\x22\x3f\x21\x7f\xbf\xc7\xc4\x45\x1c\x76\x99\x35\xe6\x6f\x6f\xcf\x3e\x3e\x77\xcd\x62\x7b\x89\xdd\x24\x5e\x7d\xd3\x86\x5f\xdd\x33\xf3\x1e\x04\xc8\x96\xef\x07\x97\x20\x04\x79\x43\xd9\x74\xc2\x46\x57\x9e\xfd\x7c\x11\xa8\x95\xce\x61\xf7\x83\x23\x3f\xaa\xaa\x62\xa3\x4a\x48\xe0\x05\xbf\x86\xbe\x19\xea\xa1\x94\xa1\x86\xb6\x55\x4c\x52\x23\x96\x89\xa5\x53\x49\x0a\x14\x13\x14\x4c\xa0\x15\x52\xd2\x02\x26\x9d\x64\x04\xab\xe9\xd4\x35\xfb\x4e\xed\xde\x5d\x33\xbe\x31\x16\x2c\xb2\x17\x42\xda\xc6\xb0\xa3\xa6\x44\xc3\x7a\x87\xd5\x51\x60\x01\xc0\x5c\xc3\x70\xfb\x84\xb4\x0e\xb3\x5c\xe6\x2f\xc9\xb5\xe3\x32\x66\x9d\x29\xa3\x2b\xfd\xe1\xf8\x50\xeb\xfa\x89\x03\xed\x45\x05\x0d\x76\xd6\x80\xf1\x80\x8d\x46\x8e\xd5\xd9\x86\x97\x02\xcb\x32\x32\xfe\x40\x0c\xd8\xeb\x2d\x52\x73\xe1\x3e\x28\x6f\x1c\x94\x76\xa4\xea\x47\xb7\x5d\x31\xb6\x9e\x9b\x30\xd8\x94\x28\x04\x8e\x83\x35\xaf\x2f\x2f\x5f\x63\xb6\x17\x3b\x8a\x30\xb0\x77\x0f\xb1\x47\xaa\xca\x58\x27\x3f\xd7\x26\x89\x1c\x66\x01\x2a\x4b\x18\xb3\x3b\x15\x29\x89\xfa\xb0\x04\x18\x63\xa6\xe0\xf9\x66\xc6\x5e\x3a\x98\xd5\x43\xaa\x0a\xc4\x9e\x71\x57\xb3\x0e\x71\x2f\x53\x9c\xf0\x00\xaa\x44\xc3\x29\x86\x6c\xdf\xa0\xbd\xbf\xaa\x1b\x7f\xbb\x37\x28\xa1\x20\xab\xd6\x07\xda\x38\xa3\x42\x3a\x6c\x4d\xd8\xd4\x71\xa9\x04\x76\x5e\x90\x35\xd0\x39\x0b\x1d\xa9\x4a\xb8\x35\x56\x5a\x3e\x68\x50\x79\x29\xe3\x8a\x97\x78\x2a\x2b\x3d\x25\xf1\x3f\xd5\x68\x3e\xf8\x78\x22\xaa\xfa\x44\x13\xe4\x9f\x45\xd1\x87\xc9\xa7\x0f\xca\xa1\x80\x7b\x40\xb3\x67\xbc\x3e\x37\x8c\x7c\xfc\x63\x18\xf5\xca\x63\x50\xf7\x0b\xbc\xf2\xba\x75\xe9\x57\x0f\xb4\xaa\x11\x1e\x04\xef\xc3\xdf\x07\xef\x23\xac\x61\x7c\x2c\x5e\x12\x8d\x93\x39\xde\x8a\x4a\x8f\xb7\xb2\x02\xfe\x7a\xb9\xc7\x31\xf6\x6e\x72\xfe\x9e\xd1\x23\x18\xc6\xc0\x5a\xf1\xb6\x0f\xce\x40\xd1\xc3\xe0\x7d\x70\xd7\x67\xb9\x96\x75\xef\x4f\xf9\xd1\x8a\xc8\x8d\x5f\x81\xff\xab\x1b\x6f\xfc\x9b\x86\x5f\xc2\x5f\xe4\x11\x45\xe3\x90\x84\x3c\xb0\x70\x84\xd1\x20\x92\x92\x56\x3d\x44\x94\xa8\x86\xae\xcc\x7f\x1a\xe0\x2f\x22\xce\x63\xb2\x16\x18\x49\xc3\x57\xb6\x22\xa3\x5e\x94\x99\x8e\xae\x5f\x90\x75\x11\x06\x07\xf9\xac\xd9\x6a\xe7\xfe\xe1\x2c\xb9\x80\x7c\x16\x1d\x77\x8a\x9c\x95\x59\x21\x60\x87\x59\x6c\xa8\xfb\x8a\x07\x4c\xa5\x25\x22\xd3\xa9\xef\xc3\x4b\xb8\xc8\xfd\x0b\xb9\x51\xf1\x25\x6f\x85\x9e\xb7\xe6\xdf\x09\x22\x70\x7a\xe8\xff\xde\xdc\x97\xe4\x97\x36\x9f\x49\x2f\x4a\xa4\x24\xc2\x30\x21\x3e\x1b\x22\x67\x3e\xba\xb0\x10\xc6\x32\x73\x48\xb0\xef\xed\xff\x45\x4e\x39\xe8\xdb\x7f\xf2\x92\xa9\x34\x6a\x67\x3a\x1d\x17\x4c\x5c\x79\xf7\x2b\xd7\xe1\x6d\xdd\xbf\xbb\x44\xee\x24\xa8\x4c\x50\xc7\x1f\xa1\x60\x58\x9b\xcb\xc6\xa5\xbc\xe9\x3e\xb5\xe8\xe7\x05\x59\x12\x7a\x24\x11\x85\x0b\xa6\x1f\x97\xbb\x94\xd0\x56\xdb\xbe\xcf\xa3\xcd\x6f\x93\x4f\xef\x39\x4e\xde\x58\x21\x80\xee\x3a\x83\xd9\x22\x0c\x7f\x6f\xc3\xe2\xe7\xaf\x1f\x37\xee\xfa\xe7\x17\xcf\x7b\xb2\xed\xba\x22\xab\xb5\x8c\x64\xdc\x4a\x49\xd4\xbf\x63\x19\x88\xb7\xde\x03\xde\xb7\x73\x17\x7a\x8c\xf7\xce\x51\x23\x34\xc6\x4b\x5e\x23\x9f\xbe\xbd\xf9\x96\x5d\x06\x97\xee\x7a\x3d\x36\xcc\x59\x3c\xee\xfa\xe7\xdf\x7d\xfe\xfa\x71\x43\x07\x5d\xef\x8f\x96\x28\x6e\xe8\x2c\xb3\x5a\x8b\xb6\x2f\x58\xb9\xf9\xed\x3b\x49\xaf\x35\x5f\x47\x8f\xfd\x5a\x9f\xfd\x0a\xe5\xfa\x37\x61\x0b\x1d\x87\x5b\xaa\xe0\x92\xdd\x64\x3b\x48\xb7\x36\xb2\xa6\x43\xf0\x85\x8f\xc0\x2d\x97\x29\x0e\x39\xb4\xf0\x91\x3f\xf7\x8f\x44\x9e\xfe\x86\x6e\xb0\xf9\x62\x96\x7f\x99\xcb\xa2\xdd\x08\x71\x79\xeb\x33\x2a\x25\xd3\xa9\x24\x93\x88\x6a\x6c\xe3\x0e\xc6\x2e\xfb\x99\xfc\xac\xae\x7f\x8c\xa8\x35\x91\xaa\x62\xa3\x55\xd0\x43\xfb\x14\x8f\x69\xb3\x37\x13\x16\x78\x87\x68\x97\xa5\x78\x40\x95\x45\x62\x22\x5a\x85\xbf\x3d\x06\x7d\x2e\xbf\xbf\xe2\x64\x65\xc5\x63\x15\x4e\x77\xb0\xa2\xde\x12\x00\x30\x46\x72\xb3\x14\x23\x40\xc4\x92\x89\x95\xb8\x9c\xd5\xa7\xaa\xca\x8f\x95\xc9\xae\xa2\xd2\x94\x39\x00\xaa\x8c\xd2\x99\xf4\xe6\xc6\xaa\xb0\xd3\x59\x75\xaa\xaa\xec\xe1\x32\x97\x2b\x58\x5e\x6b\x0e\x01\x18\xdd\xf8\x39\x97\x11\x20\x64\x1b\x17\x77\xb9\x2a\x1e\xab\x28\x3f\x5e\xee\x72\x85\x2a\xeb\xcd\x21\x08\x5a\x1a\xab\xc3\xce\xac\x20\x94\xba\x8a\xfc\xac\xc1\xe0\xd8\x00\x7b\x1c\x06\x96\x35\x38\xc8\x8d\x37\x49\x06\x1e\x7c\x45\xee\x0a\x41\x28\x73\xfa\xfd\x9c\xc1\x20\x6f\xac\x63\x2a\x99\x2a\x4f\x2c\x18\x75\xf2\x06\xd6\x4b\xc3\x2a\xdc\x7e\x0f\xe6\x0d\x8e\x7d\xa4\xd3\x51\xc0\x30\x05\x0e\xc8\xec\x73\x14\x30\xb2\x92\x0f\xf4\x02\x67\x90\xaf\xef\x1e\xb7\xc1\x61\x10\xb0\xcf\xef\xae\xa0\x18\x43\xce\x8b\x59\x96\x70\x59\x54\x91\xc7\x8f\xa0\xdb\x4f\xfa\x0c\xb4\x43\xbd\x2e\x25\x4a\xfb\xa8\x74\x2a\x9d\x2a\x85\x98\xc4\x92\x88\x33\xc6\xba\x79\x26\xec\x5a\xee\x0a\x7f\x2f\xe4\x5e\xee\x0e\xdd\x3a\x6f\xeb\xa0\xcc\xd4\xa9\x9b\x56\x42\x0c\x7e\xe3\x0a\x73\x83\x87\xfb\x32\xc0\xbb\x0a\x92\x5d\x59\x57\x38\xec\x62\x5f\xee\x6a\x56\xcf\xf0\x45\x61\x75\xfd\xa6\x75\x37\x1d\xd9\xb8\xbe\x34\x12\xa6\xf3\x08\xb5\x4e\xa1\x7e\xbc\x23\xd5\xa8\x05\x0d\x46\x43\x11\x8a\x38\x02\xc9\xc8\x37\x2c\x85\x03\x49\xd1\x11\x4a\xaa\x67\xe6\xf2\xb0\xcb\xd7\xca\x1c\x21\x4a\x53\x09\x1d\xe4\x10\xa6\xf4\x5a\x79\x5c\xb7\x43\xdd\x87\xce\x9d\xe3\x51\xae\xf8\x5c\x9f\x27\x93\xed\x73\xe3\xcc\xb9\x73\xdd\x87\xb2\xd9\x6c\xb6\x1f\x88\x9c\x02\xd9\x6c\x16\xa3\x6c\xb6\x1b\x65\xb3\xec\x25\x21\x04\xf5\xbf\xca\x47\xd3\xf4\xdb\x79\x6e\x7a\x04\x31\xc9\xc2\x17\xab\x65\x18\x51\xeb\xa9\x45\xed\x47\x23\x6a\xe5\x2c\x96\x2c\xaa\x74\xe2\x24\xbb\xc0\xa5\xd8\xce\xdd\xcf\x3d\x47\xfe\xf9\x1c\x26\x77\xce\xdc\xba\xfb\xb9\xe7\x76\x6f\x9d\x09\x8b\xf1\x73\x60\xa0\x4e\x72\x27\xc6\xb0\x78\x26\x46\x6a\x94\xe7\x76\x17\x4a\x4f\x4e\x56\x83\x26\x3f\x29\x15\x6a\xb7\x4d\x7e\x52\x72\x4a\x4f\x4e\xbe\xa4\xad\x52\x5e\xfc\xb0\xb6\x07\x36\x95\x88\xa6\xa5\xb8\xb6\x94\xec\xb0\xd3\x0d\xce\x94\x1c\x2f\x4d\x37\xc4\x7e\x63\x2b\x1f\x87\xae\x99\x3a\xb1\xe9\x4b\x8c\xbf\x6c\x9a\x38\xf5\x9a\x6b\x1e\xdb\x8a\xbf\x6c\x9e\x30\xf5\x9a\x6b\xa6\x4e\x68\xfe\x12\x6f\x7d\x0c\xae\xe9\x3f\x54\xca\x3d\xb6\xb5\x7e\xa3\xc5\x64\xd9\x58\xbf\xf5\xb1\x6b\xae\x99\x2a\x58\x36\xd6\x5d\xf3\xd8\x35\x75\x1b\x2d\xc2\xd4\x6b\x98\x73\xfd\xc7\x4d\x42\xef\xdc\xd1\x8a\xaa\x51\x33\x6a\x47\x53\xd1\x7c\xb4\x16\x21\x44\x97\x7d\xe9\x0a\x2f\x55\x4c\xa4\x53\x20\x0b\xb2\x64\x37\x53\x04\x84\xbe\x89\x5c\x3c\x26\x53\x43\x59\x91\x2e\x1e\xe7\xad\x66\x25\xbb\xcc\xf7\xbf\x4a\x69\x75\x97\xca\xcf\x68\xde\x74\x85\x6a\xd5\x35\x6c\x97\x84\x06\x8d\x66\xc7\x43\xec\x03\x5c\xcb\x8f\x54\x18\xec\x2e\x63\x41\x99\x2d\xb8\x7d\xa2\x8b\x79\xa6\xea\xef\xad\xa2\x98\x99\xb6\xf2\x79\xd2\x45\x7e\x4b\xba\x9e\x5f\x49\xe1\x54\x9f\xfa\x7e\x46\x4c\x8a\xad\x5d\x86\x42\xa3\x61\x86\x5e\x6f\x70\x1b\xa6\x1b\x3e\x2c\x70\x16\x4c\x37\x18\xf4\x1e\xfd\x0c\x7d\xb1\xcd\x44\x81\x4f\x3a\x4c\x27\x6c\x5e\x9b\xcd\x6b\xbb\x63\x86\x1a\xd5\x60\x98\x6e\x70\x1b\xf4\xcc\xdd\x31\xbb\xa1\xe2\xc8\x72\xd7\x00\x03\x57\x32\x71\x7b\xb0\x00\x7e\x58\xf5\xb7\x56\x31\x29\x66\xbe\xff\xd4\xf7\x7a\xde\x01\x7e\xe0\x9e\x5f\x39\x2d\x23\x8a\xad\x50\x91\xbf\x51\x3f\x43\xef\xf9\x2b\xfd\xd5\x53\x9f\xe7\xe8\xb3\x0f\xe5\x5f\x65\xb3\x0d\xe9\x79\xbf\xde\xe0\xce\xe3\x12\xa8\x65\xcb\x22\xbb\xfa\xe5\x21\xc2\x31\x01\x7c\xd9\x12\x10\xa4\x9a\x40\x88\x8a\xb2\x12\x95\xb9\x48\x9a\x17\xd2\xa2\x10\x75\xd8\xe5\x34\x27\x0a\x52\x2c\x1d\x15\x23\x78\x2e\x14\x41\xd1\x0a\x72\x2f\xf7\xcd\x35\x20\x76\xc5\xed\x0b\xbf\x68\xb9\xf6\xc0\x5f\x93\xe4\x13\xf2\x49\xf2\xaf\x07\xf6\x34\x7f\xb1\xf0\x76\x3f\xb4\xed\xbb\x6a\xdd\x3f\xd7\x5d\xb5\x0f\xda\xf0\xbb\xef\xbe\x4b\x1e\x63\xb3\xdf\x32\xc1\xed\x1a\x76\xa6\x8b\x99\x76\x0e\x06\x17\xbe\xdd\xbe\xe5\xfe\xfb\xb7\xb4\xbf\x5d\x48\x9e\x3f\x37\x8d\xe9\x3a\xb3\xab\x84\xfc\x72\x48\x34\x3a\x04\xca\x4a\x10\xe5\xae\xcb\xf3\x43\xf7\xec\x29\x18\x4e\x59\x43\x36\xa1\xeb\xd0\x03\xe8\x71\x74\x5a\x95\x0e\x3d\xcc\xd5\x79\x2a\xf7\xcb\xae\xe1\x3f\x84\x47\x7a\x8c\x9a\x42\xff\x29\xe6\x7f\x0e\x0f\x24\x13\x1c\x4b\x81\x1d\x9a\xd9\x70\x31\xeb\x67\xad\x97\x45\xb1\xf6\x12\x87\x82\xc6\x12\xa9\x51\x45\xf6\x39\x71\xe6\x5b\xbd\x73\x2f\x7b\x15\x8c\x15\x0f\xbe\xf8\xbf\xb9\x0b\xb2\x39\x42\x76\x90\x1d\x39\x62\x8d\x8f\xbd\xf1\x09\x30\x42\x33\x14\x3e\x79\xe3\xd8\xb8\xb5\x2f\x8e\xe2\x21\x59\x8f\x72\xae\x8f\x47\xb4\x8f\x5d\x94\xac\xf9\x36\xdf\xfd\x8a\x67\xfb\x76\x8f\x92\xfb\x5f\xdc\x02\xd7\x1b\x0d\x8b\x31\x2c\x30\x18\xad\x89\xf6\x91\xa3\xea\x23\x91\xfa\x51\x23\xdb\x13\x64\x4a\x5f\x8c\x89\xdb\x3d\x8a\xe2\xd9\xde\xab\xf7\xcb\xe3\x22\xd8\xa9\xf5\x4e\x5d\x1e\x07\xac\x57\x2e\x89\xa9\x78\x80\x2a\xfa\x7a\x3c\xa8\x2a\x21\x26\x43\x2f\xb4\x1b\xd7\xeb\xc2\x9d\x8a\x5b\x71\x13\xe4\x56\xce\x0b\x4e\xfc\xc7\x8b\x88\x45\xda\xa5\x5b\x81\xa3\x4e\xa1\xfb\x2c\x39\x64\x33\x41\xb1\xc9\x86\x0f\xf5\xb8\xd8\xce\x1c\x72\x2b\x39\xda\x55\x60\xc4\x2c\x91\x73\x19\xdc\xd9\x9d\x25\xf9\x4e\x41\x71\x33\x48\x86\xf4\xb9\x3e\xd2\x73\x6d\x9c\x4b\xd3\xec\x53\x47\x9c\x76\x01\x64\x81\x67\xa3\x10\x4a\x82\x62\x6b\x01\x19\x52\x31\xea\x09\xa9\x18\xff\xeb\x48\x84\xac\x3c\x70\xe8\x41\xd2\x70\x8a\x1c\xf8\x11\x2c\xdd\x52\xfd\xe0\xa1\x03\x70\xb3\xb2\x74\x44\x84\xac\xfa\x1c\x6e\x51\x96\xb2\x0d\xca\x12\x85\xac\x3a\x70\xe8\xc1\xea\x2d\x34\xca\x29\x78\x45\x8d\x73\x4b\x64\xc4\xb2\x08\x59\xf9\x39\xdc\x1c\xa1\xba\x7f\xd7\xc5\x42\xfe\xbf\x29\x6f\x9f\x03\xd5\x53\x56\xa2\xfe\x28\x08\xdf\xc2\x75\xe9\xe7\x62\xa9\x78\x8a\xc2\x7b\xa6\xe4\x98\x1f\x37\x73\x69\x5e\xb0\x69\xbb\xef\xd2\x0c\x55\xfb\xe7\xf9\x12\x44\x4a\xbe\xe0\x07\x39\xdf\x07\x38\xac\xe9\x94\xc4\x2c\xd9\xf6\xf8\xb6\x6d\x8f\x6f\x83\x7f\x6e\x9d\x3e\x6d\xdb\xb6\x69\xd3\xb7\x7e\x92\x19\xd3\x75\x74\x42\x43\xf9\x8c\xa1\x33\xe2\xd3\xbc\x93\x70\xab\x87\x67\xdd\x21\x61\x25\xd7\x22\xb7\x2a\x43\xe3\xc3\x9b\x46\xfc\x74\x53\xd7\xc4\x65\x83\xd6\x2d\x1e\x3d\x99\x05\x5d\x40\x00\x76\xca\x98\xc5\xeb\x06\x2e\x99\xd0\xb5\xc9\x55\x16\x65\xcd\xcc\xec\xc1\xec\x67\x83\x67\x3b\xa2\x65\x8c\x77\xc2\x86\x0d\x13\x26\xae\x5f\x3f\x31\x7f\x26\x5f\xe3\x83\x53\x86\xb7\xce\xcc\xcd\x91\x83\x92\x59\x00\x16\xbc\x3c\xe3\x72\xcf\x60\x19\x00\x86\x2f\xb0\xc8\x45\xce\xdb\x17\x91\xdf\x3d\xb9\x3a\x54\x5c\x1d\x5f\x0d\x6d\x80\x75\x40\x4e\xac\x89\x55\x17\x87\xd7\x3c\x09\x9e\x45\xb7\x47\x12\x1e\x6c\x60\xf0\x53\xc3\x16\x2e\x1c\x96\x1b\x61\xf6\x24\xd4\x32\x9b\x7f\x31\xcb\xdf\x93\xd7\xd3\x9a\x91\x4b\xad\x59\x94\x4e\xcc\x2a\xa6\xad\x01\x6b\xc0\x91\x06\x2b\x04\x84\x50\x32\x60\x15\x99\xec\x2d\xb8\xe8\x96\x5b\x72\x5d\x93\xa1\xed\x2c\xe3\x25\xa3\xc9\xb3\x67\xcf\x92\x35\x2b\xd8\xd1\x64\x34\x3c\xae\x1e\x39\x1d\x61\x3c\x5d\xff\x7d\xf6\x2c\x7b\xac\xbb\x80\x8c\x3e\x7b\x96\xbd\x16\x02\x5a\x1d\x9e\x76\x11\xb8\x63\x5c\x0e\x49\xa8\x1c\xb5\xa0\xd1\x68\x81\x2a\xa9\xb0\x5a\xd4\x74\x10\xa5\xcd\x82\x29\x80\x67\x94\x37\x03\x4b\xf7\x35\x2a\xcd\x20\xc7\x64\xba\xf5\x0d\xd4\x0e\x30\xaa\x30\x14\x9c\x33\xcf\xf3\x00\xea\xb7\x01\x85\xc2\x7a\xca\x92\x8d\x93\x04\x9e\xe3\x85\x34\xaf\xa1\xad\x52\x93\x1a\x3f\xc8\x0c\x07\x5c\x61\x34\x75\x31\x64\x64\x81\x63\x1b\xef\x80\x06\x73\x8d\xcb\xe9\x39\xc0\xd4\x6c\x24\x7f\xb6\x86\xc4\x42\x4e\x67\x2b\x0b\x19\x9f\x1f\x5a\x31\x51\x76\x31\x75\xc2\xc3\xf1\x88\xdb\x74\xac\xda\xc4\x59\x43\x03\x60\xfd\x99\xd1\x3a\x6f\x6e\x3a\xd7\x50\x5f\x4b\xae\xd5\x79\x4a\x61\x54\x7d\x89\x9e\x51\xf0\x41\xc6\x67\x26\x3f\x1d\xec\x04\xb9\xca\xe4\xf7\xc3\x88\x6b\x62\x7a\x6f\x64\xc0\x01\xfe\xec\x36\xf2\xa1\xb1\x58\xa7\x9f\x5d\x66\x76\x14\x9a\x0c\x23\x9e\x68\x13\x0b\xf4\x06\xe5\xd3\xb4\x39\x3a\x15\x07\x5d\xb1\xf6\x1f\xb5\xe2\x51\x3e\x5b\x50\x5f\x4e\x4e\xa7\x7e\x69\x37\x39\x0c\xe0\x18\xe5\x88\x39\xca\xad\x10\x1d\xe4\x11\x24\x3c\x6e\xa1\xdd\x3a\x15\x4f\x0e\x79\xca\x67\x99\x0d\x21\x5b\xee\xa5\xd7\xa2\x76\x43\xbb\x59\x87\x79\xbb\x54\x5d\x02\x0b\x1e\x19\xc4\x8b\x56\xf9\xa3\x3a\xba\xbf\x5f\xd3\xe3\x64\x2f\xd9\xfb\xe0\x41\x21\x54\x41\x39\x6b\x02\xd6\x00\x1d\xe5\x59\x29\xcc\x63\xf2\x92\x43\x1d\xc3\xd2\x45\xc2\x80\xd5\x2e\x5c\x02\xe9\x10\x48\xb2\x88\x64\x21\x9b\xcd\xd1\x9d\x1a\x1c\x22\x08\xf7\x3b\xba\x51\x56\x49\x28\x7c\xf6\x02\x2a\xe0\xce\xb8\x95\xec\xaa\xb1\xe7\xb3\x63\x57\x01\x52\x6f\xba\x88\xb2\x59\x06\xd1\xfb\x50\xaf\x3e\x9e\x1e\xdd\x19\xa6\x53\x03\x12\x66\x33\x5d\x9d\x81\x22\x85\xfd\xa0\x8b\xda\xaa\xb2\x99\x2c\x62\x51\x19\x32\x0a\xbf\xa4\x78\x0b\x45\xa8\x0e\x8d\x43\x28\x9c\x6f\xb5\x0e\x7b\x3a\x58\x05\xc1\xfc\x2e\x9a\x74\x33\xc4\x34\xf8\x79\x8a\x7f\x15\x0a\x9a\x18\xcd\x3f\x15\x2e\x66\xa9\xbf\x18\x8c\x2a\xe1\x62\x36\x8f\x0b\xd6\xe7\xcf\xda\x4b\xf6\x5f\x33\xfe\x9a\xc5\xb8\x7d\xdb\x8e\x6d\x23\x19\xdb\x1d\x86\xd1\x7f\xfa\xc3\x9f\x46\x1b\xee\x40\x17\x0b\x0a\xf7\xfe\xf1\xce\x49\x8f\x6c\x9b\x5f\x8f\xad\x07\x0c\xbb\x60\x23\x64\x61\xe3\x2e\xc3\x01\x52\x50\xf0\x04\xd9\x46\x6a\xc9\xb6\x27\x0a\x0a\xac\x77\x18\x9e\xc3\x2c\x76\x63\xf6\x39\xc3\x1d\xc6\x5b\xed\xc5\x15\x15\xc5\xf6\x2d\xb1\x58\x2c\x76\xc0\x66\x34\x8c\x9a\x3a\x75\x94\xc1\x68\x3b\x00\x16\xdd\x92\x2b\x2a\x9a\x9b\x2b\x0e\xd8\x0a\x0d\xbb\xf6\xef\xdf\x65\x28\xb4\x1d\x00\xb3\xfe\xde\xfb\xef\xbf\x57\xaf\x46\x7c\xf6\xcd\x37\x9f\x55\x23\x22\x64\xd4\xf6\xcd\xd0\x75\xcc\xfe\x5a\xa9\x16\x34\x12\x4d\x40\x57\xa0\x65\xe8\x6a\x84\xd8\xcb\x38\xe1\xd0\xff\xf2\x0c\xd6\x3c\x8a\x88\x14\x4b\xf5\xf7\xeb\x8f\x75\x67\xe9\x67\x83\xdd\x7f\x8c\x0b\xd9\x91\x4b\x47\x8e\x5c\x0a\x67\xe8\x89\x68\x27\x66\x64\xff\xab\x6f\xf5\x64\x46\xb6\x2f\x6e\x6f\x5f\xdc\x4e\x7a\xee\xef\xd9\x8e\xc7\x21\xb7\x42\xbd\xce\xb4\x27\x2e\x50\xcd\x39\x97\x4d\xb4\x27\x97\x6a\x77\xab\x7f\x70\x86\x9e\xc8\x99\xfe\x57\xdf\xea\x99\xcb\x42\x9f\xf6\x1e\x5f\xd4\x82\x3a\x29\x2c\xb5\x36\xdf\x20\x87\xa9\x1f\x83\x2e\x20\x35\x1e\xaf\xfe\x22\x8c\xf4\x17\x11\xf7\x57\x1e\xa1\x28\x1a\x42\xd7\x41\x70\x20\x14\xe4\xcd\xc0\x08\x26\xa0\x9b\xa0\x9a\x99\x74\xaa\x01\x28\xfd\x0d\x15\x20\x92\x2c\x45\x35\x4a\x27\x7b\x28\x1a\x14\x78\x86\x16\x51\xba\xc7\x22\xdd\x0f\xdc\x5f\x6d\xd2\x14\x12\xac\x70\x29\x1c\x9b\xc6\x5c\xd4\xd5\xe5\x70\x32\xfa\x90\x2d\xac\xe7\x94\x9d\xbb\x17\x3d\xba\x6a\x61\xd2\x59\x00\x0c\xcb\x8e\xb9\xab\x6a\xec\xc7\xab\xf7\x4d\x9f\x3e\xdf\x86\x27\x40\x01\x39\x2b\xf9\x98\x3f\x72\x95\x3e\x3c\x39\xb8\x6d\xc0\xb2\xd5\xcc\xe6\x89\x1b\x49\x6b\xc0\x2d\x92\x23\x66\x77\xc0\xef\xa8\x3d\xb7\xea\x37\xb5\x11\x2c\x47\x97\xcc\xb9\xa3\xad\x85\x67\x80\x69\x78\x62\xd9\xf6\xcf\xc6\x97\x60\x80\x0e\x5d\xee\x9f\x86\x80\xc4\xbd\xe8\x53\xdc\x62\xe9\x0f\x54\x19\x1e\xcd\xf7\xb5\x06\x64\x43\x2e\x54\xa2\xce\xaa\x64\x24\x06\x30\xa3\xa4\xe2\xc0\x0b\x98\x49\xa5\x6d\xa2\x4d\xf5\xd1\x83\x85\xc1\x40\x03\xd4\x1c\xd8\xe0\x54\x40\x04\x43\x07\x19\xb4\xed\x8b\x42\x9b\x9d\xf9\x41\x4d\xfb\x98\x93\x25\xec\x2f\x3e\xf9\x1f\x28\x0f\x91\xa6\x52\x82\xd8\xc5\x0b\x06\x93\x0f\x5d\xe3\x58\xd1\x02\x8b\x1c\x21\x6e\x2d\xd3\xe1\x26\xb7\x91\x85\x70\x0a\x12\x96\x10\x39\xf8\xea\xcb\x90\x02\xef\x47\x9f\x92\xe3\xf0\x3d\x72\x3a\x27\x92\xd5\xf8\x2e\x26\x9a\xeb\x24\x53\xc9\x16\x3c\x00\x17\x40\x25\x78\x2c\x2e\xb7\x9d\x2c\xd2\x74\x23\x7a\x6d\xdf\x88\x19\x39\x91\x17\x35\x6b\x3c\xf4\x10\x4a\xb5\x40\x33\xa4\x65\x8e\x51\x42\x01\x81\x8d\x50\x5a\x20\x31\x0e\x4c\x5c\x0c\x71\x74\xa7\x08\x2f\xe7\xd7\x53\xab\x41\x90\xe2\x52\x2a\x9d\x88\x6a\x8b\xf8\xa9\x22\x88\x84\x82\x02\x13\x4f\xc7\x25\x39\x7e\x79\x2d\x16\x9e\xbe\xde\x94\x60\xd8\x42\xa6\xf0\xc2\x8e\xfa\x82\x0c\xf9\x3b\x86\x34\x98\x1f\xb0\xba\xd7\x0f\xdb\xf3\x28\x70\x91\x23\x8b\x8f\xe0\x3b\x87\x8c\xbd\xfa\x1e\x80\xfd\x03\x94\xc6\xe8\xe4\x36\x49\x1e\xb1\x72\xc7\xbd\xf8\x86\x9a\x8a\x9a\xaa\xb6\x94\x19\x3a\xb3\x03\xa5\x7f\x9e\x08\xbd\xc7\x99\xef\xce\xb6\x27\xbe\xa6\xd5\x49\x87\x12\xed\x38\x18\xb9\x49\x6f\x28\x36\xa4\x37\x42\x34\x65\x1c\x33\x93\x8c\x98\xd6\xb6\xc1\x47\x30\xde\x9e\xdb\x8a\x77\x58\x3c\xeb\x67\x2f\x1c\x26\x87\x1d\xfe\xe2\x40\xc1\xcd\x41\xd8\x38\x7f\x69\xab\x2b\xe8\x90\x02\xe0\xd2\x1d\x4c\xe5\x9e\xec\x90\x46\x30\x2f\x77\xd1\x87\x71\xb4\x6e\x3a\x7b\xcb\xc6\x8a\x5c\xa8\x1c\xc5\x51\x06\x0d\x45\x53\xd1\x15\x68\x11\x5a\x8d\x36\xa3\x7b\xd0\x33\xe8\x55\xf4\x7b\x74\x1e\x0a\xc0\x05\x95\xd0\x08\x23\x60\x2a\x5c\x0d\xfb\x10\x02\xa5\x87\x9c\x23\x1e\x4b\x2b\xd8\x96\xe6\xb1\x4d\x4e\xd9\x70\x54\xb2\x61\x81\xae\xa9\x27\xe9\xba\x1a\xc4\x93\x21\x47\xdc\xd1\x80\x93\x21\x21\x1a\x72\xc4\x93\x72\x3c\xcd\x38\xca\x21\xd9\x00\x8e\x78\x34\x16\x4f\xa7\x12\xd5\x10\x2c\x07\x47\x3c\x19\x0f\x27\x7a\x95\xfa\xe1\x98\x1c\x62\x35\x59\xcc\x87\x82\xa9\xbc\x2b\x28\x07\xa3\x41\x85\x6a\x53\x12\xe9\x54\x4d\x2c\x49\x4d\x5b\x6b\x64\x87\xe4\x10\xbc\x10\x12\xf8\x10\x1f\x89\x27\x13\x4a\x34\x28\x68\xec\xc7\x8e\x78\x32\x11\x8f\xf9\x80\x9e\x1c\x72\xbc\x09\x42\x8e\x9e\x69\x76\x0b\x24\xaa\x41\x51\x03\xe4\xb4\xb6\xf2\x4b\xd7\xd1\x43\xc1\xa8\x9a\xfe\x14\x5d\xe4\x6d\x52\x93\x9f\x0c\x39\xd4\x2c\xd8\xe3\xb1\x74\xcf\x2e\x2f\x35\x2c\xaa\xbe\x29\xde\xf7\x16\x39\xad\x48\xf9\xc0\xa8\xb6\xa5\x88\x3e\xf7\xf2\x97\x5e\x72\x43\x3e\xb0\x27\x4c\x08\x86\x78\x81\xa7\x7a\x39\x3b\x5d\x9c\x4c\xab\x13\xe3\x74\x2a\x99\x88\x2a\x51\xb5\x9c\x94\x6f\xe0\xfb\xcc\xc9\xde\xb5\xe8\xf9\xbd\xe3\xc6\xed\x3d\xbd\xf8\xae\xec\xce\xd9\x73\x1e\xdc\x3a\x73\xc6\xb6\x6d\x33\x66\xce\xda\x31\x67\xf6\xce\xec\x5d\x8b\x4f\xab\x61\xcf\x2f\xba\x0b\x2f\x10\xac\x02\xe3\x63\x39\x9e\xe7\x18\x9e\xe5\x74\x98\x61\x30\xc3\x52\x1a\x58\xc0\xc0\x33\xd0\x25\x49\xa2\x4d\x92\x6c\x22\x1c\x6e\xe4\xda\x60\x8f\x14\x96\x25\xd1\x76\x41\x0e\xcb\x72\x78\x0f\xc6\x40\x4d\x60\x31\xc6\x0c\xb0\x98\xde\x84\xe1\xc2\x69\xbf\xcf\x55\x6c\x36\x15\x39\xcd\x7e\x7f\xc0\xef\x0b\xf8\x8f\xf8\x7c\x56\xb7\x4f\x51\x7c\x5e\xf3\xe3\xd5\x26\xd9\x25\xdb\x0b\xa5\x80\xdb\x5f\x6d\x74\x16\xb9\xec\x46\x57\xc0\x17\xd8\xa1\x33\x1a\xc5\x01\x03\xfc\x5e\x6f\xb5\x63\x81\x4f\x89\xfa\x03\x92\xc9\xe6\x08\x0a\x0b\xc2\x3b\xe5\x42\xbf\xdf\x67\xd0\xe9\xf5\xb6\x68\xc0\x27\x9a\x6c\x56\x9b\x2c\xdb\x44\x8b\xc9\xee\x0d\xbc\xed\xf7\x9b\x3d\xbe\x68\xd4\xe7\x35\xed\x96\x0b\x7d\x3e\x35\x9a\x6e\x9b\xcf\x67\xae\x8d\x46\xbd\x3e\xd3\x68\xac\x26\x4d\x1d\x91\x62\x96\x61\xb1\x7a\x45\x53\xa8\xa6\x7a\x51\xff\x06\xc4\x3e\x32\x69\xdc\xde\xd3\x8b\xd4\x62\x99\xb4\x0c\x9a\xa0\x71\xc2\x15\xe4\x17\xe4\xbd\x2b\xae\x80\x0a\xa8\xbc\x7a\x19\xf9\x31\xf9\xf1\x52\x35\xc6\xe2\x45\xa7\xf7\x8e\xeb\x3e\xcb\x30\x56\xbb\xd1\x68\x37\x1b\x8d\xa4\x0e\x33\x06\x0e\xd4\x52\x30\x72\x15\x8a\xd3\x65\x13\x9d\x53\x8a\x8b\x34\x87\x2b\xec\x52\x4f\x3e\x60\x69\x2a\xb0\x56\x3e\xac\x9a\x08\x4c\x13\x31\xc9\xe9\x03\xa7\xd3\x6e\xd9\x33\x32\x1c\x1e\xa9\x1e\xad\x83\x2d\xf6\x92\xe6\x12\xbb\x33\xc8\x63\xd6\x60\x2e\x70\x9a\x9c\xf6\x80\xea\xb4\x9a\x64\xab\xd3\xe4\x12\xa4\x26\x4f\x69\xa9\xa7\x29\x76\x53\x49\x51\x71\x54\x94\xcc\x81\xc2\xe2\xa8\xdd\xb2\xa7\x3d\xc4\x7a\xd9\x92\xe6\x12\x8b\xd3\x08\x4e\xc5\x59\xe8\xb4\xec\xeb\x79\xd4\xe6\x9e\xe0\x7d\xad\x9b\x87\xda\x4b\x1b\x4b\xed\x8c\xfa\xc5\xd4\x12\xc1\x34\x15\xea\x3f\xf5\x9b\x63\x6a\x4b\x0d\xec\xef\xfb\x8b\x02\x8d\x9f\x9e\xca\x02\x03\xb2\xd2\x95\xbf\x41\x68\x0a\x9a\x87\x96\xa2\xd5\xe8\x1a\x74\x3d\xba\x9b\xb2\x1c\xf2\xe5\x14\xff\x55\x8a\xd8\xa9\x83\x4b\x28\xe5\x60\xed\x21\x87\xe7\xf2\x3a\xe4\x54\x5f\x93\xa2\x44\xa1\x1a\xc6\x35\x6d\x55\x54\x97\x9c\x37\xf4\x49\xf6\x34\x0a\xb0\x9a\xa0\x10\x73\x81\xbe\xf1\x42\x84\x32\xd1\x8b\x69\xb5\xf5\xe5\x0f\x88\x53\xcb\x2b\xf5\x75\xc9\x6f\x68\x0d\xa1\x2e\xec\x6b\xb4\x5a\x9b\xbc\x61\xfe\x8b\x8c\x68\x6f\x39\x3f\x61\xfe\x98\x39\x73\x46\x54\x36\xfa\x07\x0e\x84\x4c\x69\xda\xe7\xf0\x38\x7c\xce\x60\x69\x5d\x45\x63\xb8\x2a\xa2\x13\xbd\xd2\x00\xb9\xac\x62\x68\x3c\x03\x52\xa4\xb4\xa6\xa5\xa5\xaa\x5c\x29\x29\x19\xb1\x68\xe1\x88\x32\xf6\x5f\x03\xef\x27\x3f\x21\x0f\x13\x3b\x21\x7c\xc0\xad\x74\xff\x70\xe9\x81\xa5\x4b\x0f\x00\xbe\x79\xe8\xf4\x69\x43\x6f\x7a\xf7\x99\x0d\x6b\xd7\x6e\x78\x06\xf6\x8c\x5d\xd2\xde\x5c\x3b\x77\xa0\x1e\x02\xa3\xd2\x5f\xeb\xd2\xa3\x46\xa5\x85\xaf\xd3\xa3\xf0\xbf\xe2\x01\xf7\x87\x9e\x22\x63\x62\xc1\x9a\x11\xb3\xc8\x13\x4a\x7c\x1a\x8c\xfa\x63\x49\x85\xdd\x60\x33\x59\x1c\x9e\x8a\x48\xba\x24\x54\x6a\x31\xf2\x85\x92\xdd\x53\x51\x92\x69\x2a\x1d\x15\x19\x18\x1b\x30\x58\x19\x65\x5f\xb0\x7f\x41\xee\x69\x6c\x2e\x99\xba\x7f\xfb\x0d\x03\x14\xfc\x13\xf5\xa5\x4b\x75\x30\xf9\xdc\x39\x72\x4c\x5f\x3b\xbd\x76\x44\x1d\x79\xe2\x06\xcb\xe8\xea\x04\x79\x62\x37\x0e\x77\x15\xd6\x8e\x1e\x5d\xcb\xfe\xbd\x76\xf4\x68\x75\x38\x6e\xeb\xfd\x76\x18\x15\x20\x13\x72\x20\x2f\x0a\x21\x05\xd5\xa3\x31\x68\x06\x7a\x1b\xfd\x16\x9d\x07\x0e\xf4\x10\x86\x16\x98\x87\x90\x18\x8f\x42\x5a\x15\xc6\x8e\x90\x23\x22\x27\xe5\x84\x2a\x7e\x63\x11\xed\x04\xda\x89\x8b\x47\x23\xd6\x50\x52\x08\x45\x1d\xa1\x68\x48\x08\x89\x71\xd1\x1a\x97\xd3\x60\x37\xb1\x41\x25\xe4\x08\x45\x85\x80\x35\x20\xa7\xe3\xb1\x88\x23\x64\x8d\x3b\xb4\x87\xf5\x6e\xe2\xb2\xc6\xd3\x71\x99\xca\x7a\x47\x20\x99\x8e\xf9\x20\x90\xf4\xe3\x54\x8f\xa7\x35\xe4\x88\xaa\x7f\x54\x14\xaa\x7d\x2f\xbd\x12\x7a\xe7\xb8\x34\x20\x28\x24\x03\x0e\xa5\x1c\xd4\x43\xa0\x7b\x90\xe4\x78\x32\x1e\x4b\xab\x1d\x85\x86\x93\x9e\x56\x13\x6d\xe7\x05\x3f\xf8\x20\x44\xab\x86\x9a\x94\x18\x55\xd1\x51\xbf\x44\xaa\x8a\xa1\x9e\x72\x4c\x82\xfe\xc9\xb4\x86\xac\xa0\x55\xe0\x64\x42\xd1\xf6\xd7\x37\x80\x23\x14\x74\xd8\xa5\x94\x1f\xd2\x0e\xbe\x27\x8c\xa7\xfa\x88\x7c\x98\x1f\x18\x6b\x4f\x71\x04\x93\x89\x06\x70\x04\x15\x13\x4b\xb1\x2f\xd2\xb4\x74\x92\x1b\xa6\x55\xe2\x81\x23\xda\x1e\xbc\xe9\x26\x68\xba\xe2\xf9\x92\x89\x13\x4a\x21\x50\x36\x7e\x5c\x39\xf9\x5c\xfd\x85\x33\xd3\x2a\xba\xa5\x41\xb3\xeb\x66\xef\x72\xed\x71\xb5\x5d\xd5\x71\xe5\xd2\x49\xa3\xf0\x9d\x05\x56\xaf\x33\xea\x2c\xd5\x6f\x1d\x3b\xe1\x22\x02\x76\xec\xf8\x77\x56\x90\x8f\xce\x9e\xbd\xf3\xb6\xdb\xb8\xf7\xb4\xba\xb5\xd2\x95\x76\x7d\x20\xae\xb6\x63\x9f\xc1\x00\xb2\x9c\x29\x9d\xa4\x77\xd5\xba\x7e\x17\x7c\xea\x49\xd7\x29\xf9\xfc\x90\x92\xe3\xce\x9a\xdc\x0d\xe5\xe5\x3f\x95\x1e\x1e\xad\x55\xc3\x8d\x71\xff\xc9\xb4\x4c\x7e\x52\x54\xfb\x33\xb9\xf5\xf3\x54\x8c\x3c\x08\x53\xd2\x89\x5f\x38\x1a\x8a\x4e\xe8\x74\x2c\xb6\xd6\x15\x1d\x6d\xcc\x55\x3a\x25\x97\x6d\xa0\x33\x38\x64\xe0\xdd\x03\xea\xc9\xff\xb8\x1c\x6e\xeb\x40\x00\xae\x50\xb6\xb5\x65\xee\xaa\xa9\xc7\xd6\x5f\xfd\xea\x8e\xdb\x6e\x23\x7f\x1e\x84\xff\xb5\x70\xeb\xd6\x60\xb0\x26\x16\x4c\x94\xec\xd8\x10\x0e\xd5\xd4\x84\xfe\xea\xcc\x5c\x73\x4d\xc0\x15\x29\x8f\xb8\x92\x25\xdb\xd7\x87\xeb\xc7\xdc\x36\x73\xf3\x2e\xf7\xb5\xae\x91\xdb\x77\xb7\x08\x65\xe6\xa2\x42\x2b\xef\x09\xfb\x66\xce\x5d\x71\xc5\x1a\x66\xf2\xf2\xdc\xb5\x63\xc6\xd4\xa4\x53\xa3\xaf\x3c\xdb\x18\x18\x52\xe2\x6b\x82\xaf\x7c\x8d\xca\xf2\x6a\xf2\xe5\x7b\xef\xbd\xf7\x5e\x63\x23\x98\xc9\x45\x80\x67\x9e\xc9\xbd\x67\xf7\xdb\x8d\x02\x86\x19\xd3\xa7\x83\x79\xda\xb4\xee\x5a\x30\xd7\xd5\xa4\x53\xb9\x9f\xfd\x3e\x3d\x66\x4c\x1a\x1f\x69\x6a\xaa\xaa\xaa\xae\xbe\x02\x4c\x93\xe5\xc2\x42\xc0\x4d\x4d\xf5\xf5\xb0\xb9\xa2\xa2\xa2\x42\x92\x24\x69\xee\xdc\x8a\x8a\x27\x60\x8f\x1a\x33\x37\x5d\xca\xff\xab\xaf\x27\xd7\x36\x34\x4c\x33\x2e\xbc\x82\xd5\x4d\x71\x3a\xbb\xe4\x12\xbd\x3e\xe8\x4b\x55\x06\x1c\x57\x80\xd9\x0f\x47\x9d\x25\x7a\x7d\xc0\x9f\xd4\x87\xcc\x92\x41\x98\x07\x66\xf0\xe5\xae\xaa\x05\x73\x6d\x4d\x3a\x85\x1f\x26\x5f\x82\x39\x77\xd5\xe4\x7a\x97\xc5\x20\x28\xe1\x68\x59\x9d\xcb\xa2\x07\x3e\x62\x5a\x10\xaa\x77\x19\x0b\x81\x2b\x88\xf8\x55\x4f\x3b\xcb\xe3\x41\xe4\xab\x33\x67\x1a\x1b\x77\x5f\xdf\x80\x81\x31\x58\x7d\xa2\x52\xf2\xfe\x45\x04\xe8\xf4\x69\xb5\x7d\x16\xf4\xb6\xcf\x02\x24\xa3\x10\xaa\x47\x13\xd0\x95\x68\x37\xba\x1f\x9d\x40\xa7\xd0\xeb\x79\x36\xaa\xfc\x3a\x51\xc4\xce\x87\x04\x75\x46\x10\xf3\x43\xff\xf5\xa3\x08\x05\x1d\x11\x18\x5e\x6a\x80\x58\x0b\x34\x63\xaa\x25\xe3\xc4\x14\xf5\xee\xb7\x7b\x9b\x77\xd8\x1b\x40\x9d\x8e\x95\x43\xd0\x0c\x94\xc8\x9f\x1a\x07\xc8\x5a\x40\x1a\xfe\xbf\x9f\x64\xd7\xee\x10\x93\x09\x1a\x5f\xa0\x70\x27\x69\x30\x41\x3e\x81\xd2\xe5\x72\x18\x7f\x16\x8f\xf8\x42\xb1\x88\x37\xc2\x58\x2b\x2a\x8a\xad\xb8\xc0\x26\xb9\x9d\x30\x27\x1e\xf6\x85\x55\xdf\x0b\x47\x47\x35\x1f\x12\xf1\x40\xd0\xf1\xed\x76\x6c\x83\x42\x9b\x45\x62\x26\xcf\x83\x64\xa9\xea\x63\x62\x3c\xad\xc3\x16\x0c\xa9\xf7\x36\xda\x58\xe3\x10\x11\x5e\xd6\x71\xa3\x0a\x84\xa5\x15\x9c\x75\x24\xa7\x8b\x56\xc2\x78\xe3\xa8\x02\x01\x5d\x84\xad\xa3\x9a\xef\xb7\xd3\x87\x8c\x2f\x64\xbf\xf9\x10\xf7\x10\xf5\x21\xbe\x46\xab\xfa\x90\x8f\x8c\x23\x0a\x68\xd4\x41\x22\x3e\x3f\x9c\x2b\x8b\x06\xac\xb8\x40\x2c\x09\x0b\x6b\x2e\x19\x57\xaf\x8f\xd4\x14\x7b\x23\xf1\xc0\xc6\x32\x3f\x2c\x2b\x60\x1d\x0f\x87\x63\xf4\xfa\xa6\x86\xa4\x48\x16\xf3\x06\xf1\x4a\x9d\x81\xc1\x73\x7f\x0b\x1c\x6f\x08\x94\x2c\x1f\xde\xd0\xe6\xb4\x17\xea\x2d\xe0\x30\xe8\x0d\xf7\x1c\xb0\xe8\x39\xbc\x66\x17\xbb\x4a\x67\x34\xc0\xaa\xda\xfc\x2d\xc6\xab\xbe\x79\x0b\x58\x58\x0b\x1c\x07\x53\x01\xe9\xc0\x9c\x5e\x04\x31\x24\xc1\xb2\x02\x19\x7e\x73\x49\x57\x8c\x0c\xfd\xfa\x62\x33\x8a\xa1\x61\x68\x0a\x9a\x81\x96\xa3\xab\xd0\x3e\x74\x50\xeb\x87\x43\xc1\xa8\x3a\xfa\xe5\x42\x29\xda\x0b\xd3\x7e\x37\xdf\xed\x0a\x79\x44\x6e\x75\x2c\xab\xd0\x6e\x37\x9d\x82\x74\x28\x69\x66\xe2\xf9\x6d\x94\x9a\x41\x17\x47\x3b\x60\x21\x1a\xb2\xc6\xad\xa9\x78\x4c\xa4\x3d\x38\xdd\xe5\x1a\xcd\xa3\x49\xa6\xfb\x26\xf0\x34\x80\xcf\xdf\x4f\x87\xbf\x4a\x34\xfe\x0d\x4c\x4e\xbe\xc9\x21\x06\x64\x9b\xcf\x5b\x07\x4f\x5d\xc9\xc7\xe2\xe7\xff\x34\xa8\x35\x5c\xac\xd4\x0f\xb2\x0d\x1e\x3f\xaa\x6a\xc0\xc0\xc1\xd1\xa2\x01\xbe\xf1\x45\xb6\x61\x1d\xe3\x06\xc4\x21\x2a\x76\x6c\xb7\x55\x59\x9b\x2b\x94\xe1\xc5\xd5\xc5\x85\x65\x70\x9d\xd9\x58\x5c\x6d\x30\xec\x3c\xe0\xae\xb5\x54\x1f\x38\x80\xaf\xac\x2c\x19\x9a\x49\xea\x76\x1d\x08\x17\x4f\x88\x37\x91\x8a\xaa\x41\x55\x55\x83\x98\xc7\x06\xc4\x66\x77\xac\x6c\x49\x2f\x5d\xd0\x60\xa9\x1b\x5a\x6e\x97\xb9\xaf\xf1\xa5\xb3\xa4\x4d\x43\x22\x21\xfd\x39\xff\xe4\x79\x9f\x35\x0c\x74\x19\x25\x93\x3b\xb0\xaa\x58\x89\xb6\xd5\x0f\x74\x9a\x64\x4b\x91\xcb\xb6\xba\x34\x52\x0a\xa1\x95\x7b\x1c\x6b\x74\x8b\x7e\x3d\x31\xec\x2f\x58\x2f\xc4\x5e\x71\xed\x63\x8a\xfd\xb5\xa4\x14\x62\x45\xe4\x51\xf8\xaf\x8f\x37\xd7\x25\x6a\xab\x73\x57\xbb\xee\x28\xa8\x1d\x08\x3f\x51\xdf\x5c\x4d\xfe\x67\x75\x4b\x66\xd7\x9a\x6c\x63\xba\x64\x51\x91\x28\x56\x9b\xf0\xc9\x4b\x3e\x1c\x83\x4c\x17\x91\xf0\x15\x8f\x68\x3b\x6f\x41\x08\x6c\xb2\x5a\x40\x76\x3e\xa8\x44\xb9\x58\x82\xb6\x65\xb5\x97\x01\x89\x17\x34\x34\xb6\x54\x0b\x28\xc9\x66\x36\x99\xb0\xa5\x7b\x16\x9f\x04\x3f\xc8\x90\x92\x64\x5e\x6a\xfa\x73\x7b\x82\x64\x0e\xbc\x77\x3b\x00\xb2\x58\x1a\x26\x15\x2f\x62\xe3\x3a\x30\x7c\xfd\x98\xc1\xa3\x9b\xa8\x03\xc3\xb3\x62\x6c\xfc\xd4\xa6\xe8\xe7\x2f\xe8\x6a\xc7\xd6\xea\xb6\xbc\x90\x84\x07\x0c\x1e\x1d\x3e\x4e\xee\x79\x2d\xd1\xbe\xf4\xc0\xed\x4b\x1f\x2d\x9e\xd4\x60\xb1\x0c\x5f\xc4\x67\x0c\x1e\xfd\xf9\x63\x3a\x6c\xe8\x30\x78\x74\xdf\x2f\x0e\x96\xcd\xbc\xf5\xd8\x57\xfb\xee\x04\xce\x2b\xda\x4b\x6a\x6b\x4b\xec\xa2\x6d\xfb\x2c\x58\xa6\xc3\x06\x6d\x3f\x5b\x5f\x3e\x24\xa4\xa0\xd1\x08\xb1\x7d\x89\x8f\xeb\x21\x4f\xcd\x68\x81\xde\xdc\xa5\x03\x0a\x93\xb6\x81\xfc\xff\x91\x31\x56\xcb\xca\xf0\xdc\xbf\x98\x15\x65\x3f\xda\x3d\xeb\xae\xe9\x03\xd8\xce\x9e\x8c\xde\x8e\xff\x71\xa4\x69\x65\x13\x0c\x9e\xf8\x1f\x33\xfa\x58\x3e\x73\xf0\x3f\xf8\xeb\xa9\xeb\x5a\xe6\x2d\x8f\x93\x2c\xc9\x68\x19\xdf\xfe\x1c\x58\xe6\x92\x7b\xd8\xa3\x1d\xff\xbf\x19\xef\xc5\x38\xe6\xb2\xbd\x7a\xae\x34\x9a\xa1\x71\x17\x52\x11\x6a\xd5\xd0\x9e\xfe\xd3\x35\x04\xa2\x4a\x34\xc0\x0b\x5c\x0f\xaf\xa0\xd6\x40\x42\x3d\x1c\x10\x69\x6d\x1d\xa7\x08\x54\x79\x89\xbe\x1d\xa6\xa9\xbf\x3b\x77\x0e\x3a\x07\x08\x06\xf2\x63\x83\xc0\xac\xb4\x99\x3a\x34\x02\x07\xaa\x70\x84\x64\x9b\x79\x74\x09\x64\x4a\x46\x9b\xdb\x20\x69\xb2\x1d\xc2\x54\x95\x93\xa3\xb7\x7e\x87\x9b\xf9\xcb\x3a\x3d\xc6\xfa\xdb\x33\x26\x5b\x77\xfb\x84\x4d\xeb\x26\x30\xcf\xd0\xd7\x3c\x14\x49\x24\x22\x0f\xd9\xfa\x61\x19\x57\x50\x4b\x47\x04\x1a\xe4\x10\xd2\x20\x5d\x18\x9f\x3a\x72\x0a\x36\xf5\xb7\x96\xea\x51\xab\xe1\xef\xb2\x41\x61\xb7\x0e\x5f\xbb\xa9\xee\x2d\xf2\x67\xb0\x9c\x09\x4e\x58\x34\xbe\xd6\xb2\xde\xb2\x73\xd8\x0d\x27\x9f\xbe\xa9\xf5\x06\x3d\xbf\x81\x37\x74\xff\x27\x1b\x15\x78\x7b\x45\x6c\x74\xb9\x04\xd2\x3b\x67\xc0\xa2\xf7\x94\x0e\xab\x5c\x61\xb1\xb4\x95\xd7\x3c\xbd\xff\x8e\x57\x06\x94\xb5\x09\x7a\x3d\x53\xfe\x9f\xac\x58\xfa\xeb\xe1\x4d\x68\x1e\x42\x34\x0f\x26\xac\xd1\x89\x02\x67\x37\x61\x21\xa8\x49\xb6\xfc\xd2\xaf\x8d\xa2\x4d\xb6\x68\x4c\x9c\xb2\x24\x30\x34\xc3\xcd\x6c\xd2\x82\x02\x41\x9a\x57\x55\x46\x4a\x45\x1a\x65\x1b\xf4\x83\x2b\x47\xcc\x9b\xcb\x66\xb7\x6c\x9e\xd7\xb4\x6c\x6e\xc7\xa1\x49\x38\x31\xe2\xea\x1b\x46\xf2\xa2\x30\xa7\xda\xcb\x25\xee\x9f\xfd\xfd\x93\xbb\x7e\xbb\x7b\xca\x5e\x05\x17\x80\x9e\x5b\xcf\xe9\x38\xbc\x91\x73\x15\x7b\xeb\xa7\x0e\x1a\x40\x7e\x40\x3e\xec\xb1\x84\xff\xf4\x64\x81\x5b\x57\xaa\x03\x6c\x58\xd8\xb5\x9b\xf2\xf8\x51\x7e\x3e\x98\x0a\x47\xf1\xf9\xe5\x9b\x9b\x96\x1f\x99\xbb\x6a\xf3\xee\x57\xad\x2b\x8f\xcf\x8b\x63\x48\x06\x62\x83\xa6\xbe\x78\xe2\x5e\x30\x1c\x1c\x9a\x11\x6b\xf9\xc2\x02\xae\x20\x77\xb7\xd3\x19\x75\x83\x3e\xda\xb4\x7e\x34\x84\x61\x66\x4f\x11\xdd\xac\xc7\x05\x35\x85\x85\x46\xfd\x84\xe9\xea\x23\xa1\x16\xbc\x6f\x6f\x26\x53\x7b\xed\xb6\xe8\xba\x5e\x08\x95\x20\x84\x24\x8b\x19\xa8\xd6\x9f\x0f\x56\x03\xf0\xe5\xc0\x45\xc5\x64\x22\x0d\x79\xa5\x7d\x11\xa4\x53\x7a\x88\x82\x83\x6f\x3d\x3d\xfb\x93\xc5\x06\xc3\xcf\x0d\x6e\xc3\x92\xdc\xe1\x48\xf2\xcc\x45\x94\xc9\x46\xf0\x8c\x25\x9a\xdf\xe2\xdf\xcc\xea\x7e\x05\x67\x3a\x73\x9d\x3c\x3a\x4d\xfe\x35\xeb\x37\x8b\x0d\x6e\xc3\xcf\x0d\x34\x6e\x36\x03\xe8\x4c\x92\xc6\xa5\x7e\x8b\x3f\x99\x7d\x21\x43\xe3\x76\xe6\xed\xc8\x08\xd5\x43\x96\xe6\x39\x3a\x04\x24\xf4\x92\x73\x52\xe2\x06\x09\x85\x82\x55\x38\xe9\x67\xe2\xb1\x74\x33\xcb\x8f\x69\x5b\x52\x49\x9e\xdc\x3d\x77\xd3\xd6\x1f\xcd\xc4\x5b\x1b\xba\x9f\x8d\xee\x99\x00\x2c\xf9\xc7\x7f\x5d\xfd\xc2\xda\x7a\xa1\xb5\xb6\xd9\x5c\x6a\x72\x0d\x1c\xb1\x70\x31\x8f\x66\xb5\xb5\x4c\xcd\xed\xbb\x7a\xc6\xa9\x6d\xd9\x89\x78\x70\xaa\xeb\x9f\xed\xcb\xa5\xa1\xef\x93\xbf\xcf\x7a\xe0\xcd\xf5\x5c\x2c\x1a\x8c\x0c\x9a\xd5\x10\x36\x5f\xa2\x0f\xad\xec\x45\xd3\xa3\x08\xd5\x31\x8a\xa1\xa9\x41\x5c\xe2\x38\xbd\xc2\x6a\xb5\xa1\x2c\x95\x79\xc0\x62\x3f\x16\x1d\xc1\x2a\x88\x6a\xd8\xb1\x02\x85\xf0\xfa\xf6\x0b\x75\x26\x93\x6a\x00\x6b\xa0\xf7\xbf\x36\xa3\xd1\xac\xa9\xd8\x64\x9f\x4e\xf1\x9b\x17\x02\x3a\x8f\x2a\xc7\x2a\x5e\x7f\x79\xc8\x59\x22\x49\xbe\xf0\xd8\xaa\xca\xb1\x61\xbf\x43\x8e\x3a\x43\xe5\x7e\xaf\x32\x76\xba\x16\x18\xa4\x17\x95\xf9\x38\x95\x55\x63\xc3\x3e\x49\x2a\x51\xe3\x7c\xf3\x16\x1a\xea\x2f\x0f\xad\x1a\x9b\x01\xd4\xf3\x3f\x33\x76\x55\x17\x1a\x56\x9b\x1c\x29\x7a\x83\x5e\x51\x99\x8e\xbf\xf3\x22\x4b\xb2\x90\xf5\x7a\x9c\x1e\xc9\x64\x11\x5d\x6e\xaf\xcf\xe5\x12\x2d\x26\xc9\xe3\xf4\x78\xa9\x2f\x75\x41\xa6\x53\x0b\xf5\xba\xb5\xd0\xcb\x22\xba\x5d\x1e\xa9\x73\xec\x2a\xe8\x24\x99\x9e\x63\x15\x63\x19\x35\x61\x64\xd2\x57\xe1\x2c\x2e\xaa\x57\x6e\x6b\xff\xce\x0b\xad\xcd\x53\x7d\x15\xa7\x8e\xc3\x03\x8e\x80\x35\x6e\xd5\x43\xc0\xaa\x07\x1d\xfa\x1a\x65\x79\x04\xe8\x7c\x16\x3a\x71\x26\xcb\xa3\x0b\x59\x16\x75\x67\x71\x06\x67\x72\x9d\xbd\xdc\x28\x9d\xb4\x1f\xb4\x20\x09\x21\x3d\x68\xac\x4f\x16\x5b\x38\x2e\x06\xec\x58\x10\x03\xd6\x18\x6b\x63\x10\x0e\x2e\x25\xbf\xbf\xf7\x67\x9a\xbc\xf9\xd9\x73\x0c\xb7\x71\xf9\x0f\x72\xe8\x67\x30\xf7\x6d\x7c\x6d\xee\xe3\xe5\x1b\x7b\xa4\x50\x0e\xdd\x4b\x7e\xbf\x14\x3f\xc0\xa0\xb7\xc9\xfd\x97\xa4\xad\xa8\x27\x6d\x6a\x97\xa1\xb6\x34\xb5\xb9\x45\x69\x0b\x83\xa8\xb6\x70\x4e\xd3\x2b\xa0\xa8\x65\x53\x6e\x8f\xc1\x6d\xf8\x8c\x74\x74\xe2\xe1\xaa\x03\xde\xdd\x64\xb1\x3a\xe0\x09\x93\x4d\xcb\xc3\x39\x32\xca\x61\xa5\xb1\x7a\x22\x69\x71\xa2\xb6\x3c\xdf\x92\x80\xd8\x29\xa8\x43\x1d\x49\xca\x7e\x46\x66\x35\x9b\x61\x3e\x5a\xc5\xa8\x95\x30\x0f\x5a\xa2\xed\x11\x09\x04\x29\x92\x31\x8e\xc7\xfc\xbc\x9c\x47\xdb\xe6\x29\xa8\xab\xec\x07\x39\xe4\xc7\xb2\xa0\x44\xe9\x40\x92\x2b\x34\x18\xfc\x89\x70\x04\x86\xfc\xe2\xf6\x86\x25\xa3\xdb\x63\x75\xfe\x9a\x82\xe2\x86\xa9\x1b\xc7\x77\x9c\x58\xf8\xfe\xbd\x27\xc7\xd5\x7a\x26\x9a\x7d\xb0\x93\x5c\xbc\xf5\x1f\x7b\xa7\xdc\xf2\xea\x92\x29\x37\x2f\x9a\x52\xdf\x50\x56\xef\xee\xb8\x6e\xdc\x5a\xa5\x65\xfc\x94\xa9\x23\x6a\x0b\x98\x47\x57\x8e\x9e\x34\x00\x0a\x25\x3f\xbb\xdd\xed\x95\x47\xd4\xb4\x31\x19\x3e\xe4\x2b\xf5\x18\x0d\x33\xbe\xdc\xff\x52\x24\x35\x67\xec\xb6\x31\xd7\x7a\xc7\x2d\x99\x5a\xb2\xf2\xf1\x8e\x43\x7f\x9d\xd3\x92\xbc\x33\x18\x86\x3b\xef\x03\xd8\xbf\xe4\x8d\x3b\x66\x2a\xcd\xf3\xe6\x5f\xbb\x76\x7f\xea\xb5\xb9\x63\xcb\x1a\x8b\x8b\xe4\xca\x86\x25\x6d\x16\xeb\x95\x3f\x60\x19\xb9\xac\xc0\x53\xc9\x5d\x51\xe3\x00\xc7\xa0\x4b\xfa\x82\x29\x54\x67\x9f\x88\x56\xe1\x68\xa2\x67\xf9\x2a\x24\xc9\x69\x25\xaa\xe1\x91\xd8\x29\xf2\x2d\xe3\x03\x89\x1a\xae\x72\x6a\x19\xc9\x0e\x4d\xf6\xa7\x7b\xa1\x8b\x69\x33\x17\xe2\xdf\x82\x53\x7f\xe7\xe7\xa1\x70\x89\x9e\xc5\x35\xe1\x94\x15\xec\xe2\xac\xa8\x21\x30\x24\x3e\x76\x0b\xb6\xcc\x9d\xef\x2b\x89\x79\x60\x42\xc3\xdc\x36\xb9\x2e\x3a\x64\x4c\x76\xc2\x82\xa7\x96\x32\xec\xac\x13\x2b\x9e\x9d\x65\x2f\x68\x2c\x5b\x33\x6d\xed\x9d\x3f\x58\xbc\xea\xaa\x2a\x5d\x48\x2a\x0d\xa7\x6b\xdb\xcb\x96\xdd\xb9\xf8\x12\x1e\x83\x4f\x7f\x38\xc8\x60\x8c\x78\xb1\xb1\x00\x87\xab\xcd\xe6\xf0\xd0\x94\xc1\x67\x5f\x3b\x56\xb0\x74\x4c\xf5\xe9\xcc\xde\x52\x37\x57\xdf\x76\x73\xf5\xed\x0b\x37\x0c\xab\x59\xf5\xcc\x7c\x58\xfe\xd4\xea\x2b\x3d\xce\x15\x63\x87\x9d\x58\xb7\xe4\xe8\xb2\x0d\x8e\x39\xf5\x33\xea\x5a\xa3\x9e\x7d\xf8\xf7\x97\x6e\x78\x60\xf2\x3a\x5e\x0d\x43\x34\x7e\x19\xf3\x6e\x38\x51\x85\x43\x01\xc9\x66\xc1\x42\x20\xd6\x0c\x36\x8b\x09\x87\x02\xc1\x2a\x6c\x69\xc6\xf1\x40\xcc\x0f\x6c\x36\x6f\xc7\xaa\x9d\x18\x6a\x15\x4b\xb6\x6e\xd8\xb7\x6f\x03\xec\x58\xfc\xfc\xf5\x3f\x53\xfb\xb6\x1c\xea\xe9\xe5\x18\xd5\x85\x9d\x7d\x37\xf4\x9c\xa6\x93\xbf\x93\x37\xc9\xdf\xa7\x8f\xbb\x1e\x1e\xba\x6c\x7c\xd0\x6f\x3f\x21\xa2\x68\xf9\xc8\x09\xda\xdb\x71\x3e\x35\xc0\xf6\x9a\xf5\xdb\xfd\xd0\xfb\x9e\x85\xbd\xef\x66\x1f\xbf\xe4\x8d\x40\xf2\x8f\xee\x19\x43\xdc\x72\x49\x62\xa8\xfc\x47\x48\xaf\x9e\x4c\xc8\x86\x9c\xa8\x82\xa2\x72\x05\x82\x4a\x0b\xa8\xb5\xdf\xa2\xb6\x8d\x68\x5c\x89\x72\x10\x10\x24\x99\xa5\xa0\xfc\xa2\xa4\x99\x3c\xd3\x71\x43\x31\xb2\xa0\x62\x94\x4c\xa4\xd2\x51\xb5\x1b\x55\xeb\x0d\xb2\x20\x75\xce\x46\xe9\x69\xe3\x01\x47\x20\x9a\x77\xc5\x64\x48\xc5\x63\xf8\x02\xf9\x69\x49\xc8\x79\x7a\xe0\xb0\x5d\xa7\x4f\xef\x5a\xfb\xd8\x83\xcf\xda\xea\x60\x35\x14\x93\xe2\x2b\x96\x38\x38\xee\xf4\xae\xc6\xa6\x13\x66\x83\x64\x76\x84\x6c\x27\x66\x9d\x06\x1d\x34\x92\xf3\xe4\x26\x72\x7e\x4c\xdb\x40\x72\xbf\x2d\xf0\x8a\xdc\x7d\xf4\x14\x39\x0f\xc2\xa9\x35\x0b\xae\xa3\xa6\x95\x90\x85\x27\x26\x7d\xac\x19\x46\x06\xec\x50\x30\x63\xc1\x29\xc8\xb6\x15\x77\x15\x9d\x26\x5f\x9f\xbe\xe5\xaf\x93\x5a\x6e\x83\xec\xae\x45\xb7\xff\x04\x74\xa7\x9d\xa4\x5b\x4e\x98\x0a\x7c\xc0\xce\xd9\xb1\xeb\x34\xd0\xe7\x82\x70\x6a\xee\x0f\x5b\xe6\x91\x72\xf7\x0f\x3e\x04\x01\xd6\x80\x90\x7e\x5a\x49\x28\xd9\xac\x92\x50\xbc\x64\x55\x45\xff\x7d\xd5\x02\xad\x39\xe5\x68\x64\x1f\x02\x57\x8f\x3e\x59\xec\x01\xa3\x62\x78\xaa\x0b\xc6\x97\xf0\x08\x87\x2e\xc7\xb7\xb2\x26\xd2\x62\x33\x84\x8b\x59\x49\x16\x7b\xf4\xc3\xac\xa6\xbb\xf5\x0d\xe3\x42\x72\xf7\x52\x39\xc4\x0d\xe3\x14\x3f\xab\xf8\x95\xff\xf6\xda\x73\x59\xbb\xd7\x6b\xc7\x59\x3b\x1c\x57\x23\xe7\xd0\xc8\xa5\x23\xb3\xae\x45\xfa\x93\xe0\x81\xc9\xe0\x39\xa9\x5f\x22\x43\x41\x3f\xfd\x2f\x2e\x84\xac\xec\xf3\xc9\x24\xeb\xaf\xaa\xc2\x57\x96\x78\xbd\x25\xde\xdc\x8c\xdc\xe1\x6c\x72\xe4\xc8\x64\x56\xfb\xc5\x33\x56\xad\x84\x9f\x8e\x5e\xdf\xd8\xb8\x7e\x34\xa9\x5f\x48\xfb\x85\xbd\x3a\xc4\x7d\x8d\x0a\x50\x15\x1a\xaf\xed\x36\x09\xe4\xbf\x1d\x97\x88\x6a\x38\x56\xf1\x80\x12\xce\x6f\x23\x08\x68\x8a\xac\x80\xc4\xc6\x63\xcd\x18\xd4\x89\x81\x66\x44\x19\x0a\xa2\xa8\x26\x3f\x1a\x80\x0e\x38\xc3\xf1\x18\x92\xe3\x31\x89\x7b\x3a\x16\xce\x0d\x0a\xc7\x62\x61\xfc\x42\x18\x74\x72\x77\x99\xea\x66\x6e\x98\x4a\x3e\xf8\xe1\x49\xf2\x8b\x47\x65\xe6\x97\xaa\x47\xf7\x55\x53\x21\xfa\xc3\x5d\x5f\x9d\x58\x0c\x6b\x63\xe1\x9d\xd6\x9d\x1f\x92\x77\x1e\xfa\x27\x59\x76\xc5\xf3\x6a\xe8\x2e\xeb\xce\x0f\xa1\xe6\xe8\x3f\xe0\xf6\x2b\x4e\x87\x63\xf8\x77\x6d\xf1\x78\x5b\x7c\xf2\xe4\x89\xb1\x50\x38\xf6\xbd\xa3\x8f\x92\xf7\x4e\xf6\xb8\x17\x3d\xfa\x25\xec\x0a\xc5\x26\x4d\x7a\x88\xbc\xf3\xd1\x4e\x30\x9c\x8d\x85\xe9\x15\xd4\x7c\xb4\x93\xfc\xf3\x6c\x0c\x21\x1e\x15\x5c\x44\xec\x3f\xf2\xdf\xd6\x83\x2a\xd0\x3a\x8a\x29\xce\xc8\xb6\x64\x22\x14\xa4\x7b\xa5\xab\x30\xd8\x45\x55\x7c\x32\x6a\x93\x60\x28\x39\x75\x2a\x99\xa0\xfd\x0a\xcf\xe4\x55\x5a\x29\x6b\xa2\x0a\x34\x80\x2c\xde\x61\xf7\xb3\xe9\x18\x85\x4f\xd2\x20\xc9\x1d\x76\xc9\x21\xf0\x0e\x25\xca\x87\xf2\xd4\x6b\xc9\x44\x5a\xca\x77\x3c\x74\xb9\xa2\x6f\xa3\xb0\x66\x2a\x2e\x4a\x72\x33\x47\xd5\x86\x8c\x9f\x71\xd8\xb1\x86\xe6\x8f\x99\x53\x6b\xd6\x1d\x56\xea\xc8\x0d\x7e\x26\x12\x2c\x2c\x0b\x91\xb7\xee\xb7\x16\x9b\x1b\x37\x8d\x1c\x20\xda\xc7\x2c\xda\x15\x34\xc9\xc5\x46\xa5\x6e\x90\xcf\x1e\xbf\xcf\xd5\x70\xfe\xde\xdf\x1d\xbc\x13\x3b\xec\xb5\xe4\xf5\xb5\x91\xc2\xc2\xf2\xd6\x29\x53\xc7\xfb\x2c\x82\xd3\x62\x66\xbd\xad\x4d\xc5\x99\x69\x11\x86\xbd\x4e\xaf\x0b\xe0\x71\xa9\xf1\x0f\x07\x12\xba\x51\xb5\x85\xbe\x47\x7d\xe5\xa9\x35\x93\x66\x7b\x37\x37\xf9\x4a\x1f\x1c\x3f\x7a\xe7\xcb\x3c\xe6\xab\x4a\x07\x37\x8f\x89\x0c\x1d\x7f\x7f\xd3\x18\xc5\x34\xfb\x58\xf7\x9d\x2b\x57\xdd\xfe\x01\x7b\x2d\x79\xc6\x01\x3f\x1e\x5c\xdb\xbd\x6a\xac\xae\xcc\x85\x05\x81\xd9\x3d\x8f\x4c\x33\x70\x30\xe7\xc3\x50\xf7\x3f\xc2\x47\x6e\x70\x9b\x9c\xa3\x8b\xc7\xce\xcb\xa4\xc8\xbd\xa5\x2d\xb7\xfc\xe0\xd8\xc3\x80\xcb\x07\xb4\xdb\x6a\x92\x05\x9c\x3f\x98\xf0\x8a\x2c\x8b\x45\x31\xec\x75\x4b\xce\xaa\xbd\x43\x8a\xd6\xfa\x0b\x0b\xb1\xe1\x6d\x2c\x98\x92\xc3\xef\x19\x17\x0c\x64\x0a\x17\x5b\x0b\x83\x1f\x4f\x4b\x2f\xd8\xe2\x1e\xe1\x6f\xde\x6c\x86\xb7\x97\x8c\x5d\x90\x7b\xce\xca\x5b\xb6\x5d\x79\xcb\x82\x61\xf3\x86\x2f\x27\x6d\xe6\xe6\xd9\xb3\x32\x07\x48\xf7\x0b\x57\x96\xd5\x81\xb1\x8f\xef\x4f\xed\xff\xdc\x28\x45\x71\xe2\x11\xc4\xfb\x77\x66\xa1\x7c\xef\xa7\x76\x74\x91\xef\x0c\x49\x45\x12\xea\xe0\x35\xaa\x04\x8a\x05\x13\xd6\xbe\xa0\xec\xc7\xb2\xc4\x06\x8a\xd3\xcd\x38\xdd\x0c\xa2\x35\x60\x65\xac\xef\x98\x1e\xde\xf1\xc0\xa9\x67\x6f\xb8\xed\xa8\xf1\x0c\xd7\x14\xaf\x6b\x31\xb8\x53\xd1\x39\xf8\x97\x6f\x9b\x8e\xf6\xf8\xbf\xc9\x36\xc7\x54\xff\x64\xb4\x26\x0d\x2b\x8a\x2a\x79\xb3\x17\x4f\xce\xdd\x9b\xfb\xde\x24\xce\x65\xe5\x2b\xfd\xfe\x4a\xde\x26\xf3\x15\xb0\x07\x44\x3c\x6f\x0a\xe7\xb4\x72\x55\xfe\xce\xaf\x11\xb6\xdc\xf7\xa3\x3f\xbe\xf6\xf2\xff\x9c\x38\x94\x69\xdb\xb4\x6e\xc0\xb0\xc1\xe1\x7d\x97\x7b\xb4\x3f\xf5\xce\x6b\x4d\xba\x42\x1b\x6e\x69\x61\xcd\x46\x5d\xe3\xab\x3f\x7b\xf7\xd5\x26\x9d\xc9\xc4\x05\x8a\x07\xb2\x26\x93\xbe\xf1\xa7\xcc\x99\x0b\xaa\xd8\xea\xe9\x57\xb8\x0e\x2e\x8b\x7c\xa8\x41\xb3\x78\xcc\x03\xa4\x2b\xfd\x18\x1d\x69\x4b\xa7\x8c\xc3\x26\xe8\xe9\xec\x7b\x98\x1d\x53\x3d\x17\xcc\x39\xca\x2d\x79\x68\x15\xf9\x82\x3a\x6c\x26\x78\x77\xcf\xa7\xbb\x21\xbb\xfb\xd3\x3d\x64\x80\x7a\x7d\xc8\x64\x03\xcb\xaa\x43\xd4\xc1\xdc\x4c\x2c\x34\xce\x17\xab\x0e\x75\x51\x60\x6f\x2e\x63\xb2\xed\xfe\x14\x86\x77\xdf\xbc\xe7\xd3\xdd\x36\x13\xa3\x4d\xe2\xd1\xa1\x55\xcc\x2a\x6d\x0f\x08\xdb\x6f\x0f\x48\x33\xb5\xe0\x41\x97\x5b\xc7\x72\x1a\x56\xb5\xd0\x03\x58\xdd\x00\xb1\x9e\xa0\x6f\xbb\x8a\x24\x7b\x0d\x75\x68\x58\x1e\x6f\xfd\xb2\x11\x4d\x91\xc7\xf9\x86\xd3\xeb\x75\xbe\xe1\xf4\x10\x69\x60\x72\x77\xab\xd7\xdb\xba\x23\x39\xd0\x91\x96\x3c\xae\xd9\x4e\xaf\x23\x25\x79\x9d\x73\x9d\x1e\x29\xed\xc0\xa3\x06\x25\xc9\xd7\xc9\x41\x52\xda\x51\xd4\xf2\x62\x72\xd0\xd6\xbd\x1d\x5d\xef\x76\xec\xdd\xdb\xc1\x0e\xe8\xd8\x8b\x9f\x5a\xa3\x3e\x45\xfd\x21\x17\x92\x03\x13\x89\x81\xc9\x0b\x92\xf4\x07\xd5\xef\x0f\xbd\xe7\xf5\x77\x27\x07\x0e\x4c\x92\x85\x0e\xc7\x93\x65\x03\xf1\xbd\x7d\x77\xef\xed\xcf\x5d\x88\x91\x9e\x5a\x11\x06\x3c\x10\x50\xff\xeb\xbf\xb1\xaf\xf0\x56\xf2\xc1\xad\x9f\x41\x9a\x9c\x26\xc3\xc8\x69\x48\xc3\x36\xbc\xf4\xd8\xfa\xee\xcc\xfa\x63\xc7\xd6\x33\x9d\xeb\x8f\xc1\xcb\x38\xda\x7d\x07\x8b\xba\x11\xd4\xe3\x23\x7d\xfe\xc7\xd4\xea\x20\xf7\xe2\x31\x8e\x42\x93\xd0\x5c\xb4\x18\xad\x40\x6b\xd0\x46\xb4\x0d\xed\x42\xd7\xa1\x5b\xd0\x01\x74\x0f\x3a\x84\x7e\x80\x1e\x42\xc7\xd0\xa3\xe8\x19\xf4\x1c\x7a\x01\xbd\x84\xce\x68\x58\xc7\x0c\xdd\x11\xca\xe4\xb5\xa0\x01\x5e\x3d\x34\xb9\xc6\xd0\x0d\xb7\x8c\x86\x7e\x20\x26\x54\x2f\x31\x2f\xdb\x02\x29\xf5\xd0\x60\x27\x44\x8a\xa3\x2b\xfa\x01\x02\x10\x82\x40\x2a\x06\xd4\x57\x4e\x5b\xa3\xbc\x00\x01\x39\x12\xe0\x83\x90\x4a\x47\x85\x50\x9a\x01\x19\xd2\x62\x00\x52\x5c\x1c\x02\x56\x59\x62\x02\x69\x30\x43\x3c\x29\x48\x56\xbb\x7a\x93\x6c\x4d\x5b\x65\xa8\x06\xc1\x9a\x8e\xf2\x91\x10\x27\x3b\xf4\x38\x12\xb5\x72\x42\x1c\x64\xb1\x1a\x2b\x4d\xc0\x28\x51\x3d\x4e\x32\x62\x48\x04\xa1\x05\x28\x1d\x5d\x01\xc8\x29\x1d\x72\xdb\xdf\x62\x5c\xf6\x97\x98\x80\xd3\x65\x21\xab\xac\x09\x2b\x59\x6d\x75\xcb\x41\xf6\x25\xbb\x8b\x79\xdb\xee\xf2\xd8\x5f\x85\xe0\xcf\xd8\xa0\xec\xb6\xc1\x0d\x96\x94\x05\x6e\xb2\xa9\xa1\xef\xc8\xc5\xc2\x73\xa2\xab\x3b\x0a\xbb\xc9\xb1\xef\x91\x63\xb0\xd8\x56\xd6\x3d\x03\xf0\xbb\xe6\xd3\xcf\x19\x2d\xf8\x28\xd9\xf2\x02\x2e\x23\x7f\xb4\x54\xe0\x47\x81\xcd\x58\xfd\x52\x37\xf9\x55\x0b\x6c\xb0\x0c\x24\x93\x60\x94\xae\x7b\x15\x07\x93\xc9\x3e\xd6\x64\x83\xfd\x19\x72\xe6\xde\x97\x1e\x3c\xca\x82\xee\x11\xff\x5d\x50\xfa\x9b\xdf\xb0\x6f\xbd\xc8\x33\x1b\x2c\xb9\x5b\xdf\x27\xff\x05\x69\x28\xc9\x5d\xbd\x17\xfe\x50\x36\x09\x22\x7f\xd9\xc5\x80\xa4\xfb\x15\xa7\x23\x23\x21\xd5\xdd\xf9\xe0\x83\x0f\x3e\xc8\x36\x0d\xd8\x51\xf2\x0e\x66\x1e\xd9\x3e\x8a\xc3\xdb\x1d\x45\x2c\xb9\x47\xaf\xb7\x17\xb1\xe4\x51\x9d\x4e\x0e\xda\xec\x76\x7b\xc0\xa9\x2b\x84\x31\x6c\x91\x5d\xaf\x87\xf9\x5c\x91\xdd\x51\xc4\xc2\x54\x60\x21\x6c\x86\x65\x06\x9d\x33\xe0\x70\x38\x1c\x01\x27\x5f\x48\xee\x86\x80\x64\x34\x91\xd3\x6c\x51\xf7\x5b\x30\x8f\xdc\x67\x61\xbc\xac\xde\xc0\x91\x3b\xf9\x57\x61\xc6\xcb\x3a\x0c\x9d\xaf\xbd\x66\xe9\x9a\xc8\x73\xad\x63\x96\x80\x81\xbc\x95\x21\x37\x7b\x21\x45\x1e\x66\xcd\x30\x8f\x9c\xe4\x39\xd8\x38\x08\x06\x1e\xf9\xe8\xf9\x93\x3a\x26\x09\x18\x2c\xc6\x93\x60\x2c\x20\xaf\xdf\x0b\xf5\x7f\xfa\x58\x47\xbe\x1e\xf1\x3a\x2e\x3c\xf7\x49\x39\x79\x85\xbc\x04\x71\xf3\x8d\xe4\xd3\x8f\x2a\x60\x6f\x17\x5e\xc5\x81\xc3\x68\xc1\xb0\x11\x58\x52\x43\x4e\xc1\x3f\x7f\x43\xfe\xd0\x7d\x1d\xf9\x3d\x78\x7e\xf7\xbb\x36\x58\x62\x60\xc1\x0c\x25\xb9\x7b\xc6\x33\xda\x7a\x09\xc5\xff\x37\x22\x0f\x42\xb4\xfa\xf7\x36\x86\x48\xb4\xbf\x21\xde\xd3\x3b\xf1\x1f\xa0\xe3\xe9\x9d\xdd\x7f\xdf\xf9\x34\xfb\xee\x63\x99\x2a\xe2\xad\xca\x0c\xac\x64\xa6\xee\x7c\x11\x16\x5e\x18\xb4\xeb\x85\x17\x76\x85\x9f\x84\x87\xab\x06\x0d\xaa\x22\xf6\xaa\xc1\x9a\xbc\xd9\xc9\x23\xee\x1a\x64\xa0\xcc\xde\xa5\x08\x01\x8b\x18\x75\xe0\x12\x8e\xc7\x38\x49\x56\x2f\xa2\x36\x04\x36\x14\xd1\x2e\x38\x25\xca\x0b\x29\x94\xe6\x05\x89\x39\x42\x7e\x4c\x82\x1b\xec\x6f\x41\xc7\xbb\xe3\x61\xfe\xac\xa1\xe4\xea\xdc\x2b\x2b\x67\x35\xaf\xc2\x29\xf2\xe0\x5a\x6c\x85\x2b\x4a\x4c\xe4\x43\x92\xd9\xb0\x88\x79\xe7\xa5\x13\x7b\x0e\xae\x80\x11\x6f\x3a\xc6\x0e\xe4\x96\x6e\x22\x3e\xf2\xd2\xb4\x29\xef\xc2\xdc\xb7\xae\x1f\x38\x7d\x75\xee\x25\x72\xf5\xb0\xe9\xb0\x03\xd7\x77\x35\xc2\x7c\x6c\x5f\x3f\x73\xd1\x46\xd2\x4c\x7e\x6d\xb2\xc7\x06\x4e\x94\xdf\x82\x91\x57\xde\xb9\xeb\xd1\xbc\x6c\xd0\x21\xf6\x5f\xd4\xf6\x57\x95\xe4\xa2\xc6\xf2\x43\x35\x24\xe5\x20\xa6\x02\x31\x39\x15\x2f\x86\x98\x44\x87\x2b\xd4\x9f\x51\x27\xba\x72\x2a\xad\x91\xd3\x09\x94\x1d\x4a\x4e\xc9\xc2\x82\x83\x3b\xb7\xbe\xf6\xd2\x6f\x6f\xbb\xed\xb7\x2f\xbd\x96\xdd\xc2\x1d\x3c\x07\xf8\xb3\xbb\xef\xfe\x0c\x30\xf9\x72\xfb\xdb\xf7\x6e\x79\xe4\x95\x73\x07\x0e\x9c\x7b\xe5\x91\x2d\x4b\x36\x3d\x36\xfd\x8d\xe3\xc7\xbf\x4a\xff\xe2\xb6\x3b\x3f\x7e\xec\xd0\x9a\x2d\x3f\x5b\xf7\xb3\xc3\xc7\xdf\x60\x37\x76\xe9\xea\x66\xdc\x76\xdb\x8c\x3a\xf6\xeb\x6d\x4b\x97\x76\x1d\xa9\x1b\xc8\xe4\x46\xdf\x78\xe3\xe8\x6e\xa6\xbc\x22\xb4\x7c\x79\x90\xd9\xc7\xde\x71\x70\x50\xf7\x84\x78\x6c\xe1\x32\x4e\x1b\x47\x1f\xd6\x21\x6e\x46\xef\x7e\x8b\x99\xff\xfb\x75\xe8\x6f\x5c\xf7\x01\xac\xf6\x43\x5a\xa1\xb2\xc5\x0f\xdc\x87\x7e\xfb\x2c\xbb\x9f\xfe\x90\x4f\xfd\xf6\x05\xaa\x7b\x81\xdd\x4f\x3e\xfc\x76\x37\xb7\xf7\x4f\x47\xba\xc2\x47\xfe\xb4\x75\x89\xe1\xfb\xab\x17\x8e\xae\x84\xb2\xe7\x6f\xef\xbe\xd5\xb4\xe7\xf8\x61\xfc\x91\xc3\xef\x77\xe4\x42\x6a\x44\x2c\xaa\xbf\xb9\x3f\xab\xbf\xf0\x43\xf5\x97\x4c\xa0\xee\xa5\xd4\x7d\xc0\xee\xf7\x1f\x39\xf2\xa7\x3f\x1d\xb9\xea\x95\x58\x30\xba\xfa\xfb\x83\x9f\xfe\xfc\xd6\xee\xdb\x07\xd5\x06\x7e\x8d\x10\x8a\x22\x74\xb1\x99\xd7\xf6\xce\x68\x3c\x6d\x0e\xca\xd4\x16\xa0\x5c\x6d\x95\xa8\x06\x25\x51\x1d\x6a\x42\x03\xd1\x10\x34\x1c\x8d\x42\xe3\xd0\x24\x34\x0d\xcd\x42\x73\xd1\x22\xb4\x0c\xad\x44\x6b\xd1\x06\x74\x35\xda\x86\x76\xa3\xeb\xd0\x8d\xe8\x16\x74\x3b\xba\x0b\x1d\x46\xef\x23\x64\x0d\x58\xf5\x10\xa1\xbf\xc9\x80\x43\x74\x84\x92\xf2\xe5\x47\x5a\x16\xfa\x1f\x2d\x70\xe9\x01\x8e\x50\x32\xf0\x6f\x0e\x35\x3c\xee\x48\x7f\x47\xa8\x9c\x54\x43\x85\x6f\x39\x22\x3d\x23\x2c\x0a\x7e\xe3\xc7\x29\xcd\x1c\x2d\xd4\x6b\x4f\x07\xbc\xa2\x61\xfd\x4b\x72\x3c\x5d\xc5\x87\x82\x26\xcc\xa3\xee\xaf\x73\x3a\xee\x9e\x0b\xaf\xe1\xdb\xf1\x83\x17\x5e\x1b\x17\xe9\xf9\xd7\x62\x5e\x62\x2e\x32\x2f\x31\xfb\xe9\x79\xb1\x79\xcc\x12\xf3\x92\x8d\x4b\xcc\x4b\x36\xe5\xcf\xdd\x03\xd7\x80\x7d\x2d\x38\xd6\x82\x7d\x0d\xfd\xcb\xbb\xbb\x9e\x89\xac\x7d\xe0\x72\xff\x2f\x46\xaf\xed\x7d\x70\x24\xb7\x77\xfb\x33\xcf\x6c\xdf\xf1\xf4\xd3\xe4\x6c\xb4\xb1\xb5\x31\xba\x6a\xae\x9b\x29\x1a\x3c\xc7\x97\xae\x0d\xa5\xc7\x8e\x49\x97\x96\x38\x82\xc3\xcd\x8c\x9f\x09\xeb\xfd\x26\xb7\x54\xe8\x4b\x27\x03\x3c\xba\x70\x33\x39\x01\xe3\x07\x32\xf7\x75\xcf\x23\x1f\x70\x25\xaf\xbf\x4e\x7e\xb9\x76\xed\x6d\xfd\xfe\xbe\x17\xac\x0e\x98\x82\x55\x41\xf5\x30\x06\xaa\x82\xc1\xaa\x40\xf5\xec\xaa\x60\x95\x7a\xcc\xaa\x0e\x56\xb1\x3f\x0b\x5f\xf6\x8f\x1c\x1f\xb3\xf6\x52\x9f\xb5\x63\xc2\x97\x3c\xf3\xb6\xb5\x6b\x43\x4f\xef\xd0\x52\x0b\xd7\x84\x4b\xf5\x1c\x88\x8e\x9a\x78\x4b\x99\x41\xaa\x28\xaa\xaa\x16\xa0\xc0\xee\x70\xf2\x92\x5c\x0f\x66\xa6\x80\xe1\xb1\x41\xae\xec\xe1\x17\x58\xab\x43\xdc\x8d\x14\xef\xa1\xec\xb2\x39\xec\xb7\x6d\xce\xcb\xd3\xc8\xaa\x03\x8d\x39\xf7\x9f\xbb\xef\xbe\x73\x0c\xb9\xef\xdc\xfd\xf7\x9f\x83\x73\x2d\x95\x5f\xff\xaa\xb2\xa5\xa5\x12\x1e\xad\xc8\xe0\xaf\x32\x15\xf0\x68\x65\x0b\xec\x55\xc3\xee\x53\x23\xae\x5a\x7d\x1f\x5b\x7b\xe1\x74\x45\x4b\x4b\x05\xd7\xaa\xfe\x7e\xff\xfb\x15\x2d\x2d\xf9\x71\x68\x89\x0e\xb1\x67\x11\x42\xd3\x11\x02\xae\x07\xee\x48\xe8\xd3\xcf\xd3\x85\x66\x87\x5d\x50\xe7\x91\xea\x28\x02\xf5\x87\x48\xca\x5b\x0e\x24\x35\x25\x47\x8f\x29\xbb\x76\x43\x8a\x3b\x00\xec\x6d\x3f\xff\xe0\xbe\x49\x77\x6f\x5e\xb3\x78\xd1\x9a\x8d\x77\x4e\xb8\xfb\xc7\xef\xde\x3f\xff\x57\x93\xb8\x62\xaf\xce\xe4\x68\x5c\x40\xfe\xb1\x6d\xf7\x27\x7b\xc0\xf3\xf6\xc6\xf7\xef\xbb\x65\xf7\xb5\x87\xa7\x2f\xdc\xbd\x7d\x8e\x7f\x91\xd5\x5e\x64\xfd\xaf\xfb\xeb\x97\x35\xc5\x74\x66\x87\xab\xe1\xb1\xd9\x2f\x12\xb6\x8e\x39\xf5\xe6\x2b\xfb\xef\xfd\x59\x7a\xe6\xc6\x5d\xbb\x37\xce\x4c\x3f\x7d\xd7\xbd\xcf\x8e\x6c\x62\x7d\xa2\xc3\xe4\x4c\x4e\x5d\x7e\xd5\x2f\xaf\x7d\x0b\x2c\x53\xf6\x3d\x74\x74\xdf\x94\xab\x17\xcc\xc9\x46\xfc\x76\xdb\x68\xfb\xfd\xef\x46\x2a\x22\x0e\xb3\xe8\x19\x3c\xbc\xeb\x85\x88\xcf\x9c\x1f\xcb\x66\x39\x44\xf7\x12\x94\xa3\x29\xb4\xd4\xcb\x35\x4e\x4a\x1f\x50\x53\xb1\x06\xa0\x20\x23\x4d\x40\x51\x31\x34\x3e\x8e\xfc\x59\xa4\x0c\x0b\x94\x57\x20\x10\x93\x7a\x44\x5d\x33\xa4\x99\x9e\x35\x15\x3f\xab\x4e\xc3\xd9\x4e\xc5\x9d\x55\x12\x8a\xc6\xe1\x4b\x1d\xb9\x3f\x68\x36\xe4\x9a\x29\xf9\x99\x62\x57\xd7\x9f\x40\xe0\x9c\xcc\x9d\x6a\x94\x6e\xe4\x56\xa4\x08\x3e\xf9\xa6\xb6\x6c\x62\x71\x99\x0b\x58\x01\xd8\x93\x6e\x85\xb9\xf4\x29\xaa\x23\xd7\xdf\xb0\x9c\xe9\x24\xc8\x19\x61\x36\x0b\x3e\xa7\xc1\x32\x40\x49\x28\x8a\xdb\x14\x6f\x65\x99\xb4\x92\x50\x8c\xb6\x22\x29\x22\x28\x7d\xb8\xf6\x6a\xbe\x35\x7b\xfc\x09\x5a\x6d\x33\xf7\x98\xd1\x53\x06\x34\x19\xa4\x58\x1a\xfe\xaf\x79\xe6\x90\x92\x10\x6f\x55\x12\xca\xad\x62\x42\x11\x01\x89\x09\x11\x50\xee\xd6\xff\x73\xae\xc5\xfd\x10\x51\x03\xc8\xaf\xf7\x8b\x4a\x42\xbc\x88\x44\xf5\x79\xc1\xff\x7d\xde\x35\x1e\x0d\x6d\xfc\xce\x21\x3d\x2a\xa4\x7b\xcd\x14\x84\x44\x3d\x13\x88\x8a\x01\x3d\x0e\x44\x02\x0c\x1d\xd0\x47\x34\x95\x39\x65\xf6\x48\x83\x9a\xb7\xf7\xf0\x4a\xf2\x1e\x7c\x06\xb3\x72\x6d\xd7\xbd\x49\x2e\x90\x73\x4c\x0e\xaf\x24\xcf\x77\xbf\x8c\x8f\xbd\x49\xfe\x82\x57\xc2\x74\x72\x8e\x5c\x80\x69\x90\x35\x61\x4b\x77\xc6\x56\x6f\xeb\xce\x58\xb0\x09\xb2\xb6\x00\x9b\x0d\x30\x28\xb7\x08\xdf\xd5\xdd\xcd\xb0\x94\x6f\xa3\xfb\xbf\xf1\x5d\xd4\x01\xd9\x85\x04\xd9\xaa\xad\xdd\xc8\x6e\x67\x91\xb5\xda\x86\x91\x1b\x31\x48\xbc\x88\x84\x3f\xf3\x08\x0d\x47\x77\xa0\x43\x08\x71\xa9\x58\x11\x08\x51\x0a\x45\xfd\xef\x7f\xd2\xda\xe6\xd8\xef\xfc\x89\xf4\x8f\x64\x65\x94\x54\x0b\x58\xe3\xc9\x40\x32\xe0\x08\x38\xe2\x56\xd9\x0f\x02\x63\xed\x8b\xfd\x9f\x5e\x09\x8e\x08\x97\x54\xbb\x19\x41\x14\x13\x62\x76\xfa\x84\x09\xb6\x94\x6d\xc2\x04\x31\x21\x7e\xe7\x8f\x1a\xe9\xdf\x85\x4f\xb8\x50\xd9\x2f\x56\xe6\xe7\x56\xbb\xff\x64\x56\x53\x03\x65\x4f\xfa\xed\xd6\x9f\x8b\xfd\x9f\xf4\x6f\x5f\x07\x19\xc8\x42\x36\x4b\x90\x28\x6a\x0f\x14\xbf\xeb\xf8\x37\xa1\x9b\xd4\xd0\xf1\xe3\x45\x71\x7c\x06\x22\x50\xef\x6e\x32\xd4\x43\x79\x36\x9b\xcd\x92\xf7\xeb\x0d\x4d\x6e\xf2\x53\xf2\x6b\x9b\x28\xaa\x11\xfe\xcd\x43\x58\xb7\x06\xb9\xd9\xd3\xfe\xb8\x1e\x2e\x97\xc1\x68\x3d\x42\x01\xb1\x1a\x40\x34\x03\xe4\x49\x20\x83\x79\x2e\x48\x8d\xc6\x51\x1f\x8f\x35\x33\x0d\x10\xf3\x33\xf1\x58\xb3\x4e\xdb\x18\xdd\xdb\xf6\x98\x74\x34\xae\x0a\x5a\x4d\xd8\xa6\xd5\xce\x3c\x46\x41\x5a\x80\x02\xb9\x4a\x42\x5c\xf0\x33\x38\xd3\xd1\xa1\x16\x44\xb6\x03\x10\xc6\x86\xc9\x6d\x73\x05\xaf\x30\xb7\x6d\xb2\x81\xda\xe9\x16\x60\x5c\xc0\x14\x72\xc6\x02\xab\x4d\x36\x86\xab\x44\x83\xb1\xa0\xb0\xc0\x68\x10\xab\xc2\x46\xd9\x66\x2d\x30\x72\x85\x4c\x01\x8d\x05\x0f\xec\xdf\xd4\x7d\x60\xd3\x7e\xbd\xaf\x6a\x5c\x72\xfa\x2f\x25\xfc\xf2\xcf\xad\x43\xc2\xc5\x15\xfe\xe5\x8d\xcb\xfd\x15\xc5\xe1\x21\xd6\x9f\xbf\x2c\x78\x7e\x39\xbe\x65\x5a\x99\x05\x3a\xb3\x99\x5c\x16\x67\x33\x59\x1c\x63\xb1\x4e\xc4\x58\xd4\x61\xd6\xa6\x67\x04\x81\x0d\xe8\xdc\x3a\xbb\x50\xc8\xb2\xae\x50\xd0\xe5\x0a\x86\x5c\x2c\x5b\x28\xd8\x75\x6e\x5d\x80\x15\x04\x46\xdf\xfd\xe0\xa6\xeb\xaf\xdf\xd4\xb4\xe6\xba\x2b\xe7\xba\x3f\xcc\x64\x0a\xed\x25\xb5\x75\x65\xcd\x37\x97\x45\x9a\x9b\x23\x65\x37\x37\x97\xd5\xd5\x96\x8c\x1b\xf3\x49\x60\xdb\xa1\xef\xe5\xf5\x06\x39\x0e\xa1\x76\x34\x13\xad\x42\x08\x24\x13\x8e\x56\x41\x54\xa1\x8a\x12\xba\x04\x1a\xea\xb7\xf0\xad\xf4\xee\x09\xf7\x63\x39\x10\x8f\x86\x82\x4a\x9a\xea\xda\xd5\xea\x9e\x5f\x94\xe0\xcb\x41\x4e\xc9\x7e\x80\x58\x2a\x1d\xd0\x28\xd2\xe9\x72\x7b\x09\xa4\xbe\xb1\xc6\xae\xcb\x15\xb6\xee\x78\x6e\xd1\xf7\xff\x6c\x29\x1c\x33\x66\x68\xc7\x95\x11\xcf\x45\x34\xa4\x77\x19\xbc\xbd\xdd\x79\xf5\x8f\xe8\x76\xb0\xec\xe8\x6b\xaf\xa8\xf0\x61\xb4\x76\xd2\xc7\x7e\x85\x63\x15\x67\x2e\x60\x6f\x5b\x23\x7a\x16\xa8\x81\x4f\xac\xdd\x79\xf3\xf7\xde\xf8\xfa\xbd\xb5\x8f\xc9\xe4\xa7\x21\xbb\xcd\x7a\x6b\x75\xc5\xae\xd3\xa7\xb9\x2c\xe8\x4e\x5f\xba\xe6\x0e\x7f\x5f\xf4\xe2\xde\x76\xa1\xe0\xd3\x43\x2b\x5f\x1d\xba\x6c\xec\xa7\x3b\x3c\xd1\x9e\x95\x71\x4f\xe5\x95\x4a\x42\xf1\xc4\x7c\x52\xb6\xd2\x2f\xfb\xbd\x4b\xd6\x88\x8a\x3b\xeb\x56\x8e\xb7\x78\xdc\x67\x73\x5d\xb7\xac\x2c\x2a\x2e\x02\x87\xf1\x34\xf9\xfa\xf4\xe9\xcb\x97\xdb\xf3\xfc\x46\x5c\x96\x3b\x87\x92\x68\x8c\xda\x13\x06\xec\x26\x5c\x5c\x85\x35\x3c\x0d\x49\x96\x78\xc1\xc4\x0a\x7e\x36\xd6\xcc\xa4\x29\xb0\x06\xdd\xc2\xc8\x68\x6b\x55\xfd\x2d\x4e\x7a\xed\xf2\xf2\x3d\x06\x97\xbd\xfa\xad\x7f\x90\x0b\xff\x78\xeb\xea\x41\x57\x6d\x1c\xea\xae\x60\xb9\x22\x77\x7d\x47\x5d\x89\x19\x98\x01\xf3\x76\xbc\xf8\xde\x8b\x3b\xe6\x0d\x60\xc0\x5c\x52\xd7\x51\xef\x2e\xe2\xd8\x0a\xf7\xd0\x8d\x57\x0d\x22\x59\xc5\x9d\xd1\xb6\x38\x65\xdc\xca\xc8\x24\x64\x93\x23\x3b\x28\xd7\x55\xcb\x82\xa6\xa2\xa2\xa6\x05\x2d\x35\x63\x52\xa1\x42\xae\xc8\xed\xae\x60\x0d\x1e\xa7\x6c\x61\x0b\x8a\x42\x7e\xbb\xdd\x1f\x2e\x2a\x64\x4d\x4e\xd9\x63\x60\x2b\xdc\xee\x22\xae\x30\x94\x1a\xc3\x8c\x21\x59\xb7\x42\xb2\x9a\x3e\x42\x3d\x92\x23\x47\xc2\x51\x8d\x13\x0b\xf7\x72\xd6\x78\xa8\xf5\x54\xc0\x04\x66\xd0\x30\x2c\xa3\x81\x58\x2a\xed\x01\x8d\xcb\x45\x94\x25\xb0\x0b\x81\x68\x15\x08\xbc\x50\x00\x55\x10\xe4\x05\x26\x90\xc7\x88\xc4\x72\x33\x13\x57\x3b\x3d\xa8\xe1\x0c\x2c\x93\xbb\xc5\x96\xb0\xe5\x6e\xe6\x2c\xb0\x5a\x0a\x71\x6d\x2f\xf0\x41\xc9\x11\xe4\xf7\xd7\xda\x70\x74\x11\xf9\xde\x4a\x5d\x48\xac\x2c\xd8\xfe\x13\x3e\x54\x11\xe4\xae\x22\xd3\x16\x91\x73\xcd\xdb\x57\x8e\x0d\x87\xc7\xae\xdc\xde\x7c\x8e\x60\xc4\xeb\x19\x36\x77\xd4\x66\xc3\xd3\xb1\xcd\xe3\x00\x57\x6e\x81\xdd\xed\xb6\xc3\xef\x57\x85\xe0\xf8\x2d\x07\x3f\xb2\xda\x31\x57\x4a\xc6\xe3\x13\x76\xb7\xc7\x41\x06\x1c\xbc\xe5\xc3\xaf\xcb\x87\x67\xc2\xe1\xcc\xf0\xf2\xaf\xd5\x31\x1c\xbe\x88\xd8\x2c\xd7\x4d\xf7\xd6\x20\xb0\x23\xc1\x1a\xef\xa9\xd5\xbd\x0b\x75\xbd\x78\xbb\xd6\x2a\xc0\x94\x7d\x96\xb5\x85\x2d\x88\xea\x8b\xd8\x2c\x39\x7b\xf6\x5c\x1f\x68\x8c\xe6\x3c\xf0\xb7\xed\x85\x05\xfb\x3e\xd9\x7d\x0c\xca\x4e\x74\x23\xad\xc6\x91\xf3\xe4\x26\xa6\xf3\x23\x72\xca\x49\xba\xfb\x45\xd5\xcc\x89\x58\xcb\x09\xb0\x1d\xbc\xf6\x0f\xfb\xcd\xe2\x7e\xf2\xb9\x4d\xd3\xe6\xa8\x77\xf5\xd7\x83\x46\x51\xf5\x65\x9c\x90\x94\x0d\x19\x07\xab\x30\x55\x00\xcb\x90\x07\xc2\x89\x6b\x69\x43\x16\xae\xd3\xad\xd0\x17\x90\x1d\x5b\x67\x1c\x7c\xff\xf3\xf7\x0f\xce\x98\x71\xf0\xfd\x75\x67\xee\x81\xad\xa4\x8b\x2e\x56\x2e\xea\x49\x1a\x39\xcf\x65\x15\x37\xd1\xcc\x96\x78\xb2\xfd\x9e\x33\xeb\xb4\xd8\xea\x4d\x5b\x61\x2b\x7d\xcc\x85\x6c\x5f\x5e\x7a\x6d\x51\x58\x55\x36\x37\x69\x7b\xe7\x6c\x0e\x3b\x12\x1c\xff\xa6\x08\x93\x0a\xa2\x16\x67\x51\x45\x95\x1f\xb2\x5f\x95\x1a\x54\x92\x08\x7c\x4f\xa2\x99\xe6\x5b\x4e\x92\xb3\x67\x35\xc4\x06\xfa\x5a\xcd\x79\x96\x9c\x3d\x79\xcb\xe1\x16\x5e\xb4\x0e\x71\xe8\x2a\x3a\xff\xd4\x59\xa1\xf3\x35\x59\x45\xbe\x25\xf7\x83\xbe\x4c\xb0\x3f\x19\x46\xfe\xe7\x21\xb5\x94\x77\xf5\xbb\x95\x3a\x77\x39\x61\xe8\x47\x0f\x81\x63\x58\xc7\x49\x8b\xc7\xbe\x74\xc7\x8e\xa5\x76\x8f\xe5\x64\xd7\x87\xfd\xb2\x44\xeb\x03\xed\x6b\x06\xa1\x11\x08\x41\x8f\xc1\x7b\x4f\x36\x04\xe9\x3f\xe6\x4f\xad\x22\x29\xa4\x0a\x81\x88\xda\xbe\x7b\x32\xc5\x22\x9b\x09\x8a\x7b\xbe\xc6\xd6\x6f\xcb\xdf\xed\x7f\xdb\x51\x68\x81\xe2\x33\xeb\x3f\x9c\x8a\x2e\x5e\x6b\xb2\xe5\xf6\xf4\xfb\x36\xe7\x4c\x36\xc5\x4d\x68\x95\xb9\xf6\xe2\x7d\xaf\x7f\x7b\x06\x2d\x27\xc0\x7a\xf0\x4d\x28\x97\x4d\x83\xda\x88\xcd\xd4\xd5\xd1\xff\x6b\xe1\xde\xbd\xa5\xcb\xd0\xda\xff\x5b\xde\xd4\x6f\x97\x8e\x0a\xbd\x90\xc3\x8e\x4b\x56\xdb\x7b\x3a\x83\x74\x2f\x52\x71\xaa\xf8\xd2\x42\xe0\xfe\x73\x21\x9c\x25\x67\xb7\x26\x16\xe8\xdd\x86\x01\x06\xd0\x2f\x59\x49\x43\x14\x37\x14\xab\x81\xbb\x97\x4e\xce\x07\x4c\xaf\xbb\x0f\xf6\xdf\xf7\x7f\x2c\x25\xb5\x1a\xbc\x7e\x5f\x72\xa5\x01\x74\x15\x3a\x8f\x61\xed\xaa\x6b\x69\x9d\xef\x49\xd7\xb2\xd9\xf9\x80\x2b\x6a\xb7\x6e\xfd\x46\x29\x22\xc4\xa9\x75\x84\x27\x5c\x0e\xd5\xa2\x66\x34\x12\x8d\xa7\x9a\x19\x09\xf3\xdf\x26\x3a\x02\xdf\x21\x44\xd4\x1a\x22\xa7\x64\x09\x41\xca\x12\xe5\x2d\x4c\x8c\x0e\x48\x14\xda\xf1\x82\x55\x89\xf2\x82\x15\x62\xc8\x82\x42\x41\x81\x0e\x4b\x78\x52\xb8\xfd\x6f\x07\xfa\x49\x0c\x82\x2e\x13\x37\x56\x88\xbe\xf5\xf6\x23\x8f\xbc\xfd\x16\x44\xbb\x6f\xcd\x66\xb3\x9d\x6b\x17\xdd\x7d\xf7\xa2\xb5\xb4\x67\xc5\xe7\xaf\xdb\xb0\xe1\x3a\x9c\x39\xa5\xe6\xe2\x14\x0d\x60\xfe\x7a\x90\xfc\xe5\x84\xe5\x12\x51\xf4\x4d\x81\xf4\x36\x54\x8a\x8e\xb5\x6b\x1d\x22\xf9\x45\xee\x8d\x9d\xb0\x7c\xe7\x4e\x72\x1b\xf9\x67\xdd\xe1\xdf\x9e\x7b\xa8\x4e\x2b\x72\x92\x05\xd6\x3c\x66\x8c\x99\x74\x43\x5e\x36\xd4\x3d\x74\xee\xb7\x87\xeb\xd4\x71\x1b\x5c\xe4\x05\xb5\xbe\xb5\xa1\xb1\x68\x36\x5a\xfe\x6d\x75\xce\x0f\x02\x8f\x04\x3e\x1c\xad\x62\xd2\x5a\xd7\x19\xe9\xb5\xc3\xbc\xb4\x72\xca\xf9\x06\x05\x09\x3a\x50\x91\x9b\x21\x62\x97\x64\x25\x99\x40\xe9\x2a\x75\xc0\x02\x31\x94\x4c\x28\x51\x5a\x89\xfd\xc0\x5f\x52\xd3\xda\x5b\xa4\x22\xf2\xd5\xd3\x3f\x27\x0f\x0e\x5e\xf7\xee\xad\x63\x75\xfa\xeb\x7f\xbb\x67\xfd\xaf\xa7\xd1\xfa\xd3\x3f\x5e\x43\xf0\xa9\xfd\xd4\x93\x20\xf6\x81\x0f\xd8\x07\x3e\xe8\xce\x7e\x7c\x98\x01\xd3\x99\xe4\x47\x7b\x4e\x91\xf3\x4c\xe7\x29\x10\x3e\x3e\xcc\x90\xaf\xce\x24\x3f\x62\x3b\xfa\xd7\xb5\x39\x7f\xc9\x3e\x45\xba\xdd\xbe\x0f\x5e\xe4\x17\x3d\xf8\xf1\x86\x3d\x9f\xdf\x6e\xd6\xda\x60\xa6\x7f\xac\x11\x73\xf4\x6b\x89\xcd\x44\x0e\xd9\x15\xd7\x85\x87\xe8\xcf\xd1\x6e\xd9\xe7\xff\x39\xb4\x44\x36\xee\x27\xe7\xbb\x05\x10\x4e\x1d\xed\x96\xbd\x45\x3f\x27\x2f\x45\x36\xee\x47\x2c\xe2\xf3\x7a\x8d\x11\x68\x2c\x9a\x89\x16\xff\x9b\x32\x8c\xf2\xff\x7f\x82\x89\xd2\x8d\x68\x45\x49\xeb\x1e\x1d\xea\xa5\x15\x8b\x5a\xfb\x7a\xeb\x9c\x45\x90\xf8\xec\x65\x45\x58\x4c\xfe\xf5\xa3\xdf\x3c\xbb\x6e\xdf\x37\xda\xec\xc1\xf3\xd7\xc8\x2e\x30\x3e\x7b\xee\xd9\xfd\x27\x5e\xcf\xb7\x4a\x94\xcd\x66\x73\x59\x10\x4e\xad\x5b\x70\xf7\xdd\x0b\xd6\x9d\x62\xea\xb4\xca\x47\x2f\x2f\x6d\xa7\x73\xfe\x92\x7d\x92\x74\x7b\x82\x5b\x46\x9b\xbf\xd9\x58\xad\xa7\x20\xf8\xc0\x73\x60\xf6\x05\xb7\xcc\xa5\xad\xf1\xbf\xf3\xd5\x10\x56\xaa\xd5\xaf\xee\x21\xe8\x7c\xa8\xae\xbb\xb7\xea\x91\xcc\x43\x75\x97\xd8\x0e\x35\x50\xe4\xf8\xfe\x7d\xa6\xd0\x6b\x2c\x29\x5c\xda\x7b\xa6\xfb\x2c\x26\xbf\xb3\x1f\x7d\xff\x06\xbd\xbe\x4a\xef\x36\xdc\x30\xfa\xd2\xfe\x74\xf4\x71\xcd\xff\xf8\xfb\xff\xbe\x5f\xfd\xe5\x0d\x06\xb7\xbe\x4a\xaf\xbf\x71\xcc\xa5\xfd\xeb\xe8\xe3\x9a\xff\xf1\xf7\xbf\xa3\x9f\xc5\x17\x59\xda\xcf\xd6\x51\x3e\x47\x09\x39\xec\x98\xa5\x6a\x5d\x5b\x2a\x9d\xec\xfb\xc8\x82\x06\xea\xa4\x65\xa3\x27\x9f\x7d\xd5\x02\xe7\xf3\x83\xb3\x67\x21\x7a\x82\xfc\xf2\xd8\xee\x4f\xf6\x15\xa8\x92\x85\x2a\x3f\x0f\xcd\xd4\x12\xf1\x86\x98\x10\xdf\xd0\xf2\x33\x53\x0b\x38\xdf\x97\x1b\x66\x8b\x93\x9c\xfa\xe8\x21\xf2\xf9\x7e\xd1\xbc\xff\x0f\xd7\x1e\x04\xdb\x09\x8b\xf6\xd9\x0e\xcf\xd4\xee\x79\x5d\x14\x5f\xd7\x1e\x34\xf3\x30\x0d\xe8\xca\x5e\xda\x0f\xb1\x08\x09\x59\x76\x6b\x4f\x5e\x28\x0a\xba\x96\xea\x7e\xe2\x92\x47\xa1\x60\x38\x3f\xda\x92\xe4\x78\xb2\x47\x09\x1a\xe8\x01\xa3\xea\xf9\x36\xc2\x0a\x51\x24\x1f\xe8\x3d\xfa\x4a\x83\xe1\x14\xf9\x20\x2f\xe3\xbf\x23\x8d\xa0\x9c\x32\x18\x2a\xf5\x1e\x7d\x57\xa6\x2f\x4b\x78\x85\x98\x10\xc9\x07\x5a\xc0\x29\x4d\x0a\x9e\x25\x67\x4f\x40\x59\x6f\xf9\x68\x9e\xa7\xb4\xb7\x74\xff\xf9\x1b\xfd\x2a\xfd\x36\x32\x2a\xca\x8f\x21\x7b\x81\xe0\x90\x3a\x23\x88\xf9\x71\xef\x30\x40\x1d\x2e\xd2\x94\x9c\x25\x67\xf3\x1f\x3f\x27\xf4\x2b\x5d\x3a\x40\xcc\xdd\x43\x6d\xc2\xe7\xab\x3d\x55\xbe\x96\xe4\xce\x5c\xf6\x4e\x84\xd8\x2c\x9b\x45\x02\x92\x11\x42\xf9\xc1\x28\xea\xad\xce\x31\x3f\xb0\x88\x9c\xef\x1d\x47\xee\xe9\xab\xad\x9f\xbf\x7f\x10\xfa\xf5\x99\x38\xd9\xe7\x3f\x63\xc6\x41\xd4\x0f\x87\x2d\xdc\x8f\x6b\xd3\x1a\x4f\x87\xd4\xe1\x7b\x9a\x9a\x12\xfa\x20\xe4\x88\x5b\x7b\x81\xe3\x1e\x09\xc5\x62\x21\xb2\xe9\x55\xff\xef\xab\x5b\x37\xb7\xac\xdd\xfb\xe0\x6b\xaf\xe5\x02\xaa\x1f\x97\x8d\x85\x2e\x1c\x0b\xc5\xf0\x84\x3f\xde\x56\x5b\x0b\xef\xe8\x0f\xed\x7f\xe4\x8f\xb9\x1f\xc6\x42\xdc\xe4\x50\x0c\xe5\xdf\xc5\xa9\xf2\xad\x1d\x21\x6b\x42\x9d\x17\xb0\x12\x25\x1d\x0d\x2a\x51\x13\x6f\x06\x6a\xc8\x68\x4b\xf7\x2d\xbb\x6b\xb6\xe0\x2c\x5d\x34\xa5\xc0\xe6\x9a\xd6\xb6\x8a\x19\xb9\xeb\xf8\x4f\x17\xdd\x07\x96\x63\xca\xf8\xf5\xc7\x17\xb5\x5e\xeb\x33\x84\x0b\xfc\x52\x59\x2c\x62\xd2\x9b\xcb\xa7\x0b\xc5\x8b\xc7\x36\xb5\x4e\x9d\x9e\x49\xcf\x6e\xa9\xf1\x18\x7f\xfd\xd8\x6b\xe4\xef\x2e\x9f\xcb\x2f\x61\x73\x7c\x4c\xb9\xc4\x3c\xb2\xfc\xc5\x9b\x16\x27\x76\x93\x43\x1d\xcf\x1c\xdb\x3e\x2a\x53\x1b\xbd\xb5\xfc\x8a\xf2\xf1\xc3\x63\x9c\xe1\xde\xa2\x99\xbf\x87\xe9\xfe\x81\x8b\x27\xec\x1f\xd7\x3c\xe8\x42\x73\xcb\x84\xd8\xe4\xc5\xeb\x96\x54\xff\xf0\x25\x92\x7b\xb5\x62\xfc\x80\x72\xbd\x77\x3a\x63\x1e\xbf\x6c\x45\xcf\xba\xf4\x66\x1e\x71\xd7\xa2\x72\xd4\x8c\xc6\x21\x84\x34\x64\x12\x6a\x7b\x4e\xe7\xd9\x69\x8d\x8e\x4c\xa2\xd6\x88\x40\x33\x44\x71\x86\xa4\x78\x8c\xe9\x8f\x73\x2b\xa4\x25\x5b\x0f\x0c\x59\x28\x18\xe5\x44\x6a\x7c\xc4\xbc\xe9\x7e\x98\xc3\x56\xcb\x95\xd5\x75\xbb\xe7\xdd\xdc\x3e\x0c\x98\xa1\x4e\x2f\xef\x14\x44\xb3\x4e\x17\x1b\xc2\x05\x5b\x6b\xe7\x14\x1a\xcc\xab\xb6\x7d\x76\x74\xfe\xfc\xa3\x9f\x91\xcf\x8e\xce\xdf\x38\xe6\xab\xfb\x82\x10\x03\xf9\x8d\x8d\x1b\xdf\x20\x9f\xdd\xf5\xe3\x63\x64\xce\xde\xe5\x1b\xdf\xc0\xb1\xa9\x7a\xce\x10\x28\x8f\x26\x9b\x2b\xf7\xaf\x5a\x36\x45\x37\x63\xb0\xc4\x18\x1d\xf6\xbd\x82\x63\xb8\x41\xd0\x0d\xcf\x24\x07\x08\x64\x4c\xfe\x21\xf3\x8f\x7e\xb6\xed\xcc\xe1\xcf\x46\x2d\xe6\x16\xaa\x0f\x21\x6f\x93\xcf\xde\xd8\x38\xfb\x5a\xb8\xfd\xf1\x5f\xdc\x05\xf2\x1b\x94\xd7\x25\x8f\x3f\xa6\xe1\x05\x89\x74\x8d\x38\x8a\xca\xd5\x19\x4b\x3a\x90\x0c\x58\x03\xc9\x40\xef\x56\xa5\x7e\x6e\x5b\x2f\xce\x08\xe5\xa3\xa1\x47\x96\x45\xdd\x48\x3d\xf8\xe2\xda\xb1\xb5\xb5\x63\x2f\x38\xfb\x5d\x68\x7f\x77\x9e\x47\x02\xd2\x8e\x2c\x05\xa5\xb9\x93\x06\xb0\xc5\x3d\x2e\xac\xc5\xcc\x15\x93\x2c\x64\x31\xea\xfb\xed\xd5\x3b\x52\x2c\xee\x72\x34\x1a\x21\x54\xac\x58\x52\xc5\x92\x05\xf2\x43\xd8\x7e\x56\x24\x3d\xfd\x40\xa0\xc7\x7a\x84\x12\x9c\x3b\x7a\x16\x93\xb8\x78\xcf\x0c\x26\x1e\x93\x29\x33\xde\x1c\xf2\xf2\x27\x9f\x40\xf3\x27\x38\x03\x1d\x46\x51\x34\x92\x43\xa2\xb1\xd3\x28\x92\x43\xea\x05\x74\xd0\x8b\x5c\x71\x7b\x02\x50\xeb\xa2\xee\x03\x9b\xf6\x0b\x8e\xe2\x54\xdb\x82\x26\xd1\x3e\xe6\x8e\xc7\xef\x18\x63\x17\x77\x4d\xfa\x4d\xa2\x1d\x67\xf3\x00\xff\xe4\xfe\x6f\xde\xad\x3d\x37\xd7\x99\x68\xff\x4b\xec\xfa\x4d\xc9\x05\xeb\xe6\xcf\x19\x5c\x62\x6d\x6a\x6a\x6a\xb2\x76\xb4\x27\x7a\x6c\xa2\x85\x7f\xd1\xfc\xc5\xd1\xe4\x7e\xf9\x53\x6b\xa2\x19\x34\xb4\x0c\x0d\x0b\x30\x99\x68\xa1\x4d\xac\x05\x28\x2d\x9f\x46\xce\xa7\xd6\x57\x4e\xa0\x70\x0b\xfd\x33\x2a\x15\xd3\x6c\xd2\xc1\x57\x5f\x3e\x7f\x74\x5e\xaf\xdf\xab\x37\x9a\xf4\xe7\xcf\xeb\x4d\x46\xfd\x5e\xbd\xea\xb8\xcc\x27\xe7\xf8\x51\x24\x32\xc1\x21\x5f\x92\xe1\xbb\x61\xc4\xdd\x76\xd1\xeb\xf3\xba\x23\xbd\xf9\xcd\xfd\xe6\xbb\x1f\xd2\xe7\xf3\xa3\x48\x2a\x19\x99\xc0\xf4\x65\x7e\xf3\x66\x2b\xef\xa9\x0a\xa4\x22\xfd\xec\x62\x6d\xc8\x4d\xe5\x17\x1d\x2a\x69\x76\xfa\xf9\x4f\xd8\x53\xf5\x02\xbd\x96\x34\x80\xf8\x4e\xb7\x72\x11\x5d\x40\x17\x11\x5d\x04\xc2\x99\x03\xef\x1d\x38\xf0\x1e\x37\xf9\x93\xfb\x73\x19\xb7\x82\x91\xe2\x26\x19\x50\xc5\x3c\xc5\x3a\x23\x92\x1a\x7a\x20\x73\xff\x27\x8a\x9b\x64\xfb\xb0\x74\x55\x39\x26\x51\x2b\x17\x26\xee\x08\x08\x01\x47\x40\xaf\xd6\xf5\x68\x20\x19\x67\xa8\xc9\x8b\x18\xe2\x51\x67\x27\xf9\x4b\x1a\x86\x93\x05\xe4\x20\x39\x48\x16\xc0\xf0\x34\xf9\x4b\x67\x27\x20\x18\x0c\x9b\x61\x30\x41\xcb\x7f\xc5\x23\x92\xe9\xcc\x76\x76\x77\x32\xea\x09\x3a\x73\x88\x41\x5d\x19\xe8\xe3\xd5\x46\xf9\xbe\x26\xa4\xca\x67\x56\x95\xcf\x82\x2c\xd1\x4f\xd5\xa2\xd1\x6a\x87\xe3\xb6\x1e\x66\x51\x6b\xc0\xca\xaa\xe3\xfe\xae\x27\xdf\xb7\x58\xa4\xae\x73\x92\xc5\xf2\xfe\x93\x5d\x20\x9c\xfa\x82\x92\x38\x31\xa8\x2b\xcb\xa3\xe7\x76\x77\x67\x77\x3c\xc3\xbd\x61\x2e\x29\x31\xbf\xc1\x3d\xb3\x83\xc9\xee\x7e\xee\x42\x27\xe5\x6c\x82\x77\x31\x22\xe8\x52\x9e\x29\xed\xdd\xe5\xda\x6a\xc4\xb7\xbf\x1f\xf7\x7b\x3f\xfa\x8f\x69\xf9\xad\xc6\x59\x9a\xc9\x9d\x63\x88\x46\x69\x9a\xc9\x75\x7e\x47\xb2\x34\xaa\x57\x78\x59\x4d\x56\xae\xff\x45\x8f\xae\xe6\x7a\x01\x71\xeb\x29\xff\x8a\x97\x62\xde\x58\x69\x07\x91\xa7\xf3\x8e\xc7\x64\x90\x64\x3d\xb6\xda\xf9\x60\x34\xa2\xf6\xd5\x7a\xd0\x3c\xf1\x24\x97\xd3\x6a\x21\xd5\x0e\x9f\x5d\x34\xf9\xe1\x22\x93\xc1\x52\xee\x73\x76\x99\x77\x80\x4c\x86\x62\x57\xee\x62\x05\xd9\x0c\xad\xd6\x90\xa9\x10\xfb\x58\x76\x46\xd7\x32\x57\x48\xf7\x99\xa1\x5a\x66\xaf\xb2\x7b\xcd\x17\x11\xb3\xa8\xfb\x3e\x30\xe0\xb6\xae\xdf\xba\x8a\x8c\x1f\x32\xbf\x67\xba\x5f\x1c\x8a\x37\x63\xb3\x97\x27\x5f\xe1\x4b\xf0\xd5\xcd\x97\xe3\xab\x07\xac\x97\x63\xaa\x5f\x40\x97\x21\xa9\xb3\xc7\x34\xeb\x37\x27\x9a\x78\x91\xd7\xfd\x80\xbb\x98\xdf\xa7\x5c\x8d\x5a\xd1\x28\xd4\x0d\x3c\xd8\xc0\x03\x11\x88\x41\x23\x0c\x85\x71\x30\x1b\x96\xc3\x06\x78\x02\x5e\x86\xb3\xf0\x19\x10\x6c\x44\x88\x33\x01\xc5\x54\x4b\xa5\x53\x12\xe7\x07\x8d\x89\x39\xaa\xf0\x69\xea\xa6\xa4\x66\xbc\x16\x27\x99\x50\xe3\x40\x3c\x28\xe4\xc1\x75\xa2\x79\x75\x66\x42\x49\x57\x81\xd0\x8c\xfd\x00\x92\x20\x39\x24\xed\x89\x6c\x84\x92\x54\xa7\x53\x69\x45\x9d\x5c\xe4\x7f\x13\xda\xfc\x56\x4e\xe6\xbb\xbd\x54\xba\x19\x4b\x72\x5c\xed\xea\x9a\x21\xad\x44\x95\x68\x22\x5d\x95\xbf\x2f\x25\xc9\x76\x3f\x23\x4b\xea\x23\x04\x8a\xb1\x54\xc5\x46\xc3\x20\xc9\x52\x3a\xde\xcc\xb4\x40\x33\xc8\xda\x92\x2a\x08\x0e\x5e\xe0\x05\x3f\xc8\x6a\xa4\x78\x33\xf8\x69\x08\x45\x41\x0d\xd9\x85\x94\xf6\x4e\x87\xa4\xfe\x0a\x92\x9c\x02\xbb\xfa\xab\xe6\x4c\x9d\x24\x69\x2c\x8a\x51\x5e\x08\x46\x25\x39\x96\x4e\x29\x1c\x35\xb4\x50\x28\x77\x96\xac\xa4\xd2\x35\x4a\xd4\xa4\xce\x34\x53\x69\xde\x0c\x49\x5e\xa6\xe5\xe4\x87\xb4\x9a\x60\x94\xe7\x4f\x48\x26\x18\x45\x48\xf2\x92\xe6\xaf\x70\xcd\xa0\x44\x93\x7c\x48\xa3\x31\x89\xf0\x94\xe1\xba\x19\xd2\xbc\x20\x09\x12\x2b\xa7\xc2\x69\x25\x9d\x68\x86\x26\x70\xd0\x37\x53\xcc\xc0\xa8\x49\x17\xe2\xa3\x26\x46\xe0\x43\x7c\x54\xf3\x51\x27\xfc\x12\x93\x4a\xaa\x45\x65\x02\x59\xfb\x3c\xd4\x60\x57\xbd\xcb\xce\x3b\x24\x0a\x37\x15\xe2\x65\x49\x66\x29\x45\x3d\x4f\xef\x09\x39\x62\x11\x35\x5b\x42\x2a\xa9\xc1\xe5\x29\x49\xfa\x28\x2e\xa5\x61\xc3\xda\xb5\x64\xc2\xc7\x3a\xc5\xe6\x4a\x62\x18\xef\x91\x25\x2e\x21\x28\xa2\x2b\x09\x78\x82\x47\x92\xea\x8c\x53\x82\x95\x23\xf6\x0c\x28\xa9\xbe\xb0\xc6\x38\x59\x73\x56\xe1\xd7\xa1\x34\xe4\x09\xa6\x94\x84\x97\x5b\x35\x66\xec\xaa\x55\xe7\xae\xf8\xdb\x16\xcf\xca\x6b\xd6\x8f\xc3\x5f\xe9\x44\x01\x66\x64\x53\x03\xa6\x4a\xb9\x71\xb9\x9f\xc8\x53\x6a\x26\x3f\x07\x98\x13\x75\xbc\xcb\xe4\x11\xf4\x05\x5e\x9f\xdf\x28\x7b\x43\x6e\x9b\xbd\x40\x48\x4e\x2d\xd0\xeb\xcd\xa3\x71\x50\xf1\x72\xc6\x2a\x13\x83\x0d\xa5\x06\xb3\x59\x6e\x85\xe6\xd5\xde\x62\x87\xce\x32\x42\xae\x67\x18\xcc\x0a\x9c\xa7\x66\x40\xac\x64\x73\x75\xd3\xc2\x5b\xae\xb3\x97\x25\x02\xcd\x85\x78\x02\x24\xe7\x35\x4e\x0a\x03\x27\xb0\x18\x03\x53\x2f\x0f\xb7\x09\x8e\x62\xef\xca\xc6\xa1\x4e\x93\xb5\xa0\x4c\x0f\xac\xa5\xc2\xc8\x79\x95\x20\x1e\x63\xd2\xeb\x0a\xa7\x26\x0d\x02\xd8\x6d\xee\x90\x57\x36\x05\xdc\x9e\x02\x83\xce\x6b\x94\xc9\x3f\xf4\xe3\xfd\xac\xc7\x6b\x2f\x1e\x1d\x72\x19\x07\xfb\x8d\x1c\x53\x1b\x37\x8f\xf0\x9b\xca\x0a\x1c\x92\xc5\x7f\xfe\x05\xff\x78\x7d\x40\xf4\x7a\x4a\x7c\xad\x46\x57\x28\x62\x8e\xa7\x59\xfd\xb3\xa6\x06\x31\x5c\x59\xe5\x76\x31\x67\x75\x56\x86\x31\x5a\x4b\x2a\xc0\x49\xce\xfd\xf1\xc8\x91\x3f\x1e\x49\x2d\x59\x0a\x82\xc1\xb7\xbd\x48\xcf\x72\xe4\x2b\x1d\xc3\xe2\xf7\x30\xcb\xf3\x05\xc1\x6b\xc9\x9d\x96\xd2\x3a\xb3\x8d\x61\x0c\xdc\x90\x97\x99\xc8\x2e\x90\x8f\x1c\x07\xc7\xc1\x00\x03\xd8\x3a\xc8\xec\xae\x8d\x17\x71\xac\x60\xc0\xbc\x5e\x28\xd4\x59\x74\x22\xbb\xb4\x8e\x2d\xf4\x5b\xbc\x3c\xf3\x84\x13\xa7\xaa\x2b\x0a\x75\x56\x7d\xbd\x0f\xc6\x31\xd6\xd6\x68\xe9\xa6\xa9\x5c\x68\x47\x2a\x3e\xd9\x28\xb3\x3f\x7e\x65\xde\xe1\xb9\xbc\x8c\x8b\xf4\x85\x15\x06\x11\x30\x23\x4e\xc2\x76\xbc\x80\x9c\x68\x1f\xab\xd3\x0d\xcc\xbc\xfb\x2e\x00\x7b\x88\x75\x9a\x44\x60\xcc\xe6\x32\x93\xbe\x08\x5b\x0a\xdf\x7c\xe2\xa7\xb8\x83\x9b\xba\xb1\x4c\x19\x62\x65\x0c\x93\xe3\xa9\x1d\xfb\x2c\x11\x41\xef\x12\xa5\x41\x1c\x1b\x77\xf4\x73\x4f\xf5\x0c\xd4\x1b\x43\x81\xaa\x15\x1c\x37\x29\xd8\xcf\xcd\x0e\x32\xeb\x2a\x3d\xa1\x58\xb9\x2c\x8e\x58\xb2\xe4\xb6\x25\x1f\xac\xa8\x1c\xdc\x38\x9c\x2f\x59\x71\xe1\xc3\x82\x22\xd9\x5a\xbb\xba\x0d\xe3\xea\x32\x97\xab\x74\x00\x66\x0e\x4e\x90\x6c\x45\x05\x06\xbd\xe4\xf3\xe9\x0d\x26\xbb\xc9\xa7\x2b\xf4\x72\x02\x6b\x1e\x8e\x0d\x43\x92\x4a\x79\x73\xc0\x1a\x31\xb8\x6c\x9c\x8d\x61\x81\x83\x02\xbe\x84\xe1\x59\x1c\x28\x0a\xaf\xaa\xdd\x9a\xb4\xc8\x3e\x70\x5b\x9c\x26\xc6\x84\xab\xbc\xac\xad\xaa\x3e\x39\xdc\xa8\x33\x1b\x75\x26\x66\x2b\xf9\xd7\xc4\xeb\x0d\x22\x63\x72\x9a\x4d\x26\xaf\xd3\x9a\xd8\x5a\xb7\x2a\x54\x1c\xc0\x06\x5c\xca\x15\x02\x07\x1c\x63\xe3\x6c\x4e\x9d\x62\x2d\x6e\x29\x29\x4d\xb6\xe9\x71\x8d\xd3\xcc\x0a\x9c\xb7\x50\xef\xb5\xd8\x8c\x7a\x83\xd7\xef\xd0\x31\x8f\xfa\x5c\xc5\xf3\x23\x57\xfb\x44\x76\x7d\xd9\xee\x7a\x63\xb1\xc9\x94\x59\x60\x31\x1b\x60\xed\x16\xa6\xf5\xda\x9a\xf9\xc5\x2e\x9f\x8d\x15\x7d\x57\xef\x2b\x32\xd5\xef\x2e\xe3\xcd\x96\xf9\x03\xad\x03\xb7\xac\x64\x4d\x22\x4c\x5b\xc6\x44\x95\x1b\x45\x9b\xa0\xb3\xef\x6c\xc4\x78\xe7\xe1\xab\xd6\x1d\x3e\xbc\xee\x2a\xa2\x60\x0c\x9e\xf5\x82\x09\x0a\x98\x61\x83\x9f\x65\xa7\x4e\x15\x81\xb1\x4f\x1c\xcf\x99\xf1\x6b\x0d\x1b\x5c\x3a\xde\x66\xb9\xcd\x87\x77\xc8\xc6\x1b\x7f\x9a\xae\x79\xf9\x2e\xa3\x03\x33\x0c\x00\x60\x01\xa6\x97\x29\x51\x5e\x67\xac\xe1\x74\x3c\xc7\x60\x0c\xa0\xb7\x5b\xc5\x02\x06\x83\xb5\xae\x45\xaf\xab\x32\x1a\x7d\x61\x9e\xc5\xb9\x5d\x26\xcb\xd0\xf5\x05\x85\xc9\x65\xa9\xe4\x58\x8c\x1b\x3f\x6c\xa9\x5d\xdd\x94\xd8\x3b\x97\xd5\x03\x8f\x6d\xa2\x5c\x60\x2c\x98\x30\x38\xf8\x96\xc3\x71\x6b\x4d\x48\x62\x18\x87\xb7\x31\x0b\xd5\xa9\x41\x4a\x00\x46\xb5\xeb\xac\x7a\xa7\xfd\xff\x31\xf7\xde\xf1\x71\x54\xf7\xfa\xf0\xf9\x9e\x69\x5b\x67\xfb\xae\xb4\x92\x56\x5b\x67\x56\x6d\x25\x6d\x95\x2c\x69\xb5\x96\xbb\x25\xdb\x72\x97\x2d\x4b\x96\x1b\x96\xe5\x26\x37\x6c\x8c\xc1\x8b\x6d\xaa\x6d\x30\xc6\x36\xd5\x58\xc1\x10\x20\xb4\x98\x9b\xd0\x8b\x20\x09\x2d\xe0\x40\x42\x0f\x45\xd4\x40\x12\x08\xe1\x06\x02\x96\x76\xf4\x7e\xe6\xcc\x4a\x96\x65\xdf\x9b\xfc\xee\xbd\x7f\xbc\xfa\x68\xf7\x94\x39\x33\x73\xe6\xec\x99\x53\x9f\xef\xf3\x98\x69\x86\x56\x3d\xd5\x5e\xb3\x2f\xbe\x3a\xa6\xd3\x6e\x9d\x68\xe4\x2b\x6b\x31\x6e\x56\xc6\x0c\xe3\xd4\xc0\x3c\x49\x46\xe6\x35\x44\xcf\xfb\x0c\x94\x02\xb8\x18\x1d\x44\xc2\x2e\x5a\x6e\x92\xb8\x24\x13\xa2\x38\xd6\x1f\xe2\x98\x7f\x74\x5c\xb1\x64\xc9\x15\x99\x4d\x4b\xae\xe8\xe8\xb8\x22\xb3\xb0\x7a\xf5\xe5\x57\xfe\xea\x15\x10\xa1\xfa\xed\xbd\x7f\xb8\x7e\x49\x19\x55\x3c\x69\xcd\x8e\x69\x8f\xae\x28\x58\xdc\xd6\x31\x51\xd0\xcd\xb8\x49\x3a\x71\x97\xf4\xde\x7b\x4f\xee\xda\x34\x7e\xbc\xa7\xbc\x44\x3e\x69\x09\x39\x75\x09\x53\x59\xbb\xa0\x31\x12\x74\xf0\x8c\xc6\xe1\x2e\xaf\x9a\x3c\x73\xc5\x9a\xb1\x47\x17\x46\x36\x2f\x3e\x6f\x66\x73\x6d\xa4\xd0\x48\x61\xa3\x2b\x1a\x99\x5a\x33\x27\x31\x73\x08\x73\x90\xd5\xe5\x2a\x24\xac\xa0\x8d\x68\x25\xda\x4a\x94\xb9\x46\x2a\x15\x09\xfe\x51\x34\xcd\x96\xb0\xcd\x64\x2d\x01\x6f\xcc\x14\x8d\xd0\x64\xb2\xc8\x0d\x2f\x27\x84\x20\x16\xc5\x6e\xda\x3c\x64\xf3\x6c\xb1\x29\x98\x3b\x85\xe4\xba\x00\x86\x43\x82\x9b\x1d\xcd\x85\x48\x17\x49\xf7\x4b\x2f\x7f\xb8\x67\xcf\x87\x10\x85\x59\x10\x95\x7d\x99\xb5\x67\x33\x3d\x6f\x34\x1a\xdd\x46\x23\x5c\xd8\xd5\xe8\x2b\x20\x53\xfc\x02\xdf\x4c\xc5\xb2\x79\xc8\x54\xfa\xf7\x24\x7a\xf7\x63\xbb\x89\x7b\x52\x7a\xef\x24\xd5\x21\x38\x07\xd2\x43\x84\xea\x4c\xef\x9e\x0f\xa5\x97\x47\xdd\xed\xd7\xe7\xe0\x85\xce\x4c\x37\x4a\xf2\xbd\xfa\x8c\xa9\xc6\x98\x6f\x8c\x69\x23\x6f\x36\xf3\x1b\x4d\x63\x7c\x31\xaa\x71\x94\x61\xb6\xf4\xb5\xb2\x9c\xd6\xb6\x7b\x77\x9b\xe2\x3b\x78\xf2\xe4\xc0\xd5\x98\xb0\x22\x12\xaa\xde\x21\x7b\x32\xb5\xc2\x2b\xef\x20\xe3\x3a\x79\x2e\x16\x31\xf9\x46\x15\x45\x8c\x8c\xa6\x6c\xa3\xa1\x55\x61\x3b\x97\xfe\x31\xcd\xa1\x74\xda\xcc\xff\x40\x40\xf0\x1c\xb1\x91\x6f\x8c\xb5\x37\xfc\xd0\xdb\xd0\xde\xde\xc0\xa5\x1a\xda\x63\x8d\x34\x92\xc7\xb2\x99\x5e\x48\x2b\x0b\xfa\x03\x8a\xed\x7b\x8f\x94\x8e\x35\xf6\xc8\xc9\x28\x92\xb8\xa7\x11\x8d\xca\x53\xde\x70\x9e\xb2\xeb\x11\xa3\xb2\x60\xcb\x85\xb3\xb2\x6a\x02\xc4\x20\x4c\xec\x83\x46\xe6\x62\x54\x16\x29\x94\x41\xb8\xb7\x31\x36\x2a\x0b\x99\x8e\x33\xf3\x08\xee\xff\x8b\xfc\x50\x69\x1a\xfd\xff\x29\x3f\x18\x31\xff\x77\xe5\x83\x87\xf3\xe3\x40\x25\xa7\x57\x8e\xfe\x9d\x9c\xa8\xfe\xfb\x5c\x50\xff\xd6\xfd\x01\xa1\x41\x86\xbe\x90\x45\x28\x9f\xb0\x78\xb2\x3e\x8f\x65\x48\x2a\x93\x28\x9a\x08\x59\xe5\x77\x07\xbd\x96\xc8\x7f\xec\x7a\x51\x63\xcd\x39\x91\x5b\xa1\x7d\x5a\x7a\xc1\xe2\xd4\xe9\x82\x41\x9d\x2e\xcf\x0c\x5f\xb9\xc4\xa0\xe4\xcf\xad\xd0\x36\x6a\xac\x39\xf0\x6b\xe9\x05\x0b\x63\x2a\x66\xfa\x8a\x4d\x8c\x45\xe1\xaf\xa6\xd2\x2c\x22\x1a\x05\x6e\x9b\x29\x62\xf3\x99\xac\x9e\x88\xcd\xe7\x16\x59\x8f\x2f\x16\x71\xc7\x4c\xbe\x58\xc4\x14\x25\x7e\x47\xdc\x13\xb1\x51\x29\xa9\x37\x9d\x86\x54\x2a\x25\x7d\xd3\xdd\x2d\x7d\x93\x4a\x41\x2a\x9d\x96\x7a\x53\x29\x30\x76\x77\x83\x31\xc5\xa4\xfb\xa4\x8e\x74\xa6\xaf\x2f\x7d\xf0\x60\xba\x0f\xbb\xd3\xd0\x43\xbc\x4a\x71\x0e\xd9\x35\x0c\xa9\x3d\x94\x10\xd6\x8b\x1a\xb2\x72\xea\x33\x45\x4c\x04\x88\x64\x92\xdf\x54\x8f\xcd\x13\xf3\x30\x36\x22\xc2\x1c\x33\xc5\x7c\xb6\x40\x2c\x62\x22\x88\x56\x53\x44\xd1\xd3\xcd\x1a\xac\xcb\x2e\xb1\x5f\xb7\xa9\x50\x3a\x2d\xa5\xfb\x91\x94\x4e\xa7\x21\xcd\x20\x48\x0f\xa2\xf4\x8f\x28\x9d\x66\x51\x3a\xdd\xaf\xb8\x12\x82\xf4\x40\x5a\x4a\x53\xe9\x0c\xc2\xe9\x4c\x9a\x46\x83\x48\x4a\xd3\xe9\x81\xec\x59\x34\x82\x21\x7d\xdc\x53\x48\xfe\xa6\xb3\x9a\x0f\xb2\x2f\x83\x48\x0d\x4a\x63\xb9\x16\xc9\x27\x64\xb9\x73\x90\x5a\x7e\xa6\xc2\xe1\x35\xa2\x48\x56\xc3\x62\xfe\x99\x4f\x75\xe6\xb3\x99\x7c\x43\x4f\x08\x23\x9f\xd2\x67\x8b\x04\x3c\xa7\x1f\x15\x62\x44\x9d\x5a\xae\x67\x31\x4f\xf6\x52\x11\x9b\x27\xa6\x26\xcf\x2a\x3f\x49\x5a\x4a\x2b\x59\xa7\xd2\x20\x3b\xe4\xa9\x33\x28\x7d\x2a\x9d\x4e\x33\xe9\x74\xba\x3f\x4d\xa5\xd3\xe9\x01\x45\x97\x42\x8e\x18\x3a\x85\x22\x34\xc6\xca\xb9\xf2\x07\x13\x57\xca\x8a\x03\x93\xef\xfe\x6c\x51\x60\xb2\xfd\x91\x51\x8e\x20\x3c\x74\x4f\xb9\x00\x4e\xcf\x05\x4d\x28\x87\xbc\xb5\x23\xde\x0e\x93\xc7\xcb\x3a\x3c\x72\xad\xe5\x68\x34\xd0\x11\xac\xaa\x0a\x32\xa9\x60\x15\x91\x28\x86\x8b\x0c\xe1\x47\xc2\xb3\xc0\x2d\x75\x28\xb1\x55\xc1\x81\x8e\xaa\xc9\xb3\xc2\x8f\x84\x0d\x68\xa4\xad\x0d\x4b\x74\x95\x11\xf8\x6c\xf1\x7a\x88\x07\x86\x56\x3f\xe4\xb6\xdb\x00\xa7\xcd\xa1\x88\xa5\xd0\xb6\x1f\x0a\x74\x8f\xea\xa4\x6f\xc1\xdd\x8f\xa8\x74\x15\xbc\x10\xcc\x7f\x24\xbf\x23\x38\x80\x86\x6e\x0d\xe8\x07\x8d\xee\x51\xdd\x51\x2a\xdd\x8f\xc0\x1d\xac\xa2\x7a\x06\x50\xb0\x23\xff\x91\xfc\x60\x36\x13\x43\x9a\x4e\x43\xfc\x59\x39\x48\x44\x63\xd1\x1c\xb4\x9c\x58\x5d\x0e\x13\x12\xc6\x87\xfd\xf6\x88\x9d\x21\x62\x29\x3e\xaf\x68\x73\x41\x21\xb8\x03\x31\x96\x63\x85\x28\x99\x2f\x86\xa0\x1c\x04\x62\xc9\x9c\x20\xa6\x6b\x31\x45\x71\xdb\x2b\xf8\x3c\x26\xcf\xd9\xa6\x4e\xdc\xb1\x42\x87\x4a\x73\xe3\x8d\x1a\x95\x43\xef\x72\x50\xba\xbd\x7b\x29\x2d\x38\xfa\x57\x7d\xda\x34\x6e\xcd\x05\xb1\x2b\x8a\x8a\x61\x32\x7e\x69\xd9\x8a\x35\xdb\xb7\xaf\x59\xb1\xac\xa2\x33\x3f\x7f\xe7\xc3\x4b\x4b\x4b\x97\x3e\xbc\x73\x05\x35\x65\x5e\x43\x75\x6a\x56\x03\x65\x66\xa4\x6a\xf8\xcb\xd4\xc5\x67\x52\x14\x45\xa3\x01\x06\xef\xc3\xcc\x03\x61\x2f\x0d\x97\x00\xdd\x07\x51\xe9\xe5\x31\x53\x6a\xba\x0d\x46\x00\xcf\x86\x28\xa7\x5a\xfa\xd8\x52\x15\x17\xe9\xd6\x19\x30\x66\x83\xcd\x1d\x9b\x3b\x9a\x83\x2c\x7d\x75\x7c\x02\x43\xa9\xc6\x85\x12\x0d\x14\x48\x78\x0a\x15\x3f\x83\x7f\x88\x19\x2e\x27\x06\x69\x91\x13\x85\x50\x52\xae\x01\x3c\x58\xed\xfe\xa8\x20\x9a\xe2\x88\x28\x9f\x85\x88\x74\xa7\x9b\x06\x62\xc8\x4d\x2c\x54\xcd\x74\xc4\x13\x4e\xe2\xb3\xac\xa6\x16\x76\xed\xd9\x83\x97\xee\xe9\xea\x82\xd6\xa3\xd2\xb7\xc7\xb6\xbe\x73\xb4\xed\x28\xf0\x90\x04\x1e\xe7\xaf\x7f\xe4\x3f\x77\x4b\x7f\xf8\xb9\xf4\xce\x03\xf7\x43\xf1\xfd\x50\x76\xc9\x77\x8f\xac\x87\x96\x91\x4f\x09\x22\xfe\x65\xd1\x93\x7f\x7e\xf2\xc9\x3f\x3f\x59\x94\x99\x5a\x04\xaf\x49\xcf\x4a\xdf\x1e\x6d\x3b\xfa\xce\xd6\x63\xc0\x1f\x3d\x2a\x35\xed\xfd\xee\xa7\x1d\xb7\x49\x6f\x3e\x76\x8f\xf4\xc7\x9f\xad\xb8\xfb\xaf\x14\x7b\x26\x0f\x16\x75\xc6\x58\xad\x06\x21\x66\x54\xdb\x7e\x16\x7f\xb4\xcd\x77\xda\x80\xcd\x4e\x78\xfb\x4e\x73\x53\xa5\x2d\xfa\xfe\x5e\xbd\xc5\xa2\xa7\x53\x7a\x4b\xba\xbd\xa1\x9f\x34\xf5\x74\xaa\xa1\x5d\x4a\x0f\x1f\xeb\xe9\x19\x8a\xec\x90\x93\x65\xa3\xe9\x69\xa7\x13\xb7\x43\xb2\xa7\x67\xe8\x48\x3a\x1b\x97\xd5\x7b\x55\xc9\x6d\x37\x46\x0c\x8a\xa1\x3a\x34\x17\xad\x45\x48\x0d\x1e\x35\x78\x80\x07\xce\x34\xbc\xfe\x3b\xbc\xea\x1b\x02\x71\x38\x40\x58\xc6\x87\x92\xd0\x43\x6b\x5a\xca\x8e\x0b\x01\x16\xc6\xc3\x0e\x17\xcd\x8c\x8e\x60\x7b\xa5\x34\x85\x7e\x94\x5b\x50\x04\xbf\xe4\xeb\x83\x98\x8c\xc2\x4e\x91\xde\x0d\x77\x04\xeb\x79\xc9\x46\x7a\xb0\xbf\xd8\x96\xee\x58\x6a\x83\xbf\x90\xed\xc3\xfa\x86\xf2\xf2\x86\x72\xfa\x40\xdb\xd5\xd7\xed\xb9\xee\xea\xb6\x89\x1b\x97\x77\xd2\xe6\x26\x33\xdd\xb9\x7c\xe3\xc4\x7e\x74\xae\x58\x3a\x95\x49\xe1\xde\x4c\x8a\x4a\x07\xeb\xf9\x53\xdf\x9d\xa6\x27\x62\xb4\x7c\x7d\x90\xf8\xaa\x27\x4d\xaa\x26\x1e\x63\xb9\x7c\xf9\x81\x25\x53\x36\x37\x78\x3c\x0d\x9b\xa7\x68\xf7\xbd\xf6\xd0\x63\x9c\xc7\xc3\x3d\xf6\xd0\x6b\xfb\xb4\xe7\x8c\x1d\xb9\xc6\x59\x86\xa6\x21\x04\x46\xcc\xd9\xcd\x43\x90\x87\xd3\x12\x5c\x46\x73\x42\xc0\xa6\x11\x9b\xf8\xe4\x30\x24\xa9\x98\xc7\xea\xc2\x0e\x17\x58\x59\x8e\xa7\x6c\x9e\x68\x08\x8b\x21\x88\xc6\x99\xf4\x1b\x3d\x3d\x6f\x28\x65\x42\xb2\xdc\x31\x1c\x66\x14\x7b\xca\xab\xa6\x1d\xd8\x34\x71\x00\x4d\xdc\x74\x60\x9a\xc5\xe1\xb0\xc8\x21\x7a\x28\xc4\xa4\xa5\x7e\x69\x7d\x57\x97\xb4\x5e\xea\x1f\xc1\xce\xc4\xc0\xb5\x5d\x5d\x70\x2d\x30\x23\x58\x9a\x6a\x0b\x76\x3e\xf8\xed\x9e\x3d\xdf\x3e\xb8\xb3\x80\xf3\x04\x3d\xdc\x99\xc1\x91\x6b\xab\x65\xa4\x3f\xfa\x7f\x7b\xc2\x12\xf0\x58\x1d\x9e\xb8\x49\x7e\x2c\x1f\x4f\xd9\xfe\xe5\x63\xf5\x0d\x20\x35\xf5\xb5\x7a\xfc\x86\x7d\x4d\x9f\x37\xed\xdb\x30\xfe\xdf\x7f\x92\x86\x64\xdd\xa9\x71\xbb\xfe\x76\x62\x67\x61\xe1\xce\x13\x7f\xdb\x75\xe6\xba\xb0\x9c\xf7\x9a\xff\x59\xde\xa9\x10\x88\x3e\x1e\xb8\x7f\x27\xeb\x73\xa9\x79\x73\xab\xe3\x0f\xaf\xfc\x7c\xe5\xc3\xf1\x7f\x3f\xe7\x27\x1f\x7c\x70\x80\xdf\xff\x62\x71\xf1\x8b\xfb\xcf\xac\x4f\x93\xfe\x77\xf5\x89\xe5\x3c\xc2\xff\xac\x32\x5d\xb9\x1a\x3f\xb1\xfa\xca\xff\x5d\x45\x8a\x5c\x7b\x6d\x44\xa9\x42\x23\x7e\x07\x03\xaa\x46\x53\x10\x62\x46\x35\x29\x89\xa4\x2a\x11\x52\x89\x1e\x5e\xc5\xb9\x54\x0e\xcb\xa8\xa3\x4c\xdf\xe9\x9c\x2f\xa5\x9c\xde\x31\x95\xcd\xd1\x05\xa5\x25\x25\xa5\x0b\xa2\xcd\x95\x63\xbc\x4e\x8a\x1e\x38\x57\xec\xd2\xd3\x67\xa5\xcc\x3c\xb1\x4c\x4e\xf3\xe6\x54\xa2\x73\x5e\x4b\xaa\xb1\x6c\xac\x2b\x3f\xdf\x35\xb6\xac\x31\xd5\x32\xaf\x33\x71\xae\x38\x16\x9d\x3e\x69\x04\x76\x02\xa1\xb1\xa8\x0b\x21\x62\x95\xec\xcb\x4a\xaa\x9b\x44\xc5\x53\x00\x56\x07\xd8\x6d\x4a\x1b\x5f\x07\xd1\x84\x25\x9e\x25\x1c\x53\xd2\x8a\x23\xbd\x62\x98\x68\x81\x93\xaf\x02\xb0\x12\x92\x2e\xa5\x53\x00\xe5\xb1\xc3\x0e\xc5\x8c\x8f\x42\xb1\x46\x77\xaa\x22\xd4\x40\xbe\x7c\x10\x17\x05\x27\x4e\x3b\x05\xcd\x1a\x0d\x89\x0d\x8b\xbc\x3a\xd4\xe0\x1e\x1b\x66\x54\x73\xc6\x56\x37\xd4\x74\x7a\xf3\xdc\xcb\xf7\xe9\xd7\xb2\xdd\xcd\x99\xf4\x9c\x35\xd2\xcb\x4d\xfb\x97\x69\x19\x76\xef\xe2\x68\x68\x32\x9d\x6e\x8c\xa5\xdb\x2a\xc6\x35\x84\xa4\xd9\xae\x7b\x65\xb7\xaf\xdc\x27\xbd\x2d\xd6\xcb\xd3\xde\xdc\x22\x3f\xfc\xc2\x5f\xf4\xbd\x1c\xed\xbe\x28\x38\x56\x85\x1b\x42\xe9\xed\x91\x69\x0c\xa4\xc3\xde\x78\x25\x77\xcd\xf2\xef\x23\xd5\x52\x53\x4e\x79\x73\xf7\x96\x39\x10\x9c\x72\x5e\xdf\xb2\xfd\xb0\x78\x97\x6d\xc2\xe9\xbd\x9e\x0e\x16\xa1\x4a\xd4\x82\x10\x92\x8b\xc5\xa7\xd8\x82\xe4\xc2\x10\x09\x23\x90\x92\x49\x58\xe2\xb1\xac\x95\x88\x6f\x84\x3b\x5c\x16\x71\x79\x8a\xc4\x51\xca\x90\x4c\x84\xac\xd5\x9f\xb2\x4d\x11\xa7\x6e\x5d\xd4\xe0\x6e\x58\xd4\x70\x93\x90\x8a\x35\x3a\x21\x2d\xa4\xf0\xcf\xbd\x71\xae\x89\x69\x50\xe2\xdd\xbf\xb8\x62\x53\xa1\xc5\xb1\x6c\xff\xaa\xeb\x55\x4d\xfc\x45\x33\x33\xcd\xb5\x6b\xfd\x52\x3a\x72\xa4\x6b\x7a\x78\xff\x32\x87\xa5\x90\x49\x37\x84\x32\xdd\xd8\x18\x6a\x68\x08\x65\xbe\x19\x44\xaf\x44\x1a\x63\x25\x5e\x09\x45\x4a\xbd\x70\xd8\x9d\x07\xdf\x12\xbb\xd1\x6f\x86\x12\xe0\x03\xa1\x67\x27\xd5\xd1\xfb\x97\x99\xd8\x7d\xab\x24\x3e\x58\x22\xad\x99\xd1\x99\x28\xc7\x68\xfc\xbc\xae\x23\x5e\x78\x70\xd9\x7e\xba\x6e\x98\x83\x8f\xec\xf5\x0a\x28\x86\xa6\xa2\xa5\x68\x37\x42\x8c\x3c\xbf\x52\x96\x59\x12\x1e\x05\x32\x3e\xcc\x34\xcd\x64\xe1\x4a\x1c\xc3\x52\xf2\xf8\x53\xa1\x2f\x0a\x84\x20\x46\xaa\x0c\xc7\x10\x8e\x5e\x39\x2a\x09\x54\x60\x88\x96\x9a\xb1\x65\x39\x47\x12\xb1\x68\x3d\x50\xe4\xa8\x62\xe3\xcf\x65\xb5\x2b\xea\x20\x42\x4c\x23\x6d\xf2\xa5\xe9\xca\x13\xc7\xeb\x1d\xc9\x29\x8c\xd4\xdf\x75\xe4\x48\xd7\x86\xd2\xa9\xad\x47\xba\x42\x65\x78\x33\x5c\xdb\x75\x64\xcd\x3c\xe9\xbe\x45\xd7\xdc\x7c\xdc\xe5\x6f\x08\x39\xad\x30\xab\xb2\x1e\x52\xb2\x4f\xfa\x20\xdf\x5c\x62\x34\xd6\x87\xad\x66\xe8\x70\xf9\xbf\xc8\x9c\x9f\x63\x8f\x35\x96\x05\x30\x9f\x21\x33\x52\xec\xf8\x32\xb4\x7e\xcd\xac\x29\x30\xbb\x24\xde\x18\x93\x5e\xbe\xc2\x2f\x97\x7b\x75\x74\x42\x48\x90\x5e\x4a\xef\xaf\x8c\x31\xae\x2d\x13\x04\xcd\x91\xd7\x8f\x98\xf2\x77\x37\x77\x1d\x31\xfd\xed\x48\x57\x66\x79\xcb\x5e\xdb\x5c\x07\x7e\x7e\xd2\x54\x3e\xe1\x09\x35\x68\x6e\xd2\x34\x87\x07\x51\xa8\x41\xb3\x47\xaf\x72\xda\x02\xf6\x70\x4a\xdd\xc3\x27\x28\xd3\x0f\xaa\xc6\x58\xb0\x81\x7f\x21\xd5\xd8\xd5\xd8\xf5\x5c\x7d\xc9\x79\x03\xc8\x32\x57\x3b\xa1\x14\xdf\x12\x6b\xbc\xd8\x53\x29\xbd\x1d\x4a\x4e\x0c\xbd\xfa\xea\xc4\x52\xd5\xcc\x58\xf1\x64\xd3\xfe\xe1\xba\x47\xe6\x83\x7e\xc2\x8f\x17\xb6\xcb\xaf\xe1\xb0\x04\x66\x60\x78\xb0\x22\xff\x08\xa2\xe2\x07\x53\x54\x04\x65\xc8\x65\x75\x81\xfc\xaa\x79\x6c\x9e\x2c\x6b\x52\xc4\x43\x50\x15\xd9\x59\x81\xfc\x5a\xcb\xf5\xd6\xc1\xb8\x20\xeb\x8d\xd3\x3b\xeb\xd6\xf9\x71\xed\xf9\xdd\xcd\x52\xba\xb9\x5b\xfa\x38\xf3\x41\x73\xf7\xdd\x5b\xe1\xf6\xe2\xcc\xac\xe5\xd7\xa9\xc6\x76\x37\xb3\xbd\x6d\x99\x5f\x89\xa9\x81\xb1\x4e\x81\x32\x9a\x34\x91\x42\x2a\x35\xd0\xeb\x14\x28\xd5\xe4\x32\x9c\x6e\x0d\x56\x31\x29\x4d\xb8\x50\x9a\xd0\xd0\x2e\x38\x71\xa5\x51\x0f\x75\x39\x05\x82\x13\xd2\x4e\x81\x45\x55\x95\x03\xff\x79\xec\x05\xe9\x68\x73\x77\x77\xf3\x89\x6b\xba\x9b\xdd\x5b\xef\x4e\x5f\xbe\x6c\xc6\x4a\x77\x73\xf7\x8f\xbd\xb0\xec\xe8\x4e\x4a\x1f\x15\x9c\x6e\x5f\xc8\x5a\x28\xb8\x05\x67\x29\x5f\x3a\xa6\x2a\x68\x30\xf4\x16\x04\xda\x1b\xdc\x4e\x81\xbb\x55\x1f\xca\xfb\x0d\x59\xc0\x52\x38\xf1\xe4\xb1\x5d\x18\x6d\x96\xdb\x2c\x41\xa4\x84\x58\x94\x7c\xc5\xb3\x14\x6f\x79\x90\xa5\x7a\x03\x9b\x95\xa3\xb2\x94\x24\x2c\x07\xac\x8f\xf2\xb2\x1c\xe5\xa3\x86\xc8\xa4\x2c\x23\xbc\x2e\x90\x3f\x11\x4f\x38\x01\x8a\xa1\x1e\xc7\xc4\xa2\x4e\x48\x0c\x91\x9d\x50\x3e\x8b\xec\x85\xdf\x4e\xbb\xc0\xb2\x42\xcf\x6c\xe6\x76\xb4\x99\x76\xcf\x9f\xbd\xcb\x3a\x7b\xa5\x75\xd7\xec\x05\x97\xf2\x8b\xb6\x71\x17\x6a\x12\xf6\x0a\x6f\x65\xee\xaa\x23\xd5\x61\x89\x19\x3f\xb7\x52\xa8\x53\xdf\xbe\xf3\x5a\x75\x9d\x50\x91\xa2\xf6\x38\x97\xa9\x93\x42\x79\x03\xb5\x99\xa3\x55\xcb\x55\x51\x0f\x7e\xa8\xd8\x0b\xfd\x55\x8d\xd1\x12\xaf\xf4\x4a\x6a\x32\x45\xa7\xca\xc5\x3a\xf5\x66\xe7\x11\xaa\x7e\x10\x2d\x6e\x84\x6b\xab\x23\x65\x76\x78\x3f\xcf\xd5\x76\x85\x66\xee\x9a\x95\x33\xa5\xdb\xe1\xde\x99\x2b\x37\xcd\xd7\x5c\xd5\x96\xe3\x93\x10\x57\x62\x74\x69\xb5\x87\x56\x25\xbb\x05\x69\x4f\x84\x4d\x57\x08\x99\x79\x78\xa1\x50\xd1\x50\x6e\xd0\x67\xde\x87\x1b\x02\x91\x86\x10\xaf\x93\xbc\xf9\x9b\x5d\xd2\x7a\x77\x91\x13\x2e\x2c\x19\x17\x9d\xe2\xfc\xfc\x13\x1a\x74\x10\xd4\x9b\xb5\xe5\xe3\x2b\x04\xc9\x85\xbb\x79\xbe\x62\x7c\x76\xcf\x57\x2e\xd7\x08\x61\x20\x59\x46\x98\xb8\xce\xdd\xd2\xd5\x29\x22\xe3\xbe\xd8\x88\x7e\x40\xf1\x98\xa2\x82\x48\x9a\xbb\x08\xe9\x09\x4e\x77\x04\x67\x37\x7c\x96\xac\xca\x94\xfc\xc1\xe9\x58\xe3\xf5\x45\x0d\xd1\xa9\x4a\xe3\x77\xd2\xee\x63\x16\xe5\x54\x35\x57\x29\x5d\xc4\xd4\x78\xac\xd1\x3d\x35\xbe\xfa\xb0\x5d\xb3\x6c\x6a\x79\x74\xc3\xa4\xbc\x82\xf6\x5d\xf9\x8b\x8c\x9d\x0d\x99\xb0\xd2\x10\x1e\x5e\x35\xa9\xe6\xc8\x9f\xdd\xe0\x96\xff\x99\x74\x63\x4c\x42\x52\xfa\xa5\x78\x53\x94\x34\x82\x79\x36\xe8\xee\x58\xfa\x4e\x51\x6d\x55\xb0\x4e\xee\x07\x52\x0b\x13\x33\x1a\x63\x1d\x78\x4c\x62\x46\xfa\xe6\xd5\xef\xe1\x09\xb6\xf9\xdc\xe5\xed\xef\x6c\x5e\x2b\x1d\x48\xcd\x54\x9a\xc1\x55\xd7\xfb\xb0\xaf\xeb\xc8\xa9\xac\x1d\x9a\xf2\x19\xb1\x2f\x1e\x20\x2a\xb6\x4b\xd0\x2e\xa2\xb4\x32\xf2\x11\x63\x26\x2a\x0b\x61\x2a\x04\x85\x6b\xd5\x24\x07\x38\x2f\x6b\x20\x54\x84\xa4\x12\x39\xbc\x3c\x95\x65\xb0\x54\xba\x8e\xa8\x00\x56\x87\xc5\x96\x88\xd7\x40\x62\xa8\xfb\x50\xaa\x26\x64\x4b\x9c\x22\xac\x2f\xa2\x32\xaf\x8e\x93\x89\x95\x01\xe4\xa9\x17\xa3\xaa\x2d\xdf\xef\x98\x6b\xdb\xdb\x92\x59\xde\x75\xe4\x6f\xa6\x23\x5d\xcd\xbb\xf3\x4d\x47\x5e\x3f\x92\x67\x9b\xb0\xe5\x31\x4f\x82\x9f\x3a\x29\x11\x6e\xd6\xdc\xa4\x69\x78\xc0\x1e\xb0\x39\x55\xfa\x3d\x9a\x86\x90\x27\xc1\xf7\xa8\x53\xfd\x63\x55\x3f\x9c\x57\x52\xff\x5c\x57\x63\x57\x63\xea\x05\xbe\x21\x18\x6b\xa4\xf3\x4b\x27\x68\xe7\x5a\xf6\x9b\x26\x17\xc7\x66\xaa\x4a\x27\xbe\xfa\x6a\x68\x62\x32\x24\xbd\x5d\xe9\xb9\xb8\x31\x46\x5d\xe0\xa8\x3f\x7e\xa2\x7d\x91\x74\xdf\xbc\x35\x47\xba\xe0\x5a\xbc\xb9\x2c\xd4\x75\xa4\x75\x6a\xe9\x06\xb9\x21\x96\xfa\x99\x29\x09\xbf\xeb\xf8\xcd\xf5\x95\x30\xcb\xea\x0c\x35\x5c\x6e\x34\x96\x98\xf3\xa5\x0f\x64\xbf\xdf\x05\x1d\x66\x6b\xb8\x1e\x56\xda\x73\x32\xe7\x4f\x58\x1f\xfa\x12\x3b\xe4\x76\x37\x93\xc6\x7c\xa0\xac\xf1\xd4\x5f\xe2\x25\x30\x7b\xca\xac\x56\xe9\x25\x21\x34\x21\x5a\x2d\xf7\x7a\xfe\x2b\xa4\x97\x63\x8d\xc3\x3c\x30\xdc\x2f\x68\x84\x72\xc9\xf8\xd1\x76\x6e\xe4\x4e\xd8\xce\x58\xec\x1c\x89\x15\xb5\x20\xbb\xa2\x16\x88\xb0\x8f\x28\xc4\x2c\x0a\x71\xa8\x85\x6c\x4a\x5b\x14\x4e\x98\x05\x16\xbd\xf4\xa6\x59\x7f\xb9\xde\x22\xbd\xa5\xb7\x98\x79\x2a\x57\x6f\xa1\xf9\x69\xa0\xd6\xe8\x2f\xd3\x99\x21\xf4\xa4\xca\xb6\xcd\xaa\x7e\xa2\x0c\xcc\xba\xcb\xf5\x1a\xf5\x74\x30\xeb\xae\xb6\xaa\xdf\xd3\x68\x28\x3d\xfd\xbe\xda\xba\x5f\x6f\xa6\xfa\xb6\xe8\xcd\x03\xaf\x93\x93\x4b\xcd\xfa\x2d\xbc\xd9\xa2\x19\xa8\xd7\x6b\x35\x26\x1d\x6e\x92\xe6\x5b\x2c\x70\x4f\xe6\x41\x9d\x49\xa3\xe1\xa9\x67\x74\x26\x4b\xe6\x87\x9c\x3c\xce\xa7\xc6\x2a\x8b\x69\x08\xc3\xa0\xcc\xa9\xd5\xa8\x18\x8d\x51\xec\x10\x44\x45\xc6\x21\xee\xc8\x3e\x8b\x48\xf9\xce\xa4\xba\x51\xc0\x64\x9c\x1d\x8f\xda\x24\x41\x23\x36\x48\xfc\x6e\xda\x4e\x9b\x6b\x3d\x73\x2e\xbc\xad\x61\x72\xf4\x15\x95\x5a\x65\xb9\xc1\xaa\x7a\xf6\x66\x33\xaf\xe0\xa0\x85\x74\x72\xee\xd2\xb9\x53\xd8\x32\xe9\x75\xe9\x9b\xdf\x6c\xd9\xf2\x1b\x30\x42\x29\x18\x89\xef\xdd\x73\xec\x42\x50\x63\x5b\x3c\x66\xe9\x4f\x53\xdf\x91\xf6\x9a\x78\xa3\x09\xd6\x4a\xb7\xc9\xd7\xa1\x7a\x79\x73\x4e\xe1\x2d\xe7\x2d\xba\xce\xaf\xa1\xe2\x5b\x7e\x23\x7d\x33\xea\x7a\x52\xe3\xa8\x0b\x5d\x7d\xf5\x37\x23\x9f\xbb\x0c\xb5\x2a\x4a\x57\x10\x4e\xc4\xcb\x41\x10\x05\x03\xf0\xcc\x30\xbd\x51\x21\xd8\x13\xf1\x7a\x88\x8b\x21\x5a\x19\x2b\x78\xfe\xbd\x64\x67\x15\xcd\xa8\xfd\x23\xdc\x76\x63\x27\xaf\x2d\x63\xcd\x46\x2d\x4d\x1b\xac\x79\xae\x80\xa5\x69\x69\xc7\xd4\xc0\x04\xa3\x51\x6b\x30\xaa\x62\x7a\x03\x65\x2c\x8d\xcd\x2a\x3b\xf4\xeb\x67\x29\xdd\x8d\x9d\xbc\xa6\x4c\x65\xfa\x17\x49\xaf\xfb\xcd\xb3\xe2\xd9\x85\x99\xb9\xfd\xec\xcd\x23\x28\xef\x34\x9b\x67\xe9\x69\xac\xa7\x68\x9d\x81\xd7\x71\xcb\xa7\x35\x2d\xcb\xe7\x79\x2d\x60\xdd\x74\xab\x85\x36\x16\xe6\x5a\x9f\x39\x70\xf0\x69\x39\x15\x4f\xfd\xab\x54\x74\xe5\x39\x8a\x1d\x6c\xe7\xf8\x0d\xe5\xf7\x28\x35\xd8\xc7\xf5\x32\x6e\x82\x29\x41\x6a\xda\xc1\x89\x6a\x48\xa8\x29\x31\xe1\x50\x03\x07\x1c\xe0\x3e\xb9\xa1\xcb\x74\xe0\x9e\xbb\x3a\x26\x4b\x6e\xe8\x7b\x46\xfa\x10\xf7\xe0\x9e\x4c\xc7\x5d\x1d\x93\xa1\x4f\x72\x3f\x03\x9e\x0e\x29\x8d\xfb\xa4\xb4\x94\x96\x0f\x90\x64\x72\x74\xa1\x9c\x28\x9b\x4c\x3e\xed\xa3\x0e\x48\xa3\x33\xd6\x8d\xe4\x7b\x8a\x08\x05\xd4\xc0\x39\x38\x35\x38\x12\xa2\x9a\x49\x88\x09\x35\x88\xdc\xe8\xaa\x8b\x5f\x01\x83\xf4\x65\x4b\x6f\x87\xf4\x25\x38\x82\xf3\x77\x4a\x63\xa8\x52\x78\x4e\x1a\x23\xfd\x1d\x1c\x2d\xbd\x1d\xe0\x90\xbe\x0c\xce\xa7\x9a\xce\xf1\x90\x0f\x81\x01\x1c\x2d\x4f\x77\x80\x43\x3e\x31\x2d\x8d\x91\x1a\xe0\x39\x78\x4e\xfa\xbb\xf4\x65\xcb\xd3\x1d\xd2\x97\xd2\x97\xc1\x16\xf8\xf1\x1c\x95\x52\x83\xd0\xe0\x7b\x6a\xc4\xf8\x91\x16\x59\x50\x7e\x56\x65\x73\x02\x9a\x8d\x5a\x51\xfa\x4c\x55\x80\xa1\x5d\x55\x26\x0b\x2f\x8b\x13\x11\x61\xa2\x95\x42\x52\xc9\xad\xbe\x3f\xeb\x8b\x28\x30\x7b\x1e\x08\x01\x1b\x08\x1e\x37\x17\x76\x61\x5b\x34\x89\x87\x90\xbc\x16\x0f\x4f\xe0\xe9\x98\x26\xed\x3b\x17\x02\xc2\x63\xe9\xc7\x31\x02\x9b\xf1\x10\xf1\x73\xbc\x37\x21\x88\x89\x84\x28\x24\xe8\x5d\x89\xe9\x89\xc4\xf4\x01\x71\x43\xcf\x86\x0d\x3d\x1b\xe8\x4b\x36\x34\xcf\xd8\xb8\xa1\x67\x60\xc2\xf1\x4d\x9b\x8f\xdf\xfe\xf9\x71\x7a\xd7\xf1\xcd\x9b\x8e\x1f\xdf\xb4\x79\xe0\x43\xe9\xef\x4f\x5f\xf4\xfa\x8e\x1d\xaf\x5f\xf4\x34\x75\x8f\x24\xfd\x5e\x7a\x46\xda\xf2\xfa\x8d\xad\xf3\x0f\x9f\xc4\x33\xa5\x6f\xa5\x5d\xd2\xdf\xc1\x00\x17\xd3\xb0\xb3\x34\xa9\x5e\x77\x93\xf4\xc3\xcd\x97\x7e\xd1\x5c\x3e\x4b\x3b\xd7\xdd\xfc\xe5\xa5\x37\x4b\x3f\xdc\xb4\x4e\x9d\x2c\x85\xb5\x87\xe1\x96\x8f\xfb\xe0\x2a\x9c\xa7\xdc\x3e\x81\xe5\xbb\xc7\xdb\xe5\x7b\x6e\xd8\x00\x24\x0f\xbd\xe4\xc6\xc7\xe1\xf3\xe3\xc7\x3f\x3f\x2e\x05\xe1\x62\x30\xec\x78\xe3\xd4\x1b\x3b\x68\xed\xfa\x75\xad\x37\xbd\xbe\x65\xd3\x6b\x37\xb4\x67\x38\x39\x5a\xfa\xbb\x7c\x5b\x9a\x8e\xec\x8c\x5c\xff\xd8\x2d\xd2\x0f\x37\x76\x2f\xab\xba\xd0\x7e\x41\x60\xd9\x86\x1b\x41\x75\xcb\x63\xd7\x47\x76\x46\x96\x6f\xe8\x46\x14\x3a\x6f\x10\xd1\x37\x91\x76\xd1\x82\x9a\x10\x22\x64\x8d\xc8\x8d\x6c\xd6\xd3\xe0\x1c\x70\x01\x8f\x39\x96\x73\x64\xc1\xef\xa2\x20\x66\xc1\xe5\x09\x48\x08\x62\x88\x52\x70\x48\x2e\x3a\x12\x26\xe2\x62\x2e\xa0\x6a\xa5\x2b\xa4\xef\x41\x03\xdb\x40\x23\x1d\x79\x64\xf7\xee\x47\x76\x43\xa9\x9e\xd6\x07\xcb\xc4\x4d\x2f\x4c\x01\xad\xcb\xa5\x2b\x9c\x57\x38\xee\x05\xe9\xbb\xc2\x79\x2e\x5d\x61\x21\x68\x27\xff\x76\xa3\x58\x16\xd4\xd3\x7a\x8d\xbf\x22\xe5\x61\xac\x0d\x93\xbb\xab\x5b\x7f\x1a\x10\x3c\xa9\x0a\x3f\xde\x02\x9a\xc7\x9f\x00\x8d\xf4\xfd\x13\x8f\xc3\xcd\xbb\xdb\x16\xed\xde\xbd\xa8\x2d\x73\x67\x5e\x99\xbf\xc8\x93\x3b\xc5\x36\x99\x5c\x45\xef\x72\x8d\x7f\x41\xfa\x87\xcb\xa5\x77\xcd\x93\xaf\x67\x9b\x92\xeb\x29\xf2\x97\xe5\x59\x5d\xbc\xd9\x49\xf3\x3e\xa7\x3d\x92\x9b\xeb\x34\xf3\xae\x11\xfc\x61\x1c\x8a\xa3\x24\x41\xab\x0e\xed\xda\x87\x80\xe5\x78\xec\x15\xca\x89\x8f\xb5\x3b\xec\x0e\x8e\xe5\x58\x6b\x21\xd8\xc3\xf5\x60\x77\xc8\xdf\xf1\x68\x39\x96\xc7\xbf\xd8\x28\xb8\x59\xa3\xdd\x7d\xd6\xf2\xf1\xb1\xb6\x3d\x6d\x6d\x7b\x20\xa2\xf1\xd7\x14\x6a\x84\x1d\xbb\xce\xcf\xcb\x2b\xac\xf1\x6b\xec\xc1\x71\xb3\xaf\x89\x5c\x5d\x69\xb7\xab\xed\x75\xf6\xa7\x37\x4e\xb3\xd7\xd9\xd5\x76\xfb\xd3\xd1\xfd\x73\xc6\x05\x27\x3d\x25\xfd\xe3\xa9\xa7\x40\x87\xb7\x8f\xa4\x3a\xa5\x24\xf9\x4a\x6d\x99\xef\xad\x39\x4c\xae\x2a\x27\xe8\x37\x9b\x73\x99\x1c\x6b\x59\x4d\x69\x8c\x8f\x5e\x5d\x91\xbd\xc0\xa6\x26\xe5\x92\x4f\x45\xf9\x58\x69\x0d\x98\x41\xf7\x94\x7c\x35\xf8\xe2\x4c\x7e\x53\x65\x0d\xe2\x11\x26\x8d\xcc\x8a\x6e\x9d\x3c\xc9\x21\x48\x68\xbf\x80\xb3\xe2\xe5\xc3\x23\x72\x35\x0c\x0f\x45\xd9\x82\xb1\x0b\xaf\xf8\x4c\x7a\xe6\x81\x9f\x4b\xcf\x7c\x7e\xc5\xa2\x14\x7e\xa6\xdc\x07\x87\x02\x13\x2a\xcb\x7d\xd2\x93\xd2\x93\xbe\x50\xe5\x04\x3f\x1c\xf6\x30\xe9\xd6\xb1\x99\x1f\x7f\x2e\xf5\x7e\x7e\xf9\xe5\x9f\x43\xea\xe7\x98\x4b\x2d\xea\x7f\xdb\x03\x7b\x7c\xe1\xca\x09\x1e\xe9\x25\x88\x7b\x26\x54\x46\xbc\xd2\x0e\x4f\x16\xa3\x7e\x83\x1a\x31\x2b\xe5\x3a\xc7\x00\x8b\x38\x56\x88\x09\x48\x0c\x61\x5f\x54\x88\x79\x6c\x3c\x76\xd8\x91\x23\x6e\x4e\x08\x58\x14\xc4\x18\x63\x53\x00\x5c\x04\x5e\x17\x8f\xc6\xc2\x49\x88\xd8\x78\xe0\x28\xbb\xd9\x01\x21\x2c\xc6\x18\xf9\x67\x42\x1c\xf3\xa6\xf4\x4e\xae\xf4\xdd\x58\x88\xcd\x92\xee\x98\x67\x6b\xdd\x5c\x0a\x78\x92\x38\x33\x6a\x74\xc2\x45\x65\x85\xef\xda\x2d\x6f\x16\x08\xc7\x31\xd4\x8e\xb3\x79\xd6\xb8\xd7\xd5\xe7\x8c\x5f\x0c\xa9\x37\xae\xb3\x24\x37\x7a\xde\xd0\x7f\xc6\xc1\xa3\xfc\xa4\x1a\x27\xbc\x0c\xb0\x37\x99\xf9\xd6\xb3\x12\x3f\x5c\x99\x19\xbc\x14\x00\x9e\xa1\xac\x2f\x85\x37\xcd\x63\x04\x55\x18\xe7\x8f\xf1\xd5\x0c\x1c\x58\x5e\x07\x37\x17\x8b\xf0\x69\x6c\x02\x0e\x43\x39\x0e\x85\x26\xfe\x6d\xfc\x9b\x87\x13\x95\x98\xf3\xb3\x00\x95\x38\x19\x96\x26\x7a\x32\x92\x89\xfa\x51\xa8\xe4\x21\x4c\xe3\x52\x7a\x7f\x7f\xaa\x71\x04\x9f\xb6\x06\xe5\xa0\x8d\x68\x17\x3a\x38\xa2\xc5\x93\x67\x9e\x3c\xcd\x41\x92\x0e\x58\xb9\x10\xf6\x79\x6d\x56\x07\x0f\x1c\x99\x15\x14\x92\xed\xd6\x24\x8e\x45\x09\x65\x76\x08\x44\x32\x5f\x32\xc8\xe3\xfc\x84\x0b\x13\xe1\x9e\x72\xa2\xec\x27\x8f\x74\xcb\xc9\xbc\x80\x25\xf2\x6d\x2e\x70\x10\x71\x8c\x7a\x70\x81\x82\xf0\x18\xd9\x63\x9f\xd1\x1b\x50\xbf\xf4\xe4\x3a\x05\x6f\x58\x30\x40\xbb\x7a\xcb\x65\x7b\x17\x53\xd2\x71\x6e\xdb\x9e\x7d\xed\xf8\xaa\x4e\x2a\x3f\x97\xd6\xd7\x4c\x7d\x7f\xb7\x11\x78\x86\x05\xe3\xe4\xa9\xcf\xdf\x07\x39\x16\x3d\x6b\x77\xe0\x0d\xb7\x16\x4e\xd0\x68\x99\xf1\xfc\x5a\xec\xc9\xa3\xf5\xb9\x56\xeb\xb4\xbe\x3d\x06\xac\x67\x58\x30\x4c\xaa\x7f\xf9\x01\x51\xa7\x0d\xac\xbf\xb1\xb0\x4a\xa3\xa5\xab\xf9\xb9\x3b\xdf\x94\xde\x96\x1e\x93\xde\x7e\x73\xe7\xce\x37\x21\x08\x13\x21\xf8\xe6\x87\xe7\xe8\x60\xf0\x6e\xa7\x20\x67\xc7\x33\x1b\x4f\x50\xad\xdd\xb1\xab\x95\xcd\x3c\xc1\xad\xbb\x70\x77\x6b\xed\x8b\x3f\xc3\x66\x83\x5e\xe3\xed\x3e\xea\x1e\xa7\xd1\xd2\xe3\x0d\xab\x70\xc0\x45\xeb\x0b\x82\x54\xe3\x47\x7b\x0c\x94\x4e\xbe\xed\xe4\x71\x27\xef\x03\xbb\x51\xc7\x5a\x74\xba\xee\x9b\x5c\xe3\x34\x5a\xa6\x41\xbf\xb6\x4a\xad\x4f\x35\x7e\xb0\x4b\x87\xe5\x47\xd0\x4f\xfe\x13\xb9\xf9\xce\x91\x19\xc2\x97\xfc\x57\xe3\x28\xc8\xf6\xad\x76\xe4\x45\xc5\x08\x41\xdc\x61\x77\x04\x04\x9a\x83\xb8\x5f\x0d\x76\x3a\x41\x09\x7e\x1c\x33\x06\xec\x66\xcc\x72\x6c\x00\xe2\x58\xf4\x87\xed\xa4\x61\xa1\x2e\xfa\xe6\x0f\x5f\x6c\xcb\x38\x7b\xa4\x7f\x44\xa4\xbf\xa6\x61\x5d\xe6\x7d\x98\x39\x19\xec\x37\x7d\xfe\xba\xf4\xd3\xe7\xd9\x5f\x8f\xa1\x96\x9f\xbc\xe6\x73\xe9\x1f\x70\xb8\x45\xbb\x42\xaa\x3a\x75\xe2\xc4\xa9\x13\x2c\xc2\xdb\x2f\xfb\x5a\x54\xdf\x79\x10\xee\x3a\x76\x9f\xb4\x26\xb3\xea\x9a\x43\x05\x52\x9d\xe7\x47\xd8\xf9\x1e\x68\x13\x47\xa4\xa7\xa5\xf7\x33\xb3\x2f\xe5\xf1\xfa\xdd\x50\x7f\x3e\x7b\x42\x3e\x49\x7e\xaf\xb0\x5c\xbf\x98\x17\xc9\x6e\x82\x1b\x89\x02\x76\x42\x82\x4a\x82\x3c\x16\x97\xdf\x21\x8a\x60\x3e\x31\xe7\x10\x59\x17\x4e\x24\xb1\xc3\x05\x1c\x4f\x8b\x3c\x88\x2e\x48\xe2\x44\x3c\x24\x7b\x1c\x71\x2c\xd2\xc8\x62\xc7\x3c\xd0\xd4\xe5\xd2\x67\xd2\x84\x35\x63\xcc\x13\x6f\x58\xa9\xd5\x6e\xd4\x17\x7f\xb5\x39\xbe\x9b\xcb\x6d\x8c\xcc\x55\x19\xb4\xb9\x8c\x63\x61\x95\x61\xaf\xd9\x16\x69\x2e\x8a\xb4\x4f\x09\xd4\x55\xab\x81\xe2\xed\x45\xce\xda\xbb\x2f\x9a\x7a\xa2\xe7\xf0\xea\xbc\x12\xd5\xb8\xb2\xf9\xcb\xf3\x0c\xd7\x5e\x09\x6a\x10\x68\x3c\xf7\xb6\xb7\xa5\x2f\x07\x11\x94\xfd\xb0\x1b\xe6\xc0\x04\x28\x69\x93\xfe\xc4\x53\xa6\x99\x1b\x71\xd9\xef\x6a\x55\x5a\x9a\x06\x66\xa6\x8f\x73\x54\x68\x9e\x1c\x57\x32\xad\x2a\x8f\x53\x47\x44\x4c\x8f\xf1\x63\xce\xac\x57\x51\x8b\x67\x6a\xeb\x4a\x0a\xa7\x9c\x17\x6b\xfd\xed\xfd\x82\x30\x7b\xd2\xcf\x60\xe1\xfa\x69\xd2\x6a\xe9\x37\x3b\x07\xd1\x7b\xf7\x2e\x1b\xc5\xe3\x9f\x50\xf4\x1a\x69\x02\x71\x75\x81\xc3\x4e\x47\xc2\x09\x62\xf8\x21\xc8\x0d\x5e\xd4\x1c\xf7\xd7\x80\x9d\x06\x2b\x26\x54\x0a\x71\x73\x2c\x8a\x45\xa2\xad\x68\x66\xde\xb8\xe3\xd9\x9b\xa5\xbf\x9e\xd7\xb8\x80\xa6\x17\x34\x9e\x07\xd6\x9b\x9f\xbd\xe3\x02\xe9\x95\xbb\x0b\xf8\x07\xa4\x5f\x7f\x7a\x99\x5c\x37\x1e\xa2\xee\x82\x4a\xb8\xfd\xa6\x2b\x3a\xcf\xbf\xf2\xfc\x9b\x9e\x7f\xee\xa6\xad\x97\x6f\x5d\x7d\xf9\xf5\x4c\xfe\xba\x83\x3b\xdb\x4e\xed\x2f\xde\x7f\xaa\x6d\xe7\xc1\x75\x6b\xb6\x81\xea\xd0\xd7\x30\xfe\xc4\x43\x72\x4d\x82\xad\x03\x3f\xf4\x4a\xf7\x5c\x5c\x3f\xa7\x0a\x96\x7e\xfa\x09\x2c\xad\x9e\x3d\xf6\x22\xe9\xde\xec\xfc\xc4\xc8\x21\xe6\x1b\x54\x82\x62\xa8\x1e\x4d\x24\x7a\x37\x1e\x65\xd6\xea\xe1\x41\xce\x35\xeb\xf3\x9a\xa2\x89\x78\xc2\x1c\x60\x29\x33\xf2\x84\x1d\xfe\x48\x98\xd0\xe0\xd8\x29\xd2\x64\xcb\xbf\x1b\x90\x35\xbf\x10\x88\x2c\x78\xc8\xa4\x96\x43\x5c\xff\x25\x7f\x3c\xb4\xec\xbe\x30\xdc\x59\xf5\x99\x74\xf2\xae\xc7\xef\xfe\xf4\xa7\x5f\x95\x99\x16\x3d\x0f\xd6\x47\xfe\xb3\x1e\x1e\x85\x5c\x97\x01\x0d\x3e\x98\xea\x9c\x5b\xd1\xb8\x62\x62\xd7\x9c\x35\x07\x2f\xf8\xed\x84\xc8\x8f\xcf\x2d\x99\xb7\xe9\xfa\xed\x0f\x87\x96\xc2\x0f\xf8\x6d\xe6\xed\x6b\x0e\xbc\x85\xe7\x57\x55\x1c\xfc\x4d\xdb\x9c\x63\xff\xb8\x74\xf6\x66\xe0\x36\xf5\xd4\xde\x0d\x9d\xdf\xcf\x90\xbe\x02\x33\x2c\x86\x2d\xce\xc4\xd2\x86\xcd\x3f\x7b\x08\x7e\x3e\x7b\xe9\xc4\xf2\xbb\xd7\x5f\xde\xbf\x63\x5e\xdb\xec\xc9\x1f\x5c\xf6\x0a\x9e\x7a\xf5\x53\x4f\x0d\xad\xb3\xa5\x39\x45\x67\x24\x82\xd0\x68\x44\x98\xb2\xab\x69\x3b\x6b\xbf\x30\x36\x72\x63\x1a\x59\xf4\x3f\x92\x1d\x4b\x56\xd9\xcd\xcc\xb8\x81\x6c\x44\x0c\x90\x8d\x08\xe8\xc8\xb8\x1b\xda\xdb\x1b\xd8\x54\x43\x3b\xb8\x29\x92\x70\x20\xa5\xb7\x58\xa8\x57\x06\x14\xfc\xcb\xd0\x7e\x43\x3a\x8b\x79\x51\xf2\x65\x1f\x4c\xb3\x7f\x66\xd2\xc8\x81\x92\x08\x59\x22\x2c\xc7\x53\x0a\x08\xda\x61\x77\x64\xef\x5e\x34\x6c\xee\x18\xa7\x18\x9e\xe2\x58\x91\x6c\xb5\x29\xd2\xd7\x2e\xca\x11\x10\xae\xfa\xcd\xc4\x2a\x7f\x88\xa7\x72\xcc\x16\x1a\x47\x5c\xd5\x8b\xa5\x6f\x2a\xc6\x8f\xa7\xbf\x80\x68\xc5\xf8\xf1\x15\x0f\xbe\x6e\x94\x4a\xb0\xb5\x78\x5a\xe2\xc2\x26\x77\x71\x9d\xd7\x67\xd3\x98\xad\x73\x6b\xcb\xa6\x55\x47\x7c\x26\x78\x7d\x3c\x93\x4e\xcd\xad\x3a\xff\xd2\xd5\x47\x17\x2f\xb0\xa8\xbf\x6e\xbd\xa7\x73\x7c\x05\x93\x23\x9f\x78\xea\x8b\x8a\xf1\xbf\x87\x65\x2b\xca\xa6\x4e\xac\xd4\x39\x1b\xf2\xc6\x3f\x75\xfc\xf8\x0b\xd3\x85\xa2\x94\x5e\xa7\x75\x94\x57\xba\x97\x3f\x30\xac\x5d\xc3\x5c\x40\xd6\x4b\x26\xa2\x7b\xd0\x6f\x10\x62\x38\x85\x22\x44\x81\x42\x0b\x09\x05\xc4\x9d\x35\x8b\x22\x93\x38\xd9\x0b\x9c\xc3\xce\x9d\x6d\xbd\x92\xc8\x9a\xae\x38\xec\x8c\x95\x50\x14\x7b\xc9\x45\x62\x3e\x72\x1d\x47\xc4\x94\xb5\xb8\x52\xa0\xec\x42\x22\x5e\x08\x43\xb4\xc7\x8a\x16\x93\x29\xcb\xde\xa6\x04\x0d\x40\x18\x51\xb2\x3f\xa3\xd5\xe7\x31\x45\xb2\x3c\x31\x72\x1e\x28\xbb\x75\x38\xab\x72\x6a\x82\x6c\x27\x2f\x22\x73\x01\xbb\xe1\xe0\x4d\xc7\xef\xb8\xe1\xd0\xfa\x0d\xc9\x62\x1d\x1d\x8d\x30\x60\xce\x0f\x9f\xb7\x34\xbd\xe7\xc0\x35\x97\xa6\x97\xb0\x1a\x83\xce\xe6\x97\x6c\x0d\xf5\xb6\x7c\x93\x41\xa3\x4e\x36\x30\x1a\x83\x11\x9b\x55\x0d\x0d\x46\x97\x59\xcf\x72\x63\xc7\x9a\x5d\x79\xf0\x7c\xa8\x6c\x66\xf3\x9b\xdf\xbe\xd9\x3c\xab\xc4\x00\xea\x68\x58\x13\xa8\x05\x6a\xd9\xaa\x43\xd7\xbd\xfa\xda\xc1\x31\xf1\x7c\x83\x31\x9f\xe7\x05\x6d\xe7\x81\xc9\x93\x3a\x57\x4f\x4a\xad\xdb\xd3\xf1\xe0\x65\x53\xf6\xef\x7b\xfe\x85\x7d\xb1\x1c\xac\xd2\x78\xec\xb6\x42\x9b\x89\x5a\xeb\x72\x0d\xbc\x01\xc1\x1d\xa1\xb5\xdb\x2f\x78\xb3\x79\x66\x59\xa8\x50\xad\xd5\x3a\xf5\x6a\xae\x6b\x45\xfa\xd0\xa5\x97\xe4\x99\xd5\x40\xe9\x77\xdd\x7d\xfb\x0d\x57\x6a\xd9\x0d\xc9\x54\xaa\xbe\xbb\xfb\xe0\xca\x79\xf9\x2a\x55\x3e\x50\x0b\x27\xec\x38\x6f\x69\xbc\xaa\x2a\xb1\x84\xd5\xd0\x94\x25\x80\x67\x91\x1c\x6b\xea\x1a\x18\x23\x36\xf0\x9c\x66\x6c\x83\xb1\xc0\xcc\x34\x8c\x35\xb9\xf2\xa6\x9e\xbf\x6e\xd5\xcc\xe6\x45\x8b\x9a\x67\x75\x7a\xb8\x3c\x93\x31\x7f\xd9\x78\x98\x8d\xaf\xe8\x58\x79\xf2\xe0\x75\xaf\x1a\xb5\xe1\x88\x8a\xa2\xd8\x6b\x56\xae\x98\x38\xa9\x79\x72\x8b\xb4\x6c\xdc\x94\xcb\x7e\xbe\xf8\xb9\xfd\xfb\xf6\xc5\xbc\x58\xab\xd6\xa8\x18\x87\x01\xdf\x65\x70\xac\x93\x0a\x8a\xe7\x58\x42\x8b\x9a\x67\xae\xea\x86\x57\x55\x56\xa3\xde\xc9\xb5\x16\x57\x55\x6a\xca\x73\xf5\x46\xba\x3a\x35\x46\xae\x33\x05\x83\x88\xfd\x88\x45\x28\x0f\x25\xd1\x66\xb4\x0b\xa1\x40\xdc\x6e\xe5\x78\xda\xe7\x0d\x51\x62\x08\x88\x28\xb3\x83\x0e\xc4\x03\x76\x96\x88\xc7\x27\x92\x20\x86\x28\x1e\xfb\x78\xaa\x18\x2b\x04\x37\x71\x3b\x58\x5d\xb8\x50\x1e\x90\x94\x83\x20\xf2\x14\xd9\xa6\x67\x12\xca\x2f\xcf\x53\x5c\x80\x18\x20\xba\x28\x1b\x58\x89\x31\x42\xbc\x0e\x78\x8a\x35\x18\xec\x06\x7d\xf2\x92\x1b\x3f\x3c\x7f\xeb\xd7\xbf\xb8\x63\xb9\x57\x45\xb3\x1a\x3d\xd3\xbb\x06\x2e\x85\x9b\x9e\x82\x1b\xb4\x26\xab\x37\x62\x32\xab\x6d\xe5\x26\xc6\xe6\x71\x96\x5a\x4a\x80\xe5\x55\x6a\x86\xa5\x28\x00\xb6\x2b\x1c\xda\x21\xed\xc9\x0b\x08\xbc\xfe\x93\xe0\x74\x8b\x45\xcb\x0b\x5b\xaf\x38\xb0\xbb\x33\x59\xd5\x72\xd1\xb6\x7d\xcb\xc2\x36\xef\x7c\xd6\x56\x1b\xad\x35\x4b\xef\x96\x2e\xbc\xf8\xc4\x79\xcb\x6f\x5b\x32\x36\x37\xd3\x31\xb1\x61\xca\x1c\x17\x5f\xd3\xb9\x76\x6c\x2d\xcb\x16\x58\x8c\x89\x99\xe3\x2a\x93\xad\x5b\xda\x8a\xd4\x06\x35\x03\xf4\x96\xca\x9f\xcf\x0b\xfe\xde\xb8\xba\x72\x76\x11\xaf\xb1\x94\xdd\x68\xe7\xd4\x14\xc6\x58\x11\x8b\xc5\xd8\x58\xc1\x72\x3a\xb8\xbb\xb0\x21\x5c\xac\xd5\xf6\x05\xa6\x59\xad\x5a\x7b\xcd\xfc\x20\x5b\x31\xfb\x9a\xd6\x39\xfb\xda\xa6\x14\xe5\xab\xf1\xce\xb1\xee\x18\xb6\x07\x66\x25\xf2\x6a\xcf\x5f\x33\xab\x32\x3c\xa5\x6d\x86\x37\x73\xeb\xbc\xf2\x52\x7b\xee\xd2\xb2\xaa\xdb\xb0\xb5\x7c\xf1\xb0\xcd\x4f\x9a\xf4\x51\x11\x82\xd0\x5a\x3d\xc2\x26\x74\x88\x55\xf9\xb4\x6d\xee\xb0\x2f\x90\xe5\xb4\x8c\x65\x39\x2e\x99\x51\x61\x05\x5f\xfa\xdf\x58\xab\x67\x8d\xb5\x88\x44\x77\x56\x18\x3c\xdd\xde\x20\x37\x96\x8a\x33\x38\x52\x80\x69\x84\x9f\x4e\x9f\x4a\x53\xe8\x2c\x42\x16\x05\x09\x81\x9a\xa2\xa7\xf1\x2b\x1d\x72\xf3\xdb\x91\xfd\x56\x6c\xd1\x15\x44\xe1\x08\xff\x29\x33\x8d\x06\x10\x4e\x8d\xbe\x12\xf1\x9e\x51\x3e\x06\xa2\x72\x10\x21\x08\x36\xdb\xc8\x3e\x21\x6c\x07\x8f\xc9\xf3\xaf\xb9\x40\xff\x45\x81\x46\xc2\x76\x3a\x6d\xe6\x33\x0a\x6c\x24\xc5\x9b\x07\x10\x93\x3e\x95\x86\x11\x1d\x05\x35\x52\x9f\x2a\x7d\xce\x52\x4b\x47\x9b\xa0\x67\x28\x8d\x39\xf3\x7b\x1a\xf5\x9e\xf5\xcc\x8a\x7f\xfa\xb9\x0b\xaa\xe9\xcc\x3a\x21\xa2\x84\x52\x27\x02\xa7\x29\xce\x04\xd2\x2a\x0f\x6b\x0f\x65\xed\xd0\x1d\x76\xeb\xff\x59\x39\xcc\x0f\xa9\x9d\x9a\x27\x9e\x50\x6c\xcc\x9f\x7c\x52\xb1\x3a\x1f\x0a\x3f\xf1\x84\x7a\xc0\xfd\x3f\x2b\x9a\xeb\xcf\x7d\xb9\xe1\xb0\xd4\xf7\xbf\x2b\x2f\x2b\xca\x41\x41\x54\x85\x16\x11\x9d\x1a\xaf\x38\x6c\xa8\x9f\xb5\xd6\xff\xbf\x2a\x20\xc6\x21\x21\x8d\x53\x23\xf5\x29\x59\x7f\x0f\x94\x67\xe9\xef\xf8\x9f\x15\x0b\xae\x95\x90\x5a\x0d\x6e\xa5\x40\xde\x03\xa5\x44\x32\x63\xfe\x07\x85\x01\xc3\x63\xde\x82\x6c\x3b\x02\xa4\x6b\x1e\x72\x46\xac\x4e\x40\xaf\x53\xc0\x39\x26\xc7\xd0\xb7\xe0\xfc\x91\xe0\xe4\x59\x24\x38\x07\x2e\x85\xfb\x78\xc1\x29\x29\x4e\xbf\x12\x9f\x76\x0a\xca\xba\x22\xad\xcc\x7d\x88\xea\x08\x0a\x27\x86\xd7\xc9\x87\xc8\x0f\x02\x64\xa7\x64\x78\xc9\x28\x0e\x4f\xed\x49\x12\xb3\xcf\x39\x70\x17\x94\x4a\xaf\x4b\x2d\xd2\xeb\x18\xc9\x0f\x73\xf0\xa4\x39\xdf\x7c\x37\xf4\x1a\x32\x1b\xe4\x5b\xe0\x6b\xe8\x4a\xe5\x30\x94\xc2\x5d\x4d\xe6\x7c\xf3\xc9\x83\x72\xb2\xad\x77\x2b\x6b\x9a\x81\x41\xc4\xfe\x91\xf4\x51\x01\x82\xc1\x21\x4b\x50\xa7\x97\x5b\x4e\xff\x58\x61\x07\x0c\xef\x54\x9c\x6e\x4d\xb3\xc4\x0d\xf2\x30\xd2\xc6\xbe\xa6\xd1\xec\xcf\x0f\x9e\x22\xf6\xa6\x38\xa5\x58\xa5\xa2\x60\xfe\xc0\x13\xa0\x98\xa8\x52\x84\x27\xed\x54\x6f\x30\x7f\x3f\x49\x89\x11\x20\xfa\x2d\x8d\x53\xb3\x3f\x5f\x70\x82\xc2\x04\x26\x38\x53\xf9\xfd\xef\x11\x8c\xbf\x93\xea\x55\x08\xc2\xf2\xf7\x93\x34\xbd\xbd\xca\x7a\xbb\x0a\x31\xfd\x04\x57\x2c\xbf\xcb\x48\xd9\x4b\xe6\x80\x15\x03\xcc\x10\x62\x3a\x9e\x80\xb8\x83\x09\xc4\x19\x13\x63\x0a\x98\x02\x26\x30\x31\x26\xee\xd3\x7c\xbb\x39\x93\xce\xc9\xc9\xdc\x90\xb9\x41\xc3\x5b\x4c\xf9\x76\x33\x4e\xe7\xe4\xe0\x4e\xdc\xe9\xee\xcf\xc1\xa9\xfe\x0e\xec\xa6\xfb\x32\x7d\xcc\x77\x56\xcf\xa9\xb4\xd5\xcd\x0d\x22\xad\xf6\xfb\xef\x19\xad\xd5\xc3\xc8\x41\x20\x41\xfd\x4d\xfd\x9a\xcf\xe9\xef\xf5\xfd\x9a\x77\xe8\xef\x4f\x65\xe8\xef\xdf\xe9\xd7\x8c\x5c\x1b\x36\x21\x1f\x8a\x0d\xf5\x37\x1c\xb0\x0a\x56\x30\x01\x71\xcf\x39\x62\x86\x36\xc2\xe5\xd7\x4a\xce\x36\x46\x7a\x8b\x49\x72\x73\x2a\xbd\xc5\x04\x7d\x1c\xfd\xc5\x19\xc1\xfe\xbb\x54\x2c\x46\x66\x8b\x5e\xc5\x4a\xc8\x6c\x61\x91\x45\x7f\x2a\x65\x55\x0d\x22\xda\xa2\x67\x7a\xad\x2a\x90\x3d\xa3\x63\xa8\x41\xa4\xb1\x9c\x4a\xe9\x2d\x14\x20\x8d\x85\xe9\xd5\x5b\x86\xf6\x6b\xdc\x9c\xfc\x9a\x73\xc8\x80\x1c\xa8\xea\x6c\x45\x95\x21\x57\x41\x77\x8a\x2c\xc3\x12\x53\xcc\x44\x92\x4b\x84\x40\x81\x7a\x62\x45\x38\x05\x7e\x7b\xa6\xf3\x8d\xb4\xfc\x1f\xeb\x56\xdc\x27\x9d\x8a\x7a\x75\x56\x8a\xce\x61\x02\xbc\xc7\xe0\xe4\x0d\xcc\xc1\x3b\xbf\x81\x5b\xe0\x0b\xb8\x05\x37\x8e\xa0\xf5\x54\xfe\x21\x24\xdd\x2e\xbd\x73\x8f\xf9\xbe\x2a\x0d\x05\xbc\xd6\x60\x67\x3c\x7c\xc0\x59\x51\x31\x4e\x5c\x98\xb9\xe6\x7e\x10\xef\xb9\x07\x9d\xd6\x4b\x1b\xce\x77\x88\x30\xba\x8e\xb2\x0d\x1a\x72\xb1\x9b\x96\xdf\x97\x42\xe0\x58\x2e\x5e\x0f\xf2\xb8\xdc\x1f\x37\x0a\x60\x1d\x7e\x20\x9f\x57\x10\x63\x42\x5c\x48\xe2\x44\x92\x49\x10\x4d\x2a\xf0\xbb\x69\x17\x9c\xf3\xc9\xbe\x94\x3a\xa5\xa3\xaf\x5d\xb3\x6b\x7e\x5e\x4e\xe8\x86\x0b\x4b\xaa\x27\xd4\xbd\x0c\xcb\x5e\x7b\x0d\x66\xca\x0f\x3c\xb1\xf1\x39\xe9\x54\xe5\x58\xc6\x90\x43\x53\x0c\x68\xb0\x0e\x73\x15\xb6\xa2\x1c\x97\xf6\xe8\x2f\x4f\x2f\x75\xe0\x5f\x9e\xfd\xdc\xe9\xbd\x7f\xbd\xb2\xfb\xb7\x53\xc3\x1d\xad\x33\xeb\xd7\x08\xac\x6a\xef\x5f\xc1\xfc\x57\x69\xef\xfd\xd2\x3b\xf7\xa8\x1e\x18\xc7\xab\x6c\x26\xa0\x8d\xb4\x81\xe2\xb1\x2a\xe6\xa8\x0a\x4d\x0e\x2e\x00\xf6\xc8\xae\xaf\xee\x5d\xb1\xe2\xde\xaf\xc8\xef\xa8\xa6\x11\xf3\x4f\x44\x21\x16\x69\x90\x5e\x6e\xa5\x4d\x6a\x30\x41\x2e\x10\x17\x23\x8c\x24\x24\x91\x6f\xd9\x0f\x0b\x40\xcc\x9c\x90\xde\xa6\xb6\x66\x4e\x40\x90\xbe\x55\xf6\xe3\x19\xd2\x3b\x72\x2c\x59\x37\x9c\x35\xd8\xcb\xde\xc7\xa4\x88\x1d\x3a\x0b\xc8\xe7\xa5\x04\x0a\xfb\xbc\x9c\x98\xcc\x5a\xbd\x9a\x95\xf9\x4d\x22\xee\xf3\x72\x66\xc6\xce\xde\xa7\x91\x9e\x92\xfe\xe3\xb3\xab\x97\x96\xb6\x4c\x9e\x6b\x5e\x3b\x2d\xe7\xae\xd0\x2d\x73\x17\x6f\x76\x94\xda\x13\x63\x23\x2b\x57\xa8\xf4\xdb\xab\x53\xdb\x60\x76\x3f\x75\xea\xaf\xd2\x12\x69\x26\x70\x3d\xd0\x00\x6c\xd3\x52\xdb\xf5\xc1\xab\x54\xea\x4b\xf6\x4a\x1f\xcd\xfb\xf1\x27\x3f\x99\xbb\xd7\x09\x57\x6a\x55\xe8\x0c\x1e\x1c\x0a\x69\x08\xb3\xb6\x07\x28\x8b\xc7\x42\x01\x8b\x4e\x21\xba\xee\xfd\xf7\x33\x97\xbd\xff\x3e\xd4\x31\xe9\x53\x08\xee\xc0\x5b\xa1\x48\x7a\x2b\x73\xa5\xf4\x2a\x3a\x43\xbb\x82\x42\x66\x34\x16\xcd\xcd\x9e\xcf\x11\xce\xed\x84\x98\x10\x7d\xa2\x8f\x63\xc2\x76\x2e\x11\x0d\xe1\x21\x52\x90\xb0\x8d\xa0\xcc\x6d\x9e\x98\x18\xc2\x49\x88\x99\x22\x09\x9f\x57\x1e\x49\x47\x93\x18\x62\x04\xa4\x17\x33\x79\x38\x87\x3d\x9b\x4e\xce\x07\xb5\x4f\xd7\x58\x98\xbb\x7a\x75\x6e\x61\xa3\x6e\x71\xcc\x1d\x93\x8e\xb8\x73\xe1\x7e\x5f\xc3\xe4\xca\x4b\xf7\x74\x34\x59\x35\xfa\x29\xd0\x7b\x98\x65\x30\xc0\xd3\xc2\x9f\x58\x9a\xa6\x74\x79\xf8\xfc\x38\xc7\x60\xe9\x2b\xc7\x6c\x87\x8e\x9f\x28\x67\x9f\xee\xf5\xcc\xde\x98\x5b\x5d\x9d\xbb\x71\xb6\xa7\xa3\xe3\xb8\xbb\xdc\x96\x68\x0c\xf0\x9b\x2e\x9a\x9c\x56\x49\xbb\x78\x1d\x70\x2d\xf3\x78\x00\x9a\xd6\x30\xb0\x3b\xcd\xb2\x54\x73\x5e\x5e\x81\x76\xe0\x57\xf3\xd4\x40\x51\x3a\x16\xab\x56\xd8\x39\xab\x74\x35\xaf\xc6\xea\x79\xca\xb3\x2f\x27\x6d\x50\x39\xaa\x46\x33\x51\xab\xa2\x14\x41\x36\x64\xdc\xd9\x4d\x98\x2c\x45\x7b\xc0\x92\x04\x07\x43\xa0\x25\xf2\xbb\x12\x0b\x50\x34\x01\x38\x80\xdc\xbb\x90\x7e\x06\xe2\x51\x51\xf0\x66\x27\xa6\x5e\x8e\xb5\x2a\xca\x83\xc2\x10\x0d\xb4\x95\x43\x35\x61\xdd\x1b\xd2\x01\xa9\x59\xba\xf6\x0d\x6d\x24\xb9\x79\xf6\xdc\xda\x77\xa1\x68\x33\x95\xc3\xc3\x06\xf3\xe4\x92\x64\x4b\xcb\x8e\xf9\xd2\x83\x9d\x50\xfa\xc7\x31\x73\x67\x6f\x3e\x75\xdb\xfc\x1d\x2d\x2d\xc9\xba\x16\xaa\x58\xab\xd5\xb8\xb4\x45\x3d\x3d\x3d\x45\x5a\x97\x46\xab\x2d\xb9\xbe\xbd\xa5\xfd\x7a\xfb\x8e\xf9\x2d\x75\xc9\x16\xfc\xe0\x98\xc5\xb9\xa1\xf0\xcd\xd2\x0f\x37\xde\x08\xaa\x9b\xcb\xcb\x73\x97\x8c\x99\xb5\xa5\xfe\x06\x0d\x56\xeb\x8d\xd4\xcc\x40\xd9\xfc\x1d\x2d\xf3\x93\x53\xa5\xa0\xfa\xfa\xba\x2d\xd2\x9f\xc8\x4d\x5a\xa4\x0e\xad\x4b\xab\xd1\x14\x07\x83\xc5\x1a\x8d\xa6\x50\x5b\x12\x56\xab\xc3\x3f\xc8\x37\x9b\xbf\x83\xd4\xe9\x09\x83\x98\x7d\x9c\x45\xa8\x02\x21\x4b\x24\x49\xf9\x23\x61\xda\x21\x77\x69\x2e\x2a\x09\x09\x13\xab\x03\x51\xc0\xa2\x60\x4e\xf0\xc0\x79\xe2\x21\xba\x1c\x78\x6a\x02\x18\xe7\x5e\xfb\x14\xc0\xa1\x3f\xc1\xba\xf5\x9d\xfd\x37\xc3\xaa\xbb\xfe\xf0\xd6\x8b\x53\x16\x49\x5f\x49\xb7\xed\x7f\xf2\x3b\x4c\x7d\xfa\x87\x8a\x5a\x23\xbe\x50\xe5\x4e\xce\x98\x35\xde\x6e\xbf\xfc\xc7\xe7\x6e\xc2\x9f\x5d\xfc\xa7\xdf\x1e\x9e\xf7\x87\xe7\x1e\x1f\x7c\x62\xfd\xf1\x59\x6e\xe7\xb8\x88\x74\x79\x62\x2a\x8e\x4f\x81\x8e\x5f\x7f\x0b\x73\x96\xd6\xee\x6e\x9f\x76\xf1\xb4\x2a\xa7\x01\x80\x99\xb1\xeb\xfa\xa1\xfa\x4a\xb0\xf5\x0a\x1b\x7d\x1e\x42\x31\x93\x27\x3b\xa4\x90\x2b\xa4\xc7\xe6\x89\x0d\x0f\x96\x22\x6a\xd4\xde\xf0\x43\xaa\xa1\x1d\xa7\x21\x9d\x41\x80\xd8\x8e\x86\xf6\x7f\xa2\xf6\x06\x37\xee\xc8\xf4\x34\xb4\xb7\x83\x97\x98\xb0\xa4\xdb\x1b\xfa\xfa\x1a\xda\x87\xb1\x9d\x8f\x13\xbb\x95\x0a\xb9\x7f\x0f\x90\x2d\x39\xb9\x22\x28\x7a\x92\x09\xa2\x26\xa5\x2c\x58\x47\xc2\x7e\x35\xb0\xc8\x33\x42\x70\xd4\x41\xf9\x88\xfc\xbd\x0b\x78\x60\x2b\xde\x9d\xfa\xdd\xfe\xeb\x7e\x38\x30\xf7\xda\xe7\xd7\xed\xfe\xb2\xe9\xad\x75\xd2\xb1\x97\x7e\x22\xbd\xfb\xfa\xc5\x17\xbf\x0e\xc2\x4f\xde\x80\x0d\x52\x0a\xff\x72\xb3\xd4\x28\x7d\xfd\xd0\xd0\x0a\xef\x43\x40\xc3\x1d\x17\x1d\x13\x3b\xae\x70\x97\xe9\x34\x65\xdf\xaf\xdf\x76\xd5\x81\x1f\x0e\xae\x7b\xfe\xda\xb9\x17\xac\xb9\xe8\xee\xde\x8b\x5f\x97\xde\x95\x9e\x92\x2f\xf1\x26\x9e\x28\xf5\x64\xa4\x77\x4f\xb7\x95\xd2\x77\x5f\x4a\x9b\x7b\x80\x98\x93\x20\x1a\xb9\x07\x11\xdb\x97\xe5\xd3\xcd\xf2\x11\x24\x3c\x20\x9a\xa0\x10\x4c\x6a\xec\x01\xe6\xba\xcc\x4d\x8b\xa8\xf9\xa7\x7e\xf9\x08\x7d\xcc\x7a\x5d\xe6\xaf\xb0\x48\xd2\x0d\xdc\x0d\xcb\xa9\x1a\xd8\x75\xfd\xc0\x07\x9b\xa9\x85\x99\xdc\x8e\xc5\x03\x3f\x85\x19\x78\xe7\xc0\x07\xb8\x66\xa8\x6c\xd2\xcc\x37\x64\x3f\xf7\x22\x84\x80\x28\x92\x0f\x4b\xd6\x0c\xfb\x19\x93\x27\x8b\x64\xf1\x98\xa2\x35\x10\x2e\x80\xc8\x90\x1b\x1b\x76\x93\xd8\x1e\x31\x0d\x6b\x12\xdb\x14\xba\x9c\x78\x24\x5c\xa0\xec\x3e\xf8\xbc\x9c\x2d\x1c\x77\xe1\x33\xce\xa9\x81\xb0\xcd\xa4\xb8\x38\x6d\xec\x30\x1a\x3b\x8c\x18\x0d\xb9\x99\x74\x77\x4f\x77\x46\x8e\x1e\xfe\x30\x3a\xce\x08\x6e\x4f\xa9\xc7\x5d\x26\xd8\xa6\x19\x4d\xb5\x9c\x71\x62\x9e\x79\x8a\x25\x18\x06\x23\xa7\x63\x46\xa6\xc5\xc6\x3e\xe3\xe9\xff\x8c\x11\x52\xcd\xdd\xdd\xcd\x52\x2f\xfe\xc6\x68\xec\xc6\xdd\x46\x63\x37\xf9\xb0\x1c\x05\x00\x97\x1b\x7c\x0e\xb7\xdb\xe1\x33\x98\x34\x06\x83\xf1\xf7\x06\xbd\x41\x77\x29\x00\xc5\xb1\xdd\xd9\x84\x99\x03\xdd\x46\x45\xe3\x91\xd4\xd5\x2e\x85\x01\x4b\x19\x6e\xd5\x81\xc7\xee\x70\x31\x64\x5c\x3f\x44\xf2\xa6\xcc\x24\x7d\xde\x10\x23\x86\x28\x9f\x87\x00\x7e\x14\x95\xa7\x48\x58\xee\x6b\xd9\x1a\xc8\x36\x3e\x72\x0f\xec\xf3\xf2\x34\xc7\x72\x72\x0d\x77\xa8\xbe\x31\x1a\xa5\x5e\x95\x4a\xcd\x19\x07\x7e\x1a\x08\x19\x4d\x85\x8e\x42\xb7\xa9\xc3\xcc\x03\x19\xf3\x4b\xbd\xbc\xb9\xc3\x3d\xa6\x34\x94\x2f\x9a\x2d\x8e\xfc\xd2\xb2\x1c\xe9\x06\xfb\x55\x2d\x5d\x47\x8e\x74\xb5\x5c\x65\xef\xcc\x29\x2b\xcd\x77\x58\xcc\x62\x7e\xa8\x74\x8c\x7b\xb5\x6d\x69\x52\x7e\xe8\xe4\x52\xdb\x6a\x93\xbb\xd0\x51\x68\x32\x86\x02\xf4\x42\xb7\x11\xff\x51\x25\xa8\x7a\x19\x5a\x63\x4e\x8f\x59\x1d\xf0\x27\xdd\x7e\x63\xc7\xd0\xc5\xcd\x7c\x87\x35\x2f\x2e\x34\x89\x45\xb1\xea\x29\xde\x39\x6b\x8e\xbc\x7e\x64\xcd\x1c\xef\x94\xea\x58\x91\xd8\x24\xc4\xf3\xac\xd5\x93\xba\x7b\xba\x27\x55\x1b\xfd\xee\xa4\x3f\xb0\x7a\x4c\xda\x6c\xd5\x9e\x89\x0d\xe0\x90\x09\x79\xc8\x98\x84\x80\x5f\x90\x51\xf0\x79\x4c\x11\xe2\x1b\x05\x6a\xb9\x78\x46\x55\x26\x53\x05\xf8\xe1\xdd\xd2\x8c\x5f\x64\x76\xe1\xcb\xcf\x85\x56\x49\x76\x4f\x07\xbd\xf4\x4f\xa0\x1f\x19\x48\x83\x1e\x56\x9d\x63\xf3\x44\x6e\x43\xde\x51\x23\x46\x44\x22\x1a\x83\xa6\xa1\x25\x44\x83\x58\x64\x87\xf8\x9b\x12\xf1\x58\x54\x59\xab\xb6\x3b\xe4\xe6\x5e\x54\xb6\xf8\x09\x02\xee\xb4\x7a\x87\xa2\x11\xe7\x02\x87\x22\x03\x2f\x9f\x66\x14\x05\xb2\x44\xe5\x37\x0e\x47\xc5\xa2\xca\xa2\x94\x83\x5d\x3b\x3e\xc6\x19\xb9\xa2\x1c\x9d\xae\x30\x5f\xe3\xd8\xfe\xfb\x0b\x2f\xfb\x38\xbe\xa6\xd9\x5e\x9a\x72\x34\xae\x92\x7f\x0e\xda\x3e\x63\xfd\x8d\x2f\x5e\xdd\xff\xe7\xbb\xbf\x79\xe1\x70\x12\x92\xbf\xfa\x0b\xb4\x3a\x36\xdf\x78\x6a\x89\xa3\x28\xc7\xe2\xd4\x99\x27\x4d\x32\xeb\xa2\xf5\xe6\x25\x80\x2e\x73\x14\x39\x2c\x4e\xbd\x79\xcd\x1a\xb3\xde\xe9\x4c\x9a\xe1\xa1\x9a\xc5\xb6\xb2\xf2\x9c\x7c\x4a\x53\xed\x9a\x34\xf9\xc2\xd7\xb6\x1f\xbc\x20\x7f\xba\x23\x55\x6a\x6f\x3c\xfc\xfa\xe1\xf5\xd3\xaf\x7e\xe1\x6f\x77\xdf\xf8\xa9\xfd\x91\x4f\xa5\x5f\xfd\x29\xf7\xf1\x0b\x1e\x38\xe0\xd1\x9b\xea\x9d\x9d\x80\x3b\x9d\x49\xbf\xde\x79\xf5\x78\x29\xe7\x79\xaf\xde\x9c\x74\xde\xfe\xec\xaf\x6e\x73\xd6\x9b\xcc\xba\x3c\x84\x91\x7f\x10\x31\xef\x91\x7d\xf8\x75\x08\x31\xa4\xd7\x93\xdf\x55\x85\x97\x91\x95\xab\x6a\x2c\x9a\xa4\xc2\x2e\x8a\xc0\x73\x0b\x81\x68\x92\xd2\xa2\x20\x86\xa8\xd8\xd0\x12\x1b\xe1\xf8\xf2\x15\x43\x88\x26\x16\x5f\x44\xd5\xd4\x45\x39\x5c\x2a\xe6\xbd\x8b\x7f\xb1\x73\xe7\x2f\x2e\xfe\x72\xd3\xcd\x9e\x83\x5f\xae\x7d\xe4\xc2\xa5\x71\x9f\x4e\x9d\x5f\x36\xbb\x6b\x56\x69\x9e\xca\x91\xbf\x46\x0c\x6e\x3a\x62\x2e\x8b\xb7\xb7\x4d\xc9\x37\x6c\xbe\x7a\x65\x51\x51\xeb\x65\xcf\x6f\xdf\xf6\xc2\x25\x0b\x05\x57\x49\xbc\xd4\x84\x59\x8b\x33\xea\x0f\xe5\x5b\x0d\x2d\x81\xc0\xf8\x65\xc5\x1a\x61\xfc\xc5\xf3\x9b\x2e\x6a\x9b\x52\xe1\xb5\x68\xb0\x7e\xc1\xce\x9d\x0b\x16\xee\xdc\xf9\xb4\xe1\x81\xf3\xa7\xa6\xa6\x17\x8f\x9b\x37\x67\x56\x84\xb7\x94\x8f\x8d\xf8\x7d\xe5\x35\x22\xef\x2d\xcf\x73\x61\x38\x6f\x96\xb3\xac\x54\x08\x97\x79\xf5\x5c\x62\xe1\xc6\x2b\xdb\xa7\x1f\xd8\xbd\xa4\x3a\x3a\xab\x6b\x55\x24\x34\xa5\xa4\x40\xa3\x31\x0b\xf1\xf9\x71\xa3\x05\x20\x39\x3d\x90\x23\xc4\x2b\x6a\x0a\x72\xab\xe3\xa9\xc4\xc4\xf8\x94\xc8\x48\x3b\x3c\xc5\x7e\xfd\xac\xdd\x83\xc0\xa8\xf0\x48\x21\x6e\xdc\x6b\xe6\x07\xc9\xdc\x13\x10\x6f\x86\x33\x43\xe9\xd1\x9a\xdb\x1d\x98\xbc\xc9\xa7\x17\x85\xb2\x7e\x18\x1c\xa5\xac\x4d\x8f\xe0\x9f\x71\x90\x55\x1b\x84\x46\x58\xc3\x23\x77\x12\x8c\x21\x70\xf3\x60\xb4\x07\x46\x6a\xa5\x8d\x5c\x6b\xc8\x86\x71\xf9\x99\x36\xed\x70\x2b\x04\x4f\x1d\x3c\x78\x4a\x7a\xfb\xd4\xc1\x83\xf0\xb5\x9c\x87\xde\xd3\x99\x22\x5f\xcc\xe8\x8c\xf7\xdf\x7f\xf0\xd4\xf0\x59\xd3\xcf\xc8\xfa\x08\xff\x19\xe3\x57\x83\xdc\x9f\x8f\x2e\xc9\x33\x24\xcc\x53\x23\xaf\x00\xbd\xff\x5d\x59\x9d\x55\x3e\xd4\xa8\xf2\xf9\x2f\x4b\x27\x31\xd2\x56\xf3\x5f\x95\xc6\xba\xd3\xcf\xf3\xff\x50\x04\xa3\xf1\x51\x01\x54\x87\x50\xc0\x42\x0c\x9a\x09\xbd\x3a\x58\x3c\x16\x82\xe2\x56\x40\xf0\xc3\x6e\xd8\x1e\x30\x91\x97\x31\xdb\xc3\x66\xfd\x71\xb7\x9d\x7d\xdf\x47\x59\x2c\x05\x3f\xa6\x0b\x2c\x16\xca\xc7\xb6\xcd\xfb\x71\xce\x3c\xca\x9f\x0b\x88\x4c\x9a\xe4\x2f\x94\xeb\x97\x76\x0b\x51\xe1\xc8\xeb\x47\x84\xa8\xf0\x11\x24\x3f\x4a\x4b\xcf\xe7\xdb\x6d\x36\x7b\x3e\x54\x53\x93\x06\x7e\xa4\xb8\x1c\xcf\x48\xc5\x4d\xcf\x4f\x06\x91\xa2\x3d\x21\xb7\x50\x43\xfe\x63\x1f\x7d\x94\xb5\xb3\x93\x1d\x1b\x61\x28\xaa\x41\x53\xd0\x5a\x32\x8b\x97\xdb\xf1\x21\xcc\x6f\x56\x01\x03\x92\x20\x52\x21\xe0\x15\x98\x75\x60\x28\xe7\x76\xe5\x2d\x19\xf6\x5b\xe2\x21\x20\x7a\xa4\x8e\x48\x38\x0e\x94\x8f\xe0\x36\xb3\x3f\x03\xc1\xcf\xfa\xa8\x10\x94\x0c\xb1\xfc\xcb\xed\x33\xc9\xa5\x61\x93\x6a\x72\xa8\x1f\x85\x26\xab\x36\x19\xe4\x30\xac\x70\xfa\xb0\x1b\x17\x45\xe5\xef\x40\x2e\xf4\x08\x51\x41\x88\x0a\x90\xce\xba\x1d\x6e\xec\x8b\x16\x61\x37\xf6\x39\x99\xdc\x40\xff\xc5\x6d\x7b\x56\x58\xf6\x2d\xbc\x53\xc1\xab\xdf\xb9\x70\x9f\x65\xc5\x9e\x36\xed\x84\xb2\x3b\x05\xa7\x24\x47\x94\x4d\xa0\xe4\x12\xcc\x74\x85\x6a\x6b\x43\xf8\x48\x63\x57\xe3\x40\x1f\x2e\x72\x42\x8f\xd3\x47\x17\x39\xa5\x8e\x5c\x6f\x0a\x7a\x08\xcd\x42\x07\x29\x9e\xd3\x7e\x1b\xf4\x38\x8b\x68\x9f\x1c\x28\xc2\x5e\xfa\x5d\x69\x39\x3c\xda\xb2\x5e\x3e\xbc\xbe\x45\x9a\x04\xb7\x94\x56\xc9\xfe\x2a\x84\x91\x67\x30\xcd\x7e\x48\xe6\x60\x33\x10\x02\x8b\x8f\x02\xb9\x1e\x50\x9e\xb0\xc3\x4e\x16\x97\x28\x82\x06\x15\x12\x16\xdf\xb0\x4f\xae\x25\x64\x1d\x69\x84\x2f\x9e\xd5\xc7\x8f\x0c\xfb\xe4\x2b\x50\x1f\xa6\xa4\x14\x25\x55\x71\x39\xd2\xa3\x29\x48\x18\x34\x1a\xba\x8a\x71\x4a\x8f\xce\xe4\x72\xfa\x8c\x1a\x35\x35\x5d\x9a\xc9\xe5\x7c\x64\x20\xbe\x17\x65\xa7\x8a\xcb\x81\x49\x29\xd9\x4f\x52\xc2\xa4\x99\x5c\x6e\x9f\x21\x9b\x32\xeb\x93\xaf\xa3\xc6\x08\xd0\x20\x82\x1f\xfa\x72\x06\x91\x8e\xe7\xfb\x72\xa4\x47\x72\x74\x3a\x23\x54\x0d\xb9\x3a\x9d\xb1\x2f\x07\x94\x63\x30\x59\x8e\x93\x5e\x18\x72\x75\x3a\x65\xfe\xb9\x7a\x10\x31\x87\xb3\xf6\x9a\x26\x62\x71\xef\xe0\x4c\x0e\x8e\x52\x53\x26\x8a\x53\x83\x03\x90\x11\x13\x6b\x4b\x6c\x34\x13\x96\x4d\x6a\xca\xa1\xc3\x87\x0f\xed\x86\x57\xa5\x93\x10\x96\x2a\x06\xdb\x20\x25\xf5\xb6\xa1\x41\xfc\xbb\xd4\xfa\x9f\x3d\xf3\xfd\x33\x3f\x5b\x9f\x1a\xf2\xc0\x27\x87\x0e\x53\xfb\x0e\x1f\x1a\x58\x02\xaf\x42\x18\xc2\xf0\x6a\xe6\x28\x1a\x6c\x93\x9e\x96\x9e\x6e\x43\x83\xd0\x2d\xb5\x4b\xcf\xbf\xb8\xa3\xb2\x72\xc7\x8b\x50\x0d\xb7\x41\xb5\xe2\x57\xde\xcd\xe0\x20\xa2\xde\x1e\xce\x17\x0a\x24\x44\x53\x42\xb4\xa8\xc1\x04\xa2\x1a\x12\x60\x02\x3c\xe7\xbe\xfb\xee\xbb\xcf\x0d\xcb\x33\x9f\x49\x6f\xad\x81\xcd\xd2\xbe\x35\x50\x84\xf3\x36\xdc\x7b\x2f\xac\xbb\xf7\xde\xcc\xdf\xa5\x5b\x32\x9f\xe2\xe7\xa5\xb7\xd7\xc0\x16\xd8\xb2\x46\x7a\x1b\x3f\x9f\xf9\x54\xb1\xab\xc9\x62\xbd\x0c\xc8\x81\x8a\x50\x25\x42\xc3\x2b\x47\xc3\x2b\x48\x2c\x61\xf3\xb3\x58\x39\x50\xd6\x0f\xa3\x09\x20\x8d\x33\x9d\x3d\xc2\xa0\xa6\xce\xa6\xa6\xce\x4c\x13\x71\xe8\xa6\x8f\x14\xa6\xbe\x4b\xf4\xfd\x7d\x16\x77\x8f\x53\xd0\xd3\x6e\xe2\x66\x3a\xb2\x47\x5e\x96\xd3\x35\x51\x24\x79\x93\x54\x38\x44\xec\xd7\x6b\x35\x9f\x4a\x3b\x05\xa7\xd5\xcc\xa4\x9d\xc2\xe3\xd9\x68\xb2\x6e\x44\x0d\x4e\x62\x33\xcc\xa3\x64\x95\xc4\x88\x1c\xa8\x00\x21\x8b\x1a\x42\x90\xb0\x14\x01\x54\xca\xcd\x53\x3c\x0c\x16\x3b\xcb\xa9\xa1\x52\xf6\x3b\x3a\xa9\x9c\x81\x5b\xcc\x3c\xb7\x02\x4e\xe2\x43\xd2\x43\x99\x6f\x9e\x93\xc2\xcf\xa9\xc2\x4c\xc5\x0a\x8e\x37\x0f\xdc\x42\xe5\x90\xa0\x8a\x4a\x0e\xa8\xf1\xf9\xfa\x12\x1b\x44\x07\xd4\x6c\x6b\xe6\x16\xbc\xdc\x91\xb9\x54\x7a\xd9\x56\xa2\xcf\x5c\x45\xfd\x13\x2f\x77\x38\x46\xac\xb7\xf5\x21\x8a\xec\xba\x54\x22\x04\x91\x98\x0f\x88\x0d\xb9\xe8\x70\x41\x82\x30\x4c\x32\x56\x79\xba\xae\xc0\x27\xbd\x0a\x78\x52\x91\xfd\x90\x3b\x0b\x33\xa4\x7b\x7a\xa8\x09\x9d\x7b\x2f\xff\xb1\x03\x5a\x7e\x38\x74\x89\x14\x24\xdc\x06\xe9\x65\x0b\xa4\xcc\x23\xdb\x4f\x8e\xb1\x34\x59\xc6\x9c\xdc\xfe\x88\x94\x59\xb0\xec\x1b\x38\x0a\x9f\xc3\xd1\x6f\x70\x6f\x5f\xe6\xf5\x45\x7e\x0c\x8b\x1b\x3b\x9a\x97\x00\x5c\xd4\xd7\xfb\xf8\x1d\xe7\xed\x3c\xfa\xc1\xaa\x16\x80\x96\x55\x1f\x1c\xdd\x79\xde\x1d\x8f\xbf\xa6\x74\x06\x43\xdc\x0d\x43\xeb\x27\xca\x3c\xcb\x82\x82\xa8\x24\x6b\xf3\x6d\xf3\xc5\x2c\x44\x89\xcc\x73\xfa\x43\x96\xfa\x41\xe4\x88\xf1\x49\xb6\x8b\x83\x84\x87\x49\x78\x98\x51\xb8\x3d\x4c\x0d\x0c\x0c\x50\xdf\x4a\xf7\xc0\xdc\x4c\x07\xee\xc9\x74\x50\xa2\x4e\xe5\x96\x2e\xfb\xfd\xef\xa5\xcb\xdc\x2a\x9d\x4e\x45\xbf\xad\xd2\x0d\xdc\xfd\xa8\xd4\x85\xf7\xbe\x2f\x75\xe1\x8f\xe7\x25\xfb\x83\xc9\x79\xf3\x92\xf4\xdb\xc9\x79\x78\x43\x3a\x8d\x06\x77\xee\x94\x20\x9d\x06\xa4\xf8\x07\x6e\x97\xcf\x18\x44\xf7\xdc\x03\x48\xa7\xea\x0f\xaa\x74\x3a\xba\xfd\xc8\x91\x23\xd6\xd3\xa7\xcd\x3b\x03\xb3\x52\x28\xf7\x4a\x90\xdd\xb0\x67\x0b\xc1\x45\x39\xec\x0e\x17\xed\xb0\x27\xe2\x72\x0c\x86\x10\x83\x45\xb7\x0e\x5c\x14\x0f\x1c\x6b\x03\x1f\xf0\x38\x84\xa9\x74\x67\xd5\xde\x57\xbd\xfe\x05\x1a\x51\x4c\xae\x68\x89\x95\xaa\xe9\xd2\xe6\xcd\x9b\xae\x6b\xbc\x11\x20\x1c\xcb\x9f\xf6\xb2\x34\xab\x69\xc3\xec\x9a\x31\xa1\x46\x11\x4c\xf0\x0c\xc4\xbe\xbc\x6a\x96\x8b\xe1\xf5\x7a\x18\xd7\x29\xfd\xc9\xbe\xb7\xf3\xde\xc3\x8f\xe1\x57\x7f\x3d\xeb\xa5\xcd\x16\x53\xd0\xe8\x2a\x2c\x59\xb1\xa7\x7d\x8e\x49\x35\xe7\xaa\x9f\xed\xda\xe2\x6e\x60\x29\xaf\xdf\x36\x06\xc2\xd2\xc5\xb5\xbb\x8e\xde\xf0\xde\x73\x10\xbe\x62\x72\xf7\x89\xbb\x3e\xfb\xd9\x27\x5b\xe7\xcc\x71\x48\x8f\x42\x01\xce\xe1\xb1\x7b\x1e\x1a\x81\x6d\x2b\x27\x3b\x58\x44\x61\x1e\x85\x80\xa3\xdd\x01\x81\x27\x7b\xc9\x3c\x36\x00\x4b\x00\x08\xf5\x10\x4f\x44\xec\x85\x60\x8f\x84\x13\x49\x28\x87\x10\x16\xe5\x31\x7e\xf6\x8d\xa4\x47\xcd\x45\x46\xb3\x14\x8d\x9e\xab\x30\xcb\x75\x65\x4e\xa9\x5f\xfa\x42\xea\x77\x96\xe9\xf2\x9c\xcf\xae\xc5\x79\xce\x7c\xb5\xc6\x9e\xab\xe6\x4b\x8d\xaa\xb8\xa9\xd8\x14\x57\x19\x4b\x79\x75\xae\x5d\xa3\xce\x77\xe6\xe1\xb5\xcf\x3a\xa5\x87\xc9\x02\x27\xde\xbb\xfe\x49\xa9\x5f\xfa\x58\xea\x7f\x72\xfd\xfa\x27\x81\x01\x17\x30\x4f\x4a\x8d\xd2\x0b\xd2\xa7\x27\xb7\x6f\x3f\x09\xf9\x50\x05\xf9\xc4\xf7\xc2\xb9\xe6\x3f\x73\xa3\x79\x6c\x32\xc9\xe6\x45\xcb\xd8\x90\xee\xd6\x0f\x16\x4c\xb2\xe5\x56\x68\xe8\x22\xeb\xde\x6d\xdb\xf6\x5a\x8b\x68\x4d\x45\xae\x6d\xd2\x82\x0f\x6e\xd5\x85\xd8\xe3\x64\x39\x75\xc3\xa8\x3b\xc9\xbe\x35\xdb\x4f\x4a\x9f\x8e\xba\xa1\x54\x71\x2e\x18\x1a\xa2\xd0\xf8\x41\xc4\x3c\x9e\x2d\xe3\xc9\x08\x21\x3b\x31\x87\x21\xb3\x1f\x0b\xa1\xb5\x17\xb3\x08\x4e\x31\x9e\x00\x91\x63\x43\x40\x30\xb9\x0e\xb9\xfc\x0d\x10\xc0\x0a\x68\xda\x0a\xe1\x04\x99\x55\x40\x2c\x9a\x70\xb0\x36\xab\x9d\xd9\x31\x9e\x29\xa5\xeb\x8a\x58\xaa\xb4\x9a\xf2\x5d\x93\x38\x74\x65\xeb\x2b\xd7\x5e\x76\xde\x95\xdb\x6e\x07\xd5\xe1\x5f\x7a\x5a\xc6\x30\xee\xbf\x39\xc7\xbb\xe0\x0b\xbf\xce\x54\xf2\x0a\x6c\x2a\x3a\xd4\xd9\x79\x68\xd5\xc0\xbb\x5d\x0b\xf7\x1e\x7c\xf2\x50\xff\xc1\xcd\x7b\x6b\x5f\xc1\xdf\x4f\x2c\xcf\xbc\x53\x5c\x05\xd4\xb8\x52\xb8\x4f\xb5\x61\xe7\xdb\xb7\x5c\xb9\xe2\xb2\x6b\x4f\x2e\xba\x6a\x63\x1e\x94\xce\xff\x89\x8b\x69\x68\x29\x78\xc3\xc1\x99\xa5\xcf\x6c\xe5\xe3\xc2\x5f\x58\xe1\xee\x4e\xf9\x32\xa7\x9e\xaa\xdb\xbb\xf9\xe0\xa9\x43\x4f\x1c\xda\xdb\xb2\xf6\xda\x57\xce\xd2\xf8\x9d\x4e\xb4\xe0\x46\x69\xfc\x82\x95\xc7\x1c\x8f\x95\xcd\x6e\x12\x9d\xa4\x12\x84\xd7\x82\xc8\x16\x11\x34\x4b\x48\x01\x99\x60\x37\x8f\x8d\x2e\xec\x4e\x62\x63\x08\x46\x8e\x6f\xa9\xee\xac\x44\x71\x0f\x6f\x06\xe4\xaa\x2b\x11\xdc\x05\x0e\x12\xb2\xe5\x45\x0a\x0b\x62\xa5\xf3\xa3\x55\x62\x41\x44\x6d\xd4\xaa\xd6\x68\x68\x6e\xfb\x27\x97\xfc\xf1\xeb\x51\xa2\xfc\x70\xed\xe8\x41\x71\xf3\xd0\x15\xcd\xf0\x71\xb8\x79\x8c\xcb\x66\xb6\xe6\x1b\xc8\x3e\xde\x78\x5f\x8d\xdf\x67\xd4\xe7\xfa\x0b\x8b\x6b\xf2\xac\xf5\x3a\x76\x16\xe7\xd4\xf4\xfe\x07\x8c\x3b\x2d\xc0\x4f\x2e\x2b\x3d\x3c\x6a\x28\x8d\x68\x24\x0e\x52\xcc\x02\x32\x3f\x4c\xa2\x19\xa8\x03\x21\xe4\x1d\x5a\xcd\x01\x2b\x2b\x88\x10\x02\x03\xb0\x85\x60\xa1\x08\x56\x83\xcc\x86\xf3\x80\x73\xd8\xc9\x3b\x17\xa2\x62\x94\x45\xe1\xe4\x2c\x04\xce\xce\xc8\x33\x48\xbb\xc3\x2e\x57\x0f\xd1\x27\x88\x14\xe1\xa7\x95\x03\x02\xd8\xe3\xf5\x10\x8f\xc1\xfd\xe9\x45\x8b\xd2\xad\xb0\xaf\x76\x1c\x2f\x5d\xcb\xf1\x34\xc5\x69\xb7\xc3\x4f\xc6\xe5\x1a\xf4\xe1\x58\x41\x2e\x85\x7f\xc5\xcc\xf5\xd1\x1a\xb3\x95\xe3\x2c\x85\x26\x2d\x1d\xfa\x83\x63\x61\xa3\x1b\xee\xe2\x38\x0a\x38\x69\x6d\x49\x6b\x4e\x8e\x9f\xd5\x96\xfb\x92\x41\x35\xb0\x78\x07\x75\x5d\x21\xa5\xd6\x5a\xd9\x8d\xd2\x6f\x29\x15\x45\x69\xe9\x17\x5b\xc7\xa6\x5a\x5b\x53\x63\x33\xbe\xb0\xcf\xee\x80\x87\x74\x1c\xa6\x54\xfa\xbd\xd2\xad\x52\xa2\xb7\xd8\xc9\x3a\x73\xf5\xb5\x79\x26\xbc\x00\x7a\x6e\xff\x20\xc7\x6f\xd1\x03\xa6\x74\xd6\x1c\x03\x86\x12\xb8\xc8\x1b\xcc\xfc\x93\xd1\x51\xa0\xff\xe9\x86\xbe\xaa\x44\x9b\x7b\x62\x9e\x5d\xe7\xb6\x18\xd5\xb0\x58\xba\xaf\x52\xc5\x60\x46\x5b\xa4\xb9\x17\xbe\x04\x1a\x63\xb5\x8a\x70\x9f\x51\xe8\x13\x35\xa2\xf3\x11\x46\x5a\xe4\x43\x95\xa8\x11\xad\x40\x3b\xe5\x1e\x8e\x62\xa2\x59\x1b\x20\xb0\x0c\xab\x4b\x90\x39\x81\xa0\xc8\xad\xc9\x23\x80\x11\x7d\x04\x58\x79\x8a\xf3\x25\xa9\x7a\x88\x86\x28\x31\xe2\xa2\x0a\xff\x8d\x18\x07\xfc\x70\x0f\x50\x2d\x2b\x3a\xe2\xd1\xd6\x35\x99\x67\xc1\xc2\xbf\xcd\x5b\xa4\xf7\x13\x1a\xb3\xf4\x9d\xcd\xa2\xc7\xa5\x6a\x33\x34\xf1\x56\xaa\xa6\xff\x79\xe9\x5b\xde\x6a\xe5\x41\xf7\x02\xdc\x00\x86\xfc\xba\x92\x88\x50\xed\x34\x02\x00\xef\xac\x12\x4a\x8a\x92\x05\x26\xfc\x28\x18\xf2\x93\xa7\xe3\x73\x87\xe2\x1f\xca\xa6\xaf\x3a\x33\x1e\xb0\x0b\xd4\x3f\x9d\xdf\x25\xed\xd8\x08\x2f\x65\x74\xf2\xd5\x93\x33\x0d\x7e\x13\xfe\x8e\xb7\x3e\x27\x5d\xfc\x9e\x95\xc7\xff\xe0\xad\xd2\x72\xad\x7f\xf5\x92\xad\x25\x65\x5b\x57\xb5\xe6\xe5\xa9\x0a\x5a\x17\xed\xae\x29\xdf\xb6\x72\x81\xd3\xf9\xff\x18\xaf\xec\x7f\x32\x69\xe6\x5b\x34\x15\x2d\x42\x6b\xd1\x2e\x84\x98\x68\x08\x08\xa9\x3e\x11\x67\x14\x43\x94\x28\x44\x13\x49\x2a\x4b\xd8\x4d\xd4\xd2\x71\xd6\xba\x9d\x23\x64\x79\xf2\x94\xd0\x71\x1a\xa9\x96\x04\x8b\x57\x88\x2a\x4b\x3b\xd1\x78\xd8\x61\xb7\x72\xac\xdd\x2b\x5f\x24\x6e\xcc\xc6\x18\x39\x25\x22\x09\x46\x21\x1b\x65\x36\x62\x0e\xaf\x72\xfa\x31\xa8\xd4\x6a\x83\xdf\xd1\x9e\xe3\xd5\xb3\x1a\x46\x05\x81\x00\xa8\x18\x0d\xab\xf7\xe6\xb4\x3b\xfc\x06\xb5\x5a\x05\xd8\xef\x9c\xef\xb6\xe6\x7a\x53\xd5\x33\xea\x0b\x0a\x59\xaa\x52\x10\x2a\xab\xf2\xea\x37\x53\x54\xca\x9b\x6b\x75\xcf\x3f\xe6\x14\x2c\x81\x80\x45\x88\x5a\x1a\x1b\x6d\x8f\xc4\xcd\x16\x4b\x77\xb7\x1c\x3a\x72\xe4\xb8\x1c\x58\xb8\x64\xc9\x42\x39\xb8\x76\xf3\xe6\xb5\x37\x6a\xdb\xb7\xa9\xe9\xb2\x3c\x15\xaf\xd5\x32\x36\x4b\x01\x9d\x96\xd2\x74\x81\xc5\xc6\x68\xb5\xbc\x2a\xaf\x8c\x56\x6f\x6b\xd7\xda\xeb\x74\x2a\xb3\xa9\x7c\x6e\x62\x9c\x8e\x5b\xfd\xae\xf4\xed\xbb\xab\xb7\x8b\xad\x7e\x00\xb3\x4a\x57\x47\xdd\x29\xc4\x2c\x81\x58\x54\xb4\x44\x05\x4b\xe3\xeb\x8d\x96\x5f\x5a\x2c\x51\xcb\x46\xa8\xdd\x28\x47\x1c\x91\x5a\x8e\xbc\x20\x47\xb4\xfe\x19\xd0\x9f\x5b\xe5\xa8\xb5\xd2\x17\xd2\xcb\xd2\x17\x84\x27\xdd\x4a\x78\x9a\xd3\xc3\x63\xdd\x42\xa2\x6d\x94\x40\xf5\x68\x12\xd1\xd3\x5a\x8c\x56\xa2\xf5\x68\x2b\xda\x89\x2e\x47\xd7\xa0\xeb\xd1\x31\x62\x67\x4f\x76\x54\xfc\x59\x17\x67\xdd\xd1\xf1\xff\x65\xba\x51\x3b\x9a\xff\x55\xf8\x5f\xb9\xff\xd5\xf9\x80\x15\xe6\xe2\xdb\x88\xa3\xfc\xe3\xdb\x46\xc6\x65\x6e\x3b\x3b\xc5\x8f\x6e\xc2\xb2\x8c\xbb\x89\x23\x75\x9f\x23\xc4\x28\x4e\xe6\x8c\xd0\x39\x53\x66\x43\xd0\xd1\x7e\xfa\x0e\x58\x71\xa4\xf6\xb3\xe3\xce\x08\x0c\xf0\x3d\xca\xd9\xf2\x3f\x1c\x38\x3b\xd0\xaf\x38\xd4\x19\xa1\x73\x25\x54\xfe\xb3\xdc\x65\xec\x00\x8b\x86\x19\xe1\x9b\xd0\x1c\xb4\x0a\x5d\x88\xf6\x21\x64\xcf\x96\x5a\x7c\x48\x29\x13\x38\x18\xb2\xa0\x52\x7a\x4b\xca\x36\x6c\x2c\x15\x27\xb2\x6a\xf2\xab\x47\xac\x7d\xc8\x7a\x23\x99\xef\x0d\x95\x7d\x40\x89\x53\x40\x1d\xca\x72\xa4\xdb\x1e\x50\x74\xe7\xe4\x01\xaa\xa2\xbf\x66\x67\xec\x43\xd8\xcd\x6c\x84\x32\xef\xff\x9c\x7c\xcf\x06\xb4\x70\x10\xc1\x7d\x24\x80\xbf\x74\x44\xfd\xbe\xc2\x02\xc1\xf0\xd1\x31\x79\x26\xde\x75\xc4\x11\xf1\x7b\x83\xa2\x5f\xd1\x4c\x10\xa2\xc2\x90\x76\x43\x86\xa4\x87\x89\x42\x54\xd8\xdd\xb6\x68\x8f\x10\x15\x4e\x82\xff\x24\x5c\x45\xc6\x73\x16\x0f\x37\xfe\x16\x9b\xca\x68\x8a\xda\x1e\x86\x80\xda\x96\xab\xd5\x95\x1a\x17\xbd\x62\xe7\x8c\xc6\xa8\xed\x2f\x3f\x25\x8b\x0e\x37\x29\x4b\x0f\x65\x83\x68\x21\xa0\xcb\x95\x00\xaa\x59\xd6\x52\x5e\xe4\x13\x92\x0d\x45\xc7\x3e\x12\xa2\xc2\x91\xae\xea\x25\x73\x2b\xc4\x50\x74\x49\x42\x51\x51\x91\xf3\x94\x15\x86\xf8\x23\x39\x85\xa0\x3d\xda\x76\xef\x6e\x93\xdd\x83\x27\x4f\x5e\x23\x0f\xed\xec\x96\x07\xb7\x18\xa3\x36\x9b\xca\x78\xe5\xa5\x64\xa8\xf7\xf5\xcd\xc6\xa8\xcd\xce\x19\xb3\x38\x5c\x6a\x10\xa9\x32\x59\x9c\xc5\x4a\xf4\x73\x32\x9e\xcf\x5a\xbe\x93\xd1\x6e\x3c\x11\x0f\x44\xcb\x89\x75\x4d\x56\x5c\x51\xee\x7d\x78\x62\xfa\xcd\x85\x15\x48\xac\x5c\xa2\x61\x82\xcc\x87\x12\x10\xc4\x80\x22\xf5\x27\xc4\xeb\xc1\x12\x37\x27\xe2\x2e\x90\x4f\x8d\x67\x35\xf1\x58\x4e\x91\x5a\x0c\x10\x62\x3e\x8a\x55\xd0\xec\x42\x3c\x11\x4f\x0c\xfd\x56\xc4\xaf\x8c\x11\x93\x04\x66\x90\xf0\x0e\x1f\x88\x64\xa3\x6b\xb0\xdd\xc1\xc8\x8d\x32\xad\xaa\xc9\x35\x25\x03\xb1\x46\xbf\xc6\x5b\x11\x48\x9a\x72\xf1\xa6\x21\x5f\x4d\xf6\x88\x34\xcf\xd4\xe4\x4b\x4e\x8e\x54\x50\x7a\x6a\xd1\xd1\xa0\x29\xcf\x6f\xb6\xd9\xcc\xfe\x3c\x53\xf0\xe8\x22\xd6\x98\x2f\x7d\xf0\x37\xde\x10\x34\xf5\x68\x79\xfb\x6b\x87\x4c\x87\x2f\x28\x9c\x11\xe6\x0a\x27\x96\x5f\x78\x20\x58\x4f\x33\x15\xc1\x39\x8d\xa1\xd8\xa6\x95\x7e\x27\x75\x62\x38\x85\xd3\x57\x56\x90\xab\xa4\xa1\x55\xfe\xc4\xc8\x54\xe6\xff\xe6\x56\xc0\xe7\x83\x4f\xbe\x17\x4e\xe1\x98\x57\x6c\x8c\x55\x79\x54\x85\xa2\x37\xb6\x2b\xeb\x62\x12\x0b\x66\x9f\xd3\x54\x68\x82\xe5\xb3\xfd\x8d\x26\xb5\xda\xd4\xe8\x9f\xbd\x1c\xe3\xbc\x6d\x9c\x0f\x52\x8e\x4a\xfd\x56\xd0\xde\x0c\xa6\xe5\xb9\x5c\x72\xba\xb3\x66\xc2\x1c\x13\x53\x11\x0c\xd6\xd3\x9a\x32\x4d\xd8\xdc\xb8\x43\xea\x95\x53\x48\xdf\xdd\x2c\xfd\x6d\xb9\xdd\x57\xa8\xa4\x80\x0a\xff\x70\x0a\xff\x7f\x71\xed\x33\x6c\x8e\x2d\x68\x3c\x9a\x8e\x16\x21\x04\x0a\x3a\x4a\x70\x0f\xe3\xa4\xc2\x76\x45\x9b\x82\x84\xc8\x9b\xc8\xc3\xd0\x7b\xca\x12\xf8\xbf\xf2\x9e\x52\xb1\x68\x08\xc0\x31\x6c\x77\xe7\xb0\x5b\x0d\x94\x20\xd6\x43\x3c\x4c\xbb\xe5\x17\x44\x7a\xef\xa4\x10\x15\xf6\x3c\xb2\xa7\x53\x7e\x85\xe4\x0a\x4f\xa4\x4d\xfc\x62\xd0\xeb\x8f\x38\x8e\x74\xc9\x75\xf8\xd8\x47\x06\xa1\xa0\xd0\xe7\x8f\x3a\x5a\x6f\xce\x3c\xfb\x71\xe6\x49\x9d\x57\x77\x97\x4e\xc7\xa6\xee\xd2\xe9\xbe\x74\x4e\x6a\xb8\xa4\xf5\x77\x7a\x2f\xee\xcd\x56\xf7\x83\xd9\xea\x0f\x9f\xb4\xde\xfc\xc6\x16\x39\xa0\xbc\x27\x89\x25\xd1\x90\x58\x31\x77\x49\x75\x17\x59\xd6\x3c\x56\xd4\x90\x14\x7c\x45\xe5\x2d\xcb\x6a\xb6\xbc\x71\x73\x66\x9f\x7c\x59\xdd\x5d\x3a\xaf\x8e\x65\xef\xd2\x79\xf5\x5f\xe6\x4e\xba\x71\x55\xeb\xef\x74\x23\xd7\xf0\xad\xa8\x85\xa8\x2e\x59\x39\x1e\x14\x9e\xf1\xec\x1e\x4f\x24\x6c\x87\xec\x50\x40\x94\x87\xf2\xf2\x90\x00\x13\xdb\x7d\x05\x85\xee\xf3\xc6\xa2\x72\x51\x90\x37\x2a\x4b\x7a\x92\x24\x5c\xe2\x59\xc0\x78\xe4\x6c\x76\x34\x6a\xa9\x5e\x5b\xa4\xc1\x8c\xd6\xaa\x1d\x13\x9d\x38\x3e\xdf\x91\x6f\x82\xcf\xa7\xeb\x6d\xfa\xd6\xcb\x31\x55\xf9\x6d\x4e\x69\xfb\xe1\xa9\x3f\xb9\x2e\x17\x68\x3b\xdf\x58\x56\x6c\x2b\x70\xd9\xb9\x9c\x09\x85\xbe\xea\xdc\x95\xf3\x67\x1d\x5c\x60\x63\x2d\x0c\xa5\x3d\x7f\x6d\xc5\x0c\xa0\x18\xf5\x23\x67\x18\xe7\x65\xf2\xc6\x85\x5f\x08\x6b\x29\xc0\xcb\x52\x2d\xf7\x0a\xbc\x47\xaa\xe6\x2f\x64\x54\xd3\xb0\xfd\xe3\xb1\x5f\xb2\xa6\x6b\x9f\x58\x7c\xf0\x56\x16\x7b\x67\x47\x97\x96\xe7\x94\xbb\x73\x0d\x40\x71\xf6\x82\xf1\xb3\xbc\x2d\x6b\xba\x0e\x36\xdb\x17\xd8\x75\x6c\xad\x19\xd4\xd8\x70\xa6\x99\x1e\xc2\x28\x30\x88\x98\x77\x99\x41\x94\x8b\x56\x20\x44\xf8\xea\xbc\x1c\x8b\x6d\x56\x17\x8e\x84\xed\x49\x9c\x90\x1b\x01\xb0\xb2\x3e\x51\x39\x42\x4a\x91\xf2\x79\x87\x65\xd2\xad\x72\x05\x92\x8b\x86\x4a\xc4\xa2\x42\xb1\x02\xe9\x22\x2a\x9a\x11\xb7\xc9\x8a\x39\x85\x1a\xc8\x05\xf8\x0b\x5a\x5f\xe0\x10\xc5\x55\x6b\x4c\xfe\x09\xe5\x74\xbe\xce\xaa\xc1\xc6\x94\xd1\x82\xbf\x35\xa8\x58\x7b\x73\xaa\xf0\xce\x47\x0c\xac\xa6\x40\xe5\x68\xdf\xfd\x60\xc7\xe5\xc7\xc4\xf9\x71\xe1\x76\xf0\x84\x42\x6e\x8f\xbb\xac\x39\x56\x62\x67\x38\x8d\x46\x03\x9f\x9c\x9a\x70\xe1\x93\xeb\xa2\x71\x38\xbf\x89\xa1\x56\x1c\x9f\x67\x2f\xb4\x6c\xa7\x7f\x97\x53\x50\x68\x70\x8c\x91\xfe\x79\x65\xe9\xec\xe9\xe5\x00\x8c\x4e\x33\x0d\x62\xd3\x5a\x33\x77\x72\x7a\xa0\x8c\xea\x36\x95\xc5\xbf\xb7\xb0\xf5\xc4\x0d\xed\x77\x5e\x11\x4b\xaf\x1a\x97\x0f\x0e\x31\x3c\x59\xf0\x04\xeb\xdb\xce\xef\x28\x56\x63\x0a\xbe\xfb\x78\xcd\xc7\xcf\xee\xb7\xa8\xa5\x1b\x96\x4a\xb7\xf9\xa9\xea\xa4\x9e\x7b\x1a\x51\x08\x06\x11\xbb\x93\xe9\x47\x75\x68\x16\xba\x1c\x21\x08\x17\xca\x53\x1a\x32\x0b\xe6\xf4\x90\xad\x48\x01\x0f\xd1\x54\x8d\x94\x81\xd2\xb6\x01\x13\x20\x9e\x48\xd8\xc1\x38\xc2\x8a\x81\x9c\x3c\x41\xe2\x1c\xe5\x98\x1a\x02\xb2\x17\x82\x5c\x15\xed\x60\xb1\x1b\x80\x35\x40\xbc\x1c\x04\xd2\x4e\x73\x94\xb2\xa5\xa8\x06\xc5\xb5\x64\xc3\x16\x87\x8b\x24\x8a\x27\xc2\x76\xaa\xde\x9d\xf7\x41\x5d\xe5\xc1\xa0\x76\x32\x5b\xee\xce\xfc\x5d\xea\x51\x8b\xd5\x71\x01\x68\x29\x55\x54\x8d\x71\xad\x08\x8f\x65\xfe\x59\x14\x66\xd9\xea\x80\x06\x3e\x92\x7e\x22\x54\xb0\x6c\xdc\xc7\xf2\xd0\xfb\x0e\xd0\xe0\x30\x58\x1f\xf3\xf1\xb9\x79\xb6\xc7\xde\x65\xfc\x5f\x03\x05\x39\x5a\x77\xe1\xd4\xbc\xab\x31\x0b\x6e\x33\x75\x87\x81\x36\x54\xe8\x12\x5d\xb8\xe8\x60\x2c\xf5\x81\xb7\x38\x12\xf8\x4b\x2e\xef\xf5\x4c\xcb\x01\x8d\x74\xca\x66\x0b\xf8\x1a\xad\x7f\xbf\xc2\x60\xf3\x06\xa6\x9b\x9e\x59\xa1\x72\xe5\x80\x0e\x57\x15\x89\x55\xd4\x62\xf3\xa1\x60\xf5\xcf\x42\xb5\xd2\x32\x77\x09\x5d\xe5\xae\x0a\x06\xe2\x8c\xbb\xb6\x48\x8c\x42\x8a\x49\x15\xf9\xca\x6a\xdb\x35\xf5\x01\x7f\x19\xee\x08\x40\x48\x7f\x91\x63\xa6\x47\x78\xe9\xa2\x00\x16\x80\x05\x06\x0a\xa7\xe7\x3a\xb4\xf9\xd7\x01\x83\xcb\xd6\xc0\x9d\xd2\xf7\x53\xa6\xfe\xb1\x26\x3f\x9e\x2c\xff\x59\x5d\xf1\x21\x47\x00\xaa\x3c\x33\x1d\x76\xa3\x5b\xea\x81\xe7\x7d\xcd\x16\x73\x8e\x57\x5a\x04\x33\x7d\xd3\x4d\x16\xa7\x20\x2d\xf9\xb5\x81\xb1\x1a\xfb\x8a\x6a\xa1\x5a\x69\x03\x5d\x1c\x62\x96\xa2\x59\xa8\x0d\xad\x45\xdd\x08\x05\x14\xf1\x82\x58\x34\xc9\x26\xe2\x01\x21\x16\x55\x6c\x4d\xe2\x11\x37\x92\xc7\xf6\x8a\x89\x36\x99\xbe\x63\x42\xf9\xef\x04\x25\x28\x02\xcb\xd9\x91\xcd\xea\xf3\x0a\xe5\x40\x11\xc1\x02\x8b\x35\xe0\xf0\x5b\x70\x80\xd0\x34\x20\xb9\xc6\xdb\xb3\x2d\xa9\xe0\xf3\x06\x44\x07\xcc\xc0\xf4\xbc\x3b\xaa\x6d\x34\xad\xe1\x78\xd6\x8c\x1f\x01\xdd\x3a\xd3\x66\x9d\x59\xb3\x63\xd1\x72\xd0\xc0\xef\xae\xb3\x5a\x5b\x07\xaf\x5f\x67\xda\xac\xb5\x68\x76\xa4\xa4\xf1\xdc\x98\x22\xea\x87\xaf\xd5\xfa\x9a\x6a\x4a\xaa\x12\x4b\x72\x60\x87\x96\xbf\x92\xee\xea\x2b\xf5\x62\x37\xf7\x73\x2a\x5a\x09\xa6\x13\xbf\x90\xbe\x1c\x37\xb9\x5d\x5a\x97\x6f\x9d\xb7\x3d\x3f\x98\xff\xe0\xc5\x56\x98\xa5\xe6\x7e\x81\xab\x7f\xbe\xc8\x25\xaa\xad\x46\xab\xce\xae\x72\x50\xfd\x1b\x9f\xd3\x5b\x34\x29\xe3\x67\x16\xe9\xab\x2f\x0a\x9b\x0a\xaf\xfe\x30\xf5\x9c\xde\xaa\x4e\x19\x3f\xdb\x4a\x45\xb9\x1c\x07\x23\xc5\xa5\xc9\x14\x87\x29\x8e\x9a\x92\x1f\x2c\xc9\x8c\xa3\x35\xa5\xec\x6f\xe0\x68\x2c\x46\x95\xea\xa4\x47\x35\xe7\xb5\xae\x07\x33\xd8\xba\x53\x77\x2f\xea\x7a\x12\xd7\x04\xf3\xb7\xcf\xb3\xe6\xe7\x5b\x2f\x7e\xd0\x44\x73\x43\x38\xb2\xeb\x69\x89\x59\x85\x0a\x51\x39\xd1\xcb\x95\x5b\x53\x05\x5e\x4a\x1a\x01\x07\xcb\x65\xe1\xb8\x6e\x79\xe6\x14\x4f\xd8\x45\x2b\x36\x80\x57\x4c\xd2\xb1\xa8\x68\x17\x6d\x82\xe8\x02\x8b\x57\x94\x87\x06\x3c\x70\x4a\xf3\x2b\x37\xa4\x8a\xb0\x12\xed\xbc\xee\xd0\xe7\x5f\x1c\xbc\xee\x8a\x6f\xaf\xeb\x98\xe7\xe6\x1a\xa6\xdd\xf9\xc9\x47\x30\xab\xcf\xdd\x50\x5d\xf4\xf2\xb1\x63\x7c\x81\x67\xf6\xce\xc9\x65\x06\x2a\x91\x98\x72\x69\xcb\xda\xcc\xec\x69\xef\x4e\xb6\xe0\xe2\x5f\xad\xf6\x79\x9d\xa1\xf5\x35\xed\x79\x53\x73\xdc\x1b\xe0\xfe\xb7\x8e\xfd\xe4\x27\xc7\xde\xba\xee\x9f\x07\x0b\x93\xa9\xfc\xef\xef\xfa\xd9\x57\x5f\xfd\x6c\xc1\x34\xbd\x7f\x69\x63\xaf\x74\x72\x39\x30\xee\xfd\x77\xfd\xfe\x81\xd6\x09\xde\x9e\xdb\xf0\x9b\x1f\xd7\x0c\x4a\x8f\x36\x6e\xdb\x19\xb0\xb4\x5f\x9b\x1b\xaf\x09\xcc\x71\x96\xba\x8c\x73\xc7\xac\x3a\xb4\xb6\x6e\xda\xea\x21\x7e\x2c\xd2\x77\x38\x51\x11\x0a\xa1\xf1\x68\x0e\x61\xf0\x20\xf0\x31\x36\x4b\x17\xe0\x88\x27\x14\x95\x64\x77\x9c\x22\x82\x57\x9c\xbd\x06\xe2\x26\xb9\xb7\x10\xed\x4c\x94\x20\x0e\x88\xc8\xa1\xfc\xc4\xd9\xa1\xd8\xa8\xce\x82\x76\xe6\x17\x95\xda\x6f\xfa\xe2\xe6\x5b\x36\xc5\xca\x68\x47\xed\xd8\x9b\x7e\xf7\x3b\x88\xfe\xee\x41\xac\x29\x0c\xcf\xaf\xb6\xd9\x34\x7f\x14\xe8\xe6\x31\x8b\xe0\x92\x48\xd1\xec\x09\xcd\x39\x53\x2f\x2d\xa0\xf7\x8f\x8f\x8e\x89\x4c\xb7\x99\x60\xca\xc8\xce\x01\xfe\x36\x7d\x42\xae\x3a\x9c\xda\x72\xfc\xf8\x96\x4d\x77\x5b\x4a\x4a\x6d\xef\x48\x2f\xbd\xfe\x06\x64\x72\xca\xeb\xb7\x5d\xbb\x69\x89\x9d\xda\x0b\xc6\xcd\x6b\x9b\x1f\x16\x6f\x29\x3a\x6f\xf2\x3c\x87\x65\xc2\xd8\x60\xc0\xb4\x7c\x6c\x74\xab\x10\x9d\x1a\x2b\xfe\xe6\xac\x3e\x61\xe8\xf9\x67\x10\xdc\x5c\x74\xe8\x1d\xc2\xca\x08\xdd\xe7\x15\xe3\xd9\x6e\x91\x63\x15\xc0\x80\xf2\xf3\x13\x03\x41\x96\xc4\xc9\xbd\x07\x91\x0a\x8e\x84\x09\xb6\x8a\x74\x9d\x67\x6e\xf7\x0e\xda\xc7\x9d\x57\xc0\x89\xe5\x62\xc0\xaa\x0b\x6a\x69\x15\x63\xf2\x5f\x36\xf7\xf9\x26\x13\x43\x6b\x74\x41\x8d\xcd\x27\x96\x8b\x5c\xea\x32\xfb\x95\x58\x65\x30\xea\x22\xbc\x2f\x55\x3a\xa9\xa8\x64\x72\x49\xca\xc7\x47\xf4\x46\x5e\x85\xaf\x04\x18\xbd\x1a\xb6\xc7\xce\x18\x5a\x52\x16\xd6\x60\xd7\x15\xd8\x2d\xb9\x46\xbc\xd8\x32\xc3\x37\x7d\xfe\x1d\xbe\x19\x96\xc5\xd8\x90\x63\xb5\x15\xe8\xec\x06\xd6\x72\x55\x01\x63\x0f\xd9\x99\x62\x8b\xda\xe5\x73\xb9\x7c\x2e\x95\x35\xc8\xd8\xa1\x7f\xf4\x3a\x18\x20\xc3\x60\x9a\xdd\xc0\xa4\x49\x29\xc4\x15\x1d\x30\x05\xc8\x44\x74\x07\x09\x01\x97\x23\x2b\x0f\x86\x15\x5c\x53\xd6\x9e\x49\x29\x26\xa5\xd8\x94\xaa\x1e\x8f\x45\x43\x58\x21\x9a\x88\x84\xb3\xe2\xe5\x54\xf3\x65\x6f\x54\xe7\xa9\x79\xde\xdc\x60\x2e\x88\xd7\x37\xd6\xeb\x02\xbb\x67\xe4\x47\xf3\xff\xc8\xa9\xac\x0e\xeb\x1c\x7b\x20\xd7\x9d\x8c\x27\x17\xc6\xa3\x0b\xea\xe2\xc9\x42\x67\x20\x67\xb6\x29\xd7\xaa\xe2\xfe\x98\x1f\xcd\x9f\x7e\xa9\x5f\x57\xdf\x54\x1f\x2d\x30\x34\x58\xcd\xbc\x3a\x2f\xf5\x36\x93\x86\xbd\x17\x8e\xb9\xa0\xfc\x00\x97\xe7\xcf\x77\x97\x5a\xc4\x7c\x43\xfe\xac\x2b\x3c\x3a\x2d\x5b\x30\xd1\xa3\xad\x0a\xe8\x19\xc6\x57\x14\xcc\xcb\x0b\x16\xf9\x18\xc6\x10\x18\xa3\xf5\x4c\x2c\x60\xb5\x3a\xf7\x55\x33\xf3\x0d\xf9\xa2\xb5\xa4\x30\x2f\xe0\xe4\xae\xae\xd8\x3e\xe6\xca\xed\xa3\xea\xc0\xe2\xff\xd3\x3a\x30\x9a\xc1\x80\x41\x4a\x3d\x08\x89\x01\xab\x36\xa8\x23\xf5\xe0\xd2\x79\xcf\x4d\x33\xb3\x1a\x46\x5b\xa4\xb1\xfa\xc4\x10\xa9\x07\x57\x61\x15\x6f\xd4\x47\xf4\xbe\xb1\x4a\x3d\x18\xeb\xd3\x47\xf5\x06\x83\x0a\xae\x02\x74\xc6\xcb\xb0\xc7\xce\xf0\x2d\x63\x79\xed\x70\x25\xa8\x8f\x4e\xf7\x4f\x9f\x7f\x87\x30\x4d\x68\xc2\xc6\x5c\xa5\x12\x68\x79\xb9\x12\x94\xcb\x95\x40\xa3\x54\x02\xb5\xa5\x84\xb2\x53\xda\x51\xef\x02\x28\x98\x44\x16\x91\x56\x8f\x67\x94\xe1\x0f\xc7\x72\x7e\x86\xe5\x92\x50\x0f\x49\x2a\x11\x67\xc8\xfc\x89\x62\x45\x62\x01\xcc\x86\x70\x39\x44\x63\xd1\x48\x38\x61\x46\x91\xb0\x8b\x71\x24\x92\x74\x22\x49\xa9\xd1\x84\xee\x86\x98\xdd\x4e\x69\x22\x0e\xc3\xc4\xb1\xcd\xaa\xf2\x4e\xe9\x1e\xe9\xc3\x45\x7f\x28\x9f\x6e\x34\x4c\x7a\x64\xf6\xa5\x4d\x8f\x81\x03\xd4\x5a\x96\x7d\xd6\xe0\x4e\x7f\x7c\x50\x42\x57\xcc\xba\xac\xb9\x58\x07\xec\x55\x5f\xf6\xc2\xda\x17\x19\x4b\x75\x6c\x62\x55\x94\x3f\x0f\x0b\x91\x49\x4b\xa2\x0d\x3b\xb6\x36\xb0\x28\xb4\x68\xe2\x94\xe2\x72\xd6\xfc\x55\xa8\xa0\x5e\x28\x65\x0b\x5f\xe0\xef\x8d\x5d\x6c\x74\x71\x5c\x5e\xa3\x3b\xa0\x2f\x14\x28\xd6\xae\x95\xee\x2c\xe0\x72\x16\x60\xc8\x0f\x79\x4d\x00\xc0\x26\x60\x1d\xd4\x82\xda\xe0\x2d\x9b\x12\x3a\x41\x4f\xeb\xb8\xf0\xc0\xd8\x59\x5b\xa7\x7a\x46\xf0\x60\x4d\x44\x2d\xa8\x1d\x2d\x27\xd8\x36\x2b\x27\x3a\xd8\x91\x1f\xaf\x98\xe0\x84\x91\x9f\x58\x34\xe1\x10\xe3\x23\x3f\x91\xb0\x83\x4b\xd8\xcf\xf8\x44\xb1\xdf\x47\x26\x1f\x72\x75\xf0\x9b\x2d\x04\x97\x6d\x52\xe0\xd9\xe4\x8b\x29\x66\xfe\xda\x67\x11\xdf\x3c\x51\x5a\x7f\x74\x65\xdd\x8c\x19\xbc\xd0\x24\xf0\xd3\xa7\x36\xac\x3c\x5a\x53\xf9\xe0\x9b\xa2\xa5\xef\x2b\x86\xf9\xfa\x23\x39\x41\xa8\xee\xd6\x95\xe3\xa6\x4c\xd3\xfb\x45\x41\x49\x71\x6b\x5d\xe8\xc4\x1b\x01\x5b\xdf\x57\x8c\xeb\xa8\xf4\x9f\xb7\x6e\x7d\xfb\xe8\xa2\x45\x47\xdf\xde\x7a\x2b\xe8\x8f\x4e\xc9\xac\xcf\xac\xc7\xd7\xe2\x5f\x67\x6a\x33\xb5\xcc\xaf\x33\x44\xbf\x00\xa7\xcb\x0a\xf9\xe9\x53\xc6\xaf\xbc\xb5\xae\xfc\xc1\xb7\x02\xf6\x4f\xbf\x61\xd9\xaf\x3f\xb6\x04\xdf\x7a\xb0\x64\xec\xad\x9d\x13\x26\xcf\xe0\x8b\xbd\xbe\x62\x7e\xc6\x94\x71\x9d\xc7\xe4\x14\xa2\xa5\xef\xaf\x2c\xfb\xd5\x47\x96\xe0\x9b\x0f\x96\xd7\x1d\xeb\x4c\xce\x98\xce\x17\x86\x7a\xc0\x70\xb4\xed\xe8\xbb\xdb\xb6\xbe\x7b\xb4\xed\x28\x18\xb0\x2b\x83\xa5\x4b\x60\x27\x96\x60\xe7\x8f\xbf\x85\x5b\xa8\x04\xdc\x2c\xad\x18\x78\x91\x6a\x1d\x48\x4b\x29\xe8\xa5\xd2\xd0\x3b\x8c\xb3\x24\xb6\x44\x45\x28\x8e\x10\x78\xb8\x2c\x1e\xc6\x61\x8f\x0c\x91\x29\x07\x22\xc0\xb3\x5c\x2c\x4e\x16\x22\x21\x62\x01\x93\x27\x9e\xf0\x98\xa2\x82\x98\x70\x01\xcc\xc6\xff\xe1\xcc\xac\x5c\x77\xf4\x82\x36\x47\x63\xd9\xbe\xe7\x9f\xa7\x3e\xfc\xa7\xe4\x72\xf8\x12\xb1\xa6\xd9\x6b\x92\xc7\xab\xad\x56\xe9\x93\x4f\x1f\xa7\xe6\x0d\x7c\x16\x50\xe1\x9f\x2e\x6b\xce\x5d\x71\x11\x23\x4c\xbe\x75\xdd\x40\x66\xf1\x61\x0b\x33\xf9\x85\x7d\x14\xb5\xef\x85\x77\x4f\x7d\x5b\x37\x77\x7d\xd3\xcc\x4a\x0f\xfe\x95\xf3\x96\x68\x2c\x1e\xc5\xef\x67\x1e\x86\x6f\xfb\xef\x4e\x98\x69\x7e\xee\xbe\x82\x71\xde\xff\x40\x43\x5c\xef\x59\x2c\x9f\x15\x79\x50\x19\xaa\x46\xad\x68\x1d\xda\x86\x0e\xa0\x3f\x9d\xb6\x36\xa0\x62\x51\x21\xcb\x3e\x18\x8e\x27\xce\x1d\x38\xd3\x0f\x6c\x96\x26\x3b\xc1\xda\xac\x66\xc7\x30\xb3\xdc\x10\xd5\xa8\x59\x94\x27\x64\xac\x3c\x09\x4b\x28\x8c\x6a\x89\xb8\xc2\x4f\x47\xce\xce\x82\xf8\x86\x8e\x90\x16\x99\x4b\x02\x63\xc5\x1c\x4b\x1b\x86\x54\xaf\x88\x1d\xbb\x48\x66\x24\xa4\xc5\x4a\x08\x22\x69\x7d\x49\x4b\x46\x91\x4e\x5c\x9e\xd1\x61\x65\xb4\x4e\x26\x75\x72\xc3\x4e\x28\x29\x39\xbb\x12\x41\xcd\xf1\x56\x79\xbd\x55\xbb\x8a\x6a\x83\x45\x05\xae\xa2\x7b\x83\xb5\x45\x45\xae\x82\xa2\xfb\x8b\x6a\x8b\x8a\x6a\x87\x1c\xd0\xcd\x91\xde\x7e\xe0\xc2\x37\x0e\xcc\xb2\x75\xee\xda\xe6\xaa\xab\x72\xb9\x13\x55\x2e\xf7\x3a\xb7\xab\x2a\xbf\x52\xdf\xbd\xeb\xea\xc9\x26\xd7\xe2\xf8\xc7\xae\xd9\x0f\x1e\x5c\xbf\x4c\x2f\x4d\x4c\x2d\x4d\xd5\x2f\xaf\xc7\x5b\x1a\xaf\x5f\x3a\xed\x40\xa2\xa2\xf5\xbc\xd8\x02\xbf\x29\x12\xa3\x1b\xe7\x82\x63\x5c\xed\x18\xe9\xeb\x56\xba\xa6\x24\x7b\x81\x84\xdb\x55\x55\x5e\xb5\x70\xcd\xf9\x6d\xf1\xe8\x86\x09\x6e\x71\x41\x63\x6f\x45\x8e\xb9\x6c\xec\x9a\x86\x1a\xbb\xc5\x81\xad\x94\xc6\x99\x63\x9c\xff\xe3\x15\xbe\xbc\x9a\xf9\xb3\xab\x19\x9d\xde\x02\x26\xc1\x78\x34\x98\xeb\x2b\x4b\x2c\xa4\xbf\x18\x53\x5e\x3e\xa6\xfc\xd4\x9c\x8d\xae\x92\x12\xd7\x46\x57\x69\xa9\xeb\xbf\xf5\xe1\x97\x7a\x9e\x5f\x79\x4f\xdf\xb6\x96\x79\x0f\xbc\x75\x9b\xf4\xfa\x8a\xea\x30\xf9\x2b\xcc\x6d\x07\xcb\x7f\x34\xb2\x96\xff\x9c\x77\xfe\xce\x43\x47\xde\x9f\x58\x81\x1f\x0c\xcf\x98\x11\x8e\xcc\x98\x21\xf5\x75\xfc\x74\xcd\xc4\x9a\x63\x6b\x3b\xbb\x2c\x6c\x55\xd4\x69\x1d\xff\xab\x8d\xeb\xa5\xbf\x34\xa4\x8e\x3a\x61\x63\x49\x4a\x39\x7f\x5c\xc5\xf8\x66\xb0\x14\x76\x70\xa1\xde\x8d\x55\x9d\xd5\x57\xde\x72\xf1\x9c\x68\x41\x2e\x65\x65\x0d\x21\xc1\xba\x7e\x0f\x9d\xaa\x66\x38\xc6\x64\xb0\x00\x9b\xa3\x63\x2d\x57\x7d\xe3\xaa\x6c\x1e\x39\x87\xcf\x45\x01\x82\x12\x88\x8a\x1e\x5b\x64\x18\x40\xeb\xc8\x8e\xc0\x22\xe1\x78\x20\x12\xf3\xc5\x7c\x36\x9f\x2d\x62\x8b\x9c\xb1\xe7\x76\x98\x95\x8e\xbc\xa3\xbb\xa8\x79\xd9\xbe\x7d\xcb\xda\x6a\x3b\xd7\x1c\xee\xe9\xeb\xeb\xb9\xe3\xb7\xb0\x60\xed\xda\x75\xeb\xd6\xad\x03\xf3\xa8\x21\x04\xde\xea\x29\xdc\xd3\xb4\xe0\x9a\xe7\xae\xa9\x59\xb1\xfc\x23\xe9\xd9\x8f\x7e\xbf\x75\x1d\x49\x78\xfe\xe8\xd1\x81\xdc\x37\x04\xb2\xed\xa5\x48\x54\xea\xe4\xda\xea\xf7\x79\x39\x93\xcf\x14\xca\x92\x04\x5a\x59\x82\x7e\x26\x0b\x6f\x0a\x8b\x25\x8b\x2a\xef\xbf\x7d\x8a\xf4\xc9\xdc\xdb\x4f\xf6\xd4\x37\xa5\x1f\x4a\x37\xd5\x3f\x75\xe3\xb2\x65\xfc\xaf\xa2\xd3\x5a\xb4\x57\x59\x9d\x02\x8d\x06\x1e\xad\xe0\xa3\x35\x15\xd2\xfd\x4c\x4b\x6e\xf7\xf8\xd6\x74\xba\x75\x7c\x77\xee\xf8\x52\x03\x2e\x32\x63\x41\x50\xc6\xa7\x33\x89\x4e\x07\x83\xaa\xd1\x3c\xb4\x08\x1d\x42\xc8\x1c\x8e\x0b\x5e\x96\x09\x31\xa2\x22\x12\x57\x0f\x21\xcc\xfa\xbc\x06\xf0\x99\xc2\x71\x17\xe5\x20\x9b\xdf\xf6\x78\xc2\x9e\x48\x82\x48\xba\x62\xc1\x11\x31\xf9\x44\xa1\x04\xbc\x06\x60\xe5\xa1\x4c\x3d\xc4\x5d\xc0\xb9\x14\xf5\x32\x9a\x5c\x4f\xe9\xac\x95\x85\x13\x1e\x44\x1e\x42\x20\xc2\x70\xe7\x9d\x64\x6b\x20\xec\x88\xd7\x40\xd8\xc5\x3a\x3c\x61\xfb\x0d\xcd\x6e\x77\xb3\x9b\x55\x6b\xaa\x9d\x61\x5f\xc8\x7e\xd1\xec\xfe\xe6\x6a\x18\x73\xc2\x3e\x26\xd0\xa4\x5d\xd4\x70\xeb\xcd\x8c\x5b\x97\xc7\xdb\x54\x50\xb4\xa9\x7b\x7a\x79\xf5\x7a\xd3\xd4\x98\xd5\x8d\x35\x9e\x92\xf1\x85\xdc\x9e\x8e\xb6\xa3\x0d\x2b\xef\x5c\x50\xfd\x5a\x7e\x5e\xc9\x65\xa5\xcf\xe4\x56\x07\x34\xc6\x66\x6b\xc1\x6a\x6d\x14\x10\xb9\x2c\xa8\x04\xa7\x34\x3d\x6f\xdd\x44\xcf\xe2\x44\xf1\x45\x0d\xb5\x7b\x2e\x5c\x5f\x21\x7d\x24\xdd\x44\x80\x59\x77\xf0\x0d\x05\x35\xc5\xb5\x29\xff\x96\x65\xb3\x66\x2d\xbb\xd3\x97\xaa\x8c\xfb\x22\x79\x09\x1e\x96\x39\x05\x48\xa7\x52\x29\x56\x3f\xd5\x9b\x2a\x8e\x3a\xf6\xb5\xd3\x1d\x13\x1e\x1c\x7f\x52\xab\x05\xdc\x70\x6b\xa6\x0f\xe0\xff\xa3\xee\x3d\xc0\xe3\x2a\xae\xc5\xf1\x39\x33\xb7\x6c\xef\x45\x75\xd5\x77\x2d\x59\x5a\x49\x5b\x25\x63\xf5\x62\x70\x95\x2b\xc6\x60\xcb\xab\xdd\xbb\xd2\x5a\xab\xdd\xf5\x16\xcb\x72\x28\x02\xc7\x98\x12\x4c\x27\x74\x4c\xa8\x0e\xe1\xe5\x11\x08\x84\x6e\x48\x02\x84\x84\xc4\xa1\x3f\x48\x78\x40\x48\xf2\xd2\xc0\x09\x24\x2f\x80\x75\xf9\x7f\x73\xef\x95\x2c\x17\x92\xbc\xf7\xfb\x7e\xdf\xf7\xff\x19\x34\x73\x66\xee\x3d\x73\x66\xce\x39\x7b\x66\xee\xbd\x67\xe6\x10\x4e\xab\x12\x7f\x91\x6e\xb6\xb5\xb5\x73\x3e\x4b\xd8\xa9\x69\xe8\x5e\x55\x84\xd1\x43\xcb\xfb\x3e\xae\x5a\x57\xe5\xc7\xbe\xb7\x9c\xc4\x5f\x61\xdd\x58\x54\x7b\xa9\xb1\x77\x69\x77\x77\x37\x46\x33\xd3\x25\xee\x9e\xb5\x9a\x96\x3e\x5d\xb0\x9d\xa9\xd6\x7a\xfa\x9b\xa1\xc4\x5d\x82\xf7\x97\xb8\x0d\xfd\x65\x01\x67\x99\xb6\xad\x4d\x67\xae\x2d\x09\x56\xf4\x98\xdc\xc7\xf8\x5c\xd4\x49\xab\x88\xa3\x0b\xa0\x70\x27\x17\xee\x24\x3e\x17\x76\xba\x38\xa7\x03\x6a\x65\xef\x04\xe0\x39\xde\x40\xaa\xbd\x58\xf2\xcc\x90\x9d\x18\x58\x17\xe3\xeb\x24\x3c\xda\xd2\xfb\x59\x77\xef\x16\xad\xaa\xd3\x3e\x38\xb8\xeb\xae\x14\x3b\xdc\x32\xb4\x68\xc8\x77\x16\x97\xba\x6b\xd7\xe0\xa0\xbd\x53\xa5\x9d\xf9\x09\xf0\x6b\xb4\x44\xe5\x56\x95\x68\x7f\x9b\x61\xb7\xb4\x0e\x2d\x1a\x6a\xdd\xc2\x3e\x76\x8b\xb6\x44\xe5\x56\x11\xed\x1a\xe0\x35\x43\xbe\x95\x2b\x96\xae\x58\xdd\xb2\x86\x64\x8f\x78\xa5\x90\x2c\x2f\x1b\xd5\x7c\xd8\xbc\x28\xb8\x79\x6a\x88\x39\xb5\xaa\xae\xae\x7a\x90\x1d\x9a\xda\x1c\x5c\x64\x0e\xf3\xea\x99\x7b\x9f\xee\x50\x15\x6b\x03\x5a\xa2\x3a\xb0\x9a\xd0\xab\x55\xa7\x92\x0b\xf3\x2a\xa2\x0d\x68\x8b\x55\x1d\x4f\xab\x16\x57\x37\x39\x1c\xcd\x95\x5d\xc7\xfa\x3d\xb6\xa2\x21\xfa\x04\x0e\xca\x19\x30\x06\xb2\x10\xd3\x21\x49\x27\x59\x28\x11\x01\x5d\xe4\x14\xec\xeb\xc4\xe1\xda\x70\xc8\x61\x35\xbb\x3d\xee\x3a\x2f\xbd\x4b\xfa\xd4\xce\x73\xfc\x89\x11\x08\xc2\x21\x14\xee\xa4\x48\x94\x63\xd8\xe9\x60\x9f\xf5\xa8\x88\x66\xe1\x3d\xe7\x32\x9e\x86\x55\x4b\xeb\x00\xea\x96\xae\x6c\x74\xb3\x3b\xef\xf1\x68\x89\xaa\x4e\x55\xaa\xdd\xf2\x2a\xbb\xa2\x71\xa0\x08\xa0\x68\xa0\x71\x05\x0b\x38\xac\x2d\x79\x6e\xd3\xc0\x99\xe2\xeb\x64\xa8\x61\x90\x56\x0f\x36\x0c\x91\x37\x7e\xb4\x28\x68\xe0\xad\x7a\x56\x8e\x36\x40\x19\x5c\xff\x15\x78\x8e\xab\xf5\xae\x58\x46\xdb\x5c\xb6\xc2\x5b\xbb\xf0\xfd\xf7\x37\xd6\xe3\xb4\x5f\x5b\xac\xaa\x3e\x3f\x42\x2a\x2b\x7d\x4e\xa7\xaf\xaa\x82\xd9\x7c\xbe\x4b\xe2\x0d\xa3\x3e\xed\x0e\xa6\xb3\xa2\xba\xba\xa2\x93\x79\xae\x51\x45\x66\xdc\x64\xff\xda\xb6\xa5\xbf\xc1\xbd\xae\x9a\x1a\x57\x2f\xbe\xfb\xb6\x56\x9f\x8e\x3f\xb2\x55\x6f\xb5\x92\xfb\x8f\x48\xbb\x69\xc9\xfe\x36\x77\x16\x22\xac\xab\xa6\xb5\xa8\xa8\xb5\xc6\x55\xfb\xad\x87\xd7\x50\x75\x41\x5a\x64\xff\x02\xb1\x7f\x98\xb7\xbf\xa3\x04\xb9\x50\x35\x72\x23\x2f\xf2\xa1\x1d\x08\xd5\x39\x9b\x01\xea\x3c\x2c\x38\x89\x07\xea\x08\x0b\xce\x66\xb0\x39\x38\x23\x38\x1d\xc0\x92\x3a\x08\xf3\x4e\xa9\x3a\xec\xe1\x25\x3f\x8c\xb0\x11\x7b\x78\x9b\x11\xb8\x66\x70\x4a\x3b\x15\xdc\x41\x8f\x9b\xb8\xbb\xc0\xed\x99\x4d\xc3\x75\x3e\x27\xeb\xb0\x5b\xa5\x8d\xde\x76\x67\x38\x54\x01\xe1\x40\x17\x48\x47\x6d\xd0\x07\x59\x23\x70\xb0\xf4\xc5\xea\x37\xc1\x02\x16\xad\xf8\xaa\xf8\xe1\xaf\x5a\xfe\x0a\x8b\xa1\xc3\x20\xee\x87\xcb\x86\xf1\x28\xc6\xcc\xca\xf5\xfc\x4c\x17\xa0\x7e\xf1\x77\x4c\xdc\xf8\x1b\x3c\xf3\x1e\x14\xac\xe2\x19\xe4\x46\xdb\xfb\xf8\x0a\x0e\xf3\x80\x5d\x0f\xda\xac\x4b\x54\xcc\xef\x79\x7e\x84\x67\xc4\xb7\x19\xac\xfa\x80\x09\x63\xbe\x63\x0b\x9c\x8a\x55\x5b\xf6\xe0\xad\x58\x0d\x0f\xb0\x04\x3a\x38\x1b\xb7\xe3\x5c\x96\x9d\x62\xb9\x75\x84\xfd\x29\xc7\xfe\x95\xc1\x46\x1b\xf3\x34\x07\xaf\xff\xf1\x35\xd1\xff\xd6\x5f\xdf\x80\x0b\x5f\x83\x25\x3f\x99\x79\xff\x75\xe8\x7f\x41\xbc\x63\xe8\xa3\x55\x60\x54\x93\xc0\x20\x87\x6f\x7d\x01\x7e\x7e\xff\xe7\x0f\xfe\xfe\xce\xc3\x78\xfb\xb3\xf0\xe8\x1d\x47\x1e\xff\xdd\xbe\xc4\x30\xc3\x4e\x9e\xf5\xce\xf4\x07\x55\xad\x05\x96\x3c\xce\xb2\x6b\x6f\x67\xc9\xef\x31\x86\xbf\x30\x60\xe6\x99\xba\x0d\x1c\x0c\xf3\x6c\x53\x4c\x05\x2f\x6b\xc8\x5e\xb8\x81\x61\xc5\x56\x9e\x74\xac\xc7\xdc\x57\x96\x32\x4c\x5b\x8a\x23\xe7\x12\xb2\x97\xe1\xb2\x7b\x09\x8b\x6f\x60\xe7\xaf\xe1\xca\x91\x07\xad\x97\xde\x9a\x92\x1a\x03\x43\x1f\xfc\xaa\xe5\xb7\xa1\x55\xbe\x10\x39\xba\x58\xb1\x2b\x47\x24\x1c\x1b\x73\xeb\xe8\xe1\x09\xc7\x40\xcc\x03\xda\x8a\x96\x21\x3f\x17\x76\xf9\x9b\xbd\xcd\x7e\x57\x98\xf3\x0f\xb5\x54\x68\xd7\x75\xe0\xee\x8e\x75\xf7\xdf\xf0\xfa\x0d\x37\xbc\x7e\x03\x3e\xdb\x62\xd8\xba\xa5\xf7\xf3\x6e\x29\x62\xc6\xc1\xde\x2d\x72\x5c\xb0\xb9\x14\x1a\xda\x63\xc2\x92\x26\xa6\xca\x54\xa4\xd1\x14\x99\xaa\x98\xa6\x25\x42\xac\xfd\xb4\x48\x04\xdf\x94\xbc\xfe\xfa\xe4\xf8\xf5\xd7\x8b\xab\x0e\x1a\x2c\xef\x52\x74\x56\x0a\xbb\xf1\xae\xe4\xe9\x3d\xad\xa4\xca\xf7\x04\x69\x8c\x6a\xb4\x10\x9d\x81\x12\xd2\xfe\x39\xc5\x0b\x84\xf8\x5c\xcc\xec\x70\x02\x9d\xe4\x14\x70\xb1\xbe\x4e\xe6\x24\x63\x99\x3b\x1c\xe2\x84\x91\xdb\x4f\x88\xd1\xc6\xc8\x43\x6b\xf1\x9e\xd6\x5c\x69\xe2\x57\xf5\xce\x1c\xec\x5d\xa5\x2e\x6b\x5a\x1d\x64\x79\x9f\xbd\xa9\xbc\xde\x5d\x5f\xde\x64\xf7\xe1\x07\xad\xfa\xad\x52\x00\x65\x25\x3d\x86\x0b\x7a\xeb\x17\xc8\xaa\xff\x5c\x8a\x2a\xc2\x1c\xd4\x5b\xc9\xd9\xe3\xd7\x5f\x3f\x9e\xbc\xfe\x7a\xf1\x7b\xd5\x1d\xa7\x9d\xb1\xbc\xbe\x6f\x74\xb4\xaf\xe5\xcc\x6d\x2b\x02\x4c\x85\xd6\xa9\x56\xab\xd5\x4e\x6d\x05\x30\x7a\xeb\xb4\x14\x99\x59\x4e\xe7\x73\x85\x36\xc6\x4a\x47\xfb\x7c\x46\x1b\x55\xe2\xe4\xa8\xe4\x35\x49\x15\x6a\x45\x3d\x68\x35\x2a\x20\x84\x02\x5e\x3c\xa7\x01\x58\x1a\x11\x9e\x0d\x96\xad\x84\x4b\x99\x3d\x8f\xdb\xfc\x4f\xca\xf2\xf4\x10\x94\x0f\x0d\x90\xb6\xba\xcd\x42\xf3\xde\x1c\x21\x4b\xfd\x50\x3b\xd7\x52\xda\xd8\xd0\xd0\xd0\x58\xda\xc2\xb5\x0f\xd5\x5b\x96\x86\x30\x0a\xad\xdd\xf3\xc4\x9e\x3d\x4f\x30\xd5\xf3\x5d\xe9\xed\xc6\x99\x17\x8c\x76\xbb\x11\xb7\x19\xed\xc7\xb8\xd8\xa3\x2d\xbd\xe2\xfe\xf9\x07\x70\x88\x52\x68\x16\xee\x60\xef\x16\x58\x3f\x3d\x1e\x6d\x67\xca\x8c\x36\xb5\xda\x66\x2c\x63\xda\xa3\xe3\xd3\xeb\x71\x17\x6d\x7c\x8f\xf8\x9b\xb9\x03\x28\xc0\xd2\x46\x5b\xa6\x09\x68\x8f\xd6\xae\xa4\x32\x99\xaf\x93\xb2\x7c\xb6\xc8\xb1\x01\x4f\xe4\xdf\x1e\xe9\x49\x82\x2a\x49\xa0\x13\xfb\xa5\xa9\x2e\xec\x73\x01\x9e\xfd\x9e\x7c\xdc\x79\x1c\xc1\x7f\x52\xb6\x1e\xa3\x5b\x27\x39\x62\xe1\x24\x71\x6d\x18\xb4\x34\x24\xa2\xd0\xd2\x13\x19\x7b\xe9\xff\x80\xa5\xd3\x56\xfd\xa7\xdd\x72\xac\xef\xf9\xe7\x33\xc0\x56\x69\x66\xf9\xb4\x7b\x8e\xbd\xaf\x4d\xaf\x3f\x81\xc3\xf0\xb8\xc4\xde\x99\xad\x73\x8c\xfc\x70\x8e\xbb\x7f\x9d\xab\x3b\xe2\x63\x24\x85\xa4\x5a\x3e\x9f\xc5\x56\xe6\xa5\xa3\xbf\x84\x2d\xe8\xb8\xd8\x3e\x4e\xb4\x00\xa1\x3a\xe9\x10\xd2\x6a\x39\x48\xae\xb4\x46\x96\x0f\x95\x44\xa6\xd9\x93\x19\x67\x5d\x1c\x3f\x76\xec\x9e\xec\x7b\xf4\xa7\x8f\xf6\x4d\xee\x76\x6c\x83\xa5\x70\x2e\x2c\xbd\x58\xf1\x36\xc6\xef\xed\xfb\x48\x7c\xe8\x91\x87\x8f\x71\x18\xfc\xe1\x4d\x2f\x99\x96\xae\x5d\xbb\xd4\xf4\xd2\x4d\xd7\x7d\xfb\xdb\xf8\x3b\x72\x34\xf0\xf7\x20\x24\x5e\x23\x7e\xf7\xcf\xc7\x39\x16\x1e\xed\x97\x09\xd5\xa2\x46\x69\xaf\x86\xc3\x62\xb7\x1d\x75\xb3\x84\x50\x30\xa0\x1c\x1e\x68\xb7\x39\x2d\x7e\x47\x65\xd8\xe7\x56\x3a\x8b\x5f\x94\x5b\xba\xec\xb0\xf8\x90\x78\x95\xf8\xd0\x47\xfb\xf6\x1d\x66\x26\xae\x3d\xea\xd6\x78\x6d\xef\xe1\xdd\x90\xdc\x7d\xf8\x80\xd2\x61\x0e\xed\x3b\x2c\x3e\xf4\xf0\x77\xc5\x87\x0e\x5f\xbe\xef\xcf\xb0\x4c\x42\xff\x7c\xc9\x4b\x9f\xdd\x2c\xfb\x5a\x8a\x1f\xdc\xfc\xd9\x4b\xb0\x64\x7a\xfa\x76\xa5\xd7\xc7\xc6\x63\xa9\x90\x77\xdb\xc0\x31\x26\x2f\x3c\xeb\xc0\x60\xb7\x21\xa9\x57\x21\x93\xd5\x47\x3b\xed\xe1\x2a\x3d\x9c\xf4\x15\x91\x79\xa0\x79\xfd\xe6\xde\xc6\x17\x2e\x3b\xf2\xcd\xcb\x5e\x68\xec\xdd\xbc\xbe\x79\xd5\xea\x4b\x9e\x3c\xf4\xe4\x25\xab\xc5\xdb\x14\x5f\xec\x85\x1b\xcf\xb9\xe5\xea\x2b\xc5\x0b\xae\xbc\xfa\x96\x73\x36\xe2\xc3\x86\x96\x91\x3d\xaf\xec\xbe\xf1\xed\xb7\x6f\xdc\xfd\xca\x9e\x91\x16\xc3\x39\x57\x8f\x3d\x79\xc9\xea\xd5\x97\x3c\x39\x76\x35\xb6\x2a\x83\xf9\xec\xbd\xcb\xe3\x1f\x81\x8d\x3f\xef\x3c\x5e\xfc\xe3\x47\xf1\xcb\xe7\xce\x9b\x66\xe5\xf3\x16\x8a\x51\x0d\xea\x38\xe6\xd7\xe4\xf0\x1d\xf3\x53\x32\x57\x9d\x34\xb0\xd3\x5c\x34\xcd\x63\x7e\x0a\xab\xdb\x86\xde\x1c\x6a\x5b\x5d\x7f\xd1\xde\xa7\xf6\xee\x7d\x0a\x6e\x3f\x82\xac\x7a\x22\xaf\x92\x8e\x48\xba\x46\xd5\xfc\x20\xd5\xef\xde\x2d\xb0\x61\x7a\xc3\x86\xe9\x64\xac\x7d\xd9\xb2\xf6\x18\x3c\x2a\xa9\xf2\xe7\xfb\xd9\xad\x9f\xed\xd7\x5b\xad\xec\x4b\x9f\x75\xcf\x9a\x55\xc5\x22\x20\xa4\x9a\xb3\x05\x56\x54\x8a\x16\xa2\x53\xd0\x32\x74\x26\x12\xa8\x3d\x95\xbe\x43\x72\xd5\x1e\xf9\x73\x35\xed\xee\x97\x99\xd3\xe3\xcb\x75\x73\xf6\x52\x1e\xd1\x09\xe6\x75\x2e\x6a\x7c\xd5\xf1\xdf\x6e\xa7\x8d\xd5\xfd\xcd\xdd\xdf\xeb\x6e\xee\xaf\x36\x76\x35\xc2\x37\x1b\xbb\xa6\x25\x57\x18\x26\x63\x31\xcc\xc8\x81\x2e\x0f\x1a\x2c\xe2\xf4\xec\xe6\x48\x90\x0e\x5d\x51\xb6\x48\xc9\x5b\xa6\xe6\xee\xfa\x74\x9a\x47\x16\xc3\xa7\xdd\x06\x0b\x7f\xec\x0f\xbf\x3f\xb4\xf9\x74\x5f\x77\xb7\xef\xf4\xcd\xa1\xf0\x8a\x15\x70\x87\xe4\x6b\x23\xbe\x7b\xd4\x76\xce\x9d\xe7\x32\x2f\x99\x57\x09\x29\x89\x7f\xf3\x7f\xea\xff\x88\x8f\x73\x2a\xab\x28\x02\xfe\x32\x9b\x5a\x77\x5c\x99\x3d\xce\x03\xf6\x44\x1b\x7b\x72\x45\xa2\x7c\xec\x6a\x14\x37\x34\x76\xcd\xe3\xe6\xff\x9e\x8f\xd3\x9f\x22\xab\x9e\x3b\x78\xbc\xf9\xec\x0f\xaf\x58\x11\x9e\xe3\x24\xbc\x2e\x71\x71\xe6\xe8\xc1\x48\x7f\x39\x09\x13\x8f\xd6\x1d\xf9\x0e\xb3\xf5\x73\xaa\x96\xc7\x9a\x4c\x2c\x9d\x51\xf6\x3e\x87\x50\x89\x14\x9d\xd1\x84\x6b\xaa\xb1\xd9\x64\xf1\xfb\xc2\x5e\x46\x72\x72\x96\xde\x4c\x81\xdf\x61\x20\x35\xf4\x59\x86\x93\x4f\xb3\x0d\x58\x42\xb5\xf2\x96\x48\xcc\x4b\x1e\x36\xcc\x6f\x5f\x7e\xef\x9d\x43\x87\xde\x59\xda\xee\xa8\x0e\x05\x4f\xab\xf7\x56\xb5\x26\xee\xfb\xea\x3d\x7d\x7d\x70\x61\x81\x68\x16\x9e\x76\xd9\x59\x4b\x26\xcf\xea\xad\x8a\x24\xaf\x13\x7f\xf5\xcb\xbd\x7b\xdf\x81\xf2\x6b\xa7\xfe\xf0\xfc\x0d\x1b\x6e\xbf\xa4\x79\xf3\xa2\x8e\x5e\xfc\x27\xe8\x84\x76\xf1\x39\xf1\xfb\xe2\x0f\xc4\x1f\x99\x17\x2e\x1e\x5c\x58\x6e\x8a\x9c\x99\x14\xae\x15\xf7\x94\x0e\xa5\xce\xec\x71\x2f\x5d\x13\x2e\xcd\xff\x08\xea\x0f\x7c\x13\x16\xbe\x98\x3f\xf5\x6b\x4f\x7e\x7a\xf1\x53\xe2\x0f\xc7\x07\x4f\x5b\x36\x6b\x0f\x04\x35\x62\x6f\x42\x95\xc8\x8b\x6e\x40\x4f\x4b\x7b\x3c\x25\xb7\x29\x6c\x36\x59\xa5\xd7\x10\xca\x4b\x7a\x93\xe4\xf3\x5f\x37\xb7\xf3\x55\x92\x9f\xed\xa8\x9b\xc4\xec\xa9\x7a\x76\x9b\x7c\xfa\x5e\x30\x10\x9a\xef\x10\x61\x97\x3e\xfe\xcb\xde\x93\x76\x9b\xe4\xf4\xa3\xf8\x4c\x48\xaf\xd8\xfc\x3e\xa7\x8b\x71\xda\x5c\xac\xe4\x59\xe2\x96\xca\xc0\x9a\x8e\xfa\x0f\x84\x43\x66\x29\xbe\x90\x97\x95\xbf\xa9\x39\x2c\x4e\x07\xfc\xb0\xd2\x0e\xba\xae\xe8\x7b\xaf\x79\x32\x6e\x6b\x65\xd7\x48\xeb\xe4\x57\x7c\x1b\x70\xb1\xc1\xa6\x66\xbb\x6a\xca\x3f\x7f\xbe\xc4\x5d\x53\xce\xb4\x97\xb8\xdf\xe8\x2b\x3e\xc3\x63\xd2\xf2\x26\xb7\xd7\x5d\x53\x6e\x26\xc6\x85\xce\x5e\xa2\xd1\x2f\x72\xb0\x0c\xa9\x74\x87\x82\xee\x86\x72\x9f\x09\xc0\xc2\x95\x4e\x5e\xdf\xba\x64\xb0\xb5\xb8\xbc\xd4\x5a\xef\x5b\x5c\xbf\xd8\x53\x66\x52\x71\x44\xa5\xd1\x99\x35\xce\xb2\x05\x9a\xd2\xde\x53\x3b\xf0\x2b\x97\x58\x17\xad\x5c\x57\x69\x72\x2d\x5a\xa5\x7e\xa4\x3e\xb0\x28\x81\x1d\x5a\xab\x56\x55\x69\x1d\x3c\x77\x64\xab\x0e\x0b\xf6\x2a\x62\x3c\x07\xca\xe0\x22\x58\x0f\x66\x7f\xa2\xd4\x5a\xda\x15\x5f\xf3\xfc\x67\xe2\x6f\x5f\x5e\xbf\x91\x94\x98\x8a\x1d\x67\x97\x7b\xdc\x25\xe5\x1e\x37\x3e\xed\xc2\xa8\x7b\xb5\x4d\xa3\xe3\xd4\x0d\xbe\xf5\xde\xe5\xa1\x06\x56\xd7\xac\x77\x94\x2c\x37\x2e\x32\x16\xdb\x8b\xdb\x81\x61\x70\x8b\xab\xae\xd3\xeb\xed\xac\x1b\xe9\x5c\x68\x63\x59\x4c\x4c\xda\x85\xcf\xec\x0a\x4f\x4d\x24\x27\x03\xc1\xfa\x16\x93\x5a\x67\x2b\xb7\xfa\xfd\x4b\xbb\x5b\xa0\xca\x5c\x65\x77\x68\xcb\x9c\xc5\xeb\x6c\x83\xcb\xf7\xef\x15\x3f\xfc\x75\xe5\xd0\xe6\x8e\x0a\x93\x71\xc9\x5a\xed\x6f\xa0\x69\xf7\xa1\xf1\xc9\x09\x62\xd7\x39\xcd\x36\xb5\xb5\xea\xc0\x6e\xf1\x83\x6f\x35\xcc\x7f\xdf\x50\x24\xcd\xfa\xd6\x90\x9b\x07\x03\x38\x2a\x00\x42\x4e\x07\x0f\xed\xc0\xfb\xba\xc0\xe9\x38\x61\x13\xf6\x5d\x57\xab\x3d\x95\x47\xf6\x97\xdb\x4d\x45\xbf\xc4\x60\xd7\xf2\x5a\x31\x62\x72\x3a\x92\xef\x76\xe3\xe4\x49\xf6\x23\xfc\x1a\x7f\xb7\xd1\xad\x13\x1f\xd4\x96\x15\xf3\x03\xd0\x67\x50\xb1\x1a\xf1\xe2\x0f\x1c\x63\x77\xd5\xe2\x9b\x4e\xb6\xa1\x80\x9b\x3b\xdb\x49\x2f\x7d\x49\xf6\x4b\x71\x50\x91\xe2\xfb\x17\x0a\x9b\xfd\x66\x17\x38\x03\x6e\x8f\xb2\x71\x50\x52\xb1\xca\x50\xd8\x26\x9d\x13\x1e\x96\x36\x42\xda\xcd\x0e\xab\xb2\xf3\x86\xfe\x61\x6a\x59\x06\x17\x4d\x2f\x1a\x9c\xee\x5f\x9c\xd9\x9f\x59\xdc\xff\x38\x68\x1e\x9f\x96\x9d\xfc\xa6\x25\x78\xfa\xa0\xf4\x6f\x28\x93\x19\x5a\x1c\xb3\x93\x4b\x8f\x14\xec\xb1\xc5\x2b\x2e\x6c\x22\x88\x56\xcd\xa0\xa6\x0b\x57\xec\x79\xfc\xf1\x3d\x8f\x8a\x9f\x02\xff\xe8\xc3\xbb\xf1\xf3\xb4\x34\xd3\xbe\x1b\x2e\x91\x37\xd7\x48\x1b\x6c\xfe\x7f\xd1\x77\x7c\xe9\xcc\xff\xb3\x7d\x87\x4b\xc5\xff\x2b\x7d\x0f\xfa\xed\xff\xd7\xfb\x7e\xe9\xa5\xff\x9b\x9e\xcf\xef\xbb\x5a\x9a\x97\xe5\xde\xcf\xf5\xdd\xe7\xf8\x5f\xf4\x3b\xb3\x3f\xf3\xaf\xf4\x7a\xd5\xf6\xed\xab\xfe\xc7\x3d\x36\xcd\xc5\x60\x72\x23\xaf\x74\x5a\xfd\x20\x5a\x89\x36\xa0\x2d\x28\x8e\x52\x68\x07\x3a\x17\x5d\x88\xf6\xa1\xeb\xd0\xad\xf2\x89\x17\x30\x7b\x56\xa0\x17\xc2\x72\x6c\xb9\x2a\xb3\x72\x90\x4a\xc8\xe1\x0c\x87\x7c\x4e\xac\x1c\x49\xcd\x28\xfb\x80\x42\xb3\xe5\xd9\x3c\x20\xd7\xd4\x1e\x5f\x7f\xfc\xfd\x5f\x82\x3f\x8b\xc7\x1d\x97\xb3\x37\x68\x34\x33\xfb\x34\x25\x9a\x35\x1a\x4d\xe3\xa9\xd6\xb6\xa5\xf1\x6d\xd7\x7d\x81\xe8\x42\x7a\xdb\x53\x4b\xb6\xfc\x74\x4d\xa3\xa6\x44\x53\x25\x3b\xea\x6e\x92\x32\xd9\x91\x77\xe6\x6e\xc5\x79\x57\xf6\x08\x46\xc7\x54\xce\xbf\x51\x7c\x6b\x7e\x41\xb9\x41\xde\x81\xbc\x69\x5e\xca\xf2\x9a\x12\xda\x0f\xcd\x1a\x4d\x89\xa6\xf1\xcc\xff\x8a\x2e\xb9\x6e\xdb\xe7\x88\x45\x74\x55\xbf\x66\xa9\xa7\xbc\xa7\x51\xa3\x11\xef\x91\xf0\x36\x9d\x90\x06\xa4\x26\xa6\xbf\xe4\xea\x5b\x27\xd4\xb8\x4f\xa8\x41\xe6\x79\x67\xf5\xd5\xa1\x26\x29\x62\xea\x00\x5a\x81\xce\x41\x7b\xd0\x65\xe8\x5a\x74\x0b\xba\x0b\xdd\x8f\xbe\x8b\x9e\x44\x3f\x94\x76\x3c\x1d\x0d\xb6\x2f\x6d\x54\x9f\x2b\xb9\x3b\x00\x1d\xe7\xed\xed\x56\x72\xc7\x71\x65\xf7\x49\x56\x97\xa7\x80\x12\x0f\xcf\x21\xbd\x56\x74\xf0\xc0\x35\x83\x7b\xbe\xda\xf8\x1c\xe8\x4b\xda\xf9\xb2\xf6\x8f\xaf\x9f\x2d\x73\xd3\xf2\xe1\x88\x5d\x3d\x33\xa8\xa7\xcb\xaa\xef\xd6\x5b\xa7\x71\xb7\xa5\xcc\x62\x29\x5b\x23\xa5\x5e\x29\xbd\x6a\x1e\x2c\xa7\xcc\x1a\x79\xb5\x6e\x31\x6c\xbd\x6e\x5b\x72\xb9\x77\xac\xde\xa1\xd5\x36\x68\xb5\xe2\x73\x52\xe6\xa8\x55\x97\xd5\xf9\x83\xcb\xd8\x77\x0d\x96\x23\xd3\x27\x60\xbf\xfc\x0f\x6b\x64\x6a\x70\xf0\xe0\x81\xc2\xb3\x94\xc2\x0e\x87\x23\x65\x76\x3a\xcd\x8f\x15\x0e\x1c\x84\x7f\xa3\xd7\x2c\xde\x79\xa9\xe5\x84\x9a\x99\xb9\xc7\x03\x3c\xbd\xed\xba\x95\x56\x43\xe5\xb1\x9d\xf3\xe6\x7d\x35\xcb\x82\x33\xd3\x16\x38\x78\x02\xee\x9a\x7f\x58\x23\xff\x2f\xad\x19\x81\x3e\xef\xb2\x22\xd2\xa3\x6e\x74\x2a\xda\x2e\xfb\x78\xf1\x5c\xa5\xbc\x94\xab\x04\x1b\xe2\x39\xe9\xac\x64\xfa\x9f\x25\x18\xc0\xb5\xbc\x81\x48\x2b\x36\xba\x86\x04\xa7\x83\xf3\x78\x01\x87\x43\x96\x50\x6d\x38\xc4\x38\x2c\x73\xdb\x2a\x6c\xf2\x59\x79\x1e\xb7\xb4\x61\xce\x2b\x3b\xe1\x4a\xfb\xc1\x78\x03\x48\xfe\xe0\x38\x1c\x72\x01\x79\xdf\x5c\x51\xe4\x10\x8f\x38\x8a\x2a\xcc\x70\x10\xbb\xc4\x4f\xde\x54\x19\x80\x27\x0c\x06\xd5\x6d\xcf\x3c\x2c\xbe\xf0\xdd\xb3\xdf\xbf\x7d\x18\xe0\x07\xb7\xf1\x98\x10\x50\x61\x30\xaa\xae\x79\x7f\x4a\xc5\xef\x78\x1a\xc8\xe5\x77\x42\xf3\xdb\xbb\x67\xde\xdf\xfd\xd8\xee\xdd\x8f\xc1\x1d\xe3\x9b\x55\x26\xcc\x39\x79\xcd\xa2\xde\xc2\x73\xdb\xf7\x1c\xd4\x6b\xfa\x7a\x34\x7c\x11\x8b\x4d\xaa\xe1\x71\x4c\xbe\xfa\xce\x05\x57\xfc\xfd\x4a\xd8\xb8\x21\xfd\xc6\xc8\xa6\x4d\x23\x6f\xa4\x4e\xbf\x17\xd0\x61\xf1\xec\x0d\x44\xa7\x6e\xb1\x54\x1a\xd5\x64\x35\xf8\xbe\xf7\x10\x34\xdd\xab\xe1\x93\xf7\xff\xf6\x9c\xef\x89\x3f\x5b\x45\xd4\xf6\x22\x75\xb3\x4e\xad\x63\x16\xfd\x27\xb4\xde\x73\x39\xb0\xcf\xec\x52\x6b\xb6\x1f\x12\xdf\xae\xa3\x34\x77\x7f\x81\x76\xbd\xb6\x84\x53\x69\x02\x0b\x34\x9a\xd0\x55\x6b\xd2\x8f\x45\x74\xc6\x1f\xec\x39\xeb\xde\xc5\x1a\x4d\x7d\x40\xad\xe2\x96\xbe\x75\xce\xee\xf7\x2f\xe6\xf8\x0b\xff\xac\x9c\x4d\x2e\xef\x2b\xb6\x22\x54\x27\x45\x73\x3f\x2e\xca\x32\x62\xd1\xe7\x88\x53\x3e\xf7\xc8\xcf\xcd\xd3\x04\xc1\xd6\xf9\xcf\x2b\x20\xb7\x03\xd3\xc8\x88\xd0\xf1\xcf\x6f\xfc\x31\xb8\xef\x4a\xaf\x33\x95\x17\x43\x64\xee\x7c\x07\x82\x74\xc8\x8d\x50\x3d\x98\xeb\xb1\xb9\xca\x2c\xbf\x97\x55\xa2\x70\x1d\xed\xce\x5c\x9f\x08\x9a\x41\x0c\xc2\x68\x06\x6d\xed\xdd\x42\xd0\x96\xde\x99\xfd\xb3\x2f\x02\xf0\x56\xf9\x90\x73\x8c\x08\xfa\x02\x6d\xe9\xc5\x88\xd6\x8b\x73\x01\xff\x61\xab\x4c\xfb\xe8\xd8\x6b\x90\x1f\xa1\xba\x70\x28\xd0\x0c\x52\xe2\xae\x36\x82\xc7\x2d\x7d\x8b\xac\x80\xb9\x28\x28\x4e\x87\xef\x78\xde\x30\x5f\xbf\x4a\xa3\xf9\xdd\xef\x34\x9a\xab\x34\x25\x34\x2f\xd1\x1c\x57\xc6\xb9\xf9\x43\x7f\xe3\xcb\x6e\x53\xca\x8c\x75\x3e\x4f\xc9\xbc\xfe\xc9\xef\x7d\xfe\xe5\x73\x71\x8f\xeb\xe5\xef\x28\x9d\x03\x07\x64\x3a\x07\x0e\xc8\x74\xe7\x95\x8f\xe8\x4f\x14\x31\x1c\x38\xf9\xbd\x73\x65\xf1\x25\x06\x6d\x3d\xf6\x99\x75\xd6\xc6\x4b\xba\xa4\x86\x2a\x38\x61\x59\xef\x05\xdf\x4c\x56\xfc\x29\xbb\xf5\x24\x6b\x78\x88\xe3\xc0\xcc\x4f\xe0\xd0\xc9\xd6\xeb\xbc\xd4\x36\x96\x7c\x3f\xac\xa8\x06\x79\x51\x1f\xfa\x01\x7a\x15\x21\x70\x1b\xc0\xe9\xe8\x04\x96\x93\xb7\xc6\xf9\x9c\x0e\x9b\x73\x8e\x45\x32\x63\x3c\xb3\xd7\x1c\xb6\x3a\xe9\x67\x2e\x45\xed\xe1\x0d\x60\x0d\x49\x9f\x00\xf9\x4e\xa8\x80\x90\xa7\x13\xa4\x38\x22\x21\xb7\xc7\x4d\xcd\x81\x0b\x9c\x5e\xf0\xb8\xc3\x6e\x4f\xb5\xe4\x5d\x45\x9f\x35\x39\x3e\x14\xe6\x5c\xe0\xa4\xd7\x8d\x40\x29\x3b\x39\x9e\xb3\x39\xc2\x9d\x10\xf6\x62\xbe\x93\xf1\x3b\x24\x3f\x19\x87\x7c\x9d\x75\x38\xdd\x1e\x03\xe3\x70\x3a\x42\x16\xc9\xc7\xd4\xe9\x08\x9f\x10\x7b\x84\xd5\x1a\x17\xe8\xb4\x86\x80\x49\xdc\xa4\x72\xf2\x2a\x15\xef\x54\xf1\xb7\xd6\xe8\x6a\xf4\x6e\x9d\x4e\xce\xa6\x68\x15\xaf\x72\x98\xe0\xd2\xea\xab\x43\x6e\x2f\xb3\x74\x45\xb7\x1b\x3b\x78\x2b\x67\x20\x2c\xe1\xbf\x4f\x9c\x95\xd5\xdc\x82\x8d\x03\xd6\x06\x9d\x0e\xd7\x72\x40\xc8\xc2\x36\x4e\xb3\x6d\xdd\xe2\x64\x99\x8b\xaf\xf5\x57\x34\x6d\x30\x94\x2d\x36\xe9\x7d\x1e\xab\x57\xaf\xd7\x6b\x9a\x5a\xf5\x18\xf3\x50\xe7\x2a\x76\xd4\x08\xd5\x55\x9b\x1e\x36\x81\xc6\x68\xb4\x2f\x6c\xa8\x3f\xd5\x8a\xd5\x95\x66\x67\x5b\x51\x85\x5d\x6f\x50\xf1\x0b\xb6\xb1\x50\xa6\xd7\x33\x2e\x47\x85\xd5\x88\xd5\x35\xd8\x51\xdc\x60\x35\xe8\xad\x4d\xcf\x3d\x52\xb1\x61\x47\x69\xf3\xf8\x58\x97\xe7\x6f\xfb\x0e\x8b\x0f\x8a\xd7\x88\x0f\x4a\x12\x5b\x01\x49\x58\x71\x98\xa9\x35\x9b\x17\x58\xcc\x6c\xed\xab\x2a\x95\xca\x41\x87\xe4\x58\x53\xa3\xd7\xbb\xf5\xd5\xfa\x1a\x9d\xce\xa3\xab\xd9\x41\xeb\x55\x2a\x93\x63\x53\xf7\x42\x77\xd9\x8a\x91\x0d\x36\x57\x2d\xb6\x73\x76\x8d\xdd\xe8\xb0\x15\x89\x16\x5b\xb9\xc1\xa6\x59\x12\x36\xe9\xb5\x00\x4d\x4d\xb6\x7a\x8d\xa6\x68\x8d\x6f\xdd\x1e\x0d\xef\x6f\xf5\xc7\x96\x86\x8c\x4c\x77\x5b\x32\x6b\xd7\x5a\x8b\x4a\x00\x7c\x65\x76\xa3\xa3\x9c\x21\x65\xc3\x97\x06\x0d\x0e\xd3\x44\xb3\xb7\xfa\x91\x25\x26\xad\xce\x52\xbc\xc8\x61\xb6\x76\xb8\x30\xa7\x06\xd6\xc8\xf2\xc0\xd7\xd7\x05\xe3\x2d\xa3\xf9\xf2\x06\x8e\xe3\x7d\xf5\x5d\xa7\xf4\xf5\xba\x42\x25\x45\xae\x90\xbb\xb1\x52\x5b\xfc\x1d\x50\x6f\x0d\x9c\xd7\xb6\x79\xfd\x5a\x82\x61\xea\xa4\x7b\xd0\x61\xee\x3d\xec\x12\x84\xc0\xec\x90\xf6\x97\x77\x81\x9f\x58\x6b\x24\x8f\x44\xe5\x25\x54\x27\xd3\x05\x7e\x0e\xf3\x5e\xf0\xd4\x54\xb1\x41\x2a\x77\xab\xc5\xe3\x85\x66\x08\xb2\x55\xbe\x30\x55\x0c\x7a\x7f\x4d\x55\x35\x87\xb9\xd1\x07\xea\xea\xfa\x9b\xcc\x55\xa3\x06\x7e\xb4\xdc\xb8\x38\x74\xba\xf8\xdf\xa7\x6f\x02\xa1\xa6\xb5\xa3\xd9\xd7\x60\xd9\x7c\x06\xe7\x67\xaf\xfa\x43\x53\xe3\xcc\xd7\xc4\x8b\xce\xeb\x6b\x05\x15\xd1\xe2\xe6\xfe\xf3\x60\x27\x7e\xea\xd2\x3f\x70\x26\x86\xdd\x5c\x59\xb1\x61\x70\xe6\x17\x65\x46\xf6\xb4\x99\xed\xc0\x12\x82\x9b\x4e\xdd\x27\x3e\x25\x3e\x73\x5e\xbf\x0f\x54\x33\xaf\xae\x5c\xc6\x68\x8b\x3d\x9d\x0d\x6f\xd6\x89\x6b\x3a\x58\x0e\x74\xf1\x62\x7d\x4b\x18\xef\x86\xab\x3e\xee\xf0\xea\x8b\xe2\xba\xd2\xfe\x99\xcd\x67\x9d\x3d\x55\x30\x2b\xdf\x43\x24\x1f\x17\x33\x6a\x44\x2d\xa8\x13\xad\x55\xde\xdc\xd9\x6d\x0e\x03\x53\x63\xf6\xb9\x48\x19\xb0\xb4\x80\x25\x87\xeb\xc5\x84\x2e\xb1\xa5\x4a\xbf\xb9\x06\xfc\xe6\x1a\xde\xed\xa9\x31\xfb\xcd\x56\xbf\x95\x0d\x78\xbc\x6c\x75\x4d\xf5\x42\x30\xfb\xfc\x8e\x90\xc7\xcd\x06\xe5\xfd\x1c\xc1\x1a\xb3\x3f\x7c\xd2\xfd\x2a\x37\x02\x60\x56\x65\x50\xab\x0d\x2a\x16\xc3\x62\x00\x46\xab\x52\xb3\x0c\x61\x38\x96\x53\xb1\x04\x3e\x7f\x67\xd7\x2e\xf8\xce\xb6\xdb\xca\x6c\xba\x5b\xc7\x9b\x96\x2f\x84\x03\x2c\x31\x59\x2a\xed\xf5\x66\xbb\x8a\x39\xd3\x56\x7b\xa0\x8d\x00\x74\x30\xc6\xea\x72\x6f\x45\x21\xc5\xbb\x9a\x7d\x95\x0f\xcd\xff\x24\x87\x7f\xf5\x30\xe3\x50\x99\x78\x15\x81\x20\x56\x11\x13\xeb\x88\x4e\x81\x53\x65\xe4\xd4\x9a\x9b\xb0\x86\xd7\x72\x2a\x42\x38\x4e\xcb\x1a\x3e\x84\x37\xc5\x05\xf0\xe6\x2f\xaf\x39\x4d\x5c\x00\x6d\xe2\x0b\xd0\x65\xe8\x73\x9a\x8a\x4d\x3a\x96\x88\x0b\xc0\x7f\x53\xe7\x6d\x7b\xca\x2b\x6b\x8c\xd5\x37\x8a\x0b\x5c\xb5\x1d\xc4\x72\xdc\xb7\x0e\x16\xb5\x7c\x81\x55\xcb\xd8\xbf\x23\x1d\xb2\xa3\x12\xb4\x16\x5d\x8e\x10\xeb\xf6\x48\xa7\x96\x39\x10\x35\x2b\xcd\xc0\xf1\x0e\x2b\xb5\x26\x10\xc0\xd2\x49\x8f\x3c\xc7\x77\x92\x0a\x70\x11\xde\x6d\xc0\xbc\x0b\x3b\x1d\x9d\xb8\x4b\x8e\x44\xc0\x73\x2c\xe7\x71\x11\x29\x04\xa1\xc5\xca\xf1\x1c\x96\x36\xba\x73\x35\x95\x88\x54\xbb\x6b\x38\x17\xae\x00\x87\xd3\x4b\x9a\xc1\xcb\x79\x5c\xd8\xa9\x2c\x8c\xa8\x29\xab\x65\x9c\x0e\x0b\x33\xc9\xb1\x7a\xef\xb9\xe3\x85\x0a\xf3\xad\xbd\xb0\x46\xdc\x7c\x6f\x71\x25\x61\xd6\xd5\xb1\xbb\x16\x56\x37\xba\xd8\xfd\x67\xbf\x22\xbe\x73\xdb\xd5\xe2\x27\xdb\x5c\xc6\xc5\x77\x7f\x7d\x6f\xfd\x82\xaa\x05\x6a\x86\x9c\xfb\xe3\x3b\x76\x0d\x32\xc6\xb6\xea\xaf\x7c\xfa\xd0\x95\x75\x75\x8e\x9a\x12\xc6\x10\x3c\x24\xce\xec\x7d\xb8\xfe\x92\x8b\xce\xf1\x78\x2e\xdf\xf9\xfd\x0f\x97\x1a\x4a\x06\xff\xf3\x67\x2d\xd5\xa7\x9e\x59\x5b\x27\xfe\x5a\x1c\x58\x0a\x1c\xe6\xcc\x35\x75\x7a\x83\xca\xbb\x64\xdc\x57\x4e\x30\xdb\xbe\xa0\xb7\xd5\x5f\xad\xb2\x76\xdd\xd1\x8d\xb5\x6b\xeb\xf7\x96\x05\x8d\xd5\x95\xb7\x42\x0d\xb4\x5f\xf7\x8b\xf7\x7f\x08\x44\xe5\x8a\x4d\xdc\x77\x3a\xa9\x7e\x4d\x7c\x1d\x9f\x52\xb6\xfc\x91\x50\x70\xcd\xbe\x1e\xdc\xd2\xbd\xce\xeb\x10\x6f\xbd\x1d\x6a\x5f\x3d\x27\xb1\x75\x51\xdc\xdf\x63\xe7\x18\x02\xe5\x75\x75\x1a\xad\xbd\x77\xc5\xe2\xda\xed\x1f\x2f\xe2\xea\x7b\xfb\x8b\x8b\x4c\x6a\x6b\x71\xa4\x28\x52\x67\x63\xb6\xde\xbe\xb9\x47\xab\x73\xba\xa3\x70\x36\xa8\xf7\xae\x38\x24\xfe\x21\x57\xa5\x2d\xd1\x10\xd8\x04\x7a\xf0\x9d\x93\x38\xb3\xa4\x44\x37\xe8\xbe\xf8\xf2\xdd\x0d\x0d\xd8\x6e\x2c\x29\x2a\x2d\xd5\x69\x2a\x16\xab\x2a\xaf\xbd\xec\xc5\x3b\x72\xd1\xb2\x6a\xe3\xd2\xc5\xee\x95\x39\x71\x10\xb1\xa8\xee\x0b\x1d\xf7\x26\xfb\x09\x72\xa2\x16\xd4\x8d\x4e\x97\x4e\x9c\x0a\xb9\x3d\x4a\x68\x34\x17\x76\xba\xf8\x10\x18\x30\x53\x4b\x57\x99\x9d\x24\xcc\x95\x80\x0e\x6a\xc3\x21\xde\x86\x6d\xd2\x19\x42\xd2\x07\x19\x60\xbd\xd0\x08\x3a\xe0\xb0\xd3\x8d\x3b\x19\x29\xbe\x3c\x09\x21\x4f\xb5\xc7\x1d\x76\x31\x06\xc2\x77\x12\xb6\xa3\x7c\xc9\x86\x45\x7b\x05\x8b\xce\x58\xe3\xac\x58\x54\x5a\xdb\xb5\xb0\xae\xc8\xa6\xd7\x6a\x60\x7b\xe0\x99\x3f\x8a\x7f\x11\x3f\x3b\xfc\xd0\x28\x0b\x46\x8d\x9b\xf1\x8f\xfd\x05\xd6\xc1\x56\xd8\x94\xb7\xe1\x8f\x57\x5f\xf4\xc4\xa1\x27\x2e\x5a\x2d\x67\x90\xe9\xf9\xad\xf8\x27\xf1\xc7\xe2\xdb\xa2\xf8\xf0\x90\xab\x95\x5d\xbe\xef\xc9\xf7\x3e\xfa\xdb\xfb\x3f\x5d\x56\xb5\x68\xb1\x4e\x7c\xe3\xef\x2a\x8c\x4b\xce\x79\xf9\xa2\xad\x76\x67\xec\xca\xf7\x2e\x4a\x3e\x7e\xfb\x08\x3e\xdc\x78\x5f\xbb\xa7\xdc\x56\xea\xd4\xb0\x84\x31\x6a\xf4\x75\x75\x0b\x6a\xab\x8a\xf4\x30\xf3\xe3\xf3\x1e\x8b\x14\xf9\x77\x1f\x04\xe7\x9d\xf5\xa7\xd7\xef\xd4\x1f\x12\x2f\x14\xc5\x1b\x75\xb7\xdf\x59\xaa\x67\x70\xc5\xa1\xa7\x2e\x59\xbd\xfa\x92\xa7\xe4\x8c\xbb\xfa\x50\x54\xb5\xfa\x81\xbf\x89\x77\x3e\x7f\x3b\x34\x7d\xf2\xf2\xd7\x85\x7a\xe7\xfa\x3b\x73\xbe\x7d\xe2\xf9\x9f\xc0\xc6\x7e\x96\x25\xcc\x59\xd7\x3c\xf9\xf3\x9f\x3d\x71\xd5\x19\xd8\x15\xbb\xea\x67\xb2\x3f\x89\x64\x63\xa4\xef\x80\x15\xa8\x19\x75\x49\x3e\xdd\x69\x74\x1e\xba\x1c\xdd\x86\xbe\x8d\x90\xd5\x5e\x53\xdd\x01\xf4\x2f\x70\x0a\x04\x03\xfe\xff\xd3\xf2\xf1\x6b\x21\xb0\xdb\x16\x4a\x7f\x41\xbf\xaf\x1c\xfc\xbe\xe0\xff\x61\xf9\x60\xc6\xd4\x62\x32\xb5\x98\x32\xff\x24\x67\xfe\xbd\x6d\xc1\x91\x83\x0b\xda\xda\x16\x90\xee\x05\x6d\x80\xfe\x05\x14\x29\x07\x34\x6d\x32\x99\x2a\x4d\xa6\x7f\x19\xda\xff\x59\x37\x25\xc3\x52\x62\x9f\xab\x68\xcd\xb4\xc9\x74\xf8\x9f\xe4\xb2\x0f\x61\xf3\x17\x88\x5b\xcd\x21\x74\x05\x5d\x6b\xca\xfb\x70\x9b\xe9\xd3\x94\xdb\x43\xea\xcc\x4e\x17\x18\xc0\xdd\x0c\xd2\xbe\x93\x0e\x7a\x4d\x3a\x62\xc5\xcc\x12\x03\x7d\x84\x9e\x75\xf5\x93\xe2\xa7\x38\xd9\x26\x60\xa5\x5d\x07\xb3\x35\x15\xe0\x71\x87\x1c\x4e\x2b\x6b\x96\x03\xac\x28\xa1\x8b\xcb\x21\xdc\x09\x2e\xe0\x8c\x60\xae\xb3\x76\x82\xc3\x08\xf2\xee\x5e\x23\x48\xe4\x6a\xaa\x3d\x75\x7a\xa8\x0b\xb9\x80\xe3\x5c\xf7\x3c\xe6\xd4\xeb\x0d\x3e\xe7\x63\x61\xbd\x6f\x89\x3e\x2e\xfe\xf9\x90\x09\x17\x55\xd5\x9b\x32\xee\x80\x3b\x63\xaa\xaf\x2a\xc2\xa6\x43\xe2\x9f\xe3\xfa\x25\x3e\x7d\xf8\x31\xa7\xcf\xa0\xd7\x3b\x1f\xbb\xa7\xbc\x44\xdd\x50\x0e\x21\x29\x30\xe4\x8b\x8c\xba\xb4\x9a\x29\x29\xa5\x0d\x95\x04\x1c\x4a\x3b\x60\x3c\x49\x3b\x60\x3c\xae\x9d\xd2\x12\xa6\xba\x54\xcd\x88\x2f\x4a\x31\x2d\x43\xe5\x0d\xea\x12\xb8\xa3\x6a\x5c\xef\x77\x3a\xf5\xfa\x6d\xfb\xdd\x7e\x4d\x1d\x34\xde\x2c\x3e\xff\xa1\xa5\xa1\xc2\xaa\xb2\x4c\xbf\x5e\xe2\x76\x97\xbc\x3e\x6d\x51\x59\x2b\x1a\x2c\x1f\x42\xfb\xcd\xe2\xab\x75\x1a\xbf\x7b\xff\x36\xbd\xde\xe9\xf4\xeb\xc7\xab\x38\x6f\x73\x15\xd7\x79\xcb\x2d\x9d\x50\xdb\xd8\xc0\xd2\x96\xbc\x06\x83\xdc\x90\xf8\xea\xcd\xd0\x7e\xf2\x86\xc4\xe7\x6f\x86\xc6\x63\x1b\x62\x1b\x1a\x6b\x81\x36\xc4\x55\x35\x7b\xd1\x31\x3e\x7e\x16\xfa\x44\x05\x74\x91\x4b\x27\x15\x8e\xce\x2a\xb5\x16\x35\x38\x2c\x3c\x87\x19\x9e\x05\x37\x7d\x46\xae\x0d\x87\x6a\xd9\x67\xf8\xa1\xab\x0e\x15\xf2\x6f\xdf\x95\xe0\xf9\xa1\xab\x7e\x5e\xb8\x09\x6c\xdf\x82\x25\xe2\x1d\x3b\xa7\x34\xda\x87\xc5\x57\x1f\x3e\x52\x0c\x67\x4a\x30\x34\x3d\x7c\x0f\xbe\x11\x0f\xef\xf8\x8f\xdb\x05\x9e\x5f\x79\xf9\xcf\x0a\x12\xa4\xbe\x08\x7d\xc1\x74\x88\x77\x16\xc4\x17\xef\x7e\x44\x7c\xe1\xf9\xe2\xaf\xc2\x99\x79\x08\xdf\xfd\x3d\x68\x7b\xbe\xd8\xb1\x51\x7e\xff\xa8\xc4\xff\x33\x20\x0b\x72\x20\xb7\xe4\x71\x6e\xad\xd1\x42\x8d\xd5\x13\x76\xf2\xc0\x92\x26\x70\xf2\x9e\x3a\x27\xef\x61\xfe\x59\xb8\xbe\x87\xee\xf0\x7f\xfb\xbe\xd6\x07\x57\xda\x0f\xdb\xc5\x01\x68\xb9\x40\x3c\x04\x6f\x1d\x1e\xfd\x08\xce\x7b\x7a\xcd\x53\xb8\x83\x4e\x68\xe2\xb3\xe2\x3b\xaf\x9c\x7d\xf6\x2b\x50\x0d\x9d\x50\xfd\xca\x1f\x4f\xf6\xbc\x71\x44\x7c\x04\xb6\x88\xdf\x80\x1d\x55\xad\x71\x1f\x4e\x5c\x20\x1e\xba\x60\x72\xf4\xa3\xf8\xa6\xd5\x4f\xad\xde\x22\x61\x9d\x3d\xbf\x25\x3c\x79\x92\x55\xa1\x0e\xb9\xbf\x00\x7e\x13\xfb\x05\xda\x88\x46\x50\x12\x4d\xa2\xf3\xd1\x7d\xe8\x11\xf4\x2c\x7a\x09\xbd\x89\x3e\x40\x1f\x22\x04\x5e\xe2\x71\x77\x82\x47\x0e\x29\x4c\xaa\xbd\xe0\xf1\x72\xd2\x23\x06\x91\xcf\xbb\xe2\x0d\xc4\xce\x49\x8f\x10\xd2\x53\x82\xd3\x21\xbf\x95\x08\x49\x2f\x23\x9c\x3e\x69\xbe\xa7\xb3\x4e\x88\x71\xc8\xaf\x2f\x3a\x01\x1c\x06\x90\x00\x07\x52\xde\x5b\x80\xd3\x41\x2b\xbd\x10\x0a\x87\x1c\x56\x07\xe6\x39\x0f\xbd\x45\x79\xdf\xe1\xc5\xa1\x30\xfd\xd9\x49\xf1\x4a\x43\x2e\xc2\xbb\x30\x07\x4a\x6b\x32\x82\xd4\x9e\x14\xd6\x88\x56\xcb\xcd\xc0\x1c\x3d\xc7\xfc\x9b\x3d\xf2\x1d\x9d\xe0\x60\x43\x4c\x73\xa0\x89\xb0\xcb\x97\xb2\x86\xd1\x26\x17\x61\x30\x4f\x78\x96\x27\x44\xc7\x69\x55\x5a\x2d\xe7\xaa\x2d\x05\x93\xda\xae\xd3\x86\x5c\xf5\xdb\x9c\x26\x5f\xdd\x42\xc7\xea\x41\x57\xbd\x85\xbf\x82\xe5\x2a\x0c\xa5\x1c\x1e\x01\xce\x3f\x68\x63\xd6\x0e\x71\x36\x7b\x39\x83\xcf\xe3\x75\xbe\x56\x73\xff\x32\xdf\x91\x1e\xce\x64\x34\x14\x13\x62\x2a\xc3\xa7\xeb\xf8\xea\x7a\x9d\x96\xaf\xae\x9f\xb1\xd7\x76\x95\x94\xe8\x2c\x96\xae\x92\x12\x96\xb1\xea\xda\x7a\xdc\xba\xd2\xb2\x9e\xaf\x0e\x04\x93\x9b\x26\x6c\xe7\xdf\xda\xa1\x83\xd1\x4f\x96\xf8\xc8\xda\xc9\x06\x77\x67\x2d\x13\xdc\xd6\x5f\x79\xe1\x6d\x0f\x2c\x39\xf5\xa2\xa9\x8d\xcd\x5c\x60\xd0\x5e\xf9\x79\xd6\xa0\xb6\x59\x5b\xf5\x52\xfa\x2d\xc6\x52\x5d\xc6\x10\xab\xc9\x5c\xc6\xdc\xc5\xd8\x6d\xd6\x6a\x95\xdd\x66\xab\x9a\x49\x9a\x8c\x65\xa5\x1d\x26\x93\x31\xd4\x89\x3f\x63\x4c\x46\x23\xed\x86\xd1\x50\xfc\x84\x51\xed\x70\x84\x5c\x9a\xc6\x20\x78\x8b\x6c\x50\x54\xd2\xfc\xe8\x03\x1e\x01\x83\x19\x63\x20\x40\x18\x82\xf5\xac\x86\xe5\x08\xb0\x26\x27\x18\x79\x3d\xc6\xa5\x7a\x8b\xb7\xa1\xec\xb2\xb3\xaf\x80\x81\x18\x83\x4b\xaa\xf4\x50\x50\x69\x0d\xbc\xd1\x6d\xf9\x58\xeb\xae\x73\xba\x55\xf7\xde\xa6\x2e\x07\xb7\x49\xfc\xb4\x2c\x18\x2b\x52\xeb\x49\xc5\xbd\x2e\x99\x58\x09\x27\xbe\x65\xae\x2f\x52\x99\x69\x42\x42\x21\x9d\xd5\xd2\x5d\x52\xaa\xb3\x58\x67\xa0\xac\xcf\xad\x6b\xeb\xb5\x59\x75\xb8\x7b\xbb\xf8\xe9\xf2\x2e\x32\xb4\x85\x0d\xab\x61\x49\xd3\xd8\x69\x67\x1a\xb6\x5f\x7e\xfb\xa2\xc5\x17\x65\xd7\xaa\xd7\x9f\xdb\xee\x0c\xdb\xf9\x9e\xe1\xbd\xa7\x99\xd6\x6c\x1d\xc5\x19\x5b\xab\xc1\xa0\xb6\x49\x29\xb0\xa6\x72\x95\xd5\x6c\x2e\x63\x18\xeb\x91\x53\x6c\xd5\x0c\x63\x5f\x50\xcd\x32\x4e\xb2\xad\xb4\xcb\x64\x32\x96\x96\x75\x56\x9b\x66\xd6\x19\x8b\x19\x62\x36\x18\x4b\x08\x31\xbd\xef\x08\x99\x8c\x9a\xc6\x50\xa5\x06\x21\x54\x04\x6e\xf9\xc4\x69\x84\x50\x33\xda\xaa\xc0\x80\xb4\xe8\x5e\x05\xc6\x88\x47\x3f\x50\x60\x82\xcc\xe8\xb0\x02\x33\x48\x0b\x25\x0a\xcc\x22\x0b\x2c\x57\x60\x0e\x69\x61\x52\x81\x79\xb4\x1a\x7b\x14\x58\x85\x74\xf8\x6a\x05\x56\x23\x0d\x7e\x58\x81\xb5\xc8\x8e\xff\xa4\xc0\x06\xe4\x22\x3d\x88\x20\x60\xd4\x08\x21\xf9\x8d\x12\x85\x01\x39\xd0\x15\x0a\x8c\x91\x01\x3d\xa4\xc0\x04\x55\xa3\x9f\x28\x30\x83\x1c\x80\x15\x98\x45\xb5\xe0\x56\x60\x0e\x39\x60\x58\x81\x79\xf4\x0d\xd8\xad\xc0\x2a\x54\x84\xa7\x14\x58\x8d\x6c\x78\xbf\x02\x6b\x51\x03\x7e\x46\x81\x0d\x68\x31\x21\xa8\x0f\xa5\x51\x06\x4d\xa1\x2c\x4a\xa0\x51\x34\x86\xf2\xa8\x12\xf5\xa3\x08\xda\x81\x04\x54\x89\x96\xa0\x08\x4a\xa1\x18\x9a\x42\x95\xc8\x87\x5a\x50\x2b\x0a\x21\x2f\xaa\x44\x3d\x28\x89\x92\xa8\x72\x1e\x56\x4e\x2a\x09\x28\x87\x04\x94\x95\xb0\x63\xc8\x8b\x50\x5f\x3a\x33\x95\x4d\x8c\x8e\xe5\x2b\xfb\x23\x3b\x84\xca\x25\x91\x54\x6c\xaa\xd2\xd7\xd2\x1a\xf2\x56\xf6\x24\x93\x95\xd2\xa5\x5c\x65\x56\xc8\x09\xd9\x1d\x42\xcc\x8b\xd0\x20\x4a\xa3\x14\xca\xa3\x1e\x34\x29\xb5\x96\x46\x13\x48\x40\x68\x30\x9d\xca\xf7\x4c\x0a\xb9\xf4\x84\x80\xd0\x1a\x24\xa0\x51\x54\x40\x49\x14\x41\x59\x84\xd6\x08\xa3\x85\x64\x24\x4b\x71\x57\xa1\x95\x68\x1d\x5a\x8e\x7a\x50\x2f\x5a\x84\x56\xa1\x75\x68\x10\x0d\xa0\x8d\x68\x08\xad\x42\x6b\xd0\x3a\x84\x06\x57\xad\x5c\xb7\xbc\xa7\x77\xd1\xaa\x75\x83\x03\x1b\x87\x56\xad\x59\xf7\xaf\x51\xdc\x20\x8d\x2a\x87\x12\xd2\xbd\x95\x28\x80\xbc\x28\x8c\xbc\xa8\x65\x1e\x5f\xd0\x06\x21\x9b\x4b\xa4\x53\x95\x01\x6f\xd8\xdb\x22\x0d\xf2\x5f\x6b\x7c\x08\x25\x91\x80\x22\x12\xeb\x64\x26\xc6\x25\x72\x95\x28\x8f\xd2\x52\x3a\x26\x5d\x39\x99\xa8\x28\x4e\x14\xe5\xe7\x3a\x16\x47\x69\x05\x53\xc6\x89\x2b\xf4\x69\x4d\x16\x45\x50\x0c\x09\x68\x42\x62\xdb\x38\xaa\x44\x11\x94\x97\xea\x13\x68\x04\x15\xe6\xb5\x92\x42\x69\xa9\x14\x95\xfa\xec\x45\x68\x28\x29\x44\x72\x42\x65\x56\x88\x0b\xd9\xca\x7c\xba\x32\x3f\x26\x54\x1e\x15\x6d\x4e\x88\xe6\xe9\xc0\xe3\xe9\xac\x74\x25\x9e\x4e\xe5\x2b\xf3\xd9\x48\x4c\x98\x88\x64\xc7\x2b\x23\xf9\x7c\x36\x31\x52\x90\x6e\x49\xa5\xf3\x89\xa8\x90\x53\x04\x9d\x95\x7a\x76\x02\x6f\xb2\xf9\xca\x39\xe6\x9c\x4c\x17\xd1\x51\x5d\x42\x12\x1f\xf2\x28\x83\x16\xa1\x66\xd4\x3c\x37\xde\xc8\x31\x6d\x7a\xa5\x91\xa1\xb1\x7c\x3e\xb3\xa8\xb9\x99\x76\x2f\x22\xb7\xef\x4d\xa4\xff\x27\x2d\x34\xa3\xa4\xc2\x95\x94\xc4\xf9\xe6\x2f\x69\xb3\x39\x99\x88\x0a\xa9\x9c\xd0\xac\xac\x71\xfe\xd1\x3f\xfc\x7d\xc9\x26\xd1\x5f\xf7\x3e\x74\x29\xba\x04\x5d\x86\xae\x40\x57\xa2\xaf\xa1\xab\xd0\xe5\x40\xcd\x35\x03\x2c\x70\xc0\x83\x0a\xd4\xa0\x01\x2d\xe8\x40\x0f\x06\x30\x82\x09\xcc\x60\x01\x2b\xd8\xc0\x0e\x0e\x70\x42\x11\x14\x43\x09\x94\x42\x19\x94\x83\x0b\x2a\xa0\x12\xaa\xa0\x1a\x6a\xa0\x16\xea\xc0\x0d\x1e\x58\x00\xf5\xd0\x00\x0b\xa1\x11\x9a\x80\x3e\xd6\xb7\x40\x2b\xf8\xc0\x0f\x01\x08\x42\x08\xc2\xd0\x06\xed\xb0\x08\x4e\x81\xc5\xd0\x21\xbd\x2c\xea\x86\x1e\xe8\x85\x3e\xe8\x87\x01\x18\x84\x25\x70\x2a\x9c\x06\x4b\x61\x19\x2c\x87\x15\xb0\x12\x56\xc1\x10\xac\x86\x35\xb0\x16\xd6\xc1\x7a\xd8\x00\xa7\xc3\x46\x38\x03\x36\xc1\x99\x70\x16\x6c\x86\x2d\x30\x0c\x5b\x21\x02\x23\xc8\x80\x3e\x42\x7a\x88\x42\x0c\x04\x88\xc3\x28\x8c\x41\x02\xb6\xc1\x38\x24\x61\x02\x52\x90\x86\x0c\x6c\x87\x2c\xe4\x20\x0f\x05\xd8\x01\x93\xb0\x13\xa6\x60\x17\x7c\x05\xce\x86\x73\xe0\x5c\x38\x0f\xa6\xe1\x7c\xb8\x00\x76\xc3\x57\x61\x0f\x5c\x08\x7b\xe1\x22\xb8\x18\x2e\x81\x4b\xe1\x6b\x70\x19\xec\x83\xcb\xe1\x0a\xb8\x12\xae\x82\xab\xe1\x1a\xb8\x16\xae\x83\xaf\xc3\xf5\x70\x03\xdc\x08\x37\xc1\xcd\x70\x0b\xdc\x0a\xb7\xc1\x7e\xb8\x1d\xbe\x01\x77\xc0\x9d\x70\x17\xdc\x0d\xf7\xc0\xbd\x70\x00\xbe\x09\xf7\xc1\xb7\xe0\x7e\xf8\x37\xf8\x36\xfc\x3b\x3c\x00\xdf\x81\x07\xe1\x21\xf8\x2e\x3c\x0c\x8f\xc0\xf7\xe0\x51\x78\x0c\x1e\x87\x27\xe0\x49\x78\x0a\x9e\x86\x83\xf0\x0c\x3c\x0b\xdf\x87\x1f\xc0\x0f\xe1\x39\x78\x1e\x5e\x80\x1f\xc1\x8b\xf0\x63\xf8\x09\xbc\x04\x3f\x85\x9f\xc1\x21\xf8\x39\xbc\x0c\xaf\xc0\xab\xf0\x1a\xbc\x0e\x6f\xc0\x9b\xf0\x1f\xf0\x16\xbc\x0d\xbf\x80\x5f\xc2\x3b\xf0\x9f\xf0\x2e\xbc\x07\xef\xc3\xaf\xe0\x03\xf8\x35\xfc\x06\x7e\x0b\xff\x05\xbf\x83\xdf\xc3\x1f\xe0\x8f\xf0\x27\xf8\x10\x3e\x82\xc3\xf0\x67\xf8\x0b\x7c\x0c\x9f\xc0\x5f\xe1\x6f\xf0\xdf\xf0\x77\xf8\x14\x3e\x83\xcf\xe1\x08\xcc\x80\x08\x5f\x60\x84\x01\x63\x4c\x30\x83\x59\xcc\x61\x1e\xab\x50\x35\x56\x63\x0d\xd6\x62\x1d\xd6\x63\x03\x36\x62\x13\x36\x63\x0b\xb6\x62\x1b\xb6\x63\x07\x76\xe2\x22\x5c\x8c\x4b\x70\x29\x2e\xc3\xe5\xd8\x85\x2b\x70\x25\xae\xc2\xd5\xb8\x06\xd7\xe2\x3a\xec\xc6\x1e\xbc\x00\xd7\xe3\x06\xbc\x10\x37\xe2\x26\xec\xc5\xcd\xb8\x05\xb7\x62\x1f\xf6\xe3\x00\x0e\xe2\x10\x0e\xe3\x36\xdc\x8e\x17\xe1\x53\xf0\x62\xdc\x81\x3b\x71\x17\xee\xc6\x3d\xb8\x17\xf7\xe1\x7e\x3c\x80\x07\xf1\x12\x7c\x2a\x3e\x0d\x2f\xc5\xcb\xf0\x72\xbc\x02\xaf\xc4\xab\xf0\x10\x5e\x8d\xd7\xe0\xb5\xe8\x65\xbc\x0e\xaf\xc7\x1b\xf0\xe9\x78\x23\x3e\x03\x6f\xc2\x67\xe2\xb3\xf0\x66\xbc\x05\x0f\xe3\xad\x38\x82\x47\x70\x14\xc7\xb0\x80\xe3\x78\x14\x8f\xe1\x04\xde\x86\xc7\x71\x12\x4f\xe0\x14\x4e\xe3\x0c\xde\x8e\xb3\x38\x87\xf3\xb8\x80\x77\xe0\x49\xbc\x13\x4f\xe1\x5d\xf8\x2b\xf8\x6c\x7c\x0e\x3e\x17\x9f\x87\xa7\xf1\xf9\xf8\x02\xbc\x1b\x7f\x15\xef\xc1\x17\xe2\xbd\xf8\x22\x7c\x31\xbe\x04\x5f\x8a\xbf\x86\x2f\xc3\xfb\xf0\xe5\xf8\x0a\x7c\x25\xbe\x0a\x5f\x8d\xaf\xc1\xd7\xe2\xeb\xf0\xd7\xf1\xf5\xf8\x06\x7c\x23\xbe\x09\xdf\x8c\x6f\xc1\xb7\xe2\xdb\xf0\x7e\x7c\x3b\xfe\x06\xbe\x03\xdf\x89\xef\xc2\x77\xe3\x7b\xf0\xbd\xf8\x00\xfe\x26\xbe\x0f\x7f\x0b\xdf\x8f\xff\x0d\x7f\x1b\xff\x3b\x7e\x00\x7f\x07\x3f\x88\x1f\xc2\xdf\xc5\x0f\xe3\x47\xf0\xf7\xf0\xa3\xf8\x31\xfc\x38\x7e\x02\x3f\x89\x9f\xc2\x4f\xe3\x83\xf8\x19\xfc\x2c\xfe\x3e\xfe\x01\xfe\x21\x7e\x0e\x3f\x8f\x5f\xc0\x3f\xc2\x2f\xe2\x1f\xe3\x9f\xe0\x97\xf0\x4f\xf1\xcf\xf0\x21\xfc\x73\xfc\x32\x7e\x05\xbf\x8a\x5f\xc3\xaf\xe3\x37\xf0\x9b\xf8\x3f\xf0\x5b\xf8\x6d\xfc\x0b\xfc\x4b\xfc\x0e\xfe\x4f\xfc\x2e\x7e\x0f\xbf\x8f\x7f\x85\x3f\xc0\xbf\xc6\xbf\xc1\xbf\xc5\xff\x85\x7f\x87\x7f\x8f\xff\x80\xff\x88\xff\x84\x3f\xc4\x1f\xe1\xc3\xf8\xcf\xf8\x2f\xf8\x63\xfc\x09\xfe\x2b\xfe\x1b\xfe\x6f\xfc\x77\xfc\x29\xfe\x0c\x7f\x8e\x8f\xe0\x19\x2c\xe2\x2f\x08\x22\x40\x30\x21\x84\x21\x2c\xe1\x08\x4f\x54\x44\x4d\x34\x44\x4b\x74\x44\x4f\x0c\xc4\x48\x4c\xc4\x4c\x2c\xc4\x4a\x6c\xc4\x4e\x1c\xc4\x49\x8a\x48\x31\x29\x21\xa5\xa4\x8c\x94\x13\x17\xa9\x20\x95\xa4\x8a\x54\x93\x1a\x52\x4b\xea\x88\x9b\x78\xc8\x02\x52\x4f\x1a\xc8\x42\xd2\x48\x9a\x88\x97\x34\x93\x16\xd2\x4a\x7c\xc4\x4f\x02\x24\x48\x42\x24\x4c\xda\x48\x3b\x59\x44\x4e\x21\x8b\x49\x07\xe9\x24\x5d\xa4\x9b\xf4\x90\x5e\xd2\x47\xfa\xc9\x00\x19\x24\x4b\xc8\xa9\xe4\x34\xb2\x94\x2c\x23\xcb\xc9\x0a\xb2\x92\xac\x22\x43\x64\x35\x59\x43\xd6\x92\x75\x64\x3d\xd9\x40\x4e\x27\x1b\xc9\x19\x64\x13\x39\x93\x9c\x45\x36\x93\x2d\x64\x98\x6c\x25\x11\x32\x42\xa2\x24\x46\x04\x12\x27\xa3\x64\x8c\x24\xc8\x36\x32\x4e\x92\x64\x82\xa4\x48\x9a\x64\xc8\x76\x92\x25\x39\x92\x27\x05\xb2\x83\x4c\x92\x9d\x64\x8a\xec\x22\x5f\x21\x67\x93\x73\xc8\xb9\xe4\x3c\x32\x4d\xce\x27\x17\x90\xdd\xe4\xab\x64\x0f\xb9\x90\xec\x25\x17\x91\x8b\xc9\x25\xe4\x52\xf2\x35\x72\x19\xd9\x47\x2e\x27\x57\x90\x2b\xc9\x55\xe4\x6a\x72\x0d\xb9\x96\x5c\x47\xbe\x4e\xae\x27\x37\x90\x1b\xc9\x4d\xe4\x66\x72\x0b\xb9\x95\xdc\x46\xf6\x93\xdb\xc9\x37\xc8\x1d\xe4\x4e\x72\x17\xb9\x9b\xdc\x43\xee\x25\x07\xc8\x37\xc9\x7d\xe4\x5b\xe4\x7e\xf2\x6f\xe4\xdb\xe4\xdf\xc9\x03\xe8\x1a\x76\x34\x19\xc9\xe5\xd8\x89\x42\x2e\x11\xe5\x72\x42\x24\x1b\x1d\x53\x09\xa9\x1d\x42\x32\x9d\x11\xd8\x31\x21\x92\xcd\x33\xb9\x7c\x24\xab\xa1\xc9\xb0\x30\x91\xc9\x4f\x31\x85\x9c\x90\x65\xe2\x89\xe4\x84\x2a\x3f\x36\x9c\x8c\x64\x47\x05\x9c\x1f\xe3\x29\x9c\xc8\xe5\x71\x7a\x9c\xcb\x0a\x13\xe9\x1d\x02\xbf\x2b\x9d\x9e\x18\x4e\xa4\x54\x52\x9e\x2e\xe4\x49\x3a\x1e\xe7\x72\x89\xd1\x54\x24\x49\xa2\xe9\x51\x36\x9f\x8d\xe4\xc6\x98\xb1\xf4\x84\xa0\x8a\x27\x92\xc2\x70\x24\x99\x67\xf2\x89\x09\x81\xc9\xa6\x23\x31\x5d\x2c\x3d\x99\x4a\xa6\x23\x31\x5a\xad\x9a\x2d\x70\x85\x0c\xcd\xd8\x44\x6a\x24\xbd\x53\x9b\x49\x46\xa6\x86\xa3\x89\x6c\x34\x29\x70\x59\x21\x23\x44\xf2\x7c\x56\x88\x67\x85\xdc\x98\x8a\x76\x45\x6a\x30\x99\x8e\x8e\x33\xf1\x64\x64\x54\x33\x26\x44\x62\x99\xb1\x74\x4a\xc8\x69\x76\xa4\x93\x85\x09\x61\x38\x1d\x8f\x6b\x15\x90\x12\x50\x2b\x70\x21\xc3\x6d\xcf\x46\xd3\x31\x81\x1f\x89\x48\x39\xc9\x47\x46\x99\x7c\x64\x34\xc7\x8c\xa4\xd3\xe3\x2a\x9a\xd0\x19\x9e\xcd\x64\x13\xa9\x3c\x17\x8d\x4c\x08\xd9\x08\x43\xa7\x42\x66\x24\x9d\x8c\x71\x89\x7c\x24\x99\x88\x6a\xf3\xc2\xce\xfc\xf0\x98\x40\x97\x0a\x1a\x09\x9e\x4c\xc4\xf2\x63\x9a\x48\x32\x31\x9a\x1a\x4e\x0a\xf1\xbc\x4e\x06\xa3\x42\x2a\x2f\x64\xb5\x72\x41\x5a\x59\xe8\x65\x78\x5b\x21\x97\x4f\xc4\xa7\x18\x3a\x16\x6d\x22\x15\x13\x52\x79\x19\x4f\x81\xa5\x7b\x0d\xf1\x48\x54\xa0\x5c\x1b\xde\x91\x88\x09\x69\x3e\x93\x88\xe6\x0b\x59\x81\xcb\x08\xa9\x68\x22\xa9\x99\x88\x64\x86\x69\x5f\x85\x2c\x17\x89\xd1\x06\x99\x7c\x22\x95\x67\x84\x58\x22\xcf\xe6\xc6\x22\x59\x81\x8d\x8e\x09\xd1\x71\x86\x0a\x4c\x9f\xcb\x0b\x99\xe1\x91\x48\x74\x7c\x32\x92\x8d\xe9\xe3\x91\x5c\x7e\xae\xa4\x9a\x05\x18\xca\x74\x36\x13\x29\xe4\x04\x26\x97\x4f\x67\xf8\x78\x3a\x4b\xeb\x75\xd2\xed\xb3\x05\xa9\x25\xa5\xc0\x0a\xdb\x84\x68\x5e\x17\x1d\x13\x76\x64\xd3\xf2\xc8\xf5\xb3\x05\x69\x08\xea\x4c\xb2\x90\x1b\xa6\x8a\xa1\x99\x48\xa4\x14\x50\x2b\x2b\x91\x04\xf3\xe9\x71\x29\xd7\x6f\x2f\x08\x39\xba\x9e\x92\x4a\xea\x44\x2a\x9e\x96\xd1\x72\xd1\xac\x20\xa4\x72\x63\xe9\xbc\x5e\x41\x93\xb5\x42\x9d\x1e\x57\x20\xcd\x48\x24\x35\x0b\x46\xb2\xd9\xf4\xa4\xd4\x0f\xad\x0c\x4a\xbd\x50\xc9\x70\x21\xa3\x5c\x97\x34\x42\x62\x11\xd5\x23\x6d\x56\xc8\x25\x76\x09\xc3\xf1\x42\x32\xa9\x53\xe0\xdc\x44\x24\x99\x34\x09\x3b\xa3\xc9\xc8\x44\x64\xae\x5b\xcc\x68\x22\x9e\x67\x92\x42\x24\xce\xc4\x13\x59\x41\x25\x4c\x09\xc3\xe9\x8c\x90\x52\x53\x20\x9a\x4c\xe7\x04\xdd\x64\x24\x9b\x4a\xa4\x46\xa5\xdb\xd9\x4c\x32\x92\x12\x54\xd1\x48\x52\x48\xc5\x22\x59\x2e\x1b\x49\xc5\xd2\x13\x7c\x34\x3d\x31\x21\xa4\xf2\xdc\x44\x64\x34\x25\xe4\x35\xb3\xfc\x2a\x64\xe6\xf8\x48\xfb\xc7\x67\x85\xfc\xa4\x20\xe4\xf5\xb9\xb1\x74\x26\x43\x9b\x8c\x46\xb2\x79\x5d\x3c\x9d\x8c\x09\x59\x99\x98\x56\x29\xd0\x2e\x18\x95\x8e\xef\x10\xb2\xf9\x44\x34\x92\x34\x2b\xe5\xb1\x74\x36\xb1\x8b\xae\xe4\x92\xea\x91\x48\x76\x38\x3a\x46\x1b\xc9\x4f\x26\xf2\x79\x21\x2b\x33\x9e\x2a\x19\x55\x7b\xa9\xa4\x93\x35\x7e\x38\x2b\xe4\xb3\x69\x32\x2e\x4c\x31\xd1\xf4\x68\x4e\xa5\x74\x39\xa7\xcf\x8f\x15\x26\x46\x72\xc3\x85\x0c\x65\x9c\x51\x29\xd1\xee\xd2\xb2\x5a\x32\x24\x63\x91\x64\x5c\x2b\x59\x17\xd9\xa6\xf0\xb4\xdd\x74\x21\xaf\x4f\x26\x52\xe3\x42\x2c\x21\xb3\x92\xcf\x14\x72\x63\x99\x44\x4a\x2f\xec\xcc\x0b\xd9\x54\x24\x39\x4c\x2f\x4b\x26\x24\x91\xe2\xf2\xd9\x74\x66\x6c\x4a\x3b\x9a\xc8\x8f\x15\x46\x64\x3d\x90\xad\x03\x25\xc3\x26\x85\x89\x74\x8a\x95\x7e\xef\x5a\x49\xc5\x65\x42\x86\xd9\x1f\xaf\x5c\xd4\x48\x37\xc8\xc4\x94\x01\xab\x66\xc7\xca\xc9\x2d\x73\x85\x14\xb5\x21\xda\x68\x96\xfe\x68\x28\x83\x63\x24\x9b\xcb\x91\xb1\x58\x4c\x35\x52\x48\x26\xc7\xd2\xd9\x14\x33\x22\x24\x93\xda\x28\x65\x6b\x3c\x11\x8d\xe4\x05\xcd\x58\x24\x15\x53\xb4\x5b\x02\xa9\xb6\xf1\x12\x54\xc8\xc8\x35\x94\x21\x66\x59\x23\x87\x8f\x6a\xa4\xe5\x98\x1a\xa9\x01\xe3\x31\x55\x85\xcc\xb1\x48\xb4\x19\x76\x34\x99\x1e\x11\xb8\xc9\xac\x90\x8a\x8e\xb1\xf9\x48\x6e\x3c\xc7\xc5\x13\xc9\xbc\x90\x55\x8f\x64\x13\x42\x3c\x1a\xc9\x09\x1a\xaa\xb9\xf2\xef\x84\x1d\xcd\xa6\x0b\x19\x86\xf2\x92\x8d\x26\xd3\x85\x18\x37\x22\x44\xc6\x85\x2c\x89\x16\xf2\x4c\x34\x9d\x99\xd2\x64\x22\x19\x49\x7f\x12\x19\x26\x17\xd9\x21\x68\x28\x7f\x86\x47\x92\x91\xd4\x38\x9f\x15\xd2\xd9\x98\x90\xc5\x85\x24\x4e\x27\xf5\xb9\x7c\x36\x31\x2e\xe4\xc7\xb2\xe9\xc2\xe8\x98\xba\x90\x8a\x09\xd9\x64\x22\x25\xb0\xf9\xc8\x48\x52\x60\x27\x22\xa3\x89\x28\x9b\xcf\x16\xa2\xe3\xea\x4c\x82\x5a\x39\x21\x97\x37\xcc\x41\x12\xdb\x4d\xa3\xe9\xf4\x68\x52\x18\x9e\xb3\x01\xda\x79\x15\xec\x44\x3a\x25\x4c\x69\xa2\x91\xac\x90\x97\x46\xaa\x92\xc1\x42\x46\xa9\x93\x7e\xc4\x32\x28\xf1\x8a\x8f\x52\x13\x9e\xca\x31\xb9\x74\x36\xaf\xa6\x89\xfc\x3b\x91\xa0\x42\x46\x37\x3b\xb3\x49\x93\xca\xac\xae\x31\x85\x54\x2c\xcd\x26\x85\xd1\x48\x52\x1d\x8b\xe4\xc6\x46\xd2\x91\x6c\x4c\xab\xa8\x33\xbd\x53\x37\xab\xda\xd2\x8c\x32\x92\x4e\xe6\xf9\x5c\x22\x2f\x4c\x44\x32\xaa\xc2\xc4\x48\x56\x48\x26\x23\x6c\x26\x92\xcb\x0b\x9a\x24\xed\xc4\xf0\x48\x21\x39\xa2\x12\x76\x46\xc7\x22\xa9\x51\xc1\x20\xb1\x78\x78\x76\x06\xd3\xc9\x45\x59\x53\x79\x3a\x95\x0e\x4f\xc4\xb4\xb9\xbc\x90\x1f\x4b\xe7\xa2\xe9\x8c\xa0\xca\x15\x12\x79\x2a\x31\x15\x55\x2a\x4a\x91\x8b\xa6\xe3\x71\x41\x60\xe2\xe9\x74\x4c\x2f\xcd\x94\xd2\x74\x42\x87\x30\x52\x48\x24\x63\x89\xd4\xa8\x6a\x2c\x9d\xcb\xd0\x79\x47\x1d\x99\x18\x29\x24\x23\xa9\xa8\xc0\x4d\x08\xb1\xf1\x44\x5e\x1b\xa7\x5d\x12\xb2\xc3\xdb\x84\x3c\x33\x22\x08\x59\x6e\x4c\x36\x53\xf1\x96\xb8\x60\x8e\xa5\x0b\x23\x54\x95\x52\x94\xe3\x92\xfe\x1d\x53\x23\xeb\xdf\x31\x55\x85\xcc\xb1\x48\x74\x5c\x9a\xa3\xf8\xda\x79\x88\xaa\x59\x0c\xcd\xd1\x5b\xf9\x98\x90\x1b\xcf\xa7\x33\x5c\x32\x92\xa1\x99\xa4\x28\x79\xdd\x44\x7a\x84\x8e\x4b\xfa\x35\xea\x14\xfd\x96\xf4\x4d\xb3\xbd\x90\xce\x2b\x4d\xcb\xa0\x2c\xe7\x5c\x26\x91\x4a\x09\x59\x4e\xbe\x97\xcd\x0a\x99\xe4\x94\x46\x31\x05\x91\x64\xde\x34\xdf\x04\x4a\x66\x68\x9e\x19\xa4\x65\x8d\xb0\x33\x43\x7f\x85\xb2\x74\x93\xc9\x48\x46\xbe\x8f\xcd\x4d\x24\x92\x02\x1b\xcf\xa6\x27\x53\x64\x42\x18\xe3\x47\x23\x13\x42\x26\x12\x53\x8d\x0b\x53\x92\x5e\xa8\xe8\x5a\x82\xde\x69\x90\x00\xc9\xb4\x08\x59\x21\xa6\xca\x0b\xd9\x89\x44\x2a\x92\x64\xe8\x8a\x41\x2d\x75\x68\x38\x92\x4c\x1a\xe7\xec\x9d\x62\x80\x92\xe9\xa8\x3c\x59\x48\xbf\x5f\x26\x9a\x4d\x67\xd4\x14\x85\x4e\x97\xe3\xd4\xd8\x24\x52\xe3\xcc\xb0\x2f\xdc\xae\x9d\x37\xb3\x68\x73\x85\x8c\x90\xcd\x45\xb3\x89\x4c\x5e\x9d\x2b\x8c\xc8\x10\x33\xec\x6b\xf3\xeb\x32\x85\x5d\xbb\x28\xef\x12\x42\x54\xd0\x4c\x24\x68\x83\x94\x8d\x86\xa3\xe0\xb0\xb4\xf0\x1a\x4b\x08\xc9\x98\x61\x76\xa2\x91\x7b\x63\xa6\x53\xd4\xb0\xb0\x33\x9f\x48\x8d\x16\x12\xb9\x31\x21\xcb\x65\xd3\xd1\x71\x81\x4e\x3c\x3b\xa3\xb1\x94\x79\x76\xb6\xc9\xcd\x2e\x5a\x2c\xc7\xd4\x28\x06\x6a\x7e\x15\x35\x50\xf3\xcb\x92\x81\x1a\xcb\x4f\x24\x83\x4c\x34\x97\xf3\x73\x91\x54\x74\x2c\x9d\xd5\xc8\x56\x55\x51\xe2\x64\x32\x27\x4c\x09\x56\x21\x99\x4c\x64\x72\x89\xdc\xbc\x09\xc9\x3c\x57\x37\x3b\x69\x31\xc3\xfe\x16\xbf\x5a\x5a\xfa\xd1\xf6\xb9\x7c\x82\xf6\xd7\x70\x74\xe5\x20\x4d\xd7\xb2\xc9\x97\x2a\x55\x49\x61\x87\x90\xa4\x6a\x28\x03\x92\xc6\xca\xd7\xa5\x65\x84\x64\xd6\xa5\x9f\xc4\xb0\xbf\xd5\xa7\x91\xa7\x7c\x69\x46\x88\xa6\x27\x32\x91\x1c\x9d\xd9\x64\x05\x39\xaa\x29\xf9\x74\x86\xde\x1d\x26\x42\x21\x4b\x46\x47\x32\xa4\x90\x8b\x91\x44\x2a\x4b\xb6\x65\xa6\x48\xb6\x30\x42\xc6\xb3\x93\x64\x24\x1f\xa5\xcb\x64\x41\x3d\xf7\x9b\x35\x49\x76\x68\x84\x2a\x46\x66\x2c\x32\x22\xe4\x99\x61\xbf\xaf\xdd\x32\x57\xab\xbc\x31\x12\x72\x8e\x13\xab\xe8\xb0\xf4\xb3\xd5\x92\x0d\x36\x1f\x53\x92\x6c\xd3\xb0\xdf\x1f\xa0\x49\x50\x37\x95\x2e\xe4\x0b\x23\xca\x40\x94\x02\xb3\x33\x91\x1a\x55\xef\x9c\x5d\x7a\xcc\xdd\x43\x99\xc9\xc7\xb2\xe9\xcc\x48\x7a\xa7\x3e\x97\x8f\x44\xc7\x67\x8d\x97\x3a\x91\xca\xe5\x23\xa3\xd9\xc8\x04\x17\x4f\x26\xa2\xe3\x59\x12\x89\xa5\x98\x78\x6b\xb8\xd5\x30\x92\xc8\x8f\x14\x28\xeb\x15\x31\x14\x26\x46\x92\x59\xad\x9c\x49\x55\xc6\x64\x3a\x35\x3a\x6f\x96\xd2\xcf\x2b\x17\x32\xf3\xaf\x52\xbd\x32\xcd\x2b\xcb\x3f\xf1\xc9\x44\x2a\x96\x9e\xcc\xf1\x91\x54\x2c\x9b\x4e\xc4\xd8\x64\x22\x55\xd8\xc9\xc7\xb2\x89\x11\x3a\xb7\xe4\xc6\xa7\x32\x82\x26\x9e\x2e\x64\x73\xdb\x0b\x91\xac\xc0\xe5\xa9\x1d\x4e\x73\x71\x61\x22\x92\x14\x18\x9a\xd0\x09\x3c\x9f\xc8\x90\x5c\x81\x8a\x36\x14\xe2\xe9\xc3\x4d\x62\x87\x40\x46\x0a\xa3\x78\xc7\x38\x3b\x29\x24\x46\xd2\x5c\x56\x48\x65\x05\x7a\x43\xd8\x67\x90\xc6\x3e\x3c\x3b\x78\x5a\x17\xb0\xcb\x5d\x9a\x9d\x73\x93\xf2\x9c\x43\x2f\x85\x0c\xb1\x74\x7e\xde\x05\x5a\xd7\xa6\xdb\x91\x98\x10\xd2\xc3\x72\x9f\x98\x61\x7f\x5b\x8b\x5e\x9e\xd9\xa4\x8a\xe1\x34\xad\xf2\xd1\xc4\x4f\x13\x2a\xab\xb6\x20\x4d\x42\x34\x09\xd3\xa4\x8d\x26\xed\x7c\x21\x95\x18\x6c\xed\x69\x61\xe2\xad\x91\x56\x66\xd8\xdf\x4e\x91\xda\xfd\xb4\x48\x91\xda\x29\x52\x3b\x45\x6a\xa7\x48\xed\x14\xa9\xbd\x9d\x19\x0e\xb4\x48\x18\x23\x14\xf2\xd1\xc4\x4f\x93\x80\xdc\x5a\x6f\x2b\x2d\x84\x68\x12\xa6\x49\x1b\x4d\x28\x52\x6b\x0b\x4d\xe8\xd5\x56\x8a\xd4\x4a\x91\x5a\x03\x34\x09\xd2\x84\x62\xb4\x52\x8c\x56\x8a\xd1\xaa\xf4\xad\xaf\x45\xc9\x29\x9e\x8f\xe2\xf9\x28\x9e\x8f\xe2\xf9\x28\x9e\x8f\xe2\xf9\x28\x9e\x8f\xe2\xf9\x28\x25\x3f\xa5\xe4\xa7\x18\x7e\x8a\xe1\xa7\x18\x7e\xa5\x7b\xfd\x4a\x83\xfd\xad\x4a\x2e\xdd\x41\x51\xfd\x0a\xc9\xfe\xa0\x92\x87\x94\x9c\x36\x1e\xa0\x6d\x04\x28\xd5\x00\xa5\x1a\xa0\x54\x03\xd2\x05\x8a\x1a\x50\x50\x07\x28\xe1\x20\x25\x1c\xa4\xcd\x06\x29\x52\x90\x22\x05\x29\x52\x90\x22\x05\x29\x52\x90\x22\x05\x69\x57\x43\x14\x23\x44\x31\x42\x14\x23\x44\x31\x42\x4a\x57\x07\xa5\x6b\x14\x29\x14\x66\xe2\xad\x71\xe9\x1a\x45\x0a\xd3\x0b\x61\x8a\x14\xa6\x48\x61\x7a\x21\x4c\xc9\x84\x29\x99\x70\x88\xde\x1c\xa5\x10\x25\x13\xa6\x18\x6d\x14\xa3\x8d\x62\x50\xbd\x08\x50\xbd\x08\x50\xbd\x08\x50\xbd\x08\x50\xbd\x08\x50\xbd\x08\x50\xbd\x08\xb4\x51\x8c\x76\x8a\xd1\x4e\x31\xa8\x52\x04\xda\x29\x46\x7b\x80\x89\xfb\x24\x31\xb6\x87\x28\x24\x5d\xa0\x18\x54\x29\x82\x2d\x2d\x34\x69\xa5\x89\x8f\x26\x7e\x9a\x04\x68\x12\xa4\x49\x88\x26\x61\x9a\xb4\xd1\xa4\x9d\xdd\x21\xa4\x0a\x39\x66\x38\x48\x55\x22\x48\xdb\x0a\x52\x95\x08\x52\x95\x08\x52\x95\x08\x52\x95\x08\x52\x95\x08\x52\x95\x08\xb6\x52\x22\x3e\x4a\xc4\x47\x31\xa8\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\xf9\x0a\xfa\x29\x86\x9f\x62\xf8\x29\x06\xd5\x81\xa0\x9f\x62\x04\x28\x46\x80\x62\x04\x28\x06\x15\x7d\x90\x8a\x3e\x48\x45\x1f\xa4\xa2\x0f\x52\xd1\x07\xa9\xe8\x83\x01\x8a\x11\xa4\x18\x54\xee\x41\x2a\xf7\x20\x95\x7b\x90\xca\x3d\x48\xe5\x1e\xa4\x72\x0f\x52\xb9\x07\xa9\xdc\x83\x54\xee\x41\x2a\xf7\x20\x95\x7b\x90\xca\x3d\x48\xe5\x1e\x0c\x51\x8c\x10\xc5\xa0\x42\x0f\x86\x28\x46\x88\x62\x84\xda\x99\xb8\x2f\xd4\x42\x13\x8a\x11\xf6\x51\x88\x62\x50\xa1\x07\xa9\xd0\x83\x61\x8a\x11\xa6\x18\x54\xe8\x41\x2a\xf4\x20\x15\x7a\x90\x0a\x3d\x48\x85\x1e\xa4\x42\x0f\x52\xa1\x07\xa9\xd0\x83\x54\xe8\x41\x2a\xf4\x20\x15\x7a\x90\x0a\x3d\x48\x85\x1e\xa4\x42\x0f\x52\xa1\x07\xa9\xd0\x83\xed\x14\x83\x5a\x82\x20\xb5\x04\x41\x6a\x09\x82\xed\x6d\x4c\xdc\x17\x16\x24\x35\xf5\xb5\xb5\x28\x79\x2b\x33\x1c\xa2\xa2\x0f\x51\xd1\x87\x14\x7b\xe0\x6b\x0b\x2a\x79\x88\x56\x86\x69\xd2\x46\x93\x76\x66\x38\x44\x75\x29\x44\xe5\x1f\xa2\xf2\x0f\x51\xf9\x87\xa8\xfc\x43\x54\xfe\x21\x2a\xff\x10\x95\x7f\x88\xca\x3f\x44\xe5\x1f\xa2\xf2\x0f\x51\xf9\x87\xa8\xfc\x43\x54\xfe\x21\x2a\xff\x10\x95\x7f\x88\xca\x3f\x44\xe5\x1f\xa2\xf2\x0f\xf9\xe4\x9f\xa5\xaf\x47\xe9\x61\x4f\xab\x92\xfb\x94\xdc\xaf\xe4\x4a\x57\x7b\x94\xae\xf6\x84\x94\x3c\xac\xe4\x6d\x4a\x3e\xdb\x5e\x8f\x92\xf7\x2a\x79\x9f\x92\xf7\x2b\xf9\x80\x9c\xf7\x2a\x74\x7b\x15\xba\xbd\x0a\xdd\x5e\x85\x6e\xaf\x42\xb7\x57\xa1\xdb\xab\xd0\xed\x55\xe8\xf6\x2a\x74\x7b\x15\xba\xbd\x0a\xdd\x5e\x85\x6e\xaf\x42\xb7\x57\xa1\xdb\xab\xd0\x55\x8c\xa6\xaf\x4f\xa1\xdb\xa7\xd0\xed\x53\xe8\xf6\x29\x74\xfb\x14\xba\x7d\x0a\xdd\x3e\x85\x6e\x9f\x42\xb7\x4f\xa1\xdb\xa7\xd0\xed\x53\xe8\xf6\x29\x74\xfb\x14\xba\x7d\x0a\x5d\xc5\xb6\xfa\x14\xdb\xea\xeb\x57\xe8\xf6\x2b\x74\xfb\x15\xba\x8a\x85\xf5\x29\x16\xd6\xd7\xaf\xd0\xed\x57\xe8\xf6\x2b\x74\xfb\x15\xba\xfd\x0a\xdd\x7e\x85\x6e\xbf\x42\xb7\x5f\xa1\x3b\xa0\xd0\x1d\x50\xe8\x0e\x28\x74\x07\x14\xba\x03\x0a\xdd\x01\x85\xee\x80\x42\x77\x80\x6a\x4a\xbb\x42\x74\x40\x21\x3a\xa0\x10\x1d\x50\x88\x0e\x28\x44\x07\x14\xa2\x03\x03\xf2\xa7\x25\xf8\xe2\x0b\x84\xa5\xaf\xcf\x06\x84\x50\x91\xf2\xc5\x1b\x10\xe0\x67\x11\x20\x66\xee\xdb\x94\xf4\x7d\xfa\x27\x1d\xdf\x90\xdc\xde\x7e\xbc\x6a\x71\x0b\xcd\x5f\x6d\x1d\x7b\xf4\xff\x0b\x00\x00\xff\xff\x4f\x70\x1d\xba\x6e\x87\x02\x00")
+
+func uiAppLibFontAwesome470FontsFontawesomeWebfontEotBytes() ([]byte, error) {
+ return bindataRead(
+ _uiAppLibFontAwesome470FontsFontawesomeWebfontEot,
+ "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.eot",
+ )
+}
+
+func uiAppLibFontAwesome470FontsFontawesomeWebfontEot() (*asset, error) {
+ bytes, err := uiAppLibFontAwesome470FontsFontawesomeWebfontEotBytes()
+ if err != nil {
+ return nil, err
+ }
+
+ info := bindataFileInfo{name: "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.eot", size: 165742, mode: os.FileMode(420), modTime: time.Unix(1, 0)}
+ a := &asset{bytes: bytes, info: info}
+ return a, nil
+}
+
+var _uiAppLibFontAwesome470FontsFontawesomeWebfontSvg = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x6d\x73\x1c\x49\x92\x26\xf6\xbd\x7e\x85\x8b\x32\xd3\x17\x5d\xa0\xc3\xe3\x3d\x6e\xa6\xf7\xec\x6e\xe7\x76\x4d\x66\xa2\xf6\xcc\x6e\xef\x64\xfa\xd4\x86\x26\x8b\x2c\xec\x24\x01\x26\x10\xac\x9e\xc1\xaf\x97\xf9\xe3\x91\x59\x55\xc8\xac\x02\xc0\x66\x73\x7a\xa4\xb5\x99\x66\x15\x2a\x23\xe3\x3d\x3c\xfc\xf5\xf1\x3f\xfe\xa7\xbf\x7c\x1a\x68\xbf\xbd\x7f\xb8\xb9\xbb\xfd\xf1\x0d\x5f\xd9\x37\xf4\xd0\xae\x6f\xdf\x5f\x0f\x77\xb7\xdb\x1f\xdf\xdc\xde\xbd\xf9\x4f\xff\xb0\xf9\xe3\xff\xf2\xa7\x7f\xf9\xc7\x7f\xfd\x7f\xfe\xdb\x7f\xa5\x87\xfd\x47\xfa\x6f\xff\xe3\xbf\xfc\x9f\xff\xc7\x3f\xd2\x1b\xf3\xc3\x0f\xff\xb7\xff\xc7\x1f\x7e\xf8\xd3\xbf\xfe\x89\xfe\xfb\xff\xfc\x67\xe2\x2b\xfe\xe1\x87\xff\xfa\x7f\xbd\xa1\x37\xbb\xd6\x3e\xff\xc7\x1f\x7e\xf8\xe5\x97\x5f\xae\x7e\xf1\x57\x77\xf7\x1f\x7f\xf8\xe7\xfb\xeb\xcf\xbb\x9b\x77\x0f\x3f\xfc\xf7\xff\xf9\xcf\x3f\x48\xc1\x3f\xfd\xeb\x9f\x7e\x78\xd8\x7f\x64\xbe\x7a\xdf\xde\xbf\xa1\x7f\xd8\xfc\xf1\x61\xff\xf1\x1f\x36\x7f\xfc\xb4\x6d\xd7\xef\xaf\xdb\xf5\x3f\x6c\xfe\xf1\x7e\x7b\xdd\xb6\xef\xe9\xe7\xbf\xd2\x3f\xdd\xdd\xb6\x7f\xba\xbb\xff\xb8\x25\x67\xd9\xd9\xec\x99\xae\x1b\xbd\xbd\xbb\xa5\x7f\x79\xd7\xc8\x05\xe2\xfc\x1f\x7d\xfe\x8f\xc1\xca\xf3\xb4\xa1\xff\xf2\x57\xfa\x0f\xff\xe1\x3f\x6c\xfe\xf1\xee\xf3\x5f\xef\x6f\x3e\xee\x1a\xfd\xe9\x7a\xbf\xa5\x7f\xbe\xbe\x7d\xff\x57\x94\xb8\xa2\xff\x3c\x0c\x84\x47\x0f\x74\xbf\x7d\xd8\xde\xef\xb7\xef\xaf\x36\x7f\xfc\xe1\xd0\xfa\x1f\xdf\x6f\x3f\x3c\xfc\xc3\xe6\x8f\x1f\xee\x6e\x1b\xdd\xbc\xff\xf1\x8d\xf4\xe1\x3f\xff\xb2\x7d\xb8\xfb\xb4\x7d\x43\xbb\xbb\xfb\x9b\x47\x73\xfd\x7e\x6f\xfe\xf2\xe3\x1b\x8e\x3e\xc9\x08\x88\x50\xda\x7c\xb8\x7e\xb7\xa5\x0d\x11\x51\xff\xf3\xd3\xcd\xf0\xd7\xd3\x0a\x0e\x4f\x7f\xd9\x4a\x2f\x7e\x7c\x13\xac\x3d\xfa\xf5\xa1\xdd\x6f\xdb\xbb\x9d\xcc\xff\xfd\xa7\xeb\x41\x9f\x7c\xb9\xbd\x69\x0f\xe6\xf3\xf6\xde\x6c\x3f\xfd\xf8\x86\x73\x75\xfa\xfb\xe7\xeb\xdb\xbb\x87\xad\xe1\x1f\xdf\x58\x5a\xfc\x4f\x8b\x5c\x3f\xbc\xdb\xde\xb6\xde\x55\xfc\xf2\x7e\xdb\x7f\x32\x2e\xf6\x9f\x7e\xfe\xf9\xee\x2f\x3f\xbe\x31\x7c\x65\x9d\x2d\x9e\xe4\xc1\x55\x4d\x8e\x9c\xb7\xe1\x2a\x11\x47\x9f\xaf\xac\x9b\xfa\xf2\x7e\x7b\x3f\xdc\xdc\x6e\x4d\xdb\xdd\xbc\xfb\xf3\xed\xf6\xe1\xe1\xc7\x37\xf6\xe9\xb3\xcf\x77\x0f\x37\x0d\x1b\x6b\x7e\x74\xf3\xee\xee\xfd\xd6\xdc\x5f\xdf\x7e\xdc\xfe\xf8\xe6\x7f\xfc\xef\xd6\x3a\x6b\xfe\x29\xea\xe0\x7f\x90\xf5\xbf\x79\x78\xb8\xb9\xfd\x68\x3e\x0e\x7f\xfd\xbc\x3b\x9d\xe7\x52\xd3\x1b\xda\xbc\xff\xf1\xcd\x5b\x27\x4b\xce\x6e\x17\x42\xd9\xb3\x67\xb7\x33\xf2\xcd\xc8\xd7\xc7\xb7\xcc\x8e\xec\x5e\x46\xba\x4b\xd9\xed\x0d\xbe\x99\x94\xdd\xe3\x1b\x69\x41\xba\xf1\x47\xad\x1d\xff\x9a\xdb\xeb\x4f\xdb\x1f\xdf\x5c\xdd\xde\xb5\xf7\xdb\x0f\x6f\xbe\x6b\x93\x5f\x86\xe1\x49\x83\xf6\x0d\x6d\x2e\xbc\x72\x7b\x77\xfb\xe9\xfa\xfe\xcf\x37\xb7\x1f\xef\xb7\xed\xcb\xfd\xed\x93\xb7\x63\xcd\x97\xdf\x7f\xf8\x7c\xfd\x6e\xfb\x66\x5a\x86\x1f\xdf\xd0\x93\x0a\x42\x28\x97\x2b\x78\x7f\xb3\xbd\xdf\x3e\xdc\x3c\x1c\xd5\xf1\xbf\xfd\xaf\x7f\xb9\x2e\x7f\x78\x7a\x26\x64\x77\x5e\xac\xe9\xdd\x74\x38\x9f\x54\x55\x5f\x5f\xd5\xfd\xf6\xe3\xcd\x43\xdb\xde\x6f\xdf\x3f\xa9\x6b\xfb\xfa\xba\xae\xdf\x7d\x69\xdb\xd3\x6a\x7e\x0e\xaf\xaf\xe6\x3f\xff\xd7\xd3\x3a\xde\xa5\xd7\xd7\xf1\x2f\x0f\xc3\xf5\xc3\xee\xb4\x9e\xf7\x5f\x31\xd3\xed\xfe\xfa\xfd\x56\xb6\xcd\x69\x55\x8e\x9d\x7b\x7d\x65\x37\xb7\x1f\x6e\x6e\x6f\xda\x5f\x9f\xd4\xe5\xf8\x2b\xe6\xfa\xf6\xae\x6d\xc7\x2f\xd7\xc3\xd3\xba\x92\x7d\x7d\x5d\x1f\x87\xeb\x87\x27\xbb\xf2\x83\xb5\xe7\x2a\x92\x13\xcd\xa9\x56\x62\x1f\xed\x68\xc9\xf8\x48\x26\x78\x32\xb9\x0c\x26\x79\x47\xf2\xcf\xde\xe4\x54\x76\xde\xd9\xd1\x25\xb2\x14\x22\x19\xae\x8d\x2b\x99\x10\x9b\x99\x3e\xf5\xe7\x9d\x29\x35\x8d\x06\x05\xe5\x27\xae\x28\x11\x62\xd3\x7f\xf1\x93\xd4\xb5\xcf\xa9\x37\x91\xbc\x1b\xa5\x4d\x69\x36\x78\xca\x65\xb4\xe4\x3c\x71\x21\x9f\xae\x62\xf3\x85\x38\x5f\xc5\x26\x25\x76\x1c\x6c\x19\x9d\x97\x5e\x48\x69\x79\x68\xf0\x94\x0b\x19\x29\x7e\x91\xd0\x7c\xfa\xf2\x70\xf3\x6e\x31\x37\xfc\x87\x69\x22\xa2\x4f\x24\x84\x6c\x6f\x98\x1d\xa6\x23\xca\x94\x04\x32\xa5\x36\x53\x12\x99\x64\xaf\x64\xc8\xd6\x5f\x45\x32\xde\x35\x53\x93\x7c\x63\xfc\x8c\xef\x7c\x54\x42\x0a\x94\x44\xfa\x92\x0f\x54\x6a\xd3\x7f\xa7\x1f\xe7\x62\xf3\xab\x23\xdb\x48\x96\xb8\x3a\x32\xbe\xee\xa3\xcf\x83\xcc\x3e\x19\xe7\xf3\xde\x64\x5b\x7f\x8b\x5e\x6d\x5e\xdb\xad\x9a\xf2\x68\xc9\x33\x71\xa5\x28\x8b\x14\x2a\xf9\x78\x15\x87\xe2\x1d\xb9\x98\x46\x76\x14\xc8\x15\x0a\x63\x90\xdb\x17\x03\x28\xcd\x15\x32\xa9\x5c\x5c\xa2\x87\xed\xf5\xfd\xbb\xdd\x62\x8d\x96\x07\x34\xa5\x30\x2d\x1b\x47\x47\xd9\x86\xd1\x12\x17\x19\xb6\x67\xe9\x3d\x27\x8c\x8f\x31\x04\xf9\x69\xfa\xc3\xf4\xbf\xb4\x9c\xfe\xd8\x4e\xfe\x38\x29\x77\x5c\xc3\x51\xd5\x8f\x6f\xa5\x0b\x64\xd8\x15\x2c\x89\x4c\x4c\x21\x53\x6d\x33\x55\x96\xa7\x8c\x26\x06\x39\x04\xd5\x92\x2f\x83\xf1\xc1\x93\x0f\x6e\x34\x9c\xab\xbc\x15\x64\x22\xf5\xdb\x68\x38\xc8\x96\x36\x2e\xcb\xbc\xc7\x28\xbd\x73\x2e\x12\x47\xdb\x0c\x47\x4b\xce\xc5\x66\xe4\x77\x42\x91\x4d\x3b\x7c\x6f\xd3\xf3\xe9\x85\xa3\x4a\xf4\xab\xd1\xef\x4e\x46\x14\x2d\xca\x4b\xed\x5a\x87\xb6\x39\xe2\x27\x7b\xe8\xd7\x20\xdd\x95\x3e\x8f\x3e\x93\xf1\x99\xe4\xa3\xda\x8b\x4b\xb7\xbd\xdd\x6f\x87\xbb\xcf\xdb\xc5\xe2\xf9\x8b\xc4\x27\x05\xf2\x4e\xa8\xc1\x68\x84\xde\x78\xd9\xcf\x95\x4c\x02\x15\x91\x7d\x63\x13\x99\xe0\x12\x19\x8f\x49\x65\x25\x50\xc2\x98\xa5\x2c\x3b\x59\x46\x11\x8a\xee\x6f\x87\x21\x85\xab\xb8\x33\xbc\x33\x3c\x9a\x50\x64\x62\xf5\x81\xfc\xde\x5f\xd0\xf2\xc5\x53\xca\xa3\xe1\x58\x88\xa5\x6d\x69\x05\x8d\xc8\x80\x2d\xfa\x91\x12\xa8\x9f\x4c\x10\x7b\xaa\xa8\xde\x61\x3a\xe5\x6b\xbd\x8a\x3b\x0e\xd9\x8d\x2c\xeb\x87\xdf\xea\x55\x6c\x52\x4c\xfe\xe8\x7b\x84\x6d\xf1\x7b\xe6\x3d\xcb\x72\x19\x8b\xdd\xb4\x69\xc6\x13\x4b\x4d\x46\x96\xa1\x36\x53\x29\x63\x0c\x81\x1c\xba\x2f\xd5\x1a\xd6\x7d\x31\x35\xd6\xcc\xdc\x03\xf4\x28\x15\xe2\x90\xe5\x6c\x85\x91\xab\x97\x05\x76\x14\x2c\xcb\x46\xce\x63\x22\x13\x49\x08\xba\x93\x57\x83\xcc\x20\x08\x69\xd0\x9d\x7e\x15\x5b\xb4\xba\x05\x94\xbc\x9a\xba\xe3\x1d\x8f\xce\x2a\x79\xad\xfa\xd8\xcd\xef\xe0\x95\x90\x08\xb5\xf8\x48\x52\xed\xe8\x6c\x21\x4e\x11\xad\x4a\xa3\x31\xc8\xbb\x6c\x31\x4c\x8e\x78\x63\x3a\x3f\x8f\x9b\xb7\xb2\xf4\xc2\x3f\xda\xbd\x61\x5b\x30\xaf\x49\xd6\x37\x93\x61\xf6\x4d\xfe\x91\xbf\xa6\xf1\x27\xdc\x23\xf2\x63\xc8\x4d\x4a\x31\xfb\x7d\x7f\x31\x25\xd2\x1f\x9a\x3e\xd7\x95\xc0\x1b\xbd\x96\xd6\xab\xbd\xb8\x6d\x77\xdb\xeb\xfb\xb6\xd8\xb3\xe7\x58\x1d\xd9\xb3\xa5\x26\x3d\xf7\xd3\x35\x17\x88\xe5\x2e\x73\x81\x92\x95\x45\xb3\x54\x74\x56\xc9\xa5\x7e\x6e\x13\x0e\x75\x2a\x54\xb1\xca\x51\x0e\x26\x3b\x6e\xc6\xe1\x9b\xc7\xa5\xe7\x2c\xb1\xcb\xe4\x43\x68\x3e\x32\x09\x69\x48\x4e\x86\xe3\xb0\xc9\x1d\x48\x90\x1c\xd3\x58\x5a\xc5\xe9\x4d\xb2\x8f\xb3\x1c\x99\x32\xfa\x44\x3e\x51\x4e\x94\xfa\x53\x3c\x94\xf2\xb1\x34\xad\x42\x6a\x18\x85\x83\xb7\x24\x0d\xc8\x71\x6f\xd2\xa2\xf1\x21\x28\x0d\x60\xf9\x07\x37\xba\x95\x11\xc9\x21\xb3\x76\x33\x1a\xb9\x5f\xe5\xbf\x20\x24\xef\x19\x12\xde\xae\xef\x17\xf3\x19\x2f\x11\x70\x39\x24\xa5\x54\xed\x01\xc9\xac\x9a\x20\x24\x33\x09\x0d\x8a\x61\x90\x3b\x2e\x5a\x3b\x32\x99\x4c\xd2\x43\xdc\xcd\xd2\x57\xc6\x06\xf6\x98\x5c\x8f\xef\x1c\xae\xe2\x28\x2c\x87\x2c\x8c\x4c\xdd\x60\x42\xa8\xe4\x7c\xd2\x2f\xc6\x79\xa1\x2c\x4e\x06\x8f\x12\x86\xdd\x28\x75\x59\x3d\x13\xc4\x41\x49\x89\x6c\xf8\x88\x73\x96\xc8\x91\xb3\xd2\x8b\x68\xad\x74\x2b\x90\x8f\x61\x34\x4e\x0e\x87\x88\x87\x14\x64\xf9\x7c\xa6\x98\x28\xa4\x21\x5a\x47\xd9\x0f\x42\x71\x43\x8c\xa3\x30\x3e\x4c\x41\xfe\x95\x7b\xd2\x04\xc6\x23\x13\x62\xdc\xa0\xac\xc9\x7e\x8c\x89\x8c\xdc\xa5\x64\x42\x7a\x76\x76\x7f\xda\x7e\xfa\xfc\x94\xf3\xfc\x60\xed\x92\xb5\x3e\xbe\x24\xa5\x7b\xde\x0d\xde\x26\x72\x35\x0f\x26\x38\x47\xc9\x0d\x86\x4b\x25\x5f\xfa\x17\x83\x6f\xf2\xc8\x24\x2d\x6b\x50\x38\xcb\x79\x72\x3c\xf8\x5c\x88\xe5\x7a\xc8\x72\xb2\x6a\x7d\xfc\xda\xc5\x93\x4b\x28\xb0\x7c\xfe\x96\x8b\xb5\xf9\xa6\xab\xf5\xfa\xc5\xfa\xf2\xb0\x5d\x1e\x85\xbc\x58\x26\x57\xec\xb4\x4c\xae\x58\x62\x9f\x41\xdd\xad\x5c\x83\x20\xfd\x5c\x32\x18\x01\xf9\x9e\xcb\xce\x14\x19\x50\xd1\xab\x0d\xbf\xe6\xd2\xb4\x28\x17\x79\xb7\x44\x2a\xf2\x07\xb8\x39\x9d\xa8\xe8\x5a\x2c\x4a\x88\x5b\x05\xb7\xc7\x1e\x44\x5d\xce\x0b\x7b\x10\x83\x42\x5e\x08\x27\xbb\xd2\xe4\x8b\x90\xb8\x0c\x72\xea\xf5\xca\x90\xc9\xae\xca\x77\xa2\x2e\xe1\x90\xb4\x7a\xb9\x78\x9a\xfe\x24\x6d\x3e\xbe\x65\xeb\xe4\xe2\x73\x20\x2b\x1c\x85\xd1\x61\xbd\x9c\x33\x98\x2f\x7c\xf4\x1f\x37\xd3\x9f\xac\x17\xa2\x96\xd4\x82\xc7\xdf\x8f\x0b\x1d\xbf\xdf\x8e\xab\xbe\xb8\x1e\x1f\x6e\x86\x4f\x8b\xf5\x58\x4a\x92\xd5\x4d\xeb\xe1\x4b\x20\x93\xc2\x5e\xb9\x3c\xd9\xdb\x2a\xc6\xa8\x68\xb3\x3b\xb9\x05\x54\x2c\xea\xf2\xd0\x7e\x62\x0c\x5d\xa2\x2e\x21\x75\x01\x49\x7e\x9f\xe4\x28\x15\xa3\x42\x7c\x44\x43\x22\x15\x7d\x97\x86\xb2\xbd\x38\xa2\xcd\xb7\x69\x49\x64\x35\x4c\x5e\x64\xb7\xda\x14\x78\xbe\xf5\x96\xf4\x95\x65\x4b\xf2\xca\xfa\x98\x84\x29\xf8\x16\xb3\xb7\x79\x66\x50\xc2\xbf\x7c\x97\x1d\x81\xe9\x93\x95\xfa\xcd\xa7\x0f\x63\xea\x9b\x6f\xf3\x1b\x0f\x4a\x9a\x7a\x66\xfb\x7d\xc3\x96\x5e\xb7\x29\x36\x5f\xdd\x56\x05\xe7\xa6\x7a\x50\xe5\xa4\xce\x30\xb5\xc9\xda\x73\x4c\xad\xbe\xb8\x64\x6a\xe5\x95\x57\x33\xb5\x6d\xf7\xd3\x70\x7d\xff\x71\x29\x8b\x2d\xb5\x8a\x07\x1e\x21\xa7\x42\x91\xdd\xde\xf8\x12\xd6\x65\xda\x1d\x76\x96\x3c\x98\x04\xdb\x26\x25\xaa\xdd\xeb\x2b\xd1\x11\xfe\x6c\x78\xb6\x93\xc2\x28\xab\x6f\x37\xad\xec\x11\x0d\xc9\x4d\xf7\xdb\xb7\x04\xee\xe4\xf2\x98\x36\xdf\xb2\xa9\xef\x32\xaa\xcb\x0b\xbf\x58\xf2\xeb\x0b\xa2\x4c\x64\x47\xae\xc8\xbe\xad\xa0\x18\xc2\x62\xa9\x96\x06\xc2\x8a\x71\x65\x67\xbc\xb3\xa3\x81\x1a\x47\x7e\x72\xa5\x49\x89\x54\xf6\xfa\x4a\xb0\x84\x3f\x1b\x9e\x41\x4b\xb8\xa2\xf2\x41\x43\xc5\xda\xdf\xbe\x21\x68\x83\x5e\x30\xa4\xcd\xb7\x19\x53\x57\x17\x7e\x8f\x41\x7d\xcb\xe9\xdb\x9c\x6f\x4a\xe8\xe6\x77\xd9\x12\x18\xd4\x77\x9a\x3f\x19\xd4\x34\x7f\x9b\xdf\xbe\xa9\xef\x32\xaa\xe7\xe8\xff\xcd\xc3\x52\xad\xf1\xf3\xff\xbf\x68\xc1\x4b\xf6\x72\x4d\xaf\xa1\x05\x35\xfd\xcd\x69\xc1\xf1\x5e\xbe\x30\xa8\x57\xd0\x82\x73\x83\x7a\xd9\x5e\x7e\x4d\x5b\xe7\x9a\xba\xb4\x97\xef\xfe\xbc\xd8\xc6\xef\x2e\x6a\x94\x33\x53\xcd\xf6\xb4\xbb\x83\xc9\x2e\x90\xfc\x33\x18\xf6\xc2\x0b\x42\xb3\x50\xa6\xe7\xe8\x8c\xf6\x5f\x0b\xb0\x4f\x83\xf1\xc9\x91\x4f\x0e\x05\x7b\xd9\x84\x3e\xa7\x32\xf4\x42\xa3\x3e\xd2\x91\x6b\x3d\x83\x13\x21\xd9\xd5\x38\xa4\x98\x28\xc5\xbc\x56\x66\xee\x44\xaf\xf7\x05\x13\x71\xbf\xfd\x74\xb7\x5f\xb2\x74\xef\x17\x93\x11\x6c\x99\xf5\x09\xb5\x90\xe3\xf0\x74\x32\x9e\x9d\x02\x19\x82\xab\x41\xbf\xc8\x3f\xcf\x4d\xd6\xea\x1c\x9d\xd4\x32\x55\xf2\xfa\x89\x0c\x53\x45\x2f\x9f\xc8\x4d\x9b\xc7\x7a\x52\x89\xe9\xb5\xbc\x70\xca\x1f\xef\xee\x3e\xfd\x74\x73\xbb\x98\xf3\xa5\x91\xf7\x48\xd5\x66\x5d\xa0\xec\xd3\xde\xa4\xd0\xed\x06\x07\xb5\x7d\x3b\x28\xf3\x77\xc6\xb9\xb0\x97\x7f\x2e\x97\x4a\xe1\xc4\x0e\x30\x9b\x01\xe4\xaf\xbd\x73\x01\xf5\x5c\x28\x82\x5e\x74\xe3\xc5\xc1\x76\x21\x55\x4b\xfb\xda\xfc\xea\xe3\x14\x8e\xec\x1a\x66\x32\x6c\xa0\x09\x74\x5b\xde\xdf\x9c\x2d\xf2\xf8\x3b\x31\xcc\x79\x35\x7b\x08\xe7\x8c\x69\x51\x8d\x71\xbe\x8a\xbf\xca\x40\xb7\xb9\x6c\xa1\xfb\x5d\x1a\xe8\xb0\x99\xef\xbe\x2c\xb8\x02\x5e\x7a\x07\x7c\xcd\x6e\x8e\x39\x7d\xd5\x2e\x94\xf7\x7e\x77\x9b\x68\xf3\x5d\x76\xd1\xef\x74\x13\x6d\x2e\x5e\xc7\x1f\x3e\x2c\x36\xd0\xa9\x0b\x45\x0a\x56\xb5\xbe\x89\x4c\x62\x21\xb9\xa5\x19\x96\xd9\x74\x41\x86\x0c\x5d\x4a\x0a\x4d\x1e\x48\x09\xfd\x82\xcf\x10\x09\x4f\xa4\x34\x0a\x27\x26\x57\x0b\x16\x5f\xb8\x1e\x28\xac\x7d\x73\x6a\xcd\xca\x76\x94\xe9\x76\x04\x73\x97\x8b\xad\xe8\x4c\xd8\x51\xad\xb9\xb0\xf8\x92\xa9\x30\x12\x04\x6c\xaa\x02\xf3\x90\xb4\x9b\x65\x75\xa3\x6a\x91\x0b\x77\x93\x9c\x71\xba\xde\x6c\x03\x05\xb5\x27\x55\x58\xd1\x6c\x55\xe5\x36\xd6\x22\x79\x75\xaf\xa8\x42\x07\x50\x40\x6e\x57\x79\x82\xef\xfa\x15\x85\x50\xa6\xbf\xad\x2f\xa3\x56\x94\x93\x41\x39\x26\x6d\xd8\xc9\x8d\xaa\xdd\xe1\xc2\xa3\x74\x1e\x63\x90\x17\xa5\xcf\x0d\x43\x91\x91\x8c\x9e\x29\x78\x2a\x81\xa2\x6d\x55\xba\x1c\x47\x0e\x49\xed\x05\xae\x5b\x0a\xb3\x6d\x45\xb7\x68\xf0\x8f\x30\x58\x0a\x53\x20\x67\xd8\xae\x6b\x26\xda\xa9\x3a\x42\xcb\x9d\xaa\x23\xda\xcb\xb5\x10\x0f\x37\x1f\x6f\x9f\xba\x33\x7d\xb0\x7c\xce\xcd\x0a\x7e\x85\x31\x51\x4d\x33\xa3\xc9\x81\x0c\xec\x3f\xcd\x38\x58\xa6\xf1\x40\x7e\x96\x4d\xec\xd5\x60\xee\x7c\x67\x32\x39\x90\xfc\xd5\xe4\xc1\x4e\x7e\x42\x39\xbc\xd8\x50\xcb\xe3\xdb\x24\x8c\xa8\xdc\xb7\x5e\x0d\x50\x2f\x6d\x40\x8b\xbf\xa0\x01\x10\xca\x50\xec\x1e\x84\xf0\xe5\x2d\x6c\xf6\x5a\xfe\x25\x4d\x04\x5b\xa8\xa4\xb0\x07\xcf\xfd\x8a\x41\x68\xf1\x97\xb4\xa0\x1c\x7f\x96\x85\x08\xf9\x75\x2b\xa1\xe5\x9f\x6f\xe4\xd2\xc6\x79\x77\xf7\x71\xb1\x6b\xfc\x1f\x8e\xaf\x22\xdd\x99\x6c\x13\x99\x8c\xb3\xd2\xe4\xf8\x52\x8e\xfa\x69\xe4\x4b\xee\x67\x7a\xfa\x9c\x1e\xf4\x82\xfa\xde\xa3\x12\xab\x1c\xaa\x30\x33\x3a\x54\x47\xa6\xf4\xa1\xe2\xaa\x1b\x0c\xee\x1c\x57\x60\xa4\x14\x4a\x6f\x7c\x25\x53\x79\xf4\xa0\x33\xc4\x36\x4b\xb9\x32\xb2\xbe\x2e\x1f\x42\xc4\x31\xd2\xd1\x38\x25\xab\x06\x37\x80\x95\x43\x26\x32\x08\x8f\x52\x54\xd5\xcb\x55\x18\xe8\x42\x6c\xcb\x08\xdb\x3a\x26\x8a\xa1\x97\x1c\x0d\x2b\x67\x2b\x14\x54\x06\x92\x46\x93\x95\x05\xc7\x6f\x65\x87\x7e\x4f\x2b\x21\xf4\x41\xbd\x60\xb8\x5b\xfa\x07\x29\xcb\x25\x8c\x26\x54\x92\xba\xe4\x18\xe7\xc1\x70\x80\xe5\x3c\xc3\x53\x01\x5d\x15\x22\x39\x57\x14\x89\xd1\xc3\x44\x2c\x6b\xcf\x49\x48\x57\x91\xb6\xa5\x78\x26\xe7\x41\xb9\xa8\xc8\x37\x96\xa6\x28\x32\x25\xb9\x5a\x63\xa0\x6c\x85\xc0\xba\x4c\xdd\xc2\x5b\x65\x84\xc5\x93\xcb\x60\x0e\x1c\xec\xf6\x6a\xe7\x93\x0a\xc0\xc2\xba\x43\x85\x8d\x2b\xb1\xdf\x0c\x5c\x12\xb9\x22\x9b\x27\x24\xf2\x95\x64\xcb\x05\x4b\x31\xa3\xe7\x70\x98\x90\xde\xcb\x8a\xb1\x25\xe5\x61\x2d\x76\xde\xe8\xe0\x07\x01\x4a\xcc\x36\xc3\x64\x79\x15\x29\x33\xec\x9c\xd4\x2d\x01\x76\x60\xf8\x0e\xda\x3c\x86\x20\xdb\xb3\x32\xc9\x32\x42\x14\x21\x57\x49\xa6\x3b\x8b\x88\x20\x7f\x96\x9d\x74\x52\x77\x32\xae\x14\xdc\x09\x3c\x39\x65\x0c\x0e\xde\x11\x61\x0c\xb2\x4e\x49\xd5\xb5\x79\xe0\x20\x1b\x22\x8f\x55\xfa\x15\xa8\xf6\xe6\x71\x75\x8c\x8c\x35\x95\xd1\x26\xf9\x21\xdb\x31\xcb\xe6\x93\x05\x56\x0d\xd5\xbc\x19\x47\xc3\x51\xbd\x1d\x22\x93\xc1\x3c\x63\x27\x62\xa6\x1d\xac\xeb\x24\x2b\x5a\xcb\xc0\x70\x57\x2f\xd2\x90\x71\x04\x07\x09\x99\x69\x54\xf3\x8c\x69\xb4\xdd\x2f\x7c\x6c\x3f\x58\x5e\xba\xc1\x1c\x64\xcb\x59\x8d\x73\x96\xde\x41\x72\x79\x4a\x27\x56\xa8\x9d\x08\x1a\x0b\x52\x94\x53\xf9\x2d\xab\x07\x31\xf9\xba\xfa\x37\x2f\x6b\x00\x8c\x6b\xda\xd7\x50\xe0\x14\xbb\x37\x35\x94\xee\x25\x91\x27\x7e\x21\xe8\x6d\xdd\xd4\x8f\xa5\x5c\xc5\x5d\xf1\x6e\x94\x6d\x82\x5f\xca\x54\xc6\xe5\x96\xc1\x57\x3c\xbe\x0d\xc5\x92\xd4\xbd\x0b\xa1\x0c\x26\x14\x62\xce\x72\x38\x65\x3b\x65\x62\xde\xc1\xf7\x0b\x47\xdb\xe1\x27\xc3\xdc\xaf\x0e\xf5\xbb\xea\x7c\xfc\x62\xb8\x47\x5d\x2c\xbe\x5b\xaf\x82\x57\x8a\xe2\xd5\xc9\x74\x67\x8a\x77\x9b\x63\x0b\x56\x04\xc9\x09\x99\x38\xf0\x55\xdc\xd7\xe8\xa4\xa2\x95\x79\x53\xfe\xff\x78\xd6\xbc\xad\x43\xb6\xc4\x29\x0b\x15\xf1\x99\x62\xa0\xe4\x5b\xae\xe4\xd2\x41\xfb\x25\x6c\xb4\x4b\x42\x59\x4c\xf2\x52\xde\x70\xca\xf2\xee\xeb\x2e\x96\x1d\xc2\x55\x9e\xec\xee\x8b\x4e\x49\x32\x61\x31\x84\xbd\x09\xc5\x76\x5b\xe0\xc2\xd7\xd9\x97\xb0\xf7\x45\x24\xf0\x98\x60\xf6\xc1\x4f\x6b\xee\xcf\x7b\xad\x85\x09\x2c\x6c\xc3\xbf\x43\xcc\x91\x42\x0e\xf8\x34\x21\x87\x51\x98\x65\x92\x43\x2e\x42\xac\x67\x4a\x72\x05\x25\x27\xcc\xea\x28\xc4\xa0\x76\xaf\x27\x59\xe4\x59\xd6\x62\xca\x83\x49\xd5\x51\xcc\xfd\x8b\x89\x39\x8f\x33\x01\x11\x52\x71\x4c\x7b\x19\x55\x6a\x8d\x13\x45\x07\x39\xc3\xa5\xb1\x19\x32\x57\x8a\xb5\x0a\x0f\xed\xe0\x4f\xe6\x12\x5c\xcc\x5c\x1a\x1c\xae\x28\x1b\xf6\x5c\xe3\x4b\xee\xfa\xbd\x09\xb6\x0c\x8e\x71\x7d\x39\x5c\x92\xb2\x0b\xbb\x2b\x1b\x6e\xb3\xe7\xe8\xd2\x87\x9b\x61\xfb\xd3\xf5\xb0\x14\x5a\xd3\xcc\x16\x84\x24\x95\xc6\x59\x03\x14\x84\xbb\x4f\x4d\xae\x70\xe8\x7e\x39\x9e\xd5\x5d\xc2\xea\xba\xaa\xbc\x4c\xd6\x2e\xb5\x97\xa5\x26\xdd\x95\x05\x8e\xa9\x98\x96\x50\x26\x6f\x97\x20\xd4\xc4\xe7\xb4\xf3\x90\x84\xad\x5c\x23\x72\xda\x03\x0f\xc6\xb3\x27\xcf\x1e\xab\x02\x5f\x26\x26\xe7\x26\x1f\x09\x76\x65\x2f\x55\xec\x4c\xe0\xb4\xda\x9d\xc0\x09\x06\xff\x1e\x52\xc3\xae\x3c\x23\xa5\xb5\x9b\x95\xfd\x9e\xff\x70\xe4\xc1\x58\xab\xdb\x9b\xa0\xe7\x7d\x49\x0c\xa0\xaa\x7e\xc1\x21\x16\x96\xda\xc7\x05\xe3\xb7\x4e\x11\x3d\xbb\x89\x7f\xc3\x1a\x09\x57\xe0\xe5\x80\x14\x91\x88\x9a\x48\xa9\x24\x3f\xc8\xa7\x99\x9e\x18\x3c\x92\x5f\xa4\xf0\xf4\x39\x3f\x99\xca\xf6\x77\xa7\xba\xb4\xee\xc7\x59\x20\xc5\x95\xea\x2c\xf8\x30\x91\x79\x8b\x4a\xdf\x59\x35\x0d\x19\xba\x0a\xfc\x88\x02\xd3\x77\x7c\xd5\x42\xbd\x8c\xbc\xad\x2f\x1f\xbe\x1d\x17\x38\xbc\x77\x54\xdb\x49\x33\x87\xf6\x2f\x2b\x7b\xef\xae\xdf\x2f\x16\xf0\x92\xab\x12\x33\x33\xc5\x60\xf7\x61\x90\x33\xaf\x0b\x48\xf0\xe7\x62\xea\xca\x1a\xa8\x5f\x76\xca\x4a\x76\xea\xe1\xbb\x63\x31\x4e\xa5\x03\xd3\x28\x5c\xae\x5c\x14\x72\xfd\x81\x0f\xd1\xcd\x2e\x94\xa7\xec\x5c\x08\x23\xb8\x57\xc7\x54\x5a\x21\x67\x1f\xdf\x72\xc9\x96\xb2\xb0\x85\xea\x28\x28\xbc\xb9\xdf\x99\x6c\x67\x05\x22\x94\x41\x85\x7a\x03\x16\x31\x02\xe7\x7a\xe7\x8e\x1c\x9f\x57\x7a\x07\x16\x35\x6d\xb4\x6f\x1e\x7d\x53\x75\x52\x57\x43\x49\xab\xd2\x05\x8b\x8e\xa0\x57\x31\x10\xb8\xd9\x34\x04\xb9\x22\x6d\x08\xa3\xec\x12\x82\xbb\x37\x02\x4c\xc2\xce\xfb\x7a\xa1\x55\x06\xc1\x77\xda\x68\x20\x15\x12\xd0\xe4\x8e\x53\x3a\x8c\x52\xc6\xe8\x51\xbc\x97\x5e\x1b\xa1\x34\x05\x27\x6b\x70\xa0\xa1\xa9\x6f\x3b\xfa\x66\xd0\x39\xf9\x21\x39\x65\x54\xf9\xb2\x87\xe1\xfb\xbb\x5f\x6e\x87\xbb\xeb\xf7\xab\x24\xf2\x92\xb3\x87\x7a\x1a\xd6\x35\xd7\xa2\xf6\xc4\xf5\xa6\x9d\xf8\xc0\xb4\x53\xd7\x17\xc4\xcc\xfc\xfa\x6a\x52\x0a\x14\x38\xcd\xe2\xf9\x2a\xb1\x86\x4b\xf8\x0a\x75\xd4\x77\x9e\xd0\xea\x90\xe2\xc0\x1e\x8a\xbe\xb4\x19\x63\x21\x13\x95\xb9\x37\x31\x35\xf9\x8c\x69\x32\x3d\xec\x42\x5a\x0d\x54\x79\xcb\x5e\x44\x8f\x12\x47\x59\x9a\xa0\x6b\x6f\xb2\x1d\x84\x6e\x12\x88\xa7\x3a\x46\xd7\x83\xb7\x12\x86\xa5\x05\xf0\xdc\x33\xae\x01\x16\xc9\x48\xaa\xf1\x72\xb9\x92\xaf\x3b\x61\x19\x94\xfc\xaa\x97\xd1\x1c\x1c\x25\x67\x63\x19\x68\x05\x5a\x8d\x67\x41\x4e\x5f\xac\x22\x8a\xbe\x68\x6b\x2c\xb6\xc5\xf5\x7c\x73\xb2\xb3\x94\x6c\x99\xc4\x0d\xf0\x8c\x41\x2e\x2b\xa9\x9d\xe5\x40\x70\xbf\x18\x84\x8c\x63\xff\x0e\xb2\x42\x9d\xba\x44\x48\x95\x99\x7c\x1c\x85\x10\x90\xb7\xe4\xac\x30\x02\x6b\x57\xc2\x3a\x7f\xe0\xa3\x3b\xa3\x8a\x80\x93\x10\xa4\x57\xd6\x20\x8e\x6f\x76\x2b\x6c\xda\xb9\xab\xe7\xf1\x44\x81\xf9\xf7\x74\x5d\x7c\xf9\xbc\xba\xd4\x3f\x1f\x96\x9a\x0b\xa5\x64\xc1\x46\x0a\x0d\xf5\x18\x20\x94\x39\x58\x85\x57\xe9\xc4\x84\xcb\x5f\x7d\xa4\x82\x3c\x24\xf2\x41\x76\x91\x6c\x22\x66\xec\x02\xaa\x0d\x95\x0e\x1e\xcd\x3b\x3b\x82\xa8\x26\x11\x86\x7c\xfc\x4d\xd6\x7b\xd3\xa6\x75\xfe\xff\xdc\x7a\xdf\xdc\xfe\x7c\xf7\x97\xc5\x72\xbf\x3b\x52\x95\x79\x8a\xc2\x8a\x32\x2e\x5a\x99\xaf\x49\x3f\x24\x5f\x32\xae\x52\x76\x14\xaa\x30\x96\xb6\xe8\x5f\x26\x40\x76\x23\xd3\xcb\x9b\xf9\x05\x93\xe5\xe2\xe2\x34\x54\xbd\x09\x45\x40\xeb\xb3\x17\x43\x12\x21\xc9\x9d\x13\x92\x10\xb3\xb9\x2e\x12\xc9\x3b\x72\xd1\x45\x62\xe7\x07\xe7\x0b\xc5\x08\x31\xc1\x45\x04\x7f\x52\x70\x2d\xc2\xad\x3d\x43\x30\x46\x25\x51\x5d\xe2\x73\xf3\x1a\xfa\xe5\xf0\xa2\x89\xd1\x6d\x46\x17\x61\x72\x80\x8e\xe5\x19\x89\xf0\xf3\x70\xfd\xd7\x9f\xde\xdd\xdc\xbf\x1b\x96\x8c\xf2\xfb\xc3\xb1\x29\x93\xca\x11\x8a\x3c\x2f\xc2\x55\x1c\x4c\x0c\xca\x24\xa9\x6e\xa6\xea\x83\x0a\x8d\x1d\x36\x37\x69\x34\x1b\xeb\x93\x98\xba\x42\xdd\x67\xc2\x9f\xa3\x47\x7c\x2b\x0c\x4c\xc3\x5c\x97\xd4\xc1\x85\xb4\x8d\x7f\x67\x97\x5f\xc7\x2e\x6f\x3f\x6f\xaf\x97\x1c\xd0\xf6\x34\xb6\x17\xde\x99\x5d\xe6\x59\xdb\xaa\xb8\xb1\x71\xbf\x9a\x58\x29\xc8\xf2\xe2\xc6\xe6\x40\xa9\x42\x63\xa8\x8a\xc7\x20\x5f\x10\x36\x55\x11\xad\x01\x7b\x91\xed\xc6\xa2\xae\xdb\x31\xc7\x66\xa2\x66\x4e\x2c\x48\xe6\xd8\xb6\xf4\x22\x3b\xd3\xb1\x99\x69\x64\x44\xcc\x38\x17\x29\xba\xc6\x59\xfa\x97\x47\xa8\x67\x9d\x27\x76\x42\x58\x55\xcf\x58\x37\x03\xfa\x29\xbd\xae\x22\x7b\xeb\xc4\xa2\x7b\x79\x8e\x24\xd4\x48\x13\x44\x40\xba\xa4\x02\x3e\xd6\xd7\x65\x32\x59\x0b\x44\xec\xeb\xe7\xcc\x74\xad\x7f\x4c\x3f\x4f\xe5\xf4\xbd\x91\x43\x96\x7e\x95\x70\x30\x57\x6a\x2c\x22\xc7\x74\x25\xcc\x9a\x5c\x1e\x75\x74\x72\x6d\x50\x96\x5d\x3f\x7a\xd5\x6a\xc9\x47\xbc\xcc\xed\xdc\x6f\x3f\xdc\x6f\x97\x1a\x4c\x77\x64\x9a\x64\xa6\xae\xcb\x91\x36\xa1\x15\xc1\x70\xc1\xf4\xc9\x3f\xc1\xab\xa5\x30\xcb\x61\x49\x09\x23\x57\x49\xc2\x15\x07\x73\xab\x8c\x1d\x76\xbd\x98\x07\xa3\x2a\x5c\x57\xd5\x38\xb0\x60\x02\x67\x32\xb7\xc6\xe4\xc9\x8f\xe7\xa3\xe9\x07\xd3\x97\x2d\x8f\x19\x3a\x5f\xe2\x04\x9d\xbd\x6b\x5c\x64\xdf\x89\xc8\x01\x8e\x29\x5a\x4a\xb1\x71\x49\xc4\x19\x57\x2d\x67\x8a\x9e\x98\xf3\x46\x78\x32\x0f\x9e\xcc\x2b\x8b\x75\xde\xc6\xfe\xf2\xc3\x71\x2e\xb0\xff\xe2\xe1\xf0\xdd\xb0\x20\x7c\x3b\xec\x34\x52\x7b\xee\xec\xa5\xb0\xd6\x11\x52\x52\x56\xe6\xc4\x77\xe6\xc4\x0b\x8f\x51\x2f\xb8\x14\xe4\x31\x45\x92\x85\x73\xd9\x92\xae\x1d\x94\xa3\xb2\x72\x9b\x51\x57\xce\x95\x30\xef\xb5\xc5\x4e\xe3\xaa\x6b\x42\x2a\x8e\x1c\xd6\xe1\xe2\x4e\x1b\x6e\x1e\xda\x9a\xb8\x75\x16\x45\x62\x0a\x24\xf2\xd1\x3d\xef\x45\x71\xd1\xdb\xe7\xbc\x13\xc5\x05\x5f\x1d\x8d\x8f\x49\x6a\xfe\xfd\xee\x8d\x6f\xd0\x3a\x8c\x96\x7f\x8b\xa1\x63\x6b\xbf\x68\xe2\xe1\xc6\xf8\x15\xcd\xcb\x7b\x17\x46\xaf\x37\xea\x4b\x26\xff\x37\xe9\x80\xb6\xff\xa2\xe9\xff\x76\xed\x6f\x4e\x3a\x80\xb8\x88\x64\xf7\xc2\xc0\xa1\x8a\xb9\xd2\x36\x37\xf4\x7c\xbc\xfb\xde\xe8\xfb\x5f\x17\x86\x0f\xb3\xb6\x06\xe8\xfc\xe6\x51\xe7\x9b\x17\x45\xe8\x0c\x77\xef\x16\x7e\xad\x6e\x89\x94\xc0\x71\xa6\x20\xce\x52\x4e\x08\x0a\x99\xbc\x1e\x5e\x62\x04\x87\x47\x45\xb7\x46\x01\x93\xa9\x9b\xbb\x5e\xe3\xc9\xab\xaf\x2c\xfc\x93\xa7\x6e\x94\x00\xf8\x04\xcf\xa9\x79\x18\x50\x1d\x3e\x85\xa3\x68\xe0\x2a\x3c\xab\x63\xc7\xce\xbb\xd7\x3a\xff\x7e\x18\xae\x17\x1e\x01\xee\x52\x70\xbe\x47\x28\x96\x5e\xf3\x19\xa1\x7a\xb2\x16\x76\x6f\xd8\xa5\xf4\x2b\xe8\x0f\x5e\x97\xda\x3c\x82\x1a\x89\x19\x1e\x32\x1e\x68\x08\x04\xaf\x30\x38\x85\x01\x1c\xe1\xe0\x1e\xd6\x0e\x5e\x63\xf3\x36\x64\x60\x4a\x40\x5d\xaa\x82\x0a\x0a\x43\xd4\xf2\x75\x02\x64\x18\x8d\x83\x7c\x2c\x13\xe9\x13\x6c\xc5\xd2\x3e\x42\x9f\xd9\xa9\xcb\x90\x70\x95\x70\x38\x2a\x1b\xd9\xc3\x11\x5f\x9b\xe1\x80\x98\x59\x39\x4e\xd5\xa9\x1e\x54\x26\x21\x24\xb0\xb3\x90\x56\x3c\xa4\x95\x15\x99\x2c\x07\x59\x52\xac\x26\xc5\x38\x3a\x16\xde\x37\x57\x0a\x7e\x74\x60\x12\x2c\x05\x18\xf0\xed\xc8\x16\xec\x9c\x05\x63\xd8\x60\xe4\x29\x65\xf4\xaa\x0f\x2b\xf8\x18\xe1\x1b\xc7\x0c\x28\x04\x6e\xcc\x56\x4e\x54\x29\xf2\x6f\x84\x5d\x93\x57\xb8\xa0\xe7\xe0\x1a\xde\x7f\xde\xdd\xdd\x6e\x17\x20\x47\xee\x59\x8c\x81\xa4\x18\x47\x9c\x80\x99\x23\xfb\x32\xa8\x42\x39\xd4\xee\xe9\xe1\xbd\x86\x9b\x17\x4f\xdd\xc7\x8f\x01\x42\xa4\x8c\x83\xfa\x6a\xed\x8d\x3f\xa3\x2d\xf9\x15\x06\x69\x54\x9a\x19\xc1\xd6\xb6\x23\x1a\x54\x79\x1c\xaf\xe2\x80\x70\x39\xe1\x8b\x6b\x84\x6b\x42\xf5\x93\x4c\x58\x84\xf9\x81\x66\x0e\x0e\x71\xb6\x36\xe3\xb1\x0f\xb2\x6c\x09\xfd\x6a\x72\x99\x0a\x18\x94\x80\xf1\x2a\x23\x62\xbf\x16\xd5\x4e\x56\x2f\x8d\x18\x76\xa3\x17\x56\x81\xaa\x87\x4f\x5d\x93\xce\x48\x5f\xf6\xfe\x25\x26\x9e\xd7\xda\xd2\xbd\x3b\x44\xb1\x4b\xf7\xa2\x9f\x7d\x2b\x31\xed\xba\x28\xde\x63\x91\x42\x1d\x65\xd1\x30\xec\x64\xc9\xc3\xa9\x9d\x23\x53\xca\xe4\x2a\x43\x0e\x72\x01\xe1\xe4\x0e\x0c\xb3\x54\x26\xd4\x20\x31\x3e\x4c\x62\x3c\x98\x84\x2b\x18\x96\xa5\x7c\x4b\x59\x76\x30\x5f\xdc\x76\xfb\xbb\xe1\xcb\xa7\xed\x4f\x2b\xce\x8f\x6e\x01\xbb\x90\x53\x39\x8a\xa8\x64\x2e\xe1\x70\xed\x2c\x19\xeb\x59\x65\xec\xbd\x27\xef\xfd\xce\x38\x44\x1c\x2c\xcf\xa6\xc6\x08\x3e\xd5\x16\x27\x37\xf4\x37\xbf\x92\x9f\xed\x43\x7b\x7f\xf7\xcb\xc2\xcf\xdd\x2d\xb1\x0a\x0e\x17\xd2\xef\x66\x70\xfd\x72\x53\x2d\x0d\x4c\xb2\xaa\x21\x0a\x7c\x40\x13\x30\xd5\xab\xa4\x0b\xe1\x4f\xc8\x6e\x3c\xee\x86\x3a\x4e\x49\xf5\xf0\xcb\x04\x85\xc3\xc6\x6f\xae\x92\x8b\xcd\x07\xec\xfb\x4a\x3e\x6d\x1a\x3b\x05\xbd\x32\xf3\x17\x3c\x00\x98\x16\xb6\x3c\x5e\x31\xbd\x06\xa9\x2e\x53\xaf\xbb\xf5\xc6\x0e\x22\x7a\x1c\x33\x74\x9d\x34\xf7\xb3\x4d\xdd\xbf\x8c\x9a\xd8\x97\xed\xcb\xe7\xc5\xa2\x2d\xad\x84\xa7\x31\xbe\xff\xbe\x68\xbf\xe9\xa2\xa9\x51\x7f\x76\x82\xf6\x64\xd4\x87\xd0\x4d\xfe\xde\x86\x4b\xc1\xb8\xfc\xc9\xb8\x72\x37\x59\xce\xd3\x2b\x17\x71\x55\x83\xd1\x18\xe1\x94\x96\x13\x85\x30\xe6\x40\x31\x28\xb8\x12\x31\xc6\x1b\xe0\x37\x9c\x55\xb5\x34\x7f\x9f\x99\x02\x14\x1a\x85\x88\x0a\x4b\xa1\x95\x18\x5f\x09\x8a\x78\x54\xff\x74\x11\x0f\x9e\x72\x71\xe4\xa0\xea\xb0\x43\xd7\xdb\x3c\xa0\xce\xde\x4f\x0a\x74\x0f\xe6\x24\xcb\x62\x62\xb4\xde\x83\xd1\xf3\xc7\xa3\x4d\x4f\x56\xf1\x78\xb4\xa9\x8f\x36\x53\x50\x36\x1e\xb8\x75\xf3\xb7\x31\x24\x99\xfe\xe2\x28\xf2\xc8\xea\xb4\x27\x2c\x8e\x73\xb9\xa5\x4a\xae\xd4\x66\xf4\x13\xa1\xfc\x78\x30\x1a\x9f\x30\x10\x7d\xcb\x48\xd5\xe6\x50\xf7\xe1\xab\xce\x88\x7f\xc9\x8c\x38\x98\xc5\x98\x0e\xc3\x6b\x87\x51\x5f\x3c\xb4\xe3\xbd\x1c\xd4\xc5\x89\x5d\x1a\x6a\x0f\x6e\x76\xd0\x1c\xe0\xc0\xc2\x06\xea\x00\x68\xb0\x63\x57\x3a\xee\x05\x8b\x70\xbb\x7c\xa6\xd1\xb5\xe7\x1e\x3a\xe1\x28\xea\x4e\xfd\x97\xbc\x3a\x32\x19\x5f\xbc\x3e\x2a\x35\xed\x66\xd7\xa6\xfe\x28\xa8\x1b\xf9\x99\x47\x29\x58\xd9\x04\x70\x30\x97\xcb\x1e\x1e\xe4\xbb\x14\xec\xd4\x11\x57\x56\xfb\x01\xaf\xb4\xd5\x67\x9b\xf9\x18\x1d\x1c\xab\xf6\x73\x29\xfd\x49\xbe\x49\x3b\xf3\xf4\x9c\x54\x2e\x7d\x9a\xbd\xde\x9f\x76\x0a\x0d\xaf\x3f\xbc\xb4\x7e\x3f\x5f\xaf\x2f\xe0\xa5\x18\xfb\xe4\x49\x5a\xf0\x7b\x69\x6f\x97\xfc\x1e\x16\x11\x99\xe9\x44\xbc\x33\x22\x47\x05\x9b\x45\x9e\x92\x07\xf9\xf1\x2d\x70\xc0\x76\xc6\x73\x7f\xc0\xd3\x03\x9f\xf3\xfa\x83\xe8\x83\x3c\x48\xbd\xaa\x34\x57\x95\xd2\x99\xaa\xb2\xf3\x67\x1e\x94\xb4\xfe\xa0\x06\xbc\xa1\xe3\xc8\xd3\x38\xb2\x2c\xb0\xb5\xab\x4f\x36\x6f\xd9\xe9\x18\x57\x5e\xf2\xb2\x2b\x56\x9f\x84\x70\xee\x9d\xe4\xa3\x3c\xa9\x41\x9f\xd4\x70\x78\x52\xcb\xfa\x5c\x42\xe4\x5a\x9b\xfe\x8b\xce\x53\x2b\x32\xe7\x6c\x49\x0d\x01\xee\xda\x45\xa5\x3f\x73\x10\xff\xcc\x41\xfe\x3b\x8a\x0f\x6a\xc7\x71\x43\x47\x5f\x8f\x4a\x1c\xde\x9b\x2b\x7b\x7c\xcb\x91\x23\x75\x1c\x17\x6d\x47\x5e\x1c\x4c\xa8\x2c\xf2\x8a\x03\xb9\xd2\x5f\x59\x3e\x47\x29\x65\x67\x1f\xef\xcc\x91\xb2\x48\x8c\xbe\x20\xaa\x27\x05\x90\x39\x6e\x06\x11\x22\xcc\x79\x1f\x38\x2d\x21\x27\xe4\x47\x54\xc4\x22\x2a\x3a\x04\x4f\x59\xa7\xef\x6f\x86\x8c\xfb\x83\x83\xc6\x0b\x55\x8d\x17\xba\xcc\x38\xb7\xeb\x8f\x4b\x49\x6d\x19\xbf\x7b\xf0\x63\xfa\xf7\xf9\x5d\xcc\xef\x5b\x2e\xb5\xbe\xae\xb3\x3e\x75\x23\x16\x87\x26\xaf\x84\x38\x84\x2c\xd2\xb7\x1d\x35\xce\xcb\x67\xaa\x3d\xc6\x47\x5e\xac\x3c\x8d\x29\xe8\x98\xe0\x1c\x2f\x0c\x9a\xb2\x63\x99\xa4\xaf\x3b\xe7\xc2\xd9\xee\x7f\xcd\xee\xf8\xf9\x6e\x19\xdd\xed\x96\x01\xcd\xc7\x72\xbc\xaf\xc4\x36\x96\x11\x5c\x49\x26\xf8\xdf\xb8\x3a\x18\x97\xb1\xf4\x49\xad\x31\x29\x08\xa3\xa3\xe6\x33\xc5\xd5\x54\x45\x4f\xf0\x50\x75\x3a\x3f\x9a\x0c\x86\x8b\x43\x39\x48\x9e\x75\x8a\x05\x1c\x8d\x0b\x04\xb9\x90\xd8\xe5\xd1\x52\x20\x4f\x2e\xb7\x40\x3e\x8f\x4c\x85\x8c\x27\xf5\x61\xf5\xc4\x80\xc1\x24\x96\x9f\x1d\x37\x04\x14\xaa\x47\xed\xf4\x6d\x74\x5e\x26\x34\x44\xaa\x88\x39\xb4\xf8\x1c\x3d\xb1\x55\x7f\x60\xab\xb0\xa0\xae\xc8\x6f\xb0\xe1\xb8\xd2\xe4\x5f\xbf\x19\x1d\x0b\x5f\x14\x1c\x55\xd7\x9c\xec\xde\x91\xa9\xaa\x79\xde\xbb\xd6\x5f\x0b\xc4\x9e\x9c\x23\xaf\xfc\x12\x98\xa7\x51\x3d\xdc\xc0\x98\x6a\x08\x19\x76\x7f\x92\x27\x7d\x04\x6a\xd5\xc5\xd2\x8e\x8e\x0a\x55\xe2\xd2\x58\xe3\x30\x32\x39\x1e\x0b\xdc\x39\x12\xfa\x88\x28\x44\xf2\x32\x2e\x61\x9c\x65\xd8\xd2\x03\x37\x8f\xd7\x27\x62\x40\x84\xe2\x14\x46\xc8\xef\x64\xfc\x28\xfb\x9f\x22\x53\xdd\xe5\xc4\xc2\xbd\x5a\x8d\x2c\x89\x09\xb0\xcd\xec\xad\xac\x5e\xc0\xea\x6d\xb0\x75\x11\x18\x61\x3a\xc4\x9b\xae\x0d\xbb\x72\xd5\x31\xe8\x76\xa6\xa4\x3a\x31\xcc\xd8\xa8\xb1\x9b\x92\x12\xec\x7a\xc1\x8f\x70\x7a\x96\xeb\x1f\x9f\x3b\x59\x6f\x57\xc9\x52\x4c\x04\x4c\x52\x1f\x49\xf8\xe4\xc1\x5b\x4b\xb5\xe4\x31\xcb\xe4\x45\x8a\x59\xf5\x57\x11\xfe\x55\xc1\x3f\xbe\x8d\x59\x8e\x75\x4c\xa3\x09\x34\xf9\x50\x43\xf1\x6c\x55\x69\x98\x6c\x99\xc2\x3a\xba\xca\x50\x57\xdd\x5d\xc5\xc1\x31\xa5\xa0\x4b\x63\xdc\xa4\xf0\xb6\xaa\xee\x96\xf7\x26\x65\x63\x9c\xd5\xe6\x46\x43\x53\x55\x69\x1d\x14\xe7\xe1\x7b\xb4\x7c\xd2\xf0\x73\xe7\x75\x89\xa0\xfe\xc1\xba\x65\x40\xfc\x11\xa8\x21\x27\x78\x47\x4f\xc8\xdd\xb2\xd2\xa3\xf7\x18\x95\x3a\x73\x04\xd6\xed\x64\x92\xb2\xab\xd0\x4d\x79\x19\x77\xff\xb5\x99\xa9\xa0\x1e\xef\x8e\x44\x5a\x26\x80\xdf\xe2\xc9\x03\x3c\x92\x29\xb8\xa0\x5f\x4c\x70\x41\x77\x93\xef\x78\xc1\xd0\xee\xf9\x0e\xd9\x5a\x47\xf9\x1d\x52\x89\x54\x1d\xb8\x69\x6b\xc2\x44\x69\x0f\x84\xa9\xd2\x5f\x5a\x2f\x22\x87\xb1\xca\x00\xea\x8e\x6d\xb8\xcc\x44\x7c\xbe\xbf\xb9\x5d\xda\x08\x3f\x5c\xa0\x6d\xc2\xce\xdb\x5d\xa9\x69\xef\x62\xea\x31\x23\x2e\xa6\x6e\xbf\x0b\xfa\x48\x19\xdf\x73\x90\x1b\xa9\xf3\xb2\x46\xb9\x5c\xb8\xe7\x40\x25\xf7\xab\x9d\x33\x63\x4e\x7b\xa3\x57\xda\x73\x88\x06\x9c\xce\xba\x70\x9e\xb1\x30\x6c\xb4\xe7\x97\x71\x0c\xb4\xf1\xac\x88\xe3\x5d\xf0\xc5\xbf\xf8\x61\x97\xc2\x3e\x02\x42\xed\x89\x9d\x22\x65\xb7\xe2\xb3\x3f\x88\x54\x62\x38\xba\x33\x41\x03\xb2\x02\x29\x8c\xb9\x42\x23\x8b\x73\x02\xad\x41\xec\xb1\xe3\xcf\xf9\xa3\xbc\xbb\xfe\xb4\xbd\xbf\x7e\xba\xfc\x7e\x19\x69\x7f\x60\x7c\x6a\xb2\x54\x52\x98\xbc\x3b\x14\xcd\x1d\x84\x5b\x3d\x26\xf0\x4b\x33\x27\x7f\x1c\x97\xea\x7f\xe8\x77\x94\xd2\x42\x47\x5f\x0f\x25\x8e\xf0\xca\x46\xb6\xb0\x5e\x75\xc3\xd1\x6c\x37\x2a\x55\x17\xbb\x5b\x99\xcc\x6c\x66\x32\x39\x4e\x5e\x5d\xfa\xea\x6c\x7c\x52\x63\xd4\x5e\xdf\x94\x67\xdd\x3a\xa5\xcf\x85\x7b\x18\x22\x13\x1c\x72\x65\x6f\x55\x4a\x73\x7c\x73\xc7\x9c\x8f\x57\x51\x61\xcf\x34\x06\x4a\x11\xed\x65\xa5\xd3\x1c\xbe\x3d\x00\xb9\xd8\x27\xa9\xee\x11\xb3\xc6\xae\x8c\x5c\x22\x59\x3a\x13\xce\xdf\xbe\x31\x6c\xc0\x65\x93\xd5\xdd\xf2\xdc\x7b\xbe\xa4\x93\x93\x6b\x3d\xe7\xc1\x70\x86\x4e\xc4\x0a\x71\xb4\xaa\x02\x27\xe3\x1a\x20\x55\xc9\xb8\x11\x1b\x23\x66\x72\xa3\x29\x99\x1c\xbc\x26\x4a\xa0\x10\xdd\xe3\x5b\x68\x5e\xca\xe0\x28\x57\x21\xb3\x40\xb7\x45\xf0\x9f\xf0\x48\x16\x10\xfd\x13\x5e\x2e\x9c\x6e\x5c\x6d\x9e\x29\x5a\xb9\x2d\x7c\xa6\xc4\x69\x70\xc5\x52\x76\x61\x97\xe3\x2e\xfa\x11\xbe\xe9\x3d\x58\x67\x70\x16\x20\xeb\xe8\x99\xc9\x45\x4d\x8f\x2e\x22\xf3\x82\x5c\xe5\x2e\x07\xd5\x8f\x09\xd5\x8e\x78\x55\x5a\xca\x0e\x20\xe5\x80\x09\x87\xb6\x07\x61\xb3\x19\xab\x2f\xb7\x2c\x8e\x24\x42\x03\x82\xba\x25\x8d\x09\x37\x7a\x92\x52\xdd\x51\xa7\x5b\x61\x26\xe8\x74\x98\xcb\x46\x93\xbc\xfa\x5b\x59\x2a\x42\xc2\x98\xca\x68\xb2\xba\xea\x80\x0b\x6d\x86\x73\x91\x0b\x02\x50\xe6\x81\x72\x19\xd8\x33\x42\x4a\x01\xa8\x2d\x33\x00\x86\x46\x76\xc5\x14\x65\x17\x94\xc5\x49\x1a\x0d\x55\x5a\x25\xe6\x06\xfd\x10\x6c\x0d\xd2\x37\x06\x03\xd5\x4c\x76\xc4\x19\x8c\x25\x82\x3c\x85\x17\x8f\x96\x54\x4b\x6a\x62\x99\x99\x4f\x58\x51\x8c\x22\xf7\x72\x72\x57\x71\xd3\x43\x00\x65\xd6\x14\x8e\x5d\x71\x07\xd4\x7b\x65\x1e\x6b\xcc\xea\x7c\x89\x7b\x6c\x64\x10\x6f\x96\x9a\xc7\x1e\xb2\x2b\x73\x3e\x4a\x4b\x32\x0d\x59\xa5\x8f\x36\x7f\x1b\x8d\xba\xd0\xaa\x87\x64\x43\xbc\x95\x54\x64\x4a\xb7\xce\x30\x0c\x74\xe1\x99\xcb\x7e\x58\x78\x14\xfb\xa5\x93\xcb\x51\x44\x68\x8c\xc4\x51\x38\x3c\x38\x3f\x06\xb8\x42\x8e\x1e\xeb\x22\xff\x7a\x8f\xa8\x31\x69\x3f\x30\x71\xb1\x60\xe2\xe4\x22\x4f\xd2\xbf\x1c\x9a\x49\xc2\x3b\x06\x4c\x31\x00\x0c\x1c\x68\x59\xd7\xd5\x21\x90\xd7\x8d\x26\xeb\xe2\x5b\xb8\x44\x4d\x32\x91\x4e\x71\xac\xd3\x36\xd1\xa9\x2a\xe0\x08\x53\x9e\xb7\x0f\x96\x4f\x63\x78\x55\x6f\xa7\x21\xb5\x8f\x6f\x63\x60\x12\xfe\x34\x38\x00\x55\x5b\x61\x40\xc7\x02\xf8\xf5\x20\x7c\x82\x5a\x2f\xb1\xab\x11\x6a\x2d\xdb\x16\x0c\x14\x07\x04\xec\x42\x23\x5c\x89\xf5\x4e\xcc\x95\x8a\xda\x67\xa9\xc7\x50\x22\x42\x6c\x34\x11\x97\x1f\x8c\x7c\xec\x3b\x12\xb6\x22\x51\xb4\xa0\x17\x92\x6a\x96\xb5\xb7\xa5\x4b\x06\x46\xcd\x75\x21\x21\x3a\xb0\x1e\x1d\xf7\x1a\xe4\xd8\x05\x2a\x91\x38\x35\x39\x97\x0e\xbe\x80\xae\x6f\xf2\x0c\x58\x66\x8f\x3d\x05\x86\x5d\x48\x99\x4a\xc3\x8a\xa6\xb1\x57\xfb\x9e\xcc\x63\x2d\x4e\xf7\xa6\x75\x51\xd8\xce\xd2\x77\x2a\xb6\x39\x36\x16\x77\x1c\x8d\xdc\x90\x72\x41\x4e\xcc\xa6\x23\xaf\xfb\x41\xde\xf0\x63\x2d\xe4\xc8\x07\xab\xb2\x80\xcf\x70\xd7\x50\xce\x4f\xb8\x00\x59\xc8\xfe\x39\x66\x7b\x20\x73\x32\xc1\xca\xe2\x07\xd7\x64\xda\x4c\xe6\x06\x8c\x0e\x78\x23\x22\xc2\x1a\x78\x2b\x1d\xbe\x42\xa9\xb1\x1e\x2f\x11\x7e\xb3\x6b\x2a\x84\x1b\x50\x25\x0d\x44\xd2\xcd\x63\x82\x1d\x19\xb1\xfb\xb2\x9f\x7a\x6b\xa1\xcd\xd9\x22\x3a\xe2\x47\xcf\x7e\xc3\xea\xb9\x5a\xd5\xf7\xd2\xab\x2b\xa7\x48\x05\xea\x03\xdb\x9d\x32\x65\xf4\xc2\xaf\x0b\x37\x21\xcb\x1a\xd4\xff\xd3\x3b\xf2\x4d\x3f\xe6\xcb\xd1\x03\x23\x00\x50\xff\x08\xa7\xba\xec\xd7\xdd\xae\x87\x65\x8e\x1a\xbf\x74\x0c\xb1\x6e\xba\x3e\xb0\x15\xd2\xc0\x99\x4a\x1c\x11\x5c\x8c\xd3\x84\x4b\x4b\xc8\x54\x6d\xb1\xce\x82\x68\x21\x88\x3e\xc4\x96\x47\x96\xa2\x0e\x6a\x73\x39\x93\x11\x1b\x35\x3a\x72\x72\x46\xf6\x4e\x85\x60\x30\xc8\x58\x7b\x98\x5b\xf4\xc2\x6e\x42\x78\x44\xc0\x13\xaa\x64\x3d\x6e\x05\x07\xe7\x00\x03\xe2\xa9\x58\x2b\xb9\xb1\xd3\x9b\xeb\x2a\x8e\xe0\xd3\xe1\xc3\x0a\xba\xeb\x98\x72\xc3\x9f\x70\xb3\x8c\x0a\xac\x00\xd6\x5e\x18\x73\xab\xc1\x28\x6c\x35\xc6\xbe\x67\xf7\x50\x09\xd0\x0b\x11\x35\x3d\xec\x06\xb4\x04\x27\x4e\xf8\x57\xdb\xdd\x5a\x83\x66\x5b\xd0\xdd\xa4\x30\x0c\x6a\x2e\xd7\xa7\x8c\x15\xce\x59\x99\x0b\xb5\x8d\x80\xaa\x62\xb0\x45\xd1\x1f\xaa\x90\xd3\xd4\xc9\x84\x49\xba\xaf\x06\x59\xc1\xa2\xe1\x40\x8a\x47\xe4\x79\x34\xbe\xe7\x45\x48\x64\xaa\x7a\x35\x82\xf2\x61\x03\xa9\x27\x6d\xff\x3a\x1a\x48\xa1\x72\x7b\x0b\xb5\x2e\x09\xa4\x5a\x76\x97\xd3\x44\x27\x0e\x09\x4e\x40\xa3\x35\xe4\x86\x35\xde\xf7\xb2\x8a\x6d\xfb\x97\xf6\xd3\x6e\xbb\xcc\x21\xf6\xc1\xfa\x4b\xae\x32\x9c\x03\x38\x40\x65\x37\x02\xbc\xcf\xa7\xb0\x37\x39\xee\x03\x40\x20\xe4\xda\x1a\x35\xec\x4e\x38\x67\x0d\xc7\x96\x4f\x97\xb4\xc0\xf4\x5c\xc3\xd5\x94\x44\xca\xa5\x88\x68\x76\xdb\x03\x5b\x85\xd6\x7b\x15\xbd\xf4\x51\xeb\x45\x87\xa9\x0a\xad\x01\xf5\x36\x6d\x65\x98\x9b\xef\xad\x4f\x1d\xc3\xa5\x8b\xce\x4a\xc5\x7b\x83\x26\x8a\x7d\x7c\x5b\x58\x6e\x9d\x3c\x44\xb0\x24\xa3\x10\xf7\x48\xb0\xd6\xc4\x11\x27\x54\x4e\xa6\xdb\xc0\x2b\xc9\x8d\xd0\x91\x41\x3d\xa4\x64\xe9\xf0\x75\xe7\xaa\x1f\x93\x06\x39\xe2\x11\xf6\xb1\x85\xe6\xa3\xc1\x9b\xa5\x0a\xa3\x20\xdf\x06\x19\xcf\x88\xba\x43\xaf\x46\x3f\x47\x07\x78\x7a\x59\x59\xef\xc1\x49\x97\xee\x79\x6c\xab\xea\xeb\xa4\x20\xbc\x2e\x0a\xb2\x13\xc8\x16\x8a\xba\x20\xc6\x23\x9c\x9f\xbb\x3b\x8f\x10\x5c\x3f\xf9\x6c\xab\x2d\x2f\x51\x51\xc0\x11\x45\xcc\x47\xba\x8f\x06\x35\x01\xfe\x2e\x64\x0f\x52\xbd\xc5\x81\x61\xa8\x4b\xe4\xae\xd3\x67\xb8\xc5\xf0\x0d\x4e\xd0\xcd\xc0\xd3\x78\x94\x63\x20\x3c\x7e\x51\x50\x3d\x39\x08\x01\x63\x28\xa5\x39\xa4\x41\x50\x17\x9a\x1e\x20\x02\x60\x7e\x29\xa4\xb9\x49\x20\xad\x57\xe8\xe6\x60\x8e\x9d\x4e\x27\x48\x03\xc8\x37\x7c\xd8\x49\x51\x9a\x3a\x2f\x22\xc4\xa3\x0e\x2a\xef\x83\x8b\x03\x77\xc3\x85\x70\x12\x33\xce\x48\xbf\x36\x85\xf5\x97\x53\x11\x35\xdc\xc2\x53\x44\xb0\x4a\x74\xfb\x2a\x87\xd2\x75\xda\x17\xbc\xd2\x16\x57\x5b\x2e\xe4\x94\xe1\x0c\x88\xc7\xf0\x05\xce\x33\xc8\x91\x43\x1e\xb1\x0b\xf2\xb1\x67\x16\x86\xd3\x41\x1f\x07\x15\xd1\xc4\x7d\x70\x57\x93\x79\x72\xa1\x19\xf0\x82\xb2\x32\x88\x97\x4b\xb2\x00\xd3\xc6\x46\xfe\x1d\xd7\xb0\xcc\xae\xab\x21\xd9\xab\x1e\x23\xab\x39\xb4\xe7\x2c\x90\x5b\xd4\x4d\xee\x44\x08\x38\x00\xd7\x98\x28\xc0\x1c\xf7\xfc\x61\xff\xe5\xe6\xfd\x12\xe8\xd9\xc7\x39\xbc\xfb\x45\xc7\xa0\x9f\x02\x5c\xc2\x4e\x93\xf4\x34\x6f\xa7\x5d\xe1\x82\xd0\xb8\xab\xa8\x8a\x1a\x91\x26\x3c\xff\xc6\x7b\x5d\xf5\xb4\xf3\x5e\x27\xaf\x51\xf4\x50\x62\x65\xe2\x2a\xd7\x04\xd8\x35\x21\x93\xde\xf6\x39\x67\x8d\x32\xe1\x8d\xa2\xeb\x20\xfb\x19\x7c\xfb\x4f\x36\x32\x08\x77\x74\x7b\xe5\xaf\x84\x4f\x95\xbf\x43\xeb\xf8\x5f\xb6\x75\xa6\xd1\xff\x5d\xee\xee\x2c\xc2\x09\x77\x1e\x3a\x11\xe3\xfe\xd3\xb4\x1f\x53\xc6\xa9\x38\x4b\x50\xd0\x6d\x65\x1d\xa1\xea\xb0\x5d\x57\xb1\xe0\x77\x29\x12\x42\x63\xca\xbe\x59\xca\x2a\x30\x93\x72\xd0\x50\x04\xbb\xc5\xfe\x0f\x7a\x65\x25\x3f\x09\x6a\xe0\x97\xdc\x94\x89\x07\xb1\xa5\x38\x05\x7c\x72\x0a\x94\x90\xe3\x1c\x84\x95\x53\xf0\x96\x3d\x10\x7e\xa2\xc6\x9b\x83\xe4\x57\x88\x46\x7a\x89\x23\x0f\x1a\x18\x8d\x50\x1b\xd4\x7c\x48\x50\x28\x4b\xa3\x37\x55\xeb\x37\x16\x34\xa8\x5e\x51\x93\xbc\x6d\x66\x7e\xc9\x1c\xaa\xea\x57\x4a\xed\x9e\x0a\x56\xc5\xd1\x39\x6f\x1e\xb9\x39\x12\x0e\xac\x34\x94\x09\x5e\xa7\x58\xdd\x97\x7b\xaa\x13\x47\x3a\xba\xda\x0b\x19\xef\x7b\x00\x9d\xf7\xbd\xaa\xce\xce\x28\x6b\xa4\x9e\x07\x0a\x07\x05\x02\x05\x71\x11\x42\x10\x7a\x85\xbe\x4a\x57\x7d\x22\x6f\x21\x5e\x22\x47\x93\xdc\x94\x9b\x86\x8f\x31\x90\x87\xeb\x84\x6d\x53\xe9\x43\x05\xbd\xce\xae\x29\x9e\x9b\x6c\x73\x3f\x8e\xfb\x36\xf5\x77\x1e\xc2\xae\x0f\xcb\x81\x7b\xe9\xbd\xeb\x63\x3f\xcc\x45\x9f\x9d\x79\xc2\x2e\xd2\xaf\xeb\xe1\xe6\xe3\xed\x4f\xc3\xf6\xc3\x92\x57\x39\x97\x1a\x54\x79\x95\x2a\x23\x71\xc7\xa9\x19\x96\x91\x86\x29\xad\x83\xaf\xcc\x29\x20\x8e\xfd\x94\x50\x7a\xc5\xfb\xb4\x43\xbf\x00\x03\xed\x42\x5b\xae\xd8\x57\xb4\x25\xa5\x57\xdb\x4a\x29\x50\x4d\x76\xa5\xad\xcd\x51\x63\xd1\xaf\x26\xd5\x3c\xd3\x98\x94\x5e\x6d\x4c\xb3\x0b\x85\x70\x79\x64\x22\x84\xbe\xbc\x31\xe8\x50\x5f\xe7\xc3\xab\x7b\xe0\xdd\xf6\xb6\x2d\xd3\x23\xf9\xa5\xcb\xe1\xef\x78\x17\x9c\x49\x76\xba\xde\x94\x14\x7e\xe5\x1e\x98\x5a\xda\x5c\x08\xa3\x5d\x1f\x16\xcc\x2d\x5f\xbd\x07\x52\x78\xc5\xe6\x96\xc2\x5f\xb5\x03\x56\xd2\x1e\x7f\xb0\xfe\x5c\x66\xdf\xef\xbe\x01\x32\x30\x95\xbe\x0f\x19\x90\xb6\xbe\x1b\x19\x50\x90\xc7\xdf\x09\x19\xf8\xb7\x2f\x0f\xed\xe6\xc3\x22\x9b\x9d\x3f\x97\xff\xfa\xf7\xb9\x0d\xbe\x61\x5b\xcf\x6f\x83\x6f\xd8\xd8\xf3\xdb\xe0\x9b\x34\xf6\x5c\x3c\xe5\x62\xf5\x2f\x39\xd4\xb9\x98\x14\xca\x75\xc2\x8a\x3d\x6b\x8e\x54\x8c\x8a\xb3\x21\x3d\xd5\x9d\x8b\x69\xbb\x1c\x2f\x2b\x1d\x40\x48\xdf\xf7\xec\xc0\xe6\x69\x0f\x00\xe0\xf5\xb7\x9a\x02\x4d\xad\xf1\xb2\x45\x00\xc6\xda\x57\x75\xc1\x87\x8b\x00\xf3\x0e\x88\x3e\x39\xfd\x8d\xa7\xe1\x85\x5b\xe1\x95\xd3\xb0\x39\x9d\x87\xe7\x3a\xf1\xc2\xdd\xf0\xab\xd6\xe2\xb9\x3e\xbc\x74\x2d\x9e\xed\xc4\xe6\xeb\x7a\x71\x19\x30\xe5\xfd\xf6\xb6\xad\x0b\x1e\x97\xb2\xe2\xf8\x12\x74\x6e\xa7\xd0\xa6\x33\xc3\x3a\x0e\x6f\x1a\x8c\x2b\x85\x5c\x29\xa3\xa9\x54\x09\xc1\x4e\x4d\xfe\x19\xa6\xdf\x6b\x87\xc4\xf9\x46\x27\x2c\xbb\xf2\x95\xab\x9a\x5d\xb9\x18\xbc\xfb\x8a\xfd\x6d\xcb\xd7\x76\x42\xde\xfc\x36\xdb\xfb\x57\xf5\xe1\x62\x2e\x8b\xd7\xec\xef\x6f\xb9\x1c\xaf\xdb\xde\xeb\x1c\xf5\xa5\x74\x39\x7e\x4e\xaf\x70\x88\xda\xd3\xfd\x6b\xfa\x06\x9e\x01\xc0\x2e\x8c\xa9\x07\x39\xae\x8c\xe9\x28\x48\x70\x98\x6b\x45\xa5\xc7\x90\xe3\xff\xbe\xcf\xff\x7d\x9f\xbf\x68\x9f\x7f\xb8\x7e\xb7\x6d\x37\x9f\xb6\x3f\xed\x6f\xde\x6f\xef\x16\x3b\x7d\xe9\x3a\xfc\x54\x68\x38\x89\x7d\x0b\x4e\xed\x8e\xb1\x9e\x89\xc6\xea\x60\x7e\xd6\x53\xb0\x7e\x2f\xcc\x30\xa6\x04\x76\xca\x33\x7e\x58\x1d\x81\x52\xbd\xb8\xce\xf8\x64\xed\x7b\x42\x13\xae\xb4\xea\x9d\xb5\x03\x74\xe6\x25\x3f\x30\xe9\x4b\x1c\xb4\x63\x6e\xe4\x32\x87\xd9\x75\x70\x4e\x19\xc5\xe6\x15\xf0\x39\x9f\x6f\xde\xb5\x2f\xf7\x8b\xc0\x16\xbf\xf4\xeb\x3c\x38\xac\xa5\x60\xa9\x27\x22\x80\xba\x5f\xd1\xea\x9b\x99\x40\x16\x8d\xa2\x2c\xb6\x0e\xbc\xd8\xfa\x47\xff\x75\x2a\xd5\x5f\x3b\x71\x33\x0c\x45\xf5\x1d\xb2\x87\x86\x8e\x37\x38\x70\x82\x92\xd9\x0e\x91\x1d\x45\x76\xb2\x59\xd5\xf9\xcb\x4e\x99\x55\x2f\xc1\x47\xb0\x9b\x9d\x17\x57\xf1\x23\xa4\x82\x75\xfc\x88\xbd\xbc\xba\x39\x8b\x5d\x71\x9a\xff\xb5\xb7\xf2\xfa\xfc\xaf\xfa\xe2\x37\xca\xff\xfa\x79\x7b\xfb\xee\x66\x91\x80\x23\xd8\xc9\x42\xe4\x93\x27\x3b\x54\x86\xdf\xbf\xf3\x91\x9c\x8f\x03\x82\x07\x2a\xcb\xf1\xc8\xbb\x39\x2a\x8b\x6d\x7e\x7c\x5b\x4a\xa2\xaa\x02\x9f\xba\x88\x00\x5d\x40\xad\x16\x99\x4c\x1e\x4c\x94\xb3\x14\x83\x43\x8e\x02\xfd\x3f\x2c\x6a\x5a\x58\x3e\x46\x94\xe7\x4c\x79\x90\xc2\x52\x36\x93\xfc\x8f\xa5\x01\xef\x00\x4f\x3e\x04\x96\x99\xe3\x34\x18\xf9\x49\xfe\x01\x2a\xf2\x3e\x70\xea\x41\x1b\x93\xaa\xfd\x38\x10\x82\x35\xb0\x3b\x0d\x52\x96\xe4\x75\x46\x0c\x78\x1c\x7d\xd2\xf8\x0b\xf2\x65\xa3\x5e\x85\x9a\x5e\x61\x90\x51\x1b\xe7\x5f\x13\xad\xf0\xe9\xfa\xf3\x4f\x9f\xae\xef\xff\xbc\xd4\x5a\x86\xa5\x7f\xdf\xc1\x41\x03\x48\xf6\xb3\x4b\xe4\xaf\x4f\x5b\x01\xe4\xfa\xc9\x39\xb3\xa3\x39\x70\xae\x9a\xeb\xde\xe4\x1c\x34\x73\x84\xc7\x76\x81\x79\xc5\x75\xc7\x2a\x38\xfc\xe2\x1b\x3c\x80\x11\x73\xef\xe4\xbd\x48\x78\xcd\x7b\xb8\x31\x79\x0f\x34\x29\x4b\x8e\x1d\x71\xb4\xe4\x93\x6b\x3e\xe1\x3b\x3e\x0f\x29\x86\x7c\xba\xec\xcf\x72\xfd\xfe\xdf\xbe\x2c\xc5\xfb\xe0\xfe\x70\x34\x37\x35\xed\xfb\x85\xf6\xd5\xc0\x8f\x7f\xbf\x40\x8e\x6d\xc5\x4b\x3c\x5c\x72\xf7\x11\xea\xa7\x71\xd7\xc8\x02\x62\x29\x55\x00\x0d\x93\x7a\x01\x74\xda\x04\x5f\xaf\xd2\xd4\xd6\xda\x8c\x53\x57\xcf\xd1\x04\xb8\x31\x3a\x26\x4e\x4d\xb1\xe4\x7b\x56\x11\xdf\x53\x4c\x68\x50\x6c\x24\x83\xd7\x30\x34\x5f\xba\x87\x41\x87\x8b\x73\xba\x45\xf0\x99\x6a\x3f\x8a\xaf\x09\xbd\x92\x0d\x3c\xa5\x28\x67\xdd\x4d\xd8\x49\xcd\xcc\x9b\xcb\x4c\xdb\xcd\xf4\xfd\xa7\x49\x17\x22\x15\x26\x97\xe3\x98\xa8\x52\x72\x53\x68\x18\x5b\x26\x8e\xdc\x34\x80\x27\x97\x56\x3c\x39\xcb\x57\x71\xac\xe4\xe1\xc8\x1f\x72\x8b\x4c\x2c\xff\x5e\x75\xf4\x48\xf5\xe3\x42\x72\x46\x53\x3d\x21\x75\x86\xbc\xa3\xb5\x18\xa9\x46\x5d\x0c\x23\xb7\xe4\xa6\xd1\x8d\x85\x35\xc6\x59\x3e\x5d\xbe\xbc\xb8\xdb\xf7\x37\xcb\xc5\xbd\xe4\x92\x53\x4a\x21\x1f\xdd\xc0\xac\x78\xd5\xb0\x05\xb3\x9c\x51\x00\xc1\x30\xa7\xbd\x89\x69\x87\x54\x0d\x69\x17\x85\x24\x7a\x57\x88\x2d\xc0\x93\x12\x4d\xe7\x9e\x07\xe3\x31\xa9\x51\x31\x0c\xf5\x3f\x58\xf7\xe4\x70\x0f\xf2\x50\x9e\xb1\x50\x5f\x62\xf2\x53\x76\xa1\x90\xc1\x03\xdb\x17\xb0\x39\x45\x2d\xc1\x97\xd8\x9c\x0e\xf9\x74\x96\xcd\x41\x36\x89\x74\x88\x27\x53\x17\x62\x0d\xea\x72\x7e\xf4\x34\x01\xd6\x38\xe1\xc2\xaa\x1a\x73\xe1\xbe\xaa\x2e\xa6\xa6\x20\xa0\x23\x81\x53\x4b\xbd\x4b\x87\xeb\xd5\xf4\xfb\x55\xfe\x98\xf1\xa3\xf4\x86\x35\xd3\x15\x2b\xf7\xb2\x3c\x99\xaf\x58\xbd\x61\xf5\x4a\x9e\x84\x1a\x72\x6e\x40\x98\xbb\xf4\x0f\x41\x50\x94\x11\x2a\xe0\x6a\xc7\xe9\x94\xeb\x7b\x96\x6f\x06\x93\x00\x3d\x94\xdd\x4e\xfe\xdc\xbb\x82\x64\xaa\xc2\xff\xd8\x12\x06\x53\x1d\x99\xea\x36\xb3\x9a\x60\x10\xc6\xdf\xad\x26\xb7\x7c\x12\xa5\x30\xc5\x53\xbc\x00\x39\xe9\x61\x77\xbd\xe4\xe7\xc2\x0b\x52\x5e\xe4\xbd\x71\x08\x80\xff\x0e\x1b\xc0\xc5\xb8\x3f\x8f\x5e\x36\xb9\xc2\x02\x20\xdd\x21\x62\x4f\x75\xd4\x1e\xf9\x48\x14\x19\xa2\x3b\xde\x85\x9d\x61\xfe\xda\xd5\xdf\xac\x2d\xbf\xa6\x4d\xe5\x2a\xbb\xd1\x55\x59\x01\xf6\x14\x35\x02\x10\x27\xcd\x47\x2a\xa3\x03\x42\x36\x6c\xf2\xb2\x17\x92\x30\xe1\x36\xf8\xc1\xf8\x22\x7b\x14\x78\xc6\x27\x10\xe1\x73\xf2\xa7\x48\x8a\x39\xc0\xb9\x63\x0e\x08\xb7\xdb\x63\x7b\x7c\x0f\x53\x42\x34\x9a\x67\x9d\x66\x05\x85\xcc\x41\x7a\x8d\xc3\xe1\x3a\x11\xf6\x9a\x1d\xc4\xa9\xa7\x85\x9b\x60\x68\x9d\xf0\xdb\xea\x42\x13\x40\xdd\x3d\x77\x84\xa9\xa4\x59\x5b\xe4\x6b\xd5\xc0\x33\x8f\x74\x49\x1c\x9a\x81\x7b\x1b\x23\x27\x53\xa8\x24\x2b\x55\xb9\x71\xa0\x6a\x9b\x2b\x54\x8a\x4c\x4f\x61\x78\xf1\xaa\xbf\x09\xbc\xb2\x93\x7a\xc8\xc0\x8b\x1e\xde\x7d\x70\x45\xd0\xa0\xc1\xaa\x11\xb1\xc2\xca\x4e\x49\x81\x5d\x07\x7a\x90\x19\x25\xcc\xc4\x91\xd1\x60\x98\xa7\xae\xe3\x6a\x9e\x82\x63\x5e\x8e\xbb\xd9\x6d\x97\xb8\x6a\x61\xe9\x59\xf0\x64\xd7\x27\x9b\xf6\xc6\x73\xf9\x6e\x64\xef\xf5\x54\xaf\xbb\xc4\xca\x9a\xb3\xec\x10\xb8\x3f\x21\xe2\xe0\x15\x04\x70\xf3\x3a\x0a\xe8\x62\x58\x52\x40\x3b\x01\xcd\x5a\xb8\x48\xc2\xb9\x07\x1e\x9a\xc0\x80\xef\xc7\x00\x51\xba\x35\x0e\xa6\xc8\xde\x2b\x1c\xe0\x4c\x8c\xff\xa2\x8c\x39\x34\xf9\x44\xa8\x9e\xb7\x14\xe0\xda\x12\xa8\x17\x89\xb9\xe1\xdf\x81\xa5\x31\xb6\xa3\x3e\xc2\x0b\x4d\x5f\x1f\x5c\x92\xcd\x9f\xfc\x90\x42\xa6\x24\xd7\xf8\xb2\x0c\x63\xd2\xd8\x6e\xc6\x5e\xb1\x36\xdf\x7a\x37\x2e\xf3\xfa\x2b\xa9\x96\xc3\xb3\xbe\x09\x13\x03\x3a\x1b\xd2\x06\xe3\x22\x42\x65\xd2\x33\x28\xb1\x80\xb6\x98\x00\x35\x44\xfa\xba\x08\x0f\xfb\x4c\xa5\x5a\x60\x7a\xde\x8b\x4c\x50\xad\x07\x5b\xf4\x11\x8a\xc7\x59\x0b\xe0\xe5\x1a\x37\x1d\xfd\x75\x7a\x78\x16\xef\x47\x65\xc9\x19\x39\x04\x8e\x7f\x67\xb1\x64\xcf\xd7\x36\xcc\x03\x5f\x25\x0d\x27\x76\x79\x9d\xc9\x0e\x1b\xb2\x30\x55\x5e\xae\xf0\xf2\xcd\xda\xb6\x9f\x7f\xfa\xf9\xfa\xdd\x9f\x7f\xb9\xbe\x5f\x04\xc8\x84\xa5\xfb\xc2\x81\x77\xaf\xb9\x12\xfb\x1a\xfb\xc8\x44\xe6\xf5\x0d\x3e\xa2\xee\x90\x70\x51\x6f\x38\xf9\xad\x21\x8c\xc6\x0f\x26\xb3\xa5\x2c\xa7\x1e\x5a\x53\xf6\xc4\x75\x6f\x52\xbe\xe4\x95\xb0\x6e\xb3\x0d\x76\xdd\x2b\x61\x35\xe1\x84\x34\x10\x48\x3d\x30\xf9\xb2\xfa\xe8\xc3\xf5\x43\x3b\x3f\x25\x97\x4d\xf9\x42\x6b\xbe\xd5\x9c\x64\xb6\xbf\xe3\x29\x1c\x7a\x27\x36\xab\x63\x95\xde\xbd\x70\xba\xcf\xce\xf4\xd2\x6c\x7e\x0c\x9d\xc0\xdf\x70\xf7\xbd\x60\xa6\x97\xa4\x67\x9a\x80\x5f\x3b\xfe\xcf\xc3\xf5\xc2\x61\x24\x2c\xad\x78\x47\x79\xf0\x15\x02\x19\xd9\x36\x1d\xb0\xf4\x55\x72\xd0\xbe\x83\xe1\xf4\xdd\x5d\xde\xa7\x29\x95\x29\x02\x13\xf0\x4b\xeb\x45\x86\xc3\xdb\xfd\x65\x00\x46\xb1\xc2\x1c\xfa\xcb\xda\xa3\xcf\xd7\x5f\x1e\x96\x57\xca\xbb\x53\x84\x7a\x75\xc7\xd0\x3d\xb6\xba\x2f\x45\x6e\x7e\xf9\xbe\x94\xd2\x6b\xbe\x1f\xc0\x46\xfa\x3e\x6d\x5d\xa6\xa4\x77\x0b\xf8\xba\xf0\xfe\x95\x33\x72\xde\x31\x6e\xfd\xa8\x9e\xf1\x8c\xbb\x1c\xd2\x7b\xbf\x7a\xdc\x96\xda\xf1\xc3\x71\x43\xed\x1c\x0f\x37\x34\xd2\x3b\x20\x3a\x8c\x80\x53\x34\xef\x31\xf9\xbb\xe9\x53\x1c\x10\x9c\x04\x98\xc8\x90\x3d\xaa\xee\xf5\xac\x9d\x2d\xba\x7a\x15\xea\x39\x34\xd3\x41\x5c\xe9\x01\x1e\x85\x1e\x68\x85\x86\x9e\x27\xf1\x67\x26\x22\x2e\xe3\xda\x0f\x14\xfe\xfb\x4d\xc4\x71\x51\x25\xed\x2f\x24\xd3\x17\xb7\xd7\x99\x8b\x40\x1a\x38\x9d\xbe\xc3\x94\x6f\xbe\xd1\x9c\x83\xd3\x38\x37\xe7\x97\x54\xce\xdf\x70\xce\xff\x06\x13\x79\x59\xa7\xf6\x6f\xdb\x77\x0b\xa5\x5a\x5c\x86\x25\x47\x3f\x13\xff\x40\x31\xe6\x27\x77\xcf\x09\x13\xb8\x38\x4a\x87\x1b\xcd\xb0\x9f\x60\xc1\xdd\x94\xdc\x45\x2f\x2d\x0f\xa8\xc7\x0c\x74\xb7\xb3\x34\x48\x38\xcb\x97\x92\x20\xa0\x4e\xac\xcf\xde\x73\x32\xef\xfe\xfe\x6e\xdd\xa9\x3e\x2e\x55\xc9\xc7\xc0\x2c\x99\x89\x61\xfa\x89\x1e\x99\xe8\x79\x98\xbe\x9c\xa3\x2a\x93\xa5\xe5\xac\xe4\x91\x83\xa3\x1c\xdc\xfa\xf5\xdf\x9f\xad\x2c\xc1\x5c\xef\x57\xc9\xfc\x18\xff\xaa\xf3\x43\x5c\xaa\x5b\x8f\x27\xc0\x66\x4a\xb1\xf7\xda\x4c\xdd\x5e\x1b\x96\xda\x93\x56\x05\x2a\xcc\x99\xcc\x9d\xe9\x5f\x56\x0b\x4d\x15\xac\x6d\xbf\xa9\xf1\xd7\x8f\xfd\xf3\xf0\xe5\xe1\xa7\x87\x9b\x8f\x0b\xe8\xde\x38\x47\x83\xb1\x63\xa0\xc0\x1c\xc4\xa0\x13\x24\x18\x4d\x5e\x3b\xef\xd3\x27\xcf\x4e\x0f\xed\x11\x60\x8c\x42\xa4\xa8\x0c\xba\xfe\xfc\x20\x52\x9e\x60\xcb\x20\xf1\xdd\xd1\x4e\x3f\x7d\x78\x4c\x58\x26\x04\x1a\xc0\xe1\x1c\x67\xc5\x7b\x92\x7e\x70\xdd\xea\xb3\xf9\x5d\x9b\x7d\x3e\xdd\xdc\x9e\x5b\xb8\xf4\xe2\x85\xcb\xe9\xec\xe2\x9c\x9b\x7c\x79\xe5\x55\xd3\xf8\x37\x99\xc5\xcd\xcb\xd3\x3e\x7d\xba\xdb\x6f\xd7\xe7\x31\x1f\x92\x78\x85\x4a\x81\xc3\xf1\x1c\x0e\x30\xbb\x72\xe1\xa1\x7f\xf6\x73\x39\x41\xd1\x22\x64\xbc\x52\x48\x83\xa9\x96\xea\x41\x9a\x01\x40\xef\xe9\xac\x6b\x5d\xf2\xcf\x5c\xeb\xa1\x78\xd4\xe2\x13\xb8\x2f\x8a\x57\x84\x97\x1f\x48\x8d\xd6\x7b\xb2\x5e\xc3\x69\x95\x66\xaa\xf3\x88\x3c\x75\xed\xb8\xbe\x3c\xf4\x3a\x27\xaa\x83\x96\x36\x47\x4b\x3d\x1c\x8f\xd7\xf4\x01\xeb\x5c\x40\x2b\x8d\x1e\x62\x70\x83\x0e\xf8\x30\x1f\xe9\xf7\xb7\x41\x5e\xba\x3f\xee\xfe\xbc\xbe\x37\xca\xe1\x8c\x95\x40\xc5\x82\x1b\x42\x78\xaa\x2e\x39\x9f\x2c\xf9\x31\x60\xd6\x60\x90\xb2\x39\xd8\x3c\x18\xe7\x12\x39\x97\xce\x15\x84\x3b\x85\xed\xfa\xff\xfe\x5f\x5f\x66\x55\xf6\x86\x38\xc0\xe0\xe9\x93\x3b\xbf\x1a\x31\x78\x8a\xc1\xc3\xc7\x07\xff\xff\x16\x07\x76\xf3\xb7\x5a\x90\xf1\xcb\xf6\xa1\xdd\xdc\xdd\xae\x2f\x4b\x3d\x4e\x50\x7d\x30\x17\xa8\x63\x62\xcf\x26\xb0\xc8\x4a\x69\x90\x4e\x00\xe9\x07\x26\x97\xb5\xa0\xce\x85\x9a\x70\xf2\x24\xbf\x68\x85\x1f\x6e\x47\x25\x56\x3d\x7d\x29\x9a\x21\x8a\x38\x81\x41\x56\x4b\x48\x6a\x80\x63\x0a\x3c\x1a\x17\xa0\x6c\xf7\x19\x58\x48\x5e\x73\xfe\x39\xc0\xa3\x04\x37\x20\xc3\x09\x5b\x3b\x66\x32\x7a\x7a\xd3\x08\xfb\x0b\xb2\x1a\x8e\xd1\x53\x2a\x04\xf7\x99\xd1\x43\x03\x5d\x12\xb9\xa0\x78\x18\x3a\x97\x2e\x75\xe0\xd2\x58\xa1\x9f\xf7\x3d\x45\x67\x62\x05\x4e\x0b\x8a\x77\x04\xa3\x9f\x02\x7a\x9b\x82\xb0\xdc\x9e\x09\xd1\x45\x24\xa5\x48\x2f\x1a\xba\x9a\xb4\x80\x07\x14\x10\x4d\x1b\xfa\xb7\x51\x18\xdb\x02\x00\x06\x00\x0f\x25\xf2\x1d\x2a\x2a\x20\x53\x4b\xb2\x53\x0c\x34\x9c\x50\xbe\x25\x41\xd8\x7c\xd7\xc4\x99\x1f\xee\xd6\x37\xdf\xf5\x51\xf2\x4c\xcd\x58\xa4\x40\x76\x4f\x77\x5f\x4d\x7b\x75\x5e\x78\xfa\xe0\x34\x67\xfa\xf1\xb6\x4c\x76\x65\x6d\xaa\x66\x3b\x96\x0a\x5f\xf3\x5a\x08\x65\xb1\x9b\x71\x5c\x6c\x4c\x67\x7a\x7c\xfe\xbc\x9c\xb6\xb0\xb9\x74\x60\xfe\x4e\x6f\x80\x87\x77\xf7\xdb\xed\xed\xc3\xee\x6e\x29\x19\x1c\x25\xc7\xad\x99\x22\xbb\x9d\xe2\x15\xbc\x38\xd8\x09\xe0\x06\x8e\x80\x56\xa4\x99\x00\x14\x1e\x5f\x51\xf2\x35\x39\xc0\x1e\x75\xbe\x56\xc9\x6c\x61\xf1\x2b\x5d\x6e\x2f\x8a\x0b\xd6\xb1\x3e\x14\x87\x00\x3f\xa2\x0b\xab\x72\xf8\x85\x80\x2e\x5b\x37\x9a\x6a\xd4\x16\x3a\xae\xac\x1d\xb7\xb3\xd7\x5e\xbf\x54\xec\xb7\x75\x94\xea\x40\x42\xe6\xa1\xb7\xa3\x39\xe9\x1b\x28\xdb\x67\xa2\xcd\x82\x1f\xe1\xd4\xa7\xf9\x0e\xa3\x5a\x61\xb3\x06\xcc\x67\xed\x9e\xfc\xb8\x47\xc9\x57\xab\xee\xfd\x66\x44\xcd\xd2\x82\x56\x87\xda\x5a\x6f\x09\x3f\xf5\x4e\xbc\x3c\xd0\xd6\x8f\x3e\x23\x3f\xe3\x51\x25\xed\xa8\xf6\xbd\x76\xf5\xc5\x1a\x14\x3f\x62\xf0\x3e\xd3\xf1\x88\xdb\xf1\x64\xa0\xd5\x57\xea\x30\x3b\xab\xbc\x9e\xf1\x36\x1e\x65\x0e\xae\x99\x02\xd2\x5b\x82\x89\x0c\xe9\xa9\xed\x19\x54\x85\xad\xe6\xa8\x64\x9f\x8f\x92\x55\x9e\x2d\x29\xac\x4c\xaf\xa9\x17\x71\x1e\xc0\x01\x7e\x38\xa9\x65\xaa\x64\x51\xa8\x57\x70\x64\x7c\x6e\xda\xc6\x94\xe0\x34\x4f\x15\xad\x96\x99\x86\xd2\xeb\xd5\x2e\x76\x34\x06\xbf\x39\x8c\x60\xae\x6d\xbd\xe4\xdf\x36\x29\xef\xb7\x26\xbd\x9b\xef\xc0\x7d\x9f\xd9\x6e\x47\x09\x96\x33\x53\x76\x7e\x30\xc1\x39\x64\xd0\x38\x6f\xd2\xae\x81\x5c\x0d\xeb\xca\x15\x0b\xd4\xba\x55\xc5\x12\x7c\x1d\x42\x1e\x5c\x8e\x70\x1d\x5c\x2b\x63\x41\x0f\xcf\x29\x60\x7e\x93\x55\xdf\xfc\xad\x96\xfd\xb7\x5e\xf5\x9f\xaf\x6f\xcf\x2d\xfb\x21\x1d\xb3\x4e\x28\xb8\x51\x21\x76\x25\x93\xab\x71\x30\x39\x06\x32\x39\xfa\x11\xe7\xb0\x54\x72\x15\x9f\x23\x03\x54\xcd\xb1\xe2\xdf\x20\x7f\x97\x57\x3e\x1d\xf7\x4c\x22\x20\x5f\xb6\xe0\xc9\xb1\xe6\x3c\x65\x4f\x3e\x84\x21\xc7\x48\x39\x22\xde\x30\xaa\xeb\xb7\xb5\x54\xf9\xac\xb3\x71\x9d\x56\x4c\x43\xa2\x92\xa3\x02\x4f\x9c\x3a\x2f\x88\x42\x04\xc5\x8c\x4c\xe3\x52\xdd\x0c\x0a\xe8\x42\xd2\xe4\xc8\x06\xd9\x91\x9d\xa6\x6c\x46\xc6\x64\x85\xba\xe3\xcd\x49\xf2\x64\x64\xf1\x93\x77\xe4\x4a\xb2\x56\xd3\x27\xd7\x39\xf3\xb3\x0b\x53\xde\xda\x9e\x44\x19\x55\xb4\x43\xb5\x73\x53\x73\xfb\x40\xca\x85\x2f\x5a\x7d\x0e\x87\xe5\xfe\xfe\xee\x97\x55\x95\x71\xb2\x27\x06\x38\xc0\x49\xf7\x2b\x1b\x2e\xf7\xb3\x2b\xec\x84\x45\x2c\xc2\x0b\xa2\x5e\x06\x57\x81\x76\x14\x80\xa2\xae\x9e\xf7\xc0\xd1\xd3\xcf\x01\x1e\xee\x39\xe9\x0d\xaf\xae\xfb\x3d\xb5\x02\x3c\xe2\x2a\x23\xb5\x42\x8a\x4c\x29\x3a\x94\xea\x05\xa7\x4c\x05\x9a\xa8\x40\x0b\xd8\x51\xd3\x14\xc8\x5b\x65\x44\x0d\xa8\xae\x0c\x68\xa5\xf7\x41\x33\x19\x54\xee\x7d\x60\x21\x23\xe8\xa3\x47\x8c\x0d\x5e\x3b\x8c\x62\xd3\x0e\xa3\x7b\xc1\xec\xad\x2a\x9c\xd3\x21\xe3\x74\xc8\xae\xc3\x6f\x1b\xc0\x4f\x66\xed\x81\xf4\x5f\xfe\x59\x49\x31\xc1\xc7\x29\x26\x64\xe3\xce\xc9\x18\x30\xd2\x86\x7f\x31\xcd\x32\x02\x8d\x34\xd2\xc9\xc3\x20\x7a\x42\x8c\xc9\x2f\xba\x73\x2c\xd1\xd3\xfc\x53\x9b\xcb\xc9\xf8\x75\x36\x40\x54\xa5\x19\x05\xdf\xad\x16\xcd\xd8\x41\x3b\xd0\x67\xd9\x62\x96\x8f\xe2\x27\xe6\x51\x60\x8d\xa2\xc6\x4f\x5c\xce\x9e\xa3\xb3\xb6\xcc\x58\x96\x96\xd6\x9b\x13\xb7\x05\xa6\x98\x14\xf8\x93\x0f\x21\x1f\x58\x65\x9d\x9f\xbe\xb6\xf2\x39\x1a\xa4\x9c\xc4\x1c\x96\xe9\xce\xf0\x7b\xd3\x43\x1c\x35\xdb\xc5\x1c\x50\x35\xe5\x11\x71\x60\xfb\x84\x6d\x9c\x92\x7c\x4c\x50\xa9\x5a\x5a\x0a\xef\xfb\x7c\x05\xec\x9e\x0e\x2c\x5f\xfa\x1e\x2e\x6d\x6a\x71\xb9\x6a\x53\x9e\xd0\x72\xd8\xbb\x3c\xea\x84\x61\xa5\x35\x49\xa6\x6e\x81\x79\x56\x37\xaf\x08\x4b\xd1\x69\x5d\xcb\xdf\x97\x96\xd6\x9f\x27\x13\x3b\xcd\xcb\x51\x2c\x4d\xef\xc2\x73\x19\x50\x0e\xc7\xf4\x68\xe7\x1c\x0f\x35\x07\x6c\x9f\xaa\xa7\x16\x03\xf5\xd3\x21\xcd\x43\x9f\xc8\xd0\x43\xe1\x9e\xa4\x49\x91\xb5\x38\x3a\xd2\x4d\x27\x7a\xdf\x89\x8c\xf2\x01\x53\x12\x13\xd4\xec\x0e\x53\xd8\x37\xc6\xcb\xe7\x0f\x9e\xd2\x6b\x19\xbd\xd3\x65\xf4\xcc\xea\xa6\x30\x9c\x63\x7f\xbf\x08\xb8\x3d\x3e\xc7\xc7\x1c\x19\x06\x3b\xe0\x7d\xed\x18\xce\xb8\x74\x13\x64\x11\x32\xae\xa3\x91\xfb\x09\xde\x94\xad\x3e\xc7\x5d\x5e\x14\x1b\xb5\x83\xf0\xaa\xce\xaa\x7b\xee\x42\xb5\xab\x10\x77\xd0\x0d\xe1\xb6\x4a\xa4\x50\xb7\x7e\x02\xfc\x42\xc6\x0f\x5c\x63\x80\x99\x26\xe3\x84\xa7\x50\xc8\x5b\x3b\xfb\x0f\x17\xe2\x3c\x9a\xdc\xbd\x7e\x9c\xdb\x34\xe0\xbb\x21\x5f\x09\x03\x1f\x51\xee\x55\x97\xc9\x95\xa8\x41\x11\x21\x32\x14\x4c\x15\xdb\xc0\x8b\x28\xe3\x28\x58\x4f\x25\x47\xf9\xdc\x39\x17\x56\x6d\xa2\x13\x27\x36\xcf\xde\xcb\xdd\xf1\xee\xb7\x0f\x37\x8f\xdb\x9f\x3e\x7c\x19\x16\x01\x6f\x69\x36\x82\x09\x1b\xd0\x93\xff\xc3\xc6\x6c\x35\xce\xd9\x23\x3d\xb1\x77\x03\x32\x85\x70\x38\xe3\x72\xfc\x6c\x12\xfc\xd5\x24\xff\x07\x0e\x54\xeb\x1e\xa4\x35\xef\xdd\xaa\x84\x82\xa8\x06\x0e\xa7\x72\xc7\xe3\xb1\x0f\xcc\xd9\xd4\xfc\x07\x1b\x65\x08\x24\xed\xcc\xc3\xda\x9c\x97\xc8\x80\xed\x1e\x56\x85\xad\xde\xcd\xb9\xbe\x0b\x4e\xa4\xd2\xa7\x57\xcb\xa1\x58\xae\x87\x4f\xd7\x2b\xeb\x95\x8e\xe3\xc2\xa6\x58\xd0\xd7\x8e\xfa\x6f\x34\xe8\xb7\x1c\xa5\x9d\x09\x4f\xfa\xf5\xbb\x6c\xf3\x37\xdb\x66\xcf\x59\x98\x17\xeb\xb4\x74\x84\x3e\xf2\xb5\x0b\xb6\x50\xb1\x76\x56\xc7\xaf\x25\x02\x09\x7c\x48\x27\xb2\xf6\x1c\x2a\xcb\x95\x0c\x27\x81\x13\x5e\x5e\x4f\x7f\xa2\xc1\x05\xa7\xf9\x3f\x7a\xf0\xe8\xf2\x81\x94\x5e\x66\x23\x47\xaf\x90\xa6\xeb\x95\x99\xca\x61\xd1\x5d\x4c\xd4\xd2\x1b\xf8\x95\x13\x85\xb8\xe0\x17\x0f\x16\xa5\x5f\xd9\xf1\xeb\x87\xb6\xbd\xbf\x79\x58\x44\x4d\xa4\xa5\xdb\xee\x71\xd4\x44\x71\x14\x4a\x1a\x43\xc2\xe1\x54\x4c\xcd\xdc\x53\x6d\x81\x87\xce\x57\x71\x98\xd2\xaf\x6b\x5e\x04\x29\x9b\xbb\xa5\x03\xdc\x97\x86\x9a\x48\x39\xa4\x6c\x8e\x7e\x6f\xbc\xcd\x33\xa3\xd6\xa5\x07\xe5\x01\x26\x06\xcd\xcd\xec\x5d\x53\x9e\x63\xef\x61\x8b\x83\xff\x48\xf4\xa3\xe9\x3d\xd2\xda\x8d\x2a\x4d\xd1\xaa\x34\x3a\x4c\xb9\xdb\x01\xa1\x99\x7a\xf6\x75\x29\xaa\xe0\x99\x52\x70\xd0\xce\x84\xa9\x57\x61\x83\x4a\x81\x4e\x3a\x95\x69\xf3\x7b\x43\xaf\x50\xeb\x9b\x1b\x6a\x87\xe6\x87\xa9\x6f\x7b\x1d\xdc\x0b\x79\x1d\x19\x56\x9f\x96\x51\x9b\x9f\xe7\xab\x1d\x66\x71\x98\x66\xb8\x4f\xf0\x61\xf2\x27\xa0\x53\x0c\x69\x9a\x9f\xcb\x19\x1f\xb6\x7f\x79\x37\x5c\x7f\xba\x3e\x6b\xa0\x4b\xd7\xc7\xf4\x59\xdd\x98\x6c\x25\x4b\xcf\xab\x0c\xda\xf7\x52\x5f\x74\x6b\x48\xe2\xbd\x86\x31\x4e\xc6\x10\x0d\xd9\xa7\x05\x1a\x54\xbf\x22\x94\x12\x1e\x62\x1f\xfd\xa4\xfa\xd3\x02\x3b\xa0\x12\xf5\x40\x35\x45\x07\x40\x9d\xd2\x5a\xa0\x68\xe3\xc0\x85\x92\x03\xf7\xe3\x94\xb4\x22\x3d\x0e\x72\x28\x04\x2a\xc2\xeb\x1d\xac\x43\x9a\xba\x8a\xc1\x99\xe9\x65\x55\x06\xce\x64\xb4\x82\xf9\x7a\xca\x10\xff\xc9\x88\xb4\xc6\x65\x86\x52\x91\x2d\x88\x79\xb8\x52\x08\xf2\x8b\x4b\xfa\xf1\x66\x45\xc2\x9f\x2d\x1f\x55\x78\xbc\x62\xf7\x31\xed\x83\xd2\x14\x98\xb1\x40\x91\xf6\x46\x7e\x32\xdd\x51\x27\xc2\x62\xed\xbb\x69\x10\x7c\x20\x28\xa8\x2b\xdd\x52\x0d\xa5\x8c\x48\x3d\xc8\x5d\x96\xa1\x8f\x0b\x3b\xae\x71\x42\x89\x67\x9c\x39\x8f\x04\x16\xe4\xf9\x88\xa8\x19\x37\x87\x34\x76\x82\xd5\xe3\x1f\x1f\xdf\x32\x27\x0b\x60\x00\xa5\x75\x4a\xfb\x9a\x52\xc2\xd1\xa8\x61\x36\x89\x98\xc2\xd2\x0c\xd4\x21\xbc\xe3\x1a\x66\x22\xa8\x34\x30\x95\xce\x4a\x95\x14\x60\x75\xdb\x8c\xab\x69\xea\xeb\x33\xb7\x12\xc2\xd4\xcf\x5d\x4b\x27\x76\xbc\x43\x8e\x7b\xfb\x34\x73\x7e\x08\x76\x34\x55\x73\x98\x44\x28\x75\x34\x5d\x01\x36\xb0\xfc\xd0\x8e\xbe\x1e\x4a\x8c\x6c\x33\x59\x62\xe9\x4c\xce\x03\xc3\x1c\x9c\x22\xbe\x70\x8a\x63\x62\xca\x19\x8f\x73\x1e\x51\xbd\xbe\x8b\x8a\xb5\x4a\x6d\x6f\xd3\xdb\xd2\xbf\x9a\x39\x2a\x86\xbe\x3d\x4d\xeb\x7f\x19\xbd\x6f\x7b\xbd\x48\x89\x9f\x2e\x01\x0e\x01\x80\x54\x2d\xef\x4f\x3d\x9a\x46\xc3\x19\xe4\xdd\xc3\x3b\xa2\x6a\x28\xba\x46\x63\xfb\x20\x8b\xa4\xf6\xf2\x0e\xd3\x5c\x35\x64\xfd\xc8\x1b\xe6\x89\xb7\xd3\xe8\xc2\xe4\xfe\x32\x8a\x94\x12\x48\x64\x52\x6e\x29\x53\x4a\x50\x31\xb2\x0b\xe4\x10\xc8\xc8\x39\x35\x0f\xe9\xe6\x08\xc8\xf2\xc8\x43\x0a\xe0\x31\x16\x69\x52\x4c\x8d\x6a\xa0\xe7\x3a\x5d\x37\x0e\x29\x75\x54\x8f\x54\x84\x8a\x29\xb2\xb4\x4b\x65\x33\x1a\x07\xa6\x0b\x5e\x23\x9a\x56\xf3\x08\xea\xa0\x24\x0a\x19\x1e\x05\x22\x89\x15\x0a\x8a\x5f\x0e\x33\x88\xba\x9b\x6a\xe4\x81\x53\xde\x30\xdb\xc9\xea\x2f\xdf\x92\x26\xd8\x99\x8e\x81\xef\xf4\xa0\x21\xff\x05\x6e\xa1\xd1\x38\x0a\xf0\x4b\xe0\x66\x62\x4f\x12\xe4\x69\xc6\x71\x96\x01\x8f\x96\x7c\x94\x73\x09\xdc\xf5\x54\x74\x3b\x0a\xff\x2d\x33\x42\xe0\x38\x35\xe4\x1a\x40\x00\x9a\x3d\x1c\x09\x1d\x4d\x25\xee\x40\x36\xaa\x95\x25\xe7\x6c\x63\x84\xcc\x22\x33\x0c\x67\xd0\x28\x5f\x9b\xb3\x81\xaa\x6c\xe2\x08\x42\xc2\x21\x2a\xac\x3e\xb2\xad\x50\x6d\x0c\x53\x57\x9a\x35\x9f\x8d\x75\x2d\x92\x5c\x9f\xa0\xf2\xc8\xb7\x83\x6f\xa5\xc9\x62\xda\x86\xc4\x31\x9c\x34\x83\x12\xa0\xea\xe5\x2a\x42\x93\x26\xa4\x9e\x86\x92\xd9\x81\x86\xb2\x0b\x4d\x2e\xd6\x74\xd9\xc9\xfd\x66\x19\x33\x9d\x96\xa0\x42\x4f\x78\x38\xc3\x09\x29\xf7\x7e\x15\xec\x5d\x0a\x5f\x0b\xbd\x07\x57\x16\x55\x44\xe4\x8e\xbb\x0e\x41\xa0\x75\xee\x0b\x1d\xd1\xd4\x27\xa5\x74\x78\xfc\x7c\xf8\x4d\x33\xe7\x90\x29\x8a\x05\x8f\xb7\x6b\xd7\x0f\xd4\xa4\x59\x50\x11\xa8\x49\x0c\x14\xfd\xcd\x28\xec\x57\x00\x76\x84\x9c\xe4\xd9\x67\x06\x9a\x70\x2c\xdb\x94\x04\x09\xe6\xdf\x0e\x29\x01\xde\x05\xb8\x15\xb9\x10\x5a\x91\x2e\x82\x79\x92\xc2\xe8\x4b\x29\xad\x2a\x0f\xa5\x7f\x67\x27\x05\xd0\x31\xbc\xd1\xbb\x55\x83\x66\x01\x70\x61\x50\xac\x03\x26\x1e\x85\x7b\x0a\x4c\x40\x09\x2a\xbe\x69\x9f\x8c\x74\x4a\xfb\xa4\x19\x60\x5b\x56\x83\x37\x3a\xe5\xba\xc2\xe4\x19\xa6\xe8\xaf\xdb\x9f\xee\x3e\x6f\x97\xcc\xd0\x32\xfa\xe3\x88\xca\x75\x30\xa3\x11\x08\x0e\x4e\x15\x64\x4c\x3e\xfa\x11\x96\x6d\x1b\x08\x7a\x7a\xa7\x6a\x18\xe8\x4f\x8e\xb3\xcd\x3d\x49\x4b\x77\x92\xb1\xee\x28\x97\x1d\xd8\x0d\x96\xaa\x1c\xf2\xf5\x38\xa4\x52\xc8\xda\x98\xf1\x30\xa4\x20\x48\x3c\x92\x57\xc0\x0b\x8f\xa4\xbd\xc1\xeb\x26\x81\x9a\x49\xff\xd0\xef\x5a\x0a\x85\x1e\xdf\xd6\x10\x3a\xc0\x93\xd3\xdb\x52\x88\xb0\xd7\x3c\x56\x72\xd9\x02\xbf\x43\x73\x69\xa9\x17\x4f\xd1\x6d\x29\xbf\xa9\xd5\x4a\xd3\x9c\x85\x86\xec\x07\xf8\xe0\xd0\x50\xd1\x68\xa9\x24\xe9\x38\x87\xdc\x38\x64\x4a\x3c\x3a\xb9\x58\x8f\xca\x1c\xc0\x77\xc7\x9e\x0f\xb4\x43\x8e\x18\xe4\x16\x73\x1e\xaa\x44\xcc\x93\x9f\x42\xda\xeb\x91\x42\x2c\xf4\x84\xbe\xb5\xf5\x62\x1e\x0e\xb3\xa0\x77\x8a\x9c\xd2\x14\x3f\x45\xaa\x93\xb9\x9b\x4b\xb5\xc3\xab\x73\x95\xb5\x1d\xda\x42\xbc\xb3\x8f\xa4\xfd\x79\x76\xfb\xbc\x1b\xee\x96\xa1\x5f\xf9\x52\xd0\x4c\x8c\x52\x39\x0f\x59\x68\x25\x23\xdf\x9f\xa6\x57\x10\x79\xa0\x6a\xfe\x1d\xeb\x5f\xb0\xfc\x38\xbe\x51\x2e\x16\x98\x52\x5e\xbd\xaa\xbf\xc5\xa2\x7a\x9b\xe5\xca\x00\xaf\xab\xb8\x24\x75\xa3\xe9\xb2\x0c\x17\x30\x73\x80\x06\xcb\xb2\xef\x91\x78\x33\x69\x1c\x7c\x99\xe2\xe0\x53\x77\x86\x4b\x13\x98\x02\xfb\x40\x59\x15\x97\xbd\x00\x2c\x1f\xec\x28\x04\x2a\x72\x99\x06\x4f\x09\x37\xb2\xde\x92\xc2\xf2\x21\x9f\x94\x0b\x8a\x68\x23\x7c\xe9\xc9\x96\x88\x9e\x9c\xdc\x8b\xc5\x92\xcf\xdc\x42\x05\x7a\xd9\x58\x90\x11\x14\x0a\x58\x24\x58\xa9\xea\x70\x20\x0d\x12\xa7\x31\xe2\x29\x19\x5c\x9d\x46\x73\x0d\xfb\x9e\x58\xa9\x27\xbe\x00\x57\xa7\x7b\x8a\xaf\xe2\x66\x64\x95\x01\x30\x28\x64\xc6\x0f\x61\x46\x64\x44\x66\x33\xe1\x73\x62\x07\x22\xa8\x30\xf8\xc9\xa5\x58\x2c\x45\xeb\x46\xf8\x07\x8a\x94\x51\x9e\x1e\x97\x78\x38\x2e\xbe\x67\xc4\x06\x5c\x14\xcb\x88\x01\xb9\x23\xdc\x96\xf1\xa1\xb3\x2a\xb9\x69\x66\x2c\xe1\x6f\x86\x1c\x88\xbd\x1b\x01\x00\x55\xc8\x57\x50\x72\x9f\x9b\x47\x46\x2e\x91\x63\x0d\x23\x03\x92\x74\xae\x38\x72\x35\x0c\xc9\x0b\x2d\x1f\x85\x3b\x12\xb2\x5e\x3a\xa5\xf5\x0d\xc9\x20\x41\x68\xf5\xdc\x84\xe9\xdc\x6c\x2e\x1d\x9c\x5f\xae\xef\x6f\x6f\x6e\x3f\xae\x0a\xa2\x79\x19\xfc\x74\x44\x7b\xd5\x7f\xef\x44\x00\x9c\x72\x54\xcf\x37\xef\x12\x12\xf8\x18\x31\x4e\x11\xf6\xea\xec\x1d\x77\xd0\x9e\x1f\x00\xe3\x4e\x80\x81\x67\xbc\x38\xdf\x11\x8e\x1c\x45\x0f\xa1\x30\x00\x4b\x65\x12\x0a\x15\x68\x10\x59\x35\xe5\xe6\x9b\xc4\x42\x9e\xc4\x42\x66\xdd\xe2\xb9\x6b\x0f\x19\x72\x61\xd0\x6c\x98\x93\x5c\x98\xba\x5c\x98\x54\x2e\xdc\x1c\x09\x86\x69\x16\x0c\x93\x76\xc4\x0a\x01\x49\x75\xc8\xc8\xbe\x23\x12\xbb\x6c\x0c\xb8\x93\x22\x6f\x9c\xc2\x03\x39\x38\x91\x77\xc6\x49\x39\x49\xc3\x79\x42\x9c\xf7\xe1\x88\xbf\xec\xb8\x61\x41\xcd\xb8\xa9\x67\x7e\x4b\xc3\xac\x11\xe0\x2c\x87\x29\x64\x0a\xb5\x25\xb9\xf3\xe5\x5f\xc3\x00\x0e\x31\xe1\xd9\xc0\xde\xdb\x25\xa1\xbc\x94\x73\x92\x7d\x56\x10\xe8\x11\x39\x85\x9c\xce\x34\xf2\x66\x81\x33\xcb\x6e\xe8\xce\x64\x89\x15\x42\x30\x55\x39\xa6\x6a\x9d\x81\x5e\x56\x24\x47\xb0\x86\x40\xc2\xea\x8a\x66\x64\xfc\xc6\x42\x30\xd8\x73\xdf\x51\xb3\x06\xe3\x72\xa5\x68\xcb\x20\xa2\x89\x9c\xcc\x3a\x20\x11\x6b\x0d\xa8\x35\x23\xe3\x90\x88\xa3\xc2\x67\xd5\x74\x82\xa0\xba\x03\x38\x0b\xb2\x18\x21\xb5\xde\x00\x7a\xe7\xa2\x93\xca\xe4\xa4\x69\xf6\xb8\xdc\x43\x8b\x81\xeb\x05\xf0\x8d\x38\xd4\x24\xa4\x66\xc2\x0d\xde\x00\x7a\x43\xc6\x37\xb0\x70\x43\xd1\x0f\xd2\x1b\xe9\x8c\x89\xb6\x90\xcb\x0a\x94\x84\x19\x80\x99\xc6\x09\x81\xa9\xe4\x54\x70\x44\xc6\x5c\x24\xf7\xf3\x96\xca\x90\xb0\x42\xb1\x62\x82\x38\xd9\x31\x27\x92\x69\x85\x14\x5f\x1a\x7c\x5e\x9e\x49\x5c\xf8\xee\x7a\xd8\xde\xbe\xbf\x5e\x20\xe3\xe5\x8b\x26\x48\x50\x71\x57\x76\x1d\x25\x49\xe1\x92\x0c\xf0\x92\x42\xd1\x1c\x97\x3b\xef\xac\x3e\x83\x62\x42\xb1\x94\x5c\x11\xee\x0f\xaf\xc1\x85\x16\xaf\x79\x67\xf5\x35\x79\x24\x85\xf1\x08\x6f\xe1\x11\xc3\x8b\x79\xb5\xb1\x02\xea\xb8\xde\x98\xd4\x28\xaf\xad\xf6\x23\x9c\x1f\x80\xd4\xb9\xde\x93\x0d\x40\xdc\xd8\xea\x3b\x67\x81\x25\x77\x22\x52\x5c\xc4\xb4\xd4\xb7\xcf\x41\x5a\xa6\x70\x06\xd0\xb2\x77\xfc\xcc\x0c\x4a\xbf\x2f\x8d\xf7\xcc\x14\x6a\x62\x91\x97\x8c\x69\xf3\x5b\x0d\x0a\x19\xad\x39\x6a\x5a\x08\x7b\x56\x8d\x8c\x58\xcd\x15\x3d\x72\x7f\x69\xa9\x9e\xdd\xd7\x55\x68\xce\x14\x56\x81\x39\x01\xcd\xe6\x4b\x58\x7f\x6b\x73\xf1\xb5\x75\x5d\xf0\x65\x7b\xda\xf5\xed\xfb\xbb\x4f\x8b\x63\x77\xc9\x74\x9d\x12\xdc\xc5\xe3\x08\x0d\x42\x75\x1d\x59\xca\x65\x2f\x3c\x24\xcc\x5a\x3e\x93\xe6\xac\x0b\x72\x99\x24\x5c\x9d\x91\x21\x8f\xcb\xfd\x40\x5e\x18\x43\xee\x19\xa5\xa7\xcc\xed\x4f\x75\x5f\x73\xf4\xc6\x41\xf7\x25\x05\x1d\xd2\x9d\x05\xdc\x6f\x6e\x46\x3a\x8f\xe9\x09\x06\xb5\x07\xaf\xe0\xec\x4b\x31\xa8\x71\x9f\x7b\x75\x86\xe9\x19\x1d\x91\x00\x8e\xe1\xd1\xc5\x1b\x64\x38\xd4\x74\x87\x9a\xd6\x4b\xf8\x15\xc8\x09\xb1\xf4\xfc\x5e\xb1\x52\xb0\x0d\xb6\x73\x1d\x71\x42\x86\xf2\x31\x56\xaa\x5e\xd8\x3f\x92\x39\x82\xa3\xa2\x3a\xbc\x60\x8e\x30\x45\xb8\x1e\x5b\xe4\x9e\x27\x5e\xee\x45\x1f\x5b\x51\x96\x4f\xa1\xce\xd2\xca\x84\x74\xb8\x5e\xf0\x66\x83\x47\xa4\x36\xd7\x25\x3e\x36\xf7\xc4\xc0\x5f\x3f\x3d\x1b\x55\xee\x22\x5e\x53\x75\x4f\x45\xf6\x1d\x52\xba\xaa\x11\x12\x6e\x1f\x9a\x0a\xad\x5b\x0d\x30\x9d\x26\x39\xd5\x2b\x70\x66\xe4\x2f\x55\x6c\xdb\xce\xc0\x72\x83\x6b\x13\xdb\x9e\x47\x12\x4a\x80\x1c\x20\x82\xe3\xc4\xa5\x9e\xbb\xb5\x27\x63\x6d\xa6\xeb\x2d\x5f\xbd\x6b\x34\x60\x26\x13\xc7\x96\xa0\x33\x8c\xac\xa8\x63\x41\x2d\x32\xa3\x77\x94\x1c\x89\xc0\x94\x79\x74\x15\x27\x0f\x42\x1c\xf3\xa6\x45\x59\xf4\x08\x75\x83\xb5\x2d\x07\x2a\x5e\xce\x37\x7a\xa7\x9d\x0b\xae\xa9\x26\xf5\xeb\xd7\xea\xe2\xfd\x78\xf7\xe9\xd3\x76\x09\xf5\x99\x97\x80\x7c\xeb\x90\x52\x8c\x5c\xc8\xba\xe6\x3d\xa9\xac\x08\x0c\xde\x37\x64\x1e\x47\x76\xe2\xd1\x64\x85\xe4\x15\x89\x60\xec\x1e\x8d\x19\x4c\x1d\xd8\x4b\x37\x42\x8c\xea\x36\x60\x60\xf2\x2a\xf7\x47\x9a\xc2\xb9\x76\x1f\x12\x57\xf7\xc8\x6a\xab\xc9\x1d\x89\x5d\x93\xdb\x0a\x59\xb3\x61\x71\xa2\xda\x32\xc9\xcc\x15\xaa\x63\xa6\x22\xfc\x9e\x0f\x22\xe1\x04\x85\x1d\x95\xbf\x61\x94\x91\x6d\x18\xb9\xb9\x4c\xb1\x36\x27\x4c\xc5\x08\xd7\x49\xf8\x54\x42\xf0\x70\xce\x76\x37\x2c\x57\x58\x41\x96\x2d\x65\x26\xa7\x30\x72\x95\xc9\xf5\x04\xd0\x49\x53\x45\x37\x1f\x8a\x82\x99\xba\xa0\xea\xdd\x3e\xfa\x36\xcf\xc8\x61\x9a\x9e\x81\xf3\xfd\x78\xbb\x5d\xae\x48\x3a\x71\x7f\x3c\x89\x58\xb0\x22\xaa\x6a\x16\xe2\xe4\x9a\x71\xb2\x26\x2e\xea\x72\xd4\x78\xf0\x8b\xd4\x3f\x6a\x57\x7c\x05\xea\x65\xf0\xaa\x4f\x6e\x3d\x92\xc0\x97\xb5\xd4\x39\x07\xdf\x4b\xa7\x1c\xbe\xdc\x65\x11\x5f\x62\x6e\x19\x1e\xa8\x0d\x27\xcf\xb7\x80\xfc\x97\x21\x10\xd4\x66\xec\xe5\xb1\xef\xa5\x63\x6e\x78\x5d\xef\xb9\xd5\xd6\x37\xab\x5e\x0d\x60\x55\xe0\x80\xa2\xa8\xb3\xab\x21\x17\xc0\x39\x5c\xf1\x57\xd0\x57\x5e\x34\xd0\x13\x5f\x97\xdf\xb8\xa9\x97\xa0\x09\x2c\xdd\x14\xf3\x45\xf8\xb7\x04\xcc\xd9\x03\x42\x42\x3c\xeb\xc8\x7e\x02\x17\x60\x26\xbc\x80\xf3\xa0\x03\xf1\xd4\x17\xe5\xaa\x7b\xa3\x5c\x4d\x78\x0a\x7c\x01\x53\xe0\x09\x8e\xc3\xd5\xec\x6c\xf2\xcc\xd9\x98\x66\x61\xcd\xab\x30\x5f\xcc\xd0\x26\xf3\x90\x5d\x99\x21\x15\xce\x8f\x6e\xea\xfd\xb9\xd1\x4d\xa3\x5f\x19\xdd\x09\x5c\x45\x47\xab\x38\x83\x28\x11\xbf\x72\x06\xee\xb7\xed\x97\xed\x0a\x79\x58\x7a\x45\x1c\x10\xf1\xc1\x03\xfb\x67\xd2\x26\xd4\x64\x47\xa3\x3e\x7f\xb0\x75\xc8\xb5\x97\xd5\x3a\x23\xac\xa8\xe6\xcd\x17\xc9\x8f\x85\xa9\xf1\x7b\xe6\x3d\x27\xab\x26\x46\xf0\x38\xcb\xcd\x3f\xe2\x5a\xe2\x48\x81\x15\x2e\x5f\xb1\x33\x85\x97\x93\x7f\x35\x9f\xb6\x22\xe9\x2b\xae\xa6\x4a\xaa\x8c\xe4\xa7\x67\xc3\xa8\xaa\x53\x08\xbd\x98\x0f\x11\xad\x86\xbb\x14\x2d\x3d\x51\x25\x85\x5c\x20\xbc\xe9\x28\xf8\x93\xbb\x56\x50\xdf\xc2\xc0\x13\xa3\x82\x53\xdb\xed\xed\xa1\x1b\x5d\x03\x72\xe2\x98\xa9\xc7\x06\x0a\x25\xbc\x88\x5e\x3d\x8d\x98\xaa\x4e\xc1\x03\x55\xad\x9e\x3a\x88\x2a\x43\xc0\xb7\x84\xa9\x81\xaf\x62\x26\xb5\xb9\xae\xd9\x52\x64\xf2\x0b\x32\x20\x63\x6d\x9a\x14\x6f\x1a\x52\xdb\xbc\x6a\xe4\x1a\xeb\xe7\xde\x08\x53\xce\xbc\x57\xf3\x8e\xcc\x3f\x0c\xde\x4b\x72\x72\x51\x8d\xf5\xb0\xbb\xfb\xfc\xf9\xe6\xf6\xe3\x4f\xef\xae\xef\x97\xbb\xe9\x12\x60\x5b\x0a\x96\xce\x48\x31\xed\x44\x72\x69\x47\xf2\x4a\x3b\x95\x1c\x94\xa8\xfe\xfa\x5a\x20\x5a\x89\x70\x67\x26\xe0\xee\x40\x3d\xbd\x78\x38\xc8\x09\x70\x5b\x1d\x0c\x5b\xb8\xa2\x39\x28\xc8\x44\xc6\x90\x8f\xac\x6c\x4c\xd2\x57\x53\xd8\x55\xb7\x96\x0b\x71\xb3\x82\xe5\x68\xdd\x2a\xc9\x87\xe1\x11\xdc\x07\x42\x26\xc8\xa7\xa6\x71\xcd\xb6\x29\x14\x3a\xfc\x7d\x38\x67\x2a\xce\xef\x8c\xb3\xab\xb5\x9c\xb8\xf6\x01\x08\x12\x5b\x5d\x4d\xe2\x07\x55\x2d\x08\x93\x57\xeb\x5a\x2b\x08\xda\x56\x63\xb4\xf0\x39\x1a\x99\x27\xe2\x9b\xe5\xd7\x63\x8b\x0d\xef\xb7\xf7\x67\x4c\x04\x4b\x4c\xbb\x63\xff\xed\x14\xa8\xba\x32\x3b\xb7\x57\x4d\x8e\x6d\x38\x02\xb0\xbd\xc8\x5f\x93\x03\x59\x75\xdd\xdd\x80\x52\x6a\x06\x5e\x45\x22\xd6\xca\x9a\x08\x8f\x89\xbf\x9b\x3e\x16\xc1\x7f\x44\xf9\x5e\x47\xeb\x95\xee\x8d\x77\xbb\x94\xdd\xea\xc3\x97\x8c\x71\xcd\x8a\x96\x97\xbe\x02\x47\xf4\xb4\xe4\x4a\x51\x79\x01\xa1\xf8\x70\x1e\x49\x83\xf1\xb0\xa7\xd5\x04\xd3\x37\x04\x17\xd6\xdc\xc6\x1a\x17\xcf\x41\x4d\x5d\xf1\x90\x2b\xa7\xab\x30\xd5\x1c\xdd\xe0\xff\x4c\x88\xe4\x11\x56\x95\x29\xa5\x41\xea\x94\x2a\x03\xd2\x6e\x6b\x7d\xa8\x4e\x6b\x43\x65\xa8\x0b\x55\x25\x4d\xa5\xec\x9b\xd3\x33\x30\xb9\xea\x62\x3d\x38\xd9\x0e\xc5\x5b\xd1\x2c\xd7\xac\xa9\x18\x9a\x61\x35\xc9\x62\x67\x7a\x75\x51\x4f\x83\x91\xad\xa6\x56\x76\xdb\x3d\xbc\x36\x6d\xfe\xfa\x55\xcb\x14\x43\x78\xfd\x32\x75\xd7\xdc\xfd\xf6\xbe\xdd\xbc\xbb\x5e\x78\xe7\xe6\x85\x21\x3c\xa7\x49\x0d\x9b\x6d\xa0\x29\xf7\xc9\x99\x98\xdc\xbd\x51\x8f\xa0\xef\x03\x6d\x8b\xb6\xbe\x35\xce\xec\x4b\x66\x0f\x13\x74\x77\xdb\x56\xe6\xef\xa2\xc1\xf8\x1b\xc0\x07\xcb\x98\xbf\x1a\xca\xf7\x75\x48\xbe\x68\xea\x1b\xe3\xea\xfe\x7c\x7d\xff\xd3\xbb\xdd\xca\x2d\x59\x16\x96\x52\x67\x43\x39\xba\x25\x11\xa3\x86\x00\x7e\x91\xdc\xe5\x8b\x43\x6e\x04\x18\x82\x54\x21\x88\xed\x00\xb9\x5e\xbe\xe1\xb1\x54\x42\x1a\xdc\x86\xdb\xa1\xec\xe5\x08\xf7\xcc\x37\xc1\xc2\x43\xd8\xf6\xbc\x08\xa5\xa6\xbd\xc9\xa9\x68\x1d\xf2\x45\x5b\x80\x72\xc6\x15\xa9\x85\x63\x6f\x1f\xdf\xe4\xf1\xc5\xbc\x1f\xbf\xdc\xb4\xb6\xbd\x5f\xb5\x6e\x15\xfe\xc3\x31\x43\x59\x5d\x1a\x8d\x4e\x27\x4c\xf6\x00\x7c\x4f\x85\x82\x85\x56\x8a\xf3\x68\x52\xd4\xbb\x9d\x7d\x10\x7a\x38\x9a\x24\x34\x0d\xd6\x37\x4a\x09\xe6\x63\xe8\x05\x7a\xe4\x20\xb4\x5f\x5d\x35\x55\xba\x59\xb7\x92\xd0\xb1\x32\x1a\x76\x15\x3c\x5d\x70\x94\x70\x2e\x1d\x71\x8c\xaa\xfa\x89\x5a\xd2\xb0\xed\x89\xb0\x02\xa2\x6e\x38\xc7\x11\x89\x8c\xa0\x00\x22\x97\xf6\x06\x4c\x42\x8e\x04\x3b\xa3\xe6\x89\x17\xd6\x2f\x6b\x06\x91\x0a\x2b\x89\x10\xee\x39\x83\x98\xaf\x24\x12\x28\xc3\x38\x95\xd5\x60\x68\x43\x83\x5b\x82\x30\x19\xa3\xa6\xc0\xa8\xd8\xda\x1d\x59\x47\x4f\x76\xb4\xe4\x47\xd8\x28\x6a\x20\xef\x9c\x7c\x8e\xac\xca\x1a\xb6\xa0\xdc\x8d\x53\xa1\x2a\x7d\xb0\xdd\x90\x99\x23\x71\x72\xea\x56\xc2\x49\x27\x01\x20\x3d\xe4\xf2\x98\x3c\x76\xbe\x95\xff\xa6\xc0\x4f\x66\x67\xf7\xa6\xe7\xbb\x7a\x06\x23\x1e\x2c\xfe\x65\x8c\x78\xad\xe8\x14\x23\x7e\x73\x0c\x12\x2f\x05\x2e\xa6\x00\x7b\x36\x4f\xda\xcf\x77\x67\xe0\x8f\x8a\x3b\xec\xaf\x30\x59\xed\x2e\x67\x1b\x7b\xd9\xb8\xb9\x94\x7d\xac\x71\xc7\xb5\x0e\xde\x92\xf3\x72\x22\x5c\xdd\x33\xa4\x02\xa1\x2c\x3a\xbc\x56\x19\x0a\x9f\x81\x9d\x23\xde\x3b\x9b\x81\x70\x83\x6c\x65\x85\xa0\xc5\x54\xf6\x5e\x43\x9a\x8a\xed\xca\x66\xe3\x64\x6b\x71\x66\x39\xaf\x76\x6f\xa4\x01\x7c\x91\x46\x4d\x7c\x1e\x99\xbf\x26\x78\x7e\x9e\x87\xe6\xaf\xe9\xb2\xb6\xfd\xdd\xf5\xa7\xed\xfd\xf5\x4f\xf7\xdb\x76\xbf\xc8\x3e\x57\x96\xa6\xae\x03\x7d\xaf\xae\x74\xab\xfe\x29\x3a\xcb\x39\xb8\xfe\x25\xf2\x4b\x3b\xc6\xf0\x39\xf5\xfb\x5f\x87\x37\x8a\x3d\x86\xb9\x27\x9d\x32\x73\xd6\x29\x33\xa5\x9d\xea\x59\xa7\x7a\xd2\xa9\x29\xe7\x54\x4f\x39\x65\x34\xe7\x94\xd1\xa4\x53\xae\x90\x45\x4a\xf1\x7e\xd5\xc8\x37\xa1\x9c\xdd\xf0\xa3\x6d\x71\xac\x13\x12\x8a\xcb\xdc\x31\xf8\x78\xc6\x03\xe9\x7f\x3c\x41\x32\xc1\x8f\xed\xe4\x8f\x93\x72\xc7\x35\x1c\xd5\xdd\xd3\xff\x3a\x4e\x13\xc6\xfb\x01\xca\x5e\xfb\xab\xec\x06\xba\xcc\x65\xcf\xbe\xec\x4c\x71\xa5\xc7\x24\x48\xf1\x14\xe6\xe2\x47\x74\x7c\x32\x1d\xf9\x29\x54\x54\xf5\x78\x87\xac\x46\x93\x59\xfc\x38\x56\x34\xcf\xb1\xa2\x53\xe0\x2d\x36\xda\x94\x18\xe9\x90\x17\x09\x15\xe0\xfd\x1e\x0d\x39\xd5\xda\x0e\x8d\x5d\xdc\x81\x7f\xde\x2e\xa0\xaf\xcb\xc5\x94\x42\xde\x4d\x29\xd3\x7a\x96\xbe\x39\x49\x5f\x3c\x4e\xd6\xd7\xf3\xf0\xf5\xb4\x88\x38\xe7\x7e\x84\x47\x1d\xbe\xc2\x75\xa1\xa8\x7a\xf9\xc9\x2b\x53\x0a\xbf\x39\xa5\x5f\xaf\x5b\x9b\xd2\x74\x1f\xc2\x02\x14\x3f\x06\xee\xdf\xe0\x9e\x8b\xea\x4e\x0a\x3f\xaa\xfe\x48\x9d\xa6\xa1\x9b\x0e\x30\x38\xb4\x6e\x74\x18\x8d\x9e\xee\xa2\x9e\x9f\x06\x2e\xa0\xde\xf7\xfc\x25\xc1\x76\xff\x45\x97\x36\x93\xfd\x7d\x70\xd0\x3a\x88\xac\x79\x9c\x42\xe7\x38\xfb\xa3\x1c\x0b\xf8\x4b\xd5\x13\xdf\xee\xc1\xa4\xcc\x94\x32\x8f\x86\x33\x46\x28\x65\x52\x9c\x32\xb2\x24\xb5\xb4\xa8\xaf\xb6\xed\x41\x9a\xd8\x9e\xf0\xd6\x86\x21\x9d\x6a\x24\x2f\x52\x42\x28\xe4\x42\x69\x9e\x3d\xd5\x38\xea\xbb\xae\x7b\x61\xe3\x5d\x7d\xd5\x4c\xef\xaa\x23\xd4\xd4\xe4\xe0\x23\xe4\x19\x75\x03\x48\xa3\xf1\xf0\x47\x48\xf0\xa3\x14\xd9\x9b\xd4\xe1\xcd\x7b\x92\x19\xd9\x34\xf5\x80\xd2\x5e\x64\x0a\x95\x54\x02\x08\x53\xc2\x61\x4d\x22\x92\xc8\x68\x10\x4c\x00\xbd\x77\x64\x10\x4a\x51\x92\x8a\x52\x80\xac\xc8\xa5\xa9\x2c\x1c\x2e\x07\xd1\xbe\xbb\xfb\xb8\x88\x7e\x2a\x4b\xe3\xc6\x41\xb6\x2b\x75\x42\xb7\xf8\x36\x59\xf1\xa0\xa1\xd0\x78\x77\x37\xc5\xb1\x4f\xfa\x8d\x49\xdd\xa1\xea\x8c\xaf\xc8\x58\x36\x59\x96\x7f\x65\xed\x9b\x33\xd5\x0b\x05\xcd\x9e\xf7\x86\x4b\xec\x8e\x3e\xf0\x00\x52\x3f\x6d\xf8\x87\x41\x95\x11\x01\xf2\x00\x1f\x11\xf8\x77\x79\x07\x3c\x05\x61\xfa\x02\x62\xf4\x01\xfa\x8c\x0b\x04\x2c\x9c\x9e\x22\xd7\x2b\x53\xc4\x7b\x6f\xc9\xa8\x6b\x96\xba\xf7\x29\xc6\x90\x3a\x8b\x77\x3f\x24\xa6\x3c\xc0\xbd\x4b\x78\x2c\xaf\x48\x98\x48\xbe\xa4\x99\x88\xba\x33\x3b\x36\x91\x30\x86\x59\x55\x3a\x1e\x5a\x21\x61\x02\xd2\x5c\x93\x25\x95\x7a\x2d\x1c\xd3\x37\x03\x22\x31\xa3\x87\x3c\xce\xca\x20\x22\x72\x43\x38\xaf\x52\xa7\xdc\x91\x72\x62\xf3\x51\x6f\xe0\x2f\x1f\x08\xae\xac\xf8\xa2\x02\x31\x65\xe4\x3b\xc5\x8d\x1a\x98\xa2\x6f\xea\x71\x28\x8d\x84\x80\x19\x2a\x4e\x53\xa8\xb9\x1e\xf4\x09\x9a\xa2\xc3\x26\x99\xdd\xbd\x4e\x38\xb4\x98\xac\xc8\x1b\x30\x0e\x0f\x32\xd5\x4e\xb8\x48\xf8\xc6\x3b\x18\xae\x7c\xa0\xa0\x01\xff\x80\xd6\xce\x70\xe3\x9a\x94\x8d\x8e\xf0\xcd\x39\x78\xd4\x38\x2a\xb5\x65\x4d\x71\xa4\xc0\x25\x64\xf2\x66\x90\x39\x95\x2d\x22\xa3\x2f\x94\x33\x79\x27\xcf\x65\x3a\x31\x31\x61\x44\x94\x82\xb0\x4e\x61\x27\xf3\xa8\x2f\x5b\x84\x00\xb5\x29\x26\x68\xd0\x99\xf7\x58\x77\xe9\x3a\xbc\x86\x07\x99\xc4\x52\xc7\x82\x8e\x50\x3e\x34\x2c\xec\x41\xd0\xac\x59\xfa\xa5\xe7\x6c\x9d\xb7\x05\x5c\xa6\x92\x12\xc4\x18\x54\x5c\x4c\x16\x29\x0e\x42\x21\x69\xa5\x38\x4d\x45\xe6\x3c\x22\x47\x9d\xea\x69\x65\x73\xf7\x6d\x3a\x25\x41\xad\x2a\x3b\x4d\xaa\x3e\x0e\xb0\x92\x6e\xb4\x0d\xb8\xa0\x42\x13\x39\x42\x67\xc3\x50\xb5\x18\xf6\x4a\x8e\xf1\x7f\x59\x77\x61\xe1\x33\x94\x3a\xf2\x03\x77\x6d\x79\x48\xc8\x97\x1a\x1d\x75\x2f\x5e\xb5\x5b\x92\x71\x4d\x3e\x14\xe2\x4e\x93\x18\x3a\x0d\xdb\x01\x69\xcb\xa3\x51\xdd\x97\x0b\x24\x75\x05\x21\x9d\x81\xf2\x08\x7d\x76\x64\x92\xe6\x0d\x17\x68\xb7\xbd\x9c\xef\x11\xdd\x86\x8e\x3c\x54\xf2\xbc\xd7\x01\xc9\xd6\xc0\xdf\x42\x43\x1d\x12\x0b\x4a\x59\xa9\x81\x55\x0b\xa5\x03\x09\x24\xb5\x07\x72\x04\x07\xe1\x4d\x8b\x95\x7c\x68\x5e\x6a\x18\x7b\xb4\x14\x7c\xe8\x1a\xfa\x99\xaf\xe2\xe8\x2c\x61\xdf\xb8\x86\xf1\xc8\xec\x64\x26\xd8\xfd\xdd\x90\xc8\x8d\x01\x89\x96\x02\xb4\xa8\xb2\xb3\x09\x33\x65\x7b\xba\xe2\x3e\x87\xac\x79\x1c\xfb\x0c\x63\xea\x39\x52\x5f\x82\x39\x4b\xad\x73\x6b\x2b\xf4\xad\x17\x68\xf3\x77\xb4\x42\xdf\x78\x81\x36\x5f\xbb\x42\x2f\x70\x1f\x58\x5e\xb1\xcb\xd4\x66\x47\x3a\xa5\x60\x0b\xe5\x54\x66\x57\x62\x60\x6e\x20\x01\x56\xd4\xe8\x02\xd5\x97\x7a\xb5\x27\x43\x0a\x36\x45\xc5\x91\x9c\x48\xdd\xab\x03\xe2\x92\x8c\xcb\xea\xe9\xa6\xc0\x27\xc2\x35\xc1\xba\xb6\x33\xfe\x40\xec\xd5\x82\x05\x8c\x26\x27\x3b\x4a\xd6\x91\xe1\x92\x6a\xbb\x6b\xaa\xa3\x34\xc0\x27\xa0\xc1\x26\x7d\x15\x5b\x20\x55\x9f\xcb\xb7\x70\x15\xc7\x48\x22\x25\x92\x8b\x4d\xd8\x9b\x3a\xd9\x6e\x5c\x6d\x2e\x2a\x97\x83\x76\x10\x4a\x23\xfb\x05\xac\x65\x24\xce\x19\xfe\x3d\xce\x05\x75\x22\xa8\x54\x03\xc9\x58\x75\xa8\x3a\x52\x1d\x28\x9c\x3e\x8e\xc6\xdc\x4e\x66\xa3\xcf\xd1\xe4\x4c\xad\xd6\x0e\x78\x14\x00\xff\x55\x39\x2e\x69\x52\xe6\x08\x51\x79\x9a\x5a\x4c\xc3\x8e\x42\xc3\x26\x2d\xb3\xcf\x9a\x83\xdf\x83\x9a\x09\x90\xaf\x2f\x8e\xb2\x19\x64\x7b\x84\xc9\x72\x20\x63\x37\x3a\x25\x26\x0a\x7d\xd7\x1f\x65\xf3\x35\x3b\xd9\x21\x0c\xe3\x53\x78\x3f\xf5\xe0\x90\xca\x1c\x62\x5a\x4d\xde\x8c\x26\xc2\x12\x57\xfa\xb2\xc5\xa0\xe1\x92\x59\x7d\x3d\xc1\xa3\xe0\xb8\x83\x93\x4d\xa3\x08\x5a\x38\xb3\xd9\xc1\xd1\x3b\x16\x39\x72\xb2\xd0\x01\xf0\x83\x96\xbc\x85\x52\xcf\x81\xad\xaa\x23\xbb\x88\xfd\x5e\x1d\x39\x76\x2d\x65\xd2\xe4\x70\x59\xb7\xb4\xf0\x46\xec\x2a\x26\xc9\xd9\xa0\xe9\x53\x33\xbc\xa6\x2f\x0b\xd4\x6d\xf7\xe5\xd3\xcf\x0f\x3f\x7d\xf9\xbc\x06\xc0\x52\x66\x0c\x6f\xc8\x7a\x75\x2d\x68\xb0\x3d\xc1\x3e\x6f\x27\x21\x80\xed\x34\x8a\xef\x70\x20\x00\x25\x54\x69\x0a\x71\xc0\xd6\xda\x19\xaf\x2c\x5e\x91\x8b\x1e\x29\x0c\x9b\x7c\x49\x56\xc3\x8e\x14\x8f\x93\xa1\xad\x76\x05\x81\x7b\xae\x07\x9b\x0b\xef\x57\xe4\x28\xa9\x5d\x00\xb1\x6d\x3d\xfe\x9a\xad\x06\xe2\x39\x65\x99\x32\x00\x69\x90\xf1\x22\x52\xe7\xc8\x9a\xd1\xd8\x80\xc0\xcd\x68\x64\x4e\x50\x1b\x80\xac\x61\x08\x5d\xbc\x81\x41\x43\x7f\x73\xb9\x19\x0d\x86\x04\xee\xec\xde\xa4\x60\x77\xbe\x3b\xa4\xf7\x38\x22\x04\x1e\x60\xd7\x03\x9e\xb4\xf9\x1e\x71\xd0\xf4\x45\x95\xad\xab\x5e\xe3\xa3\x03\x2f\xe3\xc9\xc3\x68\xef\x77\xec\x78\x64\x35\x20\xc8\xaa\xa7\xdc\x67\x3e\x52\x4c\x23\x28\x25\xc1\x7d\x27\x42\x76\x41\xac\x96\x57\xe4\x53\x4a\x55\x44\xdb\x08\xe1\x97\xb9\x8e\xdd\x6e\x6c\x29\xc6\x9e\x5b\x38\x74\x77\x2d\x86\x9b\x9d\x5c\x1a\x50\xf2\xcd\xb8\xc2\x39\x29\x10\x72\xa9\x2a\xff\x71\xf2\xa3\xe6\xb9\xae\x53\xc6\x61\x70\xa3\x45\xc1\x34\xd4\x35\x5b\xee\x0c\xd5\x9a\x58\x86\xd1\x51\xb6\x20\xce\x1a\x64\xbc\x29\x6e\x54\x0e\x8c\x9c\x13\x8b\xe5\x4e\x3b\x53\xfd\x28\xa2\xa2\x8a\x5c\x07\x7f\x55\xd8\x36\x21\x8c\x41\xef\x18\x40\x42\x0b\x05\x75\x95\xbd\x28\xfc\xab\x54\x73\x46\xf4\x77\x39\x8c\x3e\xc1\x5c\xef\x33\x14\xab\xb1\x08\x07\xc7\x36\xcb\x49\x45\xaa\x42\xa7\xe6\x26\x52\xaf\x26\xb5\x03\xc1\xa9\x10\x4e\xc3\x13\xa4\x12\x80\x8f\x0a\x2e\x1e\x6c\xe6\x2e\x45\x62\x02\xb0\xca\xa0\x68\x30\x0c\x2a\x23\x67\xb8\xba\x1d\xe7\x34\xb2\x0d\x53\x10\x4b\x4e\x0d\x14\x21\x5f\xf6\xcb\xef\xa7\xf4\xfd\xdd\x2f\xb7\xab\xe7\xb4\x9c\x9c\x53\x5b\xd6\xf2\x15\xbc\xfa\xa0\x2a\xed\xf5\xdd\xac\x4c\x22\x1d\xf6\xfd\x32\xaa\xa7\x40\xdf\x4a\xad\xef\xad\xd1\x52\xaa\x10\xbe\x64\xdb\x31\xdc\xd2\x74\x3f\x5a\x38\x6b\x1e\x6d\xd3\x79\xef\x8e\x11\x5c\x02\xc1\xfb\x54\x36\x89\xf0\x15\xae\xeb\x45\x02\x77\x0b\x92\xc8\xe1\x08\x5c\xc1\xe1\x18\x71\x70\x27\x45\xb8\xa6\x4f\x3d\x1c\x29\x33\x9f\x33\xd3\x0f\x9e\x99\x0e\x62\x3f\xe5\xfe\xf4\xc8\xca\xde\xeb\x67\xb9\xf5\xb3\x7d\x74\xdc\x3b\x05\x38\x50\x85\x36\x93\x0a\xa5\x1d\x63\xc4\x35\x46\x9d\xae\x04\x96\x73\x40\x47\xa4\xa7\x1d\xd3\x24\xa5\x53\x63\xd5\xcc\x9d\x42\xc3\x9a\x92\x34\xd9\xb1\x15\xdb\x04\xe4\xae\x99\x89\x02\xee\x84\x26\xc2\x63\xb7\x53\xc9\xd6\xc9\xe6\xe3\x46\x4f\x6b\xe4\x0e\x5a\x20\xc4\x4d\xf7\x92\xd0\x01\x6c\xae\x9d\x5c\x38\x23\xa4\xa6\x4a\x7d\x0b\xaa\x1e\xb9\xa8\x04\x0b\x61\x11\x11\x29\x98\xcc\x79\xf7\x9a\x79\x4f\x9f\xa0\xe2\x41\x08\x93\xe9\x8c\x81\x8a\xeb\x09\xca\x55\x3f\xc7\x79\x56\xf8\x7a\xa6\x14\xe0\xe6\x0a\xeb\x03\x4e\x16\x70\x65\x85\x01\x64\xf5\x76\xe6\x18\x77\x40\x79\xfc\xda\x93\xbc\xd9\x09\x1d\x70\x20\x91\x20\x0c\x23\xe6\x33\x90\x73\x9e\x52\x6a\xce\x5a\x72\x6e\xc7\xec\x10\x5e\x28\x7f\x80\xcb\xc8\xb5\x75\xd8\x77\x24\xf3\x1e\x93\x52\xb3\x89\x60\x41\x59\x25\xfc\xa3\x50\x33\x59\xad\x94\x69\x22\x74\xc8\x92\x0e\xe6\x2b\xd5\x51\x08\x63\xf6\xd4\xe9\xe3\x33\x69\xa4\xae\xef\x7f\xda\x5d\x0f\x8b\x40\xfd\xb2\x70\x66\x2a\x35\x1d\xeb\x0d\x23\xbc\x1f\xbd\xaf\x83\x09\xea\xb5\x93\xf4\x26\x13\x69\x01\x34\xd1\x8d\x42\x7c\x61\x9f\xef\xde\xe0\x1d\x1b\xcc\xf7\x13\x49\x8e\x9c\x1d\x4a\xa2\x68\xed\x60\x7c\x0a\xe4\x63\x18\xe5\x1a\x40\x6a\xe7\xa8\x01\xe6\x3e\x53\x4c\x14\xd2\x10\xad\xa3\xec\x07\x27\x0f\x22\x7c\xb7\x02\x13\xf2\x77\x5c\x1c\xe2\x6e\x7b\x7d\xdf\x7e\xda\x7e\xfa\xdc\x96\xda\xd1\xa5\x8f\xcd\x93\x38\xdd\x8a\x65\x46\x42\x77\x1d\x84\x87\x0f\x78\x2d\x57\x93\x97\x7b\xc7\xab\x09\x48\xa1\x5c\x8b\xb2\xb9\x42\x02\xd4\x9f\x8c\x95\x4b\x0b\xcd\xa8\xee\x0c\x21\xd5\x56\x2d\x6d\x9a\xff\x01\x3e\xe3\x55\x39\x36\xf8\x64\x69\xbe\xdb\x82\x9b\x4a\x0d\x72\x78\x55\xde\xd4\xea\x00\x11\xca\x4e\xc3\xe4\xa5\x4d\x53\xd0\x03\xa4\x1b\x54\x6b\x88\xf6\x4a\xce\xbf\x76\xd5\x75\x93\x9e\x5e\x83\xa9\x10\x97\xac\x6a\xc3\x58\xe0\x98\x6e\x87\x58\x84\x56\xd6\xcd\xc8\x45\x1e\xeb\x7f\x7e\x36\x65\xd6\x6e\x80\x46\x3e\x6b\x04\x85\x45\x3b\x98\xe4\xe0\xc6\x73\x94\xca\x02\x6a\x04\x91\xdf\x02\x71\x91\x02\x81\x92\x75\x33\xe0\x09\x1c\x7b\x53\xd3\xb4\x0a\x1d\xdd\xa2\x50\x07\xa5\xd1\x00\x71\xee\x78\x73\x2a\x91\x39\x88\xa6\x99\xbc\x90\x3a\xb8\x5f\x84\x31\xe1\x68\xe9\xa1\x71\x9a\x5e\x5a\xe4\xa6\xd2\xd4\xd3\x16\x9c\xbb\xd0\x9b\x54\xe4\x42\x05\xdb\x40\xa9\x3f\x55\xbf\x6e\x27\xac\x5c\xd3\x2a\x1c\x62\x2d\x1d\x10\x21\xbc\x7a\x8c\x84\xc6\x10\x78\xc3\xe5\xf8\xef\x87\x9b\x8f\xb7\x77\x5f\x96\x77\xde\x25\xdf\x9c\x14\x2c\x69\x44\x7e\x20\x04\x96\x2a\x1f\xef\xf4\x16\xe8\xb1\x84\x1a\xcb\xaa\x3c\xc9\xc4\xe6\x4f\x59\x04\x2e\x5a\xb1\xba\x1d\xe9\xac\x11\x4b\xaa\xb8\x94\x53\xfd\xeb\xfa\x74\x2e\xad\x74\xb6\xe1\x5c\x5a\x69\x57\xca\x8e\x79\x87\x5f\xb0\x35\xfb\xa7\x6f\x05\x92\x4e\xcb\xb0\x6b\xa9\x27\xa4\x30\x7f\xa9\xac\xf9\x40\x44\x84\xf6\x75\x4c\xb6\x0b\x90\x8a\xa5\x9c\x47\x4e\x5b\x75\x0f\x0e\x61\x8a\x56\x3a\x83\x46\x38\x35\xfc\x72\x27\x86\xe1\xe6\xf6\xcf\xdb\xf7\x37\xeb\xf8\x49\x65\x86\x59\x77\x00\x1f\x71\x3b\xe7\x79\x9f\x6a\xd8\x19\xf9\x62\x52\x0d\x8f\x6f\x43\xf1\x8a\x34\x62\x58\x95\xcd\x89\x4a\x6a\xc2\xc4\xf9\x20\x14\x00\x13\x18\xba\xed\xc3\x28\x87\x17\xb9\xb3\x10\x60\x19\x11\xad\x0b\x41\x62\xc7\x63\x94\x9d\x54\x63\x77\xd0\x4f\x60\x2a\x1f\xdf\xb2\x15\xf2\xd0\x3b\xe0\x2b\x02\xb6\x80\xbd\xec\x09\x31\x05\x5c\x3d\xe5\x23\x43\xac\xd5\xc8\xf2\x9d\xdb\xb3\x65\xf4\x56\xd8\x6e\xdd\x12\xd2\x7f\x54\x83\x99\xf4\x85\x84\x96\x0b\x8b\xe6\x85\x86\x2b\xed\xcc\x01\xb6\x8a\xcd\xc8\xac\xb1\x4f\x70\x4e\xc8\x7b\xe3\x33\x7f\x3f\x03\xfb\xb7\xb3\xaf\x7f\xfe\xf2\xb0\xfb\x7c\xb3\x5c\xe0\x25\x56\x08\xc7\x39\x11\x66\xb1\x94\xb2\xeb\x20\x7e\xa7\x66\xe0\xf6\x24\x33\x47\xf7\xa3\x3d\x67\x01\xee\x16\xde\x6e\x27\x5b\x73\xb8\x0a\xae\x0e\xd0\x3b\x85\xe2\x47\xd3\x6f\x6c\xbd\xa7\x9c\x3d\x1c\x6f\x4d\x78\x30\x25\xa8\xf2\x8e\x5c\x1e\x84\x8b\x0b\x25\xee\x4c\x58\xf7\x98\x84\xba\xdb\x13\x0c\x07\x4e\x29\x33\xf0\xc8\xe4\x12\x42\x6a\x94\xe3\xe0\xba\xcd\x8a\x77\xe9\x4e\xce\xf8\x32\xcc\xad\x3d\x71\x4f\x55\x5f\xd3\x8a\x80\x7b\x05\x3c\xc3\x35\xa7\x06\x0b\xf7\x6c\x78\xc7\xf6\x2f\x6d\x7b\x7f\x7b\x3d\xfc\x24\x47\x72\xb1\x50\x17\x7d\xb1\x44\xfa\x48\x56\x03\x22\x5f\xb0\x1b\xcb\xf3\x8e\x07\x0a\x78\x74\x7e\x37\x0a\x49\x7f\x8a\xbb\x34\x43\xca\x2c\x60\xaa\x80\xfb\x7c\x21\xcd\xff\x19\x72\x7c\x26\xcb\x7f\x87\xc3\x3a\x89\xb8\x4a\xcb\xee\x4c\x56\xf2\x90\xdd\xc1\x0b\xf8\x02\x2c\x27\x02\x88\xd3\x60\x12\xb4\xa8\xf1\xeb\x60\x39\xe5\xe5\x14\xdd\x5c\xdd\x05\xaf\xbf\xaf\xc9\x3f\x7c\xf3\xf1\x76\x79\x88\xeb\x01\x00\x9d\x4b\xf8\x7b\xb8\x90\xba\xef\x69\x75\xb3\x2f\xf0\x33\x3b\x56\x99\x8c\x73\xa1\x82\x1d\xf0\x89\x9c\x55\x2f\x54\xb0\x08\x5e\x01\x14\x00\x62\x30\x69\x61\x53\x67\x36\x56\x36\x95\xf6\x03\x56\x7b\x0d\x7f\x35\x3d\x6a\xd6\x60\x56\x58\x44\x6b\xdf\x95\xc5\xdc\x3f\x7d\x33\x05\x4a\x61\x93\x41\x11\x27\x78\xaa\xd7\x75\xe6\xeb\x89\x7a\xbb\xbf\xfb\xbc\x5b\xc8\x0f\x75\x89\x35\x71\x9c\xe5\xb9\x50\x8a\x7e\x34\x39\x10\x23\x52\x32\x90\x87\x7f\x52\x4c\x72\x99\x75\x50\x26\xbd\xb5\xe1\x70\xd6\x55\x05\x7c\xec\x31\x5c\x7b\x26\xcd\xe9\xa6\xcd\x40\x8b\xe7\x91\x03\x93\x93\x43\x09\x1f\x03\xf6\xad\xaa\xbb\x9a\x9b\x3d\xf2\x63\x9a\x1d\x3e\xb3\x10\xfb\x49\x02\xe8\xf2\x09\x03\xaa\x39\xfb\x09\x11\xd2\x69\xfa\xb0\x10\x44\x2e\x51\x73\x9f\xc2\x99\xd5\x09\x49\x1d\x20\x0a\x2a\xc3\xa8\x2b\xf5\x64\x29\xee\x28\xf6\xaa\x4c\xa8\xbc\xe9\x00\x97\x3e\x8f\x19\xa0\x27\x0a\x2f\x84\x00\x9b\xd8\xf3\x08\x21\x51\xcf\x39\x1a\xa6\x44\xf3\x69\xf0\x27\x4a\xa7\x4a\x51\xb3\x08\x21\xf1\x0d\x6a\x96\x8a\xc7\x24\xb7\x14\xda\x05\x14\x89\x6c\x5c\xee\xba\x5c\x74\x54\xb5\xb9\xe8\xbf\x3a\x1a\x46\x0f\xa0\xaa\x1a\xa9\x42\x91\xe7\x09\xc2\x44\x84\x05\x41\xb5\x06\xbe\xcb\x25\x8c\x38\x37\xdb\x74\x0e\x39\xf8\xee\xde\xfa\x04\x61\xd5\x15\x59\xae\xcd\x5a\x3c\x78\xcc\xe9\x7c\x64\xb7\x9c\xea\x57\x02\xb3\x7e\xbc\x69\xbb\x2f\x3f\xaf\x32\x92\x75\xf6\xe0\x8b\x5c\xc9\xfb\x34\x06\x4a\x64\x3c\xb1\x1f\x0d\xdc\x37\x39\x90\x83\x92\x39\xc1\x0a\x03\x05\x6a\x06\xd3\xe1\x1e\xdf\x06\xe0\xb1\xe7\xd1\x44\x14\x75\x24\xd7\x09\x29\xe0\x05\x23\xae\xa7\x00\x47\x23\x8e\x89\xa0\x2a\xf4\x8f\x6f\x43\xb4\x14\x38\x8f\x00\x94\x43\x7c\x69\x26\x07\x2b\xb2\x83\x4d\x22\x12\x50\x2d\xe5\x6f\xb9\x47\x1e\xdf\x86\xcc\xe4\x6b\x18\x1d\x31\xb1\x22\xb4\x35\xd3\xcd\x3e\xd2\x9c\x46\x0f\x79\x0d\xb7\x51\x5f\x14\xe0\xa2\x3c\xbe\x8d\x31\x93\xe7\x3a\x3a\x29\x53\x89\x59\xc6\xd4\x93\xf5\x87\x0d\xb8\x19\x05\x25\x67\xa8\x85\x49\xa6\xff\xf1\x6d\xac\x95\x3c\x3c\xd0\x61\xa9\x22\x45\xd8\xec\x57\x4e\x69\x52\x37\xfe\x2d\x8f\x6f\x93\x2f\xe4\x1d\xf8\x22\xc5\xda\x88\x60\xbc\xa4\xc5\x3e\xf2\x04\xda\x62\xbb\x6f\x86\x5e\x01\x0e\x27\x2a\x5a\x42\xf0\xa7\x4f\xd0\x8f\xe8\x17\x83\x6f\x00\xd5\xf1\x49\x35\x5c\x29\xab\xc1\xc0\x02\x69\x2c\x22\x8f\x17\x50\x1c\xe5\x47\x50\x31\x8a\x0d\x2c\x54\x07\x1d\x30\x8c\x4d\x9a\x00\x88\xa4\xe7\xb4\xeb\x13\x35\x54\xc9\x84\x42\x61\xd3\x8c\x02\xed\xc9\xf5\x29\x04\x3b\x40\xc5\xe0\x3c\xb4\x77\x31\x53\x56\xac\x0f\x58\x97\xc8\x5f\xc5\xc1\x40\x5b\xa1\x5e\x0f\x41\x81\x43\xab\x3e\x02\x86\x08\x72\x19\xc2\xaa\x39\x83\x15\x41\x73\xd3\x31\x96\xd4\x8d\x25\x38\x05\xd9\x03\xdc\x53\x91\x77\xe5\x0d\x21\x0a\x59\xce\x80\xf7\x94\x2a\x62\x8b\x93\x5a\xa0\xa0\x8d\xc8\x9e\x7c\xed\x3a\x80\x9c\x1a\xa4\x4a\x42\xe8\xc3\x68\x29\x03\x21\x1e\xe9\x9e\x5c\xa0\xe4\x28\xc2\x57\x8c\xa5\x0a\x4d\x74\x25\x3d\xd5\x28\x0b\xc4\xf1\xe0\xfa\x4d\x9b\x31\x16\x62\x68\xca\x89\x73\xd3\x58\x72\xb8\x3a\x64\x0d\xd9\xe1\xd2\xd0\xa0\x4b\x2d\x66\xaa\xa3\x53\x6a\x1a\xd5\xb7\x2d\xca\x3e\x2d\x04\xbc\x16\xaf\x38\xc3\xb9\x5b\xd3\xac\x3d\xcc\x35\x50\x16\xfd\x44\x28\x9b\x49\xdd\x35\xab\x41\xe9\x80\x23\x02\xef\x1b\x38\x87\x08\xe9\xec\x70\xa1\xca\x51\x57\xbd\xa7\x8c\xe2\x5b\xc9\x46\xd4\xdb\xa7\x87\x8a\xc4\x51\x04\xad\xe8\x48\x11\x5f\x20\xaf\x15\xc2\x36\x79\x2a\x08\x6d\xfe\x1e\x24\xa1\x2f\x9f\x87\xbb\xeb\xf7\x6b\x56\x81\xfa\x0c\xf4\x8b\x9c\xab\x5f\x6b\x27\xd0\x0c\x35\xbf\xb6\x16\xb9\x4b\x27\x00\x94\xb3\xd8\xaf\xc8\x01\xbf\x82\xfd\xea\x27\x70\xda\x13\xd4\x71\x97\xe1\xcb\x1e\x53\x07\xa4\xac\x6e\xd3\xba\x9e\xd0\x6b\x36\x6b\x58\x59\xf5\x27\x9f\x1a\x4a\x55\x87\x17\x57\xee\x89\xb7\xec\x7d\xa5\xea\x3b\x5e\x93\x74\x10\xea\x7a\xdb\x39\x8d\xb3\x30\xf9\x4f\x53\x74\x9f\x60\xc9\x4f\x78\x10\x10\xd7\x00\x7e\x81\xea\x7d\x95\x8b\x22\xd5\x21\x08\xc9\x09\x05\xb9\x67\x9f\x04\xc8\xc8\x23\xb4\x0a\x17\x45\x15\x67\x9f\x41\xc2\x1b\xb6\x9f\xee\x96\x37\x59\x38\xa4\xcb\xb1\x19\x09\xfa\x2d\xbc\xb7\x70\xb5\x76\x93\x22\x70\x1f\xe5\x28\x79\xf5\x0a\x0d\x41\xe8\x35\xd0\x00\x4c\xa0\x1e\xc2\x20\x34\x50\x15\x7f\x91\xe0\xb4\xd1\xad\x3e\x96\xa2\x30\x3b\x70\xfe\xf2\xa4\xe1\xc6\x50\x24\xaa\x05\x5e\xe7\xf1\x4a\xc1\x50\xba\xe7\x83\x0b\x0d\xc0\x09\x2e\x4c\xe0\xaa\x9d\x81\x53\x45\xed\x04\x06\xd6\xa1\xf1\x3c\x50\x7a\xb2\x32\x53\x4e\x6d\x18\x6a\x54\x44\x2a\x29\xee\xb6\x98\x6e\x6a\x86\xe7\x5c\x9a\x80\x36\x01\x73\xb0\xe9\x7b\xae\x27\x63\x74\xb6\x4d\xdf\x34\x38\x17\x81\xa9\x22\xd1\x29\x9f\xd2\x11\x7d\x01\x5e\xa5\x80\x08\xca\xfe\x28\xdc\xad\x82\x6e\x72\xeb\xf9\xb1\xc6\xa8\xa0\xc1\x47\x51\x8c\x87\xef\x23\x17\x38\x89\x95\x40\x42\x7c\x1d\xd6\xb8\x73\x9b\x6a\xd9\x4d\xa9\xa7\xa1\x8a\x0a\xb5\xad\x67\x2e\x52\xee\x7e\x11\x09\xe4\x92\x8c\x77\xca\x44\x55\x5c\x1b\x38\x1b\x48\x33\x6d\x75\xe1\x82\xaa\x8c\x81\xd0\x10\xe4\x0a\x8f\x1a\x90\x92\xed\x64\x32\x48\x15\xdf\x70\x1d\x58\xe5\x3e\x75\x54\x72\x91\x4c\xdf\x47\x99\x50\x10\x55\xf0\x11\x6a\x64\x57\xfb\x68\xdf\x03\x22\x49\xca\x29\x94\x7f\x73\xc7\x8c\xd6\x2c\x94\xaa\xf5\xe8\xdf\x59\x5d\x63\x19\x06\x42\x44\x19\x68\x22\x5c\x67\x15\xb5\x1c\x75\xd6\xd0\xe4\x46\xe7\x98\xc6\x5c\xe4\x7e\x75\xde\x49\x3d\x23\xd7\x40\xb9\x08\xb3\x41\xb9\x8c\xd8\x36\x3d\x7d\x8b\x0b\x3d\x31\x99\x71\x90\xd1\x2c\xc5\x4c\xc2\x10\x53\xdc\x8c\x45\x0f\x7c\x21\xf4\xb9\x69\xa6\xc1\x09\x55\x11\x1c\x14\x08\x4e\x9c\xfc\x93\xd9\x03\x28\xac\x3b\x86\x00\xf5\x2d\xcf\xfa\x1b\xe4\x08\xc6\x2d\x1d\xa6\xc0\xec\x02\x54\x72\x03\x94\x8c\xcb\xca\xab\xdd\xdd\x12\x65\xad\x2e\x9d\x75\x9f\xc0\xdc\xba\x3a\x25\xaf\x56\x07\x55\x55\x23\xf1\xe4\x38\x04\x72\x87\xe9\x76\x1a\x20\x04\x6b\x05\x78\xf3\x92\x34\x2a\x49\xb5\x4c\xd1\x93\xa2\xeb\xcc\x70\xf6\x90\x11\xf5\x30\xe2\xf2\x56\x03\x64\x05\x86\xba\x5c\x8e\x51\x71\x4c\x8a\xd7\x74\x33\x00\x1d\x14\x92\xcd\x09\x96\x7a\x72\xdd\xdc\x97\xb3\xba\xaa\x23\x03\x13\x38\xc4\x42\xa1\x76\x5d\x97\x6e\x17\xc8\x09\x21\xf7\x9d\x10\xf3\xcc\x94\x7a\x8d\xb1\x8c\xb2\x25\x84\xcf\x48\x04\x7b\xa1\x4d\xc4\xce\x8d\x2e\xea\xc6\x82\x25\x41\x89\x35\x4f\x48\xd9\x42\x00\xc1\xd6\x25\x70\x16\x19\x6e\x9b\x42\x65\xe0\xe7\x15\x9a\x9f\xd0\x81\x14\xb4\xe0\x2a\x8e\xf0\x6f\xd3\xd8\x16\x17\xd5\xf9\x41\xad\xbd\x59\x7d\xdb\x3b\xce\xa6\xfa\xb9\x1b\x61\x2d\x85\xc7\x8c\xb1\x7f\x8a\x10\xa5\x3e\xd9\x6a\xde\xa7\x09\x66\xa0\xcc\xdb\x03\x8c\x7e\x98\xd4\xee\x75\x54\x07\xf6\x4c\x80\x91\x71\x3e\x8a\x1c\x0a\x50\x99\x11\x8c\x27\xd4\x09\xdc\x61\x05\x39\x6c\xda\xac\x1d\xec\x6e\x4c\xe0\x5b\xe1\x19\x07\xa4\xa4\xe8\x29\xb9\x16\x23\xfe\xd5\x68\xe9\x3e\x19\xe8\x42\x6e\x13\x52\x37\x78\x5f\x35\xbd\x8f\xf8\xa2\xd0\x4a\xb0\x62\xa5\x1e\xa5\xdb\x90\x1c\xcd\x8e\x59\x51\x2b\xa5\xab\xd1\xcb\x1c\x65\x45\xdd\x7b\x0e\xa8\xe2\xdd\x9f\xd7\x0d\x7f\x75\xe9\x1b\x77\xb4\xa3\x19\x26\xa7\x32\x45\xea\x7e\x33\x6d\x9a\xbe\xb0\x54\x7c\x74\xa7\x06\x65\xee\x7a\xad\xbf\xbd\x5e\xb1\x78\xb7\xf9\x15\xcc\xdd\xcf\x77\x77\x7f\xfe\x74\x7d\x7f\x6e\x82\x97\x80\x28\xae\xcc\xb1\xdb\x1c\x5d\x9f\xe0\x29\x2e\x35\xb8\x21\x38\x4f\xc1\xa6\xa1\x54\x2a\x51\xfe\x35\x25\xe2\x47\x13\x6c\xda\x4b\x11\x60\xfe\x87\x9e\x5c\x42\xa8\xbd\x5c\x1c\x75\xf4\x2a\xff\xa9\x6e\x22\x70\x0f\xcb\x4f\x8a\xf5\x56\x27\x7c\xe0\xe9\xd7\x09\x25\x7d\x42\x1f\xe9\x26\xcb\x32\x63\x5f\x79\xf2\x6e\x30\x21\x30\x05\x60\x5b\xc3\x6d\x42\xae\x7b\x44\x96\x7b\x94\x30\xde\x43\xb2\x82\x07\x06\xd5\x51\x7e\x87\x1f\xa9\x83\xdc\xd5\x25\x1a\x85\xf3\x81\xc3\x92\x0f\xd4\x7f\x6a\xbd\x8c\xf0\x80\x55\x46\x50\x77\x6c\xc3\x65\x71\x1f\x54\x79\x5d\xda\x2f\x27\xf1\xa0\x5e\xf3\x66\x32\xfc\xb0\x13\x18\x24\xc5\x8c\x06\x06\x83\x9b\xdc\x5b\xd4\xb0\x07\x28\x78\x64\xf7\xd2\x84\xc4\x22\xf3\x7b\xd5\x1d\x7a\x38\x63\xb1\x12\x71\x60\xc2\xc2\x06\x90\x0e\x36\x02\x05\x9f\x0f\x71\x72\x40\xc3\x37\x3f\x3d\x1f\x8d\x5e\xe2\x49\xc5\xc9\xa6\x42\xab\x32\x29\xdd\xcb\x9e\x03\xe1\x6e\xa8\x95\x62\xec\xf7\xbd\xf6\x4b\xe8\x38\xe0\xe1\x45\x5c\xf5\x9a\x85\x8c\x83\x2a\x21\x39\x37\x03\xa7\xcd\xa8\xce\x35\x1d\xce\x54\x31\x3d\x40\x99\x10\x50\x1a\xba\x43\xa8\x7c\xce\x5a\x40\xdf\x0b\x0a\xe9\x15\x52\x0d\xb8\x4d\x80\x66\x23\x82\xc9\x13\x0c\x4f\x1d\xef\xcd\xa9\x5e\x69\xc2\x03\xc8\xd3\x6f\xca\x2a\xa8\xdf\xa8\xc6\xd2\x4c\x1b\x07\xce\x65\xce\x75\xd8\x7f\x26\xa4\x62\xab\xaa\xda\x80\x53\xa6\xed\xe1\x3b\x3d\xe5\x9a\x0f\x2d\x2a\xba\x56\x83\x07\x1b\x9c\xf8\xe1\x0c\xaa\x2c\x9e\xfc\x02\x06\x1a\x7e\x20\xac\x97\x1a\x1e\x38\xab\xf9\x28\x3b\xae\x46\x82\xbc\x6e\x3a\x0b\xcc\x8a\x2a\xec\x26\x4c\x7c\xc3\x16\xbf\xd4\xee\xec\xa3\x4c\x21\xfc\x9b\xc0\xfe\xe1\x57\x1f\x54\x7f\x58\x10\xa6\x10\x3d\x39\x27\x77\xdc\xef\xd5\xfc\x76\x11\x55\xa5\x87\x4f\x2f\x4e\xca\xc5\x9c\x45\xc9\x21\x97\x48\x19\x4d\xca\x04\x97\x0a\xa8\x6c\x39\x65\xf8\x09\x42\x44\x08\x1d\xbd\xc7\xaa\x7f\xa1\x53\x1f\x0b\xee\xfa\x98\xd0\xd3\xbb\x6b\x37\x15\x46\xd0\x45\xb8\xe7\xa4\x66\x3c\xb8\x38\xe5\x62\xbb\x7b\x6d\x4d\x70\xae\x92\xcb\x16\x3c\xa3\x09\xa3\x03\xc6\x76\xb0\x93\x5f\xbb\x05\x1e\x2c\x97\x42\x49\x59\x61\xe9\x08\xe2\x71\xe0\xe8\x04\x9c\xf8\x38\x42\x0c\x29\xe0\xe8\xd5\x2d\xc4\x77\x85\x92\x70\xb1\x33\x97\xec\x6c\xbc\x8a\x7b\x44\x87\x4b\xf7\x91\xf7\x3a\xf0\x06\xd7\x5b\x50\x9c\x3e\x62\xc6\xc9\x46\xb8\x89\xa5\x02\x9f\x25\x4e\x7e\x44\x64\x39\x87\x4a\x4e\x85\x1d\xa7\xce\x5e\x1a\x8a\x59\xe1\xc3\xaa\x49\x2d\x0b\x69\xb0\xa7\x0f\xaa\xd7\x76\x4e\xf9\x04\x39\xc2\xf2\xc3\xe4\xef\xe4\x53\x4f\xaa\x6c\xab\x30\x49\xce\x46\x61\x97\x35\xa0\x48\x7d\xf7\x9d\xfa\x3c\x55\x24\xdb\x61\xf8\x08\xbd\x28\xaa\x79\xb1\xec\x4b\x17\x1f\xeb\xa6\x65\xaf\x51\xc6\x2a\x37\x90\x4b\x61\x67\x38\xe6\xd9\xc9\x5d\xd8\x67\x91\xc5\x70\xa6\x6c\xd9\x8b\x90\xb6\x73\xd5\x0f\x88\x0b\x74\xaa\x96\x0f\x7b\x93\x63\xdd\x19\x6f\xd3\x1e\x5f\x5c\x8c\x7b\x79\x86\x4f\x86\x2d\xb7\x08\xb7\x08\x1d\x02\x02\x56\xb3\x06\x04\x8e\x1c\x32\xbc\x30\x9e\x87\xcf\x55\x5d\xef\x62\x5c\x3f\x7f\x75\xbe\x25\x0d\x3d\xc0\x8a\x2a\x42\x49\x87\xa9\xeb\xd6\x53\x85\x77\x14\x56\x3e\x42\x82\xc8\xa0\x90\x48\x6f\xe2\xc9\x42\x63\xd7\xdd\xf6\x27\x11\xa5\x66\x85\x57\x0e\x4e\x68\x4a\xd2\x11\x0a\x7d\xac\x81\x7c\x6d\x85\x09\xf2\x69\xf4\x00\x5a\xd4\x38\xfb\x68\xbb\x9c\xa5\x30\xe6\xce\xa6\x51\x93\x81\x9a\x42\x0a\xc7\x53\x08\x01\x98\xea\x27\x59\x9d\xdc\xb4\x83\x1e\x3c\x91\x12\xab\xef\x7a\x1d\x07\x77\x22\xf9\x34\x4e\xc1\x9f\x98\xd5\x1d\x92\x5c\x6e\xa6\x00\xa1\xa5\x74\xe1\x1c\x56\x23\x55\x7f\xc8\x75\x0d\x49\x29\x8c\xc0\x51\x2f\xb9\xe3\xa9\x2b\x7e\x41\x89\xdd\x6f\x9f\xa3\xd5\x2b\x1b\x48\x96\x45\x3d\x5f\x32\x62\x01\x7c\x9d\x62\x33\x45\x1a\x41\x4a\xd4\xd4\xdd\x92\x45\xca\xc7\xa1\xb1\xdd\x00\x08\xa1\x46\xa8\xaf\x26\xd8\x51\xa0\x46\x75\x82\x72\x3d\x65\x8d\x97\x31\x16\x78\x9f\x36\x45\xd1\x14\xfe\xc3\x59\xf2\x93\x23\x9d\x53\x7d\xc4\x06\x92\x20\xce\x36\x30\x1b\x81\x3e\xc4\x6e\x90\xfa\x47\x15\xb1\xa8\xe3\xdc\x94\xee\x13\x1a\x79\x50\xf3\x2a\x70\x97\x3c\x4e\xb6\xa2\x3d\xa4\xac\x38\x81\x9a\x10\x4c\x55\xa4\x5e\x23\xc9\xd4\xad\xb0\x90\x32\xfc\xa5\xaf\xba\x92\x31\xab\xde\x5e\xdc\x9d\xd4\x83\xc6\xe5\x89\x18\x0c\xff\x6b\xf5\x00\xe8\x49\xdf\x14\x15\x3c\xaa\x64\x2d\xbb\xf4\xd9\x3c\x5d\xae\x32\x79\x2b\xd2\x10\xc2\xfe\xb8\xa7\xab\xec\x8a\x7e\xb5\x2a\x64\x35\x50\x8c\x15\xe6\x01\x4f\xee\xf1\xad\x77\x8e\x5c\xe6\x31\x43\xec\xd1\x70\x07\x0b\x61\x2f\xc9\x24\x62\x4b\x83\xaa\xcf\x49\x0e\xe5\x94\x3f\xbe\xf5\xd1\x91\x73\x69\xac\x84\x2b\xb1\x0a\x39\xc3\x9c\x66\x52\x94\xee\xa8\x4e\xe0\x8d\xa5\x3b\x8f\x6f\x7d\x0d\x48\x58\x52\x08\xb1\x11\x3d\x50\x0e\x5e\x7f\x58\x2d\xb0\x95\xe0\x39\x47\x56\xff\x0a\x00\x9d\x3d\xbe\x0d\x22\x43\xc6\x3a\x2a\xce\xbb\x30\x1e\x88\xc8\xd0\xb2\x32\xfd\x68\x35\x02\x85\x0d\x56\xde\x04\x44\xe8\xd0\x29\x72\xef\x13\x08\xbd\x92\xa9\x04\x53\x47\xcf\x4a\x06\xea\xa9\x5e\xc3\x38\x06\x8f\x6f\x63\x96\x59\x50\xbd\x3f\xa4\x6d\x20\x28\xc0\x1c\xa4\xba\x6d\x24\xe6\x32\x45\x84\x42\xbe\xec\xeb\xf6\xe5\x76\xb8\x7b\xb7\x24\xaf\x4b\x8c\xa6\xa7\x30\x54\xc9\xee\x67\x0b\xe6\x8a\x0e\x32\xad\x63\x36\xea\x1b\x2f\x8a\xff\x45\x4a\xb2\x5d\x5d\xcb\x6e\xb8\x37\x3d\xe5\xc1\x9a\xda\x16\xac\xca\x8a\xd6\x56\x5f\x79\xa2\xb5\x4d\xd9\x4d\xb8\xaf\xa5\xa7\x5b\xd1\x3c\x2b\xed\x28\x01\xcb\xa6\x9d\xe4\x66\x39\x4e\xdb\x72\x59\x52\xbd\xdf\xbe\xbf\x69\x3f\xbd\xbb\xbe\x7f\xbf\x98\xe0\xa5\xdb\xd0\x11\x08\x56\x4e\x56\x69\xff\xba\x71\x71\x82\x5d\xea\x22\xa7\x99\x65\x4e\x11\x52\x0d\xc3\x6f\xf3\x20\xdd\x76\xe1\x56\xde\xec\x2f\x2e\xec\x98\xf2\xca\xe3\x5b\x60\xea\xb9\x62\x9f\x01\xeb\x76\x61\x27\x3b\x60\xef\x5c\xb8\x00\xfa\xdd\xab\x94\x91\xd8\x33\xf8\xdd\xfb\x64\x8b\x14\x4c\x61\x6f\x92\x2d\x9b\x0b\x18\xe0\x5a\x9b\xc2\x3f\x14\x20\x3f\xb8\x6e\x07\x87\x42\xfb\x11\xee\x97\xd3\xa3\x09\x13\x02\xe8\x10\x97\x01\x9c\x1e\x16\xe1\x75\x75\xe9\x26\x74\x50\x21\xf8\x12\x7a\x4c\x92\xe9\xc8\x0a\x66\x86\x56\x30\xf1\x08\x63\xa1\x63\x2e\xf4\x8f\xfe\xeb\x54\xaa\xbf\xa6\x69\x0b\x13\x4c\x90\x6a\xd5\xea\x68\x3c\x45\xe5\x8c\x00\x98\xc5\x9d\x61\x1f\xe1\x3c\x6d\xe1\xe6\xaf\x72\x9f\xb3\x93\x19\xd0\x91\xe6\x80\xd1\x2c\xef\xb5\x23\xd3\xb2\xa6\x5e\xba\xd2\x37\x5d\x77\x13\x70\xb6\xcb\x38\xc1\xef\xa5\x56\x0b\x57\x03\x46\x78\x45\x06\x6c\x80\x50\x9b\x5d\x1c\x15\xef\xf1\xff\x65\xef\xdd\x93\x9c\x48\x92\xed\xe1\xff\xb5\x8a\xd8\x40\x60\xe1\x1e\x6f\x9b\x35\xb0\x06\xac\x80\xa2\xc5\x37\xd9\x14\x09\x89\xee\xbd\xac\xfe\x33\x3f\xee\x91\x92\x2a\x25\x55\x15\xd0\xcd\xcc\xfc\xc6\xac\x1b\x65\x49\xf9\x88\x8c\x87\x87\x3f\xcf\x11\xed\xa0\x68\xe1\xcc\x6e\x01\xf5\x01\x35\x79\xa8\x51\xca\x46\x47\x06\xd1\x92\xbb\x6d\xa0\x31\x14\x73\x7a\x94\x3a\x5b\x75\x29\x92\x87\xab\xbd\x96\xd6\x8c\x7a\x0e\x7b\x24\x2d\x0f\x09\x91\x56\x1e\x33\x58\xd3\x89\xcd\xf9\xcf\x50\x1a\x03\xb9\x14\xd4\x7a\xd3\xf5\x09\x05\x2e\x16\xc7\xca\x8e\x84\x1f\x45\x3b\xc1\xcb\x0e\x2d\xc1\x4a\xe9\xeb\x2b\x25\x2a\x3b\x68\x92\x34\x8b\x1a\xe2\x52\x41\x80\x43\x15\xe1\xb6\x8f\x33\xc3\x2a\x88\x2e\x07\x1a\x0e\xf9\xc4\x86\xf6\x97\x76\x33\xb2\xaa\x45\xe5\x03\x87\x79\x52\x1e\x33\xe4\x26\x87\xa7\x72\xd2\xf6\xef\x37\x6b\xff\xee\x98\x6d\x14\x52\x18\x29\x7d\xd1\x12\x72\x0d\x4e\xdc\x6b\x85\x22\xc7\xf5\xd8\xd8\x4c\x06\x49\xda\x72\x3c\x3a\xfe\x7c\x72\xd1\xf1\x5e\xdf\x5f\x13\xf7\xf2\xb7\x3c\x07\xfe\xae\x12\x06\x07\xe2\x45\xd9\xb0\x1b\x08\x85\xb7\xa4\xcc\x48\xc3\xbb\x22\x0e\xe4\xfa\xab\xa4\x00\x15\x29\xc5\x7b\xa2\x16\x26\x60\x4f\xa7\x86\xc4\x08\x6c\xb3\xc5\x74\x34\x2e\x0e\x99\x90\xb5\x1d\x93\x52\x8a\xfa\x3f\x15\xb2\x92\xd6\xe8\x6c\x6a\x61\x6d\xd0\x15\x91\x8b\xf7\xb9\x28\x72\xf5\x3a\x99\x97\xc5\xd5\xbc\x9b\xa8\x57\x57\x42\x91\x05\x97\xa3\x2b\xd1\xb5\xb2\xc8\x0c\x8f\x71\x2f\x4d\xc9\xc8\xac\x09\x04\x3f\x41\x11\x5d\xb6\xe0\x12\x8f\x6b\x0a\xfc\xed\x84\xcd\xf3\xb6\x17\xef\xdb\x34\xed\x1f\xbe\x6c\xfc\x4a\x77\x37\x59\x74\x64\x5f\x6f\xfd\x16\x4e\xcd\x72\x05\x20\x67\xc5\x6f\xde\x42\x8e\xce\x3e\x51\x75\x51\x3a\xad\x11\xbb\x28\xfb\x0b\xec\xe7\xee\x7c\x27\x85\x7a\x89\x34\xe2\xf1\x09\xa8\x96\xaf\x94\xa1\xc9\xe6\xea\xe0\xb3\x44\x29\x80\x3a\xa3\x32\xca\x34\x7d\x0e\x8b\x82\x9a\xe5\x30\x40\xc6\x70\x6b\x75\x82\x83\xa8\xce\xe2\xf7\x46\xa3\xc6\x5a\x36\xe6\x2b\xac\x69\x38\x52\x5a\x55\x97\x13\x3b\x75\xea\x70\x74\xad\xc3\x89\x44\x81\x10\x88\xe9\x6a\xec\x6a\xe4\x76\x0f\x94\xd3\x2b\xdb\x6b\xe7\x4b\xbb\x6b\x6a\x61\x4e\x31\xa3\x9e\xaa\x00\xf7\xf6\x22\xf9\x2f\xe8\x9c\x64\xbe\x71\xe7\x43\xcf\x49\x4c\x0f\xb8\xc9\x01\xf9\x81\x4c\xad\x78\xf0\x5c\xc3\x1c\x45\x17\x4f\xec\xec\xdb\xdb\xee\xf2\xb7\xf7\x5b\xd6\xf5\xbb\x2d\xbf\xce\x09\x6e\x95\x82\x43\x58\x79\x3d\x2c\xaf\x32\x7b\x24\x95\x6b\xa9\x96\x33\xfc\x57\x48\xd9\x60\x81\xb5\x71\xa6\xa1\x97\x68\x1a\x5c\x74\xd9\xe4\x29\xd2\xba\x34\x00\x0a\x83\x61\xd5\x66\xcb\xf7\xd7\x0c\x12\xe3\xb6\xa7\x18\x80\xf0\x56\x5c\x0c\x58\x8e\xc5\x58\x43\xb3\x91\x27\x05\xe5\x2e\x00\x55\xb0\xa2\xc4\x35\xf3\xdb\x21\xbf\x85\x8e\xc7\xde\xfe\xd0\x40\x8b\x9e\xa5\xf5\x66\x71\x51\x20\xdb\xa0\xe9\x6d\x91\xf5\x41\xbe\x45\xfe\xbe\x7b\x4d\xd5\xa8\x72\xae\x30\x89\x8c\x24\xed\xe7\x00\x6c\x59\x22\xe8\x96\x76\x64\xce\x00\x48\xea\xe4\x5a\x5b\x9a\x65\xc8\x2c\x00\xc0\x53\x7e\xd6\x2c\xe6\x54\x51\x87\x37\xeb\x40\x88\x1d\x4e\xd5\x71\x43\x3d\x60\xa8\x7a\x26\x0c\x1a\x58\x25\xb1\x6f\x74\xdb\xe5\x4c\x65\x1e\x01\xa6\x06\xd4\x23\xea\xaa\x38\xcb\x9d\x06\x45\x2c\x68\xe4\xf0\x80\x81\x1e\xa0\xbe\x75\x2e\x61\x01\x0a\x60\x28\x8b\xa1\xf4\xa1\x95\x60\x30\x44\xd3\x61\xde\xdf\x76\x75\xbf\xbb\xff\xb2\x7c\xfc\xf0\xf1\xdd\xdd\xb2\x09\x43\xde\xc5\x7f\x9c\x32\x3b\x95\x14\x26\x52\x64\xc3\x3c\x47\x6d\x26\x6a\xf1\x83\x22\x56\x24\x03\x93\xc8\x34\xc1\x85\xe6\x53\x53\x3a\xa6\x56\xe6\xf1\x3b\x8c\xae\xa0\x02\x41\x64\x4b\x45\x89\xcb\x84\x2d\x3c\xc7\x49\x4b\x63\x9b\x11\x32\x27\xad\xa6\xf0\xc8\x57\x66\x65\xc9\xea\x6a\x8d\xc2\x3a\xcf\xe4\x98\x27\x69\x8e\xa3\xd8\xf4\x00\xd8\x0e\xd0\xda\x62\xd0\xdb\x73\x50\xe8\x2c\xc2\x05\x99\xf1\x10\x6a\x6d\xb2\x58\xa8\x22\x6b\x29\x34\x8f\xda\xa2\x11\x99\x9e\xf2\xac\x1a\x76\xf2\x0a\xd4\x8a\xbe\x52\x52\xca\x61\xd2\x49\x98\x95\x20\x2c\xc1\xda\xac\xda\x39\x14\xf3\xe4\xed\x60\x06\xd2\x86\x6a\x57\x35\x48\x1f\x24\x94\x91\x64\x9a\xf4\x66\x93\xd7\x9b\xe3\xf5\x14\xde\xab\x86\x99\x3b\x18\x60\xa5\x2d\x93\x35\x71\xd2\x26\x8b\x15\x2d\xb7\x90\xff\x66\x39\x9f\x9d\x75\xa0\xbd\xba\x1e\x50\x44\xb2\x55\x0c\x7a\x13\x45\xfa\xd2\xc5\x9a\x69\xb2\x2e\x9e\xb4\xcb\xcf\x6e\x83\x04\x12\xd6\x54\x66\x79\x75\x6f\xc3\x37\xd9\x70\xce\x49\xad\x78\x1d\x65\xd8\xf4\x89\x0d\x23\xe8\xb6\xb7\x70\x7f\xf7\xe9\xfd\x9b\x2f\x1f\xff\xd8\x6f\x32\x93\xee\x6e\x01\xa6\xfd\x22\xa8\x01\xd9\x3e\x6f\x41\x0d\xa8\x01\xca\xc8\xc0\x83\x5b\x39\x46\x97\xf1\x6f\x69\x0b\xa9\x97\x5c\xf6\x8f\x6a\x1a\xf1\xc8\x52\x85\xeb\x26\x1c\x33\x25\xba\x2e\x4f\xfc\xa9\x49\x16\xa2\x1f\x64\xcc\x99\x41\x00\x6b\xa4\x7f\x95\xcc\xd7\x16\xf0\x4f\xd9\xcd\x10\x83\x9a\x03\x87\x64\xb8\xb3\xca\x64\x70\x31\x83\x40\x32\xf2\x42\x5d\xf1\x32\x92\x51\xf6\xfa\xc8\x33\x19\x19\x62\xff\x2b\x00\x02\xf6\x31\xd2\xba\x35\xea\xce\x08\x24\xf2\xda\x65\xab\xeb\x2a\x78\xb3\x88\xda\x57\x47\xd1\x0b\x15\x04\x65\xc7\x48\x48\x54\xf2\x1a\x75\x38\xf7\x53\x9c\x80\xdd\x8b\x80\x02\x66\x60\x27\x21\xcb\x85\x91\xe9\x48\x25\x21\xdf\x92\x91\x77\xf9\xb3\x88\x00\xba\xc6\x82\xe3\x91\x25\xab\x85\x91\x49\x55\x5c\x6a\x0b\x27\x43\xb1\x0f\xc3\xa9\x48\xdd\x3e\x93\xa3\x3a\x97\xec\x2a\x88\x6d\x14\xa9\x23\x8a\x15\x17\x11\xa1\x07\x8d\xd3\x62\x1c\x4e\x4b\xce\x60\xc4\xd9\xa9\x1f\x10\x31\x79\x25\xfc\x64\xa5\xe7\x29\x75\x10\x16\x69\x44\xb5\x58\xe1\x2a\xcc\xe8\x9a\x7e\x00\x37\x00\x4b\x70\xba\xdf\x52\xd0\xdf\xdd\xe4\xbd\x01\xa7\x1f\xd8\xd8\xa4\xeb\xf6\x20\xb9\x86\xca\x04\x34\x1e\x47\x6c\x39\x99\xb1\x2e\xa2\x02\xa7\x82\x6c\x11\x51\x92\xe0\x4f\x26\x06\x99\x69\x65\xa7\x9e\x65\x2d\x70\x47\x4a\xb4\xee\xe2\xa5\x0d\x74\x9a\xb0\x1a\x24\xa4\xe4\x2c\x8b\xf2\xc3\xae\xe5\xb4\x31\xac\x3f\x12\x6c\x6c\x0d\xec\x58\x40\x48\x7f\x55\x7a\xcb\x5e\xad\xba\x32\x22\xa9\x16\xf1\x2c\x54\xfe\x37\x7c\xe4\xbc\x80\x11\x61\x5d\xfc\x1e\x45\xf5\x00\xb9\x88\xca\xca\x8e\xf9\x37\x52\xed\xc1\x42\xe6\xb5\x64\x4a\xb4\x8d\x18\x95\x88\x50\x19\x7b\xf2\x0a\x28\x2e\xe7\x9a\xbf\xbf\x74\x4d\x6d\x85\xab\x52\xc1\x4a\xf0\x59\xba\xae\x40\xc4\x88\x8c\x17\x1b\xe0\x07\x3e\x29\x74\x5b\x72\x46\xf3\xdf\x54\x16\x81\x19\x72\x21\x4d\xe2\x48\x64\x28\x13\x08\x9a\x2f\xd4\x93\x13\x29\x50\xaa\x8b\x6b\x1d\xc2\xcf\x8a\xcb\xdd\x58\xd7\x0d\xd2\xe7\x29\xfc\x4d\x5d\x6f\x1a\x7e\x44\xcc\x4d\x5e\xb8\x6b\x0f\xf8\x28\x1d\xa4\x24\xc1\xec\x8c\x26\x78\xf0\x5d\x6b\xae\xd7\x84\x70\x77\x21\xa4\x9a\x14\x72\x5a\x77\xcf\xec\xa2\x4b\x11\x61\xfe\x0c\xf7\xb6\x48\x27\x13\x25\x22\x6a\x82\x25\xb4\x21\x9b\x19\x62\x87\x1a\xc1\x7f\x19\x95\x2d\xb1\x2f\xb2\x36\x6a\xc1\x62\x91\x95\x53\xb4\x9a\x9f\x8c\x8c\x96\x9d\x52\xa6\xb5\xbe\xe8\x8a\x2b\x75\x37\xc7\xe6\x82\xb3\x94\x3c\xe4\xa1\x65\xa3\xbe\x1f\xb4\x62\x8b\x12\x8d\xe9\x5c\xd2\xcc\xe3\x0c\xb6\x6d\x19\x25\xf8\x8b\x22\xb2\x2f\xa9\x2e\x4a\x89\x3f\x24\x85\x1d\xa6\x33\x83\x59\xc4\xc9\x48\xe5\x36\x68\x65\x93\x41\x3f\x88\x47\x8a\x25\xbe\x25\xcb\xb9\x2b\x67\x39\x0b\xfe\xe7\x93\x74\x81\xdd\x13\xa0\xff\x02\x1b\xb3\x54\x25\xcc\x34\x10\x68\xd9\x7b\xe0\xf6\x56\x74\xad\x35\x9e\x5f\x8f\xb4\xf8\xd0\xf9\x1b\x16\x9e\xad\x13\x51\x46\xcc\x9b\x96\x2d\xa2\x66\xd9\x13\x9e\xf3\x41\x96\xdc\x16\xf0\x71\x00\x52\x58\xf2\x67\x1f\xc9\x11\xad\xc3\x11\xad\xc8\x67\xc1\xa2\x3c\xa4\x05\xfa\x31\xc2\x23\x2d\x1f\x2d\x59\x1e\x06\x8a\x59\xbc\x56\xd1\x68\x9e\xb9\x01\x75\xd0\x08\xdf\x25\xa7\xa8\x5d\x01\xdc\xa6\x9c\xc0\x60\x1c\xeb\x2c\xbb\xba\x68\x84\x1a\xe2\xe2\x19\x16\x87\xe6\xaa\xc9\xa6\x36\xe7\xaa\xb2\x40\xf7\x75\xa5\x6d\x48\xe1\x00\xeb\xa9\xb2\x8b\x00\xf4\x01\x45\x54\x47\x5a\x1a\x3b\xec\xe9\x03\x7d\x27\x98\xca\x1f\x6d\x3d\x89\x85\x9b\x95\x78\x58\xb3\x8e\x99\xe3\x4a\xd3\x78\xbe\x4c\x77\xe7\xeb\x54\x96\xf2\xad\x7d\xd1\x98\x22\x83\x56\x2b\xa8\x2b\x46\xa4\xf4\xd0\x14\x4e\x5c\x45\x9c\x4c\x20\x5b\xf5\x2a\x16\x12\x08\xcb\x54\xd6\x6b\xe7\x90\x28\x92\xb0\x1b\xc1\x9c\x2a\xdb\xbf\xf4\xb9\xbc\x74\x05\xe1\x5f\xb2\xd4\x42\xe4\x03\x9a\x43\xb0\x74\x23\x52\x97\x05\xa9\x7b\xe1\x22\x53\x0c\xee\xcd\xd2\x0c\x29\xc5\x33\x1f\xa2\x06\xbe\x43\xc2\x7a\x6f\x41\x74\x21\x27\x43\xae\xe2\xc1\x4c\x3f\xc3\x25\x80\xac\x38\x40\x7c\x88\x16\x92\x34\x0c\x1a\x91\x17\x2e\x82\xc6\xc5\x59\x34\x90\x20\xe2\x07\x78\x8b\x30\xb2\x1c\xab\x9d\xd5\x46\x18\x92\xb9\x3e\xbd\xfe\x2e\xd1\x34\xdd\xd5\x7f\x9c\x66\x6f\xaa\xbe\xd9\x92\x62\x58\xb5\xa8\x44\x88\x3d\xc1\xd9\x41\xa5\x1e\x22\x63\xc0\x64\xba\xcc\xc6\x1f\x4d\x86\x7f\xb7\xa8\x52\xa9\x86\x7e\xd1\x8c\xc4\x9c\x06\x20\xaf\x6f\x16\x67\xe2\x19\xea\x65\x55\x7d\x53\xe7\xa6\x2a\x10\x49\x95\x09\x59\x3c\xc0\x84\x33\x3f\x9f\x26\x50\x20\x4f\xa0\x9d\x94\xba\x84\xb1\x14\x6c\x46\xac\xbc\xd9\x56\xe6\x76\xb2\x4e\x96\xe3\xfa\xb1\x14\x09\x5d\x5e\x0b\x56\xdb\x6e\xd1\xb5\x67\x4b\x71\x0d\x14\x65\x05\xcc\x45\xb1\xc6\x58\xc6\x1b\x5d\x13\xcb\x5f\xde\x36\x22\x5e\x29\x9f\x73\x81\xc2\xab\x72\xc3\x76\x57\x15\x2a\xcb\x51\xcc\xac\xb2\x67\xd6\xad\x55\x24\x53\x9a\x5b\x56\x34\x0b\xd5\xf5\xc5\x00\x8a\x79\xc5\x7e\xa5\x98\x7e\x49\x25\x44\x6e\x56\x33\x02\xa0\x22\x15\x63\x31\x2c\x2b\x8e\x7a\x9d\x7c\x76\x34\x7b\xdb\xf7\xbc\xce\x3c\xc2\x20\xa9\xe6\x12\x67\x9f\x0d\xcb\xd5\xa6\xab\xce\xe0\x55\xdb\x1e\x13\x7b\x75\x74\x40\x3d\x0e\x9a\x96\x8d\xd5\xb0\x78\x5d\x1c\x58\x2d\x9a\x13\xaf\x3a\xa4\x11\x0e\x6a\x94\x9b\x5a\x03\xa6\x13\xe4\x32\xd2\xd5\x82\x66\x6e\x89\x19\x3b\x56\xe5\x32\x16\xea\x58\xb9\xba\x90\xb1\xaa\xe7\x0c\x80\x01\x5b\xf1\xbb\x39\x3a\xa0\x92\x8e\x6d\x8d\xfa\x72\x14\x17\x43\x82\x0c\x91\x32\x64\xcc\x90\x3a\x26\x88\xae\x28\xe8\xa8\x56\xbf\xba\x39\x1e\x25\x61\x1f\x36\xc1\x8c\x39\xd1\x15\x8e\x2a\xd2\xed\xf5\xfb\xee\xe3\x97\x77\xd3\xfd\x9b\xbb\x2f\x5f\x1e\xfe\xe7\xb2\xaa\x7c\x9e\xfd\x97\x6b\x39\x12\x6f\x9c\x4d\x97\xbd\xcf\x81\x27\x98\x63\xad\x1b\x81\x87\xfd\xae\xdc\x1e\xbe\x93\xeb\x04\xdd\x90\x94\x37\x1e\x18\x2e\x58\x5c\x93\xd6\xb1\xc5\xc2\x38\xcd\xdb\x79\x47\xc4\x17\x0d\x22\xa7\x3c\xe9\xaf\xd3\x38\x7d\xb6\x33\xf4\x36\x98\x94\x6d\xd2\x07\xe9\x73\xf0\xdb\xa2\xa7\x28\xe1\x35\xb5\xbe\xcf\xe1\x58\xad\xbd\xa9\xe7\xd1\x59\xac\xa0\x13\x6b\x46\xcb\xe2\xcf\x52\x5d\xfc\x49\x0e\x8c\x5f\xb3\x0a\xc6\x49\x76\xce\x31\x07\xe1\x89\x6c\x84\xe5\xe9\x8c\x9a\xe7\x8f\xe2\x65\x9f\x43\x3f\x19\xc6\x3c\x4a\x0a\xab\x1b\x1d\x83\x2e\xd3\x51\x90\x5e\xbd\x32\x48\xb7\x87\x46\x15\xa3\xa6\x33\xe1\x24\xe2\x7e\x22\x43\x4e\xf9\x61\xce\xc4\x89\x8c\xc8\xe4\xc7\x1d\x8e\x95\xed\x67\xa2\xc7\x06\xff\xe2\x98\x5b\xcb\xb7\x63\xff\x9f\x32\xac\x17\x94\xdc\xbb\x93\x31\x15\xb3\x88\xce\xc7\x74\x74\xc9\xed\x85\x67\x0b\x6a\x5d\x80\xb7\x17\xde\xc5\xbe\xb7\x55\x75\xc0\xb8\x5f\x1a\xdc\x53\xd6\xa5\xb1\xdc\x0e\x43\x5c\x78\x93\x17\x2a\x26\x8e\x7b\xcb\x7f\xee\x50\x5e\xd4\x97\xde\x9e\x0f\x26\x9c\xe8\x8f\x17\xe8\xb5\x31\x1c\xdd\x78\xd0\x01\xd8\x8a\xe6\x73\x26\xaa\xb3\x05\xb9\x2e\xbc\xb1\xee\x0c\x50\xe2\xa8\x00\x3c\xb5\xee\x57\xd1\x7d\x63\x8a\xa8\x7c\x19\xe2\xe5\x3f\x63\x4c\xff\x98\x1e\xde\x6e\x23\x08\xef\x7e\x38\x69\x72\xf9\xbb\x5e\xfc\xfb\x6b\x0a\x89\x5d\x6b\x55\xb1\x79\x8c\x2b\x54\x6f\x12\xed\x70\x16\xa5\x4c\xb1\x91\x51\xd1\x27\xdf\xd7\xb9\xb8\x8a\xc4\x6d\x14\xdc\x14\x87\x22\x8b\x39\x26\xd7\x14\x06\x81\x50\x1f\xcf\x08\x94\x53\x5c\x50\xee\x24\x27\x88\x76\xa4\xde\x45\xca\x0e\x20\xf2\x8e\x2d\xc4\x41\x03\x1a\x53\xb3\xee\xad\xe8\xd0\xf9\xe2\xbc\xec\x14\x55\xad\xb3\xb6\x2a\xe2\xa8\x95\xa7\x35\x57\x2f\x2b\xc6\xff\x5a\x84\x00\xe3\x96\x9d\xbe\x83\x43\x5e\xa7\x56\x4b\x79\x42\x3d\x9b\x01\x3f\xfb\xe8\xec\x7c\x2d\xe3\x93\x27\xc3\x5e\x47\xfe\x64\x5d\x8d\x71\x38\xab\xc4\x6c\x40\x8b\x34\xc5\xc3\x9a\xa1\x50\x58\xc8\x93\x8c\xaf\xf2\x0e\xb6\x05\x6b\x29\x81\x7c\xad\x99\xae\x33\x65\x94\x7f\x6b\x42\x9d\x82\x89\x14\x17\xe7\xee\x50\x0d\x0f\x67\xa2\x16\x1f\xec\x45\x93\x05\x8a\x81\xbc\xee\x9a\x2f\xa2\x47\xd1\x95\xd9\x37\x87\x94\x7e\xad\x6d\x88\x48\x94\x05\x18\x68\x71\xd6\x26\x04\xad\xb5\x4c\xfe\x95\x01\x82\xce\x84\xdf\x75\xf2\x44\xed\x62\xaf\xd5\x93\x8a\xc7\xa0\x45\x99\x41\xad\x1d\xbc\x43\xb3\x9c\xbf\x11\x3e\x65\x3c\x44\xbe\x1d\x86\xd0\xa2\x95\xc4\xd2\xe3\x3b\xa4\xd6\x38\x75\xe5\x68\xb1\x84\xd5\xb5\xda\x37\x5a\x4e\x00\xc2\x41\xc4\xb1\x10\x94\x32\xb8\xee\x62\xd3\x8d\x0b\xa2\xe0\x59\xfb\x26\xa0\xec\xa5\x19\xc2\xa9\x3c\x1c\xa9\x0d\x84\xd3\x38\x3b\x0d\xac\xa7\xb9\x38\x98\xaf\xca\x85\x90\xb5\xa8\x44\xa6\x5a\x71\x5a\xdd\xb6\x90\xe6\xe2\xa2\x6c\x06\x39\xeb\x33\x39\x72\xca\x1d\xae\x13\x74\x60\x83\x5b\x86\x7c\x0e\x28\x59\x75\xea\x6c\x45\x89\x3f\x12\x89\xeb\xdc\x5d\x91\xde\x42\x5f\xe9\x9c\x40\x94\xd2\xa6\x07\xfa\x11\xf5\x22\x98\x70\x6a\x4f\x68\x5a\xa6\x8b\x72\xb9\x4f\x40\xc7\x76\x9a\xc4\x99\x34\x19\x09\x11\x53\x9f\x00\x63\x21\x43\x3f\x96\x21\x1d\xeb\x3f\xbc\x25\x22\x15\x14\xc8\xc8\x19\x79\xb4\xdb\x8f\x37\x18\x6c\xbe\xa8\x2c\x99\xd1\x71\x44\x5a\x57\x93\x5c\x83\x22\x0e\x5c\x09\xae\xd2\x51\xc9\xba\x7e\xa4\x37\xf9\x84\xd1\xad\x63\x8a\x10\x0a\x98\x7d\xb3\x21\xc6\x0b\xdb\xe0\xea\xc4\xde\xe9\xdb\x2a\xcc\x45\x1a\xf2\xa3\xd9\x28\x8f\x55\xaa\xc0\x05\xb8\x7b\x1c\xc8\x1e\x69\xc1\xc9\x78\x60\x06\xb2\x86\x7a\xc8\xb4\xba\xa6\x2a\x42\x8b\x4c\xe7\x09\x69\xb3\xb3\x5d\x56\x80\x3e\x61\x89\xd2\x36\x61\x9a\xfc\xd8\x10\x3a\x98\x09\x80\xfa\x6c\xc0\xfd\x44\x56\xfa\x13\xb4\xf4\x27\x69\xc1\x0d\x8a\x41\x13\x70\x3e\x10\xfc\x93\x51\x66\x99\x17\xc5\x00\x7c\x65\x9e\x24\x50\x79\xb0\xab\x53\x76\x36\xa8\x05\xe1\x5e\x96\xd5\x8d\xbe\x8b\x68\x98\x7c\x57\x86\x61\x39\x2b\x86\x89\x65\x68\x5b\x23\x20\x72\xac\xdc\x93\xb4\x0c\x28\xaf\xac\xc1\xac\xf2\x2b\x15\xcd\xdc\x43\x2d\x24\x33\x6e\x54\x75\xb0\x66\x4c\x28\x60\xf2\xaa\xa7\xc2\xa0\x0b\x81\xa3\xd2\xb4\x82\x0a\x93\x19\x9e\xb9\xaa\xda\x53\x45\x2d\x28\x03\x1a\x8f\x2c\x2f\x9c\x9a\xc9\xbd\xae\x18\x37\xc9\xc0\x52\xc2\xe3\xa5\xcc\x6b\x41\x95\xce\xc1\xb2\x78\xad\x10\xd2\x22\x28\xd2\x04\xab\x49\x9b\x1e\xf5\x8d\x5f\x19\xcc\x9f\x79\x72\x49\x49\x5c\x22\x00\x46\x60\xcf\x4b\x77\x23\x7f\x59\xa3\x5f\x78\xb7\xaa\x7b\x80\x48\x57\x4d\x90\x7e\x95\x67\x40\xba\x90\xe5\x5f\x69\xf1\x68\xd4\xd2\x2c\x5f\x2c\xe7\x2a\x58\x43\x39\xca\x0b\x05\x15\xe4\x32\x1f\xf4\x53\xeb\x35\x35\x2a\x42\x69\xb1\x03\x59\xf0\x2a\xba\x29\x28\xbf\x32\x0a\x97\x67\xcd\x95\x06\xf2\xc7\xac\x15\x5a\xda\x7d\xa8\xd0\xca\xb6\xc8\xf4\xc5\x93\xc1\xca\x62\x37\x2c\x90\x81\xcb\x3a\xd9\xd5\xf9\xb3\x88\xf6\x63\xe9\xe2\x6c\x4b\x16\x6b\x1f\xdd\x5b\x15\x0d\x0c\x29\x7d\x06\x33\x63\x95\x82\x8b\x71\x70\xcf\xdd\x58\x56\xb0\xf0\xc9\x28\x4d\xe6\x6c\x7d\xc7\x65\xd1\x82\x6e\xe0\xce\x68\x78\x24\xae\x15\x5c\x1d\x4c\xe5\x58\xb0\xd2\x80\x59\x93\xd2\xdb\x2a\x47\x6c\x68\xc8\xa8\x02\x12\x92\x63\x92\x4a\x2e\x74\x76\x34\x34\x16\xe9\x06\xcd\x01\x90\x8b\x40\xaa\x3d\x47\xd5\x23\x51\x3b\x47\xb6\xd4\x35\xc6\xa9\x25\xe0\xea\x02\xb3\x42\x79\x05\x80\xd4\x86\x17\x25\x33\x54\x0d\x91\x14\xc7\xa7\xa2\x86\x11\xf5\x3b\x3a\x9e\x0d\x2c\x50\x24\x2b\x46\xfe\xd1\x1c\x07\xe5\xed\x46\xed\x35\x08\x73\xd6\xfd\x3a\xe9\x4e\xc8\xb6\x25\x2a\xb5\x8f\xae\x08\xf8\x70\x35\x51\x70\x14\x74\x03\x89\x88\x4c\x16\x22\xd5\x94\xad\xfa\xd0\x6b\xaa\xbe\xd7\xca\x3a\x75\x2d\xd9\xd6\xa6\x2a\xd8\x2b\x85\x1d\xdd\x8d\x9c\x40\xca\x8e\x66\x91\xe3\x3c\x5c\x6c\xd1\xa2\x76\x10\x3d\x59\x37\xf1\x3a\xe0\x87\xd3\x68\xc2\xc0\x35\xc3\x2e\x3e\xea\x2f\xb0\x90\x8a\x66\x68\x60\x6e\xfa\x38\x04\xfe\x9a\x19\xd6\x51\xe6\x50\xf1\x13\xc2\x27\x90\xe4\xba\xb4\x9a\xf9\x2e\xb9\xeb\x06\x00\x18\x19\x0a\x8e\x4f\xa0\xc9\x86\x3a\x93\xb0\xf7\xb1\xeb\xae\x1b\x58\x19\xa0\xf6\x45\x6a\x48\x63\xcd\x01\x15\xa4\xc5\xb8\xb0\xd8\x16\x93\x5c\xdc\x19\xc7\x57\x72\x71\x46\x43\xb4\x7c\x13\xfa\x24\xe6\x93\x4e\x18\x74\x2e\x3b\x3e\x0e\x15\xde\x38\x8c\x9d\x09\xea\x2b\x26\x15\x04\x40\xb4\x05\x6a\x11\x79\x9f\x55\x2a\xe8\xde\xa3\xf3\x07\x13\xc9\x05\x5b\x64\x83\xe0\x82\x92\x16\x3e\x80\x11\x09\xb1\x07\x31\x51\x92\x36\x0d\x95\xa8\xcb\xe8\xee\x80\x32\x4e\xb2\xd2\xfe\x49\xe6\xc0\x01\x16\x12\x00\x99\xb4\xf8\xb4\xe9\x90\x69\x30\x4c\xc5\x11\xdc\xbb\xf2\xf6\x80\x17\xda\x2d\x6b\x2d\x29\x56\x59\x9b\x19\x99\x2a\x00\x15\x9d\x51\xbf\x41\xd8\xcb\x11\xb9\x71\x51\xb7\x7c\x1b\x74\x9e\xbb\xc3\xe6\x52\x66\x79\x5c\x35\x3c\x0c\x55\x42\x35\x3c\x8c\xf5\x85\xca\x0e\xd2\xd3\xaa\x16\x02\xa9\x00\x68\xfa\x2a\xf2\x76\xec\x9a\x63\xd1\x63\x78\x11\x15\x66\x4e\xa2\x9a\x64\xd7\x65\xb1\xe7\x49\xcb\x34\x22\x30\xb2\x12\xac\x2e\x06\xe8\x3c\xd2\x54\x00\xd4\x21\xfb\x63\x54\x68\x2e\x9d\x8b\x0a\x7f\x15\x9d\xf2\xfb\xa3\xa3\x55\xc5\x01\x38\xaa\x0a\xe1\xaa\x15\x23\x28\x70\x49\x10\xf5\xdf\x5f\xb7\xda\xa5\xf9\x1c\x00\x75\x0c\x8c\xe4\xd6\x6d\x92\xa0\x8b\xb4\x76\x90\x4d\x98\x88\xf9\xa7\xbc\x5c\x6d\x56\x2e\x30\x63\xbe\x6e\xb2\x0d\x69\x9f\x02\x4b\xa4\xaa\xb9\xe0\xab\xe8\x82\xd5\xd0\xf7\xc6\xed\x50\xdf\x63\x98\xc0\x50\x1f\x69\xf8\xef\x8f\xf0\x54\xd9\xb4\x6d\xd9\x9b\x17\xdd\x16\x34\xfc\x52\x51\x29\x85\xe0\x11\xb0\x57\xc8\x99\x85\xa5\xa6\x86\xf4\xd0\x51\x5d\x01\x83\x89\x33\x5d\x1a\xaa\x13\xc4\xb5\xb4\xc8\x29\x79\xd8\xa2\x52\x75\x94\xf0\x86\xe3\x2b\x9b\xb2\x63\x69\x9e\xb6\x80\xcb\x68\xbf\x0a\x95\x66\x42\xd3\xb4\x21\x3c\x85\x6d\xc9\x4b\x0f\x24\xd3\x19\xca\x50\xec\x32\x56\xaa\x19\x0c\x11\x2a\x59\x6c\x98\xef\x96\xb7\x05\x58\x47\x0b\xc5\xa3\x64\x2b\x68\x38\xdd\x4a\x84\x34\xe5\xd1\xaa\xcf\xcc\xae\x31\xd8\x11\x99\x15\x22\x02\x6f\x9a\xb6\xff\xf3\xe5\xfe\xd3\xbb\xfd\xc6\xb6\xdd\x16\x8a\x1c\x2b\x71\x22\x5c\x50\x3f\x1b\x47\x08\xdc\x5c\x6a\x69\xf2\xa5\x81\xa4\x89\xb5\x62\x53\xfe\x47\x26\x42\x5d\x93\x18\xc9\xc5\x3a\x21\xfb\x91\x42\x03\x7c\x60\x2c\x16\x2a\x35\x67\x7a\x73\x9d\xa6\xd2\xc8\x95\x46\x33\x42\x99\x4d\x41\xfd\x64\x93\xc6\x16\x6a\xd8\x2e\xf2\x1d\x72\x09\xd8\x75\xd2\x6a\xfe\x3e\x70\x42\xcb\xac\x39\xd6\xa8\xaf\x2e\x56\x79\xab\x69\xba\xac\x48\x83\xcd\x66\xbc\xd6\xaf\x1f\x2b\x75\x16\x7f\x5a\xc2\x73\xa5\x9c\x67\xce\x1a\xe1\xa3\x61\x50\x2d\x14\x54\xad\x28\x06\x83\x26\xca\x3c\x60\x6d\x2c\x17\xbc\x4d\x9e\x3b\xb2\xc7\x3b\x0a\x60\x26\xc2\x5f\xa1\xaa\xb8\xe9\x1a\xe2\xd1\xec\x89\x66\x60\x21\x8a\xa9\x86\x5c\x9b\x68\xa6\xad\x9a\xa7\x4f\x20\x52\xde\x7d\xfd\xe7\xa6\x28\xe5\xee\x26\x76\x2d\x38\xaf\x19\x18\xbb\x07\x63\x39\x0d\xc6\x72\x6a\x54\xd9\x2b\x79\xf7\x09\x63\xf8\x08\x44\x51\xe6\x8b\x74\xaa\xb5\x03\x6d\xf8\x66\x91\x97\x4c\xc5\x1b\x65\x5e\x8f\xa0\x4e\x71\xf6\x05\xbc\x56\x7d\x56\x8b\xfc\xb2\x67\xed\x7e\xe2\x61\x14\x53\xfa\x1b\xde\xec\x66\x65\xf3\xc7\xe9\x42\x39\xfb\xdb\x0d\xf1\xf9\x39\x26\x8f\x6c\x49\x89\x40\x2b\x96\xb4\x82\xdd\xd7\x30\xf9\x04\xc2\x97\x1e\x0f\xbe\x6a\x39\xfb\x60\x3a\x45\x9e\x8c\x22\x0d\xb1\xba\x55\x14\x91\xe7\x16\x2f\xfc\x21\xb5\xa2\xb7\x4c\x3d\x1e\xf3\x54\x13\xb2\x4b\x81\x15\x96\xbb\x8b\xf0\x30\x87\x19\x19\x37\xb9\xcb\xd3\x6e\xa7\xa1\x7f\xf9\x78\xff\xe1\xdd\xdd\xd7\x8d\xf3\xee\xed\xad\x92\x04\x2b\xeb\x0a\xfb\x4c\xac\x33\x54\x0e\x4e\x66\x28\xa6\x7a\x6a\xb7\x6a\x33\x80\xe2\x76\x31\x5f\x3f\xb5\x80\x02\xc0\xc1\x8f\xb8\xf1\xa1\x47\x0e\x5b\x1f\x3a\x15\x5c\x65\x64\xf3\x63\xad\x19\x11\x3c\x9f\xd1\xc4\x03\x60\x21\xb6\xb4\xf7\xf2\xb7\x01\x00\x6f\xea\x03\x62\xe6\x83\xb6\x60\x24\x70\xef\xac\x3a\x31\xd7\xcb\xd5\x8f\xd2\x84\x98\xf9\x62\x79\xe0\xed\x49\xf7\x6d\x9a\xbe\xbe\xfb\x72\x7f\xbf\xf1\x85\xbf\x3d\x61\x08\x6f\xd1\xf5\x9e\x27\xbf\x72\xd0\xae\x07\xe0\xe2\x4c\xe9\x24\x79\x38\x41\xca\xeb\xb4\xf0\xb9\xdf\xc4\xa5\x43\x3e\xfc\x55\xe8\x39\xbb\xb7\x3e\x56\x1e\xe6\xcf\x1e\xab\xc4\x4f\xa7\xd0\x73\x5b\x60\xbc\x6b\xc8\xcb\xda\xa6\xc4\xd2\xc1\xb9\x4b\x8b\xa9\x6a\x18\x3f\xad\xf7\xde\x4d\x67\xcf\xc5\xc1\xfa\xdc\x47\xa8\xcf\x70\x29\xa9\x39\xab\x69\xb7\xd6\x90\xdc\xed\x51\x5b\x90\xe7\xe3\x42\x49\x58\x45\x58\x9d\xfa\x1e\xc7\xe7\x4c\x67\x3d\xbe\x36\x01\x2d\x88\xa4\x40\x20\xd2\x57\x72\x03\x3c\xce\xa5\x80\x9b\x6f\x65\xcf\x3a\x10\x37\x24\xc1\xb1\xa3\x6e\x43\x6f\xfc\xf1\xe5\x61\x1b\x09\x7b\xb7\x95\x54\xc7\x0a\xd6\xdc\x23\xe2\x9d\x0a\xb7\xa1\x2c\xc7\x46\xc1\x4d\x31\xcd\xbe\x29\xfd\x23\x58\x74\xb4\xf0\xcc\x91\xa5\x7b\xc4\x0c\x19\x27\x9f\x80\x2b\xd5\x8a\x77\xa6\x91\xf7\xa1\xa4\xe0\x96\xf6\xa6\xf8\xc0\x14\xa3\x63\x25\x69\x8a\x8a\x6f\x50\xca\xa8\x61\x00\xc7\x0b\x56\x64\x29\x62\x5a\xad\xd4\x7e\x71\x05\xe8\xa3\x8e\x61\x00\xfe\x52\x4d\xc7\x7c\x85\x9e\x34\x25\x41\xce\x25\xcb\xd2\x54\x24\x33\x47\x00\x37\x11\x1b\x29\x74\x45\xf9\xa4\x80\x8c\xce\x64\xe0\xc2\x85\x45\x11\x80\xf3\x3f\xe3\x54\xe5\x48\x0c\x9a\xf7\x9b\xa2\x65\xba\x54\xf0\x74\x89\xfe\xa1\x9f\x71\x65\x3e\x89\x23\xef\x37\x54\x97\x9a\x9c\x98\x9a\xdc\x5d\xdf\x5a\x71\xe5\xc8\xdc\x34\x1a\xa7\xc0\x73\xa4\xbb\x1b\xc9\x89\x8a\xff\xac\x08\xa4\x68\xdc\xa2\x4e\xc4\x6e\x8e\x6a\x20\xae\xac\x02\xf6\xd9\x55\x2d\x97\x69\xe3\x77\x27\xbc\xf1\x31\x69\x15\x19\xec\xf8\x95\x1d\xde\x78\xde\x1f\x11\xc2\x9f\x71\xc5\x9f\x50\xbd\x9f\xd2\xbe\x9f\xd1\xc1\x9f\x5d\x7e\x7a\x67\x63\x3b\x2d\x95\x0c\x80\x5b\xab\x73\xc9\x7c\xf9\xcd\x01\x2b\xc9\xa6\x1f\x61\x1f\x8d\x3a\x2d\x89\xdb\xdc\x08\xe5\x35\x8d\x9c\xed\xef\x00\x07\x28\x40\x77\x06\x68\xbd\x56\xa2\x29\xb5\x06\x8d\x5c\x6c\xcc\x48\xe5\xed\x53\x88\x5e\x9a\x89\x57\x5e\xd0\x98\xe3\x09\xcd\xfc\x4f\x76\xf0\xda\xbf\x4f\x31\x91\x6c\x96\xe9\x2d\x2c\x73\x4a\x79\xd4\x85\x5a\x25\x7d\x11\x55\x37\x34\xc7\x41\xeb\x5b\x74\xc7\x71\xbc\x0a\xee\xca\x28\x04\x50\xd7\x42\x37\x8f\x9b\xaa\xd2\x3a\x5f\x4d\x08\x45\xa3\x4a\xd2\xd5\x3b\x12\xa5\x37\xe5\xfa\x03\x83\x0a\x3e\x0e\xf5\x27\x65\xb3\x5b\x61\xfc\x8f\x14\x40\x3a\xe6\x64\x2b\x2c\x17\xac\x32\xf9\xac\xd1\xee\xac\x37\x9e\xc4\x5e\xf6\x1c\xea\x0c\x53\xad\xea\xd6\x79\x44\x58\xe5\xb2\x9b\x08\xe0\x83\x65\xd6\xf7\x93\xb7\xae\xdf\x5f\x57\xe0\x98\x70\x7e\xdc\x17\x62\xd0\xd7\xc7\x7d\x11\xbb\x1b\xd9\xf2\x62\x10\x61\xeb\x4d\x45\x2b\x82\xc6\xff\x28\x90\x38\x6b\x18\x2c\xc3\xf6\xb8\x61\xec\x34\x47\x93\x86\x6d\xdf\x0d\x4e\xf9\xf4\xcd\x6d\x37\x8b\x46\x0e\x85\xd9\xa6\x9d\x7a\x5e\xf4\x65\x16\x47\x1d\xee\x52\x1e\x51\x28\x8c\x55\xde\x9d\x0d\x95\xba\x2c\x81\xb4\x16\x51\x3f\x50\x65\xc6\x96\xd4\x56\x3a\x7e\x0e\x56\x1f\x11\xe2\xe9\x6b\x36\x83\x4b\xe3\x80\x83\x55\x64\x72\x48\xae\xe5\x93\x5e\x6b\xd1\xd9\xb9\x1c\xa2\xb1\x88\x34\x99\x5d\x7d\xf2\xad\xb9\xd6\x00\xcc\xa3\x10\xa9\xd2\x3d\xa8\xc9\xd2\x64\x5a\xdc\x2b\x9d\xcc\xc6\x96\x90\xcb\xd8\x92\xe3\x90\x16\x00\xb9\xc4\x75\x28\xf5\x41\xd2\x9e\xa6\xb8\x46\x41\x49\x49\x5b\x5e\x27\xc4\x6e\xb6\xa6\x58\xcb\xf5\x05\xe3\x78\x7a\x9f\x9a\x36\xa0\x15\x6d\x22\x9a\xa7\x8d\xd1\x5b\xa5\xe3\x10\x5a\x43\x1a\x42\x3b\xb7\x31\x06\xde\x4d\x0f\xdf\x36\x25\xe0\xef\xb6\x05\x98\x27\xf0\x0f\x22\xc8\xac\x9e\xf6\x09\x09\x2a\xf6\x1c\xfa\xec\xb6\x25\x8c\x5a\x6c\x76\x95\x1c\x27\x1d\xf9\xea\xa8\x98\xbf\x1f\xf3\xd5\x69\x75\x3c\x5c\xb6\x0a\x77\x6e\x68\xe7\x33\xc1\x5a\x66\xa5\x39\x6b\x4d\xae\xb5\x2c\xc3\xb9\x06\x27\x27\x95\xe2\x0a\xcf\x22\xdc\xd6\x84\xd8\x21\xae\x66\x65\x7c\x57\x5b\x25\x36\x25\x8c\x8d\xf2\xa0\x68\x50\xa8\x0b\xfa\x30\xf6\xa7\xe0\xbf\xde\xde\xdf\xfd\x73\x6b\x2e\xbd\xbb\x09\x38\x9d\xb9\xca\x18\xca\x46\xd0\x54\x64\x4b\x87\x1a\xcb\x81\xe5\xda\xa3\x0f\x49\xb9\x4a\xd4\x46\xb0\xda\x99\x21\xd6\x70\xc1\x94\x83\xd8\xf9\xf1\x10\xfb\x55\x6c\x93\x67\x50\x93\x2c\x17\x60\x52\x0e\x3e\xf6\xfe\xfd\x75\x4d\xcd\x35\x8a\x93\x67\x91\xb0\x89\xfb\xbe\x12\xeb\x5f\x20\xf6\x91\x29\x41\x87\x58\xb5\x05\xc4\x0d\xd7\x1d\x7c\x7c\x22\xd7\x70\x4b\x63\xf6\xee\x56\x29\x5c\x2f\x8a\x7d\xff\x74\xdb\x97\xab\x2f\xff\xfd\x35\x71\x41\xda\xe2\x94\x03\x34\xdd\x36\x5b\x7d\x22\x34\xcf\xa2\x9a\x9a\xfd\x8f\x3a\x4e\x88\xc8\xa4\x0a\x6a\x55\xef\x5a\x85\x7a\x8f\x49\xed\xda\xe4\x0b\xf2\x74\x45\xd8\x12\x4c\x3d\x0b\xe4\x7a\x25\x2d\xa0\xa4\x11\x0c\xa4\xd7\xc3\x91\x5f\xab\x69\x00\x56\x34\x83\xdc\x5d\x0d\x71\xe1\x18\xd3\x0e\xe8\xb1\x69\x77\x24\xbd\x62\x06\x60\x59\xd7\xb4\x69\x00\x58\xd5\xb9\xba\x5a\x9c\x68\xa8\xa9\x2e\x14\x95\xaa\x4e\xee\x21\x92\xa8\x36\xd7\x92\x08\x96\xc1\xc9\x4a\x73\x07\x6a\x11\x3b\xe6\x89\x18\xd4\x86\x5e\x3f\xf1\x7a\xc8\x17\x85\x8f\x14\xe9\xd1\x88\xbe\x90\xf1\xb1\x27\x6d\x84\xde\x53\x74\x64\x85\xad\xc7\x13\x55\x47\x4e\x60\x70\x00\xbc\x99\xf1\x83\x00\x52\xb5\xc7\xb9\x65\x27\xcd\x95\x07\xf5\x99\x92\xee\x02\x78\x3d\x88\xbd\x0c\xd2\x67\x74\x81\xe2\x8f\xa4\x06\xd6\x72\x94\x69\x6a\xaf\x25\x8b\xd3\xfa\x3c\x59\x1f\x4f\xd6\xe9\xd2\xbd\xe0\x56\x6d\x5a\xb7\x8d\xe1\x99\xc6\xa0\x45\x8d\x18\xeb\x58\x42\x31\x28\x66\x62\x94\xef\xaf\x73\xed\xae\xc5\x32\xa7\x82\x02\x56\x12\x3d\x79\x51\x0f\x22\xd5\xd9\x77\x86\x49\x44\xf8\x44\x4e\xff\x80\x64\x8d\x45\x03\xc9\xa8\xfc\x44\x64\x55\xd4\x64\xa8\x74\x75\xee\x0c\x9b\x8f\xf4\x73\xc6\x65\x72\x55\x2c\xdf\x5f\xa7\x9e\x5c\x27\xd1\xe8\xb2\x81\xf9\x52\x05\xde\x25\x85\xb6\xc3\xce\x8d\x10\x1b\xce\x96\x45\xaf\x10\xe0\x76\x27\x64\xb3\x67\x32\x55\x4d\xae\xb4\x67\xcf\x06\x03\x36\xda\xa6\xd7\x69\xbb\xbf\xbf\x2e\x95\x5d\x0d\x69\xea\xc0\x28\x38\x00\xba\x29\x16\xd9\x51\x73\x99\xa4\xf3\x26\x99\x4b\xa9\x4e\xc6\x1e\x3d\xaf\x51\x28\x85\x41\x53\x34\x29\x44\xfb\x50\x37\xa0\x61\xfd\x08\xd7\xba\xc2\xc4\xa4\x16\x70\xf7\xc8\x53\x8d\x05\x6b\x0b\xab\xa6\xa4\x49\xc1\x01\x52\xa4\x83\xbc\xd5\xe4\x01\xde\xd2\xcb\xd4\x9d\x6f\x9a\x29\x52\x9d\x2f\x3a\xda\x0a\x17\xc5\x8b\x7e\x4c\xda\x1a\x20\xff\xc8\xb2\x9f\xc6\x1d\x33\x8b\x5e\xd1\x26\x4f\xb5\x8e\x5a\x67\x6d\xb0\xac\xcf\x27\x68\xeb\x3f\x6f\x50\x63\xdf\xdd\x2c\xfd\x2b\xbd\xc0\x0b\x79\xd9\xd3\x61\x50\x47\x2f\x01\x7a\x02\xdd\x10\xb8\x9a\x2e\xfc\x58\x2a\x9b\xd2\x14\x5c\x6b\x4b\x6a\xae\x96\x29\x05\x31\x44\x9b\x29\x84\x20\x43\x5b\xa0\x03\xec\x13\x5d\xf6\xc0\x44\x6e\x73\x91\x8b\x94\x53\x17\x27\x1a\x45\x5b\x8f\x22\xae\x3b\xe0\x04\xfb\x9e\x7b\x3f\xb0\x08\xf8\x0c\xb6\x19\x8e\xc7\xdf\x76\xc7\x1f\x2b\x20\x73\xca\x14\x65\x21\x51\x39\x24\xf0\xec\xb7\x74\xf0\xe9\xfa\xfb\x27\x2a\x5a\xb9\x9b\x89\xcd\x2f\x79\xfe\x5e\x66\xf4\x62\xb7\x80\x9f\xf7\xf9\xb7\x6c\xfd\x76\xb0\xe2\xf3\xdd\xe7\xfb\x2f\x6f\xde\x4d\x1f\xb7\x7e\x81\x9b\x18\xcc\x29\x24\x11\x94\x8a\x38\x6a\xd0\x7c\xd4\x8b\xe1\xc8\x2b\xff\xa0\x1a\x04\xa8\xc1\x08\x93\xaf\xb5\xba\x0a\x1a\x30\x8a\x4e\x51\x24\x45\xbe\xc2\xce\x13\xed\x48\x64\x15\xd7\xb0\x70\x91\x63\x1a\xfa\x0a\xec\x7b\x8a\x53\x09\xd9\xc0\x53\x0c\x1a\x0e\x62\xde\x00\x5b\xad\xe8\x24\x69\x5a\x9a\xa6\x4d\x59\xf5\xaf\xb1\x14\x51\x98\xe4\x6a\x57\x44\x9b\xad\x1d\x28\x78\xb0\xcc\xea\x51\x61\x90\x77\xa8\xea\x26\x18\x3a\x0f\x05\x45\xb5\xa6\x46\xbb\xa9\xca\x51\xad\x75\x2e\x51\x34\x0e\xad\xe2\x2a\x71\x2e\x10\x5b\x41\x24\xe3\x92\x58\x8e\xe6\xe0\x10\x82\xc1\x39\x93\xcf\x22\xc4\x1a\x41\xd9\x10\x8b\xb2\x04\xf0\x13\x70\xd7\x62\xb3\x93\x00\x0f\x3c\x3d\x91\x75\x7f\xed\x53\x42\xde\x01\x85\x2b\x2f\x4d\x47\xc4\x6b\xec\x3b\x6c\x29\x32\xf2\xb2\x09\xc5\xff\x61\x96\x46\x14\xb2\xb6\x74\x6d\x58\xae\x8e\xa2\xd8\x76\xdd\xe5\x3a\x37\x44\x51\x52\x97\x73\x8c\x6e\xb6\x11\x04\x23\x82\x3e\x41\x07\x71\x77\x9b\x8e\xed\xee\xb0\x71\x08\xbf\x5b\xab\x98\x62\x4b\x2e\xec\x6b\x69\x07\xf8\x50\x51\x2b\xaa\x30\x29\xdc\x82\x0b\x7b\x99\xd7\xea\x69\xb0\xfc\x28\x05\x84\x14\x55\x29\xbd\x12\x33\x44\xec\xf9\x46\x2b\xcd\x5c\x4c\xc8\x4b\x88\xa2\x28\xdc\x5c\x06\x28\xd6\xbd\x20\x3c\xb0\x2c\xa1\x7b\xc1\x29\x2d\x47\x7a\x97\x47\xa8\x72\x2d\x5e\x96\x66\x10\x12\x22\xce\x3b\xb7\x27\x31\x92\x3a\xff\x14\x44\x52\xe7\xeb\x08\x49\x39\x16\xd7\x7a\x39\xf8\xae\x95\x01\x17\xd9\x4f\xe2\x15\x09\x6a\xa5\x4b\x8f\x5e\x59\xee\x84\x93\xd5\x9a\x42\x3d\x5c\x6a\x13\x2a\x41\xb9\x85\xd9\xac\x62\x99\xb5\xb5\x2c\xb0\x2b\x6f\x23\x86\x7c\xfd\xf8\xc7\xa7\x37\x6f\xa7\xbb\x0b\x2e\x8d\x63\x79\xcc\xbf\x24\x8c\xf1\x4d\xc4\xb9\xfb\x87\x2f\xef\x2f\xd8\x31\xfd\xfc\x95\x3a\x9f\x56\x6d\x6c\xa3\x53\x29\x5c\x76\x74\xaf\x65\x42\x67\xd1\x29\x6c\x6d\x97\x42\x61\x5a\xfc\x99\xfe\xb6\x67\x11\x18\xd0\x37\x0f\xdb\xfd\xea\xa7\xdd\x04\xbc\xdc\xa0\x21\xbd\xbb\x45\x17\x0e\xc8\x3f\x6d\xf0\xaf\x80\xfc\x8b\x47\x7a\xc9\x5f\x71\x3b\xb8\x17\x19\x11\x5d\xa3\xd9\x37\x71\xe2\x4f\xe4\x89\x57\x40\xc6\xc7\x98\x6b\x67\x0c\x90\x03\x04\x53\x85\x09\x38\x21\x97\x15\xcc\xf1\x11\xdc\xda\x39\xbd\xb4\xbe\x13\x14\xb8\x5f\xf9\x52\x35\x96\xbf\xe0\xa5\x9e\xfb\x4e\xbb\xe1\xb8\x4d\xed\x37\xb6\xe2\xd6\x34\x7e\xd8\x4e\xe3\x2d\x3d\xf9\xe9\x34\x26\xd8\x82\x63\x88\x34\x23\x03\x10\xcb\x86\xf9\x50\x4e\x14\x1a\x76\xa5\x4c\x19\xce\x93\x64\x95\x29\x62\x0f\xa5\x3c\x43\xf7\x50\x02\x9e\x35\x0b\x35\x29\x64\x54\x31\xb4\xf1\x5c\x60\xe6\xe4\x32\x37\x24\x09\xb2\x21\x30\x2e\x00\x0c\xcb\x69\x89\x15\x1b\xf5\x61\x85\xbb\x35\x00\x8a\x65\x1c\x1c\x7c\x8e\x7b\x69\xcd\x01\xc9\x09\x31\x1e\x7c\x6b\x13\x58\x2b\x89\xf2\xac\x5c\xee\x88\xec\xa4\x0e\x22\xbb\xd6\x64\x16\x46\x97\x53\x3c\x78\x02\x74\x77\xe1\xdd\xec\x91\x39\xe5\x8b\x03\xca\x6e\x26\xcd\xc4\xe8\x51\xe1\x0b\x65\xeb\x52\xc8\x1a\xfd\x3b\xad\x68\x86\x20\x3c\x46\x82\x6a\x5a\x51\xa6\xe3\x31\xf7\x5b\xcd\x74\x55\x78\x26\xdf\xc4\x1e\x9f\x39\xc9\xfd\xe1\x99\xb3\x0a\x13\xe4\x03\xb6\x57\x79\x06\x81\x11\x1c\x8d\xf0\xbd\x81\x30\x87\x0c\x65\x2b\x1b\x8b\x85\xe2\x76\x56\xc0\xed\xe8\xd1\x2b\x43\xb5\x1b\x25\xd2\x99\x31\x5d\xea\xa1\x84\x3d\x85\xfc\xd4\xd2\xdf\xfd\xc0\x04\x3d\x65\x03\x7e\xd6\x92\xe7\x78\xf0\x5d\x3a\x3b\xe6\x43\xef\x7b\x0a\xe0\x5f\xd2\x7c\x55\xa4\xd7\x2c\xeb\xd1\x81\x78\xef\x19\x4e\x1b\x51\xfb\x33\xe6\xe0\xe4\x2b\x89\xf9\x45\xd8\x1a\xea\x5e\x46\xdc\xa7\x90\xf6\x14\xda\x8b\xc5\xc0\xee\x97\xbe\xe0\xbf\xfa\xf2\xff\xba\x7c\xf9\xf8\xcf\xfb\x65\xff\xe5\xe1\xdb\x1f\x9b\x9c\xb1\x77\x5b\xf4\xe6\x13\x7b\xbb\x9a\x8b\xef\xf9\xe4\xd3\x54\x11\xa8\xb9\xc8\xdc\x7a\xde\xa9\x95\x9b\xd2\xd9\x57\xc3\x7a\x57\xaf\x90\x6b\x01\x74\x1a\x1d\xf8\x5e\xc0\x18\x53\x57\x31\xc5\xe4\x62\xe8\x33\xc5\x28\x33\xc0\xc5\x8e\xcf\x19\x40\x39\x00\xa2\xa2\x8e\x18\x9c\x18\xcf\x55\x01\x72\x49\xd1\xcb\xe1\x98\xa1\xa6\x35\x03\x6c\x80\x28\x2d\x0e\x04\xf3\xac\xbc\xcd\xa0\x4c\x9b\xbc\xec\xba\xbb\xc9\x28\x52\xb3\x99\x2d\x14\xa2\xe3\x90\x67\xdf\x1a\x10\xea\x99\x82\xd6\xfb\xe9\x9b\x52\x33\x9f\x90\x34\x23\x23\xa0\xa3\xe1\x0f\x8d\x1e\xa3\x55\x29\x2c\x0c\x13\x96\x3b\x4a\xc0\x39\x38\x70\xef\x96\x32\x67\x55\x78\x3b\xd6\xee\xde\xd7\x14\xbf\xbf\xee\x3d\xb8\x94\xda\x3e\x11\xcd\x9a\x02\x50\x9d\xb7\xe9\x85\x34\x5b\xb4\x82\x67\x25\x07\x2b\xca\xf0\x4b\xd2\x95\x48\xc8\x43\xd8\x16\xe8\xf9\x33\xa4\x38\x4c\xc0\x1c\xcd\x1d\x1a\xd4\x51\x86\x98\x0c\x9f\xbc\x46\xcf\x8e\x23\x5e\x3e\x20\xe7\x42\xac\xb8\x82\x40\x9e\x8c\x2a\xf2\xdd\x9b\x63\x3e\x10\x02\x34\x88\x70\x80\x01\xcd\x23\xe1\x40\x6c\x98\x89\x5d\xac\x87\x94\x26\x0a\xec\x50\x5e\xe5\x31\x6e\xd2\xbe\xc1\x16\x55\x96\x11\xa4\x50\xbc\x9a\xea\x94\x27\x65\x4e\xea\x11\x04\x96\x40\xae\xb3\x16\xcc\xab\x33\x92\xd9\x6c\xe0\xd8\x1d\xd7\xb9\x56\xe8\x77\xcc\xae\x95\x39\x55\x31\x3f\x53\x05\xc0\x95\xba\x63\x65\xbe\xe4\x3a\xc3\x8c\xeb\x4a\x6e\x55\x6f\x07\x44\xbf\x7d\x7a\x7f\xff\x65\xfa\xb8\xa5\x3e\x7b\xf7\xfe\x1f\x2b\x45\xbf\xa3\x48\x11\x3d\xcc\xd8\xea\xd2\xe4\x23\x42\x3f\xd1\x11\x1c\x3c\xc6\xf7\x86\x14\x50\x38\x7e\x91\xae\x2b\x5d\x38\x37\x85\xb1\x6c\x2e\xce\x44\x28\x82\x4a\xc5\xe5\x39\xcb\xd7\xad\x38\x9e\x90\xe8\x9e\x26\x31\xea\xd3\xc1\x77\x50\x0e\x22\x1d\x9e\xc1\x71\x64\x0c\x84\x20\x28\xb0\x42\x0e\xcc\x63\xb8\xda\x86\xd8\x51\x0c\x02\x1e\x38\xfd\x9c\x81\x67\xe4\x99\xfb\x84\xba\x8d\x16\x50\x63\xa3\x5b\x90\xe7\x60\x88\x41\xdd\xf5\x82\xd9\x05\x54\xbd\x6a\xeb\xa7\xee\x06\xa8\x57\x17\xe3\x18\xac\x67\xcd\xf5\x0e\xac\x3f\xe4\x73\x96\xec\x4a\x9a\xa1\x9b\x29\x5e\x5b\x9a\x99\x5c\x05\xc6\x18\x63\x30\xa4\xb9\x51\x39\xf8\x90\x51\x4c\x86\xa7\x85\xef\x72\x17\xd3\x3b\xc1\x9f\x0b\x78\x15\xa4\x24\x37\x0c\x9b\xb4\xab\x56\x17\xd3\xe4\xd5\x3f\x80\x25\x19\x27\x19\xf1\x3d\xe2\x6b\x98\xe2\xe0\x2e\x8b\x8e\xba\x4c\x9b\x09\x49\xd6\xb3\xe6\x99\x96\x41\xb2\x5a\xd5\x4d\x4a\xc6\xfa\x60\x0e\x7d\xe4\x0f\x5b\x29\x0e\x96\x65\x35\x00\x2d\xfb\x3f\xd1\xce\xaa\xf0\x74\xaa\x2e\x06\xe4\x3e\x2b\x1e\x2d\xb0\xc2\x7a\x41\x6f\x76\xbb\x24\xca\xea\x23\xc3\xc1\x50\x04\x47\x56\xe2\xec\x92\x07\xd2\x1e\xcb\x63\xb3\xc1\xea\x89\xd4\x40\x55\x6f\xe8\x06\x60\x8b\x9c\x9e\x38\x03\xbf\x08\xd6\x70\x72\xd0\xb6\xc4\x92\xa9\xea\x3f\x52\x4c\x59\x85\xa7\x6a\xf2\xe6\x5a\xb9\xd4\x8c\x57\x28\xd6\x43\x8c\x58\x9e\xad\x59\xd5\x91\xa2\x18\x45\x8d\x70\xb8\xd8\xcd\xc2\xf2\xbd\xac\x72\x19\x52\x1a\x42\xbc\x6b\x1a\xdc\xee\x44\x88\x7b\x48\xf1\x73\xb1\xaf\x52\x5f\x85\x3e\xd2\xe6\xc6\x16\x21\x3b\x04\xdf\xce\x2c\x5b\xee\xde\x4e\xdb\x65\xb6\xcd\x5b\x3d\x86\xe7\xe0\x10\x2d\xe1\xb8\x39\x9f\xb5\x57\xf9\xea\x2f\xb4\x76\x6c\xc7\xe7\xcd\x05\x0d\xfc\x79\x6b\xf1\x80\x9c\xd2\x5f\xf7\x00\xcd\xbc\x7d\xe9\x2b\xec\x5e\xfa\x0e\x9d\xdb\x5f\xfc\x0e\x7f\x6d\x2f\xc1\xf2\xd7\x5e\xda\xfd\x85\x2f\xf1\xd7\x76\x13\xc0\x76\x7e\xa8\x9b\x76\x2f\x79\xc4\x5f\xfb\x12\x40\xee\x53\xa5\x36\x28\x84\xcd\x95\x9c\x59\xf8\xfe\x2e\x63\x5c\xeb\x85\x5b\x0a\x09\xb9\xe4\x52\x3e\xea\x6d\x07\xf0\x9f\x77\x7f\x7c\x7c\xf7\x58\x6c\xbc\xdf\xa6\x16\x9e\x44\xf5\xa9\x07\xd7\x73\x9e\xb8\x47\x07\xe6\x26\x0a\xd5\x51\xa8\x96\xa3\xcf\x1d\x6f\x1a\x2b\xde\x74\xa5\x2f\x6d\x43\x1f\x6c\xd8\x2b\x81\x86\xbb\xa2\x2a\x00\x34\x41\x01\x1e\x26\x4f\xbd\x39\xea\x6d\xc5\x7d\x50\x34\x1b\x85\x84\xc0\xe5\xb8\x7a\x60\x29\x38\x85\x5b\xf0\xd4\x26\x02\xbf\x58\x6f\x03\x8c\x41\xef\xfd\xfd\x35\xae\x49\xb1\x4d\xca\x0e\x3f\xf9\xf1\x19\xe1\x2a\xc7\xa7\x7c\x80\x14\x7c\xd2\x7f\xf1\xd5\xf7\xd7\x45\x2d\xa3\xb2\x9b\x10\x1f\x29\x61\xf2\xeb\x01\x70\x4c\x7b\xc1\x01\x3e\xe5\x97\x12\x26\xfb\xd0\x6f\x65\x5a\x95\xe2\x6a\xff\x91\xa7\x77\xfe\xd1\x86\xdf\xdc\x29\xbe\x7c\xdb\x12\xce\xbc\x7f\x46\x16\xf8\x05\x64\xbe\x81\xcc\xbd\x0c\xa4\xee\x33\x04\xcd\xe5\x0c\x47\x96\x33\x20\x2f\x50\xec\xc0\xb9\xec\x3d\xe5\x76\x34\xdb\x9c\xef\x93\xed\xfa\xb2\xf9\x76\x67\xff\x31\x1f\x7c\x0c\xab\xff\xf2\x67\x1b\x61\x76\x25\xdc\xa0\x81\x2d\xc5\x07\xba\x8c\x91\x24\xc6\x51\x25\xbc\x5b\xeb\xd1\x35\xeb\x47\xc1\x78\x87\xe1\xc9\x96\x28\x17\xec\x8b\x41\x42\xf8\x3c\x60\xf2\x91\x5c\xf4\xbc\xb3\x0b\x2a\x98\xd7\x38\x44\x58\xb3\xf4\xc6\xc3\xd9\x9a\x57\x06\x85\x22\x1d\xd5\xc1\xa6\xb5\xa1\xac\x59\x48\xe7\xfe\x5b\x0b\x81\x34\xe5\xd1\x8f\x79\x91\x9e\xda\xa1\xfc\x1a\xa9\x41\x45\x01\x5f\x45\x45\x5c\x31\xbd\x62\x98\xc6\x02\xd5\x9a\x05\x38\xa3\x22\x2f\x28\x0c\xa2\xb8\x3f\xee\xc7\x8f\x9d\xc5\xd2\xdf\x2f\x74\x16\x7f\xfe\xf8\x69\xb9\xff\x72\xff\x75\x93\x44\xf3\x9e\xcf\x1c\xf6\xe6\xd2\x7d\x36\x92\xca\x0c\x7b\x0f\x16\x5b\x73\x91\xc5\x2a\xea\xd1\xd5\x06\x56\xa7\xee\xa2\x6c\xc9\x8e\x89\x66\xd6\xc2\x28\xd8\x94\x28\x72\x56\x8d\x1f\x38\xbe\x48\x72\xa3\xa2\x0c\xe8\x48\x84\x03\x99\x57\x66\xc7\x55\x63\x18\x40\x6f\x44\x12\x21\xe8\xcd\x51\x11\x58\x40\x02\x9a\x5d\x89\x47\x8c\x53\x70\x78\x83\xf4\x00\x7e\xc1\x8a\x62\x3d\x24\x9e\x29\x72\x3e\xca\xed\xfb\x9a\x93\x28\xfb\x83\xe1\x29\x27\xe5\xdb\x6e\x51\xe1\xe3\x89\x48\xf3\x41\x80\x65\xcb\x61\x66\x57\x91\x3a\xb2\x88\x70\x98\x8b\x33\x66\xf3\x14\x81\xa9\x59\x34\xdb\x42\x03\xc2\x84\x7c\x0d\xc4\x5c\x40\xc1\xc8\x0a\xb0\x17\xf0\xb2\x00\xe0\x54\x9e\x72\xdf\x78\x84\x5b\x48\xcd\xfd\x1a\x94\x91\x5a\x7a\x06\x00\x91\x86\xab\xd0\xa1\x53\x6b\x3c\x32\x19\xab\x89\x3e\x62\x86\x67\x02\xc9\xd1\x0a\x88\x09\x4c\x57\x2d\xf8\xaf\x0a\xc6\x99\x75\xe7\x68\x71\x81\xc9\x12\x77\xb3\x2f\x9a\xb5\xae\x96\xec\xa2\x85\x9a\x5a\x6e\x23\xd6\x11\xec\x10\x9e\x7c\x97\x69\x05\x10\x80\x6a\xc8\xf3\xa0\xf7\xaa\x33\xd2\x22\x3b\xd2\x56\xa3\x63\x2c\x39\xae\x2e\x71\x7c\x1e\x7d\xda\xcf\x42\xe7\xac\x73\xf9\x22\xe3\xec\xfb\x23\x0a\x3f\x27\x03\xd1\xb9\x19\xe6\x7a\x6e\xc8\xad\x72\x9e\x5b\x86\x59\x4f\xa1\x39\x46\x45\xae\x4c\xf0\x28\x2f\x3d\x33\xd9\x04\x7f\xa5\x70\xd4\x23\xd7\xb1\x0d\xa6\xfa\x8e\xd7\x4f\x36\xf9\x21\x11\x22\x06\x08\xc0\x96\x32\xa1\x61\x7c\x76\xcd\x7c\xc4\x24\x86\x7b\x4d\xe6\x70\xaf\xca\x0e\xeb\xd5\xe4\xf5\x64\x3c\x97\x9a\x14\xae\xd4\xdd\x2a\x69\x83\xc1\xcf\x60\x92\x17\x43\x6c\x69\xc7\xf9\x3e\x58\x11\x02\xbb\x68\xe4\xfe\x61\xa1\x21\xa0\xc1\x70\xe5\x95\x1b\xc7\x05\x83\xe0\xe9\xc0\xd1\x4f\x8e\xb2\x2b\x74\x32\xf5\xd5\x03\x85\xba\x88\x80\x0c\x4b\xfc\xab\x25\x05\x8e\x95\x72\xc7\xe8\xc6\x51\x8f\x98\x30\x08\x70\xa3\xfb\x46\x4b\xb3\x7a\x08\xed\xfb\xd2\x0c\x21\xdb\x73\x13\xf1\x3b\xaa\x2b\xdb\x70\x2d\xf4\x7a\x3a\xf5\xa3\x4e\xfd\x64\x53\x5f\xc3\x3c\x0a\xd6\x83\xa4\xa0\xaa\x10\xf4\xa9\xeb\x7e\x64\x68\x8d\x58\x4f\xe8\x02\x5b\x4f\xda\x56\x23\x10\x4a\x0a\x07\x11\x0d\xc6\xba\x32\x72\x15\x88\x49\xf5\x85\x04\xc4\x12\xc4\x06\xd4\x6e\xe7\x9c\xf6\xf0\xd4\xfd\x7c\x20\xf6\x36\x54\xd4\xc3\xc3\x1f\xd3\xfd\x9b\xcf\xd3\xb7\xaf\x97\x67\x7c\xfa\xc7\xca\x78\x52\x5d\x01\xf2\x2f\x23\x5c\x50\x12\x02\x08\x07\x19\xf7\x3d\x53\x9d\x07\x2c\x80\x8e\x77\x0e\x83\x06\x27\xc7\x31\x59\x14\xce\xb7\xaf\x00\x32\x20\x40\xc6\x00\x75\x57\x69\x01\xe7\x43\xa5\xc5\x3e\xf4\xdb\xb9\x03\x6e\x3f\x03\xce\x7a\x92\x29\x4a\x01\xc9\x0a\x23\x7b\x22\x57\x85\xb6\x25\x1d\x4a\x64\x86\x1e\x6b\x25\x46\x42\xf0\xc9\xe1\xf1\x8c\x99\x0a\x52\x00\x8b\xd6\xa6\x88\x90\x40\x36\x79\x0d\xc8\xce\x64\x97\x5b\xde\xed\x29\xf4\x03\x11\xf8\xba\xc7\x01\x85\x83\x3f\x3f\x3a\x3b\x20\x0a\xff\xaa\xec\xc1\xcf\x9c\x0b\x9b\x69\xb0\x49\x4e\xe3\x18\x8e\x05\x12\xb1\xba\x02\x09\x6d\x09\xea\x28\x8c\x56\x15\x28\x81\x2d\x38\x2d\x3e\x96\xae\x21\x9c\xd9\xeb\x6a\xf5\xdc\xb2\xcb\x22\x3e\xa2\xac\x7f\x59\x98\x59\x04\x40\x5a\x7c\x6e\x8e\x5b\x5e\xec\x63\x7c\x3d\xce\xd3\xeb\x66\x86\x5f\x31\x75\x50\x99\xb0\xe8\xa5\x48\x93\x82\x53\xb7\xaa\x81\xc5\xa8\x2f\x44\xea\xbd\xe9\x66\x98\x91\x85\x45\x07\xd3\x7d\x02\x7a\x01\x50\x5f\x21\x3d\x96\xe3\xd1\xd9\x19\xeb\x95\xbb\x91\xc7\x0a\x9d\x2e\x9a\xb8\xcd\x22\x79\xc1\xfb\x59\x81\x63\xdb\x65\x4b\x84\x58\xac\x49\x13\xc6\x38\xf3\xbe\x74\x06\xf8\x52\x01\xec\x93\x6c\x84\xdf\x5f\x4b\x3f\xba\x9a\xf2\x41\xa4\xd5\x5e\x94\xa3\x83\xfc\xb3\x97\x3f\x0f\x7a\x10\xfa\x41\x7e\xc3\x67\xe8\x7b\xf9\x01\xa7\x70\xb8\x5d\x4d\xfa\xe7\xc3\xa7\xfb\x4d\x9a\xe1\xfb\x6d\xe6\xd9\x31\xa9\xbe\x96\xe6\x62\x4b\xd0\xfe\xbb\x65\xf1\xa4\xd4\x64\x9e\xa7\xc9\x13\x5c\xe9\xb1\x4e\x48\x99\x45\x55\x6b\xac\x2e\xcb\xdb\xef\x19\x78\xaf\x96\xf7\x03\x8b\x8a\x5b\x18\x1a\x5f\x35\xaf\x3b\x25\x5e\x54\xd7\x12\xe5\x68\x31\xa2\x24\xf9\xb0\xea\x23\xec\x4c\xb1\x39\x7c\x06\x05\x2b\x22\xbb\x04\x57\x30\x39\xb9\x89\x7d\xac\xdf\x1f\xcf\xb5\xab\xc7\xdd\x4e\x9e\x70\x7c\xae\x35\x65\x94\x6f\xb7\xb4\x3b\x64\x3a\xc9\x6d\x7f\xa4\xd9\x8f\xa8\xfd\x45\x43\xe0\xe0\xe5\xd2\x8b\x69\xfd\x7b\xbb\x50\x7e\x3c\x2b\x57\xb2\x2a\x2c\x33\x70\xec\xee\x17\xb3\x4a\x6a\xe7\xcb\x79\x1e\x7a\xd1\x63\xdd\x5d\x4e\x7f\xa1\xee\xfe\xee\xee\xcb\xfd\x72\x11\xf7\xf1\x7d\xbd\x41\x1e\x0d\x5f\x92\xf2\x4e\x9d\xb4\x7c\xf2\x49\xa6\x08\x0a\x4c\xcf\x6b\x41\x97\x51\x4b\x2d\x27\x8c\xdf\xd7\x5a\xea\xb3\xa2\x80\xd6\xcb\x8f\xbd\xc4\xb6\xfa\xf2\x7d\x7b\xea\x15\x2c\x3d\xec\x52\xe7\x4b\x3b\xae\x16\x30\x4c\xe3\x3d\x06\x96\xb0\x53\xc0\x08\x4f\x7d\x5a\xfb\xc0\xde\xef\xd9\x2f\x70\x09\xe5\xf8\xfd\x86\xb9\xbd\xa4\x70\x6a\xf1\x87\xd6\x0e\xde\x2a\x09\xb7\xaf\xf1\x9c\x7e\xbf\xf1\x2e\xcf\xef\xfc\x8b\xd8\xbe\xef\x37\x39\x43\xc7\xc6\xe7\x7a\x34\x08\x9f\x3f\x81\xc6\x02\xd0\x17\x3e\x9f\xff\x3f\xd3\xff\x0f\xd3\xb7\x3f\x3f\x6d\x77\xbd\x6d\xb2\xc8\x29\xc1\x6f\x70\x61\x5f\xc2\xc8\x1a\xd6\x1a\x77\xba\x95\x6f\x68\x4a\x41\xe4\x83\x9c\xb7\x5e\x22\x3b\x43\x68\xd7\x13\x11\x4f\x1c\x92\xb7\x39\x6d\x6f\x38\x24\xaf\x71\xda\x5e\x73\x48\xde\x8e\xab\x3f\x7c\xd9\x8e\xf5\x36\x9c\xfe\x68\xad\x6d\x6a\xde\xff\x4a\x71\x71\x45\x42\xfd\x9e\xe5\x2d\xfd\x75\x59\xc6\x6e\x71\x6b\x7e\x67\xa7\x3d\xf9\x0e\x17\x44\xec\x36\x78\xf5\xd4\x2e\xf1\x7b\xc6\xe0\xfe\xd3\xe1\x7e\x7a\xf8\x7c\xff\xe6\x6e\xda\xcc\xdd\xfb\xad\x2b\xfd\x34\x15\xa4\xb3\x6b\x5c\x0e\xbe\xf6\xf4\x43\x08\x1a\x72\x5d\x1a\xb5\x57\x24\xea\xf1\x0c\x64\x62\x4e\xc5\xa5\x2e\xba\x72\xca\x20\x27\x49\x0c\x6b\xd3\xa8\x3c\xd5\x0c\x4f\x6d\x41\xa1\x11\x8b\x7e\x4f\x7b\x9a\xb3\x96\xb5\x07\xe0\xa8\xe9\x49\xa9\x2d\xb8\xae\x00\x4d\xa7\x6a\x22\x55\xea\x62\xc3\xe2\xc6\xc8\xe5\x0e\xae\xd5\x13\xc8\x8d\xd9\x22\xea\xc8\xf1\xc8\x70\xb3\x68\x94\x76\x37\xfb\x58\x51\xf2\x42\xce\x27\xd4\x5f\x21\xea\x6e\xf1\x64\x7e\xb5\xf2\x3b\x81\x11\xa1\x2d\xca\x01\xa9\xa0\x57\xd5\x42\xc6\xc8\x5d\x12\x0d\x66\xef\x09\x89\x1a\x9a\xc6\xd5\xed\x14\x9c\xc1\xce\x2e\x4a\x70\x0f\x27\x5e\x19\xdc\x3a\x21\x4f\x4e\x2c\x30\x6a\x9a\x48\x14\xb2\x68\x7c\x30\xae\xd9\x25\x76\xa6\xe3\x2b\x46\xae\x28\x81\xea\x3a\xad\x0d\x94\xcf\x8e\x62\x58\x50\xd6\xee\x32\x6b\x94\x16\x96\x9e\xf9\x4d\x20\xe6\xd4\x05\x70\x5b\xd0\x4d\x1f\x3f\xfd\xf3\xfe\xfd\xc7\xcd\xba\xbd\xa7\x35\xfb\x3e\x75\xd7\x89\x0e\xbe\x77\xda\xfb\x18\xc3\x41\x0e\x62\x0c\xdf\x5f\x47\x0c\x04\xd5\x99\x14\x48\x21\x1b\xa0\x25\x1f\xd3\x09\xbb\xa6\x7b\x19\xce\x03\xbb\xd4\xd1\x73\x84\x32\x84\x9a\x94\x18\x54\x13\x07\x50\x07\x3a\x20\x94\xa2\xa6\x03\x2e\x9a\xe4\xc7\x27\x24\xbc\xed\xe0\x73\x69\x7b\x1f\xb9\x1f\x72\x84\xb5\x18\xb2\x96\xf5\x3b\x2a\x86\x0c\x26\xe6\x6e\x06\x28\x66\x89\xe6\xac\x7b\x35\x20\x33\x51\xed\xe9\x7c\x53\x02\x0b\x1a\x9c\x17\xce\x37\x3a\xf8\x9c\x23\x6e\xbd\x9b\xd9\xc5\xde\x1d\xbb\x22\xf3\x9c\x1c\x23\xb4\xe2\x52\xdb\xcb\x83\x3d\xa5\x24\x6f\xc6\xc1\x45\x25\x5a\x2c\x9a\x3d\x98\x79\x69\xe6\x6a\x51\xbb\x89\x74\xc6\xc2\x87\x55\x75\x40\xe0\xab\x93\x99\x15\x9f\x4a\xef\xfa\xf6\xe9\xfd\xc3\x66\x64\x2e\xba\x9c\xc5\x82\x54\x1b\xaf\x03\xad\x0a\xb4\x41\xb0\x4e\x61\xe0\x89\x61\xd1\x8d\xf2\x83\x40\xef\xe7\x23\x57\x57\x75\xea\x15\xd4\x52\x2b\x0c\x29\x4a\xfe\x46\x86\x5a\x33\x1e\x8d\x89\x62\x75\x28\xdc\x0d\xae\x3b\xce\xae\x03\x1f\x8b\xd5\x99\xc5\xb3\x0c\x7e\xcf\x0e\x25\x30\x94\xea\xc2\x28\x40\xe1\x35\xc5\x44\xee\x03\x84\x0f\x54\x1b\x3b\xf5\xaf\xe1\x5f\xad\x3f\x56\xca\x2b\x9c\xb7\xf8\xd3\xe3\x93\x73\x10\x08\x39\x5e\xed\x8f\x77\x9d\x7d\x6f\xc6\x2c\xa2\xa8\xa9\x8b\x16\xbf\xc1\x34\x42\xd3\x51\xbb\xf6\x57\x80\xc6\x44\xe3\xe2\xd2\xd8\x23\x39\x56\x0e\x73\xf5\xde\xc1\x2b\x91\x15\xff\x4b\xeb\x25\x31\x02\xcb\x3a\x26\xeb\x30\xd9\xc0\xdd\x5e\xa9\xf7\x7f\xdc\x6d\x92\x7d\xef\xb7\x85\xcf\xa7\x72\x5d\xa6\xdd\x91\xab\xc9\xf9\x1e\x34\x4c\xea\x15\xb7\xad\xdb\xb7\x64\xe8\x6e\x71\x50\xd4\xd6\xc9\xc7\x12\x5d\x44\xc8\x67\x83\xee\x96\xa2\x93\xc5\x60\xa0\x51\x93\x2c\x37\x24\x11\xcf\x9a\xb4\x94\x34\x97\x95\xd2\xe2\x81\xeb\x6b\x30\xd5\xea\x1e\x64\xcb\x0f\x13\x05\x2d\x58\x50\x8b\x0c\x8d\x75\x29\xf6\x69\x5e\x09\xf9\x49\x7d\xac\xb3\xe6\xfa\x59\x71\xca\x5a\x36\xa9\x6e\xb6\xa6\xc5\x4f\xac\x2c\x54\x86\x66\xa0\xf4\xf8\x6c\x40\xa9\x1a\xd8\x03\xdb\xb7\xc7\x3c\x3f\xa9\x67\x99\xfc\x28\xfb\x1b\xe0\x0e\xa8\x67\xd1\x5c\x4d\xf8\xa0\xca\xd2\x1d\xb3\x02\x53\xca\x67\x19\x01\x2d\x45\x8e\xec\x0b\x29\x04\xfa\x1c\xad\x16\x06\x00\x0c\x48\x16\x53\xe8\xee\xc5\x1c\x86\x03\xf4\xd5\x17\xfb\xa4\x60\x10\xcf\x72\x60\x78\x8e\x0a\x58\xab\xa8\xa5\xc9\x59\x8f\xc6\x84\xf0\x57\x9a\x62\x92\x3d\x0f\xe9\x8e\xf8\xc2\x51\x5a\xb4\xb7\x0d\xfe\x5d\x21\x1e\x89\x0d\xeb\x11\x3b\x78\x18\xa1\xb8\x60\x00\xd6\xc5\x3e\xe1\x53\x2f\x03\x7b\x15\xfd\x1c\x15\x09\xa3\xcd\xd1\x45\x67\xaf\x0a\xd6\xc9\x15\x20\x13\x17\x00\x88\x5e\x3f\xfb\xc2\xc5\x81\x86\xe9\x58\xea\x84\x52\x4a\x6f\xb5\x94\x47\xd0\x8c\x91\x40\xab\xee\xba\xa2\xb9\x0b\xd2\x54\x45\x95\xe4\x35\xd6\x69\x05\x5c\xaf\x06\x7a\x61\xd3\x21\x05\xc7\xad\xcd\x02\xf9\xdc\x61\xd7\xd6\x54\x4f\x5a\xa1\xbb\xf3\x1a\x76\x1c\x28\xe7\x00\x84\x5e\x91\xa1\xa3\xe1\xc4\x92\xce\xca\xd9\xfa\x58\x27\xee\x62\x13\xf8\x38\xad\x27\x99\xe8\x00\x89\x4b\x36\xf7\x5d\x8a\x46\x1a\x85\x95\x33\xc9\x5a\x91\x05\x33\x47\xcd\xe6\xd4\x45\x75\x73\x35\xbf\xbf\xfb\xba\x7f\xfb\x70\xf7\x65\x03\x09\x71\x7f\xab\x2c\x3f\xb6\x64\x88\x10\x2b\xfb\xda\x09\x47\xa2\x92\xac\x9d\x70\x15\x9d\xd2\x28\x9e\x1c\x9e\x9c\x71\xbc\x6e\xbd\xd9\x77\x18\xae\xc6\xb8\xfd\x17\x3e\x85\x42\x48\x2e\x66\x9a\x40\x7b\xdf\x78\x2e\x70\xbb\xd7\xa1\x03\x28\xb9\x1e\x77\xc5\x82\x6e\x06\xec\x19\x11\x08\x05\xbc\x2c\xd8\xf1\x1b\x6b\x2e\x25\xd6\x90\x48\x74\x9d\xdf\xb2\x1f\xb5\x41\x1f\x5f\xab\x62\x3c\xa7\xa2\xd1\xc9\xd6\x17\x4a\xc5\x71\x58\x5a\x47\xfd\x39\x15\x10\x36\x5a\x8d\x78\x65\xd7\x69\x00\x45\xfd\xe5\x9d\xad\xc9\x63\x9a\x03\x70\xf6\x9c\xdd\xaf\x7e\x50\xaa\xfc\x77\x0c\xab\x79\x1c\xd5\x22\x82\x1f\x52\xb4\x6c\xc4\x79\xba\x42\x3a\x80\x19\x4c\x8b\xbc\x56\x7a\xd7\x9c\x9c\x28\x5d\x38\x9b\xd9\x2e\x4b\x4d\x93\x1d\x01\x59\x12\xc5\x4e\x40\xb2\x6a\x59\x90\x4a\xd3\x69\x11\x69\x58\xf5\x03\x39\xc8\x48\xea\xe9\x84\xf3\x10\x09\xab\x32\x47\xd2\x13\x9c\xe4\x0f\x7f\xfe\x79\xff\x69\xb9\x68\x36\xdd\xaa\x58\x6f\xa3\x60\x1d\x18\x35\xd8\xa1\x14\xc1\x5a\x23\xe4\x0d\x38\xe4\x46\xd5\xaa\x02\x2f\x6b\xf0\x90\x58\x2b\x44\x3c\x93\x46\x37\x74\x0b\xa8\xf9\x55\x9e\x1a\xaa\x22\x26\x24\x2b\xc1\x76\x4c\xba\x3f\x57\x2d\xc8\x99\x29\xb3\x2b\x11\xaa\x24\x55\x9a\x52\x74\xb1\x4d\xa0\x7d\x44\xe2\x79\x73\x50\x49\xda\xac\x4d\xd2\x16\xa1\x41\xd2\x1e\x6d\xce\x08\xae\xaf\x0d\xc3\xe1\xf1\x77\x7f\xbc\xea\x88\xae\xa8\x71\xfe\x9a\x0c\x0c\x28\x2a\x1e\x51\x04\x72\x40\x8c\x62\xf0\x86\xa1\x52\x57\x95\xc8\x09\x5c\x01\x9a\x0c\x05\xec\x17\x70\xa2\x26\x9e\xd5\x20\x03\xee\x2e\x60\x73\xf7\xa0\xef\x34\xf8\x27\x37\x28\x18\x00\x5e\x74\x00\x18\x52\xd2\xc4\x10\xe2\x85\x45\x80\x1b\xde\xf4\x54\x5c\x5f\x94\x51\xa2\xb9\x3e\x6b\x7e\x81\x26\x8c\x44\xad\xd7\x59\xe4\x6f\xc4\xce\x51\x71\x44\x0b\x57\x97\xb1\x5b\xa1\x8e\x3c\x57\xd7\x64\x46\xc2\x50\x62\x0e\x36\xfb\x59\xa9\x5d\x6b\x72\x04\xed\x9e\x64\x29\xca\x8b\xca\x7b\xca\x6b\x22\x34\xbf\xbe\xef\xb2\xf6\xc1\xb1\x63\x9e\x33\xdd\xbe\x5e\x9c\x6f\xdb\xd0\xc5\x71\xbe\xd5\x60\xf5\x75\x08\x59\x63\x1f\x2c\xa2\x65\x2f\x9e\x4d\x89\x48\xb4\xf8\x6a\x68\x4e\x48\x8f\x1e\xd8\x21\xb9\x2d\x5a\xea\x10\x79\xea\x40\x44\x99\x50\x46\xd0\xd2\x8c\x62\x68\x57\xc4\xda\x99\x52\x72\x91\x94\x45\x3f\xcc\x55\xc9\x1d\x11\x97\xa4\x34\xeb\x33\xe5\x91\x99\x17\x7d\xa0\x3c\xaf\x2a\x16\xd7\x78\x30\x8e\x8e\xbf\x7a\x3d\xff\xbb\xb6\x9d\x5b\x98\x65\x65\x02\xdc\x0f\x2b\x05\x4a\x54\xb6\x2d\xbf\xc0\xd8\x47\xbc\x73\xf1\x76\x00\xa8\xdf\x93\xdf\xfd\xc9\x95\xc0\x8c\xc2\xac\x2c\x0a\x9b\x2d\x6b\x05\x65\xc7\x68\x3a\xf0\xb9\x0a\x92\xb7\x20\x16\xca\xde\x23\xd6\xac\xc1\xc7\x13\x5e\x1b\x14\x49\x00\x71\x0b\x20\xd0\xc1\xc0\xa0\xd9\x95\x09\xf3\x06\xd8\x65\x18\x73\xa7\xb8\xed\x72\x94\x80\xb1\x8e\x68\x3e\x67\x99\x52\xc8\x8b\x19\x00\xf1\x6c\xe5\x62\x78\x0e\x70\x23\x39\x39\x04\x65\x61\x25\xc9\x26\x23\x62\x0e\x09\xda\xb1\xbb\x9e\x9c\xbc\xb4\xbe\x29\x5e\x74\xb7\xe8\x8b\xca\x7b\x8a\xe5\xcb\x45\x41\x0d\x14\x6c\x52\x15\xa3\x94\xe4\x39\x5e\x1f\xa4\xd9\x12\x98\xdc\x5e\x9b\x82\x94\x73\xb0\x9b\xcb\x02\x4a\x86\x39\xef\x41\x53\x63\x78\x6c\x22\x70\xb4\x6c\x63\x61\x51\x4a\x15\x0b\x09\xeb\x0f\x9f\x8a\xf9\x6d\x85\x08\xa2\x9d\x89\x1a\x5d\x91\xb7\x50\xd1\xab\xe8\xf6\xac\xc9\x3f\xd2\xeb\xe8\xf4\x3e\x28\x51\x80\x7c\x20\x32\x4c\x99\xb3\x65\xff\xa1\xc8\xa8\x88\x49\xa8\x0f\x4f\x33\x21\x91\x20\x06\x38\xc5\x18\x5e\xe0\xbe\x03\x37\x79\x67\xc0\xaa\x30\xf1\x52\xaa\x63\x94\xee\xd5\xaa\x60\x0c\x62\x59\x02\x7c\x86\x14\x92\x8b\x6a\x43\x48\x8a\xe3\x11\xae\xac\xa2\x34\x42\xdd\x01\x48\xe7\xab\xe5\x89\x85\xf9\xf6\xe1\xc2\x82\xdc\x84\x88\x5a\x2f\x43\xfe\xb7\xec\x7a\x0d\x8a\xfe\xae\x6c\x49\x69\xf2\x39\x29\x49\x78\xd5\x32\x0e\xf0\x75\xb3\x96\x75\x18\x17\x8b\xe3\x01\xf1\xae\x18\x77\x5d\xc1\xeb\x91\xd1\x56\x5d\x0b\xb0\x48\x8c\xd0\x17\xd0\x46\x5a\xd8\xa0\x1c\x60\x0a\x84\x44\x46\x47\x06\x43\x4a\x56\x2e\x07\x72\x8d\xf3\x0c\x2d\x16\xa5\x02\x0b\x37\xd7\xf7\x91\xe1\x41\x84\x97\xc2\xac\x8b\xa8\x13\x04\xe2\x41\xf5\x26\x00\xbc\xc0\x15\x16\xa7\xd8\x8b\xeb\x6d\x6e\x0e\x68\xe6\x6c\x17\x83\xac\xe8\x89\x32\xfd\xe5\xfe\xcf\xbb\x8d\xf3\xf4\x7e\x1b\x9f\x7a\xe4\x77\xe4\xd6\x56\x0c\x83\x4b\xf8\x03\xc8\x77\xbe\x00\x3f\xb0\xc2\x15\x9e\xa1\x0f\x94\x03\x75\x1e\xe8\xc0\x9d\xf7\xfd\x1a\x6c\xcb\xdf\xfe\xbc\xdd\x2f\x7c\xa0\x26\x9f\x6a\xee\x29\xd2\x4a\x15\x17\x59\x5a\xd2\x2f\x23\x56\x5c\xbc\x99\x7c\xf9\xc2\xde\xe9\x5a\x86\x09\x5c\xb3\x41\x9b\xeb\x35\xad\xd5\xf7\x70\xa3\x0f\x6e\xa7\x7f\x7f\xfb\xf3\xed\x97\xfb\x69\xba\xdb\x4c\x9f\x4d\x6c\xf0\x24\x3c\x25\xfa\x57\x0d\xed\xe0\xf3\x80\xd5\x4c\x2b\x4d\xad\x98\x8c\x01\x10\x13\x5e\x99\xd9\x07\x37\xed\xb5\x98\x9a\x05\x08\x06\x47\x70\x37\x86\x60\x84\xd8\x5b\x77\xb1\x2f\xb1\xbb\xd6\x0f\xf2\xac\x08\xe6\x0b\x11\x56\xb4\xa0\xda\x79\x58\x0b\xc5\x50\x5f\xae\x94\x88\xae\xbb\x4f\x04\x29\x5a\xea\x2e\xc9\xfe\x14\x5d\x41\x32\x00\x68\xb2\x7c\x51\x57\x96\xf4\x5a\xac\x46\x4b\xd7\x2b\x48\x90\x14\x27\xca\xb2\xbc\x8c\xe1\xc8\x73\x52\x27\xa6\x18\x36\xdc\xac\xd6\x09\xf7\xe0\x6e\xfc\x57\xc5\x2a\x98\x39\x0d\x4a\x94\x36\xfb\x14\x9d\xfa\xc8\xd6\x2c\x39\xc5\xde\x5c\x8f\xec\xf1\xda\xf8\xfa\xbc\xe7\x8f\x5a\x2b\x2b\x70\x7a\xd6\xf3\xa3\x3d\xbd\x39\xf8\xa0\xf4\xf5\x03\x6b\xe5\x69\x07\x15\xf9\xce\xe8\xea\xc2\x60\x06\xb8\x5e\x66\x2b\x4b\xc3\x91\xab\x33\x52\xf2\xa3\xd3\x6c\xd7\x08\xd2\x1f\xee\x4d\xfd\x9c\x4b\x2c\xd8\xe5\xdb\x4c\x98\xa9\x5c\x35\x10\x11\x16\x4e\x96\xca\x07\x27\xad\xc6\x27\xa8\xd5\x85\xcc\x43\x91\x49\x79\xdd\xd8\x89\x4e\xae\x20\x2e\x94\x64\x12\x76\x85\x46\x45\x85\x9f\x63\x70\x6c\x7b\x3e\xf4\x2d\x5a\xc5\x0b\x02\xcf\x9f\xef\xbe\x2e\x9b\x62\xaa\xfb\x5b\x30\x15\xc0\x00\x23\x6e\xfb\x86\x02\xb0\x80\xcc\x9c\xeb\x18\x36\x8a\xf3\x4f\x79\xa0\x98\x53\x24\xb6\xba\xb1\x8b\x78\x34\x7b\x8f\x82\xde\x5b\x70\x34\x56\x45\x76\x19\x8d\x46\xae\xbe\x1a\x04\xb6\x74\x9a\x3d\x77\x03\xce\xe2\xde\x0f\x1e\xb8\x58\xd8\x29\x20\x64\x15\xb7\xeb\x82\x6c\xda\x5d\x07\x02\xa3\x12\xae\x03\x81\x5d\x86\xb1\x41\x79\xcb\x35\xc0\x2f\x98\xa7\x11\x5e\xd1\x0b\x9e\xae\xe7\x43\xdb\x4c\x1f\xff\xd8\x2f\x6f\xde\x7e\x9b\xde\x6e\xc6\x78\x1b\x96\x3f\xc6\x1c\x6b\x2c\x6e\xe4\xdb\x5d\x91\x34\xcb\xe5\x95\x01\x06\xf7\x84\x44\x44\x0a\xc5\x71\xbe\xbe\x8e\x96\x4d\x95\xba\x16\x63\xf7\xc1\x51\x06\x43\x35\xad\x9e\x01\xc3\x33\x42\xb3\x80\x0d\x9c\x46\x42\x53\x0f\x0e\x8e\xf8\x05\x29\x6a\x48\x4c\x8b\x6b\x80\xc1\x8e\xad\xfd\x40\x47\x90\x33\xfa\xf0\xde\x2f\x7a\xa3\x93\x4c\x73\xc2\x88\x88\x24\x57\xff\xb1\x71\xc2\xc7\xb8\x8c\x83\x19\xc2\x53\xec\x15\xb8\x1e\xb8\xb7\x3d\xb3\xd6\xf1\x26\x98\x25\x8e\x7b\x33\x9e\x1e\x5c\x33\xae\x8d\x71\x2e\xcd\xd5\x2e\x4f\xa0\x16\x46\x3d\x99\x75\x75\xce\x96\xd3\xcf\xa5\x69\xb9\xa9\x58\x54\x2a\x39\x5a\x1d\x59\x5f\x5d\x71\x79\x91\xe7\x5a\x5f\xe5\x39\xa9\x58\x96\x8f\xa6\xec\xfa\xc6\x1c\x53\xd2\xcc\x46\xd2\xa4\x7f\x05\xa0\x33\xe2\xc6\x8d\x90\x48\x0c\xc0\x69\xad\xd5\x95\x29\x0f\xc8\x2e\x79\x06\x12\x49\x55\x0c\x9b\x87\x2b\x29\x2a\x98\xaf\x61\x41\x6a\x22\x17\x7c\xca\x47\x09\xae\x86\x01\x56\x81\xab\x58\x1a\x88\xc4\x3d\xa4\xba\x26\xf8\xb9\x2b\x5e\x89\x35\xd4\x8e\x6d\x2c\xa2\x65\xc0\x38\xcd\xce\xf8\x6e\xd0\x4c\xd1\xf7\xab\x6b\xa0\xfd\x33\xe0\x0a\xbc\xab\x75\x81\xf6\x00\xfa\xa5\x55\xc3\xd8\x86\x6f\x3b\x44\xc7\x70\x01\xf7\xee\x34\x4c\x82\xdc\x4d\x84\x39\x13\x23\x18\xd2\xfa\x02\xf3\x07\x71\xd3\x9d\x1d\x7b\xcb\x55\x4c\xea\xb9\x43\x7d\x41\xe2\x25\x99\x70\x4e\x4f\xa8\xf5\xf7\xff\xfb\x6e\x7f\xf7\xe9\x8f\xad\x1c\xbd\x8d\x8e\xd0\xd9\xc5\xcc\xcf\x81\x7d\x88\xf5\x69\x6c\x8a\x13\xa6\x00\x0a\x93\x8f\xd4\x91\x98\xe5\xbb\x43\x79\x11\x9f\xe0\x52\x4c\x11\x6e\x87\x30\x77\xfc\xe9\xfa\x55\x64\x08\x55\xb7\xe4\xf9\x4f\x21\x58\x0c\x1c\xf6\x01\xe9\x30\x89\x8e\xe7\xbc\x35\xc1\x1b\xe3\x4e\x7f\x02\x3b\x43\xdf\xf5\x07\x21\x2e\xa4\x97\xb6\xf8\x1b\x33\xba\x45\xd3\xc2\x27\xe9\x15\xe9\x9a\x19\x4d\x42\xa3\x9e\x86\x54\x46\xd6\xc9\xf4\x70\xb7\x75\xa4\x6f\x33\x4f\x4e\xb0\x95\xb1\xd9\x84\x76\xa1\xc0\x92\x39\x1d\x62\xe6\x1b\x7b\xe0\xd3\x90\x6c\x99\x71\x9f\x5b\x67\x9d\xd6\x6a\x4e\x11\x09\x06\x99\xf5\xcd\xb5\xae\x53\x5a\x33\xc5\x4c\x2e\x66\x65\x15\x63\xb0\xcd\xa5\xef\x2f\x07\x86\xde\x3d\x0f\x19\x5a\x24\x85\xe3\x14\x16\x6a\xcd\x51\x01\x2a\x34\xe2\x2d\xb7\x50\xa1\x11\xd8\xd4\x8a\x14\xd1\x93\x9a\xd6\xdf\x44\x9a\x2b\x3d\x0b\x15\xba\x9c\xa0\x42\x47\xb5\x6e\xd9\x82\x63\x08\xe5\x5a\x9d\x43\x6c\x4f\xb9\xd5\x30\x19\xbe\x7d\xbe\x38\x15\xb6\x29\x3c\x8f\xa7\x42\x3d\xad\xb5\x9d\x64\x2c\x64\xf9\xcf\x63\x1e\xba\x6e\x28\x28\xf2\x13\xc9\x58\x29\x9c\xe0\x51\x2f\xbd\x54\x3c\x0f\x58\x9e\x98\xf9\x87\xf0\xf9\x64\x12\xca\x1d\xae\x2b\x4c\xff\x9d\x06\x17\x2c\xc9\xaf\xf7\x5f\xde\xfc\xb9\x99\x01\x1f\x6e\xf1\x29\x01\xc5\xa8\x5f\xc9\xe1\xba\x8e\x6f\xbd\x3c\xce\xc7\x13\x4d\x90\xa2\x9a\x80\x6c\x29\x31\xd4\xc3\xca\x2c\x72\x89\x57\x44\x59\x45\x10\x59\x2f\x4d\x19\x2d\x23\x2d\xd8\x94\x9b\xa6\xf0\xa0\xe8\x68\x69\xa4\x95\x69\x2c\x62\x0b\x81\x2d\x56\x7d\x41\x73\x9a\x90\x2f\x1f\x61\x3e\x41\x21\x10\xbb\x49\x94\x01\x60\xc5\x10\x19\xde\xd7\x40\x64\x33\xa8\xb5\xdd\x80\x5e\x53\x20\x36\x69\x02\x69\x02\x85\x23\xb0\x77\xcb\x74\xaa\xe1\xa0\x20\xf9\x05\xb0\xa2\x3d\x2a\xf4\x89\x18\xdb\x0c\xbf\x5a\x48\x8b\x1c\x50\x50\x85\x46\x06\x4e\xe6\xb6\x02\x4a\x9c\x66\x9c\x7b\x4b\x39\x97\x3f\x0e\xc0\xc6\x00\xf8\x4b\x07\x62\xa9\x57\xc2\x8e\x95\x26\x61\x31\xbd\x5b\x75\xf5\x11\x91\x07\x89\x0d\xbb\x4a\x87\xd6\x37\x4e\x90\xe5\x91\x2f\xe2\x89\x27\xec\x9e\xf5\x08\x64\x87\x29\x95\xba\x06\xc8\xa2\xd5\x0a\x2a\xf9\x67\x30\xdc\xb3\x25\xb8\xd4\x94\x22\x35\x69\xad\x14\xd2\xe3\x44\xb3\x0a\x33\x14\xd6\x8c\x70\x82\x2f\x41\x07\x13\xe5\x7b\x96\xa2\x85\x01\xc6\x1e\x18\x9b\xe5\x3e\x44\x12\xed\x53\xd6\xdf\x5a\x1d\xfc\x8b\x29\x54\x76\x37\x38\x54\x6e\x23\x4e\xdd\x2f\xfb\x87\xaf\xef\x1e\x3e\x6f\x34\xaa\x0f\xdb\xe2\xed\x13\xc8\x5f\x11\xb3\x1a\x7e\xfc\x29\x96\x42\x59\x64\x96\x70\x59\xd8\x66\xab\x3f\x4e\x57\x5f\xc3\xc1\xc7\x9e\x8f\x7d\x16\xe9\xa4\xcf\xe2\x28\xd5\xe3\xe3\x5f\xa3\xcf\x22\x8d\x7e\x3a\x50\x94\x1d\x1e\x69\x51\x72\x69\x1a\x10\x37\xc1\x71\x66\x94\x52\x3c\xb6\xea\x67\x45\x00\x02\xed\x7c\x15\x71\x99\xaa\x4b\x32\xc7\x90\x56\x81\xd8\xc9\x49\xe4\xf4\x24\x9e\x7a\x1a\x66\x3d\x09\xbf\x82\xdc\x24\xc0\x99\x40\xed\xe0\x53\x58\x0b\x34\x7a\xd2\xfa\x0c\x46\xb4\x3c\xe3\xb3\x22\x72\x22\xeb\x4a\x43\xaa\xa4\x88\x06\x70\x4e\xb5\x63\x62\xcf\x1a\xe6\x3d\x06\x7f\x8f\x47\xeb\xcf\x33\x22\xb2\x45\x53\x6b\xd2\x0a\xb6\xc5\xf0\x2b\x5f\xa4\x98\xd2\x0e\x31\xfa\x2a\xec\x86\x99\x77\x0b\x3a\xce\x60\x72\xe3\x33\x9b\x2f\x23\xe7\xb3\xd2\x69\x9b\xf8\x59\x56\x89\x34\x07\xa7\x42\xec\x06\x6a\xe4\xcd\xa9\xfb\xed\xe3\x72\x89\x7a\xee\xc3\x96\x85\xe3\x11\xe8\x00\x65\xbe\x44\x3d\xc7\xb2\x40\x29\xb3\xe1\x00\x43\xe0\x75\x4d\x75\xcc\xcd\x15\xb1\xbe\x8a\xa3\xdc\x0e\x3a\x61\x3b\x3b\xfd\x7b\xd1\x9f\xf7\x25\x8d\x5d\xe3\xe4\x26\x83\xa3\x51\x71\x85\xcf\x09\xe1\x9e\xc1\x07\x77\xe4\xc4\xeb\xd2\xf3\xb6\x54\x3a\x6b\x56\xaf\x3c\x1c\x8d\xf3\xa5\x80\x75\x02\x0f\x2a\x69\xd4\x20\xe2\x87\xdd\x62\xa7\xde\x0e\x97\xdc\x4f\xd3\xa5\x18\xe6\x87\x5b\x29\x69\x1d\xfa\x92\xd6\xf8\x21\x3a\x84\x10\x52\xd6\x1a\xc9\x30\x50\x24\x2d\x55\x16\x5f\x9c\x9e\xa9\x34\x9c\x34\xa0\xd7\xb2\xca\x2f\x04\x79\xf0\xaf\xf3\xea\x9f\xb3\xb5\x08\x28\xf6\xca\x6d\x00\xb7\x1a\x60\x83\x37\xc4\x06\x1f\xdb\x7e\xb0\xa3\x3d\x13\x02\x01\x39\x82\x46\x82\xaa\x90\x0f\x9a\x16\x97\xb1\x6f\x74\x72\xad\x2d\x4d\xe6\xaa\x68\x6a\x55\x53\x01\x81\xe1\x90\x83\xe3\x50\x16\xf0\xfe\xb3\xbe\x7e\x66\x70\x4d\x31\xd2\x7f\x63\xa8\x7a\xea\xec\x1b\x72\xbd\x9b\x8b\x7d\x33\xf0\xcb\xd9\x78\x6b\x31\x22\xa2\x38\xb1\xcf\xd4\xd5\x25\x16\x91\xde\x97\x9b\x59\xd6\x1e\xf7\x9f\x8d\x05\x8d\x54\x05\x2d\x01\xf0\x93\xd2\x22\xf5\x5f\xe8\xf9\x4d\xab\xe5\x45\x16\xd0\x93\xce\xab\x77\x0f\x1f\x3e\xdc\x6f\x97\xd2\x36\x7b\xe9\x44\xd3\x2e\x65\x50\x82\x19\x3e\xec\x0a\x0f\x9b\x8b\x71\xa0\xb4\x24\xb3\xb1\x21\x79\xee\x54\x39\xf9\xfe\x1a\xd8\x1f\x5a\x01\x76\x6d\xc0\x50\x9c\x17\xae\x94\xb9\x7d\x7f\x4d\x2d\x97\x67\x52\x92\x59\x6b\x6e\xac\x1d\x38\x42\x2f\x2e\xf6\x1a\x4f\x2b\x77\x76\xa3\x74\x0d\x51\x4b\xcc\xf4\x1f\xdb\x78\x3f\x3c\x3c\x6c\xd5\xda\x6d\x7e\xca\x71\xc7\x85\xe4\x4a\x95\x81\xe4\x8f\xfd\x92\xae\xec\x97\xb5\xf6\x6b\xeb\x03\x11\xdd\xed\x8c\x3f\xc8\x25\x10\xd4\xe1\x82\xa0\x3e\xe8\x03\x6f\xf9\xbd\x57\xdc\xf5\xc7\x64\x9b\xa7\xdb\xbd\xa1\xaa\xbf\xec\x3e\xbb\x1f\xbb\xd1\x90\xc4\xc9\x88\x40\xc3\x4b\x7b\x24\xd3\x05\xa3\xff\xdc\x3f\xd2\x42\x30\x0a\xa6\x9e\x1c\x73\xc1\xe6\xd7\xd3\x9e\xf3\x8b\x8b\x55\x3e\x7c\x9c\xee\xdf\x2c\xf7\xff\x7b\x31\x6d\xe9\x43\x59\x53\xc4\x53\xc1\xee\x52\x2e\x7a\xa7\x8f\xb5\x99\x2f\x43\x7e\xd7\xde\x79\x0c\x76\x3f\xe2\x7e\x67\xc8\xef\x23\xb0\x90\x82\xe8\x65\xb5\xec\xd5\x83\xa4\xe4\x31\xcc\x2e\xd1\xe4\x23\x45\x17\xb5\x86\x19\x55\xc3\x48\x01\xb3\xf1\x50\xd2\x8a\xc0\xe9\x89\x48\x06\x48\x01\x28\xc7\x02\x3a\xda\xef\x3b\x18\x75\xba\x12\xcf\xa0\x49\x11\x81\x78\x36\xe2\xa9\x46\x3b\xb6\x80\xa7\xdf\x5f\x93\x68\xf3\x28\x8c\xfd\xe9\x9b\x5d\x68\xa2\xdd\x5f\xe6\xc5\x8b\xee\xbf\x7b\xf6\x03\x6e\xee\xec\xdf\x3e\x4e\xef\x3f\x7e\xfa\x63\x33\xad\xb6\xf5\xb2\xe7\x46\x34\xfc\x1d\x6b\x00\xe8\x8a\xbf\xb4\xdc\x5a\x21\x23\xf6\xb4\x75\x20\x96\xf4\x04\x0e\x71\x6a\xe1\xb7\x3c\x7c\x07\x41\xfb\xbb\x9e\x3e\xe6\xf9\x6f\x7a\x75\x30\xdd\xfc\xb6\x61\x37\x46\xa4\xdf\x38\xec\xbf\xab\xe7\x31\xec\xbd\xf3\xef\x1c\xf6\xdf\x36\xe5\x91\xf8\xf1\xdb\xa6\xbc\x0c\xfb\xef\xea\x79\xa3\xa1\x48\xed\x77\x8e\xfb\x6f\x9b\xf3\x88\x30\xff\xb6\x39\xaf\xe8\x83\xbf\xa9\xeb\x8d\x52\xec\xb7\xbd\x3c\xf2\x5c\x7e\xef\xcb\xff\xc6\x69\x2f\x6f\x8f\xac\x9a\xd8\xd2\x01\x4a\xa6\x37\x8f\x8d\x1c\x03\x48\x92\xaf\xde\x1a\x08\xac\x57\x23\xb8\xcc\xe9\x91\xe5\x51\xd2\x55\xb0\x14\x18\xb7\x97\xc0\x52\xf4\xa2\xc7\x60\x29\xe0\x5b\x7a\x99\x59\xb1\x7f\xf8\xfa\xf9\xe3\xb2\xad\x33\xfc\xb0\xcd\xe3\xfc\xaf\xea\xf7\x5f\xd5\xef\xbf\xaa\xdf\xef\x92\x86\xbf\xef\xdd\x7f\xa7\xf6\xf5\x7b\x15\x90\xc7\x1b\x01\x40\x71\x38\x97\xe1\x28\xbc\xc8\xa4\x99\xda\x95\x84\x6c\xbb\x14\x77\xf9\xf9\x2d\x04\x1b\x74\xc8\xe5\x26\x9d\xe0\xa6\x57\x36\x99\x2b\x03\x12\x4d\xd9\x14\x4f\x6e\xb2\x7b\xc9\x5d\x6e\x53\x12\x96\x6b\x29\x0d\x87\x0e\xef\x8d\xb4\xe2\x47\x2e\x1f\xfb\x28\xf0\xa2\xb0\xf9\xbd\x78\x1f\xe5\x0b\x09\xe2\xd2\xfb\xbb\x03\x03\xee\xfc\x91\xcb\x4b\x06\xf7\x52\x1c\x86\x9b\x26\xd7\xbf\x70\xf3\xbd\xfb\xf3\xed\xb7\xe9\xee\xd3\xbb\xad\x57\x7d\x9b\x06\x7f\xf4\xaa\x9f\xa0\x62\xff\x85\x65\x9d\x57\x50\xb3\x13\x98\x8a\x37\xb0\xd9\x55\x13\x63\xae\xe0\x66\xff\x92\x66\xee\xae\x94\x9f\x22\xc6\x10\xae\x71\x31\xc8\x7e\x65\x0b\xed\x31\x31\x06\x92\xba\x2e\xe0\xea\x33\xa7\xe1\xd7\x7d\x36\xea\x3e\xb6\x45\xbe\x98\x13\x84\x84\x9f\x33\x40\x7e\x69\x90\x26\xfa\x3c\xc6\xe9\x07\x86\x5e\x4c\x96\xa3\xbd\xbb\x3a\x9f\x6f\x84\x44\x7e\x16\xf4\x1b\xde\xee\xdb\x24\xf7\x27\xce\xf5\xe8\x72\x5b\x22\xbb\x4c\x8f\xd1\xb9\x49\xb1\xb9\x07\x32\xb7\x4a\x88\xc7\x0a\x2b\xe5\x17\xa3\xfb\xfd\x79\xff\xfe\x9f\x1f\xb7\x0e\xf0\x5b\x39\xf2\xc8\x44\x48\x54\xfe\x13\xa6\xc8\xcd\xe8\x74\x2e\x67\x81\xe5\xc8\xbb\x97\x85\xa7\x23\x9c\xf0\xf6\x84\x63\x78\xba\x35\x0b\x4f\x97\xf0\x03\xe1\xe9\x12\x9e\x1d\x9e\x8e\xac\x0f\x8a\x7c\x16\x9e\x7e\x56\x74\xfa\xc3\xc7\x3f\xf6\xcb\xfd\x97\x37\xff\xdf\xfd\x76\x72\x6c\x93\xeb\x4f\x62\x94\xb2\xe6\xc0\xfb\x4b\x9a\x35\xc4\xad\x81\x46\xdd\x6b\x8e\x26\x4f\x32\x68\xce\x97\x24\xdb\xa0\x71\x4d\x44\x20\x9f\x1e\xa7\x2e\x02\xd2\x7d\x40\xf6\x1f\x8f\xec\xb7\xbd\x6e\xb3\x05\x19\x03\xa2\x09\x94\x64\x94\xc2\x4a\xec\x00\x89\x9a\xf6\xfa\x54\x06\x98\x5e\xe7\x7d\x64\x39\x15\x5c\xc7\x7a\x92\xa6\x09\x4c\x76\x68\xc8\xa4\xa2\x57\xe8\x05\x13\x2e\xdd\xf7\x32\xad\x77\x94\x11\xc3\x83\xc6\x63\xe5\x9b\x7d\x2f\xbb\x17\x34\xbd\xf4\xe9\xf8\xce\x69\xb2\xce\xb0\x0c\x56\xd6\xdc\x7b\x6e\x8e\x03\xc2\x67\x4b\x43\x82\xf8\x13\x89\x04\x5b\x22\xdc\x0f\xdb\xe4\xec\x63\xe1\x97\x4c\xfa\x92\x82\xb2\x41\x43\x89\x52\xd6\x73\x9f\xa3\xbb\xb8\x57\x58\x52\x04\x50\x06\xbb\x55\xea\xa9\x05\x2f\xfd\x24\x4d\xd6\x6f\x40\x6f\xa7\xc9\x08\xd7\xd2\xa9\x44\x72\x4d\xbe\x24\x27\xef\xcc\x08\x49\xa7\x16\xc6\x61\x2f\x38\x54\xb4\xde\x92\xa4\x47\x0e\xbe\x85\xdb\x00\xd5\xfb\x8b\xb0\xd4\x1f\xde\xff\xe3\x54\x5e\x49\xbb\x57\x48\xc8\xb3\xec\xa9\xc7\x32\xfa\x24\x91\x0a\x9a\x98\x8a\x84\x55\xe0\x3e\xff\xda\x23\xe4\xe6\x59\x80\x56\x3a\x73\x9d\x2f\x6b\x80\x55\x1e\x04\xd1\x73\xc4\x1b\x7d\xfa\xaa\xc7\x10\xd2\xbb\x7f\x07\x0c\xe9\x0f\xe1\xc3\x56\x41\xbb\x3f\x1b\xac\x5c\xcb\x91\xa8\xf8\x51\x87\x47\x0e\x3f\x32\x18\x18\x48\xe4\xeb\x5f\xfe\xfd\x48\xa6\x7c\xde\xed\xf2\xb8\x17\x8d\x09\x46\xf2\x54\x79\xfd\xb7\x1e\xac\xf7\x0f\xdf\xde\x4e\xf7\x6f\xee\x3e\xfd\x31\xdd\x5f\x42\x9f\xa5\xb0\x4d\x0c\x3e\x56\x5a\x15\xae\x8e\x8e\x95\x56\x5a\x7f\x38\x29\x6b\x69\xb0\xfc\xef\xb5\x26\xd1\xa0\xf5\x27\x9f\x4a\x71\xa9\x94\x95\x6e\x9e\x02\x50\xb4\xe5\xdf\x69\xfc\xa6\x3f\xe1\x82\x45\x2f\x9f\xec\xae\xa7\x54\xfd\x8a\xdd\xa4\xf5\x1a\x90\xb9\x3d\x4e\xe3\xe0\xfc\xc4\xef\xaf\x29\x10\xfd\xaa\xc6\xee\xfe\xea\xd6\x3e\x7b\xc8\x2e\x81\xee\x52\xd8\xe6\x99\x1e\xc7\x2c\xf7\x8c\xfd\xfb\x51\x37\x24\x60\x5a\xda\x8b\x5e\xea\x88\x1c\x9c\x75\xd3\xe3\x31\x93\x77\x90\x77\xf1\x76\x70\xf1\x24\xbd\xfc\x42\x47\xad\x0f\x7e\x34\x5e\xbd\xf6\x5f\xdb\xce\xdd\x5f\xd3\xd0\x67\x0f\xd5\x06\x39\x95\xc2\x36\xaf\x92\xf2\xaa\x85\x87\x9a\xdd\xd0\x7f\x9f\x3f\x5f\xcf\xde\xd1\x8f\x97\x7c\xd9\x80\xde\x98\xd6\xd7\x46\x0b\xad\xd5\x7a\xa1\x9f\x6a\xed\xee\x6f\x69\xee\xb3\xc7\xec\x02\x62\x2f\x85\x6d\xfe\xe6\xa3\x51\xb3\x1a\xdc\x17\x4d\xdb\x5b\x42\xf1\xea\x94\x3c\x13\x23\x26\x45\x9e\x23\x88\x6c\xbc\x28\xe4\x97\xaf\xaf\x9b\x02\xf1\xd7\xb7\xf4\xa6\x3f\xe8\xfa\xae\xb5\x49\xb3\x3c\xc1\x4c\xe7\xea\x7a\xdf\x8c\xd0\x13\x22\x79\xf9\x0d\xbb\xdb\x33\x5e\xfe\xb2\xfc\xdf\x64\x3d\x9e\x80\xae\xff\x7b\x88\xff\xa7\xdf\xfc\x82\x38\xdd\x82\x43\x3d\x5a\x98\xc7\x52\xb3\x7f\x6d\x71\xfa\xf4\xdb\x5f\x14\x4c\xdb\xf4\xb3\x47\xef\xaf\xf9\x95\xff\xca\x82\xe9\xa6\x64\xbe\xff\xfa\xcf\xe5\x61\x3b\xec\xdb\xd0\xeb\x89\xbb\x02\xc0\x08\x29\x99\x0b\xe7\x6a\xc5\x6a\x09\xe1\xb6\xcb\xbe\xc5\x9b\x55\x8a\x72\xfd\xcd\x3a\x44\xab\x82\xbe\x49\x27\x9a\x81\xb4\xe0\xa3\x11\x8f\xc3\x73\x8b\xba\xac\x45\xfe\x4e\x5a\x54\x75\xd1\xc3\x09\xf2\x92\x13\x2f\xe4\xce\xdc\x90\xea\xa4\xa3\xe2\x52\x92\x5b\xd5\x20\x77\xaa\xcd\xd0\x1e\x5e\x46\x5c\x2a\xaf\xf8\x62\x9e\x80\xe9\xee\xf3\xa5\x21\xbb\xe5\xaf\x4f\x04\xd8\xdc\x6b\x48\xea\x21\x5d\x6c\x9d\xb4\xfa\x52\xeb\x0e\x5e\xaf\xb8\x86\xd9\x1e\x5a\xb3\xac\x21\xd8\x6d\x76\xf2\xb5\x61\x0e\xed\x1a\x49\x83\x35\xec\xea\x04\x93\x2b\x6f\x4c\xb0\xef\xbb\xd7\x54\x41\x45\xca\xf0\x42\x59\x88\x27\x05\x6d\x74\x69\xd6\x66\xe4\x1d\x63\xb2\x1e\x7b\x87\x1b\x7a\xa7\x34\xc4\x87\xd4\x87\x08\x70\x86\x14\x5c\x2f\x27\xd5\x1e\x8b\x56\x89\xe0\x0e\xe0\xcd\x0e\x06\x44\x56\x16\xfd\x80\xf7\xf1\x49\xf6\xea\xed\x7e\xb3\xf5\x26\x1f\x05\xcf\x31\xfc\xf2\x53\x65\x6d\x81\x13\xa0\xb0\xcc\x1c\xbe\xd2\xcd\x2d\x3e\x51\x79\x7e\xc4\x05\xb9\x34\xbe\x72\xf9\xd5\x55\x7c\xcc\xb1\xb9\xbd\x8a\x1b\xfc\xc8\x2f\x5a\x5b\xf2\xdc\x17\x2f\xad\x3f\x1f\xde\x7e\x9c\xee\xdf\x7c\xde\x3f\x6c\x78\xfb\x29\x6c\x5c\xb8\xb5\x8c\x6c\x94\x04\x14\x39\x40\x19\x03\x43\xe3\x55\x76\x4a\x50\x07\x74\x3d\x8e\xeb\xa1\x67\x23\xc4\x7b\x35\x38\xec\x4e\x0e\x4f\xce\x38\x5e\xb7\xde\xec\xfb\xeb\x52\x15\xba\xec\xf6\xb2\x50\xd2\xa5\x1b\xe3\x75\x7b\x3d\x22\xbf\xfc\xca\x78\xa5\x86\xee\x2c\xbb\xd3\x02\xa9\xdb\x53\xff\xac\x30\xaa\x96\xb5\xec\xcc\x4a\x4c\x2f\x15\x3b\xe0\x05\x2e\x14\x3b\x0c\xc0\xda\x0d\x0a\xd9\x05\x54\xb0\xdb\x65\x44\x1f\xbf\xbc\x9b\xee\xdf\xbc\x9d\xee\x3e\x3d\x26\x03\xa6\xf0\xee\x1f\x27\xb0\x46\x44\x0d\x01\x16\xc5\xb6\xaa\xd1\xf9\x1a\x17\x3f\xc8\x96\x51\x47\x2d\x5f\x2f\xe3\x73\xfd\x65\x9c\x2b\x9f\xf6\xbd\x7c\x5d\xa3\x93\xd3\xfc\xf8\x1c\xdf\x7b\x3d\xef\xfb\x8f\x31\xba\x8e\x63\x1c\x9e\xf2\x77\xfa\x23\xad\xe7\xf3\x09\x3e\x77\x3f\xc4\xf0\x39\x7f\x7b\x58\xae\xd8\x0d\x5b\x4c\x8c\xa3\x5b\x5d\x3a\x39\xcb\x2e\x6e\x11\x42\xab\xd1\xf2\x6b\x91\x96\xcf\x0a\x19\x35\xfb\xa6\x10\xaf\x5a\xa0\x65\x85\x5c\x63\x29\x80\x0b\x76\x45\xf0\x3f\x05\xf9\x3f\x03\xff\x5f\xd1\xfb\xf7\xe5\x12\x1d\xef\xa9\x47\x73\xa3\x0e\xdc\x2c\x2c\x5f\x73\x31\xce\x0a\xc9\x11\x3d\x5b\xcb\xca\x4e\x2b\x46\x77\x1a\x18\xf8\x7f\xf0\xcd\x9f\x9e\x43\x97\xcd\xaf\x2d\x9a\xc6\xf9\x24\x52\xda\xb7\x21\xda\x42\x32\x72\x0e\x7f\xc6\xe9\xa0\x64\x0e\x83\xd3\xc1\x9f\x91\x3a\xe0\x7c\x7d\xd9\xcb\x59\x1a\xdb\xd8\x71\x49\x27\xe0\x12\x8a\x2d\x81\x7a\x62\xd6\xf0\xa4\x66\xdd\x2c\x9a\x83\x63\xb1\xda\x8b\x43\xa9\x33\xe0\x71\x99\xf1\x5e\xbe\xbe\xd8\x87\x83\xbb\x8a\xca\xee\xff\x95\x57\xbe\x59\x62\xfd\xf9\xe3\xa7\x4f\x9b\x70\x1e\xd1\x2d\xfa\x21\x80\xdb\x2a\x7f\xf2\x9a\x1a\x72\xa1\x1e\xfe\x42\xd9\x2d\x72\x49\x2e\x54\xb0\x2f\x17\x4b\xed\x4d\xcb\x1a\x58\x5b\x57\x1f\xb5\x3c\xbb\x52\xfe\xda\x73\x22\xaf\xc4\x90\xd7\x1f\xb3\xfb\xf9\xe7\x50\x66\x5e\xbb\x6e\xb3\x7b\xbf\xb4\xee\xff\xda\x53\x72\x96\xcd\x37\x5e\x55\x09\x97\x47\x6a\xe0\x72\xa6\xfc\x2d\x8f\x75\xbe\x9d\xd6\x64\x3f\xd9\x3f\xbf\xa0\x7b\x00\xa0\xa1\xf8\x7e\x17\x65\xfa\xf2\x68\x29\x2c\xb7\xb1\x05\x5e\x53\xa1\x63\x57\x00\x9a\xb2\x8c\xda\x69\xcb\x5a\x00\x00\x7a\x8f\x96\x63\x61\x84\x55\x0b\xbe\xb7\x52\x70\x4b\xb4\xb0\x2f\x16\x3b\xab\xbc\x3c\xc3\x41\x35\xa7\xcd\x4a\xa3\x9f\x22\xa4\xff\xb5\xea\xcb\x0f\x69\x2f\x5f\xee\x3f\x4f\x8f\x39\x5d\x89\x6e\x41\x34\xc0\x09\x62\x65\xc0\x84\xae\xe3\x2a\x02\x14\xe0\xf1\x8a\x5b\x8a\x56\x24\x63\x03\xf1\x51\x59\x40\x3c\xb3\x01\x8b\x9e\x62\xa7\x2a\x10\xfd\x60\x0d\x01\x07\x45\x9e\x41\x7b\xf4\x4a\xa9\xe2\x17\x36\x7b\x60\xce\xc0\xec\x71\x04\x62\x60\xf0\x51\x00\xde\x14\x19\x55\x09\x70\xe8\x00\xe7\x96\xb9\xa7\x0c\xb0\x60\xa1\x52\x7e\x00\x8a\xd1\xb0\x0e\x08\x1c\xff\x38\x02\xc3\x76\xd1\x1c\xa4\x91\xd4\x70\x15\x92\x68\x37\x89\x7a\xee\xd4\xc6\xd8\x72\x5e\x8e\xdf\xae\x72\x5e\xe2\x09\xd0\x0e\x2a\x8c\x8c\x06\x94\xfe\x10\x67\x20\xbe\x2b\x35\xbb\x8f\xf1\xb6\x95\xf6\xc7\xc7\x65\xff\xed\xed\x85\x22\x64\xa2\x6d\x1c\xe1\x3c\x85\xe3\x04\x66\x58\x6b\xe0\x1b\x2b\x99\x3e\xd0\x7a\xf1\x4d\x4c\x76\x24\x07\x29\x02\xc7\x17\xe7\x36\xe3\x11\x6a\xbc\xe8\xd7\xe3\xac\xf5\x3a\xbb\xd1\xb8\xb3\xe1\x8b\xfe\xdd\xcf\x4c\xfa\x9e\x30\xd2\x00\xff\xd3\x1d\x07\x99\x87\xad\x3a\x51\x27\x93\x41\x41\x81\x0c\x62\x06\x68\x39\xc0\x74\x33\x84\xe5\x82\x03\x80\x7d\x67\x06\x26\x8a\x9c\x09\xbc\x7a\x32\xc6\xab\xea\x7c\x4b\x8b\xdc\xd7\xb3\x6a\x1f\xad\x29\xd8\x77\x8e\x27\x48\x43\xa0\xbe\x2b\x61\x21\x28\x06\x58\x8d\x40\xaf\xdc\x53\x69\x33\xd8\xd9\xe4\xef\x8a\xdf\xf5\x67\x66\x57\xc2\x80\x9d\x8a\xec\x70\x3f\x53\x77\x92\x65\x86\x84\x6a\xa0\x02\x91\xc0\x13\xe5\x2b\x16\x9b\x41\x18\xc9\x0e\x91\xc8\xf9\x56\x76\x32\xb5\xe1\xea\xd1\x59\xae\x88\x3c\x60\xfb\xa9\x46\xc8\x54\xf5\x7d\x12\x3b\x5c\x86\x65\x64\xab\x03\xbd\x8c\x15\x5b\x01\xf9\xb1\x00\x41\x4b\xd6\x58\x43\x82\x1b\x08\xf3\x0c\x3a\xd4\x45\xe5\x6f\x07\x5d\x59\x71\x11\x14\x1a\xd5\x35\x56\x6e\x89\xaa\xb9\x06\xc5\x65\x72\x4c\x6d\xa6\xd0\xc0\x4f\x66\xa4\x32\x0b\xb5\x0e\x86\x40\x90\x02\x55\x17\x33\xa0\xe9\xa3\xfc\xd5\x00\x70\x16\x34\xc9\x29\xc8\x2c\x70\xd2\xfb\xc4\x84\xab\x62\x9f\x41\x55\x17\x64\xd1\xc9\x60\x36\xe4\x47\x00\x8c\xb3\x82\x62\x7b\xc6\x76\x42\xc5\x14\xaa\xf8\x04\xdd\xd7\x87\x87\xe9\xfd\xfd\x97\x37\xef\xa6\x87\xaf\x97\x18\x1d\x89\xb6\x48\x1b\x27\xcc\xad\x22\xfb\x45\x88\xa8\x46\xba\xd5\x06\x51\x8b\x7e\x21\x2d\xbd\x5c\x3e\xfd\x1c\xa3\xdc\xdb\xf9\x48\xea\x33\x8f\xd3\xc6\xea\x00\x1f\xeb\xc8\x02\x1c\xf8\x5a\x36\x7f\x90\xfa\x67\xca\xf2\xe5\xd4\x3f\x5c\x7d\x39\x59\x51\x1f\x78\x21\x59\x31\xec\x2e\x6e\xa2\x62\x17\xed\x4b\xfd\x91\x1c\x42\x1d\x82\x87\xcf\xf7\x9f\x2e\x8e\xc0\x16\x7c\xe3\xd4\x31\xdf\xc8\x95\x20\x3b\x47\xcc\x9a\x99\xb6\xba\x49\xb5\x23\x75\x97\x54\xc1\xaf\x2b\x42\x66\xfa\xe4\xb9\x27\x25\x93\x02\x84\x13\x60\xc1\x00\x30\x0c\xd7\x79\x56\xa1\x9c\x4f\x00\x8a\x9b\x8c\xf4\x52\xc9\xe5\x38\xc9\xb5\x72\x29\x35\x27\x9a\x61\x73\xb1\x6b\x8e\x68\x2d\x6d\x5f\xcb\x09\x9c\xd0\xa3\x01\x46\xc6\xe3\x2f\x98\x0f\xbb\x83\x6f\xd2\x8e\x5c\x5c\xa4\x3c\x27\x6c\x22\xb2\xe0\x94\x79\x46\xa4\x61\xd2\x98\x41\xe8\xd6\x3d\x80\xf1\x4a\xd8\xb5\x83\xbc\x7d\xb6\xb7\x17\x61\x8a\x9d\x88\x8a\xac\x23\xac\xfb\x14\x14\x8d\x6d\xf4\xe4\x0b\x27\xc8\xf5\xf9\x91\x53\xba\xf2\x23\x1c\xce\x9d\xe7\x9c\x80\x7e\xac\x34\xa5\x8b\xc8\xad\x1a\xc0\xec\x87\x34\x51\x02\x27\xc9\xf7\xdd\x6d\x20\xda\xcf\x77\x9f\xde\x5f\x9c\x49\xd7\x68\x5f\x6e\x13\x3a\x4f\x77\x9f\xaf\xc8\x86\x6d\xa4\xec\xc9\xfb\x7d\xfd\xf3\xe3\x05\x6d\xb2\xad\xda\xa4\x28\x04\xa9\x88\x9c\xaf\x06\x6f\x08\x06\x7a\xea\x70\x78\x8a\xec\x4f\x7a\x50\x93\x32\xdc\xa3\x10\xa0\x39\xce\x2e\x29\xa1\x57\x6c\x2e\xd2\xab\x3c\x73\x76\x0d\xdf\x38\x9f\x16\x45\x67\x8b\x0d\xd8\x81\x2d\x18\x3b\x2c\xe9\x1e\xa4\x00\x4f\xe9\x78\x8c\x43\x9c\x82\x33\xe6\x26\x36\x71\x64\x31\x09\x53\x77\x69\x01\xff\x1a\x81\xaa\x05\x0a\x98\x4e\x7e\x4b\x64\x7c\xa9\xa9\xb1\x7b\x91\xad\x21\x3b\xf4\x0f\x3e\xe8\x45\xcf\x49\x61\xd8\x4e\xc0\xc9\x94\x8d\x4c\xe9\xd2\x0c\x55\x5b\xb4\x0b\x0e\x49\xf9\x62\x17\x8f\x1f\x5d\xa6\x71\xe4\x71\x08\xd2\x14\x3d\x61\x00\x70\xcb\x75\xd8\xb9\x92\x02\x56\x8d\xc3\xe5\xe4\x84\x93\xeb\x8e\x77\x5b\x9f\x70\x7c\xea\xb1\x29\xa3\x79\xff\x12\xde\xd4\x1f\x32\x47\x3e\x7c\xb9\x10\x8a\xa6\x7e\xb6\x2e\x62\xa8\x73\x33\xae\x17\xe3\xad\xf5\xeb\x54\x04\xcf\xc3\x82\x44\xee\x06\x2c\xed\x36\x20\x93\x74\x96\xfb\x93\xa9\xed\x4f\xa7\xbc\x3f\x59\x0b\xb2\x92\x60\x09\x8c\xf5\x62\x06\x86\x57\x7f\x51\x83\xed\x6f\x8f\xc3\xda\x9a\x23\x74\x13\x67\x2b\x71\xb1\x95\x39\x56\xea\x58\xbb\x2f\x5f\x20\xbb\x1f\x9d\xb8\xff\xfe\x0b\x64\x77\xb2\x42\xfe\xbb\x40\x8e\x15\x38\xfb\xcd\xf2\xb8\x3b\x2e\x8f\xcc\x5b\x86\xf7\x53\x7f\xf6\xc5\x4a\xbc\xe5\xdc\xcf\x79\xb1\x92\xee\x67\x44\xfb\x5f\x3a\x71\x7f\x78\x85\xfc\x2d\xa2\xfd\xaf\x9b\xb8\xbb\x7f\xb7\x99\xfb\xc7\xdd\x9f\xf7\x9f\x37\x68\xe1\x44\xb7\xea\x83\x5a\xc4\x7c\x36\x8f\xfc\x85\x0a\xb1\x2b\x55\x65\x5a\x5b\x72\xb9\x3a\xec\x46\x65\x99\x85\x82\xb6\x05\x62\xd7\xca\xca\xe4\x82\x47\xb5\x63\xc8\xb9\xd8\x94\x94\xd9\x7c\x7b\x3e\xc1\xe9\xee\x87\x19\x41\x41\x8d\x94\xc2\x5f\x4d\x3c\xda\x0d\x91\x4d\x3a\x11\x5e\x3d\x90\x53\x14\x5e\xe4\x1f\xfc\x39\xa3\x6e\x4a\xbe\x8d\x00\x05\xdd\x7b\x16\x43\x86\xd4\xfa\x68\xfa\xbd\x55\x61\x28\x5f\x83\x01\x9c\xef\x16\x3f\x20\xcf\x1f\x41\x9f\x03\xf6\x4e\x4f\x1e\x4f\x59\xc6\x83\x6f\x4e\xbe\x7f\xde\xff\xdf\x25\xfe\x5f\xa2\x6d\xe5\xd3\x71\xf6\x81\xff\xb7\x1c\x2b\xa4\xcb\xf8\x5f\x89\xbf\xd6\xb8\x3f\x15\xab\xe0\x2e\xfa\xdf\xfe\x24\x4f\xc6\x53\xf9\xfe\x3a\x13\xbb\xc2\xe9\xd2\x8d\xb4\x8e\xf1\xea\x9d\x50\x85\x78\x7a\x2b\x69\x53\x6b\xe1\xe7\xdb\xa4\xf3\xf1\xd2\xdb\xed\xf6\xbe\x95\x9b\xad\x92\x9f\xcf\x6e\x56\x4b\xbb\xf6\x82\x2f\x6b\x15\x76\x99\x5f\xf2\x7a\x81\xd3\x0f\x35\x69\xb7\xb9\x55\xeb\xe5\x17\xb5\x09\xdc\x07\xbf\xa2\x9b\x94\x2d\xf9\x57\x4c\x4d\xdd\x6f\xf5\xed\x76\xbf\x60\x46\xfd\x9a\x8e\x42\x59\xb9\xdc\x69\xe4\xd8\x3e\x7f\xc5\x10\xf1\x81\x53\xb8\x79\xfb\xda\x51\x40\x78\x68\x5a\x19\x5a\x12\xca\xef\x76\x7b\x39\x1c\x19\x96\x81\xd3\x5a\x94\x77\x5d\x11\xd1\xcb\x6f\xc5\xfe\xac\x8e\xf0\x72\xe8\x14\x4f\xbc\x81\x57\x7e\xdb\x56\x9a\xee\xfe\xb8\xe8\x8f\xd8\xa6\x9d\x9c\x44\x6f\xd4\xa3\x4c\x87\x02\x36\xd1\xd2\x95\xf0\x38\x86\x22\x07\xb3\x6f\xea\xe3\x49\xd9\x21\xf9\x2d\x04\x07\x26\xdb\x96\x5c\x55\x2d\xa7\x36\x70\x05\xcf\x9e\x2a\xde\x39\x05\x30\xe9\xd7\x83\xcf\xbd\xcf\x2c\x4a\x24\x45\x97\xc0\xda\x17\xe7\x9c\xa5\xdf\xb5\x94\x0c\x7b\x09\x0c\xab\xa5\xc2\x5c\x5b\x9a\xba\xf2\xfb\xab\x3c\x21\x20\x94\xe6\x04\x8e\x62\x8d\xee\x30\xcf\xc4\x20\x8c\xeb\xd1\x75\xd6\x40\xef\x40\x9a\x00\xd5\x02\xfa\xa9\xa4\xc5\x2b\x8f\x5c\x2a\xb2\x85\x97\x73\xf2\x1d\x03\xec\xdc\x59\x36\xc7\x63\xbc\x4e\x9c\xaf\xe4\x7d\x4e\x6f\x93\x8a\xf1\xe6\x95\xf4\xf2\x90\xb7\xce\x2c\x24\x64\x94\x88\x76\x76\x6d\x2b\x18\x4a\x8d\x39\xbd\x3a\xdf\x65\xcf\x6b\xe6\x6e\x8b\x05\x85\xbf\x65\xf6\xad\x0d\x0f\x5b\xcc\x13\x28\xfd\xd2\xec\x65\xa9\xcb\x2b\x74\x90\x1e\x74\x72\x2c\x8a\x3b\x28\xf4\x67\xb8\xc0\xf1\x46\xd0\xcd\x92\x7a\x85\x54\x4d\xe3\x1d\xe2\x6b\xd2\x0d\xb8\x7e\xac\x9a\xc8\xae\x81\xab\x81\x94\xaa\x21\x97\x43\x45\x54\x3b\x66\x17\xc9\x65\x40\xd2\x33\x39\x50\x0c\x27\x45\x4d\x4e\x2e\xcb\x66\xcc\xc3\x74\xa6\x0c\x18\x7e\x52\x42\xa1\x00\x26\xa1\x05\x9f\xad\xcc\x6a\xed\x82\xee\x59\xce\x61\x6c\xd7\x60\x00\xe3\x99\x01\x3a\x1b\xc9\x51\x9d\xe5\xdf\xe2\x64\x1f\x67\x39\xf6\x2c\xa7\x39\x9f\x9f\x31\xed\xdf\xed\xef\xdf\xfd\xf3\xfe\xcb\xfd\x76\x43\xdf\xa6\xcb\x9c\x70\x88\xcb\xdb\x46\x85\x22\xd0\x8c\x1e\x74\x7f\x03\x90\x7e\x3d\x78\x6a\x79\xe6\x90\x5d\x2f\x4e\x93\x78\xc3\x77\x5c\xd3\x73\x3a\x50\x07\xd5\x22\x2b\x02\x38\x2e\x61\x99\x6f\xad\xcf\x4c\xc0\x61\xb6\x6b\xda\xf7\xe3\x22\x43\x12\x1d\x2b\x2d\xc8\x78\x52\x25\x00\x1e\xc8\xdb\x22\x30\xe1\x28\xcf\x3e\x3b\x44\xff\x1c\x55\xe3\x60\xc3\x01\x8a\xa2\x07\x2b\x1b\x29\xd7\x19\x5c\x19\xa2\xcf\x17\x0b\xd9\xc4\xec\xd4\x05\x22\x2a\x79\x5d\x8f\x64\x55\x24\x27\x73\x80\x75\x9d\xca\x18\x1d\x3c\xb3\xa8\xa7\xb3\x4e\x1b\x52\x9f\x07\x8b\x95\x57\x35\x8a\x36\x13\x48\x91\x64\xda\x52\x96\xd7\x6b\x73\xd2\x98\x6d\x47\xc0\xf5\xd1\x92\xd4\x00\x03\xb5\x83\xf4\xc3\x05\x71\x92\x10\xdf\xad\xcd\x35\x51\xa1\x0b\x22\x3b\x3e\x81\xb2\xde\xf5\xf0\x73\x4b\xfa\xc6\x8a\xde\xfd\xa7\x2e\xe9\xeb\x2b\x7a\xf7\x6f\xbc\xa4\x97\xfb\x2f\x7f\x7e\xfc\xb4\xc1\xc1\x23\xde\x26\x32\x1d\xa3\x6e\xb9\x65\x97\xf3\xbf\x5e\xb5\xd1\xa8\xed\x1a\x8b\xa3\x5c\xc7\x90\xd6\x82\xed\xa7\x21\xa4\x51\x95\xbd\x22\x53\xef\x96\x67\x90\xb5\x3d\xbc\xdf\x84\x17\x78\x5b\xc8\x7b\x82\x6b\x44\xd5\x51\xac\xff\x92\xe5\xd6\x27\x3d\xca\x41\x4c\xc9\x90\x26\x1f\xc1\xf7\xc4\xdd\x58\xbb\xc1\xbb\xaf\x39\x80\xc7\x34\x73\x44\xf8\xc4\x72\x54\x7a\xf0\xa4\xbf\x9a\x24\x45\x5e\x49\x7a\x95\x77\x93\xdc\x0a\x77\x02\x39\x23\x29\x4d\xf8\x48\x40\x97\x7b\xc0\xd4\xac\x60\x89\x4c\xc6\xea\x80\x7b\xa8\xf4\xd4\x10\x5b\x2b\xff\xe2\xd3\xf1\xc9\x2c\xa0\x37\x77\xd3\x76\x05\x3e\x45\xd6\x92\x72\x3a\xf8\xaa\x41\x69\x56\xd9\x98\xbb\x92\xb1\x67\xf5\xd1\x67\xe4\x04\x0c\x97\xe3\xf3\xb2\x68\xb8\x8b\xd8\xa8\xb2\x0c\x66\x6c\x45\xd5\xe9\x9d\x0f\xbe\x74\xe9\x9e\x8a\x90\xfe\xec\xed\x06\xe7\x35\x1f\xdf\xcf\x72\x94\x72\x53\xf9\x4c\x31\xaa\x4f\x4c\xf3\x25\xe0\xd3\x97\x19\x94\x17\xcb\x1e\x15\x79\x3f\x29\xc1\x67\x40\x04\xe0\x34\x51\x09\x72\xb6\x3b\xda\x69\x50\x01\x83\x1a\xd3\x9c\xa2\x4b\x01\xdd\x5d\x5c\x2e\x19\x92\x1d\x69\x25\x15\xa9\xc9\x04\x73\x81\x8b\xec\x27\x59\xe1\xe3\x32\xfd\x7d\x7d\xc5\x85\xe7\x44\x84\xb7\xc8\x88\xa6\x32\xcd\xd8\xa4\x45\x79\xc7\x41\x0e\xfd\x09\x02\xaa\xbb\x2f\x6f\xf6\x77\xd3\x87\x37\xf7\x7f\x7e\x5e\x36\x99\x62\x7c\x2b\xed\x88\xa8\x15\x97\x6b\x9f\x38\x57\xc7\x39\x4c\x3e\xe6\xe2\x32\x4f\x88\x1d\xcb\x9f\xc1\x01\x83\x27\x77\x17\x99\xc5\x6e\x8c\x53\xc6\xc6\x33\x45\x6c\xa5\xa5\x4d\xbe\xc8\x2e\x96\x27\x4f\xec\x0a\x6c\xc3\xd8\x5c\x03\x91\x41\x41\x70\x3e\x4d\xad\xc8\x7b\x84\x39\xeb\xb6\x58\x94\x98\xc6\x78\x61\x9b\xda\x2a\x6a\xaa\x38\xe2\xc9\xa7\x24\x92\xb5\xe8\x81\xe7\x58\x66\x5d\xa1\x3c\x32\x95\x86\xca\x14\x93\x23\xa8\x56\x05\x99\x30\xf2\x9c\x1c\xa4\xd9\xb2\x7d\xe7\x34\x2b\x5c\x10\xa6\x42\x16\x79\x91\x13\xe2\xed\xbb\x29\x07\x76\x35\x4e\xcc\xd9\xa5\x2c\x2a\xa5\x4b\x24\x76\x54\xa2\x99\x45\x1d\x90\xe7\x26\xc2\xef\x3e\xe5\x8c\xf3\x7d\x8d\x73\x12\x2b\xc9\xe5\xa4\x61\xf7\x05\xe9\x08\x72\xe7\xdb\x45\x71\x0f\xef\xee\x96\x8f\x0f\x9f\xde\xdc\x7d\xf9\xf2\xf0\x3f\x9b\x01\xda\x26\xae\x9c\xb0\x84\xa5\x40\xa2\xb1\xd6\xc9\x17\x7d\x75\xf0\xb9\xd4\xa1\xdf\xc8\xa7\xe8\xa6\x50\x60\x1c\x83\x06\x2f\x1b\xab\x09\x1b\x8d\x97\xa8\x4f\xfd\x55\x3e\xe4\x5a\x2c\xb1\x81\xd5\x97\x07\x49\x1b\xd7\x0a\x1d\xf0\x0a\x26\x97\x78\x91\x09\x1b\xa6\x41\x40\x2d\x52\xb5\x3a\xee\xae\xce\x98\xfa\x1a\x76\x40\xa4\x9f\xb4\xff\x47\x6f\x94\x61\x2c\xde\xde\xf9\xbe\x6c\x2b\x04\x79\x9b\x3b\x72\xa2\x47\x60\x72\x96\x7d\xee\xf9\x90\x7b\x56\x6f\x5d\x0c\x34\xa1\xb8\xb9\xe7\xbd\x97\x5f\x3c\x7e\xc2\x8e\x8e\x74\xc1\xa3\x3f\xf8\xd1\x9e\xfe\x08\x69\xec\xd1\xaf\xe7\xae\xe7\xb1\xe3\x03\x7f\xaa\x5d\xd4\x66\x5b\xd9\x80\x9d\xad\x8a\xee\x86\xdf\x75\x7f\x86\xa6\x76\xfc\xfa\xd4\x1f\x3d\x98\x2d\x76\x0a\xa4\xd6\x32\x4d\x9c\x8a\xe3\x54\x65\xdf\x50\x0e\x5c\xf5\x6e\xcf\x88\x2d\x98\xbf\x7b\x30\xd9\x32\x28\x96\x45\x2d\x6f\x99\xce\x40\xd2\xc6\x8d\x9f\xd4\x4b\xde\x7c\x78\xf8\xb2\xa9\x3e\xe2\x6d\x52\xc6\x11\x65\x84\x5b\x73\x17\x73\x63\x96\x47\x09\x31\xcb\x55\x3a\x43\xa3\x0f\x63\xec\x09\x3f\x73\x9b\xce\x0a\x7a\xf9\x93\xb7\x51\x9e\x16\x2b\xfd\x03\xb3\xa4\x58\x4c\x70\xb1\x54\x64\x2e\xbe\xca\xb2\xd5\xc8\x85\xd2\xe1\x0c\xc6\x4e\xb1\x1c\xaa\x26\x9e\x73\x88\x60\xae\x56\x4f\x3a\x16\x6f\x81\x62\x52\x69\xf1\x49\x19\x8f\x42\x90\x2d\x40\x7d\x2a\xd9\x8d\xdb\x2e\xe3\x49\xcf\xcd\xd3\xd6\xca\x33\x2e\x0e\xcd\xab\x01\x29\xb5\x87\x86\xa4\xa4\x04\xfa\x49\xfb\x4e\x76\x3a\x67\x77\x7e\x8a\x3a\xee\xfa\x6b\x1f\x7c\xea\x75\x37\xe7\x84\x0a\x8c\x9c\x5c\xae\xb3\x98\x26\x15\x59\x4d\x9a\x2f\x89\xdd\x35\xd2\x22\x1b\x87\xfc\x8d\x0d\x3c\x13\x3a\x57\xfe\x16\xa9\xd1\x49\x24\xff\x8f\xb7\xf0\x36\xf1\xe9\xa7\xe9\xe3\xb6\x84\x8e\xb7\x99\x40\x47\x39\x93\x62\x77\x5c\x44\xc3\x90\x07\xa0\x26\x59\xb6\xe6\xbe\x06\xa1\xc0\xd0\x2c\x3a\x46\xb0\x60\x16\xc8\x71\xe5\x6c\x30\xd3\x3c\xb9\x38\xbf\xbf\x2e\xa1\xa9\x74\x1a\x90\xb0\x8f\xe4\xcf\x72\x2a\x3e\x0c\xba\xf6\x44\x4e\x2c\xa7\xab\x58\xa1\xbe\x53\xbb\x2c\xc7\x22\x5f\xb0\x5c\x96\xa3\xc4\x41\x7e\xe0\x46\x32\xbc\xa6\x92\xda\xc8\x0a\x46\x86\x6e\x53\x5c\xa9\xc9\x13\x0a\x16\x92\x18\xcc\x32\xb1\xe3\x98\xe1\x71\x65\x70\xe5\x90\x5c\xcb\x93\x8f\x51\x8c\x67\xd1\x94\x08\x49\xba\x49\xcc\xdd\x89\x63\x77\xd4\x26\xd6\x7a\xc4\x34\xb3\xa6\x82\x62\xe9\x89\x49\x2f\x8b\xaf\xbc\xca\x93\x3c\x47\x1e\xc3\xb2\x18\x81\xa3\x58\x4f\x57\xf2\x04\x1a\x45\xae\x79\xa2\xe6\x38\x76\xb1\x9b\xe5\x41\x32\x64\x89\xa7\x88\x5c\xd2\x58\xe6\x96\xc4\x2c\x76\xf2\xc1\x20\x10\x0a\x62\xf9\x86\x94\x26\xcf\x50\xc2\xda\x6e\x42\x69\xa3\xb4\xc5\xeb\x93\x54\x48\xcc\xa2\xf7\x8d\x4c\xbe\x7a\xfa\xe2\x86\xe5\xa7\xc2\xa3\x9e\xa5\x79\x4e\x20\x77\xe4\x9a\x26\x4b\x53\x0c\xb3\x57\x8b\x5e\xd6\x68\x62\xe9\x95\xe2\xa4\x61\xbe\x25\x27\xfa\x50\x4b\x4e\x33\x94\xa5\x9b\x1b\x90\xbe\xd6\x77\x6f\xd1\xb5\x28\xdf\xb8\x16\x67\xed\x5d\x44\xa4\x5b\x9e\xa4\x73\xbd\xf4\x2e\x23\xad\x16\xfc\xac\xb9\xac\xa6\xec\xc5\x59\xb5\x99\x0d\xbb\x4b\xd3\xe1\xd2\x6c\x90\xb6\x51\x0e\xbf\x68\xc2\x52\x66\xb1\x61\xc5\x06\xfb\xcb\x96\xd8\xed\x22\xbe\xfb\xaf\xa2\x88\x6d\xa4\xc2\x16\x52\xe2\xb8\xb5\xd5\x90\x1c\x37\x11\xd4\x9a\x8b\x82\x18\x05\x1f\x77\x11\xd0\x9c\xa5\xb5\xca\x18\xf4\x8a\x8b\x9c\xc1\xed\x24\xcc\xc1\xb6\xb3\x10\xef\xe5\x4b\x52\x7e\x68\xb9\x7a\xd1\x9b\x61\xc3\x41\x68\x0d\x82\x37\xad\xd6\x72\x20\xa5\x2d\x56\xef\x7e\xce\xaa\x70\x2e\x3e\xc3\x05\x96\xa0\xbf\x0d\x26\x3b\x24\xd0\xa3\x2b\x0b\xd4\xb2\x82\x84\x03\x1c\x61\xba\x92\x01\x11\x47\xad\xcb\x6e\xfa\x90\xd1\x7e\xad\xf4\x80\x71\x8d\x9c\x37\xad\x13\x89\xf5\x55\x3e\x00\x5a\xa2\x45\x57\xc4\x36\x47\xe2\x43\x12\xc3\x56\x54\xf7\xdc\x1d\x57\x59\x67\xb9\x2c\xb2\x89\x15\x23\x0d\x86\x5f\x0f\xc9\x8f\x41\x5a\x10\x79\xf6\x45\x15\xd5\x20\x0b\xa4\x63\x7d\xc0\xa6\x22\x50\x34\x52\x56\x43\x0b\xce\x39\x38\x7e\x51\x8c\x82\x26\xb9\x36\x81\x7e\x96\x58\x4f\x82\xfd\x0c\x1d\x37\x83\x20\x98\xdb\x4c\x25\x38\x86\x7b\x43\xb6\xa5\x62\xa5\x7a\xe8\x18\x5a\x10\xd1\x6e\x62\x9f\x6b\x35\x8c\x6c\x48\x64\x25\x49\x37\x67\xcc\x1b\xae\x7d\x33\x5b\x36\x68\x16\x27\x60\x43\x29\x18\xa4\xe6\xf5\x9a\xd5\xc7\xe0\x1d\x4f\x14\x35\x2a\xac\xe7\x4b\x0a\x21\x63\xbb\x5c\x47\x2b\x06\xc0\xc5\x12\x5b\xd5\xa8\x0d\x59\xf9\x1a\xf1\xf7\x5e\x97\xeb\xa5\x46\x74\x60\x31\x3f\x6a\xc5\x0f\x90\xf8\xdd\xff\xef\xbb\xe9\xee\xcf\xbb\x8b\x4b\x74\x83\x39\x71\x82\x71\x44\x8a\x3d\x30\x94\xfa\x97\xb4\x5d\x2f\x79\x5e\xd3\x5f\xe7\xa4\xbd\x04\x2f\xb1\xaf\xa5\x01\x15\x57\x1e\xc7\xf0\x4f\xe8\x03\x5f\x5d\x7a\xe4\x2b\x7d\x28\xce\x4b\xea\x66\xb6\xeb\xe5\xd9\x15\xdf\x2e\x09\x51\x84\x7e\x02\x37\xa9\x6c\xa4\x7d\x51\xaf\xfb\x13\xdd\xf7\xf5\xdb\xe7\xfb\x2f\x5f\xdf\x7d\xf9\xf8\x79\x13\x71\xe4\xb7\x23\x03\xad\xf5\xea\xa8\xd4\x83\xa7\x52\x65\xe1\x37\xb5\xee\x59\x8c\x7e\x16\xeb\x6f\xf6\xcd\xc1\x35\xee\x98\xf6\x3e\x2a\xf0\x2f\x3c\x75\xce\x43\x04\x29\xea\xe4\x22\x5f\x16\x98\xee\x41\x79\x57\x61\x2b\xcb\xfe\x97\xb1\xae\x83\xf4\x40\x3b\xc8\x63\x14\x96\x57\x6c\x48\x9a\x40\xb9\xcf\x95\xf7\x9e\x62\x3d\x50\x69\x7b\xae\x65\xa2\x08\xdf\x47\x9b\x45\x70\x60\x0f\x4a\x3c\x37\xf8\x73\xb0\xcd\xed\xe3\x1c\x1d\xfe\x60\x9a\xc4\x68\xe7\x09\xa5\x39\xdc\xf6\x9c\xf1\x32\xc0\xfb\xcd\x13\x02\xa1\x9e\x4b\x9d\xb0\x61\x72\x2f\x7b\x0a\xfd\xfb\xee\x35\xe5\x98\x5c\x13\xb3\x88\x83\xd8\xc1\x94\x26\x2f\x9b\xff\x2c\xcf\x13\x05\xdd\x25\x30\xbe\xab\x52\x4b\x75\x29\xd9\xb5\x02\x68\x4d\x57\xf0\x6f\x46\xa2\x7b\x76\x39\x89\x82\x0e\x6b\x07\x7a\xbe\x28\xf5\x85\x55\x41\x36\x8f\xe5\xec\x33\x34\x22\xf5\x82\x29\x2e\xbc\xbc\x08\x94\x13\xe9\xf1\x90\x5d\x07\xb6\x77\xac\xae\x44\x57\xb0\xe5\x83\x1b\xbb\xb9\x92\x67\x22\x48\xaf\xda\x4c\xd8\x2b\x63\x7a\x53\x8b\x00\x3b\x67\x5a\xd3\xc6\x0a\x8f\xbd\xa1\x69\xd5\x84\x96\xd8\x89\x5a\x80\xa4\x6d\x2d\xb6\x1c\x0e\x17\xcc\xd3\x12\xf7\x1c\xf9\x00\x4a\xe5\xa7\x28\xa2\xdf\x5e\x99\x50\xef\xfe\x3b\xa1\x60\x8d\x84\xd3\x09\x95\x30\xa1\x22\xe4\x46\xfc\xdd\x13\x2a\x3c\x77\x42\x95\x62\x9c\xfe\x9e\xd4\x9b\xa6\xba\xf3\xe2\x3b\xec\x55\x6d\x8a\x18\xb9\x25\x2e\x50\x30\x6a\xdc\x3d\x77\x02\xbd\xe1\x16\x37\x73\x67\x9b\xfe\x70\x92\x50\x08\x66\xad\x06\x45\x1e\x3b\x5f\x15\x9d\x5f\xd5\xfa\x96\xf6\x15\xa6\x79\x0f\x5d\xd4\x66\x2b\x37\x49\xce\xec\xea\x93\x19\x9e\x5f\xe5\xc9\x2b\x3d\x49\xe0\xa4\xd5\x78\x62\x66\xcb\x37\x49\xef\x8a\x2f\xcd\xa4\x75\x0c\x3f\x30\xea\xec\x32\xfa\x9b\xb2\x13\x4d\x1b\x21\x5b\x02\x23\xb5\x55\x2f\x4f\x4a\x2d\xc2\x69\x8e\xcd\x25\xd1\xb9\x5d\x42\xbb\x66\xdc\x4e\x6d\x7c\xdc\x0e\x77\xf3\x72\xbb\x9b\x5d\xf4\xf9\xdb\xf7\xef\xd3\xfd\x9b\xcf\x1f\xef\x37\x4c\x17\xc4\xb7\xb0\x25\x34\x88\xad\xd5\xd7\x4d\xec\x2c\x1d\xc3\x88\x8a\x40\x85\xee\x59\x4b\x2a\x2b\x2a\x08\x11\x7c\x16\x93\xbc\x19\xe6\x8f\x1c\x54\xc2\x0f\xb3\xd7\x49\xa2\x8c\xf5\xa4\x5b\xa9\xd8\x6c\x05\xca\xd9\x02\x7f\x1f\x89\x1a\xb1\x3a\x10\x45\x5b\x9b\xe1\xc4\x15\x6d\xbc\xea\x0c\x82\xd3\xd1\x74\x57\x28\xa7\xbd\xc1\x6d\x5e\xb4\xb4\x33\x44\x2d\x1a\x16\xab\xb0\x29\xc4\x59\xac\xba\x03\x56\x5a\x62\x53\x70\x22\xf9\xb4\x5d\x4f\x5a\x3e\x07\x57\x3b\xb4\x62\xbc\x98\xa8\xa6\x31\x63\x77\x84\x39\x05\xbb\x24\xea\x36\x8b\xf7\x53\x1d\x0f\x06\x5a\x44\x2d\x52\x8b\x4b\x8c\x1a\xb8\x96\xbb\x6b\xe7\x44\xbc\x93\x48\xc9\xd9\x10\xa4\xa1\x26\x76\xad\xe9\xd1\x9c\x00\xf3\xb0\x76\xd5\x8d\x93\xac\x46\x31\x4f\x58\x8d\x56\x97\x4c\xbf\x16\x29\x15\x1d\x8b\x6c\x93\x8e\x71\x34\x7b\x55\x5d\x1d\x29\x36\x10\x3b\xaf\xdd\xec\x44\xdc\x2d\xd2\x67\x79\x61\xb2\xbf\x67\xa4\x48\x72\x72\xf2\x04\xbf\xe2\x93\x50\x75\x31\xcf\x49\x26\x98\x4b\xc5\xb5\x0e\x35\x0b\x59\x95\x2e\x63\xc2\xe2\x4d\x72\xb4\x03\xbc\x9c\xfc\xd8\xa2\xa8\xeb\xec\xb2\x2c\x13\xad\x34\x4b\x4e\x7a\x67\x20\x58\x24\x9d\x2d\x0b\xec\x0c\x36\xa4\xb9\x34\x0a\xb6\x15\x8b\x0e\x6b\x26\x77\xfb\xb4\xdc\x22\x5d\x68\xd8\x86\x2a\xd4\xfc\x16\x47\x82\xb1\x0c\xeb\x5c\x12\x00\x38\xc4\x6a\x5c\xa8\x44\x47\xf5\xe0\x59\xd5\x24\xa7\x82\xde\x26\xa1\x16\x16\x6b\x10\x10\x7e\x20\x54\xf6\x59\x37\x48\x4f\x9b\xf3\xcb\x86\x61\x07\x27\x19\x3a\x41\x3e\x66\xcc\xc0\x1c\x34\xfd\x22\x47\x87\xd0\x91\xbc\xbf\x1e\x35\x19\x76\x2b\xe4\x55\x03\x28\xf7\xc5\x54\xb3\xf4\x04\xce\xd6\xc7\x77\x5f\x1e\x2e\xa2\x6c\xc5\x6d\xb0\xfb\x04\x70\x11\x69\x7a\xf1\x44\xf5\x47\x4d\x98\xca\x80\xa8\x30\xdf\xb1\xe8\x0a\x6d\x62\x52\x79\x8a\x7c\x45\xd3\x5c\x7e\xa8\x2e\x80\x73\x39\x90\x98\x59\x4c\xd5\x31\x8a\x26\xa1\x4f\x8e\x5a\x41\x58\x61\xd2\x90\x8b\x56\xc3\xe3\x5a\xf8\x91\x69\xdd\xb2\x23\x2b\xb2\x21\xac\x4c\x2a\xba\xb4\x09\x15\x61\xf8\x0b\x7f\x2c\x7a\x1a\xbe\x79\xc6\x13\x8c\xa2\x09\x69\x1b\x96\xa5\x4c\x91\x9d\xef\xc8\x2f\x2b\x8b\x7a\x54\x7b\xd2\x03\xf9\x54\x8e\xf0\x83\x9e\xbc\x21\x0d\x5f\xc6\xf9\x76\x83\x67\x8e\xf1\x9b\x87\x0f\x1f\x36\xe3\xbc\x0d\xc3\x1f\x23\x32\x5c\xc9\x65\xa8\x1d\xc0\x37\x08\x34\x8b\x24\xc3\x02\x48\xec\x98\xd2\x4b\x7a\x37\xab\x74\x22\x8a\xdf\x5f\x53\x94\xae\x26\x04\x97\x61\xb6\x16\x3a\x8e\xc2\xa5\x9e\x99\x7d\x36\x7b\xba\x23\x14\xd9\xe1\xa8\x9d\x45\x45\xc8\xe4\x38\x40\xe9\x9b\x65\x00\x83\xfb\xf1\x71\x42\x1b\x76\xbf\x77\x42\x13\x67\x40\xca\x71\xcc\xae\xd1\xe4\x39\xc3\x61\x9e\xae\x06\xf0\x1b\xbb\xc6\x17\x63\xf3\xc4\x11\x9b\x48\xba\x14\x9f\x17\xa5\xb9\xf1\x79\x74\x7e\x77\x92\xdb\x10\x82\xb4\x83\x91\xb2\x40\xa2\x18\xd1\xb5\xd9\x38\xd2\xb7\x14\x97\x5f\xb6\x32\x5b\x36\xf9\x76\x16\xfc\xd7\xfd\xc7\xfb\x69\x93\x32\x17\xb7\x31\x7e\x6e\x6b\x65\x75\x68\x8a\x53\x56\x52\x00\xbf\xda\x41\xe6\x53\x05\x49\x40\x89\x8e\x29\x3a\xf9\x53\xfa\x4e\x54\x59\xf9\x8c\x20\x9d\x01\x8d\x06\x6c\x7e\x51\x5e\x02\xdc\xa5\xba\x8f\x68\x70\x7c\x81\x93\x97\x72\x58\x00\xaf\x60\x7e\x13\x4f\x5c\x56\xdb\x03\x75\xaf\xba\x59\xb4\x7e\x2c\xd4\x4b\x9a\x76\x11\x14\x4d\xa4\xa8\x89\x5c\xe0\xda\xd7\x2c\xe3\xea\xf4\x1c\x0e\x76\xa1\x55\xfb\x31\xb9\x7a\xf2\x10\x7d\x06\x35\xdb\xc4\x3c\xa4\x7a\xd8\xd9\x6e\x87\x46\x1e\xb4\xed\xbf\x80\x39\xe9\xdd\xdd\x74\xff\xe9\xfd\xdd\x97\xcb\x61\xf4\x78\x33\x8c\xae\x9e\xbc\xb6\x17\x39\x61\xec\xfc\x38\x84\xf2\x69\xde\x95\xd0\x9a\xb1\xa6\x3d\xae\x85\x29\x57\x88\x92\xf4\xec\xc7\x15\x2d\xe5\x02\x31\x16\x86\xf2\xaf\x7c\x00\x40\xbd\x56\xd6\xa3\xdd\x35\x78\x44\x79\xe9\xcb\xf8\x88\x9a\x41\xf8\x08\x1f\x71\x65\xd6\xdb\x20\x64\x96\x74\x05\xdd\xb5\x2b\xbf\xec\xcb\xaf\x12\x49\xf7\x42\x2c\xc6\x0f\x1f\xbf\xdc\xbf\xb9\xff\xdf\xe5\xe3\xa7\x3f\xbe\x7d\xfc\xba\xdf\xc2\x78\xc5\x5b\xa1\xfb\xe1\x52\xfb\x59\x24\x54\x70\xf8\x01\x4d\x78\xb8\xe0\x87\x03\x5a\xab\x60\xab\x1a\xcb\x70\x64\xc8\xa7\xa3\x49\xa4\x80\xeb\xea\x5b\x67\xe0\x25\x10\x2d\xbe\x3a\x0e\x83\x64\x31\xf0\x4c\xa4\xae\x62\x6a\xba\xe4\x89\x0c\xb8\x85\x43\x04\x49\xcf\x4b\xfd\x97\x2d\x28\xae\x4b\x28\xb0\x5e\x1d\x21\x7d\x93\x8a\x12\x07\x41\xef\x20\xda\x7b\x11\xe8\xca\x29\x44\xb4\x82\x8e\x76\x32\x8d\x1c\xc6\x68\x51\x03\x21\xe8\x77\xaa\xbd\xa8\xcf\x63\x9b\xfb\x60\x5e\xf7\xee\x2a\x92\x42\xe0\xdd\xc6\xfe\x56\x97\x08\xc1\x32\x8b\x1c\x71\x04\x32\x95\xa2\x89\xa3\xb8\x67\x91\xdb\xd7\xb0\xb4\xec\x4a\x5d\xe0\xcb\x46\x06\x10\xd2\x87\x12\xab\xdb\xf9\xd2\x34\x7b\x8c\xe0\x85\xd5\x00\x5b\x48\x79\xb0\x62\xc0\x96\x40\x4e\x3a\x7c\x41\xe7\x4f\x36\x20\xd1\xc9\xb7\x34\x5b\x06\xa7\x8c\x9a\xf2\x02\xea\x78\xde\xce\x00\x7b\x78\xf7\xcf\x2d\x16\x6f\xbc\x95\x38\xa1\x64\x65\xbf\x20\x14\x8e\xe5\x1f\x15\x46\x9e\x01\x94\xa3\x99\xaf\x51\xb3\xa7\xb2\xa2\x48\x49\x8f\xce\xb0\x44\xdb\x00\xf1\xa1\x5a\x34\x61\x2b\xd6\x8e\x60\xf9\xa8\x13\xe1\x32\x69\xb2\x35\x32\x27\x2a\x0a\xc5\x81\x7a\xbd\x3a\xfd\xa3\xeb\x46\x2c\xa5\x2e\xff\xe4\x7c\x73\x91\x27\x78\x7b\xe4\xae\x8d\x1c\x43\x1b\xa8\x62\xb5\x65\x80\x5b\x69\x2c\x89\x76\xa7\xc1\xae\xe3\x5d\x2a\x52\xb4\xb2\x8b\x1d\x3c\x5d\xb1\xa9\x16\xa0\x1e\x9a\x32\xc5\xda\x1d\x87\x59\xd4\x52\x4a\x8e\x6a\x01\x66\x03\xb5\x06\x64\x9b\x98\x9b\xe3\xdc\x96\x14\xc9\x55\x32\x11\xa9\x1e\x82\x85\x0c\xd0\xf6\xb6\xd2\x79\xf7\xbf\xef\xde\x6f\x1c\xdb\xf1\x1a\xd6\x85\xa2\xa6\xa4\xec\x6a\x89\x1a\xfd\xf0\xb5\xc4\xbd\x8f\x31\x4d\x54\x9b\x33\xf0\x62\xc4\xc2\xb3\x6b\x0d\x89\x69\x51\x43\xb3\x31\xee\x3d\x95\x3e\x69\xf9\x6b\xcf\x76\x99\xfc\x85\x3f\xb8\x95\x2b\xbf\x4d\x9e\xc4\x9a\xe2\xba\x27\xae\x65\x16\x25\x57\xd4\x18\xdd\xdc\xb1\x9e\x93\xd9\xf9\x62\x34\x16\x99\xc2\xd1\x69\x9e\x7e\x7b\x95\x17\x8c\xfb\x53\x0e\x8f\x77\xfb\xfb\xc3\x97\x87\x4f\xa0\xf9\xba\x08\xcb\x1a\xeb\x70\x2e\xc2\xd1\x93\x68\x12\x75\x0a\x42\x0b\x59\x76\x26\x4b\x35\xcb\xce\xc7\x50\x5d\x0c\x75\xb2\xcf\x8b\xe7\x8c\xeb\x47\x9a\xde\x99\x18\x9e\x7c\x12\x85\x32\x41\xa1\xbc\x94\xae\x38\xad\xbf\xaf\x29\x7e\x47\x41\xfd\x8b\x2b\xd5\x77\x7f\x63\xc1\xef\xd9\x40\x5c\xc4\x36\x8d\x2b\xe0\x49\x95\xd5\x93\x08\x5d\x61\x3d\xb1\xe9\xe5\xf1\xdb\x95\x5e\x96\x41\xf0\x63\x14\x2e\xf4\xb2\x0c\xa0\x8c\xa6\x0e\xa9\xfc\x73\xed\xcc\xf5\x4e\xff\xc1\xe3\xb1\x25\xbc\x88\x27\x28\x1b\x45\xa4\x58\xbd\xb9\x2e\x9e\x18\x8d\xa7\xe6\xfc\xad\x3e\x9e\x4e\xd7\x9c\xb7\x45\xf7\x9f\x3a\x10\x97\xb8\x37\xe2\x8a\xe8\xd0\x28\x3a\x8e\xf5\xe6\xba\x78\x42\xfa\x9c\xcf\xfb\x31\xed\x7f\x60\x01\xfd\x87\x8a\xa9\xfd\xf2\xe7\x94\x37\x23\xb0\x45\x25\x38\x49\x9b\xa5\x18\x5c\x8f\x7d\xa2\xe2\xa8\xe6\xbd\x6f\x2d\x4d\xa2\xae\xe5\x98\xf6\x85\x40\x5a\x8a\xf0\xd0\xe4\x09\xfe\x12\xd9\xf7\x7a\x71\xf8\x14\x5d\x23\xec\x3d\xd5\x3c\xe1\xac\xda\x26\x2d\x65\x0f\x61\x9f\x0e\x34\xc5\xdc\x5d\xef\xc8\xf2\x4f\x88\xcc\x23\x44\x05\x7a\xe0\x52\xd3\xf7\xd7\xa2\x51\x04\xb5\x05\x27\x4d\xfe\xa3\x14\xdb\xe4\x73\x45\xc2\x34\xcb\x51\x72\xf4\x44\x3d\xfc\xbb\xaf\x5f\x37\x81\x93\xb8\xad\x85\x3f\xea\x0a\x5c\xb3\x3d\x38\x87\x3c\x79\x06\x62\x57\x8c\x71\xf2\x2d\x58\x04\xcb\x97\xde\x9c\x1c\x54\x72\x31\x97\x3d\xf7\x3a\x89\xea\xec\x29\xd5\x29\xc1\xb1\x5c\x68\x4a\x4d\xb4\x21\x9a\x4a\x73\x31\x02\xaa\x21\xb4\x49\x94\x9f\x2e\x4a\x41\xe8\x13\x20\x74\x48\x7f\x78\x82\xbb\xe6\xdd\xfe\x61\x6b\x35\xdd\xaa\x7e\xed\x65\x2d\x37\xfb\x29\xab\xa9\x76\x76\x51\xec\x55\xab\x4f\xc6\x48\x8a\x1e\xaa\x85\x03\x6c\x26\xd4\xb9\xb6\xd9\xa3\x43\x49\x07\x96\x4f\x92\xb9\xa9\xd9\xcd\x3c\x22\x16\x98\xbb\xf0\x78\xdb\x1f\x7a\xac\xa7\xe1\x2c\xdc\xc4\xcb\x5d\xfa\x31\xad\xc9\x4c\x33\x62\x64\x68\x07\x14\x27\x04\x17\xc3\x21\x2a\x8b\xf5\x59\x2a\xb0\x34\x58\xab\xb7\xb0\x4e\x67\xad\xeb\xf2\x30\x77\x26\xd4\xfb\xca\x3f\x73\xa9\x28\xe4\x33\xd5\x4c\xd1\x2d\x95\xa4\xd5\x37\xa5\xf4\xaf\x96\xcc\xfc\xdc\xb4\x11\x80\x75\x94\x38\xfb\xdc\x34\xf4\x15\x81\x3e\x86\xec\x23\x62\x8d\x15\x8a\x71\xa7\xb8\xda\x8b\xa1\x6c\x0f\xd8\x75\x43\x5d\x97\xbe\xae\xa3\x54\x90\x11\x4d\x44\x87\xa0\xb4\x82\x4a\x44\xa6\xf3\x89\x67\x66\xf7\x1c\x94\x77\x64\xd4\x94\x54\x67\x4a\xa2\xa1\x2b\xf3\xac\x6b\xac\x08\x95\x88\x01\xc4\x57\xd6\x39\x14\x34\x95\x09\x94\x3a\x2e\x02\x13\x0d\x7d\xc9\x01\x5d\xfb\xa2\x64\xe8\x6f\x9f\xa6\x87\x77\xff\xbc\x54\xc2\x1d\xb7\x81\xb9\x53\xf2\xa5\x5c\x90\xde\x71\x89\xf5\xd9\xd8\xb8\xcc\x1e\xf3\x65\xb5\xc4\xac\xda\xec\x02\xea\xa0\x5e\xf2\x88\x55\x3a\x0e\x12\xdb\xa3\x8b\xfe\xd4\x43\xaf\xbe\xde\x53\x6f\xfd\x72\xea\xc7\xbf\x05\xa8\xbf\x9d\x30\x36\xf2\xc6\x82\x7e\x64\x45\x7f\x8c\xb9\xbf\x53\x62\xd6\xfa\x44\x6e\xee\xdb\x6f\xd3\xf4\xf5\xfe\xff\x36\x01\x96\x14\x56\x05\x07\xe0\x10\x96\x70\xf7\x1c\x66\xf6\xe5\xe6\xac\x34\x14\x05\x03\x13\x42\x80\xf0\x48\x61\xbc\x9c\x93\x1b\xdb\x22\x3a\xa3\x3a\xd6\x2f\x97\xb3\x3f\xce\xce\x3b\xbd\xc3\xc9\xad\x07\xa2\x84\x6d\xba\x97\x51\x58\x96\xa7\x51\x55\x96\x2d\x96\xca\x7f\xe1\x91\xfe\x6e\x78\xa4\xfb\x69\xfa\xf8\xf9\xeb\xc7\xaf\x6f\xb0\xec\x1f\x3e\x2d\xdb\x72\xd8\x74\x2b\x72\x04\x60\x98\x10\xd6\x14\xbb\x4b\x12\x00\x02\xfb\x82\x04\xd0\x4b\x1e\x49\x00\xf9\x72\x2b\x61\x0c\x0e\xe5\xef\x78\x90\xe2\x89\x3c\xfd\xa4\xdd\x4f\x3f\xea\x59\xe3\x72\xb8\xff\xb2\x7c\x7c\x77\x61\x54\x36\xe1\x93\xd8\xd2\xc9\xa0\x20\x77\xf0\xaf\xee\xab\xbf\x6d\xf4\x81\x71\x10\x89\x7f\xef\xa0\xbc\x89\x61\xa3\xbe\xa6\xf8\x8f\xd3\x8c\xcd\x5c\xfe\x62\x04\xac\x56\xa2\xa8\xd9\x70\x1f\x32\x1c\xb4\x15\x39\x2f\x5a\xcd\x82\x0f\x87\xaf\xe0\x2d\x24\xcd\x3c\xe8\x23\xde\x77\x12\x7c\x75\xa6\x05\x5a\xc2\x06\x85\x99\xb2\x26\x60\x71\x41\x02\x05\x2d\x88\x84\x71\x49\x33\x80\x60\x35\x76\x88\x5d\x82\x9d\x6f\xca\xb8\xbf\x33\xee\x2a\x44\x1c\xbb\xe3\x24\xbb\x43\xaa\xa2\x6b\xcf\x3e\xa3\x90\xc6\xe7\x22\x6a\xb6\x4a\x63\x88\xb0\x12\x44\x48\x8b\x0c\x45\x69\x8c\xc8\x7a\xad\x92\x41\xba\x0d\xf2\xe7\xb5\xe9\x86\x36\x60\xf1\xd0\xed\x2b\x74\x7d\x01\xd8\x31\x33\xe4\x77\x75\x11\x16\x09\xe9\x6e\xa6\xef\x58\x21\xe9\x49\x15\x85\xda\x4e\x5f\x47\xaf\x36\x48\xb5\xf5\x4d\x66\x22\xd7\x9d\x85\x89\xfe\xfd\x08\xd1\x3f\x4f\x77\xff\x07\x33\x7f\x33\x59\xd3\x19\xd9\x56\x0a\x6d\x96\xcd\x2a\xb8\xa7\x77\x91\xe5\xef\xda\xd1\x4c\xad\xc9\x2d\xcf\x51\xe1\xad\xd9\x65\x40\x90\xb8\x9c\x27\x9f\x53\x42\x29\x8f\x8f\x04\x6f\x42\x49\x8e\x50\x12\xeb\x0d\x84\xc2\x67\x40\x1f\x28\xb6\x47\x75\xfa\xcd\x6e\x06\xc0\x34\xfe\x6a\x33\xea\x72\x23\xbb\xdb\x35\xc8\xcb\xc7\x4b\xb1\x89\xb4\x8d\x4d\x9c\xb8\xb6\xad\xbc\x2e\x4d\x51\x33\xfe\x8b\xd8\xc5\xd2\x82\xca\x93\xfc\x29\xda\xec\x77\xb8\x57\x28\xe4\xa9\x50\x73\x85\xda\x65\x07\x70\x61\x51\x96\x00\x10\x0e\x6c\x70\x51\x05\x4d\xa5\x6d\x93\x97\x4b\xe5\x9f\xab\x6e\x47\xd1\xad\xe4\x7a\x04\xb9\x9b\x1a\x26\x0d\x46\x91\xec\x71\x35\xb0\xab\x89\x27\xdf\x83\x98\x5c\xa1\x59\x7a\x58\x75\xab\x88\x5a\xe5\x96\xd8\xfb\xc5\x11\x97\x39\x17\xa7\xff\xa1\x6e\x4f\x3f\x77\xc7\xba\x3d\xab\x64\x9b\x34\xb5\x81\x0b\xee\x69\xb7\x35\x31\x87\xcf\x49\x1e\xda\x43\x99\xf5\x67\x7b\xcc\x2a\xf9\x26\x42\xfd\x04\xe7\x19\x59\xc1\xe3\x7f\xa3\x6e\xf1\xa3\x74\xce\xe7\x51\x42\x37\x11\x94\x7e\x06\x1e\xee\x78\xa6\x8a\xde\x71\xf4\x44\xe2\xcc\xa7\x6f\x5f\xd5\x2d\x76\xc1\x28\x4a\xe5\x1f\xc7\x88\x78\x40\x52\xc2\x65\x2a\xc8\x3d\x70\xbb\x8e\x86\xc6\x89\x55\x7f\x6a\x08\x9e\x19\xf8\x8a\x2c\x68\x96\xe3\x89\xa5\x7f\x26\x73\x7e\xa3\xc8\xd9\x3d\x5b\xe6\x00\x1a\xe9\x0d\xba\x72\xd3\x83\xdb\xfa\xc4\x53\xaf\x56\x66\x57\xe3\x0d\xb8\x12\xe5\xc3\x7c\x1a\xae\x04\xb1\xa3\x6d\xb5\x97\x0c\x9a\x28\x43\x4a\x7e\x6b\xdc\x46\x2b\xb5\x91\x91\x5d\x9e\x72\x5d\x7a\x63\x39\xd2\x28\xbb\x71\xe6\x6a\xbc\xd4\x8f\x80\xa9\x7f\x4c\x78\xa9\x91\x53\xcd\x79\x42\x70\x1b\x83\x37\x08\x77\x1f\x0d\xde\xee\xd1\xe8\xe9\x1b\xde\x1c\x3d\xa3\xfe\xbd\x3a\x7a\x78\xf9\x1f\xde\x30\xa6\xfb\xc3\xfd\x74\xc1\x39\x9f\x6e\xd5\x90\x51\xa0\xe6\x7a\x34\x0e\x03\x59\x69\x19\x9f\xe6\xda\x68\xd7\xc6\x13\xb4\x14\x56\x5c\xd9\x9d\x88\x30\x78\x33\x92\x8b\x79\x22\xa5\x8f\x9d\x35\x89\x5d\x8c\xcf\x7d\xe4\xa0\x59\x40\x27\x8a\x64\x6e\x2e\x02\x17\x0b\xf2\xc3\x95\x36\x45\x0e\x1a\xfa\x04\x29\x42\xea\x8e\x79\x01\xce\x02\xe3\x27\xf0\xfa\x71\xc5\x06\xd1\x9f\xd4\xf3\xb4\x3b\x2e\xb9\xc8\xd3\x96\xf4\xf7\xd8\x21\x11\xf0\x7e\x61\x2f\x2f\x78\x64\xf4\xf4\x83\xd2\x13\x59\x01\xd2\x2f\xf1\xa8\x7b\x6a\x8f\x21\x77\x05\x08\x23\xa3\xa9\x5a\x6f\xc9\x8a\x9f\xc5\x0c\x7c\x71\x66\x3d\x01\xbf\x73\x01\xc2\x51\x77\xa5\xcb\x3b\xc7\xea\xd0\x27\xf0\x77\xa1\xb7\x4e\x8b\x23\xa5\x1f\x27\x3f\xfa\x76\x04\x9e\x93\x8b\x69\xc6\xb6\x23\xc3\x70\x7b\x2f\xd4\xd5\x7d\x51\xa5\x58\x83\x06\xa5\x65\x04\x0d\x0a\x25\x57\xe8\x87\x82\x06\x09\x54\x31\xa5\x4e\x9e\x51\xc4\x40\x3f\x1c\x75\x43\xc7\xe6\x76\x23\x68\xf0\xf3\xe2\x75\xf7\x37\xaa\x74\xf7\xef\x3f\x2e\x97\xfb\x7f\x2d\x82\x4a\x21\xb9\xc4\x6d\x12\x81\xea\x29\xf3\x84\x6c\xa6\xcc\x7b\xd1\x88\x3a\xd0\x30\x0f\x19\xda\x47\x73\x8d\x80\x20\x8c\xda\x44\xf9\x0f\xa4\x1c\xa2\x71\x77\xd2\x6c\x14\x64\xa4\xc8\x64\x54\x5d\x3c\xba\xe8\x62\x98\x18\x98\x61\x24\x0a\x94\xac\xbd\xe0\xe2\xf7\xd7\xa2\x90\x11\xb7\x49\x3e\xb3\x96\x91\x89\x7d\xd5\x54\x55\x93\x7f\x90\x93\xb5\xe7\xd6\xbe\xaf\xd2\x7e\xea\x8c\xd2\x8e\xb5\x1c\x7a\xd8\x6a\x13\x58\x90\x28\xf3\x79\xf9\xf2\x30\xf2\x26\x50\xc9\x00\x02\x6e\x8c\xe1\xee\x77\xef\x91\xcf\x1e\xc3\x37\x91\x78\x33\x7c\xef\xce\xb4\x8b\x12\xda\x21\x5d\x0c\x14\xec\xbd\x7c\xef\x13\x3c\xfb\x40\xab\xe9\x3a\x52\x89\xb0\x9a\x6b\x98\x48\xfa\x9b\x64\x08\x32\x52\xf1\xe3\x8f\x85\x41\x33\x58\xc1\xd2\x7a\x3b\x55\x21\xfb\x0a\x91\x82\x34\x9f\xec\xf2\x1c\x81\x75\x17\xbb\xcb\x3f\xb8\xa6\x76\xbf\x77\x3c\xbe\xee\xef\xbe\xdc\x5f\x5e\x54\xef\x8f\x3e\xdb\x90\x5d\x8a\x22\x51\x10\x7b\xb9\xac\xab\xdb\x6f\xb2\x62\x44\x2a\x97\x0e\x44\xbd\x64\xc5\xc9\x29\x28\x2e\x12\x9d\x4e\x40\xe4\x0c\xa9\x65\x84\xc4\x32\x78\x2e\x09\x23\xd9\x17\xd4\xbe\x39\xdf\x61\x6b\x59\x05\x4c\xe8\x8b\x37\x53\x5d\xeb\x51\x70\x64\x75\x1e\xd4\xc8\x29\xcf\x96\xec\x3d\xa4\x61\x19\x68\xd1\x73\x45\x6d\x84\x8b\x33\xcb\xd6\x47\xdd\xc9\x8e\x9d\x00\x25\xe4\x0a\xbb\x54\xe3\x9c\x8a\x93\x45\x17\x83\xab\x59\xc4\x1a\x73\x72\xba\x59\x51\x19\x18\x5b\xfa\x12\xc8\xec\xca\x48\x11\xca\x27\x7a\xeb\xbf\x90\xc6\xfa\x7c\x85\xf5\xe1\xcf\xcf\x77\x5f\xb7\xca\xea\xfd\x3f\x4e\x71\xc6\x52\x43\x9d\xbe\x08\x38\x6f\x07\xa0\xd4\x5b\xa1\x54\x62\x3f\xf8\x2c\x96\x54\xd6\x74\xb7\x72\xc8\x49\xc4\x53\xa4\xd5\x35\x9f\x9a\xbb\x46\x40\xbd\xfc\x3a\x92\xeb\x9f\x8f\x85\xef\x7e\x97\x13\x7a\xd0\x1c\x3d\x1e\x8b\x7c\x0c\x9d\x50\xca\xae\x15\x82\x2c\x42\xa6\xa4\xa8\xe4\xa6\x30\xa5\x64\x66\xb0\x28\x78\x40\x77\xa9\x8b\x7c\x72\xd5\x13\xf0\x3b\x47\x85\x84\x74\xa5\xcc\x28\x41\x72\x59\xfe\x05\xf1\x84\xaa\x62\x08\x46\x8e\xbc\xe3\x12\x9e\x60\xe9\xd7\xf9\xfb\xc3\x2c\xfd\x98\xbb\xd7\x58\xfa\xff\xfd\xb6\xb6\x95\xa8\x6a\xd9\xc2\x60\x65\x3a\x1b\xc5\x44\xfd\x71\xc2\xab\x55\x4e\x98\x6e\x8f\x00\xa7\x28\xc0\x32\x46\xae\x94\x69\x8c\x21\x01\x94\x01\x03\xbb\xe8\x30\x4f\xeb\xf8\x33\x02\xdb\x0e\xd3\xe2\x5f\x6a\x0c\xff\x7d\xbc\x86\x6f\x22\xd5\xcd\xd8\xf1\x3f\x4e\x2b\x32\x86\x5b\x2d\x8e\xb5\xa6\x59\xd9\x7e\x38\xe4\x14\xa5\xa3\xa0\x34\x32\x02\x3c\x09\x6c\x76\xf5\xa0\x17\xa6\xa0\xeb\x6e\x46\xd9\x06\x6c\xf1\x3c\xad\x37\x00\x85\x22\x86\xd8\x67\xde\x8e\xe1\xa3\xf4\xff\x73\x10\xd3\x93\xfc\xff\x23\x5c\xcc\x69\xfe\xff\x29\x96\xe9\x5a\x00\xf0\xe4\x9e\xf5\xd8\x50\xff\xed\x63\x74\xff\x6d\x93\x79\x92\xb7\x45\x1c\x47\x93\xb4\xd7\xe2\x98\xfb\x84\xcc\x85\xdc\x67\x03\x1c\x8c\x36\x97\x55\xd5\x4f\xaf\xf2\x04\x6d\x02\x98\xa6\x3c\xa8\x74\x8d\xc6\x1c\xdc\x9d\x43\xf5\xd0\xad\x44\x6b\xef\x17\x18\x08\xa3\x5e\xd3\x5b\xed\x14\xae\x5c\xf1\x2e\x45\xee\x26\x05\x41\xec\xa2\x60\x28\x48\xaa\x2c\x6d\x42\x7f\xe6\xb3\xf5\xb7\x2e\x3f\xac\x3e\xa2\xa8\x6b\x77\x5d\xba\xeb\xca\x05\x78\xba\x48\x6c\x72\x14\x44\x7c\xd4\x0b\x40\x40\x07\xa2\x2d\xa4\x6d\x9b\x4b\x75\x4c\xc1\x71\x02\x86\x60\x6c\x4b\x0a\xa8\xb8\xe4\xb6\xc2\x53\x4b\x2f\x44\xa8\x51\x11\x09\xed\x94\x67\xd4\x0b\x3b\xe9\xb7\x34\x81\xb5\x50\x7a\x13\xc9\xd9\x96\x23\x6f\x00\xb0\xc9\xe0\x5f\xe1\x95\x46\x10\x03\x61\x07\x7c\x87\x42\xd3\x13\x68\x42\x03\x06\x93\x29\x0d\xe2\xe1\x45\xab\xe4\x81\xae\xa6\x05\x00\x28\x31\x4a\x1a\x41\xf7\x54\xcb\x3e\x95\x66\x30\x3b\xaa\xdc\x69\x55\xb3\xab\xce\x73\xd9\x4d\x5a\x6e\x2a\xaa\x67\x36\x22\x31\x40\x9d\x89\xe9\xd0\xd0\xd8\x58\xb5\xb6\x2e\xef\x53\x06\xd8\xe1\x7a\x23\x94\x17\xbb\xa2\xe0\x50\x7a\x1b\xd6\xdc\xf6\xc1\x56\xdb\x54\x62\x01\x50\x7f\xef\x63\xab\x33\x80\x4c\x91\x41\xab\xe9\x3a\xaa\x20\x28\x68\x74\x69\xaf\xf2\x0c\xfe\x5a\x59\x63\xa3\x3c\x19\x6b\x01\xa5\x51\x08\xb2\xbf\xca\x2e\x2f\x48\x33\x92\x29\x48\xec\xe2\x94\x9d\x26\x80\xc3\xfe\x61\xa8\x9b\x15\xe5\x84\x4c\xb7\x69\x7e\xde\x6e\xf7\x9d\x6d\x21\xcb\xa9\xf3\x8a\x83\x8b\xbd\x1f\x7c\x34\x14\xa1\x2d\x4c\xb2\x05\xa2\x1e\xc1\x1f\xe6\x70\x6d\x56\xf6\x7a\x88\x2d\xda\xac\x5e\xaf\xc3\x9c\xb6\x19\x0d\xde\xda\xf3\x09\x99\x0f\xac\xcc\xd2\x95\xb4\x0e\xdc\x71\xe3\x25\xa2\xb4\x83\x68\x2d\x75\x8c\xe6\x12\x17\xf9\xa4\x91\x2b\xac\xa5\xaa\x2b\x67\x52\x55\x8f\xb8\x22\x45\x0b\x45\x30\xac\x98\xa2\x28\x31\x44\x4b\xea\x4e\xe6\x45\x36\x27\x34\xe8\x84\x23\x23\x93\x09\x3e\x38\x2d\xbb\x8c\x55\xfd\x9f\xf0\x21\xa0\x9c\x8a\xf2\x3e\x86\x7c\xe6\xd0\x1a\xee\xac\x83\xd7\x37\xf2\x63\x83\xf5\x27\x3b\x2c\xb6\x48\x1f\x43\x3e\xf8\x58\xfb\x3e\x51\x3a\x68\x2a\x15\xe2\x76\xda\x73\xe8\x9e\x3d\x95\x53\xc7\xad\x6c\xa3\xcf\x28\x3c\xf8\xf6\x75\x53\x51\x98\xb7\xa1\x99\x53\x49\x08\xa9\x83\xd6\x66\x80\xa0\xa3\xbd\x45\x57\x61\x36\x78\xde\x02\xa3\xa7\xe6\x2b\x30\x9a\xf1\xa6\xbc\xaa\x19\x6e\xe4\x51\xa9\xef\x22\xd8\xc0\xc1\xfb\x07\xe1\x58\x13\x70\xd7\x81\x21\x15\xeb\x5a\x7a\x8e\x20\x4e\x05\xaa\x1a\x3b\x94\x05\x44\x27\x4f\xaa\xa3\x94\x93\x65\xa5\xb2\xd6\x65\x4c\x48\xf0\x83\x0b\xba\x77\x11\x62\xc7\xc0\x47\x73\x35\x39\xdf\xe6\x86\xea\x06\x94\x22\xa6\xb8\x5b\xb4\x54\x89\x79\x36\x6c\xae\x93\xd2\xfa\xc4\x0b\x90\x55\xac\x35\xa5\x60\x42\x80\x41\xfb\x55\x9e\x07\x4e\x02\x6e\xc0\x00\xe4\x1a\xe4\xe8\x80\xcf\xc0\xfb\x29\xe0\x82\x42\x14\xc4\x81\xf2\x0e\x00\x2f\x97\xfa\xa2\x98\xad\x59\xcc\x1d\x72\x5a\x00\x25\x8f\xab\xa8\xe7\x8b\xcd\xf5\xe6\x38\xf1\xc2\x39\x3b\x8a\x32\x3f\xae\xae\x2d\x02\x3f\xf3\xb9\x73\x5f\x46\xaa\xcc\xa2\x42\x16\xc5\x3c\xc6\x60\xb5\xaa\x05\x9f\xbb\xa5\xc4\x35\x94\x0e\xe0\x94\xae\x70\x0f\x69\xc6\xae\xd7\x80\x29\xdb\x26\xd4\xf6\x28\x04\x20\x7a\x47\xcb\x6e\x75\xe9\x7b\x55\x74\x00\x7f\x12\x75\xa7\x04\x10\x1a\x30\x15\xf1\xce\xe8\x3d\x96\xb1\xd5\x52\x2c\x65\xfc\x25\x14\xff\x77\x83\xb0\x45\x51\xd1\xe2\x0b\x14\x0c\xb2\x30\x90\x12\x3b\x36\x15\x87\x80\xce\x5c\x10\x1c\xf7\x31\x22\xcc\x15\x49\x8b\xb9\xc4\x98\xa9\x41\x91\x19\x40\xda\xce\x01\xa5\x29\x48\x7e\xab\x72\x62\x5e\xac\x70\x49\x3a\xac\x00\x22\x67\xb7\xc8\x99\x98\xdb\x9a\x1e\x57\x35\x71\xc9\xf9\x9e\x6e\xae\xaa\x8f\x9f\xb6\xfa\xc5\xa6\x96\xa7\xf5\xb6\xe2\x9a\x88\x30\x2a\x56\x7c\x77\x79\xcd\x94\x66\x40\xc7\x70\x27\x31\x7e\x05\xc2\x04\xb6\xd4\x30\xc3\x6d\x41\xb5\xb9\x94\xbb\xf3\x39\x16\x75\x4c\x16\x07\x3c\x62\x1d\x15\x00\xc8\xc8\xe7\xde\x83\x71\xd6\xea\xe3\x64\x30\x66\xb0\x3e\x44\xf8\x3e\x7a\x73\xb9\x92\x88\x40\xe4\xa9\x32\x1f\x44\x22\x5e\x9b\x51\xb2\xae\x22\x9c\x59\xa4\x6b\x65\xa1\xa0\x8c\x9d\x79\xef\x13\xd7\x4b\xc2\x3f\x6c\x53\x5b\x13\xc5\xd9\x83\xc1\x1d\x70\x11\x4d\x0e\xf6\x9e\xd2\x4d\x51\x11\xe3\x73\xa2\x57\x37\xba\x95\x63\x9c\x93\x32\xb3\x17\x75\xd3\xed\x69\x2d\xe0\x7a\x66\x22\xe8\xff\xf7\x79\x53\x11\x9c\xb7\xa1\xba\xc0\x75\x38\x44\x42\x74\xc8\x21\xe7\xf3\x57\xb3\x17\x8b\x87\x18\xc3\x1e\xf5\xb7\x97\x7f\xa6\x70\x55\xa1\x43\x80\x2e\xdf\xbe\x38\x5d\xbd\x18\xb0\x57\x4c\x2e\x57\x04\x93\x30\x3b\xc0\xe0\x2e\x87\xdc\xc0\xcf\xd4\x11\x90\x08\x4e\xe7\xd1\xc4\x84\x15\x93\xe1\x01\x05\x40\x8b\x0a\x52\x68\x86\x4e\x71\x71\xda\x02\x31\x5e\x68\x37\x51\x27\x97\x90\xb7\x3c\xc2\x25\x7b\x52\x3f\x78\x70\x4a\xfd\x0e\x0d\x0a\x0a\x5f\xa4\xc9\x47\xa0\xab\xd7\xbe\x67\xca\x97\x63\x41\x9a\x3b\x1c\x8e\x31\x32\x13\x5f\x63\xf3\xdc\x7b\xee\xe1\xe0\x5b\xde\x73\x0f\x37\x6f\x11\x9f\xb8\x45\x8c\xe1\xd6\x1e\x7d\xbb\x3e\xf3\xdb\xdb\xcd\x14\xd9\xc6\x04\x4f\xeb\xf6\x53\x74\x1d\x58\x2a\x48\xea\x2e\xd9\x51\xe1\xff\x9f\xbd\x77\x5b\x92\xdd\x38\xb2\x05\xdf\xf3\x2b\xe2\x07\xb0\x2d\xdc\x3d\xae\x76\x9e\x66\xc6\x6c\xde\xea\x1b\x68\x9b\x6a\x9e\x4e\x5a\xa3\x45\x81\x0d\x65\xf7\xa9\xaf\x1f\xf3\xb5\x1c\xc8\x2c\x66\xed\x2a\x52\x22\x4f\x4b\x76\xc6\x24\xee\xca\xaa\x04\x02\x40\x20\x2e\x7e\x59\xbe\x96\x6f\x74\x92\x9a\x22\x2b\x75\x73\x97\x91\xd4\x9c\x19\xd9\x53\x7c\xb5\xf3\xc8\x70\xfb\xd8\xc2\x22\x13\xdb\x1b\x7d\x0a\x28\xd2\x44\x99\xbe\x7a\x53\x25\xdf\x16\x91\x71\xad\xf9\xdd\xad\x41\xbf\xc1\x21\x5b\xdd\x22\x79\xe4\xd1\x7e\xea\x35\x69\xef\xce\xfd\xa9\xdf\xa4\xc4\x26\x99\xc4\x13\x27\xb6\xdf\xdd\xb7\x4e\x29\xf3\x3d\x53\xc8\xcf\x6a\x3a\x7f\xd9\x58\xb5\xb9\x69\xce\x18\xd6\x47\x0f\xec\xf7\x8e\xf9\x58\x83\xf0\xe7\x27\x76\xf6\xfa\x9c\xc5\xbc\x63\x58\xaa\x94\x64\x45\xd6\x21\x49\xa7\xf7\x46\x9d\x6b\xf7\xeb\xe4\x0c\xe0\x14\x86\xf8\xee\xff\xf8\x5d\xa6\x1c\x66\x7d\xfc\x7c\x7d\x69\x06\x25\xfa\x95\x00\x7b\x1f\x83\xba\x02\x9e\xa3\xe3\xaa\x5a\x5f\x5f\x86\x2a\xa4\xea\xc5\xe6\xba\x1c\x47\x75\x90\x37\x74\x49\x56\xf2\xea\xa6\x5a\xf6\x95\xa6\xa9\xdf\xc6\xa2\x73\xe2\x6d\xa5\xd3\x2f\x3d\x39\x86\xce\x5b\xe0\x0d\x80\x71\x44\x79\x7d\x3b\xae\xdf\x57\x50\xf2\xfb\xf5\x2d\x47\x19\xc5\x7b\x88\x83\xcb\x7d\x75\x95\xa3\x3a\x15\x7a\x65\x9d\x28\x3a\x04\x38\xca\x95\xae\x9f\xe2\x8d\x9a\x24\x77\x08\xa5\xb5\xd4\xa0\x12\x97\xa7\xff\xd6\x3f\x38\x51\x48\x19\x05\x0e\xae\x60\x23\x95\xce\xec\x6c\x34\x31\x7e\x15\xdc\x41\x3a\x58\x89\xf9\x90\x52\x7e\x1d\x46\x42\xfc\xfe\xc6\x4c\x56\x0a\xe1\x79\xee\x69\x8d\x0b\x96\x4a\x90\x6d\x8b\x5e\x41\xac\x81\x25\x14\xb7\xbd\x82\x5b\xa0\xe5\xab\xd5\xb9\xce\x9e\xac\xe5\x0d\x54\x3c\x78\xf6\xab\x68\xdb\xd0\x17\xc7\xd1\x23\x8e\x6e\x75\x9d\x86\xa3\xeb\xc3\xd1\xd6\xc3\x7f\x6d\x77\xff\xd5\xe0\x94\x8c\x95\x1a\x4e\xbe\x93\xc9\xf3\x4e\xf6\x6d\x7c\x88\x20\x05\x13\x6f\x58\xfa\xfc\x6d\x9b\xe0\xf7\xfb\x9f\x9e\xa6\xc7\x13\x2d\xe7\xe3\x0a\xe7\x6f\x77\xcc\x16\xc0\x2a\x45\x1d\x82\xdb\x22\x63\x93\x50\xee\x90\x1e\xb1\x70\xf0\x5e\x09\x4b\xc1\xbb\x90\xa1\x36\xb4\x3f\xc8\x31\x33\xfc\x4d\xf5\x83\xde\x50\x82\x3a\x8b\x84\x57\x41\xec\x04\xf1\x8e\xea\x63\xa7\xdc\xb4\xca\xb6\x0c\xf2\x99\xa9\x26\xf1\xaf\xf4\xf8\x8a\x31\x53\xd2\xec\xe6\x60\xd5\xcd\xe0\xc1\xcd\x79\x35\x49\x32\x0c\x1d\x5b\x03\x77\x50\xe5\x56\xb2\x5e\x7d\x98\xb6\x44\x4d\x32\xb9\xe9\xa0\x66\x4d\x1b\x7e\x73\x09\x7c\x81\x22\x37\x69\xe5\xb2\x12\xe9\x4f\x32\xac\xd9\xfd\xe0\xaa\x57\xbf\xf6\xa2\xa5\x6f\x43\x93\xba\x9b\x91\xf4\xa6\xa5\xc6\xdf\xab\x6e\x1d\x65\x3e\x52\x62\x47\x0f\xf4\x4c\x0d\x11\xbe\x3e\x76\x86\x8c\xc0\xa5\xf0\xfa\x32\x91\x49\xf3\xc5\xdf\x58\x02\xde\x0a\x40\x5c\xa5\x05\x37\x30\x43\x48\xed\xe0\xf3\x85\x53\x15\xbe\xec\xd1\xa9\x12\x94\x77\x8b\xf8\xde\x37\x36\x04\x21\x7a\x5a\xc0\x5e\x37\xf8\xb3\x1a\x82\x12\x30\xdf\xcb\x5e\x3b\xb4\xcc\x2a\x5a\x2d\xa4\xb8\x53\xa1\x3d\x6e\xf9\xc2\x48\x45\xc9\xd8\x76\xab\xbc\xbe\x8c\x21\x69\xc0\xb2\x04\x00\x57\xe1\xe3\x9c\x3c\x7d\xee\x55\x15\x26\xad\xdd\xaf\xa1\xbf\x84\xda\x1e\xf7\x17\x18\xe8\x01\xd2\x36\x24\xd3\xfc\x86\x6e\xa8\x37\x85\xa7\x5f\xe2\x4f\x3b\xfc\xc4\xbc\xd7\x9c\x74\xaf\x35\x55\xd4\x2d\xc0\xb9\xd8\x51\x94\x80\xe7\xb7\x9e\xb4\xef\xda\x93\x0d\x38\xce\xf5\xe3\x30\xc9\xff\xfc\x71\x7d\xce\xb2\x7c\xff\x3f\xde\xc2\x17\xb5\xdc\x4a\x47\xbd\x96\xcf\x36\x7f\x11\x3a\xd6\x92\x41\xf8\x1f\xb0\x01\xd2\x8b\x5a\xbb\x2e\xa5\x2b\xc1\xf9\xf3\x04\x66\xbf\x21\x5d\xb8\x02\x00\x20\xb9\x7e\xb3\x40\x08\x7c\x22\xef\xc2\xb6\x5b\xce\xcf\xb8\x6d\xe0\xcd\x6b\xf9\xd8\x8f\xf1\xe7\xfc\x6e\xff\xe1\xbf\x9e\xd0\x7c\xf5\x9e\x6f\x2f\x0d\xce\x4b\x7e\xe7\x89\x9e\x9f\xff\xf5\x65\x4e\x28\x84\xff\x61\xcf\xf3\x5e\xe7\x05\x60\x42\x5a\x3e\xd7\xf2\x37\x41\x70\x40\xa9\xde\x0b\x82\x9f\x6b\xe5\x63\x0c\xbc\xe7\x72\x79\x0e\x82\x43\xbc\x5d\xda\xef\x74\x81\xf7\xdb\x6f\x5d\xff\xa0\xf6\x3f\xcc\xef\xff\xf4\xf3\xfe\xdd\xf7\xff\xeb\xbb\xaf\xeb\x5f\xae\x5f\xbf\x7f\x86\xf2\xd6\xe7\x9a\xcd\x47\x15\xa1\x29\x49\xb8\xa5\xf4\x75\xe9\x9a\x54\x50\xfa\x9a\x4a\xdf\x16\x45\x64\x44\x41\x3e\x03\xce\xdd\x25\x68\x6c\x0e\x3e\xc0\xb1\x2f\x58\x83\x74\xbe\xbe\x74\x6b\x29\xb4\x69\x35\x50\xec\x7e\x0e\x3c\x0f\x09\x7c\xfb\xbd\xaa\xf2\xb1\x76\x13\x70\x2f\xfd\x76\xed\x1f\xaa\x1b\x49\x61\xf2\xa9\xf2\xca\x6d\xf1\x23\xdf\xfd\xea\xf5\x45\x80\x52\xa6\x3c\x8b\xd9\x75\xa9\xa3\xdc\x66\x5e\xad\xcd\x54\x15\x59\x7f\x19\x49\x25\x69\x5f\x45\xd2\xbc\x59\x50\x41\xb6\x63\xb1\xe2\xd3\x82\x2b\x25\x12\x0c\x40\x0f\xb9\xa3\xaa\x6e\xa6\x57\x54\xd6\xde\x54\xe7\xb5\xb6\x7e\x5b\x86\x3f\x1d\x94\xa0\x2c\xfb\x06\x84\xfa\x55\x21\x85\x0a\x43\xce\xb7\x45\x57\x9f\x95\xdb\x4c\x8a\xc7\xbd\x6a\x19\x37\x71\xcf\x4b\x05\xf4\x2d\x92\x46\xc7\x5c\x6c\x70\x1c\x6f\xfe\xc1\x8d\x22\xe8\x0d\x94\xeb\xa2\xc5\x56\x02\x39\x4b\xb9\xf6\x7a\x1e\xd9\x79\x64\x5e\xd5\x72\x6a\xcd\xf7\x40\xbd\xe0\x97\xc5\x7f\xeb\x1f\x13\x28\x7d\x67\xfa\xc4\x9e\x5e\x3f\x64\x34\xc5\x48\xca\xe5\xff\x8c\x81\xe4\xaf\x65\x91\x9a\x2f\xbf\xd3\x8b\x79\xf3\x5e\x38\x4e\x25\x67\xf9\x87\x19\xa7\xee\x60\xfb\x38\xb5\x6d\x26\xf1\xde\x14\x1f\xa7\x97\x73\xa0\xfe\xaa\x05\x6a\xdf\x7f\xfe\xf1\xfb\xbf\xee\x3f\x3c\xa1\x51\xda\x33\x3b\xe7\xdd\x53\xfb\x67\x18\x0e\xee\x6b\x2d\xa6\x1f\x28\x57\xbd\x0f\xef\x7e\x47\x65\x6a\x98\xbe\x2f\xee\x92\x73\x2a\x23\x7f\x70\x09\xa0\x0b\x7e\xcd\x25\x20\x0c\xf6\x7c\x05\xb7\x7d\xe6\xfc\xe8\x21\x08\x41\xf9\x15\x57\x00\x8e\xe1\x1d\x90\xba\x5b\xdf\x90\x24\xf9\xb6\xc2\x57\x6d\x97\x5f\x29\xc7\x55\xdb\x6f\xf3\x81\x9e\xc7\xe1\x7b\x85\x10\xed\xb9\x0e\xf4\xa1\xf2\x05\x80\xb6\x0f\x5f\xb4\xbe\x9f\x4f\xfb\x95\xf7\xff\x0f\x37\xda\xdf\x1d\x8b\x3e\x52\x3e\x1e\x8b\x7f\xef\x48\xf1\xd1\xfe\xf1\x58\xfc\x7b\x47\x3b\x94\x87\x3f\x1e\x8b\x98\x8a\xbf\x76\xd2\xfe\x6d\x63\xf1\xa7\x9f\xff\xe5\x99\x9b\xb0\xdd\xe1\x28\x56\x5a\x62\xe6\xb4\x19\x58\xd0\x45\x1a\x21\x6b\xd5\x0e\xb6\xc6\x61\x44\xd7\x03\x29\x5f\xc2\xd3\x9c\x75\x97\x0c\x27\xcb\x06\x9d\x61\x90\xaf\xed\x56\x41\x0b\xf7\x8f\x36\xcc\x9e\x15\xf4\x7c\x98\x81\xcd\x84\x3c\xf7\x1a\x18\x04\x54\x66\x92\xee\x5a\x0a\xbd\x11\xe2\x47\x67\xa8\xe6\x30\xc4\x40\x63\x02\xac\x83\x4d\x0f\xe5\x1a\x69\x08\x68\x51\x24\x5b\xea\x6a\x13\x32\xfa\x02\x61\x48\xe8\xd6\x08\x52\x8c\x62\x09\xb1\x0d\xdb\x40\x50\x2e\x70\x56\xe1\xfa\x36\xd4\x9d\x16\x0a\xef\x6c\xdc\x22\x2d\x72\x87\x78\x07\x44\xb8\x50\x68\x9a\xa5\x36\xdd\x48\x42\xbf\xb4\x9e\xa4\x6b\x50\x71\xd4\xe4\x3b\x7c\x1f\x24\x3d\xb0\x4d\x20\x8a\x09\xe2\xdf\xc9\x82\x24\xc0\x2c\x09\xb2\x2a\xb5\xa5\x31\xb0\x71\x97\xeb\x52\xda\xbc\xf9\x07\x69\xfd\x56\x50\x2f\xd3\x11\x1b\x94\xb9\x33\xca\x76\x43\x7c\x6d\x5d\x3a\x53\xe3\x83\x3d\x07\xa0\x84\x40\xb1\x77\xa9\x83\x3c\xbb\x6d\x15\x9f\x05\xa3\x5e\x91\x04\x6f\xd5\x5b\xfd\x04\x4d\xfc\x38\x70\xdf\x5d\x3f\xed\xcd\xe0\x15\x2d\xfd\xff\xa4\xd1\x7b\xb9\x2f\x92\x48\xb6\x94\xff\x7d\xaf\x2d\x26\x8c\x8c\xf9\xdf\x37\x63\x2e\xff\x6d\x53\xe6\x61\xc6\x7c\xec\xd7\x58\x79\x1a\xb2\xcf\x10\x9a\xbb\x5f\x03\x38\x34\x56\xfc\x5f\xd6\x2a\xdc\xe5\x84\xbf\x1c\x65\x90\x4c\x77\x93\xa1\xa5\xa7\xe3\xd7\x2f\xf5\xe0\xaf\x1f\x5f\x1e\xf0\xe4\x28\xd7\x9e\xe0\xf6\x7f\x7d\x29\xd2\x52\xf7\xdd\xe8\x40\x36\xbf\x27\x84\x04\xa6\xc8\x67\x4a\x20\x9e\xf2\x4b\x21\xa4\x31\xde\x15\x42\xc2\xd6\xda\x99\x91\x83\xb6\x2f\x3a\x9f\x9a\xb0\x3e\x43\x91\x46\xbf\x6c\xe6\x3f\x12\x31\x60\xd6\x81\x25\xa8\x51\x3b\xd8\xa9\x93\x5f\x3b\xb5\xce\x66\xd9\x48\xca\xc2\x32\x2e\x19\x02\xa1\x66\x9c\x0e\x86\xae\x3e\xae\x88\x38\xf5\x76\xa5\xda\x33\xdb\xc1\xc5\xee\x01\x61\x88\xf4\x43\x63\xc9\x26\xfd\x16\x4b\x44\xa0\x8d\x54\x58\x0a\x26\xf1\xdc\x5f\xa2\x26\xa1\x80\x2b\x49\x36\xc0\xbb\x64\x24\x08\xaa\x15\x83\x20\xc8\xa6\x25\x69\xea\x0d\x5a\x14\x59\x92\xa8\x6c\x6d\xa4\xd1\x13\x7f\xcb\x1b\x2b\x8e\x4d\x52\x19\x54\xab\x28\x50\x4e\x83\xe8\x2e\xe8\x50\x51\xf4\x81\xb0\x67\x93\x1d\x99\x8c\xaa\xbb\x15\x08\x84\x47\x6d\x84\x8f\x82\xe2\x8f\xc3\x38\x2f\x14\xa9\x1b\xde\xde\x5e\x72\xb0\x6e\x6a\x61\x4d\x0a\x20\x0b\x3b\xa5\xa6\x98\xe1\xc1\x3c\x05\x99\x31\xc1\x0b\xac\xa3\x05\x6d\x00\x75\x0f\x1a\xe0\x6c\x2d\x78\x01\xc6\x1e\x90\xa7\x1d\xee\x59\xb9\x6a\xef\x5b\x1f\x98\x6e\x78\x1f\x7b\xc5\x54\xfc\x74\x02\x3c\x11\xb2\xb5\x8f\x98\x68\x7d\x02\x04\x70\xf4\x79\x50\xbe\x99\x03\xe7\x14\xc0\x0c\x38\x26\xc0\x7d\xfc\xbf\x19\xfe\xcb\x31\xfe\x97\xfb\x04\x28\x65\xdc\x07\xf3\x2f\xea\x82\xde\x0e\xfe\x37\x55\xc7\xf7\x29\xf3\xb6\xea\xf8\x71\x0a\x3c\x56\x1d\x97\x9a\xea\x84\xee\xe9\xd2\x24\x1d\x13\x60\x11\x1f\xaa\x29\xc4\xf9\xc4\x28\x55\x42\x12\xf8\x7e\x5d\xbc\xb3\x19\x41\x45\xe7\xef\xf1\x2a\xf8\x66\xb6\xa8\x0d\x05\xaa\xb7\xe3\xa9\xb0\xf8\xf9\xb7\xfd\xa0\x6c\x2a\xf0\xc8\xfd\xbd\xa3\xaa\x05\x95\x35\x1c\x14\x4b\x8c\x91\xe5\x1c\x34\x4b\x8c\xa2\xe5\x3e\xb0\xde\x4c\x7d\x70\x91\x29\x65\xb4\xc1\xf2\x1e\xc3\x73\x89\xf1\xba\x2d\x13\x44\xc8\xe7\x68\x0e\x14\x16\x59\x86\x30\xe8\xb7\xc5\x8c\x91\xfd\x98\x10\x3e\x7d\x81\xb2\xe0\x74\xb9\xec\x0b\xa6\x0f\x48\x95\x15\x4b\x01\xd1\x78\x31\xd3\x8e\xa9\xc7\x65\xa7\x7c\x89\x85\xe7\x4b\x05\xee\x39\xc5\xbc\xed\x9d\xf9\xb6\x63\x62\xef\xe7\x6c\x3f\x16\x80\xab\xf4\x6b\x6f\x57\x6b\x9b\x00\x71\x9d\x62\xd1\xd8\xea\x40\x8d\xd1\xb1\xa8\xd8\x44\x17\xc7\x92\x23\x44\x85\xc4\x82\x54\x00\xe0\x4a\xc7\x6a\x95\x89\x09\xe5\x5a\xf6\xe1\x6c\xf8\x5f\x3f\xfd\x75\xff\xeb\xf7\xef\x97\x47\xb5\xb3\x24\x7e\x8a\x5b\x02\x76\x93\xea\x6d\x57\x96\xf4\xd6\x7c\x48\x9f\xa3\x13\x1b\x35\xec\x82\x24\x99\x7f\xda\x34\xb0\x18\x65\xbe\xbe\x08\xca\x4b\x6a\xbd\xb6\x76\x33\x5f\x7e\xab\xe0\xd4\x2a\x3b\x5a\xa8\x72\x5b\xac\xbc\xbe\x54\xd3\xd4\x54\x6e\x4b\xcf\xd7\xc5\x9d\xac\xa2\x76\x5d\x7a\xb9\xf1\xe7\xb8\xf5\x7c\x55\x53\xb7\x82\x2c\x95\x59\x81\xed\xbc\x2e\x6e\x56\x64\xa0\xd9\x30\x3f\xb0\x78\x57\xbc\x63\x56\x36\xe9\x40\x06\x0c\x30\xb2\x5a\x6e\x3a\xb3\xdf\xc8\xa2\x3d\xc7\xe0\x44\xb8\x07\xb9\xef\x4a\x65\x8b\x7a\xd9\xd4\x4d\xaf\xa2\xc9\xe4\xa6\x23\x5f\x5b\x7f\x7d\x99\x03\x52\x24\x37\x80\xc9\x82\x4b\xbe\x43\x60\x9d\x22\xef\x0a\x69\x8c\xa5\x28\xb0\xf1\x4c\x0e\x14\x7f\xb4\xc6\x7b\x9c\x76\xa5\xe2\x98\x6c\x86\x7a\x2b\xff\x3e\x6f\x90\x3a\x8a\x13\x3b\x82\x4f\xde\x28\x78\x56\xac\x25\xad\xf5\xb6\x60\xb9\x04\xb2\xca\x07\xe3\x46\x78\x37\xdf\x32\x14\x29\xa2\x06\x6d\x64\xfe\x1e\xe6\xa5\x24\x1b\x94\xb3\x65\xb3\xa3\xdd\x04\xd0\x83\x0a\x3e\xba\x81\x97\x64\x23\x0d\x70\xde\xfb\x02\x60\xe3\x42\x85\xd6\x09\xb4\xe2\x68\x37\x6e\x5d\x06\x5b\x6b\x23\x5f\x17\x4a\x0f\x25\x72\xc2\x3e\x0b\xce\x1c\x7d\xa7\x3d\xd7\xbe\xd4\x9b\x0f\xf5\x2b\x0c\xd6\x51\x93\xe4\x3e\x6f\x8b\x30\xa3\x82\x77\xaf\x2c\x87\x33\x4d\x55\x6e\xfc\xa2\x42\xf4\xde\xf7\x19\x8d\xfa\x00\xf3\x4d\xaa\xa1\xf9\x1e\xa5\x03\x80\xe7\xe7\x04\x55\x1d\x4b\x1d\xd8\xce\xde\x90\x53\xdb\x40\x4f\x81\x2e\x11\xb7\xd8\xbc\x5b\xf0\x16\x0a\xc2\x78\xd4\x6c\x5e\x02\x2a\x77\x24\x61\xa9\xf9\xe0\xed\x5c\xb0\xae\x40\x30\x0c\x2a\x6e\x51\x2f\xd0\x5b\x3a\x7e\x15\x0a\x33\x1d\xa7\x04\x28\xcf\xea\x06\x4c\xad\xd4\x54\xc8\x94\xb6\xc7\xf5\x8b\xa5\x8a\x7a\xbb\x64\x75\xc7\x59\xdd\x7c\x58\x41\x42\xd7\x1f\xe5\xf5\xa5\x36\xf3\x4d\xb9\xaf\xd3\xe7\x8a\x1b\x0a\x75\x45\x07\xc9\xf4\x0f\x96\x64\x56\x1f\xf8\x18\x17\x06\x33\xbb\xcd\xd5\x97\xcc\x46\x09\x61\x9f\x58\x05\x89\xd4\x71\x5b\x34\xcb\xb5\x97\x9b\x66\x79\x7d\x19\x55\xd3\xb4\x76\x13\x60\x83\x2a\x83\x9a\xa3\x6f\x0b\x5f\xb9\x2f\xf7\xfe\xb2\x43\xa0\x8d\xef\x3e\x4c\xd4\xc9\x00\xe8\xf0\xa1\x4a\x64\x51\x1d\x1c\x0e\x9d\x15\xf6\x23\xc5\xf1\xc5\xe7\x38\x5a\xda\x38\xca\x70\x0d\xa8\x16\x5b\x1a\xd2\x7c\xb8\x9b\xcf\x65\x1f\xf6\x3a\x0c\x12\x5c\x70\x77\x0a\x7e\x1e\xea\xad\xd2\x60\x6e\x93\xf6\x3f\x69\xbb\x41\x18\x0f\x27\x4d\x0b\x9a\x17\xd8\x6b\x80\xec\x6b\xc7\x6a\xa7\x7d\x33\xdf\x15\x7a\x77\x43\x70\x29\xf9\x37\xd7\x28\x5e\xfe\x01\xea\x3d\x62\x15\x7e\x5a\x80\xef\x5c\xe2\x5d\x92\x4e\xbd\x2d\x4a\x64\x29\x84\xda\x27\xa4\x71\x17\xb5\xd8\x15\x55\x6f\x96\x65\x53\x05\x37\x82\xff\xbe\x41\x0d\x9a\x07\xfa\x54\xca\x33\xe9\x94\xdb\x52\xda\x75\x99\xf9\x46\x91\x3f\xb0\xc6\x34\x90\xc6\x90\x84\xcb\x87\x6c\x9e\x57\xc9\xfd\x36\xcb\x75\x01\x1f\xd7\x2c\x57\xc9\xf5\xb6\xd4\xe6\x5f\xe4\x5b\x6d\xf3\xf5\xa5\xa1\x0a\x36\x5f\xc7\xbc\x15\x3f\x72\xcc\x1b\x88\x97\x10\x6c\xc7\x42\xd8\xb9\x10\x12\xb1\x00\x49\x6d\x7f\xc1\x20\xbb\xb7\x7a\xb3\x76\x9c\x34\xf1\x54\x65\x26\xd4\x50\x5e\x50\x10\x40\xb2\x83\xc5\x50\x81\xe0\x0e\x90\xa6\x26\xb7\xa5\x42\x10\xbb\xe5\x34\xc6\x4d\xa6\xef\x47\xdd\xfd\xce\x34\x59\x6f\xe6\x4e\x67\x17\xb0\x4b\xc1\x6f\x06\x85\xa7\xaf\xf7\xd2\x79\xad\xd6\x0c\x37\x3c\x36\x7f\xe0\x5a\x13\x0e\xa8\x5b\xf5\x95\xcc\xcf\xac\x1b\xaa\x93\x66\x92\xec\xa3\xc9\xe6\x48\x73\xdc\xc4\xae\x0b\xef\xb2\x52\x10\xcc\x6d\x8c\x4e\x15\xc3\x02\xe8\xcc\xb6\x14\xda\x27\x2d\xb5\x79\x1b\xfd\x2a\x7d\x06\x18\xb2\xb3\x6a\x51\x7c\x7c\xdb\xc4\xc6\xe7\xbe\x5e\x75\x4f\x61\xd0\xd7\x84\xf2\xd1\x85\x3a\xdd\x46\x80\xc9\x22\xbe\xa9\x4a\xc7\xe0\xef\x93\x98\x46\x69\x30\x04\xaa\x24\x68\x11\x57\xd9\x3a\xaa\x59\xf2\x48\xd5\xc0\x8b\x81\x09\x58\xcb\xa6\xee\xbe\xa7\xea\xab\xef\xf4\x03\x44\x6e\x2a\x3e\x8a\xdb\xc4\x12\xd6\xe6\x0e\xf7\xa6\x4d\x1f\x56\x39\xd8\x4f\xfd\x2f\x3d\xbb\x17\xc1\x44\x4c\xe6\x7a\x8b\x00\x42\x09\x77\xbc\x32\xf2\x88\xfa\x74\x7f\x45\x13\xc4\x63\xd0\x4d\xde\x42\x73\x52\xbc\x4f\x81\x8b\xd9\xf1\xc1\x5f\x7c\x1d\x89\x9a\x86\x6e\x87\x1d\x48\x8f\x39\x2f\xf4\x6d\x84\x7a\xfd\x86\xc2\x0b\xbf\x56\xfc\x22\xc5\x77\xaa\x3a\xd2\x9c\x28\x34\x2d\x7d\x13\x08\x8c\xa7\x5a\x7d\x0d\xdd\x79\x9d\x0c\x73\xc9\xbd\x1b\xac\xcc\xc5\x9d\x01\x44\x52\xe6\x06\x5b\x9a\xb8\x27\xbf\xf7\xd7\x97\x2a\x6e\x9e\x59\xbb\x4a\xd6\x95\x42\x40\xa8\x11\xd1\x2e\xd7\xc5\x47\xb7\x76\xc1\x13\x76\x40\xc3\x92\x02\x7f\xdc\xa9\x94\x05\x61\xca\x7e\x95\xdc\xd6\x0e\x93\xc1\x88\x14\x11\x68\x8f\x44\x51\x01\xe0\x6c\x78\x83\x94\x6a\x5c\x8e\x57\xbe\xe0\x9d\x1f\xf5\x39\xe9\x78\xe5\x46\x65\x76\x91\x71\x63\x0b\x60\xb3\x49\x6e\xda\xd9\x48\x78\xd9\x7e\xf0\xd6\x38\x13\xd8\x4e\x0c\x15\x5e\xa7\x1f\xe9\x05\x6b\xbe\x0e\xce\xe9\xc3\xf5\x56\xeb\x06\x6b\x84\x1c\xd0\xf8\x70\x0c\xd3\x3a\x41\xae\x32\x50\x70\x30\x52\xaf\x37\x9b\xe5\x3a\xe5\x2c\x95\x31\x03\x06\xb0\x6e\xb4\x33\xb0\x2b\xe8\x06\x77\xa7\xfa\xe2\x7b\xb3\x21\xd7\xf9\x71\xea\xeb\xbf\x7e\xfc\xf3\xbf\x3e\xad\x6a\xcf\xc8\xd2\x07\xe5\x99\xd9\xd3\x68\x07\x1b\x9c\xf7\x0a\xd6\x10\xc8\x11\x77\x8a\x1c\x36\x88\x1d\x5e\x17\xb5\x79\x10\xcc\x98\x24\xe9\x7b\x4e\xd6\x56\xad\xc6\x2a\xd2\x04\xb5\xc0\xd5\x0d\xad\xa4\x9d\x61\x30\x98\x4b\xfe\xd8\xd3\x4d\x04\xf3\x0d\xfa\xea\xcd\x90\x20\xb0\x45\x80\xa0\x64\x4b\x52\x45\x58\x61\x8f\xce\xb2\xbe\x2e\xd5\x3b\x7a\x9a\x5b\x7e\x94\xea\x6f\x12\x5b\x51\x46\x47\xf5\xb8\xe9\x7a\x18\xdf\x71\x8b\xe4\x72\x68\x8d\x1c\x02\x36\x53\x53\xf0\x75\xb9\x9d\x63\x92\x66\xd1\xcb\xa6\x15\x8b\x70\x49\xa5\x5e\xb5\x48\x90\x28\xc3\x62\xf9\xb4\x7f\xdf\xb7\xdd\xe7\x23\x5f\x4b\x27\x54\x17\x28\xdb\xa4\xca\x30\x14\x2c\x38\x4d\x56\xae\x3e\x67\xcf\x45\x1a\x93\x65\x63\x14\x0e\x36\xf1\x24\x53\x17\xd4\xee\x84\x5c\xe3\x8b\xf9\x4c\x27\x14\x1a\xd0\x98\x8d\xd1\x3a\x54\x94\xd9\x55\x46\xdd\x0c\xf6\xac\xbf\x92\xd8\x78\x44\xdb\xf0\x66\x31\xcf\x4b\x12\xf5\xcb\x76\xec\x15\x5c\xfa\xc1\x11\x0d\x33\xad\xeb\xdc\xb0\xc8\xaa\x8f\xdb\x32\x64\x53\xd2\x32\x43\xb7\xa9\x5e\x85\x0c\x40\x0c\x7b\xe8\x36\x50\xf9\x2b\x09\xc5\xfb\x2d\xa7\xd2\xdb\x4d\x2e\x6b\xc9\x33\x75\xb5\x2d\x90\xe2\x80\xd9\xfc\xd3\xd1\x17\x1c\xfe\xd9\x5f\xd6\xaf\x4f\x28\xfe\xf6\x0c\x60\x7c\xc8\x1a\x8b\xa4\x92\xc7\x5a\xdc\xd0\xac\x79\x5d\xf8\xc1\x6e\x4b\xcd\x76\x08\x18\xf6\xbc\x09\x96\x14\xa3\x28\x33\xea\xf5\x58\xaa\x32\xbf\xd4\xd5\x37\xd6\x82\x99\x84\x52\x1a\xe2\x97\x17\xdb\xf5\xac\x04\x65\x15\x20\x59\x35\xc5\x76\x8c\xd8\x89\xea\xbf\x43\x53\x13\x55\x3b\x67\xf0\x0f\x5f\x20\x32\x70\x28\xb1\x89\x0f\x1d\xc8\xe3\x9f\xa5\x59\x3b\x0f\x17\x50\x53\x00\xfe\x6d\xf4\xcb\x18\x35\xf1\x21\x99\x31\x40\x6b\x88\xf0\x4f\x92\x1d\x28\xa3\xaa\x97\x95\x95\x9a\x3d\xa4\x86\x6b\x58\xb3\x2d\x3c\x7f\x84\x4e\xa8\x7a\x86\xf7\x1d\x8f\xc0\x18\x04\x2b\x57\x51\xdb\x1a\xf4\xd3\x54\x55\x12\x06\x7e\x1a\xab\x97\xdd\x4b\xe8\x09\x83\x11\x82\xc7\x1c\x37\x70\x7e\x50\x15\x3a\x53\x59\xdd\x32\x28\x9b\xff\x1b\x42\xba\x49\x32\xc8\x89\xf5\xa8\xa7\x2a\xbe\x15\x60\x4b\xbc\xe3\x1c\xdd\xaf\xe6\x07\x8a\xc8\x89\xaf\xd0\x24\xea\x04\x31\x36\xcb\x91\x00\x0f\xf4\xee\x29\xf9\x26\x86\x84\x71\x12\x84\x54\x93\xf7\x4d\x4f\xbe\xe3\xfa\xde\xfa\xa5\xba\x23\xe5\xbd\xb2\x42\x16\xc8\x77\x53\xa9\x6e\x49\x28\xe9\xb6\x19\x4d\xf4\xad\xc6\xf8\x32\x07\xdf\x6e\xe1\xcb\xb6\x5d\x7a\xf2\x2e\xf0\x1e\x90\x91\x1a\x82\x5a\x1f\x8e\xd8\x7f\xf9\xf9\xa7\xbf\x7c\xff\xd3\x7f\x3d\x0d\xd6\x67\xcd\x83\xfb\x60\x2d\x59\xd3\xd0\xb9\x96\x59\xd2\x62\x19\x40\x5f\x5f\x26\x06\x3a\xd3\x57\xc2\x09\xc8\xb7\x5b\x37\x80\x02\x0d\xfe\xdd\x3d\x03\x2e\x4a\x58\xe9\xd3\x22\x37\xf1\x91\xee\xb6\x92\xdd\xfc\x30\x29\x3d\x2d\xb3\xad\x86\x08\x40\xb9\xe9\xea\x47\xad\x02\x54\xed\x6a\x70\x21\x46\x79\x7d\x71\x5b\x42\x8a\x8c\xf5\xf1\xc2\xb8\x19\x7f\x93\xe6\x17\xa6\x31\x98\x71\xa3\x86\x0d\xbb\xc7\xc5\x16\x83\x14\x46\xb1\xa4\x03\xd4\x12\x36\xd9\xd8\xc3\x97\x3c\x21\xb3\x59\xcb\x1f\xe3\x1a\xff\x63\xff\xfa\xa7\x7f\xfb\xe1\xbf\xfe\x74\xfd\xfa\xe7\x7f\x7d\xf6\x0a\x1e\xb9\x84\xa6\x3f\x1d\xd0\xbb\x60\x14\xba\x2e\xd2\x32\x02\x82\x57\x29\x36\x82\x51\xcd\xff\x54\x46\x76\xd3\xbe\x83\x3b\xca\xb7\xf6\xda\xd7\x0e\x91\xc4\x46\x80\xb9\x7b\xe6\xaf\x2f\xa5\xba\xed\xa1\x6b\xeb\x49\x4a\x5b\xbb\xa2\x54\x6d\xae\xf0\x38\xc4\xb7\xc7\xe6\x23\x41\xea\xa0\x7e\x8b\x1a\x88\xc0\x96\x0a\x28\x7d\x66\x39\xa9\x1b\xe8\x65\xc0\xc4\x5a\x8b\x3b\xed\xad\x48\xc8\x49\xcc\xb6\x2e\xfe\xa7\x56\xe4\xf5\xc5\x2c\xa7\x56\x6f\x52\x27\xe1\x91\xfe\x61\x19\xf9\x63\x60\xd6\x8f\x7f\xfe\x8f\xfd\xeb\xbf\xfe\xfc\xf5\xdf\x9f\xfa\xe5\x5f\xde\x61\x60\xff\x55\xd4\xef\x07\xd5\xfa\x49\xbd\x1e\x07\xf2\xbc\xd7\x17\x91\xa6\x27\xa3\x3b\x26\xa3\x90\xfb\x04\x4c\x2a\x94\x98\xc6\x27\x7c\xf0\x2f\xfd\xbb\xe3\xe7\xf1\xc5\x79\xe8\x71\x36\x4a\x21\x90\xd9\xc9\x47\x20\xdc\x97\x97\x06\xe4\x33\xe9\x4d\x1a\xb2\x7e\xfe\xe7\xe6\x0d\xf8\xbf\xfc\x53\x1c\xc0\xe3\x5f\xc9\xf3\xaa\x3d\x5f\x7c\x5d\x8c\x98\x2b\xe1\xe1\x92\x2b\xf0\xc5\xcb\x3c\x6a\xf6\x59\x43\x9c\xf7\x25\x48\xe0\x07\x24\xda\x43\xb7\x7e\xb8\xad\x4a\x04\xf3\x82\x22\x2d\x39\x6a\xf2\xbe\x9c\x32\xe5\x24\xe9\x35\x88\xde\x83\x8f\x98\xc6\x6c\x54\x87\x84\xa0\xff\xfd\xe3\xf9\xed\x71\xf8\x71\xfe\xbd\x4d\xec\xef\x95\x11\x8a\x31\x76\xde\xc4\x46\x7f\x27\xdd\x6f\x73\x3f\x6e\xfd\x78\x96\xe3\xe1\x8e\xc7\xbd\xf0\x13\x20\x60\xc7\x77\x38\xd6\x70\xaa\xe4\x9d\x5c\xf7\xfe\xc8\x15\xf1\xe3\x31\x52\x1d\x7b\x1d\x69\x0c\xb7\xe5\xc0\x54\x78\xc8\xa6\x43\x47\xd5\x76\x4b\xf1\x90\x7c\x0a\x3c\x19\x1f\xec\xfc\x70\x7c\x15\x87\x2e\x71\xe6\x72\xb6\x85\xb0\x52\x65\x10\x65\x8c\x7d\xc1\x65\x11\x86\x81\xbd\x23\xe7\xfa\x1f\xb7\xb9\xc4\x5d\xdf\x5f\xdf\xf9\x60\xbf\x20\x00\xc2\x86\xea\x8b\x4c\xbf\xd0\xfe\xd4\x8c\xad\xcd\xd7\x2e\x55\xdf\x15\x95\x8a\xe8\x7c\xb5\x38\x92\x74\x0e\xee\x2c\x6f\x38\x5c\x10\x2f\xf6\xd9\x5c\x76\x9c\x6a\x6e\x22\xd6\xc4\x33\x4c\xfa\x8e\x7f\x51\x35\xe7\x87\xf3\x88\x3d\x4e\xd9\xfc\x61\x12\x9a\xdb\xd9\xf8\xc6\x7b\x70\xb3\x82\x17\xdf\x8f\xfb\xd9\x2a\x86\x18\x6f\xe3\x63\x68\xf7\xfa\xe3\x9f\xfe\xed\x19\x19\xf2\xc3\x7d\xed\x2b\x41\x6d\xfc\xa1\x71\xf5\xbf\xd7\xd0\x7b\x7d\x69\xf3\xa0\x4f\xf1\xce\x0b\x05\x04\x10\x3b\xa0\x3e\xae\x22\x31\xbd\x2f\x87\x24\xc2\x1b\x69\x84\xd0\x4e\x68\xba\xf3\x3c\x5f\x1f\xce\x85\xe7\xde\xdc\xe5\x6f\x6e\xef\x43\xbd\x9b\x67\x79\xbf\x9e\x1f\x69\xa4\xa7\x94\x55\xb3\x3b\x3a\xb9\x5d\x97\x92\xd5\xd7\x45\xb3\x64\xa3\x5c\x67\x59\x97\x52\x67\x6a\x53\xf8\x61\x69\x53\xfc\xaf\x92\x4b\x92\x96\xaf\x55\xf5\x77\x16\x71\xfa\xdf\xc8\x5b\xf5\x3f\xa5\xcb\x53\xdf\x7c\xa4\x96\x30\xa4\xa6\xd6\x3b\x2c\x5b\xa3\x4a\x3f\x4c\xdd\x7d\x09\x76\x72\x86\x81\x30\x57\x2c\x2a\xe7\x33\x54\x61\x76\x50\x62\x6f\xee\xa5\x8c\xd4\x59\xa6\xbc\xfb\x8e\x63\x7c\x3a\x9c\xdc\x51\x42\xa3\x2d\xb5\x49\x90\x19\xa2\x47\x22\x96\x04\x2c\x22\xb3\x27\xb1\x0d\x97\x86\x99\x0b\xc3\x74\x19\xcc\x7c\x11\x6c\xe0\x36\xfe\x56\xa0\xc2\xd3\x99\xee\xab\x75\x97\x56\x23\xeb\x3a\x25\xf9\xf6\xad\x69\x94\xbd\xe6\x24\x10\x4c\x90\xe6\x77\x83\x4c\x03\xab\x61\x6b\x0b\xc6\x83\x3a\x92\xea\xc5\x37\x14\x98\xf1\x1b\x48\x26\x21\x59\xd5\x40\xef\x81\x30\x53\x27\x65\x90\xe8\x4e\xbb\xdd\x7f\x22\x96\xbe\x19\xab\x2b\x98\xb1\xf9\x52\xf7\x4e\x65\x7d\xdd\x47\xc8\x35\xfa\x06\xa1\x2c\x0e\x07\x8d\x90\x6c\xcd\xd2\x48\x94\xcf\x51\x4a\xbf\x02\xe5\xd1\x6b\x2a\x8d\xd2\x25\xaa\x49\x33\x55\x66\xf5\x30\xb1\x63\x6b\x82\x1c\x67\x39\x2c\xff\x9e\xb9\xdb\x55\x90\xe9\x0f\xbf\x09\x94\x7c\xcd\xfb\x86\xa7\x59\x79\xc3\x9a\xcf\xed\x03\x7a\xfe\x69\x19\xfc\xc3\x25\x16\x68\xdf\xac\xbb\x31\x11\xef\xce\x75\x0b\xf7\x21\xb9\xd3\x5c\x7b\xd2\xa9\x2b\xf4\x3a\x65\xa4\xb9\x29\x0b\xe6\x47\xaa\x99\xbe\x46\x19\x7b\xcd\x20\x8b\x28\x08\xa6\x2f\x0d\x2e\xb5\xda\x99\x30\x45\xc8\xe7\x88\x51\x48\x23\x11\x35\x4b\x11\x21\x8a\xdb\x10\xf1\x21\xdc\x99\xef\x28\x68\x1a\x96\xe2\xcf\x49\x48\x91\xf8\x2d\x29\xa3\x01\x4b\x93\xcc\xad\xde\x17\x54\x44\xf6\x67\x49\x02\xda\xc9\x1a\xda\xae\x27\x1f\x04\x18\xd5\xf6\x65\x26\x2b\xfb\xd2\x90\xcf\xbc\xd0\x1d\xb1\xba\x2d\x93\x99\x41\x38\x2e\x48\xea\xba\xe7\xcd\x0e\x84\xe6\x75\xe9\xac\x48\x4e\xe2\x43\x1c\x69\xd1\x33\x25\x1b\xba\xb7\x4c\xa2\x5a\xde\x01\xfb\x63\x25\x17\xba\x5b\xd4\x5f\x6d\x32\xb1\xd4\xca\x66\x7d\x26\xeb\xa9\xf9\x90\xa9\x79\x23\xf7\x42\x4b\xa8\xf6\x16\x55\x24\x21\x35\x27\x7a\x70\x55\x78\x8b\x4b\xfd\xd8\xe8\xfe\xfe\xc7\xfd\xfb\xbf\xfe\xe9\xdf\x7e\x78\x9f\x80\xb5\x9f\x98\xc4\x51\x46\x6a\x48\x48\xf9\xb0\x2e\x92\x5a\xdb\x97\xde\xc1\x04\x44\xe2\x86\x23\xa1\x84\x07\x30\x0e\xb2\x2f\x20\xd2\x74\xdf\x72\x48\x2a\xbb\xb5\xd4\xd5\x67\xf1\x48\x6d\x28\x56\x8a\xc6\x60\xb2\x28\xd6\x09\x5f\xbf\xf1\x61\x26\xbc\xb9\x06\xe0\xd1\x42\xd2\x63\x7f\x9c\x69\x1c\xf8\xad\x6c\x1d\xb1\x22\x29\xa1\xf0\xb0\x8f\xe0\x8f\xc4\xac\x85\xae\x54\x37\x26\xb6\x10\x97\x25\x5f\x46\xd9\x11\x19\x94\xb6\x2f\x64\xd0\xf0\xb5\x84\xa1\x54\xdf\xaa\x4b\xca\xc8\x95\x35\xac\x61\xf1\xa2\xb1\x20\xb5\x18\x47\x60\x0f\xf1\x45\x67\x26\xf3\x37\xb3\x97\x4c\x40\x4b\x41\x9d\xdd\x26\x13\xdc\x6e\xa0\xc9\xde\x90\xe0\x45\xe0\x7b\x10\xa3\xe2\x17\x46\x46\x9b\x52\x43\x52\x34\x19\x6a\xed\x7a\x3a\xc7\x9b\x81\x73\x83\xec\x29\x94\xba\x68\x47\x18\xd5\x1a\x1e\xb5\xed\x8b\xb5\xe6\x56\xfe\x4a\xbd\x76\x32\x5c\x29\x63\xbe\xb5\xa4\xe2\xf6\xab\x64\x90\x28\x0c\x49\x14\xff\xc9\x63\x83\x12\x70\x69\xee\x0d\xa5\x6a\x9b\x15\x24\xf1\x67\xaa\x72\x50\x0e\x70\x67\x41\xc2\x4e\x5e\x2f\x6e\xaa\x83\xd3\x38\x6f\x13\x69\xda\x91\x7a\xc5\x0b\xaf\x5c\x3d\xa9\x62\x2b\x8d\x48\xbf\xd1\x93\xb5\x6d\x11\x3b\xc4\xda\xfc\x7e\x4a\x63\x2c\x18\xe0\x21\x6e\x43\x95\x14\xe4\x60\xca\x98\x1c\xa3\x1b\xc9\x70\x41\xd9\x6a\x03\x01\x13\xe9\xb2\x33\xb4\xd6\x37\x90\x1b\x62\x12\xef\xc8\x3e\x00\x57\xe3\x9e\x00\xdc\xd6\x4d\x72\x45\x06\x58\x47\xa1\xd6\x9a\xfa\x6e\xac\x23\x95\x92\x53\xb3\x4d\xc9\xf2\x4b\xb6\x05\xf7\xff\x75\x12\xda\x53\xf2\x56\x20\xb0\x97\x46\x4e\xa5\xdb\x3f\x25\x3f\xe1\xfe\xd7\x7f\xff\x7e\x7d\x32\x1a\xfb\x87\xd4\x69\xa5\x24\xcd\x7d\x1d\xc8\x70\x30\x9d\x46\x05\x38\x2c\xa7\xcd\xc7\x1f\x08\xc5\xdd\xba\x0e\xde\x34\x48\x18\xa8\x7f\xc5\x84\x6e\xd9\x97\xe9\x96\x86\xcf\x0c\xd8\x1c\x9a\x23\x7c\xe4\x6e\x39\x94\x16\xa5\x8d\x9b\x4a\xdd\x7a\x94\x5f\xbb\xad\xf4\xa5\xee\x53\xd2\xcc\xee\x7e\x48\x06\xb4\x6a\x82\xbc\x66\x60\xfa\x24\x44\x61\x50\xb2\x1a\x8c\x62\x57\x2d\xe5\xb6\x14\x2d\x57\x33\x8b\xaa\x60\xb3\x72\x5b\xaa\x80\x05\xc1\xdd\x69\xee\xe0\x41\x5f\x58\xb1\x02\xdd\xa9\x67\x62\x61\x28\x97\xad\x8f\x04\x89\xf7\xa4\x9f\xa8\x63\xa0\x47\xdf\x5f\x11\xcb\x9d\xf0\xd1\x97\xb3\x0a\x90\xa6\x0c\xf2\xce\x12\x9a\x90\x91\x3b\xd8\xb8\xb0\xd1\x80\xa5\x60\x03\x08\x75\xe4\x0e\xcb\x61\x29\x33\x71\x35\x36\xc7\x55\x6b\xbf\xc9\x2c\xd4\x7c\x37\x6d\xd7\x45\x06\x58\x3f\x88\x6c\x95\x8c\x5d\x0e\x5c\x33\x30\x12\x46\x07\x5d\xcf\x32\x2b\xd6\x62\xfc\x14\x09\x8e\xb2\xdb\x22\xad\x5e\xc5\xf2\x6d\x29\xec\x29\xdf\x8a\x63\x91\x84\x47\x0d\x09\x79\x24\x82\x38\xed\x03\x1d\xe0\xab\x76\x9b\x49\x52\x88\x81\xd5\x1d\x96\x64\xcd\xbe\x20\xfc\xd3\xc5\x92\xd7\x9f\xfe\xfc\xaf\xdf\x7d\xfd\xf9\xe7\x9f\xfe\xf3\x5d\xd2\xfb\xfe\x04\x82\xeb\x6d\x9c\x0e\x00\x48\xdf\x0f\x41\xc7\xca\x60\xbd\xd5\x93\xc7\xfe\xd4\xed\xe1\xbb\x89\xbc\x80\x9b\xa6\x7e\x58\x25\x9b\x3d\x2c\x54\xb8\x94\xf5\x81\x91\x9e\x1c\x1a\x5a\xc6\xaf\xc4\x1c\x6b\x19\x7e\xca\x86\xd4\x0f\x96\xc7\x8f\x87\xf0\xc3\x63\x3f\x4b\x1f\xf4\x27\xda\xa3\xb7\x0f\x2d\xb9\x50\x0f\x13\xc4\xb3\x33\x70\xa8\x5a\x78\x1f\xdf\x60\x2a\x98\xef\x96\x3a\xf9\x7d\x93\x26\xe4\xae\x8a\x30\xdd\xb3\xae\xab\x77\xe4\xa1\xe8\x7e\x6a\x13\x1d\x22\xed\x92\x57\xef\x41\x74\x34\x12\x1d\x88\x28\x7f\x82\x72\x7c\x78\xe8\xf7\x54\xca\xfb\x33\x01\xd0\xa3\x72\xfb\xc1\x9c\xf1\xcd\xca\x10\x7f\x18\xe2\xbd\xc2\xa8\x60\xf7\x40\x6f\xb3\x52\x1d\x9f\x59\x62\x3c\xd0\x82\x87\xe2\xeb\x05\xf3\xce\xca\x03\x80\x16\x13\xff\x94\x1a\x18\x7a\x28\x02\xa0\x13\x4d\x5f\xd1\xc3\xbf\xa9\xaa\xe4\xe1\xa9\xdf\x95\x04\xef\xcf\xa9\xc7\xc7\xc7\x76\x63\xac\x9c\x3c\x3b\x27\xac\x7e\xc0\xff\x2a\xe0\xa3\x22\x5d\x18\x5d\x38\x01\x01\x15\x86\xf1\x4d\x41\xfc\xa1\xbf\xb6\xea\x07\xfd\xc7\xee\x53\xe1\x4c\xd8\x81\x61\x5d\xe3\x6a\x04\x1a\x45\xf7\x7d\xf2\xd4\x5f\xff\xf2\x97\xe7\x72\xff\xfe\x4c\xfe\xf2\xa0\xc6\x62\xd3\x6d\x2b\x21\x5c\x2e\x84\x78\x7c\xa9\xc6\x3b\xe3\x30\x6f\x91\x7b\x95\xd9\x80\x8c\x44\xaf\x80\x70\xc9\x9d\x24\x66\x38\x05\xbf\x06\x0c\x11\x68\x1e\xdb\x90\xfb\x06\x4f\x87\x1f\x03\x72\x7a\x22\xd1\x2c\x4b\x52\x50\xa3\x94\x9e\x14\x96\x5c\xe9\xa9\x02\x20\xa1\x48\x76\x5b\xb2\x5e\xc0\x7a\x27\xbe\x2b\x8f\xe2\x3f\x03\xdf\x80\x4d\xd8\x7b\x05\x41\x79\xd0\xca\xf9\xef\xa5\x82\x05\xcf\x92\x15\xf0\x7a\xba\x21\xd7\xf9\x1b\xd7\x49\x41\xca\xfe\xb2\x21\x75\xe8\x96\x62\xd8\x45\x4b\x9f\x84\xd1\x80\x8c\x1d\x79\xfa\x06\x24\x3d\x13\xcc\x9a\x49\x17\xa9\x05\x70\x09\x55\xdb\xa5\x22\xb0\x06\x4e\x70\xd2\x61\x62\xf4\xb7\x23\x42\xea\x06\x9f\xbb\x5d\xbd\x12\x74\x22\x36\x36\x00\xc4\x2b\x6d\x4e\x77\x08\xa8\xbf\xc4\x8a\x52\xe6\xa8\xfc\x59\x67\xf2\xed\xb8\xf6\xad\xd3\x97\xd7\x0a\x3a\xf1\x8d\xcc\xa4\xdc\xa6\xf6\xf8\x09\x9c\x4c\x8a\x88\xc2\x1e\x3f\x3f\x1c\x1e\xff\xf9\xe3\x9f\xff\xe5\xa7\xff\x7c\xaa\x39\xed\xcf\xd9\xc3\x3b\xe6\xb9\x0d\x4d\xd5\xf7\xcb\x56\x65\x5d\xfc\xb7\x59\x6e\xb5\xf6\x6b\x1b\xfa\x8a\x6f\x45\x3b\xe0\x80\xf3\xea\x5f\xdf\x2a\xea\x2f\x5a\x2b\x3c\xad\x8f\x46\xd1\x29\xd1\x7a\x6b\x4d\xae\x33\xf7\xf8\xde\x87\xe1\x6d\xe9\xbe\xb7\xcf\xdc\x6f\xad\x7d\xbc\x7a\x7f\xfd\xf3\xbf\xfc\xfc\xd3\x8f\x4f\x24\x90\xfd\x23\x09\xed\x32\x21\xbc\x65\xc1\x41\xd3\x83\xaa\x6f\x27\x47\x2b\x29\x19\xef\x1f\xef\xdf\xc3\x63\xe6\x27\x42\xcc\x70\x4e\x7c\x38\xbe\x7b\x7d\x99\xee\x18\x3f\x34\x7f\x34\x7e\x36\x7d\x36\x7c\x36\x7b\xc4\x31\xe2\xc2\x47\xd3\xe7\xc7\xfb\x11\xc0\xcd\x01\x02\x01\xdc\x40\xf7\x61\x9b\x77\x8c\x2b\xbd\x2d\x85\x50\x3c\xf8\x99\x33\x10\x88\xf0\x33\xfd\xa8\x0b\x62\x0f\x96\xc1\xd8\xdb\xed\xc6\x83\x0b\xca\xea\xbb\xee\xf8\x0e\x71\x1c\x4b\xa3\xfa\xbb\x6d\x24\xb7\x08\x06\xd9\x3e\x68\x3a\x99\x5e\x97\x5e\x7d\x09\xee\xc7\xb5\x70\x79\x23\x65\xbd\xb7\xff\xe6\x32\xaa\xfd\xea\x83\xfd\x83\x33\x0e\x10\x44\xd7\xfb\x79\xeb\x22\x09\xa7\xf6\x72\x40\x52\xfa\x80\xc3\x67\x9a\xfa\xb8\xb5\xd6\xae\xd3\x5d\xd8\xe9\xbe\xad\xd6\xba\x11\x24\x55\x41\x25\x16\xaa\xd1\x0d\x58\xa3\x4a\x14\x9f\xa2\x4e\x46\x7a\x6a\x25\xe1\x8f\xbb\xb8\xcf\x46\x7d\xe5\xee\x46\x1c\x70\x0d\xe4\x9d\x05\xd9\x1a\x61\x9d\x6d\xed\x40\x8a\xeb\x36\xab\x77\x97\x66\x49\x45\x77\x04\x3b\x8b\xfa\x97\xfe\x1d\x90\x0b\x9a\x7d\xa7\x02\xe2\x17\x8b\x44\xd4\x82\xf6\xd6\xdf\xbc\x9b\xcf\x9f\xfe\x78\x39\xc6\x97\xe3\x36\xbe\x26\x46\xe5\x2c\x11\xd2\xa6\x08\x62\x66\xc6\x11\x3e\xde\xf6\x7e\xfc\xf3\x5f\x9f\x12\xae\xfd\x4c\x13\xb6\x66\x6e\xa8\x56\x66\x73\xe4\x08\x86\xd1\x12\x1f\x91\xec\x87\x3d\x4d\xe7\x72\x03\x4b\x94\xcc\x24\xf5\x2a\xf9\xf5\xa5\xfb\x72\x24\x42\xde\xe8\x83\xea\xb8\xdd\x6d\x77\x16\x9b\x88\x60\x53\xd0\x8d\x15\x1b\xbe\x63\xbf\xbe\xd8\x9c\xa9\xb9\xe9\x07\x78\x75\x43\xfe\x29\x22\x90\x47\x22\x1b\x10\xfd\x48\x2a\x59\x58\x92\x71\x9b\x8a\x82\x03\x42\x03\x3a\x7d\x71\xf1\x55\xd1\x92\xa6\xbe\x6b\x6a\x20\x08\x2b\x91\x8a\x29\x37\xdb\x7d\x4c\x31\x11\xa3\xf0\xd9\x6b\x49\xc6\x61\x31\x30\x74\x8a\x37\x29\x48\xd3\x73\x92\xc2\x8f\x33\x46\x0f\xf3\xc9\x1d\x1f\x69\x71\x70\x33\x40\x96\x29\x90\xff\x24\x48\x3d\xe2\x13\x04\x21\x0f\x2a\x8d\x65\x4c\xc4\xd4\xd1\x17\xc8\xf6\xf4\xb4\x0c\xdb\x06\x68\x03\x15\xb0\x7d\xed\x91\x51\x2b\x4c\x77\x11\x24\xee\xbf\x27\x7a\x44\xcc\x01\x8d\x90\x66\x47\x3f\x4b\x06\xd9\x2f\xf6\x69\x60\x0d\x66\x14\x3b\x14\xd6\x0e\xe1\x66\x48\x25\x65\x49\x82\xf9\xa0\xb3\x6c\xb7\x11\x67\xcb\xd0\x39\x0a\x24\x5a\xc4\xe2\xcc\xbb\x0a\x4e\xbf\x3f\x9b\xa4\x96\x30\x9d\x40\x80\x34\x4f\x35\x12\x0c\x99\x9a\x50\xba\xf8\x85\xc2\x84\x60\x7a\x15\xb0\xa8\x4a\xa8\x88\xee\x23\x55\xd9\xad\x25\xed\x90\xfa\x23\xae\x3f\xef\x05\x49\x3c\xbe\x4c\x82\xd6\x19\xd4\xc9\x24\x66\x10\x4b\x8c\x45\xb4\x9b\xbb\xdd\x15\x9a\xf1\x28\xd7\x40\xec\x50\xd2\x41\x23\x8e\x70\x22\x56\xd3\xce\x3e\x07\x09\xee\x32\xb0\xe7\x92\x3f\xa6\xc6\xb0\xbe\x04\x29\x28\x09\xb6\xe9\x69\x5a\x30\x42\xa0\xa7\xe0\x56\xe3\x8d\xb8\xdf\xbd\x94\xea\x96\x02\x16\x6a\x7a\xc8\xb1\x1c\x07\xf6\xa3\xb2\x10\x0b\x17\x08\x92\x59\xb0\xab\x22\x4e\x29\xe7\xe0\x75\x53\x0d\x9e\x8d\x94\x0d\x4c\x36\x3d\x8d\xc8\xc3\x12\xd9\x51\x0e\x56\x50\x33\x36\x08\x8d\x16\xeb\xee\xf1\x93\xa7\x36\x07\x3a\x9f\x94\x8f\xe6\xef\x98\x31\xf0\xed\x84\xf8\x83\x7e\x6c\xb2\x2e\x52\x53\xec\x29\x7a\xb0\xd7\x1f\x73\x6a\xbb\x33\x95\xd7\x2f\x41\x2b\xcb\xf4\x29\xf8\x8f\x06\x89\xc0\x91\xfc\x68\x2c\x8b\x0b\x4a\xe4\x1d\x6f\x76\xf1\x61\x5d\x3a\xaa\x50\x32\xf0\xeb\x9a\xc4\xcd\x6f\xbf\xd7\xa3\x4f\xd9\xbb\xb6\xbb\xe5\xea\xaf\x64\xba\x6d\xab\x39\x8d\xcd\x6f\x93\x21\x08\x26\x1b\x18\xee\x67\x67\xce\xc8\x82\x2e\x8d\xb1\xf6\x10\x99\x3d\xab\x07\xbf\x04\x36\xdf\xc7\x0a\x98\x70\x0d\x81\x73\x60\xf5\x67\x42\xf8\x25\x29\xfd\x90\x1d\x70\xa4\x09\xd8\x9c\x1b\xda\x0d\xfc\xd8\x90\xab\x4a\xd6\xfc\x5e\xfd\x5d\x90\x8b\x5c\x3a\xc7\x9c\x74\xf2\x7b\x89\xb2\xd8\xcd\xe7\xf9\xb8\x9b\x54\x00\x06\x12\xfe\x53\x90\x1e\x3d\x08\xf1\xa9\x10\x0e\xc2\xa2\x72\xac\x53\x87\x7a\x04\xea\x0d\x90\x62\x29\x4c\xcb\xf8\x44\xd9\x17\x54\x7c\x82\x0b\x18\xa5\x3b\xf0\xf7\x10\x4c\xb2\xd4\x89\x7e\x27\x95\x5c\xf2\xd7\x0b\x1b\x0f\x63\x8c\x79\xb1\x1a\xf1\xc1\x76\x12\xc5\x23\xa6\xb4\x33\x74\x3b\xc2\x68\x68\x76\x61\xa4\xaa\x25\x92\x34\x2f\x18\xce\x7c\xd5\x45\x48\xe9\x3e\x12\x47\x91\x2f\x19\x0c\x80\x73\xf8\x60\x81\x9a\x10\xfd\x32\xde\x8b\xb5\x34\x7d\x1e\x24\x1d\xa9\xa4\xda\xb6\xc2\xf8\x23\x48\xab\xa3\x6b\xa8\xf6\x40\xfc\x25\x16\xe9\xd6\xb6\x7a\x2a\x10\xe9\xd8\xb9\xee\x21\x95\x0f\x0f\xb6\x1c\x52\xc7\x16\x35\x60\x42\xae\x37\x06\x6c\x6c\x30\x11\x83\x6e\xe2\x50\xb5\x8d\xc1\x51\xbf\xb7\x42\x74\x99\x1b\xcf\x7b\x8f\xf8\x79\x41\x36\xa4\x27\xea\x3f\xa7\x11\x0a\x06\xd2\xf8\x3a\x7c\xa8\x69\x6a\x9b\x6f\xef\x24\x90\xdd\x71\x2f\x3c\x73\x01\xc1\x16\x22\xc7\xa8\xb3\xc2\x8d\xf4\x34\xfa\xa6\x96\x6c\xb8\xe3\xe0\xee\x85\x02\xaf\x86\xb2\x1e\xbc\x9b\x18\x61\x8b\xbb\xf4\x51\x51\xdd\x62\x01\xd0\x98\x64\x1b\x42\xe0\x20\x8d\xee\x9d\xe5\x93\x33\x6f\x04\xcc\x36\xd4\x7b\x1c\x84\x34\xb3\xbb\xf7\x87\x67\x11\x80\xb5\x00\xaa\xf2\x0d\xad\x93\x10\xae\x46\x4c\xff\x5e\x47\x89\x02\xf8\x06\x7c\x74\xd5\x8b\x5f\xaa\xe3\x91\x60\x49\x70\x83\x40\xe6\x85\x33\xa3\x6f\x1a\xe1\xe1\xe6\x8b\x52\x4e\x9d\x35\x2f\xc1\x27\x8d\xf7\xe3\xe6\x85\x25\x62\x74\x6a\x9a\xd5\x87\xb0\x7f\xd5\x4e\x2b\xd8\x0d\xa4\x9d\x2c\xd8\x95\x86\x41\x70\xca\xba\x81\x08\x7a\xbb\x63\xff\x2f\xa9\x60\xbe\x48\xe8\x50\xfb\xba\xda\x13\x12\x4e\x67\x70\x7f\xe3\x40\x42\x28\x73\xc7\x86\x9a\x5f\x5f\x46\x03\x1a\x1e\x21\x1f\x18\x1d\x51\xd4\xca\xcd\x1e\x19\xa6\x6d\x81\x4d\xe8\x37\xbd\xfb\x56\x79\xd9\x7d\xd4\x6c\x94\x34\x44\xb9\x21\x26\xae\xa5\x91\xd4\x7b\x3b\xa9\x3f\xd4\xf4\xb9\x56\x32\x0a\xf3\xd8\x51\x68\xad\x73\x88\xb4\xed\x28\xee\x72\x83\xa5\x32\xb0\x13\x06\xcd\xc2\x85\x1f\x6b\xe1\xf2\xb8\x9e\x62\xec\xb7\xc3\x5e\x6a\x69\x99\xbb\x61\x81\xdb\x0a\x2f\x9f\xdd\xf6\x47\xe0\x76\x6e\x92\x24\xcd\x24\xfe\x8b\xee\x33\xf5\x28\x4a\x6f\x9c\x17\x12\x53\xbf\x7c\x61\x3d\xac\x96\x1d\xf7\x78\xc8\x74\xd4\x48\x7c\x72\xd7\xc3\xa2\x78\xa1\xfe\x86\x44\xdd\x22\xfe\xdc\x0e\xb8\xa3\xd4\xd3\x6b\xb1\xc8\x2d\x4c\x86\x30\x99\xf9\x63\x71\x52\x2b\x21\xf6\xd7\x90\x59\x08\x0d\x8b\xc1\x31\x0b\xdc\xef\xb1\x65\xaa\x9d\x9b\x9f\xd6\x23\x59\x47\x7b\xa0\xa7\x63\x85\x46\x17\xe5\x44\xd1\x46\xc6\x52\x17\x89\x34\x30\x66\x1b\x97\x71\x5f\xb6\x99\x59\xde\x8f\x94\x53\x3e\x72\x91\x3a\x4e\x26\x79\xa6\x77\x11\x0c\x63\xcc\x1d\x74\xfa\xa5\xa5\xe2\x4b\x9c\xcc\x04\x70\x19\x89\xb5\x6b\x4e\x33\xd8\x14\x69\x9e\xd9\xb9\xbb\xfa\xda\x3f\xc3\x24\xf3\x39\x46\x1a\x7a\x9f\x62\x05\xb1\x74\x08\x9c\x20\x93\xe6\x36\x1b\xd9\xeb\x7d\x16\x11\x8f\x04\x6b\x10\xd8\x48\xca\x8d\x14\x9f\x7c\xa2\x9b\xc1\x70\x74\x0f\x0a\xef\xab\x0a\x92\xb2\xb0\xea\x11\xdd\x6e\x94\xa4\xd6\xa0\x71\xc0\x54\x2b\xb0\x97\x8e\x38\xa8\x91\x8a\xdf\x7b\x69\xc3\xda\x82\xdc\x72\xec\x3c\x63\xa7\x2d\xdc\x77\x62\xeb\x0f\x53\x06\x24\xe7\x97\x58\x1f\x07\xd4\x5c\xa8\x76\xac\x6d\xe3\x0e\x1a\x9c\x01\x20\x83\x64\x26\x29\x4a\xbe\x97\x86\xa2\x05\xd5\x60\xde\x54\x23\xdf\xe5\x52\xdc\xb1\x68\x09\xdc\x99\xbe\x58\x1b\x44\x0a\xfa\xc9\x69\x29\x13\xe5\xb3\x9a\xd1\x27\x1b\xaa\x22\x64\x62\x9d\x9f\x49\xdd\x50\x6d\x54\x1e\x80\x0c\x6e\xa6\x5d\x37\xa3\x58\xd2\x57\x18\x12\x9c\x99\x2f\x67\xfe\x32\xb3\x37\xa7\x25\x15\xa4\xa6\x8a\x6e\x24\xec\xc2\x82\xa8\x34\x21\xfa\xf0\x8d\xb9\x89\x2f\x15\xb5\x5c\x36\x11\x86\x72\xc4\x27\xe7\x24\x75\x17\xca\x42\x20\xa8\x9d\x7d\x9d\x9a\x08\x89\x4a\x25\x3c\x0b\xe1\x1c\x26\x56\x15\xdc\x6b\x49\x65\xab\x06\xb9\x98\x16\x8e\x85\x9b\x89\x6e\xd9\x6d\xac\x45\x4a\x93\x53\x88\x02\xf7\x1c\xa0\xa5\x87\xfb\x33\x69\x84\xaa\x94\xcd\xe2\x49\x59\x92\x2b\x03\xc5\xd2\x75\x26\xf6\xb6\x34\xdb\x99\xc1\x93\x09\x00\x73\x99\xe9\x88\xc6\xb3\xa6\x99\xb3\x27\xd3\x84\x93\x1c\xe2\x1c\x5f\xa2\x70\x1b\x69\x76\x68\xf0\xa1\xda\x99\x4a\x06\xfb\xc2\x98\x18\xb5\xc0\xb9\x78\xa6\x83\xc2\x3b\x9c\x24\x1a\xc3\xf7\x00\x46\xe6\x62\xc9\xa1\xef\x86\x05\x95\x22\x8d\xd9\xf7\xa5\x4c\xdf\x3c\x67\xc7\xa8\xe9\xac\x00\x98\x9c\x24\xac\x63\x09\x74\x08\x34\xe8\xcc\xf6\x41\x91\x87\xad\x22\x17\x0a\x08\x04\xe7\x51\x3e\x44\x1f\xd0\xbd\x23\xf5\x1e\x53\x07\x79\x1c\xa2\xa6\x7d\x5c\x61\x96\x4a\xac\x24\x28\xbe\x85\xbb\x03\x7f\x65\xc0\xe5\xf0\xfd\xed\x42\xe3\x19\xfd\x8e\x07\x4d\x81\xbf\xd8\x85\x30\x74\x58\x99\xf9\x5c\x29\x18\x60\xde\x23\x63\x63\xfb\x69\x50\x7e\x02\x44\xfe\xf1\xfb\xef\xdf\x09\x8c\xbe\x85\x89\xa2\x6e\x4b\x93\x82\x1f\xa4\xe4\x54\xe6\x00\x0b\x09\x48\x70\xb9\x64\xc6\x74\x0e\x64\x1f\x9e\x67\xa7\x84\xca\x70\xeb\x96\x34\x20\xe5\x80\x24\x2d\x52\x20\x6f\x9a\xa0\xea\x02\x1b\x21\xa7\x82\xae\xae\xf9\x90\x22\xa8\x2d\x55\x7d\x7d\x19\x36\x11\x71\x76\xe3\xae\x80\x7d\x0e\x62\x30\x8b\x61\x72\xb9\xad\x81\xda\x36\x63\x6d\x3e\x16\x55\x95\x23\x2e\x89\x24\x1b\xdf\x02\x4d\x2f\x21\xaa\xd1\x17\x76\x7a\x4d\x7c\x77\x85\x30\x22\xec\x39\x60\xae\x1d\x72\xe1\xaa\x51\xc6\x6a\xc0\x0a\x15\xa4\xb8\x40\xf0\xed\xb3\xdb\x6d\x8e\x6e\x9a\x06\xd8\x86\x35\xa2\xa8\x5a\x4a\x42\x75\x1f\x62\xaf\x08\x92\x62\x96\x8c\xb6\x13\xdb\xab\xdd\x57\x4c\x7f\xbe\x96\x5b\x1a\x08\x8e\x88\x7b\x96\xcd\x1f\xd0\xff\x4a\x81\x28\x9d\xf0\x8a\x81\x92\xc6\x28\x6d\x73\xf3\x95\x1f\x70\x5b\xff\x0f\x99\xd1\x96\xb4\x02\xee\xd8\x60\x15\xf4\xee\x9d\x10\x96\x3a\xb6\x59\x4d\xf2\xfa\x22\x9a\xdd\xb8\x46\x7a\xd6\xcf\x6d\x30\x29\x81\x84\xda\x96\xde\x4e\x65\x0e\xf7\x16\xf8\xa6\xba\x2f\x21\x6e\xc3\x0d\xdd\x7c\x69\x6b\x50\xc4\x04\x45\x00\x40\x97\x40\xac\x00\x09\x55\xfb\x6e\x47\x72\xd2\x9f\x05\xa0\x62\x88\x84\x28\x96\xff\x32\x53\x91\x4c\xdc\x39\x4d\x09\x0d\x57\x97\x7e\x04\x61\x37\xd4\x84\x41\xa1\x24\x87\x48\x26\xc4\x57\xb8\x99\x37\x84\x4f\x2a\xde\xbd\xbf\xd1\x59\x69\xc3\xb5\xd8\x19\x68\xd2\xa3\xca\xb5\x26\xc8\x8f\x74\x02\xa4\x74\x6f\x93\x1b\x2f\x9e\x79\xa7\x4f\x55\x83\xfd\x18\x9e\x36\xfe\xd2\x2e\xbb\xd2\x57\xf9\xe7\x45\xe0\xfd\xc7\xbf\xfd\xaf\xbf\x3c\x4f\xe4\x3b\x16\x54\xba\x41\xe1\x94\x18\x5b\x84\x47\x26\x9d\xcb\x01\x85\x07\xbc\x02\x83\x54\x0d\xb6\x45\x2b\xfb\x02\x70\x99\x02\xb5\x5e\x92\x16\xc4\xee\x3b\x29\x60\x18\x38\x38\xcc\x61\x37\x02\xda\x61\x15\x09\xf7\x4c\x04\xef\x3a\x78\x2e\x53\xef\x11\xb3\x43\xc9\xd4\x8e\x40\x0f\x20\x4d\x23\xd6\x75\xb0\x07\x4f\xbc\x16\x51\xf7\xae\x73\x14\x84\x2b\x4b\x2e\x3a\x48\x15\x60\xb2\xb1\x64\x03\xb9\x94\x46\x7b\x74\x68\x72\x4f\x38\xca\x44\x0f\xa3\xef\x02\x64\xd0\x17\x16\x3a\x22\x14\x82\x04\x38\x37\x18\x6f\x34\x32\x13\xf0\xe2\x32\x6a\x6a\x80\x83\xf7\x0d\xd1\x67\xe1\x09\xa6\x36\x45\x69\x08\xfd\x22\x54\x54\xc4\x9e\x6b\x6d\x0b\xd3\x06\x75\x35\x44\xa8\x4f\x86\xae\x5a\x2c\x76\x95\xe0\xb0\xa3\x7e\x1c\x5b\x2b\xf0\x44\x95\x3c\xd5\x74\xec\xc0\xeb\xd1\xe2\x2f\xb5\x20\x7a\xc4\xd2\xdc\xa8\x9d\xcf\x87\xd6\x1c\x6b\x27\x27\x09\xc6\x17\xa9\xf0\xb2\xa6\x90\xa3\xe9\xb2\x75\x43\xae\x27\x07\x73\x10\xf6\x45\x84\xad\xc6\x00\x1e\x0a\xf2\x63\x49\x02\x51\x54\x41\x9b\x40\x92\xac\x4a\x82\x1e\x8e\xbb\x08\xc9\x47\xfa\x3f\x62\x26\x39\x45\x85\xeb\xc8\x1b\xa2\xe0\x74\x56\xf3\xa1\x11\x44\xad\x12\x4c\xbc\xd8\xdb\xb5\xde\xb1\xbd\x8a\xb0\x20\x42\x71\x9d\x72\x05\x9d\x01\xa1\x9a\xc1\xe4\x0e\x67\x78\xa0\xac\xd5\x3d\x9e\x3a\x13\xef\x86\x37\xc3\x7b\xe1\xad\xf0\x4e\xb0\xb0\x8e\x7c\xd9\x7c\x88\xa1\x19\xef\x35\xde\x05\x6f\x82\x16\x86\x32\x5c\x10\x78\x5f\xbf\x8b\x1a\x51\x1f\xde\x05\x4c\xd5\x78\x92\x6d\x64\x66\x9d\x88\x74\xf9\x84\x58\xfb\xa7\xbf\xfe\xfc\x1f\xdb\x5f\xbf\xfe\xfc\x34\xeb\xc6\x33\x55\xe9\xa3\x2e\x48\x76\x87\x2e\x2b\xf6\x95\x59\xb6\xca\xd4\x2d\x0c\x6f\x28\x45\x5e\x97\x0e\xc5\x39\xf4\x67\xa8\x07\xf6\xc3\xf3\xb1\x7e\x5b\x44\xe0\xbc\x2d\xa8\xf5\x17\x48\x91\x5b\x55\x77\xd2\xb5\xc1\x4f\x37\xae\x70\xfd\x0b\x4b\x37\x59\x29\xd9\xe9\x06\xa0\xfe\x29\xc2\xd1\xc6\x3f\x4f\xd9\x10\xe1\xa4\xc1\x84\xfb\x80\xa7\x0b\xd9\x94\x02\xc7\x03\x13\xe2\xa4\x93\x1a\xb7\x02\xb2\x2b\x32\x1c\xf5\x3b\x06\xf1\x6a\xa5\x85\xd6\x5d\xd8\x63\xbe\x33\xba\x15\x72\x79\x11\x55\xdf\x48\xa1\x01\x52\xd9\xed\xf4\x6e\x94\x72\x58\x8d\x71\xbd\xca\x6e\x58\x04\xef\xc7\x2d\x0b\xa5\xe3\x6e\x7a\x00\x53\xf9\x89\xe5\x78\x76\x2a\x2c\xa2\x66\x0c\xd6\xda\x75\x61\x71\x72\x88\xe7\xd0\xcd\x18\x68\xa4\x00\x64\x86\x87\x52\x46\x2e\xa8\x77\x46\xb3\x0c\x4b\x21\x67\x6b\x45\x21\x6c\xad\xa8\x6b\x2f\x08\x3c\x01\xa2\xc1\xe2\xe9\xdd\x77\x7c\x7f\xf0\xeb\x18\x63\x83\xba\x95\x00\x4a\x6a\xac\xdc\x80\x0c\xf8\xf1\xbc\x97\x15\x04\x55\x4b\x9f\xd9\xad\x08\x28\xee\xe2\xe9\x76\x3c\xb2\x3f\x31\x3a\x02\xfd\xf0\x31\xd2\xe8\xe7\x1f\xd6\xf5\xa7\xa7\xe1\x76\xaa\xca\xf6\xec\x5e\x81\xde\xdc\x6a\x7b\x87\x62\x1c\xb2\xe9\xef\x51\x8c\xc7\xf1\xbf\x24\x19\xf7\xe3\x9f\x48\xcc\xad\xb7\x54\x7b\xbb\x1d\x8a\xce\xbf\xf2\x12\x47\x69\xd0\xaf\xb8\x02\x40\x43\x06\x6e\xf9\x92\xc7\xb7\x88\xce\xfc\xbb\xcb\xbb\x54\x67\x71\xd6\x2f\xb8\xce\xf0\xd7\x77\xc8\xce\x3e\x9c\xe2\x3f\xfc\xfb\xd7\x67\xeb\x78\xe8\x47\xd3\x5b\x07\x38\x78\xdf\xa7\xc4\x3f\xb6\x01\x3f\xc6\xd6\xc5\x47\x88\x15\xb9\x82\xa1\x4a\x4c\x57\x2d\x70\x4e\x64\xa3\xd7\x38\x81\x16\xf8\x56\x07\x80\xeb\xa2\xeb\x99\x9f\xb4\x10\x4c\xc7\x59\x57\x6a\xac\x47\xd2\x70\x22\x9b\x61\x96\xfa\x24\x65\x08\xf0\x37\xcf\x7d\xc7\x2c\x90\x1f\x8d\x5b\x29\x22\x37\x31\xf5\xfb\xe3\xcd\x2e\x86\xc0\x29\xc9\x11\xc8\xa2\x63\x97\xf7\x18\xfe\x63\x75\x70\xcb\x16\xaa\xe1\x36\x8a\xef\x4d\x92\x7b\x92\xee\x3e\x69\xbf\x12\xcc\x83\xfd\x0a\x34\x70\xb9\xe3\x48\x62\x78\x1a\xc3\x4f\xcd\xa7\xd4\xeb\xcb\x40\xf1\x2b\x3b\x15\x26\x7f\x08\x82\xd0\x2b\xaf\x8f\x1c\x85\xf8\x85\x9f\x29\x8d\x41\x82\xc1\xfb\xc7\x87\x23\x1e\xcf\x7c\x68\xf2\xc3\x21\xf1\xee\x80\xf8\x08\x3c\x09\x0f\x6a\x98\xde\x96\x22\xdf\x10\x4a\xd8\xdf\x8a\x23\x58\xd5\xeb\xd2\xca\x6d\x99\xf2\x8d\x97\xbb\xbf\x7d\xa3\xa5\x15\x9e\x50\xa8\x15\xf0\xe9\x09\x53\xe2\x0a\xbe\x6d\xfc\x9a\x5b\xe2\xad\x8f\x9c\x2a\xd8\x13\x76\x71\x53\xbb\x81\x36\x17\x22\x2c\xfe\xfb\x52\x1b\x2c\x28\xb1\xf6\x7a\x01\xfd\xe6\x3f\xc8\x2b\xfb\xd7\x1f\xf7\xfd\xc7\x27\x54\xdb\x38\xa1\x99\xbd\xbb\xb7\x52\x80\x30\x73\x0b\x59\x9a\xaf\xfd\xd4\x64\x9d\xfb\xd2\xd2\x38\x64\x4b\xfa\xc4\x58\xf7\xd9\x38\x2c\xc2\x7f\x34\x35\x90\x42\x89\xda\x81\x12\x49\x00\xef\xd5\xd9\x82\x68\x0a\x5b\xe8\x64\x3a\x51\xa9\xb0\x81\xa3\xcb\xd1\x04\x5b\x00\x31\x48\x8d\xda\x89\xc5\xc2\x25\xe2\xab\xf4\xab\x86\x56\xec\x82\x0d\xe6\x9f\x55\xe4\xfe\x3f\xfe\xfa\x04\xac\x1c\xcf\xec\x82\x0f\xa8\xb3\xd2\x8f\x12\x2f\x08\x0b\xc1\x64\xd6\x08\xc4\xaa\x25\x19\x65\x07\xa7\x8a\x50\xbc\xcc\xce\xd4\xaf\x46\x19\x3e\x07\x1a\x22\x0d\x7e\x08\x80\x5c\x38\x2b\xd2\x2a\x68\xeb\xf1\xf3\x79\xc4\x79\xd2\x63\x53\x0f\x97\x38\x2e\x7b\xdc\xc7\xfd\xde\x5e\x5f\xa4\x97\x91\xac\x19\x41\x01\x51\x36\xa0\x79\x5d\x74\xba\x49\xd3\x6e\x8b\x65\x1a\xdf\xed\x20\x72\xa5\x6d\x24\x41\x62\xe6\xa6\x83\x1f\x3b\xcb\xba\x08\x6c\x52\x80\xe7\xf2\x9d\xf6\x55\x0c\xc2\xc9\xa8\x2c\x76\xe3\xb9\x8c\xa3\x75\xaa\x89\xc0\x7e\x9a\x29\x80\xa5\x3c\x51\xdb\xcd\x72\x8b\x96\xdb\x16\x60\x49\x70\x05\x42\x09\xab\xa7\x92\x74\xae\x67\x7b\xf1\xc1\xdd\x77\x28\x16\x25\x9d\x44\x08\xe0\x94\x95\xcd\xdc\xf8\x28\x60\x57\x49\xda\x90\xbc\x21\xad\xdd\x1a\xf7\x73\x34\xb8\xcd\x53\x60\x6b\xa7\xf6\xd5\x7a\x3c\x1b\xdb\xa2\x34\x4b\x63\x8e\x8b\x70\x4e\x0a\xd7\x2b\x7b\x2c\x1a\x6c\x1b\x81\xb2\xec\x54\xe4\xd9\x10\xc0\x5e\x74\xde\x7b\xeb\x6c\x3a\x64\x9d\xf1\xf5\x27\xdc\x97\xad\x3d\x8d\xce\x76\x2f\xa9\x6c\xee\x6c\x1a\x51\x6b\x70\x99\x32\x09\x84\x07\x01\x7c\xd6\x91\x35\xd7\x52\x93\xfa\xdc\x9e\x39\x19\xd8\x06\x41\xc7\x9b\x4b\xb2\xda\xb7\x05\xb8\x99\x86\x22\x12\x9a\x9f\x64\x36\x8d\xac\x1f\x6d\x31\x23\xfb\x9f\xd2\x11\x65\xa0\x42\x73\xd9\x59\x9f\x81\xa0\x16\xbe\x03\xcf\x8d\x3b\xd9\x87\xdf\xd3\x58\x9f\x41\xc6\x60\x3a\x7a\xc5\xdd\x4d\xf1\x57\x88\x28\x18\xaa\xde\x98\x6f\x88\x38\x8c\xd8\x19\xf2\xf5\x21\x48\x51\xd1\x39\x52\x93\x0b\x1f\x86\x65\x73\xad\xf0\xa9\x9a\x24\x9d\xc8\x4c\x55\x4b\x20\x11\xd2\x09\xb3\xb8\xb6\xa4\x85\x2c\x18\x44\x41\x20\x47\x39\x33\x02\x0c\x5b\x29\x49\x53\x03\x95\x10\xd8\x30\x8b\x04\x01\x23\x01\x93\x60\x57\x8b\x98\x8f\x8c\x87\xcc\xb7\x4a\xb8\xeb\xe2\x5e\x0d\x28\xcd\x6c\x97\x89\x3c\xcd\xd8\xd5\xff\xe2\xeb\x36\xf9\x4e\x74\xa4\x2a\x5b\x11\x96\x07\x22\xed\x13\xb2\x46\x91\x55\x2d\x81\xaf\xb1\x8f\x49\x1a\xbe\xfe\xfc\xa7\xeb\x8f\xb7\xe7\xcd\xfe\x43\x58\x70\x1e\x23\x88\x73\xdf\x61\x27\xad\xed\x7d\x76\xd2\xfd\x17\x94\xa4\xb5\xbd\x47\x49\xda\x5a\x49\xc3\x17\x8d\x6f\x12\xad\xd2\x28\x7e\xd7\x26\xe6\x39\xbf\xd2\x24\x26\xcc\x97\x26\x78\x84\x07\xde\xbd\x58\x05\xad\xc6\x3b\x57\xe3\x49\xbf\xbc\x5a\xb5\xf6\x5b\x0d\xf0\xef\xff\xfa\x44\x8d\x34\x9e\xf1\xc9\x0f\x02\x33\xcd\xd4\xbd\x93\x6f\xb2\x23\x87\x9f\x83\x58\x63\x07\x4b\xca\x8a\x42\x6c\xcd\x13\xe8\x6a\x92\xf6\x92\x77\x75\x72\x2b\x97\x71\xb4\xc3\x77\x86\xa7\x59\x7d\xe4\x25\x99\x40\xe5\x2c\x01\x48\xf0\xc5\x98\xd4\x18\x5f\x82\x9f\x80\x5c\x24\x60\x9d\x0e\x7d\x3b\xb1\xdb\x00\x1b\x85\x8e\xdb\x32\x7c\xf9\xa5\x47\x40\x75\x6c\xa6\x30\x46\x87\xad\xd6\x5a\xb2\x19\x31\x52\xa3\xb4\x79\x4d\x82\xad\x00\xc9\xea\x7e\xb9\x17\xac\x15\xf0\x16\x1e\x5a\x8c\xc5\x48\x13\x38\x91\xbe\xc0\x4a\x80\x18\x2b\x53\x0a\xed\x4b\x5d\x35\x6b\x52\xed\x20\x1c\x03\xba\xb7\x82\x37\xe4\x00\xdf\x3f\xbd\xd2\xfd\x0d\x6d\xb4\x96\x9b\x62\x4f\x72\x93\x1e\xac\x9e\xec\xb6\xa7\x43\x63\x48\xaf\x82\x20\x4b\xb7\xeb\x28\x65\x3d\xce\x7a\x20\x48\xde\xdf\x0c\x89\xa3\xef\x79\x01\xff\xe7\xb6\xe8\x2c\xac\x68\xb8\x0f\xa0\xcb\x7d\xbc\x42\x1a\x4c\x68\x37\x53\x38\xdb\x10\xec\x4a\x0a\x3c\x15\xfe\x65\xf4\x8b\x1f\x17\x7c\x9e\x51\x44\xfb\x99\xdb\x7d\xfb\xb7\xa7\x41\xf8\x8c\x1c\x9f\x7a\xba\x80\x53\xc0\x20\xdd\x36\x40\x21\x22\xbd\x11\xa1\x94\xc2\xbc\xa8\x0f\x8e\x51\x37\xa2\xdc\x84\x34\x3d\x5d\x43\x36\x6f\x21\xbe\x8c\x54\xa9\x44\x53\x15\xb0\xd4\x04\x66\x06\xac\xda\xb6\xa1\xd2\x0a\x69\x4b\xc1\x42\x0a\xa6\x1a\x64\x49\x65\xb3\x7b\x7c\x1c\xc0\xc9\x83\xdb\x27\x1f\x2b\xa0\x9e\x38\x2e\x04\xfe\x30\xbc\xe0\x7e\xc5\x4d\x32\xd4\xca\x0a\x5d\xd5\x15\xa5\xa2\x50\x98\x46\xa0\xa8\x67\xc8\x11\x36\x86\x66\x23\x2f\x57\xc7\x25\x58\x7b\x00\xf9\x08\xcc\xce\xa0\x4c\x29\xb3\xeb\xcc\x82\x11\xb7\x35\x8f\xbf\x56\xdd\xa9\x4a\xe4\x2d\x1d\x09\x5e\xbb\x03\xcd\xfa\x91\xc7\x5d\x03\x61\x73\xcc\x48\x68\x80\xbb\x33\x2b\x75\x43\xfa\x00\xcb\x7c\x0b\xa1\x41\x6e\x24\x35\xd8\x3c\x50\x80\x9a\x91\xb1\xe0\xa3\x22\x9e\x7d\x14\x0f\xf4\x40\x8b\x20\xca\x38\x21\x56\xdf\x92\x54\xff\xa0\xac\x9c\xf6\x8f\xc6\x24\xb8\x82\x24\x17\x59\x2f\xed\xbb\x4f\xb5\xb5\xa4\x76\x81\xc9\x33\x91\x1b\x9f\xab\xf6\x92\x14\x50\x19\x25\x19\x69\xa0\xc9\xfc\x29\x88\xd1\x68\x84\x06\x62\x3c\x1c\xdc\x1e\x20\x28\x45\x41\x93\xbf\xd0\x01\x4a\x22\x18\x70\xe0\xf9\x68\x99\xda\xcc\xb9\x50\xf5\x10\xdd\xbf\x13\x92\x87\xc8\x31\x52\x4d\x65\xd7\x9e\x88\x49\xab\x09\x29\x79\x55\x22\x6e\x4a\x07\x74\x6e\xc8\xee\xef\x12\x98\x16\xb8\x28\xa9\x1b\xe2\x6a\xa5\xad\xfe\x60\x0a\x4c\x19\xa2\xab\x35\x15\x83\xe5\xe8\xe3\x8c\xc4\xc5\x02\x56\x54\xcb\x5b\x45\xb4\x51\x6d\x26\x2d\x97\x0d\xea\x9f\xe4\x18\x17\xe3\xe3\xa4\x08\xb5\xdb\x3d\x51\x59\x88\x23\x58\x4c\xf7\x47\xbb\xdc\x87\x7f\x80\x3c\x3a\x13\x40\x80\xc7\x69\x8c\x06\x22\x5d\x8b\xc6\xe8\x2d\x23\x4e\xce\x27\x3e\xdc\x66\x14\xf3\x41\x9b\x60\x00\x9a\xe7\x7e\xc2\x0e\x50\xd0\x0e\xe8\xd2\x97\xba\x43\x7e\x6f\x87\xd6\xa1\x8f\xb4\xc6\xa0\x33\xaa\x09\xb4\x6e\xa8\xbb\xf1\xff\x07\xa4\xdd\x6f\x75\x2d\xc9\x56\x02\xe1\xc4\x92\xed\x9a\x93\xff\x55\xc7\x48\x7a\xd9\x6c\x26\x10\xd2\xf9\xad\x93\xd7\xeb\xb3\x95\xe4\x3f\x7f\xf8\xf1\xfb\xe7\xf8\xdd\x47\x1c\x65\xad\xd7\xa4\x55\x37\x92\xd1\x89\x90\x92\xb2\x82\x59\x1a\xd0\x48\x44\x52\x85\x64\xe0\xa5\x05\x71\x6c\xa1\x87\xd0\x8e\x42\xe2\x8a\x04\x36\x6b\xe0\x20\x8d\x1f\xa9\xe5\xd7\x97\xde\x66\xb2\x6e\x24\x88\xb3\x87\x2a\xf6\xb3\x88\x5f\x4a\x8a\x00\x69\xa0\x44\xf5\x81\x13\xc7\xbb\xd9\x84\x7e\x01\xb4\xa7\x17\x60\xd3\x90\x9c\x56\x34\xf0\xfa\x32\x8b\x0f\x95\xb6\x71\x07\x05\xff\x51\x65\xaa\xd7\x1d\x34\xb8\x57\x17\x62\x56\x39\x80\x71\x69\xdc\x06\xd6\x92\xd1\x89\xb7\x9c\x46\x50\x43\x12\x7f\xdd\x84\xb5\x31\x29\x0a\x64\x4c\x0d\xa4\x22\x30\x6d\x04\x11\x30\x27\xa9\xc0\x34\x83\x8b\xcf\xbd\xf1\x31\x93\x74\xbf\x72\x06\x9a\x38\x03\x6a\x00\xc4\x87\x6f\x9f\xa8\xf0\xf1\x05\xb7\x05\xee\x21\xd0\x5e\x1c\x5d\x48\x44\x82\x4e\x2a\x01\x5a\xdb\xf3\xce\x66\x16\x6f\x47\xa3\x83\x05\xa4\x05\x6a\x89\x8d\xb0\x0d\x36\x81\x16\xdc\x73\x6f\x96\x8a\x42\x41\x1f\x01\x17\xea\x63\x84\x17\x0e\xd0\x6e\x77\x6b\x3b\x1e\x29\x38\x01\x10\x75\xf0\xbb\xe5\x1c\x92\x1d\xbc\xcd\x84\x45\x28\x30\x12\xd3\xa0\x2f\x8e\x15\x58\x60\x81\xc8\x9c\x94\xc6\x90\x8a\x6a\x5a\x98\xef\x32\x61\xb1\xd7\xb1\x49\x9b\xc9\xff\xb3\x42\x40\x42\xdb\xb5\x70\x29\xde\x1a\x12\xaf\xe1\x5d\x4d\xba\xb0\xc4\x2c\x69\x26\x67\x3d\x91\x08\x98\x85\xc6\xe2\xdb\xb5\xf9\xa2\xe7\xd3\x62\x22\x81\x5c\xe7\x2e\xa0\xd6\x14\x10\xc9\x36\xa3\x74\x07\xe2\xb6\x1c\xa1\x51\x96\xb9\xdf\x01\xef\xa8\x1c\x40\x5d\x42\x5a\x1a\x10\x29\x32\xc8\x2a\x5a\x3a\x12\x73\x70\x0c\x88\x3d\x21\x8f\x45\xf1\x57\x9a\x4b\xdb\xdc\xf6\x2a\x3d\x31\x0a\x23\x99\x56\xd8\xd9\x85\xc4\x75\x9e\x55\x21\x70\x03\x18\xaf\x41\xae\x65\x60\xda\x70\x57\x2a\x30\x97\x7c\x19\x03\x41\x88\xcf\x3b\xec\x09\x50\x82\x39\xb6\xc7\x02\xb0\x9f\x2f\x95\x30\x02\x21\x81\x02\x2b\xcb\x3a\x42\x43\x58\x5f\x0c\x95\xaa\x0b\x83\x2a\x91\xa5\x7b\xbd\xbc\x48\xeb\xbe\x06\x67\x66\xf9\x67\x4b\x47\xe6\x2d\x40\x6e\xdc\xfd\x80\xc9\x59\xc8\x8b\x8b\x39\x0d\x96\x03\x7f\x48\xa8\x00\x80\x9e\x20\xf9\xda\x30\xd2\x50\x2e\x5d\xba\x23\x97\x56\x07\x14\x5a\x90\xfd\x2e\x23\x51\xcb\xc5\x8d\xa9\x71\xc0\x71\x89\xf6\x9c\x91\xbc\x05\x1a\x91\x9a\xbe\x07\x1f\x03\x92\x44\xc2\x9c\x92\x02\xad\x06\xb7\x0e\xac\x45\xbe\x9a\x7e\x2c\x96\xff\xc3\x9f\x7f\xfe\xe1\x39\xc8\xf3\xfd\x43\x35\xb4\x45\xe1\x5b\x17\x56\x94\x19\x44\x67\xfc\x2f\x93\x74\xa2\xad\xa7\xe9\xee\x3f\x04\x39\xe8\x4e\xfa\x36\xcc\x6d\x5d\xdb\x20\xad\x77\x29\xe9\x9c\x9d\x23\xbc\xce\x45\x45\x5e\x5f\x9a\xf9\x9a\x36\xcb\x6d\x29\x83\xe2\x0a\xc1\xe7\xc1\x9d\x27\xd0\x71\x9c\x4b\x99\x78\xae\x21\xc1\x8f\x31\x24\x95\xc9\x68\x78\x47\xa5\x41\x32\xd8\x64\x24\x7e\xd4\x46\xd2\x40\x5f\x8a\xfa\x11\x87\x33\x66\x2a\x90\x41\x1c\x00\xc0\x90\x29\xbd\xa4\x89\x10\x2c\xc4\x0d\x32\x17\x57\xdc\x03\x6e\xe1\xe6\xf7\x26\x08\xd2\xe6\x64\x48\x55\x5a\x3f\xf8\x25\x79\x9d\x70\xd4\xcb\x67\x58\x9e\xef\xac\xeb\x53\x8f\xff\xe9\xa3\x0a\xc7\x92\x35\x15\x23\xc4\x19\xc1\x7c\xc4\xe1\x6d\xec\x90\x1f\x27\x19\xce\x04\x07\x44\xc0\x7a\xb8\x24\xe2\xcf\x2d\xca\xee\x97\xd1\xa2\x00\x84\xcb\x0b\xd6\xaa\x60\x26\x59\x01\x39\x04\x0e\x0e\x96\x1a\x22\xcb\x91\xe5\x8b\xb0\x24\xa7\xaa\x31\xc3\x8c\x18\xa9\x69\x72\x3f\x4a\x40\x6c\xe1\xff\x0a\x09\x1a\x99\xfa\xf5\xbd\x2e\x19\xe1\x5e\x19\xb9\x6f\x42\xa9\x26\x60\x9a\x16\xc5\xa7\x54\x70\xdd\x09\x38\x34\x3c\x0e\x21\xb3\x06\xfc\xd5\x65\x5f\xa6\x22\xb6\x3b\x08\xd8\x77\xcb\x0f\x9f\x4a\xdb\xdc\x1b\x2a\x3d\xa9\x6f\x7b\x7d\x17\x42\xd6\x3b\x11\x44\x5f\x0e\xd4\xf9\x20\x2d\x4e\x0f\x44\xc9\x50\x60\xbe\x4c\x12\x28\xa8\x83\x1a\x36\x88\x38\xd9\x21\xc7\xd6\xcb\x6e\x62\x59\x91\x04\xe1\x25\x5a\xc3\xfd\x96\xc0\x5d\xf6\x9a\xda\x11\x4f\x9e\x34\x9a\xb1\x5b\x79\xf7\x6e\x9d\xbc\xc7\x30\xaf\x88\x6d\x0a\x62\xd0\x7d\xb2\x12\x2e\xb2\xdf\x19\xe1\xf8\x26\xbb\xaf\x8b\xcd\xf6\x43\x30\xe6\x02\x4b\xd4\x77\x9b\x15\x70\x64\x68\x85\x82\xa7\x8c\x90\x42\x50\x50\xeb\x01\x54\x28\x21\xdc\x41\x06\x14\x22\x03\x6a\xc1\x56\x03\xe8\x5a\xac\xd9\xa2\x7d\xef\xa8\x39\xf5\x3b\x44\x9d\x6c\x8a\x80\x16\xe2\x51\x7c\xd3\x20\x17\x72\x5f\x75\x1c\x36\xe1\x98\x61\xd6\x31\x6c\x2d\x76\x32\x10\x4d\xd2\x76\xc1\x90\x0b\xc9\x2b\x40\xe1\x80\xae\x05\xaa\x00\x81\x23\x4b\x1d\x4b\x1f\x0c\x60\x78\xba\xb6\x83\x4d\xaa\x8e\x1d\x54\xe5\xa0\x90\x08\x0f\xf8\xe2\x7d\x15\x79\xf0\x58\x35\x80\xe9\x47\xe4\x29\xec\x1a\x6e\xf9\x95\x48\x80\x7b\x62\x9a\x4f\x4e\x76\x08\xda\xad\xc1\x29\x50\xb0\xe4\x2e\x18\xd0\x18\x2d\x12\xef\xbb\xc4\x0c\x30\x96\x21\x80\x66\xb3\x33\xf4\xb6\x35\xbf\x6b\xe6\xcc\x49\x3e\x51\x64\x07\xcb\x14\xe8\x28\x88\x3c\xd3\x5d\x58\x86\x91\x77\xd4\x1b\x33\x30\xed\xa6\x82\x1f\xf9\x39\x39\xe6\x77\xdf\x62\xc7\x1c\xcf\x6a\xcf\x8f\x09\x4c\xdf\xbc\x87\xdd\x16\x96\x3e\x8e\x7a\xca\xdd\x94\xa8\xa1\x62\xd0\x71\x7e\xa9\xd7\xa5\x76\xf2\x09\xfb\x5a\x75\xd3\x36\xaf\x4b\x45\x01\x0e\x63\x1a\x38\x92\x53\xbd\x92\xb2\x09\x72\x4c\xed\x2a\x6a\xe3\x95\x97\x6a\x79\x1e\xba\xfe\x6a\xe3\xe6\x9f\x1e\xbe\x9d\xd6\x3f\xf8\x56\x72\xef\xb7\xa5\xf5\xf8\x16\x9c\xdc\xa3\xa4\xb8\x16\xbb\xeb\xb8\x85\xeb\x28\x6d\xc3\x7d\x3d\x3c\xc0\x7e\x3c\x99\xf9\xb6\xfc\xc9\xea\xfa\xa4\x09\x36\x1e\xd0\x55\xf5\xce\x7e\x79\x30\x01\x50\x49\x6e\x81\x94\xdc\x7c\x23\x36\x17\xc0\x84\x03\xa3\x3d\xa3\xa8\xee\x26\x53\xaf\xc8\xc9\x7d\x78\x08\xe2\x1b\xe9\xf8\xcb\x7e\x1c\x74\xb5\xaa\xef\xd4\xd1\x6f\x90\xb6\x3b\x48\x12\x0e\xf9\x3b\xdc\xcf\xa1\x42\x67\x72\xa6\x57\x0a\xc4\x05\x92\xc2\x25\x44\x84\xcb\x6d\x9c\x6e\xf0\x11\x23\xd0\xca\x6f\xfc\x1f\x56\xd3\x22\x1a\xfb\xad\xa8\xec\x1e\x27\x1f\x8d\xb1\xf1\x7f\x5e\x98\x1d\x99\x13\xfe\xf4\xe3\xcf\x7f\x5a\x7f\xf8\xee\xeb\xba\xbf\x4b\x1d\x31\xf3\x9b\x81\xf1\x86\x27\x22\xea\x44\xa2\x9c\x81\x6e\x2b\xa6\x92\xbf\xbe\x6f\xb1\x49\x9c\x02\x85\xc1\x16\xe2\x5e\xb8\xcc\xa8\xe4\xc3\xab\xf6\x7f\xd6\x43\xb9\x70\xe2\xf5\xfb\xbb\x07\x1a\xea\xb8\xc6\x7e\x5e\x18\x17\xf2\x01\xf3\xcd\x23\xfe\xff\x61\xf1\x9b\x86\xc5\x77\xd6\x9f\xb2\x46\x53\xde\xa0\xa8\x67\xb0\x0e\x7f\x53\x24\x2d\x93\x45\x3f\x89\xae\x4b\x29\x83\x1a\x94\xda\xc9\xf7\xd1\x51\x2b\xe0\xff\xae\xc7\x77\x82\x72\x6b\x9c\xf0\x7e\x14\xdf\x8d\x51\x69\xf9\xa0\xcc\x89\x91\xf7\x30\xf0\xe6\x9d\x73\xe7\xbe\xde\x2c\xe7\x82\x13\x43\xe5\xa0\xee\xe1\x9a\xb3\xdc\x17\x1d\x8c\x5b\xf0\xed\x9c\x83\xe8\x18\x43\x18\x42\xff\x8c\x04\x40\xff\xf2\xd3\xfe\x30\xbb\x9f\x5e\xa9\xbe\xc3\x9f\xbc\x1c\x04\xca\xcb\xc9\xa0\xbc\x1c\x14\xca\xc1\xa0\x1c\x04\xca\x07\x7f\x72\xd0\x27\x2f\xe4\x4f\x5e\x40\xa0\x0c\x7a\x62\x8a\x0c\x94\x11\x48\xca\xb7\xd3\xea\x6f\x9d\x55\xfb\xb7\xa6\xee\x6f\x98\x6e\x97\x7f\xbc\xf9\x36\x9e\x5e\xce\x33\x0c\xe7\x21\x33\x94\xd5\xdc\x89\x03\x25\xb7\xbb\x65\x1b\xc1\x82\x90\x9d\x61\xbe\x3d\xef\x90\x9e\x58\x50\x5e\x70\xe4\x40\xc7\x3d\xc4\xed\x87\x29\x48\xa1\x61\x95\x0d\xe6\x24\xfd\x45\x52\x87\xd6\x2c\xef\x47\x28\x49\x56\xc4\xbb\xa1\xdc\x04\x20\x21\xaa\x76\x91\xa3\x0e\xd4\x08\x8a\x05\x22\xc2\x39\x6a\x8a\xb4\xa7\x09\x39\xe7\x19\xb6\x40\x6d\xa0\x60\x6e\x2b\xcc\xd5\x06\x06\xd2\x24\x40\x29\x17\x96\xa3\x31\x08\x52\xbb\x24\x2d\x73\xc5\x43\x49\x89\x60\xbe\xe8\xb8\xb0\xc2\xaa\x13\x51\xd0\x0f\xb0\x56\xed\xc9\xea\x8a\x02\x83\xd2\xfb\x75\x29\x5d\xcf\xec\x91\x06\x99\x60\x84\xfa\x4a\x76\x43\x76\xb6\xd4\xbb\x2f\x53\x49\x7a\x6a\xa9\x80\x77\xaa\xa2\x54\x7c\xc0\x66\xed\x70\xd5\x36\x28\x77\xc2\xe1\x2b\x7d\x2f\x24\x5d\x45\x98\x6b\x52\x07\x2e\xc2\x59\x02\x0e\x48\xf9\x52\x57\x2a\xf9\xcc\x6b\x21\x73\xd5\xb8\x2e\x25\x77\xc4\xbd\xfd\x97\x52\x2b\xa5\x47\x2a\xea\x81\x56\x78\x91\xa5\x7e\x92\xb0\xf9\xf1\xdf\x7f\xf8\xe9\xbb\xf7\xc1\xb9\xf3\x4e\xc9\xa6\x53\xd3\x98\x03\x9c\xcd\xd4\xe4\x93\x50\xfe\x60\xb9\x8d\x51\x6f\x47\xb6\x82\x5a\xdf\xe1\xfe\xd1\x36\x6a\xca\x28\xf2\x02\xe7\x0f\x4b\xfb\x50\xf3\xd5\x7a\xe0\xbd\xc5\x5d\x5e\xa2\xa1\xfd\x94\x46\x8b\xaf\x16\x0a\x50\xd5\x8a\x2c\x8a\x20\x80\xd8\xc0\xda\x03\x78\x10\x1c\x1c\x4a\x2b\xe6\x15\x04\x41\x5d\xcf\x9f\xde\x71\xad\x6f\xbd\xa5\xaa\x69\xf8\x2e\xb0\xd5\x0e\x99\x9b\x8e\x31\x0c\x65\xd6\x5a\xb9\x03\xb4\xd0\x59\xe4\xa7\xad\xc5\x30\x67\xe3\x7d\x5e\x36\xc1\xb9\x36\xcc\xfd\xe6\x4d\xd5\xfd\x49\x4b\xaa\x2d\x95\x52\xfe\x19\x15\x40\xbe\x33\x77\x5f\x7e\xf1\x9e\x9f\x11\x45\x52\xf5\x8d\x59\x46\x81\x5b\xe4\xcc\x26\x11\x01\xd5\x17\xb4\xa8\xbc\x67\x79\xb9\x55\xe3\xb7\x01\xa8\x7c\x62\xae\x6a\x22\xeb\x82\xa8\x51\x6b\x47\xce\x8b\x25\xed\xa8\x2e\xf6\x6d\xbe\xfd\x02\x7d\x23\x0a\x7c\x24\x63\xc4\xb2\xaa\x59\xea\x72\x9b\xf6\xfb\xb4\xa3\x35\x3f\x51\x69\xb5\xfc\xac\xd1\x7f\xf3\x7d\x67\x35\xdf\x96\x04\x78\x9d\x4a\x54\xda\x7e\x40\x6d\xd8\xfc\x72\x86\xc4\x65\x5d\x6c\x52\x2d\xfa\xb6\x4c\xfb\x9b\x4f\x2d\xa3\x6f\x32\x98\x70\x70\x1f\xb8\xca\x0e\x24\xba\x3e\xb3\xdb\xb5\x77\x64\xf9\x3f\x1a\x08\x7f\x59\xff\xfa\x1f\x31\xef\xbf\x7b\xca\xb3\xcc\x27\x1e\xbb\xc7\x60\xd8\x69\xa8\xb7\xf2\x3e\x9f\x1b\xec\xf3\x00\x4c\x3e\x7f\xdb\xca\x3b\x63\x03\x48\x4e\xfa\x73\x4f\xc3\xa6\xfc\xf2\x61\xbd\x7d\x36\xff\xe6\xcf\xad\xbc\xf3\xe6\xbc\x61\x58\xef\xbf\xec\x1c\x1a\x7d\x3a\xc6\x6d\x40\x3f\x1c\x82\x4d\xdd\xd7\xe3\x9d\x55\xa9\xfd\xba\x0c\xd3\xcb\xa9\xb0\x1c\x0b\xf5\x12\x2b\xf5\x6d\xe1\x79\xd0\x62\xe2\x9f\xf6\x38\xe6\xea\xdf\x9c\xab\x3b\x17\x77\x11\x0b\x7a\x1f\xae\x17\x71\xf2\x27\xeb\xc5\x40\x29\xda\x87\xeb\x05\x1b\xfa\xf6\x7a\xe1\xdf\xff\x5d\xeb\xc5\x53\xa8\x74\x3e\xe1\x7a\x54\xdc\xa6\x67\x16\x4e\x73\x2a\x80\x54\xa0\x2c\x14\x22\x6f\xd0\xe4\x21\x90\x83\xf8\xdb\x37\x56\x34\xd1\x89\x24\x94\xc1\x2e\x0f\x5a\x86\x32\x61\x76\x28\x55\x1e\x1e\x89\x3e\x51\xa6\x7a\xff\x74\x7e\xbd\x2d\x1d\xe4\x11\x38\x37\x27\xa3\x11\x5e\xdb\x61\x83\xfb\x75\xae\xad\xf8\x2d\xf8\xa4\x93\x0a\x0c\x54\xdc\x9c\xf8\xde\x5b\x94\x9a\x6f\x34\x29\xc6\x3e\x58\xb8\x5f\xb6\x71\x94\x26\x1f\x82\xc2\x8c\x34\xa3\x9e\x83\xf6\x7d\xc9\x97\xc3\x45\x2d\x79\x5f\x1e\xbe\x5f\xce\xb3\x58\x00\x0a\x34\x38\xdb\xdd\x97\xf3\x5a\x10\x5d\xf1\x11\xd2\x6d\xa6\xd6\xc6\x56\x91\x5a\x03\x39\xf0\x54\x92\x2b\x4f\x5d\xc1\x86\x97\x7d\xa3\x2a\x23\x41\xa5\x43\x81\x3f\x16\xd5\xd7\x97\xa6\x6e\x81\xe4\xab\x64\x28\x95\x0a\x75\x35\x17\x28\xe7\x8f\xbc\x2d\xb5\x9f\xe3\x18\xa1\x38\x50\x0b\xaf\xc8\x71\xa8\x9b\x41\x03\x51\x67\xa2\xa2\xf0\x1f\xd3\x67\x20\x0a\x8f\xf2\xe4\x2b\x24\x57\xa6\xa5\xd2\xca\x55\xcf\x0d\xd2\x8d\xe4\x56\x5e\x5f\xcc\xf7\x5c\x08\xef\xcf\x35\x0e\x9a\x8d\x92\xde\x28\xfe\x9e\x7b\x07\x5a\x66\x3d\xaf\x45\xfe\x05\x09\x3e\x04\xe6\x18\xd4\x22\x6b\xaf\x73\xa7\xb0\xbd\x06\x93\xc5\xc2\x4c\x33\x1f\xe8\xba\xf0\x41\x45\x1a\x53\xcb\xbc\x89\x4f\x46\xb3\x3d\x8d\xe6\x0f\x51\x52\x55\x66\xea\x2d\x6f\x8d\xb2\x88\xf7\x74\xfa\x41\x8f\x2d\x34\x4c\x67\x3f\x68\xfa\xf2\xba\x48\x77\x3b\x76\xae\x95\x64\xea\x77\x05\xde\x02\x46\xb3\x3a\xa9\x67\x29\x59\x8f\x12\x60\xdb\x16\x54\xf2\x91\x6d\x41\x7b\xd0\x19\xb8\x5d\x53\xdd\xc2\xac\xeb\x62\xa4\x70\x6c\x6b\xa5\xbd\xb2\x91\x7b\x65\x7c\xa3\x55\x7d\xdb\x6a\xb4\x79\x6f\xd1\xd6\x05\x09\xc7\x6a\xac\x52\x98\xe4\x90\x9a\x97\x93\x81\x31\x1f\x25\x4e\x48\x98\xb2\x90\xaa\x74\x12\xe0\x8d\x4a\xed\x93\x6a\xab\x9b\xff\x15\x85\x8f\x35\x19\xd0\xb5\xfe\xd8\x95\xd8\xa8\x65\x10\x70\x35\xb6\xa5\xe5\x68\x35\xe8\x79\x8b\x3b\x03\x19\xbd\xf7\x6e\xab\x1d\xad\x56\x4b\x42\xa2\x19\x0a\x0b\xe2\x59\x1b\x78\xe8\xa2\xbc\x28\x2b\x4b\xc9\xf1\xa4\x83\x24\x45\xfe\x60\x6e\x0b\xc2\xd8\xcc\xab\x01\xae\x50\x57\xd6\x0b\xe6\x5f\xb4\x56\x27\xf5\x77\x25\xeb\x65\x8f\xa7\xb6\xa3\xb9\x13\x5b\xc3\x02\x2c\xbf\xbd\x95\x44\xe7\xb2\x82\x88\xab\x6e\x20\xbc\x2a\x96\xda\x86\x47\x0c\xc9\x48\xa4\xa8\xc9\xdc\x3e\x03\x92\x59\x82\x49\x9f\x78\xcd\x0e\x2a\x0a\x62\xd5\xa0\xfd\xbf\xc2\x24\x36\x69\xab\xdb\x9f\xb5\x6d\xcc\x93\xb6\x34\x5e\x5f\xba\x4f\xed\x39\xee\x4f\xc2\xde\xbe\x0f\x8b\x8f\xe5\x4f\xbe\xb3\xf1\x14\x92\x9d\xf3\x1f\x5c\xfc\x04\xfb\xb3\x6f\xf5\x05\x5c\x98\x12\x4c\xa9\x05\xfa\xaa\x48\xf2\xaa\xa6\x03\x70\x30\xb0\xd0\x62\x4e\xce\xb9\x2d\x93\x62\xe7\x74\x13\xda\xbc\xe5\x5b\x3e\xf7\xf1\x56\x52\xf3\x61\x5e\x3a\x79\x47\x8b\xa6\xa9\x47\x9d\xec\x64\x7e\x0d\x1c\x36\x66\x98\x35\x26\x49\x41\xc8\x77\xd4\xa4\x44\xfd\x07\xcb\x3f\xb0\xbf\x52\xf1\x11\x65\x20\xa8\x02\x89\x9b\x27\x87\x60\x09\xce\xc7\xd4\x73\xe0\xc0\x74\xc6\xce\x7e\x56\x03\x2d\x51\x40\xb2\xb4\x11\xda\xc4\x76\x97\x3c\x62\x62\x0d\x1e\x0a\xe8\xdd\x35\x89\xf5\xc8\x08\x09\xf3\x9f\xc3\x36\x3b\xb0\x3c\xcc\x3e\x0b\x01\x4e\x64\xa0\x09\xae\x08\xbb\x04\xeb\xc1\x3c\xf7\xad\x7e\x87\x1c\x1d\x9f\xce\xa0\x15\xbe\x93\x08\x55\x91\x03\x80\x34\x5d\xfc\xb7\x40\xcd\xcd\x47\xb0\xb6\x9e\xa4\x97\xcd\x50\xa0\x09\xc2\xaa\xa6\x87\x0c\x43\xff\x15\x26\x46\x7d\x1a\x9c\x1f\x01\x7d\x44\xfb\x11\x6d\x6d\xa0\xeb\xf2\x65\xc7\xc0\xbe\x9a\x73\x65\x5a\x7c\x62\x2a\xb9\xb1\x7d\xc8\x1e\x88\x80\x41\xa0\xa6\xd6\x27\x9d\x19\x32\xfa\x10\x10\x86\x52\x81\x00\x13\x32\x71\x55\x02\xda\xb3\xd4\x79\x7e\x1a\x2b\x12\xbf\x5a\xdb\xba\x68\x1f\x69\x28\x76\x37\x4b\x63\xa4\xb1\xc9\x4c\x44\xeb\x53\x72\x0f\x9c\xe4\x47\x3a\x12\xac\x91\x0a\x9f\x37\x6f\x88\x73\x25\x08\x81\x20\xe7\x4b\x65\x4c\xbc\x85\xf3\xfa\x72\x80\xbb\x48\xcb\x42\xc4\xd4\x85\xec\xfa\xcb\x00\xc1\xfc\x58\x85\x59\x93\xb1\x2e\xe2\x83\xa8\x66\x6c\xe3\x39\x61\x4c\xfe\x2d\xf7\x15\xa6\x37\xc1\x4b\x2d\x81\x5b\x2a\xfb\x76\xe1\x7b\x3c\x49\xfc\x50\x18\x8d\x21\x39\xc1\x56\x87\x85\x52\x69\xd2\x54\x1f\x6a\x84\xe2\x94\x79\x25\xaf\x3a\xd4\xb8\xa7\xc6\xb6\x09\xfc\xce\xac\x11\xcd\xd1\x44\xda\xa2\x12\xf4\x6d\x80\x9d\xc0\x3e\x17\x32\x1a\xe9\xa1\x9a\xb0\xa8\x5c\x82\xcf\x43\xcb\x2e\x20\xab\xd8\x9a\x51\xeb\x18\xd0\x13\xd1\xd7\x97\x99\x67\xaa\xdd\x56\x35\xc8\xc4\x41\xdf\x00\x25\x1b\x88\x53\xa1\xa0\x15\x55\x43\x78\xbf\x1b\x64\x7c\x81\x0a\xf6\x95\x00\x91\x21\x5f\x5d\xf3\xdc\x10\x7e\xea\x85\xa3\xa8\xcd\x87\x98\x5f\x79\x8c\xf9\x81\x83\xd1\xc7\xbf\xf9\xa8\x1a\x5b\x25\x44\xa8\xce\xa4\x00\x56\x23\x9b\x9c\xfa\x0c\x81\xcc\x6a\x6d\x63\xf1\x83\x21\x4b\x20\xbb\x0e\x44\xb7\x65\x27\x1a\x75\xb4\xbd\x83\xee\x78\x90\xe3\x01\x1f\x8e\xaf\xdc\xbe\x3c\x0e\x5f\x8e\x06\xf0\xa1\x0b\xbf\xc2\x37\x7e\xb8\x37\xe4\x0d\xf8\xf9\xf1\xe3\xf8\xf3\x71\x1c\xcf\xe3\x8d\xb9\x2f\x0d\xbc\x80\x1b\xcd\x60\xe3\x64\x98\x54\x10\xad\xc2\xbf\x08\x8a\xb6\xc1\xef\x61\x71\xc6\xa7\xfb\xb7\xcb\xfd\x94\xe5\x6c\x26\x3e\xa1\x5c\x0e\x91\xd7\x38\x40\x82\x4f\xc8\xcf\x03\xaa\x0b\xad\xdd\x3f\xdd\xbf\xbf\xec\x0f\xe7\x9d\xad\x7d\xb6\xa0\x3c\x67\x18\x3e\x12\x8c\x94\x3c\xf8\x7a\x6e\x40\xea\xfb\xdc\x06\xfe\xc5\x4d\x61\x1d\x89\xf1\xb7\x02\x55\x85\x45\xa7\x25\xcd\xb1\x64\xb8\xdd\x42\xec\x25\x88\x04\x32\x95\x1c\xb0\x99\x75\xdf\xd6\xa0\x53\x47\x22\x83\x3c\x6e\x6e\x17\x3e\xd8\xe5\xc6\xe8\x09\xcb\xfe\x2d\x14\x3c\x02\xd5\xab\x49\x88\xcd\xd2\xd6\x77\x1b\x31\xa5\xea\x4d\x0c\x3b\x63\xaf\x35\xcd\x5a\x10\x10\xb4\x99\xd7\xa5\x6a\x4d\x22\x05\x02\x95\xc3\xb8\xfd\xf6\x00\xd9\xcc\x79\xf3\x0b\x2b\xd8\x78\x2d\x95\x81\x52\x92\x4f\x0d\x86\xfe\xd4\x85\x4f\x08\x19\xcd\xe5\x08\x0a\xcc\x96\xa9\xd0\x38\x1b\x59\xfc\x23\x40\x79\x84\x37\xda\xb1\xc0\x95\xa3\x78\x3c\x0a\x23\xb4\x01\x65\x15\x34\x12\x80\xd1\x13\x85\x5f\xe9\x30\x8a\x8e\xd7\x17\xad\x2d\x8d\xd9\xae\x5a\xdb\x6d\xe9\x6d\xb8\x03\x77\xf3\x9f\xbf\xe1\x0f\x75\x6e\xb8\xce\x71\xf1\xfd\xb8\x9f\x1b\x9d\xd3\x06\xd7\x90\xc5\x18\x71\x07\x7b\xdc\xd2\xb5\x4e\x6f\xeb\xf5\x45\x46\xf5\x15\xa5\x5c\xbe\xd9\x14\x1f\x7a\x6a\x3e\x42\x4e\xcf\x8d\x49\x1f\xfa\x59\xe7\x3f\x47\xec\x9f\x80\x08\x6a\xf9\xf4\x52\x7a\x2f\xa9\xe7\xbc\x92\xc8\xae\x6d\x85\xd6\xcf\xe0\x28\xde\x17\x5f\xa0\x08\xe4\x5f\x4c\x0f\x90\x3c\x3e\x06\xdb\x92\x05\xe6\x1f\x61\x58\x1d\xde\x90\x1b\xa2\x15\xe1\xda\x01\x05\x69\xf7\xab\x7d\xd1\x01\x5d\xc2\xeb\x8b\x5f\x3e\x1d\xd5\xf0\x4a\x51\x6f\x44\xaf\x84\x9b\x52\xd5\x93\xe0\xd7\x47\x34\x55\x0c\xd7\xa5\x55\x4d\x9a\x1b\xc5\x8d\xdc\x86\xeb\x24\x6a\xc3\xfd\x20\xea\xea\xc6\x72\xa3\xf3\xcb\xf5\x7d\x9e\x31\xf1\xc1\xda\x67\xff\x59\xcc\x2e\x9b\x32\xbc\x04\x5d\x6f\x52\xe6\x08\xf9\x28\x45\x0e\xdd\x84\x7a\xe4\x82\x19\x1d\x14\x21\x6b\xa9\xb7\x01\x3c\x57\xa5\x5a\x3a\x34\x53\x42\xfd\xbf\x55\xd0\x26\x89\x24\xcd\x3d\x4d\x5f\xea\xf2\xba\x98\x81\x85\x12\xa8\xe1\x91\x48\xbb\xb9\xe3\xdf\x15\x4f\xec\x0f\x0c\xe2\xa3\x9c\x84\xcc\x06\xeb\xbd\x27\xbc\x6f\x46\x62\x0f\x7d\xf6\xea\xe7\xd3\xab\x3f\xb1\x13\xa3\xfa\xf6\x36\x57\x64\x29\x72\x07\x70\x91\xbe\x33\xf8\xa1\xdc\xa5\x0a\x25\xf8\x45\xc4\x8f\xc2\x41\x85\x1a\xfd\x12\xa6\x67\xd0\x7f\x42\x11\xb2\x13\xa6\x32\x7c\x6f\xe8\x1b\xa1\xc6\x10\xff\x5f\x04\x25\x68\x60\x6a\x4e\xc2\x17\x82\x8f\x16\x85\x20\xe4\x7c\x75\xc7\x16\x26\x6a\x00\x45\x94\xa4\xbd\xcd\xbb\x01\x80\xde\x4e\x84\x38\x50\x26\x33\xef\xb8\xd1\xde\x76\x14\xb7\x8f\xf9\xa5\x6e\x35\xea\xcd\x10\x9d\x2f\x5b\x65\xd0\xac\x24\x29\xb7\x4c\x31\x7b\xf0\xc4\xb4\x7c\xa0\xec\xa8\x3f\xd3\x49\xff\xc2\x02\x15\x42\xaf\x16\x26\x04\x51\x0e\x8f\xd5\x15\x68\xda\x8f\xc9\xec\xff\xfa\xe7\x1f\xff\x5f\xf9\xbf\x9e\x02\xe2\x5f\xdf\x48\x15\xf6\x9a\xaf\x5d\x2b\xd9\x3c\xa9\x38\x7e\xac\x6a\xbe\x94\xfb\xf6\x6c\x83\x69\xaf\xd0\x61\x22\x4b\x87\x8d\xb8\xbd\x6d\x61\x94\x64\xd1\x39\x49\x0d\x15\x75\x82\xc1\x8f\x68\x01\x36\x66\x01\xb3\xce\xb9\x9f\x1f\xee\x5f\xde\xcf\x38\x5a\xd9\x2c\x23\xdb\xc3\x72\x59\x59\x69\xa2\x68\x86\xa9\x13\x68\x5a\xcb\xcd\x3f\x50\x86\x01\x13\x35\x8a\xc2\x77\xb2\x86\xf8\x84\x23\xa5\x88\xdb\x45\x05\xfc\xbf\xe7\xc7\xfd\xcd\x21\xe7\xa9\xdb\x40\x3e\xc5\x4d\xc2\x02\x76\x8f\x96\xf7\xa1\x90\x1b\xf4\x9d\x6e\xf4\xf0\x1e\xc6\xd5\x7d\xa6\x9b\x7e\x12\x93\xf9\x9f\xf2\xf5\x49\x0f\xf1\xeb\xb3\x1e\xe2\xe3\x6e\x3d\x6b\x72\xab\x8c\x89\x28\x2a\xf6\x63\x2e\x50\xb8\x72\x1e\x70\x38\xef\x27\x45\xd0\x0d\xcb\x80\xc9\xd6\x12\x3e\xb7\x1d\xc9\x83\xad\x90\x6b\xcf\x6d\xb6\xa5\xcc\x4d\x80\x2b\xf0\xdf\xca\xfc\xc5\xa1\xaf\x2f\x7d\x8c\x54\x43\x5a\xb7\x73\x43\x6b\x6e\xbc\x20\x8c\x1f\x90\x3f\xff\x00\xc0\x6a\xb3\x2d\xfb\xba\xc2\x5f\xca\x7e\x7c\xcb\xa3\xa1\x57\x9e\x70\xca\xeb\x8b\xc8\xb0\xb7\x0d\xa3\x97\xed\xd0\x51\x63\xe3\x49\x61\xff\xf9\x92\xb8\xe3\x5f\xb7\x96\x8c\x15\x08\xe7\x71\x71\x6a\x71\x3f\xc7\x4a\x6a\x1d\x9c\xf0\x90\xc2\x4f\xa3\xec\x0b\xf8\xf8\x76\x94\x8f\x52\x4e\x8c\x51\x39\x13\x49\xb3\xad\xde\xdc\xb0\x55\x33\x22\x15\x71\x3b\xf1\x98\xf1\x94\xed\xac\x7a\x88\xa7\xfc\x52\xcf\x07\x3e\x71\x8f\xe4\x32\xaf\x25\xc8\x3b\x96\x9a\xd7\x45\xc1\x48\x07\xdc\x6a\x88\xac\x4b\x5b\xb1\xa6\x9b\x80\x6b\x0d\x14\x3d\x8b\xf9\x00\x9e\x7d\xf3\x1b\x06\x21\x5e\x4f\xd6\x2f\x07\xbf\xd3\x40\xda\x89\x94\x37\x2c\xfc\x35\x16\x5e\xf8\x33\x1f\xba\x54\x85\x3c\x38\x3d\x88\xa1\xb7\x90\x12\x11\xf0\x36\x14\xdb\x0d\xf5\x03\x59\xa0\x27\xe7\xf6\xae\x2f\xfc\xb2\xfb\xf7\x0a\xb1\x16\x23\x1d\x7f\x07\x5b\x67\xf5\x2d\x8f\x53\x61\xa4\x78\x5f\x7d\xde\xf1\x6b\xbe\xc1\x3e\x19\xea\xbf\xa7\x9d\x7e\x09\x43\x7d\xff\xd4\x63\xf8\x64\x5b\x99\x4f\x51\xfc\xaf\x27\x40\x63\xda\x4c\x25\x77\xd6\x8f\x33\x2e\xdf\xb6\x85\xc1\xc1\xa8\x00\xad\x2c\x97\x48\x95\x45\x4e\x44\xb1\xb4\xad\x26\x14\xb1\x37\x64\xb3\xa2\xaa\x40\xa1\x1d\x8f\x72\xbc\x02\x8a\xfc\xb7\x07\xbd\xbe\xb4\xde\x52\xc5\x0c\x21\x0b\xb9\x81\x96\x19\x79\x7f\x48\x53\x96\x83\x24\xa7\x16\xbe\x0f\x52\x73\xa1\x2c\xa9\x1c\xa8\x9c\xb0\x8e\xef\x00\x9b\xca\x72\x91\x2c\xe5\xd7\x36\x7e\xf9\xed\xad\xab\xce\x43\xac\x11\xf8\xe1\xd4\x35\xe4\x2b\x4e\x55\x06\xe3\x6a\x24\xbe\xfb\x42\x2d\xb4\xa7\x81\x48\xa4\x16\x5b\xd1\x97\x36\x41\x53\xa9\x89\x51\x99\x5a\x22\xb6\xa8\xba\x81\xce\xf1\x7e\x1b\xf7\x5b\x5b\x1e\x3e\x9e\xdf\x6f\x0b\xe1\x2f\x58\xbe\x40\x6b\x30\xbd\xbf\x17\xa1\x9c\x04\x42\x3f\xeb\x42\xc8\x29\xe4\x18\x83\xe4\x00\x15\x95\x76\xd9\x08\xa4\x47\x4e\xde\xf4\xc8\xc3\x1f\xa2\x1c\x94\x8a\x08\x1d\x38\xd0\x07\x54\xa0\xa3\x21\x43\x93\x0e\x2e\xf5\x10\xad\x02\x24\x9a\x6a\xd1\x20\xda\xf6\xdd\x18\x1c\xdd\x1d\xfc\x63\x33\xa7\xd1\x82\x0a\x0a\x87\xb8\x61\xec\xd3\xd6\x17\x05\xd4\x06\x20\x26\x9c\xee\x4c\xf8\xf5\x4e\x30\xf8\xfb\xa7\xd7\x2f\x7f\x68\x7e\x7d\x3e\x65\x18\xbe\xda\x69\xc0\xb5\x96\xda\xec\xeb\xcc\x49\xfb\xad\x79\xf7\x76\x1a\xb6\x62\xc4\x0b\x43\x54\x01\x94\x98\x24\x86\xab\x47\x11\xc9\x0d\x60\xe8\xd0\x55\x07\xb5\x17\xcd\x79\x3b\x24\x2f\xec\x17\xc4\xae\xfe\xfd\x4d\x34\xbb\x93\x25\x37\x08\x99\x12\x66\x11\x40\x5e\x9b\x7b\x78\x9d\xb5\x3f\xa2\x7d\x91\x30\x23\x2e\xd8\xda\x97\x7a\x23\x33\x8d\xcc\x14\xad\x06\x11\x7e\xd9\xd0\x47\x8c\xbe\x4a\x61\x61\xd3\x62\x76\x5b\xaa\x6f\x40\xbe\xf9\xd6\xac\x37\x41\xd5\x69\xcd\x17\xbf\x83\x76\xde\x7f\x1c\xfc\xa5\x9e\x34\x83\xf6\x58\xd7\x80\x0b\x9c\xcf\x71\x13\xb5\x75\x01\x9d\x60\xc3\x78\x56\xf7\xa5\x21\x01\xe6\x3b\x0c\xbb\xa8\xfb\xd3\xf8\xb3\x1c\x40\xe6\x7e\x3c\xc4\xef\xc0\xff\xf2\xb7\x62\xb7\x2e\x7f\xbf\x58\xf4\xd7\xa7\xc0\xfd\xd7\xf2\x51\x45\x75\x6e\x6e\x8a\x95\x9b\x40\x9a\xf0\x71\x99\xa2\x5e\x4c\x48\x00\x2d\x87\x06\x50\x23\x73\x92\x00\x5d\x07\x37\x7d\x4e\xff\xd6\x42\xe7\x5d\xfa\xa0\xdc\x16\xde\x3a\x89\x7c\xf0\x23\xe1\x4f\x37\x6d\xed\x6a\xfe\x42\xb4\x69\x08\xd6\x1c\x2a\x33\x3b\x8a\x4b\xe6\x5d\x8d\x66\x0f\x75\x9a\x5b\x53\x8c\x29\x28\x3c\x37\x52\x62\xec\xc6\xb2\x7e\x95\x4d\xc0\xb4\x6a\x28\x7f\x54\xdd\xe3\xae\xca\x6d\x11\x6b\x2b\xb1\x61\xd5\x9d\xf1\xea\x3b\x71\x56\xbf\xfc\xc5\xaf\xcf\xdd\x1e\xcc\x18\x1a\x5c\x90\x1c\x61\x39\x28\x3b\x2a\xeb\x30\x7b\x3c\x50\xd0\xd8\xe2\xb1\x2d\x67\x3c\xcc\x58\xc1\xeb\xda\x64\xf5\xeb\x54\x7f\xae\x4e\x86\x32\xe5\x73\xc9\xb7\x9e\x4b\xfc\xfc\xfe\xe9\xea\xf0\x14\xea\xfe\x5a\xff\xc7\x23\x79\x8f\xb4\x7c\x2b\x23\x5f\x97\x9e\xcb\xad\xe7\x12\x44\x71\x93\x05\x81\x8f\x6c\x50\x0f\xa4\x4e\x37\x3f\xe8\xea\x67\xf8\x69\xe0\x8a\xc3\x09\x0f\x74\x50\x77\x92\xa8\x7f\x20\xd8\xd2\xe5\xb7\xac\xab\x4f\x31\xbd\xaf\x4f\x28\x95\x87\x80\x94\xe9\xf0\xe1\x5a\xae\xea\xbd\x32\x87\x5d\x97\x6a\x7a\x6b\xb3\x63\xb8\xea\x68\xaf\x38\xa6\x58\xbd\x59\x83\x08\xa1\xdd\x16\xff\x24\x6a\xaf\x2f\x4d\x4a\x9a\x6d\xdc\x16\x3f\x41\x73\xc5\x89\x8b\xe6\xca\xaf\xbc\xe5\xdb\xa2\xb9\xe0\x3b\xff\xc9\xef\x66\x76\x5b\x7a\x5c\xab\x2f\x84\xb3\xa8\x5f\xd4\x6e\xd2\x0c\x17\x1d\x7a\x5d\xfc\x67\x9b\x3d\x8c\x89\x6f\x5c\x5d\xaa\xb4\x68\x47\xcf\x76\x34\xda\xe9\xd1\x4e\x8f\x76\x46\xb1\x37\xed\x5c\xee\x0d\x7d\xd2\xa3\x4f\x21\xbe\xaf\xfd\x0e\xda\x2d\x2d\x55\xd2\xb0\x41\x31\x7e\xb0\x72\x17\xee\x6e\xa9\xa7\xb5\xe0\x63\xec\xa6\xbd\x6f\xde\xdd\x3d\xf9\xef\x7d\xab\xfe\x1d\x0f\x0c\xe6\x5a\x84\x03\x5e\x5f\x7a\xb6\x34\x4b\xf9\x45\xa3\x80\x7f\xc4\xd1\xbf\xba\xe1\xa3\x59\xef\xc8\x56\x53\x05\x74\x52\x50\x8b\x3f\x12\x48\x82\x54\x2c\xcd\x7a\xa2\xc5\x29\x51\xe2\x06\xa1\xaf\x10\xe4\xcf\x69\xdb\x82\xaa\x52\x16\x42\xc2\x31\xb8\xdc\x96\x66\x6d\xf5\x5f\x8b\xdc\x34\xb7\xad\x52\x72\x48\x28\x13\x03\xed\x70\x72\x58\xcf\xba\xf3\x5a\xaf\x2f\x53\x35\xcd\xe0\xd3\x28\x29\xca\xd4\xe2\x26\xbe\x54\xdc\x46\x2f\xd4\x35\x84\x40\xca\x75\x91\xd1\x6e\xcb\x28\xf9\xcd\x95\x6a\x5c\xa9\xbd\xbd\x12\x5a\xd8\x8f\x46\xff\x59\xed\xa2\xa7\x98\xe6\xd7\x27\xe4\x85\x66\x3b\x51\x66\xaa\xbe\xba\xf7\xad\xd7\x64\x2c\x51\x62\x08\x79\x17\xa8\x6f\x8d\xa3\x4e\x78\xf2\x36\x50\xc6\xbc\x93\x03\x58\xa0\x5f\x00\x91\xf0\x96\xfa\x59\x75\xce\x2f\x07\x40\x43\x93\x2f\x09\x26\x34\x25\x31\x58\x9d\x5e\xfb\x9b\xc2\xad\x9d\x82\x8e\xe4\xf4\x07\x63\x39\xcc\x65\x91\x83\x91\x9b\x10\x52\xd4\xf7\x0d\xc2\x1a\x08\x09\x26\x49\x34\xb9\xd2\xed\xe0\xc6\x28\x60\xe6\x00\x84\x7a\x05\x11\xfc\x86\xfa\x68\x6a\x2c\x5d\x36\x72\x74\x8d\x28\x5f\xd3\x43\xbe\x03\x74\x31\x63\x3f\xf8\x69\x0e\xa1\x3f\x09\x86\x08\xa0\x13\x42\x89\x7f\x2f\x4c\xb3\xad\x02\x3a\x4c\x89\xc0\xfb\xfd\xc1\x98\xc6\xd4\x7d\x61\x52\x2d\x38\x06\x85\xb9\x3b\xf8\xdd\x9c\x05\x47\x69\x43\xa8\xe2\x40\xd9\x93\x9a\x73\x54\x4e\xa0\x3c\x03\xe0\x13\xee\x3d\xa4\xd9\x36\x4d\x51\x82\x9a\x50\x16\x58\x7b\xaa\x93\x71\x82\x4a\x4d\x8e\x92\x34\xb4\x06\xcb\x85\x05\xa8\xd5\x22\xf6\x9b\x96\x60\xaa\x26\x77\x57\x41\x08\x01\xa3\x9f\xac\xce\xcd\x0e\xa8\x54\x94\xfe\x0f\x5f\x9d\x49\x7a\x0b\xe4\x0f\x3d\x30\xc4\xbb\x21\x98\x80\x2e\x15\x06\x7f\xc8\xd8\x88\xb2\x74\x4d\xd0\x14\x14\x14\xe4\x46\x24\x43\x43\xf5\x63\x2d\x03\xd2\xef\x10\x23\x0b\x71\xab\xbd\x1e\x74\x83\xd2\x52\x54\x75\x27\xc8\xee\x94\x43\xae\x00\x59\xf9\x24\x20\x72\x49\xac\xc6\xa7\x9e\xcd\x86\xa0\x13\xf4\x9c\x1a\xa4\x83\xcc\x2e\x9b\x34\x43\x19\x8a\x1b\x63\x3d\xa4\xba\x08\xad\x92\x23\xcf\x39\x0e\x5e\x97\x71\x84\x7f\x22\x7b\x0f\x3a\x23\xe4\x51\x49\x12\xdf\x28\x29\xd4\xd2\x21\xd0\x8f\xab\x03\x5f\x0f\xf2\x6c\x42\x58\x30\xa1\xb3\x5b\x2a\xa2\x80\xc5\xb5\x90\x8e\x70\x97\x1e\x8a\x41\x70\x33\xe4\x10\x97\x64\x05\x77\xf0\xd3\xe5\x64\x65\xa5\x7e\xfc\x56\xc0\x28\x5f\xcc\x17\xc2\x20\xed\x72\x03\x69\x03\x70\x1b\xd4\xe5\xd2\x18\x33\x0e\x32\xec\x2f\x91\xf2\x58\x50\x47\x0c\xd2\x8f\x47\x82\x93\x53\xf4\xcc\x2c\x38\x0c\xca\xa1\x83\xd4\xf2\x5a\x33\xf4\xe2\x2c\x18\x37\xcd\xff\x18\x93\x0b\xf4\xc5\x20\x0e\xff\x72\x6a\xab\x69\x10\x58\x0c\x4d\xc3\x5d\x60\x88\xa4\x3c\xea\x5b\xe8\xa1\xec\x92\xef\xc2\x44\x99\xc4\x25\xcb\x48\x83\xca\x5c\xe4\x95\x4c\xa1\xd3\x55\x08\x29\xb4\x14\xe2\x45\x91\x98\x8a\x9a\xa0\x94\x51\x89\xa6\xf8\x97\x52\x72\xe4\x82\x42\x50\xb8\xe0\x5d\xbb\xc5\x68\x0d\x34\x52\x7b\x0d\xc6\x04\xd8\x61\xd6\xf6\xd2\x58\x91\x5c\x73\xaa\xc1\x23\x50\x91\x6e\x07\x85\x33\xe2\xde\x51\xce\x4d\x6a\x2c\x6c\x77\xb6\xfa\x83\xdc\x96\xde\x56\x60\x5f\x36\x2d\x3d\x4d\x77\x9c\x21\xaf\xe2\x7b\xa5\x4a\xaa\x39\xd9\x24\xf6\x08\x1e\xb5\x19\x72\x15\x93\x54\xf5\x5a\xf0\x1b\xca\x30\x30\x94\x6d\xec\xda\xc9\x4d\x4d\x59\x3f\x5b\x7b\x42\xf9\x02\x26\x28\xd4\x2a\x6c\x52\xe2\x56\xa8\x66\x4b\x86\x8f\x1d\xe1\xe5\x45\x0a\x51\xbb\x78\x59\xa4\xa4\xb8\xb0\x2a\x98\x0e\x15\x98\x15\x20\x3b\x33\x49\x15\xba\x94\x16\x38\x94\x10\xdc\x8b\x75\x0a\x7a\xa2\xb9\x41\xeb\x07\x2a\x2c\x2d\x6a\x3d\x70\x6f\x52\x48\x99\x0f\x5e\x91\xa3\x10\x0f\x6f\x17\x75\x0e\x1a\x51\xd5\x9a\x31\x84\xaa\x04\x5a\xc0\x8c\xea\x33\x40\x5f\x81\x9d\xc1\xad\x97\x80\xb8\x21\x6b\xfa\xfa\x32\x54\x53\x6d\x63\x2d\x6e\x32\xae\xa4\x15\xe9\x7d\x45\x2c\xa4\xb8\xa7\x61\x6a\xa9\x82\x2a\x8a\x02\x86\xb4\x8b\xfa\x21\x17\xcf\xa1\x05\x4a\x22\xbb\x30\xd8\xc4\x4a\x5e\x3b\x20\x36\xe0\x0d\x40\x95\x73\x4f\xc5\x36\x95\xa4\x88\xe1\x53\x8f\xdf\x57\x55\xc6\xfc\xed\x4b\xbd\x4a\x79\x65\xa0\xa0\x4f\xd4\x92\x80\x07\xb3\xb9\xf9\xe3\x23\x96\x1e\x77\x08\xe8\xb5\x70\xc2\xb1\xc1\x45\xe7\x95\x7a\x35\x59\x05\x22\x42\x2b\x79\x03\xf5\x36\x7d\x76\xcc\x8a\x1c\x6d\xbd\xc9\x6d\x91\x87\xdf\xb1\x9c\x54\x88\x94\xe8\x2a\x10\xf3\x3a\xbf\x92\xf4\x59\xc2\x6a\x3e\x25\xac\xbe\xde\x91\x65\x48\x11\x55\x92\x65\x42\xca\x22\xb1\xa6\x03\xd9\xc2\xd1\x43\x9c\x90\x4a\x1a\x67\x92\x42\xa6\x11\xfe\x9b\x48\xce\x03\xa4\x46\x3a\x6a\x01\x15\x94\x01\x2d\x05\xd9\x55\xa3\xa6\x85\x66\x88\xec\x98\xa6\xd1\x63\x88\x05\x10\x4f\x58\x26\xce\x85\x5a\x52\x39\xcc\x1b\xcc\x45\x77\x89\xf5\x80\x12\xb3\xba\x3f\xf5\x04\x1b\x4b\x74\xa4\xc6\x98\x04\x50\x57\x33\x35\x81\xfd\x08\x1a\xc6\x06\x9d\x22\xa2\x2b\x91\xc2\x44\xb6\x2a\x54\x3b\x3a\x04\x68\x02\x47\x5b\xf8\xb7\x52\x36\xb7\x39\x82\x59\xb1\x1c\xe8\x28\x28\xdb\x58\x52\x2c\x45\x69\x1c\xfa\x51\xfc\x90\x3a\x37\xfb\x50\x2b\xf5\x05\x93\x1b\x4f\x3b\x60\x5a\x58\xcd\x36\xf5\xdb\x20\x43\x0b\x66\x71\x2c\x59\x11\x93\x51\xa5\xfa\x77\x4f\xb1\xc3\xe4\x10\x3f\xdd\xfc\x61\x14\x92\xe9\xc8\x19\x0c\x4b\x56\x40\x47\x08\xcd\x90\xa8\x61\x6f\x41\xbd\x6b\x85\x0b\xd6\x52\xb9\x63\x5e\x20\xc8\x13\xd0\xd7\x20\xff\xf1\x0e\x08\xb5\x51\xca\xdd\x6e\x94\x13\x63\xb2\x03\xc9\xfd\xde\x28\x9c\x61\xe4\x1d\x80\x82\x09\x14\x70\xc4\x97\x30\x7f\xd3\x95\x59\x63\x6f\x96\x69\xbe\x71\xe6\x85\x97\xd8\xe0\x59\x45\x54\xc0\xf5\xa5\x39\xb5\xd8\x39\x4f\x6d\x21\xe8\xa9\xb1\xec\xc7\x14\x33\x66\x77\xbb\xbc\x0b\x42\x90\x3d\x74\x04\x4d\x36\x8c\xa8\x04\xfe\x41\x38\xf6\x84\x97\x80\xf9\x0a\x0c\x05\xa1\x80\x60\x0a\x0a\x15\x83\xba\x95\x3f\x3b\xff\xde\xcc\x57\x5c\x1f\x54\xc4\x8f\xc6\x9a\x23\xb9\x85\x8d\x5e\x0f\xd2\xda\xc2\xdc\x94\xe5\xe8\x53\x6c\xc2\xbe\xb5\x97\x88\x9f\x61\xbd\xd0\x99\x23\x22\x0c\x98\x09\x4d\x36\x25\xcb\x53\xed\xfb\x22\x00\x64\x93\x35\xd4\x1d\x28\xcb\xba\x51\xa1\x87\xc9\x56\x45\xa9\x5b\x12\xb8\x5d\x9d\x3b\x1d\x16\x18\x28\x5a\x14\xfe\x04\x53\x0a\x84\xbb\xb0\x2f\xe1\x06\x40\x06\x26\x25\x41\x43\x50\xdb\x19\x0b\x1f\xe4\xa0\xb0\x58\x9d\x4a\xb9\x6c\xd6\x7c\x73\xaa\x83\x32\xc3\x96\x19\x13\xda\x28\xf3\x5e\x6b\x12\x26\x28\x6c\x2b\xd4\x85\x14\x03\xc2\x91\xbc\x0c\xad\x6d\x0c\x4b\x43\x81\x56\x2b\x9b\x25\x6b\x4a\x0f\xc0\x39\xea\x3c\x67\xa5\x1e\x8d\x2a\x0b\xe3\xc8\xec\x4a\x4b\xe9\x53\x4a\x87\xef\x4a\x7e\x4e\xe9\x7e\xbd\x7b\xb6\x3d\xa7\x02\xfc\x73\xcb\xc4\x07\x43\x7b\x7e\x91\xaa\x2b\xd6\x26\xb7\x25\x83\xd3\xe9\xc0\x94\x8e\x7e\xd0\x45\x2d\x34\x2a\x21\x2a\x0a\x94\x90\x1c\x03\xdf\xf7\x15\x94\xbc\x2d\x52\x6a\xe4\x79\x5b\xe6\xdb\xd8\xa0\xbd\x4d\xdd\x5b\x1d\xbb\x08\xd1\xdd\x44\x13\x34\x37\x1f\xbb\xb9\x33\xe9\xf7\x80\x55\x68\xbd\xdf\x12\x1c\x53\xa1\xd6\xfb\xf1\xdf\x98\x3b\x80\x74\x79\x8b\xbf\x8c\x09\x3d\xd9\x31\x93\xf5\xd5\xcd\x8e\x8c\x16\xd0\x5e\x93\x24\x2d\xbf\x5e\x5e\xba\xbf\x0f\x29\x75\x65\x0e\x7b\x05\xd0\x28\x2e\xa2\x24\x2d\xa4\x32\x1c\x9a\xa1\x12\x8c\xff\xe4\x9f\xc8\xd7\x84\x0f\x2b\x26\xde\x5c\xcf\xf3\xdf\xeb\xca\xb8\x2e\xff\x74\x74\x2e\xfa\x76\x40\x63\x75\x42\xbb\x04\xaa\xc9\xd2\x21\x39\x06\xa7\x1f\x5d\x8a\x5c\x59\xa9\x61\xb3\x0e\xef\xce\x18\xd6\x47\xdf\x6e\x08\x12\x06\x1e\xa1\xcc\x3d\x58\xc8\xd4\xb6\x01\x2a\x2e\x09\x91\x0c\x80\x26\x99\x1c\x1c\xfd\x0c\x7e\xf5\x71\x10\x76\x34\xbe\x2f\xe2\x7f\x2b\x49\xc4\x4f\x67\xdd\x24\x95\x8e\x14\x1d\x24\xfd\x7d\x68\x2b\x6b\x04\xb1\x4e\xf8\x4c\x06\x3e\x36\xaf\x14\x9b\xbc\xf7\x39\x3a\xf8\xbd\x97\xb3\xe3\xf7\x9d\x7f\x8e\x2e\x59\x03\xf1\xa5\x1c\x93\xde\x69\xc7\x1f\xce\x8e\x3d\xbb\x1a\x5a\xab\x79\xc3\x92\x52\x62\xb7\x13\xb0\xd6\x71\x29\xf1\x51\x7a\xd9\x3a\x49\x13\x83\xc3\x09\xee\x68\x65\xd5\x89\x1d\xa9\x95\x92\x44\xb1\x80\x40\xa1\x06\xaf\x0d\x49\x08\x24\x4f\x27\x96\xc6\x41\x6b\x87\x10\x81\x79\x04\x20\xd7\xe5\x3e\x7e\xe4\x3e\x64\x37\x0e\x9e\xc7\xe7\xdb\xdf\x8e\xa4\x63\x7a\xbd\x19\x78\x0f\x23\x47\x1f\xc7\xeb\xd9\x05\x3a\x7d\xd4\xb4\xee\x83\x46\x2a\x85\xe4\x76\x84\x79\x81\x3f\x85\xd2\x57\x23\xe7\x4f\xbb\xec\x02\x5e\xab\x2a\xac\x3e\x3d\x5f\xe9\x7e\xbe\xe7\xcf\xe2\xed\xdf\x3f\x2d\x1d\x27\x17\x57\xab\x25\x15\xa8\x50\x53\x66\x57\x0f\x7e\x22\x93\xf0\x2a\xc0\xfe\x39\x11\x2a\x80\x8c\x23\xeb\x98\x90\x8f\x2b\x42\x82\xa6\xc5\x06\x16\xd6\x6d\x21\x62\x19\xe6\x75\xc0\xac\x50\xc4\x0a\xf0\xe9\xbd\x3a\x96\x1a\x65\xcc\x6e\xef\x40\x03\xa7\xbc\xb9\xdb\x3b\x34\x4d\xb0\x1d\x6a\x61\xa1\x82\x2f\x45\x58\xe2\x7d\xb0\x8a\xfb\xc4\xbe\x9c\x4f\xd0\xfd\x34\x54\x66\x9f\x42\xdb\x99\x86\xf1\xa0\x92\x60\xbf\x9b\xa9\xf4\x1e\xbf\x1c\x7c\xa3\xa4\x9f\xe3\xff\x59\x82\x25\x0f\xfa\xee\x91\x64\x45\xb5\x11\x0b\xa7\xdd\x20\x02\xeb\x28\x64\xab\x40\x14\x58\x12\xe3\x1a\xb6\xb5\x74\x68\x05\xd0\xd1\x68\x5b\x1d\x74\x33\x6b\x32\x37\x52\xa8\x85\x93\x35\x19\x54\xb0\x15\xde\x26\xea\x28\xca\x61\xf8\x53\x5c\x3d\x8d\xfd\x10\x94\xdd\x1b\x05\xc0\x35\x04\xd3\x4e\x1d\x90\x78\x3f\x8b\xf6\xc0\x28\xc0\x1c\xe7\x73\x51\x39\x1b\x39\xcc\x18\xfe\x62\xb2\x02\xf8\x32\x2e\x21\xdb\x4b\x8a\x42\xd3\x80\xdf\xeb\x08\xf9\x78\xba\xaf\xf5\x0c\xba\xc0\xf3\x2c\x65\x22\xb0\x49\x0f\x01\x2f\x6d\x6c\x54\xd6\x36\x5e\xc4\x06\x0d\x5f\x34\x9e\x69\xc7\x6a\x83\xba\xa7\x7b\x3a\xf0\xa0\x48\xa8\x96\x8a\xb8\x15\xee\x6d\xf1\xf1\xd3\x12\x80\x8b\xbc\xa3\xc3\x36\x08\x46\xa4\x5a\xef\x72\xdf\x30\xa0\xdd\x68\x2d\x3d\x0d\xa9\x2b\x00\x1b\xda\x57\xf7\xdc\x52\xd1\xd7\x17\x9b\xc9\xff\x3c\x4b\x52\xd3\x9b\x64\xd3\x75\x69\xa0\x38\x37\xa8\xda\x98\x40\x77\x68\xe4\x64\xa6\xac\xfc\x07\x98\x6f\xb8\x75\xe4\xed\xf8\xcb\x41\xf9\x2e\xe2\x36\xed\x3c\xc4\x17\x69\x61\x14\x73\x69\xf5\xf5\xa5\x77\xb7\x33\x67\x59\x2b\x61\xbb\xe5\x66\xd0\xee\xcb\xa8\xf8\xf2\x2d\x83\x8e\xec\x72\x14\xe7\x00\x9f\x16\x70\x14\xd4\xa4\x29\x35\x4e\x46\xd0\x0e\x28\x21\x56\xa2\x57\x20\xbc\x7a\xb8\x08\xf0\x66\xdd\x6e\x84\x25\x39\x30\xb4\x21\xe5\x4e\xfd\x8d\x14\xb9\x50\x31\xa8\x14\x01\xca\x36\x38\xc8\x59\x59\x81\xaa\xfd\x50\x3a\x17\xa8\x81\x81\x50\x84\x08\x2e\xf0\x70\x09\x13\xa5\xb0\x8d\xa8\x5b\xd4\x0e\x61\xa8\xda\xc3\x59\xaf\x29\x2a\x35\xe0\x88\xfa\x92\x3a\xe9\x4f\x04\xe1\x22\x02\xb5\xb9\x66\xef\x62\x77\xe7\x7a\x2f\x49\x4b\x3b\x05\x07\x8c\x69\x37\xce\x3d\x94\x9f\x07\xaf\x3c\xd3\x3d\x23\x31\xac\xed\x03\xcf\x6e\x92\xfb\xd8\x2c\xcd\x54\x92\x64\xc0\x2a\x7c\x9f\x93\x0d\x6c\x8b\x2d\x49\x99\xa9\xe6\x9b\x8d\xb2\xd6\x4a\xb6\x8b\x4d\x89\xd4\x82\xce\xd8\x6e\x98\x6b\xb0\xa4\x9a\x84\xda\xd9\x65\x43\x78\x9c\xe4\xd8\xb7\xa5\xc8\x27\x40\x92\x92\x9f\x81\x24\xcf\xcc\x79\x77\xb0\x96\xba\x51\x23\x55\xdf\x25\x3b\xf0\x5e\x19\x23\x6a\x68\x8f\xba\xda\xfd\xa8\xb4\x25\x78\xf8\xa1\xfa\x36\x8a\x6f\xfd\xc4\x38\x8f\xa5\xb7\x47\xe5\x6d\xe9\x57\xa0\x85\xc1\xff\x3e\xc7\x04\xa0\xd1\x4a\x9a\x50\xbd\xdc\xe1\x25\xeb\x00\x1a\xf8\x9b\x5c\x24\xd7\x65\xb4\xf2\xad\x8b\x56\x94\x00\xb1\x02\x88\x05\x40\x3a\xae\xad\x47\xfd\x0f\x06\x78\x86\x1d\x5b\xc6\xe5\xdc\xb0\x37\x92\xf9\x11\x3c\xcb\x48\xe0\x18\xb7\x45\x1a\xf4\xa5\x47\x3a\x90\xc2\xbf\xd4\x87\xc2\xc3\xbf\x2b\x41\x15\x21\xc2\xb7\xfa\x50\x28\x69\xfd\x85\x3e\x94\x37\xaf\xb5\xfd\xb1\x17\xa8\xa2\xbf\xb8\xc0\xe5\x77\xbc\x82\xc8\x28\x7f\x64\x17\xa1\xfd\xdf\xb3\x8f\x2e\xef\x5f\xe2\xb9\x97\x7e\xcf\x87\x28\x3e\x00\xff\xe0\xf6\x3f\xec\xa4\xcb\xef\x72\x89\x3f\xb6\x93\x7c\x2d\x1e\xb3\xdd\xb4\xb6\x43\xf2\xeb\x49\x8c\xeb\x26\x2d\x83\x19\xff\xb6\x54\xd1\xeb\x98\xed\xb3\xe5\xf0\x19\xed\x73\x57\x04\xb6\x52\xd2\x37\xb4\x1c\x6e\x28\x38\xf8\xa6\x5e\x84\x8e\xfc\xbe\x60\x5b\x3b\x4a\x14\xde\xe8\x45\xa8\x6f\xb1\x15\x56\x78\x19\x0f\xbc\x0c\x8f\x7d\xf2\xc0\x8e\xc0\x2e\x39\x89\x15\xde\xf4\xf4\x1b\x76\x86\xb3\xa3\xd9\xfa\x9c\xfa\x2b\x1a\xbf\xfc\x8d\xad\xbf\xa5\x94\xf8\x9d\x6f\xbd\x8c\xfc\xc7\x34\x6e\x03\x35\xc5\xb7\x06\x3c\xe1\xaf\x3b\xeb\xd7\xde\x09\x5b\x2f\xd2\x7e\xcb\x2d\xfd\xb6\xc6\x5b\xd7\xdf\xa5\xf1\xe7\x65\xcf\x5b\x9f\x60\x7c\xf8\x83\x6e\xdd\xd7\xd5\x3f\xa6\x75\x14\xc5\xcd\x76\xa7\x88\x7c\xd3\x3a\xc8\xe6\x1e\x9a\xbf\xdc\x17\xa3\x93\x92\xf0\xf1\x02\x20\xa0\x7b\xe7\x0a\x7f\xd8\x7b\xf5\xc6\x7f\xaf\xf7\xfa\x6e\xe3\x7c\xad\x7f\xc4\x78\x47\x9d\xe4\x1f\xf6\x5e\x29\x7e\x82\xc9\xfa\x47\x8c\x78\x34\xff\x87\xbd\x55\x12\xa7\xfe\x51\xaf\x15\xad\xff\xda\xe9\x7a\xf9\x1b\x7b\xfe\x8f\x7a\xb1\x9f\x6c\xd1\xcf\x08\xca\x1f\x3e\x62\xf5\x95\x31\xd2\x1c\x87\x3a\x9c\xfa\x9e\x37\xf4\xd7\xa9\x45\xda\x08\x79\xc9\x50\x26\xfb\xf4\x84\x01\xe2\x95\xa9\x49\xa1\x32\x3a\x52\x38\x0b\x2d\x88\x04\x36\x9d\x74\x36\x10\x8d\x3f\x43\x11\xe4\x76\x53\x1d\x57\x6b\xfc\x45\x75\x6c\x3c\x9d\xe6\x4c\x88\xa8\xe2\xb0\x19\x8c\x05\xc8\x26\x44\x62\x23\x94\x42\xa5\x52\x59\xe1\xbf\x59\x77\x12\x75\x58\xff\xf7\x53\x19\xd0\xf7\xcf\xea\xd0\x77\x6a\x96\x0e\x25\x6c\x8e\x90\x16\xf5\xfc\x22\x51\x87\x92\x96\xa0\x74\x00\xa5\xc6\x3c\xc5\xfb\x6d\x44\x56\x65\x6a\x42\xa4\x90\x82\xec\x55\xc8\x2a\x02\xf0\x55\xd4\xd6\x50\xa5\x2d\xd7\x64\x73\xeb\xfd\x81\x0c\xb9\x1f\x34\xd9\x88\x97\x22\xa6\x53\xa1\x1d\x57\xbc\xf5\x21\x01\x4b\x26\x19\x0b\x42\x14\xd0\x35\xb8\xdf\x04\xa8\x63\x08\xef\x66\xc9\xb0\x04\x12\xda\x7b\x53\xa9\x1e\x5a\x34\xa0\x2e\x7e\x72\x9d\x11\xd2\xcd\x94\xc8\x08\x70\x38\x4f\x5e\xc4\x0a\x7d\xdb\x0a\x32\xda\x61\x9a\x1a\xb8\x3c\xc0\x6f\x54\x6b\x5a\x26\x79\x8a\x30\x89\x3a\xa8\xcf\xb5\x06\xa1\x22\x92\xd6\xfd\x60\x12\x27\x5e\x03\xa5\x68\x87\xdc\x04\x08\x0f\x00\xcc\x0b\xd1\x78\x44\x9c\xcb\x59\xc3\x8d\x6c\x3a\x9f\x6b\x92\xfe\x88\xf5\x0a\xbc\x37\xf0\x36\x42\x85\x0b\xa7\x1a\x78\xe3\x73\x1a\x0d\xf2\xa8\x93\x72\x1f\x48\x5e\xb1\xbb\x07\xf9\xa8\xdb\x2e\xd3\x12\x94\x3b\x73\x97\x34\xe4\x91\x96\x86\x71\x9f\xe3\x0d\x2d\xc7\x3b\x0b\x28\x52\xa6\xf4\x09\xdf\x90\xbf\xa0\x03\x0e\xfe\xa5\x6e\x68\x21\x86\xc4\x7e\x0e\x92\x73\xe0\x6c\x67\xf9\x03\x5e\x29\x06\xc9\x12\xa3\x84\x90\xfc\x48\x20\x64\xbf\xb6\xc5\xa8\xe0\xcb\xfd\xc2\xea\x08\x3c\x0c\xda\x29\xa4\x2b\x11\x80\xad\x8e\x17\xc5\x00\xe4\xfd\x15\x42\x1c\x3e\xe0\x7b\x75\x42\x12\x4d\x6c\xc6\x93\x60\x34\x20\x7d\x11\x83\xa4\xec\xf7\xa1\xf3\xd9\x9a\xf7\x04\x96\xfd\xfe\xa9\xa4\xae\xb7\xf1\x28\x86\x9d\x73\x78\x52\x95\x4c\x8d\x2c\x01\x8c\x48\xbd\x77\xc2\x5a\xc0\xdf\x2f\x9b\x86\xd3\xd2\xc2\x69\x29\xa7\xca\xf2\xe9\xb3\x14\xfa\x2c\x2d\x15\x9c\xe6\x67\x2d\x93\x45\x5d\xd8\x09\xd8\xa9\xb5\x27\x5c\xc5\x77\x04\x1d\x29\x52\x91\xf3\x2c\x19\xd5\x9c\x77\x69\x19\x10\x3e\x7c\x60\x42\x98\x5f\xfa\x10\x0b\x82\x1d\xfd\x5c\xf1\xa1\xe4\x27\xb0\xeb\xf7\xcf\xe2\xd4\xf7\xb8\x15\x4d\x40\x5b\x1b\xd4\x43\xe6\xad\x59\x5b\xdd\x2f\x8c\x80\x69\xaf\xca\x99\xd6\xbb\xae\x6d\x8e\xa4\xb5\xac\xcb\x9b\x0f\x3e\xc7\x22\x16\x25\x59\xcb\x19\x76\x32\x06\x79\x51\x83\x59\xdc\xef\xeb\xeb\xd2\xc9\x2b\x51\x58\xf0\x0a\xc1\x2c\x20\xbc\x20\x16\x26\x8d\x07\xe0\x7b\x13\xea\x35\x4d\x04\xa6\x64\xa4\x56\x6f\x6c\xb8\x60\x47\xec\xb6\x37\x49\xa5\xaf\x7e\x06\xe4\x11\x15\x62\x2b\x69\xec\xfe\x9e\x06\xfe\x0e\xa9\x42\x00\x8a\x0a\x34\x26\x0b\x70\x40\x4b\xb7\x4f\x88\xdd\xc1\x01\xf8\x8b\x4e\x7c\x62\x92\x7d\xa8\x4b\x6f\xd4\xf5\x5d\x61\xad\x4f\xbd\x99\x94\xd5\x1f\x13\x19\xf1\xdb\x62\x45\x5f\x5f\x6a\x6f\xc9\xea\x58\x8b\x8f\xc1\x6e\xeb\xf2\xe6\xc3\x22\xe0\xde\xf5\x4e\xfc\xac\x21\x69\xc8\x1f\x7c\xd2\x12\x8c\xa8\x2a\x6c\xa9\xa1\x7c\xe1\xb1\x25\x6d\x3d\x62\xd5\x92\x2d\xaf\x05\xda\x98\x73\x5d\xde\x7c\x58\x64\xcc\xd7\x17\x95\xde\x10\xb1\x38\xd4\xaa\x2d\x1c\xf9\xd6\x2f\xa1\x3d\xd3\xc9\x4e\x1d\x4a\x81\x95\x75\x3b\xd0\xe9\x29\x18\xfc\xfe\x14\x7e\x00\xbe\x07\x3c\xb2\xa7\x72\x64\x5c\xfc\x2d\xff\x96\xf3\xcd\x58\xa6\xa5\x1c\x19\x33\xb5\x1e\x62\xd4\x36\x98\x34\xe9\x99\x22\x1c\x65\xac\xc5\x4a\x92\xd1\x6e\x25\xe7\x6f\x1c\x50\x86\xf7\x34\x20\x22\x39\x55\x5f\x36\x77\x0a\x3d\xe0\x2b\x4c\x76\x8c\xe4\x96\x58\x85\x5d\x46\x60\xba\x7a\xbe\xdc\x96\x92\x33\xae\xb1\xc8\x40\xba\x02\xc7\xf5\x38\xca\x8f\xf9\x6c\xb6\x3e\x81\x8a\xbe\x7f\xaa\x7a\x79\x00\xfb\xcb\xf0\xdb\x95\xd9\xaf\x4b\x15\x14\x3b\x95\xab\x7f\x10\x05\x49\x2b\x08\x79\x7d\x05\x22\x05\x59\x41\x37\xc1\x50\x20\xff\xd3\x97\x7a\x85\x1a\xa8\xf8\x33\x73\x65\xf1\x0f\x3e\xa6\x44\xbd\x9f\x36\xe8\x31\x89\x6a\x32\xdd\x7b\x4b\xa3\x5f\x55\xc1\x28\x80\x7c\x26\x74\x37\x50\xbf\xda\xb7\x45\x69\xc8\x1a\x59\xd3\x4c\x0f\x11\x1b\x03\x5a\x56\xf3\x48\x54\xc7\x33\x82\xe3\x8d\xa8\x56\xdf\x9e\x7c\x8f\xc9\x89\xfa\x54\x80\x4c\xb0\xfc\x72\x46\xe6\x56\xa3\xd8\xae\x63\x78\x94\x7e\x5d\x5a\x1d\x17\x02\xe8\xe4\xa8\xea\x42\x7d\x8a\x34\x66\x7d\x91\x9a\xd2\xde\x93\x5a\xbb\xea\x6c\x9b\x66\x60\x52\xc1\xe8\x03\x20\xec\x60\x2e\xc5\x3f\x5c\x17\xcb\xea\x73\xa9\xf3\x9c\xde\xed\xaa\x43\x36\xd4\xff\x88\x9e\x12\x2a\x85\xa9\xc6\x58\xb6\xb9\xf8\xe3\xc3\x75\xd1\x96\x21\x3f\xf9\xfa\x82\x05\x5d\xaf\x75\x96\xa8\x16\xaf\x51\x25\x16\x9a\x42\xb0\xa1\x32\xb9\x1d\xf7\x90\xb1\xad\x34\xf6\x41\x4f\x82\x0a\x9b\x66\x90\x98\x01\xe1\xd5\x01\xb5\xa8\x08\xb2\xc3\xf7\x44\xec\x5e\x43\x16\x87\x45\xec\xa7\x28\x20\x38\xd7\x58\x79\x4b\xf0\x9f\xbf\x06\x6a\xbd\x5d\x97\x86\x91\xd1\x3e\x1b\x83\xf2\x04\x22\xf9\xbe\xfe\x83\x53\xa6\x95\x09\x7d\x2f\xb9\x2e\xd6\xe5\xb6\xf4\xd1\xaf\x36\x74\x13\x24\x09\x65\x76\x1a\xbf\x6e\x38\x77\x32\xef\x31\x1b\x57\xcc\xb7\x5a\xe4\x91\x7c\x73\xce\x3d\x09\xec\x6a\x2c\x35\x6e\x9d\xcd\x46\x4c\x27\x4a\xbd\x91\x06\x86\x7a\x0f\x3a\xba\x27\xd4\x14\x15\x1f\x32\x6a\xd7\x45\x7a\xbb\xc9\x28\x57\xc1\xeb\x9b\x87\x89\x34\xa9\x6f\x5f\x22\xef\xe2\x83\xa4\x8c\x96\x6c\x8c\xeb\x22\xa3\xde\x54\xfa\x55\xc6\xdc\x04\xcc\xda\x42\x16\x0f\x63\x9e\x06\x10\x3a\x40\xd1\x51\x5a\x68\xbe\x63\xb4\xd3\x20\xc5\xd6\xb8\x2f\xc8\xb4\xf5\x6b\x11\xd9\xc8\xc2\x91\x8c\xf5\x18\xa8\x70\x45\xe9\x44\xbe\x77\x3c\xc1\xff\x42\xe6\x19\xb0\x9a\x8f\x16\xf2\xb3\x5c\xcd\xc5\x6a\x22\xe3\x79\xbf\xec\x2a\x06\xe9\xa2\x98\x3f\xad\xbb\xed\x7a\x75\xa3\x10\xd0\x44\x2a\x8e\xf5\x03\xbb\xc5\x3a\x03\xcd\x00\x11\xb6\xd4\xd5\xdf\x80\x9d\x4f\xa5\x7a\x75\xdb\x60\x2b\x6e\x03\xdb\x4c\x63\xee\x53\x92\xd9\xeb\xcb\x44\xde\x6a\x5c\x4d\xe6\x6d\xe9\xfd\xba\xf8\x87\xfe\x09\x53\x4f\x91\x67\xbf\xe9\x99\xbe\xf7\x81\x3e\xa1\x0e\x4d\x33\x26\x5b\x16\x96\xb4\x61\xca\x31\x3b\x4e\x5a\x38\xb9\xff\xc2\xcf\xd4\xca\x63\x59\xdf\xfd\xe3\xc3\x11\x8f\x67\x3e\x34\xf9\xfa\x32\x44\x93\xa2\xca\x10\x6f\x12\x92\xb6\x80\x53\xf5\xd4\x0d\x00\xc1\x4c\xd6\xf7\xb6\xe2\x80\xa2\x5b\x0f\xad\xc4\x4c\x50\x0f\xb4\xc0\x62\x91\x40\x7a\xd4\x24\xb2\xf6\xa0\x0d\xc9\xf3\x30\x53\x7d\xf5\x4d\x03\x58\x3b\x96\xf6\x35\xc1\x87\xcb\x66\x4c\xbb\x83\xc0\x9a\x84\x25\x99\xc0\xea\xcd\xaf\x09\x6e\xf1\x44\xb9\x00\xe9\x6e\x02\xb4\xe2\x9d\x84\xe4\x2b\x80\x30\x28\xee\x94\xe0\x4e\xf1\xf7\x0b\xf6\x12\x80\x65\x30\x80\x28\x6e\xc5\xda\x04\x96\x79\xca\x49\x72\xd6\xd3\xf1\xa7\xb6\x9f\x47\x1e\x64\xf5\xd1\xd8\x1e\x57\x68\xc1\x30\xc0\x6b\x2f\xe4\x3e\xb7\x10\x20\xd7\x7d\xb1\x90\x5e\x32\x37\x6b\x00\x2f\x22\xbb\x47\x22\x06\x0d\xd8\x65\x95\xb1\x2f\x70\xf7\x86\xfb\x4d\xbe\x00\xe2\x1e\x4b\xea\xcd\xbd\x51\xec\xec\xeb\xa2\x96\xd3\xd4\x5b\xd1\xb9\x1a\x09\x6e\xfb\xd6\x67\xf2\x85\xad\x5b\x2a\x83\x5a\x15\xbe\xc9\xeb\xaa\xa3\x80\x22\x40\x21\xf3\x46\x8c\x8d\xc9\xdc\x4d\x63\x97\x03\x4d\x75\x4e\xf7\xdb\x43\x1f\xc7\x7d\xcb\xa7\xd6\xb9\x3c\x65\x95\xbf\xef\x0f\x6b\xad\xa6\x31\x26\x1d\x63\xd8\x3d\x16\xb2\xb5\x9d\xd5\xca\x47\xdd\x48\xed\x07\x27\x8c\x90\xac\x71\xe4\x74\xfe\x7e\x97\x86\xaf\x2d\xd4\xa1\xa2\xd4\x99\xed\xbd\xbe\x34\xd3\x64\x99\xfe\xbb\x05\xdd\x10\x49\xeb\x40\x1f\x01\x17\x72\xa1\xd8\x81\x64\x4b\x3a\x51\x4d\xdb\xfb\x56\xa1\x93\x90\xdc\xe8\x2f\x79\x6b\xc1\x38\xa4\x39\x81\xd3\xae\xa2\xf8\x7d\xd3\x92\x10\xa6\x00\x50\x29\x87\x1a\xdc\x28\xab\x2f\x3a\x66\x6e\xa7\x57\xf7\xfa\x2b\x14\x62\x49\x28\xc6\x58\xc3\x79\x1f\x7f\x4c\xe1\x97\x54\x5b\xb1\xbd\xb6\x09\x35\x5a\x1f\x7c\x2c\x38\xa9\xba\x87\xb0\x66\xcb\xc7\x34\x19\xe2\x56\xa2\x8f\x81\x6e\xab\x15\x2a\xae\x0a\x08\x3a\xb4\xb2\xea\x99\xa1\x09\xf0\xd8\x46\x94\x41\x68\x39\xf2\x4f\x9c\x43\xf7\x63\x2f\x77\x19\x0f\xd8\x3b\x01\x91\xf5\x99\xad\x95\x62\xcb\xca\xd1\xbf\x2d\x13\x44\x89\x23\x09\x28\x14\xb1\x4a\x77\x02\xcb\x74\x76\xdf\x67\x6e\x05\xbe\xd0\xdf\x53\xc5\xf6\x22\x3a\x66\x1a\xa3\x73\x81\x3c\xf0\xdd\x21\xb7\xdb\xe5\x54\xde\x05\xc0\x96\x9f\x89\xb5\x25\x7a\x95\x1f\x65\x8f\xef\x65\xf3\x45\x16\xc5\xce\x5f\x0e\xd5\x5e\xf2\x2a\xe3\x2f\x9f\x79\x5c\xf2\x94\x5f\xfc\xfe\x99\xaf\xf8\xc1\x6d\xf5\xbd\xb1\xf5\x95\xc2\xd0\x6d\x10\xd4\xaf\xeb\x52\x34\x27\x9d\x28\xbb\x32\xd0\x18\x11\x8b\x56\x3a\x82\x76\xd8\xc5\xb4\x1f\x95\x2e\x75\x2f\xd0\xcf\x50\xff\x88\x19\xdd\xca\x2e\x33\x55\xdb\x58\x5d\x9d\x2a\xd6\x99\x11\xc0\x27\x1f\x41\x03\x84\x31\x73\x85\x78\xdb\xd4\x0d\x41\x38\x5a\x6d\x21\x16\x57\xce\x92\xb8\x45\x14\x85\x21\xc0\x9a\x05\x05\x15\x86\x99\x41\xb7\x5a\x65\x85\x4d\x69\xb5\x83\xcc\x02\xc1\x06\x30\x23\x34\xf7\x6c\x47\x12\x28\x5a\x36\x23\x53\xd4\x18\x97\x15\x33\x74\xf8\xe2\xd9\x46\x4e\x05\x75\xe2\x03\x2c\x50\xb1\x3a\x02\x35\x79\x16\x97\x45\xf1\x1e\x0a\x7a\x56\x78\xe3\x85\xb2\xd8\x60\x6a\x06\xf0\x78\x85\x23\x5e\xb8\x4c\x7a\x97\xaa\x48\xb2\xa6\x2b\xaa\x3e\x0c\xd4\x16\xee\xd5\x28\x96\x0a\x7f\xdb\xd8\xc2\xc7\x04\x6f\x42\x46\x6d\x40\xb0\x03\x41\x8a\x1c\x54\xbd\xdd\x97\xcf\x15\x21\x2b\x5d\x7d\x58\xbb\x1d\xa3\x39\x99\x80\xd3\x98\xa6\x59\xf6\xa5\x62\xd1\x83\x5d\x4e\x11\x58\x52\x39\xe4\xab\x6d\x77\x7f\xca\x50\x3d\x6d\xa1\x4e\xc8\x32\x21\x2c\x10\x70\xd5\xaa\xad\x2a\xa8\x1c\xb2\x4d\x46\x48\x25\x61\xf8\xb5\xfd\x80\xfb\x91\x84\x7d\x61\x65\x5a\xe0\x7c\x83\x88\x36\xd8\xb7\x35\xb8\xee\xdb\xbe\xd4\x78\x87\x51\xe5\xa2\xe0\xdf\xa5\x91\x5e\xd1\xdd\x26\x16\x2e\x53\x71\xf3\x51\xfb\x5c\xc5\x97\x6d\xf3\xe9\x8b\xa1\x81\x62\x94\x99\x94\xc0\xe4\xd1\xd0\x84\xef\x3b\xdd\xbd\x91\x16\x66\x93\x90\x0d\x1e\xe1\xc7\x91\x71\x03\x50\xe1\x47\xf9\x82\xad\x05\xb8\xc8\xcb\x66\x92\x8c\xc4\x0f\xa0\x0d\x9f\x44\xff\xaf\x42\x34\x22\x18\xc3\x24\xa1\x14\x50\xe6\xa7\x76\xfe\x53\x7e\xe0\xfb\x27\xcd\xfa\x07\x5f\xb3\xf8\x00\x2b\xe3\x5d\xc5\x80\xfd\x49\x25\x60\xff\x85\x34\xc0\xfe\x0b\x45\x80\x2a\x2d\x81\xae\x30\x4b\x5b\x81\x96\xf5\x41\x0f\x8a\x39\x1f\xdb\xa1\xa6\x43\xf9\xa9\xde\x86\x2f\x81\x99\xdc\x2e\x04\x69\x16\xd6\x20\xbd\xbe\xc8\x18\xe3\x77\xbc\x2f\x7f\xe0\x54\x0b\x53\x19\x97\xf7\x85\x1c\xe6\x5d\xbe\x02\x1b\x33\xea\x9f\x40\x5f\x02\xee\x25\x7e\xf0\x9f\xb5\xf9\x9c\xb8\x91\x1b\x11\xb1\xb0\xdf\x7c\xda\x6c\xef\x89\x46\x20\xcb\x32\x2d\xbd\x9b\x89\xb8\xea\x00\xa5\x76\x91\xb9\xf9\x49\x85\x1a\xe6\x95\x45\x9a\x13\x7c\x4e\x57\xef\x53\x30\x41\x41\xde\x08\x34\x56\xf4\x37\xfc\xb0\x0b\x29\xb9\x8b\xcc\xab\x8e\x47\x46\x85\xdf\x96\xdd\xf8\xae\xc8\x13\xeb\xc3\xf7\x4f\x04\xc7\x6f\xc2\x19\xa1\x98\xf5\xd1\x25\xcf\x24\xd3\xfb\x2f\x86\x89\x91\x5f\xd5\xc1\xa0\xbf\xc4\x6b\xf9\x8d\x27\xfd\xbe\x2f\xe5\x72\x7f\x2b\xa2\xe3\xa6\xfa\xa4\xfb\xe1\xc3\xfb\x59\xe1\x43\x95\x82\x0e\xdf\x7c\x8d\x8f\x6f\xf1\xf5\xc5\x50\x1c\x90\xdf\xd1\xe7\xd8\x7f\xf3\xac\xe1\xfc\x6d\x25\xff\xdd\xf3\xf7\xf2\x22\xdd\x0d\x9b\xdf\xeb\xc6\x3e\x19\x8f\xcf\xe9\x81\xbb\xe0\x74\xcd\x3e\xf8\xbe\x05\x4d\x2a\x4d\x37\xd8\x43\xa9\xb1\xa2\x62\x3f\x14\xc4\x71\x46\x04\xb7\xa9\xcd\x8b\xd2\xd1\xce\x3a\xd9\x7c\x14\x74\x17\x8b\x6e\x11\x46\xfc\x19\x7f\xac\x81\x4c\x6d\xa8\x68\xe0\x65\xde\x01\x40\xed\xf8\x77\x85\x1c\x73\xb6\xab\x7b\x39\xbf\xe6\x30\x99\xfd\x83\xc3\x6c\x20\xb8\x7e\xd9\x7c\x5f\xf6\xbf\xf8\x11\x7c\x5e\x7c\x87\x89\x06\xab\x00\xdf\xa3\x3b\x9e\x10\x5b\xb3\xe3\x72\x4b\xc9\xf6\xd9\xb1\xaa\xf3\x1b\xc7\x7e\xf6\xda\x9e\x73\x18\x7f\xba\x97\x5a\x6a\x4f\x06\x8a\x25\x23\xe9\x4f\x95\x0d\xa5\x94\xa8\xa8\x2b\x18\x41\x40\x16\x93\xe1\x0d\xc5\x97\x05\xb4\x65\x4b\x28\x47\x50\xb0\xc7\xa7\x47\xe8\x68\xfb\xd6\x5a\x8f\x02\xd7\x0d\x1c\x8a\x3d\xb9\x5f\xa8\x6e\x2c\x6a\xb1\xa4\x7d\x53\xf4\xab\x4d\x16\x33\xf0\x79\x24\x81\x97\x4a\xa2\x3c\xd5\x02\x8b\x5d\x92\x1d\x3c\x6a\x96\x6a\x11\x66\x2d\x16\xb7\xe5\x50\x5a\xd9\x13\xe8\x31\x2a\x62\x6b\x50\x96\xb3\x83\xaa\x07\xb5\x84\x08\x3c\x1b\x15\x25\x88\x3f\x81\x76\x32\x2b\x2a\xf5\xd4\x5b\x80\x84\x7d\x3f\xef\x56\xdd\xbf\x4a\x5a\x05\x6e\x16\xf0\xe3\x65\x0c\xd2\x1b\x29\x2b\x4c\x59\x5c\xbd\x61\x80\xb2\x96\xef\xac\xe4\x2f\xa1\xf0\x69\x92\x3a\x7c\x50\x9f\x69\x25\xa7\x9e\x59\xf1\x0d\x79\x3a\xf4\x32\x2b\x41\x8a\x25\x96\x83\x6b\x66\x1c\xb8\x21\x36\x74\x56\x48\x04\x51\x6a\xe4\xd5\x19\x39\xe7\xdc\x31\x49\xc1\x01\x1f\x4c\x9a\x8b\x82\x85\x16\x9d\xe4\xbd\x0e\xea\x00\xcb\x24\x45\x94\x8a\xae\xcd\x87\x42\xbf\xb2\xd8\x78\x56\x56\xd8\x29\x7a\x56\x74\x43\x49\x2d\x02\xc8\x08\x7f\xc1\x9a\x67\xba\xfa\x9f\x56\x40\xb4\xc8\x73\x1a\xea\x59\xa7\x39\x6b\x79\x14\xa0\x14\x35\x5b\x39\x94\xea\xd0\xd5\x5f\xbc\xc9\x55\xfb\xbc\x2d\x45\xea\x75\xa9\x19\xd9\x9a\x28\x4f\x82\xc9\xdd\xed\x28\x58\xba\x2e\x96\xe5\x66\xd9\x56\x6f\xa0\xc2\xaa\x2d\xc9\xff\xee\x0d\xf8\xf9\x7e\x7a\x29\x28\xbb\x2b\x3e\x3b\x8c\x45\x78\x57\x3f\xcf\xaf\xfa\xd9\x13\x3d\xe7\x3b\x9e\x30\x2a\x0f\x89\xb5\x8e\xec\x55\x59\xdd\xff\x28\xee\x2d\xb5\x54\xd5\x36\x94\xa7\xb0\x30\x5a\x7a\x94\xee\xf6\xd8\x72\x50\xb3\xb8\xb3\x66\x7d\x65\x22\x49\x6d\x05\x91\x7e\x91\x8d\x34\xcd\xfd\x2c\x8c\xe0\xc8\x44\xd8\x22\x34\x91\x81\xe2\xc9\xee\x9f\x4c\x73\x3b\x5b\x45\x50\x07\x56\x47\x23\x59\x04\x94\xd6\xca\xb6\x8c\x14\x69\x21\xe4\x7f\x17\x16\x33\x2c\x31\x73\xb5\xa0\xd8\xbc\x91\x05\xa5\x86\x12\x03\x48\x8c\x15\xf4\xeb\x74\xba\x13\x50\x09\x1b\x97\x12\x94\x33\xcb\x85\x53\x01\xe5\x55\x33\x75\xb7\x0a\xf2\xeb\x8b\xd5\x54\xcd\x56\x70\xca\xe9\x58\x49\x2e\x07\x4a\xf1\x14\x42\xd2\x30\x4b\x26\xfd\x07\x6d\x2b\x7e\x8c\x4d\xd3\xf4\xff\xb9\x09\x01\x06\x21\x49\xcd\x3d\x32\x14\xdb\x43\xa7\x1b\xd1\x80\xa3\x19\xbf\xd7\x19\xfd\x38\x21\x2b\xac\x96\x34\xeb\x8a\x1f\xdd\xcd\x1d\xff\xdf\x06\x03\x24\xa3\xc9\x92\x25\x49\x45\x9a\xd0\x2d\xa1\xbc\x2a\x92\x15\x75\xc5\x16\xa9\xd6\x0f\xe2\x83\xa3\xba\x33\xa4\xeb\x34\x51\x24\x2f\xa9\xb9\xcb\x99\xb4\xd4\xcb\x46\xc1\x79\xd4\xd8\xa1\x13\x70\x8e\xbe\xbe\xf8\x5a\xd0\x6a\x5f\x41\xbf\x5d\x11\xd2\x03\xc7\x01\xeb\xa4\x8d\xa6\xa1\xd8\x59\x4e\xe2\xeb\x30\x1b\x2f\x05\x8d\xd7\x50\xc8\xc6\xff\x29\x7f\xcd\x53\xf8\x00\xcd\xa6\x1f\xb6\xa8\x15\x9c\xb6\xa0\x74\x45\x39\x98\xf8\xdf\xb6\x44\x3c\x8c\x84\x19\xfb\x52\x1e\x2b\xe1\xb4\x34\x7f\x37\x0a\x9e\x87\x96\xca\x21\xe4\x75\x1c\x4e\x6b\x0e\x2d\xd5\xd7\x63\x54\xbf\xbe\x94\x59\x53\x1f\xf5\x82\x8b\xdb\xc8\xf7\x8b\x93\x75\xe1\xa8\xea\x87\x67\x5f\x43\x58\x2b\xea\x65\x06\xfc\x79\xbf\xb0\x8c\x64\x23\x23\x64\xc9\xff\x63\x4f\x88\x53\xf6\x68\xe3\xf5\xa5\x8e\x99\x46\x97\x15\x3b\x70\x1b\x2b\x85\x41\x48\x52\x35\x70\xec\xc1\xb0\xc8\x6d\x91\xd7\x63\xc0\xca\x67\x03\x66\x9f\x77\xa8\xb4\x54\x9a\x0f\x2d\x78\xb9\x10\xc0\x4c\xc7\x5e\x8a\x2b\x1e\x2d\xbd\xbe\xb4\xd1\xd3\x14\x01\x5f\x7b\xcd\x8d\x21\x08\x2d\x1a\xe5\x76\x42\x7e\x04\x64\x18\x0f\x7b\x51\x25\x2e\xa4\x7e\x21\x16\x96\xcf\xd4\x8e\xd2\x23\x04\x6e\x5a\x70\x63\x08\xe7\xee\xde\x49\x90\x01\x14\x0d\x68\x8e\x6f\xd9\xff\xf7\xfa\x32\x86\xa4\x29\x75\x85\x16\xa6\x64\x86\x8b\xd4\x66\xcc\xbe\xa0\x56\xa0\x95\x76\x2f\x0e\x94\x9e\xfa\xbe\x44\x1f\xfb\x8a\xe0\x3e\x7e\xaa\xc2\xc4\x14\x56\x0f\x19\xdc\x35\xfb\x1e\xe7\x91\x9d\x41\xc6\xeb\xcb\x1c\x39\x8d\xd9\xb0\xe4\x94\xa9\x5c\x83\xd4\xda\xe5\x98\x09\xc8\x2a\xd3\x5a\x02\x9b\x6e\x1a\x3e\x75\xd1\xc1\x9a\xd4\xda\xea\x9b\xda\x74\xeb\x53\x14\xd3\x7f\xc7\x31\x0c\x1d\x8d\x7d\xdc\x93\x2e\xd3\x77\xbf\x72\x5c\x41\x6e\x87\x28\x33\xdc\x24\x05\x7b\x8b\xaf\x0b\xaa\xee\xb4\x48\x4e\x0a\x3a\x26\x68\xc1\xfa\x8f\xee\x57\x6a\xd6\x6e\xe6\x2f\xb3\xfa\xe5\xb4\x60\xd1\xd1\x9c\x3a\xdf\xaa\x77\xdc\x46\x9a\x20\x70\x21\xb5\x60\xc4\x2f\xa4\xa5\x04\x59\xd8\xb0\x28\x54\x03\x1c\x2a\x2d\x03\x64\x31\x7d\x34\x0a\xcd\x22\x32\x07\x5e\xa2\x99\x54\x6f\x63\xce\x90\xa8\x1c\x6e\xa8\x8c\x9a\x90\xa3\x97\x64\x6e\x7c\xd6\x20\x2b\xa6\xd2\x2d\xc1\x30\x06\xf2\x88\x6a\x09\xcd\xf8\x63\x44\xa6\x8f\x57\xb3\x1d\xd5\x74\xf9\x63\x02\x0f\x40\xef\xfe\x9f\xa7\x54\xe7\x9f\xde\x52\xa0\xfb\xb8\xfe\xff\xd8\x7b\x93\x1c\xc9\x91\xa4\x69\x74\xef\xa7\xb0\x0b\x30\x61\xaa\x6a\x23\xfe\xed\x7b\x6f\x17\x67\xf8\x80\xbf\xab\x0a\x5c\x70\x43\x80\xf0\x45\x9c\xfe\x41\x45\x94\x74\x8f\xf4\xc8\x8c\x1a\xba\xba\xfb\x03\x1a\xdd\x95\xee\xe1\x9c\x8d\x36\xe8\x24\x22\x46\x96\x09\x4b\xc5\x0e\x73\xbb\x4b\xfb\x7d\x11\xb2\x23\xb6\xd3\x7c\xa0\xdc\xc0\xc8\x97\xdc\xc0\xa8\x97\xdc\x00\x1e\x89\x45\x88\x39\xe4\x06\x04\x2c\x8c\xe3\xee\xa7\x89\x50\x76\x32\x25\x26\xee\xf0\x6b\x2d\xc5\x28\xf8\x9c\xff\xf5\x37\x70\xfb\x78\x07\xee\x05\xfc\x9b\x1b\x81\x60\x92\x8c\x4c\xcb\x75\xce\xc7\x85\xce\x8b\x5f\xf1\x95\x3f\x77\x47\xb7\xa7\x5b\xc2\x79\x9a\x2f\x7a\xf8\xe1\xb8\xee\xfa\x3c\xec\x77\x74\xae\x97\xfc\xe4\x3f\x1e\x72\xef\x05\x5a\xde\xb5\xfd\x08\x25\xc7\x82\x48\x92\x40\x51\x76\x2b\xe4\xb2\xd6\x45\xcc\x57\xba\xcf\x31\x3c\xf9\x15\xa7\x37\x66\xfb\x04\xa7\xf7\x1e\xd6\x61\xc9\xf9\xbe\x58\x6f\xab\xf5\x86\xc5\x18\xd5\x92\x9a\xdc\xba\x32\x10\x9b\x19\x85\x9a\x14\x48\x6e\xd5\x10\xf3\xa4\x46\x49\xd6\xb2\xa2\x0c\xe8\xb3\xdb\x29\xd2\xe0\xfb\x53\x5c\x86\x60\x9d\xdb\xdb\x98\x25\x95\x46\x96\x3a\x6d\xc9\xdd\xcc\xda\xf6\xea\xb3\x8c\x0f\xe2\x1e\xc2\x4a\xd2\x3b\xb9\xe9\x1b\x6e\xe7\xf2\xd2\x00\x09\x5d\x94\xf1\x7d\xb7\x9b\x80\x26\x1d\x41\x47\x3e\x4e\x6a\x68\xf7\xfd\x14\xfa\x32\x19\xdc\xdd\xaa\xa1\x90\x61\x53\xa1\x1a\x46\x11\x40\x6d\xd0\x61\x42\x3c\xf7\xa1\x9a\x31\x52\xdf\x98\xc9\x82\x65\x09\x29\x25\xaa\x68\xf8\x23\x26\x6b\xfb\xf4\x46\xae\x2d\x45\x21\xa7\x92\x94\x2d\x62\x36\x69\x69\x28\x15\x04\xed\xdb\x5e\x35\x8d\xca\xda\x82\xd9\x6f\xbb\xbf\x76\x64\xec\x4b\xc2\x25\x15\x78\xf6\x25\xb0\xb4\xa0\x28\x41\x34\xb8\x13\xe2\x5f\x50\x11\x5b\xf2\xaa\xb2\x82\xb7\x26\x48\x8f\x2a\xc2\xdb\x2a\x69\x42\x3a\x6d\x01\x72\x7b\xf1\x69\x19\x1c\xdb\x7e\xd3\xe3\x0e\x42\x0f\x64\x48\x4f\x93\x68\xea\x1e\x2a\x8a\x89\x8a\x11\x36\xde\xdf\x4c\x46\xaa\xb8\x51\x7f\x66\x80\x81\xc7\x0e\x5e\x84\x92\x19\xea\xf0\x91\x79\x29\x50\x94\xf7\xb7\x2e\x2d\x4d\x04\xd2\x2b\x3d\x68\xea\xd1\xed\x92\x7a\xea\x09\x26\x84\x25\x10\x3e\x49\x2a\xa9\x24\xc0\xe4\x88\xe6\x45\x93\x02\xaf\x0e\xb3\x9d\x4a\x76\x89\x59\xcb\x78\xb7\xf7\x45\xdf\xdf\xea\x54\xf4\x3d\x71\x4b\xb7\x24\x1d\x25\x0d\x01\x03\x1f\x0e\xa0\xe7\xd5\x12\xe9\x93\x7b\x03\xb1\x86\x68\x4f\xe2\xdd\x58\x7d\x11\x6a\xe7\x42\xd4\x09\x40\xaf\x8d\x5c\x58\x03\x12\xb8\x36\x92\x21\x86\x52\x20\x89\x48\x1e\x7c\xb0\x47\x80\x3f\x95\x40\x76\x09\xf8\xb4\x10\x8b\xac\xe9\x2b\x77\x46\x5f\xd2\xb9\xff\xd0\xff\x0e\x79\xa8\x4e\xe3\xc7\xdc\xd7\x9e\x37\xd2\x02\x35\x59\xa5\xce\x0d\x05\xb0\xa3\xee\x30\x32\x24\xa7\x02\x46\x45\x52\x26\xac\x65\x83\x61\xcf\x3e\x1d\x99\x2b\xda\x93\xee\xd2\x80\xff\x6c\x54\x9e\xa6\x95\xe4\xa7\xec\xf9\xee\x57\x59\x2c\x13\x7b\xbe\xce\xbc\x2d\x13\x44\xf1\x41\xe0\x4e\x53\xba\x34\x4e\x21\xb2\x2e\xec\xae\x4b\xa6\x21\x49\xf5\x39\x37\xc4\x60\x56\x2e\x02\x0e\x8b\xa4\x72\x2c\x35\x69\x75\xe3\xaa\xa4\x0a\x95\x26\x30\x13\xba\xeb\x5c\x4b\x3d\x5d\xa6\x72\x42\xe7\x6f\xc7\xc2\x1b\x86\x4f\x50\xe2\x52\x7e\x51\x45\x3f\x86\xce\x6c\xf2\xdb\x98\x33\x15\x1b\xeb\x7c\xdc\xf9\x57\xbd\xec\x25\x37\xfa\x0f\xfb\x6f\x2f\x2b\xea\xab\xb5\xfb\xd2\xb9\xad\x3a\xe4\xee\x9f\x4b\xaf\x1b\x96\xf0\x26\x7b\xf5\x25\x26\x83\xa1\xe0\xe8\x27\x67\xbc\xbf\xa3\xb2\x22\xb4\x5b\x12\xd5\x00\xfd\x86\xd2\x45\x2a\xe6\xd3\xc8\xc1\xda\x15\x44\xd4\x91\x18\x14\xbf\x7e\x5c\x69\xc6\x95\xe8\x42\x31\x06\xe2\x76\xab\x0e\x5d\x5b\xe7\x3b\x45\xb8\x05\xbd\xdf\xbb\x0c\x0c\x93\x3a\xc1\x71\xd2\x43\x27\x8a\x4c\x33\xf4\x93\xd0\x33\x6d\x05\xe3\x52\x22\x53\x6a\xde\x61\xa1\x23\xfe\xac\x10\x9d\x6d\xbe\x5c\xac\xbd\xf9\x05\x6e\xeb\xa2\x33\xfa\x7b\x1b\x1b\x8a\x67\xb4\xbb\xab\x01\xa6\x8b\x61\xeb\x97\xd2\x71\x45\x5f\xb2\x81\xff\x28\xff\xed\x54\x05\xd4\x11\xf1\xaa\x4d\x3b\x5f\xf5\xb4\xbb\xb4\xbe\x8a\xf5\x00\xa7\x40\xa3\x7e\x6f\xfe\x6e\x42\x46\x7b\xf4\x83\xf8\x0e\xe2\x3e\x84\xb9\xe8\x22\x24\x7e\x1b\x1d\x86\x0a\x62\xc6\xe6\x2e\xf3\xba\xd8\x39\x41\x4e\xbd\x2f\xb5\xd6\x75\x99\xea\xc6\xef\x4c\x36\x9a\x4f\x36\xf3\xae\x90\x77\xcb\xbe\x52\xe7\x84\xb5\x6d\xec\x95\x48\x2b\xa4\xad\x04\xe1\xd4\x31\x43\x0f\x48\xf3\x1e\x34\x35\x41\xfb\xfc\x55\x78\x51\x5f\xb2\x75\xff\xa8\xff\xed\x02\x24\x87\x51\xbf\x2a\x44\x25\xb2\x96\xbb\x4c\xdd\x7c\xac\xe3\x53\x79\xf2\x33\x9d\xf2\xfe\x56\x0a\xd8\x21\xf6\x65\x30\xb6\xf5\x21\x81\x78\xc4\x47\xfc\x7a\xa6\x19\xaf\xbc\xe3\xf7\x09\xc8\xaf\xde\xd9\x4b\x46\xeb\x1f\xed\xff\x3c\xc1\x10\xfc\xbd\xdc\x4f\x45\x42\xca\xf4\x81\x2b\x04\x5e\x15\x1e\xe5\x75\x9b\x1f\x37\x66\xfb\xd1\x61\xde\x42\x9f\x6c\xfa\x4f\xea\x21\xb7\xbf\xb5\x8b\x5c\xcf\x7d\x0a\x35\xae\x0b\xf0\x10\x8f\x5e\xf3\xd6\x87\xa4\x3a\x8d\xeb\x85\x95\x09\xd1\xf2\x9e\xc6\xe9\xc6\x0c\x4b\x67\x49\x90\x45\x52\x30\x44\x71\x1e\x7f\xd4\x47\xe1\x10\xeb\xe4\x21\x1e\x33\x52\x05\xf9\x55\x33\x54\xda\x59\xbc\xa7\xeb\x9e\xfa\xbc\x31\x76\x0d\xfe\x59\x62\x47\xad\xf0\xa5\xba\x57\x4b\x2a\xf9\x4c\x56\x4a\x3b\x31\x6d\xd7\x97\x73\x0b\xbf\x20\x30\x45\xcd\xe5\x52\x8f\xeb\xcb\xb9\xed\xab\xbe\xf9\x92\xb6\xfb\x47\xff\xef\x7c\xd2\x34\xa7\x36\x50\xfe\xb4\x50\x63\xd5\xf2\x7d\xa9\x0c\xbc\xaa\x46\x65\x52\x3e\x49\xca\x50\xc4\x85\x3b\x88\x72\x83\x0d\x34\x9a\xbe\xfe\x2c\x02\xc5\xa5\xef\x0b\x11\x2e\xf4\xfe\xa3\x80\x40\x4c\xb6\x38\x6a\xa7\x2c\x9c\xd5\x04\xc4\x0f\xea\x08\x77\x13\x24\xcb\xdc\x05\x12\x37\xa3\xea\x4c\xfe\x69\xe0\x1f\xe7\x17\xc4\x9a\x01\x29\xb0\xa4\x25\x12\xf0\x65\xa7\xdc\x52\x0f\x6e\xed\x85\x9a\x61\xe5\xc4\x3a\xdc\x40\x6e\x46\x59\xbe\x8c\x37\x49\x54\x20\xbe\xed\x3c\x4e\xa2\xfa\x2e\x68\xb0\xed\x4c\x6a\xc2\xc3\x95\xca\x7c\x5e\x7d\x7f\x1b\xda\x92\x94\x1a\xa4\xaf\xee\x2e\xec\xa3\xa7\x69\x69\xf4\xa4\xde\x4f\xf9\x19\x68\x16\xf8\x7a\x9a\xa3\x6e\xab\x1f\x68\xd5\x42\xf6\xf2\x20\x5a\xaf\x8a\xa2\x5a\xe2\xfc\x84\xd0\x25\xb6\xe8\x0c\xb5\x9e\xd8\xf3\x38\x8f\xc5\x3b\x13\xf7\x70\x41\x3b\xf6\x45\xef\x7f\x49\xd6\xfd\x63\xfc\xb7\xf7\x9f\x51\x55\xd8\x30\x50\xe1\x1b\xa0\xf8\x76\xf3\x35\xea\x7a\xaa\x32\xa2\x33\x33\xb9\x17\x6d\xac\xc4\x08\xe2\x18\xff\x09\xb0\x87\x91\x66\x8e\xa2\x9b\xaa\x09\x7f\x1e\xd8\xb6\x62\x11\x16\x6d\x39\xf5\xf6\x32\xce\x7a\xfb\xf9\x38\x2b\x8f\x71\xa6\xad\x26\x6d\xed\x3e\xf3\x16\x5f\xf7\xc9\x08\xcf\x24\xb1\x9a\x1f\xf2\x55\x2f\x78\x49\x70\xfe\x63\xfe\xb7\x17\x94\x91\xd1\x0b\xfc\xf1\x7d\x52\x41\x56\x0b\x0c\xf8\xdf\xea\x56\x19\xc9\x63\x6a\x44\x2e\xe6\x7b\xf2\xdd\x9f\x62\x00\x50\x95\x8b\x2f\xbe\xb8\x0a\xdc\x75\x88\xa4\x9f\xfc\x87\xb2\x2d\x71\xaa\x33\xcd\x12\x57\x40\x65\x92\x44\x89\x75\x43\xe9\x3b\x8a\x96\x50\x58\x30\x82\x4e\xbf\xf8\x54\x89\x98\x19\xaa\x19\x06\xf7\x5d\xb0\xf3\x08\xee\x76\x39\xf3\x71\x5a\x12\x8a\x35\xab\xa4\xb8\xdc\x08\x1a\x46\x15\x38\x8f\x5a\x70\xb7\x5a\xec\xc6\x07\xf0\xdb\x5e\xf0\xf8\x0b\xb7\x1f\xb1\xfb\xc6\x73\xe0\x14\x3c\xed\x71\x5e\xe7\xfd\xad\x35\x4d\xed\x4a\xa2\x10\x82\x70\x20\x55\xe7\x17\xb0\x91\x86\x09\x05\x29\x7c\x97\xcc\x46\xad\xdf\xc8\x8b\x28\x19\x4a\x87\x1a\xd5\x16\x62\x11\x49\xf1\x26\xf5\xf1\xe6\xc7\x5e\x09\x54\x0b\xd1\x0d\xb4\xd9\xd7\x95\x09\xf6\x9a\x48\x79\x10\x0f\x97\xd9\x53\xcf\xee\x01\x4f\x6f\x9c\x1c\xfa\x84\x02\xb0\xb0\x91\x73\x58\x08\x96\xe4\x1d\x75\xf2\xd2\x5d\x70\x92\xe3\x84\x41\x21\x22\x33\x58\xcd\xb4\x48\xd3\x64\x40\x0e\xfb\x3a\x42\xa2\x66\x6a\x39\xd7\x74\x92\x71\x53\x88\xe4\x54\x2d\x47\xa2\xae\x1c\x67\x49\x7e\x29\x07\x04\x23\x92\x91\xc8\x1e\xe5\xe9\x36\xf3\xaa\xc3\x40\x03\xab\x32\xa0\x26\x6e\x73\x3c\x24\x26\x4c\xfa\x21\x84\x7b\xa8\x31\x05\x09\x30\x61\xdd\xa5\x51\x53\x55\x47\x4f\x25\x23\xdb\x55\x94\xd5\xc2\x6a\x49\x01\x7e\x90\x64\xe0\xe9\x84\xf7\x90\x4b\x5c\x5a\x47\x49\x90\x4a\xd9\x29\x3b\x46\xe9\x77\x20\x0a\x80\xcb\x9c\x3d\x30\x35\x35\xe4\xa0\x75\x34\xd0\xc1\xcb\x49\x91\x6a\x5c\xe9\x14\x04\x01\x0d\x08\x4f\xd6\xda\xa0\x04\x06\xe8\x21\x00\x8b\x7c\x30\x7b\x23\xb8\x53\xda\x83\xa8\x5a\x01\x6b\x2b\x15\xda\x97\x41\x0f\x4c\x62\x6e\xd3\x80\x60\x10\x93\x43\xca\xd2\x45\x91\x08\x51\xd2\xb8\x82\x5f\x00\x09\x74\x1f\x54\x3f\x97\xbc\xfd\x9f\x62\xaf\x39\x91\x9f\x09\xd4\xab\xb0\xac\xbf\xa1\x12\x2a\xeb\xdd\xea\xdc\x16\xb3\x92\x94\xd4\x66\x25\x55\x91\x0d\xd5\x5e\xea\x96\x11\xbf\xdc\x17\xad\xe3\xfd\x6d\x82\xd4\xa0\xe2\xe8\x92\xd5\x27\x74\x20\x3e\x79\x06\x7f\x29\xf7\xc5\xea\x0c\x56\xa2\x3a\x36\xed\x9a\x64\x28\x75\xf0\xaf\x2f\x3e\x5e\xdf\xdf\xca\xa8\xa9\x9b\x6d\x71\x71\xde\xc9\x79\x5f\xe0\x71\xab\xa9\x95\x8c\x7b\x71\x9b\xe9\x8e\x5b\x10\xcb\x1d\x87\x5d\x97\x8e\x9b\x89\x2b\x13\xf3\x24\x50\x0f\x64\x46\xb8\x04\xac\xae\x95\x6d\x19\xe0\x58\x40\xed\x81\x44\x05\x18\xc6\x26\x2a\x0c\xc5\xb8\x03\xb6\xfb\x4d\x51\x58\xbc\x95\x7b\x45\xcc\xa1\x48\xc2\x9f\xdb\xb9\x93\xbf\x1f\x03\xb5\xac\x1d\x3c\xcf\x76\x5d\x00\xed\x61\x89\x17\xfe\xea\x1d\xbe\x06\xb9\x7f\xa6\x90\x2f\x23\xfb\x64\x5f\x76\xf1\xc9\xae\xb4\x14\x2c\xd2\x24\x9f\x6e\x51\x72\x2f\xd1\xc7\xc0\x3d\x8e\xdc\x06\x65\x85\x74\x80\xa8\x14\x03\x9f\xdc\xd4\x72\x92\x0f\xa3\x98\x02\x6a\x24\xa2\x79\xae\x8b\xac\x8b\xae\xa8\xbb\xe9\x4c\xd5\x80\x83\x33\x2a\xce\xc4\x17\xa5\xc0\x7e\x4a\x4e\x15\x10\x99\x43\x4a\x4f\x52\xa0\xc0\x40\x7f\x49\xd3\x80\xf1\x2c\x35\x0d\x77\xef\xdb\x21\x73\xa6\x21\x41\x84\xea\xbd\xa1\x8e\xbd\xd7\xe4\x5d\x4f\x95\xc4\x0d\xe3\x30\xc0\x7b\x67\xb9\xed\xd2\xa8\xe1\xd7\x42\x70\x49\x63\xa6\x00\x1f\x3d\xa7\xb4\x80\x5a\x91\xbf\x17\x12\x47\xe7\x97\xf7\x37\xb7\x08\xca\xbc\xc4\x45\x81\xcf\x9f\x76\x68\x46\x86\x6b\x17\xa4\x61\xb5\xe4\x34\x27\x0d\xf2\x1c\x00\xcc\xfa\x40\x77\x80\xa1\x15\x24\xcb\x8d\xf8\x13\x88\x57\x2f\x15\xc9\xad\x79\x4a\x64\x1e\xac\xc8\x1b\x9c\x59\xaa\xa5\xf8\x93\x04\x22\x56\x28\x69\x13\x00\x21\x39\x7c\x28\x55\x28\x47\x2c\x9d\x1c\xf5\x43\x8f\xde\xf1\xd7\xec\xbe\xed\x76\xcd\x8a\xb2\x13\x7a\xa7\x98\x30\x01\x8c\x1c\x94\x41\x88\x17\xe0\xbd\x99\x8c\x06\x6e\x97\xf7\xd4\xb1\x00\xb3\x3e\xd3\xfb\xff\xec\x1b\x46\x51\x1e\x7b\x6b\x09\xc9\x2a\x4d\xad\x84\xd1\xa8\x00\x83\x20\x37\x45\x7b\x31\xb8\xe1\x91\x8c\x03\xd2\xd6\xca\x43\x50\x6d\xc4\x2a\xbc\x74\xa0\x7a\xc8\xe3\xd3\xfd\x8b\xf7\x42\xf7\x47\x7a\x8f\x5f\x66\x23\x08\x68\x81\x7a\x00\xe2\xf4\xa2\xf4\xbb\xdc\x8d\x27\xe4\x09\xfd\x71\x7c\xcd\xbb\x61\xaf\x41\xfa\xd7\x5a\xbd\x8f\xbc\x1b\xc8\x72\x0b\x50\x70\x5f\xca\x1e\x1f\x7f\xaf\xfe\x72\xc8\x2f\x07\x31\x19\x49\x02\xc8\x22\x60\xcd\x5f\x90\xcf\x73\xe8\x9b\x65\x77\x63\x66\x80\x23\x58\x47\x48\xe3\x0f\x6c\xf5\x8d\x00\x8e\xcd\x38\x6c\xe6\xf7\x37\x5f\x52\x01\x92\xe1\x0e\x94\xba\x87\x1d\x87\x73\x1c\xfc\x60\xe4\x1a\x27\x00\xfb\x7a\xc7\x35\x71\x96\x23\x3e\x83\xad\x0e\x8c\x97\xb8\x33\x5e\xe1\xe9\xc8\x38\xeb\x12\xf7\x74\x2c\xbc\xc7\x88\x8a\xfb\x2e\xe7\x79\xe3\x99\x78\x4a\xad\x2d\x8a\x4c\x95\x80\x5f\x98\x78\x42\xf3\x2c\xf0\xc1\xcf\x7f\x3c\xef\x15\x7f\x2c\xf1\x97\x9c\x4c\xdc\x72\x9d\x81\x7f\xdc\x8e\xe7\x1d\x7d\x99\x18\xee\xd3\xda\xa3\x55\x27\x65\x42\x79\x73\x47\xdc\xe4\xd3\xad\xfb\x83\xb1\xe5\xfd\xb1\x8e\xf3\x41\xbf\xea\x94\xaf\x41\xfe\x57\x4a\xb0\x27\xc8\x74\x6f\xf9\xd2\xfc\x76\x97\x81\xb3\xb5\x21\x3c\x39\x20\x40\x16\x45\xb3\xac\xf1\x72\xdb\xca\xac\x9d\x9c\x5b\xfe\x35\xd8\xb7\x88\x71\x82\xed\x35\x4a\x8a\xc3\x70\x36\x43\xee\x17\xb2\x82\x3d\xd1\xd0\x52\xe8\xd3\x80\x25\xa2\x97\x04\x15\x5f\xd5\x11\x49\xfc\x02\x80\x5f\x8b\x55\xe3\xe0\x32\xe2\x8b\x70\xa0\xd7\xc1\xfd\xbe\x28\x85\x33\x2c\x44\xb2\xca\xa1\x40\x45\x00\x0d\xab\x84\x79\x55\x89\x6f\xfe\x25\x17\x82\x61\x6f\x71\x8c\x1f\x52\x25\x69\xd4\x28\xab\x9d\x2c\xfa\x6e\xd8\x1d\x71\x03\xaa\x72\x07\xff\x98\xcf\xf6\x26\xc9\x3a\x85\x33\xf0\x00\x0b\x9f\x60\xf6\x30\x1f\xbf\xae\x17\xf9\x7f\x5e\x6c\xe8\x5f\x5e\x79\xc0\x9e\x5e\xce\x4c\xad\xe9\x3e\x92\x4a\x87\x74\xa2\xdf\x99\x65\xb7\x66\xc7\x5a\x1f\xf9\x74\xd2\xdd\xd3\xc1\x0c\xe9\x61\xf7\xb0\x49\x7c\x05\x64\x2e\x2b\xb8\x4b\x30\x4a\xd4\x0b\x9f\x51\x4f\x8c\x59\x60\x87\xa8\x14\x28\xb5\xec\x15\xfa\xf6\xa0\xac\xc7\x3c\x7a\x46\x04\xbd\x9f\x63\x5e\x05\x9a\xad\x74\x48\xd0\x6c\xd2\x40\xde\x3e\xfd\xcd\x54\x4b\x58\xcd\xa3\xcc\x41\x4f\x6f\x2c\x9f\x6c\xf5\x23\xb3\xc8\x6e\xd2\x11\x0d\xa6\xf9\x44\x7b\xb4\x58\x2a\x72\x8b\x75\x8e\x3c\x0c\x56\x59\x2a\x67\x89\x30\x7a\x09\x1c\x9c\x74\xe8\x90\x57\x3d\xea\x0c\x5d\x5b\xef\xaf\xbb\xc0\xcb\xc6\x04\x1f\x94\x19\xe0\x1d\xf1\x75\x10\xa5\x9b\x88\x94\xb9\x89\x6c\xa1\x41\x31\x04\x1c\x33\xcb\xc9\x9e\x92\xe8\x56\x84\x34\x39\xe2\xa4\xc8\xef\x12\xcb\x6c\x3d\x81\x63\x1c\x2c\x01\xa0\xad\x03\x96\x17\x4e\xca\xc6\xcc\x9f\x50\x52\x11\x6d\x3c\x40\xc5\xcf\xf7\xd0\x6a\xd4\x60\x4e\xe6\x6d\x50\xb0\x30\x2e\xfa\x2c\x54\x30\xe7\xdb\x01\x72\x0a\x5f\xee\x51\x42\x53\x2a\x04\x0e\x42\xec\x61\x44\xc9\x65\x6f\xa1\x66\xd3\x63\xb5\xdf\xbc\x8d\xdb\xde\xb0\xd2\x63\x9d\x13\x09\x99\x3a\xac\xda\x87\xe4\xf8\x82\xf0\x99\xdb\x24\xd6\x13\xac\xfb\x03\xfa\xa4\x69\x1a\x80\x1c\x5d\x43\x2c\xa1\xa0\xc1\xdc\xd3\xec\xf4\x9e\x51\xe6\x2f\x06\x05\x2e\xdb\x11\xb3\x98\xa1\x50\x54\xda\xd1\x14\x0f\xea\xe6\x5d\x1d\xc7\x89\xec\x0a\x99\xa1\xde\xc9\xae\xb2\x8c\x11\xf2\xa6\x16\x81\x40\x71\x67\x2b\xdc\xd5\x76\xdb\x51\xef\x8b\xda\x2e\x84\xe6\xa0\x40\xa1\x40\xda\xfb\xcd\x45\x0e\x6c\x11\xaa\xd1\x58\x95\xd4\x8b\x4f\x8d\x34\x3e\x46\x4c\x3e\xfe\x24\x14\x1d\xab\x3f\xaf\xe7\xe0\xa8\x7c\xf1\x58\x7e\x79\x61\x14\x7b\x5e\xc7\x31\x07\xb8\x7d\xdf\xdc\x6c\xcf\x23\xa1\x3e\xa9\xa6\xd0\x7b\xd5\x61\x9c\xfe\xb6\x3a\xdc\xca\x82\x80\xce\x04\x9a\x62\xce\xad\xd5\x54\xfb\x2e\x78\xeb\x6d\x24\x30\xe3\x2b\x04\x47\x50\xd1\xb2\xc3\xa0\x53\x1a\x50\x40\x2b\xf6\x96\x8a\x2f\x69\xa8\x78\x1c\xde\x01\xbd\x2b\x15\x14\x90\xeb\x46\xd3\xc8\xf6\x65\x0e\x52\xde\xcc\x91\x6c\xd4\x83\x1f\xdb\xb9\xf5\xaa\x8e\x89\xc3\xb8\x70\xee\x64\xec\xca\x41\xdd\xa5\xa1\x97\x9d\x27\xa5\x14\xc5\x9d\x9e\x0a\xa2\x75\xb9\x6d\x64\x9c\xdf\xc9\x71\x42\x16\x1b\x4a\x1a\xd4\xab\xea\x0e\x0d\x70\x6f\x6d\xaf\xd0\xfd\x81\x37\x82\x07\x1b\x6d\x57\xcd\xa9\x14\x3c\xaf\x3f\x6e\xa3\x38\x7b\x29\xa9\x66\x6f\x9a\xe9\x9e\x92\xf5\x9e\x46\xf6\x41\xea\xfd\x7e\x80\x5b\x16\xc4\x71\x18\x46\x47\x0c\xa7\x4d\xdd\x67\x1d\x91\xfa\x74\x5b\x11\x5a\x9e\xcd\xa7\x08\x7f\x0b\x4d\x77\xb4\x0a\x9c\xd7\xd2\x71\x08\xa8\xa6\x8a\xec\x8c\x00\xe7\x38\x24\x43\x06\x54\xb2\x6f\xc6\xd6\x49\x29\x05\x48\x4d\x54\x9e\x6e\x91\xa6\x37\xd8\xda\x6e\x0a\xfb\xee\x6d\xe2\x0e\x06\xa9\x72\x41\x8d\x57\xd2\x00\x06\x68\xc4\xbd\x8f\xec\x23\x77\xfa\x63\x61\xff\xf3\x44\x7b\x9d\xa9\x8d\x84\xf3\xb7\x6d\xc1\x65\xb3\x37\x82\x80\x62\x41\xf2\xc1\xfb\xc2\xa6\xc5\xb7\x01\xcd\xc3\x23\x96\xd1\xb6\xf3\x01\x5b\x83\x50\xdb\x84\x6e\xa1\xbb\xb7\xbe\x8a\x16\x10\x64\x37\x46\x5b\x10\xef\x14\x0a\x2b\xb2\x67\x11\xad\x0c\xd9\x74\x76\x3a\xd9\x7c\xcf\xea\xbe\xe5\x08\x7d\x43\xef\xa3\x03\x9d\x0a\x92\x9e\xb9\xc1\x21\x52\x37\x43\x7a\x8d\xd2\xc8\x10\x3c\x96\x9e\xeb\x03\x63\x53\xd9\xa4\xde\xe7\x78\xf4\xae\x88\xbb\x97\x99\xd0\x4d\x7d\x4c\x0c\xa8\x7b\x64\xf3\xde\x15\xac\x29\x18\xda\x15\x3d\x02\xa6\x0e\x22\xf3\xd1\x51\xfd\x38\x9e\x0a\x8d\x32\xc8\x42\x61\x03\xf8\x1e\xdc\x47\xb3\x47\xff\xb7\x8a\xe3\xbc\x2b\x0d\x3c\x17\x64\xea\x7c\x9c\x49\x9b\x7c\x64\x7f\x62\x76\x46\x24\x6a\x85\x2d\x24\x76\x47\x08\x79\xa2\xf0\xef\xea\xc6\xb7\x43\x31\x48\x3a\xab\xcc\x7b\x19\xf1\xb0\xd2\x8d\x3c\xa3\xc9\xec\x0a\x62\xa9\x4f\x9a\x0c\x29\x50\x08\xc7\x24\xb5\x7e\x7e\xa3\xde\xda\x19\x69\x88\x29\x98\x8e\x94\x1f\x47\xea\x53\x3f\xdb\xe3\xdb\xd3\xf6\xa7\xc3\x1e\x27\xbb\x2e\xf0\xb8\xe8\xe3\x4e\xce\xbb\x8b\xe0\xc3\x69\xde\xf9\xf3\xfc\x1e\x97\xe2\xf6\x57\x7d\x8a\xe3\x4b\xdf\xe6\x77\x4c\xca\x2f\x21\x88\x5f\xae\x3a\xbb\xea\x7d\x45\x2f\x75\x0d\x30\xbc\x22\xaa\x4d\xc6\xc9\xdc\x53\xb3\xdd\xcd\x5a\xef\x31\xad\xec\x6e\xc4\x9c\xa6\x8c\xbc\xbf\xd5\xd2\x52\x9b\xe5\x94\xc9\xea\x98\x55\x4e\xbe\x4a\x9f\x82\x80\xf2\xcd\x3e\xe0\x67\xf6\x3e\x8b\x60\x02\x81\x6d\x12\x18\xdc\xf7\xb7\x2e\x9a\x7a\x9b\x77\x51\x3f\x96\x64\xb4\xa0\x56\xc2\xea\x5e\x19\x61\x47\xed\xfa\x84\xbc\xd6\x83\x80\xf2\x58\xb0\xc0\x15\x94\xd3\xd7\x4b\x26\x37\xeb\xd1\xb1\x22\xb6\x7e\x77\x93\x0e\xcb\x64\x67\xa2\x64\x54\x44\x8e\xaa\x1b\x47\x7e\x8f\xd8\x01\x80\x58\x23\x3a\x96\x42\xa6\x39\x72\x62\xc1\x26\x59\xa9\x16\x8a\xb9\xba\x22\x38\x91\x16\x5f\x41\x80\x33\x56\xf0\x4b\x78\x33\x81\xbc\x2e\xcd\x09\x3a\xb7\x54\x58\x5d\x09\xf3\xf9\x84\xd6\x91\x8b\x2c\x08\x40\x4b\xf1\x51\x5d\x41\x65\x04\x08\x81\xa6\x9e\x41\xd7\x0f\x2c\x0c\x6a\x2d\xb3\x6f\xb7\x9e\x26\x26\x00\x7b\x7f\xeb\xde\x61\x6a\x46\x41\xcd\x02\x8c\xe5\xa2\x69\xe8\xdd\x40\x46\x52\x5a\xd2\x04\x8d\x77\xeb\xb0\x00\x2c\xb9\xad\x21\xf7\xc5\x26\x59\x7c\xa1\x33\x94\x96\x4e\x12\x13\x77\x95\xda\x5d\xdc\x7d\xb7\xc0\x1c\x73\x4a\x3b\xe3\x9b\xd5\xfc\xe4\xaa\x75\xad\x4a\x4d\x55\x72\xe5\x1c\xf1\x79\x17\xe9\xeb\x22\xd9\x9f\x67\x68\x32\xef\x1c\xeb\x22\x3e\x19\x23\x87\xe0\x0d\x57\xef\x64\xa2\xcb\x77\xb7\x51\x76\xd0\x8b\x58\x87\x7a\x11\x71\x4a\x80\xfb\x28\x3e\xef\x8b\xae\x28\x6b\x85\x80\xb0\xbf\x14\x58\x45\xad\x84\xa4\x75\xa5\x57\x72\x62\x22\x29\x8a\xbb\xf8\x88\x27\xe7\x44\x43\xb2\x29\xfb\x7a\xf0\xfe\x36\xfd\xd5\xe4\x8e\x07\x37\xea\x6c\x36\x0b\x53\x9e\x7a\x3a\x2d\xe4\xb1\xe3\xc5\x04\xb8\xdd\xa7\x55\xff\x43\x43\x13\x8c\xf6\x21\x61\x8a\xbc\x78\xd3\xbf\x4d\x61\xfd\xef\x14\x58\x2f\xf6\x92\x68\xfd\xe5\x85\x9c\xf3\xc9\x42\xab\xd3\x3d\x37\xb0\x72\x65\x0a\xfb\x4a\xf6\x67\xa8\x2c\x1c\x27\xb9\xc6\xc5\x12\x46\x02\xbe\x2c\xbb\x54\x20\xd0\xaa\xfb\x2a\xf5\xfd\x0d\x62\x7a\xdd\xdf\x67\x13\xa0\x8e\x7d\x84\x2e\x63\x26\xe0\x77\x95\xa1\x4a\x56\x16\xd7\x93\x56\x8d\x7f\x5b\x7d\xa2\x87\x13\xeb\xef\x6f\x23\x43\x4b\xca\xdd\xdc\xac\x54\x08\x87\x9a\xea\xa4\x86\x69\x23\x76\xbc\x9d\xf1\x2e\x08\xd5\x01\x7e\xcb\xaa\x41\x28\x86\x22\x90\xb0\xb3\x62\x9b\xbc\xbc\xec\x02\xa1\xa3\x45\xbe\x44\x93\x90\x0f\x06\x53\x30\x6c\x36\xa5\x72\xda\xa2\x7a\x40\xe5\xaf\x9e\xb2\x99\x28\xfb\xc0\x3e\xad\x1c\xe1\xea\x9c\x80\x5d\xb0\xb6\x36\x30\x06\x97\x7d\x69\xc4\x59\x42\x12\x93\x51\x8f\x96\x8a\x1c\xac\x1c\x1f\xe0\xee\xba\x4a\xda\x73\x42\x83\x63\x8a\xae\xf7\x02\xd3\xa9\x60\xd9\x4a\x02\x0c\xb7\xdb\x97\xcd\xbc\x5d\x7c\x6b\x57\xce\x18\xd4\xf9\x04\x50\x9e\xe1\x4e\x64\x8a\x80\xe1\x9b\xc9\xdf\x27\xc0\x41\x6a\x15\xdc\xc8\xfb\x44\x51\x9e\x4f\xbb\xa5\xdf\xc8\x8f\xa0\x32\x52\x81\x52\x18\x53\x31\xeb\xa2\xaa\x7b\x49\xa5\x26\xf7\x5d\xca\xbd\x65\x9f\x21\xa7\xdb\x94\x49\x74\xac\xbe\x99\x6e\x1d\xea\xea\x05\x34\x11\x24\xe6\xf3\xb7\x0c\xfa\x69\x5f\x42\x7d\x3e\x28\x7a\x5f\x64\x36\x52\xe9\xd0\xf9\x2c\xa4\xdf\x46\x66\x04\x8b\x0e\x28\xa5\x73\x72\x67\x0f\x85\x81\x7d\x04\xfb\xcf\xd4\xc3\x2f\x99\xed\x6e\x55\x56\xc5\x63\x93\x56\x3a\x09\xbd\x31\x84\xff\x7d\xde\xf2\xe5\xe5\x2e\x33\xaf\xb3\xdd\x91\xc7\x06\x7b\x5c\x1a\x73\x55\xed\x40\x42\xa0\x2d\xd1\xab\x57\xe9\x72\xf3\xdb\xca\x27\xae\x81\x4e\x73\x88\x89\xeb\xba\x8c\x7a\x5f\xac\x45\xef\x14\xa4\x83\xc4\xe4\x24\x8b\x9e\xa0\xf5\x11\xd8\x48\x06\x00\x38\x12\x4f\x78\xba\xcc\x48\x6b\xe3\x39\xa1\x57\x46\xab\xb9\x84\x43\x9d\xb0\x8b\xdf\xe0\x4c\x2c\x83\xcc\x76\x80\x9a\xb2\x94\x1d\x7b\x4f\x72\x12\x01\x6a\x3f\x2e\xa7\xfa\xab\x91\xfe\x92\x4c\xff\xe5\xaa\x51\x1d\x79\xa6\x6a\xba\x69\x6b\xa9\x4c\x5f\x2d\x28\xd4\x08\xaa\x38\x02\x2d\x60\x37\xbb\xe7\x3d\x41\x0c\x95\x00\xc6\xab\x35\x99\x28\x72\x08\x9b\x36\xc8\xd2\xd9\x7d\x31\x2d\xab\x8f\x48\x93\xf1\xbf\x71\x52\xa4\x91\xf4\x52\xce\xf9\x4b\xfd\x09\xff\xff\xf0\x16\x79\x22\x42\xe9\x17\xbd\x68\x54\x22\x22\xab\xc0\x8a\x46\xf1\xf5\x1a\xbd\x9b\x8e\x14\x04\xfc\x60\x1b\x40\x32\xda\x87\x81\xba\x41\x35\xea\xdc\x03\xd4\xc9\xe8\xa7\x31\x30\xc8\x50\xd3\xf0\xb6\x02\x63\x00\xdd\xf5\x24\xa7\x50\x21\x75\x0a\xa5\x90\x84\x10\xfd\xf6\xa1\xd3\xae\xd2\xdd\x78\x91\xd1\x8e\x36\x93\x80\x58\xcd\x3d\x1c\x05\xd1\xf9\x24\xf5\xa5\x34\xa2\x63\x83\xab\x17\x33\xf5\xc9\x8a\xf7\x4c\x8a\x57\x9f\x82\x7e\x5c\x88\x9f\x88\xf3\x82\xb1\xe1\xe4\x24\xf4\xfe\x4f\x5b\xce\xed\xf9\xb3\xca\xc0\xbf\x93\x01\xbe\x8f\x7d\x69\x97\x80\x6a\x14\x47\x81\xc2\xed\x8c\x88\x21\xd7\x0f\x4b\x09\x86\x98\x5b\x32\xc2\x18\x9b\x4f\x8e\x94\x22\xc5\x4a\xbf\x88\xed\x13\x38\x28\x70\x85\x82\x12\xd7\x57\x18\x37\x53\xa5\xda\x61\x03\xcf\xbf\x9c\x9f\xe7\xef\xcb\xb9\xe3\x12\x07\xe2\x73\xc1\x17\xb2\xcc\x29\x77\xf6\x3f\x6f\x64\xbe\x92\xc1\xd0\xa9\x14\xd4\x42\xa9\x0c\xe8\x66\x6b\x26\xe2\xa2\xe4\x03\xcb\x82\xcf\xf6\x27\x79\x99\x1d\x8c\xca\x69\xc3\x13\x03\x60\xd4\x4a\xd2\x56\xa3\x53\x53\xb3\x5e\xfb\x21\x30\x2d\xfc\x1e\x91\x3e\x56\x5f\x4b\x60\x46\x72\xbd\xbd\x5a\xee\x78\xb4\x27\x56\xa0\xc4\x46\xfd\x1d\xbd\xfc\xa5\x00\xf6\x97\x9f\xb1\x80\x6a\xcf\xa9\xb3\xea\x07\x63\x38\xa1\xc4\x06\x7a\x82\xa9\xcc\xc3\x67\xf3\x1a\xc0\x24\x04\xef\x8c\x6b\x1f\xcc\x71\x2c\x36\x78\x97\x03\x61\xea\xe0\x6a\x9f\xa0\x30\x9e\xa9\xb5\x64\x6e\x8d\xb5\x9d\x5c\x23\x3e\x13\x2d\xb5\xee\x65\x12\xa9\x95\x41\x03\xdd\x85\xf5\xbe\xa4\x3a\x86\x5f\x5d\x0e\xf4\x10\x0e\x71\x36\x35\x18\x35\x01\xd7\x1d\x9b\x1f\x00\xd8\xd6\x30\xb8\x1a\x52\xf3\x13\xfd\x91\xbf\x9e\x89\x2a\x17\x32\x0a\x7c\xa3\xf8\xef\xc1\x72\xd2\x43\x29\x05\x0c\x66\x51\xb0\xc6\xb1\xf8\x43\x51\x76\x70\x92\xc1\xc5\xba\x8e\xa4\x70\xb8\x1b\xf9\x58\x18\x9b\xab\x17\x91\x02\x56\xad\x6f\xa1\x3c\x70\x7e\x51\x88\x01\x33\xda\x48\xa0\xb8\xff\xc2\x1d\x02\xf4\x65\x49\xb6\xa5\x82\x6a\x0e\xae\x0d\x04\x30\x8d\x55\x11\xa8\xce\xd2\xcc\x98\x29\x67\x07\x77\xc8\xa1\xf4\x4d\x0a\x96\x46\x68\x4d\xe1\x2a\xdc\x18\x07\xe5\x40\x83\x02\xbb\x79\x67\x9e\xfd\xb4\xed\x11\xcc\x46\x29\xe4\x48\x9a\x81\xe8\x84\x77\xc2\x55\x10\x35\x1b\x89\x01\xcb\x82\x90\x6e\x39\x17\x2c\x58\x4f\x91\x5f\x10\x52\xc5\x35\x60\xcc\x02\x5f\x8d\x20\x02\xa1\xa5\x5c\xfd\x8c\x20\x6a\x09\x27\x08\x54\xbb\xfe\x32\xf0\x2e\x31\x8f\x62\x1d\x4c\xd4\x48\x10\xd0\xda\xed\x22\x49\x53\x30\x64\x1f\x00\xd4\x89\xb2\x96\xac\x24\xdd\x35\xf9\xff\x00\x12\x32\x02\x04\x84\xb1\x4e\x96\x82\x80\x42\xb6\xb2\xd0\x08\x3b\x04\x73\x02\xee\x0e\xc5\x8a\xc2\x0a\x62\x12\xff\xde\x22\xb5\x09\x4b\x6e\x5d\x24\x0e\x88\x67\x86\x88\x2c\xd8\x59\x2a\x73\xff\x82\xba\x31\xed\xa0\xb6\x4c\xa5\xfd\xbc\xf2\x9c\x63\xef\xa5\xc0\xf7\x97\xfe\x93\x4a\x80\x0a\x96\xbf\x5e\x59\x9c\xb0\x68\x4d\xad\x81\xbc\x5a\xaf\x6c\x6d\x3f\x6d\x50\xd8\x5d\x61\xe4\xb9\xd1\x81\x3f\x4b\xc8\xa5\x43\x79\xbd\xb8\x9d\xe2\x07\x73\xd4\x80\x65\xeb\xfd\x4d\xcc\x9f\x08\x64\x98\x28\xaa\x83\x28\x72\x8e\xb4\xaf\xea\x49\xbb\x4b\x2c\xa3\x3e\xc5\xf1\x4b\x08\x58\x40\x53\x06\x1d\x3f\x43\x55\xfe\xdc\x8f\xe5\x73\x71\x1a\x8e\xd2\x2a\xa0\x06\xe9\x1f\x1e\x0a\x9e\x54\x3b\x2f\x58\x6f\x7f\xfa\xc9\x6a\xe8\xd3\x87\x73\x16\x91\x26\xd5\xe7\xa7\x6b\xf1\x6c\x7f\xed\xc9\x6c\xe2\x7a\x78\xae\xc6\xa7\x2a\xb5\xa5\xd9\xc8\x38\x5c\x20\xfa\x5e\x7c\x39\x65\x2d\x9c\x20\xca\xe0\xa7\x7f\xcc\x1f\xc7\x12\x31\xa9\x81\xb2\x5f\x04\x19\xc8\x60\x52\x95\x91\x64\xa3\x1b\x6e\x27\x21\x55\x25\x4d\xec\x52\x03\x76\x87\xfc\x53\x3f\xd8\x81\x99\x92\x42\x8a\x09\x79\x19\xac\x5d\xda\x37\x77\x08\x7c\xf4\xeb\x84\x61\x94\xf0\xa5\x80\x63\xdb\xef\x6e\x22\xb6\x25\xee\xc9\xa3\x4a\x07\x0a\xd0\xb0\xa9\x04\xb5\x55\xa8\xcd\xe0\x64\xdb\xda\x01\xf4\x2f\xd4\x5c\xae\x4c\x61\x50\xc7\xe7\x32\x52\x09\x27\x10\xc5\x65\xe1\x23\xd1\x3e\x09\x1a\x9f\x69\xdf\xea\x56\xa9\xa3\xba\x91\x4d\x3e\x83\x77\xb8\xd2\xc9\x47\xf9\xd8\x62\xfd\x43\xc3\xb1\x88\x80\x2d\x47\x1d\x18\x36\x9c\xb6\x72\x5c\x5f\x9e\x37\x9f\x07\xed\x02\xc3\x1c\x44\x3e\x9d\x95\x25\xa4\x98\x98\x7a\x8c\x80\x44\x7e\xed\x2b\x97\x97\xaa\x84\x5f\x7e\x46\xab\x2a\xdd\x57\xf7\xaa\x01\xd7\x2e\x08\xcd\x80\x1c\x14\xc9\x96\x6a\x8d\x98\xca\x09\xb2\xfa\xa5\xd0\x68\x73\x0f\xd4\x10\x4d\x5a\x84\x14\xcc\x25\xd5\x6d\x29\x6e\x9a\x20\x08\x0e\xc8\xf0\x24\x9d\x08\x4a\x01\xb1\x44\x5e\x7c\x2d\xaa\xe8\x6d\x33\xf5\x48\xfe\x45\xbb\x4b\x50\xf1\xdf\xad\xcc\x0d\x32\x4e\xb9\x4e\x60\xe1\xa6\xdb\xf4\x75\x5b\x6c\x46\x88\x1f\x60\x2b\x54\xce\x56\xac\x1f\x05\xec\x60\xc0\x89\xb6\x92\x60\x5c\xd7\x34\xfd\xb7\x49\x21\x60\x38\xdd\x3f\x67\x8c\xf8\x9f\x52\x5e\xd2\xe7\xbf\xbc\x30\x66\xfe\x5d\xad\x57\xb5\x27\x15\x6f\x3d\x04\xba\xdd\xdf\x0b\x08\x38\x4a\xf1\xf5\x19\x09\xf0\xd4\x7a\x57\xdb\xb1\xe5\x4a\x75\xd7\xa7\x6b\x92\x69\xdf\xb7\x92\x25\x9b\xdf\xb7\x12\xc2\xef\x09\xe1\x33\x9f\x15\x54\x93\xb6\x4d\x11\x18\x07\x0c\x11\x5a\x17\x43\xfb\x86\xb4\xbf\x58\xbf\x6d\xa3\x19\x08\x74\x96\xe2\x56\x5c\x9f\x5f\xd5\x24\x94\x57\x37\xe5\x51\x3a\xfa\x44\xd5\x25\x35\xe4\x61\x14\x99\x3c\x88\x96\x17\x44\x1f\x89\x68\x3f\xd8\x32\xcd\x1b\xa2\xc3\xed\x36\xed\xcc\xc3\x2e\x98\x0e\x32\xaa\x82\x3a\x51\xfc\x98\xc6\xdd\xa3\x8a\x28\xe6\x06\xe0\xbb\xc1\xf4\x9d\x49\x6b\x0a\xea\x01\xce\x61\x0a\x9d\x6c\xef\x5c\x1d\xc1\xd9\x7e\x80\x9b\xb9\xea\x49\x0f\x4d\xdf\x16\x31\x3f\xcc\x37\xcc\xf6\x91\xc7\x1d\xbf\x1c\x5c\xf4\xe7\xb8\x32\xce\xf1\xfd\x69\x1f\xb7\x56\x9e\x8e\x5e\x1e\x67\x45\x06\x0f\x51\x7a\x70\xfb\x12\xfc\x9e\xc3\x13\xc7\xad\x83\x93\xdf\x22\x14\x55\x40\x6a\x8d\xf8\x70\x89\xb8\x41\xc9\xeb\x52\xca\xf8\x54\x5c\x95\xec\xa9\xe0\x19\x48\x75\xfa\x72\x20\x3d\x81\x42\xa3\x6c\x42\xed\xf6\x09\x91\x04\x58\x3b\x98\xa7\x85\x31\xcb\x51\x42\x96\x69\x17\xf0\x83\xc7\x1b\x38\xae\x77\x72\xbd\xa6\x78\x71\x0f\x1d\xc5\xa5\x94\xf1\x81\xc5\xf3\x76\xd1\x78\x7e\x14\x9a\x3c\x61\x2d\xed\x85\x16\x53\xb5\xdc\xad\xbe\x80\x5d\x9e\x74\xf2\x4e\xb2\xcc\xaf\xba\xe0\xab\x0f\xf1\x7f\x9f\x69\x60\x28\x4b\xeb\x4d\x91\xa3\xb4\x04\xa1\xf3\xe5\xa9\xa8\x64\x79\xaa\x35\x59\x1e\x15\x28\x7f\xa5\x16\xe5\x93\x52\x14\x9c\x3a\xbe\x3d\xb6\x2e\x8f\x43\x96\xf3\x34\x7f\x9d\xe6\xee\xf6\xef\xe3\xb9\x2b\xaf\x76\xe5\xcf\xb4\xd6\xa5\x0d\x65\x25\xd8\x52\xc2\xfd\xf6\x25\x3e\xb8\xab\x8c\x5f\x9f\xb6\xd1\x41\xba\xbe\x21\x36\x14\x71\x79\x16\x96\x5a\x2a\xb4\xcf\xa8\x3a\x55\xda\x81\x31\xe1\xaf\xa1\x23\x97\x81\x19\x5d\xc1\xf6\x28\x25\x6f\x8b\x24\x9b\x82\x32\x26\x30\x5b\x08\x56\xb2\x02\x1b\xa7\xac\x4b\xeb\x15\x09\x1b\x1f\x8a\x02\x3f\x48\x02\xf5\xed\x33\x3d\x88\xe1\xac\x93\x01\xae\x28\xb5\xc2\xbc\x0f\x43\xd4\x85\xd5\x2a\x86\xaa\x0f\x4c\x23\x70\x00\x6f\x84\x24\x85\x11\x09\xba\x52\x9a\x7a\xd0\x03\xa1\xad\x02\x26\xee\x1c\xd2\x6c\x67\x63\x8c\xab\x31\xe8\x2d\xa1\x26\x88\x05\xf6\xfd\x6c\x0c\x72\x4f\xd6\x28\x9b\x94\x10\xbb\xcb\x94\x98\x23\x4c\xd0\x1a\x3d\x40\xc4\x62\x3b\x35\xe0\xa2\x51\x8c\x8d\xe2\x8b\x43\xaa\xfd\x3e\x10\x32\xb5\xc4\x68\xc1\x91\x93\x5d\x1c\x0b\x11\x0b\x02\xd7\x64\x44\x46\xda\xb9\x56\xc9\xc9\xef\x31\xe0\xb7\x49\x4c\x59\x7a\xb8\x9b\xa7\xb7\xc3\x5d\x1d\x29\xe4\x52\xad\x21\x0c\xad\xa9\x0c\xbf\x33\xd5\xbd\xb4\x87\x6e\x21\x15\x19\xce\xaf\x7b\x61\xad\x7a\x8b\x36\xb9\xbe\x91\x04\x93\x10\x47\xd5\xe3\x6c\x4f\xc6\xbb\x99\x6b\x2b\x8f\xb2\xd9\x85\x88\x01\x1a\xd1\x25\x18\x5f\x99\x68\xc6\x92\xcc\xb0\x53\x76\xdf\xdd\x67\x33\xa6\xa1\xf0\x07\x30\x18\x58\x6a\x17\x5b\xdb\x9c\x71\xdd\x91\x6c\x07\x1f\xa0\x24\xd3\xcd\xff\xc9\x11\x71\x40\x60\xac\xe5\x1b\x81\x6d\xee\xe1\xb1\x6a\xe7\x1b\x85\x7f\xc4\x22\x3c\x13\x66\x3e\x5a\x02\x5a\x56\xc4\x6b\x7a\x6b\x60\x89\x3a\xfb\xfd\xd5\xed\x0b\xa5\x59\x66\xb4\xc3\xfc\x5d\xad\xc0\xa8\x2d\x5c\xe6\x68\x03\x52\x76\x5a\xe8\xe1\x21\x0b\x61\xf4\xb3\xa3\x15\xc4\x5b\x61\x16\x3b\x03\xa7\x46\xbe\x95\xab\x83\xb7\xe0\x99\x23\x91\x27\xe2\x12\xa1\x79\x72\xa2\xf5\x4a\xb8\x14\x1a\x99\x11\x76\x73\xbf\xc3\xaf\x26\x92\xd7\xd4\xd0\x6b\x11\xee\x93\x04\xaa\xf6\x91\xc4\x4a\xbf\x2f\x1d\xb7\x8b\x2c\x2d\x6b\x95\x24\x02\xe7\xfe\x0a\x17\xe8\x3e\x40\xbb\x45\xb0\xa2\x82\x84\xc8\x9b\x55\xdc\x8c\xa2\x34\x4e\x82\x20\xea\x89\xe1\xba\x08\x82\x2d\x3a\x0b\x28\xc1\xc7\x33\x39\xf0\x60\x77\xb6\xbb\x28\xb6\x16\xc8\xbc\xcb\xb8\x0e\x67\xe3\xdb\x49\xe2\xff\x38\x45\xbb\xc2\xfb\x38\x09\xb0\xbc\x76\x2f\xa4\xa9\xee\xc4\xa9\x95\x9a\xa8\x09\xd0\xc8\x1f\x3f\xd5\x8d\x99\x1b\xe3\x77\xf0\x71\x4a\xd2\x3a\xe1\x48\xb5\x34\x46\xd2\xd1\xf6\x81\x5a\xb0\xe4\xcb\x87\xd4\x89\x0a\x7e\xeb\xa9\x48\x4f\xd6\xd7\xd2\xa3\xf3\xf2\x79\xf8\xaa\xbe\x5c\x6a\x5f\x43\xf8\xbf\x9e\x4b\xad\x55\x4d\x0f\x6c\xb5\x05\x70\xdd\xaa\xbe\xbf\x5d\xaa\x7e\x9f\x08\xca\xfb\xef\x3f\x20\x6d\xf6\x4d\x9f\x59\x3c\x3c\xe4\x3b\x35\x79\xad\x8d\xea\xb0\x90\xc1\xc7\x3d\x8c\x46\x80\xfc\x68\xe5\xfd\x0d\x49\x71\xa9\x1a\xdb\x34\xc0\xf3\x4a\xad\x35\x9f\x12\xaf\x7b\xef\x41\xdf\xde\xad\x51\xe9\x0f\x16\xc4\x0f\x6e\xfe\xf6\xcf\xbb\x7b\x51\xd2\xea\xff\xfd\xed\x74\x5a\x17\x3f\x6e\x8c\x47\x4b\x3d\xb7\xe2\x97\x31\xa5\xff\xf7\xa5\x0a\xf6\xd7\xfc\x50\xc4\x11\x48\x0f\x9e\x01\x56\xe6\xeb\x81\x46\xa2\x74\x8b\x32\x0e\xf9\xe1\x8f\xe7\xbd\xe2\x0f\x7e\xc7\x5e\xf8\x01\x98\x84\xa4\xc9\xca\xb6\x58\x83\x3c\xdc\x8e\xda\xb1\x11\x20\x30\x54\x48\x9d\x0c\xd2\x9f\x9e\xe2\x78\xfa\xfa\xd8\xe3\x12\x3b\xc2\x29\xb6\xeb\xdc\x0a\xe2\x2b\xbf\x20\x26\x79\x4b\x9f\x1e\x7d\x3b\xfe\xf0\x13\x72\x80\x67\xde\xf5\x68\x7c\x9c\x45\x40\x07\x1a\x3c\x6a\xe6\x06\xa3\x7f\x6c\xd7\xb6\xa9\x69\xb4\xc4\x43\xbe\x18\xbf\xf5\xa5\x1c\xf2\xd7\x07\xa9\x1d\x6a\x2f\x40\x6f\x3d\x06\x4b\x0d\x12\xf4\x64\x51\x49\x9c\x9a\xed\xcb\x28\x8f\x52\x97\xb1\x01\xed\x21\x9a\x2f\xc6\x27\x5f\xcb\x92\xda\x76\xfe\xde\xb0\xdc\xa5\xd8\x7f\x1f\xa4\xa0\xe4\xc9\x8e\xc7\xf9\xe3\x1b\x8d\x37\x6e\x66\x26\xda\xcd\x2d\x7e\x05\x00\xb2\x06\x92\xad\x03\x3e\x69\xbc\x3e\x89\x52\x9a\x52\xf5\xad\xa0\x02\x73\x19\x51\x0c\x40\x49\xc2\xd0\x4c\xe4\xa2\xe4\x57\x79\xfa\x7e\x3b\x9e\xf6\xda\x21\xf8\xcb\x93\x6c\x8f\x93\x07\x73\x2c\x2e\x8a\xfc\xda\x48\xd7\xfd\x1c\x8f\x9b\x7c\xba\xf5\xc7\x13\xfd\x6f\x4c\x3f\xfe\x4f\xa9\x2f\x05\x5a\xbf\xfe\x4c\x75\xb6\x76\x49\x13\x38\xac\x28\xf9\x2e\xc9\x28\x13\xeb\x4f\x92\x23\x6d\x8b\x3a\x31\x41\x55\x03\x34\x7b\x26\xe9\x83\xcf\x25\x74\x42\x0d\xda\x0a\x2c\xac\x8a\xc2\x81\x30\xf7\x5a\x4e\x25\xef\x56\xd2\x28\x09\x3e\xb5\xd0\x25\x83\xaf\x84\xaa\x06\xad\x09\x39\x4d\xbf\x6c\x4e\x65\x7a\xab\x03\x45\x9b\x6d\x73\x03\x05\x74\x61\xa5\x10\x77\xdc\x80\xc5\xfe\xc8\x60\xff\xed\xe2\xbb\xff\x56\x37\x24\x27\x5a\xd9\xa1\x2e\xd6\x04\x6a\x2f\x16\x06\x50\xb1\x14\x99\x15\xed\xe1\xf3\x57\xcc\x2a\x18\xc8\xec\x55\x07\xb7\x85\xdc\x75\xfc\x11\xdf\x15\xfd\x82\x47\xe1\x20\x9c\x0c\xbb\x1c\x4f\x5f\xcf\xcd\xe7\xfe\x8f\x73\x5c\x08\x23\x4b\xcb\x98\x1b\xd6\xbb\x4b\x01\xe0\x5b\x68\x00\x30\xb2\x18\x4f\x8a\x42\x5f\x49\x42\x51\xa1\xa0\xca\x45\x4e\x37\x5f\x21\x3b\x03\x3d\xf4\x94\x34\x33\xe4\xaa\x72\x08\xdd\xfb\x3f\x11\x53\x71\x57\x1e\x3e\xf9\x06\x05\x4c\xb9\xed\x12\xbc\xd2\x67\xbc\xfa\xfc\xf6\xfe\x26\xbd\x42\xc7\x66\x12\xbb\x3d\x2f\x81\x7c\x22\xf3\x67\x4e\xf1\xf2\xc9\x52\xad\xd4\x2c\xc7\xe7\x8e\x33\x22\xd2\x2d\x39\x2a\x57\x24\x6f\x50\xc0\xcb\x3b\xf7\x0f\xd9\x10\xc6\x06\x58\x07\x29\x16\x05\xce\x9f\xa8\x8a\xbc\x46\x23\x8e\x47\xb8\x61\xb6\xd7\x70\x03\x45\x79\xa5\xe6\xe2\x63\xf6\xb3\xd3\x32\xda\x71\xc6\x36\xb0\xcf\x73\x10\xe3\xf8\x78\x36\xb4\x46\x29\x13\x2d\xbc\xa0\xa4\xe3\xc7\xaf\xe1\x07\xed\xb2\xb1\xd1\xbe\x7b\x17\x9f\x35\xc8\x17\x43\xfb\x25\x84\xfc\xeb\xcf\xca\xad\x5a\x9e\xa9\x6b\xde\x74\xb8\x7b\x3d\xf0\xb9\xf8\x17\x6a\xf6\x99\x35\x37\xf5\xea\xfb\x7f\x2c\x02\x4e\xaa\x20\x81\xbd\x4b\x99\xc8\x39\xf8\x67\xa9\xe5\x0e\x1a\x36\xc5\x20\x5a\xb4\xa0\x68\x72\x6b\x96\x4c\xed\xb6\x51\x73\x55\x99\x0c\x20\x3e\x68\xcc\xa4\x43\x37\x66\x32\xca\x46\x25\x0a\xa9\x93\xdf\xfc\x4b\xb5\x24\x50\x3c\x76\xaf\xaf\xc7\x31\x8b\x1f\xc4\xea\xb1\xad\x01\xeb\x60\xbc\x9c\xdb\x5c\xbc\x83\x31\xef\x0b\xdd\x15\x74\x13\xcc\x42\x65\x33\xf8\x7c\x9b\xb9\xbd\x57\xf2\x06\x57\x52\xa7\xb7\x3b\x74\xb6\x27\x38\x93\x17\x9b\x80\x93\x2e\x36\x0f\xff\xb4\xc9\xed\x6d\xe2\x00\xdf\xdf\x4f\x50\xbe\xa2\x24\xac\x2f\x91\xf1\x5f\x5f\x74\x8b\x9f\x3a\x45\x88\x37\xdf\x17\x72\xd5\x7c\x32\xe8\x20\xaa\xfe\xbb\xa8\x6d\xa6\x7e\x32\xfe\xb4\xb6\xd4\xf2\xf8\xfb\x2e\x30\x4c\xff\xcc\x13\xdc\x7e\xff\x15\x5a\xc9\x7f\xef\x23\x34\xba\x0a\x0b\xb5\x60\xdd\x4f\x0c\xbb\xdf\x7d\x97\xb9\x56\x81\x5e\x15\x2a\xbf\xb8\xdc\x02\xc8\x43\x42\x9d\xb9\x2e\x46\x22\x55\x37\xdc\xbe\x6a\x87\xdb\x5f\xb9\x4d\x50\x94\xfc\xad\x0d\x81\xc9\xfa\x6f\xec\x8e\xb7\xa0\x4b\xf9\x7b\x1f\x02\x8b\x58\x96\x76\x87\xd6\xb3\xbf\x3d\x12\xd4\x53\x62\xdf\xb7\xe9\x8e\x2f\x88\x37\xe2\x33\xbb\x87\x96\x63\x67\x54\xb8\x40\xd4\x18\x1c\xdf\x6e\x16\x1c\x01\x96\x06\x7a\x15\xaa\x8e\x0d\x0c\xec\xc4\x16\x68\x49\x51\x94\xc5\xc8\x03\xbf\x32\x60\x82\xad\xa4\x80\xf2\x23\x58\xb8\x7e\x9d\x66\xe9\x2d\x14\xbd\x88\x1b\x81\xb5\x44\x22\xfb\x72\x3e\xca\xdf\xdf\x58\xb3\xe9\x17\x1d\xbc\x5c\x49\xf5\xf6\x3a\x38\xbe\x9a\x11\x5f\xd2\x5a\xbf\xbe\x56\xdf\x3d\x66\xc4\x9e\x4b\xf2\xc1\x74\x87\x5a\xd6\xa7\x6e\xfa\x83\xbc\xe8\x13\x0f\x1e\x7c\x83\x9f\x78\xf0\x55\x74\xd3\x32\xd3\xe8\xb6\x77\x16\x9c\x25\xb5\xb5\xc0\x4f\xa7\x3e\x0c\x2e\x9a\x0b\xa2\x00\x77\xff\x42\x07\xdf\x9b\x08\xb4\x87\x95\x86\xd1\x1f\xba\x6a\xff\x3c\x9e\xd0\xdb\xf0\x4b\xef\x08\xb8\x1b\x78\x60\xde\x6f\x6f\xdd\xfd\x1b\xd8\x4a\xaa\x85\x81\x9f\x4f\x44\xd0\x74\xbc\x8a\xa0\xc5\xc0\xfa\x93\x07\x7f\xf1\x02\x5f\x92\x42\xbf\xfe\x54\x5e\xba\x57\x94\x28\xdb\x6e\x84\x65\x80\x92\x80\xda\x48\xfd\x82\x89\x66\xb0\x6a\xe7\x8d\xca\xb0\x35\x6f\x91\xc7\x83\xc7\x06\x9f\x10\x65\xd5\xd4\x4d\x96\xc1\xc2\x08\x24\xbe\x25\xe3\x0c\x06\x1b\xa0\xe9\xba\xc8\x90\xbb\x0c\xd9\xfc\x17\x03\x7b\x39\x40\x1b\xac\xde\xf2\x41\x2c\xc4\xfd\x20\xbe\xed\x27\x04\x9e\x15\x41\xe9\xf3\xe2\x25\xbb\x63\x24\x3b\xef\x76\x4a\xb2\x4e\x78\x7d\x3f\x3e\xbf\x7b\x90\x51\xc9\xa6\xa4\x0b\x29\xb7\xcd\x1f\xa8\xe4\xfc\xc9\x19\xbe\x6a\xdd\x97\x14\xcf\xaf\x2f\xa5\x43\x1f\x60\x95\x96\x3a\x2d\xe9\x61\x04\xd9\x20\x5b\x42\x2f\x9f\x55\x2d\xf3\xf1\x07\xbf\x33\x97\x1a\x5a\x6b\x83\x38\x89\x24\xc5\x8e\x73\xa7\xe3\x3a\xf4\x38\xcf\x68\x40\x1a\xd6\x8f\x17\x7b\xba\x94\xf1\x42\xfb\x32\x58\x14\xf7\x47\x2e\xb7\x83\xa7\x20\xce\x71\xf0\xb4\xe7\xf2\xd3\xa4\xdd\x5b\xeb\x41\xcb\x63\x4a\x41\x50\xf7\x0e\x23\x75\xbf\xfa\x37\xdd\x97\x11\x65\x6e\x8c\x45\x23\xeb\x8d\x3b\xd7\x76\x5f\x5a\xb7\xbd\x10\x21\x33\x46\xd4\x6e\x0e\x98\xc6\xf8\xc0\xc4\x0c\x51\x5f\x39\xba\xbf\xca\xc0\xe1\xe6\xb3\xea\x55\x0f\x24\x77\x15\x2c\xf5\x09\xcc\x43\x7d\x47\x74\x9b\x4a\x40\xe0\x44\xaa\x40\x3c\x54\xd9\xf1\xbe\x45\x46\x1a\x9d\x1a\x69\x2c\x9c\x45\x5d\x61\x5a\xf4\xf4\x22\x0f\x37\x6b\x0f\x54\xf5\x94\x6f\x48\x04\xa3\xca\x4f\x59\xed\x0b\x49\xf9\x13\x2a\xad\xfd\xe8\x4a\x75\x85\xdb\x9b\xf4\x66\xa9\x91\x84\x03\x1c\x81\xee\x2d\x10\xad\xa4\x3b\xc8\x07\x46\xa4\x19\x4a\xab\x3b\xb0\x5e\x84\x3a\x81\x19\xb7\x80\x69\xaa\x30\x2c\xef\x1e\x85\x54\x00\xad\xaa\x80\x37\x01\x0a\xb7\x92\x4c\xdb\x1d\x7c\x5e\x7a\x56\x6e\x1d\x24\x32\xac\xcc\xca\xd9\xd8\x0b\xeb\x26\xc9\x25\xdf\xca\x0e\x58\x06\xc8\x0f\xf1\x0b\x24\x84\x3b\xcb\x47\x70\x15\xb8\x5f\x95\x70\x5b\xd5\x54\x9a\xed\xb4\xcb\x91\xfc\xec\x0a\xf1\x21\x6f\x45\x1f\x57\x05\x71\x2c\x7f\x9f\x80\x16\x25\xe2\x81\xfa\x2d\x30\xcf\xe3\x4e\x24\x5a\xd7\x84\x30\xbe\x1d\x28\xd2\x95\x55\xb4\xf6\xbd\xa1\x3e\x58\x08\xe3\xc2\x1d\xa9\xdd\x97\x36\x21\x71\x44\x14\xbc\xf6\xe4\x63\xfe\x58\x7c\x85\xfd\x72\xc2\x7b\x49\x96\xfc\xfa\x53\xc9\x65\xf7\xd7\x60\x42\x14\x2b\xeb\x22\xa5\xde\xfd\x8b\x14\x94\x4d\xcf\xf2\xf3\x8d\x56\x74\xd3\x6a\x49\x6b\xb9\xf7\x89\xde\x3d\xdd\x00\xcb\x65\xae\xfe\x56\x16\x95\xbe\xa9\xf4\xa4\xd2\x57\x9b\xc3\x87\xc9\x44\x8d\x33\xc8\x98\x05\x32\xf0\x6e\x62\xf8\xe9\x4d\xdb\xe6\x07\x24\xff\x67\xf5\x7f\xee\xf8\x62\x73\xdc\x45\xea\xd8\xdc\xd5\xd4\x31\x57\x29\xe3\xcb\x56\x78\x49\x50\xfc\x7a\x11\xf6\xf5\x6e\x7e\x3f\x6e\x35\x74\x24\x71\x75\x52\x78\xc1\x72\xa5\xdc\xb2\xf7\x36\x2a\x27\xec\x48\x0f\xcd\x00\x67\xb2\x14\x1b\x51\xbd\x31\xe1\xad\xa3\x64\xde\x3b\x0e\xaa\x64\x35\x95\xa4\x6d\x07\xd6\xd7\xdc\xae\x3a\x64\x48\x52\x69\xbb\x30\x7e\xd5\x51\xb1\x24\x01\xa7\x40\x5d\x20\x93\x8f\x46\x89\x75\x77\xe2\x23\x6d\x37\xcf\xb4\x9d\xbe\xbf\x35\x37\xd2\xdc\xc8\x47\xd4\x89\xdc\x8a\xdd\x57\x1d\x90\x1f\x4e\xb7\x6f\x00\xbb\x8f\x47\x19\x44\x7d\x2b\x72\x5b\x06\x06\x33\x4d\xcc\x3d\xa5\xee\x03\x28\x75\x80\xb7\x9b\x2f\x4c\x00\xfc\x14\xcc\x1d\x89\x79\x4d\x77\x75\xfd\x02\x7d\x07\x02\x60\x86\x04\x63\xdf\x20\x26\x59\x76\x2c\xbe\xc9\xa2\x98\x1c\xe6\xe0\x09\x7a\x43\xcd\x21\x38\x4f\xc0\x6b\x86\xb6\x63\x16\xb0\xb9\xcb\x1e\x72\x8c\xde\xec\xc8\x8f\xa3\x3f\x47\x21\x2f\x42\x21\xa3\x24\x1d\x7d\xf3\x91\xd9\xf9\x33\x26\x0d\x3f\x45\x69\x07\x6a\x97\x4b\xdb\xcd\x6d\xdb\x34\xcc\xdb\x5a\x28\xc0\x86\xda\x98\x1d\xb5\x84\x28\x26\x05\xf0\xca\x67\x5e\x54\x55\x65\x6f\xdd\xc1\xd0\x79\x00\x44\x7b\x1f\x69\x64\xdb\x89\x59\x89\x2c\xa0\xea\x4e\xdd\xfc\x28\xb3\xee\xb2\x2d\xd6\x47\xaa\x73\x78\xab\x81\xa4\x22\x35\xdd\x8b\xf8\x0d\x28\xa8\xe8\xa2\xc6\x1b\xe5\xc9\xc2\x02\x53\xe4\x43\x61\x63\xed\x98\xc9\x70\x51\x12\x89\x40\xbc\xa4\x13\x5c\x5d\xdc\x35\x9c\xd8\x07\x5e\x7d\xf3\x05\x85\x6a\x1c\x60\x5f\xd0\xc9\x8c\x05\xb0\x19\x35\x21\x68\xa4\xb6\x41\x7d\x03\xa5\xfa\x2c\x7d\xc6\xda\x6e\x0a\x98\x24\x6a\x05\x46\xbf\xed\x92\x24\xf5\x0a\x6f\x41\x20\x32\x29\x89\x31\x8c\xe2\x76\xba\x4d\x6f\x0e\x7f\x16\x5f\x26\x0a\xcb\xf7\xa8\x2f\x02\x96\x0a\x2c\x33\x3e\x97\xdf\x97\xaf\x06\x5a\x7b\x4d\xf4\xfc\x54\x1b\x18\xc6\x2a\xb8\x26\x6d\x50\x9e\x79\xf5\x2f\x24\xfb\x14\x50\x80\x96\x48\x38\xb5\x92\x91\x70\x6a\x25\xc7\x36\x66\xa3\x5a\xc9\xdc\xe8\x5f\xb8\x11\x56\xee\x75\x60\x15\xe6\x1c\x2b\xd8\x0d\x02\x1e\xfd\xc3\x6d\x23\x84\xa0\x3f\xdb\xf6\x94\xfe\xfa\xb0\x51\xab\xbb\x12\x7a\x9f\x2d\x07\x91\x74\xc4\xf4\x99\x64\x5b\x4a\x94\x78\x4c\x26\xdb\x6e\x94\x6a\x7d\x7f\x93\x09\x69\x35\xbd\x4b\x1e\x63\x5d\xce\x79\x70\x30\x35\x1f\x39\xe7\x56\x30\xc3\x5d\xd9\x3f\x26\xff\xca\x59\xd1\xea\xb6\x32\x52\xca\xed\x47\x6a\xc7\xeb\x22\xcd\xd7\xb8\xcf\x88\xcb\x79\x65\xf7\x11\xc0\x37\xdd\xe7\x57\xc9\xf7\xf6\x9a\x2a\x7a\xe1\xfa\x7b\x79\xc1\x76\xc2\x81\xa6\xa5\x6e\x51\xf4\x8e\xcc\x16\x2a\x38\x31\x83\xd6\x72\x80\xba\x25\xa9\xc6\x97\x45\x35\x72\x32\xb5\x84\x96\x2b\xe9\x0a\x22\x4b\xe7\x7f\x7d\x3b\x97\x1e\x85\x5f\x97\x48\xac\xaa\x08\x3b\x4b\x54\x89\x83\x2a\x92\xbf\x69\xe8\x95\xb2\xc6\x1f\x24\x2d\x85\xd0\x89\x4b\x06\x0f\x7e\x6f\xaf\xa1\xe0\x3e\x2d\x34\x05\xdd\xc9\xd8\xfb\x48\xdd\x4d\x9b\xe6\x0e\xd6\xa1\x66\xa9\x14\x7c\x2c\xa5\x1c\x42\xe6\xaa\x88\x80\x87\xb0\x50\x08\xa8\x0d\x3a\xc5\x7e\xf6\x33\xcd\x07\x5c\x73\x6d\x3d\x55\xb0\x16\x48\x78\xbd\x6e\xe1\xd8\x49\xc9\xe8\x7d\x9c\x84\xe1\x0a\x0a\x39\x98\xa8\xc8\x8b\x48\xcf\xd1\x42\xb4\xa1\x2a\xe5\x94\x99\xb2\x02\xf3\x23\x7e\x82\x37\x46\x4e\xe6\x0c\xe2\x0c\x3e\x58\x3c\x96\xa6\xd0\x59\x73\xcb\xd4\xe0\x18\x26\xcd\xf5\xb0\x91\x53\x37\x7c\x2c\xfe\x49\x38\x47\xfd\xf0\x5c\xfa\x78\xae\x78\x2a\xc5\x33\xdd\xde\x64\xd8\x48\x03\x6b\xa9\x44\xe1\x2f\xca\x16\x67\x22\x6e\x0f\x1c\x59\xca\xaa\xa0\x02\xe0\x0a\x4b\xd1\xf8\x7d\x89\xe2\xb5\x1e\x5c\x9c\x94\x6b\x89\x6c\x81\x42\xb9\xf2\x7c\x98\x1f\xbf\x27\x19\x1d\x18\xab\x52\x00\xeb\x39\xaa\x76\xe0\xa7\x2a\x22\x02\xd9\x2d\x62\x54\xb5\x8f\x2f\x5f\x95\xc6\xab\xfa\x62\x50\xbc\x26\xc6\x7e\x56\xda\x66\xa3\xa4\x4c\x7e\x3e\xf2\xb0\xd3\x27\x03\xdd\x12\x89\xe3\xc9\xbc\xc4\xef\x34\x00\xb0\xcb\xd3\xd7\xa7\x3d\x1e\xc7\x5d\x27\x3b\x55\xe6\xfe\xde\x6b\x84\x36\xc2\xef\xbc\xca\xed\xcf\x5e\x06\x73\xfd\xbf\xa2\xbd\x7e\xff\xb3\xfc\x91\xab\xdc\xbe\x6f\x32\xc6\x82\xfe\xce\x87\x39\x57\xce\x7f\x41\x9b\xfd\xfc\x61\x6e\xff\x94\xa7\xa9\xd6\xd2\x13\x2b\x38\x59\xc2\x8f\x93\x33\x3c\xf8\xc6\x97\x57\xc2\xf1\xe0\x1b\x8f\x1d\xb8\x3b\x8e\x8d\x16\xfa\xdb\x5f\xc4\x2d\xd2\xfc\x79\x8c\x47\xd5\x4d\xa8\xb5\x33\x86\x06\x73\x21\x3f\x85\xd5\x2e\xd5\xd0\x8f\xc5\x3d\x1f\xac\x88\xf5\x43\xe1\xd1\xc3\x1e\xc0\xc5\xfe\x05\xbd\xab\x81\xbc\x33\x07\xfd\xf7\xe7\xec\xee\x37\x70\x6b\x8c\x4f\xf9\xdd\xe3\xa8\xef\x08\xde\xb1\xfb\x2b\x83\xfc\x57\x53\xef\x6b\xe2\xf2\x97\x07\xd0\x40\x66\x1a\x33\x43\x74\x60\x10\x6c\xa8\xd9\x2d\x21\xf7\xd2\xa1\xf1\xd5\x50\xf9\x58\xd6\x05\x3a\xc3\x2c\x39\x28\xa7\x72\x13\xa2\xdd\x1a\x4c\x70\x32\x37\x38\x5b\x16\x22\x63\x52\x89\xf3\x68\x11\x64\xa0\x66\xfb\x49\xb8\x87\xd8\x8e\xd6\x0b\xe5\x6f\xee\x1b\x1e\xee\x27\xb5\x1d\x74\x47\xa8\xee\x91\x36\x8e\xc7\x97\x9e\x24\xf8\x7d\xf8\x65\x47\x38\x01\x12\xec\xab\x98\xa0\x3e\x0a\x95\x34\x2d\xa9\xec\xd2\x6b\x32\xd2\x52\x4b\x21\xe1\xcd\xac\x49\xaa\xfb\x91\xed\xe6\xde\x63\x87\xac\xa0\x98\xed\x92\x1a\xd8\x49\x7a\x40\x48\xe5\x20\x00\x7b\x87\x9d\x30\x13\xd9\xb4\xdc\xca\x35\x28\xeb\xf7\x60\x05\xeb\x24\xc8\x53\xf7\x67\x11\xfa\x30\x0b\x6c\xa6\x31\x46\x62\xc1\x63\xef\xef\xbf\x9c\x52\x8e\x20\xf7\x44\x3a\x1f\xd9\xfc\x00\x97\xfb\xcb\xa4\xde\xf2\x08\x86\x3c\xc0\x37\xa3\x66\x1a\x89\x8b\x95\xf8\x21\xb2\xb3\x1a\xdb\xe5\x81\x11\x1a\xdf\xc8\x03\x26\xa5\xcb\x5e\x93\x4e\x30\xa3\xa4\x32\xa8\x2f\x2f\x73\xad\x73\xdc\x76\x2b\xde\x83\x88\xa2\xb2\x43\xe8\x8c\xba\x27\x8b\xa7\x11\x82\x32\x10\x56\x39\x41\xe1\xf3\xab\xf2\xa8\xf6\x9a\x07\xfd\x19\xc1\x66\x29\x92\x46\x2b\x3b\x2a\xcb\x00\xbe\x6e\x3b\x60\xc3\xd6\xdc\xff\x86\x2f\x8d\x1e\xe7\x76\x9f\xf6\x54\xc0\x0e\xdd\x7a\xea\x65\x92\x91\xbf\xa1\x98\x18\xd5\x3b\x04\xdd\xae\xd6\x91\x34\xcb\x39\xd5\xdc\x77\x92\xba\x81\x0a\x0c\x85\x35\xd3\x10\xc1\x32\xd6\xcd\xb4\x54\x67\xd9\x91\xbb\x16\x50\xf7\x94\xb9\x2b\xaa\x57\x4b\x4e\x66\xa0\x10\xf6\x29\x30\xcf\x89\x44\xc1\xae\x28\xb1\x51\x2c\xe6\xb0\x20\xc9\x8c\xce\x3f\xba\x1b\xd9\xeb\x52\xbc\x2f\x17\x49\x0d\x3c\x5b\xd5\xfc\x35\xe8\x5a\xac\x3e\x5c\x2a\x32\x5d\x33\x6c\x21\x69\x19\xa2\x70\x56\x2b\xd4\x7d\xeb\x64\x1c\x1d\x41\xb2\x8c\xd7\xde\x52\x75\xa3\xbd\xf8\xf3\xa2\xc6\x65\x9c\x48\x69\x51\x7f\xe4\xea\xb7\x8d\x32\xea\x78\x99\x2c\xfb\xf0\xfe\x8c\x08\x44\x8e\x50\xc4\xa8\x3f\x9f\x24\x50\x81\xf8\xff\xbd\x38\xa6\xbf\xbd\xf0\x70\x3e\x69\xd2\xcb\xec\xee\x92\xb8\xef\x64\x48\x32\x58\x4f\x0d\x2c\xd7\x1b\x85\x22\x68\x34\x6a\x3b\x66\x82\x6a\xa1\x37\xca\xfb\x5b\x35\x49\x4d\x64\x5b\xea\x48\xc4\xc2\x09\x90\xb8\x38\xd9\xea\x56\x3c\xe7\x0e\xdb\x89\xb7\x9c\xa9\x20\x82\x68\xed\xfd\xad\x4b\x4e\xb3\x21\x79\xa0\x50\x36\x24\x8f\xde\xc4\xe2\xd0\xc9\x5c\x25\xa4\xc7\x04\xb3\x07\x94\xeb\x8c\x9a\xd7\xab\xf4\xba\x69\x93\xd4\x8a\xac\x8b\xf4\xf6\xfe\x36\xca\x04\x69\xa8\x34\x52\x68\xb6\xa2\x70\x04\x7d\xfe\x96\x9e\x66\x21\xc9\x0b\x2c\xe2\xe2\x9f\x88\x0b\xb1\xe0\x04\xbe\xd1\xa4\x1b\x21\xd5\x62\x98\x2a\x4b\xf6\xa4\x97\x33\x46\x00\x1e\x29\x41\x2d\x2a\xa9\xa8\x2c\xfe\x2b\xed\xa0\x5c\x6f\xbb\x88\xb0\x6a\x4b\x66\x1b\x45\xa2\xa9\xed\xee\xd3\x16\x28\x55\x22\xc3\x81\x22\x2f\x4c\x21\x00\x9f\xa6\x3a\x8f\x01\x4c\x15\xcb\xda\x40\x42\x58\x72\xf2\xeb\xfb\x00\xf0\x9e\xdf\x05\x30\x03\xf5\x95\xc4\x57\x57\x4d\x8c\xbc\x20\x26\x9e\x63\x02\xd9\x7b\x06\x37\x21\x0a\xbd\xa0\x12\x3e\xe0\x3b\x6b\x3a\xfd\xf5\x1b\x08\xf4\xa0\x8b\xea\xce\xe6\xb6\x28\x78\x41\x87\x7b\xc4\x65\xb3\x9a\x66\x5b\x55\x74\xaf\x8c\x19\xf9\x7a\xd6\x56\xa9\x25\x64\xb2\x7d\x39\xbe\x73\x21\xff\x81\xd2\x89\x7b\xc4\x9f\x2f\x85\x3c\xe8\xbb\xa5\x10\xbb\xff\xf1\xa5\xf0\x25\xb7\xf5\xdb\x0b\xa9\xe5\x73\x17\x07\x55\x91\xa0\x97\xea\x48\x88\xbb\x0f\x49\x03\xaa\xb8\xcc\x47\x70\x1a\x2d\x2c\xc1\x8c\xf2\xc8\x1c\x00\x37\x0e\x4a\x77\x36\x4b\x08\x47\x75\x2e\x1a\x25\x9d\x3f\x8c\xe3\x69\x37\xf4\x6a\x1e\x0d\x8d\x08\x20\xe0\x04\xf8\xfe\xeb\xb2\x10\x33\x00\x25\xea\x48\xda\xea\xb7\x7a\xc0\xfe\xc0\x2a\x20\x80\xbd\x6b\xab\x57\xf0\x07\x04\xe3\xbe\xfe\x62\x22\x44\x12\x81\x84\xb2\xb4\x5f\x32\x62\x91\xd4\xe3\xd2\x32\x6f\xbb\xcf\xb5\x3e\xe5\x75\x12\xbc\x4f\xee\xc8\xfd\x70\x3c\x0e\xf7\xd3\xfb\x48\x83\xf6\x83\xc5\x32\xc8\x8b\x2f\x8f\x7b\x82\x60\x04\xee\x73\xd1\x06\xed\x7f\xe5\xb2\xa6\x60\x5c\xab\x0f\x08\xe1\x09\x20\xd4\xa0\x3a\x62\x93\x78\x8b\x9c\x80\x41\x74\x6e\x4b\x27\x80\xb0\x9f\xad\x8b\xc6\x65\xb3\x9f\xad\x8e\x17\x42\xec\x20\x9b\x6e\x89\xeb\x21\x96\xd4\x52\xe9\xb6\xf6\xbb\xf9\x14\x70\x5f\xfc\xeb\x22\x7d\xb5\xbb\x74\x37\x45\x67\xad\xa9\xd4\xb6\x96\xbb\xe6\x75\xa9\x1b\x38\x85\x0c\x2a\xf1\xb6\x2e\x6e\x6e\x66\xdf\xb7\x6e\xf8\x7d\x2d\x9b\x1b\x0f\x77\xc8\x34\xc9\x74\xbb\xa0\x91\xf3\x6c\x5d\xec\x6e\xab\xad\x7a\x5f\x24\x36\xf5\xd5\xdc\x48\xaa\xab\x6e\x92\x04\xe1\x46\x49\x76\x2c\x92\x00\x19\x92\x75\xb1\x75\x61\x11\x83\xdd\xeb\x2a\xef\x6f\x6d\xb8\xf7\x0e\xcd\x0c\x14\x69\x0a\x23\xcf\xbb\x90\x40\x24\x34\x58\xb0\x6a\x9d\x4a\x15\x33\x30\x18\x72\x10\xc2\xa1\xfb\xa9\xe3\x92\x01\x22\xc2\x69\xd0\x3b\x86\xbf\xbe\x1d\xc8\x3e\x2e\x6d\xb7\x75\xe9\xd9\xed\x29\x45\x39\x28\x38\xd1\xa4\x7c\x77\x03\xbe\xd6\xea\x71\x66\xde\xae\x40\xf6\x67\xd7\x27\x7e\xf2\x0c\x19\xf1\xc0\xeb\xfa\x7d\xb4\x38\xf3\x60\xee\x07\x51\x71\x9d\x27\xc0\xe7\x8b\x2b\xb0\x77\x3d\x52\x80\xf1\xed\xa4\xe1\x8a\xf3\xa1\xe1\x0b\xa4\x52\x60\xb4\xc2\xd6\x42\x63\x24\x3f\x22\x84\x98\x7d\x32\x2d\x20\x95\x4b\x92\x40\xd5\x07\x2a\x0a\x7f\x47\x7e\x98\xe2\x53\x92\x1f\xed\xbd\xc9\x97\xee\xcd\xa7\xc9\xcd\x57\xa0\xfb\x22\xe0\xf9\x01\xc4\x09\xa9\x33\xb9\x2f\x78\xa9\x0b\xf1\x6d\x0a\x73\x8e\x3c\x1e\xba\x07\x33\xb5\x9f\xe3\xfd\xad\xce\xe9\x9d\x22\xdf\x47\x3d\x09\x02\xcb\x03\x1d\x86\xe7\x01\x53\x85\x69\x94\x29\x2d\x5a\x18\xe0\x2f\x24\x34\x2c\x17\x80\x0f\xba\x5d\x77\x69\x2b\xa4\x9e\xc4\xaa\x9f\x16\xed\x6b\xbe\xa4\xb8\x45\xcd\x37\x0d\xa3\xf1\xbe\xf4\xba\xea\xbc\xf7\x7a\xfb\xc9\x1e\xee\xbb\xd6\xd4\x7d\xc7\x36\xee\xad\xbb\xe5\x79\xc7\x6a\x25\x9d\xf2\x0b\x96\x50\xe3\x8d\xfe\x55\x28\xaf\x84\xf7\x53\xb9\xdc\x55\x39\xf8\xeb\x8e\x42\x2b\xec\xee\x83\xed\xfd\x6d\x16\x4b\xc0\x56\x21\x91\xd5\x53\x09\xea\x6b\x04\xe9\x83\x94\x03\x95\x0c\x35\xa1\x8a\x97\xfa\xdf\x40\xdb\x88\xdb\x11\x78\x72\x12\xe0\xd6\x4a\xbe\x21\xfa\x86\xc2\xce\x20\x34\x67\xe9\x53\x80\x98\x69\x6e\x10\xf6\x41\xc2\xe8\x14\xbe\xbe\xed\x01\x6f\x83\x56\x68\xbf\x7c\x1b\x3f\xe3\x46\x21\x20\xdb\x23\x07\xc4\x14\xc7\x8e\x67\x65\xb1\xb0\xcf\xd6\xdf\x62\x9c\xe4\x6e\x38\x66\x80\xd0\x83\x84\xd0\xf0\x7a\xfa\x39\xfc\x64\x26\xd5\x7b\x93\xb5\x8c\xbb\xf6\x75\x29\xe3\xee\x56\x88\xbf\x2d\xff\xd4\x71\x5f\xb4\xaf\xfe\xd1\x24\x88\x1d\xfd\xbe\x6b\x0e\xf3\xce\x1d\x64\x0c\xdb\x99\x48\x37\xf5\x49\xa3\xe3\x79\x35\x05\xf1\x9d\x5c\x89\x32\xff\x21\x0c\xed\xa0\x0c\x2f\x49\x95\xb0\x3a\x36\xd5\xa4\xab\x06\xb7\xc0\x1b\xd1\x0c\x1c\x60\x28\x7f\x61\x1a\x19\x42\x3a\x07\xcb\x81\xc8\x36\x02\xfa\xdd\xf6\x40\x4d\x7e\xda\x03\xdd\x85\x35\xf8\x21\x86\xd0\x28\x89\x84\xcb\x36\x41\x6a\x0b\x36\x39\xb7\xbf\xe1\x54\x0d\x4e\x08\xfe\x36\xce\x47\x38\x58\xa5\xe0\x3d\x08\x0d\x3f\x92\x34\xde\x7e\x89\xbb\x3f\xb1\x76\x4f\xf3\x0c\x5f\x4e\xcc\x02\x72\x9c\x9f\xb1\xe1\xb6\x53\xed\x0a\x07\x6d\x71\x2a\xcd\xf0\x27\x70\x7e\x70\x9e\xe7\x93\xf1\x9c\xad\xcb\xbb\xf1\x09\x71\x1a\x87\x6c\x8c\x08\x3c\x6b\x43\x02\x2a\x58\x84\x9f\x47\xc4\xf7\x27\x38\xae\x2f\xe7\xb6\x18\x19\x7a\x8d\x0c\xe9\x10\xfb\xfb\xac\x5d\x31\xfa\x8c\x03\xf7\xe7\xed\x3a\x9e\xda\x75\xb4\x76\x8d\x61\x51\xbd\xf1\x3c\x30\x0b\xea\x63\x14\x07\xb9\x60\x28\x5f\xc5\x6d\x62\x4d\x7e\x7c\x7d\xec\x11\x6f\xe3\x31\x9e\x31\xcd\x6a\xa7\xdd\xbe\x82\xe9\xe4\x9c\xe7\x8c\xb8\x40\xc0\x02\x89\xff\xe5\x26\x84\x44\x20\xd7\x4f\x24\x6f\xc2\x76\x4c\x95\x7e\xd4\x51\x59\x1a\x90\x53\x0b\x11\x7a\x4d\x3e\xe3\x72\xdd\xb4\x54\x76\xff\x45\x12\xd8\x67\xfc\x84\xed\xe2\x5c\x2a\xa7\x66\xbd\xfa\xfd\x3c\xa6\xfc\xcc\xf0\x6a\x22\xd1\xc9\x7f\x92\x4d\xfa\x52\x11\xf4\xdb\x0b\x64\xe4\xc9\x26\x35\xb1\xd4\x2b\x79\x09\xe1\x14\x83\x1e\x13\xcb\xbd\x4f\x39\xa8\x9c\x6e\xb0\x6e\x54\xdd\xe9\x21\xaf\x21\x95\xb1\x77\x0b\xc1\x06\xdf\xd1\xdc\xc2\x1f\x33\x0d\xbd\xd4\x07\xc1\x52\xef\x3e\xd0\xbc\x4b\x96\x55\xf3\xde\xbc\x1b\x92\x1d\xf0\xfd\x0d\x49\x0f\x5c\xba\x13\xe3\x2d\xd1\x61\x94\xc4\x67\xeb\x32\xeb\x7d\x31\xb3\x75\x56\x77\x5b\x08\xb4\xb1\x01\xfa\x7d\x41\x45\x86\x8e\xf7\xb7\x02\x72\x28\x5b\x5b\xbd\xfb\xbe\x4b\xe3\x41\xef\x6f\xdd\x72\x50\x10\x23\x62\x42\x50\x50\x64\x2f\x8a\xcf\x58\x4a\xd0\x04\x17\xc7\x19\x4a\x48\x48\x4a\x48\x4b\x41\xc2\x85\xba\xca\x60\xd2\x61\x4f\xad\x20\x64\xdf\xcc\xdd\x7c\x38\xe8\x46\xce\x72\xeb\x27\x36\xbe\x43\xd2\x03\xeb\x6e\x66\xc1\xe6\x1e\xc4\x7c\x23\xb0\x28\xad\x30\xdc\xb2\x93\x72\x22\x20\x86\x84\xc2\x28\x42\x8f\x76\x25\xe0\xa4\x9c\x7a\x13\x16\x10\x5f\x70\x5a\x65\xfa\x62\x05\x14\x8c\x0b\x19\xce\x09\x42\x25\x57\x2d\x78\x56\x87\xd1\x14\x32\x4d\x91\xf3\xce\x28\xa0\x2d\xb7\x7b\x8f\x1a\x00\xff\xaf\x07\xc1\x4e\xc1\x54\x03\x17\xd0\x60\xfc\x18\x44\xfc\x59\x8a\x55\x46\xe2\x9f\x3e\x77\xf7\x53\x11\x81\xf0\x67\x08\x73\x0f\x9c\xb3\x80\x06\x6e\x19\x19\x93\x57\x0f\x72\xad\x7a\x0d\xfc\x00\x3a\xa3\x2e\x0b\xbc\x0e\xfc\x86\xb0\x0a\x80\x65\x80\x1a\x0d\x9f\xb6\x81\x15\xcd\x29\xdf\x2b\x68\x39\x6b\x0a\xb8\x74\x21\x92\xea\x58\x94\x31\x54\x71\xcf\xc0\xc2\x7a\x63\x9c\xb5\x48\xc4\xa3\x88\xad\xce\x94\xc3\x5a\xa5\xb6\x79\xfb\x2c\x8e\x6b\x63\xa6\x5e\xdd\x9f\xea\x08\x94\x79\xd7\xa2\x5c\x1e\xf2\x7c\xee\x6a\xf8\x17\xa2\x0e\xc6\x71\x7e\x9e\x1b\x62\x47\x1e\x07\x41\x35\x49\x75\x94\x4d\x0a\x4a\x74\xd6\xa5\x33\x3c\x47\xb0\xc1\xf0\xe5\xbb\xe0\x47\x01\x55\x7c\xd1\x95\x61\x1d\x29\xe8\xca\x32\xca\xbd\x86\x5a\xf9\xcc\xab\x48\x8d\x3f\xeb\xbd\x97\xd5\x7f\xad\x7d\x5d\x04\xf9\x7b\xef\xe9\x2a\xb9\xe2\x40\xa8\x7e\x64\x37\x39\xf2\xde\x5b\x02\x8a\x35\x71\x08\xd0\x32\xe9\x76\xa3\xc2\x6b\x5b\x97\xd9\x39\xba\x5a\xbd\x8b\x0f\xb2\x6b\x1e\xeb\xc8\xe3\xb3\x7e\x16\xc2\xe8\x58\x5f\xe6\x85\x97\xb4\x89\xb9\x2c\x7f\x14\xc3\x9a\x81\xe9\x9f\xf5\x1e\x07\xd7\x96\xe2\x97\x23\x76\x59\x71\x18\x8e\x3a\x4f\x75\x9c\x67\xff\xe9\xbc\xf6\x9b\xfc\xf6\x12\x76\xfe\xed\x05\x2f\xf3\xc1\xd7\x9e\x69\xd4\xb2\x8e\xb9\xc1\x06\xcb\xe3\xfd\xad\x83\xbe\x68\x6c\xbd\xa4\x3e\xb7\xa5\xe7\xd4\xe7\xba\x48\xb3\xfb\x52\xe6\x2a\x05\x8a\xf1\xeb\xc2\x2f\x65\x15\x6a\xda\xb9\x3f\xd9\xb6\x49\xa2\xf1\xbb\x62\x85\x42\xaa\x13\x74\x96\xc6\x80\xac\x4f\x3c\xfe\x3a\xda\x5c\x87\x91\x79\xcc\x67\x86\xf6\xfe\x26\xa5\xbb\x13\xe8\x5d\x0b\x22\x15\x9a\x74\xae\xcb\x50\xb7\xcd\xd6\x21\x1c\x3f\xc5\x68\xfa\xc9\xec\x69\x62\x06\xfa\x7e\xdf\xfc\x61\x5f\xb7\x1e\x5a\x6d\x8f\x27\x2c\x78\xc2\xdb\x5b\x03\x7d\x56\x9e\x6e\x00\xca\xba\xb4\x76\x87\xee\xc5\xc4\x12\xae\xeb\x52\x3b\xfe\x50\x01\x8f\xb6\xcf\xcd\xe6\x0b\x5b\x4d\x88\xcb\x18\x38\xc2\x92\x5f\x6d\xe9\x79\x13\x69\xc9\x4f\x33\xdb\x26\x0c\x74\xf6\xbb\xd6\xbe\x4a\x6e\x1b\xf5\xbb\xca\xd6\x7b\x92\x51\x56\xb4\xaf\x28\xfc\x5d\x3b\x67\x2e\x16\x28\x85\xa6\x84\x5e\x44\x6a\x11\xea\x6f\x14\x87\x30\xd6\x2e\x5d\xb3\xcd\x22\xc1\xfd\x47\x86\xaf\xc9\x6f\xf7\x65\xca\xea\x9d\x72\xf3\x99\x65\x66\x4a\x75\xcc\xcc\x6a\x6b\xbf\x49\x6d\xf9\xb6\x0d\xd0\x0a\x6f\x43\x41\xe6\x9b\xfb\x2e\x79\x06\x0d\xef\x32\xe6\xfb\xdb\x6c\xfe\xea\xcb\x1d\x35\x1a\xa8\x6f\xf3\x23\xdd\x75\xc7\x80\xaa\x1a\x3d\x61\x9c\x3d\x61\x44\x4f\xd0\x18\x1c\x6a\xee\xb5\xb3\xd8\xbd\xd6\x6b\x68\x94\x6f\x4f\x83\x03\x89\x88\xd7\xe1\x71\x91\x5e\xf8\xde\xf7\xd6\xc7\x2a\x22\x1b\xea\x40\xd7\x5a\x37\xb4\xbb\xdf\xcc\xb8\x97\xb6\xb1\x88\x7e\x15\xb1\x4d\x7d\xf0\x82\x26\xbd\x16\xb9\xcf\xb9\x49\x4e\x12\x66\x1a\xa6\xc3\xfb\x32\xda\xaa\x7d\xde\xee\xee\x61\x60\x66\x22\xc1\xe5\x08\x8b\x17\x3a\x41\x30\x55\x22\x70\x7f\x5e\xb5\x5d\x57\xd5\x7e\xaf\xc3\xd7\xb4\xa5\x8e\x55\x86\xde\xad\x0f\x9f\x61\xdc\xa3\x00\xd3\x56\x2a\xc5\xff\xae\xf1\xb7\xe1\x6f\x2d\xf3\xe2\xad\xce\x28\x17\xb8\xab\xf7\xa9\xee\xbd\x8b\x64\xc1\x4a\xc5\x0b\xff\xb9\xe9\xd8\x40\xda\x30\x3b\x3e\xa7\x37\xf9\x1c\x71\x46\xe5\x15\x9a\x0f\x4c\xb8\x47\xf3\x4e\x32\x98\x5a\xd3\xd5\x6c\xc7\xd5\x96\x98\x49\x6e\x1f\xa7\x92\x8b\x04\x19\x2d\xbc\x34\x3c\x82\xaf\x42\x58\x0b\x17\x94\xf0\x9e\x77\xd8\xcf\xb7\x83\x80\x12\x7f\x35\xc4\x5b\x74\x27\xc1\x37\x62\x93\xfe\xb3\x62\x38\xd1\x9d\x44\x41\x84\xf0\x67\x2b\x1b\xaa\xd6\xea\xd8\xdc\x7a\xa9\x63\x5d\xac\xcc\xfb\xe2\x4d\x67\xc5\xb6\xea\x73\xf2\x06\x79\xec\xb9\xaa\xc8\xdd\xfb\xa4\xec\xd0\x44\x03\xbd\xee\x7d\x91\xac\xab\xf4\x72\x9f\x73\x1d\xfb\x88\x37\xaa\x07\xe2\x76\xf7\x65\xf4\xb5\xea\xdc\x6b\xa7\xe0\xb0\x96\xfb\xa2\x65\x95\x36\x6e\x3b\x08\x84\x41\xa4\x85\xd5\xa6\xa5\xd2\x08\xc0\xb0\xa0\xf6\xb0\x03\xf2\x97\x0a\x6e\x89\x85\x6c\x21\x88\x9d\x2f\xa5\xa1\x4f\xbb\x9d\x44\x3e\x1a\x1e\x12\x9c\xd3\x0d\x96\xce\xba\xb4\x79\x5f\xe6\xc4\x5e\x3e\x46\xa4\x22\x04\x0d\xbd\x86\x45\x90\x25\x59\x20\xcc\xa9\x6d\xa6\xc9\x94\xa4\x96\x8b\x3f\x07\x02\x66\xac\xa2\x44\xb5\xf3\x4c\xe4\x2a\xa6\x42\x02\x76\x69\xfe\x8a\x2a\xec\xb5\x3d\xa7\x19\xcc\x36\xdf\xea\xc1\x62\x22\x23\x12\x66\x61\x58\x2e\xd8\x38\x06\x8c\x6e\x0d\x22\x1e\x9f\xa3\xee\xcb\x44\xa1\x9a\xdf\xe4\x46\x6a\xde\x1d\x56\x0c\xfa\x50\xf9\x16\x77\xda\x09\x86\x75\x2b\x4d\xfb\x39\xfa\x63\xde\xf0\x97\x8e\xd5\xb5\xca\xa7\xa3\x1f\x95\xec\xfa\xfd\xac\xda\x65\x6d\xcd\x4d\xde\x56\x93\x61\x76\x07\xcb\x01\x91\x8c\x0d\x53\xd5\xdd\x87\x92\x36\xe6\xc7\xac\xb8\x37\x4f\xcf\x10\xe5\xb8\x07\xd8\x59\xd3\xc9\x7e\xc3\xd6\xd7\x14\x08\xde\x9e\x2a\xde\xcd\x4c\xda\x52\xcb\x47\x6b\x49\xe5\xb6\x0a\xb5\xb7\x61\x19\x80\xe1\x9e\x8a\x04\x8b\x86\xea\x67\x92\x87\xe3\x05\xb3\xf0\x00\x25\x60\xfc\x45\x85\xaa\xce\xfa\xae\xcb\x6f\x29\xb9\xa3\x14\x98\xdc\xde\x16\x75\xac\x06\x3d\xd0\xca\x67\x08\x87\xdf\x2c\x9e\xc1\xe2\x45\xbb\xd1\x6c\x92\x2a\xc9\xd8\x40\x8a\x9e\xd3\xc0\x6f\x97\x80\x74\x48\xbf\xe1\x49\xdc\x02\xf7\x67\x01\x27\xd2\x0a\x85\x59\x3e\xcc\x78\x7d\x18\x3d\xe5\xb3\x43\xdb\xb4\xde\x22\x7b\xa8\xde\xec\x62\x58\xe7\x10\xe8\xc8\x2b\x98\xc8\x05\x89\x02\xbb\x2f\x9a\xed\x5c\xd7\x5a\xac\x6b\xe5\x69\x5d\x43\xf4\x9d\x73\x16\x64\x7b\x59\xc7\x34\xc0\x1f\x21\x36\x56\x37\x07\xea\x0c\xf6\x78\x1d\x09\x98\xd7\x6b\x3d\x42\x49\xfe\x42\x85\x4e\xa6\x4a\x43\xef\xed\x8a\x15\x02\x5f\x65\xb4\xd9\x61\xf7\x0f\xfa\x12\x4b\x1d\x27\x5b\x68\x5e\x75\x6e\x53\x93\x8a\xad\xb3\x6f\x9c\x3b\x7d\x1d\xab\x6d\xf5\x09\x1e\xb2\x71\x63\xdc\x65\x8c\xf5\x0b\x02\xd9\xff\x29\xed\xa5\xd2\xfa\xb7\x17\xcc\xe8\x93\x61\xd4\x4b\x4d\xcd\xf2\x7e\x92\x6b\x92\x1d\x58\x1e\xd4\x0c\x0a\x7e\xbf\x88\x3a\xb4\xe7\xe1\x57\xdc\x90\xb4\x9e\xf4\x62\x57\x80\x38\x72\x84\x1d\xda\xb5\xb6\x93\xea\xa7\xd4\x28\x25\xf1\x49\x83\xb2\x29\x24\xcf\x80\x3a\x0b\x70\x06\x75\x23\xae\x60\x13\x90\xbf\xee\x0a\xe6\x26\x4b\x22\xab\x40\x85\x8b\xa1\x15\x3d\xf4\x0a\xdf\x2a\x83\xb7\xef\x6f\x32\x86\x5c\x0f\xd2\x1e\x0f\x72\x2c\x24\x41\xd6\xc7\x43\xf4\x24\xed\x46\x56\xa0\x3f\xf1\x04\x55\x2c\x0d\x68\xcd\xd6\x19\x0b\x3e\xc9\xdf\x88\x0f\x52\x82\x4a\x80\x3c\x22\x55\x84\xb0\x74\x81\xfe\xca\x40\x94\xa2\x25\x44\x1b\x0f\x9f\xde\xeb\xda\x1b\xc9\x32\xd5\x5d\xbd\x0d\x31\xeb\xbc\x4b\x1a\xa9\x27\xb1\x43\x48\xe4\xea\x4d\x12\x5a\x38\x72\xa0\x43\xec\x83\x74\x5c\x1c\x53\x07\x44\x5f\x30\x8c\x87\x2f\x9e\x63\x6e\x45\x92\x36\x41\xed\x81\xcf\x9f\x02\x26\x00\x9f\x26\xdb\x85\x1c\x95\x50\x72\xd2\x0e\xa7\x78\xd6\xe4\x76\x0a\x79\x1e\x25\x68\x6d\x4b\xa8\x5d\xa3\x4e\x9c\xbc\x87\x9c\xbd\x67\x39\x58\x9e\x67\xd1\x62\x75\x24\xd1\xc3\x1d\x43\x8a\x3c\x48\x44\xa6\xe5\x9c\x8d\x00\xf6\x58\xdb\x64\x98\x0c\xcf\x1b\x6b\x46\x07\x9f\x93\x37\x51\x82\x65\x34\x13\x38\x37\xfa\x55\xc4\x28\x21\xd2\xc5\x2c\x64\x6d\x34\x72\xab\xaf\xe6\x98\x44\xfd\x64\x8d\xc3\x99\x56\x56\x18\x91\x25\x2d\x27\x51\xef\x19\xf9\x9b\x37\x4c\x7f\xa2\xa7\x1c\x5e\xcf\x94\x35\x85\x34\x16\x49\xef\x48\x08\x62\xbc\x65\x5b\x7b\xdf\x71\x1b\x02\xe9\x32\xb7\x6b\xad\x8d\x20\x96\xf6\x25\xb7\x95\xf9\x3b\x3a\x85\x4f\x23\x2c\xc3\x05\xbf\xc0\x4f\x3b\xc5\xd0\x5d\xc0\xa9\xd6\xa0\xfe\xe7\x9d\xa2\xfd\x95\x4e\x21\xb3\x0e\xef\x15\xb7\x9f\x74\x8b\x97\x5e\xd1\xfe\x6a\xaf\x40\x80\x04\xc9\x19\xa8\x56\x46\x7d\x8a\x92\x73\x02\x91\xd5\x9f\xf5\x0c\x95\xde\xd2\x98\xe3\x2e\x04\x1e\xe2\x85\xb8\xa3\x5c\xae\x5e\xc1\xa8\x3d\xdb\x11\xe1\xdb\xb4\xe0\x9c\x35\xf1\xc5\xa3\x35\xbd\x2b\xb5\x16\xc1\x59\x65\x28\xc1\xa6\x42\x3e\x7b\xa9\x11\x07\x6d\x91\x34\xcf\x3c\x23\xcc\xa0\xcf\x26\xa2\x49\xca\x6a\xc4\xec\x25\xa6\x20\x42\x2d\xfe\x93\xc2\x7e\xfd\xb5\xda\xe2\x05\x27\xfb\xec\x1e\xd7\xd9\x53\xc3\xda\x87\xb2\x01\x65\x7d\x08\xe6\x30\x34\x0f\x1e\xe4\xa2\x31\x2c\x92\x26\xf0\xa0\x3a\x93\xe5\x54\x7b\xb2\x4c\xbb\x14\x6c\x3f\xea\xee\x51\xb6\x9a\x1a\xf4\xa5\x24\xef\x2d\xcd\xe1\xfe\xff\x1c\x0c\x44\x01\x88\x32\xde\xdf\x4a\x6f\xa9\x22\xb6\x85\x71\x63\x89\xdc\xcd\x92\x25\x55\x50\xdd\x1b\xfb\x46\x55\x5a\x10\x8d\x16\x87\x36\x6f\x22\x6d\x14\x3d\x41\x61\x81\xc5\x20\x61\xc9\x0b\x15\xf6\x27\x26\x22\x6a\x8c\x01\x4d\x61\x03\xb1\x32\xe4\x24\xc0\x00\x99\xe7\x2d\x24\x58\x4c\x1f\xe5\x77\x9c\x26\xda\xb7\x90\x3c\x2d\xa9\x3e\xac\x55\x09\x92\x99\x6f\x67\x3a\x81\x27\x94\x73\x75\xe9\xa7\x5e\x4f\x57\xc4\xda\x36\xce\x5c\x62\x7b\xd7\x28\x7f\x02\xa5\xfc\x3e\xe4\xe4\x09\xec\xde\x26\x45\x12\xb8\x59\x3a\x75\xbb\x7a\x99\x1b\xf2\xa2\xb2\x2e\xb3\xdd\xe1\x8a\x0b\x0c\x20\x39\xcf\x58\x36\xd4\x86\xb1\x4a\x65\x91\x6c\x6b\x83\x17\x8f\xb5\x75\x94\x44\xe2\x40\x80\x48\x91\xa0\x65\x2a\x77\x47\xc2\xaf\xfb\xa9\xef\x22\xe3\x86\x0c\xe0\xd2\x59\x75\xd7\xf7\xa5\x30\x1f\xa8\xa9\xe6\xbb\xcc\xbe\xf6\x1e\x6c\xec\x5d\xcb\x5d\x8c\x78\x18\xc8\x62\x26\x3b\xb3\x87\x24\xde\x71\xbb\x80\x56\x7e\xf1\x81\x98\x13\xac\x68\x73\x2b\x1a\x1e\x43\xbe\x5b\x06\xd5\x9c\x09\xf4\xbf\x64\x17\xb0\x78\x35\xb2\x20\x0b\xca\x9f\x26\x76\xf4\x03\x16\xff\xe2\x87\x42\x09\xb0\xa5\x86\x02\x13\xb7\xea\x10\xc0\xe9\x13\xb1\x45\x68\x4b\x8a\xa4\xaa\x97\x48\x88\xb7\x86\xaf\x0f\x23\x95\x0e\xc3\xef\xbe\xb4\x52\x01\xcf\xd5\x7a\x97\x2a\xb7\x9d\xb4\xd4\x20\x60\x16\x09\x76\x29\x2b\xa9\xb6\xbd\x49\x6a\x80\x62\x6a\xf6\x9b\xd2\x3e\xd2\x84\x90\x87\x11\x00\x1a\xc0\x0d\xb7\xe9\x6a\x7b\x60\xe7\x6b\x3b\xf8\x41\xdc\xd6\xc2\x68\x66\x23\x4d\x34\x0e\xc3\x04\xe1\xf3\x59\x43\xb4\x80\x95\x7b\x23\x89\xcf\xba\x15\xba\x79\xd0\x94\xf7\x19\x69\x46\xbd\x0e\x8d\xca\x76\x4a\x46\x08\xa7\x14\xd1\xa0\xb9\x1a\x03\xf2\x15\xd5\xd7\x3f\x81\x24\x86\x0f\x1b\x60\x91\x99\xf3\x84\xf0\x23\x75\x39\x91\x84\x04\x2b\xa9\x5c\xd4\xf9\xcd\x92\x7b\x0d\x6a\x08\x30\xfb\x59\xdb\xaa\xc5\x57\x35\x29\x49\xd3\x15\xe3\xf8\x4f\x99\xd1\x5e\x70\x2f\xbf\xbd\x00\xc7\x9f\x71\x2f\xb5\x8e\xd4\x46\x01\xd9\x99\xf9\xab\x98\x88\xb6\xff\xa0\x5a\x76\xbd\x88\x93\xdd\xbe\xe8\xa4\x9f\x87\x64\x24\xb4\xf8\xbd\xf1\xbf\xd5\xd4\x61\x52\x84\xea\x36\xcd\xce\x0c\x37\xb7\x37\x76\x66\x68\x32\x93\x62\xb5\x41\x97\xe3\x64\x93\x4e\x51\x9c\xca\x5a\x12\xf9\x76\xf9\x7e\xd7\x01\x0b\xf1\x43\xdd\xd2\x19\x11\x2f\x58\x5d\xca\x99\x70\xf5\x39\x15\xf9\x3b\x2d\x3b\xe6\xae\x44\xe7\x8e\xae\x46\xa0\x51\xbe\xd5\x9b\xcf\x0f\x90\x57\x6b\x00\x9e\x50\xba\x2c\x0c\x9d\x70\x55\x7c\x81\x1b\x25\xcd\x06\xc1\x16\xbf\xea\x49\x07\xcf\x9c\x07\xe8\xaf\x87\xdf\x9a\x60\x09\xc0\x74\x3a\x53\x6b\x7b\x45\x42\x71\x4a\x1a\xe3\x60\x91\x0e\x64\x82\x50\x4e\x00\x66\x66\xf0\xf2\x30\xb3\xa7\x2c\x1b\x63\xa9\x50\x52\x28\x02\x58\xee\xdc\xf3\x21\x15\x83\xc2\xb5\x02\xe9\x85\x36\x8e\x36\x92\xe2\xdf\x45\xc7\xa1\xa4\x04\x8b\xf8\x21\x26\xee\x9d\x72\x6f\x23\x29\x8e\x56\x12\x8e\x85\x98\xb6\x1b\x37\x23\x59\x03\x37\xd6\xc0\x13\xa5\x7e\x68\x68\xc2\x7f\xd5\xc1\x5e\x30\x24\xbf\xfd\x4c\x76\x43\x72\x09\x8a\x81\xa7\x37\xf9\xcf\x7e\xe7\x4f\xbd\xea\xfd\xad\x66\x4b\x26\x75\x1b\xbd\xa7\xee\x0e\x46\x51\x30\x02\x92\x97\x59\x4a\xb0\x16\x02\x68\x8d\x16\x9e\x2c\x22\x6b\x44\xb4\x72\x65\x65\x63\x0c\x78\xaf\x6d\x06\x3b\x35\x4b\x46\xc3\x3d\x85\x9d\x05\xe6\x52\xb8\x55\x15\x34\x9b\xb7\x7f\xe6\xb0\xd9\x7c\x69\x16\x9d\x6b\xaf\x90\x71\x68\x49\x40\x5f\xe5\x5e\x48\x75\x7f\x57\xd2\xec\x2f\x03\x17\x99\x60\xf5\xfe\x94\x81\x7c\x9d\xed\x67\xc3\xe0\x9f\x3b\x0a\x6e\xff\xab\x86\xc1\x5f\x1a\x05\xaf\x79\x95\x57\xb8\x7a\xc9\x97\xf8\x0c\xaa\xa5\xf3\xbd\xe7\x20\x07\x21\x8f\x1b\xe8\x63\xd6\xa5\x95\x27\x3a\x99\x65\x06\x13\x1a\x78\x51\x82\x80\x86\xfc\x33\xa4\x9f\x79\x62\x98\x9f\x60\x82\x23\xc0\xe5\x6f\x3c\x3d\xc1\x91\x7f\xe6\xfc\xb7\xdf\x77\x81\x32\x32\x30\xab\x6b\x29\x63\xa3\xf4\x50\xdf\x97\x9e\xa8\xa4\xef\xc6\x9d\x49\x0f\xba\xc5\x13\xe6\x7c\xb2\xaf\x80\x9a\xb2\x95\x1f\xb1\xe7\xdd\x97\xc9\xa1\x37\x2c\x98\x13\x4a\x04\x9d\x8c\xb2\xf5\xeb\x32\xdc\xfc\x6d\xb4\x26\xc4\x30\x29\x1c\x08\x7f\x14\xf9\x56\xef\xb3\xea\xe7\x2c\x7c\x9f\x68\x02\x58\x9e\x9b\x5b\xb6\xad\xdf\x76\x01\x2a\xa2\x82\x64\xa1\xcf\xa4\x6d\x35\xcd\x74\x8a\xa0\xad\xd9\xa0\x81\xdb\xcc\x0f\x58\xa4\x75\x3f\xf8\x8f\xb2\xc4\xf4\x97\x82\xff\xdf\x2e\xba\x00\x71\x4b\xae\x80\x65\x28\xcf\xfd\xd4\xa9\x45\xb0\x66\xf8\x13\x94\x50\xed\x27\xe4\xc1\xa2\x6a\x2f\x32\xc3\x3b\x74\xb3\x33\x92\xac\x90\x8b\x9a\x07\x73\xc4\xc9\x0a\xe0\x41\xd9\x7d\xfe\x96\xcc\xe6\x61\xe6\xde\x73\x04\x6c\x09\x49\x64\xce\x01\xb9\x94\x79\x52\x85\xf8\x2c\x1a\xba\x0d\x69\x19\x72\xdd\x56\x4c\xf5\xee\xd7\x32\xa4\x29\x7c\x13\x3e\xa1\xdc\xbb\xcf\x09\x25\x24\x8b\x42\xb6\x9a\xf7\xc1\x78\x9b\x94\x88\x13\x30\x81\x21\x88\x74\x93\x7d\x04\x59\x6e\x4a\x77\x48\x22\x9a\x9f\x65\xb7\x4a\xeb\x1b\xcc\x9b\x6d\x90\xaa\xdd\xdd\xa6\x9e\x53\x8b\x2b\xf6\x84\x39\x4a\xce\x39\xce\x3d\x63\x91\xb9\xb7\x90\xd7\x05\xef\x00\x1d\xdb\xf7\xff\x2c\x8d\x86\xdb\xbf\x52\xa4\xe1\xdf\xa7\xd1\xd0\x5f\xf8\xad\x7e\xbb\x64\x5b\x66\xd7\xd4\x51\xc1\x07\xee\x56\x10\xbb\x4b\xf3\x0e\x8c\xea\x29\xb7\xd5\x5a\xe8\x0f\x94\x60\x82\x80\x18\x36\x59\x66\x97\x7e\x16\x44\x84\xca\xe0\xe5\x50\x88\x26\x92\xc4\x4b\xb7\x8b\x76\x57\x4e\xb9\xd7\x96\x40\x4b\xc1\xb8\x8f\xb4\x76\x50\xe8\x34\xdb\x85\x0c\x3c\x95\x64\xe0\x60\x82\xf1\xab\x1f\xe8\x85\x90\xe5\x05\x58\xe2\x5b\x88\xa7\x1d\x24\x29\x86\xfb\xbc\x84\x9b\xf3\x2d\xb8\x72\x10\x6a\xc5\xd7\x7d\x99\xc4\x58\xbb\x1b\x6a\x37\x70\xe9\x01\xf8\x64\x69\xd8\xce\x5a\x22\xd4\xbe\xc4\x92\x96\x0f\xbf\x75\x66\x9a\xf6\x85\x8a\x4e\x1c\x13\x69\xe2\x95\x63\xe0\x68\x63\x20\x50\x2a\x90\x24\x3a\xf3\x21\x3e\x7f\x41\x14\x4b\x4b\x4b\xdd\xef\x6a\x80\xfe\x05\xb9\x5c\xbe\x70\x94\xb7\x7f\xab\x1b\x83\xb3\xe2\x4e\xa2\x24\xe2\x65\x44\x0f\xbf\x46\x5b\x7d\x78\xd7\x14\x99\x10\xd9\xbd\x5b\x23\x98\xd7\x82\x12\xa4\x09\x03\x4d\x20\xcf\xbd\x98\xff\x27\x25\x05\x96\x1a\x04\x41\x8b\x18\x68\x20\x52\xed\xc8\xa1\x74\x4b\x5a\x6e\x47\xef\xa9\xe6\xa3\xf6\x60\xb6\xf0\xee\xce\xea\x01\xa5\x22\x6e\x69\x60\x57\x6b\xc4\x65\xfc\xad\x43\x75\x57\x46\xc6\x51\x52\x52\x76\xb7\xd3\x92\x96\x34\x0e\xc4\x8b\x74\x83\xd2\xdf\x84\x59\xa6\x29\x4a\x8a\x35\xa2\x74\x1a\x40\x78\x64\xc4\x0c\xd6\x1e\x4d\xde\x71\x2c\x5a\x23\xc0\xbe\x2f\x54\xbc\x81\xe8\x50\x93\x1b\x75\x88\x20\x43\x24\xad\x24\x28\x13\xb9\x73\x3e\xc7\x11\x1f\xe7\xcf\xe7\x7e\x3c\x70\x37\x94\x5e\x55\xf8\xe2\xa2\x87\x12\x1f\xf4\x55\xee\xa4\xbf\x02\x38\x5e\xb8\x15\x3e\x28\xa4\xcc\xe1\x0d\xa1\xbb\x2f\x3a\xb3\x40\xe7\xf8\xa4\x12\xc7\x57\xd0\x16\x83\x7f\x58\xd5\x80\x02\x82\x0a\xf6\x07\xd0\x7b\x10\xf4\xda\xb6\x28\xbe\xc8\x33\x0f\xad\xb1\x2a\x22\x88\x80\x51\xcb\x93\xeb\xb6\x34\x10\xab\x64\x7b\xd4\x6c\x91\x1e\xcc\x7d\x71\x3b\x95\xb0\x74\x80\x32\xb9\x95\xcd\x5d\x7f\x24\x94\xb2\x11\x9a\x6a\x3d\xcd\xbc\xf9\x59\x5a\xb6\xeb\xbc\xfb\x79\x53\x00\xf1\x83\xe1\xd6\x36\xbf\x29\xbf\xa7\xc0\x5b\xf9\x8d\xdc\x0e\xde\xd7\xf5\x40\x9b\x22\x17\x5e\xf7\x69\xde\x06\x78\xee\x34\xcb\x45\xb4\x5e\xde\x61\x28\xb6\xb2\xd5\xde\x52\xed\x3e\x2e\xa6\x0f\x28\xdd\x16\xff\xc5\xff\x01\x2d\xe1\x2a\x5f\xf0\x5f\xfc\x26\xbf\xfd\xe3\xe5\x1d\xfd\x5c\xc5\x46\x2a\x09\x70\x3b\x4a\x24\x42\xbc\x0f\x81\x1a\x96\x9f\x08\xa9\xea\x41\x48\x46\x1d\x18\xd9\x17\x73\x5b\xbf\xa1\xea\xa6\x81\x80\x40\x77\xe8\x62\x82\xf3\x05\x50\x4a\x79\x22\x85\x07\xb5\xbc\x5e\xe0\x5e\x95\x98\x69\x74\x24\xa4\xf5\x74\x6b\x36\x52\xed\x73\xaf\xd3\x2d\x27\x1f\xa4\xb5\xbc\xbf\xf5\xdc\x52\xcd\xba\x07\x33\xad\xe4\x10\xc9\xcd\xe7\x34\xdc\xdb\xe6\x9e\x14\x79\xac\x38\x8c\xe8\xcc\x95\x0e\x0a\xde\x28\x6a\x7b\x00\xc7\x64\x20\x6f\x75\x3b\x29\xdb\x84\x85\x87\xa0\xab\x93\x61\x00\x6e\xa8\xe6\xbd\x23\x44\x8e\x88\xe0\x01\xb4\x1b\x56\xfe\x49\x43\xea\x00\x57\x63\x67\xdd\x52\x75\x73\x6f\x87\xaa\x24\x62\xb2\x09\x24\x69\x07\x9c\xca\xde\x8e\x31\x48\x57\xe9\x2b\x1c\x03\xa4\xca\xea\xc8\xaf\x86\xda\x0b\x2d\xd6\x6f\xaf\x1a\x22\xcf\x3c\x80\x33\x54\x2c\x6c\x94\x75\xf1\x3f\x81\x47\x2f\x3e\xed\xba\x07\x56\xfc\xee\x95\xea\x39\x00\x4c\xef\x96\x93\x76\x3a\xd6\x36\x98\x2c\x16\x21\x47\x22\x62\x9d\x07\x82\x62\xf5\x40\x64\x0f\xd5\xf7\xa8\x6b\x01\xcd\x20\x14\xda\xb5\x43\xbc\x5d\x9e\xaf\x42\xf1\x76\xed\xc8\x72\xf9\x55\x90\x4e\x60\xf4\x58\x71\x4a\x09\x01\xd8\xbe\x43\xd9\x34\x20\xae\x72\x84\xa0\xcb\x20\xf1\x51\xe1\x85\x7a\xb4\x3a\x6e\x1c\x35\x54\xe5\xf8\xf0\x34\xb7\x2f\x1e\xc7\x38\xcd\xfd\xc1\x6b\x04\x64\xb4\x94\x20\x03\x0d\xa4\x47\x29\xa9\x23\x5b\x2f\xd4\xd3\xd4\x8e\xa8\xb6\x82\x6d\x0a\x61\x3d\x3e\x3b\x80\x90\x65\x5f\xa0\x07\xc4\x3a\x87\x82\x6d\xd0\xc6\x67\x0b\xee\x91\xe3\x22\x8d\x8e\xf2\xbc\xde\xdc\x67\xa0\x99\xba\xaf\xf1\x1c\x51\x06\x8a\xc3\x9e\x2e\x78\x7b\x5c\xb1\xf1\x8a\x04\x09\x5e\x4a\x41\xd7\x35\x07\x1f\x74\x8f\x74\x6b\xa8\x43\x7f\xbc\x2e\x9d\xff\x9f\x5c\x79\x10\xfc\xd2\x03\xa8\x7f\x76\xa8\xdf\xf7\xb8\x16\x7c\xa7\xe7\x3b\x38\x96\xf3\xd5\x07\x81\x2a\x74\xb2\xdd\x56\x3d\xc8\x00\xb4\xb6\x72\x2f\x85\xdc\x3f\xcb\xf9\xe5\xf9\x87\xdb\xcb\x2f\xee\x62\x82\x44\x28\x88\x85\x8e\x60\x1a\xe2\xf4\x7a\x72\xad\xf7\xce\x14\xb8\xb0\x64\x66\x2a\x95\x7f\x4f\x2d\xdf\x27\x2a\x82\x8b\x53\x80\x15\x86\x33\xcc\x70\x14\x55\x15\xef\xcc\x3a\xfc\x5f\x84\x8e\xf0\x2b\xa6\x09\xd8\x3c\x7d\x87\xf4\x96\xaf\xe4\xbd\x84\x7e\x56\x3e\x3d\xea\x3f\x7f\x23\xb7\x7f\xde\x9d\x80\xf8\xe1\xdf\xdf\x24\x5f\x4c\x83\xaf\xd5\x1a\x2f\xc8\xf6\xa7\xa0\x23\x08\xa7\x2e\x75\x98\x5c\x06\xa8\x1c\x56\x4a\xe4\x94\x3c\x7c\xfd\xcc\x27\x41\x44\xd6\xb2\xc1\x12\x18\x33\x28\xa8\xee\xbe\xf4\x96\x32\xb0\x04\x9f\x0b\xef\x17\x77\x38\xbe\xcf\x24\x6a\x7e\xc1\x6d\x3f\x33\xee\xb6\x91\x5a\x69\x5b\x05\x80\x17\x08\x7b\x64\xec\x33\x66\x24\x9a\x7c\x6d\x40\x55\x12\x7e\x46\xde\xe1\xa1\xe5\xf4\xd7\xbd\xaf\xfb\xd2\x9b\xbe\xbf\xcd\x5a\xdd\x25\x59\x7b\x0f\x7d\xf9\x9e\x90\xd5\xd5\x50\x86\x6c\xe7\x9d\x44\x3b\xf5\x36\xd6\xa5\xb7\x71\x87\xc2\x0f\xee\xe5\x2f\xbb\x71\xe3\xfb\x64\x85\xe6\x57\x24\xf0\x1f\x7f\xad\x60\x2b\x53\x9f\xb5\x8b\xd5\xfd\x2a\x2e\x61\x65\x1d\x7a\x6f\x25\xc9\xc4\x06\x76\x4f\x51\xd9\x96\x06\x25\x64\xb3\x1f\x1a\x95\x0a\x7d\x39\xdb\x96\x02\x98\x92\x3c\x19\x67\x75\xd4\x54\x81\xa5\xbd\x6c\xbf\xd3\xf4\x53\x26\xc4\x6c\x2b\xcd\x5d\x90\x72\x5d\x71\x67\x84\x83\xd1\x54\xf8\x50\x04\x47\xcd\x6f\x75\xf5\xbb\x7e\x44\x82\x6e\xbf\x2b\x14\x34\xbe\x0f\xcb\x6b\xfe\x99\xe6\x89\xb8\x5f\x34\x58\x6a\x40\x82\xd5\x22\x14\xde\x8f\x75\x25\x74\xc3\x17\x2b\x07\x94\x47\x32\x44\xe3\x61\x04\x9a\x92\xd5\x0f\x9f\x16\xe5\x0a\xb0\x85\x32\xb3\xbe\x0c\xe8\x2b\xd3\xc1\x13\xcc\x58\x11\xef\x27\x99\x30\x27\x17\x84\xfe\xa9\x2c\xde\x23\xf6\xdd\x2c\x0d\xae\x29\x14\x22\x65\x79\x9f\x9d\xfd\x9d\x90\x93\xdc\xae\x57\x38\x89\xcc\x1c\xc2\x5a\xac\x44\x1a\x40\xd0\xad\xa5\x49\x4f\x0e\x8c\x02\x07\x7c\x64\xcd\xb7\x2b\x6b\x38\xec\xd4\x37\x11\x1b\x81\x8e\xa0\xaf\x27\x23\xaa\x02\xf3\x69\x68\xb2\x53\x6b\xf0\x71\xc0\x68\x15\x64\xcb\xb5\x0e\xbf\x85\xda\x52\x03\xaf\xa3\x48\x43\xc8\x1d\xaa\xd3\x42\x25\x19\xae\xe3\xd0\xe2\x13\x22\xc7\x7d\xb3\x0f\x8f\x71\xee\x48\xa5\x44\xa5\xa9\x08\x56\x1d\x58\xc7\x19\x2d\xd1\x7c\x61\x2f\xb4\x93\x73\x45\xbd\x29\x63\xe6\x28\x5b\x64\x75\x8b\x9b\x7c\x98\x68\xa1\x36\x5f\xda\xe9\x9d\x4f\x2a\x70\x31\x9c\x5f\xf3\xed\x98\xc8\x69\x1c\xc4\x9a\xcf\x19\x0c\xbc\x22\xfd\x38\x8b\x54\x0a\xa3\xf2\x6e\x5c\x43\xd2\x85\x85\x2b\xd3\xfd\xc3\xec\xfd\xd1\xf0\x25\xb2\xf2\x28\xe0\xa1\x6b\x0c\x8b\x57\x59\xb4\x58\x68\xd1\x74\x8d\xda\x97\xd2\x8e\x05\x97\x64\x6e\x85\x9a\x3f\x6e\xac\x30\x9e\x78\x2c\x43\x52\x55\x28\x89\x0f\x3d\xe8\xf0\x53\xc9\xef\x62\x18\x41\x2a\x38\xa3\x73\xf8\x88\x3b\x28\x4e\xdb\xc7\x0e\x0c\x0e\x21\x50\x61\xec\x90\x15\xa8\xa2\xd2\x55\x6e\x3b\x18\x5b\x04\x23\x89\x7a\xe6\xe0\x37\x41\x2d\x90\xc6\x0c\x30\xbd\x2d\x58\xc6\x33\xc1\xa8\xd9\xf3\x5d\x58\xb7\x2c\x90\xf9\xf7\xd1\x1a\x20\x1f\x94\x50\x1c\xac\xf7\xfc\x72\x48\x7e\x9f\x23\xd0\x6c\x57\x74\xb6\x98\xa6\x02\x06\x28\xe9\x98\x22\x4a\x52\x9b\xb0\xba\x50\xd9\x64\xc1\x29\x63\x03\x85\xbd\x01\xee\x02\x32\x7a\xd1\x44\x78\x32\x31\x96\x89\x71\x4e\xa3\x18\x3d\xe9\xa0\xdb\x29\x5c\xbd\x57\x44\x65\xd1\xeb\xd6\x45\x76\x40\xa3\x40\xc8\xb3\x54\xd9\xa6\xa5\xee\x5e\x1c\xbc\x2d\x7f\xc4\x56\x00\xbd\xf4\x26\x01\x27\xb2\x4d\x37\xeb\x30\xea\x2e\x5e\xc6\xa2\x2c\x0d\x3e\x16\x30\x25\x9c\x61\xd6\x90\xb5\x82\xb0\xe2\x6c\xa9\x31\x54\x53\x72\x08\x1d\x2d\xdd\x6e\x70\x1e\x06\x5a\x19\xf2\x8a\x88\x71\xc9\x55\x7f\x0e\xd4\x91\xd8\x53\x9d\xf3\x4e\x05\xae\x60\x6e\x98\x76\x16\x8a\xa1\xc6\x66\xb2\x60\xa5\x91\x57\x08\xc5\xf5\xa7\x5d\xc9\xe1\x80\x44\x02\x55\xef\x2b\x08\x81\x31\x37\x94\x08\x76\x91\xbb\x31\x42\xe0\xa5\x9f\x01\xe5\xcc\x82\x29\x37\x7d\x6a\x3b\x50\x6c\xb0\x48\x19\x90\x83\xf7\x9f\xef\x64\x4b\xf6\x85\x3a\xc6\xcc\x9c\x07\x75\x5e\x19\x60\x24\xbf\x22\xca\x62\x04\x55\x66\x8a\x2a\x92\x7c\xf3\xb6\xd7\x9e\x4c\x52\xf5\xf5\x06\xf8\x0a\x24\x27\x41\x59\x44\xa4\x0c\xae\x88\x1e\xba\x2f\x22\x8c\xee\x4d\x49\xa3\x1f\xee\xf8\x2a\xd3\x2f\xd9\xc7\x49\x92\x31\x0f\xbf\xc0\x28\xbb\xb0\x04\xae\x67\xf6\xfb\x83\xf1\x86\x0e\x49\x30\x2c\x7e\x51\xe5\x09\xde\x1a\xbe\x0c\x20\xf4\x1e\xf1\x46\xbe\x00\x98\x63\xdf\x4e\xcd\x31\xba\x4b\x38\x21\x48\x81\xec\x18\x39\x90\x74\x92\x31\xc1\x0c\x4b\x0d\x19\x3d\x04\xd5\x5e\xd5\xc2\x6e\xff\x3b\xe4\xc2\xc6\xf7\x59\x14\xcd\xaf\xa5\xc0\x4f\x19\x6d\x9f\xbf\x19\xcc\x45\x43\xff\x40\x4f\xfb\x87\x72\xda\xe7\xf7\x8b\xaf\x84\x7d\x27\x76\xcb\x0c\x3f\xf3\x0c\x17\x41\xc9\x29\xe1\x1d\xdf\x3f\xec\xf5\xe1\x04\xcf\xa7\xfe\x43\xba\xe0\x61\x36\x7d\xfa\x5c\xb7\xdf\xf7\x60\xeb\x62\xa3\xe1\x4d\x80\x53\x2b\xd2\x30\x5a\x18\x04\x59\x74\x8c\x63\x79\xfa\xfa\xd8\x61\xc5\x71\x7f\x5c\xcb\x3c\x98\x65\xcf\xc0\xba\x05\x1a\xf7\x43\xf6\x63\xb9\xd2\x1f\xcb\x87\xfc\xc7\x52\x05\xe6\xec\x77\xa1\xe0\x33\x12\x8c\x7d\x6f\x1f\x52\x28\x57\x5e\xe5\xfa\xf2\xd8\xf8\x48\xaf\x9c\xa7\x59\xfd\xdc\x3c\xf5\x53\x0a\xe7\x71\x1b\x4f\x77\x77\xdd\xf3\x57\xfd\xf4\xfb\xa4\x87\xe6\xd7\x62\xc5\x47\x3f\xbd\x5e\xa6\x01\xf8\xfb\xf7\xdc\xf2\xf1\xcf\x6d\xf1\x4f\x1b\xfc\xcc\xf4\xea\xf8\x69\x27\xb9\xfd\x51\xc5\xfb\x7f\xfb\x08\xfd\xea\x7d\x7f\x1f\x66\xd7\xfc\x5a\xca\xf5\x04\x51\x68\xe0\xd2\x5c\x17\x43\x14\x86\x22\xc1\xf4\x2e\x0e\x60\x48\xfa\x26\xc3\xad\x09\x01\x2a\x18\x96\xa8\xf5\xd0\x0b\x57\xa6\x51\x1b\x0a\x93\x23\x2a\xdf\x8e\xf3\x33\x36\xec\x5c\x92\x34\x5b\xea\x64\x85\x11\x5f\x04\x50\xee\xdf\xa1\x8d\xba\x0a\xb4\x4a\xc9\xd2\xd4\x21\x75\xf8\xfe\x26\xb9\x62\xe3\xa6\x63\xf0\x0e\xcb\xc8\x1b\x57\x3c\x10\xde\xd1\x87\x4c\x42\x85\x07\x5d\xa5\x9d\x55\x80\x2c\x9b\x81\x68\x34\x02\xe6\x0d\x7a\xa3\x69\x96\xdb\xbe\x34\x9a\x23\x2a\xa4\xcb\x02\x7c\xbc\x81\xa8\x9e\x2e\x1b\x44\x19\x11\x6b\x2a\x39\xe8\xc9\xe5\x0c\x6f\x5c\xd1\x2d\xb7\x75\x36\xe4\x87\xfc\x58\x90\x35\x4f\x98\x1a\x48\x4b\xec\x21\xd9\xfe\x5d\x3b\x1c\xbc\x87\x83\xb7\x74\x02\x82\xa2\xc2\x07\x51\x37\x0b\x76\x1c\x9a\x70\x12\xf1\x6a\x79\xfc\x15\x7f\x70\x47\x8b\xd8\xfa\xec\x24\xd8\x47\x9b\x9e\xbd\xd9\x3d\x31\x54\x6e\xcf\xb1\x2d\x56\xa1\x38\x31\x83\x38\x04\xdc\xeb\x12\x5c\x03\xb3\x93\x5f\x5d\x58\x24\x09\x03\x17\x0a\x1d\x40\x71\x7b\x13\x90\x92\xf9\x47\x37\x70\x3c\x7f\x7f\xda\x69\x17\xfa\xa2\x82\x2a\xca\xcd\xfb\x8c\x0c\x83\xea\xee\x67\x32\x3b\xc7\xb3\x5a\xef\x45\x6e\x5e\xac\x6e\x24\x86\x83\x5e\xef\xa7\xc2\x3d\xc7\x77\x3a\xbf\xc1\x97\x82\x2a\xda\x4d\xc1\xe1\x96\xf3\x6d\x9f\x20\x0b\x14\x04\x66\x77\x3e\xd3\x87\x16\x7e\x6e\xfc\xaf\x46\xd8\xf7\xac\x0f\x9a\xfb\xff\x79\x22\x3f\xa6\x0e\xfa\xdf\xca\x51\xea\x33\xdb\xbf\xe0\x32\xd6\x34\x75\x69\x1b\xea\xad\x07\xd2\xac\x70\x89\xf4\xba\x08\x27\xc9\xf2\xad\xde\xd6\x65\xca\xb8\x6a\xd8\x1f\x9e\x55\x00\x91\x0d\x6e\x53\x87\x0f\x1b\xc0\x00\xd6\x04\x55\x23\x6e\xce\x56\xc9\x4d\x49\x65\x54\x50\x1c\x23\x25\x55\x7b\x7f\x13\x30\x86\x9b\x82\x02\x8f\xf5\x3a\xee\xfe\x59\x01\x5c\xc1\x57\xab\xc0\x7d\x50\xa4\x9d\x08\x68\x2b\x47\x7c\xf0\xd7\xb5\x41\x31\x81\xe0\x40\xc1\x46\x3b\x65\x9f\x5b\xb6\xfb\xd2\x00\x64\x0b\x35\xec\x9d\x83\xfc\xb9\xd9\x3e\x34\xe7\x33\x03\xf0\xd5\x5e\x77\xca\x68\xb7\x3f\x78\x8a\x97\x33\xf8\x4d\xb4\x4c\xe7\x15\x4a\x16\xcc\x6e\x5a\x2a\xb5\xec\x33\xf5\x41\xfe\x4f\xb1\x7e\xa8\xe5\x34\xe6\x61\x48\x75\x5b\x8e\x2f\x8b\x65\x6c\x59\xc6\x3c\x4e\xaa\xd0\xbe\x61\xc2\xf4\x53\x30\xc6\xa4\xf1\x26\xbf\x74\x47\xbf\x4f\x25\x69\x7e\x29\x59\x7b\x36\x73\x4b\xb3\x14\x25\x62\x40\x7e\xd4\xb3\x60\xa8\x09\x8b\xfc\xd7\xa5\x43\xd5\x0d\x03\xb9\xd1\xcb\x38\x88\x8a\x07\x41\x26\x3f\x63\xc3\xea\xfb\x62\xd7\xf3\xf0\xe3\x3c\xe3\xfb\x9b\xb4\xde\xe3\x5a\x10\xbd\x36\x77\x66\xd6\x65\x8e\x8f\xa7\x8f\x93\x87\xb3\x5b\x53\x13\x9e\x7d\x9d\x79\x40\x35\x59\xa8\x3f\xe4\x0d\x0d\x6e\x8b\xec\xde\xd1\xc2\x60\xcd\x62\xcc\xa4\x33\xc0\xa4\x36\xa2\x44\x28\xe2\x10\xbe\xf9\x16\x78\x54\xb4\x6b\xcf\xab\x5f\xff\xe9\x96\xe3\x86\x1f\xd0\xb9\x13\x38\xe7\xdf\xd7\xc5\x6f\x02\x41\x9d\x62\x49\x29\x19\xe2\xb7\x61\x8c\x4d\xb8\x9b\x86\x55\x56\x2b\xcb\x58\x0f\x75\x9b\xc6\xdc\x79\x9c\x49\xf3\x38\xaa\x77\x11\xbb\xac\xda\x49\x7a\x99\x47\xd3\x3f\xae\x04\x92\xdd\x4e\xa2\x4d\xb0\x10\xd2\xfe\x6d\x3d\xea\xa4\x16\x13\x9a\x2a\xac\xc6\xd2\x66\xc7\xa2\x41\x8b\xd8\xdb\xc1\xcd\xdc\xf7\xb6\x83\x43\x12\x59\xad\xc1\x08\xda\xb1\x18\xca\x72\xad\xe6\x75\x91\x31\x3f\x79\x05\x12\xd4\x47\x04\xa6\xe2\x15\xf8\x4a\x0e\x1e\x50\x72\x75\xf1\x9e\xfc\x96\x70\x47\xbc\x21\xde\x8f\xdf\x0e\xef\xc6\x6f\x86\xcd\xd3\x00\x27\x44\xda\xaa\x44\xf4\xdb\xec\xe0\x7d\x2c\x7e\x23\x32\xc6\xeb\xab\xf8\xaa\x48\x73\x7c\x9f\x35\xd0\x3c\x5f\x62\xa2\x3a\xf2\x59\x38\x54\x2d\x41\xb0\x87\x9a\x4b\xa6\x63\x13\xca\xfa\xec\xd2\x6a\x2a\x55\x92\x7f\x56\x09\x96\x8e\xc5\x46\xaa\x0d\xc8\x81\xd3\xfd\x50\xad\xef\x6f\xad\x96\x54\xba\x6c\x66\xd0\xb4\xb1\x9e\x8a\x4f\xbe\x6e\x80\x2d\x66\xc4\xfd\xc2\xe1\xee\xc1\xd9\x00\x1b\xd7\x20\x4a\x05\x11\xae\x65\x0e\x46\xef\x2a\xf8\x93\x13\x75\x59\x04\xb6\x4d\x50\xad\x30\x8e\x6c\x6e\xcb\x75\xef\xee\x01\xdd\x51\x7d\x00\x2a\x51\x3c\xf9\x2d\x84\x8d\x0d\x81\x7c\x75\x8f\x3d\x8f\xe8\xc1\x51\x4c\x0d\x9d\x8f\x28\xfc\xab\x76\x48\x06\x3c\x27\x02\xd0\x88\xfd\x18\x09\xbc\x80\x60\x53\xaa\x5a\x41\xcf\x51\x0c\xb5\xbe\xa6\x88\xf5\x15\xca\xca\x04\x92\x74\x40\x19\x1d\xc8\x22\xce\xe9\xa5\x9e\x99\x46\x46\x23\x4a\x07\xf5\x45\x52\xe6\x1f\x8a\x50\xea\x27\x97\x1d\x71\xcb\x12\x66\x10\x07\x91\x0e\xd6\x63\xeb\xae\xd0\x44\x84\xa4\x24\x54\x89\x34\x49\x9b\x28\x1b\x2e\xb8\x3f\x10\xd4\xa5\xd6\x03\x56\xdc\x34\xca\xb8\xf0\xa2\x18\xe1\x53\x6c\xf1\xbe\x78\x73\xfb\xf0\x44\x1e\xa2\x48\x04\x56\x23\x2d\x44\xd4\xc2\xb0\x22\x87\x59\x04\x2b\x29\x10\xcc\x39\x82\x23\x25\x1f\xfd\x51\x56\x3d\xa2\x78\x32\xf2\xc7\xa8\x28\xcc\xab\x5a\x24\xd3\x33\xc9\x8a\xea\xa5\xdb\x5d\x2b\x92\xa9\xf8\x0f\x31\xa3\xb2\x73\x88\x2b\x0d\xd0\xd2\x00\xd6\xa1\x24\x64\x10\x94\xfa\xaa\x78\x56\x41\xf5\x93\xa9\x0d\x9b\xc6\xb8\x10\xb8\x03\x2b\xb4\x91\x92\xed\x01\x30\x15\xb7\x9a\x61\xbe\x45\xc0\x5e\x41\x7b\x4b\x66\x44\x20\x02\xf5\x0c\xe3\xc9\xb9\xe8\x71\xf9\x1f\x04\x9b\xe2\xba\x54\xba\x18\x44\x39\x02\x94\xde\x47\x84\x6b\x04\x53\x96\x95\x64\x96\x5a\xdf\x83\xcc\xaa\x79\x7f\x6a\x3b\x28\x10\xe0\xe7\x59\x54\xf7\x60\x36\x6c\xec\xff\x87\x30\xb4\xc3\x50\x66\xe1\x33\x24\x29\xa8\xcd\x63\x0a\x5a\x4e\x44\x0e\xd4\xe3\x68\x90\x84\x3a\xa0\x9b\x16\x49\x59\x8f\x9b\x25\xb1\x66\xb5\x59\x78\xac\x63\xb0\x36\x0e\x1e\xc2\x48\x82\x75\xa6\xa9\x4f\x25\x50\x35\x53\xff\x4a\x10\x26\x6a\x71\x2b\xd5\x10\x0b\xc2\x9b\xcd\x52\xa5\x32\x1e\xb8\x69\x24\x94\xa3\x26\xa2\x7f\xbb\x18\x98\x01\xc1\xc2\x34\x64\x27\x4b\x01\x56\x96\x1d\xd9\x1d\x9d\x14\x0d\x61\x0e\x03\x89\x8f\x5a\xa2\xda\x04\x11\x52\xbf\x01\xf4\x40\xa8\x2d\x76\xb0\x19\xb6\xbd\x23\xbc\x8e\xd7\x36\x0f\x12\x2a\x06\xd3\x39\x92\x06\xe8\x3b\x19\x95\xff\x12\xda\x8c\x40\x65\x32\x9c\xdf\x07\x82\xdc\x13\x0a\x7e\x28\x95\x3e\x69\x3b\xeb\x49\x61\x39\xf2\x01\xbf\x26\x84\xdf\x45\x2e\xe1\xf7\xc1\x6e\x29\xa7\x24\x8a\xa5\x82\x14\xc5\x04\x64\x51\xeb\x48\x72\x62\x0f\x67\xd2\xf1\xb5\x89\x3d\x5f\xf3\xa2\x3f\x13\x5a\xea\xa3\xa6\xaa\x03\x2c\x34\x30\xff\xa4\x8e\x14\x55\x92\x11\x65\x50\x72\x07\x4c\xb2\xcb\x36\x7a\xae\x95\x05\xbb\x2d\xa4\x50\x0c\x88\x11\x99\x25\x4d\x4b\x26\xcc\x42\xfb\xec\xde\xfd\xa5\x81\x92\x43\x0d\x5c\x25\xc7\x44\x01\x1e\x4b\xc2\xdc\x9a\x05\xc9\x18\x92\x4b\xf3\x58\xa8\x9e\x56\xcf\x39\x7e\x44\x32\xf6\xdb\x83\x76\xa7\x47\xf8\xbb\x8c\x44\x7a\x2d\xf7\xcb\x10\x15\x2d\x39\x18\x20\x51\x84\x39\x76\x14\x6b\x7a\xb3\x89\x4d\x37\xfc\x67\x8f\x27\x0d\x9c\xf9\xf9\xa8\xcf\x0f\xfa\xb7\x3c\x26\xb8\xcc\xf9\x98\xf1\x90\x7f\xf6\x11\xed\x41\x73\xd9\x02\x7c\x17\x3c\x22\xd4\xfd\x3c\x8c\xf1\x15\x09\x84\x4c\x2b\x58\x42\x40\x9d\x0c\xb3\x20\xf7\xdb\x81\x8b\x11\x43\xd5\xd2\x60\x84\xd9\x0d\xfb\x40\x9f\x54\xe2\xc4\x04\x04\xdd\xcd\xfc\xca\x3d\x35\xdb\x97\x46\xaa\xd0\x2e\x28\x4a\x83\x23\x52\xb8\xe4\xc5\x24\xcc\xb4\x6f\xb9\xc8\x26\x10\xe0\x2f\x95\x69\x6e\x00\x98\x4f\xd5\x4e\x37\xb4\x47\xc0\xdf\xa1\xe8\xea\x3f\x60\x8c\x32\x13\xf8\xad\xfa\xd0\xe6\x06\x71\xcb\x8d\xe7\x0b\x56\x10\x51\xb0\xc8\x21\x3f\x8c\x06\xf1\x41\x4b\xdd\x23\x69\x7b\x03\xe7\x10\x6e\xba\xee\x35\x95\x04\x44\x03\xcf\x21\xe5\xc6\x84\x87\xb4\xbd\xb8\xfb\x82\x39\x09\xd2\xa0\xc9\xf2\xfc\xa8\x9c\x55\xad\x3d\x67\xbd\xfd\xdb\x57\x63\xef\x35\xbd\xfe\x7f\xaf\x2a\xe9\xa9\x69\x0a\x98\x9b\xda\x0f\x54\x8e\x11\x99\xff\x1e\xf4\xc0\xdd\x49\x01\x00\x4d\xb0\x03\xc9\x92\x91\xd7\x45\xbb\xde\x17\x91\xfa\x23\xd5\xe4\x4f\xcf\x27\x56\x5e\x60\x14\xa5\xb9\xb1\x8c\x50\x93\x2f\xc6\x2c\xac\x1e\x67\x31\x36\x46\x14\xe7\x83\x09\x96\x19\xf7\x29\x7b\xbb\x2f\x23\x0a\xb5\xad\xf2\x18\xec\x71\x82\xab\xf8\x81\x4a\xd9\x38\xe5\xba\x94\x0f\xc8\x95\xf3\x8e\x22\xdd\xf0\x41\xc7\xb9\xe5\x17\x68\x06\xb4\x92\x57\xed\x7a\xa6\x5f\xd0\x0a\x07\x1b\xe5\xce\x7b\xf9\xf2\x24\x5f\xbd\xc0\xd7\xa4\xfe\x3f\xae\x0c\xa2\x89\xa4\x06\xd9\x4a\x29\x17\x91\x10\x39\x9d\xc6\x19\x27\x70\xbf\x5a\xf3\x55\xb9\x66\x23\x85\x5b\x6d\xe3\xce\xc3\xd4\x9d\xe8\x10\x9c\x91\xb2\xfa\xce\xd4\x47\xee\x67\x1f\x8f\x53\xbe\xbf\x0d\x95\x54\x5a\xb9\x6b\xbd\xc2\x15\x7a\x31\x38\x20\x4b\xe8\x7f\xbb\x7b\xe2\xa3\x93\x22\x65\x6e\xd6\x28\x56\x5f\xb7\x06\x66\x4b\x60\xb6\xb4\x7c\x96\x14\xb1\x82\x24\x68\x13\xe1\xa1\xf8\x2f\xf7\x85\xd7\x00\x8b\x3d\x2c\xa2\xb5\xd6\x1b\xa9\x4d\x20\x86\x78\x57\x50\x98\xa0\x88\x2a\x66\x1a\x78\x2f\x65\x9d\xa7\xbe\xf3\xe0\xdd\x43\x7f\xfc\xbe\x70\xff\xe7\xf3\x95\xcf\x4f\xf7\xd4\x16\xb3\xff\xa0\x29\x3e\x9c\x4e\xe3\xf6\x48\x12\xac\x92\x54\x7d\x76\x07\xb0\x3b\xdf\xa5\x5e\xe2\x46\x76\xb6\x54\x8b\x76\x52\xf0\x2a\xd8\x59\x2d\x17\x8d\x60\x67\x13\x14\x61\x02\x4d\x49\xab\xa5\xf2\xe1\x22\x72\x97\x91\x77\x00\xeb\x19\x9f\x2c\xba\xca\x94\x1d\xe7\x8b\x4b\x1c\x71\xcd\x2b\x2f\x87\xf2\xe1\x4c\xd5\x14\x7f\x35\x40\x76\x9f\x55\xe3\x4b\x1b\x2b\xb7\x9e\x45\x12\x6e\xbc\x0d\x94\x20\x48\x2b\xf7\x38\x70\xb6\xc4\x1f\x0e\x6e\x5f\xf1\x3b\x51\x10\x3c\xcb\x11\xa7\xfd\xaa\x73\xbf\xa6\xc7\x2f\x45\x9c\x29\xee\x6f\x41\x68\xa5\x6c\x52\x7a\xaa\xc0\xab\xe4\x2c\x88\x20\x1a\xa8\x27\x2e\x49\xc6\x52\x32\xff\x5c\xf0\xb7\x6f\xb5\xe1\x0b\x62\xf9\x3e\x23\xb9\x9f\x12\x2f\x83\xb9\x41\x24\x23\xfd\xaf\x2b\x11\x39\x22\x11\x99\x06\x2b\x1a\x35\x5f\x33\x02\xc3\xda\x7e\x14\xb7\x47\xe2\x71\x44\x48\x7c\x19\xb4\xfb\x35\x7f\x39\xac\x5f\x13\x8e\x5f\x56\xb3\xb5\x22\x57\x25\x93\x45\xfd\x31\xd9\x37\x10\x1f\xd6\x0c\x47\xb9\xed\x14\x39\xc5\x4a\x7c\x32\xa1\x06\xcd\xc8\x63\x88\xf1\x10\x99\xe8\x95\xdd\x0f\x19\xc4\x61\x5c\x5c\x68\x2d\xbc\x9b\x33\xfc\xf7\x20\xe6\x76\x77\x63\x5d\x4a\xce\xf0\xf6\x97\x60\x2f\x06\xc5\x32\xc8\x88\xd7\xc5\xe6\xfc\x7e\xdb\x23\x98\x78\x2a\xe5\x74\xaa\x03\xe4\x34\x52\x49\x9a\x79\x37\x66\x88\x47\x80\x4d\x98\x60\x5d\xae\xcf\x1a\x25\x52\x60\x3c\xb3\x24\xc3\x9f\xb7\x25\x7f\x5c\xdf\x3b\x26\x90\x74\xf2\xe0\x3e\xf6\x56\x89\xf9\x01\x21\x6d\x8b\x33\x6e\x32\x67\x8a\x65\x27\x51\x5b\x21\x24\x16\x82\x89\xbd\xa4\x2a\x9b\xe6\x09\x70\xe8\x42\x8d\xd7\x92\xd0\xa2\x8a\xf5\x1b\x79\xa1\x78\x98\xe0\x45\x45\xe5\xf9\x6a\x13\x08\x77\xa5\xd0\xaa\x50\x8b\xda\x7f\x1e\x3b\x40\xa8\xbe\x9f\x4a\x50\xa9\xe7\x93\x36\xa9\xd3\xcf\xba\xb1\x18\x0b\x56\xcc\xd8\x60\x25\x59\x1d\x8c\xf2\xa1\x62\x03\xee\xbc\x04\xb5\x68\x30\xef\x80\xe5\xbc\x6f\x42\xe1\xee\x02\x32\xdc\x92\xc2\x72\x43\xd0\xe5\x7a\xfd\x3e\x80\x40\x89\x50\xc7\x6a\x63\x6e\x8b\x15\x4d\x56\xa1\x90\x6c\xfc\x6b\xf1\x3f\xad\x41\x89\x4a\x9a\x5f\x54\xda\x81\x4b\x37\x70\x4f\xa4\x56\xcb\x0e\x52\x69\xf4\xc3\xfd\x2c\x95\x03\x2b\x95\x9b\x4e\x8b\x41\xe2\x3d\x2d\x0d\xc9\x26\x99\xf3\x6e\xa5\x03\x65\xec\x76\x2a\x89\xd9\x47\x44\x27\xf2\xfb\xdb\x44\xc5\x32\x64\xb8\x6c\x8c\x4d\xc0\xf6\x9a\xf3\x56\xab\x77\x0b\x9f\x00\x00\xac\x0b\x8c\x20\x26\xf5\x86\xa2\x18\xdc\x50\x03\x27\x6c\x20\x8d\x00\x54\xc6\x94\x44\xaa\x8f\x3e\xd7\xee\x3b\xd5\x61\xbe\xd3\xa6\x4a\x50\x88\x56\x4d\xda\xda\xb6\xe8\x84\x78\x72\xdf\x60\x55\x96\xb5\x34\x48\xfa\x4f\x4c\xf6\xba\xf9\x7b\x1c\x1b\x32\x65\x79\x5d\x8a\xf6\xcd\x80\xae\x2a\xb6\x7b\xa7\x15\x4b\xc8\x7b\x0d\x36\x68\xdd\xae\xd6\xb4\x6e\xf7\xc5\xac\x6e\x3e\x1b\xee\x88\x8c\x63\x06\x17\x7b\x7f\xab\x7e\x71\x6d\x6b\xc9\xba\xf9\xbd\xb6\xdb\xb6\x98\xf7\x34\x10\x96\x80\x16\xa6\x81\x4e\x51\xde\xdf\xac\xe2\xe9\x56\x69\x76\x17\x7f\x5f\xa8\xc9\x94\xde\x77\xf7\x8f\x13\x2c\x4f\xdf\xcb\x5d\x5a\x32\xcf\x4b\x22\xb0\x9b\xd2\x1f\x27\x6b\x10\xdb\x7b\x13\x54\x01\xf5\x7e\xd7\x36\x79\x23\x22\x2a\xf7\xc5\xa7\x4b\x72\x00\xd6\xbe\xe9\xec\x3e\x6f\x6e\x70\xfd\x14\x25\xd3\x15\x64\x0a\x14\x17\xf3\xa5\xaf\x95\xcd\x67\x9b\x5e\x36\xd4\xa6\x68\x86\xe1\x8e\x3e\xe0\x26\x06\x14\x82\x3b\x5e\xea\x0a\x68\x57\xe3\x8a\x5b\x36\x20\x33\x10\x21\x93\xec\x16\x51\xf1\x87\xf7\x0b\x2e\x26\x75\x33\x6a\x56\xcc\xcd\x5f\x8b\xe5\xfe\xfe\xd6\xc6\x48\xcd\x20\x03\xe0\xb7\x20\xf7\x45\x21\xb7\x9b\x6d\x24\xed\x39\x28\x9c\xcb\x0a\x55\x11\xeb\x25\x35\x1f\x36\x08\xec\x56\xd9\x04\x82\xad\x65\x5b\x8c\x7a\xea\x20\x48\x01\x31\x95\x80\x9e\x9d\x1d\x51\xe7\x5d\xb7\x45\xbd\xaf\x83\x62\x84\xfd\xda\x8f\x28\x90\x48\x6f\xb6\x19\x55\x8d\xfb\xfb\x5b\x85\x28\x50\xd1\xbb\xaa\x6d\x08\x0d\x2c\x3a\x34\x7e\x67\xf1\xb0\x6d\xf1\xb3\xdd\x75\x50\x5e\x1f\x42\xac\x1b\x75\x02\x7c\xa4\x9a\x1b\x1d\x7d\x5d\x86\xde\xc0\x35\x3f\xd1\x1b\x7d\xb8\x9b\xfb\x40\x4a\xbc\x53\x88\x2f\xf8\x74\xd7\xbc\x3f\x4b\xd2\xd9\xa2\x5a\xad\x89\x6e\xbd\x23\x1c\x56\x13\xc4\xbc\xfb\xcf\xd1\x40\x2a\x2f\x5e\xb8\xe4\xff\x73\xd5\x09\x0c\xd0\x7d\x88\x05\x4e\x96\xd0\x2c\x45\xb6\x67\x22\x74\x5f\x74\xb3\xea\xbd\x1b\x85\xb6\x11\x6e\x46\x52\x56\xce\x08\xdd\xc2\xfd\x97\x59\xd7\xa5\x13\x0c\x1b\x21\x04\x9e\x26\x0a\x3e\x55\xfb\xbd\x43\xd8\x50\x19\x45\xf4\x67\x6b\x49\x46\xbe\x17\xe4\x5b\x51\xfd\xa4\xa8\x83\xec\x03\x04\xc1\x65\x5c\xa0\x02\x54\xfb\xd9\x41\x2e\x9e\xe9\xbe\x0b\xfa\x78\x69\xc1\x4b\x84\x58\x0b\x23\x72\x3e\xdb\xaf\xbd\x7f\x55\x58\x3e\x5f\x72\xec\x22\x97\x11\x62\x3e\xca\x47\xdb\x17\x43\x98\x5d\x41\x1f\x83\xea\x2c\x9a\x6a\xee\xaf\x57\x78\x87\xbe\x0c\x81\xdd\x1d\x50\x50\xf8\xb8\xde\xd3\xb0\x14\xa1\x1a\x49\xfb\x60\x25\xf6\x61\xa3\x70\xcb\x3e\x48\x5c\x86\x2a\x4d\x6f\x10\xa6\xc0\xfb\x3e\x81\x77\xa6\x35\x25\xb5\xee\x8b\x8d\x99\x02\xb0\xde\x29\xe1\x47\x2d\x20\x9b\x58\xa7\x5b\x6f\x41\x63\x01\x26\x07\x30\xdd\xd0\x2b\x31\x37\x04\x67\x4d\xad\xcb\xd1\x5a\x4f\x36\xe7\xfb\x5b\xe9\xa0\x57\x47\x32\xdf\xaa\x77\x7c\x94\xe5\xab\x1e\x0d\x79\x01\x1b\xe5\x06\x39\xf0\xa9\x28\x0b\x84\xf2\x12\x61\x94\xa0\x27\xc6\x44\x5c\xfc\xf2\xbe\xba\x55\x40\xb6\xfd\xd6\xb1\x6b\x01\x21\x0e\x8c\xae\x45\x20\xc4\x31\x2d\x11\x79\xee\x6e\x2f\x94\x39\x2a\xeb\x28\x75\x52\xb4\x08\x6c\xc3\x3e\xa3\x68\x2f\xc9\x3a\x32\x9b\x10\xfc\xaa\x17\x50\x05\xf4\x45\xd9\xa7\x91\x51\xf6\x06\x83\xa4\x92\xb2\xdd\xbe\x78\xc3\xbf\xa9\xbc\xf8\x50\xf2\xca\xec\xff\x94\xf6\x1a\xd3\x7c\x90\x97\x4d\xa2\xfa\x55\x1f\x7d\xb9\xf6\x54\xdd\x14\xca\x39\x4d\x81\x9e\x5d\x9a\x3e\x64\x99\xcb\xf6\x29\x68\x91\xe2\xed\x01\xaf\x7d\xf0\x27\xfe\x42\x92\x11\x43\x81\x81\xec\xc1\x8d\xde\x43\x92\xb0\xf6\x75\xa9\xb8\x20\xae\xa7\x8a\x18\x61\x2a\x43\xfd\x73\x57\xf2\x88\x8e\x4e\xb6\x31\xa9\x05\x2a\x63\xfe\x83\xff\xad\xa0\xf7\x2a\x64\xe4\xeb\x3e\x17\x22\x7f\xd0\x77\x12\x76\x22\x02\x44\xcd\xba\x16\xbc\xca\x1b\xb0\xcf\x92\x15\x8c\x1d\x5d\xc0\xfb\x6a\x6d\xa4\x0e\x40\x52\x79\x7a\x1a\x88\x54\xb8\x27\x2b\xe7\xd3\x80\xeb\x86\x19\x35\x5f\x8f\xfa\xe0\xd9\xdc\xf6\x96\x9d\x35\xca\x49\x88\xd7\xaf\x51\xfc\x69\xcc\xfe\x0c\x10\xad\xee\x9a\x41\x51\xd9\x59\x46\xb9\xa3\x7e\x39\x0f\xfc\x40\x42\xec\x62\x08\x33\x42\xc7\x72\x66\x6f\x70\x09\x21\x0b\xa4\x06\x10\xa0\x84\xe4\x74\x8d\x7b\xc2\x2f\x9d\x2f\xc1\x7b\x9e\xaf\xee\xc8\xe1\xcc\x22\xa0\x00\xa9\xee\x43\x0d\x42\xf1\x14\x71\x25\x75\x7f\x92\x28\x06\xde\x88\xc6\x8d\xf4\xb8\x91\xaf\x04\xc6\xe7\x4b\x3a\x55\x5e\x99\xd5\x9f\x89\x96\xb2\x0f\xf6\x7a\xef\xa8\x66\x66\xb7\x4e\xd6\x50\x4b\x2c\xee\x7f\x5c\xe2\xe3\xc6\x28\x13\xe3\x52\xed\xbe\xf0\x08\xcc\x2d\x64\x06\xe7\x0e\xeb\xb4\xc8\x83\x23\x4a\x86\xd1\xec\xd3\x08\x70\x05\xf5\x5e\x4d\xce\x34\x3b\x4a\x80\xce\xeb\x90\xb3\xf6\xf5\x42\xe0\x15\x96\x4f\x2f\xe4\x87\xbc\x5e\x69\x82\x14\xa4\xde\x0b\x98\xba\x3e\xbd\xd0\xed\x47\x57\xe2\x31\xbf\xf7\x4a\xcd\x97\x8a\x56\xef\xd6\xf4\x8f\x3e\x12\x0f\xf9\xbd\x17\x82\xa7\x65\x12\x44\x9c\x2d\x7c\x45\x85\x68\xc2\x08\x31\x04\xef\xec\x85\x74\x3c\x60\xba\x2d\xee\x18\x92\x45\x43\x07\x08\x4f\x44\x10\xa8\x44\x9c\xfa\x70\x9b\x0d\x83\x00\xc0\x12\x94\x30\xe4\xd4\x2d\xb8\xcd\xa8\x1b\x08\xa1\x78\xfc\x8b\x1f\xa0\x91\x9a\x7d\x4d\xc4\x3c\xcd\x4c\x18\xa2\xbc\x96\xf3\x61\x46\x7a\x14\x41\xa0\x55\x7b\xa5\xbc\xfc\x21\x33\x84\x86\xb0\x06\x32\x73\x46\x31\x1f\x3c\x48\x61\x12\x01\xb3\xaf\x19\x24\x37\xdd\xca\xfd\x56\x01\xde\x24\xd0\xe7\x8b\x0e\xff\x92\x4d\x95\xf2\xb0\x21\x88\xc4\xa9\x06\xf1\xb4\xa9\xdb\xd2\x3b\x8a\x86\xc7\xb6\xf4\x96\x93\xd9\xb8\xfb\xef\x18\xdd\x2d\x69\x9e\xf7\x89\xaa\x25\xf3\x23\xa6\xb6\xad\x21\xf5\x35\x4b\xec\x21\x6a\xf5\xae\x59\xce\x5d\xfc\xab\x40\x7f\x52\x86\xa4\x69\x1d\xa1\x46\x37\xb6\xef\xfe\x69\x9d\x1b\xfa\x98\x9f\x6f\x68\x6e\x3f\x7e\xb6\xa1\x4c\xfb\x7c\x83\x95\xfa\xba\xc1\xcd\x34\xcd\xea\x2e\x8e\x95\x5b\x94\x62\xb8\x7f\x83\x66\x7d\x7f\xf3\x35\x11\xce\x83\x6f\x8f\xcd\x2d\x36\x17\x5f\x7b\x47\x1a\x3f\xdc\xda\xa4\x24\x35\x6c\x0d\x14\xfc\xf3\xd6\x3e\x7d\xba\xc7\x51\xa5\x6d\xbc\x20\x31\xe9\xc8\xa5\x4e\xb7\x9a\x3e\x6e\x2e\xe7\xe6\x06\xd7\xcf\x6d\xde\x9f\xec\x00\xfb\x63\x4c\xee\xd0\x5f\x77\xd0\x3a\xdd\x1c\x9a\x3e\xa8\x56\x9f\x5e\x6f\x77\x7f\xe5\xe2\x8f\x05\x47\xfb\xb1\xa9\x72\x8b\xfb\x47\xc3\x7e\xb0\xa5\x97\xf2\xf1\x74\xd7\xd9\x66\x6e\x3f\xd8\x12\x0f\xf1\xd9\xe9\x44\x2d\xff\x68\x93\x4d\xf9\xd1\x09\x87\x24\xc9\x65\xde\xdd\x5b\x3c\xdf\xb3\x1f\x8b\x3d\xfb\x88\x47\xcb\xa3\xbe\x9c\xf6\xc6\x67\xfb\x6c\x13\x9f\xed\x69\xcb\x77\xcf\xf6\xe9\x16\x3e\xdb\xa7\xa7\xe3\xb3\x7d\xbe\xc9\x7c\x8d\xec\xf9\xee\xf7\xdf\x47\xfc\x7e\xf5\xdb\xd8\x61\xa8\x46\x0f\xfe\x7e\x4b\xeb\xe5\x07\x5b\xaa\xb6\x1f\x6c\xb1\x3e\x6e\x3f\xd8\xa4\x96\x5f\xb7\xf8\xf8\xd7\xf6\x20\x10\xf7\xb9\x87\x49\xc4\xe9\xce\x70\x30\xbe\xe9\x4c\xfc\xf3\xc0\x76\x3d\x2b\x91\x99\x72\x9f\x7a\x9c\xbe\x86\x5c\xc5\xde\xd7\x2f\x2c\x4e\xe3\x8e\xe0\xe4\xa9\x6e\xf4\x96\x16\x85\x0e\x72\x31\x95\x9e\x54\xe2\xd4\x12\xea\xf8\x57\xe3\xc7\x19\x42\x5b\xa7\xca\x21\xeb\x00\x90\x83\xbd\xc0\x26\x6a\xa9\xca\x6d\x5d\x6c\x03\x5e\xba\xd9\x8e\xb2\x44\x5f\x9e\xa8\x2c\x4d\x2a\xdf\x06\x8a\x7a\xd4\x08\x48\x23\xa6\xc2\x8c\xd9\x22\xe8\x7c\x40\xac\x1a\x64\x34\x08\x70\x01\x6a\xe3\x3e\x14\x2c\x71\x3b\xa0\x46\x7c\x70\x0f\xbd\x22\x59\xc8\x18\x99\x45\x65\x33\xd0\x79\x16\xa4\x4b\x0c\xd2\x5d\xc0\xf6\xb2\xda\x66\x39\xd5\xb1\x53\xdd\x4b\x85\x80\x21\xba\x62\xa1\x2d\x06\x97\x0d\xff\xe6\xc4\x64\x7a\x49\x85\x68\xc7\x93\xa4\x95\xc8\x6c\xc2\x67\x10\xaa\xba\x21\xc8\xb7\x58\x39\x59\x68\xea\x97\xe8\x8a\x9a\x5f\x5d\xcf\x9f\x55\xad\x8f\xe6\xfe\x42\x39\x73\x4c\x9d\xa0\x48\xa6\x9c\xf1\xbe\x03\xed\x3a\x25\xdc\x3d\x8a\xff\x62\x8f\xf8\x76\xc4\xc6\xe3\x3c\xe0\x38\xcf\x12\xda\x6e\x15\x1c\x7e\x71\x7e\xff\x9d\xe7\x23\xf6\x8e\xa0\x98\x79\x11\x01\x4d\xf6\x37\xb1\x74\xfe\xa0\xc7\x63\x2f\x1e\xc7\x6b\xcb\x94\xab\x7a\x4b\x4c\x8a\xaf\x84\x2c\x0a\x46\x7a\x90\x87\x10\xf0\xd8\xbe\x05\xd5\xe0\xba\xc8\x30\xbd\x9d\x90\x7d\xe6\x4d\xe5\x4a\xbe\xfa\xee\xf7\x38\x4b\x89\xb0\x1e\x4e\x71\xed\xb8\x16\x93\x1d\x2c\x2e\x58\x6f\x85\xb2\x55\xb8\xce\x7d\x91\x26\x6b\xaf\xe5\x2e\xa8\xd8\xf2\x13\xe8\x79\xf8\xd3\xc1\xf5\x4c\xd8\xc6\xe1\xd7\x8d\x7e\xf5\x66\x5f\xd2\x8b\xf2\x53\xaa\xd1\x62\x39\x4d\xd4\x81\xb6\x99\x21\x22\x1e\x29\xea\x6a\x4c\xf1\x1f\x58\x6b\xb4\x94\xb3\x5e\xa1\x9f\x0a\x29\x64\xda\x47\x0d\xb0\x64\xe4\x71\x59\xcb\xec\xc3\x4e\xfb\x09\xe3\xec\xc1\xec\xe6\xf3\x68\x63\x89\x82\x68\x3b\xa1\x5e\x12\x1c\x67\xd4\xac\xd5\x50\x6c\xef\xb1\xaf\xb5\xf3\xf0\xe0\x33\x70\x1f\x83\xa9\xc1\x7a\x4d\x2c\xc7\xc2\x2a\xcc\x0f\xb7\x88\x85\x5a\x6b\x3e\xb4\xf9\x73\xd8\x4e\x29\x79\xcd\x23\x0a\x4b\xdd\xf7\x03\xdb\x58\x4d\x05\x21\xe9\x01\x6a\xc3\xa4\xe5\x50\x4d\x80\x93\x22\x2d\xc8\x2c\x75\x3e\x49\xc7\x28\x29\x10\x89\x3d\x14\xd1\xf4\x3d\x14\xcb\x51\x61\x12\x49\x6d\xf5\x76\x21\xe6\x11\xe1\x55\x12\x9c\x60\xce\xa9\x40\xd9\xc0\xed\x38\x27\x99\x42\xa7\xa0\x92\xdc\x2e\x59\x91\xc3\x0a\x8b\x50\xdb\x2e\xc1\xaf\xcf\xe8\x3f\x8c\xca\x40\x78\x83\x4b\x5d\xae\x12\x31\x46\x84\x11\x8d\x0e\xe4\x1b\x71\x67\xa1\x75\x29\x76\x3b\x05\x8d\x8b\x3d\xec\x59\x28\x52\x34\x39\xf3\xb7\x50\x0c\xde\xa1\xc7\xb2\xb4\x28\x1f\x3a\x98\x93\x27\x0e\x31\x53\x7e\x86\xc9\x5b\x62\x61\xcf\xef\x0f\x73\xff\x2c\x11\xa8\x2c\xd4\x00\xf7\x3c\x60\x25\xfd\xa0\x36\xf7\x7e\x22\x61\x73\x8f\xe2\xc3\x45\x79\xfd\x5c\xf6\x05\xae\x73\xe0\x92\xe3\x2a\xa3\x9c\xc0\x8f\xb3\xc8\xeb\x4a\xb5\xd0\x8c\xaf\xec\x15\x21\x6f\x77\x0a\xe0\x55\x06\xf0\x05\xf8\xe9\xd2\xf6\x3a\x13\xa0\x89\x3d\x70\xcc\x32\x14\x79\x88\xdd\xa7\x8c\x9c\x0c\xec\xd4\x41\x05\xc3\x10\x68\x70\x65\x77\xb8\xba\xad\xed\xde\xb7\x18\xe6\x90\x2f\x87\xe2\x6b\x90\xe3\x85\x94\x55\x5a\xbb\x78\xcc\xdd\x49\x24\xfa\x1b\x82\x52\xa8\xbb\x67\x2d\x3e\xab\x96\x59\xf6\xfc\xfd\xb6\x83\xc4\x3f\xac\xd7\x5f\x60\x1e\x47\x99\xf3\x53\x39\xff\xd3\xf6\x23\x3e\xf8\xeb\xfa\x5c\x93\xad\x2d\x7d\xd8\x78\x3c\x09\xcb\xa1\x78\xda\xf7\x7b\x55\x9c\x6b\x25\xa7\xfc\x67\x0a\xb2\x6f\x8f\x6a\xf8\xa7\x0a\xf9\xa7\xa3\x1e\x27\x8b\xf0\xd5\x9f\xba\xcc\x1f\xba\x0a\xd9\x27\xc6\xb8\x2f\x95\xf4\x1b\x88\xa2\xb4\xb4\x04\x21\xae\x10\x1d\xeb\x26\x78\x39\xdd\xb7\xb4\x90\x9b\x90\xb8\x59\x37\x23\x10\xab\xa5\x1d\x74\xc6\xfb\x31\x61\x94\x75\x6a\x7e\xa8\xf6\x2d\x6c\xc4\x05\x15\x75\xf1\x19\xef\x05\x59\xd3\xcf\x00\x19\xac\x60\x10\x61\xfc\x06\xfc\x04\xa8\x98\xa1\x25\x82\x34\x4b\x4f\x43\x2d\x8a\x8a\x7e\x07\xa2\x83\x54\xe6\x2c\x31\xc2\x89\x02\x09\x2c\x27\x3c\x3b\xe4\xcb\xbf\xd5\x83\xe5\xa2\x28\xa4\xfa\x16\xac\xf2\xab\xa8\xbb\xed\x2f\x4f\xf4\xd5\xe0\x78\x49\x34\xcb\x2b\x57\xeb\xf3\xe0\x18\xf9\x07\x83\xe3\x6c\xb2\x0d\x88\xe1\x45\x4a\xbb\xeb\xb4\xdf\x35\x52\x74\x1a\x8f\x82\xb0\x6c\x54\x80\x7e\xba\x6f\x3c\x14\x39\x49\xd0\x68\x33\x4e\xfe\x18\x28\xd8\x18\xdb\xf8\xff\xff\x8e\x8e\xff\x8e\x8e\x3f\x37\x3a\x5e\x8a\x11\xe4\xa5\x48\xfe\xb9\x18\x41\x34\xf5\x36\xb6\xa6\xe6\x8b\x54\xdd\x16\xcb\x39\xb5\xe6\xbe\xde\xc5\x15\xbc\x94\xcd\xca\x4c\xbd\xeb\xba\xb4\x39\xde\xdf\xaa\x8d\x34\x66\xdb\x34\x17\x22\x00\xb5\xe9\xb6\x28\x24\xb3\x46\x59\x8d\x01\x08\x71\x7f\xda\x70\xea\xc7\x09\xdb\x30\x3f\x74\x6d\xc3\x8f\xb8\x8e\xef\xa8\xed\x90\x8c\x6d\x56\x1a\xcf\x76\x9e\x1b\x42\x8f\x70\xfa\x75\x03\x55\xb7\xf7\x21\xea\x43\x21\xf1\x57\x24\xaa\x10\xb0\xba\x6f\xcb\x44\xa1\x5f\x3e\x25\xad\xf5\x2c\x94\x85\x28\x73\xd2\x7c\xe3\x2e\xb1\x47\x0b\xd8\x45\x40\x50\x2d\xf9\xe9\x70\x1d\x5c\x66\xf8\x74\x50\x25\x29\x7c\x71\x0d\x18\x1b\x60\x7a\x5f\xbd\x8b\x17\x84\xaf\xfc\xac\x58\x56\x06\x2a\x77\xe7\x7e\x4e\x01\x89\xf3\x83\xcf\x50\x48\x30\x80\xdb\x70\x82\xb9\x09\xd2\x8f\xc3\xa8\x00\x39\x2c\xa4\xbb\xe7\x63\xc9\xe6\xbc\xf2\xb2\xd7\xfc\x4f\xdc\xeb\xf6\x17\x4f\xe6\x8d\xe3\x6d\x33\x21\x8a\xc9\x9d\x37\x1c\xfa\x59\x53\xfe\x27\x6d\xbf\xfd\x78\x87\xf7\x37\xb5\x0e\xad\x8a\xdf\xff\xd4\x8a\xb3\xea\x0f\x4f\xca\x22\x85\x72\xc7\xea\xa5\xe2\x66\x2b\x00\x55\x58\xf0\x7a\x62\x48\x25\x63\x1c\x6c\x3e\xdd\xd5\x71\xd7\x49\x4b\xcf\x8d\x38\xad\xed\xfa\x5c\x3e\x7c\x81\x2d\xa8\x73\xe2\xa8\xa5\x8e\xdd\x58\x4a\x52\xf2\x69\x70\x77\xc6\x1f\x82\xee\xd3\xa4\xdc\xb8\x88\xfa\xad\x8e\x9f\xdc\xf0\x0f\x1f\xe8\x7f\xe9\x88\xf8\xab\x7d\x1d\x7b\xd1\x36\x10\x48\xb5\x7a\x13\x20\x09\x1d\x9f\xa7\xc1\xbf\x3e\xbe\x54\xd1\x87\x6d\xff\xd5\x9c\xf5\x9a\x41\xbf\x8a\x8c\x6b\x6f\x29\x6f\x13\x38\x6e\x9f\x41\x71\x4d\x4a\xb3\x94\xf7\xb7\x61\x9a\xf2\xc6\xbf\x32\x7f\x5e\x5a\xc1\x7e\xb8\x2e\x6a\x94\x25\x4b\xde\x29\x48\x5f\x20\x30\x9f\x13\xe1\x32\x63\x5f\x7a\x3e\x19\x60\x7c\x12\x44\x25\x14\x2b\xe4\xa0\x35\x98\xc8\x45\x2a\x33\x48\x62\x26\x2a\xc8\xa3\xf2\x71\x80\x71\x97\xb8\x98\xb6\x2b\x16\x86\x42\x82\xcb\xb4\x18\xb5\x12\xda\xb9\xe2\x52\xc5\xdc\xf7\x7d\xe8\x44\xf6\xf3\x93\xf5\x71\x94\xe7\x94\x7e\x00\xbb\x74\x83\xdc\x95\xd0\x27\x0e\x81\x2d\x82\x0f\xa3\x76\xbc\x1c\xf4\xf6\x03\x5f\x58\xc9\x71\x7c\x58\xa0\x3f\x51\xb0\x4e\x3a\x1c\xe4\x2a\xaf\x13\xf8\x5e\xab\xaf\x31\x00\x88\x44\xf5\xf9\xb9\x1b\xed\x01\x16\xbb\xe3\x60\x3b\x31\xa4\xf0\x7f\x15\x78\x95\x33\xd0\xa0\xbc\x93\xa8\x61\x1f\x7e\x9f\xac\x16\x43\xc5\xdc\x31\x93\x14\x3c\x93\x74\x3c\xa2\x7f\xa4\xeb\x81\x95\x0d\xd2\xd1\x1e\x72\xfe\xda\xdc\x03\xd6\x34\x53\x49\x48\x43\x83\xb4\x81\x29\x45\xd4\x4e\x74\x54\x2b\xe6\x03\x65\x02\x4b\x9b\xeb\x32\x40\xc5\xac\x41\xb9\x53\x52\x9b\x87\xef\x25\xd3\xcd\xcb\x26\xc1\xc2\x3e\xdc\x90\xa1\xab\x6c\x6c\x04\x70\xd2\x3c\x28\xc2\x90\x39\xeb\x05\x0b\x79\x4e\xaa\x79\x55\x9f\xa6\x54\x81\x72\x50\x30\xa2\x22\xc4\x9c\x08\x48\xf3\x4b\x95\xb8\x24\xca\xd9\x6b\x4f\x3e\xcb\xcc\xb9\x4b\x4f\x4d\x89\x8c\x13\x2b\x84\xe6\x88\x94\xdd\x34\x59\x4f\xbd\x25\xeb\x04\x36\x83\x09\x4a\x8e\xc7\x87\xc9\x8d\x1f\x4f\xd1\x38\x6a\xfd\x17\xbd\x22\xb4\x25\x42\xb4\x62\x65\xc7\xbc\x56\x14\x57\x5e\xe6\x3c\x65\xc3\xd1\x38\xb3\xed\x3d\xa4\x77\x89\x40\xf0\x27\xda\x20\xba\xa7\x5a\xf7\xc6\x7a\x62\x86\x34\xc0\xb0\x76\xe2\x2f\x10\xb5\x41\x71\x1d\x50\x19\x28\x82\xfe\x92\x59\xa4\xe6\x17\x1c\xbc\xbc\x90\x05\x3f\x31\x4d\xa8\x65\x49\x35\x67\x92\x6b\x65\x3b\x85\xfa\xc8\xeb\x36\x2f\x72\x0c\x09\x7e\x31\x04\xd8\x66\x44\x18\xc9\x3c\xee\x86\x0b\x39\x03\x45\x11\xbd\x23\x29\x18\xba\x03\x34\xb8\x18\xfc\x66\x34\x4c\xd8\x11\x61\xa9\x75\x81\xd4\x1c\x07\x71\xb0\xfb\x7b\x9b\x1d\x10\x96\xd6\xc2\x52\xf8\xce\x60\x4d\x30\x18\x07\xf6\x50\xa8\x31\x5d\x9b\x1b\xa5\x7f\x98\x2b\xe1\xf6\xfb\xc8\x12\x50\x85\x80\x82\x15\xed\x9b\x96\x04\xb2\x6e\x35\xd0\x97\x2d\xd0\x89\x92\x4c\xc9\x8c\x2f\x1c\x02\xef\xb3\x1d\xf2\x04\x98\xd0\x31\x97\x30\xe8\x6e\xde\xce\x9d\xa1\xfe\x19\xbc\xe4\xd6\xbe\xd5\x15\x04\x1c\xf2\x3d\xd1\x02\xe3\x68\x65\x9e\x22\xb9\x25\x55\x9f\x0a\x4a\x42\x85\x5f\xb2\x71\x14\x4b\x52\x57\xad\xf6\x81\x71\x01\x58\xb8\x5c\x6f\x10\x56\xf5\x31\x10\x6b\x6a\xc3\xdd\x7d\xea\x6a\x3c\x87\x77\x5e\xfd\xa8\x3e\x37\xd4\xec\x48\x57\x00\xe7\x9a\x21\x7d\x6d\x6d\x27\x6e\xbb\x25\x85\x27\x17\x13\x1f\xea\xf8\x80\x87\x2e\x25\xd8\x5f\x7e\x40\x3f\x12\x94\x27\x41\xe9\x51\x49\x69\x32\xa8\x43\x93\x9a\xa1\x80\x5c\x7b\xdf\x21\xea\x81\x02\x9c\x24\xf6\x25\xeb\xc9\xed\xa4\xfb\x78\xc8\xfb\x9c\x10\xee\x67\xfa\x8f\xe3\x3b\x66\x92\x7f\x27\x31\xc9\x57\xc3\xfc\xb5\x64\xe5\x97\x07\x21\x5d\x1e\xf4\xea\x51\x0d\x1b\xd0\xe0\x60\xc9\x29\x3e\x17\x1d\x64\x68\x2f\xfe\xa4\x21\x84\x10\x80\x7f\xcc\xc4\xfc\xae\xa4\xfb\xf3\x43\xc6\x29\x2a\x8b\xd3\xec\xc0\x30\x9b\x25\xe0\x54\xa7\x84\x5c\x02\xd4\x65\x39\x9c\xb0\xcc\x79\xa7\xaa\x89\xa2\x83\xc1\xd6\x07\x06\xda\x90\x9e\x64\x60\xbc\x8c\x90\x81\x5e\xb4\x21\x84\x1b\x9c\x9d\xa7\xa2\x5c\xe4\x57\xc8\x47\x50\x42\x0d\xe4\xdb\x99\x51\x63\x59\xf4\xc2\xa9\x49\x6f\xbb\x91\x20\xb0\x87\x67\xdd\x31\xb7\x1e\x01\x01\x47\x05\x47\x8e\x9c\xa1\x12\x8f\x2e\x39\xbe\x49\x8e\x8d\x5a\xb1\xbf\x99\x1f\xfd\xff\xb3\xf7\x6e\x3b\x92\x2b\xcb\x92\xd8\x7b\x7e\x45\xfc\x40\x34\xc2\x3d\xee\xd0\xbb\xde\xfa\x1b\x84\x91\x74\x06\x29\x80\x18\x80\x10\x27\x1f\xea\xeb\x05\x37\x73\x32\x59\xcd\xaa\xca\xea\xb5\x7b\xed\xb3\xcf\x68\x03\x6b\x75\xb1\x8a\xf7\x60\x5c\xfc\x66\x66\xe0\xa0\xd4\xbe\x27\x11\xcc\xac\x18\xce\xa1\xac\xdd\xe5\x9f\xf1\x50\xa7\x67\xc5\x1c\x98\x28\x84\x47\x26\x42\xbe\x77\x60\xfa\x02\x34\x8b\x36\x62\x9b\xfd\x07\xe7\xd5\x86\x84\xad\xc2\x28\xea\x05\xa9\xf1\xbe\xfe\xdb\xc0\x21\xdb\xae\x38\x76\x8a\x40\xf4\x43\x87\x6d\xcc\x06\x7e\xf0\xdb\x67\x23\xb5\x15\xec\xff\x6c\xb7\xa2\xee\xfe\x32\x7b\x3d\xe0\x7c\x7f\x3c\xb3\x3d\x78\x39\x50\xea\x5f\x42\x40\x77\xdb\x09\xdc\xca\x27\xb1\xa0\xa9\xae\xb0\x92\x38\x00\x7c\xad\xa3\x50\x8f\x2f\x32\xad\x3e\x7f\xe1\x76\xab\x87\xce\xd4\x69\xf3\x79\xc4\x6d\x3b\x9f\x7a\xba\xe6\xab\x51\x74\xad\x83\xb9\xa0\x37\xde\x31\xad\x8e\x04\x6a\xa4\x9c\x20\xba\x1b\xdb\xde\x5d\xb1\x5a\x82\x00\x16\x60\xed\xb2\x44\x06\x55\x80\xad\x18\xd4\xf2\xc5\x84\x38\xc0\x06\x2e\xc3\x0e\x28\xa1\x25\x05\x7d\x0b\x91\x41\xe9\x9e\xdb\x74\xd1\x67\x2c\xa7\xe8\x7d\xea\xf6\xa3\x4d\xe2\x3a\x84\x75\xf5\xad\xf5\xb5\x51\x22\x9c\x7d\x1c\x69\x9c\x4c\x4c\x11\xf4\xb6\x37\x5b\x0f\x6c\xbe\x6c\xa1\x8c\xba\xc0\x1c\x61\x44\xc3\xa6\x25\x28\x24\x56\x27\x45\x9f\x4e\xba\x56\xea\x2e\x1b\x93\xd2\x3d\xe6\x66\x93\x96\x0d\x27\x94\x16\x0e\x04\x4a\x90\x2a\x01\x21\x07\xd0\xd8\xc4\x60\x56\x5a\x3b\x65\xaf\x69\x2e\x19\x20\x90\x16\xda\x68\x6b\x6c\xa8\xf2\x22\x9d\xf4\x41\xfc\x8a\x8d\x5d\x34\xdc\x2c\x0e\xbc\x61\x14\x04\x05\x5b\xb9\xc7\xa2\xd9\x6b\x51\xab\x3f\x55\x4e\xc0\x75\x81\x0f\xb8\x87\x5c\xca\x96\xab\x04\xd1\xb2\x02\x50\x2b\x4c\x75\x51\xe1\x1d\xc5\xad\x63\x9b\x4f\xae\xc4\x0e\x88\x94\xd9\x70\xb9\x99\x41\xd7\x7c\x2f\x76\xda\xf1\x75\x6c\xbc\x04\x8a\x18\x58\x38\x99\x61\x90\x28\x7c\x00\x6b\xb0\xf2\xf5\xac\xfc\xf8\x8f\xff\xf1\x3f\xff\xdf\x5f\x3b\x94\x5e\x58\x90\x4f\x34\x15\xe0\x1f\x74\x2c\x93\x97\x71\xb1\xe2\x99\xc4\x89\xd9\x99\x37\x47\x07\x8e\xce\x4c\x47\x2d\x1f\xa0\x17\x3f\x93\xcc\x52\x2d\x0f\x70\x3b\x7d\xb8\xf7\x43\xc4\xa4\x6a\x71\x3a\xa8\x6f\x68\x64\xd9\xf5\xb1\xa4\xa1\xac\x14\x85\x10\xb2\x13\xfc\xca\x68\x41\xd5\x6c\x39\xe0\x79\xa6\xde\x56\x28\x0a\x17\x16\xca\x69\x99\x48\xa3\xc9\x18\x1b\x33\x9c\x63\xac\xd2\x91\x74\xcb\x60\x54\x28\x9b\x66\xd7\x32\x01\x20\x26\x21\xae\x38\xf6\xe6\x32\xab\xee\x1d\x37\xd7\x3b\xe2\xa8\x33\x31\xd6\xd9\xbc\x7b\x67\xf7\xbd\xa7\xcf\x7a\x4f\xed\xf5\x7d\xe6\xa9\x2a\x97\xdc\xb9\xea\x73\x29\xee\x0a\xd0\xef\x87\x16\x56\x91\x4f\xf0\xba\x1f\x7f\x9a\xa6\x4b\xcc\x03\x64\x4d\x79\x05\xc3\x9a\xc0\x96\x69\xa8\xa6\x5d\x77\x25\x58\x67\xe7\x70\x79\x40\x98\xc6\xa3\xd8\x07\x29\x54\x00\x77\xc1\xc4\x58\x7c\x99\xcf\x07\x79\xb3\x20\x94\x90\x79\x16\x4e\xc2\xb5\x78\xa9\xd3\xe6\xbe\x7b\x3f\xfe\x79\x8d\xdb\x6a\x26\x9d\x8d\x1c\xb8\xa9\x6d\xb1\xe7\xcd\x43\xef\x51\x21\xac\xf9\xba\x4f\x15\xe8\x3e\x9a\xe9\xfd\x8e\x10\xec\x0f\x7d\xca\xed\xd3\x2e\xf3\xea\x23\x5f\xb2\xb2\x7a\x29\x11\x3e\x0d\xec\x91\x21\xbc\x92\x56\x4c\xaa\x5d\x83\x2b\x95\xd1\x0b\x22\x30\x3f\x27\x4f\x13\xbf\x1c\xf9\x92\xf5\x3e\xdb\x6f\x0c\x7c\x68\xe5\xfd\x4e\xdf\x9a\xed\xdb\xc2\x78\xd0\x66\xd6\x35\xaa\x74\x32\xc8\x30\xe1\x3f\x48\xbc\xc5\xd7\xc0\x5b\x38\x69\x10\x5e\x16\xef\xea\x72\x6d\x68\x03\x73\x1d\x6b\x00\x19\xb5\x0e\x10\xc7\x44\xb0\x6c\xe4\x3d\x46\xa2\xcd\x57\xc0\xbb\xad\x89\x80\xca\x02\x94\x01\x7c\xbe\xd9\x57\x02\xb7\xbf\xcb\x06\x6e\x85\x56\xf1\x13\x65\xea\x29\x48\x97\x75\xd8\xba\x93\xbb\x2d\xab\x0d\xd4\x3b\xce\x50\xc2\x45\x27\xef\x41\x16\x28\x88\x21\xbf\x83\x27\x89\xda\x33\xfb\x1f\xb2\x38\xdf\xee\x81\xb7\x7f\x42\x17\xbc\xe4\x3e\xf5\x28\xda\xa5\x08\x45\x4d\xd7\x29\x7a\x7c\x3c\xf5\xd8\xdf\xbf\xdf\x3d\x24\x97\x25\x6a\x45\x71\x4c\xdd\xa7\x9e\xf1\x6e\xea\xf9\x67\x77\xe2\xdb\x9f\xe9\xc5\xd0\x65\xc5\xca\x95\x4e\x2b\xd7\x31\xd3\xd1\x79\x73\x59\x5a\x50\x9b\x36\x9b\xdc\xd0\x83\xcc\x03\x05\x31\x33\xaa\x94\xcc\x71\x1c\xde\xc4\xf0\x62\xf2\xa2\xd5\xbc\x81\x72\x77\xbd\xa2\xeb\x43\xfd\xab\x76\xb4\x4b\x1a\x51\x2f\x65\x7e\xbf\x5a\xc5\xff\xee\x7b\x7f\x64\x06\xfd\x75\x02\x55\xa0\xe4\x9b\xad\xa7\x4b\xac\x1a\x2a\xca\xc4\x05\x65\x4e\x6b\x9c\x0e\xd9\xd5\xdd\x05\xd1\x4c\x29\x8c\x62\xae\xf8\x1e\x60\x3f\xa4\x7d\xb7\xdd\x53\x45\x5d\x38\xa2\x4b\x88\xbb\x20\x43\x90\xbf\x65\x25\xde\x76\x5b\x64\x78\x51\xd1\xbb\xbc\xb7\x99\x70\xdf\x6e\x62\x41\x61\x3c\x3c\xa8\xbe\x0c\x84\x5b\x26\x34\x37\x94\x61\x68\x3b\x0c\xca\xbe\x70\x9d\x56\xea\x19\x7b\x35\x9d\x1c\x5e\x3f\x5e\x87\x59\xa0\xb9\x54\x24\x9a\xd6\xbd\x7b\xe4\xca\xa2\xc1\xc3\x18\xf9\xc6\x80\x1c\x59\x3f\x1e\x90\xb7\xff\x4c\xe3\xe3\x92\x4b\xd6\x4b\x75\xe6\x7b\xe5\xb0\x14\x24\xa5\xce\xa0\x2e\x24\xf3\x59\x38\x01\x8a\x17\x80\x44\xcc\x32\xa7\xb5\x1e\xa1\x23\xf3\xcf\x73\x2e\x90\x90\xfa\x5b\x9c\x92\xdb\x5f\xf0\x4a\xcc\x30\x50\xb3\x26\x30\x06\x33\xb2\xa0\x99\x3a\x72\x10\xcf\xb4\x7d\x2a\x21\x9b\x7d\x30\xcb\x2a\x5d\x50\xc5\x67\xbf\xcf\xb2\x82\xaa\xc1\x3c\x16\x17\xd6\x43\x0d\x38\x2f\x15\x71\xad\xb7\x9f\x63\x92\x2b\x09\x19\xdb\x0c\xce\x8b\x90\x05\x36\x36\x36\x1c\x3f\x48\x35\x11\xdb\xb2\x9d\xfb\xc6\x41\xc6\xbc\xc7\x4b\x65\x00\xb5\x08\xd8\x20\xc0\x93\xb5\x84\x3c\x05\x1a\x52\xb0\x00\xf0\x2b\x3d\x67\x40\x12\xf7\x13\xce\x31\xf0\xdf\xec\x9b\xf4\x52\x45\x87\xb7\x6a\x46\x2d\x23\x14\x17\xc1\x02\x60\xd3\x3a\x64\x90\x2b\x02\x97\xec\x4b\x55\xd4\x01\x6c\xac\xa3\xf8\x4b\x96\xfc\x21\x9c\x00\xfd\xc1\xda\x01\x97\x64\x06\xd0\x36\xfc\xc5\x19\xf5\xdd\xff\xb2\x22\x82\x81\x2c\x10\xce\x79\x35\xb4\x2e\x29\x4f\xbd\x56\x5b\x4e\x3d\x1c\xf6\x9d\x82\xe4\x9f\xb1\xd6\xf5\x86\x40\xb1\xa7\x86\x54\xca\x46\xc4\x43\xe9\x2b\x25\xde\x00\x13\x85\xa0\x83\xa8\x35\x1c\xf8\x0b\xda\xea\xaa\x9a\xd3\x17\xc3\x30\xd2\x16\x95\x35\xc2\x88\x47\x49\x0f\x8d\x8b\x26\xb5\x3f\xc0\x0a\x46\xba\x50\x21\x85\xd5\x74\x12\x9f\xa0\x39\xdd\x6c\x5a\xce\x35\xf4\x11\xb4\x2a\x9d\x76\x14\x50\x6b\x19\x10\x68\x7d\xda\x3f\x1e\x92\xdd\x79\xd1\xbf\x65\x03\xfd\x33\x1a\xd2\xe6\xff\x0e\x62\x35\x1b\xa2\x2b\xda\x6d\x86\xcc\x22\x82\xf2\xe9\x33\xde\x4e\xeb\x02\x0c\x6c\xd2\xda\xa2\xa2\x08\x88\x0c\x20\x45\x20\x75\xda\x77\xda\x3d\xd6\xb8\xcf\x1d\xa9\x58\x50\x10\x81\xd2\xf6\x1a\xec\x28\x3b\x08\x20\x69\xe0\xe7\x74\xec\xb4\xbc\xc0\x16\x0a\x61\x73\x9b\x76\xc0\xfc\xe6\x1a\xa9\xdf\x92\x59\xfb\x6c\x9f\xd5\xbe\x44\x26\x61\x1b\x90\xb5\xcd\x25\xdd\x84\xc9\x45\x7e\xbd\xbc\x79\xd5\x78\xcf\xdf\x18\xfa\xf6\x72\x83\xf5\x14\xb7\xaf\x47\x2a\x3c\xba\x41\xdd\x63\x7b\xce\x68\x0f\x6a\xcf\x89\x2c\x53\xb0\x71\x47\x7b\x4c\x76\xee\x2e\x3e\x6a\xcc\x60\xfb\xc0\xc3\x82\x9d\x42\x53\xd8\x89\xf4\x67\xf6\xf8\x4f\xec\x2f\xb8\x76\xaa\x5c\x52\x9b\xfa\x25\xeb\x31\xca\x0e\xff\x49\x76\xe9\x97\x63\x15\x35\x09\x64\x61\x62\xab\x27\x1b\xad\x9e\x77\xe9\x2b\x08\x3a\x28\x30\x95\x66\x98\x3e\x44\xc1\x90\xc0\x39\x35\x7f\xdf\x82\xbd\xfd\x53\x63\x00\x80\xb9\xf7\x23\xfd\xeb\xaa\x0a\xa3\x07\xa7\x63\x46\xb0\x37\x27\x88\xa9\x82\x36\x06\x88\x80\xac\x2c\x90\x20\x57\x60\xf1\x70\x6b\x2e\xa1\x20\x7d\x9e\x56\x29\x0d\x04\xfa\x9a\xc2\xec\xab\x42\xc7\xe7\xa5\x11\x77\x1e\xad\xb6\xe8\x62\x2d\xf8\x6b\x8b\xee\x79\x5c\x7e\x15\x66\x5c\x85\x61\x85\x77\xab\x72\x3f\x56\xe5\xed\xb4\x1c\xcb\xef\x2d\xc7\xbe\x76\xbe\x74\x0d\x6f\x5f\x2f\x9e\xfd\xcb\xc5\x73\x3b\x2f\x9a\xf2\x3b\x8b\xe6\x25\xf9\xa8\xf3\x6f\x8b\x78\x92\x6a\x46\xca\xc2\x80\x4f\x49\x2b\xdd\x1e\x3f\xdf\x7e\xe8\x02\x62\xdd\xd2\xe0\x12\x4d\xa7\xdd\xc5\xb5\x51\xdf\x0d\xce\x83\x05\x03\xaa\xcf\xbf\x21\x72\x7a\xfb\x13\xa1\xd3\x5f\x23\xa7\x7d\x04\xf0\x31\x58\x73\x82\xc8\x0d\xe9\x66\x8c\xc1\x19\x54\x97\xd2\x42\x69\xeb\xb4\x51\xa9\x61\xc2\x5d\x9a\x8b\x80\x36\xa4\x2b\x08\x7a\x54\xf2\xdf\x1c\x77\xfd\x67\x04\x23\x2e\x29\x3a\xbd\xd4\xd1\x9e\x02\xaf\xad\xa4\x30\xa6\xae\x8a\x69\xa9\x84\x73\x1c\x60\x3b\x87\x08\x0e\x9a\x75\x4f\x2e\x58\x6f\xf1\x74\x43\xf4\x04\x04\x21\x58\xb0\x75\x3d\x43\xb1\xc5\x3d\x67\x11\xf7\x2c\x06\xab\x5c\x00\xb2\xa5\x47\xb1\xed\x3e\xc6\xe1\x76\xd8\x5c\xf9\x19\x67\xe6\xf5\x43\x48\x4b\x0f\x69\xe6\xd4\x5a\x27\x56\x8a\x58\x4e\x92\xb9\x4d\x24\xcb\x26\xba\x3b\x7b\x3b\xfa\xbb\xea\xcd\xfa\x44\x5e\x34\x29\x48\x9c\x3e\x28\x99\xb4\x5d\xd1\xf6\xfd\xe6\xe8\x99\x1a\xa0\x94\xd6\xea\x27\xd4\x99\x9f\xfa\xf7\x2d\x61\xd9\x62\xaf\x42\x35\xc9\xdf\x10\xd0\xbf\xfd\xe5\x8e\xa5\x17\x30\xab\x5e\x94\xef\xcf\xd6\xc4\x4c\x12\x9a\xca\x0e\xe1\x78\x0f\x31\x58\x58\x6f\xa4\xe6\x10\x1d\x51\x19\x2f\x30\xe0\x96\xa4\x25\x96\xca\x1a\x22\x34\x3f\x42\x1d\x00\x08\xe2\xe7\x82\x95\x66\x54\xf0\x24\xfe\x25\x07\x99\x31\x25\x90\xd7\x75\xef\xf1\x1e\x5b\xda\xdc\x11\x60\x70\x69\x45\xbf\x47\x09\x53\x83\x1c\x9d\x8a\x19\xfa\x0d\xd8\xe0\x4c\x5e\x73\x41\x75\x47\x50\xce\x6e\xa0\x7f\x1b\xba\x69\x99\xce\x6a\x01\x7a\x9b\x00\x26\x21\xeb\xf7\x9b\x02\xd1\x31\x1a\xf5\x62\xd1\xf3\xef\x92\xf5\xc1\xd7\x78\xd7\xbf\xdb\x47\x41\x06\x7b\x01\x9d\x65\x89\xde\x0a\x9f\x35\x12\x5b\xd0\xe3\x44\x2c\xdb\xd8\xdb\x99\xfd\xec\x8f\x75\xb3\xdb\x1f\x9a\xbf\xf4\x9a\x1d\xbc\x8a\xf7\xff\xc5\x8c\x70\x93\x4f\xf8\x79\x3f\xec\x24\x76\xf4\x77\x62\x8e\xb6\x14\x7e\x6b\xc5\xda\xce\xcb\xe1\xb1\x48\x1e\xeb\xe6\x69\x35\x3d\xc5\x31\xfe\x95\xe2\x6a\x7a\x4d\xea\x5d\x15\xf9\x4f\xdf\xc6\x7c\xc0\x0a\x4e\xb0\x93\x34\xd4\x9f\x7a\xd6\xcf\x72\xd6\x1e\x7f\xe1\x7d\xff\x93\x32\xbc\xb7\xbf\xf6\xd5\x5f\xb4\xfe\x35\x9f\xf5\x59\xf1\xcd\xd7\xd7\xb9\xa6\x2b\xfe\xfb\x5f\xba\xce\x25\xca\x9a\xd3\xd3\xaa\xad\x42\xab\x16\x35\x7d\x10\xd7\xde\x45\x64\x6c\x95\x6b\xed\x22\xf0\x92\x28\xf0\x92\xa7\x3c\xea\xac\x77\x99\x73\xc9\x60\xf0\xba\x47\xd5\xf9\x90\xe2\xd2\x23\x4a\xf1\x4b\x72\x62\xe8\x58\x44\x35\xc8\x03\xa4\xf9\x2d\x63\x0e\xec\x23\x98\x99\x41\xe9\x16\xf5\xea\xf3\xe4\x8c\xf6\x51\xb5\x3d\xa2\x74\xb9\x47\x4d\xe9\x11\xed\x06\xd8\xa8\xa0\xef\xcb\x75\x2f\x43\x6c\xe9\x29\xbb\xf3\xf0\x27\x7e\x0a\xbf\x24\x0a\xbf\xb4\x57\xb0\x26\xbd\xc4\xcb\xf2\x57\x05\x2e\x29\xcc\x0c\xd8\xb6\x23\xe8\x5d\xf1\xd3\x51\xfc\xac\x1b\x44\x70\x31\x6f\x36\xa4\xfa\xd8\x60\xc2\x30\x86\x9f\x02\x16\xd5\x46\x0a\x43\xd4\x06\x67\x17\xe4\xd0\xd1\x77\xe2\x63\xac\xc7\xd0\xa3\x44\x3e\xb8\x43\x58\x16\xe1\x13\x4e\x6d\x0c\x44\x59\xd7\x9f\xce\xb6\xea\x84\xd6\x08\xa5\xe8\x06\x00\xc2\xa0\x99\x95\x27\x25\x3c\x44\x28\x7b\x8d\x8e\x3e\xa1\x73\x8a\x08\x85\x6c\xa8\xa2\xb3\x9f\xe6\xd4\x93\x3b\xd0\x8c\xa7\x7e\x88\xe8\x0e\x33\x4a\x16\xcc\xc9\x66\xc3\x41\x6d\x17\xb0\xef\x4e\x85\x07\xc4\x18\xa6\x52\x7e\x44\x21\x80\x0d\x08\xbb\x62\x2a\xae\x66\xbf\x65\x84\x0c\x5a\xa5\x3a\x4b\xb3\xf6\x1b\x39\x80\x25\xad\x6d\x92\x35\xf4\xbc\x36\xf3\x89\xe7\x0e\x69\x27\x17\x15\x31\xf8\xe0\x88\x42\x92\xdc\x3c\x3c\x16\x9d\x75\x2f\x06\x65\x63\x14\x2a\xd2\xed\xe5\x98\xd4\x32\x50\xeb\x1d\x60\x36\x6c\x63\xab\x2d\xcc\x0a\xea\x6c\xa6\x62\x6c\x51\x10\x28\x0f\xce\xc9\x35\x02\x00\x00\xa8\xda\x29\x43\x3c\x0a\x7a\x81\xd9\xa8\x43\x94\x08\xe9\xc7\x73\x51\xa7\x5d\x32\x75\x78\x9c\x90\xa5\x04\x71\x8a\xf0\x4d\x3b\xd3\xf7\x7d\x9f\x53\x1c\xea\xe0\xc5\x11\x08\x6a\x86\xd8\xf3\x46\x3c\x7d\x5d\x23\x05\x4b\x7a\xc8\x6b\xb4\x61\xe9\xc5\x85\xa1\x36\xe8\x2a\x4d\xae\x94\x34\x0f\x40\xe7\x45\xf5\xef\x57\x3d\xfb\x12\x5d\xca\x47\x19\xcf\x1c\x76\x75\x25\xe6\x82\xbc\x11\xa5\x6c\x83\x5c\x34\x79\x85\xba\x0c\x52\x2d\x98\x05\x50\x4f\x00\xa1\x14\x32\xdd\x4e\xeb\x31\x47\x59\x23\xec\x70\x86\xed\x48\x44\x33\x53\x68\xe6\xdf\x0d\x7e\x9e\x9e\x9c\x85\xac\x0c\x5a\x42\x4e\x65\x87\x72\xf9\x59\x1e\x63\xcd\x61\x4a\x00\x57\xde\x58\xb5\x98\xfb\x07\x26\xda\x15\xe5\xea\xd6\x5c\x3f\x08\x3c\x46\x84\x62\x1e\x75\x0f\x1c\x6c\x98\x32\xba\xcb\x09\xa7\xc0\x7a\x52\xcc\x64\xfd\xd0\xd7\x27\x1f\x45\x75\x29\x35\xd2\x54\xb6\x5d\x1a\x1a\x41\xab\xd5\xbe\x66\xcf\xe8\x37\x90\xaf\xa9\x8d\x42\xd7\xa8\x98\x33\x0f\x84\xfa\x33\xf6\x2f\xa5\x8e\x6a\x71\x79\x71\x0d\x14\x02\xed\x03\x08\x0e\x81\x08\x90\x42\x55\xa5\xa6\x4d\xa1\x80\x22\xb9\x6c\xd6\x61\xf0\xdb\x56\x7d\x3f\x84\x9b\x7d\xeb\xb9\x37\x3e\x4f\x89\xc7\x65\x7c\x2b\x62\x93\xa2\x2a\x38\x00\xbd\xd0\xcf\xab\x00\x22\xe7\x5d\x2b\xc2\x63\xa8\xb9\x8d\x85\xe9\x8c\x9c\x6f\x8b\x16\x0d\xbd\x63\x36\x82\xe2\x4d\xf6\x11\xc4\xc7\x97\x22\x65\x15\x94\xbb\x2a\x44\x3c\x6c\xe6\x57\xe7\xd9\x6e\xb2\x09\x78\xd0\x30\x42\xb1\x1c\x30\xac\x7e\xda\x3c\x1d\x10\x4f\xe7\xc5\xe3\x6a\x6b\x94\xc9\x50\x51\xab\xc1\xec\xe3\x02\xdb\x3e\x97\xc5\x96\x83\x92\x60\x28\x8f\x20\xa0\x2e\xb6\x39\x76\x90\x24\x23\xdb\x12\xc5\x9b\xd8\x3d\x78\x0b\xde\xc1\x6e\xc0\xeb\xb7\x17\x8c\xaa\x55\x2f\x71\x9e\x7c\x2d\x7a\x7a\x57\x08\x00\xac\x82\xd9\x49\x8e\x42\xb3\x2d\x02\xc0\x1c\x1b\xf6\xc9\xce\x36\x5b\x10\x44\xcd\x0b\xc7\xbc\x93\xd5\x2b\x7f\x44\xfb\x09\x4c\xd9\xd8\xfc\x87\xff\x95\xc7\xe0\x04\xde\xc3\x8c\xa5\x2f\x6e\xc2\xb0\xde\x3f\x74\x13\x3c\xab\x4a\xbb\xfd\xa3\x17\xea\x13\x02\x8e\x28\xd0\x06\xa6\x42\x51\x77\x6d\x1b\xbe\x77\x2f\xef\xfe\x78\x2f\xc5\x44\x3e\xd8\xfd\xe2\xab\x5e\x22\x2a\xf9\x2b\x8d\xec\x9e\x0a\xd4\x87\xc1\xa6\x93\x8e\x6c\x2a\x57\x48\xfc\x08\xf8\xd3\x76\xde\x3e\x1f\xb4\xa7\x99\x1d\xdd\xc6\x4c\x74\x97\xe7\xe9\xfb\x6f\xe7\x03\x9d\x35\x00\xc5\xd6\xd5\x27\x5e\x67\x25\xfe\x51\x3d\xb6\xae\x28\xed\x60\xae\x05\x58\x90\xfd\xaf\xbb\xbc\x25\x40\x42\xb9\xea\xc3\xfe\xf9\xfa\x28\x99\x14\x41\xdb\x1d\x77\x88\x10\xe3\x58\xdc\x26\x57\xc5\x95\x7e\x3d\xe6\x74\x08\x1f\x44\x72\xd8\xff\xb2\xed\x07\xd9\x1b\x3c\xf8\x04\x1f\xee\x96\xf9\xd5\x0b\xe6\xaa\x2c\x9b\xf7\xf4\x44\x55\x08\x62\xcc\xb4\x4d\xc8\x80\x10\x88\xab\x79\xc0\xae\xa1\xb6\xbd\x2d\x37\x35\xbd\x00\xe5\xd5\x1c\x9e\xb8\x3b\x29\x41\xd2\xf4\xaa\xbb\x04\xa1\xf0\x92\xb1\xd4\x6d\x4d\xc3\x90\x0d\xcb\x3b\xa9\x81\x08\x64\x4c\x5c\x5b\x48\x66\xbf\x76\x70\x59\x07\xa9\x14\x74\x92\x53\x1e\x3c\x1d\xdb\xdc\xc4\x21\xa8\xa9\x02\xc5\x32\x98\xe9\xfb\x0e\xc7\xb1\xe9\x6d\x36\x33\x91\x6d\x71\xc7\x42\xcf\xd7\x04\x53\x7c\x9c\x09\x5f\xfc\x45\x0f\xcf\x97\xd0\x4e\xfe\x8a\xa7\xec\x3f\xad\x87\xf7\x21\x21\x6b\x5a\xa0\x63\xa3\x65\xae\x88\xbf\x61\xed\x39\x7a\x2b\x03\x74\x02\x48\x51\x7e\x1f\xa2\x3b\xfb\xf8\x0b\xc4\x70\xb4\xf8\x06\xae\xb6\x1f\x9b\x79\xac\x77\x5c\x84\xc4\x21\xde\xda\x6e\xa7\x08\xe2\x33\x4c\xb3\xbc\xbb\x92\x5f\x88\x47\x65\xef\xc2\x41\x75\xf1\x6b\x1c\x11\xe8\x53\x54\xe7\x78\xa1\xfd\x52\x3c\x28\xdb\x41\xec\xe7\x88\x55\xef\xef\x74\xbc\xf5\xfb\x68\x06\xe6\xf3\x8c\x06\x8a\x32\x90\xef\x16\x08\xfb\x1d\xff\xcf\x5d\xdb\x0e\xbf\xec\xe8\x7f\x12\x4d\x67\xa7\x6a\xfb\x68\x10\xdc\xbe\x3d\x0a\x7e\x6f\x10\x30\xc3\xa2\xca\x0a\x76\x51\xdd\x32\xe0\xae\xfa\xae\xa7\xab\x79\x1f\xe6\x0e\x34\xd7\x0c\xec\xd4\xec\x43\xfa\x38\xa3\x82\xc9\xde\xaa\xf0\xad\x5e\x08\x63\xd6\x7c\x89\x2f\xe5\xaf\x98\xdb\xb4\xba\xb8\x77\xd7\x4f\x32\x34\x65\x00\x16\xf4\x00\xb8\x92\x2c\xb0\xd8\x24\x01\x00\xf2\x37\xbf\xd4\x7d\xc9\x27\x97\xea\xc9\x0b\xaa\xc8\xc0\x83\x62\xaf\x6e\x2e\x90\x6c\xf8\xa0\xbd\xf2\x67\xb4\x8d\x8e\xb0\x96\x6c\xfb\xcf\x7d\x87\x1f\xc8\xf3\x9c\x91\xaf\xf6\xe6\x81\xf3\x3a\xc3\xbb\x11\x7a\x1e\xbb\x77\x7b\x80\xdb\xc7\x74\x56\x5c\x36\xcd\x56\x78\xd5\xbc\x97\x10\x51\x3e\x64\xa5\x59\x0c\x52\x73\x5b\xa0\x9b\x85\xa6\x13\x04\xcb\xa7\x82\xd6\x04\xac\xd7\x00\xdf\x67\x9d\xfe\xe7\x02\xbd\x1b\xfb\xfc\x23\x2b\xb7\x46\xe6\xdf\x6d\x09\xb1\x23\x71\x1a\x41\x9f\xbd\xe0\x8f\x32\x95\xf7\xb0\x5b\x68\x6d\x4b\x46\x75\x5c\x1b\xf7\xdc\x07\x7e\x81\x80\x55\x6d\x6f\x3f\x7b\x83\x08\xf5\x62\xd6\x20\xbf\x9b\xbc\xf2\xe9\xf3\x25\x10\x93\xc7\xb3\xb0\x78\x0c\xbc\xe3\x7b\x79\x6e\xd2\x1c\xe7\x3d\x00\x61\xeb\xd4\xf0\x64\x33\xd8\x1f\xd4\xa3\x40\x90\xec\xc4\xf6\xec\x2e\x1a\x91\x74\x85\x06\x48\x0d\x80\x22\xd9\x01\xf6\x57\x33\xd5\x50\xbb\xa2\x0c\x4d\x07\x4d\xdb\x08\xb9\x32\x93\x05\x89\xd2\x41\x7d\x18\x5c\x6f\x9a\x9f\x4f\x34\x92\xea\x83\xf7\x46\xb6\x26\x3f\x65\x0f\xf8\xac\x13\x35\xe4\x25\xb1\x69\x6c\xad\x1d\xe6\x9c\xda\xec\x53\x9b\x79\xba\x82\xd0\xb7\xff\xe4\x9f\x6f\xdc\x88\x95\x7b\xec\x97\x6d\xff\xe9\x3b\xde\x7e\x4a\x2e\xc5\xda\xfd\x61\xe3\x29\x92\x90\xc1\x61\xbb\x2f\x7b\xd5\x25\x64\x95\xe7\xff\x8a\x2d\xae\x63\x04\xd5\xb2\x82\x60\x5b\x24\x87\xd2\xb7\xd2\x6d\x0b\x64\x3c\xf8\xc9\x3f\xdf\xb8\x11\x4b\xc7\x1e\xd0\x14\xee\x3f\x7d\xc7\x1b\x16\xea\xa3\xc1\x6b\x29\x6c\xef\x5a\x8a\x2d\x15\xe5\xbb\xb7\xfa\xce\x9d\x00\xa1\x7d\xde\xaa\x37\xbf\x55\x7f\x39\x96\xae\x41\xc4\x6b\xba\xf2\xe9\x32\xd5\x69\x8f\x46\x96\x5f\x8a\xe7\x6a\xdd\x65\x9e\x48\x8e\x95\x19\x21\x66\xde\x86\x69\x9b\x1c\xc6\x12\x4b\xab\x41\x33\x17\x3b\xd9\xe9\x13\x33\x7d\x63\x33\xb0\xcc\x61\x7f\x88\x00\xda\x67\xab\x4f\x0a\xb9\x6c\x3a\x83\x78\xfa\x05\x81\xa1\xba\x54\xd4\x1c\x51\x6c\x2a\xa3\x82\xe7\xed\x67\x33\x43\x2e\x49\x59\x2a\xd4\x5b\x5b\x5b\xa2\x6d\x69\x6b\x8f\x96\xd2\x0e\x1a\x9c\x10\x20\xab\xe5\x78\xe8\x83\x6b\x11\xc5\x3e\x04\xec\xf6\x20\x79\x89\xa5\x48\x50\xc5\x99\x63\xda\xfb\xc2\x77\xb2\x25\x5a\xc9\x4b\x5b\x88\xe3\xcd\x2e\x7f\xea\xa2\xb7\x33\x41\x33\x26\x6b\x09\x55\x3b\x2a\x35\xa1\x3d\xa7\x7b\x99\x71\x0b\xb1\x2d\x15\xf4\x61\x3d\xad\xe6\xd9\x87\x12\xe2\xcb\x4f\x74\x0d\x61\x1e\x2c\x27\x23\xcd\x50\xb3\x2e\xda\x5a\x28\x73\xda\xb0\x56\x17\xf3\xc9\xe2\xe9\xb5\xe2\x58\x4e\x9b\x93\x8b\x06\x4c\xcd\x40\xaa\xdb\x2c\x60\xd6\x5c\xb3\x4e\x34\xf3\x23\x66\x2d\x77\x49\xf2\xc8\x32\x76\xf5\xb2\x93\xfe\x23\xd6\xd6\x83\x6b\xfd\xd5\x43\x5f\xa3\x53\x57\x5a\x07\x9d\xcd\xdf\xa3\x20\x20\x90\x27\x34\x81\x59\x03\xeb\x44\x22\x30\x9c\x94\x7a\x1c\x15\x96\x16\x68\x2c\x08\xc4\x1c\xce\x44\xbb\x46\x08\xd5\x95\x14\x6a\x35\xa7\x35\x43\xba\x0a\x35\x3a\x2c\xbe\x56\x46\x84\xc0\xba\x3d\x79\x27\xe8\x1d\xe1\x9b\x90\xb0\x64\xf8\x6d\x78\x97\xe3\x26\x28\x12\xc4\x3d\x28\xb8\x87\x12\xa1\xba\x33\x82\x66\x88\x56\x04\x4a\x70\x7a\x9d\xf7\xe9\x5e\x0d\xb9\xfa\x15\xb3\x1a\x29\x8b\x42\xac\x4f\xa1\x98\x22\x3f\xea\x6d\x25\xc7\x42\x18\x0a\x2e\xe4\xdc\x29\xef\x4b\xa6\xe6\x46\x96\x13\x72\x7d\x22\x18\x56\x81\x01\x2a\x98\xe8\x58\x92\xc6\xd2\x25\x5c\xbb\xe3\xbe\x05\x85\x41\x89\x82\x57\xda\x89\x76\xa5\xde\x68\xef\x1e\x45\x8d\x7e\xd7\xe8\xb7\x8d\xef\xee\x7b\xba\xed\xe9\xae\xb8\x69\x73\xe2\xbd\xad\xed\xb7\x13\xd4\xaf\xa7\x59\xee\xb2\x9a\x61\x08\x2e\x61\x04\xdd\xec\xde\x03\x23\x97\x9e\x94\xdd\x7c\xba\xd8\x18\x72\x0f\xdd\x73\x0f\xc8\x43\xec\xfe\xd3\x48\xa1\x50\x53\xd5\x8c\x06\x4c\x2c\x88\xe4\x15\x08\x9f\x93\x3d\x17\xc5\x7a\xe0\x92\x78\x2e\x8e\x36\xfd\xb0\x4a\x06\xd1\xb2\x63\x6b\xdf\x69\xb3\x24\x84\xce\x6d\x60\xcc\x19\x58\xfa\xc8\xaa\x2e\x26\xbe\xbc\xb0\x0f\x0c\xbb\xda\x43\x4b\x61\xa8\x07\x89\x81\x6d\xa7\x96\x88\xba\x34\xed\x46\xd5\x83\x6e\xcd\xb7\xeb\x62\x93\x85\x19\x44\x75\x79\x1d\x64\x57\x80\x80\x88\xde\xac\xc3\x99\xe1\x03\xea\x05\x71\x08\x72\x79\xfa\x61\x1e\x9e\x76\xb2\x5f\x40\xe9\x73\x5f\xa9\xdd\x04\x41\x1c\xf6\xae\xd6\xa8\x58\x1f\xdb\xe8\xfb\xec\x6b\x6e\x20\x49\x45\x8a\xec\xfa\xa3\xad\xba\x50\xaf\xb9\x29\x10\x7e\xb4\x67\x9e\xae\xf3\xe0\xfb\xa8\x2f\x8b\x8e\xdd\x43\xa1\x7e\x7b\xe6\x23\x17\x5d\x1b\x66\x61\x09\xb2\xa2\x5a\x36\x14\x09\x10\x7d\x0f\x3a\x83\x39\xf5\x00\xc8\xd2\x99\x28\xab\xfd\x0d\x6c\x42\x00\x66\xd8\xc4\x6d\x6e\xce\xcd\xc6\xa1\x28\x28\xe8\xa4\xad\xb9\x5a\x0f\x82\xde\x37\x10\xe6\x94\xca\x9c\x0f\xd4\x7d\xd2\xe1\x19\x41\x59\x20\x6a\x9e\x74\x27\x43\x83\xd9\x97\x03\x2b\xca\xb4\x33\x52\x18\xb2\x4a\x0d\x4d\xc3\xcc\x61\xda\x0b\x08\xc8\x96\x20\x34\x98\x99\xa2\x02\xf3\x40\xf7\xc8\xb2\x75\xbf\xbb\xe4\xd5\x86\x54\x65\x36\x2c\x73\x05\xa9\x08\xf8\x42\xed\x2a\xf9\x88\xdf\x37\x98\x07\x11\x98\x1a\x50\x21\xcc\x08\x9f\x4d\xb1\xee\x99\x42\x0b\x82\x64\x49\x53\x84\xd2\x49\x14\xe3\x2c\xbe\xb6\x9e\x75\x64\x16\xb2\x86\xec\xc4\x91\x61\xea\x16\x95\xd6\xbe\x19\x38\xa2\x2d\x4c\xbb\xf4\x44\x23\x59\x27\xe5\x0c\xa0\x5c\x98\xa8\xaa\xc6\xce\x56\x9c\x49\x52\x36\x0a\x1e\x3a\xa9\x8c\x53\x3f\x25\x8c\x34\x29\x81\x85\x2b\x6b\x19\x36\x88\xe7\x08\xe6\x49\x16\x54\xf5\xa2\xf4\x57\xca\x52\x7a\x28\x6d\x6d\x12\x6c\xcc\xb6\x0c\x6d\x73\x29\x35\xf4\x1c\x74\x68\x18\x94\x35\x1c\x54\x5b\x3c\xd6\xc4\xb2\xf1\x0d\x88\xda\x21\x69\xb3\x80\x90\x5d\xd2\x5a\x67\xf5\x77\x01\x83\xca\xbc\xad\x73\x40\x66\x09\x51\x68\x55\x5d\x91\x7c\x4e\xc1\x7c\xda\x79\x17\x08\x87\x0d\x16\x43\x54\x92\x52\x64\xca\x2d\x66\xf4\xf1\x45\x6c\xd1\xb7\xe7\x09\xd9\xe6\xf4\x0d\x32\x45\x6b\xcf\x88\x25\x4d\x28\xc9\x0d\x1b\x4d\x58\xe5\x38\x80\xb2\x3f\x20\x04\x8e\x30\xfd\xa9\x39\x2c\x5c\x9d\x9f\x93\x27\x98\x79\xcc\x0c\x58\x91\xe1\x50\x12\x9b\xd8\x6c\x43\xa9\x3c\x96\xa9\xf7\x15\xc3\x16\x24\x2e\xec\x10\xf8\xb9\x4a\xb0\xee\x3b\xf0\xed\x06\x02\xd6\xd9\x3a\x95\x7d\x76\xf4\xbe\x04\xd1\xd3\xdb\x86\xba\xac\xcc\x8e\xd7\x10\x69\xca\xe8\xa9\x71\xd6\x75\x52\x89\x32\xc4\xb1\xcb\xfc\x67\x4e\x05\x63\x6c\xd6\xdf\xa3\xe3\xa0\xa0\x69\xd7\x5d\x48\x0f\x72\x00\x21\x76\x88\xee\x48\x05\x61\xc2\x34\x17\xb6\xdb\x60\xd2\x15\xc1\x36\x1b\x63\x42\xcd\xbf\x09\x45\xac\xdc\x57\xa4\x76\x9a\x8d\xca\x98\x8b\x75\x12\x1b\x94\x23\x10\x9d\x24\x29\x00\x9b\xbd\x72\xb9\x08\xf0\xe9\x21\x10\x39\x38\x09\xbc\xfd\x94\x09\xc9\x7e\x92\xbe\x28\xc3\x33\xb5\xac\xc0\x74\x2b\x59\xec\x25\xeb\x6d\x75\xdf\xdf\xfa\x38\x5a\x1b\xc5\xfb\x73\x57\x27\x63\x43\x04\xe9\x1b\x97\xf6\x04\x56\x9b\x19\xa6\x56\x9b\x11\xcc\x28\x29\x4e\x76\x86\xb3\x99\x57\x00\x05\x79\xc3\x23\xdb\x3c\x00\x02\x31\x29\x01\x5a\x37\x6b\xcc\x54\x11\x97\x20\x90\xba\x89\x7d\x82\xd5\xc5\x39\x6d\xb0\x38\xd8\x70\xb1\x3b\xa9\xd9\x3c\x72\x90\x11\x95\x20\x6b\xc1\x88\xad\xa4\x1b\xca\x8e\xd7\x2d\x39\x64\xfb\xb6\xe6\x75\x05\xc9\x04\x53\x8a\x19\x90\x5a\x47\x18\x79\xae\x90\xc2\x20\x7b\x3f\x5e\x3b\x82\x70\xdb\xac\x85\xb2\x7a\x2a\x0b\xa9\xd1\xb4\xd1\xbc\xa5\x78\xa9\x4b\x4e\x92\x35\xc6\xd9\x6a\xb1\x89\xb4\x92\xce\x12\x7a\xee\x2b\xea\xe6\x25\x4c\x4f\x19\x4a\xb6\x11\x8a\xa6\x40\x4b\x6c\x1c\x74\xd6\x40\x8f\x84\xa8\x12\xe4\x8d\x83\xbd\x18\x27\xd7\x10\x3b\x29\x45\xda\xa1\x9e\x2e\xe8\x6f\x36\x37\x22\x9c\xff\xf6\xb3\x74\x09\x6d\x64\xeb\x24\xa2\x05\x83\x3e\x57\xd2\xf7\x95\x40\xe7\x7f\x2c\x1e\x7a\x78\x08\xa4\xef\xa2\x6b\xcb\x45\x99\x0d\xb6\x91\xb9\x24\x21\xe6\xb7\xdb\x4f\x29\xb9\x84\x56\xca\x3a\x28\xef\xdc\x9e\xdf\x90\xa4\x70\x40\x5b\xa0\xce\x22\x30\x40\x4c\x95\x78\x9b\x1d\x69\x4e\x68\xb2\x49\x7c\x10\x6b\x4d\x9e\x35\xd8\xac\x98\xab\x5a\x28\x4f\x2c\x0f\xca\x83\x29\x0d\x3c\xa7\x59\x2d\x98\x68\xb3\x53\x7f\xed\x95\x26\xfc\xc3\xa4\x24\x91\x1f\x65\x5b\xd8\x80\x90\x91\xa7\x83\x21\x4d\x69\xbf\x73\x72\xf0\x43\xcc\x47\x1e\x09\xea\x1d\xd0\x9e\x41\x17\x92\x90\xac\x29\x60\xb4\x07\xe6\x80\x9b\x4b\xa7\xc7\xd6\xf0\xdd\xa4\xc0\x87\xa4\xce\x3b\x79\x3a\x80\x19\x87\x62\xac\x84\x3c\xd9\xa7\x99\x78\xde\x9d\x1d\x7b\x37\xd1\x50\x4a\x87\xa6\xe7\x04\xd1\x0e\x0f\xb4\xb9\xa0\x84\x96\xed\xbe\x66\x4b\x44\x56\x14\x87\x08\x49\x58\x7c\x0d\xb3\x9c\x74\x33\x6b\x29\x83\xe7\xaf\x34\xa4\x38\x05\x92\xf7\x50\x2a\xb5\x9f\x92\xde\x7e\x76\x9b\xab\xb2\xe7\x76\xeb\x0c\x6e\x72\x8c\xc3\x0a\x45\x19\x95\x0d\x99\x81\x4a\x2b\x10\xf1\xa9\xac\x58\x92\x46\x98\x69\xb3\xa9\x3b\xe5\xdb\x1a\xdb\xe4\xbc\x04\x9d\xb3\xb7\x9f\x75\x9a\x41\x90\x80\xa6\x70\x40\x40\x6e\x08\x8c\x47\x31\x0f\x8a\xc1\x63\x2d\x69\x73\x0f\x5f\x6a\x81\xd2\x59\x31\x2b\x83\x22\xf4\x6d\x53\x34\x9d\x56\xeb\xd5\x19\x1c\x59\x39\xb9\x11\x11\xf6\x25\x19\xc6\xf8\x26\x01\x79\x8b\x47\x14\xf2\x80\x22\x79\xe0\x44\x4b\xe8\x51\x28\x76\x98\x09\x46\x2d\xcb\x0b\xc1\x4f\x36\xf0\x07\x1b\x28\x36\x68\xe0\x52\x46\xb2\x71\x81\x72\x0f\x74\x8c\xa4\x85\x99\x5b\x44\x93\xf4\xcd\xfc\x90\x7a\x0c\xd5\x72\x5b\x38\x29\xb3\x80\x29\x44\xf3\xa1\x94\x99\x6b\x17\x3e\x97\x7d\x83\x64\x01\x09\x77\x8a\x5c\x62\xf1\xd5\x90\x08\x4d\xce\xf4\xe4\xda\x82\x2c\x80\x03\x3d\x0d\x97\x18\x30\xf4\xf0\x4c\x7b\xc7\xe9\x8b\x40\xca\xb0\xce\x94\x0c\x59\x30\xe7\x0b\x28\xc5\x06\xec\x91\xea\xdc\x75\x99\x0c\x3b\x8d\xcd\x03\xf1\x8a\xd0\x2a\x69\xaa\x1a\x2b\x87\x05\xb6\x27\x3c\x16\x94\x20\x26\x44\x12\xc6\x8a\xb9\x35\x87\x4c\x6d\x65\xe4\x63\x6c\x12\x4c\x0c\x3d\xf7\x04\xcb\x9e\x9c\x7b\x72\xf4\x74\xd6\x66\xb0\xb8\x27\xef\x3a\x07\x98\xd2\x39\x73\x86\x38\xf3\x06\xbc\x5d\xd1\x15\x2c\xc4\x61\x96\xa0\x63\xab\x39\xf4\xf9\xf6\xb3\x4a\x0a\x35\x43\x65\x18\x84\x6c\xf6\x28\x73\x95\x09\xde\xae\x90\xa7\xd9\x75\x05\x95\x06\x55\x5d\x45\x3f\x88\xcd\xae\x34\x64\xa5\xb1\xc1\x8a\x6b\xfa\x32\x09\x81\xff\xca\x66\xff\xd6\x95\xb0\x33\x3a\x6e\x9d\x0b\xae\x7a\x0b\x66\x5f\x68\xd1\x6a\x08\xff\xdf\x23\x34\x50\x31\x31\x00\x1e\x05\xc6\x5b\xeb\xd7\x99\x70\x9f\x9f\xb5\x53\x0d\x73\xad\x99\x1c\x48\x62\xb6\x93\x7d\x99\x5a\xa0\xb7\x10\xcd\xf7\xb2\x99\x12\x2e\x10\x05\xdf\x1a\xd0\x0c\xd6\xa1\xb8\x1a\x9b\xcd\x58\xa9\xc2\xa7\x33\x94\x69\x6b\xe4\xa0\xcc\x46\x41\xdc\x6b\x8c\x7b\x44\x2f\x07\xd3\x26\xd5\x63\xc1\x8c\xd6\xd7\x12\xaa\x35\xa0\xb5\xc2\x0a\xbd\xf8\x90\x73\xe8\xb2\xe0\xb5\xd7\x1c\x7a\x87\x28\x6b\x5e\xf7\xe8\x59\x0a\xe6\x58\x99\xdb\x8f\xb7\xce\x19\x8b\x16\x52\x1a\xf0\x5d\xc1\x3c\x8a\x72\x2d\x10\x7f\xe1\xd2\x28\x88\x29\xac\xf4\x88\x79\x64\x6a\x5f\x82\x26\xc0\xe6\x0f\x70\x59\xf7\xf6\xf6\x53\x01\xd5\x9d\x69\xad\x81\xb8\x0c\xc2\x89\xd0\x2d\x00\xe2\x93\xa4\x41\x30\x30\xb3\xfb\x42\x54\xe6\xe8\xac\x67\x60\x47\xd2\xb9\x17\xb7\x87\x4c\x6f\x99\x16\x8f\xad\xcd\x7d\x92\x11\x6f\xac\xf6\xda\xc1\xba\x52\xd1\xcd\x7a\xd6\x7c\x05\xbe\xca\xd7\x5a\x80\x4b\xad\xe4\x89\x57\x52\x2a\x2a\x91\x59\x90\x34\x18\x34\x11\x69\x9b\x53\x3c\xa1\x2c\xa7\xf9\x14\x5d\xc8\xa9\xd6\xb6\x7d\xe3\xe0\x47\x2c\x5c\xfb\x9a\x5b\x9d\x7e\x11\x54\x8f\xf4\xfa\xfe\xf2\x9c\x85\xdb\x7e\xdd\xfd\x16\x7e\x03\xbf\xfc\xf3\xe2\xc7\xa5\x0f\x93\xf6\xb8\x84\x5d\x3e\xd9\x54\x3a\x57\x64\x69\x12\xab\xa0\x8e\xca\x29\xeb\x69\x43\x19\x07\x6e\x79\x03\x00\x93\x75\xd2\x9a\x92\x0b\xef\x28\xd2\xb0\x14\x87\x71\xd6\xd8\xcc\x6f\x45\xea\x56\x54\xe5\xd0\x5b\x65\x8a\xc3\xe5\xc3\xd1\x68\x1d\x9c\x90\xce\x08\x89\x25\xc4\x35\x93\xb0\x44\x96\xcd\xc5\x9c\x3a\x26\xbe\xe1\x4e\xae\xb7\x2c\x9f\x31\x52\xd6\x05\x04\xd2\xa3\xba\xfc\x8e\xba\x3a\xa0\x2d\xb1\x55\x28\x13\x24\x09\x3d\x42\x40\xcf\x32\xcb\x6e\x70\x8e\x4c\x55\xaf\x4a\xb6\xa6\x4d\x6c\xca\xf2\x5a\xd1\xca\x32\x26\x7e\x1f\xd9\xd0\xb5\xcd\x06\xb9\x6d\xe0\xc4\x44\x79\x39\x7d\xec\x2c\x25\x80\x61\xd0\x3c\x48\x1c\xe8\xa7\x10\x06\xe6\x6f\x85\xa4\x37\x2b\xe9\x50\x02\x89\x72\x3f\xfb\xa8\x4c\xe8\xd4\xd3\x4a\x9f\x50\x68\x81\x88\xa8\x5d\xe1\x55\x8f\xbd\xd6\x39\x7c\x45\xee\x36\x66\xb3\x29\x47\xed\xf9\x91\x06\xce\xa4\xc5\xdf\xa2\x3a\xa1\x5c\x3f\xa1\x65\xf9\x47\x84\x0f\xec\xc0\x6d\xff\xf9\x6e\xef\xbb\x13\xf7\xcb\x65\x50\xe2\xfb\x3e\xee\xe2\x49\x3c\xa7\xb5\x60\xd7\x89\xfb\xcf\xf3\xbe\x78\x3e\x29\xf2\x42\x04\xbb\x79\xbe\x00\xd4\x71\x36\x4a\xba\x6c\xf8\xdc\x87\x84\x96\x8e\xc6\x3e\x65\xe3\xc1\x37\x6e\xae\xbd\x65\xfb\xe2\x71\x78\xdc\x2f\x80\x0d\x94\x3c\x8e\xf6\x54\xd6\xc2\xc1\x5d\xec\x36\x9b\xff\xd8\xff\xbc\x1f\xc7\xf3\xde\x7e\x16\xaf\xb7\x81\x9d\x49\xdd\xf7\x47\x2c\xe4\xfe\xdb\x65\xe0\xa5\xdd\x23\x90\x84\xb4\x45\x5b\x90\xf6\xe0\x21\xd8\x0e\xd2\xee\x59\x77\x14\x7d\xfa\x82\x5a\x70\x8f\x81\xb1\x3c\xd6\x46\x49\xe1\xd8\x6e\x8f\x28\xf2\x19\x48\xf2\x63\x64\x27\x18\x87\x27\x90\x8d\xb8\x08\x68\x30\x3b\xb5\x8c\x3e\x63\x3e\xf4\xef\x00\xe0\x1b\xb5\x68\x5d\x6f\x29\xe5\x8d\xf0\x48\xa2\x24\x89\x90\xc0\xce\x2d\x9e\xb7\xdf\x1d\x14\x4f\x67\xfb\x36\x36\x79\x90\x1f\x03\x56\x3c\x9c\xfc\xdc\x3a\x1f\x70\x9c\xf7\xf6\xb3\x96\x12\xa6\x8e\x47\x9c\x0c\xbd\x23\xd5\x1f\x09\xc9\x88\xef\x30\x19\x73\x73\x30\xe8\x6a\x8b\x42\xf8\x90\x6e\xf1\x33\xb6\xc5\x13\xe0\xf4\x1b\x57\x37\x8f\x04\xef\xa0\xe0\x50\x2d\xd3\x5f\x11\xde\x39\x2a\x76\x81\x25\x29\x73\xe7\x9f\x9e\xfa\xa0\x7e\xc8\x55\xe8\x68\xcc\xf6\x59\xa2\xb7\xda\x02\xfc\x81\x4c\xd1\xdd\xce\xb9\xc8\x12\x7d\x3d\xa5\x94\x4b\x61\x49\x49\x5f\x2d\x82\x53\x29\x34\xf1\x40\xae\x36\x4a\x6b\xe5\x61\x5b\xb6\xe1\xb9\x6c\x24\x8d\x75\x90\x71\x13\x24\x0b\x28\xf3\x61\x5f\x75\x48\xc7\xbc\xdb\x34\x7e\x86\xe6\xc6\x49\xec\x56\xb6\x26\x4f\x1f\xb4\x39\x8e\xff\xa5\xd5\x75\x8c\xb7\x9f\xf6\x78\x61\x64\x3d\x68\x41\x3f\x57\x7e\x79\x00\xb3\xb6\x57\x14\x7b\x8a\x6c\x4f\x9e\xed\x8f\x44\xed\xdc\x3d\xb3\xc6\x4c\xdb\xed\xc1\x87\x6a\x2d\x78\xea\x8d\xfb\xf9\x54\x47\x86\x2e\x32\x45\x67\x27\xf3\x56\x5f\x10\x87\xbe\xf8\x2e\x97\x22\x88\x72\xa9\x4a\x3f\x93\x5e\x53\x71\x87\x9f\x42\x47\xda\x3f\x8f\x8e\x64\x56\x58\x6f\x40\xe0\x7c\xfe\x34\x7f\x67\xdb\xfd\xb5\xa6\xf3\xc7\x2e\xe5\x45\x47\xba\xfd\xb1\x9e\x74\x7f\x2d\x27\x50\x2e\xb5\x13\xe5\x2a\xd7\xfe\xf1\x57\x41\xe1\x23\x3e\xca\x98\xed\xdf\xdf\xe4\x0f\x7e\x93\x4b\xad\x47\xb9\x4a\x9d\x7f\xfc\x4d\x40\xdc\x83\x6f\x02\x72\x97\x7f\x7f\x93\x3f\xf6\x4d\x2e\xd5\x20\xe5\x5a\x90\x7b\xfa\x26\xff\x2b\x37\xfc\xe7\xed\x7e\xfb\x1b\x1a\xfe\x52\xac\x51\xae\x44\x77\x67\x6c\x66\xce\xa1\xcc\x8c\x28\x48\xe6\x93\xb7\xb9\xba\xf6\x14\x9c\xf9\x58\xd2\x3d\xe6\xa1\x8b\x26\xb1\x36\x68\xf0\xbe\xb5\x06\x67\x8a\x47\x4c\xaf\x52\x4f\x2c\x76\xcf\xc1\xbb\x83\x8e\x28\x77\x80\x4e\xf7\x94\x50\xaa\x2e\x31\x23\x58\x29\xfa\xab\x22\x0c\x22\x2f\xd4\x51\x63\xf2\xda\x1f\xa1\xce\x87\x13\x9e\x14\x66\xef\xe7\x2a\x1a\x6a\xc0\x71\x00\x5a\xf0\xfc\x57\xed\x72\xa9\x90\x28\x57\xbe\xb1\xa4\xe5\x20\x3b\x75\xc6\x87\x98\x5d\xca\x13\x8c\xcf\x66\xf6\x14\x69\x87\x56\x24\x3f\x7a\xac\xae\xeb\xa0\x25\xec\xc7\xdd\x5b\xf1\x23\x40\x39\xde\x59\x90\x34\x8a\x0b\xec\x89\x87\xaf\x23\x25\x6e\x4a\x03\xad\xb9\x1d\xdf\xca\xca\x5b\x66\x84\x60\xca\xa3\x96\xf2\xd4\xbe\xb1\x9f\x24\x9c\x00\x3c\xd9\x8f\x39\x9f\xcc\x5b\xed\x97\x5d\x91\x88\x28\x2d\xf8\xad\xcf\x8f\xf5\xaa\xc5\x2e\xe5\x19\xe5\x42\x23\x75\xae\xc2\x84\xae\xb0\x54\xf5\x36\xb1\xc6\x64\x3b\x61\x70\xe4\x51\x0e\x15\x9f\xe4\x8f\x60\x7f\x43\xcd\xa2\xbd\x5c\x52\x7f\x4d\x28\xae\x8d\x72\x08\x31\x25\x9c\xb7\x83\x0a\xde\xe1\x04\xf6\x16\x39\xb4\x80\x08\x97\xf8\x64\x9f\xb2\x36\xe0\xa4\x26\xb4\x1f\xe4\x95\xf9\xe9\x68\xe2\xe7\xd3\xfc\xfa\xcc\xbf\xbc\x9b\xe8\xb8\xdd\x69\x64\xc1\x32\xfe\xf4\xfa\x50\x6d\x9c\x8d\xef\xb1\x5b\x01\x2c\x48\xb5\x3f\x1d\x06\x02\x0a\x1e\x2b\xd2\xe1\x7a\x6f\x25\xb1\x5a\xcb\x36\xb8\x44\xa1\xe4\xc6\x96\x2f\xfc\x1d\x75\xf2\x47\xfb\x46\x76\x81\x57\x10\x98\x72\x09\x7b\x95\x2b\xe7\xd0\x3b\x39\x15\x94\xa8\xf9\x2b\x01\xf0\x72\xfd\xac\x78\xf8\xeb\x57\xdd\xff\x70\xdd\x65\xd7\xb9\x7e\x6f\xbb\xcc\xf9\x73\x9f\xda\x71\xbf\xd5\xb3\x27\xb0\xcb\xed\x68\x98\x5f\x7b\x02\xfc\xab\xbf\xd8\x4d\xb4\xb6\xdb\x87\x9f\xd1\x5a\xff\xfd\x63\xf9\xc9\x6f\x3f\x6d\x84\xd9\xae\xfd\x15\xde\xbd\xe4\x2f\x6d\xf4\xbe\x25\x71\xfa\x98\x9f\xf7\x4e\xac\x33\x9f\xee\x4c\xd4\x1f\xf9\xe5\x66\x47\x0b\x7e\xf0\xb1\xce\xc3\xeb\x7d\xbb\x7f\x63\x81\xb9\x84\xa0\xca\x7c\x47\xd9\xab\x63\x70\x92\x8c\x53\x07\x66\x72\x06\x34\x1d\x41\xd4\xc6\x43\x72\x71\xc4\x12\x71\x46\xd8\x79\xc7\x5f\x71\xb4\x23\x8b\x88\x33\x7a\xd8\x65\xee\x60\xd9\x79\x5e\xeb\x04\x47\xf2\xfc\x9f\x8d\xa4\x8c\x84\x79\x65\x6e\x07\x54\x82\x59\x17\x87\x90\x8f\xb2\x02\x47\x52\x5d\x9a\x24\xb6\xfa\xc8\xe3\x55\x25\x7a\xbd\x3a\xc7\xff\xed\x24\x49\x92\xbc\x1c\xb9\x8c\x87\xfd\xb3\x2a\x58\x1c\x50\x19\xb8\x73\x5f\xd8\x62\x25\xca\xd2\x18\x7b\x54\xc5\xdc\x7c\xb7\x46\xb2\xe9\xe0\x39\xb5\x24\x7c\x03\xda\x0f\xef\x5b\x66\xaf\xb3\xcb\x20\x35\x4d\x64\xd1\x28\x24\x63\x43\x4d\x00\x82\x5b\xed\xfc\xa6\x48\x28\x0f\x16\x59\x95\xb1\x51\x92\x3b\xed\x62\xa1\xff\xe8\x27\xb9\xbd\x6a\xb5\xab\xeb\x7a\xa5\x21\x39\x87\x14\xaa\x84\x9a\x9f\xca\x3c\x47\x85\xd5\x06\x70\x33\x19\x51\x91\x1d\xa1\x12\x5a\x54\x54\x1a\x3e\xc4\x06\x50\xcd\x66\x8f\x30\xb5\xae\x2b\xcb\xc1\x9e\x67\x6d\xcf\x8b\xa1\x54\x21\x87\x5e\xe5\x28\xef\x44\x61\x01\x8b\x3b\x91\xfd\x67\x6a\xc8\xf6\xdc\xa3\xe4\xf9\x10\x9d\x77\xc9\x73\x35\xa3\x74\x78\xe2\x0e\x90\x61\x64\xf0\x50\x4c\x15\x78\x32\xee\xc4\x1a\x9e\xb7\x9f\x5d\x47\xa8\xa3\x3f\x72\x82\xc8\x91\x0d\xbf\x44\x9c\x13\xb3\xe0\x71\x16\x92\x71\xa4\x4a\x69\x24\x22\x1e\x61\x38\x4c\x33\x78\x20\x6b\x01\x56\xb9\x1a\x28\xd4\x93\x89\x6e\x9e\x0b\xca\x12\xd6\x0c\xc0\x85\xfd\xab\x82\xd2\x5e\xd8\x46\xf9\x21\x92\x51\xb7\xc6\xd2\x86\x04\x03\x8e\x17\x67\xd1\xe4\x44\xac\xba\x49\x90\xa2\x9b\xff\xe0\x5f\x49\x97\xd5\x03\x4f\x1a\x0f\x7b\x02\x24\x19\x90\xcf\x4b\xc1\x55\x69\x52\x98\x10\x3d\x44\x09\x96\x28\x59\x17\xa9\x65\x25\x65\x8b\x42\xc0\x67\x4b\x0c\xc8\x5a\xe7\x24\x93\x6f\xdb\xf6\x9f\xfc\xfb\x6d\x7b\x1e\x7a\x9c\x8f\x67\x28\x94\xa6\x17\x9f\xf5\xaa\x80\x53\xa0\x84\x58\x5c\x9c\x07\x7c\x84\x79\xfe\xa8\x8f\xbc\xd6\x1e\x46\x18\x93\x9a\x33\x59\x43\x67\xa2\xa8\xa2\x70\x92\xe4\x46\xa9\x87\xdc\xec\xdb\x62\x71\x0e\x2c\x93\x2c\xf6\xf3\x1e\x4b\x45\x30\x2d\xdd\xcb\x94\xb5\x17\x48\x6e\x20\x8f\xdc\xf6\x6a\x8a\x89\xd4\x09\x96\xc0\xe7\x48\x75\xc8\x9a\xa3\xb7\x36\x47\x73\x41\x48\x77\x9c\x10\x5e\x0e\xf0\x9a\x30\x2b\x80\xcb\x01\xcc\x6d\xa6\xdb\x86\xbd\x77\x1c\x8f\xc3\x1d\x0f\xc6\x0b\xbe\x1a\x5d\xd7\x10\xc4\x57\x6a\x68\xa3\x8e\xa0\xb3\x3e\xda\xcc\x9e\x73\x2e\x28\x60\x42\xfa\xfb\x88\xf7\xab\x50\xf8\x7e\xdf\xf2\xfd\x1c\x36\xb9\x69\x68\x90\xe6\x07\x55\x47\x6b\x81\x07\x91\xc8\xcb\x2e\xf2\x88\x6d\xda\xe7\x6b\x36\xf9\x1d\x7f\xdd\xf6\x23\x6d\x06\xeb\xdd\xaf\x01\x48\x9a\x17\xa2\x90\x71\x51\x5c\x47\x80\x05\xbb\xb3\x70\x2f\x69\x58\x31\x28\xba\xd7\x43\x90\x88\x8f\x92\x6c\xa4\xdf\xf3\x90\x38\x0e\x71\xf0\x0c\xae\xac\xb3\xdc\x36\x5e\x98\xd7\x45\x0d\xcd\xf0\x8d\xc8\xad\xf3\x7d\x8f\xe7\xb1\x69\xa2\xa1\x4a\x1b\x60\x00\x1b\x4b\x00\x08\x34\x79\xd2\xca\x68\x62\x78\x9b\xcc\xa2\x59\xb6\xa8\xa0\xca\x2a\xb6\xb6\x26\xa4\xe5\x9b\xa7\x5b\x90\xfb\xb6\x03\x50\xcc\x9a\xd3\x16\x9d\xc4\x28\x33\xa3\xd9\x25\x80\xad\x4b\x3a\x0a\x5c\x50\x16\x26\x7b\x6a\x65\xd4\x7b\x06\xf0\x1c\xb9\x35\x24\x43\x2b\x50\xcf\x28\x87\x97\xbc\xd3\x7f\x69\x42\x61\x2b\x9e\xb3\xb4\xb7\xdb\x9f\xee\xb0\xff\x58\x7f\xbd\x86\x67\xae\x8c\x34\x27\xc4\xb5\x59\xe2\xd1\xcc\x91\x44\x5f\xda\xf1\xad\x27\x78\x2b\xd1\xad\x09\x0c\x17\x4f\xe8\x6a\x3c\xb0\xab\x3b\x8c\x36\x39\xf9\x65\x0e\x4f\x80\xec\x13\x1f\x8b\xdd\x4f\x8c\xea\x0e\x51\x55\xc7\x31\x02\x0f\xa0\xcf\xab\x7c\x12\x53\xc0\x53\x7c\x18\x53\xf0\x13\xaf\x41\x05\xfb\xfb\x47\x41\x85\xdb\x21\x4a\xd9\x1b\x02\x0c\x6e\xcd\x21\x42\xf0\xf7\x35\x43\x3b\x5c\x9b\x96\xfe\xd4\xab\xbc\xea\x12\xd7\xe8\xd0\x25\x8d\x79\x36\x10\x6c\x41\xb5\x7b\x2d\x74\x97\x7b\x2a\xf7\x6e\x96\x1f\x94\xf7\x3e\xf8\xbb\x68\x9b\x94\xe4\x72\x08\xc7\xce\x2f\xc4\xfc\x2b\x8b\x8e\x0a\xe6\x2d\xd1\x29\xf7\x96\x7e\x8f\xe5\xbd\x7c\x8f\xf7\xb7\x25\xb3\xc5\xa7\x30\x9c\x51\x78\x7b\x67\x2d\x22\x97\xad\x60\x15\x9a\x1f\xd3\x19\xde\x2e\x7c\x86\x53\x56\x30\x1c\x87\x9e\xc2\xdc\x35\x06\x31\xd3\x82\x67\x17\x5b\xdd\xc6\xb2\xfe\xa8\x38\xfa\xfb\x2f\x55\xa6\x38\x69\xae\x68\x2b\xae\xb4\xd8\x76\x19\x38\xcc\x63\xb5\x1d\x04\x32\xd5\xeb\xe7\x0f\x99\x38\xa6\xef\x5d\xc6\x8e\x34\x15\x6d\x3f\x8f\x9b\xcf\x23\x7c\x65\xf7\x70\x5e\xcf\x9e\x91\x8c\x98\x48\x85\xc9\xce\x29\x10\x5e\x21\x4f\x87\x93\xad\xa0\xf7\xee\x94\x5a\x2c\xee\xe1\x94\x8c\x1c\x3c\x0f\xc2\xd9\x20\x89\x71\xe2\x29\x2c\x5a\x21\xd7\x30\x64\x63\xb1\x10\x72\x8b\x3d\xc8\x64\x96\x51\x41\x0a\x55\x5b\x90\x94\x56\x41\xb1\x0c\x8a\x60\x00\x8e\xcb\x79\x2d\x54\x92\x86\x15\xb4\x91\x1b\x64\x14\x5c\x21\xf2\x12\x13\x65\xb8\xa8\xca\xc6\x5c\xef\x54\xad\x5f\xbf\xdd\xe7\x2f\x77\xfb\x17\x7f\xbb\x17\x23\xfb\x12\x7e\xac\xe9\x9d\x86\x23\x82\x6a\x30\xf4\xc1\xaa\xe2\xf9\x6c\x42\x2b\x88\x4a\xc8\xf6\xc7\x55\x9a\x6b\x26\x9e\xff\xba\x9d\x4f\xf8\x3d\xf5\x0b\x2f\x83\xf8\x0e\x0f\x30\xb2\xb1\x4e\xb0\x13\xf8\x6c\x7c\x08\x3e\x99\xcd\x93\x04\xfe\x9e\xfe\xba\xc5\xd3\xe1\xbf\x72\x0e\xdf\x3e\x27\xc6\xb4\xa7\xfa\x1d\x09\x8f\xb7\x9f\xa3\x97\xd0\x53\x5a\x3b\xca\xf7\xa4\x4c\x9f\x09\x14\x7d\x06\x08\x17\xe0\x36\x54\xd2\x06\x2e\xac\x7c\x3f\x9c\x46\x73\x7c\x49\xe8\x95\x37\x07\x7e\x48\xf2\x53\x23\xcf\x85\xda\xec\x54\xd2\xec\xc4\x4e\xc8\x83\xbb\x52\x64\x79\xe3\xdb\x9e\xb6\x9f\x87\xac\x00\x0f\xb1\xdc\xd5\x2f\x63\xdd\xf9\x7c\xfd\xf8\xbc\xaf\x73\x8b\xe5\xbb\x3f\x1e\xdc\x72\x3e\xb2\x1f\x86\xa3\xce\x6f\x16\xf7\xf7\x45\xf4\xb8\x13\xb5\xe1\x53\x90\x1c\x96\xfb\x73\xeb\xd8\xfd\xaa\xdb\x5e\xa2\xc3\x55\xfe\xdd\x6d\xff\x64\xb7\xa5\xa2\x4e\x49\xe3\xd9\x1b\x5b\x03\x15\x1c\xd8\x75\x52\x5b\x67\x68\x12\xb0\x6c\xfb\xd1\xae\xd6\x0b\x2c\x70\x2e\x41\x39\x09\x22\xdd\xa3\x20\xc1\x22\xa7\x41\xd5\x0d\xa1\x74\x73\xaa\xef\x66\x62\x7b\x61\xa5\x78\x84\x9d\xdc\x59\xae\xa5\x88\xa3\x99\x31\xc2\x35\x80\xfe\x2b\x34\x07\xf5\x55\x44\xbc\x5e\x22\xe2\x55\xff\xdd\x4b\xfe\xe6\x5e\xa2\xa9\x85\x41\xb6\xd0\xfb\xa8\x65\x1d\x15\xd4\x50\x03\xe4\x9e\x76\x86\x66\x20\xe0\x23\xca\x6b\xf1\xd1\xe9\x07\x79\x81\x21\x3c\xa5\xa2\x47\xdf\x40\x05\x0e\xa2\x28\xd3\xf9\x63\x7d\x62\x21\xd8\xbc\xa0\xf1\xe5\xa5\x53\x73\x89\xa1\xd7\xfc\xef\xae\xf0\xff\x9f\x75\x4e\x72\x47\xf9\x7b\xa4\x26\xf8\x6c\xb7\x7b\x87\x10\x89\xd9\x5e\x85\x52\xef\x2c\xf2\xfe\xb3\xeb\xd4\x25\xf8\x5e\x9f\x7a\x79\x35\x95\x10\x3f\xa4\x22\x76\xd9\xf3\x6f\xf7\x16\x9f\x78\x7f\xfd\x82\x6f\x3f\x6d\x2e\x4e\x6b\x0e\xb5\xa2\x90\x31\xf5\x2d\xa7\x30\xeb\x56\xc0\xba\x0c\xa5\xed\xde\x36\x10\x23\xa1\xbe\xb5\xb5\xd0\xd2\x06\x1d\xba\xea\xa4\x90\x05\xc0\xe0\x0a\xfc\x6e\x01\x82\x2f\xe2\xb7\x2d\x3e\x77\xc7\xfd\x8c\xc8\x0b\xc4\xe7\x15\xe3\x7e\x93\x88\x7b\xa2\x42\xd7\x9e\x20\xf2\x79\xee\xa2\x1d\xd1\x3e\x22\x95\x28\xc5\x45\x76\x88\xe9\xbc\x96\xa3\xfb\x45\xa2\x5d\x85\x84\x4e\xbc\xb4\xb9\xf8\x08\x5d\xe2\x43\xf3\xf6\x18\x86\x44\x4f\x13\x06\x58\x28\x0c\xc2\xdf\xb6\xd3\x01\xc7\x59\x7e\x99\xd3\x95\x8f\xdb\xf9\xfd\xfd\x71\xfc\xf1\xcc\xcd\xef\x36\xf9\xd9\x07\x64\xd5\xeb\x77\xbf\xe0\xed\xb7\x3f\xe1\xd7\xfd\xab\x5d\xf2\x1d\xb5\xee\xfd\x0b\x54\x23\x52\x09\xbd\x4d\xe1\x54\x77\xb1\xc5\x73\x99\x06\x33\x4c\xfa\x98\x79\x4d\x90\x4a\xcf\x1a\x86\x78\xf4\x38\x63\xf4\x14\x04\x19\x80\x7a\xcc\x1b\x60\xf1\x7d\x3e\x62\xd1\xb9\x00\x0c\x9b\x1e\xd2\xf5\x37\x4f\x76\x72\xf1\xd2\x31\xf0\x87\x2e\x99\x82\x41\x6d\xcd\x13\xb8\x03\x82\x4f\xf4\xc3\xb2\xc9\x56\xd2\xa5\x6c\xf2\xa1\x00\xa1\x17\xe0\x97\x7b\x07\xf9\x4c\xc9\x28\x7e\xc8\x8d\x7f\x7b\x68\x69\xbf\xf9\x98\x59\xd1\x36\x82\x32\xff\xc2\x3c\x44\x27\x85\x62\x09\x85\xb8\x20\x60\xdb\x34\x07\xfd\xec\x22\x7b\x0b\x0b\xd8\xa5\x80\x5f\xb2\x49\x6e\x30\x44\x8f\x40\x24\x1e\xa1\x02\xa3\x92\x83\x38\x4f\x8c\x8e\xb4\x0e\x44\xb9\x6d\xf2\xab\x69\xad\x3d\x64\x90\x21\x87\x5c\x56\x10\x85\x51\xaf\xa7\xdf\xb6\x01\xec\xfe\xaa\x3d\xf4\x50\x67\xe8\xab\x80\xff\x54\x7a\xf2\x28\x4a\x67\xf4\x12\x2a\xce\x85\xf4\x4e\xbc\x5b\x94\x34\x16\x8a\x06\x59\x7b\x45\x54\xe8\x03\x5c\xd4\x11\xfe\x35\xcb\x6e\x27\x9e\xd9\x29\x69\x90\xe1\x5e\x23\x1e\x2e\x4a\x1e\x81\xe2\xe9\x58\xd2\x15\xc4\x19\x69\x04\x75\xcc\x4c\x07\x4f\x50\x90\x5e\x9d\x8b\x7d\xce\x40\xa9\x4b\xd7\x2a\xb3\x69\xbe\x83\xd3\x5d\xf6\x2a\xed\xb5\x85\x59\x43\xaf\x04\xb4\x3b\x77\x5b\xab\x1e\xcd\x44\x0a\xe7\xb6\x76\x0d\x6d\x9a\x13\x1d\xda\xab\x72\x92\x76\x49\x71\xd5\xaf\xe4\xeb\x86\x9b\x35\x9f\x7d\xd1\x86\x3a\x00\x7d\x54\x8c\x5a\xd4\x85\xe4\xd0\x27\x30\xab\x76\xdc\xaf\xc7\x57\x1d\x28\x15\x58\x20\x77\xa2\x89\xf0\x19\x12\x95\x2a\x10\xf8\x5f\x8d\x51\x0c\x94\x8c\x92\xe3\xde\x17\x84\xce\xaa\xe8\x9a\x07\x11\x5d\x49\xed\xe7\xbd\x8d\xb1\x66\xfb\x20\x4d\x82\xea\x96\x4b\xa8\x6d\xe9\x64\xe8\xac\x21\x6b\xa8\xa1\xce\x47\x99\x5f\x3d\xf1\xed\x34\x40\xbb\xfe\xee\x2b\xe2\xf8\x06\xee\xb0\x5f\x8f\x7f\x63\x93\xda\x64\x09\xe6\x63\xe7\x0a\x42\x04\x8c\x52\xc4\x50\x66\xb2\x91\x8c\xba\xa1\x75\xa2\x77\x37\xd2\x31\xa4\x63\xba\xc6\x5f\x1e\xc0\x73\xa7\x1a\x5a\x20\x80\x2c\xb6\xb2\x75\xc7\x39\xd4\x47\xe4\x3b\x22\x8c\x38\x42\x1c\x79\x61\x5e\x35\x31\x0a\x88\x27\xef\xa7\x18\x8f\xd3\xb4\xea\xed\x1e\x1b\xa2\xc3\x89\x21\xd5\x82\x2a\xf6\xc3\x87\xe9\x90\x87\xb7\xd6\xb7\xc6\xb7\x96\x6f\xfe\x01\x08\x15\x4e\x2d\x38\xb3\x18\xf9\xc2\xd6\xce\x17\xb5\xd9\xa6\x3c\x4a\xfe\xb2\xe7\xab\x7d\x7e\xb3\x72\xcb\x9a\xc5\xbe\x20\x1a\x85\x2c\x15\x68\x2a\x6b\xa9\x57\x7d\xfc\x92\x68\xaa\x57\x1d\xb9\x53\xe0\x3e\x81\x40\x19\x91\xe4\xde\x57\xe0\x1a\x5d\xc9\x4e\x8a\x90\x1b\x81\xd4\x7d\x92\xf4\x51\xc1\x8a\x80\x85\x70\x00\xce\x7a\x10\x03\x89\xe7\x72\xac\x43\x23\xa3\x42\xb9\x97\xc4\xc0\xb4\x73\xac\x79\xcb\xbc\x6b\xa0\xbb\x90\x98\x07\x4c\x0c\x1d\x18\xb8\x28\x40\x18\x81\x68\x8a\x21\x57\xd8\xf9\x1f\x36\x2f\x46\x26\xa9\x03\x96\x86\x04\x7a\x9e\xf7\x92\x64\xe5\xad\x77\xf2\x36\x27\x73\x7b\xc4\xd6\x06\x8a\xf0\xc7\x00\xb3\x5d\x14\x57\x9e\x2b\x3e\xee\x96\x98\x6d\xcd\x19\x75\x85\xec\x09\xc9\xe4\x9b\xb3\x00\x82\x76\xdf\x7a\x12\xf0\x71\x40\xe7\x35\xeb\xf8\x05\x18\x74\x46\xad\x07\x01\xe1\x1b\x52\xde\x6d\x1f\xb7\x2d\x70\x84\x6c\x1c\x30\xbe\x6e\xd9\x8a\xb4\x40\x3e\x0d\xa8\x4f\x0a\xeb\xa0\x2f\xd7\xe4\x58\xef\x99\x1e\xb5\x3a\xc5\x97\x72\x7d\xfd\x65\x50\x1d\x70\x03\xd8\x25\x4b\xd4\x99\x1c\x23\x4b\x65\x29\x32\x14\x0a\x8d\x2e\x8e\x8e\x2d\xd2\xa8\x76\xd3\xd6\x5e\x6f\x02\x18\xbb\xb3\x53\xd4\x14\x88\x34\x1f\xba\x91\xdc\x3d\x83\x3a\x10\xdf\x77\x2e\xb9\xaa\x4d\xc8\x2b\x4b\x0f\xcb\x60\x26\x17\xd4\x09\x07\xfc\xd9\x1a\x6b\x89\x0d\x44\xc9\x03\xd8\xef\x81\x67\x1c\xdf\x98\xe5\x76\x02\xd2\x9e\xb7\x4a\x98\x6e\x5f\xaa\x82\x61\x20\x99\xff\xe1\x0b\xcf\x57\xd7\x39\xd5\xa0\xde\xb6\xe7\x21\xf7\x9a\xeb\xa2\xd9\x7a\x73\x7b\x08\x66\x88\x96\xf9\x21\xda\x02\x0d\xda\xa4\xf7\xd8\xe6\x1b\x07\x46\x5a\x81\x64\x82\xca\xc8\x5c\xac\x67\x8c\x6a\xb6\xa4\x48\xe8\xc9\x45\x08\x3a\x32\x94\x8f\xd6\x06\x21\x39\xf1\x89\xc9\x89\x07\x28\xe7\x6e\x6b\xe1\xce\x9e\xa9\x66\xeb\xf2\x2b\xe2\xe7\xd0\x07\x6c\x9e\x53\x47\xe9\xec\x28\x62\x3f\x32\x28\x4f\x86\x3c\x34\x8d\x7b\xb6\x63\xe9\xa4\xda\x5a\x0e\x32\x77\x29\xb6\x22\xc6\x11\xc6\x13\x44\x48\xb2\x6c\x1b\x42\xe8\xee\xc5\xfb\x72\x1f\x28\x24\x88\x35\x2f\x11\xb6\x96\x14\xb9\xbf\xa4\x76\x6c\x97\x64\x60\xfd\x52\xef\x4e\x30\x1f\xe6\x46\x72\x78\xc0\x01\x75\x6c\x36\x4a\x7b\x5f\x6a\x57\x7b\x0e\x81\x5a\x23\xd2\xca\xa4\xc4\xa9\x66\x68\xd5\xfa\xb9\xb1\x91\x47\x59\xe3\xe0\xb4\x4c\xce\x3c\x27\xcb\x7b\x48\xef\x0b\xc1\x61\x25\xdf\x63\x2d\xed\x93\xe3\xc8\xfe\x28\x33\x80\xc8\x85\x0a\x00\xf8\x17\x7f\xb8\x17\x4d\x4b\x51\x12\x1e\xb6\x01\xaa\x00\x5e\xa5\xdb\x21\x0d\x3d\x0c\xa3\x41\xc8\x48\xd1\x6a\x00\xdb\xac\x4d\x48\xfa\xc8\x40\xf7\x0c\x48\x29\xec\xf4\x7c\xb5\xdd\x67\x9d\x7b\x95\x61\x2b\x0f\xbe\x20\x50\x90\xd3\xdc\xa8\xb2\xc4\xda\x73\xe8\x20\x14\x9d\x44\x43\xa7\x1c\xaa\xde\xe3\xac\xf3\x63\x24\x11\x00\x66\x4a\xfe\x98\x72\x70\xf4\x92\x58\x9b\xde\x0e\xd9\x7d\xc0\x54\x51\x13\x73\x38\x32\xef\xc4\xda\xe8\x3d\x0e\x4c\x0e\x9f\x5c\xb9\x14\x90\xaf\x8d\x95\xe4\x62\x05\xf4\xea\xdb\x80\x20\xa4\x99\xdc\xf7\x29\x1f\x15\x17\xb1\x44\x80\x54\x2b\x69\x31\xbb\xd8\x99\x8c\x77\x01\xd0\xc3\x23\xc3\x87\x1d\x48\xa1\x99\x37\xf9\x4c\x5d\x9e\x89\xf0\xec\x41\x3f\x34\xfa\x6b\x13\xc2\xf8\xec\xa2\x7d\xc9\x00\xdf\x93\x7e\x3e\x82\x03\x85\x9e\xff\x26\x84\xb4\x82\xa5\xb7\x7f\x78\x25\xeb\x4e\xbf\x89\xba\x6a\x97\x0c\x68\x9d\x5f\x8c\x83\x52\x29\x46\x8b\x00\x3b\x7a\x63\x7f\xfa\xca\x08\x88\x40\x4a\x08\xa2\x7c\x05\x05\x08\xd4\xca\x35\xe3\x1f\x43\xbc\xa0\x41\x5b\x5f\x08\x20\xb6\xf5\xb9\x03\x4d\xdf\x43\xed\x0e\x8b\x53\xf0\xa8\xdb\x0c\xd5\xc7\x2a\x3d\x8c\x4a\x6e\x2b\xc9\x73\x43\xd0\x24\xd4\xb2\x8e\x0c\xff\x61\x38\x82\x97\x9a\x31\x76\xef\x01\x7a\x87\xb1\x58\xa7\x2b\x3a\x6c\x8e\x1f\x12\x20\x35\xc8\x78\xcb\x00\x3a\x76\x1d\x93\xd3\xe0\x0f\xa7\xe3\xdf\x68\x71\x21\xcf\xb5\x22\xdb\x64\xbb\x6d\x60\xcf\x1b\x28\xe6\xa5\xf1\xfb\x21\x55\x15\xeb\x5c\x28\x0f\x03\xe5\x9d\x14\xba\x6b\x70\x60\xa6\x62\xe5\x07\x73\x55\x9a\xb7\x22\x41\xad\x2f\x17\xf2\xa7\x6e\x05\x10\x5d\x33\x0b\x13\x04\x22\x06\x28\xc3\xb8\xa2\x77\x48\xe6\x41\xfc\xd4\x41\xd3\x63\xf3\x22\x95\x69\x43\x2b\xf5\x10\xf3\x48\x4e\x48\x8d\x32\x31\x3c\x84\x4d\xf1\xe0\x20\x31\xdf\x9d\x05\xe3\x83\xd5\x75\x0c\x27\xba\x60\x64\x6c\x6a\x4b\xbc\xf9\x41\x03\x15\xd2\xf6\x25\x4a\x0d\x2d\xa9\x33\x56\xf1\xb8\xa6\xce\x1a\xa7\xe5\x86\xfa\x2b\x9f\xc3\x60\x19\xdb\xcc\x9c\x7c\x78\x20\x0a\xb1\x20\x65\x52\x4b\x37\x23\x69\x89\x73\x06\x3c\xc1\x04\xd5\x4e\x49\x0e\x41\x6e\x33\x90\x35\xa5\xf4\x77\x97\x83\x19\xe1\x51\x05\xbb\x9c\x2d\x5b\x28\x72\x00\x73\x92\x8e\x60\xd6\x4b\xdb\x60\x49\xd8\x77\xc5\x7a\x2a\x2b\xbd\xdd\x5c\x5c\x26\x0b\x3d\x33\xfd\xa8\xf7\x36\xcb\x5a\x6c\x8d\xeb\x2d\x68\x5b\xac\xc5\x72\x9f\x6b\x6d\xa1\x20\xe9\x28\xe2\x25\x25\x5c\xd6\x68\xf1\x01\xea\xcd\x12\xb8\x82\x35\x18\x09\xa4\x76\x33\x8f\x0f\x64\x68\xe9\xa1\x6a\x1d\xb4\x98\xc7\x21\xd9\x2b\x13\x75\xcb\xd3\x7a\xeb\x0a\xb2\x9f\x12\xd4\xde\x03\x9c\x33\xe0\x34\x86\x39\x53\x30\x0f\x26\x86\x60\x2e\x9f\x82\x00\x7c\x45\xc3\x49\xb5\xa6\x2a\x3b\xc1\x05\x1d\x94\x41\xd8\x7b\x18\xea\x43\x2c\xbf\x4a\x0f\xb4\x6b\xee\xf3\x2b\x9e\xcc\x56\x76\x9f\xf0\xeb\x78\x0a\x30\x4a\xd9\xe6\x77\x5b\x0c\x41\x62\x5a\x04\x15\x71\x92\x3a\x78\x3d\x9c\x13\x6f\x3a\xa7\x38\x88\xa3\xbf\xe7\xe3\x75\x19\x2b\xb8\x52\x99\x71\xce\x7b\x65\x88\xad\xf9\xcb\xd4\x90\x1b\xe6\xc3\xd9\x82\x16\x28\x75\xa8\x74\x06\x45\xac\x7f\x74\x01\xa8\x3d\xa7\x5f\x25\x02\xe8\xb8\xc9\x27\xb1\x91\xdb\xa7\x5e\x70\x61\xe0\x28\x79\x09\x5f\xee\x2e\x7c\x32\x05\x0f\xf8\xaa\xa5\xa6\x3b\xd1\xfd\xb3\x0b\xbc\xb1\xd1\x11\x62\x4b\x9d\x46\x3d\xac\x43\xc4\xef\x5c\x86\xac\x20\xa4\xa1\xc9\x1a\x46\xad\xd7\xa9\x3b\x8f\xe6\xde\xb4\xb9\x96\x1e\x54\xcc\xf3\x52\x33\x3c\x30\x1d\x5a\xeb\x8e\xee\xc1\x92\x16\xfa\x3a\x11\x65\xb1\xa1\xd1\x3c\xdc\x19\xa5\xc9\x8f\x7a\x7b\x44\xb6\x60\x74\x53\xc6\xfc\x23\xd7\x45\xb4\xb6\x86\x05\xcd\x59\xe2\xc9\x7b\x20\x6e\x4e\xdf\xa3\x7d\xae\xbf\xec\x4e\xf2\x10\x7a\xb8\x1b\xd9\x51\xcc\xc7\x5d\x3b\x2c\x2b\x24\xd9\xea\xa3\x96\xfe\x91\x73\x74\x04\x90\x88\x74\x72\xa8\x2d\x60\xec\x70\x65\x3e\xde\x83\x64\xce\x73\xcf\xed\xd8\xf5\x62\x1c\x5d\x93\xb1\x07\x99\xa9\xe8\x18\x61\x8c\xb9\xa2\x15\x84\x73\xc4\x8a\xbc\x4f\xcb\xcc\xff\xb8\x78\x14\xc5\x94\xca\xe1\x78\x2d\x11\x59\xa4\x3c\xc9\xa5\x3e\xda\xde\x8f\xa4\xa4\x8d\xce\x9b\x4d\xa5\x77\xf3\xeb\x3e\x71\x37\x1f\x25\xc9\x62\x6e\x61\x68\x3a\x80\x91\xa2\xba\x4d\x00\x69\xfb\xd5\xa3\x24\xef\xa4\x13\x46\xa2\x98\xc2\xa9\xe8\xe6\x8f\xba\x00\xde\x54\x50\xb1\xfb\xc1\xb9\xdb\x2f\xee\xa6\x75\x9c\x26\xd6\xc3\xcc\x27\x0e\x75\x05\x9f\x83\x68\x3f\xd2\x13\x1e\xf5\x18\x14\xbf\xee\x10\xda\x00\x5d\x52\xa2\xf3\x68\x97\x71\xd6\xb5\x58\xc6\x62\x0e\xb2\xf9\x9c\x4b\xa4\xce\x77\xbd\xd7\xba\xd6\xb4\xd7\xf6\x09\x35\x6a\xe0\x42\x2e\xd0\xfc\xcd\xc3\x96\x5b\xd2\xee\x96\x8f\x43\x32\xa2\x33\x87\x6e\xde\x3a\xf9\x97\x59\xe1\x6b\xb3\x02\x68\x8e\xf6\xca\x20\x17\x4f\xf2\xac\x88\x6f\xd9\x7a\x08\xc2\x1c\x68\x45\x7b\x71\x3b\x50\x64\x44\xf7\x5f\xfc\x5e\xbc\x19\x5e\x4c\x06\x57\x78\x33\x3e\x5a\x0a\xb9\xea\x3a\x6d\x59\xb0\x65\xd5\x26\x82\x74\x9e\x82\x34\x90\x80\x93\xba\x2a\xea\xa2\x84\xf4\x28\x17\x2d\xc8\x46\x98\x67\x38\x17\x14\xcf\x88\x98\x93\x46\xaf\x2e\x94\x76\x97\x69\x2b\x61\x0b\x9a\xf3\xa3\xa2\x84\xf3\x33\x3f\x6d\xfb\x74\x9a\x02\x4e\xa3\x95\x05\x05\xda\x55\x99\x42\xc3\x8a\xdd\x83\x53\xb0\x66\xb8\xad\xb7\xaf\x27\x3c\xb3\x3a\xf6\x34\x79\xb1\x09\x87\x95\xaf\x9d\x7a\x75\x3d\x2d\xa3\x06\xeb\xef\x32\x03\xa4\x01\xcc\xea\x7a\x4c\x59\xc0\xbc\x65\x3e\x1b\x61\x7e\x58\x12\x6c\x6a\xb3\x75\x13\x61\x8f\xe3\xb6\xd9\x97\x02\xe7\xb3\x19\x5c\xa7\xcb\xe1\x2c\xda\xc6\xdd\x9c\xc8\x07\x14\xda\x06\x63\x28\x43\x42\xce\x66\x82\x59\xd7\xc8\xc2\x1e\xd2\x43\xce\x77\xf8\xa6\xc0\x05\x12\xa3\x01\x9a\x79\xa5\x7b\x86\x22\xf9\xdb\x21\x7e\x70\x78\xdf\x27\x8f\xbb\xb5\x57\xe0\x94\x76\xcd\xd0\x5f\x95\x29\x67\xcf\x47\x6d\x74\xf7\x22\x4f\x9f\x94\x9f\x5a\x2a\x87\x92\x8a\x3d\xf4\x78\xc4\x21\xfa\x4e\xbf\x82\x55\x98\xbb\xd2\x4a\xae\xef\x55\x54\x5c\x43\x25\x3f\x06\x50\x5a\xb3\x7f\xb8\x5b\x1f\xbc\xef\xbb\x2c\x4d\x9f\xf9\x53\xe5\x94\xb7\x9f\x32\x66\x0d\x73\xd6\xa5\x43\x54\x44\x56\x8f\xb9\xdb\x77\xdb\xc9\xaa\x1c\x64\x2a\x69\xd7\x13\x27\xae\x52\xc2\x70\xd4\x01\xac\x62\x28\xe4\xd6\x31\x16\xaa\xc8\x15\x25\xc2\x42\xa6\x17\xf0\x4c\x30\x3f\x83\x9c\x91\x8e\x97\x98\xe5\x3d\x46\x28\x66\xbb\xc2\x9f\xc0\x50\x0d\x64\x39\x4b\xb4\x02\xc9\x5a\x36\x7e\x6d\x14\x90\x80\x3e\xe5\x9e\xcb\xd2\x47\xe0\xd3\x23\xbe\x43\x33\x9d\x4f\x78\x97\xe2\x01\x22\x3e\xc6\xa2\x8a\xea\x65\x92\x3e\x69\x09\xf8\x15\x44\x56\xd4\x9d\x61\xc9\x1b\x4a\xb4\x7f\xd4\x45\x55\x82\x1d\x0c\x35\x5b\x3c\xf5\x5d\x8a\xdc\x9e\x22\x1d\x83\xd2\xab\x78\xda\x57\xbd\xe9\x9a\xe4\xff\xb2\x72\x39\x15\x0d\x23\xdb\x7c\x3e\x48\xd6\x25\x40\x95\x64\xd2\x3e\x82\x63\xd1\x1a\x35\x3f\xa2\x0e\xb9\x9b\x5f\xc3\xda\xd9\xa4\x21\xf7\x0d\x59\x25\x4c\xde\xb3\x84\x5a\xc6\xa2\x80\x87\x38\x49\x70\x07\x36\x25\xcb\x3b\xf6\x6b\x01\xe5\xb6\x1e\x1f\x69\x04\xb1\x79\x74\x96\x90\x9b\x7d\x81\x0a\xad\x9d\xf4\x69\x19\xeb\x87\x8a\xf9\xe9\xd7\x1e\xa9\xb3\x40\x75\x3e\x05\xb0\x7d\x29\x6a\x30\xc0\xab\x49\x8d\xbe\x79\xdb\xc0\x6f\x42\xdf\x04\xaa\x11\xd4\xaf\x75\x75\x38\xa7\x55\x4d\x66\xc1\xb5\x5d\xa9\x59\x76\x96\x9f\x0c\x4d\xb9\xea\x2f\xd0\x42\x64\xea\x47\x19\x76\x92\xda\x37\xa7\x7a\xe2\x44\x44\x96\x16\x1d\x6d\x7b\x6e\x9d\xf6\x9f\x4e\x7b\x5e\xcc\xb6\xb8\x81\xbd\xb6\xd3\x4e\xe1\x19\xb8\x0c\x18\x80\x9e\x5b\xcf\xbd\xf1\x79\x4a\xdc\x2f\xe3\xd5\xe1\xad\x24\xc6\x2a\x6c\x26\x3b\x78\x88\xfe\x46\xf6\xa1\xed\x25\x0d\xd2\xab\xfe\x7c\xad\x1e\xf8\x8a\x3d\xaa\xa5\x1a\x72\xca\xbb\x1a\x5c\xed\x41\x12\xaa\x0b\x64\x84\x1c\x6c\xee\x2e\xe6\x1e\xad\xb1\x91\x56\x90\x81\x77\x69\x48\x5f\x62\x81\x58\xe2\x41\x48\x69\x3d\x85\x64\x6e\xc9\x89\x87\xa2\x9c\xaa\x85\xc9\x15\xe8\xae\x37\x5c\x82\x7d\xf2\xf3\x05\x8f\xd5\x85\x34\xca\x94\x51\xed\x32\xcd\x00\x5a\xe1\x70\x02\xa9\x44\xa5\x45\x45\xb5\xec\x9a\xcd\xbe\xef\x3b\x35\x72\x65\xed\x86\x59\x08\x44\x1a\x91\xc1\x1a\x6b\x4f\x5a\xf1\xcc\xf6\xfc\x65\xa9\x39\xf4\x81\xe9\x02\x40\xee\x60\xf6\x62\x06\x15\xa2\xcd\x55\xa8\x24\x60\xac\xbb\xb0\xb7\x6c\xe4\x5f\xe7\x82\x60\x9f\x0b\x35\xe7\x04\x73\xa1\xfa\x0c\xa5\x23\xc8\x30\x1e\x84\xcd\xa5\x81\xc3\x95\x25\x4a\x6a\x6e\xeb\xac\xb4\x49\xf2\xe7\x2d\x5e\xce\x2d\x3e\x50\x4e\xae\xf5\xef\x68\xf1\xdb\x7f\x4a\x93\xff\xa3\x2d\xde\xd9\xe2\x75\x4f\xfd\x6d\xcc\x2b\x7d\xa3\xd5\xf7\x59\xe8\xf6\x5f\x6e\x1a\xfa\xcb\x2c\x69\x1f\x4d\x53\xb7\x3f\xc7\x92\xf6\xd5\x2c\xf4\xdf\xf5\x5a\x63\xd2\xae\x84\x53\x27\x25\xb3\xdc\x42\xcf\x8d\x21\x0c\x84\x41\x9e\x5b\xad\x6b\x68\x5d\x97\xfd\x27\x58\xfa\xa4\x8d\x05\x2a\xba\xb3\x2d\xb1\x6b\xe8\xba\xc4\x62\x76\x72\x19\x69\x39\x36\x64\x9a\x49\x9c\x97\xa8\x63\x06\x1d\xfd\xed\xa7\x64\x21\xf3\x3f\x2e\x67\xd7\xe6\x0d\xb8\x65\x97\xb6\x2b\xcf\x16\x66\x5b\x90\x78\x50\x5c\xcd\x2e\x16\x8f\x0d\xbb\xac\xfd\xb3\x28\x38\x91\x47\x7f\x3e\x8a\xe3\xc3\x5f\xb5\xce\xa5\xb0\xa0\x5d\xc5\x88\x9f\x73\x74\x87\x55\xa1\x8b\x76\x90\xe9\x2e\x51\xfb\x0c\xda\xe7\x82\xb4\xe4\x18\x0b\x54\x9c\xc4\xac\xfe\xfd\x39\xf6\x23\xf6\x9f\x40\xc7\xa4\x65\xf4\x60\x4f\x2b\xda\xcd\x67\xb7\x99\xc6\xe6\x90\x5a\xe0\x4d\x56\x5b\xfa\x17\xfb\x53\xa9\x85\xfb\xb0\xa1\xa0\x48\xef\x82\x8b\xd9\x95\x17\xb8\xe7\x14\x76\xb2\xbb\xb2\xb9\x8e\xbd\xf1\xb9\x55\x52\x28\x69\x01\xe1\xec\x18\xcf\x25\xf5\x3b\x2b\xea\x9f\xeb\xaa\xff\xf0\x92\xda\x2f\x39\xf2\xf6\x15\x1f\x54\x03\xd2\x19\x41\x57\xe8\x32\x93\xd8\x8f\xec\x90\x4f\x19\xdb\x3d\x6e\xd9\x8e\x08\x0f\x0e\x6c\x6d\xcf\x8b\xf3\xd7\x7a\xe8\x2c\x83\x52\xd7\xd6\x9c\xe7\x45\x36\xbf\x36\x17\x96\x91\x6a\xa8\x6c\xdc\xcb\x7d\xdb\x71\xca\x87\x77\xdc\x7c\x6b\xbf\xd5\xb6\x9f\xb0\xdf\x01\x02\x5d\xd5\x5f\xab\x4f\xc2\x7d\x0e\xe5\xa9\x1f\x35\xd4\x7e\xdb\x37\xe3\x09\x38\xc4\x3f\x6d\xe7\xed\xf3\x41\x7e\xee\x71\x08\x7e\x7f\xfb\x29\x53\x86\xbf\x0a\x73\x7b\xfb\xae\xe3\x6e\x70\x52\xfb\xdc\x93\x76\xfb\x2d\xfb\x5f\xbc\xe1\xa8\x69\xff\x64\xa4\x04\xe7\xfa\x36\x99\xec\x9f\x38\x7f\x50\x5f\x66\x27\x1f\xef\x1e\x36\x66\x86\x6f\xf6\xdb\x36\x6c\x34\xe0\x26\xb3\x33\x12\x71\x3a\x73\xdb\x2f\x49\xac\x71\x4a\x65\xff\x56\x22\xf5\x79\x43\xbe\x23\x95\x9a\xf7\x1b\x56\xde\xd0\x2e\xe5\xf1\x0d\xde\xb2\xed\x57\xdd\xef\xba\x1f\xb1\xf2\x21\x4f\x97\x79\x7f\x77\x49\xc5\x5e\x17\x5e\x29\x6a\x21\xa8\xc1\x44\x42\xea\xcc\x82\xfb\x8c\x64\x82\x90\x01\x48\xb3\x80\x66\x3c\xee\x73\xef\x0f\x17\x0d\x07\x8c\xf5\xb6\x1d\x9b\xdb\xe9\x00\x3f\x69\xb5\x5b\xa4\x70\xba\xec\x76\xba\x9f\xcd\x09\x69\x04\x11\xd9\xc9\x93\xcd\x82\xa8\xc8\x24\x98\x5b\x45\x70\x70\x45\xd1\x89\x19\x14\x50\x92\x52\x80\xf2\x29\xe3\x4f\x27\x44\xd5\x4d\x94\x28\x23\x3f\xa5\xfc\x91\xbe\x65\xa1\x5c\x50\x80\xdb\x45\xc6\x11\x1c\x05\x91\xbe\xf9\x3f\xd2\x43\x05\xd1\xd3\xe8\xbf\x34\xcb\xa9\x51\xfc\xd9\xbd\x7d\xd8\x66\xe8\xf2\xac\x49\xda\xd5\x68\x9e\xbf\x9c\x0f\xdc\x9e\x17\x38\xae\x8a\x34\xaf\x04\x91\x94\xef\x79\x64\x8f\xb9\x20\x20\xe8\x91\x5f\x30\xc7\x72\x73\x15\x78\xfd\x15\xc7\x87\x98\x33\x43\x19\xb5\x79\x32\x05\x20\x7c\xe8\xd8\x50\x3a\x41\x47\x67\xbd\x92\x79\xe7\x74\xcf\xcb\x44\x6e\x5b\x60\x4f\x30\x51\xc4\xe4\x2a\x5c\xf0\x3e\xa1\xbc\xa2\x50\xa2\xf8\xc1\xa4\xe0\x06\x4d\x1b\xe8\x48\xde\x90\x22\x07\xeb\x80\x77\x6a\x21\x9f\x2e\x70\x15\x1c\x5c\x2b\xea\x5c\x60\x5a\xf5\x40\x92\x5f\x7b\x24\x7f\xa2\xde\x5d\x08\x56\x06\xd2\x44\xc1\xde\x01\x02\x4b\x54\xc2\x70\xf9\x86\xca\xad\x7b\x6e\x75\x15\x94\xb8\xa4\x90\xab\x59\x45\x80\xeb\x67\xe5\xd8\x57\x85\x16\x98\x42\x3f\x87\x13\xbc\xd4\xfe\x6a\xd9\xbd\xd4\x25\xb4\xab\x2c\xf4\x93\x36\xab\x21\xb9\x06\x2a\xe2\x41\xa0\xb7\x79\xc3\x79\x43\x8b\x66\x44\x15\x6d\x0f\x7f\x93\x6d\xdf\x9d\xc1\xe8\x9d\xf3\x26\x28\xd8\x50\xc2\xe1\xc1\xb9\xce\x3f\xa4\x2d\xee\xc7\x78\xae\x22\xa7\x86\xfa\xa1\x14\xf6\x18\xb5\x93\xf4\x3e\x29\x4a\xdd\xeb\xde\xff\x02\xf6\xdd\xd3\xa1\xdc\x7e\xf2\x9a\xe2\x77\xa6\x7c\xe3\x89\x0a\x35\x3e\x8f\x7b\xfb\x29\xd2\x72\xa8\xbd\xec\xb2\x54\xe2\x05\x02\x37\x6a\x13\xb8\x28\x1a\x7b\x71\xa6\x9c\x07\x15\xee\xfb\x16\x1b\x43\xcc\xc7\x0c\x05\x0c\x64\x16\x26\x52\x51\xbb\xa9\x8b\x36\xa4\xf9\xfa\x8a\xb4\x83\xa0\x0e\xac\x17\xd6\x69\xf7\xec\xc4\xf9\x79\x8d\xce\x4a\x86\x60\x75\x4e\xd6\xe9\x40\x3f\xdf\x3a\x6b\x06\x5a\x0f\x6a\xd6\x9e\x5f\x6e\x7c\x70\x42\x0e\x39\x2d\x64\xbe\x5f\xf7\x3b\x65\x09\x3d\x6f\xf6\x6f\x59\x78\x8d\xbe\xc0\x50\x5c\x41\xa3\x0f\xa9\x55\xe9\x61\x96\x1b\x96\x62\xb5\x96\x44\x80\x59\x8e\x37\xb5\x17\xc5\xeb\xfb\xdb\xdb\x5e\x2a\x01\xd3\x15\x62\xa8\x5c\x47\xc8\x75\x2b\x1a\x54\x01\xb8\x54\x64\x82\x72\x5d\xad\x81\xd0\xa8\x22\x1b\x0a\xca\xad\x87\x37\x57\x21\x02\xe6\x52\x0b\x95\xfb\x44\x56\x4c\x92\xd2\x4b\x70\x6f\x2b\x81\x04\x60\x31\x3b\xa0\xae\x19\x39\xbe\x56\xed\x46\xb5\x05\xdd\x50\x9f\xa3\x28\xa6\xc8\xaf\x02\x5c\xfd\x52\x85\xd0\x0e\x38\xc1\xd4\x1e\x26\x75\x5b\x01\x7d\xe7\xc8\x3e\x0b\x08\x47\xa7\x64\xc0\x2f\xdc\x26\x2e\x15\x07\x9d\x36\x4f\x47\x9c\xcf\x3c\x5d\xd2\x7a\x5c\x91\x50\xc9\x51\x41\x47\x70\x84\xac\x2e\x24\xc4\xea\xfc\xf4\x34\x90\x84\xa5\x98\xe0\xe4\x4f\xb6\xea\xd9\xe0\xd9\x60\xbc\xe2\x0f\x62\x9e\xe5\x80\x7b\x98\x61\xf2\x06\x61\xe7\xc0\xb7\x4c\x87\x95\x43\x4d\x99\xc9\x69\xd1\xae\x71\x43\xee\x02\xe1\x4d\x75\xdd\x2e\x4c\x97\xe6\x0b\x8f\x8c\xd8\xb4\x42\xa3\xaf\x2f\x98\x90\x21\x9f\x0d\x34\x11\x21\x45\x02\x4a\x7c\x5e\x64\xff\xbf\x12\x70\xcf\x8d\x65\x86\x38\x57\xdf\x55\x5d\x7c\x6b\xc3\x86\xea\x62\x17\x90\x29\x2b\x62\xeb\x36\x78\xfc\x8a\xf2\xe9\x19\x33\xe0\x6a\xfc\xaf\xee\x61\xe9\xca\x6a\x10\x5c\x2d\x2d\xb1\xda\x5f\x90\x25\x83\x4a\x57\x0d\xad\xaf\xad\x87\x52\x82\x4d\xc7\x0c\x0a\x20\x3b\x78\x43\xf8\x51\xfd\xc3\x23\xbe\x37\xed\x36\x73\x03\x35\xcd\xac\xfc\x09\x2c\xc5\xc4\x83\xcc\x6d\xff\xb9\xef\xf0\x03\x79\xde\xce\x5d\x24\x9a\x9e\x5c\x87\x32\xa9\x28\x02\xd5\x0a\xae\x05\xe4\xc9\x28\xc4\x14\xa5\x27\xf5\xc7\x51\x52\xe5\x92\x59\xf8\xc3\x1e\xa4\xfc\xb4\xfc\xca\xf6\xf3\x0a\xa7\x2b\x6f\xa7\x5b\xbe\x1a\x17\x97\x4c\x7e\xbb\x92\x28\x76\x3d\x48\x14\x6b\xab\x4c\xe5\x37\xd4\x95\x88\xf3\x0d\xb0\x3e\x48\x3c\x8b\x4f\x13\xb2\x37\x26\x77\x33\xec\xe3\xe1\x4a\xda\x30\xb8\x41\xde\x44\x81\x4c\x86\x0f\x9a\x2b\x64\x92\x4b\x04\x06\x44\x73\xe3\x9c\x99\x5c\x0e\xc6\x91\x03\xae\xd0\x46\xc8\xb9\x3d\x78\xa7\x56\x90\xb5\x92\xb4\x09\x12\x76\x77\x29\x69\xbe\xfd\x1c\xcd\xdc\xa1\xb2\x22\x5e\x32\x34\xe4\xbc\x94\x64\x7e\xe9\x58\x33\xa0\x13\xb9\x87\x01\x6c\xc2\xa4\xe8\x61\x18\xf8\x42\x63\x4f\x05\x1d\x55\x24\x8a\xfa\xee\x85\x94\xf2\x59\x12\xb7\x90\x55\xb2\xcb\x64\xb3\x2e\x51\x53\xea\xe9\x1e\xea\x10\x92\xd4\x89\x8a\x20\xd9\x2b\x44\x05\xf2\x67\xa3\x2e\x05\x01\x6f\x7b\x94\x4c\x49\x50\x1b\xd6\xaf\xb8\x24\xfa\x25\x5b\xdc\xae\x62\xd1\x27\x2e\x89\x32\x11\xb4\x36\xcf\x7f\xd6\xd0\xa6\x13\x56\x22\x82\xcd\x58\x4e\x26\xbb\x8b\x30\x80\x94\xa1\x50\xe4\x9a\x21\x74\x79\x9e\x8b\x1f\x16\x39\x18\xf7\x10\xfe\x44\x99\xdc\xb0\xa5\x81\x6a\x00\x60\xf0\x16\x64\x20\x1b\xa5\x09\x5c\xfb\x22\x9f\x24\x1b\x93\x52\x2c\x8e\x17\x0e\x5a\x28\xf0\xa3\xfd\x5e\x47\x7e\x44\x88\xde\x50\x54\xa7\x3b\x49\xc0\x81\x4b\x02\xa1\x38\x30\x5f\x4a\xe1\x1e\x75\xf1\x87\x39\x37\xa5\xc1\x59\x4b\xba\x79\x09\xb8\x94\x44\x94\xe1\x26\x36\x13\x96\xee\x30\x6a\x20\x63\xb4\x05\x85\x88\x75\x6e\x41\x27\xf1\x04\xd0\xf2\x49\x12\xba\x3c\x6a\x5a\x2a\x96\xa3\x47\x2c\x1d\x35\x08\x50\x46\x63\x3e\x17\xf0\x5a\x74\xd8\x89\x4f\xd7\x13\x38\x6d\x04\x80\x14\x38\xd6\x50\xe6\xb3\x8e\xa8\x52\x50\x48\x91\x5b\x5e\xb5\xa0\x48\x43\x52\x70\xee\x77\x9d\xc8\xe1\xac\x12\x7a\xb0\xa9\xfa\xa1\x65\x6d\x85\xa8\x93\x1f\x15\xd4\x4d\x32\x52\x10\x62\xfa\x30\xac\xca\x5c\xe9\x6d\xf8\xb4\x62\x36\x18\xd4\x7d\xe4\xb6\x44\x48\x05\x97\xa2\xb0\x62\x72\xde\xd3\xe5\x3a\xd3\xae\xd0\xa8\xbd\x2c\x05\x10\x1f\x04\x52\xc9\xe6\x55\xe6\xa1\xde\xd0\xa8\xeb\xb9\x91\x03\x68\x58\x33\x14\x88\xb0\x2c\x42\x81\x1f\x17\x63\xcb\x54\xc7\x02\x43\xaa\x14\xc8\x54\xc2\x7c\x86\x9e\x12\x04\xbd\x75\xca\x3d\x96\x57\xb0\x92\x7e\xc9\x5f\xb6\xaf\x4a\xee\x67\x99\xa1\x95\x7c\x10\xa7\xf1\xe3\xef\xe2\x6a\x20\x55\x3d\x8a\x33\x9d\x4e\x82\x5c\x59\x2e\x78\xde\x21\x78\x6e\xdd\x77\x03\x8c\xb1\xb9\x16\x62\x41\x8a\x7c\xb6\x12\xea\xa8\x4b\x36\x0f\x78\x08\xb4\xf7\x87\xeb\x8d\xc6\xe6\x3a\x47\x34\x3a\xe5\xe4\x80\xdb\x2a\x0c\xae\x0a\x9f\xfb\x5c\xef\x02\xf5\x82\x4b\xcc\x80\x1e\x8d\xb4\xf6\xd0\x83\xd9\x71\xba\x59\xdf\x73\x11\x13\x5b\x2a\xb4\x6f\xc8\x95\x89\x6c\x95\xa6\xce\xdb\x4f\x69\x22\x47\xc2\x85\xad\x9c\x20\x5f\x07\xd6\x36\xea\xe0\x89\xec\x83\x92\x0f\x63\x9b\xec\xe2\xe4\xfe\xca\x87\xfc\x0f\x34\x28\xf1\xe1\x30\xe7\x8a\x7a\xd9\x0f\xd6\x6e\x7a\x2e\x2e\x8e\x86\x3c\xa9\x34\x5b\x2f\x23\x35\x89\xa1\x9e\xb5\x46\x38\x33\xbb\xfe\x13\xd3\xc0\x88\x73\x9b\x0d\x0a\xea\xac\xea\xe8\x73\xc1\x18\xa3\xf8\x46\xd7\x20\xc9\xba\x37\x74\x98\x3c\xe7\xb9\x4b\x1c\xa3\x00\x6b\x3a\xd3\x8f\x64\xd8\xab\x8c\x27\x74\x06\xeb\x6f\x7b\x4a\x3a\xbb\x1c\x0a\x3a\x30\x54\x31\x73\x80\x63\x38\x35\x60\xa4\x59\xeb\xbb\x16\xcb\xd2\x66\x10\x98\xa3\x90\xcb\x94\xca\x89\x06\xbd\xd9\x26\x0f\x9b\x68\x16\x56\x1b\x11\x7a\x86\x87\x2f\x41\x10\xf1\xd0\xd4\x20\x81\x9a\xfb\x5c\x15\x4a\x93\x4c\x17\x28\x10\x8c\x32\x37\xa6\x15\x9c\x46\xc9\x1e\x5a\xa1\x7a\xc9\xe9\x40\xdc\x29\x86\x87\x0d\xd6\xb8\x64\x07\xf4\x4e\x75\xbc\x31\xed\xff\x0d\x40\xd9\xd4\x17\xc1\x82\xb7\xee\x05\xa0\x48\x12\x58\x2b\x8f\x40\x1d\x9a\xe0\x1f\xa3\x86\xd6\xd6\x2e\xb8\x5b\xb6\x07\x5d\x35\xd9\x1c\x91\xa1\xbb\x94\x26\x67\x4b\xd0\x9b\xa0\xa2\xda\xb3\xf6\xee\x51\x00\x11\x56\x46\x68\x65\x45\x38\x01\x45\x37\xcc\x8d\xa0\xd4\x91\x13\x44\x91\xc5\xfd\xdf\xa7\xd0\x22\x2a\x51\xb1\x5e\x85\xca\xb2\x16\xa6\xe5\x97\xda\xed\x21\x00\x04\x52\xa4\x65\xa4\x24\xeb\xb1\x2e\xef\x91\xa0\xa1\x49\x1d\xde\x6c\x7d\x94\x93\x99\x56\xeb\x38\xe6\xbd\x52\xe9\x28\x5b\x07\xcf\xfb\x16\x0e\xbf\xf1\x80\xe8\x47\xf0\xbc\x88\x13\x5d\xd5\x57\x64\x7b\x6e\x9d\xf6\x9f\x4e\x3b\xae\xb6\x1d\x77\x78\xde\xf5\xf9\x28\xfb\xe3\xfd\x5e\x20\xf6\xef\x8b\xc3\xde\x7e\x3b\x10\x7b\xc9\xd5\xb7\x0b\xb0\xe0\x9d\x32\x4e\x66\xea\x44\x6d\x51\x0c\x05\x15\xbd\x9a\x56\xcd\xe4\xbd\x0b\x99\x85\xaa\xba\xc4\x5e\x98\x93\x92\x86\xc4\x35\xf9\xe3\x38\x04\x07\x4d\x5f\xf4\xed\xde\x42\x51\x26\xca\xa5\x4e\x6b\xcb\x80\x74\xd4\x96\x47\x86\x32\x2d\xb4\x85\x83\x48\x96\x25\x67\xd0\xe8\xe5\x95\xa3\xcd\x5c\x4e\x7b\x59\xe9\x9b\x4e\xc4\xaf\x96\xa8\x19\xd3\xb6\xab\xfb\x65\x6a\xaa\x04\xc7\x18\x29\x74\x97\xb2\x59\x02\x10\x18\x2e\xb2\xcf\xe9\x1d\x64\xcf\x24\x73\xea\x59\xc3\x6c\x7a\x5b\x2b\x86\x77\x0a\x44\xc0\x64\x57\x68\x75\x5b\x07\x79\x26\x78\xf9\xba\x31\x65\xa9\xc8\xd4\xf3\x09\x10\x97\x28\x93\x48\x2a\x18\x68\x4d\xf3\x8a\xd0\x86\xb0\x3a\x5c\xa7\x9b\x31\x0c\x0f\x1f\xb2\x31\xd3\xd6\x5d\xc4\x08\x9d\x67\x0f\x05\xbf\xac\x52\x73\xaa\xbf\x77\xbf\x9c\x8f\xf2\x5f\xbc\x44\x78\x1c\x24\x7e\xa7\xcd\xe7\x11\xaf\x3a\xc6\x25\xe9\xdd\x2e\x95\xf6\xe7\x25\x35\x65\xaf\xb4\x57\x94\xba\xc7\x9a\x98\x79\xe3\x28\x05\xda\x29\x43\x4f\x32\x56\xb6\x42\x6c\x3d\xe4\x24\x9b\xb6\x90\xf3\x41\xca\x25\xba\x49\x9f\x41\x09\x5f\xc5\xe7\x05\x50\xc5\x66\x88\x36\x38\x37\x02\x42\x5b\x7f\xd4\xb5\xa8\xd9\xba\xc2\x6a\xb6\x3c\x3c\x41\x58\x27\x48\x2d\x88\xac\xa0\x52\x96\x50\xa9\x96\x76\xaa\xd8\xa0\x85\xde\xe6\x80\xb9\xe2\xf9\xdd\xe6\xa2\xc6\xd0\x10\xf3\x2c\x6c\x5e\x89\xa8\x20\xbe\x83\xf3\x32\x76\xf4\xca\x32\x33\xd4\xd6\xbb\x3a\xe7\x78\x86\xe8\xb3\x4b\xfa\x60\x08\x62\x8a\x96\x31\x17\xd8\x3b\x58\x12\x07\x8a\x8c\xe3\x33\x98\x0c\x01\xb1\x76\x48\xe8\x14\x06\x98\x43\x34\xb3\xae\x4a\x98\x61\x0e\x56\x94\xc1\x1f\x28\x75\x03\x20\xc6\x96\x91\xb5\x99\x31\x15\xa8\xfd\x95\xf3\xe6\xd2\x60\x34\xbd\x15\x22\x63\xbe\xdc\xfa\x1a\xb4\x23\xe3\x7c\x99\xf1\x54\xf7\x11\x85\x88\x42\x33\x75\xee\xe0\x82\x83\xef\x52\x29\xa2\xad\x90\x19\x37\x0b\xc0\x6c\x63\x36\x20\xd5\x40\x59\xbb\xdf\x36\xa9\xf8\x0c\x66\xa1\x0c\x0c\x61\x62\x15\x24\x95\xb5\xe4\x80\x9a\xe2\x20\x53\x8f\x22\x05\x61\x87\x45\x19\x9e\x68\x5d\x07\xab\xeb\xc0\x15\xd1\x29\xe9\xee\xf1\x0e\xfb\x1c\x42\xd4\x15\xfc\xaa\xbc\x3f\x95\x02\x4a\x82\x92\xe4\x50\x20\x45\x48\x81\x25\xc4\x1a\xd0\x4c\x1a\x18\xe6\x28\xcf\xd5\x40\xbc\xae\x32\xdb\x24\x3d\x18\x87\xb5\xb1\xdc\xcf\x2f\xcd\xc1\x56\x5e\x6b\x8c\x8d\x6b\x7e\xf6\xab\x32\x76\x29\x36\x95\xe6\x84\xe2\xe5\xea\x31\x68\x40\xb1\xd2\x33\xea\x6b\xb3\x5a\x87\x10\x12\xec\xb7\xb4\x22\x92\x8d\x5c\xa9\xb8\xec\xeb\x2e\x9a\x17\xb5\xb5\x47\x2c\xba\x16\x4a\x84\x1e\x7f\xdc\x9e\x87\xae\x64\x2a\xd3\x1e\xf6\x0b\x6e\x7e\x8b\x55\x50\x7a\xfd\x7c\x00\x44\x53\xd3\x08\xee\x33\x47\x81\xdc\x1a\x0d\xa9\x96\xa0\x89\xc5\x4a\x79\xb0\x76\x52\x10\xd1\x5c\x4f\xc5\x2c\x6b\x8e\xdd\x86\x2a\x60\x38\x47\x36\xd2\xf3\x04\x2f\xdf\xd0\xf0\xe5\x8a\x76\xcf\x2b\x13\x1e\x21\xab\x13\xdd\x22\x97\xc6\xda\x8b\xd6\xcf\x65\x44\x58\x6a\xa7\x32\x5e\x9f\x69\x59\x2b\x35\x27\x9d\x1c\xb8\x50\xd5\x53\x15\xf2\x9e\xa4\x1f\x01\x79\x40\x0d\xa3\xac\x52\xa1\x7b\xaf\x88\xce\x6b\xce\x54\x9d\x2f\x09\x4b\x82\xf5\x15\x00\x43\x8a\x99\x13\x39\x68\x2e\x88\x8d\x8c\x1c\xb4\x96\x30\xf2\x1e\x29\x41\x58\xab\xae\x90\xcd\xb7\x89\x5b\xa9\x10\xa8\xb3\x3a\x16\x3a\x37\x79\xbb\xbd\xe8\x3b\xd7\xec\xf5\x85\xf9\xf9\xdc\x77\xac\x01\xea\x44\x64\x04\xf9\x0a\xd8\xf5\xf7\x28\x42\x92\x66\x2c\x98\x3e\x5a\xc1\x07\xad\x8c\x6b\x63\xfe\x65\x51\x3e\xf4\xc0\xca\x33\x7f\x27\xd0\x71\x2f\x28\x62\x6d\xce\x35\xbb\x5b\x46\xe0\x61\x6d\x6e\xed\x11\x70\xac\x2e\x86\xbf\x22\x0c\x8f\xae\xdb\xac\x4d\xa2\x12\x3d\x0c\x33\x12\x4e\x82\xad\x08\xde\xea\xb9\x07\x6d\x47\x06\xc9\x56\xbd\xba\x4a\x0f\xa0\xcb\x99\x41\x75\xae\x66\xf1\xe7\x96\x42\xe9\x35\xb4\x84\xd2\x92\xe1\x48\xf1\x62\x1f\x24\xd7\xb2\x42\xce\xb4\x04\xe5\x4c\x08\xf8\x5d\x85\x70\xaa\xa0\x2c\x1f\x52\xd4\x98\xfa\x57\x18\x6c\xe6\xac\x99\x0f\x2b\xdd\x7d\x62\x94\xd5\x64\x2a\x1c\x32\x20\xdf\x9e\x1a\x8a\xca\xf8\xe1\x91\xb5\xec\xac\x51\x21\xcb\xb3\x75\x5e\xce\xe9\xd3\x2c\xd5\xae\x1a\x44\x61\xf0\x7b\x88\x53\x10\x4c\xcd\x1d\xca\xa3\x3b\x35\x75\x05\xc3\xe6\x8a\x11\x55\x7a\x50\xf5\x25\x47\x0e\x43\x92\x94\x81\x2b\x54\x61\x6b\xa8\x12\x54\xda\xdb\x0d\xa5\xd6\x28\x9e\x1d\xcd\x47\xb3\x43\xc2\x18\x07\x2a\x70\xf9\x91\xca\xd4\xc6\xc6\x17\x55\x38\x22\x4e\xb0\x3b\x90\x58\x41\xd1\x8f\xf9\xd6\x28\xa6\x4a\xe8\x06\x36\x58\xf5\xed\x67\xcb\x36\x1a\xeb\xbd\xeb\x00\xeb\x05\xb5\xbb\xad\xaf\x23\x16\x23\x61\xc2\xb9\x61\xad\x23\x35\x45\xe7\x33\x8c\xad\xf9\xeb\xec\xd0\xff\x51\xc7\x35\xcb\x7f\xa5\x5c\x3e\xa1\x56\xad\x5b\xeb\x18\x7b\x9c\xf2\x33\xea\xd6\x06\xc6\xa0\x2f\xa8\x5b\xf7\x80\xe9\xa7\xcc\xad\xe9\x73\x02\x5b\xe8\xb4\x81\x99\x7e\x7e\x25\x8a\xd3\xb3\x6b\x12\xe4\xfa\x3b\x0c\x4d\x00\x7e\xfe\x5a\x3c\x7a\xfb\x80\xf9\x29\x57\xa5\xe6\x40\xcf\xbf\x2b\xbe\x63\xaf\xf7\x17\xc8\x65\xc7\x35\x95\xf7\x65\xd5\x6e\x26\x59\xd7\x5d\x66\x5f\x81\x84\x06\xe2\x14\xf1\x14\xeb\xfe\x2c\x21\xa0\x12\x8e\x48\x65\x8e\x8a\x85\x6f\xbb\x25\x92\x36\x17\x53\xcd\xba\x51\xb3\xb7\x6d\x44\xcc\x5b\xd7\x06\x7e\x15\x3c\xe9\x83\x02\xc7\x79\x30\xb2\xa9\x14\x63\x15\x73\x66\xc1\xd7\xde\xeb\xdd\x16\x9d\x03\xf7\xa7\x21\x17\x50\xd4\x0d\x7d\x48\xa6\x06\x8e\x99\x4f\xb6\x3a\x61\x27\xd0\xfc\x54\x68\xbc\xdb\x0a\x8c\xf3\x10\x99\x2d\x5b\x2e\x84\x83\xfb\x89\xa0\x13\xe0\xdf\x36\x06\x6f\xcb\xed\x1e\xa5\x8f\x55\xa1\xe5\x9d\x82\xcc\x16\x6a\x43\x5d\x38\x3c\x69\x0a\x1d\x63\x06\x52\x9e\x96\xa1\xce\xbb\x45\xfa\x11\x84\x2a\x30\x04\xe8\x24\xf6\x9a\x3d\x10\x85\x05\x67\x8d\x59\x81\x31\xad\x39\x34\x71\x31\x5f\xd1\xe9\xa4\x4b\x5a\x07\x42\xc5\x70\x8f\xc9\xd9\xd6\xf2\x86\xd0\x84\xe4\x69\xbd\xa7\xf7\x55\x01\x36\x83\x71\xd6\xf3\x26\x09\x89\xa4\xba\x16\xbb\x10\x42\xd3\x01\xc6\x26\x9a\x71\x83\xc2\x70\x45\x42\xad\x0c\xc7\xad\x9b\x1d\xbb\x14\xb3\xb8\x53\xba\x01\xbd\x29\x84\xd4\x24\x54\x7d\xbd\xe8\x4a\xd7\xfc\xd8\x7f\x9c\x58\xde\x84\x15\x97\xb6\x6e\x32\x0a\xc3\x7f\x94\x6b\x0e\x92\xde\x85\xdd\x09\xe0\x62\x08\x73\x22\x43\x80\xdf\xa9\xd3\x39\x42\xf3\x53\x78\x86\xe4\xc0\x80\x54\xf7\x16\x2a\x36\x57\x67\x50\x4c\xc8\x98\x6b\x04\xaf\x85\x75\x83\x66\xbd\x69\x80\xbc\x55\xa1\xd8\x2d\xc1\x66\xe6\x55\x40\xca\x1d\x18\x7c\x9a\x2b\x04\x2f\xb4\x78\x17\xd3\xb6\xda\xac\x39\x07\xd7\x7b\xb1\x41\x0f\x0c\x69\x0b\xe6\xc1\x46\xc8\x4e\x61\x4a\xe9\xd6\x1b\xe0\xce\xd6\x8a\x9c\x91\x54\x5d\x5a\x68\xb7\x15\x5a\xef\x41\x6b\xb0\xdd\x21\x66\x78\xa7\xaa\x2b\x88\x08\x3a\x74\x9b\xea\x78\xfb\x39\x75\x86\x96\xca\x42\x5a\xad\xb6\x30\x0a\xb2\x42\xce\x00\x52\x03\x08\xde\x22\xba\x45\xe0\x66\x44\x0c\x96\xe8\xb6\x19\x24\x2d\xb1\x69\x68\xb2\x5f\x60\x75\x01\x76\x78\x32\xd0\xf9\x60\x2a\x57\xda\x12\x15\x72\x04\x83\x71\xa3\x41\x38\x68\x0f\x28\x87\x6f\x2d\x58\xa7\xb6\x1f\x14\xb8\xb7\xff\x8a\x75\x22\xd4\x7b\x04\xbb\xc2\x58\x1b\xe3\x57\xb1\x2e\xad\xf2\x69\x41\x0f\x64\x87\x74\x80\x18\x25\xdf\x56\x64\x17\x6d\x8e\x0a\xb1\x94\x37\x0a\x80\x10\x30\xe7\x20\x3d\xfb\x14\xd0\x3c\x81\x2b\x52\xf7\x69\x64\x90\x45\x00\xff\x33\xdb\xaf\x66\x9f\x2b\x4e\xe1\x06\xe4\x58\xc1\x6d\xdf\x90\x50\x80\x3a\x3d\x28\xee\x51\x1d\x8f\x26\x36\x63\x23\x41\x80\x7c\xda\xb0\x2a\x39\x94\x62\x9f\x57\x5a\x00\x4e\x5a\xd7\x4c\x5b\x6f\xc2\x97\xeb\x77\x79\xe4\x3c\x1f\xba\xda\x82\xde\x00\x33\xd0\xac\x00\x3f\x43\xa2\x14\x02\xec\x79\x65\xed\xac\x92\x3c\xc8\xc6\x18\x29\x31\x5d\x53\xb5\x87\x5d\xc1\x5d\x2b\x78\xee\x77\xd9\x68\xf8\xbf\x89\xe1\x53\x18\x47\x03\x0d\x23\x36\xd6\x57\x69\xb6\xfc\x97\x12\x4a\x5e\x04\x15\xc9\xf8\x17\xaf\xd1\x10\x3c\xcc\xab\x24\x86\xf6\x1b\x55\x91\xbb\xd3\x17\x03\x0d\x27\x0c\xa6\x75\x59\x63\x17\x48\xcd\xdb\x78\xe8\x42\x82\x3d\x04\x45\x07\xc0\xd0\x18\x5d\x28\xd2\x44\xfc\x3a\x3d\x62\x41\x94\x2f\xc1\x2d\xd7\x82\xf2\xcd\x75\x92\xc0\x65\xa7\xdd\x03\x1d\x72\xa6\xc6\x2c\x7c\x7b\xf3\x5b\x69\x68\xc0\xb6\x47\xb8\xa3\x08\xc0\x53\xe0\x73\x01\xa7\x4b\x36\x6f\x0f\x12\xfb\xe4\x72\xc8\xa8\xc0\x71\xf6\x10\xfc\x6f\xe6\xfb\xe8\x0b\xbc\x55\xe2\x34\x76\x46\x2c\x97\x0b\x38\xd6\x78\x20\xd5\x33\x93\x43\xc1\x69\x6f\x18\xb5\xae\x0e\x64\x79\x34\x2a\x06\xd7\x70\x60\x5b\x58\x70\x27\xf2\xa3\xde\x47\xef\x34\x10\xad\x29\xab\x2f\x4a\xb5\xde\xe3\x10\x79\xc4\x32\xf2\x1d\xd4\x0a\x98\x3b\x34\x80\xd1\x79\xe0\xbb\xa4\x69\x13\x83\x66\x09\xa5\xc1\x94\x33\xe3\x01\xfd\xf0\xb6\xed\x5d\x73\xb5\xd5\x69\x48\x38\x3a\x2f\xa6\x12\xd1\xc0\xfe\x3d\xa1\x08\x61\xfe\x95\x8e\x15\x29\x81\x49\x6c\x21\x53\x01\xc3\x43\xef\x50\x54\x01\xd3\x8a\x87\x62\xad\x67\xb3\x2a\xaf\x85\x4e\x84\x25\x42\x7c\xa9\x07\xc9\x30\xfa\x7c\x32\xe3\xcc\x73\x14\x27\x35\xe5\x4c\x81\x02\x77\xe6\x32\x58\x1e\xc4\xc8\x47\x1e\xd6\xbf\x31\xac\x6d\x1a\xcc\x29\xd4\x1e\x74\xce\x50\xfb\x2a\xb0\x94\x33\x41\xb5\x2b\x39\x1b\x47\x50\x6a\xee\xbf\x82\xa1\x8e\x4b\x12\xb8\x5f\xea\x94\xcf\x76\x44\xad\x12\x5a\x32\xcf\xbe\x05\x6d\xc1\xec\x18\x4a\x37\x6f\x98\xb2\xb2\xf3\x46\x12\xbd\x53\x20\x68\x82\x05\x14\xcd\x66\x5e\x29\x60\x79\xbd\x6c\x28\x2a\x8a\x15\xda\x29\xee\xfb\x9c\xd5\x30\xb2\xcd\x59\xac\x9f\x62\x25\x95\x20\x1a\x28\xe6\xe0\xc1\xb0\x0e\x92\x90\x2e\x47\xc8\x62\xf5\xef\x93\xd8\xc1\x50\x52\x3f\x42\x27\xf7\xa4\x3a\xd7\x25\xaa\xc8\x50\x28\x2c\x3d\xe4\x84\x6f\xd4\xd6\x8c\x50\x82\x8d\xcf\x39\x01\x29\x97\x09\xce\xba\x3c\x61\xe0\x9b\x65\xdf\x2b\xd6\x53\xd6\xf6\xb7\xe0\x49\xc0\x13\xb0\x20\x81\xab\x19\x76\x07\xf4\x2c\xb0\x16\xf9\xac\x5f\xd8\x37\xe6\x96\x82\x16\x5b\x17\x8a\xf9\x41\xb0\x11\xc4\x75\x76\x3c\xd0\x16\xba\xab\x02\x51\x76\x44\x3b\x34\xd8\x61\xec\x62\x34\xd5\xb0\x93\x1c\x45\x37\x53\xf2\x9e\x2c\x01\x3c\x25\xee\xe3\x90\xb9\x91\x10\x65\xb7\xdd\x36\x5b\x87\x80\xad\xae\xe0\x11\xc1\xe5\x28\x12\x03\x5e\x94\x25\x0a\x47\x2a\x3a\x58\xe9\xa1\x24\x2a\x53\xa7\x9b\x0d\x8b\x1e\x6c\x60\xc9\xd6\x41\x72\x87\x81\x51\x42\x83\x64\x0d\x01\x52\x3f\x48\x26\x86\x25\x76\x38\x93\x50\x69\x1b\xab\xbd\x16\x9a\x0c\x4b\x84\x93\xae\x2e\xcd\xc4\x68\x11\xb0\xd9\x9b\x75\xd7\x3a\x58\xcb\x61\xdd\x1b\x98\x08\x01\xf2\xc3\x86\x0c\xa0\x9b\xf6\x6d\xfa\xd1\xd8\x28\x82\xc1\x5d\xc9\xc8\x84\xf8\xc8\xd3\x7f\x3a\x38\xe8\x59\x45\x36\x32\x2c\x6e\x2e\xa3\x8a\xc9\x77\xc0\xc0\x90\x5a\x30\x23\xcb\x93\x8d\x76\xe4\x8d\xc2\xf6\xb5\xdf\x36\x1b\x67\x88\xe3\x31\x28\x83\x98\x21\xa2\x0e\x36\x75\x11\x22\xd2\x30\x07\x04\xb3\xaa\x73\x01\x4c\xd6\xe6\x9b\x7a\xa4\xb5\x9a\x7f\x00\x06\xb2\x44\xc9\xe7\x42\x70\x30\x0d\x6e\x86\xa9\xbd\x6a\x7d\x96\xc0\xcb\x02\xc6\x27\x32\xcd\xea\x83\xbb\x90\x46\x98\x08\x91\x1d\x52\xde\xe4\x88\x46\xaf\x26\x6b\x21\x48\x67\x76\xf2\x58\x14\x73\x21\x2a\x89\x82\x50\x92\x5c\x38\x4b\x14\x4a\x35\xc6\x7c\xfb\xd9\x10\x99\xe8\xee\xb6\x76\x86\xc2\x6f\x6b\xe3\xd8\x45\xc2\x57\x75\xb5\xc6\x42\x59\xa2\x39\xd0\x2b\xcc\x0a\x33\x2e\x24\xc9\x43\x9a\xae\xf8\x38\x18\x56\xc2\x37\x74\x5e\xdf\xcc\xf0\x77\xf7\xd4\x09\x1d\x69\x29\xaf\x43\x73\x97\x5a\x87\xfe\x15\x38\x80\xa5\x37\x3a\xd2\x07\xa2\x2d\x5f\x0b\xc3\x38\x2f\xc5\x77\x85\x61\x44\x07\xf5\xcf\x2f\x4e\x5c\x2b\x9f\xe8\xa7\xba\x14\xe2\xef\x9f\x45\x7e\x70\xb3\x66\xa9\x93\xa2\x63\x5c\x05\x54\x6f\x1f\x08\xb4\x7f\x2c\xcd\xfa\x4e\x2d\xff\x10\x66\xa5\x9a\xdf\x17\x37\xf8\x87\xaf\x8f\x6f\x13\x4f\x5a\x93\x54\x23\x84\xb0\x64\x49\xae\x07\x58\xca\xb8\xdb\xb4\xf0\x7d\xbf\x5c\xb5\xdc\x0e\x32\xd4\xeb\xee\xf6\x11\xe4\x13\x02\xa2\x98\x7d\xbe\x41\x1b\xad\x5a\x9c\x75\xf3\xbd\xd4\xc9\x47\x0f\xa9\x2f\x19\xd5\xc7\xa5\xde\xa1\x5f\xe0\x13\xe7\x0e\x6d\x9f\xbd\x48\xfb\xfc\xfd\x6b\x6f\xdf\x7a\x0d\x3b\xee\xd7\x07\x26\x29\x00\x09\xe9\xed\x6b\xfc\xfa\x61\xa8\xcb\x29\x69\x7c\x26\xf3\xfb\xf1\xb7\xfe\x76\x0f\xda\x19\x33\xae\x37\xb8\xfd\xb9\x3b\xb4\x56\xc0\xe2\xfb\x5f\x69\xfc\xdf\x7e\x9d\x00\x7e\x5f\x84\x6a\x5c\xd2\xc3\xfd\x5a\xdf\x7d\xee\x68\xb6\xd0\x56\x01\x48\x3e\x16\x58\xae\xc4\xfd\xa3\xd5\xad\x41\x09\x86\x67\x3a\xcc\xec\x35\x38\xe7\xc4\xb7\xef\x1f\x47\xd5\x0e\x2b\x2d\xf0\x02\xb8\x84\x2a\xbe\xc4\xc2\xf2\x07\x47\xdf\xcb\x18\x27\x74\x7c\xb6\x23\x74\xe1\x79\x76\x9a\x5d\x87\x9f\x74\xf1\x5b\x8d\x85\x37\x07\x27\xc7\xe4\x07\xc6\xb3\x2d\xfe\xbc\xb8\xd7\x24\x91\x01\x1e\xe8\x78\xca\x71\x5c\x63\x9d\x3b\x18\xdb\xba\x30\x0e\xf6\x68\xed\xbf\xe2\x18\xf8\xbb\x86\xc0\xed\xbf\xc6\x18\xf8\x03\x43\xe0\x92\x08\xef\x17\x49\xf6\x77\x71\xd1\x94\x43\xed\xba\x44\xfb\xe2\x20\x8f\xfa\xb5\x7b\x63\x14\xe8\x18\x40\x6f\x7c\xaf\xff\x2a\xe5\xb1\xd3\x52\xc0\x08\x58\xbe\xdd\x7f\xff\x59\x93\xf3\xed\x5f\xa7\x67\xfe\xb3\x3b\xe6\xed\x3f\xab\x67\xce\x4b\xc6\xb9\x7f\x50\x6e\x7d\xf4\x4c\xa8\xbe\xa1\x76\xa7\x1d\xea\xef\x2c\x5b\xac\x8f\x38\xa6\x2c\x66\x5a\x15\x9d\xab\x74\x44\xfa\xec\x4b\x7d\x78\x6c\xee\xf3\xdb\xc7\x82\xf9\x7e\xaf\xb3\x9c\x5e\x65\x59\x9d\x27\xa5\x41\xe3\xfd\xa8\xb4\x24\x0b\x66\xa9\x0f\xec\x60\xa9\xe5\x0c\xe4\x8b\x24\x5d\xe4\xab\x06\xb9\xa4\x51\xfb\x57\x62\xf5\xd6\xf3\x4b\xd9\x95\xf8\xe0\xbd\x3d\x62\x23\x01\xea\x87\xcf\xab\xe3\xc3\xc7\xb5\x53\x9a\xba\xea\x2c\x2a\x2b\x7c\x54\xa1\xb1\x41\x23\x93\xb9\x3f\x6d\x02\x5a\x25\x00\xff\x8e\xad\x63\x27\xb6\xb0\x61\x3b\x6d\xdf\xfe\xd3\x77\xf8\x75\xb3\xe8\x2f\x83\x60\x3b\x8d\xa8\x15\xf9\x5f\xc7\xa7\x21\x36\x49\xf1\x96\x67\x70\xf2\x3c\xa0\xb6\xe3\x1a\x5f\x41\x03\x5e\x35\xfc\x25\xd1\xd7\xbf\xa4\xbc\xee\x48\x44\xe4\xb9\x3a\xf1\x8e\xec\xde\x76\xf2\x35\x97\x82\x34\xf2\x54\x64\x26\x51\xde\x2e\x22\xf8\xc1\x47\xd0\xda\xae\x5d\xa6\xf6\xf6\xf8\xa8\x2b\xd9\x97\xfc\xa8\xb7\xb6\x72\xb7\x09\xfb\xc4\xae\x4a\x06\xb7\xac\xe9\x0e\xcd\xf8\x2a\x9f\xf7\xe6\x4f\x7a\x07\xe5\xe7\x5b\x4a\xa1\xb7\x71\xfb\xf0\xb6\x7c\xf6\x8f\xaf\x8a\xf7\x3d\x29\x4f\xb3\x71\xd0\x36\xde\x70\x62\xfd\x60\xc3\xbf\xcb\xbe\x4f\x07\x05\xa9\x83\x0e\x7b\xa3\x87\x4c\xe5\x0b\xd8\x46\xed\xed\xd5\xf7\xbc\xe4\x02\xfb\x57\x74\xc3\x9a\x14\xe4\xa3\x75\xc5\xe7\x02\x80\x2b\xd6\xfc\x88\x87\x9a\x4f\x62\x50\x37\x37\x92\x9a\xd9\x37\x6e\x94\x71\x68\x60\xa6\xc6\xde\x32\x42\x5a\x62\x93\x16\xb4\x34\x6e\x40\x23\x01\xdd\xa2\x92\xca\x94\xa5\xf7\x18\x39\x41\xd8\x3f\x1c\xf5\x44\x61\xeb\xb1\x92\x6c\x4d\x42\x6e\x9b\xc2\x64\xb4\x1b\xd9\x7d\xd4\x16\x89\x80\x9b\xec\x97\x5e\xfc\x66\x2b\x48\x32\x91\x0e\x68\x6f\xa0\x4e\x90\x4c\x5f\xbf\xa7\xa5\x22\x4a\x95\x6d\x9d\xe8\x69\x67\x40\xeb\xf9\xb6\xef\x2e\x25\xa8\xf4\x7d\x2f\xf2\xc7\x89\xbf\x2e\xd1\x76\x46\xdb\x8b\x63\x5f\xb5\xfa\x25\x6d\xd6\xbf\x2a\xb9\x3b\xa6\x98\xcf\x68\xaf\x1e\x14\x39\xd9\xdb\x1f\xa0\x56\xe7\x74\x20\x27\x2e\xc9\x4e\x6a\x88\xe5\x3d\xcf\xd6\x9e\x4e\xc7\x45\xfc\x1a\xf6\x5a\xdd\xfa\x9f\x9d\x6f\xa7\xf7\x00\x28\x5e\x79\xfb\x29\xbd\xa5\x7f\xd6\x93\xdc\xbe\x7e\x94\x83\xa7\x12\xb4\x4b\x25\xc4\xbc\xc0\x0c\xb3\xa3\x50\xf4\xe6\x82\xe7\xf3\xf9\x44\x27\xf2\xb2\xa3\xce\x20\x4e\x46\x80\x9d\xe4\x95\xb6\x1c\x9e\x54\x06\xc7\xdc\x08\x3a\xf7\xa6\xf1\x3a\x83\x67\x99\xc1\xeb\x62\xb1\x79\x0d\x92\xbf\xe2\x3c\x65\xc1\xd3\xef\xd2\xe6\x6d\x1f\x52\xc2\x6d\xcf\xf3\x8e\x8b\x39\x25\xe5\x3f\xe1\x36\x25\x8d\x17\xb7\xb9\xfd\x91\xfb\x9c\xcb\xc4\x80\x58\x50\x42\x8e\x77\xf8\x79\xd4\x9c\x6d\xa6\x4d\x21\x0e\x62\xf3\x99\x45\x55\x41\x6e\x33\x82\xb9\x14\xff\x94\xcc\x8a\x65\x98\x8f\x44\x51\x36\x22\x6d\x91\x73\x86\x83\x0b\xde\x06\x9c\x87\xce\xa8\x29\xe4\xbe\xd6\x40\x7d\x2a\x54\xf2\x6f\x40\x7d\x3c\x85\x61\x51\x0c\xa1\x85\x50\x19\xe5\x2b\xdc\x36\x4d\xa1\x0c\xb2\x67\x13\x93\x8c\x24\x3e\xb5\x1b\x4b\x83\x81\xc8\xfc\x86\x32\xf5\x85\x6c\xbe\x36\x2a\xb8\xdb\x7b\xda\x6b\xf2\x2d\xed\x25\xed\x1d\xed\x15\x07\x81\x75\xfe\xae\xdb\xf1\xfe\xcf\x46\x79\xd5\x65\xaf\x41\xd4\xaf\x6a\xd4\x9e\x5d\x36\x1e\x5f\x39\x9e\x3e\x73\x3c\x75\xa7\xd3\x57\x7e\x7e\xe4\xe7\x37\x7e\x7e\xe2\xf8\xfc\xc6\xf1\xd2\x67\xff\xde\xfb\x3c\x3b\xed\x17\xf7\xb9\xfd\xe3\x37\x02\x39\x91\x93\xd3\xc1\x29\xca\x24\x9a\xd8\xd3\x43\xea\xb0\xb0\xed\x99\x5f\xf6\x72\x35\x75\x0e\x29\x2f\xf4\x4e\xac\xec\xed\xf5\x47\x5d\x46\x0f\xb1\x26\x00\x7a\xa1\x3d\x67\x2b\x29\xc4\x00\x30\x34\x74\x95\xaa\x01\x75\x75\x35\x48\x97\xa5\xe4\x90\xc7\x52\x7b\x88\x6d\x6d\x48\x55\x82\xe7\x76\xec\x90\x11\x3c\x11\x1e\xc8\x9e\x07\x8f\x73\xdb\xf8\x38\x2c\xac\x7d\x6e\x1e\x07\x6c\xf1\x79\xda\x5f\x19\x9b\x9d\x05\x0e\xa5\x06\x1b\x99\x48\x35\x77\x24\x85\x60\xe8\xea\x4a\x24\x62\x71\x7e\x4d\xd5\xfb\xb3\xd8\x41\x7b\x60\x81\xb3\x2d\xf6\xdd\x16\x12\x67\xca\x42\x55\xb2\x02\x23\xb3\x15\xce\xdb\x4b\x0b\x73\xeb\x01\x35\xf7\x61\xae\x3d\xa0\xd2\x01\x29\x1b\x14\xc6\x98\x6f\x46\x52\xe4\x0d\xf9\x87\x2a\xb7\x4d\x7b\xa8\x73\xd3\x16\x48\xc9\xd7\x03\x38\x8c\xa8\x30\xaf\x69\x97\xde\x1c\xe2\xa2\x9c\x5d\x82\xa2\x1e\x1d\x15\xb0\x20\x2b\x46\x0d\x2c\x15\xed\xca\xa0\x56\x3d\x90\x1d\x54\xad\xe7\x5c\xd3\xfc\x8c\xc8\x53\xc0\x20\x54\x5e\xd7\xf1\xcf\x6b\xa8\xf8\x4a\xed\xf9\xde\x27\xca\xa5\x62\xd5\xd4\x59\x1f\xb1\x4e\xf1\x50\x86\xce\xf6\xa8\x53\xdf\x7e\x62\x60\x73\x0f\x0f\x6b\xbb\xbf\xa3\xfd\x7a\x82\x70\xe7\xcc\xed\xdd\x45\x5f\x3d\xf6\x35\xf0\xf8\x65\x35\x5a\x4f\x33\x48\xc2\xac\x0d\x1f\x02\x24\xbb\x1a\x62\xab\xa0\x92\xc4\x1c\x0e\x66\x0b\xc5\x16\xd1\xe7\xe8\x3a\x09\x45\xa9\xc8\x4e\x35\xd7\x40\x2c\x43\x01\x47\x53\x3a\x66\xdd\x36\xb0\xf4\x27\x2f\x22\xef\x6d\x89\xbd\x87\x09\x96\x6f\x15\x64\x33\xc9\x18\x93\x51\xdd\x8a\x4a\x75\xfb\xa4\x23\x28\x2c\xf2\xb6\xce\x1a\x66\x20\xf9\x7d\xf5\x34\x1a\xdc\xab\x15\x16\xe2\xe8\xa1\x35\xb2\x56\xd6\x4a\xcf\x0d\x23\x42\xcb\x5c\x2b\x78\x0c\x6a\x01\x71\xbb\x24\xb1\x9f\xac\x98\x2d\x0d\x8c\x7b\x42\x8d\xb6\x09\xf4\x59\xac\x2c\xf4\x40\xbd\x50\x5b\xb1\x18\xcc\x1c\x4a\x9d\x21\x0f\x5d\x51\xaf\x32\x02\x1b\x48\xbf\xf6\x03\xfe\xbb\xf6\xff\xb8\x7c\x85\xa3\x90\xcb\x05\x47\xcd\xda\x7a\x44\xfb\xf7\x8e\x7f\x1f\xf6\x0f\x24\xd1\x6b\x50\x10\x85\xa9\x84\x96\x05\x0c\xa3\x3a\xfb\x3d\xb6\x5c\xf0\x4b\xd4\xd9\xb9\x3b\xda\xfe\x4c\x66\xe3\xaf\x7d\xfc\xff\xf9\x3f\xfe\x9f\xff\x5d\xaf\x95\xf6\x23\x7d\xef\xa9\x66\xda\x85\xef\x51\x81\x95\x97\x5e\x29\x4c\x05\xd5\x5b\x29\x8b\x62\x42\x5d\xc0\x10\xdf\xf1\x23\xd6\x6e\x7f\xd5\x8a\x83\xec\x98\x5e\xc3\x20\xd7\x46\xce\xf7\x38\xeb\x62\x0b\x02\x39\xd4\xb1\x09\x3e\xf5\x09\xd2\x74\x09\x53\xab\x39\x17\x29\x38\x94\xa2\x79\xe9\x40\xcb\x0b\xa8\x29\xc4\x29\xd7\x29\x51\xae\x07\xec\xb3\xb6\x43\x80\x60\x8b\xa3\xa2\xf2\x83\x85\x1d\x32\xa7\x2b\x40\xa0\xc0\x0b\x68\xf6\x47\xec\x7a\xbb\xc7\xe9\x35\xa9\xbd\x39\x13\xac\xcd\x9e\x8f\x68\xdf\xdd\xb3\x3e\xd5\x79\x1e\x46\x88\x7d\x01\xc3\x48\x7f\xc4\x31\xee\xa5\x8c\xc7\x68\x0b\x74\xa2\xa5\x20\x6d\x0f\xca\xd7\xc0\x09\x79\xaf\x18\xb0\x27\x2b\x9b\x84\xbe\x11\xd0\xf1\xc8\xa3\xdf\x65\xca\x92\x07\x45\x5b\xd4\x86\x16\x83\x0f\xa1\x6d\x25\xcc\x07\x42\x6b\x36\x03\xef\x54\x1f\x94\x9d\x20\x4e\x45\x13\x2b\x88\x9c\xc6\xb1\xd8\x28\xc2\x73\xd4\x12\xa6\xb9\x05\xe2\x25\xc0\x58\xfb\x6c\xfa\xb5\x9b\x7b\x3d\xc6\xa3\x6a\xba\x47\xed\xf5\xb6\x38\x71\xaf\x40\x4d\x43\x75\x85\xd0\x0e\x72\x54\x36\x23\xe5\x7e\x50\xb9\xb6\x1d\xa7\x03\x35\x98\x1f\x75\xc1\x12\x38\x1f\x71\xb4\x7b\x7e\x51\xda\xc2\xbe\x77\x09\x31\x8d\x2f\x53\xc9\x58\xe7\x28\x2b\x50\x47\x70\xd5\x27\x21\x52\x9e\xb8\x74\x98\x76\xd6\x1d\x4b\x03\xda\x92\x32\x44\x42\x88\x37\x2b\x82\x00\x8d\x3f\xd4\x97\xc9\x62\x94\xbc\x62\x3d\x66\xd4\x0f\x38\x39\xd0\x4c\x3b\x39\x90\x03\xcb\x46\xa7\xc2\x83\x48\x98\x05\xf4\xf6\x28\xff\x51\xa7\xaf\xc8\xae\x63\xbb\xa2\xfe\xb5\xa2\xa4\x17\xaa\x23\x82\xfa\x89\x75\x54\x52\xb1\x7b\x09\xe2\x40\x39\x64\x95\x1a\xa4\x29\x64\x2f\xaa\x0a\xea\xe4\x60\xf2\x02\xcc\x55\x6f\x4b\x86\xd1\x20\x10\xce\xef\xa1\x16\xd2\x73\xf7\x09\x17\x69\x6d\x10\x74\x4a\xcd\x2b\x79\x80\xa0\x66\x83\x70\xb3\xe1\xe1\x43\x2c\x65\xe3\x8e\xc0\x8a\x9f\x42\xf4\x7f\xa5\x44\x58\x09\xbd\x2c\x84\x78\x98\x17\x86\xea\x9b\x19\xaa\x80\x23\x37\xad\x75\x10\xba\x8f\xb2\x3a\x17\x5f\x11\x27\x94\x04\xae\xaf\xc0\xda\x2a\x32\x42\x01\x0d\x7d\x6c\x4a\x56\x2b\x3c\x01\xef\x6b\x8f\x00\x02\xf3\xb2\x01\x6d\xdb\xf0\x88\xfe\xb0\xd8\x81\xe2\x24\x68\x2c\xb1\x70\xb1\x94\xdb\xfe\x1a\xe8\xd1\x6a\xa6\x53\x5b\x59\x7e\x02\x16\xcf\x8d\x64\x9e\x47\xf4\x46\xed\x9d\xb6\xe8\xf4\x9e\xd1\x1e\x12\x65\xf8\x7a\xf0\x83\x25\x1f\xb3\xcd\xbe\xed\x86\x3d\x58\x8e\x08\xac\xd6\xc6\xf3\x89\xfc\x65\x95\x8e\x47\x5b\xc8\x7b\x83\x75\xe0\x07\x44\xb3\x80\xd7\x21\x16\xb9\x0d\xaf\x4a\x61\xe5\x88\xd9\x15\x85\x3f\x0b\x79\xbf\x76\x49\x18\x1e\xdf\x20\x2e\xae\x35\xe4\x22\xfb\x07\xc4\x97\x29\x9b\x7f\x16\xd0\xcd\x03\x8b\x56\x58\x48\x65\xed\x51\x0a\x68\x06\x5c\xaa\xd9\x2b\xb7\x9e\x1f\x7c\xff\xde\xfe\xb9\xbf\x36\x09\x5a\xba\x04\x19\xc7\x57\x49\xef\x36\x43\x2f\x72\x47\x51\xa5\x28\xb9\x3f\x5d\xde\x5a\xd0\x59\xfb\x06\x3c\x51\x90\xde\x36\x85\x43\x86\x12\x9f\x4d\x21\x4a\x58\xf2\xaa\x19\xa8\x67\x39\x9e\x17\x18\xd6\x8c\x55\x1b\x1d\x0f\x95\xa7\xe8\x81\x45\x1f\x51\xc6\xb8\x9b\x19\x5e\x51\x54\x2c\x12\x28\x5f\x4b\xa4\xdb\x81\xf1\xc7\x2f\x44\xeb\xd5\xbe\x01\xae\x94\x37\x4d\xc3\xc1\x38\x7d\x8f\xb8\xda\xb4\xd5\x29\x81\x57\x77\xb8\x6c\x88\x13\x75\x5a\x84\xb3\x0f\xdb\x6c\xa1\x66\xc0\x64\x40\x56\x1f\x33\xeb\xd3\xca\x04\x97\x0f\x5c\x0d\x05\xd4\xbf\x80\x94\x3f\x14\xd1\x2d\xdb\x72\xd6\x06\xca\xe5\x01\xf5\xeb\xe3\xa8\xcc\xf7\xea\xe7\x1f\xf5\xde\x72\x5d\x47\x40\x69\x66\x80\xd4\x83\x4d\x22\x09\xcb\x01\x40\x2b\x64\x41\x04\xb0\xaf\x08\x58\xc6\xc8\x63\x5e\x5b\x40\xe1\x95\x2a\xa0\x61\x99\xc5\xc7\xea\x2a\x72\x24\x65\x75\x26\x5d\xd7\xe9\xe8\xcd\x87\xe3\x06\x09\x53\xe2\x33\x5f\xf5\x85\x4b\x80\x72\x5c\xf2\xd2\x27\xf6\x12\x73\x88\x1f\x2d\x8d\xbb\xfd\xed\x11\x1b\xa3\x92\x1f\x23\x3b\x64\x8e\xf2\x31\xe2\x82\xe1\x25\x86\x51\x75\x20\xd3\x43\x49\xd9\x51\xde\x7e\x2a\x90\x64\xbe\xcb\x36\xb8\x1e\xd6\xf6\xf6\x53\xa5\xb8\xc8\xd1\xc7\xf9\x1f\x16\x92\xd8\x93\xb1\x42\xe4\x0a\xe9\x98\xaf\x52\x1f\x2d\x5d\x62\x87\xe3\xcb\x2c\x65\x1d\x85\x51\x56\x4c\xea\x22\xce\xe9\xa0\xe9\xc9\x46\x37\xa6\x4d\x4b\x2c\xc5\x9b\x4f\xae\xe0\x2e\xa1\xab\x93\xde\xcd\xb6\xc1\x4e\xee\xe4\x15\x4a\x01\x24\x5f\x80\x64\x62\x90\x49\xd7\x4d\x50\x0f\x67\x0e\x29\xd0\x75\x58\xed\x30\xb0\x1c\x68\x09\x80\x9f\x4c\xa7\x3e\xb7\xbe\xa3\x42\x1c\x28\xe2\x31\x02\x36\x15\xe8\xea\x69\x83\x53\x4d\x45\xce\x35\x0a\xe7\xdd\x9c\xac\x1b\x67\xa2\xf4\xa2\x34\xeb\xfa\x38\xa7\xe6\x0d\xe8\xbf\x9c\xc6\xe6\x3f\x6f\xdb\xb1\xeb\x38\xda\xcf\x5f\x15\x71\xc7\x8c\x9a\x40\x49\x7d\xe3\x82\xab\x13\x5a\x2d\xd9\x7c\x9e\xbc\xb4\x69\xd7\x01\x79\x15\x22\xc8\x88\x04\x38\x1c\x2b\x81\xe7\x99\xaf\x51\x00\xf2\x55\x96\x3b\xff\x23\x00\xff\x55\x21\xd8\x52\x1c\x27\x86\x02\xb8\xec\x94\x88\x8d\x8c\x87\xd5\xd6\xb8\x92\xee\x31\xcf\x87\x2d\x12\x30\x03\x73\xd5\xbb\x2d\x3c\x30\x3d\xab\x13\x38\xdd\x36\x56\x97\xda\xdd\x40\xf2\xe7\xbc\x3c\x65\x6c\x04\xd4\x46\xfd\x3a\x44\x4d\x0b\xe8\x12\xba\x1c\x5f\x65\x1d\xa5\x68\x0f\x43\xfb\x12\x1b\x78\x62\xda\x32\xcd\x53\x94\xfb\xa8\xb6\xfe\x26\x33\x75\x75\x01\xce\x4f\xa4\x3d\x46\x1d\x8b\xc8\x80\xa6\x67\x7e\xb3\xb3\x4b\x68\xb3\x2f\x42\xe2\xe9\x47\xb4\x03\x62\xcd\x66\x7c\x43\x95\x73\xf4\xd0\xc5\xfe\x94\x80\x14\xd0\x7b\x1c\xb5\x2e\xb9\xb6\x50\x5f\x50\x2a\xf3\x6d\x2e\x51\xad\xf1\x95\x20\xb1\x4d\x00\x55\xc7\x5e\xca\x05\xf2\x98\x20\xcd\x15\xfd\xbd\x40\xd3\xfe\x7f\x16\x93\x35\x3f\xec\x3e\x1b\x75\xf3\xf0\x17\xaf\xc5\xfb\x53\xd7\x6a\xad\x84\x62\xe6\x7f\xaf\x0a\x6d\xce\x07\xd9\x14\x5d\xc7\xf1\x90\x71\xac\x4f\x39\xc7\x6d\x17\x78\x7c\xc4\xac\x89\x27\x75\x24\x6b\x1d\xec\x61\x77\xb9\x1d\xb7\xc1\x73\x88\x28\xf2\xe2\x6d\x7f\xe4\xfd\xb8\x8f\x0f\x13\xd1\xef\x1f\xc6\x32\x68\x50\x1f\x99\x47\x40\x4c\x1e\xbd\xa5\xb4\x4d\x04\x6b\x1e\x79\x0a\xd0\x51\x28\x0c\xd7\x00\x89\x06\xcd\x28\xd1\x0e\x79\x52\xc8\x4e\x1a\x7f\xc2\xd7\x62\xd9\x28\x89\x83\x79\x0e\x15\x09\x3b\xa0\x50\x00\x6e\x4a\x5a\x51\xcf\xcf\x15\xca\x0c\x00\x8e\x17\x50\x74\x82\x1c\xb5\xf4\xc0\x28\x1d\x78\x71\xde\xbd\x82\xca\x2e\x2c\x87\xeb\x33\x7e\xd5\x94\xc0\x7d\x8f\x18\xe0\x72\xfd\x60\x43\x42\x71\x39\x13\x7a\xd0\x89\x05\xd6\x2c\xaf\xf6\x08\x93\x5c\x4d\xfe\xca\x2c\xcb\xc6\xab\xd4\x6d\xcf\x4a\xfc\xc5\xc6\xfd\xf4\xb0\xa6\xe5\xe3\xc3\xde\x7d\xf9\x57\x8b\xcf\x25\xc6\x34\x2e\xe9\xdf\xd3\x6a\xac\x3a\x46\xe8\x19\x96\x99\x59\x17\x00\x2f\xb8\x0a\x6e\x5f\xac\x37\xba\x74\xe5\x20\x70\xa9\x21\xed\xb7\x63\x20\x0a\xd1\x48\xfc\xc5\x9e\xdc\xd6\xd9\x51\x41\xc4\x66\x3e\xd6\xc0\xbc\x8e\xef\x14\x73\x47\x39\x33\xb0\x1e\x6a\x76\xda\xdc\xc0\x01\xd0\xf1\x23\x97\xcd\x8b\xdf\x59\x59\x3e\xee\xb3\xb1\x76\xe3\x3d\x14\x53\xd3\x07\x45\x9a\x1c\x5f\x1f\x94\x52\x66\xd4\x9b\x5f\xf5\x41\x6c\x5c\xdf\xd0\x7b\x13\xa9\x13\xd2\x06\x77\xcc\x35\x96\xe9\x1c\xdb\x13\x97\xe6\xaa\x02\x64\xad\xdf\xf3\x00\x51\xa9\xee\x0b\x45\x68\x86\xa0\x9d\xbc\x38\xb7\xd0\x60\x57\xdb\xa1\xf9\x60\x72\x90\x7e\x8f\xb9\x39\xa9\xe2\xf0\x88\xaf\x80\xec\xa0\x5a\x53\x95\x6f\xa9\x43\xaf\x60\x6a\xf5\x33\x36\xbf\xc4\x5d\x52\x59\xc9\x17\xcb\x3b\x6d\xcf\x9b\xf3\x69\xfc\xe1\xa0\x24\x2e\xc1\x1f\xdd\x17\x20\xbc\xce\xfe\x86\x7c\xe1\xfd\xfd\xf7\x06\x41\xfb\xdc\x25\x75\x1b\x9b\xb5\x87\x9e\x18\x1c\x01\x47\x48\xfd\xb1\x6b\x84\xf9\x4c\x76\x28\xd5\xfe\x2a\x59\x7b\x78\x1f\x7e\x9a\xd9\xae\xb8\xd0\x3d\xda\xb5\xa3\x10\xbb\x9e\xa1\xb6\x75\xf4\x85\xe8\x9d\x23\x7a\x5f\x89\xde\x75\xe2\xde\x97\x56\x97\x7a\xee\x84\x67\x48\xab\x77\x11\x81\x35\x08\x8e\x03\x80\x6a\x06\xd0\x0b\x2f\xe2\x9c\x2d\x5d\xe2\x9c\xe3\x2b\xfe\x1d\x91\x9a\x42\xef\x65\x47\xfe\x53\x99\x71\x1e\x78\x98\x3c\xcd\xe6\xcc\x0f\x6d\xf3\xae\x35\xaf\x15\xe2\xdc\xbe\xcb\x5a\xdd\x8f\x87\xe5\x90\x75\xfa\xb5\x10\xde\x9f\x70\x1d\x28\xe1\x84\xa9\x58\xef\xb1\xe4\xfc\x88\x63\xb6\xbb\x8c\x74\x5c\x54\x00\xa1\x52\xd5\x60\xa7\x6c\x53\x83\xaa\x5c\xa2\xfa\x7f\x8e\x03\xe9\xf6\xf7\x92\xd1\xb7\x74\xa9\xf0\x1b\x57\x51\xd9\x13\x15\x62\xb3\xde\x4a\x8d\x34\xb0\x3d\x32\x84\x02\x60\x42\x03\xf0\xa6\x3b\x13\xaa\x4d\x08\x8a\x5f\xad\x07\xb9\xe8\xdc\xf0\x91\x1a\xe5\xa9\x31\x55\x02\x59\x76\x77\x9c\x16\x63\x3c\x0c\xc1\x68\x46\xc6\x20\x07\x01\x63\x1d\xc0\xc2\x4d\x82\x92\x89\x55\x9a\xcd\xd7\xc4\xc9\x29\xb0\x6a\xa0\x61\xc2\x45\x3b\xc9\x43\x04\x30\xdf\x59\x56\xf2\x79\xa0\xfe\x15\x7e\x37\xc9\x51\x33\x19\xaa\x5d\x97\xab\x96\x0d\xe4\x39\xd6\x0d\x00\x60\xbd\x81\x73\x64\xc7\xfe\x02\x6b\xfb\x9c\x34\x9c\xd0\xc9\xf7\xfe\xd8\x65\xf7\xc8\x38\xe8\xbb\x6d\xae\x68\x2b\x88\xe5\xc9\x5c\x80\xf8\x77\x25\x5e\x39\x7b\xb7\x19\xde\xa0\xce\x07\x9b\x18\xeb\x2a\xa0\x56\xa2\x49\x9d\x92\x8d\x59\x54\x83\x34\x02\xba\xc6\x0c\x40\xd1\x6c\x70\x5b\x40\xd4\x02\xe4\x5f\x06\xc3\xb5\xb6\xbe\x21\x8c\x9e\xdb\xda\x14\x5a\x93\x8c\x40\x8f\x2d\x83\x14\xbd\xac\x9a\xab\xcd\x60\x89\xd6\x42\x1d\x4f\x7a\x79\x90\x57\xde\x56\x37\xf2\xc3\xee\x9d\x20\x74\xd8\x1d\xa5\x57\xc8\x3a\x5f\x9e\x8f\x0e\x6e\x16\x9b\x3a\x40\x20\x48\xee\x44\xc2\x98\x33\x52\x6e\x4e\x98\x42\xbd\x78\x07\xef\x32\x11\xa4\x98\x13\x41\xcf\x96\x0a\x3f\x77\x46\xef\x57\x20\xfc\x06\xd5\x5f\x14\xf3\xa5\x86\x32\xb7\xba\x43\x1a\x29\xce\x0b\x2c\xcc\x0a\xfc\x6a\xd1\xc0\x67\x18\x6f\x3f\xad\xd3\xee\x4f\xa7\x08\xb6\x64\x04\x2b\xb2\x3f\xde\x8e\xb2\x2e\xf8\x9d\x22\xe5\x92\x6f\x7c\xbe\xc1\xab\xda\xdd\x60\x91\xd4\x8e\x0e\x24\xad\x20\xdd\x91\x2b\xe6\x3a\xd0\x04\xe1\xd7\xfe\x7c\x50\x39\x26\x79\x5c\x00\xbd\x18\x57\xac\x3d\x88\x42\xf5\xca\x2c\x1e\xc8\x60\xcd\x11\xfc\xa9\x5e\x00\x0b\x9b\x5c\xc3\xfe\xff\xed\x40\x95\xc3\xfc\x27\x4f\xe1\x98\x64\x7d\x11\xd2\xfa\x22\xe7\xe2\xa8\x2e\x44\x64\xb8\xdd\x08\x61\x25\x78\x6b\xa6\xe0\xbf\x03\xde\xfa\x3c\xec\x79\x32\xaf\xc8\xfe\xea\x04\xda\xce\xd3\x2d\x7b\x90\xe7\x80\x92\x75\x77\xa6\x2a\x99\x5a\x7b\x21\x0e\x39\x0f\xa6\xf0\x11\x70\x01\xef\x5e\x47\xbe\xca\x29\x7b\x85\x30\x33\xdc\xbc\xba\x84\x69\x3a\x42\xbb\xbd\x85\xb1\x2f\xf2\x83\xc8\x86\x23\x0a\xd3\x28\xf3\x9a\x50\xe3\xe6\x4e\xf6\x86\xb8\x5d\x6d\x1e\x60\x1f\x9b\x79\x08\x20\x4c\x24\x07\xee\x06\x7a\x96\xee\x6f\x56\x64\x73\xde\xd3\xec\xe4\x84\x65\x6e\xc5\xd1\x97\x89\x5d\x45\xc1\x4d\xcb\x12\xaf\x0e\xa4\x75\xd1\x0d\x5c\x44\x1d\x62\x28\xe2\x6c\x24\x32\x53\xa8\xb4\x22\x20\xea\x06\xb0\x22\x3b\x3a\xd7\x58\x46\x81\xca\xdc\x43\x47\x25\x94\xe2\x8c\x08\xc5\x69\x18\xe7\xa1\x48\x81\x08\x2a\x35\x79\xd3\x8d\x7e\x37\x42\xe3\x08\xbd\x21\x1c\x4a\xe8\xa6\x22\x12\xe1\x61\x2c\x14\x53\xec\xc8\xbc\x3e\x02\x7f\xaf\x69\x6b\xd0\x2c\x3a\x08\xb5\x45\xca\x06\x29\xf9\xd0\xfb\x86\x45\x0c\x8a\xd8\xc8\x9a\xd9\x0a\x87\xf8\xea\x26\xcd\x69\x85\x37\x27\xd5\x99\x65\x6b\x47\x50\x50\x58\x64\xc9\x76\x62\xfc\xcc\x09\xb1\xa2\xab\x64\x1c\x14\x4d\x66\x99\x20\x4d\x4d\x30\xf3\x0c\xb1\xde\x23\x54\x7f\xf1\x1b\x63\xa3\x52\xb6\x08\x93\xe9\x30\x06\xb5\x84\x9e\x76\x0d\xc2\x49\x6e\xce\x0a\xb3\xb9\x1e\x19\x22\x71\x9e\xc7\xdc\x83\x80\xae\x01\x56\x0f\x57\x1c\xf1\x90\x5d\xec\x89\x3a\x83\xbd\xb9\x32\x38\xc9\x70\x61\xde\xb4\x8d\xc2\xdc\xdb\xec\xd4\x2b\x60\xa9\x2a\x96\xa0\xee\xd3\x20\xfd\x2a\xee\x4c\x73\xcf\x64\xda\x69\x73\x23\xcd\x38\x02\xfd\x50\x95\x45\x31\x14\xde\xbf\xa9\x6b\xc1\x73\x1c\xf1\x0f\x3c\xe2\xd5\x88\xbf\x26\x5b\x0e\x45\xdb\x9e\x40\x36\xf8\xa8\xbd\x7d\x50\x53\xce\x5a\xad\x0f\x8a\xca\x79\xf8\xaf\x45\xe5\x28\x0f\xfb\xb5\xaa\xdc\xfc\xf3\xbf\xf7\x0e\x35\xef\x5c\x97\x54\x9a\x40\x99\x6e\x1e\xec\xc2\xcc\x0e\x91\xc7\x8c\x7f\xc4\x01\xb7\xfd\x17\x14\xf6\xf2\x28\x3f\x08\x00\x5b\x9c\xfd\xdc\x3a\x1f\xf0\x3c\xef\x79\xb9\xed\xdd\x7d\x9e\x0f\xf0\xea\xcb\x5c\x63\xf1\xff\xd7\xf1\x65\x1a\x99\x61\x56\xc5\xcc\xf6\xfa\x5e\xdb\xb7\x5e\xfc\x0f\xbc\x37\x8b\x79\xcd\x05\x06\xe3\x8b\xf6\x0c\x76\x14\x5b\x82\xe6\xd8\x7a\xb6\xbf\x50\x45\x16\x76\x93\xff\x3d\xfa\x71\xf8\x19\xf7\x3d\x11\xbb\x3a\x52\x8c\xf9\xb6\xf9\xc6\x76\xec\xf2\x83\xdf\x7e\x8e\x56\xc2\xc7\x3e\xe1\xd1\xb1\x9e\xbe\xa6\xb9\xbd\x57\x5f\xf3\xd9\xa5\x7e\xd5\xa2\x9c\xfa\xf6\xb3\x8c\xf4\xb7\xde\xe0\x45\x4f\xb8\x46\xe2\xff\xef\x63\x55\x4e\x63\x7c\x31\x84\xde\x83\x0e\x5f\x0e\xa1\x33\xf6\xf0\x1f\x1a\x42\x7f\xe3\x08\xba\xfd\xc6\x10\xba\x46\xec\xff\xe3\xdf\x43\xe8\xc3\x21\xf4\x5b\x3d\xfc\x23\x88\xea\x17\x3d\xfc\x65\x31\x7c\x93\x4b\xc0\x7b\x7e\x49\x68\xd1\x2b\xa5\xe0\x10\x70\x94\xbc\x66\x22\x18\xb0\x5e\xa7\x95\x4a\xc1\xac\x76\x8f\x2a\x07\x0a\x86\x7c\x8a\x23\xa8\xe0\x10\x08\x2f\xb5\x50\x93\x5d\x26\x4b\xbe\x4b\x57\xf5\x40\xef\x6c\x7d\x19\x90\x29\xaa\xf7\x28\x3d\x0d\xfb\xad\xf7\xba\xe6\xc0\x72\x24\x84\x52\x0a\xe3\xa2\xf7\x3d\x29\xf5\x95\x44\xf4\x47\x05\xb4\x8f\x3d\xc7\xf5\xea\xe4\xdb\xa7\x67\xa3\xea\x1e\x3e\x56\x76\x96\x74\xbc\x78\x72\x21\xf1\xe4\xa0\xad\x4f\xe1\x0f\xdb\x47\x10\x0f\x24\x8b\x3d\x44\x75\x44\xae\x76\xd9\x77\x77\x45\xe5\xb7\x2f\x0a\xe2\x4b\x24\xaf\xc0\xaa\x83\x7f\x5d\x86\x45\x5d\x9a\xf3\xa4\xc9\x12\xf1\xb7\x57\xfd\xe6\x92\x5a\x98\x97\x52\x91\x33\xfb\xdd\x54\x40\x44\x56\x88\x98\x7e\x58\x1d\xba\x7d\x52\x76\x7a\x8f\x02\xb2\x5c\x50\x30\x31\x6e\x5a\x9c\x2c\xa5\x37\xa7\x2d\x4b\x77\x82\xe3\x22\xb1\x41\x43\x43\x4e\xb0\x37\x7b\xe3\xa9\xad\xe9\x1d\x6c\xe6\x27\xed\xf4\x6f\xd4\xb1\xde\xad\xeb\xdb\x10\x85\x17\x6a\x7e\x9e\xd7\x51\x30\xd3\xbd\xd3\x4c\x2e\x70\x76\x41\x78\x04\x87\x00\x56\x7b\x21\x5b\x37\x63\x88\xf5\xa8\xf1\xf0\x4a\x7c\xea\x1f\xe3\xe4\x6c\xce\x86\xb4\x15\x95\xfc\xb4\xe6\xcd\xf9\xf0\x7a\x8d\x7e\xf7\xba\xd9\xac\x8f\x22\x0e\x03\xe2\xe7\x3d\x3e\xf6\xfe\xed\x77\xc8\x0d\x8f\x8b\xc4\x05\xc5\xe2\x9a\x23\x93\xf8\xa0\x0d\xe7\x7a\x1f\xfd\xe3\x17\x6d\xa0\x77\x5b\xd8\x1e\xb7\x95\xed\x71\x34\x94\xb7\x01\x9b\xc0\x19\x79\xeb\x13\x98\x60\x3b\xd1\x96\xd1\x1b\x13\x77\x3b\x5a\x6a\x7b\x36\xe0\xbd\xee\x63\x8f\x11\x5a\xb4\x5a\xb1\x4f\xd5\x5b\x10\x2d\x65\x01\x91\x6c\x11\xfb\xec\x59\x17\x49\x12\x4a\x91\x55\x66\x18\x23\x8c\x19\x04\xee\xa2\xb4\x84\x88\xcd\x5d\x5a\xff\x10\x93\xf7\x01\xa2\x09\xc7\x4e\x44\x68\x5b\xda\xdd\x04\x94\xe7\xda\xd3\x83\xa6\xaa\x14\xb9\xf1\xbe\xf6\x14\x45\x58\xd0\x02\x7a\x1f\x24\x49\xd4\xcb\xa3\x80\xf9\xc2\x9d\x3f\x84\x47\xd9\xfd\x3f\x00\x5d\xf1\x1c\xfb\x53\xda\xe5\x3f\xcc\x9f\xa2\x8a\x5d\x7f\x69\xd2\x5c\xd2\x19\xf3\xab\x42\x93\x39\x25\x54\xd1\xa5\x95\xa0\xb5\x99\x67\x50\x16\xc4\x55\xec\x37\x85\x12\x68\xaf\xa8\x4e\x6d\xa4\xc7\x07\x67\x84\x07\x05\x33\xca\x78\xcd\x05\xec\xcf\x93\xb2\xc8\x4a\x62\x4f\x94\x8c\x10\x25\x57\xc8\x85\x78\xba\x44\xfd\xe0\x12\x64\x48\x1c\x97\xeb\x93\xa7\x82\x95\x79\xf6\xf9\x81\x3b\xd6\x10\x5b\xd0\xb1\xf4\x11\x32\x04\xf7\xed\xc9\x3f\xbf\xc2\xb3\xa0\xba\x06\xd1\xdb\x87\x97\xb0\x47\x3f\x1f\xf5\xee\xa0\xda\x82\x3d\x47\x0f\x00\x3d\x04\x2d\x77\x7b\xe6\xbd\xdd\xae\xa7\x0a\x6d\xc6\xf3\xb9\xf5\xfd\xb9\x43\x82\x3d\x2b\xaf\xa8\xf6\x57\xf0\x7e\x9c\xda\x0e\x22\x22\x7b\xd3\x21\xf0\x22\x6a\x5f\xe5\xaf\x9e\x9a\x45\x6e\x9f\x1d\xf5\xaa\x5f\x5d\x62\xfd\x33\xef\x16\xdf\x00\x65\x73\x5e\x04\xa4\x79\x65\xb0\x14\xd3\xfe\x79\xfb\x39\x0a\x18\x72\xcb\xb2\xff\x69\x89\xfb\x61\x6f\x3f\x3b\x3a\x47\x4e\x4b\x81\x74\x51\x59\x62\x4e\x2d\xe4\xd4\x96\xfd\x67\xf4\x3d\x8f\xd8\x40\x9a\x54\x51\x9a\xcf\xd1\x3f\xf3\x92\xbd\xf2\xde\x13\x6f\xb6\xe5\x7b\xfc\x48\x9c\x87\x54\xfc\x7c\x67\x6a\xdb\x24\x94\x9d\x0f\x89\x01\x2f\xa8\x3d\x3b\x2f\x91\x0b\x9d\x10\xbc\x30\x58\x9d\x28\x07\x2d\xd7\x6d\xff\x4d\xcb\xf3\x30\x1e\xc5\x0b\xf8\xf9\xb8\x30\xae\x9b\x35\xf0\x66\xc7\xc6\xb1\xef\x7c\xc6\xe9\x4a\xa7\x1b\x9c\xee\xbc\x9d\x1f\xe9\xdd\xc3\x3e\x5f\xe2\x78\xb3\x57\x1f\xf4\x92\x38\x98\xd7\xa2\x9b\x53\x6d\x3d\xa0\x1d\x79\x91\x9e\x83\x40\x1c\x99\x1b\x8f\x98\x4b\x79\xc3\xee\xa1\x9f\xee\x6e\x0a\x00\x0a\x4a\x1b\x62\xae\x36\x97\x20\x82\x54\xd2\xa3\xe3\xbb\x42\xa5\x7b\xda\x6a\xce\x2a\xe7\x25\x77\x0d\xb9\xe7\x25\xee\x1b\xfb\x8e\xfd\x50\x9c\xb8\x5f\xe5\xc5\xbb\xea\x25\xfa\x3a\xeb\xe1\xe7\xa9\x03\xf1\x00\xa2\x27\xaa\x7e\xdb\x31\xf6\x8e\x68\xdf\xe1\xf8\xfe\xc3\xff\xca\x63\x70\xc2\xce\x44\x80\xd2\x82\x7f\xe4\x32\xf0\x09\xdd\xfc\x23\x8f\xf5\xc9\x66\xdb\xe2\x3b\x73\x2e\x9e\x0d\xbd\x78\xb6\x00\xbf\x63\x0d\xde\xde\x9b\x83\x3f\xa5\x40\x7a\xb2\x94\x03\xe9\x08\x9f\xcc\xbe\x48\x65\x91\xdb\x70\xfb\xbf\x51\x97\x54\x1b\xe8\x8c\x3f\x5a\xc2\x1c\xe7\x08\x24\x0e\x4e\xc7\xd9\xe6\x19\x80\x23\x52\xdb\xdd\x4e\xbc\xae\xbd\x74\xd0\xbc\x19\xff\xfc\xfb\xdf\xfe\xb2\x39\xac\x97\x60\xde\xfc\xaa\xd2\x46\x52\x09\x23\xa7\xa5\x83\x5f\x2f\x99\x81\x3b\xda\x08\x2d\x27\x82\x30\x33\xd9\xdc\x6c\x44\xb3\xec\x0c\x76\x45\x4e\xe3\x61\x3d\x09\x84\xd8\xe9\xde\x5a\x5a\x62\x06\xf3\x70\x92\x6a\x7b\x32\x3c\xeb\xa2\x0b\xbc\xcc\x66\x4b\x56\x69\xfc\xad\x89\xae\xc3\xbc\xc6\x9c\xcd\x99\x04\x3b\x2b\xd8\x25\xcc\x1c\xca\x89\x76\x4b\x4e\xb6\x64\x44\x54\x8c\x40\xd2\x92\xa5\xb7\xf6\x1c\x7c\xc0\xd8\xfc\xa1\xf7\x3b\xee\xe7\xbf\xba\xd1\x8b\xd6\xbb\x04\xdc\xe6\x57\x08\xfb\x3c\x4a\xe8\xa9\x58\x1f\x21\x4f\x15\x38\x3e\x15\x5c\x7b\xaa\x12\x72\xd7\xc7\x54\xa7\xc8\xcf\x00\x43\xa3\xab\x7a\xc5\xa6\xec\x15\x9b\xb4\x48\x95\xf1\x73\x45\x2b\xa3\x42\x1d\x2a\xe9\x29\x28\xe0\x8f\x0a\x6d\xe2\x6e\x36\x29\x0a\x64\xe0\xcb\x6a\x1e\xc1\x16\xaf\x56\x12\x9e\xa4\x15\x7f\x12\x60\x87\xf8\x24\xd6\x4c\x3d\xb7\x43\xcd\x75\x4e\x56\xd7\xc1\x56\x4c\x4a\x1c\x95\x52\x00\x10\x94\xcf\xce\xeb\x08\x2d\x02\x92\x04\x8a\x2d\xc7\x20\x3e\x07\x2e\xb2\xba\x96\xa3\x50\xb7\xcd\x95\xda\xec\x7d\x70\x3e\xf4\xac\x05\x14\xac\x10\x7a\xb7\xc3\xf6\xda\x53\x3b\x19\x52\x93\x24\x9d\x07\x13\x21\x8b\x82\x65\xf3\x3b\x6b\x43\xce\x4b\x81\xf0\x02\x1c\x74\xce\x20\xad\xe2\xc9\x73\x25\x4c\x9a\xc8\x9d\xbc\xa3\x2c\x8f\x10\x0a\xa8\xea\x11\x7a\xe1\x16\x02\x32\xae\x68\xec\xe1\x1c\xac\xbf\xdf\x08\x1d\xe9\x25\xe6\x36\xc7\xff\x76\x00\xb8\x6a\x68\x5a\x59\x87\x1a\xd5\x69\xc4\xb5\xea\x1b\x76\x8d\x41\x58\xfb\xbe\xab\x73\x97\x28\xc4\xe5\xa6\x9f\x96\x8b\xd0\xfd\x2f\xe2\xfb\x9e\x97\x6c\x9d\x97\x6c\x7d\x3f\xef\x79\x4d\xee\xeb\xbe\xaf\xa4\x11\x34\x3d\x44\x29\x3b\x6e\x86\x9c\x94\x0d\x96\x2c\xc1\x32\xd9\x8c\x2a\xad\xa8\x42\x4d\x40\x1e\x62\x23\x62\xcb\x76\xd2\x2e\xd4\x27\x14\x3b\xb6\x0d\x18\x0e\x44\x25\x68\x8b\x0c\x08\x67\x95\xdb\x86\xdd\x77\xfc\xd9\xd1\xdf\x6d\xb3\x3b\xbe\xfd\xac\x15\x7c\x8d\x69\x11\x68\x01\xd9\x50\x4c\xed\xed\xe7\x1c\xfe\x67\x1b\x11\xcf\x3f\x3b\xfd\x5f\x4b\xcf\x7b\x10\x35\x86\x8c\xcf\xe6\x85\xfe\xf9\xce\xbd\x47\x7d\xbb\xb9\xb3\x1b\x12\xbc\xa9\xee\xef\x0c\x4c\x01\xca\xe1\xb9\x9f\x4f\xb7\xd7\xcf\x23\xf9\xe2\x97\x7d\xf5\xc5\x2f\xc1\xc2\xf9\x15\x35\x80\x39\xc3\x1d\x01\xb3\x54\x40\x50\x4e\xf4\x00\xd2\x8d\x79\x06\x4d\x20\x32\xef\x21\x43\xde\xb5\xc0\x5d\xed\x29\xe4\xb6\xc6\x31\x43\x31\xf7\xdf\x8c\x62\x90\xa1\xe7\xb1\x98\x85\x90\x51\xf7\x4f\x04\x01\x8b\xd1\x8e\x64\xa2\xeb\xd8\x79\x8d\xaa\xe4\x7d\x2b\x0b\x8c\xe3\xee\x93\x35\x90\x6e\xa3\x84\x01\xa8\x7f\xde\x10\xe6\xab\x65\x13\x71\x05\xe6\x04\x81\x45\xca\xb2\x6c\xc2\x94\xd9\x4c\xc0\xd2\x65\x54\x6b\x93\x17\x3c\xad\x12\xa0\xae\x04\x3e\xdb\x9a\x29\x83\x29\xa1\xf6\xdb\x1a\x7b\x0f\x80\x77\xf4\x19\x14\x03\x77\xd4\x90\xc5\x96\x84\x32\x83\xf4\xbe\xc6\xee\xb4\xcf\xa4\x7c\xd5\xba\xc5\x39\xdc\xd7\x8d\xa0\x94\x2f\x3f\x76\xa9\x20\x19\x6d\x8b\x55\x6d\x50\xbb\x8e\xae\x56\x73\x4c\x89\xac\x99\xab\x75\xfe\x14\x0a\x69\x44\x73\xdb\x90\xd3\x9d\x6a\x4b\xa4\x8b\xe7\x6c\xe2\xc1\xd7\xce\xd5\x12\x95\x6d\xc0\xa0\x90\xee\x7d\xc7\x77\xfb\x5f\x49\x44\x20\x88\x94\x26\xf7\x97\x37\x52\xb0\xa6\xbe\x50\x32\xd4\xc6\x99\xa4\xb2\x44\x85\xbc\x4a\x75\xe9\x5d\xf5\x02\x9e\x88\x21\xa6\x2e\x64\xe8\x25\xf5\x0d\xf0\x11\xc6\x01\xa8\xa2\x12\xaa\xed\xeb\xd3\xa6\xb7\x57\x7d\xef\x1a\xff\xfc\x52\xd8\x26\xf7\x12\x46\x9f\x6b\x6c\x8c\xf4\x80\xb3\xd9\x49\x49\xf7\xfa\x47\x6d\xe2\xa3\x2a\x39\xce\xc5\x36\x9a\xc2\x12\x6a\xc1\xf3\xa5\x5e\xf6\x76\x54\x2f\x79\xb5\xf2\x51\xc7\xc4\x5c\xed\x44\xfa\x32\x64\xb0\xbd\x0f\xc4\x44\xa4\xba\xc0\x91\x2d\x16\x73\x57\xdc\x76\x7d\x75\x70\xcb\x08\x60\x44\x93\x74\xcb\x3b\x0e\x07\x59\x6f\x20\x23\xcb\x0a\x65\x4a\xa8\xe2\xaf\x10\xc0\x68\x29\x14\x59\x6c\x42\x5b\x2b\x89\x4c\xbb\x04\xad\xf3\x5e\x14\x65\xa2\x28\x42\xe9\x5c\x38\x97\x41\x6e\x79\x7b\x11\x41\x6f\x2b\x72\xc4\xa4\xcb\x0a\xc8\x8f\xf5\xda\x5c\x36\x09\xe6\xce\x4d\x84\x7d\x75\xe0\x02\x45\x08\x21\xdd\x65\x19\xf9\xd4\xce\x70\x3d\xc1\x45\x2d\x8a\xd7\xad\x60\xb1\x61\xf6\x1f\x89\x6b\xb4\x10\x40\xc1\x04\xc6\xef\xd6\xf4\xdf\xc7\xe6\x70\x23\xb5\xcd\x5e\xf4\x55\x1c\xdf\x8a\x48\x3e\x1f\x9b\xeb\xb2\xaf\xaf\x20\x37\x72\x35\x1f\x57\xbb\xc7\x2f\xbe\xad\xf5\x49\x7f\x84\x93\x70\x2d\x5e\xea\xb4\xb9\xef\xde\x8f\x3f\x5d\xe3\x7c\xed\xe3\x8e\xc7\x43\x9c\x1e\xcd\x91\xf6\x34\xc9\x2b\x03\x23\x34\x09\xb7\xa8\xb0\xa8\x9b\x0d\x24\x84\x64\x4a\xdd\x62\x03\x60\x75\x6c\xfe\xf3\xb6\x1d\xbb\x8e\xa3\xf7\xf3\x15\x36\x1e\xfe\x6e\x7f\xb6\x03\xed\xb8\xc6\xea\xa3\xb8\xff\xdc\xff\x1e\xf7\x03\x23\x4f\xfc\x57\xd1\x12\xfc\xdd\x32\x3a\xbd\xc6\xbb\xff\xcf\xa7\xea\x43\x1e\xa1\x6b\x5e\xb1\xa2\xd4\xa0\x33\xc4\xa1\x0b\x42\xd4\xb5\xca\x1a\x0b\x61\x6f\xc4\x52\xf4\x64\x8f\xcc\x11\xee\x70\xd2\x69\x66\x5b\x29\x21\x13\x30\x49\x46\x7a\x20\xdc\x42\xef\x3f\xea\x92\x6b\x28\x8a\xc0\x48\x0e\x71\x00\x44\x2d\x92\x03\xc1\xd4\x8c\x59\xa0\x94\x19\x72\x1e\x70\xae\xb3\xad\x4b\x7d\x9d\x50\xb1\x0d\xd6\x24\x19\x25\x34\x65\xaf\xe3\x09\x6a\x2d\x4e\x94\x8a\xa4\xfc\x2c\xac\xb3\x19\x62\x1e\x97\x18\xa8\x16\x11\x29\x41\x47\x09\x52\x64\xd1\x56\x42\x4e\xe9\xc6\x18\xce\xe8\x0b\xd3\x13\xd2\x00\x45\x77\xa1\xfd\xce\x82\x40\x4a\xed\x3f\x47\x7b\xef\xe4\x19\xe8\x79\x51\x5b\xa9\x25\x23\xa4\x0e\x6e\x22\x90\xd9\xa3\xf0\xc4\xbc\x8d\x32\x50\xcd\x97\xa1\x1f\xa1\x20\x36\x8a\xff\x1f\x7b\xef\xb6\xe3\x48\x92\x24\x0b\xbe\xf3\x2b\xec\x07\x2c\xc7\x54\xed\x8e\x1d\x0c\x70\xba\xfb\x3c\xc6\x37\x2c\xea\x76\x96\x0f\x8e\x5d\x38\xc6\x97\x0f\xf1\xf5\x0b\x15\x51\x73\x32\x92\x11\x99\x51\x55\x59\x33\xbd\x73\x06\xe8\xae\x60\x92\x4e\xa3\x5f\xcc\xd4\xf4\x22\x2a\xd2\x06\x4c\x11\x65\xfd\x01\x00\xd9\x28\xf9\xa3\x59\xb7\x6c\x06\x2b\xed\xb6\x6f\x02\x24\x9d\xe1\xbf\x59\xc4\x2a\x23\xa1\xff\x27\x51\x79\xc1\xf6\xb8\xaa\xe6\x02\x1d\xfe\xc7\xdf\x15\xda\xd1\xea\x32\xea\xd4\x63\x78\x78\x79\x7e\xfe\x7a\x79\x69\xb6\x6b\x35\xdd\x89\x16\x34\x1f\xa4\xc9\xc6\x4e\xf5\xec\x14\x65\xae\x13\x95\xab\xeb\x44\xb1\xa4\xe8\x16\xc1\x8b\x84\x50\x77\x1d\xab\xa2\x08\x74\xed\x80\x86\x53\xce\xed\x61\x38\xb3\xb1\xc3\xdb\xd9\x84\xf4\xd3\x02\x84\x3f\xc3\x53\xc0\x8a\x96\xb0\x5b\xfa\x3e\xf0\x44\x9f\x33\xc0\x27\xbc\x61\x8c\x04\xbd\x70\x04\xee\xef\x17\xcd\xdb\x7b\xa5\x4a\x1e\xfe\xb6\x18\xdf\x9e\x91\xe5\xaf\x2f\x22\xd9\xa2\x57\xf4\x6c\x57\x6f\x2e\x98\x69\x65\xaf\x6d\x3b\xab\xca\xee\x58\x17\xa6\x6c\x3b\x65\x40\x46\xf0\x82\x81\x0e\x36\x94\xaa\x59\x30\xae\xa3\x79\x8b\x59\x7f\xcf\xe9\x22\xd4\xc9\x2e\xa3\xd0\x90\xb2\xd3\x42\x7c\x56\x9e\x9c\xb1\x45\x88\x3e\x02\x26\x4d\x65\xaf\x39\x28\xa0\xa2\x25\x1f\xaa\xa1\x58\xe0\x56\x94\x35\x0b\x8a\x55\x10\xa5\xac\x60\x57\xa2\xcd\x85\x0a\x7e\xdf\xc9\x0a\xe6\x5a\x1f\x23\x83\x37\x96\xbc\x4d\xae\x26\x2b\x2e\x6f\xe2\xe9\xad\xc1\xec\x30\xb6\xdd\xa0\xe9\xa8\x41\xf3\x6e\x51\xa0\x4c\x0d\xb9\x40\x5f\xf0\x1e\x88\x22\xdf\xc7\x82\xf9\x7c\x00\x6f\x22\x51\x82\x9a\x18\x11\xcd\xe4\xd3\x00\x08\x0a\xe4\x2b\x24\xdd\xb8\x9c\x02\xcd\x9a\xca\xc1\xb4\x0d\x7c\x90\xfb\xab\x87\xcf\xef\xdf\x3b\xee\xa3\xf1\x95\xbd\x30\x77\x3c\xdf\x55\xd7\xec\x1b\x75\xd1\x81\xc4\xfb\xab\xfb\xa7\xf1\xfe\x95\xb8\x86\xf9\x8f\x80\x3d\x5c\xfe\x2a\xe4\x90\x3e\x27\xc1\x9f\x89\x3d\x4a\x5a\x55\xd1\x6c\x6e\x3f\x4a\x0f\x8d\xf6\x49\x52\x28\xab\x55\x15\xf8\xc8\xbb\x68\xbf\xb7\x1d\xfa\x01\xfe\xac\x0b\x79\x8f\x78\xd2\x44\x49\xc6\xe6\xef\x9f\x4a\xdb\x0f\xc7\xbe\xbe\x4c\xb1\x18\x22\xaf\xe5\x97\x13\xb5\xbb\x97\x7a\x30\x6b\x74\xd4\x9f\xdc\x62\x6e\x1d\x08\xdb\xd8\x29\x95\x5c\xbc\x90\x29\x42\x19\x04\xbb\x2b\x28\xa5\x8c\x00\x26\xb8\x4d\x50\xd9\xcf\x73\x13\xc8\xd9\x6d\xcc\x41\x14\x04\x2f\x04\x6a\x9b\x27\x0f\x60\x76\x41\x39\x84\x2b\x19\x68\xdc\x1d\x27\xc4\x56\xf1\x0c\xa5\x4e\x9d\x44\x47\x02\x56\x99\x19\x3f\xd4\xbe\x6b\xb0\xa8\x6b\xf6\xd0\x64\x6c\x35\x14\x69\x1b\x45\x24\x5a\xd9\x48\x65\x05\x9d\x48\x10\xef\xa1\x92\x4a\x55\x09\x82\x2f\x27\xb5\xf2\x6d\x23\xe9\x60\x48\x80\x1a\x04\x54\xe2\x7d\x83\x86\x22\x65\xc0\x41\x25\xa8\x45\x44\x30\xd3\x98\x7c\x20\xd1\xb1\x87\xa3\x73\x6e\x2a\x12\xf2\x90\x5d\x73\xb0\x28\x53\xec\xcf\xde\x01\x12\x4d\xd0\xe2\xdc\x0a\x48\xfd\x54\x2e\x7b\x0f\x90\xa0\x03\x9c\xd4\x7e\x08\x2a\xf1\x62\x6f\x4b\x0e\xc8\x57\xbf\xbe\x54\x29\xa1\xe4\x8c\x5e\x76\x1b\xcd\x95\x70\xb5\x1e\xcd\x35\xfe\xc7\x86\x01\x2b\x76\xc5\x99\x03\x7b\xe9\xa9\xb4\xd1\x49\x1b\x18\x21\xad\x50\xc9\x4a\x0d\x0a\x8d\xc6\xb5\xa7\x20\x27\xcc\x15\x5a\x41\x6c\xb5\x1b\x20\xfe\x10\x2d\x21\x63\xdd\x65\x34\x28\xd7\xb9\x67\x61\x04\x8a\xcc\x12\xe5\xad\xed\xf6\x40\x60\x05\x4d\x4b\xc5\x95\xf7\x97\xe3\x8e\xfe\xa6\xcc\x8c\x14\xc4\xfc\x81\x9f\xcd\xa1\x35\xb9\xec\x76\x39\xa1\x07\x39\x7a\x28\x5b\x0e\x6a\xa7\x3b\x41\x19\xf0\x1d\xa9\xad\xa6\xcf\x25\x88\xdf\xbe\xd1\xbb\x50\x53\x09\xb5\xe8\x15\x19\x16\x09\xda\xd0\x41\x8a\xee\x56\xd9\x53\x20\x4f\x94\x3d\xcc\x62\x5e\x38\x76\x93\x9a\xaf\xb1\x96\x5b\xcc\x63\x5c\xab\x9a\xbf\x44\x27\xa9\x42\x38\x4c\xf2\x78\x7d\x99\x50\x06\x92\xb1\x01\x84\x71\x07\xda\x70\xef\x75\xa8\x72\x94\x74\x35\x27\xec\xbe\xd7\x7c\x21\xf5\x01\xab\x34\xb7\xa6\xd7\xa8\xe0\x0e\x82\x28\x2e\xa3\x32\xcc\x7f\xdc\xf2\x6b\xd4\xd6\x77\x4f\xbc\x42\x84\x57\xc6\x01\xf5\xed\xba\xd5\xda\x42\xaf\x7d\x9f\x36\x7f\xb4\x07\x29\xd7\x9c\x17\xce\x0d\x40\xdd\xcb\x81\x18\x0f\x49\xc7\x91\xfd\x6a\xa3\x00\xbd\x4c\x2d\xfe\x0c\x03\xa9\x9e\xcf\x00\xb1\xc8\x7d\x5b\x2c\x38\x51\x88\xc3\xdf\x78\x81\x50\xab\x08\x5a\x0e\x7c\x76\xd5\x36\x76\xea\x1b\x65\x2e\xcf\x09\x9f\x29\xe6\x64\x4e\xd6\xcc\x67\xe5\xcc\xe6\xa1\xeb\x83\x1e\x11\xfe\xf6\x97\x53\xe2\x08\x20\x66\xef\x0d\x49\xf0\x79\x4e\x7f\xe5\x1a\xab\xec\x79\x84\x42\xc8\x77\x60\xef\x7c\xf1\xb4\xfc\xa1\x12\xe6\x38\x26\x68\xe2\x36\xa1\xe0\xc7\xe0\x0f\x29\x92\xf6\x58\xa1\x2d\x21\xad\x80\xa6\x1d\x46\x99\xe2\x2c\x32\xe0\x0a\xb8\x96\xbc\x17\x8a\x54\x42\x5f\x3b\xf5\x65\x37\x71\x1c\xbc\x85\xe6\x92\x7d\x1d\x18\x1e\x15\xcd\x9f\xbf\xb0\xf3\xb2\xca\x0f\xb9\xa8\xfb\x35\xa1\xb8\xe7\x57\x95\x98\xb1\x7d\xbc\xae\xcb\x1f\xb8\xb0\x9c\xca\x8f\x7c\x62\xe7\xa5\xfd\xd0\x0b\xfb\xd4\x75\x5d\xd8\x48\x8a\xeb\xfa\x6e\x37\xf4\xff\x78\x2a\xf2\xfd\xf4\x0c\x75\xbb\x6f\xce\x0d\x79\x8f\x4a\xe6\x60\xd8\xe9\x3a\x9c\x53\xa6\x63\xaa\x81\x37\x20\x80\x77\x48\xd9\x22\x85\xd0\xed\x80\xe2\x36\x38\x11\x09\x65\x2f\x28\x87\xc9\xd9\x87\x02\x89\x67\x4f\xc8\xc5\xea\x52\x48\x29\x90\x87\xc1\x6c\x33\x2e\xd2\xb7\xda\x4e\x22\xa1\x08\x97\xc9\x3c\x34\xc8\xea\xec\x80\xc2\x63\xdf\xec\xa0\xa2\xe3\x9f\xdd\x4e\xc7\x85\x77\xfc\x0b\xfe\x7d\x1f\x0f\x84\x5a\x42\x02\x06\xb6\x38\xfa\x39\x1c\x7e\x52\x17\xdb\x5a\x52\xe0\xf9\xce\x30\xc2\x79\x2d\x87\x5f\x1d\x2f\x76\x57\xf3\xf4\xed\x1e\x1c\x7e\x47\x70\x7f\xa0\x2d\xec\x3e\x31\x6b\x15\x50\x09\x06\x2f\x82\xdd\xb2\x81\x32\xe0\x58\x57\x8c\x24\xe9\xd8\x59\xbe\x00\x7b\xdf\x97\x25\x5b\x8b\x9b\xd3\x1a\x49\x3b\xfa\x19\x20\x4c\xa8\x5e\xb1\x5f\x08\x6e\xf4\x74\x6e\x3c\xdb\x71\x41\x6a\x8c\x8d\x1b\x14\x75\xe5\x58\x7f\xfd\x83\x1d\x79\x49\x55\xef\xa2\x95\xbd\x65\xf4\x8d\x4a\x87\x43\xde\x2f\x9b\x39\x23\x3b\x82\xd0\x11\xfc\xe4\x08\x33\xb2\x93\xce\x16\x2e\x86\xf3\x82\x8e\xf3\x2a\x5f\x5f\x7a\x6f\xa1\xbf\x5f\xea\x64\x13\x45\x81\x7a\x6f\x0f\xfc\xdf\x4c\xab\x0a\xdc\xc3\x24\x24\x12\x8e\x09\xb0\x47\x0f\x08\x24\x87\x58\x99\x53\x71\xef\x53\x93\x13\x07\x88\x0d\xc3\x51\x43\xf6\xd7\xf6\xaa\x1e\x6a\xa7\x2e\xda\x3a\x8f\xf7\x86\xdf\x21\xd0\x67\x66\xde\x22\x8c\xae\x17\x94\x47\x03\x74\x46\xbf\x77\x32\xc2\xb0\x2d\x85\x67\xb6\x6f\x8a\xbf\x3f\x9e\x90\x48\x1e\x21\xcf\xf1\xfd\x33\x9a\x66\xbb\xbd\x0b\x43\xd3\x38\x0a\x19\x6d\x56\x62\x15\xaf\xce\x4f\x3f\x71\x96\x69\xd1\xc6\x21\x5f\x50\xe6\x41\x86\xaa\x72\xc4\xf3\xc5\xfa\xe8\xf2\x74\xde\xdf\xb7\x25\x4f\xf5\xde\x9f\x9e\xe1\x8f\xd2\xdb\x1d\xfe\x88\x12\xda\x03\xf3\x4a\x74\xea\x15\xd4\x14\xd6\xdf\xf5\x81\x53\xb3\x38\x51\x4a\x5c\x7f\xf9\xf6\xeb\x6a\x0f\xf9\x91\xc3\x8d\x56\x7e\xd4\x70\x52\x3a\xae\xf6\xf2\xc3\x06\x9c\xe3\x87\x5e\x2f\x4e\xf0\x47\x5e\xb0\x9d\xdf\x68\xe5\xc7\x5e\xb0\xe4\xde\x7e\xd4\x80\x10\xae\x9a\xd4\xdb\xf6\xe6\xea\xc7\x4e\xf2\x3b\x7d\x86\xd3\x69\xf8\x1f\x7f\xf7\xab\x4e\x74\x4f\x2e\x3f\x0d\x77\xf9\xc3\xe3\x79\x41\xff\x47\x9e\xde\x0f\x1c\x0e\x37\x4f\x89\x7e\x7d\x6f\xbc\xcb\xef\x1d\x90\x92\x1e\x3f\xf8\x71\x7c\xe3\x04\x7f\xef\x78\x66\xb8\x3e\x73\x7e\x97\xdf\x75\xc1\x3f\xf0\x89\xe0\x04\x7f\xe0\x78\x7c\x20\xbf\xe3\x0e\x5e\x3e\x77\x0b\x7f\xdc\x33\xf9\xfe\x86\xf4\x04\xa1\xf9\xe9\x9b\xa2\x69\x88\x3b\xe7\x07\x7a\x0f\x6f\xbb\x08\xde\xd9\x5e\x4f\x38\x56\xd6\x14\xd2\x9f\x1e\xa4\x99\x67\x59\x37\x05\xf8\xb7\xb6\x0d\x78\xb8\x99\xb6\xe8\xbc\x63\xbe\xe3\x8d\xf2\x27\x7f\xe9\xf2\x22\x45\x64\xcd\x1c\xa2\xc7\x3c\xbc\x79\xa8\x11\x9e\x3c\x7e\x4c\x8c\xa1\x3c\x0f\xb7\x13\x1a\xa2\x67\x76\xad\x16\x67\x32\x89\x28\xfb\xb1\x1b\xb4\xd0\x63\x8f\xfd\x33\x00\xb5\xf7\xdc\xc5\xc7\xb3\x5f\xe5\x05\xb6\x81\xb0\x2b\x64\x87\x94\x2d\x4e\x9b\x1d\xba\x70\x21\xe9\x8b\xa2\x5f\x1a\x64\xd7\xd0\xf9\x6d\x64\xfd\x31\xef\x0e\x57\xd6\x59\xb2\x0f\xab\x9f\x57\x06\x71\x0c\xe6\xd7\x93\x6d\x1d\x7f\x02\xde\x5a\xff\x88\xfe\x2f\x1e\xc7\x37\x3f\xf3\x14\x10\x35\xf5\x40\x09\x77\x62\x1e\x34\x07\x19\xe5\x00\x19\x96\x66\x67\x25\x2c\xac\x65\xe6\x33\x9b\x29\x40\x50\x68\xc6\xf1\xd1\xbe\xc0\xdb\x8d\x63\x68\xeb\xbc\xdd\xe9\x73\x13\xe1\xf2\xfe\x9c\x13\xb9\xef\x39\x9f\xb8\x96\x69\x93\x00\x69\xe2\xca\x1c\x36\x20\x14\x0d\xd1\xdb\x24\x46\xc6\xdc\x4a\x02\x86\x91\x76\xab\xe3\xf3\x37\x0a\xf9\xdd\x0c\x66\x43\xb0\x3a\xa4\x7c\x9c\xf2\x36\x4b\xdd\xe6\xf5\x45\x6a\x1f\x61\xce\xbc\x7b\x45\x3f\xb2\xa4\x1f\xbd\xa6\x1f\x51\xd4\x47\xdd\xc3\x3c\x11\x17\x12\xa1\x40\xae\x67\xa9\x72\x72\xb1\xfb\x01\x90\x7d\xd0\x59\x11\x43\x38\x13\x44\xd1\x43\x34\x94\xbe\x4b\x47\xa3\x55\x0e\x5a\xe9\x69\xe8\x0e\xd6\x32\xb1\x30\x13\x54\xce\xc8\x17\xf6\x61\x93\xa9\x03\x4e\x80\xf3\xf9\x52\xfd\x8c\x98\x74\x2a\x64\xec\x5c\x27\x85\x12\x67\x42\x19\xab\x08\x6e\x9b\x66\xb8\xe2\x3d\xe4\x99\x01\xf4\xe0\x89\x7c\xf1\x53\x41\xcb\xfc\x2e\xcd\x62\xca\xa2\x5e\x8e\xc1\xe9\x80\x39\xa4\x92\x95\x22\x23\x4b\x50\x3e\xe3\xb4\x3f\x21\xcb\x7e\xfa\x16\xaf\xa2\xa4\xac\x98\x6b\xe8\x44\x07\xba\xa7\x56\xd0\xea\x80\xd2\x61\x38\x1d\x91\xdd\x50\xd6\x7c\xee\xad\x45\x4f\xa0\x03\xa7\xb4\x01\x98\x67\x6e\xd0\x58\x60\xb5\x58\xc0\x35\x90\xc5\x82\x43\xc8\xf2\x20\xd3\xec\x83\x5b\xf0\x59\x73\xc0\x0f\x2f\x99\x1d\x4c\x59\xa0\xa4\x5b\x80\xce\x60\xf2\x78\xda\xac\xd3\xd0\x90\x05\xc9\x01\x2a\xea\x78\x33\x3e\xd8\xd6\xc1\xe6\x0a\x18\x60\x26\x63\x52\xad\x3b\xa5\x68\xf9\x0f\x02\x3d\x72\x09\xeb\xe8\x63\x0d\xf0\xd0\xb4\xf5\x24\x43\x21\xbd\x80\x06\x1a\xf1\x3b\xf8\x30\x9d\x73\xaf\xe7\x40\x7e\x54\xa0\x9e\x70\x7e\x60\xe8\x4d\x44\x42\x4a\xdf\x31\xa8\x27\x92\xfd\xef\x8e\xb5\x24\x84\x58\xd5\xe4\xfc\xac\xa4\x10\xeb\xb8\x64\x18\x0a\xa2\x2f\x08\x34\xac\xc5\xc9\xc8\x6c\xfe\xe7\x19\xe2\x24\xe3\x19\x5f\x42\x4f\xb5\x87\xfb\xa1\xe4\x7b\xc6\x08\x17\x30\x95\x91\xe4\xe8\xfc\x9d\x23\x9e\xbf\x7e\x8d\xa4\xaa\x43\x3d\x32\x94\x8d\x04\xc4\x7d\x8b\x8a\xca\xac\xb7\x6c\xa2\x82\x30\x91\x1c\x27\xef\x59\xed\x21\xd7\x0d\x98\xb4\xec\xea\xcc\x98\xfe\x2c\x2f\xea\xc4\x3d\xdc\x00\xa5\x94\x89\x96\x08\x6d\x58\x72\x52\x99\x0f\x0b\x8a\xac\x98\xb0\x9c\x98\xcd\xe0\x66\x30\x1b\xe3\xc4\x28\x83\x5d\xbe\x38\x2e\xf7\x60\xae\xae\xa7\xc3\xe1\x05\x8d\x72\x02\xbe\xbb\x61\xb5\x8c\xdd\x6c\xe9\x28\xf6\x43\x41\x92\x5c\x6c\x7b\xa8\x2e\xa8\x20\xd3\xc9\x31\x5a\xd9\x91\x7c\xa1\xb9\xe2\x6e\x05\x02\x15\x18\x39\x58\xe5\xb5\xa5\xd5\xba\xc3\x64\x85\x69\xc6\xca\x99\x31\x54\xc0\xe9\xcf\x5b\x3e\x42\x59\x14\x0a\xd1\x6f\xb7\x39\x45\x19\xda\xd8\x75\x43\xe7\x14\xa8\xc7\x04\xc6\xa1\x10\x5d\x4b\xfd\x24\xdc\x1f\xaf\xfc\xc9\x6a\x07\x41\x7e\x9c\x19\xb9\xba\xc0\x60\xbc\x4f\x91\x37\x2a\xf2\x4e\xb1\xa0\xa4\x81\x90\x16\x3d\xdb\xa4\x2c\x80\xbc\x60\xfe\xa3\xe5\xc7\xbe\xdf\x13\xd1\x08\xad\xee\x1d\x6c\x47\x76\xbb\x20\x74\x85\xad\x67\x40\x8a\x1c\xfa\xf2\x84\x70\x08\xb3\x4e\xb6\xbe\xb0\x6d\xa3\x62\xa6\xc5\x79\x3f\x5a\xda\x63\x85\x56\xdc\x64\x39\xb8\x15\x27\xf3\x42\x32\xdd\xee\xdb\x9d\x5b\xcb\xd7\x40\x22\xc9\x0a\xf0\x1b\x23\xd4\x84\x91\x51\xe9\x9e\x4e\x24\x04\x26\x6b\x9b\x1c\xb9\x86\x5a\x43\x41\x17\x72\x2c\x40\x2b\x42\x4b\x1c\x36\x84\x2c\xfa\xf6\x30\xfa\x1e\x69\x85\xec\x8e\xa4\x13\x74\x97\x30\xdb\x7d\xa3\xc2\x34\x02\x10\x09\xb3\x9e\x3a\xfb\x1d\xb6\x89\xd8\x84\x45\xbc\x83\xa5\x25\x23\x4c\x5b\x4c\xf3\x2c\x4f\xe0\x75\x26\xc9\xcf\x79\xdc\xb1\xbe\x6a\x73\x6b\x2c\x26\x66\x5b\x50\xeb\xf7\xae\xed\x0a\x9c\x58\x54\xd6\xcd\x37\x05\x02\xa7\x03\x0a\x22\xa4\xa1\xeb\x41\x67\xe8\x94\x28\xab\x30\x28\x9f\xb0\xea\x4f\xe8\xd1\x9f\xbe\x49\x0e\x9b\x6a\x7b\xd8\xf8\x3f\xec\x65\xf4\x7d\x39\xae\x8d\x39\xae\x9d\xf9\x1d\xe5\xb9\x4f\x8c\x35\x33\x32\xe5\xe4\x61\xaa\xc3\x35\xc9\x4f\x9f\xe1\x74\x19\x5e\x5f\x46\xae\xab\x70\x4f\x06\xb7\x47\xef\x28\x9e\xee\x51\x3c\xfd\xa3\xf8\xe0\x20\x7d\x7c\x26\x97\xfb\x65\x0d\xf7\xf1\xdc\xed\x7b\xf4\xfa\xde\x38\x7d\x5f\xfb\x7c\xa4\xa6\x71\x42\x98\xb5\xbb\x91\x24\xcb\xf9\x25\x95\xb2\xfe\x68\xba\x51\x12\xd7\xb2\x67\x93\x54\x3e\xb9\xdb\xd2\x3d\x4e\xaf\xdb\x29\x84\x56\xd3\x73\x3c\xbb\x9e\x63\x7f\x74\x8e\x1f\xda\x50\x8f\x37\x57\xb6\xdb\xaa\x4a\xe1\xb1\xcd\xe3\xa1\xb3\x63\x37\x3f\x23\xd0\xf3\xbd\x90\xae\xa5\x15\xa7\xe6\x4b\xf4\x2a\x6b\xd9\x73\xb5\xa3\x6a\x06\x0c\xe4\x28\x25\xb4\xfb\x16\x97\x17\x61\x25\x02\x04\x77\x69\xe3\x83\x4f\x1b\x97\x53\x1b\x97\x57\x1b\xef\x6e\xed\xeb\x4b\x9d\x12\x6a\x93\x4d\x69\x94\xda\x16\x6b\x87\xbe\xc1\x74\x6d\x25\xe5\xde\x21\x2c\xce\x8a\xda\xb6\x31\x82\x80\x7d\x49\x83\x1f\xa2\xf3\xc0\x7f\xcd\x03\xa0\x10\x49\xd9\x04\x7b\x73\x1b\xbb\x1f\xc3\x91\x0e\x2a\x3f\x58\xe0\xc4\xbe\x8b\x7c\xd9\x68\x10\xeb\x86\x84\x7a\x97\x9d\x50\x63\x9b\x3a\xb3\x06\xad\x63\x9b\x12\xa6\x6c\x9a\x7a\xd0\xd4\x51\x20\xd0\x90\x13\xa4\x63\x70\x6a\x9f\x58\x81\x4f\x18\xda\x9f\xce\xee\xa9\x81\xfa\x10\x94\x20\xc0\x38\x08\x41\x32\x77\x0c\x91\x35\x96\x05\x8f\x66\xdd\xd3\x5e\x12\xe5\x4a\xd2\x76\x7a\x7b\x5e\x53\x89\xab\x8e\x10\xd5\x5b\x37\xd1\xed\x90\x60\xac\x0b\x4b\xf4\xe8\x42\x23\xe7\xff\x00\xc4\xa7\x17\xf8\xd0\xa2\x65\xd7\x11\xa4\x78\x71\x43\x07\x94\x2b\x59\x58\xf7\xf2\x06\x36\xa1\xd7\x17\xc9\x75\xe9\xfc\x0b\x67\x73\xe7\x46\xa6\x08\xb1\x60\x08\x07\x5c\xa5\xb1\x47\x94\x8c\x23\x9e\x70\x37\xdf\x20\xe8\x65\x07\xeb\x1c\x18\xf1\x24\xd7\x03\x65\x57\xe9\x28\x8e\xe0\xb1\x98\x2f\x7b\x67\x4d\x43\x5b\xcd\x1e\xc9\x58\xe5\x2c\xd1\x8e\xe8\x61\xad\xcb\xde\x3b\x97\x8f\x0c\x76\x8c\x94\x16\x46\x5a\xf8\x00\x25\xfb\x5e\x9f\xac\x56\xa0\x67\xe7\x40\x5f\x08\x36\x2e\xf0\x5b\x11\x31\x47\x97\xa5\x42\xbb\x97\x6b\x50\x0e\xf0\x39\x99\x29\xdf\x23\x65\x63\x0a\x82\x00\x54\x97\x51\x37\xa4\xe3\xe2\x38\x67\x3d\xe1\xb8\xda\xbc\xb2\xc4\xb5\x01\x55\x0a\x49\x17\x5c\x17\xd8\xf6\xc6\x09\x65\x64\xe8\xc4\x20\xba\x9e\x7b\x27\x68\x28\x8b\x73\x1b\x30\x4a\xee\x30\x08\x63\x04\x3f\x3d\x8b\x03\x9c\x98\xa9\xec\xe0\x9c\xb6\xfd\xbf\xe6\x83\xf4\x4f\xa2\xed\xf0\xb0\x2c\xef\x88\x13\x00\x48\x68\x6c\x7f\xf4\x57\x3b\xa6\xb4\x94\x20\x63\x17\x19\x00\x1b\x6a\xb7\x0d\x1b\x90\x3c\x68\xde\xd8\x47\x81\xd5\x3c\xd9\xab\x3b\xa6\x30\x08\x5f\x6a\x20\xe4\x18\x8d\x13\xa2\xe9\x16\xa7\x63\xe3\xcc\x16\x0d\xa7\x9f\x66\xb3\x3f\x35\x45\xf1\xe6\x15\x87\xe1\xa0\xe4\x07\x80\xfa\xfe\x88\x77\x0d\xd2\x1b\x47\xfa\x50\x98\xf4\x6a\x9f\x73\x84\x87\x91\x8f\x87\xdf\xfc\xc4\xe2\x7c\x02\xae\xfe\xf4\xdc\x99\x56\x73\x5d\xe4\x2c\x05\x76\x4c\xf8\xf8\xa3\x3a\x5d\x23\x1e\x25\x09\xb6\xcc\xc8\x31\x9f\x80\xc7\x89\xcb\x43\x40\x69\x6e\x44\xaa\x94\x02\x61\xe6\x83\x88\x6c\x30\x2e\xba\x84\x9b\x79\xd2\x9c\xdf\xf5\xa4\xd0\x02\xa3\x22\x81\x96\x6c\x55\xa5\x73\x07\x5f\x22\x50\xd2\x10\x4a\x51\x29\xa4\x43\x5a\xc8\x87\xe0\x91\x1c\x3d\x08\xf8\x7e\x7b\xb7\x90\x45\xb1\x65\xad\x17\xbb\x4c\x94\x93\xa6\x6d\xe2\xaf\x2f\x52\xe6\x08\x95\x93\x8b\xc8\x9f\x00\x8b\xb2\x78\x18\xda\x97\x7a\xd9\x62\x0b\x82\x28\x14\xd8\x4e\x44\xcd\x20\x5d\x23\x3a\x2a\x30\xce\x68\x24\x55\xad\x12\xa2\xc5\xac\xa0\x43\x23\xe5\x89\x76\xa2\x3a\xd8\x70\x76\x6e\x70\x8b\xdb\x00\xb4\x8f\xa4\x26\xbc\x8b\x93\xcd\x7b\x63\x62\x04\x11\x9b\x9d\x90\x5b\xbd\xcc\xfe\x8e\x08\xba\xf5\xec\x5e\x22\x09\xf2\xbe\x2c\x7d\x15\xb4\xfe\x12\x03\x8f\x72\xba\x48\x3f\x9a\x39\x5f\xb6\x00\xd0\xb9\x81\x9e\xaf\xcc\x79\x9e\x48\x79\x07\x52\xb3\x26\xe6\x12\x26\x7a\xb5\xed\x6e\x67\xd9\x7b\x90\xe5\x70\x92\x8d\x2f\xce\xe5\xd6\x84\x1c\xc6\x4c\x6c\x65\xa7\xa5\x8e\x35\xb3\x50\x17\x35\xed\xf0\xb4\xd1\x91\x02\x87\xc6\x66\xc8\xb0\x07\xe2\x79\x2a\x75\xea\x79\x69\x61\xa6\x9b\x59\x31\xa5\xc3\x99\xd7\x04\x13\x52\xd7\x52\x29\x17\x53\xa7\xe1\xaf\x3d\x14\xbf\xed\xca\x46\x3d\x33\x17\x16\xf9\xfb\xae\x9c\x06\x7a\x25\x83\xaa\x1c\xb3\x05\x95\x74\x40\xa1\x0a\x5b\x39\x14\xc5\xc2\x40\x1c\xab\x61\x82\x62\x65\x5e\xf6\x0c\x48\xb0\xfd\x17\x3c\xc2\x5e\x8d\x46\x42\xa2\xb3\xd5\x29\xaa\x08\xc0\x5a\xd0\xa5\xaa\x3d\x40\x8d\x28\x8c\xe1\xd2\x1a\x59\x76\x74\xe6\x61\x33\xcd\x3b\xa2\x26\x70\x92\x93\x28\x11\xdd\x77\x76\x97\x3e\xb1\x46\x9f\x10\xb9\x3f\x3d\xf7\x3f\xb6\xb6\x12\x13\x23\x4b\x18\x2d\x3b\xff\xbd\x2d\xb4\xb1\x29\x90\x77\x65\xec\x00\xdc\x51\xaf\x20\x82\x5a\x1e\x11\x70\x32\x9f\x9a\xc0\x35\xf8\x5b\x5b\x04\x44\x4b\x32\x8a\xe9\x59\x97\x78\x0f\x53\x1a\xde\x49\x80\x2e\x92\x6a\xe6\xb1\xb6\x0d\x37\x3f\x66\xbd\xc6\xb9\x56\x7d\x73\xb5\x23\x76\xb1\x10\x53\xdb\x83\x99\xd6\x72\xb4\x1a\xb2\x6e\x8a\x20\xf8\x1a\x4b\x19\x50\x7f\x49\x94\xfa\xa3\x29\xc1\x0c\x91\x5d\x2d\xba\xc8\x1a\x5a\x3d\xda\x0c\xda\xb6\x52\x34\x88\xfd\xb0\x84\x56\xf0\x35\x38\x90\xd0\x8f\x34\x37\xb0\x9b\xa9\xcf\x6c\x8f\x25\x13\x67\xab\x8e\x2e\xb9\x4a\xda\x8a\xf9\x8f\x68\x8d\xad\x94\x05\xca\x54\x35\x6d\x1a\x0a\xe3\xc5\x41\x26\x5b\xa4\x63\x72\x06\x11\xed\xd1\xd4\xf5\x7b\x5c\x59\x4a\xb7\x62\x61\xe7\x6c\x9b\x22\xf3\xd0\xc1\x61\x9e\x39\x2f\xf9\x67\x07\x9c\x03\x5e\x0b\xfd\x71\x6c\x77\x5b\x94\xd1\xa8\xf0\x90\x2b\x23\x7f\x75\xba\xcd\xc1\x00\x49\x7b\xc8\x23\xf4\x16\x32\x04\x98\x25\xb4\x26\x9b\xa0\x2f\xc1\xfc\x34\x85\xb0\xd0\x16\x6b\xd0\x0d\x19\x8f\x01\x09\xa8\xe1\x3a\x6d\x41\x02\xc5\xa2\xbe\x2c\xd5\x28\x2c\x10\xe6\x7f\x10\x74\x59\x5c\x0b\x90\x4d\x41\xde\x20\x23\xab\xd4\x1d\x5d\x9f\x41\x52\x02\xe0\xa0\x19\x16\x0a\x7c\x56\x2c\xc4\x03\x7d\x0a\x30\xea\xfa\xc0\xf1\x3b\x0f\x60\xd6\x90\x80\x2a\x90\xd3\xa8\x1b\x91\x9b\x6d\x2f\x01\x0c\x57\xc0\xc7\x94\xbe\x39\xed\x93\x7b\xb7\x36\x33\x2d\x7e\x46\x8f\x80\xb9\xf8\xb5\xec\x1a\x10\xb9\xda\x2a\x44\x64\x6f\x51\x64\x42\xea\x8c\xcb\xc5\x3c\x08\xc8\xaa\xd9\x86\x3d\x2e\x08\x27\xa0\x77\xd5\x82\xed\x2f\xcc\x1f\x0d\xe0\x5e\xec\xa6\xd8\x22\x54\x46\xf5\x08\x86\x3c\x78\x15\xdc\xf0\x3d\xc3\x0f\x63\x70\x50\x8e\x46\x2f\x27\x6d\x9e\xc1\x54\x73\x8d\x35\x94\x4a\x87\x0e\xe9\x44\x30\x92\xd6\xa3\xb0\x87\xcc\x62\x03\x1b\xd3\xbe\xd8\xc8\x4a\x1b\x4b\xdb\x94\x32\x46\x69\x43\x09\x27\xe7\x8e\x6d\x00\x85\x01\xc4\x1a\x4e\x17\xde\xf6\xdc\x91\x0c\x68\x81\x75\x9c\x2a\x9b\x90\x94\xc6\x69\x62\x64\xb6\x1d\x7b\x25\x2e\xd1\xe5\x79\xa8\x00\x26\x41\xdb\x05\x32\x6c\xe0\x36\x51\xf0\x8c\xb7\xd0\xc5\xd6\x48\x96\x1d\x0b\x10\xf0\x05\x34\x8c\xf9\x62\xfc\x84\xa5\x79\x02\x28\xff\xf4\x2d\x46\xee\x8c\x3b\x00\x87\x3c\x81\xaa\x64\x8f\xa3\x21\x32\xa7\x9b\x2a\x44\x65\x60\xeb\xc1\x61\x62\xa1\x83\xfd\x69\x66\xe0\x67\x50\xa4\xde\x83\x0c\xdb\xad\xc7\xe1\x12\x06\xe2\xdd\x7a\xc8\x8b\x1c\x42\xaf\x0d\x18\x25\x66\x1c\x4a\xd0\x2a\xa1\x54\x90\x61\xb8\x52\x0a\xe0\x38\x92\x82\x8a\x90\x0b\x56\x7a\xd0\x09\x16\x63\x14\xef\x86\xcd\x77\x68\x12\x90\x8f\x6c\x13\xf8\x2f\x3a\xf7\xa9\x38\x1c\x7f\x76\x45\x41\xdd\xbb\x1a\xc5\xd3\x99\xce\x5f\x0a\x5a\x64\xec\x92\x02\x1b\x80\xe6\xba\x44\x81\x18\x70\xc3\xdb\xb2\x51\xa6\x0a\x95\x96\x52\xf9\x5d\x08\x91\xee\xab\x03\x92\xc6\x97\x27\x7a\xd7\x84\x9e\xae\xab\x02\x78\x91\x19\x55\x33\x6e\xee\x1d\xce\x20\x8d\x48\x5c\xd5\x09\xaa\x1c\x64\xbe\x8a\x79\x4b\x9a\xb6\x1e\x3a\xdb\xba\x21\x6d\x3a\xe1\x13\x64\x20\x8a\x6d\x1c\xcd\xe5\x40\x87\x7b\x01\x9b\x31\xda\xca\xb3\x7b\x3a\x48\x82\x92\xa9\x21\xc0\xe4\xe7\xa5\xa1\xd8\x52\xb0\x05\x5b\x5b\x18\x45\x2e\x30\xe9\x00\xa3\x0e\x45\xa7\x0d\x68\x53\x73\x50\x06\x40\x30\x5f\xa0\xa3\x40\x4e\x28\xdd\x65\xb8\xe4\xc4\x91\x62\x73\x04\x5e\x1a\x2f\x06\x17\xbd\x50\x06\xb1\x04\xec\x35\xe8\x88\xca\x2e\xca\x94\x40\x79\x95\xa9\x59\x4d\x44\x5f\x2e\x1b\x14\x93\xb2\xf6\xf3\x47\xf0\xff\xd7\x17\x91\x66\xa3\xea\x56\xec\x9a\x04\xed\xa9\x10\x7d\xaa\xe8\x47\xdf\xc1\xe0\xad\x1d\xf1\xf9\x0c\x79\xcc\xbd\xe1\x1e\x07\xa2\xc9\xd9\x58\x89\xbd\xb0\x2d\xcf\x27\xb9\x44\x92\x26\xd7\x67\xa2\x20\x26\x92\x30\x65\x84\x41\xb1\x3a\xf5\x28\xb0\xa0\x61\x58\xca\x3e\x50\x94\xb3\x2f\x36\xe1\x2e\x5f\xfa\x7b\x07\xda\x1f\x29\x87\x94\x90\x41\x43\xaf\x48\xfe\x07\x15\x20\x2c\xcd\x25\x41\x2c\xeb\x04\xc4\xde\x3c\x1e\x33\x58\x0c\xa4\x84\xd9\x64\x8b\x33\x94\xcd\x1c\xd6\x4f\xac\xec\x27\xac\xf4\x4f\xcf\x4d\xd4\x50\x97\x5c\x69\xb0\x14\x4a\xf6\xe6\x31\x84\x5a\xd8\xe6\xca\xee\xf4\x3b\x76\x61\x68\x61\x47\x67\x97\x52\xd9\xc1\xde\xc0\xbf\xed\x68\xfa\xf8\xa5\x9b\x13\xb5\xf3\x8e\xb4\x11\xb4\x93\x20\xdd\x56\x1c\x1a\x45\x9a\x59\xe5\x7d\xb2\x92\xc9\x5a\x07\x36\x18\xdf\x08\xa2\x28\x61\x2e\x58\xb6\x36\xe5\xc6\xe9\x66\x2b\x43\x5c\xfa\xc2\x9e\x01\xa0\x9e\x9d\xf4\xb4\x5a\xb5\xc1\x8d\x7e\xe8\xf0\xba\xaa\xff\x83\x09\xc8\x03\xa8\x36\x3b\xc0\x9e\xf8\x20\xaf\x8f\xb4\xb6\x83\x2a\x19\x74\xf3\x65\x02\x66\x3a\x87\x99\xd8\xa8\xa2\xf6\xf0\x5b\x68\xc2\x38\x7b\xea\xe2\xd8\xca\xe8\x66\xcc\x6b\xf5\x6f\xd4\xe3\x5d\xe4\x86\x4d\x43\xdd\x47\x36\x47\x86\xc8\x72\x3a\x81\x90\x2f\x64\xd7\xb5\x37\x5d\x4f\xb3\xd6\x94\x4d\xa3\x3e\x1b\x7d\xd8\x86\x0e\x04\x49\x94\x48\x25\x2f\x19\x45\x4c\x5f\xfa\x34\x3f\xa6\xdf\xa2\xee\xe8\x14\x43\x0e\x15\xc2\x7d\x09\x54\x15\xd5\x82\x1c\x86\x10\xe0\xfd\x61\x6c\xad\x16\x41\xbf\x5e\x5e\x24\x65\xdb\x94\xca\x1e\x07\x15\x36\x1b\x88\xee\xa1\x8c\xa5\x29\xa0\xa6\x51\xba\x79\xaf\x19\x55\xbf\xda\x90\x06\x60\x3e\x22\xcf\x87\xf4\x03\x1d\xe9\x48\x8e\xe6\x5c\x43\x65\xb7\xa3\x80\x98\xdc\xf6\xba\x1e\xfa\x3c\x8a\xf9\x1b\x7b\xb1\xd3\x83\xb0\x46\x2f\xbb\x9d\x60\x83\xdf\x0d\x57\xab\xdb\x9a\x34\xff\x89\x58\x69\x3b\x3b\xdc\x51\xae\xc9\xe9\x9d\x1b\xe6\x16\xd8\x34\x81\x48\x9b\x57\x67\x7c\x99\xa6\xe5\xa9\x7e\x62\x55\xfc\x8f\xa7\x55\x71\xa7\x55\xc7\x12\x98\xce\xa2\x0d\x2e\x6e\x73\x89\x30\x0d\xe0\xf1\xa0\x84\x89\x4c\x06\x61\xad\x22\xac\xea\xa3\x79\xa4\x9f\x6d\xed\xd8\xd4\x87\x97\x22\x10\xba\x53\x48\x8e\x7d\x23\x2b\x71\x68\xd1\x50\xf0\xa6\xf8\x99\x11\xde\x7b\x5d\x0d\x55\xb6\xbd\xa0\xde\xda\xc3\xe8\x68\xf8\x03\xb2\x53\x2b\x19\x33\x2b\x81\xfa\xb5\x3f\x80\x15\x84\x09\x01\xa5\x6b\xb9\xfe\x21\xc7\x79\x54\xf3\x97\xd4\x6f\xe0\x11\xda\xd8\xd6\x3c\xba\x86\x51\x13\x28\x07\x4b\x40\x0f\x2e\x5a\x87\x32\xdb\x3b\x90\xc7\x74\x9a\x03\x3d\x01\xda\x76\xe7\x8f\xc8\xf4\x94\x0b\x59\x9e\xa8\xf2\xdd\xce\x97\x0d\x29\xf9\x0a\xd1\x21\x08\xf6\x5a\x80\x1a\x0a\x77\x6c\xb4\x43\x8e\xa0\x6a\xe6\xd5\x7f\x3f\x16\x04\x4c\x36\x55\xbc\x85\x0e\x6a\xdc\x2c\x04\xa2\x73\x19\x7b\x2e\x1b\x0d\x34\xf5\x30\x2b\x03\x3e\x25\xa6\xba\x33\x3e\xa0\x60\x3d\x9b\x21\xe6\x1e\x1b\x81\xa1\x9c\x4c\xae\x19\x83\x92\x8b\x1b\xfe\xc2\xdc\x46\xef\x36\x03\xcd\xe5\xc4\xe5\xb5\x7e\x4c\x56\xcb\x99\x35\xb3\x70\xa7\x97\x3b\xe2\xdc\xd1\xa7\x9c\xff\xc8\xa0\x29\x37\xfa\xaa\x5e\x7f\xb1\x55\x70\x34\x7b\xb1\x4b\xb7\x7b\x61\x63\x4b\xff\x4c\xee\xe8\x3f\x28\x75\x74\xf9\x9d\xb9\xa3\xbf\x3d\xad\x9e\x7b\xd3\xb3\x76\xdb\x66\x17\xe4\x1b\x09\x4f\x34\x79\x09\xcd\x30\x38\x18\x06\x82\x73\xf4\x8f\x21\x3a\x56\x8a\x58\x30\x59\xa1\x0d\x34\xae\xfd\x00\xfd\x3d\xd6\x85\x27\x0c\xe9\xe0\x31\x9a\x71\x30\x0a\x8c\x27\xf9\x6b\xb8\x13\xa9\xcb\xda\x84\x68\xa1\x25\xbb\x7b\x83\xee\x35\xcc\x1a\xc0\x7d\x6f\xcb\xda\x19\x3a\xa4\xa0\x60\x45\xaf\xc3\xcc\x3e\x9f\x67\x55\xd7\x38\x95\xc9\x3b\x8d\x1a\x44\x7b\x28\x66\x23\x21\xeb\xab\x7e\x12\x97\x5f\x2e\x98\x1d\x6c\x87\x43\xef\xd8\x3a\x1f\x96\xfc\x93\x73\x40\xb0\x56\xc6\xc5\xa2\x47\x74\xb6\x7a\x02\xae\x84\x37\x20\xb2\xd1\x34\x07\x2c\x36\x92\xa5\xf4\xc3\xd9\xdc\xe0\x7b\x34\x96\x97\xd9\x20\xe8\x02\x92\xb0\x17\xe8\x16\x52\xaa\x4f\x2a\x72\x4f\x0c\xef\x25\x77\xba\x6f\xf6\x51\x23\xc1\x3f\x8b\x38\x48\xa1\x61\x22\x4c\x4a\xf2\x26\x12\xde\x96\x45\x38\x61\x06\x09\x69\x26\xd4\x3c\xeb\x01\xf3\x6e\xab\xbf\xfa\xa9\xdb\xf4\xe9\xce\x35\xb1\x17\x33\x5d\x7d\x9a\xff\x8e\xcf\x79\x64\x5e\xaf\x30\x0f\xd8\xa3\xc4\x3d\xa4\xb8\x6e\x59\xa1\xf2\x96\xda\x5e\x67\x1e\x7f\x4e\x47\xb3\x69\x01\x68\x89\xe2\xfc\x21\xc7\xfa\xff\x57\xea\x6b\xae\x9b\xbf\x3f\xad\x9b\x67\x59\xfa\x87\x7c\x4e\x71\x42\x6c\x31\x8f\x31\x28\xad\x6d\x83\xff\xd2\xee\x32\xab\xbb\x52\x03\x0c\xf9\xea\x0e\xf7\xa4\x74\xef\x82\x60\x65\xb5\xc3\x89\xea\x0c\x83\xcc\x3e\x66\x76\xf2\xa2\x20\x02\x3f\x05\x78\xc2\x41\x9d\x30\xcc\x30\xb0\x01\xca\xc2\xb3\xc1\x0b\x61\xe5\x7f\xb2\xa0\xc4\xcf\x40\x7d\xc5\x8e\x35\x88\x39\x67\xe8\x91\x0d\x5d\x3d\xe8\xe0\xa1\x58\xad\x42\x54\xd1\x10\x85\x69\xd7\x8c\x7f\xd1\xbd\xcb\xb4\xbf\x1d\x6b\x80\x0f\x15\xed\xa3\x08\x24\x6c\x03\x99\xf4\x81\x49\xcc\xc5\x90\xde\x2b\x3e\x74\xb1\x9a\x83\x12\x9a\xb7\xc0\x38\x7b\x91\xa7\x2c\x2a\x77\x30\x26\x08\xeb\x20\xa5\x9e\xfd\xf5\x8e\x92\xe6\xf9\x4f\x16\xdf\xb1\xf2\x2b\x16\xef\x64\x01\x94\xfd\x2a\x81\xc7\x60\x56\xf3\x8b\x75\x80\xa4\x6f\xa5\x88\xa2\xa2\x45\xa7\xe5\x50\xcf\x1a\x0e\xb9\x57\x4f\x6e\x9d\xd8\x1d\x6c\x43\x69\x3e\xbb\x8a\x0b\x2e\x6d\x49\x80\x84\x82\x68\x79\x22\x6f\x81\xcd\x32\x41\x4d\x64\xda\x7d\xca\xd8\x5f\x44\xec\x06\x6a\xde\xfb\xa0\x57\x89\x32\x52\x92\x83\xf7\x5c\x6a\xda\xe1\xdc\xda\x13\x81\x78\x12\xee\xb0\x9c\x3a\x23\x48\xb4\x41\xe5\xd8\x73\x6e\x8e\xea\x5b\x49\x61\x08\x97\x6b\x23\x02\xaf\x7a\x5f\x11\xd0\x08\xf0\xff\xf3\xb1\xf2\x9a\x28\x94\x69\x40\xf7\x27\xb6\x63\x73\xed\xb1\xf9\xc0\xe8\x23\xf2\x6f\xc0\xab\xa3\xf1\x13\xe4\xe6\xf6\x8c\xbe\xcd\xfa\xc6\x85\xf2\x8f\xa7\x85\xf2\xeb\x1b\xde\xc5\x77\x37\x98\xe2\x1b\xcc\xf0\x0d\x86\x62\xea\xe5\xdd\x0d\x46\x5d\xc1\x8d\xd2\xad\x9f\xdf\x64\x68\xbe\x85\x9b\x8c\x3e\x6d\x32\xf6\xf0\xe1\x29\xd0\x77\x7c\xda\x64\x48\xbf\xb4\xb6\x19\x67\x83\xde\x61\xbc\xdf\x6e\x34\x9e\x73\x46\x59\x5d\xb8\x3c\x32\x49\xbf\xa0\xa0\xc5\x52\x27\xd2\x6d\xf7\x93\xb2\x2d\xde\xcb\xa5\xe3\x0c\x21\xfb\x43\xad\xf4\x34\xd8\xef\xec\x36\x8c\x99\xd2\xf9\xf2\xab\x1d\x07\xad\xc4\xbf\x63\xcb\x01\x49\x08\x52\x24\x6f\xb6\x9c\x73\xc3\xf1\xed\x06\x99\x52\x4a\x5f\xf2\xcf\xda\x6a\x68\x3d\x2e\x2e\x4b\xf9\xd5\x7e\xf3\xbd\xed\xa6\xac\xcd\x06\xeb\xc1\x7f\x65\x52\xec\xdb\xff\x3a\x9b\xed\x52\xdf\x14\xc2\x1e\x0e\x52\xa7\xee\x02\x87\x14\x97\xd0\xe6\x7f\x9a\x9f\x76\xf9\xd3\x35\xbe\xff\xf9\xb4\x8c\xbe\xd5\x27\x8d\x06\x50\xbb\x56\xba\xca\x85\x99\x67\xea\x6f\x0f\x88\xdb\x9f\x80\x0e\xb9\x03\x3d\x5c\xa7\x51\x57\x55\x08\xee\x0f\x80\x8f\x48\xd1\x0c\x07\x9b\x3a\x3f\x84\x93\x5c\x09\x91\xd3\x98\xc0\x93\x15\xff\xc6\xca\x0e\xc7\xa4\x61\x66\x66\x56\x08\x54\xb4\xf8\x1f\xb9\x08\xdb\x14\x40\x43\x81\x8c\x41\x11\xd2\x25\x67\x62\x6d\x5d\x3c\x1c\x84\x33\x99\xfb\xa1\xcd\xc5\x16\x46\xc3\xf3\xad\x41\x75\xb3\xa0\xeb\xb2\x77\x81\x95\x6a\x0e\xf1\x10\x22\x40\x18\x36\xb1\x70\x74\x30\x7e\x66\xe1\x10\x03\x84\xd2\x2a\x76\xd2\x40\x21\xfb\x0c\xa4\x5a\xf3\x16\xfe\x23\x62\x9b\xd9\x22\xe8\xb9\x72\x79\xb8\x42\xe4\x93\xe0\x15\x0e\x04\x19\xb9\x96\x00\x76\x6a\x32\xd3\x97\xa4\xf7\xaa\x9a\x72\xa7\xdb\x91\x73\x43\x1e\xc9\x82\xa6\x03\xcd\x8c\xb9\x83\x4b\xa9\x24\xec\x83\xb9\x6c\x51\x82\xdc\x28\x25\xdb\x42\xc3\xcc\x35\x0f\x4e\x42\xad\x3b\xda\xcb\x50\x21\x41\xe6\x59\xcd\xd9\xa2\xe2\xd7\xb8\xa0\x9a\x4d\x89\x22\x94\x2e\x46\x88\x30\xf7\xe6\x95\x36\x56\x5a\x8b\xeb\x64\xa1\xbe\x6f\x6e\x5f\x9d\x47\xf1\x8c\xde\x66\xb1\x96\xf4\xbe\x6b\xa0\xfa\x82\x2e\x4e\x14\xe6\x1a\xc4\x99\x29\xd0\xb0\xc4\x7b\x8a\xe4\x6e\xee\x7b\x6b\xc1\x3c\x04\xc4\xd5\x80\x13\x01\x75\x87\xa4\x10\x04\xc5\xf0\x08\xc6\x80\x83\xf8\xfd\x39\xfe\xb7\xa7\xee\xdd\x9f\xd3\xb9\x55\x64\x3d\x29\xa5\x0a\x35\xd9\x7b\xdb\xc0\x65\x24\x65\x53\x04\x7b\x4e\x4e\xdb\xb3\x17\xa8\x0b\xf8\x18\x91\x1e\xdc\x04\xd1\xbc\x4d\x2a\xc0\xfe\xc5\xfb\x49\x25\x8d\x0d\xdc\x9c\xd2\xc7\x46\xac\x97\xc5\x86\xcc\x8c\x81\x5a\xd3\x6e\xd5\x16\xfb\x0c\xaa\x63\xc3\x82\xb0\x7d\x1d\x06\x11\x35\x8b\xd8\xe0\x76\x34\xfb\x4c\xb3\x13\x6d\xab\x36\x10\x12\x61\xf7\x29\x29\xd4\x89\xc1\x15\x32\x07\x6c\x85\x1d\xc0\x1c\x93\x3d\x91\xac\xc6\xd2\x87\x3d\x4e\x9e\x73\x94\x54\x98\xb2\xb5\xf5\x5b\x07\x89\x99\xb4\x84\x3e\xed\xaa\x3b\xe5\x17\x2b\xc2\xf1\x1a\x80\x96\xcf\x16\x15\xf5\xbe\x01\x72\x2d\x65\x03\x1d\x59\x9f\x3b\xea\x69\x01\x43\xa4\x6d\x8d\xbd\x45\xbb\x23\x52\xe7\x8e\x4c\x18\xf8\x2c\x70\x12\x64\x1f\x44\x6a\x17\x27\xbc\xb7\x6e\x06\x17\x57\x31\x36\xd0\x3e\xa9\x7d\x3b\x07\xcd\x6d\x37\x17\x3e\xf4\x1a\x1a\x0b\xd0\xb8\x1f\x4c\x9b\x69\xee\x5b\x47\x2e\x80\x49\x20\x0e\x81\x9b\xe9\xf7\xb9\xe0\xc7\xec\x4e\x34\x36\x81\xaf\x27\x72\xe1\xc9\x45\xa9\x73\x53\xb1\x30\xa2\xc0\x19\x6d\x1a\xee\xcf\x95\x4f\x7c\xb3\x5b\x21\x80\xb5\x66\x14\x11\x7b\x77\x70\x0f\xe7\x0a\x50\xa8\x48\xe0\xeb\x64\x60\x21\x48\xaf\x1d\x51\x31\x41\x91\x9a\x3b\xcd\x3b\x7d\x66\x16\x10\xbd\x60\x8e\x3a\x34\xbd\xde\xd1\x9d\xb6\xe5\xe4\x74\x95\x19\xf8\xcf\x71\xbc\x39\xe8\xe1\xdb\xe7\x98\xbb\x00\xc6\x74\xff\xd9\x63\x9d\x8a\x9f\x5e\x61\x2e\xaf\x80\x5d\x4f\xf3\x2d\xf6\xd6\xb6\xd8\x80\x91\x1c\x99\xaf\xf2\xc8\x37\x7b\xdb\x5f\x93\x02\x28\xca\xc8\x5b\x4f\x23\x14\xd1\xdb\xd0\xbc\x45\xfe\x43\xf8\x22\x16\x91\x5b\x1c\xa7\xda\x90\xa4\x31\xa0\x89\xba\x45\x7c\xbb\x94\xc1\x57\xa5\x8c\x9b\xbd\xed\xaf\x3f\xb1\x5e\x9f\x3a\x64\x7f\x7e\xea\x90\x7d\x88\x81\xb2\x4d\xa3\x2c\xe3\xda\xa6\x10\xb3\xd6\xf5\x1a\xdb\x2a\xff\x60\x87\xa1\x67\x3d\x8f\xe8\x45\x97\x31\x6f\xb1\x33\x73\x35\x6b\x68\xce\x76\x3e\x4f\x91\x43\xb4\xf2\xec\x8a\xa4\x96\xb9\x30\xf5\x86\x41\x61\xae\x89\xd5\x56\x96\xae\x52\x3a\x90\x1d\xb2\xd0\xeb\xc6\x11\xed\x80\xf5\xd6\x71\x1e\xf6\xfa\x22\x32\x21\xc3\xd9\xae\xca\x82\x27\xf0\x77\x93\xcd\xfd\xb1\xb9\x02\xcc\x89\x91\x34\x6b\x34\x07\x31\x30\x6c\x2c\x22\x74\xbb\x33\x22\x60\x84\xd9\x4e\x85\xdb\x02\x70\x64\xa3\x57\x7a\x93\x59\x77\xdb\xb6\xb4\x41\xad\x4f\x86\xee\x8a\xbe\x71\x05\xc3\xea\x9e\x90\x82\xc5\x3f\xcc\xda\x8d\x1a\x7a\xce\x57\x98\x22\x70\x9d\xb0\x66\xdb\x4a\x98\x7d\xdc\xa2\x88\xc8\x35\xf6\x89\x3e\xf4\x5a\x43\xb1\xc3\xaf\xad\x8f\x9b\x24\xa8\x68\x02\x6c\xc2\x7c\x75\x5d\xa4\xc0\x73\x6e\x5a\x43\xeb\x3b\xf9\xa1\x4b\x58\x01\x29\x85\x8c\x9d\xdd\xf3\x53\xa5\xc7\xbf\x3d\x75\xa8\xfd\xfc\xad\x0e\xb5\x41\xac\x07\x2b\x2b\xcc\xe3\x44\x52\x0a\x14\x47\x07\xe1\x95\xc3\x30\x3b\xe9\x06\xd6\xdf\xf5\xc1\x79\xe8\xfa\xf6\xeb\x4b\x03\x35\x72\x99\x37\xe6\x75\x50\xae\x04\x40\x19\xae\x4e\x3d\x21\xf6\x64\x23\x62\xcf\x56\x22\x5c\xee\xb6\x72\x41\x39\xb9\x4c\x4b\x55\x97\x28\x55\xdd\xc1\xb2\xc5\xef\x2b\xf5\x48\xaa\xbe\xbe\x0c\x90\xb6\x7d\xf5\x73\xe7\x8f\x9d\x3f\xf5\xc5\xf5\xd5\x2f\x2b\xf1\xfa\xe1\xef\xf9\xb1\xca\x78\x1e\xbf\xfe\xf8\x7b\x92\x58\x4c\xfa\xcc\xf5\x7d\xa9\xf7\x2b\xfc\xd4\x6f\x1e\x4f\x97\x27\x9a\x3e\x7d\x3b\x3f\xfc\xb9\xcb\xef\xf8\xbd\xd2\x5b\xa8\x79\x35\x24\x34\xac\x61\x75\x42\x6f\x8b\xd4\x32\xf3\xbc\xc4\xf0\xc3\x6c\xcf\xf3\x6c\x50\x6b\x31\xd7\x84\x8d\xd1\x98\xb7\x94\xa3\x44\x5e\x6e\x0c\x73\x70\x90\x53\x06\x73\x38\x24\x6f\xc9\x21\x3e\x19\x0c\x34\x0d\x0d\x9b\x89\x1e\x80\x66\x69\x15\x7b\xec\xb5\x87\x29\xa1\x76\x0a\x52\x0f\x4a\x61\x41\xc1\x3f\x8c\x1e\x6a\xfa\xe8\xfd\x83\x8c\x44\x17\x8c\x81\x03\x6a\x22\x2e\xd5\x69\x07\xeb\xc9\x56\x0a\xb6\x6f\x11\x0d\xb3\x98\x37\xe6\x68\xb7\x9e\x83\x0e\x87\xac\x6a\x0b\xb5\x21\xe9\x09\x20\x36\xc5\x8c\xbb\xf3\x8a\x00\x60\x5a\x3d\x2b\x5e\x9c\x37\x43\x09\xb0\xb6\x3f\x8a\x04\x82\x79\xbe\xf6\x14\x58\x2b\x62\x91\x7a\x40\xb7\xcc\x93\x3f\x2c\xa1\xa1\x88\x70\xb0\xff\x4a\x78\x5e\x82\xfe\x8f\x14\x7a\xb2\x20\xac\x80\xc1\xbe\xcf\xd7\x97\x01\x54\x34\xaa\xd1\x95\xc9\x26\xe2\x5a\x87\xc0\xeb\xbb\x1c\x14\x64\xf1\x67\x47\xd4\x2b\x90\xe6\x12\x98\x78\x02\x82\x90\xa5\x3d\x1c\x85\x97\x14\xfb\x96\x7b\x13\x52\x05\x5b\x96\x5d\xfc\x6c\x1e\x0a\x8b\xed\x13\x78\xca\x78\xdc\xe4\x50\x2d\xa0\x50\x4e\x7e\x0f\x32\xac\x5c\x27\x1e\xb9\x2c\xd0\x22\x9b\x4d\xa8\x79\x9c\x4a\x70\xce\x19\x08\x71\x30\x64\xc9\x2c\xdb\x48\x01\x9e\x00\x3e\x4e\xcd\xa1\xb1\x06\xe0\xe2\xb8\xe3\x84\x36\xae\x16\x40\x64\xb5\x2e\xbb\x79\x43\x23\x38\x78\xb5\x9d\x01\x39\x2a\xd0\x8b\x1a\x95\x82\x40\x82\x20\x9a\x65\x1d\x42\x9b\x27\xff\x91\x10\x51\xa1\x73\xa0\x10\xc5\x1d\xc5\xb9\xfa\x91\x77\x4b\x60\xeb\xb7\x8f\xce\xb5\x8c\x14\x33\x03\xba\x33\xdc\x02\xe1\x1a\xd5\xb2\x1a\x5b\x4f\x58\xe8\x8a\x9c\x94\x10\xfc\xc6\xdb\xce\x14\xe7\xd3\x37\x56\x24\xb5\x3e\xf8\xb0\xe0\xee\x9e\x39\x34\x1d\xa8\x85\x5d\x76\x34\xf4\xb6\x95\x4a\xa0\xb8\x30\x33\x21\xc8\x72\x81\x74\x18\x05\x42\x36\x4c\x65\x07\x33\xd9\x0e\xd0\x77\x54\x01\x41\x54\xd3\xf7\x01\xa5\x6d\x50\xe2\xed\x91\x90\x0e\xd4\xb0\xcc\xf2\x34\x64\xe3\xd0\x43\x6c\xfb\x54\x62\xab\xec\x74\xd9\xdc\x4c\x18\x50\xf3\x64\x57\x91\x63\xb0\x4c\x4b\x6a\xfa\xa2\x3b\x7a\x09\x6c\x3e\x56\x85\x14\xc5\x34\xff\x19\x98\x25\x02\x88\xf3\x61\xd3\xa9\xed\x40\xad\x40\xe1\x60\x1c\xec\x9a\x54\x0b\x62\xf6\xd1\x01\x48\x50\x76\x0c\xf4\x7e\x39\xb0\x52\x42\x6b\x9e\xec\xb0\x78\xcf\x7e\xa5\x15\xb4\x96\xb4\xb2\x0f\xce\x24\x74\x8d\xed\x08\x5c\x48\x09\x49\xca\xb5\x76\x82\x54\x1d\x20\x4a\x08\xa6\x00\x4f\xf5\xc5\xf1\x4a\xe4\x44\x0d\xec\xba\x72\xc6\x1b\x2f\x1d\xb0\x9b\x72\x67\x4c\x91\x07\x38\xf3\x62\xee\xe0\xb4\xc9\x20\x7d\xce\x8e\xda\x94\x94\x00\x00\x9f\xec\x56\x9f\xc8\x51\x7d\xa2\xa3\xf2\x6f\x4f\x1d\x95\x3f\x9f\xa2\x3f\x53\x7a\x68\x00\x12\x43\x29\x3c\xb4\x72\x8d\xb9\xe9\x2d\x4a\xd6\xab\x02\x8a\xae\x0c\x92\xbc\xca\xa6\x2c\xef\x32\x2d\x55\x30\xcb\x59\x97\x91\xe6\x2d\x55\xb1\x7b\x73\xe0\x71\xbe\x58\x9f\xed\x13\xb7\x12\x32\xbf\x16\x4f\x59\x60\x07\x9a\xb5\xc1\x8b\xd3\x0a\x49\xe5\x1d\x7b\x06\x2e\x4f\x4f\x99\x10\x41\xf7\xc4\x12\x06\x59\x2f\xef\x47\xec\xd2\x90\x44\x6a\xe7\x84\x49\x68\xd3\xeb\x09\x72\xd9\x16\x78\xd4\xab\x24\xdb\x03\xd3\xe5\x1a\xfd\xd5\xd5\xac\xe3\x2d\xbe\x7d\xf5\xe6\x85\x48\xfa\xe7\xab\x74\xfc\xae\x42\xc7\xdf\x9e\x7a\xaf\x7e\x2e\x77\xd5\x72\xc4\x13\x5a\x6e\x71\x64\x56\x2b\xd8\xd9\x16\x81\x63\xec\x5e\x62\x05\xe9\x60\x25\xb4\x81\x58\x94\x33\x6d\xcd\xb6\x06\xcf\x31\x91\x21\x33\x77\x8c\x73\xb3\xaf\x51\xf7\x43\xb2\x99\x93\x96\xa9\x58\x95\x24\x0c\x81\x8e\x8e\x60\x19\x4c\xc1\x6a\xab\x16\x12\xa0\xfd\x07\xed\x83\xcd\x25\xae\x2b\x09\x33\x57\x0e\x16\x8c\xb2\xe6\xe7\x0e\xb9\x81\x6d\x78\xa6\x50\x4a\xc8\x25\x87\x52\x76\xcc\x45\xa6\x42\xab\xf7\xb1\x79\x7b\x06\xc5\x00\xdd\x11\x44\xab\x1d\x76\x19\x9b\x35\x68\x39\x08\x28\x85\xa8\x1c\x00\xc5\xbc\x27\x6b\xf3\xfd\x1b\xfd\xd4\x62\xf3\x73\xfd\x56\xeb\xf2\x54\xd0\x25\xb0\x91\xae\x85\xac\x47\xb2\xab\x8f\x7c\x0d\x36\x0a\xbc\x67\xb7\x82\xff\x40\xa8\x50\x43\x29\x2e\x4d\x96\xbd\x7a\x69\x5b\x01\x58\xeb\xc0\x77\x30\x42\x99\x07\xa4\x61\x42\xcd\x8e\x0b\x00\x2f\x4d\x05\xd5\x3b\xd2\x88\x52\x12\x1d\x88\x89\xe8\x84\x45\x73\x3d\x28\x19\x1f\x26\xf9\xbe\x90\xb8\x20\x03\xfc\x70\x68\x4c\xed\x48\xc4\x28\x0c\x39\xea\x1f\xa8\xf1\xdf\x29\x49\x41\x96\xb1\x12\x59\xa4\xfd\x7a\xdb\x7d\x0f\xc8\x24\xdb\x0f\x6c\x76\xd4\x7a\x8b\xb5\x94\x9d\xdd\xa9\xe8\x33\x56\x0d\x69\xe5\xbb\x0f\x97\x5a\x44\x78\x80\xdd\x7a\x09\xcb\xc3\xec\x2e\x21\x29\xdd\x29\x84\x6f\xcf\x11\xa5\x37\x91\xbd\x13\x50\x8f\xfe\xf4\xda\x19\x83\xc1\x48\x8f\x03\xbb\xeb\x60\x5e\xa3\x01\xa0\x57\xca\x8e\xe8\xcd\x6c\x34\x29\x0e\x0a\xe2\x84\xdd\xe1\x6d\x4c\xf3\x78\x8a\xbb\xdb\x3c\x61\x57\x65\x3e\x44\xdd\xee\x21\xd7\xcf\x26\x5a\x19\x0a\x2a\x8c\xeb\x6c\xb7\x2a\x7a\x8d\x33\x7b\x92\x6a\x24\x12\x10\xf5\xe6\x26\xb3\xb9\x52\xe0\xa0\x15\x2d\x2d\xc4\xd6\xbd\xb3\xd6\x3c\x3e\x12\xaf\xba\x82\x6b\x07\xf8\x34\x76\xe4\xda\x71\xe3\x89\x6d\x38\x00\xb2\x9b\x80\xae\x2a\xf9\xd0\x34\x23\x77\x47\xc7\x1e\x09\xcf\xce\xf6\x29\x88\xda\x0b\x09\x0f\x6c\x56\xb5\x7c\xb4\xc4\x7a\xf4\x64\xc3\xba\xb7\x42\xd4\xb3\x87\x99\x38\x18\x72\x95\x32\x54\x4a\xaf\x2f\x6a\x66\xf8\xf7\xce\xdf\x0b\xf3\xda\xb3\xa5\x5b\x5c\xf6\xf4\x1d\x51\xc5\x92\x0b\xc8\xc8\xc0\x93\x8b\xe8\x3d\xb5\xd5\x50\x80\x90\x84\x34\xe6\x65\xb0\x31\xe5\x44\xf6\xb0\xd0\x09\x1e\x37\xe0\xa3\x50\x1d\x23\x22\xca\x8f\xa0\x96\x83\x92\xa1\x6e\xa1\xfa\xc0\x93\x49\xcb\xcc\x86\x30\xb0\x56\x77\xe7\x0e\x20\x2a\x67\x88\x45\xef\x3d\xe8\xd0\x6b\xcc\x50\x79\x78\xe2\x05\xb9\xb5\xae\xcf\x0a\x95\x45\xe5\x62\xb6\x08\x95\xc5\x50\x06\x91\xcb\xf6\xb7\x84\x92\x18\x3e\x01\xe3\x5a\x9d\xcd\xba\x29\x09\x06\xda\x08\x90\xbd\x94\xee\x76\x0d\x7e\x4f\xdb\x87\xda\xed\xb6\x7f\xd5\x06\xa1\xcb\x13\x11\xd0\x0e\xae\x3d\x01\x96\x8d\x76\xaf\xad\x5c\x70\xcc\x02\xf8\x02\x3d\xf3\x49\xfd\x52\xc8\x00\x93\xf1\x12\xd5\x80\x6b\xae\xf5\x8f\x19\xbf\xa7\x16\xa6\x9f\xbf\x29\xae\x65\x5e\xf4\x18\x7a\x8b\x13\x4d\x77\xe0\xe3\x58\x84\x59\x8b\x4a\xeb\x1a\xa5\xf4\x37\x8c\x62\x4e\xaf\x25\x92\x6f\xfc\x9e\x54\xb3\x41\x5a\xf6\x11\x90\xe5\xcc\x27\x81\x67\x6e\x6c\x1f\xc5\xad\xed\x94\x10\x3d\x66\x83\x58\x34\x15\x49\x53\x3f\x50\xb3\x77\x9d\xa6\x1a\x0a\x63\xba\x92\x8e\xbe\x2a\xb0\xec\x10\x3f\xda\x74\xc2\x46\x2f\x46\x1e\x6d\xd5\xea\xc0\xcd\xa8\x07\x08\xd1\x13\xd1\xc5\xc3\xb1\x83\x4b\xd8\x49\x5c\x25\x36\xf5\x8b\x9d\x40\xec\x99\x4c\x8e\x77\x5e\x68\x9c\x23\x1f\x42\x6e\x78\x36\x19\x95\x2f\x41\x1d\x57\x9c\x37\xd6\x42\x07\x9d\x7d\xd7\x66\x71\xb1\x84\x5c\x20\x07\x63\x87\x8d\x20\x67\xf1\x94\x34\x94\x54\x69\x1d\xa1\x42\xbb\x08\x63\x88\xf7\x49\x69\x41\x33\xd5\x1e\x15\x1e\x3c\xf0\x04\x88\x3e\x10\x3a\x00\x85\x8c\x4d\x7f\x2e\x0d\x04\xa6\x74\x9c\xcf\xc0\x71\x07\xb8\x0b\x71\xdd\x17\x7e\x98\xab\x7f\x83\x5f\xa8\x1a\x32\x79\xfb\x9a\x37\xc1\x83\xad\x84\x74\x0b\x04\x4a\xbb\x2a\x23\x8b\xa2\x38\xdf\xc8\x13\x46\x8d\x93\x9c\xe6\xf9\x94\xa8\xb1\xcb\xdb\x07\x79\x03\x32\xd2\x46\x95\xd2\xa4\x83\x91\xeb\xc0\x63\x29\x9d\x4d\x14\xd0\x6b\x61\x99\xd2\x86\xe8\x4e\x4c\xca\x17\xf6\xd7\x67\x0b\x4f\x7d\xf2\xa1\xa2\x2c\x5f\x06\x8a\xcf\x9f\x98\xf4\x4f\x3d\x41\x3f\x7f\x4b\x13\x4d\x4a\x2f\xa1\x69\x86\x9c\x51\x95\x9d\x97\x79\xbf\xca\x45\x95\x8f\x76\x2a\x2c\x55\x5a\x27\x6c\xce\x04\x14\xba\x1e\xaf\x2d\x12\x5b\xf0\x6e\x0b\x5d\x0b\x13\x3a\x2f\xc3\x85\x82\x90\xa7\x64\x6d\x96\xc5\x3e\x24\xf1\xd9\xbe\x05\x7e\x69\x42\x33\x7a\x09\x44\xce\xf5\xb6\xfa\x40\xc5\x7b\x70\x5a\xc2\xed\x40\x91\x02\xa6\xb8\xba\xf3\xff\x20\x4a\x86\x9a\x6d\xf1\x6a\xfc\xe0\x73\xe4\x34\x5c\xb3\xf0\xb2\xe5\x6e\xb3\x10\x93\x10\xd5\x25\xc9\x6c\xb7\x8d\x7d\x9f\x6c\x4e\xc9\xa9\x81\x1b\x02\xe4\x16\xd4\x0b\xb6\x89\xe6\xd7\x81\x70\xb0\xdd\x4b\xcf\x8e\xe6\xbf\xca\xd5\xf9\x51\xe9\x9a\x74\x1e\xc4\x6a\x73\x5a\xd2\x71\x85\x0c\xcd\xbb\x56\x08\xc1\x87\x2c\x39\x68\xf1\x45\xe3\x33\x70\x4d\x40\xcf\xc4\xc6\xd9\x6e\x53\x07\x02\x62\xe4\x58\x2a\x70\x92\xe8\x2f\x40\x2b\xda\x98\x21\xa7\xb2\xc7\x1c\xa8\x47\x95\xfd\xae\x0d\xdf\xfb\x30\xf9\x27\xfa\x79\x2e\xeb\x6e\x13\x83\x02\x34\x36\x21\x28\xcd\x2f\x87\xf9\xe8\xc1\x6e\xb6\x0c\x54\x1a\xe1\xbc\x66\xb0\xd9\xe3\xe5\xac\x02\xea\xa2\x6d\x85\x82\xda\x9d\xb7\xbd\x78\x8b\x3a\x7a\x55\x6e\x71\x52\x2a\x5d\x72\x98\xa7\xdb\xcb\xe6\xc6\x69\x7b\x89\xd9\x53\x94\xe0\xcf\x6a\xfb\xf4\xb6\x2c\xcf\x6c\x8c\xac\xe7\x20\xbf\xdf\x26\xe3\x7b\xb5\x85\x22\x61\x96\x0b\x28\x4d\x44\xcc\x82\x02\xc4\x8c\x8c\x54\x0e\xd0\x3f\xdd\x33\x12\x59\x75\x72\xc9\xa1\xca\x59\xf4\x58\xb3\x10\xe1\xa6\x28\x9e\x31\x26\xea\x8a\x3f\x0f\x20\x84\xda\xfa\x8a\x6d\x62\xc8\x08\xd9\x44\xc5\x1d\x6c\x41\x9c\x42\xf6\x40\xc3\xb7\xf4\x7e\x28\x3a\x79\x3a\xc9\x8a\x33\x51\xe4\xb3\x7c\x62\x7d\x3f\x75\xe2\xfc\x7c\xca\xdc\xe5\x9c\x82\x6c\x10\x32\x53\x29\x1b\x9b\xa0\x20\x24\xd7\x82\x4a\x7e\x7d\xa9\x94\x49\xae\x9b\xf6\x62\x5e\xd9\x06\x96\x99\x62\x66\x2e\x31\x88\x7a\x7d\x51\xf3\xc9\x25\x6f\x70\x5a\x55\x32\xba\xb3\x20\xa3\x6c\x9f\x68\x2a\xaf\x2f\x65\x02\x91\xbe\x65\x10\x3e\x15\xd4\xe6\xb2\x16\xef\xf5\xd3\x94\x5e\x5f\x06\x20\x9a\x63\x9b\xc8\x66\xa1\xbf\x3d\x7b\x95\x8e\x10\x34\x34\xa4\x0d\x08\x55\x02\xe8\x58\x17\xb1\x3e\xec\xed\x36\x00\x10\xde\x91\xa3\x00\x92\xfb\xf5\x45\xf2\x08\x33\x27\xa7\x7b\x4b\x69\xb3\x08\xac\xb4\x7a\xd9\x2c\x02\x0d\xd2\x21\x13\xd2\x73\xd0\xd6\x37\x64\x5a\xca\x16\x15\x75\xff\x56\x36\xa6\x7b\x5e\x5f\x8a\xf4\xd0\x55\xb7\xdc\x6d\xc7\xb2\x73\x9f\xa1\x14\xd9\xc0\x3b\x1f\xa5\x65\xe8\xf7\xa5\x90\x6b\xdf\x14\x9d\xf7\x1b\x52\x9d\x52\x74\x03\xa6\x26\xd5\x4d\x8a\xad\xc8\xba\x23\x3f\x67\x2f\x37\xa2\xd1\xe6\xeb\x8b\x14\x5b\x75\xb3\x6d\xd9\xe6\x33\xf4\x6a\xd1\xab\x30\x36\xf2\x0f\xe8\x58\xba\x82\x3a\xc1\xad\x60\xe1\xcf\x60\x8f\x3d\xb3\x37\x25\x44\x3b\x18\x76\x76\x74\xe0\xdc\xb0\x6d\x87\xb4\xc5\x39\xc2\xc8\x1b\xda\xa8\xe4\xf2\xf6\xf8\x99\x5d\x1d\x81\x20\x53\x30\x12\xc7\x01\xfe\xa9\x80\x4b\x18\xb0\x31\x3c\xe1\x3a\x83\x76\xb4\xf1\x75\xe0\x91\x36\xdb\xbd\x3a\xc8\x04\x46\x43\x55\x6c\x2a\x5a\x3d\x73\x15\x1e\x65\x21\xc9\x36\x4b\x40\x11\xcc\x16\x4c\xc2\x8a\x06\xc5\xc5\x16\x67\x0b\xa5\x41\x79\x1d\xfa\x23\x92\xb7\x62\xc7\xe4\x8a\x18\xca\x2e\x0f\x73\x25\xb2\xdd\x3e\x42\xb5\x7b\xda\xed\x8d\xa5\xad\x96\x23\x70\xa6\x6c\x48\xf0\xc5\x26\x1b\xdb\x5e\x6c\x80\xa8\xc1\x26\xd1\xc6\xf2\xd1\x26\x6a\x26\xef\x02\xdf\x48\x24\xa4\x0d\x34\x54\x6d\xb3\x65\x0d\x79\xc1\x50\x83\x8d\x0d\xb9\xc2\xbd\x85\xcc\xa3\x28\x48\x95\xeb\x5e\xec\xf7\x6d\x76\xd1\x2b\x89\xe0\x14\x77\x14\x14\x01\x2a\xc9\xb1\xe9\xe7\xfd\xed\x1b\x35\xa6\xec\xf4\xed\x3c\x31\x52\xf8\xb6\x38\x30\x17\xeb\x53\x73\xcd\xcf\xcf\xcd\x35\xf7\x62\xa6\x98\x51\xd0\x39\x98\x81\x8c\xd5\x3d\x42\xb8\x49\xec\x35\x42\x41\x71\x34\x80\x19\xeb\x38\xcc\xfc\x13\x5b\xc8\x54\xb1\xe7\x7d\x19\xe7\xea\x09\xd2\xf0\xda\xa2\x26\x8f\x7e\xfb\x12\xd1\x5f\x6a\xfa\x0c\x8b\xf1\x7e\x72\xe2\x70\xe6\x97\x89\x38\xc9\xbe\x81\x9e\x44\x5c\xb2\xd0\x92\xb6\x35\x81\xde\x1c\x96\x1d\x12\x5c\xe2\x3d\xeb\x47\xf4\x3c\x11\x26\x76\x5f\xaa\x13\xb2\x52\x45\x70\xed\x6b\x6f\x97\xbd\x11\x2d\x93\x21\xd2\x76\x14\x25\x02\x0e\x6a\x6d\x23\x0c\x90\x4d\x4a\xb2\x50\x13\x71\x3f\x59\x53\x40\x1b\xd4\xd6\xab\xd8\xdb\x72\x2c\x84\x6c\x8f\x92\x7a\x58\x6f\xe4\xe3\x7e\xd4\xf9\x4d\x1f\x2c\xfb\x06\x9b\xab\xde\x16\xb1\xe5\xb3\x1a\xd0\x6c\x50\x67\xfd\xc6\x06\x04\x0d\x87\x77\x37\x20\xec\x4d\x29\xb4\x16\x9c\x5d\x97\x9f\x5f\xed\x2b\x97\x1d\x5f\x59\x6c\xbc\x3e\x2e\x7e\xeb\x3a\xdb\x93\x0c\xd2\x77\xce\x50\x74\xfc\xb8\x6f\x7d\x62\x72\x3f\xf5\xc8\xfc\xfc\x2c\x81\xf8\x30\xb9\xef\x4f\x93\x30\x99\xfb\xe3\x79\x7c\x8a\xf7\x47\xbb\x9e\x90\x3f\xfe\xf3\xe9\x9f\x47\xdc\xbf\x75\x3e\xfa\xd7\x97\x39\x2c\xee\xd4\x1d\xb8\xa9\xb1\xa0\x8a\x70\x43\xfb\xa9\x91\xd8\xfa\x61\x11\xc7\x10\x47\xb9\xdb\x71\x07\x07\xc3\xe6\x64\x7e\xac\xf7\x30\x89\x77\xcd\xd4\x55\x7a\xbc\xc6\xfa\x40\xb0\x8c\xf7\x59\x26\x64\xb1\x5f\xd8\xb8\x53\x46\x28\x4e\x05\x74\x61\x72\x68\xb2\x93\x70\x89\x17\x2c\x58\xd9\x64\x7f\xcd\xb5\xda\x5e\x07\xd1\x7d\x92\xef\x11\x14\xa7\x02\x25\x64\xe9\x07\xd0\x39\xed\xc8\xe6\x35\xf9\x55\x3c\x42\xf0\xed\x83\x69\x07\xd9\x31\xe8\x8e\xc0\x00\xf6\x7d\x86\xee\xab\xa4\x7f\xfa\x62\xf1\xee\x8c\xc5\xbb\x37\xf6\x66\x4a\x9c\x4e\x59\x5c\x5e\x19\x8e\xbc\x4f\xa8\x4f\x8c\x72\xf9\xb3\xc3\xfc\x15\xeb\xee\x3b\xcb\xee\x5b\x27\xec\x12\xbe\x76\x6a\xfe\x0b\xeb\xf4\x1f\xce\x1e\x27\xcf\x05\x8e\x9d\x22\xdc\x2f\xea\x88\x8f\xe3\x71\x84\x0f\x5d\x63\x3b\xd5\x0f\x5c\xe3\xef\x2f\xcf\xa7\x26\x9c\x9f\x7f\x7e\x4a\xfd\xa6\x32\xee\xcb\xb3\x84\x92\x5c\x39\x0a\x31\xbe\x33\xeb\xad\x7a\x01\x02\x98\x6e\x9b\x4e\x07\x91\xcf\xb9\xe9\x00\x64\xb3\xe0\x9e\xac\xd4\x3b\xa4\x93\x85\xf2\xec\xd9\x1f\xe4\xbf\xd6\x8b\xe2\x1f\xf1\x13\xf2\x8d\xde\xc9\x2f\x7d\x94\x14\x5c\xe6\x01\xa4\x14\xde\xb5\xee\xb1\xa4\x9d\x89\x9e\x9a\xd1\x91\xb4\x85\x24\xb6\xf5\xdc\xdc\x14\xaa\x91\x5f\xab\xe8\x8e\x5e\xb8\xe9\x40\x44\xf0\x09\x36\xb6\xb4\xb5\x0e\x22\xca\x14\x2c\xf0\x63\xa9\x86\x50\x53\xf1\x2a\xdc\xfd\xb5\xd3\x91\x35\x67\x7f\x4a\x8b\xaf\xc4\x5f\x3f\x1e\xf4\xf0\xe5\xfb\x98\x1e\xcf\x14\x69\xb7\x56\x9c\x25\x0a\xc2\x77\xd0\x98\x73\xc3\x72\x8a\xce\x45\xa8\xce\xc1\x80\xb7\xe2\xf6\x9b\xe6\x9b\xd6\xdb\x8e\x5e\x56\xdb\x8c\x36\xc0\x58\xa8\x04\xf7\x76\xa3\x1e\xcf\xe2\x26\x50\x56\x85\xe8\x50\xc0\x84\xb5\x71\x01\xf8\x34\x39\x71\x6a\x5c\x9a\x5f\x5f\x9c\xc1\xe3\x16\x5d\xb3\xc8\xd5\xee\xf0\xe6\x71\x3f\xf6\x5a\xdb\x70\x90\xf4\x1a\xf6\x38\x7f\xcb\x4f\x64\xea\xf8\xab\x2e\xd4\x66\x6e\x10\x2d\xe3\x16\x17\x5d\xf6\xfb\x16\xc2\x36\xf6\xd9\x9e\xce\xe1\x72\x65\x1f\xfd\x3b\xe7\x30\xdb\x35\xf6\x36\xde\xfb\xd6\xb7\xbf\xf4\x95\xd4\xc0\xa3\x2d\xe2\x29\x3e\xdb\xa2\xae\xe3\x5d\x5b\xf4\x89\xe5\xfd\xd4\x2b\xf4\xf3\x53\xaf\xd0\xfb\xcb\x9b\xec\x9c\xe7\x2a\x89\xe7\x32\x89\xb6\x4e\x22\x9b\x46\xd7\x4a\x89\x6b\xa9\x1c\xcb\x22\x9c\x06\x61\xd9\x83\x65\x0e\x60\x0d\xdc\x18\x3c\xd8\x82\x07\x53\x70\x5a\x82\x65\x08\xdc\x0e\x2c\x33\x70\xb7\x02\x77\x23\x40\x1b\x00\x13\x70\x5a\x80\xd3\x00\xdc\xd7\xff\x5a\xfe\xaf\x6b\x41\x23\x3c\x3a\x97\x74\x7c\xb3\xa6\xe3\xe3\xa2\x7e\x58\xd3\x0f\x4b\xfa\x71\x45\x3f\x2c\xe8\x78\x5f\xd1\xf1\xcd\x92\x1e\xe9\x61\xf2\x7e\xe5\x65\xbd\x9d\xed\xa7\x96\x64\xf9\x5a\xf9\xf2\x71\x9e\x3f\x28\x5f\xda\xf8\x3d\xeb\xc3\x82\x7c\x58\xa6\xc7\xc3\xf2\x7d\x67\x59\x3f\xac\x6a\x2c\xea\x65\x16\xee\x56\xe1\x6e\x14\xde\x2e\xe8\x78\x5f\xd1\xf1\x71\x49\x4f\xfd\xcb\x2e\x74\x6a\x0a\x59\xd7\x62\xf9\x70\x5b\xed\xe8\xf4\x7f\xbb\xab\x5e\xde\x6e\xab\x6e\x11\x3e\xd8\x56\x1f\x4d\xc2\xfd\xa4\x5a\x79\xc7\x73\x9e\xed\xfa\x68\x0a\xbe\x7f\xb4\xd9\x80\x8f\x92\x59\x9f\xb6\x59\xbc\xc4\x4f\x59\x92\xcb\x8f\x30\x25\x4f\xdd\x54\x3f\x3f\xab\x4f\x3e\xa4\x8c\xab\x02\x04\xc7\x6a\x2b\x48\x7e\xb0\x5a\xd9\xe8\x21\xe8\x40\xa1\x1b\x0c\x3f\x1a\x39\xde\xea\xce\x34\xb3\x86\x0b\xb4\x7a\xff\x87\xbf\xae\x74\xa1\xeb\xc2\x4f\x13\xb7\x32\xca\x83\x27\x3e\x68\x59\xec\xc7\xc0\x73\x4f\x59\x6c\x68\x8c\x93\x95\xa5\x36\x9e\x10\x5e\x0d\x92\xe3\x48\xc0\x87\xaf\x6c\x0e\x23\x41\xc7\x03\xc9\xfe\x1b\x8e\x7d\x07\x77\x3c\x12\xee\x5f\x8e\xb7\x6c\xfc\x6f\xfe\xf1\x78\xe0\xf1\x01\xa5\xe8\x87\xea\xd5\x2e\x2e\xc9\x55\x46\x05\x6b\x2e\x3e\x52\x14\xe7\x32\x49\xbe\x29\x83\xdd\xc2\xff\x99\x62\xd6\x9c\x2b\x4f\x2d\x43\x3f\x3f\xb5\x0c\x3d\xa2\x71\x67\x63\xc7\x10\x2f\xe0\xbb\x27\xc0\xdb\x23\x4c\xc0\xe0\x06\x7d\x7d\x7b\xda\xd7\x37\x67\xbd\xe4\x7d\x81\x35\x5b\xfc\xce\x30\x72\xe7\xdd\xe9\x2c\x8d\x7d\x7c\x7f\x80\x08\xb4\x18\xb3\xee\x52\x66\xd0\x54\x83\xfd\x2d\xe4\x0e\x40\x61\xfa\x3b\x2a\xe5\xc7\x92\x4b\xbf\x7c\x53\x2f\x1d\x35\xe6\x9a\x30\x7a\xb4\xe1\x5b\x0b\x59\x3b\x6a\x0e\x59\xfb\x2e\x28\x82\x29\x2b\x03\xf6\xe2\xc8\x60\x1d\x19\xbb\xa2\xb2\x8d\xda\x44\xd6\xbe\xe6\x33\x60\xa8\xbf\x63\x3e\xff\xe9\xe9\xfc\xdd\x69\xf2\xf7\xa7\xae\x9b\x5f\xee\x5d\x37\x9a\x24\xf4\xaa\x3b\x0c\x54\x01\xb4\x13\x95\xb2\x31\x59\x88\x7c\xb0\x15\x68\x38\xea\x7a\xa0\x73\xd0\xbb\x2f\xc1\x6b\x11\x89\xce\x6a\xc4\x0b\x16\x71\x21\xdb\x6b\x1c\x15\x1e\x1a\xd9\x55\xcb\x6a\x33\xc2\xe1\x38\x1a\x3b\x8b\x80\x68\x35\x2f\x50\x5f\x57\xfe\x28\x7f\x73\xcc\xd0\xf3\x81\xb3\x82\x86\x2d\x90\x80\x01\xdd\x3a\x8c\xf7\x52\x09\x54\x1e\x44\x48\x4f\x99\x5c\x21\x9f\x46\x63\x15\x97\x6c\x1d\xc3\x3b\x81\x2f\xfe\x9a\xfd\xc4\x0b\x09\x9f\x1e\xb4\x97\xf9\x6d\xef\x00\x70\xea\x0f\x32\xeb\xf4\x09\xcc\x99\xeb\x32\xbb\x30\xbf\xb3\x0e\xfc\xb8\x07\x7a\x7c\x38\x71\xd0\xb9\x50\xc9\x06\x3f\x80\x5e\x01\x38\x80\x4c\xe5\x6c\x92\xe5\x4d\x05\xb9\x3d\x80\xd2\xb9\x77\xdb\xaf\x49\xdd\x5a\xcd\x1f\xc1\x4a\xd0\x1e\x62\x06\xdc\x50\xfb\x81\x57\x02\xea\x4b\x5c\x65\xf0\x2f\x44\x30\x83\x39\xb1\x56\x77\x32\x27\x0d\xde\x30\x00\x96\x36\x9e\x00\x16\xfe\x75\xd4\x4f\x54\x4c\xfe\xfe\xd4\x51\xf2\xcb\x73\x47\xc9\x23\xc3\x91\x96\xa0\x8e\x00\x38\x3d\xe5\xee\x7e\x72\x7e\xf2\x92\xb3\xfb\xc8\x1d\x1e\xf2\x58\xfe\x71\x39\x9a\xb0\x25\x07\x5d\xe2\xf0\x90\x07\x41\xae\x32\x88\x9b\xb1\xbf\xbd\x12\xe5\x3d\x5d\xa3\xdc\x09\x20\xd9\xcb\x73\x16\xd7\xb0\xb2\xc7\xeb\xcb\xe8\x29\x74\x2a\xb9\x4f\x17\x9a\x79\x70\x6d\xf5\xd1\xb5\xd5\xbb\x6b\xdb\xef\xae\x6d\x7f\x70\x6d\xd7\x11\x97\xe3\xf1\xab\x0f\x63\xda\xb3\xaf\xca\x54\x47\x06\x2a\x08\xa8\x3c\x08\x8c\x7d\xec\x5d\x81\x40\xe4\xa3\x72\x9e\x99\x2b\xfb\xfe\x3d\xf5\xf1\xbe\x07\x84\x06\xd9\xdf\x95\xd6\x41\x02\x77\xb6\x77\xc2\x47\xa8\x9e\xbf\x09\x1f\x6f\x74\xd4\xde\xcf\xbe\x7e\x62\x42\x3d\x75\xa4\xfc\xf2\xd4\x91\xf2\x10\x7a\xd9\x1e\x98\x91\xc4\x32\xbb\x45\x6a\x9d\x44\xb3\x05\x28\x3a\x74\x96\xdb\x70\x7c\xfb\xea\xa0\x26\xd0\xb0\x51\x1b\xc8\x5e\x80\xd3\x12\x99\x90\x01\xa6\x21\xaa\xae\xf3\x7b\xac\x5d\xdb\x50\x4e\xe2\x93\x4e\xe6\x75\xc7\xc3\xdf\xe1\x06\x79\x7c\xa9\xd7\xa2\x6d\x87\xaa\x0a\xde\x03\x57\x2f\x81\xf1\x79\x69\xc0\x77\x60\xd9\x5d\x82\xea\x54\xa0\xaa\x8f\x4a\x54\x4b\x9b\x6a\xfd\x5d\x1f\x2c\x95\x2f\x7e\xd1\x7d\x1f\x1d\x1f\xe4\x02\x7a\xfa\x20\xa4\x7e\x37\x17\x60\x47\x3f\x25\x3d\x4a\x1a\xa1\x96\xf2\xfe\xf8\x59\xd3\xef\x18\x3f\x53\x50\xe0\x39\xa9\xf2\xe1\xf8\x36\xbd\xde\x19\xff\xf2\xc1\x0f\x3c\xcf\xc6\x55\xe5\x4e\xe9\x2f\xbb\x41\x3a\x6c\x6f\xd3\xab\xfd\xd0\xfb\x79\x0d\x8f\xaa\xde\xcd\x6c\xfc\xce\xc8\xe5\xf2\x1f\x97\x04\xf9\xfb\x13\x8e\xfc\x97\x67\x65\x9e\xf7\x56\x22\x34\x09\x1e\x96\x46\x7c\x58\x1b\xd1\x16\x87\x6b\x0e\xdd\x97\x47\x3c\xd7\x07\x17\xf2\x7d\x1d\xaf\x65\xbc\x56\x31\x17\xb1\xaf\xe1\xb5\x84\x7d\x05\x63\x01\xfb\xfa\x3d\x97\xef\xb9\x7a\xef\x8b\xf7\x71\x0d\xfe\x08\x1d\xb8\x0b\xe7\x18\x8c\xe4\x47\xd1\xfb\xdb\x79\xf6\x71\xf4\xfe\x38\xc3\x1e\xa2\x77\x5b\x84\x2d\x8d\x8f\xc7\x7f\xbb\x10\x3f\x1e\xff\x71\x09\x7e\x95\x06\xf9\xe6\xf8\x6f\x17\xe2\x7d\xfc\xcb\xd7\x3f\xf0\xb8\x04\xbf\xfa\x81\xd1\xca\x5f\x76\x83\x56\x7a\x43\x34\xd9\x42\x99\x7a\x33\xaf\x2b\x7d\x2b\xff\x6f\x2b\xe3\x4f\x66\x13\x2e\xbf\x2b\x9d\xf0\x23\xd6\xe4\x13\xb6\xff\x97\x6f\xea\xaa\x68\xad\xa1\x43\x0b\x25\x53\x24\xa4\x86\xd2\xbd\xee\x8c\xb0\x8b\x44\xde\xce\x96\xd5\xd8\x54\xc5\xfe\xba\xe2\xac\xe2\x60\x09\xc4\xbf\x91\x31\xe4\x41\x95\x4c\x81\x74\xf7\x85\xd9\x0a\x62\x4d\x03\x88\xba\x4b\x68\x50\xe9\x03\xe7\xee\x17\x72\xb5\xdb\x02\x23\xff\x1e\x80\x4c\xe4\x5e\x00\x80\xa3\x6d\xb1\xcc\x30\xfb\x6e\xe7\x67\xd1\x63\x6f\x61\xca\x2e\xe0\xb7\x64\xf3\x41\xac\x65\x39\xa7\x52\xd1\xe2\x6e\xf1\x5d\xeb\xa1\x80\x86\xae\x15\xf0\xac\x5f\x45\xfa\x65\xcf\x54\xb5\x50\x94\x22\x5d\x04\x70\x3a\xfb\x90\x7b\x07\xac\x91\x8e\xd3\xb1\x03\x2f\x8b\x45\xb2\xc9\x29\x0d\x09\xf2\x65\x01\xd2\xce\x7b\xa2\x38\xd3\x5a\x98\x6d\x67\xb5\x04\x08\xf3\xea\x14\xf3\x95\xfd\x2b\xa4\x50\x18\x47\xd4\x9a\x4f\x55\xba\x3e\xa8\x55\xe3\xfc\xe4\x64\x6d\x92\xee\x44\x2b\x19\x05\x49\x76\x41\x2a\x00\x77\x60\xb1\xb5\x88\xf3\x80\x96\x52\xa8\x63\x17\x30\x97\x39\xcf\x65\x6e\x07\xe8\xaf\x25\xb5\x43\x88\x2b\x07\x8b\x9c\x38\x84\x5e\x26\xe9\xcb\x9a\x78\xa8\xc3\x06\x22\x0f\xf9\x09\xc0\x24\x2a\x1a\x3c\x20\x08\x11\x52\x98\x1e\x38\x91\x97\x90\xd0\x4f\x9b\x1d\xc0\x0f\xcc\xe2\x22\x63\x23\x7c\xae\x07\xe5\xef\x4f\xad\x11\xbf\x7c\xab\x35\xa2\x10\xb8\x2d\x4e\x8d\x83\xcc\xd4\x52\x6b\x23\x15\xfe\x1e\xfd\xd9\x84\x8c\xc6\x12\x62\xe6\x34\xa0\xaf\x41\xd5\x62\x00\x30\x0b\xd7\xd0\x48\xad\x50\x24\xa8\xe4\xd0\xa4\xec\x79\x86\x2a\x61\x56\x8a\x2c\x1e\x93\xb0\xdf\x1d\x14\x02\xd9\x1b\x0b\x0e\x69\x0f\xec\x3c\x9d\xa4\x55\x33\xed\x94\x43\x4f\xea\x11\xa3\x8c\xb2\x92\x67\x73\x3a\x13\x4d\x71\xad\xa1\x21\xe0\x2e\x8d\x65\xca\x8e\xfe\xbb\x1a\x84\xe4\xb6\xd9\x39\x75\x99\x6a\x6b\xab\xd7\x41\x2e\x68\x81\x26\x03\x12\xa9\x65\xb2\xab\x5b\x44\x85\x96\x9f\x6d\xa9\xf9\xde\x6c\xfd\xc5\x41\xdb\x0b\x61\x22\xcc\xd9\x26\xa8\x8e\x3f\xa1\xd3\x49\x5d\x25\x04\x9f\xdb\xb8\x48\xbd\xc3\xf4\xd9\x37\xde\x01\x7d\xbf\x48\x1d\x12\x5a\xa1\x89\xce\x85\xb5\x7a\xca\xa2\x54\xf6\xe3\x34\x76\x2c\xd2\xa1\xa6\x8a\x50\x62\x2b\x10\x59\x81\xd1\x8c\x91\xf6\xc8\x8e\x4e\xb4\x87\x98\x21\x05\xef\xb4\xcc\x90\x13\xca\x12\xed\x62\x7f\xa0\x04\x20\x33\x0c\xc6\xe4\x00\xfa\xd9\x3d\x4b\xe0\x6f\x45\x19\xa3\x85\xa2\xae\x9e\x95\x43\xe4\x74\x06\xa9\xdf\x42\x63\x9f\xf3\x34\x39\x03\x12\x41\xd5\x10\x0b\xc5\x2d\xca\xcb\x38\xa3\x09\xc3\x13\xf4\x76\x4b\xca\xc1\x3f\x7b\xf2\x2e\x25\xb6\x2f\xb2\x67\xa9\xa8\x37\x03\x54\xf1\x72\x2c\x15\xcb\xbc\xcd\x65\xe9\xde\x1c\x94\x57\x24\x25\x31\x85\x12\x1b\x66\x52\xa5\xed\xec\x6c\x75\x68\x83\x2c\x14\xb5\x5c\xdc\x28\xc6\xd2\x8e\x07\xc9\x52\x1e\xe4\x7a\x07\x80\xf2\xb4\x84\xf6\x8c\x92\xc1\x97\xd8\x32\x3a\x38\x6a\xe0\xba\xdf\x05\x3f\xb7\x6e\x48\x73\xaa\xaa\xb6\x47\x5c\x69\xce\x41\x84\xd3\xb4\xb8\xa6\x90\xb0\xdd\xa1\xb7\xa0\x8e\xa1\xa8\x04\x20\x79\x5a\xa6\x81\x0d\xf5\x40\x62\x90\x5c\xa6\x9e\x2d\xce\xcb\x85\x42\x5b\x15\x55\x2d\x6c\x32\x80\x5c\x61\x52\x96\x90\xe1\x93\xcc\x40\x8a\x4f\xe8\x0a\x29\x74\x9e\x34\xed\xb0\x8c\xe4\xde\x9e\x17\xe0\x31\xa1\xc5\xe6\x84\x3b\xae\x01\x28\x54\x80\xa2\xd4\x08\x84\xe2\x26\x6e\x23\x5b\x75\x25\x2c\x26\x76\x2e\x8d\x7a\xb8\x14\x02\x76\xff\x7e\x88\x8b\xc7\x1d\x6b\x81\x9d\x2d\x43\xf5\x14\x04\xe8\x8b\xf5\xb9\xfb\xf3\x56\xb3\xbf\xa0\x11\xa8\x0a\xce\xf3\xb4\x43\xcf\x62\x66\x62\x23\xd9\x06\x79\x52\xe9\xb5\xc3\x95\x90\x86\x79\xec\x39\x95\xd0\xc4\x6d\xc5\x62\xe4\xaa\x29\x93\xce\x06\x4c\xfd\x23\xc4\xae\x10\xa2\x8c\xa3\x9d\x5d\xd5\xbd\x13\x97\x9d\xd7\xa2\x21\xa1\x99\xa7\xee\x9d\xed\x88\xad\xac\x93\xf0\x6b\x50\xbb\xf6\x4e\x45\x0f\xda\xad\x91\x83\xa2\x72\x97\x43\x45\x2f\x27\x52\x9a\x4a\xcd\x83\xd5\x4b\xac\x36\x05\xea\x08\x9e\xe9\xcf\x41\xcd\x4f\x81\x8e\x0a\x1a\xb0\x99\xc8\x40\xc6\xc2\x7f\x9b\x08\x01\x21\x42\x8d\xec\xf1\x30\x35\x01\xac\xcb\x02\xbe\x60\x2c\xba\xcc\x2f\xed\x1d\x8f\x76\xb2\xb3\x69\x87\xa1\xb4\x6b\x01\xc1\x4a\x67\x97\x51\x96\x72\x31\xe3\x57\x34\xd8\x53\xfd\x4c\x42\xe9\xa9\xaf\xe4\x97\x6f\xf6\x95\xc8\x98\xe0\x67\x07\xd3\xf5\xcc\xfb\x0c\xa5\x78\x0d\xaf\xe5\x83\x8a\x4a\x7d\x8b\x83\x3a\x0b\x79\xa7\x29\x95\x05\x41\x52\x17\x6c\x60\xdf\xcc\x02\x08\x6d\x6a\xbb\x50\x9b\x5b\xb5\x0d\x47\xf3\xae\x20\xba\xca\x1a\xda\xde\x17\x70\x51\xea\x16\x8b\x20\x97\x56\x6f\xe9\x96\x36\xf6\xf6\xea\xe0\x94\x2b\x64\xbb\x42\xaf\xab\xf3\x1d\x49\x63\xe8\x92\x9b\x85\x29\x79\x7c\x58\xb9\x18\x2c\x3e\xbc\x4d\xcb\x1f\xd1\x33\xfc\x97\xe3\x9f\xa0\x56\xf1\xf7\xa7\x56\x88\x5f\x9e\x5b\x21\x92\xae\x1d\xbe\x41\x84\xf1\xd3\xea\xea\x3b\x3b\xa1\xcd\xec\xa4\x63\xe6\xd0\xe5\x36\x53\xbf\x8a\x8e\x5b\x9c\xa9\xef\x95\xfa\x3e\x58\xac\x72\x38\xeb\x81\xe7\x71\xf1\x2b\x9d\xb2\xa9\x52\xca\x11\x67\x09\x22\x7a\xfb\x7c\xd2\xe5\x16\x3b\xfa\x57\x9d\xb9\x0a\xac\xdb\xa2\x87\x53\xc2\xfb\xee\x98\xdd\x65\x52\xcc\x1c\x75\x37\x33\x9f\xaf\x89\x4e\x23\x02\xcd\xde\x78\xa3\xd0\xff\x20\xf3\x1c\xdf\xe8\x3c\xc7\x37\x42\xcf\x6f\x74\x9e\x97\xe4\x9f\x38\x81\x57\x96\x7c\xeb\xa4\x71\x5e\x27\xf3\x78\x2e\x0f\xa7\xc2\xd3\x7a\x38\xdd\x5b\xb4\x2f\x52\x6f\xdc\x96\x2c\x59\x2a\xf3\x2b\xf3\xb3\xbd\x0d\x02\xcc\x2c\xea\xbb\xd9\x0b\x42\xb3\x12\xb4\xc7\x90\xa5\xfc\xe0\x43\x1d\xe9\xfe\xe1\xe5\xfc\xf4\xfb\x93\xe9\x09\x77\xff\xcb\xb3\x02\xc6\x8f\x9c\x4c\xad\x0a\x27\x53\xab\xf2\xdf\x93\xe9\xbf\xd8\x64\x7a\xc2\x85\xff\xf2\x8c\x0b\xff\x91\x93\x29\xcf\xca\xc9\x94\x67\xfd\xef\xc9\xf4\x5f\x6c\x32\x3d\xe1\xb0\x7f\x79\xc6\x61\xff\xc8\xc9\x24\x79\x72\x32\x49\x9e\xff\x3d\x99\xfe\x8b\x4d\xa6\x27\xd4\xf0\x2f\x4f\xa8\xe1\x3f\x35\x99\x3a\x5a\xfc\x05\x5e\x3a\x3f\xf4\x17\x60\x01\xf0\x84\x75\x5d\x19\xf0\x7f\xa6\x29\xf4\x38\x83\x2e\xff\xbb\x4d\xa1\xdf\x31\x83\x9e\x80\xa9\xbf\x3c\x93\xd8\x4f\x3d\xcb\xed\xe8\x14\xd3\xd1\x17\xad\x05\xe2\xf0\xcc\x36\x2c\xcd\x5b\x6c\xda\x2c\xea\x6e\xfb\x29\xeb\x84\x46\xbd\x84\xb4\xbc\xa4\x2d\x0e\x0d\xc3\xc9\x47\x78\x80\xe6\x03\xff\xdd\x4a\x09\xa5\xec\xb1\x6b\x98\x42\xba\x85\xa0\xa9\x33\xcb\x04\x4a\xd6\x5e\x10\xe7\x4b\x6f\x01\x28\xab\xc4\x1c\xf9\x70\x6d\x59\xd7\x96\xc6\x5d\x48\xd7\xa8\xb5\xdd\xa0\xb0\xfd\x07\x30\x20\x3b\xc7\x46\xd7\x67\x91\xcb\x81\x66\x5a\x91\xba\xcf\x02\x26\xd4\xd9\xd9\x6c\x85\xb9\xd4\x2d\xbe\xe3\xc9\xf3\xaa\x28\x7b\xc0\xeb\x7e\x7d\x91\x5c\xf8\xec\xde\x49\x90\x1d\x5f\x11\x57\x1c\x6f\xf2\x6d\xc7\x03\x09\xc4\xeb\x8b\xb4\x44\x30\xdc\x3b\x99\xb9\xc7\x23\x8f\x6f\xfe\xc2\xeb\x8b\x8c\xda\x3e\x7b\x3e\x97\x6f\x9e\x90\x4a\xc3\x09\xfd\xc9\xeb\x2a\x69\x38\x28\xea\x2d\xef\xc5\xb7\x2f\xe4\xed\x90\x16\xf8\xea\xf8\x11\x67\x93\x06\x2a\x79\x97\x3f\x3b\x8e\x3d\xf5\x86\x5c\xf2\x9f\x7b\x5a\xf6\xd4\xcd\x24\xfe\xc9\xd3\xb1\x67\x05\x28\xcc\xa7\x4e\xe7\xf2\xf1\xf9\x94\xce\xfc\xc2\x0f\xb8\xcd\x76\x3e\x3f\xe0\x2e\xff\x80\x61\xec\xee\xe4\x51\xfe\xf4\x43\xb7\xab\xd2\xfa\x27\xe7\xe0\xf7\x6d\xf6\x13\x02\xf8\x97\x6f\x22\x80\x5b\x2b\x60\xf6\x3d\x3b\xb8\x1a\x9b\x9c\x91\xa0\xb1\x77\x3f\xa8\xa0\xb6\xf7\x0a\xa8\x22\x24\xe2\x42\x72\x9c\x83\xe8\xd5\x37\xed\x4a\xed\x84\x11\x14\xd5\x52\x26\xa1\xfa\x6a\x17\x1b\xf7\x76\x31\xb2\x48\x60\xfc\x3b\x32\x9c\x2c\x12\x4b\x78\xfc\x26\xa3\x91\x60\x1d\x4a\x5c\x18\x75\xb4\x9b\x4c\xbd\x4a\xcd\xed\xf5\xa5\xa7\x12\xc6\xfb\xc5\x5f\x6f\x1a\xe1\x19\x1f\x67\xa9\xf7\x78\x53\xe1\x35\x87\x65\xf5\xd7\xbd\xfb\xfd\xef\x7c\x3d\x95\x30\xdf\xef\xd4\xfc\xcc\xd7\x47\xd6\x3f\xf3\x75\x78\x5b\xa9\xb6\x3f\x7e\xf5\x09\x9e\x59\xfa\xa3\x27\xf0\x89\x02\xff\x5b\x8c\xca\xc7\x05\xf8\xd9\x6e\xce\xd4\x9d\x40\x24\x2e\x43\x0e\xdb\xd4\xbb\x6d\xc3\x00\x31\x0e\x52\xbb\x17\x6c\x0f\x73\x04\x51\x8b\x6d\x62\x9e\x9b\x6a\x50\x50\x71\x80\xb7\x2b\xa4\x0d\x45\x1e\xbd\xec\x2e\x36\x93\xc8\xe0\x9f\xa1\xb9\x08\xad\x0d\x17\xa1\xc1\xc1\xe8\x6c\xa3\xe4\x06\xc9\x4d\xd5\x07\x8c\xb9\x81\xd6\x9b\x4e\x43\x2a\xd4\x54\x82\xc8\x55\xee\x28\xf1\x0d\x08\xb8\x44\x90\x84\x46\x42\x9e\xf3\xbd\x21\x0e\xef\x80\xa0\xea\x2a\xf5\x5d\x7c\x01\x1c\xd2\x6f\x3e\xc0\xef\xcf\x9f\x8f\x9e\xdf\xe5\xd3\x33\x68\xb5\x5f\xff\x81\x13\x98\xa8\xf0\xfc\xf1\x09\x84\x1b\xf0\x27\x7e\x1f\x37\x40\xcb\xdb\xf5\x7b\xf9\x3d\x33\x18\x6e\xf3\x9f\xbd\x03\x5f\x9f\xc1\xef\x3a\x81\x31\xfe\xcc\x00\xdf\xdf\x27\x9e\xd0\xff\xbf\xfc\x76\xf2\x76\x9a\x27\xcb\x78\x0a\x29\x7b\x14\x16\xfb\x0e\x3d\x0e\xf0\xc7\x10\x72\x95\xa9\x06\x33\x51\x7b\x55\x82\x16\xed\xc5\x4c\x20\xa4\x01\xdf\xba\x85\x47\x79\xa7\x3a\x0e\x0d\xbe\x00\xf4\x2a\xcd\x36\x82\x62\x7f\x0f\xaf\x56\x2c\xcd\x2f\x87\x4a\x69\x59\x65\xe1\x92\xcb\x11\x73\xa5\x1a\x28\xe8\x9b\x40\x9b\x13\xf2\x11\x5b\x90\xba\x43\xfc\x5f\x52\x80\x1a\x75\xd6\xd0\x42\xe9\xbb\x84\x09\xe2\xd7\x5d\xea\x0c\xc0\x71\xa1\x89\x3a\x17\x82\x78\x33\x4a\x73\x32\x88\xfc\xcd\x39\x91\x78\xbb\x74\x3b\x84\x88\x15\x08\x57\x52\x53\x10\x75\xe9\xee\x12\xf8\x8e\x5d\xa0\x30\x14\x37\xb9\xa4\xab\x48\xae\x8c\x10\x50\xbb\x0f\x73\x02\x27\x0d\x94\x05\x86\x90\x2f\xe8\x0d\xcf\xa8\x5d\x2a\xa0\x23\x12\xcc\x94\xe0\x2b\x90\x97\x23\xc1\x10\x0b\xce\x7c\x33\xba\x02\xce\x11\x9d\xb0\x87\xfa\xac\xc8\xd6\x34\x09\xa4\xbb\x77\x7e\x63\x05\x43\x9e\x2e\xa4\xc7\xde\x83\x94\x1c\x5a\x0b\xea\x80\x6b\x6a\xe4\xf7\x43\x15\x74\x8b\x24\x39\x85\x62\xf8\x65\x17\x48\xe5\x06\xe7\x05\x2a\x94\x6e\x95\xb3\x25\xb6\xa3\x80\x95\x96\xd8\x7a\xcc\x69\x58\x6c\x6f\x93\x65\x24\xca\xe7\xe7\xa5\x83\xb5\xd0\x28\x64\x53\x6a\xf5\xfe\x0f\xbe\xc6\x51\x3c\xe8\xe1\xe5\xc3\x11\x8f\xdf\x7c\x18\x12\x00\x48\x5d\x53\x44\x20\x46\xe4\xe1\xf3\x1b\x06\xab\x0e\x66\xa9\x71\xe7\xc0\x45\x10\x6a\x36\xbe\x05\x10\xdb\xcc\x30\x15\x9a\x51\x29\xe4\xa0\xe9\xb2\xd7\x11\x6a\xb1\xe0\x52\xb4\xa3\xed\x9e\xad\x22\xa0\xa0\x04\x5a\x26\x01\xbc\x4b\x44\x11\xa1\xf5\xa2\x54\x91\x42\xd2\x81\xf2\x2f\x2c\xf7\x21\xe4\x9d\x2e\x5b\x03\x15\x7e\x0d\x14\xde\x93\xde\x0e\x36\x10\x08\x23\xc2\x88\x13\x88\xca\x25\x43\xe5\xd1\x69\x77\x12\xc2\xec\xd3\xc5\x8f\x33\x68\x7f\x15\x0c\xde\xa8\x00\x17\x2a\xc9\xae\x92\xa3\xe6\xb2\x67\x14\x66\xdb\x0c\x5a\xca\x01\xf1\x0e\x90\x12\x6a\x11\xb0\x1b\xed\x52\x4a\xe8\x41\xdb\x00\x4f\x8a\x4c\xe7\x59\xe8\xd0\xf4\xf3\xa2\xe4\xa7\xa4\x86\xfe\xf1\xd4\x10\xf2\x6b\xfa\x86\x87\xa9\x16\x51\xea\xb8\x22\x09\xd1\xdb\xb8\x46\xa6\x23\x7a\x5b\x15\xc9\x4f\xa1\x51\x3f\xa6\x85\xfa\x10\xf8\x66\x5f\xf9\x63\xc0\xb7\x7f\x3c\xf5\x19\xfc\xfa\xdc\x67\xf0\x15\xdd\xa0\x22\x01\x33\xbf\x81\x84\xff\xd6\x35\xcc\xf7\x09\x0e\xfe\xc4\x25\x3c\x21\xdb\x7f\xfd\x16\xb2\xdd\x9e\x52\x42\x83\x24\x18\x45\x91\x6a\xaa\xa2\x8e\xf3\xb7\xf7\x2a\x53\x75\xfe\x99\xd6\x76\x9d\x1f\x91\x2f\xe4\xaa\x0b\xd4\x88\x06\x01\x57\xd2\x7a\xff\xae\xc0\x4f\xcc\xf5\x0f\x75\x10\x70\xe0\xa7\xdb\x66\x43\x72\xc4\xa7\x8f\xec\x1b\x8f\x27\x7d\xf9\x1d\x77\xf4\x09\xa1\xfc\xeb\x13\x42\xf9\x0d\x56\xa0\x23\x35\xb5\x89\xb9\xa6\xa5\x79\xfe\x87\x49\x2d\xe6\xb6\xb6\xa8\x39\x83\x97\xca\xff\xbe\x7b\xcc\xfa\xfe\x3d\xa3\x16\x3c\x65\x06\x96\x25\x05\x7d\x6b\xbe\x0f\xf6\xd1\x81\x80\x4a\xac\x81\x1e\x32\x70\x87\xa7\xe7\xde\x0e\x14\xd7\x48\xef\x1c\x79\x8e\x74\x66\xe9\x90\xc5\xc3\xef\x5d\xb6\xc7\x6b\x8a\x7e\x51\x5f\x1f\xf5\xcf\xbb\xf2\x9f\x20\xaf\xbf\x7e\x07\xf2\xda\x43\xd1\xfa\xde\xdd\xfd\x2a\xb7\x69\x81\xb5\xb4\xb9\x79\x84\xdd\xe6\xc7\x47\x7e\xf5\xc0\x1f\xf3\xa0\x6f\x46\x59\x83\x3c\x1d\xf4\x66\xc6\x3d\x66\x1c\xb7\xf5\xe3\x6b\xa0\x77\x8f\xf9\xea\xf1\xbe\x4d\xe3\x5e\xee\x57\x70\x8e\xf6\xfe\x91\xaf\x6f\x6d\xbf\xf9\xd4\xcb\xf8\xdb\xeb\x7f\xde\x39\xf0\x04\x27\xfd\xf5\x09\x4e\xfa\x38\x07\x12\x38\xe6\xc6\x96\x13\x04\x38\xae\xb1\xd5\xb2\x45\x74\x76\xda\x3f\x5b\x2d\x7f\x10\x7a\xf3\xcf\x80\xbc\xf9\xc7\x13\x42\xea\xd7\xf7\x10\x52\x77\xde\xb3\x09\x19\x87\xb4\x13\xe4\x05\x90\x25\x93\x3b\xcd\xd3\x3c\xc0\x76\xee\x94\xd1\x0b\x70\xf2\x41\x18\x51\x9c\x5f\x56\x06\x55\x73\x66\x0d\xc3\x1c\xb6\x11\x40\xaa\x47\x56\xb2\x83\x62\x9d\xc3\xde\xc6\x07\x32\x8f\x11\x64\xec\x3d\x8c\xc0\x8f\x1c\xef\x6a\x6f\xc5\x1e\x3a\x09\x6d\xba\x27\x28\x53\x4b\xa1\x97\xb4\x41\xda\x39\x53\x4a\x1a\xa4\x45\xde\xa0\x97\x9d\x68\x5b\x32\xe8\x62\xf3\xc0\x11\x6c\xdd\x0d\x39\x1d\xf8\xef\x96\xc1\xf9\x69\x1f\x68\x60\x8f\xa0\x5e\x16\x62\x4f\xb7\x6c\x01\xca\xdc\x31\x32\x0e\x89\xea\xec\xcf\x7c\xf5\xfa\x32\xab\x84\xd1\x81\x5b\xc5\xb5\x8d\x75\x6d\x93\xd7\x66\x17\x03\xc1\xec\xc3\xfe\xb3\xdb\xa5\xca\x0c\x94\x76\x18\xc7\x60\x8a\x70\xf8\x25\x65\x73\x5b\xdb\xd8\x51\x05\x43\xab\x59\x22\x95\xb9\xd3\x7a\x76\x47\xdd\x41\x94\x0e\x42\xbc\xe2\xdd\x84\x2a\x6c\xaa\xcf\xe6\x0c\xb3\xa5\xac\x66\xa2\x32\x63\x25\x89\xb0\x40\x1f\xde\x6f\xc0\x1d\xf3\x88\x58\x22\xf3\xc5\xc5\xe9\x73\x85\x8a\x03\xfe\xc2\xe5\xb9\x8e\xe2\x5c\xbe\x88\x1c\x0f\x2a\x87\x2e\x82\x07\x5b\x16\xb5\xd6\x50\x46\xdb\xcd\x09\x07\x89\x24\x59\x73\xa3\x3e\x50\x07\x81\x03\xcb\x8c\xa3\x79\xc9\x25\xa1\xce\x63\xd1\x15\x3d\x7e\xc9\x48\x0e\xee\x90\x9b\xb7\xf9\x84\xdf\xcb\x39\x94\x2f\x75\xc3\x43\xd8\x15\xe9\xd6\x5c\x2c\x32\x6d\xf6\x43\xed\x14\xf6\x45\xa8\x94\xc0\x0e\x1c\xc8\xc0\xae\x28\x24\x35\xcc\xc8\x29\x66\xd9\x06\x62\x50\xb6\xcb\x1e\x51\x32\xe9\xe8\x2e\x28\x44\x52\x1d\x7c\x11\x16\xdf\x89\x53\x33\x25\x6c\x9c\xc6\x0f\x9a\xbd\x24\x0a\xef\xe4\x8c\x25\x6b\x39\xe2\x2c\xdd\xc1\x9d\xcf\xb4\x51\x3b\x62\xed\x61\x0c\x30\xb3\x43\x9c\xd2\x3c\x4b\x05\x7a\x53\x19\x1c\x40\xb6\x05\x1d\x00\x83\x32\x3e\x62\x3e\x7f\x28\x1a\x72\x3f\xa8\x77\x68\xf7\xc4\x05\x77\x24\x07\x08\x1f\x82\xff\x1e\xd1\x65\x60\xa8\x04\x81\xcd\x7b\x52\xaa\x24\xe8\x3b\x96\x40\x9e\x4a\x4c\x14\x80\xaf\x2b\x61\xd3\x51\xc4\x61\xa1\xe4\xe5\xbd\x10\xa5\x0d\xad\x66\x1b\xa9\xed\x94\x4b\x6f\x9c\x79\x6c\xfb\x77\x19\xd4\x08\xb5\x8c\x8d\xac\xea\x8d\x52\x30\x24\xc5\x44\x73\x7c\xfd\xb2\x0a\x74\x4d\x3d\x78\x6e\xe4\x94\xee\x54\xd5\xb4\xa7\x98\x21\x10\x05\x55\x75\xfc\xb0\xfd\xad\xe5\x20\x02\xbb\xa4\x03\xa5\xba\xb6\x17\xb1\xa5\xd2\x3b\x64\xb1\x8e\x4a\x4d\x38\x8b\xa5\x94\xd7\xb3\xa4\xa7\xba\xcf\x2c\x97\x87\xab\xd0\xca\x86\x6e\x58\xc2\x4e\x48\xb1\x01\x6d\xc1\xd3\x7b\x88\xea\xa9\x2f\xac\x21\x97\xcb\xde\x83\xcd\x83\x40\x15\x64\x48\x7a\x26\x0a\x32\x83\xc8\x22\xd9\x6c\xc2\x9c\xb7\x1d\xda\x11\xf5\x95\xaa\x3a\xe8\xe5\xe8\x90\x48\x8c\x0d\x24\x9f\x0e\xdc\xce\x4a\x2b\x49\x42\x5e\x56\x88\xab\xbd\x57\x3d\xf3\x80\x46\x81\xc5\x75\xd9\x7c\xb9\xb5\x8c\x3b\x5f\xd9\xdf\x3c\x12\x93\x32\x10\x1e\x65\x5f\xc5\x74\xda\xc7\x58\xd4\xad\x1b\xf0\xe0\x2c\x6b\x17\x39\x22\x13\x94\xc3\x19\xa1\xb4\xef\x24\xbf\x0e\x82\x2a\xd5\xe1\xe4\x0b\xd4\x26\x23\x27\xb3\xb2\x07\x1a\xb1\xb4\x94\xb3\xdb\xde\x9e\xda\xf4\x26\x8f\x69\x0b\xa6\x50\xc9\x12\x1d\x3d\x23\x07\x69\x1d\x28\xeb\x3c\x83\x86\xd2\x42\x61\xae\xb8\x7c\x62\x63\x64\x03\x02\x77\x44\xcc\xae\xf3\xa5\x6f\x8f\x24\x8b\xf8\xcc\x06\xe9\x47\x9e\xdf\xbe\x8f\xf8\xf0\x3b\x7f\x60\xa3\x7c\x82\xa8\xfe\xda\x57\x42\xad\x8a\x85\x42\x35\xdf\x62\xab\x75\x07\x67\xa6\x90\xdb\x22\x50\x16\x15\xb6\xf7\x4b\xdd\x72\x0f\x79\x6f\x23\x68\xe0\x4d\x3f\x79\x01\xa7\x59\x33\xb3\x84\x45\xaf\x92\x32\x35\x34\xb3\xea\x06\x99\xdc\x79\x8d\x78\x53\xa7\x77\xe2\x43\x63\xca\xcc\xca\xcc\xb6\x06\x83\xb6\x3d\x0e\x6c\x2b\xb9\x6a\xb0\xd8\x8e\xd9\xe5\x3e\x9c\x0f\x9b\x4f\x90\xc2\xb8\xb0\x08\xd7\x5c\x9d\xfa\x1f\xd8\x7c\xb5\xb5\xd4\x29\x0e\x6b\x66\x1d\x96\x5a\x8f\xd2\x88\x1b\x47\x27\xd6\x06\x7d\x88\x76\x1d\xf3\x02\x42\xb9\xdc\x57\x63\xa6\xd6\x73\xea\x29\x89\x85\xa0\x9f\x8e\x84\x43\x38\xfb\xa2\xca\x35\x16\xf3\x9e\x74\x6c\x31\xa3\xd5\x48\xcd\x69\xdc\x44\xa1\xea\xdd\xba\x19\x78\xdc\xb4\xdc\x39\x59\xfb\xdc\x46\x68\x25\xef\x66\xf8\xc1\x8f\xdb\x0a\x56\x3b\xd8\x39\x2a\x04\x96\x8f\xc8\xaf\xb4\x0d\xc4\x05\x5a\x30\xa6\x8f\x7f\xed\x49\x77\xc9\xe8\xcd\xe9\x85\xf2\xe2\x2e\x53\x05\x65\xad\x72\x6e\xdc\x00\x6a\x47\xe8\x98\x50\x70\x83\x29\x66\x24\x45\xc5\x8c\x51\x2f\x41\xfa\x74\x86\x99\x0c\xd6\xf0\x6b\xac\x85\x96\x3c\x2d\x69\x64\x98\x5e\xf6\x91\xa4\x4f\x25\x5b\x9e\xb0\xaa\xbf\x9e\x1c\xd1\x53\x35\xf4\x3c\x6f\xb6\x6e\x20\xae\x13\xbc\x63\x0d\x44\xcc\x16\x93\xd0\x5a\x7b\x07\x09\x4b\x68\x34\xea\xdc\x39\xd1\xb2\xe0\x8a\x52\x5f\xea\x2d\xa7\xb9\x53\x5c\x2b\x44\x41\x9f\x03\x79\xd6\x71\x14\xd5\x34\xb9\x93\x0b\x0a\x18\xb6\xf9\xdf\xa2\x40\x3b\x20\xe3\x31\xc0\x8d\x67\x0f\x85\x3b\x43\x4e\x0a\x5d\xd7\x56\xeb\x27\xe1\xdd\xb1\xdc\x4e\x71\x33\xf6\xe8\x0a\x25\x61\x9a\x49\x14\x5c\x8e\xb4\x7a\xeb\xb7\xf1\xa5\xde\x26\xda\x67\x86\xad\x01\x7b\xec\x97\x03\xcb\xc5\x5c\x3f\xb0\x95\x79\x08\xe4\xbc\xf0\xe4\x23\x0b\xb1\x1d\xea\xbc\xd4\xb8\xf3\x37\x3b\xfd\x5b\x04\xca\x21\x85\x02\x80\xb7\xde\x4a\x57\x0b\x4a\xf4\x16\x4b\xd7\xd7\x97\x26\x85\x1f\xa5\xe6\x1f\xd5\xb9\x45\x56\x32\x05\x4a\xeb\x62\x3e\x35\x76\x65\xb1\x4f\x07\xbe\x78\x95\xd4\x6f\x59\x74\x2b\x14\x07\xbc\xf6\xb6\x95\x1c\xb2\xcc\x9b\x2d\x4f\x88\x32\xce\xd0\xd1\x9a\x04\x66\x7d\x24\xc9\x33\x6f\xb5\xf8\x8e\x2c\xdd\x5d\x60\xa5\x48\x08\x76\x00\x6f\x58\x0e\x20\xa6\xb1\xcb\xbd\x5c\xe1\x45\xda\x49\x5f\xe3\x14\xfe\x7c\x6d\x3b\x63\xb1\x3b\xfc\xc4\x06\x19\x6c\xfc\x80\xee\x98\xb8\x7a\x69\xae\x2d\x54\xa9\x37\x41\xaf\x97\x6d\x4c\xe6\x1e\xd1\x27\x73\xcd\x36\x24\x89\xa9\x65\xdb\x1f\x9a\x27\x01\xdd\xba\x49\xb5\x28\x4e\xba\x5f\xb7\xa4\xad\x87\x9c\x76\xec\xcf\x8d\xf8\xae\xc6\x3e\x9c\xd6\xe0\x5a\x1d\xd2\xc2\xa0\x70\x0d\xf4\xa0\x3e\x13\xef\x7d\xc8\x05\x7a\xf9\x38\xe0\xfb\x88\x0c\xf4\x13\x8b\xec\x09\xc3\xfb\xeb\x13\x86\x57\xa5\xb7\x33\xb3\xc3\x46\x27\x18\x0b\x96\x0c\x59\xac\x1e\xb8\x05\x16\x00\x8f\x86\x96\x54\x21\x5a\x2c\x15\xe7\x65\x09\x52\xd2\x01\x89\xc3\x20\x1d\x4d\xa0\xd2\xd9\x6e\x64\x36\xcd\xce\x9e\x02\xc4\x88\x4e\x9a\x1e\x79\x8a\x73\xe1\xd6\xa4\xa1\x24\x8b\xb8\x5d\x1f\x5d\x2b\x5a\xd8\xcc\xdf\x69\x4e\x3d\x65\x5b\x31\x85\xff\x6a\xa6\x3a\x26\xa5\x69\x51\xd1\x84\x06\x72\xf3\x9e\x2e\x5b\xb4\xcd\x4e\x27\xc9\xa0\x16\x84\x05\x0e\xd0\x54\x2e\x63\x2f\xc5\x36\xe7\x5e\x42\x1b\x48\xe3\xcd\x50\x07\x5b\xaf\xcd\xac\x36\x0b\x81\xba\x59\x0d\x52\x85\xc1\x41\x41\xcc\x44\x02\x0b\x74\x2b\xf1\xda\xc8\x71\xa1\x14\xd4\xe3\xcc\x4a\x9e\xbc\x76\x0f\x99\x9b\x14\x1a\xd0\x5a\x82\x0f\x56\x32\x26\x8b\x17\x00\x0a\xe4\x54\xd8\x40\x24\xd4\x91\x92\xad\x40\x8d\x1d\x39\x77\x34\x88\xc1\xbc\xb0\xf3\x3e\x67\x5a\x00\x28\x3e\x32\xde\xdc\xa1\xc0\xc3\xb2\x6e\xa7\x27\x07\x6a\x62\xf3\xe9\xbf\xdc\xd5\xe6\xfa\x42\xf4\x51\x0c\xe3\xb2\xb3\x73\x86\xa4\xc2\x53\x1f\xd8\x0f\xc7\x81\xe5\x64\xb6\x1e\x12\x04\xb1\x05\x2d\xab\xd3\xf8\x50\xf8\xf9\xd4\x96\x27\x2f\x4b\x77\x4c\x59\x9d\xb6\xbd\x6b\xd9\x15\xcd\x7b\xd8\xd6\xb1\xde\xb3\x47\x5c\x88\x96\x8b\x3b\x9a\x10\xea\x43\x99\x08\x66\x67\xf0\x9d\xd2\x20\xe4\x87\xe9\xc6\xb6\xb2\x48\x36\x76\x78\xbe\x11\x65\x53\x94\xd9\x08\xc5\xec\xa4\xe8\x61\x8f\x71\xec\xd3\x65\xeb\x70\xe5\x1b\x47\xdf\x31\x99\x2d\xb8\x42\x9f\xeb\x65\x97\x59\xc3\x9c\x21\x4b\x09\x3a\xe6\x81\xbe\x3e\xb1\x89\x60\xd7\xda\xec\x6c\xb0\x35\x66\xb8\xdd\x36\x5f\x75\x8f\x1d\xca\x75\x08\x65\x09\x9d\x2c\x0e\x9d\x64\xe7\xaf\xdd\x0d\xea\x6b\xda\x43\x1b\xd0\xbf\x07\x96\x8f\xf2\x4c\x2d\xb3\x9d\x30\x37\x54\xf6\x7a\xc6\x7e\xa0\x50\x46\x8c\x15\xdd\xc1\xd2\xb3\xd9\x3f\xf0\xcb\xa1\x28\x1f\xd6\x7e\x67\x31\x65\x72\x06\xdb\x9a\x82\x6f\x32\xe8\xec\x23\x2c\xcf\x42\xa2\x38\x07\x49\x51\xf0\x98\x29\xd3\xde\x20\x90\xa2\x70\x9c\x87\x5e\xd0\x8f\xed\x1a\x70\x58\xb3\x54\x35\x19\x14\xf0\x59\x94\xd0\x54\x12\x25\x99\xbb\x2d\x35\x42\x04\x6a\x50\x8f\xf4\xc8\xe0\xe4\xd5\x99\x23\xd6\xec\x16\xbd\x76\x37\xa9\x35\x39\x83\x2b\x49\xd9\x3b\x8c\xbd\x56\xc6\xaf\x16\xa5\xd5\x3b\x1f\x24\xed\x18\xe5\xc2\x9c\xd3\x62\x53\x0b\xff\x44\xd0\x8f\x3e\x4b\xd0\x99\x76\x74\x3e\x6a\x10\x88\x5b\xd4\x9d\x04\x21\x28\x79\x4a\xd9\xc5\xc2\x3d\x0b\x22\x4b\x3d\x0a\x62\x47\xa9\xc3\xd6\x76\x4e\x44\x2d\x94\xcb\x91\xed\xdb\x72\xe4\x44\x4c\x6a\xdf\x55\x61\x77\x6d\x3f\xc8\xa8\x60\x42\xa6\xb6\xf4\x4f\x34\xd4\xfd\xe3\x09\xc1\xfe\xeb\x33\x82\xfd\x21\x77\x96\x0b\x09\xc4\x94\x9d\x74\x30\x97\x2b\x5d\x42\xb9\x4e\x75\xad\x53\x4e\xd7\xba\x16\x17\xd4\x05\x60\x57\x9b\x53\x4c\x31\x99\x83\x9e\x68\x42\x8a\x28\xac\x1a\x25\x41\x00\x3c\x07\x36\xb4\x2f\xbd\xaa\xb9\x20\xca\x9d\x72\x21\x66\xc0\xc9\x98\x04\x70\xaf\x19\x96\xdc\x0f\xd8\x9a\x71\x2e\x52\x8b\x92\x94\xab\xf4\x90\x3b\xcf\x13\xd2\x0c\xe3\x24\xd9\x6c\xe6\x3c\x91\xa8\x1b\x50\x9a\x3e\x2e\x3b\x44\x8f\xc0\x9c\xc5\xe2\x5d\x54\xb5\x58\xd0\x13\x2a\x5e\x51\xb4\x1f\x25\x05\x94\xb6\xe6\x6d\x93\x5a\x25\x58\x60\xa3\x02\x03\x4c\x93\xc5\xa2\x5f\x3d\x9b\xb3\xf1\x34\x77\x09\x45\x02\x92\x60\x65\xa9\x1a\xb5\x72\x68\x09\x83\xe2\x28\xa1\x67\xf0\xfe\x63\xad\xa2\x29\xb1\x1f\x82\xe5\x06\xb2\x2b\x7c\xd0\x8e\x5c\x2c\x86\xcf\x07\x98\xf8\x60\xd2\x06\x8a\x8a\x16\x29\xa7\xa0\x3d\x58\x30\x43\x51\x59\x76\x26\x16\x68\x65\xd4\xd0\xd4\x59\xbe\xca\x29\x81\x3e\xa7\xb9\xc3\x6e\xb8\x49\xa0\xa7\x8b\x30\x8d\x4a\xb0\x5e\x46\x9f\xc3\x13\x32\x68\xb3\x5f\x44\x6f\x58\x47\xf6\x35\x07\xe8\xce\xe3\x7c\x71\xff\xf0\xfe\x8d\x73\x94\xfb\xc8\x0f\xbf\xf7\x70\x1a\xe7\xd9\xd9\x13\xaa\x1a\xa6\x54\x20\xd4\xbc\xeb\x9e\x8c\xaa\xb2\x88\x15\xf8\x18\xe6\x6a\xd2\xce\xd0\x41\x67\x06\xcd\x65\x9f\x74\x1e\x11\x8b\x46\xe5\xbe\x8d\xe8\xec\x17\xa6\xc2\xb3\xdd\xf7\x32\xb9\x7f\x56\x62\xc6\x4f\x3e\x5d\xd4\xdf\x6d\x8b\x40\x5d\x5e\x58\x0e\xe7\x03\x4b\x3d\x88\xb6\x43\xb3\x5a\x9c\xaa\x98\xce\xf3\x50\xa0\xe2\xcb\xa1\x70\x1e\x09\x35\xee\x83\x0e\x89\xad\xd7\x4a\x9d\x59\x51\x39\x40\x3e\x88\x2a\x5e\x9b\x29\xd4\x9e\x77\x51\x7b\x94\x40\xd3\x83\xab\xb3\x99\x65\x6b\x14\xb9\xdf\xe3\x20\x11\x7e\xa8\x98\x34\x3b\xc8\xf2\x0a\xda\x7f\x63\x4d\x9c\x2a\xa2\xe9\xa0\x3e\x3d\xb6\x7b\x97\x4b\x9a\x93\xfb\x6d\x1a\x97\x23\x52\x3a\xc7\xb5\xb5\xc5\x41\x7d\xcd\x2c\x27\xd0\xf5\x4e\x46\xce\x55\x50\xa0\x17\x98\x06\x65\xa7\xe1\xe4\xdb\x0f\x95\x20\x9a\x0f\x6a\x12\x71\x33\xab\x35\x80\x57\xee\x13\x26\xe8\xa9\xef\xe1\xd7\x9f\xff\x8f\x07\x55\x4c\xad\x6d\x81\xe1\x45\x57\x5b\xb4\xb4\x20\xed\x26\xed\x1a\x2d\x62\x7b\x7c\x8f\x8c\x8c\x8d\xff\xbb\x96\x71\x23\xa5\xed\x7a\x83\xb7\xd7\x26\x87\xe8\x5f\x31\xec\x03\xe8\xff\x0f\x0e\x7b\x79\x77\xdc\xc7\x86\x81\x1f\x79\xbe\x8f\xbd\x06\x3f\x6c\x5c\x70\xcd\x95\x92\xee\x5c\x73\x70\x3d\x06\xc9\x0e\xe8\x12\x5f\xe3\xc8\x8a\xfc\x30\x05\x5d\xd5\xa6\xa2\x8e\xd0\xc6\x22\x9a\x2b\x29\xe0\xdf\x07\x3e\xbd\xda\xe1\x38\x9a\xdf\x3f\x38\x9c\x47\x29\x8a\xaa\xb4\x9e\x8c\x07\xf8\xff\x15\xba\xb3\x4e\x48\xfc\xf0\xae\x88\x37\x55\x98\x3b\xd5\x56\x04\x6d\xb3\xcc\xae\xe8\xf1\x2d\x1f\xbd\xb4\xf2\x17\x8e\xde\x35\xd9\xe8\x97\xbf\x68\xf8\xd9\xdb\x5f\x78\xf2\xa2\x59\x7f\xc8\xf0\x97\xaf\xc7\xff\xbe\xe1\x78\x6a\x77\xf9\xf5\xb9\xdd\xe5\x41\x05\xa5\x5a\x0c\x2a\xa8\xc5\x82\x10\x73\x13\x94\xd9\x52\x87\xbf\x61\x71\x9c\xd3\xa1\x9e\x79\x17\x46\x3e\x70\x3f\x49\x5f\xe4\xa5\xa1\x32\x42\x33\x77\x12\x5a\x86\xa9\x6d\xd5\x63\x22\x4a\xf0\x32\x01\x4e\x7e\xd4\xe6\xf2\x3f\xa7\x9b\x59\x74\x03\x63\x4c\x4e\x69\x8b\xda\x25\x88\x99\xb7\x2c\x79\x83\x43\xae\x79\xec\x4e\xd9\x81\xf0\x62\x32\xef\xe3\xdb\x97\xbb\xe7\x24\xbe\x81\x37\x81\x6d\x01\x62\x57\xa8\x5d\x8d\x9b\xb9\x28\xfb\x1b\x21\xd5\xcb\xfb\x30\xf5\x1b\xe5\xc3\x58\xf6\x1a\xfb\x49\x14\x92\xe9\x26\x29\x7e\xa4\x9e\x3f\xab\xcc\x40\xe1\x44\x2c\x08\x9e\x38\x5f\xcd\xe3\x66\xe7\x8e\x2b\x89\x52\x1b\x2f\x2e\x66\xe8\x76\x67\xe6\x14\x7d\xe7\x50\xbf\x1b\x5e\x36\xd4\x60\x77\xc8\x6e\x9d\xb4\xc4\x5b\x19\x05\x42\xc2\x7c\x18\x88\x3f\x18\x96\xcc\xa5\x28\x9d\x01\x4a\x68\x8b\xb3\x46\xa7\x53\xc4\x6d\x7c\x10\x9d\x8f\x36\xe7\x0b\x88\x1c\x1a\x99\x25\xe6\x81\x3a\x15\xf1\x71\x95\x8a\x9e\x35\x81\x78\x7d\xcb\xc8\xc8\xeb\xc6\x07\xd1\xd7\x13\xe9\x5b\xf4\x4f\x90\xef\x17\x9e\x90\x40\x85\xd6\x8c\x19\x72\xaa\xb8\x8d\xb6\xb9\x5a\xd4\x6b\xb6\xaa\x6d\xfc\xf5\x35\x2f\x3a\xae\xe5\xac\x56\x62\x5e\x9d\xe7\x9e\x49\x77\x33\x42\xec\x6b\x1e\xb6\x2d\xf2\x6e\xe0\x4a\x21\x88\x8d\x7b\x74\xdc\x6f\xdb\xba\x95\xdb\xba\xcb\xdb\xba\xf1\xf6\x18\x2e\x5b\xf4\x87\x82\xc7\x09\xda\x17\x7b\x54\xc7\x7a\x70\xeb\x49\xfa\x93\x5d\x8f\x7a\x5b\xb3\xe0\xc6\xc9\xf3\xad\xd6\x1d\x4c\xb0\xcd\x67\xdb\xce\x5f\xf1\x49\x78\xac\x59\x79\xce\xd3\xfb\xd4\xe5\x64\xe6\xf9\xd9\x24\xf7\x29\xcf\xf9\xbf\xf9\x82\xb0\xf5\x93\x7b\xf0\x75\x72\x3c\xac\x9d\xb5\xa0\x70\x87\x6c\xa9\xf9\x13\x6f\x97\x9d\xb7\x98\x2b\xf2\x58\x4b\x14\x2b\xd1\xe2\xdf\x2f\x27\x29\xd2\x7d\x71\x9f\x93\xad\x6f\x6e\x09\x76\x45\x8e\x0f\x9b\x14\x82\x81\x58\xb2\x37\x79\x24\xf0\x95\x45\x19\x2b\xe3\x99\x83\x70\x76\x34\x3d\xa7\x7d\xdf\xce\x17\xfc\x64\xc7\xf4\x43\x3d\x2f\x9d\xda\x1d\xc8\x25\x9d\x50\x4d\x48\xb2\xe8\x27\x3a\x44\xfe\xf1\xd4\x21\xf2\xeb\x37\x3b\x44\x4a\xcf\xa1\xa5\xbe\xf7\x00\x41\xb7\x9c\xbd\x9d\x91\xa5\xd7\x61\xeb\xbf\xf7\x20\xd9\xfc\x65\x95\x00\x3a\xf7\x68\x2e\xe2\x9d\x0a\x38\xab\x5d\x3d\xc4\xf4\x3d\xe9\x8b\x4c\x0a\x84\x2c\x3d\x16\x02\x23\x1a\xb8\x71\x03\x70\x43\xf8\x09\x44\xc0\xf6\x13\x42\xa9\x55\xfb\x11\x65\xc9\x8f\xac\xf1\xf6\xf4\x6c\x35\xe7\x50\x27\x70\xc4\xe0\xa0\x3f\x2c\x32\xf6\x94\x23\x20\x26\x35\xb7\x8d\x24\xe3\xd9\x36\x05\x86\xb7\x9d\x6e\x36\x48\x99\xa9\x93\x1c\xb3\xca\xc5\xdb\x00\x20\xcd\x89\x45\x61\x36\x13\xb4\xd4\x80\x10\x1f\x31\x83\xb7\xc5\xfc\xee\x2d\x4e\xf0\x72\x65\xdd\x72\xe9\x21\x17\xc4\xa0\x29\xd0\x3f\x66\x18\xc1\xbc\x12\x65\x98\x55\x28\xbb\x2b\x03\x4d\x7f\x21\x97\x74\x28\x63\x39\x0c\x9d\x51\x9e\xc5\xd0\xbb\xcd\x24\xd5\x50\x53\x0a\xad\x1d\xfc\xf3\x89\x67\xfb\x84\xea\xfe\xf5\x5b\x9c\xee\xb3\x8c\x50\xd3\xd8\x90\x82\xc9\x3a\xaf\xb1\xca\xc6\x6c\x64\x35\x1b\x8a\xe2\x57\x4d\xd7\x58\xe6\x26\x7d\x86\xdc\x0b\x64\x1d\x73\xde\x14\x7a\x87\x4c\xe8\x25\x9b\xb9\x16\xda\xa4\xd7\x97\xda\xa0\xde\x97\xb6\x9c\x10\x66\xd8\x30\xac\xdd\x02\x13\x53\x82\xe4\xf4\xfa\x32\x53\xb7\xa0\x6b\x7d\x3f\x53\x4e\x32\x42\x58\x52\xf3\xb4\xbb\xf3\xfa\x22\x60\x55\x6e\x75\x13\xf6\x7c\x6e\xcc\x67\x4e\x1b\x72\xa6\x30\xc4\xe2\x9a\x91\xbc\x7a\x08\xd2\x74\x24\x27\xcb\x3d\x39\xe9\xe9\x74\xa6\x27\xfb\x3d\x3d\x79\xe1\x8b\xd8\xce\xec\x65\x5c\x69\xd4\xe6\xaa\x04\x14\x3b\x86\x55\x2c\xc7\xfa\xfb\xe6\xd3\x37\x5f\x5c\xc3\x71\xfc\xe3\xf1\x37\x1f\x4f\x86\x27\xf8\x9f\x8c\x07\xba\xfc\x19\x40\xd0\xff\x7c\x82\xff\xfe\xf6\x0c\xff\x7d\x68\x0a\xce\xb9\x84\x9c\xb0\xf1\xa9\x39\x3e\xa0\x21\xb4\x90\x7e\x9e\xa2\x26\xcc\x97\x31\x43\x5c\x9d\xab\xbd\x06\x5b\x51\xd9\xb9\xc4\xbc\xf3\x07\x35\xb7\xee\x3e\x14\x0a\xec\x58\xc6\x29\x03\x42\x81\x56\x5f\x12\x3c\xda\x5c\x42\xb5\x8e\xf9\x38\x3c\x33\xa2\x4f\xf0\x5f\x3e\xdb\xc0\x82\x58\xc8\xcb\x3f\xab\x2e\xba\x3b\x59\x75\x99\xc1\xb7\xfa\xbe\x7a\xcf\xce\x17\xd5\x0b\x68\x9e\xd8\xb7\xc7\xeb\x39\xed\x4a\x47\x23\xbb\x97\x04\x04\x38\x76\xfc\xe9\xc5\x3f\x47\xcb\xc8\xe1\xf2\x2f\xab\x12\x5f\x7d\x5b\xcb\x60\x24\xb7\x0d\x64\x94\x60\x41\x79\x11\xec\xbc\xb3\x40\xe4\xb1\xb7\x10\x9b\x53\xe0\x59\xc4\x52\x64\xa9\x37\x7b\x21\x97\xb2\xbf\xde\x3c\x71\x38\x45\x5d\xf7\x5e\x0d\x57\xd4\x06\x97\xe0\x21\xe2\x60\x80\xdd\x82\x6f\x66\x1e\xa5\x1e\x99\xde\xcd\x8e\x72\x6b\x9f\x41\x26\xb5\xae\x03\xca\xa1\x7b\xbb\x2b\x2d\x3b\x43\x3a\xb8\xcc\x40\xe5\x65\x36\x00\xce\x12\x5d\xbf\x0a\x47\x67\xd2\x00\xfa\xa9\xb1\x32\x3c\x02\x51\x5a\x20\x0a\x70\x0d\x20\x0b\xf1\x0b\xe0\x03\x61\x04\x24\x3c\xa7\x1e\xc8\x27\x3b\xa7\x7e\x23\x77\x9f\xa2\x6a\x55\x6c\x82\xdb\xb6\x48\x82\xb5\x3c\xf8\xab\xed\xec\x40\x20\xf9\x64\xf7\x92\x28\xfd\x3d\x8a\xf6\x63\x53\x49\xf9\xe8\x25\xc4\x5e\x76\x34\x21\x06\x9c\x2b\x25\xd7\x89\xc6\x22\x25\x7e\x39\x34\xc1\x81\x78\x7d\xc9\x23\x07\x20\x95\x88\xe4\xe0\x54\x76\x78\x6d\xfd\x42\x76\x7c\x24\xb0\xd5\x81\x26\xc2\x8e\x13\xd4\xf9\x4a\x40\xb6\x17\xa9\xff\x03\xde\x01\x28\xe7\xd0\x2a\x84\x1a\x46\xef\x44\x8c\xf5\x30\xbe\x9c\xfd\x62\xea\xbb\xd2\x1d\xa6\x33\x0e\xc7\xf0\x08\x3b\xd3\x3a\x69\xc8\x71\xb8\xa6\x25\x50\x8d\x63\x57\xca\x9b\xe4\x8e\x3d\x34\xe0\xdd\x06\x59\x13\x49\x85\x97\xb3\xa7\xa6\xd1\xcb\x43\x0f\x2f\xdb\x4c\x30\x07\xa9\x8e\x5d\x86\x4d\xc4\xc2\xd2\xe0\x51\x5d\x5a\x75\xf7\x58\xc0\xf6\xc1\xca\xc6\x19\xdc\x59\xf6\x67\xa0\x44\x51\x14\xf9\x6c\x1d\xb8\xd9\xcd\x95\x3d\x4e\xad\xf7\xb4\xc0\x76\x4c\x86\x99\xc1\xce\xa1\x41\x20\xb1\x66\x64\xb0\x27\x80\x3b\x41\xf2\x51\x49\x99\x0a\xb0\x18\x18\x27\x74\x6f\xd3\xcb\x82\xae\x8b\xca\x55\x48\xb8\x8b\x26\xd8\x87\x99\x48\xaa\x09\xe2\x4c\xf3\x80\xd5\x79\x2d\x1c\x90\xa4\x7d\x49\x8d\x47\xff\x7a\x49\xcb\x75\xf1\xc6\x8b\x4c\x6e\x49\x6c\x4c\x10\xa5\xd1\xd3\xf7\x93\x99\x03\x94\xd3\x2f\x80\x62\xf5\xcc\x79\xd5\xca\x0e\x98\x0b\x92\xa2\xec\xaa\x01\x06\x0a\x57\xa2\xe3\x88\xe6\x8a\xd8\x9c\x0e\x92\x59\x03\x6b\x01\xbc\x75\x03\x1f\xb3\xf0\xa0\x95\x0a\x16\x64\x23\x30\x87\xca\x7c\xa3\xac\x61\xa0\x2e\x23\x66\xdd\xcb\xa9\x3d\x29\xcd\x02\xbb\xc3\x55\x79\x1a\x88\xf2\x34\x80\x40\x2e\x91\x63\x4f\x74\xf1\xb8\x3a\xd1\xea\x48\x4b\x19\x40\x2c\xf4\xfa\xb2\x9a\x99\xf6\xca\x05\x34\x6c\x76\xf6\x83\x25\x07\x73\xef\xf0\x62\x72\x19\x0f\x2a\xf2\xbc\x5e\x5e\x8a\xc5\x16\xaa\xe0\x5f\xb6\xbb\x3b\xef\xf7\xd2\x6b\x71\x0c\x76\xa7\x83\xc4\x4e\x00\x81\xcb\x02\x2e\x7d\x71\x7b\x30\x50\xbe\x2c\xab\x8a\x87\x2f\xa2\x9c\x49\x70\xca\x5c\x33\x1a\x03\xb3\x46\x2f\x35\xe5\xbd\x70\xc1\x3b\x98\x82\xe0\x29\x59\x05\xf3\xea\x60\x52\x25\xf6\xd1\x96\x0a\x32\xe5\xe2\x3a\x59\xc3\x16\x7e\x09\xd9\x51\x10\xe0\x46\x05\xa3\x8c\x8c\x94\x42\xad\x90\x17\xb6\x93\x3b\x0b\x8a\x0e\x60\x81\x8b\x38\xa9\x97\xd8\xc2\x42\x52\xe6\xa5\x4a\x9f\x3b\x6b\x05\xaa\x66\xa9\x0a\x83\x99\x78\xae\x4f\xe2\x3e\x5e\x44\x80\xd4\x63\x8a\xc2\x56\x24\x6b\x13\x3c\x79\x7a\xf7\x98\x8c\xb0\xac\x8d\xee\xae\x6f\x20\x4c\xf8\x17\xa7\x74\xb4\x3d\x00\x64\x8d\xf3\xc0\x02\x28\xe3\xa8\x23\xcc\x83\xa0\x3c\xbb\x9a\xa1\xa1\x4f\xc5\xcd\x22\x95\xe0\x83\xdd\x62\xfb\x52\xa5\xd9\xea\xe7\xc6\x56\x9d\x9a\x1a\xf7\xad\x9a\xe9\x1a\xc0\xed\xb7\x8b\x3d\xed\x1c\x1c\x9b\x76\x78\x43\x1a\x94\x77\x81\xfb\xcd\x79\x67\x1f\x94\x2b\x0d\x96\xb9\x80\x6c\xc5\x77\x20\x9c\xc3\xe4\xc6\x67\xd1\x34\x08\xa0\x43\x99\x66\x14\x2d\xee\x85\x2b\x20\x47\xa1\xe9\xfa\x8c\x3f\xf2\xd4\xab\xf3\xdb\x47\xbd\x3a\xdf\x1d\xea\xa9\x67\xe6\xb7\xa7\x9e\x99\xcf\x0e\xf5\xd4\x2c\xf2\xdb\x47\xcd\x22\xdf\x1d\xea\xa9\x25\xe1\xb7\x8f\x5a\x12\xbe\x3b\xd4\x13\xb2\xfd\xb7\x8f\x90\xed\xdf\x1d\xea\x09\x17\xfe\xdb\x47\xcc\x99\xdf\x1d\xea\x09\x39\xf7\xdb\x33\xb9\xe3\x77\x87\xfa\x3f\xdb\x7c\xc2\x4a\xfd\xf6\xcc\xeb\xf7\xc9\x53\x7a\x42\x84\xfc\xf6\xcc\xea\xf6\xc9\xa1\x9e\x2a\xa2\xbf\x7d\x54\x11\xfd\xee\x50\x4f\x95\x8d\xdf\x9e\x19\x9d\x3e\x39\xd4\x53\xae\xf3\xb7\xe7\x5c\xe7\x27\x87\x7a\xca\x27\xfc\xf6\x51\x3e\xe1\xbb\x43\x3d\x85\xaf\xbf\x7d\x14\xbe\x7e\x63\xa8\xed\xb7\x7f\xff\xf7\xdf\xf6\xff\xf7\xa7\xed\xab\xc1\x6a\xfa\xa8\x4f\x91\x83\xfd\xeb\xbf\xfc\xaf\xff\xe7\xff\x3e\xfe\xed\xf2\xaf\xff\xf2\xeb\x6f\xff\xeb\xdf\xff\xed\x5f\xff\xe5\xdf\x6f\xff\xd7\xbf\x5d\xfe\xbf\x00\x00\x00\xff\xff\xae\xf1\x3b\x5f\xdb\xc7\x06\x00")
+
+func uiAppLibFontAwesome470FontsFontawesomeWebfontSvgBytes() ([]byte, error) {
+ return bindataRead(
+ _uiAppLibFontAwesome470FontsFontawesomeWebfontSvg,
+ "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.svg",
+ )
+}
+
+func uiAppLibFontAwesome470FontsFontawesomeWebfontSvg() (*asset, error) {
+ bytes, err := uiAppLibFontAwesome470FontsFontawesomeWebfontSvgBytes()
+ if err != nil {
+ return nil, err
+ }
+
+ info := bindataFileInfo{name: "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.svg", size: 444379, mode: os.FileMode(420), modTime: time.Unix(1, 0)}
+ a := &asset{bytes: bytes, info: info}
+ return a, nil
+}
+
+var _uiAppLibFontAwesome470FontsFontawesomeWebfontTtf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\xbd\x0b\x7c\x54\xd5\xb5\x3f\xfe\x5d\xfb\xbc\x66\x26\xf3\x3e\xf3\x48\x26\x93\x64\x9e\x67\x02\x89\x01\xe6\x19\x79\x24\x23\x20\xaf\x04\x44\xa5\x95\x22\x62\x44\x50\x14\x50\x54\x14\xa4\x3e\x8e\x95\x5a\x54\xaa\x88\x68\xa9\xb5\x36\x3e\x0b\xb7\xd6\x72\x5b\xed\xd5\x16\xbd\xd3\x97\xb5\xad\x5a\x5b\xb9\xd6\x5a\xdb\x9b\xb6\xda\x7a\x2b\xda\x40\xad\x57\x21\x73\xf2\xff\x9c\x73\x66\x92\x49\x00\x6d\xef\xfd\xfd\x7e\x9f\xff\x7c\x72\xce\xd9\xef\xbd\xf6\xda\x6b\xef\xbd\xd6\xda\x6b\xef\x80\x00\x38\xa0\x82\xc3\xe2\x39\x73\x96\x2c\x5c\xfb\xcc\xdc\xa7\xc0\x6e\xda\x01\x20\x3c\x77\xf6\xa9\x73\xd8\x20\x78\xb0\x9b\x36\x00\x88\x9c\x76\xe6\xa4\xf4\xb6\xf4\x96\x22\x40\x4b\x01\xf4\x9d\xbf\xfe\xbc\x0d\xb6\x7f\x9f\x7a\x3d\x60\xdf\x03\xb0\xc3\x17\x9e\x77\xc5\x86\xe1\x61\x70\x60\x37\xad\x01\x60\xb9\x70\xdd\xd5\x17\xdc\xfe\xdf\x8f\x2d\x04\x42\x8f\x82\xf5\xee\x5f\xb3\xfa\xbc\x55\xee\x9b\xdf\x3c\x09\xc0\xeb\x00\xf2\x6b\xd6\xac\x3e\xcf\xc5\xd9\x9e\x00\xc8\x07\x20\xb1\x66\xfd\xc6\xcd\xa7\x5e\x5d\xff\x59\x80\x9e\x04\x6c\x83\xeb\x2e\x3d\xff\x3c\xf6\xf7\x07\x96\x03\xae\x7b\x81\x3a\xf7\xfa\xf3\x36\x6f\xe0\xda\x59\x18\xa0\x4e\x1d\x9e\x4b\xce\x5b\xbf\xfa\x8f\x5f\xb8\xf5\x51\xb0\x0b\xd7\x00\xfc\x4d\x1b\x2e\xbd\x62\xe3\x37\x6e\xff\xd2\xfd\x60\x6b\x07\x81\xd0\x95\x46\xdb\x78\xfa\xd9\x8e\x9f\x6f\xfe\xd4\xb9\xae\xe9\x7f\x47\x9d\x04\xfd\x77\x20\xf3\x42\xba\xfa\x1d\x1e\x1e\x86\x95\x44\xdd\x6b\x01\x33\x72\x40\x7f\x8b\x18\x06\x60\xc5\xf0\xf0\xf0\xb0\x95\x2a\xe1\x23\x3f\xf6\x84\x1e\xc2\x7e\xc0\x1a\x90\x32\x03\x8c\x5c\x7a\xaa\x62\x25\x09\x27\x5e\x44\x3b\x20\x00\xfc\x76\x3e\x03\xe0\x26\xf3\xcb\xae\x00\xe8\x16\x7c\xc4\x6f\xc3\xd5\x97\x5f\x81\x22\x22\x7f\xaf\xc0\x20\x9a\x95\xd7\x42\x10\x01\x71\x2a\x36\x18\x15\x7f\x02\xa0\x12\xa0\xb7\xec\x1f\x78\xce\xd1\x5b\x2a\xaa\xa3\x61\xba\x5b\x7f\x04\xdd\xaf\x8e\x8d\x93\x80\xab\x05\x15\x97\x54\xd3\x88\xd5\x3c\x00\x04\x33\x2c\x24\x56\xfc\x92\x8a\x74\x35\xcd\xf1\x1e\x3d\x1f\x6f\x96\x5d\xd4\xd3\x71\x15\xbf\x51\xb7\x3a\x5a\x6e\x05\x06\x9b\x50\x85\xb3\x26\x0d\x5f\x53\xff\xc7\xb6\xb5\x02\x0b\x8f\xd1\x6f\x6d\x7b\xa5\xb1\x61\x5b\x84\x5a\xd8\x6b\xe2\x45\x06\x12\x80\x7b\x04\x60\xd9\x89\xda\x76\x9c\xa7\x58\x29\x27\xa7\x3f\xd2\x68\xb8\x43\x50\x47\x70\xb7\xa5\x16\x37\xc2\x58\xbc\xbb\x85\x71\x7d\x51\x49\xb7\xcc\x78\xd4\x9a\x76\x98\xb8\x2c\x4a\x06\x01\x8f\xc5\x77\x15\x0f\x35\xf5\x83\x53\x6b\xf0\x30\xda\x27\x23\xed\xae\xfd\x56\x61\x15\x46\xe3\xdb\x79\xe0\x5c\xb1\xa6\x6f\x04\x75\x4c\x7d\x7a\xbb\x59\x2d\xcc\x27\x7c\x54\xf8\x2b\xed\x16\xc6\xf5\xbd\xbb\xf2\xbd\x42\x02\xa8\x92\x86\x1f\x4f\x4b\x12\xe0\x1a\x03\xb7\x8a\x46\xa9\x8a\xf7\xca\x63\xad\x94\xc9\x57\xfa\x92\xa9\x28\xb2\x0a\xde\xaa\x61\xfc\x38\x58\x25\xa0\xb5\x96\x8e\x38\xd5\x84\x61\x3c\xcd\x48\x35\xed\xaf\xe9\xbb\x62\x2d\x4e\x46\xe2\x54\xb3\x7f\x2a\xed\x1a\x81\x91\x07\x4e\xe2\x01\x07\xaf\x62\xa1\xfe\x30\x15\x27\x31\x75\xd4\x5f\xad\x83\xaf\x8c\x17\x71\x2c\xfd\x16\xc5\xf1\x34\x3d\x8e\x5e\x6a\xc6\x66\x35\xae\x58\x19\x7f\x0e\x49\xc5\x49\x95\xbc\x4c\x50\xc1\xaa\x38\xa9\x7c\xfb\x74\x3c\x31\x15\x2b\x45\x40\xd0\x1f\x49\x05\x89\x15\x58\x04\x15\x8e\xea\xf8\x14\x54\x70\xa2\x8a\xc4\xf1\xfa\xbb\x82\x17\x7b\x75\xec\x57\xc3\x48\x1d\x83\xef\x7c\x35\x9c\x07\x38\xfd\xf9\xb8\xf1\x55\xd3\x77\x59\xee\x33\x00\xcf\x81\x17\xaa\xe3\x08\xe8\xac\xa1\xb1\x98\xfe\x48\x30\x1f\xb1\xfa\xd4\xcc\x67\x22\xd0\xa8\xd3\xe0\x38\x1a\xae\x1b\xdf\x8e\x4a\xbd\xb3\x8d\x31\x04\x70\xfa\x53\xc1\x67\x75\x3c\x57\xd3\x8d\xe4\x15\x80\xf6\xca\x77\x64\x1e\x92\x2a\x61\x95\x7e\x88\x48\xea\xf0\x70\xed\x9c\x2a\x00\xfe\xe3\x8c\x95\x91\xb1\xaa\xa7\xb1\x8c\x9b\x8f\xab\x63\xdf\x6a\xa6\x5f\x2f\x8e\xa7\xe9\x4a\xda\xea\xfc\x20\xbd\x8f\x09\xe3\xc7\x53\x05\xce\xea\xdc\x6c\xb4\xcb\x5a\x9b\x67\xf4\xeb\xb6\x8c\x86\x47\xaa\xfd\x61\xfd\xc7\xe7\x46\xfd\x49\x55\x61\xae\xc0\x1f\x91\x00\xb9\xa6\x8e\xd9\x15\x78\x4e\x96\x00\x6f\x4d\xba\x5a\x98\xbb\x04\xa0\xfe\x38\xf3\xc2\xf8\xa7\x41\x02\x56\x89\xc0\xa7\x2a\x70\x4f\xac\x94\x63\x95\x80\x94\xb5\x02\xfb\xf8\xc7\x02\x38\xf5\x47\x50\x8f\x5f\xbe\x65\xdc\xb7\x8a\xdf\x9a\x7e\x30\xdc\x02\x50\x67\x19\xd7\x7e\xcb\x38\xb7\x65\xbc\xbb\xd2\xbf\x15\xbf\x2c\xd6\x94\x59\xa1\x71\x56\xa5\xab\x9a\xf9\x96\xe9\x63\xd4\x02\x88\x95\x38\x66\x81\x39\x2e\x84\x71\xf8\x13\x6a\xca\xb2\x8c\x83\x61\x3c\x4d\x58\x3e\xc0\x12\x6b\xc5\x7f\x3c\x3c\x55\x69\xdb\x32\x8e\x06\xaa\xf1\xd2\xc7\xd0\x86\x34\x0e\x8e\x11\x1a\x78\x62\x4c\xdc\x08\x3d\x0a\xc0\x05\x46\xde\x27\x47\xcb\x1f\x69\xff\xd8\x3e\x09\x88\x80\x53\x02\x9a\x8e\x47\x17\x95\x79\x3c\x69\x39\x7e\xf8\x19\xe3\xe0\x3b\xd5\x3a\x96\x56\xc7\xb7\x2d\x71\xbc\x76\x55\xca\x8e\x8a\xc0\x5a\x1e\x68\xad\x84\x73\xe3\x79\x18\xb1\x4a\xef\xaa\x41\x8f\x5c\x75\x8c\x57\xca\x1f\x49\x2f\x0c\x23\x29\x56\xd6\x23\x61\xec\xfc\xe0\xaa\xa5\x11\x71\xec\x9a\x9f\xb4\x8e\xad\xcb\x3f\x8e\xbe\x8e\xa1\x8d\x9a\xf0\x26\x6b\x0d\x5e\xc6\x3f\x35\xbc\x05\x8d\x1f\x17\x23\x0f\xab\xa1\x75\x15\x93\x75\x9c\x57\x60\x9c\x54\xc3\xa3\x28\xd2\x47\xb1\xc4\x15\x8e\xba\xf2\x84\x2b\x0c\xf1\x41\x70\x86\x2b\x0c\x9e\x5e\xd2\x19\x67\x14\x21\x60\x32\x22\xd8\x8b\xc7\xf0\x38\x9e\xc5\xab\xd1\x58\xac\x39\xd6\x37\xe8\x1c\x6c\x1e\xec\x1a\x5c\x34\xb8\x62\xf0\x92\xc1\xeb\x06\x6f\x1b\xbc\x6f\xf0\xb1\xc1\x6f\x0e\xbe\x38\xf8\xbb\xc1\x77\x07\xb5\x43\xce\x43\xcd\x87\x3a\x0e\x75\x1d\x5a\x74\x68\xc5\xa1\x4b\x0e\x5d\x77\xe8\xb6\x43\xf7\x1d\x7a\xec\xd0\x33\x87\x5e\x3c\xf4\xbb\x43\xef\x1e\xd2\x0e\x3b\x0f\x37\x1f\xee\x3a\xbc\xe8\xf0\x8a\xc3\x97\x1c\xbe\xee\xf0\x6d\x87\xef\x3b\xfc\xd8\xe1\x67\x0e\xbf\x78\xf8\x77\x87\xdf\xfd\x3b\x86\x87\x0d\x7e\x7c\xcf\xb8\x1a\x31\xe8\x1e\x8c\x0e\x16\x07\x17\x0f\xf6\x0d\x6e\x18\x54\x07\x77\x0c\xf6\x0f\xee\x1b\x2c\x0d\xbe\x34\x38\x30\x38\x78\x08\x87\xdc\x87\x22\x87\x26\x1f\x2a\x1e\x5a\x7c\xa8\xef\xd0\x86\x43\xea\xa1\x1d\x87\xfa\x0f\xed\x3b\x54\x3a\xf4\xd2\xa1\x81\x43\x83\x87\x71\xd8\x7d\x38\x7a\xb8\x78\x78\xf1\xe1\xbe\xc3\x1b\x0e\xab\x87\x77\x1c\xee\x3f\xbc\xef\x70\xe9\xf0\x4b\x87\x07\xf4\x1a\x87\xff\x38\xbc\x7c\x78\xe9\xf0\x99\xc3\x33\x87\xa7\xfc\xee\xad\xdf\xbe\xf3\xdb\x47\xdd\x0e\xb7\xdd\x6d\x73\x5b\xdd\x16\xb7\xe4\x16\xdd\x82\x9b\x77\x73\x6e\xe6\xfa\xbb\xeb\x3d\xd7\xdf\x5c\x87\x5d\x87\x5c\x83\xae\xbf\xba\xde\x75\xbd\xe3\x3a\xe8\x7a\xdb\xf5\x17\xd7\x7f\xb9\xde\x72\xfd\xd9\xf5\x27\xd7\x9b\xae\x37\x5c\x7f\x74\xfd\xc1\xf5\x7b\xd7\x80\xeb\x77\xae\xdf\xba\x5e\x77\xfd\xc6\xf5\x9a\xeb\xd7\xae\x57\x5d\xbf\x72\xbd\xe2\xfa\x0f\xd7\x01\xd7\xcb\x8e\xef\x8f\x97\x7d\xfe\x5f\xfc\x74\x81\xac\x5a\x2d\xb1\x8a\x7c\x35\x26\x81\x49\x0a\xff\x7f\xf8\x89\x82\x4d\xe2\xed\x16\x6b\xdd\xff\xad\x0a\xda\xff\x07\xcf\x0e\x53\xa6\xa6\xdd\x00\xdb\x08\xb0\x97\x00\xae\x17\xe0\x06\x01\x7e\x09\x20\x26\x00\x71\x00\xb0\xac\x03\xac\x9b\x01\xeb\x4b\x80\x6d\x09\x50\xd7\x0a\xd4\x1d\x00\xec\x5b\x01\xc7\x2a\xc0\xb9\x07\x70\x1d\x00\xdc\x5b\x01\x0f\x00\xcf\xbd\x80\x77\x1d\x20\xb7\x03\xf2\xab\x80\x4f\x05\x7c\x43\x80\x7f\x07\x10\xc8\x02\x41\x37\x50\xbf\x0a\xa8\x7f\x1e\x68\xd8\x00\x84\xe6\x01\xa1\x5d\x40\x63\x02\x08\xaf\x02\x9a\xda\x81\x66\x0b\xd0\xbc\x11\x68\x69\x05\x22\xdb\x81\xc8\x20\x10\xed\x07\x62\x93\x81\x78\x04\x48\xb4\x03\x89\x01\x40\x99\x0d\xa4\xde\x00\x5a\xef\x05\x26\x2c\x01\x26\xea\x4b\xf7\x7e\xa0\xdd\x0d\xb4\xbf\x07\x9c\xf4\x2a\xd0\x51\x04\x3a\x5e\x05\x26\xf5\x01\x93\xf6\x03\x93\x7d\xc0\xe4\x87\x80\x29\xbb\x80\xf4\x0e\x20\xb3\x0a\xc8\x66\x81\xec\x2e\x20\x17\x01\x72\x2a\x90\x7b\x12\xc8\x47\x80\xfc\x72\x20\xbf\x1f\x28\xcc\x03\x0a\x7b\x80\x4e\x3b\xd0\xd9\x07\x74\x3e\x0e\x9c\xdc\x0b\x9c\xfc\x38\x30\x75\x0d\x30\xf5\x20\x30\xad\x04\x4c\xdf\x00\xcc\xd8\x00\x74\x4d\x07\xba\xde\x00\xba\xd7\x00\xdd\xaf\x02\xc5\x79\x40\x71\x3f\x70\xca\x64\xe0\x94\x27\x81\x99\x4b\x81\x99\x1f\x00\xb3\x56\x01\xb3\xee\x05\x66\xf7\x02\xb3\xdf\x00\x4e\x7d\x12\x98\x73\x2f\x30\x77\x32\x30\xf7\x75\x60\xde\x41\x60\xfe\x76\x60\x41\x27\xd0\xf3\x28\xd0\xfb\x06\xb0\x70\x15\xb0\xa8\x1d\x58\xa4\x02\x8b\x0e\x00\xa7\xed\x03\x16\xf7\x01\x8b\xf7\x00\xa7\x67\x81\xd3\xfb\x81\x33\xec\xc0\x19\xeb\x80\x33\xdb\x81\x33\x77\x03\x4b\xfa\x80\x4f\x4c\x06\xce\x1a\x04\x96\xbe\x0e\x2c\xb3\x00\x67\x17\x81\xb3\xb7\x03\xcb\xa7\x03\xcb\x3f\x00\xce\xd9\x0d\xac\x68\x05\x56\xbc\x01\x9c\xdb\x0f\xf4\x6d\x00\x56\xb6\x03\x2b\xdf\x03\x56\xf1\xc0\xaa\x83\xc0\xea\xc5\xc0\xea\x97\x80\x0b\x7e\x08\x5c\xd8\x07\x5c\xb8\x07\xb8\xa8\x17\xb8\xa8\x04\x5c\x3c\x1b\x58\x6b\x07\xd6\x1e\x00\xd6\xa9\xc0\xfa\x22\x70\x49\x3b\x70\x69\x2f\xb0\x61\x2b\x70\xd9\x43\xc0\xe5\xaf\x03\x57\x6c\x06\x36\xba\x81\x8d\x7b\x80\x2b\x67\x03\x9f\xee\x03\xae\x01\x70\xcd\x7e\xe0\x5a\x37\x70\xed\x43\xc0\x75\xdb\x80\xeb\x77\x01\xea\x7e\xe0\x86\x7a\xe0\x86\xed\xc0\x8d\xf3\x80\xad\x3e\x60\xeb\x01\xe0\xb3\x7b\x80\xcf\xbe\x01\xdc\xb4\x0e\xf8\x5c\x11\xd8\xb6\x1b\xb8\xb9\x04\xdc\xea\x06\xb6\x3f\x07\x7c\x7e\x3b\x70\xdb\x3a\xe0\xf6\x79\xc0\x8e\x08\xb0\xa3\x04\xdc\xb1\x04\xd8\x69\x07\x76\xce\x03\x76\x6e\x05\x76\x96\x80\x9d\x43\xc0\x9d\x7d\xc0\x9d\xcf\x01\xbb\x78\x60\x57\x11\xd8\x35\x08\xdc\xa5\x02\x77\x27\x80\x2f\x2c\x07\x76\x2f\x05\xbe\x18\x06\xee\x99\x0d\xdc\xf3\x24\xf0\xa5\xdd\xc0\xbd\xfd\xc0\x97\x97\x00\xf7\x2d\x05\xee\xfb\x00\xf8\xca\xbd\x40\xff\x6c\xe0\xfe\xc5\xc0\x03\xed\xc0\x03\x0f\x01\x0f\x76\x02\x0f\xee\x01\x1e\x5a\x05\x3c\xbc\x1c\xd8\xb3\x03\xf8\x9a\x05\x78\x34\x0c\x3c\x7a\x10\xf8\xfa\x0e\xe0\xeb\x6f\x01\x8f\xa9\xc0\x37\xea\x81\x6f\xec\x03\xf6\xcd\x03\xf6\x0d\x00\xff\xba\x19\xf8\xd7\xe7\x81\x6f\x46\x80\x6f\x6e\x04\xbe\xf9\x1c\xf0\xad\xa5\xc0\xb7\xde\x03\x1e\xdf\x00\x3c\x01\xe0\x89\x55\xc0\xb7\xc3\xc0\xb7\x0f\x00\xff\xf6\x38\xf0\x6f\x83\xc0\x93\x9b\x81\xa7\x36\x02\x4f\x7d\x00\x7c\xe7\xf9\xd1\xe7\xbb\x7b\x80\xfd\x5b\x81\xa7\x8b\xc0\x33\x3c\xf0\xef\xcf\x01\xa5\x1f\x02\xdf\xb7\x03\xdf\xdf\x0e\xfc\x60\x39\xf0\xc3\x08\xf0\xc3\xfd\xc0\x8f\xdc\xc0\x8f\x9e\x04\x9e\xdd\x05\x3c\x37\x19\x78\x6e\x00\xf8\xc9\x2a\xe0\x27\xcf\x03\x3f\xdd\x03\xfc\x4c\x05\x7e\x36\x00\x3c\xff\x1e\xf0\xc2\x2e\xe0\xc5\xcd\xc0\x8b\x6f\x01\x3f\xdf\x07\xbc\xb4\x1d\xf8\x45\x3b\xf0\x8b\x6d\xc0\x2f\x2d\xc0\x2f\xb7\x01\x2f\xdb\x81\x97\xb7\x03\x2f\x1f\x04\x0e\x74\x02\xff\xd1\x0e\xfc\xc7\xbd\xc0\x2b\x7d\xc0\x2b\x6f\x01\xbf\x5a\x07\xbc\x3a\x0f\x78\xf5\x71\xe0\xd7\x7d\xc0\xaf\x7f\x08\xbc\xb6\x04\x78\xed\x49\xe0\x37\xf5\xc0\x6f\x76\x01\xaf\x17\x81\xd7\x9f\x03\x7e\xbb\x0e\xf8\xed\x20\xf0\xbb\xad\xc0\x7f\xd6\x03\xff\xf9\x28\x30\xb0\x1f\xf8\xfd\x3a\xe0\x0f\x1b\x80\x3f\x46\x80\x3f\xbe\x01\xbc\xa1\x02\x6f\x3e\x07\xfc\xa9\x04\xfc\xb9\x1e\xf8\xf3\x41\xe0\xad\x37\x80\xff\x7a\x15\xf8\xcb\xab\xc0\xdb\xaf\x02\x07\x0f\x00\xef\xbc\x04\xbc\xfb\x3a\xf0\xd7\x37\x80\xc3\x3c\xf0\xb7\xf7\x80\xf7\x54\xe0\xef\x59\xe0\x7d\x37\xf0\xfe\xbd\xc0\x7f\xd7\x03\x1f\x2c\x05\x3e\x28\x01\x1f\x26\x80\x23\xeb\x80\xa3\xfb\x81\xa1\x56\x60\xe8\x49\xa0\x6c\x07\xca\x7d\x40\xf9\x71\x40\xb3\x00\xda\x93\xc0\xb0\x05\x04\x1f\x48\x78\x1c\x24\xbe\x07\x92\x3e\x00\x59\x5e\x02\x59\x57\x81\x6c\x6e\x90\x6d\x37\xa8\xae\x1e\x64\xe7\x41\xf6\x87\x40\x8e\x76\x90\x13\x20\xd7\x36\x90\xa7\x1d\xe4\xe9\x07\x79\x9f\x07\xc9\x9d\x20\xf9\x0d\x90\x6f\x07\xc8\xdf\x0a\xf2\x3f\x04\x0a\x2c\x05\x05\x86\x40\xc1\x12\xa8\x7e\x2b\xa8\x61\x33\x28\x74\x0d\xa8\x71\x09\x28\x7c\x00\xd4\x54\x04\x35\x1d\x00\x35\xef\x00\xb5\xf0\xa0\x96\x6b\x40\x91\x87\x40\xd1\x12\x28\xb6\x19\x14\xb7\x80\xe2\xeb\x40\x09\x1e\x94\x78\x1e\x94\x5a\x03\x6a\x7d\x0b\x34\xb1\x17\xd4\xbe\x04\xd4\xd1\x0b\x9a\xb2\x11\x34\xe5\x3d\x50\x7a\x00\x94\x99\x0c\xca\xec\x03\x65\xf7\x80\x72\x1b\x41\xf9\x25\xa0\x42\x02\xd4\x69\x07\x9d\x3c\x0f\x34\xd5\x0d\x9a\x3a\x08\x9a\xb6\x03\x34\x7d\x2b\x68\xfa\xab\xa0\xee\xa5\xa0\x62\x18\x74\x4a\x09\x34\xf3\x39\xd0\xac\xe7\x40\xb3\xef\x05\x9d\x3a\x0f\x34\x67\x1e\x68\xee\x06\xd0\xbc\x79\xa0\xf9\x9b\x41\x0b\x22\xa0\x05\x6f\x80\x7a\x0e\x80\x7a\xfb\x41\x0b\xeb\x41\x8b\x8a\xa0\xc5\x45\xd0\xe9\xfd\xa0\x33\x06\x40\x67\xce\x06\x2d\x89\x80\x3e\xd1\x0b\xfa\x64\x1f\xe8\x93\x07\x40\x67\x2d\x05\x2d\xcd\x82\x96\xf6\x83\x96\xf1\xa0\x65\xdb\x40\x67\xaf\x02\x9d\x3d\x00\x5a\x7e\x0d\xe8\x9c\x57\x41\x2b\xfa\x41\x7d\xbb\x40\xe7\xcd\x03\x9d\xb7\x1f\xb4\x72\x10\x74\xfe\x52\xd0\xaa\x47\x41\xab\x37\x82\x2e\x58\x03\xba\xf0\x75\xd0\x9a\xc7\x41\x17\x2d\x07\x5d\xbc\x19\x74\xc9\x56\xd0\x86\x22\xe8\x8a\x01\xd0\x55\x6e\xd0\xa6\xe7\x40\x9b\x77\x80\xae\xde\x06\xda\xb2\x1d\xf4\xe9\x35\xa0\x6b\xb6\x83\xae\x0d\x83\xae\x7d\x08\x74\xfd\x72\xd0\xf5\xbb\x41\xd7\x7f\x00\x52\xd7\x81\x6e\xd8\x08\xfa\xcc\x0e\xd0\x8d\x59\xd0\x8d\x0f\x81\xb6\x3e\x07\xfa\xec\x3e\xd0\x4d\x0f\x81\xb6\x6d\x04\xdd\xbc\x1d\x74\x4b\x27\xe8\x56\xfd\xe9\x07\xdd\xd6\x0b\xba\x6d\x0f\xe8\xf6\x25\xa0\x1d\x6e\xd0\x1d\x3e\xd0\x9d\x3b\x40\xbb\x7c\xa0\xbb\x78\xd0\x5d\x43\xa0\xbb\x3f\x00\x7d\xa1\x1f\xf4\xc5\x6b\x40\xf7\x3c\x07\xba\xd7\x0d\xfa\xb2\x05\xf4\xe5\x57\x41\xf7\x5d\x03\xfa\x4a\x3d\xe8\x2b\x6f\x81\xfa\x7f\x08\x7a\xc0\x0e\x7a\x30\x0b\x7a\x68\x33\xe8\xe1\x7d\xa0\x47\x54\xd0\x57\x7b\x41\x7b\xc2\xa0\x3d\x3b\x40\x7b\x0e\x8e\x3e\x7b\x97\x82\xfe\xa5\x15\xf4\xb5\x08\xe8\x6b\xcf\x83\x1e\x7d\x14\xf4\xf5\x3d\xa0\xc7\x22\xa0\xc7\xb6\x81\xbe\xc1\x83\xbe\xb1\x07\xb4\xaf\x08\xda\xb7\x0d\xf4\xed\xfd\xa0\x7f\x5b\x07\x7a\x72\x00\xf4\xd4\x46\xd0\x77\x78\xd0\x77\x76\x81\xbe\x9b\x00\x7d\xf7\x21\xd0\x7e\x0b\x68\xff\x66\xd0\xd3\xbd\xa0\x67\xf4\xe7\x21\xd0\xbf\x47\x40\xa5\x79\xa0\xef\xd5\x83\xbe\xf7\x43\xd0\x0f\x78\xd0\x0f\xde\x00\xfd\xb0\x1f\xf4\xa3\x25\xa0\x67\x5b\x41\xcf\x1e\x04\x3d\x67\x07\xfd\xc4\x0e\xfa\xe9\x36\xd0\xcf\xfa\x41\xcf\x7f\x00\x7a\x31\x0c\xfa\xf9\x2e\xd0\x4b\xeb\x40\xbf\x58\x05\xfa\xe5\xeb\xa0\x97\x17\x83\x5e\xfe\x00\xf4\x1f\x5b\x41\xaf\x6c\x06\xfd\x6a\x03\xe8\x57\x43\xa0\x57\xdf\x03\xbd\xf6\x28\xe8\x37\x4b\x40\xaf\x2f\x01\xfd\xd6\x0e\xfa\xed\x20\xe8\x77\xdb\x40\xff\xd9\x0b\xfa\xbd\x0a\xfa\xc3\x07\xa0\x37\xea\x41\x6f\xda\x41\x7f\x9a\x0e\xfa\xf3\x3c\xd0\x9f\xf7\x80\xde\x4a\x80\xde\x3a\x00\xfa\xaf\x75\xa0\xbf\x84\x41\x7f\x39\x00\x7a\xfb\x0d\xd0\xc1\x2c\xe8\xe0\x93\xa0\x83\xef\x81\xde\x19\x04\xfd\xd5\x02\xfa\xeb\x43\xa0\x41\x1e\x34\xf8\x3c\xe8\x50\x04\x74\x78\x31\xe8\x6f\xeb\x40\x7f\x7b\x0b\xf4\x77\x3b\xe8\xfd\x76\xd0\xfb\x25\xd0\x7f\x6f\x06\xfd\xf7\x00\xe8\x83\x0d\xa0\x0f\xdb\x41\x47\x36\x83\x8e\x6e\x04\x0d\xd9\x41\x43\xab\x40\x65\x3b\xa8\xbc\x1d\xa4\x65\x41\xfa\x7c\x31\xfc\x12\x18\x65\xc1\x58\x18\x8c\x6b\x07\xe3\xd7\x80\x09\x07\xc0\xa4\xc5\x60\xd6\x2c\x98\xed\x00\x98\x7d\x00\xcc\x31\x08\xe6\xaa\x07\x73\x67\xc1\x3c\x6f\x80\xc9\xd3\xc1\x7c\xed\x60\xfe\x76\xb0\x40\x16\x2c\x38\x19\xac\xbe\x13\xac\x21\x01\x16\xda\x06\xd6\xd8\x09\xd6\xf4\x38\x58\xf3\x12\xb0\xe6\xe7\xc1\x22\xd7\x80\x45\xd7\x80\xc5\x1e\x05\x4b\xf4\x82\x25\x27\x83\x29\xf3\xc0\x52\xdb\xc0\x5a\xdf\x03\x9b\xb0\x1d\x6c\xe2\x64\xb0\x89\xaf\x83\xb5\xed\x02\x6b\x7f\x1d\xac\x23\x01\xd6\x71\x10\x6c\xf2\x41\xb0\x29\x5b\xc1\xd2\x45\xb0\xf4\x10\x58\xe6\x49\xb0\xec\x46\xb0\x5c\x02\x2c\xff\x1e\xd8\xc9\x11\xb0\xa9\xdb\xc1\xa6\x1e\x00\x9b\x66\x07\x9b\xb6\x0d\x6c\x7a\x2b\xd8\xf4\x57\xc1\x66\x64\xc1\xba\x9f\x04\x2b\xee\x06\x3b\x65\x00\x6c\x56\x3f\xd8\xec\x21\xb0\x39\xbb\xc1\xe6\xf5\x81\xcd\x7b\x0f\x6c\xfe\xf3\x60\xbd\xfb\xff\x77\x0f\x36\x00\x9c\x5b\xd4\x99\x7f\x09\x28\x44\x3d\x51\xce\x13\xf5\x0c\x50\x49\x2b\x6e\x60\xfd\x1b\x84\xc8\x91\x0d\x22\x8e\x18\x5c\x33\xe1\x9c\x61\x88\x0f\x0a\x2a\x9a\x74\x5e\x58\x22\x4f\x34\x1d\xf0\x89\xf1\x68\x4c\xc9\xe6\x33\x51\x0f\x29\xb9\x6c\x17\x65\xa2\xe9\x66\x12\x1f\x6c\x2b\x6f\xa3\x62\x48\x51\x42\x43\xaa\xfe\xa6\x62\x79\x5b\x5b\xa2\x35\x28\xa8\xc1\xd6\x84\x30\x27\xde\x56\xde\x56\x86\x92\x55\x94\xac\xc2\x81\x6d\x6e\x8b\x07\x1b\x2d\x96\x46\x43\x0a\x19\x86\xa8\xcb\xed\x6d\x00\x79\x7c\x4e\x16\xeb\x60\xd9\x2e\x96\x49\x07\x3d\xc2\x58\x6f\x36\x5f\xa0\x7c\x26\x1d\x10\x31\x7b\xcd\x85\xcb\x2e\x5c\x33\x7b\xf6\x9a\x0b\x4f\xba\xe8\xac\xf2\x58\xaf\xd2\xcc\x15\xed\xee\xd6\x4e\x21\x72\xb4\x3f\xbd\xa8\xcd\xef\x6f\x5b\xb4\x6a\x51\x9b\x3f\xc5\x1a\xde\x29\x4f\xab\x0d\xe0\x7e\xdc\x92\xb1\x11\xf8\x4e\x5d\x32\x1a\x86\xa8\x0a\x2a\x24\x44\x01\xb8\x11\xd1\x1f\xf2\x89\xf1\x58\x8a\xc4\x78\x2c\xa1\x30\xb7\x37\x9f\x88\xf0\x01\xaf\xdf\x27\x51\x80\x57\xb5\x0f\xb5\xdb\xb4\x0f\x49\xa2\xcb\x39\xa9\x37\x9b\x4f\x68\x7b\xbf\xf5\xfa\xed\xda\xd1\xa7\x2f\xbd\xf4\x69\x12\xa8\x99\x84\xa7\x2f\xbd\x86\xce\x4a\x32\x89\x2e\x27\xc9\x4c\xac\xa9\xd9\x5e\x85\x3e\x79\xcd\x68\x8a\x4b\x9f\xd6\x8e\xde\xfe\xfa\xb7\xb4\xbd\x49\x43\x14\x1b\x56\x25\x08\x40\x08\x33\xb0\x10\x48\x7a\x44\x89\x97\x9c\xac\x8d\xc5\x3a\x28\xa5\x24\x95\x94\xc7\x17\xc8\x44\xd3\x79\xcf\x74\xd6\xc1\xc5\xa3\x31\xd1\xef\x0b\x06\x82\xcd\xfc\x34\x96\xee\xe2\x0a\xf9\x42\x17\x15\x3c\x66\xe7\xe4\x3c\x7a\xf7\xa4\x03\xa2\x1a\x49\x6a\xef\xdd\x97\x29\xae\x9f\x4c\x34\x79\x7d\x31\x73\x9f\xf6\x5e\x32\x22\x3b\x84\x92\x43\x26\x41\xb4\x5b\x8e\x14\x1d\xf2\x9d\xdf\x7b\x49\x9c\x1a\x2b\x74\xf8\x88\x7c\x1d\x85\xd8\x54\xf1\xa5\xef\xe5\xcf\x51\x57\xcc\x3c\x52\x9c\xb9\x62\xc5\x4c\xa1\x34\x73\x45\x84\x43\xa2\xf9\xc5\xad\x6d\x93\xa7\x4c\x99\xdc\xb6\xf5\xc5\xe6\x44\x19\x0e\x59\xe6\x5b\x99\xd7\xea\xb1\xd8\x04\xd9\xb1\x67\xe3\xee\x87\x85\x29\xa1\xa4\xd7\x9b\x0c\x4d\x11\x1e\xde\xdd\x76\x47\xdf\xd1\x92\x9e\x9b\xd7\xcb\x30\xfb\x58\x6f\x9b\x8a\x30\xc0\xc7\x52\xd4\xc1\xe7\xb2\xf9\x4c\xba\x99\x05\xbb\xb8\x4c\x3a\xa0\xe3\x94\xbb\x27\xeb\x2d\xef\xb0\xc5\x7b\xa7\x4f\xd2\x06\xba\x6e\xb8\x74\x71\x22\xb1\xf8\xd2\x1b\xba\x06\xb4\x37\xcb\x77\xa8\x5e\xb6\xcc\x92\x38\x77\xd5\x6d\xb3\x5e\xff\xa0\x6d\x7e\x31\x91\x28\xce\x6f\xfb\xe0\xf5\xdf\xbe\x59\xde\x63\x96\xfd\x75\x51\x15\x06\x10\x33\x69\x54\x0e\xf8\x8d\x7e\x4b\x0a\x62\x3c\xa6\xe4\xb2\x05\x59\x27\xd3\x42\x52\xce\xa7\x83\xb2\x10\x10\xd5\x90\x76\xd7\x27\xc9\xef\x93\xfd\x5a\xb7\xd6\x1d\xf0\xfa\xfd\xec\x93\xda\xae\x86\x4e\x7a\xff\xf7\xf2\x74\xf9\xf7\xf4\x7e\x27\x77\x75\x20\xa4\xdd\xa7\xd9\x25\x87\xbf\xc9\x7e\xf0\xa0\xbd\xc9\x2f\x3a\xe9\x3d\x5a\xd9\xe8\x4f\x5a\xe7\xd3\x8f\x27\x4c\xd0\x4e\x9e\x6f\x85\x29\x51\x57\xea\xb6\xea\xd4\x6b\xa5\x64\x1d\x09\xc4\x25\x85\x2a\x1c\x27\x06\x83\xbf\x8c\xd2\xda\xb2\xa7\x9f\xd6\x96\x51\x7a\x3e\x6d\xa1\xab\xe9\xc7\x06\x5c\x13\x4e\x0c\x16\xf3\xd1\x84\x2e\xba\x4e\xfb\x4c\x97\xf6\x2b\xed\xec\x1f\xff\x98\xb3\x55\xc1\x4c\x7f\x04\x94\x3a\x8c\xaa\xa0\xe3\xde\xaf\x8f\xe2\x64\x85\x42\xb2\x5d\x5c\x26\x10\x29\xa4\x9b\x39\xb8\xc5\x88\xe2\xce\x47\x04\x5c\xbb\x74\xe8\x5f\x96\x5e\xeb\xe9\x98\x7b\x65\xef\x8d\xb4\xee\xc6\xde\x2b\xe7\x76\x78\x86\xf1\x7b\xed\xfb\xbf\xff\x3d\x75\xdd\xbc\xfe\xde\x7b\xd7\x7f\xe2\x0b\x5f\x5c\x7f\xaa\xaa\x9e\xba\xfe\x8b\x5f\xe0\xbe\x67\x86\xff\x1e\x40\x9d\x3e\x7e\x24\x7d\xfc\xb8\xd0\x82\x49\xe8\xc6\x69\x38\x17\x97\xe2\x7a\xdc\x8e\xaf\xe0\x1b\x80\x90\xcb\x2a\x6d\x14\x13\x9b\xc8\x17\x98\x46\xe9\xbc\xe7\x63\xfc\xe4\xc9\x2a\x06\x85\x57\x48\x9e\xc6\xc7\xff\x93\xe9\x3f\xae\xbe\xf1\x03\x87\x54\x25\x64\xcc\x62\x27\x78\xf1\x50\x42\x65\xe8\x1e\x0e\x21\x65\x08\xa3\x31\x42\x4d\x4e\x4d\xad\x4d\xf5\x71\x65\xaa\x2b\x66\x7e\x68\x0c\x1a\xb1\x38\x73\x45\x71\x24\x8a\xee\x39\x9e\xb3\x1c\x62\x46\xc1\x9a\xfe\xe6\x47\xc3\x8f\x8e\x3a\xb9\xda\x24\xda\x71\x4b\xa9\x71\x7e\xe7\x88\x51\xb7\x60\x0c\x58\xde\xd0\xc9\xd4\xf6\xa7\x3e\x33\x8f\xc1\x50\x03\x8d\xc3\xd8\xc7\xc4\x73\xe8\xcd\x6a\xc8\xf6\xf6\x66\x99\xf1\x1e\x75\x73\xea\x89\x62\x18\xf4\x29\xb3\x37\x4b\xfa\x9b\x3d\x5f\xe3\x19\x7a\xfe\x44\x31\x86\x02\x17\xc6\x5c\x73\x2c\x2d\x82\xfc\x26\x54\x33\xc8\x84\xca\x33\xce\x3f\x3e\xfe\xff\xb4\x7f\x7c\x7d\x0c\x9d\xad\x5a\xa9\xb5\xb3\xb3\x95\x8a\xfa\x7b\xd4\xcd\xd4\x5a\x5f\x59\x3d\x71\xdc\x3f\x9e\xb2\xd6\x4d\x11\xc3\xa9\xbf\xe8\xd5\x11\x67\x79\xd4\xc9\x1d\x37\xf4\x63\x13\xd4\x14\x66\x2a\xac\x8f\xed\x8b\xff\xe3\xbd\xf0\x8f\x63\x55\x40\x67\xeb\x90\x11\xc6\x95\x5a\x3b\x8f\xe2\xc4\x71\xb5\xee\xff\x21\xae\xc6\xa0\x02\x84\xab\xe1\x14\x3f\xc7\x7f\x13\x01\x00\x3e\x89\x24\x31\x36\x89\x48\xc9\x76\x53\x3e\x1d\xb4\x52\x3e\xdd\x42\xe2\xe7\xc2\xe5\xf6\x6d\xe1\xc5\xe1\x6d\xda\xdd\xe1\xb0\xee\x20\x85\xed\xd0\xfd\xdc\xe1\xc5\x46\x54\x78\x1b\x5d\xac\xfb\xc3\x61\xed\xd7\xec\x8e\x70\x78\x1b\x08\x97\x0c\xbf\x2b\x78\xf9\x9d\x88\x03\x09\x9f\x8b\xc4\x58\xca\x4a\x7a\xd9\x4a\xb6\x60\x1d\x5b\x7e\xc0\x27\x59\x49\xf0\x1a\x25\x6b\xaf\x69\xaf\x99\x25\x91\xa2\xbd\x56\xad\x8d\x94\x4a\xe9\xaf\x91\xa2\x7d\x64\x6c\x78\xa4\x14\x93\x77\x31\xe7\x8b\x38\xda\x30\xdb\xec\xe1\x36\xf3\xa5\x77\x4b\xdc\xec\x9b\x69\x94\xd3\x5f\xe9\x40\x13\x65\xd2\xcd\x54\xe1\xb2\x70\x22\x2e\x8b\x87\xec\x18\x90\x1d\x45\x87\x3c\xe0\x90\x6b\x9c\x63\x78\xaf\x9e\xdc\x89\x78\x2f\x36\x70\x4c\x4e\xdd\xf9\xa7\x1a\x86\xec\x89\x8b\x7b\x4e\xc0\x90\xd5\xb6\xc9\x85\x20\x26\x1f\x43\xb5\xff\x18\xfc\xe5\x92\x5e\x2b\x2b\xfe\x73\x50\x1b\xf0\xfe\xc3\x90\x56\xd6\x78\x51\x1f\x6e\x13\x90\xd3\xb9\x20\x26\xf2\x91\x84\xc2\x72\x59\x6f\x21\x1f\x08\x06\x44\xc9\x49\x7e\x5f\x33\x4b\x77\xb1\x5c\x56\x49\x75\x50\xa1\x8b\x82\x01\xaf\x3e\x67\x9b\x33\xb4\xce\x53\x6f\x79\x51\x7b\x43\x7b\x4e\x7b\xe3\xc5\x2d\xf7\xef\x6c\xbb\xa8\x25\xe2\x9a\xb8\x72\xed\xe9\xb7\x3c\xfd\xd2\xd3\xb7\x9c\xbe\x76\xe5\x44\x57\xa4\xe5\xe2\x89\x3b\xef\x2f\xab\xbd\x6b\x7a\x7b\xd7\xf4\x32\xf5\x5e\x3d\xe5\x96\x17\x29\x7c\xef\xb7\x69\xe6\xfa\x88\xb3\x6d\xe2\x45\x91\x05\xaf\x5c\xbd\xe6\xe9\x5b\x4e\x3f\xfd\x96\xa7\xd7\x5c\xfd\xca\x82\xc8\x45\x13\xdb\x9c\x91\xf5\xda\x33\x6c\x41\xd9\x98\xa0\x99\x31\x41\x9b\x1b\x64\x15\x7e\x70\x74\x5e\x40\x72\x84\x5c\x4c\x22\x49\x7a\x4c\xbf\x0e\xdf\xf1\xfc\xf4\x71\x7e\x78\x9d\x25\xa7\xd7\x78\x91\xfa\xcf\xb9\xfb\xaa\x0e\xef\xe5\x9a\xe1\xa4\xa2\xd3\xeb\x3d\x5c\x36\xdc\x4c\x77\xd3\xe5\x43\xfa\xc7\xc9\xe9\x41\x74\xf8\x88\xe1\x11\x74\xcf\x68\x7f\x18\xf2\xc4\x25\x00\xb2\x4a\x4c\xf4\x05\xd2\x3a\x05\xb9\x48\x94\x02\xc1\x80\x4f\x72\x52\x3c\x36\x89\x44\x49\x94\x0c\xa8\x27\x91\x92\x92\x74\x42\x52\x52\x3a\x9b\xd8\x45\x05\x65\x12\x75\x90\x8e\x8c\x6e\xca\x17\xaa\xa1\x99\x74\x0b\xe5\x0b\xf9\x82\xd1\xc2\x16\x0a\x04\x0b\xf9\x4c\x3a\x18\x08\xea\x2c\xb4\x93\xa4\x40\x0b\x35\x13\x8f\xbb\x0f\xdc\x7d\xf7\x01\x76\xb7\xdb\xfe\x94\xec\x8b\xcf\xb3\x59\x1b\x77\x04\xec\xce\x5b\xda\x27\xb9\x1d\x52\xd3\xef\x9c\x7e\x0a\x4f\x99\xf0\x79\x9b\xcb\x59\x77\x5d\x4a\xb2\xb8\xe6\x79\x1b\x9d\xff\xe6\x70\xbb\xeb\xbe\xe3\x6c\x68\x9d\x65\xb3\x86\xee\x08\x38\x1c\x63\x13\xdf\x66\x75\x39\xec\x37\x24\x8c\xc4\x21\xd7\xbf\x39\xdc\x2c\xa0\xd7\x70\x37\xad\xff\x9d\x3d\xc0\xc2\xf9\x64\x7a\xa9\x3d\x64\x4b\xde\x66\x5d\x17\x74\x6d\x4b\x87\x3d\x8e\x27\xdd\xfe\xb5\xd6\xba\xcb\xf3\x36\x87\xbd\xce\x7f\x76\x43\x7a\x4a\x23\xf3\x3b\x8c\xb4\x1d\x1d\x27\x9f\x6e\xb7\xdb\x1c\x89\xdb\x6d\x6b\x6b\x13\xdb\x36\x65\x2c\x4e\x33\xf1\xe4\x30\xf3\x1b\x6b\xc7\xb0\x2a\x8c\xf2\x20\xd3\x30\x0b\x17\x9a\x7c\x48\x6d\x2f\x0b\x1f\xe3\x97\x3d\x51\x8f\xaf\x59\x97\x51\xbb\x88\xa2\x29\x25\x15\x15\x25\xc1\xa0\xb4\x11\x86\x25\x5e\x1d\xd3\x05\x43\x96\x0d\xb4\x90\xb1\x86\x78\x9d\x46\x9f\x16\x9d\x5e\x3a\x81\x5b\x1d\x52\x9d\x2e\x8e\x2b\x72\x2e\x67\xb9\x8f\x4a\x93\x25\x9b\xf6\x03\x9b\xc4\x5d\xea\x75\xf6\xad\x98\x39\x54\x9a\xb9\xa2\xcf\x20\x9d\xdc\x1c\xd7\x22\x7d\x85\x59\xe4\x9a\x43\x39\xa7\x97\x8b\xd4\x90\x91\xf3\x04\xee\x72\x33\xf7\xf8\x50\x6f\x20\xe9\xf1\x24\xf9\x05\x57\x5a\x19\xb3\xde\x55\x74\x7a\x87\x7a\xcf\xbc\xfa\xca\x33\xb9\x27\x8d\xda\xbf\x9a\xcc\x66\x93\x5f\xf5\x9a\xe3\x3f\x04\x88\x17\x08\x1c\x64\x63\xfc\x1b\x4d\xf3\x44\x3d\x15\xfe\x2b\x67\xa5\x40\x41\x12\xa5\xb8\xb1\x32\xa4\x74\x5a\xd3\x25\xe9\x74\x4b\x75\x3e\xf6\x7b\x82\xcd\xa4\x73\xae\x9a\x3a\x0c\x4d\x0d\x29\xc4\xba\x59\x37\xfd\x67\x97\xc5\xc1\x39\x2c\xe5\xde\x72\xaf\xdd\xee\xb0\x74\x59\x98\x8d\xfd\x3c\xb2\x34\xf2\x9e\x31\x34\x7e\x63\x63\x2c\xa2\x45\x74\xc6\x56\x67\x74\x69\x80\x78\xa2\xd7\x34\x85\x9d\xb2\xc0\xca\x24\x76\x4a\xf9\xdf\x2d\xc4\xac\x0b\x6c\x8d\x16\x76\x56\x28\xf4\xfc\x0f\xf4\xb6\x69\x6b\xbe\xad\xcb\xfc\xe6\xdc\xaa\x77\xb1\x8c\x90\xbe\x6e\x51\x33\xf9\xc7\x31\x90\x41\xc9\x13\x55\x52\xa4\x90\xd9\x8a\xa8\x47\xd8\x1f\x6e\xed\x6c\x3d\x62\xac\xa9\x9c\xda\xda\x17\xde\x4a\x9b\x6d\x76\xed\xc7\x76\x3a\x5f\xeb\x6b\xed\x2c\x83\xdf\x1a\xee\x6b\x3d\xaa\xea\xf1\x62\xb1\xb5\xb3\x35\x3c\x5b\xdb\xd6\x64\xa7\x93\xed\x47\xbc\x3c\x3a\x5b\xa9\xdf\x50\x6a\x70\x23\x63\xd3\x87\x08\xda\x47\x39\x5b\x73\xde\xa9\x90\x0d\xdc\x1d\x14\x71\x92\xbb\x99\x22\x79\xb8\x19\x1f\x49\x30\xb7\x37\x11\xe1\x39\xd5\xeb\x34\x67\x84\x01\x93\x1c\xfa\x77\x1e\xd1\x5e\x3d\xb2\x73\xe7\x11\x6a\x3d\x42\x97\xbf\xa8\x7d\x45\x5b\xa1\x7d\xe5\xc5\x17\xe9\x3c\x7a\x80\xce\xe3\x06\xb4\x11\xba\xd1\x69\xa1\xac\x51\xab\x9e\xd6\xc8\xc1\xce\xad\x4d\xfa\xe2\x8b\x46\x3f\xa6\x01\x69\x91\x00\x78\x30\x0b\xa0\x1c\xd7\x41\xba\x98\x22\x71\x7e\xd1\x94\x73\x7c\xf1\x68\x3a\x9f\xe2\x3a\x48\x97\x76\x24\x4e\x0c\x64\xa2\xb1\x5c\xb6\x40\x3a\xe5\xc6\xf4\xc9\xc5\x48\xa6\xcf\x1c\x71\x1d\x87\x14\xe0\xcf\xaa\x27\x9f\xe3\x3b\x0e\x1f\xd5\x93\xd7\xfe\x9e\xdd\xcb\xde\xef\x28\x17\x1d\x5e\xf2\x91\xcf\xa1\x0d\x3a\x7c\xe4\x23\xaf\xa3\x5c\xec\x08\xd1\xfd\x96\x84\x8f\xce\x74\xf8\xc8\x45\x5e\xc7\x23\x0e\x2f\xb9\xc8\xe7\xa0\x33\x7d\x09\x0b\xdd\x1f\x62\x61\x9e\x8c\x95\x49\x2b\xf1\x76\xb7\x5b\x3b\x79\xbe\xec\x20\xe8\x01\xc3\x70\xc8\xf3\xf3\x5d\xbc\x4f\x0e\xcb\x0e\x73\xde\x74\xc8\x61\xf9\xe8\xc1\xae\xaa\x1c\x21\xea\x4c\xa0\x0b\x49\xcc\x00\x12\x95\xb9\xb0\xfa\x95\xc7\x74\x7b\x30\x90\xee\xd6\x47\x1f\x05\x24\x9d\x8f\x21\xa5\x90\xcf\x44\x2b\x04\xe1\xf7\x44\xd3\x82\xa9\x41\x22\xc5\xf8\x3c\xd2\xd9\x7a\xc4\x60\xd2\xe8\x17\x9f\x9b\x7a\xef\xd4\x6d\xf4\x52\x6b\xa7\xf6\x5d\x4f\x8b\x56\xf4\xe6\xbd\x5a\xb1\xc5\xe3\x99\x48\x50\x42\xa4\x0b\x5f\x98\xf8\x48\xd6\xcc\xa5\xff\x51\x64\x94\xef\xdb\xd6\xd9\xb9\xad\x93\x79\x26\x34\x69\x45\x59\xa6\x52\xd3\x84\x14\x95\x0c\xb9\xa9\x58\x43\x2b\xf5\x48\x18\x3c\x80\x6f\x04\xae\x11\x52\xf1\x7b\x32\xe9\x00\xab\x10\x4b\x17\xb9\x15\xbe\x86\x5e\xf8\x3e\x9b\xf6\xbd\xba\xfa\x3a\xad\xe4\xb2\x58\x02\x25\x63\xe0\x94\x9c\xde\xe7\x47\x68\x66\xe7\xce\x63\xa8\x86\xf5\xd9\xed\xda\xf7\xac\x56\x2a\xba\x65\x9f\x41\x37\x4e\xad\xdf\xcb\xd2\x35\x94\xf6\xf4\x31\xa4\x73\x1c\x58\xcd\x39\xce\x9c\x0c\x4d\x15\x84\xce\x09\xd2\x89\x61\x5d\x51\x03\xa1\x8d\xba\xeb\xea\xeb\xa8\xe8\xfa\xe5\x47\x82\xba\xcb\xa7\xf5\x1b\x93\x5c\x9f\xd7\x69\xb7\x53\xb7\xd5\xaa\x95\xdc\xf4\xe1\x47\x80\x6a\x58\x21\x88\x3a\x0b\xe0\x30\x46\x7e\xb4\x83\x52\x5c\x94\x73\x92\x14\x0d\x46\x93\xa3\xd4\x50\x90\xcd\xd9\x38\x28\x07\xb8\x61\x9a\x4e\x1c\x1d\x28\x4f\x3f\x40\x1c\xd1\xf4\x73\xa9\xc8\xfa\x94\xd0\x11\x35\xa4\x34\xbc\x6b\xcb\x85\xb8\x62\x28\x67\x7b\xb7\x81\x15\xb9\x3a\x46\x83\x9a\x9b\xab\x63\xa5\x07\xb4\x66\x43\x0b\xf9\x87\xae\x19\xac\xb5\x21\x16\x6b\x28\xbf\x3a\xa3\x06\x47\x2e\x34\x1a\x56\xe7\x7a\x7f\xea\x8b\xae\x5e\x61\x3e\x48\x81\x13\x0c\x7b\xbe\x3f\x52\x1e\x70\x79\xdc\xee\x48\x24\xda\xc2\x22\x1f\x39\xe8\xd9\xc3\x0b\xbc\x5a\xc9\x6a\x91\x93\x4c\x4d\xca\x5e\x59\x2b\xfd\xec\xa3\x46\x3d\x8d\xc0\x94\x19\x99\x8b\x52\x4a\x37\x29\xf1\x98\x93\xf9\x9a\x59\x26\xad\xaf\xf7\x69\x7d\x61\x97\x44\x7e\x84\xc9\xcc\xa4\xf9\x60\x21\x1f\x0c\x88\xd0\x29\x75\xa2\xc7\xd3\x72\xcb\xae\x9f\x54\x99\xaf\x4d\x07\xe6\x4b\x6e\x97\xed\x66\x2b\x59\xd6\x6b\x3f\x7d\x74\x94\x55\xbb\x93\xe4\xb5\x9f\x69\x9a\x90\x12\xa0\x15\x43\x4a\x6b\xaa\xf9\x96\x9b\x2b\x2c\xde\x9a\x73\x6d\xcc\x7a\x8b\xa5\xc1\xb6\xf5\x0e\x3d\x25\x75\x52\xf8\xc5\x2d\x97\xae\xbe\xa1\xc5\xe3\xa9\xe5\x67\x12\x98\x6b\x8c\x02\x86\x68\x2c\x91\x92\xc4\xd1\xf9\xda\xe7\xa2\x66\x32\x81\xad\x2c\xbc\x15\x45\xb1\xd1\x94\x11\x3e\x67\x06\x79\x11\x35\x60\x4f\x07\x84\x3f\x53\x51\x5b\xa3\xbd\xbb\x53\xfb\xeb\xda\x1b\xe4\xac\xde\x5d\xa5\x90\x22\xdf\x3c\xf7\xf1\xf3\x6e\x7a\x6b\x4e\xdd\x44\x4b\xa0\xe4\x90\x1b\xf4\xf6\x85\x14\xf9\x96\x5d\x3f\xa9\x04\xfe\xd8\x21\x9f\x42\xf7\x90\xbc\x93\x7c\x6b\x3f\x23\x67\x15\x1a\x10\x98\xf6\x9e\xf6\xad\x4b\x2e\xb8\x41\x36\x8b\x50\xb2\xf2\xcd\x33\xe7\x7d\xe6\x72\xcf\xaa\xa0\xcc\xc9\x7a\x76\x25\x2b\xdf\x72\xb3\x19\xe0\x90\xc8\x4e\x0b\x2f\x5d\x7d\x83\xac\xa0\x62\x6c\x75\x7c\x7d\x01\x68\x1c\x47\x9a\xfb\x18\xff\x78\xb9\x34\xf7\x31\x7e\x79\x9c\xd6\x4a\x3e\x46\x0b\x65\x0a\x02\x27\x7a\xf1\xaa\xec\x18\x32\x3c\x9c\x21\x66\x1c\xdf\xad\xca\x8e\x23\x86\x47\xd0\x3d\xb5\x7a\x5d\xea\x1b\x29\xee\x6f\xc7\x71\x95\x8f\x17\x58\x13\x9d\xe1\x0c\xf7\x90\x5e\x1f\xbf\xb0\x56\xe1\x6b\x8c\x71\xde\xd4\xa7\xb7\xe8\x63\x3c\xa7\xcf\xf6\xfe\x5a\x1d\x91\x2e\x0b\x22\x02\x5d\x12\x0c\x50\x91\xe9\x2c\x2b\x57\xac\x0a\xdd\x11\xb2\xd0\x06\xb2\x44\x5a\x3b\x39\x94\x2e\xbe\xfb\xee\x8b\xb5\x81\xb2\x31\x5f\xb3\x62\x6b\x67\xe9\x49\xb2\x68\x1f\x3c\x59\xea\xd4\xe9\xb2\x58\x91\x23\x3c\x28\x18\x74\x39\x32\xe1\x29\x39\x5d\xaa\xd1\xb9\x41\x9d\xab\xee\x60\xf1\x98\xa9\x87\xd5\xc7\xb9\xce\x33\x07\x82\x81\x4c\xba\x8b\x19\xb5\x17\x8d\x06\x15\x7b\x2e\xee\x11\x4a\x0d\x8d\xbf\xba\x67\xc6\xb5\xcb\x6f\x9d\x5f\xd2\x06\x3d\xee\x90\xd2\xe2\x9f\x7a\xf0\xa9\xb5\xdf\xb9\x4e\x49\xe7\xaf\x3f\xe7\x4c\x47\x48\x11\x30\x4f\x39\xea\xd4\x1b\xce\x1f\x56\xe6\xe5\x7a\x7a\xae\x2c\x0b\x0d\x8d\xce\x8d\xed\xd9\xf6\x9d\x56\x25\xc4\xfe\x14\x09\x3a\x9b\x36\x4f\x9d\x26\x4f\xcc\x4e\x54\xaa\x67\x4e\x0c\x39\xb2\x47\x87\xd0\xc5\x9c\x14\xf7\x8f\xe5\x51\x9b\x28\xad\x33\xf2\xb9\x2c\x4b\x44\x78\xe6\xf7\xb5\xe8\xcb\xf9\x08\x6b\x56\xa5\xb1\x98\x32\x89\x29\xb9\x6c\x45\xc0\x14\xd5\xe9\xbe\xa7\x02\x37\x2f\x1d\xe5\x46\xe7\x5e\x15\x9b\xdd\xb4\x4f\xfb\x95\xf6\x4d\xed\x57\xfb\x9a\x66\xc7\xae\x9a\x3b\x1a\xb7\xf4\xe6\xc0\x53\xbe\xe9\x37\x0d\x50\x96\x7a\x29\x3b\x70\x13\xbb\xe5\x91\x5d\x53\xa2\x67\xae\x8d\x8c\x32\x9f\x91\xb9\xd3\xed\xe7\xae\xdc\x45\xe2\xbd\xf7\x6a\x47\x76\xad\x3c\xd7\x3e\x7d\x6e\x64\x94\x29\x8d\xac\x3d\x33\x3a\x65\xd7\x23\x5f\xa0\xfa\x17\xb6\x6c\x79\x41\x7b\xcb\x6c\x57\x84\x03\x3f\x00\xd9\x9c\xb7\x62\x29\x1a\xa1\x5d\xca\xa7\x03\x1c\x94\xac\xac\x7d\x4b\x3b\x62\xcc\xc3\x22\x2d\x94\xb3\x0a\xdf\x7f\x54\x1f\xe1\xb4\x50\x09\x91\xce\x66\x2e\x34\xc7\xa0\x4e\x2f\x11\x5e\x35\xca\x3a\xe9\xf8\xa5\xc1\xec\x48\x43\x71\x9d\xed\xe0\x8c\xed\x83\xe0\x71\xeb\x20\xf5\x13\x73\x6c\xae\x90\x52\x1f\x8b\xd5\xeb\x8f\x12\x72\xd9\xe6\x1c\xa7\x62\xcd\xbb\xfb\xc6\xb0\x90\x6c\xf4\x37\xf9\x1b\x26\xcd\x9c\xd4\xe0\x6f\xf2\x37\x26\x85\x46\x98\x86\x99\xc3\x4f\x89\xaa\x30\xd7\x80\x67\x3e\xd6\xfe\x33\x30\xf1\x6e\x56\x09\x35\xf6\x64\xb2\x8a\x29\xd2\x8d\x8f\xeb\x22\x9d\x10\xbd\x6e\x96\xd2\x05\xf2\x91\x14\xff\x70\x8b\xe8\x13\xff\xb2\xdd\x61\x6f\x54\x52\x9d\xbe\x05\x67\x9e\xb9\xc0\xd7\x99\x52\x42\x0e\xc7\x76\xfa\x17\xed\x65\x87\x23\xa4\xa4\xa4\x16\xa9\x23\xf1\xe9\x5b\x6e\xf9\x74\xa2\x43\x6a\x91\x8c\xc8\x97\xff\x71\x2c\x14\xb4\x17\xb5\xf2\x34\x41\x09\xa5\x7c\x4d\xae\xfc\x83\x4f\x3e\x98\x77\x35\xf9\x52\x21\x45\x98\xf6\x6d\x2d\xab\x5d\x7f\xb6\xa0\x84\x12\x41\xde\xc1\x37\x84\xce\x26\x37\xa5\xc9\x7d\x76\xa8\x81\x77\xf0\xc1\x44\x48\x11\xce\x86\xdd\x10\xf2\x75\x9a\xe7\x20\xa1\x0e\x2e\xc8\x08\xa2\x11\x2d\x88\x63\x12\x32\xc6\x58\xf5\xc7\x73\xb2\x3f\x9e\x8b\xfa\xe3\x39\x32\x64\x15\x4f\x54\xff\x92\x27\xea\xa1\x4a\xb8\xec\x89\xe6\xe2\x9e\xb8\x27\xea\xcf\xe4\xc8\x4c\xe2\x21\x55\x55\x55\x4e\x55\x87\x54\x5d\xec\xd0\x1f\x0e\xfa\x7b\x18\x65\x95\x57\x55\x3d\x5a\x53\x8d\x6f\x59\x2d\xab\x82\x5a\x36\x82\x38\xe8\xd9\x86\x88\xae\xa7\x4a\x3e\x3d\x96\xa9\x9a\x11\xce\xa0\xe9\xb9\x98\x91\x50\x0f\xd6\x1f\x18\xfb\x80\xd5\xb5\xe1\xd8\x76\xa4\xd0\x56\x69\xcb\x34\x74\x03\x99\xb8\x27\x23\xff\x2f\x9e\xee\xee\xee\xee\x48\x64\x45\x4b\xcb\x97\x5b\x5a\xbe\xdc\xd5\x75\x5d\x4b\x4b\xb7\xf1\xf7\xe5\xee\xee\x2f\x77\x77\x5f\x67\xfc\xad\xe8\xee\x7e\x7a\xc5\x0a\x3d\x59\x77\xb7\xa0\x1e\xb9\x41\xb8\xfe\x7f\xf4\xe8\xfd\x62\xae\xe9\x77\x09\x6f\x1b\x73\x74\x53\x8d\x8e\xa2\xc2\x11\x51\x07\x8d\x48\x62\x14\xa0\x52\xcf\xc5\x3d\x3d\x17\xf3\x57\x25\x35\x7f\x2a\x9b\x4b\x96\x73\x4a\xae\x37\x4b\xfd\x39\x55\x61\x3f\x4b\xf2\x75\x7a\x64\x8f\x56\xcc\x25\x35\x5f\x32\xc9\x9e\x4f\xaa\x39\xea\xcf\xf6\xe6\x94\x72\x3e\x55\xe5\x4d\xef\x92\xd6\x56\xea\xca\x7d\x5c\x6d\x82\x19\xaa\xa4\x28\x9f\xcb\xea\x71\xf1\xcc\x3f\x00\x05\xa9\x46\x70\xa2\xa3\x99\x5e\x49\xea\x71\x6a\x6e\xe0\x1f\x80\x2f\x6b\x04\x86\x5b\xe8\x95\x64\x2e\x9b\x62\x3f\x55\x72\x26\xd8\x1c\x6c\xc3\xaa\x78\xb5\xa0\x62\x09\x56\x61\x23\xa0\xcb\x24\x4e\x5d\xee\x52\x52\x4a\x21\x9b\x2f\xe4\x95\x42\x17\x33\x86\xb1\xa2\xbf\xc7\x3b\x58\xa1\x4b\x0c\x4a\x46\x93\x2a\xf9\x24\x31\x68\x2c\xf3\x05\xca\xa7\x02\x82\x68\xb8\xbb\x29\xaf\x8c\x8a\x72\x35\x7e\xf1\xc2\xd6\x80\xf6\x8e\x7c\xc5\x29\x43\xab\x17\xde\x1e\xae\x0f\x88\x44\x16\x62\x76\xbf\x18\x6c\xb7\x70\x02\xe3\xc2\x9c\x7f\x22\x4f\x12\xcf\x27\x78\x79\x12\x4f\x16\xc6\x9c\x01\xd1\xe2\x71\xc8\xbe\x68\x2a\x4c\x8a\x83\x7d\xb8\x60\x71\x40\x7b\x37\x31\xf7\x9c\xa1\x2f\x35\xd6\xd5\xd9\xea\x37\x73\x5f\x6a\xca\x5b\xa8\x5d\x62\xca\xd1\x77\x78\xbb\x93\xf5\x39\x1a\x78\x3f\x6f\x77\x96\xfb\x1d\x0d\xfc\x9a\x63\x42\xf8\xd8\xc9\xf3\x86\xae\x2a\x9e\xb5\x76\xd1\xac\xe9\x7c\x87\xd3\xd2\x28\xd6\xf9\x1a\x6d\xca\x5a\xc5\xd6\x6a\xa9\x8b\x89\x89\x0d\x31\x6b\x87\xe0\x88\x0b\xa1\x2b\x15\x4b\xdc\x6a\xf1\x85\x2c\xf6\x64\x34\xd5\x10\x20\x91\xb3\x6e\x58\x30\x74\xd5\xa6\x53\x5d\xee\xc6\x39\x2d\x21\xee\x37\x81\xb8\xab\x79\x84\x6d\xd1\x4a\x23\x4e\x73\xef\xf6\x0b\x42\x65\x5f\x98\xd2\x41\x53\x0b\x60\xa8\xc1\xac\x06\x5d\x98\x64\x51\xc8\x67\xf8\xed\x41\x7f\x34\x95\x8a\xca\x0d\x93\xe3\xda\x5c\x6d\x6e\x62\x92\xe9\xf7\x07\x05\xd5\xea\xe8\x8c\x1d\xf9\xef\x58\xa7\xc3\x12\xa1\x3d\xda\xd2\xa8\xee\x17\xac\xb1\x4e\x87\xb5\x3a\x97\xab\xa2\x39\x17\xd9\xe1\xc3\x74\x60\x82\x39\x99\x18\x7a\x9f\x68\x95\x14\x0b\x9e\x8a\xca\xda\xe4\xd0\xe2\xd5\xe5\xb9\x42\x96\x2d\x86\x8a\x42\x67\x17\x54\x4e\x1d\x52\x39\xb5\xbf\xb5\x53\x9f\x71\x4c\x41\x54\x76\x0c\x98\xbc\xcb\x80\x43\xbe\xec\xb4\x62\x67\x2b\xeb\x6f\xed\x0b\xef\x0e\xb7\x16\x4f\xbb\x8c\xa0\xcf\x39\x9d\xad\xfd\x65\x53\xf6\x2c\x6a\x7d\x0e\xb9\x5f\xe7\x66\xfa\x65\x07\xf5\x9f\x76\x19\x8b\xb4\x76\xb6\x86\x77\x87\xfb\x5a\x87\x71\x59\xc5\x0e\xc0\x94\x99\xa3\x98\x00\x20\x1d\xf0\x89\x31\x25\x5b\x61\x06\x46\x19\xa8\x11\x75\x55\x45\x0f\xed\xe6\xe6\xbf\xbb\x77\xef\xbb\x7b\xb9\x01\x9d\x65\x3a\xa2\xea\xef\x81\x8c\xbc\x3a\xc7\x90\x5b\x2d\x67\xca\x17\x8e\xea\x93\xb9\xbe\xbd\x7a\x52\x36\xff\xee\x8b\x87\x8c\x74\x9c\x7a\xf1\xdd\xdb\xa6\xcc\x9d\x3b\x65\xdb\x51\x95\x46\x6c\x16\x46\x75\xcb\x26\x2f\xb7\x18\x20\x2e\x1d\xc8\xa4\x0b\x0a\x15\xba\xf8\x82\x4c\xd3\x48\x17\xd0\xbc\xc1\x66\x0a\x06\x8c\x97\xdf\x27\xfa\x63\x4a\x3c\xc6\x4b\xd9\x6e\x4a\x77\x09\xb9\x6c\x07\xa5\x92\x22\xf3\xfb\x9a\xb9\x4c\xc0\xef\x93\xf4\x48\x31\x2e\xb2\xff\xf8\x97\xe8\xcf\x4f\x96\x95\xb3\x86\x7e\xca\x82\x33\x27\x67\x14\xfb\x3b\x54\xdf\x93\xb3\x70\x2f\x44\x77\x4e\x70\x7d\xb2\xc9\xe7\x92\x6f\x71\x89\xd4\xad\x15\x7b\xb5\xbf\xa4\xf8\x1b\x29\x68\xf1\x5b\x1d\x42\xd7\x19\xa4\x75\x85\x56\x87\xa7\x29\xbd\x1c\xb1\xa9\xff\x35\xd5\x92\xe4\x16\x73\xbf\xd0\xba\x78\x56\x1e\xba\xea\x34\xa9\xce\x26\xa7\x5a\xd8\x1a\x76\xc0\x29\x69\x91\x45\xda\x17\xcf\x8d\xfd\x76\xea\x49\x76\x57\x93\xa8\xc8\x82\x87\x77\x3b\xa9\x2d\x1e\x16\x98\x24\xda\xec\x16\xf7\xfd\xdf\xe7\xd8\x54\xed\x9d\x86\x40\x8b\xd7\x6a\x91\x53\x56\xaf\xcf\xe2\xac\xc8\xd1\xc6\xda\xe5\x47\x1b\xce\x03\x92\x81\x4c\xc4\x93\x4d\x75\xf0\xf1\x98\xe4\x13\xfd\x3e\xb1\x99\x38\x83\x77\xcc\x65\x75\xb6\x52\xf2\x19\x6d\xf6\x19\x03\xbf\x8b\x9f\x4e\x39\x77\xaa\x83\x9f\x44\xba\x88\x16\xc8\xa4\x9b\x39\xbf\xcf\xc9\x49\xcd\xa4\x7f\xe2\x06\x66\x58\xdb\x82\x99\xb4\x79\x42\xe3\xa9\x33\xcf\x9d\x3f\x75\x7e\x98\x18\x59\xc4\x89\xb3\xce\xd8\xb2\x32\x33\x75\xd5\xc6\x99\xe9\xc5\x16\x2a\xbf\xc1\x5c\xdb\x13\x52\x9d\x28\x50\x80\x4f\xe4\x3a\x32\x02\xbf\x92\xde\xb8\x31\xb8\x2c\x38\xe7\xb3\xd7\x2c\xef\x8c\x9e\xb4\xa4\x2b\x77\xcf\x0b\x73\xae\xfc\xca\x9e\xe5\xed\xfb\xda\x2f\xd6\x2e\x71\x45\xe8\xb4\xcb\x67\xb6\x4f\x8f\x7a\x78\x5b\xee\x40\xd6\xb2\x69\xc1\x39\xec\x15\x29\xd4\xbd\x71\xc9\x9c\x8b\xa6\x85\x1d\xe9\x9f\x66\x1a\x2f\x0e\x75\x0c\x6d\x58\xc1\xd7\xbb\xec\xcd\xc9\xf0\x24\x7f\x5a\xe0\x5e\x69\xb3\x38\xac\x02\x4f\x67\x32\x99\x42\x53\x97\x5c\xdb\x93\x3d\xeb\xe4\xa9\x91\xfa\xf8\xb3\x77\xad\xfa\xca\x05\xa7\x86\xc5\x80\x29\x9b\xf2\xfa\xf8\x9c\x0a\xf8\xf5\x39\x2d\x5f\xc8\x87\x28\x95\xeb\x60\xa9\x82\x2e\x9a\x76\x51\x41\x94\x9c\x24\x39\x39\x49\x64\x92\x93\x6b\xa1\x40\x50\x94\x62\xfa\xe4\x1d\xd7\xfb\xd9\x13\x38\xed\x94\xc6\xb0\x83\xb6\x5c\x4c\xf5\x33\x16\xc9\x72\xf4\xb1\x6b\xa7\x4e\x5e\xfd\xf9\xb0\xe0\x6c\xbe\x3d\x69\xb1\x8b\x56\xd6\x78\xb5\x87\x05\xbc\x4e\x22\xcf\x1e\xce\x51\xd7\x56\xd7\xb4\x31\x7c\xcb\xec\xcc\x93\xd7\x7d\x42\x92\x65\x67\x7c\xa6\xc4\xb2\xac\x2e\xde\xe0\xa8\x13\xb8\x0b\x99\x55\x10\xac\x2c\x95\xb6\x25\x5d\xf2\xa4\xe8\x54\xc7\xae\xf2\xef\x97\x58\x57\x9e\xf1\x09\x97\x97\x6f\x6c\x2f\x70\x3e\xe6\x1d\xa5\xd7\x23\x82\x8a\x46\x5c\x0b\x24\xd3\x01\x97\xb9\x1b\xa6\x8f\xe5\x78\x4c\xe9\x36\x77\xc2\xc4\x36\xf2\x90\x2e\x03\xe8\xb2\x80\x3e\x8c\xba\x58\x37\xa5\x03\x06\x89\x8a\x92\x92\xea\x60\xa9\x0e\x4e\x6f\x87\x3e\x17\x07\x7d\x5e\xbf\x4f\xac\x12\xb8\x8b\xc4\x84\x4e\xc3\xca\x0c\xd2\x31\xe2\xc9\x32\x5d\xa0\xd3\xe9\xdc\x10\x74\x9d\x4c\x52\x52\x1e\xf1\xa5\xa8\xd7\x77\x9d\x6f\xaa\xef\x3a\x9f\x37\xba\x78\x71\xad\xe7\xc3\x5f\xe4\xed\x3f\x6e\xdf\xd7\x9e\xb8\x3d\x41\x49\xb1\xb9\xce\xef\xb4\x4c\xe4\x7d\x3c\x13\x52\x4d\x0d\x4d\x9c\xdb\x41\xa2\x5d\x96\x9a\x98\xe7\xfc\xf4\xa2\x88\x95\x78\x41\xb0\xb5\xee\x49\x08\x5c\xac\x57\x7b\xe3\x94\xf4\x4f\x33\x9c\xe7\x53\xeb\xea\x65\x91\x18\xcf\xd5\x7d\x21\xba\xd9\x27\x37\x47\x43\x13\x9d\x6a\x32\xf4\x40\x28\xf4\x40\x28\xc9\xa3\xea\x1a\x02\x3f\xdc\x28\xf0\x44\x24\x38\xea\x88\x36\x0c\x2c\x6e\x72\xf2\xed\x4b\xac\x8b\x4e\x25\x8b\x95\x63\x44\x3c\x7f\x7a\x61\x45\xf9\xf1\xfb\xdd\x97\xce\x8b\xfa\xdb\xdc\xad\x36\xa7\x8b\x98\xcf\x9b\x21\x6b\x63\x24\xe4\x9c\x48\x9f\x58\x4d\xbb\x56\x5f\xc9\x1a\x83\x61\x1f\x6f\xaf\x77\x3a\x36\x5d\xc8\x42\x5e\xba\xde\xc4\x31\x67\xe8\x03\xce\xc3\x5d\x80\x5c\xc1\x63\x82\x0f\x06\xc6\x21\x31\xa7\xe8\x48\x31\x90\xd8\x42\x39\x9f\x3e\x0c\x4e\x80\xc7\x2e\x96\x55\x72\x59\xc3\xa0\x6c\x2c\x26\x29\xdd\xcc\x8c\x0d\x13\x2e\x1e\xeb\xa0\x6c\x3e\x17\xf5\x05\x7c\x4e\xd2\x85\xba\x94\x92\x2d\x74\x71\x99\x74\x33\xf9\x44\x7f\x34\xab\x64\xbb\xe8\x74\x13\xb7\x73\xe8\x3c\xc2\xa6\x68\xb0\x16\xb1\x4e\x9b\x47\x98\xd1\x7c\xdd\xe2\x75\x13\xad\x44\x8c\x8e\x8b\x57\xc9\xca\x91\xa0\x63\x8c\xaf\xfb\xc2\x84\xf7\xdc\x26\x6e\x85\x66\xfb\xf4\x42\x91\x0f\x85\xf8\x62\x61\xba\xdd\xe1\x12\xb8\x21\x70\x82\xcb\x31\x3e\x94\xd7\x43\x85\xeb\x1b\x05\x9e\x11\x4f\x91\x1a\x94\x2f\x9c\x43\x0e\x91\x31\x5e\x38\xbd\xb0\x3b\x5b\x78\xf6\x81\x79\xc7\x47\xb9\x7b\xe3\x37\x3e\xf7\x28\x27\x35\x59\xa4\x05\xf3\x4e\xcf\x0b\xf6\xc6\x3a\xfb\xa6\x35\x06\xce\x8f\x0c\xa7\xda\xf3\x9c\xbf\xd3\xcf\xe5\xdb\x53\xfe\x44\x4b\x9c\xb1\x78\x4b\xc2\x7f\xdc\x40\xf3\x60\xd9\x58\x9d\x86\xb1\xbb\xf6\xbf\xd9\x63\x97\xa0\x84\x3e\x34\xac\x45\xc4\x8a\x65\xcb\x51\xc3\xba\x44\x30\x94\xab\x4a\xe8\x88\xe1\x13\x51\x89\x33\x52\xf2\x6a\x48\x29\x8d\x1a\x9b\x5c\xf0\x31\xce\xff\x47\x70\x9b\xe6\x89\x9c\x5a\x81\xdb\xf0\x09\x55\x6b\x1d\xc3\xc7\xfe\x2f\xc0\x3d\xde\x46\xe1\xe3\xfc\x63\xe1\xae\xc5\x76\x2d\xae\xff\xc7\x98\xfe\x7f\x02\xf3\xc7\xbb\xff\x49\x98\x3f\x42\x57\x37\x7e\xf7\xd8\xf3\x31\xfe\xe3\xd1\xcd\x47\xc5\x7f\x5c\xdb\x09\xb2\xc3\x60\x6d\x4f\xf0\x12\x21\x3b\x8e\x18\x1e\xa1\xe8\x90\x8f\xe0\x44\x31\x27\x72\x0f\x8c\x94\x46\x57\x1c\xcf\x39\xf4\xb7\x11\x27\x7f\xdc\xd0\xe3\x67\x33\x0f\xab\x8e\xc7\xa9\xa9\x87\x8e\xa5\x48\xc9\x9a\x16\xb7\xff\x2c\x36\x8e\xc1\x8e\x2a\x3b\x9c\x56\x6d\xc0\x6a\xa5\x88\xd5\xe9\x90\x05\x55\x76\x7c\x68\xb4\x50\x34\x40\x39\x6a\xbc\xf9\xe2\x78\xf7\x68\x1a\x6e\xa0\x5c\x72\xc8\x7a\xf6\xb0\xfe\xfa\xf8\x96\xd5\x36\xf2\xb8\x6d\xac\xe8\xfe\x4d\x7d\x4e\x3a\x68\xfd\x5f\xb7\xb1\x4f\x6f\xa0\xa1\x19\x74\x5a\x29\x22\xec\xfd\x67\x9b\xc8\x5e\x0c\xeb\x25\x98\xe6\x22\x56\x6d\x40\xb3\xfe\x13\x4d\x34\xf5\x8c\x86\xfd\x70\x8b\xd1\x7f\x86\x14\x55\x6d\x53\x55\xb8\x6e\x22\x32\xb4\x4c\x12\x52\x0e\x7b\xa3\x57\x5b\xbf\x77\x53\xb9\xb8\x69\xef\xde\x4d\xac\xb4\x69\x2f\xdd\xe9\x6d\xb4\x3b\x52\x7c\xff\xd1\xd2\x44\x8f\x20\xd3\x9d\x8f\x54\x63\xf6\x6e\x7a\x98\x76\xca\x82\x67\x44\x9e\x92\x4c\x79\xc0\x89\x66\x74\xe8\x98\xd4\xe5\x93\x7c\x9a\x3c\xd1\x1c\x05\xad\x54\xa3\xd2\xce\x79\xb2\x4a\x70\x9c\x5a\x9b\xa9\x1b\xfa\x37\x6c\xe8\xe7\x37\x1c\x51\xa9\xd8\xcf\xc0\xf0\xa1\xd1\x0e\x51\xc7\xc4\x9d\xb5\x56\x90\xbc\x5b\x4f\xb8\xa1\x5c\xd2\x8a\x25\x23\x29\x45\x64\xc7\x51\x03\x61\x7c\xc9\x21\x47\x8e\x1a\xaa\x6c\xbe\x54\xb1\x59\x1c\x56\x85\xb7\x85\xb5\x10\xe1\x43\x03\x92\x40\xb4\x90\x92\xfc\x19\x3f\x65\xe3\x31\x89\x44\xbf\x2f\x93\xd6\x45\x6f\x2b\x45\x3d\xe4\x73\x11\x15\xf2\x19\x9d\x13\xa4\xb5\x67\xbf\x7d\xb6\xca\xae\x0a\xd8\xa4\xf2\x1f\xa4\x80\x4d\x62\xcd\x52\x9e\xfa\x87\x4a\x5a\x9f\xf0\x76\xf2\x11\xad\xef\x91\x44\x3e\xa7\xbc\x9d\x3c\xfb\xed\xb3\xd7\xaa\x5c\x7f\x40\x4f\x65\x0b\xe8\xa9\x7e\xaa\xf5\x0d\x95\xa8\x9f\x0d\xe4\x92\x8f\x50\xff\xc3\x8a\xf2\x97\x54\x85\xff\xe4\x4d\xdb\x8f\xe0\x58\x4d\x87\x93\x62\x4a\x8a\x14\x43\xf1\xcd\x99\x46\x1a\x74\x77\x54\xdb\xe5\xee\x9e\xd7\xed\xd2\xee\x8c\x52\x3b\xed\xa1\x76\xae\x62\x5b\x81\xf5\x73\x86\x8e\x44\x15\x25\xca\x89\x73\xd6\x1f\xa0\x76\xed\xc0\x18\xbb\x12\x19\x48\x7a\x62\xc6\x5e\xd5\x98\x0d\x6a\xec\x3a\xb2\x73\xe7\x11\x6e\xd7\xb8\x5d\xa9\x3e\xbe\x68\xee\x40\xb1\x43\xc7\xee\x1d\x9a\xfa\x7a\x08\x25\xf8\x0d\xfd\x6b\x36\xd5\xc1\xa5\x94\x98\xc1\xd6\xfb\x7d\x81\x74\x3e\xe9\x43\x04\x39\x9d\xd9\x2a\x74\x51\x3a\x10\x6c\xe6\x82\x01\x06\x1f\x35\x05\xc2\x12\x1f\xe3\xa5\x70\xa0\x89\x7c\x3d\x17\xf7\x30\x68\x07\xb4\xa5\xda\x81\xd3\xc5\xcb\x3e\x75\x49\xd8\x9a\xce\x66\x2c\xe1\x4b\x3e\x75\x99\x78\x3a\xa9\x89\x28\xb5\x45\x0b\x41\xb7\x3b\x58\x88\xb6\x51\x34\x91\xeb\xe9\x79\xe2\x80\x76\x80\xda\x0f\xdc\xf1\x19\xeb\x83\xb7\xfe\xfa\x9c\xe6\x58\xac\xf9\x9c\x5f\xdf\xfa\xa0\xf5\x7a\x73\xbc\x8a\x1f\x08\x2a\x44\x38\x71\x32\xba\x30\x0f\x20\xb3\x37\xa1\x48\x24\x06\x0a\x24\x8f\x25\xed\x60\x20\xa8\x33\xfa\xa9\x31\x1b\x2a\x33\x28\xdb\x4d\xf9\x00\x67\x74\xb9\x44\x05\xd3\x06\x8e\xdb\xbc\x71\xf7\xc6\x3e\x86\x88\x47\x7b\xc0\x13\xf1\xd0\x8a\xd3\xf7\x6e\x1a\x32\xa8\x9c\x2b\x76\xe7\x5d\x1c\x67\x9f\xe2\xf4\x06\x03\x43\x06\x19\x72\xc5\x99\x2b\xac\x45\x57\x6b\x1f\x45\xca\x7d\xda\x00\xbf\x7c\xb9\x36\xb0\x3c\xbc\x38\xbc\x3b\x4c\x7d\x1b\x77\x6f\xec\xec\x63\xa5\x91\x72\xca\x3f\x7f\xc6\x2c\x65\xd3\xde\x06\xc9\xed\xb1\x4f\x71\x8a\xa2\x69\x08\xb2\x62\xe6\x75\x0e\x6b\xd1\xe5\x66\x2f\x68\x03\xe5\x3e\x8a\xb0\xf0\x72\x8a\x2c\x0f\x87\x77\x87\x17\x8f\xe0\xdf\xd8\x27\x6f\xc3\xb2\xf1\xb6\xb6\x53\xd2\x26\x3b\xad\x2f\x4f\xb5\x2d\xd3\x65\xb1\x60\x40\x36\xf7\x2f\x67\x50\x3c\x22\x89\x72\xc0\x18\xf5\x1d\x7c\x2e\xdb\x25\x4d\xa3\x5c\xd6\xb0\x0e\xa2\x80\x4f\x50\xab\x4d\xc4\xb0\x43\x0e\x2d\xec\xb4\x89\x1b\xaa\xad\xf3\x86\x43\x6e\xd9\xff\x8e\xa6\x1a\xa3\xbf\x5f\x7b\xfa\x8a\x4d\x27\x71\x41\x0b\xef\xb6\xd9\x02\x27\x4f\x8c\x4b\xfe\xf8\xb4\x45\x97\xde\xf2\xc4\xc5\xfd\x29\x87\x3d\x24\x93\x2a\xb3\xb8\x56\xae\xb6\x53\x76\x34\x0a\xa1\x18\x5f\x6d\xe5\x2b\xb2\xcd\x51\xef\xb6\x58\xe9\x75\x4d\x95\x05\xcf\xc4\xd2\x8d\x37\x6b\xfb\x82\x75\xcc\xe1\x8c\x5d\xd8\xb7\xb5\x73\xca\x92\xbe\xc5\x67\x9e\x32\x35\x15\x30\x26\x18\x4d\x95\xb3\xd5\xb6\x5f\x2f\xa8\x98\x64\x58\x0e\x7a\x8e\xd7\xad\x7a\x13\x8f\xed\x58\x7d\x26\x93\xcd\xfd\xf8\xb1\x56\x8e\xa3\xcd\x1d\xe9\x51\x9b\x83\x13\xc7\xf6\xa9\xcd\x21\x8a\xbe\x3f\x0f\xfd\xb2\x7e\x66\xbd\x76\x46\x7d\xfd\x25\xf5\x33\xeb\x49\x62\x9f\xab\x9f\x59\x7f\x49\x3d\x5b\xa1\x7d\x7f\x6c\x57\xda\xd8\x48\x57\x6a\x0e\x6b\xd1\xc6\x59\xe8\xc0\xd0\x2f\xeb\xeb\xe9\x31\x23\x43\xbd\xf6\x21\xfb\x9c\x51\x88\x79\x6e\x06\xc3\x90\x20\x02\xb3\x2a\xeb\x8c\xa1\x6a\xf2\x64\xd2\x81\xaa\x01\x81\xa1\x5a\x8a\xfa\x7d\x62\x75\x95\xd5\x27\x67\x43\x27\x55\xdd\xa6\x37\x6c\x94\xa2\xb9\xac\xee\x91\x20\x0f\x43\xce\x2a\x9a\xaa\x86\x14\xc3\xa9\xbf\x94\x90\xaa\xa9\x8a\xe1\x94\x09\xc6\x46\x81\x1e\xad\x3b\xf5\x97\x12\x52\x49\x8f\x26\xb0\x7b\xfe\xb9\xf4\xf2\xd8\xda\x6a\xf4\x00\x4d\x00\xe5\x0d\x3d\x54\x8a\x94\xd4\x38\x5b\x2b\xbf\x27\x5f\xe0\x5e\x96\x43\x21\xb9\x3c\xd5\xca\xd7\x58\xcb\x5b\x85\x2b\x64\x7b\xe8\x48\x31\x64\x97\xd9\xb3\x56\x5b\x79\x59\x95\xe7\x56\x42\xe5\x65\x36\x6b\xcd\xf9\x90\xb6\xf1\xe5\x9f\xa0\x1a\x23\x51\xbe\x20\x8e\xd4\x76\x6c\x9d\xec\x59\x39\x74\x4c\xcd\x53\x4f\x00\x02\x7b\x56\xb6\x87\xca\x53\x0d\x58\xb6\x54\xf4\x5d\x0d\xc7\x81\x25\x3b\x52\xf3\x99\xb5\x35\xcb\xf2\x47\xd4\x26\x67\xe5\xd1\xe2\x8d\xb6\x5e\x23\x5c\x2f\x6c\x45\x1d\x60\x25\xd1\x68\x96\x31\x46\xd7\x1c\x79\x29\x18\x8d\x06\x85\xc9\x41\x76\x5e\xb9\xd9\xe1\x0b\x09\xa5\x90\xcf\x51\x6e\x76\x24\x30\xc6\xa6\xd0\x55\x59\xe1\xc7\x2c\xaa\xc2\xf8\xa3\x3f\xa8\x58\xfe\x1b\xa7\x00\x86\xd4\x5a\x9f\x50\x1c\x95\x7a\x6a\x25\x20\xa5\x4a\xbb\xd5\x7a\x8e\xa9\x45\x1c\x23\x31\x8d\x29\x67\x34\xaf\x68\xe2\x2e\x38\xd2\xb4\x60\xa5\x85\x92\xd1\x5a\x51\x3a\x49\x47\x1d\x7b\x56\x47\x1d\x7b\x56\xd6\xd1\x17\xe2\xad\x3a\xe6\x84\x52\xc8\xae\xe3\xd4\xc6\x9e\x35\x1c\x72\x56\x7f\xd9\x43\xec\x59\x9b\x75\xa4\xfc\x2a\x9d\x1c\x53\x7e\xd0\x33\x76\xcb\x54\xaf\xea\x78\x35\x8e\x25\x93\x13\xd7\x6e\xb5\xb1\x47\x46\x11\xc4\x1e\xb1\x59\x6b\x81\x19\x33\x26\xc6\xc2\x32\x1e\x88\x91\xda\x6b\xeb\x1d\x5b\xe3\xb8\x8a\x8c\xfe\x26\x40\x24\x41\x44\x1d\x1a\x01\xd9\x9c\x14\x8c\xde\xa0\x9a\x1e\xd1\xeb\x71\x8e\xd2\x98\x4e\x7b\xc2\xb3\x35\xdd\xc2\x4e\xaa\xa2\x38\x54\xfe\x93\x69\x0b\xa5\x84\x86\x11\xaa\xf4\xd7\x3d\xc3\xf7\xf0\x8f\x08\x7f\x82\x0f\xb0\xb2\x80\x69\x3d\x5e\x99\x8f\xf4\x89\x94\xbf\xb3\xfc\x0e\x93\x65\xf9\x11\xbd\x27\x42\xb2\xcc\xfe\x24\x67\xe5\x47\x64\xfe\xe5\xf2\x3b\xe5\x77\x0c\xa7\x19\xc4\xfe\x64\xa4\x31\xcb\x5c\x36\x7c\x0f\x7f\x41\xa5\xcc\x63\x0c\xd1\xf5\x42\xcf\x2c\x87\x2a\x79\xe5\xf2\x3b\x66\xe1\xec\x4f\x32\xbb\x53\xaf\xc1\xf0\xc8\x4c\x36\x13\xe8\x09\xc7\xd0\x7e\x1c\x93\x00\xca\x65\x95\x78\xd4\x63\x1e\xe1\xf1\x7b\xa2\xe6\x39\x9e\x4c\xd4\x63\x1e\xe6\xc9\x79\xa2\xe9\xb1\xd6\x3b\x25\xbd\xc9\x06\xde\x87\x8d\xf6\x93\xe9\x31\x0c\xc3\x8a\xe3\xcd\x77\x8a\x95\x98\x63\xf3\x50\xdb\xb1\xb6\x4c\x35\xf6\x44\x15\xb8\xaa\xd0\x1c\x0b\x43\xcd\x59\xa0\xe3\xd6\x5a\x91\x79\xc7\xd7\x52\xdb\xfe\x36\x63\xef\x34\x3b\x89\x0a\xf9\x5c\x76\x12\x29\xf1\x98\xcb\x50\x96\xb9\x74\xfe\xb6\x85\x24\xe3\x1d\xc8\xa4\xbb\x0d\xdd\x66\x37\x8d\x85\xe1\x5a\xf9\x89\x27\x64\x79\x99\xdc\x18\xd2\x1d\xa1\x46\x79\x99\x7c\x6c\x08\xdd\x38\x0e\x36\xba\xef\xa3\x92\x57\x42\xe8\xc5\x13\xe2\x26\x68\xd8\x79\xe9\xd0\xc6\x24\x4a\x29\x26\xac\x41\x1d\xca\x02\x75\x51\x0d\x7c\x02\xef\x3d\x5b\xce\xca\xda\x9a\x3f\xc8\x59\xf9\x6c\xaf\x97\x2e\xd6\xab\x60\x2d\xde\xa1\xf1\x76\x95\xb1\xb0\x77\x99\x2c\x6b\x17\xfd\x41\x96\x97\x79\xc3\x8d\x5e\xed\x6e\x59\x4f\xb7\x60\x1c\x0c\xb5\xf6\x5e\x53\x31\x07\x48\x8e\x3f\x37\x96\xed\xa0\x78\x4c\x12\x0d\x9c\x55\x0c\x43\xfc\x3e\x51\x72\x52\x35\x45\x2e\x9b\x2f\x74\xf1\x89\x71\x26\xa0\x23\x36\xe3\xb8\xf4\x91\xb3\xfe\xa6\xba\x82\x5b\x25\xbb\xdb\x9a\x8b\xc6\xb2\x93\x7b\x5a\x27\x77\x5f\x64\x44\xb6\x45\x23\xb1\xa9\x2d\x0d\xa4\x8e\x83\xbe\x7f\xc4\xb8\x9c\x3d\xb6\xf4\xee\x33\xfe\xa3\xde\xbb\x4a\xb4\xcf\xae\xaf\xcf\x46\x95\x8e\x40\xf8\xca\x59\x09\x3d\x5a\x9e\x21\x7b\xfd\x53\x26\x2d\x98\x31\x9e\x18\x46\xdb\xa4\xcb\x5e\x53\xab\x6d\xf2\x8c\x92\x9e\xa1\xe7\x1e\x21\x42\x6e\x5c\x93\xc7\x58\xfc\xc1\xeb\xec\xab\x1a\xb4\xf6\x99\xd6\xca\x25\xa7\xb7\xa6\x81\xec\x18\xe0\xfb\x9d\x5e\x06\x3d\xb6\xdf\xe9\xd5\x4a\xc6\xc7\xcb\xdd\xd6\x5f\x09\xf1\x7e\x6f\x3c\xbc\xa3\x74\x30\xc9\x38\xfb\x33\x72\x16\xa4\x83\x52\x23\x3a\x17\x27\x49\x19\x9d\x01\xd2\xfd\xcd\x14\x1c\x39\x26\xd2\x45\xa6\x5e\xc6\x49\xd2\x48\xda\x0e\x4a\x8d\x94\xd1\x45\x85\x91\xb4\xcd\x14\xcc\xa4\x03\xfc\xd7\xd7\xeb\x03\x69\x7d\xe4\xfe\x75\xc6\x70\x5a\x77\x7f\x64\x7c\x00\x5d\xa1\x84\x6e\x4f\xbe\x7d\xbf\xe1\xbd\xff\xed\xe4\xed\x7a\xfc\xb8\x00\x86\x13\xe5\x1e\x09\xa0\xf6\x13\x67\xaf\x04\x8c\xb5\xcb\x8c\x1b\x56\xec\x30\x0f\xfe\x48\xe6\xc4\xd8\x4d\x29\x73\x62\x6c\xa9\x4a\x27\x2e\x0a\x06\x7c\xf9\x13\xd9\x21\xce\xdf\x69\x0b\xd9\x6e\xbe\xd9\x16\xb2\xed\xb4\xe9\x5f\xdb\x38\xff\x0b\x1f\x65\x99\x48\x3f\x39\x7e\xa6\x11\x7f\xc3\x47\x9b\x27\x1f\x6b\x3b\x6d\xad\xe1\xbe\x5b\xa8\xb2\x68\x9c\xd0\x88\xf2\x4e\x6d\x99\x3e\xbc\x5f\x93\xe5\x0b\xe4\xac\x7c\x27\xe9\x93\xfc\x05\xf2\x96\x8f\x34\xa6\x7c\x59\x5b\x26\xcb\xa4\x18\x29\x8d\x2c\x7a\xde\x23\xff\x20\x9c\x9f\x85\x15\x5e\xe3\x5c\x70\x36\x45\xc6\x9e\x9d\x60\xd8\x55\x92\xdf\x07\x77\xe5\x8c\x4c\xe5\xc4\x8e\x10\x39\xab\xec\xbc\xb9\xff\xd2\x9f\xec\xfc\xe4\x50\x03\xfb\xdb\xe7\x1e\xde\x75\x64\xa7\x10\xd9\xf2\x82\xf6\x47\xed\x39\xed\x8f\x2f\x6c\xd9\xf2\x02\x35\x51\x27\x35\xbd\xc0\x6e\xbc\xff\xa6\xb2\xeb\x53\x67\xed\xfc\xd9\x7e\x76\xf8\xec\x9d\x43\xbb\x1e\xa0\x6e\xed\x59\xed\x0f\x86\x85\x65\x33\x4d\xa5\x26\xdd\xa5\xaf\x83\xc5\xe1\x9c\x08\xa1\x07\x91\xea\xd9\x21\xa3\x77\x4d\xbd\x5a\xce\x54\xac\x19\x47\xb2\xc8\x60\xac\x4e\xc9\x96\x8b\x94\x54\x94\x9e\x64\x2e\x9b\x2a\x5f\x99\x4c\xb2\x5b\x95\x5c\x56\xe9\x51\x14\xed\x37\xac\x94\x3d\x85\xa9\x6a\xae\x47\x7b\x2d\xb1\x2e\xd1\x9b\x4c\xb2\xed\x86\xb1\xc2\x2d\x8a\xb2\x40\xb9\x58\xd1\x7e\xd3\x63\xf2\x23\x39\xa1\x54\xa9\xcf\xd4\x6d\x19\x4b\x2f\x8d\xe8\xa8\xcc\x8e\x32\x24\x42\xa1\x94\x2c\x5f\x99\xca\x66\x52\x3d\x8a\x42\xc9\x72\x31\x7b\xca\x29\x59\x56\xd2\x7e\xa3\x28\x3d\x4a\x36\xa7\xb0\x5b\x93\xac\x98\x4f\xea\x60\xf4\x28\x17\x2b\x94\xec\xc9\xa9\xb9\x1e\x52\x12\xeb\x12\x3d\x8a\x52\xbe\x52\x9f\xd0\x91\x1b\x56\xc5\x1e\xa1\x88\xa8\x61\xd7\x66\x36\x6c\x84\xeb\x31\x17\xfe\x4a\x33\x75\xc6\xa5\x27\xd9\xa3\xe4\xf2\x09\xed\x35\xa3\x28\xa3\x21\x3d\x8a\xc2\x6e\x8d\x17\xf2\x49\xbd\xba\xdc\x47\xc0\xa2\xc3\x6a\xf2\x16\xb9\xe1\x27\xc4\x1e\x41\xad\x9e\xf5\xae\x22\xb3\xd2\xac\x11\xde\xab\x82\x5b\xb1\xc7\x68\x65\x2e\x59\xbe\x52\x51\x16\xe8\x0e\x52\x7a\xb3\x6a\xb6\x97\x14\x1d\x7f\x3d\x49\x56\xca\x25\xcb\x1b\x75\x7c\x26\xf2\x39\xa5\x27\x99\xd4\x5e\x63\xa5\x6c\x6f\xaf\xde\x17\x4a\x32\xd9\x93\x1a\xe5\x39\x4b\xc6\x9d\x60\xa6\x2c\x97\xf3\xc4\x63\x4e\xc1\xef\x0b\xfa\x2a\x67\xcd\x3b\x58\x8a\xe5\xb2\x05\x6f\x34\xe3\xa9\xca\x6b\x9a\x2e\x41\x0d\xac\xfc\xd2\x17\x2f\x5b\xd9\x15\x17\x04\x8f\xcb\x6d\x97\xec\x2e\xee\xfa\xdc\x03\xec\x27\x03\x4a\x56\x66\xe0\xee\xc9\xea\xa9\x74\xd6\xc2\xde\x92\xff\xc4\x95\xfd\xab\x0b\xb3\xc5\xb8\xd5\xe5\xf3\x58\x43\x31\x89\x9a\x1e\xf9\xf1\x4d\x74\xa7\xce\x89\xc8\xda\x18\x1e\x20\xa8\xf3\x40\x3a\x24\xc1\xc0\x28\x77\x5e\x1d\x7e\x86\x9d\xda\x24\xaa\xf2\x5d\xfa\xf4\x62\x2a\xdd\xfe\x66\xd3\x1e\xdf\x21\x9b\xc6\xb4\x4a\x56\xde\x41\xbd\xb6\x90\xed\x72\x2e\xa8\xbb\xb5\xc7\x75\xb7\xcd\x46\xbd\x3b\x2a\x16\xb4\xf4\x4e\xc8\x48\x3f\x62\x94\xab\xa7\xb7\x5d\xce\xcd\x37\x6c\x71\xf5\x0c\xb6\xcb\x6d\x21\x23\x43\x56\xa9\xd8\xf0\x39\x86\x3f\x2f\xfc\x4d\xb8\xc2\x84\xef\x44\x70\x9c\x08\x6e\xc3\xee\xed\x38\x80\x9c\x00\x6e\x56\x3c\x2e\x20\xec\xce\xe3\x82\x8d\xaa\x1d\xa6\x60\x9e\x51\xac\x8c\xc7\x11\x62\x1d\x19\x21\x23\x04\xa4\x4b\x54\x6a\x67\xab\xd6\x67\x9c\xdf\xd4\xfa\x8c\xc3\x02\xfd\x86\x87\xfa\x5b\x3b\xb9\xc8\xf1\x42\x8d\xf4\x95\xba\x18\x04\x95\x33\x65\xa8\x71\x7a\x62\xbd\xdc\xa3\x86\x99\x2b\x5f\xaa\x94\x54\x3d\x24\x6a\xca\x9e\xba\xfc\x94\x33\xce\xc4\xb8\xc8\x49\xa9\xd1\x73\x6f\x82\x68\x1e\xdd\x39\x89\x3a\xa8\x9b\xba\x28\x28\x8c\xc0\x9b\xcc\x07\x74\x7a\x97\x04\xe1\xa7\x1d\x8d\xa1\x62\xe8\xc2\x0e\xed\x7d\x83\xd2\xb5\xf7\x3b\x2e\x0c\x15\x43\x8d\x1d\x64\xd3\xde\xaf\x44\x91\xcd\x1c\x04\xb6\x4a\x94\xf6\x3e\xfd\x29\x74\x61\xc7\x25\x1d\x8d\xa1\x2f\x6a\x2f\x18\x47\xa9\x33\x5f\x0c\x35\x76\x5c\xd2\x71\x61\xe8\x9e\x7b\xaa\x31\x94\x31\x4e\x67\xbf\x30\x12\x53\xbb\x1e\xe8\x32\xca\x49\x86\x15\xa7\xb7\x3a\xe3\x8f\x3f\x83\xcf\xc9\xd9\x94\x1e\x20\x89\x7e\xd9\x0c\x61\x93\xcc\x29\xbb\x3a\xe5\xb3\x6f\x7a\x1d\x25\x87\xcf\xe7\x28\x39\xbc\xcc\x6b\xb3\x39\x5f\x77\xda\x6c\x1e\x9f\xf3\x29\xa7\x2c\x8c\xe7\x43\x8e\xfe\xf5\x19\xa7\xec\x73\x3c\xe3\xf0\xc9\x74\x01\x5b\x6f\x17\x2d\x16\xd1\x5e\xbe\xd3\xe6\x72\x55\xf7\xb6\x44\x08\x45\x38\x10\x40\x0b\x16\xe8\x5c\x92\x27\x17\xf5\x7b\xfc\x15\xbe\x2f\x63\xec\x30\xfb\x02\x89\xac\xc1\x3c\x67\xd2\xe6\xb9\xb1\xda\x33\x61\xa6\x84\x65\xdc\x74\x62\xac\xce\x19\xf3\xea\x93\x74\x80\xeb\xd7\x4a\x89\x70\x29\x9c\xd0\x3a\x7f\x70\x5d\xa8\xad\xb5\xb3\x93\xbd\xda\xd9\xda\x16\xba\xf6\xfb\xad\xb4\xcf\xeb\xec\xeb\x6c\x3d\x5a\x6a\xed\x34\xb9\xa9\x27\xcf\xb9\xf1\xc6\x73\xd6\xce\x50\xd5\x19\x6b\x75\x17\x3d\xe9\xf4\x3e\xde\x49\x07\x4a\x25\xad\xbd\xb3\xa1\xb1\x91\x5b\x7d\x7f\x4b\xe7\xe2\xce\xce\xc5\x9d\x2d\xf7\xf7\xeb\x6c\x58\x95\xa6\xcc\x13\x87\x37\x7e\xe7\xc6\x85\x0f\x3f\xbc\xf0\xc6\xef\xdc\xe8\x35\xf5\x64\x92\x79\x8f\xc3\x22\x43\xaf\x1c\x8f\xf1\xa2\xa1\x9f\xcd\xa4\x0d\xa3\xb3\x44\x26\x4d\x3e\x49\x84\xa9\x03\xa4\x78\xcc\xc9\xe2\x31\x25\xd5\xc1\xe5\xb2\xe6\xb9\x4f\x45\x77\x14\xba\xf8\x42\x17\x9f\x49\x37\x33\x01\x4a\xe8\x51\xed\xf5\x3f\x6e\x91\x95\x50\xbd\xbf\x71\x85\xef\x66\x92\xbe\x1d\x62\x8a\xaf\x43\x7b\xfb\x37\xaf\x0c\xec\xba\xc5\xb5\x33\xe8\x9e\xd4\xd6\xd5\xd4\x36\xa1\x81\x59\x38\xae\x6b\x41\x57\x98\x59\xcf\xfa\xc2\x33\xeb\x0b\x8f\x7f\xeb\x9b\x77\xa5\x6c\x29\x5f\x2c\x55\x9f\xea\x8e\xb8\x39\x25\xab\x9c\xbf\xf7\x73\xfe\xfa\x90\x22\xd7\xaf\x90\xaf\x59\x43\xe2\xb9\x2b\x07\xb4\xef\xaf\x5f\x37\x49\x58\x50\xec\x2d\xc6\x27\xf2\x4e\xd1\x21\xc5\x17\xe6\xa7\xca\xfc\x6c\x5b\x26\x77\xc5\x2f\xbf\xb2\x29\xe1\x75\x71\xd6\x54\xd2\x96\xf2\x04\xad\xcb\xb7\x6e\xac\xea\x38\x20\xa8\x22\xe0\x42\x06\x10\xc6\xef\xb0\xf8\x8c\x49\x37\x15\x34\x14\x9c\x42\x2e\x9b\x0a\xa6\x9a\x79\x41\xad\xdd\x27\x1b\xc6\x94\xd3\xfa\xfa\x4e\x9b\x32\x8b\xa7\x65\xdb\x6f\x5e\x56\x30\x7d\x33\x39\xd3\xd7\x3f\x62\xbd\xce\xcb\x8b\xb6\x9e\x73\xe6\xbc\x79\x67\x67\xfa\x54\xa2\x09\x4b\x36\xde\xf0\xe8\xca\x6a\xc8\x8a\xcf\x54\x42\x2a\xbc\x84\x8e\x77\x5e\x85\x07\x51\x4c\x01\x48\x49\x05\xfc\x15\x7d\xb8\x28\x05\xf8\x48\xc2\xe8\x0b\x53\x51\x6e\x58\xf1\x42\xef\x85\x08\x52\x4a\xb6\x90\x47\x04\x41\x51\xdd\xfd\xe6\x0c\xd3\xf0\x6a\xc6\x9b\xbb\x3f\x4b\x77\xd0\x01\xba\xa3\xfc\x44\xd8\x77\xed\xb7\xc2\xad\xe1\x2d\x9f\xf4\x71\xeb\x7c\xdb\xb5\x54\xf9\xb0\x96\xda\xee\xf3\x6d\xa7\x5f\x33\x27\xfd\x7a\x3b\x2b\x1e\xbc\x72\xcd\xd5\x4f\x69\x1f\x92\xf4\xd4\xd5\x6b\xae\x3c\xf8\xc2\xdf\xfe\xc6\x4e\x6e\x0d\x7f\xeb\x5a\x5f\x38\xec\xfb\xe4\x16\xed\x97\xb3\xe3\x7f\xd2\xde\xa6\xc0\x9b\xf1\xd9\xf1\x37\x29\xa0\xfd\xe5\x4d\xe3\x5c\x6d\xbf\x04\x7e\x00\x56\x34\x60\x06\x66\xe1\x13\x40\xb2\xd0\x41\x06\xa8\xde\xf1\x70\x26\x75\x38\x2b\xda\xd5\x5c\xb6\xd0\x41\x26\xc4\xd1\xb4\x71\xaa\xb4\x99\x0b\x06\x64\x9f\x28\x51\x80\x37\xd4\xcf\x7c\xbc\x90\x4f\x14\x94\x54\xa1\x99\x82\xac\x6d\xd1\x59\x2b\x67\xbc\xb9\xfb\xab\xec\xe6\xd1\x56\xd0\xe7\xe8\x62\x6d\xf9\x45\x53\x6c\x5e\xfb\x16\x77\xfb\xed\x87\x96\xfa\x7c\x5f\xa4\x67\xc9\xf1\xa9\xb3\xf3\x36\xaf\x10\x4a\x34\x47\x39\x77\xf2\xbe\xcf\x50\xbd\x85\x4a\xbe\xd4\x9c\xbb\xb5\x2b\x7f\xb7\xe0\x00\x5d\x74\xf5\x15\x5f\xed\x3e\xf7\x1b\x27\xff\xe4\xf3\xdd\xa5\xb5\x7a\x3b\x35\x8d\x5d\x32\xda\xcc\xbf\x4a\xec\xe9\xb2\x7d\xff\xa7\xdc\x73\x6c\x5e\x7b\xcf\x29\xaf\xde\xdc\xd2\xdb\xf2\x36\xb9\x3d\xe7\xb9\xed\xb2\x57\x66\x36\x6d\xf2\xad\x6f\xa6\xe9\xfd\x93\xb6\xce\x89\x15\x4f\x7f\xf4\x99\xad\xde\x77\xf7\x7f\xeb\x8a\x0d\xc5\x6f\x9e\x6b\xf6\x9d\x7b\x58\x15\x07\x0d\x7a\x8a\xea\x14\x35\x5e\xfe\x3b\x76\x4e\xe2\x28\x20\x8d\x58\x79\x52\x17\xa5\x03\x7c\xcd\x5e\x2d\xf3\xda\x1c\x75\xaf\xd7\x39\x2a\xb3\x92\x83\x43\x3c\xe9\x99\x16\x3b\x82\xd8\x34\x4f\x32\xce\xc1\x33\x7d\xce\xf4\xfb\x9f\x71\xca\xb2\x53\x7f\xd1\x56\xfa\x99\x5d\xaa\xab\x93\x9c\x5a\xc1\xe6\x70\x70\xfb\x8e\xa8\xdd\xdd\x4d\xb1\x58\x53\x77\xb7\xa0\xb6\x24\x12\x95\x35\x69\x9d\xb0\x0e\x69\x80\x02\xa2\x8b\xe4\xaa\xb6\x3b\x65\x25\x43\xf3\xdd\x46\xca\x24\xa6\xa4\x94\x6e\x93\xa5\xb1\x92\xe9\x0e\x0a\x85\x2e\x12\xfa\xda\x8b\xbd\xf7\xf7\x0b\x1e\x55\xb2\xf3\x9c\x4b\xd4\xfe\x4b\x2b\xe7\x04\x47\x9f\xd5\xc9\x5c\xd6\xa7\x87\xea\x18\xd9\xfa\xac\x4e\x91\x7d\x9f\x38\x8d\x77\x72\xac\x4e\x75\xba\xd9\x17\xfb\x7b\x4b\x42\x5f\xb6\xd4\x7b\x7f\x79\x9e\xec\xec\x13\x89\x73\xd0\x90\x56\xfe\xbe\xc7\xd9\x67\x65\x75\x43\x4f\x4b\x6e\x87\xfd\x3c\x2b\xe5\x88\xa3\xa0\xc5\xed\xae\x53\x1d\xc2\x57\xfa\x7b\x8b\xfa\x4a\x36\x6c\xee\x51\x1c\x6b\x0b\x5d\xb5\x82\x3e\x0d\x57\x00\xc1\x8a\x25\x77\x72\xdc\x97\x6a\xfd\x23\xca\x9b\xca\x7c\x5c\x93\xae\x30\x2e\x2e\x39\xee\xd4\x48\x45\xdc\x8b\xd6\xdc\x25\x10\x50\x29\xa2\x0d\x50\x1f\x15\xb5\x92\xd6\x3f\xde\xcd\x06\x0c\xb7\xaa\xbf\x39\xe8\x21\xa6\x5b\xeb\x1f\x3d\x4a\xc3\x06\x46\xc3\xc9\x28\x2d\x32\x1a\x49\x6a\x6f\xf6\x88\x71\x82\x5d\x5d\x31\xb3\x38\x73\x05\x99\x1f\x35\xdb\x6b\xd6\x1b\x29\x1a\xd9\x8a\x45\x8a\x0c\x81\x22\x54\x32\xbf\x45\x2a\xb2\x08\x45\x0c\xab\xd7\x01\x87\x2c\x0f\x7d\xdd\x48\xa2\x67\x28\xd5\x04\x2f\x3c\x6a\x5c\x78\x22\x20\xdb\xdb\x37\x73\xc5\x8a\x99\x7d\xe6\xbb\xb7\x22\xc7\xf4\x4b\x10\x06\xe0\x45\x01\x97\x01\x24\x4a\x1d\x7c\x8d\x99\x42\x75\x0f\x7b\x06\xc5\x9c\xd4\x21\xa6\xf2\x85\x66\x3e\x13\x35\x8f\x12\x90\x77\x24\x32\x1a\x73\x32\x49\x94\x9c\xb5\x16\x0e\x86\x31\x5f\x97\x38\x92\x9a\xdd\x33\x7d\x61\xa0\x39\x93\xe9\x69\x1f\x30\x8e\xb7\x1e\x11\x44\xab\x56\xb2\x3a\x1d\x72\xe4\xe2\xce\x65\xd9\xde\xf4\xcc\xec\xd4\xc6\x69\x95\x24\x84\xd1\xe3\x7e\x7a\x92\x61\x4c\x5e\x34\x7d\x62\x7d\xa4\xa3\x69\xc2\xac\x19\x67\x9d\xb3\x79\xb6\x59\xc6\xb8\xc0\x6a\x2e\xbe\x65\xf9\x13\x27\x15\xe6\x4d\x68\x32\x54\x0c\x43\xce\xb0\x5e\x8a\xec\x28\x11\x71\x92\x33\x18\xeb\x98\x91\x3a\xe7\x71\x23\xbe\xe4\xf4\xda\xb4\xef\x71\x9b\xaa\x09\x9a\xa7\x77\x77\x74\xad\x9f\xb9\x6c\xf3\xe2\x4f\x66\xa2\x46\xe6\x31\x21\x66\xf2\xd1\xfd\x17\x01\xd0\x59\x53\x37\xe3\xe3\xb1\x94\x28\x88\x92\xa8\xa4\x72\x4a\x5e\xd1\x17\x41\xa1\xa0\xb0\x5c\xb6\x8b\x12\x99\x34\x2f\x61\x50\x5b\xf5\xde\x9c\x9e\x67\xb5\x23\x53\x4e\xf1\x34\xf2\x9c\x40\x36\x66\x67\xd2\x64\xff\x84\xfa\xe6\xba\x2f\x3f\x71\xdb\x20\xf5\x7e\xfb\x3d\xba\x97\xeb\xd0\x1e\xd2\x7e\xfd\x35\xcb\x37\x66\x39\x2d\x2c\xe0\x25\xde\xcd\xbb\x38\x27\xb3\xe4\x82\x9d\x1d\xf3\x5a\x3f\x45\xe2\xdd\x9f\x79\xe7\xd1\xd5\x5f\x1b\x2b\xf3\x67\x8c\x93\xbc\x7e\x9f\xc1\x15\x55\x57\xb2\x26\xf2\x35\x73\xe9\x2e\x6e\x64\x65\xfb\x58\x6d\xfe\x8f\xb4\xfb\xb5\x79\xda\xfd\x3f\x32\x4f\x6e\x4c\x9a\x7e\x46\xc7\xc4\x8e\x33\xa6\x4f\x32\xbd\x43\x50\x42\x9a\x79\xeb\x5a\xe5\x72\xa2\x51\x1f\x2b\xa9\x3f\xd1\x9e\x79\xe2\x09\x9a\xf9\x13\x53\xc5\x98\xed\x55\x02\x3c\x1f\xd0\x05\xa1\x90\xa2\xb0\x0b\x46\x93\xd6\x66\xab\xe8\x87\x97\xc1\x2f\x3e\xc2\x47\xe0\x03\x92\x52\xed\xcd\x22\xd5\x3d\xaa\x3b\x0d\xd5\xf0\x31\xda\xe0\x17\x1e\xae\x6a\x77\x1f\x96\x73\x32\x7b\x53\x96\xcb\x8d\x72\xae\xaa\x1f\x1e\x10\x1f\xe1\xde\xae\xea\x87\x8f\xd9\xbd\x13\xef\x34\xf4\xc3\xc7\x68\x83\xd9\xab\xe5\x46\x59\x2f\x2b\x27\x3f\x2c\xcb\xa6\x62\xfa\x61\xa3\x50\x93\x37\x52\x79\x15\x49\xf4\x54\xef\xb8\xea\xe0\xa6\xd3\x0c\x1a\x73\xf2\xd5\x3c\xf7\x1f\x35\x76\xfd\xab\x1b\x71\x39\x73\x27\xce\x94\x56\x8d\x8b\x3d\xb8\x30\x35\x91\x27\x93\x0e\x08\x90\x1d\x43\x45\x4b\x9d\xc4\xb3\x52\x48\x71\x51\x51\x9e\x2e\x53\xd1\xa5\x84\x4a\xac\xe8\xb6\xf6\x4b\x4c\x75\x69\x25\xdf\x54\x9f\x56\xd2\xc3\xca\x25\x3d\x4c\x76\x70\xa5\x6a\x8e\x88\x43\xe6\x6d\xa2\x47\xf4\x51\x3f\xf5\x2b\xa1\x7a\x0f\xa9\x81\x80\xa6\x7a\xea\x43\x8a\xa6\xd6\x95\x6c\x74\x57\xbd\x47\x53\x83\x41\x32\x82\x48\xb5\x97\xac\x75\xa3\x59\xb4\xbe\x1a\xfd\x91\x2a\x98\x67\xa8\xa7\x02\x89\x8a\xb5\x05\x5f\xf9\xca\x1e\x9f\x28\x09\x01\xbf\x4f\x1a\xb9\x9c\xcf\xe0\xf3\xb8\xb8\x79\x4b\x5f\xba\x99\x0f\x1a\x56\x17\xc6\xcd\x1d\xdc\xf3\xc6\xe7\xf9\x68\xfd\xd1\x83\x8e\x7a\x6e\xb7\x71\x61\x1f\x42\x8a\xdb\xdd\xc8\xfe\xf5\x79\x53\xd1\xed\x6e\x70\xda\x79\x89\xf8\x7f\x0d\x29\x59\xe3\xb6\x0f\xf3\x8f\x2b\x69\xa8\x4f\x72\x5b\xa6\xdb\xdc\x93\x15\x5d\xc2\xaa\x9b\xd0\x32\x45\xe0\x0a\x4a\x56\x71\x78\x5b\xfc\x8a\xa4\x60\xcc\x79\x37\xdf\xb1\xfb\x47\x4d\x86\xae\x43\xdd\xba\xfc\x68\x71\xf9\xd6\xad\xcb\xa9\xb8\x7c\x2b\xeb\x5f\xbe\x95\xeb\x2f\x1b\x7e\xae\xa4\xbf\x23\x5b\x47\xf6\xc4\xa5\xb3\x04\x15\x32\x26\x9a\xd2\xbe\xb9\x2e\x57\x8f\xbb\xa7\x03\xe4\x8f\xc6\x44\x89\xa4\xec\xd8\xf2\xa5\xb3\x5a\xb4\x7d\x6d\x5f\x9a\x79\xb4\x14\xcb\xb5\xd0\xe2\xb6\x2f\xcd\xe4\x8b\xb1\x9c\xb6\x77\xa8\xb4\xe2\xc5\x19\xda\x37\x04\xaa\x54\x1c\x59\xbe\x95\xcd\x6b\x89\x6b\x1b\x33\x73\x43\xcd\x2d\x71\xda\x9e\x99\x1b\xa2\xa9\xfd\xe7\xce\xd3\x36\x8a\xbc\x87\xaf\x01\x86\x50\x1c\x06\x2b\x89\x86\x6d\x0d\x0c\x22\x1a\xbf\x95\x3b\xba\x71\xcb\x4a\x4a\x68\xfc\x36\x6d\xcd\x36\x2b\xff\x5a\x56\x1f\xaf\x35\xbb\xb0\x3c\x46\x36\x5d\x4d\xfc\x51\x51\x02\x57\x32\xeb\xaa\xee\x1d\x8f\xdf\x29\x1e\xbb\x2f\x7c\xdc\x02\x47\x77\x7d\xc7\xed\xf2\x56\x76\x75\x2b\xf7\xb0\x58\xaa\xe7\x9b\x1c\xf0\xc0\xaf\xf7\x59\xd4\x63\x9e\xc2\x8a\x7a\x32\x9e\xaa\x8f\xa9\xc3\xd0\x1f\x01\x1f\x40\x15\x60\x7a\x98\xaa\x81\x81\x61\x08\x3c\x8e\xaa\xaa\x88\x23\x2a\xa7\x96\xc1\x81\xd4\xa3\xfa\x68\x1c\xd5\x59\x4c\x46\xd1\x58\xbd\xf2\x05\x51\x32\x99\xd0\x60\x07\xa5\xf4\x8f\x92\xf2\xfb\x02\x41\x9d\xe7\x69\x26\xe3\x13\xc8\xa4\xbb\xb8\x5c\x36\x95\x3f\x66\x52\x44\xe7\x29\xb3\x1b\x4e\x39\x75\xc6\xf2\xb3\x3e\x2d\xdc\xf0\x87\xd3\x9a\xce\x9e\x94\x5b\x35\xbf\x29\xe0\x08\xf9\xd7\xce\xde\x78\x47\xa8\x7e\xd7\x63\x1b\x7e\xb8\x7d\xf5\x14\xea\xa6\x89\x7b\x37\x0d\x19\x76\x4d\x5c\x69\xd3\x5e\xee\xbe\x06\x6b\xeb\x42\xc5\x31\xf3\xd3\x67\x35\xc9\xd2\xc6\xf3\xd2\x9d\x97\xcf\xa0\x06\xd6\x73\xa5\xd3\xc2\x77\x9f\x41\xcb\xb8\x15\x73\x37\x7d\x69\xef\x12\xaf\xf5\x24\x62\xa3\xb9\xf6\x8e\xd9\x0b\x4d\x00\x23\x9b\x7a\x9e\x4c\x21\xae\x4f\x15\x85\x9c\x62\xe8\xd9\xe3\xfe\x4c\xf5\xa6\x8d\x0c\x3f\xa0\xe7\xdf\xff\xe3\xe6\x37\x27\xcd\xde\xd2\x7d\xc5\xb6\x07\x9f\x7b\xae\x7c\x50\x0f\x32\x4c\x12\x8a\x9b\xf6\xb2\x33\xdf\xda\xd5\xd9\x49\x3f\xb7\xf6\xef\xfc\xda\x5b\xe5\xaf\x9b\x75\x99\x22\xc6\xe8\x9d\x38\x3a\x5f\x15\x47\x0a\x1d\xe8\xaa\x48\x7a\x35\x5c\x7b\xbe\x6a\x6d\x15\xcd\x45\xe1\x56\x22\xa2\x3b\x10\xd1\xdd\x5c\x74\x06\x45\xa5\xda\x23\xf4\xe6\xc5\x6b\xfd\x5e\xe7\xcc\x15\xde\xb0\xb7\xb3\xd5\x79\xd8\xb0\x39\x1a\xba\x5b\xc4\x11\xf0\x6a\xe5\x62\xbf\xa1\xdf\x93\xaa\xe9\x9d\x37\xf4\xc3\x62\xf9\x1a\x51\xed\xc9\x1d\x41\xae\xa7\x27\x27\x22\xd7\xc3\xbe\x19\xf6\xae\x98\xa9\xaf\xe5\xad\x9d\x16\xc3\x2c\x69\xe8\xfb\x2a\xb5\x50\xd7\xef\xf5\xcc\x3c\x53\xb5\xd2\x55\xb7\xa8\xea\x51\x23\x83\xa0\xbf\x8d\x3e\x9f\x27\xde\x69\xc8\xa9\x73\x2b\xf6\x4f\x7a\x37\x1b\xe2\xb6\xde\x04\xbd\x83\x8d\x9b\x35\x3b\x58\x4a\x0a\x56\x14\x68\xa6\x25\x5e\xd6\x9b\xa8\xdc\x06\x59\xa8\x1e\xa7\x6c\xe6\xb9\xe2\x86\xfe\x0d\xf2\x84\x89\x8b\x37\x54\xbe\xdc\x0f\x56\x7a\xac\xa9\x58\x1b\xd7\xf7\x7a\x78\xd1\xc4\xd6\x70\xf9\xbc\x7d\x4f\x3f\xf8\xc2\x33\x94\xee\x7f\xf0\x85\x1b\xe9\xfc\x3e\xae\x23\x16\x59\xe9\x71\xd8\xc4\xc5\x4b\x3e\x75\x32\xb7\xaf\x7f\xc3\x86\xc5\x13\x27\xc8\x1b\x2a\x5f\x0d\x9e\x95\x91\x58\x87\x9e\xb9\x75\xe2\xa2\x30\xfb\xca\x8d\x2f\x3c\xd8\x4f\xe9\x67\x5e\x78\xf0\xe9\x7d\xda\x97\xfb\xb8\xb6\x58\xca\xea\x59\x69\x13\x17\x9e\xb1\x6c\xa6\xa9\x46\xc0\xb0\x4b\x52\x85\x41\x48\xf0\xa0\x11\xd7\xe3\x69\x1c\xad\xb1\xeb\x32\xdb\x17\x48\xe7\x3d\x23\xae\x9a\x7b\x7e\xfc\x1f\x71\xd1\xcf\x3f\x7f\xcd\x4f\xcd\x25\x3f\x64\xd8\x04\x19\x96\x41\xba\x90\x2f\xc6\x52\x7a\x3d\x46\x76\x25\xa5\x98\xe6\x41\x46\x59\x2c\x93\x0e\x04\xf3\xe9\x60\xbe\x9b\xcc\x12\x02\xc1\x80\xe7\x7f\x93\x99\x53\x0d\x2a\xe2\xee\xee\x5d\xd3\xdb\x73\x71\x8f\xf9\xd6\x54\xa7\xf5\x4b\x75\xfe\x58\xa7\x24\x05\x37\xc9\x75\xb6\x2b\x92\xad\x75\x76\x29\xf8\x9d\x3a\x2f\x05\x63\x13\xae\x92\x1c\x75\xb6\x1d\x92\xad\xcb\x1d\xb4\xef\xb6\x39\x47\x92\x06\x36\xeb\x49\x63\x6d\xb5\x49\x2d\x76\x3d\xa9\x7d\xba\x2b\x58\xb7\xdb\xe6\x64\xea\x5d\x76\x6f\x86\xdf\xc2\x2c\xbd\x4e\x9f\xcf\xe7\xec\xb5\xb0\x2d\x7c\xc6\x6b\xbf\xeb\x2e\x87\x27\xc3\xf3\x5d\x9d\x95\x88\xcc\x04\x91\xdf\xcc\x67\x3c\x8e\xbb\xfe\xd9\xf4\x95\xab\x8c\x86\x0d\x26\x3c\xd7\xd3\xc3\xe7\x2a\x0e\x6d\xc7\x53\x36\x99\xea\xe3\x13\x26\xcf\xaa\xb3\xda\xa5\xe6\x4d\xd2\x32\xd9\xbe\x6e\x52\xbd\xcb\xf6\x45\x9b\xff\x53\x92\xe5\xb3\x8d\x56\x9b\x73\x51\xa0\x5d\xa9\x27\x4f\x5d\x6d\x52\x4b\xf3\x55\xd2\x32\xaf\x73\x5d\x47\x4d\x52\x4b\x9d\xbb\x37\x30\x39\x16\x64\x9e\xf2\xc0\x76\xb7\xab\xb1\xe1\xb2\x06\x9e\x9b\xbb\xc2\xcf\x98\x7f\xc5\x5c\x8e\x6f\xb8\xac\xa1\xd1\xe5\xde\xee\x76\x35\x05\xf5\x08\x96\x88\x9c\xe3\x67\x6c\xee\x04\x36\x47\x8f\x0b\x36\xb9\xb8\xc1\xff\x49\xae\x11\xbb\x11\x83\x17\x4e\x1a\x56\xaf\x6e\xd1\xe0\x86\x8d\xeb\x80\x94\x94\x92\xed\x12\x0a\x5d\xbc\xa1\x22\xc8\x27\x22\x3c\xf9\x44\xa9\x99\x0f\x36\x8b\x3a\xa5\xa5\x94\x94\x92\x12\xe3\x11\x7d\xc4\x26\x0a\x5d\x94\xcb\xa6\x9a\x49\x50\xf7\x6b\xdf\xfd\xf7\x4f\x2e\xbb\xe6\x9e\x44\x9a\xab\x93\x19\x11\xc7\x04\x4e\x24\x21\xe1\x6e\xf2\xdb\xae\xb9\x6d\x3f\x9d\x4a\xd7\xd1\xa9\x6c\xfa\x6d\xd7\xd8\xfc\x4d\xee\x84\x40\x22\x27\x30\x8e\x88\xf3\xd9\xd3\x89\x7b\xae\x59\xf6\x49\xed\xd0\x4f\xa6\x36\xdf\x4f\xad\x1b\xaf\xbd\x29\x78\xc3\xdd\xdc\xad\xda\x5f\x0e\xde\xec\x5e\xda\x6a\x95\xdc\x0e\x4e\x12\x45\x5e\xe2\x24\x12\x15\x7f\xb2\xb5\x7e\xde\x2f\x37\xdd\x7a\xf0\xe6\x9b\xcb\x37\x6f\xfe\xc5\xbc\xfa\xd6\xa4\x5f\x11\x49\xe2\x24\x5e\x14\x25\xce\xe9\x26\xc9\xda\xba\xd4\xbd\x95\x5f\xb6\x64\xf9\xe0\x4d\x0b\x7b\xe6\xbe\x32\xc2\x77\x1b\x67\xe7\xa6\x63\xfd\xe8\x6d\x33\x94\x55\xe2\xd1\x6c\x3e\x97\x55\xe2\x23\x92\x90\x27\xa3\x73\x46\xba\x88\x99\xcb\xa6\xba\x28\x9b\xd2\xa3\x53\x5d\x54\xf0\x19\x23\xc3\x78\xc4\x36\xa6\x23\x69\x74\x3e\xd5\x07\xa5\x2e\x39\x65\xd2\xcd\xfa\x08\xcc\xa4\x03\x64\x5e\x49\xc3\x3f\xb2\x28\xad\xf5\xf7\x15\xfb\x42\xf5\xc9\x09\x81\x02\xaf\x34\xb4\x27\x26\xa4\xdc\x91\x88\x23\xd9\x34\x29\x38\x59\x78\xf9\xc6\xab\x4b\x42\x73\xdc\x9b\xf3\xb9\x22\x6d\xea\x14\xab\xc2\x4d\xa7\x47\x3f\x9f\x38\xa7\xef\xbb\x9f\xde\x18\xd0\x06\xf4\xf9\x93\xbc\x89\xd5\x53\xa7\xd4\x07\x95\xb6\x54\x66\xc9\x4d\x73\x26\xef\x5b\xb3\xdb\xbc\xb3\x86\xa9\x99\x85\x53\x7f\x36\x6d\xe5\x8a\xd0\x55\x9f\x6d\x0b\xce\x16\xd2\x91\x5c\x3c\xe1\x2d\xab\xa2\xe4\xb2\x78\xd8\xfc\xaf\x86\x9a\xdd\xf3\x17\x44\xd2\xa7\x36\xcc\xf0\xd0\xf2\xc4\xa7\x16\x44\x13\x0b\x67\xf9\x03\xab\x17\xde\x7a\xff\x49\x6d\xad\x3d\x39\xa6\xe6\x7a\xea\x6f\xec\xc9\x35\x5c\xbd\x75\x62\xf2\x94\x5b\xae\x3c\xe7\xfc\xdd\x18\xb9\x83\xc9\xb0\x25\xed\xd2\x65\xcb\x9a\x19\x2d\x65\xf4\xb5\x81\x8f\xbc\xa9\x31\x91\x9c\x82\x89\x31\x21\x18\x08\x36\xb3\xa0\x3e\x91\x2b\xb9\x68\x3a\x5f\xd0\x57\xc4\xea\x34\x67\x98\x8d\xa6\x94\xd4\xe8\xf2\x53\xe8\x22\x7d\x0a\x93\xfc\x23\x28\x1d\xc1\x57\x5b\xc4\xe5\xcb\x79\xe3\xcd\xc2\xca\xb3\xd4\x1b\x5f\x16\x26\x07\x27\x35\x25\x1d\x91\x88\x3b\x35\x21\xd1\xde\xa0\xf0\x85\xc0\x84\x64\x7d\xa8\xaf\xd8\x47\x7d\xe9\x45\xea\xee\x35\xfb\x26\xc7\xe3\x37\x2d\xc9\xa4\x62\xad\x75\xf5\xf2\xe4\x69\xab\x13\xda\xbb\x06\xd2\x22\x81\x8d\xea\x33\x17\x6d\xd8\xfe\x75\x9a\xce\x29\xd6\x29\xbc\x79\xc8\x52\x43\x7c\x39\x79\x66\x34\x9c\x9a\x6e\x51\x92\xf3\xdd\xcd\xa1\x4f\x9c\x31\x9f\x79\x2c\x2e\x49\x2c\xab\xde\x44\x3c\x17\x49\x0b\xb3\x83\x6d\x9f\xbd\x2a\xb4\x62\xe5\xb4\x9f\x4d\x5d\x98\xbe\x70\xf7\xf9\xe7\x5c\x35\xfb\xd4\x53\x92\xd1\x95\x67\x7e\xd2\x9f\x5e\x78\x63\xbd\x89\xb7\xd6\xf6\xf6\xfb\x6e\x16\x16\xae\x0e\xf8\x67\x2d\x4c\x44\xe7\x57\x78\x82\xaf\x73\x45\x43\x26\x07\x79\x8e\xb9\xdd\x97\x2b\x8e\xbf\xbd\x57\x18\x38\xf2\xa3\x63\xaf\xe7\xad\x1d\x9b\x2a\xc2\x38\x19\xa0\x6c\x07\x67\x48\xea\x3a\x22\x63\x4e\xce\xef\xd3\x65\xa2\x42\x85\xcf\x1c\x77\x67\xb2\xa8\xb6\xcd\xea\x5b\xbe\x66\xf3\xea\x79\xf5\xde\x2e\x6f\xfd\xbc\xd5\x9b\xd7\x2c\xef\x9b\xd5\xf6\x5d\x76\x2a\x9b\xbd\x5f\x7d\xb3\x7c\x87\xf7\x04\xf7\x29\x73\x8f\x9e\x7e\xcd\xfc\x0e\x77\x66\xe1\xac\x70\x20\x10\x9e\xb5\x30\xe3\xee\x98\x7f\xcd\xe9\x7b\xbe\x5b\x7e\x89\x4d\xda\xbf\xe7\xb7\x6f\x96\xf7\x78\x8f\x77\xdd\xf2\xa8\x9d\x6a\x44\x00\x5a\x75\x7e\x2e\xe9\x0b\x38\x59\x2d\xaf\xe1\xaf\x04\x54\xec\x34\xa7\xb2\x66\x6e\x64\xc7\x6c\x24\x99\xb9\x43\xc6\x54\x46\x82\xcb\xa1\x19\x56\x9a\x54\x74\xc8\x15\xef\xcc\x15\x2b\x66\x52\x84\x7c\xa2\x47\xb4\xf1\x5c\xbf\x5c\x1e\x90\xb3\x8a\xb1\xf7\x13\xa2\x92\x92\x95\x59\xa4\x8f\x8f\xf8\x43\x0e\xd3\x30\x5d\x76\x18\x9e\x15\x33\xcb\xc5\x99\x2b\x18\x2f\xd5\xb1\x74\x56\xcf\xa2\x84\x28\x52\xb9\xe3\x20\x12\x52\xe4\xf2\x40\xf5\x1c\xb0\xc9\xeb\xba\x90\x44\x0e\x28\x64\x3c\xf1\x42\x07\x19\xab\xb6\xb9\x2b\xe0\xd1\x79\x2d\x29\x93\x8b\x07\xb8\x8c\xc7\x5c\x88\xfd\xe3\xd9\xd0\x77\xfe\xfc\xe7\xf7\x69\xce\xc6\xf9\x73\x4f\xa6\x69\xf3\xd8\xfc\x3f\xef\xdc\xbc\x6d\x3e\xfb\x33\xc7\xfd\x59\x72\x4d\x6f\xdf\x48\x07\x6a\x59\xcf\x2d\xec\xdb\xaf\x64\x67\xcf\xce\x66\x4e\x3d\x75\xe8\xab\x74\xdb\x3d\xf7\x5d\xb9\x7a\x66\x79\x3b\x6d\x55\xbc\xf1\x29\x5f\x66\x57\xd4\x72\x9b\x86\xee\xdb\xb8\x33\xa5\x0e\x1d\x3a\x65\x19\xec\x84\xc7\xe0\x27\x74\x00\x38\x27\xb5\x51\x2c\xc5\x19\x12\x50\x3e\xe3\xa9\x08\x77\xba\xc4\xe7\x49\x07\x68\xc0\x1b\xf6\x7a\xc3\x5e\xd6\xaf\x84\xb4\x33\x33\xcc\x63\xa7\x46\xa1\x57\x5b\x17\x52\xbe\x7c\xfe\xc8\xd5\x8b\xd9\xf3\xbf\xcc\xfa\xc9\x30\xed\x30\xee\x25\xd3\x1e\x0b\x29\x5a\x93\xdd\xd3\x48\x6f\x2a\xa1\x4f\xff\x88\xc1\x94\xf3\x34\xfc\x68\x44\xfe\x32\xfe\xcf\xe0\xf1\xee\xff\x6d\x32\xef\xf7\xad\x35\xf4\x1f\xb9\x85\xf1\x78\xfb\x7e\xa3\x26\xb9\xcc\x00\xa0\x5c\x1c\xb1\x3f\x36\xae\x47\x53\x95\xac\xbc\xaf\xbc\xd1\xdc\xfe\x63\xdb\xf7\xc9\xa6\xa9\x22\xeb\xd3\x4a\x55\x43\x5c\x23\x61\xd5\x08\xd7\xb8\x90\x91\x3b\x43\x43\x48\x31\xf2\x19\xbb\x80\x7a\xbe\xac\xa2\xd4\xdc\x31\x15\x34\xfe\x97\xf0\xf1\x69\xd0\x3a\xd2\xa6\xac\xd2\xc5\xaa\xa7\x15\xe2\xd1\x89\x4c\x67\x3e\xcd\xa0\x00\x7f\x3c\x12\xa4\x2b\xf6\x6e\xd2\x4a\x15\x9a\x25\xa3\x25\xda\x40\x85\x66\x2b\x61\x9b\xf6\xea\xe2\xd7\xf1\x48\x91\x32\xe5\x62\x0d\xe5\xb2\x92\x49\xb9\x16\x93\xac\x47\xe4\x7d\x15\x22\x1c\x98\x0f\x90\x92\x8b\xfa\x7d\x81\x64\x2e\xea\x93\xba\xa8\xe0\xf7\x99\x2b\x18\x19\x1b\x3f\xd5\x7e\x30\xf7\x48\x8c\x59\x39\xa5\xa4\x3a\x2a\x8a\xa5\x5c\x8d\x54\x4c\x3f\x5d\x30\x8c\xa7\xf9\x1f\x0c\x63\xc1\xe7\x9f\x56\xcf\xfc\xfc\x0b\x97\x4d\xcc\x29\x4d\x33\x66\xf5\x5c\xe9\x75\x0e\x95\x9c\xde\x2b\x7b\x66\xcd\x68\x52\x72\x13\x2f\x7b\xe1\xf3\x67\x76\xb6\x52\x64\xc5\x4c\x56\x9c\xb9\x82\x22\xad\x9d\xec\xf3\x0f\xfc\xa2\x6f\xd1\x9e\xf7\xfb\x7e\xf1\x40\xd3\x9e\x17\xd5\xb9\x3b\x36\x9e\x26\xe4\x27\xc4\x16\x66\xf2\x0b\xce\x3e\xd5\xbc\x61\xe6\xd4\xb3\x17\xe4\x33\x0b\x63\x13\xf2\xc2\x69\x1b\x77\xcc\x55\x5b\x3b\x4d\x1d\x66\xa7\xf9\x0f\xf5\x46\xce\x2c\xe8\x92\x4d\x0b\x52\x68\x47\x1a\x37\xe0\x0e\x80\xf2\x29\x45\x12\x83\x01\xf3\x5d\xc8\xa7\x2a\xfe\x60\x5e\x49\x29\xc6\xd7\xf0\x37\x53\x36\x1e\xf3\x15\xf4\x90\x3c\x65\x11\x81\xdf\xe7\x0d\x06\x74\x59\xc2\xc9\x3a\xc8\x68\xb0\xb1\x22\x07\x9b\xc9\xb8\x80\x4a\xef\xbf\x82\x52\xc8\x07\x5a\x74\x89\xbc\x8b\x05\x03\xfa\xda\xe3\xe4\x24\xf3\xa8\x76\xa0\x90\xf7\x8e\xa7\x67\x26\xf1\x92\x55\xe0\x25\x6b\x50\x90\x44\x51\x12\xc4\x49\x4c\x92\x88\x93\x2c\x01\x46\x9c\x68\x11\xc4\xb3\x59\x9d\x95\x67\x75\xd6\x0e\xbb\x6d\x06\x0b\x30\xe6\x63\x9f\x31\xcf\x3a\xfc\xf0\x1e\xaf\x87\x44\x39\xdb\xde\x66\x09\xc6\x98\x50\xc7\xd5\x39\x45\xef\x44\xbb\xbb\xad\x3d\xe2\x94\x42\x53\x16\xcc\x4b\xe5\xea\x9b\xe4\xb9\x0d\xa1\xa9\xdb\xa7\xd6\xc5\x7b\xe5\xa6\xfa\x5c\xb8\xad\x38\x43\x89\x93\xc7\x7b\xcf\x0f\x09\xb5\xf3\x05\x2d\x16\x25\x49\x10\x25\xa9\x43\xe2\x78\x8b\x85\xe3\xa7\xf0\x3c\xe3\x05\x8e\xc9\x24\x31\xc9\x22\x89\x73\x25\x9e\x93\x24\x9e\xe3\xdd\x6e\x97\xc4\x4b\x16\x9e\x4e\x35\x8e\x86\x1c\xf8\xaa\xf6\xf7\x2c\xe7\xb6\x67\xdb\x88\x23\x6b\x4b\x68\x9a\x8b\x84\x3a\x8b\xc4\x37\x06\xc2\x61\x49\x9c\x14\x10\x1b\x72\xe7\xcf\x39\x6d\x6a\xd7\x02\xb1\xd1\xed\xf6\x78\xa4\x40\xb3\xb8\xa0\x6b\xea\x69\x27\x9f\x95\x4b\xb8\xf9\x96\x62\xeb\x4a\x66\x77\x73\x59\xaa\x63\x9f\xab\x9d\x93\xaa\x77\x27\x94\x8c\xbe\x33\xe6\x81\x8f\xbe\xbf\xcf\xb8\x68\x33\x5f\xd0\xc9\xcd\xdc\x5f\x37\xa3\xa2\xb1\x94\x52\x51\xc1\x9d\xe8\x06\xbf\xaf\xf9\xcf\x9f\x41\x98\x71\xbe\x9f\xbe\x66\x5c\xe2\x37\x71\x18\xa6\x9d\xea\x30\x26\x7a\x3c\x2d\x54\xf2\xe6\xbd\x54\x6a\x51\x4e\x70\x89\x5f\xe7\xbc\x79\x9d\x9d\xac\xaf\xb5\x3a\x4c\x5b\x53\xcd\x54\x92\xe5\xff\x8f\xb7\x37\x81\x6f\xa3\x3a\xf7\x86\xcf\x73\xce\x2c\xda\x66\x24\xcd\x68\xb3\x2c\xcb\x92\x65\x49\x5e\xe5\x44\xab\x1d\x6f\x8a\xb3\x91\xd8\x49\x9c\x95\x40\x42\x62\xb2\x11\xcc\x96\x00\x21\x2c\x59\xa6\x90\x02\x21\x14\x02\x29\x21\xa5\xa5\x31\x94\x16\x28\xe5\x96\xd2\xdb\x85\x36\xb4\xba\x2d\xa5\x7d\x4b\xa1\x84\x0b\xb7\x1b\xed\x35\x5d\xb8\xb4\x85\x96\xb7\xbd\xb4\x25\xb6\xc6\xdf\x6f\xce\x68\xb3\xe2\x10\x7a\xbf\xf7\x7d\x13\x6b\xe6\xcc\x99\x73\x66\xce\x36\xe7\x3c\xe7\x59\xfe\x8f\x9a\xf5\x97\xd6\x59\x76\x8a\x55\xd0\x6c\xb4\x45\x5b\x67\xa9\x69\xb2\x46\x0f\x52\x31\x30\x35\xcb\x17\x41\xfb\xaa\xb0\x93\xaa\x74\x38\x8a\x86\xe1\x1a\x01\x23\x65\x1c\x58\x07\xfa\xd1\xd3\xd2\x8c\x3a\x8f\x4d\xd7\x18\xd4\xd3\xd2\xa1\xe5\xc7\x6e\x3f\xb0\x07\x44\xb3\xc5\x64\x30\x99\x18\xa3\xbc\xcc\xd1\xf3\x56\x77\xeb\x25\xf3\x3a\x0f\xcd\x1d\x39\x30\xbb\xc6\xe5\x71\x79\x2e\xae\xe9\x7a\xa3\xeb\x2b\x97\x7c\xe4\xb5\x3d\xca\x9d\x93\x9f\xdc\xfb\xc3\xae\x5f\x77\x7a\x2e\xae\x59\xbc\xcd\x55\xd3\xb8\x58\x59\xbb\xec\x81\xef\xdc\xd8\xf3\x5f\x73\xe4\x21\xc7\x8a\x25\x26\x86\x58\xb0\x4d\xc2\xcf\xb7\x1d\xae\xf5\xfb\xda\xbd\xee\xf5\xae\xb0\x04\xc6\x59\x6e\x8f\x2b\x3d\x7b\xf1\xef\xff\xfc\x91\xa6\xb1\x66\xf7\xf9\x6d\x75\xae\xfa\xc6\xf6\x9f\x80\xe3\xf0\x67\xd5\x6f\x4e\x64\xda\xea\xea\xae\x5a\xec\x59\xe7\x6e\x7a\xa8\xf9\xaa\xd7\x5e\xfa\xea\xdc\xee\xde\x65\xb3\x4c\xdb\x56\xbb\x2f\x74\x0b\x1e\x63\x80\x69\x7a\xb0\x52\x17\x62\x39\x42\x1a\xc9\xaf\x83\x64\x51\xe2\x0d\x69\x9f\x13\x53\x00\x2f\xa2\xd8\xb2\x5a\x9d\xb0\x36\xed\x14\xaa\xe7\xf6\x13\x1d\x3a\x4b\x0b\x62\xb7\xcb\xed\x62\x15\x87\xd9\xb9\x6d\xe3\x86\xda\x64\x7f\xfd\xb0\x71\xf3\xd2\x03\xea\x9f\x96\xcf\x0a\x11\xbf\x59\xe2\x13\x9d\xf1\x9a\xf3\x6b\x45\x5e\x0a\x99\x23\x01\x2b\xa9\x13\xbb\xe6\x75\x99\x78\x27\x0c\x3d\x77\x08\x37\x88\xb5\x46\xa9\x33\xde\xe3\x10\xeb\x5a\x98\x9a\xae\x85\xf2\x42\x8e\x40\x53\xed\xf9\x35\xf1\xce\x04\x2f\x99\xfd\x24\x34\x6b\x39\x48\x07\x96\x6e\x36\x0e\xd7\xf7\x27\x6b\x37\x6c\xdc\xe6\x34\x3b\x08\xb7\x50\x5e\xd8\x55\xc3\xb4\xd4\x89\x8e\x9e\x78\xa7\x64\xac\x15\x1b\xf0\xa1\xe7\x86\xc0\xc9\x9b\xba\xe6\x75\x89\x75\xc4\x1a\x88\x98\x43\x12\x5f\x5c\xc3\x4a\x18\xb2\xe8\x5c\x86\x69\xcc\x48\xd9\x3e\x64\xe3\xaf\xca\x26\x24\x7b\x1e\x67\x51\x71\xdd\xd1\xee\x8d\x95\x6f\xe8\xeb\xb6\x8e\x61\xc2\xe9\x78\x86\x76\xc8\xb8\x41\xfe\x40\x30\x13\x65\x12\xc1\xa3\x17\x5c\x00\x8f\x5a\xce\x8a\x6a\x82\x26\x22\x70\x6c\xcd\x1a\x75\x94\xbd\xf0\x83\xf1\x4d\xca\x3c\xb6\x45\xe8\x7c\x4a\x43\x32\xd1\x18\xd6\x85\xff\x31\x1c\x8d\x41\x49\x01\x40\x0b\xb2\xa1\x06\x1d\x0b\x9a\x71\xbb\x90\xdb\xcf\x52\xc0\xbe\x33\x19\x6d\x4c\x60\x76\xac\x9d\x63\x7d\x2e\x93\xb5\xb5\xb1\x59\xe0\x65\x8b\x8b\x6c\xb9\xab\x13\x0b\x1c\xdf\x3c\xbb\xd9\xe4\x20\xc4\xe3\xad\x75\x9b\xcc\xb3\x52\xb1\xf9\x2c\x2b\xf0\x12\xee\x81\xae\x47\xb8\x59\x52\x73\x4d\xa3\xad\xeb\xa8\xd3\x55\x35\xad\x9d\x6f\x36\xb9\x6b\xbd\x1e\x42\x1c\xa6\xe6\xd9\xcd\x3c\x27\xe0\xcc\xdd\x5b\x88\xcb\x22\xf3\x42\x73\x63\xab\xd5\xe4\xf2\xb1\x5c\x7b\x6c\x76\x80\x71\x39\x8f\x76\xd9\x1a\x6b\x9a\xa5\x59\xdc\x23\xea\xf7\x7b\xb0\xc4\x0b\x2c\x3b\x3f\x96\x22\x5d\x95\xf3\x12\xa0\x36\x84\xb8\xd5\x2c\xa2\xf2\x78\xca\xc9\xc0\x22\x30\xfa\x4e\x35\x13\x83\xc2\xa9\x17\x5c\x6e\x2a\xfb\x76\x31\xee\x02\xbe\x56\x3a\xc3\xf1\x69\x6e\xf5\xbc\x4d\x30\xf4\xc9\xff\x50\x5f\xf9\x82\xfa\xbf\xdf\x08\xb5\xbe\xf1\xd4\xa5\x9f\xab\x0f\xfa\x5a\x5b\x76\x1e\x9d\xbf\x6c\x60\x59\xdb\x0d\xb0\xfe\x79\xc3\xb3\xb7\xde\x39\x72\xc5\x48\xf8\xd2\x8b\x98\x1d\x9b\x17\x88\xbe\x9b\xd5\xfc\x9f\xbe\x76\xc5\x3d\xcc\x1d\x78\xdf\xc5\xac\xd9\xfd\xa5\xdd\x4c\x84\xb4\xdd\xb5\x6a\xdd\xe0\x7d\x5f\x36\x45\x1a\x6f\x7d\x76\xbb\xb3\xeb\x9a\x7e\x13\xdd\x1f\x6c\x9a\x52\xc8\xb7\x39\xa4\xf3\xbf\x29\x87\x30\x48\x42\xf6\xa0\x3d\x64\xd7\x65\x6d\xe4\xdb\x0f\xae\xed\x81\x70\x54\x55\x5f\x9a\x42\x53\x2f\x3f\x79\x94\xfd\x6f\xf5\x1f\xe7\x9d\xf7\xac\xfa\xd3\xbc\x11\xff\x1d\x9a\x7e\xfe\x8d\x17\x75\x5b\xe7\xa9\x47\x69\xbf\xae\x46\x1b\xd0\x56\x74\x19\xba\x06\xdd\x88\x6e\x46\xb7\xeb\x5a\x36\x4e\x07\xe2\x39\x7d\x2a\x8a\xf6\x31\xda\x6e\x2d\x1a\xe1\xac\x10\x69\xe0\x63\x98\xe7\xdc\xda\x54\x44\xdc\x1a\x99\xd0\x10\x89\xc6\xa0\x03\x1a\x38\x3f\xd4\x03\xfd\x91\x7e\xa0\x93\x5c\x34\x82\x52\x49\x49\x2e\x2d\xb9\x95\xe7\x69\x97\xda\xd2\x9c\xe4\x1b\x9c\x8e\x4c\x3c\xa3\xdd\x2b\x2a\xee\xa8\xbf\x78\xab\xd6\x0b\xc9\xae\xf5\x17\xcf\x6d\x5e\x1e\x6e\xf7\x8d\x46\x23\x17\x3d\x7f\x91\x2d\x75\xb5\xaf\x3d\xbc\xbc\x39\x7b\xf1\xfa\xae\xa8\xc9\x39\x6b\x60\xae\x5b\xee\x76\x38\x9c\x36\xce\xc2\xf3\xae\x56\x93\x49\xe8\x3b\x6f\x9e\xcb\x0d\xde\xda\xb7\xd4\x5f\xbc\xb4\x86\x98\x4c\x84\x98\x8c\x21\xde\x68\xe2\x78\xa3\xa9\xd1\x68\x34\x18\x8d\x52\xdc\x60\xb1\x18\x8c\x82\x65\x2e\xb1\x59\x0d\x76\xeb\x3c\xbb\xcd\x6e\x9b\x83\x6d\x36\x26\x40\x35\x81\x4e\x4d\xa8\x57\x2d\x65\x3d\x12\x39\xda\x7b\x71\x3b\xe7\x49\x2f\xbf\x65\xcd\x9e\xf3\xd7\xef\x32\x36\x79\x3c\x5e\xaf\x39\xd0\x6e\xdc\xb5\xfe\xfc\x3d\x6b\x6e\x1e\x4e\x7b\xb8\xc6\x79\x26\x53\x6b\x73\xa0\x89\x21\x46\x51\x64\x59\x53\xa7\xdb\x1d\xe9\x10\x80\x61\x22\xdb\x18\xc9\xc3\x2e\x85\x7b\x26\x4e\xc1\xc5\x93\x07\x78\x96\xb0\x3c\xcb\x79\x59\xb3\x91\x63\xcd\xa6\x08\x6f\x11\x78\xd6\xdb\x68\x30\x5b\x8c\x06\xb3\xc5\x66\x66\x19\x17\xc3\xf1\x02\x36\x0b\xd8\x69\xc6\xc4\x63\x98\x26\xeb\x08\x4f\x43\xa6\x8e\x68\x9d\x9e\x98\x8e\xd7\xa3\x51\x63\x28\x80\x38\x25\xe2\xcd\x7a\x23\xc7\x5e\x3d\x36\x52\x76\x32\x80\xc7\x74\xcc\x1d\x92\x2b\xda\x1a\x8c\x1e\x3b\x36\x9a\xeb\x6c\xaa\x40\x3d\x7c\x06\x78\xf5\xfd\x12\x76\xba\x3e\xa7\xd5\x14\x70\xc8\x50\x15\x36\x50\xc2\x49\x47\x5d\x2a\x19\x09\xd9\xa9\x3d\x84\x36\xe9\x65\x52\x41\x67\x22\x15\x74\x72\xe3\xda\x3c\xa6\x1b\xd9\x0a\x32\xa7\xc8\x82\x20\xbf\xaf\xc8\xc2\x08\x20\x05\x14\x56\xd9\x38\x50\x36\xab\x55\x64\x61\x7c\x5c\x90\x27\x90\x2c\xe0\x91\xfc\x98\x20\x2b\xda\x3f\x5d\x27\x86\x2d\xfa\x4b\xea\xad\xb0\x00\x76\xe9\x4c\x4e\x6d\x19\xa1\x5c\xcd\x4c\xba\x1b\x5c\x8c\xdb\x25\xb1\xa5\x3b\x18\x35\x96\xef\x59\x28\x0e\xbd\x6e\x10\x8c\x77\x62\x59\xaa\xbb\xad\xa6\x11\xbb\xd4\x6f\xfe\xae\x26\xe8\xb4\x7b\xd9\x31\x68\xdc\x75\xf5\x6d\x58\xc0\x0e\xc9\x77\xb7\x37\x0c\x96\xa7\xd5\xdf\xa8\xfb\x7e\x52\x13\x72\x48\x5e\x02\x1c\xfc\xe7\x37\xbe\xf9\x1f\xa0\x5b\x09\xab\xdf\xf3\x39\x9c\xc1\x9a\xdf\xc1\x02\x17\x6e\xac\xb9\xad\x4e\xb2\x0b\xb7\x5d\xbd\x4b\x7d\xfd\xe1\x5a\x87\x23\x54\xf3\x13\xb8\x05\xea\x9e\x16\x20\x5c\x73\xb7\x4f\x92\x84\xff\xf8\xe6\x37\xd4\x60\xc1\xce\x14\x15\x64\x6b\xf5\xa8\x59\xa3\x70\x50\x95\x7c\xcd\x5d\xed\x5b\x26\x58\x84\x5f\x86\x19\xd1\x6a\x19\x5b\xc7\x40\x47\xc7\x00\x74\xd0\xd3\x89\x4a\x83\xe5\x89\x38\xf3\xa9\x07\x19\x8f\x38\xf9\x17\xd1\xc3\x30\x5f\xd2\x5b\xda\xf6\x3d\xfb\x86\x0c\x11\x33\x1b\xec\xdf\xb3\xc1\xc5\x03\x7a\x36\xed\xef\x5d\x28\x23\x66\xc1\x3b\xf0\x6b\xc1\x6e\x17\xf2\xfb\x0b\x5b\xe4\x6c\x4d\x1c\x6f\x4c\x0d\x0c\xa4\xf2\x0f\xc7\xe9\x1a\x70\x0b\xe5\x23\xc4\x50\x92\x8e\x06\x6d\x57\xe8\xe0\x42\x28\x2c\x82\xcb\x2d\x82\x1f\xbb\x45\xd0\xd6\xf5\x74\xa6\x84\x76\x1e\xd0\x06\x0d\xb1\x23\xd6\xce\x70\x4a\x6a\x70\x30\x35\x94\x54\x37\xa9\xbb\xe7\x0c\x30\x11\x07\x27\xcd\xee\x88\xd4\x7d\xf6\x0b\x31\xbe\x5d\xae\x25\x26\xfb\x8d\xf4\x9d\xe3\xf0\x65\x78\x31\x39\xa4\xa8\xd7\xa9\x77\xc0\x0d\x44\xa1\x7c\xdf\xe4\x10\xac\x0f\xca\x1b\x2f\x8b\x06\xe7\x26\xba\x9b\xfd\x73\xe2\xb5\x2d\xee\x8f\xf4\x5c\xb7\x7a\x57\x7a\xe3\x40\x6e\x60\x23\x28\x43\xc9\xc9\x46\xf2\x0d\xf5\x95\x66\xf5\x2f\x2d\x94\xef\x94\x9d\x42\x5c\x8e\x43\xc8\x8c\x6a\xd0\x5c\x84\x98\x24\xa5\xa9\x1a\xb4\xfd\x0c\x04\x91\x3d\x19\xc3\x0d\x22\x76\xda\xe8\xc6\x86\x3a\x28\xd0\x9a\x58\x9b\xe3\xa4\x8c\x8e\xea\xe9\x74\xf0\x2e\x49\x9b\xe0\xc8\x11\x5b\xf7\x9a\xc0\x25\x8b\xf3\xd7\xb1\x0e\xf5\x6f\xb3\x2e\xfc\xc4\x37\x3e\x71\xe1\x2c\x26\x37\x94\x54\xb3\xc7\x5e\x3d\xa6\x66\x93\x43\xf1\x95\xeb\x7a\xa3\x7f\xf8\x96\xa1\x73\xb8\xd3\xf0\xad\x3f\x44\x7b\xd7\xad\x7c\x2a\xb0\xa6\xdb\x66\x5b\x7c\x09\xcc\x82\x36\xec\x48\x5c\xbe\xb9\xbf\x7f\xf3\xe5\x89\xfc\xdb\xea\xab\xc9\x21\xed\xab\x1b\x4a\xb6\x6c\x38\xfa\xf9\xbf\x1c\x3e\x0e\xac\x4f\x76\x68\x9f\x9f\x43\xf6\xa9\x13\xc7\x0f\xff\xe5\xf3\x47\x37\xd0\x6f\x1e\x4f\x29\xac\xca\xee\xa3\x7b\x33\xb7\x8b\xe7\xac\xf4\xd8\x01\x3a\x15\xa5\x9d\xa3\x11\xfd\xd8\x4f\x59\xa8\xda\x31\x93\xd6\x8f\xf5\x14\xf5\x51\x3b\xba\x5d\xfa\x51\xcb\xed\x76\xf1\xec\xc8\x1d\x7e\x93\xa5\xe9\x64\xca\x52\x5f\xd7\xfc\x8d\x59\xa6\x66\x0b\x5f\xef\xb8\xed\x36\x5f\x4b\xb3\x69\xd6\x37\x9a\xeb\xea\x2d\xa9\x93\x4d\x16\x93\xff\x8e\xaa\x54\xcd\x75\xb7\xdd\x56\xd7\x3c\x3d\x0d\x56\xaa\xb2\x61\x97\x96\xcd\xdc\x5c\xce\xd6\xe2\x9b\xfe\xe8\x66\x93\xa5\xfe\xf0\x61\xbf\xd9\x34\x2d\x4d\xc9\x27\x99\xf6\x9d\xa7\xd0\x8e\x6a\x7e\x2a\xd5\x2a\x0c\x35\xf0\x1c\x5f\x90\x6e\xd8\x35\x9a\x30\x31\x8d\x9f\x5a\x64\x11\x72\x05\x86\x6a\xc1\x92\xb7\x48\x6b\xf4\xb1\x1a\x9d\xc9\xe8\x52\x9f\x60\x89\x9b\xca\x7e\x6e\x59\x3c\x9f\xf3\x37\xfa\x2f\x58\xe4\x19\xf0\x08\x4d\xe7\x2d\xf2\x2f\x58\x14\x08\x9c\xf7\xad\xef\xad\x78\xb6\xc0\x45\x85\xc1\xe4\x90\x72\xff\xa5\x8f\x33\x41\xca\x49\xfd\xe8\xb3\x8f\x74\x17\xd8\xa8\x01\x93\xdb\xe3\xac\x15\x3d\x78\x6e\x48\x68\x6a\xe8\xe8\x8f\xec\xfb\x8c\x0b\xae\xab\x64\xa6\x3a\xba\x52\xab\x5a\xe7\xf5\x1e\x6e\x73\x66\x57\xac\xa8\xe9\xca\x2b\xd9\x6c\x25\x13\x75\x28\x75\xe9\xf1\xbe\x2e\x9d\x83\xba\xa0\x5b\x67\x04\x1a\x65\xbb\xcf\xea\x23\x4b\x32\xce\x95\x7d\xd9\xd0\xad\x37\xce\xef\x39\x8e\x2a\xda\x27\x85\x7a\xd1\x2e\x84\xc2\x09\xbb\x8e\x4b\x44\xff\xc7\x18\x2a\xb8\xf3\x63\x27\x75\xd6\xe6\x4a\x04\x35\xd2\xcb\xcd\x39\x5c\x6e\x5d\x6d\xb3\x0f\xaa\xb6\x51\x74\x97\xd1\x0f\xba\x20\x46\xdf\x6a\x24\x82\x3a\xe9\xe2\x27\x1a\x29\xce\x51\xfa\x6c\x24\x10\x08\xcd\xed\x69\xaa\x33\x30\xe7\x35\x89\x1e\x90\x25\x97\xd3\xb0\xe8\x02\x7f\xa3\x3f\x9f\x8b\x2f\x1b\x4a\xc2\xa0\xce\x59\x65\x2e\x3e\x7f\xf5\xf3\xdf\x82\x1d\xfa\x56\x6b\x30\xa5\x8e\x77\x3f\xf2\xad\x03\x77\x3d\x05\xd0\x4b\x82\xcc\xe3\x97\xde\x7f\x7c\x07\x5c\xe7\xfa\xcc\xbe\x48\x7f\x47\x43\x93\x10\x9a\x8b\x3d\x62\xad\xd3\xe3\x36\x41\x20\x35\xa8\x60\xc5\x13\x6f\x09\x1a\xd9\x15\x59\x57\x8c\x44\x83\x11\x77\xef\xbc\xd6\x55\xa9\x2e\xc7\xd2\x44\x72\x88\x32\x56\x03\x4b\x16\xdb\x3c\x81\x35\x2b\xb3\xd9\x48\xa1\x61\xf3\x4a\x6a\xb0\x7b\xc1\x27\xef\x64\x87\xb6\xbb\x9c\x5d\x7d\xc7\x2f\xbd\xe4\x78\xcf\xfc\x1b\x6f\x0d\x65\xfb\x56\x3a\x33\x4b\x88\xcf\xea\xb3\xcb\xc6\x41\x54\x89\xff\x5f\x18\x57\x4c\xb1\x19\x92\xa1\x06\x3e\x06\x0d\x54\x46\xcc\xdb\x75\xc9\xa7\x9d\xc2\xf7\xea\xde\xee\xe8\x7f\xba\xb4\x51\x46\x3d\x57\xb1\xea\xc5\xd8\xc2\xce\x25\xad\xfb\x0a\xa4\xcc\x11\x97\x9b\x52\x7d\xc5\x6d\xe7\xe7\xa6\x75\x73\xf2\x8c\x91\x80\x95\x6c\x56\xd1\xba\x3c\x3f\x73\x97\x5f\x52\x1e\x18\x17\xea\xae\x0c\x7b\x2a\xc7\xe3\xd9\x06\xed\xda\x0f\x31\x3a\x4b\x43\x79\x5a\xfb\x24\x51\x0f\xda\x49\xa9\x7a\xa0\x4a\x00\x94\xf7\xa3\xfd\x17\x19\x7d\x04\xe1\x84\x9d\x6e\x56\x53\x76\x8d\xe6\x75\xc5\xd3\x19\xed\x0a\x97\x50\x27\xb8\x0e\xba\xf7\xe0\x78\x2a\x67\x8d\xa4\xec\x45\xc0\x5a\xaa\xfd\x55\x61\x45\xaa\xed\xe2\xb2\xd9\xfc\x07\xf4\x7a\xac\xab\xdc\xe9\x4a\x61\x17\x5f\xe8\xec\xf4\x5c\xad\xb3\xd3\x4b\x6e\xb8\xad\xaa\xb3\xe9\xb7\xd3\xbd\x00\x67\x57\x3f\xff\xad\xf3\xce\x35\x6a\x43\xfa\xa0\x25\xbd\xb4\x69\xf3\xf3\xf5\x91\xea\xe7\x3f\x78\xa4\x16\xc6\xf5\xf4\xbd\x50\x3d\xa5\x8a\xa8\x3d\x66\x26\x5d\x30\x3d\xe4\x39\x47\x3d\x80\x2b\xde\x0f\x5a\x4c\x95\x7d\x26\x8b\x22\x5e\xd5\xf4\xac\x2c\xaf\x97\xd2\x92\x7a\x6c\xbd\x24\xad\x87\x51\x29\x2d\xad\x97\xa4\x67\xe1\x6f\xde\x08\xa0\x99\x2c\x36\x9f\xd5\x0d\x15\xb5\xf4\x69\x69\xbd\x7a\x4c\x92\xb4\xc0\xb3\x1f\x6c\xc3\x49\xcb\x86\x92\x1d\x00\xd4\x16\xd2\x51\x0f\x25\x9b\x51\x5a\x44\x57\x3c\x03\x99\x4a\x8b\x43\x96\xa5\xcf\xd6\x0b\xa3\x9a\x28\x85\xf8\xb7\x42\x51\x61\x74\x3d\x08\xd5\x45\xdb\x96\xa6\xa5\x2f\x14\xc6\x5b\x2e\x28\x8c\xae\x57\xcf\x6a\xa7\x59\x28\x57\x54\xb7\xd1\x04\xbd\x28\xfd\x50\xb2\xaa\xa5\xce\x19\x1a\xa7\xdb\x6b\x9e\x51\xf3\xd2\xcb\x40\xac\x2e\xd5\x76\x5a\x5a\xe9\x2c\x75\xc9\x9f\xab\x5c\x1d\xb4\xb9\x4a\xca\xa1\xba\x21\xa9\xc3\x0d\xb4\x58\xd3\x30\x50\x58\x66\xc6\x9a\x4b\xb4\x55\xce\x2c\xd7\xd6\x72\x2f\xcf\x30\x06\xd0\xd4\x07\xd9\xc1\x99\xe1\xa7\xd8\x53\x65\xf7\x20\x02\x1f\xd7\xd1\x9d\x33\x69\x77\x24\x9d\xe9\x83\x7e\xe0\x22\x51\x07\x9f\x8c\x70\xd1\xe2\x96\xbc\x41\x84\x50\x44\xc4\xbc\x08\xbc\xb6\xd3\x4a\x47\xa2\x09\x7a\x8b\xe7\xfc\xe0\x74\x69\xcb\x83\x76\x8b\x73\xb9\x5d\x22\xb6\x6a\xd9\x23\xd1\x08\xaf\xfd\xb4\xd4\x7d\x90\x4a\x67\xfa\x70\xc8\x45\xf5\xfe\xfd\x90\x70\xa5\xa3\x2e\x9a\x82\x73\x47\x44\xd0\xde\xd0\xa0\x3d\x32\xad\x3d\x90\x52\x7f\x2e\x5e\x9b\x39\x5c\xbc\xb6\x37\xd6\x36\x83\x11\x8d\x18\xa1\x2a\x38\xbc\xfe\x10\x77\xc6\xe5\x8e\xf0\x1c\xef\xe2\x63\x38\xaa\x2d\xe9\x2e\xb7\x1f\x67\x5c\x7c\x9a\x52\x27\x5a\xb9\x5c\x99\x06\xce\xc1\xbb\x39\x57\x86\x2b\x30\x85\xc0\xcd\xb9\xf8\x06\x2e\x44\xf9\x40\x99\xb4\x0e\x64\x1d\xf7\x63\x9e\xa3\x77\x43\x71\x97\xce\x2d\xa2\x78\x7f\xf1\x34\x75\x45\x95\xd1\xef\x69\x1b\x71\x57\x26\x9d\xe2\xa2\xc9\x18\x4e\x27\xe2\x69\x9a\x57\x6b\x25\xce\xd9\x10\xed\x83\x4c\x1f\x89\x50\x7e\x1c\xcf\x69\x77\xb4\xe9\x9e\xc6\x82\x8b\x2a\x49\x84\x5c\x69\x6d\x4f\x1a\xc9\xb8\x32\xf4\xe5\xe9\x0c\x5d\x18\xfa\x20\xd2\x01\xc9\x54\x34\x06\xba\x94\x36\x1a\xcf\x34\xc4\x20\x94\xd6\xb2\xba\x32\xfa\x29\x9d\xa4\x1d\x92\x0e\x51\x76\x73\x24\x9a\xd6\xce\x11\x92\xa6\xea\xef\xd1\x74\x01\xf7\x91\x17\x89\x3b\x12\x8d\x61\x8a\x6e\x19\x49\x47\x23\x22\xa3\x85\x62\x90\xf2\x53\x6a\x8f\xe7\xdc\x0e\xce\xed\xa8\xb6\x60\x21\xf3\xb1\x95\xc3\x2c\x0b\x9c\x4d\x8c\x34\xd8\xb1\x9b\x10\x0f\xc1\x16\x33\x70\x46\x11\x9b\x4c\x1c\x60\x2b\x06\x42\x58\xce\xc0\x03\xe1\x08\x87\x89\x99\x58\x6d\x26\xce\x48\x78\x16\xac\x0e\x62\x48\xf2\x2c\xf0\x20\xf8\x18\xe2\x25\x2c\xcf\x63\xe0\x58\x86\x98\x65\x86\x37\xba\x39\xb6\xb1\x26\xc8\x71\xbc\x85\x60\x62\x04\x0b\x4f\x42\x56\x56\x60\x8c\x26\x99\x15\x89\xd1\x62\x64\x18\x8b\xd5\x60\x02\xbb\xcd\x00\x46\xd6\x60\x20\x3e\x93\x5c\xcb\xd7\x72\x2c\x98\x4d\x02\x16\x39\x2c\x98\x80\x70\x2c\x6b\x20\x7c\xc0\xc4\x78\xec\x2c\xc3\x00\x61\x44\x12\x9b\xc5\x71\xac\x0d\x37\x18\x58\x91\xe3\xdd\x0e\xcc\x63\xc6\x2a\x1a\x6c\xdc\xbd\x17\xf0\x2c\x83\x89\xc9\xc8\x41\xab\x8c\x89\x00\x36\x20\x3c\xcf\xb3\x80\x89\x5d\x10\x82\x1c\x26\x92\x85\x61\x2c\x06\xec\x06\x20\x40\x6a\x08\x60\x86\xc3\x5e\x2b\x26\x2c\xc6\x06\x23\x07\xc4\x24\x3a\x30\x67\x33\x18\x5d\x1c\xcb\x61\x2c\x58\x1c\x84\xad\x35\x98\x2c\x76\xd6\xea\xe3\x1b\x65\xcc\x9a\x79\xcc\x7a\x59\x0e\x88\xc3\x20\xd6\x4b\x2c\xc1\x98\x31\x62\x0e\xc0\x81\x59\x17\x4b\x04\x0c\x04\x83\x91\xc3\x66\x8b\xcc\x03\xc3\x71\x7c\x03\x2f\xc8\x2c\x70\xc4\xc2\x60\xad\xf0\x40\x08\xf0\xad\x9c\x95\x67\x31\xeb\x21\x35\x2c\x31\x10\x9e\x35\x61\xb3\x81\x37\x80\xf6\xcf\xca\x9b\x4c\x20\xda\x19\x27\xc7\x33\x60\xe0\xc1\xc8\xb3\x2c\x6b\xb4\x18\x78\xb6\x9e\xf0\x98\x30\x2e\x6c\x27\x44\x12\x4c\x36\x62\x31\x12\x3b\xb6\xba\xec\xcf\xbe\x74\x0f\x91\x89\xc4\x01\x6f\xb4\x11\x6c\x62\xcc\x1c\xaf\x75\x15\x06\xa7\x95\xb5\x18\xcd\x1c\x8b\x81\x17\x59\x62\x35\x8a\x8c\x80\x09\x87\xb1\x8c\x19\xc2\xcb\xb5\x98\xb1\xd9\xe0\x0c\x03\x25\xf5\x7b\x60\x07\x93\x05\x78\x03\xc7\x19\x64\xec\x02\xcc\xb2\x2e\xb0\x09\x98\xe3\x31\x03\xc4\xe8\x21\xac\x85\xc1\x3c\xc7\x9a\x4c\x18\x80\x05\x8c\x81\xe5\x18\x60\x6c\x1c\x63\x34\x60\xd6\xc8\x70\x46\x99\x70\x22\xcb\xdb\x05\x83\x8d\x31\x38\x39\x2a\x07\xc0\xac\xcb\x5a\xc3\x1a\x8c\x82\x60\x64\x41\xb4\x12\xce\xad\x75\xac\xd5\xc2\x58\x59\x0f\xcb\x81\x09\x3c\x06\x90\x78\xcc\x18\x19\x06\xdc\x16\x33\xd4\x80\xd5\x20\x82\xc5\xca\x60\x96\x37\xf2\x0c\x03\x26\x06\x58\x06\x33\x0e\x86\xad\x61\x8c\x04\x18\xcc\x1b\x2c\x0c\x26\x02\xb6\x7a\x01\x63\x23\x88\x3c\x6b\x33\x32\x84\xe3\x2c\x1c\x11\x0d\x00\xc3\x77\xf1\x00\x36\x8e\x33\x98\xc1\x67\x67\xcc\x3c\x16\x09\x5b\x0b\x81\x28\x03\x96\x76\x42\x9a\x0c\x80\xcd\x46\x8e\x0d\x71\x9c\xcf\x88\x79\x51\xcb\x83\x1d\x2d\x35\x0c\xeb\x64\x08\xc3\x00\xef\xb4\xb9\x30\x57\xeb\x34\x1a\x1a\x39\x5e\xe0\x4c\x18\xdb\x09\xc3\x02\x6e\x60\x64\x03\x08\x92\x99\x70\x12\xc7\xb0\x06\x0f\x26\x75\xd6\x20\x18\x0d\x46\x8e\x97\x18\x83\x87\x18\xb1\x01\x8c\x18\x48\x9d\x81\xb1\x09\x16\x1e\x40\x26\x56\x03\x21\x98\x31\xb4\xd8\x4c\x41\xbb\x0d\x5b\x09\x00\x30\x0c\x60\x42\x8c\x9c\x59\x00\x3b\x5b\x2b\x11\x86\x60\x1e\x13\x56\x34\x35\x31\x04\xdb\xcd\xbc\xc1\x68\x34\x10\x49\x36\x02\x6b\x60\x64\x9b\x91\x63\x58\x33\xb1\x61\x8b\xc9\x60\xe0\x79\x0e\x1b\x6c\x0c\x6b\x00\x33\x83\x05\xb3\x91\xe3\x31\x00\x36\x71\xec\xe4\xcd\x8d\x9f\x20\x04\xf3\xc0\x5b\xb4\xd2\x1a\x08\x87\xb5\x91\x46\xc0\xce\x82\x91\xc5\x1c\xeb\x20\x6c\x0d\xc7\x11\xce\x8c\x8d\x84\xb1\x11\x86\x25\xa6\xb8\x50\x6f\xaf\xb1\xba\x18\xbe\xd6\x40\xad\x23\x9c\x53\x4e\x6e\x3f\xdd\x33\x39\x51\x47\x79\xcf\x64\x2c\x58\xe4\xa6\x92\x19\xf0\x03\xe8\x1a\x13\xc8\x86\xa8\x2f\x0a\x07\xcf\x3a\xdd\xba\x3b\x0a\x9d\xb4\xc2\x9f\xcf\xaf\x0d\xa7\x92\xd1\xd1\x48\x04\x3f\x1e\xbd\x1f\xbf\xee\xee\xf8\xe3\xc7\x74\x63\xa0\x39\x07\xda\x6c\x36\xf5\x17\xff\xc6\x7e\xfc\x26\xa3\xd5\x5e\x90\x85\xfc\x36\xbf\x36\x1c\xbe\xbc\x31\x9d\x8a\xe0\xc7\x37\xdf\x0f\x77\x46\xe7\xdd\xfa\xa8\xce\x54\x0a\xfa\xcd\x0d\xe6\xc7\xc7\x2f\x23\xeb\x17\x39\x50\xa5\x4f\x4e\xdd\x8e\xa3\x16\xb5\xa2\x6e\x84\xc2\xc1\x54\x10\x8a\xbf\x73\xf8\x72\xad\xbe\x66\x90\x46\xfb\xab\x0a\x83\x26\x11\xa6\xf8\xfa\xf8\x43\x21\x41\x52\x98\x7e\x50\x94\xc9\x6c\x91\xed\xe5\x8d\x44\xe0\xcd\xb3\x5d\x68\x7b\x6f\x76\x4a\x61\x6f\x62\x11\xd5\x53\x75\xf1\x25\x98\xbb\x48\xca\xae\xfb\x8a\x8a\xb3\x37\xd9\xeb\x55\x99\xa2\xdb\x4d\x21\x59\x95\xeb\xed\xf6\x16\x16\xb5\x30\x3f\x6b\xae\x53\xe5\xbc\x97\x02\xdb\x21\xd9\x0b\x6f\xc2\x3b\x75\xcd\xd1\x32\x0e\x26\xed\x39\x37\xaa\xa5\xb6\xab\xd3\xda\x20\xe8\x2c\x62\x4e\x85\x9c\x41\xea\x87\xa0\x5a\xb4\x8a\x15\x8c\x54\xc4\x14\x7c\xab\xe0\xb1\x88\x17\xb2\xde\xc8\xc8\x14\x62\xd0\xfb\x68\xe3\x00\x8c\xe8\x2c\x3c\x18\x19\xd8\xc8\x22\x25\x8f\xd4\x80\xce\x4e\x19\xd3\xaa\x36\xa6\x28\x30\xae\x2a\xa0\x0c\x6c\xd4\x41\xc1\x37\x56\xea\x9d\x2e\x42\xc8\x88\x33\x69\x77\x91\xbd\x17\x8d\xf4\x83\x91\xae\x40\x45\xc6\x53\xba\x1e\x8c\xc0\x17\x9d\x18\xe9\x98\x59\x56\x30\x52\x6e\x43\x81\xb4\xa7\x77\x59\xa2\x3e\x08\x5b\x8e\xd4\x35\x47\x8b\x0e\x83\x8e\xa8\x0f\xaa\x0f\x1e\xd1\x1a\xa8\xe0\x0c\xe8\x08\x6c\x51\x1f\x3c\x22\x7b\x2d\x96\xa6\x88\x17\x72\x34\x0d\x6c\x81\x2d\x34\x0d\xe4\xbc\x11\x8a\x00\x46\x7e\x33\x73\x3e\x7f\xb4\x2a\x97\xcc\xea\xb9\xb4\x14\xf4\xdd\x34\x85\xf6\x6e\x56\xd6\xf5\x2a\x11\xc5\x39\xb7\xa3\xd9\xa8\x0b\xcd\x45\xab\xd0\x7a\xca\xcd\xd7\x36\x28\x36\x9d\x93\x90\xe1\x9c\x0e\x28\xe9\xb4\xb3\x89\x38\xf5\x61\x99\x88\xfb\xd9\x22\x97\xae\xe8\xbd\x9a\x42\x47\x50\x75\x25\xaa\x40\x0c\x89\x38\x2e\xa4\xc0\x2b\x1e\xbe\xe4\xd6\x95\x3b\xf7\x72\x83\xd7\x77\xcf\x1b\x60\x19\xe5\xde\x1b\x26\x8f\xdd\x70\x2f\xef\x0c\xa4\x17\x6e\xeb\x35\x0d\x0c\xdf\x7a\xfb\xad\xc3\x03\xa6\xde\x6d\x0b\xd3\x01\x27\x3f\xa9\xe3\xf2\x91\xb5\x05\xed\x58\x12\xdc\xb9\xf2\xd6\x4b\x1e\x5e\xc1\x0e\xcc\xeb\xbe\x7e\x90\xdb\xab\x2b\x3f\x62\x85\xbd\x69\xc5\x32\xb8\xb8\xa5\xd5\x1d\xae\x3b\x9c\x17\xaf\x3f\x7c\xf8\xfa\xd4\xb6\xdd\x5b\x37\xcd\x6b\x6a\x4d\xb5\xb6\xa6\x5a\x9b\xe6\x6d\xda\xba\x7b\x1b\x1b\xa7\xba\x85\x6a\x7d\xc1\x55\x76\xfe\xc4\xb2\x15\x37\xb1\xbb\x0f\xd7\x85\xdd\xad\x2d\x30\x4a\x6f\x16\xed\xd4\x8e\x70\x3b\xd9\x77\x51\x10\xcd\x43\x97\x16\xd0\x52\x42\x0d\xbc\x9f\xa1\xdb\xb6\x18\x89\x96\x81\x5d\xd2\x50\x04\x7e\x29\xc6\x65\x8a\xaa\x41\xc4\x9d\x46\xba\x25\xbe\x3e\xcf\x44\x0b\x18\x00\x05\xe3\x31\x97\xd3\xc1\xbb\x69\x88\x7d\xca\xf7\xb2\xaf\xa9\xc5\x4f\x02\x66\x99\xef\x6c\xb2\xd6\x78\x2d\xf5\x24\xe8\x7b\xa9\xb6\xb9\xc9\x77\xd4\x97\x9f\xeb\x7b\xc9\xd7\x14\xad\x3b\xea\xf3\xbd\x5c\xdb\x5c\x9d\x8a\x1c\x58\x73\x74\xd5\xf5\x37\xac\x7a\x69\xd5\xba\x75\x6b\x6f\xbc\x7e\xf5\xcb\xab\xab\xae\x21\xdb\xe4\x7b\xd9\x17\x20\xf5\x16\x6f\x8d\xb5\xa9\x93\x97\xcd\x01\x52\xdf\xd2\xe4\xfb\x71\xad\xf7\x5e\x1f\x7e\xab\xc9\xf7\x63\x5f\xed\xbd\xbe\x68\x93\xef\xe5\xda\xfa\xe9\x89\xf2\x6f\xbc\xbb\xea\xde\x55\x6b\x7e\xbc\xea\xfa\x9b\xd6\xae\x5b\xb7\xfa\xe5\xd5\xd3\x2f\x0b\x18\x97\x0a\xc5\xf6\x46\xfa\xb8\x40\xa9\x24\xd5\x55\x45\x89\x38\xe3\xd6\xc5\xb0\xbc\x1f\x78\xe5\x8d\x13\x13\xb9\x67\xd4\xf7\xef\xba\x16\x43\xdb\xab\x9f\x06\xe8\x5e\x38\x32\x7a\xac\xf9\x23\x8f\x81\x72\xe2\x0d\xe0\x9f\x39\xf8\x8b\xb4\xcf\xfa\x2a\xb4\x3d\x75\x57\xdf\xb1\xd1\xc1\x7e\xff\x29\x84\xd1\x35\x53\x0a\x27\x50\xfb\xfa\x20\x42\x61\x1d\x6a\x29\xa3\x6b\xf6\x17\x34\x6d\x5a\xb5\x65\x20\x08\xd1\x94\x3d\x64\x77\xb2\x7f\xef\x5c\x30\x3a\xa1\x8c\x2e\xe8\x84\xbf\x67\x8b\xd0\x5a\x11\x6f\x56\x7d\x5b\x7d\x17\xff\x40\x7d\xd7\xa1\xac\xbb\xe0\xc0\x81\x0b\x48\x0d\xdc\x5d\xd0\x49\xdb\x35\x5f\x5d\x05\x4f\xd6\x87\xe1\x6e\x75\x57\x58\x9f\x76\xa0\xa0\x9b\xc9\xa3\x65\x68\x03\x1a\x45\xd7\xa3\x5b\xd1\x9d\x65\xcc\x7f\x16\x28\x7f\x91\xce\x71\x94\x38\x17\x0b\x9f\x3a\xa5\xd9\x13\x54\x31\x97\xea\x68\x36\x50\x1f\x32\x54\x1c\x4d\xa9\x6d\xde\x55\x0f\x85\x4e\x77\xbb\x78\x36\x4d\x61\xb8\xe9\x76\x22\x11\x27\x7d\x14\x32\x88\x17\x29\x46\x10\xb8\x53\xc9\x7e\x88\x52\x14\x77\xe0\xeb\x01\xa2\xe0\xe4\x29\x98\x7f\x3d\x40\x46\x7b\x2b\xd1\x19\x67\x70\x39\x4c\xf8\x08\xeb\x57\x04\x9b\x5d\xcc\x2f\xbb\xd2\xc0\x88\x0c\xbf\x79\xd5\xc1\x7b\x6e\x5f\x7b\xa1\x99\xdf\xbc\xf2\xe0\xbd\xab\xe6\x1b\x85\x1b\x6f\x14\x8c\xf3\x57\xdd\x7b\x70\xe5\x66\x9e\x6d\x6e\x5d\x73\xe8\x9e\x83\xab\x36\xf3\x8c\xc8\x18\xae\xc4\x4f\x8b\x76\x9b\xa0\xf8\x59\xe2\x9b\xd8\x10\x8b\xaf\xd8\xb0\x75\x49\x54\x3f\xc5\x56\xc4\x63\xd1\x25\x5b\x37\xe8\x27\x10\x47\x82\xe2\x72\x2f\x11\x59\xcc\xc0\x4f\x46\xf0\xb8\x92\x47\x63\x46\xcc\x32\x22\xe3\x25\x23\x4a\xfe\x1f\x5f\xc2\x66\xac\x2f\x92\x5e\xf5\x6a\x47\x63\xc8\x96\xe5\x0d\x70\xcb\x00\x03\xb3\x67\x2d\xfd\x58\x6a\xf5\xb2\xd5\x37\x0d\xdd\x95\x5a\x5d\x2f\x18\x17\x2f\x36\x0a\xf5\xab\x53\x77\x0d\x75\x5f\x1e\x5d\xbe\x3a\x79\xd7\xd2\x59\xb3\x81\x19\x80\x5b\x0c\x7c\xd6\x16\x6a\x74\xdc\xd1\x72\x30\xd1\xdd\xa8\x1d\xf2\xdd\x89\x83\x2d\x8d\xf4\x80\xc7\xe6\x98\x1b\x1d\x86\x0e\x2f\xb1\x31\x98\xc0\xef\x03\x38\x9b\x55\x57\xec\x1a\x31\x60\x86\xb1\x31\x5e\x35\x97\x85\xe3\x77\x10\x46\x97\xc3\xe8\xeb\x46\x3d\x6a\x40\x61\x94\x40\x3d\x55\x72\x98\xc2\x0a\x59\xb4\x56\x71\xda\xd3\x09\x1e\x82\x46\x08\xca\xda\x22\x52\x70\xd1\x99\x4c\x97\x2e\xb8\xb1\xa2\x44\x28\x3f\xde\xd4\xd9\xe4\x83\xe3\xbe\x91\x26\x18\x6b\xea\x9c\xdf\xa3\xa8\xaf\x41\x6b\x9e\x1e\x9f\x83\x1e\x95\x22\x13\x60\xd4\x44\x7e\xaa\x07\x99\x12\xa4\x00\x04\x0a\xbe\x27\xe0\xb8\xaf\xa9\xb3\x49\xfd\x7a\xd3\x6b\xea\x6b\xf8\x09\xf5\x35\xf5\x11\xe8\x81\x31\xea\x28\x53\x01\xd4\x34\x32\xf9\x0f\x46\xd1\xaf\x28\x4f\x9b\x99\x3a\xc8\xee\x65\xf7\x52\x14\x68\x47\x11\x55\x43\x47\xee\x28\x28\xe8\x17\xac\x36\x80\x32\x9b\x92\x15\xd7\xce\xaa\xf4\xec\xde\x4f\xef\xbe\x6d\xeb\xe4\xdf\x77\xbd\x7e\xe2\xd3\xd7\xe0\x8b\x4c\xbd\x36\xc1\x94\x7f\x78\xf9\xf6\xd1\x7b\x87\x88\xa1\x7f\x65\x76\x75\x7f\xfe\x9b\xde\x86\xba\x48\x0d\x3c\x60\xea\xb3\x59\x4c\xea\xf6\xfe\xab\x57\xae\xeb\xc5\x0b\xb6\xde\xbf\xfb\xd3\x5b\x89\xe1\x9a\x4f\x9d\xf8\xd5\xae\xfc\xc3\x26\x8b\xad\xd7\x84\x37\x2d\x3d\x36\x7a\xe9\xd0\xe4\xdf\xfb\x57\x67\x57\xf6\xe3\x05\x9e\x48\x5d\xa0\x56\xdd\x6e\xb2\xd8\xfa\x4c\xf0\x40\xef\xba\x95\x57\xf7\xe7\xbf\xb9\x79\x9a\x6e\x5f\x10\xcd\x46\x0b\x74\x1f\x1f\x54\x9f\x8f\xfa\x8f\x29\xdb\xf5\xdb\x13\x45\x96\x57\xb5\x0d\x6a\xb5\xcd\x9d\x5b\xa3\xd2\x14\x82\xf2\x88\x28\x8a\xc3\xa4\xfe\x97\x69\x96\x55\x97\xc8\x29\x4a\x67\x13\xc9\x36\x75\xaa\x4a\x85\x65\xb0\x52\xf2\x4d\x4a\x9b\xdf\xe3\x6b\xa2\xce\x89\x14\x71\xb6\x09\x6a\x4c\x8e\xa2\x61\xff\x04\xd2\x91\x22\x30\xaa\x90\xee\xc8\x93\xf4\x2e\x4b\xbd\x96\xaa\x6f\xf9\x46\xce\x8d\xc3\x57\x29\x5e\x67\x46\xa6\x9b\xad\xe8\xf2\x39\x2a\xd7\xd2\xf1\x8e\xff\x69\x64\xef\xe9\x38\x7f\x67\x0b\x57\xa0\x77\xbf\x39\x53\x90\xae\xf1\x39\x1e\xb1\xd9\x82\x7c\x2d\x8a\x32\x1a\x45\x53\xb4\x60\x93\x8a\x52\xc3\xaa\xb7\xa3\xb3\xc4\x9f\x89\x2a\x4d\xe5\x86\xfa\x1f\xfb\x6e\xa5\xa4\xed\xb4\x32\x43\x64\x65\xf8\x65\x9a\x0d\x8e\xe8\x00\xc3\x63\x25\x20\x65\xf2\x9b\xea\x18\xf8\x6b\x05\xca\xb2\xd6\xac\x56\x6a\x5b\xfa\x77\xe4\x47\x3d\x68\x08\x6d\x40\x97\xa3\xbd\x08\xb1\xf4\x2b\xc8\xe8\x5f\x07\x1f\xed\xc3\x99\x54\x03\x17\xa2\x8e\xac\x78\x3f\xc8\xce\x20\x65\xba\xea\xf2\x92\x68\x1f\x15\x0e\x3b\x44\xcc\x27\x52\x67\x02\x91\x07\x53\x89\xa4\x46\x6d\x72\x7c\x34\x93\xb0\x9f\xb3\x11\xf6\x5d\xb1\x62\x74\xa0\x6b\x76\x57\x5d\xeb\xa5\x5e\xc3\xec\x46\xd9\x36\xd7\x36\x0a\x4b\x37\x25\x7a\xb0\x7a\x8c\xeb\x18\x18\xe8\xa8\xab\x89\x85\xd6\x78\x36\xcd\x59\xbc\x75\xfe\xca\x05\x70\x80\xfd\x83\xde\x0e\x92\xa8\x37\x94\xfa\xa5\xcb\x00\x1b\x5a\x16\xdd\x3e\xca\xbe\x5d\x79\xa7\xb2\xb5\x56\x0f\x6f\x18\x58\xd7\x5e\xe7\xcb\x1a\x3a\x4d\xf3\x9a\x25\xc0\xa9\xe3\xeb\xae\xb1\x2c\xc1\xd9\x13\x8d\x52\x62\x75\xb2\xb5\xcd\x5d\x53\x3b\xa7\x3b\xd1\xb5\x6a\x51\x7c\x55\x2c\x53\xd3\xa3\xfe\x9b\xde\x66\xa2\x24\x93\xeb\xb6\x6c\x69\x7e\xa8\xd9\x62\x0f\x0f\x1d\x50\x2f\x57\xf7\x95\x6e\x54\xb5\x2b\xa9\xb0\x7f\x4a\xa1\x6d\x74\x2e\x9d\xa6\xdc\x18\xd6\x8d\x63\xd2\x3a\x28\xac\xee\x40\xa2\x03\x0a\x0b\x5b\x49\x38\x40\x82\x05\xb4\xdc\xa2\x34\x4e\x37\x68\xd1\xe8\xe6\x54\x46\xd7\x56\x72\x17\xb0\xde\x52\xc9\x68\x84\xa3\x86\xca\xef\x53\x2d\x46\xf8\xae\xcf\x3d\xeb\xd6\x8f\x02\x13\xdf\x3d\x70\x95\xc9\x2c\xb2\x96\xd5\x62\x3c\xb5\xee\xc6\xab\xe7\xcf\x1b\x18\x78\x6d\xc1\x8e\x39\xe1\xb7\xe1\x93\x7c\xb3\x7b\x56\xf8\xbc\xe1\xc5\xc3\x37\x5d\xbd\xe2\xce\x2e\xab\x41\xdb\x37\x6e\xb7\xfa\xad\x6c\xa8\xbd\xb5\xaf\x7b\x71\x76\x70\x69\x7b\xc7\x8a\x06\xac\x94\x7d\xef\x65\x43\xed\x9b\x2f\xfc\x8a\x72\x40\xb6\x34\x46\x86\x6f\xea\x91\x6a\x09\x87\xef\xeb\x5c\xdf\x3d\x67\xdd\xe2\x79\xf3\xfa\x1c\x31\x9f\x67\x0a\x45\x53\x57\x6d\xeb\x9c\x15\x8a\xcd\x92\x9c\xee\x26\x9b\xc5\x20\x0a\x97\xcf\xf2\x47\xc2\x6d\xb8\x61\x49\xc4\xd0\x15\x6e\x74\xba\x6a\xbd\x3d\xbd\xf3\x57\x2f\xae\xab\xe0\x8b\x6e\x41\xd7\x20\x24\x47\x3a\x74\x20\x5c\x5a\xa7\x78\x86\x77\x3b\x39\xbd\x41\x5c\x4e\xb7\x5c\x51\x5b\xbd\xc6\x31\xbd\xc9\xac\x10\xcd\x24\xdc\xae\x8c\xbb\xd4\x58\x5a\x7a\x97\xec\x2a\xb7\x9c\x2e\xc3\x4a\xd9\x93\xd1\x48\x35\xae\xe1\xac\xb0\x81\x08\xb5\x3d\xc9\x83\x0d\x6b\x57\x5e\xeb\xef\xf4\x03\xee\xc9\xf6\xc8\x02\x80\xc8\xb5\x87\x7a\xd7\x5d\xb0\xe3\xfc\xce\xd6\x59\xf6\x46\xbb\x93\xb7\x72\x0c\x2b\x37\xb4\x6e\x15\xf1\xea\x17\x87\xae\x97\x38\xa6\x3d\xba\x98\xb3\x12\x83\xc8\x39\xad\xde\xc8\x92\xc1\xcb\xae\xb8\xf7\xd1\xdd\x7b\x7a\x7a\x5d\x36\x7b\x0d\xbb\x56\x12\xcb\x6e\xd4\xd9\x20\xc6\xeb\x80\xe1\x09\x03\x58\xcc\x1a\x8d\x35\xe2\x75\x42\x94\xfb\x9d\xfa\xd6\xde\x65\xdd\xc1\x0e\x9f\x14\x6c\xf4\x75\xce\x59\xfc\xa9\xe5\x9b\x8f\xae\xed\x9e\xe7\x0c\x01\x26\x6b\x4d\x44\xc0\x11\x81\xf7\x58\xc0\xcc\x59\xbd\x7c\x93\x59\x56\x6f\xfb\xee\x15\x43\xb1\xb9\x73\xba\x02\xc1\x58\xc7\xe0\xd0\x9e\xe1\x07\x61\xe9\xc9\x9a\xc6\xd3\x37\x17\xfb\x46\x42\xc8\x54\xd2\xe1\xa8\xf6\x29\x70\x37\x3a\xa1\x23\x46\x54\xd6\xdd\x5e\x75\x5d\xdd\x36\xff\xa7\xaf\xab\xdf\x57\xed\x23\x14\xa3\x22\x7e\x1f\xd5\x88\xae\x08\x4f\xbf\xa3\xa2\xb3\xdf\xfb\xf0\x29\x2b\xc3\xda\x76\x97\xea\x22\xb0\xd9\x81\x8d\x65\x4c\x43\xb8\xab\x14\x54\xcb\x41\x22\xce\x14\x7b\xce\x04\x15\x0f\x83\x65\x95\x1e\x46\xb5\x79\xb8\x76\xea\x93\x05\x3c\x0a\x99\xda\x4b\xb6\xa2\x04\x42\x46\x88\x42\x23\xd5\xf7\xee\x28\xe1\x98\x86\xdd\xda\x4c\xd1\x0f\x70\x96\x33\xf3\x39\x08\x5f\xa6\xfe\x02\xb7\x48\xa7\x4f\x4b\x69\xe9\x79\x49\x62\x39\xed\x7c\xfa\x85\xcd\x9b\xfd\xfe\xcd\x9b\xfd\xb0\xf7\xb9\xe7\x7a\x7a\x9e\x7b\xae\x87\xfc\xaa\x10\x93\xff\x74\x21\x40\xbe\x49\xf3\xbe\x96\xd6\xf2\x4a\xcf\x4b\x69\x2d\xaf\xf4\xfc\x3d\xf4\xa6\x7f\xb3\x3a\x49\xf3\xf5\x3c\x97\xdf\x58\x88\xc1\xfe\x42\x80\xf2\x1e\xb2\x25\xfa\xdf\x86\x3c\x68\x69\x85\x84\x3d\x68\xd7\xb7\x78\x25\xb3\x1c\xbb\x43\x64\x22\x21\x5d\x21\x82\x1e\x43\x0d\x9c\xbe\xf1\xb3\x27\x23\x7d\xa4\x1f\xfa\x80\xc2\x63\x24\xca\xc6\xde\xea\x8f\x40\xf9\xb4\x60\xfc\xae\x91\xd5\x55\xfb\x61\xc8\x20\x8b\x41\x4b\x94\x68\x9b\x52\x6d\x27\x9b\x25\x51\x4b\x50\x94\x0d\x11\x2f\x00\x63\x94\x85\xe7\xe5\xfe\xda\xb1\x88\x97\x41\xde\x88\x6e\x0b\x80\x15\x40\xc6\xef\x1a\x85\xfc\xbf\xd0\x4b\x26\x37\x89\xac\x6e\xd1\x48\x00\x46\x8f\x1d\x1b\xd5\x7e\x00\xc4\x28\xba\xad\xde\x08\x64\x0d\x69\x57\x47\x6d\x83\xf0\xbc\xec\xcd\xe9\x00\x02\x65\x1a\x66\x49\x09\x87\x41\x9b\x88\xb4\xad\x7d\x1f\xa4\x28\xf8\xa6\x48\x9c\x0e\x97\x5b\x17\x42\x14\xbc\x60\xea\x24\x65\x24\x53\xd0\x2f\xd0\x26\x77\xc2\xb9\x23\x38\x95\x94\x1a\x03\x0c\x87\x5e\x52\x4f\x9c\xba\xea\xb2\x6e\xd9\xd8\xee\x18\xed\xbd\xe1\x5b\x3b\xf6\xfc\xfa\xae\x4b\xbf\x7a\x60\x7d\xeb\xf0\x52\xbf\x01\x5b\x30\x67\x4f\x9c\x7a\xfc\xfe\xc7\x0f\x5d\xd6\xbb\x44\x34\x84\xdd\xe9\x78\xdf\xda\x9a\x2d\x76\xe6\x25\xb5\x88\x1e\xba\x82\xf2\x69\x03\x17\x2d\x6a\xf8\x52\xb4\xeb\xd0\xbb\xc7\xae\xfe\xc1\xfe\x39\x23\xfb\x6e\x9d\xb7\xe3\xd3\x01\x4b\x80\x9f\xc5\xb9\x1d\xbd\x17\xde\xff\xb3\x47\x6e\xf9\xfc\x9f\xce\xef\x0d\xed\xbe\xa0\x3e\x3e\x70\xf5\x9a\xc5\xb3\xd5\x8d\x0b\x2f\x5b\x0f\x7b\x7f\x7f\x4a\x97\x02\x95\xeb\x36\x54\x41\xf7\x17\x6b\x27\xe9\xce\xc1\x0a\x95\xa3\x93\xef\x07\x56\x2e\x34\xcd\x7e\x38\xdf\xba\xc6\x6d\x6c\x73\x5e\xda\xf3\x95\xdf\x2d\xbc\xe9\xab\xa3\x3b\xbe\xb2\xef\xc2\xd6\xe5\x4b\x05\x27\x63\x62\x39\x7b\xfc\xc7\x8f\xde\xf7\xe8\x6d\xa3\x3d\x5a\xe5\x5c\xa9\xd9\xbd\x6b\x3c\x9b\x3d\xf6\xaf\x55\xda\x18\xdf\xb8\xae\xe1\x8b\xd1\x4e\x88\xfe\x7a\xf5\x83\x37\x2c\xee\x1a\xb9\xe9\xa3\x03\xdb\x3f\x15\x60\x4d\x62\x9b\xdd\x2d\xf7\xad\x3b\xf6\xda\xc3\x1f\x79\xec\xed\xf3\x7b\x1a\x76\x9f\x5f\x3f\x7b\xee\xae\x55\xe7\xcd\x56\x37\x6f\x7d\xa0\x64\x88\x5c\x96\x6d\xd5\x52\x7a\x0d\x41\x32\x1a\x74\x26\xc4\x02\x9c\x40\xdc\x9d\xd1\x4a\x6d\xd3\x08\x9d\x70\x22\x15\x4a\x85\x9c\x21\x67\xc2\x99\xa8\xa6\x50\xc9\x7d\x9c\x7a\xec\x67\xa4\x76\xd6\x9a\xf4\x96\x3b\xef\xdc\xb2\xa1\x77\xc7\xe5\xf7\x8d\x8d\x8f\x8f\x7d\xf6\x05\xb8\xe0\x8a\x2b\xae\xbc\xf2\xca\x2b\x41\xaa\xa4\x61\xf1\x1e\x6f\xe4\xa0\x27\x99\x0e\xdd\xf5\x83\xbb\xba\xb7\x6d\x7d\x43\xfd\xce\x1b\xaf\xec\xd1\x92\x5d\x89\x3f\x3a\x8d\xba\xd5\xd6\xbf\xcf\x18\x11\x7b\x51\x01\x0b\xd8\x81\x2b\x9c\x62\x07\xdc\x3c\x55\xe5\x76\xd0\x11\x46\x32\xc1\x54\xd0\x15\x76\x6a\x64\x58\x28\x95\x48\x25\x9c\xec\x83\xff\xa2\x7e\xeb\xe5\xfb\xd4\x77\x9f\xbb\xf6\xda\xe7\xc0\x76\x1f\xf8\x5f\xfc\xfe\xee\x2f\xde\x74\xea\xc6\x1b\x4f\xdd\xb4\xea\xf0\x85\xf3\xea\x39\x75\x04\xff\xab\x85\x6c\x39\xf5\xca\xa9\x53\xaf\xe0\xab\x5e\x56\xbf\xf9\x35\x2d\x21\xb4\x80\xed\xb9\x6b\x73\xdf\xde\xb5\xf7\xb5\xc9\xd7\xf6\xc6\x16\xac\x5b\x16\x9a\xec\xef\xd7\xd2\x9c\x3a\x55\xe2\x21\x2a\x2c\x42\x16\xe4\x43\x6d\x74\x27\x48\x5d\x97\xf2\xee\x74\x26\x61\x0f\x35\x3a\x44\xdc\x10\xc3\xc9\x3e\x1c\xf7\x03\xd8\xf5\x2f\x38\x64\x8f\xbb\x9c\xc1\xe4\x19\x33\x3a\x41\xa0\x28\x57\x7f\x7c\x69\x8b\x80\x15\x8c\x5a\x96\xee\x3f\xb6\x7f\x69\x8b\x7e\xc2\x2d\xa3\xc7\x26\x14\xed\xbb\x63\x94\x63\x7f\x88\x78\xdf\xa7\x1c\x07\x1e\x79\x23\xa0\x8c\x40\xee\xd0\x70\xd8\xa1\x8e\xbf\x79\xe7\x91\xbd\xcb\x96\xed\x3d\xa2\x9f\xd4\x16\x8c\xb4\x0c\x2a\x3d\x92\x6c\xd9\x5f\x50\xa4\x80\x35\xc0\x20\xa2\x20\xa1\x68\x25\x43\xf1\x0c\x12\xc1\x38\x83\x64\x35\x2b\x27\xb5\x03\x75\x96\x44\x2e\xa4\x61\x19\x72\x72\xb2\x88\xf3\x00\x88\x41\x24\xab\xe7\xd5\x7d\x7d\xeb\x4a\xfe\x0c\xd2\xbd\x2c\xd1\xc4\x32\xe4\x80\xea\x4a\xc8\xba\x42\xbe\x9e\x37\x8b\x14\xac\x30\xf4\xbd\x05\xcf\xba\x05\x68\x03\x6d\x67\x5f\x7e\x11\x93\xad\x7c\x8e\x5c\xf4\xa7\xac\xe0\x2c\x53\x51\x66\x1d\x48\xd0\x0d\x38\x4b\xcb\xac\xbf\x0b\x3f\x50\x2e\x7c\xa4\xf0\xde\xe9\xb6\x35\x75\x08\x25\x82\x54\x37\x32\x6c\x0f\xda\x67\x58\x5b\xc7\xf0\x48\x5e\x91\xd9\x2b\xf2\x0a\x1e\xd1\x5d\x67\x97\xd6\x3b\x46\x99\x18\x13\xe4\x00\x33\x32\xa1\xc8\xcc\x8b\x95\x7e\x48\xb4\xf1\x99\x63\x74\xec\xb9\xda\xea\x56\x95\xaa\xda\x69\x7a\x1b\x47\xaa\x9a\xed\xe7\x15\x2d\x31\x43\x1b\xd2\xf7\x60\x74\xee\xbe\x9b\xf6\xa0\x42\x5e\x82\x0a\x65\x3c\x47\xdf\x91\xea\xf7\x96\xed\x89\xbd\x68\x4e\xe5\xce\xd4\xe5\x66\xdc\x7e\xdc\x8d\xa9\xec\x3b\x9c\x96\x1d\x1c\x8f\x78\x91\x69\xc5\xd4\xb0\xa0\x91\x4a\x71\x0b\x6e\xa2\x74\x46\x79\x5b\x17\x8c\xde\xd6\xb5\xe8\xba\x04\x40\xe2\xba\x45\x5d\x9f\x87\xf3\xba\x5a\x37\x2f\x56\x6f\xdf\x60\x9a\xdb\xda\x9b\x76\x03\xb8\xd3\xbd\xad\x73\x4d\xeb\xd5\xcf\x37\xf4\x5d\xb9\x6a\x29\x9b\x9b\xbb\x89\xcc\x99\x7c\x93\x6a\xe1\x7b\x67\x47\xfe\xb6\xa5\xa5\x63\xf6\xec\x8e\x96\x9b\x7e\x15\x85\xb5\xcb\x8f\x24\xd4\x89\x2c\xdf\x51\xd7\x28\x49\x8d\x75\x1d\x7c\xf6\x1d\x4f\xcb\xd1\xfe\x65\x3b\x36\xd2\x3e\x7f\x8a\x43\xec\xe5\xd4\xee\xaf\xb5\x80\x6f\xe1\xd2\x55\x75\x93\xe9\xb8\x8b\x72\xf4\x75\x17\xf5\x4e\x7b\x50\xb2\x75\x40\xd0\x19\xa2\x26\x96\x70\x91\xfa\x55\xd8\x04\x97\xac\xc6\x2b\xb7\x5e\xf2\xb9\xad\xcc\xdd\xea\xd7\x56\xac\xed\x5f\xe3\x34\xab\x5f\xc3\x00\xb0\x18\x3b\x5a\x16\x5d\xd2\xff\xc4\xcb\xe4\xee\xc9\x20\xf9\x4f\x88\x2f\xde\xbc\x79\xf1\x92\x8b\x2f\x9e\xfc\x65\xfe\x07\x58\xba\x74\xcf\x82\x84\x3f\x91\xff\x09\xdc\x0d\xef\xce\x9a\x75\x24\x30\xab\xb3\xfe\x37\xd3\xf1\xf5\x93\x74\x4d\xa4\x3e\xfd\xa3\x91\x74\x3f\xa4\x13\x2e\x37\x9d\xb7\x30\x5d\x3b\x38\xbe\x8a\xcd\x4f\x9d\xfe\xbb\x38\x74\xe3\x4b\xea\x6f\x3f\xf5\x05\xf5\x87\x57\xf0\x60\x38\x64\xb2\xda\xf8\xc5\xaf\xee\x29\x7a\xfe\xdf\xfc\xaf\x0b\x0f\x55\x70\xe6\x6f\xbe\x0c\xe4\xa3\x9f\x02\xdf\x4b\xc4\xa7\xfe\x40\xfd\xed\x4b\x37\xde\x73\xd0\x54\x63\xb8\xc3\x88\x4d\x9b\x76\x14\x1c\xff\x2f\x1a\xb8\xa3\x82\x73\xff\x91\x6d\x57\xdd\xf8\x12\x02\xd4\x34\xe5\xe4\xfe\xc8\xfe\x14\xed\x42\x28\x38\x0d\xb4\x96\xe7\x1a\xa2\x7e\xce\xe9\xe0\x45\xb6\x10\xd7\xc7\x50\x73\x68\xd6\x5d\x18\x42\x31\x2e\x95\xcc\xf4\xb1\x05\xde\x91\xc8\x50\xd3\x12\x36\xea\x72\x58\xa1\x88\x05\xfb\xc7\xf0\x65\xd4\xef\xee\x7d\x91\xd6\x29\xb4\x5f\x6c\x12\xb1\x93\xb1\x31\x06\xe2\x23\xb5\x66\xaf\xe4\x15\x9a\x7c\xea\x0e\x9f\xd1\xe8\x32\xfb\x89\x3f\x62\xb2\xd9\x4d\x76\xce\x81\x45\x11\x36\xcc\x94\x14\x8e\xcf\x90\x74\x3f\xa0\xd6\x54\x32\x0a\x97\x85\x53\xe1\xcb\xc3\x61\xb8\xbc\x31\x9d\x6a\x05\xb4\x5f\x14\xb1\x83\xb3\x9b\xec\x36\x53\xc4\x4f\xfc\x66\x97\xd1\x48\x39\x65\x82\x57\xf2\x9a\x6b\x89\x8f\x18\x18\x1b\xe3\xc4\x62\x93\xf6\xae\x33\x93\xaa\x3b\x66\x4a\xba\x7f\x0a\xb5\x86\xd5\xfb\xa2\x65\x0c\x0f\x5d\x9f\x38\x88\x9a\xa9\x64\x63\xb0\x6c\x5b\x5d\x22\xe6\xe4\x74\x0c\x38\x9e\x88\x54\xdf\x23\x9d\x49\x47\x1a\xab\x52\x14\x35\xe2\xc0\xc6\xeb\x72\x1f\x7b\xd1\xf3\x3b\x28\xd4\x0b\x32\x98\xf5\xd3\xdf\xb7\x71\xb5\xf1\x18\xbf\xad\x67\xa3\xcd\x31\xfc\xc0\x1d\x0e\x5b\x1b\xde\x4c\xef\xe4\x5f\xa0\x27\x5c\x48\x77\xf8\x63\x72\xe8\xf4\xad\x21\xf9\x63\x77\xbd\x0b\x43\x70\x39\x0c\xbd\x7b\x17\xd0\x3b\x83\xb8\xe0\x1e\xf9\x04\xec\xf7\xb6\x8b\xb5\x5e\xf5\x66\x76\x69\xcf\xd2\x3b\x9a\x86\x97\xf6\x5c\x2d\xea\x29\x5e\xa0\xa7\xdd\x7a\xba\x9c\x3a\xf1\xab\xba\xba\x5f\x02\xf7\x55\xed\x21\x77\xbd\xab\xfe\x6b\x09\xbb\x91\xd6\xdd\xa5\xad\x7f\x28\xc0\x68\x7b\xca\x7a\xe0\x39\x3e\xad\xa3\xd1\x37\xa6\x6d\x11\xa6\x0c\xc6\x15\x6a\xa8\x46\xe3\xa2\x20\xd1\x43\xea\x0e\xf5\xc1\x53\x77\xdf\x7c\x7e\xad\x27\x76\xfc\xa6\xd6\xae\x05\xbd\x3f\x82\x2d\xa7\x4e\xc1\x8a\x0a\x8c\x2e\xd6\xea\x39\x03\xa4\xeb\x5d\xf8\x14\xbc\x05\x9f\x62\x94\xc3\x6f\x1f\xda\xf9\xc2\x92\xf8\xc8\xfa\x15\xfd\x97\x47\x38\xc3\xe1\xb7\x41\x7a\xfb\xfb\x65\xe0\x2e\xa7\x7d\x06\xdc\xae\x7f\x81\xe8\x13\x4f\x94\x79\x10\x08\x39\xd0\x1c\xb4\xb5\xb2\x16\xa5\x3a\x24\x23\x5a\x2f\x7c\x00\x8a\x02\x7c\x30\x7e\x82\xd3\xc1\x91\x0b\xd4\x97\xd4\xbf\x3d\x38\x3a\x72\x71\xa8\xc1\xd7\x96\x5a\x36\xf8\x09\x30\x3d\xf8\x60\xfe\xd3\xb0\x1f\x16\x9c\x3c\x07\xba\x02\x3b\xe7\x43\xa1\x2a\xdc\xc5\x28\x3b\x9e\xde\xbe\xf2\x78\x67\xe7\x6a\x87\x5c\x6f\x12\x77\x3c\xfd\xa3\xa7\xdf\x3a\xf4\xf6\x39\xa0\x16\x26\xfe\x71\x6e\x94\x85\x9b\xae\x3f\x85\x00\xc1\x14\x22\x7b\x59\x85\x62\x3f\xbb\xf8\x82\x79\x53\x46\x66\x75\xe1\x44\x41\x19\xde\xe9\xe0\x49\x38\x9d\x88\x93\xdd\x92\x39\xff\x5b\xa1\x8e\x31\xd9\xed\xcc\xf7\xd4\x51\xc6\x20\x09\x12\xfb\xbf\x18\x8f\x0d\xce\x93\xbd\xec\x13\x70\xa7\x81\x91\xc9\x0f\x1d\x9e\x89\x9b\x6a\x30\xeb\xb3\x91\xa6\x6d\x60\xb6\x7a\x48\x97\x28\xd5\xd8\x0d\x26\x75\xf6\x66\x5c\xe9\xfb\x63\xcd\x74\x7e\x68\x37\xa4\x82\xce\x44\xb5\x73\xe4\x19\xe3\xa8\xe0\x36\x34\xdd\x79\x46\x2b\x38\x83\x05\x14\x41\x1e\x75\x36\xe9\x26\x85\x23\x2a\xa2\x1c\xd9\x19\xaf\x86\x92\x58\xbf\xa6\x86\x87\x4d\x23\x18\x25\x87\x46\x9a\x3a\x2b\xcd\x11\x73\xb9\x62\xea\x19\xae\x92\x43\xb9\x62\x5e\x2d\x36\x37\x94\xcc\x75\x96\x69\x93\x1c\x92\xd1\x72\x74\x41\x81\x2e\x2a\x2a\xbc\xbb\xe2\xe9\x94\x3d\x1d\xd7\xb9\x8c\xda\xb6\x89\x2b\x8a\x82\x62\x10\x8d\x41\xd5\x25\x5d\xcc\x74\x5c\x82\x34\xd2\x56\x0d\x3f\xb8\x5d\xe0\x8c\x34\xf0\xf4\x71\x44\x39\xfe\xf2\xf1\x48\x32\xb2\x6c\xeb\xb2\x60\x1f\x09\xca\x82\xd9\x32\x7b\xdd\x9c\xf9\xd7\xb7\xf2\x4e\xc6\x6c\x97\xcc\x8c\x93\x6f\xdd\x73\xfb\x1e\x7a\x29\xd9\xe9\xe5\xf5\xf3\xe7\xac\x9b\x6d\x31\x0b\x32\xb4\xa3\x29\x58\xf3\xad\x3b\x41\x18\xff\x6c\x10\xf2\xa8\xa5\xad\x25\x92\x8c\xe0\xe7\xf2\x27\x77\x1c\x3f\xbe\x43\x23\x61\xe2\xcb\x96\xc5\xf1\x7c\x73\x44\x90\x4d\xb1\xd8\x92\x1e\x53\x23\x67\xb7\x73\x8d\xa6\x9e\x25\x95\xe1\x58\xcc\x24\x0b\x2c\xfe\x1a\xd8\x6f\x1f\x3e\xfa\x9b\x3b\x30\x7e\x65\x33\xc6\x9b\x35\xa2\x94\x29\xc9\x55\x0c\xc8\x83\x6a\xb5\x1d\x08\x1b\xd4\x65\x29\xc1\x33\x98\x25\xc1\x92\x0d\x77\xef\x74\xa7\x28\x94\x7b\x4f\x10\xa1\x32\x0e\x55\x01\x24\x0b\x79\xca\xcd\xc4\x39\x41\x06\x04\xad\xea\x6b\x18\x95\x85\x2d\x9d\x4d\x4c\xb6\xa9\xd3\x69\xd5\xd6\x02\x05\x2b\x9d\x4d\x30\x06\x81\x12\x56\x6c\xfe\x0a\x68\x55\xd7\xe4\x69\x9f\x8f\xe9\x6c\xfa\xce\x26\xf5\xeb\x82\x55\xdd\x41\x59\xf5\x7a\xdf\x51\x5f\x30\x36\xd4\x84\x36\x50\xd9\x24\x35\x2b\x2f\xec\x99\xfc\xe0\x2e\x58\x35\x38\x74\x4f\xd9\x89\x34\xdd\xef\x66\x1c\xbc\x88\xcb\x68\x23\xda\xce\x90\x1a\x6c\xd1\x9e\x2b\xfe\x62\x58\x07\xee\x8d\xfb\x31\x1e\x97\xbd\xf2\xe5\x49\xad\x5c\xf1\x2d\x83\x63\x0b\xae\xba\xed\x8e\xdb\xae\x5a\x30\xdf\xd4\x6c\x52\x84\xdf\x0a\x8a\xa9\xd9\x34\x5f\xb9\xa4\xbd\xbb\x87\xe9\xa8\xa9\x69\x17\xfa\x63\x8e\xe1\x8d\xc3\x8e\x58\xbf\xd0\x5e\x53\xd3\xc1\xf4\x74\xb7\x5f\x72\xc1\x3d\x5f\xfb\xd6\xd7\xee\xb9\x80\x50\xce\x6b\x2c\x2e\x7b\xe5\xc0\x50\xf2\xbc\xbd\xcb\xdb\xdb\x97\xef\x3d\x6f\xdb\x72\x73\x9b\xf9\x13\xf7\xdc\xf3\x09\x73\x9b\x79\xf9\xb6\x4f\xee\x9a\x3d\x74\x4d\xdc\x97\x0e\xd7\xd6\x86\x93\x75\x6e\x4f\x2c\xde\x96\x4c\xb6\xc5\x63\x1e\x77\x5d\x52\x8b\x4b\xfb\xe2\xd7\x0c\xcd\xde\xf5\xc9\x2d\x4f\xec\x9a\x3b\x77\xd7\x13\x74\xfe\xd7\xb1\x67\xbd\xd4\x06\x85\xb2\xa9\xcb\xb2\x21\xdd\x8f\x24\x55\x97\xb0\x55\xe0\x52\x46\xca\x86\xea\x3a\x9c\x99\x70\x7a\x4c\x16\x2c\x16\xf5\xdf\x8c\x46\xc8\x52\x57\x91\x23\x82\x5c\x40\x99\x3c\x3d\x46\x51\x7e\x47\x74\x14\x49\x18\xc9\x09\x72\x4e\x90\x4d\x90\x35\x0a\xa2\x96\x5a\x16\x72\x32\x0e\x16\xc1\x22\x29\x6b\xb9\x04\x09\x59\xc4\x08\xa4\xbe\x89\x52\xd4\x06\xb8\xb5\x2c\x01\x2a\xca\xb2\xe2\x19\x48\xb3\x1f\x20\x57\x66\x91\x24\x8e\xd3\x07\x8f\x0b\xb2\x11\x46\x8c\x3e\x23\x6c\x32\xe1\xa2\xb4\xf9\xce\xeb\x30\xb4\xbd\xfa\x29\x20\xdd\x8b\x36\x8d\x1e\x6b\xbe\xf9\x51\x3c\x22\x4a\x30\x42\xe5\x3c\x63\xd4\x03\xe6\x98\xd1\x08\x9b\x2c\xaf\x52\x19\xf4\xcd\xaf\x67\xfc\xc2\xab\xd0\xf6\x2f\x47\xfa\x8e\x8d\x0e\xf5\xd5\x9f\x3a\xb3\x8c\x51\xaa\xb8\xac\xe3\x53\x94\xf4\x70\x13\x05\x44\x88\xb3\x96\x51\x7b\x8d\xcf\xa8\x3e\x64\xaa\x28\xec\x07\x94\x71\x4c\xd4\x6a\x62\x54\x1f\xb2\x58\x44\x49\xa5\x6d\x0c\x23\xb2\xfa\xce\x59\x0a\x89\x2a\x7d\xa4\xf3\x68\x1d\x1a\x29\x4b\x74\xd8\x92\xae\x06\xc9\x70\x75\x40\x41\x0a\x74\x50\x82\x54\x32\xe3\x0a\x64\x5c\x75\x14\x7c\xb7\x88\x66\x16\xa5\xd3\xd1\xb4\xeb\x48\x34\x99\x8e\xe1\xa8\x9f\x29\x29\x76\xe8\xa2\x5e\x26\xa2\xab\x6d\x98\xc3\x73\x76\xcc\x77\xcd\x59\xb8\x73\x6c\xe7\xa2\xae\x9a\x83\xb0\xf0\x60\xcd\xe8\xb1\x40\xe7\x70\x67\x60\x68\xc7\x10\x3d\x2f\xe8\x06\x60\x4c\x86\xf9\x3b\xe6\x84\xcd\x6a\xae\xa0\xc6\xf1\x73\x2a\xc2\xde\x77\xc3\x1d\x77\xdc\x30\x7f\xff\xb1\x6b\xd6\x5b\x93\xf3\x5f\x70\x6c\xed\x1d\xde\xb9\x73\xb8\x77\xab\xe3\x85\xbe\xfa\x1d\x3b\xea\xfb\xb2\xc7\x46\x2f\xa8\x6b\xd1\x3e\xee\x96\xba\x0b\x92\x43\x43\xc9\xf2\xd5\xfc\x3d\x0d\xa6\xb9\xf5\xc9\x16\xd9\xba\xfe\x9a\x63\xfb\xc9\x4f\x0b\x0a\x1d\x25\xdb\x72\xbd\x2d\x96\x96\x29\xbd\x8c\x83\xe3\xed\x0e\x26\xd0\xd8\x0b\xba\xdd\x6f\x22\xee\xa6\x62\x1f\xfa\x45\xd8\x1d\xae\x40\x5a\xd7\xc5\xa7\x3c\x21\xbd\xf7\xec\x0e\x8e\x77\xea\x77\x28\x25\x11\x2f\x99\x2d\x2c\xea\xd2\xe1\xa3\x1f\x79\x3d\xe2\xe5\x4c\xf6\x9e\x50\x6a\x70\x30\x15\xac\x3f\x09\x86\x93\xf5\x41\x2d\x1c\xea\xb1\x9b\x38\x6f\xe4\xf5\x47\xb4\xa8\xae\x45\x3b\xc7\x76\x12\x5d\xe9\x20\xdb\xb7\xd9\xa9\xee\x3e\xf1\xc6\x1b\x27\x0e\x3a\x7e\x7a\x84\x42\x6a\xf8\x1b\x07\x47\x07\x25\xf5\x4a\xca\xbd\xbb\x57\x1a\x1c\x1d\x6c\xf4\xe3\x88\x57\x45\x47\x7e\xea\x38\x48\x23\x0f\x3b\x37\xf7\x0d\xef\xdc\x59\xf0\xf5\xa9\xcb\x55\xb5\xdd\x6c\x58\xd7\x8d\x62\xcb\xf0\xe8\xf6\xa0\x3d\x51\x52\x85\x2a\x60\xa8\x27\x8a\x1a\x51\xea\x18\x45\x75\x64\xc6\x26\x91\xa2\xab\x40\x61\x74\x70\x43\x36\xbb\xe1\x20\xa3\x28\xca\x04\x3a\xb8\x81\x64\x37\x1c\x9c\x40\x2c\xd2\x35\x9f\xc6\x27\x73\x1b\x0e\xb2\xe8\x20\xc2\x15\x36\x62\x89\x2a\x0b\xb1\x0f\x6f\x15\x46\xb2\x1f\xd2\x10\xec\x43\x19\x7e\xe9\xb4\x61\xb6\x40\xdb\x37\xd0\x9e\xa6\x95\x85\xa0\x3e\xe8\x91\x4d\xa3\x25\xa6\x71\x10\x38\x65\xe7\x70\x36\x3b\xfc\xfe\xbb\x3c\x3a\x36\x3a\x81\x46\x8f\xf1\xd9\x37\x4e\x64\x0f\x6e\xc8\x67\x37\x1c\x8c\x78\x19\xe5\x04\x99\x35\xb6\x53\x55\xf2\xb9\xd1\x63\xc7\x18\xa3\xfa\x9d\x37\x02\x5a\x7b\xe1\x71\x6f\xa4\x12\x0b\xbd\x1d\x0d\xe8\xd4\x00\x5f\xb2\x30\xd5\x87\x14\x1d\x32\x2e\x1d\x7b\x65\x7a\x98\x2d\xa5\x0c\x55\xfa\x5d\x5d\xd4\x45\x81\xff\xbb\x16\x55\xc2\x28\x44\x92\x11\x82\x68\xfc\xb8\x20\x9f\x3c\x08\xc8\x1b\x61\x73\x79\xa5\x77\xab\x63\xf2\x3d\xed\x23\x20\x66\xc7\xd6\x5e\xac\xc3\xc3\x8e\x50\x65\xbc\xb1\xea\xf0\xfb\xd4\x67\x06\x46\xb2\x40\x02\x07\x4f\xea\x72\x5f\xdd\x7e\x45\x46\xde\x02\x06\xee\x2a\xea\xd1\xc0\x59\x2d\x64\xe7\xed\xc1\x48\x14\x22\x50\x58\xe1\xed\x30\x0d\x5e\x26\x92\x62\xab\xa4\x80\xd5\x52\x41\xf6\xa4\xaf\xa9\x24\x79\x57\x9a\x46\x7c\x07\xe1\x7a\x93\x45\xfd\xbe\x05\xb6\x50\xf5\x06\x04\x48\x12\x8b\x90\x33\xa2\x84\xc7\x8b\xa1\xca\x58\x49\x64\x0e\xfa\x46\x9a\x26\x14\xed\x29\x1c\x95\xc2\xcf\x57\x6f\xaf\xb3\x40\x97\xe5\xb4\xc4\x20\x8d\x1c\x38\x8d\xc8\x48\x51\x68\x24\x8e\x95\xa5\x7b\x53\xa8\x1c\x46\x8e\x0a\xfc\xfa\x33\x65\x49\x5f\x44\xdf\x46\x3f\x46\xff\x89\xfe\x8c\xa6\xc0\x0a\xf5\xd0\x0e\xbd\x67\xfa\xad\x4e\x55\x5d\xb3\x55\xd7\xd5\xe9\xab\xfd\x56\x57\xdf\x3f\xd7\xf5\xff\xeb\xfc\xe7\x4a\x5f\x5d\x5f\xd0\xa6\x98\xa2\xb6\xe5\x19\x58\x4c\xa0\x94\x51\xba\x2b\xf0\xba\x51\x39\x3c\x55\x11\x26\x67\x89\x3f\x5b\xf8\xff\x46\x7a\x7c\x96\xf8\xe9\x65\x06\x65\x42\xd1\xea\x46\x81\xb1\x50\xa5\xf7\xf7\xf1\x52\x4d\xff\x7a\x66\xc5\x2b\xe2\xf2\x7f\x9d\x21\x72\xa6\xd0\xff\xa9\x84\xea\x4c\x91\xe5\xc3\xe9\xa3\x1c\x3a\x8d\xc6\x75\x02\xae\x42\x1d\x18\x09\x1f\xf8\xcd\x7c\x0d\xfd\x02\xbd\xf7\xff\xfe\x2b\xf9\x9f\x8c\xd2\x92\x5e\x46\xc5\x78\xad\x81\xa2\xbf\x81\x50\x6a\xba\xb6\x51\x2f\x24\x9c\x67\xe2\xdb\x27\x82\xa5\x1d\xcc\xff\x95\xd1\xfd\x61\x47\xdf\x94\xb6\x13\xce\x36\x75\x6a\x61\x7d\x14\xd2\x5b\x15\xe5\x51\x0a\xcf\x2b\x8e\x4d\xc8\x76\x36\x41\xae\xa9\x13\xb2\xff\xc7\xc6\xe8\x39\x46\xd4\xe4\x51\x46\x09\x68\x13\x76\x60\x42\xa1\xe3\x8a\xe4\xf4\x82\x8e\x8c\x94\x14\xab\xf4\x70\x7b\xf9\xf3\x01\x9a\x43\x1d\x8f\x20\x96\xca\x5e\x75\xba\xcd\x86\x3c\xa8\x07\x6d\x99\x2e\x7d\xa5\x10\xae\x45\x72\x4e\xa6\xdd\x57\xf2\x1e\x11\x2a\xba\x90\x70\x96\x7a\x33\x9e\xd6\x01\x20\xa6\x09\x68\x23\x54\x3a\x9b\xd6\x65\xb3\xa5\x65\x98\xb2\xdd\xd4\x17\x40\xf9\xb4\x68\xf8\x2e\x8f\x59\x44\x23\x5e\x90\xc4\x71\x2a\xea\xd6\xb1\xf3\x8b\x41\x40\x11\x6f\xae\x28\xaf\xa5\xdf\x8d\x57\x7e\x5e\xce\x7a\xc7\x74\x29\x4e\x81\x85\xa7\x00\xc2\xfc\x77\x2d\xa6\xfc\x93\xf4\x9a\x04\xce\x78\x8e\x16\xc4\xb1\x09\xc5\x1b\x29\x4a\x6e\x23\xc9\x08\x8c\x79\xb3\xf2\xf3\x32\xd5\x57\x8f\x14\xb1\x25\x74\xdc\xfa\x28\x9a\x8d\xfa\xa9\x8d\xfb\x87\xa9\xfa\x87\xa2\x0a\xe9\xee\x69\x86\x2a\xe6\x75\x6a\x51\xa1\xd4\x0f\x93\x9b\xc8\x8d\x95\xa9\xc5\x40\x60\xc3\x41\x18\x9b\xb9\x36\x7f\xfa\x40\x22\xb2\x88\xcf\x41\x71\xe1\xe7\x20\x04\x9c\x00\x7c\x48\x27\xc1\x5b\x49\x2a\x61\x0f\xf1\xa1\x68\x2a\x91\x4a\xa4\xa2\xa9\x4c\x2a\x94\x0a\xa5\x32\x09\x77\xc2\x1e\x4a\x75\x63\x5d\xd7\x17\x12\x6e\xd6\x0f\x6e\x5e\x01\xf5\x0d\x75\x6c\x3c\xab\xfe\x62\x81\xd6\xfc\x23\x63\xd9\xec\x58\x6e\x24\x10\x50\x72\x39\x25\x10\x18\xc9\x69\xd7\x94\x18\x5a\x00\xe1\xec\x38\x8c\x28\x47\x0c\x38\x1b\xc8\x06\xb2\xea\x98\x51\x34\x06\x60\x6c\x3c\x90\x0b\x18\x3c\x8a\xc7\x10\xc8\x05\xc6\x61\x2c\x60\xd4\x36\x82\xd9\x80\x6f\x96\x89\xee\x1f\xb2\x05\xfd\x13\x0e\x79\x74\xe9\x84\x46\xe6\x3a\x83\xa9\x0c\x6d\xcf\x68\x26\x98\x09\xba\x79\x0a\xc0\x3d\x98\x62\x94\x09\x45\x51\x4e\xbc\x91\x0d\xc0\x78\x80\xe4\x02\x59\xac\x68\x5f\x6b\x6a\x50\xcd\xe6\x72\xb9\x37\x4e\x40\x36\xab\x28\xb9\xc0\xe4\xf8\x34\x9f\xa9\x09\x84\xc2\x65\x77\xa9\x55\x7a\x8f\x3a\x3c\x08\xc5\x3f\x3c\x03\x07\x88\xea\xf1\xa9\xa8\xec\xb7\x16\x17\x3d\xa7\x56\xca\x6e\x73\xba\xec\x4a\xcd\xd1\x61\x44\xc5\x47\xda\x84\xa0\xe6\xbc\x91\x08\xf9\x46\x95\x6e\x62\x55\xb9\x3e\x8c\x2f\xd7\x99\xca\xa5\xe6\xf4\xb2\xe5\xf4\x77\xe9\xa5\xca\x56\x97\x4c\x77\xe6\x9a\xd5\x4b\x37\x3d\x03\x9e\x33\xbd\x60\x18\xb5\xa3\xa5\xe4\xaf\x4c\x02\x39\x50\xb3\xb6\xa3\xad\xf6\x85\xcb\x1b\x81\x99\x29\x12\x5f\x63\x8a\x9b\xbc\x26\x35\x66\x32\xc1\x2b\x26\xaf\x29\x6e\x32\xa9\x7b\xe0\x10\xdc\x31\x63\xf4\x93\x34\x44\x63\xe0\x15\x93\x9e\x64\x8f\xba\xc7\x34\x73\xb4\xee\x57\x0d\x2d\x25\xff\x5e\x2c\x17\x2a\xeb\xb6\x94\x7d\xea\x32\x33\x45\xe2\x55\xda\xcb\xf5\xe7\x1e\x52\xf7\xe8\x0f\x85\x57\xe0\x8e\x19\xa3\xf1\x52\xbd\xac\xf4\xea\x10\x1c\x2a\x94\x38\x66\x9a\x39\x5a\x2b\xd7\x52\xf4\x31\x26\xc1\xac\x9a\xd6\x5e\xd3\xfd\x43\x48\x33\x45\x32\x89\x73\xd5\x7a\x5a\xf4\x3b\x67\x14\x55\x7b\x3f\x5c\x37\x63\x34\xd2\xcb\xf5\x24\x93\x60\xae\xa9\x6c\xaf\x2a\x1f\x13\xd2\x4c\x91\x4c\xe2\xec\xd5\x9d\x21\x1a\x3f\x79\x66\xe7\x9a\x4c\x71\xad\x60\x33\x44\x6b\x73\x51\x3b\x5a\x8a\xaf\xa1\xfd\xa8\x95\xca\x08\xd5\xee\x96\xf1\x35\xc5\xd4\xd3\xc6\x0d\x79\x67\xe6\xc6\xa2\xf3\x9b\x80\x96\xe2\x55\xa5\x67\x7e\xe8\x41\x70\xb6\xde\xa6\xcf\x5c\x0a\x02\x93\x20\xab\xf4\x67\xfe\x13\x1d\x08\x57\x9c\xad\x4f\xb4\x67\xb6\x33\x09\x72\x4d\xb9\x9c\x1f\xb2\xf1\x49\xfb\x59\x9a\xb3\x20\x87\xd6\xe9\xc6\x0e\x1d\x2f\xb5\x12\xa5\x47\x97\xe5\x3b\xfc\xa5\x1d\x79\xb2\x0f\x52\x15\x73\x08\x8f\x64\xe1\x7d\x4a\x22\x70\x59\x2a\xdb\xcf\x8f\x07\x02\xba\x93\xf4\x40\x20\x4f\x21\x92\xb8\xec\xc0\x46\x1c\x20\x94\xa6\x98\xa4\xba\xc1\x4b\x27\x72\x03\x1b\xc3\x2b\x7a\x05\x6d\x0e\x11\x7b\x86\x23\x65\x75\xb4\x0a\x1d\x10\x2b\xb5\x58\xd7\xe6\xb6\xe9\x92\x86\x10\x54\x60\xcf\x69\x65\xd5\x48\xc0\x02\xcd\x98\x60\xe3\xc9\x56\x68\x70\x24\x60\xac\xa4\xe4\x36\x30\x31\x26\x0b\x0c\x7d\xfd\x44\x4e\x90\xd9\x91\x31\x1d\xb6\x69\x8c\xec\xb4\xd9\xc6\x6c\x36\x40\x3a\x7a\xa8\x8e\x7e\x4b\x46\xca\x0c\x6e\x79\x72\x15\x65\x56\x8f\x8c\x04\x02\x25\x7d\x70\x46\xa7\x75\xdc\x28\x5a\xa6\x73\xc2\x33\xb6\x5a\x25\xcb\x40\xc7\x79\xf8\x5c\xa1\x05\x04\xa2\x37\x56\x19\x0b\x6f\x3b\x65\x20\x8c\xeb\x1c\xe5\x49\xad\x04\xe4\xc5\x69\x8a\x7a\x8c\x5e\x00\xca\x37\x71\xeb\xda\xe8\x67\x7b\x3b\xa6\x4d\xd0\x0d\xd5\x2e\x0c\xe0\x65\x0a\x88\x84\xa6\x64\x41\x45\xb4\x8e\x48\x90\x73\x5a\x13\x8c\xc1\xac\xa1\xa4\x8a\x74\xee\x43\x72\x68\x93\x8e\x9b\x44\x9b\x40\xe7\xf7\x93\xa5\x81\x40\x60\x92\x26\x60\xb4\x63\xe5\xfa\x63\x46\x6e\x84\x50\xc1\x53\x6d\x1f\xe8\xc2\xc9\x92\x97\xe7\x8f\x97\x9c\xd2\xde\x7b\xef\x19\x6e\x69\x99\xb1\x0a\xa7\xb5\xcf\xce\x84\xf5\x50\x58\xd3\x83\xd4\xfb\x4f\xb9\x3e\x7d\xb8\x1b\x8a\x8e\x8e\x4b\x6e\xc8\x2a\xdd\xfd\xcc\x9c\x80\xa0\x9d\xc3\xaa\x32\xbc\x73\xc5\x1d\xcf\xee\xa0\xab\x59\x76\xf4\x58\x67\xd3\xf8\xf0\x4e\xa2\x9c\xe5\x06\xce\x6a\xd1\x3b\x87\x71\x6e\xc7\xb3\x77\xac\xa0\x4b\xdf\xb1\xd1\x40\x53\xa7\x9e\x7c\x86\x78\x34\x63\xb9\x45\x5c\xb1\xcd\x49\xf7\xea\xdb\x99\x4a\x37\x45\x1f\x9c\x80\xa0\x33\x0a\xb6\x73\x18\x14\xad\xdc\x67\xb9\xc1\xe4\xf2\xd9\xea\x12\x03\x2d\xf1\x59\xe2\x11\xc5\xca\xcb\x4e\x65\x29\xbf\xd0\x88\xec\x14\x15\x4d\xfb\xfe\xba\x0b\xb6\x06\x3a\x8e\x4e\xbc\x64\x31\x58\xb4\x2e\x70\xe8\xec\xd7\xb2\xbd\xc1\xcc\x29\x74\xad\x3d\x2c\x0e\xa6\x92\x43\x83\xa3\xb8\x57\x17\xae\x1f\xa6\x27\x26\x4f\x5d\x05\x8c\x0e\x4e\xf6\x6c\x3c\xb8\x71\xe3\x41\xe6\xdd\x82\xe8\x5d\x07\x34\xbb\xf9\xe0\x86\x8b\x6e\xb9\xe5\xa2\x0d\x07\xbf\x3b\x3a\xa8\x25\x54\xff\x4b\xa7\xd6\x75\x41\x7a\xfe\x2e\xed\x81\x83\x83\xe4\x7f\x6b\x59\x37\xe6\x3f\xa3\xdf\xd4\x4d\x12\xd4\xab\xf5\x9c\x07\xa7\xeb\x8c\x98\x75\x3d\xca\xe2\x28\xe5\xaa\x51\x49\x0a\xba\x8d\x15\x83\x71\x9a\xff\x5a\x70\x10\x11\xf3\x45\x10\xd3\x74\x2a\x19\x63\x5b\xa7\xeb\x5f\x39\xed\x89\x80\xec\xe2\xd1\x01\x62\xb5\xf0\x16\x9b\xd5\xce\xb2\xa1\xbe\xcd\xbb\x3e\xf1\xc9\xcd\xe3\x11\xea\xae\x56\xdb\x43\x26\x23\xe3\xf8\x7f\x3d\x9c\x82\xb1\xcf\xa9\xbf\xe1\x1b\xbc\x46\xbb\xc3\x6a\x0c\x71\xf3\x33\xdb\xc6\x76\xaf\x49\xd7\x5b\xa6\x90\x37\x42\x93\x69\x87\x88\x77\x0a\xa9\x57\xdc\x5a\xc2\x92\x45\xf4\xbb\x9b\x8d\xd6\x69\x2b\x81\x08\x0d\x31\x48\x52\x2f\x7b\x15\x61\xb7\x8e\x2a\xd5\x10\xd5\xf5\x23\xfd\xa4\x1b\xe2\x7d\x44\x76\xf0\x22\x13\x6a\x88\x31\xd1\xa2\x64\x4c\xe7\x9b\xbb\xfb\x20\x41\x99\xbf\x58\xa9\xe9\x5d\xdd\x5b\xa3\x1d\xf0\x27\x4a\xc1\x67\xee\xb8\xae\xf9\x81\x45\x5f\x58\x74\xbc\xf5\xba\x3b\xb2\x9b\xef\xbd\x75\xe5\x63\x2b\x6f\xbd\x77\x73\x76\xbc\x37\x72\xdb\xd1\x7f\x3b\xb6\x61\x99\xf2\xe8\x1d\xb7\x8f\x06\xfb\x6e\xaf\x4d\x5c\xfe\xc8\x65\x47\x1f\xfe\xf8\xc1\x4b\x1f\xb9\x2c\x51\x7b\x3b\xec\x18\x5e\x3d\x7f\xfe\xea\xe9\x87\xbd\xd7\x3f\xe6\x34\x9b\x9d\x8f\x5d\xbf\xee\x96\xc1\x76\x51\x6c\x1f\xbc\x05\x0c\x3f\xde\xbb\x74\x67\x4f\xc8\xc8\xc9\xcd\x7d\x5b\xe7\xde\xf4\xf2\x3b\x27\x56\xae\xbb\x76\xfb\xf2\xd5\xa1\xc0\xca\x65\xdb\xaf\x3d\x7f\xc5\xd8\xf4\xef\xca\xad\xf5\x42\x61\xde\xd3\xbe\x9a\x0f\x9c\x7d\x75\x6f\x49\xa8\xb3\x29\x9f\x2d\x8b\x9f\x99\x5c\x53\xe7\x19\x0e\x94\xc6\x31\xbd\x97\x2d\x41\x0a\xe2\xb7\xaa\x3d\x2a\xe9\x7e\x2c\x77\xb3\x0a\xb2\xa3\x28\x5a\x80\x10\x24\x75\x10\x3b\xce\xe9\xa0\xa0\xbd\x90\x0e\x07\x53\xd5\x05\x83\x3e\x60\xcb\x9e\x97\x2a\xcb\x45\x25\xe6\x6e\x17\xf7\x5e\x6a\x22\xd7\xb4\xde\xab\xfe\x5c\x4a\x31\xd9\xa6\x0d\x35\x10\x91\x26\x0e\x13\x54\xc4\x2e\xd4\x0a\x0d\xa8\xed\x08\xdb\x15\x53\x7f\xd6\x7a\xef\xbc\x89\x5c\xa9\xdc\x81\x0d\x07\x73\xe9\x0b\x5d\x56\x7c\x51\xa8\xb5\x5e\xbd\xcf\x63\x0b\xb5\xd5\xc3\x65\xae\x7f\x1d\x2b\x57\xe5\x09\xe8\x4e\x2d\xf8\x4c\xdf\x1c\xf5\xbe\xd4\x82\x72\x65\x36\x8c\xcd\x8e\x05\x4a\xfe\x8b\x0a\xfe\xc8\x7d\xa8\x11\x25\xa9\x97\x21\x2a\x42\x8d\x50\xb8\x11\x8a\x07\xdd\x07\x7e\xa8\x06\xf5\x43\xb6\x18\x0e\x88\xd8\xe6\xc7\x81\x3e\x90\x2a\x9d\x94\x5f\x19\xfe\xa1\xfa\xc3\xb0\xc1\xe3\xad\xe9\x30\xd4\xdc\xf6\xd8\x6d\x35\x86\x59\x71\x8f\x6a\xd2\x75\x69\x06\x75\x5d\x9a\xc1\xed\x4f\xbc\xa3\x4e\xbe\xf3\xc4\xf6\xed\x4f\xbc\x03\xcc\x3b\x4f\xbc\x59\xed\x68\xfd\xc5\x1b\x3e\xfe\xf1\x1b\x6a\x3a\x0c\x06\x8f\x77\x78\xcb\x96\x61\xaf\xc7\xd6\x01\x3f\x1e\xd5\x73\xd3\x4f\x5f\xd5\xb2\x6d\x2f\x3f\x06\x67\xab\xbf\xdb\x99\xeb\xe6\xa2\x30\x7e\xba\xbc\x3f\x1a\x83\x8c\xf6\xb9\xfc\x13\x75\x33\x78\xe2\xb3\x0a\xb5\xea\xa8\xf1\x7a\x0c\x5a\x5d\xd5\xcc\x3f\x57\xb7\x44\x4d\x87\xad\x58\x2d\x83\xa1\xa3\xe6\x86\x8f\x7f\x1c\x1b\xff\xa7\x75\x33\x53\xdd\xfd\x56\x94\x29\xeb\x21\x6a\x43\xec\xc3\x57\x49\x89\x78\xf3\x74\xbf\x89\x15\xaf\x1a\xf9\xe7\x6a\xa2\x0b\x05\xe1\x2b\xff\x54\xe1\x0b\x74\x1e\x83\x0a\xab\xcc\xbc\x0f\xc7\x21\x61\xaa\xf4\xbb\x1a\x6d\x28\xd4\x10\x0d\x71\x3a\x04\x44\x30\x4e\xb2\x92\x98\x93\x44\x45\x94\x74\x8b\x87\x62\x10\x67\x0b\x95\x29\x9c\xd4\x57\x5f\xcd\xdd\xfb\xfa\xbd\xb9\x57\xd5\x57\xa1\xed\x55\xa2\xbc\x0a\xb9\x33\xf2\x68\xc1\x4b\x68\x75\x0a\x1a\x5e\x14\xa7\x5c\x51\xa0\x0d\x1e\x83\x36\xa4\x51\xa8\x45\xbe\x88\x36\x17\x87\x50\x07\x5d\x2b\x57\xa1\x4d\xe8\x32\xb4\x07\xdd\x42\x39\xaf\x9f\x41\x5f\xa6\x52\xfc\x56\x68\xe8\x85\x64\x37\xc4\x33\x15\xe1\x68\x45\x18\x9c\x8e\x50\x50\x0b\x27\x82\xf1\xf0\xd9\xd3\x9c\x33\xfe\x6c\x61\xb6\x32\x6c\x2f\x85\x53\xda\xb5\x4c\xbd\x93\x55\xcb\x04\x6c\x23\x36\xdb\x88\x4d\xb1\x8d\xdb\x6c\xe3\xb6\xc2\x15\x83\x6c\x93\x63\x36\x1b\x19\xb1\xe5\x4b\xf7\xe9\x09\x66\xbe\x2c\x9e\x55\x54\xb8\x2e\x9f\xc7\x6d\xb6\x9d\x5a\x86\xf7\x15\x1e\x0d\xa6\xde\xa7\xd8\x99\x9c\x92\x1a\x84\x9d\x34\xc5\xbb\x15\xc7\xfc\xbb\x67\x44\xa9\x33\x5c\x14\x4e\xa0\x9f\x0a\x7f\xea\x18\x4d\x67\xcb\x23\xa2\x4c\x2a\xda\x4f\x7b\x11\xd1\x8e\xa8\x80\xa3\xa9\xf3\xea\x5c\xa8\x05\xad\xd5\xa8\xb5\xa2\x6e\x10\x6f\xa7\x7e\x42\x28\x36\x00\x54\x89\x0d\x0b\xd2\xc1\xa2\x75\x5c\x0c\x87\x1a\x98\x12\x7a\x44\x86\xaa\xbd\x16\x2d\xc6\xdc\x2e\x4e\x79\xfc\xd0\xca\xfe\xad\x8f\x6d\x7c\xf2\xcd\xf7\x4e\x66\x2e\xde\x92\xc9\xf8\xda\xba\xae\x9f\xb8\x22\x54\x47\xe5\x5d\x75\xa1\xc1\xd1\x41\x36\x17\x32\xf1\x3f\xbf\x7f\xdd\x42\x5f\x76\xe1\xce\x39\xdb\xd5\xf7\x36\x59\x25\x9b\x2d\x50\x1f\x3a\xff\x63\x8f\x2c\xde\xf9\x9d\x9d\x91\xc4\x8d\x27\x5d\xc6\xfa\xfa\x7a\xf8\x23\xde\xb1\x3e\x30\x3b\x73\x20\xff\xf8\x2e\x6b\xb8\xa6\x56\x74\x91\x5d\xa1\x39\xf6\x09\x91\xca\xdf\xfe\x62\x9f\x13\x4a\x0d\x0e\xee\xce\xb3\x51\x89\x65\xae\x0d\x89\x41\xbf\x6f\xdd\x1c\xa3\x41\x0e\xe3\x37\x43\x0e\x67\x6b\x6f\xa4\x2f\x23\xef\xb4\xb0\x36\xc9\x81\x10\x57\xaa\x3b\x8b\xcc\xa8\x05\xc5\xd1\x42\x74\xb5\xf6\x1d\x72\xbc\x33\x2d\xd3\x23\xa4\xb8\x68\x2a\x12\x8d\x19\x43\x0d\xbc\x93\x56\xca\xed\x74\x25\xe2\x72\x4a\xab\xab\xd3\xf5\xff\xab\x59\x48\xf6\x2b\x2f\xbc\xf8\xe5\x2f\xbc\xfa\x13\xf2\xfb\x3f\xde\xe7\x90\xd9\x4e\x21\x2e\xc7\xbc\x6d\xa1\x36\x97\xdb\x2b\x6f\xff\xca\x65\xb2\xa3\x65\xf6\xf5\x4f\x3e\x7e\xa8\x3d\xf8\xf1\x89\x2f\xfc\x8f\xda\x0a\x7b\x72\xb6\x6d\xcf\x8c\xc0\x53\xdf\x33\x5c\xf7\xec\x55\x6a\xe7\xd7\xaf\x6d\x1f\xe7\x8c\xc4\xc7\x79\x78\x99\x33\x33\x0c\xf9\xd5\x9c\x94\x91\x3b\x69\xc7\xfc\xb3\xeb\x0d\xcf\xb5\xc0\x9f\xfe\x67\x0d\x89\x91\xa0\xd1\x25\x94\x7f\xd0\xa8\x7b\xe3\xac\xe2\x1f\xb8\x1c\xd5\xf6\xa7\x78\xf1\x4c\x0c\x05\x13\xd3\x2e\x89\x93\x54\x10\x4a\xb4\x59\xab\x79\x66\x2e\x8a\xda\x5e\x61\x79\xa7\x8d\xe1\xf6\xa9\xa3\xfc\x2a\xe6\x1d\xfa\xfe\xae\x82\x8f\xd1\xe9\xec\x35\x97\xc3\x08\x22\x74\x40\x0c\x32\xd0\x47\x21\xac\x67\x2c\x26\xbe\x74\x26\x6e\x9b\x09\x2f\x50\x0f\x33\x6e\x4b\x9f\x20\x30\xb0\x5b\x0f\xe0\x8f\xcd\x58\x81\x43\x33\x73\xa2\x98\xe0\xe9\xf7\x04\x81\xb1\x33\x6e\x81\x35\xeb\x81\xfc\x8e\x99\x2b\x57\xd6\x8d\xff\x26\x72\xa2\x6e\x3a\x7b\x16\xe0\x69\xb4\x0a\xb9\x5d\x75\x40\x01\xeb\x1c\x22\x29\x80\x38\x48\xd1\x18\x44\xab\x12\x39\xed\x8c\xdb\x85\x15\x8a\x60\xa3\x93\xdb\x75\xcd\x51\xf5\x1a\x59\xe6\x84\x86\xd6\x94\x8f\x33\x38\x38\x52\x83\x5b\xef\xcb\xbe\xf6\xd0\xf4\x34\xf0\xc9\x93\x8f\xc3\xf3\x0b\x5b\xec\x6c\x91\xf6\xae\xb7\xdb\x5b\x16\xa8\x57\xcb\x49\x59\x5d\x3a\xe7\xfe\x7d\xfb\x3a\x2d\x76\x30\x78\xe1\xc8\x67\x17\x2d\x17\x26\xaa\xd2\xa9\xa7\x7d\xff\xf6\xa4\x4e\xab\xe2\xa9\x27\xb9\xfd\xec\x38\x32\xa1\x26\x84\xa0\x1d\x3a\x80\xd8\xdd\x2c\x89\x1a\x41\xa6\xf8\xad\x61\xea\xf3\x28\x23\x43\x24\x9d\x09\xcb\x1a\x05\x2e\xb3\x7e\x60\x1e\x06\x50\x3f\x35\xe0\x3f\xd1\x0d\x7d\x3d\x16\x78\x4f\xbd\x6f\x2d\xeb\x72\xdb\xdd\x6a\xbf\xda\xef\xb6\xbb\x5d\xec\x5a\xf5\xe3\x01\xa9\x1d\xfe\xf6\x86\xa3\xce\xe7\x7c\x03\xfe\xd6\x2e\xe1\x79\xa7\x93\xa6\x1e\x18\x98\xec\xad\x7f\x0c\xb6\x0c\x40\x4a\xfd\xb4\x6a\x09\x86\x2d\x6f\xbf\x6d\x09\x07\xe1\xbf\x61\x73\x20\xc3\x2f\x86\xef\x37\x37\xab\x5d\x8b\xf9\x4c\x09\x7b\x57\xa1\x3a\xc6\xa8\x0c\xaa\x1f\x6c\x88\x41\x9a\x2a\x98\xb9\xfd\xc0\xde\x90\x57\xec\x4d\xac\xc9\x55\x9b\xcf\xb9\x42\x26\xc9\xc1\x22\xc1\x56\x2b\x59\x79\xe6\x33\x13\x28\x84\xd9\x90\x0b\x67\x6b\xdb\x9a\x4c\x58\xe1\x65\xb1\xb9\x88\xb5\xa9\xd1\xe6\x18\xb1\xa8\x93\x22\xf8\x1b\x21\xa8\x4b\x00\x4b\x62\xbe\x60\x41\x97\x42\xdf\xe8\x96\x9d\x50\x67\xd2\x71\xb7\xcb\x61\xd5\x95\x5e\xda\xf1\xaa\xbc\x82\x57\xe5\x9f\x64\x94\xa2\xa8\x62\x72\x6c\x9a\xe4\x82\xac\xfa\x9b\xc9\x6b\x32\x1a\xff\x4e\x05\x3b\x78\x55\xfe\xe7\x78\x55\x7e\xa4\x42\xba\x41\x46\x2a\x24\x1c\x7f\x37\x1a\x4d\x5e\xd3\xdf\x26\x9f\x94\x50\xc1\x7f\x11\x53\xf6\xa3\x32\x58\xe6\xa3\x48\x55\x3a\xe3\x19\x07\xc7\xeb\x3e\x62\xea\x80\x32\xc0\xe8\x76\x2f\x53\x9c\xe7\x9c\xda\xdc\x97\xce\xf4\xb1\xa9\x42\x04\x04\x3a\x87\x3b\x8b\x7f\xf8\xeb\xf4\x74\x3c\xd9\x86\xc7\xe7\xdd\xae\xac\x6a\x4b\xee\x1c\xdb\x99\x6c\x2b\x9c\xd2\x5b\x33\x73\x87\x5a\xa2\x76\x7a\xe9\xa1\x59\x98\xaf\xd3\xd3\x79\xf4\x38\x92\xbc\xa0\x46\x7d\xe3\x40\xa4\xb5\xa9\x6f\x81\xb7\xe6\x82\xa4\xb6\x71\x4f\x5e\x50\x43\x92\xe5\xb0\x6a\xf5\xd6\xdb\x6b\xc2\x2d\x3d\xcb\x0b\x91\x3a\xd6\xbd\x42\x6d\x39\x05\x54\x83\xc2\x28\x8b\x36\xa0\x1d\xe8\x5a\x74\x73\xc1\x43\x70\x81\xf3\xe8\x72\xb8\x75\x9d\x58\xaa\xe3\x12\xa9\xa0\x17\xd9\x92\x8d\x42\x34\x03\x7e\xe8\x07\x0a\x51\x91\x71\xb9\xc1\x05\x7c\x09\x2c\xc7\x0d\x7c\x84\x2a\x23\xf6\x17\x0c\x11\x98\x8a\x47\x40\xc5\xa3\xd9\x69\x2f\x85\xaf\x4d\x21\xb3\xc7\x6c\x34\x02\xd2\x3a\x6f\x4c\xf7\xb4\x34\x5e\x61\x0b\xcb\x62\x1d\x02\x47\x7d\xda\xe9\xfc\x33\xd8\x6b\x57\xd6\x1e\xf5\xf9\xd4\x3f\x49\x21\x27\x0c\xaf\xce\xdf\xff\x67\xf5\xcf\x05\x38\x1d\x90\xa4\x90\x53\x7d\xaa\x80\x98\x03\xcb\x9c\xf8\xae\x8a\xc7\xe4\xff\xa2\x3f\x1a\xee\x9f\xf6\x42\x30\x4e\x21\x3a\x12\x80\x9e\x12\x15\xe6\xb8\xe3\x34\xfd\xd8\xf5\xab\xee\x5d\xb5\x06\x96\x3b\x43\x92\xfa\xa7\x5a\xd0\xc1\x75\x40\xfe\xb3\xd3\xa9\x3e\xb5\x16\x6f\x94\x40\x2a\x00\xee\xa8\x7f\x7a\xd7\xe9\x84\xe1\xb5\xd7\xd1\x0c\xea\x97\x9c\x97\xea\x4e\xa3\x50\xc5\x23\x3f\x3b\xed\x65\xda\x7c\x30\x82\x10\x99\xa4\x7c\xcd\x1e\x5d\xaf\x73\x9a\xe4\x5b\x9b\xcd\xc4\xca\x58\xaa\xe8\x5e\x80\x85\xa6\x6b\x29\x64\xa4\x60\xdc\x8f\x71\xce\x63\x7b\xd7\xe6\xa1\x07\xe8\xa9\x8f\x2e\x6a\x8b\x36\x67\x3c\xb6\x77\xad\xce\x9b\x97\x75\xc7\x2f\xea\x9d\xdb\x1a\x3a\x4f\x90\x2c\xc2\x23\x02\x6b\x18\x83\x59\xc3\x0f\xdf\xbc\x12\x3c\xc5\x0c\x1e\x7c\x5e\x7a\x63\x77\x4f\xad\xcb\xbd\xba\xc6\x5e\x1f\x96\xdb\x57\x1d\x0d\xd5\xce\xe9\x68\xc9\xd6\xd5\x5c\x68\x33\xec\x33\xf9\x05\x30\xf5\xed\xb8\xbf\xb8\xd7\xc6\xda\xf7\xec\x47\xb1\xe9\xc8\x17\xba\x9b\xde\xe2\x42\xe6\xd4\xbe\x59\x52\xbd\xba\x29\x3a\x0f\x38\xe2\xcd\x66\x8b\xae\xb0\xb3\xde\x88\xa2\xfb\xa2\xd1\x81\xc8\x4a\xb0\x17\xa0\x14\x04\x63\xf9\x5c\x84\xd9\x4e\x05\x4b\xba\xe1\x2b\x46\x9b\x11\xc2\xfe\x92\xdf\x91\xaa\x97\xc8\x44\xdf\x4f\x47\x49\xa4\x60\xc3\x5d\xf9\x78\xbf\x0f\xa2\xda\x65\x14\x7c\x10\xf6\x42\xd6\x1b\x86\xc0\xb8\x76\x53\x3b\x30\x5c\x9e\x26\x24\x14\x10\x4d\x9b\xb1\x10\xab\xb2\x97\xa1\x30\x5a\xa2\xd5\x35\xd4\x01\x91\x28\x75\x71\x68\x85\x60\x2a\x21\x93\x50\x2a\x48\x21\x0f\x12\xe9\x7e\x1c\x74\x86\x88\x0c\xce\x20\x55\x27\x66\x8a\x7d\x14\xd5\x7d\xd8\x50\x4b\x9d\x44\x8a\x7c\xe4\x1f\x27\x3c\x06\x42\x80\x30\x60\xb2\x7e\x52\x55\x95\xef\x3d\x73\x08\x1c\x87\xb1\xd3\x40\x08\x31\xd4\xdc\x09\xb0\xef\xeb\x3f\xc2\x7f\xc8\xab\x84\x49\x2e\xbb\x70\x59\xb2\xbb\x39\x11\x13\x5d\x97\x7a\xc3\xab\x2e\xbd\xf2\xf6\xd9\x83\xeb\x86\x32\xe4\xad\x47\x1f\x9d\x6c\x31\x5a\x08\x6f\xc4\x0e\xcf\xe9\x47\x21\x04\xb6\xc7\x7e\xcb\x44\x8c\x16\xa3\xa5\xe5\xb7\x8f\xa9\xef\xa9\x3f\xc5\x8f\xbe\x54\xeb\x93\xb2\xa3\xf3\xfa\x63\x7d\xc1\xc8\xec\xa8\xb9\x76\x43\xb8\x6e\xee\x9e\x2d\x9d\x1b\xbb\xe7\xb4\xf6\x04\x87\xf5\x75\x88\x9d\x42\x1c\x22\x37\xa3\x30\x5a\xfc\xe1\xea\xc6\x9e\xbd\x6e\xe4\xc3\xd7\xed\xed\xbc\xca\x90\xe9\x75\x1b\xbe\xfc\xca\xdb\x17\x6c\xd9\xba\x84\x39\x77\xd5\x7e\xf6\x52\x6d\x3b\x9c\x59\xb3\x81\x4b\xe7\xcd\x99\x1f\x1d\xa6\xf5\x02\x84\xf8\x03\xac\x8e\x37\x87\xc2\x10\x34\x82\x8b\xe3\x81\x8e\x90\x68\x84\xae\x63\xc1\xb8\x8b\x28\x30\x9c\x47\xea\x53\xdc\x7b\x56\x73\xcd\xa4\x12\x99\x93\x47\x91\x7e\x9b\xd5\x5c\x43\x94\xc8\x1c\x82\x22\xfd\x14\x67\x8f\x49\x35\x0c\xfa\x26\x51\x5b\x73\x43\xc3\xa0\x8f\x41\x6d\xcd\x3a\xbf\xef\x75\x3a\x97\xee\xd0\x31\xb2\x28\x7a\xb6\xd3\xe1\xe2\x9d\x0d\xbc\x88\x75\xf4\xe7\x92\xed\xb1\x1f\x17\xc8\x0f\xea\x23\x24\xda\x90\xb2\xfb\xb1\x4e\xe8\xa6\x92\xd4\x45\x52\x01\xa8\x84\x82\x4d\xa7\x33\x4e\xad\xf9\x9d\x0e\xb7\x8e\x3c\x1d\x77\x71\xca\x05\xcb\x9b\x17\xb7\xcf\x0f\x5f\x19\x00\x97\xb9\xe1\xc0\x8e\x58\xef\xea\x50\x73\xe8\xf2\x15\xab\xaf\xf3\x87\xfd\xb1\xf0\xf0\xa6\x63\xc6\xb0\x51\x00\x8c\x71\x7d\x98\x1c\xdb\x34\x1c\x8e\xf9\xc3\xfe\xeb\xd6\x0c\x5f\x1e\x6a\x0e\xad\xee\xcd\xbe\xd5\x01\x2c\x0b\x9e\x50\x5b\xbb\xab\x6b\xf6\x70\xeb\xca\xf5\xf0\xd5\x15\xda\xad\xbd\xd1\xe3\x51\x16\x88\xdd\x94\xea\x0a\xcf\x6f\x5f\xdc\xbc\xfc\x82\xf5\x2b\x5b\x87\x67\x77\xb9\xda\xdb\x42\x1e\xcc\x60\x0c\xc0\xa0\xaa\xac\x85\x92\x74\xa5\xfc\x55\x6f\x2b\xd0\x65\x8c\x42\x7d\xd9\x25\xe8\xf7\x88\x78\x67\xc9\x5b\x3a\x55\x40\x8f\x20\xed\xeb\xa4\x9c\x77\x14\x28\x84\xb5\x25\x21\x40\x97\x84\x80\x8b\x51\xd4\x9f\xfd\x8c\xc2\x10\x16\xf8\x0d\x80\x7e\xa6\xfe\x2c\x92\x8c\xe8\x20\x8b\x91\x64\x64\x0a\x9d\x54\xff\x71\xf2\x24\x18\x4e\x92\xac\xf2\x4b\xf5\x19\xcf\x41\x5d\xb9\xf2\xa0\x07\x16\xfd\x52\x9f\x32\x74\xfc\x46\x8a\x92\xb3\x5d\x45\x07\x4f\x9e\x3c\x88\xb5\x23\x22\x48\x98\x52\xd8\x6b\xa8\xbe\xeb\x3c\x6d\x65\x07\x3e\x52\x2a\x8e\x11\x74\x2d\x7a\xde\x95\x88\x57\x14\xf2\x8c\x0a\x44\xf9\x4a\xcc\x03\x97\x23\x0c\x3a\x08\x3a\x58\xb7\xb5\x44\x92\x11\xe6\x52\xf5\xfe\x93\x07\x33\xe9\x91\x8b\x2f\x7f\x86\x96\xf7\x8c\xfa\xec\xbb\x52\x35\x79\x4d\x2b\x4d\x26\xe6\x15\x7a\x56\x6f\xcc\x1f\x3d\x79\x70\xfb\x67\xf1\xf2\x6d\x97\x5c\xa5\x57\x20\x85\xfd\xea\xfd\xca\xc1\x93\xf2\x48\xa2\x50\x11\xef\xb4\xaa\x0a\xf3\x55\x93\x69\xa5\xc9\xab\x3d\x42\x3b\xdf\x98\x3f\xaa\xd5\xf0\xba\x92\x9e\xb4\xee\x27\xa9\x41\xd7\x73\x48\x67\xd2\xb2\xdd\x21\xb2\xd4\xe1\x65\x09\x8b\x9c\xc9\xaa\xd9\x3d\x1b\xff\x98\x9b\xb7\xe5\xd0\xb5\xfb\x53\x36\x8b\xcf\x62\x4b\xed\xbf\xf6\xd0\x96\x79\xba\xc2\x0b\xce\x62\x65\xe2\xee\xfe\x25\x5f\x27\x4f\xe5\xd1\xda\xc7\x6f\xd9\xbb\x72\xb1\x97\xe7\x38\xde\xbb\x78\xe5\xde\x5b\x1e\x5f\xab\x4f\x8c\x05\x7a\x09\x95\xf0\x21\x42\x68\x11\x42\xee\xa0\x3d\x18\xae\xd2\x7e\x38\xf3\xba\xca\x62\xa8\x40\xe8\x95\x42\x89\xb8\x4b\x61\x95\xd3\x0a\x54\x40\xbc\x90\x0a\x25\x50\x50\x86\x92\xa7\xa9\xb7\x45\x65\xe3\x40\x76\x60\x23\xe8\x27\x25\x39\xa4\x30\x28\x07\x01\x0a\xa2\x41\xe9\xbb\x8a\xf0\xb2\x09\x2a\xa2\x62\x51\x72\x48\xf7\x9c\xa7\x1f\x87\x68\xbb\x11\x4a\xf3\x8e\x23\x1e\x0d\x95\xf5\xcb\xc3\x05\x58\xc7\x70\x0c\x52\x41\xe7\x74\xc5\xda\x4c\x2a\xd4\x50\xd8\x63\xc4\x20\xd3\xc7\x94\x15\xa4\x83\xc9\x74\x26\x4c\xe1\x62\xb0\xae\x59\x4e\x3e\x67\x31\x58\x18\xa2\x66\xcd\xe2\x14\xba\xea\x1e\x7d\xf1\xdb\xb7\x25\xd0\xbd\x73\x51\xaf\x83\xb1\x37\xd9\x04\xb7\xdd\xc2\xca\x9d\x73\x2f\xed\xac\xd9\x78\x70\xa3\x08\x31\xd1\x0c\x39\xc2\x58\x0c\x16\x56\xef\xf3\x11\x35\x67\x33\xf2\x30\x82\x25\xf3\x76\xf7\x53\xd7\x4c\xd2\xa5\x8a\x04\x46\x1f\xf7\x5f\xd5\xd1\xbd\x24\x68\x08\xf1\x96\xb8\xc7\x14\x18\x9c\xbb\x40\x6a\x69\xd3\x6a\x15\xac\x37\x4b\x78\x04\x78\xa3\x56\xb7\xc6\xa9\x00\xa7\xcb\x25\xdb\x2b\x3c\xd0\x3a\x34\xea\x95\x70\x3c\xab\x23\xf8\x64\x64\x28\x85\xb4\xf2\x67\xd2\x8d\xc1\xb8\x8b\x1d\xa3\x84\x2a\x78\xee\x7f\x7a\xc5\xd5\x0e\x2c\xaa\x0a\x6f\xb4\x98\xb3\x02\xbb\x46\xfd\x2f\xf5\x6d\xc2\x89\xc6\xac\xdd\x32\x6e\xb2\xc1\x4d\x23\xc3\x27\x61\x35\xb0\xa2\x83\xd1\x29\x56\x50\xde\x57\xef\xfb\xf2\xf0\x88\xfa\x51\x9b\x69\x9c\x31\x6a\x9d\xe6\x80\x9a\x35\x60\xcc\xca\x0e\x50\x44\xec\xb8\x7a\xc5\x37\xef\x92\x4b\xfe\x7d\x4e\xe9\xfb\x0d\x20\x41\x39\x1d\x8d\xb4\x6a\xe7\x20\x09\xca\x24\x48\xf1\xad\xb9\x53\x8f\xa8\x4f\x3f\x2d\xf8\x6a\x3b\x1f\xff\x91\xfa\xf4\x8f\xd4\x5f\x6b\xc7\x4f\x30\x93\xdb\xbe\xd4\xdd\xd3\x82\x27\xf2\x2c\xc9\x76\x06\x82\x93\x8b\xc8\x33\xda\x0f\x16\xad\x58\xbc\xf8\xdb\xd3\xf5\x60\xb4\x09\x07\x85\x33\xe9\x64\xd4\x08\x45\xac\x7a\x8e\x5a\xa3\x54\x8a\x7a\xc8\xc7\xb6\xcb\xb2\xfa\x22\x24\x64\x79\xbb\xb6\xa3\x9b\x23\xcb\xf0\xbc\x9c\xc4\xb7\x56\x71\x35\x3f\xa6\xdd\x85\x04\x24\xe4\xa4\xac\xe5\x98\xa3\x27\xc6\x3f\x39\x2b\xbe\xba\xfe\x7e\x48\x53\x6b\x13\x8a\xa9\x6e\x2c\x80\xbf\x57\xbe\x1f\xbf\x08\xcf\x17\x1e\xb7\x5d\x96\x21\xa1\xbe\x48\x0b\x42\x16\x56\xbf\x5f\x2b\x95\x56\x34\xbd\x98\x2f\xaa\x2f\xd2\x1c\xe7\x7a\x3f\x64\xd2\x45\x6b\x17\x1d\x02\xdf\x58\xf5\x7e\xe6\x63\x15\xb5\x91\xcb\x95\x84\xea\x06\x00\xbd\x05\xaa\x0b\x0b\xd5\x05\x98\xa1\x0f\x8a\xcd\x6f\x2c\x36\x44\x75\x1f\xb4\x9f\x51\x2f\xbd\x13\xaa\x59\xcb\xef\xd0\x46\xa8\xee\x30\xbc\x67\x86\x36\xc8\x52\xdb\x11\x3b\x1d\x61\x99\xa0\x1c\xb4\x42\x07\x84\x64\x36\x91\x0a\xcb\xc1\x28\x04\x09\x1b\x66\x46\x6d\x93\x77\x76\xe0\xad\xae\xef\x3d\x27\x7c\xd1\x05\xa3\x0c\x5c\x12\xcf\xef\xb5\xaa\x9d\xac\xa2\xe4\xbf\x95\xff\x0e\x79\xe2\x8b\xf9\x3f\xfc\x36\x95\xba\x53\xfd\xc3\x56\xd8\x82\x03\x5f\x81\xd7\x4e\x6f\x7e\xf8\x61\x3a\x7e\x2d\x53\x59\xee\xbf\x0b\x18\x72\x41\x23\x96\x83\x3c\x1b\x96\x83\x72\x30\x13\x04\x99\x7d\x43\xfd\xdb\xe4\xeb\xf9\x85\x8b\xa0\xb9\x0e\x3e\x07\x6f\xce\x9f\x38\x6f\x0e\xf3\x4c\x64\xe2\x3c\x56\x39\xfd\x82\xfa\x1e\x98\x61\xeb\xd1\x87\x1e\x82\x55\xd0\xfc\xed\x42\x5b\xd9\x78\xdd\x67\xc7\x9a\x8a\x6f\x55\x9f\x87\x3a\x80\x63\x02\x8d\xd1\x33\x70\x68\xfd\xe0\xae\xd8\x36\x57\x6c\x40\x9d\x89\xa2\x94\xdb\xde\x07\x99\x22\x58\x2d\xc9\xe9\xb3\xd2\x76\x87\x81\xb1\x98\x2f\xda\xa3\xee\x52\x93\xea\xae\x3d\x17\x19\x45\xc6\xe0\x90\x44\x18\x71\x19\x0c\xd6\xad\xf3\xde\xbb\x4f\x27\xb6\xe7\x2c\x3c\xf6\xea\xb1\x85\x73\xf4\x8b\xfb\xde\x9b\xb7\xd5\x6a\x30\xb8\x60\x44\x94\x98\x37\xe9\xdc\x34\x39\xa6\x8e\xb9\x0c\xd8\x78\xd1\xdd\x8f\x3e\x7a\xf7\x45\x46\xac\xdf\x74\xc8\xb6\xad\xeb\xf7\x39\xf0\x6d\x94\x7a\xff\x4c\xc3\xee\x85\xa3\xc7\x8e\x8d\x2e\xdc\xdd\xf0\x19\x1a\x91\xbf\xc1\xb1\x6f\xfd\x56\x9b\xec\x90\xf4\xef\x9f\xd2\x0d\xa1\x33\x7c\x6c\x75\x83\x5d\xf7\x44\x5a\x40\x12\xa0\xde\x7a\x99\x40\xd9\xa9\x57\xa0\x40\x19\x14\xdc\x7d\x95\x45\x62\x14\x0b\x38\x4b\xfd\x79\x3d\xa3\x95\x5c\x7b\xbb\x9a\x9b\x2e\xcf\xd2\xf7\xf8\x94\x5a\x29\x23\xdd\x46\x02\x9c\xcd\x15\x40\x36\x54\xf8\x9d\x4d\x26\xa2\x43\xd8\x82\xab\x60\xfb\x04\x17\xeb\x8e\x4a\x29\xfb\xff\x0b\xe7\x10\x8a\xe0\x3f\xe8\x90\xb5\x17\x43\xdf\x1b\x5a\x7e\xbc\xba\x94\xb5\x2d\xbf\xff\x9c\x92\x1d\xca\x4f\xc1\x88\x55\x48\x11\x4f\xeb\x8c\x1d\x63\xb5\xee\xf4\x19\xba\xd4\x4a\x67\x13\x6d\xa7\x5c\x53\x27\x46\x33\x87\x49\xa0\x18\x9a\xf1\x50\xd2\x79\x81\x32\xae\xd7\x19\xe5\xb0\x9f\xe3\xba\xb2\x1c\x33\x1d\xa0\x5c\x06\xf8\xe9\x4c\xc1\x4a\x9f\xd3\x3c\xaa\x45\x29\xb4\xa0\x42\xf7\x25\x82\xa2\x11\x2a\x27\xa2\x3e\x12\x80\xd2\x1e\x11\x1c\x83\xc6\x68\x84\xd7\xe3\x5d\x8c\xa4\xdf\x38\xd3\x43\x23\xd6\x55\x86\xe1\xf3\x82\xfa\xcc\xef\x45\x87\x5d\x78\xe0\x75\x33\x48\x82\x22\x38\xe0\x00\xbb\xfd\x4b\xbf\x57\xdf\x78\x40\x34\x9a\x24\xe1\x47\xb0\xe1\x14\x4f\x6f\x98\xcc\x50\x5f\xa9\x19\xa9\x5b\xf4\x37\xfc\x1e\x16\x09\xe0\x10\x14\x41\x02\xf3\xeb\x0f\x08\x76\x87\xf0\x00\xd4\xff\xfe\x4b\xdb\x59\x30\x99\x68\x2c\x7f\x4a\x7d\xe4\x47\x82\x64\x32\x92\x17\xab\xf5\x25\xcb\x32\xbc\xda\x2a\x0f\x18\x74\x2a\xa7\xce\x79\xe8\x5e\xe2\x0c\x2f\x09\x4f\x07\x02\xf9\xf1\xfa\x60\x20\x60\xb3\xd9\xad\x67\x20\xe7\xe7\xef\x97\x96\x48\x90\x95\x25\x39\x9c\x57\xc2\xb2\xc1\x88\x08\x4a\x4f\xa5\xb8\x17\xd8\x1f\x52\x5a\xae\x03\x21\x23\x5b\x5e\x2d\xb4\x49\x5a\x67\x09\xa7\x93\x91\x06\x3e\x5a\xa4\x80\x29\x27\xcc\xed\x72\x30\x08\x7a\xf2\xcf\xa9\xcf\xc1\xa5\x78\x54\x96\xa9\xef\x91\xfc\x31\x59\x86\x51\x29\x4d\x0e\x4f\xee\x0e\x5f\x16\xde\xdf\xb9\x73\xac\x73\x5f\x38\x4c\x0e\x87\x2f\x0b\xef\xd3\x2e\xf6\x87\x99\x1e\xf5\xb9\xfc\x73\xd0\xa3\x6a\xb9\x92\x5a\x6a\x2d\x57\x52\xcb\x8f\xef\x9e\xbc\x36\x1c\xde\xdf\x39\xb6\xb3\x73\x7f\xf8\xb2\x30\xb9\x23\x1c\xde\xa7\x5d\xec\x0b\x5f\x36\xad\x5d\xf4\xbd\x7f\xb5\xc9\xf2\x0c\xba\xac\xba\xc2\x2c\x39\x43\xaf\x96\x6a\xaf\xea\x2c\x86\xe9\xda\xaa\x64\x9a\x5f\xd3\x8e\x19\x38\x0c\xe7\xd0\xeb\x62\x14\xdd\xe9\xb3\x24\x12\x1d\xc9\xad\xac\xd0\xa5\x54\xfa\x3d\xc5\xe3\x25\x7e\xbd\x1a\xa7\x6e\x51\xf5\x94\xe4\xe6\x4a\x17\xa8\x08\xb4\x12\x91\xd3\xec\x01\xe4\x43\x08\xb8\x56\x28\x83\x95\xa7\x13\x41\x7b\xa8\xec\xfe\x97\x9c\x96\x9a\x72\x92\x98\xcf\x3a\x0d\x06\xcb\x98\xd1\x06\xd9\x5c\x93\x64\xf7\x42\x56\xea\x93\x20\x5b\x4b\x3e\x1b\x9e\x1c\x13\x25\xc9\x61\xcd\x99\xb1\x12\x0e\xd7\x83\xe2\x72\xa9\x4a\x80\xae\x65\x64\x4a\x21\xa7\x59\xa4\x8d\x36\xb9\xc8\xbf\x29\xa8\x12\x66\xb4\xe9\x38\x48\x29\xc4\x74\x00\xe7\x04\x39\xd7\xd4\x58\xab\xe6\xa4\x3e\x49\xcd\x79\xed\x52\x53\x4e\xcd\x89\xe6\x31\xc1\x68\x64\x91\x2c\x4e\x3e\xb4\x24\xa0\x2a\x2e\x17\x28\xf5\x91\x30\x56\xcc\x39\xd1\x21\x4f\xa7\x05\x1a\x2b\x68\x01\x88\x96\x69\x81\x33\x3e\xc3\x27\xf1\xf6\xc2\xea\xde\xfe\xef\x05\x72\x40\xa3\x89\xb6\x57\xf6\xe2\x3b\x78\x7b\x81\x16\x68\xff\xf7\x42\xe2\x07\x64\x72\x6b\x65\x7f\x96\xe7\x7d\x0e\xd9\x90\xb3\xd0\xa7\x6e\x3e\x94\x0a\xa5\x28\xbc\x02\x6d\x3f\x23\xb1\x43\xc1\x99\x91\xf5\x4c\x1d\xb9\x8f\x1f\x4f\x76\x8e\xc0\x2b\xa2\x5d\xfd\xa5\x5d\x10\xed\x10\xb2\xab\x13\x38\xa0\x8e\xe7\xc7\x89\xb2\xc1\xe7\x3b\xee\x1b\xf6\x6d\xc0\x63\xd3\xbc\xb2\x7e\xe1\x78\x72\xa4\x13\xbe\x21\x68\x59\x44\x41\xcb\x92\xcf\xe2\x00\x04\xf2\xe3\xea\x38\x1e\xd9\xe0\x1b\xf6\x1d\xf7\xf9\x36\x8c\x9c\xed\xbb\xaf\x41\xcd\x25\xbd\x4b\x9e\xab\x2f\x7a\x0c\xca\x80\xce\x40\x98\x51\x6b\x3b\x40\xe1\xe1\xf3\x7f\xd0\x1b\x02\xbb\x8e\x48\xb5\x16\x21\x5a\x35\xec\x47\x60\xdc\x1b\x89\x36\xd7\x69\xe9\x68\xcb\x61\xd7\x11\x99\xb5\xe3\x96\x6a\x7f\xf9\x7a\x39\xa8\x2f\x7f\x63\x71\xd2\xa9\x83\x06\x91\xd5\x59\x14\x99\x74\x14\x67\xfa\x20\xa1\x5f\x9d\x81\x50\xf6\x0e\x8c\xc8\xb2\x3a\xe6\x8f\x36\xed\xf9\xce\x2d\x17\x77\x06\x4d\x8f\x9a\x45\x9e\x73\x91\xb6\xd1\xd8\x63\x77\x36\x59\x2c\x5e\x1c\x99\xd6\x5c\x5f\x86\x11\x6d\x26\x18\xa9\xb7\xdb\x5b\xc6\xa2\xfd\x9b\x46\x6e\xdc\xd6\xf3\x95\xff\xb4\x10\xa3\x07\x36\xef\x49\x76\x8c\xb5\xd8\x59\x9c\x9b\xd6\x58\xe5\xf9\x1f\x23\x0e\x49\xc8\x4f\xe5\x29\x60\x07\x3b\xb2\xc5\xa0\xa0\x79\x38\xcd\x0d\x15\x56\x00\x4d\x21\x50\x54\x44\x02\x15\x2a\x86\x67\x28\x20\x42\x4e\x51\x60\x79\xfe\xd7\x53\x08\xfb\xd5\x5f\x52\x25\x45\x3d\x35\xde\x54\xb5\x24\x97\xf1\xdc\x04\x54\xa7\xed\xb2\xa0\xfc\xd1\x24\x82\xf1\xea\x99\xa2\xba\x95\x98\x1b\x24\xb7\x9a\x93\x07\x64\x35\xe7\x96\xec\x4d\x58\x69\x3a\x5e\xd0\xf3\x14\x08\x85\x52\xa8\x6c\x22\x72\x51\xa8\x5e\xcd\xd6\xd6\x42\xae\x3e\x14\xca\x07\xa6\x29\x85\x56\xcd\x5f\x55\x65\xd2\xa7\x8b\xc2\x24\x71\xee\x32\xd9\x9b\xf2\x4a\x93\x5d\x72\x43\x56\x1e\x90\x21\xeb\xde\x7d\xf6\x32\xc1\x67\x42\xa1\x50\x3d\xe4\x6a\x6b\xd5\x6c\xbd\xfa\xf3\x0f\x5f\x26\xaa\xa7\xac\xcb\x7f\xd3\x6e\x38\x67\x99\xb2\xda\xf3\x43\xfa\xbb\x7e\x51\x29\x0b\xad\x1a\xdc\x0f\x55\x34\xa5\x5d\x6b\xdb\xfc\xdb\x84\xce\xc4\x34\x07\x79\x69\xba\x9f\x63\x8d\x90\xf9\x2b\xab\xa0\x11\x84\xc2\x6e\x17\x67\x05\x91\x0f\x35\xa0\x68\x89\xa4\x8e\x64\x4a\xc1\x34\xa2\xde\xba\x5d\x56\x5d\x5c\xca\x86\x1a\x38\x5e\x27\xc2\xb9\x50\x90\x73\xeb\x41\x11\x42\x41\x8a\x31\xc5\xf4\x43\xda\xed\x22\x2f\x87\x88\xc5\xcc\x32\x82\xec\xa9\x0d\x36\x44\xe5\x3f\xa8\x0f\xf7\x6f\xd2\x1a\x68\x00\x93\x79\x5a\xa1\x36\xcf\x83\x8b\xc7\xb7\x6f\x30\x1b\x39\xd2\x4a\x5c\x02\xc3\x58\x1d\x35\xb5\xf5\xe2\xfe\x1f\xc4\xe1\x55\x9b\xd1\x44\x3c\x6c\xad\xea\x21\x04\x5e\xb0\x9a\x8c\xc4\x83\x25\xb3\xba\x6f\xd6\x0b\x07\xa4\xc6\x7a\x9f\xd3\xc6\xb0\x82\x60\xf9\xdd\x09\x8b\x93\x01\x4c\x38\x96\x65\x19\x0c\xec\x2f\x65\x61\x97\x20\x77\xcd\x92\xc4\xab\x45\xe9\x15\x40\x6e\x62\x31\x0b\x27\x04\x81\x01\x20\x0c\x21\x58\xd9\x69\xb1\x88\x57\x7b\xc3\xf3\x2d\x16\xeb\x4e\xb3\x75\xf7\x21\xc2\xb0\x2c\x03\x98\xe5\xf9\xc2\x7e\x9c\x4c\xb2\x0a\xea\x2f\x6b\xd5\x4e\xe7\xec\xeb\x28\x2f\x71\xb7\x1f\xac\xc0\xf1\x1c\x75\x85\xcd\x15\x14\xd6\x74\xc8\xf5\x02\x27\x87\x4c\x4a\xe2\xe4\x7c\x51\x92\x85\x8b\x37\x69\x35\xdd\xf4\xf7\x6f\x3f\x73\xcc\x88\x0d\x97\x18\x05\xc1\xc4\xb6\x8c\xb4\xaf\xd9\x01\xb3\xa9\x21\xd9\x8f\xe1\xd3\x92\xf8\xb0\x28\xc1\xdd\xea\x3d\x5a\xca\x63\x82\x0c\x07\x64\xe1\x16\x51\xfa\xcf\x27\x7e\xb5\xcf\x50\x63\x3a\x60\x06\x6c\x64\x7d\x8d\x1b\x87\x7e\x22\x89\xb7\x08\xb2\xfa\xd1\xaf\xe8\xa0\xc6\x80\x92\x53\x88\xbc\xc2\x21\xb4\x59\xf7\xb3\x5e\x22\x31\x63\x0c\x5d\x1c\x33\x69\xf7\x2c\x1d\xa2\x37\x9d\x4a\xc6\x48\x34\x66\x48\x25\xd3\x99\x12\xaf\xc9\xcf\xd0\xee\xd3\xaa\x51\x70\x25\xc9\xb8\xfd\x1c\x79\xe5\xfb\x27\x24\xf1\x36\x41\x1e\xb8\x69\x78\x7e\x0d\x6b\xb7\x5e\xc2\xdb\xac\x46\xbc\xeb\xe6\x70\x78\xc5\x4d\xfe\xf0\x70\x32\x1d\x6d\x5f\xd6\x31\xd0\x1c\xab\xb1\x3f\xf7\xa0\x2c\xdc\x26\x4a\x5d\x97\xcd\xeb\x91\x38\xbb\x65\x85\xc1\x2a\x0a\xc4\x9d\xe9\x3b\xbf\x65\xd3\xf5\xf6\x96\xf0\x60\xac\x23\xd5\x39\x92\x59\x10\xf6\xc2\xa6\x4f\xfc\xd2\xfb\x45\xad\x35\xbe\x68\x6c\x6b\x4f\x78\x38\xa7\xe3\x36\x13\xc6\x66\xbc\xc5\x6b\x58\xbb\xdc\x17\x6f\x68\x76\x3b\x6d\x52\xa8\xb6\xad\xb9\xab\x7b\x49\xf3\x1d\x2f\xfb\xff\x55\x90\x25\xf1\x29\xae\x21\xd8\x62\xe3\x24\xc7\xbd\x56\x20\x26\x22\x85\xea\xdc\x6b\xe7\x7b\xdb\xa2\xb5\x21\x59\x72\xb8\x3b\x22\x7d\x73\xd7\x15\xfa\xec\x66\x56\x41\x7d\x45\x1a\x5c\x04\xde\x55\xf0\x14\x1c\x45\xd1\x92\xf2\x70\xa6\x44\xc0\x44\x8a\x74\x78\xd1\x14\xbc\x15\x5c\xee\x44\xdc\x45\x6e\x96\xc4\xc7\xdc\xaf\x7e\xfe\x51\x68\x14\x4d\x06\xe7\x77\x6d\x46\xf5\xa5\x9c\x51\x16\x76\x1e\x7c\xc8\xa5\xae\xa1\x3c\xb5\x07\xbb\xfe\xfd\x1e\xad\x68\x84\x7e\x7f\xbf\xef\xb0\x3f\x21\x4a\x4c\xcb\x76\x51\x3a\xf2\xaf\x8e\xa7\xd5\x07\x6c\x92\x64\x81\xab\x7e\x64\x14\x0e\x08\xf2\xda\x95\x92\xb8\x5d\x94\x76\xc9\xc2\x47\xb5\xb4\xdb\x45\xa9\x77\x95\x44\x41\x0d\x11\x99\x62\x15\x8d\x5a\x0f\x86\x0a\x40\xfe\x05\x98\x92\xd2\x70\xd3\x49\x8e\xb8\x5b\x76\xb9\xfb\x20\x23\xd3\xb0\x8b\x87\x44\x71\x98\x39\xcb\x03\xce\xc1\xe1\xf5\x5f\x10\x64\x95\xda\x28\x42\x40\x3f\xff\x87\xfa\x6d\x83\xc1\x24\x7d\x47\x36\xfd\x44\x0e\x9b\x9a\xf9\x6f\x1b\x9c\xdf\xb6\x9b\x8c\x06\xf5\xfb\x3f\xa1\x63\xee\x57\xd0\xa0\x9f\x65\x49\x84\x25\x92\x78\x89\x20\xaf\x91\xc4\x1d\x82\x8c\x07\x6c\x36\x9b\xa4\x9e\x1f\x39\xdf\xb3\xce\x0e\x8f\xc8\x36\xd1\x9e\x7f\x56\x16\x76\x88\xd2\x1a\x59\xb8\x44\x94\xd4\xaf\x0a\x72\xc1\xef\xbd\xbe\xef\xe8\xa4\x7b\x75\x6d\xe0\xc7\x91\x6d\x5a\xc9\x4a\x83\xb1\xfc\xe9\x94\x42\xfa\xac\xc6\xc8\x37\x8f\xaa\x39\xc8\x8e\xc2\x55\xf9\x1f\xa8\x5f\x80\xf7\x29\xc3\x92\x97\x85\x47\x8b\x22\xea\xa2\xdc\x1a\xd7\xfe\x80\x5c\xf2\x83\xbd\x6a\x16\x1e\x52\xf7\xff\xf7\x75\xd5\x8a\x6c\xd7\x49\xe2\x7d\x82\x8c\x77\x8b\x52\x85\xff\x21\x03\xb2\x20\x1b\xaa\x41\x75\xe8\x4a\x84\x40\x0e\xc9\x2e\x87\x3b\x99\x96\x33\x41\x77\x30\x11\x0d\x69\x11\x0e\x57\x21\x42\xdf\x23\x12\x3a\x62\x48\x88\xe8\x9e\xa4\x49\xa9\xb4\xe5\xf9\x90\x14\xfb\x25\x28\x4f\x3b\xbb\x78\x52\x62\x38\xf0\x89\xb8\x0b\xe3\x15\x27\x06\x01\xe0\xda\x90\xfa\x7a\x00\x1e\x3a\x1c\x5a\x08\x27\x96\x3d\xbc\x02\x00\xae\x0a\xaa\x3f\xa1\xf8\xdd\xaf\x3d\xc2\x7b\x4e\x78\xf8\xcf\x9d\x7a\x94\xf7\x9c\x30\xdb\xf1\xd8\xcb\x5a\x7d\xbe\x18\xbc\x4b\x3b\x5d\x71\x01\x6b\x32\xd9\x0e\x79\xd9\x0b\xe1\x92\x8b\x79\xcf\x7e\x0f\xbf\x19\xae\xb8\x88\xf5\x1e\xb2\x99\x4c\xec\xfa\xab\xb4\x24\xf7\x34\x7c\x59\x94\x60\x0d\xb4\xaa\xaf\x02\x03\xc0\xc2\x17\x14\x45\xc9\xbf\x0a\x6d\xea\x6b\xc0\x02\x30\xf0\xa4\xa2\x04\xb2\xa2\x94\x3f\xee\xf1\xe0\x1d\xf9\xe3\x1e\xd1\x84\x77\x50\x5a\x5b\xe7\x2c\xc3\x3a\xab\x60\xf1\xa8\xc7\x61\x87\x47\x3f\x5a\x04\xab\xfa\x58\x21\x81\xb6\xbf\xed\x9c\x42\xcc\x5b\xac\x82\x12\xe8\x3c\x8a\x39\xe4\xe2\xfd\xc0\x8b\x0c\xef\x0c\xa5\x1a\xa2\xce\x90\xbd\x21\xd2\x0a\x99\x44\x3c\x63\x4f\x44\x42\xf6\x48\x2b\xa4\xdc\xf1\x4c\x2a\xe1\x4c\x27\x52\x09\xa7\x9f\x90\x64\x8c\x69\xa0\x20\xa4\xf1\x3e\x4e\xbb\x10\x41\xbb\xe8\xe3\x98\xbb\xa5\xfb\x76\x5f\x2b\xf0\x89\x65\xd7\x1e\x58\xf9\xc0\x70\xcb\x03\xd2\x79\xf2\x0f\xea\xaf\x8a\x1b\x6c\x9c\x49\x18\xba\xea\xd5\x6c\xf0\x81\x95\x4d\x0f\x2c\xbf\x71\x47\xef\x29\x7f\xdb\xa2\x9e\x75\xf1\xe5\x06\xc3\x9c\xc8\xfc\xd9\x73\x63\xb3\xfd\xf2\xa2\x9a\xc6\x9e\xf8\xe2\xd6\xb9\x3c\xdb\xdd\x30\xd0\xd6\x1d\x69\x94\x88\xf2\xd5\x21\xdf\xb1\xc3\x8b\x2e\x5f\xd8\xe1\x62\xa6\x26\x60\x12\x4d\xc1\xd7\x12\x70\x2f\x40\xfd\xfc\x47\x00\x26\xff\x8e\xdf\x9b\xe4\xeb\xbb\x2f\xce\x3f\xd8\xd8\xd9\x58\x63\xe1\xb0\xfa\x2f\x40\x58\x8b\xcd\xdb\x10\x83\x7f\x04\x13\x41\xb7\x89\x03\x50\x5f\x04\x20\x06\xd1\x5d\x1f\xd3\x71\x31\x28\xb6\x44\xc1\x5e\xd2\xe5\x06\x97\x9b\xd5\x6d\x06\x2b\x96\x64\x06\xb9\x44\x38\x2e\x8a\xf9\xc7\x3a\x9b\x70\xa0\x04\x11\x11\x60\x10\xfc\x54\x14\xd5\x1d\xa2\x2b\xd0\xd4\x39\x31\x5e\x44\x7c\xd0\xfd\x79\x94\x9e\xdb\x84\x3a\xd1\x79\x5a\x9b\xba\x83\x76\x97\x9b\x4c\x7f\xb4\xdd\xe1\x92\xcf\x01\xd3\x5d\x7d\xcd\x9e\x14\x45\xb5\xc9\x25\xce\xaf\x2c\x4a\xe7\x0f\x66\x82\xa2\xa8\x0e\x33\x8d\xa2\x4b\x2b\x72\xfe\xb9\x72\x69\xf3\xe3\x4d\x9d\xf9\x40\x69\x6f\x06\xe2\x4c\x41\x8d\xfe\x6c\x98\x42\xdc\x3e\x0e\x21\x13\x6a\x44\x03\x68\x25\x42\x90\xe8\x80\x48\x2a\xc4\x3b\x38\x1e\x74\x1c\xa6\xe2\xf6\x49\x5f\x74\xe8\xae\x8a\x75\x06\x53\x90\xee\x87\x54\x03\x17\xe2\x5a\x81\x7a\x31\x00\xce\x0a\x4e\x2d\x61\x4a\x76\x06\x53\x89\x68\x88\x4f\x68\x67\x39\x21\x33\x8f\x7e\xe9\x3c\x0b\x66\x08\xcf\xe4\xdf\x35\xa9\xff\x66\x12\x2c\x66\x35\x67\x35\x18\x5c\x39\xaa\xcb\x92\x13\x25\x32\x3f\xff\x75\xd8\x65\x31\x9a\xb1\x91\x58\xa4\xb7\xae\xc7\x19\xf5\x6e\xce\x6a\x16\x8d\xce\x7f\xbc\xa2\x8e\x0f\x76\xfc\xb5\x63\x50\x7d\x63\xe1\x9b\x0f\xbf\xc9\xec\xf8\x79\x87\x8d\x71\x40\x83\x65\xc2\x5f\x04\x81\xb2\xc9\x0e\x96\x42\x6f\x9c\x1e\x93\x3e\xfa\xfb\x0b\xb1\x5d\x32\x1a\x09\x90\x6b\x7e\x77\x41\xfe\x4f\x06\xc9\x8c\x31\xde\x43\x3e\x32\x3a\x7a\xe4\xc8\xe8\x28\x3e\x96\x1f\xd5\x65\x3f\x95\xf5\x4e\x6a\xf5\x0e\x97\xeb\xcd\x9e\xb5\xde\x50\x55\x33\xf2\x81\xed\xf0\x21\xea\xfd\xe0\xb4\xda\xc9\x67\x6d\x85\x52\xb5\x7f\x3d\x53\xad\xd5\xc9\x72\xf5\x98\x03\x67\x34\x81\x89\x10\xd8\x83\x58\xad\xce\x94\x3f\xab\xed\xcb\xfe\x3f\xda\xfe\x03\x3e\x8e\xe2\xfc\x1f\xc7\xe7\x99\x6d\x57\xf7\x6e\x6f\xf7\x76\x4f\x77\xa7\xeb\xb7\xab\x7a\x92\xae\xad\x7a\x77\x91\x2c\xdb\xb2\x70\x2f\xb2\x42\x71\x05\xdc\x00\x57\xcc\xd9\x86\x04\x48\x30\x60\x7a\x17\x60\x20\x14\x27\x04\x4c\x71\x28\x51\x20\x10\xc2\x27\x94\x84\x10\x42\x02\xc1\x49\x0c\x09\x84\x9e\x02\xd8\xba\xf5\xff\xb5\x7b\x27\x5b\x36\xa6\xe4\xf5\xfd\xff\xc0\xda\x9d\xb2\xbb\x37\x33\x3b\x3b\xf3\x3c\x33\xcf\xf3\x7e\x37\xa0\x1e\x34\x0f\xa1\xf8\xd7\xbc\xe2\x63\x57\x0c\x8e\x37\x84\xf8\xa6\x38\xde\x7f\xe2\x2a\x93\xa1\xf1\x2b\x0b\xba\xaa\x9f\x33\x3a\x72\xce\x88\x68\x05\xa2\x85\x11\x23\x72\x18\x19\x11\xc4\xba\x86\x4e\x54\xeb\x71\xd0\xef\x9f\x7e\x43\xb0\x30\xdd\x8d\xd5\xdf\x71\xb4\xfe\xc7\xd7\xf2\xab\xdb\xe3\x4b\x2b\x28\xdf\x10\x27\x8f\xa9\x80\x16\x3a\x71\x6b\xe0\xe1\xe3\xea\x7c\x4c\x6b\x1c\x6d\xa7\xd0\x91\xaa\xac\x3d\x51\x53\xc0\xda\x6f\x6e\x00\xa3\xcf\x53\x2f\x16\xfb\x7c\x17\x9a\x8d\x50\xdc\xd8\xe4\x37\x76\xee\xbf\xba\xcf\xc7\x05\x96\x30\xd8\x1e\xd4\x82\x1c\xaa\x46\x59\x38\xe2\xf5\xa4\x7f\x00\x29\xce\x60\x23\x61\x68\x83\x34\x82\xa3\x3a\xe7\x36\xa5\x5b\x7b\xba\x93\x13\xf3\x37\x7f\x45\xa5\x3f\xf4\xd6\xf7\x9f\x3d\xa1\x35\xe1\x71\x29\x0e\x67\x5c\x9e\x79\x9a\x13\xbb\x67\x54\xad\xf8\xee\x65\x67\x6c\xde\x1d\xd0\x2a\xef\x02\xcc\x98\x5c\xad\x03\x23\x9b\xdf\x6a\x5b\xd1\xbb\xb6\x2f\x3b\xfb\x44\x75\x56\x5b\xd7\x9f\x31\x50\xe7\x34\x31\x6b\x18\xd2\x7e\xf6\x1c\xc9\x7f\xe9\x69\xcb\x77\x3d\x81\x6b\xd6\xae\x85\xfb\x19\x0f\xe5\xb4\xd9\x5d\x8d\xb3\xf7\xe5\xd7\xa2\x2f\xd5\x5d\x35\xac\xa1\x8f\xd6\xfd\xeb\xc7\xb9\xe3\xaa\xc7\x7f\x5d\x73\x7c\x8b\xba\xbf\x3c\xbe\x7e\x4f\x7f\x4d\x43\x90\xc5\xca\x1f\xba\xe7\x44\xb5\x1f\x3d\xbe\x9a\x54\xea\x84\xed\x31\x86\x1b\xd9\x5e\x5c\x87\x5d\x38\xf6\xd6\x0b\x06\x1b\xc7\xaf\xfb\x51\x02\x23\xba\x45\x46\x34\xb8\xc4\x68\xa6\x12\x47\x0c\xd6\xdb\x02\x9c\x54\x01\x92\xb0\x15\x1b\xd4\xb9\xa9\x64\x80\x72\x0b\x2c\x30\x2c\x2e\xf2\xf2\x7b\x7d\xf1\xb8\xcf\x2b\x0f\xcb\x5e\xcd\xd8\xe3\x85\x90\x57\x26\x87\x55\x07\x91\xe0\x38\x87\x62\x6e\x6c\xbf\x20\xd6\xc7\x75\xde\x38\x67\xea\xe6\xa8\x57\x8e\x95\x78\x96\xd5\x75\x87\x5d\x5e\xb3\x99\xb1\xfa\x05\xde\x9b\xe8\xa9\x09\x3b\xcc\xc0\xf3\x2e\x82\x35\x91\xe0\x9e\xb6\xd6\xd8\xb5\xf1\xc5\xe3\xd8\x77\xc4\x81\x43\x96\xbd\xb3\xdb\xaa\x42\x7d\x2d\xf5\x2d\x0d\xf1\xd5\x13\xfa\x70\xd0\xe7\xad\x04\x88\x7b\xf1\xb6\x92\x38\xc6\x6b\xdb\xe7\x84\x5d\xcd\xf1\x0a\xa5\xaa\x59\xe0\xdd\xc1\x64\x59\x73\xc0\x23\xf7\x55\x45\x68\x8f\xc0\xae\x45\x47\x78\xd3\xdb\x0d\x1f\x33\x5f\x11\x87\xf1\xc8\xcb\x3b\x5e\x83\x8f\x8b\x6e\x43\x1b\xc6\x52\x00\xbb\x05\x03\xce\x38\x81\x15\x83\xbc\xdf\x00\xd1\x34\x9a\x44\x6f\x8f\x26\x42\x94\x44\xc6\xf8\x63\x84\xaf\x6a\x88\xe5\x2a\xac\x99\xa6\xfd\x93\x34\xb1\x84\xcb\x25\x80\xd9\x11\xae\xe9\x49\x78\x79\xc1\x6f\x65\xcc\x66\xaf\x2b\xdc\x5d\xb7\xcc\x53\x12\x93\xbd\xd1\xcd\x53\xe7\xdc\xd8\xc9\xf5\xc5\x2e\x68\x6f\x34\x2b\x0e\x8e\x4b\x10\xc4\x58\x4b\xe4\xdf\x2e\xb4\x81\xd1\x1e\x3f\x6e\x99\x3b\x6d\x2d\x2b\x78\xe8\x78\xd9\x54\xd9\x13\x68\x2e\x4b\x06\xdd\xbc\xd0\x5c\xa5\x54\xc4\x9b\x5d\xe1\x39\xed\x6b\x31\x8e\x97\xe0\x6d\xde\x38\x40\xa5\xd7\x17\xc4\x7d\x13\x56\xc7\x1b\x5a\xea\x5b\xfa\x42\x08\xd9\x8e\xac\x65\x98\x8d\x7d\xa4\x4a\xd4\x82\x16\xa2\x53\xd1\x79\xe8\x07\xe8\x66\xf4\x00\x7a\xca\xe0\x35\x89\x46\x18\xb7\x98\x4a\xaa\xa9\x4c\x3a\xe2\x8e\xbb\xa3\x5c\x94\x8b\x66\x28\x2e\x9a\x29\x6e\xe2\xa5\x8a\xcb\xf7\x1c\x55\xb4\x11\x72\x47\x39\x5d\x7c\x4c\x4a\xa2\xe4\x16\xc6\x58\x62\x5a\x20\x6d\x18\xc1\x96\x42\xd4\x2d\xa4\x92\x6a\x3a\x9b\xce\x80\x5b\x88\xb4\x40\x3a\x09\x69\x83\x96\x2e\x1c\x32\xd0\x49\x8b\xe0\x97\x21\xa3\x9f\x01\x1f\x65\x94\xa8\x01\x86\xe9\x4e\xc5\x33\xe9\x02\x8d\x4f\x29\x14\x17\xee\xa4\x14\x17\xe5\x8a\xe5\x88\x16\xcb\xf1\xa5\x05\xbc\x6b\x4a\x39\xa7\x93\x2b\x7d\xb4\xb3\x33\xff\x4c\x7f\xef\x34\xf8\x49\x97\x12\x0f\x9b\xe9\x4e\x00\x56\x10\xa1\x8d\xb1\x95\x47\xc3\x5d\x5d\xa1\x58\xb9\x8d\x39\x84\x09\x9b\x2f\x93\x2e\x75\x0b\xa5\x4b\x7c\xee\x0b\x22\x1e\x1a\xb4\x6d\xed\xed\xd8\xcd\x5b\x3a\x2b\x2f\xd4\xde\xd7\x3e\xb8\xb0\xaa\xc3\x22\x08\x96\x8e\xca\x8b\xb0\x7c\x51\x65\x87\x45\xc8\xdb\xe7\x4f\x49\x65\xa6\x31\x21\x53\xd4\xda\x0b\x61\x77\x69\x5d\xca\xe7\x76\xfb\x52\x75\xa5\xee\x87\xba\xba\x0c\x38\xeb\x2e\xda\x1a\x8a\x95\xc3\x67\xe3\x17\x78\xde\xbd\x29\xe9\xdc\xef\xbc\x37\x92\x4a\xfd\x63\xa2\x36\x0f\xee\x9a\xb8\x55\xbb\xbc\xac\xda\xcf\xc5\x21\xa2\x7d\xea\xc1\x8e\x20\x78\x56\xed\x4a\xbb\x2b\xca\x63\xf0\xc1\xad\x65\x15\xee\x87\xcd\xa5\xac\xe8\x2a\x93\x7d\x4d\xdb\x9a\x7c\xb2\x5c\xda\xd0\xd7\x91\xf2\x82\xcd\x6d\x25\xea\x6f\x4c\xa5\x6e\x4c\xe7\x89\x9f\x9c\x54\xd5\x44\x39\x1c\x54\x53\xd5\x9c\x3d\xf7\xcf\xac\x6c\xd6\xc3\xcd\x95\x33\x89\x26\x28\x7b\xfa\x69\x69\xa1\xb4\x54\xfd\xd5\x86\xed\x8d\xa5\xb2\x5c\xda\x68\x9c\x7c\xcd\xb0\x56\x7b\x3b\xe8\xc4\x1e\x70\x6a\x7f\x8a\xbb\x7c\xd5\x60\x3a\x76\x0d\xd7\x8a\x7c\x87\x11\xf5\xb6\xe1\x2f\x3b\xd6\x3f\x16\xa0\x53\xd0\xb9\xe8\x22\x74\x03\xfa\xb1\xa1\xa7\x47\x23\x0a\x97\x4d\x25\x29\x77\x34\x93\x4e\xc6\x53\x99\xb0\x3b\xc5\xa5\xc2\x27\x78\x2d\x63\x2f\x2f\x13\xe5\x52\x19\xe3\xe5\xc5\x33\x51\xa3\xc3\xb4\x40\xea\x4b\x2f\x56\xcd\x42\x26\x1d\x29\x05\x21\x69\x30\xe0\x32\x74\xc8\xe8\x22\x99\xb4\xd1\x2b\x42\x46\x0f\x81\x14\xc1\x45\x39\x59\x91\x95\x14\x3f\xd6\xf7\x0a\xfd\x4c\xef\x7b\xf1\x13\xf4\x50\xe2\xff\x14\x49\x14\x25\x05\x06\xe6\xcf\x1f\x6d\x5c\xa9\x3d\xb7\xfc\x54\x08\xcd\x9b\x17\xf0\xb9\x08\x98\x67\xb2\x25\x6a\xb3\xb0\xc7\xcc\x65\x93\x95\xf3\xe6\x55\xd7\x66\x39\x33\x0c\x2c\xc0\x4c\x38\xf1\xa0\x4f\xe9\xea\x56\xfc\xa5\xca\x84\xc9\x31\x17\x81\xf3\xc3\xb3\x67\xe3\x97\xbc\xec\xdc\xc6\x47\xf3\xde\x47\x1b\xe7\xd9\xbd\x5e\x76\x6e\xd3\x23\xf8\x1d\x23\x3c\xea\x5d\xb2\xf1\x54\xb6\x26\xee\x5f\x31\x09\x1e\xf6\xcb\xdd\x5d\xb2\xdf\x2f\x77\x75\xcb\x7e\x98\xbe\x20\x93\x4c\xd8\x4d\x0b\x80\x70\xf9\x02\x10\x7b\xa5\x4b\x84\x6a\xb1\x3b\x91\xe8\xbe\x7a\x70\x30\xff\x4b\xf8\x50\xfb\x6e\x85\x9b\x08\xc1\xe9\xda\xc6\x3a\x4f\xbc\x65\xf0\x99\x1e\x6f\x7d\xf6\xf5\xfc\xf2\x5a\x55\xf5\x9d\x64\x4f\x59\x62\x13\xe6\x2c\x9d\x1e\x4f\xa5\xe2\xd3\xf7\x4c\x8f\xa7\x32\x3e\x9f\x99\x78\xea\xb7\x13\x26\xfc\x76\x62\x7e\xce\x7b\x67\x35\xf5\xd3\x6e\x37\xdd\xdf\xb4\xfa\x43\x3d\xcc\x08\x02\xd3\xdf\xb4\x9a\x64\xb5\x35\xda\x27\xe0\xe8\xbd\x78\xe9\x4c\xed\x8b\x89\x3f\x9e\x11\x4f\xa5\xe4\xfe\x1f\xf7\xeb\x0f\x19\xd0\xec\x6a\x6b\xdc\x93\x82\x8b\xb5\xcb\xc3\x58\xac\x84\x73\x0b\xb6\x94\x39\x6a\x33\xf5\x5f\xc4\x23\x05\x21\xa0\x0b\x1a\xb4\xca\x27\x95\x31\x85\x19\x44\x06\xdc\x63\x8b\x32\x90\x05\x3d\x11\xcf\xb2\x7c\xe6\x93\x3f\x72\x0b\x96\x3c\xc0\xad\x36\xab\x59\xfa\xa8\xcc\x4b\x3c\x6f\xb5\xe6\x3f\x86\x7e\xab\xc5\x22\x7e\x54\xe1\xd1\xf6\xb8\x30\x94\x28\x9f\x88\xc4\x69\x2e\xad\x37\x11\xe1\x61\x04\x40\x12\x1d\x8e\x6a\x38\xd5\xe9\x1e\x9d\x0f\xf9\xeb\x04\xce\x51\x8d\xcf\x0c\x11\x3b\xab\x8f\xe5\xce\xe7\x8f\xf0\x8b\xc8\x95\x60\xec\x20\xb8\x09\x5a\x12\x9b\x20\xa9\x82\x91\x02\x22\x18\xb1\xac\x02\x19\xc8\x4a\x5f\xda\x7c\xd9\xea\x0e\x3e\xea\x32\x31\xa6\x73\x7f\x61\x36\x9b\x9c\xfb\x82\x3c\xa1\x32\xdc\x63\x01\x5e\x3b\x0d\x80\x12\x42\x8f\xba\x18\x93\x59\x1b\x85\xeb\x4c\x7f\x3a\x66\x91\x9a\x80\x37\x23\x56\x1b\xf7\x07\xd0\xee\x64\x59\x7b\x8c\x98\x61\x8b\xe6\x15\xac\x85\xa3\x36\xbb\x03\xde\x00\xfc\x8a\xf3\xc2\x2f\x63\xd6\x20\x0b\x83\xc8\xff\x22\x6c\x20\x22\x55\x03\x9f\x24\x83\x90\x0c\x50\x45\x1e\xfc\x52\x10\x19\x16\x1c\xc0\xd2\x51\x3a\x2c\xc7\x6a\x70\x61\x26\x49\x80\xd2\x02\xb2\xc1\x37\xdf\x4a\xa7\xb2\xf8\x97\x70\x40\xf3\xef\xfb\x21\x34\xf4\xf4\x40\x88\x0d\x7b\x42\x01\x96\xe6\x15\xc6\x64\x06\xe0\x99\x18\xcb\xb2\x81\x90\x27\xec\x08\xc2\x21\xed\xc2\x97\xb4\x97\x6a\xeb\x62\xb1\x78\x87\xe7\xcb\x57\xb0\x21\x38\x04\xd7\x1e\xcc\xc3\x52\x33\x45\x12\x04\x6d\x71\x4a\x0e\xba\x64\xa1\xda\x7e\x79\x79\xd9\x85\x97\x5f\xae\xce\xe3\x38\x87\xe4\xb0\xd0\x04\xc1\x63\x33\x41\x92\x94\x25\x54\xf2\xa5\x7c\xa7\x9e\xef\x42\x05\x1c\x2c\x7a\x84\xba\xd8\xd8\x5b\x95\x90\x0f\x05\x11\x32\x93\x6e\x70\x2b\x4c\x06\x32\x12\x64\x24\xd5\x6d\xb6\xc1\x2e\xf8\x50\xbb\x47\x13\xa9\x2a\x4d\x04\xd0\xa4\x2b\x60\x36\x00\xcc\xc9\xcf\x80\xd9\x9a\x4b\xfb\x11\x95\x80\x01\x4d\xd2\xee\x86\x39\xf0\xae\xf6\x23\xcd\x45\xb4\x68\x2f\x69\x7f\x83\x36\xed\xc0\xe9\xda\x9f\x0c\x3e\xf6\xf8\xe9\x43\xe0\xc7\x00\x58\x3b\x40\xfe\x41\xfb\x9b\xf6\x32\xb0\xda\xa7\xda\x27\xda\xcf\xa1\x94\xd8\xaa\xfd\x5c\xfb\x14\x6a\x11\x8d\xac\x87\x11\xf5\x1f\xc3\xc6\xc4\x8a\x1c\xc5\xf2\x20\x2a\xcc\x45\xb9\x30\x17\x8d\xab\x14\x03\x2a\x18\x7f\x04\x30\x66\xc8\x84\xdd\x94\xf9\xd0\x6d\xc3\xd4\xcd\xc3\xa3\x03\x61\xc2\x11\xce\xcf\xed\xc2\xaf\x76\xe5\xff\xbd\x04\x2f\x59\xf2\x3a\xbc\x99\xd3\xa2\xf9\x07\x88\xd0\x10\xec\xcf\xe7\x70\xae\xea\xa6\x3b\x6e\xc4\xde\x5d\xda\x9e\xcb\xf1\xc3\x9b\xf3\x87\x37\x13\x9b\xf3\xe7\x0d\xe1\x6d\x07\x6f\xbd\xe5\x96\x13\xd8\x5e\x4c\x47\x4b\xc7\xe1\xf6\x17\xc1\x68\xc7\x70\x6e\x63\x11\x99\xc5\x06\x65\x2a\x21\x0a\x74\xa1\x0f\x04\x88\x6c\x52\xd4\xa5\x27\x50\x5b\x09\xd9\x40\xb1\xd5\xe5\x08\x02\x39\xc7\x8d\x73\xce\xa3\xc3\xdc\x98\x99\x46\xe8\x1d\xed\xd1\x77\xde\x81\xc9\x30\x90\xed\xcb\x66\xfb\xb4\x49\xec\xf7\x27\x6f\x9c\x55\x9a\xec\x13\xac\x0e\x4a\x6f\x39\xca\x61\x15\xfa\x92\xa5\xb3\x36\x4e\xfe\xfe\x57\x67\xe1\x33\x29\xcb\x81\x97\xe7\x6a\xd9\xb9\x2f\x1f\xb0\x50\x46\x18\x9e\xd7\xc3\x58\x34\x0c\x3a\x60\x77\xe1\x57\xde\x31\x7e\x24\x9b\xfb\x96\x8f\x3d\x36\x4b\x3b\xf3\xcb\xcf\x37\xc2\xc7\x7c\xd7\x0e\x03\xe7\xe3\x78\x7b\x99\xd4\x11\xcf\xd7\x31\x6f\x15\x83\xea\xa8\xf0\xa5\xc1\xf5\x5b\xee\xdf\xb2\xe5\x7e\x7c\xbf\x71\x1a\xe3\x31\x2a\x7c\x81\xa3\x3f\xd4\xd3\x8a\xff\xc6\xff\x0e\x46\x66\x83\x07\x9c\x0f\x53\x29\x33\xa4\xd4\xf0\x31\xa6\x5a\xe8\x57\xda\x99\x38\x3b\xa8\x65\xb4\xcc\xe0\x32\x6c\x81\x43\xc7\x23\x25\xec\xd2\x5e\xdc\x8f\x1f\xcc\x4f\x1d\x86\xba\x13\xf9\x27\xf7\x53\xdb\xa8\xdb\x91\xc5\xf0\xae\xec\xd2\xfb\x02\x88\xb4\x92\x80\xac\x9a\x0d\x80\x94\x00\x86\x05\x29\x00\x6a\x2b\xf0\x09\xac\xc4\x28\x16\x33\x01\x2c\x89\x6a\x2b\xe6\x0d\x7f\x08\x59\x49\x10\x8a\xac\xb4\x81\x18\x52\x03\x40\xf3\xb4\x81\xbb\x10\x97\x95\x04\xa9\xe7\xb4\x92\x6a\x56\x8d\x51\xa2\x14\x00\xa2\xc6\x74\x76\x46\x29\xf5\xcb\xb1\x1e\x75\x15\xfb\xec\xc9\x6d\x53\x08\xf2\x8a\x85\x0b\x36\x1d\x10\x26\x57\xd5\x69\x6f\x6a\x1f\x54\x26\xda\x5d\x81\x85\x6a\xf3\x81\x37\xda\x32\x0b\x67\x9b\x1c\xf6\xaa\xd8\xec\x97\x9e\x59\x9a\x98\x34\xd0\x2e\x94\x84\x68\xd7\x5b\x58\xdd\xef\xa6\x9d\x0f\x79\x67\x51\x55\x95\xe1\x51\xed\xfa\xcf\x77\x39\xdc\x76\x8a\xc1\xe6\xa8\xdb\x6b\x26\x4a\x23\xf5\xb1\xc0\xb9\x8f\xc3\x66\x28\xbf\xa1\xd9\x09\xf8\x8e\xb6\xbe\x10\x37\x30\xc0\xb9\x6c\x4d\xdc\xca\xb5\x55\xfe\x8d\x13\x16\xe4\x4c\xa6\x6b\xf1\x26\x5f\xd4\x6c\xaa\xa9\x63\x2c\x11\xaf\x3f\x6a\x66\x4a\xfd\x26\x53\x74\xd4\xe5\x3d\xad\xab\x47\xa8\xad\x21\x38\x93\x10\xc9\x44\x87\x7e\xe1\x34\x5f\x79\x25\x1d\xa9\x27\x1e\xbd\x4b\xf3\x04\xd2\x7e\x6e\xab\xec\x5b\x6d\x2b\x2d\xf7\xa5\xcd\xc9\xe7\x36\xdf\x37\xd9\x5b\x1d\x08\x38\xac\x09\x57\x7c\x4e\xa2\x4f\x68\x35\x70\x60\x0b\xef\xca\x64\x8c\xf6\x8d\x68\x5e\x81\xdd\x5a\x36\xa8\x88\xb3\xaa\xe1\xce\x6e\xb8\xea\xf3\x7a\xfb\xe8\x63\xa6\xae\x7c\x48\x01\xcc\xa7\xb3\xb2\x42\x87\x14\x07\x18\x1c\x86\x7a\xc3\x66\x15\x59\x91\x29\x9a\x29\xb4\x75\x80\x90\x44\x89\xd4\x75\x15\xd7\x97\x04\xc3\xfe\x81\x58\x25\x54\x2a\x33\x7b\x4d\x73\xcf\x5f\x41\x60\xb5\x7a\xe2\xa5\x0f\x0b\x5d\x4a\xd5\x0d\x77\x57\xc9\x5d\x6e\x7b\x22\x12\x78\xf6\xb7\xe1\x58\xb2\xde\x4a\x39\x6e\xd5\x96\xdd\x66\xa3\xbc\x8e\x9a\x9b\xbe\x78\x30\x12\x70\x7c\xcf\xcc\x55\xae\xfe\x83\xf6\xc9\xf9\x83\x72\x65\x8a\x34\x89\x31\x1a\x4c\xb4\xcb\xbe\xfc\x41\x20\x1e\xf2\x04\x83\x64\x2d\x94\x1d\xb3\x9b\x77\x7d\x65\x42\x14\x96\xbb\xa4\x6c\x4b\xe7\x99\xb6\x85\x5d\x75\x73\x85\xe0\x00\x34\xba\xbd\x34\x25\x08\x34\x53\x22\xf0\x1e\x86\x8a\x46\x28\xa6\x24\x4f\x30\x4a\x09\xb9\x62\x05\x6d\xbb\xbe\x7e\x86\x2f\x71\x0a\xdf\xb1\x02\xff\x32\x23\xaa\xe1\x36\x9f\x2d\xe2\x10\x6a\x03\xdd\x3f\x78\x3e\x46\xa5\x85\x88\xb5\x5f\xf0\x2f\xb0\x0b\xb2\x1b\xac\x90\x3c\x6e\x1e\x02\xd4\x7d\x38\x47\xea\xcd\x1a\x41\x28\x2e\xe9\xc3\x4a\x82\xc8\x70\xd1\x4c\x2b\xa9\x1a\x08\x83\x61\x77\x98\x13\x02\x58\xcd\x12\xf7\xf7\x4b\xf7\xcf\x5b\xb6\x67\xf5\xb4\xf0\x0f\x27\xaf\xed\xae\x15\x28\x60\xc8\x7f\xc3\x54\xed\x01\x7b\xa8\xab\x76\xda\x4b\x1f\x44\x5b\x01\xd7\x2f\xdc\xb0\xa1\x11\x87\x5e\xf3\xce\x59\xb4\x6a\x4e\x35\xc5\x68\x73\x47\xf3\x07\x03\xe9\x4c\x00\xf0\xf8\x7d\xfe\x02\x83\xac\x42\x47\xe9\x04\xce\x70\xe1\x4c\x98\x8b\x46\x18\x96\x60\xdc\x29\xe3\xb7\x5a\xe1\x4b\x7b\xa1\xab\x5b\xab\x9a\x62\xe9\x12\x0b\xc0\x61\xf4\xb8\x09\xa8\x92\xcc\x69\xdd\xdb\x2b\xe7\xdc\x70\xca\x84\xef\xc1\x6d\xe3\xdb\x6f\xca\x23\x22\x48\x65\xe5\x12\xec\x7c\x0a\x26\x5a\xaa\x66\x2f\x9b\x5d\x72\x87\x36\xd8\x70\xd6\x8a\x0e\x0c\xb5\x64\xcd\xb1\x7b\xa1\xc4\xe1\x76\x9c\xa7\x91\x81\xda\x23\x9e\x58\xa5\xc7\xff\x71\xda\xb5\xdb\x2c\x76\xd6\xa2\xdd\x64\x37\x99\x85\x22\x5e\x20\x20\xd9\xa9\xe5\x2c\x16\xc8\x39\x79\x9e\x34\xf6\x2c\x0e\x8d\xd9\x94\x20\x9c\xa7\x46\xf4\x67\x16\xed\x56\x8e\xc0\x26\xab\x45\x27\x31\x9c\x3f\xf2\x1c\xb7\xd3\x0e\x83\xfa\xd3\xe1\x14\x3b\xc9\xf3\x87\x0c\x03\x6e\x72\xbf\xec\x84\x9c\xc5\xa2\xe5\x9c\x45\x6e\x2b\x20\x18\x44\xe4\x8d\x67\x8e\xa1\xe0\x8f\x61\xe0\x4b\x05\xf0\x0c\x06\xe9\x25\x38\xae\x50\x78\xff\xb1\xbf\x71\x32\x6b\xd4\xa0\xc8\xb5\x45\xd0\x23\xc5\x67\x16\xf6\xa5\x8f\x45\xcf\x97\x40\xa4\x47\xf4\x22\x1c\x57\x2a\xbc\x83\xb5\x68\x37\xb3\xa6\xf1\x55\xd0\x6e\xb3\x1c\xb1\xc7\x5f\x43\x23\x24\x1b\x5e\x8f\x45\x75\x4e\x17\xd6\xa3\x11\x02\x67\x8a\xd2\xb6\x2e\xb3\x1b\x1a\x5f\x81\x23\x14\xc6\xb8\x55\x0b\x44\x77\x92\x20\x52\x6b\x94\x99\xdb\x72\x75\x0b\x66\x77\xb4\xcc\x98\x91\xba\xf6\xaa\x2b\xd6\xac\xb9\x77\xf2\xf2\x65\x91\xea\x93\x97\x4c\x5a\x3f\x98\x4e\x4f\x8f\x76\x5c\xac\xfd\xa5\x34\xd0\x96\xcd\xc6\xbb\x88\x29\xbd\xf7\x03\x01\x00\x1d\xe7\x9e\xfb\x8b\x50\x28\x1c\x01\x02\xa8\x4f\x0f\xec\xba\x2c\x10\x88\x44\x3a\x62\xed\x5d\xa9\xc1\x35\x5b\x9e\x25\x37\xb5\x4c\x99\xd2\x96\x75\x59\xe9\xab\x4e\x5f\x59\x4e\x38\x09\xd2\x76\xc4\x9e\xdf\xc0\x22\x2f\x48\x07\x08\xb8\x38\x67\xb0\x39\x15\xcf\xf8\x9e\xfc\x6c\xfd\x8f\xce\x8d\x9e\x4d\x7c\x7f\xf4\x6c\xec\xca\x9f\x3d\x88\xab\xf1\xdf\xf3\x67\xe0\x4c\x7e\xfd\xe8\x87\xe7\xe2\xab\x88\x33\x47\xdf\xc1\x37\x19\xfc\x91\x06\xee\x2c\xb5\xd5\x98\xef\xfd\x48\x45\x53\xd1\x02\x84\x50\x32\x6b\xcc\x4f\x64\xf1\x4c\x15\x66\xb1\x42\xe7\x2e\x40\x59\x1a\x0e\x95\x2d\xba\xba\x6b\x2c\x2e\x28\xc6\x1e\x21\x04\xc0\x1d\x4e\x67\x0d\x4b\xd6\x20\x64\x93\x92\x9a\x95\x44\xc6\xf8\x32\x8a\x1f\x46\x52\x84\x37\x43\x92\x14\x12\xe1\xf1\x90\x28\x86\xa4\xd1\x43\x15\xcd\x4d\xb3\x9b\x9b\xc9\xe9\xed\xd5\x53\x9a\x67\x37\x5f\xdc\x5c\x59\xd1\x0c\xbd\x89\x76\xfc\xa3\x95\xb9\xd1\x53\x72\xa7\x4f\x62\x6c\x76\x66\xf2\xe2\xdf\x2d\x9e\xcc\xd8\x6d\x0c\x5c\xad\xe7\x37\x57\x54\x36\x93\xa5\x92\xfe\x9c\xc2\xbf\x97\x9a\x2b\xb4\x81\xca\xe6\xe6\x4a\xf8\x51\x45\x33\x9f\x5f\x92\x68\xff\x9b\x1e\xfb\x5b\xe1\xd8\x9e\xc0\xd7\xc3\x55\xea\x33\x67\x9f\xfd\x8c\xba\xc3\xce\xd0\xb6\xf3\x2b\x2a\xce\xb7\xd1\x8c\x3d\x7f\xd5\xd8\x5d\x95\x4d\x4d\xc8\x6c\xc8\x5d\x5f\x18\x9c\x1b\x0e\x14\x01\x13\xb8\x21\x0e\x29\xe8\x81\x4f\x0c\x3c\x95\x28\x9d\x49\xab\x49\x89\x96\x99\xac\x24\x82\xac\x8f\x3b\x0c\xad\x8f\xdf\xad\x44\x33\xc8\x90\x56\x74\x81\xa7\x20\xef\x88\x92\xc1\x21\xab\x4b\x3e\xc6\x4c\x27\x67\x8b\xcb\x29\xfa\x20\xcf\xd0\xa2\x9a\x4d\x67\x12\x84\x42\x4b\x42\x34\x01\xb4\x92\x95\x15\x99\x66\xe8\x00\xe8\x9a\x21\x63\x38\x40\x49\x49\x91\x36\x9c\x57\x8d\x29\x96\xd0\xc7\x7e\x42\x9f\x12\xa0\xc0\x71\xc2\xd0\x8a\x5c\x98\x11\x28\x51\x12\x58\x8a\x61\xb1\x3e\x2f\xe8\xbd\x93\xc5\xc6\x90\x28\xea\x97\xe8\xef\xc1\x28\xa5\x61\x5d\x69\xdc\x1d\xc0\xee\xac\x92\xd0\x07\x2c\x49\x2c\x38\xf2\xeb\x17\x18\x1b\xb8\x59\x83\x3a\xbf\x15\x44\xd0\x0b\xe4\x16\xa5\x24\x43\xa7\x92\x94\x5e\x25\xb2\x30\x55\x29\xe9\x04\x30\x11\x3d\x28\x09\x6a\x56\x4d\xeb\xc2\x5c\x94\xd5\xc5\x7e\x2c\x89\xfa\x13\x92\x59\x08\x60\xbd\x38\x60\x40\xb3\x10\x06\x78\x11\xc3\x12\x4a\xa1\x29\xf4\x1f\xd0\x1b\x41\x97\x0e\x21\x63\x14\x51\x2f\x1c\xc1\x08\xb4\x54\x30\x01\xc5\x6a\x2b\x36\x56\xe3\x64\x3d\xd3\x58\x87\x23\xd4\xac\x5a\x98\x1f\x53\x06\x98\x0d\x53\xbc\x56\x34\x24\x4f\xe3\xb1\x2c\xe8\xd5\x10\x8b\x0f\x2e\xb6\x74\x80\xc2\xd7\x58\xcd\x24\xc5\x53\x0b\x49\x87\xc5\x63\x22\xb4\x1b\x48\x92\x22\x08\xc6\x62\x26\x39\x12\x30\x06\x4c\xcc\x52\x49\x86\x20\x30\x03\x66\xb0\xf4\x46\x3d\xe1\x39\x61\xab\x12\x74\x80\xd5\xec\x76\xd9\xed\xc0\x46\x4a\x44\x92\x14\xac\x8a\xa3\x89\x36\xd1\x62\x49\xdc\x6f\xb1\xba\xdc\x76\x8a\x2b\x11\x9d\x2b\x5d\x60\x2e\x2f\x21\x20\xe2\xf7\x95\x62\x30\x73\x8c\x85\x26\xad\x0c\x07\x20\x78\x38\x01\x40\x34\x9b\x14\xb0\x53\x16\x56\xb4\xf8\xc4\x1a\x15\x57\xf8\x42\x94\xd9\x4a\x11\x66\x9b\xd0\x63\xae\xf2\x96\x64\x2d\x00\xce\x92\x0a\x4e\x8e\x84\x7d\xa2\x1d\x63\x9a\xb6\x32\x76\xc2\x3f\x3d\x2b\xba\x2b\x44\x02\x02\xa5\x76\x97\x34\xdd\x84\x81\x36\xb9\x43\x24\xa6\x49\x0a\xe3\x58\x82\x2a\x23\x85\x1f\x9a\x9d\x44\x30\x60\xaa\x60\x13\x0a\x69\xa7\x81\x10\x2c\x89\x0d\x17\x54\x49\x56\x1b\x06\xd1\x4c\xbb\x09\x09\x63\x0e\x8b\x8e\x18\x74\x4d\xcb\xdf\x4a\x58\x69\x33\x26\x2c\x04\x61\x25\xe0\x76\x6c\xe6\x68\xca\x4c\xd1\x98\x60\x2b\x5c\x66\xeb\x5e\x8b\x8d\xa0\x49\x92\x60\x49\x13\xce\x52\x76\xc2\x61\x36\x53\x04\x06\x0b\x26\x49\x13\x6b\x02\x27\x8b\x55\x41\xc4\x8c\x47\x8a\x7b\x65\x93\xbc\xd8\xcf\x2d\x91\x5d\x92\x25\x12\xa8\x9a\xcd\xf7\x09\x55\x93\x62\x29\x7f\xe9\xee\x76\xbe\x3d\x56\xe9\xa1\x2c\x11\x00\x8b\x05\x2c\xec\x6c\x2e\xe0\x71\x67\x42\xa9\x88\xd9\xee\xc2\x36\x8a\x84\x08\x41\x44\x84\x6d\x51\xcf\xa9\x1d\x52\x65\x25\xe1\x12\x2c\x1b\x6b\xbb\xab\xad\x24\x01\xe0\x0a\x30\xa6\xb8\x28\x0b\x67\xb2\x36\x12\xa7\xfb\x95\x8e\xcc\x8a\x58\xc3\x04\x8a\x8a\x46\x4e\x51\xe7\x39\x4c\xb4\xcb\x6a\xf1\xf9\xb2\x11\x97\xcf\x65\x66\xb1\x28\xbb\x9c\x02\x6f\xa9\x9f\x5f\xd6\xd4\xd2\x93\xa9\xb5\x2a\xa1\x70\x98\x60\x81\x75\x78\x9d\x3e\xf2\x34\xe0\x81\xb6\x11\x2c\x38\x08\xab\x9d\xd6\x06\xc0\xc4\x51\x94\xc9\x0a\xe0\xb4\x10\x26\xfd\x85\x63\xed\x7a\x97\xc7\x51\xe2\x73\x96\x5a\x22\x4c\x25\x55\x7b\xa6\x20\xb4\xdd\x76\x56\x19\x26\xab\x37\x25\x94\xe6\xa0\xcb\x06\xad\x03\x81\x98\xe8\xee\x88\x98\x88\x00\x40\x32\x0d\x44\x67\x09\xef\x60\xc8\x76\x2a\x50\xe6\x36\x13\xa6\xad\x0e\x33\x41\x32\x0d\x9d\x00\x0d\x41\x47\x55\x10\x13\x56\x33\x94\xf2\x62\x00\x2a\x62\xa4\x83\xb5\x49\xc0\x7a\x29\x93\xe4\xb0\x02\xe6\xc0\x66\xe6\xcc\x2c\x4d\x58\xed\x04\x1d\x24\x79\x92\x62\x30\x49\x3a\x24\x00\x9b\x93\x77\x98\x49\x33\xa6\x28\x92\x26\x18\x60\x9b\xbd\x36\x6b\x6b\xd0\x4c\x30\x25\x6d\xb5\xdd\xa5\xf4\x0f\x1b\x5c\x4b\x4c\x1e\x77\xb0\xcd\xef\xe7\x01\xc8\x8e\xd3\x6c\x21\x52\xfa\x9e\xd9\x91\x28\x23\x1c\x4d\x75\x09\x4f\xb7\xc9\x69\xc2\x94\x99\x49\x3b\x1d\x93\x65\x13\x9d\x28\xe9\x92\x4a\x81\x3f\x2b\xe4\x5e\x3e\xcf\xeb\x8a\x87\xac\x44\x05\xe7\xc5\xd8\x4c\x81\x43\x78\xca\xc4\x10\x24\x61\xa1\x19\xc0\x4e\x95\x04\xd7\x7e\x2b\x67\x02\x92\x04\xd2\x47\x50\xf8\x3d\x4c\x9b\xb0\x03\xec\x76\x9a\xb4\x53\x34\x41\xdb\x08\x20\x0f\x3e\x67\x2b\x91\x44\x91\x13\xec\x2e\x92\xef\xf5\x39\x19\x97\xb9\x54\xe4\x40\x9f\xa2\xfc\xa1\x12\x80\x66\x3b\x69\x65\x6c\x9c\x55\x9a\x63\x75\xd6\xc6\x63\x66\x1b\x69\x71\x45\x22\x3d\x61\x81\x22\xec\x8e\x0a\xda\x63\x13\xad\x8e\x6e\x96\x33\xd3\x25\x26\x3a\xc4\x12\x74\x55\xba\x43\xe1\x9e\x4c\xf7\x46\xcc\x1e\xa7\x58\x9a\xa8\x75\xb9\x97\x64\xbb\x85\x4b\xd3\xab\x9f\x9d\xbf\xb9\xd2\x0d\xa5\xbe\x8a\x5b\xba\x17\xaf\x5f\xb3\xbc\xe9\xe5\x39\x75\x93\xca\x30\x8e\xc4\x03\x00\x26\xde\x56\x4a\xc5\xd9\x99\xea\xc4\x73\x3b\x26\x51\xe1\xba\x68\x89\x2b\x1e\x2a\xb1\x5a\x7b\x27\xd9\x82\xa9\x80\xcf\xea\x28\xfa\xc7\xeb\xb2\x18\x8b\x42\x48\x41\x09\x94\x44\xad\x68\x36\x3a\x19\xa1\xb8\x4c\x44\x19\x96\x64\x14\x31\x95\x24\x64\x85\x0c\xeb\xb3\xb4\x54\xa0\x03\x56\x64\x85\x05\x26\x44\xc9\x8c\x3e\xc8\x41\x84\xc9\x52\xfa\xfc\x2e\x4a\xad\x24\x2f\x2b\xfa\x5d\xc6\x68\xd2\x0a\xc9\x00\x29\x65\x8f\xf1\x20\xa8\x38\x19\x63\x67\xf6\xca\xad\x17\x46\x1d\x8f\xbe\x77\x7e\x8b\x3b\xa4\xfd\x4a\xbb\x1a\xe6\xf6\x27\xaf\xb8\x78\xb3\x1c\x27\x5d\x4b\x37\x6c\xb9\x78\x24\x04\x09\xe2\x8d\xdf\xfe\x72\x4e\xf9\xaa\x2b\x47\x3f\x01\x00\x3c\x7d\xdf\xe7\x7d\xd3\x77\xac\x9b\xb0\x69\x52\xb3\xe3\x00\xb1\x0b\xcc\x42\xd7\x94\x73\x27\x94\xf0\xd8\x4c\xc4\xa6\x4e\xec\x6e\xce\x54\x06\x2c\x9b\x8e\xd3\xc3\x62\xfa\x9d\xb4\x7b\xea\x9c\x9d\x53\xad\x57\xe3\x2b\xea\x5a\x17\x31\xec\x96\xbf\xcc\x9b\x77\xc3\x60\x37\x6b\x07\xea\xf7\xaf\xde\xd1\xf1\xe9\x35\x1f\x35\x07\x3f\x7a\x67\xca\xdb\xc4\x19\x00\x97\xef\xe6\xef\xf9\x9d\x77\x42\xb6\xd9\xad\x45\xfe\xf1\x00\xd8\x4a\xda\x1b\x7a\xfc\x99\x0a\xca\x43\x51\x24\x41\xd1\x0c\x85\x9f\x3b\x11\x1e\x63\xb1\xfd\x5a\xd1\xa0\xae\x7f\x24\x88\x1a\x48\x90\x99\x74\x2a\x19\x20\x0a\xb6\x57\x10\x35\xe8\x99\x0c\xd4\x1c\xa9\xc0\xd1\x9b\x20\xc6\xf6\x51\x5a\x71\x81\x78\x8b\x36\x98\x66\x0b\xe8\x73\xba\x54\x94\x4d\x25\x49\xd1\xe5\x16\x18\x91\xbc\x4a\x69\x9c\x3b\xb5\x6e\x59\xc0\x5f\xe1\x72\x5c\x56\xd9\x5d\x16\xab\xf2\xd6\x34\xac\xbe\x6f\xa8\x3b\xb7\xaa\x4b\xee\x9d\xdd\xbc\x6b\xbe\x18\xea\xef\x48\xcd\xa8\xab\x48\x96\x26\x53\xff\xbe\xbb\xe7\xbb\xab\x3a\x61\xe5\x5f\x6e\xd9\xbe\x6c\x6a\xcf\xa5\xda\xa1\x27\x56\x39\xfb\x8b\x11\xa0\xf4\x08\xbc\x9e\x3c\x29\x5b\xe5\xb1\x7a\x18\xc6\xe9\xf4\x72\x53\x3d\xe1\x88\xa7\xbd\x5a\x9d\x97\x08\xb6\xad\xea\x69\x59\xd0\x1c\x67\x63\x22\x2b\x94\x29\xa9\x50\x75\x75\xa8\xb9\x7a\xe1\x8e\xf8\xc4\xb3\x2f\xbb\xe5\x2f\xfd\xce\x55\x4f\x00\x75\x69\xcf\xd4\x65\xdb\x0b\x11\xed\x90\x1e\x31\xf4\xf3\xaa\xc3\x39\xf2\xff\x0c\x5f\x96\x36\xd4\x6d\x78\x5c\x8d\xed\x87\xa8\x06\x3e\x79\xd2\xa0\x29\x96\xc7\xed\x72\x66\x55\xda\x02\x0c\x4b\x1a\x06\xbe\xc0\x82\x72\x14\x3e\x95\xc8\x7a\x81\xf8\x47\x9c\xf2\xbb\xf3\xf5\x52\x90\x86\xa8\x14\x08\x7f\x24\x06\x08\x8f\x9d\x0c\xba\xb5\x3f\x96\xca\x72\x29\xcc\x77\x45\xde\x71\x4c\x6d\x25\x69\x5a\xf4\x25\xc3\xda\x27\x76\xb3\x49\x1b\x14\x7b\x6c\x6a\xdf\x00\xb1\x61\x71\xbb\x78\x33\xd9\x3a\x95\x9c\xf6\x94\x14\x89\x08\x87\x1e\x64\x68\x18\xf2\x3a\x4a\x1d\xdb\x5b\xdc\xb2\x5c\x5a\x51\x1a\xf7\x7d\xd8\xa3\x9d\xab\xfd\x92\x13\xdd\x55\xa2\x60\x31\x6b\xbe\x12\xc6\x2c\xf6\x51\xdb\xd5\xc5\x2b\x56\x8c\xbe\xc7\x41\x03\xec\x40\xc7\xad\x3b\x14\x34\x95\x2f\x59\x6a\x7e\x03\xc6\xe9\x88\x8b\xd5\x0c\x99\x19\xf6\x17\x77\x6c\x8f\xc4\x86\x65\xef\x41\x63\x4b\x86\xca\x79\xe5\x11\xd2\xd8\xef\x1d\x45\x06\x31\x39\x36\x76\x72\x8d\xfd\x5c\x82\x3d\x7a\x91\x7c\x84\x0b\x91\x42\xd4\x7e\x83\xff\xb1\xb0\x0b\xa5\x10\x51\x37\x2f\x1a\x76\x4c\xc7\x90\xb3\xa4\x55\x3e\x13\x25\x8a\x6c\x6d\x86\xef\xb7\x04\x47\x20\xdd\x28\x54\x5f\x96\x2a\xfd\x5b\xf5\x67\x66\xd9\x3b\xd2\x99\x18\x4e\x74\x8e\x78\x65\xf3\x67\xd5\x7f\x2b\x4d\x95\xd5\x3b\x01\xf5\x2c\x85\xdc\xd2\x1e\x40\x4e\x6d\x68\xc7\x4f\x77\xec\xf8\x29\xec\x2f\xab\xaf\x84\x59\xe7\x6b\xa7\x39\x5c\x5e\x59\xfb\x38\xd1\xd9\x99\x00\xa7\xec\x75\x39\xe0\x86\xf3\xb5\x7b\x2b\xeb\xcb\x4a\x3d\x90\x5b\xb9\x52\xcb\x79\x88\x21\xfd\x86\x1d\x85\xb2\x92\x7a\x59\xe3\x86\x25\x6e\x51\xd8\x8d\x7e\xc5\xb9\xd0\x66\x47\xf0\xd9\x50\x7d\x7f\x7d\x7b\xe7\xc2\x4e\xe3\xaf\xbe\xbf\x7e\x75\x3f\xce\xf5\xaf\xd6\xf6\x1b\xa5\x21\xda\xb5\x02\x4f\xde\xd0\xe8\x6a\xa3\x24\x2f\x6b\xb5\xfa\x99\xb8\x4c\x33\x30\xfe\x60\xb8\x7f\xf5\x6a\x78\xe1\x68\x39\x0a\xef\xd1\x8d\xc2\x08\xc5\xa1\x15\x64\x45\x1e\x63\xb5\xc3\x0c\x0b\xa2\x14\x1b\xbf\xc0\x43\xc1\xa0\x93\x2b\xad\x29\x9b\xdd\xe2\x89\x35\x37\xc5\x3c\x2d\xb3\xcb\x13\xa5\x9c\x93\x9c\x7b\xdc\x00\xf3\x1e\xbc\x2e\xf6\x0e\x05\xbd\x10\xf1\x97\x95\xf9\x23\xe0\x0d\x0e\xf5\x8a\x3b\x4f\x30\x46\x54\x1d\x46\xf4\xef\xa8\xc3\xc8\x81\x7a\x10\x42\x05\xc2\x36\x21\x80\x93\xad\x10\xa7\x19\x03\x1c\x4a\x89\x1b\x3e\xd6\x94\x61\x16\x1c\x97\x15\xb9\x0d\x74\x39\x53\x8d\x1b\x36\xc2\x94\x6a\x90\xcd\x1b\x18\x3e\x94\x61\x88\x2b\x89\xd4\xc8\x82\x1b\x5e\x7d\xef\xd5\x1b\x16\x14\x4e\xb0\x8a\x74\x6a\x6f\xd8\x1d\xac\xf6\xc6\x5e\x4b\xc8\xb2\x57\x7b\x83\x75\xd8\xb5\x37\x9c\x24\x65\xde\xbb\xd7\x4c\x91\x4e\x88\xd9\x1d\x2c\xc4\xf6\x9a\x23\xe6\xbd\x10\x63\x1d\x76\x88\x15\x33\xb1\xf5\xe8\x63\x16\x2c\xb8\x21\xe3\xa0\x86\xb4\x17\x9d\x16\x0b\x3d\xf8\xb9\xdd\xfe\xf9\x20\x6d\xb1\x38\x21\x39\x44\x39\x38\xdb\xe7\x9f\xdb\x9d\x0e\x6a\x08\x92\x85\x5c\x9b\xad\x90\xab\xbd\x38\x44\x39\x9c\xf6\xcf\x3f\xb7\x15\x75\xbf\x27\xa9\xf3\x90\x0b\xd5\x21\x14\xd7\xc7\x35\x7d\x58\xa3\x8d\x11\x30\x95\x8c\xc5\x69\xb2\x38\xd4\xb9\xb2\x31\x43\x52\x66\xc1\x6d\x90\x6a\x1b\x92\x38\xf9\x61\xb6\xfe\x61\xed\xf9\xbd\xcb\x7e\x75\x78\xc9\xbd\x1f\x6c\xbf\x0c\x08\x90\x07\xb5\x0b\xf6\xdf\xa8\x1d\x78\x71\xd3\xba\x67\xc0\x75\x5d\x15\xe7\x0a\xcf\x5e\xb0\xeb\xe0\x95\xe7\x9c\x59\x1e\x64\x99\x77\xcd\x7b\x21\xfb\xf0\xc8\x1d\xcd\xda\x8f\x5e\xdb\xfe\xc1\xbd\x4b\x36\x3f\xfd\x7f\xff\xda\xf4\x22\xf8\x6f\xbc\x0e\xa4\x5f\x9f\x4b\xe3\xf2\xf2\xe0\xb4\x97\xd6\x5d\x79\x70\x57\xca\x15\x64\xcb\x0a\xd8\x66\xf4\x48\x71\x4f\xbb\xb2\x68\xc1\x68\x6c\xe7\x87\xbf\x64\xc7\xff\x25\xdf\x96\xf6\x71\x68\x1a\x78\xc9\xf8\x2f\xb8\x5d\xf6\x1e\x34\x72\x68\xe4\x95\xf1\x9d\x05\xf8\x3f\x34\x6a\x20\x7d\x18\xbb\xb0\x70\xe7\x51\x1c\x0e\x03\xc7\x23\x74\x78\x98\x1e\xa2\x46\x50\x27\x9a\x6c\x78\xe2\x55\x82\xc0\x48\xa2\x60\x74\x03\x96\x8c\x72\x51\x2e\x92\xc0\x35\x63\xd4\x8b\x6d\x50\x24\x7d\x68\x02\x4e\xd1\xbf\x8f\xa0\x81\x10\x54\x04\x08\x82\x70\x3a\x1b\x12\xe9\x21\xd9\xbb\xbf\xeb\x65\x9e\x77\x65\x5d\xcf\x52\x42\x7b\xe7\xc9\xb5\xb9\xd4\x69\x3d\x4d\xac\xe3\x11\xc1\xef\xe1\x79\x82\x7b\xbe\xb1\x00\xf7\xb1\x87\x97\xd3\xfc\x1e\xa2\x6f\x0f\x9f\x96\xf9\x3d\xfb\xbd\xda\xc4\x7c\xee\x31\xb0\x3c\x86\xe7\xa7\xe5\x7b\xd7\xff\x86\x4f\xf3\x3c\xff\x0c\xe5\x2c\x0f\x79\x89\xdc\x68\xce\xa7\x28\x76\xf6\x25\xb7\xd3\x95\x11\xfe\xb6\x76\x58\xaf\x98\x5c\xb8\xb1\xf0\x18\xed\x8f\x18\x5d\xf0\xd8\x63\x08\xc1\xe1\xc3\x08\x98\x73\xc9\x49\xe8\x02\xc3\x66\x90\x66\x58\x1c\xc0\x06\x90\x46\x00\xb3\x10\xa5\x68\xb9\x06\x12\x04\xc3\x92\x92\x60\x50\x60\x44\x69\xbd\x86\x09\x02\x2b\x06\xda\x56\x2a\x1e\x00\x7d\x8e\xd4\x8f\x01\x22\xa9\xb6\x92\x06\x76\x84\xa1\x70\xe9\x3d\x45\x0a\x10\x82\x81\x07\x63\xac\x8a\xb7\x62\x35\x5b\xd8\xff\xc0\x52\x3c\x2b\x4a\xcc\xb9\xd2\x1e\x4f\x79\x59\x20\xc8\xf0\x89\x08\x09\x97\x24\x09\x86\x31\x55\xc8\x87\x91\xa7\x5d\x10\x02\xfd\x0d\x1d\x1e\xc2\xe2\xe1\x1d\xc0\x90\xa4\x2b\xba\x6e\xd2\xd5\x6b\x16\x79\x4a\x2c\xd1\xd3\x97\x5d\xd2\x4c\x13\xa4\xa3\x02\x5c\x36\x91\xa2\x9c\x26\x21\xed\x70\x96\x66\x2b\xcb\xfc\x76\x4c\xbb\xcc\x16\x0a\xb3\x0c\x5d\xd2\x6c\x77\x39\xc5\xcc\x4f\x07\x32\x82\x8f\x65\x30\x81\x81\xe6\x58\x93\x2b\x52\xd1\x1a\x6f\xae\x21\x6d\x14\x89\x69\xc1\x02\x21\x25\x49\x13\x9f\xb7\xbf\x13\xca\xa4\x2a\x1a\x7c\x15\x55\x41\x8c\x77\xcc\xa7\x1c\x72\xa0\x84\xa4\x04\x9b\xcd\x3d\x7b\x42\x8d\x09\x28\x4f\x74\x42\xa5\xa3\x84\xa6\x78\x82\x2c\xef\xe8\xf2\x78\x2c\x65\x3b\x87\x81\xbe\xc4\x29\x52\x34\x8f\xb1\x99\x24\xac\xee\xe4\x4a\x7f\x69\xf3\xdc\x3a\x3f\x05\xa6\x58\xe3\xb2\x9e\xb2\x4e\xbb\x2d\x62\xc6\x22\x6f\xf5\x62\xb0\x51\x5c\x30\xdc\x98\x9e\x27\x5b\x5b\x23\x35\x41\x33\x26\xbd\x95\x0b\x5a\x97\x6d\xb4\x38\x08\x02\x08\x02\x30\xe5\x30\x1b\x5c\xc1\xf7\xd0\x9f\x51\x53\x90\xc5\x18\xf1\x6a\xd0\x2c\xb4\x1c\x9d\x87\x50\xfc\x88\x4e\xac\xcf\xc6\x46\x50\x12\xb3\xd2\x18\xde\xa7\x14\x80\x78\x02\x62\x0c\x4d\xea\x1f\xa2\x9a\x8d\xc5\x05\x56\x1f\x15\x13\x90\x49\xbb\xd4\x6c\x4c\x57\x07\x03\x90\x35\x70\xd1\xf4\xcf\xd6\x50\x2d\x71\x00\x8a\x80\xa1\x59\x99\xa1\x0b\x2a\x65\xdc\x48\x33\x92\x94\x04\xe8\x2a\xbb\xae\xa2\xe3\xdb\xdd\x42\x34\x32\xcd\x2d\xba\xba\x67\x9c\x65\x32\xdb\xd9\x52\x86\x0b\xb0\x81\x87\xaa\xff\xba\x6a\xe5\x8c\x9a\x9a\xdf\xac\x58\xb5\x18\xac\xe6\x61\xed\xf0\xae\xb7\xb4\x3f\xb1\xe6\x61\x80\x5d\x6f\x41\x1c\xe4\xde\xcb\x7e\xae\xe5\xb5\x77\xb4\x7f\xbf\xba\xfd\xfb\xb9\xbb\x61\x5e\x6f\x47\x35\x49\xb3\x0e\x9a\xfe\xfe\xef\x13\xd5\xd5\x98\x62\x2d\xb6\x86\x85\xdd\x67\xcd\x2c\xe1\x4d\x95\x92\x24\x32\xc2\xdc\x36\x4f\x05\x49\x79\x3d\xcd\x30\x6b\x4e\x4a\x31\x27\xb3\x5e\x93\x3f\xd6\xda\x7a\xdf\x1c\x7f\xad\x2d\xe8\xdf\xfc\xe9\x68\x64\xa2\x83\xf5\x86\x23\x13\x42\xbe\x1b\xec\x3e\x8a\xb2\xda\x83\x2c\x65\x1d\x5c\x32\x14\x8b\xec\x5b\xbc\x68\xa1\xaf\xf4\xa1\xe6\xa1\x2b\x27\xb2\xd2\x07\xbb\x0a\xa7\x9d\xdd\x97\xee\x58\xd6\xda\xb5\xfe\x91\xd3\xd7\x01\x99\xbb\xfb\xbb\xbd\xed\x97\xb3\x36\x4c\x60\xdc\xd4\xd2\xb6\xce\xce\x5a\x49\xd2\xd5\xb8\x1c\x2f\x1e\xdc\x5c\x2f\x89\x8c\xa9\x52\x6a\x1b\xb2\x53\x5e\x8f\xa7\x9c\xb2\x4f\x1f\xca\xaf\xf3\x79\x5d\x49\xdf\xc0\xde\xee\x09\x19\x17\x1d\xac\xaf\xa1\xbd\x53\xc6\xcb\x16\x6b\x91\x19\xf1\xa8\x14\x21\x83\xdf\xb6\x15\xd4\x00\x00\x27\x60\x46\xe6\xd2\xae\x18\x38\x19\x19\x67\x38\x91\x74\x91\x67\xdc\xfb\xcc\x2f\xee\xbd\xf8\xe9\x48\xf4\x69\xed\x86\xfc\xaf\x1f\xba\x0b\x62\x64\xe6\xa1\x5f\xe7\x1f\x84\xd8\x5d\x91\xc1\xc1\x39\x9f\x5f\x76\xd9\xe7\x54\x8b\xe6\x1b\xd5\xbe\x73\xca\x6b\xe0\x79\x0c\x26\xfc\x3e\x5f\xa1\xfd\xe3\xb5\x53\xe0\x96\x51\x78\x3b\xf0\x7b\xed\xb1\x22\xd6\x33\xa2\x36\xd1\x08\xad\x44\x08\x58\x42\x17\x55\x69\xc4\x18\x28\x1f\xd9\x98\xca\xe2\x04\xa1\xb4\x42\x00\x4b\x59\x3d\x4c\xe9\x61\x2a\x08\xd9\x4c\x82\xca\xaa\x01\x92\xc5\x0e\x10\x05\xa6\x95\x12\x25\x56\xff\x90\x69\x3d\x48\x6d\x0a\xcd\x1d\x5c\x76\xca\xe0\xf4\x66\x27\xb7\x46\xbb\xe5\x65\xde\xeb\xe5\xf7\x40\xe5\x92\xd8\xe4\xc1\xb9\x27\xcf\x3e\x29\xbc\xf6\xb9\xef\xad\x6d\x2b\xc9\x78\x19\x71\x52\xf7\xe2\x81\xd9\xed\xd5\xf4\xc4\xf3\x4e\x9e\xdd\x92\x0a\x8b\x14\x69\x33\xf9\x26\xd5\xa7\x59\x39\xd5\x73\x46\x73\x8c\xa2\x05\x97\x89\x01\x20\xd8\x9a\xec\xdc\xc5\xdb\xba\xb1\xd2\x32\x6d\xd6\xcc\xbe\x26\x8e\x93\x92\xb4\x67\x4a\xff\xfa\xb3\x76\xc2\x4f\xfa\xcf\x6a\x09\x11\x6c\xa0\xc4\x62\x39\xa0\x7d\x01\x5e\xb9\x04\x5e\x7d\x9c\x75\x99\xec\x55\xbd\x5b\x4f\xaa\x11\xa2\xd3\xfa\xaa\x76\x0c\x03\x81\x09\xae\xb4\xbe\x77\xdd\x44\x3f\xc7\x97\x37\xb5\xb5\xd5\x39\x9c\x9b\x7a\x68\x61\x42\xef\xea\x35\x97\x74\x97\xf4\xf4\xcf\x9f\x7b\xd2\xc4\xac\xc3\x41\x2e\xf4\x32\x52\x5b\xa6\x31\x88\xa5\x69\xe7\x0d\xb4\x04\x5c\x40\x10\xc4\x15\x17\x32\x52\x53\x42\xc6\x75\x88\x44\xee\xc3\x88\xfc\x27\x85\x0c\x4b\x72\xc1\xf0\xaf\x32\x24\x2c\x28\xd8\xec\x83\x3b\xcc\xe9\x7f\x71\xf7\x18\x23\x13\xf9\xcf\x75\x33\x1a\xb4\xd1\xfc\x47\x33\xd6\x91\xbf\x3f\x54\x31\xf6\xb7\x6e\x06\x31\x6d\xc6\x3a\xf0\x75\xce\x5a\xaf\xfd\x0b\xec\xeb\x67\x75\xc2\xc4\xc3\xe8\x30\x4c\x3e\x8c\x0e\xff\xa0\xab\x6b\xe6\xfa\xf5\xe3\xe4\xcc\x12\x14\xd7\x67\x4d\xf4\x95\x34\xa6\xe2\x57\x38\x77\x91\xb9\x22\x91\xe9\x18\xc9\x66\x81\xc8\xf4\xee\xaf\x73\xf4\xc2\x3b\x4f\xc0\x67\x7a\xef\xd7\x39\x7c\x1d\x23\x13\x17\xcb\x7a\x2c\x1b\xeb\x78\x32\x56\xd7\x57\x96\x95\xb7\x6b\xc3\x7a\x01\x8f\x52\xb1\xc2\x90\x9d\x1f\xfe\xda\xc2\xee\x2f\x16\x11\xda\xcc\xfe\x31\x46\x56\xed\xf0\xd7\x96\xf6\x4b\xf2\x7b\x61\xcd\xf4\x68\x31\x8f\x97\xdf\xbf\xb4\xdb\x80\x64\xaf\xc0\x15\xdc\xce\x38\xc1\x2b\x03\xfa\x1a\x07\xb5\x91\x7c\xce\x2b\xdb\x8a\x6e\x63\x36\x79\xf4\xd9\x6f\xe1\x0f\xc6\x20\x1e\x05\x8f\xfa\xe1\xbb\xbe\x82\x31\xa0\xb8\x9f\x5b\xf1\x75\xbc\x01\x45\xef\x7a\x08\x7d\x2d\x7d\x40\xd1\xc6\x7d\x11\xb5\x1f\xb9\x51\x16\x21\x90\x0c\x71\x4c\x97\xc6\x54\x49\x9f\x5b\x51\x4a\x17\x4a\x25\x63\x34\x22\x0a\x40\x62\xaa\x41\x2e\xea\x16\x68\x85\x0f\xbb\xc3\x52\x38\x29\xf1\xc4\xe1\x25\x8d\xda\xcb\x8f\xdd\xa8\x7d\x76\xc3\x6f\xee\xe1\x36\xed\x02\x66\xdf\xd6\x57\xcf\xc6\xbe\xc6\xc3\xc8\xee\x2c\xe3\x3e\xd2\xca\x3c\x71\x62\x08\x9b\xd8\xd9\xd9\xce\xc1\x65\xdd\x71\xb8\x4b\x5b\xee\x84\x5f\x96\x71\x07\x60\xd1\xaf\x1f\xfc\xf3\x0d\x60\xbe\xf1\x21\xa8\x68\xdd\x91\x7d\xeb\x82\x7d\xda\x17\xdb\xdf\xf4\xae\xcd\x31\x51\x78\x33\xec\x21\xac\x5c\x49\xaa\x6d\xb0\x73\xc2\x77\x18\xed\xad\x5c\x2e\xaa\x35\x9c\x80\xd7\x27\xab\xc8\x44\x36\x95\x64\x58\x30\xcc\x29\xe5\xc2\x92\xae\x54\xf0\xcd\x92\xc4\x54\x92\x77\x7d\xc9\x3a\xd1\x66\xb9\xf7\xef\x33\xaa\xe4\x59\x56\xf2\x07\xd1\x4a\xc5\x1e\x0a\x6c\x6f\x5a\xee\x3b\xdd\x97\xee\xb3\x36\x24\x1d\xcd\x8e\xee\xa1\x9b\xfe\xfa\xc6\xc1\x63\xde\xe7\xf6\x3f\xd0\x26\xed\x5f\xfc\x50\xc3\x1b\x77\x67\x7f\xf5\x84\x8d\x59\xe4\x19\xf2\x74\xa5\x1f\x54\xff\xa4\x3e\x08\x32\xf8\xe0\xbc\x63\x76\xd0\xe0\x08\x0f\x86\xae\xff\x0a\x98\x2c\xa8\x61\x47\x0c\x8c\xda\x20\x33\x3e\x3c\xe6\x86\x15\xcf\x8a\xa5\x20\x30\x94\x7b\x2c\xc0\x65\x51\x31\x93\xcc\x3d\xa1\x3d\xfe\xb3\x61\xd6\xf5\x1a\x41\x5b\xcc\x76\xe9\xdd\xb1\xb3\x8b\x1d\x66\x5d\xb0\xde\xe1\x95\xb4\xf5\xc5\xd3\xe3\x40\x1a\xa9\x78\xe4\x67\xda\xe3\x4f\xb8\x58\x7c\x4a\x27\xd0\x16\x67\x4e\x32\x4d\x5a\x74\x24\x74\x50\xd7\x2a\x1f\x3a\x8b\x12\xf4\xd8\xc6\x45\x63\x01\xad\xc4\x0e\xc2\x93\xac\xcb\x35\xce\xf7\x3b\x5a\x44\x9f\x76\x17\xdd\x8c\x0a\x95\x39\x32\x18\x1d\xd9\x15\xfb\x96\xfe\xe0\x5a\x81\xd5\x52\x1b\x36\x94\xdf\xa1\x82\x0f\xca\xd0\x37\x7a\x87\x7f\xe9\x7a\xe3\x49\x5f\xe7\x2d\x5e\xf4\x8b\x35\xe5\x28\x84\x14\x83\xf1\xaf\xbf\xb0\xfb\x96\x29\x28\xc1\x09\x28\xd0\x1a\x67\x9b\x20\x93\x4a\x4a\x61\x43\x82\x31\x4c\x51\x81\x51\x45\x81\x91\xb2\x69\x05\xc2\x34\x13\xa1\x1d\x00\x2c\x54\x02\x91\x4a\x12\x51\x3e\x95\x14\x25\x08\x90\x29\x2a\x2c\xe3\xd3\xcf\xbc\x39\xd7\x6e\xe7\x99\xc6\xa9\x53\x1b\x19\xde\xde\x9e\xbb\xf9\x4c\x72\x5e\xc5\x36\xe7\xbc\x4d\xd5\xd5\x9b\xe6\x39\xb7\x55\xd0\x99\xcc\x8c\xee\xee\x43\xb3\x88\xcf\x5e\xff\xa8\x61\xb5\xcf\xaf\xed\xf7\xce\xab\x1e\x5a\x54\x7a\xd3\x4d\xa5\x8b\x86\x12\x73\xbd\x10\x22\xd9\x9a\x64\x4f\x0c\x9e\x1b\x35\x9f\x05\xc3\xed\xed\x35\x61\x4f\x09\xe6\x3c\x1c\x2e\xf1\x84\x6b\xda\xdb\x19\x91\x70\xa4\xaa\x62\x55\x29\x07\x21\x32\xa3\xb1\xd5\xb1\x40\xed\x95\xb5\xda\xef\xe5\x8a\x5a\x8f\x47\xdb\xef\x95\xe1\x65\xd8\x0f\x2f\xcb\x5e\x6d\x3f\x69\x0f\x97\xb8\xfb\xdb\x8b\xdf\x47\x8e\x46\x68\xc0\xb0\x4f\xd6\x3f\x56\x5d\x43\x2c\xec\x22\xd5\x00\x75\x34\x38\x46\xd0\xd0\x06\xc4\xd1\xa0\x52\x34\x63\x0d\x42\xfc\x68\xb0\x08\x6f\x47\x3b\x80\x57\xb3\x10\x27\x28\xea\xa3\xd6\x93\x16\xdd\x57\xcf\xcc\x6c\xaa\x99\xea\x50\xb5\xe7\x55\xd3\xcc\xe6\x9a\x3e\x87\x7a\x5d\xa9\xbb\x65\x86\x5a\x75\xe3\xf2\x1b\xbd\x62\xf3\x80\x5a\x75\x53\xa6\x90\x91\x85\x6c\xd6\x34\x4b\xbf\x38\x73\x9b\x5b\x6c\x9e\xd5\x5c\x75\xd3\xf2\xdd\x9e\xd1\x51\xc8\x2e\xd7\x9e\xc7\x9f\xcf\x68\xf9\x4e\xb8\xe9\x2e\xb7\xb7\x69\x76\xb6\xfa\x8e\x15\xbb\x3d\x92\x1e\xb8\x3d\x63\xee\x6f\xa9\xe9\x73\x64\xa0\x21\x6b\x9a\xa1\x3f\x25\x73\x8b\x47\x6a\x9e\x95\xad\x1e\x5e\x3e\xac\x5f\xa2\x56\xdd\xaa\xd2\xd3\x9b\xaa\x7b\x1c\x59\xed\x17\xf5\x26\xed\xe0\x72\x68\x5a\x79\xfc\x5a\x4d\xb9\x61\x49\x75\x9c\x8d\x08\x70\x45\x22\xfb\x06\x28\x52\xd9\x2b\xc5\x1e\x3b\xd6\x81\x8b\x78\x19\x74\xb2\x95\x52\xe3\xad\x30\xde\x88\x84\xd8\x1f\x0c\x47\x9e\xc9\x9c\xdc\xd9\x79\x72\xcd\x93\x35\xb6\x0a\x4b\x7d\x19\xd1\x5e\x56\xaf\x96\x8f\x8e\x94\xd5\xb7\xc4\x6b\x1e\x52\x08\x3f\xeb\xe7\x3d\x6e\xc1\xed\xe1\xfd\xac\x9f\x00\x6b\xb4\xed\x58\x5b\x93\x43\xfb\x61\x6f\x54\x10\xb7\xc6\x26\x4c\x08\x6d\x0c\x99\x64\x93\xd6\x57\x56\x5f\x8f\x4f\x2b\x6f\xac\x2f\x8b\x4f\x2f\x09\xad\xf5\x62\xde\xcc\x99\x2d\x14\x65\x31\x73\x66\x1e\xff\x48\x9a\x8e\xc6\xf6\x12\x0d\xdf\x03\x0a\xb5\xa1\x49\x68\x06\xfa\x0e\x5a\x83\x10\x9f\x56\x41\xc6\x06\x42\x26\x61\x6c\xfd\xc8\x8e\xc2\x9a\x86\xae\x3b\xf1\x47\x92\x22\x72\x34\x1b\x4b\x25\x49\xa9\xe0\xe2\x49\x4b\x22\xc5\x8b\x92\x31\x07\x8a\x6e\x01\x33\x7c\x36\x93\x46\x21\x52\x74\x39\x31\x4d\x86\x62\x32\x76\xba\xb2\x28\x14\xcb\xba\x9c\x58\x8e\x85\x48\x1a\x3b\x5d\xe2\x79\x5d\xb0\xea\x17\x1f\x52\x26\xca\x61\xf2\x91\x7d\xda\x7b\x89\x0a\x9e\xe5\xf9\x17\xa6\x9c\x67\xe3\x68\xc2\x61\xeb\xdf\xf0\x43\xed\x1f\xc5\x34\x26\x64\x59\x0e\x27\x3d\x7b\x05\x58\x97\x5b\xd4\x5e\x92\xb4\xd1\x2e\x46\x24\xda\x34\xfa\x03\x20\xb7\x6e\x5b\xbd\x9c\xd8\xbc\xf8\xe5\x1f\xff\xb3\x69\xf4\x36\x38\x1d\xfa\x3e\xde\xb9\xf3\x63\x6d\xaf\x76\xa5\xb6\x57\x0f\xc1\x2c\x98\x0f\x2d\x6f\x5f\x78\xe1\xdb\xda\xd3\xda\x9d\xda\xd3\x7a\x08\xe7\x6e\xbf\x7a\x94\x5f\x0c\x67\x81\x89\x57\x9a\xfd\xf3\xed\x87\x11\xd1\x48\x50\x38\x5c\x0a\x16\x30\x83\xcd\xc5\xb3\x60\xd2\x1e\xd5\x4c\x44\xfb\x58\xea\xf0\x63\x2b\x86\x66\xa8\x36\x0f\xef\x73\x04\x6c\x31\x6a\xe5\x2b\xf9\x8d\x34\x55\x15\x22\x07\x7e\xf4\xf4\x6f\xb4\x5b\x96\xe0\x3b\xef\x5e\x59\x81\xd3\xc7\xfc\x70\x9f\x51\x98\x2f\x1e\xb9\xf0\x6d\x68\x39\xae\x0c\x47\xb8\xa0\xf4\xf6\x77\x21\x9f\x2e\x41\x50\x72\x4c\xff\x46\x62\xaa\x9b\x26\xdd\x02\x29\x71\xc0\xc7\x55\x59\xc9\x90\x12\xd9\xaa\x7d\x7c\x40\xfb\xc1\xef\x7f\x05\x8b\x5e\x7f\x5d\x7b\x17\x32\xef\x11\x7b\xe2\xf9\x7f\x5d\xb1\xfe\x56\x70\xff\x9a\x46\x07\x51\x4e\xd8\x9d\xdf\xf5\x83\xcf\x76\x7b\xef\x93\xf7\x5f\x7a\xed\x3b\x01\xaa\x5f\x6b\xd3\x36\xad\x3d\x69\x62\xe9\x7d\xe1\x2d\x63\x36\xe6\x06\xef\x94\x0d\xc9\xa8\x16\x21\x33\xb8\xa3\xc5\x2e\x1c\xcd\x40\x98\x4b\x71\xe3\xfe\x8e\x62\xc7\x51\x63\xc1\x14\x31\x42\x8c\xe4\xca\xfd\x07\x2d\xfe\xf2\x1c\x20\x40\xb9\xb1\x7f\x4d\xfe\xf2\x2f\x72\xe5\xfe\x26\xba\xc9\x5f\xfe\x79\xae\xdc\x4f\x23\x2d\x57\x40\x00\x39\x8c\xf2\x88\x18\xf7\x57\x80\x27\x1d\x91\xbd\x7a\x7e\xb1\xfe\xe6\x82\xef\xba\x2e\x2f\xf0\xa2\xd1\x51\x54\x9e\x12\x93\x6a\x91\x6f\x2b\xce\x02\x23\xba\x05\x86\x2f\xda\x78\xca\x2a\xaf\x0f\xb6\x59\x35\x3e\xc6\xeb\x45\x7f\xe8\x22\xef\xd3\x7e\xaf\xed\xd6\x7e\x7f\x1f\xe9\xc2\xad\x62\x5a\x24\xfb\xc5\x43\xc3\xa4\x8d\xcc\x9f\x55\x59\x4f\xb7\x35\x36\x62\x8b\xd9\x31\xe2\x30\x5b\x70\x63\x63\x87\x75\x8e\xf6\xa0\x28\x92\x43\xa4\x8d\x24\x87\xf0\xe3\xda\x2f\x26\x9c\x33\x61\xc2\x39\x13\xa0\xf9\x21\x86\xc1\xce\x84\x49\x1b\x06\x78\x31\x72\xc3\x69\xb1\x9e\x09\xb2\x36\x9d\xb5\x5a\xad\x56\x16\x7e\x22\x4f\xe8\x91\x5f\xda\xbc\xcc\x94\x30\xc1\x10\x80\x36\x8c\x00\x9d\x71\x38\x47\x5d\x51\xb0\x69\x01\x5e\x8e\x46\x18\x5e\x46\x58\x11\x53\x49\x35\x00\x2e\xa9\x95\x50\xf5\x60\x1d\x4b\x30\x34\xb1\xc0\xde\x5a\x59\xde\x6e\x2f\xd3\x0e\xdf\xbf\xa8\x31\x59\xd5\xd5\x76\xc9\xcf\x2b\xe2\x97\xcf\xdf\x50\x93\xcd\xd4\x37\xfa\xdb\xa3\xd3\x2c\xbb\x70\x57\xbe\xc5\x6a\xc5\x4f\x4f\x80\x67\xa0\xec\xfb\x0e\xc7\xaa\x0f\xb4\x5f\x4c\x68\x79\xf7\x8a\x17\xe6\xb0\xac\x72\x4a\xe3\x77\xb9\xcf\x8b\x9c\x38\xd4\x5f\x8c\x39\x14\x41\x58\xff\xca\x0a\xeb\x5d\x4e\x57\x36\x96\x0a\x49\x8c\x1c\x8d\x18\x42\x5e\x2a\xd9\x4a\xa8\x61\x02\xe1\x57\x6d\x0f\x6b\x3f\xfe\xe3\x4d\xda\x81\x17\x37\x6e\x7c\x11\xfc\x37\x41\xd5\x6b\xbf\xd9\xfc\xc8\xb6\x3f\xe5\x72\x7f\xda\x36\x67\xd7\xe0\xc4\x30\xad\xf5\xe1\x0f\xbb\x5a\x5e\xd7\xee\x1d\xd1\x2f\x80\x46\xf0\xbf\xb8\xf1\x57\xbf\x5a\xbf\xfd\x2d\xed\xf3\xb7\xb6\xd7\x4e\x5e\x38\x10\x2f\xd8\x95\x15\xc6\x09\x27\x2a\x41\x11\x34\xcd\xd8\x8d\x10\x19\x3a\xa4\xc8\x86\x11\x7d\x2a\xa9\x66\x93\xb1\x22\x60\x73\x92\x2a\x4a\x9c\xa2\x9a\x96\x23\x8c\xac\xf0\x92\x20\x26\xb3\x06\xb6\xa9\x22\x33\x04\xcd\x14\x1d\x3d\x24\xda\x2d\x90\xa9\x64\x2c\x93\x56\x5a\x21\x36\x6e\x94\x88\x85\x48\x91\x9c\xe4\x74\xb6\x6a\x1f\xb6\x3a\x9d\xb4\x8b\xae\xdd\xb8\xa1\x8e\x76\x69\xaf\xa4\x7b\x33\x99\x5e\xf8\x59\xa6\x37\x9d\xee\xcd\x1c\x9a\x78\x6a\x6c\xfb\x43\x6d\xcf\xe9\x89\xf1\xac\xf7\x4d\x9e\x9e\xb0\x77\x5b\x34\x9d\x9c\x18\x0f\xd2\xe0\x79\xe6\x59\xf0\x30\x81\x18\x2c\x39\xc1\xf7\x08\x6b\x9c\x8e\xd6\x56\x87\x93\xa6\xeb\xea\xe8\xdf\xf5\xa6\xd3\x71\x39\x3d\x3f\xae\x3f\x33\x3d\x50\x37\x31\x36\x9f\x06\x5f\x75\x3c\x9d\xe9\xcd\x24\xeb\x28\xb7\xf6\x1c\x33\x3f\x3e\xb1\x2e\xda\xe8\xf0\x95\xee\x7c\xfe\xf9\x9d\xa1\x12\x47\xc3\x63\xc7\x3d\x70\xe7\xce\x8f\x8f\xc5\xc1\x72\x18\x6c\x4e\xfa\x78\x6a\xb4\x53\xa4\xd8\x4e\x7a\x33\xc5\xc7\x9a\x49\xa4\x8e\x84\x54\xa3\x71\x64\x45\x95\xf4\x77\xf7\x15\x4d\x55\xf0\xb6\x57\xbe\x6c\xb7\x44\xdc\x6b\xb7\x67\xde\xcf\xd8\xed\x94\x93\xaa\x78\xb1\x82\x72\x6a\x5a\xa2\x35\x51\xdd\x5e\x0d\x03\x85\xf3\x6b\xcd\x95\x15\xc1\x35\xd7\x67\xef\x85\xea\x60\xa8\xba\x3a\x54\xeb\x7e\x82\x23\x9b\xaf\x5f\x15\xa8\xaa\x6c\x0e\x79\xa9\x8f\xef\xbe\xe7\x63\xba\x24\x08\xa9\x63\xf0\x27\xae\xb1\xdb\x33\x19\xbb\x9d\xa6\x2b\x2a\xe8\xab\x83\x89\x84\x71\x67\xf1\x3c\xa9\xa2\x39\x38\x8d\xfc\x97\x12\xaa\xaa\x6e\xaf\xae\xac\xa0\x5c\xda\xbf\xe9\xa9\xa1\xe6\x8a\x40\xd2\x5e\x22\x6d\xda\xb3\x67\x53\x89\xc7\x5e\x07\x07\x4e\xac\x97\x04\x50\xad\x81\xc8\xac\x16\xc1\xc7\x8e\x98\xa5\x18\x15\x2c\x98\x9c\x94\x02\x95\x29\x1a\xaa\xb4\x00\xa3\xb8\xf5\x0e\x74\x8c\x99\xe4\xc9\xf3\xcf\x1a\x3e\xcb\x2f\xfb\xae\x59\x37\x30\x63\x9d\x4f\xe0\x7d\x70\xd1\xd5\xfa\x69\x7e\xf3\x59\xb7\xad\x83\x19\xc7\xeb\x2f\xfb\x7c\xad\xd3\x57\xaf\x9a\xae\xbd\x2d\xf8\x7c\xc2\x86\x4d\x03\x6b\xd7\xf4\x83\x87\xf7\xfb\xf9\xec\x5b\x9b\xb6\x0a\x3e\x3f\xbf\xd9\xeb\xdf\xdc\xbf\x76\x2d\xec\x39\x5e\xab\xd1\xc7\xa8\xdb\x99\x1c\xb5\xc8\x28\xb7\x81\x8b\x54\x28\x74\xc1\xc5\xfe\x08\x79\xbd\x51\x68\x86\x0a\x8f\xe5\x48\x6a\x21\x8b\x94\x9b\x67\x36\x8f\xfe\xe4\x81\x43\x30\xb9\x79\x66\x73\xfe\xc7\xf7\x8f\x3e\x0d\x97\xc2\xe4\x43\x0f\xfc\x64\x74\xc7\xd3\xcd\x33\x9b\x89\xfa\x73\x2a\x9a\x9b\x2b\xf2\x37\xfe\xf8\xf3\x43\x0f\x80\x45\x3b\x58\xd9\xd4\x54\x89\x4f\xbf\xf7\xd3\x7f\xdf\x77\x61\xe3\xad\xda\x7f\x1f\x38\xf4\xc5\xfd\x60\x6b\x69\xd4\x3e\xad\x68\x6a\xaa\x18\xaf\xaf\xd8\x51\x29\x42\x71\x2e\xcc\x85\x0b\xf4\xa8\x27\x90\x8f\xa9\x91\x7c\xbb\x16\x5a\xb4\x03\x8f\xc0\xfe\x45\x3b\xda\xc7\xbf\xdf\x61\xd8\x8f\x47\x76\x2c\xd2\x42\xf9\xf6\x1d\x64\xe9\xb1\x06\x7b\x26\x84\x90\xd7\x84\xc8\x77\x10\x85\xcc\xc8\x6e\x70\x93\x95\xa2\xb8\x81\x9b\xa3\x4f\x0f\xe1\x12\x88\x72\xc0\xa5\x38\xc2\x9d\xca\xf0\x61\x2e\x9c\x09\x67\xc2\x71\x2e\xca\xc1\xf8\xf0\xe4\x5f\xe7\xdf\x87\xc9\x9b\xe1\xba\x17\x5e\x78\x61\x00\xbb\xf3\xff\x84\xc9\xda\xa3\x7a\xc2\xf5\x58\xc8\xbf\x0f\x93\xb4\x7d\x30\x69\x33\xf9\xce\x68\x39\xde\x97\xff\x27\xac\xd1\x2e\xc5\xee\xfc\x24\xbc\x0f\x02\xbf\xfe\xb5\xf6\xd7\xd1\x81\xdb\x07\x76\x17\x12\x8f\x04\xc7\x7d\x5f\x66\x03\x1b\xb5\x16\xb5\x17\xf8\x77\x0a\x3e\x1f\xe3\x42\xce\x22\x90\x37\xc3\xa9\x19\x31\x95\xc4\x46\x3c\x5a\x88\x7c\x49\x11\x17\xfb\x32\x95\x3e\x7f\x45\x46\xfb\x4f\x31\x80\xb7\xde\x7f\xae\xc0\x4b\xea\x9c\x2d\xaf\xa4\x3a\xcf\xbd\xeb\x27\xe7\xf6\x76\xfd\xf4\x15\xb5\xe5\x5c\x42\x3a\xc6\x88\xb2\x3b\x37\xdf\x01\x6e\x0e\x66\xe4\x16\xe8\xe7\x7c\x1d\xd8\x9e\x24\xa6\x35\x2e\xa6\xf3\xe7\x97\xbf\xc8\xe3\xe5\x60\x7b\x32\x36\xfa\x68\xf9\x8b\x3c\x7c\x7e\x6c\xfb\x5a\x50\xf9\x61\x33\xf3\x02\x8d\xd0\x76\xf4\x38\x7a\x1e\xbd\x88\xde\x40\x7f\x43\x7f\x47\xef\xa2\x0f\xd0\x47\xba\x0e\x1a\x20\xa4\x00\x96\x58\xcc\x24\xa8\xa8\x03\x44\x29\xc0\x04\x41\x64\x31\x23\x17\x1c\x48\xd2\x6a\x2b\x56\x64\x43\x45\x35\x2c\x6f\xc8\x82\xb0\xad\x4f\x89\xad\x44\x41\xa3\x96\xc6\x24\x6c\x4c\x17\x51\x3a\x70\x26\xad\x2a\xfa\x00\x62\xf8\xc8\x49\x2a\x4b\x48\x6a\x82\x51\x12\xb8\x02\xa2\x11\xa6\x95\x52\x03\xb8\x0d\xdc\x52\x56\x6d\x35\xb5\x15\x6c\x96\x58\xcc\x04\xc0\x2d\x10\xfa\x03\x03\x44\x41\xb2\x53\x25\x06\x0a\xc0\xd4\x4a\x2b\x4e\x01\xa3\xe8\x99\x7c\x4a\x62\x20\xe3\x76\x40\x1b\x26\x9f\x9d\x72\xd1\x29\x4b\x3b\x2a\xc3\x0b\x9a\x27\xd4\x6e\xbc\x31\x56\xd5\xec\x53\x12\xa7\xf4\x58\x68\xd2\x4c\x57\x31\x41\xca\x45\xd0\x00\xc0\x98\x38\x22\x7a\x7e\x48\x09\x63\x02\x37\xa9\xe0\xe1\x63\xd7\xb4\x94\x9c\xb6\xda\x4f\xbb\xb5\x40\xd0\xe9\xe1\x58\x78\xc7\x64\x75\xf3\x3e\x8a\x94\x68\x87\x97\xb9\xdd\xcc\x95\x70\x8e\x87\x01\xee\x10\x6b\x2e\xab\x51\x6b\x2c\xdd\x95\xd4\x40\x6b\x95\x5a\x21\xb8\x2d\x1e\x5b\x92\x28\xab\x8e\x42\x0b\xc5\x31\x2c\x6d\x61\xcc\x24\xe3\xf0\xba\x6a\xd8\xad\x0b\x9c\x65\xdd\x6d\xa5\x93\x4c\xb6\x50\x48\xb4\x89\x9f\x6d\xf1\x57\x95\x97\x44\xd8\xa8\xb5\xd2\xc4\xe0\xf2\xe9\xa3\x7b\xd9\xfa\x2a\x8e\xa8\xfc\x4c\xd9\x97\x35\xfb\x4a\xa5\x12\xbc\x71\x73\x4b\xbb\xf6\x45\xed\x19\x3d\x70\x2b\x11\x6d\x48\xd5\x93\x8c\x7b\x7a\x87\x5f\x9b\x30\x44\x5b\xaa\x6d\xfc\x2b\x41\x4b\x39\xb1\x11\xb0\xfe\xff\x62\xa2\x66\xe2\xfa\xef\x4c\xae\x5f\xa1\xb6\x04\xd4\x36\x67\xfc\xc6\x3d\x8f\x5f\xf5\x1d\x4c\x52\x66\x2a\xce\x94\xda\x02\x25\x71\x31\xec\x6d\x2b\xef\x73\x80\xdb\xe2\x0c\xf6\x8a\xf6\x86\x16\x37\xf6\x66\x16\x6d\xbd\x4e\x20\xbd\xab\x45\xa7\x43\x22\x56\xb0\xa2\xdd\x42\x52\x18\xec\x21\x2e\x2e\x72\x0e\x91\x28\x73\x7a\x1f\x19\xae\x8b\x45\x08\xc1\xe3\x74\xf1\x55\x3d\xde\x90\x93\x60\xed\xb1\x60\xbb\xbf\xa4\xac\x0c\x5b\x1d\xbf\xa7\xdc\x26\x07\x6d\xa1\x28\x4c\x90\x50\x19\x08\x7b\x13\xbe\x93\xcc\xe6\x6a\x3f\x40\x1f\x2c\x5e\xec\x8e\x29\x52\x35\xd7\xc0\xf7\x39\xcc\x99\xd9\x77\x3c\x5b\x49\x98\x2d\x66\x3e\xcb\x58\x47\x67\x7a\x2b\x83\xd9\x44\x3d\x55\x6d\x25\x62\xb6\x9f\xd4\x6a\x2f\x3b\x80\x71\x58\x4d\x0c\x54\x62\x3b\x83\xcf\x12\x38\xb0\xe5\xb7\x9c\x64\xa3\xeb\x00\x8c\x27\x17\x74\x5c\x17\x8d\xa8\x0f\x91\x84\xb2\x68\x11\xda\x81\x10\x25\x17\x57\x43\xa2\x91\x82\xf9\xb8\xe1\x6d\x69\x98\x35\x17\xbe\x32\xc3\xa4\x8e\x49\x25\x0d\x83\x35\x35\x0b\xe9\x04\xd6\x05\x91\x28\x9d\x20\x0c\xb5\xc8\x98\xd5\x5a\x0b\xb6\xcf\x86\xc5\x97\x50\x9c\xeb\x33\xe9\x56\x4a\x35\xba\xac\x5a\xd4\x8f\xc8\x4b\x29\x3e\xb0\xb6\x77\x5b\x3b\x65\xb2\x3a\x18\x30\x45\x56\x9e\x9c\x2c\x9f\x53\xc9\xd8\xaa\x78\x41\xca\xd4\x78\x4a\xeb\xbc\xac\x99\x93\x08\x07\xcd\x9a\x9d\x2c\x6f\xf5\x45\xad\x26\x0b\x65\x91\x60\xbe\x45\xaa\x0e\x84\x73\xdb\x63\xbe\x9e\xe9\x73\x57\xab\xeb\x76\x63\xdc\x57\xda\x35\xb1\xe1\xea\x73\x36\x85\xbc\xd3\x3a\x26\x09\xd1\x9a\x90\xbf\x34\xb3\xe5\x65\xed\x9f\xda\xcb\xda\x3b\xaf\xe6\x94\xa6\x81\x29\x03\x35\x3c\xdb\x1b\x6d\x09\xc4\xaa\x4c\xdb\x1a\xaa\xee\xab\x74\xc7\x66\x75\x9d\xa4\x2a\x49\x9e\x15\x23\x75\xa4\x8d\x16\x2c\x21\x3f\x41\x90\x61\x1f\x63\x3b\xbf\x86\x75\x58\x6c\x55\x1e\xc1\xc4\x08\xd8\x4e\x5a\x48\x9a\xc0\x0e\xd6\xc1\xd1\xa4\x0d\x6a\xc4\xea\x6a\xff\x49\x33\xa1\xac\xb1\xb1\x0c\xe0\x86\xd3\x56\xa7\x05\xae\x63\x6a\x3b\x40\x4b\x4f\x2b\x10\x91\x44\xf9\x86\x17\x77\x6b\x7f\xff\xd9\xe9\xeb\x7e\x09\xfe\xe1\x79\x77\x6d\x59\x33\xa5\xbd\xd4\x62\x8a\x0b\x65\x1e\xff\xbc\x19\x37\xc8\xa5\xd3\x7c\x76\xcf\x84\xc9\xe7\x6c\xbd\x17\x8d\xc7\xde\x0a\xa0\x66\x34\x1f\x6d\x40\x08\x1c\x98\x05\x65\xcc\x9f\x57\x95\xb3\x6d\x20\x31\xb4\x20\x89\xc9\x36\x82\x90\x18\x45\x8e\xd0\x42\x90\x60\x6a\x70\x02\xd4\x44\x01\x47\x48\x94\xb2\x62\xc1\x89\x54\xa1\xe5\x1a\x50\x25\x5d\x00\xab\x21\xd4\x20\x0e\x00\x13\x00\x42\xa0\x19\xd1\xf0\x1c\xce\xa6\xe5\x88\x83\x50\xda\x70\x2b\x48\xc6\xc0\x41\x26\x86\xaf\x09\x74\xec\x99\xe5\x5c\xdd\x33\x6b\xc3\xbc\x09\x62\xa2\xc3\x76\x8d\x35\x1e\x8f\x2f\x8b\x07\xae\xb9\xf5\x49\xdb\xb5\xb6\xf8\xb2\xde\x78\xe9\xb5\xc3\xd7\xdc\x7a\x4d\xa0\xbb\xca\x37\x71\xfe\x86\x59\x7d\xeb\x6c\x33\xef\x25\x96\x6e\x98\xd5\xbb\x96\x9d\xfd\x58\xb7\xf5\x1a\xe3\x9a\xc0\xb5\xc3\xd7\x0e\x5f\x5b\xda\x5e\xe3\xee\x3b\x0d\x2f\xe9\xf3\x26\xba\x6c\xd7\xd8\xe2\xbd\xcb\x8c\x8c\x5b\xaf\x2d\xed\x7a\x74\xb6\x75\xdd\xb4\x59\x1b\xe0\xa5\xe1\x6b\x03\xed\x09\xf7\xc4\xf9\x1b\x67\x4d\x5e\xed\x9c\xfd\xa3\x0e\xdb\xb5\xd6\xf8\x32\x39\xae\x5f\x88\x5d\xfa\x2f\xf6\x2e\xd7\x7f\xf1\xda\xe1\x6b\x03\x5d\xfb\xe6\x38\x56\xf7\xcc\xda\x78\x72\xaf\x50\x73\xe8\xaa\x59\x1b\x07\x27\xf9\xab\xba\x8d\x4b\x96\x15\x7f\x30\xd0\xbe\x67\x96\x75\x1d\x29\x4d\x3d\xcb\x3a\xeb\x91\xae\x62\x79\x8b\x59\x5d\xd5\xde\x29\x4b\x36\x16\x78\x3b\x0a\x98\x19\x13\xd0\x5c\xb4\x00\x2d\x46\x4b\xd1\x0a\x74\x11\xba\x1d\x21\xd0\x9b\xcb\x30\xfd\x2c\x18\x73\x2a\x45\x0b\x45\x55\xd6\x87\x43\x5a\x28\x18\x72\x2a\xb2\x62\x38\x1d\x67\x53\x7a\x26\x96\x44\x46\x30\x6c\x3c\x0b\x26\x9b\x84\x61\xa0\x19\xd5\xaf\x52\x8d\xdd\x30\x35\x49\x49\x0a\xc4\x39\x0a\x24\x42\x21\x24\x55\x02\x8a\x03\x89\xd1\x7f\xc2\x40\x84\x29\xac\x8b\x18\xf7\xa6\x92\xc6\xc7\x05\x9c\xb1\x95\xad\xa4\x15\xce\xb0\x6e\x51\x39\x2a\x59\x05\xa9\xa4\x9b\xc3\x3b\x41\x12\x84\xaa\x4a\xa6\x9b\xec\xea\x9a\xe1\x21\x83\x04\xdd\xe7\xde\xc6\x72\xdd\xd8\xb4\xc4\xa4\x04\x30\x06\xca\x2b\x79\x5c\x16\x12\xe8\xb8\xb5\xb1\xe6\x54\x6c\xe9\xb4\x9a\x4b\x48\x12\x13\x25\x7e\xa2\x24\xdd\x6e\x3b\x97\x22\xed\x2f\x11\x8c\x4d\x0e\x04\xbc\x12\x4b\x02\x11\x16\x6a\x63\x3c\x87\x9f\x6c\xfb\xfe\xa1\xcf\xf1\xc3\xf9\x5e\xf2\xf5\x25\x0f\x9d\xfa\x87\x25\xd5\xaf\x68\x09\xdc\xa2\x1d\xbc\x39\x5b\xb6\x7d\x57\x63\x78\xe6\xf4\x4f\xda\x4c\x16\x13\xe9\x0f\x93\x3d\x7b\x26\x2d\xbe\x6c\x96\x23\x18\xb7\xc0\x55\xa3\x07\xd9\x7c\x82\xb1\x53\x40\x00\xe5\x58\x59\x81\x13\x18\x5a\xa0\x89\x14\xe0\x79\x82\x31\x99\x85\x52\x2a\x83\x97\x4e\x5b\xec\xc0\x24\x26\xe7\x7a\x1e\xf6\x05\x2e\x32\x43\x04\x5b\x4d\x80\x39\xb0\x50\x0c\x43\x72\x34\x87\x69\xc2\xe9\x8c\xe2\x28\x49\x58\x00\x6c\x6e\x9c\x6c\xa0\x92\x33\xfc\x74\x1a\x43\x1d\xec\x77\xd8\x25\x87\x8d\x90\x1c\x5e\x82\x20\x49\xd6\x86\x77\xfd\xad\x22\x7f\xdd\x3f\x48\xd3\xbb\xf9\x6c\x10\x5f\x1e\xcc\xff\x23\x78\x66\x07\xd1\xf4\x28\x6c\x39\xc8\xd9\x87\x3b\x4f\x2a\xb1\x4d\x4b\x30\x66\x93\xd5\xe1\xc2\xf1\xba\xd2\x18\xc3\xb9\x69\x32\x77\xe8\x57\xff\xa5\xff\x65\x07\x4c\x66\xcd\x40\x53\x31\x16\x72\xcf\x9e\xb9\xd2\xad\x0d\x1a\xfe\xc6\x63\xd8\x0b\x0a\x52\xd1\x24\x34\x07\x2d\x45\xeb\xd1\xf7\xd0\x35\xe8\x2e\xf4\x08\x1a\x39\xb2\xd2\x73\x84\x1c\x96\x3a\x16\xb2\x5c\x97\x1f\x82\x10\x00\xf7\x51\x1a\xbd\x02\x1e\x3b\xf7\x0d\xf1\xff\xaf\xaf\xe7\x0b\xc0\x62\x61\x0e\x42\x9d\x83\x83\x9d\x39\xfd\x40\xed\x6f\x9c\x78\xf5\x8a\xd1\xe1\xce\xc1\xfa\x32\x3c\x5c\x36\xe4\xbf\xd6\x5f\x96\x0f\x19\x40\x47\x5f\x79\x00\xf4\xff\x96\x3f\x34\x5c\x56\x9f\xcf\x91\xb9\xc1\xce\xa3\xec\xca\xb7\x47\xce\x99\x90\x47\x2b\xae\x1e\xec\xa4\x51\x59\x7d\x99\xff\x5a\xff\x50\xd9\xa1\xdc\x91\xdb\x80\x3d\x51\x50\x3b\x61\xea\xff\x72\x01\xec\x04\x54\x5f\x36\xac\x21\x24\x14\x6c\xe8\x69\x54\xdc\xbb\x69\x43\xd3\xd1\x62\xb4\x0a\x9d\x67\x30\x08\xfe\x18\xfd\x0c\xbd\x84\xde\x42\x1f\xa1\xc3\xe0\x80\x20\xd4\x40\xdb\x09\x56\xfc\x8e\x90\x24\x16\xda\x9d\xfb\x1f\xe3\xc4\xff\xf8\x3e\xbf\x4d\xff\x38\x1e\xc8\xe7\xff\xf5\x79\xff\xff\x2c\x1f\x65\x18\xab\x1c\x2a\x58\xa9\x8c\x1c\xa5\x1d\xf8\xfa\x43\xee\xdb\x5e\x78\xf4\x80\xd1\x38\x66\xa2\x6f\x7d\x17\xa0\xff\xfd\x97\x68\x24\x7b\xbf\x30\xd6\xb9\xe8\x9c\x57\xd6\xc6\x41\xce\x7e\xfa\x4d\xc1\x07\xbe\x01\x02\xe9\xc4\xc1\x43\xec\x11\xe0\x14\xfc\x3f\xdc\x36\xfa\x3f\x5c\x7b\x0c\x0c\x13\xc2\xa8\xfd\xb0\x93\x1c\xa1\x86\x50\x10\x29\x08\x99\x8f\x37\xb2\x03\x39\xad\x8e\x19\x0b\x49\xa2\x30\xe6\x65\x4a\xee\xd6\xde\x28\xda\xd6\x69\x6f\xf8\xfd\xa5\xd3\xfd\x07\x60\xf5\x01\x7f\xbf\xdf\xaf\x0d\x17\x0c\xec\xde\xd0\xde\x18\x7d\xce\x30\xad\xcb\x69\x39\xc3\xb4\xae\x1e\x62\xfa\x05\xfe\x03\x07\xf4\x1b\xde\x2e\xd8\xd6\x51\x45\xee\xe5\x1c\x72\xa0\x52\x63\xd7\x68\x06\x42\x20\x14\xf4\x9e\x4c\xda\xd0\x4b\xa0\xc0\x15\x03\xc5\x29\x94\x4a\x92\x2e\xb7\x60\xf0\xc5\x44\x23\x74\x34\x92\x49\xb7\xe2\xf8\xb8\xab\xdd\x02\x0b\x71\x83\x1b\xa6\x20\x4e\xb5\x02\x61\x93\xe7\xb6\xf4\x6d\x69\x96\xe7\xb6\x4c\xdd\xdc\xac\xdd\x33\x73\x6a\xdf\x8e\x89\xc6\x01\x2e\x3e\x07\x5c\x8f\x46\xda\x3a\x2b\xbb\x3f\x6a\xeb\xcc\xf7\x3e\xb2\xfa\xae\x97\x61\x72\xcb\x5c\xb9\x79\xf3\x54\xfd\xb8\x05\x4e\x9d\x3a\x73\xe2\x8e\x3e\xfd\x40\x96\x35\xaf\x9c\xb6\xee\xc6\x1e\xfd\x78\x43\xfe\x95\xfe\x73\x56\xdd\xd8\xdb\xbf\x7e\xd5\x4d\x35\x4f\x6b\xef\xae\x4b\xb4\x94\x5a\xe7\xcf\xdb\x35\xfb\x95\x1f\x9d\xf3\xca\xb4\x95\xcd\xbd\x37\xac\x9b\xb6\xb2\xb9\xe7\xc6\x75\xcb\xd6\xf7\xf7\xde\xb8\xea\x9c\xfe\xde\x9b\x56\x21\x40\xed\x87\x11\x1e\xa1\x91\xe1\x1b\x2a\xd0\x0c\x2f\x16\x9d\xdd\x0b\x85\x4f\x06\x00\x8f\xac\x5d\x5c\x8d\x63\xde\x11\x6f\x0c\x57\x2f\x5e\x3b\xeb\xea\x7b\xae\x9e\x45\x7c\x7c\xf9\x33\xf1\xd1\xff\x33\x2c\xc1\x32\xf1\x67\x2e\xcf\xfd\xeb\xa6\x9b\xfe\x75\x14\x53\x64\xcc\xef\x28\x88\x10\x05\x1c\xa5\x54\x83\x5d\x7f\x89\x05\x24\xd5\x22\x56\x88\xb1\x88\x1a\x00\x22\x87\x73\xf9\x5c\x3b\xfe\x69\x7e\x62\x7e\x22\x75\x30\x16\xcc\xb7\xfb\x3b\xfd\xf9\xf6\x60\x2c\x21\xe3\x11\xb1\x4a\xc4\x23\x72\x62\x11\x2c\xc2\x5b\xde\x5d\xa3\x69\x1a\xce\xa3\x68\x33\xa7\xe5\x9c\x4e\xc8\x71\xcd\x51\x02\x95\x75\xb2\x80\x4c\xa6\xc3\x88\xed\x2c\x40\xe5\xa1\xc3\xc8\x54\xe0\x31\x39\xea\x15\xdd\x89\x10\x15\x37\xca\x41\x41\xf1\xac\x8c\xc5\xf5\x72\x51\x74\x44\x89\xcb\x4a\x31\x50\x2c\x60\xdc\x38\x64\x93\x92\x31\xf9\x52\x01\xc0\x06\x89\x50\x3b\x5c\xa9\x9d\xae\x9d\x4e\xfd\x6e\x5c\xa4\xaa\x10\xde\xa7\x4d\xd2\x26\x51\x5f\xc8\x61\xad\xbd\xa4\xbd\x44\x6b\x27\x09\x4c\x15\x83\x61\xb9\x32\x0a\x0f\x54\x46\x61\x44\xca\x4a\x30\x12\xad\x84\x07\x62\x15\x43\x23\xd0\xb8\x7b\xf5\x9e\x3d\x7b\xf2\x97\x8c\x85\x36\xdc\x01\x96\xdd\xab\x9f\x78\xe2\x89\x7c\x8b\x36\x14\x6b\x75\xee\x67\xd9\xfd\x18\x63\xac\x9f\x9d\xad\x31\x18\x96\xdb\x9d\x3f\x85\xcb\xe4\x76\xe7\x88\xc5\x32\xe2\x6c\x97\xb5\xd5\x3f\x75\xb6\x17\xf6\x54\x34\x13\xa2\x30\x22\x90\x19\x05\x91\x8c\x12\xa8\x03\x21\x08\xbb\xc3\x44\x84\x66\xc2\x32\x91\xcc\xaa\x29\x1c\x8e\xe0\x4c\x1a\x15\x7a\x24\x13\x16\xc4\x78\x38\x99\x49\x47\xc3\x99\xb0\xae\xab\x47\xc3\xf1\x70\xd2\xa0\x38\x32\x3a\x2c\x11\x0d\x33\xf5\x1a\xc0\xe1\xd1\xf9\xab\x69\xb8\xd6\x75\x67\xdb\x39\xdc\x9b\xa7\x6a\xfb\x7e\x9f\x07\xea\xc5\x8b\x5f\x38\x0d\xe7\xcf\x5c\x77\x28\x0b\x65\x2f\xfc\x52\xfb\x2d\x94\x4c\x5b\xf0\xa4\x36\xaa\xfd\x13\x0f\xcc\xb9\xf0\xec\xb6\xfb\xd6\x9e\x55\x77\xd2\xda\xdc\xc4\xfc\x4d\xe4\x9e\x2d\xda\x6f\x97\xcf\x7f\x3a\xff\x48\xbb\xaa\xbd\x00\xa6\xd7\x5e\x06\xfe\xc2\x3f\x5f\xc4\x05\x56\x6d\x4c\xde\xb5\xf7\xc9\x9e\xa9\x97\xbd\xe6\xef\xda\xba\xe0\xa1\x81\xd0\x9d\x1b\xa7\x6c\x9e\xd9\xe8\x2d\xbe\xc3\xb1\xf5\xcc\x00\x8a\xa3\x2a\xd4\x81\x26\x19\x3c\x3f\xc7\xcd\x86\xbc\xb1\xfa\x94\x49\x2b\xc6\x42\x03\x11\xcd\xa4\x92\x6e\xa1\x78\xa2\x22\x72\x26\x9c\xcd\x1c\x45\xf7\x51\xa3\x2c\x10\x49\x29\xda\x0a\x44\xd8\x1d\x1e\xbf\x13\xf6\x8a\x76\x09\x6c\x3d\x7b\xf8\xd2\x95\x4a\xef\xcc\xa9\xf7\xdf\xbe\xfe\x3b\xfb\x9e\xd8\x82\x2d\xdd\x93\xe1\x06\xb8\x6a\x5b\x6e\xf7\xcd\xdf\x7d\xa1\xf5\x62\x6b\x4f\xdd\x1a\xab\x46\x4e\x5c\x01\x6d\xda\xcf\x8f\xdd\x05\xd3\x2e\x1f\xfd\x60\xdd\x9a\x9b\x2b\xd2\xab\x1b\xa6\x57\x70\xda\x53\x8f\xce\x1f\xd4\x7e\xf2\xfa\x9a\x65\xa1\xbe\x09\x16\xe1\xfc\x9f\xdc\xb7\xfd\x7b\xbb\x7f\x16\x29\x83\x33\x37\xd5\x77\x82\x65\xea\x98\xae\xc5\x8c\xe1\xdc\x2b\xa8\x6d\x1c\x6b\x81\xb1\x06\x2b\x8d\xd9\x9f\x29\xba\x64\x0e\xe3\x10\x8a\x54\x01\x45\xc1\x18\x43\x6a\x80\xa3\x0c\xf3\x99\x2c\x4a\x25\x11\x9d\xb8\xf4\xf9\x4b\x2f\x7d\x3e\x7f\xc9\xae\x65\x3e\xdf\xb2\xa9\x1d\xc1\xe0\xb5\x7d\xee\x01\x21\x74\xce\xa4\x65\xc4\xcb\x0f\x6e\x3d\xef\xc1\x07\xcf\xdb\xfa\xe0\xd5\xda\x7f\x1e\xd7\xa6\xd8\x9e\x3a\x7f\xe3\x4f\x4b\xde\x81\x0b\xa6\x0f\xda\x45\xf0\x63\xb0\x3e\xf6\x38\x58\xc9\xa0\x7e\xff\xa5\x87\x9e\x7c\x79\x17\x5d\x11\xbc\xa6\x6f\x6a\x7b\xd0\x14\x36\x35\xf7\x10\x6f\x6d\x7d\xf0\xc1\xad\xe7\x3d\xf0\xc0\x79\x4f\x68\xff\xd5\x7e\xbe\xed\x81\x6b\xcf\x5a\x08\x7b\x6e\xaa\xc5\x70\xcd\x63\x60\xd2\xfe\x83\x8e\xd1\x1d\x4d\xc8\x87\xba\xd0\xd4\x22\x12\x80\x5b\x10\x0b\x8b\x63\xb2\x62\xb8\x2f\x67\xe5\x1a\xc8\x1e\x5d\x08\x6b\x19\x53\x3c\xe2\xc9\xe2\x7b\x62\x08\xbd\xf6\xf1\xb1\xf5\xe5\x42\x9b\xe8\xca\xe1\x1f\xd7\x0e\xaf\x59\x33\xac\x39\xcf\x1a\xa8\x1f\x2c\x49\x27\x9a\x37\x94\x78\x52\x2d\x03\xa2\x30\x40\x8c\x16\xde\xc4\x7d\xc2\x15\x8b\x97\x5d\x6f\x81\x79\x57\xbf\xf2\xca\xd5\x57\xfe\x16\xff\xc5\xcc\x4f\x69\xd5\x5e\x2b\xbc\xa0\xcf\x76\x3e\x77\xc9\x25\xa7\x9e\x76\x09\x51\x3e\xbc\x66\xed\xf4\xfe\x35\xda\x73\x77\xae\x6b\xac\x15\x04\x4f\xaa\xa5\x79\x83\x27\x4c\xe1\x33\x0a\x2f\xf3\xba\x09\x0b\x37\xfc\x60\xe9\xe8\x2b\x57\x5d\xfd\xca\x6f\xae\xd4\x9e\x84\xf8\x7a\xf8\xdd\xfa\xbb\xef\xd6\x86\x4f\xbd\xe4\x92\xe7\x76\x5e\x82\x68\xe4\x3c\x3c\x9b\xfe\x88\x3a\x8c\xec\x28\x80\xaa\x51\x33\x9a\x62\xa0\x26\x11\x4c\xdc\xd8\x7c\x6d\xc5\xaa\xe8\x03\x85\x25\x1c\x40\x24\xa0\x0d\xb2\xaa\x02\x04\x6b\x20\xeb\x4a\x04\xaf\xb7\x00\xd0\x44\x5c\xe1\x5b\x41\x0a\x50\xc0\x8b\x34\xc3\x52\x8c\x4c\xc4\x15\x95\x88\xab\x09\xa2\x06\xa8\xac\x18\x04\x91\xe8\x76\x60\x6d\x61\xac\xd5\x69\x65\x1c\xe6\x08\x9e\x56\xb5\xf7\x8a\xb6\xef\xd4\x06\x09\xf2\x49\x0e\x33\xa6\xe8\xf4\x1f\xd0\xb9\xc7\x6d\x75\xbc\x6b\xd2\x95\xa6\x77\x5e\x61\xee\xf9\x6b\x43\x5e\xa9\xf9\xa3\xf6\x34\xff\x17\xa1\xbf\xcc\x53\x17\xad\xf5\xd4\xe2\x6b\x7e\xe7\xb2\x8a\xf6\xb2\x58\x4b\x78\xa2\x35\xf2\x77\x68\xd8\xb2\xf3\x0d\x6d\xd1\x35\x91\x81\x09\xcd\x1c\x07\x57\x05\xb3\x36\xab\x02\xab\xb4\xcb\xc4\x52\xa2\x21\xee\xab\xef\x8d\x2d\x64\x6c\xb8\x51\xbb\x60\xe1\xe4\xcb\x97\xcf\x74\xbb\xe1\x34\x6f\x33\xe7\x6a\x3b\x77\x76\xfe\x3d\xed\xba\xd2\x28\x41\x32\xd4\x6e\x58\x05\x2b\xf6\x38\x45\x91\x78\xa0\x4d\xfb\xc1\x63\x36\x38\x35\xe8\x27\xb1\x20\x56\x95\x64\xb5\x67\xb4\xab\xe2\xd3\xa2\x42\x44\x14\x2d\x2e\x62\x32\x9c\xfe\xf4\x07\x27\x69\xdf\x17\x66\xcf\xbb\x7e\x51\x97\xdd\x0e\x84\xcf\xe1\x68\x29\xf4\x91\x76\x53\xa1\xcf\x73\xa8\x04\x75\x1d\x45\x8b\xe0\xc3\x44\x02\x0c\x72\xfd\x23\x29\xe3\x1d\x47\xc3\x63\x0e\xa4\x63\x44\x22\x7c\x2b\xe8\xdd\x43\xe2\x53\x49\x11\xf6\x0f\x9e\x3f\x38\x78\xfe\x76\xe2\xf3\x79\xd8\x63\xce\x23\xb3\x07\x53\x84\x91\xa4\xb9\xd8\xa1\xd5\xc3\xab\x47\xd1\xea\xe1\xd5\x43\xac\x6b\xc7\x22\xff\x72\xe9\xb6\x93\x09\x74\xf2\x6d\xd2\x72\xff\xa2\x1d\xb0\x55\xbf\x68\x10\xf6\xc3\x69\x26\x9e\x37\xe5\x4b\x0a\x51\xa4\xe5\x58\x57\xae\x7f\xf5\xea\xfe\x5c\xe1\xe8\x62\x21\xb7\x68\x07\xdc\x3e\x78\xde\x79\x83\xda\xa2\x1d\x05\xbf\x5a\x93\x3e\xdc\xa6\x50\x13\x9a\xa0\xf7\xf5\x23\xba\xda\xd7\x14\xb8\x80\xb3\x1c\x2e\x32\x62\x49\xfc\x98\xdf\x2c\x1c\xad\x7b\x31\x85\x09\x2d\xda\x71\xc2\xa2\xe7\x0a\xa8\x78\x39\xbd\x02\x5f\x1c\x2c\x14\xf7\xd4\x71\xf5\x26\xc3\x46\x1a\xce\xed\x58\xa4\x57\xa2\x5d\x2f\x7e\x7b\xe1\x78\xb4\x12\x05\x00\x5a\xbd\x2a\x5a\xc8\x68\x26\xd8\x5e\x68\x80\xd1\xc7\x8c\x28\x02\x14\x3a\x8c\xa8\xfd\x46\xfd\x50\x4c\xff\x50\x03\x63\x58\x7f\x99\xb4\x81\x39\x9c\x56\xf5\x9a\x1d\x39\x16\xf8\x84\xe9\x4a\x28\x1e\xa9\xfd\xb2\x57\x4b\x82\x25\x56\xa2\x8d\x94\xc4\x2c\xa0\x25\xbd\x32\x0f\xbb\xde\x36\x8e\xcf\xe8\xc7\x1c\x9f\xd6\x0f\xb2\xf7\x19\xd8\xc5\xcb\xde\xb7\x61\xd7\xfc\xb4\xcc\x5d\x22\x97\x44\xa3\x25\xf2\x25\x9c\x9c\xe6\xe1\x8a\x23\x87\x1c\xcf\x6b\x39\x3e\x2d\x6b\x67\x18\x87\x71\x63\x8d\x1b\x55\xa2\x6e\xc3\x16\xa6\x08\x9a\x54\x18\xe5\x8b\x6e\xd8\x59\x35\xad\xc8\xe1\x71\xa9\x21\x23\x95\x4f\x2b\x72\xcc\x58\x4f\x3c\x72\x35\x69\xd0\xf3\xc1\x78\xd3\xb4\xa5\x81\x9f\x6b\x17\x5c\x5f\xe1\x13\xa9\xd0\xf9\xab\xfe\x7a\x2f\xcf\xf2\xfe\xa1\xe8\x07\xda\xaf\xae\xbb\xba\x36\x5a\xc2\x04\x36\x6d\x03\xe9\x37\x1e\xb6\x24\x7a\x7a\xd9\x56\xed\x81\xfb\x7f\x3d\x2c\x05\xcb\x83\xd6\xd2\x0b\x7e\x74\x0b\x54\x2f\x75\xf3\xa5\x95\x2f\x1c\x0f\x3f\x3f\x31\xc4\xaf\x8b\x98\x2b\x85\x52\x93\x6f\xa9\xd5\xf7\x7e\x99\xfb\x92\x0a\x7b\xaa\x24\x6a\x0a\x6f\xb1\x47\x81\xab\x91\x7a\xa6\xd4\x30\xf1\x40\xb0\xc2\x14\xef\x6e\xb1\x95\x2f\x38\x6e\x33\x08\x0a\x5c\xb6\x34\x42\xbc\x2e\x0d\x4b\x61\x2e\xcc\x10\x4c\x98\x03\x25\xcc\x85\x55\x5e\x0d\x93\x48\xfb\x8d\x07\x24\x8d\xaa\xda\x19\xd0\x5e\x81\x1a\x8f\xf6\x2e\x1c\xaa\xda\x19\x80\x6a\xf2\x37\xf9\x9f\x06\xb5\xef\x04\xb4\x8f\x02\x50\x83\x27\x05\xe0\x96\x00\x70\x01\x84\x10\x87\x10\xfa\x81\x19\x91\x67\x21\x16\xc5\x0d\x46\xfb\x66\x34\x19\xcd\x44\x27\xa3\x53\xd0\x1a\x74\x1e\xba\x04\x5d\x86\x6e\x46\xf7\xa1\x11\xf4\x3b\x84\xe2\xaa\xde\x4b\x23\xb4\x9b\x30\x46\xec\xb8\x4a\xa4\x15\x59\x6f\x5b\x86\x10\xa4\x31\xf2\x80\x0c\x48\x86\x9d\xbf\x9a\x4d\xaa\x12\xa3\xcb\xc0\x8a\x9a\x4e\x25\x81\x90\x18\x21\x6a\xa4\xa7\x92\x41\x38\x9a\x11\x2c\x1a\xee\x28\xaa\x3e\xc6\x9b\x81\x67\x04\x83\x19\x89\xd7\x47\x7c\xf5\xf8\x58\x21\x52\xf0\x0b\x6f\x00\x42\xcf\xd6\xe7\x40\x3e\x9d\xd5\x3f\xa7\xb1\x58\x2b\x24\x45\x9e\xa9\x33\x62\x98\xcf\x64\x8b\xce\xf8\x06\x7e\xb3\x21\xd5\xe9\x09\xc8\xd8\xa4\x20\x9c\x4e\x27\xd8\x2d\x66\x96\x65\xc1\x6e\x16\xa1\xc2\x6a\xb3\x9b\x9c\x26\x3b\x58\xac\xb4\x99\xb5\x9a\xcd\x87\xde\x17\x04\xcc\x62\x8e\xc3\xec\x5c\xaf\x17\x9b\xcc\x92\x64\x36\x81\xf7\xf1\x92\x12\xab\x05\xbb\xdd\xd8\x62\x1d\x94\x24\x6c\xb3\xbb\xdd\x76\xdb\x90\xdb\x8d\x59\xda\x2c\x08\x66\x9a\x85\x6d\xda\x5b\x6e\xb7\x85\x71\x62\x97\x0b\x3b\x19\xcb\x20\xcf\x5b\x4d\x2e\xec\x74\x62\x97\xc9\x7a\xb2\xcb\x85\x05\x1e\x3b\x9d\x76\x93\xd9\x06\x17\x3d\xeb\x70\x38\x04\x16\x58\xd6\x21\x38\x4e\x61\x59\xa7\xe8\x04\x9b\x0d\x9c\xa2\xe3\x55\xd6\xe5\x75\x01\x4d\xdb\xb0\xc5\x6c\x35\x31\x2c\x26\x97\xdc\x79\xf6\xe8\x87\x76\x97\x7f\xd6\xd0\xd3\x10\xe0\x32\x0d\x67\xdf\xb9\xfb\x13\x6c\xb5\xb0\xac\x25\xff\x9f\x4f\x2c\xf6\xf4\x2b\xb8\xd7\x69\xa2\x28\x93\x93\xce\x3f\x01\xff\x04\x0b\x63\x35\x33\x76\x38\x3d\xb7\xd5\x6c\xde\x9a\x33\x4f\x7c\xe9\xff\xcc\x96\xe7\x5f\x32\x6b\x49\xf8\xe7\x7f\x3e\xb0\x5a\x3f\xf8\x8f\x8d\x1a\xfd\xb7\xdd\xfe\xef\x51\x7b\xf0\xbd\xff\x3a\xcd\xcc\x7f\xdf\xa3\xcd\x9a\x88\xcf\xd0\xce\xff\x2f\x63\x75\xfd\x17\xb6\xb8\xac\xd3\xb5\xaa\x7f\x9b\xac\xfc\xbf\xe1\x77\xbc\x35\xa4\xd1\x9f\xba\xdd\x9f\xc2\x41\xb3\xdd\x9e\xe7\xf0\x7b\x1a\xfe\xc8\xe2\x60\xad\x1f\x81\x66\x65\xd9\x80\x26\xbc\x6f\x75\x3a\xad\xef\xc3\xfb\x36\xa7\x53\x33\xfd\xdd\xee\x72\xd9\xd7\x9e\x8d\xb7\x10\x0e\x33\x43\x99\x5c\xf9\x2b\xcf\xbe\x03\xbb\xec\xc4\x0e\xc9\x12\xd1\xbe\x18\x11\xef\x3c\xc2\x37\x88\x0c\x0e\x63\x9f\x81\x40\x8a\x50\x28\xa6\xba\x05\x63\x85\xbe\x05\xc4\xaf\x8f\x91\x06\x38\x75\x21\x9a\xce\x62\x1e\xfe\x08\x37\xae\x7f\x51\xbb\x59\x1b\xd2\x6e\x7e\x71\x3d\xdc\xf8\x0d\xf1\x7d\x30\x0c\x27\xbf\x38\x16\x7f\x91\x40\xb3\x67\xde\x53\xb0\xc7\xb8\x67\xe6\xe8\x3d\xe3\x22\x50\x31\x2e\x42\x56\x4c\x38\x67\x42\xae\x10\xcb\x4d\x38\x67\xdc\x7a\x2e\x8f\xbc\x28\x8a\x06\xd1\x29\xe8\x2c\x74\x1e\xfa\x1e\x42\xf0\xe5\xf5\x3a\x89\xe1\xc2\xb2\x02\xb2\x61\x6c\x9d\xe1\xc2\x1c\x18\xbb\x65\x92\xc8\x08\x34\xe3\x2e\xac\x99\x33\xd8\xe0\xed\x53\x64\x03\xf7\x48\x12\xdd\x59\x35\xab\x26\x40\xcd\x36\xe1\xa4\xe1\x7f\x2f\x96\x02\xcd\x88\x90\x55\x59\x00\x5a\xca\xaa\x69\x35\xab\xca\x19\x39\x23\x2b\x02\x43\xe8\x97\x2a\xfa\x53\x68\x4a\x8e\xea\xdf\x64\x9a\x7a\xdc\x5f\x76\x04\x40\x39\x57\x36\xe4\x3f\x1f\x36\x58\x6c\xda\x2f\x6d\x70\x8a\x36\x54\x56\x9f\x47\x58\x0b\xa7\x9a\x1a\xaf\x08\x38\x59\x0c\x74\x47\xed\x77\xdb\xde\xbc\xf7\xba\x79\x0e\xbb\x07\x28\x0b\x69\x1e\x9c\xc5\x9a\x71\x5a\xed\x8e\x79\xec\x76\x6b\xd0\x0d\x92\xcd\x65\xc6\x18\xb0\x4d\xd5\x7c\xe9\x59\xa9\x1e\xd8\xe6\xb0\x03\xcd\x18\x08\x15\x36\xd8\xf2\xbd\xab\xb0\x48\xf5\xa5\x7c\xf5\x01\xbc\xde\x73\x56\x5f\x2d\x4b\x92\xe7\x1b\x4b\x6c\x63\x30\xcc\x65\xfe\x6e\xed\xc2\x52\x1b\x34\xd8\x0e\xba\x48\x54\x5f\x06\xc3\x07\x11\x9e\xe1\x0d\x30\x75\x62\x00\x30\x80\x5c\x16\xf6\x34\x69\x07\x19\x1b\x90\x16\x6f\xd9\xd2\x6a\xb3\x03\xe3\x59\xab\x2f\xdc\x3a\x70\x43\xb2\xcc\xe1\xae\xa1\x31\x41\x05\x36\x4f\xd8\xad\xf9\x3c\xdf\x2d\x9b\x4b\x6c\xaa\x98\xcf\xc4\x89\x32\x92\x04\xc0\x20\xb2\x00\xf9\xe5\x59\x1f\x70\x54\xd7\x19\xb3\x57\xd5\x5b\x3d\x7e\x00\x74\x4c\x3f\x2b\xbc\xa3\x99\xdf\xee\xdd\xf0\xee\x14\x9f\xe2\xb3\x6a\x36\x93\x92\x02\x20\xf1\x29\xde\x80\xf4\x23\x68\x07\x44\xd3\x09\xc8\x24\x40\x21\xa2\x86\x6c\x17\x55\x64\x85\x48\x65\xbe\xb1\xa5\x97\x4f\xdc\x7d\x4b\x8e\x21\x30\x49\x00\x45\xe4\x6e\xd9\x3d\x51\xfb\xdd\xfc\x53\x28\x8c\x49\xc0\x40\xe3\xcb\xd6\x5e\x86\x29\x20\x49\x8c\xa9\x53\xe6\x7f\x8b\x66\x23\x72\x2b\xf3\x2b\xe1\x6d\xc1\xeb\x34\x79\x88\x88\x59\xf3\xe1\xab\x56\xae\xd4\x7a\x05\xaf\x9b\x60\xcc\x98\x0a\x99\x71\x38\xff\x96\x39\x48\xbb\xdd\x5e\x01\x1e\x5e\xf9\xe5\x76\x38\xe9\xdb\xb5\x43\xdc\x1d\xce\x44\xd5\x56\xdc\x04\xa2\x14\xc0\x41\x88\xea\x71\xa2\xd0\x18\x06\x84\x5b\x54\x56\xe4\x1a\x30\xe2\x3c\xf1\x8d\x8d\x00\xd5\x50\x32\x65\x29\x65\xa1\x00\x03\x89\x29\x86\x58\xd9\x07\xd1\xee\x91\xa7\xbb\xb4\x77\x7b\x97\x92\x36\x02\x63\x20\x69\xeb\x8a\x3e\xed\xcf\xdd\x4f\x3c\xf5\x2d\x9a\xe1\xbd\x15\x2b\x6e\x65\x78\x13\x49\x93\x8c\x99\xbc\x75\xc5\x0a\xe0\xc0\xbb\x72\xe5\x2d\x0c\x4f\x12\x24\x6d\xb5\xdd\xb2\x72\xa5\xf6\xb1\xf6\xf6\x98\x8d\xcc\xf8\xfa\xd7\x1b\xb6\xc0\xdf\xb6\x05\x32\xa9\x64\x81\xa7\x5b\x91\xa3\x61\x77\x8a\x83\x28\xa7\x7f\xb9\x6e\x81\xa1\xbf\xb9\xce\x21\x98\xb4\xe8\xa2\xbe\x8a\xae\xe9\xbd\x6d\xb5\x03\xda\x65\x0b\x81\x5a\xbf\x21\x1d\xac\x6f\x0d\x7e\xbb\x0a\xde\xe5\x90\x72\x03\x33\x36\xf8\xf8\x95\xf9\x57\xc1\x03\x36\x57\x78\x60\x5e\xd0\x71\xa2\x3a\x55\xa0\xe4\xb7\x1c\x79\xb8\x70\x46\x95\x80\x2c\x98\x4b\x09\xdf\x58\x05\x32\x37\x8a\x46\x72\x90\xd3\xfa\x87\x57\xaf\x1e\x5e\xfd\x2d\xca\x0d\x23\xda\xc8\x88\x7e\x4b\x6e\xb5\x7e\x0b\x42\xe6\x23\x65\x1d\x5b\x97\xd1\xcb\xab\xa2\x5e\x03\x65\x3d\x13\x75\x53\x99\x68\x69\xf1\xec\xfe\xe6\x3a\x44\xdd\xd1\x4c\x98\x03\xc3\x43\xd8\xb0\x82\xce\xf2\x99\x94\x3b\x95\x14\x71\x51\x8c\xc6\xb9\x1c\x20\xe3\x8f\x68\xfe\xda\xda\xe5\x72\x1a\xc2\x97\xac\x34\x5d\xfe\xe7\xcb\x4d\xee\x53\x72\xd3\xc5\xc8\xe3\x06\xd7\x1b\x99\x1b\xf7\x1f\x7c\x53\x8d\x73\xb9\x83\x08\xff\x46\xbb\xdd\x57\x72\xd2\x19\x67\x9c\x54\xe2\x6b\x83\xa9\xb9\x9c\x57\xf3\x1a\xfc\x8c\x47\x6c\x5e\xc7\xbd\xab\x06\xd4\x67\x58\xb3\x7d\xab\x79\xc2\x3d\xc6\x1a\x79\x84\xb8\x41\xcd\x42\x52\xcd\x3a\x95\x02\xb2\x9a\xe8\x34\x50\x57\x94\xa4\x9a\x4d\x2b\x09\xd0\x53\x04\x23\xe5\x9b\x3b\xe7\xfb\x82\xc1\x1d\x79\xe7\x0e\x5d\x31\xd8\x71\xa7\x13\xf6\x06\xf9\x6d\xdb\x9c\x59\xc1\x4d\x71\xa7\x9e\xca\x51\x6e\xd7\x13\x3e\x61\xce\x1c\x57\x56\xc6\x7c\x3a\xcd\x63\x5e\xf8\x36\xa3\x53\xc2\x24\xe6\xf7\x8b\x26\x6c\xbe\xcb\x58\x37\xbe\xcb\x91\x9f\xe4\xb9\x05\xae\xbd\xc5\x4d\x73\x5c\xc6\xbd\x59\x7b\x6a\xb3\x3b\xe3\x74\x5c\x29\x2c\x1a\x5d\xc4\xe3\x58\x46\x68\xb8\xb2\x41\xc8\xb8\xb8\x13\xf4\xe9\xd4\xb7\xfd\x4e\x8f\x5f\x1b\xa2\xc6\x5a\xcd\x40\xc3\x4c\x25\xbf\x79\x2a\x34\x58\x88\x35\xe3\x48\x9c\xae\x37\x0b\x6b\xd6\x3e\x03\xb3\xf9\x5b\xcd\x63\x44\x6e\xec\x5e\xc8\xa5\xfb\xb0\x49\xcc\x8f\xe8\xf5\x07\xcb\x7c\xb0\x98\x4f\xf0\xfe\x55\x34\x05\x2d\xf8\x96\x35\x6b\x85\x20\x04\xc0\x01\x06\xa3\x11\x6d\xb8\xaf\x84\x45\x86\x30\x78\x8b\xa0\x0d\x14\x39\xdb\x06\x59\x51\x82\x04\xa8\x7c\xe1\x5a\x3d\x53\xf9\xe6\x97\x3f\x64\xf2\x5a\x53\x56\xc2\xf4\xf0\xc3\x26\xc2\x9a\xb2\x7a\x4d\x7f\x65\x59\x92\x64\xd9\xbf\x1e\x9f\xae\x9d\x63\x77\xe0\x8b\xb1\x68\x6f\x2b\x9e\xbf\x55\x8b\x58\x09\x93\x6c\xf2\x5a\xff\xf5\x2f\xab\xd7\x24\x9b\x08\x2b\x54\xf3\x3c\xcf\x6b\xaf\x1c\x9f\x9e\xa7\xb1\x68\x27\xf4\x47\x5b\xb0\x68\x1f\xfd\xb9\xdd\x81\x11\x20\xe5\xf0\x35\xd4\xeb\x34\x32\x2c\x74\xdd\x74\x94\xc6\x05\x62\x1f\x0b\x28\x61\xd1\xab\xcb\x4e\xaa\x7c\x84\x71\x9d\x61\x21\x92\x00\x65\xfc\x72\x1f\xf5\xfa\x69\xdf\xe9\xf8\xd5\x6d\x35\xfd\x03\xfe\x8e\xe5\xa7\xae\x1b\x9a\xe3\x03\x9f\x77\xee\xc6\x4d\xd3\xef\x3e\x67\xe7\x6d\x2f\xef\x7d\xe0\xc9\x46\xa6\xa4\xab\xa9\xc3\x15\x6c\x4c\x66\xda\x7f\x7b\x5b\x2b\x7e\xe6\x59\xe9\x42\xed\xd3\x5b\xbd\xd5\xb5\x5c\x66\xed\xa5\x7f\x01\x06\xce\x7c\xe9\x8f\xda\x35\xda\x47\xcf\x0e\xdd\xfd\xc1\x64\x28\xdb\x37\xf2\x9f\x57\x46\x6e\x39\x0f\x48\x9b\x12\x5a\x3a\x63\xce\xfc\x53\x16\xfc\xf4\xb5\xe2\x9e\x3e\x53\x18\xd7\x68\x64\x41\x2c\x72\x21\x37\x2a\x41\xd5\x08\xf1\xc0\xc5\x29\x55\x31\x43\x7c\x6c\xc1\xd9\x0c\x12\x47\xc5\x81\xa3\x38\xa1\x48\x2a\xa6\xab\x24\x05\x15\xfa\x0f\x78\x81\xf6\x80\xf6\xd0\xcf\x7f\x4e\xa4\xf0\x02\xed\x5f\xda\x03\x53\xc1\xa9\x7d\xac\x7d\xfc\x7d\x98\x96\xbf\x83\x7c\xe1\xe7\xda\x43\x60\xcf\xdf\x41\xa4\x22\xa3\x2f\xb8\xab\xdc\xa3\x2f\x44\x22\x44\xca\x5d\xe5\x26\x52\x11\x58\xa5\x9d\x09\x4b\xdf\x8a\x6d\xdb\x36\xfa\x06\xec\xda\xfb\xd6\x77\x1f\x7e\xf8\xe1\x45\x6f\xc1\x52\xed\x4c\xed\xa3\x6d\x80\x63\x7b\x61\x97\x76\x5d\x65\xfe\xcf\xe5\x52\xfe\xcf\x76\x3b\x8e\x48\xe5\x38\x52\x2e\xe1\x88\xdd\x9e\xff\xb3\x34\x86\xd7\x8a\x4c\x88\xda\x80\xa2\x68\x4e\xa1\x4f\x1a\xab\x76\xd1\x70\x25\x36\x76\x38\x8e\x00\x78\xc4\x52\xc6\x3e\x07\x0d\x86\xf2\x9c\x00\xe5\x08\x5e\x78\x80\x4a\x15\x57\xf1\x98\x31\x1b\xb0\x68\xa4\xc0\xaa\x65\x5a\x75\xd1\xfb\x77\x91\x0e\xe2\xd0\x24\xc0\xd4\x3d\xef\x9f\xb9\xd0\xb6\xfb\xec\xc5\x53\xa7\x80\xf2\xe0\x9d\xe0\xb9\x1d\x0e\xfe\xfa\x87\x5b\x2e\x5a\xea\x6c\xb3\x75\x4d\x55\xa7\x4e\xcd\x54\xcd\xe8\xe8\xe8\x99\xb1\xa6\x63\xe3\x5d\x3f\xdc\x7c\xe9\xc9\x8b\x3a\xfb\xd2\xfd\xbd\x0d\x95\xd3\x3b\x3a\x7b\x06\x56\xb5\x6d\xba\x07\x8f\x26\x7e\xb9\x69\xf7\xbb\x60\xf9\xfb\x1d\x67\xfe\x34\xab\x54\xae\xbb\xad\xf1\xfa\xc7\x6f\xd5\xde\xbf\x9d\xf6\x68\x1f\x6f\xda\x79\x8a\xd0\xc3\x76\x74\x65\x33\xdd\x15\xdd\x03\x03\xdd\x15\x97\xae\xdf\xb8\xf3\x3b\xa7\xb7\x77\xa6\x1a\x26\x14\x12\x2e\x39\xd6\xff\xa0\x80\xbd\xa9\xa0\x1a\xa4\x1a\x9c\x9c\xc7\x38\x0d\xc4\x42\x8c\x94\x4d\x4a\x2a\xa8\x72\x5a\x55\x68\x27\x0a\xa9\x0a\x1d\x51\x18\x57\x28\x6b\x70\xcb\x52\x52\xd6\xa9\x30\xa2\x80\x9f\xff\xb2\xe9\x3f\x1e\xd1\xce\xbf\xf7\xa9\x81\x7b\x06\x9e\x3a\xf4\xc9\x53\x7e\xff\x53\xf3\x71\x27\x6c\x29\x24\x3c\x5f\xa4\x8a\x25\x4e\x7d\x6a\xfe\xfc\xa7\xfc\x34\x3a\x81\xa5\x30\x3b\x5f\xbf\xe9\xd0\x27\xc6\x0d\xf7\x6a\xe7\xe7\x9f\x34\x12\x40\xfe\x4b\xe1\x66\xd3\x53\xf7\x16\x1e\x67\xac\xd7\x84\xe8\xfd\xd4\x6b\x28\x6c\xf8\x68\x8d\x19\x38\xb9\x62\xaa\x9b\x46\x6e\x21\x80\x43\xad\x38\x93\x46\x4a\x46\x24\x5d\xf4\xfe\x8b\xfe\xae\x8d\x68\xc3\xda\xc8\xdf\x2f\x7a\x0a\xfa\x5f\x7c\x53\x7b\xb3\xc8\x6b\xbb\x44\x7b\xf3\xcd\x17\xa1\xff\x29\x9c\xbb\x5f\xcf\xbc\xe8\xef\xd0\x7e\xff\xab\xb0\xee\xe3\xe0\x81\x6a\x6d\xf8\x9d\xed\x05\x1a\xdb\xed\xef\xc0\x50\xf5\x81\xe0\xc7\xda\x25\x08\x01\xe2\x0f\x23\xfa\x43\x1a\xa1\x53\x10\xe2\xb3\x2e\x35\x59\x27\x30\x2c\x69\x18\x93\x18\x0e\xec\x90\xd0\x87\x27\xa2\x06\xd4\x00\x04\x21\x6b\x58\x03\xe9\x02\xa3\x9e\x69\x04\x58\xc3\x2b\xbe\xe0\xec\x9e\x20\x6b\x40\x4e\x89\x75\x01\x93\xe4\x2a\xda\x96\xf3\xa6\x3f\x3c\x43\x81\xa9\xac\xbd\x3e\x4c\xf5\x4c\x4e\x2e\x9b\xda\xea\x74\x2a\x7e\x87\xcf\xce\x5a\xca\xab\x2b\x58\xfb\x32\x65\x9a\xc0\x83\xe2\x16\x6e\x1d\x0e\x2b\x04\x29\x4e\xf7\xfb\x97\x56\x0d\xf0\x7c\x30\x22\xd4\x84\xe7\xcd\x98\x24\xba\x9b\x7b\x3c\x64\xa8\xa2\xae\x9c\xb5\xb3\x8c\xa5\xac\x7a\x7a\x5d\x77\x65\xad\x9f\x07\xe2\xcf\xda\x99\x87\xf7\x69\x7b\xff\x79\x01\xbe\xfa\x75\xd8\xb4\x0d\xb0\x29\xb5\x64\xfd\xb5\x57\xdd\x39\x29\xa9\x38\x83\x9c\x33\xb5\x63\xed\xa9\x81\xd2\x92\xba\xb0\x97\xa6\xd7\x71\x13\xbd\xbe\xda\x55\xa1\xe0\x23\x0f\x25\xd6\x44\xc2\xf1\x49\x1c\xb7\x8e\x9d\x5c\x5a\x5a\x7f\xc3\xbe\xf6\xea\xa0\x10\xe6\x9c\x99\x2d\xeb\xb7\xac\x5e\x7a\x52\x0b\xc7\xd9\x89\xd2\x48\x67\xb2\xbf\x77\xc9\xb2\xed\x93\xb4\xbc\x76\xea\x3b\x57\x7e\x0e\x03\x05\xb9\xc7\xe8\x6b\x36\xe4\x43\x65\xa8\x1f\x2d\x42\xa7\xa3\x8d\xe8\x22\x74\x1d\x42\x94\x5b\x8e\x29\xaa\x28\xa9\xa2\xc4\x88\xc0\x88\x12\x23\x3b\x55\x89\x66\x24\xda\x2d\x80\x44\x93\x4c\x26\xab\x2a\x59\x55\xca\x12\x8c\x28\x30\x12\xcd\x28\x7a\x5e\x44\x51\x65\x85\x91\x15\xa3\x5b\xea\xb9\xaa\x92\x4d\x4a\x8c\xfe\x18\x70\xd3\xc5\xcb\x94\x6c\x0c\x39\x19\x25\x5b\xb0\xbd\x54\x65\x45\xd5\x6f\x31\xee\xd2\xbb\x02\x1a\xe7\x0c\x43\x16\x9c\x63\x8e\x31\x83\x27\x56\xbc\xac\xdd\xbc\xa2\xb1\xb4\xaa\xe3\xca\x37\xb8\x8e\xfc\x5f\x4f\x12\x7d\x0d\x27\x9f\xdc\x10\xe0\x07\xa2\x94\xa9\x71\x85\x76\xf3\xcb\xf5\x1d\xdc\x1b\x57\x76\x54\x6d\x7a\x97\x65\xff\x11\xec\xda\xd7\x30\xbf\x36\xbd\x30\x5d\x3b\xbf\x61\x5f\x57\xf0\x1f\x2c\xfb\x6e\xb8\x73\x5f\xd3\xdc\xda\xaa\xd3\xab\x6a\xe7\x36\xed\xeb\xd4\x2a\x3a\xea\xf5\xcb\xe5\x68\xc3\x0a\x18\x22\x9d\x27\x37\xf8\xc4\x93\x62\xd1\x01\x3e\xd0\x20\x36\x44\x65\xfd\x47\xea\x3b\x7e\x03\x43\x60\xff\xde\x01\xed\x17\xda\x9d\xda\x2f\x0e\x7c\xef\x7b\x07\xa0\x19\xe6\x43\xf3\x81\x07\x4f\xf0\x81\x2c\xe9\xa4\x5f\xba\x2f\x52\x97\x6c\xf8\x61\xd5\x6c\x1b\xe6\xfc\xcd\xe9\xf0\x5e\xb8\x7e\x6f\xb8\xbe\xde\x7f\xea\xea\x33\xb4\x7f\x44\xee\x7b\x89\xee\x04\xdb\xec\xaa\x1f\x36\x24\xf1\x82\xfe\x8a\xd9\x15\xfd\x0b\xa7\xde\xd6\xe5\xfa\xc4\x62\xf9\xc4\xd5\x75\xdb\xd4\x85\x46\xd2\xa2\xbe\xdb\xba\x5d\x1f\x5b\x2c\x1f\xbb\xba\x6f\xeb\xc3\x72\x27\xb6\xce\xae\xb8\xbb\xbe\xa2\x3e\x7c\xdf\x4b\xf9\x7b\xb5\x25\x7b\xff\x7f\x9c\x7d\x07\x9c\x14\x45\xda\x77\x3d\xd5\x69\xc2\x4e\xec\x99\xee\xc9\xbb\x93\x7a\x36\x2f\x3b\x71\xf3\x0e\x69\x49\x4b\xce\x79\x41\x32\x28\x49\xa2\x08\x43\x12\x14\xf5\x14\x15\x03\x06\xee\x3c\x10\x91\x43\x51\x4f\x45\x51\x57\xef\x3c\x03\xea\xe9\x9d\xfa\x1e\x9e\x7a\x78\xe7\xdd\x7b\xfa\x5e\xf4\x92\xb0\x3b\xc5\xf7\xeb\xea\xd9\x00\xea\xdd\xf7\xbe\xb0\x3d\x5d\x5d\x55\xdd\x5d\x55\x5d\xf5\x54\x78\x9e\xfa\xff\x83\xc9\x26\xdf\xe2\x2b\x57\x2d\xf0\xd5\xd5\x05\x95\x60\x5d\x79\xdd\xc3\xe5\x53\x8c\x78\x10\xff\xd3\x3c\xa2\x29\xdb\xd3\x3f\xb5\xf8\x81\x6f\xb2\xce\x17\xfa\xed\x8b\xb5\xa2\x7a\x34\x14\x2d\x45\x6b\xd1\x4e\x84\xa2\x8e\x70\x28\x95\x4c\xc4\x99\xc2\x59\xca\xa4\xf8\x70\x8f\xd9\xbd\x93\x77\x3a\xe8\x4f\x00\x27\xe2\xea\xb4\x43\x15\xc3\x74\x06\x12\x4b\x8b\x09\xda\x6b\x84\xd5\xf1\x0d\x97\xd2\x70\xe3\xe3\x52\x22\x15\x56\xfd\xfc\x10\x76\xaa\xe2\x37\xe1\x0c\x3b\x1d\x01\x86\x2a\x8f\x34\x45\x4c\xfa\x72\x0a\x54\xdc\x36\x7b\xf9\xfc\x45\x91\x91\xa3\x47\x47\x94\x23\x63\xea\xe3\x4d\x53\xd6\x37\x56\x2a\x65\xab\x4b\x87\xb4\x57\x9c\xeb\x18\xe3\xad\xad\x1d\x3d\xc3\x10\x1d\x76\x3d\xc6\xd7\x33\x70\x21\xa0\xa4\x92\xfa\xb0\x7e\x29\x73\x23\xdb\x14\x01\xc6\xca\x62\xce\x5e\x5c\xa7\x64\xc9\x6b\x03\x86\xd7\xc6\xdb\x6a\xf1\x82\xfe\x2a\xb1\xcf\x06\xb5\x66\xe1\x8e\xc9\x93\x66\x24\xa2\xd7\xfa\xfd\x6b\xa6\xc4\x97\x58\x18\xdb\x90\x94\x8b\x89\x2e\xaa\x1a\x1c\xb6\x9e\x1e\x9c\x35\x73\xc5\xae\x4a\x9d\xe5\xaa\xb1\x2e\x9f\x9e\xcc\xf3\x66\x60\x67\xb5\x2c\x0f\x20\x1b\xe3\xfa\x4d\xce\x09\x9f\xe2\x75\x13\x1c\xae\xe2\x9a\x75\x0c\xe0\xb3\xd1\x74\xa3\xe2\xc2\x1f\x46\x32\xe9\x68\x24\x95\x9e\x78\x19\xc6\x2b\x8f\x86\x5c\x44\xfc\x69\x8a\x81\x6d\xa5\x6b\x98\x2b\xd0\x06\x84\xa2\xc9\x70\xc8\xe9\x48\xc4\x19\xb5\x47\x52\x1d\x6a\xcb\xa0\x4c\xea\x14\x99\x85\x73\x5a\x83\x21\x6a\x9a\x9c\x52\x27\x0f\xa9\x82\x1e\x5f\x8e\x43\x38\x9d\xb2\x25\x63\x09\xde\x69\x73\x44\x9d\x14\xd5\x2a\x65\x4b\xa4\x42\x14\xb1\x3f\x91\xa2\x21\x09\x67\x48\xa9\x00\x9b\xa3\x60\xf9\xad\xf5\x7f\x78\xe2\xe1\xfb\x8f\xdf\xd9\xd8\xd4\xb8\x65\xcb\x06\x30\x45\x2a\xac\xfb\xb7\x94\xc6\xaa\x86\x4d\x99\x32\xac\x8a\xdc\x31\x74\xf3\x55\x03\x9f\x1a\xdc\x3a\x7c\xee\x0b\x37\x76\x4c\x98\x0f\x4f\x7d\xc2\xb2\x9f\xb0\x78\xf6\xb0\xc5\x2d\x33\xe2\x7e\x1d\x16\x5c\xbc\x53\xe9\xe0\x7f\xc3\x3f\x62\xa9\x37\x4f\x9e\xda\x9c\xff\xcb\x98\xfa\x86\x71\x63\x1b\x1b\xa4\x05\x4b\x16\x32\xb3\x9a\x27\xdc\xba\x07\xde\x7a\xa3\xc8\x50\x51\xb6\xed\x09\x59\xa7\xc4\x8a\xcb\x64\x67\xa0\x6a\x62\x3d\x79\xc7\x5d\xbf\x7c\xe4\xe1\x26\xb6\x6c\xf2\x95\x3e\xd6\xf5\xf0\xf8\x7d\xa7\x6a\xba\x5f\xa8\x9a\x8e\xe7\xcd\x09\x05\x67\xe6\x0f\x4e\x3f\xf9\xe3\x58\x69\x53\xc7\xb4\x46\x98\xcb\x62\xfe\x85\xf6\x74\xb8\x6c\xcb\x0b\x2c\xb9\x6d\x27\x6b\xbe\x7a\xea\xd4\x86\xc6\x69\x5f\xe7\xa5\xd6\x43\x98\xe1\x85\x18\x13\x06\x5b\xe2\x6b\xfb\x3d\xca\xc0\xb0\xea\x3e\x97\xa3\xfc\xe0\x46\x10\x16\xe2\xff\xba\xc4\x28\xdd\x01\x7f\x23\xaf\x0d\xa8\x9c\x05\x75\x44\x24\xa7\x99\x1b\x2e\xe5\x9e\xad\xbf\x88\xd8\x57\x79\x84\xfc\x14\x2b\x48\x03\x07\x13\xb0\x28\xf1\x42\x38\xa4\xc4\x14\x0d\xb9\x31\x95\x4c\xc7\x59\xab\x2a\xfe\x0b\xd0\x1d\x14\x4a\x4c\x03\x16\x72\x3a\x64\x0d\xfc\x38\x95\x6c\xc1\x89\x38\xcb\x8c\x5c\x33\xb6\x29\xd1\x92\xfa\x57\x15\x78\x9d\x9c\x23\x80\xcd\x4e\xa5\x6d\x48\x69\xf3\x30\xeb\xea\x43\xf0\xa7\x7b\xc9\xdf\xee\xcf\x0e\x76\xca\x1c\x17\x71\x26\xea\xe7\x3d\x9e\x6b\x6f\xcf\x3d\xfe\xf2\xe3\xb9\xf6\xa4\xc1\xa4\x94\x19\xb2\xb3\xef\xfd\xc5\xfa\xfb\xc1\xc4\x3a\x0e\xad\x0e\x0f\x1e\x4b\x6e\x22\x2e\x29\x88\xbd\x8e\xad\x7f\x7b\xf1\x87\x3b\x9a\x66\x8c\x0a\x97\x8f\x5b\x5d\x4d\x7e\x4c\xfe\x7e\xaf\x99\x8b\x3a\x1d\x32\x6b\x2a\xdc\xde\x9e\x7b\x7c\xde\x9a\x25\x8e\x52\x87\x59\xbc\xe6\xe6\x0d\xbf\xb8\x77\xd6\xbd\x08\x90\xbd\xd0\x0f\x2e\x45\x08\x0a\x86\xb2\x99\xa4\x9d\xae\x3c\x07\xf8\x62\x50\x2b\x9d\xd3\x11\x00\x67\x61\x54\x55\xcd\xc6\x94\xb0\xc0\x0b\x01\x0d\x7d\x33\xdc\x43\x29\x43\x0d\x6d\xab\x99\x94\x46\x2c\x13\xcf\xa4\x53\x14\x28\x26\x24\x98\x41\x2b\xa4\x94\x15\xcc\x3a\xc9\x04\x36\xf3\xa9\x6b\xf7\x9d\xda\xbd\xbb\x76\x42\x53\x3c\x54\xec\x28\x82\x8c\x9d\x61\x47\x4f\x8d\x45\xf4\x4e\x9b\xd3\x68\x05\xc0\x5c\xe3\x08\xc7\xc4\x8c\x0e\xb3\x5c\xf6\x4f\xa9\xb5\xe3\xb3\x16\x9d\x39\xab\x2b\xfb\xc1\x84\xf0\x90\xf5\x93\x06\x3a\x8a\x8d\x8d\x0e\xd6\x80\xf1\x80\x8d\x26\x8e\xd5\xd9\x47\x94\x01\xcb\x32\x32\xfe\x50\x0c\x3a\x1a\xac\x52\x4b\xd1\x3e\xa8\x68\x1a\x94\x71\xa6\x1b\xc6\xb4\x5d\x31\xae\x81\x9b\x38\xd8\x9c\x2c\x02\x8e\x83\x35\xaf\xaf\xa8\x58\x63\x71\x94\x38\x8b\x31\xb0\xf7\x0c\x75\x44\xab\xcb\x59\x17\x3f\xcf\x2e\x89\x1c\x66\x01\xaa\x4a\x19\x8b\x27\x1d\x2d\x8d\xf9\xb1\x04\x18\x63\xc6\xf8\x7c\x0b\xe3\x28\x1b\xcc\xea\x21\x5d\x0d\x62\xcf\xb8\xab\x45\x87\xb8\x97\x29\x4e\x78\x10\x55\xa1\x11\x14\x43\xb6\x6f\xd0\xde\x5f\xd5\x8d\xbf\xd9\x1b\x94\x70\x88\x55\xeb\x03\x6d\x9c\x31\x21\x13\xb1\x25\xed\xea\xb8\x54\x02\x07\x2f\xc8\x1a\xe8\x9c\x95\x8e\x54\x25\x3c\x24\x5e\x56\x31\x68\x50\x45\x19\xe3\x4e\x94\x7a\xab\xaa\xbc\xa5\x89\x3f\xd4\x6a\x3e\xf8\x78\x32\xa6\xfa\xc4\x92\xe4\x9f\xc5\xb1\x87\xc9\x67\x0f\xca\xe1\xa0\x67\x40\x8b\x77\x82\x3e\x3f\x9c\x7c\xf2\x23\x18\xfd\xca\x63\x50\xff\x73\xbc\xf2\xfa\x75\x99\x57\x0f\x0c\x51\x23\x3c\x08\xbe\x87\xbf\x0b\xbe\x47\x58\xc3\x84\x78\xa2\x34\x96\x20\x73\x7d\x95\x55\x5e\x5f\x55\x25\xfc\xf9\x72\x8f\x63\xec\x3d\xe4\xfc\xbd\x63\x46\x32\x8c\x81\xb5\xe1\x6d\x1f\x9e\x81\xe2\x87\xc1\xf7\xe0\xae\xcf\xf3\xad\xeb\xde\x9f\xfa\xc3\x2b\xa3\x37\x7d\x09\x81\x2f\x6f\xba\xe9\x6f\x1a\x7e\x09\x7f\x91\x47\x14\x8d\x43\x12\x0a\xc0\xc2\x51\x46\x83\x48\x4a\xd9\xf4\x10\x55\x62\x1a\xba\x32\xff\x59\x90\xbf\x88\x38\xaf\xd9\x66\x34\x91\xc6\x2f\xed\xc5\x26\xbd\x28\x33\x1d\x5d\x3f\x27\xeb\xa2\x0c\x0e\xf1\x39\x8b\xcd\xc1\xfd\xc3\x55\x7a\x01\xf9\xad\x3a\xee\x14\x39\x2b\xb3\x42\xd0\x01\xb3\xd9\x70\xf7\x15\xdf\x33\x97\x95\x8a\x4c\xa7\xbe\x0f\x2f\xe1\x22\xf7\x2f\xe4\x41\x25\x97\xbc\x15\x7a\xde\x5a\x78\x27\x88\xc0\xe9\xa1\xff\x7b\xf3\x7f\x25\x1f\xd8\xfd\x66\xbd\x28\x91\xd2\x28\xc3\x84\xf9\x5c\x98\x9c\xf9\xf8\xc2\x22\x18\xc7\xcc\x25\xa1\xbe\xb7\xff\x17\x39\xe5\xa4\x6f\xff\xf1\x4b\xe6\xb2\x98\x83\xe9\x74\x5e\x30\x73\x15\xdd\xaf\x5c\x8f\xb7\x75\xff\xe6\x12\xb9\x93\xa4\x32\x41\x1d\x7f\x84\x43\x11\x6d\x2e\x9b\x90\x0a\xa6\xfb\xd4\xa2\x9f\x17\x64\x49\xe8\x91\x44\x14\x2e\x98\x7e\x5c\xee\x52\x42\x5b\x6d\xfb\x3e\x8f\x36\xbf\x4d\x3e\xbb\xf7\x38\x79\xe3\x4a\x01\x74\xd7\x1b\x2c\x56\x61\xc4\x7b\x1b\x96\x3c\x7f\xc3\xf8\xf1\x37\x3c\xbf\x64\xfe\x93\x6d\xd7\x17\xdb\x6c\xe5\x24\xeb\x51\x4a\x63\x81\x1d\xcb\x41\xbc\xed\x5e\xf0\xbd\x9d\xbf\xd0\x63\xbc\x77\x8e\x1a\xa1\x31\x3e\xf2\x1a\xf9\xec\xed\xcd\xb7\xee\x32\xb8\x75\x37\xe8\xb1\x61\xee\x92\xf1\x37\x3c\xff\xce\xf3\x37\x8c\x1f\x36\xe8\x86\x40\xac\x54\xf1\x40\x67\xb9\xcd\x56\xbc\x7d\xe1\xca\xcd\x6f\xdf\x45\x7a\xad\xf9\x3a\x7a\xec\xd7\xfa\xec\x57\x28\xd7\xbf\x19\x5b\xe9\x38\xdc\x5a\x0d\x97\xec\x26\xdb\x41\xba\xb5\x91\x35\x1d\x82\x2f\x7a\x04\x6e\xbd\x4c\x71\xc8\xa1\x45\x8f\xfc\xb1\x7f\x24\xf2\xf4\xd7\x74\x83\x2d\x17\x73\xfc\xcb\x5c\x0e\xed\x46\x88\x2b\x58\x9f\x51\x29\x99\x49\xa7\x98\x64\x4c\x63\x1b\x77\x32\x0e\x39\xc0\x14\x66\x75\xfd\x63\xc4\x6c\xc9\x74\x35\x1b\xab\x86\x1e\xda\xa7\x44\x5c\x9b\xbd\x99\xb1\xc0\x3b\x45\x87\x2c\x25\x82\xaa\x2c\x12\x93\xb1\x6a\xfc\xcd\x31\xe8\x73\xf9\xfd\x95\x27\xab\x2a\x1f\xab\x74\x79\x42\x95\x0d\xd6\x20\x80\x29\x9a\x9f\xad\x98\x00\xa2\xd6\x6c\xbc\xd4\xed\xaa\x39\x55\x5d\x71\xac\x5c\x76\x17\x97\xa5\x2d\x41\x50\x65\x94\xce\xac\xb7\x34\x55\x47\x5c\xae\xea\x53\xd5\xe5\x0f\x97\xbb\xdd\xa1\x8a\x3a\x4b\x18\xc0\xe4\xc1\xcf\xb9\x4d\x00\x61\xfb\xf8\x84\xdb\x5d\xf9\x58\x65\xc5\xf1\x0a\xb7\x3b\x5c\xd5\x60\x09\x43\xc8\xda\x54\x13\x71\xe5\x04\xa1\xcc\x5d\x1c\x60\x0d\x06\xe7\x06\xd8\xe3\x34\xb0\xac\xc1\x49\x6e\xba\x59\x32\xf0\xe0\x2f\xf6\x54\x0a\x42\xb9\x2b\x10\xe0\x0c\x06\x79\x63\x3d\x53\xc5\x54\x7b\xe3\xa1\x98\x8b\x37\xb0\x3e\x1a\x56\xe9\x09\x78\x31\x6f\x70\xee\x23\x9d\x4e\x23\xc3\x18\x9d\x90\xdd\xe7\x34\x32\xb2\x52\x08\xf4\x01\x67\x90\x6f\xe8\x1e\xbf\xc1\x69\x10\xb0\x3f\xe0\xa9\xa4\x18\x43\xae\x8b\x39\x96\x70\x39\x54\x59\xc0\x8f\xa0\xdb\x4f\xfa\x0c\xb4\xc3\xbd\x2e\x25\x46\xfb\xa8\x4c\x3a\x93\x2e\x83\xb8\xc4\x92\xa8\x2b\xce\x7a\x78\x26\xe2\x5e\xe1\x8e\x7c\x27\xec\x59\xe1\x09\xdf\x36\x7f\xeb\xa0\xec\xb4\x69\x9b\x56\x42\x1c\x7e\xe5\x8e\x70\x83\x47\xf8\xb3\xc0\xbb\x8d\xa9\xae\x9c\x3b\x12\x71\xb3\x2f\x77\xb5\xa8\x67\xf8\x4b\x51\x4d\xc3\xa6\x75\x37\x1f\xd9\xb8\xbe\x2c\x1a\xa1\xf3\x08\xb5\x4e\xa1\x7e\xbc\x23\x35\xa8\x15\x0d\x46\xc3\x10\x8a\x3a\x83\xa9\xe8\xd7\x2c\x85\x83\x29\xd1\x19\x4e\xa9\x67\xe6\xf2\xb0\xcb\xd7\xca\x9c\x61\x4a\x53\x09\x1d\xe4\x10\xa6\xf4\x5a\x05\x5c\xb7\x43\xdd\x87\xce\x9d\xe3\x51\xbe\xe4\x5c\x9f\x27\x93\xeb\x73\xe3\xec\xb9\x73\xdd\x87\x72\xb9\x5c\xae\x1f\x88\x9c\x02\xb9\x5c\x0e\xa3\x5c\xae\x1b\xe5\x72\xec\x25\x21\x04\xf5\xbf\x2a\x44\xd3\xf4\xdb\x05\x6e\x7a\x04\x71\xc9\xca\x97\xa8\x65\x18\x55\xeb\xa9\x55\xed\x47\xa3\x6a\xe5\x2c\x91\xac\xaa\x74\xe2\x24\x87\xc0\xa5\xd9\xce\xdd\xcf\x3d\x47\xfe\xf9\x1c\x26\x77\xcd\xda\xba\xfb\xb9\xe7\x76\x6f\x9d\x05\x4b\xf0\x73\x60\xa0\x4e\x72\x17\xc6\xb0\x64\x16\x46\x6a\x94\xe7\x76\x17\x49\x4f\x4e\x51\x83\xa6\x3c\x29\x15\x69\xb7\x4d\x79\x52\x72\x49\x4f\x4e\xb9\xa4\xad\x52\x5e\xfc\x88\xb6\x07\x36\x9d\x8c\x65\xa4\x84\xb6\x94\xec\x74\xd0\x0d\xce\x94\x1c\x2f\x43\x37\xc4\x7e\x6d\x2b\x1f\x87\xae\x9d\x36\xa9\xf9\xaf\x18\xff\xb5\x79\xd2\xb4\x6b\xaf\x7d\x6c\x2b\xfe\x6b\xcb\xc4\x69\xd7\x5e\x3b\x6d\x62\xcb\x5f\xf1\xd6\xc7\xe0\xda\xfe\x43\xa5\xfc\x63\x5b\x1b\x36\x5a\xcd\xd6\x8d\x0d\x5b\x1f\xbb\xf6\xda\x69\x82\x75\x63\xfd\xb5\x8f\x5d\x5b\xbf\xd1\x2a\x4c\xbb\x96\x39\xd7\x7f\xdc\x24\xf4\xce\x1d\x6d\xa8\x06\xb5\xa0\x76\x34\x0d\x2d\x40\x6b\x11\x42\x74\xd9\x97\xae\xf0\x52\xc5\x44\x26\x0d\xb2\x20\x4b\x0e\x0b\x45\x40\xe8\x9b\xc8\x25\xe2\x32\x35\x94\x15\xe9\xe2\x71\xc1\x6a\x56\x72\xc8\x7c\xff\xab\xb4\x56\x77\xa9\xfc\x8c\x15\x4c\x57\xa8\x56\x5d\xc3\x76\x49\x6a\xd0\x68\x0e\x3c\xd4\x31\xc0\xbd\xe2\x48\xa5\xc1\xe1\x36\x19\xcb\xed\xa1\xed\x93\xdc\xcc\x33\xd5\x7f\x1f\x22\x8a\xd9\xe9\x2b\x9f\x27\x5d\xe4\xd7\xa4\xeb\xf9\x95\x14\x4e\xf5\xa9\xef\x66\xc5\x94\x38\xa4\xcb\x50\x64\x32\xcc\xd4\xeb\x0d\x1e\xc3\x0c\xc3\x47\x46\x97\x71\x86\xc1\xa0\xf7\xea\x67\xea\x4b\xec\x66\x0a\x7c\xd2\x61\x3e\x61\xf7\xd9\xed\x3e\xfb\x9d\x33\xd5\xa8\x06\xc3\x0c\x83\xc7\xa0\x67\xee\x89\x3b\x0c\x95\x47\x56\xb8\x07\x18\xb8\xd2\x49\xdb\x43\x46\xf8\x41\xf5\xdf\x86\x88\x29\x31\xfb\xdd\xa7\xbe\xd3\xf3\x0e\x08\x00\xf7\xfc\xca\xe9\x59\x51\x1c\x02\x95\x85\x1b\xf5\x33\xf5\xde\x3f\xd3\x5f\x3d\xf5\x79\x8e\x3e\xfb\x50\xe1\x55\x76\xfb\xd0\x9e\xf7\xeb\x0d\x9e\x02\x2e\x81\x5a\xb6\x2c\x72\xa8\x5f\x1e\xa2\x1c\x13\xc4\x97\x2d\x01\x41\xba\x19\x84\x98\x28\x2b\x31\x99\x8b\x66\x78\x21\x23\x0a\x31\xa7\x43\xce\x70\xa2\x20\xc5\x33\x31\x31\x8a\xe7\x41\x31\x14\x5f\x49\xee\xe3\xbe\xbe\x06\xc4\x5e\x79\xc7\xa2\xbf\xb4\x5e\x77\xe0\xcf\x29\xf2\x29\xf9\x34\xf5\xe7\x03\x7b\x5a\xfe\xb2\xe8\x8e\x00\xb4\xed\xbb\x7a\xdd\x3f\xd7\x5d\xbd\x0f\xda\xf0\x3b\xef\xbc\x43\x1e\x63\x73\xdf\x30\xc1\xed\x1a\x7e\xa6\x8b\x99\x7e\x0e\x06\x17\xbd\xdd\xbe\xe5\x81\x07\xb6\xb4\xbf\x5d\x44\x9e\x3f\x37\x9d\xe9\x3a\xb3\xab\x94\x7c\x30\x34\x16\x1b\x0a\xe5\xa5\x88\x72\xd7\x15\xf8\xa1\x7b\xf6\x14\x8c\xa0\xac\x21\x9b\xd0\xf5\xe8\x7b\xe8\x71\x74\x5a\x95\x0e\x3d\xcc\xd5\x05\x2a\xf7\xcb\xae\xe1\x3f\x84\x47\x7b\x8c\x9a\xc2\xff\x29\xe6\x7f\x0e\x0f\xa6\x92\x1c\x4b\x81\x1d\x5a\xd8\x48\x09\x1b\x60\x6d\x97\x45\xb1\xf5\x12\x87\x82\xc6\x12\xa9\x51\x45\xf6\x39\x71\xf6\x1b\xbd\xf3\x2f\xfb\x14\x8c\x15\x2f\xbe\xf8\xbf\xb9\x0b\x72\x79\x42\x76\x90\x1d\x79\x62\x4b\x8c\xbb\xe9\x09\x30\x41\x0b\x14\x3d\x79\xd3\xb8\x84\xad\x2f\x8e\xe2\x25\x39\xaf\x72\xae\x8f\x47\xb4\x8f\x5d\x94\xac\xf9\x26\xdf\xfd\x8a\x77\xfb\x76\xaf\x92\xff\x5f\xdc\x02\x37\x98\x0c\x4b\x30\x2c\x34\x98\x6c\xc9\xf6\x51\xa3\x1b\xa2\xd1\x86\xd1\xa3\xda\x93\x64\x6a\x5f\x8c\x49\xdb\xbd\x8a\xe2\xdd\xde\xab\xf7\x2b\xe0\x22\x38\xa8\xf5\x4e\x7d\x01\x07\xac\x57\x2e\x89\xe9\x44\x90\x2a\xfa\x7a\x3c\xa8\x2a\x21\x2e\x43\x2f\xb4\x1b\xd7\xeb\xc2\x9d\x8a\x47\xf1\x10\xe4\x51\xce\x0b\x2e\xfc\xfb\x8b\x88\x45\xda\xa5\x47\x81\xa3\x2e\xa1\xfb\x2c\x39\x64\x37\x43\x89\xd9\x8e\x0f\xf5\xb8\xd8\xce\x3c\xf2\x28\x79\xda\x55\x60\xc4\x2c\x95\xf3\x59\xdc\xd9\x9d\x23\x85\x4e\x41\xf1\x30\x48\x86\xcc\xb9\x3e\xd2\x73\x6d\x9c\x4b\xd3\xec\x57\x47\x9c\x0e\x01\x64\x81\x67\x63\x10\x4e\x81\x62\x6f\x05\x19\xd2\x71\xea\x09\xe9\x38\xff\xcb\x68\x94\xac\x3c\x70\xe8\x41\xd2\x78\x8a\x1c\xf8\x21\x2c\xdb\x52\xf3\xe0\xa1\x03\x70\x8b\xb2\x6c\x64\x94\xac\xfa\x02\x6e\x55\x96\xb1\x8d\xca\x52\x85\xac\x3a\x70\xe8\xc1\x9a\x2d\x34\xca\x29\x78\x45\x8d\x73\x6b\x74\xe4\xf2\x28\x59\xf9\x05\xdc\x12\xa5\xba\x7f\xf7\xc5\x22\xfe\xbf\x29\x6f\x9f\x13\x35\x50\x56\xa2\xfe\x28\x08\xdf\xc0\x75\x19\xe0\xe2\xe9\x44\x9a\xc2\x7b\xa6\xe5\x78\x00\xb7\x70\x19\x5e\xb0\x6b\xbb\xef\x32\x0c\x55\xfb\x17\xf8\x12\x44\x4a\xbe\x10\x00\xb9\xd0\x07\x38\x6d\x99\xb4\xc4\x2c\xdd\xf6\xf8\xb6\x6d\x8f\x6f\x83\x7f\x6e\x9d\x31\x7d\xdb\xb6\xe9\x33\xb6\x7e\x9a\x1d\xdb\x75\x74\x62\x63\xc5\xcc\x61\x33\x13\xd3\x7d\x93\xf1\x10\x2f\xcf\x7a\xc2\xc2\x4a\xae\x55\x1e\xa2\x0c\x4b\x8c\x68\x1e\xf9\x93\x4d\x5d\x93\x96\x0f\x5a\xb7\x64\xcc\x14\x16\x74\x41\x01\xd8\xa9\x63\x97\xac\x1b\xb8\x74\x62\xd7\x26\x77\x79\x8c\xb5\x30\x73\x06\xb3\x9f\x0f\x9e\xe3\x8c\x95\x33\xbe\x89\x1b\x36\x4c\x9c\xb4\x7e\xfd\xa4\xc2\x99\x7c\x85\x0f\x4e\x1d\x31\x64\x56\x7e\xae\x1c\x92\x2c\x02\xb0\xe0\xe3\x19\xb7\x67\x26\xcb\x00\x30\xbc\xd1\x2a\x17\xbb\xee\x58\x4c\x7e\xf3\xe4\xea\x70\x49\x4d\x62\x35\xb4\x01\xd6\x01\x39\xb1\x26\x5e\x53\x12\x59\xf3\x24\x78\x17\xdf\x11\x4d\x7a\xb1\x81\xc1\x4f\x0d\x5f\xb4\x68\x78\x7e\xa4\xc5\x9b\x54\xcb\x6c\xc1\xc5\x1c\x7f\x6f\x41\x4f\x6b\x41\x6e\xb5\x66\x51\x3a\x31\x9b\x98\xb1\x05\x6d\x41\x67\x06\x6c\x10\x14\xc2\xa9\xa0\x4d\x64\x72\xb7\xe2\xe2\x5b\x6f\xcd\x77\x4d\x81\xb6\xb3\x8c\x8f\x8c\x21\xcf\x9e\x3d\x4b\xd6\x5c\xc9\x8e\x21\x63\xe0\x71\xf5\xc8\xeb\x08\xe3\xed\xfa\xef\xb3\x67\xd9\x63\xdd\x46\x32\xe6\xec\x59\xf6\x3a\x08\x6a\x75\x78\xfa\x45\xe0\x8e\x71\x79\x24\xa1\x0a\xd4\x8a\xc6\xa0\x85\xaa\xa4\xc2\x6a\x51\xd3\x41\x94\x36\x0b\xa6\x00\x9e\x31\xde\x02\x2c\xdd\xd7\xa8\xb4\x80\x1c\x97\xe9\xd6\x37\x50\x3b\xc0\x98\xc2\x50\x70\xce\x02\xcf\x03\xa8\xdf\x06\x14\x0a\xeb\x29\x4b\x76\x4e\x12\x78\x8e\x17\x32\xbc\x86\xb6\x4a\x4d\x6a\x02\x20\x33\x1c\x70\x45\xb1\xf4\xc5\xb0\x89\x05\x8e\x6d\xba\x13\x1a\x2d\xb5\x6e\x97\xf7\x00\x53\xbb\x91\xfc\xd1\x16\x16\x8b\x38\x9d\xbd\x3c\x6c\x7a\x7e\x58\xe5\x24\xd9\xcd\xd4\x0b\x0f\x27\xa2\x1e\xf3\xb1\x1a\x33\x67\x0b\x0f\x80\xf5\x67\xc6\xe8\x7c\xf9\x19\x5c\x63\x43\x1d\xb9\x4e\xe7\x2d\x83\xd1\x0d\xa5\x7a\x46\xc1\x07\x19\xbf\x85\xfc\x64\xb0\x0b\xe4\x6a\x73\x20\x00\x23\xaf\x8d\xeb\x7d\xd1\x01\x07\xf8\xb3\xdb\xc8\x47\xa6\x12\x9d\x7e\x4e\xb9\xc5\x59\x64\x36\x8c\x7c\xa2\x4d\x34\xea\x0d\xca\x67\x19\x4b\x6c\x1a\x0e\xb9\xe3\xed\x3f\x1c\x82\x47\xfb\xed\x21\x7d\x05\x39\x9d\xfe\xc0\x61\x76\x1a\xc0\x39\xda\x19\x77\x56\xd8\x20\x36\xc8\x2b\x48\x78\xfc\x22\x87\x6d\x1a\x9e\x12\xf6\x56\xcc\xb6\x18\xc2\xf6\xfc\x4b\xaf\xc5\x1c\x86\x76\x8b\x0e\xf3\x0e\xa9\xa6\x14\x16\x3e\x32\x88\x17\x6d\xf2\xc7\xf5\x74\x7f\xbf\xa6\xc7\xc9\x5d\xb2\xf7\xc1\x8b\xc2\xa8\x92\x72\xd6\x04\x6d\x41\x3a\xca\xb3\x51\x98\xc7\xd4\x25\x87\x3a\x86\xa5\x8b\x84\x41\x9b\x43\xb8\x04\xd2\x21\x98\x62\x11\xc9\x41\x2e\x97\xa7\x3b\x35\x38\x44\x10\xee\x77\x74\xa3\x9c\x92\x54\xf8\xdc\x05\x64\xe4\xce\x78\x94\xdc\xaa\x71\xe7\x73\xe3\x56\x01\x52\x6f\xba\x88\x72\x39\x06\xd1\xfb\x50\xaf\x3e\x9e\x1e\xdd\x59\xa6\x53\x03\x12\x66\xb3\x5d\x9d\xc1\x62\x85\xfd\xb0\x8b\xda\xaa\xb2\xd9\x1c\x62\x51\x39\x32\x09\x1f\x50\xbc\x85\x62\x54\x8f\xc6\x23\x14\x29\xb4\x5a\xa7\x23\x13\xaa\x86\x50\x61\x17\x4d\xa6\x05\xe2\x1a\xfc\x3c\xc5\xbf\x0a\x87\xcc\x8c\xe6\x9f\x8e\x94\xb0\xd4\x5f\x0c\xc5\x94\x48\x09\x5b\xc0\x05\xeb\xf3\x67\x1d\xa5\xfb\xaf\x9d\x70\xed\x12\xdc\xbe\x6d\xc7\xb6\x51\x8c\xfd\x4e\xc3\x98\x3f\xfc\xee\x0f\x63\x0c\x77\xa2\x8b\xc6\xa2\xbd\xbf\xbf\x6b\xf2\x23\xdb\x16\x34\x60\xdb\x01\xc3\x2e\xd8\x08\x39\xd8\xb8\xcb\x70\x80\x18\x8d\x4f\x90\x6d\xa4\x8e\x6c\x7b\xc2\x68\xb4\xdd\x69\x78\x0e\xb3\xd8\x83\xd9\xe7\x0c\x77\x9a\x6e\x73\x94\x54\x56\x96\x38\xb6\xc4\xe3\xf1\xf8\x01\xbb\xc9\x30\x7a\xda\xb4\xd1\x06\x93\xfd\x00\x58\x75\x4b\xaf\xa8\x6c\x69\xa9\x3c\x60\x2f\x32\xec\xda\xbf\x7f\x97\xa1\xc8\x7e\x00\x2c\xfa\xfb\x1e\x78\xe0\x3e\xbd\x1a\xf1\xd9\x37\xdf\x7c\x56\x8d\x88\x90\x49\xdb\x37\x43\xd7\x31\xfb\x6b\xa5\x5a\xd1\x28\x34\x11\x5d\x81\x96\xa3\x6b\x10\x62\x2f\xe3\x84\x43\xff\xcb\x33\xd8\x0a\x28\x22\x52\x3c\xdd\xdf\xaf\x3f\xd6\x9d\xb5\x9f\x0d\x76\xff\x31\x2e\xe4\x46\x2d\x1b\x35\x6a\x19\x9c\xa1\x27\xa2\x9d\x98\x51\xfd\xaf\xbe\xd1\x93\x19\xd5\xbe\xa4\xbd\x7d\x49\x3b\xe9\xb9\xbf\x67\x3b\x1e\x87\x3c\x0a\xf5\x3a\xd3\x9e\xbc\x40\x35\xe7\x5c\x2e\xd9\x9e\x5a\xa6\xdd\xad\xfe\xc1\x19\x7a\x22\x67\xfa\x5f\x7d\xa3\x67\x3e\x07\x7d\xda\x7b\x7c\x51\x0b\xea\xa4\xb0\xd4\xda\x7c\x83\x1c\xa6\x7e\x0c\xba\x80\xd4\x78\xbc\xfa\x8b\x30\xd2\x5f\x44\xdc\x9f\x79\x84\x62\x68\x28\x5d\x07\xc1\xc1\x70\x88\xb7\x00\x23\x98\x81\x6e\x82\x6a\x61\x32\xe9\x46\xa0\xf4\x37\x54\x80\x48\xb2\x14\xd3\x28\x9d\x1c\xe1\x58\x48\xe0\x19\x5a\x44\x99\x1e\x8b\xf4\x00\x70\x7f\xb6\x4b\x53\x49\xa8\xd2\xad\x70\x6c\x06\x73\x31\x77\x97\xd3\xc5\xe8\xc3\xf6\x88\x9e\x53\x76\xee\x5e\xfc\xe8\xaa\x45\x29\x97\x11\x18\x96\x1d\x7b\x77\xf5\xb8\x4f\x56\xef\x9b\x31\x63\x81\x1d\x4f\x04\x23\x39\x2b\xf9\x99\xdf\x73\x55\x7e\x3c\x25\xb4\x6d\xc0\xf2\xd5\xcc\xe6\x49\x1b\xc9\x90\xa0\x47\x24\x47\x2c\x9e\x60\xc0\x59\x77\x6e\xd5\xaf\xea\xa2\x58\x8e\x2d\x9d\x7b\x67\x5b\x2b\xcf\x00\xd3\xf8\xc4\xf2\xed\x9f\x4f\x28\xc5\x00\x1d\xba\xfc\x3f\x0d\x41\x89\x7b\xd1\xaf\x78\xc4\xb2\xef\xab\x32\x3c\x56\xe8\x6b\x0d\xc8\x8e\xdc\xa8\x54\x9d\x55\xc9\x48\x0c\x62\x46\x49\x27\x80\x17\x30\x93\xce\xd8\x45\xbb\xea\xa3\x07\x2b\x83\x81\x06\xa8\x39\xb0\xc3\xa9\xa0\x08\x86\x0e\x32\x68\xdb\x5f\x8a\xec\x0e\xe6\xfb\xb5\xed\x63\x4f\x96\xb2\x3f\xff\xf4\x7f\xa0\x22\x4c\x9a\xcb\x08\x62\x97\x2c\x1c\x4c\x3e\x72\x8f\x67\x45\x2b\x2c\x76\x86\xb9\xb5\x4c\x87\x87\xdc\x4e\x16\xc1\x29\x48\x5a\xc3\xe4\xe0\xab\x2f\x43\x1a\x7c\x1f\x7f\x46\x8e\xc3\x77\xc8\xe9\xbc\x48\x56\xe3\xbb\x99\x58\xbe\x93\x4c\x23\x5b\xf0\x00\x6c\x84\x2a\xf0\x5a\xdd\x1e\x07\x59\xac\xe9\x46\xf4\xda\xbe\x11\x0b\x72\x21\x1f\x6a\xd1\x78\xe8\x21\x9c\x6e\x85\x16\xc8\xc8\x1c\xa3\x84\x83\x02\x1b\xa5\xb4\x40\x62\x02\x98\x84\x18\xe6\xe8\x4e\x11\x5e\x2e\xac\xa7\xd6\x80\x20\x25\xa4\x74\x26\x19\xd3\x16\xf1\xd3\xc5\x10\x0d\x87\x04\x26\x91\x49\x48\x72\xe2\xf2\x5a\x2c\x3c\x7d\x83\x39\xc9\xb0\x45\x4c\xd1\x85\x1d\x0d\xc6\x2c\xf9\x3b\x86\x0c\x58\xbe\x67\xf3\xac\x1f\xbe\xe7\x51\xe0\xa2\x47\x96\x1c\xc1\x77\x0d\x1d\x77\xcd\xbd\x00\xfb\x07\x28\x4d\xb1\x29\x6d\x92\x3c\x72\xe5\x8e\xfb\xf0\x8d\xb5\x95\xb5\xd5\x6d\x69\x0b\x74\xe6\x06\x4a\xff\x3c\x11\x7e\x8f\xb3\xdc\x93\x6b\x4f\x7e\x45\xab\x93\x0e\x25\xdb\x71\x28\x7a\xb3\xde\x50\x62\xc8\x6c\x84\x58\xda\x34\x76\x16\x19\x39\xbd\x6d\x83\x9f\x60\xbc\x3d\xbf\x15\xef\xb0\x7a\xd7\xcf\x59\x34\x5c\x8e\x38\x03\x25\x41\xe3\x2d\x21\xd8\xb8\x60\xd9\x10\x77\xc8\x29\x05\xc1\xad\x3b\x98\xce\x3f\xd9\x21\x8d\x64\x5e\xee\xa2\x0f\xe3\x68\xdd\x74\xf5\x96\x8d\x0d\xb9\x51\x05\x4a\xa0\x2c\x1a\x86\xa6\xa1\x2b\xd0\x62\xb4\x1a\x6d\x46\xf7\xa2\x67\xd0\xab\xe8\xb7\xe8\x3c\x18\xc1\x0d\x55\xd0\x04\x23\x61\x1a\x5c\x03\xfb\x10\x02\xa5\x87\x9c\x23\x11\xcf\x28\xd8\x9e\xe1\xb1\x5d\x4e\xdb\x71\x4c\xb2\x63\x81\xae\xa9\xa7\xe8\xba\x1a\x24\x52\x61\x67\xc2\xd9\x88\x53\x61\x21\x16\x76\x26\x52\x72\x22\xc3\x38\x2b\x20\xd5\x08\xce\x44\x2c\x9e\xc8\xa4\x93\x35\x10\xaa\x00\x67\x22\x95\x88\x24\x7b\x95\xfa\x91\xb8\x1c\x66\x35\x59\xcc\x87\x43\xe9\x82\x2b\x24\x87\x62\x21\x85\x6a\x53\x92\x99\x74\x6d\x3c\x45\x4d\x5b\x6b\x65\xa7\xe4\x14\x7c\x10\x16\xf8\x30\x1f\x4d\xa4\x92\x4a\x2c\x24\x68\xec\xc7\xce\x44\x2a\x99\x88\xfb\x81\x9e\x9c\x72\xa2\x19\xc2\xce\x9e\x69\x76\x2b\x24\x6b\x40\x51\x03\xe4\x8c\xb6\xf2\x4b\xd7\xd1\xc3\xa1\x98\x9a\xfe\x34\x5d\xe4\x6d\x56\x93\x9f\x0a\x3b\xd5\x2c\x38\x12\xf1\x4c\xcf\x2e\x2f\x35\x2c\xa6\xbe\x29\xd1\xf7\x16\x39\xa3\x48\x85\xc0\x98\xb6\xa5\x88\x3e\xf7\xf2\x97\x5e\x72\x43\x21\xb0\x27\x4c\x08\x85\x79\x81\xa7\x7a\x39\x07\x5d\x9c\xcc\xa8\x13\xe3\x4c\x3a\x95\x8c\x29\x31\xb5\x9c\x94\xaf\xe1\xfb\xcc\xcd\xdd\xbd\xf8\xf9\xbd\xe3\xc7\xef\x3d\xbd\xe4\xee\xdc\xce\x39\x73\x1f\xdc\x3a\x6b\xe6\xb6\x6d\x33\x67\xcd\xde\x31\x77\xce\xce\xdc\xdd\x4b\x4e\xab\x61\xcf\x2f\xbe\x1b\x2f\x14\x6c\x02\xe3\x67\x39\x9e\xe7\x18\x9e\xe5\x74\x98\x61\x30\xc3\x52\x1a\x58\xc0\xc0\x33\xd0\x25\x49\xa2\x5d\x92\xec\x22\x1c\x6e\xe2\xda\x60\x8f\x14\x91\x25\xd1\x7e\x41\x8e\xc8\x72\x64\x0f\xc6\x40\x4d\x60\x31\xc6\x0c\xb0\x98\xde\x84\xe1\xc2\xe9\x80\xdf\x5d\x62\x31\x17\xbb\x2c\x81\x40\x30\xe0\x0f\x06\x8e\xf8\xfd\x36\x8f\x5f\x51\xfc\x3e\xcb\xe3\x35\x66\xd9\x2d\x3b\x8a\xa4\xa0\x27\x50\x63\x72\x15\xbb\x1d\x26\x77\xd0\x1f\xdc\xa1\x33\x99\xc4\x01\x03\x02\x3e\x5f\x8d\x73\xa1\x5f\x89\x05\x82\x92\xd9\xee\x0c\x09\x0b\x23\x3b\xe5\xa2\x40\xc0\x6f\xd0\xe9\xf5\xf6\x58\xd0\x2f\x9a\xed\x36\xbb\x2c\xdb\x45\xab\xd9\xe1\x0b\xbe\x1d\x08\x58\xbc\xfe\x58\xcc\xef\x33\xef\x96\x8b\xfc\x7e\x35\x9a\x6e\x9b\xdf\x6f\xa9\x8b\xc5\x7c\x7e\xf3\x18\xac\x26\x4d\x1d\x91\x62\x96\x61\xb1\x7a\x45\x53\xa8\xa6\x7a\x71\xff\x06\xc4\x3e\x32\x79\xfc\xde\xd3\x8b\xd5\x62\x99\xbc\x1c\x9a\xa1\x69\xe2\x15\xe4\xe7\xe4\xbd\x2b\xae\x80\x4a\xa8\xba\x66\x39\xf9\x11\xf9\xd1\x32\x35\xc6\x92\xc5\xa7\xf7\x8e\xef\x3e\xcb\x30\x36\x87\xc9\xe4\xb0\x98\x4c\xa4\x1e\x33\x06\x0e\xd4\x52\x30\x71\x95\x8a\xcb\x6d\x17\x5d\x53\x4b\x8a\x35\x87\x3b\xe2\x56\x4f\x7e\x60\x69\x2a\xb0\x56\x3e\xac\x9a\x08\x4c\x13\x31\xd9\xe5\x07\x97\xcb\x61\xdd\x33\x2a\x12\x19\xa5\x1e\x43\x06\x5b\x1d\xa5\x2d\xa5\x0e\x57\x88\xc7\xac\xc1\x62\x74\x99\x5d\x8e\xa0\xea\xb4\x99\x65\x9b\xcb\xec\x16\xa4\x66\x6f\x59\x99\xb7\x39\x7e\x73\x69\x71\x49\x4c\x94\x2c\xc1\xa2\x92\x98\xc3\xba\xa7\x3d\xcc\xfa\xd8\xd2\x96\x52\xab\xcb\x04\x2e\xc5\x55\xe4\xb2\xee\xeb\x79\xd4\xe6\x9e\xe0\x7d\x43\x36\x0f\x73\x94\x35\x95\x39\x18\xf5\x8b\xa9\x25\x82\x69\x2a\xd4\x7f\xea\x37\xc7\xd4\x96\x1a\xd8\xdf\xf6\x17\x05\x1a\x3f\x3d\x95\x05\x06\x64\xa3\x2b\x7f\x83\xd0\x54\x34\x1f\x2d\x43\xab\xd1\xb5\xe8\x06\x74\x0f\x65\x39\xe4\x2b\x28\xfe\xab\x14\x75\x50\x07\x97\x54\x2a\xc0\xd6\x43\x0e\xcf\x15\x74\xc8\xe9\xbe\x26\x45\x89\x42\x35\x8c\x6b\xda\xaa\xa8\x2e\xb9\x60\xe8\x93\xea\x69\x14\x60\x33\x43\x11\xe6\x82\x7d\xe3\x85\x28\x65\xa2\x17\x33\x6a\xeb\x2b\x1c\x90\xa0\x96\x57\xea\xeb\x52\x5f\xd3\x1a\x42\x7d\xc4\xdf\x64\xb3\x35\xfb\x22\xfc\x5f\xb2\xa2\xa3\xf5\xfc\xc4\x05\x63\xe7\xce\x1d\x59\xd5\x14\x18\x38\x10\xb2\x65\x19\xbf\xd3\xeb\xf4\xbb\x42\x65\xf5\x95\x4d\x91\xea\xa8\x4e\xf4\x49\x03\xe4\xf2\xca\x61\x89\x2c\x48\xd1\xb2\xda\xd6\xd6\xea\x0a\xa5\xb4\x74\xe4\xe2\x45\x23\xcb\xd9\x7f\x0d\x7c\x80\xfc\x98\x3c\x4c\x1c\x84\xf0\x41\x8f\xd2\xfd\x83\x65\x07\x96\x2d\x3b\x00\xf8\x96\x61\x33\xa6\x0f\xbb\xf9\x9d\x67\x36\xac\x5d\xbb\xe1\x19\xd8\x33\x6e\x69\x7b\x4b\xdd\xbc\x81\x7a\x08\x8e\xce\x7c\xa5\xcb\x8c\x1e\x9d\x11\xbe\xca\x8c\xc6\xff\x4a\x04\x3d\x1f\x79\x8b\x4d\xc9\x85\x6b\x46\xce\x26\x4f\x28\x89\xe9\x30\xfa\xf7\xa5\x95\x0e\x83\xdd\x6c\x75\x7a\x2b\xa3\x99\xd2\x70\x99\xd5\xc4\x17\x49\x0e\x6f\x65\x69\xb6\xb9\x6c\x74\x74\x60\x7c\xc0\x60\x65\xb4\x63\xe1\xfe\x85\xf9\xa7\xb1\xa5\x74\xda\xfe\xed\x37\x0e\x50\xf0\x8f\xd5\x97\x2e\xd3\xc1\x94\x73\xe7\xc8\x31\x7d\xdd\x8c\xba\x91\xf5\xe4\x89\x1b\xad\x63\x6a\x92\xe4\x89\xdd\x38\xd2\x55\x54\x37\x66\x4c\x1d\xfb\xf7\xba\x31\x63\xd4\xe1\xb8\xbd\xf7\xdb\x61\x64\x44\x66\xe4\x44\x3e\x14\x46\x0a\x6a\x40\x63\xd1\x4c\xf4\x36\xfa\x35\x3a\x0f\x1c\xe8\x21\x02\xad\x30\x1f\x21\x31\x11\x83\x8c\x2a\x8c\x9d\x61\x67\x54\x4e\xc9\x49\x55\xfc\xc6\xa3\xda\x09\xb4\x13\x97\x88\x45\x6d\xe1\x94\x10\x8e\x39\xc3\xb1\xb0\x10\x16\x13\xa2\x2d\x21\x67\xc0\x61\x66\x43\x4a\xd8\x19\x8e\x09\x41\x5b\x50\xce\x24\xe2\x51\x67\xd8\x96\x70\x6a\x0f\xeb\xdd\xc4\x65\x4b\x64\x12\x32\x95\xf5\xce\x60\x2a\x13\xf7\x43\x30\x15\xc0\xe9\x1e\x4f\x5b\xd8\x19\x53\xff\xa8\x28\x54\xfb\x5e\x7a\x25\xf4\xce\x71\x69\x40\x48\x48\x05\x9d\x4a\x05\xa8\x87\x40\xf7\x20\xc9\x89\x54\x22\x9e\x51\x3b\x0a\x0d\x27\x3d\xa3\x26\xda\xc1\x0b\x01\xf0\x43\x98\x56\x0d\x35\x29\x71\xaa\xa2\xa3\x7e\xc9\x74\x35\x43\x3d\xe5\xb8\x04\xfd\x93\x69\x0b\xdb\x40\xab\xc0\xa9\xa4\xa2\xed\xaf\x6f\x04\x67\x38\xe4\x74\x48\xe9\x00\x64\x9c\x7c\x4f\x18\x4f\xf5\x11\x85\xb0\x00\x30\xb6\x9e\xe2\x08\xa5\x92\x8d\xe0\x0c\x29\x66\x96\x62\x5f\x64\x68\xe9\xa4\x36\x4c\xaf\xc2\x03\x47\xb6\x3d\x78\xf3\xcd\xd0\x7c\xc5\xf3\xa5\x93\x26\x96\x41\xb0\x7c\xc2\xf8\x0a\xf2\x85\xfa\x0b\x67\xa6\x57\x76\x4b\x83\xe6\xd4\xcf\xd9\xe5\xde\xe3\x6e\xbb\xba\xe3\xaa\x65\x93\x47\xe3\xbb\x8c\x36\x9f\x2b\xe6\x2a\xd3\x6f\x1d\x37\xf1\x22\x02\x76\xdc\x84\x9f\x5e\x49\x3e\x3e\x7b\xf6\xae\xdb\x6f\xe7\xde\xd3\xea\xd6\x4a\x77\xc6\xfd\xa1\xb8\xda\x81\xfd\x06\x03\xc8\x72\xb6\x6c\xb2\xde\x5d\xe7\xfe\x4d\xe8\xa9\x27\xdd\xa7\xe4\xf3\x43\x4b\x8f\xbb\x6a\xf3\x37\x56\x54\xfc\x44\x7a\x78\x8c\x56\x0d\x37\x26\x02\x27\x33\x32\xf9\x71\x71\xdd\xbb\xf2\x90\x2f\xd2\x71\xf2\x20\x4c\xcd\x24\x7f\xee\x6c\x2c\x3e\xa1\xd3\xb1\xd8\x56\x5f\x7c\xb4\x29\x5f\xe5\x92\xdc\xf6\x81\xae\xd0\xd0\x81\xf7\x0c\x68\x20\xff\xe3\x76\x7a\x6c\x03\x01\xb8\x22\xd9\xde\x96\xbd\xbb\xb6\x01\xdb\x7e\xf1\x8b\x3b\x6f\xbf\x9d\xfc\x71\x10\xfe\xd7\xa2\xad\x5b\x43\xa1\xda\x78\x28\x59\xba\x63\x43\x24\x5c\x5b\x1b\xfe\xb3\x2b\x7b\xed\xb5\x41\x77\xb4\x22\xea\x4e\x95\x6e\x5f\x1f\x69\x18\x7b\xfb\xac\xcd\xbb\x3c\xd7\xb9\x47\x6d\xdf\xdd\x2a\x94\x5b\x8a\x8b\x6c\xbc\x37\xe2\x9f\x35\xef\xca\x2b\xd6\x30\x53\x56\xe4\xaf\x1b\x3b\xb6\x36\x93\x1e\x73\xd5\xd9\xa6\xe0\xd0\x52\x7f\x33\x7c\xe9\x6f\x52\x56\xd4\x90\xbf\xbe\xf7\xde\x7b\xef\x35\x35\x81\x85\x5c\x04\x78\xe6\x99\xfc\x7b\x8e\x80\xc3\x24\x60\x98\x39\x63\x06\x58\xa6\x4f\xef\xae\x03\x4b\x7d\x6d\x26\x9d\x7f\xf7\xb7\x99\xb1\x63\x33\xf8\x48\x73\x73\x75\x75\x4d\xcd\x15\x60\x9e\x22\x17\x15\x01\x6e\x6e\x6e\x68\x80\xcd\x95\x95\x95\x95\x92\x24\x49\xf3\xe6\x55\x56\x3e\x01\x7b\xd4\x98\xf9\x19\x52\xe1\x5f\x43\x03\xb9\xae\xb1\x71\xba\x69\xd1\x15\xac\x6e\xaa\xcb\xd5\x25\x97\xea\xf5\x21\x7f\xba\x2a\xe8\xbc\x02\x2c\x01\x38\xea\x2a\xd5\xeb\x83\x81\x94\x3e\x6c\x91\x0c\xc2\x7c\xb0\x80\x3f\x7f\x75\x1d\x58\xea\x6a\x33\x69\xfc\x30\xf9\x2b\x58\xf2\x57\x4f\x69\x70\x5b\x0d\x82\x12\x89\x95\xd7\xbb\xad\x7a\xe0\xa3\xe6\x85\xe1\x06\xb7\xa9\x08\x38\x63\x34\xa0\x7a\x3a\x58\x1e\x0f\x22\x5f\x9e\x39\xd3\xd4\xb4\xfb\x86\x46\x0c\x8c\xc1\xe6\x17\x95\xd2\xf7\x2f\x22\x40\xa7\x4f\xab\xed\xd3\xd8\xdb\x3e\x8d\x48\x46\x61\xd4\x80\x26\xa2\xab\xd0\x6e\xf4\x00\x3a\x81\x4e\xa1\xd7\x0b\x6c\x54\x85\x75\xa2\xa8\x83\x0f\x0b\xea\x8c\x20\x1e\x80\xfe\xeb\x47\x51\x0a\x3a\x22\x30\xbc\xd4\x08\xf1\x56\x68\xc1\x54\x4b\xc6\x89\x69\xea\xdd\x6f\xf7\x36\xef\x74\x34\x82\x3a\x1d\xab\x80\x90\x05\x28\x91\x3f\x35\x0e\x90\xb5\x80\x0c\xfc\x7f\x3f\xc9\xa1\xdd\x21\xa6\x92\x34\xbe\x40\xe1\x4e\x32\x60\x86\x42\x02\xa5\xcb\xe5\x30\xfe\x3c\x11\xf5\x87\xe3\x51\x5f\x94\xb1\x55\x56\x96\xd8\xb0\xd1\x2e\x79\x5c\x30\x37\x11\xf1\x47\x54\xdf\x0b\x47\x47\xb7\x1c\x12\xf1\x40\xd0\xf1\xed\x0e\x6c\x87\x22\xbb\x55\x62\xa6\xcc\x87\x54\x99\xea\x63\x66\xbc\x43\x86\x2f\x1c\xda\xe0\x6b\xb2\xb3\xa6\xa1\x22\xbc\xac\xe3\x46\x1b\x85\x65\x95\x9c\x6d\x14\xa7\x8b\x55\xc1\x04\xd3\x68\xa3\x80\x2e\xc2\xd6\xd1\x2d\x0f\x38\xe8\x43\x26\x14\xb1\x5f\x7f\x88\x67\xa8\xfa\x10\x7f\x93\x4d\x7d\xc8\xc7\xa6\x91\x46\x1a\x75\x90\x88\xcf\x8f\xe0\xca\x63\x41\x1b\x36\x8a\xa5\x11\x61\xcd\x25\xe3\xea\xf5\xd1\xda\x12\x5f\x34\x11\xdc\x58\x1e\x80\xe5\x46\xd6\xf9\x70\x24\x4e\xaf\x6f\x6e\x4c\x89\x64\x09\x6f\x10\xaf\xd2\x19\x18\x3c\xef\xd7\xc0\xf1\x86\x60\xe9\x8a\x11\x8d\x6d\x2e\x47\x91\xde\x0a\x4e\x83\xde\x70\xef\x01\xab\x9e\xc3\x6b\x76\xb1\xab\x74\x26\x03\xac\xaa\x2b\xdc\x62\xba\xfa\xeb\xb7\x80\x95\xb5\xc2\x71\x30\x1b\x49\x07\xe6\xf4\x22\x88\x61\x09\x96\x1b\x65\xf8\xd5\x25\x5d\x31\x32\xf4\xeb\x8b\x2d\x28\x8e\x86\xa3\xa9\x68\x26\x5a\x81\xae\x46\xfb\xd0\x41\xad\x1f\x0e\x87\x62\xea\xe8\x97\x0b\xa7\x69\x2f\x4c\xfb\xdd\x42\xb7\x2b\x14\x10\xb9\xd5\xb1\xac\x42\xbb\xdd\x4c\x1a\x32\xe1\x94\x85\x49\x14\xb6\x51\x6a\x06\x5d\x1c\xed\x80\x85\x58\xd8\x96\xb0\xa5\x13\x71\x91\xf6\xe0\x74\x97\x6b\xac\x80\x26\x99\xe9\x9b\xc0\xd3\x00\xbe\x70\x3f\x1d\xfe\x2a\xb1\xc4\xd7\x30\x39\xf9\x66\xa7\x18\x94\xed\x7e\x5f\x3d\x3c\x75\x15\x1f\x4f\x9c\xff\xc3\xa0\x21\x91\x12\xa5\x61\x90\x7d\xf0\x84\xd1\xd5\x03\x06\x0e\x8e\x15\x0f\xf0\x4f\x28\xb6\x0f\xef\x18\x3f\x20\x01\x31\xb1\x63\xbb\xbd\xda\xd6\x52\xa9\x8c\x28\xa9\x29\x29\x2a\x87\xeb\x2d\xa6\x92\x1a\x83\x61\xe7\x01\x4f\x9d\xb5\xe6\xc0\x01\x7c\x55\x55\xe9\xb0\x6c\x4a\xb7\xeb\x40\xa4\x64\x62\xa2\x99\x54\x56\x0f\xaa\xae\x1e\xc4\x3c\x36\x20\x3e\xa7\x63\x65\x6b\x66\xd9\xc2\x46\x6b\xfd\xb0\x0a\x87\xcc\x7d\x85\x2f\x9d\x25\x6d\x1a\x1a\x0d\xeb\xcf\x05\xa6\xcc\xff\xbc\x71\xa0\xdb\x24\x99\x3d\xc1\x55\x25\x4a\xac\xad\x61\xa0\xcb\x2c\x5b\x8b\xdd\xf6\xd5\x65\xd1\x32\x08\xaf\xdc\xe3\x5c\xa3\x5b\xfc\xcb\x49\x91\x80\x71\xbd\x10\x7f\xc5\xbd\x8f\x29\x09\xd4\x91\x32\x88\x17\x93\x47\xe1\xbf\x3e\xd9\x5c\x9f\xac\xab\xc9\x5f\xe3\xbe\xd3\x58\x37\x10\x7e\xac\xbe\xb9\x86\xfc\xcf\xea\xd6\xec\xae\x35\xb9\xa6\x4c\xe9\xe2\x62\x51\xac\x31\xe3\x93\x97\x7c\x38\x06\x99\x2f\x22\xe1\x4b\x1e\xd1\x76\xde\x8a\x10\xd8\x65\xb5\x80\x1c\x7c\x48\x89\x71\xf1\x24\x6d\xcb\x6a\x2f\x03\x12\x2f\x68\x68\x6c\xe9\x56\x50\x52\x2d\x6c\x2a\x69\xcf\xf4\x2c\x3e\x09\x01\x90\x21\x2d\xc9\xbc\xd4\xfc\xc7\xf6\x24\xc9\x1e\x78\xef\x0e\x00\x64\xb5\x36\x4e\x2e\x59\xcc\x26\x74\x60\xf8\xea\x31\x83\x57\x37\x49\x07\x86\x67\xc5\xf8\x84\x69\xcd\xb1\x2f\x5e\xd0\xd5\x8d\xab\xd3\x6d\x79\x21\x05\xdf\x33\x78\x75\xf8\x38\xb9\xf7\xb5\x64\xfb\xb2\x03\x77\x2c\x7b\xb4\x64\x72\xa3\xd5\x3a\x62\x31\x9f\x35\x78\xf5\xe7\x8f\xe9\xb0\xa1\xc3\xe0\xd5\x7d\xb7\x24\x54\x3e\xeb\xb6\x63\x5f\xee\xbb\x0b\x38\x9f\xe8\x28\xad\xab\x2b\x75\x88\xf6\xed\xb3\x61\xb9\x0e\x1b\xb4\xfd\x6c\x7d\xf9\x90\x90\x82\xc6\x20\xc4\xf6\x25\x3e\xa1\x87\x02\x35\xa3\x15\x7a\x73\x97\x09\x2a\x4c\xc6\x0e\xf2\xff\x47\xc6\x58\x2d\x2b\x23\xf2\xff\x62\xae\x2c\xff\xe1\xee\xd9\x77\xcf\x18\xc0\x76\xf6\x64\xf4\x0e\xfc\x8f\x23\xcd\x2b\x9b\x61\xf0\xa4\xff\x98\xd1\xc7\x0a\x99\x83\xff\xc1\x5f\x4d\x5b\xd7\x3a\x7f\x45\x82\xe4\x48\x56\xcb\xf8\xf6\xe7\xc0\x3a\x8f\xdc\xcb\x1e\xed\xf8\xff\xcd\x78\x2f\xc6\x31\x97\xeb\xd5\x73\x65\xd0\x4c\x8d\xbb\x90\x8a\x50\x9b\x86\xf6\xf4\x9f\xae\x21\x18\x53\x62\x41\x5e\xe0\x7a\x78\x05\xb5\x06\x12\xee\xe1\x80\xc8\x68\xeb\x38\xc5\xa0\xca\x4b\xf4\xcd\x30\x4d\xfd\xdd\xf9\x73\xd0\x39\x40\x30\x90\x1f\x19\x04\x66\xa5\xdd\xdc\xa1\x11\x38\x50\x85\x23\xa4\xda\x2c\x63\x4a\x21\x5b\x3a\xc6\xd2\x06\x29\xb3\xfd\x10\xa6\xaa\x9c\x3c\xbd\xf5\x5b\xdc\xcc\x9f\xd6\xe9\x31\xd6\xdf\x91\x35\xdb\xbb\xdb\x27\x6e\x5a\x37\x91\x79\x86\xbe\xe6\xa1\x68\x32\x19\x7d\xc8\xde\x0f\xcb\xb8\x92\x5a\x3a\x22\xd0\x20\x87\x90\x06\xe9\xc2\xf8\xd5\x91\x53\xa8\xb9\xbf\xb5\x54\x8f\x5a\x0d\x7f\x9b\x0d\x0a\xbb\x75\xc4\xda\x4d\xf5\x6f\x91\x3f\x82\xf5\x4c\x68\xe2\xe2\x09\x75\xd6\xf5\xd6\x9d\xc3\x6f\x3c\xf9\xf4\xcd\x43\x6e\xd4\xf3\x1b\x78\x43\xf7\x7f\xb2\x51\x81\xb7\xaf\x8c\x8f\xa9\x90\x40\xfa\xe9\x19\xb0\xea\xbd\x65\xc3\xab\xae\xb4\x5a\xdb\x2a\x6a\x9f\xde\x7f\xe7\x2b\x03\xca\xdb\x04\xbd\x9e\xa9\xf8\x4f\x56\x2c\xfd\xf5\xf0\x66\x34\x1f\x21\x9a\x07\x33\xd6\xe8\x44\x81\x73\x98\xb1\x10\xd2\x24\x5b\x61\xe9\xd7\x4e\xd1\x26\x5b\x35\x26\x4e\x59\x12\x18\x9a\xe1\x16\x36\x65\x45\xc1\x10\xcd\xab\x2a\x23\xa5\x62\x8d\xb2\x0d\xfa\xc1\x95\x23\xe6\xcd\xe5\x73\x5a\x37\xcf\x6f\x5e\x3e\xaf\xe3\xd0\x64\x9c\x1c\x79\xcd\x8d\xa3\x78\x51\x98\x5b\xe3\xe3\x92\x0f\xcc\xf9\xee\xc9\x5d\xbf\xde\x3d\x75\xaf\x82\x8d\xa0\xe7\xd6\x73\x3a\x0e\x6f\xe4\xdc\x25\xbe\x86\x69\x83\x06\x90\xef\x93\x8f\x7a\x2c\xe1\x3f\x3b\x69\xf4\xe8\xca\x74\x80\x0d\x8b\xba\x76\x53\x1e\x3f\xca\xcf\x07\xd3\xe0\x28\x3e\xbf\x62\x73\xf3\x8a\x23\xf3\x56\x6d\xde\xfd\xaa\x6d\xe5\xf1\xf9\x09\x0c\xa9\x60\x7c\xd0\xb4\x17\x4f\xdc\x07\x86\x83\xc3\xb2\x62\x1d\x5f\x64\xe4\x8c\xf9\x7b\x5c\xae\x98\x07\xf4\xb1\xe6\xf5\x63\x20\x02\xb3\x7a\x8a\xe8\x16\x3d\x36\xd6\x16\x15\x99\xf4\x13\x67\xa8\x8f\x84\x3a\xf0\xbd\xbd\x99\x4c\xeb\xb5\xdb\xa2\xeb\x7a\x61\x54\x8a\x10\x92\xac\x16\xa0\x5a\x7f\x3e\x54\x03\xc0\x57\x00\x17\x13\x53\xc9\x0c\x14\x94\xf6\xc5\x90\x49\xeb\x21\x06\x4e\x7e\xc8\xe9\x39\x9f\x2e\x31\x18\x7e\x66\xf0\x18\x96\xe6\x0f\x47\x53\x67\x2e\xa2\x6c\x2e\x8a\x67\x2e\xd5\xfc\x96\xfc\x6a\x76\xf7\x2b\x38\xdb\x99\xef\xe4\xd1\x69\xf2\xaf\xd9\xbf\x5a\x62\xf0\x18\x7e\x66\xa0\x71\x73\x59\x40\x67\x52\x34\x2e\xf5\x5b\xf2\xe9\x9c\x0b\x59\x1a\xb7\xb3\x60\x47\x46\xa8\x1e\xb2\xac\xc0\xd1\x21\x20\xa1\x97\x9c\x93\x12\x37\x48\x28\x1c\xaa\xc6\xa9\x00\x93\x88\x67\x5a\x58\x7e\x6c\xdb\xd2\x2a\xf2\xe4\xee\x79\x9b\xb6\xfe\x70\x16\xde\xda\xd8\xfd\x6c\x6c\xcf\x44\x60\xc9\x3f\xfe\xeb\x9a\x17\xd6\x36\x08\x43\xea\x5a\x2c\x65\x66\xf7\xc0\x91\x8b\x96\xf0\x68\x76\x5b\xeb\xb4\xfc\xbe\x6b\x66\x9e\xda\x96\x9b\x84\x07\xa7\xbb\xfe\xd9\xbe\x42\x1a\xf6\x3e\xf9\xfb\xec\xef\xbd\xb9\x9e\x8b\xc7\x42\xd1\x41\xb3\x1b\x23\x96\x4b\xf4\xa1\x55\xbd\x68\x7a\x14\xa1\x3a\x4e\x31\x34\x35\x88\x4b\x9c\xa0\x57\x58\xad\x36\x94\xa5\xb2\x00\x58\x1c\xc0\xa2\x33\x54\x0d\x31\x0d\x3b\x56\xa0\x10\x5e\xdf\x7c\xa1\xce\x64\xd2\x8d\x60\x0b\xf6\xfe\xd7\x66\x34\x9a\x35\x15\x9b\xea\xd3\x29\x7e\xfd\x42\x40\xe7\x51\xd5\x38\xc5\x17\xa8\x08\xbb\x4a\x25\xc9\x1f\x19\x57\x5d\x35\x2e\x12\x70\xca\x31\x57\xb8\x22\xe0\x53\xc6\xcd\xd0\x02\x43\xf4\xa2\xaa\x10\xa7\xaa\x7a\x5c\xc4\x2f\x49\xa5\x6a\x9c\xaf\xdf\x42\x43\x03\x15\xe1\x55\xe3\xb2\x80\x7a\xfe\x67\xc7\xad\xea\x42\xc3\xeb\x52\xa3\x44\x5f\xc8\x27\x2a\x33\xf0\xb7\x5e\xe4\x48\x0e\x72\x3e\xaf\xcb\x2b\x99\xad\xa2\xdb\xe3\xf3\xbb\xdd\xa2\xd5\x2c\x79\x5d\x5e\x1f\xf5\xa5\x2e\xc8\x76\x6a\xa1\x3e\x8f\x16\x7a\x59\x44\x8f\xdb\x2b\x75\x8e\x5b\x05\x9d\x24\xdb\x73\xac\x62\xac\xa3\x27\x8e\x4a\xf9\x2b\x5d\x25\xc5\x0d\xca\xed\xed\xdf\x7a\xa1\xb5\x79\xaa\xaf\xe2\xd4\x71\x78\xd0\x19\xb4\x25\x6c\x7a\x08\xda\xf4\xa0\x43\x5f\xa1\x1c\x8f\x00\x9d\xcf\x41\x27\xce\xe6\x78\x74\x21\xc7\xa2\xee\x1c\xce\xe2\x6c\xbe\xb3\x97\x1b\xa5\x93\xf6\x83\x56\x24\x21\xa4\x07\x8d\xf5\xc9\x6a\x8f\x24\xc4\xa0\x03\x0b\x62\xd0\x16\x67\xed\x0c\xc2\xa1\x65\xe4\xb7\xf7\xbd\xab\xc9\x9b\x77\x9f\x63\xb8\x8d\x2b\xbe\x9f\x47\xef\xc2\xbc\xb7\xf1\x75\xf9\x4f\x56\x6c\xec\x91\x42\x79\x74\x1f\xf9\xed\x32\xfc\x3d\x06\xbd\x4d\x1e\xb8\x24\x6d\xc5\x3d\x69\x53\xbb\x0c\xb5\xa5\xa9\xcd\x2d\x46\x5b\x18\xc4\xb4\x85\x73\x9a\x5e\x01\xc5\xac\x9b\xf2\x7b\x0c\x1e\xc3\xe7\xa4\xa3\x13\x8f\x50\x1d\xf0\xce\x26\xab\xcd\x09\x4f\x98\xed\x5a\x1e\xce\x91\xd1\x4e\x1b\x8d\xd5\x13\x49\x8b\x13\xb3\x17\xf8\x96\x04\xc4\x4e\x45\x1d\xea\x48\x52\x0e\x30\x32\xab\xd9\x0c\xf3\xb1\x6a\x46\xad\x84\x05\xd0\x12\x6d\x8f\x48\x30\x44\x91\x8c\x71\x22\x1e\xe0\xe5\x02\xda\x36\x4f\x41\x5d\xe5\x00\xc8\xe1\x00\x96\x05\x25\x46\x07\x92\x5c\x91\xc1\x10\x48\x46\xa2\x30\xf4\xe7\x77\x34\x2e\x1d\xd3\x1e\xaf\x0f\xd4\x1a\x4b\x1a\xa7\x6d\x9c\xd0\x71\x62\xd1\xfb\xf7\x9d\x1c\x5f\xe7\x9d\x64\xf1\xc3\x4e\x72\xf1\xb6\x7f\xec\x9d\x7a\xeb\xab\x4b\xa7\xde\xb2\x78\x6a\x43\x63\x79\x83\xa7\xe3\xfa\xf1\x6b\x95\xd6\x09\x53\xa7\x8d\xac\x33\x32\x8f\xae\x1c\x33\x79\x00\x14\x49\x01\x76\xbb\xc7\x27\x8f\xac\x6d\x63\xb2\x7c\xd8\x5f\xe6\x35\x19\x66\xfe\x75\xff\x4b\xd1\xf4\xdc\x71\xdb\xc6\x5e\xe7\x1b\xbf\x74\x5a\xe9\xca\xc7\x3b\x0e\xfd\x79\x6e\x6b\xea\xae\x50\x04\xee\xba\x1f\x60\xff\xd2\x37\xee\x9c\xa5\xb4\xcc\x5f\x70\xdd\xda\xfd\xe9\xd7\xe6\x8d\x2b\x6f\x2a\x29\x96\xab\x1a\x97\xb6\x59\x6d\x57\x7d\x9f\x65\xe4\x72\xa3\xb7\x8a\xbb\xa2\xd6\x09\xce\x41\x97\xf4\x05\x53\xa9\xce\x3e\x19\xab\xc6\xb1\x64\xcf\xf2\x55\x58\x92\x33\x4a\x4c\xc3\x23\x71\x50\xe4\x5b\xc6\x0f\x12\x35\x5c\xe5\xd4\x32\x92\x9d\x9a\xec\xcf\xf4\x42\x17\xd3\x66\x2e\x24\xbe\x01\xa7\xfe\xae\x2f\xc2\x91\x52\x3d\x8b\x6b\x23\x69\x1b\x38\xc4\xd9\x31\x43\x70\x68\x62\xdc\x16\x6c\x9d\xb7\xc0\x5f\x1a\xf7\xc2\xc4\xc6\x79\x6d\x72\x7d\x6c\xe8\xd8\xdc\xc4\x85\x4f\x2d\x63\xd8\xd9\x27\xae\x7c\x76\xb6\xc3\xd8\x54\xbe\x66\xfa\xda\xbb\xbe\xbf\x64\xd5\xd5\xd5\xba\xb0\x54\x16\xc9\xd4\xb5\x97\x2f\xbf\x6b\xc9\x25\x3c\x06\x9f\xfd\x60\x90\xc1\x14\xf5\x61\x93\x11\x47\x6a\x2c\x96\xc8\xb0\xb4\xc1\xef\x58\x3b\x4e\xb0\x76\x4c\xf3\xeb\x2c\xbe\x32\x0f\xd7\xd0\x76\x4b\xcd\x1d\x8b\x36\x0c\xaf\x5d\xf5\xcc\x02\x58\xf1\xd4\xea\xab\xbc\xae\x2b\xc7\x0d\x3f\xb1\x6e\xe9\xd1\xe5\x1b\x9c\x73\x1b\x66\xd6\x0f\x89\x79\xf7\xe1\xdf\x5e\xba\xe1\x81\x29\xe8\x78\x35\x0c\xd1\xc4\x65\xcc\xbb\x91\x64\x35\x0e\x07\x25\xbb\x15\x0b\xc1\x78\x0b\xd8\xad\x66\x1c\x0e\x86\xaa\xb1\xb5\x05\x27\x82\xf1\x00\xb0\xb9\x82\x1d\xab\x76\x62\xa8\x55\x2c\xd9\xba\x61\xdf\xbe\x0d\xb0\x63\xc9\xf3\x37\xbc\xab\xf6\x6d\x79\xd4\xd3\xcb\x31\xaa\x0b\xbb\xfa\x6e\xe8\x39\xcd\x20\x7f\x27\x6f\x92\xbf\xcf\x18\x7f\x03\x3c\x74\xd9\xf8\xa0\xdf\x7e\x42\x44\xd1\xf2\x91\x0b\xb4\xb7\xe3\x42\x6a\x80\xed\x35\xeb\x77\x04\xa0\xf7\x3d\x8b\x7a\xdf\xcd\x3e\x7e\xc9\x1b\x81\x14\x1e\xdd\x33\x86\xb8\xf5\x92\xc4\x50\xf9\x8f\x90\x5e\x3d\x99\x91\x1d\xb9\x50\x25\x45\xe5\x0a\x86\x94\x56\x50\x6b\xbf\x55\x6d\x1b\xb1\x84\x12\xe3\x20\x28\x48\x32\x4b\x41\xf9\x45\x49\x33\x79\xa6\xe3\x86\x12\x64\x45\x25\x28\x95\x4c\x67\x62\x6a\x37\xaa\xd6\x1b\x64\x45\xea\x9c\x8d\xd2\xd3\x26\x82\xce\x60\xac\xe0\x8a\xcb\x90\x4e\xc4\xf1\x05\xf2\x93\xd2\xb0\xeb\xf4\xc0\xe1\xbb\x4e\x9f\xde\xb5\xf6\xb1\x07\x9f\xb5\xd7\xc3\x6a\x28\x21\x25\x57\x2c\x75\x72\xdc\xe9\x5d\x4d\xcd\x27\x2c\x06\xc9\xe2\x0c\xdb\x4f\xcc\x3e\x0d\x3a\x68\x22\xe7\xc9\xcd\xe4\xfc\xd8\xb6\x81\xe4\x01\x7b\xf0\x15\xb9\xfb\xe8\x29\x72\x1e\x84\x53\x6b\x16\x5e\x4f\x4d\x2b\x21\x07\x4f\x4c\xfe\x44\x33\x8c\x0c\x3a\xc0\x38\x73\xe1\x29\xc8\xb5\x95\x74\x15\x9f\x26\x5f\x9d\xbe\xf5\xcf\x93\x5b\x6f\x87\xdc\xae\xc5\x77\xfc\x18\x74\xa7\x5d\xa4\x5b\x4e\x9a\x8d\x7e\x60\xe7\xee\xd8\x75\x1a\xe8\x73\x41\x38\x35\xef\x07\xad\xf3\x49\x85\xe7\xfb\x1f\x81\x00\x6b\x40\xc8\x3c\xad\x24\x95\x5c\x4e\x49\x2a\x3e\xb2\xaa\xb2\xff\xbe\x6a\x81\xd6\x9c\x0a\x34\xaa\x0f\x81\xab\x47\x9f\x2c\xf6\x80\x51\x31\x3c\xd5\x05\xe3\x4b\x78\x84\xc3\x97\xe3\x5b\xd9\x92\x19\xb1\x05\x22\x25\xac\x24\x8b\x3d\xfa\x61\x56\xd3\xdd\xfa\x87\x73\x61\xb9\x7b\x99\x1c\xe6\x86\x73\x4a\x80\x55\x02\xca\x7f\xfb\x1c\xf9\x9c\xc3\xe7\x73\xe0\x9c\x03\x8e\xab\x91\xf3\x68\xd4\xb2\x51\x39\xf7\x62\xfd\x49\xf0\xc2\x14\xf0\x9e\xd4\x2f\x95\xc1\xd8\x4f\xff\x8b\x8b\x20\x27\xfb\xfd\x32\xc9\x05\xaa\xab\xf1\x55\xa5\x3e\x5f\xa9\x2f\x3f\x33\x7f\x38\x97\x1a\x35\x2a\x95\xd3\x7e\xf1\xcc\x55\x2b\xe1\x27\x63\xd6\x37\x35\xad\x1f\x43\x1a\x16\xd1\x7e\x61\xaf\x0e\x71\x5f\x21\x23\xaa\x46\x13\xb4\xdd\x26\xc1\xc2\xb7\xe3\x92\x31\x0d\xc7\x2a\x11\x54\x22\x85\x6d\x04\x41\x4d\x91\x15\x94\xd8\x44\xbc\x05\x83\x3a\x31\xd0\x8c\x28\xc3\x21\x14\xd3\xe4\x47\x23\xd0\x01\x67\x24\x11\x47\x72\x22\x2e\x71\x4f\xc7\x23\xf9\x41\x91\x78\x3c\x82\x5f\x88\x80\x4e\xee\x2e\x57\xdd\xcc\x8d\xd3\xc8\x87\x3f\x38\x49\x7e\xfe\xa8\xcc\x7c\xa0\x7a\x74\x5f\x3d\x0d\x62\x3f\xd8\xf5\xe5\x89\x25\xb0\x36\x1e\xd9\x69\xdb\xf9\x11\xf9\xe9\x43\xff\x24\xcb\xaf\x78\x5e\x0d\xdd\x65\xdb\xf9\x11\xd4\x1e\xfd\x07\xdc\x71\xc5\xe9\x48\x1c\xff\xa6\x2d\x91\x68\x4b\x4c\x99\x32\x29\x1e\x8e\xc4\xbf\x73\xf4\x51\xf2\xde\xc9\x1e\xf7\xe2\x47\xff\x0a\xbb\xc2\xf1\xc9\x93\x1f\x22\x3f\xfd\x78\x27\x18\xce\xc6\x23\xf4\x0a\x6a\x3f\xde\x49\xfe\x79\x36\x8e\x10\x8f\x8c\x17\x11\xfb\x8f\xc2\xb7\xf5\xa2\x4a\xb4\x8e\x62\x8a\x33\xb2\x3d\x95\x0c\x87\xe8\x5e\xe9\x6a\x0c\x0e\x51\x15\x9f\x8c\xda\x24\x18\x4a\x4e\x9d\x4e\x25\x69\xbf\xc2\x33\x05\x95\x56\xda\x96\xac\x06\x0d\x20\x8b\x77\x3a\x02\x6c\x26\x4e\xe1\x93\x34\x48\x72\xa7\x43\x72\x0a\xbc\x53\x89\xf1\xe1\x02\xf5\x5a\x2a\x99\x91\x0a\x1d\x0f\x5d\xae\xe8\xdb\x28\xac\x99\x8a\x8b\x92\xdc\xc2\x51\xb5\x21\x13\x60\x9c\x0e\xac\xa1\xf9\x63\xe6\xd4\x9a\x75\x87\x95\x7a\x72\x63\x80\x89\x86\x8a\xca\xc3\xe4\xad\x07\x6c\x25\x96\xa6\x4d\xa3\x06\x88\x8e\xb1\x8b\x77\x85\xcc\x72\x89\x49\xa9\x1f\xe4\x77\x24\xee\x77\x37\x9e\xbf\xef\x37\x07\xef\xc2\x4e\x47\x1d\x79\x7d\x6d\xb4\xa8\xa8\x62\xc8\xd4\x69\x13\xfc\x56\xc1\x65\xb5\xb0\xbe\x21\xcd\x25\xd9\xe9\x51\x86\xbd\x5e\xaf\x0b\xe2\xf1\xe9\x09\x0f\x07\x93\xba\xd1\x75\x45\xfe\x47\xfd\x15\xe9\x35\x93\xe7\xf8\x36\x37\xfb\xcb\x1e\x9c\x30\x66\xe7\xcb\x3c\xe6\xab\xcb\x06\xb7\x8c\x8d\x0e\x9b\xf0\x40\xf3\x58\xc5\x3c\xe7\x58\xf7\x5d\x2b\x57\xdd\xf1\x21\x7b\x1d\x79\xc6\x09\x3f\x1a\x5c\xd7\xbd\x6a\x9c\xae\xdc\x8d\x05\x81\xd9\x3d\x9f\x4c\x37\x70\x30\xf7\xa3\x70\xf7\x3f\x22\x47\x6e\xf4\x98\x5d\x63\x4a\xc6\xcd\xcf\xa6\xc9\x7d\x65\xad\xb7\x7e\xff\xd8\xc3\x80\x2b\x06\xb4\xdb\x6b\x53\x46\x2e\x10\x4a\xfa\x44\x96\xc5\xa2\x18\xf1\x79\x24\x57\xf5\xde\xa1\xc5\x6b\x03\x45\x45\xd8\xf0\x36\x16\xcc\xa9\x11\xf7\x8e\x0f\x05\xb3\x45\x4b\x6c\x45\xa1\x4f\xa6\x67\x16\x6e\xf1\x8c\x0c\xb4\x6c\xb6\xc0\xdb\x4b\xc7\x2d\xcc\x3f\x67\xe3\xad\xdb\xae\xba\x75\xe1\xf0\xf9\x23\x56\x90\x36\x4b\xcb\x9c\xd9\xd9\x03\xa4\xfb\x85\xab\xca\xeb\xc1\xd4\xc7\xf7\xa7\xf6\x7f\x1e\x94\xa6\x38\xf1\x08\x12\xfd\x3b\xb3\x70\xa1\xf7\x53\x3b\xba\xe8\xb7\x86\xa4\xa3\x49\x75\xf0\x1a\x53\x82\x25\x82\x19\x6b\x5f\x50\x0e\x60\x59\x62\x83\x25\x99\x16\x9c\x69\x01\xd1\x16\xb4\x31\xb6\x9f\x9a\x1f\xde\xf1\xbd\x53\xcf\xde\x78\xfb\x51\xd3\x19\xae\x39\x51\xdf\x6a\xf0\xa4\x63\x73\xf1\x07\x6f\x9b\x8f\xf6\xf8\xbf\xc9\xb6\xc4\x55\xff\x54\xac\x36\x03\x57\x16\x57\xf1\x16\x1f\x9e\x92\xbf\x2f\xff\x9d\xc9\x9c\xdb\xc6\x57\x05\x02\x55\xbc\x5d\xe6\x2b\x61\x0f\x88\x78\xfe\x54\xce\x65\xe3\xaa\x03\x9d\x5f\x21\x6c\xbd\xff\x87\xbf\x7f\xed\xe5\xff\x39\x71\x28\xdb\xb6\x69\xdd\x80\xe1\x83\x23\xfb\x2e\xf7\x68\x7f\xea\xa7\xaf\x35\xeb\x8a\xec\xb8\xb5\x95\xb5\x98\x74\x4d\xaf\xbe\xfb\xce\xab\xcd\x3a\xb3\x99\x0b\x96\x0c\x64\xcd\x66\x7d\xd3\x4f\x98\x33\x17\x54\xb1\xd5\xd3\xaf\x70\x1d\x5c\x0e\xf9\x51\xa3\x66\xf1\x58\x00\x48\x57\xfa\x31\x3a\xd2\x96\x4e\x19\x87\xcd\xd0\xd3\xd9\xf7\x30\x3b\xa6\x7b\x2e\x98\x73\x94\x5b\xf2\xd0\x2a\xf2\x17\xea\xb0\x9b\xe1\x9d\x3d\x9f\xed\x86\xdc\xee\xcf\xf6\x90\x01\xea\xf5\x21\xb3\x1d\xac\xab\x0e\x51\x07\x73\x0b\xb1\xd2\x38\x7f\x59\x75\xa8\x8b\x02\x7b\x73\x59\xb3\x7d\xf7\x67\x30\xa2\xfb\x96\x3d\x9f\xed\xb6\x9b\x19\x6d\x12\x8f\x0e\xad\x62\x56\x69\x7b\x40\xd8\x7e\x7b\x40\x5a\xa8\x05\x0f\xba\xdc\x3a\x96\xd3\xb0\xaa\x85\x1e\xc0\xea\x46\x88\xf7\x04\x7d\xd3\x55\x34\xd5\x6b\xa8\x43\xc3\x0a\x78\xeb\x97\x8d\x68\x8a\xbd\xae\x37\x5c\x3e\x9f\xeb\x0d\x97\x97\x48\x03\x53\xbb\x87\xf8\x7c\x43\x76\xa4\x06\x3a\x33\x92\xd7\x3d\xc7\xe5\x73\xa6\x25\x9f\x6b\x9e\xcb\x2b\x65\x9c\x78\xf4\xa0\x14\xf9\x2a\x35\x48\xca\x38\x8b\x5b\x5f\x4c\x0d\xda\xba\xb7\xa3\xeb\x9d\x8e\xbd\x7b\x3b\xd8\x01\x1d\x7b\xf1\x53\x6b\xd4\xa7\xa8\x3f\xe4\x42\x6a\x60\x32\x39\x30\x75\x41\x92\x7e\xa7\xfa\xfd\xae\xf7\xbc\xfe\x9e\xd4\xc0\x81\x29\xb2\xc8\xe9\x7c\xb2\x7c\x20\xbe\xaf\xef\xee\xbd\xfd\xb9\x0b\x31\xd2\x53\x2b\xc2\xa0\x17\x82\xea\x7f\xfd\xd7\xf6\x15\xde\x46\x3e\xbc\xed\x73\xc8\x90\xd3\x64\x38\x39\x0d\x19\xd8\x86\x97\x1d\x5b\xdf\x9d\x5d\x7f\xec\xd8\x7a\xa6\x73\xfd\x31\x78\x19\xc7\xba\xef\x64\x51\x37\x82\x06\x7c\xa4\xcf\xff\x98\x5a\x1d\xe4\x5e\x3c\xc6\xd1\x68\x32\x9a\x87\x96\xa0\x2b\xd1\x1a\xb4\x11\x6d\x43\xbb\xd0\xf5\xe8\x56\x74\x00\xdd\x8b\x0e\xa1\xef\xa3\x87\xd0\x31\xf4\x28\x7a\x06\x3d\x87\x5e\x40\x2f\xa1\x33\x1a\xd6\x31\x43\x77\x84\x32\x05\x2d\x68\x90\x57\x0f\x4d\xae\x31\x74\xc3\x2d\xa3\xa1\x1f\x88\x49\xd5\x4b\x2c\xc8\xb6\x60\x5a\x3d\x34\xd8\x09\x91\xe2\xe8\x8a\x01\x80\x20\x84\x21\x98\x8e\x03\xf5\x95\x33\xb6\x18\x2f\x40\x50\x8e\x06\xf9\x10\xa4\x33\x31\x21\x9c\x61\x40\x86\x8c\x18\x84\x34\x97\x80\xa0\x4d\x96\x98\x60\x06\x2c\x90\x48\x09\x92\xcd\xa1\xde\x24\xdb\x32\x36\x19\x6a\x40\xb0\x65\x62\x7c\x34\xcc\xc9\x4e\x3d\x8e\xc6\x6c\x9c\x90\x00\x59\xac\xc1\x4a\x33\x30\x4a\x4c\x8f\x53\x8c\x18\x16\x41\x68\x05\x4a\x47\x67\x04\x39\xad\x43\x1e\xc7\x5b\x8c\xdb\xf1\x12\x13\x74\xb9\xad\x64\x95\x2d\x69\x23\xab\x6d\x1e\x39\xc4\xbe\xe4\x70\x33\x6f\x3b\xdc\x5e\xc7\xab\x10\x7a\x97\x0d\xc9\x1e\x3b\xdc\x68\x4d\x5b\xe1\x66\xbb\x1a\xfa\x53\xb9\x44\x78\x4e\x74\x77\xc7\x60\x37\x39\xf6\x1d\x72\x0c\x96\xd8\xcb\xbb\x67\x02\x7e\xc7\x72\xfa\x39\x93\x15\x1f\x25\x5b\x5e\xc0\xe5\xe4\xf7\xd6\x4a\xfc\x28\xb0\x59\x5b\x40\xea\x26\xbf\x68\x85\x0d\xd6\x81\x64\x32\x8c\xd6\x75\xaf\xe2\x60\x0a\xd9\xc7\x9a\xed\xb0\x3f\x4b\xce\xdc\xf7\xd2\x83\x47\x59\xd0\x3d\x12\xb8\x1b\xca\x7e\xf5\x2b\xf6\xad\x17\x79\x66\x83\x35\x7f\xdb\xfb\xe4\xbf\x20\x03\xa5\xf9\x6b\xf6\xc2\xef\xca\x27\x43\xf4\x4f\xbb\x18\x90\x74\xbf\xe0\x74\x64\x14\xa4\xbb\x3b\x1f\x7c\xf0\xc1\x07\xd9\xe6\x01\x3b\x4a\x7f\x8a\x99\x47\xb6\x8f\xe6\xf0\x76\x67\x31\x4b\xee\xd5\xeb\x1d\xc5\x2c\x79\x54\xa7\x93\x43\x76\x87\xc3\x11\x74\xe9\x8a\x60\x2c\x5b\xec\xd0\xeb\x61\x01\x57\xec\x70\x16\xb3\x30\x0d\x58\x88\x58\x60\xb9\x41\xe7\x0a\x3a\x9d\x4e\x67\xd0\xc5\x17\x91\x7b\x20\x28\x99\xcc\xe4\x34\x5b\xdc\xfd\x16\xcc\x27\xf7\x5b\x19\x1f\xab\x37\x70\xe4\x2e\xfe\x55\x98\xf9\xb2\x0e\x43\xe7\x6b\xaf\x59\xbb\x26\xf1\xdc\x90\xb1\x4b\xc1\x40\xde\xca\x92\x5b\x7c\x90\x26\x0f\xb3\x16\x98\x4f\x4e\xf2\x1c\x6c\x1c\x04\x03\x8f\x7c\xfc\xfc\x49\x1d\x93\x02\x0c\x56\xd3\x49\x30\x19\xc9\xeb\xf7\x41\xc3\x1f\x3e\xd1\x91\xaf\x46\xbe\x8e\x8b\xce\x7d\x5a\x41\x5e\x21\x2f\x41\xc2\x72\x13\xf9\xec\xe3\x4a\xd8\xdb\x85\x57\x71\xe0\x34\x59\x31\x6c\x04\x96\xd4\x92\x53\xf0\xcf\x5f\x91\xdf\x75\x5f\x4f\x7e\x0b\xde\xdf\xfc\xa6\x0d\x96\x1a\x58\xb0\x40\x69\xfe\xde\x09\x8c\xb6\x5e\x42\xf1\xff\x4d\xc8\x8b\x10\xad\xfe\xbd\x8d\x21\x1a\xeb\x6f\x88\xf7\xf4\x4e\xfc\x3b\xe8\x78\x7a\x67\xf7\xdf\x77\x3e\xcd\xbe\xf3\x58\xb6\x9a\xf8\xaa\xb3\x03\xab\x98\x69\x3b\x5f\x84\x45\x17\x06\xed\x7a\xe1\x85\x5d\x91\x27\xe1\xe1\xea\x41\x83\xaa\x89\xa3\x7a\xb0\x26\x6f\x76\xf2\x88\xbb\x16\x19\x28\xb3\x77\x19\x42\xc0\x22\x46\x1d\xb8\x44\x12\x71\x4e\x92\xd5\x8b\x98\x1d\x81\x1d\x45\xb5\x0b\x4e\x89\xf1\x42\x1a\x65\x78\x41\x62\x8e\x90\x1f\x91\xd0\x06\xc7\x5b\xd0\xf1\xce\x04\x58\x30\x7b\x18\xb9\x26\xff\xca\xca\xd9\x2d\xab\x70\x9a\x3c\xb8\x16\xdb\xe0\x8a\x52\x33\xf9\x88\x64\x37\x2c\x66\x7e\xfa\xd2\x89\x3d\x07\xaf\x84\x91\x6f\x3a\xc7\x0d\xe4\x96\x6d\x22\x7e\xf2\xd2\xf4\xa9\xef\xc0\xbc\xb7\x6e\x18\x38\x63\x75\xfe\x25\x72\xcd\xf0\x19\xb0\x03\x37\x74\x35\xc1\x02\xec\x58\x3f\x6b\xf1\x46\xd2\x42\x7e\x69\x76\xc4\x07\x4e\x92\xdf\x82\x51\x57\xdd\xb5\xeb\xd1\x82\x6c\xd0\x21\xf6\x5f\xd4\xf6\x57\x95\xe4\xa2\xc6\xf2\x43\x35\x24\x15\x20\xa6\x83\x71\x39\x9d\x28\x81\xb8\x44\x87\x2b\xd4\x9f\x51\x27\xba\x72\x3a\xa3\x91\xd3\x09\x94\x1d\x4a\x4e\xcb\xc2\xc2\x83\x3b\xb7\xbe\xf6\xd2\xaf\x6f\xbf\xfd\xd7\x2f\xbd\x96\xdb\xc2\x1d\x3c\x07\xf8\xf3\x7b\xee\xf9\x1c\x30\xf9\xeb\xf6\xb7\xef\xdb\xf2\xc8\x2b\xe7\x0e\x1c\x38\xf7\xca\x23\x5b\x96\x6e\x7a\x6c\xc6\x1b\xc7\x8f\x7f\x99\xf9\xf9\xed\x77\x7d\xf2\xd8\xa1\x35\x5b\xde\x5d\xf7\xee\xe1\xe3\x6f\xb0\x1b\xbb\x74\xf5\x33\x6f\xbf\x7d\x66\x3d\xfb\xd5\xb6\x65\xcb\xba\x8e\xd4\x0f\x64\xf2\x63\x6e\xba\x69\x4c\x37\x53\x51\x19\x5e\xb1\x22\xc4\xec\x63\xef\x3c\x38\xa8\x7b\x62\x22\xbe\x68\x39\xa7\x8d\xa3\x0f\xeb\x10\x37\xb3\x77\xbf\xc5\xac\xff\xfd\x3a\xf4\xd7\xae\xfb\x00\x56\xfb\x21\xad\x50\xd9\x12\x00\xee\xa3\x80\x63\xb6\x23\x40\x7f\xc8\x67\x01\xc7\x42\xd5\xbd\xd0\x11\x20\x1f\x7d\xb3\x9b\xdb\xfb\x87\x23\x5d\x91\x23\x7f\xd8\xba\xd4\xf0\xdd\xd5\x8b\xc6\x54\x41\xf9\xf3\x77\x74\xdf\x66\xde\x73\xfc\x30\xfe\xd8\x19\x08\x38\xf3\x61\x35\x22\x16\xd5\xdf\xfc\x1f\xd5\x5f\xf8\x81\xfa\x4b\x26\x52\xf7\x32\xea\x3e\xe0\x08\x04\x8e\x1c\xf9\xc3\x1f\x8e\x5c\xfd\x4a\x3c\x14\x5b\xfd\xdd\xc1\x4f\x7f\x71\x5b\xf7\x1d\x83\xea\x82\xbf\x44\x08\xc5\x10\xba\xd8\xc2\x6b\x7b\x67\x34\x9e\x36\x27\x65\x6a\x0b\x52\xae\xb6\x2a\x54\x8b\x52\xa8\x1e\x35\xa3\x81\x68\x28\x1a\x81\x46\xa3\xf1\x68\x32\x9a\x8e\x66\xa3\x79\x68\x31\x5a\x8e\x56\xa2\xb5\x68\x03\xba\x06\x6d\x43\xbb\xd1\xf5\xe8\x26\x74\x2b\xba\x03\xdd\x8d\x0e\xa3\xf7\x11\xb2\x05\x6d\x7a\x88\xd2\xdf\x54\xd0\x29\x3a\xc3\x29\xf9\xf2\x23\x23\x0b\xfd\x8f\x56\xb8\xf4\x00\x67\x38\x15\xfc\x37\x87\x1a\x9e\x70\x66\xbe\x25\x54\x4e\xa9\xa1\xc2\x37\x1c\xd1\x9e\x11\x16\x05\xbf\x09\xe0\xb4\x66\x8e\x16\xee\xb5\xa7\x03\x5e\xd1\xb0\xfe\x25\x39\x91\xa9\xe6\xc3\x21\x33\xe6\x51\xf7\x57\x79\x1d\x77\xef\x85\xd7\xf0\x1d\xf8\xc1\x0b\xaf\x8d\x8f\xf6\xfc\x6b\xb5\x2c\xb5\x14\x5b\x96\x5a\x02\xf4\xbc\xc4\x32\x76\xa9\x65\xe9\xc6\xa5\x96\xa5\x9b\x0a\xe7\xee\x81\x6b\xc0\xb1\x16\x9c\x6b\xc1\xb1\x86\xfe\x15\xdc\x5d\xcf\x44\xd7\x7e\xef\x72\xff\xbf\x8c\x59\xdb\xfb\xe0\x68\x7e\xef\xf6\x67\x9e\xd9\xbe\xe3\xe9\xa7\xc9\xd9\x58\xd3\x90\xa6\xd8\xaa\x79\x1e\xa6\x78\xf0\x5c\x7f\xa6\x2e\x9c\x19\x37\x36\x53\x56\xea\x0c\x8d\xb0\x30\x01\x26\xa2\x0f\x98\x3d\x52\x91\x3f\x93\x0a\xf2\xe8\xc2\x2d\xe4\x04\x4c\x18\xc8\xdc\xdf\x3d\x9f\x7c\xc8\x95\xbe\xfe\x3a\xf9\x60\xed\xda\xdb\xfb\xfd\x7d\x27\x54\x13\x34\x87\xaa\x43\xea\x61\x0a\x56\x87\x42\xd5\xc1\x9a\x39\xd5\xa1\x6a\xf5\x98\x5d\x13\xaa\x66\xdf\x8d\x5c\xf6\x8f\x1c\x1f\xbb\xf6\x52\x9f\xb5\x63\x23\x97\x3c\xf3\xf6\xb5\x6b\xc3\x4f\xef\xd0\x52\x0b\xd7\x46\xca\xf4\x1c\x88\xce\xda\x44\x6b\xb9\x41\xaa\x2c\xae\xae\x11\xc0\xe8\x70\xba\x78\x49\x6e\x00\x0b\x63\x64\x78\x6c\x90\xab\x7a\xf8\x05\xd6\xea\x10\x77\x13\xc5\x7b\x28\xbf\x6c\x0e\xfb\x4d\x9b\xf3\x0a\x34\xb2\xea\x40\x63\xee\x03\xe7\xee\xbf\xff\x1c\x43\xee\x3f\xf7\xc0\x03\xe7\xe0\x5c\x6b\xd5\x57\xbf\xa8\x6a\x6d\xad\x82\x47\x2b\xb3\xf8\xcb\x6c\x25\x3c\x5a\xd5\x0a\x7b\xd5\xb0\xfb\xd5\x88\xab\x56\xdf\xcf\xd6\x5d\x38\x5d\xd9\xda\x5a\xc9\x0d\x51\x7f\xbf\xfb\xdd\xca\xd6\xd6\xc2\x38\xb4\x54\x87\xd8\xb3\x08\xa1\x19\x08\x01\xd7\x03\x77\x24\xf4\xe9\xe7\xe9\x42\xb3\xd3\x21\xa8\xf3\x48\x75\x14\x81\xfa\x43\x24\x15\x2c\x07\x52\x9a\x92\xa3\xc7\x94\x5d\xbb\x21\xcd\x1d\x00\xf6\xf6\x9f\x7d\x78\xff\xe4\x7b\x36\xaf\x59\xb2\x78\xcd\xc6\xbb\x26\xde\xf3\xa3\x77\x1e\x58\xf0\x8b\xc9\x5c\x89\x4f\x67\x76\x36\x2d\x24\xff\xd8\xb6\xfb\xd3\x3d\xe0\x7d\x7b\xe3\xfb\xf7\xdf\xba\xfb\xba\xc3\x33\x16\xed\xde\x3e\x37\xb0\xd8\xe6\x28\xb6\xfd\xd7\x03\x0d\xcb\x9b\xe3\x3a\x8b\xd3\xdd\xf8\xd8\x9c\x17\x09\x5b\xcf\x9c\x7a\xf3\x95\xfd\xf7\xbd\x9b\x99\xb5\x71\xd7\xee\x8d\xb3\x32\x4f\xdf\x7d\xdf\xb3\xa3\x9a\x59\xbf\xe8\x34\xbb\x52\xd3\x56\x5c\xfd\xc1\x75\x6f\x81\x75\xea\xbe\x87\x8e\xee\x9b\x7a\xcd\xc2\xb9\xb9\x68\xc0\x61\x1f\xe3\x78\xe0\x9d\x68\x65\xd4\x69\x11\xbd\x83\x47\x74\xbd\x10\xf5\x5b\x0a\x63\xd9\x1c\x87\xe8\x5e\x82\x0a\x34\x95\x96\x7a\x85\xc6\x49\xe9\x07\x6a\x2a\xd6\x08\x14\x64\xa4\x19\x28\x2a\x86\xc6\xc7\x51\x38\x8b\x94\x61\x81\xf2\x0a\x04\xe3\x52\x8f\xa8\x6b\x81\x0c\xd3\xb3\xa6\x12\x60\xd5\x69\x38\xdb\xa9\x78\x72\x4a\x52\xd1\x38\x7c\xa9\x23\xff\x3b\xcd\x86\x5c\x33\x25\x3f\x53\xe2\xee\xfa\x03\x08\x9c\x8b\xb9\x4b\x8d\xd2\x8d\x3c\x8a\x14\xc5\x27\xdf\xd4\x96\x4d\xac\x6e\x8b\x91\x15\x80\x3d\xe9\x51\x98\x4b\x9f\xa2\x3a\xf2\xfd\x0d\xcb\x99\x4e\x82\x5c\x51\x66\xb3\xe0\x77\x19\xac\x03\x94\xa4\xa2\x78\xcc\x89\x21\x2c\x93\x51\x92\x8a\xc9\x5e\x2c\x45\x05\xa5\x0f\xd7\x5e\xcd\xb7\x66\x8f\x3f\x51\xab\x6d\x96\x1e\x33\x7a\xca\x80\x26\x83\x14\xcf\xc0\xff\x35\xcf\x1c\x52\x92\xe2\x6d\x4a\x52\xb9\x4d\x4c\x2a\x22\x20\x31\x29\x02\xca\xdf\xf6\x7f\xce\xb5\xb8\x1f\xa2\x6a\x00\xf9\xe5\x7e\x51\x49\x8a\x17\x91\xa8\x3e\x2f\xf4\xbf\xcf\xbb\xc6\xa3\xa1\x8d\xdf\x39\xa4\x47\x45\x74\xaf\x99\x82\x90\xa8\x67\x82\x31\x31\xa8\xc7\xc1\x68\x90\xa1\x03\xfa\xa8\xa6\x32\xa7\xcc\x1e\x19\x50\xf3\xf6\x1e\x5e\x49\xde\x83\xcf\x61\x76\xbe\xed\xfa\x37\xc9\x05\x72\x8e\xc9\xe3\x95\xe4\xf9\xee\x97\xf1\xb1\x37\xc9\x9f\xf0\x4a\x98\x41\xce\x91\x0b\x30\x1d\x72\x66\x6c\xed\xce\xda\x1b\xec\xdd\x59\x2b\x36\x43\xce\x1e\x64\x73\x41\x06\xe5\x17\xe3\xbb\xbb\xbb\x19\x96\xf2\x6d\x74\xff\x37\xbe\x9b\x3a\x20\xb7\x88\x20\x7b\x8d\xad\x1b\x39\x1c\x2c\xb2\xd5\xd8\x31\xf2\x20\x06\x89\x17\x91\xf0\x47\x1e\xa1\x11\xe8\x4e\x74\x08\x21\x2e\x1d\x2f\x06\x21\x46\xa1\xa8\xff\xfd\x4f\x46\xdb\x1c\xfb\xad\x3f\xd1\xfe\x91\x6c\x8c\x92\x6e\x05\x5b\x22\x15\x4c\x05\x9d\x41\x67\xc2\x26\x07\x40\x60\x6c\x7d\xb1\xff\xd3\x2b\xc1\x19\xe5\x52\x6a\x37\x23\x88\x62\x52\xcc\xcd\x98\x38\xd1\x9e\xb6\x4f\x9c\x28\x26\xc5\x6f\xfd\x51\x23\xfd\xbb\xf0\x89\x17\xaa\xfa\xc5\xca\xfe\xcc\xe6\x08\x9c\xcc\x69\x6a\xa0\xdc\xc9\x80\xc3\xf6\x33\xb1\xff\x93\xfe\xed\xeb\x20\x0b\x39\xc8\xe5\x08\x12\x45\xed\x81\xe2\xb7\x1d\xff\x26\x74\x93\x1a\x3a\x61\x82\x28\x4e\xc8\x42\x14\x1a\x3c\xcd\x86\x06\xa8\xc8\xe5\x72\x39\xf2\x7e\x83\xa1\xd9\x43\x7e\x42\x7e\x69\x17\x45\x35\xc2\xbf\x79\x08\xeb\xd1\x20\x37\x7b\xda\x1f\xd7\xc3\xe5\x32\x18\xad\x47\x28\x28\xd6\x00\x88\x16\x80\x02\x09\x64\xa8\xc0\x05\xa9\xd1\x38\xea\x13\xf1\x16\xa6\x11\xe2\x01\x26\x11\x6f\xd1\x69\x1b\xa3\x7b\xdb\x1e\x93\x89\x25\x54\x41\xab\x09\xdb\x8c\xda\x99\xc7\x29\x48\x0b\x50\x20\x57\x49\x48\x08\x01\x06\x67\x3b\x3a\xd4\x82\xc8\x75\x00\xc2\xd8\x30\xa5\x6d\x9e\xe0\x13\xe6\xb5\x4d\x31\x50\x3b\x5d\x23\xc6\x46\xa6\x88\x33\x19\x6d\x76\xd9\x14\xa9\x16\x0d\x26\x63\x91\xd1\x64\x10\xab\x23\x26\xd9\x6e\x33\x9a\xb8\x22\xc6\x48\x63\xc1\xf7\xf6\x6f\xea\x3e\xb0\x69\xbf\xde\x5f\x3d\x3e\x35\xe3\x03\x09\xbf\xfc\x33\xdb\xd0\x48\x49\x65\x60\x45\xd3\x8a\x40\x65\x49\x64\xa8\xed\x67\x2f\x0b\xde\x0f\x26\xb4\x4e\x2f\xb7\x42\x67\x2e\x9b\xcf\xe1\x5c\x36\x87\xe3\x2c\xd6\x89\x18\x8b\x3a\xcc\xda\xf5\x8c\x20\xb0\x41\x9d\x47\xe7\x10\x8a\x58\xd6\x1d\x0e\xb9\xdd\xa1\xb0\x9b\x65\x8b\x04\x87\xce\xa3\x0b\xb2\x82\xc0\xe8\xbb\x1f\xdc\x74\xc3\x0d\x9b\x9a\xd7\x5c\x7f\xd5\x3c\xcf\x47\xd9\x6c\x91\xa3\xb4\xae\xbe\xbc\xe5\x96\xf2\x68\x4b\x4b\xb4\xfc\x96\x96\xf2\xfa\xba\xd2\xf1\x63\x3f\x0d\x6e\x3b\xf4\x9d\x82\xde\x20\xcf\x21\xd4\x8e\x66\xa1\x55\x08\x81\x64\xc6\xb1\x6a\x88\x29\x54\x51\x42\x97\x40\xc3\xfd\x16\xbe\x95\xde\x3d\xe1\x01\x2c\x07\x13\xb1\x70\x48\xc9\x50\x5d\xbb\x5a\xdd\x0b\x8b\x12\x7c\x05\xc8\x69\x39\x00\x10\x4f\x67\x82\x1a\x45\x3a\x5d\x6e\x2f\x85\xf4\xd7\xd6\xd8\x75\xf9\xa2\x21\x3b\x9e\x5b\xfc\xdd\x3f\x5a\x8b\xc6\x8e\x1d\xd6\x71\x55\xd4\x7b\x11\x0d\xed\x5d\x06\x6f\x6f\x77\x5d\xf3\x43\xba\x1d\x2c\x37\xe6\xba\x2b\x2a\xfd\x18\xad\x9d\xfc\x49\x40\xe1\x58\xc5\x95\x0f\x3a\xda\xd6\x88\xde\x85\x6a\xe0\x13\x6b\x77\xde\xf2\x9d\x37\xbe\x7a\x6f\xed\x63\x32\xf9\x49\xd8\x61\xb7\xdd\x56\x53\xb9\xeb\xf4\x69\x2e\x07\xba\xd3\x97\xae\xb9\xc3\xdf\x17\xbf\xb8\xb7\x5d\x30\x7e\x76\x68\xe5\xab\xc3\x96\x8f\xfb\x6c\x87\x37\xd6\xb3\x32\xee\xad\xba\x4a\x49\x2a\xde\xb8\x5f\xca\x55\x05\xe4\x80\x6f\xe9\x1a\x51\xf1\xe4\x3c\xca\xf1\x56\xaf\xe7\x6c\xbe\xeb\xd6\x95\xc5\x25\xc5\xe0\x34\x9d\x26\x5f\x9d\x3e\x7d\xf9\x72\x7b\x81\xdf\x88\xcb\x71\xe7\x50\x0a\x8d\x55\x7b\xc2\xa0\xc3\x8c\x4b\xaa\xb1\x86\xa7\x21\xc9\x12\x2f\x98\x59\x21\xc0\xc6\x5b\x98\x0c\x05\xd6\xa0\x5b\x18\x19\x6d\xad\xaa\xbf\xc5\x49\xaf\x5d\x5e\xa1\xc7\xe0\x72\xd7\xbc\xf5\x0f\x72\xe1\x1f\x6f\x5d\x33\xe8\xea\x8d\xc3\x3c\x95\x2c\x57\xec\x69\xe8\xa8\x2f\xb5\x00\x33\x60\xfe\x8e\x17\xdf\x7b\x71\xc7\xfc\x01\x0c\x58\x4a\xeb\x3b\x1a\x3c\xc5\x1c\x5b\xe9\x19\xb6\xf1\xea\x41\x24\xa7\x78\xb2\xda\x16\xa7\xac\x47\x19\x95\x82\x5c\x6a\x54\x07\xe5\xba\x6a\x5d\xd8\x5c\x5c\xdc\xbc\xb0\xb5\x76\x6c\x3a\x5c\xc4\x15\x7b\x3c\x95\xac\xc1\xeb\x92\xad\xac\xb1\x38\x1c\x70\x38\x02\x91\xe2\x22\xd6\xec\x92\xbd\x06\xb6\xd2\xe3\x29\xe6\x8a\xc2\xe9\xb1\xcc\x58\x92\xf3\x28\x24\xa7\xe9\x23\xd4\x23\x35\x6a\x14\x1c\xd5\x38\xb1\x70\x2f\x67\x8d\x97\x5a\x4f\x05\xcd\x60\x01\x0d\xc3\x32\x16\x8c\xa7\x33\x5e\xd0\xb8\x5c\x44\x59\x02\x87\x10\x8c\x55\x83\xc0\x0b\x46\xa8\x86\x10\x2f\x30\xc1\x02\x46\x24\x96\x5b\x98\x84\xda\xe9\x41\x2d\x67\x60\x99\xfc\xad\xf6\xa4\x3d\x7f\x0b\x67\x85\xd5\x52\x98\x6b\x7b\x81\x0f\x49\xce\x10\xbf\xbf\xce\x8e\x63\x8b\xc9\x77\x56\xea\xc2\x62\x95\x71\xfb\x8f\xf9\x70\x65\x88\xbb\x9a\x4c\x5f\x4c\xce\xb5\x6c\x5f\x39\x2e\x12\x19\xb7\x72\x7b\xcb\x39\x82\x11\xaf\x67\xd8\xfc\x51\xbb\x1d\xcf\xc0\x76\xaf\x13\xdc\xf9\x85\x0e\x8f\xc7\x01\xbf\x5d\x15\x86\xe3\xb7\x1e\xfc\xd8\xe6\xc0\x5c\x19\x99\x80\x4f\x38\x3c\x5e\x27\x19\x70\xf0\xd6\x8f\xbe\xaa\x18\x91\x8d\x44\xb2\x23\x2a\xbe\x52\xc7\x70\xf8\x22\x62\x73\x5c\x37\xdd\x5b\x83\xc0\x81\x04\x5b\xa2\xa7\x56\xf7\x2e\xd4\xf5\xe2\xed\xda\xaa\x01\x53\xf6\x59\xd6\x1e\xb1\x22\xaa\x2f\x62\x73\xe4\xec\xd9\x73\x7d\xa0\x31\x9a\xf3\xc0\xdf\xb6\x17\x19\xf7\x7d\xba\xfb\x18\x94\x9f\xe8\x46\x5a\x8d\x23\xe7\xc9\xcd\x4c\xe7\xc7\xe4\x94\x8b\x74\xf7\x8b\xaa\x99\x13\xb1\xd6\x13\x60\x3f\x78\xdd\xef\xf6\x5b\xc4\xfd\xe4\x0b\xbb\xa6\xcd\x51\xef\xea\xaf\x07\x8d\xa1\x9a\xcb\x38\x21\x29\x1b\x32\x0e\x55\x63\xaa\x00\x96\xa1\x00\x84\x93\xd0\xd2\x86\xac\x5c\xa7\x47\xa1\x2f\x20\x3b\xb6\xce\x3c\xf8\xfe\x17\xef\x1f\x9c\x39\xf3\xe0\xfb\xeb\xce\xdc\x0b\x5b\x49\x17\x5d\xac\x5c\xdc\x93\x34\x72\x9e\xcb\x29\x1e\xa2\x99\x2d\xf1\x64\xfb\xbd\x67\xd6\x69\xb1\xd5\x9b\xb6\xc2\x56\xfa\x98\x0b\xb9\xbe\xbc\xf4\xda\xa2\xb0\xaa\x6c\x6e\xd6\xf6\xce\xd9\x9d\x0e\x24\x38\xff\x4d\x11\xa6\x14\x44\x2d\xce\x62\x8a\x2a\x3f\xe4\x80\x2a\x35\xa8\x24\x11\xf8\x9e\x44\x33\x2d\xb7\x9e\x24\x67\xcf\x6a\x88\x0d\xf4\xb5\x9a\xf3\x2c\x39\x7b\xf2\xd6\xc3\xad\xbc\x68\x1b\xea\xd4\x55\x76\xfe\xa1\xb3\x52\xe7\x6f\xb6\x89\x7c\x6b\xfe\xfb\x7d\x99\x60\x7f\x3c\x9c\xfc\xcf\x43\x6a\x29\xef\xea\x77\x2b\x75\xee\x72\xc1\xb0\x8f\x1f\x02\xe7\xf0\x8e\x93\x56\xaf\x63\xd9\x8e\x1d\xcb\x1c\x5e\xeb\xc9\xae\x8f\xfa\x65\x89\xd6\x07\xda\xd7\x0c\x42\x23\x11\x82\x1e\x83\xf7\x9e\x6c\x08\xd2\x7f\xcc\x9f\x5a\x45\xd2\x48\x15\x02\x51\xb5\x7d\xf7\x64\x8a\x45\x76\x33\x94\xf4\x7c\x8d\xad\xdf\x94\xbf\x3b\xfe\xb6\xa3\xc8\x0a\x25\x67\xd6\x7f\x34\x0d\x5d\xbc\xce\x6c\xcf\xef\xe9\xf7\x6d\xce\x99\xed\x8a\x87\xd0\x2a\x73\xdd\xc5\xfb\x5f\xff\xe6\x0c\x5a\x4f\x80\xed\xe0\x9b\x50\x21\x9b\x07\xb5\x11\xbb\xb9\xab\xa3\xff\xd7\xc2\xbd\x7b\x4b\x97\xa3\xb5\xff\xb7\xbc\xa9\xdf\x2e\x13\x13\x7a\x21\x87\x9d\x97\xac\xb6\xf7\x74\x06\x99\x5e\xa4\xe2\x74\xc9\xa5\x85\xc0\xfd\xe7\x42\x38\x4b\xce\x6e\x4d\x2e\xd4\x7b\x0c\x03\x0c\xa0\x5f\xba\x92\x86\x28\x1e\x28\x51\x03\x77\x2f\x9b\x52\x08\x98\x51\x7f\x3f\xec\xbf\xff\xff\x58\x4a\x6a\x35\x78\xfd\xfe\xd4\x4a\x03\xe8\x2a\x75\x5e\xc3\xda\x55\xd7\xd1\x3a\xdf\x93\xae\xe5\x73\x0a\x01\x57\xd4\x6d\xdd\xfa\xb5\x52\x44\x88\x53\xeb\x08\x4f\xb8\x3c\xaa\x43\x2d\x68\x14\x9a\x40\x35\x33\x12\xe6\xbf\x49\x74\x04\xbf\x45\x88\xa8\x35\x44\x4e\xcb\x12\x82\xb4\x35\xc6\x5b\x99\x38\x1d\x90\x28\xb4\xe3\x05\x9b\x12\xe3\x05\x1b\xc4\x91\x15\x85\x43\x02\x1d\x96\xf0\xa4\x68\xfb\xdf\x0e\xf4\x93\x18\x04\x5d\x26\x6e\x6c\x10\x7b\xeb\xed\x47\x1e\x79\xfb\x2d\x88\x75\xdf\x96\xcb\xe5\x3a\xd7\x2e\xbe\xe7\x9e\xc5\x6b\x69\xcf\x8a\xcf\x5f\xbf\x61\xc3\xf5\x38\x7b\x4a\xcd\xc5\x29\x1a\xc0\xfc\xf9\x20\xf9\xd3\x09\xeb\x25\xa2\xe8\xeb\x02\xe9\x6d\xa8\x12\x9d\x6b\xd7\x3a\x45\xf2\xf3\xfc\x1b\x3b\x61\xc5\xce\x9d\xe4\x76\xf2\xcf\xfa\xc3\xbf\x3e\xf7\x50\xbd\x56\xe4\x24\x07\xac\x65\xec\x58\x0b\xe9\x86\x82\x6c\xa8\x7f\xe8\xdc\xaf\x0f\xd7\xab\xe3\x36\xb8\xc8\x0b\x6a\x7d\x6b\x43\xe3\xd0\x1c\xb4\xe2\x9b\xea\x5c\x00\x04\x1e\x09\x7c\x24\x56\xcd\x64\xb4\xae\x33\xda\x6b\x87\x79\x69\xe5\x94\x0b\x0d\x0a\x92\x74\xa0\x22\xb7\x40\xd4\x21\xc9\x4a\x2a\x89\x32\xd5\xea\x80\x05\xe2\x28\x95\x54\x62\xb4\x12\x07\x80\xbf\xa4\xa6\xb5\xb7\x4a\xc5\xe4\xcb\xa7\x7f\x46\x1e\x1c\xbc\xee\x9d\xdb\xc6\xe9\xf4\x37\xfc\x7a\xcf\xfa\x5f\x4e\xa7\xf5\xa7\x7f\xbc\xc6\xd0\x53\xfb\xa9\x27\x41\xec\xf7\x3e\x64\xbf\xf7\x61\x77\xee\x93\xc3\x0c\x98\xcf\xa4\x3e\xde\x73\x8a\x9c\x67\x3a\x4f\x81\xf0\xc9\x61\x86\x7c\x79\x26\xf5\x31\xdb\xd1\xbf\xae\xcd\xfd\x53\xee\x29\xd2\xed\xf1\x7f\xf8\x22\xbf\xf8\xc1\x4f\x36\xec\xf9\xe2\x0e\x8b\xd6\x06\xb3\xfd\x63\x8d\x9c\xab\x5f\x4b\xec\x66\x72\xc8\xa1\xb8\x2f\x3c\x44\x7f\x8e\x76\xcb\xfe\xc0\xcf\xa0\x35\xba\x71\x3f\x39\xdf\x2d\x80\x70\xea\x68\xb7\xec\x2b\xfe\x19\x79\x29\xba\x71\x3f\x62\x11\x5f\xd0\x6b\x8c\x44\xe3\xd0\x2c\xb4\xe4\xdf\x94\x61\x8c\xff\xff\x13\x4c\x94\x6e\x44\x2b\x4a\x5a\xf7\xe8\x50\x2f\xa3\x58\xd5\xda\xd7\x5b\xe7\xac\x82\xc4\xe7\x2e\x2b\xc2\x12\xf2\xaf\x1f\xfe\xea\xd9\x75\xfb\xbe\xd6\x66\x0f\x9e\xbf\x56\x76\x83\xe9\xd9\x73\xcf\xee\x3f\xf1\x7a\xa1\x55\xa2\x5c\x2e\x97\xcf\x81\x70\x6a\xdd\xc2\x7b\xee\x59\xb8\xee\x14\x53\xaf\x55\x3e\x7a\x79\x69\x3b\x9d\xfb\xa7\xdc\x93\xa4\xdb\x1b\xda\x32\xc6\xf2\xf5\xc6\x6a\x3b\x05\xa1\xef\x3d\x07\x16\x7f\x68\xcb\x3c\xda\x1a\xff\xbb\x50\x0d\x61\xa5\x5a\xfd\xea\x1f\x82\xce\x87\xea\xbb\x7b\xab\x1e\xc9\x3e\x54\x7f\x89\xed\x50\x23\x45\x8e\xef\xdf\x67\x0a\xbd\xc6\x92\xc2\xa5\xbd\x67\xa6\xcf\x62\xf2\x5b\xfb\xd1\xf7\x6f\xd4\xeb\xab\xf5\x1e\xc3\x8d\x63\x2e\xed\x4f\xc7\x1c\xd7\xfc\x8f\xbf\xff\xef\xfb\xd5\x0f\x6e\x34\x78\xf4\xd5\x7a\xfd\x4d\x63\x2f\xed\x5f\xc7\x1c\xd7\xfc\x8f\xbf\xff\x2d\xfd\x2c\xbe\xc8\xd2\x7e\xb6\x9e\xf2\x39\x4a\xc8\xe9\xc0\x2c\x55\xeb\xda\xd3\x99\x54\xdf\x47\x16\x34\x50\x27\x2d\x1b\x3d\xf9\xec\xab\x16\xb8\x90\x1f\x9c\x3b\x0b\xb1\x13\xe4\x83\x63\xbb\x3f\xdd\x67\x54\x25\x0b\x55\x7e\x1e\x9a\xa5\x25\xe2\x0d\x31\x29\xbe\xa1\xe5\x67\x96\x16\x70\xbe\x2f\x37\xcc\x16\x17\x39\xf5\xf1\x43\xe4\x8b\xfd\xa2\x65\xff\xef\xae\x3b\x08\xf6\x13\x56\xed\xb3\x1d\x9e\xa5\xdd\xf3\xba\x28\xbe\xae\x3d\x68\xd6\x61\x1a\xd0\x95\xbb\xb4\x1f\x62\x11\x12\x72\xec\xd6\x9e\xbc\x50\x14\x74\x2d\xd5\xfd\xc4\x25\x8f\xc2\xa1\x48\x61\xb4\x25\xc9\x89\x54\x8f\x12\x34\xd8\x03\x46\xd5\xf3\x6d\x84\x2b\x45\x91\x7c\xa8\xf7\xea\xab\x0c\x86\x53\xe4\xc3\x82\x8c\xff\x96\x34\x82\x72\xca\x60\xa8\xd2\x7b\xf5\x5d\xd9\xbe\x2c\xe1\x2b\xc5\xa4\x48\x3e\xd4\x02\x4e\x69\x52\xf0\x2c\x39\x7b\x02\xca\x7b\xcb\x47\xf3\x3c\xa5\xbd\xa5\xfb\x8f\x5f\xeb\x57\xe9\xb7\x91\x51\x71\x61\x0c\xd9\x0b\x04\x87\xd4\x19\x41\x3c\x80\x7b\x87\x01\xea\x70\x91\xa6\xe4\x2c\x39\x5b\xf8\xf8\x79\xa1\x5f\xe9\xd2\x01\x62\xfe\x5e\x6a\x13\xbe\x40\xed\xa9\x0a\xb5\x24\x7f\xe6\xb2\x77\x22\xc4\xe6\xd8\x1c\x12\x90\x8c\x10\x2a\x0c\x46\x51\x6f\x75\x8e\x07\x80\x45\xe4\x7c\xef\x38\x72\x4f\x5f\x6d\xfd\xe2\xfd\x83\xd0\xaf\xcf\xc4\xa9\x3e\xff\x99\x33\x0f\xa2\x7e\x38\x6c\x91\x7e\x5c\x9b\xb6\x44\x26\xac\x0e\xdf\x33\xd4\x94\xd0\x0f\x61\x67\xc2\xd6\x0b\x1c\xf7\x48\x38\x1e\x0f\x93\x4d\xaf\x06\x7e\x5b\x33\x64\x73\xeb\xda\xbd\x0f\xbe\xf6\x5a\x3e\xa8\xfa\x71\xb9\x78\xf8\xc2\xb1\x70\x1c\x4f\xfc\xfd\xed\x75\x75\xf0\x53\xfd\xa1\xfd\x8f\xfc\x3e\xff\x83\x78\x98\x9b\x12\x8e\xa3\xc2\xbb\x38\x55\xbe\xb5\x23\x64\x4b\xaa\xf3\x02\x56\xa2\xa4\xa3\x21\x25\x66\xe6\x2d\x40\x0d\x19\xed\x99\xbe\x65\x77\xcd\x16\x9c\xa5\x8b\xa6\x14\xd8\x5c\xd3\xda\x56\x33\xa3\x76\x1d\xff\xc9\xe2\xfb\xc1\x7a\x4c\x99\xb0\xfe\xf8\xe2\x21\xd7\xf9\x0d\x11\x63\x40\x2a\x8f\x47\xcd\x7a\x4b\xc5\x0c\xa1\x64\xc9\xb8\xe6\x21\xd3\x66\x64\x33\x73\x5a\x6b\xbd\xa6\x5f\x3e\xf6\x1a\xf9\xbb\xdb\xef\x0e\x48\xd8\x92\x18\x5b\x21\x31\x8f\xac\x78\xf1\xe6\x25\xc9\xdd\xe4\x50\xc7\x33\xc7\xb6\x8f\xce\xd6\xc5\x6e\xab\xb8\xa2\x62\xc2\x88\x38\x67\xb8\xaf\x78\xd6\x6f\x61\x46\x60\xe0\x92\x89\xfb\xc7\xb7\x0c\xba\xd0\xd2\x3a\x31\x3e\x65\xc9\xba\xa5\x35\x3f\x78\x89\xe4\x5f\xad\x9c\x30\xa0\x42\xef\x9b\xc1\x58\x26\x2c\xbf\xb2\x67\x5d\x7a\x33\x8f\xb8\xeb\x50\x05\x6a\x41\xe3\x11\x42\x1a\x32\x09\xb5\x3d\xa7\xf3\xec\x8c\x46\x47\x26\x51\x6b\x44\xa0\x19\xa2\x38\x43\x52\x22\xce\xf4\xc7\xb9\x15\x32\x92\xbd\x07\x86\x2c\x1c\x8a\x71\x22\x35\x3e\x62\xde\xf4\x3c\xcc\x61\x9b\xf5\xaa\x9a\xfa\xdd\xf3\x6f\x69\x1f\x0e\xcc\x30\x97\x8f\x77\x09\xa2\x45\xa7\x8b\x0f\xe5\x42\x43\xea\xe6\x16\x19\x2c\xab\xb6\x7d\x7e\x74\xc1\x82\xa3\x9f\x93\xcf\x8f\x2e\xd8\x38\xf6\xcb\xfb\x43\x10\x07\xf9\x8d\x8d\x1b\xdf\x20\x9f\xdf\xfd\xa3\x63\x64\xee\xde\x15\x1b\xdf\xc0\xf1\x69\x7a\xce\x10\xac\x88\xa5\x5a\xaa\xf6\xaf\x5a\x3e\x55\x37\x73\xb0\xc4\x98\x9c\x8e\xbd\x82\x73\x84\x41\xd0\x8d\xc8\xa6\x06\x08\x64\x6c\xe1\x21\x0b\x8e\x7e\xbe\xed\xcc\xe1\xcf\x47\x2f\xe1\x16\xa9\x0f\x21\x6f\x93\xcf\xdf\xd8\x38\xe7\x3a\xb8\xe3\xf1\x9f\xdf\x0d\xf2\x1b\x94\xd7\xa5\x80\x3f\xa6\xe1\x05\x89\x74\x8d\x38\x86\x2a\xd4\x19\x4b\x26\x98\x0a\xda\x82\xa9\x60\xef\x56\xa5\x7e\x6e\x7b\x2f\xce\x08\xe5\xa3\xa1\x47\x8e\x45\xdd\x48\x3d\xf8\x92\xba\x71\x75\x75\xe3\x2e\xb8\xfa\x5d\x68\x7f\x77\x9d\x47\x02\xd2\x8e\x1c\x05\xa5\xb9\x8b\x06\xb0\x25\x3d\x2e\xac\xc5\xcc\x97\x90\x1c\xe4\x30\xea\xfb\xed\xd5\x3b\x52\x2c\xee\x0a\x34\x06\x21\x54\xa2\x58\xd3\x25\x92\x15\x0a\x43\xd8\x7e\x56\x24\x3d\xfd\x40\xb0\xc7\x7a\x84\x12\x9c\x3b\x7b\x16\x93\xb8\x44\xcf\x0c\x26\x11\x97\x29\x33\xde\x5c\xf2\xf2\xa7\x9f\x42\xcb\xa7\x38\x0b\x1d\x26\x51\x34\x91\x43\xa2\xa9\xd3\x24\x92\x43\xea\x05\x74\xd0\x8b\x7c\x49\x7b\x12\xd0\x90\xc5\xdd\x07\x36\xed\x17\x9c\x25\xe9\xb6\x85\xcd\xa2\x63\xec\x9d\x8f\xdf\x39\xd6\x21\xee\x9a\xfc\xab\x64\x3b\xce\x15\x00\xfe\xc9\x03\x5f\xbf\x5b\x7b\x6e\xbe\x33\xd9\xfe\xa7\xf8\x0d\x9b\x52\x0b\xd7\x2d\x98\x3b\xb8\xd4\xd6\xdc\xdc\xdc\x6c\xeb\x68\x4f\xf6\xd8\x44\x0b\xff\xa2\xf9\x4b\xa0\x29\xfd\xf2\xa7\xd6\x44\x0b\x68\x68\x19\x1a\x16\x60\x2a\xd9\x4a\x9b\x58\x2b\x50\x5a\x3e\x8d\x9c\x4f\xad\xaf\x9c\x40\xe1\x16\xfa\x67\x54\x2a\xa1\xd9\xa4\x83\xaf\xbe\x7c\xfe\xf0\xbc\x5e\xbf\x57\x6f\x32\xeb\xcf\x9f\xd7\x9b\x4d\xfa\xbd\x7a\xd5\x71\x99\x4f\xde\xf9\xc3\x68\x74\xa2\x53\xbe\x24\xc3\xf7\xc0\xc8\x7b\x1c\xa2\xcf\xef\xf3\x44\x7b\xf3\x9b\xff\xd5\xb7\x3f\xa4\xcf\xe7\x87\xd1\x74\x2a\x3a\x91\xe9\xcb\xfc\xe6\xcd\x36\xde\x5b\x1d\x4c\x47\xfb\xd9\xc5\xda\x91\x87\xca\x2f\x3a\x54\xd2\xec\xf4\x0b\x9f\xb0\xa7\xea\x05\x7b\x2d\x69\x00\xf1\x9d\x1e\xe5\x22\xba\x80\x2e\x22\xba\x08\x84\xb3\x07\xde\x3b\x70\xe0\x3d\x6e\xca\xa7\x0f\xe4\xb3\x1e\x05\x23\xc5\x43\xb2\xa0\x8a\x79\x8a\x75\x46\x24\x35\xf4\x40\xf6\x81\x4f\x15\x0f\xc9\xf5\x61\xe9\xaa\x72\x4c\xa2\x56\x2e\x4c\xc2\x19\x14\x82\xce\xa0\x5e\xad\xeb\xb1\x60\x2a\xc1\x50\x93\x17\x31\xcc\xa3\xce\x4e\xf2\xa7\x0c\x8c\x20\x0b\xc9\x41\x72\x90\x2c\x84\x11\x19\xf2\xa7\xce\x4e\x40\x30\x18\x36\xc3\x60\x82\x56\xfc\x82\x47\x24\xdb\x99\xeb\xec\xee\x64\xd4\x13\x74\xe6\x11\x83\xba\xb2\xd0\xc7\xab\x8d\x0a\x7d\x4d\x58\x95\xcf\xac\x2a\x9f\x05\x59\xa2\x9f\xaa\x55\xa3\xd5\x8e\x24\xec\x3d\xcc\xa2\xb6\xa0\x8d\x55\xc7\xfd\x5d\x4f\xbe\x6f\xb5\x4a\x5d\xe7\x24\xab\xf5\xfd\x27\xbb\x40\x38\xf5\x17\x4a\xe2\xc4\xa0\xae\x1c\x8f\x9e\xdb\xdd\x9d\xdb\xf1\x0c\xf7\x86\xa5\xb4\xd4\xf2\x06\xf7\xcc\x0e\x26\xb7\xfb\xb9\x0b\x9d\x94\xb3\x09\xde\xc1\x88\xa0\x4b\x79\xa6\xb4\x77\x57\x68\xab\x11\xdf\xfc\x7e\xdc\xef\xfd\xe8\x3f\xa6\xe5\xd7\x1a\x67\x69\x36\x7f\x8e\x21\x1a\xa5\x69\x36\xdf\xf9\x2d\xc9\xd2\xa8\x5e\xe1\x65\x35\x59\xf9\xfe\x17\x3d\xba\x9a\x1b\x04\xc4\xad\xa7\xfc\x2b\x3e\x8a\x79\x63\xa3\x1d\x44\x81\xce\x3b\x11\x97\x41\x92\xf5\xd8\xe6\xe0\x43\xb1\xa8\xda\x57\xeb\x41\xf3\xc4\x93\xdd\x2e\x9b\x95\xd4\x38\xfd\x0e\xd1\x1c\x80\x8b\x4c\x16\x4b\xf9\x2f\xd8\xe5\xbe\x01\x32\x19\x86\xdd\xf9\x8b\x95\x64\x33\x0c\xb1\x85\xcd\x45\xd8\xcf\xb2\x33\xbb\x96\xbb\xc3\xba\xcf\x0d\x35\x32\x7b\xb5\xc3\x67\xb9\x88\x98\xc5\xdd\xf7\x83\x01\xb7\x75\xfd\xda\x5d\x6c\xfa\x88\xf9\x2d\xd3\xfd\xe2\x30\xbc\x19\x5b\x7c\x3c\xf9\x12\x5f\x82\xaf\x6e\xb9\x1c\x5f\x3d\x68\xbb\x1c\x53\xfd\x02\xba\x0c\x49\x9d\x3d\xa6\x59\xbf\xb9\xd0\xa4\x8b\xbc\xee\xfb\xdc\xc5\xc2\x3e\xe5\x1a\x34\x04\x8d\x46\xdd\xc0\x83\x1d\xbc\x10\x85\x38\x34\xc1\x30\x18\x0f\x73\x60\x05\x6c\x80\x27\xe0\x65\x38\x0b\x9f\x03\xc1\x26\x84\x38\x33\x50\x4c\xb5\x74\x26\x2d\x71\x01\xd0\x98\x98\x63\x0a\x9f\xa1\x6e\x4a\x6a\xc6\x6b\x71\x52\x49\x35\x0e\x24\x42\x42\x01\x5c\x27\x56\x50\x67\x26\x95\x4c\x35\x08\x2d\x38\x00\x20\x09\x92\x53\xd2\x9e\xc8\x46\x29\x49\x75\x26\x9d\x51\xd4\xc9\x45\xe1\x37\xa9\xcd\x6f\xe5\x54\xa1\xdb\x4b\x67\x5a\xb0\x24\x27\xd4\xae\xae\x05\x32\x4a\x4c\x89\x25\x33\xd5\x85\xfb\xd2\x92\xec\x08\x30\xb2\xa4\x3e\x42\xa0\x18\x4b\xd5\x6c\x2c\x02\x92\x2c\x65\x12\x2d\x4c\x2b\xb4\x80\xac\x2d\xa9\x82\xe0\xe4\x05\x5e\x08\x80\xac\x46\x4a\xb4\x40\x80\x86\x50\x14\xd4\xb0\x43\x48\x6b\xef\x74\x4a\xea\xaf\x20\xc9\x69\x70\xa8\xbf\x6a\xce\xd4\x49\x92\xc6\xa2\x18\xe3\x85\x50\x4c\x92\xe3\x99\xb4\xc2\x51\x43\x0b\x85\x72\x67\xc9\x4a\x3a\x53\xab\xc4\xcc\xea\x4c\x33\x9d\xe1\x2d\x90\xe2\x65\x5a\x4e\x01\xc8\xa8\x09\x46\x05\xfe\x84\x54\x92\x51\x84\x14\x2f\x69\xfe\x0a\xd7\x02\x4a\x2c\xc5\x87\x35\x1a\x93\x28\x4f\x19\xae\x5b\x20\xc3\x0b\x92\x20\xb1\x72\x3a\x92\x51\x32\xc9\x16\x68\x06\x27\x7d\x33\xc5\x0c\x8c\x99\x75\x61\x3e\x66\x66\x04\x3e\xcc\xc7\x34\x1f\x75\xc2\x2f\x31\xe9\x94\x5a\x54\x66\x90\xb5\xcf\x43\x0d\x76\xd5\xbb\x1c\xbc\x53\xa2\x70\x53\x61\x5e\x96\x64\x96\x52\xd4\xf3\xf4\x9e\xb0\x33\x1e\x55\xb3\x25\xa4\x53\x1a\x5c\x9e\x92\xa2\x8f\xe2\xd2\x1a\x36\xac\x43\x4b\x26\x7c\xa2\x53\xec\xee\x14\x86\x09\x5e\x59\xe2\x92\x82\x22\xba\x53\x80\x27\x7a\x25\xa9\xde\x34\x35\x54\x35\x72\xcf\x80\xd2\x9a\x0b\x6b\x4c\x53\x34\x67\x35\x7e\x1d\xca\xc2\xde\x50\x5a\x49\xfa\xb8\x55\x63\xc7\xad\x5a\x75\xee\x8a\xbf\x6d\xf1\xae\xbc\x76\xfd\x78\xfc\xa5\x4e\x14\x60\x66\x2e\x3d\x60\x9a\x94\x1f\x9f\xff\xb1\x3c\xb5\x76\xca\x73\x80\x39\x51\xc7\xbb\xcd\x5e\x41\x6f\xf4\xf9\x03\x26\xd9\x17\xf6\xd8\x1d\x46\x21\x35\xcd\xa8\xd7\x5b\xc6\xe0\x90\xe2\xe3\x4c\xd5\x66\x06\x1b\xca\x0c\x16\x8b\x3c\x04\x5a\x56\xfb\x4a\x9c\x3a\xeb\x48\xb9\x81\x61\x30\x2b\x70\xde\xda\x01\xf1\xd2\xcd\x35\xcd\x8b\x6e\xbd\xde\x51\x9e\x0c\xb6\x14\xe1\x89\x90\x9a\xdf\x34\x39\x02\x9c\xc0\x62\x0c\x4c\x83\x3c\xc2\x2e\x38\x4b\x7c\x2b\x9b\x86\xb9\xcc\x36\x63\xb9\x1e\x58\x6b\xa5\x89\xf3\x29\x21\x3c\xd6\xac\xd7\x15\x4d\x4b\x19\x04\x70\xd8\x3d\x61\x9f\x6c\x0e\x7a\xbc\x46\x83\xce\x67\x92\xc9\x3f\xf4\x13\x02\xac\xd7\xe7\x28\x19\x13\x76\x9b\x06\x07\x4c\x1c\x53\x97\xb0\x8c\x0c\x98\xcb\x8d\x4e\xc9\x1a\x38\xff\x42\x60\x82\x3e\x28\xfa\xbc\xa5\xfe\x21\x26\x77\x38\x6a\x49\x64\x58\xfd\xb3\xe6\x46\x31\x52\x55\xed\x71\x33\x67\x75\x36\x86\x31\xd9\x4a\x2b\xc1\x45\xce\xfd\xfe\xc8\x91\xdf\x1f\x49\x2f\x5d\x06\x82\xc1\xbf\xbd\x58\xcf\x72\xe4\x4b\x1d\xc3\xe2\xf7\x30\xcb\xf3\xc6\xd0\x75\xe4\x2e\x6b\x59\xbd\xc5\xce\x30\x06\x6e\xe8\xcb\x4c\x74\x17\xc8\x47\x8e\x83\xf3\x60\x90\x01\x6c\x1b\x64\xf1\xd4\x25\x8a\x39\x56\x30\x60\x5e\x2f\x14\xe9\xac\x3a\x91\x5d\x56\xcf\x16\x05\xac\x3e\x9e\x79\xc2\x85\xd3\x35\x95\x45\x3a\x9b\xbe\xc1\x0f\xe3\x19\xdb\x90\x58\xd9\xa6\x69\x5c\x78\x47\x3a\x31\xc5\x24\xb3\x3f\x7a\x65\xfe\xe1\x79\xbc\x8c\x8b\xf5\x45\x95\x06\x11\x30\x23\x4e\xc6\x0e\xbc\x90\x9c\x68\x1f\xa7\xd3\x0d\xcc\xbe\xf3\x0e\x00\x7b\x88\x75\x99\x45\x60\x2c\x96\x72\xb3\xbe\x18\x5b\x8b\xde\x7c\xe2\x27\xb8\x83\x9b\xb6\xb1\x5c\x19\x6a\x63\x0c\x53\x12\xe9\x1d\xfb\xac\x51\x41\xef\x16\xa5\x41\x1c\x9b\x70\xf6\x73\x4f\xf3\x0e\xd4\x9b\xc2\xc1\xea\x2b\x39\x6e\x72\xa8\x9f\x9b\x1d\x64\xd1\x55\x79\xc3\xf1\x0a\x59\x1c\xb9\x74\xe9\xed\x4b\x3f\xbc\xb2\x6a\x70\xd3\x08\xbe\xf4\xca\x0b\x1f\x19\x8b\x65\x5b\xdd\xea\x36\x8c\x6b\xca\xdd\xee\xb2\x01\x98\x39\x38\x51\xb2\x17\x1b\x0d\x7a\xc9\xef\xd7\x1b\xcc\x0e\xb3\x5f\x57\xe4\xe3\x04\xd6\x32\x02\x1b\x86\xa6\x94\x8a\x96\xa0\x2d\x6a\x70\xdb\x39\x3b\xc3\x02\x07\x46\xbe\x94\xe1\x59\x1c\x2c\x8e\xac\xaa\xdb\x9a\xb2\xca\x7e\xf0\x58\x5d\x66\xc6\x8c\xab\x7d\xac\xbd\xba\x21\x35\xc2\xa4\xb3\x98\x74\x66\x66\x2b\xf9\xd7\xa4\x1b\x0c\x22\x63\x76\x59\xcc\x66\x9f\xcb\x96\xdc\x5a\xbf\x2a\x5c\x12\xc4\x06\x5c\xc6\x15\x01\x07\x1c\x63\xe7\xec\x2e\x9d\x62\x2b\x69\x2d\x2d\x4b\xb5\xe9\x71\xad\xcb\xc2\x0a\x9c\xaf\x48\xef\xb3\xda\x4d\x7a\x83\x2f\xe0\xd4\x31\x8f\xfa\xdd\x25\x0b\xa2\xd7\xf8\x45\x76\x7d\xf9\xee\x06\x53\x89\xd9\x9c\x5d\x68\xb5\x18\x60\xed\x16\x66\xc8\x75\xb5\x0b\x4a\xdc\x7e\x3b\x2b\xfa\xaf\xd9\x57\x6c\x6e\xd8\x5d\xce\x5b\xac\x0b\x06\xda\x06\x6e\x59\xc9\x9a\x45\x98\xbe\x9c\x89\x29\x37\x89\x76\x41\xe7\xd8\xd9\x84\xf1\xce\xc3\x57\xaf\x3b\x7c\x78\xdd\xd5\x44\xc1\x18\xbc\xeb\x05\x33\x18\x99\xe1\x83\x9f\x65\xa7\x4d\x13\x81\x71\x4c\x9a\xc0\x59\xf0\x6b\x8d\x1b\xdc\x3a\xde\x6e\xbd\xdd\x8f\x77\xc8\xa6\x9b\x7e\x92\xa9\x7d\xf9\x6e\x93\x13\x33\x0c\x00\x60\x01\x66\x94\x2b\x31\x5e\x67\xaa\xe5\x74\x3c\xc7\x60\x0c\xa0\x77\xd8\x44\x23\x83\xc1\x56\xdf\xaa\xd7\x55\x9b\x4c\xfe\x08\xcf\xe2\xfc\x2e\xb3\x75\xd8\x7a\x63\x51\x6a\x79\x3a\x35\x0e\xe3\xa6\x8f\x5a\xeb\x56\x37\x27\xf7\xce\x63\xf5\xc0\x63\xbb\x28\x1b\x4d\xc6\x89\x83\x43\x6f\x39\x9d\xb7\xd5\x86\x25\x86\x71\xfa\x9a\x72\x50\x93\x1e\xa4\x04\x61\x74\xbb\xce\xa6\x77\x39\xec\x2c\xc7\xea\x5e\x98\xd3\x78\x63\x7a\x79\xaa\xc8\xb8\xa1\xcd\x6a\xae\x6d\xc2\x78\x9c\x36\x66\x18\xac\x07\xee\x79\x3a\x32\x6f\xa4\x7c\xde\x97\x58\x29\x40\x80\x2b\x82\x44\x3c\xc0\xaa\x22\x49\x68\xe1\xaa\x19\x81\x8f\x54\x0b\xdc\xdf\x3b\xf6\xce\x9b\xb7\x37\xbf\x76\xde\xde\x8e\x8e\xbd\xf9\x19\xf5\xcb\xf7\x5c\xff\xa3\xb7\x20\x06\xf5\xbf\xd8\xf7\xf3\x3b\xe7\x55\x31\xe5\xc3\x56\x6c\x19\x7d\x6a\xa1\xff\xff\x31\xf7\xde\xf1\x51\x5c\xf7\xfa\xf0\xf9\x9e\x69\x5b\x67\xfb\x8e\xb4\x92\x56\x5b\x67\x55\x57\xd2\x56\x09\x49\xab\x45\x88\x2a\x01\xa2\x0b\x84\x84\x68\x46\x88\x26\x9a\xc1\x18\x9b\x35\xe0\x0a\xd8\x18\x03\xae\x18\xc5\xd8\x71\xb7\x83\x6f\xe2\x5e\x64\x27\x71\x8b\x4d\xec\xc4\x3d\x2e\x72\x8d\x49\x62\xc7\x71\x62\xc7\x46\xda\xd1\xfb\x99\x33\x2b\x21\x04\xb9\xc9\xef\xde\xfb\xc7\xab\x8f\x76\x4f\x99\x33\x33\x67\xce\x9e\x39\xf5\xf9\x3e\xcf\xa2\xb6\x8e\x09\xa2\x6e\xfa\x4d\xd2\xf1\xbb\xa4\xf7\xdf\x7f\x6a\xe7\xc6\x86\x06\x77\x59\xb1\x7c\xd2\x62\x72\xea\x62\xa6\xa2\x66\x7e\x63\xb8\x40\xe0\x19\x8d\xe0\x2a\xab\x9c\x34\x63\xf9\xea\xb1\x47\x16\x84\x37\x2d\x3a\x6f\x46\x73\x4d\x38\xdf\x48\x61\xa3\x33\x12\x9e\x52\x3d\x3b\x3e\x63\x08\x73\x90\xd1\xe5\xca\x27\xac\xa0\x8d\x68\x05\xda\x42\x94\xb9\x46\x2a\x15\x89\xbe\x51\x34\xcd\x96\x90\xcd\x64\x2d\x06\x4f\xd4\x14\x09\xd3\x64\xb2\xc8\x0d\x2f\x27\x04\x21\x1a\xc1\x2e\xda\x3c\x64\xf3\x6c\xb1\x29\x98\x3b\x85\xe4\x3a\x0f\x86\x43\xa2\x8b\x1d\xcd\x85\x48\x17\x4a\x0f\x48\xaf\x7c\xb4\x7b\xf7\x47\x10\x81\x99\x10\x91\x7d\xe9\x35\x67\x33\x3d\x6f\x30\x1a\x5d\x46\x23\x5c\xd8\xd5\xe8\xcd\x23\x53\xfc\x3c\xef\x0c\xc5\xb2\x79\xc8\x54\xfa\x77\x24\x7a\xd7\xe3\xbb\x88\x7b\x42\x7a\xff\x04\xd5\x21\x3a\x06\x52\x43\x84\xea\x4c\xef\xee\x8f\xa4\x57\x46\xdd\xed\x57\xe7\xe0\x85\x4e\x4f\x33\x4a\xf2\xbd\xfa\x8c\xc9\xc6\xa8\x77\x8c\x69\x03\x6f\x36\xf3\x1b\x4c\x63\xbc\x51\xaa\x71\x94\x61\xb6\xf4\xb5\xb2\x9c\xd6\xb6\x6b\x57\x9b\xe2\x3b\x70\xe2\xc4\xc0\xd5\x98\xb0\x22\x12\xaa\xde\x21\x7b\x32\xb5\xc2\x2b\x2f\x90\x71\x9d\x3c\x17\x0b\x9b\xbc\xa3\x8a\x22\x4a\x46\x53\xb6\xd1\xd0\xaa\x90\x9d\x4b\xfd\x98\xe2\x50\x2a\x65\xe6\x7f\x20\x20\x78\x8e\xd8\xc8\x37\x46\xdb\xeb\x7f\xe8\xad\x6f\x6f\xaf\xe7\x92\xf5\xed\xd1\x46\x1a\xc9\x63\xd9\x74\x2f\xa4\x94\x05\xfd\x01\xc5\xf6\xbd\x47\x4a\x45\x1b\x7b\xe4\x64\x14\x49\xdc\xd3\x88\x46\xe5\x29\x67\x38\x4f\x99\xf5\x88\x51\x59\xb0\x65\xc3\x59\x59\x35\x01\x62\x10\x26\xf6\x41\x23\x73\x31\x2a\x8b\x14\x4a\x23\xdc\xdb\x18\x1d\x95\x85\x74\xc7\x99\x79\x04\xd7\xff\x45\x7e\xa8\x14\x8d\xfe\xff\x94\x1f\x8c\x98\xff\xbb\xf2\xc1\xc3\xf9\x11\x50\xf1\xe9\x95\xa3\xff\x24\x27\xaa\xff\x3e\x17\xd4\x7f\x74\x7f\x40\x68\x90\xa1\x2f\x64\x11\xca\x25\x2c\x9e\xac\xd7\x6d\x19\x92\xca\x24\x8a\x26\x62\x46\xf9\x5d\xa0\xd7\x10\xf9\x8f\x9d\x2f\x69\xac\x59\xc7\xb3\xcb\xb5\xcf\x48\x2f\x5a\x1c\x3a\x5d\x41\x81\x4e\x97\x63\x86\xaf\x9c\x81\x02\xc9\x97\x5d\xae\x6d\xd4\x58\xb3\xe0\x57\xd2\x8b\x16\xc6\x54\xc4\xf4\x15\x99\x18\x8b\xc2\x5f\x4d\xa5\x58\x44\x34\x0a\x5c\x36\x53\xd8\xe6\x35\x59\xdd\x61\x9b\xd7\x15\x60\xdd\xde\x68\xd8\x15\x35\x79\xa3\x61\x53\x84\xf8\x85\x98\x3b\x6c\xa3\x92\x52\x6f\x2a\x05\xc9\x64\x52\xfa\xa6\xbb\x5b\xfa\x26\x99\x84\x64\x2a\x25\xf5\x26\x93\x60\xec\xee\x06\x63\x92\x49\xf5\x49\x1d\xa9\x74\x5f\x5f\xea\xc0\x81\x54\x1f\x76\xa5\xa0\x87\x78\x95\xe2\x1c\xb2\x6b\x18\x52\x7b\x28\x26\xac\x17\xd5\x64\xe5\xd4\x6b\x0a\x9b\x08\x10\xc9\x24\xbf\xa9\x6e\x9b\x3b\xea\x66\x6c\x44\x84\x39\x6a\x8a\x7a\x6d\xfe\x68\xd8\x44\x10\xad\xa6\xb0\xa2\xa7\x9b\x31\x58\x97\x5d\x62\xbf\x6e\x53\xa1\x54\x4a\x4a\xf5\x23\x29\x95\x4a\x41\x8a\x41\x90\x1a\x44\xa9\x1f\x51\x2a\xc5\xa2\x54\xaa\x5f\x71\x25\x04\xa9\x81\x94\x94\xa2\x52\x69\x84\x53\xe9\x14\x8d\x06\x91\x94\xa2\x53\x03\x99\xb3\x68\x04\x43\xfa\xb8\xa7\x90\xfc\x4d\x67\x34\x1f\x64\x5f\x1a\x91\x1a\x94\xc2\x72\x2d\x92\x4f\xc8\x70\xe7\x20\xb5\xfc\x4c\xf9\xc3\x6b\x44\xe1\x8c\x86\xc5\xbc\x33\x9f\xea\xcc\x67\x33\x79\x87\x9e\x10\x46\x3e\xa5\xd7\x16\xf6\xbb\x4f\x3f\x2a\x44\x89\x3a\xb5\x5c\xcf\xa2\xee\xcc\xa5\xc2\x36\x77\x54\x4d\x9e\x55\x7e\x92\x94\x94\x52\xb2\x4e\xa5\x40\x76\xc8\x53\xa7\x51\xea\x54\x2a\x95\x62\x52\xa9\x54\x7f\x8a\x4a\xa5\x52\x03\x8a\x2e\x85\x1c\x31\x74\x0a\x45\x68\x8c\x95\x73\xe5\x0f\x26\xae\x94\x11\x07\x26\xdf\xfd\x99\xa2\xc0\x64\xfb\x23\xad\x1c\x41\x78\xe8\x9e\x72\x01\x9c\x9e\x0b\x9a\x50\x16\x79\x6b\x47\xbc\x1d\x26\xb7\x87\x15\xdc\x72\xad\xe5\x68\x34\xd0\x51\x50\x59\x59\xc0\x24\x0b\x2a\x89\x44\x31\x5c\x64\x08\x3d\x1a\x9a\x09\x2e\xa9\x43\x89\xad\x2c\x18\xe8\xa8\x9c\x34\x33\xf4\x68\xc8\x80\x46\xda\xda\xb0\x44\x57\x19\x81\xd7\x16\xab\x83\x98\x7f\x68\xf5\x43\x6e\xbb\x0d\x70\xda\x1c\x8a\x58\x0a\x6d\xfd\x21\x4f\xf7\x98\x4e\xfa\x16\x5c\xfd\x88\x4a\x55\xc2\x8b\x05\xb9\x8f\xe6\x76\x14\x0c\xa0\xa1\x5b\x03\xfa\x41\xa3\x7b\x4c\x77\x84\x4a\xf5\x23\x70\x15\x54\x52\x3d\x03\xa8\xa0\x23\xf7\xd1\xdc\x82\x4c\x26\x86\x34\x9d\x86\xf8\xb3\xb2\x50\x00\x8d\x45\xb3\xd1\x32\x62\x75\x39\x4c\x48\x18\x1b\xf6\xdb\xc3\x76\x86\x88\xa5\x78\x3d\x01\x9b\x13\xf2\xc1\xe5\x8f\xb2\x1c\x2b\x46\xc8\x7c\x31\x08\x65\x20\x12\x4b\xe6\x38\x31\x5d\x8b\x2a\x8a\xdb\x1e\xd1\xeb\x36\xb9\xcf\x36\x75\xe2\x8e\xe6\x0b\x2a\xcd\x8d\x37\x6a\x54\x82\xde\x29\x50\xba\x3d\x7b\x28\x2d\x08\xfd\x2b\x3f\x6b\x1a\xb7\xfa\x82\xe8\x15\x85\x45\x30\x09\xbf\xbc\x74\xf9\xea\x6d\xdb\x56\x2f\x5f\x5a\xde\x99\x9b\xbb\xe3\x91\x25\x25\x25\x4b\x1e\xd9\xb1\x9c\x9a\x3c\xb7\xbe\x2a\x39\xb3\x9e\x32\x33\x52\x15\xfc\x79\xca\xa2\x33\x29\x8a\x22\x11\x3f\x83\xf7\x62\xe6\xc1\x90\x87\x86\x4b\x80\xee\x83\x88\xf4\xca\x98\xc9\xd5\xdd\x06\x23\x80\x7b\x7d\x84\x53\x2d\x79\x7c\x89\x8a\x0b\x77\xeb\x0c\x18\xb3\x05\xcd\x1d\x9b\x3a\x9a\x0b\x58\xfa\xea\xd8\x78\x86\x52\x8d\x0b\xc6\xeb\x29\x90\xf0\x64\x2a\x76\x06\xff\x10\x33\x5c\x4e\x0c\xd2\x22\x07\x0a\xa2\x84\x5c\x03\x78\xb0\xda\x7d\x11\x31\x60\x8a\x21\xa2\x7c\x16\x24\xd2\x9d\x2e\x1a\x88\x21\x37\xb1\x50\x35\xd3\x61\x77\x28\x81\xcf\xb2\x9a\x5a\xd0\xb5\x7b\x37\x5e\xb2\xbb\xab\x0b\x5a\x8f\x48\xdf\x1e\xdd\xf2\xee\x91\xb6\x23\xc0\x43\x02\x78\x9c\xbb\xee\xd1\xbf\xef\x92\x7e\xff\x33\xe9\xdd\x07\x1f\x80\xa2\x07\xa0\xf4\x92\xef\x1e\x5d\x07\x2d\x23\x9f\x12\x02\xf8\x17\x85\x4f\xfd\xe9\xa9\xa7\xfe\xf4\x54\x61\x7a\x4a\x21\xbc\x2e\x3d\x27\x7d\x7b\xa4\xed\xc8\xbb\x5b\x8e\x02\x7f\xe4\x88\xd4\xb4\xe7\xbb\x9f\x76\xdc\x26\xbd\xf5\xf8\xbd\xd2\x1f\xee\x59\x7e\xf7\x5f\x28\xf6\x4c\x1e\x2c\xea\x8c\xb1\x5a\x35\x42\xcc\xa8\xb6\xfd\x2c\xfe\x68\x9b\xf7\xb4\x01\x9b\x9d\xf0\xf6\x9d\xe6\xa6\x4a\x59\xf4\xfd\xbd\x7a\x8b\x45\x4f\x27\xf5\x96\x54\x7b\x7d\x3f\x69\xea\xe9\x64\x7d\xbb\x94\x1a\x3e\xd6\xd3\x33\x14\xd9\x21\x27\xcb\x44\xd3\x53\x4f\x27\x6e\x87\x44\x4f\xcf\xd0\x91\x54\x26\x2e\xa3\xf7\xaa\x92\xdb\x6e\x8c\x18\x14\x45\xb5\x68\x0e\x5a\x83\x90\x1a\xdc\x6a\x70\x03\x0f\x9c\x69\x78\xfd\x77\x78\xd5\x37\x08\x81\xe1\x00\x61\x19\x1f\x4a\x42\x0f\xad\x69\x29\x3b\x2e\x04\x58\x18\x0b\x09\x4e\x9a\x19\x1d\xc1\xf6\x4a\x29\x0a\xfd\x28\xb7\xa0\x08\x7e\xc1\xd7\x15\x60\x32\x0a\x3b\x45\x7a\x37\xdc\x51\x50\xc7\x4b\x36\xd2\x83\xfd\xd9\xb6\x64\xfb\x12\x1b\xfc\x99\x6c\x1f\xd6\xd5\x97\x95\xd5\x97\xd1\xfb\xdb\xae\xbe\x6e\xf7\x75\x57\xb7\x4d\xd8\xb0\xac\x93\x36\x37\x99\xe9\xce\x65\x1b\x26\xf4\xa3\x73\xc5\xd2\xc9\x74\x12\xf7\xa6\x93\x54\xaa\xa0\x8e\x3f\xf5\xdd\x69\x7a\x22\x46\xcb\xd7\x15\x10\x5f\xd5\xc4\x89\x55\xc4\x63\x2c\x93\x2f\x3f\xb0\x78\xf2\xa6\x7a\xb7\xbb\x7e\xd3\x64\xed\xde\xd7\x1f\x7e\x9c\x73\xbb\xb9\xc7\x1f\x7e\x7d\xaf\xf6\x9c\xb1\x23\xd7\x38\x4b\xd1\x54\x84\xc0\x88\x39\xbb\x79\x08\xf2\x70\x5a\x82\xcb\x68\x8e\x8b\xd8\x34\x62\x13\x9f\x1c\x86\x04\x15\x75\x5b\x9d\x58\x70\x82\x95\xe5\x78\xca\xe6\x8e\x04\x71\x20\x08\x91\x18\x93\x7a\xb3\xa7\xe7\x4d\xa5\x4c\x48\x96\x3b\x86\xc3\x8c\x62\x4f\x79\xd5\xd4\xfd\x1b\x27\x0c\xa0\x09\x1b\xf7\x4f\xb5\x08\x82\x45\x0e\xd1\x43\x21\x26\x25\xf5\x4b\xeb\xba\xba\xa4\x75\x52\xff\x08\x76\x26\x06\xae\xed\xea\x82\x6b\x81\x19\xc1\xd2\x54\x93\xb7\xe3\xa1\x6f\x77\xef\xfe\xf6\xa1\x1d\x79\x9c\xbb\xc0\xcd\x9d\x19\x1c\xb9\xb6\x5a\x4a\xfa\xa3\xff\xb7\x27\x2c\x06\xb7\x55\x70\xc7\x4c\xf2\x63\x79\x79\xca\xf6\x6f\x1f\xab\x6f\x00\xa9\xa9\xaf\xd5\x0d\xeb\xf7\x36\x7d\xd1\xb4\x77\x7d\xc3\x7f\xfe\x24\xf5\x89\xda\x53\xe3\x76\xfe\xf5\xf8\x8e\xfc\xfc\x1d\xc7\xff\xba\xf3\xcc\x75\x61\x39\xef\xd5\xff\xb3\xbc\x53\x41\x08\x78\x79\xe0\xfe\x93\xac\xcf\xa1\xe6\xce\xa9\x8a\x3d\xb2\xe2\x8b\x15\x8f\xc4\xfe\xf3\x9c\x9f\x78\xe8\xa1\x01\x7e\xdf\x4b\x45\x45\x2f\xed\x3b\xb3\x3e\x4d\xfc\xdf\xd5\x27\x96\x73\x8b\xff\xb3\xca\x74\xe5\x2a\xfc\xe4\xaa\x2b\xff\x77\x15\x29\x7c\xed\xb5\x61\xa5\x0a\x8d\xf8\x1d\x0c\xa8\x0a\x4d\x46\x88\x19\xd5\xa4\xc4\x13\xaa\x78\x50\x15\x70\xf3\x2a\xce\xa9\x12\x2c\xa3\x8e\x32\x7d\xa7\x73\xbe\x84\x72\x78\xc6\x54\x34\x47\xe6\x97\x14\x17\x97\xcc\x8f\x34\x57\x8c\xf1\x38\x28\x7a\xe0\x5c\xb1\x4b\x4e\x9f\x95\x34\xf3\xc4\x32\x39\xc5\x9b\x93\xf1\xce\xb9\x2d\xc9\xc6\xd2\xb1\xce\xdc\x5c\xe7\xd8\xd2\xc6\x64\xcb\xdc\xce\xf8\xb9\xe2\x58\x74\xfa\xa4\x11\xd8\x09\x84\xc6\xa2\x2e\x84\x88\x55\xb2\x37\x23\xa9\x6e\x0a\x28\x9e\x3c\xb0\x0a\x60\xb7\x29\x6d\x7c\x2d\x44\xe2\x96\x58\x86\x70\x4c\x49\x1b\x18\xe9\x0d\x84\x88\x16\x38\xf9\xca\x03\x2b\x21\xe9\x52\x3a\x05\x50\x1e\x3b\x24\x28\x66\x7c\x14\x8a\x36\xba\x92\xe5\xc1\x7a\xf2\xe5\x85\x58\x40\x74\xe0\x94\x43\xd4\xac\xd6\x90\xd8\x50\x80\x57\x07\xeb\x5d\x63\x43\x8c\x6a\xf6\xd8\xaa\xfa\xea\x4e\x4f\x8e\x6b\xd9\x5e\xfd\x1a\xb6\xbb\x39\x9d\x9a\xbd\x5a\x7a\xa5\x69\xdf\x52\x2d\xc3\xee\x59\x14\x09\x4e\xa2\x53\x8d\xd1\x54\x5b\xf9\xb8\xfa\xa0\x34\xcb\x79\x9f\xec\xf6\x95\x79\xa5\x77\x02\x75\xf2\xb4\x37\xbb\xd0\x07\x3f\xf7\x15\x7e\x2f\x47\xbb\x2e\x2a\x18\xab\xc2\xf5\xc1\xd4\xb6\xf0\x54\x06\x52\x21\x4f\xac\x82\xbb\x66\xd9\xf7\xe1\x2a\xa9\x29\xab\xac\xb9\x7b\xf3\x6c\x28\x98\x7c\x5e\xdf\xd2\x7d\xb0\x68\xa7\x6d\xfc\xe9\xbd\x9e\x0e\x16\xa1\x0a\xd4\x82\x10\x92\x8b\xc5\xab\xd8\x82\x64\xc3\x10\x09\x23\x90\x92\x89\x5b\x62\xd1\x8c\x95\x88\x77\x84\x3b\x5c\x16\x31\x79\x8a\xc4\x51\xca\x90\x2c\x00\x19\xab\x3f\x65\x9b\x22\x46\xdd\xba\xb0\xde\x55\xbf\xb0\xfe\x26\x31\x19\x6d\x74\x40\x4a\x4c\xe2\x9f\x79\x62\x5c\x13\x53\xaf\xc4\xbb\x7e\x7e\xc5\xc6\x7c\x8b\xb0\x74\xdf\xca\xeb\x55\x4d\xfc\x45\x33\xd2\xcd\x35\x6b\x7c\x52\x2a\x7c\xb8\x6b\x5a\x68\xdf\x52\xc1\x92\xcf\xa4\xea\x83\xe9\x6e\x6c\x0c\xd6\xd7\x07\xd3\xdf\x0c\xa2\x57\xc3\x8d\xd1\x62\x8f\x84\xc2\x25\x1e\x38\xe4\xca\x81\x6f\x89\xdd\xe8\x37\x43\x09\xf0\xfe\xe0\x73\x13\x6b\xe9\x7d\x4b\x4d\xec\xde\x95\x12\x5f\x50\x2c\xad\x9e\xde\x19\x2f\xc3\xa8\x61\x6e\xd7\x61\x0f\x3c\xb4\x74\x1f\x5d\x3b\xcc\xc1\x47\xf6\x7a\x45\x14\x45\x53\xd0\x12\xb4\x0b\x21\x46\x9e\x5f\x29\xcb\x2c\x71\xb7\x02\x19\x1f\x66\x9a\x66\x32\x70\x25\x8e\x61\x29\x79\xfc\xa9\xd0\x17\xf9\x83\x10\x25\x55\x86\x63\x08\x47\xaf\x1c\x95\x00\xca\x3f\x44\x4b\xcd\xd8\x32\x9c\x23\xf1\x68\xa4\x0e\x28\x72\x54\xb1\xf1\xe7\x32\xda\x15\xb5\x10\x26\xa6\x91\x36\xf9\xd2\x74\xc5\xf1\x63\x75\x42\x62\x32\x23\xf5\x77\x1d\x3e\xdc\xb5\xbe\x64\x4a\xeb\xe1\xae\x60\x29\xde\x04\xd7\x76\x1d\x5e\x3d\x57\xba\x7f\xe1\x35\x37\x1f\x73\xfa\xea\x83\x0e\x2b\xcc\xac\xa8\x83\xa4\xec\x93\x3e\xcc\x35\x17\x1b\x8d\x75\x21\xab\x19\x3a\x9c\xbe\x2f\xd3\xe7\x67\xd9\xa3\x8d\xa5\x7e\xcc\xa7\xc9\x8c\x14\x0b\x27\x83\xeb\x56\xcf\x9c\x0c\xb3\x8a\x63\x8d\x51\xe9\x95\x2b\x7c\x72\xb9\x57\x45\xc6\x07\x45\xe9\xe5\xd4\xbe\x8a\x28\xe3\xdc\x3c\x5e\xd4\x1c\x7e\xe3\xb0\x29\x77\x57\x73\xd7\x61\xd3\x5f\x0f\x77\xa5\x97\xb5\xec\xb1\xcd\x11\xf0\x0b\x13\xa7\xf0\x71\x77\xb0\x5e\x73\x93\xa6\x39\x34\x88\x82\xf5\x9a\xdd\x7a\x95\xc3\xe6\xb7\x87\x92\xea\x1e\x3e\x4e\x99\x7e\x50\x35\x46\x0b\xea\xf9\x17\x93\x8d\x5d\x8d\x5d\xcf\xd7\x15\x9f\x37\x80\x2c\x73\xb4\xe3\x4b\xf0\x2d\xd1\xc6\x8b\xdd\x15\xd2\x3b\xc1\xc4\x84\xe0\x6b\xaf\x4d\x28\x51\xcd\x88\x16\x4d\x32\xed\x1b\xae\x7b\x64\x3e\xe8\x23\xfc\x78\x21\xbb\xfc\x1a\x0e\x4b\x60\xfa\x87\x07\x2b\xf2\x8f\x10\x50\xfc\x60\x8a\x04\x40\x19\x72\x59\x9d\x20\xbf\x6a\x6e\x9b\x3b\xc3\x9a\x14\x76\x13\x54\x45\x66\x56\x20\xbf\xd6\x72\xbd\x15\x18\x27\x64\xbc\x31\x7a\x47\xed\x5a\x1f\xae\x39\xbf\xbb\x59\x4a\x35\x77\x4b\x9f\xa4\x3f\x6c\xee\xbe\x7b\x0b\xdc\x5e\x94\x9e\xb9\xec\x3a\xd5\xd8\xee\x66\xb6\xb7\x2d\xfd\xcb\x40\x72\x60\xac\x43\xa4\x8c\x26\x4d\x38\x9f\x4a\x0e\xf4\x3a\x44\x4a\x35\xa9\x14\xa7\x5a\x0b\x2a\x99\xa4\x26\x94\x2f\x8d\xaf\x6f\x17\x1d\xb8\xc2\xa8\x87\xda\xac\x3c\xd1\x01\x29\x87\xc8\xa2\xca\x8a\x81\xbf\x1f\x7d\x51\x3a\xd2\xdc\xdd\xdd\x7c\xfc\x9a\xee\x66\xd7\x96\xbb\x53\x97\x2f\x9d\xbe\xc2\xd5\xdc\xfd\x63\x2f\x2c\x3d\xb2\x83\xd2\x47\x44\x87\xcb\x1b\xb4\xe6\x8b\x2e\xd1\x51\xc2\x97\x8c\xa9\x2c\x30\x18\x7a\xf3\xfc\xed\xf5\x2e\x87\xc8\xdd\xaa\x0f\xe6\xfc\x9a\x2c\x60\x29\x9c\x78\xf2\xd8\x2e\x84\x36\xc9\x6d\x96\x18\xa0\xc4\x68\x84\x7c\xc5\x32\x14\x6f\x39\x90\xa1\x7a\x03\x9b\x95\xa3\x32\x94\x24\x2c\x07\xac\x97\xf2\xb0\x1c\xe5\xa5\x86\xc8\xa4\x2c\x23\xbc\x4e\x90\x3f\x61\x77\x28\x0e\x8a\xa1\x1e\xc7\x44\x23\x0e\x88\x0f\x91\x9d\x50\x5e\x8b\xec\x85\xdf\x4c\xbd\xc0\xb2\x5c\xcf\x6c\xe2\xb6\xb7\x99\x76\xcd\x9b\xb5\xd3\x3a\x6b\x85\x75\xe7\xac\xf9\x97\xf2\x0b\xb7\x72\x17\x6a\xe2\xf6\x72\x4f\x45\xf6\xca\xc3\x55\x21\x89\x69\x98\x53\x21\xd6\xaa\x6f\xdf\x71\xad\xba\x56\x2c\x4f\x52\xbb\x1d\x4b\xd5\x09\xb1\xac\x9e\xda\xc4\xd1\xaa\x65\xaa\x88\x1b\x3f\x5c\xe4\x81\xfe\xca\xc6\x48\xb1\x47\x7a\x35\x39\x89\xa2\x93\x65\x81\x5a\xf5\x26\xc7\x61\xaa\x6e\x10\x2d\x6a\x84\x6b\xab\xc2\xa5\x76\xf8\x20\xc7\xd9\x76\x85\x66\xce\xea\x15\x33\xa4\xdb\xe1\xbe\x19\x2b\x36\xce\xd3\x5c\xd5\x96\xe5\x95\x10\x57\x6c\x74\x6a\xb5\x07\x57\x26\xba\x45\x69\x77\x98\x4d\x95\x8b\xe9\xb9\x78\x81\x58\x5e\x5f\x66\xd0\xa7\x3f\x80\x1b\xfc\xe1\xfa\x20\xaf\x93\x3c\xb9\x9b\x9c\xd2\x3a\x57\xa1\x03\x2e\x2c\x1e\x17\x99\xec\xf8\xe2\x53\x1a\x74\x50\xa0\x37\x6b\xcb\x1a\xca\x45\xc9\x89\xbb\x79\xbe\xbc\x21\xb3\xe7\x2b\x97\x6b\x98\x30\x90\x2c\x25\x4c\x5c\xe7\x6e\xe9\x6a\x15\x91\x71\x6f\x74\x44\x3f\xa0\x78\x4c\x11\x31\x40\x9a\xbb\x30\xe9\x09\x4e\x77\x04\x67\x37\x7c\x96\x8c\xca\x94\xfc\xc1\xa9\x68\xe3\xf5\x85\xf5\x91\x29\x4a\xe3\x77\xc2\xee\x65\x16\x66\x55\x36\x57\x2a\x5d\xc4\x94\x58\xb4\xd1\x35\x25\xb6\xea\x90\x5d\xb3\x74\x4a\x59\x64\xfd\xc4\x9c\xbc\xf6\x9d\xb9\x0b\x8d\x9d\xf5\xe9\x90\xd2\x10\x1e\x5a\x39\xb1\xfa\xf0\x9f\x5c\xe0\x92\xff\x99\x54\x63\x54\x42\x52\xea\xe5\x58\x53\x84\x34\x82\x39\x36\xe8\xee\x58\xf2\x6e\x61\x4d\x65\x41\xad\xdc\x0f\x24\x17\xc4\xa7\x37\x46\x3b\xf0\x98\xf8\xf4\xd4\xcd\xab\xde\xc7\xe3\x6d\xf3\xb8\xcb\xdb\xdf\xdd\xb4\x46\xda\x9f\x9c\xa1\x34\x83\x2b\xaf\xf7\x62\x6f\xd7\xe1\x53\x19\x3b\x34\xe5\x33\x62\x5f\xdc\x4f\x54\x6c\x17\xa3\x9d\x44\x69\x65\xe4\x23\x46\x4d\x54\x06\xc2\x94\x0f\x0a\xd7\xaa\x49\x0e\x70\x1e\xd6\x40\xa8\x08\x49\x25\x12\x3c\x3c\x95\x61\xb0\x54\xba\x8e\x88\x08\x56\xc1\x62\x8b\xc7\xaa\x21\x3e\xd4\x7d\x28\x55\x13\x32\x25\x4e\x11\xd6\x97\x80\x32\xaf\x8e\x91\x89\x95\x01\xe4\xa9\x17\xa3\xaa\x29\xdb\x27\xcc\xb1\xed\x69\x49\x2f\xeb\x3a\xfc\x57\xd3\xe1\xae\xe6\x5d\xb9\xa6\xc3\x6f\x1c\xce\xb1\x8d\xdf\xfc\xb8\x3b\xce\x4f\x99\x18\x0f\x35\x6b\x6e\xd2\xd4\x3f\x68\xf7\xdb\x1c\x2a\xfd\x6e\x4d\x7d\xd0\x1d\xe7\x7b\xd4\xc9\xfe\xb1\xaa\x1f\xce\x2b\xae\x7b\xbe\xab\xb1\xab\x31\xf9\x22\x5f\x5f\x10\x6d\xa4\x73\x4b\xc6\x6b\xe7\x58\xf6\x99\x26\x15\x45\x67\xa8\x4a\x26\xbc\xf6\x5a\x70\x42\x22\x28\xbd\x53\xe1\xbe\xb8\x31\x4a\x5d\x20\xd4\x1d\x3b\xde\xbe\x50\xba\x7f\xee\xea\xc3\x5d\x70\x2d\xde\x54\x1a\xec\x3a\xdc\x3a\xa5\x64\xbd\xdc\x10\x4b\xfd\xcc\xe4\xb8\xcf\x79\xec\xe6\xba\x0a\x98\x69\x75\x04\xeb\x2f\x37\x1a\x8b\xcd\xb9\xd2\x87\xb2\xdf\xe7\x84\x0e\xb3\x35\x54\x07\x2b\xec\x59\xe9\xf3\xc7\xaf\x0b\x9e\xc4\x82\xdc\xee\xa6\x53\x98\xf7\x97\x36\x9e\xfa\x73\xac\x18\x66\x4d\x9e\xd9\x2a\xbd\x2c\x06\xc7\x47\xaa\xe4\x5e\xcf\x77\x85\xf4\x4a\xb4\x71\x98\x07\x86\xfb\x39\x8d\x50\x36\x19\x3f\xda\xce\x8d\xdc\x09\xd9\x19\x8b\x9d\x23\xb1\x01\x2d\xc8\x6e\x40\x0b\x44\xd8\x27\x20\x46\x2d\x0a\x71\xa8\x85\x6c\x4a\x5b\x14\x4e\x98\xf9\x16\xbd\xf4\x96\x59\x7f\xb9\xde\x22\xbd\xad\xb7\x98\x79\x2a\x5b\x6f\xa1\xf9\xa9\xa0\xd6\xe8\x2f\xd3\x99\x21\xf8\x94\xca\xb6\xd5\xaa\x7e\xb2\x14\xcc\xba\xcb\xf5\x1a\xf5\x34\x30\xeb\xae\xb6\xaa\xdf\xd7\x68\x28\x3d\xfd\x81\xda\xba\x4f\x6f\xa6\xfa\x36\xeb\xcd\x03\x6f\x90\x93\x4b\xcc\xfa\xcd\xbc\xd9\xa2\x19\xa8\xd3\x6b\x35\x26\x1d\x6e\x92\xe6\x59\x2c\x70\x6f\xfa\x21\x9d\x49\xa3\xe1\xa9\x67\x75\x26\x4b\xfa\x87\xac\x1c\xce\xab\xc6\x2a\x8b\x69\x08\xc3\xa0\xcc\xa9\xd5\xa8\x08\x8d\x51\xec\x10\x02\x8a\x8c\x43\x4c\xc8\x3c\x4b\x80\xf2\x9e\x49\x75\xa3\x80\xc9\x38\x3b\x1e\xb5\x49\x82\x46\x6c\x90\xf8\x5c\xb4\x9d\x36\xd7\xb8\x67\x5f\x78\x5b\xfd\xa4\xc8\xab\x2a\xb5\xca\x72\x83\x55\xf5\xdc\xcd\x66\x5e\xc1\x41\x8b\xa9\xc4\x9c\x25\x73\x26\xb3\xa5\xd2\x1b\xd2\x37\xbf\xde\xbc\xf9\xd7\x60\x84\x12\x30\x12\xdf\x7b\xe7\xd8\x85\xa0\xc6\xb6\xb8\xcd\xd2\x1f\xa7\xbc\x2b\xed\x31\xf1\x46\x13\xac\x91\x6e\x93\xaf\x43\xf5\xf2\xe6\xac\xfc\x5b\xce\x5b\x78\x9d\x4f\x43\xc5\x36\xff\x5a\xfa\x66\xd4\xf5\xa4\xc6\x51\x17\xba\xfa\xea\x6f\x46\x3e\x77\x29\x6a\x55\x94\xae\x20\x14\x8f\x95\x81\x18\x10\x0d\xc0\x33\xc3\xf4\x46\xf9\x60\x8f\xc7\xea\x20\x16\x08\xd2\xca\x58\xc1\xfd\x9f\x25\x3b\xab\x68\x46\xed\x1f\xe1\xb6\x1b\x3b\x79\x6d\x29\x6b\x36\x6a\x69\xda\x60\xcd\x71\xfa\x2d\x4d\x4b\x3a\xa6\xf8\xc7\x1b\x8d\x5a\x83\x51\x15\xd5\x1b\x28\x63\x49\x74\x66\xe9\xc1\x5f\x3d\x47\xe9\x6e\xec\xe4\x35\xa5\x2a\xd3\xbf\x49\x7a\xdd\xaf\x9f\x0b\x9c\x5d\x98\xe9\xdb\xcf\xde\x3c\x82\xb2\x4e\xb3\x79\xa6\x9e\xc6\x7a\x8a\xd6\x19\x78\x1d\xb7\x6c\x6a\xd3\xd2\x5c\x9e\xd7\x02\xd6\x4d\xb3\x5a\x68\x63\x7e\xb6\xf5\xd9\xfd\x07\x9e\x91\x53\xf1\xd4\xbf\x4b\x45\x57\x9c\xa3\xd8\xc1\x76\x8e\xdf\x50\x7e\x8f\x92\x83\x7d\x5c\x2f\xe3\x22\x98\x12\xa4\xa6\x05\x2e\xa0\x86\xb8\x9a\x0a\xc4\x05\x35\x70\xc0\x01\xee\x93\x1b\xba\x74\x07\xee\xb9\xab\x63\x92\xe4\x82\xbe\x67\xa5\x8f\x70\x0f\xee\x49\x77\xdc\xd5\x31\x09\xfa\x24\xd7\xb3\xe0\xee\x90\x52\xb8\x4f\x4a\x49\x29\xf9\x00\x49\x26\x47\xe7\xcb\x89\x32\xc9\xe4\xd3\x3e\xee\x80\x14\x3a\x63\xdd\x48\xbe\x67\x00\x21\xbf\x1a\x38\x81\x53\x83\x10\x0f\xa8\x99\x78\x20\xae\x86\x00\x37\xba\xea\xe2\x57\xc1\x20\x9d\x6c\xe9\xed\x90\x4e\x82\x50\x30\x6f\x87\x34\x86\x2a\x81\xe7\xa5\x31\xd2\xdf\x40\x68\xe9\xed\x00\x41\x3a\x59\x30\x8f\x6a\x3a\xc7\x43\x3e\x0c\x06\x10\x5a\x9e\xe9\x00\x41\x3e\x31\x25\x8d\x91\xea\xe1\x79\x78\x5e\xfa\x9b\x74\xb2\xe5\x99\x0e\xe9\xa4\x74\xb2\xa0\x05\x7e\x3c\x47\xa5\xd4\x20\x34\xf8\xbe\x1a\x31\x3e\xa4\x45\x16\x94\x9b\x51\xd9\x1c\x8f\x66\xa1\x56\x94\x3a\x53\x15\x60\x68\x57\x95\xc9\xc0\xcb\x62\x44\x44\x98\x68\xa5\x90\x54\x72\xab\xef\xcb\xf8\xc2\x0a\xcc\x9e\x07\x42\xc0\x06\xa2\xdb\xc5\x85\x9c\xd8\x16\x49\xe0\x21\x24\xaf\xc5\xcd\x13\x78\x3a\xa6\x49\xfb\xce\x05\x81\xf0\x58\xfa\x70\x94\xc0\x66\xdc\x44\xfc\x1c\xef\x89\x8b\x81\x78\x3c\x20\xc6\xe9\x9d\xf1\x69\xf1\xf8\xb4\x81\xc0\xfa\x9e\xf5\xeb\x7b\xd6\xd3\x97\xac\x6f\x9e\xbe\x61\x7d\xcf\xc0\xf8\x63\x1b\x37\x1d\xbb\xfd\x8b\x63\xf4\xce\x63\x9b\x36\x1e\x3b\xb6\x71\xd3\xc0\x47\xd2\xdf\x9e\xb9\xe8\x8d\xed\xdb\xdf\xb8\xe8\x19\xea\x5e\x49\xfa\x9d\xf4\xac\xb4\xf9\x8d\x1b\x5b\xe7\x1d\x3a\x81\x67\x48\xdf\x4a\x3b\xa5\xbf\x81\x01\x2e\xa6\x61\x47\x49\x42\xbd\xf6\x26\xe9\x87\x9b\x2f\xfd\xb2\xb9\x6c\xa6\x76\x8e\xab\xf9\xe4\xa5\x37\x4b\x3f\xdc\xb4\x56\x9d\x28\x81\x35\x87\xe0\x96\x4f\xfa\xe0\x2a\x9c\xa3\xdc\x3e\x8e\xe5\xbb\xc7\xda\xe5\x7b\xae\x5f\x0f\x24\x0f\xbd\xe4\xc6\xc7\xe0\x8b\x63\xc7\xbe\x38\x26\x15\xc0\xc5\x60\xd8\xfe\xe6\xa9\x37\xb7\xd3\xda\x75\x6b\x5b\x6f\x7a\x63\xf3\xc6\xd7\x6f\x68\x4f\x73\x72\xb4\xf4\x37\xf9\xb6\x34\x1d\xde\x11\xbe\xfe\xf1\x5b\xa4\x1f\x6e\xec\x5e\x5a\x79\xa1\xfd\x02\xff\xd2\xf5\x37\x82\xea\x96\xc7\xaf\x0f\xef\x08\x2f\x5b\xdf\x8d\x28\x74\xde\x20\xa2\x6f\x22\xed\xa2\x05\x35\x21\x44\xc8\x1a\x91\x0b\xd9\xac\xa7\xc1\x39\xe0\x04\x1e\x73\x2c\x27\x64\xc0\xef\x01\x31\x90\x01\x97\xc7\x21\x2e\x06\x82\x94\x82\x43\x72\xd2\xe1\x10\x11\x17\x73\x02\x55\x23\x5d\x21\x7d\x0f\x1a\xd8\x0a\x1a\xe9\xf0\xa3\xbb\x76\x3d\xba\x0b\x4a\xf4\xb4\xbe\xa0\x34\xb0\xf1\xc5\xc9\xa0\x75\x3a\x75\xf9\x73\xf3\xc7\xbd\x28\x7d\x97\x3f\xd7\xa9\xcb\xcf\x07\xed\xa4\xdf\x6c\x08\x94\x16\xe8\x69\xbd\xc6\x57\x9e\x74\x33\xd6\xfa\x49\xdd\x55\xad\x3f\xf5\x8b\xee\x64\xb9\x0f\x6f\x06\xcd\x13\x4f\x82\x46\xfa\xfe\xc9\x27\xe0\xe6\x5d\x6d\x0b\x77\xed\x5a\xd8\x96\xbe\x33\xa7\xd4\x57\xe8\xce\x9e\x6c\x9b\x44\xae\xa2\x77\x3a\x1b\x5e\x94\xfe\xe1\x74\xea\x9d\x73\xe5\xeb\xd9\x26\x67\xbb\x0b\x7d\xa5\x39\x56\x27\x6f\x76\xd0\xbc\xd7\x61\x0f\x67\x67\x3b\xcc\xbc\x73\x04\x7f\x18\x87\x62\x28\x41\xd0\xaa\x43\xbb\xf6\x41\x60\x39\x1e\x7b\xc4\x32\xe2\x63\xed\x82\x5d\xe0\x58\x8e\xb5\xe6\x83\x3d\x54\x07\x76\x41\xfe\x8e\x45\xca\xb0\x3c\xfe\xc5\x46\xd1\xc5\x1a\xed\xae\xb3\x96\x8f\x8f\xb6\xed\x6e\x6b\xdb\x0d\x61\x8d\xaf\x3a\x5f\x23\x6e\xdf\x79\x7e\x4e\x4e\x7e\xb5\x4f\x63\x2f\x18\x37\xeb\x9a\xf0\xd5\x15\x76\xbb\xda\x5e\x6b\x7f\x66\xc3\x54\x7b\xad\x5d\x6d\xb7\x3f\x13\xd9\x37\x7b\x5c\xc1\xc4\xa7\xa5\x7f\x3c\xfd\x34\xe8\xf0\xb6\x91\x54\xa7\x94\x24\x5f\xa9\x2d\xfd\xbd\x35\x8b\xc9\x56\x65\x15\xf8\xcc\xe6\x6c\x26\xcb\x5a\x5a\x5d\x12\xe5\x23\x57\x97\x67\x2e\xb0\xb1\x49\xb9\xe4\xd3\x11\x3e\x5a\x52\x0d\x66\xd0\x3d\x2d\x5f\x0d\xbe\x3c\x93\xdf\x54\x59\x83\x78\x94\x49\x21\xb3\xa2\x5b\x27\x4f\x72\x08\x12\xda\x27\xe2\x8c\x78\xf9\xf0\x88\x5c\x0d\xc3\x43\x51\x36\x6f\xec\x82\x2b\x3e\x97\x9e\x7d\xf0\x67\xd2\xb3\x5f\x5c\xb1\x30\x89\x9f\x2d\xf3\xc2\x41\xff\xf8\x8a\x32\xaf\xf4\x94\xf4\x94\x37\x58\x31\xde\x07\x87\xdc\x4c\xaa\x75\x6c\xfa\xc7\x9f\x49\xbd\x5f\x5c\x7e\xf9\x17\x90\xfc\x19\xe6\x92\x0b\xfb\xdf\x71\xc3\x6e\x6f\xa8\x62\xbc\x5b\x7a\x19\x62\xee\xf1\x15\x61\x8f\xb4\xdd\x9d\xc1\xa8\xdf\xa0\x46\xcc\x0a\xb9\xce\x31\xc0\x22\x8e\x15\xa3\x22\x0a\x04\xb1\x37\x22\x46\xdd\x36\x1e\x0b\x76\x24\xc4\xcc\x71\x11\x07\xc4\x40\x94\xb1\x29\x00\x2e\x02\xaf\x8b\x45\xa2\xa1\x04\x84\x6d\x3c\x70\x94\xdd\x2c\x40\x10\x07\xa2\x8c\xfc\x33\x21\x8e\x79\x4b\x7a\x37\x5b\xfa\x6e\x2c\x44\x67\x4a\x77\xcc\xb5\xb5\x6e\x2a\x01\x3c\x31\x30\x23\x62\x74\xc0\x45\xa5\xf9\xef\xd9\x2d\x6f\xe5\x89\xc7\x30\xd4\x8c\xb3\xb9\x57\xbb\xd6\xd6\x65\x35\x2c\x82\xe4\x9b\xd7\x59\x12\x1b\xdc\x6f\xea\x3f\xe7\xe0\x31\x7e\x62\xb5\x03\x5e\x01\xd8\x93\x48\x7f\xeb\x5e\x81\x1f\xa9\x48\x0f\x5e\x0a\x00\xcf\x52\xd6\x97\x43\x1b\xe7\x32\xa2\x2a\x84\x73\xc7\x78\xab\x07\xf6\x2f\xab\x85\x9b\x8b\x02\xf0\x59\x74\x3c\x0e\x41\x19\x0e\x06\x27\xfc\xb5\xe1\xad\x43\xf1\x0a\xcc\xf9\x58\x80\x0a\x9c\x08\x49\x13\xdc\x69\xc9\x44\xfd\x28\x56\xf0\x10\xa2\x71\x09\xbd\xaf\x3f\xd9\x38\x82\x4f\x5b\x83\xb2\xd0\x06\xb4\x13\x1d\x18\xd1\xe2\xc9\x33\x4f\x9e\xe6\x20\x41\xfb\xad\x5c\x10\x7b\x3d\x36\xab\xc0\x03\x47\x66\x05\xf9\x64\xbb\x35\x81\xa3\x11\x42\x99\x1d\x84\x00\x99\x2f\x19\xe4\x71\x7e\xdc\x89\x89\x70\x4f\x19\x51\xf6\x93\x47\xba\x65\x64\x5e\xc0\x12\xf9\x36\x27\x08\x44\x1c\xa3\x0e\x9c\xa0\x20\x3c\x46\xf6\xd8\x67\xf4\x06\xd4\x2f\xdc\xd9\x0e\xd1\x13\x12\x0d\xd0\xae\xde\x7c\xd9\x9e\x45\x94\x74\x8c\xdb\xba\x7b\x6f\x3b\xbe\xaa\x93\xca\xcd\xa6\xf5\xd5\x53\x3e\xd8\x65\x04\x9e\x61\xc1\x38\x69\xca\x0b\xf7\x43\x96\x45\xcf\xda\x05\xbc\xfe\xd6\xfc\xf1\x1a\x2d\xd3\xc0\xaf\xc1\xee\x1c\x5a\x9f\x6d\xb5\x4e\xed\xdb\x6d\xc0\x7a\x86\x05\xc3\xc4\xba\x57\x1e\x0c\xe8\xb4\xfe\x75\x37\xe6\x57\x6a\xb4\x74\x15\x3f\x67\xc7\x5b\xd2\x3b\xd2\xe3\xd2\x3b\x6f\xed\xd8\xf1\x16\x14\xc0\x04\x28\x78\xeb\xa3\x73\x74\x30\x78\x97\x43\x94\xb3\xe3\x9e\x85\xc7\xab\xd6\x6c\xdf\xd9\xca\xa6\x9f\xe4\xd6\x5e\xb8\xab\xb5\xe6\xa5\x7b\xb0\xd9\xa0\xd7\x78\xba\x8f\xb8\xc6\x69\xb4\x74\x83\x61\x25\xf6\x3b\x69\x7d\x5e\x01\xd5\xf8\xf1\x6e\x03\xa5\x93\x6f\x3b\x69\xdc\x89\xfb\xc1\x6e\xd4\xb1\x16\x9d\xae\xfb\x26\xe7\x38\x8d\x96\xa9\xd7\xaf\xa9\x54\xeb\x93\x8d\x1f\xee\xd4\x61\xf9\x11\xf4\x93\xfe\x48\x6e\xbe\x63\x64\x86\xf0\x25\xff\x6a\x1c\x05\x99\xbe\xd5\x8e\x3c\xa8\x08\x21\x88\x09\x76\xc1\x2f\xd2\x1c\xc4\x7c\x6a\xb0\xd3\x71\x4a\xf4\xe1\xa8\xd1\x6f\x37\x63\x96\x63\xfd\x10\xc3\x01\x5f\xc8\x4e\x1a\x16\xea\xa2\x6f\x7e\xff\xe5\xd6\xb4\xa3\x47\xfa\x47\x58\xfa\x4b\x0a\xd6\xa6\x3f\x80\x19\x93\xc0\x7e\xd3\x17\x6f\x48\x3f\x7d\x81\xfd\xd5\x18\x6a\xd9\x89\x6b\xbe\x90\xfe\x01\x87\x5a\xb4\xcb\xa5\xca\x53\xc7\x8f\x9f\x3a\xce\x22\xbc\xed\xb2\xaf\x03\xea\x3b\x0f\xc0\x5d\x47\xef\x97\x56\xa7\x57\x5e\x73\x30\x4f\xaa\x75\xff\x08\x3b\xde\x07\x6d\xfc\xb0\xf4\x8c\xf4\x41\x7a\xd6\xa5\x3c\x5e\xb7\x0b\xea\xce\x67\x8f\xcb\x27\xc9\xef\x15\x96\xeb\x17\xf3\x12\xd9\x4d\x70\xa1\x80\x88\x1d\x10\xa7\x12\x20\x8f\xc5\xe5\x77\x88\x22\x98\x4f\xcc\x09\x01\xd6\x89\xe3\x09\x2c\x38\x81\xe3\xe9\x00\x0f\x01\x27\x24\x70\x3c\x16\x94\x3d\x42\x0c\x07\x68\x64\xb1\x63\x1e\x68\xea\x72\xe9\x73\x69\xfc\xea\x31\xe6\x09\x37\xac\xd0\x6a\x37\xe8\x8b\xbe\xda\x14\xdb\xc5\x65\x37\x86\xe7\xa8\x0c\xda\x6c\x46\x58\x50\x69\xd8\x63\xb6\x85\x9b\x0b\xc3\xed\x93\xfd\xb5\x55\x6a\xa0\x78\x7b\xa1\xa3\xe6\xee\x8b\xa6\x1c\xef\x39\xb4\x2a\xa7\x58\x35\xae\x74\xde\xb2\x1c\xc3\xb5\x57\x82\x1a\x44\x1a\xcf\xb9\xed\x1d\xe9\xe4\x20\x82\xd2\x1f\x76\xc1\x6c\x18\x0f\xc5\x6d\xd2\x1f\x79\xca\x34\x63\x03\x2e\xfd\x6d\x8d\x4a\x4b\xd3\xc0\xcc\xf0\x72\x42\xb9\xe6\xa9\x71\xc5\x53\x2b\x73\x38\x75\x38\x80\xe9\x31\x3e\xcc\x99\xf5\x2a\x6a\xd1\x0c\x6d\x6d\x71\xfe\xe4\xf3\xa2\xad\xbf\x79\x40\x14\x67\x4d\xbc\x07\x16\xac\x9b\x2a\xad\x92\x7e\xbd\x63\x10\xbd\x7f\xdf\xd2\x51\x3c\xfe\x71\x45\xaf\x91\x26\x10\x57\x27\x08\x76\x3a\x1c\x8a\x13\xc3\x0f\x51\x6e\xf0\x22\xe6\x98\xaf\x1a\xec\x34\x58\x31\xa1\x52\x88\x99\xa3\x11\x1c\x20\xda\x8a\x66\xe6\xcd\x3b\x9e\xbb\x59\xfa\xcb\x79\x8d\xf3\x69\x7a\x7e\xe3\x79\x60\xbd\xf9\xb9\x3b\x2e\x90\x5e\xbd\x3b\x8f\x7f\x50\xfa\xd5\x67\x97\xc9\x75\xe3\x61\xea\x2e\xa8\x80\xdb\x6f\xba\xa2\xf3\xfc\x2b\xcf\xbf\xe9\x85\xe7\x6f\xda\x72\xf9\x96\x55\x97\x5f\xcf\xe4\xae\x3d\xb0\xa3\xed\xd4\xbe\xa2\x7d\xa7\xda\x76\x1c\x58\xbb\x7a\x2b\xa8\x0e\x7e\x0d\x0d\xc7\x1f\x96\x6b\x12\x6c\x19\xf8\xa1\x57\xba\xf7\xe2\xba\xd9\x95\xb0\xe4\xb3\x4f\x61\x49\xd5\xac\xb1\x17\x49\xf7\x65\xe6\x27\x46\x0e\x31\xdf\xa0\x62\x14\x45\x75\x68\x02\xd1\xbb\x71\x2b\xb3\x56\x37\x0f\x72\xae\x59\xaf\xc7\x14\x89\xc7\xe2\x66\x3f\x4b\x99\x91\x3b\x24\xf8\xc2\x21\x42\x83\x63\xa7\x48\x93\x2d\xff\x6e\x40\xd6\xfc\x82\x10\x60\xc1\x4d\x26\xb5\x1c\xe2\xfa\x2f\xf9\xc3\xc1\xa5\xf7\x87\xe0\xce\xca\xcf\xa5\x13\x77\x3d\x71\xf7\x67\x3f\xfd\xaa\xd4\xb4\xf0\x05\xb0\x3e\xfa\xf7\x3a\x78\x0c\xb2\x9d\x06\x34\xf8\x50\xb2\x73\x4e\x79\xe3\xf2\x09\x5d\xb3\x57\x1f\xb8\xe0\x37\xe3\xc3\x3f\x3e\xbf\x78\xee\xc6\xeb\xb7\x3d\x12\x5c\x02\x3f\xe0\x77\x98\x77\xae\xd9\xff\x36\x9e\x57\x59\x7e\xe0\xd7\x6d\xb3\x8f\xfe\xe3\xd2\x59\x9b\x80\xdb\xd8\x53\x73\x37\x74\x7e\x3f\x5d\xfa\x0a\xcc\xb0\x08\x36\x3b\xe2\x4b\xea\x37\xdd\xf3\x30\xfc\x6c\xd6\x92\x09\x65\x77\xaf\xbb\xbc\x7f\xfb\xdc\xb6\x59\x93\x3e\xbc\xec\x55\x3c\xe5\xea\xa7\x9f\x1e\x5a\x67\x4b\x71\x8a\xce\x48\x18\xa1\xd1\x88\x30\x65\x57\xd3\x76\xd6\x7e\x61\x74\xe4\xc6\x34\xb2\xe8\x7f\x24\x3b\x96\xac\xb2\x9b\x99\x76\x01\xd9\x88\x18\x20\x1b\x11\xd0\x91\x76\xd5\xb7\xb7\xd7\xb3\xc9\xfa\x76\x70\x51\x24\xe1\x40\x52\x6f\xb1\x50\xaf\x0e\x28\xf8\x97\xa1\xfd\x86\x54\x06\xf3\xa2\xe4\xcb\x3e\x98\x62\xff\xc4\xa4\x90\x80\x12\x08\x59\xc2\x2c\xc7\x53\x0a\x08\x5a\xb0\x0b\x99\xbb\x17\x0e\x9b\x3b\xc6\x28\x86\xa7\x38\x36\x40\xb6\xda\x14\xe9\x6b\x27\x25\xf8\xc5\xab\x7e\x3d\xa1\xd2\x17\xe4\xa9\x2c\xb3\x85\xc6\x61\x67\xd5\x22\xe9\x9b\xf2\x86\x06\xfa\x4b\x88\x94\x37\x34\x94\x3f\xf4\x86\x51\x2a\xc6\xd6\xa2\xa9\xf1\x0b\x9b\x5c\x45\xb5\x1e\xaf\x4d\x63\xb6\xce\xa9\x29\x9d\x5a\x15\xf6\x9a\xe0\x8d\x06\x26\x95\x9c\x53\x79\xfe\xa5\xab\x8e\x2c\x9a\x6f\x51\x7f\xdd\x7a\x6f\x67\x43\x39\x93\x25\x9f\x78\xea\xcb\xf2\x86\xdf\xc1\xd2\xe5\xa5\x53\x26\x54\xe8\x1c\xf5\x39\x0d\x4f\x1f\x3b\xf6\xe2\x34\xb1\x30\xa9\xd7\x69\x85\xb2\x0a\xd7\xb2\x07\x87\xb5\x6b\x98\x0b\xc8\x7a\xc9\x04\x74\x2f\xfa\x35\x42\x0c\xa7\x50\x84\x28\x50\x68\x31\xae\x80\xb8\x33\x66\x51\x64\x12\x27\x7b\x81\x13\xec\xdc\xd9\xd6\x2b\xf1\x8c\xe9\x8a\x60\x67\xac\x84\xa2\xd8\x43\x2e\x12\xf5\x92\xeb\x08\x61\x53\xc6\xe2\x4a\x81\xb2\x8b\xf1\x58\x3e\x0c\xd1\x1e\x2b\x5a\x4c\xa6\x0c\x7b\x9b\x12\x34\x00\x61\x44\xc9\xfc\x8c\x56\xaf\xdb\x14\xce\xf0\xc4\xc8\x79\xa0\xec\xd6\xe1\xac\xca\xa9\x09\xb2\x9d\xbc\x88\xcc\x05\xec\xfa\x03\x37\x1d\xbb\xe3\x86\x83\xeb\xd6\x27\x8a\x74\x74\x24\xcc\x80\x39\x37\x74\xde\x92\xd4\xee\xfd\xd7\x5c\x9a\x5a\xcc\x6a\x0c\x3a\x9b\x4f\xb2\xd5\xd7\xd9\x72\x4d\x06\x8d\x3a\x51\xcf\x68\x0c\x46\x6c\x56\xd5\xd7\x1b\x9d\x66\x3d\xcb\x8d\x1d\x6b\x76\xe6\xc0\x0b\xc1\xd2\x19\xcd\x6f\x7d\xfb\x56\xf3\xcc\x62\x03\xa8\x23\x21\x8d\xbf\x06\xa8\xa5\x2b\x0f\x5e\xf7\xda\xeb\x07\xc6\xc4\x72\x0d\xc6\x5c\x9e\x17\xb5\x9d\xfb\x27\x4d\xec\x5c\x35\x31\xb9\x76\x77\xc7\x43\x97\x4d\xde\xb7\xf7\x85\x17\xf7\x46\xb3\xb0\x4a\xe3\xb6\xdb\xf2\x6d\x26\x6a\x8d\xd3\x39\xf0\x26\x14\x6c\x0f\xae\xd9\x76\xc1\x5b\xcd\x33\x4a\x83\xf9\x6a\xad\xd6\xa1\x57\x73\x5d\xcb\x53\x07\x2f\xbd\x24\xc7\xac\x06\x4a\xbf\xf3\xee\xdb\x6f\xb8\x52\xcb\xae\x4f\x24\x93\x75\xdd\xdd\x07\x56\xcc\xcd\x55\xa9\x72\x81\x5a\x30\x7e\xfb\x79\x4b\x62\x95\x95\xf1\xc5\xac\x86\xa6\x2c\x7e\x3c\x93\xe4\x58\x53\x5b\xcf\x18\xb1\x81\xe7\x34\x63\xeb\x8d\x79\x66\xa6\x7e\xac\xc9\x99\x33\xe5\xfc\xb5\x2b\x67\x34\x2f\x5c\xd8\x3c\xb3\xd3\xcd\xe5\x98\x8c\xb9\x4b\x1b\x60\x16\xbe\xa2\x63\xc5\x89\x03\xd7\xbd\x66\xd4\x86\xc2\x2a\x8a\x62\xaf\x59\xb1\x7c\xc2\xc4\xe6\x49\x2d\xd2\xd2\x71\x93\x2f\xfb\xd9\xa2\xe7\xf7\xed\xdd\x1b\xf5\x60\xad\x5a\xa3\x62\x04\x03\xbe\xcb\x20\xac\x95\xf2\x8a\x66\x5b\x82\x0b\x9b\x67\xac\xec\x86\xd7\x54\x56\xa3\xde\xc1\xb5\x16\x55\x56\x68\xca\xb2\xf5\x46\xba\x2a\x39\x46\xae\x33\x79\x83\x88\xfd\x98\x45\x28\x07\x25\xd0\x26\xb4\x13\x21\x7f\xcc\x6e\xe5\x78\xda\xeb\x09\x52\x81\x20\x10\x51\x66\x81\xf6\xc7\xfc\x76\x96\x88\xc7\xc7\x13\x10\x08\x52\x3c\xf6\xf2\x54\x11\x56\x08\x6e\x62\x76\xb0\x3a\x71\xbe\x3c\x20\x29\x03\x31\xc0\x53\x64\x9b\x9e\x89\x2b\xbf\x3c\x4f\x71\x7e\x62\x80\xe8\xa4\x6c\x60\x25\xc6\x08\xb1\x5a\xe0\x29\xd6\x60\xb0\x1b\xf4\x89\x4b\x6e\xfc\xe8\xfc\x2d\x5f\xff\xfc\x8e\x65\x1e\x15\xcd\x6a\xf4\x4c\xef\x6a\xb8\x14\x6e\x7a\x1a\x6e\xd0\x9a\xac\x9e\xb0\xc9\xac\xb6\x95\x99\x18\x9b\xdb\x51\x62\x29\x06\x96\x57\xa9\x19\x96\xa2\x00\xd8\xae\x50\x70\xbb\xb4\x3b\xc7\x2f\xf2\xfa\x4f\x0b\xa6\x59\x2c\x5a\x5e\xdc\x72\xc5\xfe\x5d\x9d\x89\xca\x96\x8b\xb6\xee\x5d\x1a\xb2\x79\xe6\xb1\xb6\x9a\x48\x8d\x59\x7a\xaf\x64\xc1\xc5\xc7\xcf\x5b\x76\xdb\xe2\xb1\xd9\xe9\x8e\x09\xf5\x93\x67\x3b\xf9\xea\xce\x35\x63\x6b\x58\x36\xcf\x62\x8c\xcf\x18\x57\x91\x68\xdd\xdc\x56\xa8\x36\xa8\x19\xa0\x37\x57\xfc\x6c\x6e\xc1\xef\x8c\xab\x2a\x66\x15\xf2\x1a\x4b\xe9\x8d\x76\x4e\x4d\x61\x8c\x15\xb1\x58\x8c\x8d\xe5\x2c\xa7\x83\xbb\xf3\xeb\x43\x45\x5a\x6d\x9f\x7f\xaa\xd5\xaa\xb5\x57\xcf\x2b\x60\xcb\x67\x5d\xd3\x3a\x7b\x6f\xdb\xe4\xc2\x5c\x35\xde\x31\xd6\x15\xc5\x76\xff\xcc\x78\x4e\xcd\xf9\xab\x67\x56\x84\x26\xb7\x4d\xf7\xa4\x6f\x9d\x5b\x56\x62\xcf\x5e\x52\x5a\x79\x1b\xb6\x96\x2d\x1a\xb6\xf9\x49\x91\x3e\x2a\x4c\x10\x5a\xab\x46\xd8\x84\x0e\xb1\x2a\x9f\xb6\xcd\x1d\xf6\xf9\x33\x9c\x96\xd1\x0c\xc7\x25\x33\x2a\xac\xe0\x4b\xff\x1b\x6b\xf5\x8c\xb1\x16\x91\xe8\xce\x08\x83\xa7\xda\xeb\xe5\xc6\x52\x71\x06\x47\x0a\x30\x8d\xf0\xd3\xa9\x53\x29\x0a\x9d\x45\xc8\xa2\x20\x21\x50\x53\xe4\x34\x7e\xa5\x43\x6e\x7e\x3b\x32\xdf\x8a\x2d\xba\x82\x28\x1c\xe1\x3f\x65\xa6\xd1\x00\xc2\xc9\xd1\x57\x22\xde\x33\xca\xc7\x40\x54\x0e\xc2\x04\xc1\x66\x1b\xd9\x27\x84\xec\xe0\x36\xb9\xff\x3d\x17\xe8\xbf\x29\xd0\x70\xc8\x4e\xa7\xcc\x7c\x5a\x81\x8d\x24\x79\xf3\x00\x62\x52\xa7\x52\x30\xa2\xa3\xa0\x46\xea\x53\xa5\xce\x59\x6a\xa9\x48\x13\xf4\x0c\xa5\x31\xa7\x7f\x47\xa3\xde\xb3\x9e\x59\xf1\x4f\x3b\x77\x41\x35\x9d\x59\x27\x02\x28\xae\xd4\x09\xff\x69\x8a\x33\x91\xb4\xca\xc3\xda\x43\x19\x3b\x74\xc1\x6e\xfd\x3f\x2b\x87\x79\x41\xb5\x43\xf3\xe4\x93\x8a\x8d\xf9\x53\x4f\x29\x56\xe7\x43\xe1\x27\x9f\x54\x0f\xb8\xfe\x67\x45\x73\xfd\xb9\x2f\x37\x1c\x96\xfa\xfe\x77\xe5\x65\x45\x59\xa8\x00\x55\xa2\x85\x44\xa7\xc6\x13\x18\x36\xd4\xcf\x58\xeb\xff\x5f\x15\x10\x23\x48\x48\xe3\xd0\x48\x7d\x4a\xd6\xdf\x07\xe5\x59\xfa\x3b\xfe\x67\xc5\x82\x6b\x24\xa4\x56\x83\x4b\x29\x90\xf7\x41\x29\x91\xf4\x98\xff\x41\x61\xc0\xf0\x98\x37\x2f\xd3\x8e\x00\xe9\x9a\x87\x9c\x11\xab\x13\xd0\xeb\x10\x71\x96\x49\x18\xfa\x16\x1d\x3f\x12\x9c\x3c\x8b\x44\xc7\xc0\xa5\x70\x3f\x2f\x3a\x24\xc5\xe9\x57\xe2\x53\x0e\x51\x59\x57\xa4\x95\xb9\x0f\x51\x1d\x41\xa1\xf8\xf0\x3a\xf9\x10\xf9\x81\x9f\xec\x94\x0c\x2f\x19\xc5\xe0\xe9\xdd\x09\x62\xf6\x39\x1b\xee\x82\x12\xe9\x0d\xa9\x45\x7a\x03\x23\xf9\x61\x0e\x9c\x30\xe7\x9a\xef\x86\x5e\x43\x7a\xbd\x7c\x0b\x7c\x0d\x5d\xa1\x1c\x86\x12\xb8\xab\xc9\x9c\x6b\x3e\x71\x40\x4e\xb6\xe5\x6e\x65\x4d\xd3\x3f\x88\xd8\x3f\x90\x3e\xca\x4f\x30\x38\x64\x09\xea\xf4\x72\xcb\xe9\x1f\x2b\x24\xc0\xf0\x4e\xc5\xe9\xd6\x34\x43\xdc\x20\x0f\x23\x6d\xec\xeb\x1a\xcd\xbe\xdc\x82\x53\xc4\xde\x14\x27\x15\xab\x54\x54\x90\x3b\xf0\x24\x28\x26\xaa\x14\xe1\x49\x3b\xd5\x5b\x90\xbb\x8f\xa4\xc4\x08\x10\xfd\xb6\xc6\xa1\xd9\x97\x2b\x3a\x40\x61\x02\x13\x1d\xc9\xdc\xfe\xf7\x09\xc6\xdf\x41\xf5\x2a\x04\x61\xb9\xfb\x48\x9a\xde\x5e\x65\xbd\x5d\x85\x98\x7e\x82\x2b\x96\xdf\x65\xa4\xec\x25\x73\xc0\x06\xfc\xcc\x10\x62\x3a\x16\x87\x98\xc0\xf8\x63\x8c\x89\x31\xf9\x4d\x7e\x13\x98\x18\x13\xf7\x59\xae\xdd\x9c\x4e\x65\x65\xa5\x6f\x48\xdf\xa0\xe1\x2d\xa6\x5c\xbb\x19\xa7\xb2\xb2\x70\x27\xee\x74\xf5\x67\xe1\x64\x7f\x07\x76\xd1\x7d\xe9\x3e\xe6\x3b\xab\xfb\x54\xca\xea\xe2\x06\x91\x56\xfb\xfd\xf7\x8c\xd6\xea\x66\xe4\x20\x90\xa0\xfe\xa6\x7e\xcd\x17\xf4\xf7\xfa\x7e\xcd\xbb\xf4\xf7\xa7\xd2\xf4\xf7\xef\xf6\x6b\x46\xae\x0d\x9b\x90\x17\x45\x87\xfa\x1b\x0e\x58\x05\x2b\x18\x87\x98\xfb\x1c\x31\x43\x1b\xe1\xf2\x6b\x25\x67\x1b\x23\xbd\xc5\x24\xb9\x38\x95\xde\x62\x82\x3e\x8e\xfe\xf2\x8c\x60\xff\x5d\x2a\x16\x23\xb3\x45\xaf\x62\x25\x64\xb6\xb0\xc8\xa2\x3f\x95\xb4\xaa\x06\x11\x6d\xd1\x33\xbd\x56\x15\xc8\x9e\xd1\x31\xd4\x20\xd2\x58\x4e\x25\xf5\x16\x0a\x90\xc6\xc2\xf4\xea\x2d\x43\xfb\x35\x2e\x4e\x7e\xcd\x39\x64\x40\x02\xaa\x3c\x5b\x51\x65\xc8\x55\xd0\x9d\x01\x96\x61\x89\x29\x66\x3c\xc1\xc5\x83\xa0\x40\x3d\xb1\x22\x9c\x02\xbf\x39\xd3\xf9\x46\x5a\xf6\x8f\xb5\xcb\xef\x97\x4e\x45\x3c\x3a\x2b\x45\x67\x31\x7e\xde\x6d\x70\xf0\x06\xe6\xc0\x9d\xdf\xc0\x2d\xf0\x25\xdc\x82\x1b\x47\xd0\x7a\x2a\xff\x10\x94\x6e\x97\xde\xbd\xd7\x7c\x7f\xa5\x86\x02\x5e\x6b\xb0\x33\x6e\xde\xef\x28\x2f\x1f\x17\x58\x90\xbe\xe6\x01\x08\xdc\x7b\x2f\x3a\xad\x97\x36\x9c\xef\x20\x61\x74\x1d\x65\x1b\x34\xe4\x62\x17\x2d\xbf\x2f\xf9\xc0\xb1\x5c\xac\x0e\xe4\x71\xb9\x2f\x66\x14\xc1\x3a\xfc\x40\x5e\x8f\x18\x88\x8a\x31\x31\x81\xe3\x09\x26\x4e\x34\xa9\xc0\xe7\xa2\x9d\x70\xce\x27\x3b\x29\x75\x4a\x47\x5e\xbf\x66\xe7\xbc\x9c\xac\xe0\x0d\x17\x16\x57\x8d\xaf\x7d\x05\x96\xbe\xfe\x3a\xcc\x90\x1f\x78\x42\xe3\xf3\xd2\xa9\x8a\xb1\x8c\x21\x8b\xa6\x18\xd0\x60\x1d\xe6\xca\x6d\x85\x59\x4e\xed\x91\x5f\x9c\x5e\xea\xc0\xbf\x38\xfb\xb9\x53\x7b\xfe\x72\x65\xf7\x6f\xa6\x84\x3a\x5a\x67\xd4\xad\x16\x59\xd5\x9e\xbf\x80\xf9\x2f\xd2\x9e\x07\xa4\x77\xef\x55\x3d\x38\x8e\x57\xd9\x4c\x40\x1b\x69\x03\xc5\x63\x55\x54\xa8\x0c\x4e\x2a\x98\x0f\xec\xe1\x9d\x5f\xdd\xb7\x7c\xf9\x7d\x5f\x91\xdf\x51\x4d\x23\xe6\x9f\x88\x42\x2c\xd2\x20\xbd\xdc\x4a\x9b\xd4\x60\x82\x6c\x20\x2e\x46\x18\x49\x48\x22\xdf\xb2\x1f\xe6\x43\x20\x7d\x5c\x7a\x87\xda\x92\x3e\x0e\x05\xf4\xad\xb2\x1f\x4f\x97\xde\x95\x63\xc9\xba\xe1\xcc\xc1\x5e\xf6\x7e\x26\x49\xec\xd0\x59\x40\x5e\x0f\x25\x52\xd8\xeb\xe1\x02\x89\x8c\xd5\xab\x59\x99\xdf\xc4\x63\x5e\x0f\x67\x66\xec\xec\xfd\x1a\xe9\x69\xe9\xbf\x3e\xbf\x7a\x49\x49\xcb\xa4\x39\xe6\x35\x53\xb3\xee\x0a\xde\x32\x67\xd1\x26\xa1\xc4\x1e\x1f\x1b\x5e\xb1\x5c\xa5\xdf\x56\x95\xdc\x0a\xb3\xfa\xa9\x53\x7f\x91\x16\x4b\x33\x80\xeb\x81\x7a\x60\x9b\x96\xd8\xae\x2f\xb8\x4a\xa5\xbe\x64\x8f\xf4\xf1\xdc\x1f\x7f\xf2\x93\x39\x7b\x1c\x70\xa5\x56\x85\xce\xe0\xc1\xa1\x90\x86\x30\x6b\xbb\x81\xb2\xb8\x2d\x14\xb0\xe8\x14\xa2\x6b\x3f\xf8\x20\x7d\xd9\x07\x1f\x40\x2d\x93\x3a\x85\xe0\x0e\xbc\x05\x0a\xa5\xb7\xd3\x57\x4a\xaf\xa1\x33\xb4\x2b\x28\x64\x46\x63\xd1\x9c\xcc\xf9\x1c\xe1\xdc\x8e\x07\xe2\x01\x6f\xc0\xcb\x31\x21\x3b\x17\x8f\x04\xf1\x10\x29\x48\xc8\x46\x50\xe6\x36\x77\x34\x10\xc4\x09\x88\x9a\xc2\x71\xaf\x47\x1e\x49\x47\x12\x18\xa2\x04\xa4\x17\x35\xb9\x39\xc1\x9e\x49\x27\xe7\x83\xda\xab\x6b\xcc\xcf\x5e\xb5\x2a\x3b\xbf\x51\xb7\x28\xea\x8a\x4a\x87\x5d\xd9\xf0\x80\xb7\x7e\x52\xc5\xa5\xbb\x3b\x9a\xac\x1a\xfd\x64\xe8\x3d\xc4\x32\x18\xe0\x19\xf1\x8f\x2c\x4d\x53\xba\x1c\x7c\x7e\x8c\x63\xb0\xf4\x95\x30\x4b\xd0\xf1\x13\xe4\xec\xd3\xbd\xee\x59\x1b\xb2\xab\xaa\xb2\x37\xcc\x72\x77\x74\x1c\x73\x95\xd9\xe2\x8d\x7e\x7e\xe3\x45\x93\x52\x2a\x69\x27\xaf\x03\xae\x65\x2e\x0f\x40\xd3\x1a\x06\x76\xa5\x58\x96\x6a\xce\xc9\xc9\xd3\x0e\xfc\x72\xae\x1a\x28\x4a\xc7\x62\xd5\x72\x3b\x67\x95\xae\xe6\xd5\x58\x3d\x57\x79\xf6\x65\xa4\x0d\x2a\x43\x55\x68\x06\x6a\x55\x94\x22\xc8\x86\x8c\x2b\xb3\x09\x93\xa1\x68\xf7\x5b\x12\x20\x30\x04\x5a\x22\xbf\x2b\x51\x3f\x45\x13\x80\x03\xc8\xbd\x0b\xe9\x67\x20\x16\x09\x88\x9e\xcc\xc4\xd4\xc3\xb1\x56\x45\x79\x50\x1c\xa2\x81\xb6\x72\xa8\x3a\xa4\x7b\x53\xda\x2f\x35\x4b\xd7\xbe\xa9\x0d\x27\x36\xcd\x9a\x53\xf3\x1e\x14\x6e\xa2\xb2\x78\x58\x6f\x9e\x54\x9c\x68\x69\xd9\x3e\x4f\x7a\xa8\x13\x4a\xfe\x30\x66\xce\xac\x4d\xa7\x6e\x9b\xb7\xbd\xa5\x25\x51\xdb\x42\x15\x69\xb5\x1a\xa7\xb6\xb0\xa7\xa7\xa7\x50\xeb\xd4\x68\xb5\xc5\xd7\xb7\xb7\xb4\x5f\x6f\xdf\x3e\xaf\xa5\x36\xd1\x82\x1f\x1a\xb3\x28\x3b\x18\xba\x59\xfa\xe1\xc6\x1b\x41\x75\x73\x59\x59\xf6\xe2\x31\x33\x37\xd7\xdd\xa0\xc1\x6a\xbd\x91\x9a\xe1\x2f\x9d\xb7\xbd\x65\x5e\x62\x8a\x54\xa0\xbe\xbe\x76\xb3\xf4\x47\x72\x93\x16\xa9\x43\xeb\xd4\x6a\x34\x45\x05\x05\x45\x1a\x8d\x26\x5f\x5b\x1c\x52\xab\x43\x3f\xc8\x37\x9b\xb7\x9d\xd4\xe9\xf1\x83\x98\x7d\x82\x45\xa8\x1c\x21\x4b\x38\x41\xf9\xc2\x21\x5a\x90\xbb\x34\x27\x95\x80\xb8\x89\xd5\x41\x40\xc4\x01\xd1\x1c\xe7\x81\x73\xc7\x82\x74\x19\xf0\xd4\x78\x30\xce\xb9\xf6\x69\x80\x83\x7f\x84\xb5\xeb\x3a\xfb\x6f\x86\x95\x77\xfd\xfe\xed\x97\x26\x2f\x94\xbe\x92\x6e\xdb\xf7\xd4\x77\x98\xfa\xec\xf7\xe5\x35\x46\x7c\xa1\xca\x95\x98\x3e\xb3\xc1\x6e\xbf\xfc\xc7\xe7\x6f\xc2\x9f\x5f\xfc\xc7\xdf\x1c\x9a\xfb\xfb\xe7\x9f\x18\x7c\x72\xdd\xb1\x99\x2e\xc7\xb8\xb0\x74\x79\x7c\x0a\x8e\x4d\x86\x8e\x5f\x7d\x0b\xb3\x97\xd4\xec\x6a\x9f\x7a\xf1\xd4\x4a\x87\x01\x80\x99\xbe\xf3\xfa\xa1\xfa\x4a\xb0\xf5\x0a\x1b\x7d\x0e\x42\x51\x93\x3b\x33\xa4\x90\x2b\xa4\xdb\xe6\x8e\x0e\x0f\x96\xc2\x6a\xd4\x5e\xff\x43\xb2\xbe\x1d\xa7\x20\x95\x46\x80\xd8\x8e\xfa\xf6\x7f\xa2\xf6\x7a\x17\xee\x48\xf7\xd4\xb7\xb7\x83\x87\x98\xb0\xa4\xda\xeb\xfb\xfa\xea\xdb\x87\xb1\x9d\x4f\x10\xbb\x95\x72\xb9\x7f\xf7\x93\x2d\x39\xb9\x22\x28\x7a\x92\x71\xa2\x26\xa5\x2c\x58\x87\x43\x3e\x35\xb0\xc8\x3d\x42\x70\x54\xa0\xbc\x44\xfe\xde\x09\x3c\xb0\xe5\xef\x4d\xf9\x6e\xdf\x75\x3f\xec\x9f\x73\xed\x0b\x6b\x77\x9d\x6c\x7a\x7b\xad\x74\xf4\xe5\x9f\x48\xef\xbd\x71\xf1\xc5\x6f\x80\xf8\x93\x37\x61\xbd\x94\xc4\xbf\xd8\x24\x35\x4a\x5f\x3f\x3c\xb4\xc2\xfb\x30\xd0\x70\xc7\x45\x47\x03\x1d\x57\xb8\x4a\x75\x9a\xd2\xef\xd7\x6d\xbd\x6a\xff\x0f\x07\xd6\xbe\x70\xed\x9c\x0b\x56\x5f\x74\x77\xef\xc5\x6f\x48\xef\x49\x4f\xcb\x97\x78\x0b\x4f\x90\x7a\xd2\xd2\x7b\xa7\xdb\x4a\xe9\xbb\x93\xd2\xa6\x1e\x20\xe6\x24\x88\x46\xae\x41\xc4\xf6\x65\xf8\x74\x33\x7c\x04\x71\x37\x04\x4c\x90\x0f\x26\x35\x76\x03\x73\x5d\xfa\xa6\x85\xd4\xbc\x53\xbf\x78\x94\x3e\x6a\xbd\x2e\xfd\x17\x58\x28\xe9\x06\xee\x86\x65\x54\x35\xec\xbc\x7e\xe0\xc3\x4d\xd4\x82\x74\x76\xc7\xa2\x81\x9f\xc2\x74\xbc\x63\xe0\x43\x5c\x3d\x54\x36\x29\xe6\x1b\xb2\x9f\x7b\x11\x42\x40\x14\xc9\x87\x25\x6b\x86\xfd\x8c\xc9\x9d\x41\xb2\xb8\x4d\x91\x6a\x08\xe5\x41\x78\xc8\x8d\x0e\xbb\x09\x6c\x0f\x9b\x86\x35\x89\x6d\x0a\x5d\x4e\x2c\x1c\xca\x53\x76\x1f\xbc\x1e\xce\x16\x8a\x39\xf1\x19\xe7\x54\x43\xc8\x66\x52\x5c\x9c\x32\x76\x18\x8d\x1d\x46\x8c\x86\xdc\x74\xaa\xbb\xa7\x3b\x2d\x47\x0f\x7f\x18\x1d\x67\x04\x97\xbb\xc4\xed\x2a\x15\x6d\x53\x8d\xa6\x1a\xce\x38\x21\xc7\x3c\xd9\x52\x10\x02\x23\xa7\x63\x46\xa6\xc5\xc6\x3e\xe3\xe9\xff\xb4\x11\x92\xcd\xdd\xdd\xcd\x52\x2f\xfe\xc6\x68\xec\xc6\xdd\x46\x63\x37\xf9\xb0\x1c\x05\x00\x97\x1b\xbc\x82\xcb\x25\x78\x0d\x26\x8d\xc1\x60\xfc\x9d\x41\x6f\xd0\x5d\x0a\x40\x71\x6c\x77\x26\x61\x7a\x7f\xb7\x51\xd1\x78\x24\x75\xb5\x4b\x61\xc0\x52\x86\x5b\xb5\xe0\xb6\x0b\x4e\x86\x8c\xeb\x87\x48\xde\x94\x99\xa4\xd7\x13\x64\x02\x41\xca\xeb\x26\x80\x1f\x45\xe5\x29\x1c\x92\xfb\x5a\xb6\x1a\x32\x8d\x8f\xdc\x03\x7b\x3d\x3c\xcd\xb1\x9c\x5c\xc3\x05\xd5\x37\x46\xa3\xd4\xab\x52\xa9\x39\xe3\xc0\x4f\xfd\x41\xa3\x29\x5f\xc8\x77\x99\x3a\xcc\x3c\x90\x31\xbf\xd4\xcb\x9b\x3b\x5c\x63\x4a\x82\xb9\x01\xb3\x45\xc8\x2d\x29\xcd\x92\x6e\xb0\x5f\xd5\xd2\x75\xf8\x70\x57\xcb\x55\xf6\xce\xac\xd2\x92\x5c\xc1\x62\x0e\xe4\x06\x4b\xc6\xb8\x56\xd9\x96\x24\xe4\x87\x4e\x2c\xb1\xad\x32\xb9\xf2\x85\x7c\x93\x31\xe8\xa7\x17\xb8\x8c\xf8\x0f\x2a\x51\xd5\xcb\xd0\x1a\x73\x6a\xcc\x2a\xbf\x2f\xe1\xf2\x19\x3b\x86\x2e\x6e\xe6\x3b\xac\x39\x31\xb1\x29\x50\x18\xad\x9a\xec\x99\xbd\xfa\xf0\x1b\x87\x57\xcf\xf6\x4c\xae\x8a\x16\x06\x9a\xc4\x58\x8e\xb5\x6a\x62\x77\x4f\xf7\xc4\x2a\xa3\xcf\x95\xf0\xf9\x57\x8d\x49\x99\xad\xda\x33\xb1\x01\x1c\x32\x21\x37\x19\x93\x10\xf0\x0b\x32\x8a\x5e\xb7\x29\x4c\x7c\xa3\x40\x2d\x17\x4f\xaf\x4c\xa7\x2b\x01\x3f\xb2\x4b\x9a\xfe\xf3\xf4\x4e\x7c\xf9\xb9\xd0\x2a\x89\xee\x69\xa0\x97\xfe\x09\xf4\xa3\x03\x29\xd0\xc3\xca\x73\x6c\x9e\xc8\x6d\xc8\xbb\x6a\xc4\x04\x50\x00\x8d\x41\x53\xd1\x62\xa2\x41\x1c\x60\x87\xf8\x9b\xe2\xb1\x68\x44\x59\xab\xb6\x0b\x72\x73\x1f\x50\xb6\xf8\x09\x02\xee\xb4\x7a\x87\xa2\x11\xe7\x04\x41\x91\x81\x97\x4f\x33\x06\x44\xb2\x44\xe5\x33\x0e\x47\x45\x23\xca\xa2\x94\xc0\xae\x69\x88\x72\x46\xae\x30\x4b\xa7\xcb\xcf\xd5\x08\xdb\x7e\x77\xe1\x65\x9f\xc4\x56\x37\xdb\x4b\x92\x42\xe3\x4a\xf9\xe7\xa0\xed\xd3\xd7\xdd\xf8\xd2\xd5\xfd\x7f\xba\xfb\x9b\x17\x0f\x25\x20\xf1\xcb\x3f\x43\xab\xb0\xe9\xc6\x53\x8b\x85\xc2\x2c\x8b\x43\x67\x9e\x38\xd1\xac\x8b\xd4\x99\x17\x03\xba\x4c\x28\x14\x2c\x0e\xbd\x79\xf5\x6a\xb3\xde\xe1\x48\x98\xe1\xe1\xea\x45\xb6\xd2\xb2\xac\x5c\x4a\x53\xe5\x9c\x38\xe9\xc2\xd7\xb7\x1d\xb8\x20\x77\x9a\x90\x2c\xb1\x37\x1e\x7a\xe3\xd0\xba\x69\x57\xbf\xf8\xd7\xbb\x6f\xfc\xcc\xfe\xe8\x67\xd2\x2f\xff\x98\xfd\xc4\x05\x0f\xee\x77\xeb\x4d\x75\x8e\x4e\xc0\x9d\x8e\x84\x4f\xef\xb8\xba\x41\xca\x7a\xc1\xa3\x37\x27\x1c\xb7\x3f\xf7\xcb\xdb\x1c\x75\x26\xb3\x2e\x07\x61\xe4\x1b\x44\xcc\xfb\x64\x1f\x7e\x2d\x42\x0c\xe9\xf5\xe4\x77\x55\xe1\x65\x64\xe5\xaa\x1a\x8d\x24\xa8\x90\x93\x22\xf0\xdc\x7c\x20\x9a\xa4\x74\x40\x0c\x04\xa9\xe8\xd0\x12\x1b\xe1\xf8\xf2\x16\x41\x90\x26\x16\x5f\x44\xd5\xd4\x49\x09\x4e\x15\xf3\xfe\xc5\x3f\xdf\xb1\xe3\xe7\x17\x9f\xdc\x78\xb3\xfb\xc0\xc9\x35\x8f\x5e\xb8\x24\xe6\xd5\xa9\x73\x4b\x67\x75\xcd\x2c\xc9\x51\x09\xb9\xab\x03\x05\x1b\x0f\x9b\x4b\x63\xed\x6d\x93\x73\x0d\x9b\xae\x5e\x51\x58\xd8\x7a\xd9\x0b\xdb\xb6\xbe\x78\xc9\x02\xd1\x59\x1c\x2b\x31\x61\xd6\xe2\x88\xf8\x82\xb9\x56\x43\x8b\xdf\xdf\xb0\xb4\x48\x23\x36\x5c\x3c\xaf\xe9\xa2\xb6\xc9\xe5\x1e\x8b\x06\xeb\xe7\xef\xd8\x31\x7f\xc1\x8e\x1d\xcf\x18\x1e\x3c\x7f\x4a\x72\x5a\xd1\xb8\xb9\xb3\x67\x86\x79\x4b\xd9\xd8\xb0\xcf\x5b\x56\x1d\xe0\x3d\x65\x39\x4e\x0c\xe7\xcd\x74\x94\x96\x88\xa1\x52\x8f\x9e\x8b\x2f\xd8\x70\x65\xfb\xb4\xfd\xbb\x16\x57\x45\x66\x76\xad\x0c\x07\x27\x17\xe7\x69\x34\x66\x31\x36\x2f\x66\xb4\x00\x24\xa6\xf9\xb3\xc4\x58\x79\x75\x5e\x76\x55\x2c\x19\x9f\x10\x9b\x1c\x1e\x69\x87\xa7\xd8\xaf\x9f\xb5\x7b\xe0\x1f\x15\x1e\x29\xc4\x8d\x7b\xcd\xfc\x20\x99\x7b\x02\xe2\xcd\x70\x66\x28\x35\x5a\x73\xbb\x03\x93\x37\xf9\xf4\xa2\x50\xc6\x0f\x83\xa3\x94\xb5\xe9\x11\xfc\x33\x02\x59\xb5\x41\x68\x84\x35\x3c\x72\x25\xc0\x18\x04\x17\x0f\x46\xbb\x7f\xa4\x56\xda\xc8\xb5\x86\x4c\x18\x97\x9d\x69\xd3\x0e\xb7\x42\xc1\xa9\x03\x07\x4e\x49\xef\x9c\x3a\x70\x00\xbe\x96\xf3\xd0\x7b\x3a\x53\xe4\x8b\x19\x9d\xf1\xfe\x07\x0e\x9c\x1a\x3e\x6b\xda\x19\x59\x1f\xe1\x3f\x63\xfc\x6a\x90\xfb\xf3\xd1\x25\x79\x86\x84\x79\x72\xe4\x15\xa0\xf7\xbf\x2b\xab\xb3\xca\x87\x1a\x55\x3e\xff\xb2\x74\xe2\x23\x6d\x35\xff\x5d\x69\xac\x3d\xfd\x3c\xff\x0f\x45\x30\x1a\x1f\xe5\x47\xb5\x08\xf9\x2d\xc4\xa0\x99\xd0\xab\x83\xc5\x6d\x21\x28\x6e\x05\x04\x3f\xec\x86\xec\x7e\x13\x79\x19\x33\x3d\x6c\xc6\x1f\x73\xd9\xd9\x0f\xbc\x94\xc5\x92\xf7\x63\x2a\xcf\x62\xa1\xbc\x6c\xdb\xdc\x1f\x67\xcf\xa5\x7c\xd9\x80\xc8\xa4\x49\xfe\x42\xd9\x3e\x69\x97\x18\x11\x0f\xbf\x71\x58\x8c\x88\x1f\x43\xe2\xe3\x94\xf4\x42\xae\xdd\x66\xb3\xe7\x42\x15\x35\x71\xe0\x47\x8a\xcb\x72\x8f\x54\xdc\x74\xff\x64\x10\x29\xda\x13\x72\x0b\x35\xe4\x3f\xfa\xf1\xc7\x19\x3b\x3b\xd9\xb1\x11\x86\xa2\x6a\x34\x19\xad\x21\xb3\x78\xb9\x1d\x1f\xc2\xfc\x66\x14\x30\x20\x01\x01\x2a\x08\xbc\x02\xb3\xf6\x0f\xe5\xdc\xae\xbc\x25\xc3\x7e\x4b\x2c\x08\x44\x8f\x54\x08\x87\x62\x40\x79\x09\x6e\x33\xf3\x33\x10\xfc\xac\x97\x0a\x42\xf1\x10\xcb\xbf\xdc\x3e\x93\x5c\x1a\x36\xaa\x26\x05\xfb\x51\x70\x92\x6a\xa3\x41\x0e\xc3\x72\x87\x17\xbb\x70\x61\x44\xfe\xf6\x67\x43\x8f\x18\x11\xc5\x88\x08\xa9\x8c\xdb\xe1\xc2\xde\x48\x21\x76\x61\xaf\x83\xc9\xf6\xf7\x5f\xdc\xb6\x7b\xb9\x65\xef\x82\x3b\x15\xbc\xfa\x9d\x0b\xf6\x5a\x96\xef\x6e\xd3\x8e\x2f\xbd\x53\x74\x48\x72\x44\xe9\x78\x4a\x2e\xc1\x74\x57\xb0\xa6\x26\x88\x0f\x37\x76\x35\x0e\xf4\xe1\x42\x07\xf4\x38\xbc\x74\xa1\x43\xea\xc8\xf6\x24\xa1\x87\xd0\x2c\x74\x90\xe2\x39\xed\xb7\x41\x8f\xa3\x90\xf6\xca\x81\x42\xec\xa1\xdf\x93\x96\xc1\x63\x2d\xeb\xe4\xc3\xeb\x5a\xa4\x89\x70\x4b\x49\xa5\xec\xaf\x44\x18\xb9\x07\x53\xec\x47\x64\x0e\x36\x1d\x21\xb0\x78\x29\x90\xeb\x01\xe5\x0e\x09\x76\xb2\xb8\x44\x11\x34\xa8\x18\xb7\x78\x87\x7d\x72\x2d\x21\xeb\x48\x23\x7c\xb1\x8c\x3e\x7e\x78\xd8\x27\x5f\x81\xfa\x28\x29\x25\x29\xa9\x92\xcb\x92\x1e\x4b\x42\xdc\xa0\xd1\xd0\x95\x8c\x43\x7a\x6c\x06\x97\xd5\x67\xd4\xa8\xa9\x69\xd2\x0c\x2e\xeb\x63\x03\xf1\xbd\x24\x3b\x95\x5c\x16\x4c\x4c\xca\x7e\x92\x12\x26\xce\xe0\xb2\xfb\x0c\x99\x94\x19\x9f\x7c\x1d\x35\x46\x80\x06\x11\xfc\xd0\x97\x35\x88\x74\x3c\xdf\x97\x25\x3d\x9a\xa5\xd3\x19\xa1\x72\xc8\xd5\xe9\x8c\x7d\x59\xa0\x1c\x83\x49\x72\x9c\xf4\xe2\x90\xab\xd3\x29\xf3\xcf\x55\x83\x88\x39\x94\xb1\xd7\x34\x11\x8b\x7b\x81\x33\x09\x1c\xa5\xa6\x4c\x14\xa7\x06\x01\x90\x11\x13\x6b\x4b\x6c\x34\x13\x96\x4d\x6a\xf2\xc1\x43\x87\x0e\xee\x82\xd7\xa4\x13\x10\x92\xca\x07\xdb\x20\x29\xf5\xb6\xa1\x41\xfc\xdb\xe4\xba\x7b\x9e\xfd\xfe\xd9\x7b\xd6\x25\x87\x3c\xf0\xe9\xc1\x43\xd4\xde\x43\x07\x07\x16\xc3\x6b\x10\x82\x10\xbc\x96\x3e\x82\x06\xdb\xa4\x67\xa4\x67\xda\xd0\x20\x74\x4b\xed\xd2\x0b\x2f\x6d\xaf\xa8\xd8\xfe\x12\x54\xc1\x6d\x50\xa5\xf8\x95\x77\xb3\x60\x10\x51\xef\x0c\xe7\x0b\xf9\xe3\x01\x53\x3c\x60\x51\x83\x09\x02\x6a\x88\x83\x09\xf0\xec\xfb\xef\xbf\xff\x7e\x17\x2c\x4b\x7f\x2e\xbd\xbd\x1a\x36\x49\x7b\x57\x43\x21\xce\x59\x7f\xdf\x7d\xb0\xf6\xbe\xfb\xd2\x7f\x93\x6e\x49\x7f\x86\x5f\x90\xde\x59\x0d\x9b\x61\xf3\x6a\xe9\x1d\xfc\x42\xfa\x33\xc5\xae\x26\x83\xf5\x32\x20\x01\x15\xa2\x0a\x84\x86\x57\x8e\x86\x57\x90\x58\xc2\xe6\x67\xb1\x72\xa0\xac\x1f\x46\xe2\x40\x1a\x67\x3a\x73\x84\x41\x4d\x9d\x4d\x4d\x9d\xe9\x26\xe2\xd0\x4d\x1f\x2b\x4c\x7d\x97\xe8\xfb\xfb\x2c\xae\x1e\x87\xa8\xa7\x5d\xc4\x4d\x77\x64\x8e\xbc\x22\xa7\x6b\xa2\x48\xf2\x26\x29\x7f\x88\xd8\xaf\xd7\x6a\x3e\x95\x72\x88\x0e\xab\x99\x49\x39\xc4\x27\x32\xd1\x64\xdd\x88\x1a\x9c\xc8\xa6\x99\xc7\xc8\x2a\x89\x11\x09\x28\x0f\x21\x8b\x1a\x82\x10\xb7\x14\x02\x54\xc8\xcd\x53\x2c\x04\x16\x3b\xcb\xa9\xa1\x42\xf6\x0b\x9d\x54\xd6\xc0\x2d\x66\x9e\x5b\x0e\x27\xf0\x41\xe9\xe1\xf4\x37\xcf\x4b\xa1\xe7\x55\x21\xa6\x7c\x39\xc7\x9b\x07\x6e\xa1\xb2\x48\x50\x45\x25\x06\xd4\xf8\x7c\x7d\xb1\x0d\x22\x03\x6a\xb6\x35\x7d\x0b\x5e\x26\xa4\x2f\x95\x5e\xb1\x15\xeb\xd3\x57\x51\xff\xc4\xcb\x04\x61\xc4\x7a\x5b\x1f\xa2\xc8\xae\x4b\x05\x42\x10\x8e\x7a\x81\xd8\x90\x07\x04\x27\xc4\x09\xc3\x24\x63\x95\xa7\xeb\x0a\x7c\xd2\xa3\x80\x27\x15\xd9\x0f\xb9\xb3\x30\x43\xaa\xa7\x87\x1a\xdf\xb9\xe7\xf2\x1f\x3b\xa0\xe5\x87\x83\x97\x48\x05\x84\xdb\x20\xb5\x74\xbe\x94\x7e\x74\xdb\x89\x31\x96\x26\xcb\x98\x13\xdb\x1e\x95\xd2\xf3\x97\x7e\x03\x47\xe0\x0b\x38\xf2\x0d\xee\xed\x4b\xbf\xb1\xd0\x87\x61\x51\x63\x47\xf3\x62\x80\x8b\xfa\x7a\x9f\xb8\xe3\xbc\x1d\x47\x3e\x5c\xd9\x02\xd0\xb2\xf2\xc3\x23\x3b\xce\xbb\xe3\x89\xd7\x95\xce\x60\x88\xbb\x61\x68\xfd\x44\x99\x67\x59\x50\x01\x2a\xce\xd8\x7c\xdb\xbc\x51\x0b\x51\x22\x73\x9f\xfe\x90\xa5\x7e\x08\x70\xc4\xf8\x24\xd3\xc5\x41\xdc\xcd\xc4\xdd\xcc\x28\xdc\x1e\xa6\x06\x06\x06\xa8\x6f\xa5\x7b\x61\x4e\xba\x03\xf7\xa4\x3b\xa8\x80\x4e\xe5\x92\x2e\xfb\xdd\xef\xa4\xcb\x5c\x2a\x9d\x4e\x45\xbf\xa3\xd2\x0d\xdc\xfd\x98\xd4\x85\xf7\x7c\x20\x75\xe1\x4f\xe6\x26\xfa\x0b\x12\x73\xe7\x26\xe8\x77\x12\x73\xf1\xfa\x54\x0a\x0d\xee\xd8\x21\x41\x2a\x05\x48\xf1\x0f\xdc\x2e\x9f\x31\x88\xee\xbd\x17\x90\x4e\xd5\x5f\xa0\xd2\xe9\xe8\xf6\xc3\x87\x0f\x5b\x4f\x9f\x36\xf7\x0c\xcc\x4a\xbe\xdc\x2b\x41\x66\xc3\x9e\xcd\x07\x27\x25\xd8\x05\x27\x2d\xd8\xe3\x31\x39\x06\x43\x90\xc1\x01\x97\x0e\x9c\x14\x0f\x1c\x6b\x03\x2f\xf0\x38\x88\xa9\x54\x67\xe5\x9e\xd7\x3c\xbe\xf9\x9a\x40\x20\xb1\xbc\x25\x5a\xa2\xa6\x4b\x9a\x37\x6d\xbc\xae\xf1\x46\x80\x50\x34\x77\xea\x2b\xd2\xcc\xa6\xf5\xb3\xaa\xc7\x04\x1b\x03\x60\x82\x67\x21\x7a\xf2\xaa\x99\x4e\x86\xd7\xeb\x61\x5c\xa7\xf4\x47\xfb\x9e\xce\xfb\x0e\x3d\x8e\x5f\xfb\xd5\xcc\x97\x37\x59\x4c\x05\x46\x67\x7e\xf1\xf2\xdd\xed\xb3\x4d\xaa\xd9\x57\xdd\xb3\x73\xb3\xab\x9e\xa5\x3c\x3e\xdb\x18\x08\x49\x17\xd7\xec\x3c\x72\xc3\xfb\xcf\x43\xe8\x8a\x49\xdd\xc7\xef\xfa\xfc\x9e\x4f\xb7\xcc\x9e\x2d\x48\x8f\x41\x1e\xce\xe2\xb1\x6b\x2e\x1a\x81\x6d\x2b\x23\x3b\x58\x44\x61\x1e\x05\x81\xa3\x5d\x7e\x91\x27\x7b\xc9\x3c\x36\x00\x4b\x00\x08\x75\x10\x8b\x87\xed\xf9\x60\x0f\x87\xe2\x09\x28\x83\x20\x0e\xc8\x63\xfc\xcc\x1b\x49\x8f\x9a\x8b\x8c\x66\x29\x1a\x3d\x57\x61\x96\xe9\x4a\x1d\x52\xbf\xf4\xa5\xd4\xef\x28\xd5\xe5\x38\x9e\x5b\x83\x73\x1c\xb9\x6a\x8d\x3d\x5b\xcd\x97\x18\x55\x31\x53\x91\x29\xa6\x32\x96\xf0\xea\x6c\xbb\x46\x9d\xeb\xc8\xc1\x6b\x9e\x73\x48\x8f\x90\x05\x4e\xbc\x67\xdd\x53\x52\xbf\xf4\x89\xd4\xff\xd4\xba\x75\x4f\x01\x03\x4e\x60\x9e\x92\x1a\xa5\x17\xa5\xcf\x4e\x6c\xdb\x76\x02\x72\xa1\x12\x72\x89\xef\xc5\x73\xcd\x7f\xe6\x44\x72\xd8\x44\x82\xcd\x89\x94\xb2\x41\xdd\xad\x1f\xce\x9f\x68\xcb\x2e\xd7\xd0\x85\xd6\x3d\x5b\xb7\xee\xb1\x16\xd2\x9a\xf2\x6c\xdb\xc4\xf9\x1f\xde\xaa\x0b\xb2\xc7\xc8\x72\xea\xfa\x51\x77\x92\x7d\xab\xb7\x9d\x90\x3e\x1b\x75\x43\xa9\xfc\x5c\x30\x34\x44\xa1\x86\x41\xc4\x3c\x91\x29\xe3\x49\x08\x21\x3b\x31\x87\x21\xb3\x1f\x0b\xa1\xb5\x0f\x64\x10\x9c\x81\x58\x1c\x02\x1c\x1b\x04\x82\xc9\x15\xe4\xf2\x37\x80\x1f\x2b\xa0\x69\x2b\x84\xe2\x64\x56\x01\xd1\x48\x5c\x60\x6d\x56\x3b\xb3\xbd\x81\x29\xa1\x6b\x0b\x59\xaa\xa4\x8a\xf2\x5e\x13\x3f\x78\x65\xeb\xab\xd7\x5e\x76\xde\x95\x5b\x6f\x07\xd5\xa1\x5f\xb8\x5b\xc6\x30\xae\xbf\x3a\x1a\x9c\xf0\xa5\x4f\x67\x2a\x7e\x15\x36\x16\x1e\xec\xec\x3c\xb8\x72\xe0\xbd\xae\x05\x7b\x0e\x3c\x75\xb0\xff\xc0\xa6\x3d\x35\xaf\xe2\xef\x27\x94\xa5\xdf\x2d\xaa\x04\x6a\x5c\x09\xdc\xaf\x5a\xbf\xe3\x9d\x5b\xae\x5c\x7e\xd9\xb5\x27\x16\x5e\xb5\x21\x07\x4a\xe6\xfd\xc4\xc9\xd4\xb7\xe4\xbd\x29\x70\x66\xe9\x73\x5b\xd9\xb8\xd0\x97\x56\xb8\xbb\x53\xbe\xcc\xa9\xa7\x6b\xf7\x6c\x3a\x70\xea\xe0\x93\x07\xf7\xb4\xac\xb9\xf6\xd5\xb3\x34\x7e\xa7\x11\x2d\xb8\x51\x1a\xbf\x60\xe5\x31\xc7\x63\x65\xb3\x9b\x44\x27\xa8\x38\xe1\xb5\x20\xb2\x45\x04\xcd\x12\x54\x40\x26\xd8\xc5\x63\xa3\x13\xbb\x12\xd8\x18\x84\x91\xe3\x5b\xaa\x3b\x23\x51\xdc\xc3\x9b\x01\x39\x6b\x8b\x45\x57\x9e\x40\x42\xb6\x9c\x70\x7e\x5e\xb4\x64\x5e\xa4\x32\x90\x17\x56\x1b\xb5\xaa\xd5\x1a\x9a\xdb\xf6\xe9\x25\x7f\xf8\x7a\x94\x28\x3f\x5c\x3b\x7a\x50\xdc\x3c\x74\x45\x33\x7c\x12\x6a\x1e\xe3\xb4\x99\xad\xb9\x06\xb2\x8f\xd7\xe0\xad\xf6\x79\x8d\xfa\x6c\x5f\x7e\x51\x75\x8e\xb5\x4e\xc7\xce\xe4\x1c\x9a\xde\xff\x82\x71\xa7\x05\xf8\xc9\x65\xa5\x47\x46\x0d\xa5\x11\x8d\x02\x83\x14\x33\x9f\xcc\x0f\x13\x68\x3a\xea\x40\x08\x79\x86\x56\x73\xc0\xca\x8a\x01\x08\x82\x01\xd8\x7c\xb0\x50\x04\xab\x41\x66\xc3\x39\xc0\x09\x76\xf2\xce\x05\xa9\x28\x65\x51\x38\x39\xf3\x81\xb3\x33\xf2\x0c\xd2\x2e\xd8\xe5\xea\x11\xf0\x8a\x01\x8a\xf0\xd3\xca\x01\x11\xec\xb1\x3a\x88\x45\xe1\x81\xd4\xc2\x85\xa9\x56\xd8\x5b\x33\x8e\x97\xae\xe5\x78\x9a\xe2\xb4\xdb\xe0\x27\xe3\xb2\x0d\xfa\x50\x34\x2f\x9b\xc2\xbf\x64\xe6\x78\x69\x8d\xd9\xca\x71\x96\x7c\x93\x96\x0e\xfe\x5e\x58\xd0\xe8\x82\xbb\x38\x8e\x02\x4e\x5a\x53\xdc\x9a\x95\xe5\x63\xb5\x65\xde\x44\x81\x1a\x58\xbc\x9d\xba\x2e\x9f\x52\x6b\xad\xec\x06\xe9\x37\x94\x8a\xa2\xb4\xf4\x4b\xad\x63\x93\xad\xad\xc9\xb1\x69\x6f\xc8\x6b\x17\xe0\x61\x1d\x87\x29\x95\x7e\x8f\x74\xab\x14\xef\x2d\x72\xb0\x8e\x6c\x7d\x4d\x8e\x09\xcf\x87\x9e\xdb\x3f\xcc\xf2\x59\xf4\x80\x29\x9d\x35\xcb\x80\xa1\x18\x2e\xf2\x14\xa4\xff\xc9\xe8\x28\xd0\xff\x74\x7d\x5f\x65\xbc\xcd\x35\x21\xc7\xae\x73\x59\x8c\x6a\x58\x24\xdd\x5f\xa1\x62\x30\xa3\x2d\xd4\xdc\x07\x27\x81\xc6\x58\xad\x22\xdc\x67\x14\xfa\x54\x8d\xe8\x5c\x84\x91\x16\x79\x51\x05\x6a\x44\xcb\xd1\x0e\xb9\x87\xa3\x98\x48\xc6\x06\x08\x2c\xc3\xea\x12\x64\x4e\x20\x2a\x72\x6b\xf2\x08\x60\x44\x1f\x01\x56\x9e\xe2\xbc\x09\xaa\x0e\x22\x41\x2a\x10\x76\x52\xf9\xff\x41\x8c\x00\x3f\xdc\x0b\x54\xcb\xf2\x8e\x58\xa4\x75\x75\xfa\x39\xb0\xf0\xef\xf0\x16\xe9\x83\xb8\xc6\x2c\x7d\x67\xb3\xe8\x71\x89\xda\x0c\x4d\xbc\x95\xaa\xee\x7f\x41\xfa\x96\xb7\x5a\x79\xd0\xbd\x08\x37\x80\x21\xb7\xb6\x38\x2c\x56\x39\x8c\x00\xc0\x3b\x2a\xc5\xe2\xc2\x44\x9e\x09\x3f\x06\x86\xdc\xc4\xe9\xf8\xec\xa1\xf8\x87\x33\xe9\x2b\xcf\x8c\x07\xec\x04\xf5\x4f\xe7\x75\x49\xdb\x37\xc0\xcb\x69\x9d\x7c\xf5\xc4\x0c\x83\xcf\x84\xbf\xe3\xad\xcf\x4b\x17\xbf\x6f\xe5\xf1\x3f\x78\xab\xb4\x4c\xeb\x5b\xb5\x78\x4b\x71\xe9\x96\x95\xad\x39\x39\xaa\xbc\xd6\x85\xbb\xaa\xcb\xb6\xae\x98\xef\x70\xfc\x3f\xc6\x2b\xfb\x9f\x4c\x8a\xf9\x16\x4d\x41\x0b\xd1\x1a\xb4\x13\x21\x26\x12\x04\x42\xaa\x4f\xc4\x19\x03\x41\x2a\x20\x46\xe2\x09\x2a\x43\xd8\x4d\xd4\xd2\x71\xc6\xba\x9d\x23\x64\x79\xf2\x94\x50\x38\x8d\x54\x4b\x80\xc5\x23\x46\x94\xa5\x9d\x48\x2c\x24\xd8\xad\x1c\x6b\xf7\xc8\x17\x89\x19\x33\x31\x46\x4e\x89\x48\x80\x51\xcc\x44\x99\x8d\x98\xc3\x2b\x1d\x3e\x0c\x2a\xb5\xda\xe0\x13\xda\xb3\x3c\x7a\x56\xc3\xa8\xc0\xef\x07\x15\xa3\x61\xf5\x9e\xac\x76\xc1\x67\x50\xab\x55\x80\x7d\x8e\x79\x2e\x6b\xb6\x27\x59\x35\xbd\x2e\x2f\x9f\xa5\x2a\x44\xb1\xa2\x32\xa7\x6e\x13\x45\x25\x3d\xd9\x56\xd7\xbc\xa3\x0e\xd1\xe2\xf7\x5b\xc4\x88\xa5\xb1\xd1\xf6\x68\xcc\x6c\xb1\x74\x77\xcb\xa1\xc3\x87\x8f\xc9\x81\x05\x8b\x17\x2f\x90\x83\x6b\x36\x6d\x5a\x73\xa3\xb6\x7d\xab\x9a\x2e\xcd\x51\xf1\x5a\x2d\x63\xb3\xe4\xd1\x29\x29\x45\xe7\x59\x6c\x8c\x56\xcb\xab\x72\x4a\x69\xf5\xd6\x76\xad\xbd\x56\xa7\x32\x9b\xca\xe6\xc4\xc7\xe9\xb8\x55\xef\x49\xdf\xbe\xb7\x6a\x5b\xa0\xd5\x07\x60\x56\xe9\x6a\xa9\x3b\xc5\xa8\xc5\x1f\x8d\x04\x2c\x11\xd1\xd2\xf8\x46\xa3\xe5\x17\x16\x4b\xc4\xb2\x01\x6a\x36\xc8\x11\x87\xa5\x96\xc3\x2f\xca\x11\xad\x7f\x02\xf4\xa7\x56\x39\x6a\x8d\xf4\xa5\xf4\x8a\xf4\x25\xe1\x49\xb7\x12\x9e\xe6\xd4\xf0\x58\x37\x9f\x68\x1b\xc5\x51\x1d\x9a\x48\xf4\xb4\x16\xa1\x15\x68\x1d\xda\x82\x76\xa0\xcb\xd1\x35\xe8\x7a\x74\x94\xd8\xd9\x93\x1d\x15\x5f\xc6\xc5\x19\x77\x74\xfc\xbf\x4c\x37\x6a\x47\xf3\x5f\x85\xff\x9d\xfb\xaf\xce\x07\xac\x30\x17\xdf\x46\x1c\xe5\x1f\xdf\x36\x32\x2e\x7d\xdb\xd9\x29\x7e\x74\x11\x96\x65\xdc\x4d\x1c\xa9\xfb\x1c\x21\x46\x71\xd2\x67\x84\xce\x99\x32\x13\x82\x8e\xf6\xd3\x77\xc0\x8a\x23\xb5\x9f\x1d\x77\x46\x60\x80\xef\x51\xce\x96\xff\x61\xff\xd9\x81\x7e\xc5\xa1\xce\x08\x9d\x2b\xa1\xf2\x9f\xe1\x2e\x63\x07\x58\x34\xcc\x08\xdf\x84\x66\xa3\x95\xe8\x42\xb4\x17\x21\x7b\xa6\xd4\x62\x43\x4a\x99\xc0\xc1\x90\x05\x95\xd2\x5b\x52\xb6\x61\x63\xa9\x18\x91\x55\x93\x5f\x3d\x62\xed\x43\xd6\x1b\xc9\x7c\x6f\xa8\xec\xfd\x4a\x9c\x02\xea\x50\x96\x23\x5d\x76\xbf\xa2\x3b\x27\x0f\x50\x15\xfd\x35\x3b\x63\x1f\xc2\x6e\x66\x22\x94\x79\xff\x17\xe4\x7b\x16\xa0\x05\x83\x08\xee\x27\x01\x7c\x52\x88\xf8\xbc\xf9\x79\xa2\xe1\xe3\xa3\xf2\x4c\xbc\xeb\xb0\x10\xf6\x79\x0a\x02\x3e\x45\x33\x41\x8c\x88\x43\xda\x0d\x69\x92\x1e\x26\x88\x11\x71\x57\xdb\xc2\xdd\x62\x44\x3c\x01\xbe\x13\x70\x15\x19\xcf\x59\xdc\x5c\xc3\x2d\x36\x95\xd1\x14\xb1\x3d\x02\x7e\xb5\x2d\x5b\xab\x2b\x31\x2e\x7c\xd5\xce\x19\x8d\x11\xdb\x9f\x7f\x4a\x16\x1d\x6e\x52\x96\x1e\x4a\x07\xd1\x02\x40\x97\x2b\x01\x54\xbd\xb4\xa5\xac\xd0\x2b\x26\xea\x0b\x8f\x7e\x2c\x46\xc4\xc3\x5d\x55\x8b\xe7\x94\x07\x82\x91\xc5\x71\x45\x45\x45\xce\x53\x46\x18\xe2\x0f\xe4\x14\x82\xf6\x68\xdb\xb5\xab\x4d\x76\x0f\x9c\x38\x71\x8d\x3c\xb4\xb3\x5b\x1e\xda\x6c\x8c\xd8\x6c\x2a\xe3\x95\x97\x92\xa1\xde\xd7\x37\x1b\x23\x36\x3b\x67\xcc\xe0\x70\xa9\x41\xa4\x4a\x67\x70\x16\x2b\xd0\xcf\xc8\x78\x3e\x63\xf9\x4e\x46\xbb\xb1\x78\xcc\x1f\x29\x23\xd6\x35\x19\x71\x45\xb9\xf7\xe1\x89\xe9\x37\x17\x52\x20\xb1\x72\x89\x86\x08\x32\x1f\x8a\x41\x0c\xf8\x15\xa9\x3f\x31\x56\x07\x96\x98\x39\x1e\x73\x82\x7c\x6a\x2c\xa3\x89\xc7\x72\x8a\xd4\xa2\x9f\x10\xf3\x51\xac\x82\x66\x17\x63\xf1\x58\x7c\xe8\xb7\x22\x7e\x65\x8c\x98\x20\x30\x83\xb8\x67\xf8\x40\x38\x13\x5d\x8d\xed\x02\x23\x37\xca\xb4\xaa\x3a\xdb\x94\xf0\x47\x1b\x7d\x1a\x4f\xb9\x3f\x61\xca\xc6\x1b\x87\x7c\xd5\x99\x23\xd2\x5c\x53\x93\x37\x31\x29\x5c\x4e\xe9\xa9\x85\x47\x0a\x4c\x39\x3e\xb3\xcd\x66\xf6\xe5\x98\x0a\x8e\x2c\x64\x8d\xb9\xd2\x87\x7f\xe5\x0d\x05\xa6\x1e\x2d\x6f\x7f\xfd\xa0\xe9\xd0\x05\xf9\xd3\x43\x5c\xfe\x84\xb2\x0b\xf7\x17\xd4\xd1\x4c\x79\xc1\xec\xc6\x60\x74\xe3\x0a\x9f\x83\x3a\x3e\x9c\xc2\xe1\x2d\xcd\xcb\x56\xd2\xd0\x2a\x5f\x7c\x64\x2a\xf3\x7f\x73\x2b\xe0\x73\xc1\x2b\xdf\x0b\x27\x71\xd4\x13\x68\x8c\x56\xba\x55\xf9\x01\x4f\x74\x67\xc6\xc5\x24\x16\xcc\x5e\x87\x29\xdf\x04\xcb\x66\xf9\x1a\x4d\x6a\xb5\xa9\xd1\x37\x6b\x19\xc6\x39\x5b\x39\x2f\x24\x85\x0a\xfd\x16\xd0\xde\x0c\xa6\x65\xd9\x5c\x62\x9a\xa3\x7a\xfc\x6c\x13\x53\x5e\x50\x50\x47\x6b\x4a\x35\x21\x73\xe3\x76\xa9\x57\x4e\x21\x7d\x77\xb3\xf4\xd7\x65\x76\x6f\xbe\x92\x02\xca\x7d\xc3\x29\x7c\xff\xe2\xda\x67\xd8\x1c\x5b\x50\x03\x9a\x86\x16\x22\x04\x0a\x3a\x4a\x74\x0d\xe3\xa4\x42\x76\x45\x9b\x82\x84\xc8\x9b\xc8\xc3\xd0\x7b\xca\x12\xf8\xbf\xf2\x9e\x52\xd1\x48\x10\x40\x18\xb6\xbb\x13\xec\x56\x03\x25\x06\xea\x20\x16\xa2\x5d\xf2\x0b\x22\xbd\x7f\x42\x8c\x88\xbb\x1f\xdd\xdd\x29\xbf\x42\x72\x85\x27\xd2\x26\xbe\x40\x81\xc7\x17\x16\x0e\x77\xc9\x75\xf8\xe8\xc7\x06\x31\x2f\xdf\xeb\x8b\x08\xad\x37\xa7\x9f\xfb\x24\xfd\x94\xce\xa3\xbb\x4b\xa7\x63\x93\x77\xe9\x74\x27\x1d\x13\xeb\x2f\x69\xfd\xad\xde\x83\x7b\x33\xd5\xfd\x40\xa6\xfa\xc3\xa7\xad\x37\xbf\xb9\x59\x0e\x28\xef\x49\x7c\x71\x24\x18\x28\x9f\xb3\xb8\xaa\x8b\x2c\x6b\x1e\x2d\xac\x4f\x88\xde\xc2\xb2\x96\xa5\xd5\x9b\xdf\xbc\x39\xbd\x57\xbe\xac\xee\x2e\x9d\x47\xc7\xb2\x77\xe9\x3c\xfa\x93\xd9\x13\x6f\x5c\xd9\xfa\x5b\xdd\xc8\x35\x7c\x2b\x6a\x21\xaa\x4b\x56\x8e\x07\x85\x67\x3c\xb3\xc7\x13\x0e\xd9\x21\x33\x14\x08\xc8\x43\x79\x79\x48\x80\x89\xed\xbe\x82\x42\xf7\x7a\xa2\x11\xb9\x28\xc8\x1b\x95\x21\x3d\x49\x10\x2e\xf1\x0c\x60\x3c\x7c\x36\x3b\x1a\xb5\x44\xaf\x2d\xd4\x60\x46\x6b\xd5\x8e\x89\x4c\x68\xc8\x15\x72\x4d\xf0\xc5\x34\xbd\x4d\xdf\x7a\x39\xa6\x2a\xbe\xcd\x2a\x69\x3f\x34\xe5\x27\xd7\x65\x03\x6d\xe7\x1b\x4b\x8b\x6c\x79\x4e\x3b\x97\x35\x3e\xdf\x5b\x95\xbd\x62\xde\xcc\x03\xf3\x6d\xac\x85\xa1\xb4\xe7\xaf\x29\x9f\x0e\x14\xa3\x7e\xf4\x0c\xe3\xbc\x74\xce\xb8\xd0\x8b\x21\x2d\x05\x78\x69\xb2\xe5\x3e\x91\x77\x4b\x55\xfc\x85\x8c\x6a\x2a\xb6\x7f\x32\xf6\x24\x6b\xba\xf6\xc9\x45\x07\x6e\x65\xb1\x67\x56\x64\x49\x59\x56\x99\x2b\xdb\x00\x14\x67\xcf\x6b\x98\xe9\x69\x59\xdd\x75\xa0\xd9\x3e\xdf\xae\x63\x6b\xcc\xa0\xc6\x86\x33\xcd\xf4\x10\x46\xfe\x41\xc4\xbc\xc7\x0c\xa2\x6c\xb4\x1c\x21\xc2\x57\xe7\xe1\x58\x6c\xb3\x3a\x71\x38\x64\x4f\xe0\xb8\xdc\x08\x80\x95\xf5\x06\x94\x23\xa4\x14\x29\xaf\x67\x58\x26\xdd\x2a\x57\x20\xb9\x68\xa8\x78\x34\x22\x16\x29\x90\x2e\xa2\xa2\x19\x76\x99\xac\x98\x53\xa8\x81\x9c\x80\xbf\xa4\xf5\x79\x42\x20\xb0\x72\xb5\xc9\x37\xbe\x8c\xce\xd5\x59\x35\xd8\x98\x34\x5a\xf0\xb7\x06\x15\x6b\x6f\x4e\xe6\xdf\xf9\xa8\x81\xd5\xe4\xa9\x84\xf6\x5d\x0f\x75\x5c\x7e\x34\x30\x2f\x26\xde\x0e\xee\x60\xd0\xe5\x76\x95\x36\x47\x8b\xed\x0c\xa7\xd1\x68\xe0\xd3\x53\xe3\x2f\x7c\x6a\x6d\x24\x06\xe7\x37\x31\xd4\xf2\x63\x73\xed\xf9\x96\x6d\xf4\x6f\xb3\xf2\xf2\x0d\xc2\x18\xe9\x9f\x57\x96\xcc\x9a\x56\x06\xc0\xe8\x34\x53\x21\x3a\xb5\x35\x7d\x27\xa7\x07\xca\xa8\x6e\x53\x59\x7c\x7b\xf2\x5b\x8f\xdf\xd0\x7e\xe7\x15\xd1\xd4\xca\x71\xb9\x20\x04\x42\x93\x44\x77\x41\x5d\xdb\xf9\x1d\x45\x6a\x4c\xc1\x77\x9f\xac\xfe\xe4\xb9\x7d\x16\xb5\x74\xc3\x12\xe9\x36\x1f\x55\x95\xd0\x73\xcf\x20\x0a\xc1\x20\x62\x77\x30\xfd\xa8\x16\xcd\x44\x97\x23\x04\xa1\x7c\x79\x4a\x43\x66\xc1\x9c\x1e\x32\x15\xc9\xef\x26\x9a\xaa\xe1\x52\x50\xda\x36\x60\xfc\xc4\x13\x0e\x09\x8c\x10\x52\x0c\xe4\xe4\x09\x12\x27\x94\x61\x6a\x08\xc8\x9e\x0f\x72\x55\xb4\x83\xc5\x6e\x00\xd6\x00\xb1\x32\x10\x49\x3b\xcd\x51\xca\x96\xa2\x1a\x14\xd7\x92\x09\x5b\x04\x27\x49\x14\x8b\x87\xec\x54\x9d\x2b\xe7\xc3\xda\x8a\x03\x05\xda\x49\x6c\x99\x2b\xfd\x37\xa9\x47\x1d\xa8\x8a\x89\x40\x4b\xc9\xc2\x2a\x8c\x6b\x02\xf0\x78\xfa\x9f\x85\x21\x96\xad\xf2\x6b\xe0\x63\xe9\x27\x62\x39\xcb\xc6\xbc\x2c\x0f\xbd\xef\x02\x0d\x82\xc1\xfa\xb8\x97\xcf\xce\xb1\x3d\xfe\x1e\xe3\xfb\x1a\x28\xc8\xd2\xba\xf2\xa7\xe4\x5c\x8d\x59\x70\x99\xa9\x3b\x0c\xb4\xa1\x5c\x17\xef\xc2\x85\x07\xa2\xc9\x0f\x3d\x45\x61\xff\x9f\xb3\x79\x8f\x7b\x6a\x16\x68\xa4\x53\x36\x9b\xdf\xdb\x68\xfd\xdb\x15\x06\x9b\xc7\x3f\xcd\xf4\xec\x72\x95\x33\x0b\x74\xb8\xb2\x30\x50\x49\x2d\x32\x1f\x2c\xa8\xba\x27\x58\x23\x2d\x75\x15\xd3\x95\xae\xca\x02\x7f\x8c\x71\xd5\x14\x06\x22\x90\x64\x92\x85\xde\xd2\x9a\x76\x4d\x9d\xdf\x57\x8a\x3b\xfc\x10\xd4\x5f\x24\xcc\x70\x8b\x2f\x5f\xe4\xc7\x22\xb0\xc0\x40\xfe\xb4\x6c\x41\x9b\x7b\x1d\x30\xb8\x74\x35\xdc\x29\x7d\x3f\x79\xca\x1f\xaa\x73\x63\x89\xb2\x7b\x6a\x8b\x0e\x0a\x7e\xa8\x74\xcf\x10\xec\x46\x97\xd4\x03\x2f\x78\x9b\x2d\xe6\x2c\x8f\xb4\x10\x66\x78\xa7\x99\x2c\x0e\x51\x5a\xfc\x2b\x03\x63\x35\xf6\x15\xd6\x40\x95\xd2\x06\x3a\x39\xc4\x2c\x41\x33\x51\x1b\x5a\x83\xba\x11\xf2\x2b\xe2\x05\xd1\x48\x82\x8d\xc7\xfc\x62\x34\xa2\xd8\x9a\xc4\xc2\x2e\x24\x8f\xed\x15\x13\x6d\x32\x7d\xc7\x84\xf2\xdf\x01\x4a\x30\x00\x2c\x67\x47\x36\xab\xd7\x23\x96\x01\x45\x04\x0b\x2c\x56\xbf\xe0\xb3\x60\x3f\xa1\x69\x40\x72\x8d\xb7\x67\x5a\x52\xd1\xeb\xf1\x07\x04\x98\x8e\xe9\xb9\x77\x54\xd9\x68\x5a\xc3\xf1\xac\x19\x3f\x0a\xba\xb5\xa6\x4d\x3a\xb3\x66\xfb\xc2\x65\xa0\x81\xdf\x5e\x67\xb5\xb6\x0e\x5e\xbf\xd6\xb4\x49\x6b\xd1\x6c\x4f\x4a\x0d\xdc\x98\x42\xea\x87\xaf\xd5\xfa\xea\x2a\x4a\xaa\x0c\x14\x67\xc1\x76\x2d\x7f\x25\xdd\xd5\x57\xe2\xc1\x2e\xee\x67\x54\xa4\x02\x4c\xc7\x7f\x2e\x9d\x1c\x37\xa9\x5d\x5a\x9b\x6b\x9d\xbb\x2d\xb7\x20\xf7\xa1\x8b\xad\x30\x53\xcd\xfd\x1c\x57\xfd\x6c\xa1\x33\xa0\xb6\x1a\xad\x3a\xbb\x4a\xa0\xfa\x37\x3c\xaf\xb7\x68\x92\xc6\xcf\x2d\xd2\x57\x5f\xe6\x37\xe5\x5f\xfd\x51\xf2\x79\xbd\x55\x9d\x34\x7e\xbe\x85\x8a\x70\x59\x02\x23\xc5\xa4\x49\x14\x87\x29\x8e\x9a\x9c\x5b\x50\x9c\x1e\x47\x6b\x4a\xd8\x5f\xc3\x91\x68\x94\x2a\xd1\x49\x8f\x69\xce\x6b\x5d\x07\x66\xb0\x75\x27\xef\x5e\xd8\xf5\x14\xae\x2e\xc8\xdd\x36\xd7\x9a\x9b\x6b\xbd\xf8\x21\x13\xcd\x0d\xe1\xc8\xae\xa7\x25\x66\x25\xca\x47\x65\x44\x2f\x57\x6e\x4d\x15\x78\x29\x69\x04\x04\x96\xcb\xc0\x71\x5d\xf2\xcc\x29\x16\xb7\x07\xac\xd8\x00\x9e\x40\x82\x8e\x46\x02\xf6\x80\x4d\x0c\x38\xc1\xe2\x09\xc8\x43\x03\x1e\x38\xa5\xf9\x95\x1b\x52\x45\x58\x89\x76\x5c\x77\xf0\x8b\x2f\x0f\x5c\x77\xc5\xb7\xd7\x75\xcc\x75\x71\xf5\x53\xef\xfc\xf4\x63\x98\xd9\xe7\xaa\xaf\x2a\x7c\xe5\xe8\x51\x3e\xcf\x3d\x6b\xc7\xa4\x52\x03\x15\x8f\x4f\xbe\xb4\x65\x4d\x7a\xd6\xd4\xf7\x26\x59\x70\xd1\x2f\x57\x79\x3d\x8e\xe0\xba\xea\xf6\x9c\x29\x59\xae\xf5\xf0\xc0\xdb\x47\x7f\xf2\x93\xa3\x6f\x5f\xf7\xcf\x03\xf9\x89\x64\xee\xf7\x77\xdd\xf3\xd5\x57\xf7\xcc\x9f\xaa\xf7\x2d\x69\xec\x95\x4e\x2c\x03\xc6\xb5\xef\xae\xdf\x3d\xd8\x3a\xde\xd3\x73\x1b\x7e\xeb\x93\xea\x41\xe9\xb1\xc6\xad\x3b\xfc\x96\xf6\x6b\xb3\x63\xd5\xfe\xd9\x8e\x12\xa7\x71\xce\x98\x95\x07\xd7\xd4\x4e\x5d\x35\xc4\x8f\x45\xfa\x0e\x07\x2a\x44\x41\xd4\x80\x66\x13\x06\x0f\x02\x1f\x63\x33\x74\x01\x42\x2c\xae\xa8\x24\xbb\x62\x14\x11\xbc\xe2\xec\xd5\x10\x33\xc9\xbd\x45\xc0\xce\x44\x08\xe2\x80\x88\x1c\xca\x4f\x9c\x19\x8a\x8d\xea\x2c\x68\x47\x6e\x61\x89\xfd\xa6\x2f\x6f\xbe\x65\x63\xb4\x94\x16\x6a\xc6\xde\xf4\xdb\xdf\x42\xe4\xb7\x0f\x61\x4d\x7e\x68\x5e\x95\xcd\xa6\xf9\x83\x48\x37\x8f\x59\x08\x97\x84\x0b\x67\x8d\x6f\xce\x9a\x72\x69\x1e\xbd\xaf\x21\x32\x26\x3c\xcd\x66\x82\xc9\x23\x3b\x07\xf8\xeb\xb4\xf1\xd9\xea\x50\x72\xf3\xb1\x63\x9b\x37\xde\x6d\x29\x2e\xb1\xbd\x2b\xbd\xfc\xc6\x9b\x90\xce\x2a\xab\xdb\x7a\xed\xc6\xc5\x76\x6a\x0f\x18\x37\xad\x69\x7e\x24\x70\x4b\xe1\x79\x93\xe6\x0a\x96\xf1\x63\x0b\xfc\xa6\x65\x63\x23\x5b\xc4\xc8\x94\x68\xd1\x37\x67\xf5\x09\x43\xcf\x3f\x9d\xe0\xe6\x22\x43\xef\x10\x56\x46\xe8\x5e\x4f\x20\x96\xe9\x16\x39\x56\x01\x0c\x28\x3f\x3f\x31\x10\x64\x49\x9c\xdc\x7b\x10\xa9\xe0\x70\x88\x60\xab\x48\xd7\x79\xe6\x76\xef\xa0\x7d\xdc\x79\x79\x5c\xa0\x2c\xe0\xb7\xea\x0a\xb4\xb4\x8a\x31\xf9\x2e\x9b\xf3\x42\x93\x89\xa1\x35\xba\x02\x8d\xcd\x1b\x28\x0b\x70\xc9\xcb\xec\x57\x62\x95\xc1\xa8\x0b\xf3\xde\x64\xc9\xc4\xc2\xe2\x49\xc5\x49\x2f\x1f\xd6\x1b\x79\x15\xbe\x12\x60\xf4\x6a\xd8\x6e\x3b\x63\x68\x49\x5a\x58\x83\x5d\x97\x67\xb7\x64\x1b\xf1\x22\xcb\x74\xef\xb4\x79\x77\x78\xa7\x5b\x16\x61\x43\x96\xd5\x96\xa7\xb3\x1b\x58\xcb\x55\x79\x8c\x3d\x68\x67\x8a\x2c\x6a\xa7\xd7\xe9\xf4\x3a\x55\xd6\x02\xc6\x0e\xfd\xa3\xd7\xc1\x00\x19\x06\x53\xec\x7a\x26\x45\x4a\x21\xa6\xe8\x80\x29\x40\x26\xa2\x3b\x48\x08\xb8\x84\x8c\x3c\x18\x56\x70\x4d\x19\x7b\x26\xa5\x98\x94\x62\x53\xaa\x7a\x2c\x1a\x09\x62\x85\x68\x22\x1c\xca\x88\x97\x53\xcd\x97\xbd\x59\x95\xa3\xe6\x79\x73\xbd\x39\x2f\x56\xd7\x58\xa7\xf3\xef\x9a\x9e\x1b\xc9\xfd\x03\xa7\xb2\x0a\xd6\xd9\x76\x7f\xb6\x2b\x11\x4b\x2c\x88\x45\xe6\xd7\xc6\x12\xf9\x0e\x7f\xd6\x2c\x53\xb6\x55\xc5\xfd\x21\x37\x92\x3b\xed\x52\x9f\xae\xae\xa9\x2e\x92\x67\xa8\xb7\x9a\x79\x75\x4e\xf2\x1d\x26\x05\x7b\x2e\x1c\x73\x41\xd9\x7e\x2e\xc7\x97\xeb\x2a\xb1\x04\x72\x0d\xb9\x33\xaf\x70\xeb\xb4\x6c\xde\x04\xb7\xb6\xd2\xaf\x67\x18\x6f\x61\x41\x4e\x4e\x41\xa1\x97\x61\x0c\xfe\x31\x5a\xf7\x84\x3c\x56\xab\x73\x5d\x35\x23\xd7\x90\x1b\xb0\x16\xe7\xe7\xf8\x1d\xdc\xd5\xe5\xdb\xc6\x5c\xb9\x6d\x54\x1d\x58\xf4\x7f\x5a\x07\x46\x33\x18\x30\x48\xa9\x07\xc1\x80\xdf\xaa\x2d\xd0\x91\x7a\x70\xe9\xdc\xe7\xa7\x9a\x59\x0d\xa3\x2d\xd4\x58\xbd\x81\x20\xa9\x07\x57\x61\x15\x6f\xd4\x87\xf5\xde\xb1\x4a\x3d\x18\xeb\xd5\x47\xf4\x06\x83\x0a\xae\x02\x74\xc6\xcb\xb0\xdb\xce\xf0\x2d\x63\x79\xed\x70\x25\xa8\x8b\x4c\xf3\x4d\x9b\x77\x87\x38\x55\x6c\xc2\xc6\x6c\xa5\x12\x68\x79\xb9\x12\x94\xc9\x95\x40\xa3\x54\x02\xb5\xa5\x98\xb2\x53\xda\x51\xef\x02\x28\x98\x44\x16\x91\x56\x8f\x67\x94\xe1\x0f\xc7\x72\x3e\x86\xe5\x12\x50\x07\x09\x2a\x1e\x63\xc8\xfc\x89\x62\x03\xc4\x02\x98\x0d\xe2\x32\x88\x44\x23\xe1\x50\xdc\x8c\xc2\x21\x27\x23\xc4\x13\x74\x3c\x41\xa9\xd1\xf8\xee\xfa\xa8\xdd\x4e\x69\xc2\x82\x61\xc2\xd8\x66\x55\x59\xa7\x74\xaf\xf4\xd1\xc2\xdf\x97\x4d\x33\x1a\x26\x3e\x3a\xeb\xd2\xa6\xc7\x41\x00\xb5\x96\x65\x9f\x33\xb8\x52\x9f\x1c\x90\xd0\x15\x33\x2f\x6b\x2e\xd2\x01\x7b\xd5\xc9\x5e\x58\xf3\x12\x63\xa9\x8a\x4e\xa8\x8c\xf0\xe7\x61\x31\x3c\x71\x71\xa4\x7e\xfb\x96\x7a\x16\x05\x17\x4e\x98\x5c\x54\xc6\x9a\xbf\x0a\xe6\xd5\x89\x25\x6c\xfe\x8b\xfc\x7d\xd1\x8b\x8d\x4e\x8e\xcb\x69\x74\xf9\xf5\xf9\x22\xc5\xda\xb5\xd2\x9d\x79\x5c\xd6\x7c\x0c\xb9\x41\x8f\x09\x00\xd8\x38\xac\x85\x1a\x50\x1b\x3c\xa5\x93\x83\xc7\xe9\xa9\x1d\x17\xee\x1f\x3b\x73\xcb\x14\xf7\x08\x1e\xac\x09\xa8\x05\xb5\xa3\x65\x04\xdb\x66\xe5\x02\x02\x3b\xf2\xe3\x09\xc4\x39\x71\xe4\x27\x1a\x89\x0b\x81\xd8\xc8\x4f\x38\x24\x70\x71\xfb\x19\x9f\x08\xf6\x79\xc9\xe4\x43\xae\x0e\x3e\xb3\x85\xe0\xb2\x4d\x0a\x3c\x9b\x7c\x31\x45\xcc\x5f\xfa\x2c\x81\xb7\x8e\x97\xd4\x1d\x59\x51\x3b\x7d\x3a\x2f\x36\x89\xfc\xb4\x29\xf5\x2b\x8e\x54\x57\x3c\xf4\x56\xc0\xd2\xf7\x15\xc3\x7c\xfd\xb1\x9c\x20\x58\x7b\xeb\x8a\x71\x93\xa7\xea\x7d\x01\x51\x49\x71\x6b\x6d\xf0\xf8\x9b\x7e\x5b\xdf\x57\x8c\xf3\x88\xf4\xf7\x5b\xb7\xbc\x73\x64\xe1\xc2\x23\xef\x6c\xb9\x15\xf4\x47\x26\xa7\xd7\xa5\xd7\xe1\x6b\xf1\xaf\xd2\x35\xe9\x1a\xe6\x57\x69\xa2\x5f\x80\x53\xa5\xf9\xfc\xb4\xc9\x0d\x2b\x6e\xad\x2d\x7b\xe8\x6d\xbf\xfd\xb3\x6f\x58\xf6\xeb\x4f\x2c\x05\x6f\x3f\x54\x3c\xf6\xd6\xce\xf1\x93\xa6\xf3\x45\x1e\x6f\x11\x3f\x7d\xf2\xb8\xce\xa3\x72\x8a\x80\xa5\xef\x2f\x2c\xfb\xd5\xc7\x96\x82\xb7\x1e\x2a\xab\x3d\xda\x99\x98\x3e\x8d\xcf\x0f\xf6\x80\xe1\x48\xdb\x91\xf7\xb6\x6e\x79\xef\x48\xdb\x11\x30\x60\x67\x1a\x4b\x97\xc0\x0e\x2c\xc1\x8e\x1f\x7f\x03\xb7\x50\x71\xb8\x59\x5a\x3e\xf0\x12\xd5\x3a\x90\x92\x92\xd0\x4b\xa5\xa0\x77\x18\x67\x49\x6c\x89\x0a\x51\x0c\x21\x70\x73\x19\x3c\x8c\x60\x0f\x0f\x91\x29\xfb\xc3\xc0\xb3\x5c\x34\x46\x16\x22\x21\x6c\x01\x93\x3b\x16\x77\x9b\x22\x62\x20\xee\x04\x98\x85\xff\xcb\x91\x5e\xb1\xf6\xc8\x05\x6d\x42\x63\xe9\xde\x17\x5e\xa0\x3e\xfa\xa7\xe4\x14\xbc\xf1\x68\xd3\xac\xd5\x89\x63\x55\x56\xab\xf4\xe9\x67\x4f\x50\x73\x07\x3e\xf7\xab\xf0\x4f\x97\x36\x67\x2f\xbf\x88\x11\x27\xdd\xba\x76\x20\xbd\xe8\x90\x85\x99\xf4\xe2\x5e\x8a\xda\xfb\xe2\x7b\xa7\xbe\xad\x9d\xb3\xae\x69\x46\x85\x1b\xff\xd2\x71\x4b\x24\x1a\x8b\xe0\x0f\xd2\x8f\xc0\xb7\xfd\x77\xc7\xcd\x34\x3f\x67\x6f\xde\x38\xcf\x7f\xa1\x21\xae\xf7\x0c\x96\xcf\x8a\xdc\xa8\x14\x55\xa1\x56\xb4\x16\x6d\x45\xfb\xd1\x1f\x4f\x5b\x1b\x50\xd1\x88\x98\x61\x1f\x0c\xc5\xe2\xe7\x0e\x9c\xe9\x07\x36\x43\x93\x1d\x67\x6d\x56\xb3\x30\xcc\x2c\x37\x44\x35\x6a\x0e\xc8\x13\x32\x56\x9e\x84\xc5\x15\x46\xb5\x78\x4c\xe1\xa7\x23\x67\x67\x40\x7c\x43\x47\x48\x8b\xcc\x25\x80\xb1\x62\x8e\xa5\x0d\x43\xaa\x57\xc4\x8e\x3d\x40\x66\x24\xa4\xc5\x8a\x8b\x01\xd2\xfa\x92\x96\x8c\x22\x9d\xb8\x3c\xa3\xc3\xca\x68\x9d\x4c\xea\xe4\x86\x9d\x50\x52\x72\x76\x25\x82\x9a\xed\xa9\xf4\x78\x2a\x77\x16\xd6\x14\x14\xe6\x39\x0b\xef\x2b\xa8\x29\x2c\x74\xe6\x15\x3e\x50\x58\x53\x58\x58\x33\xe4\x80\x6e\xb6\xf4\xce\x83\x17\xbe\xb9\x7f\xa6\xad\x73\xe7\x56\x67\x6d\xa5\xd3\x15\xaf\x74\xba\xd6\xba\x9c\x95\xb9\x15\xfa\xee\x9d\x57\x4f\x32\x39\x17\xc5\x3e\x71\xce\x7a\xe8\xc0\xba\xa5\x7a\x69\x42\x72\x49\xb2\x6e\x59\x1d\xde\xdc\x78\xfd\x92\xa9\xfb\xe3\xe5\xad\xe7\x45\xe7\xfb\x4c\xe1\x28\xdd\x38\x07\x84\x71\x35\x63\xa4\xaf\x5b\xe9\xea\xe2\xcc\x05\xe2\x2e\x67\x65\x59\xe5\x82\xd5\xe7\xb7\xc5\x22\xeb\xc7\xbb\x02\xf3\x1b\x7b\xcb\xb3\xcc\xa5\x63\x57\xd7\x57\xdb\x2d\x02\xb6\x52\x1a\x47\x96\x71\xde\x8f\x57\x78\x73\xaa\xe7\xcd\xaa\x62\x74\x7a\x0b\x98\x44\xe3\x91\x82\x6c\x6f\x69\x7c\x01\xfd\xe5\x98\xb2\xb2\x31\x65\xa7\x66\x6f\x70\x16\x17\x3b\x37\x38\x4b\x4a\x9c\xff\xad\x0f\xbf\xdc\xf3\xc2\x8a\x7b\xfb\xb6\xb6\xcc\x7d\xf0\xed\xdb\xa4\x37\x96\x57\x85\xc8\x5f\x7e\x76\x3b\x58\xfe\xab\x91\xb5\xfc\x7d\xee\xf9\x3b\x0e\x1e\xfe\x60\x42\x39\x7e\x28\x34\x7d\x7a\x28\x3c\x7d\xba\xd4\xd7\xf1\xd3\xd5\x13\xaa\x8f\xae\xe9\xec\xb2\xb0\x95\x11\x87\xb5\xe1\x97\x1b\xd6\x49\x7f\xae\x4f\x1e\x71\xc0\x86\xe2\xa4\x72\xfe\xb8\xf2\x86\x66\xb0\xe4\x77\x70\xc1\xde\x0d\x95\x9d\x55\x57\xde\x72\xf1\xec\x48\x5e\x36\x65\x65\x0d\x41\xd1\xba\x6e\x37\x9d\xac\x62\x38\xc6\x64\xb0\x00\x9b\xa5\x63\x2d\x57\x7d\xe3\xac\x68\x1e\x39\x87\xcf\x46\x7e\x82\x12\x88\x04\xdc\xb6\xf0\x30\x80\x56\xc8\x8c\xc0\xc2\xa1\x98\x3f\x1c\xf5\x46\xbd\x36\xaf\x2d\x6c\x0b\x9f\xb1\xe7\x76\x88\x95\x0e\xbf\xab\xbb\xa8\x79\xe9\xde\xbd\x4b\xdb\x6a\x3a\x57\x1f\xea\xe9\xeb\xeb\xb9\xe3\x37\x30\x7f\xcd\x9a\xb5\x6b\xd7\xae\x05\xf3\xa8\x21\x04\xde\xe2\xce\xdf\xdd\x34\xff\x9a\xe7\xaf\xa9\x5e\xbe\xec\x63\xe9\xb9\x8f\x7f\xb7\x65\x2d\x49\x78\xfe\xe8\xd1\x81\xdc\x37\xf8\x33\xed\x65\x80\xa8\xd4\xc9\xb5\xd5\xe7\xf5\x70\x26\xaf\x29\x98\x21\x09\xb4\xb2\x04\xfd\x4c\x16\xde\x14\x16\x4b\x16\x55\x3c\x70\xfb\x64\xe9\xd3\x39\xb7\x9f\xe8\xa9\x6b\x4a\x3d\x9c\x6a\xaa\x7b\xfa\xc6\xa5\x4b\xf9\x5f\x46\xa6\xb6\x68\xaf\xb2\x3a\x44\x1a\x0d\x3c\x56\xce\x47\xaa\xcb\xa5\x07\x98\x96\xec\xee\x86\xd6\x54\xaa\xb5\xa1\x3b\xbb\xa1\xc4\x80\x0b\xcd\x58\x14\x95\xf1\xe9\x0c\xa2\xd3\xc1\xa0\x2a\x34\x17\x2d\x44\x07\x11\x32\x87\x62\xa2\x87\x65\x82\x4c\x40\x11\x89\xab\x83\x20\x66\xbd\x1e\x03\x78\x4d\xa1\x98\x93\x12\xc8\xe6\xb7\x3d\x16\xb7\xc7\x13\x10\x20\x5d\xb1\x28\x84\x4d\xde\x80\x58\x0c\x1e\x03\xb0\xf2\x50\xa6\x0e\x62\x4e\xe0\x9c\x8a\x7a\x19\x4d\xae\xa7\x74\xd6\xca\xc2\x09\x0f\x01\x1e\x82\x10\x80\xe1\xce\x3b\xc1\x56\x43\x48\x88\x55\x43\xc8\xc9\x0a\xee\x90\xfd\x86\x66\x97\xab\xd9\xc5\xaa\x35\x55\x8e\x90\x37\x68\xbf\x68\x56\x7f\x73\x15\x8c\x39\x6e\x1f\xe3\x6f\xd2\x2e\xac\xbf\xf5\x66\xc6\xa5\xcb\xe1\x6d\x2a\x28\xdc\xd8\x3d\xad\xac\x6a\x9d\x69\x4a\xd4\xea\xc2\x1a\x77\x71\x43\x3e\xb7\xbb\xa3\xed\x48\xfd\x8a\x3b\xe7\x57\xbd\x9e\x9b\x53\x7c\x59\xc9\xb3\xd9\x55\x7e\x8d\xb1\xd9\x9a\xb7\x4a\x1b\x01\x44\x2e\x0b\x2a\xd1\x21\x4d\xcb\x59\x3b\xc1\xbd\x28\x5e\x74\x51\x7d\xcd\xee\x0b\xd7\x95\x4b\x1f\x4b\x37\x11\x60\xd6\x1d\x7c\x7d\x5e\x75\x51\x4d\xd2\xb7\x79\xe9\xcc\x99\x4b\xef\xf4\x26\x2b\x62\xde\x70\x4e\x9c\x87\xa5\x0e\x11\x52\xc9\x64\x92\xd5\x4f\xf1\x24\x8b\x22\xc2\xde\x76\xba\x63\xfc\x43\x0d\x27\xb4\x5a\xc0\xf5\xb7\xa6\xfb\x00\x28\x56\xab\x92\xde\x5f\x57\x66\xad\xac\x62\x43\xe6\xb8\xa0\x29\x4a\x4e\xcf\xc2\xe8\xe7\x4d\xe3\xfe\xee\x9e\xed\x0e\xe3\xd0\x7b\x02\x15\xce\xb7\xb4\x64\xf9\xf6\x18\xea\xa7\x24\x93\x49\x8c\xd2\x29\x87\x38\x76\x96\xa6\x7c\x9c\x2e\x5a\x45\x7b\xb4\x81\x86\x32\x70\x88\x0e\xdc\xe3\x10\xf9\x86\xdc\x88\x90\xab\xad\xac\xd4\x99\x7c\x8e\x68\xfe\x58\xe3\xff\x47\xdd\x9b\x80\xc7\x51\x1c\x8b\xe3\x5d\xdd\x73\xec\x7d\x1f\x3a\x57\xf7\xae\x25\x4b\x2b\x69\x4f\xc9\x58\x92\x75\x1a\x7c\xca\x27\x60\xb0\xe5\xd5\xee\xac\xb4\xd6\x6a\x77\xbd\x87\x65\x39\x1c\x02\xc7\x98\x23\x98\x9b\x70\x63\xc2\xe9\x10\x5e\x42\x20\x10\x6e\x43\x12\x20\x24\x24\x0e\xf7\x83\x84\x00\x21\xc9\xcb\x05\x4e\x42\xf2\x02\x58\xe3\xff\xd7\x33\x23\x59\xb2\x4d\x92\xf7\x7e\xdf\xef\xfb\xfe\x3f\x83\xba\xab\x7b\xa6\xba\xba\xab\x6a\xab\x7b\x66\xaa\xbb\xdc\xf3\x7c\x2e\xea\xa4\x55\xc4\xb1\x05\x50\xb8\x93\x0b\x77\x12\x9f\x0b\x3b\x5d\x9c\xd3\x01\xb5\xb2\x77\x02\xf0\x1c\x6f\x20\xd5\x5e\x2c\x79\x66\xc8\x4e\x0c\xac\x8b\xf1\x75\x12\x1e\x6d\xe9\xf9\x6c\x49\xcf\x16\xad\xaa\xd3\x3e\x30\xb0\xeb\xee\x14\x3b\xd4\x32\xb8\x68\xd0\x77\x36\x97\xba\x7b\xd7\xc0\x80\xbd\x53\xa5\x9d\xfe\x31\xf0\x6b\xb5\x44\xe5\x56\x95\x68\x7f\x9b\x61\xb7\xb4\x0e\x2e\x1a\x6c\xdd\xc2\x3e\x7e\xab\xb6\x44\xe5\x56\x11\xed\x5a\xe0\x35\x83\xbe\x55\x2b\x97\xad\x5c\xd3\xb2\x96\x64\x8f\x78\xa5\x90\x2c\xaf\x18\xd5\x7c\xd8\xbc\x28\xb8\x79\x72\x90\x39\xb5\xaa\xae\xae\x7a\x80\x1d\x9c\xdc\x1c\x5c\x64\x0e\xf3\xea\xe9\xfb\x9e\xe9\x50\x15\x6b\x03\x5a\xa2\x3a\xb0\x86\xd0\xab\x55\xa7\x92\x8b\xf2\x2a\xa2\x0d\x68\x8b\x55\x1d\xcf\xa8\x16\x57\x37\x39\x1c\xcd\x95\x5d\xf3\xfd\x1e\x5b\xd1\x20\x7d\x02\x07\xe5\x0c\x18\x03\x59\x88\xe9\x90\xa4\x93\x2c\x94\x88\x80\x2e\x72\x0a\xf6\x75\xe2\x70\x6d\x38\xe4\xb0\x9a\xdd\x1e\x77\x9d\x97\xde\x25\x7d\x6a\xe7\x39\xfe\xc4\x08\x04\xe1\x10\x0a\x77\x52\x24\xca\x31\xec\x74\xb0\xcf\x79\x54\x44\xb3\xf0\xde\xf3\x18\x4f\xc3\xea\x65\x75\x00\x75\xcb\x56\x35\xba\xd9\x9d\xf7\x7a\xb4\x44\x55\xa7\x2a\xd5\x6e\x79\x8d\x5d\xd9\xd8\x5f\x04\x50\xd4\xdf\xb8\x92\x05\x1c\xd6\x96\x3c\xbf\xa9\xff\x2c\xf1\x0d\x32\xd8\x30\x40\xab\x07\x1a\x06\xc9\x9b\x3f\x5c\x14\x34\xf0\x56\x3d\x2b\x47\x1b\xa0\x0c\xae\xff\x12\x3c\xcf\xd5\x7a\x57\x2e\xa7\x6d\x2e\x5f\xe9\xad\x5d\xf8\xc1\x07\x67\xd4\xe3\xb4\x5f\x5b\xac\xaa\xbe\x20\x42\x2a\x2b\x7d\x4e\xa7\xaf\xaa\x82\xd9\x7c\x81\x4b\xe2\x0d\xa3\x3e\xed\x4e\xa6\xb3\xa2\xba\xba\xa2\x93\x79\xbe\x51\x45\xa6\xdd\x64\xff\xba\xb6\x65\xbf\xc1\x3d\xae\x9a\x1a\x57\x0f\xbe\xe7\xf6\x56\x9f\x8e\x3f\xb2\x55\x6f\xb5\x92\x07\x8e\x48\xbb\x69\xc9\xfe\x36\x77\x16\x22\xac\xab\xa6\xb5\xa8\xa8\xb5\xc6\x55\xfb\x8d\x47\xd6\x52\x75\x41\x5a\x64\x3f\x8a\xd8\x3f\xcc\xd9\xdf\x51\x82\x5c\xa8\x1a\xb9\x91\x17\xf9\xd0\x0e\x84\xea\x9c\xcd\x00\x75\x1e\x16\x9c\xc4\x03\x75\x84\x05\x67\x33\xd8\x1c\x9c\x11\x9c\x0e\x60\x49\x1d\x84\x79\xa7\x54\x1d\xf6\xf0\x92\x1f\x46\xd8\x88\x3d\xbc\xcd\x08\x5c\x33\x38\xa5\x9d\x0a\xee\xa0\xc7\x4d\xdc\x5d\xe0\xf6\xcc\xa4\xe1\x3a\x9f\x93\x75\xd8\xad\xd2\x46\x6f\xbb\x33\x1c\xaa\x80\x70\xa0\x0b\xa4\xa3\x36\xe8\x83\xac\x11\x38\x58\xf6\x52\xf5\x5b\x60\x01\x8b\x56\x7c\x4d\xfc\xe8\x57\x2d\x7f\x83\xc5\xd0\x61\x10\xf7\xc3\xe5\x43\x78\x04\x63\x66\xd5\x06\x7e\xba\x0b\x50\x9f\xf8\x3b\x26\x6e\xfc\x0d\x9e\x7e\x1f\x0a\x56\xf1\x4c\x72\x93\xed\x03\x7c\x25\x87\x79\xc0\xae\x87\x6c\xd6\xa5\x2a\xe6\xf7\x3c\x3f\xcc\x33\xe2\x3b\x0c\x56\x7d\xc8\x84\x31\xdf\xb1\x05\x4e\xc5\xaa\x2d\x7b\xf0\x56\xac\x86\x07\x59\x02\x1d\x9c\x8d\xdb\x71\x1e\xcb\x4e\xb2\xdc\x7a\xc2\xfe\x84\x63\xff\xc6\x60\xa3\x8d\x79\x86\x83\x37\xfe\xf8\xba\xe8\x7f\xfb\x6f\x6f\xc2\x45\xaf\xc3\xd2\x1f\x4f\x7f\xf0\x06\xf4\xbd\x28\xde\x39\xf8\xf1\x6a\x30\xaa\x49\x60\x80\xc3\xb7\xbd\x08\x3f\x7b\xe0\xf3\x87\x7e\x7f\xd7\x61\xbc\xfd\x39\x78\xec\xce\x23\x4f\xfc\x6e\x5f\x62\x88\x61\x27\xce\x7e\x77\xea\xc3\xaa\xd6\x02\x4b\x9e\x60\xd9\x75\x77\xb0\xe4\xf7\x18\xc3\x5f\x18\x30\xf3\x4c\xdd\x46\x0e\x86\x78\xb6\x29\xa6\x82\x57\x34\x64\x2f\xdc\xc8\xb0\x62\x2b\x4f\x3a\x36\x60\xee\x4b\xcb\x18\xa6\x2d\xc5\x91\xf3\x08\xd9\xcb\x70\xd9\xbd\x84\xc5\x37\xb2\x73\xd7\x70\xe5\xc8\x83\x36\x48\x6f\x4d\x49\x8d\x81\xa1\x0f\x7e\xd5\xf2\xdb\xd0\x2a\x5f\x88\x1c\x5b\xac\xd8\x95\x23\x12\xe6\xc7\xdc\x3a\x76\x78\xc2\x3c\x88\x79\x50\x5b\xd1\x32\xe8\xe7\xc2\x2e\x7f\xb3\xb7\xd9\xef\x0a\x73\xfe\xc1\x96\x0a\xed\xfa\x0e\xbc\xa4\x63\xfd\x03\x37\xbe\x71\xe3\x8d\x6f\xdc\x88\xcf\xb1\x18\xb6\x6e\xe9\xf9\x7c\x89\x14\x31\xe3\x60\xcf\x16\x39\x2e\xd8\x6c\x0a\x0d\xed\x31\x61\x69\x13\x53\x65\x2a\xd2\x68\x8a\x4c\x55\x4c\xd3\x52\x21\xd6\x7e\x5a\x24\x82\x6f\x4e\xde\x70\x43\x72\xec\x86\x1b\xc4\xd5\x07\x0d\x96\xf7\x28\x3a\x2b\x85\xdd\x78\x4f\xf2\xf4\x9e\x52\x52\xe5\x7b\x82\x34\x46\x35\x5a\x88\xce\x44\x09\x69\xff\x9c\xe2\x05\x42\x7c\x2e\x66\x66\x38\x81\x4e\x72\x0a\xb8\x58\x5f\x27\x73\x92\xb1\xcc\x1e\x0e\x71\xc2\xc8\xed\x27\xc4\x68\x63\xe4\xa1\xb5\x78\x4f\x6b\xae\x34\xf1\xab\x7b\xa6\x0f\xf6\xac\x56\x97\x35\xad\x09\xb2\xbc\xcf\xde\x54\x5e\xef\xae\x2f\x6f\xb2\xfb\xf0\x43\x56\xfd\x56\x29\x80\xb2\x92\xce\xe3\x82\xde\x7a\x14\x59\xf5\x9f\x4b\x51\x45\x98\x83\x7a\x2b\x39\x67\xec\x86\x1b\xc6\x92\x37\xdc\x20\x7e\xb7\xba\xe3\xb4\x33\x57\xd4\xf7\x8e\x8c\xf4\xb6\x9c\xb5\x6d\x65\x80\xa9\xd0\x3a\xd5\x6a\xb5\xda\xa9\xad\x00\x46\x6f\x9d\x92\x22\x33\xcb\xe9\x5c\xae\xd0\xc6\x58\xe9\x68\x9f\xcf\x68\xa3\x4a\x9c\x1c\x95\xbc\x26\xa9\x42\xad\xa8\x1b\xad\x41\x05\x84\x50\xc0\x8b\x67\x35\x00\x4b\x23\xc2\x33\xc1\xb2\x95\x70\x29\x33\xe7\x71\x9b\xff\x45\x59\x9e\x1e\x82\xf2\xa1\x01\xd2\x56\xb7\x19\x68\xce\x9b\x23\x64\xa9\x1f\x6c\xe7\x5a\x4a\x1b\x1b\x1a\x1a\x1a\x4b\x5b\xb8\xf6\xc1\x7a\xcb\xb2\x10\x46\xa1\x75\x7b\x9e\xdc\xb3\xe7\x49\xa6\x7a\xae\x2b\xbd\xdd\x38\xfd\xa2\xd1\x6e\x37\xe2\x36\xa3\x7d\x9e\x8b\x3d\xda\xd2\x23\xee\x9f\x7b\x00\x87\x28\x85\x66\xe1\x0e\xf6\x6c\x81\x0d\x53\x63\xd1\x76\xa6\xcc\x68\x53\xab\x6d\xc6\x32\xa6\x3d\x3a\x36\xb5\x01\x77\xd1\xc6\xf7\x88\xbf\x99\x3d\x80\x02\x2c\x6d\xb4\x65\x9a\x80\xf6\x58\xed\x2a\x2a\x93\xb9\x3a\x29\xcb\x67\x8b\x1c\x1b\xf0\x44\xfe\xed\x91\x9e\x24\xa8\x92\x04\x3a\xb1\x5f\x9a\xea\xc2\x3e\x17\xe0\x99\xef\xc9\xc7\x9d\xc7\x11\xfc\x17\x65\xeb\x3c\xdd\x3a\xc9\x11\x0b\x27\x89\x6b\xc3\xa0\x65\x21\x11\x85\x96\x9d\xc8\xd8\xcb\xfe\x07\x2c\x9d\xb2\xea\x3f\x5d\x22\xc7\xfa\x9e\x7b\x3e\x03\x6c\x95\x66\x96\x4f\x97\xcc\xb2\xf7\xf5\xa9\x0d\x27\x70\x18\x9e\x90\xd8\x3b\xbd\x75\x96\x91\x1f\xcd\x72\xf7\x6f\xb3\x75\x47\x7c\x8c\xa4\x90\x54\xcb\xe7\xb2\xd8\xca\xbc\x7c\xec\x97\xb0\x05\x1d\x17\xdb\xc7\x89\x16\x20\x54\x27\x1d\x42\x5a\x2d\x07\xc9\x95\xd6\xc8\xf2\xa1\x92\xc8\x34\x73\x32\xe3\x8c\x8b\xe3\x5f\x1d\xbb\x27\x7a\x1f\xfb\xc9\x63\xbd\x13\xbb\x1d\xdb\x60\x19\x9c\x07\xcb\x2e\x51\xbc\x8d\xf1\xfb\xfb\x3e\x16\x1f\x7e\xf4\x91\x79\x0e\x83\x3f\xb8\xf9\x65\xd3\xb2\x75\xeb\x96\x99\x5e\xbe\xf9\xfa\x6f\x7e\x13\x7f\x5b\x8e\x06\xfe\x3e\x84\xc4\x6b\xc5\xef\xfc\xf9\x38\xc7\xc2\x63\xfd\x32\xa1\x5a\xd4\x28\xed\xd5\x70\x58\xec\xb6\x63\x6e\x96\x10\x0a\x06\x94\xc3\x03\xed\x36\xa7\xc5\xef\xa8\x0c\xfb\xdc\x4a\x67\xf1\x4b\x72\x4b\x97\x1f\x16\x1f\x16\xaf\x16\x1f\xfe\x78\xdf\xbe\xc3\xcc\xf8\x75\xc7\xdc\x1a\xaf\xeb\x39\xbc\x1b\x92\xbb\x0f\x1f\x50\x3a\xcc\xa1\x7d\x87\xc5\x87\x1f\xf9\x8e\xf8\xf0\xe1\x2b\xf6\xfd\x19\x96\x4b\xe8\x9f\x2f\x7d\xf9\xb3\x5b\x64\x5f\x4b\xf1\xc3\x5b\x3e\x7b\x19\x96\x4e\x4d\xdd\xa1\xf4\x7a\x7e\x3c\x96\x0a\x79\xb7\x0d\xcc\x33\x79\xe1\x19\x07\x06\xbb\x0d\x49\xbd\x0a\x99\xac\x3e\xda\x69\x0f\x57\xe9\xe1\xa4\xaf\x88\xcc\x83\xcd\x1b\x36\xf7\x34\xbe\x78\xf9\x91\xaf\x5f\xfe\x62\x63\xcf\xe6\x0d\xcd\xab\xd7\x5c\xfa\xd4\xa1\xa7\x2e\x5d\x23\xde\xae\xf8\x62\x2f\x3c\xe3\xdc\x5b\xaf\xb9\x4a\xbc\xf0\xaa\x6b\x6e\x3d\xf7\x0c\x7c\xd8\xd0\x32\xbc\xe7\xd5\xdd\x37\xbd\xf3\xce\x4d\xbb\x5f\xdd\x33\xdc\x62\x38\xf7\x9a\xd1\xa7\x2e\x5d\xb3\xe6\xd2\xa7\x46\xaf\xc1\x56\x65\x30\x9f\xbd\x7f\x45\xfc\x63\xb0\xf1\xe7\x9f\xcf\x8b\x7f\xfc\x38\x7e\xc5\xec\x79\xd3\xac\x7c\xde\x42\x31\xaa\x41\x1d\xf3\x7e\x4d\x0e\xdf\xbc\x9f\x92\xb9\xea\xa4\x81\x9d\x66\xa3\x69\xce\xfb\x29\xac\x69\x1b\x7c\x6b\xb0\x6d\x4d\xfd\xc5\x7b\x9f\xde\xbb\xf7\x69\xb8\xe3\x08\xb2\xea\x89\xbc\x4a\x3a\x22\xe9\x1a\x55\xf3\x83\x54\xbf\x7b\xb6\xc0\xc6\xa9\x8d\x1b\xa7\x92\xb1\xf6\xe5\xcb\xdb\x63\xf0\x98\xa4\xca\x9f\xef\x67\xb7\x7e\xb6\x5f\x6f\xb5\xb2\x2f\x7f\xb6\x64\xc6\xac\x2a\x16\x01\x21\xd5\xac\x2d\xb0\xa2\x52\xb4\x10\x9d\x82\x96\xa3\xb3\x90\x40\xed\xa9\xf4\x1d\x92\xab\xf6\xc8\x9f\xab\x69\x77\xbf\xc8\x9c\x1e\x5f\xae\x9b\xb5\x97\xf2\x88\x4e\x30\xaf\xb3\x51\xe3\xab\x8e\xff\x76\x3b\x65\xac\xee\x6b\x5e\xf2\xdd\x25\xcd\x7d\xd5\xc6\xae\x46\xf8\x7a\x63\xd7\x94\xe4\x0a\xc3\x64\x2c\x86\x69\x39\xd0\xe5\x41\x83\x45\x9c\x9a\xd9\x1c\x09\xd2\xa1\x2b\xca\x16\x29\x79\xcb\xd4\xec\x5d\x9f\x4e\xf1\xc8\x62\xf8\x74\x89\xc1\xc2\xcf\xff\xe1\xf7\x85\x36\x9f\xee\x5b\xb2\xc4\x77\xfa\xe6\x50\x78\xe5\x4a\xb8\x53\xf2\xb5\x11\xdf\x3b\x66\x3b\x67\xcf\x73\x99\x93\xcc\xa9\x84\x94\xc4\xbf\xb9\x3f\xf5\x7f\xc6\xc7\x59\x95\x55\x14\x01\x7f\x91\x4d\xad\x3b\xae\xcc\x1e\xe7\x01\x7b\xa2\x8d\x3d\xb9\x22\x51\x3e\x76\x35\x8a\x1b\x1b\xbb\xe6\x70\xf3\x7f\xcf\xc7\xa9\x4f\x91\x55\xcf\x1d\x3c\xde\x7c\xf6\x85\x57\xae\x0c\xcf\x72\x12\xde\x90\xb8\x38\x7d\xec\x60\xa4\xbf\x9c\x84\x89\xc7\xea\x8e\x7c\x9b\xd9\xfa\x39\x55\xcb\xf9\x26\x13\x4b\x67\x94\x7d\xc0\x21\x54\x22\x45\x67\x34\xe1\x9a\x6a\x6c\x36\x59\xfc\xbe\xb0\x97\x91\x9c\x9c\xa5\x37\x53\xe0\x77\x18\x48\x0d\x7d\x96\xe1\xe4\xd3\x6c\x03\x96\x50\xad\xbc\x25\x12\xf3\x92\x87\x0d\xf3\xdb\x57\xde\x7f\xf7\xd0\xa1\x77\x97\xb5\x3b\xaa\x43\xc1\xd3\xea\xbd\x55\xad\x89\xfb\xbf\x7c\x6f\x6f\x2f\x5c\x54\x20\x9a\x85\xa7\x5d\x7e\xf6\xd2\x89\xb3\x7b\xaa\x22\xc9\xeb\xc5\x5f\xfd\x62\xef\xde\x77\xa1\xfc\xba\xc9\x3f\xbc\x70\xe3\xc6\x3b\x2e\x6d\xde\xbc\xa8\xa3\x07\xff\x09\x3a\xa1\x5d\x7c\x5e\xfc\x9e\xf8\x7d\xf1\x87\xe6\x85\x8b\x07\x16\x96\x9b\x22\x67\x25\x85\xeb\xc4\x3d\xa5\x83\xa9\xb3\xba\xdd\xcb\xd6\x86\x4b\xf3\x3f\x84\xfa\x03\x5f\x87\x85\x2f\xe5\x4f\xfd\xca\x53\x9f\x5e\xf2\xb4\xf8\x83\xb1\x81\xd3\x96\xcf\xd8\x03\x41\x8d\xd8\x9b\x51\x25\xf2\xa2\x1b\xd1\x33\xd2\x1e\x4f\xc9\x6d\x0a\x9b\x4d\x56\xe9\x35\x84\xf2\x92\xde\x24\xf9\xfc\xd7\xcd\xee\x7c\x95\xe4\x67\x3b\xe6\x26\x31\x73\xaa\x9e\xdd\x26\x9f\xbe\x17\x0c\x84\xe6\x3a\x44\xd8\xa5\x8f\xff\xb2\xf7\xa4\xdd\x26\x39\xfd\x28\x3e\x13\xd2\x2b\x36\xbf\xcf\xe9\x62\x9c\x36\x17\x2b\x79\x96\xb8\xa5\x32\xb0\xa6\x63\xfe\x03\xe1\x90\x59\x8a\x2f\xe4\x65\xe5\x6f\x6a\x0e\x8b\xd3\x01\x3f\xa8\xb4\x83\xae\x2b\xfa\xfe\xeb\x9e\x8c\xdb\x5a\xd9\x35\xdc\x3a\xf1\x25\xdf\x46\x5c\x6c\xb0\xa9\xd9\xae\x9a\xf2\xcf\x5f\x28\x71\xd7\x94\x33\xed\x25\xee\x37\x7b\x8b\xcf\xf4\x98\xb4\xbc\xc9\xed\x75\xd7\x94\x9b\x89\x71\xa1\xb3\x87\x68\xf4\x8b\x1c\x2c\x43\x2a\xdd\xa1\xa0\xbb\xa1\xdc\x67\x02\xb0\x70\xa5\x13\x37\xb4\x2e\x1d\x68\x2d\x2e\x2f\xb5\xd6\xfb\x16\xd7\x2f\xf6\x94\x99\x54\x1c\x51\x69\x74\x66\x8d\xb3\x6c\x81\xa6\xb4\xe7\xd4\x0e\xfc\xea\xa5\xd6\x45\xab\xd6\x57\x9a\x5c\x8b\x56\xab\x1f\xad\x0f\x2c\x4a\x60\x87\xd6\xaa\x55\x55\x5a\x07\xce\x1b\xde\xaa\xc3\x82\xbd\x8a\x18\xcf\x85\x32\xb8\x18\x36\x80\xd9\x9f\x28\xb5\x96\x76\xc5\xd7\xbe\xf0\x99\xf8\xdb\x57\x36\x9c\x41\x4a\x4c\xc5\x8e\x73\xca\x3d\xee\x92\x72\x8f\x1b\x9f\x76\x51\xd4\xbd\xc6\xa6\xd1\x71\xea\x06\xdf\x06\xef\x8a\x50\x03\xab\x6b\xd6\x3b\x4a\x56\x18\x17\x19\x8b\xed\xc5\xed\xc0\x30\xb8\xc5\x55\xd7\xe9\xf5\x76\xd6\x0d\x77\x2e\xb4\xb1\x2c\x26\x26\xed\xc2\x67\x77\x85\x27\xc7\x93\x13\x81\x60\x7d\x8b\x49\xad\xb3\x95\x5b\xfd\xfe\x65\x4b\x5a\xa0\xca\x5c\x65\x77\x68\xcb\x9c\xc5\xeb\x6d\x03\x2b\xf6\xef\x15\x3f\xfa\x75\xe5\xe0\xe6\x8e\x0a\x93\x71\xe9\x3a\xed\x6f\xa0\x69\xf7\xa1\xb1\x89\x71\x62\xd7\x39\xcd\x36\xb5\xb5\xea\xc0\x6e\xf1\xc3\x6f\x34\xcc\x7d\xdf\x50\x24\xcd\xfa\xd6\x90\x9b\x07\x03\x38\x2a\x00\x42\x4e\x07\x0f\xed\xc0\xfb\xba\xc0\xe9\x38\x61\x13\xf6\xdd\xd7\xa8\x3d\x95\x47\xf6\x97\xdb\x4d\x45\xbf\xc0\x60\xd7\xf2\x5a\x31\x62\x72\x3a\x92\xef\x2d\xc1\xc9\x93\xec\x47\xf8\x35\xfe\x4e\xa3\x5b\x27\x3e\xa4\x2d\x2b\xe6\xfb\xa1\xd7\xa0\x62\x35\xe2\x25\x1f\x3a\x46\xef\xae\xc5\x37\x9f\x6c\x43\x01\x37\x7b\xb6\x93\x5e\xfa\x92\xec\x97\xe2\xa0\x22\xc5\xf7\x2f\x14\x36\xfb\xcd\x2e\x70\x06\xdc\x1e\x65\xe3\xa0\xa4\x62\x95\xa1\xb0\x4d\x3a\x27\x3c\x2c\x6d\x84\xb4\x9b\x1d\x56\x65\xe7\x0d\xfd\xc3\xd4\xb2\x0c\x2c\x9a\x5a\x34\x30\xd5\xb7\x38\xb3\x3f\xb3\xb8\xef\x09\xd0\x3c\x31\x25\x3b\xf9\x4d\x49\xf0\xd4\x41\xe9\xdf\x60\x26\x33\xb8\x38\x66\x27\x97\x1d\x29\xd8\x63\x8b\x57\x5e\xd4\x44\x10\xad\x9a\x46\x4d\x17\xad\xdc\xf3\xc4\x13\x7b\x1e\x13\x3f\x05\xfe\xb1\x47\x76\xe3\x17\x68\x69\xba\x7d\x37\x5c\x2a\x6f\xae\x91\x36\xd8\xfc\xff\xa2\xef\xf8\xb2\xe9\xff\x67\xfb\x0e\x97\x89\xff\x57\xfa\x1e\xf4\xdb\xff\xaf\xf7\xfd\xb2\xcb\xfe\x37\x3d\x9f\xdb\x77\xb5\x34\x2f\xcb\xbd\x9f\xed\xbb\xcf\xf1\xbf\xe8\x77\x66\x7f\xe6\xdf\xe9\xf5\xea\xed\xdb\x57\xff\x8f\x7b\x6c\x9a\x8d\xc1\xe4\x46\x5e\xe9\xb4\xfa\x01\xb4\x0a\x6d\x44\x5b\x50\x1c\xa5\xd0\x0e\x74\x1e\xba\x08\xed\x43\xd7\xa3\xdb\xe4\x13\x2f\x60\xe6\xac\x40\x2f\x84\xe5\xd8\x72\x55\x66\xe5\x20\x95\x90\xc3\x19\x0e\xf9\x9c\x58\x39\x92\x9a\x51\xf6\x01\x85\x66\xca\x33\x79\x40\xae\xa9\x3d\xbe\xfe\xf8\xfb\xbf\x00\x7f\x06\x8f\x3b\x2e\x67\x6f\xd4\x68\xa6\xf7\x69\x4a\x34\x6b\x35\x9a\xc6\x53\xad\x6d\xcb\xe2\xdb\xae\x3f\x8a\xe8\x42\x7a\xdb\xd3\x4b\xb7\xfc\x64\x6d\xa3\xa6\x44\x53\x25\x3b\xea\x6e\x92\x32\xd9\x91\x77\xfa\x1e\xc5\x79\x57\xf6\x08\x46\xf3\x2a\xe7\xde\x28\xbe\x3d\xb7\xa0\xdc\x20\xef\x40\xde\x34\x27\x65\x79\x4d\x09\xed\x87\x66\xad\xa6\x44\xd3\x78\xd6\x7f\x45\x97\x5e\xbf\xed\x73\xc4\x22\xba\xaa\x5f\xbb\xcc\x53\xde\xdd\xa8\xd1\x88\xf7\x4a\x78\x9b\x4e\x48\x03\x52\x13\x53\x5f\x70\xf5\xed\x13\x6a\xdc\x27\xd4\x20\xf3\x9c\xb3\xfa\xea\x50\x93\x14\x31\xb5\x1f\xad\x44\xe7\xa2\x3d\xe8\x72\x74\x1d\xba\x15\xdd\x8d\x1e\x40\xdf\x41\x4f\xa1\x1f\x48\x3b\x9e\x8e\x05\xdb\x97\x36\xaa\xcf\x96\xdc\x1d\x80\x8e\xf3\xf6\x76\x2b\xb9\xe3\xb8\xb2\xfb\x24\xab\xcb\x53\x40\x89\x87\xe7\x90\x5e\x2b\x3a\x78\xe0\x9a\xc1\x3d\x57\x6d\x7c\x0e\xf4\x05\xed\x7c\x51\xfb\xc7\xd7\xcf\x94\xb9\x29\xf9\x70\xc4\xae\xee\x69\xd4\xdd\x65\xd5\x2f\xd1\x5b\xa7\xf0\x12\x4b\x99\xc5\x52\xb6\x56\x4a\xbd\x52\x7a\xf5\x1c\x58\x4e\x99\xb5\xf2\x6a\xdd\x62\xd8\x7a\xfd\xb6\xe4\x0a\xef\x68\xbd\x43\xab\x6d\xd0\x6a\xc5\xe7\xa5\xcc\x51\xab\x2e\xab\xf3\x07\x97\xb3\xef\x19\x2c\x47\xa6\x4e\xc0\x7e\xe5\x9f\xd6\xc8\xd4\xe0\xe0\xc1\x03\x85\xe7\x28\x85\x1d\x0e\x47\xca\xec\x74\x9a\x1f\x2f\x1c\x38\x08\xff\x41\xaf\x59\xbc\x73\x52\xcb\x09\x35\xd3\xb3\x8f\x07\x78\x6a\xdb\xf5\xab\xac\x86\xca\xf9\x9d\xf3\xe6\x7d\x35\xcb\x83\xd3\x53\x16\x38\x78\x02\xee\xda\x7f\x5a\x23\xff\x2f\xad\x19\x81\x3e\xef\xb2\x22\xd2\xa3\x25\xe8\x54\xb4\x5d\xf6\xf1\xe2\xb9\x4a\x79\x29\x57\x09\x36\xc4\x73\xd2\x59\xc9\xf4\x3f\x4b\x30\x80\x6b\x79\x03\x91\x56\x6c\x74\x0d\x09\x4e\x07\xe7\xf1\x02\x0e\x87\x2c\xa1\xda\x70\x88\x71\x58\x66\xb7\x55\xd8\xe4\xb3\xf2\x3c\x6e\x69\xc3\x9c\x57\x76\xc2\x95\xf6\x83\xf1\x06\x90\xfc\xc1\x71\x38\xe4\x02\xf2\x81\xb9\xa2\xc8\x21\x1e\x71\x14\x55\x98\xe1\x20\x76\x89\x9f\xbc\xa5\x32\x00\x4f\x18\x0c\xaa\xdb\x9f\x7d\x44\x7c\xf1\x3b\xe7\x7c\x70\xc7\x10\xc0\xf7\x6f\xe7\x31\x21\xa0\xc2\x60\x54\x5d\xfb\xc1\xa4\x8a\xdf\xf1\x0c\x90\x2b\xee\x82\xe6\x77\x76\x4f\x7f\xb0\xfb\xf1\xdd\xbb\x1f\x87\x3b\xc7\x36\xab\x4c\x98\x73\xf2\x9a\x45\x3d\x85\xe7\xb7\xef\x39\xa8\xd7\xf4\x76\x6b\xf8\x22\x16\x9b\x54\x43\x63\x98\x7c\xf9\xdd\x0b\xaf\xfc\xc7\x55\x70\xc6\xc6\xf4\x9b\xc3\x9b\x36\x0d\xbf\x99\x3a\xfd\x3e\x40\x87\xc5\x73\x36\x12\x9d\xba\xc5\x52\x69\x54\x93\x35\xe0\xfb\xee\xc3\xd0\x74\x9f\x86\x4f\x3e\xf0\xdb\x73\xbf\x2b\xfe\x74\x35\x51\xdb\x8b\xd4\xcd\x3a\xb5\x8e\x59\xf4\x4b\x68\xbd\xf7\x0a\x60\x9f\xdd\xa5\xd6\x6c\x3f\x24\xbe\x53\x47\x69\xee\x3e\x8a\x76\xbd\xbe\x94\x53\x69\x02\x0b\x34\x9a\xd0\xd5\x6b\xd3\x8f\x47\x74\xc6\xef\xef\x39\xfb\xbe\xc5\x1a\x4d\x7d\x40\xad\xe2\x96\xbd\x7d\xee\xee\x0f\x2e\xe1\xf8\x8b\xfe\xac\x9c\x4d\x2e\xef\x2b\xb6\x22\x54\x27\x45\x73\x3f\x2e\xca\x32\x62\xd1\xe7\x88\x53\x3e\xf7\xc8\xcf\xcd\x53\x04\xc1\xd6\xb9\xcf\x2b\x20\xb7\x03\x53\xc8\x88\xd0\xf1\xcf\x6f\xfc\x3c\xdc\xf7\xa4\xd7\x99\xca\x8b\x21\x32\x7b\xbe\x03\x41\x3a\xe4\x46\xa8\x1e\xcc\xf5\xd8\x5c\x65\x96\xdf\xcb\x2a\x51\xb8\x8e\x75\x67\xb6\x4f\x04\x4d\x23\x06\x61\x34\x8d\xb6\xf6\x6c\x21\x68\x4b\xcf\xf4\xfe\x99\x17\x01\x78\xab\x7c\xc8\x39\x46\x04\x1d\x45\x5b\x7a\x30\xa2\xf5\xe2\x6c\xc0\x7f\xd8\x2a\xd3\x3e\x36\xf6\x1a\xe4\x47\xa8\x2e\x1c\x0a\x34\x83\x94\xb8\xab\x8d\xe0\x71\x4b\xdf\x22\x2b\x60\x36\x0a\x8a\xd3\xe1\x3b\x9e\x37\xcc\x57\xaf\xd6\x68\x7e\xf7\x3b\x8d\xe6\x6a\x4d\x09\xcd\x4b\x34\xc7\x95\x71\x6e\xee\xd0\xdf\xfc\xa2\xdb\x94\x32\x63\x9d\xcb\x53\x32\xa7\x7f\xf2\x7b\x9f\x7f\xfb\x5c\xdc\xe3\x7a\xf9\x3b\x4a\xe7\xc0\x01\x99\xce\x81\x03\x32\xdd\x39\xe5\x23\xfa\x13\x45\x0c\x07\x4e\x7e\xef\x6c\x59\x7c\x99\x41\x5b\xe7\x3f\xb3\xce\xd8\x78\x49\x97\xd4\x50\x05\x27\x2c\xeb\xbd\xe0\x9b\xce\x8a\x3f\x61\xb7\x9e\x64\x0d\x0f\x71\x1c\x98\xfe\x31\x1c\x3a\xd9\x7a\x9d\x97\xda\xc6\x92\xef\x87\x15\xd5\x20\x2f\xea\x45\xdf\x47\xaf\x21\x04\x6e\x03\x38\x1d\x9d\xc0\x72\xf2\xd6\x38\x9f\xd3\x61\x73\xce\xb2\x48\x66\x8c\x67\xe6\x9a\xc3\x56\x27\xfd\xcc\xa5\xa8\x3d\xbc\x01\xac\x21\xe9\x13\x20\xdf\x09\x15\x10\xf2\x74\x82\x14\x47\x24\xe4\xf6\xb8\xa9\x39\x70\x81\xd3\x0b\x1e\x77\xd8\xed\xa9\x96\xbc\xab\xe8\xb3\x26\xc7\x87\xc2\x9c\x0b\x9c\xf4\xba\x11\x28\x65\x27\xc7\x73\x36\x47\xb8\x13\xc2\x5e\xcc\x77\x32\x7e\x87\xe4\x27\xe3\x90\xaf\xb3\x0e\xa7\xdb\x63\x60\x1c\x4e\x47\xc8\x22\xf9\x98\x3a\x1d\xe1\x13\x62\x8f\xb0\x5a\xe3\x02\x9d\xd6\x10\x30\x89\x9b\x54\x4e\x5e\xa5\xe2\x9d\x2a\xfe\xb6\x1a\x5d\x8d\xde\xad\xd3\xc9\xd9\x24\xad\xe2\x55\x0e\x13\x5c\x56\x7d\x4d\xc8\xed\x65\x96\xad\x5c\xe2\xc6\x0e\xde\xca\x19\x08\x4b\xf8\xef\x11\x67\x65\x35\xb7\xe0\x8c\x7e\x6b\x83\x4e\x87\x6b\x39\x20\x64\x61\x1b\xa7\xd9\xb6\x7e\x71\xb2\xcc\xc5\xd7\xfa\x2b\x9a\x36\x1a\xca\x16\x9b\xf4\x3e\x8f\xd5\xab\xd7\xeb\x35\x4d\xad\x7a\x8c\x79\xa8\x73\x15\x3b\x6a\x84\xea\xaa\x4d\x8f\x98\x40\x63\x34\xda\x17\x36\xd4\x9f\x6a\xc5\xea\x4a\xb3\xb3\xad\xa8\xc2\xae\x37\xa8\xf8\x05\xdb\x58\x28\xd3\xeb\x19\x97\xa3\xc2\x6a\xc4\xea\x1a\xec\x28\x6e\xb0\x1a\xf4\xd6\xa6\xe7\x1f\xad\xd8\xb8\xa3\xb4\x79\x6c\xb4\xcb\xf3\xf7\x7d\x87\xc5\x87\xc4\x6b\xc5\x87\x24\x89\xad\x84\x24\xac\x3c\xcc\xd4\x9a\xcd\x0b\x2c\x66\xb6\xf6\x35\x95\x4a\xe5\xa0\x43\x72\xac\xad\xd1\xeb\xdd\xfa\x6a\x7d\x8d\x4e\xe7\xd1\xd5\xec\xa0\xf5\x2a\x95\xc9\xb1\x69\xc9\x42\x77\xd9\xca\xe1\x8d\x36\x57\x2d\xb6\x73\x76\x8d\xdd\xe8\xb0\x15\x89\x16\x5b\xb9\xc1\xa6\x59\x1a\x36\xe9\xb5\x00\x4d\x4d\xb6\x7a\x8d\xa6\x68\xad\x6f\xfd\x1e\x0d\xef\x6f\xf5\xc7\x96\x85\x8c\xcc\x92\xb6\x64\xd6\xae\xb5\x16\x95\x00\xf8\xca\xec\x46\x47\x39\x43\xca\x86\x2e\x0b\x1a\x1c\xa6\xf1\x66\x6f\xf5\xa3\x4b\x4d\x5a\x9d\xa5\x78\x91\xc3\x6c\xed\x70\x61\x4e\x0d\xac\x91\xe5\x81\xaf\xaf\x0b\xc6\x5b\x46\xf2\xe5\x0d\x1c\xc7\xfb\xea\xbb\x4e\xe9\xed\x71\x85\x4a\x8a\x5c\x21\x77\x63\xa5\xb6\xf8\xdb\xa0\xde\x1a\x38\xbf\x6d\xf3\x86\x75\x04\xc3\xe4\x49\xf7\xa0\xc3\xec\x7b\xd8\xa5\x08\x81\xd9\x21\xed\x2f\xef\x02\x3f\xb1\xd6\x48\x1e\x89\xca\x4b\xa8\x4e\xa6\x0b\xfc\x1c\xe6\xbd\xe0\xa9\xa9\x62\x83\x54\xee\x56\x8b\xc7\x0b\xcd\x10\x64\xab\x7c\x61\xaa\x18\xf4\xfe\x9a\xaa\x6a\x0e\x73\x23\x0f\xd6\xd5\xf5\x35\x99\xab\x46\x0c\xfc\x48\xb9\x71\x71\xe8\x74\xf1\xbf\x4f\xdf\x04\x42\x4d\x6b\x47\xb3\xaf\xc1\xb2\xf9\x4c\xce\xcf\x5e\xfd\x87\xa6\xc6\xe9\xaf\x88\x17\x9f\xdf\xdb\x0a\x2a\xa2\xc5\xcd\x7d\xe7\xc3\x4e\xfc\xf4\x65\x7f\xe0\x4c\x0c\xbb\xb9\xb2\x62\xe3\xc0\xf4\xcf\xcb\x8c\xec\x69\xd3\xdb\x81\x25\x04\x37\x9d\xba\x4f\x7c\x5a\x7c\xf6\xfc\x3e\x1f\xa8\xa6\x5f\x5b\xb5\x9c\xd1\x16\x7b\x3a\x1b\xde\xaa\x13\xd7\x76\xb0\x1c\xe8\xe2\xc5\xfa\x96\x30\xde\x0d\x57\xff\xb5\xc3\xab\x2f\x8a\xeb\x4a\xfb\xa6\x37\x9f\x7d\xce\x64\xc1\xac\x7c\x0f\x91\x7c\x5c\xcc\xa8\x11\xb5\xa0\x4e\xb4\x4e\x79\x73\x67\xb7\x39\x0c\x4c\x8d\xd9\xe7\x22\x65\xc0\xd2\x02\x96\x1c\xae\x17\x13\xba\xc4\x96\x2a\xfd\xe6\x1a\xf0\x9b\x6b\x78\xb7\xa7\xc6\xec\x37\x5b\xfd\x56\x36\xe0\xf1\xb2\xd5\x35\xd5\x0b\xc1\xec\xf3\x3b\x42\x1e\x37\x1b\x94\xf7\x73\x04\x6b\xcc\xfe\xf0\x49\xf7\xab\xdc\x04\x80\x59\x95\x41\xad\x36\xa8\x58\x0c\x8b\x01\x18\xad\x4a\xcd\x32\x84\xe1\x58\x4e\xc5\x12\xf8\xfc\xdd\x5d\xbb\xe0\xdb\xdb\x6e\x2f\xb3\xe9\x6e\x1b\x6b\x5a\xb1\x10\x0e\xb0\xc4\x64\xa9\xb4\xd7\x9b\xed\x2a\xe6\x2c\x5b\xed\x81\x36\x02\xd0\xc1\x18\xab\xcb\xbd\x15\x85\x14\xef\x6a\xf6\x55\x3e\x3c\xf7\x93\x1c\xfe\xd5\x23\x8c\x43\x65\xe2\x55\x04\x82\x58\x45\x4c\xac\x23\x3a\x09\x4e\x95\x91\x53\x6b\x6e\xc6\x1a\x5e\xcb\xa9\x08\xe1\x38\x2d\x6b\xf8\x08\xde\x12\x17\xc0\x5b\xbf\xb8\xf6\x34\x71\x01\xb4\x89\x2f\x42\x97\xa1\xd7\x69\x2a\x36\xe9\x58\x22\x2e\x00\xff\xcd\x9d\xb7\xef\x29\xaf\xac\x31\x56\xdf\x24\x2e\x70\xd5\x76\x10\xcb\x71\xdf\x3a\x58\xd4\x72\x14\xab\x96\xb3\xff\x40\x3a\x64\x47\x25\x68\x1d\xba\x02\x21\xd6\xed\x91\x4e\x2d\x73\x20\x6a\x56\x9a\x81\xe3\x1d\x56\x6a\x4d\x20\x80\xa5\x93\x1e\x79\x8e\xef\x24\x15\xe0\x22\xbc\xdb\x80\x79\x17\x76\x3a\x3a\x71\x97\x1c\x89\x80\xe7\x58\xce\xe3\x22\x52\x08\x42\x8b\x95\xe3\x39\x2c\x6d\x74\xe7\x6a\x2a\x11\xa9\x76\xd7\x70\x2e\x5c\x01\x0e\xa7\x97\x34\x83\x97\xf3\xb8\xb0\x53\x59\x18\x51\x53\x56\xcb\x38\x1d\x16\x66\x82\x63\xf5\xde\xf3\xc6\x0a\x15\xe6\xdb\x7a\x60\xad\xb8\xf9\xbe\xe2\x4a\xc2\xac\xaf\x63\x77\x2d\xac\x6e\x74\xb1\xfb\xcf\x79\x55\x7c\xf7\xf6\x6b\xc4\x4f\xb6\xb9\x8c\x8b\xef\xf9\xea\xde\xfa\x05\x55\x0b\xd4\x0c\x39\xef\x47\x77\xee\x1a\x60\x8c\x6d\xd5\x5f\xfa\xf4\xe1\xab\xea\xea\x1c\x35\x25\x8c\x21\x78\x48\x9c\xde\xfb\x48\xfd\xa5\x17\x9f\xeb\xf1\x5c\xb1\xf3\x7b\x1f\x2d\x33\x94\x0c\xfc\xf2\xa7\x2d\xd5\xa7\x9e\x55\x5b\x27\xfe\x5a\xec\x5f\x06\x1c\xe6\xcc\x35\x75\x7a\x83\xca\xbb\x74\xcc\x57\x4e\x30\xdb\xbe\xa0\xa7\xd5\x5f\xad\xb2\x76\xdd\xb9\x04\x6b\xd7\xd5\xef\x2d\x0b\x1a\xab\x2b\x6f\x83\x1a\x68\xbf\xfe\xe7\x1f\xfc\x00\x88\xca\x15\x1b\xbf\xff\x74\x52\xfd\xba\xf8\x06\x3e\xa5\x6c\xc5\xa3\xa1\xe0\xda\x7d\xdd\xb8\x65\xc9\x7a\xaf\x43\xbc\xed\x0e\xa8\x7d\xed\xdc\xc4\xd6\x45\x71\x7f\xb7\x9d\x63\x08\x94\xd7\xd5\x69\xb4\xf6\x9e\x95\x8b\x6b\xb7\xff\x75\x11\x57\xdf\xd3\x57\x5c\x64\x52\x5b\x8b\x23\x45\x91\x3a\x1b\xb3\xf5\x8e\xcd\xdd\x5a\x9d\xd3\x1d\x85\x73\x40\xbd\x77\xe5\x21\xf1\x0f\xb9\x2a\x6d\x89\x86\xc0\x26\xd0\x83\xef\xdc\xc4\x59\x25\x25\xba\x01\xf7\x25\x57\xec\x6e\x68\xc0\x76\x63\x49\x51\x69\xa9\x4e\x53\xb1\x58\x55\x79\xdd\xe5\x2f\xdd\x99\x8b\x96\x55\x1b\x97\x2d\x76\xaf\xca\x89\x03\x88\x45\x75\x47\x75\xdc\x5b\xec\x27\xc8\x89\x5a\xd0\x12\x74\xba\x74\xe2\x54\xc8\xed\x51\x42\xa3\xb9\xb0\xd3\xc5\x87\xc0\x80\x99\x5a\xba\xca\xec\x24\x61\xae\x04\x74\x50\x1b\x0e\xf1\x36\x6c\x93\xce\x10\x92\x3e\xc8\x00\xeb\x85\x46\xd0\x01\x87\x9d\x6e\xdc\xc9\x48\xf1\xe5\x49\x08\x79\xaa\x3d\xee\xb0\x8b\x31\x10\xbe\x93\xb0\x1d\xe5\x4b\x37\x2e\xda\x2b\x58\x74\xc6\x1a\x67\xc5\xa2\xd2\xda\xae\x85\x75\x45\x36\xbd\x56\x03\xdb\x03\xcf\xfe\x51\xfc\x8b\xf8\xd9\xe1\x87\x47\x58\x30\x6a\xdc\x8c\x7f\xf4\x2f\xb0\x1e\xb6\xc2\xa6\xbc\x0d\xff\x75\xcd\xc5\x4f\x1e\x7a\xf2\xe2\x35\x72\x06\x99\xee\xdf\x8a\x7f\x12\x7f\x24\xbe\x23\x8a\x8f\x0c\xba\x5a\xd9\x15\xfb\x9e\x7a\xff\xe3\xbf\x7f\xf0\x93\xe5\x55\x8b\x16\xeb\xc4\x37\xff\xa1\xc2\xb8\xe4\xdc\x57\x2e\xde\x6a\x77\xc6\xae\x7a\xff\xe2\xe4\x13\x77\x0c\xe3\xc3\x8d\xf7\xb7\x7b\xca\x6d\xa5\x4e\x0d\x4b\x18\xa3\x46\x5f\x57\xb7\xa0\xb6\xaa\x48\x0f\xd3\x3f\x3a\xff\xf1\x48\x91\x7f\xf7\x41\x70\xde\x55\x7f\x7a\xfd\x4e\xfd\x21\xf1\x22\x51\xbc\x49\x77\xc7\x5d\xa5\x7a\x06\x57\x1c\x7a\xfa\xd2\x35\x6b\x2e\x7d\x5a\xce\xb8\x6b\x0e\x45\x55\x6b\x1e\xfc\xbb\x78\xd7\x0b\x77\x40\xd3\x27\xaf\x7c\x55\xa8\x77\x6e\xb8\x2b\xe7\xdb\x27\x5e\xf0\x09\x9c\xd1\xc7\xb2\x84\x39\xfb\xda\xa7\x7e\xf6\xd3\x27\xaf\x3e\x13\xbb\x62\x57\xff\x54\xf6\x27\x91\x6c\x8c\xf4\x1d\xb0\x02\x35\xa3\x2e\xc9\xa7\x3b\x8d\xce\x47\x57\xa0\xdb\xd1\x37\x11\xb2\xda\x6b\xaa\x3b\x80\xfe\x05\x4e\x81\x60\xc0\xff\x7f\x5a\x3e\x7e\x2d\x04\x76\xdb\x42\xe9\x2f\xe8\xf7\x95\x83\xdf\x17\xfc\x3f\x2c\x1f\xcc\x98\x5a\x4c\xa6\x16\x53\xe6\x5f\xe4\xcc\xb7\xda\x16\x1c\x39\xb8\xa0\xad\x6d\x01\x59\xb2\xa0\x0d\xd0\xbf\x81\x22\xe5\x80\xa6\x4c\x26\x53\xa5\xc9\xf4\x6f\x43\xfb\x3f\x5b\x42\xc9\xb0\x94\xd8\xe7\x2a\x5a\x33\x65\x32\x1d\xfe\x17\xb9\xec\x43\xd8\x7c\x14\x71\x6b\x38\x84\xae\xa4\x6b\x4d\x79\x1f\x6e\x33\x7d\x9a\x72\x7b\x48\x9d\xd9\xe9\x02\x03\xb8\x9b\x41\xda\x77\xd2\x41\xaf\x49\x47\xac\x98\x59\x62\xa0\x8f\xd0\x33\xae\x7e\x52\xfc\x14\x27\xdb\x04\xac\xb4\xeb\x60\xa6\xa6\x02\x3c\xee\x90\xc3\x69\x65\xcd\x72\x80\x15\x25\x74\x71\x39\x84\x3b\xc1\x05\x9c\x11\xcc\x75\xd6\x4e\x70\x18\x41\xde\xdd\x6b\x04\x89\x5c\x4d\xb5\xa7\x4e\x0f\x75\x21\x17\x70\x9c\xeb\xde\xc7\x9d\x7a\xbd\xc1\xe7\x7c\x3c\xac\xf7\x2d\xd5\xc7\xc5\x3f\x1f\x32\xe1\xa2\xaa\x7a\x53\xc6\x1d\x70\x67\x4c\xf5\x55\x45\xd8\x74\x48\xfc\x73\x5c\xbf\xd4\xa7\x0f\x3f\xee\xf4\x19\xf4\x7a\xe7\xe3\xf7\x96\x97\xa8\x1b\xca\x21\x24\x05\x86\x7c\x89\x51\x97\x56\x33\x25\xa5\xb4\xa1\x92\x80\x43\x69\x07\x8c\x27\x69\x07\x8c\xc7\xb5\x53\x5a\xc2\x54\x97\xaa\x19\xf1\x25\x29\xa6\x65\xa8\xbc\x41\x5d\x02\x77\x56\x8d\xe9\xfd\x4e\xa7\x5e\xbf\x6d\xbf\xdb\xaf\xa9\x83\xc6\x5b\xc4\x17\x3e\xb2\x34\x54\x58\x55\x96\xa9\x37\x4a\xdc\xee\x92\x37\xa6\x2c\x2a\x6b\x45\x83\xe5\x23\x68\xbf\x45\x7c\xad\x4e\xe3\x77\xef\xdf\xa6\xd7\x3b\x9d\x7e\xfd\x58\x15\xe7\x6d\xae\xe2\x3a\x6f\xbd\xb5\x13\x6a\x1b\x1b\x58\xda\x92\xd7\x60\x90\x1b\x12\x5f\xbb\x05\xda\x4f\xde\x90\xf8\xc2\x2d\xd0\x38\xbf\x21\xb6\xa1\xb1\x16\x68\x43\x5c\x55\xb3\x17\xcd\xf3\xf1\xb3\xd0\x27\x2a\xa0\x8b\x5c\x3a\xa9\x70\x74\x56\xa9\xb5\xa8\xc1\x61\xe1\x39\xcc\xf0\x2c\xb8\xe9\x33\x72\x6d\x38\x54\xcb\x3e\xcb\x0f\x5e\x7d\xa8\x90\x7f\xe7\xee\x04\xcf\x0f\x5e\xfd\xb3\xc2\xcd\x60\xfb\x06\x2c\x15\xef\xdc\x39\xa9\xd1\x3e\x22\xbe\xf6\xc8\x91\x62\x38\x4b\x82\xa1\xe9\x91\x7b\xf1\x4d\x78\x68\xc7\x7f\xde\x21\xf0\xfc\xaa\x2b\x7e\x5a\x90\x20\xf5\xc5\xe8\x28\xd3\x21\xde\x55\x10\x5f\xba\xe7\x51\xf1\xc5\x17\x8a\xbf\x0c\x67\xe5\x21\x7c\xcf\x77\xa1\xed\x85\x62\xc7\x19\xf2\xfb\x47\x25\xfe\x9f\x01\x59\x90\x03\xb9\x25\x8f\x73\x6b\x8d\x16\x6a\xac\x9e\xb0\x93\x07\x96\x34\x81\x93\xf7\xd4\x39\x79\x0f\xf3\xaf\xc2\xf5\x3d\x7c\xa7\xff\x9b\xf7\xb7\x3e\xb4\xca\x7e\xd8\x2e\xf6\x43\xcb\x85\xe2\x21\x78\xfb\xf0\xc8\xc7\x70\xfe\x33\x6b\x9f\xc6\x1d\x74\x42\x13\x9f\x13\xdf\x7d\xf5\x9c\x73\x5e\x85\x6a\xe8\x84\xea\x57\xff\x78\xb2\xe7\x8d\x23\xe2\xa3\xb0\x45\xfc\x1a\xec\xa8\x6a\x8d\xfb\x70\xe2\x42\xf1\xd0\x85\x13\x23\x1f\xc7\x37\xad\x79\x7a\xcd\x16\x09\xeb\x9c\xb9\x2d\xe1\x89\x93\xac\x0a\x75\xc8\x7d\x14\xf8\x4d\xec\x51\x74\x06\x1a\x46\x49\x34\x81\x2e\x40\xf7\xa3\x47\xd1\x73\xe8\x65\xf4\x16\xfa\x10\x7d\x84\x10\x78\x89\xc7\xdd\x09\x1e\x39\xa4\x30\xa9\xf6\x82\xc7\xcb\x49\x8f\x18\x44\x3e\xef\x8a\x37\x10\x3b\x27\x3d\x42\x48\x4f\x09\x4e\x87\xfc\x56\x22\x24\xbd\x8c\x70\xfa\xa4\xf9\x9e\xce\x3a\x21\xc6\x21\xbf\xbe\xe8\x04\x70\x18\x40\x02\x1c\x48\x79\x6f\x01\x4e\x07\xad\xf4\x42\x28\x1c\x72\x58\x1d\x98\xe7\x3c\xf4\x16\xe5\x7d\x87\x17\x87\xc2\xf4\x67\x27\xc5\x2b\x0d\xb9\x08\xef\xc2\x1c\x28\xad\xc9\x08\x52\x7b\x52\x58\x23\x5a\x2d\x37\x03\xb3\xf4\x1c\x73\x6f\xf6\xc8\x77\x74\x82\x83\x0d\x31\xcd\x81\x26\xc2\xae\x58\xc6\x1a\x46\x9a\x5c\x84\xc1\x3c\xe1\x59\x9e\x10\x1d\xa7\x55\x69\xb5\x9c\xab\xb6\x14\x4c\x6a\xbb\x4e\x1b\x72\xd5\x6f\x73\x9a\x7c\x75\x0b\x1d\x6b\x06\x5c\xf5\x16\xfe\x4a\x96\xab\x30\x94\x72\x78\x18\x38\xff\x80\x8d\x59\x37\xc8\xd9\xec\xe5\x0c\x3e\x9f\xd7\xf9\x5a\xcd\x7d\xcb\x7d\x47\xba\x39\x93\xd1\x50\x4c\x88\xa9\x0c\x9f\xae\xe3\xab\xeb\x75\x5a\xbe\xba\x7e\xda\x5e\xdb\x55\x52\xa2\xb3\x58\xba\x4a\x4a\x58\xc6\xaa\x6b\xeb\x76\xeb\x4a\xcb\xba\xbf\xdc\x1f\x4c\x6e\x1a\xb7\x5d\x70\x5b\x87\x0e\x46\x3e\x59\xea\x23\xeb\x26\x1a\xdc\x9d\xb5\x4c\x70\x5b\x5f\xe5\x45\xb7\x3f\xb8\xf4\xd4\x8b\x27\xcf\x68\xe6\x02\x03\xf6\xca\xcf\xb3\x06\xb5\xcd\xda\xaa\x97\xd2\x6f\x30\x96\xea\x32\x86\x58\x4d\xe6\x32\xe6\x6e\xc6\x6e\xb3\x56\xab\xec\x36\x5b\xd5\x74\xd2\x64\x2c\x2b\xed\x30\x99\x8c\xa1\x4e\xfc\x19\x63\x32\x1a\x69\x37\x8c\x86\xe2\x27\x8d\x6a\x87\x23\xe4\xd2\x34\x06\xc1\x5b\x64\x83\xa2\x92\xe6\xc7\x1e\xf4\x08\x18\xcc\x18\x03\x01\xc2\x10\xac\x67\x35\x2c\x47\x80\x35\x39\xc1\xc8\xeb\x31\x2e\xd5\x5b\xbc\x0d\x65\x97\x9f\x73\x25\xf4\xc7\x18\x5c\x52\xa5\x87\x82\x4a\x6b\xe0\x8d\x6e\xcb\x5f\xb5\xee\x3a\xa7\x5b\x75\xdf\xed\xea\x72\x70\x9b\xc4\x4f\xcb\x82\xb1\x22\xb5\x9e\x54\xdc\xe7\x92\x89\x95\x70\xe2\xdb\xe6\xfa\x22\x95\x99\x26\x24\x14\xd2\x59\x2d\x4b\x4a\x4a\x75\x16\xeb\x34\x94\xf5\xba\x75\x6d\x3d\x36\xab\x0e\x2f\xd9\x2e\x7e\xba\xa2\x8b\x0c\x6e\x61\xc3\x6a\x58\xda\x34\x7a\xda\x59\x86\xed\x57\xdc\xb1\x68\xf1\xc5\xd9\x75\xea\x0d\xe7\xb5\x3b\xc3\x76\xbe\x7b\x68\xef\x69\xa6\xb5\x5b\x47\x70\xc6\xd6\x6a\x30\xa8\x6d\x52\x0a\xac\xa9\x5c\x65\x35\x9b\xcb\x18\xc6\x7a\xe4\x14\x5b\x35\xc3\xd8\x17\x54\xb3\x8c\x93\x6c\x2b\xed\x32\x99\x8c\xa5\x65\x9d\xd5\xa6\xe9\xf5\xc6\x62\x86\x98\x0d\xc6\x12\x42\x4c\x1f\x38\x42\x26\xa3\xa6\x31\x54\xa9\x41\x08\x15\x81\x5b\x3e\x71\x1a\x21\xd4\x8c\xb6\x2a\x30\x20\x2d\xba\x4f\x81\x31\xe2\xd1\xf7\x15\x98\x20\x33\x3a\xac\xc0\x0c\xd2\x42\x89\x02\xb3\xc8\x02\x2b\x14\x98\x43\x5a\x98\x50\x60\x1e\xad\xc1\x1e\x05\x56\x21\x1d\xbe\x46\x81\xd5\x48\x83\x1f\x51\x60\x2d\xb2\xe3\x3f\x29\xb0\x01\xb9\x48\x37\x22\x08\x18\x35\x42\x48\x7e\xa3\x44\x61\x40\x0e\x74\xa5\x02\x63\x64\x40\x0f\x2b\x30\x41\xd5\xe8\xc7\x0a\xcc\x20\x07\x60\x05\x66\x51\x2d\xb8\x15\x98\x43\x0e\x18\x52\x60\x1e\x7d\x0d\x76\x2b\xb0\x0a\x15\xe1\x49\x05\x56\x23\x1b\xde\xaf\xc0\x5a\xd4\x80\x9f\x55\x60\x03\x5a\x4c\x08\xea\x45\x69\x94\x41\x93\x28\x8b\x12\x68\x04\x8d\xa2\x3c\xaa\x44\x7d\x28\x82\x76\x20\x01\x55\xa2\xa5\x28\x82\x52\x28\x86\x26\x51\x25\xf2\xa1\x16\xd4\x8a\x42\xc8\x8b\x2a\x51\x37\x4a\xa2\x24\xaa\x9c\x83\x95\x93\x4a\x02\xca\x21\x01\x65\x25\xec\x18\xf2\x22\xd4\x9b\xce\x4c\x66\x13\x23\xa3\xf9\xca\xbe\xc8\x0e\xa1\x72\x69\x24\x15\x9b\xac\xf4\xb5\xb4\x86\xbc\x95\xdd\xc9\x64\xa5\x74\x29\x57\x99\x15\x72\x42\x76\x87\x10\xf3\x22\x34\x80\xd2\x28\x85\xf2\xa8\x1b\x4d\x48\xad\xa5\xd1\x38\x12\x10\x1a\x48\xa7\xf2\xdd\x13\x42\x2e\x3d\x2e\x20\xb4\x16\x09\x68\x04\x15\x50\x12\x45\x50\x16\xa1\xb5\xc2\x48\x21\x19\xc9\x52\xdc\xd5\x68\x15\x5a\x8f\x56\xa0\x6e\xd4\x83\x16\xa1\xd5\x68\x3d\x1a\x40\xfd\xe8\x0c\x34\x88\x56\xa3\xb5\x68\x3d\x42\x03\xab\x57\xad\x5f\xd1\xdd\xb3\x68\xf5\xfa\x81\xfe\x33\x06\x57\xaf\x5d\xff\xef\x51\xdc\x28\x8d\x2a\x87\x12\xd2\xbd\x95\x28\x80\xbc\x28\x8c\xbc\xa8\x65\x0e\x5f\xd0\x46\x21\x9b\x4b\xa4\x53\x95\x01\x6f\xd8\xdb\x22\x0d\xf2\xdf\x6b\x7c\x10\x25\x91\x80\x22\x12\xeb\x64\x26\xc6\x25\x72\x95\x28\x8f\xd2\x52\x3a\x2a\x5d\x39\x99\xa8\x28\x4e\x14\xe5\x67\x3b\x16\x47\x69\x05\x53\xc6\x89\x2b\xf4\x69\x4d\x16\x45\x50\x0c\x09\x68\x5c\x62\xdb\x18\xaa\x44\x11\x94\x97\xea\x13\x68\x18\x15\xe6\xb4\x92\x42\x69\xa9\x14\x95\xfa\xec\x45\x68\x30\x29\x44\x72\x42\x65\x56\x88\x0b\xd9\xca\x7c\xba\x32\x3f\x2a\x54\x1e\x13\x6d\x4e\x88\xe6\xe9\xc0\xe3\xe9\xac\x74\x25\x9e\x4e\xe5\x2b\xf3\xd9\x48\x4c\x18\x8f\x64\xc7\x2a\x23\xf9\x7c\x36\x31\x5c\x90\x6e\x49\xa5\xf3\x89\xa8\x90\x53\x04\x9d\x95\x7a\x76\x02\x6f\xb2\xf9\xca\x59\xe6\x9c\x4c\x17\xd1\x31\x5d\x42\x12\x1f\xf2\x28\x83\x16\xa1\x66\xd4\x3c\x3b\xde\xc8\xbc\x36\xbd\xd2\xc8\xd0\x68\x3e\x9f\x59\xd4\xdc\x4c\xbb\x17\x91\xdb\xf7\x26\xd2\xff\x93\x16\x9a\x51\x52\xe1\x4a\x4a\xe2\x7c\xf3\x17\xb4\xd9\x9c\x4c\x44\x85\x54\x4e\x68\x56\xd6\x38\xff\xec\x1f\xfe\x9e\x64\x93\xe8\xaf\x7b\x1f\xba\x0c\x5d\x8a\x2e\x47\x57\xa2\xab\xd0\x57\xd0\xd5\xe8\x0a\xa0\xe6\x9a\x01\x16\x38\xe0\x41\x05\x6a\xd0\x80\x16\x74\xa0\x07\x03\x18\xc1\x04\x66\xb0\x80\x15\x6c\x60\x07\x07\x38\xa1\x08\x8a\xa1\x04\x4a\xa1\x0c\xca\xc1\x05\x15\x50\x09\x55\x50\x0d\x35\x50\x0b\x75\xe0\x06\x0f\x2c\x80\x7a\x68\x80\x85\xd0\x08\x4d\x40\x1f\xeb\x5b\xa0\x15\x7c\xe0\x87\x00\x04\x21\x04\x61\x68\x83\x76\x58\x04\xa7\xc0\x62\xe8\x90\x5e\x16\x2d\x81\x6e\xe8\x81\x5e\xe8\x83\x7e\x18\x80\xa5\x70\x2a\x9c\x06\xcb\x60\x39\xac\x80\x95\xb0\x0a\x56\xc3\x20\xac\x81\xb5\xb0\x0e\xd6\xc3\x06\xd8\x08\xa7\xc3\x19\x70\x26\x6c\x82\xb3\xe0\x6c\xd8\x0c\x5b\x60\x08\xb6\x42\x04\x86\x91\x01\x7d\x8c\xf4\x10\x85\x18\x08\x10\x87\x11\x18\x85\x04\x6c\x83\x31\x48\xc2\x38\xa4\x20\x0d\x19\xd8\x0e\x59\xc8\x41\x1e\x0a\xb0\x03\x26\x60\x27\x4c\xc2\x2e\xf8\x12\x9c\x03\xe7\xc2\x79\x70\x3e\x4c\xc1\x05\x70\x21\xec\x86\x2f\xc3\x1e\xb8\x08\xf6\xc2\xc5\x70\x09\x5c\x0a\x97\xc1\x57\xe0\x72\xd8\x07\x57\xc0\x95\x70\x15\x5c\x0d\xd7\xc0\xb5\x70\x1d\x5c\x0f\x5f\x85\x1b\xe0\x46\xb8\x09\x6e\x86\x5b\xe0\x56\xb8\x0d\x6e\x87\xfd\x70\x07\x7c\x0d\xee\x84\xbb\xe0\x6e\xb8\x07\xee\x85\xfb\xe0\x00\x7c\x1d\xee\x87\x6f\xc0\x03\xf0\x1f\xf0\x4d\xf8\x16\x3c\x08\xdf\x86\x87\xe0\x61\xf8\x0e\x3c\x02\x8f\xc2\x77\xe1\x31\x78\x1c\x9e\x80\x27\xe1\x29\x78\x1a\x9e\x81\x83\xf0\x2c\x3c\x07\xdf\x83\xef\xc3\x0f\xe0\x79\x78\x01\x5e\x84\x1f\xc2\x4b\xf0\x23\xf8\x31\xbc\x0c\x3f\x81\x9f\xc2\x21\xf8\x19\xbc\x02\xaf\xc2\x6b\xf0\x3a\xbc\x01\x6f\xc2\x5b\xf0\x9f\xf0\x36\xbc\x03\x3f\x87\x5f\xc0\xbb\xf0\x4b\x78\x0f\xde\x87\x0f\xe0\x57\xf0\x21\xfc\x1a\x7e\x03\xbf\x85\xff\x82\xdf\xc1\xef\xe1\x0f\xf0\x47\xf8\x13\x7c\x04\x1f\xc3\x61\xf8\x33\xfc\x05\xfe\x0a\x9f\xc0\xdf\xe0\xef\xf0\xdf\xf0\x0f\xf8\x14\x3e\x83\xcf\xe1\x08\x4c\x83\x08\x47\x31\xc2\x80\x31\x26\x98\xc1\x2c\xe6\x30\x8f\x55\xa8\x1a\xab\xb1\x06\x6b\xb1\x0e\xeb\xb1\x01\x1b\xb1\x09\x9b\xb1\x05\x5b\xb1\x0d\xdb\xb1\x03\x3b\x71\x11\x2e\xc6\x25\xb8\x14\x97\xe1\x72\xec\xc2\x15\xb8\x12\x57\xe1\x6a\x5c\x83\x6b\x71\x1d\x76\x63\x0f\x5e\x80\xeb\x71\x03\x5e\x88\x1b\x71\x13\xf6\xe2\x66\xdc\x82\x5b\xb1\x0f\xfb\x71\x00\x07\x71\x08\x87\x71\x1b\x6e\xc7\x8b\xf0\x29\x78\x31\xee\xc0\x9d\xb8\x0b\x2f\xc1\xdd\xb8\x07\xf7\xe2\x3e\xdc\x8f\x07\xf0\x52\x7c\x2a\x3e\x0d\x2f\xc3\xcb\xf1\x0a\xbc\x12\xaf\xc2\xab\xf1\x20\x5e\x83\xd7\xe2\x75\xe8\x15\xbc\x1e\x6f\xc0\x1b\xf1\xe9\xf8\x0c\x7c\x26\xde\x84\xcf\xc2\x67\xe3\xcd\x78\x0b\x1e\xc2\x5b\x71\x04\x0f\xe3\x28\x8e\x61\x01\xc7\xf1\x08\x1e\xc5\x09\xbc\x0d\x8f\xe1\x24\x1e\xc7\x29\x9c\xc6\x19\xbc\x1d\x67\x71\x0e\xe7\x71\x01\xef\xc0\x13\x78\x27\x9e\xc4\xbb\xf0\x97\xf0\x39\xf8\x5c\x7c\x1e\x3e\x1f\x4f\xe1\x0b\xf0\x85\x78\x37\xfe\x32\xde\x83\x2f\xc2\x7b\xf1\xc5\xf8\x12\x7c\x29\xbe\x0c\x7f\x05\x5f\x8e\xf7\xe1\x2b\xf0\x95\xf8\x2a\x7c\x35\xbe\x06\x5f\x8b\xaf\xc3\xd7\xe3\xaf\xe2\x1b\xf0\x8d\xf8\x26\x7c\x33\xbe\x05\xdf\x8a\x6f\xc3\xb7\xe3\xfd\xf8\x0e\xfc\x35\x7c\x27\xbe\x0b\xdf\x8d\xef\xc1\xf7\xe2\xfb\xf0\x01\xfc\x75\x7c\x3f\xfe\x06\x7e\x00\xff\x07\xfe\x26\xfe\x16\x7e\x10\x7f\x1b\x3f\x84\x1f\xc6\xdf\xc1\x8f\xe0\x47\xf1\x77\xf1\x63\xf8\x71\xfc\x04\x7e\x12\x3f\x85\x9f\xc6\xcf\xe0\x83\xf8\x59\xfc\x1c\xfe\x1e\xfe\x3e\xfe\x01\x7e\x1e\xbf\x80\x5f\xc4\x3f\xc4\x2f\xe1\x1f\xe1\x1f\xe3\x97\xf1\x4f\xf0\x4f\xf1\x21\xfc\x33\xfc\x0a\x7e\x15\xbf\x86\x5f\xc7\x6f\xe0\x37\xf1\x5b\xf8\x3f\xf1\xdb\xf8\x1d\xfc\x73\xfc\x0b\xfc\x2e\xfe\x25\x7e\x0f\xbf\x8f\x3f\xc0\xbf\xc2\x1f\xe2\x5f\xe3\xdf\xe0\xdf\xe2\xff\xc2\xbf\xc3\xbf\xc7\x7f\xc0\x7f\xc4\x7f\xc2\x1f\xe1\x8f\xf1\x61\xfc\x67\xfc\x17\xfc\x57\xfc\x09\xfe\x1b\xfe\x3b\xfe\x6f\xfc\x0f\xfc\x29\xfe\x0c\x7f\x8e\x8f\xe0\x69\x2c\xe2\xa3\x04\x11\x20\x98\x10\xc2\x10\x96\x70\x84\x27\x2a\xa2\x26\x1a\xa2\x25\x3a\xa2\x27\x06\x62\x24\x26\x62\x26\x16\x62\x25\x36\x62\x27\x0e\xe2\x24\x45\xa4\x98\x94\x90\x52\x52\x46\xca\x89\x8b\x54\x90\x4a\x52\x45\xaa\x49\x0d\xa9\x25\x75\xc4\x4d\x3c\x64\x01\xa9\x27\x0d\x64\x21\x69\x24\x4d\xc4\x4b\x9a\x49\x0b\x69\x25\x3e\xe2\x27\x01\x12\x24\x21\x12\x26\x6d\xa4\x9d\x2c\x22\xa7\x90\xc5\xa4\x83\x74\x92\x2e\xb2\x84\x74\x93\x1e\xd2\x4b\xfa\x48\x3f\x19\x20\x4b\xc9\xa9\xe4\x34\xb2\x8c\x2c\x27\x2b\xc8\x4a\xb2\x8a\xac\x26\x83\x64\x0d\x59\x4b\xd6\x91\xf5\x64\x03\xd9\x48\x4e\x27\x67\x90\x33\xc9\x26\x72\x16\x39\x9b\x6c\x26\x5b\xc8\x10\xd9\x4a\x22\x64\x98\x44\x49\x8c\x08\x24\x4e\x46\xc8\x28\x49\x90\x6d\x64\x8c\x24\xc9\x38\x49\x91\x34\xc9\x90\xed\x24\x4b\x72\x24\x4f\x0a\x64\x07\x99\x20\x3b\xc9\x24\xd9\x45\xbe\x44\xce\x21\xe7\x92\xf3\xc8\xf9\x64\x8a\x5c\x40\x2e\x24\xbb\xc9\x97\xc9\x1e\x72\x11\xd9\x4b\x2e\x26\x97\x90\x4b\xc9\x65\xe4\x2b\xe4\x72\xb2\x8f\x5c\x41\xae\x24\x57\x91\xab\xc9\x35\xe4\x5a\x72\x1d\xb9\x9e\x7c\x95\xdc\x40\x6e\x24\x37\x91\x9b\xc9\x2d\xe4\x56\x72\x1b\xb9\x9d\xec\x27\x77\x90\xaf\x91\x3b\xc9\x5d\xe4\x6e\x72\x0f\xb9\x97\xdc\x47\x0e\x90\xaf\x93\xfb\xc9\x37\xc8\x03\xe4\x3f\xc8\x37\xc9\xb7\xc8\x83\xe8\x5a\x76\x24\x19\xc9\xe5\xd8\xf1\x42\x2e\x11\xe5\x72\x42\x24\x1b\x1d\x55\x09\xa9\x1d\x42\x32\x9d\x11\xd8\x51\x21\x92\xcd\x33\xb9\x7c\x24\xab\xa1\xc9\x90\x30\x9e\xc9\x4f\x32\x85\x9c\x90\x65\xe2\x89\xe4\xb8\x2a\x3f\x3a\x94\x8c\x64\x47\x04\x9c\x1f\xe5\x29\x9c\xc8\xe5\x71\x7a\x8c\xcb\x0a\xe3\xe9\x1d\x02\xbf\x2b\x9d\x1e\x1f\x4a\xa4\x54\x52\x9e\x2e\xe4\x49\x3a\x1e\xe7\x72\x89\x91\x54\x24\x49\xa2\xe9\x11\x36\x9f\x8d\xe4\x46\x99\xd1\xf4\xb8\xa0\x8a\x27\x92\xc2\x50\x24\x99\x67\xf2\x89\x71\x81\xc9\xa6\x23\x31\x5d\x2c\x3d\x91\x4a\xa6\x23\x31\x5a\xad\x9a\x29\x70\x85\x0c\xcd\xd8\x44\x6a\x38\xbd\x53\x9b\x49\x46\x26\x87\xa2\x89\x6c\x34\x29\x70\x59\x21\x23\x44\xf2\x7c\x56\x88\x67\x85\xdc\xa8\x8a\x76\x45\x6a\x30\x99\x8e\x8e\x31\xf1\x64\x64\x44\x33\x2a\x44\x62\x99\xd1\x74\x4a\xc8\x69\x76\xa4\x93\x85\x71\x61\x28\x1d\x8f\x6b\x15\x90\x12\x50\x2b\x70\x21\xc3\x6d\xcf\x46\xd3\x31\x81\x1f\x8e\x48\x39\xc9\x47\x46\x98\x7c\x64\x24\xc7\x0c\xa7\xd3\x63\x2a\x9a\xd0\x19\x9e\xcd\x64\x13\xa9\x3c\x17\x8d\x8c\x0b\xd9\x08\x43\xa7\x42\x66\x38\x9d\x8c\x71\x89\x7c\x24\x99\x88\x6a\xf3\xc2\xce\xfc\xd0\xa8\x40\x97\x0a\x1a\x09\x9e\x48\xc4\xf2\xa3\x9a\x48\x32\x31\x92\x1a\x4a\x0a\xf1\xbc\x4e\x06\xa3\x42\x2a\x2f\x64\xb5\x72\x41\x5a\x59\xe8\x65\x78\x5b\x21\x97\x4f\xc4\x27\x19\x3a\x16\x6d\x22\x15\x13\x52\x79\x19\x4f\x81\xa5\x7b\x0d\xf1\x48\x54\xa0\x5c\x1b\xda\x91\x88\x09\x69\x3e\x93\x88\xe6\x0b\x59\x81\xcb\x08\xa9\x68\x22\xa9\x19\x8f\x64\x86\x68\x5f\x85\x2c\x17\x89\xd1\x06\x99\x7c\x22\x95\x67\x84\x58\x22\xcf\xe6\x46\x23\x59\x81\x8d\x8e\x0a\xd1\x31\x86\x0a\x4c\x9f\xcb\x0b\x99\xa1\xe1\x48\x74\x6c\x22\x92\x8d\xe9\xe3\x91\x5c\x7e\xb6\xa4\x9a\x01\x18\xca\x74\x36\x13\x29\xe4\x04\x26\x97\x4f\x67\xf8\x78\x3a\x4b\xeb\x75\xd2\xed\x33\x05\xa9\x25\xa5\xc0\x0a\xdb\x84\x68\x5e\x17\x1d\x15\x76\x64\xd3\xf2\xc8\xf5\x33\x05\x69\x08\xea\x4c\xb2\x90\x1b\xa2\x8a\xa1\x19\x4f\xa4\x14\x50\x2b\x2b\x91\x04\xf3\xe9\x31\x29\xd7\x6f\x2f\x08\x39\xba\x9e\x92\x4a\xea\x44\x2a\x9e\x96\xd1\x72\xd1\xac\x20\xa4\x72\xa3\xe9\xbc\x5e\x41\x93\xb5\x42\x9d\x1e\x53\x20\xcd\x70\x24\x35\x03\x46\xb2\xd9\xf4\x84\xd4\x0f\xad\x0c\x4a\xbd\x50\xc9\x70\x21\xa3\x5c\x97\x34\x42\x62\x11\xd5\x23\x6d\x56\xc8\x25\x76\x09\x43\xf1\x42\x32\xa9\x53\xe0\xdc\x78\x24\x99\x34\x09\x3b\xa3\xc9\xc8\x78\x64\xb6\x5b\xcc\x48\x22\x9e\x67\x92\x42\x24\xce\xc4\x13\x59\x41\x25\x4c\x0a\x43\xe9\x8c\x90\x52\x53\x20\x9a\x4c\xe7\x04\xdd\x44\x24\x9b\x4a\xa4\x46\xa4\xdb\xd9\x4c\x32\x92\x12\x54\xd1\x48\x52\x48\xc5\x22\x59\x2e\x1b\x49\xc5\xd2\xe3\x7c\x34\x3d\x3e\x2e\xa4\xf2\xdc\x78\x64\x24\x25\xe4\x35\x33\xfc\x2a\x64\x66\xf9\x48\xfb\xc7\x67\x85\xfc\x84\x20\xe4\xf5\xb9\xd1\x74\x26\x43\x9b\x8c\x46\xb2\x79\x5d\x3c\x9d\x8c\x09\x59\x99\x98\x56\x29\xd0\x2e\x18\x95\x8e\xef\x10\xb2\xf9\x44\x34\x92\x34\x2b\xe5\xd1\x74\x36\xb1\x8b\xae\xe4\x92\xea\xe1\x48\x76\x28\x3a\x4a\x1b\xc9\x4f\x24\xf2\x79\x21\x2b\x33\x9e\x2a\x19\x55\x7b\xa9\xa4\x93\x35\x7e\x28\x2b\xe4\xb3\x69\x32\x26\x4c\x32\xd1\xf4\x48\x4e\xa5\x74\x39\xa7\xcf\x8f\x16\xc6\x87\x73\x43\x85\x0c\x65\x9c\x51\x29\xd1\xee\xd2\xb2\x5a\x32\x24\xa3\x91\x64\x5c\x2b\x59\x17\xd9\xa6\xf0\xb4\xdd\x74\x21\xaf\x4f\x26\x52\x63\x42\x2c\x21\xb3\x92\xcf\x14\x72\xa3\x99\x44\x4a\x2f\xec\xcc\x0b\xd9\x54\x24\x39\x44\x2f\x4b\x26\x24\x91\xe2\xf2\xd9\x74\x66\x74\x52\x3b\x92\xc8\x8f\x16\x86\x65\x3d\x90\xad\x03\x25\xc3\x26\x85\xf1\x74\x8a\x95\x7e\xef\x5a\x49\xc5\x65\x42\x86\x99\x1f\xaf\x5c\xd4\x48\x37\xc8\xc4\x94\x01\xab\x66\xc6\xca\xc9\x2d\x73\x85\x14\xb5\x21\xda\x68\x96\xfe\x68\x28\x83\x63\x24\x9b\xcb\x91\xd1\x58\x4c\x35\x5c\x48\x26\x47\xd3\xd9\x14\x33\x2c\x24\x93\xda\x28\x65\x6b\x3c\x11\x8d\xe4\x05\xcd\x68\x24\x15\x53\xb4\x5b\x02\xa9\xb6\xf1\x12\x54\xc8\xc8\x35\x94\x21\x66\x59\x23\x87\x8e\x69\xa4\x65\x5e\x8d\xd4\x80\x71\x5e\x55\x21\x33\x1f\x89\x36\xc3\x8e\x24\xd3\xc3\x02\x37\x91\x15\x52\xd1\x51\x36\x1f\xc9\x8d\xe5\xb8\x78\x22\x99\x17\xb2\xea\xe1\x6c\x42\x88\x47\x23\x39\x41\x43\x35\x57\xfe\x9d\xb0\x23\xd9\x74\x21\xc3\x50\x5e\xb2\xd1\x64\xba\x10\xe3\x86\x85\xc8\x98\x90\x25\xd1\x42\x9e\x89\xa6\x33\x93\x9a\x4c\x24\x23\xe9\x4f\x22\xc3\xe4\x22\x3b\x04\x0d\xe5\xcf\xd0\x70\x32\x92\x1a\xe3\xb3\x42\x3a\x1b\x13\xb2\xb8\x90\xc4\xe9\xa4\x3e\x97\xcf\x26\xc6\x84\xfc\x68\x36\x5d\x18\x19\x55\x17\x52\x31\x21\x9b\x4c\xa4\x04\x36\x1f\x19\x4e\x0a\xec\x78\x64\x24\x11\x65\xf3\xd9\x42\x74\x4c\x9d\x49\x50\x2b\x27\xe4\xf2\x86\x59\x48\x62\xbb\x69\x24\x9d\x1e\x49\x0a\x43\xb3\x36\x40\x3b\xa7\x82\x1d\x4f\xa7\x84\x49\x4d\x34\x92\x15\xf2\xd2\x48\x55\x32\x58\xc8\x28\x75\xd2\x8f\x58\x06\x25\x5e\xf1\x51\x6a\xc2\x53\x39\x26\x97\xce\xe6\xd5\x34\x91\x7f\x27\x12\x54\xc8\xe8\x66\x66\x36\x69\x52\x99\xd1\x35\xa6\x90\x8a\xa5\xd9\xa4\x30\x12\x49\xaa\x63\x91\xdc\xe8\x70\x3a\x92\x8d\x69\x15\x75\xa6\x77\xea\x66\x54\x5b\x9a\x51\x86\xd3\xc9\x3c\x9f\x4b\xe4\x85\xf1\x48\x46\x55\x18\x1f\xce\x0a\xc9\x64\x84\xcd\x44\x72\x79\x41\x93\xa4\x9d\x18\x1a\x2e\x24\x87\x55\xc2\xce\xe8\x68\x24\x35\x22\x18\x24\x16\x0f\xcd\xcc\x60\x3a\xb9\x28\x6b\x2a\x4f\xa7\xd2\xa1\xf1\x98\x36\x97\x17\xf2\xa3\xe9\x5c\x34\x9d\x11\x54\xb9\x42\x22\x4f\x25\xa6\xa2\x4a\x45\x29\x72\xd1\x74\x3c\x2e\x08\x4c\x3c\x9d\x8e\xe9\xa5\x99\x52\x9a\x4e\xe8\x10\x86\x0b\x89\x64\x2c\x91\x1a\x51\x8d\xa6\x73\x19\x3a\xef\xa8\x23\xe3\xc3\x85\x64\x24\x15\x15\xb8\x71\x21\x36\x96\xc8\x6b\xe3\xb4\x4b\x42\x76\x68\x9b\x90\x67\x86\x05\x21\xcb\x8d\xca\x66\x2a\xde\x12\x17\xcc\xb1\x74\x61\x98\xaa\x52\x8a\x72\x5c\xd2\xbf\x79\x35\xb2\xfe\xcd\xab\x2a\x64\xe6\x23\xd1\x71\x69\x8e\xe1\x6b\xe7\x20\xaa\x66\x30\x34\xc7\x6e\xe5\x63\x42\x6e\x2c\x9f\xce\x70\xc9\x48\x86\x66\x92\xa2\xe4\x75\xe3\xe9\x61\x3a\x2e\xe9\xd7\xa8\x53\xf4\x5b\xd2\x37\xcd\xf6\x42\x3a\xaf\x34\x2d\x83\xb2\x9c\x73\x99\x44\x2a\x25\x64\x39\xf9\x5e\x36\x2b\x64\x92\x93\x1a\xc5\x14\x44\x92\x79\xd3\x5c\x13\x28\x99\xa1\x39\x66\x90\x96\x35\xc2\xce\x0c\xfd\x15\xca\xd2\x4d\x26\x23\x19\xf9\x3e\x36\x37\x9e\x48\x0a\x6c\x3c\x9b\x9e\x48\x91\x71\x61\x94\x1f\x89\x8c\x0b\x99\x48\x4c\x35\x26\x4c\x4a\x7a\xa1\xa2\x6b\x09\x7a\xa7\x41\x02\x24\xd3\x22\x64\x85\x98\x2a\x2f\x64\xc7\x13\xa9\x48\x92\xa1\x2b\x06\xb5\xd4\xa1\xa1\x48\x32\x69\x9c\xb5\x77\x8a\x01\x4a\xa6\xa3\xf2\x64\x21\xfd\x7e\x99\x68\x36\x9d\x51\x53\x14\x3a\x5d\x8e\x51\x63\x93\x48\x8d\x31\x43\xbe\x70\xbb\x76\xce\xcc\xa2\xcd\x15\x32\x42\x36\x17\xcd\x26\x32\x79\x75\xae\x30\x2c\x43\xcc\x90\xaf\xcd\xaf\xcb\x14\x76\xed\xa2\xbc\x4b\x08\x51\x41\x33\x9e\xa0\x0d\x52\x36\x1a\x8e\x81\x43\xd2\xc2\x6b\x34\x21\x24\x63\x86\x99\x89\x46\xee\x8d\x99\x4e\x51\x43\xc2\xce\x7c\x22\x35\x52\x48\xe4\x46\x85\x2c\x97\x4d\x47\xc7\x04\x3a\xf1\xec\x8c\xc6\x52\xe6\x99\xd9\x26\x37\xb3\x68\xb1\xcc\xab\x51\x0c\xd4\xdc\x2a\x6a\xa0\xe6\x96\x25\x03\x35\x9a\x1f\x4f\x06\x99\x68\x2e\xe7\xe7\x22\xa9\xe8\x68\x3a\xab\x91\xad\xaa\xa2\xc4\xc9\x64\x4e\x98\x14\xac\x42\x32\x99\xc8\xe4\x12\xb9\x39\x13\x92\x79\xb6\x6e\x66\xd2\x62\x86\xfc\x2d\x7e\xb5\xb4\xf4\xa3\xed\x73\xf9\x04\xed\xaf\xe1\xd8\xca\x41\x9a\xae\x65\x93\x2f\x55\xaa\x92\xc2\x0e\x21\x49\xd5\x50\x06\x24\x8d\x95\xaf\x4b\xcb\x08\xc9\xac\x4b\x3f\x89\x21\x7f\xab\x4f\x23\x4f\xf9\xd2\x8c\x10\x4d\x8f\x67\x22\x39\x3a\xb3\xc9\x0a\x72\x4c\x53\xf2\xe9\x0c\xbd\x3b\x4c\x84\x42\x96\x8c\x0c\x67\x48\x21\x17\x23\x89\x54\x96\x6c\xcb\x4c\x92\x6c\x61\x98\x8c\x65\x27\xc8\x70\x3e\x4a\x97\xc9\x82\x7a\xf6\x37\x6b\x92\xec\xd0\x30\x55\x8c\xcc\x68\x64\x58\xc8\x33\x43\x7e\x5f\xbb\x65\xb6\x56\x79\x63\x24\xe4\x1c\x27\x56\xd1\x61\xe9\x67\xaa\x25\x1b\x6c\x9e\x57\x92\x6c\xd3\x90\xdf\x1f\xa0\x49\x50\x37\x99\x2e\xe4\x0b\xc3\xca\x40\x94\x02\xb3\x33\x91\x1a\x51\xef\x9c\x59\x7a\xcc\xde\x43\x99\xc9\xc7\xb2\xe9\xcc\x70\x7a\xa7\x3e\x97\x8f\x44\xc7\x66\x8c\x97\x3a\x91\xca\xe5\x23\x23\xd9\xc8\x38\x17\x4f\x26\xa2\x63\x59\x12\x89\xa5\x98\x78\x6b\xb8\xd5\x30\x9c\xc8\x0f\x17\x28\xeb\x15\x31\x14\xc6\x87\x93\x59\xad\x9c\x49\x55\xc6\x64\x3a\x35\x32\x67\x96\xd2\xcf\x29\x17\x32\x73\xaf\x52\xbd\x32\xcd\x29\xcb\x3f\xf1\x89\x44\x2a\x96\x9e\xc8\xf1\x91\x54\x2c\x9b\x4e\xc4\xd8\x64\x22\x55\xd8\xc9\xc7\xb2\x89\x61\x3a\xb7\xe4\xc6\x26\x33\x82\x26\x9e\x2e\x64\x73\xdb\x0b\x91\xac\xc0\xe5\xa9\x1d\x4e\x73\x71\x61\x3c\x92\x14\x18\x9a\xd0\x09\x3c\x9f\xc8\x90\x5c\x81\x8a\x36\x14\xe2\xe9\xc3\x4d\x62\x87\x40\x86\x0b\x23\x78\xc7\x18\x3b\x21\x24\x86\xd3\x5c\x56\x48\x65\x05\x7a\x43\xd8\x67\x90\xc6\x3e\x34\x33\x78\x5a\x17\xb0\xcb\x5d\x9a\x99\x73\x93\xf2\x9c\x43\x2f\x85\x0c\xb1\x74\x7e\xce\x05\x5a\xd7\xa6\xdb\x91\x18\x17\xd2\x43\x72\x9f\x98\x21\x7f\x5b\x8b\x5e\x9e\xd9\xa4\x8a\xa1\x34\xad\xf2\xd1\xc4\x4f\x13\x2a\xab\xb6\x20\x4d\x42\x34\x09\xd3\xa4\x8d\x26\xed\x7c\x21\x95\x18\x68\xed\x6e\x61\xe2\xad\x91\x56\x66\xc8\xdf\x4e\x91\xda\xfd\xb4\x48\x91\xda\x29\x52\x3b\x45\x6a\xa7\x48\xed\x14\xa9\xbd\x9d\x19\x0a\xb4\x48\x18\xc3\x14\xf2\xd1\xc4\x4f\x93\x80\xdc\x5a\x4f\x2b\x2d\x84\x68\x12\xa6\x49\x1b\x4d\x28\x52\x6b\x0b\x4d\xe8\xd5\x56\x8a\xd4\x4a\x91\x5a\x03\x34\x09\xd2\x84\x62\xb4\x52\x8c\x56\x8a\xd1\xaa\xf4\xad\xb7\x45\xc9\x29\x9e\x8f\xe2\xf9\x28\x9e\x8f\xe2\xf9\x28\x9e\x8f\xe2\xf9\x28\x9e\x8f\xe2\xf9\x28\x25\x3f\xa5\xe4\xa7\x18\x7e\x8a\xe1\xa7\x18\x7e\xa5\x7b\x7d\x4a\x83\x7d\xad\x4a\x2e\xdd\x41\x51\xfd\x0a\xc9\xbe\xa0\x92\x87\x94\x9c\x36\x1e\xa0\x6d\x04\x28\xd5\x00\xa5\x1a\xa0\x54\x03\xd2\x05\x8a\x1a\x50\x50\xfb\x29\xe1\x20\x25\x1c\xa4\xcd\x06\x29\x52\x90\x22\x05\x29\x52\x90\x22\x05\x29\x52\x90\x22\x05\x69\x57\x43\x14\x23\x44\x31\x42\x14\x23\x44\x31\x42\x4a\x57\x07\xa4\x6b\x14\x29\x14\x66\xe2\xad\x71\xe9\x1a\x45\x0a\xd3\x0b\x61\x8a\x14\xa6\x48\x61\x7a\x21\x4c\xc9\x84\x29\x99\x70\x88\xde\x1c\xa5\x10\x25\x13\xa6\x18\x6d\x14\xa3\x8d\x62\x50\xbd\x08\x50\xbd\x08\x50\xbd\x08\x50\xbd\x08\x50\xbd\x08\x50\xbd\x08\x50\xbd\x08\xb4\x51\x8c\x76\x8a\xd1\x4e\x31\xa8\x52\x04\xda\x29\x46\x7b\x80\x89\xfb\x24\x31\xb6\x87\x28\x24\x5d\xa0\x18\x54\x29\x82\x2d\x2d\x34\x69\xa5\x89\x8f\x26\x7e\x9a\x04\x68\x12\xa4\x49\x88\x26\x61\x9a\xb4\xd1\xa4\x9d\xdd\x21\xa4\x0a\x39\x66\x28\x48\x55\x22\x48\xdb\x0a\x52\x95\x08\x52\x95\x08\x52\x95\x08\x52\x95\x08\x52\x95\x08\x52\x95\x08\xb6\x52\x22\x3e\x4a\xc4\x47\x31\xa8\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\x32\x04\xa9\xf9\x0a\xfa\x29\x86\x9f\x62\xf8\x29\x06\xd5\x81\xa0\x9f\x62\x04\x28\x46\x80\x62\x04\x28\x06\x15\x7d\x90\x8a\x3e\x48\x45\x1f\xa4\xa2\x0f\x52\xd1\x07\xa9\xe8\x83\x01\x8a\x11\xa4\x18\x54\xee\x41\x2a\xf7\x20\x95\x7b\x90\xca\x3d\x48\xe5\x1e\xa4\x72\x0f\x52\xb9\x07\xa9\xdc\x83\x54\xee\x41\x2a\xf7\x20\x95\x7b\x90\xca\x3d\x48\xe5\x1e\x0c\x51\x8c\x10\xc5\xa0\x42\x0f\x86\x28\x46\x88\x62\x84\xda\x99\xb8\x2f\xd4\x42\x13\x8a\x11\xf6\x51\x88\x62\x50\xa1\x07\xa9\xd0\x83\x61\x8a\x11\xa6\x18\x54\xe8\x41\x2a\xf4\x20\x15\x7a\x90\x0a\x3d\x48\x85\x1e\xa4\x42\x0f\x52\xa1\x07\xa9\xd0\x83\x54\xe8\x41\x2a\xf4\x20\x15\x7a\x90\x0a\x3d\x48\x85\x1e\xa4\x42\x0f\x52\xa1\x07\xa9\xd0\x83\xed\x14\x83\x5a\x82\x20\xb5\x04\x41\x6a\x09\x82\xed\x6d\x4c\xdc\x17\x16\x24\x35\xf5\xb5\xb5\x28\x79\x2b\x33\x14\xa2\xa2\x0f\x51\xd1\x87\x14\x7b\xe0\x6b\x0b\x2a\x79\x88\x56\x86\x69\xd2\x46\x93\x76\x66\x28\x44\x75\x29\x44\xe5\x1f\xa2\xf2\x0f\x51\xf9\x87\xa8\xfc\x43\x54\xfe\x21\x2a\xff\x10\x95\x7f\x88\xca\x3f\x44\xe5\x1f\xa2\xf2\x0f\x51\xf9\x87\xa8\xfc\x43\x54\xfe\x21\x2a\xff\x10\x95\x7f\x88\xca\x3f\x44\xe5\x1f\xa2\xf2\x0f\xf9\xe4\x9f\xa5\xaf\x5b\xe9\x61\x77\xab\x92\xfb\x94\xdc\xaf\xe4\x4a\x57\xbb\x95\xae\x76\x87\x94\x3c\xac\xe4\x6d\x4a\x3e\xd3\x5e\xb7\x92\xf7\x28\x79\xaf\x92\xf7\x29\x79\xbf\x9c\xf7\x28\x74\x7b\x14\xba\x3d\x0a\xdd\x1e\x85\x6e\x8f\x42\xb7\x47\xa1\xdb\xa3\xd0\xed\x51\xe8\xf6\x28\x74\x7b\x14\xba\x3d\x0a\xdd\x1e\x85\x6e\x8f\x42\xb7\x47\xa1\xdb\xa3\xd0\x55\x8c\xa6\xaf\x57\xa1\xdb\xab\xd0\xed\x55\xe8\xf6\x2a\x74\x7b\x15\xba\xbd\x0a\xdd\x5e\x85\x6e\xaf\x42\xb7\x57\xa1\xdb\xab\xd0\xed\x55\xe8\xf6\x2a\x74\x7b\x15\xba\xbd\x0a\x5d\xc5\xb6\xfa\x14\xdb\xea\xeb\x53\xe8\xf6\x29\x74\xfb\x14\xba\x8a\x85\xf5\x29\x16\xd6\xd7\xa7\xd0\xed\x53\xe8\xf6\x29\x74\xfb\x14\xba\x7d\x0a\xdd\x3e\x85\x6e\x9f\x42\xb7\x4f\xa1\xdb\xaf\xd0\xed\x57\xe8\xf6\x2b\x74\xfb\x15\xba\xfd\x0a\xdd\x7e\x85\x6e\xbf\x42\xb7\x9f\x6a\x4a\xbb\x42\xb4\x5f\x21\xda\xaf\x10\xed\x57\x88\xf6\x2b\x44\xfb\x15\xa2\xfd\xfd\xf2\xa7\x25\x38\x7a\x14\x61\xe9\xeb\xb3\x01\x21\x54\xa4\x7c\xf1\x06\x04\xf8\x39\x04\x88\x99\xfd\x36\x25\x7d\x9f\xfe\x71\xc7\xd7\x24\xb7\xb7\x1f\xad\x5e\xdc\x42\xf3\xd7\x5a\x47\x1f\xfb\xff\x02\x00\x00\xff\xff\x5c\xbc\x44\xc5\xac\x86\x02\x00")
+
+func uiAppLibFontAwesome470FontsFontawesomeWebfontTtfBytes() ([]byte, error) {
+ return bindataRead(
+ _uiAppLibFontAwesome470FontsFontawesomeWebfontTtf,
+ "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.ttf",
+ )
+}
+
+func uiAppLibFontAwesome470FontsFontawesomeWebfontTtf() (*asset, error) {
+ bytes, err := uiAppLibFontAwesome470FontsFontawesomeWebfontTtfBytes()
+ if err != nil {
+ return nil, err
+ }
+
+ info := bindataFileInfo{name: "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.ttf", size: 165548, mode: os.FileMode(420), modTime: time.Unix(1, 0)}
+ a := &asset{bytes: bytes, info: info}
+ return a, nil
+}
+
+var _uiAppLibFontAwesome470FontsFontawesomeWebfontWoff = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x6c\x92\x53\x70\x25\x0c\xb0\xad\x77\x6c\x3b\x13\x4c\x6c\x4c\xec\x89\x6d\x4e\x6c\xdb\xb6\x6d\xdb\xb6\x6d\x27\x3b\xb6\x6d\xdb\xb7\xfe\xba\xe7\xbc\x9d\xae\xfa\xaa\x1f\xfa\xa1\x57\x7d\xb5\x5c\xe5\x44\x45\x01\x20\x00\x00\x00\xc4\xe7\x14\x80\x00\x00\x00\x40\x43\xaa\x00\xe0\x00\x28\xc0\xff\x31\xa2\xa2\xca\x32\x00\x00\x08\x23\x00\x00\xc0\xfb\x0f\xcb\x1e\xb1\x76\x31\x61\x11\x51\x00\x00\x44\x1a\x00\x00\x10\x02\x00\x80\xdf\xa0\xb7\x00\x70\x39\x25\x06\x26\x00\x00\xc4\x0a\x00\x00\xf0\x01\x00\x00\xbd\x30\x26\x0f\x7e\x43\x6b\x7d\x3b\x00\x00\xa4\x0a\x00\x00\x31\x07\x00\x40\xef\x61\x7b\xb9\x7c\x4d\xf5\x1d\xed\x00\x00\x30\x6c\x00\x00\x00\xfd\x1f\x3f\x3f\x00\x30\x53\x2b\x77\x13\x00\x00\xec\x37\x00\x44\xd7\x1d\x00\x2a\xdd\x15\xfb\x52\x23\x63\x66\xac\x6f\x04\x00\x31\xc8\x02\x00\x00\xcc\x00\x00\x80\x0d\x39\xfc\x88\xce\xcc\xcc\x58\x1f\x00\x62\x30\xfb\x3f\x7f\x49\x91\xc0\x60\x9b\xcd\xac\x9d\xdc\x00\x20\x06\xb7\x00\x00\xe8\x23\x00\x00\x7b\x2b\xe2\x8e\x1d\x6c\x65\x6b\xa8\x0f\x00\x31\x3e\x04\x00\xa0\x30\x01\x00\x38\x64\xd0\xa7\x02\x2d\x6b\x7d\x37\x3b\x00\x88\xd5\xe7\xff\x66\x06\xa3\x05\xc5\xb3\xd1\xb7\x36\x06\x80\x58\xe3\x01\x00\xa0\xc2\x00\x00\x78\xc8\x41\x6a\x64\x95\x9d\xad\xa3\x13\x00\xc4\x56\x0f\x00\x40\x0a\x06\x00\x70\x9d\x6b\x63\x33\xf3\xff\x33\xf5\x9f\x8b\x29\xde\x82\x99\xff\xf6\xa4\x1c\xcf\x7f\x3e\x00\x8b\x7f\xcc\xda\xdd\xb2\x0c\xf5\x8c\xf4\xf4\x76\xc1\x0c\x60\x20\x91\xf5\x0c\xf4\x8c\xf4\x8c\xb8\xc0\x49\xd5\xfb\x78\x20\x01\xf0\x6d\x80\x17\xc0\x7f\x77\x93\x49\xa3\xac\xbe\xbe\x89\xbe\xbe\xf9\x41\x83\xa9\xbe\xbe\x59\xc8\xfc\xf4\x08\x1c\x6c\xec\x4e\xec\x5b\xbf\x80\x89\x02\x03\x48\x28\xc8\xe0\x5a\x78\x2b\xf8\x1f\x7f\x2f\x36\x48\xd1\x38\x46\x92\x04\x54\x08\x48\x51\xc0\xec\x24\xb4\x0d\x00\xe0\x96\x35\x9d\xb0\x23\xb9\x6f\x8f\x3c\x7c\x62\x6a\x61\x7c\xfc\xc6\xd7\x47\x7c\x0e\x26\xdc\xed\x37\xc6\xe7\x07\xed\xb9\x20\x12\x26\xf7\x9b\xcf\xff\x15\x7c\x1f\x2d\x2c\xf5\x17\x2d\xf1\x9c\xf3\x98\xce\x65\x31\xb4\xa6\xa6\xe6\xdb\xe0\x96\xc5\x87\xad\x63\xc9\xd3\xb2\x6e\xaf\xcc\x69\xc1\x05\x19\x17\xa3\x29\x07\xe3\x14\x54\x08\x4a\x3c\x44\xfa\x0a\xd4\x9d\x20\xd6\x0d\xbd\xf4\xb6\x63\x8c\xc7\x60\xdd\x4a\xd1\xef\x3f\xea\xa9\x51\x56\x52\x6a\x2e\x47\x99\x78\xc6\x8e\xed\x4e\x35\x05\x54\x32\x96\x3a\x91\x1a\xcb\x15\xcb\xcd\xe5\xd6\x57\xe7\x31\x88\x8b\x2b\xe1\xc0\x34\x83\x0c\xcb\xa9\xc6\x31\xa6\xca\xaa\xc6\x71\xb6\xce\xcd\x03\x3f\x3e\x8a\x2c\xf5\x89\xf9\x94\xd6\x82\xe4\x6a\x0b\x67\x4b\x8d\x8d\x8e\x16\x53\xb0\x07\x6b\xa6\xe4\xdf\xd0\xe3\x38\x6f\x9f\x11\x94\xe7\x2c\x95\x10\x74\xe6\x22\x96\xeb\xb3\x29\x2e\x4d\xa5\xde\xf8\xe7\xff\x92\x05\x47\xe1\x57\xd4\xf5\xc2\x31\x96\x57\xf5\x22\xf1\x9f\x57\x4f\xe2\x0c\x2b\xc2\x39\x27\x35\xfa\x25\x55\xeb\x33\x58\xab\x8c\xf1\x2f\xd4\x77\x42\xd8\xbe\xc5\xe0\x81\x01\xd5\x7a\xcc\xaf\xe8\x5e\xf0\x6c\x9f\x95\x73\x5f\xa7\x91\x9a\xce\x12\xa9\x76\x93\x36\xe3\x74\x1d\x6d\x91\xed\x65\x9a\x76\x28\xd2\x77\x58\xb1\x8c\xc8\x11\x50\xd2\x76\xb1\xdc\x9b\xfb\x90\x2b\x6d\x03\x64\xdf\xbb\xa0\x27\x1c\x83\xb6\x9f\x03\xd8\x7c\xa2\x1c\xc3\x30\x31\x77\x68\x62\x1c\x43\x48\x78\x7a\x84\x3b\x6a\xbd\xc0\xda\xaf\x96\xfb\xfd\xfb\x80\x27\xe2\x7c\x11\x1d\xa4\x29\xdd\x3d\x5e\x4a\x02\x29\x5a\xd1\x44\xa9\x49\x9a\x1f\xf7\x1b\x34\x83\xb7\xc1\x87\xff\x5f\x77\x90\x9f\x1f\x00\xa8\x5b\x56\x57\x37\x8c\x9f\xf2\x52\x32\xe3\xe7\x75\xb7\x6d\xb9\xb7\x67\xb3\xb3\xb3\xb3\xab\x8a\xda\x52\xe5\xb9\xcd\xa9\x8d\x85\xb5\x07\x5d\x46\xb6\x8d\x0b\x38\xf8\x10\xa6\x48\xbc\x88\x80\x00\x32\x96\x24\x11\x75\xd8\x2f\xca\xfd\x6d\x33\xe1\x71\x26\x43\xcc\x07\x32\xd1\xac\x89\x92\x44\x11\x03\x54\x03\xb6\xde\xb7\x75\x52\xf2\xf4\xb6\xa8\xc4\x43\x76\x94\x0e\x82\x9d\xf6\x17\x15\x15\x35\x76\x84\xd3\xa9\x4f\x42\xa7\x6e\xd7\x97\xa7\x4d\xcf\x19\xce\x97\xac\x07\x8e\x29\xeb\x63\x0e\x03\xb4\xbd\x7e\x09\xbc\x54\x98\xf5\xc0\x21\x82\x26\xa4\xfc\xae\x8c\xad\x28\x28\x76\x38\x7f\xa5\x4c\x91\x6b\x74\xb1\x1f\xa2\xeb\x04\xe6\xac\xd7\xa8\xb8\x03\x8b\xbe\x83\xa4\x38\x5e\x6c\x57\xee\x61\xf9\x3a\x1d\x89\x12\x34\x01\x6e\x45\xc5\x71\x9b\x24\xe8\x11\xcb\xf8\x57\x69\xa5\x3d\xfa\xa4\x27\xaa\x08\x5b\x0e\xb1\x5c\x4a\xcd\xb6\x4a\x2a\xbc\x07\x68\x4e\x39\x5a\xda\x29\x68\x01\x27\x7f\xa5\x04\xd8\x4f\x14\xc4\x1b\x33\x58\xf7\x0a\xe7\x0e\x0b\x0d\x28\x28\x67\x3b\x79\x31\x34\xb7\x4b\x59\xb8\x1a\xdb\x91\x71\x9b\xac\x30\xcf\xcb\x01\x33\x5b\xa6\x6c\x81\x33\xe1\x4d\x3a\x87\x85\x65\xed\xe6\xfd\x0a\xe7\x85\x5d\xd6\xbb\x73\xe3\xe0\x39\x9d\xe2\x14\x23\x99\x96\x7f\x99\xc8\x1c\xbc\xd8\xb9\x2b\x87\x0e\xac\xd3\x9d\xa0\x3a\x0a\x5a\x4f\x3e\xf9\x85\x4c\x7e\x5d\xaa\xa9\x8c\xbf\x63\x6c\x0f\x18\x2d\x85\x10\xd7\x7f\xdb\x0b\x9c\xb6\x46\xc3\xcd\x12\x06\xd4\x2c\x8b\xa1\xf0\x0c\xc0\xb6\x70\xce\xef\x01\x6e\x5c\xda\xf4\xb0\x37\xbd\x64\xbf\xfe\x75\xab\x7d\x61\x4b\x9c\x72\x11\x3f\x51\x2c\xe8\x3f\xad\xaa\x6d\x77\xc8\xf1\x7a\x7f\xae\x5b\xc6\x92\x80\x2c\x11\xef\xbd\x36\xb3\x17\x1a\xa3\xc0\xc3\xc4\x15\x91\xa9\x3a\x8e\xfb\x40\xd0\x75\xbb\x93\x0e\x37\x8f\x2e\x2d\xbc\x74\x3f\x61\x3c\xfd\x0b\x02\x42\xba\x92\x53\xd8\x83\x8e\xbe\xb5\xd1\xdb\xd0\x8f\x8a\x5c\x16\x0c\x49\x61\x6e\x82\x93\xf8\x15\x48\x0a\x87\xaf\x67\xdb\x60\x5f\x34\x75\xa3\xb1\xa3\xa5\x81\xcd\x1d\x3d\xb6\xf1\x36\x7b\x41\xc5\xb8\x26\x4a\x73\x2d\x44\x33\xb9\x58\x3b\x28\xba\x70\xf1\x32\xca\xb7\xf3\x0b\x7f\x6d\x24\x86\x5f\x96\xa8\x06\x69\xb0\x1b\xa3\xc9\x55\xf8\x46\x82\x1b\x35\xc6\xb1\x4f\x8a\x23\xcb\x74\x28\xa9\x37\x7a\xdd\x6a\xda\x86\x5d\x3d\xa5\x9b\x50\x08\x02\x8f\xa5\xbd\x3b\x5f\x47\x5a\xe7\x53\x0f\x55\x5f\x72\x26\x9e\x6b\x74\xb6\x68\x0e\x3d\xd5\xa0\xa0\xb1\x6a\x78\xeb\x4b\xcb\x9d\xe7\x8b\x96\x4b\x78\x29\x2c\x06\x21\x80\xb4\x93\x5e\xf0\xdc\x8f\x2e\xd9\x02\x71\xd3\x33\xb6\xbc\x9f\x55\x8c\xe3\x58\xf6\x1c\xc4\x3d\x12\x03\x8d\xa1\x99\x04\xd8\x1c\xd9\xa5\xed\xee\x1a\x21\x6c\xa3\x4d\xb6\x9c\xc0\x19\x7b\x1e\x78\x73\xe6\xdc\x00\xcc\x11\xcb\xfa\xd2\xcc\xbe\xa0\xf9\x3f\x64\xb1\xe4\xf8\xc1\x1f\x08\xf9\xdf\x40\x4c\xe7\xb2\x8f\x16\x4b\xac\xa0\x41\xb8\x9a\xee\x6a\x4f\x71\xef\xd2\x5b\x7e\xa0\xbf\xda\xe9\x40\xaa\x8e\xfd\xcd\x62\xeb\xf7\x1c\x0b\xf7\x2f\x44\x53\x53\xf6\xaf\x83\xea\x9f\x2f\xd9\x3d\xf7\xea\x4b\x86\x81\x4d\x04\xfb\x27\xdc\xa8\x09\x79\xbc\xec\xd6\x30\x80\x1c\x60\x36\x4a\xba\x9f\x05\x2d\x7e\xc1\x3e\x96\xb6\x2f\xed\x75\x31\x34\x85\x38\x55\xc9\xa5\x9c\xd7\x02\x49\xba\x0c\x8e\x41\x85\xb0\xca\x42\x88\xb0\x9b\xce\x75\xc2\xb6\x30\x76\x7d\x2c\xda\x26\xf7\xbd\xc8\x22\x61\xaa\x06\x77\xc1\xf3\x26\xdd\x42\xab\x00\xe2\x0b\xa1\xba\xdc\x45\xe4\xb1\x71\xce\x12\x01\xe1\xfc\x70\xcd\xa3\x83\xcf\xae\xdd\x86\x37\x58\x87\x37\x02\x5b\xdf\x42\x42\x98\xb2\xf9\x60\x73\x7a\xb7\x35\xaf\xad\x63\xff\xd5\xde\x19\x22\x62\x46\x94\x7b\x2e\xfa\x94\x75\xb9\x26\xc4\x91\x1d\x8e\x5b\x41\x88\xbd\x43\xa5\xbb\x5b\xf3\x2b\xb8\xe3\xbe\x79\x25\x2c\x7f\x71\xea\xd5\x5d\x43\x62\x23\x0d\xed\x74\xb5\xf3\x94\x3a\x06\x9d\x88\x14\x06\xec\x06\xd1\x68\xbf\x39\xa8\x31\x1c\x64\x38\x05\x11\x7a\x93\x6e\x32\xf4\x6f\xeb\x27\xa6\xe7\xc3\x94\xf5\x57\xe7\xdc\xc8\xd6\xd7\x86\x09\xdb\xc6\x8c\x9d\x6d\xe5\x8e\xcf\x87\xf5\x62\xb7\xeb\xc2\x41\xac\x6d\xc7\xe9\x9e\x18\x9b\xcc\xcc\x51\x89\xad\xc7\xa1\xfe\x3d\x1d\xdd\xa7\x35\x36\x14\x89\xf6\x5f\x54\xed\xbf\xaa\x35\x31\x96\x7b\x1e\x6d\x6f\x9b\xc5\x9b\xcd\x9b\xf4\xd7\x7c\xd7\x54\xd7\xb9\x9c\xb2\xe2\x64\xc9\xe4\xca\x0c\xcb\xbf\x4b\x3b\xc1\x40\xa0\x75\xfb\x62\x2f\x25\x82\x05\xdc\x50\x0e\xe7\x56\x5f\xe5\xd2\xbf\x05\x9f\xa2\xb5\x39\x28\x4b\x5f\x57\xe9\x5d\x62\xa0\x66\xa8\x7a\x40\xc5\x78\xc1\x73\x06\x37\xc5\xa3\xe4\xe3\x95\xa6\x55\x4a\x3a\xe4\xd3\xeb\x0e\xf9\x4c\x22\x45\x83\x44\x12\xe9\xc4\xf2\xc5\x46\x1d\x31\xbd\xd2\x30\xaa\xe6\x29\xfe\xa2\xfa\x78\x0c\x49\x50\x27\x96\x1d\xa4\x28\xee\x79\x9d\xa1\x57\x6a\xea\xc1\xa5\x94\xf6\xd1\xa9\x02\x29\xb6\xd2\xc5\xa2\xe5\x31\x70\x99\x0d\xb0\xc2\x28\xb4\x7c\x15\x8f\x12\xbe\xbe\x24\xa6\x72\x48\x6c\x12\xb8\xd5\xe0\x8f\x4f\x53\xd6\x72\x85\x1f\xc3\x7d\x95\xf7\x70\xbe\xe7\xda\x0d\x38\x5a\x18\xd7\x74\x1c\xd9\x68\x1d\xc6\x8a\x9b\x2b\xe0\xcc\xab\x1b\x62\xef\x62\xa3\x7f\x72\x9f\x63\xab\x91\x1c\xad\xff\xb0\x12\x5a\x5a\x46\xe6\xd3\x7a\xc7\xb4\xd9\xd7\xcc\xab\x8d\x65\x73\x5f\x27\x96\x56\x39\x15\x02\x1c\xe7\xa1\xde\x8d\xd7\xd4\xb1\xed\x13\xec\x85\x18\xd2\xf2\x0a\x18\x01\xf9\xf6\x27\xfb\xbe\x5e\x98\x7c\x6f\x65\xb0\xc8\xcc\x53\x03\xd0\x41\xd9\xc7\x40\x7c\xb5\xb3\x6f\x86\x98\xa5\xb2\x7c\x3f\xc7\x73\x51\x20\xf1\xf6\xb8\x6f\xba\x63\x20\x12\x10\x4a\xa2\xca\x56\x40\x5c\xe2\xf9\x37\x07\xca\xe3\x6d\x99\xd0\x7e\xf6\xf7\x40\x50\xe7\x27\xdc\xa7\x6b\x79\xe8\xa7\xcf\x39\x3f\x6c\x4f\xee\xfb\xb8\x2e\x66\x1d\xe5\x8f\xb6\x19\xef\xd3\xc7\xd7\x79\xed\x2d\xd8\x6e\xb0\x43\x2d\xe7\x83\xff\xee\x2e\x92\x1d\x51\x0c\x1c\x77\xb5\x78\x55\xec\x39\x0a\x9d\xa6\x84\xc9\x63\xe1\xa4\x2b\x37\x19\x2f\x2a\x5e\x95\xd1\xd3\xca\x79\x6d\x73\x42\x1c\x68\x8d\x81\xb5\x38\x55\xca\xb7\x25\x34\xaf\x6d\x55\xaf\x56\x44\x48\xa7\xd9\x87\x08\x34\xb0\xdf\x7c\x1d\x9e\xdd\x1c\x89\x8b\x8e\xc8\xda\x86\x4b\x4f\x33\x44\x6c\x53\x3b\x70\xf7\x52\x4c\x84\x36\x92\x1b\x2b\x65\xd8\xb1\xc1\x5d\x9c\x0d\x2c\x82\x09\xfc\x74\x24\xcc\x11\xfd\x7a\x29\x95\x0b\xeb\x3a\x38\x14\x38\x21\x91\xed\x5b\xc6\x3f\xa6\xa3\xb5\xe3\x8a\x18\x54\xd5\x20\xa7\x0a\x1c\x6c\xce\x81\x68\xce\xad\xfa\x0a\xe6\xa9\xc6\x30\xfd\xab\x5d\xa9\xee\xf9\xd7\x5e\x2a\xd2\xb4\x4b\x3c\x55\x13\x2c\xb5\xe0\x1f\x32\xe6\x1b\xa0\x89\x3c\xd9\xc9\x68\xde\x26\x56\x33\x89\x76\xf6\x5d\xa3\x0f\x8d\x48\x3c\x9c\x8d\xa4\x0f\x83\xd7\x06\x6a\xab\xb1\x19\x3f\x63\x7f\x91\x5b\xae\xac\x57\xed\x47\xe5\xeb\x2b\x3c\x5b\x0c\x91\x45\x5b\x1b\xab\x8e\xad\x66\xad\xce\x6e\xe7\x8e\x3d\xe6\x46\xb3\x4d\x5f\xa6\x90\x55\xbe\xb5\xe7\xae\x2f\x5e\xb0\xc6\x57\xfb\xef\xe7\xde\xe6\x01\xcb\x11\x10\x6d\xec\xe7\x75\x45\xfe\xa6\xc4\xaf\xb8\xfc\xee\xbc\x2f\x8b\xdd\x56\x0b\x6a\x9c\x68\xa5\xe3\xd7\x4e\x16\x5a\x5b\x47\xfd\x38\xea\x6a\x51\x4f\xc0\x09\xfa\x2a\x64\xf4\x1a\x24\xc2\x4f\x10\x13\x1f\x47\x03\x83\x5d\x3c\x53\x9b\x19\x3f\x6a\xbd\xa5\xcf\x7a\xcf\xdd\xe7\xa9\xa0\x0f\x50\x7f\x5c\x13\xef\xd2\xdf\x21\x17\xc8\x2b\xef\xc0\x51\xa3\x94\x8e\x66\xbc\xf7\x96\x0a\xea\x68\x78\x2e\xba\x82\xb0\x90\x1a\x3c\xfb\xfb\x31\x55\x69\x8a\x44\x7e\x66\xcc\x8b\xd1\x63\x1f\xf7\x96\x22\xd9\x63\xee\x2c\x46\x09\x3a\xe0\x89\xaa\x3f\x8a\x43\x5f\x54\xb0\x4e\x54\x04\xe6\x7b\x41\x75\xd0\x21\x5a\x12\x3d\x2e\x89\x52\x04\x0d\x24\x35\x34\xcf\x44\x18\x0a\x0c\xd3\xae\x04\x3d\xc3\x4f\x25\x0b\x52\x2b\xf7\x09\x19\xb3\x89\x02\xcc\x8c\x45\x1e\x04\x3d\xb8\xe5\x37\x4c\x80\x05\xc8\x35\x62\x36\x8f\xd3\x29\x29\x9f\x11\xb3\xb7\x90\x4b\x88\x09\xce\xe3\xd2\x4b\xa7\x4c\x8a\x37\x9a\x86\x95\x49\xf9\xf1\x0e\x2d\xfd\x61\xee\xa2\x5d\x6c\xbf\xc5\x9f\x6d\xdc\x64\xa7\x65\xf5\x18\x8b\xc9\x1f\xa6\x0d\xab\x91\x54\x5a\x95\xfa\x72\xc8\xee\x1b\x90\xd6\x35\x1e\xae\xbb\x6e\x8f\xca\x35\x27\xcd\x34\xb2\x67\x75\xa2\x3f\x2e\x0b\xb8\x88\xf9\x32\x3f\x26\x0e\x86\xbe\x5c\xa8\xba\x36\xf7\x38\xc4\x2f\xe7\xec\x1e\x55\xae\xc3\x5f\x2e\x0f\x2b\xd6\x35\x08\x1e\x07\xce\xe6\x81\x6b\x46\x4e\xd5\x55\x11\x72\x15\x23\xf4\xcc\x52\x1b\x9b\x3c\xee\xf9\xe3\x46\x8c\xa1\x37\xcc\x56\x65\xd2\x56\xab\x39\xb3\xea\x4d\x43\xd5\x3e\x97\x06\xa6\x50\xbb\xd5\x24\x1c\xe2\x50\xec\xc9\x9d\x92\x83\x42\xd4\xa6\xea\x6d\x7e\xba\x90\xeb\xcb\xea\x52\xe6\x8b\x36\x41\x01\x8c\x1d\x02\x0a\xa8\xd8\x45\xc9\x28\x29\xf2\xe6\x32\xa6\xd8\x74\x70\x86\x63\x40\xe4\xd0\xe0\x69\x2a\x9e\x59\xce\xcd\xf6\xbd\xac\x61\x49\xf1\x94\x7f\x74\xc1\x20\x49\xb6\xc9\xf0\xe7\xae\xf0\xa8\xed\xcb\xfa\x38\xff\xb6\xb8\xe1\x5f\x17\x01\x60\xd9\x8b\xf0\x17\x3c\x1e\x03\x53\x8d\x40\x7e\xaa\xc8\x40\x70\xea\xbe\x31\x07\x44\xd7\xfc\x14\x2f\xe7\x36\x42\xbd\x6d\x82\xbd\x13\xab\x05\xc3\x2a\x5f\xe8\x80\xd0\x0f\xac\x9d\x36\xeb\x3f\x6f\x5c\x95\x5f\xed\xe2\x4c\x38\xee\xc0\xfc\x6a\x5f\x42\xf8\xd5\x64\xd0\x3d\xa3\x96\x6f\xf5\x95\xbc\x03\x91\x4f\x9a\x62\xb1\x6b\x78\x80\x46\x58\x36\xbc\x02\xac\x65\x52\x02\xa4\x3c\xf5\xf5\x28\x7d\x27\x14\x1b\x46\x9f\xdc\xd2\x26\x4e\x5f\x3b\x40\x6d\x98\xb7\x0d\xea\x2b\xd7\x26\x3b\x3d\xcd\x39\xf8\x5b\xb0\x77\xdc\x68\xd9\xf9\xa2\x0e\xe4\x87\xa3\x8e\xe7\x96\xbd\x85\xc5\xc7\xb0\x8f\x23\x0f\x92\xd2\x40\x0a\x45\x9b\x25\xc8\x2d\xc8\xa7\x9a\xda\x6d\x02\x8f\x37\xe5\x36\x69\xa0\xf7\x14\x79\x79\xe6\x8f\xf2\xc5\x2d\x53\xee\x8d\xd8\x4e\xbe\xb7\xd2\x8a\x77\xf4\xfc\xe7\xfa\xb6\x64\xe9\xbf\x90\x94\xc1\x76\x08\xf9\x0b\xdc\x40\x7e\x0f\x52\x4f\xf9\xf0\x81\xf4\xc2\x27\x62\x33\x2c\x9d\xe7\xd1\x75\x83\xd2\xd5\x74\x49\x87\x7a\x90\x1f\x82\xa6\x41\x3d\x45\x5d\xe6\xfc\xc9\x25\x10\x7e\x2f\x0e\x9f\x58\xdf\xdf\x2e\x5c\x62\x07\x22\x1c\x9d\x86\xdf\xe6\xe7\xda\xac\xe4\x2c\x6b\x4e\x13\xfd\x83\x6b\x31\x90\x38\x4a\x81\x49\x2b\x25\x68\xcf\xd7\x30\x24\x69\xd5\x2d\x37\xe8\xfd\x21\x8d\xac\x85\x7e\x10\x6b\x16\x0a\xbf\xa7\xd7\x18\x2f\x4b\xea\x9a\x07\x81\xb2\x7a\x89\xb3\x2e\x41\x44\x08\x78\x90\x48\x59\x8a\xbe\xee\xe7\x7d\xfe\x4a\x94\x2e\xb0\xda\xae\x82\xde\x92\xda\xd5\x7c\xce\xfb\xe0\x1d\xf0\xbc\xd1\xf4\x24\x42\x16\x38\x36\x94\xb4\xe8\xca\xe2\xce\x79\x69\x60\xba\x1a\xe9\x8f\x43\x30\x6c\xb1\xf6\x7d\xa9\xc7\xfd\xcf\x66\x50\x66\x27\xf2\x11\x2c\x24\x92\x25\xe2\x43\x64\x16\x4e\x31\xcc\xe0\x8b\x32\xe8\x01\x54\xcd\x24\x28\x28\x65\xd9\x1e\xab\xd8\xc8\xc1\x9b\x1e\x1d\xed\x75\x46\x4e\x27\xd0\x73\x7f\x84\x6d\x7c\xd2\xb1\x38\xa7\x19\xd2\xb3\xc7\x22\xf1\x4a\x7a\xd3\xf1\x5e\x0b\x8f\x05\x97\x2f\xf9\x65\xa1\x55\xff\x06\xd9\x51\x38\xa4\xc1\xad\x99\x10\x72\x15\xc0\x71\xcf\x19\x40\xd7\x0b\x8e\x29\x88\x1b\x04\x93\x9a\xd5\x33\x57\x09\x89\x79\xad\xce\x90\xb8\x30\x95\xbb\x6f\x1b\x35\x82\x58\x53\x65\xa2\x18\x83\xa5\xcd\xf4\x39\xba\x74\x64\xba\x4e\xf8\xac\x55\x5d\x65\x9a\xd8\xe5\xf8\xd4\x76\x0a\x8b\x85\xa1\xc3\x34\x39\xa0\xd4\xc0\x31\x26\xed\xeb\xfc\xf3\x98\x2c\x2c\xd9\x3a\x88\x79\x99\x5d\x0a\xdd\x44\x1d\x36\x8c\x4b\xc8\xb7\x22\x47\xf8\xad\xf5\xac\xa7\x35\xcb\x21\x2e\xae\x5f\x5b\x08\x40\x84\x97\x10\xfa\xdb\xde\xf8\x75\xf7\xdc\x39\xfb\xab\x9e\xed\x29\xf3\x99\x8b\xf5\x42\x9c\x7b\xd1\x2a\x7b\x6b\x3b\xcc\x8f\x45\x28\xe9\x75\x1f\x37\x96\xbc\x59\xeb\x11\x09\x42\xf4\xb6\xa7\x73\x7d\x17\x69\xe3\x97\xc5\x62\x15\x6d\xa1\x97\x8c\x10\xfa\x11\xce\x56\x52\xb5\x1f\x06\x03\x96\x09\x87\x5f\xe3\x66\x0d\x53\x59\xdb\x25\xcc\x2a\x7d\x44\xdf\x7c\xb4\x15\xac\x2e\x08\xc3\xa7\x9f\xc0\x57\xca\x9c\xa5\xf2\x83\x6a\x36\x30\xdb\x14\x0e\xea\xdb\x47\x39\x24\x1d\x0c\x0a\x18\x80\xcb\xa3\xc7\x54\xbe\x33\x7f\xa1\xb0\x4c\xce\x8d\xb3\xf9\x6f\x51\x00\x2a\x46\x8d\x7f\xfd\xae\x91\xdf\x34\xab\xc5\xc2\x33\xab\x05\xc7\x82\x16\x3a\x02\xa6\xc0\xb1\xd5\xd9\x59\x04\x0e\xa1\x0c\x2a\x23\xba\x61\x39\x37\xa7\xb5\x1c\x89\x6b\x49\xa0\x65\x1c\x81\x83\x96\x1c\xed\x7c\xee\x62\xa9\x0b\xc1\xdb\x2b\xa7\xc4\x00\x12\x0d\x1d\x82\xb1\x31\x99\xd0\x4a\x54\x01\x95\xd4\xce\x0d\x82\xb7\x7f\x0c\x9a\xc5\xc8\xc8\x9a\xfd\x79\xcc\xc6\x01\xd2\x99\x38\x40\x16\x93\x4b\x6e\x00\xce\x59\x27\xa2\xc1\x8d\xff\x2e\x3b\x20\xba\xe2\x1c\x4c\x68\x42\xac\xa1\x27\x69\x2f\x90\x3a\x8b\x4c\x34\x8a\x4f\xd9\xfa\x76\xe2\x6f\xf5\x32\x13\xfd\xa1\x6d\x67\xa7\x5d\x55\x45\x4f\x4f\xc5\xed\x64\x4d\xc4\x9f\x06\x87\x25\x2d\xe5\xc1\xc1\xb5\x7c\x29\x1a\xe9\xc1\xd5\x2c\xc3\xb5\x87\x40\xff\x81\xb8\x25\x9b\x46\x08\xd0\x7e\x2e\x3c\x8e\x9b\x82\xd1\x19\xa0\x7d\x99\x7b\xb7\x6c\xcc\xae\x96\xb0\xcb\x98\xc5\x77\xe8\x89\xe6\x53\xd9\x66\x89\xb0\x3b\x43\x04\x35\xaf\x38\xcc\x92\x26\xe3\xae\x55\x38\x07\xef\xcd\xc1\xa3\x5e\xaa\x70\x4f\x94\x11\xf9\x3e\x4f\xd6\x97\xdf\xba\x3d\xba\xe2\xaf\xab\xe7\x0e\x6f\x24\x9f\xde\x20\x2f\xeb\xbf\x9c\x9a\x0d\xea\x08\x9e\x4f\xe2\xad\x12\x5f\xfd\x58\xa2\xf2\xcd\x81\xe2\xdb\x76\xdc\xfc\x6d\x7d\xe5\xea\xb9\xa8\x91\xcb\xd7\x1b\x9a\xc2\x77\xcb\xda\x16\x7d\xef\xde\x1d\xd4\x83\x39\x50\x66\x92\x8b\x21\x9f\x14\x2e\x3a\x9d\xcf\x6c\xff\x84\x93\x5f\xa5\xd3\x32\xc7\x55\x41\x8e\x03\x9e\xf4\xf9\xff\x89\x3e\x5b\xe6\xf1\xec\xa6\x45\xa7\xc6\x27\xce\x0f\xc8\x36\xd4\x24\xdd\x65\xd1\x1f\xee\x06\x54\x5d\xd9\xa9\xfe\xa0\x18\x2f\x39\x9f\x43\x41\x2d\xfe\xac\xda\x65\x66\x15\x2d\x40\xd0\xc8\x6d\x73\x3f\x54\xa6\x6e\xdd\x95\xe2\x8c\x88\x02\xc4\x1a\xb5\x44\x3e\xa0\xf2\x67\xbb\x0d\x76\x2d\x4d\xdc\x61\x3d\xd0\xc7\xa1\xe2\x1c\x07\xaf\xe2\x10\x10\x60\xfe\x7d\x65\xbe\x27\x5b\xd6\x74\xc9\x2c\x47\xc8\x27\xdc\x6f\x6f\xab\xb7\xea\x9a\xf6\x0e\x90\xa0\xa5\x9b\x84\xc6\x79\x7b\x36\x03\x1a\x83\xa4\xcd\xe8\x9d\x64\x54\x29\x29\xcf\x81\xe3\x0c\xbb\xb3\xd8\x51\x2c\xce\x20\x3f\xff\x3a\x58\x9c\x41\x7a\x79\x42\x2c\xc9\x72\x87\x83\xe7\xa1\xfd\x1d\x79\xdd\xc2\x08\x4d\x08\x06\xc6\xa2\xee\xb6\xe2\x4e\xd1\x1f\xe4\x6b\x6e\x28\x7b\xe8\x71\x29\xb1\x5e\x56\xec\xb5\x82\xef\x40\x69\x0a\xd0\x82\xda\x43\xcd\xbd\x3f\x37\x25\x43\x18\x34\x0f\xba\x46\xe4\x6a\x0b\x2d\x79\x44\x5c\x3d\xd5\xc8\x62\xc3\xe6\x03\xec\xbe\x15\x25\x67\x11\x26\xd3\x0b\xaa\x48\x35\x89\x3b\xc0\xc4\x43\xd9\x48\xb4\x7f\x2f\x8b\xb6\x7d\xbe\x0b\x85\x2e\x57\x0a\x41\xb4\xe8\x1a\x86\x01\x7d\xf1\xcf\x16\x7d\xbd\x78\x77\x44\xf7\x98\x34\x8b\x48\x2e\xb5\x42\xfa\x8d\xdd\x07\x03\xaf\xe8\xab\xf5\x03\xd1\x2b\x6d\x46\xf2\x3d\xa2\x91\xa4\x56\x38\x87\xd3\x41\x8c\x65\x87\xce\x9a\x41\x17\x73\x8c\xf1\x27\x9e\xab\x6f\xd0\xee\x55\x96\x7a\xdd\x9a\x2e\x52\x54\x5c\x67\x80\x95\x84\xeb\xd6\x7c\xc5\xc0\xa5\xef\x6d\x76\xb6\x2e\xa7\x4a\x54\xb9\x9b\x0e\xa3\xfa\xb5\x52\xe8\x4d\xda\xa3\xa6\x60\x97\xac\x9f\x48\x26\x9a\xa5\x95\xd6\xea\xdf\xca\x2a\x9a\x2d\xb2\xe2\xb2\x1c\x79\x6a\x5e\xaf\x48\x20\xb1\xc5\x26\x62\x9e\xa1\x9b\x69\x56\xca\xd8\x5b\xba\xfb\xc5\x4f\x73\x98\x1a\x7f\x7e\x7f\xd7\xcc\x71\x58\x20\x7c\xea\x09\x14\x25\x60\xb7\xe0\x5e\x3a\x2c\xcf\x1d\x74\x45\x65\x24\xeb\xc1\x9b\x81\xc3\x77\x53\xa3\xa6\x19\xd4\x2c\xbc\x21\xbc\x6c\x1f\x91\xac\x9e\x4e\xfd\x3a\x2f\x5d\xea\xca\xfb\x16\xfc\x6a\x78\x8f\xc4\xb2\x28\x59\xda\x61\x74\x24\xb5\x79\xd3\x79\x61\xcf\xca\x76\x85\xcf\x27\x3d\x17\x1b\xcf\xe7\xbe\xed\x29\x44\x92\x85\xa5\xdf\x46\xc6\x16\xe0\x03\x63\xe6\x96\x49\xad\x71\x47\x0e\x8f\xfd\x5b\x93\xe3\x61\x37\x5d\x5c\x02\x4c\xf7\x47\x29\x62\xa9\xd3\xb7\xb7\x9b\x0f\x14\x23\x14\xdd\x5e\x71\xbd\xf6\xd2\xfe\x4a\x5c\xae\x05\xec\xbd\x12\xf5\xed\xad\xf6\x40\x8c\x1a\xe0\xb8\xec\xe5\xd9\xa3\x71\x54\x1a\x3f\xd1\x9c\x53\xb5\x20\x45\x9a\xd1\xd3\xaa\xf8\xdc\xb2\x68\xef\x99\xd1\x07\xc9\xb3\x38\xd6\xb4\x40\x52\x75\x81\xbf\xe2\xd1\x58\xee\xbf\x16\xdb\xaf\x0b\x33\x8d\x38\x37\xa4\xd7\x5d\x80\xcd\xb4\x39\xe7\x6d\x8a\x30\xc3\xab\xe6\xee\x57\xd7\xbe\xcc\xe7\xee\x37\xe2\x9a\x44\x29\xd5\x9f\x73\x74\x6d\x30\x08\x57\x68\xb3\xd6\x54\xa4\x6c\xa7\x50\xbb\xa9\x89\x05\x59\x40\x76\xd4\xed\x78\x83\x1d\x5b\x91\x5b\xce\x58\xd9\x0c\x96\x9a\xa3\xe1\x95\x0f\xcb\xbb\x50\x80\x3d\xb2\x91\x6c\x8f\x8c\x80\x04\x43\xf9\x9d\xd6\xed\x51\x92\x8d\x4d\x52\xf1\xd9\xc7\xce\x8a\xe4\x6e\xd8\xb2\xa9\xd0\xcc\xb1\x9d\x64\x0d\x47\x9e\x70\x6c\x14\x44\xcc\x58\x6d\xc7\xf2\x95\x7e\x4f\xc1\xeb\xe1\x26\x9f\x17\x1d\xdf\xca\x7c\x3c\x6f\xa1\xdb\x40\x52\x44\x7e\xae\x51\x10\x06\x47\x79\x08\xd2\x39\x41\x47\x30\x9c\x57\xd5\x97\xe4\xbe\xbd\x33\x9b\x5b\x46\x33\xc3\xce\xee\xdc\xb1\xb2\x96\x5f\x6b\xc0\xfc\xd1\x47\xb2\x3d\xae\xf4\xa2\x89\x47\x18\x8e\xb7\x2e\xae\x85\xed\xca\x61\x24\x55\x1f\x4f\xc7\x8e\x97\xd3\xcf\xd9\xfe\x83\xab\x6f\x9a\xcc\x89\x94\xd5\xe6\x6c\xb7\xdf\xda\xc7\x29\xb6\x52\x41\x93\x94\xb0\x87\x15\x44\x68\xd0\x14\xc1\x2b\xbe\xe3\x77\xbd\xa1\xf0\x07\xcf\xac\x55\x79\x8c\xa0\x01\x4a\x3b\x1c\x7d\x3e\x61\x55\x01\xf1\x3b\x1e\x2f\x4e\x27\xe9\x32\xef\xef\xc0\xdc\x09\x4e\x4d\xdc\x81\x23\x27\x6e\xf5\xf1\x6a\x27\xe0\x07\xe2\x75\xee\xf7\xc0\x9c\xd5\x20\xf4\x95\xe0\xb0\x17\x0b\xe6\x89\x32\xa6\xec\xdb\x14\x72\x98\xba\x20\xae\xb4\x2f\x5e\x27\x14\x6d\x36\x82\xe9\x0b\xc9\x04\x2b\xc6\xc7\xbc\xc0\xdb\x41\x78\x1c\x2f\xd1\x0f\xbb\x0f\xef\x2d\x03\xf2\x3f\x6d\xb5\x17\xf0\x4f\x67\xd7\x1d\x0d\xb5\x95\xc1\xef\x9c\xd3\x33\xff\x5e\xcd\xb5\x9d\xf3\x9c\x9c\x83\x4a\xb5\x05\x23\x5e\x5e\xc1\xeb\x45\xeb\x81\x9a\x9f\xf9\x58\x60\xa4\x4b\xc9\x5f\xd2\xae\xc9\xe7\xd3\x0c\x58\x02\x11\x14\x12\x50\xd8\x02\xe9\x70\x22\xf6\x89\xc1\xe3\xd5\xd6\x9c\x5e\xa2\x82\x8e\x82\x71\xe5\xa2\x38\x45\xc5\x2f\x09\x96\xb4\x09\xaa\xd7\x50\x94\x6d\x71\x92\x8f\x45\x2b\xea\x02\x2e\x12\x94\xcf\x42\x71\xfa\x60\xc8\xc4\x2f\xaa\xe2\xb8\x98\x14\xbb\x85\xd0\x22\x84\xe1\x0e\x45\xac\x0a\x99\x59\x41\xff\xf7\x40\xde\xf8\x91\x60\xd4\xdc\x3c\x0c\xca\xd1\x80\xc1\xe9\xe6\xd3\x69\xe8\xe8\xc9\xe2\x10\x3e\x81\x8f\x04\xda\x59\x5d\xa8\xf4\x3c\xa6\x4f\x30\xb2\x62\xd6\x4c\x3b\xc8\x3e\x77\x9b\x20\x36\x86\xbd\x9a\xdd\x16\xd0\x21\x50\x19\x83\x7c\x27\x2c\xda\x13\x69\xd4\xe5\x9a\x84\xb3\x11\x2b\x1c\x9a\x47\xce\x65\x10\x85\x02\x31\x03\x6d\xea\xe3\x44\x61\x24\xee\x63\x10\x84\xd8\x0e\x88\xf8\x76\x4f\x79\x0d\x1c\xa2\x23\xea\xcf\x7d\x95\x3f\xad\xef\x3d\x5e\x5f\x49\x7b\xcd\x8e\x37\x0f\x9e\x5b\xc4\x01\xcc\x28\x99\x5a\x05\xa6\x01\x31\xd0\x69\xaf\xe1\x95\xf1\x62\xa8\x33\xa1\xee\xed\xc1\x62\x5c\x51\x74\x36\x0a\xa6\xec\x93\x40\xbd\xc5\x58\x74\xe6\x6f\x37\x20\x68\xeb\xbb\x80\xdb\x31\xd9\x60\xac\xca\xaf\x68\xc8\x1b\xc4\xfb\x7f\x32\x1a\xa1\xe4\xe2\xff\x38\xbf\xf8\x6c\x1b\x76\x41\x1c\x31\x6e\x40\xc5\xf4\x91\xf1\x2e\x80\xb0\x7b\x17\x14\x33\xb8\x3d\x44\x9d\x56\x83\x5d\xe5\xd9\x5e\x8d\x22\x6a\x74\xb8\xd9\x4b\x90\xc6\x81\x06\x61\x67\x51\x4f\x06\x6e\x8e\xdd\x3d\xea\x8c\xa1\xe0\x3b\x6c\x22\x58\xf3\x17\x59\x7c\xd9\x54\xa8\x51\xaa\xed\xf1\xe2\x8f\x99\x27\xf0\x3b\x75\xde\x1d\x4b\xaa\xbc\x85\x40\x31\x9f\x03\x44\x75\xcb\x49\xb3\xc8\x0c\x06\xee\xe6\xce\x8d\xd0\xe0\xfd\x6e\xc6\x08\x4f\x16\x7a\x80\x61\xe0\x19\x8e\x96\x99\x1e\xc8\x09\x6b\xef\xce\x01\xac\x68\xa1\x40\x7b\x05\x6b\x11\x50\xd9\x34\x44\x93\xa5\x77\x92\xe4\xf0\xf1\xb8\xe5\x5d\xc9\xb7\xd6\x96\xf9\x02\xf4\xd4\xdd\xd9\x3d\xee\x1d\x82\xf7\xf5\xa9\xb8\x9b\x87\xc2\xc2\x33\x1e\xc6\xec\x5b\x36\xc6\x72\x96\x0d\x6d\xe4\x05\x26\x85\xff\x8f\x21\x43\x43\x15\x2b\x3c\x9d\x32\x57\x4e\xa4\x9e\xfa\xe8\x3f\x74\x74\x6d\xbf\x2d\x53\x6c\x9f\xc0\xc7\x9a\xe0\x19\xf3\xa0\x32\x2b\x82\x79\xbb\x54\xa2\xc6\x2e\x63\xbe\xdd\x3f\x6e\x8c\x6c\xbb\x7f\x2f\x63\x8d\x4f\x6c\x05\xf0\xb6\x1c\xd7\x0d\x02\x21\xa2\x9f\xa7\x2a\xc0\x4c\xdc\xe3\x0c\x98\x03\xf9\x05\x91\x80\x3b\x01\x60\x49\xea\xf6\xab\x7f\x91\xb9\x07\xad\xa9\x26\x40\xcc\x58\x1c\xe3\x2c\xfd\x08\xe4\xe3\xe1\xfa\x0a\x23\xc7\xfa\xa0\x41\x55\x4c\xd4\x30\xde\x66\xd9\x98\x3e\x02\x0d\x47\xf9\x38\x44\x43\x28\x27\x9c\xa8\xc5\x72\x85\x60\xdc\xad\x61\x1d\xcb\x9b\x1d\x0a\xec\x96\xa0\xff\xa6\xc3\xe3\x15\x4a\xdc\x5d\x0a\x5d\x84\xaa\x73\x81\xce\x74\x92\x4f\x67\x71\x9e\xd5\x2c\x70\x2a\xa7\xa8\x63\xef\xd1\x59\xb6\x6d\x82\xa6\x91\xa1\x42\x0d\x51\x15\xf2\x5f\x79\x89\x8a\xe2\x87\xa1\x9a\x21\xa6\x71\x52\x47\xf8\x51\x12\x2a\x3a\x2d\x81\x0d\xcc\x48\xf9\xbd\x8e\x76\x06\x2b\xa3\x22\xb6\x86\x41\xff\x93\xa1\x93\x90\xa7\x27\x8b\x46\x17\x22\xfe\x7e\x3b\x09\xf8\x9b\x43\x4b\x33\x19\xe2\xeb\xc7\xdb\x5d\x0d\x33\xfc\xc8\x77\xff\x5c\xec\x74\xf8\xb4\xeb\x0f\x79\x31\x8f\x5b\xaa\xb2\x6d\x8a\xa1\x10\x9b\x71\xa5\xf6\x83\x77\xe4\x4a\x12\x0b\x2c\x66\x87\xdb\x8a\x8c\x5b\xbf\xd2\xbc\xb8\x91\x7f\x87\x19\xb8\xfa\xd9\xae\x89\x8c\x83\x38\xa4\xb0\x60\x8f\x85\x1b\x64\x9f\x4a\x8d\x82\xe4\xd4\x08\x5d\xd9\x4b\xc4\x94\x40\x98\x52\x22\x6c\x6f\xfa\xf6\x6d\x95\x63\x51\xb7\x14\x16\xc1\xbc\xec\x9a\x0e\xc8\x10\xf4\x01\x01\xea\x05\x4a\x98\x72\xdf\x5b\x07\x6c\x2c\xbd\x54\x6e\x3a\x23\xe6\x2d\x17\x78\x84\x2a\x99\x52\xcd\xcf\x5d\x5e\x3a\xf4\x23\xfa\xe2\x8c\x8a\x6c\x86\xfb\xf1\xe2\x58\x43\xae\x4b\x05\x00\x39\x87\x35\x84\xb1\xaf\xa1\xb5\x07\x59\xa2\x9e\xd6\xc6\x31\x7d\xd8\x77\xc2\x15\xd9\xc4\x37\x02\x28\xc3\x21\xc7\x2d\xc2\x27\xcd\x89\x50\x01\x48\x5d\x82\x56\x46\x76\x0b\x59\x3a\x4d\x85\xf9\x1e\x1e\x37\xc5\x8d\x1b\xa6\x1f\x28\xa2\x5c\xf5\xf6\xe7\x05\xd9\x96\xa8\x57\x6a\x56\x57\xd1\x0c\xb3\xf9\x03\x37\xf5\xce\xbe\xff\x98\x22\x40\x1d\x1e\xf6\x94\x1d\x05\x77\x57\xf2\x76\x6e\x9e\xab\x6e\xa7\x5e\xa7\xa6\x2b\xd7\x03\xd0\x52\x9d\x4a\x09\xbc\xbd\x47\x5a\x4a\x73\x74\x59\xf7\x82\x61\x2e\x96\x2c\xab\x40\x58\x7e\x3a\xb6\x61\xb2\x05\xb8\x6d\xc5\xb3\xa5\xcf\x5b\x66\xda\xc1\x7b\xa9\xde\x3c\x5a\xe8\xd3\xed\x9d\x43\x77\xf0\x7e\x04\x0a\x3c\xba\x6b\xdd\xdd\x1e\x2c\xb6\x2d\x59\x97\x44\x3f\xe9\x6a\xda\xf8\xb7\xad\xe6\xd3\x9f\x40\x63\x31\x0d\x71\xde\xd6\x53\x37\xe7\x53\xb5\xd8\xda\x79\x77\x11\xba\xdf\x67\x31\xe4\xb4\x39\xb7\x18\x3a\x58\xd7\x93\x4a\x2f\x1a\xb3\x0f\xb4\x9c\xe4\x02\x9b\x4f\x85\xe6\x94\x99\x63\x4c\x28\xcd\x61\xb5\x4b\x5c\xe1\x50\x1f\xe5\x87\x6e\x8b\xf0\xcc\x15\x2a\x4a\x33\x5d\xc3\x80\x8d\x5b\xbc\xbe\x92\xcd\x3b\x51\x2e\x35\x62\xdb\x35\xee\x0d\x78\x9f\xa5\x9a\xeb\x9a\x2b\xdb\x07\x58\xb4\xcd\x2f\x22\x4e\xe4\x0a\xb1\x95\xb6\x4d\x86\xad\x83\x01\x71\x5f\xee\x06\x6c\x6c\x38\x96\x2d\xef\x2f\x32\x52\x5e\x5f\xcb\x91\xa4\xea\x2d\x41\x1e\x64\x59\x43\x23\xf2\xc9\x6b\x94\x71\x95\x75\x3a\xc8\x8f\x1c\xb8\xec\xc2\x55\x0e\x52\x75\x5b\x9f\x7a\x7b\x57\x64\xef\xac\x91\xf4\x0d\x5c\xaf\xe7\x30\x38\xfb\x43\x31\x28\x6e\xbc\x10\xd6\x35\xc7\x36\xfe\x6b\x91\x9d\xd5\xeb\xd6\xd8\xda\x93\xb3\x35\x04\x57\xe4\x51\x4c\x62\xc8\xc5\x20\x94\x74\xfc\xa9\x0a\xec\x90\x6e\xce\xcc\xc8\x18\x64\xfc\xe3\x76\x4d\xe9\xb3\x3e\xb3\xdd\xab\x07\x4e\x7d\x78\xa9\x00\xbc\x09\x38\x25\xec\x10\xed\x80\x98\x30\xde\x70\x2a\x01\xb1\xbd\x2c\x94\x0e\x4c\xf8\xb5\xab\xfd\x5f\x02\xa1\x0f\xaa\xa6\xdc\x9f\x78\xfd\x10\x70\xd4\xbc\x84\x3f\xa4\xd6\x1e\x08\xc7\x74\x5e\xba\xd8\x22\x43\x1a\x85\x93\x05\x96\x87\xd9\x3c\x98\x05\xac\x2a\xac\x43\x26\xa2\x05\x12\x29\x16\x75\x5f\xf7\xaf\x5d\x7e\x04\x77\x01\x7a\x61\xbc\x84\x98\xe2\xde\xbd\xef\x1f\x54\x8c\x89\x43\x3e\x77\xa2\xb5\xb4\xc4\x53\x68\x07\x83\xfd\xf8\xb2\xed\x6c\xa7\x96\x4d\x87\xc4\x3d\xa5\xde\xb7\x58\x7b\xed\x09\x96\x69\x07\x33\xca\x83\x9f\xc4\xa4\x69\xd1\xd0\xd6\x04\x1a\xf2\x86\x7b\x14\xb4\x73\x33\x99\x31\x4e\x1e\x01\x28\xfb\x6f\xc1\xe9\x4b\xc1\xb5\x04\xf5\xda\xdc\x34\xa7\x16\x0d\xc3\xf0\x98\x34\x03\xb2\x62\xa0\x67\x95\x60\x7c\x52\x24\x1d\x66\x74\x1e\x76\x57\x6c\x5a\x57\x77\xdc\xee\x89\x2b\x06\xdb\x3e\x18\xcf\x9c\xb3\xf4\xd6\x51\x30\x07\x50\x5a\x23\xbc\x43\xf6\x0e\xf6\x78\x83\x5d\xa3\xbc\x26\xc8\x4a\xb0\xf8\xe8\x6c\x61\xce\x94\x47\x45\x93\xbb\x78\x07\xab\xd1\x89\x7e\x60\xcc\xfe\x0d\x73\x24\xe1\x65\x69\xc8\xdd\x8c\xfe\x47\x0b\xf0\x60\xd9\xb0\x5c\x5b\xb2\x1e\x9e\xa0\x4a\x45\x00\x02\x99\x53\x6d\xe2\xaa\x3e\x3d\x45\xff\x2e\xb8\xe6\xfa\x6c\x7f\x7a\xa1\xcd\xe7\xbc\x52\x07\x3d\x3a\xc8\xce\x59\x15\xcf\x8b\x80\xe8\x68\x0f\xf0\x48\x9b\x4d\xfb\xe4\x47\x70\x18\xa7\x21\xb7\x83\x41\x04\xdf\x46\x73\x43\x9a\xc5\x0c\x2e\x66\xf5\xed\x93\x83\xc6\x74\xd9\xc4\x35\xea\x38\xfd\x18\x68\xd5\x87\x55\xf9\x9c\x10\xd8\x4e\xbd\xa9\x3f\xfb\x0a\x79\x06\x63\x27\x40\x7e\x13\x14\x43\x9d\x7f\x69\x9c\x59\x53\x5d\xef\x8f\x55\x77\xa1\x9b\x2d\x4f\xb9\x37\x9f\xa0\xf1\x16\x4e\xf3\x59\xea\x70\x0b\x01\xe5\xeb\x66\xeb\x3d\x31\xd1\x6f\xe5\xcc\x73\x30\xe6\xfb\x16\x8e\xf1\x8f\x41\x65\x34\x5a\x58\x03\x1c\xca\x58\x2e\xd1\xbf\xc6\xcc\xbd\x56\x14\x78\x10\x5c\x3a\x9f\x77\xda\x0d\x53\x39\x86\x5f\xfe\x24\x62\xa2\x44\x26\xd0\x95\xa6\x3b\x85\xf7\xa5\x55\x46\xdc\xa0\x3f\x84\x6b\xfd\x89\x29\x3e\xdc\x4b\x27\x44\x61\x6b\xbf\x07\x05\xfe\x88\x5d\x2d\x0f\xa1\x49\xd4\xac\xda\x1c\xa3\x49\xce\x73\x4d\x85\xfe\xf8\x9a\xbd\xfc\xc3\x09\x86\x7b\x13\x6b\xed\x74\x68\xa2\x19\x7d\xef\xe5\x99\xff\x91\x5b\xf7\xd2\x7f\x29\xb5\x7a\x70\x77\x73\x36\xb4\x8d\xbd\xc2\xba\x8d\x85\x62\x3f\x89\xec\x95\xdf\x41\xa1\xc8\xc4\xb1\xf0\x8c\x09\x85\xbe\x2b\x4d\x13\x03\x1c\xbe\xa0\xbb\xd6\xa4\x39\xb6\x87\x4e\x14\xe7\x5f\x8c\x3a\x22\xfe\x34\x5f\x1e\x8e\x22\xe0\xff\xfd\xd5\x19\xf9\xd7\x52\x9a\x95\x8f\xa5\xfb\x44\xdc\x02\xb5\x35\xd7\x85\x05\x88\x9b\x9d\x65\xd5\x72\xba\x44\xd4\x4d\x00\xf1\x88\xd9\x48\xeb\xf7\x63\xb8\x2c\x14\xcf\x7a\xc4\xe2\x79\xbf\x56\x7f\x1d\xcf\x62\x14\x16\xa1\x38\x7b\xe9\xf3\xde\x66\x37\x43\xcd\xcd\x69\x43\x18\xd9\xe5\x1b\x9d\x2b\x44\x66\xf4\xdd\xe9\x8d\x97\x87\x6f\x94\x25\x00\xc7\xa2\xc0\xf1\x6c\xde\x19\x26\xf7\x6a\x0e\x93\xd1\x06\xdd\xa6\xfc\x55\x7a\x5a\x30\x62\x6a\x74\x3f\xe8\x6c\xf5\x8d\x8d\xa1\x72\xae\x14\xde\x56\x23\x10\x66\x9f\x4e\x4a\x6f\xc1\xa6\xc2\xbd\x28\x33\xda\x82\xd5\xb0\x11\x8b\xbf\x11\xf3\xb0\x11\x9b\x1f\x18\x63\x91\xc8\x29\x99\x2e\x1c\xed\x22\x20\x0a\x15\x9b\x62\x10\x63\xed\x8b\x89\x0f\x00\xef\x90\x96\x93\xc0\xe5\xd5\xdb\xb3\x68\x37\xe1\x4a\x48\xe2\x93\x18\xf5\xaf\x92\x24\xc2\x1e\x83\x4d\x61\x53\xae\x72\x1b\xa9\x6b\xb6\xb7\x79\xd8\x3d\x9e\x0e\xfc\x3c\x56\xe2\x4c\xc2\x1f\xf2\x93\xf1\x9a\x7a\x27\x9a\x8f\xe7\xf8\x47\x05\x31\xbe\x61\x36\x30\x1d\xdc\x95\x31\xdd\x58\x44\x09\x08\x1c\x85\x8c\x0a\xa5\xf5\x5f\x88\x4a\x9e\x3e\x89\x64\x8a\xf4\x6b\xed\xa5\xb1\xda\x15\xce\xbb\xaf\x68\x83\x1e\x85\x60\x56\x18\x4f\xb6\xcb\x27\xd5\x3b\x83\x96\x77\xca\xd3\xf4\x7b\x0c\x79\x5e\x43\xf9\x4d\x18\xd6\xe0\x0f\x82\x26\xfc\x4b\xb5\xa7\x93\x29\xd4\xd6\xee\x57\xd1\x80\x2d\x99\xdb\xbe\x06\x55\x34\x64\xe8\xc3\xb9\xdf\xad\xcd\x61\x19\x97\x1d\x4b\x96\x2c\xd5\x8d\xe8\xef\xa5\x10\x3c\x1c\xa7\x05\x65\x48\x76\x99\x27\x30\x67\x3d\x8e\x58\xc8\x3b\x79\x6a\x07\x74\x04\xbe\x4a\x4a\xdf\x18\xcc\x3b\x39\x9d\xc4\xaf\xdb\xa8\x63\xa7\x7f\xc8\x47\xe6\x94\x51\x77\x32\x2c\x44\x08\x4e\x94\x65\x7c\x66\x17\xe9\x4b\x86\x2a\x48\x90\x73\xe0\x8f\x3c\x19\xfc\x11\x0d\x18\x9b\x25\x38\x83\xa5\x01\x11\xa8\xa4\xfb\x51\x32\x14\x73\xe0\x4f\x87\x94\xed\xa8\xe9\x92\x61\x2b\x8d\x9d\x15\x0a\x58\x8b\x9b\x81\x8f\x35\xe1\x3c\x1c\xc7\xaa\x16\x7e\x33\x16\xec\xf2\xaf\x7f\x67\x7a\xb8\x17\x5f\x9f\xb2\xe2\xa0\x32\x42\xef\x75\xfd\xd7\x89\x14\x8a\x73\xf2\x9f\xe8\xcd\xbc\xb8\x04\x6f\x26\xa8\x16\x12\x00\xc9\x68\x50\xe0\x31\x6e\x9b\x69\x8e\x05\xb8\xad\xba\xfb\xfe\xcb\x0f\x60\x46\x9c\x1f\xcb\x2f\xfa\xb2\xbc\xe5\xf4\x6a\x72\xf4\xe8\xad\x5a\x5e\xd1\xba\x84\x72\xe4\x4e\xdf\x96\xf4\xdb\xc4\xf4\xc2\xed\x76\xc8\xac\x10\xcc\x04\x99\xd3\x89\x30\x6c\xf9\x7a\x1c\x4b\x2b\x2f\xfb\x12\x18\xef\xce\xf7\xfe\x1b\x4f\x33\x9b\x5f\x95\x52\x16\x17\x17\x96\x0c\x6f\x4b\x5b\x33\xa7\xae\xe6\x17\x2a\x9f\x50\x8f\x4a\xe0\xd8\x99\x53\xce\x8e\x8d\x79\x2a\xeb\x56\x0e\xb0\x53\xc5\xdc\x81\x87\x73\x79\x32\xc6\x7a\x55\xca\x6d\xf9\xf7\x82\x10\x29\xe4\x79\x1f\x36\x03\x25\x5a\x01\x30\xa6\x4c\x76\x46\xa3\xcb\x83\x9a\x50\x8c\x58\x75\x95\x72\x1b\x60\x2e\x4d\x1e\x7b\xf5\x57\x83\xf0\x13\x12\x2d\x14\xd6\x64\x43\x2c\xe3\xfb\xb7\x6d\xa1\x38\xd8\xa8\x80\x3f\xde\xcb\xb8\xbf\xf8\xfd\x07\xfc\xb8\x86\x6a\x35\x8a\x11\xab\xef\x19\x00\x0e\xf8\x08\xfc\x7f\xac\xc1\x38\x74\xe9\x4b\x6f\x0f\xd4\x9a\x14\x5b\x08\x2b\x13\xac\x5c\x28\x45\xd1\x59\x05\xe2\x96\xba\x5b\x33\xf2\xd1\x7f\xf9\x68\xe3\x53\xf3\x2b\xac\xf6\xc2\x42\xa8\xbe\xe5\x27\x41\x1c\xdd\x99\xbe\x1c\xca\x6c\x46\xd4\x37\xb4\x24\xee\xe3\x72\xc9\xc4\x96\x4e\xe4\x28\x68\x4c\x1d\xa4\x34\x7f\x4c\xd2\xa3\xc3\x8a\x17\x5c\x9a\x54\xe6\x48\xae\xb8\x4a\x3d\x86\x04\x4b\x40\x09\xa4\x06\x6b\x95\x47\x6e\xe2\x34\x5e\x66\x6e\x98\x20\xb3\xa7\x7a\x9c\xdc\x7e\x58\x35\x5c\x78\xb3\x8e\xaa\xfe\xe4\x79\x7c\xbe\x5f\xa1\x85\x8b\x8d\x6e\xc0\x43\xbe\x1c\x8e\xc4\x1d\xc2\x3a\x4f\x75\xba\xec\x44\x5e\x40\xe9\x4f\xde\x8e\xd7\x25\x1e\xc4\x69\x50\x3e\x29\xb1\xa9\xc1\xf5\x78\xf4\x2c\x4e\xb2\x1b\x07\xae\x59\x2e\x9c\xcd\x69\x5a\x20\x3e\x47\x8e\x7c\x5e\x77\x9f\xc3\x11\x90\xb0\x69\x9e\xd7\xe2\xae\x2e\xb0\x99\x8f\xf7\x05\x0c\x2b\xad\x17\xda\xb4\xf4\xf3\x27\x18\x95\xdf\x74\xea\xd5\x68\xa6\x1d\xe6\x79\x77\x99\x17\x6b\xf3\x78\x1a\x9c\xc9\x92\x5b\xbe\xdc\x15\x16\xe3\x89\x75\x68\xe6\x28\x04\xa6\x87\x15\x9e\x2c\xea\x61\x8a\x9c\x10\x86\xfa\x9e\x5f\x3d\x55\x44\x76\x6d\x5b\xee\x46\x93\x7a\x51\x74\xd5\xdc\xed\x2f\x9d\xb7\x8a\xc9\x15\x83\xa4\x96\x2a\x06\x97\xb3\x20\xe3\x73\xc1\xb8\x77\x9f\xe6\xfe\x83\xac\x7d\xff\x63\x54\x1c\x6c\xe6\xc1\xac\x4c\x90\x33\xd1\x2a\x4d\x97\xc3\x1c\xb5\x24\xbc\x26\x46\x06\x02\x3a\xa2\x01\xdb\x91\x65\x70\x96\x54\x9c\xc9\x7c\x20\x91\x5c\x73\x96\x1e\xa5\x18\xa7\x63\xe8\x8e\x4c\xfb\xc2\x9c\x95\x05\x8e\x87\x21\x4f\x74\x5c\x84\xc4\x1f\x05\x30\x37\x96\xc5\xb1\xbf\x2c\xf0\x13\x55\xa2\xf0\xe6\x67\x29\x98\x0b\x1b\x8c\xf5\xe9\x78\xbc\x3f\x5d\xa7\x7e\x05\x28\x23\x51\x4e\xbf\xca\xcf\x5e\x9e\x62\xab\xd3\xa4\xf2\x66\x13\xfd\x4d\xf4\xe6\x6b\x9f\xad\x39\xa1\x29\x3a\x7a\x1a\x78\x6a\x18\x77\xa5\xbe\x60\x1e\x7f\x55\xe9\xce\xaf\x2b\x08\x72\x04\x1b\xe9\x1e\xc8\xab\x9d\x45\x32\xc7\xd5\xfc\xe6\xac\xd0\x0f\x9f\xc7\xa9\xd7\xda\x58\x73\xde\x57\x33\xde\x51\x67\x6d\xcd\x2d\x84\x89\x5b\x3d\xa4\x69\x6a\x6c\xb9\xa4\xbd\xef\xac\x18\x31\x97\x6a\xd0\x7a\xd8\x9f\xc8\x30\x7e\xe3\x69\xee\x3f\x8d\x41\x9f\x79\xf7\x68\xac\x93\x5a\x15\x6a\x26\x7f\x14\x37\xda\x32\xb0\x74\xda\x2a\x67\xe7\xe9\xcf\x13\x33\x7b\xda\x9d\x84\x6d\x36\x29\x95\x1b\xfb\xc8\x32\xb1\x0b\xa6\x31\xe2\x89\xe4\x98\x52\xbf\x7f\x1d\xf8\xb7\x44\x58\x43\xf9\x36\xd3\x04\x08\x71\x4c\xe6\x23\xe2\x16\x7c\x52\x56\xe4\x97\x84\x71\x91\x7a\xca\x52\x89\xe4\x88\x30\xc0\x55\x01\x8a\xeb\x28\xfc\xe2\x96\x6b\xb7\xcc\x31\x40\x22\x5b\xd6\x54\xc8\x10\x0f\x45\x84\x0c\x2b\x95\x4b\x47\x24\x84\xc7\xc7\xe7\x3c\xad\x0b\x8f\x29\x07\xe9\x9d\xc0\x63\x74\xb8\x65\x7c\xbb\xad\x84\xf4\x6e\xff\x44\xcd\xca\x52\xe9\x19\xe5\x7b\x9f\x48\x52\x65\xd5\x89\x2e\xec\x3f\xdc\x6c\x0e\x3c\x38\x1d\x03\xec\x15\x42\x7a\x1b\x1b\x8a\x56\x87\xcf\x59\xe3\x6c\x84\x39\x5c\x25\x3f\xc5\xd4\xd8\x4b\x8b\x58\xf5\xe4\x43\xa2\xc0\x10\xf7\x49\xb0\x8e\x8e\xaf\x97\xf4\x99\x80\xa9\x4c\x41\x57\x8f\x32\x81\x1a\xa2\x3f\x07\xa9\xd1\x94\x40\xc8\xd1\x22\xd4\xd7\xde\x42\xc9\x60\x4a\xde\x65\xfb\x97\xb2\xe5\xc4\xe6\xb8\x27\xfd\xa5\xfe\x04\x61\x24\x97\x8d\xdd\xca\x78\x74\xb3\xff\x5b\xf0\x8b\xca\xb7\xee\x96\x2f\xc5\xf8\x8d\x32\x1b\x86\x90\xff\x8d\xb0\xcf\x5e\xf9\xd8\x57\xd5\xad\xf7\x96\xcf\xd1\x42\xe0\x36\xcf\xbc\x89\x49\x8d\x3f\x5d\x0d\x73\x92\x47\x0a\x39\x1b\xb3\x03\x3b\x62\xfe\x7e\x42\x1e\x96\x06\x0f\xb6\x0f\xca\x1c\x61\x0a\xec\xa7\x19\x9c\x65\x8f\x72\xb5\xf4\x25\x14\x6f\xe9\x1a\x06\xe2\x2a\x03\x36\x76\x92\x60\xf1\xd1\x0d\x55\xa0\xb3\x64\x2a\xb1\x61\x10\xe6\x8f\xa4\x07\x85\x5c\xe7\xd4\xc8\x17\xfc\xc5\xdf\x79\x1e\x69\x46\x5a\x6e\x55\x2f\x0a\xcd\x28\x4e\x6e\x24\x0b\x2e\xcd\x94\x72\xc1\x9c\xb2\xd5\x1a\x45\x4b\xa0\x8d\x50\x30\xfd\x6c\x5b\x33\xa6\xf9\x76\x7d\xb3\xf2\x73\x6f\xf8\x56\x36\xb9\x26\x32\x06\x96\x59\x7e\x02\xab\xea\x08\x6d\xa3\xe2\x67\x0b\xa2\xc4\xe5\x99\xec\x90\x27\xb6\x2d\x9a\xa8\x97\xf2\x2f\x9b\x78\x5d\x2f\x85\x14\xb5\xb1\x25\xbe\xf3\x5b\x95\xc0\x87\x4b\xe4\x26\x4f\xe9\x8d\xd9\xc4\x13\x29\x1d\x78\x01\x0a\x20\x27\x1b\x01\xf9\x89\x88\x26\x9c\x19\x47\x5e\x72\x55\x35\xc1\xba\x24\x75\xeb\xbf\x39\x3e\x7f\xd7\xaa\x20\x77\xb5\x95\x2f\xcc\x1c\x1a\x7c\xc4\xa6\x1c\x55\xff\x0b\xbc\x41\xc3\x23\xea\x8b\x2f\xc4\x32\xf5\xee\xf7\x56\xf9\xe6\x41\xa4\xa0\x29\xa2\xf4\x92\x4c\xe6\x12\x84\xe4\x7b\x9d\xab\x4d\xf8\xbe\xb4\xd1\xf3\x68\xb2\x4c\x14\x64\x28\xe2\x5f\x8d\x05\x7a\xd0\x59\xe3\x09\x10\xc9\x8a\x7d\x6f\x99\x67\xc7\x83\x86\xc2\xfc\x93\x4c\x07\x9b\xcd\x62\xa9\x5f\xac\xa6\x4f\x97\xf1\xd2\x6c\xde\xd4\xff\x72\xad\xae\x22\x9b\x9f\xb5\xa6\x89\x33\x03\xfc\xdf\x9f\x3b\xa8\x93\x7e\x2d\xbc\xf7\x37\xd8\x71\x7e\x97\x1e\x85\x62\x7e\x6d\x5e\xb4\x09\xb2\xc8\x3c\x78\x24\x0a\x14\xaf\x5d\xed\xb0\xb1\x4a\x17\x1e\xd1\xaf\xed\x65\x2c\x32\x95\x5a\xd2\x32\x46\x3d\x86\xcf\xeb\x5c\x15\xf3\xad\x89\xf1\xc7\xde\xb5\x4f\xf2\x8b\x8f\x38\xb9\x27\x0d\x11\x9e\xd4\xc1\x27\x81\x6b\x40\xb1\x98\x1b\xdb\xa9\x39\x21\xe7\x2e\xbd\x0a\x40\x1f\x9a\xd1\x72\x2c\xf2\x78\x72\x8e\x75\x07\x0e\x23\x8f\xb6\x8e\xb4\xb8\x82\x23\x6a\xa4\x5d\xcb\xa9\x63\x15\xe1\x88\x4c\xf2\x60\xc1\x25\xa0\xa2\x83\x14\x7c\x6b\x1c\x52\x55\x86\x3b\x91\x44\x33\x80\xdd\x1d\x35\xc5\xd5\x6a\x89\xb2\x4f\x24\x2d\x08\xf2\x51\x06\xfe\xec\x93\x77\xc4\xb1\x41\xc4\x58\x19\x4d\x9a\x1f\xc4\xf7\xad\x02\x9c\xba\xf7\x3b\x19\xee\xaf\x51\x8e\x79\xef\x6d\x0e\xf9\x70\xff\x92\x03\x1c\x4f\x26\xb4\x11\xf9\xd1\x80\xd9\xdd\xd8\x8c\x1a\xf4\xcc\x43\x45\xab\x9c\x32\x77\x62\xf3\x6c\x23\x04\xff\x90\x25\xae\x24\x0b\xc4\xb3\xff\xe9\x1f\x71\x2d\x9c\x24\x08\x65\x79\xf7\xed\x32\x5f\x6e\xc1\xc5\x82\x41\xbe\xb3\x45\xdd\xf5\xfa\xf0\x8d\x0b\x3f\x7e\xdd\x31\x27\x7f\xa9\x9c\x60\xc9\xf1\x69\xba\x68\xe8\xfa\x7b\xaf\xe4\xef\xe7\xdb\xcb\x12\x4d\x04\x9e\xc3\x76\x74\xf9\xd2\x4d\xaa\x0d\x7c\xfc\x2e\xc8\xfc\x4c\xbe\x07\x3e\xc0\x2a\x7d\xc3\xdf\x8f\x89\xeb\x53\xa9\x63\x66\xbc\x2c\x52\x58\x9d\x98\x72\xf0\x9e\xe8\x79\xf4\x8f\x53\x1a\xb8\xba\x80\x26\x56\x82\xe7\x05\x84\x98\x73\x31\x89\x44\xe3\x13\xd5\x55\xe9\xad\x71\xbb\x5d\xbd\x20\xd1\xe2\xd7\x0c\xf8\x76\x3f\xa8\xff\x2e\x0c\xee\x03\xae\x2c\xed\x94\xff\x54\x7c\xc7\xc0\xf2\xf6\xa7\xcc\x86\x58\xe8\x8c\x76\xc6\x6e\x2a\xd4\xe9\x74\x5d\xf6\x21\xe9\x8e\xf8\xaa\xbb\xeb\xbd\xf6\x97\x2a\xc4\xbe\x57\xbc\x6b\x92\xeb\xab\x47\xae\x2b\x20\x38\xcf\x39\x32\x7a\x92\x43\x58\x9f\x06\xc6\x53\x9f\x23\xd6\xaf\x2d\xbd\x5a\x50\x45\xd7\x8f\x28\x37\x20\x0b\x55\x95\x90\xc2\xa9\xa3\x2b\x24\xf1\x51\x87\xc8\xaf\x62\x86\xef\x76\x9e\x79\x8b\xe7\x16\x94\xf5\xf6\xbf\x1d\xa2\x67\x4d\x16\xbf\x2f\xea\x86\xb2\x87\x7c\x10\xd9\xfc\x45\x53\x5d\x2d\xa5\x74\x4c\x7a\x8a\xcb\x93\x1b\x14\x53\x14\xec\xf9\x97\x3b\xb2\x61\x20\xc6\x40\xfd\x50\xd6\x14\x6e\x80\x9e\x1f\x17\x8b\xde\x22\x92\x18\x4e\x99\x14\x4b\x1c\x6c\xe5\x30\x91\x44\x0a\xac\xec\xf5\x7f\x4f\x36\x92\xec\x77\x15\xb3\x63\xc3\xcf\x9f\x3e\x0d\x84\x95\x2f\x62\x80\x68\x26\x81\xb0\x08\x85\x0f\xb6\x76\x12\x3a\x51\x64\x1c\xf1\x16\x4c\xb1\x98\x2a\x54\x1c\x9d\xf8\x17\xeb\x72\x8b\xd5\x29\x81\x92\xca\x47\x19\x6e\xc1\xfb\x95\x81\x31\xcc\x05\x2a\xb2\xd7\x29\x94\xee\x14\xa4\x9a\xca\x25\xa7\x69\xa6\xc9\xba\x49\xec\x7c\x2c\x52\xc6\xac\x36\xff\x44\x8f\x60\x52\xaf\x69\xbc\x59\xc9\xd1\x22\x4f\x75\x65\x0c\x9b\xc3\xa8\xb8\xe8\x9f\xf4\x6d\x44\xbf\x16\x8b\xce\xe5\xe3\x8d\x92\x15\xda\x56\xed\xc4\x43\x15\x5b\xca\x80\xaa\xe0\x8b\x60\xb8\xb5\x23\x77\x22\xe8\xdf\x23\x26\x66\x07\xe4\x09\x7e\x21\xa6\x13\x3b\x2a\xa7\x03\xc5\x33\x00\x16\xd4\xb8\x33\xc7\x18\x9c\x56\x92\xa4\xd5\xa5\x9e\xb2\x26\x2b\xca\x0b\x59\x12\x78\x1a\x4d\x66\x5c\xc7\xfd\x5e\xad\x66\x4b\x34\x6a\x48\xd0\x2e\x2f\xbd\x7b\x09\xf5\x9b\x18\xc0\x03\xa9\x90\x2e\x36\xc2\xda\x97\x76\x3e\x8b\x6c\x41\xa8\x99\x96\x46\x13\xf2\xa8\x5c\xa8\x79\xe9\x97\x50\x77\x7c\x6c\xe6\x9e\x15\x88\x08\xe7\xa7\xb6\x59\x74\x5f\x2f\x68\x1e\x3a\x20\xe8\x07\x4a\x4d\xc6\x8e\x97\x37\xe7\xa1\x6e\x8b\xb4\x62\x45\x9f\x3d\xab\x05\xbe\x2f\x7d\x18\xcb\xa4\x61\x56\xf4\x12\x3e\x0d\x16\xf4\xc6\xb8\x95\x69\x7e\x51\x3b\xff\x82\x2f\xfb\xf9\x2e\x00\xa7\xf3\xd8\x19\x9d\x4f\x0d\x76\x30\xf7\x10\xe7\xcb\x1c\xdf\x9f\x87\x8f\xdb\x1e\x65\x22\x4d\x2e\x80\xcf\x7d\x9b\xe2\x1d\xd0\x0d\xbe\x68\x7e\xce\xae\xc4\x3f\xb1\x60\x4f\xf4\xfc\x55\x4a\x74\x62\xc6\x0e\x8c\xd9\x40\xf6\xb2\xdb\x34\x71\x24\xe3\x94\x16\x58\x50\xa0\xad\x19\x65\xaa\x4b\x51\x13\xc7\xf1\xa3\x14\x11\x71\x36\x85\x4a\xfb\x26\x5f\x62\xc8\x87\x25\x9d\x0a\x84\x34\xb4\x26\x65\xd4\xa1\x94\xd2\xad\x82\x13\xd2\x16\x2e\xcc\x1f\xb9\x0d\x37\x6f\x2f\x4d\x4f\xa3\xc9\x65\x48\x51\x56\x44\x5d\x32\x93\x93\xfc\x5b\x9c\x26\x1b\x85\x81\xd8\x73\x1a\xb6\x9d\xf9\xdb\xa2\x82\x1b\x6d\x0f\xfe\xd2\xbf\x71\x86\x24\x69\xe3\x97\x84\x92\x35\xa3\x02\x6a\x10\x21\x8b\xda\x47\x43\x4f\x65\xc6\x52\x2c\x76\x51\x25\x21\xab\x2e\xc4\xf7\xb9\x89\x11\xa0\x14\x33\x18\x7e\x9d\x98\x11\xbd\x70\x31\x76\x96\xf0\xf7\x2b\x6e\x98\x8f\xb0\x77\x76\xb9\x22\x05\x81\xff\xad\xe5\xef\xef\x39\x31\xa9\x3f\x94\xfd\x4d\x8d\xba\x0c\xa3\xca\x39\x50\x49\xa2\xe9\x63\x45\x1c\xf8\xc5\xf8\xbe\x55\x88\x7c\xf1\x89\x0a\xb8\x00\x8e\x8a\xaa\xe0\x5d\x4c\xeb\x49\x7a\xeb\xb7\xd7\x49\x44\xc7\xed\x4b\xa7\x81\x41\x7f\x7c\xc8\xc0\x23\xba\xc8\x7e\x3d\x57\x8d\x1e\xfd\xf8\xe0\x7a\xb7\xb1\xb3\x1f\xb7\x61\x62\xee\xe9\xda\xb4\x6c\xa6\x0e\x54\x5b\xa6\x70\xae\x6c\x33\x6a\x3c\x96\x7f\xd5\xc5\x9d\x74\x66\x6a\x29\xcc\x8e\x36\x79\x29\x27\xf2\xb4\xe3\x39\xb0\x1d\x97\x35\xc4\xdb\xa9\x7a\xec\x53\xb2\xae\x1c\xe3\x71\x27\xc2\x5a\x0b\xbf\x2a\x17\x61\x16\x28\x69\x4d\xce\x82\xb2\x81\x30\xd3\x8f\x12\x9b\x32\x90\x4b\x5e\xab\xb9\x2f\xa1\x4b\x2d\x37\x9b\xe7\x96\x01\xe9\x83\xbd\x56\x91\xac\x6f\x36\x6f\x2e\xf0\xdd\x00\x37\x74\x69\x06\xe9\xd2\x10\x19\xef\xaf\x84\xad\x4e\x86\xb5\xd9\xe4\x49\x67\xeb\x3c\xfa\x47\xe7\xc8\x83\x4a\xeb\x53\x23\xbe\x5a\x59\xb3\xca\x8a\x1a\x72\xcb\xd8\xc5\x66\x3a\xb3\xc0\xde\x0e\x92\x40\x74\x04\x9a\xfe\xa4\x12\xfb\xb6\x8f\xe2\x2d\xc7\x5c\x6f\x17\xfa\x2e\x3c\xdc\x5c\xe9\xf9\x4b\x8e\x29\x43\xaf\x23\x79\x5e\x06\xa6\x6f\xda\xbc\x1a\xe5\x53\xda\xac\x3c\x2d\x93\xf8\x05\x37\xbf\xb0\x73\x24\x79\x22\x2e\xea\xb4\x8a\x33\xef\xf9\x49\x67\xe9\x23\x97\x0e\x77\x0b\x4f\x21\x00\xde\x09\xdc\xb9\x66\xef\x06\x4c\xe5\xe4\x45\x85\xce\xd5\x66\x64\x51\xed\x5b\xdd\xbe\x95\xea\xce\xd7\x74\xa6\x10\xd2\x75\x23\xc1\xed\xaa\x46\x46\x87\x65\x06\x6e\x45\x5d\x4c\xdc\x35\xe7\x96\x4f\x95\xee\xf3\x2d\x4d\x26\x93\xee\xd7\x44\x2a\x61\x04\x6e\x01\xf0\xbd\x8c\x7d\x1d\xad\x0e\x85\xac\x5c\xcb\xe7\x52\x36\x15\x4b\x35\xcb\xb5\xd9\xeb\x81\x8b\x54\xa7\xc3\x44\xfc\xeb\xb9\x24\x9a\x6e\x20\xcb\xca\x97\x6d\x71\x4c\x53\xb8\x11\x3d\x23\xd3\x26\xf5\xcd\x3c\x44\xf8\xfc\x3d\x97\xaf\x99\xf7\xb2\x0e\xd5\x9b\xc5\x20\x6c\x9d\xf7\x5d\xc5\xb3\x25\xc5\x0d\x6f\x56\x28\x3e\xd0\x39\xd1\x6f\x89\xeb\x39\x64\x78\x9c\x6d\xab\x2c\xf4\x0f\x07\xc4\x6a\x3f\xef\x9c\x46\xce\x36\x59\xf4\x66\x62\xf6\x1e\xf9\x34\x21\x76\xda\x5f\x73\xea\x58\xd5\xcb\x9d\x4e\xe2\xc2\x37\x8f\xf0\xe3\x5f\xb4\x52\xb5\x0f\xf7\x5d\xbc\xa9\xb4\x39\xac\x96\xc6\x06\xbf\x43\xe5\x07\x13\xaa\x5b\xbd\xf5\x65\xa8\x8c\x9e\xae\x86\xe3\x88\xe9\x05\x46\xb3\x4b\x99\x8e\x05\x6c\x50\xab\xa4\xc8\x60\x3b\x7b\x46\x90\xb0\xc8\xd8\x01\xdc\x99\x70\xd1\x0a\xc0\x22\x37\x4e\x2e\x38\x90\x18\x49\x8a\xa2\xbd\x2b\x14\xc7\xd0\x9d\xb3\x79\xf0\xda\x8e\x6d\xce\x4f\x9c\x47\x00\x57\x38\x01\x65\xd7\xa9\xeb\xf6\x3d\x86\xef\x54\xaf\x63\x79\xa2\x95\xd3\xb5\x5a\x61\x70\x6f\xd9\xdc\x97\xec\x89\xcf\x23\x8d\x95\x40\xef\x7a\x6c\xe3\x8d\xb5\xa6\xeb\x01\x7b\xd9\xc4\x2d\xbb\x8d\x56\xeb\x55\xf7\xca\xcf\xbb\x1a\x0f\xe7\xf1\xcf\x04\x9d\x6c\xef\x4e\xbb\x53\xe9\xfb\x82\x79\xfe\xdf\xb2\x1b\xe2\x17\xee\x7c\xf3\x7c\xd7\x38\xcd\xaf\x07\x6e\xe9\x5a\x17\xf9\x02\xa6\x35\x8f\x9a\x88\x8b\xfd\x12\x07\x2c\x90\x43\xd3\x0c\x14\xcb\x0a\x43\x2b\x6e\x92\xa6\x6c\x91\x6b\xea\xa2\x3c\x03\xac\xa6\xe1\x7e\x8e\x05\xea\x62\x1e\x1f\x1c\x33\xa2\xc3\x63\x9c\x8f\xf4\xd0\x44\xae\x2c\x85\x02\x1c\xfe\x26\xfb\x85\x2e\x63\xcb\x3c\x86\x99\xbd\x6e\x92\x6e\x7e\xd7\x82\xa7\xf3\x8a\x4a\x0a\x1c\xbc\x92\xec\x16\x98\x97\xaf\x13\x87\xd2\x07\x94\x47\x6a\x26\xdd\x2e\x26\x6b\x3b\xe8\x1e\x3b\xeb\xb8\x55\x62\xb9\xed\x98\x2e\xae\x24\x57\x51\x53\x3c\xc5\xd6\xaf\x8d\xac\xc4\xd3\xf3\x5f\xb5\xbe\x35\x27\xf3\xbe\x39\x9f\x5f\x9e\x1e\xf7\xbf\xcc\xfe\xaa\x60\xe8\x32\xcf\x4f\xff\xc4\xdd\xde\x05\x9c\x1d\x45\x5a\x33\xe7\xad\xf6\x50\xf5\x6e\x6a\xae\xe8\xbe\xd0\x37\xac\x31\x34\xa6\x1b\x85\x46\x21\x58\x5c\x6c\xdd\x0c\xcd\x89\xa1\xbd\x4c\x95\xcd\xd0\x7f\x0e\xd0\x78\xe2\x11\x76\x7d\x26\x5f\xb0\x9b\xf6\x7a\x95\xb3\xb9\xb2\xad\xe6\xf2\x19\xdd\xa2\x17\x21\xb3\xa6\x7c\x73\x7b\xca\x11\x8f\xd1\x25\x17\xf3\xa0\x74\x5f\xee\xd2\x5c\x5b\xe8\xab\x31\xfd\xda\x61\xca\x88\xec\x4c\x48\xb7\xcb\x0f\xeb\x2e\xfc\x46\x57\xdb\xd1\x8f\x0d\x82\x36\xbd\xc9\x9a\x73\x07\x67\x23\x5f\x13\x24\x34\x43\x7a\xcf\x97\x60\xc2\x25\x8b\xcc\xf8\x93\x36\x7d\x18\xac\xd4\x9e\x93\x93\xf1\xfe\x8e\x4b\xdd\xa3\x89\x85\x88\x35\x53\x14\x3d\x20\x5a\xf1\x02\xb5\xd1\x8a\x31\x4e\x66\xe3\xaa\x1c\x8b\x7d\xd2\x09\xa3\x50\xef\x5b\x81\x3c\xd4\x42\xc4\x3b\xbf\x49\x00\x92\xd2\xc5\xc8\x48\xb4\xe1\x6b\x24\x5f\x77\x42\x8a\x26\x57\x55\xf0\x7e\x63\x41\x44\x96\x06\xf5\x88\x69\xb5\x44\x48\xc8\x66\x60\x04\x68\x0d\xeb\x8d\x0e\x9b\xd0\x84\x66\x3b\xa6\x65\xfb\x1c\xd3\xf3\xd5\xc1\x16\x3f\xfe\x88\x45\x37\x19\x4f\x01\x41\x41\x61\xc6\x55\x85\xdb\x69\xd1\x84\x7c\x5c\xe5\xf0\xd2\x6a\x48\x97\x49\x3d\x53\x80\x45\x39\x9c\x5b\xb3\x1a\xc9\x52\x77\xb3\xa8\xfb\x2b\x25\xd7\xc0\xbc\x8e\x3f\xbc\xd6\x30\x4b\x46\x75\xfa\xb6\xf9\x84\x77\x42\x25\xe9\x20\x36\xd2\xa5\x50\xdc\x3b\xd5\x45\x75\x3d\x8a\x71\xc6\x64\xb8\x4f\x5c\x18\x44\x30\x79\xa8\x53\x37\x90\xe2\xc7\x1d\x0a\x7a\x8e\x8c\xcb\xaf\xce\x5a\x8b\x18\xe3\x7c\x40\x74\x0c\x9c\xa3\xd8\x33\x0b\x3b\x56\x85\x12\x53\x36\xff\x2d\xc3\x89\x57\x3f\x0f\x4a\x12\x4f\xb9\x92\xcb\x33\xcc\xb2\xea\x58\xe9\xd9\xd8\x5d\x19\xff\x1c\x80\x5c\xbd\xcd\x9f\x62\x3c\x69\xa2\xa0\x87\x3d\x21\xe6\x7e\x85\x90\xcf\xe1\x07\x2a\x7d\x9e\x8c\x4b\x88\xfd\x4d\x2c\x25\xc8\x7c\x48\x13\x70\x92\x63\x02\x29\x07\xee\x86\x38\x7b\x11\x0c\x72\xb5\xa6\x5b\x64\xa8\xc7\x0b\x27\xc4\x3f\x6c\xd4\x46\xa7\x5c\x2a\x67\x71\x4c\x33\x84\x2e\xe9\xba\xaa\x0d\x1d\x96\x61\xf2\x27\x03\xb8\x78\x1f\x9e\x57\x22\xe9\x87\x77\x34\xf6\x1b\x0f\xa2\x2e\x88\x2e\x19\x15\x51\x3a\xad\x56\x93\xb6\x74\x24\xd6\x05\xe8\xbc\x42\x8e\xea\x8d\x16\x92\xe6\x71\x41\x25\xb0\x58\xe9\xee\x91\x8b\xff\x6f\xa7\x85\x78\x8d\xf0\x46\xa6\x45\xcd\x15\x3d\x51\x9e\xee\x34\xa1\x83\x50\xc6\x21\xc4\x32\x7b\x65\xed\x14\x81\x65\x85\x45\xfa\x4a\xc3\x65\x3c\xc6\x5c\x03\xc7\x10\x54\xaa\xfd\xb5\x43\x85\x41\x76\x6a\xca\xa2\x4c\x9f\x36\x44\x3f\x32\x37\x05\xf4\x02\x8e\x88\x58\x9d\xe7\x69\x5a\x7b\x4e\xaa\x67\x62\xbf\x9c\xa0\xe0\x9d\xae\xa1\x3b\x29\xaf\xa5\xb1\xb4\xdd\x53\xe9\x26\x02\x1f\x2e\x85\x3c\x80\xf6\xa1\x0c\x99\xee\x6d\xec\x0b\xce\x2a\x14\x9d\x15\x22\x08\x5c\x35\x89\xb2\x8f\xa0\x44\x58\x49\x52\x23\x3f\x34\x2f\x2e\xff\x18\xa5\x03\x45\xa5\x28\xb1\x0d\x69\x89\xe6\x9b\xad\xf0\x46\xe5\x69\xb1\x88\xea\xd9\x22\x07\x7a\xcc\x4f\xe6\x9f\x85\x33\xab\x9b\x65\xb4\x5c\x97\xdb\x4d\x68\xd9\x8f\xa5\xaf\x50\x6c\xa2\xc9\x53\xe3\x79\x2d\x5f\xed\xc7\x49\x39\x26\xbe\x0b\x37\xb2\xed\x41\xf5\x50\x80\x33\x95\x9c\xe6\x43\xd5\xea\xb0\x38\x8f\xd3\xc7\x87\xee\xbf\x8f\xb7\x39\x16\xdf\x00\xf3\xfb\x8e\x2c\x78\x1a\xea\x6c\xa3\xba\x9f\xc5\x04\x37\x76\xaa\x5c\x2b\xac\xc3\x63\x5f\x39\xde\x02\xa0\x62\xac\x97\xdc\xc2\xa6\xd9\x99\xd6\xe2\xe6\x6a\x57\x59\xa3\xc8\x83\x22\x98\x30\xb5\xe1\x6f\x45\xc2\xbf\x13\xa1\x0f\xed\x37\x95\xb5\x5d\xaf\xc4\xe7\x5f\x3d\x23\x06\xd2\xcf\x34\x36\x39\xae\x4a\x82\x61\xf7\xa1\xb5\x78\x12\x1a\xe9\xd5\x63\x84\x3a\xfd\xed\x43\x85\x5e\x7e\xf7\x0e\x24\x8a\xc5\xc6\xf1\xf3\xf8\x4b\x02\x23\xb8\x7c\x91\xbf\x3e\xdf\x1b\xc9\xae\xaf\x1b\x1d\x24\x47\x6e\xc6\x1c\xf2\x35\x64\x93\x5f\x07\x85\xf6\x15\xee\x6d\xc2\xff\x7a\x2d\x5f\x65\xbb\xc5\xdd\x85\xce\xec\x43\x1e\xe8\x0a\xe2\x34\x55\xa1\xa3\x53\x5b\x46\x9d\x99\xaa\xe7\xe3\xda\x24\x05\x32\x73\x09\x36\x57\xb1\xfc\x52\x9b\x2e\x42\x73\xce\x57\xc8\xa8\xcd\xd8\xf6\x8d\xdb\x7a\x4f\xa5\xdf\x57\x5c\x97\xc9\x12\xad\x66\x1a\x24\x18\x42\x2a\xe2\xeb\xae\x44\xe3\xa8\x10\x2b\x65\x96\xe4\x81\xd4\x18\x88\x68\x70\x28\x8d\x6a\x50\x1d\x4e\x1d\x55\xcf\xf4\x91\x1f\xe0\xac\xcc\x70\x6d\xe1\x5e\xe2\x41\xa0\x39\x34\xc7\x5e\x6a\xa7\x39\xf2\x63\x05\xfe\x12\xee\x3c\x15\x0e\x34\x43\xb6\xa3\xe5\x9e\x68\xdf\xb2\x00\x5e\x17\x0f\x98\x8c\x74\x81\xf0\x1e\x36\x57\x72\xc6\x42\xd5\xff\x4e\x62\x3e\x7a\x1a\x89\xa7\x3d\xe7\x87\xf8\xa1\xa4\x30\xe3\x5a\xbc\x5a\x1c\x89\x24\xb7\xee\xc7\xda\x51\xb6\x94\x47\x3d\xc5\xb7\x5f\xe3\x20\x1c\x7c\x28\x6b\xaa\x5f\x26\xda\x1e\x2c\xa2\x4f\x3b\x42\xbc\x27\x79\x7e\x57\x98\xf5\x7c\xe7\x6d\x4c\xc5\x2b\x79\xe0\x85\x67\x29\x99\x56\x8d\xee\x7d\x24\x89\x9e\xb3\xae\x6c\x48\x73\x83\xb9\xd3\xbd\xa7\x92\x30\xb9\x12\xfa\x20\x71\x4f\x7e\x10\x1d\x03\xca\x06\x56\x27\x47\x34\x7c\x44\x21\x38\x27\x82\x27\x80\xb4\xae\x29\x9c\x28\x16\xcd\xe3\xcb\x2b\xec\x4c\xbb\x3f\x7f\x29\x20\x1c\x38\x1f\x3e\x57\x71\x65\x6b\x37\x9b\xce\x50\x83\xcb\xf1\xb4\x59\x20\xe1\xd0\x32\xfe\x1d\x5f\x30\xd5\x93\x7b\x93\xd5\xd2\x80\x3c\x1a\xd3\x2a\x14\xbd\xb2\x3c\x71\x90\xd8\xca\x96\x24\x53\x90\x81\x21\x25\x13\x4b\x65\xa0\xab\x54\xd2\x35\xf3\xa8\x7a\x71\xea\xe1\x53\x09\xc5\xf4\x8b\x9c\x59\x2e\x5d\x34\x1c\x7c\x5b\xa2\xe8\x58\xf4\xc5\x94\xaf\xdf\x07\x7c\x9a\x2c\x05\x2f\x56\x87\xa7\xf7\xac\x77\x20\xaf\x23\xd9\x2e\xf2\xb9\x9d\xd1\x3a\x57\x8e\x6d\xbc\x45\x8c\xc8\xeb\x20\x86\x3e\x10\x27\x56\xef\x61\x23\x47\x77\x4f\xe0\xb7\xb7\x0d\xbb\xff\x33\x32\xac\x31\xa7\xa9\x51\x7f\xd3\xa5\x38\xf3\xa8\x6e\x0b\x3e\x6a\xbf\x2f\xae\x64\xf3\xa1\xa4\xb1\x27\xad\x5d\x52\xe9\xe0\x26\xf0\x54\xe2\x79\xd7\x71\xdb\x04\x15\xb3\xf1\x1e\xdd\xbc\xc7\xb4\x75\x8e\x74\xf9\xe7\x44\xf6\x45\xce\xac\xd7\x46\xcf\x65\x2a\xd0\x59\x12\x8c\xd1\x44\x71\x49\x46\x08\xec\x87\xee\x93\xdb\xfd\xee\x07\x61\xb4\x20\xa8\xe0\x17\x39\x72\x0d\xf1\xdf\xe7\xca\x0e\xc4\xbf\x41\x9f\xed\x82\x88\xb1\x30\xca\x2e\xa9\xb4\x0f\x32\x9d\x9b\x30\x5e\x3b\x4b\x86\xe4\x51\x16\x12\xe4\xf5\xb3\x99\x4f\x45\x85\x08\x5a\x14\xb2\x27\xe8\xa3\x39\x8b\xbc\x3f\xf3\x33\x0a\x2f\x99\x59\x47\x6f\x6f\xa1\x5a\xa8\x28\x91\xbe\xd1\x68\xbe\x24\xdf\x6b\xd9\x01\xd6\xaa\xaf\x25\x74\x18\xb8\x44\x6f\x5c\x3a\x5a\xa7\xb5\x3c\x81\xe4\xbe\xf4\xfb\xae\x7f\x6e\x7d\x59\x52\x80\x58\x6f\xba\x59\x7d\x30\x26\x5a\x12\xbf\x5d\x8d\x8e\x25\xaa\xbc\xaf\x6a\x0d\x6f\x7a\x2e\x34\xe0\xaa\xaf\x7b\xa8\x77\x5d\x75\xd0\x2b\x07\x7f\xb4\xa8\x3b\x79\xcd\x10\x37\x05\x54\xe5\xb4\x7f\xd5\x1b\x4a\xe1\xbd\x87\x43\xc7\x1e\x72\xb1\x9d\xd3\xb3\x48\x3f\x29\x45\xa4\x7a\x3c\x0b\x93\x0b\xb7\x46\x48\x4b\xea\x7b\x3d\xc7\xd1\x28\x34\x34\xc5\xef\x86\x9a\x7d\xa7\xea\x56\x7a\x97\x1a\xaf\x03\x73\x2e\x6e\x3c\x8e\x75\x7f\x9a\x6f\x09\x10\x0c\x88\x61\xe4\x39\x74\x3e\x4b\xa1\x36\xd6\x67\x63\x9f\x02\xa1\xf8\x7e\x4a\x07\xb0\x9a\x3b\x58\x50\x0d\x87\xc8\x11\x87\x2b\xcb\x42\xd4\x99\x57\xb4\x8b\x1e\xa9\xeb\x9e\x9d\x24\xd6\xa9\xd3\x60\x1d\xd8\xc8\x7e\xaf\x6f\x82\x9c\x93\x0b\x00\xd0\xca\x15\x83\x75\x98\xbb\x20\x9b\x48\x31\xee\xed\x9a\x86\x69\x7d\xf5\x99\xc4\x06\x43\xcb\xbc\xe5\xf8\xd4\x58\x2e\xd9\x3f\xd9\x96\xc2\x02\x6d\x10\x7d\xd9\x35\xdb\xd4\xa7\x9e\x8a\x65\xed\xcb\x7b\x7a\x92\xa0\xe5\x3e\x8d\x7b\x0d\x9d\x19\x78\x27\x0d\xad\xb9\xc8\x53\x58\x3e\xaf\xf0\x2a\x84\xb6\x6c\x17\xa6\x78\xa6\x7c\xbf\x43\xbc\xdb\x37\xcd\x53\x04\xf2\xe4\xd8\x4e\x1a\x87\x02\xa3\x64\xb3\xd5\x93\x7c\x0b\x16\xa6\xc6\xac\xd7\x21\xb8\xfa\xa7\x1a\x4c\x98\x63\x24\x73\x88\xc1\x64\x12\x87\xa4\xb8\x06\x44\x2c\xe3\xd2\x13\xb8\x8c\xe9\xe4\x1a\x32\xa1\xd8\x27\x11\xa2\xe1\xd8\xb0\x76\x0e\xb9\x2d\x2f\xdf\xcd\xbc\xd1\x70\xdc\x26\xff\xd6\xfe\x39\x66\xd0\x7a\x1e\xb8\x33\xd5\xf1\x85\x18\x86\xca\x75\xf7\x66\xef\xf0\xf2\x63\x59\x81\x5a\x5e\x9d\x86\xb4\xef\x4f\x88\xa4\x48\xc4\x82\x64\xb7\xd5\x99\x5d\xfd\x6d\x4b\xdf\xa3\x02\xec\x21\x07\x84\x82\x19\xc5\xb0\x02\x1f\x0e\x4a\x5d\x7a\xbf\xa7\x7e\x47\xf4\xde\xbf\x33\x8f\xea\xca\xe7\x62\xff\x96\xb1\x1b\x5b\x5b\xc1\x1e\x6a\x8f\x54\x7d\xb4\xb0\x02\xbf\x8e\x52\x99\x80\x21\x1c\x80\x5f\xd3\xd7\x71\xb1\x1f\x6d\x5f\xd8\x0c\xd3\x4a\x5d\xfe\x7b\x9a\xde\x7d\x59\x51\xf7\x70\xc0\x15\x9b\x9f\x2b\x67\x7b\x5c\x3a\x30\x86\x64\xc0\x24\x20\xcd\x14\x86\xfa\x56\xc7\x39\xeb\xf1\xcf\x25\x38\x02\x4c\xe1\xee\xb7\x2a\xa6\x8a\xfd\x73\x9f\x0e\xc8\x91\x25\x19\x7f\xe5\xe5\x4f\xf6\x14\xe9\x68\x5e\x18\x5e\x00\x49\xbe\xad\x77\xee\xb3\xb2\x23\xe6\x97\xa1\xa8\x9a\x77\x26\xa9\x7b\xcb\xa4\xe8\xe0\x53\x7c\xda\x1c\xa9\xbb\x0e\x13\x57\x5c\x69\xcf\x1e\xe4\xb8\x15\xcb\x26\x03\x4e\x87\x35\xc1\x82\x7e\x60\x71\xd6\x62\x77\x20\x79\xb5\x6d\x85\x74\x05\xf3\x5c\x51\x89\x6c\xe5\x28\xb4\x84\xfd\x35\x51\x22\x49\xff\xcd\x50\x87\x4f\xe4\xc2\x59\xd3\xe3\xc5\xad\x2c\xdf\x1e\x23\xef\x63\xdc\x5a\xce\xee\xdb\x75\x8b\x81\x70\x81\xc0\xa1\xeb\x2d\x4c\xe7\x5b\xbe\x5c\x66\x8f\xd9\xc4\x29\xbc\xd0\x00\x88\xdf\x9b\xf2\x5c\xfe\xf6\x0f\x42\x60\x54\x57\x7e\xc8\x72\xb9\x68\xb7\x44\xc5\x16\x7d\x75\x9c\xcc\x2f\xcd\x2e\xd5\x41\x12\xc8\x95\xe1\x84\x6b\xe6\x25\x8f\x40\xe3\x1c\xcf\x80\x7d\x11\x17\x43\x63\x45\xed\x2b\x84\x79\xd8\x50\x63\x43\x47\x11\xc5\xec\xb9\xe5\x1b\x9b\xea\x17\x3d\x4f\x7d\xb3\xde\x69\x0d\xed\xe6\xe2\x08\x0a\x66\xb5\x4e\x46\x97\xea\x1c\x09\xb7\x5b\x55\x4d\x6b\x64\x85\x83\x7c\x14\x0e\xbc\x36\xf0\x02\x13\xb6\x5d\x1c\x16\xa0\x92\x21\x19\xe1\xb7\x9a\x43\xf2\x91\x28\x36\x3d\x9e\xbe\x62\x2d\x5b\xbc\xfe\xe0\x14\x1e\xb2\xb4\x0b\x2a\xe3\x9e\x4d\x4e\x3d\xf4\x29\x2f\x34\xad\x34\xcc\x6d\xb0\x46\xbc\x20\xae\x8a\x56\x4c\x44\x3e\x40\xbb\x5e\xdf\x4f\xf2\x5f\xe7\xa2\xf4\xec\xe4\x39\xfb\x8f\xf1\x59\x44\x26\x21\xc2\x68\xb8\xc2\x88\x5f\x93\xa1\x7f\x98\x38\xf4\x86\x85\x56\x48\xe6\x8d\x37\x8e\x8c\x58\x6b\xc1\x59\xdb\xc3\x76\x26\x42\x0d\xae\xe6\x3f\x7e\xe2\x25\xb5\x20\x23\x59\x25\x9e\xcf\xd3\x69\x9a\x94\x8a\x9f\xb7\xaf\xe7\x75\x12\xca\x96\xa7\x14\x6e\x9e\x56\x7c\x62\xd7\x4a\x5f\x1f\xdb\x5a\x6b\x77\x69\xa4\x24\x8a\x78\xe1\xf8\x54\x68\x8c\x0d\x3b\x11\x83\x6d\xf5\xbf\x5b\x3e\x2f\x9e\x9e\x2f\x98\xcf\xd7\xaf\xe3\xb4\xb6\xb4\xfb\x8a\xc2\xe0\xf1\x5d\x94\x92\x43\x06\x42\x09\x7c\x2d\x9b\x2d\xa1\xba\xf5\x46\x4b\xa1\xae\x53\x57\x99\x6f\x26\x38\x37\x26\x1d\x8e\xd9\x9b\x25\x28\x96\xcc\x61\xdb\x31\xe4\x0b\x8f\x3e\x3d\xd2\x30\xfd\x28\x88\xbc\xc5\xa4\xe4\x8f\x95\xbf\xfa\xfd\x85\xdc\x8d\xea\x88\xb3\xad\x8c\xeb\x72\x57\x83\xce\x7e\x47\x5f\x96\x3a\x29\x28\x4e\x84\x9f\x67\xf1\x83\x52\xe3\x56\xa7\x17\xed\xc5\x02\x23\x2b\x03\xc1\xd6\x40\x72\xd9\xe7\x77\x81\xb7\x92\x4b\x41\x76\x42\x8b\x98\xd0\x69\x24\xac\x74\x39\xaa\x7b\xa6\x9d\xb6\x53\x70\xcd\x44\x62\x13\xe6\x08\x2c\x47\xe4\x67\x18\x7d\xb2\xbd\x76\x72\xaf\x09\xfe\xb6\xdb\x4d\x4b\xd5\x88\x73\x5f\x68\x9c\x03\x96\x1b\x14\xee\xbc\x92\x4a\x2c\xf5\x87\x31\x38\xd5\x0c\x55\xdc\x55\x6b\x55\xfd\xed\x43\x9b\xcf\x84\x2e\x55\xea\x57\x9d\x7b\xcc\x32\x39\xe6\x82\x3c\x71\xb0\xc1\xf8\xc1\x59\x94\xea\xce\x2e\x3c\x1f\x9c\xba\xd5\xd6\xcf\x59\xfc\x5e\x1e\x2a\xa9\xf8\xd5\xb0\xba\x3c\x14\xd8\x39\xdc\x4b\x47\x3a\xdc\x2f\xd7\x24\x68\x99\x06\xde\x54\x59\x52\x4f\xee\xae\x2f\xc5\x15\x36\x9b\x0b\xd8\xe9\x0d\xb6\x1b\x64\xa9\x84\xc7\x13\x6c\x69\x69\xb4\xe6\xec\xc5\x74\x34\x2e\x4d\x94\x99\x96\x6c\x04\xe6\xd1\x86\xc4\xea\xe0\xd6\x43\xe0\x15\x27\xa1\xbc\x4e\x24\x6a\x8a\xca\xe9\xc9\x39\x61\xc5\xd6\x31\xe1\xd1\x8a\xbf\x34\x8f\x0e\xa0\xf2\x42\x6c\xf4\x13\x2a\x79\x8a\x8e\xee\x2c\x60\xff\x65\x53\x89\x95\xa9\xfe\x6b\xa4\x6d\xfd\x30\x15\xac\x2c\x2d\x26\x37\x40\x04\xb7\x9a\x0b\xb9\x0d\xa2\x0e\x9e\x69\xfb\x45\xac\x43\x08\x4f\x89\x1b\x36\x33\x89\xaf\xf3\x22\x68\x49\xe9\x34\x9a\x20\xdc\xc4\x67\xf2\x38\x51\x8d\x6f\x39\x78\x0e\x65\x35\x0b\x7a\x5d\xdd\xae\x56\xb3\xdd\xf5\x13\x59\x96\x48\xf9\x2e\xd1\x55\x62\x54\xee\x90\xaf\x32\xb6\xad\xc2\xca\xab\x53\x2a\x6c\xb2\x61\xe1\x8d\x45\x97\x11\x7d\xc5\x55\x49\x8a\xe9\x10\x63\x47\x89\x11\x06\xb7\xc0\x23\x93\xdb\xde\xdf\xea\x21\x33\x8a\xb4\x71\x32\x52\xcb\xe5\xf5\x46\xc6\x2e\x9d\xc9\x47\x86\xaa\xd5\xe8\x56\x4e\xc3\xe7\xda\xaa\xf6\xab\x75\x35\x08\x46\xee\x1a\xe3\xb8\xc6\xb9\xb3\x04\x88\x00\x65\x8a\x65\x1f\xc0\x90\x40\x5b\x38\x0e\xa2\xc6\x35\xd9\xc1\x30\x1e\xd3\xbc\x4d\x03\x9f\xfd\xbe\xbd\x76\xec\x4e\xb3\x42\xbe\xe4\x9b\x2d\x6d\x4b\x95\x09\x53\xb8\x78\xc6\xbf\xac\x09\x8d\x97\xc9\x8f\x66\x1c\xe1\x76\x8c\x9d\x39\x6e\x50\x63\x7e\xde\x57\xe1\xcc\xbd\x0c\xbc\xe7\xea\xc0\xdf\x56\xb7\x74\xad\xd2\x64\x65\x6c\x3e\xcb\x74\xe3\xca\x79\x76\xb8\xce\x1e\x00\x8b\x71\x5c\x55\x22\xd7\xfd\xe7\xf6\x70\x69\xa2\x69\x70\xad\xdc\xbb\x71\x95\xcb\xc5\xae\x6f\x99\xe3\xfd\x30\x70\xd2\xab\xee\x06\xd6\xda\xf5\xc9\xc3\x5a\x71\x89\x3d\xb3\xe9\x80\x43\x81\x05\x56\x97\x3a\x44\xc9\x87\x65\xdf\x41\xd7\x86\xba\x62\x87\x01\x16\xe1\x90\x71\xd5\x96\x92\x64\x3b\x35\x31\xde\xf4\x8b\x29\x6b\x50\xbc\x2e\x43\x85\xbc\x58\x82\x4e\x0a\xa3\x3b\xe9\xc5\xbf\xec\xc8\xba\xd3\x6c\x77\x3c\x4f\x0b\xbb\x20\x20\x4c\x5d\x34\xed\xf0\xac\x59\x5d\xcf\x0f\xa9\xcd\xcb\x44\x86\x51\x9b\x8d\x79\xe6\x7c\x5b\xb0\xc5\x95\xf5\x98\x8c\x24\x86\xc2\x1c\x53\x1c\x8f\x72\x9d\x03\x1a\xd0\xa0\x89\x4d\x7d\x06\x62\xd9\x46\xdf\x2c\x02\xe1\x64\x48\xae\x8f\xd4\x0f\x1c\x95\xb5\xbe\x52\xf5\x93\x54\x58\x94\x0a\x57\x1e\x93\xe9\x9b\x46\x34\x58\xf9\xc7\xf2\xf8\xf5\xf7\xfb\x8e\x84\xc5\xf0\xe2\x32\x3d\x51\x61\x94\x96\xe7\x23\x16\xca\x65\x93\xf5\xd7\x4f\x7c\xdc\x5f\xc9\x65\x20\x8c\xe6\xdc\xb8\xe4\xa2\x23\xc5\xf7\x7a\xe6\xb8\xf9\x42\x42\xf8\xd9\x42\x68\xae\xd0\x0b\xdf\xfb\x61\x4b\x73\x77\xf0\x97\x59\xec\x3e\xb4\x8c\x07\xa8\xae\x6e\xb8\x35\xd3\x36\x7b\x63\xba\x41\x11\xd3\x93\xb8\x10\xc5\x25\x7c\x6e\x1e\xc2\x6f\x4c\x0b\x58\x5a\x49\x6c\x88\x24\xd9\xd5\xc8\x21\xfc\xe2\xd7\xcb\x3a\x38\x04\x90\x10\x28\x5f\xec\x53\x69\x67\x7b\xd0\x0d\x99\x32\x8d\x53\x35\xf6\xf7\x24\x0a\x7a\x86\x4c\x1d\x69\x9d\x6f\x70\x02\x61\xe9\xa6\xc0\x35\x32\xa5\x1f\x18\xe8\x39\xdc\xc4\x6e\xdc\xee\xc2\x57\x9b\x77\x82\x63\x16\x2e\xb9\xa3\x1e\xb5\x92\xde\x53\x1d\x5c\xfc\x99\x6f\xdb\x68\x93\x9d\x56\xc5\xd9\x5e\xab\x60\xfb\x2e\xcf\x5e\x94\x78\xad\x29\x5c\xf9\xb1\x94\xa3\xd8\x74\x77\x16\x6a\xb7\x77\x41\xfd\x4a\x97\xaf\xd0\x97\xde\xdf\x96\x05\x11\x6e\xfc\xd3\xa9\xe0\xf6\xea\x03\x09\xc8\xf4\xcc\x63\xe2\x98\x0a\xf9\xa2\x29\xb1\x5b\xa0\xf3\x5e\x8f\x5c\x0e\x43\x23\x49\xa1\x03\x67\x9c\x7a\xf2\xba\xd7\x4a\x8a\x20\xd2\xa5\x65\xd5\xc8\xb0\x6c\x06\x11\x5e\x16\x02\x36\x3e\x3c\xc8\xc2\x2b\x84\x1b\xb2\x18\x6b\x38\x53\xc4\xcb\x68\xce\x65\xd0\x8d\xc3\x8c\x7d\x8f\x84\xf8\x84\xe8\x0a\x05\x71\xd5\x7e\x5a\x59\x2b\xbf\xd5\x4a\xfd\x9d\xd3\xb7\x4b\x1b\x6e\x4c\x6c\xd8\xba\x6d\xc5\x41\x9e\x4e\x62\x8a\x02\x64\x61\x64\x29\x52\x95\xb8\xfb\x91\x3b\x5f\xa9\xa6\x03\x5d\xc4\x06\x5c\x8c\x2d\xe4\x8a\xc6\xfe\x49\xaa\xc8\x0f\x9f\x42\x39\x02\xed\x46\xdf\x6e\xb2\xf6\x8e\x37\x1d\x79\x5a\x5f\x73\x56\x5a\x59\x4a\x92\x32\x6a\xca\xbd\x37\xf0\x52\xf4\xd3\x12\xac\xbd\x95\x3a\x2d\x92\x94\x0f\x52\x56\x6e\xd4\x37\x31\x85\x40\xcc\x70\x8c\x9d\x21\x0d\xac\x5f\x73\x4a\x7d\x99\x18\x6f\xde\x62\x21\x7d\xee\x9d\xa6\x1f\x28\x1c\x98\x6f\x76\xb8\x74\xc5\xd9\x17\x67\x64\x8a\x4e\xaa\xb2\x6a\xd4\xd3\xd2\x7b\x1c\x64\xb9\xfe\xb4\xf6\x10\xd1\x4d\xed\x78\xfc\x4c\x69\x55\xc9\x1c\xe8\xcf\x4f\xca\x7b\x07\x03\x41\x8b\xad\xce\x01\x39\xe4\x76\xf6\xd7\x6c\xd7\x20\xd4\xba\xbf\x54\xca\xd4\xc1\xaf\xd2\x25\xc4\x22\x7d\xe4\x70\x3b\xfa\xb7\xa7\x74\xa5\x54\x38\xb2\x70\x70\x13\x44\x95\x3d\x07\x8e\x9c\xfc\xd0\x80\x94\x70\x25\xad\x98\xb3\xfa\x2e\xc4\x42\x82\x26\x7e\x11\x40\x5d\xd1\xf1\x59\x6e\x85\xb4\x13\x9b\x4b\xfb\x85\xc6\x51\x41\x52\x19\x95\x5f\xd4\x0e\x51\xc1\xa6\xb4\x77\x09\x3a\x7e\xb9\x62\x00\x3c\x61\xd4\x21\x4c\x5a\x89\x30\x71\x2e\x76\x51\xe1\x45\x98\x7d\x49\xab\xc5\x87\x5b\x4b\x36\x9c\x8e\xba\x5f\x86\x14\x3d\xda\x0b\xce\xaf\xd7\x85\x88\xdc\xa8\x47\x87\x41\xe4\xd9\xa5\x04\x70\xa2\x06\x4d\x61\x31\xa2\x89\xd5\xe6\x82\x7d\xc4\x6f\xe4\xd3\xe9\x18\x32\xee\x96\x87\xe9\x2a\x3d\xcf\x5f\x57\x23\xf2\xbd\x5a\x07\x32\x6f\x99\x0d\xda\x92\xd0\x6b\xf8\xb1\x3e\x58\xf6\xc9\x1f\x10\x1a\xbf\x25\xe5\x5b\x49\x59\xa5\x82\x56\xce\xa0\xff\x86\x9f\xfc\x61\x40\xa6\x25\x81\x91\xe2\x92\xc8\xa2\xba\x13\x0e\x20\xb4\x6d\x54\xcf\x1f\xe6\x22\x90\x31\xad\x20\xa2\xc8\x55\xfa\xe9\x25\xad\x4f\x4f\x90\x09\xfb\xed\x9d\x5d\x3b\x18\x01\x5e\x28\xbb\x5f\xb9\xe5\xd3\x4b\xda\xd2\x36\x5c\xb1\x78\xc4\x7c\xdc\xea\x3a\x83\x52\x69\xcd\xd6\xa9\xed\xb0\x12\xe1\xd8\xb1\x71\x22\xa7\x93\x02\xbb\xf1\xda\x61\x65\x85\xc0\xb6\x26\x8e\x8a\x73\x97\x9d\xec\xa9\x38\xee\x22\x98\x33\x8d\xbf\x01\x05\xb4\xed\x8d\xc5\x59\x97\x36\xa5\x6c\x33\x7f\xb9\xd0\x40\x6f\x36\x53\x35\xea\xcf\x9e\x0c\xd8\x39\xd1\x4e\x75\x25\xaa\xb9\x70\xc0\x7a\xe7\x61\xde\x5f\x11\x0f\x66\x28\x3f\x3c\xc2\x89\xc1\x65\x17\x72\x87\x9a\x52\xef\x91\xe5\x0c\x45\xe9\x6d\x51\x6f\x5c\x5f\xbf\xe5\xaf\x6a\x92\x36\xf4\x2b\x3f\x36\x56\x9f\x5e\x4e\x99\x51\xdf\x83\xef\xdb\x25\xbd\x76\xf0\x00\x32\x2d\x19\x45\x20\x35\x58\xea\x95\xa4\x20\x05\x61\x2c\x71\xb8\xfc\x89\x47\x34\x95\xf8\x93\x45\xcc\x18\x13\x85\x66\x19\xe2\xd3\xd4\x44\x5b\x38\x62\xb8\x40\x0a\xd9\xdc\x04\xdf\xb4\xeb\x04\x89\xee\x9e\x3a\x6c\xc6\x74\x0a\x0f\xa9\xc3\x30\xe3\xe8\xf2\x5d\x5e\x78\x56\x51\x6e\xed\x59\x0a\x7f\x99\xa1\x7c\xf4\xdc\xd1\x9d\xaa\x22\xe3\xe3\x79\x1f\xa9\xb6\xf5\xfc\x70\xd5\xfe\x35\x18\xbb\xf5\x19\x38\xde\x6b\x1d\x58\xb7\x66\xb9\xa5\xb2\xb7\xd6\x5e\xfc\x40\xf0\xf5\x0c\x04\xfe\x6d\x99\xfc\x02\x06\x3b\xee\x82\xb3\xe8\x67\x82\xf5\x72\xed\x5d\x9f\x6b\xfc\x08\xe7\x9a\x16\x73\xef\xf3\xbf\xab\xc6\xae\x64\xe7\xb0\x7c\xec\xfc\x1c\xb4\xac\xea\x05\x9a\xae\x05\xe1\xba\x6a\xbb\xed\x33\xc4\x3d\x5c\x9b\x2e\xd9\xe6\x00\xa5\xcb\xca\xdb\x5d\x5a\x5c\xdb\x29\x5c\x8a\xf6\xd6\x73\x73\x5f\xd7\x93\x62\x6a\xdc\xab\x43\x9a\xa5\x78\x68\x78\x4c\x6a\xf9\xfa\x46\x73\xca\x92\x82\xf3\x3a\x7c\x64\x45\x33\x41\x79\x81\x71\xec\x31\xf4\x14\x3d\x66\x5d\x61\x6b\x29\xc5\xde\x03\x4e\x1b\x54\x2e\x33\x4a\x52\x2c\x0b\xea\x8b\xe1\xe5\x21\x21\x71\x8e\xb8\xda\x96\x6a\xb5\x15\xb2\xcf\x8b\x74\xb3\xb5\xe9\x9d\x52\x5f\x7a\x3e\x96\x61\x8b\xb8\xf8\x8a\x05\x74\x3a\xcd\x55\xeb\xc4\x9c\x82\xa2\x64\x7a\x64\xac\x29\xe3\x4a\x14\xbf\x48\xb1\xce\x7f\xae\x75\xb4\x6c\xcb\x97\xb9\xd7\xf7\xb3\x65\xa5\x64\x48\x74\x59\xdd\x43\x78\x84\x48\x29\x55\xbb\xab\xa8\xb7\x53\xe2\xf0\x46\x34\x50\x2d\xb2\x63\xf1\x3a\x8f\x6b\xe6\x18\xca\x2e\x24\x54\x6b\x35\xba\x97\x8d\x9d\x50\x51\xe6\x65\x6a\xf6\x7f\x59\xd2\x02\x81\x6e\x99\x42\xba\xd6\xe5\xa3\x9e\xbd\x1b\xb1\x5a\x09\x20\x13\x2d\x8b\xc8\x96\xfc\x7f\x42\xf0\x14\xcf\xe0\x69\x36\xe2\x8e\xe8\x8b\xd2\x46\x90\xa2\x4e\x43\xab\xbe\x5b\x51\x30\x12\xae\x46\xc1\x6b\x9c\xae\x67\xdb\xfa\xe3\xa1\xaf\x36\x97\xad\xd2\xc2\x32\x78\x85\xb8\x27\xdc\xe2\xbc\x74\x0c\xc9\xdb\xf5\x11\x79\x5d\xef\x86\x4f\x39\x17\x38\xab\x33\xec\x4a\x31\x9c\x4e\x0b\x22\x17\x9f\x06\x22\x1e\x36\xd8\x71\xf6\xea\xa7\x0f\x53\xfe\xe0\x25\xc4\x2a\x76\xa2\x3f\xde\xe7\xe2\xfe\xe1\x37\x06\x01\x9c\xa3\x03\xba\xf5\x5b\xf2\xfc\xef\xf7\x78\x9a\x41\x99\x57\x5d\xd9\x0a\xa3\x91\xa4\x2d\x72\x28\x61\x7d\x5a\xfb\xd7\xd1\x6d\x18\xa5\x1a\xc6\x65\xe8\x7b\x5b\x11\x32\x45\xca\xf5\x15\x03\xfb\x25\xc2\x56\xd4\xae\xfe\x60\x6b\x2a\x4d\x2f\x80\xf7\xd3\x72\xda\x51\x64\x7c\xaa\xd7\x2f\xcd\xc9\x63\xb4\xc8\xf0\x9d\x3a\xc4\xae\x2d\xa7\xe0\x20\xe4\x58\xe4\xa6\x22\x97\x82\xdc\x4b\x15\xe0\x98\x5e\x77\x66\xb5\xc9\x34\x18\xd9\x40\xb3\xab\x23\xd8\xf4\xfe\x96\xb5\xca\x41\xdf\xdd\xaa\x09\x4c\xb4\xde\xab\x80\x14\xab\x7c\x55\x7f\x6a\x96\xbd\x8c\x9b\x0a\x60\xac\xe6\x14\x21\x57\xbb\x96\x0a\x9b\x30\x08\x97\xda\xf5\xca\x1d\x6a\x8b\xa8\x7b\xae\x83\xb8\xc3\x2d\x96\xbc\xa9\x6f\x56\xc3\x72\xf0\x5c\xdd\x6a\xcd\x7c\x41\xbf\xb2\x54\xf8\x36\xd4\xd0\x62\x7a\x52\x5c\xfc\x59\xcd\x3c\x97\xeb\xcd\xfb\x3e\xd9\xc8\x2f\x69\xd5\x6d\x7b\x37\xd3\x9e\xdd\x59\x6c\x7b\xdb\x6d\x72\xef\x7e\x20\xdf\x0c\x53\xed\xa9\xe0\xf6\x19\xfd\xf6\x97\x01\x8b\xaf\x64\xd8\x5b\xa9\x4e\xb7\xb9\xdb\xa9\xc1\xe4\x7b\xd5\xcd\x24\xd8\x7d\xd9\xd3\xa4\x47\x8b\xca\x61\xb0\x3e\xc0\x60\xda\xdb\x1e\x9e\xfc\x20\x78\x8f\x10\x80\xd9\xb1\xff\x94\x5c\x39\xbc\xf0\x84\x8f\xe2\x6b\x7b\x94\x8e\xf9\x84\xdb\x95\x89\xfa\x99\xe6\x08\x12\x40\x2d\x78\x36\xb9\x5c\xd7\xfe\xf5\x96\x4a\x91\xe2\x52\x20\xae\xac\x22\x97\xb5\x07\xec\xba\x1b\x0e\x1c\xd8\x59\xf4\x9d\xca\x70\xd6\xfa\x32\x16\x88\xfd\x89\x31\xe8\xf5\x39\x73\x8e\x39\xe3\xca\x75\x8f\x99\xbe\x40\xb5\xc1\x70\x85\x68\xf5\xef\xcc\xd9\x18\xdf\x02\x6e\x15\x4b\xac\xb5\x65\x65\x91\x5a\x68\x2a\x34\x65\x96\x2e\xe2\xe2\xa5\xa9\x52\x1b\x6c\xc1\x9f\xfa\x87\xda\x88\x0c\x09\xcd\x81\x53\x83\x04\x68\x00\xc6\xab\x45\x92\x6c\xc1\xff\xce\x07\xae\x92\x43\x59\xf2\x26\x3b\x8d\x1d\x91\xb4\xde\xf3\x4e\x48\xc5\x1e\x17\x29\xdf\x38\x98\xec\xe3\xe0\xaa\xa1\x6e\x2a\xf8\x3e\x94\x5a\x10\x4a\xca\xea\xb8\xaf\x25\x85\xbc\xc5\x87\x7f\x3f\x29\x1c\x25\xa8\x31\xd4\x17\xd7\x3c\xc8\x45\x4d\xd9\x8e\xe9\xb4\x38\x38\x2c\xee\x5a\x5c\x65\xef\xc7\x73\x67\xc9\xa6\xca\xb0\x48\x24\x74\x8e\xeb\x31\xba\xce\x64\x9c\x3f\xff\xd6\x7d\xca\x5d\xdc\xc9\x6a\x0b\xc3\x86\x0f\xc2\x7e\x24\x92\xb0\x45\xde\xc3\x5a\xbe\x70\xf6\xe8\x26\xa9\x61\x4e\x77\xf2\x68\x34\x87\xad\x07\x89\xb6\xcc\xb6\x68\x5d\xb3\xbe\x5a\x35\x39\x00\x93\x46\x3d\xa5\x28\x5d\xb2\x3c\x81\xd5\x81\xe2\x5c\x75\x5e\x13\x9e\xcb\xcc\xe9\xfd\x28\xb8\x9a\x54\xb5\x99\x1b\xed\xd2\xc9\x9d\xc1\x4e\x2b\xdb\x69\x70\x58\x7b\x8e\xb4\xd1\x8d\x7b\x8e\xd8\x2b\x87\x14\x52\x12\xfa\x3d\x82\xd6\x3d\x4c\x0c\x1d\xc2\x16\x2b\x66\xfe\x87\x24\x47\x6d\xf9\x1e\xb1\x96\x11\x8b\xd7\xee\x9d\xe2\xb4\x61\x4f\x3b\x81\x1f\x9c\xc3\xc3\x3b\x40\x81\x01\x56\x34\x90\x38\x7d\x2a\x61\x17\xee\x22\x8a\x9c\xf7\xd3\x4a\xd4\xdf\xf5\xa1\xc0\x68\x44\x94\xd9\x05\xe7\xcf\xdd\xb9\xe8\x96\xb3\xb0\xa8\x7a\x89\xea\x69\x11\x85\xe8\xc6\x45\xfe\x2a\xb6\x1e\xbd\x81\xec\x5d\x3f\x8e\xf3\xe9\x61\xbe\x7f\x7c\x2c\x3c\x40\x15\x68\x75\x1d\xe7\x25\xb1\xe2\xb7\x7e\x38\xde\x3a\x4c\x5d\x45\xe0\x13\x98\x71\x48\x75\x77\x19\xb9\xa3\x51\x4e\xbd\x4e\x44\x73\x57\x32\xe9\xdc\x8e\xbd\xa8\xe0\x12\x9a\x7d\x26\x34\x2b\xc3\x90\x58\xe0\xb2\x18\x40\x6f\x1f\x76\x6d\x98\x91\x50\xad\x8e\xe9\xd8\xb0\x46\xeb\x0b\x3f\x03\x32\x74\x84\x9c\xd4\xd9\xe1\x2a\x5c\x8d\x19\x10\x1a\x32\x75\x6f\x2e\xcb\x76\xe0\x3f\x90\xa7\x5e\x72\x3c\xef\x90\x21\x1d\x95\x77\x06\x80\x2a\x57\xd9\x69\x80\xac\xd3\x34\x74\x98\x37\x0c\xb2\x67\xa5\x82\x42\x53\xcd\xdd\x20\x4a\x32\x64\xc4\x22\x08\x67\xfe\xc3\xfd\x98\x21\xc8\xb8\x1d\x65\x2c\x36\x9d\xad\xa2\x7f\xa9\xda\xfb\x26\xab\x32\x6b\xfc\x02\x13\x48\xd9\x75\xd4\xc1\x5d\x8f\xc3\x8d\xff\xfd\xe1\x85\x62\xf4\xde\xf0\xce\xfd\x94\xa2\xab\x1c\x9c\x85\x48\x28\x40\xfc\xfe\x97\xc1\xfb\x41\xa6\xc8\x1c\xa6\x72\xe7\x81\x5b\xbb\xbf\xc2\x75\xd6\x89\x1d\x51\x6d\x4b\xfd\xa0\x2e\xf3\xa6\xcb\x26\xf2\x7d\x79\x61\x49\xd6\xb4\xec\x1c\xcb\x8c\xbd\xe2\xad\x01\x47\xa4\xe2\x1a\x4c\x70\xfc\xf3\x98\x5d\x57\x31\x50\x84\x57\xa9\xc6\xad\x55\x75\x94\x55\x1e\x3e\xf4\x97\x63\xef\x31\xce\x87\x75\xba\xde\xf8\xa7\xc3\x70\x8f\xba\x7e\x75\x4a\x6b\xf3\x63\x4b\xd3\x63\x01\xe6\xb3\x47\x85\xa2\xfe\x9b\x53\x96\xef\x27\xcc\xb6\x25\xce\x77\xe4\xf0\xe4\x83\xee\xbc\xe8\xfa\x33\xef\x47\x05\x7c\xbd\x91\xea\x5a\xaf\xa9\x50\xea\x93\xc5\xda\xe9\x4e\x28\x59\xe0\xa4\xf2\xd2\x87\xf7\xa3\x66\xe3\x96\x0d\xfd\xa6\x06\x69\x7c\xa3\x8a\x7d\x17\xd7\xd2\x46\x26\x35\x0f\xbe\xa9\x69\x9f\xcd\x88\x98\xd9\x71\x02\x3c\x2e\xa5\x0a\xf4\x5f\x7a\x03\x7f\xde\xd9\x80\xdd\xb4\x96\xdf\x1e\x35\xa5\xcc\xc6\x96\x27\x20\xb0\x2c\x43\x40\x18\x17\x9d\x29\x05\x55\x49\x5f\xc5\x6e\xe5\xad\xe5\xed\x49\x1a\xd9\xb9\x3f\xe5\x22\xe5\xee\xcf\x70\xd3\xf3\xc2\xed\x19\xd8\x97\xdc\xea\xd9\x42\xa7\x34\xa7\x4f\x46\xbe\xb2\xdd\x02\x5b\xa1\x36\xa4\x9c\x23\x2f\x32\xcf\x85\xc9\x02\xee\x4f\x21\x66\x76\x92\x05\x85\xf9\x2d\xbc\x3a\x5b\xa7\xed\xd5\x0f\x21\x64\x9a\xf3\x95\x9e\xe5\xd1\x73\x5a\xbe\x0e\x1c\xd2\x3a\x8a\xbe\xeb\x79\xdf\xc5\xf1\x77\xd9\x0d\xa6\x1c\xf1\xdb\xc5\x38\x20\x3e\xa5\x00\xfd\x1c\x23\x0e\x15\xde\x62\x53\xf9\xb8\x46\x8a\x4c\x90\x3f\x7d\xf4\xbf\x48\xac\x56\xa1\x60\x4f\x91\x17\x78\x81\xf1\x73\x55\x1e\x8a\x6c\x09\x81\x36\x76\x87\x3e\x9a\xa3\x22\xfe\x95\x26\x58\x36\xc8\x59\xe7\x62\xd5\x34\x04\xee\x67\xf1\x18\xd5\x5e\x04\x5c\x09\xc1\x10\x25\x26\x89\x5f\x77\x22\x93\x9d\x05\xbe\x3e\x22\x2b\x2d\x79\x32\x2f\x13\xb9\x85\xda\x93\x58\xdd\xc8\x6d\x65\x83\x26\x99\xde\x18\x16\x22\x68\x75\xcc\xf5\xf6\x32\x72\x33\x19\xd1\xe1\x03\x9e\xe7\xe3\x46\x7f\xb5\x9d\xbf\xc6\x47\x54\xa0\xfe\xbe\xa4\x76\x22\x91\xf4\x33\x70\x9f\xdd\x3b\x4e\xf8\x3c\x3d\xee\x75\xfe\xdc\xb7\x07\x56\xae\x66\x8c\xfa\x49\x55\x0c\xd0\x45\xb1\x81\x4d\x08\x36\x35\x50\x60\x9c\xa5\xa6\x4d\x35\x0f\x49\x57\x2d\x98\x22\x19\xe6\xcf\x9b\x92\x57\xf3\x5e\xa4\x2d\x89\xbd\x3f\xb6\x35\x53\x4c\x23\xbc\x05\xfb\x7b\x37\x43\x2a\x5d\x1e\x25\x95\xd7\x94\xec\x15\xab\x0a\x05\x4a\x54\x38\x6e\xbb\x97\xf6\xd6\xf7\xcf\xbe\x2b\x0a\xc9\x64\x53\x3d\x39\x4c\x19\x95\x6d\xb1\x93\xab\x08\x4d\x67\xbb\x2e\xb3\x44\xc9\x06\x3a\x1a\x36\xe8\xb3\x4f\x9b\x58\x61\x8f\x2f\x9f\x12\x6a\x3b\x05\xf6\x2b\xbb\xbe\x6c\x35\x8b\x0e\x96\xb1\x1c\xd9\x26\xcc\x39\xe7\xec\x2f\x47\x1f\x95\x32\x95\x0b\x56\xf0\x91\x60\xd8\xb2\x53\x06\x22\x3f\x77\x4b\xfa\x58\x84\x8b\x50\x62\xe2\x54\x88\xc8\x6c\xa3\xd6\xcc\xd1\xc9\xf3\x24\xae\xd8\x78\x07\x18\xdb\x54\xd8\x39\xe9\x74\xc5\xd5\x22\xac\xe8\xf0\x2c\x6c\x5c\xb0\x8e\x9a\x4c\x57\x65\xf3\x31\x23\xa7\x3d\x4d\xbc\x60\x12\x30\x38\x28\x28\x10\xf2\xef\x0f\xaa\x11\x1e\x04\x46\x25\xbe\xa7\x1f\xe4\x5e\x51\x36\x28\x80\x41\xc6\xae\xa8\x58\xdf\xed\x53\x11\x39\x56\xf5\x14\x8b\xb5\x1f\xe1\xb0\x77\xe4\x27\xa4\x9f\x67\x65\x69\x6c\xb2\x34\x5f\x5c\xc3\xd4\x5c\x0e\x04\xab\x24\xc2\xb5\x5b\xb5\x24\x84\xaf\xe7\x76\xbc\xdb\xbd\x18\x45\x07\x72\x75\x0b\x19\x82\x9f\x1b\x77\xee\x9c\x53\x38\x32\xd5\x88\x6c\xad\xcd\xe2\x73\x97\x3a\x13\x1c\x53\x8f\x50\x40\x74\xee\x62\xc6\x44\x92\x5e\x66\x68\x13\x3f\xe7\x66\xc0\x1b\xb2\xf8\x47\x7a\x57\x21\xb8\x20\x45\x78\xb8\x0b\x7b\xec\x8c\x97\xbd\xd8\xb0\x84\x44\x19\x28\x8b\x22\xcd\xd3\x1b\xb0\x28\x92\xa0\x2c\xca\x63\x51\xc7\x9c\x94\x63\xe0\xf8\xb0\x21\x43\x07\x95\x38\x8d\x58\x38\x7d\x56\xa5\x0d\x47\x1a\x85\x6e\x14\x67\xba\xff\x81\x57\x23\x22\xcc\x5d\xc9\x15\xf6\xc6\x35\x4d\xee\xb5\x5a\x4b\x50\xd3\x15\xb8\x60\x51\xac\x64\x28\x46\x74\xf6\x7a\x4e\xd6\x7e\xe9\xf1\x93\xc7\x82\xb9\x1f\xad\xf1\x79\xbd\xe5\x72\x0a\xfc\x48\xd7\x4c\xca\x49\x79\x4f\xe3\x64\x81\xf0\xa4\x5b\xa2\xaf\x1d\xf5\x03\x2d\xef\xc1\x03\xba\x1f\x44\x0b\x74\xd7\x31\x5e\x40\x0e\xfc\x2e\x73\xeb\xf8\x7f\x00\x03\x40\xfc\xbf\xa6\x36\x2d\x4e\x4d\x76\xce\x4d\x24\xfb\x19\x63\x35\x30\x67\xb6\xcd\x1b\xb8\x68\x51\x36\xab\x14\x07\xb6\x00\xe3\xd4\x31\xfd\xb1\xfd\x42\xff\x95\x6e\xd7\xe4\xee\xc3\x57\x5f\x75\xb8\x73\xda\xce\x3b\x42\xd9\xee\x45\xae\xcc\x1c\x02\xe3\x67\x97\xf5\x7d\x5c\xa5\xfd\xff\x22\x5c\xf1\xa5\x61\xa0\xa6\x1a\x9a\x51\x3d\xbb\x23\x96\xec\xda\xcd\xa7\x9d\x99\xef\xd5\xbe\x76\xc7\xfe\xb3\xa3\x8d\x31\xea\xc5\x8a\x53\xaf\x59\x28\x52\x2e\x69\xed\x5b\x81\x8c\x39\x02\xf8\x0b\xc5\xfa\x4a\x64\xe7\xd1\x51\xd3\x9c\x3c\x0b\x12\x30\x40\x42\x8e\x4e\x79\x61\xfc\x29\xbf\x6a\x04\x30\x56\x68\x9f\x32\xec\xac\x84\xc7\x73\x01\xed\xd2\x4f\x00\x9d\x65\x50\x1e\x35\x3e\x49\xae\x93\x7e\xaf\x91\xea\xa9\x31\x21\x00\xc6\xfb\xa1\xff\x2d\xbc\x06\x41\x38\x61\x67\xc4\x6a\xca\x4e\x71\x5e\x37\xac\x36\xea\xc3\x65\xab\x13\xb0\x2f\x89\xec\xbe\x87\xdd\xb3\x52\x75\xd4\xa2\xc1\x5a\x26\xfd\x55\xa1\x45\x4a\xa9\xb8\x6c\xb6\x70\x9e\x59\x6f\x9e\x3c\x32\xe9\xb9\x22\x15\x5f\x9c\xec\xf4\x14\x3a\xd9\xe9\x39\x37\xde\x39\x66\xb2\xd9\xda\xe9\x98\x8e\xb3\x00\x88\xb3\x2e\x04\xb5\x21\x0d\x68\x49\x17\x1b\xda\xc2\x34\x0d\x52\x6b\xa5\xf3\x43\x6a\x11\xae\x47\xd3\x42\x75\x0c\x2b\x62\xfa\x98\x99\x74\x51\xf5\x50\x12\x9d\x75\x08\xd1\x2f\x0c\xd0\x90\x31\xfa\x99\x54\x18\x5a\x35\x1c\x97\xe5\x95\xf4\xdb\x01\x87\x56\x3a\x1c\x2b\xd1\x7a\x70\x82\xe3\x38\xfa\x88\x6a\x84\x8e\xa7\xb1\x79\x5c\x53\x54\xa4\xe9\x21\xa9\x7a\x08\x72\x81\xe3\xf8\xf9\x75\x38\x59\xdb\xb8\x24\xfd\xf8\x13\xd5\x85\x84\x46\x95\x75\x46\x59\x13\xdd\xf1\x0c\xca\x54\x6a\x1c\x0a\x02\x2b\x5b\x6b\x8c\x6a\x60\x18\xe2\x47\xc5\xa6\xa2\xf5\x2b\x91\x79\x6c\xd3\xd6\xa6\x59\xeb\x8b\x8d\xf1\x8d\x34\x14\x52\xab\xe7\xd4\xd3\x2c\xb6\x2b\xaa\xe9\x68\x22\xad\x29\x3d\xa8\xac\x55\xcb\x3e\xce\x10\x1e\xad\xaf\x79\x56\xcf\xcb\x95\x21\xcb\xd8\x56\x5d\xc9\x5a\xeb\x38\x47\x5f\x0a\x17\x6a\x57\x0b\x1b\xae\xb2\x70\xa8\xa6\x48\xea\xf4\x20\xd6\xac\x51\x36\x50\xa8\x1e\xe9\x38\x3d\x77\xb0\x51\x39\xbb\x5d\x57\x8c\xcc\xf2\x38\x30\xc0\x9d\x39\x9f\x1e\x9c\x11\xfd\x12\x7b\xb9\xd1\x7a\x0f\x16\x24\xc5\x35\xeb\xce\x70\xbe\x2b\x94\x8d\xd2\x83\x44\x25\xea\x94\x92\x8a\x18\x2d\x91\xe4\xf5\x16\x14\x52\x60\x35\x43\x62\x4a\x69\xa5\x95\x68\x82\x45\x49\x40\xa7\xb9\xdc\xf4\x78\xa0\x51\x40\x87\xb9\x2d\xd8\x4a\xb3\xc3\x7f\x89\xfe\x68\xea\x6e\x94\xa2\xd7\x90\x21\x37\x93\xfb\x87\x23\xd7\x9d\x8e\xba\x59\x0a\xd1\xa3\x58\x10\xad\xa1\x9e\x16\x99\xa6\x05\x32\xec\xcf\x4d\x8d\xe9\x89\x6e\x89\xd2\xc6\x94\x18\xa4\xd2\xcd\x69\x26\x82\x23\x69\x85\x78\x32\x6e\x8f\x42\x85\x02\x80\x7e\x8c\xd2\x23\x9d\xf2\x7d\x32\x6e\x29\xcd\xb0\x13\xda\x2e\x77\x06\xb6\x14\xc9\x03\x6f\xb1\xc8\x14\x42\xe0\xa1\xc6\x1e\x19\x1f\x28\x93\xd6\x0c\x59\xc7\x6b\xa1\x22\x16\x1b\x8a\xbb\x35\x6e\x11\xb3\xf7\x47\x19\x0d\x50\x54\x46\x8b\xa3\x84\xb8\x3b\x93\x4e\x89\x51\x40\xf7\x28\xe3\x9a\xe5\xa5\xa3\x24\xba\xea\xe9\x25\x6c\x37\x51\x18\x3f\x8e\xca\x6c\x52\x1a\xbe\x1b\xb1\x50\xe4\x66\x42\x12\x21\x77\x9a\xd2\xa4\x4a\xc6\x9d\x61\x95\xc3\xae\x47\xdb\xd9\x8d\x00\xf1\x4a\xa6\x20\x83\x76\x4b\x1b\x8d\x67\xea\x01\x57\x4f\xd3\xac\x94\xbb\x4c\x5f\xe9\x24\x9b\x90\x74\x88\xb1\x9b\x61\x8c\xe8\x5b\x21\x69\x26\xfe\x1e\x4d\x17\xed\x3e\x4a\x16\xe2\xa1\x4c\x42\x66\xdd\x52\x81\x04\x16\x9e\xba\xa0\x25\xb5\x0c\xdb\xa3\x36\x21\xe1\x6f\xac\x06\x0b\x99\x86\xad\x22\x16\x04\x24\xda\x2c\x4a\xbd\x1d\x7b\x08\xf1\x12\x6c\x32\x22\x51\x6f\xc1\x06\x83\x88\xb0\x15\x23\x42\x04\x51\x27\x21\x22\x12\x11\x13\x23\xb1\xda\x0c\xa2\x9e\x48\x02\xb2\x3a\x89\x2e\x09\x6f\x09\x99\xfd\x3c\xf1\x01\x39\x2a\x61\x24\x0a\x3c\x31\xca\x94\x2f\x2d\x0a\xe1\xaa\xa0\x28\x4a\x26\x82\x89\x1e\x99\x24\x12\xb2\x0a\x66\x5e\x6f\x90\x05\x0b\xd1\x9b\xf4\x3c\x6f\xb2\xea\x0c\xc8\x6e\xd3\x21\xbd\xa0\xd3\x11\xbf\x41\xae\x96\xaa\x45\x01\x19\x0d\x66\x6c\x11\xb1\xd9\x00\x35\x0a\x82\x8e\x48\x01\x03\xef\xb5\x0b\x3c\x8f\x08\x6f\x21\xcd\xad\xa2\x28\xd8\x70\xbd\x4e\xb0\x88\x12\x74\x48\xc2\xbc\xd5\xa2\xb3\x89\x07\x2e\x96\x04\x1e\x03\x61\x2e\xa2\x26\x19\x13\x33\xb2\x21\x22\x49\xd0\x3a\x4c\xec\x66\x73\x10\x5a\xee\x30\x41\x95\x3a\xec\x41\x88\x20\x52\x45\x10\xe6\x45\xec\xb3\x62\x22\x60\xac\x83\x5c\xc4\x60\x71\x62\xd1\xa6\xd3\xbb\x45\x41\xc4\xd8\x6c\x72\x12\xa1\x5a\x67\x30\xd9\x05\xab\x5f\x0a\xcb\x58\x30\x4a\x58\xf0\x09\x90\xd0\xa9\xb3\xd4\x39\x04\x82\x31\xaf\xc7\x22\x42\x4e\x2c\xb8\x05\x62\x86\x71\xc2\x48\x2f\x62\xa3\x49\x96\x10\xbd\xf2\xaf\x97\xcc\x32\x15\x26\x30\xf1\x98\x36\x1e\x86\x11\x49\x4d\xa2\x55\x12\xb0\xe0\x25\x55\x02\x81\x9e\x09\x06\x6c\xd4\x49\x3a\x44\xff\x59\x25\x83\x01\x59\xec\xbc\x4b\x94\x78\x04\xc3\xad\x97\x04\x41\xd0\x9b\x74\x92\x50\x47\x24\x4c\x78\x37\xb6\x13\xe2\x30\x1b\x6c\xc4\xa4\x27\x76\x6c\x75\xdb\x8f\x9f\x78\x80\xc8\xc4\x21\x22\x49\x6f\x23\xd8\xc0\x1b\x45\x89\x4e\x15\x46\x2e\xab\x60\xd2\x1b\x45\x01\xc3\x62\x12\x88\x55\x6f\xe1\xcd\x18\xe6\x0e\xcb\x98\x27\x92\x5c\x8d\x79\x9b\x0d\x9d\xa5\xa0\xa4\x7e\x0f\xd9\x91\xc1\x84\x24\x9d\x28\xea\x64\xec\x46\x00\x16\x6e\x64\x33\x03\x48\x61\x18\x7a\xbd\x97\x08\xd0\x13\x49\x14\x0c\x06\x8c\x10\x8c\x2b\x46\x82\xc8\x23\xde\x26\xf2\x7a\x1d\x16\xf4\xbc\xa8\x97\x89\x68\x11\x24\xbb\x59\x67\xe3\x75\x2e\x91\xdd\x03\xc0\xd8\x58\xab\x04\x9d\xde\x6c\xd6\x0b\xc8\x62\x25\xa2\x87\x4e\xac\xd5\xc4\x5b\x05\x2f\x8c\xa5\x81\x2a\x57\x38\xa0\x02\x00\x07\xe4\x01\xb8\xab\x42\x56\x9d\x05\x99\xac\x30\x66\x92\x5e\x82\x40\x03\x8f\x60\x5e\x79\x27\x2f\x54\xf1\x7a\x82\xa0\x05\x3a\x68\x06\x0c\xb7\xd5\x07\x4d\xd0\x23\x8b\x24\xd8\xf4\x3c\x11\x45\x93\x48\x2c\x30\x92\x0b\xee\x95\x10\xb2\x41\x17\x8c\xc8\x6f\xe7\x61\xce\x2c\x30\x8d\x28\x10\xe5\x91\x69\x22\x21\x31\x1d\xc2\x94\x5f\x12\x12\x45\xbf\x1e\x36\x33\x9a\x07\x3b\x1b\xab\x78\xc1\xc5\x13\xa8\x4d\x72\xd9\xdc\x58\xac\x76\xe9\x75\x61\x51\x32\x8b\x06\x0c\x83\xce\x43\x5f\xeb\x79\x59\x87\xcc\x0e\x23\x11\x1d\x22\x2f\xe8\xbc\x98\xd4\x58\x83\x48\x0f\x70\x23\x39\x78\x9d\x97\xe8\x31\x40\x31\x40\x00\xe0\x0a\x36\xb3\x09\x5a\x20\x13\xab\x8e\x10\xcc\xeb\x1a\x6d\x86\xa0\xdd\x86\xad\x04\x51\xfb\xa5\x00\x8d\x44\x2f\x1a\xcd\xc8\x2e\x54\x3b\x08\x4f\x00\x7c\x89\x60\x31\xc4\xc0\x65\x37\x4a\x3a\xbd\x5e\x47\x1c\xb2\x1e\x09\x3a\x5e\xb6\xe9\xa1\x26\x23\xb1\x61\x93\x41\xa7\x93\x24\x11\xc3\xa8\x0a\x3a\x64\xe4\xb1\x19\x7a\x00\x2b\x0d\x61\x83\x28\x0c\xdf\x1e\x7e\x04\xea\x01\x64\xc1\x44\x5b\xab\x83\x69\xa6\x90\x46\xa0\x02\x58\x56\x58\x14\x00\x8a\xab\x44\x58\xb9\x46\xac\x27\xbc\x0d\x3a\x43\x0c\x71\x73\x9d\xbd\xca\xea\xe6\xa5\x6a\x1d\xd3\x8e\x70\x9d\x71\x89\xb7\x32\x9a\xc9\x45\x35\x21\x4b\x28\xbe\xbe\xa8\x91\x4b\xe5\x57\x6b\x01\xcc\x99\xc4\x04\x67\xe3\xd8\xb7\x28\x9c\x92\xe0\xf2\x68\x9f\xa3\xd0\x50\x2b\xfc\xb9\xc2\x52\xaa\xa3\xba\x5e\x51\xf0\xb1\xe8\xc3\xf8\x2d\x4f\xcb\xbb\xf7\x68\xca\x40\xed\xbb\x26\xd8\x6c\xea\x6f\xbe\x25\x3c\x78\x93\xde\x6a\x2f\xde\x85\xfc\x1e\x92\x47\x36\x52\x2d\x56\x7c\x6c\xcd\xc3\x68\x7f\x74\xea\x1d\xcf\x69\x4c\xa5\x60\xad\xb1\xde\x78\x6c\x68\x03\x59\x39\xd3\xc9\x55\x7e\x93\x53\xd3\xe3\xa8\x86\xd3\xb5\x03\x28\x97\x60\x2a\x88\x4a\xbf\x0b\x7c\xcb\x75\xac\x9f\xe7\x28\xee\xaf\xe6\x78\x6e\x18\x5c\x54\x9a\x10\x7f\x22\x4b\x90\xcc\x4c\x3f\xfc\x0d\x67\x4b\x6c\x2f\x6a\xfe\xe2\x0f\xe7\xf2\x50\xda\x5b\x00\xda\xfb\x26\x81\x63\x72\xaa\x6e\xa9\x6c\xe6\x8e\x2a\x1c\xb3\x6f\x45\xc5\x85\x9b\xec\x75\xaa\xcc\xac\xdb\x9d\xe1\x64\x55\xa6\x1f\x81\x12\xb8\x46\xfe\x57\x0d\x35\xaa\x5c\xf0\x31\xc3\x76\x9c\xec\x43\x7f\x40\xef\xd7\x34\x50\xa5\x62\xbe\x7c\xcf\x4d\x98\xdc\x65\x0b\xfb\x5e\x49\xc5\x18\x04\x5d\x25\x9b\x53\x21\x57\x90\x7d\x87\x60\xec\xd5\x2a\xa6\x5f\x10\xe0\xf8\xe2\xb7\x55\xe8\x15\x3c\xfd\x10\xfa\xc0\x19\x28\xfb\x63\x6e\x75\x2f\x1a\xd0\x58\x78\x68\xa0\x77\xb5\xc0\xe5\x0a\x9c\x1a\xd0\xd8\x29\x83\xb4\x6b\x83\x30\x04\x54\xf1\x24\xd7\xbb\x5a\x33\x0a\x5e\xfa\x5e\x76\x91\xa7\xcf\xe9\x31\x65\x13\xb8\x46\xbe\x0c\xa4\x67\x27\x50\x89\xf1\x94\xa6\x4a\x41\x52\xe9\x23\x46\x9a\xcd\x2c\x2b\x04\x45\xb5\xf1\xa0\x19\x59\xac\x40\xd4\x27\xd0\xe5\xf7\x43\xa7\x4b\x1f\x0c\xba\x5f\x7d\x42\x7d\xe2\x7e\x3a\x40\xc5\x8f\x01\xdd\x8f\x2e\x87\x00\xd9\x67\x32\xc5\xe8\x1d\x1a\x4b\x83\x2e\x87\x4c\xec\x4b\x5a\x79\x9f\xc2\x2c\x80\x91\xdf\x8d\x9f\xaf\x36\x3a\x26\x17\x35\x00\x46\x73\xd1\x14\xac\x6e\x96\x82\xd6\x2d\xc8\x9a\x5c\x25\xc7\xec\x9c\xdb\xb9\x49\xdc\x64\x6e\x0a\xb7\x98\x5b\xc9\xb8\xf9\x94\x40\xb1\x69\x9c\x84\x0c\x35\xac\x5d\x96\x69\x17\xa8\xf4\x8b\x76\xf3\x24\x94\xb8\x74\xa5\xaf\x57\x33\xd3\x11\x4c\x5c\x89\x09\x10\x43\x5e\x5c\x4c\x81\x17\x3e\x7d\xd5\x1d\x8b\x36\xdf\x2c\xf6\xed\xe8\x98\xda\x2b\xf0\xb9\x03\x37\x0e\x1f\xba\xf1\x80\xe4\x0a\xa4\x67\xac\xed\x32\xf4\x2e\xb8\xe3\xae\x3b\x16\xf4\x1a\xba\xd6\xce\x48\x07\x5c\xd2\xb0\x66\x97\x8f\x2c\x2d\x4a\xc7\x92\xe0\xe6\x45\x77\x5c\xf5\xf4\x42\xa1\x77\x6a\xc7\x8e\x3e\xf1\x66\x4d\xf8\x11\x03\x14\x2e\x9c\x87\x2e\x6b\x6c\xf2\x44\x6a\xee\x2e\x58\x76\xdc\x7d\xf7\x8e\xd4\xda\x6d\x57\x5c\x3a\x35\xd6\x94\x6a\x82\xbf\xd8\xd4\x4b\xaf\xd8\xb6\x56\x88\x33\xd9\x42\xb5\xae\xf8\xa9\xec\xc2\x53\xf3\x16\xde\x24\x6c\xbb\xbb\x26\xe2\x69\x6a\x44\xeb\x59\x64\x49\x4f\xed\x7e\x71\xb3\xf0\x21\x17\xe4\xa6\x72\x57\x17\xad\xa5\x00\x29\x5c\xcb\x33\xb2\x0d\x48\xb1\x11\xc3\x2e\x69\x54\x32\xfc\x52\x0a\xcb\x94\x44\x83\x88\x27\xcd\x69\x9a\xf8\xda\x3e\x13\x2d\xda\x00\x28\x2a\x8f\x51\x1e\x8b\x87\xb9\x84\x17\xfc\x6f\xf8\x63\x8d\xb5\x24\x60\x94\xa5\xb6\x98\xb5\xca\x67\xaa\x23\x41\xff\x89\xea\x86\x98\xff\xa0\xbf\x30\xc5\x7f\xc2\x1f\x8b\xd6\x1c\xf4\xfb\xdf\xa8\x6e\x18\x9b\x8a\xec\xba\xe8\xe0\xe2\x1d\x37\x2e\x3e\xb1\x78\xf9\xf2\xa5\x3b\x77\x2c\x79\x63\xc9\x18\x3f\xca\xc6\xa0\xf4\x00\xa9\x33\xf9\xaa\xac\xb1\x36\x49\x36\x82\xbb\x31\xe6\xff\x71\xb5\xef\x80\x1f\xff\x09\x1c\xfe\xea\x03\xfe\x28\x24\xaa\xae\x1b\x9d\xa8\xf0\xf6\x87\x8b\x0f\x2c\xbe\xe8\xc7\x8b\x77\xdc\xb4\x74\xf9\x72\x28\x79\xb4\xb7\x68\xe3\x32\xc7\x6c\x7b\x73\x1a\x5c\x70\xd4\x40\x0b\x35\xa9\x48\x3f\x88\xa5\x5d\xc3\x4a\xb5\x48\xca\xbd\xfd\xd4\xe9\x3c\x6c\x97\xf7\x6e\xc5\x68\xc2\xc9\x27\x11\xea\x98\x31\xb0\xfe\x50\xc3\x6d\xcf\xa3\xdc\x53\x6f\xc3\x1e\xba\xe7\x37\x69\xbf\xf5\x24\x9a\xf0\xc2\xbd\xdd\x87\xd6\xf7\xf5\xd4\xfe\x04\xe8\x8d\xeb\x61\xcd\x99\x99\x7e\x7d\x90\x5a\x7d\x67\x50\x97\xd1\x24\xfb\x8b\x92\x36\x4d\xf4\x18\x08\xa2\x68\xca\x1e\xb2\xbb\x84\xbf\xb7\x4d\x5f\x7f\x3a\xb7\x7e\x7a\x1b\xfa\x7b\xb6\x64\x5a\x4b\xf1\x65\xd5\xf7\xd4\x0f\xf1\xbf\xaa\x1f\x3a\x73\xcb\x2f\xde\xb5\xeb\x62\x52\x85\xee\x2b\xca\xa4\x6d\x99\xa6\x2e\x46\x5f\xac\x8b\xa0\xfb\xd4\x2d\x11\x6d\xdb\x41\x45\xd9\x4c\x89\x9b\xc7\xad\xe2\xd6\x73\x3b\xb8\x3b\xb8\xfd\x5c\xd9\xe6\xbf\x80\x18\x7f\x91\xed\x71\x0c\x39\xb7\x14\x97\x3a\xc3\xd9\x13\x4c\x30\x97\xc9\x68\xd6\xb3\x6f\xc8\xb0\xeb\x68\x86\x6d\x53\x21\xe1\xe2\xa4\x53\xe6\x62\x9a\x99\xe1\x66\xe4\x44\x22\x4e\xba\x99\xc9\x20\x28\x8b\xfa\xa8\xb5\x15\x28\x84\x59\x71\x47\x12\xe4\x8a\x22\x97\xc4\x8c\xf9\x83\x3b\x43\x6b\x25\x1a\xe3\x0c\x6d\x44\xa7\xfd\x44\xa8\xcd\x99\x6d\x76\x4b\x61\xde\x35\x3a\x1e\x70\xe2\x35\x8b\xf7\x3c\x70\xd7\xd2\x15\x46\x69\xcd\xa2\x3d\x07\x16\x4f\xd3\x9b\x77\xee\x34\xeb\xa7\x2d\x3e\xb0\x67\xd1\x1a\x49\x68\x68\xba\x68\xef\x03\x7b\x16\xaf\x91\x20\xa5\xee\x1a\xfc\x65\x8b\xdd\x66\xce\xd5\x0a\xc4\x7f\x7a\x55\x73\x7c\xe1\xaa\x2b\xe6\x44\xb5\x57\xf3\xc2\x78\x73\x74\xce\x15\xab\xb4\x17\xb2\x0c\x04\x2d\xf3\x7d\xc4\x22\x00\x9e\xf4\x8b\x01\x3c\x04\x3b\xe6\xa0\x1e\x70\x3e\x0b\xef\x23\x03\xb9\xc2\x3f\xbe\x84\x8d\x58\x3b\x24\x7d\xea\x75\xce\x70\xc8\x96\x05\x94\x6f\x77\x2f\x8f\x26\xb5\xce\xbd\x27\xb5\x64\xde\x92\x9b\xfa\xef\x4d\x2d\xa9\x33\xeb\x67\xcf\xd6\x9b\xeb\x96\xa4\xee\xed\xef\xd8\x18\x9d\xbf\x24\x79\xef\xdc\xd6\x49\x88\xef\x45\xbb\x75\x52\xd6\x16\x0a\x3b\xf7\x35\xee\x49\x74\x84\xe9\xa3\xd0\x91\xd8\xd3\x18\x66\x0f\x3c\xd8\x6e\x0c\x3b\x75\x2d\x3e\x62\x03\xb4\x08\xfd\x7b\x00\x67\xb3\xea\xc2\x2d\x03\x3a\xcc\xf3\x36\xde\xa7\xe6\xb3\xe8\xf0\x3e\xc2\x6b\xf7\x30\xda\xb9\x51\xc7\xd5\x73\x11\x2e\x41\xbf\x2c\x31\xea\x1e\xa6\x78\x42\x96\xb4\x55\x5c\xf6\x74\x42\x42\x41\x3d\x0a\xca\xf4\x10\x29\x7e\xa2\x33\x99\x2e\x7b\xc4\xc1\xd2\x8d\x50\x61\x88\x7e\x11\x02\xd1\x4f\x42\x50\xbb\x02\xd3\x3a\x73\xea\xcf\x51\x53\x81\x3d\xbf\x8b\x3a\x55\x66\x99\x00\x73\x31\xf2\x4b\xcd\xc9\x97\x4d\x0a\xa0\x40\xf1\xdb\x13\x90\x19\xca\x50\xbf\x1e\xfb\xb9\xfa\x73\xfc\x79\xf5\xe7\xea\x67\x51\x27\xd5\x29\xa2\x5f\xad\x40\x5c\x6c\x60\xf8\x1f\x7c\x4e\xf3\x31\x9e\x36\x7f\x66\x8f\x70\xb3\x70\x33\xb3\x02\xed\x2c\x59\xd5\xd0\x2c\x77\x14\x05\xf4\x8b\x5a\x1b\x88\x31\x9b\x92\x15\x7e\xd7\x98\xf4\xc2\xcd\x4f\x6e\xbb\xf3\x8a\xe1\xbf\x6f\x79\xeb\xa9\x27\xaf\xc7\x97\x18\xba\x6c\x66\x43\xe1\xe9\xf9\x57\xae\x3f\xd0\x4f\x74\x3d\x8b\xb2\x4b\x7a\x0a\xdf\xf4\xd5\xd7\x28\x55\xe8\x51\x43\xb7\xcd\x64\x50\xaf\xec\xb9\x6e\xd1\xf2\x2e\x3c\xfd\x8a\x87\xb7\x3d\x79\x05\xd1\x5d\xff\xf8\x53\xff\xb6\xa5\xf0\xb4\xc1\x64\xeb\x32\xe0\x4b\xe7\x1e\x5a\x7f\x75\xff\xf0\xdf\x7b\x96\x64\x17\xf5\xe0\xe9\x5e\xa5\x26\x50\xad\x5e\x09\x71\xdd\x06\xf4\x68\xd7\xf2\x45\xd7\x41\x61\x6b\x46\xc9\xf6\x51\x1d\xed\xe9\xda\x37\x3e\x98\x3c\x1f\xfb\x7e\xcc\x88\x5e\xbf\x3d\x51\x62\x79\x8d\xd5\x41\x1d\xab\x73\xe7\xa1\x58\x1a\xfd\x20\x10\x47\x72\x39\xa7\x41\xfd\xa3\xa1\xd5\xaa\xdd\xc8\xe5\x60\xb8\x09\x0c\xb7\x9a\xab\xd0\x0c\xce\x95\xbf\x4d\xca\x86\xdf\xeb\x8f\xb1\x8f\x13\xe5\x2c\x93\x0c\xa8\xca\xe0\x2c\x29\xf6\x9f\xe6\x34\x4b\x11\x98\xab\xb8\xdd\x91\x87\x59\xac\xc0\xbe\x5a\xaa\xfe\xc9\x3f\x30\x4a\xf7\x64\x5c\x3b\x7c\x95\xd7\xeb\xfc\xc0\x68\xb5\x15\xed\x7e\x8e\xdd\x6b\x69\xf6\x8e\x3f\xb5\x65\xef\xd1\x76\xfe\xce\xe5\xae\xb0\xde\xfd\x87\xf1\x9c\xec\x8c\xcf\x4b\xd4\x0e\x83\x76\xbf\x16\xe5\x32\x14\xa3\x29\x69\xb0\x39\x4a\xb7\x86\x63\x6a\xe7\xce\x11\x7e\xb6\x55\x69\x76\x6f\xa8\xfd\x09\x1f\x56\xde\xb4\x9d\xca\x8d\x13\x58\xe9\x7e\x83\x65\x43\xf7\x6b\x06\x86\x07\xcb\x86\x94\xc9\xef\xc6\x86\xa0\x11\x4b\xd3\xda\xb0\x5a\x99\x6e\xe9\xdf\xb9\x5a\x58\xf1\xfd\xb0\x6b\x6f\xe4\x6e\x86\xed\x80\xad\x82\x8c\xb6\x3a\xa4\x68\x37\xce\xa4\xea\xc5\x10\xfb\x90\x15\x9c\x47\xb2\x2b\xc8\x98\xae\xda\x7d\x49\xb4\x9b\x5d\x0e\x53\x66\x6e\x22\x75\xb6\x21\xf2\x60\x2a\x91\xa4\xd8\xa6\x28\x45\x33\x09\xfb\x05\x07\xe1\x96\x4d\x0b\xd7\xf7\x4e\x9e\x34\xb9\xa6\xe9\x6a\x9f\x6e\x52\x58\xb6\x4d\xb1\xad\x47\x73\x2f\x4d\x74\x62\xf5\x90\xd8\xd2\xdb\xdb\x52\x53\xd5\x1c\xba\xc8\x7b\x69\xfb\xec\x2b\xa6\x2d\x9a\x8e\x76\x09\x7f\xd6\xc6\xc1\x61\xd1\x06\x4a\xfd\xd2\x06\x84\x75\x8d\x33\xef\x5a\x2f\xbc\x57\x19\x53\x39\x5a\x4b\x16\xac\xea\x5d\x3e\xb1\xc6\x9f\xd5\xb5\x19\xa6\x36\x38\x10\x4e\x1d\x5e\x7e\xbd\x69\x0e\xce\x3e\x15\x76\x24\x96\x24\x9b\x26\x78\xaa\xaa\xdb\x3b\x12\x93\x17\xcf\x8c\x2f\x6e\xce\x54\x75\xaa\xdf\xd2\xc6\xcc\xe2\x90\xc9\x0d\x97\x5f\xde\x70\xa4\xc1\x64\x8f\xf4\xef\x52\x37\xaa\xb7\x94\x23\xc6\x8c\xeb\xc8\x5d\x8a\x95\x4b\x71\x6b\xd9\x5e\x3a\x4a\xb8\x31\xa2\x29\xc7\xa4\x35\xa3\xb0\xda\x07\x24\xa8\x32\x0d\x3b\xd8\xca\x97\x03\x24\x58\xb4\x96\x5b\xba\x8d\xd3\x14\x5a\x28\xde\x9c\xca\x68\xd2\x4a\x9e\xa2\xad\x37\x2a\xfd\x25\x32\x45\xe5\x8f\x99\x14\x23\xfa\x8e\xdf\xd3\x7a\xc7\x67\x10\x1f\xdf\xd6\x7b\xad\xc1\x68\x11\x4c\x4b\x2c\xf1\xd4\xf2\x9d\xd7\x4d\x9b\xda\xdb\xfb\xf3\xe9\xeb\xda\x23\xef\xa1\xc7\xa4\x06\x4f\x6b\x64\xd6\x82\xd9\x0b\x6e\xba\x6e\xe1\xfe\xc9\x56\x1d\xa5\x1b\xaf\xb4\xd6\x5a\x85\xd0\xc4\xa6\xee\x8e\xd9\xd9\xbe\xb9\x13\x5b\x16\xd6\xe3\xdc\xc8\xb7\xf7\xb2\xa1\x89\x6b\x56\xbc\x98\xdb\x25\x9b\xc2\xca\x82\x9b\x3a\x1d\xd5\x40\x53\x3e\xd4\xb6\xb2\xa3\x7d\xf9\xec\xa9\x53\xbb\x9d\xcd\x7e\xef\x19\x2e\x9a\xba\x76\x6d\x5b\x6b\xa8\xb9\xd5\xe1\xf2\xc4\x6c\x26\x9d\xc5\xbc\xb1\xb5\x56\x89\x4c\xc0\xf5\x73\x14\xdd\xe4\x48\xd8\xe5\xae\xf6\x75\x76\x4d\x5b\x32\xbb\xa6\x82\x2f\x7a\x39\xd5\xb6\x97\x95\x16\xcd\x10\x2e\xeb\x53\x3c\x23\x79\x5c\xa2\x36\x20\x6e\x97\x47\xae\xe8\xad\xd6\xe3\x66\x6d\xc8\xac\x08\x40\xcb\xe3\xce\x78\xca\x83\x45\xd3\xbb\x65\xf7\xc8\xc8\x69\x77\x58\xb0\xe1\x44\x95\xb1\x76\x0d\x5b\x23\x3a\x62\xae\xee\x4c\xee\xa9\x5f\xba\x68\x6b\x6d\x5b\x2d\xc2\x9d\xd9\x4e\xd9\x8c\x90\x45\x9c\x18\xea\x5a\x7e\xf1\xba\x65\x6d\x4d\xad\xf6\xb0\xdd\x25\x59\x81\xe6\x96\xeb\x9b\xae\xb0\xe0\x25\xaf\xf7\xef\x00\x5a\x7f\x62\x74\xb6\x68\x25\x3a\x8b\xe8\xb2\xfa\x94\x39\x7d\x1b\x36\x1d\x78\x6e\xdb\xf6\xce\x2e\xb7\xcd\x5e\x25\x2c\x75\x58\x46\x3e\xa3\x2e\x04\x31\x5e\x8e\x78\x89\x00\x8d\x6f\xc9\xea\xf5\x55\x96\x1b\xcc\x51\xf1\x1d\xf5\x4f\x37\xcf\xeb\x08\xb6\xf8\x1d\xc1\xb0\xbf\xad\x7d\xf6\xe3\xf3\xd7\x1c\x5c\xda\x31\xd5\x15\x42\x98\x2c\x35\x10\x33\x56\xcc\x92\xd7\x84\x8c\xa2\xd5\x27\xc5\x8c\xb2\x7a\xe7\x77\x36\xf5\x37\x4f\x69\x9f\x1c\x08\x36\xb7\xf4\xf5\x6f\x5f\xf0\x04\x9a\xfb\x72\x55\xf8\xd4\xed\xa5\xb9\x71\x70\x9c\xa1\x2c\xc3\x31\xf6\x9b\x02\xf7\x71\x4f\x69\x16\x23\x2a\xfb\x6e\x1f\xe3\x1f\x3b\x36\xff\xd3\xfe\xb1\xf5\x8d\xfd\x46\x28\xfd\x4e\x79\xc5\x27\xea\x2b\xdc\xa3\x63\x54\xee\xdc\x71\x9f\x3c\x65\xa5\x9b\x92\xbb\x4c\x16\x41\xa0\x22\x71\x65\x9b\x86\xe8\xde\xb2\x53\x1d\x71\x12\xcb\x78\xa1\x17\x4c\x50\x51\x18\x9a\x57\xf9\x85\x51\xba\x0f\x57\x9f\x79\xac\x68\x8f\x42\x66\xfa\x92\x4d\xd4\xc2\x07\x10\xbe\x28\xcc\xe4\xbd\x5b\xca\x76\x4c\x23\x9e\xff\xcb\xdb\x9b\x00\xb6\x51\x9c\x7d\xe3\x3b\xb3\x97\xce\x95\xb4\xab\xcb\x92\x2d\xeb\xb0\x24\xc7\x67\x6c\x59\x92\x6f\x2b\xb1\x73\x38\x71\x12\xe7\x4e\xc8\x65\x72\x3a\x0e\x90\x9b\x40\x42\x82\x08\xa1\x90\x70\x85\x00\xe1\x26\xe6\x2a\xd0\x90\x42\xb9\x79\x09\xad\xda\x02\xa5\xdc\xe1\x85\x52\x5a\x68\x4d\x4b\x79\x0b\x2d\x47\xdb\x97\x02\xb1\xb5\xf9\xcf\xcc\xae\x0e\x1f\x21\xbc\xef\xff\xfb\x3e\x88\xb5\xb3\xbb\xb3\xbb\x33\xb3\xb3\x33\xcf\x33\xcf\xf3\xfc\x7e\x78\xa4\x68\x03\xe0\x34\x5b\xe6\x87\x20\xb8\x41\xfe\x3d\x2c\x13\x4f\x9e\x14\x63\xe2\x8b\xa2\xc8\x72\x78\x7b\xf2\x95\x95\x2b\x3d\x1e\xf4\x07\x2e\x7a\xfe\xf9\xe6\x66\xf4\x47\xff\x41\x3d\x92\xbe\x53\x4d\xd0\xcf\x92\x6b\xdf\x89\xe1\x6b\xd1\xa5\x31\x7c\xad\xf8\xe2\x75\xe4\xa4\x67\xa5\x3c\x44\xae\x6b\x7e\x3e\xbd\x5c\x3d\x02\x3d\x6a\x82\xac\x3d\x24\xb2\xf2\xbf\x99\x72\x52\x33\xf2\x2c\xec\x18\x0b\x1a\xab\x78\xd9\xb0\x1c\x8b\x55\x60\x42\x01\xc5\x21\x82\xfc\x22\x01\x4c\x51\xfc\x90\x20\xd3\x4a\x63\x40\x28\x02\x8f\x11\xc9\x05\x7b\xcb\xaf\x82\xe4\x9d\x46\xed\x2f\xb5\xac\xe2\xda\x0f\xba\x34\x92\xe0\x33\x84\x69\xac\x94\x62\x4d\x36\x41\x87\x0d\x3e\x41\xd2\x20\xc5\x1d\x30\x5a\xc9\xf8\xa2\xd4\xe6\xee\x0f\xb9\x18\xa4\xc9\x28\xb1\x00\x10\x09\x8b\xe8\x7a\x63\xfa\xc7\x64\x97\x49\x0d\x51\x26\x87\xa0\xa5\x01\xc0\xbe\x12\xf8\x0f\x00\x5a\x2b\x38\x4c\x18\xd3\x54\x13\xb3\x57\xbb\xfd\xe8\x26\xae\x94\x02\x20\x90\x93\x61\xa6\x51\x19\x1c\x06\x3c\x10\x61\xd5\x1e\x87\x18\x11\x90\x22\x1a\xc7\xff\x2a\x46\x08\x95\x05\x53\x11\x29\x31\x87\x5e\x54\x8d\x7d\x75\xd0\x9c\x03\xe3\x35\x60\xeb\x0e\x87\x2d\x71\x27\x36\x6e\x68\x92\xb4\x95\xd6\xbe\x96\x0b\x7f\xda\xbb\xe3\x4f\xd7\xac\x7f\xf2\xe2\x25\xe5\xdd\x33\x3c\x1a\x68\x80\x9c\x25\x72\xe2\xc1\x9b\x1e\xdc\xbf\xa1\x65\x9a\xa0\x09\x3a\x62\xb5\xad\x0b\x0a\x56\x59\x98\xd7\xe5\x0c\x7a\xe8\x6c\xb2\x4e\xeb\x5d\x36\xc5\xff\x93\x70\xc3\xfe\x2f\x0f\x6f\x79\x69\x4f\x63\xcf\xee\x1f\xb4\xf7\xde\xe9\x35\x78\xf9\xf1\x9c\xc3\xda\x72\xd6\x4d\xef\xdd\x7b\xe9\x8f\x3e\x5f\xd8\x12\xd8\xbe\xb8\xb8\x76\xe2\x96\xf9\x9d\x35\xf2\xf2\xc9\x1b\x96\x80\x8b\x3e\x39\xa1\x58\x81\x72\x75\xeb\xca\x93\xfb\x33\xb5\x13\x15\x72\x30\xb5\x72\x64\xf0\xfd\xce\xca\x65\xf0\xa6\x94\xf8\xe1\x74\xf9\x7c\x87\xb6\xc2\xb6\xbe\xf9\x89\xbf\x4c\xde\xf5\x64\x5f\xef\x13\xbb\xcf\x2a\x9f\x35\xc3\x68\x63\x74\x2c\x67\xa9\x7d\xe3\xfe\x1b\xef\xbf\xbc\xaf\x19\x57\xce\x1e\xad\x69\x99\xef\x5c\xe9\xb4\x3c\x95\x1f\x63\xbc\x73\x91\xff\xe1\x70\x3d\x08\xff\x69\xde\x1d\x17\x76\x36\xf4\xec\xba\x6c\xe2\xda\xdb\xbd\xac\x4e\xa8\xb0\x38\xa4\xd6\x45\x87\xdf\xb9\xfb\x92\x07\xfe\xbe\xb0\xd9\xbf\x7d\x61\x71\xcd\x84\xcd\x73\xa7\xd6\xc8\x2b\x57\xdf\x9a\x0d\x44\xce\xd9\xb6\xdc\x44\x5e\xc3\xd8\x89\x3e\x5b\x44\x50\xe1\x04\x6a\x1d\x71\x5c\x6a\x33\x16\x74\x82\x91\x68\x20\x8a\x64\x1c\x5b\xc4\x16\x19\x29\xa1\xd2\x37\x72\xf2\xe1\xf7\x68\xf7\xf8\xf9\xb1\x55\x57\x5d\xb5\x6a\x69\x4b\xef\x39\x37\xf6\x0f\x0c\xf4\xdf\xf7\x0a\x58\x7c\xee\xb9\xe7\xa1\xff\x80\x98\x2f\xc3\xc2\x1d\xae\xd0\x3e\x67\x5d\x2c\x70\xcd\x4b\xd7\x34\xad\x59\x8d\x57\x5f\xde\xda\x81\xb3\x9d\x07\x2f\x1b\x26\xdd\xe2\xf9\xef\x1e\x2d\xc5\x2e\x53\xb1\x80\xad\x30\x8f\x14\xdb\xeb\xe0\x89\x2b\xb7\x95\xf4\x30\x3a\xee\x8b\xfa\xec\x41\x1b\x16\xc3\x02\xd1\x48\x34\x62\x63\xef\xf8\xb1\xfc\xd3\x37\x6f\x94\xbf\x7c\x7e\xdb\xb6\xe7\x81\xf9\x46\xe0\x79\xed\x57\xdb\x1f\xde\x75\x62\xe7\xce\x13\xbb\xe6\x5e\x79\x56\x7b\x31\x87\xf4\xaa\xc7\x0d\xf4\xaa\x13\x6f\x9d\x38\xf1\x16\xdc\xf8\xa6\xfc\xec\x53\x38\x23\x28\x03\xe6\xe7\xb7\xa5\x7e\xb6\xf9\xa2\x77\x86\xde\xb9\xa8\x6a\xd2\xa2\x99\x81\xa1\xb6\x36\x9c\xe7\xc4\x89\xec\x1a\x22\xc6\x68\x30\x50\x85\x54\x05\xd1\x04\x09\x75\x29\xef\x88\xe1\x20\xa3\x12\x24\xea\xf9\xab\x60\x5d\x2b\xac\x45\x3a\x85\x45\xf9\x82\x71\xd8\x8e\xcd\x57\x37\x6a\x44\xc7\xd1\xf3\xc9\x2d\x37\xcc\x28\x33\xe2\x75\xc5\xb2\x19\x7b\x0e\xef\x99\x51\xa6\x6c\x60\x59\xdf\xe1\xc1\x24\xfe\xee\x98\xe4\xe1\x4f\x43\xae\x6f\xc9\x8a\x03\x8f\x01\x85\x93\x3d\x20\xb5\xbf\x3b\x68\x95\x07\x3e\xbe\xea\xe0\x45\x33\x67\x5e\x74\x50\xd9\xc8\x65\x90\xc2\x17\xc8\xe4\x97\x4e\xe4\xf8\x82\x42\x2a\xd6\x00\x83\xf4\x1b\xca\x98\x89\x92\x21\x78\x06\xa8\x18\x0c\x25\xc9\x09\x8c\xd6\x99\x90\x08\x59\x12\x7d\x16\x49\x4b\x20\x25\xd5\x65\x70\x1e\x90\xda\x48\xd1\x09\xe5\x5a\x52\x05\x15\x01\x01\x03\x90\x0c\x11\xcc\x81\x14\xc6\x1c\x48\x01\xe2\x2b\x21\x29\x0e\xf9\xca\xb5\x09\x2a\x09\x31\x42\x80\x31\xcb\xac\xab\x42\x1b\x60\xcd\x3e\xf7\x20\x26\x91\x7f\x1f\x29\xc3\xa7\x9c\x84\x09\x26\xaf\xcc\x0a\x90\xa0\x03\xc0\x04\x29\xb3\xf2\x2c\x1c\x7e\x93\x29\x7c\x48\x7d\xee\xf0\xd8\x9a\x22\x8a\x8a\xf8\x88\x6f\x64\x10\xf3\x41\x8e\x9e\x5b\xfb\x61\x4f\x3a\x29\xb1\xe7\xa6\x93\xb0\x47\xa1\xce\xce\xce\x77\x4c\x72\xb0\xdf\x28\x79\x99\x9e\xc1\xa4\xc4\xbc\x96\xcf\x43\x82\xfb\x67\x8a\x51\xb0\xe7\xdc\x23\x5b\x55\x1c\xd1\x4e\xc3\xdb\x38\x34\xa2\xd9\x7e\x97\xd7\x12\x63\xb4\x21\x79\x0e\x7a\xdc\x19\xdf\xdd\xb0\x1b\xa9\xd7\xd2\x94\x5a\xc6\x33\xbc\x3b\x7a\xe4\x73\x73\xf1\xc4\x2e\x8c\x46\x92\xfb\xee\xed\x0e\xc6\xe1\x81\x4d\x90\xd8\xbe\x83\x31\x0c\x1d\x46\xf1\x02\x53\x0e\x49\x60\x41\x09\xb1\xe2\xaa\x34\x51\xca\x42\x79\x45\x03\xe8\xbb\xbc\x61\xca\xf9\x11\x00\x22\xe7\x4f\x69\xf8\x11\x98\xda\x50\xbe\xb2\x53\xbe\x62\xa9\x6e\x42\x79\x4b\xcc\x81\xa6\xe7\x58\x4b\xf9\x04\xdd\x12\xf9\x47\xfe\xd6\xf3\xe6\xce\x60\x53\x13\x56\xd0\x8d\x43\x1f\x13\x2f\x7c\x57\x4d\xe8\xdf\xab\xca\xaa\x6b\x6a\xaa\xcb\x76\xfd\x21\x0c\x16\xcc\x3a\x18\x91\x07\x13\x7c\x75\x51\x89\x28\x96\x14\x55\xf3\x89\xcf\x9c\x65\xd7\xb7\xcd\xec\x5d\x4e\xde\xf9\x23\x68\x3c\x3b\x87\xc4\xfd\x95\xab\xf8\x16\x76\xc5\x55\x17\x7b\x13\x92\x15\x7d\x85\xa2\xde\x66\xf1\x89\xe6\x6a\xe0\xb3\x05\x48\x88\x25\x58\x26\x3f\x09\x56\x80\x75\xf3\xe0\x9c\xd5\xeb\x7e\xb8\x9a\xb9\x56\x7e\x6a\xf6\x82\xb6\xf9\x36\xbd\xfc\x14\x12\xfb\x41\x27\xb4\x96\x4d\x59\xd7\x76\xf4\x4d\xfa\xda\x21\x1f\xfd\x47\x50\xdb\xb9\x72\x65\xe7\xb4\xb3\xcf\x1e\xfa\x20\xfd\x12\x14\xd7\xef\x98\x14\xf1\x44\xd2\xef\x82\x6b\xc1\x97\xe3\xc7\x1f\xf4\x8e\xaf\x2f\xfe\x73\xe6\xbd\x29\xe3\x6b\x1d\x99\x13\x71\x38\x76\x49\x38\x84\xc3\xff\x23\x78\xd5\x0d\xfb\xf4\x90\xb9\x83\xe3\x47\x2c\xf3\x63\x80\x3f\x06\xa9\xe6\x3b\x5f\x97\x3f\xba\xfd\x21\xf9\xe5\x73\x79\xa0\xd9\xaf\x33\x99\xf9\xce\xb7\x77\xf4\x3e\x77\x60\xf6\xec\x03\xcf\xf5\xae\x7c\x7c\xf2\xfe\xbc\x95\xf9\xbd\x1b\x80\x74\xfd\xed\xa0\xf0\x75\xba\x50\x7e\x49\xfe\xe8\xf5\x9d\xd7\xed\xd3\x15\x68\x0e\x68\xa1\x6e\x45\x2f\xca\xfe\x26\xba\x6a\xca\xc4\x03\x79\x2b\xf7\x97\xac\xd9\xb8\xf3\x75\x54\xc6\xd2\x53\x36\xee\x6f\xec\x6f\xb1\x4f\x9b\x6f\x18\x68\x2d\x0e\x4e\xf5\x70\x38\xde\x97\x55\x8f\xb5\x32\x24\x1c\x9a\x75\xa8\x5d\xa8\x8a\xc3\xc8\x01\xac\xba\x76\x24\x30\x24\xb4\x84\x0d\x63\xec\xdb\x0c\x16\xec\xdf\x82\x1b\x08\xef\xee\x8d\xa1\xf2\x53\xd4\x1e\xa1\x54\x80\x36\xc6\xcc\x68\xe8\x42\xda\xad\x77\x89\x2e\x63\x69\xa1\xdc\x5b\xa8\xd5\xda\xf5\x1e\xda\x13\xd2\x99\x2d\x3a\x0b\x67\x85\x82\x00\x96\x8e\x95\x15\xdc\x3c\x46\xd6\x3d\x80\x2a\xc7\xab\x54\x1b\x82\xd1\xe0\x39\xc1\x20\xc0\x96\xb1\x72\x80\x9e\x25\x40\x2b\x87\x32\x99\x75\x21\x74\x81\xde\xae\xd5\x92\x95\x32\x23\xba\x95\xde\x8d\x6e\xaa\x41\x37\xb7\x41\xf4\x18\xf4\xac\xd1\x59\x51\xa9\xc6\xc8\xba\xe7\x14\x55\x8e\xea\x12\xce\x61\x78\x28\xfe\xc4\x98\xbd\x15\x5b\x36\xa6\xe7\x62\xab\xb3\xc2\x9c\x14\xab\x02\x38\x8a\x9d\xf8\x7b\x60\x2e\xe1\x92\x11\x39\x32\x1e\x71\xc0\xcc\x2b\x76\x1f\x4b\x86\xf9\x1d\x24\x09\x0b\x32\xd0\x2b\x9b\xaf\xd7\x70\xee\xda\x2a\x7e\x4d\xf3\x72\xb3\xb5\xfb\xd6\x03\x56\x73\x05\x5c\x49\xce\xa4\x5f\x21\x1b\xa8\xe6\xbb\xf2\x6a\x29\x70\xf2\x07\x01\xe9\x6a\x8c\x66\x05\xce\x01\x5d\x5f\x5e\x03\xc8\x99\xe9\x50\xa5\x47\x3e\x02\xf6\xb8\x2a\x05\xb7\x4b\xde\xcb\xce\x68\x9e\x71\xa0\xb4\x7b\x46\xf3\x16\x41\xc9\xf1\x0a\xd9\x6c\x57\xf2\xa5\xe4\xc1\x3f\x14\x15\x7d\x00\xb8\x27\xf1\x4d\xae\xf9\x52\x7e\x3c\x33\x2e\x28\x98\x5b\x76\x3c\xff\x51\x48\x50\x43\xb2\x0f\x86\xa4\xe7\x63\x0a\x1a\x7d\x49\xcc\x1c\x62\x72\x60\x5c\x18\x7e\x60\x38\x1a\x17\x01\x89\xee\x92\x7b\xe5\x3b\x4e\x5c\xbb\x77\xa1\xdb\x59\x75\xf3\xae\xf2\x86\x49\x2d\xaf\x82\x55\x27\x4e\x80\xd9\x79\x18\x5d\xac\xc9\x39\x0a\xa4\xeb\x4b\x70\x3b\xf8\x2b\xb8\x9d\x49\x5e\xf9\xf7\xfd\x9b\x5e\x99\x56\xdb\xb3\x64\x76\xdb\x39\x21\x4e\x73\xe5\xdf\x81\xf8\xf7\x5f\xe5\x80\xbb\x6c\x96\x31\x70\xbb\x7e\x0c\xc2\x47\x8f\xe6\xd6\x20\x70\xec\x46\x23\xb5\x3a\xbf\x16\xd9\x3a\xd4\x85\xf0\x5b\xf8\x0e\x14\x05\xf0\xdd\xf8\x09\x48\xfc\xa3\x17\xcb\xaf\xcb\xff\xbe\xa3\xaf\xe7\xec\x80\xbf\xb0\x22\x3a\x73\xfa\x2d\x40\x77\xc7\x1d\xe9\x3b\x31\x6e\xc2\xf1\x33\xa0\x2b\xb0\x8d\xdf\x0b\x55\xe1\x1a\x26\xd9\xfb\xe8\xda\x39\x37\xd7\xd7\xcf\xb3\x4a\xc5\x3a\xa1\xf7\xd1\x57\x1f\xfd\xeb\xfe\xbf\x9f\x01\x6a\x61\xf0\x9b\x33\xa3\x2c\xec\xba\xe0\x04\x1a\x1f\xc0\x29\x8a\xbe\x08\x8d\x61\x3e\xc5\x0e\xab\x18\x20\xe2\x12\xab\x18\x27\x54\x67\x78\x34\x4a\xd0\x41\x1c\xf0\xb2\x5d\xd4\xa7\x3f\x32\x16\x31\x3a\x8b\x85\x79\x41\xee\x63\x34\xa2\x51\x64\x7f\xcd\x38\xcd\x60\xaa\xe4\x62\x8f\x82\xab\x34\x8c\x44\xbf\x6c\x75\x0e\xee\x2a\x80\x6c\xa1\x99\x2e\x5d\x03\xf4\x26\x27\xdd\x20\x88\x05\x16\x8d\x4e\xae\x59\x09\xf3\xb9\x3f\xe6\x0f\x5f\x0f\x45\x4a\x0f\x92\x4f\x47\x92\x23\x8f\x79\x8c\x18\x6e\x03\xb9\x09\x5e\xc1\xf3\xb1\xf9\x54\x14\x41\x9e\xaa\x2f\x55\x42\x0a\x7b\x64\x8a\xac\xc8\x8e\xb9\xd7\x55\x07\x95\x7d\x12\x78\x58\xda\x03\x31\x72\x5f\x69\x7d\x7e\x38\x62\x2a\x95\xc9\x3d\xc6\x5e\x5d\x57\x2a\x73\x2d\x3e\x9a\xea\xaa\x4b\xd5\xe7\x64\x93\x14\xd2\x66\x67\x51\x8b\x55\xb9\x28\xe3\xf0\x8e\x91\x73\x2c\xb1\x5a\x65\x95\x11\xab\x4d\x5c\xc6\x14\x84\xbd\xc9\xc0\x88\x5d\x32\x99\x29\xb8\x04\x31\x0a\xcf\x1a\xd8\x24\x04\x6c\x21\x3f\x4f\x6e\x47\x27\x6f\x7e\xf3\xe6\x50\x5d\x68\xe6\xea\x99\xbe\x56\xda\x27\x19\xf5\x86\x9a\x45\x8d\x1d\x17\x94\xf3\x36\x46\x6f\x11\xf5\x8c\x8d\x2f\xdf\x71\xc5\x0e\xb2\x2b\x5a\xc8\xee\x05\x1d\x8d\x8b\x6a\x0c\x7a\xa3\x04\x2a\xa9\x53\x60\xfe\x4f\xaf\x02\xc6\x81\xfb\x7c\x20\x4d\x95\x55\x94\x61\xdf\xdf\xe7\xd3\xc7\x7b\x6f\xbe\xb9\x17\x8b\x30\xb5\x33\x67\xd6\xc2\x0e\x7d\xc8\x28\xe9\xaa\xaa\xa6\x35\xeb\x4a\x38\x8b\x85\x2b\xd1\x35\x4f\xcb\x4f\x57\x55\xe9\x24\x23\x0b\x9f\x02\x96\x2b\xba\xaf\xff\xf3\x01\x08\xdf\x5a\x09\xe1\x4a\x2c\x94\x32\x59\xbb\x8a\x06\x69\xc4\x6e\xac\x81\xb0\x3e\xc5\x96\xe2\x1b\xb5\x58\xe2\xcb\xc6\x70\xb7\x0c\x27\x45\x21\xab\xf7\x34\x92\x6c\xf1\xba\xbb\x9c\xc4\xec\x8c\x69\xb2\x9a\x09\x53\xa8\x0e\x14\x28\x97\xdf\x81\x54\xce\xd8\x52\x5f\xca\xa0\x94\xcd\x84\xe7\x82\x24\x5e\xca\x07\xfd\xc0\x9b\xc5\x8a\x4d\x9f\x8b\xf2\xcf\x4f\x93\x77\xde\xaf\x2c\xd3\x63\xd3\x8a\xd1\x84\xe6\x83\x9e\xac\x5c\x49\xb8\x60\xcc\x54\x29\xb5\x94\xd8\x26\x49\x58\xb9\xaa\x33\xa1\xe6\x57\xa3\x1a\xac\x0a\x53\x76\x24\x46\xf4\xdd\xb8\x15\x7b\xb8\x65\xa1\x31\xb0\x66\x48\x02\xb6\xc8\x9b\xcb\xfc\x61\x77\xf2\x28\x51\x1d\x20\x1c\x90\x5c\xd2\x39\x75\xb8\x5c\xb5\xab\xa6\xf7\x4f\xda\x78\xf9\x81\xcb\x37\x4e\xea\xd0\x8d\xd3\x25\x8d\x1f\x19\x93\x68\xdb\x91\x5c\x57\xd9\xd4\xcc\x54\x17\x14\x54\x1a\xdb\xaa\xac\xdd\xcb\xbb\xad\x55\x6d\xc6\xca\x82\x82\x6a\xa6\xb9\xa9\x72\xdd\xe2\xeb\x9e\xfa\xe9\x53\xd7\x2d\xa6\xc9\xca\x6b\x55\x2d\xba\x9b\xb7\xab\x6e\xea\x45\xb3\x2a\x2b\x67\x5d\x34\x75\xcd\x2c\x7d\x85\xfe\x96\xeb\xae\xbb\x05\x6d\x66\xad\xb9\x6d\x73\x4d\xd7\xd6\xda\xc2\x58\xd0\xed\x0e\xd6\x15\x39\x9c\x55\xb5\x15\x75\x75\x15\xb5\x55\x4e\x47\x51\x1d\x3e\x16\x2b\xac\xdd\xda\x55\xb3\xf9\xb6\x55\x47\x37\x4f\x98\xb0\xf9\x28\x19\xff\x15\xec\x59\x17\x89\x41\x21\xcb\xd4\x39\xdb\x90\xc2\x23\x49\xdc\x25\xcc\x79\xb8\x94\xa1\x5c\xa0\xba\x02\x67\x66\x3c\xd9\x2f\x19\x0d\x06\xf9\xe7\x5a\x2d\x48\x10\xaa\xc8\x1e\x4c\x86\x48\x50\x26\x4f\xf6\x13\x94\xdf\x1e\x05\x45\x12\xf4\xa0\x5a\xa0\x7f\x3a\x94\x0f\x33\x2e\x26\x30\x42\xa4\x04\x7d\x19\xb0\x48\xb2\xb4\x9c\x85\x84\xcc\x60\x04\x12\x6e\xa2\x28\x89\x01\x2e\xcf\x59\x80\x32\xb6\x2c\x4c\x10\xc8\x7e\x87\x5d\x99\xa5\x44\x61\x80\xdc\x78\x00\x93\x51\xf6\x60\x32\xca\x15\x3a\x98\xb1\x36\x5f\x75\x3e\xb6\x36\xdf\x0e\xe8\xa6\x29\x2b\xfa\x0e\x8f\xdb\x7b\x3f\xec\x11\x44\xd0\x43\xec\x3c\xfd\x84\x01\xb3\x1f\x55\x6b\x85\xe1\x6d\x62\x83\xde\xfb\x7e\xdc\x63\x7c\x1b\x54\xfc\xf8\x60\xeb\xe1\xbe\xae\xd6\xe2\x13\xa3\xcb\x18\x26\x8e\xcb\x0a\x3e\x45\xd6\x0f\x37\xa2\x22\x42\x9c\xb6\x8c\xf8\x31\xa8\x15\xee\xd2\xe5\x15\xf6\x3b\xca\xd8\x2f\xe0\x9a\xa0\xfc\x06\x83\x20\xca\xa4\x8d\x41\x8f\x24\x7f\x76\x9a\x42\x66\xfa\xbb\x1a\xff\xb5\x88\xea\xc9\x59\x74\xd8\xac\xaf\x06\x1d\x47\x5f\x29\x01\x29\x50\x40\x09\x70\x14\xa6\x37\x8e\x3a\x00\xfe\x7a\x33\x68\x66\x61\x32\x1c\x0d\xdb\x0f\x85\xeb\xb0\x0f\xa6\x87\xc9\x3a\x76\x28\xa6\x5e\x26\xa4\xb8\x6d\xe8\x83\x8d\xbd\x1d\xf6\xc6\xc9\x9b\xfa\x37\x4d\x69\x28\xd8\x07\x26\xef\x2b\xe8\x3b\xec\xad\xef\xae\xf7\x76\xf5\x76\x91\xed\xa4\x26\x00\x18\x9d\xa6\xa3\xb7\x31\xa8\x97\x53\xaa\x1b\xc7\xef\x88\x09\x7b\xf7\x85\x07\x0e\x5c\xd8\xb1\xe7\xf0\xd6\x25\xa6\xba\x8e\x57\xac\xab\x5b\xba\x37\x6d\xea\x6e\x59\x6d\x7d\xa5\xb5\xb8\xb7\xb7\xb8\x35\x71\xb8\x6f\x71\x51\x19\xfe\xb8\xcb\x8a\x16\x63\xbc\x8c\xdc\x5e\xc7\x0e\xbf\x6e\x42\x71\x5d\x99\x64\x5a\xb2\xf5\xf0\x1e\xfa\xb7\xaa\x43\x47\x36\xb6\x5c\x69\x8b\x19\x39\x49\x2f\x8e\xd4\x1f\x8b\x95\xf1\x96\x60\xc2\x12\x95\x62\x94\x98\x7d\xc8\x17\x81\xde\xa5\x37\xa6\xf8\xe2\x93\x35\x21\xe5\xed\xe1\x70\x61\x9b\x72\x86\x48\x12\xb5\xd9\xb0\x85\x29\x0d\x0a\x7c\xf4\xbd\xef\x87\x5c\x9c\xce\xd2\x1c\xc0\x6e\xef\xbe\xe2\xe3\x40\x73\xbc\xd8\x87\xd3\x81\x66\x8b\x8e\x73\x85\xde\xbf\x17\x1f\x6a\x98\x82\x5a\x87\x56\x9c\x0e\x12\xad\x2b\x6d\xf2\xf6\x23\x1f\x7e\x78\x64\x9f\xf5\xb7\x07\x09\xa4\x86\xa7\x04\x49\x71\xa2\x7c\x1e\x59\xbd\x3b\x24\xa2\x9d\x12\x0f\xc4\xfc\x60\x07\x7f\x6b\xdd\x47\x0e\x5e\x69\x5b\xd9\x8a\x9a\x46\xe5\xfa\x54\xec\xaa\x58\x9b\x0d\x2a\xbe\x51\x6c\x0e\x1e\x1d\xe9\x4e\x91\xac\x2b\x94\x8a\xa1\x1e\xc9\x78\x44\xc9\xfd\x04\xd5\x91\xe9\x1f\xa2\x92\x8a\x0b\x14\xa4\xf6\x2d\x4d\xa0\x83\x4c\x12\x83\xc6\xed\x5b\x4a\xa3\xf4\x20\x92\xb7\x14\xcf\xa7\x81\xa1\xd4\xd2\x7d\x2c\xb5\x0f\xb5\x69\x2e\x46\x2c\x32\x22\x42\xec\xfb\x47\x85\xd1\x89\xef\x19\x08\xf6\xbd\x02\xbf\x14\xd9\x30\xa1\xca\xf6\x7e\xf2\xa6\x49\x65\x81\x4f\xe9\xf4\xa8\xc3\x96\x8f\xe0\x5b\xe5\x92\x9b\xba\x13\x89\xee\x6f\xbf\xe4\xa9\xc3\x7d\x83\x54\xdf\x61\x3e\xf1\xe1\x91\xc4\xbe\xa5\x18\xed\x12\x2f\xc2\x1c\xa1\xc7\xf7\x6f\x92\x93\xe9\x14\x7a\x3e\xa3\x45\x7d\xca\x8b\xdb\x0b\x0e\x60\x76\xae\x1c\x16\x7a\x25\x35\x51\x91\x06\xf8\x6c\x84\xa9\xd2\xa5\x48\x97\xb1\x2b\xd8\x2b\xc3\xd3\x6c\x36\x67\x9e\xb4\x03\x93\x53\x1a\x08\xf0\x7f\xc3\x94\x7c\x18\x05\x1c\xc5\x42\x91\xe3\x68\x98\x38\xbe\x0f\xbb\xda\xb1\xa9\x74\x12\x7d\x16\x43\x5f\xe1\x8f\x80\xd6\xa3\x0f\x05\x2a\xf0\xb0\x3d\xc4\x19\xaf\x7f\x64\xfa\x5b\xc2\x99\x01\xd1\xe8\x4d\x7b\xf7\x1d\x57\xec\xbe\x4a\xfc\x8a\x84\x66\x03\x05\x03\x77\x2e\x61\x34\xb0\x8d\x34\xb2\xf3\x16\x1f\xe6\x44\x05\xea\x0c\x6f\xc9\x01\xe4\x2a\xf9\xd8\x11\x56\xc0\x91\x56\x41\xf6\x38\xf6\x73\x50\x2d\xef\xc9\xd2\x9e\xc2\x7d\xe0\x02\x9d\x41\xfe\x95\x01\xac\x22\xee\x0d\x14\x06\x1d\xce\x40\xce\x08\x22\x1c\xc8\xa4\xf2\x8f\x8a\x02\xb3\xaf\xb0\xa7\x74\x30\x89\xef\xc2\x11\x2b\x7c\x87\x7c\x45\x91\x01\x34\x18\x4e\x8a\x0c\x85\xc5\x81\x93\x14\xdd\x93\x31\x1a\x09\xfd\x39\xeb\xde\x29\x2a\x97\xc6\x11\xdf\x59\xfc\xfa\xd1\xb6\xa4\x87\xa9\x9f\x51\x6f\x50\x7f\xa4\xbe\x40\x12\x94\x09\x14\x83\x4a\xd0\x32\x9a\xb7\x3a\x3a\x62\x9f\x1d\xb1\x3f\x32\xff\x48\xde\xea\x91\xe7\xcf\xb4\xff\xff\xfa\xfa\x33\xe5\x1f\x59\x5f\x8c\x08\x6e\xc9\x78\x5b\x8e\xc2\x62\xc2\xbc\xd2\x59\x31\x2d\x87\xd7\x4d\xe5\xd2\xa7\xf2\xd2\xf4\x69\x8e\x9f\x2e\xfd\x7f\x23\x3f\x3c\xcd\xf1\xe1\x65\xc6\xf8\xa9\xb8\x6e\x04\x18\x8b\xca\x67\x7f\x1f\xc8\xd6\xf4\x5f\xa3\x2b\x9e\x77\x2c\xfd\xaf\x31\x0e\x8e\x95\xfa\x3f\x95\x51\x1e\xeb\x60\xee\xe7\xe4\xf5\x18\x74\x74\x40\x11\xe0\xf2\xdc\x81\xf1\x0a\xe4\x77\x7c\x33\x4f\x51\xbf\xa7\xbe\xfa\x7f\xff\x95\xfc\x6f\x7a\x69\xd6\x2f\x23\xaf\xbf\x16\x80\x0c\xdf\x40\x20\x3a\xdc\xdb\xa8\x05\x44\x6c\xa3\xf1\xed\x23\xbe\xac\x06\xf3\x7f\xa5\x77\x7f\xdf\xde\x77\x0a\x6b\xc2\x68\x1c\xc4\x69\xa5\x17\x92\x53\x79\xe5\x49\xaa\xf7\xcb\xf4\x4d\x90\x40\xa3\x24\xe6\xc1\x49\xfc\x1f\xeb\xa3\x67\xe8\x51\x43\xd7\x33\x49\x2f\x1e\xb0\xbd\x83\x49\xd2\xaf\xe8\x94\x52\xd0\x9e\x9e\xac\x63\x95\x92\xae\xcc\x7d\x3e\x80\x5c\x21\x0f\x84\x90\xd0\x91\xc8\xf2\x98\x63\xdb\x6b\x33\x46\x06\xca\xb7\xbe\x12\x08\xd7\x8c\x38\x27\x91\xd7\x97\x65\x8f\x08\x64\x28\x24\x6c\xd9\xb7\x59\x1b\x53\x00\x20\x86\x19\x68\x43\xc4\x3a\x1b\x53\x6c\xb3\xd9\x69\x98\x2c\xbb\xc9\xaf\x80\xe4\x9d\x82\xe6\x97\x3c\x64\x29\x72\xe0\x15\x24\xad\x13\x53\xb7\x82\x9d\x9f\x49\x62\xae\xca\x54\xc6\x5e\x4b\xbe\x1b\x97\xf4\xa2\x94\x70\xf5\x2b\x56\x1c\x75\x09\x0f\x69\xb8\x90\xff\xa5\x41\x97\x3e\x46\xf6\x69\xef\xa8\xfb\xe0\x24\xac\xc2\xe6\x9f\x8c\xe5\x16\xfb\x74\xf6\xbb\x12\xe8\x6e\xc4\x5f\x3d\x94\xc1\x96\x50\x70\xeb\xc3\x54\x0d\xfa\x16\x3b\x95\x28\xca\x33\x56\xfd\x7b\x49\x85\x44\x7b\x1a\xa3\x8a\x69\x45\x5a\x4c\x12\xe9\x87\x49\x0d\xa6\xfa\x73\xd2\xa2\x17\x1d\x04\xfd\x63\xd7\xe6\xf3\xef\x14\x22\x33\xf8\x1c\x04\x17\x1e\x5b\x2a\x38\x23\xe0\x03\x8a\x08\x5e\x4e\x47\x23\x96\x00\x1f\x08\x63\xab\x60\x34\x1c\x8d\x63\x43\x66\x34\x1e\x71\xa0\xa3\xd1\x26\xa8\xf8\xfa\x82\x88\x83\x45\xda\x3a\x9f\x04\xf2\x87\x72\xff\x40\x42\xfe\xfd\x24\xdc\xfc\x3d\xfd\x89\x44\x7f\xaa\xc7\xeb\x4d\xa6\x52\x49\xaf\xb7\x27\x85\xf7\x89\x30\x34\x09\x04\x13\x03\xa0\x27\x79\x50\x03\x13\x5e\xf4\x3f\x52\xc3\x04\xad\x17\xf4\x0f\x78\x53\x5e\x8d\x33\xe9\xd4\xa0\xed\x00\xe8\xf7\x6a\xb1\x22\x98\xf0\x16\x8e\xd7\x11\xfd\x21\xa1\xfa\x9f\x70\xa8\x17\x12\xeb\x04\x16\x73\x6d\xbe\x68\x9c\xb4\x67\x38\xee\x8b\xfb\x90\x98\x84\xf1\xb6\xa7\x47\x19\x34\x31\x24\x93\x47\x3e\x4c\x78\xc1\x80\x97\x4e\x79\x13\x38\xde\xe2\x14\x15\x9d\x2e\x27\x52\xa9\xd4\x87\x47\x40\x22\x91\x4c\xa6\xbc\x43\x03\xc3\x38\x53\x31\xf3\x49\x8e\x2e\x75\x84\xdf\xa3\x02\x0f\x42\xf0\x0f\x47\xe1\x00\x11\x3f\x3e\x99\xca\xf1\xd6\xc2\x0c\x73\x6a\xbe\xed\x36\xa5\xd8\xae\x30\x05\x46\xc6\x86\x85\x07\x04\x19\x7b\x01\xd0\xff\x31\xc2\x37\x71\x44\xb9\xbe\x0f\x97\xeb\x58\xe5\x92\x53\x4a\xd9\x52\xca\xb3\x94\x52\x25\x46\x96\x4c\x21\x73\x4d\x28\xa5\x1b\x7e\x01\x6c\x1c\x5e\x30\x88\xe4\xec\x19\xf4\xbf\x98\x08\x92\xe2\xc6\x61\x8d\x76\x24\x17\x2e\xaf\x05\xcc\x58\x07\xe1\x56\x5d\xad\xce\xa5\x93\xab\x74\x3a\xf0\x16\x4a\xd4\xea\x74\xf2\x0e\xb0\x1f\x1c\x18\xf3\xf0\x31\x92\x22\x47\xd0\x8f\x92\x65\x87\xbc\x43\x37\xf6\x61\x52\x2e\x23\x2a\xd7\x7f\x66\xca\x45\xe5\x7c\x5b\x72\x9c\xba\xcc\x58\x07\xe1\x5c\xfc\x70\xe5\xbe\xfb\xd1\x13\xc8\x4d\xc1\x5b\xa8\x5c\x63\x1d\x86\x33\x94\xb2\x92\xbd\xfd\x60\xbf\x5a\xe2\x2a\xdd\xd8\x87\x71\xb9\x66\x50\x57\x33\x11\x66\xee\xb0\xf6\x1a\xce\x0f\x21\x8e\x75\x90\x89\x9c\xa9\xd6\xc3\x0e\x7f\x36\xaa\xa8\xf8\xf9\xe0\xfc\x31\x0f\x53\x4a\xb9\x8e\xa1\x72\x6d\xcd\x6f\xaf\x11\x1c\x13\xe2\x58\x07\x51\xb9\x4e\x5b\xdd\x31\x0e\xc3\x63\xa3\x5f\x2e\xca\x81\x0b\x36\xc6\x61\x3c\x16\xa1\xfe\x05\xb7\x92\xf7\x88\x4b\xa5\x05\x23\xe9\x96\x51\x47\x52\x73\x0f\xeb\x37\xf4\x67\x63\x37\x16\x19\xdf\x50\xdf\x80\x73\xb3\xf7\xfc\xde\x9d\xe0\x74\x6f\x9b\xdc\x73\x06\x30\x32\x11\x7a\xae\x72\xcf\xff\xc1\x0b\x04\xe7\x9e\xee\x9d\xe0\x7b\x56\xa2\x7b\x6e\xcd\x95\xf3\x7b\x36\x3e\x5d\x79\x9a\xe6\x54\xed\xd0\x8a\xdc\x58\xad\xe0\xa5\xe6\xa3\xf4\x28\xb6\x7c\xab\x27\xab\x91\xd7\xb5\x82\x68\xde\x18\x82\x97\x1a\xbf\x25\x22\x02\x97\x20\xb6\xfd\xf4\x80\xd7\xab\x90\xa4\x7b\xbd\x69\x02\x91\xc4\xe1\x60\x2e\x2f\x4d\x64\x8a\x21\x9c\x95\x9e\x81\x5d\xd0\x82\xb3\x5b\x8c\x78\x0c\x11\x9a\xbb\x43\x39\x77\xb4\x3c\x1f\x10\x13\x89\x58\xc7\x63\xdb\x70\x4b\x43\x00\xe4\x61\xcf\xe1\xb2\x62\x11\x50\x95\x19\x23\x6c\x6d\x1d\x1a\x01\xad\x11\xd0\x9f\x75\x72\x9b\x38\xd8\x2f\x19\x19\xf2\xf8\xc1\x14\x5e\x08\xed\x57\x60\x9b\xfa\xe9\x4d\x66\x73\xbf\xd9\x0c\x28\x05\x3d\x54\x41\xbf\xa5\x7b\x72\x0b\xdc\xd2\xd0\x5c\xb2\x58\xdd\x83\x66\xa9\xac\x3f\x38\xa3\xc8\x3a\x0e\x34\xb3\x67\xe5\x9c\xe0\x98\xad\x96\xbf\x64\xa0\xe0\x3c\xfc\x50\x6d\x01\x23\xad\x34\x56\x0e\x0b\x6f\x2d\x59\x40\x18\x50\x56\x94\x87\x70\x09\xe8\xd7\x86\x39\xea\x31\x4a\x01\xc8\xba\x89\x43\xf1\x46\x3f\xdd\xd3\x21\x69\x82\x26\x30\x92\xc2\x00\xbc\x49\x00\x91\xa8\x53\x48\xaa\xa3\x48\x1d\xd1\x6f\x0a\x37\x41\x3f\x18\xdf\x55\x27\x53\xca\xea\x43\x5d\xd7\x0a\x05\x37\x89\x34\x81\xb2\xde\x4f\xcf\xf0\x7a\xbd\x43\x24\x03\x83\x7f\xf3\xe7\x1f\x3d\x2a\x0f\x45\xa9\x4c\xb5\xad\x40\x31\x4e\x66\x59\x9e\x6f\xc8\x92\xd2\x1e\x3a\x34\x8a\x96\x96\xe9\xcf\x23\xad\x7d\x6e\x2c\xac\x07\x75\x4e\xf7\x11\xf6\x9f\x5c\x7d\x5a\x61\x13\xc8\x10\x1d\x67\x69\xc8\xf2\xe9\x7e\xc6\xce\x40\x53\x9b\xba\xe5\x64\xf7\x26\x6c\xe2\x27\xb3\x59\xa2\xef\x70\x7d\xe9\x40\xf7\x26\x3a\x79\x9a\x13\x30\x81\x0f\x6f\xea\x86\x29\xec\x1a\x40\xa6\xbe\xc3\x7d\x48\xf8\x55\xb2\x8f\x71\x9c\x1a\xb3\xdc\x02\xcc\x53\x73\x90\xac\x47\xe6\xe9\x7c\x9a\xa2\xef\xce\x40\x53\xa3\x0a\xb6\xa9\x1b\x24\x71\xb9\x4f\x73\x82\x49\xa5\x13\x23\x4b\x0c\x48\x89\x4f\x73\x1c\x17\x59\x83\x64\xf9\x04\x59\x2f\xd4\x52\x16\x82\x8a\x86\xbf\xbf\x26\x35\xd6\x40\xc1\xd1\xa9\xcd\x46\x0c\x66\xa2\x0b\xac\xca\xf2\x6b\x2e\xde\x60\xec\x1c\x8a\xd7\x1e\x14\xa6\x47\xeb\xba\xa6\xf7\xc1\x16\xc5\xb8\x7e\x25\xd9\x30\x69\x42\x15\xd0\x37\x7d\xa8\x79\xf9\xbe\xe5\xcb\xf7\x31\x5f\xaa\xa6\x77\x05\xd0\x6c\xef\xbe\xa5\x98\xf5\x71\xe9\xbe\x5f\xf6\x4d\xc7\x19\xe5\xff\x52\xa4\x75\xc5\x90\x9e\xbe\x06\xdf\x70\xfa\x74\xfa\x1f\xf8\xd2\xe5\xe9\x7b\x94\x93\x4a\x48\x82\xbc\x45\xb9\x32\x23\xc7\x66\xfb\x2c\x95\x8f\x74\xc1\x8d\x44\x25\x51\x7d\x1b\xf3\x3a\xe3\x30\xfe\x5a\x60\xa5\x31\xa4\x82\x0a\x62\x8a\xfd\xc1\xd9\xf2\xe1\xfe\x57\x36\x4b\xc4\x2b\xa1\xd1\xf1\x62\xda\x64\xe0\x0d\x66\x93\x85\x65\x03\xad\x2b\x37\xdf\x72\xdb\x4a\x4c\x5a\x2b\x53\x12\xd6\x21\xd1\x07\x0f\x7f\x7d\x77\x14\xf4\xff\x50\xfe\x33\xef\x77\x69\x2d\x56\x93\x36\xc0\x75\xc4\xd7\xf4\x6f\x9f\x1f\x2b\x36\xe0\x98\x5d\x92\x0d\xff\x60\x14\x57\xf9\xdc\x1f\x64\xb1\x64\x29\xf2\xdd\xd5\x50\x8b\xf0\x4c\x20\x00\x7f\x15\xa8\x23\x2c\x7b\x79\x69\x87\x82\x2a\xe5\x0f\x2b\xfe\x91\x1e\x1a\xd3\x95\xd1\x92\x95\x17\x98\x80\xbf\x8a\x09\x67\x2c\x63\xca\xba\x39\x5e\x56\x27\x8b\xbf\x30\x59\xd0\x32\xaf\xa5\x00\xff\xc0\x5b\xb2\xc9\x67\x0e\x9c\x3f\xee\xd6\x29\x0f\x4d\xb9\xb9\xfc\xfc\x03\x89\x95\x87\x7e\x30\xe7\x81\x39\x3f\x38\xb4\x32\x31\xd0\x12\xba\xfc\xfa\x9f\x1f\x5e\x3a\x33\x79\xff\x81\x2b\xfa\x7c\xad\x57\xb8\x23\xe7\xdc\xbb\xe1\xfa\xbb\x6f\xd8\xb7\xfe\xde\x0d\x11\xf7\x15\xa0\xb7\x7b\x5e\x47\xc7\xbc\xe1\x3f\x17\x5d\xf0\x80\x4d\xaf\xb7\x3d\x70\xc1\xa2\x4b\xa7\x57\x0a\x42\xe5\xf4\x4b\x81\xe6\x8d\x8b\x66\x6c\x6a\x0e\x68\x39\x69\x5c\xeb\xea\x09\xbb\xde\xfc\xec\xc8\x9c\x45\xdb\xd6\xce\x9a\x17\xf0\xce\x99\xb9\x76\xdb\xc2\xd9\xfd\xc3\xbf\x2b\x07\x7e\x0b\xea\xb8\x87\xbf\x9a\xef\x1c\x7d\x15\xb6\x24\xa4\x8a\xa7\x13\x39\xf3\x33\x26\x8d\x1d\x45\xa0\x34\x00\xc9\xb9\x44\x16\x52\x10\xfe\x75\x24\xa3\x92\xc2\x63\xb9\x9d\xc5\x3c\x96\x61\x1c\x21\x05\xea\x14\x10\x3b\xd4\xc2\x04\xb4\x17\xc4\x82\xbe\xe8\xc8\x82\x21\xc5\x95\xcd\x31\x2f\xe5\x97\x8b\x58\xcc\x1d\x76\xee\xab\xe8\x60\xaa\x74\x89\x4b\xfe\x9d\x18\x65\x12\xa5\x4b\x0b\x40\x48\x1c\xbc\x92\xa6\x32\xd8\x85\xb8\xd0\x80\xaa\x38\xc8\x36\x54\xc9\xef\x95\x1f\x6a\x1f\x4c\x65\xcb\x8d\x34\xbb\x54\xec\x2c\xbb\x09\x2e\x0b\x94\x17\xcb\x37\x3a\xcd\x81\x8a\x62\xb0\xc1\xfe\x78\x7f\xae\x2a\x47\x41\x53\x74\xd2\x3d\xad\x8d\xf2\x8d\xd1\x49\xb9\xca\x2c\xed\xaf\xa9\x22\xf3\x1a\x9b\xc7\x47\x5e\x48\x95\x50\x75\x84\x65\x88\x98\x50\x43\x04\x6e\x84\xe0\x41\xb7\x02\x0f\x18\x09\xea\x47\x99\xab\xa0\x57\x80\x66\x0f\x44\x23\xbf\x98\x4f\x52\x7e\x5e\xf0\x65\xf9\xe5\xa0\xc6\xe9\x2a\xa8\xd6\x14\x5c\xfe\xc0\xe5\x05\x9a\xf1\xb5\x4e\x59\xa7\xf8\xd2\x4c\x57\x7c\x69\xa6\xaf\x3d\xfa\x99\x3c\xf4\xd9\xd1\xb5\x68\x0b\x98\xcf\x8e\x7e\x3c\x92\x68\xfd\xb5\x0b\x6f\xb8\xe1\x42\x74\x03\x74\x9b\xee\x55\xab\xba\x5d\x4e\x73\x35\x78\xa3\x4f\xb9\x9a\x7c\xfa\x32\xbe\x6c\x6d\xee\x36\x68\xb8\x1e\xf1\xdd\x8e\x5d\x37\x3b\x81\xf1\x53\xec\xfd\xd8\xe3\x02\x7f\x2e\xff\x83\xba\x69\x9c\xb5\xe3\xd5\x5a\x55\x17\xb8\x9c\x1a\x5c\x57\x39\xfe\x3f\xab\x5b\xa4\xa0\xda\x9c\xa9\x96\x06\xdd\x06\x55\x15\x6a\xff\xb7\x75\xd3\x13\xdf\xfd\x72\x6c\xe5\xcf\xf8\x21\xe2\x2e\xf6\xfd\xab\x94\x0c\xb9\xd2\x44\xdf\x84\x49\x97\x1c\xfa\x9f\xd5\x44\x31\x0a\x82\x27\xfe\x47\x85\x57\xe5\x3c\xb4\x51\x66\x99\xf6\xef\xb7\x42\xc2\x8c\xf0\xef\x2a\x31\x53\x01\x7f\x38\xc0\x29\x10\x10\xbe\x5a\x3a\x21\x0a\x29\x51\x48\x0a\xa2\x12\xf1\x90\x49\xc2\x84\x5a\x19\x75\x23\xbf\xfd\x76\xea\xd0\xfb\x87\x52\x6f\xcb\x6f\x83\x8a\xb7\xe9\xe4\xdb\x20\x35\xea\x1a\x9c\x5c\x47\xaa\xa3\x7a\x78\x11\x9c\xf2\x64\x12\x54\x80\x07\x00\x66\x31\x37\x65\xd7\x45\xf0\x58\x8c\xfd\xa8\xf1\x5c\x39\x97\x5a\x41\x6d\xa0\x76\x50\x97\x92\x95\xd7\x7b\xa8\xc7\x88\x15\x1f\xd5\x09\x0d\x07\xa8\x1e\xf1\xbc\x74\x38\x2f\x8d\xf2\xa0\xf7\x86\xd2\xa8\x16\xc1\xd3\xe7\x39\xe3\xf1\xd3\xa5\xd9\xfc\xb4\x25\x9b\x8e\xe2\x7d\x89\xb0\x93\x8d\xb4\x09\x98\x7b\xcc\xe8\x5f\xd2\x3c\x60\x46\xff\xd4\x3d\x86\x32\x0f\x21\x81\x91\xee\x31\xa7\xb3\xe7\xc9\x06\x8c\xbd\x9b\xd9\xca\x94\xba\x9f\xdb\xa2\xdb\x6e\xc2\x17\x7c\x8b\xa6\xd5\xe9\xd1\x6f\x09\x76\x26\x46\xd0\x04\x9b\x48\x8e\x2f\xf3\x7e\xd3\x5f\x8e\x3a\x24\x8f\xb1\xa3\x6e\x80\xb2\x51\xff\xc9\xfd\x24\x9f\x19\xc7\x9f\x0e\x25\xf1\x1f\x7e\x10\x8d\x7f\x15\x91\x3a\xa1\xae\xd5\xd9\xa9\x32\x6a\x01\x96\xd6\x32\xbe\x41\xbc\x85\xf0\x84\x10\x6c\x00\x30\xc2\x6c\xa8\x5a\x07\x33\xd1\x71\xd8\xd1\x94\xc9\xa2\x47\xc4\x89\xdb\x6b\x26\x62\x0c\x0d\xee\xc9\x07\xf7\xcf\x69\x5b\xfd\xc0\xf2\x63\x1f\x7f\x75\x3c\x7e\xf6\xaa\x78\xbc\xb0\xa2\xe1\x82\xc1\x73\x03\x45\xc4\xde\x55\x14\x40\x7d\x8b\x4d\x05\x74\xfc\xef\x6e\x5a\x34\xb9\x30\x31\x79\x53\xe3\x5a\xf9\xab\x15\x26\xd1\x6c\xf6\x16\x07\x16\x5e\x7d\x6f\xe7\xa6\x5f\x6c\x0a\x45\x76\x1e\xb7\x6b\x8b\x8b\x8b\xc1\xdf\x60\xef\x12\x6f\x4d\xfc\xe2\xf4\x83\x9b\x4d\xc1\x02\xb7\x60\xa7\x37\x07\x1a\x2d\x83\x02\xb1\xbf\xfd\xd3\xd2\x88\x8d\xda\xdb\xd3\x6c\x58\x64\x99\x6d\x01\xc1\xe7\x29\x5c\xd4\xa8\xd5\x48\x41\xf8\x71\xc0\x6a\x2b\x6f\x09\xb5\xc6\xa5\x4d\x06\xd6\x2c\x5a\x71\xec\x4f\xa6\xee\x2c\xea\xc1\x65\x54\x2d\x35\x99\xda\x82\xbf\x43\x8e\xb7\xc5\x24\xf2\x8b\xd2\xe1\x28\x1a\x2a\xb5\xa8\x39\x6c\xa4\x52\x0e\x1b\xaa\x17\x3a\x89\xea\x6a\xb3\xff\xff\x6a\x16\x3a\xf1\xc4\x2b\xaf\x3d\xf6\xd0\xdb\xef\xd2\x9f\xfc\xed\x46\xab\xc4\xd6\x1b\x6b\xa5\x2a\x57\x45\xa0\xc2\xee\x70\x49\x6b\x9f\xd8\x20\x59\xcb\x6a\x2e\x38\xf6\xe0\xfe\x4a\xdf\x0d\x83\x0f\xfd\xaf\xda\x0a\x3a\x53\xe6\x35\xcf\xf4\x80\x47\x5e\xd0\x9c\xff\xdc\x46\xb9\xfe\xe9\x6d\x95\x03\x9c\x96\x2e\xe4\x9c\xbc\xc4\xe9\x19\x86\xfe\x43\x63\x54\xcb\x1d\xb7\x40\xfe\xb9\x25\x9a\xe7\xcb\xc0\xe7\xff\xbb\x86\xc4\x6b\x4b\x48\x2e\x21\xeb\x07\x25\x0a\x1b\xe7\x88\xf5\x03\xbb\x75\x64\xfc\x29\xec\x1c\x6b\x41\x41\xc7\x54\x8a\xc2\x10\x31\x84\xd2\x78\xd4\x1a\x37\xf6\x2a\x8a\x5c\x99\x17\x79\x87\xfb\x70\xe5\xa9\xeb\xf9\xb9\xcc\x67\xe4\xf9\x0d\x2a\xc7\xe8\xf0\xe5\x35\xbb\x55\x8b\x66\x74\x4c\x92\x86\x03\xe9\x31\x84\xf5\x98\xc5\x84\xeb\xc7\x5a\x6d\xd3\xc1\x49\xf2\x95\x8c\xc3\xd0\x6a\x34\x32\x60\xbb\x92\x80\x57\x8f\x59\x81\xfd\x63\xaf\x44\x31\xbe\x93\x5f\xa1\x8b\x2d\x8c\xc3\xc8\xea\x95\x44\xba\x77\xec\xca\xe5\x7c\xe3\x9f\xa5\x6c\x18\x53\x07\xd8\x32\xf0\x34\xb8\x42\x18\xb7\x92\x00\xd6\x61\x22\x0a\xc5\x4f\x52\xc4\xee\x7a\x23\x32\xd9\xd0\x13\x90\x28\x4b\x10\x6c\x14\x71\xbb\x68\x5c\x58\xde\x2a\x49\x9c\xd1\x5f\x1e\x2d\xe4\x34\x56\x8e\x2e\x80\xe5\x37\x26\xde\xb9\x6b\x78\x1e\x70\xdb\xf1\x07\xc1\x8b\x93\x31\xba\x8a\x2a\x7b\x63\x47\xf0\x49\xf2\x16\x1c\x09\x30\xa3\xf1\xa6\xdd\xbb\xeb\x0d\x16\xa0\x71\x81\x83\xf7\x4d\x99\x65\x1c\x1c\x91\x4f\x3e\x59\xf8\xf3\x63\x8a\xac\x0a\x4f\x1d\xe3\xf6\xb0\x03\x94\x8e\x2a\x45\x75\xa8\x44\x6d\x4f\x5b\x1c\x2c\x1d\xd6\x02\x89\xe0\xb7\x06\x09\xe7\x11\x66\x3c\x8a\x61\xc2\x23\x24\x81\x4b\xac\x07\x30\x77\x03\x20\xdf\x3e\xd1\x73\xa4\x09\xb4\x36\x1b\xc0\x57\xf2\x8d\x0b\x58\xbb\xc3\xe2\x90\xdb\xe4\x36\xb4\xb1\xb3\x0b\xe4\x1b\xbc\x62\x25\xf8\xf7\x87\xd6\xa2\x42\xdb\x87\xe0\xdf\x95\x22\x6c\x3f\x59\xa7\x6b\x06\x13\x87\x5a\x8a\x1f\x00\xab\x26\x82\xa8\x7c\xa7\x6c\xf0\x05\x0d\x7f\xff\xbb\x21\xe8\xc3\x5c\x49\xde\x38\x8f\xa9\x92\xc6\xc9\x0d\x9d\x7c\x9c\xca\x60\xef\x26\x89\x8f\x31\x95\x03\xd5\xf7\xf9\x31\xe0\x1b\x50\xb0\x2f\xd8\x0b\xd3\x49\x4b\x29\xab\xb3\xbb\xd3\x29\x7b\x40\x27\x5a\x59\xca\x68\x76\x8b\x26\x9e\xb9\x67\x90\x0a\x40\x36\x60\x87\x09\x77\x45\xa9\x0e\x26\x79\x49\x18\x97\xc1\xda\xc4\xb2\x39\x44\xa3\x49\x3d\x41\xf0\xd7\x02\x9f\x62\x01\xcc\x9a\xf9\x7c\xaa\x2f\x85\xa2\xe8\xe6\x48\xa8\xe3\xa8\xf7\xe1\x75\x3c\xe2\xf4\x52\x09\xe7\xa6\x93\xe8\xef\x18\x93\xcc\x98\x2a\x86\xfa\x87\x59\x2e\xe8\xb9\xff\x46\xfd\x45\xab\xfd\x9a\x18\x76\x50\xd6\xdf\xa1\xbf\x9e\x3c\xeb\x06\xdd\x93\x67\xe1\xf8\x5a\xab\x45\xb9\xff\x3d\x74\x4c\xa4\x54\xfe\x22\x26\xc7\xa3\x32\x3d\xb7\x8e\x22\x8e\xf0\x19\xc7\xbe\x47\x0a\x47\x4c\x11\x20\x0b\x60\x44\xdd\x8b\x67\xc6\x39\x1b\x1e\xfb\x90\x58\xcc\x46\xd5\x03\x00\xfb\x4d\x65\xfe\xc1\xa7\xc9\xe6\xe6\xba\x0a\x38\xd0\x7e\x45\x72\x6e\x45\x1d\xd2\x46\xeb\x2a\xd4\x4d\x6c\x75\x7c\x42\x57\x59\xd8\x42\x76\x9d\xe4\x12\xe6\x69\xb2\x99\x4a\x7e\x7b\xea\x16\x17\xc8\x1f\x5e\x1c\x2a\x2f\x6d\x9d\xe4\x2a\x58\x5c\x87\x15\x77\x74\x88\xae\xcb\xa5\x65\x93\xab\xd8\x52\x10\x2c\x6b\x9e\xa5\x1e\x54\xb0\xee\x93\x24\x96\xd3\x88\xb4\xf7\x20\x92\x74\x97\x52\xbd\xd4\x36\x6a\xaf\xca\x10\xac\xae\x3c\xda\xad\x0e\xc5\x27\x96\xf8\xb8\x84\xf2\xe4\x45\x36\x1b\xa3\x10\xc6\xe0\x5a\x68\x50\xc0\xce\xff\x71\x3b\x1a\x19\x00\x9f\x05\xcb\x71\x00\x3e\x44\x9c\x11\xdb\xd4\x40\x04\x26\xef\x16\x20\xef\xd6\xec\xb0\x87\x82\xa7\x4e\x51\x7a\xa7\x5e\xab\x05\x14\x7e\x79\xfd\x0a\xd3\xd2\x40\x5e\x2c\x2c\x0b\x15\x08\x1c\xf9\x51\x9b\xed\x0b\x60\x71\xcf\x71\x5f\x5f\x58\x28\x7f\x2e\x06\x6c\xa0\x7b\x5e\xfa\xa6\x2f\xe4\x2f\x54\x38\x1d\x20\xa2\x63\xf2\x23\x2a\x62\x0e\x98\x69\x83\xd7\xe4\xdd\x26\xfd\x4f\xe5\xd6\xe0\xa6\x61\x0f\x04\xda\x53\x14\xe9\x09\x80\x6c\x22\x79\xe1\xb8\x03\x24\x7f\xff\x05\x18\x26\x07\xcc\xb2\x05\x44\xf9\x73\x37\x50\xc0\x75\x80\xf4\x85\x0d\x3d\x6a\x01\x5c\x2e\x02\x51\x05\xdc\x91\x3f\xff\xd2\x86\x8a\xb4\xe0\x7c\x72\x81\xfc\x13\xdb\x7a\x85\x34\x8a\xca\xbb\xe5\x7d\xc3\x1e\x86\xc7\x83\x1e\xf4\x91\x0c\x91\x75\xcd\x66\xc5\xaf\x73\x98\xe5\x1b\x8f\x66\x42\xfe\x51\xe2\xe8\xae\xc2\x42\x93\xb9\x14\xc4\x45\x1f\x76\x5e\x4d\x39\x91\x34\xe3\x24\x3f\xa0\xb9\x38\x3c\xa5\x22\x3c\x2e\x8e\xf6\x4c\xb6\xbd\x33\x9b\x6a\x97\xb5\x4c\x28\x0f\x4c\x35\x8a\x06\xe3\xbd\x46\x56\xd3\x0f\xc6\x77\xdf\xbd\x77\x0e\x70\x66\x2e\x70\xc2\xa9\xb1\xe5\x4d\xcd\x6e\xbb\x63\x5e\x81\xa5\x38\x28\x55\xce\xbd\x3e\xe0\x6e\xac\x2e\x4b\x14\x15\x9c\x65\xd6\xec\xd6\x79\x8c\x40\xd7\xda\x7b\x53\x46\xd7\x86\xf8\x7b\xf6\x60\x1e\xad\x7c\xe4\x0b\x85\xa6\x37\x33\x91\xd9\xf0\x37\x4b\x8f\x9c\xdd\x92\xca\x1a\x70\xc8\x95\x48\x64\xa8\xb0\x51\x22\xa9\x70\xd1\x28\x40\x64\x59\xd8\x0b\x90\x54\x0d\x63\xe9\x54\x88\x59\x4b\x0c\x4b\x4a\xe0\x2b\xa4\x56\xa2\x1f\x4f\x96\x77\x64\xc4\x43\x24\x5a\xd1\xa7\xc3\x74\x48\x8d\xe1\xce\xbf\xbd\xa7\x10\x84\xf1\x6e\x18\x14\x82\x20\xb6\xcc\x06\x81\x77\x00\x9f\xc4\x3f\x0c\x97\x26\x19\x69\x02\x88\x86\x47\x2c\x8a\x95\xd9\x0d\xe8\x9b\x99\x86\xeb\x1a\xc0\xd1\xfd\x84\xe2\xd0\x04\x7c\xd1\x88\x44\x07\xa2\x3e\x02\x79\x10\x89\xb5\x41\x9f\x2d\x40\x4b\xc0\xe6\x23\xee\xc4\x4c\xe6\x1d\x85\x15\x0e\x1b\x12\xa9\x13\x89\xd2\x97\x7c\x73\xc4\xa9\xa1\x69\x40\x33\x40\x67\xba\x4d\x96\x93\x2f\x3c\xb3\x1f\x58\xaf\x84\x36\x74\x90\xd6\x14\x5c\x05\xc0\xee\xa7\x5f\x85\x9f\xa6\x65\x9a\xa9\x9b\x79\xd6\xcc\xba\xa6\x71\x91\x2a\xc1\xbe\xde\x15\x9c\xbb\xfe\xbc\x2b\x6a\xa6\x2f\xea\x8a\xd3\x7f\xbd\xff\xfe\xa1\x32\xad\x81\xe6\xb5\xd0\xea\x3c\x79\x3f\x08\x00\xf3\x03\x1f\x31\x21\xad\x41\x6b\x28\xfb\xe8\x01\xf9\x2b\xf9\xb7\xf0\xfe\xd7\xdd\x85\x62\xa2\xaf\xbd\xad\xaa\xd5\x17\xaa\x09\xeb\xdd\x4b\x83\x45\x13\x76\xac\xaa\x5f\xde\xd4\x58\xde\xec\xeb\x56\xe6\x21\x16\xfb\x90\xd1\x7b\x51\xdd\x3a\xbf\x5f\xdd\xd8\xd3\xd7\x8d\xfe\xfe\x75\xfb\x7b\x5a\x66\xe8\xe1\x75\xeb\x3e\xe7\xbc\x2b\x26\xad\x5a\x3d\x8d\x39\x73\xd5\xde\x7b\xdd\x5d\x09\x46\xd7\x6c\xe2\xfa\xf6\xc6\x8e\x70\x37\xa9\x17\x40\xba\xd7\xc5\xac\x82\x37\x47\x05\xb1\x0f\xbb\x1d\x2f\xc3\x90\x1e\x11\x22\xf3\x18\x5e\x39\x4d\x82\xee\x34\x25\x3f\xc2\x7d\x65\xd2\x17\x0c\x25\x43\x8d\x69\x2a\xd4\x66\x46\x69\x1a\xa5\x69\x94\x26\x38\x7b\x4c\xd4\x3f\xbd\x70\x88\xaa\x18\xe7\x47\x5b\x06\x6d\x95\xf5\xbe\xf7\xc9\x58\xda\xab\x60\x64\x11\xf4\x6c\x8c\x27\x6b\xf3\xf3\x98\x14\x26\x14\xad\xcb\xc5\x1e\x63\x62\x1f\x35\x6e\xa0\x1a\xf8\xc3\xfe\xa8\x05\x63\x64\x60\x41\x17\x07\x30\x67\x02\x96\x09\x2d\x12\xa6\x8a\xb1\xe1\xe6\xc7\x58\x1b\x0a\x01\x10\x52\x10\x16\xcf\x1a\xd7\x59\xd9\x11\x3c\xcf\x0b\xec\x7a\xff\xc5\xbd\x55\x2d\xf3\x02\xe3\x02\xe7\xcc\x9e\x77\xbe\x27\xe8\xa9\x0a\x76\xaf\x38\xac\x0d\x6a\x8d\x00\x42\x58\x1c\xa4\x0f\xaf\xe8\x0e\x56\xa1\xe3\xe7\xcf\xef\x3e\x07\xe5\x9a\xd7\x92\xf8\x6b\x35\x60\x59\xe0\x0c\x54\x54\xda\x1b\x6a\xba\xcb\xe7\x2c\x01\x4f\xce\xc6\xa7\x2e\x0a\xdf\x1c\x66\x91\xd8\xa1\x8b\x36\x04\x3b\x2a\x3b\xc7\xcd\x5a\xbc\x64\x4e\x79\x77\x4d\x83\xbd\xb2\x22\xe0\x84\x0c\x84\x00\x30\xd4\x88\x4b\xd5\x92\x34\x44\x3d\x23\x9e\xa6\xca\x65\x4c\x92\x70\xd9\x45\xc8\xf7\x48\xf1\x36\x5f\x86\x2d\x9d\x38\xa0\x87\x28\xfc\x75\x92\x95\x77\xca\xab\xa6\xf1\x94\xe0\x25\x53\x82\xd7\xce\x24\xe5\xf7\xde\x23\x30\x84\xea\x7a\x03\xa0\xde\x93\xdf\xc3\xcb\x07\x04\x64\x11\x25\x4e\x51\xc7\xe5\x6f\x8e\x63\xff\x5b\x3a\x91\xfc\x40\x7e\xc6\xb9\x4f\x71\xae\xdc\xe7\x04\x53\x3e\x50\x86\x0c\x05\xbf\x91\xa0\xe4\xac\x95\xa9\x7d\xc7\x8f\xef\x83\xf8\x17\x7b\xd7\x22\xb9\x66\x2b\xf1\x77\x6d\xc7\x33\x3b\xba\x61\xb6\x38\x5a\xa0\x78\xd1\xf3\xa8\xd1\xf3\x0a\x39\xaa\x02\x61\x3e\x1f\xf3\xc0\x6e\x0d\x02\x05\x04\x1d\x98\xd6\xe0\x10\x0d\x66\xbd\x7c\xd3\xf1\x7d\xf1\x58\xcf\xd9\xe7\x3c\x43\xca\x3b\xaa\x3e\xbb\xcf\x93\xd1\xb8\x3f\x47\xa7\x63\xde\x22\x5b\x79\x67\xfa\xfa\xe3\xfb\xd6\xde\x07\x67\xad\x59\xb7\x51\xa9\x40\x14\x7a\xe4\x9b\x92\xfb\x8e\x4b\x3d\x11\xb5\x22\xae\x61\x55\x35\x76\xc8\x3a\x74\xa5\x0b\xdf\x02\x6f\xd1\x1d\x70\x0d\xcf\xcf\xfa\x49\x2b\x3c\x49\x7e\xc5\xcf\x01\x7d\x9d\x92\xc5\x2a\xb0\x84\xf0\x32\x8b\x45\xce\x24\xe4\xc4\x8e\xe5\x7f\x4b\xb5\xaf\xda\xbf\x6d\x4f\xd4\x6c\x28\x34\x98\xa3\x7b\xb6\xed\x5f\xd5\xae\x38\xbc\xc0\x04\x4c\x0e\x5e\xdb\x36\xed\x69\xfa\x91\x34\xb5\xe0\xc1\x4b\x2f\x9a\xd3\xe9\xc2\x8c\x6d\xae\xce\x39\x17\x5d\xfa\xe0\x02\x65\x60\x54\xe5\x25\x2a\x8b\x0f\x11\xc0\xb6\x00\x87\xcf\xe2\x0b\x8e\xf0\x7e\x18\xbd\x3f\x22\x62\x48\x15\xf4\xb2\x29\xd4\xa2\x68\x72\x39\x89\x3e\xbf\x9c\xe3\x27\x9d\xe7\x04\x8a\x09\x2f\x4e\x12\xb6\xc5\xe4\xf2\x89\x98\x41\x4f\xd9\xa0\x23\x48\x7a\x4b\x01\x2f\x01\xd1\x20\xf2\x5d\x5e\x7a\xe6\x20\x31\x51\xb1\x38\x92\x88\x30\xe7\x29\xbf\x5d\xa4\xdd\x68\x22\xf3\x0e\x20\xb9\xaf\x2b\xe7\x5f\x1e\x54\x61\x1d\x83\x55\x38\xd4\x69\xb8\x63\x6d\x3c\x8a\x91\x07\xd4\xcf\x1a\xc7\xa5\x65\x1d\xa4\x7d\xe8\x64\x90\xc0\xc5\x40\xc5\xb3\x9c\xfe\xa1\x41\x63\x60\x68\x39\xa1\x17\x4e\x51\x1b\xaf\x53\x26\xbf\xdd\xab\xbc\x4d\x9b\xa6\xb4\x58\x19\x4b\xa9\xd9\xe8\xb0\x18\x58\xa9\x7e\xc2\xfa\xfa\x82\xe5\xfb\x96\x0b\xa0\x4a\xd0\x83\x14\xcd\xa0\xab\x58\xe5\x9d\xf7\xc8\x29\xb3\x96\x07\x3d\x50\xd4\xaf\x75\x3c\xb2\x75\x88\x4c\x55\xb4\xb7\xef\x41\xcf\xc6\xea\xa6\x69\x3e\x4d\x80\x37\xd4\x3a\x75\xde\xe9\x13\x26\x89\x65\x15\xb8\x56\xbe\x62\xbd\x08\x7b\x00\xaf\xc5\x75\x2b\x39\xe5\xe5\x14\xbb\x64\x65\xae\x6e\xc0\x8a\xa5\x57\x1a\xb3\xf0\x11\x04\x1f\xa4\x6a\x64\x53\xb8\xfc\xf1\x58\x09\x36\x3e\xf5\x13\x41\x15\x38\x6f\x7a\x74\xf6\x16\x2b\x14\xe4\x24\xaf\x35\xe8\x13\x46\x76\xbe\xfc\x5f\xf2\xdf\x69\x4e\xd0\x26\x2c\x86\x01\x9d\x19\xec\xea\xe9\x3e\x0e\xe6\x01\x56\xb0\x32\x8a\xc4\x0a\x92\xdf\xca\x37\x3e\xd6\xdd\x23\x5f\x66\xd6\x0d\x30\x5a\xfc\xd2\xac\xa0\x60\x3e\xd0\x26\x24\x2b\x48\x0a\xd0\xba\x65\xf6\xb3\xd7\x48\x19\xff\x21\xee\x84\xa2\x6f\x00\xda\x87\xb9\x92\xca\xf1\xd6\x87\xfe\x68\x1f\xc1\xb7\xe6\x4e\xdc\x2b\x3f\xfa\xa8\xb1\xd0\x5d\xff\xe0\xab\xf2\xa3\xaf\xca\x7f\xc2\xbf\xb7\x30\x43\x6b\x7e\xd2\xd4\x5c\x06\x07\xd3\x2c\x9d\xa8\xf7\xfa\x86\xa6\xd0\xcf\xe0\x3f\x30\x65\x76\x67\xe7\xcf\x86\xfb\xc1\xe0\x01\x87\x0a\xc6\x63\x75\x48\xc3\xca\x60\xd5\x73\x24\x1a\x25\xdf\xd4\x43\x5f\xbd\x56\x92\xe4\xd7\x40\x44\x92\xd6\x62\x8d\xae\x51\x92\xc0\x8b\x52\x1d\xfc\xc1\x88\x55\xcd\xab\xf1\x59\x10\x41\xf9\xea\x24\x7c\x45\xa3\x92\x19\xbe\x7b\x5a\x7c\x75\xe5\xf9\xe8\xd1\x61\x15\x90\xde\xa1\x55\xc1\xdf\xf3\x9f\x0f\x5f\x43\x8f\x53\x6e\x87\x6e\x0b\x22\xf2\x6b\xa4\x20\xf4\xe4\x91\xcf\xc7\xa5\xc2\x45\x53\x8a\xf9\x1a\xca\x87\xaf\x38\xd3\xf3\x41\x3c\x96\x89\x76\x51\x20\xf0\xb5\x23\x9e\xcf\x5c\x9d\x57\x1b\x29\x57\x49\x30\xb2\x01\x80\xd2\x02\x23\x0b\x0b\x46\x16\x60\x8c\x77\x90\x69\x7e\x6d\xa6\x21\x46\xbe\x83\xca\x51\xf5\x52\x5e\xc2\xc8\xa5\xe5\xcf\x48\x23\x8c\x7c\x61\x70\xc7\x18\x6d\x90\x20\xb1\x23\x16\xd2\xc3\xe2\xa8\x67\x61\x48\x9a\x80\xc4\x46\xa2\x41\xc9\x17\x06\x3e\x9a\x0d\x32\x7d\xe6\xa1\xab\xaa\xe1\x6a\xfb\x0b\xcf\x1b\x1f\xb6\x83\x3e\x06\xac\xab\x4d\x5f\x64\x92\xeb\xd9\x64\x32\xfd\xd3\xf4\x2f\xe8\xa3\x0f\xa7\x3f\xfd\x28\x1a\xbd\x4a\xfe\x74\x35\x58\x05\xbd\x4f\x80\x77\x4e\xae\xbc\xfb\x6e\xd2\x7f\x0d\xa7\x12\xdc\x7f\xab\x18\x72\x3e\x2d\x94\x7c\x3c\x8b\xee\x2b\xf9\xe2\x3e\x20\xb1\x1f\xca\xff\x1e\x7a\x3f\x3d\x79\x0a\x18\x57\x04\x7e\x08\x3e\xee\x18\x9c\xda\xc8\x3c\x13\x1a\x9c\x8a\x86\xb7\x57\xe4\xaf\x80\x1e\xac\xbe\xfe\xae\xbb\xc0\x5c\x30\xee\x67\x6a\x5b\x99\x79\x85\xb3\x63\x7e\xde\xb7\xaa\x8c\x43\xd5\x80\x43\xad\x14\x1e\x85\x43\xeb\x01\x8e\x3c\xb5\x39\x4f\x01\xb5\x45\x32\x56\x6e\x4b\x2b\x88\x67\xc0\x6a\xe9\x94\x32\x2a\xad\xb5\x6a\x18\x83\x7e\xd9\x0e\x79\xb3\x5c\x27\x6f\xde\xb1\x4c\x2b\x30\x1a\x2b\x1a\x31\x7b\xec\x1a\x8d\x69\x75\xfb\x57\x37\x2a\xc2\x76\xe3\xe4\xc3\x6f\x1f\x9e\xdc\xa8\xec\xdc\xf8\x55\xfb\x6a\x93\x46\x63\x07\x3d\x82\xc8\x7c\x4c\xc6\xa6\xa1\x7e\xb9\xdf\xae\x81\xda\x65\xd7\xde\x7f\xff\xb5\xcb\xb4\x50\x39\x69\x95\xcc\xab\x97\xec\xb6\xc2\xcb\x89\xf4\x7e\x8f\x7f\xfb\x64\xec\x0d\x39\x79\xbb\xff\x1e\x72\x20\x7d\xa1\x75\xf7\x92\xd5\x66\xc9\x2a\x2a\xdf\x3f\x91\x1b\x02\xa3\x38\xb6\xb0\x3f\x27\x61\x22\x55\x91\x04\x08\x5b\x2f\xe3\xcd\x91\x7a\x79\x55\xc9\x40\xa5\xfb\xca\x99\xc4\x08\x16\x70\x82\xf0\x79\x3d\x83\x4b\x8e\x9f\x2e\xa7\x86\xdb\xb3\x14\x1d\x9f\x48\x2b\x39\xa4\xdb\x90\x97\x33\xdb\xbd\x94\x99\x52\xff\x4e\x67\x13\x51\x20\x6c\x81\x5d\x8d\x7d\x02\x67\x2b\x44\xa5\x64\xf9\xff\xa1\x33\x18\x45\xe0\xa7\x0a\x64\xed\xd9\xa0\xf5\x43\x7c\x3d\x9c\x97\xbd\xb4\x22\xbd\xe7\x8c\x96\x1d\xb2\x9e\x82\x44\xf7\x24\x9d\xc1\xd3\x1a\xa5\x31\x8e\xf4\x9d\x1e\xe5\x4b\x9d\xac\x2f\x25\xed\x94\xc2\x1e\xa0\x63\xa7\x69\x6f\x26\x35\xe6\x4f\xd6\xe7\x05\xe4\x70\xbd\x46\x95\xc3\x72\x86\xfd\xfc\x72\x8c\xf5\x03\x72\x65\x00\xbf\x1d\x2b\x99\xcf\x39\xcd\x53\x6e\x2a\x8a\xad\xae\x59\xdf\x17\x4c\xb4\x49\xec\x44\x84\x23\x01\x10\xd9\x23\x04\xab\x40\x09\x66\x71\x20\xc7\xed\x8c\xa8\x9c\x18\xcd\xd0\x08\x15\x97\x61\xf0\x23\xa3\xfc\xcc\x27\x82\xd5\x62\xbc\xf5\x7d\x3d\x10\x8d\x49\xa3\x15\x5c\xcc\xae\xfd\xc9\x27\xf2\x87\xb7\x0a\x5a\x9d\x68\x7c\x15\x2c\x3d\xc1\x93\x13\x3a\x3d\x28\xce\xf7\x8c\x54\x22\xfa\xfd\x9f\x80\x29\x46\x60\x45\xe7\x45\xa0\x7f\xff\x56\xa3\xc5\x6a\xbc\x15\x14\x7f\xf2\x93\xb5\x2c\xd0\xe9\xc8\x51\xfe\x84\x7c\xef\xab\x46\x51\xa7\xa5\x5f\x1b\xe9\x2f\x99\xb3\xe1\x61\x9c\x93\x7c\x06\x0c\x32\x94\x13\x72\x1e\xa2\x4b\x8c\x62\x49\x78\x14\xbb\x58\x15\xfb\xbc\x5e\xb3\xd9\x62\x1a\x85\x9c\x9f\xbe\x49\x9c\x26\x82\x84\x24\x4a\xc1\x74\x32\x28\x69\xb4\xe8\x5d\xc6\x4e\x45\xb9\x57\xd8\x97\x89\x2c\x87\xde\xa5\x96\xcd\xcd\x16\x78\x90\x56\x96\x84\x63\xa8\x6d\xf9\x70\x46\x02\x26\x2b\x61\x0e\xbb\x15\x29\x0a\xcd\xe9\xe7\xe5\xe7\xc1\x7a\xd8\x87\x06\x64\xcc\x3d\x92\x3e\x8c\xc6\xed\x3e\x31\x46\x5f\x39\xb4\x3d\xb8\x21\xb8\xa7\x7e\x53\x7f\xfd\xee\x60\x90\xbe\x12\xed\xec\xc6\x3b\x7b\x82\x4c\xb3\xfc\x7c\x1a\x63\xad\xe2\xab\xea\x70\x6e\x7c\x55\x1d\xbe\x1e\x5e\x3b\xb4\x2d\x88\x2e\xea\xdf\x84\xf2\x6d\x08\xd2\x07\x82\xe8\x22\xb4\xb3\x3b\xb8\x61\x58\xbb\x28\xba\xff\xc8\x90\xe5\x31\x7c\x59\x15\x87\x59\x7a\x94\x5f\x2d\xf1\x5e\x55\x96\x18\x86\x7b\xab\xe6\xf8\xf7\xf2\xfa\xf6\xb0\x15\x86\x33\xf8\x75\xe1\x05\xca\x21\xb2\xe6\x43\x2b\x48\x6e\x39\x87\xae\x64\x3e\xef\x29\x1c\xc8\xae\xd7\xcb\xb5\x84\x16\x55\xc9\x49\xef\xcd\xa7\x40\x45\xe3\x24\x2a\x11\x7d\x92\xbd\x98\x2a\xc4\x7e\xd6\xe5\x20\x07\x56\x8e\xbd\xc1\x03\x39\xfa\x5f\xfa\xa4\x58\x9a\xc2\x41\x57\x36\x8d\xc6\xd0\xaf\x35\x83\x44\xaa\x54\xb4\xb8\x40\x42\x6c\x45\xaf\xdc\x4d\xdf\x17\xc4\x2b\xa6\xa2\xd5\x94\xd2\xc3\x64\x30\x58\x0c\x92\x76\xbb\x9c\xf4\x92\xb9\x0c\xc9\xc1\xe8\x19\x14\xee\x6d\x52\x66\xfd\x46\x75\x25\xc4\x54\x82\x16\x1f\x91\x10\x63\x5e\xec\xfe\x95\x2a\x2d\x71\xcb\x29\x74\x53\x39\xe5\xb2\xa0\x47\xca\x29\x41\xdf\x6f\xd4\x6a\x59\x4a\x12\x86\xee\x9a\xe6\x95\xd1\x7d\x41\xb2\x38\x14\x84\x49\x7d\x4a\xb0\x4a\xc3\x65\x81\x92\x3c\x59\x00\x84\x73\xb2\xc0\xa8\xcf\xf0\x18\x5c\xab\xce\xee\x95\xff\xa9\x8a\x03\x58\x26\x5a\x9b\xff\x16\x3f\x83\x6b\x55\x59\x00\xe5\x51\x32\xdf\x2a\xd1\x3f\xc8\x7f\x9f\xb9\x71\x9f\x43\x23\xbb\x4d\x7d\xa7\x0e\x1e\x3b\xa5\x13\x78\x05\xd2\x7e\x5a\xda\x02\x54\x32\x23\xd3\x68\x1f\xb9\x1b\x6e\xae\xab\xef\x01\x6f\x09\x16\xf9\x03\x8b\x51\xb0\x80\x80\x45\x1e\x84\x5e\x79\x20\x3d\x40\x27\x97\x16\x16\xde\x5c\xd8\x5d\xb8\x14\xf6\x0f\x63\x65\x7d\xe8\xe6\xba\x9e\x7a\xf0\x1f\x46\x7c\x89\x60\xc4\x97\xa4\x13\xd0\x0b\xd0\xb7\x29\x0f\xc0\x9e\xa5\xe8\x8a\x9b\x0b\x0b\x97\xf6\x9c\xee\xbb\x2f\xc0\xfe\xb5\xaa\xdf\x25\xcf\x15\x67\x18\x83\xe2\x40\x59\x40\x18\xd3\x6b\xdb\x4b\xe0\xe1\xd3\x9f\x2a\x0d\x01\xed\x07\x45\xb7\xc1\x18\x1e\xd1\xed\x7b\x00\x52\x22\xc2\xe3\x8a\x70\x3e\xd2\x72\x28\x9f\xc4\x5a\x60\x59\x7e\x49\x72\xe5\x08\xe2\x58\x69\x6d\x66\xd0\x29\x02\x7e\x81\x55\x96\x28\xe2\xb1\x30\xc4\x24\xc6\xca\xde\x28\x84\xb2\xcf\x40\x0f\x7a\x29\xfd\x9e\x70\xe9\x8e\x5f\x5c\x7a\x76\xbd\x4f\x77\xbf\x5e\xe0\x39\x3b\x5d\xd1\x57\xf5\xc0\x55\xa5\x06\x83\x0b\x86\x86\x35\xd7\x63\x28\x3f\x1a\x09\x7a\xb0\xb9\xa4\x3f\xdc\xb6\xa2\x67\xe7\x9a\xe6\x27\xfe\x68\xa0\xb5\x4e\xb0\x72\x47\x5d\x75\x7f\x99\x85\x85\xa9\x61\x8d\x95\x1b\xff\x21\x7a\xb3\x22\xe5\x21\xf6\x14\x60\x01\x16\x34\x79\x03\xd5\xf3\x70\x18\x0d\x15\x0e\xe4\xc0\x41\x37\x32\x45\x7b\xf3\x5c\x0c\x47\x39\x20\x82\x54\x32\x09\x66\xa5\xff\x74\x8a\x42\x1a\xf9\x07\xc4\x49\x51\xc9\x0d\x57\x8c\x98\x92\x73\x78\x6e\x18\xf1\xaa\x52\xc5\xeb\x50\x3e\x1a\xd4\x0c\x23\x47\x8a\x91\xad\xc4\x5c\x28\x3a\xe4\x94\x34\x51\x92\x53\x0e\xd1\x52\x0a\x93\xa5\x37\xab\x7e\x9e\x46\xec\xf3\x39\xfc\xcd\xd1\xcb\x02\xc5\x72\xc2\xed\x06\xa9\xe2\x40\x20\xed\x1d\xe6\x14\x3a\x62\xfc\x1a\x51\x26\x65\xb8\x50\x07\x89\x33\x97\xc9\x52\x9a\x4e\x96\x5a\x44\x07\x9a\x25\x26\x4a\x20\xe1\xd8\x7e\xfa\x32\x81\x7b\x02\x81\x40\x31\x48\xb9\xdd\x72\xa2\x58\xfe\xdd\xf7\x2f\x13\xf1\x53\x56\xec\xbf\x31\x07\x38\x63\x99\x12\xf8\xfe\x01\xe5\x59\xbf\xcf\xb7\x85\x8e\xe8\xdc\x77\xe5\x35\xa5\x05\xb7\x6d\xfa\xef\x34\x19\x89\xc9\x15\xf4\xeb\xc3\x79\x8e\xb1\x20\xf3\x2f\x54\xa6\x1e\x34\x22\x39\xec\x9c\x09\x08\x7c\xc0\x4f\x85\xb3\x22\x75\x28\x9e\x4d\xc6\x28\xc2\xd6\x8d\x84\x6e\x62\x2e\x65\x31\x08\x88\x22\x84\xa3\x82\x72\x0e\x25\x89\x17\x9e\x09\xc6\x14\xd3\x86\x8d\x8d\xf4\x9b\x01\xda\xa0\x67\x19\xa3\xe4\x74\xa3\x17\x20\x7d\x2a\xdf\xdd\xb6\x02\x37\xd0\x44\x48\xb7\xe3\x42\xad\x6c\x07\x67\x0f\xac\x5d\xaa\xd7\x72\x74\x39\x6d\x37\x32\x8c\xc9\x5a\xe0\x2e\x16\xf6\xbc\x54\x0b\xde\x36\x6b\x75\xb4\x93\x75\xcb\x4e\x9a\x06\xaf\x98\x90\x84\xe0\x84\xa2\x5e\xde\x3d\xfe\x95\x8b\xc5\x92\xe2\x42\x9b\x99\x61\x8d\x46\xc3\x5f\x8e\x18\x6c\x98\xa6\x85\x63\x59\x96\x81\x80\xfd\x40\x32\x6e\x36\x4a\x0d\xe3\x45\x61\x8b\x20\xbe\x05\x28\x07\x7a\xbe\xf1\x08\x36\xcf\x02\x9a\xa1\x69\x98\xdc\x64\x30\x08\x5b\x5c\xc1\x0e\x83\xc1\xb4\x49\x6f\xda\xbe\x9f\x66\xd0\x85\x00\xb2\x3c\xaf\xea\xe3\xf4\x10\x6a\x8f\xb6\x9c\x57\xed\xf0\x95\x7d\x05\xe5\x05\x1b\x02\x71\xf8\x16\x47\xa8\xb0\x39\xd5\x61\x4d\x81\x5c\x57\x57\x72\xe8\x21\xd4\xe4\x1d\x82\x28\x19\xcf\x5e\x81\x6b\xba\xe2\xeb\x9f\x3d\x73\x18\xa9\x08\xeb\xb4\x46\xa3\x8e\x2d\xeb\xa9\x9c\xdf\x0b\x6a\x48\x20\xd9\x1b\xe0\x4e\x51\xb8\x1b\xbd\xc8\x6b\xe5\xeb\x70\xce\xc3\xa8\x8b\x5d\x2c\x19\x2f\x15\xc4\x3f\x1e\xfd\xc3\x6e\x4d\x81\xee\x62\x3d\x80\x5a\xb6\xb0\x64\x79\xd7\xbb\xa2\x70\xa9\x51\x92\x2f\x7b\x42\x01\x35\x06\x54\xdd\x29\x8a\x7e\x0b\xe9\x0f\x2b\x15\x9e\xf5\xac\x88\x89\xbd\x18\xdb\x30\xf0\x93\x63\xbc\x02\xd1\x8b\xd7\x5b\xe9\x70\x95\x06\x1b\xea\xb2\x6b\x4d\x98\xa5\x5b\xad\x86\x4a\x25\x89\xa1\x85\xe8\xb7\x7e\x75\x44\x14\x2e\x37\x4a\x13\x77\x75\x77\x14\xb0\x16\xd3\x3a\xde\x6c\xd2\xc2\xcd\x7b\x83\xc1\xd9\xbb\x3c\xc1\xee\xba\x58\xb8\x72\x66\xf5\xc4\x71\x55\x05\x96\xe7\xef\x90\x8c\x97\x0b\x62\xc3\x86\xf6\x66\x91\xb3\x18\x66\x6b\x4c\x82\x91\x76\xc4\x5b\x17\x96\xad\xb8\xc0\x52\x16\x9c\x5e\x55\x1d\xad\xef\x89\x4f\x0a\xba\xc0\x8a\x5b\x3e\x70\x3d\x8c\x5b\xe3\x61\x6d\x45\x65\xc4\x89\x9e\x75\xb9\x0e\x42\x3d\x5c\xe5\xd2\x2c\x98\x55\x58\xeb\x1f\xe7\xb0\x99\xc5\x80\xbb\x62\x5c\x43\xd3\xb4\x71\x07\xde\xf4\x3c\x8e\x61\xa2\x1f\xe1\xfc\xbe\x32\x33\x27\x5a\x0f\x99\x00\xad\xa3\xc5\x40\x91\x63\x41\x87\xab\x22\xec\x0e\x48\xa2\xd5\x51\x1d\x6a\x9d\xb0\x48\x7d\x67\x7b\xd1\x3b\x6b\xcd\xc8\xe0\x02\xe0\xed\x2a\x53\x70\x98\x0a\x67\x9d\x87\xe3\x59\x01\x26\x94\x91\xc3\x33\xa1\xe0\xe5\xc0\xee\xc0\xd6\x9a\xbd\xa2\xf0\x80\xe3\xed\x1f\xdd\x0f\x4a\x04\x9d\xc6\xf6\x4b\xb3\x56\x7e\x1d\x63\x7d\x6c\xda\x77\x97\x5d\x9e\x4f\xd6\xd4\xee\x68\xf8\xcf\xeb\x70\xd1\x68\xf2\xfd\x7d\x52\x6d\x39\x8a\xb4\xc1\xb2\xb5\x82\x78\xf0\x71\xeb\xa3\xf2\xad\x66\x51\x34\x80\x8d\xaf\x6a\x8d\x17\x1b\xa5\x05\x73\x44\x01\x9d\xd8\x2c\x19\x2f\xc3\x79\x51\xb2\x65\xae\x48\x40\x0d\x91\xa8\x81\xca\x8b\xa4\x75\x5f\x40\x05\xf2\x57\x61\x4a\xb2\xdd\x4d\x11\x39\x6a\x31\xc2\x32\x52\x5f\x25\x92\x46\xe3\x6a\x24\xd3\xcd\x6c\xb9\x0e\x67\xe5\xe0\x92\x87\x50\xa7\x20\x31\x8a\xc0\xab\x6c\x7f\x23\xff\x4c\xa3\xd1\x89\xbf\x90\x74\xef\x4a\x41\xdd\x38\xfe\x67\x1a\xdb\xcf\x2c\x3a\xad\x46\xfe\xd5\xbb\xa4\xcf\xfd\x01\xf8\x95\x2d\xaa\x0a\x98\x26\x0a\xeb\x8c\xd2\x7c\x51\xe8\x35\x4a\x70\xa2\xd9\x6c\x16\xe5\x85\xa1\x85\xce\x45\x16\x70\xaf\x64\x16\x2c\xe9\xe7\x24\x63\xaf\x20\xce\x97\x8c\xeb\x04\x51\x7e\xd2\x28\xa9\xbc\xf7\x8a\xde\x51\x4f\x74\x75\xdc\xf1\x31\x57\x4a\x7e\xc9\xb2\x9d\x31\xf7\xe9\x64\x53\xca\xa8\xc6\x48\x7b\xfb\x70\x54\x57\x1f\xd8\x98\x7e\x49\x7e\x08\x7c\x4b\x16\x2c\x79\xc9\x78\x7f\xc6\x44\x9d\xb1\x5b\x43\xf7\x4b\xf4\xba\x97\x2e\x92\x13\xe0\x2e\x79\xcf\x7f\x9f\x3f\xd2\x91\x0d\x1d\xb8\x11\x95\x7d\xbb\x20\xe6\xf1\x0f\x69\x28\x03\x92\x76\x0a\xd0\x68\x7b\x1e\xea\x19\x52\x40\xb2\x5b\x1d\x75\x31\x29\xee\x73\xf8\x22\xe1\x00\x3e\x80\x94\x20\xe5\x80\xa2\x23\xd2\xa4\xc7\xd0\x01\x5a\x61\x92\xa6\xb3\xa5\xcd\x8d\x87\x74\xe6\xbd\xf8\xa4\x61\x5b\x3b\x4f\x67\x17\x1c\x78\x6c\xab\x87\xb3\x8f\x4c\x07\x00\x6c\x0b\xc8\xef\x7b\xc1\x5d\x57\x06\x26\x83\x23\x33\xef\x9e\x8d\x8e\x6c\xf4\xc9\xef\x12\xfc\xee\x77\xee\xe5\x9d\x47\x9c\xfc\x0f\x4f\xdc\x8f\xb6\x7a\x0b\xec\x7f\x13\xd7\xe7\x61\xdf\x35\x78\x73\xee\x62\x56\xa7\x33\xef\x77\xb1\x67\x81\x75\x67\xf3\xce\x3d\x4e\x7e\x25\x38\x77\x19\xeb\xda\x6f\xd6\xe9\xd8\x25\x1b\x71\x96\xeb\xfc\x8f\xa1\x31\x63\x3e\x28\x47\xea\x33\x83\x19\xbe\x1e\x4a\x26\x93\x69\xa4\x4a\xcb\xef\xa0\x1d\x74\xe8\x58\x32\xe9\x45\xbd\x34\x7d\xb3\xd3\x09\x7b\xd1\xaf\xa0\x83\xbd\x44\xd6\x56\x56\x96\xc1\x22\x93\xd1\xe0\x94\x6f\x06\xbd\x4e\xe5\xd7\x60\x34\xc9\x0f\xa8\x19\xb0\x7e\x5b\x7f\x8a\x62\xfe\x8a\xda\x31\x42\x4d\x25\x98\x43\x76\x4c\x7c\x22\x30\xbc\x2d\x10\xf5\x87\x6d\x01\x8b\x1f\x7d\x46\x71\x24\x05\x59\x22\xa1\x80\x05\x3b\x28\x3a\x6a\xe3\xd1\x88\x2d\x86\x81\x50\x3d\x34\x5d\x57\xc5\xf8\x09\x08\x69\x6d\x2b\x87\x77\xd0\xd4\x80\x76\x5a\x39\xe6\x5a\xf1\xc6\xed\xdb\x8c\x7c\x64\xe6\xb6\x8b\xe7\xdc\xda\x5d\x76\xab\x38\x55\x7a\xa9\x78\x63\xad\xc6\xcc\xe9\x8c\x5d\x1b\xdf\x4e\xf8\x6e\x9d\x53\x7a\xeb\xac\x9d\xbd\x2d\x27\x3c\x15\x53\x9a\x17\xd5\xce\xd2\x68\x1a\x43\x1d\x35\x13\xaa\x6a\x3c\xd2\x94\x82\x92\xe6\xda\xce\xf2\x09\x3c\xdb\xe4\x9f\x58\xd1\x14\x2a\x11\xe9\xe4\x93\x5d\x85\x87\xaf\x9c\x72\xce\xe4\x6a\x3b\x73\x6a\x10\x0c\x51\xa7\xc0\x53\x11\x70\x08\x80\xe2\x8e\x7b\x01\x18\xfa\x1a\x7e\x35\xc4\x17\x37\x9d\x9d\xbe\xa3\xa4\xbe\xa4\xc0\xc0\x41\xf9\xc7\x80\x66\x0d\x66\x97\xbf\x0a\x7c\xe3\x8b\xf8\x1c\x3a\x0e\x00\xf9\x35\x34\x3d\x68\x04\x47\x71\x95\x82\x8b\x41\xb0\x25\xd4\x78\x49\x6c\xe4\x77\xb0\x4a\xcc\x60\xde\x94\xcc\x50\x76\x01\xdc\x2c\x08\xe9\x07\xea\x4b\xa1\x37\x0b\x11\xe1\x45\xea\xe0\x6f\x05\x41\xee\x15\xec\xde\xd2\xfa\xc1\x81\x0c\xe2\x83\xc2\xe7\x91\xbd\x6f\x29\xfa\x6e\xa6\xe2\x36\x75\xf8\x2c\x18\x54\x7e\x78\x8c\xb6\xd5\x2e\x9d\x01\xa6\x7b\xe4\x3e\x7b\x1c\x3d\xb3\xd4\x2e\x74\xe4\x17\xa5\xfe\xa5\xb1\xa0\x28\x46\xa6\x99\x12\xc1\x8e\x8b\x9c\x7e\x3e\x57\x5a\x8c\x59\x95\xf6\x66\x75\x33\x20\x8c\x95\xc4\xf2\xa7\x1f\xd5\x69\x37\x87\x51\xce\x4b\xa8\x89\xd4\x1c\x54\xa3\x08\xa6\x06\x0a\xf0\x68\x32\x02\x0a\x0e\x53\x46\x7d\x52\x26\x1d\xa2\x55\xb1\x98\xe8\x2a\xd6\x06\x30\x85\x01\xf6\x82\xc1\x2c\x06\x00\x09\x1f\x36\x9c\x31\x2a\x61\x86\x82\x70\x80\x8f\xe0\xad\x14\x91\x98\xfb\x7f\x32\xd5\x80\xa9\xf0\x98\xf4\x97\x3a\xf9\xe7\x3a\xa3\x41\x2f\xa7\xf0\x4a\x5c\x8a\xf8\xb2\x60\xb7\x97\x8e\xf4\xd3\x60\xb3\x41\x8b\x49\xd3\x0c\xe2\x5f\x2f\x80\x71\xf9\x5a\xce\xa4\x17\xb4\xb6\x6f\xde\x92\x07\xa6\x57\xff\xab\x7a\xba\xfc\xe1\xe4\x8f\xef\xfe\x98\xe9\xfd\x5d\xb5\x99\xb1\x02\xbf\x61\xd0\x93\x01\x81\x32\x4b\x56\x96\x40\x6f\x9c\xec\x17\x2f\xfb\xe4\x2c\x68\x11\xb5\x5a\x1a\xd0\x5b\xff\xb2\x38\xfd\xb9\x46\xd4\x43\x08\x77\xd0\x97\xf4\xf5\x1d\x3c\xd8\xd7\x07\x0f\xa7\xfb\x14\xdb\x4f\x7e\xbd\xeb\x70\xbd\x83\xb9\x7a\xb3\xa7\xad\x37\x18\x51\x33\xfa\x3b\xdb\xe1\x7b\xd4\xfb\x8e\x61\xb5\x93\x4e\xdb\x0a\xd9\x6a\xff\x69\xac\x5a\xcb\x43\xb9\xea\x31\x17\x8f\x6a\x02\x1d\x92\xbf\x76\xa0\xfe\xeb\x57\x71\xd3\xb0\x5e\xd6\x40\x75\x62\x0c\xb9\xe0\x77\xbc\xe2\xe1\x2b\x06\x23\x1d\x21\xce\xb4\x0f\x07\xc6\xae\x32\xe3\xcd\x5f\x59\xc0\xaa\x7e\x92\x74\xe4\x24\xd9\x91\x49\xe7\x04\x29\xb2\x73\x8a\x22\x3b\xe8\xb7\x67\xac\x5a\xe7\x41\xbf\xff\xf3\x0c\x49\x65\xba\xcb\xd4\xdf\x94\xab\xff\xc8\x5a\x9e\xbe\x3d\x46\xad\xa0\x9c\x61\x9f\x19\x56\x01\xd9\x3b\x76\x6b\xc0\xfe\x11\x75\x1e\xd6\x1a\xb9\x76\xf2\x66\xab\xb2\x65\xac\xa6\x00\x5b\xce\xdc\x00\xa4\xcf\xb3\xaf\xab\x7d\xbe\x1d\x7b\x04\x07\x89\x91\x9f\x58\xee\x4f\xdf\xe7\x83\x56\x0c\xed\x1d\x0e\x85\xe3\x8a\x1c\x1a\x0f\x60\x5e\x42\x35\xea\x09\x7f\x00\x18\xc0\x00\xc9\x08\xd8\xed\x02\xf3\x91\xb0\x13\x17\x35\xd5\xb5\x76\x76\xd4\x4e\x4e\xdf\x79\x9a\x4a\x7f\xee\xaa\xef\xde\x3e\xa9\xb5\xca\x29\x86\x4d\xe6\x60\x68\xde\x1a\x33\xb4\xcd\xae\xe8\xfb\xc1\xc1\x73\x77\xdd\xeb\x91\xcb\xef\x07\x90\xd7\x88\xad\x73\x52\xbb\xfe\xd8\xd6\x37\x6d\x4b\x57\x6c\xc1\x58\x75\x8e\xb7\xee\x38\x77\x4e\x8d\x59\xc3\x6f\xe6\x19\xe3\xf6\x85\x8e\xc2\x6b\xd7\xac\x3f\xf4\x1c\xac\xde\xb2\x05\x3c\xc2\x3b\x59\xb3\xc1\x28\x36\x2e\x78\x26\xbd\x85\x1a\x55\xf7\x38\xf1\x86\xce\xd5\xfd\xbb\xc7\xb9\x11\xd5\x93\xbe\xab\x39\xbe\x47\xdd\xdf\xcc\xaf\xdf\x2f\xbf\xa3\x21\x18\xb5\xf2\x83\x3f\x1a\xab\xf6\x43\x23\xab\xc9\x46\xc6\x6c\x8f\x0c\x6e\x64\x42\x5d\x87\x5d\x9a\x00\x00\x40\xff\xbf\x79\xeb\x8a\xc3\xc6\xc8\x75\x3f\x16\xa3\x0c\xda\x79\x3b\xe1\x12\xe3\x78\x8c\xcd\x0c\x08\x6d\x2f\x31\x1b\x13\x48\x42\x0c\xc7\x0a\x15\x44\x5f\x9b\x15\x93\x82\x41\x1e\x2f\x2f\x51\x21\x97\x3b\x18\x74\xbb\x42\xfd\x21\x97\x4c\x6c\xbc\xc0\xeb\x0a\x31\xfd\x71\x13\x5d\x65\xb1\x98\xc2\xda\xc6\xc4\x65\x25\x5d\x96\x89\xb7\x2f\x9c\xb1\x2b\xe0\x0a\x95\x14\x38\x7b\x6b\x3a\x7c\xa2\x4b\xab\xe5\xf5\x85\x56\xc9\x55\xd5\x59\xed\x33\x69\x81\x24\x89\xb4\xa0\x61\x80\x6d\xe6\x16\x62\xb5\x41\xf7\x84\xee\x6c\x00\x07\xfa\x5d\xd0\x56\xe1\xed\x6a\xa9\x6f\x69\x08\x6e\x9a\xd4\x05\x8b\xdd\xae\x72\x00\x82\x2e\x78\x49\x41\x10\xc2\x2d\x89\x85\x3e\xb1\x39\x58\x16\xae\x68\xb6\x4a\xb6\xe2\xda\xd2\x66\x8f\x33\xd4\x55\xe1\xe7\x9c\x56\x61\x8b\xba\xe6\x8f\xc6\xfd\x04\x89\x31\x73\xab\x38\x8c\xd9\x97\x37\x52\x83\x0f\xda\x6d\x44\x1b\x86\x0e\xec\x04\x43\xe0\x8c\x31\xf9\x2f\x54\x68\x8c\xd5\x26\xc1\xed\xd1\x44\x63\x0e\x35\xf2\xc7\x5b\x4f\xd7\x10\xeb\xe3\x60\xf3\x4c\xf9\x6f\x8c\x46\xa0\x45\xd1\x0a\xb4\x26\x5f\x75\x67\x95\x4b\xb2\x16\xea\x79\xad\xd6\x25\xfa\x3a\x6a\x7a\x9d\x05\x25\x21\x57\x60\xd7\x8c\x85\xb7\x4f\xb4\x74\x95\x5c\x96\x68\xd4\x86\x4d\x16\x4b\x15\x4d\x67\x5a\x22\xfd\x17\xa5\x0d\x48\x7b\x3c\xdc\xb2\x68\xe6\x16\xc1\xea\xe4\x82\xa5\x33\x42\x4e\x4f\x73\x69\x6d\xb1\x4d\xb2\x36\x57\x84\xcb\x82\xcd\xa2\x6f\x61\x62\x0b\x84\xc1\x02\x78\x89\x2b\x08\x40\xb9\xcb\x5d\x0c\xbb\x26\x6d\x0a\x36\xa0\x86\xeb\xf2\x62\x14\xfa\xcc\x5a\x86\x96\xd8\x91\xca\xa9\x16\xd4\x1a\xab\xa9\x8b\xa9\xab\xa8\x3b\xa9\x47\xa9\x5f\x10\x5e\x13\xec\x19\x8f\x57\xc9\x22\x18\x5a\x2d\x88\x04\x46\xf4\x7f\x94\x45\x7f\xaa\x11\x2f\xa2\x2e\xdf\x5b\x58\xd5\x47\x08\x65\xc1\xe2\x23\x5e\x65\xb0\x59\x33\x2c\x31\x68\x40\x24\x4e\xb0\x45\x20\x60\xb3\xa2\xdc\x75\xb1\x3a\xcc\x69\x84\x83\x34\x6a\x41\x1d\xa1\xa5\xf3\x79\x09\x3a\xa9\x0a\x7e\xe9\x25\xfd\x0c\x89\xf7\x7c\x38\x40\xc0\x30\x6d\x11\x4c\x74\x4a\x3c\xb6\x90\xb8\xa4\x2c\xdc\x61\x20\x0e\x8b\x5a\x8e\x80\x5a\x8e\x51\x0b\x78\x37\x15\x59\xcc\x66\x4b\xd1\xd3\x13\x27\xa6\x5f\xe8\x9e\x36\x13\xfc\xa4\x3d\x1c\xf4\x69\xb9\x89\x00\x08\x56\x3b\x68\xe3\x0d\xe3\x02\xbe\xf6\x76\x6f\xc9\x38\x03\x3f\x08\x69\x83\x3b\x5a\x57\x64\xb3\x16\xad\x75\xdb\x2e\xf3\x3b\x39\x20\x5f\x92\x48\x40\x9b\xa4\x9b\x58\x7e\x85\xfc\x77\xf9\xb3\x2b\x2a\x26\xe8\xac\x56\xdd\x84\xf2\xfd\x30\xb4\xbf\x1c\xa5\xd3\xc6\xb3\xa6\x47\xa2\x33\x79\xaf\x26\xa0\x9f\x06\x7c\xb6\xa2\x9a\x88\xdb\x66\x73\x47\x6a\x8a\x6c\x4f\xb4\xb7\x13\x38\xeb\x76\x4e\x8f\xee\x0e\xbe\xce\x5f\xe0\xf9\xe4\x8e\x5a\xf3\x80\xf9\xa8\x3f\x12\xf9\xeb\x64\x79\x31\xb8\x7f\xf2\x1e\xf9\xba\xd2\xca\x42\x4b\x10\xf8\xe5\x7f\x3a\xa1\xa9\x18\x38\x37\x1e\xaa\xb3\x95\x8d\x2b\x01\x9f\xdd\x55\x5a\x66\x7b\x52\x5b\x24\xd8\xc5\xd2\x90\xbb\xe9\x92\x26\x77\x28\x54\xd4\xd0\x35\x21\xe2\x02\x06\x9b\x9e\xae\xbf\x3d\x12\xb9\xbd\x2e\x4d\xff\x64\x6e\x45\x13\x6b\x32\xb1\x4d\x15\x0b\x8f\x3d\x32\xaf\xbc\x19\xa7\x9b\xcb\xe7\xd1\x4d\xa0\xf4\x97\xbf\x74\x2c\x75\xac\x8b\xff\xfa\x82\xbd\x8d\x45\xe8\xda\x46\xb2\x71\x37\x83\x2d\xf2\x5f\x8a\xcd\xd0\x09\xcc\xf2\xef\x83\xa2\xbb\x12\x68\x86\xaf\xe1\xa2\xaf\x03\x8d\x97\x7f\x21\xf1\xb2\x99\xfe\xb1\x84\x5a\x45\xed\xa6\xf6\x53\xb7\x51\x0f\x13\x3d\x1d\xa3\x14\xa2\x77\xcd\x22\xa1\xa7\xae\x36\x18\xc1\x78\xba\x96\x88\x6f\x8c\xd7\x92\x79\x79\x51\xd4\x3b\xa2\xe4\xe5\x05\xa3\x01\xd2\x61\x5a\x40\x64\xd4\x8b\x8d\x63\x86\x1b\x3f\xda\xad\x25\x0c\xb8\x3c\xe7\x25\x5d\x04\x43\x86\xa3\x5e\xe1\x25\x3d\x04\x44\x68\x74\x77\x0c\x9e\x1c\x91\x32\x7d\x4f\xe9\x67\xb8\xef\x05\xc7\xe8\xa1\xf4\x2b\x61\x87\xdd\xee\x08\x83\x39\x67\x9d\x35\xd4\xb8\x41\x7e\x69\xfd\x6a\xe0\x5d\xbc\xd8\xe3\x16\x69\xb0\x58\x63\xa8\x1a\x1f\x03\xc7\xb4\x96\x58\x6d\xf9\xe2\xc5\x95\xe3\x63\x16\x2d\x98\xb3\x04\x0d\x6b\x55\x8f\xb9\xc3\xed\x1d\xe1\xc2\xa2\xf0\xa4\xa9\x48\x51\x81\xe9\xfe\x05\x0b\xe0\x1b\x2e\x61\x51\xe3\xd3\x69\xd7\xd3\x8d\x8b\x8d\x2e\x94\x6e\x7a\x0a\x7e\x4c\xd2\x43\xae\xb5\x17\xae\x16\xaa\x83\x85\x7d\x53\xc0\x93\x85\xa1\x8e\xf6\x50\x61\x61\xa8\xbd\x23\x54\x08\x66\x2d\x89\xd6\x56\x19\x35\x4b\x00\x2d\xba\x3d\xa0\xe4\x3f\xdb\xed\xa0\xd2\xde\x51\x55\xd5\x71\x78\xf9\xf2\xf4\xaf\xc0\xe7\xf2\x0f\xca\x6c\xb4\x17\x9c\x23\x5f\x58\xe3\x0c\xb6\x2c\x7f\xa1\xd3\x55\x1f\x7b\x2f\xbd\x7e\x7c\x3c\xee\x9e\x6b\x8c\xe8\x4a\x26\x2d\x5c\x37\x2b\x18\x89\x04\x67\x1d\x43\x9b\xa8\xdb\xad\xa5\x7f\xf1\xd6\xa4\x49\x6f\x4d\x4e\x2f\xfc\x74\x5b\x53\x37\x67\xb3\x71\xdd\x4d\x9b\x3e\xc7\x69\xde\x6a\xe5\x51\x9a\x11\xe4\xcd\xf2\x3f\x80\x69\xda\x81\x75\xf3\xe4\x6f\x27\x3f\x3c\x1b\x5d\x1d\xea\x7e\xb8\x1b\xdf\x64\x8e\x6c\x8c\xb7\x06\x9d\x11\x70\x40\xbe\xce\x07\xed\xe5\x60\xb7\xe2\x4b\x89\x79\x73\xff\x4d\x49\x38\xfa\x1f\x70\x8a\x06\x1d\x97\x6a\xc3\x19\x85\x19\xaf\x0a\xdb\x32\x8b\x32\x20\x06\xf0\x41\x38\x5f\xf7\xb5\x3b\xf4\x85\xcd\xaa\x4b\x03\x70\x97\x41\xaf\x75\x7c\x51\xea\xa2\x5f\xd6\xeb\xd3\x5f\x82\x6e\xbd\x4e\x67\xff\xa2\xcc\x29\x1f\x13\x21\x28\x08\xff\xc3\x4e\xaf\x11\xe5\x69\x55\x7e\xcc\x5b\x80\x5e\xa1\xc9\x54\x09\x56\x9b\x6d\x43\x67\x81\xf4\x2d\x56\x8b\xa9\x12\x9e\xe7\xa5\xaf\xa9\xcc\x8c\xd1\xca\xd8\x24\x65\xf9\x45\xf0\x7a\x0f\xb6\x20\xd8\x68\xce\x81\xbd\xb0\xe2\x80\x1c\x01\x76\x40\xf6\x62\x61\x80\xc4\x70\xc7\x28\xe3\xcb\x1e\x5b\xf1\xd3\xa2\x86\xd7\xec\x7e\x5e\xab\xd5\x98\x9f\x29\x96\xe8\x38\x6f\x79\xd6\x23\xc9\x6b\x90\xba\x6d\xf5\x3e\x2d\xf2\x1a\xad\x3c\x04\x6e\xd1\xfc\x7e\xd8\x22\x35\x0d\x3e\xf0\xeb\x0d\x96\xdf\x02\xf9\x87\x82\x60\x2c\xa1\x67\x1b\x02\xe9\x30\x94\x7d\x01\xa4\x60\x83\xf7\x01\xfc\x4f\xf3\x15\xa3\x31\x6b\x28\x1d\x4f\x31\xff\x46\xa9\x4e\xb2\x86\x2f\xd5\x32\xc5\x00\x83\xde\x2b\x6c\xf6\x45\x00\x53\x73\x9a\x80\x80\xf4\x04\x5f\xa8\xa4\x1a\x2a\x33\x09\xea\xd9\x2d\x20\x44\xf8\xe6\x5b\xb9\x48\x0c\xfe\x0a\x7c\x24\x17\x3e\xf3\x00\x68\xe8\xec\x04\x5e\xc1\xe7\xf4\x7a\x04\x4e\x0a\xa3\x52\x02\x20\xf1\x25\x82\x20\x78\xbc\x4e\x1f\x1a\x21\x06\xe5\x2b\xde\x90\xdf\x18\x5f\x53\x52\x12\x9c\xe0\x1c\x9d\x43\xf0\x82\x41\x70\xf3\xc9\x34\x58\xa7\x65\x19\x9a\xe6\x74\x66\x87\x89\x2b\x58\x1a\x4f\x5c\x37\xae\xf4\x8a\xeb\xae\x8b\x2f\x46\x13\xb2\xc3\xa4\xe3\x68\x5a\xc2\x2c\xd5\x0c\xab\xf3\x16\x8c\x3a\x6f\xc6\xe7\x45\x4a\xc1\xc1\xe2\x52\xec\x01\x62\x5b\xc5\x0c\xc8\xc5\x68\x58\x60\x6c\xc0\x16\xe6\xa3\x20\xea\x40\xff\xe2\x36\xad\x01\x29\xec\x9f\xcb\x3f\x92\xed\x6c\x85\x6c\x47\xfa\xb8\xe3\x7a\xb0\x00\x00\xb0\x30\x3d\x1b\x2c\x90\x45\xf9\xc7\x6c\x15\x98\x23\x3b\xe4\x07\xc1\x42\xf0\x89\xfc\x63\x59\xa4\x5b\xe4\x37\xe4\x3f\x83\x36\xf9\xa3\x73\xe4\xdf\x13\x3e\xf6\xe0\x39\x3d\xa0\x10\xb3\xa5\xc9\x1f\x31\xbf\x95\xff\x2c\xbf\x09\x04\xf9\x9f\xf2\x3f\xe4\x9f\x83\x22\x7a\x8f\xfc\x73\xf9\x9f\x60\x3c\x12\xde\xf5\x68\x5c\xfa\x8a\xf8\x98\xe8\xd1\xc8\xa4\x94\x07\xe3\x3f\x07\x2c\xe8\x2f\x18\x67\x79\x4c\x49\x8a\xff\x68\xc0\x6b\xb1\xe7\x1b\xab\x1d\xbc\xbb\x9f\xbd\xb3\x7f\x68\x8e\x8f\x36\xf9\xd2\x8b\xda\xe1\x3b\xed\xe9\xff\x5e\x0b\xd7\xae\x7d\x0f\x7c\x90\x94\x03\xe9\x47\x69\x6f\x0f\x18\x48\x27\x61\xb2\xe2\x8e\xfb\x6e\x87\xae\x43\xf2\xb1\xeb\xe0\x93\xbb\xd2\xa7\x76\xd1\xbb\xd2\x17\xf7\xc0\x4b\x4e\xde\x75\xe4\xc8\x18\xbe\x17\xb3\xa8\x75\x39\x2f\x97\x0c\x18\x6d\x06\xe7\xb6\xc4\x1f\x42\x72\x11\x96\x8e\x68\xbb\x95\x53\xfa\x80\x87\x8e\xd5\xda\xb1\xf4\x04\xe2\xad\x74\x88\xa0\xd8\x62\x39\x82\xa6\xcc\x79\xe3\x9c\x39\x37\xcc\x65\xdc\x34\xbc\x1f\xcb\x4f\x7f\xfc\x31\x98\x0a\xe6\xc4\xba\x62\xb1\x2e\x79\x8a\x70\xe5\xd4\x0b\xe7\x17\xd5\x76\x59\xf5\x26\x16\xb7\x1c\x6b\xd2\x5b\xbb\x6a\x8b\xe6\x5f\x38\xf5\xca\xd3\x9f\x82\xe7\xb1\xba\x8f\xde\x5c\x24\xc7\x16\xbd\xf9\x91\x8e\x25\x69\xf0\x32\x4e\x43\x3b\x71\xe8\x00\xf7\x2a\x4f\xf9\x98\x3c\x24\x96\xfc\x9e\xb7\x1d\x7e\x4a\x3e\x6f\xf4\xfd\x49\x7a\xd8\x77\x6d\x22\x38\x1f\x23\xfd\x65\x22\xd9\xc8\xd7\x4c\xb4\x0a\xa1\x3a\x52\xbe\x34\x70\xeb\x45\x8f\x5c\x74\xd1\x23\xf0\x11\xb2\xc9\xf0\x18\x29\x5f\xe0\xd0\x03\xf8\x98\xfa\x2f\xff\x39\x10\xcd\x5e\x98\x07\x5c\xf2\xb1\x11\x2d\x88\xc4\x7d\xc3\x5c\xb5\xa8\x5f\xcb\xe7\xc1\xd8\x72\x39\x2a\x47\x97\xf7\x42\x1d\x18\x1c\x89\x94\x70\x48\x7e\x7d\x00\x3e\x96\x9e\xd1\x0f\x6a\xc6\x8a\x4f\xee\x66\x2f\x61\xef\x41\xfa\x04\x8e\xae\x6c\xc7\x7d\x01\xd8\xb9\x30\x8e\x33\x8a\xa1\x77\x57\x85\xc9\x72\xd1\x4b\x44\x6f\x53\x42\xef\xb9\x84\x45\xbd\x01\x3b\x4e\x23\x69\x51\x22\xf1\x10\x48\x86\xa4\xd1\xfc\xd5\x06\x90\xb8\xe3\x01\x9c\xc4\x11\xdc\x85\x20\x3a\xcc\xe0\x33\x98\x33\x23\x5e\xc2\x62\xdf\x0f\xba\x5a\xb3\x3d\x1a\x2e\x2a\x0c\x95\x74\xc6\x37\x0a\x2f\xae\x6c\x9b\x4e\x33\xd7\x2f\x5d\xb2\xf3\x23\xeb\xd4\x8a\x1a\xf9\x03\xf9\xb3\xf2\xaa\x84\xe8\x59\x1a\x6f\xfe\xe8\xfd\xb6\xe8\xd2\x05\x1a\x93\xb1\xa2\x64\xc1\x1b\x2f\xac\xab\x9a\x32\x27\x61\x2d\xf0\x72\xe2\x1f\x61\x7c\xc0\xc6\x99\x9f\x70\xcd\x67\x2b\xca\x7d\x43\xf2\xad\xdf\x1c\x32\xd9\x8c\x2c\x0f\xb5\x01\x9b\x4b\x4b\x17\xf9\xeb\x4b\x3c\xbb\x8f\x83\x5d\x60\xdc\x6d\xcd\x66\x00\xef\x6b\xeb\xf2\x5a\xe6\xcc\xb1\x88\x86\x26\xcb\x86\x2d\x15\x85\x17\x4e\x5a\x92\xd4\x68\x6e\x86\x3b\xdd\x01\xad\xa6\xba\x86\xd7\xf9\x5d\x85\x01\x2d\x5f\x54\xa8\xd1\x04\x86\x44\xd7\x9a\xf6\x4e\xeb\xf8\x6a\xda\xa2\xb1\xfa\xa3\x81\x9e\xe7\xcd\xda\x1b\x6e\xe0\xfc\xf5\xf4\xd3\xf7\xcb\x4e\x4f\x5d\xa1\x65\x4f\xc8\xbd\xc9\x50\x34\xce\x5d\xa7\xad\x7d\x69\xd7\x43\x53\x5d\x95\x1e\x8f\x49\x5f\x25\x06\x17\x56\x75\x59\x5b\x09\x0e\xac\xf2\xae\x34\x64\xb4\x6f\x44\x3a\x39\x61\xb7\x0e\x11\x2a\xe2\x58\x9c\x84\xb3\x93\x50\x7d\x09\xb7\x0f\x1e\x33\xb1\xf2\x81\x46\x55\xa9\x2e\x16\x0a\xa3\x8f\xc6\x04\x08\x87\x21\x6e\xd8\x18\xe6\x53\x60\x39\x5e\x69\x6b\x0f\x8d\x8e\x33\x58\x57\x11\x47\x09\x86\xdd\x73\x4a\xca\x41\x79\x78\xde\x34\xcd\xa2\x7d\x7d\x34\x8c\x57\x4e\xbe\xf6\x49\x6b\x7b\xb8\xe2\xb6\x07\x2b\x42\xed\x36\x63\x95\xdf\xf3\xe2\x5b\xbe\x92\xda\x7a\x3d\x6b\xba\x4b\xee\xbd\xdb\xc0\xba\x4c\xd5\x77\x7c\xfb\x98\xdf\x63\xba\x5c\x6b\x29\xdf\xf4\x5b\xf9\x1f\xfb\x96\x87\xca\x23\x8c\xc6\x5e\xc2\x01\x0d\x27\x1a\xd7\x3f\x06\xe8\x27\x9c\xc5\xc5\xcc\x78\x50\x3a\xcc\x9a\x77\x6b\x79\x95\xdd\xba\x5e\x74\xc4\x5a\x26\x9e\x67\x58\xda\x5e\xb3\xc8\x5a\x3c\x07\x34\xda\x5c\x1c\x6b\xb5\x72\x7c\x81\x55\x72\xf2\x48\xb1\x60\xf9\x82\x34\xcd\x87\x0b\x98\xbe\x3e\xce\x70\x6b\xfd\x6c\x77\xd5\x2a\x69\x42\x1f\xfc\x55\xd4\x1e\xf7\xb5\xb9\x0d\x7e\x93\x75\xbc\xa7\xe3\xaa\x97\x4b\xd8\x3a\xab\x5f\xdf\x6d\x2d\x5c\x62\xb4\x86\x6c\x40\x0f\x6a\x47\xcc\x43\x80\xea\xc0\x31\x60\xa8\x59\xfd\xd8\x1e\x88\x87\x95\x2a\x1a\x49\x62\x51\xd4\x9f\x08\xc2\xa0\xcf\xe6\xb3\x58\x3d\xa8\x05\xe9\x47\xba\x1d\x8f\x2c\xee\x3d\xb6\x69\xa6\xef\x81\xa9\x5b\x3a\xc6\x5b\x59\xc0\x33\xff\x0d\x66\xc8\x8f\x1a\xbd\xed\xe3\x67\xbe\xf1\x59\xa0\x15\xc0\xfa\xa5\x17\x5c\xd0\x08\xbd\xef\xba\x16\x2e\xdb\xb8\xb0\x92\xe5\xe5\x45\x43\xe9\x93\x9e\xba\xa8\x07\xc0\x7c\x3b\xbf\xc2\x20\x1b\x46\x53\x5b\x15\x8c\x5a\x7c\x51\xec\xd0\x81\x06\x3e\x1e\x09\x84\xf8\x59\xad\x60\x94\x2d\x74\x53\x6b\x45\x53\x49\x5d\x81\x0e\x80\x53\xd4\x71\x0d\x60\x0b\xa2\x6b\x3a\xf6\x96\x2f\xbc\x6d\xd5\xa4\xcb\xc1\xdd\xf9\xed\x37\xfd\x29\x3b\x70\x94\x8e\x73\x80\x6b\x7e\x01\x26\xeb\x2a\x16\xf4\x2e\x28\xb8\x4f\x5e\xde\xb0\xad\x6f\x02\x04\xe3\x99\xea\xe1\xb6\x50\xfa\x54\x02\xa6\x51\xdd\x31\x6a\x8f\x7d\x6c\x95\x1e\x7e\x65\x36\xca\x77\xeb\x8c\x82\x4e\xbe\xc3\xa8\xd1\x5a\x55\xbc\x40\xa4\xb4\x99\xe5\xa4\x4e\x07\x92\x66\x49\x62\x88\xcd\x62\x30\xe3\x53\x42\xc1\x34\x9b\xc2\xf7\x54\xfd\x56\xb2\xb0\xc9\x71\x35\x48\x0c\xa6\xb3\xf7\xb1\x99\x8d\x60\x39\xbe\x3b\x58\x65\x64\x24\x69\x90\x38\x70\x33\x03\x21\x33\x40\x37\x97\x93\x66\xe5\x1d\x25\x00\xcd\x53\x74\x9a\xdc\x33\x83\x82\x9f\xc1\xc0\x77\x28\xe0\x19\x3c\x85\x4b\x30\xa2\x50\x70\x60\xf8\x33\x56\x0a\xa4\x06\x8a\x1f\x32\xa0\xb9\x94\x7a\x4f\xc5\x2e\x3d\x1c\x3d\x1f\xb3\xea\xa4\x70\x11\x46\x94\x0a\x5e\x8a\x9a\xe2\x4e\x41\x93\x5f\x05\xd4\x40\x59\x7f\xfc\xcd\xa8\x3d\x43\x24\xea\x51\x55\xe7\xb0\xb0\x1e\xf0\xd3\x30\xaa\x4a\xdb\x58\x66\x27\x1a\x9f\xc2\x11\x0a\x32\xdc\xaa\x0a\xd1\x9d\xc3\x6a\x67\x37\x87\xe7\x5d\x92\xac\x59\xb2\x60\x42\xcb\xec\xd9\x91\x9b\x6f\xbc\x7e\xf3\xe6\xa3\x53\xd7\xf7\xfa\x2b\x57\xae\x9d\xb2\x63\x79\x5d\xdd\xac\xc0\x84\x03\xf2\x87\x45\x9e\xb6\x58\x2c\xd8\x4e\x4f\x9f\xf6\x08\xa0\xd1\x0c\x33\x61\xf7\xee\xe7\xbd\x5e\x9f\x1f\xed\xb0\xff\xfc\xe8\xd0\x41\x8f\xc7\xef\x9f\x50\x92\x68\x8f\x2c\xdf\x7c\xd1\x8b\xcc\xce\x96\xe9\xd3\xdb\x62\xa2\x9e\xbb\xf1\x9c\x0d\xe3\x68\x33\xcd\x18\xb2\xfe\xfc\x04\x8b\x5c\x91\x0e\x28\x60\x09\x5a\x08\x9b\x93\xba\x85\x3f\x4a\x2f\xc0\x7f\x5c\x72\x68\x3b\x76\xed\x82\x62\x7a\xfb\x72\x58\x09\xff\x2b\x7d\x2e\x8c\xa6\x77\x0c\x7d\xbe\x1b\xde\x48\x9f\x37\xf4\x31\xbc\x03\xbb\x75\x2b\xb8\xb3\xec\x1e\x32\xdf\x17\x22\x49\x74\x06\xd2\x81\x28\xaa\x36\x46\xe6\x27\x46\xdd\xb2\xca\x2c\xa6\x74\x6e\x05\xca\x92\x04\x54\xb6\x60\x75\x97\x2c\x2e\x84\x89\x8d\x10\x07\x5a\x62\xef\x7a\xec\xc9\x5a\x8c\xdd\x18\x70\xa0\x38\x4f\xbe\x0c\xf5\xc3\xa8\xb5\x83\x0f\xbc\x0e\x87\xd7\x0e\x8e\x7b\xed\x76\xaf\x63\x68\xb0\xac\xb9\x69\x41\x73\x33\x33\x2b\x51\x39\xbd\x79\x41\xf3\x81\xe6\xf2\xb2\x66\x30\xad\x2a\x01\x7f\xbc\x21\x39\xb4\x2a\x79\xce\x14\xde\x60\xe4\xa7\xae\x78\x7b\xc5\x54\xde\x68\xe0\xc1\x61\x7c\xbe\xb9\xac\xbc\x99\x29\x72\xe0\xfb\x28\xff\xde\x68\x2e\x93\xe7\x94\x37\x37\x97\x83\x1f\x97\x35\x4b\xe9\xb5\x55\x89\x3f\xe3\xbd\x3f\x2b\xbf\x89\x2a\x78\x2b\xb8\x31\xfe\xc2\xf6\xed\x2f\xc4\x2f\x35\xf2\x9c\x61\x5f\x59\xd9\x3e\x03\xc7\x1b\xd3\x37\x66\xae\x2a\x6f\x6a\x42\xf3\x28\x96\xbb\xbe\x25\x9c\x1b\x26\xca\x0f\x34\x48\x15\x08\x82\x08\xe8\x04\xff\x20\x78\x2a\x01\x4c\xe9\x54\xeb\xe0\x42\x3c\xaa\x14\x08\xe1\x71\x87\xe7\xf0\xf8\xdd\x4a\x37\x83\x10\x12\xe0\xb1\xc0\xa3\xc8\x3b\x78\x99\x04\x9d\xc4\x92\x0f\x99\xe9\x42\x31\x75\x39\x05\x0f\xf2\x68\xd4\x8f\xc7\xea\xa2\xe8\x30\xe7\xb0\x06\xaa\x50\x37\xc6\xc4\xf4\x1c\xe6\x40\xc2\x9a\x21\x4f\x02\xa0\x1c\xb5\x76\x8e\x04\xaf\x92\x29\x96\xc6\x63\x3f\x8d\xa7\x04\xa0\x70\x9c\xa0\x59\x22\xa4\xcc\x08\x68\xfa\xc4\xc1\x23\x02\x5e\xb1\xc1\xde\x86\x56\x01\x92\x21\xd1\x8e\xb3\xe0\xf7\x40\x4a\x49\xbc\x2b\xc9\xd5\x1e\x68\x8b\xa1\x19\x06\x0d\x58\xe8\x6a\x12\xc8\x8f\x33\x10\x03\x6e\x0c\xcf\x41\x91\x56\xa4\x70\xe0\x02\xd9\xec\x8e\x5a\x9e\x43\xba\x2f\xae\x12\xa3\x4c\x55\xe1\x3a\x34\xe7\xfb\x71\xd2\x61\x45\x17\xd7\x61\x61\x2e\x20\x60\xb1\x1f\x4d\xfb\xf8\x0e\xb5\x31\xe0\x81\xb8\x38\x80\x40\xb3\xd0\x04\xbc\x08\x0d\x93\x61\xa5\x29\xf0\x03\x70\x23\x60\xe9\x10\x44\x49\x11\x71\xe1\x68\xde\x8a\x1a\x92\x94\x10\xaf\xbb\x91\xd5\xb8\x10\x3e\x49\xd6\xe1\x50\xbd\xe3\xca\xfc\x18\x21\x60\x36\xbc\x9a\xd7\x4e\x24\x4f\x72\x5b\xd4\x46\xb8\x59\xd5\x1b\xab\x2d\xed\x61\xe1\x4d\x7a\x2d\xc3\x4a\xec\x52\xc6\xa4\x73\x6a\x68\xf9\x36\xa4\x05\xd0\x34\xaf\xd3\x32\x16\x06\x40\x08\x20\x3d\x3f\xce\xf0\x34\x0d\x79\xa0\x05\xba\x69\x01\xa7\x6f\xa1\x4f\x1f\x2e\x36\x01\xbd\xd6\x26\x1a\x8d\x40\xf0\x17\xd8\x19\xc6\xaa\x0f\x9b\x9a\x38\x0d\x67\x2f\x08\x16\xea\xf4\x22\x92\x2a\x2c\x05\x76\xf3\x06\x11\x68\xc7\x15\xd0\xc0\x5f\xe8\x2e\x82\x40\x6b\xe1\x75\x1c\xa3\xe7\x2d\x00\x58\x9d\x16\x2b\x00\x76\xad\x26\x0c\x8c\xac\x4e\xb0\xeb\xdc\xf6\xea\x38\x2c\x73\x7b\x59\xad\x9e\xa5\xb5\x06\x6b\xa7\xb6\xc2\x55\x10\x43\xd3\x82\xb9\xa0\xcc\x12\xf2\xfb\xdc\x76\x23\x84\x1c\xa7\xe7\x8d\x74\xe1\xac\x98\xdd\x56\x66\xa7\x81\xa7\xc8\x28\x3a\x66\x69\x20\xe0\x34\x36\x2f\x03\x39\x86\x85\xb0\xa4\x8a\x2d\x65\xac\x0f\x68\xcd\x74\xb1\x47\x53\x26\x54\x85\x19\x23\x07\x68\xab\xae\xea\x82\xcb\x2a\x1c\x7a\x03\x44\xcf\xe4\x6c\xb4\x03\x42\x0b\xb4\x9b\x4a\x40\xfb\xcc\xf4\x5d\xb4\x9e\xd3\x42\x5a\x47\xd3\x7a\x1a\xdc\x03\xb5\x16\x8e\xd5\xb2\x1c\xa4\x85\x32\x51\xab\x7f\x5c\x67\xa0\x39\x86\xa1\x05\x46\x03\x63\xac\x91\x36\x69\xb5\x2c\x0d\x81\x0e\x32\x8c\x46\xd0\x00\xb3\x00\xe3\x56\x3b\xe4\x9d\x8e\xa0\x2b\xa4\x09\xad\x28\xb4\xac\x0d\x89\x0e\x9d\xdf\x53\xb1\x40\xea\xb2\x56\x4c\x29\x89\x14\x16\xdd\x9b\x90\x12\x25\xe5\x4e\x56\xe7\x07\x00\x0d\xe1\x3a\x61\x81\xc5\xe3\xb4\x45\xbd\x11\xbf\xd6\x28\x42\x03\xcb\x00\x3f\x4d\xfb\xad\x97\x04\x9c\xab\x27\x38\xca\xcb\x69\xd1\xaa\xbb\x70\x7c\x47\xa5\x9e\x41\x83\x9f\xe8\xe1\x35\x41\x7b\xc8\x7a\x9e\x60\x60\x60\x5d\x77\x78\x42\xb4\xaf\xa4\x61\x12\x8b\xe4\x84\x55\xf1\xc5\x26\x24\x6e\xe8\x75\x6e\x77\xcc\x2f\xba\x45\xad\x00\xed\x21\xd1\x6c\x95\x74\xf5\x67\x95\x36\xb5\x74\x46\xc7\xeb\xc3\x5e\x9f\x8f\x16\x80\x60\x72\x99\xdd\xcc\x1a\x20\x01\xce\x80\x76\x4d\xb4\xde\xc8\xc9\x73\x80\xc6\xc2\xb2\x1a\x3d\x6a\x5f\x1d\xad\xc1\x2f\x1c\xca\xb7\x8a\x4e\x53\x81\xdb\x5c\xa4\xf3\xf3\xe5\xec\xf8\xf3\xac\xd6\xb6\xbb\xb7\x95\x42\xa6\x72\x67\x55\xb8\xb9\x58\x34\x80\xd6\x39\x9e\x12\xbb\x6d\x82\x5f\x43\x7b\x00\xa8\xad\x03\xf4\xc4\x02\xc9\xc4\x33\x09\xd6\x53\x6a\xd3\xd2\x9a\x3d\x26\xa4\x40\xf2\x0d\x13\x01\x68\x28\x36\x55\x14\x43\x5a\xaf\x05\x45\x92\xdd\x03\xca\x4a\x18\x93\x60\x70\x00\xc1\xc5\x6a\x1c\x26\x3d\x80\x16\x60\xd0\x5a\xb4\x02\x87\x4a\x42\x73\xc5\x8c\xc4\x20\x09\x94\x61\x4c\x0e\x00\x0c\x66\xc9\xa4\x65\xb4\x90\x65\x19\x8e\xe6\x81\xd0\xec\x32\xe8\x5b\x8b\xb5\x34\x5f\xd0\x36\xbe\xa3\x88\x7b\xa0\x41\x5c\xab\x71\xda\x8a\xdb\x0a\x0b\x25\x00\x98\x09\x6b\x0c\x5e\xc6\x71\xb9\xd6\x54\x55\x4a\x9b\x9a\x6a\xaa\x9c\x1d\x1a\xb3\x06\xb2\x5a\xbe\xce\x6c\x9a\x1a\xd2\x70\x55\x05\xed\x48\xdd\x96\xb6\x79\x6d\xeb\x17\xbb\xc4\xa0\x57\x4f\x97\x59\x5c\x10\x6a\x59\x60\xb2\xfe\x42\xc3\xd3\x0c\xad\xe3\x78\x00\xcd\x71\x06\x88\x03\x7a\x8b\x06\x30\x0c\x60\xdc\x34\x0b\x3f\x85\x9c\x06\x9a\x80\xd1\xc8\x31\x46\x96\xa3\x51\xbb\x01\xe6\xe4\x4b\x86\x02\x87\xdd\x6e\xb1\x1a\x45\x46\x9a\xe6\x36\xf3\xa2\xb6\xc8\x8e\x7a\x32\x7a\x4b\x85\xde\x02\x00\x9a\x8d\xa8\x67\x1b\x2c\x7a\xc7\x42\xbd\x79\x7c\xb0\x44\x6b\x60\x74\xa2\xdf\xdf\xe9\xb3\xb2\xb4\xd1\x54\xc6\x39\x0d\x76\xbd\xa9\x43\xb0\x68\xb9\x02\x0d\xe7\x15\x68\xae\xa2\x6e\x42\xd8\xf2\xd3\xba\x69\x7e\xad\xd3\x6c\x2f\xc2\x74\xde\x6b\x63\x1d\xd6\x6b\xeb\x36\xbd\x78\xd6\xae\x72\x1b\x28\x72\x97\x1d\xe9\x58\xb1\x63\xf3\xfa\xa6\x37\x17\xd6\x4c\x29\x85\xd0\x1f\x44\xad\xae\x91\x0c\x45\x6c\x50\x98\x17\x9f\xbc\x7b\xc2\x14\xd6\x57\x13\x28\x40\xd5\x2a\xd0\xeb\xa7\x4d\x31\x14\x47\x3c\x6e\xbd\x49\x8d\x8f\xc7\xb2\x98\x40\x79\x91\x1c\x5d\x45\xd5\x52\xad\xd4\x02\xec\x55\x14\x0c\xd1\x01\x6c\xf4\xc7\x1c\x63\x74\x28\xcc\xf8\xf0\x2c\xed\x50\xe8\x80\xd1\x58\x82\x06\x0a\x2f\x1b\xe2\xf1\x20\x07\xfc\x7c\x8c\xc5\xf3\x3b\xda\x61\xa4\x50\x18\x5f\x45\x46\x93\x56\x50\xeb\x61\x1c\xb1\x61\x11\x04\x65\x2b\x21\x34\xc7\x6e\xd8\x73\x45\xc0\xf4\xf4\xa7\xfb\x5a\x6c\x5e\xf9\xd7\xf2\x61\xb0\xa8\xbb\xf6\xfa\x03\xbb\x42\x41\x46\x5c\x77\xc1\x45\x07\x52\x5e\x50\x45\xbf\xff\xd6\xaf\x16\x8e\xdb\x78\xc3\xd0\x3f\xd0\xa4\x0e\x67\x3d\xf3\x4d\xd7\xac\x4b\xb7\x4e\xda\x39\xa5\xd9\xf4\x11\x7d\x08\x68\xad\xed\xd3\x77\x4f\x2a\xc0\xab\x10\x25\x33\x26\x77\x34\x47\xcb\x3d\xba\x9d\x23\xf4\xb0\x12\x7c\x25\x67\x9b\xb1\xf0\x9a\x19\xfa\xc3\xf0\xfa\x9a\xd6\x65\xbc\x70\xd1\x87\x8b\x17\xdf\xb6\xbc\x43\x30\x02\xf6\x37\xef\xdc\x37\xe1\x9f\x37\x7d\xd1\x5c\xfc\xc5\xc7\xd3\xff\x42\x9f\x0b\xc0\x75\xf7\x4a\x3f\x7a\xdb\x35\x29\xd6\x6c\x93\xfd\x7f\x7d\x14\x18\x0a\x12\x0d\x9d\x85\xd1\x32\xd6\x89\xba\x17\x8d\xb4\x03\x16\xbe\x34\x16\x1e\xa3\xda\x7e\xad\xd4\x72\xac\x7f\x54\xd1\xd5\x00\x73\x27\x47\x6a\x3d\xb4\xe2\x7b\x85\x99\x88\x21\x8e\x87\x2d\x06\x84\x5b\x1e\xc7\xcd\xd2\x19\x3b\x4a\x2b\x54\x88\xb7\x38\xc2\x34\xab\xa0\xcf\x61\xa9\x28\x86\x09\x19\x45\x8c\x3d\xc7\xdc\x18\x6e\x5c\x34\xa3\xa6\xd7\x53\x58\x26\x9a\x0e\x96\x77\x94\x96\x54\xb8\xaa\x1b\x36\x3d\xd4\xd3\x91\xdc\xd8\x1e\x9a\xb6\xa0\xf9\xd0\x59\x76\x6f\xf7\x84\xc8\xec\x9a\xb2\xda\xa2\xda\xc8\x7f\x3f\xd8\xf9\x83\x8d\x13\xc1\x86\x0f\x8f\xec\xed\x9d\xd1\x79\xad\x3c\xf8\xdc\x46\x73\xb7\xba\x03\x58\xbc\x03\xde\xab\x9d\x1b\xab\x70\xea\x9d\x3c\x6f\x36\xbb\x2c\x33\x9c\x3e\xbf\x33\x51\x19\x5f\x5c\x55\xdc\xb6\xb1\xb3\x65\x49\x73\x50\x28\xb1\x0b\xd6\xd2\x70\xc4\x5b\x59\xe9\x6d\xae\x5c\x7a\x69\x70\xf2\xf6\x83\x47\x3e\xec\x36\x6f\x7c\x0e\xb0\xd7\x76\xce\xe8\xdd\xab\xec\xc8\x83\x78\x87\xe8\xe7\x15\x48\x77\x78\x85\xc4\xb2\xb4\x51\x1d\x24\xe2\x2a\x63\x0f\x89\x13\x7c\xf2\x5a\x42\x53\x1c\xca\xb3\x72\xc6\xe2\x9c\x0e\xbb\x94\x10\x07\x5f\x80\x09\xed\xb2\xf0\xa9\x74\xcc\x05\xe8\xbf\x06\xd9\x42\x5b\xba\xde\x51\xcc\x81\x80\xc3\xe3\xfb\xc2\xee\xa1\x9d\x46\xa6\xd8\x26\xff\x0e\xaf\x46\x83\xb3\x44\xff\xc7\xa6\x19\xad\x0c\xc7\xd9\xdd\xb5\x3e\xf9\x1f\x46\xad\x46\x5e\x6e\xef\x34\xc4\xbb\xe6\xd0\x17\xac\x48\xd8\xef\x64\x5a\x67\x30\x33\x7f\xe1\xf0\xfb\xad\x83\x8f\xa1\x07\xf4\xb8\x4c\x45\xa6\xbd\x2d\x36\x74\x6d\x59\x51\xd0\xfd\x79\xa7\xbc\x5b\xfe\x95\xc5\x6e\xab\xb0\x5b\x75\x5a\xd9\x5d\xc0\x6b\xed\x5d\xec\xde\xf8\x8a\xbe\xbe\xa1\x4f\x2d\xa0\x01\x5c\x4a\x8d\x58\x77\x50\x34\x95\x51\x9e\x9a\x67\xc0\x38\xc5\x76\x69\x22\x33\x83\x01\xd5\x62\x9b\xdd\xeb\x0f\xb9\x4e\x12\x93\x0c\x8b\x7e\x53\x0c\xb1\xf7\x0e\x51\x84\x98\x1c\x12\x4b\x2e\xb1\xe7\xd2\x42\x2e\x53\x28\x13\x57\x86\xfd\xaf\x06\x08\xff\xa3\x62\x85\x0a\xd3\x01\x9b\x64\x27\x7e\x4c\xc3\xc8\x59\xea\xe2\x52\x34\x40\xab\x6c\x6d\x24\xf6\x1b\xc9\xf2\x99\x98\x1f\x96\xaa\x2f\x8d\x14\xfd\xb9\xf2\x6b\x6d\xc8\x95\x9a\x58\xd5\x5f\x35\x31\xe5\x0a\x69\xbf\xae\xfc\x73\x51\xa4\xb4\xde\x0c\xa8\xce\x75\x20\xb9\xae\x13\x50\x66\xb9\xe7\xd2\xff\xb8\xf4\xd2\xff\x00\x03\xa5\xf5\xe5\x60\xfe\x3e\x79\x8d\x49\x74\x85\xe4\x2f\xab\x26\x4e\xac\x02\xe6\x90\x4b\x34\x81\xdb\xf6\xc9\x47\xcb\xeb\x4b\x8b\x9c\x20\xb9\x61\x83\x9c\x74\xd2\x3d\xf8\x82\x4b\x95\xb2\x32\xb8\xac\x41\xe2\x89\xab\x0a\xbb\x81\xd3\x6c\x95\x36\xcb\xe2\xb3\x51\xf5\xdd\xf5\x89\x89\x4b\x27\x92\x3f\x94\xde\xd4\x0d\x93\xdd\x9b\xe4\x01\x52\x1a\x3a\x21\x2b\x3c\x79\x3d\x43\x9b\x48\x49\xde\x94\xc7\xe3\x2d\x7d\x50\x26\x18\x7f\xa0\xbf\x7b\xd3\x26\xf0\x5a\xae\x1c\xca\x7b\xb4\x61\x56\xc1\x20\xea\x92\xa1\x70\x28\xc3\x6a\x87\x17\xdb\xec\x8e\x92\xfc\x05\x1e\x16\x2c\x37\x5b\x8a\xaa\x4b\x17\xb4\x38\x4b\x9a\x9b\x4a\x9c\x2d\x0b\xc6\x55\x15\x59\xcc\xcc\xa2\x11\x03\xcc\xa7\xe0\x3d\xfb\xb4\x9e\x62\x17\x92\x57\x4a\x4b\x0b\xfd\xc0\x55\xdc\x33\xcd\x7e\xcd\x18\x63\x44\x05\xd2\x2f\xde\x66\x4f\xa1\x7e\xd4\x89\x57\xfe\x08\x61\x1b\x1a\x10\x6a\x5b\x41\x10\x0d\x2b\x38\xce\x2d\x1c\x24\x31\xd6\x2c\x71\x0b\x0e\x86\xb0\x0b\x27\x96\x33\xe3\x41\xe2\x23\xcc\xc6\x09\xd9\x3c\xc1\xf0\x61\x89\x23\xae\xc3\xce\xa6\x96\xdc\xf6\xce\xa7\xef\xdc\xb6\x44\xd9\x80\x8d\x8c\x59\x7e\xdf\x68\x12\xe4\xf7\x1f\xd7\x79\x75\x8f\xcb\xef\x0b\x26\xa3\xfc\xbe\x99\x61\xb5\x8f\x3f\xae\x65\x19\x33\x28\x41\x27\x41\xc9\xe3\x5a\xbf\xf6\x71\x50\x82\x4e\x82\x12\xf5\x24\xd4\xe7\x6e\x83\x36\x51\x13\xdb\x23\xbf\x6e\xd6\xe9\xb8\xe5\xdf\x18\x8d\xdf\x2c\xe7\x74\x3a\x33\xa8\xed\x61\x4d\x16\xc3\x37\xdf\x18\xcd\xe8\x2c\xa8\x55\xce\x1a\x0c\xca\x59\xf9\x75\x74\xd6\x6c\xfc\xe6\x1b\x83\xaa\xfb\xfd\x94\xbd\x98\x12\x51\x0f\xa5\x82\x78\x5c\xc3\xc3\x1a\x47\x46\xc0\x48\x6d\x49\x90\x63\xd4\xa1\x4e\x8c\x95\x10\x49\x19\x43\x7c\x60\xc7\x61\x22\x89\x33\x9f\xc7\xea\x9f\x94\x5f\x7e\xbc\xf7\xd7\xa7\xd6\x1e\xfd\x6c\xef\x41\x34\x5f\x86\x96\xcb\x97\x0d\xdc\x8e\x29\x66\xb7\xbe\x00\xc4\x5b\x2a\x2c\xa2\x6f\xc1\x92\x43\x27\x6f\x38\xff\xbc\x71\xc5\x02\xff\x09\xaa\x4d\xec\xc9\xd4\x7d\xcd\xf2\x8f\xdf\xdd\xfb\xd9\xd1\xb5\xbb\x7e\xf9\xca\xbf\x76\xbe\x0e\x0a\x6f\xbf\x05\x38\x5e\xdd\xcd\xc1\x71\xe3\x8a\x67\xbe\xb1\xf5\x86\x93\x87\x22\x62\xb1\x50\xaa\x60\x9b\x71\x29\xd5\xa6\x5d\xae\x7a\x30\x12\x73\xbe\x6f\x94\x1f\xff\xa8\xd8\x96\x44\x1e\x9a\x06\x5c\x9b\xff\x05\xa3\x33\x27\xc9\x19\x0e\xf3\x60\xfd\x50\x81\xff\xa3\x86\x08\xd2\x07\xb1\xc2\x82\x1f\xe6\x70\x38\x08\x8e\x87\xf7\x54\x3f\xd7\xc3\xa6\xa8\x89\xd8\x1b\x8c\x22\xfc\x0e\xbc\xc3\x6e\x25\xdd\x00\x8d\x8b\xe8\xb3\xf0\x57\xc1\xea\x0c\xf5\x62\x1b\x50\x49\x1f\x9a\x80\x25\x8c\xbf\x8f\x62\x82\x10\xa4\x02\x04\x01\x1f\x06\x12\xe0\x7a\x42\xae\x81\xf6\x37\x25\x49\x8c\x89\x2f\xb2\xd6\xc4\xc4\x95\xe3\x93\x91\x35\x9d\x4d\x82\xe9\x29\x6b\xa1\x53\x92\x68\xcb\xcb\x8d\x0a\xdc\xc7\x31\x29\x54\x27\x1d\xa3\xbb\x8e\x49\x75\x21\xe9\xd8\x80\x4b\x9e\x9c\x4e\x3e\x0b\x74\xcf\xc2\xb3\xea\x42\x47\x77\x9c\x90\xea\x24\x49\x7a\x81\x35\x8f\xf3\xba\x30\x38\x9c\x3b\x1c\x36\x0a\x6f\xd8\xcc\x62\xd4\xfa\xe7\x2d\xfd\xb8\x62\x21\xe5\x42\xe5\x36\xf2\xef\x20\x75\xd9\xb3\xcf\xa2\x0f\xfc\xd4\x29\x0a\xf0\xbb\x99\x29\xd4\x65\xc4\x67\x10\xaf\xa7\xe1\xa5\x4b\xac\x59\x40\xa4\xea\xb1\x5c\x08\xcd\x8d\x34\x1a\xf5\x1d\x56\x42\x81\x81\x97\x7d\xf0\x11\xa4\x66\x11\xe0\x1c\x24\xb2\xe0\x39\x12\xff\x7a\xe8\xda\x78\x2b\x43\xb0\x23\x88\xc2\x85\x7b\x0a\xd2\x69\xac\x04\x0f\x86\xac\x8a\xe3\xd5\x3c\xc5\xfe\x01\x1d\x41\xa4\xc3\xf0\xbb\x1d\xc7\x9c\xe3\x4a\x3d\xc5\xbc\x54\xe5\x67\xc0\xd5\xb5\x34\xcf\x6b\xca\x42\xa7\x28\x67\xc2\x6a\xf5\x74\x37\x4c\x70\xd2\x3a\xa7\x64\x02\x3c\xc3\x88\x81\xad\x53\x0e\x6f\x5e\xe6\x2c\xd0\x05\xce\xe9\xbd\xba\x99\xa3\x19\x53\x19\x10\x0d\x76\x96\x35\x6b\xac\x75\x26\x73\x51\xac\xbc\xb4\xd0\x08\x39\x51\xab\x63\xa1\xc0\x73\x05\xcd\x46\xd1\x6c\x8f\xfe\xc7\x9c\xa8\xd5\x2d\xf0\x10\x09\xf4\x9c\x45\xd0\x88\xfe\xb2\xd6\x60\x73\x35\x83\x44\x72\xc8\x59\x75\xc0\x1b\xae\xe5\xe8\x6f\x12\x1f\x7b\xa3\x91\xb2\x06\x77\x19\x12\x69\xe1\xa5\x67\xb1\xa6\x90\xa7\x80\x61\xad\x06\x83\x6d\xc1\xa4\x6a\x0d\x60\x9d\x81\x49\xe5\xa6\x02\x8e\x95\x68\x66\xdc\x84\x76\xa7\x53\x57\x7a\x4d\x3f\xe0\xae\x36\xdb\x59\x4e\x42\xb2\x26\x43\xeb\x6d\xb5\x1b\x0a\x8b\x9a\x17\xd5\x14\xb2\x40\x53\xd2\xd8\xdb\x59\x3a\xd1\x68\xf0\x6b\xa1\x5d\xd2\xbb\x20\x30\xb0\x96\x62\x5f\x63\xdd\xe2\x90\xbe\xd5\x5f\x5d\xac\x85\x8c\xab\x7c\x49\x6b\xef\x85\x3a\x13\x06\x1f\xa1\x01\x64\x4d\x5a\xc2\x15\xfc\x23\xee\x6b\x76\x3a\xa5\x23\x23\x5e\x35\x35\x9f\x5a\x4f\x5d\x8c\xbe\xc6\xac\x4e\x8c\x67\x63\x92\x44\xfa\xa7\x23\x83\xf7\x89\x1a\x35\x58\x05\x4a\x78\x8e\xc1\x1f\x62\x3c\x56\x12\x44\x7a\x2f\x1a\x15\x71\x6c\xad\x88\x76\xb1\x3a\xe8\xc1\x4e\x6b\xd8\x28\x8f\x3e\x5b\xa2\x5a\x42\x0f\x50\x01\x43\x63\x48\xbb\x54\x54\xca\x20\x39\x46\x0e\xa1\x13\x58\x65\xc7\x2a\x3a\xbc\x07\x9b\x7e\x67\xda\xec\x62\xc7\xec\x6d\x1a\xad\x51\x28\xe2\x2d\x1e\xc1\xf3\x44\xe5\x9f\x36\x6e\x98\x5d\x5d\x7d\xa2\x6f\xe3\x0a\xa4\x23\xf6\xcb\xa7\x0e\xfd\x51\xfe\xbd\xa0\xed\x07\xe0\xd0\x1f\x41\x10\x84\xa6\x1d\xfc\xb9\x9c\x96\x3f\x96\xff\xfb\x9d\xbd\x57\x26\x1f\x04\x8b\xa7\x4d\xa8\x64\x38\xc1\xc4\x71\x57\xfe\xa6\xaa\xb2\x12\xb2\x82\xce\xd0\xb0\xb4\x63\xdb\xbc\x02\x49\x53\xee\x40\x05\xb3\x2e\x6a\x73\x96\x31\xac\xcb\xd9\x0c\xe6\x2f\x8c\x84\xb5\xb5\x31\x97\xa6\xb0\xa4\xb5\xf5\xa1\x85\x85\xe3\x0d\xc5\x85\xbb\xfe\x39\xe4\x9f\x6c\x12\x5c\x3e\xff\x24\xaf\xfb\x36\xa3\x9b\x65\xf5\xc6\x62\x81\xd5\x2f\x5f\xdb\x53\xe2\x7f\x66\xc5\xb2\xa5\xee\xa2\x27\x9a\x7b\x6e\x98\x2c\x38\x3e\x3b\xa4\x6c\xae\xe9\xb8\xf6\xd2\xde\xd6\xf6\x1d\x4f\x9d\xb3\x15\x30\xc9\x07\x7f\x30\x2d\x71\x9d\x60\x40\xbd\x00\x36\xb5\xb4\x6d\x35\x0a\x7a\xd4\xa1\x1a\xd7\xc3\x15\xcb\x77\xd5\xa3\xa7\xa3\x32\xb4\xf5\x18\xd1\xd3\x9d\xe3\x58\xe3\xac\x9e\xf4\x56\xb7\x4b\xac\x75\xcf\x79\xbc\x63\x52\x54\xe4\x8a\xeb\xab\x39\xd7\xf4\x7c\xd9\x62\x0b\xa5\xa5\x24\xcc\x17\x4f\xf8\x6d\x91\xa6\xed\xc1\x6b\x9e\x90\xc7\xa4\xcc\x25\xc0\xcc\xa3\x81\xd2\x62\x67\x44\xe6\xdc\xa3\x2f\x3c\x7f\xf4\xc0\x2f\xfd\x81\x5f\xca\xb7\xa5\x5f\x7d\xe2\x7e\x50\xc2\x44\x9f\x78\x35\xfd\x18\x28\xb9\xdf\xbf\x7c\xf9\xc2\x6f\x0e\x1e\xfc\x86\x6d\x91\xdd\x43\xf2\xd9\xab\xde\x05\xce\x67\xc1\xa4\xdf\xa4\xcb\xe4\xbf\xbe\xbb\x0a\x1c\x19\x02\x7f\xf1\xfc\x46\x7e\x56\x59\xeb\x43\xb2\xc3\x4e\x24\xa7\x6d\xc0\x6b\x2f\x34\x16\x55\x39\x8a\x27\x28\x1f\x68\x2c\x16\x20\x36\x1f\x00\xf4\x71\xc5\x70\x9a\xc5\x69\xb6\x18\xc4\xa2\x55\x2c\xd2\xfb\x19\x01\x69\x38\x68\x78\xc2\x6b\x23\x02\xfe\x90\x39\x9c\x64\x77\x7a\x17\x2d\xef\x5d\xb5\x7c\x56\xb3\xd9\xb2\x59\x3e\xf2\xa6\xe4\x72\x49\xc7\x40\xf9\xda\x92\xa9\xcb\x17\xad\x5c\x30\xd7\xb7\xe5\xa5\xcb\xb7\xb4\x15\x44\x5d\xbc\x7d\x4a\xc7\x8a\x39\x0b\x12\x95\xdc\xe4\x8b\x57\x2e\x68\x89\xf8\xec\x2c\x63\xd0\xb8\xa7\xd4\xd7\x09\xa1\x48\xe7\xb9\xcd\x25\x2c\x67\x15\x35\x3c\x52\x8f\x84\xea\xd8\xa2\x15\x97\x74\xc0\x70\xcb\xcc\xf9\xf3\xba\x9a\x2c\x16\x47\x2d\xe7\x9c\xde\xbd\x63\xdb\x35\xe0\x27\xdd\xdb\x5a\xbc\xb4\xe0\x29\xd0\xe9\x3e\x92\xbf\x05\xae\x50\x01\x78\xe7\xb8\x20\x6a\x8c\x15\xd3\xf6\xcc\xad\xb6\x06\x66\x76\x55\x5c\xda\x0f\x68\x48\x5b\x8a\xea\xa7\x6d\x9d\x5c\x68\x91\xc6\x35\xb5\xb5\xd5\x98\xcc\x3b\x3b\x39\xeb\xa4\x69\x9b\x36\x5f\xdd\x51\xd0\xd9\x7d\xd6\xa2\xb9\x93\x63\x26\x13\xb3\xd4\xc5\x3b\xda\xa2\x8d\xc5\xd0\x31\xf3\xe2\x39\x2d\x1e\x11\x7d\x3e\xf4\xf5\x57\xf0\x8e\xa6\xaa\x10\xac\x41\x62\x8b\x0d\xc9\x2e\x7f\x63\x29\xe2\x49\x6e\x25\xf1\x55\x44\xc2\x02\x8a\xcf\x3e\xb0\xf9\x2c\xf8\x2f\x68\xcb\x30\x32\x31\x7f\xdb\x3a\xbb\x41\x1e\x4a\x7f\x31\x7b\x2b\xf3\x9b\xc1\xb2\xcc\xdf\xd6\xd9\xf4\xcc\xd9\x5b\x81\x7b\xe2\xfc\x1d\xf2\xbf\x80\x71\xc7\xfc\x89\x60\xf2\x29\xea\x14\x98\x8a\x7e\xae\x6a\x6f\x9f\xb7\x63\x47\x9e\x9c\x89\x11\xca\x6a\xd4\xf8\xa0\x31\x69\x4c\xed\xa7\x09\xee\x62\x92\x2a\x91\x69\x86\x64\x53\x21\x32\x7d\xf0\xbb\x02\xbd\xe0\x35\x63\xf0\x99\x1e\xfd\xae\x80\xaf\x61\x32\xb1\x5a\xd6\xe1\x6c\xac\xf9\x64\xac\xe2\x69\xcb\x8a\x39\x4b\x71\x01\x73\x54\xac\x98\xc9\xb4\xff\x3b\x0b\x3b\xa0\x16\x11\xb4\x61\x66\x54\x85\x91\x55\x3e\xf5\x9d\xa5\x1d\x25\xbf\x2b\x6b\xa6\xb9\x62\x8e\x94\xdf\x47\x59\x1b\xa8\x90\xcb\x6a\x51\xc2\xce\x2c\x56\x1c\x43\xfb\x1d\x01\x6a\x29\xec\x5b\x65\x50\xc3\xc6\x0c\xa1\xa1\x17\xbf\x47\x3c\x18\x8f\xbe\xfd\xe2\x5c\x1c\xbe\x78\x1a\xc6\x00\xd5\x9e\x5b\xf6\x5d\xbc\x01\x6a\x74\x3d\xf0\x7e\x27\x7d\x80\xea\xe3\xbe\x0c\xc9\xe4\x36\x2a\x86\x23\x41\x89\x38\x86\xa5\xb1\xb8\x03\xcf\xad\x54\x04\x0b\xa5\x0e\x32\x1a\xd1\x0a\x90\x58\x9c\x90\x8b\x62\x4b\x83\xe4\xb3\xf9\x70\xb4\x97\x44\x9f\x5a\xdb\x28\xbf\xf9\xec\xed\xf2\xd7\xb7\x9d\xf8\x91\x65\xe7\x21\xc0\x3f\xb3\xe7\x9d\xed\xd0\xdd\x78\x8a\x32\x9a\x4b\x2d\x5f\xc8\xa5\xce\x20\xdd\x03\x35\xc2\x82\xd8\xc4\xe5\xbd\x1d\x41\x70\xbf\xbc\xde\x0c\x7e\x55\x6a\xf9\x08\x2c\x7b\xf5\xb1\x3f\xdc\x06\xb4\xb7\x3f\x01\xca\x5a\x2f\x8d\xfd\xf1\xb2\x67\xe4\x6f\xf7\x7e\xe0\xda\x92\xe4\x03\xe0\x03\x9f\x93\xd6\x5b\x0a\x22\x6d\xcb\x27\x4e\x3a\x9b\x97\xff\x98\x4c\x06\xe4\x86\x61\x3a\xb6\xc2\xeb\x13\x0b\x87\x68\xf4\xfa\x78\xec\x3e\xa9\x2c\x6a\xe2\xa5\x51\x87\x12\x9b\x85\xed\x0a\x92\x38\xca\x3b\xd1\xa0\x3b\xfa\x5f\xb3\x2b\x42\xf3\xf5\xcc\x55\x81\xf2\xb0\xd1\xeb\xd9\xdb\xb4\xde\x7d\x8e\xbb\xae\x4b\xdf\x50\x6b\x6a\x36\x75\xf4\xdc\xf1\xa7\xf7\x4f\x0e\x7b\x9f\x7b\x7f\xcb\x69\xe4\x7f\x49\x3d\x0d\xef\x3f\x18\xfb\xf5\x73\x06\x7e\x99\xb3\xc7\xd9\x5e\xf7\x58\xfc\xf7\xf1\xc7\x40\x08\xb8\xc1\xc5\xc3\x2c\x68\x2a\x9e\x03\x2a\x23\xd6\x7f\xad\x90\x51\xd4\xb0\xac\x83\x51\x1b\x88\xe6\xa7\x33\x61\x58\x48\x70\x29\x42\x72\x1f\x6b\xcb\x24\x2c\x31\x4a\x3d\xc9\x24\x9f\x93\x8f\xff\xac\x5f\x10\xdf\xa5\x39\x9d\xd6\xe8\xf8\x24\xb3\x15\x05\x74\x10\xec\x30\xb9\x1c\xf2\x0e\x75\x73\x1c\x30\xe4\x28\x4c\xfd\x4c\x3e\xfe\x9c\x28\xc0\x55\x13\x01\xa7\x33\x27\x1d\x9a\x29\xcb\xb2\xa9\x93\x58\xab\x7c\x62\x1b\x6b\xc5\x7b\x17\x2e\xcb\x24\xe4\x02\x23\xb0\xfe\x14\x7b\xfa\xe6\x62\xbf\x03\x2a\xfa\xb4\x4d\x0d\x33\x52\x2a\x93\x1d\x8c\xb2\x56\xb1\xef\x19\x0f\x2e\x2b\xac\x96\x72\x3f\x51\x7e\x7b\x94\x18\x94\x9e\x33\x46\x87\x8f\xca\x4f\xee\xf4\x5d\xd1\xe2\x6a\x5c\xac\x06\xe3\x78\x86\x09\xe3\x5f\xb7\x62\x7d\x8b\x2a\x4a\x70\x15\x50\x68\x8d\xb1\x8f\x3d\xea\x2d\x3e\x22\xc1\x10\x57\x54\xc0\xc7\xd1\xe4\xe6\xc0\x91\xbe\x3e\x8e\xf7\x23\xf1\x14\x08\xa0\x1c\xd0\x91\x5a\x3a\x20\x61\x88\x5e\xe0\x61\x22\xac\x2f\x04\xcf\x39\xef\xce\x24\xfa\xa4\xf9\xc6\x19\x33\x1a\x79\xc9\x98\x48\xde\x79\x1e\xb3\xb8\xec\x12\xf3\xe2\x9d\x95\x95\x3b\x17\x9b\x2f\x29\xe3\xa2\xd1\xd9\x1d\x1d\x83\xf3\xe9\xaf\xdf\xfb\xa2\x61\x93\xbb\x50\x1e\x70\x2d\xae\xec\x59\x56\x74\xc7\x1d\x45\xcb\x7a\xaa\x16\xb9\x80\x97\x11\xaa\x6b\x3b\x4b\xc0\x4b\x43\xda\x6d\xa0\x3f\x91\xa8\xf6\x39\x0b\xa0\xc5\x69\x81\x05\x4e\x5f\x75\x22\xc1\xdb\x69\x53\xa4\xa2\xa4\x22\x62\xa2\xed\xfc\x50\xc9\xa6\x12\xcf\xf8\x1b\xc6\xcb\xbf\x09\x95\x8d\x77\x3a\xb1\x57\x28\x78\x13\x0c\x80\x37\xb1\x87\x28\x63\xf4\x15\xd8\xba\x13\xea\xf7\x81\xb1\x44\xe6\x10\xff\x64\xfc\xb1\x62\x0d\x51\xb1\x22\x21\xa5\x32\x97\xcc\x10\x34\xb4\x01\x3a\x97\x0c\xab\x6e\xac\x48\xc3\xcc\x25\x55\x78\x3b\xd4\x10\x52\x3c\x06\x82\x34\xcb\x7e\xd1\x3a\x77\xd9\x43\xf5\xfc\xbc\xa6\xea\x19\xa6\xb8\xfc\x72\x5c\x33\xaf\xb9\xba\xcb\x14\xbf\xa5\xc8\xd6\x32\x3b\x5e\x71\xfb\xfa\xdb\x5d\xf6\xe6\x39\xf1\x8a\x3b\xa2\xca\x89\x18\x88\xc5\x34\xf3\x71\xe6\xe8\xdd\x36\x7b\xf3\xfc\xe6\x8a\x3b\xd6\xdf\xeb\x1c\x1a\x02\xb1\xf5\xf2\xcb\xf0\x9b\xd9\x2d\x67\xfb\x9a\xee\xb7\xb9\x9a\x16\xc4\x2a\xef\xeb\xbb\xd7\xe9\xc0\x89\x7b\xa2\xda\xee\x16\x74\xed\xff\x47\xdb\x77\xc0\x47\x55\x65\xff\xbf\x7b\xdf\x7b\xf3\xa6\xb7\x37\xbd\x66\xfa\xa4\x27\x33\x99\x99\xf4\x4e\x80\x90\x84\x10\x7a\x68\xa1\x77\x09\x20\x1d\x61\x68\x62\x03\x15\xa5\xa8\x28\x51\x11\x1b\x76\x2c\x28\xba\x59\xfb\x5a\x50\x17\xb7\xe0\xcf\x82\xbb\xb8\xbb\xb6\xb5\x17\x20\x73\xf9\xdf\xfb\xde\x4c\x08\xc8\xfe\x74\x3f\xff\xff\x3f\x30\xef\xdd\xfa\xca\x7d\xb7\x9c\x73\xcf\x39\xdf\x13\x03\x65\x71\xe9\x08\x72\x95\xd8\x3e\x8b\xb9\x72\x74\x3c\xbf\x67\x6e\x0f\x29\x92\xc8\xbb\x3d\x21\x19\x5e\x91\x3f\x54\x13\x47\x2f\x96\x4a\xd1\xe9\xb9\xa0\x62\xfe\x85\x7b\x35\xd9\x82\x26\xd5\x05\x3a\x22\x40\x97\x76\x64\x5f\x06\xd2\xae\xec\x43\xe9\x1e\x9b\xe9\xc0\x69\xbc\x0c\x49\xa4\x9a\x4d\x04\xaa\xc1\x40\x25\x12\xfa\x84\xdb\xe3\x7d\x29\x36\xad\xbe\x7e\x5a\xe1\x73\x85\xca\x1c\x79\x69\x98\xae\x0d\x97\x26\xb2\xfb\x7a\xc3\xa5\x55\x81\xc2\xc7\x43\xb4\x43\xed\xe0\x2d\x46\x83\xd1\xc2\xe3\x10\x0d\x14\xbe\x9a\xf3\x75\x4d\xce\x9c\x00\x87\x7c\x06\xd3\x3a\xff\xa0\x41\x59\xab\xb2\xa4\x41\x29\x6a\x21\xce\x14\x66\x66\x97\x97\x86\x03\xc3\xad\x59\x4b\x6c\x90\x97\xe9\x64\x44\xe9\x05\x9f\x78\xf8\xa0\x79\x38\x95\x91\x25\x0a\xb6\x07\x2c\xee\xcd\x83\xa9\x11\xd4\x54\x6a\x31\x45\xf1\x78\x05\x0b\x42\x01\x21\x93\x16\x44\x3f\x41\x8d\xb8\xa7\x41\x78\x27\xbe\x3f\xc9\x1b\xf4\xc5\xfd\xc4\x85\xb7\x68\xe2\x89\xa9\x7d\x96\x37\x99\x85\x35\x10\x7f\x5b\xc8\xf1\xf1\x58\x09\x95\xc5\xe0\xa5\x1a\x12\x90\x9d\x20\x5e\x6e\xe2\x54\x96\x3f\x8e\xe3\x41\xe2\x03\x04\xc7\x4d\xeb\x1b\xc0\xa2\x17\xff\xcd\x4a\x59\x8d\xd4\xce\xb4\xa0\xcf\x0a\x72\x78\x35\xcf\xbf\x39\x6c\xbd\x52\x27\xa1\x35\xca\xf6\x95\xf7\xa0\x7f\xa5\xd3\xb8\x2c\xf9\x5c\x30\xf2\xe5\x1b\x80\x62\xae\x3c\xd1\xcc\x30\x4a\x89\x1e\xf7\xe6\x1a\x24\xf9\x12\x30\xeb\x36\x74\xcf\xa5\xd7\x4c\x79\xfb\xa1\xcf\x2b\xfa\xee\x00\x0b\x40\xcb\xd7\xdb\xb7\x7f\x8d\x0e\xa1\x1b\xd1\x21\x12\x02\xa3\x41\x27\xa8\xfa\xe4\x8a\x2b\x3e\x41\x2f\xa0\x03\xe8\x05\x12\x82\xc9\x3b\x77\xf5\xf1\x53\xc0\xa5\x40\xca\x87\x2a\x1d\x9d\xaa\xb3\x14\x5d\x4e\xb3\xd0\xe3\x04\x72\x20\x03\x4a\x3d\xaf\x06\x52\xf4\x14\x92\xd2\xb5\x99\xd4\x9e\x67\xe6\x75\x8d\x48\x28\x2d\xbc\x5d\xe3\x52\xfa\xd9\xf9\xc7\x52\xab\x24\x6c\x5e\x16\xd3\xf1\xe0\x0b\xef\xa0\x7d\xb3\xe0\x81\x7b\xe7\xe7\xc0\x92\xf3\x6e\xdc\x22\x3c\xcc\xa9\x27\xaf\xf8\x04\x54\x5d\xf0\x0c\x99\xb5\x47\x68\x7f\x3d\xd1\x17\x03\x3a\x36\xe8\x27\x63\xc4\x9f\x30\x4a\x18\xa3\x81\x31\xeb\x00\x1f\x48\x04\x43\x31\xc6\xcc\x54\xa3\xaf\x4f\xa2\x6b\xfe\xfc\x07\x30\xe9\xf8\x71\xf4\x29\x88\x7d\x46\x3f\x10\x48\x7d\x77\xc3\x8a\xdb\x81\xf1\x0d\xe2\xa2\x34\x69\xd8\x9f\xda\x71\xcd\x4f\xfb\x6d\x07\x83\x27\xae\xdd\xf3\x0f\x17\xdb\x8e\x6a\xd0\xea\x25\x23\x9b\x9c\x07\x3d\x6b\x33\x3a\xe6\x82\xdf\x29\x25\x15\xa4\x8a\x08\xf2\x80\xd1\x97\xee\xc2\xbe\x18\xf0\xe8\xa2\xba\x01\xbf\x73\xd8\x71\x6c\x26\x18\xa5\x7b\xe9\xde\x64\xb6\xe3\xb4\xdc\x91\x9d\x04\x78\x4d\x4a\x66\xfe\x57\x38\xb2\x4f\xe1\x8c\x0a\x09\x0e\xfc\x8c\x03\x12\x0a\x25\x45\x04\x90\xb3\x54\x0a\xdf\xf8\xdc\x4f\x84\x27\x25\x1e\xed\x92\x19\x5f\xd1\x49\x99\x68\xbb\x4e\xe8\x05\xde\x24\x74\x94\x04\xcf\x9a\x22\x89\xb4\xbf\xad\x00\xb1\xba\x35\x1a\x38\x3e\xad\xe3\x89\x73\xc9\x64\x1b\x4f\x04\x32\x7e\xbd\x24\xff\xd6\x33\x07\xd1\x9f\xd1\x7e\xf4\xe7\x83\x8c\x1e\x56\x9b\x4a\x4c\x4c\xbb\xe9\x4c\x0f\xa3\x64\x52\x97\xe6\x96\x4a\x6a\xca\xcb\xa1\x5c\xa6\xe9\xd5\xc8\xe4\xb0\xbc\xbc\x4e\x31\x16\x3d\x66\x32\x31\x5d\x38\x9b\xe9\x82\x47\xd0\x8b\x83\x96\x0f\xc2\xff\x41\xe5\xe3\x1c\x07\xb5\x05\x52\x84\x79\xc3\xa3\xde\x5b\x66\xfa\x87\x0e\x0a\xa2\xe1\x6a\x05\xfe\x53\x83\x47\x82\x83\x86\x06\xdf\x5a\x33\x47\x5a\x20\x05\x5d\x00\xa0\x1e\xfc\xfe\x0b\xcf\x26\xd9\x1b\x44\x9d\x16\xc0\x13\x01\x05\x1f\xa4\x20\x91\x67\x60\x36\x4b\x6f\xae\xa6\x13\x24\x58\x4c\x00\xed\xe8\x09\xaa\xea\xdc\xec\x5a\x55\x18\x9d\x7d\x78\x52\x79\x24\xaf\xa1\x66\xdb\xef\x73\x02\xd7\x77\xae\x2c\x8c\xc7\x4a\xcb\x1d\xb5\xbe\x36\xf9\x0e\xd8\x90\xaa\x52\x28\xe0\x0b\x83\xc0\x4b\x20\x7c\xb5\x46\xb3\xe8\x4b\xfc\x64\x55\x9f\xde\xf0\xe6\x58\xb5\x3a\x34\xbd\xfc\x72\xdd\xcf\x69\x9f\x38\xec\xc7\xc2\x1a\x4a\x01\x0f\x19\x65\xe2\x7e\x17\x1e\x59\xfe\x68\x96\x99\xc3\x4f\x21\x10\x79\x98\xce\xa2\x13\x1e\x9a\x82\x7f\x52\x3e\x81\x1e\x7a\xef\x56\x74\xf2\xe8\xaa\x55\x47\x81\xe3\x56\x90\xf7\x97\x77\xd6\x3c\xb9\xe1\x7f\x92\xc9\xff\xd9\x30\x76\xc7\xe4\x26\x8f\x04\xb5\xc0\x7f\x37\x54\x1d\x47\xf7\xf7\x92\x02\xa0\x1c\x38\x8e\xae\xfa\xc3\x1f\x56\x6c\xfc\x08\xfd\xfc\xd1\xc6\xa2\x21\x13\x3b\x02\xa2\x5e\x99\x38\x4f\x10\xbb\x57\x2f\xd5\x26\x48\x23\x4c\x44\x39\x30\x28\x28\xd1\x93\xfd\xb5\x88\x3f\x0d\xd8\x1c\x61\xd3\x14\xa7\x29\x41\x80\x6d\x82\x21\xde\x4c\x3c\x7c\x0b\xd8\xa6\x98\x9e\xa2\x25\x5c\xda\xd0\xc3\x8c\x0f\x4c\x34\xe2\x8f\x95\x60\x6e\xd0\x3f\x60\x96\xc0\xb3\x83\x89\x19\xac\xd5\x56\xa3\x7f\x57\x6b\xb5\x12\xbd\xa4\x68\xd5\xca\x62\x89\x1e\x1d\x2b\x69\x8e\xc5\x9a\xc1\xef\x62\xcd\x25\x38\x74\xa6\x69\x86\x7f\xe3\xe3\x35\xaf\x92\xc4\x40\xdc\xf6\x01\x2f\x19\x74\x68\x83\xaf\x24\xd2\x14\x70\x4b\x80\xe5\xa5\x97\x81\x85\x73\xf9\xc1\xac\x8b\x8c\x47\xb0\x58\xab\xa9\xae\xd6\x68\x25\x92\xe2\x62\xc9\xbb\xf8\x62\xb8\x2f\x75\x06\xc8\x35\x4b\x3a\x8a\x9b\xfc\x9d\x12\x60\xcf\x0f\x94\xc4\x9a\x63\x91\x62\xd6\x88\x5e\xe5\x3a\x03\x4d\xc5\xbe\x72\x8d\xdd\xb9\xfd\xb5\xd7\xb6\x67\x59\x35\x65\xcf\x5c\x70\x41\x1c\x3a\x1f\x07\x4b\x23\x78\x73\x22\xf3\xa9\xd0\x4e\xde\x74\x3b\x91\x66\x0a\x64\x9a\xc9\xc4\xf6\x87\x12\x42\xe3\x04\x43\x09\x33\xf9\x76\xff\xa1\xa9\x44\x6b\xfb\xd0\x2f\xf5\x96\xe8\xfb\x55\xaa\xd8\x17\x31\x95\x8a\xd5\xb2\x39\x47\x73\x58\x2d\x42\x05\xd5\x05\xf9\xb5\xf9\xa0\x43\x3c\xff\xa5\x32\x37\xc7\xbd\xf8\xe6\xf8\xfd\x20\xdf\x4d\xe4\x2e\x45\xc6\x67\x75\x4c\xe5\xcd\x8b\x5c\x79\xb9\x95\x59\x36\xf6\xeb\x7b\xef\xfb\x5a\x62\x75\x83\xe8\x79\xf8\x13\xbb\xf1\x45\xf1\x35\x25\x92\x9c\x1c\xc9\x2e\x77\x41\x81\x50\x33\x7d\x1e\x9c\x53\xe9\x6e\x63\xbe\x0b\x65\xe5\xe1\xab\xe7\xe6\xb0\x7a\xf4\xbd\xa4\x35\xab\x32\xc7\x15\x51\x59\xcd\xab\x1f\x78\x60\xb5\xd5\xa2\x2a\x06\x27\x2f\xce\x97\xb8\xf0\xec\x43\x10\x99\x13\x69\xf0\xb1\x7e\xb5\x14\xe1\x05\x45\x95\x13\x27\x60\x63\x69\x45\x95\x2a\xc0\x85\x8c\xa4\x03\x9d\xa7\x26\x39\xad\xf3\xd2\x9e\x4b\x1d\x41\xfb\xee\xa5\x1d\x23\x96\xda\x0d\xbc\x1d\x5c\xb9\x8b\x9c\x3a\x2b\x2f\xbd\x63\x29\x18\x71\x21\xff\x72\xd8\x5e\x3d\xbc\x7b\xd1\x70\xf4\x89\xc1\x6e\x37\xac\x5c\xdd\xb1\x64\x71\x3b\xc0\x8b\xa9\x83\x8f\x7f\xb4\x7a\x9d\xc1\xee\xe0\xd7\xd8\x1c\x6b\xda\x97\x2c\x01\x0f\x5c\xc8\xd5\x90\x39\xea\x4e\x2e\xc9\x4e\x12\x9e\x5b\xc0\x45\x12\x1f\x5a\x34\xb1\xef\x77\x5e\x2f\x3c\x34\xc7\x7a\x32\x39\xe6\x84\x98\xc5\x04\x2b\x47\x55\xf6\x3d\xf2\xe8\x19\x30\x04\x07\x52\x0f\x3d\xdc\xf7\x02\xb8\x16\x0c\x39\xf3\xe8\x23\x7d\x9b\x5e\xc0\x29\x74\xe9\x72\xa2\x1e\x93\xda\xfb\xd0\xcf\x67\x1e\x05\x72\x74\x3a\xb7\xa2\x22\x17\x2e\xb8\xff\xdb\xef\x0f\x5e\x51\x7e\x3b\xfa\xf1\xd1\x33\xa7\x1e\x06\xca\xaa\x72\xf4\x6d\x4e\x45\x45\xce\x40\x7e\x85\xe0\x7d\x50\x01\xe2\x66\x5c\x74\x8f\x7a\x11\xfa\x98\xed\x4d\xd5\xa2\xac\x49\x9b\x60\x2f\x38\x31\x69\x53\xed\xc0\xef\xdb\x03\x4e\xc0\xde\x4d\x93\x50\x56\xaa\x76\x13\xe3\x3c\x5f\x61\x4f\x8a\x7f\x36\x29\xc5\xfc\x03\xf7\x68\x19\xbe\x8f\x4e\xb0\x76\x0f\x08\xb8\x39\x64\x79\xf0\x58\x81\x4f\x07\xf0\x4a\x41\x1b\xa3\x31\x9e\x60\x53\xe0\x7f\x01\x1d\x4e\x1b\x18\x1e\xf2\x46\xea\x0b\x30\x64\x0d\xb8\xe9\xcd\x37\xdf\xec\x80\xc6\xd4\xe7\x60\x08\x7a\x8a\x24\xdc\x0c\x0d\x38\x67\x30\x3a\x0c\x06\xaf\x61\xfe\xd1\x97\x0d\x0f\xe3\xbc\xc5\xe8\x5a\x5c\x66\x30\x3c\x0c\x5c\x6f\xbc\x81\xfe\xd6\xd7\x71\x67\xc7\x7e\x31\xb1\x3f\x38\x60\x7c\xc9\x04\x6c\xd4\x22\xe2\x5b\x88\x12\xd8\x6e\x62\xf3\x31\x20\xa4\x4d\x03\x79\x73\xba\x04\xb1\xed\x80\x42\xdc\x27\x46\x7e\xc1\x88\x9b\x5a\x62\xb9\x76\x47\x4e\x0c\xfd\x90\x0e\xc0\x75\x0f\x5f\x66\xe0\xcd\x89\xb1\x6b\x8f\x45\xeb\x2f\xbb\xfb\x91\xcb\x9a\x1b\x9e\x3e\x96\xa8\xba\x8c\x36\x9f\xa7\x44\xd9\x98\xec\xd4\x00\xa3\x0e\x8c\x48\x4e\x20\xe7\x54\x31\x50\x3e\x47\xb7\x95\x4f\x91\xa4\x36\x67\x1f\xe5\xe1\x5c\x1c\xf5\xf7\x3d\x85\x83\xe0\xe7\xf3\xdb\x57\x4e\x65\x9f\x95\x71\x6f\xe2\xf9\x74\x23\x75\x84\x7a\x8d\x3a\x4a\xbd\x4f\xfd\x9d\xfa\x27\xf5\x29\xf5\x25\xf5\x15\xe1\x41\x5d\x34\x51\xd0\x57\x43\xae\x80\xf5\x11\x4d\x52\x17\xe7\x06\x26\x1c\x0d\x8a\x06\x24\x25\x89\x6a\x88\xa7\x07\xc2\xa2\x0a\x9a\x37\x8c\x48\x6c\x93\x25\x11\xcf\xfb\x02\x47\x6d\xce\x50\xd8\x50\x92\x46\xe9\x20\x82\x92\x10\x99\x40\x04\x1b\x39\x73\x42\x4d\x9b\x13\x05\x5c\xa8\x00\xe6\x10\xd7\x2b\x98\x2c\x75\xc1\x1a\x60\x34\x63\xe2\x4e\x5a\x23\xea\x2c\x11\x85\x55\xcc\xa5\xd1\xe4\x82\xf8\x89\x04\xca\x2e\x61\xe6\x80\x08\x4c\x1d\xaa\x86\x51\x3c\x34\x49\x26\x1f\xc5\xa9\x31\xa3\x06\xd4\x40\xe6\xe5\x61\x57\x4e\x9f\x5d\x97\xeb\x99\x50\x39\xa8\x68\xd5\x5e\x7f\x5e\xa5\x3d\x54\x30\x7d\xa8\x5c\xc2\xc8\x24\x79\x9c\x9b\xd5\xd3\x12\x00\x00\x27\xd5\xd1\xbe\xcd\x59\x21\x0f\xa4\x61\x45\x02\x8f\x44\xff\xee\x2a\xeb\xcc\x6e\x87\xc4\x88\x5c\x6e\xad\x45\xa7\x06\xff\x90\x2a\x8c\xbc\x9d\x65\xcc\x12\x8d\x8d\xbb\x53\xa6\xb3\xea\x34\x4f\x00\x70\x97\xa9\xf0\xba\xc2\x44\xa1\xbc\x31\x97\xed\xa8\xce\x4b\xe4\x18\x8c\x72\x8b\x32\x42\x87\xf3\x7d\xa0\x8a\xd5\x71\x6a\x89\x9c\x93\x31\x9c\xc6\xa6\x2f\x54\xaf\x9b\xa0\x0d\x37\xd6\x38\x07\x4b\x95\x59\x59\x26\xa5\xe9\xa7\xb5\x8e\xbc\x6c\xab\x57\xed\x53\xe4\x4a\x39\x98\x3d\xbc\xef\x90\xba\x34\x4f\x47\xe7\xfe\x14\x3a\x1c\x97\xd9\x9d\x66\x2b\x5c\xb5\xa6\xaa\x16\x9d\x2a\x5a\x38\x14\xdc\x4e\xfb\xca\xa2\xa5\x0c\x67\x1c\x5e\xe7\x40\x83\xba\x24\xf2\x7c\x25\x7f\xcc\x2d\xcf\xa6\x57\x01\x48\xfe\x4d\xa1\x0b\x9b\x56\x4c\x1d\x52\x3a\x2f\x51\xe5\x4a\xd4\x68\x03\x7b\x1f\x38\xb2\x73\x2a\x64\x58\x19\x1b\xe0\x9c\x4a\x97\x35\x60\xf2\xd8\x6a\xb2\x5b\x70\x9f\x90\x6b\xdd\xcd\x26\x55\x59\x95\x11\xda\x62\x93\xd6\xdd\x64\x60\x6c\xdd\x26\xad\xc6\x4c\xcf\x53\x9b\x54\x72\x86\x85\x40\x95\xa5\x0b\x98\x74\x1a\x13\x1d\xd6\xda\x9e\xec\x29\xf6\x7b\x69\x83\x45\xab\xe7\xf3\x86\xda\xb2\xb4\xb4\x5a\xe5\x77\xd7\x3a\xac\xe1\x30\x54\x68\xfe\xcc\x1a\xa5\x1a\x09\x26\xe0\x21\xcd\x80\x5c\x97\xc7\x56\x60\x1f\x29\x93\xe5\x3b\x00\x5e\x81\xa6\x4c\x31\xfa\x43\xe6\x7c\x5d\x19\xdf\xa2\x91\xc5\xc6\xdc\xf5\x72\x2e\x2d\x93\xcb\xf8\x38\xa7\xe8\x1b\x65\xcb\x75\xc7\x0b\x4a\xd9\x7c\x05\xed\x57\x3e\x52\x84\xde\xd6\x00\x4e\xa3\x90\x72\x20\x17\xaa\x38\x78\xa9\x41\x07\x94\xa9\xb5\x23\x95\x92\x62\x00\x84\x2b\x8b\x3c\xae\x1e\x8f\xb1\x7f\x53\x66\x4c\x93\x4d\xa2\x36\xe1\x65\x2d\x98\xde\x0d\x21\xfa\xb3\x64\x23\x5f\xb0\xb6\x14\xd4\x9a\xc5\x51\x26\xa8\xd4\x71\xb8\x93\x08\xba\xe5\x71\x50\x42\xd0\x6b\x88\xfa\x1d\x91\xc7\x00\x41\x99\x8d\x28\x23\x08\x5a\x71\x82\xc6\x97\x21\xbd\xd6\xc7\x4a\x70\xbf\x13\xba\x6c\x22\xcd\x1f\x31\xd7\xb2\xbc\x6b\x49\xf3\x86\x5a\x56\xaa\xd0\x70\x40\xea\x9d\x3f\x2d\x92\x3d\x36\x97\x53\xe6\xf1\x06\x73\xac\xd0\xe2\x2c\xb6\xa9\x65\x3a\x33\xad\x91\xa8\x65\x5a\x35\xaf\xb0\xfb\x14\x52\x39\x2b\x37\x83\x4e\xb9\x39\xdf\xe5\x49\x6e\xf4\xdb\x87\x0e\x1f\xd7\x9d\x58\xba\x1f\xc2\x16\x67\x43\x53\xd9\xae\xe5\xab\xb3\x6c\x6d\x75\x83\x0d\xbe\xc2\x2c\x87\x33\xb6\xf6\x6d\xf4\x39\x7a\x1b\xfd\xe3\x4f\xc9\x50\x45\xc7\xb0\x8e\x42\x5e\xdd\xec\xab\x72\xf9\xf3\xa4\x1b\xca\xf2\x0e\xe6\x1a\xfd\xa3\x1b\x46\x26\x42\x11\x5e\x6d\xf2\x16\x63\x0e\xc3\x20\xcf\x72\xd0\x34\xe3\xb1\x73\xca\xcd\x85\x6a\x8d\x5c\x99\x67\x31\x48\x39\x03\x54\x31\x72\x46\x42\x43\x8d\x5a\xa3\x93\x30\x4a\x50\x68\xca\xcf\x77\x8c\x1c\x05\xc2\xe5\xe5\x61\x00\x6e\x99\xd9\x5d\x62\xd0\xd5\xb5\xd6\x02\x50\x35\xb4\x1a\xd0\xde\x82\xec\x95\x47\xf7\xa3\x7f\xfe\x6e\xc1\xd2\x57\x80\xa3\x67\xfc\xdd\x6b\x17\x0f\xab\x75\xca\xa5\x01\x43\xd8\xe2\x18\x3f\xe2\x96\xa0\xb3\xcd\xae\xb2\x0c\x1a\xb2\x7c\xdd\xfd\xd4\x40\xec\x2d\x17\x5e\x25\x3b\xa9\x95\x78\x3e\xd0\x40\x35\x08\x65\xec\x79\x13\x41\xcc\x55\x9b\x39\x89\x01\x93\x13\x35\x34\x6d\xc6\x84\x82\x57\x62\x70\xd3\x5c\x21\x2c\x00\x89\x02\x11\x47\x08\x8f\x7f\x93\x68\x44\x1a\x22\xdb\xe9\x09\x33\x21\xc0\x0a\xe9\x84\x9b\x48\x54\x5c\x80\x36\x48\x38\x93\x60\x39\x4c\xb4\x45\x35\x74\xa8\x06\x56\x13\x85\x1a\x5c\x91\x29\xe8\xd9\xed\xaa\x7b\x60\xb4\xb6\x7b\xe8\xe8\x95\xe3\x07\x99\x0a\xea\x94\xbb\x15\x81\x40\x60\x4e\xc0\xb5\xfb\xf6\xe7\x94\x7b\x94\x81\x39\xcd\x01\xe7\x9e\x9e\xdd\xb7\xef\x76\x35\xe6\xd9\x9b\x3a\x57\x8e\x6e\x59\xaa\x1c\x75\x3f\x3d\x7b\xe5\xe8\xe6\x25\xea\x31\xcf\x34\x2a\x76\x0b\x65\x5c\x7b\x7a\xf0\x3f\x67\x6d\xa1\xb1\x65\x26\x9c\xd5\x62\x2b\x68\x50\xe2\x8c\xe6\x39\x42\xc6\xed\x7b\x9c\x0d\x4f\x8d\x51\x2c\x6d\x1b\xbd\x12\xbc\xd5\xb3\xc7\x55\x5b\x60\x6c\xea\x5c\x35\x7a\x48\xb7\x76\xcc\x83\x75\xca\x3d\x8a\xc0\x9c\x60\x80\x14\x84\x7a\x72\xc7\xe6\xb9\xe4\x8e\xf8\x9f\xab\xe1\xf0\x58\x0d\x7e\xb0\x55\xd3\x9a\x0d\x85\x67\x76\x8e\x5e\x35\x79\xb0\x23\xaf\x51\x28\x32\x27\x7d\x43\x57\xed\x03\xa3\x15\x4b\x19\x73\xeb\xa5\x8a\xd1\x4f\x36\xa4\x9f\x37\x9d\xd5\x90\x6f\x1b\x36\x6b\x95\xe8\xb7\x43\xc4\xcc\x18\x44\x8d\xa3\x26\x50\x53\xa8\xd9\xd4\x3c\xea\x4a\xea\x4e\xb2\x9f\x13\x2c\x14\x5c\xd5\x85\x44\x65\xce\x50\x5a\x43\x31\x11\x24\xd3\xa1\xc4\x20\x2a\x72\xe2\x7f\x82\xd1\x31\xd1\xbd\xc4\x63\x81\xc8\x85\x04\x1d\x4f\x51\x65\x93\x16\x14\x34\x7d\xa4\x54\x42\x90\x86\x25\x22\xac\x39\x04\x02\x3a\x16\x98\xe9\x10\x9e\x76\xcd\x80\xd5\xe1\x4f\x48\x6e\x21\x20\xc2\x88\xfb\x22\x42\x5d\x62\xba\x8d\x07\x17\xd0\x09\xa2\xec\x50\x49\x48\x27\x68\xb7\x24\x74\x6c\x24\x0f\x67\x1a\x75\x70\x3b\x30\x1b\x0c\x79\xb9\x5c\x23\xd3\xd0\x30\xc2\xc2\xb8\x69\x49\x8b\x71\x83\x5a\xd7\x08\xa5\xb3\xa4\x21\x17\x84\x80\xb5\x99\x2d\x7a\x39\x03\x24\x01\x45\x79\xe1\x0c\x28\xaf\x57\xc8\xac\x0c\x03\x69\xab\x83\xb6\x96\xd4\x2a\x2f\x63\x19\xd5\x5b\x34\xa7\x0c\xba\x5c\x36\xb3\x9a\x01\xb4\xc7\x50\xe4\xe7\x75\xf0\xb9\x9a\xab\xcf\xfc\x0c\x9f\x48\x35\x33\xc7\x67\x3d\x3e\xe3\xaf\xb3\xf2\x8f\xa1\x02\x58\x85\x4e\xdf\x16\x0f\x6f\xdc\x51\xee\x19\x35\xfc\x9b\x1a\xa9\x5c\xca\x38\x3c\xcc\xd0\x07\x06\x4f\xb9\x6e\xb4\xc6\x1d\x90\x83\x9d\x7d\xa7\xd5\xa9\x02\x4e\xc5\x12\x85\x68\x0d\x66\x7f\x0b\x20\x66\x74\x2b\x18\x03\x78\x8d\xe6\xa4\x32\x83\x93\x8d\xc1\xd9\x6d\x53\x34\x90\x81\xcc\x38\xcb\x13\x76\xd7\x95\x32\xe0\x85\x0a\x29\xd1\xbb\x93\xb3\x1c\xc7\xe8\x24\x3a\x28\xa1\xb5\x5a\x1f\xf4\x31\xb4\x1c\x00\xa5\x11\x46\xca\xd8\xc8\x08\x87\xa4\x04\x82\x62\x70\x42\xa3\x32\x6b\x94\xb4\x59\x63\xc3\xc3\x90\x51\x2b\xe1\x8e\xbf\xe7\xa4\x6e\xfa\x17\x23\xfd\x34\x15\x77\xc3\xeb\xdd\xa9\x7f\xb9\x2f\xa9\xa3\x2b\x9e\x02\x6b\x4f\xeb\x54\x3d\xf5\x23\xad\xca\xb6\x02\x4e\x86\xa7\x0e\x3d\x0c\x14\x3b\xfd\x9c\x0e\x33\xd2\xc9\x33\x7f\xf8\x51\xf2\x9d\x0a\x40\x26\x2e\x03\x12\xd6\xaf\x06\xc9\x97\x2f\x99\x6f\x44\x93\x05\x7b\xe3\x0c\xf6\x02\xb1\xe9\x1b\x4c\x8d\xc5\x3d\x61\x05\xb5\x95\xda\x4d\xdd\x4d\x3d\x49\xf5\xf6\xef\xf4\xf4\x3b\x87\x65\xcf\x87\x2c\x27\xf4\x03\xf1\xed\x64\x3c\xe7\x46\x4f\xc4\x63\xd7\xfd\x4a\xfc\xff\x77\x79\x5e\x04\x16\xf3\xe8\x40\x16\xd9\xcf\x4c\x92\x03\x7b\xa2\xbc\x69\xd7\xbc\xbe\x9e\xfa\xc9\xa5\x61\xd8\x13\xee\x72\xec\x71\x84\x53\x59\x02\xd0\xd1\x7f\x3c\x00\xea\xff\x2e\xbf\xab\x27\x5c\x9a\x4a\x32\xc9\xc9\xf5\xe7\xbc\x2b\xdf\xe9\x5d\x3e\x28\x45\xcd\xdb\x35\xb9\x5e\x42\x85\x4b\xc3\xf8\x31\xba\xc2\x67\x92\xfd\xd5\x80\xfa\x62\x41\x74\xd1\xd4\xff\xa6\x00\xd8\x0e\xa8\xd2\x70\x0f\xa2\x88\x37\x6f\xa2\x43\x2f\xa1\xd2\xb2\x9b\x1a\x6a\x38\x9e\x03\x16\x51\xeb\x05\x0f\x82\x0f\x51\xbf\xa3\xde\xa2\x3e\xc2\x94\xd8\x59\xa0\x01\x6e\x50\x08\x6a\x2e\xb2\xe3\xd7\xef\x24\x51\x6c\x77\xdd\x7f\x19\xa7\xff\xcb\xef\xf9\x5b\xfa\xc7\x85\x40\x3e\xff\xb7\xd7\xfb\x7f\xf9\x7c\xac\xa0\xac\x72\x46\xd4\x52\xe9\x3d\xe7\x76\xe0\x7f\x3f\x24\x7f\x6b\xc1\x73\x07\x48\x0d\xf0\x4c\xf4\x9b\x6b\x01\xea\xbf\xbf\x93\x84\x0a\xda\x4e\x09\xfb\x5c\x12\x7c\x44\x03\x20\x67\xbf\xfd\xb5\xe0\xa3\xfd\xc1\x8b\x43\x20\x5d\x3c\x78\x46\xc0\x4c\x11\x0e\xf0\xbf\xa8\xd6\xf7\x5f\x94\x3d\x0f\x86\x09\xf3\x9a\xb5\x67\xb5\x4c\x2f\xdb\x85\x47\x49\x88\xec\x18\x5e\xa0\x54\x47\x64\x9d\x19\x65\x21\xb3\xc9\x90\xb1\x32\x65\xf6\xa3\xf7\xd3\xba\x75\xe8\x7d\x87\xc3\x39\xdc\x71\x12\x74\x9f\x74\xb4\x3b\x1c\xa8\x47\x54\xb0\x7b\x1f\xbd\xdf\xf7\xaa\xa0\x5a\x97\x44\x49\x41\xb5\xae\x14\xf8\x49\x01\xc7\xc9\x93\xa4\xc2\x27\xa2\x6e\x1d\x9b\xf6\xbd\x4c\xf6\x53\x9c\x82\xd4\x68\x04\x91\x7f\x89\x7c\x0f\xa6\x1d\x09\x5f\x02\x44\x5f\x31\x20\xbd\x84\xb2\x11\x46\x4f\x2c\x2a\xf0\xec\xe7\xf3\xe2\x0c\xe2\x34\x26\x30\xa0\x34\xc1\x06\x09\x08\xbe\x61\x44\x72\x0a\xd3\x67\xca\xe0\xb8\xaa\x96\xb5\x95\xf8\xd8\xba\xa6\x12\xdd\x37\xaa\xb5\x65\x53\x93\x70\x00\x57\x2d\x07\xfa\xa7\xbc\x35\xf5\xb9\x8d\x5f\xd5\xd4\xa7\x9a\x9f\xec\xbe\xfb\x6d\x30\xa4\x6a\x5c\xb0\x72\x4d\x2b\x39\xae\x05\x33\x5a\x47\x35\x6d\x6a\x21\x07\x26\x5c\x39\xbf\x6d\xe9\xde\xa1\xe4\x78\x4b\xea\x58\xfb\xf2\x45\x7b\x9b\xdb\x57\x2c\xba\xb5\xf0\x05\xf4\xe9\xd2\x82\x2a\xa7\xa2\x73\xfc\x8e\x31\xc7\x1e\x5c\x7e\xac\x6d\x7e\x65\xf3\x2d\x4b\xf1\x71\xe8\xde\xa5\x73\x56\xb4\x37\xef\x5d\xb4\xbc\xbd\xf9\xd6\x45\xc4\xfe\xea\x2c\x05\x89\x2f\x70\xa3\x88\xb9\xc8\x9b\xd2\xc6\xee\xe2\xc3\xe3\x67\x87\xbd\x4b\xa6\xe4\x43\xbf\xad\xd7\xe6\x87\xf9\x53\x96\x8c\xde\x75\xdf\xae\xd1\xf4\xd7\xd7\xbf\x14\xe8\x7b\x5d\xd0\x04\x8b\x05\x5e\xba\x3e\xf9\xdd\xad\xb7\x7e\x77\x0e\x53\x24\x63\x77\xe4\xc6\x54\x3c\xd0\xb1\xa1\x7c\xa0\x22\x1f\x51\x44\x52\x4d\x63\x85\x08\x9b\xa8\x98\x6a\x49\xc2\x64\x2a\x59\x0b\x9f\x4e\x35\xa5\x9a\xd8\xd3\x7e\x77\xaa\xd6\x51\xef\x48\xd5\xba\xfd\x05\x41\xd8\x6b\xca\x33\xc1\xde\x60\xc1\x24\x30\x09\xae\xfd\x74\x31\x42\x08\xa6\x28\x5f\xa5\x0e\x25\xb5\x5a\x90\xd4\x55\xfa\x68\x2a\x5c\xaf\x06\x94\x54\x7a\x96\x52\xd7\x8b\x50\x79\xf8\xfe\x52\xd1\x8f\xc9\x39\xab\x68\x9c\xc5\x06\x84\xe7\x60\x41\xfa\x1c\xca\xc4\xc9\x73\xb1\x64\xc7\x17\xd3\xac\x62\x20\xfd\x80\x01\xe1\x80\x9f\x52\x58\x7c\xf1\x01\x0a\x4e\x84\x6a\xc1\x8d\x68\x01\x5a\xc0\xbe\x3b\x20\x92\x27\x86\x0f\xa3\xc1\x68\x30\x7b\x2a\xe8\x41\xb5\xd6\x5a\x2b\xaa\x65\x68\xc8\xa6\x83\x9e\x60\xae\x0f\x3c\x8a\x7f\xbd\xe6\xb8\x19\xf4\xfa\x72\xc1\xa3\xfe\x9c\xae\x5e\x50\xbe\xbf\xfb\x81\x07\x1e\x48\x6d\xcb\x84\x56\xde\x05\xe4\xfb\xbb\x9f\x7d\xf6\xd9\x54\x15\xea\xf2\x57\x6b\x4f\xa8\xd5\x27\x20\xfe\x23\x67\x6d\xb5\x1f\xf4\x04\x6b\xb5\x4f\x83\xeb\xf0\xb1\x57\x2e\xef\xd5\xd6\x06\x51\xf7\xd3\xda\x5a\x51\xa6\x82\xa4\x14\x0b\xf1\x7b\xcb\x70\xbb\x07\xa9\x02\xaa\x8e\xec\xd6\x1a\x3d\x34\x41\x36\x0d\xd2\x98\xc2\x8b\x42\x8f\x17\x33\x3f\x94\xd8\x23\x39\x8f\xc1\x14\xf0\x44\x62\x25\x3e\x4f\xcc\x43\x78\x75\x9f\x27\x40\x3c\x8f\xe1\x1c\xa1\xc3\xd2\x3e\x0f\x57\x8a\x00\x38\xdb\xd7\xd9\x2d\x01\x7b\xf4\x07\x6a\x96\xeb\x3e\x98\x81\x0e\xff\x39\x05\xd8\xa3\x57\xbd\x39\x13\xa6\x2e\x59\x7a\x26\x0e\xc2\x6f\xbe\x82\xfe\x08\xac\x6d\x13\x9e\x43\x7d\xe8\x73\xd8\x31\xf6\x8a\x65\x35\x07\x97\x5c\x5a\x3c\x72\x49\xb2\x29\x75\x2b\xf3\xc0\x5a\xf4\xc7\xb9\x9d\x2f\xa4\x9e\xac\x4d\xa0\x37\x81\xf4\x2f\x6f\x03\xfe\x8a\x0f\xaf\xd4\xb9\x16\xad\x8a\xdc\x7d\xe8\xb9\xa1\xad\xd7\xfd\xc5\xd1\xb0\x6e\xc2\xe3\x1d\x59\x07\x56\x0d\x5b\x33\xaa\xdc\x96\xfe\x86\x99\xfd\x4c\x17\x15\xa0\xf2\xf0\x9b\x0c\x16\xfc\xfc\x5c\xb0\x1a\xf2\xc2\xee\x13\xd9\x5b\x20\x1b\x0d\xb4\x2f\x86\x29\x55\x43\xfa\xc4\xe2\x32\x9e\x78\xec\x1c\xba\x0f\x81\x26\xa2\x23\x66\x1f\x1e\x7a\xb8\x51\x06\x4a\xc2\x8e\xa1\x6d\x60\xdd\xb2\x9e\x6b\xe7\x87\x9a\x47\xb5\x3e\x7c\xe7\x8a\xa9\x87\x9f\x5d\x0b\xe5\x8d\x43\xc0\x2d\x60\xe7\x86\xe4\xfe\xdb\x2e\x7f\xb3\xfa\x2a\xc5\xd0\xe2\xc5\x0a\xc4\x34\xcd\x03\x35\xe8\xf7\xe7\x4b\xc1\xd0\xf5\x7d\x5f\x2e\x5d\x7c\x5b\x4e\x49\x77\xd9\xf0\x1c\x1d\x7a\xfe\xa9\xce\xc9\xe8\x91\xe3\x8b\xe7\x64\xb5\x0c\x92\x1b\x36\x3f\x72\x70\xe3\xd6\xfd\xbf\xf3\x86\xc1\x25\xab\x4b\xeb\x81\xbc\x35\xc3\x6b\x71\x19\x9c\xfb\x10\x41\x67\xed\xf7\x5a\x20\xec\xc1\x9a\x33\xfa\x67\x21\x42\x99\x83\x01\x08\x45\x09\x03\xe5\x03\xc2\x1c\x52\x88\xc7\x95\xa0\x3e\x43\x80\x6c\x29\x49\xc1\xb5\xaf\x5d\x7b\xed\x6b\xa9\x6d\x3b\xe6\xd8\xed\x73\x5a\xeb\xdc\xee\x3d\x2d\xc6\x0e\x43\xd6\xf2\xc1\x73\xe8\xb7\x1f\x5b\xb7\xfe\xb1\xc7\xd6\xaf\x7b\x6c\x17\xfa\xe1\x08\x1a\xa6\x7c\x7e\xf3\xaa\xa7\xad\xff\x00\x5b\x86\x4f\x56\x99\x08\xc6\x80\xe2\x99\x23\x40\xc1\xb8\x49\xfd\x6b\xcf\x3c\xf7\xf6\x0e\x49\x8e\x7b\x77\x4b\x6b\xad\x5b\xea\x91\x56\x0e\xa5\x3f\x5a\xf7\x18\xae\xff\xe8\xa3\xeb\x9f\x45\x3f\xa2\xdf\x6f\x78\x74\xcf\xa5\x13\xc1\x03\xb7\x16\x41\xb0\xfb\x19\x20\x45\x3f\x50\xe7\xf1\x8e\x52\xfc\x3e\x0d\x54\x6b\x1a\x09\x80\x6c\x9f\x52\x22\x37\x28\x98\x2f\xc7\xf1\x43\xc7\xcf\x6d\x84\x55\x65\x18\x8f\x40\x24\xfd\x9d\x38\x9a\xbc\x7d\x20\xb3\xbf\x2c\xb6\x09\x61\x0e\xdf\x5b\xd2\xb3\x78\x71\x0f\xd2\x5e\xda\x51\x3a\xd9\x5a\x52\x50\xb9\xd2\x6a\x89\x56\x75\x98\x0c\x1d\x74\x9f\xf8\x25\x0e\x1a\x6e\x98\x32\xe7\x66\x39\x18\xbf\xeb\xd8\xb1\x5d\x37\xfe\x11\x7e\x2c\xe3\x87\x55\xa3\xbf\x88\x1f\xe8\xa7\xed\xaf\x6e\xdb\x36\x63\xe6\x36\x3a\xbb\x67\xf1\x92\xe1\xed\x8b\xd1\xab\x07\x96\x96\x17\x19\x0c\xf8\x1a\x95\x2b\x2d\x1e\x16\x2e\x14\x3f\xe6\x4d\x83\x26\xae\xbc\x66\x76\xdf\xb1\x9d\xbb\x8e\xbd\x73\x23\x7a\x0e\x04\x56\x80\x77\x71\x3a\xea\x99\xb1\x6d\xdb\xab\xdb\xb7\x11\xb4\xf1\xb3\x63\x24\x5f\xb1\x67\x29\x15\xee\x97\xf9\x98\x4f\x1e\x26\xa0\x26\xd1\x5c\x40\x10\xbe\x62\x06\xca\x64\xc7\x1c\x33\xad\x01\x34\xd1\x6e\x8d\x27\x42\x80\x58\x1b\x01\xcc\xa1\xd1\x3c\x69\x01\x20\xa1\x03\x21\x9e\x68\x25\xb2\x44\xea\xc4\xa9\x59\x2e\x88\x53\x12\x74\x20\x41\x14\xd7\xd8\x38\xa6\xea\x4d\x74\xa3\x06\xa2\x89\x78\xec\x2b\x38\x8d\xcc\x0b\xdb\xf2\x0e\xdd\x50\x33\xb5\xc8\x4d\x33\xcf\xe9\x20\x27\xf5\x0d\xbf\x46\x92\x3c\xa2\x2c\xe6\xf5\x83\x6f\x94\xfe\xe3\x18\x77\xdf\xdf\xca\x52\xa1\xc2\xf7\xd0\x0b\xfc\xc7\x86\xf6\xb0\xa5\xd8\x57\x64\x29\x82\xbb\xdf\xd5\x2b\x4c\xaa\xb0\xbf\xca\xd3\xa4\xf0\xfe\x13\x94\xad\xdd\xfe\x3e\x9a\xb4\xdb\xdb\x31\xa8\x52\xa7\x03\x3b\xdd\x71\xa5\x22\x04\x16\xa1\xeb\x4c\x4e\xba\x2c\x60\x2f\x6d\xf6\x4f\xe4\x94\xb0\x1c\x6d\x99\x38\xe4\xfa\xb9\xa3\x8c\x46\x30\xd3\x56\xa9\xd3\xd7\x5c\x36\x26\xf5\x19\xba\xc9\xe9\xa3\x19\x8e\xdd\x0f\x16\x81\x79\x0f\x68\x4d\x26\xfa\xd1\x1a\x74\xcd\x33\x4a\x30\xc3\xed\x60\xa0\xc1\x94\x67\x8d\xa3\x97\xd0\xce\x40\x9b\xcf\xe0\x35\x99\xe4\x7a\x7a\x08\x58\xf0\xc2\x97\x23\xd1\xd5\x86\x31\xe3\x6f\x9e\xd4\xa0\x52\x01\xda\xae\xd1\x54\x89\x7d\xa4\x56\x2a\xf6\x79\xb2\xaf\xdb\x70\x0e\x2d\x82\xf7\xe0\xd6\x22\x44\x24\xd7\x9f\x32\xd0\x70\xd4\x93\x31\x20\xcd\x38\x12\xc1\xed\x47\xba\x87\x99\xa8\x30\x80\x13\x93\x37\x4f\x9e\xbc\x79\x23\xfd\xf3\x78\x68\x91\xa5\x28\x99\x05\xb2\xb4\x90\x84\xf4\xea\xae\xee\x9e\xee\x3e\x0a\x1f\xba\xd4\xfa\x4d\x93\x1c\x73\xcd\x77\x4c\xa3\xa9\x69\x77\x98\xe7\x3a\x26\x6d\x02\xeb\x48\xa1\xc9\xe0\x04\x98\x29\xe5\x79\x69\xca\x2a\x46\x29\x84\x49\xf6\x24\x71\xbd\x99\x14\x8f\x98\x9e\x4b\xe2\xd2\x77\x4e\x5e\xbf\x7e\x32\x9a\xb4\x49\xb4\xab\x95\x92\xe9\x36\x4a\x55\x60\x3e\xbe\x75\x00\xaf\xf6\xbf\x3c\xb0\x88\xb3\xec\x49\x7b\xc4\x32\xf3\x19\xbb\x59\x70\xee\xdd\xd3\x29\x5c\xd6\xa4\x4d\x17\x7d\xf4\xa4\x88\x8a\x97\x24\x2f\x70\xea\xb4\xf8\xb8\x33\x06\xbc\x37\xe3\x11\xd2\x60\x72\xd3\x24\xf2\x12\xb5\xe4\xf1\x6b\xc5\xe3\xb9\x97\x38\x41\xc8\xac\x13\xe4\x55\x50\x96\xd0\x4c\x60\xa3\xd8\x00\x7d\xcf\x08\x51\x4c\x0f\x64\x61\x1e\xe5\x84\xf0\x7e\x94\x9f\x0c\x54\x57\x06\xeb\x8f\x6c\x02\x11\xf7\x69\x09\xf2\x66\xfd\x47\xd1\x9f\x30\x51\x22\x14\x8f\xec\x89\xa0\x0d\x45\x80\xdc\x6f\x45\xbd\x56\xbf\x1c\xa0\x88\x2d\xc8\x83\x1d\x9f\x08\xc7\x97\xc8\x31\x49\x60\xe1\x93\x7c\xd0\xf6\x12\xd8\x81\x8f\x9f\x80\x1d\x9d\x25\x41\xdd\xb6\xa0\xd5\xe7\xb3\x06\xb7\xe9\x82\x38\xf7\x86\xfe\x43\x92\xe7\x11\xae\x10\x44\x0b\x85\xc3\x80\xb9\xc6\x48\xe5\x52\x8d\x82\x2e\x4c\x1a\x34\x49\x9c\xe5\xd3\x66\xd8\xf1\x04\x4e\xf5\x0c\x48\xcd\x12\x52\x79\x9c\xea\x17\xf6\x13\xfb\x4b\x33\x82\x7b\x3e\x30\x50\x35\x6d\xb6\xeb\xf7\x68\xcb\xcd\x39\x76\x13\x9b\xb5\x79\xd1\xdf\xee\xe7\xd5\xbc\xa3\xcb\xf7\x25\xfa\xc3\x4d\xbb\x8a\x7c\x56\xce\xb5\x7a\x03\x30\xbf\x63\x51\x5b\x7d\x0b\xc2\xeb\xd0\xa3\x0f\xbf\xd1\x63\x76\x67\xbb\x15\xce\x2d\x0f\xee\x03\xf9\xb3\x8d\xbc\x33\xf7\xcd\x0b\xe1\xe7\x9b\xb2\xf8\xa5\x5e\x59\xae\xc1\x29\xb5\xcf\x56\xd8\xbf\x08\x1b\xb7\xe5\xa8\xa2\x56\x9f\xd4\xb3\x56\xe5\x03\xba\x42\xf3\xd0\x61\x85\x5c\xc0\xe5\xce\x91\x06\x1a\xab\x94\xd9\x13\x2e\x10\x06\x01\xd1\x97\x2d\xfe\x26\x3c\xa1\x86\x89\x5f\x36\x8e\xe6\x30\x8f\x1d\xc2\xa1\x04\x9f\xf0\x30\x14\x7a\xc7\x02\xcc\x88\xcd\xdb\xee\x42\xc7\x40\xa1\x05\x7d\x0a\xce\xe0\x30\xc8\x67\xde\x49\x3d\xed\x46\x53\x5d\xe8\x2b\x17\x28\x84\x83\x5d\x60\x9f\x0b\xe8\x5c\x78\xec\xe9\xf0\xef\x1a\x19\xc5\x5c\x4a\xa9\xf1\x0a\x4b\x3c\xda\x57\x52\x43\xa8\x51\xd4\x34\x6a\x3a\xb5\x18\x73\xa4\xdb\xa8\xeb\xa8\xdb\xa8\x83\x54\x2f\xf5\x2e\xf1\xb6\x45\x7a\xa9\x97\x18\x8d\x92\x19\x1b\x47\x71\x33\x92\xb6\xe5\x68\x83\x39\xe3\x3c\x20\x46\x76\x07\xbd\x85\xc4\xb6\x37\x61\x26\x8a\x38\xb1\x50\xa2\x04\xcf\xf6\xb4\x99\x33\xf8\x84\xf4\x28\xa6\xd9\xcf\x65\xb8\xd3\x8a\x3b\x38\x82\x73\x64\x80\xe7\x0c\x82\x67\x24\xe2\x22\xd9\x94\xb8\x30\x26\x46\x44\xbb\xf0\x32\x40\x93\x6c\xb2\x06\xf2\x44\x8c\x69\xee\x8f\x61\x7a\xd5\xc4\x73\xc5\x42\x0c\xf2\xb1\x78\xda\x18\x5f\xc0\x6f\x16\xa8\x3a\x92\x40\x09\x42\x0a\x5a\x8b\x49\x48\x95\x5c\xa6\x56\xab\x81\x4a\x66\x02\x39\x0a\xa5\x4a\xaa\x95\xaa\x80\x5c\x21\x91\xa9\x15\x32\xd9\x99\x2f\x0c\x06\xa8\x86\x3a\x1d\x54\x8f\xb3\xd9\xa0\x54\x66\x36\xcb\xa4\xc0\x76\xc4\x6a\x55\xc8\xa1\xd1\x08\xe5\x8a\xc9\x66\x33\x54\xaa\x8c\x46\x95\xb2\x0b\xc7\xd5\x12\x99\xc1\x20\x93\xa8\xc1\x06\xf4\x91\xd1\x28\xe7\xb4\x10\xf3\x4b\x5a\x4e\x3e\x99\xe7\x15\x52\x1c\xc2\x71\xa9\x62\x1a\x4e\x33\xf0\x38\xa2\x92\xca\x94\xe0\xca\x97\x35\x1a\x0d\x66\x09\xd4\x6a\x8d\x41\x33\x5d\xad\xd6\x9a\xb4\x40\xa9\x04\x5a\x93\xe6\x4f\x6a\xbd\x4d\x0f\x24\x12\x25\x94\xcb\x14\x52\x4e\x0d\x99\x59\x07\x96\xf5\xfd\x5b\xa5\x77\x8c\xee\x7a\x01\xb8\x74\xb1\xb2\x65\x07\xf6\x7f\x03\x15\x72\xb5\x5a\x9e\xfa\xe1\x1b\xb9\xaa\xe4\x18\x6c\xd6\x4a\x59\x56\xaa\x95\xa4\x9e\x05\x9f\x03\x39\xa7\x90\x71\x2a\xb0\x20\xb9\x4e\x26\x5b\x97\x94\x35\xbd\xf5\xba\x4c\xfe\xda\x5b\x32\x3c\x32\x3f\xff\xe1\x4b\x85\xe2\xcb\x1f\x94\x6c\xdf\xf7\x2a\xd5\xf7\x7d\x2a\xf7\x67\x3f\x6a\x65\xdc\x8f\x9f\x49\x64\xc8\x04\x17\xa2\xcd\x3f\x72\x0a\xfd\x8f\x60\xad\x5e\x31\x1c\xe5\x7d\x2f\x55\xf0\xdf\x83\x77\x79\x45\x16\x92\x7c\x6b\x34\x7e\x0b\x4e\xcb\x54\xaa\x94\x0e\x7e\x86\xe0\x57\x72\x8d\x5a\xf1\x15\x40\x0a\xb5\xda\x85\x0c\x5f\x28\xb4\x5a\xc5\x17\xe0\x0b\xa5\x56\x8b\xa4\xff\x54\xe9\xf5\xaa\x25\xcb\xe0\x5a\x5a\x23\xe3\x58\xa9\x3e\x75\xe3\xb2\xbb\xa0\x5e\x45\x6f\x32\xcb\xbd\xe8\x54\xaf\xe9\x00\x95\xc1\x27\xa0\x04\x1f\xc6\x76\x01\x81\x94\xa2\xb2\xfc\x09\x3c\xd5\x90\x1d\xfa\x2a\x60\xfa\xdf\x63\x8c\x00\x4e\x2d\x46\x4b\xe2\x90\x07\xef\x81\xbd\x2b\x8e\xa2\xdb\x50\x17\xba\xed\xe8\x0a\xb0\xf7\x57\xe2\x87\x41\x0f\x98\x76\x34\x13\x3f\x4a\x53\x63\x46\xdd\x27\xea\x63\xdc\x37\xaa\xef\xbe\x01\x11\x90\x33\x20\xc2\xe4\xe0\x53\x52\x8c\xe1\xd3\x80\xfd\x5c\x9e\xb2\x51\x3e\x6a\x32\x1e\x3b\x97\xe2\xb1\xb3\x15\xcf\x49\xbf\xdc\xaf\x33\x73\x3a\x0f\xf1\xa7\x2c\x28\x5b\x13\x11\x2e\x10\xa4\x65\x64\x13\x57\xc2\x19\xc5\x3d\x73\x0e\x0a\x7e\xfb\x88\x3d\x3b\x20\xd6\x21\x46\xb2\x07\x4b\x6c\x0e\x2a\x60\x44\xb0\xbf\xc7\xaf\x8d\x0f\x98\xb2\x50\x03\x20\x31\xe3\x49\x8e\x98\xbc\xc7\xf0\xbf\x90\x81\xa3\x49\xd1\x10\xb9\x8a\x84\x0d\xfa\xc8\x98\x2c\x61\x8f\x38\xc2\xfd\x00\xca\xc9\x70\x97\x63\x33\x58\x29\x57\xa2\x57\x94\x60\x3a\xb1\x35\x4b\x51\x10\x79\xa2\x15\xe5\x37\xb8\xb4\x6a\x08\x24\x75\x45\x97\xd7\x7c\x70\xff\x4d\xe3\x35\x2a\x0b\x60\xe5\x8c\x6c\xf2\x68\xb5\x0c\x96\x24\x1a\xfd\x16\x95\x4a\xe1\x36\x02\xb3\x52\x2f\x23\xc6\xf0\xca\x04\xb2\x97\x8c\x8e\x0e\x05\x1b\x34\x2a\xfc\x38\x02\x42\x85\x12\xac\xdd\xba\x13\x9a\xd8\x96\xa8\xbd\xd4\x05\x57\x58\x2e\x6d\x29\x52\x33\xcc\x66\x61\x8b\x2d\x03\xc3\x1c\x76\x34\xa2\x2b\x9c\x4a\x50\xa6\x3c\xad\x67\x28\x62\xd0\x76\x9a\x82\x23\x6c\x2e\xae\xd8\x84\x99\x2b\x00\x82\x61\x8f\xa5\x02\x9d\xe6\x94\x80\x91\xdb\xc2\xb3\xf3\x65\x1a\x08\x47\x77\x5f\xb1\xae\xe3\x96\x48\x58\x63\x2c\x94\x40\x9a\x75\xad\x19\xb4\x1f\xd9\x2d\x97\x87\xc7\xd1\xab\x73\x3a\xb9\x00\x1d\x66\x18\x80\xeb\x9a\x70\x7b\xa4\xe6\xc6\xed\x98\x28\x6e\x58\x38\x66\x51\xa9\xc2\xe2\x00\x80\x3a\xaf\x9f\x89\xdf\x68\xd4\x6f\xfb\x36\xbc\x91\x00\x1a\xe3\xd6\x8f\x45\xc9\xe6\x3a\x0e\x0b\x90\x7e\xb4\x44\x03\x7c\x25\x05\xc4\x35\x1b\x01\x56\x27\xb4\x9d\x0f\xb7\x38\x1d\x8d\xfd\x6a\x4b\xcf\x6d\xda\xbf\x2f\xc9\xd1\x90\xa1\x01\x4b\x27\xf7\xed\x6f\x42\xef\x76\x4e\x67\x21\x64\xf0\xd3\x4b\xe0\x75\x4b\xae\x83\x2c\x60\x18\x08\xd9\xe9\x9d\xbf\xa1\xd9\xe8\xe4\xfc\xd4\x7c\xf0\x89\xc1\xa6\x95\x5a\x68\xaf\x0c\xd9\xe1\xce\xf9\xf3\x51\xb3\xc1\x66\x24\xce\x76\xd9\x2c\x19\xf4\xa4\x3e\x92\xb9\x25\x46\xa3\xcd\x00\x9e\x98\xff\xcb\x76\x18\xf9\xdb\xda\x81\x98\x02\xf8\x08\xa8\x27\x91\x06\x43\x37\xf0\x91\x38\x2d\x36\x86\x00\xe1\x46\xc4\x0d\x85\x40\x88\xf3\xf4\xaf\x36\x02\xc8\x07\xd6\x61\xb3\x59\x39\x8b\x5f\x9a\x81\x2c\x47\xcf\x6f\x01\xbe\xc6\xde\x17\x1a\xd0\xa7\xcd\xb3\x19\x25\x8d\x7b\x17\x23\x51\xcc\x6b\x41\x1f\x36\x3e\xfb\xfc\x6f\x68\x86\xcf\xe6\xcd\xbb\x9d\xe3\xa5\x8c\x84\xe1\x64\xcc\xed\xf3\xe6\x01\x1d\xb0\xcd\x9f\xbf\x8f\xe3\x19\x1a\x5f\x47\xb9\x0f\xb7\xc9\xd7\xe8\x93\x8c\x8e\xcc\xc0\xf7\x2f\x15\x74\x81\x7f\x6b\x0b\x60\x8e\x52\xf4\xd3\x8d\x29\x0d\x82\xec\x08\x7c\x3a\x32\x72\x09\xd8\xe2\xaf\xbf\x73\x16\x18\x3c\xe9\xca\x96\x9c\x86\xe1\xcd\x35\x45\x1d\xe8\xba\x89\x80\x5d\xb1\xb2\xc4\x5d\x5a\xed\xfe\x6d\x2f\x78\xb7\xc6\x9c\xec\x18\xb1\xd2\xce\xcf\x4f\xfd\x09\x58\x80\x52\xef\xe9\x18\xef\xd6\x5c\xec\x9d\x72\xa8\xc8\x6f\x9c\x79\x74\x9e\x58\xc2\x0c\x18\x51\x5d\xca\xf0\xab\xaf\xc0\x24\xfb\xa8\x5e\xb2\xf9\xd1\xde\xd3\x8d\x69\xd2\xdf\xf0\xdc\xa0\x17\xf5\xf6\x92\x2a\xc9\x6e\x52\x85\x20\x67\x66\x9e\x35\xb3\x2f\x43\x9e\x37\x41\x35\x0b\x28\xeb\x31\x9f\x91\x8d\xf9\x9c\xe9\xb3\xf1\xd7\xdf\xc1\x47\xc0\xc5\x75\x40\xb0\x10\x16\xb4\xa0\xe3\x7c\x2c\x4a\x9c\x24\xc2\x34\x19\x0d\x93\x44\x49\x90\xfc\xe8\xca\xff\xf5\xed\x92\x49\x44\xc1\x6d\xf3\xa5\xd7\x7f\x78\xbd\xd4\x38\x3d\x39\xdc\xe4\x3d\x22\xf8\x7a\x63\x92\x03\xfe\xc0\xaf\xbd\x71\x32\x89\xa7\xb2\x77\xd0\x9d\x76\xeb\xc8\x85\x0b\x47\x5a\xed\x35\xa0\x35\x99\xb4\x21\x9b\xe0\x9f\xb1\x5f\xe7\x75\xc0\xb7\x2a\xa3\x5a\x04\x6d\xb6\xdf\xb4\x4e\x18\x33\x5e\x23\xfb\x1d\x37\x24\xe2\x04\xe8\x51\x1b\x12\x91\xd5\x4c\x5a\x01\x75\x25\x14\x21\x5e\x41\x0b\x00\x49\x31\x08\x29\xbf\xde\x39\x31\x91\x43\x7c\x47\x1e\xd8\x44\x18\x83\x4d\x07\xb4\xe0\x90\x9b\xdf\xb0\x41\x1b\x37\x18\x59\xdd\x8c\x19\x3a\xd6\xa8\x7f\xd6\x6e\x18\x3b\x56\x1f\x0f\x42\xbe\xa4\x84\x87\xbc\xe1\xb7\xcc\x4e\x05\x52\x53\xea\x04\x71\x25\x79\xb7\xb0\x6f\x7c\xb7\x26\x35\xd8\xb2\x0f\xec\xd9\x67\x94\xe8\x74\x31\xe3\x1a\xf4\xfc\x1a\x63\x4c\xab\xb9\xd1\x30\xa9\x6f\x12\x0f\xfd\x31\x43\xd9\x8d\x65\x86\x98\x5e\x77\x91\x3e\x1d\xfd\xad\xe3\xf4\xc2\xbd\x21\x36\xd3\x6a\x02\x1a\x66\x34\xf2\xeb\x4b\xa1\xe0\x85\x18\x09\x47\x7a\x01\x69\x16\xb5\x0c\xfd\x04\x64\xb2\xdf\xb4\x8e\xd1\xc9\x4c\x5d\x80\x8f\x10\xbf\x7f\x2f\x79\x7f\x20\xef\x04\x72\xd9\x45\xbe\x7f\x82\x1a\x46\xf0\x93\x7e\xd3\x9b\x55\x13\xdb\x51\x40\xb4\xdf\x89\x85\xa9\x60\xbe\xe2\x31\x71\xb4\xe0\xb7\x08\x10\x55\x77\x62\xbe\x88\xa9\x5c\x4c\x28\xf0\x62\x59\x92\x19\xfa\xf5\x8f\xdf\x25\xb5\x29\xa2\x0a\x5a\xfa\xc4\x13\x52\x1a\x07\x6c\xd2\xbf\xa9\xf1\xcb\xaa\xd5\x7f\xbb\x30\x1d\x2d\x57\x69\xe0\x55\xd0\xa4\xaa\x49\x9f\x7f\x53\x8b\xe0\x2b\x04\xf1\x95\xbe\xfb\x0e\x5f\x21\x88\xaf\x04\xf2\x79\xfc\x87\x8e\x5d\x98\x9e\x92\xe0\x2b\xd2\xe4\xd2\x72\x1c\xe8\xfb\x3d\x0e\x60\x9e\x27\x74\x76\x37\x7b\x1c\xb7\x17\xd1\xd0\xc5\xe4\x91\x04\x8a\x8e\x7d\xe4\x98\xeb\x31\xd9\x08\xed\x94\x08\xf6\x7b\x5c\xc7\x83\x80\xa8\x24\x0d\xdc\xee\x63\x8f\xcf\x9c\x5a\xf7\x87\x3b\x0a\xdb\x3b\x1c\x75\x73\x67\x2c\xed\x1a\x6b\x07\x76\xdb\xb8\x55\xab\x87\xdf\xbb\x7c\xfb\x1d\x6f\x1f\x7a\xf4\xb9\x72\xce\xda\x50\x51\xa7\x77\x97\x47\x62\xb5\x7f\xbc\xa3\x1a\xbe\xf4\xb2\xf9\x0a\xf4\xed\xed\xb6\xfc\x22\x5d\x6c\xc9\xb5\x1f\x03\x0e\x5c\xf2\xd6\x7b\x68\x37\xfa\xea\xe5\xae\x7b\xbf\x1c\x02\xc2\x87\x7b\x7f\x38\xd6\xbb\x6f\x3d\x60\x94\xa1\xac\xd9\x23\xc6\x76\x4e\x9f\xf0\xf4\x5f\xd2\x32\x7d\x4e\x9c\xd7\x24\x94\x1c\x73\x53\x7a\xcc\x99\x5a\x09\x36\x00\x0f\x74\x01\x36\x11\x92\x81\x40\x66\xc3\x19\xf3\x6e\x3a\x36\x80\x69\x14\x9d\x21\xed\x54\x8c\xb0\x24\x22\x0b\xfd\x57\x38\x01\x3d\x8a\x1e\xff\xfd\xef\xe9\x28\x0e\x7d\x87\x1e\x6d\x05\x5a\xbc\x78\x7d\x7d\x35\x68\x4b\xdd\xc5\xbc\xf9\x7b\xf4\x38\x50\xa5\xee\xa2\xa3\xde\xbe\x37\x8d\x79\xc6\xbe\x37\xbd\x5e\x3a\x8a\x03\x38\x01\x2c\x42\x97\x80\xd9\x1f\xf9\x37\x6c\xe8\x7b\x1f\xec\x38\xf4\xd1\xe5\x4f\x3c\xf1\xc4\xa4\x8f\xc0\x6c\x74\x09\xfa\x6a\x03\x80\xfe\x43\x60\x07\xba\x29\x37\xf5\x61\xb6\x39\xf5\xa1\x4a\x05\xbd\xe6\x6c\xe8\xcd\x36\x43\x2f\xa6\xe4\x3f\x34\x67\xf0\x5a\xf1\x8b\xb0\x2b\x71\xbf\x1c\x2b\xf6\x49\x61\xd7\xce\xe7\xc9\x85\x82\x84\xa3\x1f\xc0\x83\xe8\xdd\xeb\x71\x26\x10\x98\x67\xa2\xad\x90\xc1\x0b\x77\xb1\xd1\xf4\x2e\x1e\x97\xd1\x01\xf3\x79\x45\xaf\x5a\xd2\x45\x57\x7e\x71\x37\xa3\xa1\xcf\x0c\x06\x90\xbd\xef\x8b\x4b\x26\x2a\xf7\x2f\x9b\xd2\x3a\x0c\x84\x1e\x3b\x00\x2c\x77\x82\xd3\x6f\xdc\xb3\xf6\xca\xd9\xda\x1a\x65\x43\x6b\xa2\xb5\x35\x96\x37\xa2\xae\x6e\xe8\x88\xc5\x75\xab\xee\xbe\x67\xcd\xb5\xd3\x26\xd5\xb7\x94\xb4\x37\x97\xe5\x0e\xaf\xab\x1f\xda\xb1\xa8\x66\xf5\x7d\xb0\xaf\xe0\x95\xd5\xfb\x3f\x05\xf2\x7f\xde\x75\xc9\xd3\xf1\x50\xee\xd2\x3b\xca\x6f\x3e\x72\x3b\xfa\xe2\x4e\x89\x05\x7d\xbd\x7a\xfb\x74\xc3\x50\x75\x5d\x43\x3c\xd6\x98\xd3\xd8\xd1\xd1\x98\x73\xed\x8a\x55\xdb\xa7\x2e\xa8\xad\x8f\x96\x0d\x12\x13\xb6\x9d\x6f\x7f\x20\x62\x6f\x12\xab\x9a\x04\xe1\x3f\xce\x37\x1a\xf0\x67\xe1\x57\x89\x98\x13\x20\x11\x2c\x49\x84\x24\x5a\x2a\x0b\x1f\xbd\x21\x4e\x9f\x15\x17\x7c\xcb\xb2\x66\x3c\x01\x73\x26\x03\x7c\xed\x97\xaa\xff\xb0\x17\x6d\xbe\xff\xf9\x8e\xfb\x3a\x9e\x3f\xf3\xcd\xf3\x0e\xc7\xf3\x9d\xb0\x1e\xac\x15\x13\x5e\x4b\xbb\x8a\xa5\x67\x3c\xdf\xd9\xf9\xbc\x43\x42\x5d\x44\x53\x58\xdd\x49\x2a\xe1\xaa\xa4\xc2\xfd\x68\x73\xea\x39\x21\x01\x04\x3f\x16\x2b\x4b\x9f\xbf\x5f\xbc\x9c\xb0\x5f\x93\x25\x39\xc1\xfe\x85\xa0\x40\x80\x73\x0a\x4e\x7a\xa2\xcc\x4f\x11\x7c\x82\xac\x6a\xb2\xe5\x1f\x8a\x99\x18\xbd\xe4\xc4\x95\xff\x44\xbd\xa8\x07\xf5\xfe\xf3\xca\xe7\x41\xfb\xd1\x0f\xd0\x07\x69\xbf\xb6\xb3\xd0\x07\x1f\x1c\x05\xed\xcf\xc3\xe4\xc3\x24\xf3\xca\x7f\x82\xda\x87\xff\x04\x96\x7e\xed\x3e\x99\x8f\x7a\xfe\xb1\x51\x74\x63\xbb\xf1\x1f\xa0\x2b\xff\xa4\xfb\x6b\xb4\x8d\xe8\x84\xf3\x78\x3e\xfb\x37\x6e\xc3\xe9\xb8\xa7\xc7\xf5\x89\x48\x31\x1e\x85\x8c\xa0\x4c\x22\x18\xb0\x03\x62\xe6\x4e\x36\x35\x13\xc4\x7c\x23\x2e\x68\x03\x11\x82\x91\x64\x0a\x01\xb5\x60\x15\x2f\x1a\xbb\x17\x30\x98\xeb\x89\x9a\x8a\x5d\x52\xb3\x3e\xad\x5b\xce\x4b\xff\xfa\x12\x0b\xa4\xe1\xda\x52\x0f\x3b\x74\x48\x64\x4e\x6b\xb5\x56\x1b\x72\x68\xec\x2a\xb5\x3c\x3b\x3f\x47\xad\x9a\x13\x6a\x33\xf0\x20\x64\x34\xdc\xde\xe3\x09\xd1\x8c\x69\xb8\xc3\x31\x3b\xaf\x83\xe7\xdd\x5e\x43\xa1\x67\xfc\x88\xc1\x26\x63\xe5\x50\x0b\x93\x95\x53\x9c\xad\x56\xa9\x39\x79\x38\x7f\x78\x71\x63\x6e\x91\x83\x07\xf4\x87\xe8\x92\xb3\x87\xd1\xa1\xcf\xb7\xc0\x5d\xc7\xc1\x6a\x3c\x42\xa4\xd1\x59\x2b\xf6\xec\x3c\x30\x38\x12\xd2\xba\x75\xda\xe8\xa6\x25\x33\x5c\x4e\x6b\xb1\xc7\x26\x91\x2c\xd5\x35\xd9\xec\x45\x8b\xb2\xdc\x4f\x3e\x5e\xb0\xd8\xeb\x09\x0c\xd6\xe9\x96\xaa\x87\x38\x9d\xa5\xb7\x1c\xae\xcd\x77\x1b\x3c\x3a\x6d\x6c\xed\x8a\xb5\xdd\xb3\x47\x56\xe9\x74\x2a\xda\xe9\xad\x8f\xb4\x37\xcf\x9a\xb3\x71\x30\x4a\xa1\x19\xff\xb8\xf1\x67\xd0\x21\xd2\x3d\x42\x5f\x53\x62\x3e\x37\x4c\xb5\x53\x93\xa8\x05\xd4\x2a\xea\x4a\xea\x26\xe2\x6f\x23\xe8\x27\x9e\x13\xf0\x7f\xcc\xd4\x71\xf8\x18\xd4\x26\xcc\x12\x8e\xa8\x5d\x13\x2b\x46\x2e\x16\x4f\x84\xe2\x09\x73\x9c\xe6\x88\x21\x97\x84\xa8\xee\x98\x71\x17\x4c\x04\x43\x44\x6b\x9b\x74\x4b\x92\x8b\x8f\x11\x7c\x01\x7c\x19\x3c\x51\xa6\x8b\x85\xe2\x7e\x4a\x8b\x8f\xa2\xee\x25\xae\x90\x20\x55\x84\x5a\xa4\x2b\x50\x03\x8c\x61\x18\xd1\x38\xe6\x3c\x35\x78\x7a\xde\xdb\xe8\xb6\x79\xe5\x00\x00\x40\xff\xbf\xce\xbc\xba\x1b\xdf\xd7\xd5\xa5\xfe\x36\xd2\x64\x2f\x9b\x36\xad\xcc\xc5\x77\xf8\x58\x69\xf9\x3c\x74\xdb\xdb\xa5\x75\xba\xf7\x6f\xac\xcb\x5b\xfd\xa9\x5a\xfd\x2f\x77\xc3\xe1\xb2\xce\xa2\x92\x89\x25\x45\x9d\x65\x87\x1b\xdc\xff\x52\xab\x3f\xf5\xd4\x1f\xae\x18\x57\x94\xb7\x20\xaf\x68\x5c\xc5\xe1\x7a\x94\x53\x57\x4a\x8a\x07\x7d\x65\xf3\x40\x17\xa3\x9d\x56\x66\x37\x8d\xf4\xfb\x3a\x78\x57\x99\xa9\xcc\x17\x24\x37\x29\xad\x7b\x07\x74\x01\xd5\xd6\x93\xe8\x45\x74\x00\xbd\x78\x72\xeb\xd6\x93\xa0\x12\x74\x82\xca\x93\x8f\x5d\x64\x80\xcc\xaa\x97\xbc\x75\xd0\x5b\x1c\x29\xbb\x27\x6f\x8c\x12\xea\x1c\x95\x25\x9e\x43\xe0\xe6\x43\x9e\xd2\x52\xc7\x8c\xee\x85\xe8\x5f\xde\x83\x6f\x49\xea\x81\x72\x4c\xde\x3d\x65\x11\x38\xa1\x3d\x67\x4c\x4e\xfb\xc4\xd6\x3b\x1a\xf4\xdf\xc8\xe5\xdf\xe8\x1b\xee\x68\x9d\x28\x24\x4d\x6a\xb9\xa3\x51\xff\xb5\x5c\xfe\xb5\xbe\xf1\x8e\x16\x18\xac\x87\x8a\x31\x39\xf7\x96\xe6\x94\x7a\x0e\xbe\x95\xba\x1f\xcd\x3a\xe4\x29\xa9\x74\xcc\x5e\xd8\x3d\xc3\x51\x5a\xea\x09\x7a\x70\xc6\xbd\x39\x63\x14\x10\xdf\x1a\xaf\x9d\xe4\xc9\xb6\x0e\x7c\x5a\xb8\xef\x62\xda\xf9\xe7\x64\x59\x1c\xa5\xc5\x54\xdf\x20\x6a\x2e\xb5\x94\x68\x37\x06\x0c\x44\x4a\x1c\x8d\xd0\xe9\xb3\x29\x11\x93\xf8\x32\x6a\xf7\x46\x82\xfe\x4f\x0e\x04\x5e\x84\xb0\x1d\x64\x1a\x16\x38\x90\x50\x9c\x8f\x0a\xab\x86\x8f\xd0\x37\x6c\x4c\xc4\x8d\x8f\x98\xa2\x31\x1f\x49\x23\x6e\x05\xc8\xf4\x1b\x35\xfa\x70\x65\x5a\x10\x1e\x89\x82\x98\xf8\x85\x2e\x50\x61\xd3\xa4\xf9\xd3\x66\xf9\x9b\x5b\x5b\xfd\xc1\x03\x6d\x65\x91\xca\x31\xcb\x2b\xf2\x82\xd9\x8b\xc3\x8d\x2d\xb9\x27\xba\xda\xec\xc5\xc5\xad\x9d\xf2\xc0\xe0\x2b\x21\xbc\x92\x06\xa7\x5d\x78\x9a\x97\xf9\x64\x73\xe9\x6b\x98\x4a\x3f\xa0\xb5\x98\x7b\xd3\xbb\x4b\x83\xb5\xe8\xd5\xa2\x21\xc5\x91\xa6\x62\x38\x63\xa0\x48\xec\x64\x7d\x4d\x2d\xd8\x39\x7a\x54\x67\x34\x70\x99\xd3\xb9\x64\x4c\x64\x8e\x86\xd6\x35\xc6\x2c\x74\x60\x56\x7e\x83\x4f\x7b\xa4\xa1\x56\xcd\xba\x2d\x79\x52\xcd\x25\xc3\x2d\x0e\x19\x9a\x6a\x4f\x80\x4d\x05\x66\x73\x11\x5a\x19\x91\xad\x32\x76\x7c\x0c\x97\x75\x18\x2c\xee\xc2\x65\x34\x80\xc7\x03\xf1\x8a\xa0\x05\xbe\xe7\x4f\xc4\x03\xfe\x58\x7c\xe4\x05\x18\xaf\x12\xaa\x11\xcf\x43\x47\x04\x0c\x6c\xad\xb0\x87\xb9\x80\x5a\x41\xbc\x7a\xf8\xbc\xc4\xbf\x02\x4d\x56\x24\x12\x20\x23\x43\xf0\xa4\x2e\x20\xb3\xb0\x46\xad\xc7\x2b\xa8\x26\xc7\x08\xf3\x10\x4b\xcb\xf1\xcd\x11\xe0\x23\x5a\xf5\xa1\x28\x51\xb5\x0f\x18\x05\x54\xab\x98\x2e\x1a\xf3\x0a\x88\xfd\x04\x9e\x1f\xe7\x44\x8d\xc4\x55\x98\xce\x90\xd6\xfc\x16\xd7\x3f\x38\xf2\xae\xdb\x0e\xee\xae\xa8\xac\x58\xbb\x76\x05\x50\xf9\x73\xb5\x3b\xd6\x86\x43\xf9\x83\xc7\x8c\x19\x9c\x8f\x76\x0e\x5a\x7d\x49\xdd\x13\x0d\x35\x43\xa6\x3c\x77\x4d\x57\xc7\x34\xf0\xc4\x87\x0c\xf3\x21\x03\x27\x0d\x9e\x5d\xdd\x19\x71\x4a\x21\x67\x91\x18\x83\x5d\x92\xbf\x4b\xee\xd7\x94\xa9\x47\x8f\xad\x4a\x7d\xdd\x56\x56\xde\x3e\xbc\xa2\xdc\x34\x63\xce\x4c\x7a\x62\x55\xc7\xf5\x5b\xc1\x9b\xaf\x29\xe5\xb9\xd9\xeb\x1f\x33\x4b\x83\x21\x77\xb6\xd9\xe8\xca\x1f\x59\x86\xde\xb6\x96\xcd\x6f\xbe\xab\x92\xc9\x1e\xbd\xd0\xc1\x58\xee\x1d\x71\xf5\xe1\xc2\xbe\xe7\xf2\xc7\xc3\xa9\x93\xbd\x9e\x09\xa9\x5b\xc6\x3f\xf2\x62\x28\x5c\xd9\x35\xae\x02\x4c\x61\xa0\xe4\xb9\x96\xb8\x2f\x7b\xed\x73\x0c\xba\x61\x13\xa3\xbe\x74\xec\xd8\xf2\x8a\x71\xd4\x2f\xfc\x52\xcb\x80\x8f\xc6\x93\x07\xed\x03\xba\xe8\x2f\xec\x3d\xb2\x81\xbc\xfb\x56\x8b\x21\xe7\x96\x95\x80\x9b\x09\xff\x72\x9e\x52\xba\x01\x7c\x87\xbb\x42\xde\x44\x50\x8a\x78\x74\x84\xbe\xea\x7c\xdf\xb3\x65\x67\x29\xe6\x15\xfc\x8d\x9c\x02\x56\x90\x08\x0e\xc6\x41\x22\x01\x23\xdb\x5e\x41\x11\xb9\x91\x98\xa4\x10\x0b\x71\x01\x1b\x46\x80\x9d\x24\xda\xbb\x22\xb0\x10\xd9\x64\x16\xc0\x8f\x89\x62\x05\x26\x42\xe8\xe6\x25\xc3\x2b\xa3\xd5\xb1\x9f\xf2\x81\xdd\xc8\xe2\x61\xa2\x36\x06\x9b\x1a\xc3\x55\x83\xb5\x8b\x7b\xc0\xbf\xf7\xa2\xef\x6e\xab\x6d\x30\x9a\x59\xd6\x6f\x8c\x96\x4d\x7d\x34\xd9\xd2\x92\x7c\xf4\x79\x7c\x2a\x91\xab\x82\xd9\xf2\xda\x49\x7b\xff\xba\xfc\x36\xa0\x62\x0c\x3d\x8b\x7d\x0d\xc3\xd1\x36\x64\x31\x79\xa0\xdd\xb0\xee\xbb\xdf\x3d\xbe\xb1\xb2\x73\x98\x2f\xa7\x7d\x71\x01\x1e\xd8\xdf\xef\x55\xb3\x01\x7c\x67\x46\x95\xae\x8e\x4f\x53\x97\xcc\x31\x84\x0d\x6a\x7e\xcd\xf6\x15\x7f\xdd\x3b\x71\x2f\x5e\x07\xf5\xe9\x75\x90\x20\x35\xa7\x15\x65\x13\x04\x5a\x84\x58\x6e\x4b\xdc\x44\x6b\x9d\x8c\x63\x60\x4c\x53\x55\x04\x85\xd2\xc7\x11\x78\x4d\xb3\x88\xd6\x94\x76\x29\x23\x28\xda\xe2\xde\x26\x3a\x96\x21\xfb\xe9\x02\x50\x0c\x11\x55\x88\x8d\x14\xd3\x02\xb5\xd4\xa4\x02\x3a\xf5\xe1\xcb\xae\x3e\xbc\x65\x4b\x71\x47\x65\xc4\xeb\x36\x28\x41\x42\x4f\x33\xad\x63\x43\x7e\x99\x51\x67\x54\x68\x01\x26\xb2\x2a\x86\x1a\x46\x26\xa4\x90\x61\x6b\xff\x1d\x5b\x3a\xa2\x56\x23\x55\xd7\x4a\xb3\x1f\xe8\xf0\x35\x2e\x1f\x55\x67\x70\x2b\x2a\x0c\x8c\x1c\xc2\xa2\x95\x2a\x96\x91\xea\x87\x66\x03\x86\xa1\xcd\xf0\x3d\xde\x63\x28\xd7\x9a\xaa\x95\x57\x83\xdc\xca\xfa\x84\x31\x5e\xde\xd6\x34\xbd\xbd\x9c\x1d\xd9\xa0\x2e\x51\x02\x96\x05\x4b\xfe\xb0\x20\x77\x89\xc6\x90\x65\x74\x43\xc0\xdc\x3c\xc8\x10\x28\xc8\x61\x2c\x92\xa9\x7a\x13\xcf\x42\x06\x80\xfc\x30\xad\xb1\xc5\x03\xe1\x90\x13\x9a\x00\x84\x90\x56\x3c\x5b\x4d\x1b\xb2\x1b\x18\x19\x88\x17\x00\x3e\x43\x77\x55\x63\x3a\xf3\x79\x01\x27\xdc\x83\x69\xe4\xa1\x02\x86\xec\x39\xa2\x7d\xa0\xa8\x1b\x5e\x3c\x19\xe0\x20\x43\xfa\x83\x30\x38\x43\x5c\xc2\x4f\x50\x45\x08\xb2\x1c\xd1\x5e\x31\x8b\xa0\x73\x5a\x81\x52\x35\xc1\xc6\x48\x76\x6e\x7d\x7d\x6e\x36\x6d\x8d\x86\xed\xf9\xf9\xf6\x70\xf4\x8b\x62\x31\x05\x1e\x2c\x09\x91\x94\x50\x09\xfa\xd1\x1d\xba\x17\x9d\xbc\xd3\xec\xf3\xd8\x8a\xaa\xed\x1d\xb2\xd4\x10\xf4\xe1\x0b\xa0\xf5\xa5\x87\x41\xd9\x31\xb8\xe8\xca\x65\x89\x57\x76\x35\x92\x02\x77\x02\xc7\xbd\xb7\x03\xc7\xfd\x8c\xbc\x23\x12\x0d\x87\xa2\x68\x8a\x23\x2f\xdf\xee\xc8\xcf\x03\x5f\x5d\x98\x70\x1f\x73\x33\x3a\xb5\xb7\xad\x99\xa6\xe5\x8c\x0e\xae\x7f\xef\x75\xe0\xbe\x17\x38\xee\xdc\xfc\x69\xaa\x66\xd9\x9f\xc6\x3e\xbe\x30\xb0\xed\x5b\xe0\xfa\x76\xdb\xb6\xef\x44\xfc\x12\xc9\x59\xdc\x34\xae\xb4\xaf\x61\x81\x67\x0d\xd0\x22\x44\x52\x0c\xf3\x0c\x04\x39\x4b\xc0\x76\x90\x9c\xf4\x48\xce\x52\xac\x5d\xad\x53\xa8\x50\xc5\xb7\x7a\xb7\x4a\xc6\x9b\xe9\xae\x33\xc7\xd0\xb2\x00\x0d\xbd\x92\xa4\x06\xaf\x08\x3f\x58\xc2\xa7\x29\xa7\x56\xca\x1e\x46\xc7\xcd\x0c\xe7\x31\x80\x49\x8c\xaf\x6f\xfa\x1d\xea\xec\x30\x4f\xf7\xca\xce\xe1\x25\x9c\x65\x7f\xc2\x9c\x68\xd6\x79\x77\x05\x99\xbb\xa6\xef\x09\x78\xc0\xca\xc0\xc0\xfb\xa6\xbe\x41\x7f\xd6\x3b\xd5\x32\xde\x84\xc2\x01\x9a\xf6\x49\x92\x3e\xf4\xfa\x07\xa7\x67\x81\x76\x7a\x0a\xf2\x9e\xbb\xfb\x5f\xd0\x61\xa3\x70\xf7\x17\x7f\xaf\xce\x0e\x19\xe8\x5e\xe3\x69\x35\x9b\xdb\xf7\xd2\x95\x70\x7d\xdf\xdf\xcf\x9b\x77\x4a\x84\x39\x81\xd0\x1f\xf8\xcb\x89\xbc\x6c\xd4\x94\x56\xdd\x17\x34\xfa\xf1\x57\x35\x71\x99\x99\x48\x80\x0b\x16\x3e\x2e\x7b\xbe\x43\x5b\xd1\x7c\x5f\x42\xad\x3e\x8a\x4e\xee\x3d\x88\x5e\x5b\xc8\x01\xe9\x95\x72\x8d\x96\x1b\xfa\xee\x8a\x39\xcf\x5e\x35\x62\xc4\x55\xcf\xce\x99\x76\xa8\xe9\x4a\xe2\x8e\x1a\xd5\xda\x82\xe1\x90\x6b\xe3\x7c\xc0\xdf\xb0\x17\x38\x8e\xa6\x4e\x67\x94\xf7\x4e\x08\x4a\x68\xb4\x03\xbd\x4a\xb0\xb9\xae\xdf\x2c\xb7\x4a\xaf\x92\x41\xf9\x94\x39\xb8\xfa\xdb\xf8\x2a\x83\xeb\xaf\x72\x85\xc2\x44\x97\x90\x78\xe6\xde\x30\x73\xd1\xea\xa3\x7b\x50\xbf\x36\x5f\x57\x46\x7f\xed\x9c\xfe\x8a\x9d\xf0\x15\x6a\xa8\x15\xe8\x70\x6d\x01\x38\xcf\x9a\x6c\x23\xea\x13\x29\x6b\x81\x04\x9f\x75\x3f\xb8\xfe\x02\xc1\x21\x4b\xe1\xcc\x81\x85\xd0\x93\xbf\x90\x0d\x56\xe3\x7b\x3d\x8f\xef\xb5\x05\xd3\x93\x69\xed\x33\x61\x96\xc4\x33\x08\x11\xd3\x09\x60\x84\x46\xda\x60\x76\xd1\x69\xae\x6e\x60\x89\x10\x6e\x37\x82\x3c\x0c\x32\x6e\x9f\xf0\x08\x13\xb8\x37\xa2\x75\x6e\xe4\x89\x68\xcf\x43\xe6\x22\xbe\x24\x54\x00\x2f\x5e\x42\xb8\xae\x64\x47\xde\x23\xf9\x79\x0f\xe7\x59\x6c\xde\xbc\x72\xad\x07\x00\x55\x20\x35\x29\xa8\x02\x20\xa0\xad\x8d\x84\xad\x96\xc2\xc3\x05\xb9\xf7\xe5\x98\xad\xee\xec\xb8\xc6\x43\xb0\x2f\x59\xa9\x5a\xa6\xa9\x2c\xf0\x5b\x2c\x05\x87\x0b\x72\xee\xcd\xb1\x5a\xbd\xb9\xa5\x1a\x1f\xae\x68\x83\xcf\x58\x71\x45\x9f\x7e\x44\xd4\x6a\xc5\x97\xcc\x3d\x98\x6b\xb5\xfa\xf2\xcb\x71\xa6\x57\x5b\x59\xe8\xb7\x24\x39\x2e\xdb\xea\x76\x31\x72\xb9\x71\x05\xd8\x6a\x94\x33\x8c\xdc\x88\xb6\x6d\x37\xc9\x25\xc0\xe9\xb6\xe5\x71\x5c\x8e\xc5\xe5\x62\xe5\x72\xf3\xca\x32\x3a\x9f\x2e\xb0\x47\xbc\x21\x8b\x44\xce\x38\x84\xbc\x3c\x9b\xcb\x0e\x25\x72\xe3\xd5\xa8\xd7\xa8\xa0\x69\x85\x11\xd4\x5e\x8d\x03\xe6\x60\x3a\xd3\x01\x58\xb9\xf9\xaa\xbe\x11\x2b\x8c\x72\x0e\x3a\x5d\xb6\x3c\x01\x63\xc8\x72\x36\xc9\x20\xdc\xc6\x79\x69\xfc\x08\xc1\xfc\xe4\x9c\x82\xb6\xaf\x3f\x44\x94\xef\x45\x3b\xe1\x78\x36\xc1\xbb\x40\x01\x4b\x84\xb1\x49\x68\xbf\x75\x81\xd5\x7f\xad\xcf\xb6\xc0\xe6\xbb\x61\xda\xba\xfa\xda\x71\xe3\x56\x2d\x02\x11\xf0\x91\xd5\xcf\x36\x0c\x75\xd6\x02\x89\x55\x11\x3b\x93\xb4\xfa\xfd\x56\xe6\xf9\x33\xd5\xe4\x0c\xbe\x56\x16\x96\xaf\x5a\xb6\xfd\xc0\xca\xe5\xd9\x01\xbf\xc0\x47\x90\x3e\x45\x0d\xf0\x3b\x42\x34\x88\x1b\xa8\xc1\x98\xda\x31\x7a\x62\x81\x5f\x68\x0a\x7b\x62\xbc\xd1\x17\x23\x67\xfa\xc2\xbc\x0b\xf7\xca\x70\x39\xe2\xa6\x12\x74\xa1\x1e\x28\xb8\xd7\x4a\xe3\xba\xf5\xf4\xf5\x9c\x38\x21\xa1\x52\x59\x27\xce\x25\xd2\xc9\x73\x61\x58\x7b\xe2\x44\x5f\x0f\xd9\x21\x1d\x00\x22\x17\x04\x38\x0e\xa9\x64\xb2\x0f\xff\x98\xf3\x72\x10\x35\x30\x96\x2e\x26\xca\xb7\xd3\xbe\xe9\x89\x36\x05\xf1\x1e\x82\xdb\x90\xe0\xec\xe1\x99\x1c\xaf\xa3\x01\xd2\x39\xb3\x70\x3a\x9e\x9d\x58\xcc\x09\xb1\x71\xa6\x77\xcb\x33\xcf\xa0\x1f\x9f\x81\x68\xcf\xc4\x75\x38\xb8\x65\xdd\x44\x30\x07\x12\xb8\x37\x12\x44\x7b\x20\x04\x73\x26\x42\x8a\x14\x79\x66\x8b\xd2\x74\x68\x0c\xc9\x1a\x73\xc8\xa4\x14\xab\xe1\x90\x05\x27\x9e\x37\x56\x03\x54\x8c\xa2\xfc\xa2\x0d\x6c\x1c\xb3\x4c\xa6\xa8\xb8\x95\x8c\x97\x1a\x2e\xe3\x1c\x2f\x21\x18\xc4\xfe\xc2\x94\x8f\xa5\x2e\x1b\x37\xaa\xea\x1b\x08\xbf\xa9\x1a\x35\xee\xb2\xcb\x1e\x5e\x07\xbf\xa9\x1e\x89\x03\xe3\x46\x56\x7f\x03\xd7\x3d\x0c\x2e\x1b\x48\x2a\xa5\x1e\x5e\x57\xbe\x52\xab\xd6\xae\x2c\x5f\xf7\x30\x2e\xc2\x69\x57\x96\x5d\xf6\xf0\x65\x65\x2b\xb5\xdc\xb8\xcb\xe8\x13\x03\xe9\x26\xae\x9f\x77\xd4\xe1\x6f\x5d\x4d\xb5\x50\xe3\xa8\x19\x98\x7b\xa0\x28\x61\xdb\x57\xd8\xe1\x15\x04\x13\x89\x38\x30\x13\x9c\x3d\x8d\x80\x80\x70\x8e\x91\x8b\x12\x5c\xf5\x88\x1b\xf0\xc2\xe6\x71\x5a\x6b\xd6\x84\x97\xce\x81\xb1\xb8\xd8\x77\x85\xf9\x33\x94\x56\x5d\x11\xa4\xea\x22\xb6\x4b\x89\x08\x8d\x66\x80\x83\x0c\x45\xd6\x05\x07\xf2\xe4\x06\xab\x4a\x91\xa3\xf7\x6e\x18\x65\xa5\x9f\x2a\xf8\xbe\x91\xe7\x6b\xc7\x13\xdc\x54\xf4\x37\x02\xcb\x2a\xc0\xa9\x3e\x71\x7b\x2d\x1f\xe3\x1b\xcf\xc8\x95\x2a\xf9\x04\x99\x4c\x6e\x93\x77\xca\xdf\x57\x58\x14\x9d\x72\xb9\xcc\x2e\x9b\x20\xcb\xd2\xab\x05\xe0\x93\x2e\xf5\x83\x7a\x87\x1e\xff\xdf\x3d\x81\x14\x95\xe3\x62\x36\xb9\x8c\xbe\x39\x62\x90\xe7\x1d\x58\x60\x2d\x92\xb3\xe1\x51\x1b\xbc\x0a\xf0\x40\xc1\x77\x8d\xf8\x82\xb5\xb7\x3f\x71\x6d\xe6\x1e\xc0\x45\x70\x5f\xc7\xd7\xf2\x7c\x23\xc8\x4b\x57\xc4\x57\xb6\x7f\x25\x1c\x65\x42\xca\x33\xc2\xb5\x7b\xd2\xb7\xd2\xeb\x07\x65\xee\x8f\x9f\x28\x8d\x4b\x40\xda\x96\xa1\x0c\xe4\xcb\x83\x00\x4b\x7b\xe0\x05\x5b\x40\x20\x4e\xcc\x80\x79\x73\x30\x64\x66\x03\x09\x09\x97\xe0\x89\x51\xb0\x39\xc1\xf2\x9c\x29\x92\x08\xf1\x01\x38\x15\xb8\x81\x7b\x21\xba\x95\xfd\xe5\x1e\x10\xb3\x70\xe7\xac\xaf\x6b\x2e\xdf\xf5\x55\x0c\x7d\x8c\x3e\x8e\x7d\xb5\x6b\x6b\xf5\xd7\xb3\x76\xba\x40\xd3\xd5\x97\x2e\xfb\x71\xd9\xa5\x57\x83\x26\xf8\xf6\xdb\x6f\xa3\x87\x99\xe4\x45\x18\xdc\x33\x43\x5e\x3f\x43\x8f\x3f\x01\x1a\x94\x47\x5b\xd6\xee\xdb\xb7\xb6\xe5\xa8\x12\x3d\x7b\x62\x3c\x7d\xe6\xf5\xcd\x61\xf4\xe7\x41\xa1\xd0\x20\x90\x13\xa6\x04\xdf\x75\x69\xff\xd0\x19\x9b\x82\xa1\x82\xd7\x10\xb2\xc3\x70\x07\xf5\x28\x75\x84\xcc\x0e\x19\xcf\xd5\x69\x57\xee\x17\xc4\xc1\xaf\xe4\x07\x32\x4a\x4d\xbe\x5f\x2b\xf9\xeb\xf9\x9e\x58\x09\xcb\x08\xc0\x0e\xd5\x0c\x5e\x01\x5d\x8c\xee\x82\x22\xba\x7e\xc7\xa1\x40\xf4\x12\x29\xba\x8a\x3c\x17\x84\xb5\x17\x4d\x4e\x3d\xef\x08\x42\x18\xb4\xc3\xb3\xff\x4d\x2d\x90\x4c\x21\xb4\x11\x6d\x4c\x21\x5d\xb4\x7d\xdb\x63\x40\x05\xaa\x81\xf2\xd0\xb6\xf6\xa8\xee\x5c\x99\xa0\x1d\x25\xed\xc1\x13\xfd\x3a\xf0\x03\xbc\x8b\xa2\x25\x17\x4b\xdd\x11\xb4\x6f\xd8\x60\x0f\xa6\xfe\x8b\x2a\xe0\x2a\x95\x7c\x0e\x04\x33\xe5\x2a\x5d\x49\xcb\xb0\xd6\xf2\x40\xa0\xbc\x75\x58\x4b\x09\x1a\x7b\xae\xc4\x28\x7c\x49\x7c\xe1\x7e\xb9\x5f\x1a\x17\xc1\x20\x68\xef\x94\xa5\x71\xc0\xfa\xe7\x25\x9e\x20\x1a\x11\x41\x5f\x26\x41\x10\x25\x44\xcc\xa0\x1f\xda\x8d\xed\x0f\xc1\xde\xa0\x2d\x68\x43\x78\x42\x3e\xc5\x59\xe0\xbf\x08\xbc\xad\x18\xc5\x33\xf9\x3d\x16\xae\xef\x38\x81\x3a\x02\x59\x04\xec\x37\x13\x62\x7a\x53\x38\x3f\x25\x2c\x15\x90\xa2\xe7\x9a\x53\xb5\xb0\xb7\x2f\x89\xd2\x8b\x02\x5e\x24\x28\x33\x48\xa4\xdd\x9d\x93\xa3\x48\xe7\x0a\xcf\xec\x24\x14\xa7\x81\x23\xda\x42\x4c\x08\xe0\x05\x2a\xa8\xaf\x01\x66\x40\x04\x91\x9c\x70\x96\xfc\x4f\x20\x80\x16\xed\xea\xb9\x13\x55\x1c\x46\xbb\x1e\x07\xf3\xd6\x16\xde\xd9\xb3\x0b\x5c\x17\x9c\xd7\x1c\x40\xdd\x9f\x81\xeb\x83\xf3\x98\x8a\xe0\xdc\x20\xea\xc6\x65\x0a\xd7\x0a\x45\x0e\x83\x97\x48\x99\xeb\x03\xcd\xf3\x71\xdd\xcf\xc0\x75\x01\x41\xf6\x6f\x3d\xab\x94\xfc\x53\xf0\xdb\x67\xa4\xca\x05\xaf\x44\x03\x51\x10\x2e\xe2\xeb\xd2\xc5\x62\xea\x26\x2e\xc0\x7b\xc6\xcd\x11\x17\xac\x66\xf1\xa8\xd7\x8b\xd6\x77\x09\x5a\x10\xfb\xa7\xfd\x25\xf0\x82\xf3\x05\x17\x30\xa7\xd7\x00\xa3\x2e\x11\x37\xd1\x73\xd7\x3f\xba\x1e\xff\x07\x3f\xae\xeb\x1c\xbf\x7e\xfd\xf8\xce\x75\x1f\xd7\x0e\x3f\x73\xcf\xc8\x8a\xdc\x09\x83\x27\x44\xc7\x3b\x46\xc3\x46\xbb\x84\xb1\xf9\xb8\x45\x6c\x8d\xb9\x31\x38\x38\x3a\xb4\xaa\xf9\xe5\x55\x67\x46\xcd\xaf\x5f\x36\xa7\x6d\x0c\x03\xa4\x1e\x0e\x30\x63\x87\xcf\x59\x56\x37\x77\xe4\x99\x55\xd6\x9c\x10\xa3\xa1\x27\x37\x30\x9f\x36\x4c\x36\x86\x72\x68\xc7\xc8\x15\x2b\x46\x8e\x5a\xbe\x7c\x54\xfa\x8c\x7e\x86\xb7\x8c\x1d\xda\x38\x31\x35\xc5\xec\x35\x69\x70\x4d\xe0\x90\xd0\x56\xdb\x04\x82\x9a\x4f\x4b\x14\x5a\xb3\xdb\xb2\x73\x36\xfa\xfb\xa1\xc5\xbe\xac\xc2\xe8\x62\xd0\x04\xa0\x14\xa0\x07\x97\x44\x0a\xb3\xfc\x4b\x0e\x01\xfb\xec\x9d\x81\x12\x3b\x94\xd3\xf0\x89\x21\xb3\x66\x0d\x49\x35\x6b\xec\x25\xa4\xcd\x66\xe0\xf5\x70\x6f\x5a\x4e\x4b\xf0\x24\x70\xcf\x12\xdc\x89\xe9\xf8\x04\xb1\xc1\x37\x26\x80\x0e\x78\x38\x22\x7e\xe5\xe9\xe4\xf5\xd0\x7d\xfd\xf5\xa9\x33\x63\x40\xd3\x71\x4c\x34\xb7\xa1\xa7\x8f\x1f\x47\x4b\x16\x32\x6d\xa8\x0d\x3c\x4a\x7e\x29\x29\xa2\xed\x67\xfe\x79\xfc\x38\x73\x5f\x9f\x02\xb5\xe1\xf3\xe5\xc0\x23\xf6\xe1\xf1\x67\x01\x7b\x1f\x9b\xc2\x9c\x60\x2e\x9e\xb5\xda\xa8\x99\x64\xa6\x82\xa4\xa9\x05\x22\x4a\xe4\x82\x05\x00\xcf\x90\x44\x03\x18\xc1\xae\x31\x88\xe3\x78\x31\x22\x22\x2e\x40\x16\xc0\x50\x90\x16\xc0\x39\xd3\x7e\x1e\x08\xe6\x85\xe0\xe4\xc6\x4f\xbe\xa0\x9e\xc5\x51\x16\x4f\xda\x12\x11\x6d\x55\x50\xa9\xc1\xc5\x68\x16\xb0\xca\x50\xfc\xac\x4f\xc5\x00\x96\xa9\xdc\x0d\x2a\x34\xc5\x56\x8b\x7d\x17\x5d\xbc\x12\x7d\xa9\xf3\xf1\x4a\x56\xaa\xcf\xf1\xa9\x9e\x1d\x9c\x37\xca\x6c\xa5\xcb\xb8\x7b\xa3\x01\x9b\xfa\xbe\x42\x35\xab\xf3\x15\x81\xe5\xaf\xb7\x49\x1d\xa9\x4e\xb6\xa2\xbc\x14\x5d\x2e\xb5\x67\x83\xd6\xf2\xb0\x8c\x0e\xc2\x5b\x68\xa7\x06\xbd\xdc\x60\x01\xe6\x02\xb5\xcb\x05\x9a\x2f\x8b\xc8\x1c\x81\xa2\x5d\x92\xe3\xeb\xd1\xfb\xaa\x2c\xa9\x6c\x72\x8e\xc6\xa8\x54\xcb\x9b\x1f\x6b\xe2\x15\x32\x79\xf0\x64\x42\x13\x1a\x07\xbd\xd6\x48\xcb\xe3\x8d\xb0\xd5\xa9\xf7\xca\x72\xd1\x91\xf8\x9f\x0d\x6a\xa3\x1c\x18\x5b\x8d\x11\x63\xae\x0e\x84\xea\xed\x9c\x09\x8e\x98\x65\xd0\x8d\x83\x63\x7c\xf6\xdc\x49\x1a\xb9\x4f\x9f\xfa\xfd\xab\x21\x83\xbc\x45\x23\x85\x98\x20\x29\x0c\x83\x99\xf7\xd7\x4b\x78\x9d\xf9\x83\x32\xc1\xbe\x5f\x94\xe3\x24\xcf\xb3\x7d\xb0\x53\x3e\x4c\xb7\x12\x9f\x35\xf8\xeb\x09\x54\x9e\x4e\x80\x79\x8c\x9d\xf7\x23\x34\xac\xb0\x49\xe8\xd1\x19\xb8\xf3\x20\x1d\x3c\x31\x86\x42\x44\x92\x9f\x12\x2c\x35\x58\x0a\x61\xa2\xe9\xdc\x0f\x13\x79\xc1\x92\xa0\x24\x79\x9a\x52\xb0\xaf\x63\x9a\xae\xbb\xfd\x54\xb2\xbd\x1b\x50\xa4\xd2\x59\x4c\xdd\xd1\x94\x50\x8f\xea\x97\xc7\x0b\xbf\xbe\x5a\xba\x57\x04\x12\x66\x6a\xcf\xf4\x7a\xdc\x41\xe6\xbd\x33\x82\xae\x2a\x53\x9b\xc4\x55\x73\x28\x15\xf7\x67\x01\x6f\xc1\x8d\xe7\xb6\x11\x98\x2e\x4b\x8f\x5a\xa3\x21\xe1\xc5\xcc\x4a\xda\x8a\x26\x41\xf4\xfd\x04\x20\x30\x01\xff\xca\xe7\x25\xce\x88\x05\xf2\x1b\xaf\x2d\x42\x3a\x8f\x29\x18\x1c\x4e\xe3\x82\x9d\x4b\x67\x0c\xe1\x1d\x97\x75\x5c\x36\x07\xb6\xac\xdf\xb8\x7e\x18\xad\xdf\x2d\x6f\xfb\xe2\x1f\x5f\xb4\xc9\x77\x53\x67\x15\xca\x2b\xfe\xb5\x67\xf4\xfd\xeb\x67\x94\x43\xdd\x2e\xf9\x66\xb0\x12\x24\xc1\xca\xcd\xf2\x5d\x48\xa1\x78\x0c\xad\x47\xa5\x68\xfd\x63\x0a\x85\x6e\xb7\xfc\x19\xc8\x40\x1b\x64\x9e\x91\xef\x56\xdd\x60\xc8\xca\xcb\xcb\x32\xac\x8d\xe0\xbf\x5d\x7a\x95\xbc\x75\xdc\xb8\x56\xb9\x4a\xbf\x0b\x68\xa5\x73\xa7\xe7\x55\x57\xe7\xed\xd2\x2b\xe5\x9b\x77\xec\xd8\x2c\x57\xe2\x44\x8d\xec\xd6\x7d\xfb\x6e\x95\x91\x82\x4f\xbf\xf1\xc6\xd3\xa4\x20\xd1\x82\x13\xec\x66\x84\x7d\xcc\x81\x52\xa9\x1a\x6a\x18\x35\x92\x9a\x4e\xcd\xa7\xd6\xe0\xc1\x79\x81\x4f\x38\xea\xbf\x3c\x13\x6c\x48\x11\xd5\x2e\x12\x1f\x98\x36\x10\xeb\x4e\x3b\x40\x07\x7b\x20\x8d\x0b\x92\xc3\x88\x5e\x04\x78\x5d\x38\x21\xf1\x44\x0f\x1b\x18\xbb\x68\x22\x3d\xac\x65\x4e\x0b\xfe\x8f\x32\xf5\x33\xe6\x78\x2c\x3e\x0a\x49\xaf\xb7\x94\x9c\x16\x24\xe7\x2c\x3e\xc6\xe6\x89\xb5\xc9\x7f\xf0\xba\x70\x42\xaf\x0f\x8c\x5d\x34\x31\x95\x04\xe7\xa4\xf7\xf0\xac\x98\xd5\x2b\xc0\x52\x8b\xfc\x06\xba\x4b\x48\xa3\xa9\xd3\x14\x29\x27\x21\x47\xe2\x11\xef\x2c\xc5\x7e\x25\x21\xb8\x7a\x83\x84\x7d\x10\xe8\xf1\x11\x98\x3c\x02\x1f\x20\x18\x41\x91\x8d\xc9\x0a\x20\xb8\xbf\x11\x26\x10\xa2\x64\x21\xba\x74\x32\xf8\x42\x98\x09\xa4\x85\x26\x4a\x64\x34\xd2\x31\x51\xfa\x95\xde\x34\x16\x79\xf3\xac\x41\x96\x49\x40\x36\x64\x3d\x63\xb4\xd0\x32\x9f\xde\x2f\x63\x83\x9b\xb6\xcc\x7e\xa8\x7b\x56\xcc\xa2\x00\x34\xc3\x0c\xbf\xa9\xa0\xfd\xc3\xc5\x57\x77\x76\xce\xd0\xc3\x91\x40\x81\x8e\x9b\x9c\xf4\xbf\xd8\x7c\x27\x1c\xe3\x5d\x5f\x34\x7f\x31\xbd\x7a\xd4\x4a\xd4\xe8\xb1\xf1\xe8\x80\xc6\xe6\x71\x19\x4b\x4f\x74\x7f\x54\x1a\x80\xe6\xd0\xdc\x29\xbb\x9b\x6a\x24\x34\xa0\x2b\x1e\x9b\xbf\xe1\xd3\x8e\x30\x04\xa0\x4b\x9a\xfa\x51\xee\x31\xb1\xbf\x73\x06\x6d\x7c\xf6\x7e\x32\x87\x87\xd2\x6b\xad\x9c\xd2\xe3\x19\x3c\x4c\xb8\x2a\x33\xc5\x7b\x20\x1d\xc4\xcc\x9f\x84\x83\x74\x3c\xa1\xe7\xf5\x24\x45\x06\xb4\x34\xf1\x6f\x13\x14\x75\x0f\xf4\xe0\xb0\x87\x07\xf2\x2e\x54\xbf\xfe\x6b\xa5\xde\x40\xef\x2f\x6e\x19\xfe\x48\x98\x39\xf6\xf1\xe7\x20\xd7\x87\xaa\xb2\x11\xc5\xcc\x99\xd9\x80\xde\xb7\x8e\x60\x78\x2d\x98\x6d\xf4\xb1\x4b\xe9\x2e\x1b\xa6\x5d\x67\x81\xc3\xa0\x44\xeb\x43\xb7\xbc\xf2\x3c\x88\x03\xc7\x07\x27\xd1\x41\x70\x2d\x3a\x92\xe2\xd1\x62\x78\x13\x1d\x4a\xf5\xa2\x71\x68\x2d\x2c\x82\x0a\x90\x0f\xec\x5a\xab\xcd\x80\x66\x8b\xb2\x11\x99\x68\x37\xa2\xa1\x2c\x94\x03\xf3\x38\x82\x1f\x7a\xe0\x8b\x13\x09\x62\xc2\xcc\xd2\xb8\x6f\x72\x4c\x40\x70\x0b\xc4\x47\x01\x1d\xe5\x7d\xac\x60\x29\x42\xc0\x1d\x8c\xa2\x8a\x30\x67\x8a\x9a\x88\xba\xb7\xb8\x89\x1f\x77\x83\x00\x66\xe1\xe8\x68\x22\x6a\x32\x47\x2f\xec\xc5\xdc\x93\x57\xa9\x4b\x68\x46\x49\x2b\x4f\x6f\x2c\x57\xd4\xa2\xef\x21\x48\x00\xcd\x1d\x3a\xdb\xf2\x21\x5b\x1f\x02\x6c\xe0\xc0\x9c\x03\x70\xcf\xa0\xf6\x35\x7b\x01\xd8\x51\x14\xac\x0c\x8d\x69\x32\x99\x9b\x17\x6d\xbc\x15\x5e\x53\x9c\x57\x5c\xd0\x14\xd7\x80\xde\x64\x9d\xe9\xc7\x07\x7d\xef\xb2\x9a\x9b\x93\x2d\x25\x3f\x0b\xdd\x49\x8a\x8f\xd0\x1b\xd8\x2e\x93\x67\xc9\x13\x2b\x41\x28\xae\x1a\x3e\x11\x35\x8f\x6f\x5a\xe1\x44\x10\x6e\x48\xad\x83\x1b\xb5\xf6\xe5\x93\x67\x0d\x31\xfb\x8d\xae\x2c\x8f\xe2\x3a\x2f\x58\x39\x63\x5e\xa3\xd5\x6b\x34\x79\x80\x55\x7a\x4b\x3c\x75\xa8\xcb\xd4\x4c\x3f\x7f\x46\xb8\x18\x2b\xf4\x4d\x4b\x7f\xdb\x10\x6b\x89\x5c\x2a\x4a\xd5\x62\x4e\x7f\x1c\x9e\x09\x66\x53\x8b\xa9\xd5\xd4\x5e\xea\x29\xea\x15\xea\x13\xea\x14\x50\x00\x2b\x6e\xd3\x4a\xd0\x0c\xc6\x81\x35\xe0\x6a\xb2\x0b\x9d\x71\xce\x81\x99\xc3\x20\xd4\x27\x24\x50\x6f\x8e\xeb\x61\xc8\xa4\x87\x9c\xb0\xa7\x1e\x13\xf6\xd5\x40\x34\xe6\x33\x46\x8d\x15\x30\x46\x7c\x4b\x1b\xa3\x31\x73\x34\x41\x1b\x73\x41\xac\x02\x18\xa3\xa1\x48\x34\x11\x2f\x29\x04\xde\x5c\x1c\x89\x45\xfd\x25\xfd\x42\x7d\x7f\xc4\xec\x63\xc4\xb9\x18\xc7\xe2\xe9\x90\xd7\xec\x0d\x79\x83\x82\x34\x05\x4f\xb3\xc5\x91\x98\xa0\xda\x5a\x6c\x36\x9a\x8c\x9c\x83\xf8\x8b\xf7\x49\x02\x51\x22\xc9\xf2\x72\xa2\xf7\x63\x7c\xd5\x92\x68\xc4\x09\x84\x93\xd1\x1c\x25\x50\x4c\x19\x36\xbb\x06\xe0\x3b\x07\x49\x86\x39\x21\xee\xfc\x0a\xfb\xe8\x98\x1d\x25\xcf\x1f\x17\x36\x79\x89\xb7\x64\x1f\xbe\x0c\x79\x05\xe2\x48\x3b\x63\xe5\x45\xf2\x42\xe4\x4e\xd1\x73\x77\xc1\x57\x31\xa5\x33\x43\xa2\x49\x91\x70\xdd\x0b\x6f\x7a\x5e\x85\x74\x66\x26\x8f\xf3\xfa\xc8\x96\x0f\xd9\x0d\x30\x08\x9b\x93\x09\xc2\x18\x27\x88\x70\x35\x18\x22\xed\x14\xfc\x05\xbe\xcf\x94\xe4\x4d\xb3\x9f\xbd\x62\xc4\x88\x2b\x8e\xcc\xb9\x29\xb9\x69\xf2\x94\x3b\xd7\x4d\x9c\xb0\x7e\xfd\x84\x89\x93\x36\x4e\x99\xbc\x29\x79\xd3\x9c\x23\x24\xef\xd9\xd9\x37\xc1\x99\x9c\x8e\xa3\x9d\x0c\x2b\x91\xb0\xb4\x84\x61\xa5\x90\xa6\x09\x28\x8a\xf0\x07\x01\x1e\xec\x67\x4c\x26\x5e\x6f\x32\xe9\x79\x70\x57\x25\xdb\x04\xb6\x9a\x30\x7d\xc3\xeb\x4f\x9b\xfd\x66\xb3\x7f\x2b\xd1\x99\x24\xe5\xc8\x9e\x3b\x60\xa0\x50\x09\x82\xd3\x47\x5c\x4e\x6b\x96\x46\xed\xb6\x68\x5c\x2e\x8f\xcb\xe9\x71\x1d\x70\x3a\x75\x36\xe2\x68\xc4\xa1\x79\xb4\x50\x6d\xb6\x9a\x0d\x4a\x93\xc7\xe6\x2a\x54\x59\xdc\x56\x83\xca\xea\x71\x7a\x36\x4a\x55\x2a\xbe\xa8\xc8\xe5\x70\x14\x1a\x67\x3a\x83\x21\x97\xc7\xa4\xd6\x1b\xbd\xdc\x4c\xff\x26\xb3\xd2\xe5\x72\xca\xa5\x32\x99\x3e\xe4\x71\xf2\x6a\xbd\x4e\x6f\x36\xeb\x79\xad\xda\xe0\xf0\x1c\x75\xb9\x34\x76\x67\x28\xe4\x74\xa8\xb7\x98\x95\x4e\x27\x29\x26\x5d\xef\x74\x6a\x4a\x43\x21\x87\x53\xdd\x46\x34\x86\x21\xa1\x48\x21\x43\x33\x90\xc4\x84\x27\x24\x4f\x3d\x7b\xe0\x00\x62\xee\x1f\x8d\x9b\x6a\x36\x69\x96\xd1\xf3\x41\x15\xa8\x1c\x39\x1d\x1d\x43\xef\x4e\x9f\x0e\xf2\x40\xfe\x9a\xf9\xe8\x05\xf4\xc2\x3c\x52\x62\xce\x6c\x5c\xa2\xef\x38\x4d\xeb\x0c\x2a\x95\x41\xa3\x52\xa1\x32\x48\xcb\x59\x40\x5a\x41\xc5\xe6\x05\x2d\x56\x3d\x6f\x19\x9b\xe5\x16\x03\x56\xbf\x95\x9c\x9c\x80\x11\x9e\x02\x8a\xed\x43\x94\x6e\xc9\x33\xe0\x87\x18\x8d\xf3\x2c\x16\x83\x76\xeb\x30\xbf\x7f\x18\xf9\x35\x36\x68\x0d\xe1\xea\xb0\xc1\xe2\x95\x40\x46\xae\x51\x58\xd4\x16\x83\x87\x04\x75\x6a\xb3\xce\xa2\xb6\x72\xa6\x2a\x7b\x76\xb6\xbd\x2a\xb2\x3d\xec\xce\x0a\xf1\x26\x8d\x47\x99\x15\xc2\xf5\x5b\x7c\x8c\x83\xc1\x15\xb5\x16\x15\xb0\x04\x2d\x4a\x8b\xf6\xea\xcc\xa5\x56\x67\xb2\xaf\x6e\x5c\x3d\xd8\x90\x5d\x99\x6d\xa0\xc9\x17\x23\x2d\x02\x85\xa7\x20\x7f\xe4\x9b\x43\x41\x97\x1a\x30\x9f\x0c\x9c\x0a\x44\xff\xf4\xc2\x5c\x20\xc7\xb3\x01\xd9\xf9\xab\xa7\xc6\x52\xd3\xa8\x79\x78\x26\xb8\x8c\xba\x8a\xba\x59\xf0\x72\x48\x10\x61\x05\x87\xdf\x06\x21\xc0\x12\x43\x78\x5d\xc6\x39\x3c\x9b\x96\x21\xc7\xcf\x0d\x29\xc1\x51\xa8\x88\x71\x2d\x8c\x2a\x41\x96\x9c\x56\xf4\x89\x65\x06\x05\xd0\xa9\x81\x12\xb2\x9e\x73\xf4\x42\x40\xf0\x44\xcf\x27\xc8\xe8\x4b\xff\x40\x54\xd0\xbc\x22\xb7\x8b\xfd\x42\x6a\x08\xca\xfc\xce\x4a\x9d\xae\xca\xe1\x97\x7c\x5d\xcb\x1b\x6a\x4e\x8d\x9c\x31\x7c\xca\x94\xe6\xfc\x4a\x57\x5d\x1d\xa8\xcd\x4e\x38\x8d\x76\xa3\xd3\xe2\xcd\x2e\xcb\xab\xf4\x17\x04\xa4\xbc\xc3\x54\x64\xce\xc9\x1b\x1c\xad\x05\xa6\x40\x76\x71\x4d\x4d\x41\x6e\x30\x1c\x6e\x9e\x3d\xab\x39\x87\xf9\xa9\x6e\x1f\x7a\x11\xdd\x8b\x0c\x08\x49\x3c\xb6\x60\xdf\x03\xf3\x76\xcd\x9b\xb7\x0b\xc0\xeb\x06\x77\x8e\x1f\xbc\xfd\xed\xa7\x56\x2c\x5d\xba\xe2\x29\xb0\xb5\x7d\x6e\x4b\x75\xe9\xd4\x3a\x19\xf0\xb4\x26\x7e\x96\x26\x5a\x5b\x13\xdc\xcf\x89\x56\xf8\x53\xd4\x63\x7b\xdf\xee\x56\x95\xcc\x5c\xd2\x3c\x09\x3d\x16\x8c\x8e\x07\xad\xff\x0a\xe7\x19\xe4\x7a\xb5\xd6\x68\xcf\x0b\x24\xc2\xbe\x6c\xad\x4a\xa2\x34\x19\xec\x79\xe1\xda\xaa\xec\xd6\x40\x5d\xa4\xa8\x21\xd8\x6a\x98\xb9\x63\x66\xea\x49\xa8\x09\x8f\xdb\xb1\xe1\x9a\xa2\x20\x7c\x91\xdc\x74\x9e\x14\x8c\x39\x71\x02\xdd\x27\x2b\xed\x2c\x6d\x2e\x43\x8f\x5d\xa3\x6d\x2b\x2c\x41\x8f\x6d\x81\xfe\x33\xca\xd2\xb6\xb6\x52\xe6\x7b\x7c\x24\xe4\xb8\xbe\xff\xdb\x41\x4c\x91\xab\x31\x1f\xea\xc0\xf4\x78\x10\x73\xa3\xc3\xa9\x09\xd4\x51\xea\x6f\x78\x06\x67\x81\x0c\xf8\x41\x0d\x98\x46\x51\x7c\x34\x04\x12\x64\x32\xc6\xf3\x5a\xc0\x1c\x33\x97\x90\xe9\x37\x12\x10\x4f\x40\x3c\xb1\xd1\x10\x71\xea\xce\xf9\x42\x46\x5f\xc8\xc7\xf9\x78\xbc\xca\x45\xcd\x09\x60\x50\x33\xde\x20\x9e\x10\x43\x1c\x26\xf4\xcd\x09\x5c\xcd\xe8\xd3\x45\x8d\xe2\xc5\xfa\x8d\xb8\x74\x78\x61\x34\x0b\x73\x3d\x26\xfb\x13\x11\xb2\x17\xe3\x82\xf1\x4c\xa2\xce\x67\x0c\x91\xff\xc2\x54\x48\xd6\x5e\x21\xc6\xf5\xf3\xb8\x42\x06\xfe\x79\x8c\xf8\x73\x93\x1f\x27\xd8\x20\xe1\xba\xb8\xa7\x91\x85\x42\xc4\x49\x4f\x90\x87\x36\x48\x38\x17\x70\x62\x0e\x9f\x74\x0d\xf2\x28\x11\x41\x44\x27\xa4\x95\xc4\x0b\x68\x21\xd1\x4c\x76\x85\x06\x3c\x26\x41\x70\x13\x3b\x30\x41\xbc\x2b\x10\x51\xa5\x8d\x44\x86\x6f\x8a\xbb\x40\xc2\x28\xc9\xe4\x49\x04\x79\x44\x3a\xcf\x05\x68\x5d\xa6\x39\xbc\xb1\x12\x9c\xea\x0d\xaa\x19\x01\xfb\x22\x21\xb4\x4e\x6c\xc5\xf8\x7c\x58\xd7\xdc\x74\xe7\xf6\xed\xa0\x6a\xfa\xb3\xe1\x51\x23\xb3\x81\x27\xa7\x63\x44\x2e\xfa\x8c\x1c\xc1\xeb\xe3\xf3\xfa\x4c\xf5\x93\xcb\x26\x6f\xb6\x6e\xb5\x36\x5d\xda\x75\xc9\xbc\xd1\xad\x70\x8f\x42\xe7\xb0\x84\x2c\xd9\xb2\x75\xed\x23\xcf\x52\x80\x69\xef\x78\x6b\x21\xfa\xe0\xf8\xf1\x3d\x37\xde\xc8\xbe\x2b\xf6\xad\x45\xd6\x84\xf5\x3d\x7e\xb1\x01\x3a\xe5\x72\x60\x36\xd7\x66\x8f\x96\x59\x4b\xad\x7f\xf7\x3e\x71\xc8\x7a\xd8\x7c\x6a\x50\xf8\xa0\xa5\x38\x75\x4d\x6e\xee\xcb\xa6\x7b\xdb\xc4\x6e\xb8\x32\xea\x7a\x24\x61\x46\x2f\xba\x4b\xdf\x31\x37\x7e\x16\x8f\xa0\x3b\xc1\xd8\x44\xc9\x31\x63\x85\xfb\x41\xa9\x94\x81\xba\x32\xf7\x3d\x95\xa9\x7c\x8b\xc9\xaa\xaf\xb3\x78\x07\xd5\xdd\x5c\x54\x8e\x3e\xb7\x1a\x6d\xba\x3a\x80\x99\x56\xb3\xbe\xa9\xf6\xa6\x62\xcc\x97\xfc\xf5\xaf\xbb\x6f\xbc\x11\x7d\x59\x0f\x7f\x9a\xb5\x6e\x9d\xd7\x5b\x1c\xf1\x96\x84\x37\xae\xf0\xfb\x8a\x8b\x7d\x5f\x59\x6a\x2f\xbb\xcc\x63\x0d\xe4\x06\xac\xb1\xf0\x86\xe5\xfe\xf2\xe1\x37\x4e\x5c\xbd\xd9\x76\xb9\x75\xd8\x86\x2d\x35\x5c\x8e\xc6\xad\xd4\x49\xec\x7e\xe7\xc4\xa9\x0b\xa7\x2f\xa1\xc7\x2c\x48\x5d\x3e\x7c\x78\x71\x22\xde\x76\xc9\xf1\x4a\xcf\xa0\xb0\xb3\x0a\x7c\xeb\xac\x0c\x2e\x28\x44\xdf\xbc\x8b\xff\x2a\x2b\x81\x06\x9d\x05\xe0\xa9\xa7\x52\xef\x1a\x5c\x06\x15\x07\xc1\x84\xce\x4e\xa0\x19\x3f\xbe\xaf\x14\x68\xca\x70\xbd\xd4\x3b\x9f\x24\x86\x0f\x4f\xc0\x03\x55\x55\x05\x05\x85\x85\xd3\x81\x7a\x8c\x59\xa9\x04\xb0\xaa\xaa\xbc\x1c\xac\xce\xc3\x7f\x26\xfc\x37\x75\x6a\x5e\xde\x63\x60\x2b\x29\x99\xea\x34\xa5\xff\xca\xcb\xd1\xe5\x15\x15\xe3\x55\xb3\xa6\x33\xd2\xb1\x16\xcb\x19\x73\x58\x26\xf3\x3a\xe3\xf9\x1e\xe3\x74\xa0\x71\x81\x7b\x2c\x38\xee\x71\xc5\x64\x3e\x8d\x49\xce\x4d\x03\x1a\xe0\x4c\x5d\x8a\xef\x5a\x8a\xef\x0a\xef\x45\xdf\x00\x4d\xea\xd2\x31\xe5\x56\xad\x9c\x0b\xfa\x43\x39\x65\x56\xad\x0c\x48\x02\xea\x99\xbe\x72\xab\x4a\x09\x58\x45\xc0\x45\x12\x0d\x8c\x04\xd6\xa3\x6f\x5f\x7f\xbd\xb2\x72\xcb\x55\x15\x78\x76\x95\xeb\x9c\x7c\x30\xfc\x27\xfc\x35\xa9\x23\x47\xc8\xf8\x54\xf4\x8f\x4f\x05\xe6\xba\x7c\x78\x5c\x8e\xa4\x2e\xa1\xb6\x50\xfb\xa8\x07\xa9\xc3\xd4\x1f\xd2\xde\xa8\xd2\xfb\x44\xb8\x4b\xfb\x38\xc2\x11\x10\xc4\x87\x81\xe9\x02\xe8\x08\x47\x4b\x08\xe6\x08\xd1\x67\x13\xa4\x64\x2c\x1f\x17\x92\x07\x58\x6f\xe3\x33\x2e\x41\x09\xc5\x35\x20\x24\x40\x95\x90\xde\x6b\x16\x33\x12\xe0\x37\x5f\xc9\x20\xd6\xe0\x63\x25\x42\x79\x4e\x80\x3b\x49\x10\xd3\x70\xf1\x01\x4d\x17\xce\xc3\xf0\xd3\x68\xc0\xe9\x8b\x04\x1c\x01\x5a\x87\x99\x55\x1d\x54\xe8\x4d\x36\x0b\x98\x12\xf5\x3b\xfd\x24\xf5\xf4\x3d\xad\xd5\x3d\x3c\xac\x03\x52\x49\x8b\x01\xea\x81\x52\xaf\x35\xd1\x63\xa6\x81\x58\x36\x49\x51\xd3\xf6\xc6\x21\x33\x07\x95\x3b\x2a\xf5\x8c\x6a\x10\x0f\x9e\x97\xb2\xad\x0a\x6e\x5e\x1e\xab\x1b\xc6\x4a\x43\xf9\xa0\x43\x85\xa3\xd4\x59\xb0\xae\xb5\x7a\x9f\x41\xb8\x48\x87\x92\xf9\xe5\x45\x6c\x83\xc8\x45\xf0\x7a\x40\x2e\xf2\x81\xaa\x59\x21\x14\xad\xe7\xe1\xa9\xa1\x6c\x0e\x9e\x49\xa0\x82\x0f\xfb\xb9\x25\xe7\xd1\xd5\xcb\x03\xc5\x59\x8e\x40\xd4\xb3\x32\xc7\x05\xe6\x2b\x18\xe3\xbd\xfe\x88\x10\xdf\x5e\x11\xe3\xd1\x1c\x89\x9c\xbf\x44\x2a\xa7\xe1\xd4\xbf\x01\x56\x22\xf7\x84\x17\x0c\xad\x68\xb2\x18\x94\x32\x2d\x30\xca\x65\xf2\xbd\xbb\xb4\x32\x16\x2e\xd9\xcc\x74\x4b\x55\x72\xd0\x5d\x9a\xae\xa2\xba\xf4\x97\x55\x80\x96\xd1\x82\x83\x40\xad\x40\x5d\x90\x95\xf1\x80\xf7\x99\xf0\xed\xcc\xe0\xa3\xf3\x96\x62\xb2\xc7\xd2\xbf\x16\x6b\xa8\x08\x35\x04\xaf\xc4\x13\xa8\x05\xd4\xa5\xd4\xd5\xd4\x2d\xe2\x3a\x8c\x17\x54\x42\xfd\xb2\xbe\xb8\xb0\x0a\x0b\xeb\x6e\x7a\xd9\xe5\xd2\x88\xdc\x84\x96\x0d\x0a\xcb\x6e\x22\x0e\x12\xbe\x98\x86\x8e\xa6\xcd\x28\x45\x85\x2e\x56\x58\x80\xf1\xe4\xab\x8b\x12\x5c\x49\x5e\x58\xc1\x05\x2b\xd7\x50\x1a\x4d\x32\x71\x8e\x81\x17\x32\x24\xe9\xfa\x02\xf9\x1b\x0c\x45\x7f\x81\xc9\x29\xa9\x32\xf2\x1e\xb3\xde\xe9\x28\x03\x4f\x5c\x22\x89\x44\x4f\x7d\x51\xdf\xe8\xcf\x0a\x96\xd7\xeb\x1b\x3a\x5a\x0b\x8a\xea\x1a\x42\xee\x22\x67\x87\x5b\x3f\xa4\x6b\x44\x51\x14\x33\x5b\x5d\x1b\xf4\x05\xba\xea\xbc\xe0\xd0\xac\xc2\x2c\x65\x0e\xb8\x52\xa3\xca\x2a\x94\xcb\x37\xed\xb2\x95\x6a\x0b\x77\xed\x82\x97\xe4\x87\x07\xd7\xc6\xa4\x9b\x77\xf9\xb3\x46\x46\xab\x50\x5e\x41\x7d\x41\x41\x3d\xfd\x70\x51\x64\x72\xd7\xa2\x9a\xc4\xbc\x99\x15\xda\xb2\xc1\xb9\x06\x33\xfb\x33\x3c\x9f\x4b\x5a\x35\x28\xe0\x93\x9d\x70\x8d\x99\xf6\x69\x45\x9d\x55\x65\x52\xdb\x3c\xdd\x59\xc1\x50\x53\x79\x9d\x45\x6d\xd6\xba\xad\xfa\xc5\xd9\x81\x6c\xe0\x5b\xb4\xd5\xb8\x44\x3a\xfb\x7f\x46\xf9\x5d\x8a\xe5\x5c\xe4\x25\xeb\xd5\x74\x96\xab\x14\x65\x83\x88\x1b\x3d\x04\xfe\xf2\xe1\xea\xb2\x92\xd2\xc2\xd4\x1a\xeb\x6e\x45\x69\x1d\x78\x91\xdc\xb9\x10\x7d\xbe\xb8\xa6\x76\xf3\x92\x64\x65\x22\x3c\xdb\xcd\xf3\x85\x6a\xf8\xc8\x79\x1f\x8e\xa6\xd4\x98\x27\xfe\x56\x42\x09\xe3\x9c\x20\x2b\xe9\xcd\xa4\x81\xc8\x7e\x70\x88\x8d\x94\x08\x63\x99\xac\x32\xc0\x44\x60\x4a\x08\x1a\x5b\x9c\xf8\xa7\xaa\x66\x88\x1b\x89\xcc\xe6\x13\x5e\xbc\xcc\x44\xd5\x5e\x62\xaa\xfa\xb2\xa5\x04\xd5\xee\x7a\x77\x27\x00\x94\x56\x5b\x31\x3a\x6b\x36\x13\x95\x02\xf9\xcf\x0f\xcb\xed\xd2\x51\x38\xf0\x34\x1f\xe9\x18\x57\x15\xfa\xec\x39\x69\x69\x7b\xa9\x74\xed\x73\x31\x70\x07\xce\x81\x07\xd1\xde\x57\x4b\x5a\xe6\xed\xda\x39\xef\xa1\xac\xd1\x15\x5a\xed\xd0\xd9\x92\x5a\xb9\x5d\x76\xea\x3e\x29\x94\x77\xe1\x02\xb7\x67\x79\x73\x26\xde\x70\xdf\xb7\x57\xef\x01\xac\x83\x37\x10\xfd\x7a\x03\xaf\xdf\x30\x09\xcc\xc7\x05\x44\x7b\xb6\x73\xef\x61\xc2\x74\x44\x1b\xd9\x15\xea\x7f\xf8\xa8\x0c\xa4\x5d\x33\x6a\x41\xff\xdb\x25\x3c\x41\x3a\xa1\x27\xd6\x03\xbf\xfa\x62\x8c\xf8\x2a\x43\x53\x3f\xd1\x0b\x73\x1e\xdf\x32\xe9\xa6\xce\x22\xa6\x37\xf3\xa2\x3b\xe1\x0f\x07\xaa\x16\x55\x81\x86\x51\xbf\xfa\xa2\x0f\xa7\x5f\x0e\x7c\x0e\x7f\x1e\xb7\xac\x66\xda\x82\x28\x4a\xa2\x5a\xf1\xc5\x37\x3c\x03\xb4\x53\xd1\x5e\xe6\x9e\xae\xdf\xfa\xe2\xfd\x18\xc7\x6c\xb2\x5f\xce\x95\x20\x9a\x43\xc4\x77\xa1\x30\x85\xea\x44\xb4\xa7\x5f\x8b\x03\x0f\x1e\x1a\x1e\x09\xc7\x66\xfc\x0a\x8a\x03\xc4\x97\xf1\x01\x91\x10\xf7\x71\xdc\xc4\xd3\x0b\xa4\x2e\x0e\xd3\x34\x30\x9c\x3a\x01\x7a\x8b\x38\x39\x7a\x41\xce\xd1\x8b\xf4\xea\x2e\xd1\x81\x83\x20\x70\x04\xb1\x26\x4d\x5b\x18\xd4\x86\xdb\x34\x4d\x20\xa6\xd6\xf7\x40\x41\x94\x93\x12\xaa\xfe\x87\x30\xfd\xef\x65\x32\x08\x65\x3b\x71\xb8\xaf\x65\xe4\xaa\x65\x23\xe9\xa7\x84\xdb\xdc\x1d\x28\x29\x09\xdc\xad\x1f\x80\x65\x9c\x27\x68\x3a\x12\x5d\x04\x02\x39\x44\x89\x90\x2e\xb4\x93\x50\x4e\xde\xaa\x81\xda\x52\x19\xb1\x1a\xfc\x4f\x3a\x28\xcc\xba\xa1\x4b\x57\x95\xbd\x89\xbe\x04\xda\xd7\xbd\x23\x67\x77\x94\x6a\x97\x6b\x37\x0d\xb9\xe6\x91\x27\xb7\x37\x5e\x23\x93\xac\x90\xc8\xfb\x7e\x4d\x47\x05\x1c\x5d\x18\x69\xcb\xc5\xe3\xe6\xad\xd7\x81\x56\x66\xcf\x1e\x92\xbf\x50\xab\x6d\xca\x2d\x7e\x72\xc7\xee\x97\x8a\x72\x9a\x38\x99\x8c\xce\xfd\x35\x2d\x96\x81\x72\x78\x35\xf1\xd3\x2a\xbc\x03\xd9\xc4\x10\x6c\xf3\x59\xa2\x6c\xe2\x15\x67\xb6\xf4\xd6\xaf\x5e\x40\x9b\xac\x11\x3d\x71\x9a\x4d\x78\xc5\x24\x65\x71\xa7\xd6\x52\x1e\xaf\xf0\xae\x64\x8e\x24\x70\x1a\x02\x9e\xe2\x00\xb8\x72\x8a\x7e\x63\xfe\xe4\x9a\xd5\xd3\xaa\xe6\x4f\xed\xea\x19\x0d\x4b\x9a\xd7\x5c\x33\x4c\xc2\x73\x53\x0a\x1d\x6c\xc9\xbe\xc9\xb7\x3f\xb2\xf9\x6f\x5b\xc6\x5e\x11\x84\x0a\x20\x63\x97\xb3\x52\x16\xae\x64\xad\x59\x8e\xf2\x71\xf5\x45\x68\x3f\x7a\x3f\xa3\x09\x7f\xf2\x11\x85\x4d\x9a\x2d\x05\x50\x3e\xeb\xcc\x16\xc1\x8f\x9f\xe0\x9f\x0f\x8c\x03\xf7\xc0\x53\x0b\x56\x57\x2d\x38\x30\xb5\x7b\xf5\x96\x57\x74\x8b\x0e\x4e\x8b\x42\x10\xf3\x44\xea\xc7\xfd\xee\xc1\x5b\x81\xfc\x96\xc1\xb5\x7c\xa9\x44\xa9\x60\x15\xa9\x9b\x2d\x96\x90\x0d\xc8\x42\x55\xcb\xdb\x30\xf5\x3f\x31\xd3\x44\xd7\xc9\xa0\xa2\x58\xa9\x54\xc9\x46\x76\x92\x4b\x82\x52\xe0\x38\xba\x1a\x8d\xeb\xd7\xdb\x12\xf6\xf5\x7c\x64\x4f\x8f\x32\x69\x89\x4d\x90\x41\x03\x88\x3c\x9f\x78\x04\x61\x43\x3c\xf1\x8a\x99\x16\xda\x13\x7f\x17\x32\x10\x02\x46\x49\xe3\x91\xc9\x1f\xcf\x91\xcb\xff\x28\xb7\xc9\xe7\xa6\xee\x0a\xc4\x5e\x3f\x4b\xd5\x26\x03\x70\xc2\x5c\x31\x6d\xce\x47\x93\xfa\x5e\x82\xb5\xbd\xa9\x5e\x09\x75\x04\xfd\x34\xe9\xa3\x39\x38\xf1\x8f\x72\xa1\x6c\xb2\x16\x50\xaf\xc7\x84\xb2\x42\xda\x9c\x8f\x27\x9f\xae\x15\xca\xf6\xa6\xf5\xc8\x90\x20\x87\xcc\x4e\xfb\xe8\xe0\xa8\xcc\x5e\x3b\x88\x0b\x8e\x1b\x4c\x94\x8f\x68\xda\x12\x5d\xe4\x44\x35\x23\x19\xde\x34\x37\x1f\x1d\xda\x32\x75\xd5\xba\xc7\x27\xc2\x75\x15\x7d\x4f\x87\xb6\x8e\x04\x0c\xfa\xe1\x2f\x6b\x9e\x5b\x5a\xce\x35\x96\x56\x6b\xb2\xd5\xd6\xba\xe6\x59\x73\x24\xd4\xa4\xa6\x9a\x71\xa9\xab\xd7\x4c\x38\xbc\x3e\x39\x0a\x36\xc4\xcf\xfc\xd8\xb2\xc0\x34\xf8\x4f\xe8\xfb\x49\x77\xbc\xb1\x9c\x8d\x84\xbc\x81\xfa\x49\x15\x7e\xcd\x79\xf2\xd0\xfc\x7e\x34\x3d\x01\xa1\x3a\x22\x60\x68\x8a\x10\x97\x30\x2a\xc4\x20\xe9\x36\x82\x97\xca\x34\x60\xb1\x0b\xf2\x46\xa2\x83\x29\x62\xc7\x72\x02\x84\xd7\xc5\x23\x84\x93\x21\x9a\x66\x9e\xfe\x7f\x22\x47\x23\x6a\x53\x31\xb1\x73\x32\xc5\x5f\x46\x38\xea\x14\x95\xdf\x1e\x74\xb8\x72\x7d\x96\xb0\xc9\xe4\xf4\xb7\x17\xe4\xb7\xfb\x5d\x46\x73\xc8\xe2\xcb\x75\x39\x82\xed\x9d\x62\xa6\x57\x88\xe4\xa7\xcb\xe4\x17\xb4\xfb\x9d\x26\x53\x98\x94\xf9\x65\x15\x21\x17\xd7\xe9\x6e\xaf\x25\x7e\x11\xc4\x7f\xb5\xed\xdd\x67\xa8\x21\xa5\xb1\x61\xbc\xc3\xeb\xe0\x83\x9d\xf0\x3f\x46\x92\x44\xa8\xe3\xb0\x5b\xec\x26\xb5\x96\xb7\xda\x1c\x4e\xab\x95\xd7\xaa\x4d\x38\xc1\x21\xa4\x0a\x21\x50\xdb\x2b\xe6\x3a\x6c\x62\xee\x05\x05\x6d\x56\xbb\xa9\xb7\xbd\x1b\xf4\xa2\xda\xcc\xaf\x9b\xd6\xb6\x8e\x1c\x16\x73\xe6\x59\xb2\xdc\xe5\xc1\x1b\x5b\xfe\x63\x44\x1c\xf3\x82\xbc\x8a\x25\x74\xb8\xc7\x48\xbc\x40\x60\xb6\x1d\xff\xa4\xd4\xcf\x14\x9e\x0e\x00\x75\x2a\x09\x7a\x61\x2d\x0e\x9e\x4e\x32\x54\x5f\x12\xe2\xbe\x97\xea\xed\xf7\x8d\xd2\x2b\xac\x83\x5a\xbc\x12\x52\x98\xfc\x17\xbc\x3e\xe1\x59\x2d\xca\x7b\x88\x1f\x10\xfc\xfd\x19\x3d\x4d\x41\xef\x3c\xf4\xc9\xad\xef\x88\xf3\xcd\x3b\xcf\xd0\xec\xca\x05\xfb\x53\xd4\x3b\x78\xde\x81\x97\xa7\x3e\x5c\xb0\x32\x33\x0b\xa5\xa8\x5b\xd1\x27\xf3\xe0\x1d\x34\x85\x27\xb8\xf3\x9e\xcd\x9d\x79\x36\xb2\x64\x90\x91\x46\x86\x5b\x48\x18\x61\xc4\xf8\x8e\x2c\x19\xc2\xf3\x72\x54\x48\xbb\x2a\xb5\x15\x0f\x94\x4f\x51\x57\x2f\x1c\x4a\x02\xe0\xed\x55\x5a\x9d\x11\x3c\xa6\xd6\x8b\xef\x70\x02\xb5\x1a\x75\x42\xa9\x4c\x21\xb1\x4c\x48\x9f\xf6\xb7\xc4\x51\xcc\x58\xaa\x8b\x50\x92\x04\xb7\x98\x11\x75\x86\x25\x21\xe2\x5d\xb9\x1f\xb4\x44\xb4\x11\xc1\x6b\x17\x14\xd5\xa1\x89\x13\x14\x11\x6d\x5b\x22\x80\xba\x12\x29\xa7\xcf\x05\xcd\x5c\x30\x24\x10\x92\xac\x52\x2e\x77\x95\xf8\x03\x60\xd0\xb1\x9d\x15\x73\xdb\x5a\x22\x65\xae\x62\x45\x56\xc5\xb8\x95\x1d\x5d\x0f\xce\xfa\xd3\xad\x8f\x8c\x28\xb5\x8f\xd2\x38\xc1\x26\x74\xf6\x86\x1f\xae\x18\x7b\xfd\x2b\x73\xc7\x5e\x37\x7b\x6c\x79\x45\x4e\xb9\xad\xeb\xca\x11\x4b\x83\x35\x1d\x63\xc7\x35\x97\x2a\xe8\x87\x16\xb5\x8d\x2e\x02\x4a\x93\x8b\xd9\x60\x73\x98\x9b\x8b\x9b\xe8\x5a\x89\xcf\x99\x6d\x57\xc9\x27\x7c\xb3\xe3\xf7\x81\xf8\x94\xf6\xf5\xc3\x2f\x77\x8c\x98\x3b\x2e\xbc\xe8\xd1\xae\x9e\xaf\xa6\xd4\xc4\xf6\x78\xfd\x60\xcf\x6d\x00\xec\x98\xfb\xda\xee\x89\xc1\xea\x69\x33\x2e\x5f\xba\x23\xfe\xea\xd4\xf6\x9c\xca\x2c\xb7\x39\xbf\x62\x6e\x93\x56\x77\xc9\x7e\x86\x36\xe7\x28\xec\xf9\xec\xf4\x62\x23\x30\xd6\x9f\xb7\x16\x8c\x15\x64\xf6\x44\xf7\x30\x54\x92\xd9\xbe\xf2\x99\x30\x29\x1d\x12\xf1\x48\x0c\x02\xf2\x2d\x5e\xf8\x4c\x82\xe2\x2a\x4b\xda\xc8\x6c\x14\xe7\xfe\x44\x3f\x74\xb1\x30\xcc\xb9\xe8\x45\x70\xea\xf7\x7c\xe6\xf3\x87\x65\x0c\x2c\xf6\xc7\x75\xc0\xc0\x4f\x0a\xc9\x3d\x83\xa2\xed\x6b\xa1\x76\xea\x0c\x67\x38\x62\x07\x23\x2b\xa6\x36\x99\xcb\x42\x83\x86\x27\x47\xce\x7c\x62\x1e\xcd\x4c\x7a\x70\xe1\xd3\x93\x0c\x8a\xca\x9c\x25\xe3\x97\xee\xd9\x3f\xa7\xfb\xd2\x02\xa9\xcf\x94\xed\x4f\x94\xb6\xe4\xcc\xdf\x33\xe7\x3c\x3f\x06\x27\x1f\xa8\x97\xab\x02\x0e\xa8\x52\x40\x7f\xa1\x46\xe3\x1f\x1c\x97\x3b\x0d\x4b\xdb\x39\x6d\xd7\x38\xa7\x54\xe3\xc8\xb6\xb1\xe5\x4d\xd7\x15\xee\x9c\xb5\x62\x48\x71\xf7\x53\x33\xc0\x82\x27\x16\x5f\x62\xb7\x2c\x6c\x1f\xf2\xe0\xb2\xb9\xf7\xcc\x5f\x61\x9c\x52\x3e\xa1\xac\x31\x64\xbf\x1a\x7e\x72\xbe\xc1\x03\x9d\x96\xf1\x8a\x18\xa2\x51\xea\x7c\xcf\xbb\x7e\xb2\xb1\xef\x21\x2a\x4c\x9c\x07\x47\xf5\x5a\x3c\x83\x11\x43\x07\x2d\xee\x25\x1e\x3c\x0d\x32\xc9\xb4\x1e\xab\x78\xa2\x05\xad\x58\xb4\x6e\xc5\xd5\x57\xaf\x00\x1b\xe7\x3c\x7b\xd5\x3b\x64\x6d\x4b\x51\x99\x55\x8e\x26\x21\x68\x39\x57\x21\x73\xea\x44\xdf\xa3\x37\xd0\xf7\x9d\x23\xae\x02\x77\x5f\x40\x1f\x0c\xb0\x27\xa4\x04\xb4\x7c\xca\x02\xc4\xbb\xc3\xf4\xd3\x00\xa6\x5f\xad\x1f\xb3\xbe\xfd\xf7\x99\xd5\x7f\x6f\xe6\xd1\xf3\xee\x08\x50\xfa\xd2\x19\x1a\xe2\xfa\xf3\x1e\x46\x98\xff\x89\x8a\x07\x3e\x11\xeb\x4b\x0b\xa6\x8e\x08\x2a\x17\xfe\xce\x35\x44\x14\x22\xd1\x92\xb1\x11\x8a\x62\x32\x1f\x78\x38\x93\x99\x11\x40\xf9\x89\xed\x81\xe0\x0f\x8e\xd0\x0d\x59\x78\x0a\xc9\x22\x3e\xca\x12\x21\xb2\x8c\x92\x7e\x83\x53\x08\xcf\x26\xb8\xa7\x8d\xe2\xd1\x1f\x4a\x87\x08\xe0\x5a\x34\x02\x4f\xa3\x97\xc3\x3e\xcb\x91\xba\x21\x9b\x8f\x1c\xd9\xbc\xf4\xe1\x3b\x9f\xd6\x97\x81\xc5\x20\x0b\x65\x4d\x9f\x6b\x64\xd9\x23\x9b\x2b\xab\x1e\xd4\xc8\x4d\x1a\xa3\x4f\xff\xe0\xa4\x23\x40\x0a\x2a\xd1\x29\xb4\x1d\x9d\x1a\xde\x54\x87\xf6\xe9\x3d\x2f\x99\xfb\xee\x39\x8c\x4e\x01\xee\xf0\x92\x99\x57\x0a\xaa\x95\x20\x09\x1e\x1b\xfd\xa1\xa8\x18\xe9\x31\x00\xc5\x84\x99\x87\x41\xb2\x29\xeb\x8c\xfb\x08\xfa\xf9\xc8\xf5\x5f\x8d\xae\xb9\x11\x24\x37\xcf\xde\xf9\x22\x90\x1e\xb1\xa0\x3e\x73\x89\x5a\xe1\x04\xcc\x94\x8d\x9b\x8f\x00\xe1\xba\xf8\x4a\x53\x1f\xa8\x99\x86\x72\x6d\xfb\xdf\x07\x1c\x58\x02\xb8\xc4\x93\xc1\x92\x60\x92\x88\xe6\x1d\xa8\x3b\x6f\xa0\x5d\x35\x27\xf4\x9c\x5c\x82\xa7\x47\x5d\x20\x4f\xe6\x33\x60\x54\xb4\x44\x90\x05\xc3\xf3\xfc\x08\xfb\x2e\xc4\xb7\xd2\x95\x10\xc9\x27\x31\x17\x33\xf3\x19\xf9\x30\x23\xca\x6e\x9d\x43\x58\x9f\xb9\x6f\x9e\xd9\xc7\x0e\x61\x83\x2e\x26\xe8\x0a\xfe\xd3\x61\x48\x25\x0d\x0e\x87\x01\x26\x0d\xe0\x20\x29\x9c\xa2\xf0\x21\x69\x9d\x2d\x7b\x04\xd8\xc1\x18\x60\x7f\x44\x36\xd7\x0c\x14\x03\xe4\xbf\x50\x09\x92\x66\xa7\xd3\x8c\x92\xae\x82\x02\x78\x49\xd8\xe1\x08\x3b\x52\x13\x52\x77\x25\x63\xc3\x86\xc5\x92\xe2\x11\x4e\xe8\x5e\x04\x5e\x6e\x5b\x5e\x59\xb9\xbc\x0d\x95\xcf\x12\xd6\x85\x2b\x70\xdf\xfb\x19\xaf\x0b\x05\x04\x5b\x80\x12\x87\xbc\xf0\xed\x30\x0f\x2d\xe2\x58\x45\x3d\x04\x05\x4a\x30\x23\xf0\x88\x82\x2c\x8f\x89\x21\x92\x31\x40\x18\x03\x51\x89\x12\xf7\x81\x90\x38\x7f\x54\x00\x81\xe0\xf4\x13\xe8\x20\x3c\x97\xb0\x4f\x46\xfc\xa9\x7a\x7f\x24\xe2\x87\xcf\xf9\x81\xd4\xdc\x97\x43\xc2\xf4\x35\xe3\xd0\x7b\x0f\x3c\x82\x8e\x3d\x64\xa6\xff\x4c\x12\xfa\x2e\x1d\x07\x42\x0f\x6c\xfe\xf6\xc1\x39\x60\x69\xc4\xbf\x49\xb7\xe9\x7d\xf4\xd6\xdd\x3f\xa2\xf9\xd3\x9f\x25\xb9\x9b\x71\x1c\x14\xdf\xf3\x03\xd8\x39\xfd\x88\x3f\x02\xff\xde\x14\x8d\x36\x45\xc7\x8c\x19\x15\xf1\xf9\x23\xd7\xde\xf3\x10\x7a\xf7\x91\x4c\x78\xf6\x43\xdf\x80\xcd\xbe\xc8\xe8\xd1\x77\xa3\xb7\x3e\xd8\x04\xe4\xc7\x23\x7e\x21\x06\x8a\x3f\xd8\x84\x7e\x3c\x1e\x21\x76\x15\x8a\xb3\x14\xf3\x43\xfa\xdb\xda\x71\xff\x5f\x26\x60\x8a\xd3\x66\x7d\x0c\xf3\x86\x82\xad\x74\x01\x7e\x35\x82\xa5\x64\x26\x10\x7b\x12\x5a\x70\x4e\x4d\x84\x57\x64\x5d\x91\xd0\x69\x91\x56\x5c\x57\x42\xac\x51\xfc\xe2\x46\x85\x8b\x49\x44\x04\xf8\x24\x11\x92\x1c\x8f\x13\x23\x4e\x0e\x86\x24\xbe\xb4\xeb\x35\x4c\xe4\x99\xd2\x0b\x8f\xb0\x5d\x71\xce\x50\x58\x54\x15\xe7\x4d\xe6\x6a\x56\x10\x1b\xd2\x44\x49\x1c\x8a\x68\xfe\x90\x3e\xbc\x64\xd9\x5d\xc1\x32\x74\x8d\x8b\x0e\x78\x95\x39\x3e\xf4\xe6\x3e\x5d\x96\xa6\x72\xd5\xb0\x22\xde\x30\x7c\xf6\x66\xaf\xda\x9c\xa5\x0a\x96\xd5\x3b\x0d\xd1\xdb\xac\x15\xa7\x6e\xfd\xfb\x2d\x7b\xf0\x77\x2a\x45\x7f\x58\x1a\x50\x2a\x73\x1b\xc7\x8e\xeb\x70\x6a\x39\x8b\x56\xc3\x38\x1a\xab\xb2\x6a\xc7\x07\x68\xe6\x4a\x99\xd4\x03\x47\xc4\x3b\xee\xf5\x94\x48\x5b\x4b\x95\xce\x87\x9c\xb9\xf1\x25\xa3\x27\x3b\x56\x57\x39\xb3\xef\xec\x68\xdb\xf4\xbc\x04\x4a\x0a\xb2\x1b\xaa\x87\x07\x06\x77\xec\xab\x1a\x1e\x54\x4f\xbe\xaf\x6f\xcf\xa2\xee\x9d\xef\x31\x97\xa3\xa7\x8c\xe0\x85\x86\xd2\xbe\xee\x76\x69\x8e\x15\x72\x1c\xbd\x65\x1a\x1a\x2f\x67\xc1\x94\xf7\x7d\x7d\x3f\xf8\x0f\x5c\x63\x53\x5b\xda\xb2\xda\xa7\xd5\xc6\xd1\xad\xd9\x35\xd7\xef\xbf\xef\x5e\x00\x73\x8b\x5a\xf4\xc5\x31\x05\xeb\xf2\x96\x38\x78\x86\x81\x3c\xef\x77\xd8\x4c\x96\x82\x2b\x06\xb9\x97\xba\x94\x4a\x28\x3f\x0a\x39\x75\x6c\xe8\xde\x11\x5e\x4f\xad\x72\x8e\x4e\xe9\xfd\x70\x7c\x62\xe6\x5a\x5b\xb3\xab\x7a\xb5\x06\x1c\x9d\xdb\x3e\x33\xf5\x8c\x4e\xa2\x5d\x7f\xc9\xf5\x33\x87\x4c\x1b\xba\x00\x35\x69\xaa\x27\x4f\xaa\xdd\x85\xfa\x9e\xbb\x24\xa7\x0c\xa8\xce\xf9\xfb\x23\xeb\x9f\x8d\x8a\x0b\x38\xf1\x14\x88\x0e\x5c\xcc\x7c\xe9\xd5\x8f\x2c\x74\x81\xff\x98\x13\x0f\x90\xcd\x27\x18\x0a\x7a\xb2\x08\x88\xbc\xf0\x05\x89\x7f\x0f\x13\xe3\xc9\x22\x60\xef\xd5\x80\xc7\x34\x2c\xad\x7b\x4b\x7d\xef\xc6\x3b\x0e\x3f\x7d\xcd\x8d\xf7\xa8\x5e\x67\xab\xa2\x65\x35\x72\x5b\x3c\x34\x05\xfe\xf9\xa8\xfa\x9e\x4c\xfa\x1b\x4c\x75\x84\xa4\xc7\x42\xc5\x09\xb0\xd0\x9d\x2f\xd1\x38\xe0\x98\xd4\xad\xa9\x6b\x47\xb3\x56\x9d\x24\xdf\xe5\xca\x97\xe8\xcd\x92\x3c\xb0\x15\xf0\x70\xda\x58\xd6\xa2\x63\x0b\x5c\xbd\x3f\x53\x50\x7b\xdb\xe3\xff\x7a\xf5\xf9\xcf\x1f\xec\xa9\x6d\x5a\xb5\xac\x68\x48\x83\xff\xea\x0b\x13\x5a\x9e\x78\xeb\xd5\x2a\xa9\x52\x0f\x6b\x6a\x18\x8d\x4a\x5a\xf9\xca\x3b\x6f\xbf\x52\x25\x55\xab\x59\x4f\x56\x1d\xa3\x56\xcb\x2a\x5f\xa6\x5f\x3f\x4d\xa6\xad\xcc\xba\xc2\x76\xe1\x76\x71\x52\x15\xa2\xc6\x63\x1a\x20\x3d\x38\xc0\xa3\xa3\x30\xd2\x05\x8f\xc3\x6a\x90\x59\xec\x33\x9e\x1d\xe3\x99\x08\x7d\x42\xf0\x2d\xd9\xd3\x8d\xbe\x16\x02\x98\x61\x7f\x7b\xeb\xc9\x2d\x20\xb9\xe5\xe4\x56\x54\x44\xe2\x38\x11\x68\xbb\x7b\x84\x00\x7d\x1d\xd2\x0a\x65\xbe\xee\xee\x39\x93\x24\x21\x16\xb3\xe5\x5b\x4e\xfe\x1f\xe6\xbe\x3b\xb0\x89\x23\xfb\x7f\x67\x8b\x56\xbd\x17\x5b\x96\x65\xc9\xb2\x24\x57\xb9\xc8\x92\x6c\x83\x65\xd9\x98\x62\x6c\xc0\x98\x66\xba\xe9\xa6\x9b\x4e\x80\x80\xe8\x24\x40\x42\x4f\x80\x40\xb8\x10\x52\x08\x29\xe4\x9b\xde\x30\xb9\x4b\x42\x0a\x1c\xc9\x41\x0e\x12\x92\x38\xb9\x34\xee\x92\x5c\xbe\xb9\x4b\x0e\x6c\x69\xf8\xcd\xcc\x4a\xb6\x6c\xb8\xdc\x7d\xef\xfb\xfd\xe3\x07\xd6\xee\xec\xec\xec\xec\xcc\xec\xcc\x9b\x37\x6f\xde\xfb\x3c\x50\x13\xd9\x81\x9e\xd2\x2a\x19\x61\x11\x4f\x1d\x69\x61\x5a\x04\x1b\x10\x36\xc1\x06\x24\x48\x34\x78\xa8\x9e\xda\xb1\x9c\x80\x55\xcd\xc7\x01\xab\x51\x5c\xfc\xd6\xad\xae\x9c\xbe\x4e\x45\x1d\x72\x2f\x86\xb7\xde\x83\xa3\x49\x4b\x49\x7a\x27\xc9\x62\x41\x87\x14\x68\xac\xf4\x6d\xac\xb6\x58\xaa\xd7\xf9\x2a\x0d\x01\xc4\xba\x4f\x48\xb2\x18\xfc\x46\x4b\xd2\x24\xc4\xdd\x07\x0c\xf4\xa0\x2a\x1f\xbc\xe6\xab\x42\xc1\xb4\x8a\x53\xbe\xaa\xd5\x5b\x9a\x3a\xce\x37\x6d\xd9\xd2\xc4\x16\x34\x6d\xa1\x9f\x5b\x88\x73\xc1\x07\xd8\xee\xab\x2c\x2e\xae\xf4\xb5\x1b\x8d\x5f\xe3\xb8\xaf\x3b\xcf\x4b\x0f\xf8\x2a\x2b\x7d\x70\xba\xc1\xf0\x4c\x76\x25\x7d\xa8\xeb\xe9\x2d\x89\xbe\x0b\x69\x34\x35\x63\x2d\x42\x7b\x0a\xb0\xe3\xff\x92\x9b\xec\x0a\x77\xc3\x8f\x76\x5f\x05\x01\xf8\x0a\x1c\x00\x5f\x01\x01\xb0\x86\x9e\x75\x7c\x69\x24\xb4\xf4\xf8\xf1\xa5\x4c\xeb\xd2\xe3\xe0\x75\xda\x1d\xb9\x07\x71\xff\x14\x28\xa3\x1f\xea\x8a\x3f\x8e\xbb\x83\xa9\x13\x8f\x71\x10\x35\x82\x9a\x44\x35\x53\x73\xa9\x85\xd4\x72\xb4\x0a\xdc\x40\xdd\x41\xed\xa4\xf6\x51\xf7\x51\x47\xa8\x07\xa9\x87\xa9\xe3\xd4\x93\xd4\x0b\xd4\xcb\xd4\x6b\xd4\x69\xea\x5d\x01\xeb\x98\x21\x16\xa1\x4c\x6c\x17\xd4\x2e\xc2\x3f\x81\xae\x31\xc4\xe0\x96\x11\xd0\x0f\x74\xc5\x38\x4a\x17\xa3\x6d\x76\x3f\xfe\x09\xb0\x13\x3a\x82\xa3\x8b\x8e\xa8\x62\x0e\x80\xee\x00\x12\x6b\x0a\x68\xdc\x22\x1e\xd8\x4d\x4e\x94\x27\x86\x01\xe5\x1d\x01\x06\x98\x40\x40\x67\x07\x7e\xce\x8b\x56\x38\x26\x23\x63\x0f\x00\x15\xf0\xfa\x78\xa3\x46\x8f\x1f\x32\x69\x02\x1a\x13\xc8\x07\xbc\x26\xe0\x16\x39\x1d\x9c\xc9\x20\xa1\x9d\x6e\x0d\xc7\x7b\x81\x49\x97\x4f\xa3\x5e\xc3\xb8\xdc\x12\xda\xc7\xe8\x1c\x3a\xc0\x57\x00\xe2\x8e\x4e\x06\x4c\x7e\x31\x65\xd6\x9f\x65\x92\xf5\xa7\x19\x7b\x52\xb2\x1a\xb6\x68\x8a\x35\x70\x81\xc6\x6c\x4a\x67\x4f\xeb\x93\x99\x73\xfa\xe4\x14\xfd\x5b\x20\xfd\x7d\x36\xdd\x64\xd6\x82\x6d\x6a\xbf\x1a\xdc\xa5\xc5\x77\x7f\x6f\xb2\xf1\x2f\xeb\x92\x23\x6e\xb0\x11\x1e\xbf\x1b\x1e\x07\xcd\xda\xec\xc8\x58\x40\x9f\x57\xbd\xf2\xb2\x42\x4d\x3f\x02\x57\xbd\x46\x67\xc3\x6f\xd5\xb9\xf4\x93\x80\x0d\x69\xac\xc6\x08\xbc\x54\x01\x96\xa9\x2b\xe1\x08\x30\x48\x1c\x69\xe1\xc0\x48\xb8\x95\x45\xa3\x64\x57\x08\xbe\x7b\xe8\xf4\xd1\x47\x58\x20\x7e\xcc\xba\x1f\x64\x7d\xf6\x19\x7b\xf6\x94\x88\x59\xa6\x8e\xee\xbe\x08\xff\x88\xbe\x67\x66\x74\xe5\x16\xf0\x75\xf6\x08\xe0\xfc\x61\x03\x03\x8c\xe2\x4b\x9c\x18\xd6\x02\x7f\xa4\xf5\x28\xfa\xc7\x96\x17\xac\xcb\xfc\x3d\xcd\x3c\xb6\x76\x10\x47\xaf\x35\xa4\xb1\xf0\x3e\x89\x44\x8f\x4e\x4f\x8a\xc5\xa6\x74\xad\x5e\xaf\xb7\x27\x89\xe5\x60\x08\x9b\xa6\x97\x48\xc0\x54\x2e\x4d\x8f\xd2\x80\x46\xc0\x82\x0c\x15\x98\x2d\x15\x27\xd9\x0d\xe8\x9f\x3d\x49\x24\x87\x07\x80\xdd\xa8\x50\xc2\x57\xd8\xb4\xc8\x59\x30\x19\x1e\x56\x33\x16\x56\x22\xe5\xe0\xbd\xa2\xb7\xc0\xd8\xd7\xc5\x34\x68\x3d\x73\x46\xdd\x31\x5c\xc4\x55\x0f\x99\x09\xa4\xf0\x6c\x08\xee\xb0\x00\x3f\x7c\x94\x55\xa1\xd4\x27\x45\x1c\x58\x5e\x05\x2a\x1f\xfa\xe4\xd5\x93\x62\xc6\x07\x68\xa0\x56\x9c\x04\x0a\x19\x7c\xfb\x10\x28\xfb\xee\x53\x31\xbc\x36\xf0\x6d\x5a\xde\xf6\x79\x0e\x7c\x03\x9e\x06\x5e\xd5\x76\xf8\xe5\x27\xb9\x60\x4b\x07\x8d\x1a\xc2\x80\xda\x0b\x2c\x07\x2c\x2c\x84\x2f\x82\x5f\x3e\x83\x5f\x47\xee\x80\x5f\x81\x94\x3f\xfd\xa9\x1f\x98\x29\x65\xd1\x67\xce\x8c\xde\xd7\xc0\x08\xf2\x12\x82\xff\x8f\x31\xef\x28\xd2\xfd\x3b\x07\x03\xfa\xd6\x09\x8a\x78\xcf\xaf\xa7\xbf\x06\x4d\xcf\xaf\x8f\xfc\x7d\xfd\xf3\xec\xf9\xa7\x42\x1e\x68\xf1\x84\x2a\xf3\x98\xc6\xf5\xa7\xc0\xf4\xf6\xaa\x0d\xaf\xbd\xb6\x21\xe3\x19\xf0\x28\xc6\x30\x87\x7a\x4f\x1f\x81\xde\xac\x47\xe3\xed\x76\x4a\x4a\x3c\x7b\x63\x79\x0c\x4b\x31\x98\x71\x41\x7c\x0b\x87\xd8\x5e\x74\x81\x16\x99\x40\x4b\x39\x85\x0b\x0e\x23\xc5\xf9\xa9\x80\x88\x37\x32\x0f\xc1\xdf\xc2\xf4\x65\xfa\xb3\xa0\xe9\x7c\x03\x98\x3a\xbe\x3f\x5c\x19\x7d\x63\xfe\xf8\x60\x0b\xed\x87\x47\x17\xd1\x1a\x30\x25\x53\x09\xaf\xc0\xd0\xb2\x19\xcc\xef\x4f\x3f\xb1\xf9\xe0\x5c\x30\xf0\x3d\x43\x7d\x25\x37\xeb\x36\x98\x0a\x4f\x8f\x1e\x75\x1e\x4c\x3a\x7b\x67\xe5\x98\x05\xd1\xd3\x70\xe5\x80\x31\x60\x1d\x5d\xd6\xd1\x1b\x4c\xa5\xf5\x4b\xc7\xcd\x58\x0e\x83\xf0\x63\xa5\xbe\xa8\x72\xb8\xe9\x2c\xa8\x9d\x77\xef\x86\x27\x63\xb4\x41\x4c\xb1\xff\x20\xba\xbf\x98\x92\xeb\x04\x2f\x3f\x64\x87\x24\x07\xe8\xfc\x88\xcd\xf6\x7b\x6d\x58\xb9\x93\x89\xc7\x33\x78\xa1\x8b\x18\x19\xc1\x39\x1d\x4f\xbc\x43\x99\xfc\x26\x7e\xda\xc1\xf5\xab\xcf\x9c\xfe\x62\xcf\x9e\x2f\x4e\x9f\x09\xaf\xe2\x0e\xb6\x01\xfa\xea\x81\x03\x57\x01\x0d\xff\x7b\xed\xb9\x43\xab\x1e\x7b\xa3\x6d\xdf\xbe\xb6\x37\x1e\x5b\x35\xf3\xb6\xa7\xc6\xbc\x73\xe2\xc4\x4f\x81\x3f\xec\xb9\xf7\xd3\xa7\x8e\x2c\x5c\xf5\xfe\x92\xf7\x8f\x9d\x78\x87\x5d\xde\x21\x2e\x1d\xbb\x67\xcf\xd8\x52\xf6\xda\x9a\x59\xb3\x3a\x1e\x2a\xad\x64\xa2\x83\xb7\x6f\x1f\x1c\x61\x72\x72\x1d\x73\xe6\xa4\x33\x5b\xd9\x7b\x0e\x56\x45\x86\x79\x8b\xa6\xcf\xe6\x04\x3e\xfa\x18\x9a\x9b\xc7\x76\xda\x5b\x8c\xfb\x9f\xcb\xa1\x6f\xba\xee\x02\x58\x4d\x40\x5a\x21\xb4\xc5\x0a\xb8\x2b\x56\xfd\x78\xbd\x95\x1c\xe0\x97\x56\xfd\x34\x1c\x46\x07\x78\xe5\xd6\x61\x6e\xcb\x77\x0f\x75\x64\x3c\xf4\xdd\xea\x99\xd2\xdf\x2c\x98\x3e\x38\x0f\x64\xbf\xba\x37\xb2\x5b\xb9\xf9\xc4\x31\xfa\x13\x83\xd5\x6a\x88\x3a\x70\x42\x5a\x87\x8f\xd1\xef\xf1\x11\x3c\x8e\x8f\x70\x18\x09\xcf\x22\xe1\x7d\xe8\xf8\xd0\x43\xdf\x7d\xf7\xd0\xe2\x37\x8a\xd2\xdd\x0b\x7e\xd3\xe7\xf9\x3f\xef\x8e\xec\xad\x2a\xb1\x7f\x4c\x61\x6d\x49\xea\x46\x50\x24\xd8\xce\x08\x7e\xda\x0c\xc4\x53\x9b\x9d\xf8\x6a\xcb\xa3\x0a\x29\x1f\x55\x4a\x95\x53\x95\x54\x5f\xaa\x06\xd1\xe5\xa1\x88\x32\x8f\xa6\xc6\x23\xea\x3c\x83\x9a\x4d\xcd\xa7\x16\x51\xcb\xa8\x95\x88\x42\x6f\x44\x14\x7a\x3b\xa2\xd1\x7b\xa9\xfd\xd4\x31\xea\x22\x1a\x11\x58\xf4\xe3\x24\x47\x9f\xdd\x80\xad\xd7\x4c\x3d\x7f\x01\x13\x9f\xf8\xc3\x2e\x89\x12\x7f\x00\xe3\x82\xfd\xca\x0f\xdf\xf7\x1a\x02\xff\xe4\xae\x09\xeb\xb3\x18\xf8\x5b\xfc\x9c\x71\x0e\x8b\x80\xdf\x58\x69\xbf\xa0\x8e\xe6\xe8\xd4\xa7\x03\x22\x97\x80\xf5\x6f\x34\x79\x03\x1e\x11\x16\x5e\x8b\xa8\xc8\xb5\xa8\x98\xbb\xaf\xfd\x0c\xbd\x97\x3e\xda\x7e\x66\xa8\x33\xfe\xaf\x42\x35\x53\x95\x86\x7e\x56\x72\x6e\x56\x0d\x99\xa9\x9a\xb9\x1c\xfd\x6e\x8b\x9d\x23\x95\x0b\x81\x7e\x11\x30\x2c\x02\xfa\x85\xe4\x2f\x16\xee\x78\xc1\xb9\xe8\x81\x9e\xf1\x3f\x0e\x5e\xd4\x99\xb1\x33\xba\x65\xed\x0b\x2f\xac\x5d\xf7\xfc\xf3\xf0\xb2\xbb\x77\x75\x6f\x77\xcb\x24\x33\x93\xd6\x67\x62\x6a\xa0\xc4\x11\xa8\x1f\x12\xc8\xca\x34\xa4\xd7\xa8\x10\x37\x9e\x21\xb1\x2a\xcd\x46\x79\x6a\xc0\x67\x17\x51\xed\x3b\xe0\x13\xa0\xa1\x92\x39\x1c\x99\x0c\x3f\xe2\x32\xdf\x7e\x1b\x7e\xb8\x68\xd1\x9e\x84\xbf\xbb\xd3\xf3\xed\xca\x74\x4f\x3a\xfe\x29\xec\x9e\xf4\x74\x8f\x3d\x7f\x82\x27\xdd\x83\x7f\xe3\xf3\xd3\x3d\xec\xfb\x19\x3d\xfe\xc1\x13\x43\x16\x75\x8f\x59\x34\x24\xa3\x5b\x9e\xe8\xcf\xf1\xfc\x3a\xa1\xb4\xe0\xf6\x8c\x2c\x09\x07\x74\x86\x42\x6f\x45\xb6\xd4\x98\x9b\xe6\xc9\xe7\x81\x4c\x6f\x48\x12\x19\x4d\x65\x40\xc5\xc8\x18\x11\x2d\x35\xe5\xc5\xfd\x0b\x2c\x42\xe3\x6f\x3b\xc1\x7b\xc8\xee\xb1\x86\xbd\x95\x71\x5e\xcc\x8d\x2c\x66\x34\x26\xde\xdf\x76\xf8\x70\x1b\x03\x0f\xb7\xdd\x7f\x7f\x1b\x68\xab\xc8\xbb\x76\x29\xaf\xa2\x22\x0f\x3c\x99\x1b\xa2\x7f\x0a\xe5\x82\x27\xf3\x2a\xc0\x16\x7c\xef\x30\x4e\xd8\xb2\xe0\x30\x5b\xd2\xfe\x4a\x6e\x45\x45\x2e\x57\x8d\x8f\xbf\xf9\x0d\x3a\xc6\xf8\xd0\x4c\x44\xbf\x2e\xa3\xf3\x18\x44\xbd\xb8\x38\xdc\x11\xdf\xb5\x3f\x4f\x04\xcd\x18\x1f\x90\x15\xbc\x44\x50\x89\x10\x49\x31\xcd\x01\x9f\xb0\xc9\x11\x57\x65\x17\x1e\xf0\x73\xfb\x00\xbb\xe7\x83\x8f\x0e\x8f\x38\xb0\x62\x61\xf3\x8c\x85\xcb\xef\x1d\x76\xe0\xb7\xe7\xef\x9f\x7a\x69\x04\x67\xb3\x88\x95\x86\xde\xd3\xe0\xcf\x6b\x36\x7e\xbe\x19\xa4\x9c\x5b\x7e\xf1\xf0\xce\x8d\x9b\x8e\x8d\x99\xbe\x71\xed\x44\xeb\x0c\x8d\x3e\x4d\xf3\xc7\xfb\xcb\x66\x97\x17\x89\x55\x86\xe4\x5e\x4f\x4d\x38\x05\xd9\x52\xe6\xc5\xf7\xde\xd8\x75\xe8\xfd\xc0\xb8\xe5\x1b\x36\x2e\x1f\x17\x78\x7e\xff\xa1\x97\x6a\xcb\xd9\x54\x9d\x41\x99\xe4\x6b\x9c\xb3\xf8\xc3\x4d\x67\x81\x7a\xd4\xd6\x87\x1f\xd9\x3a\x6a\xe5\xb4\x89\x61\xa7\x55\xaf\x1d\xac\xbf\xff\xbc\x33\xd7\x69\x50\xe9\x52\xfa\xd4\x74\xbc\xe6\x4c\x55\xc5\x78\x59\xec\x7f\x1c\xdb\x12\xe4\x60\x8c\x28\xa2\xc2\x40\x7c\x52\xa6\x02\xa2\x2a\xd6\x0b\x10\x90\x11\x8c\x45\x12\xc7\xb2\x67\x63\x67\x1d\xf1\xb0\x40\xfc\x0a\xa0\x8f\x10\x27\x75\x41\x10\x60\xe2\x32\x15\x2b\x8b\x97\xe1\x2c\x76\xd0\x8b\xa5\x16\xc4\x87\x2f\x09\x44\xbf\x16\x74\xc8\x05\x55\xf2\x77\x6d\xc9\x1d\xdf\x01\x9e\x4b\x62\xee\xc5\x49\x22\x94\xd9\x65\x74\xd2\x27\xdf\x13\xc4\x26\xea\x64\x95\x8c\xe5\x01\x7b\xd2\xec\x62\xba\xe7\x82\x03\xd1\x44\xc5\x72\xa6\x15\x52\x49\x4e\x66\x05\x9f\x9a\x24\x55\x17\x60\x8c\x3e\xb3\xd2\x5b\xcd\x32\x01\x14\x54\x68\xd3\x8c\x4e\xde\xd5\x85\x6b\x8f\xeb\x2d\xe8\xe3\x0f\x13\x7a\x9b\x2a\xae\x46\x4f\x3c\xa0\x99\x80\xb1\x28\x00\xfe\xd3\x3a\x73\x94\xab\x58\xb7\x1b\xbd\x76\x37\x62\x32\x75\x80\xc2\xd0\xd8\x54\x74\xf7\x7f\x5c\x6b\xdd\x2e\xe0\xc4\x37\xe0\xc7\xbb\x74\x28\xe7\x1b\x94\x0e\xe7\x97\xfe\x3f\xaf\xbb\xe0\x47\x43\xe0\xdf\xb1\x37\x4e\x39\xb1\x35\x43\xb7\x74\x12\xc6\xee\xd6\xd9\x25\xb4\xdd\x69\x67\x08\x43\xef\x14\xb6\xcc\x89\x67\x0f\x8c\x53\x60\x2f\xba\x40\xcf\x87\x17\xc0\x55\x30\x3e\xda\xef\x8e\xf7\x60\x3b\x6c\x63\xa2\x28\xe6\xd5\xc8\xeb\xf4\xf1\xf7\xe0\x0f\xf4\x7c\x30\x06\xb6\xc1\x76\x30\x1a\x84\x95\xb4\x3a\x12\xd2\x96\x69\x23\x21\x35\xad\x04\x61\xad\x9d\x0d\xdb\x19\x2a\x3a\x83\xde\x1f\x89\x30\x2c\xf1\xb7\x11\xf9\x86\xde\x4f\x02\x20\x3c\x1d\x52\xda\x7c\x4d\x84\xd2\xeb\x59\x4a\x93\xaf\xa5\x29\x6c\xc7\x89\x2a\xc9\x7f\x8f\xe6\xa2\x1a\xea\x1e\xc4\xe9\x53\x1c\x16\xcb\xf3\x6e\x02\x45\xfd\xeb\x87\x80\x60\x1c\xfb\x4f\x0f\xce\xc4\x44\x1a\x06\x6f\x9b\x6b\xbc\xd8\xcd\xa8\x01\x43\x80\x62\x1f\x0d\x8c\xa6\x2b\xf5\xbf\x7a\x25\x30\x38\x39\x1f\x9e\x66\x78\x1d\xfa\xc8\xe1\x31\xc3\x86\x69\xfd\xda\x61\xc3\x50\xf8\x9f\x1e\x70\xa2\x5f\xbb\x3f\xac\x3d\x2f\x21\x55\xe8\x03\x8d\xde\x7a\x32\x2c\x6c\x03\x85\x4f\x5a\xf5\x9a\x0f\x74\x89\x39\xfd\xea\xeb\x40\x08\x60\x13\x1f\x88\xfa\x8b\x90\xa1\xee\x9f\xfd\x7e\xe5\xee\x6d\xf8\x6e\x43\x83\x4e\xd7\x10\x02\x4e\x50\x66\x2e\x97\x96\x81\x1c\x6c\x1c\x0e\x2f\x96\x49\xcb\xcd\xf0\x4d\xf8\xb1\x16\xdd\x6c\xf8\xd5\x4c\x58\xb3\x00\xb9\x19\x1f\x7f\x5c\xdc\x97\x4b\x1f\x6a\x29\x45\xd9\x75\xa8\x25\x75\x2a\x00\x62\x4e\x20\xd3\x63\xbe\x20\x05\x37\x8e\x12\xec\x80\x1a\x6b\x67\x31\x28\x20\x16\x0c\xa3\x3b\xc7\x1e\x13\x70\x7b\x31\xa1\x15\x88\x2d\xc6\x67\x31\x16\x11\x90\x16\x40\x80\x5c\x8d\xbc\x97\xb7\x32\x74\xa8\xa9\x09\x37\x44\xb8\x09\x50\x34\x2d\x1d\xd9\x6f\x12\x6f\xe1\x27\xf5\x1b\x29\x25\x7a\xba\x32\xf4\xc7\xc8\x39\x85\x4c\xa3\x35\x29\x32\x3c\x3a\xa9\x42\x26\x97\x29\xa4\x3a\x4f\x86\xc2\xa4\xd5\xc8\x14\x9c\x9c\x91\x91\x54\xe0\x81\x5d\xb7\x45\xf6\xdd\xb6\x4b\x92\xea\x19\xea\x1b\xf3\xa1\x91\x7e\xfd\x03\x4d\xdf\x0c\x5b\xae\x75\x4e\xef\x39\xd6\x5c\x5b\x46\x5f\xcd\x07\xaf\xf3\x29\x1f\x36\x54\x8c\xce\x56\x83\xd6\x70\x08\x9b\x48\x85\xc2\x74\x11\x4b\x8b\x75\x34\xad\x13\xd3\xac\x56\xc2\xf0\x3c\x6b\x17\x9b\xc5\x7a\x5e\xce\xb2\xc9\x8e\xf4\xe4\xe4\x74\x47\x32\xcb\xca\x79\x3d\x8a\xb4\xb3\x3c\xcf\x48\x22\x47\x6f\xbb\xf3\xce\xdb\xca\x17\xde\x31\x6f\x92\xf9\x4a\x28\x24\xd7\x67\x96\x94\x66\x07\x77\x64\x3b\x83\x41\x67\xf6\x8e\x60\x76\x69\x49\xe6\xd0\x21\x9f\xdb\xd7\x1c\xb9\x3b\xb6\x6f\x10\x45\xb4\xac\x0e\x71\xac\x2d\xd8\xda\x45\x49\x63\xab\x0a\x17\xd9\x28\x21\x22\x50\x47\x82\xe0\xdb\xd5\x69\x13\x6e\xa5\x4d\x76\x2f\x96\x84\x06\xc8\x5e\x3b\xee\xee\x31\xa1\x04\x62\xd5\x4d\x78\xaf\x09\x71\xb0\x01\xbb\xe0\x22\x9d\x88\xdb\x33\x81\xff\x26\x19\xbb\x38\x2a\xaf\x5e\xf7\xf2\x8c\xdf\x7c\xaf\x96\x0f\x19\xd2\xbf\x69\x9e\x33\xe5\x06\xd5\xb7\x53\x0c\x5e\x57\x97\xb4\xf2\x59\x62\x0e\x16\x1e\xbc\x69\x4a\x6e\x2a\x4d\x2d\x1a\xf1\xa9\xd5\xc5\xb1\xae\xa4\xa8\x5d\xdf\x6f\xa1\x2e\x65\x1a\xbe\xf9\x5f\x8b\xd6\xef\xb8\xfb\x9d\x6b\x17\x16\x3d\x65\x82\x6f\x3a\xf4\x5a\xcd\xee\xfc\xdc\x0d\xaf\xbc\xc2\x85\x81\xf8\x95\xee\x32\x77\xf0\xf7\x19\xa7\xb6\xd4\xf1\xb2\x2f\x8f\xcc\x7f\xab\xff\xec\xfa\x2f\xd7\xa5\xb8\xe3\x92\xf1\x94\xbc\x79\x88\xd4\xa5\x14\xa5\x1a\xc3\x79\x56\x93\xd5\x32\x73\xa1\x0e\xbd\xd6\xec\x3a\x51\x91\x62\xbe\x1c\xed\xd8\x39\x3f\xcd\x96\x86\x56\x74\x58\xf0\xfe\x4a\x4f\x71\x7b\xcc\xbf\x11\x17\xe6\xda\x10\x8f\x3b\x04\xcf\x84\x76\xbd\x92\xb6\x79\x68\x01\x4f\xc3\x88\x95\x6c\x94\x2c\x6f\x65\xb1\x27\x74\x02\xac\x41\x4c\x18\x19\x41\x56\x95\xa8\x71\xd2\xa9\x97\x17\x9b\x31\xb8\xf0\xca\xb3\x3f\xc3\xf6\x9f\xcf\xae\xac\x5a\xbc\xbc\xbf\x39\x97\xe5\xd2\xcc\x65\x4d\xa5\x99\x2a\xc0\x14\x4c\x5e\x77\xea\xc2\xa9\x75\x93\x0b\x18\xa0\xca\x2c\x6d\x2a\x33\xa7\x71\x6c\xae\xb9\xff\xf2\xc5\x55\x30\xec\x32\x87\x04\x13\x27\xd4\x7a\xb5\x3e\x10\xf6\xd5\x36\x11\x5f\x57\x15\xd3\xca\xd3\xd2\xca\xa7\x55\x14\x0e\xf1\x3b\xe4\x28\x2b\x94\xa1\x34\x25\xc9\xa4\x66\x65\x69\x0e\xab\x5e\x6f\xcd\x48\x93\xb3\xca\x24\x53\x8a\x14\xe5\x84\xf2\x93\x3b\xfc\x43\x98\x21\x10\x3b\x14\x0b\x0b\xfb\x11\xf8\xe7\xab\xad\x05\x8f\x08\x3e\xb1\xe8\x4e\x9f\x35\x29\x44\x7b\xca\x8e\x21\xfc\x04\x0c\x4b\xb7\x1d\x7d\xff\x14\x20\xf8\x72\xd1\x99\x8c\x00\xcd\x79\x18\x98\x56\xc4\xcb\xd0\x8c\x80\x77\x13\xec\x31\x8c\x48\xda\x14\x64\xb0\x00\x9d\x02\x85\x9c\x94\x65\xa2\x3b\xb5\xc5\xda\xe8\x0e\x4e\x0d\x16\x18\x1d\x5c\xbf\xd7\x44\xe9\x46\x43\xba\x68\x57\x89\x96\x76\xcf\x80\x77\xcf\x17\x3b\x74\x79\xb2\xb5\xbf\x13\x39\x72\xd3\xb9\xc5\x70\xf4\x0c\xd8\x16\x5c\x3b\xbf\x3e\x23\xa3\x7e\xfe\xda\x60\x1b\xa4\x29\x91\x84\x61\xa3\x8f\x68\xb5\xf4\x18\x5a\x9b\x62\x00\xc9\xd1\x69\x7a\xb3\x59\x0f\xbe\x6a\x71\x80\x13\x3b\x0f\x7e\xa2\xd1\xd3\x5c\x16\x6c\xa0\x9f\xd0\x9b\x53\x0c\xb0\xe0\xe0\xce\x2b\xd7\x72\x6a\x42\x19\x19\xa1\x9a\x9c\x6b\x98\x87\xa3\x6f\x50\x6c\x98\x8b\x10\xdb\x1a\x0a\xe8\x29\x5e\xe3\x8d\xf7\xea\x4e\x41\x5d\x27\xde\xae\xc6\x03\x68\xe2\x7d\x96\xd5\x66\xe0\xbd\x22\xf4\x63\xc3\xf0\xf2\xe5\xb6\x2e\xd0\x18\x21\xb8\xef\x6f\x6b\xe5\xb2\xad\x9f\x6f\x3c\x0e\xb2\x9f\x88\x50\x42\x8f\xc3\x7b\x3f\x4c\xeb\x27\xf0\x45\xd4\x97\x12\x92\x0a\xea\x44\xac\xfa\x09\xa0\x3d\xb8\xe9\xeb\x5d\x2a\xdd\x2e\xf8\x67\xad\xb0\x9b\x83\x9f\x4a\xdc\x07\xc5\xb6\x80\xdd\x7d\x42\x12\x6f\xc8\x74\xba\x87\x26\x1b\xc0\x26\x10\x03\xc2\xf1\x0a\x65\xa3\xd4\x5c\xab\xd9\x45\x5e\x00\xd7\xad\x1e\x7b\xf0\xe2\x9f\x2f\x1e\x1c\x8b\x4e\x4b\xde\xbd\x0f\xac\x86\x1d\x44\x58\x39\x23\x5e\x34\x78\x9d\x43\x5f\x1b\x0a\x6a\x4b\x22\xb8\xf6\xbe\x77\x97\x08\xa9\xf1\x43\xab\xc1\x6a\x92\x4d\x7b\xb8\xab\x2e\x9d\xba\x28\x2c\xa6\xcd\xe5\x82\xed\x9c\xd6\x80\x9a\xd0\xf0\x2b\x4d\xe8\x73\x51\x44\xe3\x0c\x51\x1c\xac\xb2\x63\xc5\x54\x83\x50\x12\x5e\x14\x2f\x34\x13\xdc\x79\x12\x35\xaa\x80\xd8\x40\x5e\x2b\x04\x2f\xc3\xcb\x27\x77\x1e\xab\x10\xe9\x34\x7d\x0d\xe2\xdc\xd6\xef\x5a\x73\xc5\xa9\xe5\x1a\x9d\xa8\x22\xfa\x60\x57\x25\xd8\xdf\x0d\x80\x7f\x79\x18\xb7\xf2\x86\x84\x47\x49\x70\x43\x12\xe8\xff\xc9\xc3\xc0\x30\xa0\xe9\xa4\x3a\x45\x3f\x6b\xdd\xba\x59\xfa\x14\xf5\xc9\x8e\x2b\x09\x55\x22\xfd\x81\xcc\x35\x55\xd4\x40\xbc\xe7\x1c\x53\x78\x8f\x57\x03\x83\xc7\xfd\x8b\xfa\xe1\x2e\xe2\xa7\x30\x11\x70\xe2\xf1\x1d\xaf\x14\x4b\x61\x9b\xf9\xf8\xd7\x58\x7d\xab\xfa\xed\xfd\xdb\x3a\xb9\x1a\xd8\xde\x5d\x7a\xa5\x91\xba\xb1\x49\xa9\x8d\x6e\x4e\xf8\x36\xa8\xb3\xa0\xaf\x43\xba\xcc\xa6\x1b\x87\xdf\xbe\x75\x05\x51\x27\xd2\x1c\x7c\x0f\xe4\x98\x94\x55\xfd\xa0\x56\xd9\xd1\x94\xf8\xb5\xe8\x4e\xdb\xd2\xd9\x18\x3d\xe4\x3f\xa9\x1b\xfe\x76\x01\x37\xdf\x09\x39\x6c\xe8\x26\x6d\x8f\x4f\x06\x81\x4e\xa4\x62\xbf\xad\x7b\x23\x70\xff\xba\x11\xd0\x47\x5e\x5d\x3c\x4d\x62\x96\x16\x48\x81\x64\xe6\x7c\x72\x07\x11\x21\x1b\xbe\xb9\x71\xd6\xc8\xd8\x8d\x31\xa5\x87\xc1\xae\xc3\xff\x61\x2b\xe1\x6e\xf0\xf6\x61\xdf\x7c\x29\x10\xe7\x8a\x53\xa4\x8b\x5a\x36\x91\x3e\x1f\x2f\xd7\xec\x09\xb1\x1b\x53\x4a\x56\xaf\xbe\xa9\x15\xb1\xec\x87\xc6\xfa\x4e\x5c\x94\x2a\xa1\x82\x54\x2d\xd5\x40\x76\x66\x8c\xb4\xe8\x56\xa4\xc3\xfe\x4f\x88\x08\xee\x21\x68\xd6\x34\x52\x68\x92\x74\x8b\xd4\x4c\x11\x61\x48\x5c\x64\xe2\x05\x1a\x2c\x93\xd3\x80\x22\x14\x46\xf3\x27\x61\x4b\x44\x50\xbe\xf6\x6f\xfb\x12\x28\x06\xa4\x7a\x90\x1b\x0d\x70\x9f\x3d\xf7\xd8\x63\xe7\xce\x02\x77\x64\x37\x62\x5d\x5a\x17\xcd\x38\x70\x60\xc6\x22\x32\xb3\xd2\xd7\xef\x58\xb6\xec\x0e\x3a\xf4\x22\xae\xc5\x8b\xe4\x06\xf3\xd7\x83\xf0\x87\x27\xd4\xdd\x48\xd1\xcd\x04\xe9\x1c\xc8\xd3\x19\x16\x2d\x32\xe8\xe0\x1f\xa2\xef\xac\x07\x73\xd6\xaf\x87\x7b\xe0\x2f\xa5\xc7\xbe\x68\x7b\xb8\x54\x68\x72\xc4\x90\xb3\xaa\x21\x43\x54\x30\x02\x62\xb4\xa1\xf4\xe1\xb6\x2f\x8e\x95\x62\xbe\x0d\xdc\x10\xf1\xb8\xbf\xf5\xa3\xea\xa9\x09\xd4\x9c\x5b\xf5\x39\xc4\x3e\x8b\x28\x5e\x94\xe1\xf6\x30\x01\x61\xea\x74\x76\xea\x61\x76\xef\x9c\xa6\xd8\x80\x02\xc5\x84\x51\x31\x05\x81\x53\x6f\x34\xa1\x56\xa3\x02\x78\xb7\x0b\xd1\x45\x0a\x1b\x16\x92\x4e\x6c\x05\xa2\x6e\x3d\xad\xae\xc2\x98\x06\x7f\x7a\xfe\x03\x78\xb4\xcf\x92\xf3\xbb\xeb\xc5\x92\x3b\xbf\xd8\xbc\xf4\xe3\xd1\xa4\xff\x24\xa6\xeb\x95\xfe\xdc\x2e\x12\x09\x29\xf6\x81\x8f\xd0\x5f\x24\xfc\xe9\x31\x06\x28\xdf\xf5\x7d\xb2\x19\x35\x24\xd3\x8a\x1a\x10\x45\xc0\x9f\x50\x04\xdb\x94\xd8\xd7\x26\xfe\x10\x7e\x0e\x46\xcc\xa9\x1f\x9d\x12\xcd\x38\xfa\xe9\xb2\xcd\x7f\xde\xab\x12\xc6\x60\x28\x31\xd5\xc0\x89\x92\x45\x28\x0e\x1e\xd1\xbb\x92\xdb\x1f\x26\x87\x47\x22\xa6\x54\xeb\x07\xa0\xc2\xb9\x7c\x17\xbc\x1e\xe1\x11\x17\x84\x62\x2c\x69\x1f\xc0\xd3\x28\x06\xb5\xa1\x28\xb6\xaf\x31\x10\xb5\xe1\x38\xaa\xf9\x57\xda\x10\xf5\x99\x7f\x8b\x30\x11\x77\x23\x42\x53\x92\xbe\x47\x58\xbd\x80\x4b\x8d\x7b\x5f\x67\x9f\x53\xa3\x2e\x17\xee\xd1\x84\x36\xf8\x8f\x67\x3f\x7b\x69\xc9\xd6\x9b\xc6\xec\xc1\xeb\xb7\x9b\x92\x81\xe2\xa5\xb6\x97\x76\x3d\xf1\x76\x6c\x54\x52\x61\x0c\x15\x80\xaa\xb3\x64\xda\x81\x03\xd3\x96\xbc\xc8\x94\x0a\x9d\x8f\x5c\x76\x1f\xa7\xa8\xed\x9e\x81\x91\x94\xf4\x55\x83\x55\x37\x0f\x56\xcd\x8b\x20\xfd\x81\x97\x81\x2a\x35\x7d\xd5\x24\x32\x1a\xbf\x89\x75\x43\x30\x1f\x77\xbf\xd2\x87\x41\xeb\xc3\xa5\x91\xce\xae\x07\x43\x0f\x97\x76\xd3\x1d\xea\x45\x90\xe3\x13\xe7\x4c\xbe\x53\x59\x92\xef\x3e\x7b\x06\xba\x34\x26\xff\xe9\x3c\x7a\x71\x9b\x44\xe2\x41\x44\x68\xdb\xe0\xee\xf3\xe9\xe0\x13\x42\xfc\x89\x8b\xbf\x3e\xaf\x7e\xb8\x4d\x6a\x46\x09\x25\xdb\x87\x74\x9f\x5f\x07\x9f\x10\xe2\x4f\x5c\xfc\x27\xf3\x2c\x7d\x83\x25\xf3\x6c\x29\xf1\xe7\x68\xa4\x0c\x7a\x9a\x25\xdb\xba\x5a\x7f\xc0\xd7\xf5\x91\x79\x01\xd4\x49\xa8\x46\xbc\x9e\x5d\xdd\x82\x8e\xd5\x87\x0e\x5f\x06\xee\x27\xe0\x87\xc7\x37\x7e\xbe\x55\x86\x29\x0b\xd9\xfc\x3c\x32\x4e\x28\xc4\x3b\x68\x2d\xf8\x8e\x50\x9f\x71\xc2\x8d\xeb\x5d\xb5\x61\x56\x25\xc1\x17\x3f\x79\x18\xfe\x79\x97\x4e\xb5\xeb\xeb\x4d\x07\x81\xf6\x09\xb5\xf0\xd9\x8e\x8d\x13\x9e\x79\x5b\xa7\x7b\x5b\xc8\x68\xdc\x31\x72\xa3\x23\xdc\x7d\x1e\x42\x2b\x3a\x3e\xcc\xae\x8e\xd7\x85\xa0\xa0\x0b\xa5\x4e\x20\x97\x22\x0a\xeb\xf1\x09\xdc\x96\xd1\xe4\xf5\xc5\x37\x41\xed\x71\x30\xaa\xf8\xb7\xe1\xe7\xea\x74\xf0\x23\x49\x8a\x24\x4f\x2a\x7d\x11\x7e\x14\xa3\xf1\xff\xa4\x8c\xc0\xf5\xa2\x54\x9a\x87\x12\x77\x84\xba\xaa\x44\xcf\x45\x15\x86\x1f\x09\x37\x5e\x14\xa8\x20\x9a\x87\x9e\x00\xd9\x9d\xed\x23\x44\xbe\x28\xbc\x25\xf2\xfd\x4d\xf3\x2a\xf9\x36\x58\x3e\x24\xf0\x90\x9d\x40\x70\x14\x5e\x11\x20\x96\xb7\x93\x0d\xc0\xec\x22\x29\x09\x7a\x41\xec\xe3\x47\xf9\x84\xd6\x25\x0c\x62\xf4\x3e\xa2\x13\x3e\x15\xcf\x54\xb1\x5e\x12\x7d\xb7\xc7\x3b\x11\x81\x0d\xb3\x18\x4f\x18\x83\xb7\xc7\x98\x51\xaa\xb3\x3b\x63\x2d\x2f\x0a\x5e\xef\xe4\x23\x37\x77\xf5\x56\x74\x02\x09\x73\x26\xed\xeb\x8a\x47\x27\x2a\x01\x87\x2d\x23\xc1\xd7\xa6\xc6\x1b\xc0\x8a\xaf\xde\x00\x51\x25\xc4\x00\xc3\x5e\x4d\x27\x70\xdc\x63\x8e\xa2\x22\x07\xbc\xed\x2d\xeb\x57\xf9\xd5\x2b\x2a\x16\x6d\x39\x7a\xe6\x4c\xd4\x8e\xe3\xb8\x70\x91\xa3\xfd\xb8\xa3\x88\x1e\xf6\xed\x9e\x92\x12\xf0\x7b\xc9\x91\x5d\x8f\x7d\x1b\x7d\x1c\xdd\x18\xe9\x28\xa2\x62\xef\xe2\x30\x7d\xab\xc3\x3b\x61\x78\x5d\xc0\x1a\x89\xd3\xd1\x74\x97\x5b\x29\xc2\xc6\x51\xe8\xa5\xda\x40\x97\xd8\x5d\xd0\x05\x67\x89\xd0\x94\x00\x9b\x0b\xbb\xb6\x1e\xa6\x76\xc3\x89\x37\x67\x1c\x06\xea\xe3\xae\x86\xa5\x27\x66\x54\x6f\x4a\x95\x66\xc8\xac\xc6\xec\x22\xa7\x52\xa2\xca\x19\xc3\xdb\x9a\xeb\xcb\xab\x1b\xc7\x84\x02\x13\x2a\x0a\x53\x14\x1f\x3f\x75\x06\xfe\x3d\x39\x35\xd9\x6a\xa4\x55\xde\x21\x39\x46\xe6\xb1\x39\xa7\xee\x6a\x2e\xde\x08\x8f\x34\xbd\x70\x7c\xed\xa0\x50\x89\x7b\x77\xce\x94\x9c\x86\x9a\x22\x4e\x7a\x28\x6d\xdc\x57\x60\x8c\xb5\xb2\x79\xd8\xae\xa1\xc1\xaa\xf6\x60\xc5\xb0\xa2\x91\xcd\x4b\x66\xe6\x3f\x7e\x1a\x46\xdf\xca\x6d\x28\xc8\x91\x58\xc6\x30\xaa\x86\xd9\x73\xe3\x72\xe9\x15\xa8\xed\x36\xa1\xf5\x44\x10\x23\x96\x50\x02\x32\x09\xd1\x3d\x27\xeb\xec\x80\xe0\x8e\xcc\x48\xb4\x11\x01\xa9\x10\xc1\x19\x42\x11\x4c\x22\xce\x2d\x1f\x30\x6a\xe3\x30\x64\x18\xef\x4e\x47\x94\x8f\x98\xf7\xcc\x8f\x72\xb4\x46\x3d\x2f\xbf\x74\xe3\xe4\x1d\x75\x03\x00\xd3\x3f\xc9\x22\x4a\xe2\x75\x2a\xb1\xb8\xa8\x2f\x97\x5e\x5d\x32\x51\x2e\x55\xb5\xac\xb9\xfa\xc8\xd4\xa9\x8f\x5c\x85\xe8\xb4\x7c\xc8\x4f\x87\x11\x59\x07\xa6\x77\x96\x2f\x7f\x07\x5e\xdd\xff\xdb\xe3\x70\xe2\x96\x39\xcb\xdf\xa1\x8b\x1a\x25\x9c\xd4\x9e\xe3\xf6\x05\xf3\x76\xb5\xcc\x1e\x25\x1e\xdb\xc7\xc8\x28\x0c\xfa\x2d\xbc\xa1\x46\xca\x8b\x6b\x42\xbe\x02\x1e\x0e\x89\x65\x82\x4e\x6b\xde\x3d\x76\x75\x50\x33\x37\x1d\x67\x02\xcf\xc1\xab\xef\x2c\x9f\xb0\x09\xec\x7d\xfa\x0f\xfb\x51\xce\xc4\xaf\x4b\x0c\x7f\x4c\xc0\x0b\xd2\x11\x19\xb1\x1b\xb5\x02\x5a\xb1\x04\xec\x3e\xbb\x06\xfd\x3a\x4d\x95\x12\xc2\xda\x4e\x9c\x11\xe2\x8f\x86\xfc\xb0\x8a\x2f\x85\x7f\x22\x5b\x49\x7d\x49\x49\x7d\x7b\x52\xc2\x85\xf0\x77\xef\x75\x0a\xeb\x52\xe3\x5f\x98\x80\xd2\xdc\x4b\x6e\xb0\xb6\x78\x88\x16\x52\x46\x6d\x58\x60\x48\x53\x5d\xc7\xce\x7d\x47\x82\xc5\x9d\x83\x2d\x67\x28\x9b\x4b\x8d\x71\x05\x41\x8c\x85\x4d\xd0\x22\x89\xcf\x03\xf6\xb8\xf6\x08\x71\x70\x6e\x88\x0b\x93\x38\x6f\x7c\x05\x83\x35\x52\xb1\x67\xbc\x89\xf0\xf5\xcf\x31\x3a\x3f\x1d\x02\x4d\x0a\x9d\x4e\x01\x8f\xe8\x14\xad\x0a\x1d\x3c\x82\x2f\x40\x13\xb9\x88\xda\xea\x8a\x01\x55\x3d\x03\x8b\x86\x78\x83\xcd\xdf\x6f\x5a\xb9\x4e\x3f\xe4\x9e\xa7\xef\x19\xa2\xd7\x6d\x18\xf1\x59\x71\x1d\x1d\x8e\x01\xfc\xc3\xfb\x6f\x7e\x5a\xc8\x37\xda\x5a\x5c\xf7\x43\xd1\x9d\xb7\xf9\xa6\x2d\x99\x3a\xb1\x4f\xa6\xa6\x1c\xfd\xd3\x34\xd5\x15\xc7\x75\xa2\xf9\x7f\x90\xfa\x79\xa9\x91\x09\xf5\xc3\x3d\x51\x05\x04\xb4\x0c\x01\x0b\xd0\x57\x5c\x41\x86\x18\x46\x5b\x25\x32\x1d\x7c\xc4\xfd\x95\xe3\x09\xdc\x42\x62\x45\x8d\x36\x52\x4d\xc2\x7c\x75\xd5\xf3\xd9\xeb\x12\xc9\x16\x89\x42\x29\xb9\x7e\x5d\xa2\x54\xa0\x20\x0e\xf4\x88\x89\x1a\x9e\x75\x3a\x87\x19\x4c\xdd\x2a\x7c\x00\x0c\x3c\xa0\xd7\x59\x52\x2d\x66\x67\x67\x7d\xa3\x9f\xfd\xf3\x4c\xba\x62\x9e\x75\xfa\x7d\xce\x61\x4c\x57\xe5\x57\xac\xd0\x88\x52\x3c\x76\xbf\x33\x41\x2f\x56\x4b\x99\x09\xfd\x22\xac\x92\xa0\xa7\x1f\xfb\x84\xf1\xae\x67\xef\xd4\xa4\x01\x94\x08\xcd\xef\x37\xa8\x76\x44\xc8\x89\x10\x88\x0e\xed\xbb\xb0\x6f\xdf\x05\x6e\xe4\xe7\xf7\x47\x43\xe8\x12\x23\xa1\x85\x00\x26\xf3\x04\xeb\x0c\x1a\xf1\xdd\x7d\xa1\xfb\x3f\x47\xe1\x70\x17\x96\x2e\xa6\x63\x46\xa2\xe5\xc2\x78\x0d\x76\xde\x6e\xb0\x4b\x70\x5f\x77\xdb\x7d\x5e\x86\xa8\xbc\xe8\xd0\xac\xd6\xda\x0a\x7f\x08\x80\x1a\x38\x0d\x1e\x44\xff\xa7\x81\x9a\x00\xfc\xa1\xb5\x15\x50\xa0\x0f\x58\x01\xfa\x40\x6a\xce\x25\x11\x05\x43\xad\xe1\xd6\x48\x2b\x83\x4f\xa0\x35\x8a\xaa\x85\xa6\xab\x38\x7d\x11\xde\x83\xe7\x1a\x07\xa6\xcf\x2c\xa6\xcf\x88\xa7\x21\x9f\xaa\x42\x70\xab\x9d\xe1\xd5\xc6\x3d\x8b\xa2\x7a\xb3\x98\xef\xef\x78\xe6\xa2\x5a\x6d\xec\x68\x33\xaa\xd5\x17\x9f\xe9\x40\x7c\xd9\x8f\xc4\x89\x13\xca\x19\xd1\xfa\x97\x37\x46\xc2\xeb\x5e\xe0\xde\x51\x65\x66\xaa\xde\xe1\x5e\x58\xc7\x84\x37\xbe\xdc\xde\x4a\x7c\x36\x81\xf3\x18\xde\xa9\x13\x6f\x2e\xe1\xdd\x39\x82\x34\xe2\xd6\xef\xa7\x13\xde\x4f\xfd\xcb\xb2\x7c\x21\xf8\x2c\x0d\x45\xdb\x18\x28\xb8\x34\x0d\x61\x2b\x94\x5b\x16\x4b\x70\xf5\x0a\x5e\xc7\xc5\x8a\x26\x5e\xc4\xf7\x6a\xee\x44\x74\x68\x29\xf1\xbf\x62\x21\x98\x37\x1a\x32\x41\xc4\xdc\x79\x63\x21\x89\xd1\x24\xa1\xb1\x0f\x79\xb7\x13\xcf\xd5\x12\x20\x44\xd2\x23\x92\x93\x34\x6a\x98\x6f\x48\xd5\xeb\x94\x56\x70\x83\x09\xd1\xc6\xe8\x9f\xd9\xd9\x96\x02\x13\xec\x4f\x27\x47\x6f\xe4\xc2\x15\xa0\x5a\xe3\x50\xca\xe9\x54\x96\x1d\xdb\x31\x3b\xd9\x21\xbe\x2a\xcd\x37\xb1\x8b\xf5\x16\xd5\x0d\x8a\x99\x11\x39\x0c\xa4\x74\xbf\x8e\x2f\x92\xd3\x14\x57\x98\xaf\x98\xc8\xa9\xfe\xf4\x0a\x5a\x65\x11\xc1\x9f\xe8\x6e\xf8\xea\xaa\x9e\xf8\xea\x76\x4d\x4f\x4c\xf5\x76\xaa\x07\x92\x3a\x7b\x5c\xd0\x7e\x4b\xa2\x86\xdf\x10\x89\x1f\xe4\x6e\xc4\xec\x94\xf3\xa9\x6a\x6a\x10\x15\x01\x22\xa0\x05\x29\xc0\x89\xe8\x7c\x6f\xd0\x1f\x0c\x05\x13\xc0\x1c\xb0\x0c\xfc\x17\x78\x1d\x5c\x06\x57\x01\xa4\x15\xe8\xf3\x61\xa4\x34\x17\xc1\x49\x33\x72\x58\xda\x8d\x3d\x31\xbb\x5d\xa2\x00\x09\x13\xa7\x66\x22\x21\x0d\x56\x40\xf0\x1b\x81\x37\x9d\x8f\x81\xeb\xb8\x63\xdb\x99\xc5\x2e\xb4\xd4\xe2\x83\xb4\x15\x00\x23\xe2\x9d\x8d\x42\x8e\xac\x93\x38\xa9\xc6\xd8\xed\x78\x71\x11\x3b\x16\x0b\xeb\x5b\x93\x2f\x36\xed\xe1\xbd\x50\xc4\xc6\xe1\xa9\x2e\x08\xb0\xf8\xc7\x5d\x1c\xf0\xc4\x9e\x43\xab\x3e\xbd\x95\x31\x61\x80\x25\x17\x4f\x30\x96\x3c\xac\x3b\x03\xc3\x2c\x05\xbc\x41\x06\x5b\x77\x99\x04\x91\x2a\xe0\x0d\x58\x0b\x15\x95\x18\x27\xf2\x06\x81\x95\xdc\x21\x28\xa8\x0e\x3d\xef\x17\xde\x69\xc0\xa8\x7d\xa8\x80\x26\x3f\xd0\xe3\x23\xae\x19\x5e\x24\x09\x5e\x14\xd1\x32\x29\xdd\x6d\x34\x15\xa1\xda\x73\x44\xd1\xc2\x45\x7c\x67\x99\x50\xc3\x14\x62\xbb\x32\x00\x03\x40\xfc\xbf\xfc\x44\x00\x71\x1e\x3e\x91\x89\xb4\x93\x15\xcb\x6e\x03\x2e\x2a\xe6\x3f\xc1\x57\xcc\xb8\x78\x9f\xc8\x28\xc4\xbb\x38\xf4\x73\xfb\x44\x0e\xc1\x8d\x89\x53\x44\x3c\x5c\xa3\xf4\x22\x1e\x15\x80\x35\xf9\x33\x50\x73\x14\x07\x41\x39\x30\x90\x37\x13\xcc\x40\xb7\x52\xec\x10\xb9\x95\x0c\x46\xc3\x71\x0b\x31\x78\xc1\x6f\x64\xfc\x18\x59\xd0\xa5\x04\x26\xe1\xf3\x10\x85\x5d\xfc\x14\x62\x12\x8c\x04\x6e\xca\x81\xca\x64\x62\x89\x8b\x7a\x11\x79\xc6\x61\x28\x72\xe2\x6a\xf1\x7e\x9f\x00\x97\x87\x7d\x40\xa2\xac\x38\xbf\x80\x0d\xab\x17\x8a\x09\x3e\x15\xbb\xb4\xc9\x3e\x1a\x34\xa4\xa0\x4a\x15\xf3\x2e\x5d\xb2\x0f\xd0\xc3\x52\x8c\xc6\x52\xc5\xa8\xf4\xbc\x81\x9b\x0b\x32\xf3\xdb\x17\x2a\x46\x0a\x41\x0f\xfd\x36\xc8\x72\xa4\xa4\xfb\x5d\xc5\x16\xae\x65\x48\x7d\x4b\x4b\xdb\x94\xbf\xad\x4a\x99\x7f\xfb\xd2\xa1\xf4\x4f\x62\x1d\x0f\xc6\x86\xfd\x05\x8d\xc6\xe8\xd0\xe8\xef\x4c\xa3\x0a\x47\xbe\x0c\x68\x4e\x27\x16\x25\x2b\x53\x78\x89\xcc\x92\x6a\x55\x98\x2c\x0e\xb3\x56\x2f\xe3\x7d\x8d\x32\x89\x44\x35\x98\x4e\x77\x59\x38\x85\x47\xc9\xd0\xd2\x2c\xa9\x4a\x65\xaa\x06\xc1\x05\x16\x9b\x41\xac\x1e\x68\x2a\x63\x18\x9a\xe5\xb9\x94\xc2\x82\xa2\xcc\x15\xf9\xe5\xd3\x77\xde\xa1\xcf\x2e\xb6\x07\xe5\xf4\x30\xe0\x9b\xdc\x7b\x44\x06\xe0\x78\x96\xa6\x01\x53\x66\xaa\xd1\xa2\x89\xc3\x32\xbf\x77\xff\x24\xa5\x46\x96\x2d\x01\xac\x3a\x57\xc1\x59\x5c\xe9\xf4\x10\xa5\x44\x2c\x6f\xf4\x49\x79\xa0\xd7\x9a\x1d\x16\x93\xd2\x6e\x4e\x91\x49\xc5\x16\x85\x09\xfe\x2c\x69\xb0\xb2\x29\x16\xbd\x6d\xb0\x23\x59\xd1\xc7\xaa\xe0\x98\x12\xaf\x6a\xa0\x55\x99\x2d\x33\x18\xd5\xd6\xeb\xaf\x59\x1b\x24\x76\x9d\x25\x25\x33\xb5\x5a\x91\xec\x70\xaa\xbc\x01\x56\xf2\x92\xb2\x97\x2e\x23\xcf\x63\x4e\x66\x2e\x8b\x35\x0c\xa3\xd0\x64\xe6\x82\x24\xd8\xf6\xed\x43\x0f\x7d\xfb\x90\x7f\xe6\x2c\xc0\x4b\x53\xd7\xa6\x49\x58\x0e\xfe\x24\x66\x58\xfa\x02\xcd\x8a\x44\xb2\xf4\x4d\xf0\x5e\x75\x56\xa9\x4a\xcb\x30\x52\xae\xef\xeb\x8c\x73\x03\x30\x3d\x74\x02\x18\x0e\xda\x19\x40\x6b\xaa\x54\xe6\x12\x6f\x1a\xc7\xf2\x52\x5a\x24\xe1\xe5\x62\xb5\x58\xc7\xce\x2a\x65\xe5\x56\xb5\x45\xc4\xfc\x57\x12\xed\xcf\xcf\x95\x8b\x35\x92\xb2\x54\x30\x94\xd1\x54\xbb\xb3\x6e\x6b\xe4\x1c\xeb\xfc\xde\x91\x0a\x13\xfb\xdb\x37\x26\x1f\x9b\x24\x32\xd1\x69\x12\x79\xae\x54\x07\x68\x46\x37\x82\xd6\xd3\xd3\xe0\x13\x75\xf5\x62\x71\x65\xe8\xfc\x79\x00\xd8\x23\x6c\x92\x52\x07\x18\x95\x2a\x5b\x29\x49\xa3\xd5\xf2\xf7\xfe\xeb\x4d\xba\x89\x6b\x5c\x9e\xed\xea\xab\x61\xa4\x23\xbd\xfe\x75\x5b\xd5\x4e\x5e\x92\xac\x33\x56\x71\xac\xd7\x90\x10\x6e\x4c\xa9\x94\x28\x1c\x76\xcf\x5c\x8e\x1b\x91\x9e\x10\x66\xab\x54\xe2\xbc\x14\x47\x51\x8e\x49\x37\x70\xe6\xcc\x3d\x33\x3f\x9a\x9b\xd7\xa7\x77\x8d\x28\x73\x6e\xfb\x15\x59\x9a\x49\x53\xb2\xa0\x1f\x4d\xe7\x67\x27\x27\x67\x15\xd0\xcc\xc1\x61\x46\x6d\x9a\x4c\x2a\x31\xa6\xa6\x4a\xa4\x4a\xbd\x32\x55\x2c\xb7\xa0\x4f\xa6\xaa\xa1\xa5\x7d\x7d\xae\x9c\xa0\x5d\xe3\x94\x26\x6b\x39\x2d\xc3\x02\x0e\xc8\x44\x99\x8c\x88\xa5\xed\x69\x19\x2d\x25\xab\x7d\x6a\x53\x2a\x30\xab\x93\x94\x8c\x92\xf6\x58\x58\xad\xa7\xcc\x57\xa3\x10\xab\x14\x62\x25\xb3\x1a\xfe\x63\xf8\x9d\x52\x1d\xa3\x4c\x52\x29\x95\x96\x24\x4d\xf1\xea\xd2\x16\x87\xcd\x4e\x4b\xe9\x2c\x4e\x8e\xf2\xe1\x18\x94\x63\x92\xd8\xa5\xb1\x55\x64\x66\xf9\xfa\x49\xe8\xc2\x24\x15\xea\x44\x16\xb9\xc4\xa2\xd6\x2a\x24\x52\x8b\xd5\x20\x66\x9e\x4c\x4d\xb6\x4d\x75\xae\x4c\xd5\xb1\x4b\xb3\x37\x96\x29\x6c\x4a\x65\x68\x9a\x5a\x25\x05\x8b\x56\x31\xd5\x9b\x0a\xa7\xda\x92\x53\xb5\xac\x2e\x75\xe5\xd6\x34\x65\xd9\xc6\x6c\x91\x4a\x3d\xb5\x52\x53\xb9\x6a\x3e\x8b\xda\x72\xf4\x6c\xc6\xed\xda\xae\xd3\xf2\x62\xfd\xfa\xde\x34\xbd\xfe\xd8\xe2\x25\xc7\x8e\x2d\x59\x0c\x5d\xa8\x23\xa6\x2c\x45\x83\x4a\xc6\x0c\xe8\xf3\x12\xdb\xd8\x88\x9a\x5d\x3f\xbc\x81\x53\xd1\x67\x7a\x2d\x4b\x16\x8b\xb4\xea\x3d\xa9\xf4\x3a\x93\x62\xfb\x9b\x81\xc2\xd7\xf7\x2b\x0c\x34\x83\x41\x7c\x68\x1e\x8c\xc9\x46\x43\x52\xac\x28\xe4\xc4\x22\x0e\xbb\xb6\x04\x12\xbd\x46\x27\x63\x68\xa0\x29\xad\x90\x88\x3d\x0a\x45\x6a\x06\x6a\x96\xe8\x06\xa5\xba\xff\x52\x99\xdc\x37\xdb\xef\xab\xa7\xe9\xde\x57\x2a\x4a\x16\x94\x17\x6f\x99\xc4\x4a\x80\x88\xd6\xea\x4c\x32\x85\x6c\x58\x9f\xf4\xb3\x06\xc3\xee\x42\x87\x91\x61\x0c\x96\xde\x61\x90\xef\xaf\x72\xd9\xc1\xa0\x3a\xd4\x7f\x92\xf4\x5a\x96\x63\xc5\xaf\x4d\xe8\xb5\xcd\x3f\xdb\x27\x97\x2d\xeb\xa7\x56\x16\xa2\xe2\xd7\x0b\x3c\x43\x1f\x09\xe0\x5e\x25\x9c\x79\x2f\xe2\xcf\xbb\x9b\x96\x02\xb0\xa2\x76\xf5\x16\x59\x59\x4c\x92\xf8\x20\xe7\x41\xa7\x0c\x0f\xcf\xfd\xbd\x69\xcb\xa4\x49\x5b\xa2\x8b\x26\x6d\x69\x6a\xda\x12\x1d\x53\x3a\x7b\xf3\x1d\xbf\x3d\x0b\xdc\xa0\xf4\xd2\xd6\x3f\xdc\x33\x29\x8f\xc9\xee\x3f\x67\xd5\xa0\x17\xa7\xa5\x4e\x1c\xdf\xd4\xcf\x25\x1f\x72\x00\x9e\x7c\x04\x5e\xb9\xf2\xea\xba\x45\xd5\xd5\xf6\xfc\x1c\xfc\xd0\x24\xf2\xe8\x24\xae\xb0\xf7\xe8\x5a\x6f\xa6\x49\xc9\x49\x4d\xb6\xfc\x92\x01\x43\xa7\xcd\xa9\x3c\x34\xc6\xbb\x78\xe2\xf4\xa1\xf5\xbd\xbd\x69\x6a\x86\x56\x5b\x8b\xbd\x03\x7b\x0d\x0f\x0c\x8d\xeb\x1c\xc4\xfc\x72\xa5\x11\x54\xd0\x5a\x6a\x06\xf6\xe6\x42\x75\xf7\x54\x84\x11\x1d\xbb\xc1\x34\xeb\x8a\x10\x2b\x82\xf8\x76\x34\xcf\x7b\x59\xb2\x58\xe4\x3b\xc5\x09\x58\xf9\x86\xb6\xb1\xda\xb8\xcd\xb3\xce\x20\xe8\xdc\x09\x20\xd7\x88\xeb\x8f\x5f\xb9\x6c\xa2\x9e\x58\x88\x6c\x16\x7c\x02\xbe\xf7\xd9\x86\x0d\x9f\x81\x62\xd0\x00\x8a\x71\x28\x3a\xf7\x66\xa4\xe7\x85\x6a\xb5\x4d\xad\x06\x2b\x67\xd5\x3a\x52\xc9\x12\x3f\xd5\x31\x54\xb0\x6c\x8e\x9b\x4a\x7f\x40\xa2\xd7\xbf\xb4\x9e\x9c\xcf\xc1\x2b\xe7\x98\x26\x97\x39\x12\x8e\x03\xaa\x73\xad\x1b\x3e\x83\xef\xf5\x78\xdb\xef\x6e\x81\x0b\x1d\x1d\xac\x86\xf8\x5d\x6d\xea\x50\xad\xcf\x51\xa6\x59\x88\xe5\x05\x0b\x35\x65\x0e\x1f\x53\xdb\xc3\x30\x1b\xfe\x20\x88\xd3\xc6\xaf\x5f\x3f\x5e\x08\xed\x3a\x77\x2e\x72\x17\x4d\x50\x11\x09\x54\x6f\xdc\x9e\x4c\x22\xe0\xca\x9b\x08\x5f\x87\xd7\x62\x5e\x8d\xa3\x47\x53\xf8\x08\x37\x65\xe8\xa9\x5a\x55\x64\xe4\xc3\xd7\xc3\x3c\x5a\x8b\x69\x95\xd7\x88\x12\x3c\x4f\x6c\xe4\x6b\x7d\x13\xaa\xae\xb5\x56\x4d\x98\x50\xc5\x87\xaa\x26\xf8\x6a\x59\x0a\xf3\xb2\xd1\x56\x10\x16\x04\xfa\x11\xc1\xf6\xfd\x08\x0c\xfb\x6a\x8f\xe0\x64\x0c\x49\x7c\xa4\x96\xea\x51\xa6\x94\xce\x32\xc5\xe4\x11\x3d\x8a\x60\x48\x06\x37\x15\x15\xb1\xf5\x1c\x45\x13\xfb\xa0\xc4\x52\xf4\x28\x22\x2a\x0e\x45\xb7\xd6\xfa\x7a\x14\x21\xda\xd4\xbd\x8c\xc0\xf6\x7f\x51\x1e\x06\x2d\x6d\xff\x7f\x2a\x0f\x8d\x38\xd2\xff\xb3\xf2\xd0\x9d\xe5\x31\xa1\x51\x4b\xfd\x4f\x4a\x22\xfe\xf5\x52\x30\xff\xd6\xfb\xb1\x2c\x89\x63\x57\x22\xba\x61\x21\x28\x9e\xe8\xb5\xba\xb8\xab\x4c\xe2\xd1\xc4\x15\xf3\xfc\x6e\x62\xe7\x12\xf7\x1f\xeb\xde\x96\xea\x93\x4e\x26\x17\xc8\x4e\xc1\x33\x3a\xb3\x5c\x9e\x99\x29\x97\xa7\x68\xc1\xf7\x56\x77\x26\xcc\x40\xd1\xb5\xe8\x36\xf8\x1d\xba\xc7\x69\xb2\xb9\xb6\x6c\x0d\xa7\x13\xf0\xab\x19\x2c\xeb\xc3\x3e\x0a\x6c\x06\x8c\x58\xa5\xd1\xdb\xd1\xd1\xe6\x16\xd9\x1d\x3e\xaf\xcd\xa7\x41\x47\x4d\x31\x09\x9b\xfc\xe8\x0e\x13\x82\xad\xe1\x30\x08\x85\x42\xf0\xc7\x96\x16\xf8\x63\x28\x04\x42\xe1\x30\x6c\x45\x67\x75\x4b\x0b\x50\x87\xb8\x70\x1b\x6c\x0a\x47\xdb\xda\xc2\xbb\x76\x85\xdb\x68\x5b\x18\x1c\x21\x41\xa1\x39\xe3\x76\x0d\x71\x6f\x0f\x39\x04\xf5\xa2\x17\x91\x9c\x62\x5c\x18\xa2\x88\xa4\xc1\x23\x15\x9d\x7d\x76\xce\x40\x9c\x30\xfb\x34\x3e\x87\xc1\x89\x0a\x42\x34\x5a\x51\x29\x89\x3f\xdd\x98\xc1\x3a\x3e\x13\xfb\x75\x83\x18\x8d\x58\x18\xee\xa0\x20\x76\x6e\x1b\xe6\x28\x80\xb1\x7a\xb1\x48\x45\x84\x7e\x1d\xc2\x19\xa2\xd8\x08\x4a\xc5\x84\xb1\x73\xd4\x28\xea\xc1\x37\x50\x7a\xec\x0b\x58\x78\x8a\xa5\x40\xdc\x3f\x6e\x3b\x16\xfa\xa3\x08\xc1\xe7\x03\x0e\x45\x29\xd2\x83\xc2\x34\xee\x45\xf8\x01\x4a\xc0\xce\x41\x15\x43\x75\x4a\xeb\x94\x11\x79\x63\x3e\x2c\x46\x75\xaf\x55\xf7\xba\x69\x1c\xf1\x1a\x82\xc4\x5a\x3a\x0c\x5e\xa7\xbd\xab\xaa\xd8\x7b\xb0\x1d\xfd\x50\x3f\xf3\xd9\x63\x59\xa1\xd5\xb8\x4f\x42\xea\x8a\x6b\x82\xfe\x84\xa2\x33\x58\x74\x84\x35\x9e\x50\xad\xa3\x54\xb8\x1d\x45\x72\xe8\xd7\x81\x6e\xa0\x2a\x08\x7e\x29\x70\x44\xfc\x11\x86\xc0\x18\x0b\xcf\xe2\x1f\x4d\xce\x30\xe6\x1c\x98\x1c\x3b\x62\x4d\x41\x93\xed\x8f\xa8\x70\x07\xb5\x5b\xec\x9d\xb8\x01\xba\xd6\x82\x1a\x8c\xef\x09\x34\x89\xa3\x03\x5d\x88\x4c\x76\xdc\x6b\x79\x96\x8a\x34\x61\x00\x14\x2e\x94\x59\x42\x5c\x14\x83\xdb\x55\x45\x2f\x14\x35\x00\x1b\x6c\x12\x62\x4b\x32\x23\x4d\x25\x03\x1a\x50\xa4\x8a\x4a\xb4\xb5\x11\x11\xbf\xca\x14\x76\x02\x57\x01\xfc\xce\xb8\xf4\x03\xd3\x6e\xec\x70\xb1\x9b\xa5\xd0\xf2\x6b\xa9\xf2\x17\xe5\xf0\x27\x60\xeb\x40\x1d\xbb\x04\x9c\xc9\xb4\xbc\x60\x69\xca\x8c\x50\xf1\x57\x03\xea\x9a\x14\xa5\x38\xc4\xa0\x0e\x01\x6c\x99\x25\xcc\x11\x74\xaf\x09\x25\xca\x8c\x15\x02\xf7\x53\x51\x02\x7e\x56\x12\xfa\xa6\x95\xd4\x70\x6a\x2a\xb1\xba\xec\x04\x24\xf4\x77\x86\x8d\x5e\x23\x47\x9c\xa5\xa0\x31\x69\xc0\xe0\x10\x36\xa7\x0f\xe3\x7d\x17\x93\xf5\x22\x76\x77\xe5\x22\x96\xcc\x01\x62\xba\xe6\x13\x3c\x6e\x63\x3f\xa4\x1a\xfb\xcd\xa6\x4e\xfc\xfd\x69\x26\xb1\x74\xff\x7e\xa9\xd8\xa4\xb0\x9a\x18\xf9\xd6\xad\x8c\x0c\x98\x3a\x66\x7e\x59\xd7\x67\xce\x6d\xbe\x2d\x59\xd9\x60\x00\xfd\xce\x94\x69\x73\x56\xac\x98\x33\x6d\x4a\x41\xb3\xc5\xb2\xe6\xf9\xc9\xb9\xb9\x93\x9f\x5f\x33\x8d\xa9\x19\x59\x55\x1a\x6a\xa8\x42\xec\x24\x2c\x05\x7f\x19\x38\xb1\x3b\x44\x51\x71\xb1\x93\xa3\xb7\xd1\xdc\x93\x45\xe9\x2c\x58\x0b\xd8\x36\x50\x0c\xdf\x2b\xab\xe9\xd5\xa2\x52\x03\x60\x5f\x50\xcc\x8b\x27\xbf\x34\x59\xcc\x7b\x5b\xe4\x2a\x9a\x16\x65\xd6\x37\x2d\x6e\xaa\xcf\x14\xb1\x77\xf9\xfb\x72\x8c\xb8\x8f\x27\x50\xc5\xa0\x75\x77\x0d\xe3\xef\x86\x3f\xc4\x75\xb6\x13\xc6\x3a\x30\x53\x1e\x2a\x88\x7b\x80\x12\xf1\x1f\x19\xa8\x92\x1a\x3f\x45\x3c\x9f\x79\x88\xeb\x4e\x1b\x0b\x88\x21\x37\xb1\x50\xd5\xb2\xa8\xb6\x41\xfa\x26\xab\xa9\x31\xb3\x36\x6c\xa0\x27\x6f\x98\x35\x0b\x8c\x3d\x04\x7f\xba\x7f\xd9\xe5\x43\xe3\x0f\xa1\x6f\x1c\x04\x4a\xda\x32\xff\x85\xbf\xad\x87\x7f\x78\x0a\x5e\x7e\xf2\x09\x90\xfd\x04\xc8\x5b\xfb\xf3\x0b\xf3\x41\x63\x62\x2d\x81\x9b\x7e\x36\xeb\xd5\x3f\xbf\x8a\xfe\xb2\xa2\x03\xb3\xc0\xfb\xf0\x75\xf8\x13\xca\xe1\xf2\xb2\xfb\x81\xf2\xd0\x21\x58\xb7\xf5\xe7\x87\x9a\x1e\x80\x1f\xbe\xf4\x18\xfc\xf8\xf8\xb4\x47\xbf\x63\x44\xdd\x71\xb0\x98\x6e\xbc\x1a\xe2\x2d\xb9\x1e\xb4\xfd\x26\xfc\x68\x83\xa3\xcb\x80\xcd\x48\x70\xfb\xba\xb0\xa9\xc2\x3a\x45\x47\x2b\x96\x6e\xb2\x21\x85\x2e\x3c\xa1\xaa\x83\x90\x7a\x16\x4d\x07\x68\xec\xc4\xef\x1d\x39\x12\x8f\x6c\xc2\xc9\x62\xd1\xec\xa0\xae\xc4\x13\x40\xf0\xc8\x91\xf8\x9d\x70\x2c\x2e\xe6\xef\x55\x8c\x69\x37\xd6\x65\xf5\x51\xe5\xd4\x08\x6a\x2e\x96\xc5\x60\x29\x1d\xc6\x91\xd7\x74\xca\x7f\x3b\xa5\xbe\x68\xf9\xdd\x79\x41\x50\xc6\xe3\x49\xd8\xb8\x4c\x4b\xd8\x71\x21\x8a\x85\xfe\x22\x93\x95\xe5\x7a\x46\x88\x5a\x11\xed\xa4\xae\x63\x0a\x4a\x81\x67\x95\x15\x99\x34\xe1\xc2\xda\xc9\xec\x46\x37\x65\x56\x28\xa1\x81\xcc\x60\x7f\x31\x4c\x5e\x35\xd9\x00\xfe\x42\xb6\x0f\x2b\xaa\xf2\xf3\xab\xf2\xd9\x1d\xe3\xef\xda\xbd\x61\xf7\x5d\xe3\xfb\x2d\x9c\xda\xcc\x6a\xeb\xb4\x6c\xf3\xd4\x85\xfd\x3a\xa8\x5b\xc5\xb2\x21\xec\x7d\x21\x1a\x62\xc2\x28\xcb\xf6\x9f\xbb\xe0\x89\x38\x19\x7a\x29\x09\x95\xf6\xef\x5f\x4a\x02\xea\x7c\x9c\x7d\x64\x52\xcd\xe2\x2a\xbb\xbd\x6a\x71\x8d\x6c\xdb\xfb\xcf\xbd\xc4\xdb\xed\xfc\x4b\xcf\xbd\xbf\x4d\x76\xcb\xd8\x44\x19\x67\x1e\x35\x08\xf5\x5a\x35\xcd\x1b\xb5\x71\x95\x87\x2e\x17\x5c\x6a\x6d\xc0\x45\x6b\x12\x36\xf1\xc9\x6d\x10\x64\x7c\x76\x34\xa6\x4d\x56\x6c\x71\xa7\x64\x0c\x76\xd4\xb5\xdd\x1e\x94\x84\x0b\x5f\x3c\x72\xe4\xa2\xd0\x26\xa4\xc8\x4d\x9d\xd7\x9c\x60\x4f\x79\xe7\xa0\x1d\x8b\xfa\x45\xa8\x7e\x8b\x76\x0c\xd2\x99\x4c\x3a\x7c\xc5\xc6\xaf\xb8\x30\xec\x80\xf3\x67\xcd\x82\xf3\x61\x47\x02\x3a\x13\x07\x76\xa2\x11\xb1\x13\x70\x09\x28\x4d\xbd\x53\xd7\x3c\xfd\xd3\x86\x0d\x3f\x3d\xbd\x26\x95\xb7\x67\xda\xf9\xee\x97\x89\xb2\xd5\x3c\x32\x1f\xfd\xcf\x6a\x98\x03\xec\x7a\x93\x1d\x9b\x4e\xd3\x6e\x07\xaa\xdf\xbf\xac\x56\x5b\x84\x92\x30\x3f\x48\xaa\x17\x6c\xab\xfb\xba\x6e\xdb\x82\xea\x7f\xbf\x26\x55\xc1\xf2\xf6\x3e\xeb\xfe\x7a\x72\x4d\x5a\xda\x9a\x93\x7f\x5d\xd7\x5d\x2e\x8c\xcb\xde\xeb\x3f\x2b\x3b\x83\x7a\xbb\x03\x8d\x83\x7f\xa7\xe8\x23\x98\x91\x23\x4a\xfd\xcf\xcf\xf8\x7a\xc6\xf3\xfe\x7f\xbf\xe4\xe7\x9e\x7e\x3a\xa2\xdc\xfe\x76\x76\xf6\xdb\xdb\xbb\xf7\xa7\xfe\xff\xbb\xfe\x24\xe2\xed\xae\xff\xac\x33\xdd\x31\x9b\x7e\x65\xf6\x1d\xff\xbb\x8e\xe4\xdd\xb9\xd3\x2b\x74\xa1\x84\xef\xa0\xa2\x4a\xb1\x47\x3b\xae\x07\x49\x09\x04\xc5\x01\x8f\xd8\x6d\x57\x8a\x79\xab\xd8\xa4\xeb\x71\x97\x6b\xeb\x2a\xf9\x64\xc6\x9c\x5e\x56\x58\x5f\x3c\x3a\x37\x27\x27\x77\x74\x71\x7d\x61\x59\xba\x99\x61\x23\xb7\x8a\x9d\xdc\xf5\x54\x48\xab\x0c\xe3\x33\x3a\x84\x02\xcd\x23\x1b\x43\xb5\x79\x95\x56\x8b\xc5\x5a\x99\x57\x1b\x6a\x1c\xd9\x1c\xb8\x55\x1c\xd6\x95\x89\x3f\x94\xa0\x3b\x41\xa1\x59\x7c\x16\xfa\x2e\x64\xb7\x37\xe6\x52\x5d\xe3\x16\x02\xa8\xd4\x26\xbc\x4f\x44\x68\x3c\x2a\x7a\x40\xe7\x8f\x01\x8e\x09\x69\xdd\x89\x41\x77\x11\xf1\x05\x4e\x0e\xe8\x41\x02\xd2\x25\x4c\x0a\x40\xa8\x76\x91\x49\x30\xe3\x63\xd0\xe2\xc8\x16\x2a\xf0\x54\x91\x83\x03\xf8\xdd\x2e\x33\x8d\x96\xc5\xd2\x39\x52\x12\x5b\xe4\x56\x4a\xd0\xa9\xb2\x88\x13\x0f\xaf\x2c\xad\xea\xd5\x9c\x9e\x62\x9b\xba\x4d\x31\x57\xd4\x52\x1f\x0d\x0f\x9f\x03\xdf\xab\xdb\x3e\x45\xc6\x89\xb6\x4e\x2c\xf6\x0c\x60\xc3\xb5\xbe\xf0\xf8\x82\x3e\x55\x1e\x38\xcc\x7a\x02\x9f\xdb\xf2\x1d\xf0\x92\xbb\x02\x2f\x7b\x93\xb3\x32\xc0\x33\x19\x59\xbf\xe0\x68\xdb\xed\x99\x95\x62\xba\xca\x13\x5e\xe1\x1d\xc4\x81\x70\x51\xba\xbf\x90\xbf\x7b\xea\x2f\xde\x52\x58\x97\x94\x5f\xdf\xb2\x64\x38\xc8\xac\x99\xde\x36\x65\x3b\x98\xb8\xce\xd0\xb7\x6b\xaf\xa7\x09\x7d\xe3\x42\x0a\x03\x72\xe1\x66\x71\x08\xb6\x20\xc9\x20\x0e\xc2\x08\x48\xcb\xa0\x66\xf1\xc5\xac\x44\x1c\x09\xe7\xce\xb6\xf0\xe3\x25\x12\xcf\x08\x2c\x99\x1b\xc4\xac\xfe\x84\x6d\x0a\x3f\x73\x78\x5c\x95\xad\x6a\x5c\xd5\x01\x57\xc8\x57\x8b\x55\x71\x43\xf4\x53\xe9\x7e\xbe\x8e\xab\x12\xe2\x6d\xcf\x6c\x59\x94\xa6\x33\x4d\xd9\x3e\xf3\x1e\x71\x9d\xf2\xf6\xa1\xd1\xfa\xde\x73\x33\x60\xd8\xbb\x6f\xd6\xe0\xa2\xed\x53\x4c\xba\x34\x2e\x5c\xe5\x89\xb6\xd0\x6a\x6c\x1e\x1a\xfd\xf1\x06\x75\xd6\x5b\xeb\xcb\x49\x87\x94\x37\x37\x1d\xec\xb5\xa5\x80\x9f\x88\xdd\xe8\x8f\xf1\x04\xf4\x0e\xcf\xeb\xfd\xcb\xd9\xed\x53\x34\xa2\x6d\x33\xa1\x32\x33\x07\xce\x19\xd2\x1c\xc8\xa7\xa9\xea\x91\xb3\xf6\xa5\x83\xa7\xa7\x6c\x67\xcb\xe3\xfb\x40\x82\x0e\xb0\x0b\xcd\xa2\x03\xa9\xc9\xd8\x8f\x31\x87\xd7\x57\x82\x98\x25\x60\x17\x54\xc6\x3b\x91\xa6\xb9\x98\xba\x12\xcf\x89\x18\xcc\x7f\x0a\xf0\x45\x78\x43\x86\x74\x19\x9e\x23\x18\xbd\x38\x2a\x08\x18\x67\x1c\x96\x9a\x33\xc4\x30\x47\x02\x78\x7b\x92\x21\x77\x05\x1b\x7f\x3e\xe6\xbb\xa2\x1c\x78\x89\x69\x24\x16\xf4\x70\x6c\xe1\xc9\xa3\x15\xa6\x60\x0d\x07\x3b\x66\xed\xdb\x37\x6b\x41\xee\xc0\xb1\xfb\x66\x79\xf2\xe8\xc5\x68\x00\xef\x9b\x33\x12\x3e\x3e\xee\xee\x83\x47\xad\x19\x55\x1e\xb3\x1e\x34\x14\x56\x80\x10\x0e\xc1\x4f\x2d\xda\x1c\xb5\xba\xa2\x48\xaf\x05\x4d\xd6\x8c\x6f\xa3\x4b\x93\x8c\xbe\xda\x3c\x27\xad\x8c\x92\x15\x29\x6d\xba\xea\x99\x3f\xa7\xa1\x06\x0c\xcb\xf1\xa3\x25\xe8\x7b\x5b\x32\x70\xbb\x97\x16\xf7\xf5\xb8\xe0\x3b\xe1\xed\x85\x3e\xce\xba\xa4\xaf\x4b\xba\xef\xc2\x3e\x8d\x65\x7d\xfd\xac\x7d\x9a\xbf\xee\x9b\x15\x9d\xda\xb8\xd5\x30\xc2\x44\xbf\xd5\x7f\xa0\x32\x60\xf7\x54\x49\x0f\x48\xeb\x8b\x6e\x50\x28\xb0\x41\x21\x36\x1b\x9c\xc6\xa2\x90\xe4\x88\x32\xc0\x68\xae\x89\x6b\x7d\x99\x55\xca\x33\xa1\xda\x59\xb5\xb3\xde\xac\xc8\x99\x1e\xa1\x74\x23\x64\x7d\x73\xe9\xfb\x7c\xb5\xab\xed\x85\xf0\x92\x27\xd8\xcf\x73\xfe\x7c\xbf\x5c\xf1\x50\x5f\xf6\x00\xcd\xf6\xce\xbe\x47\xd6\x83\x19\x04\x1f\x0f\xf5\x24\xd0\xe9\xc4\xaf\x1c\x38\x3b\x99\x15\xfc\x11\xdc\x42\x18\x68\x8a\x51\xd7\x22\x2c\x17\xc6\x98\xc5\xe0\x86\x06\x7b\x0c\x35\xc9\x6b\x27\x5a\x15\xb1\x55\x01\x1e\xd6\xb8\xdf\x9a\x38\x8c\xce\x1c\x13\x7e\xad\x29\x9f\x97\x41\xf7\x5e\xda\x52\x0f\xc3\xf5\x2d\xf0\x8b\xe8\xa7\xf5\x2d\x8f\x2e\x03\x0f\x66\x47\x1b\xa6\xee\x16\x57\xb6\xd4\x8b\x5a\xc7\x47\x7f\xeb\x0e\x45\x2a\xcd\x2e\x46\xad\x91\x7a\xd3\x98\x50\xa4\x15\x85\xc5\x03\xf2\xe8\xf0\xd8\xcc\x12\x2e\x24\x2d\x4a\x83\x7d\xab\x26\xa0\xb1\x5c\xa8\x56\x80\xf2\xa4\x54\xac\x54\x6e\x76\x89\xa8\x92\xc2\xc8\xdf\xee\x3f\x03\x0f\x61\x8f\x2f\x27\xef\x6e\xa9\xb7\x2d\x7b\x34\xbc\x79\xca\x90\x19\xb6\xfa\x96\xeb\xad\x60\xca\xa1\x35\x8c\xa2\xd8\x65\xb6\x39\x3c\xfa\x34\x97\xcd\x65\xce\x55\xe6\x96\x95\x64\xaa\x54\xad\xa9\xce\x09\x55\x36\xb3\x8b\x3f\xac\xf0\xa4\xbc\x41\x04\x58\x02\x26\x1e\xe6\xed\x8a\xa8\xc5\x98\x66\xa1\x35\x3f\x1a\x4d\xe4\xe0\x8f\x41\xbc\xa5\x80\x18\xd4\x1b\x36\xa8\x65\x62\x90\x24\xd8\x64\xc9\xc1\x60\xed\x74\x07\x13\x07\x93\xd2\x25\x04\x51\x83\xe9\x70\x33\x15\x05\x80\x60\xa8\xc7\x73\xbe\x62\x33\x08\xc4\xc1\x4e\x18\x87\x0e\x07\xc1\xbb\x83\x6e\xd3\x4d\x53\x70\x8b\xf9\x55\xe3\x35\xeb\x47\x0d\x5b\xa7\x1f\x36\x43\xbf\x6e\xd8\xe8\x8d\xca\x71\xcb\xf9\x95\xd2\x80\xb1\x20\xbd\x30\x79\xe6\xbe\xd2\x22\xc8\x55\x8f\x28\x74\x95\x4b\x1e\x5c\xb3\x53\x52\xee\x2a\x08\x31\x1b\xcc\x53\x24\x41\x57\x7e\x15\xb3\x98\x67\xc5\x53\xc5\xc5\x76\xfa\xb9\xec\x74\xd0\x51\x52\x5b\x8c\x86\xea\xd9\xd0\x00\x86\x0d\xe5\xbb\xcb\x25\x8b\xcd\xfb\x98\x8a\x1b\xd4\xc4\x5a\xb0\xb3\xd4\x9b\x67\x04\x9f\xa4\x58\xc7\x6f\x91\x8e\x98\x33\x63\x28\x7c\x10\x9c\x18\x3a\x63\xd1\x28\xe9\x9d\xe3\x93\x1c\x90\xe2\x73\xd4\x56\x99\x6c\xcf\xcc\x60\x8b\x0b\x6e\xf0\x8a\xc2\x05\xae\xe8\x48\x7a\x8c\xab\xa0\x2a\x5f\xa5\x88\x7e\x02\xee\x75\x7a\xab\x3c\x4a\x39\x4c\xb7\x2c\xb6\xc2\xf9\xb6\x2c\x33\x58\x99\xd3\xa7\xb8\xc6\xfc\xf5\x9f\x58\x20\x07\x99\x0a\xad\x2c\xbf\xba\xc0\x05\xad\x74\x8b\x52\x59\x50\x1d\xdb\xf3\xc5\xed\xea\x25\x08\x24\x53\x08\x12\xd7\xad\x29\x5d\xb9\xe0\x64\xdc\xe1\x4b\x98\x07\x84\x00\x1a\xb5\x6e\x42\xee\xbc\x64\x26\xe8\x9a\x08\x6e\x26\x7c\xba\x98\x97\x29\xfc\xc3\xb2\xbb\x7b\xb2\xaa\x8a\x07\x0a\xc4\xef\x9c\xd1\xc1\x8d\x4b\x2a\xa9\x2f\x11\xa6\x88\x81\x7e\x34\x59\x0c\xf4\xcf\xde\x6b\x94\x4e\x19\x98\x5f\xbc\xa0\x7f\x4a\xea\x84\x75\x96\x71\xea\xe6\xaa\x68\x91\x40\x08\xf7\xce\xec\xdf\x6b\xdf\x9f\x6d\xc0\x86\xff\x38\x34\x1f\x40\x0a\x86\xdf\xf1\xd7\x15\x13\x22\x98\x62\x00\x2d\x4d\x93\x2f\x67\xf5\x2e\xc9\x2c\xc7\xf3\x40\x68\x4c\x60\x48\xad\xaf\x89\x2e\x0b\x0c\x09\x1f\x9c\x7d\x85\xee\x6b\x18\xc5\x6f\x9e\x70\x79\xf1\x5c\xb8\x23\x34\x54\x20\x83\x33\xef\x71\xd0\x8e\x59\xfb\xda\x63\x76\x68\xc2\x2f\x61\x5f\xdc\x49\xbc\xd8\x4e\xa2\xd6\x11\x4f\x2b\x89\x55\xf4\x69\x98\x98\x0a\x53\x1a\x10\xb0\x56\x31\xa0\xaf\x91\x4f\x17\xa9\x08\x14\x21\xe9\x44\xa6\x74\x25\x13\x43\xb0\x14\xa6\x0e\xd4\xaf\x50\x17\x34\x60\xfd\xf8\x40\x7c\xfa\x10\xba\x26\x88\xb5\x38\x43\x50\x5f\xdc\xc2\xba\xda\x4f\x16\x56\x2a\x80\x97\x5e\x9c\xb8\x77\xfe\x76\xd3\x08\xc3\xd6\xc6\xe8\xd4\x59\xfb\xfe\xaa\xd9\x37\xab\x7e\xbd\x45\x83\x08\x55\x8a\xa1\xef\x92\x97\xec\x01\xe5\xc0\xfe\x81\xa2\x7a\x44\x9b\xaa\x9e\x34\x3a\x0d\x66\xb1\x62\x83\xb4\xca\x83\xa2\x8f\x48\x42\x1d\x95\xe2\x6b\xd3\x73\x2a\xde\x44\x54\xa9\x36\x74\x46\x59\x95\xe9\xab\x65\x2d\xb9\x7d\x65\x23\x74\xdb\x35\x03\xb2\x7d\x43\xc5\xb9\xfd\xce\x9f\xf7\xf4\x0b\x7a\xe0\xa5\x42\xfb\xea\x5a\x1f\x73\x9b\xa9\xe2\xe8\xc9\x09\xe3\xe0\xe3\x23\xe7\xec\x43\xbc\x12\xbd\x38\xcf\x33\x6b\xdf\xd8\x81\xb9\x0b\x30\x21\x86\x1d\x5c\x4d\x20\xc3\x7a\xf4\x60\x45\x21\x68\xd0\x9b\x3d\x55\x9b\xd5\xea\x1c\xad\x05\x7e\x8a\xc3\x19\x56\xd0\xa4\xd5\x17\x55\x80\x19\xc6\xa4\xe8\xd2\xbe\xf3\x3d\x57\x69\x13\xa6\xbb\xd1\x30\xad\x74\xe6\xd5\xb6\xff\xc5\x9f\x03\x86\xd5\x34\x8c\x85\xef\xb8\x3c\x7d\x8b\x4b\xf1\xac\x97\xb1\x05\xbe\xe7\xab\xed\xc4\x81\xe1\x9f\x61\x29\x2a\x99\xf0\x8f\x86\x5b\x6b\xee\x14\x19\x39\x9d\x91\x27\xb1\x6e\x19\xc6\xf5\x4a\x47\x27\xe2\xd8\xc7\xed\xf2\xe9\x04\xe0\x50\x1d\xd9\x94\xd6\x09\x98\x30\xa3\x75\x0a\xf8\xa1\x56\xb1\x59\xa1\x83\x7f\x54\xe8\xb4\x4a\x26\x59\xa1\x63\x95\x83\x80\x44\xaa\xd8\x24\xd7\x02\xcf\xab\x62\xc3\x72\xbd\xe4\x95\x3c\xa0\x95\x6f\x56\x48\x25\x83\xd1\xf9\x2e\xbd\xe4\x8a\x54\xca\x28\xd8\x4f\x24\xfa\xed\x0a\x2d\xd3\xb6\x44\xa1\x8d\x5c\x20\x0f\xe7\x6a\x15\x4b\x94\x5a\x9d\x34\x52\xa1\x90\x49\x35\x72\xba\x0e\x8e\xd2\xe9\xc0\x63\xd1\xa7\xe5\x1a\xa9\x54\xc9\x9c\x96\x6b\x74\xd1\x6b\x49\x29\xbc\x43\x42\x8b\x75\x9a\xb8\x0e\x83\xb0\xa6\x96\x50\xd9\x54\x99\x60\x87\xe0\x16\xdc\x38\xf8\x4d\xb1\xba\xb8\x99\x2e\x6f\xb3\x02\x20\x99\x30\x0f\x1a\xe9\x1e\x9b\x24\x54\xc2\x06\x09\xde\x30\x61\xb5\xbd\xed\xc3\x57\x3e\x50\x35\xa0\xf8\xac\x58\x22\xd6\xdd\xab\x17\xbf\x7e\x50\xab\x14\xf4\xa0\x5d\xe1\xe0\x88\xc9\x23\x6a\x44\x79\xf0\x02\xfc\xf1\x8d\x25\x4b\xde\x00\x6a\x90\x0b\xd4\x24\xf4\xd1\x2d\x76\x21\x98\xca\x46\xbb\x16\x7e\x33\xf0\x32\xdc\xaa\x51\xaa\x35\x60\x2e\x7c\x00\xe7\x83\x61\x70\x92\xd2\xee\x9b\x3e\x6e\x77\x86\x94\xf1\x2f\x79\x03\xfe\xd8\x23\x3f\x58\xdb\x23\x23\x14\x4a\xac\x77\x1e\xa2\x35\xc4\xd3\x15\x28\x0a\xf8\xf3\xb1\x91\x1f\x9a\xa0\xb8\x4e\x78\xa3\x34\xec\x8a\xa9\x02\x71\x87\x1e\x56\xe0\x15\xec\xff\x5e\xb2\x9b\x9a\xa6\xc7\xfe\x11\x3d\x7e\x7f\xb3\x52\x96\x27\xd2\xaa\x65\x2c\xab\xd2\xa7\x58\x9d\xba\xba\xc9\x4d\x03\x9d\x7d\xd5\x6a\x99\x4a\x2d\xf6\x29\x54\x8c\x3a\xd7\xd7\x90\xb7\xe7\x77\xaf\x33\x72\x94\x54\x9a\x27\xd6\xfc\x8b\xa4\xbb\xdf\x78\xdd\x7d\x73\x63\x46\x1f\xbc\x79\xf3\x08\xe4\x37\x6b\xb5\x0d\x0a\x96\x56\x30\xac\x5c\xa5\x94\xf3\x53\x07\xd5\x4d\xb1\x28\x95\x32\x40\xcb\x07\xeb\x75\xac\x3a\x2d\x59\x7f\x7a\xc7\xae\x53\x38\x95\x92\xf9\x57\xa9\xd8\xc2\x5b\x34\x3b\x30\xdc\xe2\x1b\xe2\x71\x14\xba\xd1\xc6\xb7\x72\x36\xa2\x53\x42\x49\x58\x13\xef\x96\x80\x80\x84\x71\x07\x4c\x12\xc0\xa3\xff\x74\x1b\x26\x74\xd1\x26\xfa\xc8\x23\x4d\x03\xa0\x0d\xb4\x9d\x86\x9f\xd1\x47\xe8\x23\xd1\x26\x74\x0d\xda\xa0\xed\x34\xb0\x37\xc1\x30\xdd\x86\x85\x9c\xf8\x06\x49\x86\xa3\xd3\x70\xa2\x58\x32\xfc\xd8\xe7\x4d\x20\x4c\x75\x93\x1b\xe1\x77\xba\x11\xe9\x44\x6f\x32\xf1\x12\x60\x0a\xb8\x25\x5c\xc0\x1d\x90\x00\x37\xdf\xb3\xeb\xd2\x67\x81\x0a\x5e\x6d\x6c\x6d\x82\x57\x81\x29\x73\xd4\x1a\x58\xc6\xe4\x82\x37\x61\x19\xfc\x6f\x60\x42\xb1\xc0\x04\xaf\x66\x8e\x62\xea\x6e\x51\xc9\xe7\xb0\x31\x4a\xe3\x29\x94\x04\x3f\x18\x46\x8f\x54\x81\x37\xd1\xa3\xff\x8d\xb2\x3b\x85\xb2\x43\x0f\x36\x82\xeb\xb7\xe8\x94\x58\x56\x7d\x45\x42\x71\x19\xa8\x9c\x3a\xca\x12\xf3\xb2\xd9\x97\x1a\x86\x7a\x68\xb8\xbb\x57\x80\xf8\xae\x2a\x17\x53\x2f\xf3\x13\x27\xc2\xc4\x57\x0a\x49\x85\xa9\x7e\x46\x2c\xe4\x15\xd4\xec\x95\x80\x00\xb0\x01\x0c\xcd\x55\x64\xa5\x0d\xc5\x41\x3a\xae\xc9\xab\xb3\x2b\x89\x7a\x3a\x96\x06\x62\x8d\x0e\xb4\x34\x27\xf0\xc5\xb4\x8f\xa8\xcd\xd8\x89\xf3\x73\x7a\x6b\xc0\xe5\x0e\x04\xdc\xae\x00\xbb\x2e\x30\x38\x10\x18\x1c\x71\x2f\x38\xb2\x00\xfd\xb1\x6b\x17\xd4\x0f\x59\xb8\xe0\x48\xa4\xef\xd1\x45\x8b\x8f\x3e\xf8\xf5\x51\x76\xdd\xd1\xc5\x8b\x8e\xa2\x8b\xc8\x67\xf0\xbf\x4f\xdd\x7e\x61\xd5\xaa\x0b\xb7\x9f\x62\x1e\x83\xf0\x03\x78\x1a\x2e\xb9\xb0\x7f\xec\xa8\xbd\xe7\xe8\xa1\xf0\x27\xb8\x0e\xbb\x54\x00\xab\x59\xb0\x26\x37\x28\x99\x77\x00\x5e\x3b\xb8\xf1\xdb\xfa\xfc\x06\xd9\x08\x5b\xfd\xd5\x8d\x07\xe1\xb5\x03\xf3\x24\xc1\x5c\x30\x77\x2f\xb8\xef\x8b\x36\x70\x27\x9d\x22\xbc\x3e\x40\xe3\xb7\xfb\x27\xe0\x77\x2e\x58\x00\x48\x19\x5a\xc9\x8b\x8f\x02\xf4\xfb\xfa\x28\xcc\x04\xab\x81\x6a\xd5\xc5\xf6\x8b\xab\x58\xd9\xfc\x79\x63\x0f\x5c\x58\xb2\xe8\xfd\x7b\x27\x44\x79\x1c\x8d\x3e\x03\x7a\x2d\xcb\x7a\xd7\x78\xef\x79\xe9\x3e\x78\x6d\x7f\xcb\x94\x92\x95\xc6\xdb\x9c\x53\x16\xec\x07\xe2\xfb\x5e\xba\x07\xc5\x4f\x5d\xd0\x82\xfa\xcc\xf4\x1b\x14\x7b\x80\xd0\x45\x1d\xd6\x17\x26\x60\x8d\xe8\x60\xd0\x77\x29\xe7\x00\x2b\xc0\x1e\xc9\x79\x53\x4c\xf9\x1d\xad\x3e\x63\xca\xe5\x01\xac\x75\xe4\x61\x04\x3d\x24\x2b\x8b\x68\x29\x56\x2c\xb2\x02\xa6\x37\xdc\x02\x7f\x01\x52\xb0\x1c\x48\xe1\xbe\x17\xd6\xaf\x7f\x61\x3d\xc8\x55\xb0\x8a\xcc\x3c\xf7\xa2\x33\x35\x40\x66\xb5\xca\xd3\x46\xa6\xf5\x39\x03\x7f\x4e\x1b\x89\x82\x69\x40\x36\xe0\xdd\x85\xee\xbc\x4c\x94\x44\x9a\x51\x10\xb2\x73\xfa\xaa\x01\x2d\xa5\x63\x1f\x72\xba\xec\xa1\x82\x0c\x7a\x09\x90\xbe\xfc\x0a\xca\xe9\x97\x57\x5e\x06\x07\xd7\x8f\x1f\xb7\x7e\xfd\xb8\xf1\xd1\x87\x53\xf2\x32\xb2\xec\xc9\x35\x86\x01\x24\x17\x85\xd5\x5a\x7d\x06\xfe\xdd\x8a\x02\x23\x71\x7e\x86\x9a\x64\x7b\x56\x46\x5e\x8a\xde\xaa\xd4\x9a\x59\xa5\xc3\x6c\xf4\x26\x27\x9b\xb5\x4a\x6b\x02\x7e\x18\x4f\xf9\xa9\x20\xd1\x56\x8d\xef\xda\x7b\x80\x88\x57\xd2\xe9\xae\x7c\x12\xc2\x9a\x47\x26\xac\x24\x84\x9d\x64\xa1\x19\x15\x5d\xa2\xa3\xbf\x38\x9f\xc6\xfc\x2f\xad\x76\xd9\x44\x6a\xa3\xed\x26\xf1\xf1\xfd\xe3\x37\x8c\x1f\xbf\x01\x78\xa5\x19\xbd\xd2\xa4\xae\x55\xeb\x96\xa6\xa4\xa4\xf5\xca\x90\x1a\x33\xfb\x0c\xbb\xdb\x7b\x57\xa1\xd1\x28\x31\x96\x1b\x4f\x2d\x1c\x84\x8e\x12\xa3\xf1\x54\xf1\xf6\xe1\x7d\x32\xfb\xbf\x06\xff\xfe\xda\x6b\x40\x4e\xaf\x48\x84\x3a\x65\x20\xce\x69\x7c\xf4\x17\x7d\x12\x97\x2c\x4e\xca\xcc\xd0\x6a\x93\xb9\x24\x7d\x5e\xaf\x5c\x9f\xb2\xf8\xae\x82\x58\x06\x8b\xea\x84\x2c\x5f\x2b\x56\xfa\x72\x7b\x01\x2d\x90\xbf\x86\x73\x03\xdf\x76\xc7\x37\x15\x64\x10\x2f\xa0\x7a\x6b\x05\xbf\x75\x78\x91\x43\x34\xa1\x11\x39\x88\x39\x2f\xef\xe4\xc8\x25\xa0\x93\x15\x15\xa5\x56\x8e\xd9\xf2\x15\x3c\xfd\xe4\x53\xf0\xf4\xd7\x5b\xc6\x85\xe8\xd3\xf9\x0e\xb0\xc7\xd9\xb7\x10\xad\xfd\x5f\x85\xaf\x3a\x3c\x85\x7d\x33\xc0\x5e\x3b\x17\x1e\x5b\x19\xbd\xfe\x14\x6c\xfd\x7a\xf3\xe6\xaf\x41\xe8\x29\x9a\x0f\x8d\xeb\xb8\x64\xc7\x00\x8b\x85\x7d\xed\xf0\x1d\xe0\xb7\xf7\x2d\xf4\xa6\xc3\x55\xf6\x98\x8e\xfa\xbd\x88\x06\xcc\xc0\x7d\x8e\x03\xd8\xd4\xc6\xe5\x73\x51\x18\x10\xba\xd8\xe5\xb3\x1b\x94\xb4\xc9\x48\x99\xb0\x92\x3a\x8d\x7a\x9b\x8f\x33\x08\x0a\x5c\x44\xbd\xce\x5f\xec\x2b\x42\xab\x0e\x14\xc5\x33\x46\xad\x09\x78\x68\x94\x00\x7f\x26\x8a\xe7\x3e\x84\x97\x93\xe1\xcf\x95\xc0\xd7\x00\x8f\x8d\x34\x8c\x5d\x9c\x0b\xe8\xfe\xee\xa1\xc5\x6a\x33\xb8\x3d\x2f\xed\x23\xa3\xee\xc3\x54\xd7\x51\x1a\xf4\xee\x63\xb0\xcf\xb1\xcd\xab\x48\xaa\x9e\x08\x42\x17\x77\xeb\x82\x0b\xed\x17\x15\x5f\xf1\xe0\x45\x65\xff\x5e\x66\xf0\x1e\x00\x5b\x83\xd1\x9f\xec\x33\xe8\xe7\x0b\xa3\x37\x36\x02\x00\x4e\x33\xfa\x77\x8a\x16\x8d\xe4\x5c\xe2\x22\xda\x52\xe6\xe8\x15\xd9\x31\xb5\x1c\x1c\xcc\x76\x83\x2f\x7d\x7d\xe9\x22\x90\x4f\x7b\x3c\xfd\xfe\x5a\xfd\xe1\xde\x40\x21\xcd\x67\x88\x00\x28\xa4\x83\x45\xb0\x9f\x3d\x0a\x35\xcc\x75\x57\xa1\x12\x20\xaa\x92\xcb\x6e\xef\x08\xd5\x26\xe0\x69\x4b\xa9\x24\x6a\x21\xe2\x6a\x77\x25\x50\x3c\xbc\xf2\x54\xb2\x3c\x08\xb2\x4e\x3d\x8f\xb1\xb1\x51\xfb\xa3\x5a\x92\x55\x41\x1a\xd9\x6e\xc5\x80\x38\x04\x32\x1b\xd1\x2b\xb2\x5e\x52\x61\x3e\x3f\x80\x31\x09\xd1\x45\x3e\xf1\xec\x87\x39\xdd\x7c\xb2\x2e\x10\x11\xf7\x6d\x56\xec\x0f\x18\x0d\xe5\x0a\x34\x30\x05\x0d\x8f\xc4\x19\xbb\xdb\x6c\xc0\x3c\x6b\x4f\x36\xbb\xd2\x8b\x50\xb6\x13\x24\x4b\x36\x6d\x9d\xc8\xc0\xa3\xfc\xf2\x0d\xdb\x26\xd0\x77\x36\x33\x96\x64\x56\xd1\x6b\xe0\x27\xeb\xd5\x88\x21\x10\x01\xf5\x80\x81\x6f\x3d\x0e\x92\x74\x0a\x34\x48\xe8\x05\x87\xd3\xfa\x4a\x65\x5c\xb5\x72\x2e\x6d\x4f\x61\x15\xc9\x7a\xfd\xa0\xb6\x0d\x2a\x5a\x81\xd2\xa9\xfa\x57\xbc\xf7\xa4\x5b\x2e\x73\xce\xdf\x9f\x56\x22\x95\xb1\xa5\xca\x11\x6b\x3e\x84\x97\xe0\x4b\xf0\xd2\x87\x6b\xd6\x7c\x08\x32\x41\x3f\x90\xf9\xe1\x67\xb7\x98\x60\xe8\xf5\x66\x17\x2e\x8e\x7d\x18\xdd\x57\x3c\x77\xd5\xba\xb1\xa2\xe8\x2b\xfc\xbc\x95\xeb\xc7\xf6\x7e\xfb\x38\xad\x55\x29\xa4\xe9\x2d\x87\x6c\x7d\x50\x96\xd5\xaa\x99\xb4\xd3\xca\x2a\x52\x33\x99\xda\xcf\x37\xa8\x18\x39\x7e\xed\x80\x3e\xe7\x1e\x07\x46\xb5\x5c\xa4\x93\xcb\x5b\x0e\x58\x51\x3a\xae\x4a\x31\xb7\x44\xa2\x08\xd5\x7e\xba\x4e\x4e\xe3\x2a\x28\x06\x7c\x43\x5e\xbe\x26\xb1\x40\xf4\xda\x7f\xc6\x47\x81\xd8\xdc\x6a\xa4\xd2\x31\x3a\x0e\xc0\x3b\x6b\x4e\x17\xfa\x5c\xfe\x0c\x09\x30\xb2\x01\xc6\x85\x66\x12\xb5\xd3\xa8\xa5\x11\xc5\x70\x02\x3f\xed\xce\xc0\xf8\x24\x88\xb0\x30\xb7\xff\xf8\x87\x6f\x97\x47\xcd\x47\xe0\xdf\xbd\xf0\xbb\x30\x98\x87\x16\x8d\x43\x07\x00\xe3\x81\xaf\x2f\xc0\x87\xde\x12\xfd\xae\x8c\x99\x7a\xee\xee\xaf\xe1\xdf\xc1\xde\x46\xd9\x34\x58\xd2\x7e\xf2\x64\xfb\x49\x11\x45\xaf\xd8\xf4\x83\x5b\xf2\xf0\x2e\xf0\xc8\xfd\x8f\xc3\x39\xd1\x99\x77\xef\x49\x85\xe5\xf6\xeb\x60\xcd\x15\x20\x0b\xec\x83\xa7\xe0\x27\xd1\x61\x1b\x95\xf4\xfc\xf5\xa0\x62\xa9\xe8\x24\x7e\x08\x8f\x2b\x1a\xf7\x2f\xee\x6d\xb2\x9b\x60\xa3\xdc\x2e\x1a\x2d\xac\x99\x20\x16\x51\x04\xf0\x18\x62\x88\xce\x27\xcd\x9b\xdc\x22\x2b\x36\x04\xc2\x58\x1b\x4a\x16\xcd\x83\x6e\x2b\xc0\x66\x41\x1e\x1c\x30\xa1\xb2\xb3\x94\xce\x48\x2b\x01\xcb\x6c\x86\x5f\xc1\xbe\x73\xca\xb4\xfd\xee\x9d\x21\x93\x2d\x54\x64\x7f\xbf\xd8\xbf\x9e\x4f\xae\xf5\x8e\x10\xab\x64\xc9\x9c\x69\x4c\x89\x6a\xab\xd6\xe0\xad\xcf\xf2\x4e\xa8\x71\x96\x97\x4a\xd0\xf2\xc9\x98\x65\xee\xfd\xe8\xed\x03\x4f\x1e\xd9\x3b\x3b\x25\x47\xdc\x27\x6f\xd4\xd4\x14\xd5\xce\x3b\x00\x22\x29\x2c\x3d\xe2\x81\x4b\xf0\xea\x0d\x0a\xe4\x5d\x5b\x0f\x86\x83\xbe\x20\x67\x3c\xfc\x46\xc9\x68\x86\x2e\xa4\xf3\x7e\xdf\x5b\x8c\x18\x3f\xc0\x0d\x75\xf0\xa6\x02\xe9\xab\x7d\x72\x06\x95\xa4\xf0\x12\xaf\x9b\x66\xcb\x32\x68\x5e\xab\x10\x33\x13\x87\xca\xca\x73\xd2\x6a\xa6\xfb\xc6\xbe\xfb\x84\xcb\x35\xac\xff\x71\x30\x66\xfe\x20\x38\x1b\xbe\xb1\xe6\x06\x75\xe5\xc4\x94\xb8\x2c\x27\x86\xe3\x1f\x10\xfc\x35\xb2\x44\xc5\x15\x6b\x7f\xa2\xf9\x29\x40\x0c\x3f\x5c\x98\xe0\x61\xd8\xd9\x5e\xe8\xbb\x01\x3d\x4d\xa0\x14\xfc\x5a\x5f\x31\xed\x26\xbe\x15\xb5\xdc\xc5\x63\xaf\x1f\x84\xdf\x4d\xaf\x1d\xcd\xb2\xa3\x6b\xa7\x03\xfd\xc1\xd7\x8f\xdd\x06\xcf\x3e\x9a\xaa\x7c\x12\xfe\xee\xcb\x4d\xb8\x6f\x3c\xc7\x3c\x02\x0a\xc1\x83\x07\xb6\x34\x2f\xbd\x63\xe9\x81\xb7\xde\x3c\xb0\x6c\xf3\xb2\xd9\x9b\xef\xe1\x2c\xf3\x76\xad\x19\xdf\xbe\x3d\x7b\x7b\xfb\xf8\x35\xbb\xe6\xcd\x59\x0e\xc4\x7b\x7e\x00\xd5\x27\x9f\xc3\x3d\x09\x2c\x8b\x5c\x6b\x85\x8f\xad\xae\x18\x5e\x02\x26\x7f\xf9\x27\x30\xb9\x74\x58\xe5\xed\xf0\x44\x6c\x7d\xa2\x46\xdf\xed\x47\x2a\x87\xf2\x51\x15\x54\x3f\xe2\xef\xc6\x2e\xac\x5a\x11\xdb\x82\x4b\x8d\x0a\x89\x75\x2d\x02\x5a\xa7\x88\xd1\x52\x68\x75\x82\x81\xcc\x30\x0c\x8e\x91\x21\x24\x1b\x7f\x37\x40\x64\x7e\x58\xc1\x15\xd8\xc9\xa2\x16\x11\xc5\x8e\xb5\x1f\xef\x99\xf2\x78\x11\x78\xb8\xe4\x2b\x78\xee\x91\x97\x1f\xfd\xf2\xa1\xef\xf3\x34\xe3\xde\x02\xfa\x17\xfe\x56\x01\x5e\x04\xc9\x56\x15\x75\xe3\xe9\x50\xf3\x88\x82\xda\x69\xfd\x66\x0d\x9f\xb3\xeb\xb6\x77\xfb\x7a\xaf\xbf\x39\x69\xe4\xa2\x7b\x56\x3c\xef\x99\x0c\xae\xd1\x97\xb8\x4b\x77\xef\xf8\x23\x3d\xaa\xa4\x60\xd7\x1b\xe3\x87\xdf\xff\xf7\x8d\xc3\x16\x03\x7e\xd1\x91\xde\x8f\x82\xe6\x5f\x86\xc0\xef\xd1\x84\x33\x11\x2c\x31\x07\x26\x57\x2d\x3e\xfe\x1c\x78\x6a\xd8\xe4\x7e\xf9\x8f\xce\xdf\xdc\xb1\x6a\xe4\xf8\x61\x03\x3e\xdd\x74\x96\x1e\x78\xd7\x6b\xaf\xc5\xe5\x6c\x61\x5e\xf0\x33\x82\x71\x01\x6e\xb9\xab\x69\xb8\x69\xbf\xd0\x97\xb8\x31\x4d\xe9\x14\xd7\xc9\x8e\xa5\x48\xd8\xcd\x8c\xda\x00\xd9\x88\x88\x90\x8d\x08\xd0\x14\xb5\xe1\x0d\x4b\x51\xa8\x6a\x02\xb0\x31\x24\x61\x04\xef\x67\x32\x67\x23\x82\xfe\x4b\x7c\xbf\x21\x1c\xd3\x79\x11\xca\x65\x44\xf3\xe2\x9f\x51\xb9\x4c\x78\xe7\x58\xe7\xc5\x7b\x69\x82\x12\x34\xfa\x1f\x7b\x7b\x56\xa7\xb9\xa3\x9f\xe1\xb0\x4e\x9f\x9b\x6c\xb5\x09\xae\xaf\xd1\xa8\x72\xba\xee\x7c\xa3\x5f\x49\x86\x47\xc9\x24\x69\x75\x2c\xed\xb5\x96\x4e\x84\x3f\x16\x54\x57\xb3\xdf\x82\x62\x74\x2a\x78\xfa\x82\x1a\xe6\xd0\xfa\xec\x41\x81\x95\x75\xb6\xec\xf2\x74\x87\x41\xaa\xd5\x8f\xe8\x9d\x37\xa8\xd4\xeb\xd0\x80\x0b\xd5\x5c\x38\x34\xa2\x64\xe9\xc6\xd9\x87\x26\x8e\xd6\x49\x7e\x18\xfb\x58\x73\x75\x01\x97\x84\x1f\x6c\xff\xb6\xa0\xfa\x03\x30\x65\x5a\xde\xc0\x7e\x85\x72\x73\x55\x4a\xf5\x6b\x47\x8f\x9e\x19\xec\xca\x0a\x29\xe4\x32\x53\x7e\xa1\x6d\xea\x93\xc2\xfa\x56\x79\x83\xe2\x6e\x23\xf2\x92\x7e\xd4\x63\xd4\x1b\x68\x56\xe5\x05\x88\x10\x41\x15\x1a\x2b\x90\x63\x25\xee\x98\x59\x14\x59\xc4\xe1\x20\x5a\x21\x18\xf9\x9b\xad\x57\x02\x31\xd3\x15\x93\x91\xd3\x13\x88\xe2\x74\x92\x89\xcf\x41\xf2\x31\x79\x35\x31\x8b\x2b\x41\x95\x1d\x45\xa6\x81\x38\xec\xb1\xe0\x8b\x49\x13\x43\x6f\x13\x2e\xd1\x1a\x12\xb7\x56\xec\x33\xea\xb1\xe5\x5b\x0c\x27\x06\x97\x81\x31\xea\x3b\x8b\x8a\x53\x13\xcd\x76\x32\x10\x51\x8d\x16\xec\x3a\x70\xf4\xd8\xbd\x7b\xe6\x2f\x08\x66\xcb\xd9\x62\x2f\x07\xb4\x96\xa2\xe9\x93\xc3\x1b\x76\xdc\xbd\x31\x3c\x49\x24\x55\xc9\x0d\x19\xd0\x50\x55\x61\xb0\x68\x54\x52\x49\xb0\x8a\x93\xaa\xd4\xb4\x56\x5c\x55\xa5\xb6\x6a\x15\x22\xbe\xb2\x52\x6b\x4d\x01\x6f\x79\xf2\x86\xd6\x7f\xf8\xd3\x87\xf5\x0d\x39\x2a\x20\x29\x2e\x92\x3a\x7b\x03\x66\xca\xcc\x3d\xbb\xcf\xbf\xbf\xab\xcc\x6f\x51\xa9\xd1\x6a\xcf\x25\x6b\xde\x31\xa0\x7f\xf3\xec\xfe\xa1\x79\x1b\x9a\x9e\xde\x54\xb3\x7d\xdb\x5b\x67\xb6\xf9\x92\x68\xb1\xd4\x6e\x34\xa4\x19\x34\xcc\x5c\xab\x35\x72\x11\x64\xae\xf2\xcc\x5d\x71\xdb\x87\xf5\x43\xf3\x3c\x69\x12\x99\xcc\xac\x90\xf0\xb3\xa6\x85\xf7\x6c\x5c\x9b\xa2\x45\xa4\x4f\xb1\xee\xd1\x07\xef\xbd\x43\x26\x5a\x10\x0c\x85\x2a\x5a\x5a\x76\xcd\x18\x69\x11\x8b\x2d\x80\x19\xd3\x77\xd5\xf4\xc9\xfe\x92\x92\x00\x2a\x31\xcb\xe8\x9c\x74\x03\x29\xb1\xb4\xbc\x8a\x53\xd3\x2a\x25\x2f\xad\xac\x52\xa7\x6a\xb9\xaa\x4a\x8d\x35\x65\xe0\xd2\x79\x33\x87\xd6\x8f\x1b\x57\xdf\xd0\x6c\xe7\x53\x34\x6a\xcb\x94\x6a\x30\x8c\xde\xd2\x34\xe3\xdc\xae\xdd\xe7\xd5\xb2\x22\xaf\x98\x61\x44\x77\xcf\x98\xd6\xaf\x7f\xfd\x80\x46\x38\xa5\x4f\xcd\xa6\xa7\x26\xbe\xb9\x7d\xdb\x36\x5f\x3a\x2d\x93\x48\xc5\x9c\x49\x45\x3f\xa2\x32\xcd\x83\xa9\xd9\xc3\x75\x9e\x71\xf5\x43\x67\xb6\x80\xf3\x62\xbd\x5a\x61\xe6\xc7\x66\x97\x14\x4a\xf3\x93\x15\x6a\xb6\x34\x54\x86\xfb\x4c\xea\x0d\x4a\xf4\xb9\x08\x63\x8f\x05\xa9\xc5\x58\xc2\xe6\xf4\x1b\xf5\x68\x3a\x70\xa4\x7b\xb0\x5b\x60\xe2\x94\xd9\xc4\x3a\xfd\x4e\x8c\x36\x83\x38\x34\xd4\xd9\x11\xb7\xaf\xa4\x1d\x4a\x26\x9b\x16\x00\x6e\xfc\x46\x8c\xd9\x97\x86\x19\x12\x2c\x2d\x50\x32\x64\x9b\x9e\x0b\x08\x5f\x1e\x0d\x14\x27\x31\x40\xb4\x32\x06\xa0\x27\xc6\x08\xfe\x72\xa0\x64\x44\x2a\x95\x51\xa5\x08\xae\xdd\xff\xd9\xd2\x65\x3f\x3c\x73\x6c\x6a\xba\x98\x15\x49\x15\x5c\xeb\x1c\xb0\x11\x1c\x78\x0d\xdc\x2b\xd3\xe8\xd3\xbd\x1a\xad\xc4\x90\xaf\xe1\x0c\x76\x73\xae\x2e\x07\x88\x94\x62\x09\x27\xc2\xfa\xbf\xa2\x59\x45\x9e\x55\x70\x43\x8a\xd3\xa5\x54\xfc\x29\x73\xb0\x4e\x27\x53\xba\x96\x6d\xd9\xb1\xbe\x39\x58\xd2\x78\xfb\xf2\x6d\x53\x8a\x0c\xe9\xa3\x44\x86\xde\xc5\xbd\xb5\xf0\xa3\xdc\x31\xab\x4f\x4e\x9f\xfa\xc0\xa4\xca\xe4\x68\x53\xbf\xaa\x9a\xe1\x56\x65\xaf\xe6\xb9\x95\xbd\x45\xa2\x54\x9d\x3a\x30\xb4\x4f\x61\x70\xec\x92\xf1\x59\x12\x95\x84\x03\xec\x92\xc2\xa7\x46\x66\x7e\xa0\x9e\x5d\x38\x2c\x4b\x29\xd5\xe5\xed\x37\xf2\x12\xec\x42\x54\x70\x16\x4b\xd3\xea\x02\x11\x2f\x07\x8f\xa6\x55\x15\x65\xcb\x64\x6d\xce\x41\x7a\xbd\xcc\xd8\x6b\x54\xa6\xa8\x60\xd8\xdd\x63\x87\x6f\x1b\x5f\x93\x65\x91\xd0\x6b\x2a\x6d\x3e\xda\xe8\x6c\x08\xa4\xf4\x5e\x3a\xa7\xa1\xb0\xa8\x66\xfc\x90\xf4\xe8\xe1\x91\xf9\xb9\xc6\xe4\xc9\x79\x25\x0f\xd0\xfa\xfc\x89\x9d\x36\x3f\x61\x32\x47\x79\x89\x86\xd6\xec\x04\x9b\xd0\x38\xaa\x72\x97\x6d\x6e\x67\xc8\x19\xc3\xb4\xf4\xc5\x30\x2e\xb9\x1e\xd7\x82\x7e\xe9\xaf\x58\xab\xc7\x8c\xb5\x88\x8b\xee\x98\x63\x70\x44\x08\x31\xb1\x14\x4e\x37\x12\x1d\x30\x25\x84\xd9\x70\x7b\x98\xa1\x12\x90\x0c\x12\x82\x1c\x55\x57\xdc\xa5\xbf\xd2\x84\xc9\x6f\x53\xec\x28\xd8\xa2\x0b\x1a\x85\x09\xe1\x76\x2d\x36\x3d\xa4\x43\x3d\x73\x22\xc1\x6e\xed\xa3\x22\x5e\x0e\xbc\x44\x83\xcd\x90\x38\x27\x14\x19\xb1\xbe\xdd\xbf\xc6\x02\xfd\x17\x0d\x8a\xda\x8a\x45\x93\x42\x54\x50\x1b\x41\x45\x88\xa0\x55\x21\x96\x44\x77\x55\x9d\x49\xf4\x4f\x15\xbe\x65\xab\xa1\x18\x70\x24\x9e\x46\x1b\xfd\x80\xa5\x5a\x6f\xaa\xb3\x10\x1e\x7c\xeb\x86\xaa\xeb\xde\x27\xdc\x88\x73\x21\x7d\xc2\xd9\x05\x71\xe6\x22\x54\xb9\xd3\xf7\x50\xcc\x0e\xdd\x64\xd4\xff\x9f\xb5\xc3\x28\x6c\x65\xfe\xca\x2b\x82\x8d\xf9\xab\xaf\x0a\x56\xe7\xf1\xeb\x57\x5e\x91\x44\x6c\xff\x59\xd3\xdc\x73\xeb\xec\x3a\xaf\x61\xdb\xff\xae\xbd\xf4\x68\x1d\x95\x49\x95\x60\xac\x58\x89\x00\x9a\x14\x6b\xa5\x98\xb5\xfe\xff\x55\x03\x71\x26\x48\x49\xcd\x52\xd8\x26\x14\xfd\x0a\x10\xea\xd2\xd1\xf4\x9f\x35\x0b\xdd\x1b\x52\x12\x09\xb0\x09\x0d\x82\x72\x23\xd9\x46\xcb\xfe\x83\xc6\x00\x9d\x3c\x6f\x6a\x8c\x8e\x00\x32\x35\xc7\x4f\x09\xd2\x09\xd0\x6a\x76\xd1\x49\x1a\x53\xfc\xe8\x32\x5f\x27\x7a\xf2\x22\xca\x65\x8e\x6c\x04\x8f\x2b\x5d\x66\x28\x9c\x3a\x84\x78\x74\x14\xe4\x8a\xac\xb0\xf6\x21\x5e\x47\xa8\xa2\x40\xa7\x9c\x3c\x0e\x7e\xe0\x24\x3b\x25\x9d\x22\x23\x3f\x78\x6d\x43\x90\x98\x7d\x0e\x07\x8f\x80\x5c\x78\x01\x36\xc2\x0b\x34\x85\x2b\xb3\xeb\x9c\xd6\xa2\x7d\x14\xb4\xaa\xa2\x0b\xf0\x2b\xe8\xbb\xd9\x42\xe1\x36\xc8\x05\x8f\xd4\xa1\x7b\xe7\x76\xe1\x64\xcb\x1e\x15\x64\x9a\x4e\xf4\x9d\x3f\x26\x73\x94\x93\xe8\xe0\x10\x11\x54\x97\xb8\xa5\xeb\x63\x61\xa4\xa6\x78\xb1\xba\xa8\x69\x0c\xb8\x01\xb3\x91\x06\xd1\xfb\x52\xe9\x76\x4b\x66\x3b\xb1\x37\xa5\x43\x82\x55\x2a\x95\x69\x89\xbc\x02\x04\x13\x55\x86\xe0\xa4\xb5\xb7\x66\x5a\xb6\x93\x94\x34\x6a\x5b\xf6\x8f\xe8\xab\x6f\xb7\x60\x40\x48\x82\x04\xe6\x32\x87\x2c\x1d\x57\x88\x8e\xbf\x99\x69\x15\x00\xc2\x50\x72\x9c\xa6\xb5\x55\x90\xb7\x8b\x29\xae\x83\xe8\x15\xe3\xb1\x4c\x09\x7b\xc9\x3c\x10\xb9\x9d\x5c\x5c\x63\xda\x1f\x40\xdc\x17\xe7\xf4\x73\x1a\x4e\xe3\x44\xff\x01\x3a\xf3\x5f\x5a\x8c\xda\x68\x38\x29\x29\x7a\x6f\xf4\x5e\xa9\x52\xa7\x41\x97\x34\xba\xa4\x9b\xe9\x66\x5b\x47\x12\x1d\xea\x68\xa2\x6d\x6c\x5b\xb4\x8d\xfb\x59\x6f\x6f\x0f\xeb\x6d\xfc\x0d\x4a\x26\xfb\xe5\x17\x4e\xa6\xb7\x73\xf8\x12\x90\x4b\xc5\x81\x0e\xe9\xd7\xec\x2f\x8a\x0e\xe9\x65\xf6\x97\xf6\x28\xfb\xcb\xe5\x0e\x69\xa2\x6c\x58\x83\x4a\xe5\x8b\xcf\x37\x78\xa3\x96\xb4\x24\x2a\x8f\xfd\x16\x31\xf1\x8d\x70\x3c\xac\x70\xb1\x69\x4a\xa1\xd3\x40\x1b\x2f\x46\x27\xd0\xc6\xb3\xdf\x76\xbb\xec\x78\x44\x2c\xa2\x29\xad\x4e\x21\x16\x41\x74\x12\x21\x66\xbd\x3d\xa4\x17\xa3\xce\xa3\x43\x73\xbb\x5e\x0c\x70\xa0\x67\x0c\x73\x83\x92\xea\xda\x11\x93\xce\x00\x14\xe0\x10\xcf\x1e\xdf\xaf\xb1\xf1\x78\x98\x63\xfb\x1a\x13\x85\x15\x62\x7b\x78\x54\x89\x9f\x05\xed\x4e\xb7\x88\x13\x11\x53\xcc\x40\x90\x0f\x60\x25\x09\xac\xea\x49\x0b\x8e\x53\xc0\xbb\xdd\x4f\x3f\xc2\xa9\x7f\x9f\x37\xed\x71\xd8\x5e\x9c\x2e\xd7\x33\x6c\x12\xe7\x54\xda\x55\x66\xa5\x8a\xdb\xf5\xf0\x8f\xe0\x3e\xf0\x2d\xb8\x8f\xae\x4d\x80\xf5\x14\xfe\x80\x07\x3e\x08\x2f\x3f\xa6\x7d\xbc\x44\xca\x00\xa5\x4c\x65\xe4\xec\x4a\xa7\xb9\xa0\xa0\x8f\x7b\x4c\xf4\xee\x27\x80\xfb\xb1\xc7\x3a\xed\x79\x13\xca\xed\x21\x88\xae\x3d\x6c\x83\xe2\x67\xbc\x77\x82\xc6\x4b\x1a\xc6\x73\x43\xfc\x38\xe6\xcb\x33\xfc\x6a\x17\xd0\x77\x56\x08\xcb\xa9\x7d\x2e\xbf\x0b\xbb\x94\xe0\x02\xc4\x27\x15\x76\x0a\x63\x05\xb7\xac\xd9\x55\xd8\x0c\x0f\xbd\x7f\xf7\xba\x51\x29\x49\x9e\x7b\x57\xe6\x94\xf6\x2d\x7f\x0f\x4c\x79\xff\x7d\x30\x14\x57\xb8\x5f\xed\x9b\xb0\xbd\xb0\x92\x53\x25\xb1\x0c\x07\xa4\xb4\x9c\xe6\x0b\x0c\x59\x49\x56\xd9\xa1\x67\xbb\x44\x1d\xf4\xb3\x37\xd7\x3b\xbc\xf5\xbb\x3b\x5a\xde\x1d\x58\xd4\x34\x76\x68\xc5\x1c\x97\x48\xbc\xf5\x3b\xa0\xfd\x0e\x6e\x7d\x02\x35\x86\xf8\xc9\x3e\x4a\x31\xa2\x33\xac\x9a\x55\x21\xb6\x50\xec\x33\x95\x78\x06\x64\x8e\x06\xa2\x7d\xeb\xbe\x3f\x31\x6d\xda\x89\xef\xc9\x77\x94\xb0\x14\xf7\x0f\xd4\x03\x45\x94\x94\x52\x60\x2a\xad\x41\x7f\x20\x19\x90\x33\x36\xe3\x85\xe8\x3f\x4d\x7e\x68\xc0\x8d\x06\xee\xe8\x49\x78\x89\x59\x16\x3d\x09\x32\xd9\xc3\x38\x4c\x0f\x81\x97\x71\x2c\x91\x1b\x36\xdc\x68\x15\x3d\xce\x85\x88\x1d\xba\x08\x50\x8e\x74\xc6\xc5\xd0\xd8\x7b\x6b\x30\x66\xf5\xaa\x15\xd6\x37\x01\x3f\x8a\xd4\x72\x46\xd1\xe3\x52\xf8\x1a\xfc\xaf\xaf\xee\x9a\x9c\xdb\x38\x60\x84\x76\xee\xa0\xa4\x47\x3c\xf7\x8d\x98\xb8\xd8\x94\x6b\x0c\x54\x7a\x67\x4c\x13\x2b\x56\x94\x86\x96\x83\x61\x1d\x4c\xfb\x77\x70\x12\x1c\x0a\xf8\x23\xa0\x0a\x88\xea\x26\x1b\xee\xc9\xbc\x53\x2c\x59\xbb\x15\x7e\x3e\xf2\xfa\x6f\x7e\x33\x62\xab\x19\xdc\x21\x13\x77\xae\x63\x45\x02\x2e\x83\x94\x20\x6b\xdb\x01\xa3\xb3\xa3\x0e\x2c\xa2\xda\x29\xb6\xfc\x93\x4f\xa2\x9b\x3e\xf9\x04\x94\xa3\x89\x81\x02\xc7\xe8\x65\x20\x0b\xfe\x31\x7a\x07\x3c\x1f\xef\xd7\xf1\x67\xb5\x54\x25\x35\x22\xf6\x3c\x4f\x30\xb7\x03\xee\x80\x1b\x3b\xda\xe6\xd0\x4a\x37\x80\xd5\x94\x63\xa0\x20\xd8\x06\x0b\xad\xa1\x0c\x76\x1f\x5a\x75\x62\x8d\x1d\x6f\xc0\x91\x8e\x39\xe9\xe2\x20\x0d\x7c\x44\x49\xcf\xa7\xb1\xa3\x95\x5c\x2c\x1d\x2e\x07\xb3\x4d\x5e\x9b\x96\x3c\x7b\x76\x72\x5a\xad\x7c\xa2\xcf\xe6\x83\xfb\x6c\xc9\xe0\x09\x47\xd5\x80\xc2\x8d\x1b\x9a\xea\xf4\x52\x45\x0d\x68\xdd\x2b\xe2\x68\x00\x4e\xb9\xbe\x11\xb1\x2c\x23\x4f\xa1\x97\xfa\x79\x8e\x86\xdf\x9b\x86\x99\xe4\xca\x7e\xb8\xf8\x6c\xab\x7d\xd8\xc2\xe4\xd2\xd2\xe4\x85\xc3\xec\x4d\x4d\x47\x6d\xf9\x86\x40\xad\x53\xb9\xe8\xf6\x01\x61\x31\x5c\xa7\x94\x03\xbe\x71\xa4\x12\x00\x96\x95\x72\x60\x7d\x58\x24\x62\xea\x53\x52\x52\x65\x91\xdf\x8e\x44\x4b\x21\x46\x2e\xa2\xc5\xd3\x8c\xbc\x1e\xde\xa5\x94\xd0\x92\x91\x42\xdd\xa7\x12\x1a\x84\xf7\x7b\x86\x62\x2f\xa3\x58\xcf\x90\x6c\xc8\xd8\x62\x9b\x30\x31\x88\x76\xa7\x2e\x08\x4c\x1c\x51\x2d\xc1\x63\xc5\xe7\x64\x58\xa2\xe0\x00\xf0\xec\x42\xe6\x19\xe0\x47\x0b\x8c\xf4\xd8\xc2\x14\xad\x19\xf5\x82\xe7\x41\x57\x1c\x06\x5a\xcf\x53\xbd\x8a\xe4\x17\xe1\x0e\x58\x0f\x77\x5e\x94\x79\x83\x8b\x87\x8d\xe8\xfd\x11\xc8\x5a\xcc\x24\x29\xc1\x02\xed\x80\x9c\x60\x63\xe3\xaa\x51\xf0\xe9\x66\x90\xfb\x71\xd9\x88\x61\x8b\xdb\x1f\x18\xb5\xaa\xb1\x31\x58\xde\xc8\x20\xf6\x5e\x6a\x95\x65\x1d\x39\x72\x24\x4b\x66\x95\xca\x64\x39\xf7\x4c\x68\x9c\x70\x8f\x71\xd5\xa8\xc6\xf2\x60\x23\xfd\x74\xd9\xc4\x64\x4f\xd1\x41\x78\x6d\xff\x7e\x20\x3e\x98\x9f\x9f\x3c\xa9\xac\x61\x49\xc5\xbd\x52\x5a\xa2\x50\x33\x43\x9d\x79\x28\x97\x51\xc1\x81\x30\x53\x72\x4f\xf9\x12\xf8\x0d\x79\x49\x23\x6c\x92\x59\x65\x52\x69\x76\x66\x66\xb6\x54\x2a\x4d\x93\xe5\x14\x49\x24\x45\xd7\xf0\xcb\x46\xad\x22\x7d\xba\xef\x0d\x5a\xf4\x32\x6a\x97\x02\x2c\x7d\x08\x32\x78\x1b\x0a\x6b\x3a\xd8\xad\x0c\xea\xd4\x1a\x91\x1c\xb1\x7e\x18\x94\x28\xa0\x04\xbc\xdd\xef\x61\xf3\xd1\x0a\xaa\x2f\x50\x8f\xd8\xf9\x1a\x00\x7b\xbe\x01\xf3\xe6\x37\x77\x1c\x04\x33\x1f\xf9\xc3\x1f\xdf\xae\x19\x07\xbf\x87\x0f\x6c\x7f\xf5\x67\x9a\xf9\xf2\x0f\x05\xbd\xd5\xf4\x4a\xb1\x2d\x38\xa4\xa1\xda\x68\xdc\x7c\xfd\xcd\x03\xf4\x57\xab\xbf\x79\x77\xef\xc8\x3f\xbc\xf9\xf2\x8d\x57\xe6\x1f\x6d\xb0\x99\xfb\x78\xe1\xe6\xc0\x40\xda\x5f\x03\x9a\x7e\xf7\x13\x18\x3e\xb9\xf7\xfa\x09\x83\x56\x0f\x2a\x31\xab\x00\xe0\x86\xac\xbb\x27\xde\x5f\x89\x6e\xbd\x80\x46\x9f\x42\x51\xa8\xa7\xc5\x58\x0a\xdc\x21\xb1\x11\x49\x27\xb3\xe4\x95\x50\x13\xaa\xae\x21\x06\x07\x1b\x71\x60\x33\x15\x11\xe2\x51\xfe\x81\xe2\x6c\x74\x53\x14\xab\x98\x83\x74\x62\xc2\x82\xb8\xa0\xb6\xb6\xaa\x09\x9d\xba\x9d\x2f\x13\xbb\x95\x02\x3c\xbf\x3b\xc9\x96\x1c\xee\x08\x82\x3f\xc9\x00\xf1\x26\x25\x08\xac\x11\x79\x44\x2c\x1e\x65\x4f\x70\x38\x6a\x62\x1c\xd8\x3e\xa5\xc8\x0a\x94\x40\x54\xf0\xd1\xc0\x9f\xb7\xef\xbe\xb6\x63\xc4\xce\xb7\xe6\xad\xbf\x5a\xf7\xc7\x79\xf0\xfe\x77\x7e\x03\x3f\xba\xb0\x7a\xf5\x05\xe0\xfa\xcd\x45\xb0\x00\x86\xe8\x67\x17\xc3\x5a\xf8\xc3\x73\x71\x09\xef\x73\x80\x05\xc7\x6e\xbf\xdf\xdd\xb4\xc5\x96\x27\x97\xe6\xfd\x32\x7f\xf9\x9d\x3b\xae\xed\x9a\xf7\xd6\xce\x11\xb7\xcd\xb9\xfd\xd1\xd6\xd5\x17\xe0\x47\x88\x7a\xa0\x2c\x3e\xa4\xfb\xc1\x23\x51\xf8\x51\x17\xad\x84\x3f\x5f\x85\x8b\x8f\x00\x62\x4e\x82\xda\xc9\x86\xea\xd1\x16\xc3\xd3\x8d\xe1\x11\x04\xec\xc0\xad\x01\x69\x88\xce\xd1\x76\xc0\xed\x8e\x1e\x18\xc7\x8c\x6a\x7f\xf6\x05\xf6\x7e\xfd\xee\xe8\x77\x60\x1c\x94\x47\x1e\x05\x53\x99\x5e\x60\xdd\x3d\x91\x4f\x17\x33\x63\xa2\xc9\x4d\x13\x23\x0f\x81\x21\xf4\x9a\xc8\xa7\x74\xaf\x78\xdb\x84\xb9\x1f\xc9\x7e\xee\xed\xa8\xa3\x10\x8f\xe4\x9d\x2e\x6b\x3a\xc3\x1c\xb6\x44\x21\x9a\x2c\xe8\x8c\xae\x11\xbf\x1a\x3f\xfb\x3a\xcf\x41\xda\xe8\xd5\x74\xfa\x24\x36\x08\x70\x39\xe8\x98\x2a\xec\x3e\x20\x62\x69\x28\xf2\x5b\xe9\x6e\xcf\xa0\xb3\x41\x23\x9c\xe9\xb0\xba\x49\x8d\xfe\x68\x2a\x7e\x8e\x86\x5b\x8e\xb4\x44\x71\x74\xe7\x8f\x93\xf3\x6a\x60\xb3\xe7\xda\x6d\x79\x2e\xc3\x20\xb5\xa6\x37\xaf\xee\x97\xa2\xad\xd1\x65\x16\x01\x35\x2f\xe7\x12\xd3\xd2\xea\x36\x75\xd7\x5f\x54\x0d\x42\x58\x61\x0d\xb6\xd2\x3f\xaa\xd5\x2d\x74\x0b\x3a\x90\x9f\x88\xc7\x06\xbf\x9b\x55\x0e\x93\xcd\x66\x72\xa8\x34\x52\x95\x4a\xfd\x81\x4a\xa1\x92\x6f\x04\x80\xe1\x45\x2d\xb1\x84\xd1\x1d\x2d\x6a\xc1\xc7\x23\xe9\xab\xb3\x04\x04\x2c\x81\xdd\x2a\x07\x76\xa3\xc9\xca\x11\xbe\x3e\x0e\xf2\x26\xac\x24\x51\x3f\xe3\xb0\x97\x2e\x3b\x51\xf8\x11\xbc\x3c\x61\xa9\x55\x20\x28\xea\x05\x62\xc4\x07\xcf\xc0\x8e\x74\x25\x8b\xd5\xa1\xb1\xfb\x47\x31\x2a\x1f\x6c\x15\x8b\x25\xbc\x3a\xf2\x90\xd3\xa3\xd6\xa4\x99\xd2\x6c\x9a\x26\xc4\xa9\x13\x9e\x1f\xa2\xa5\x64\x93\xad\x2c\xd7\x63\x71\x6b\x75\x26\x4b\x6e\x5e\x12\xbc\xd7\x78\x67\x23\x56\xda\x69\xbc\xd3\xd8\x9c\x94\x97\x6b\x31\xe9\xb4\x6e\x8b\x27\xb7\xcc\x36\xdb\x30\x39\x88\x2b\x1d\x9c\x6c\x98\xad\xb1\xa1\x7c\x34\x6a\x8f\x93\x1d\x63\x53\xd3\x1f\x8b\x5d\xe2\x56\x8e\x95\x6a\xc3\x65\xb3\x9d\x19\x41\x5b\x86\xba\x29\x9e\xb9\x56\xd9\xa4\x4f\xf1\xbb\xea\xdc\x59\xbe\xd2\x9a\xf4\xe1\x73\xf6\x5d\xd8\x37\x67\x78\x7a\x4d\xa9\x2f\xcb\x5d\xe7\xf2\xa7\xe8\x4b\xfb\xa3\xaf\xd2\xbf\x54\x9d\x61\x0b\x66\x38\x67\x97\x85\xb5\x7a\x59\x77\xdd\x00\x1e\x8d\x62\x3b\xe1\x49\x88\xf2\x0b\xa5\xc6\x36\x40\x5e\x12\xea\xa1\xd4\xb2\x7a\x48\x49\x34\x5a\x02\xe8\xe7\xd7\xc3\x21\xcf\x44\xd7\xd1\x9b\x6f\xa5\xad\x12\x6c\x19\x0c\x14\xf0\x1f\x80\x7d\x21\x12\x06\x0a\x30\xf3\x16\x9b\x27\x98\x86\x5c\x46\xdf\xc5\x8d\xb8\xe1\x32\x6a\x10\x35\x89\xf8\x20\x76\x8b\xe2\xf8\x4d\x78\x1f\x4b\x90\x55\x1b\x4d\x98\xdc\xbb\x85\x2d\x7e\xa2\x01\xd7\xe5\xbd\x43\xf0\x11\x67\x05\x26\xc1\x0d\x3c\x7e\x4c\xed\x76\x11\x11\x55\x86\xba\x33\x0a\x8b\x9d\x08\x17\x20\x9a\x5b\xed\xe3\xd5\x7c\x56\x92\x5c\x9e\x66\x91\x9a\x56\x7c\xb0\x72\xd3\x17\xfe\x39\xf5\xc6\xdc\x90\xa9\x76\x26\xfe\x1c\xac\x71\xc8\xfc\xfd\x6f\xdf\xd5\xf1\xe7\x47\x7f\x3c\xb3\x37\x08\x82\xbf\xfd\x0b\x18\x6b\x5a\xbc\xbf\x7d\x92\x29\x2b\x49\x67\x96\x6b\xfb\xf7\xd7\xca\x8b\x2b\xb4\x93\x00\xb5\xc9\x94\x65\xd2\x99\x15\xda\x39\x73\xb4\x0a\xb3\x39\xa8\x05\xcf\xf5\x9a\x68\xc8\xcb\x4f\xb2\x30\xd2\x52\x6b\xff\x01\x2b\xdf\x5f\xb1\xeb\x36\xcb\x60\x53\x28\xd7\x58\xbb\xf7\xc2\xde\xf9\x83\xef\x3a\xf3\xd7\x47\xf7\x7f\x69\x7c\xe1\x4b\xf8\xdb\x6f\x92\x5f\xbe\xed\xc9\x1d\x76\x85\xa6\xc2\xdc\x0c\xe8\x66\x73\x30\x43\x61\xbe\xab\x1a\x26\xbd\x95\xae\xd0\x06\xcd\x0f\xbe\xfe\xdb\x07\xcc\x15\x1a\xad\x3c\x05\xf1\x14\x19\x37\x28\xee\x0a\xd9\x87\x9f\x87\xd8\x48\x32\xeb\xe1\xb1\x2a\xe0\x32\x62\x0f\x08\x1c\x36\x7f\xc1\x82\x34\xac\x9e\x9b\x06\x88\x4f\x52\xd6\x8d\xb7\xdf\x7d\x71\x11\x1b\xc1\xf8\x72\x64\x03\x0f\x4b\x2c\xbe\x88\x57\x53\x2b\x63\xb2\x8a\xb9\x2b\xab\x9f\x59\xb3\xe6\x99\xd5\x57\x17\x1d\xb4\xef\xba\x3a\xf7\x85\x95\x93\xfd\x0e\xb9\xc4\x92\x37\x6c\x56\x43\x6e\x8a\xd8\x64\x99\xe3\xce\x5c\xb4\x4f\x9b\xe7\x9f\x30\xbe\xc6\xa2\x5a\x7c\xd7\x8c\xac\xac\xb1\x9b\xde\x5a\xb1\xfc\xcc\xda\x31\x2e\x6b\x8e\x3f\x57\x43\x8b\x74\xe6\xe2\x0c\x8f\x45\xaf\x6a\x74\x3a\xab\xa7\x64\x4b\x5d\xd5\xab\x47\xd5\xdd\x3e\xbe\xa6\x20\x5d\x27\xa5\x15\xa3\xd7\xac\x19\x3d\x66\xcd\x9a\x53\xaa\x27\x97\x0e\x0c\x0d\xce\xee\x33\x72\x78\x83\x57\xa9\xcb\xaf\xf4\x66\x38\xf2\x7b\xb9\x95\xe9\xf9\x29\x56\x1a\x4c\x6f\x30\xe7\xe5\xba\x8a\xf2\xd2\x15\x7c\x60\xcc\xc2\x3b\x26\x0c\xde\xb1\x7e\x52\x69\x71\xc3\xac\x99\x5e\x4f\x4d\x4e\xaa\x54\xaa\x75\xf9\x47\xf9\xd5\x3a\x00\x82\x83\x9d\x49\x2e\x7f\x41\xaf\xd4\xe4\x52\x7f\x28\xd0\xcf\x5f\xe3\x4d\xb4\xc3\x13\xec\xd7\x6f\xda\x3d\x70\xf6\xb8\x4e\x74\xc4\x4d\xb7\x6a\x95\x37\xc8\xda\x13\xa0\x23\xe8\x7e\x15\xee\xe9\x73\xbb\x89\x26\x23\xb9\x4b\x28\x14\x0b\x83\x1b\x3d\x3c\x6b\x77\xf1\x72\x82\xbe\x4d\x80\x58\xd3\x77\x5a\xc3\x53\xb6\x20\x50\x7b\xd0\x02\x1e\xa8\x8d\xce\x44\x5f\x69\x89\xb2\x86\xd8\x35\x9d\xdf\xdd\xa6\x1d\x1c\x06\x99\xed\xbb\x76\xb5\xc3\x4b\xe8\x08\x7e\xc0\x65\x68\xed\x2a\x14\x39\x70\x3d\x0b\xde\xf1\xc4\xae\xf6\xce\xa7\x06\x77\x2b\x7a\x42\xb8\x1b\xff\x8a\x3d\x1a\xde\xd4\x92\xdd\x5c\x98\x87\x12\x73\x00\xad\xbf\xd6\x56\x37\xb5\x0f\xd3\xa3\x7d\xfe\x69\xeb\x04\x12\x6d\x35\xff\x55\x6b\xcc\xeb\xaa\xcf\xff\xa0\x09\x7a\xea\x47\x39\xa9\x72\xc4\x6b\xe8\x88\x41\x33\x81\x57\x07\x88\x81\x27\x5a\xdc\x82\x12\x7c\xe7\xb9\xc8\x88\x85\x43\x82\x27\x3c\xd2\x46\x42\xd8\x6f\x33\x8a\x3e\x71\x30\x3a\x5d\xea\xf5\x70\xaa\x4e\xc7\x38\x44\xe3\x47\x5e\x1f\x3e\x92\xc9\x48\x06\x14\x59\x34\xe1\x03\x95\x9c\x01\xd7\xbb\x8a\x5d\x88\x46\xa3\x23\x86\xe3\x0a\xc3\xb7\x2c\x46\x83\xc1\x68\x01\xa5\x4c\xff\xc8\x75\x86\x4f\xb2\x27\x7a\xdc\xb4\xff\xe6\x06\x25\xf8\x9e\xc0\x14\x2a\x1e\xbe\xff\xf3\xcf\x63\x76\x76\xf8\x64\x20\x08\x45\xbd\xa8\x1a\x6c\x67\x07\xf0\x14\x95\x03\xe2\x3a\xbf\x31\x0f\x18\x68\xee\x72\x33\x1e\xc4\x11\x11\x35\x6b\x67\xbc\xe4\x46\x61\x94\x74\x86\x75\x7e\xac\xe3\xc2\x88\xf0\xa4\xe7\x07\x8c\x83\xe8\x6d\xc6\x3e\x03\xd1\x9f\xc5\x7a\xb1\x39\x71\x94\x7f\x4c\x9f\x49\x29\x55\x8b\xc4\x03\x3c\x1d\x94\x67\x80\x78\x91\x0a\x5f\x83\x69\x66\x07\x6d\xa3\xb3\x8a\xf1\xd1\x99\x0c\x8e\x60\xc7\x17\xc5\x2e\x10\x8e\x9d\x9b\x6c\xb4\xa3\x38\x0b\xdd\x73\x98\xb9\x64\x67\xc7\xea\xf1\x1b\xa6\xe9\xb6\x8d\x79\x58\xd0\x57\x7f\x78\xcc\x36\xdd\xb4\x0d\xe3\x65\x7d\xf3\x1e\xc6\xb0\x5f\x28\x22\xaf\x2f\x83\x5b\x30\x3a\xcb\xd3\xbb\xb7\x87\xde\x87\x82\x91\x36\x3a\xcb\x0c\x8e\x98\x1d\x6c\x96\x19\x36\x25\xa7\x87\x50\x18\xc3\x2c\x34\x91\xe6\xe9\x0a\x1b\x50\x38\x8b\x75\xe0\x8b\x2c\x3a\x9d\xfd\x08\x4e\x05\x2f\x36\xce\xc7\xb7\xe7\x37\xc2\xfe\xe0\xbe\xdc\x12\x1c\x2e\x41\xfd\xdf\x8e\xfa\xe5\x67\x64\x0d\x36\x04\x7b\xc8\x72\x30\x78\xf3\xcb\xce\xd8\x8b\x4c\x46\x22\x5c\x62\x88\x36\x28\xea\x15\x8e\xce\x10\xee\x25\x44\x8e\x94\x10\x22\x60\xdb\x46\x9e\xf1\x76\x86\x70\x0e\xcc\x67\x21\x18\x62\x60\x09\x9f\x04\x5f\x0c\x81\x80\x4a\x2a\x65\x4b\x38\x33\x7c\x71\x28\x9f\xd4\xa6\x96\x4a\x98\xc1\x10\x85\x3e\x57\x91\xd0\xdb\xf8\x84\x52\x82\xfe\x21\x1c\x26\x29\x41\xff\xa1\x7c\x72\x9b\x2a\x96\x32\x16\xc2\xf9\x48\xb0\x38\xea\x06\x05\xae\xb5\x25\xdd\xa0\xe4\x4a\x65\x5b\x12\x7c\x01\x4d\x6f\x6a\x50\x12\x3f\xa3\x43\x5b\x12\x10\xee\x81\x01\x38\x0e\x9e\x89\x9f\xe5\x72\x61\xfd\x39\x1b\xcd\x33\x7b\x63\xf6\x9a\x1a\x62\x71\x6f\xe2\x35\x26\x9e\x91\x30\x1a\x06\xeb\x0a\x02\x34\xfe\x89\xb5\x25\x1a\xa4\x04\x65\x93\xa9\xd9\xb3\x77\xef\x9e\xf5\xe0\x3c\x3c\x07\x8a\x60\xc1\x8d\xf1\x20\x04\x5b\xc7\x53\x37\xe8\xdf\x87\xe6\x1f\x3f\xfd\xcb\xe9\xe3\xf3\x43\xf1\x00\xf8\xd3\x9e\xbd\xcc\xb6\xbd\x7b\x22\x93\xc0\x79\x50\x84\xfe\x9f\x8f\x1e\xa2\x6e\x8c\x87\xa7\xe0\x29\xf4\x00\x68\x41\x63\xf5\xad\xb7\x57\x15\x16\xae\x7a\x1b\x94\xa2\xf1\x5a\x2a\x84\x85\xb1\x99\x79\x83\x62\x2e\x75\x96\x8b\x72\x06\xdc\x9a\x80\x5b\x87\x25\x05\x58\x71\x12\x9d\xe8\xe1\x8f\xa3\x7f\x36\x30\x35\xfa\x15\xfc\xe3\x1c\xb0\x18\x6e\x9b\x03\xb2\xe8\x94\x05\x27\x4e\x80\x79\x27\x4e\x44\xff\x1b\xde\x17\xfd\x92\x7e\x0b\x5e\x9a\x03\x96\x80\x25\x73\xe0\x25\xfa\xad\xe8\x97\x82\x5d\x4d\x4c\xd7\x0b\xcb\x63\xb2\xa8\x42\x8a\xea\x94\x1c\x75\x4a\x90\x44\x04\xcd\x4f\x87\xa5\x5f\x44\x7e\x88\xa5\x5f\x98\x38\xb3\xb1\x3b\x1c\x55\xd7\x5c\x57\xd7\x1c\xad\x23\x27\xb6\xee\x73\x01\xa9\x6f\xad\xa2\xa3\x4d\x67\x43\x3d\x50\xc1\xda\xc8\x39\xda\x14\xbb\xf3\x1e\x4e\x57\xc7\x90\xe4\x75\x30\x2d\x0e\xec\xd7\xaa\xd7\xb6\xa3\x4e\x6e\xd6\x6b\x39\x74\x7a\x39\x16\x4d\xe4\x46\xcc\x8d\xfe\xa2\x28\xf7\x22\x91\x92\xa8\x51\x49\x53\xb1\x3f\x18\xec\xf6\x45\x97\x05\x40\x21\x26\x4f\xfe\x22\x80\xdd\x3e\x48\x40\x21\x0e\x9b\x9a\x99\xa4\xc8\x7d\x5a\x25\x3f\x0d\x9c\xa3\xf7\xc0\xe7\xa2\x3f\xbe\x09\x8b\xde\x14\x17\x71\x05\xd3\x78\xa5\x36\x72\x1f\x93\x44\x2e\xc5\x4c\x30\x22\xa1\x97\x2a\x72\x0c\xa0\x38\x22\x11\x8d\x8d\xde\x47\x4f\x35\x45\x37\xc2\xf7\x0c\x39\x8a\xe8\x9d\xcc\x3f\xd0\x95\x29\x41\xde\xd6\x86\xbe\x04\xde\x75\x29\xc4\x7e\x51\x7d\x0e\x40\x6c\xc8\xdd\x18\xf0\x8a\x20\x4c\x72\x7a\xbc\x5c\x17\xd4\x27\xd3\x05\xe5\x49\xc1\xed\x07\x9e\x2c\xd0\x5c\x7a\xe4\x08\xd3\xb7\x79\xeb\xe6\xeb\x4d\xa0\xf1\xda\x9e\xb5\x30\x93\x60\x1b\x84\xa7\x8c\x86\xd1\x17\x56\x9c\x2b\xd3\xd5\xe9\xca\xce\xad\x78\x01\x46\x47\x4f\xf9\x11\x1c\x02\x5f\x83\x43\x3f\xd2\xad\x6d\xd1\x0b\xe3\x32\x68\x30\xb1\xb6\xa9\x7e\x12\x00\xb7\xb7\xb5\xbe\x7c\x6c\xfa\x9a\x43\x9f\xce\x6c\x04\xa0\x71\xe6\xa7\x87\xd6\x4c\x3f\xf6\xf2\xfb\xc2\x64\x10\xc7\x6e\x88\xcb\x4f\x84\x75\x96\x8e\xca\x44\xfc\x80\x60\xf3\x6d\x70\xf8\x74\xc4\x13\x99\xbd\xeb\x47\x44\xfd\xc0\xcd\x13\xe3\x93\xd8\x14\x87\x56\x66\x1c\xfa\xeb\xa1\xb7\x47\x33\x91\x48\x84\xf9\x09\x3e\x06\x46\x60\xb5\xdc\x68\x13\xe3\x96\x8b\x6d\x70\xd3\x07\x1f\xc0\x4d\x36\xb1\x5c\x2e\x66\x2f\x89\xd1\x92\xed\x45\x38\x8b\xde\xfa\x09\x3a\x7c\x31\x32\xd8\x91\x19\x1c\x39\x32\xc8\x5e\x0a\x8e\xa4\x17\x84\xc3\xd4\x8d\x35\x6b\x20\x46\x3f\xa0\x84\x70\xe4\x41\xfc\xc4\x0d\xea\xb1\xc7\xd0\x98\x14\x77\x64\xa2\x3c\xd8\x09\xfb\xf6\xed\xd3\x77\x3d\x36\xb2\x9b\xce\x4a\x1a\x9e\x95\x40\x6c\xc3\x5e\x94\x06\xb0\xb6\x8e\xc9\xca\xe2\x7d\x53\x1c\x43\x03\x0f\x47\xbb\x6d\x72\x14\x8f\xc1\xd9\x0c\xc0\x01\x94\xb4\x87\x66\xc2\xcd\x25\x5b\xcf\xa7\x67\x8c\x96\xba\xdd\xc1\x69\x8d\xbe\x5c\x09\x9b\x5b\xbf\x78\xd1\xee\xda\xfd\x00\x14\xf9\x2c\x83\xde\x83\x0d\x75\x0b\x86\xf5\x2a\xf3\xd4\xba\xd1\x30\x3a\x0d\x7c\x57\xef\x6c\xb0\x72\x4a\x85\x02\xf4\x69\x86\xdf\x18\xb7\x36\x9f\xd8\xfb\x12\x7d\xfe\x77\x0d\xef\x2c\xd6\x69\x32\xd5\xd6\xb4\x9c\x69\x1b\x26\x0c\xd7\x88\x87\xdf\x79\x7c\xdd\x12\x5b\x95\x88\x49\xcf\x30\x94\xa1\x91\xbf\xba\xf7\xba\x43\xf7\x5e\x79\x13\x14\x6d\x19\xd0\x72\xf2\x91\xaf\x8e\xff\x69\xd9\xf0\xe1\x26\xf8\x22\x48\xa5\x93\x94\xb4\x6d\x24\x95\xa0\xdb\x96\x4f\x76\xb0\x88\x87\x79\xca\x03\x78\xd6\xe6\x74\x29\xc9\x5e\xb2\x92\x46\xf4\x95\x28\x20\x20\x0a\x1a\xf0\x62\x75\x72\x6f\x51\x20\x88\xa1\xef\x69\x37\xe6\xf1\x63\x23\x92\xed\xb1\x16\xe9\x89\x52\xd4\x73\xad\xc2\x4d\x95\xe7\x99\x61\x07\xfc\x16\x76\x98\xf3\xe4\x29\xe6\xd7\xe7\xd2\x29\x66\x8b\x44\x6a\x4c\x96\x28\x73\xd5\x62\xbf\x26\x5b\xe3\x17\xab\x73\x95\x92\x64\xa3\x54\x62\x31\xa7\xd0\x73\x5f\x37\xc3\xe7\x89\x80\x93\xde\x3a\xff\x55\xf4\xe4\x17\xb0\xe3\xd5\xf9\xf3\x5f\x05\x1c\xb0\x02\xee\x55\x58\x0b\xcf\xc0\x2f\xcf\xad\x58\x71\x0e\x58\x40\x09\xb0\x90\xd0\x99\x5b\xad\x7f\x46\x14\xa7\x88\x82\x41\x51\x4a\x71\x9e\xc8\x23\x3f\xfc\xe9\xe8\xfe\x86\xe4\x02\x29\x9b\xa5\xdf\xba\x7c\xf9\x56\x7d\x16\x2b\x2d\x48\x36\xf4\x1f\xfd\xe9\x61\xb9\x47\x74\x94\x88\x53\x17\xf4\x78\x13\x0e\xcd\x59\x71\x0e\x7e\xd9\xe3\x85\xb0\xe0\x56\x6a\x68\xa8\xd7\x57\x23\xfa\xfd\x72\xac\x8d\x07\xa0\x18\x23\x31\x87\x21\xab\x1f\x1d\x81\xb5\x77\xc7\x34\x38\x51\x7b\xa2\x6e\x2f\xf2\x00\xa2\x93\x8b\x11\x1a\xd1\xe4\xe6\xa4\x05\xa5\x69\x3d\x28\x0a\x90\x55\x05\xb6\x2d\xc4\x7a\x82\x46\x6e\x55\x35\x97\xcb\x96\x67\x89\x98\xdc\x52\xc6\x71\x77\x60\xcf\x1d\x63\xcf\xee\xdc\x34\xfd\x8e\xe5\x0f\x02\xf1\xde\x67\xed\x8d\x65\x9c\xed\xaf\xe6\x6a\x2b\xf8\x36\x43\xae\xc9\x39\x0b\x16\x65\xed\x69\x6e\xde\x33\x33\xf2\xd1\xac\x31\x5b\x77\xbd\xba\xa7\x63\xd7\xe2\xad\xbd\xcf\xd2\xbf\xf4\xcb\x8f\x5e\xce\x2e\x01\x4c\x9f\x5c\xf0\xb8\x78\xc1\x9a\x4b\xf7\xdd\x31\x6d\xd3\xce\x73\xe3\xee\x5c\x98\x02\x72\x47\xfd\xc6\xca\x55\x35\xa6\x5e\x34\xf1\x5a\xf8\x95\x21\xbf\x4f\xd1\xb7\x7a\xf0\x68\x33\xce\xa6\xfd\xb5\xf2\xad\x8b\x77\xb5\xef\x79\x65\xcf\xd6\xc6\xb9\x3b\xcf\x52\x3d\x7d\xfc\x0e\x26\xbe\xe0\x7a\xf8\xf8\xc5\x28\x01\xbc\x92\x16\x36\xbb\x49\x74\x90\xf9\x7f\xd5\x7d\x09\x7c\x1b\xc5\xd9\xf7\xce\xec\xa5\xfb\x5a\x69\x65\xdd\xb2\x4e\xcb\x87\x64\x4b\xb2\xe4\xdb\x8a\xed\x38\x89\x1d\x27\x8e\x73\xc7\x89\xe3\xdc\xf7\x09\x39\x49\x88\x21\xe4\xe0\x86\x04\x52\x20\xe4\x6a\x80\x70\xb6\x25\xd0\x70\x15\x1a\xa0\x25\x94\x16\x48\xb9\x1b\x5a\x9a\x04\xde\xb6\x94\x12\x28\x94\xb6\x90\x68\xf3\xcd\xcc\xca\x8e\xed\x84\xd2\xbe\xef\xf7\xfe\x7e\xdf\x97\x58\x3b\x3b\xb3\xb3\xb3\xb3\xb3\xcf\xcc\x3c\xcf\xcc\xf3\x3c\xff\x34\xf1\x6b\x41\x60\x8b\x88\x36\x4b\x54\x56\x32\x81\x5e\x1d\x34\xb8\xa1\xb7\x0e\x22\x96\xb3\x3f\x7f\x4b\x2f\xcf\x41\x14\xef\xc7\x6e\x79\xdc\xb5\x45\x21\xaf\xcb\x4a\x62\x16\x47\xc2\xe3\x2a\x2f\x9e\x98\xac\x08\xbb\x12\x4a\x83\x5a\xb1\x58\xc5\xf0\xeb\x3f\xbc\xea\xfd\x33\xd2\xb9\x4f\x1f\x9a\x3b\xf7\xa1\x4f\x01\x43\x42\x70\xeb\x60\xa6\xb8\xbd\xb7\x44\x13\x38\x1d\x6f\xaf\x72\x5b\x4c\x66\xa7\x9e\xec\xe3\x35\xf9\xab\x03\x7e\x83\xd6\x16\xf0\x14\x56\x3b\xcc\xf5\x1a\xae\x83\xb7\xab\x8e\x3e\x06\x1a\x51\x71\xfd\x8b\x95\x9e\x18\xc4\x4a\xa3\xf6\x08\x9f\xa7\xd9\xc9\x44\x3e\xac\x43\x5c\x4b\x37\xb6\x91\xed\x5d\xcd\x41\x2d\x10\xc2\x08\x61\xa8\x6f\x79\x80\x40\x13\x5d\x0d\x22\x0d\x3b\xb0\x76\x0f\xe9\x73\x48\x48\xa4\x05\xd9\x27\xa7\x07\xf0\xd8\x07\xa3\x07\x13\x04\x26\x8f\xb0\x1f\xfb\xf2\x21\x80\x7a\x58\xa5\x03\x88\x58\x35\xa8\x1c\xfc\xa0\x67\xea\xd4\x9e\x4e\x70\x43\x4d\xa3\x4e\xba\x95\xd7\x31\x34\xaf\x5e\x0f\x0e\x34\xda\xf4\xda\x78\xb9\xcb\x46\xc3\x17\xd9\xf1\x7e\x46\x65\x32\xf3\xbc\xe0\x31\xaa\x99\xe8\x9b\xd6\x29\xad\x5e\x70\x3f\xcf\x23\x66\x4a\x5a\x52\xd4\x99\x97\x17\xe0\xd4\x31\x7f\x5d\x01\xf6\xb5\xb6\x81\xde\xe9\xa1\x95\x6a\x33\xb7\x52\xfa\x25\xad\xa0\x69\x35\xf3\x8b\xce\x21\x99\xce\xce\xcc\x90\xac\x3f\xee\x17\xad\xe0\x88\x86\x87\xb4\x42\x7b\xbd\xb4\x57\x4a\x1f\x2d\xb4\x73\x76\x9b\xb6\xc6\x61\x84\x93\xc1\xfe\x7b\x3e\xc8\x0b\x08\x5a\x00\x69\x8d\x39\x4f\x0f\x11\x3f\xba\xd1\x57\x90\xfd\x07\xab\xa1\x81\xf6\xbe\x15\x27\x2b\xd2\xd3\xbc\xcd\x0e\x51\xe3\x15\x0c\x4a\x30\x5d\x7a\xa4\x4c\xc1\x42\x56\x1d\x51\x3d\x0c\x3e\x06\x0c\x84\x4a\x05\xf1\x7d\x46\x53\x1f\x2a\x29\xc6\x89\x46\x5a\x35\xe2\x9e\xcb\xa8\x56\x6a\x0e\xb5\x09\xcf\x70\x34\x9b\xcc\xd9\x00\x01\xa1\x0f\x5d\x82\xc8\x04\x21\x19\x6e\x0d\x73\x00\xfd\xe6\x08\x44\x73\x34\xef\xc7\xee\x33\x93\x51\x3a\x9c\x70\xd3\x9e\x7f\x23\xc5\x0a\xfe\xf9\x10\xa0\x27\xcd\xe9\x4e\x25\x3b\x17\x67\x5f\x00\x82\xee\x3d\x9d\x20\xfd\x2e\xad\x32\x49\x5f\x59\x04\x2d\x2c\x56\x9a\xc0\x48\x9d\x99\xae\x3e\x7b\x4c\xfa\x42\x67\x36\xeb\x80\xe6\x65\x70\x07\xd0\x3b\x6b\x8b\x12\xa1\x4a\xbb\x01\x00\xa0\xb3\x57\x84\x8a\x22\x75\x2e\x23\x7c\x0a\xa5\xd7\x5d\x48\xb7\xf5\xa6\x1f\xc9\xe5\xaf\x18\x98\x0e\xa0\x1b\x28\xef\x9b\xb8\x50\xda\xb0\x12\xbc\x92\xd5\xe0\xd2\xeb\xc6\xe8\x03\x46\xf8\x95\xce\xfc\x92\x74\xe5\x6f\x51\x1f\xfa\x9b\xce\x2c\xcd\x56\x07\x16\xcd\x58\x53\x54\xb2\x66\x41\xa7\xc3\xa1\x70\x75\x4e\xdd\x5c\x1d\x5b\x3b\x6f\xb2\xdd\xfe\x1f\xa6\xcb\xfb\x9f\x6c\x0f\xfb\x05\xd5\x42\x4d\x45\x12\xca\xd5\x68\x5a\xc0\xc0\xf7\xd8\xa9\x3e\x01\x67\x0c\xa3\x36\x09\x25\xd3\xd8\x91\x07\x59\x81\x24\x68\xe9\x30\x67\xdd\xce\x13\x67\x79\x58\x24\xb4\x5e\xd0\x54\xab\x03\x02\x1a\xb3\xe4\xa5\x1d\x44\xef\x56\x11\x11\xaa\xe8\xc3\x85\xe0\x05\x20\x92\x62\xe0\xe5\x04\x24\x52\x86\x72\x49\x68\x96\xe0\xe1\x02\x3b\xe2\x2c\x14\x4a\xa5\x3e\x60\xed\xca\xf3\x69\x39\x15\xab\x00\xc1\x20\x50\xb0\x2a\x4e\xeb\xcb\xeb\xb2\x06\xf4\x4a\xa5\x02\xc0\x80\x7d\xa2\xd7\x8c\xe4\x8a\xca\xd1\xf5\x2e\x0f\x47\x97\x85\x42\x65\x15\x8e\xfa\xcb\x69\x3a\xe3\xb3\x99\xbd\x13\xf7\xd9\x43\x42\x30\x88\x31\xff\x5a\x5b\x2d\x4f\xa6\x4c\x82\xb0\x7c\x39\x8e\xed\xda\x75\x10\x47\xa6\xcc\x98\x31\x05\x47\x97\x5c\x7e\xf9\x92\x3b\xd5\x5d\x6b\x95\x4c\x89\x43\xa1\x53\xab\x59\x8b\xe0\x62\x7a\xa4\x1e\x0c\x09\xc9\xaa\xd5\x3a\x85\xa3\x84\x51\xae\xed\x52\x8b\xb5\x1a\x85\xc9\x18\x1b\x9f\x6e\xd4\xf0\x8b\x4e\x48\x5f\x9c\x58\xb4\x3e\xdc\x19\x00\xc0\xa4\xd0\xd4\xd2\x87\x42\xe5\x42\x10\xbd\x29\x86\x2c\x6c\x7d\xab\x55\xf8\x31\xc6\x99\x5b\x09\x6a\x56\xe2\x84\x5d\xd2\xa4\x5d\x2f\xe3\x84\xce\x3f\x03\xea\xcf\x9d\x38\x69\x09\x9a\xf2\x7e\x25\xfd\x89\xf8\x49\x37\xe3\x83\xa2\xa7\x8f\xd7\xf5\x10\x6c\xa3\x34\x55\x8f\xe6\x62\x8c\xa7\x35\x1d\xcd\xc7\xcb\xa8\x35\x88\xf2\xb7\x51\x37\x53\xdf\xa3\xf6\x11\x3b\x7b\xb2\xa3\x12\xc8\x85\x30\x17\x0e\x4e\xff\xd6\x7c\x83\x76\x34\xbf\x2d\xfe\x5d\xe1\xb7\xdd\x0f\xa0\xec\xb9\xf8\xfb\x24\x90\xff\xe0\xf7\xfb\xa7\x65\xbf\x7f\x71\x8e\xaf\xbd\xc4\xcb\x32\x5c\x4e\x02\x69\xf9\x25\x62\xac\x1c\x64\x07\xc4\x2e\x99\x33\x17\x03\xdd\x5d\x17\x9e\x00\xe5\x40\xea\xba\x38\x6d\x40\xe4\x9c\x6e\xbf\x7c\x37\xfe\x03\xb7\x5c\x1c\x39\x2b\x07\xf4\x80\xd8\xa5\x32\xca\x7f\x39\xdf\x65\xdc\x39\x8e\xea\xf3\x08\x3f\x92\x1a\x47\x2d\xa0\xae\xa0\x6e\x40\xac\x40\xae\xd5\x52\xbd\x48\x99\x80\x07\xbd\x16\x54\xf2\x6c\x49\x5b\xfa\x8c\xa5\x52\x04\x56\x0d\x77\x3d\x62\xed\x43\xd6\x1b\x89\xbc\xd7\xdb\xf6\x41\x39\x4d\x56\xea\x90\x97\x23\xbd\x62\x50\xc6\x9d\xc3\x0c\xaa\x8c\xbf\x26\xb2\x62\xaf\xee\x66\x2e\x41\x96\xfb\xff\x40\x8e\x63\x01\x35\x05\x49\xac\x8f\x90\x08\xfc\xd8\x9a\x0c\xf8\x3d\xae\x90\xfe\xd4\x3e\x2c\x89\x2f\xdc\x65\x4d\x04\x7c\x05\xe1\x80\x8c\x99\x80\xf2\xf4\x62\x37\x64\x49\x7e\xd0\x8c\x82\xcd\xd3\xa6\x5e\x83\x82\xd7\x40\xe0\x35\x70\x1d\xe1\xe7\x84\x7c\xbe\xe9\x6e\x8b\xc2\x60\x4c\x5a\x9e\x00\x41\xa5\xc5\xa6\xd6\x14\x1b\xa6\xbe\x2a\xf2\x06\x43\xd2\xf2\xc9\x7d\x64\xd1\xe1\x2e\x79\xe9\xa1\xe4\x3c\x35\x05\x50\xdb\xe4\x08\x55\x3d\x6b\x52\x2c\xe2\x0f\xd5\x35\x44\xf6\x9d\xc2\xab\x32\x0b\x2b\x67\x8c\x2f\x0d\x47\x93\x33\xd2\x32\x8a\x0a\xae\x53\x0e\x18\xe2\x7d\x72\x0b\xd1\xf6\xc0\x2e\x1e\x71\xb8\xe3\xb5\xd7\x6e\xc6\xac\x9d\x28\x1c\x5e\x85\x1e\x84\x2a\x70\xed\x16\xc2\xea\x9d\xd9\x8d\xa2\xe8\xe9\x39\x3d\x5c\xfa\x3c\xa5\xc8\xe6\xf4\x2c\xe6\x51\x3f\x22\xfc\x7c\xce\xf2\x9d\x70\xbb\x29\xec\x81\x2b\x46\xac\x6b\x72\xe0\x8a\x78\xf6\xd1\x11\xd3\x6f\x3e\x2e\xab\xc4\xe2\x16\x8d\x13\xcd\x7c\x34\xdf\x85\xc2\x41\x19\xea\x0f\xa3\x64\x0a\x29\x53\x3a\xe5\xc6\xa6\x49\x7c\x2a\x87\x89\x87\xce\x88\xc7\xfc\x20\x71\xcc\x47\x73\xb2\x36\x3b\x5e\x05\x4f\xf7\x7e\x2b\x72\x2e\xf3\x88\x75\x44\xcd\x20\xed\xeb\xbb\x90\xc8\x25\x57\x43\xd1\xca\xe2\x41\x99\x51\x54\xdb\x8c\x75\xc1\xf2\xd6\x80\xca\x57\x1a\xac\x33\xda\xe0\x65\xbd\x67\xd5\xb9\x2b\xd2\x04\xe3\x48\x7f\xdd\xf0\x44\x29\xad\xa5\xa7\xee\x29\x30\x3a\x02\x26\x8b\xc5\x14\x70\x18\x0b\xf6\x4c\xe5\x0c\x4e\xe9\x83\xcf\x74\xfa\x02\xe3\x7e\xb5\x4e\xfc\xf5\x6d\xc6\xdb\xd7\x79\x46\xc7\x79\x4f\x73\xec\x8a\x5b\x0a\xea\x19\xb6\xb4\x60\x5c\x6b\xb4\xfc\xb2\x79\x01\x3b\xfd\x68\x5f\x0e\xbb\xbf\xc4\x65\x93\xf3\x30\x8a\x40\xba\x7f\x2e\xd3\xbf\x78\x14\xd0\x39\x81\x1f\x3f\x0b\x66\x60\xb9\x2f\xdc\x5a\x5e\x91\xaf\xf0\x84\x7d\xe5\x57\xe7\x42\x48\x52\x81\xc9\x6f\x37\x7a\x8c\x60\xf6\xd8\x40\xab\x51\xa9\x34\xb6\x06\xc6\xce\x86\xd0\xb1\x96\xf7\x83\x8c\xb5\x4c\xbb\x06\xa8\x77\x03\xe3\x6c\x1b\x5f\x37\xca\x5e\x3d\x74\x9c\x11\x3d\x1b\xd5\x53\x55\xa2\x8a\x9b\x5a\x37\x48\x47\x71\x0e\xe9\xab\xdd\xd2\x67\xb3\x45\xbf\x47\xce\x01\x4a\x03\x7d\x39\x02\xdf\x52\xf6\x00\x9b\x63\x81\x6a\x42\x3c\xec\x54\xbc\xdf\x4d\xb4\xa3\x42\xde\x3e\x3d\x29\xc4\x9c\x12\x6c\x0a\x12\x23\x3d\x11\x89\x76\xb9\x7e\xca\x11\xf5\x7f\xb9\x9f\xd2\x78\x8f\x04\x71\xf1\xbd\x76\x77\x18\x6f\x87\x0e\x85\xb1\xaa\x1b\xe3\xc5\x1d\x44\xfa\xed\x6b\x28\xb8\xe6\xc9\x6b\xe6\xe3\x2e\x84\x09\x9e\x40\x9b\x04\xc2\x05\xbe\x40\xc2\xba\x6b\x21\xa6\xe1\x7d\xa7\xf4\x21\x97\xc7\x1f\x48\x5a\x3b\x77\x67\x5f\x38\x9d\x7d\x56\xe3\xd3\xdc\xaf\xd1\x70\x19\x74\xf8\xd8\x3e\xac\xe1\xaa\xce\xd7\xb5\x3e\x78\x34\x47\xee\x3b\x72\xe4\x0f\x3e\xc4\x70\x3c\x38\x22\xf7\x93\xf4\x8c\x64\x34\x5c\x3a\x7e\x46\xe5\x42\xb2\xac\xb9\x2f\xd2\x50\x17\xf2\x47\x62\x93\x66\x55\xa3\xde\x93\xbd\x01\x17\x8b\x4a\xf5\x69\x38\x0e\x1d\xb5\x1f\xdb\x86\xdd\xb9\xa0\xf3\x75\x4d\xff\x35\x7c\x33\x35\x89\xa0\x2e\x61\x08\x0f\xd9\xcf\x78\x6e\x8f\x07\x6f\xf1\xe7\x58\x81\x30\x66\xe5\x31\x4b\x00\x89\xed\xbe\xac\x85\xee\xf7\xe1\xbd\x0e\x34\x3f\xe2\x1e\x95\x73\x7a\x52\x47\x7c\x89\xe7\x14\xc6\x13\x17\x7b\x47\xa3\x67\x6a\x11\x43\x88\xb8\x42\xb3\xba\x2a\xd9\xdc\xe4\xb4\x3a\x8d\xe0\x0f\xa3\xb4\x16\x6d\xe7\x36\x48\x97\x7d\x91\x57\xdc\x75\x7b\xcb\x81\x9d\x36\xc0\x88\xba\xd6\x92\x42\x8b\xcb\x2d\xf2\x79\x43\x3d\xfe\x4a\xdb\xbc\x89\x1d\x3b\x26\x5b\x38\x81\xa5\xd5\xab\x97\x94\x8e\x06\x34\xab\x7c\x72\x80\x71\x5e\xd6\xd1\x18\x7f\x39\xae\xa6\x01\x9c\x95\x99\xf4\x70\x48\x97\x2f\x55\xea\xae\x60\x15\x6d\x50\x3c\x3d\xe4\x63\xce\x78\xeb\x4f\xa6\xef\xd8\xcb\x41\xdf\xd8\xe4\xcc\x58\x5e\xcc\x6b\x43\x9d\x93\x17\x5d\x4d\x1d\xbe\x49\x8b\x17\xee\x68\x17\x27\x8b\x1a\xae\xc6\x04\x94\x50\x3f\xd0\x4c\x0f\x71\xa9\x41\xc4\x43\x9d\x60\xcf\x53\x36\xc4\xa7\x52\xc4\x5f\x1d\x92\x68\x20\x06\x66\x41\x0d\x84\xad\x74\x4c\x32\xfa\x6a\x58\xbe\x42\x5a\x91\xf6\xfb\xfa\x60\xd2\xcd\x98\x80\x70\xd3\xd0\x69\x44\x6c\x85\xb2\x4a\x17\x41\xd1\x4c\x78\x8d\x66\xc8\xcb\xae\x81\xdc\x00\xfe\x89\xd1\xba\xac\xe1\xf0\x82\xc5\xc6\xc0\xd0\x18\xe3\xd4\x98\x55\xd0\x90\x31\x08\xf0\x0b\xbd\x82\x13\xdb\x33\x9e\x43\x4f\xea\x39\x95\x4b\x61\xed\xda\x7c\xb8\x7b\xdb\xbe\xf0\xc4\x54\xe8\x1e\x90\x1f\x8d\x7a\xf3\xbd\x25\xed\xe5\x45\x22\xcb\xab\x54\x2a\xf0\xe1\x37\x43\xaf\x78\x76\x69\x32\x05\x56\x8f\x64\xe9\x39\x07\x27\x88\x1e\x61\x3d\xf3\x7a\x9e\xcb\xa3\xb7\x56\x49\xff\xb8\xb6\x78\xec\xa8\x18\x00\xac\x46\xd5\x06\xca\xdb\x3a\xb3\x87\x78\x2d\xa0\x0d\xca\x69\x0a\x21\x70\xbd\xa7\xf3\xd1\x3b\xba\x0e\x6d\x2f\xef\x59\xd0\xe8\x04\xd6\x70\x7c\x78\x28\xbf\xa0\x7e\xda\xea\xee\x42\x25\xa4\xc1\x57\xa7\x17\x9f\x7e\xe1\x46\x41\x29\xdd\x31\x53\xfa\x7e\x80\xae\xac\xd3\xf2\x3f\x45\x34\x04\xd0\xfc\xb7\x89\x3d\x4b\xd5\x52\x1d\x88\x8f\xa1\x30\x6a\x2a\x5e\x46\xc0\x52\x30\x2a\x39\x47\x48\xd8\x67\x0b\xf6\x50\x52\x02\xe4\xb1\x0d\xb0\x41\x72\x82\x1d\xe7\x58\xe3\xb2\x81\x1c\x16\x90\x78\x6b\x0c\xd2\xbd\x8a\xec\x1e\xec\xaf\x8e\x13\x81\x80\x17\x81\xf5\x00\x5b\xbf\x93\x71\x9a\xa7\xe5\x2d\x45\x25\x90\x43\x21\x17\x17\x50\x0b\xe2\x4c\xa9\x34\x22\xb2\x7a\xaf\xe3\x83\xda\xb2\x1d\x05\xea\xe1\x5c\xcc\x9b\xfd\xab\xb4\x5f\x19\xae\x4c\x85\x00\x23\x65\x22\x95\x10\xd6\x84\xc1\xd3\xd9\x7f\x44\xe2\x1c\x57\x19\x54\x81\x53\xd2\x81\x50\x29\xc7\xa5\xfc\x9c\x0e\x1c\xfd\x0d\x60\x80\x55\x6f\x7e\xda\xaf\xb3\x39\x2c\x4f\x9f\x60\x03\x67\x00\x0d\xf2\xd4\x5e\x4f\x8b\xe3\x26\xc8\x01\xaf\x89\xbe\x57\xcf\xe8\x4b\x35\xe9\x85\x30\xb2\xa3\x3c\xf3\x81\xaf\x30\x11\xfc\xc4\xa6\xf3\xe5\xb7\xe5\x01\x95\xf4\x8d\xc5\x12\xf4\xb7\x9a\xff\xba\x5d\x6f\xf1\x05\x47\x19\x9f\x9f\xa3\x70\xe7\x01\x0d\xac\x88\x84\x2b\xe8\xe9\xa6\xdb\x0a\x2a\x1f\x8c\xd6\x48\xb3\xbc\x45\x4c\x85\xb7\xa2\x20\x98\x62\xbd\x35\x91\x70\x12\x64\xd8\x4c\xc4\x5f\x52\xd3\xa5\xaa\x0f\x06\x4a\x60\x77\x10\x44\xb5\x1b\xad\x63\xf2\x43\xaf\x6c\x0c\xc2\x10\xe0\x00\x0b\x3c\xa3\x6c\x56\xb5\x73\x27\x60\x61\xc9\x62\x70\x48\xfa\xfb\x88\x96\xf7\xab\x9d\xa9\xba\xd8\x83\xb5\x85\xb7\x59\x83\xa0\x22\x7f\x0c\xe2\xba\xbd\xd2\x7e\x70\xcc\xdf\x2e\x98\xf2\x7c\xd2\x54\x30\xc6\x3f\xca\x28\xd8\x43\xd2\x8c\x9f\xe9\x59\xb3\xe1\x64\xa4\x06\x54\xca\x63\xa0\x9b\xa7\xd8\x99\xe8\x6b\x4d\x43\xf2\x00\x62\x61\x82\x32\x78\x01\xa2\x47\x0e\x4d\x85\x78\xad\x95\xd8\x9a\xa4\xb0\x36\x87\x48\x46\x04\x22\x8b\x22\xf1\x1d\x12\x97\xff\x76\x20\x47\xc3\x68\xd6\xc3\x10\x5d\x7e\x6c\x9d\x4b\x13\xc0\x02\xc1\x1c\xb4\x06\x04\x18\x24\x6e\x1a\x28\x4c\xf1\x62\x6e\x24\x45\x9f\x2d\x18\xb6\x82\xd1\x90\x99\x70\x6f\xa5\x85\x61\x54\xbc\x8e\x33\xc1\x27\x81\x66\xa9\xf1\x72\x8d\x49\xb5\x61\xea\x6c\xa0\x02\xaf\xef\x34\x9b\x3b\xcf\x7f\x0f\x25\xa9\x05\xd5\x86\x8c\xd4\xc4\x57\x45\xe8\x7f\x9e\x51\x6a\xab\x2b\x69\xa9\x22\x5c\x94\x07\x36\xa8\x75\xd7\x32\x0b\x4f\x16\xfb\xa0\x97\xff\x11\x9d\x2c\x03\xc6\x47\x1f\x97\x3e\x6e\x1c\xde\x25\x2d\x75\x9a\x27\xac\x77\x16\x38\x0f\x5f\x69\x06\x1d\x4a\xfe\x71\x58\xf9\xa3\xa9\xee\xb0\xd2\x6c\x30\x6b\x44\x85\x95\x3e\xbb\xf2\x25\xad\xa0\xca\x18\xfe\x4b\x90\x3e\xfd\x93\x67\xa4\xe7\xa6\xdf\x67\x5e\xd2\x9a\x95\x28\x61\x0d\x9d\xe4\xf3\xac\xac\x94\x92\x86\xd3\x48\xe6\xe5\xe9\x11\xce\x82\xa2\x6c\x23\xa3\x2a\xe6\x7e\x0e\xf6\x94\x97\xd3\xc5\x1a\xe9\x29\xd5\xdc\xce\x65\xc0\x04\x2c\xcb\x33\x0f\x4c\x5d\xf8\x2c\xac\x2e\x70\xae\x9f\x60\x76\x3a\xcd\x57\x1e\x36\x32\x7c\xaf\x1e\xd9\xf7\x18\x89\x5d\x80\xb8\xfc\x18\xc1\xcb\xc5\xa3\xa9\xac\x5e\x4a\x06\x01\x2b\xc7\xe7\xd4\x71\xbd\x58\x72\x4a\xa5\xc5\xb0\x19\xea\x81\x2f\x8c\x61\x9e\xc2\x62\xd8\x12\x0a\xbb\x91\x60\x85\x17\xdd\xb0\x5a\x91\x3c\xfc\xe2\x81\x54\x06\x56\x62\xec\x3b\x6f\xfb\xc3\x9f\x76\xec\xdc\xfe\xc5\xce\xee\x09\x5e\xbe\xa1\xed\xd0\x87\xa7\x40\xc7\x49\x6f\x43\x65\xe4\x57\xfb\xf6\xe9\x5c\xf9\x63\x37\x0d\x2f\xd1\xd3\xe9\xf4\x88\x2d\x93\x96\x64\xc7\xb6\x9d\x18\x2e\xc0\xc2\x17\x17\xf9\x7d\xf6\xe8\xb2\xea\x2e\x47\x4b\x9e\x77\x05\xf8\xc1\xbb\xfb\x0e\x1c\xd8\xf7\xee\xce\x7f\xec\xf0\xd4\x65\x9c\x7f\xbf\xff\xc1\x4f\x3f\x7d\x70\x72\x9b\x36\x30\xb3\xf5\xa8\xf4\xda\x6c\xc0\x7a\x6f\xbc\xff\x8d\x1f\x76\x0e\xf5\xed\xff\x3e\x7c\xe7\x74\xf5\x79\xe9\xa9\xd6\xb5\x9b\x82\x42\xd7\xad\xb6\x54\x75\x70\x9c\xbd\xd8\x6d\x18\x5f\xb5\xe0\xb6\x25\xb5\x6d\x8b\x7a\xfd\x63\x91\xb9\xc3\x4e\x45\xa8\x28\x9a\x4f\xc7\x11\x0f\x1e\x44\x7d\x8c\xcb\xb9\x0b\xc0\x38\x19\x04\x25\xd9\x9b\xa2\x09\xe0\x15\x2f\x56\x83\x94\x11\xcf\x16\x61\x91\x4d\x12\x8d\x03\x02\x72\x88\xdf\x38\xc7\x8a\x0d\x9a\x2c\x18\xbb\x33\x52\x2c\xde\xf5\xa7\xdd\x77\x5f\x56\x5e\xc2\x58\x6b\x86\xdc\xf5\xfa\xeb\x20\xf9\xfa\x61\xa8\xf2\xc4\x27\x56\x5a\x2c\xaa\xf7\x43\x4c\x7b\xd5\x54\x70\x55\x22\x32\x76\x68\x7b\x5e\x8c\x96\x53\x70\x26\x00\xb4\x98\x93\x8d\x36\xb6\x9d\x0d\x36\xb6\x6d\xdb\xb6\x6d\x9b\x1b\x6f\x6c\xdb\xb6\x9d\x8d\xed\xe4\x8f\xff\xd8\xc9\x1f\x77\xda\xe9\xbd\xb7\xd3\xce\xb4\x7d\xf9\xce\x37\xdf\xcc\x79\x39\x4f\x67\x0a\x0b\xdb\xd5\x54\xb5\x89\x86\xf9\x9f\x09\xe4\xaf\x37\x45\x24\x40\xb3\xb2\xa8\xfd\x3f\x2f\x8b\x95\xc1\xd0\x6a\x06\x5f\xa1\xdf\x34\x6d\x1f\x12\x3e\xc7\xb5\xed\xc2\x1c\x8c\x1a\xfd\xcf\xab\x53\x16\x51\x8f\x4f\x03\x4e\xaf\x49\xcf\x54\x43\x9e\x92\x27\x48\xf9\x46\x98\x11\x48\xd4\x3f\xf1\x2c\x91\xa5\xeb\x60\x29\x74\xff\xc1\x0b\xf6\x5b\x29\x00\xfd\xbf\x17\xc4\x1c\x19\x36\xb6\x22\x0b\xa6\x0b\x4d\xdf\x47\xb7\x5b\xa2\xec\xfd\x6b\x9b\x64\x90\xa9\x4c\xbd\xf7\x9f\x48\x2e\x33\xe1\xd0\xc2\x89\x09\x50\x76\x68\x58\xdc\x91\xb6\xaf\xf9\x19\x39\x66\xdd\xef\xf6\xb5\xb8\xac\x56\x31\x2a\x70\xa1\x6c\x11\xec\x08\x03\xed\x4a\xfe\x9a\xab\x65\xfd\x48\x1d\x4d\xa8\xbb\xcd\xac\x3d\x68\x55\x2a\xe4\xb4\x42\xe3\x09\x2c\xf3\xd2\x2a\xb1\xf2\x52\x1e\xab\x97\xb5\x42\xe4\x81\xea\xc1\x0a\x1a\xac\x36\x5e\x8b\xaa\x09\x50\x91\x00\x3c\x16\x8d\x51\xc0\x71\x40\xe4\x30\xc4\x3e\x27\x64\x79\xd5\x07\xb6\x30\x11\x9e\x3f\x4c\x63\xa5\x4b\x2c\xbb\x0e\xb9\x33\x68\xc4\x46\xdb\x15\x16\xb8\xbd\xef\x00\x15\x8d\x19\x8c\xc4\x9d\x3c\x6e\x79\x70\x0a\x1e\x2b\x08\x35\x0a\x3c\x06\x6a\x13\x93\x9c\x07\xcc\xc4\x29\x43\x78\xa5\x08\x9c\xb4\x5d\x6f\x8d\x94\x56\x6d\xff\x6d\xb0\x4e\xce\x90\x73\x66\xcb\x9d\x6b\x85\xfe\xf8\x17\x4f\x89\x76\x47\xe0\xc5\xbd\xd3\xf7\x74\x25\x13\xa9\x52\xce\xca\x9e\xa1\x57\xf9\xb6\xea\x23\xef\xf4\x60\x65\xb9\xf8\x2a\x50\xcf\xa4\x3b\x73\x38\x52\x30\xa3\x9b\x5e\x95\x9d\x24\xa3\x50\x27\xbf\xe2\x7d\x39\xd8\xd3\x28\x91\xad\x3d\xd8\x9f\xd0\x14\xbb\x89\x36\xbf\x9c\x50\xa3\xd8\xf5\x88\x68\x91\xac\x70\x36\xd1\x33\xfe\x1c\x74\x51\x5f\xa1\x83\xdd\x1d\xee\x09\x99\xb3\x6b\x42\x7a\xb9\xcc\xcb\xdb\x76\x6a\xbb\x9c\x53\xcd\x6d\xa8\x8f\xba\xdc\x54\x23\xa8\x02\x70\xc2\x10\xfb\xa0\xab\x46\xd6\xa8\x7c\xc8\xd6\xcf\xd1\x39\xec\x75\x40\xf8\x87\xc3\x81\xed\x4d\x20\xcc\x1b\xa8\x7a\xf6\x56\x65\xbb\x86\x5c\x14\x7c\xf6\xad\x69\x6d\xd4\x00\x03\x91\x96\x74\x46\x12\x0d\x14\xd2\x2f\x20\x75\x6b\x30\x1f\x92\xb5\xa7\x54\x08\xc7\x5e\x9b\x8e\xba\x23\x71\x73\x22\x54\x03\x22\x6c\x86\xad\x0a\x8a\x95\x85\x92\x06\xd8\xab\x54\xaf\xd1\x0e\xb8\x07\xe1\xcd\xe3\xa2\xa0\x02\x29\x11\x07\x75\x96\xb8\xc9\x2a\x14\xe3\xe1\x48\xc8\x7e\xb6\x86\x4b\x88\x84\xca\x53\xfe\x68\x45\x42\x17\x46\x40\x0f\x96\xa1\xfc\x51\xaa\x24\x16\xd3\xe2\xa3\x64\x08\xd6\xa4\x40\x76\x50\x7d\x57\x51\x6e\x6a\xfe\x0c\xd3\x6b\x14\x74\x0c\xe2\x51\x42\xbe\x3d\x40\x93\x3d\xa2\xca\x82\x47\x87\x37\x62\x80\x33\x25\xd1\xce\x13\xcb\xdf\x10\x2b\x5c\xb3\xac\x3d\xe3\x81\x66\x5e\x91\xb1\x01\xde\x47\xb8\x28\x97\xa8\xc3\x56\xf7\x79\x4b\x75\x93\x71\x18\xfa\x48\xbd\x7d\x2e\x73\x9a\x16\x23\xbc\x19\x2b\xc6\xef\xb0\xdc\x5b\x8f\xb8\xd2\xae\x10\xbc\x84\xec\x6e\xb9\xfa\x44\x8a\xd9\xdf\xac\x6f\x1a\x54\x80\x6f\xbb\x13\x13\x43\xc9\x06\x0c\xc2\xa5\x1e\xcf\x60\x4a\xef\xe8\xe1\xc8\x20\x64\xff\xb5\x5b\x6f\x28\x0b\x2e\x2e\x52\xcd\x96\xc4\x18\xe3\x5a\x2a\x57\xd6\xf4\xaf\xc8\x78\xe8\xa9\xf1\xed\xf8\x90\x09\xcd\x3e\x25\xac\xdd\x2d\x58\x45\x2f\xe2\x56\xa6\x27\x74\xb9\xf3\x4e\x26\x75\x92\xf0\x97\x00\x03\x4b\x87\x96\x15\x46\x54\x3a\xf7\xa7\xf8\x55\x94\xc0\x62\xbf\xa3\xb9\xcd\x52\x62\x2a\x2f\x1b\x20\x28\xa8\x35\x13\x65\x79\x5d\x64\x81\xbe\xc3\xc1\x4a\x2c\x71\xe8\xdb\x9f\xcf\x98\x73\x22\xfa\x19\xe8\xa5\x4e\x1c\x77\xf5\x19\x60\xe5\x75\xb4\x74\x10\x64\x88\x06\xfd\x21\x06\x1a\x38\x42\x61\x82\x15\x63\xdc\xfa\x5d\x6d\x99\x0c\xa1\x3b\xf1\x75\x5c\x82\x12\x70\xba\x70\xf0\xc6\xff\x60\x23\x99\xb0\x1a\x2e\x11\xe1\x56\xac\x83\x77\x72\x55\xc9\xc0\xfb\xa1\xa0\xc5\xf5\x4a\x3d\x95\xc7\x1d\xce\x2a\x66\xfb\x32\x6b\x4b\x10\x0c\xfd\xe2\x24\x35\xdb\xd8\xce\xf1\x06\xdc\x12\x86\xff\xb7\xbf\xfb\xcb\xbf\xd3\x73\xc6\xd7\xb7\x4c\x61\xe7\x61\x37\xab\x57\xa8\xdb\x52\xcc\x43\xdb\x03\xb7\x07\xf3\x8b\x4e\x37\xb9\xd6\x38\x30\x8d\x02\x04\xd5\x50\x3e\x52\x8c\xcf\x5e\x04\xbb\x83\xc3\xfb\xe1\xa0\xf4\x01\x74\x8d\xe7\x75\xd5\xf9\xed\xf5\xe2\xb4\x90\xd8\xfb\x10\x89\x44\x5c\x4b\xfb\xf8\x0a\xef\x5e\x2c\xc9\x36\xbb\x17\xe9\x5a\x10\xf9\x1d\x7e\x28\xc0\x4f\x81\xd1\xe3\xca\xa5\xd1\xed\x18\xb0\x03\x54\xe6\x51\x74\x13\x9c\xbf\xc9\x6c\x3b\x1d\xd9\x64\xa7\x6a\x18\xb7\xe0\x77\xb3\x2c\x74\xc3\x5c\x87\xa4\x68\x38\xbb\x30\x0c\xe9\x3e\x63\x5b\xa7\x9f\xe1\x7e\x81\xef\x7a\xd0\x4b\x48\x01\x97\x3c\x23\x72\x6a\x51\x9c\x4b\x5a\x47\x13\xaf\xc0\x18\xe3\x3c\x74\x7d\x63\x92\x2a\x00\xba\x97\x11\xc8\x81\x11\x8e\x9b\x36\x6b\x2e\x8f\x0b\x89\x80\x8d\x7d\xa8\xe1\x5d\xe8\x47\x2c\x39\x80\x8d\x0d\x8d\x5f\x6e\x78\xcb\xbe\xd4\x64\x5b\xd8\xd3\x77\xee\xaf\x33\xbf\xbd\x7c\x27\x6e\x6b\x04\x76\xf9\x1d\xad\x8f\xba\xc3\xd0\xce\x58\x9c\x0d\x27\xe4\x15\x52\xe5\xbc\xd7\x17\xfc\xd8\xe5\xac\xde\xe1\xb0\xfc\x85\x8f\xd7\xe7\x79\xd6\x79\xf9\xb8\x05\xe5\x01\x9a\xe2\x9c\x7f\x44\x64\xcc\x07\x9d\xc4\x6c\xde\x4d\x49\xc4\x53\x4f\x45\x32\x6e\xde\x28\xa4\x95\x27\xdd\x7a\x6e\x50\x0d\x60\x5b\x12\x4b\x65\xe3\xec\x80\xf0\xf5\xe2\xfa\xc6\x2b\x0c\x0c\x6f\xb8\xf5\x05\x58\x53\x15\x53\x95\x52\xad\xd8\xf4\x64\x6a\x4b\x1d\x0a\xbf\xbc\x06\x37\xc1\xfe\x48\x17\xe6\xbc\x08\xb3\x2d\xe9\xf3\xb0\xdc\x12\x38\x71\x73\x6e\x58\xb3\xa9\x65\xf8\xf4\xfe\xd3\x56\xed\xad\x93\x90\x37\xa6\x4b\x74\xd6\xfa\x29\x3b\x45\xb4\x32\x3f\x2f\x8c\x21\x33\xb1\xc3\x4d\xd1\xb7\x4b\x6b\x26\x26\xf1\xf9\x77\xf4\xf9\x29\xb6\x0f\xfb\x29\x7a\xbd\x31\xf2\x8f\x98\x88\x44\x8d\xdb\x6f\x39\x09\x43\x96\xa4\x05\x33\xb4\x71\x34\xc2\x94\x4e\x77\xb2\xe5\xfd\xe0\xdc\x8e\x92\x23\x71\xee\x60\xa2\xd3\xea\xdb\x57\x9a\xba\xf8\x65\x0c\x31\xbd\xeb\x89\x61\x28\xf6\xbf\x51\x5b\x98\xaf\xc2\x90\xe1\xec\xbd\xe0\xf3\xb1\xc9\xbb\xef\xfb\x98\x8e\x7b\x8b\xc6\x99\x81\x4f\x3a\x9e\xf6\xe1\x5b\xd9\x12\xfd\xa5\x06\x9e\xe1\xcd\x72\xdd\x1f\xe7\xd9\x11\xf8\x3b\x4b\xaa\xe5\x3b\xa6\xc8\x37\x5a\x1c\xb2\xb4\xec\x96\x16\x16\xe7\x96\x6b\xc3\xea\xb5\x7b\xd9\x1b\x1e\xb2\x5d\x2d\xae\x0e\xaf\x47\x41\xcc\xca\xb3\x2d\xf1\x30\xab\x63\x59\x34\x67\x72\x54\xaa\xfa\x29\xb4\x24\x71\x01\x8d\xd1\xd4\x31\x9a\x8a\xb2\x14\x9a\x08\x4f\x11\x54\xed\x44\xf4\x33\xac\xa9\x08\xda\xdb\x4a\xf4\x70\x1a\x56\x65\xea\xcf\x7c\xc3\x23\xf5\xed\xef\x84\x2b\xe8\xe3\x1a\x4d\x78\xf4\x64\xe9\x89\xc6\x8a\xc1\x33\x86\x49\x79\x43\x1f\x95\x34\x58\xd5\xd1\xfe\xac\x0e\xa5\xdd\x15\x13\xbd\x8b\xfa\x7a\x97\x5f\xe9\x96\xb7\xa9\x9f\xe3\x27\xfc\x6e\x2e\x57\x25\xb0\x82\x7e\x2f\xef\x8b\xba\xae\x34\x87\x47\xf9\xe3\xab\x50\x61\xe3\x3a\xdc\xfb\x53\xb0\xd5\x9c\x3b\x6d\x17\x9e\x33\xa5\xb7\x4e\x7e\x8f\x40\x2f\x93\x47\xab\x33\xb3\x17\xff\x98\xec\xea\x17\xfa\xcc\x7e\x25\x00\x4d\x92\x87\xeb\x52\x0c\x6d\xba\x74\x3e\x9b\xd9\xf3\xfa\xe0\xbf\xa2\x58\xbf\x40\x53\x6b\x55\x5e\x14\xbe\x1d\xbf\x47\xe0\xbf\xe8\xd7\xd4\xb5\x5d\xff\xe3\x8e\x92\x29\x89\x6c\x6e\x7f\x36\x33\x03\x0f\xc4\xe4\x4a\x33\xef\xd5\x0a\x6c\xb0\xf4\x72\xe1\x87\x87\xd3\xeb\xa6\xe7\x2f\x96\x9e\x38\x38\x34\xfa\x60\x33\xae\xbd\x24\xa0\x6a\x41\xeb\x09\x17\x93\x98\xf9\xa0\x58\x67\xff\xb6\xe3\x9d\x2e\x5a\xda\x48\x10\x7f\xfb\x16\xb7\xf5\x9a\x23\x1b\xfe\x96\xe5\x8e\xd3\x70\x8d\x35\xfb\x03\xf6\x5e\xdf\xf7\xd1\xe4\xe7\xcb\x17\x9a\x9c\x41\x93\x19\xf5\x1b\x8c\x5c\xa8\xd6\xcf\x0e\xca\x3d\xd7\x99\x89\x49\xce\x7e\x37\xd7\xa7\x9c\x0d\xad\xfe\x83\x38\x76\x59\xe9\xb1\x95\xd0\x4e\x08\x3e\x4e\x48\xd7\x43\xf3\x8c\x82\x65\x63\x1b\xf1\x50\x02\xc7\x47\xfc\x62\x6e\xaa\x60\x9c\x41\x09\x03\xe6\x5f\xd9\xf0\x51\x72\xdc\x55\x97\x30\x2f\xb1\x89\x02\x04\x81\x73\xb6\xef\x17\x92\xcf\x04\x67\xb8\xda\xdf\xdb\xb9\xcd\x16\x67\x06\x72\x6d\xf2\x2a\x86\x96\x6d\x91\x38\xe7\xdb\xaa\xa5\x5d\x66\xee\x95\x8f\x10\x1e\x49\xf6\xde\xaa\x96\x8a\x8a\x96\x4b\x2e\xba\xaa\x8d\x44\x12\x72\x28\xef\xff\x46\x0e\x1f\x71\x42\x96\x06\x8b\x76\xb9\x82\xb3\x64\x76\x24\x94\xcb\xbc\xe0\xdc\x91\x38\xfe\x45\x98\x27\x76\xf8\xa0\x84\x57\x08\xf8\x00\x38\xc7\x1a\xe7\xc0\x9a\x5e\xe3\x98\x27\x1b\xf4\xd9\x33\xa3\x45\x57\xc3\x16\x12\x76\x16\x0b\xe5\xd6\x4b\xc0\xe5\x2d\xa8\x39\xa1\x8b\x29\xf5\x10\x45\xff\x25\x53\xd9\x7a\xef\x8b\x45\xf2\x6b\x91\x32\x80\x3d\xca\xef\x6a\xb9\xe3\xba\xe3\xbb\x39\xb9\xae\x37\xbe\x11\x5e\x19\x38\x76\xa7\xab\x56\xd1\x5c\x39\x07\xaa\x6d\x73\x3d\xdb\xf9\x52\x54\xf8\xa8\xd5\xc0\xc5\xab\x29\xda\xaf\x77\x67\x3f\xd9\x10\xf0\xc4\xfc\x10\x63\xd0\x15\xa0\xd1\xe8\x9c\x5e\x57\x71\x78\x16\x51\x0f\x50\x4e\x8e\xec\x2f\xf3\xdd\xcc\x8b\xf0\x8e\xa4\xd4\xfc\xda\x3c\xfb\xbd\xa9\xf3\xd1\x83\x38\x59\x17\xe1\xd1\x6c\xfb\x97\x07\xf6\xb7\x0a\x9d\x52\xd8\xe5\xe2\xef\xf1\xc5\x93\x8f\xb3\xb3\xa1\x38\x44\xf6\x35\xbd\xc6\x1a\x35\x1e\x8a\x1d\x71\x8c\xe6\xeb\x15\xf6\x8e\x2a\x78\x5b\x96\x60\xf5\x66\x1e\x1e\x0b\xc2\x7b\xcb\x7f\x2a\x5f\x61\x10\x8d\xbb\xcd\x97\xa4\xf3\xc9\x93\x66\x5c\xf6\x31\x8c\xaa\x19\x2d\xbb\xf3\xa3\x6e\xc8\xfc\xdb\x8f\x59\x3a\x88\x46\xc3\xbb\x97\xd2\x41\x25\xbc\xad\x22\x6f\x57\x4d\x19\x9d\x45\x49\x31\xd9\x8b\x1a\xea\xc6\x16\x6e\x44\x25\x44\xc4\x1b\x20\xf3\xaf\x8e\x0f\xc8\xd8\xfc\x86\x45\xd8\x04\x26\x6a\x46\xa7\xde\xbe\x42\x28\xcc\xf0\xd6\x85\xab\x42\x52\x53\xf5\xd2\xb8\xac\x7b\x99\xb1\x72\x24\xce\xd1\x20\x7e\xb3\xc8\xf7\x2b\x52\xfd\x64\x56\x6b\xf7\x2a\x5a\x1a\xb6\xb1\xa0\xde\x6d\xd6\x11\x14\xbc\x02\x57\x54\x72\xbd\x11\x28\xe8\xdf\x71\x23\x2a\x35\x96\xf0\xb5\x15\xe0\xe2\x28\x89\xad\xe8\x0d\x7f\xd2\xe2\x9f\xf7\xed\x6b\x9c\xa2\x92\x53\x71\xb4\x38\xd1\xeb\x8b\xbd\xab\xaa\xf7\xb3\xe5\x44\xd3\x75\x94\x2d\xad\x1d\x0c\x02\x6f\x54\x3c\x7c\xac\x7d\xd5\x7d\xfd\x68\xda\x1f\x77\x9f\x66\x66\xd2\x78\xc2\x79\xde\x69\x07\x3c\x2b\xac\xc5\xa5\x8c\x35\xbf\x9d\xb9\xb7\xd4\x23\xea\xd2\xdd\x1b\x15\x6f\x94\xb7\x94\xf1\x6a\xaf\xc1\x7a\xaa\xf8\x05\xaa\x6a\x4b\xed\xe5\xac\x61\x7a\xef\xf5\x52\x84\x9a\x7a\x0a\x35\xef\xad\x4d\xd5\x5f\x5b\xdc\xaf\xa6\x6f\x3f\x8c\xe6\xd7\xa6\xdb\xea\xb3\x35\x0c\xcc\xe5\x1e\xfe\x5d\x7e\x0a\xd6\xaa\xaf\x2f\x4b\xab\x01\x21\x4c\xad\xfc\xd8\x03\xb9\x7a\x9f\x5c\xd4\x34\x54\xec\x55\x97\xbf\xd4\x94\x0f\x69\x51\x47\x33\xda\x03\x0a\x76\x4d\x71\x57\xe2\x29\x9c\x12\x1f\xc0\x8b\x8b\x63\x1a\x8a\xd2\x2f\x27\xc9\x22\x7f\x02\xcb\xaa\x49\x35\x82\x91\x4b\x54\x8b\x8c\xc4\x18\xf1\x63\x0f\xf4\xcc\xaa\x09\x5b\x07\x47\x7f\x42\xe2\x7c\xf5\x20\xed\x85\xe9\x22\x14\x69\x78\x93\xd6\x14\xa8\x8b\x47\xd6\x99\x0d\x85\x17\xeb\x86\x80\x41\xea\x4a\x60\x46\xae\xb7\x46\x0e\x55\x34\x09\x87\x8b\xee\x3c\x61\x6d\x69\xf0\xb1\x21\x07\xf5\x14\x8e\xda\xd3\x05\x59\xb7\x7e\x96\x52\x8b\xf2\x96\x7a\x02\x9f\x87\x2c\x72\xb6\xf5\xd6\x15\xfa\xdf\x63\xaa\x5c\x08\x13\xe2\x20\xff\x64\x23\x6f\x0f\xfc\xa5\x1d\x90\xd5\x23\xd9\x5c\x8d\x9e\xb2\xb3\x8f\x81\x8e\x56\xc8\xcf\xc3\x08\x9e\x42\x03\xc6\xf9\x6b\xce\x14\xf4\xee\x76\xac\xe0\xcd\xbd\x30\x2d\xd5\xb9\x24\xb7\x19\xa7\xfc\x42\x62\x71\x27\xca\x9f\x53\x1d\xef\x51\xab\x29\x68\x26\xf5\xf9\x5e\x8f\x4e\x13\x1c\x80\x6e\xdf\xbb\x71\x08\x7a\xb9\xa2\x8d\xb1\x05\xb9\xe2\xbc\xa5\x06\x1c\x11\x34\x96\x95\xbe\x68\x86\x69\x84\xe0\xd6\x6c\x19\xa6\xa5\x6b\x9e\x78\xc2\x10\x09\x2c\x06\x4f\x86\xab\xa8\xa6\x3d\x60\xbc\x4b\x0b\xbe\x23\xf1\x1e\x97\xf9\xa9\xfd\x9c\x2c\x72\xb6\x61\x27\xfb\x65\x8b\xa0\x4e\x3b\xfd\x83\x96\x10\x5a\x18\x2f\x9c\x99\xad\xdc\x65\x5d\x02\xbf\xc1\x0d\xa5\xc4\x9b\x56\x5a\x21\xd2\xbb\x28\xf2\xef\xea\x30\x53\x82\xbc\xb6\xa9\x56\x71\xee\xf1\x47\xe1\xbd\x53\x14\xd2\x0a\xc4\xa5\x99\xa6\x40\x59\xa8\x33\x2d\xad\x0e\xa4\x09\xd0\xbe\xd1\x84\x18\xdf\xda\x6e\x2a\x5a\xdf\xde\x48\x18\x6b\x07\x41\xc7\xe0\xae\x17\x46\x6e\xa0\x24\x6d\x37\x69\xd6\x4f\xeb\x0d\xd3\x84\xcc\xd6\x7d\x31\xc0\xe9\xd0\x8d\x0b\x59\xc4\x62\xd9\x4b\x40\x17\xb9\x82\xf2\xcc\xd4\xa2\xee\x0b\x99\xc9\x17\xae\x06\xad\x64\xf2\x51\xff\x64\xe9\x16\x0b\xe9\x1e\xac\x8b\x98\x15\x7e\x18\x63\x3a\xdf\x3b\x80\x72\x4e\xea\x86\x55\xe9\x0e\x35\x39\xc2\xcf\x1e\x1b\x07\x09\x53\x5f\xd7\x88\x53\x2d\x44\x52\x1b\x6f\xd9\xc5\xc2\xe1\x29\x95\xae\x3b\xfe\x78\x6c\xe1\xd2\x96\xe0\x1d\x13\xe2\xc9\xe2\xa4\x9c\xc0\xeb\x94\xd1\x51\xf6\x0f\xba\x61\x2f\x7c\x5b\x1f\x62\xc4\x27\x8d\xef\x1b\xe1\xfc\x63\x93\x5b\xc3\x67\xf3\x82\x50\x7d\x49\xf2\x0c\xc1\xf6\x3b\x0b\xe8\xe9\x97\x25\xf1\xfb\x03\x7f\xfe\x30\x26\x63\x50\x39\x52\x9e\xef\xc9\x61\x36\x96\x9c\xe5\x3a\xbb\xaa\x20\xf0\xf5\x77\xbf\x1d\xa6\xac\xe0\x70\x93\x29\x72\xc3\x63\x3e\x29\xa4\x21\xd3\xc0\x04\xeb\x20\x2c\x41\xc6\x6c\x33\x45\x33\x26\x00\x11\xb3\x17\x71\x7b\xb2\x41\x05\x57\x71\x2d\x3e\x72\x1b\x93\x1e\x41\xb5\x31\xa5\xb8\xbe\xe4\xcc\x1e\xa1\xdd\x05\x7f\x66\x88\x77\xe3\x8b\x2f\x07\x3e\xee\xe3\x70\xb2\x8a\xfa\x6a\x8d\x59\xeb\xf6\x61\xb2\xba\x30\xca\xee\x0c\x7e\x3a\x9a\xe2\x94\xcc\x98\xe4\x64\x15\xea\x14\x16\x62\x36\x43\x72\x25\x6f\xf1\x19\x32\xdd\x83\xca\x64\x41\x6b\x28\xf7\x04\xed\xaa\x94\xe8\xa9\x43\x27\xa3\x92\xf0\x65\x22\xf7\x66\xfb\xcf\x17\x00\x3a\xb9\xae\xbb\x7a\xdf\x2e\x82\xc4\x82\xc0\x1e\x48\x46\x89\xbf\xe3\x2f\xa9\xa4\xc5\xed\x3b\xdb\x80\x46\xb9\x97\x58\xae\x72\x8c\x7b\x9f\x99\x64\xec\x6a\xa1\x19\x9f\xc1\x0c\x71\x6d\xe0\x37\x4e\x18\x83\xbd\xe3\x1c\xc9\xf6\x56\x31\xeb\x86\xb6\x37\x8b\xb6\x1e\x97\x2c\xb6\xd4\x4d\xe5\x39\x7d\x45\x95\xe8\xa9\xa6\x22\xbe\x6c\x66\x03\xde\x98\x3f\x65\x1d\x5c\x80\x1a\x73\xe6\x4f\x38\x22\xa9\x0e\xc1\x89\x5f\x6f\xca\x70\xc7\xe0\x3f\x4b\xca\xe0\xe3\x3a\x25\x8e\x63\x1f\xfb\x61\x53\xba\x80\xca\x5c\x1f\x4c\xbc\x93\xc8\xbf\xc9\xa4\x73\x46\x87\xab\x3a\x7b\xef\x2c\xfb\x87\x16\x2d\xba\x43\x86\xce\x19\x94\x51\x70\x45\x09\xf6\xaf\xf3\x30\x48\x63\x1e\xee\x94\x5a\xd8\x37\xad\x20\x9a\xa9\x82\x73\x09\x7f\xbe\x9a\x41\xa4\x9e\x8e\xff\xac\x9a\x90\xd9\xdb\xac\xc4\x79\xb7\x67\x6c\x71\x36\xdc\x5e\x7a\xac\xb8\x8d\x66\x41\xb0\x7a\x13\x02\x67\xf9\x0a\x96\xa5\xd9\xef\x72\x8f\xa6\x83\x29\xad\xe3\x79\x50\x63\x58\x04\x89\x4a\x92\xf4\x81\xfc\xd5\x2a\x16\x5f\x24\xae\x50\xc3\xd8\x77\xff\xf7\x65\x31\x98\xd4\xee\xcf\xe7\x10\xf3\x53\x80\x8a\xcf\xa7\x33\x7e\xff\x2f\x06\x45\xe4\xe3\xa6\x25\x30\x93\xf3\x55\xdf\x55\xc7\xe3\x28\x16\xf1\x4d\xda\x4e\x15\x49\x67\x63\x63\xe3\xc6\xe2\x94\x6a\xbb\x84\x0c\x1d\x95\x44\x99\xb8\x9d\xfb\x64\x7a\xdd\x80\x21\xd0\x5b\xf5\xa2\xee\xe3\x46\xfa\x13\x56\x0c\x91\x06\x90\x1e\x42\xed\x72\xc1\x8e\xec\xea\xe6\x26\x48\x94\x6c\x9e\x8e\xc0\xc7\x93\xa9\xcf\x72\xa1\x46\x66\xac\x92\x93\x36\xd5\xa2\x37\xb9\x32\xa7\xb5\xc2\x92\xaf\x66\x3c\xdc\xf1\xef\xd7\xfc\x69\xd0\x8f\x0c\x1a\xa7\x49\x10\xd8\x32\xb6\x8a\xe4\xbe\xe3\x62\x3e\xe5\xf1\xcd\x12\x85\x29\x84\xc1\x76\x80\x6e\x14\x79\xf0\x1f\x48\xdd\x83\xbf\x95\x0c\x84\x9e\x10\xeb\xdd\xf9\x7c\x13\xc4\x92\xaf\x9e\x23\xe1\xe0\x2d\xee\xb0\xd8\xf0\xe9\x03\xad\xc6\x15\x69\x29\x62\xa5\x3a\x0c\x0e\xeb\x17\xdf\xa1\x94\xe2\x18\x8f\xee\x12\x63\x6f\xd7\x37\xf9\xe0\xa2\x01\xc5\x99\xc7\x17\x72\x86\x0f\x7d\x3b\xac\x5f\x45\x58\xd0\x73\x89\x27\x33\x1e\x2f\xec\x47\x99\x7d\xab\x9f\x55\x8c\x57\x7a\x39\xa4\x90\x7f\x2a\x7b\x02\xd1\xe1\xa7\xab\xb1\x7d\x44\xd6\x06\x3a\x71\x6c\xad\x30\x0a\xbc\x43\xb9\x48\x9f\x26\x49\x3a\xc3\x24\xd3\x72\x65\x54\x22\x0c\xe6\x62\x7b\x69\xe2\x0d\xa3\xb3\xd7\xd8\x04\x9e\x36\x55\xe3\x6c\x39\x62\xe0\x85\xe1\x3b\xd0\x5a\xf4\xb2\x97\x38\x22\xca\x1d\xde\xe4\x7c\x3e\xfe\xfc\x82\xc0\x80\x0e\xec\x7b\x57\x17\x9d\x5a\x6f\xa4\x8f\xd0\xf4\xbc\x79\xdb\x47\xde\x37\xc6\x45\xfc\xc0\x90\x92\x6e\x97\x16\xfc\xba\x20\x19\x1d\x82\x7f\x62\x51\x02\xaf\xca\x58\xb7\x89\xa2\x8c\x79\x0d\xc9\xa2\xf0\x40\xc8\x74\x25\xb2\x62\xd6\x95\x87\x5d\xc8\x8e\x8f\x74\x49\x0d\xaf\x9f\xa0\xd8\x89\xc2\x24\xf7\x94\x4a\x08\x8c\xf8\x67\x96\xb6\x1d\x20\x5c\x7b\xf7\x1c\x31\xc7\x19\x3a\x9a\x2d\x18\x48\xa2\x69\x1c\x3f\xd4\x95\x22\x19\x10\x4b\xe3\xf7\x20\x1f\x08\x55\x7b\xf4\xdc\x3c\x6c\xf0\x79\xe2\xa0\xbd\xa6\xf2\x06\xbc\x76\x34\x80\x1a\xf6\xf1\x41\x3a\xb2\xe1\x47\x49\x18\xfd\xa5\xbb\x15\x04\x2e\x6a\xd0\xa5\x19\x3c\x68\x52\x26\x55\xab\x02\x0d\xee\x08\x35\xc0\x74\x8a\xe8\x6a\x86\xfd\xd7\x9b\x8d\x23\x40\x47\xf4\x6e\x8a\x33\xcf\xf7\x76\x2c\x3d\x06\xbf\x2c\x2e\x21\x8e\xc8\x75\xa7\x79\x3c\xbf\xd7\x01\x21\x89\xcb\x4c\xff\xb2\x48\x1a\xff\xe5\xb2\x47\xbd\xeb\x6d\x35\xd7\x97\x43\x21\x24\xff\x42\xc6\xd2\xc1\xdb\xf5\x41\xff\xa6\x3f\x70\xed\x84\xb3\x7d\x9a\x6e\xc5\x7e\x9b\x9b\xf8\x58\x82\x73\x66\x0f\x36\x7c\x7b\xca\xcf\xf5\xfc\xa4\x33\x1f\x9c\xb5\xdf\x1a\x9d\xf1\xf3\xb8\xb9\x93\xf3\xe5\x35\xdb\xc2\x3c\x10\x9e\xe3\x5f\xc2\x93\xcf\xfb\x13\x25\xb3\x40\x01\xad\x71\xe8\xa6\x2c\x18\xef\x53\xa1\x35\x12\x10\xce\x94\x66\x73\xcf\xb6\x1e\x07\x7d\xa3\xef\xaa\xd3\x7e\x2b\x0f\x02\x66\xb6\x70\x21\x35\xad\xb3\xc4\x35\x6c\x95\x29\x93\x78\xf4\x31\x4e\xca\x47\x64\x2e\x0c\x96\x3f\xc6\x52\xb3\xad\x4d\x63\x16\x5a\x11\x55\x45\xa0\x3b\xff\xea\x0b\xfa\x17\x77\x63\x7d\x40\xf2\x19\xa1\x86\xeb\xaf\x1f\x11\xde\x37\x84\xf0\x0d\x0e\xd2\xa8\xea\xf2\xad\x2a\xb9\xcb\x04\x7c\x79\x49\xfe\x52\xe4\x7d\x53\x5b\x2b\x1d\x5d\x7b\x1c\x39\x48\xf1\x30\xef\x63\xb2\xaf\x71\x0c\x78\x06\xef\x4a\x87\x0f\x30\x37\x3b\xcf\x40\x7f\xf9\xc6\xe9\xe4\x4c\xad\x64\x45\x43\x43\x04\x22\xba\xba\x1b\xd2\x2a\xa6\x69\x97\xe5\x51\xe9\xef\x50\xa0\x7e\x69\x9e\xc1\xa1\x94\x50\x4e\xdd\x91\x5c\x89\x59\x72\x65\x9f\x1e\x8e\xdc\x52\xc9\x3b\xde\xe8\x6b\x30\x61\x3f\x35\xbb\xbd\x09\x5f\xf2\x1f\xc5\x9c\x34\x99\xf6\xd6\xe0\x50\xb1\x35\x09\x1e\x6f\xe3\xcb\xcb\x87\xd3\xc5\x9b\x79\x46\x54\x3a\x8a\xab\xb5\xfe\xea\xef\x6a\x8f\xcb\x5f\x1b\x04\xa4\x03\x8e\xf8\xaa\xa1\xa1\x07\x97\x24\x88\xeb\x31\xe3\xeb\xb2\xe8\x68\x0e\xe3\x6f\x26\xd6\x22\xce\xfe\xfd\xab\x1f\x37\xed\xa6\x73\x6b\x51\x47\x1d\xc5\xa1\x91\x73\x94\xcb\x1e\x67\x7d\x69\x90\x37\x89\x1a\xd3\x06\x4e\xb1\x8f\xa3\x14\x78\x77\x22\x9b\x9d\xc3\x72\x2f\xda\x72\x69\x10\x91\x72\x52\x7e\x29\xb9\x12\x9f\x13\x0a\xf3\xb8\x88\xf3\x37\xa1\x12\xa1\xb0\xbc\xdc\x66\x51\x49\xac\xda\x99\x3f\x60\x51\x1d\x83\x7e\x09\x47\x24\xf7\x6e\x98\x9c\xc6\x37\x49\x93\x1b\x70\xcb\x90\x18\x9c\x24\x38\xe6\xbc\x01\x40\x77\xc8\x3a\x34\xe2\x86\x55\x7e\x62\xe4\x59\x86\x6d\x80\x42\x5b\x24\x76\x8e\x90\xda\xea\xc4\x0e\x96\x83\xb1\xca\xe1\x55\x39\xfb\x89\xfc\x46\xaf\xf4\xc7\xfd\x9b\x36\xfb\x77\xb0\x0e\x07\xc3\x97\xc9\x46\x5e\x2a\x82\x0e\x06\x8e\xda\xaa\x36\xf0\x80\xe8\x91\x62\x99\x33\x8a\x33\xf1\x33\xcb\x45\xc6\x58\x71\xf6\x19\x71\x86\xe1\xd8\xd9\x51\x57\x87\xf4\x36\xae\xcd\x74\x0f\x24\xd8\x56\xb7\x12\xc2\xf4\xef\x1f\x62\x44\x5e\x28\x18\xbd\x2e\xaf\xb7\xf8\x79\x9f\x6f\x9b\xa7\x25\xf9\x8c\x36\x44\x0b\x9b\xbc\x44\xd3\xca\x2a\x97\x0e\xff\x62\xc8\x23\x78\x2b\xf3\xd1\xf0\x15\x8b\x38\xc2\x0d\x24\x49\xa6\x50\x3a\xc5\x7d\x20\x16\x5e\x91\x9f\xb5\xfb\x92\x6e\x2c\xfb\x0a\x28\x17\x2e\xd4\x91\xdd\x45\x9a\x4a\x22\x9a\x1e\x35\xa3\x1a\x12\x67\x02\xb5\x7d\xd1\x1c\xd3\xd0\x46\x70\x8a\x58\x85\xd3\xd6\x6f\x87\x60\x4c\xd9\xbb\xb5\x8b\xb4\xd1\xc8\x9c\x07\xf0\x18\x80\xc8\x25\xaa\x12\x21\x8c\x61\x57\xf2\xe6\x96\x19\x52\x21\xaf\x9d\x6b\x3f\xd8\x9e\x9a\x15\x7a\x09\x0d\x88\xd0\x7a\x9e\x58\xa7\x56\xf5\x50\xf3\xc1\xec\x79\x9a\x93\x6a\x5f\xba\x67\x89\x9a\x23\x3f\x18\xca\x16\x89\x7c\xda\x17\x38\xb8\xed\x94\x1e\x22\x94\x30\x4a\x71\xac\xfd\xff\xb6\x06\x6b\x58\x57\x8b\xa5\x15\xf6\x16\xaa\x79\x57\xcc\x63\x72\x82\x19\x1d\x10\xd8\x5e\xff\xc6\x5f\xd5\xb3\x70\xe5\x0e\x93\xea\xa1\x54\x41\xf7\xc0\xc3\x20\xa8\x55\xb2\x8e\xa5\xa9\x6e\x16\x3a\xb6\xc2\x31\x80\xdf\xeb\x51\xa8\xc0\x63\x9f\xb5\x75\xd2\x8c\xd3\x10\x40\x95\xd6\xa0\x0f\x2a\xd2\x51\xa2\xed\x11\x79\x48\x65\xed\x66\x77\x8a\xa7\xc8\x5f\x75\x84\x54\x68\x20\x8c\x85\x19\x1b\xf9\x11\x09\xa8\xc8\xdf\x72\xbe\xc4\x3f\x4b\x70\x8c\xcd\x17\xdb\x42\xe4\x70\x0e\xa5\x25\x68\x2a\x26\x26\x68\x74\xd7\xb0\x8a\xd5\x2e\xdd\x4f\x09\xbf\xbb\x5b\xf8\x5b\x29\xa2\x81\xbe\x14\xfd\xfc\xf7\x8d\xa6\x77\xc6\xa4\x1a\x12\x01\x42\x76\x67\xb0\xcb\xaa\x85\x81\xab\xb9\x6e\x62\xba\x29\x91\xa3\x22\x26\xcf\x30\xdf\xa0\xdd\xec\x2e\xcb\xcc\xbb\x64\xb9\x60\x39\x43\x5f\x84\x6c\x21\x89\x7a\xf4\xab\x84\xae\x68\xd3\xba\x35\x8e\x95\x33\x61\xbb\x5f\x9e\xe7\xc1\x70\xf7\xd9\xba\x95\x28\x34\x60\x5d\xeb\x89\x58\x68\xf2\xe4\x30\x66\x95\xae\x90\x1e\xaf\x7a\xa1\x06\xe3\x9e\x78\x9d\xce\xff\xd1\xc9\xf8\xfb\x29\x82\x8f\xe5\x02\xbe\x12\x25\x21\x8c\x0b\xb5\xbb\xb2\x29\x9a\xaf\x02\xd2\x8f\xc0\x37\xa8\x73\xe2\xe7\xfb\x6e\xee\xbf\x86\x97\xed\x80\xf4\xd1\xc4\x17\xde\x9f\x74\x36\x06\xf4\x33\x42\x18\x4d\x20\x33\x68\x86\xbe\x30\xfe\xa1\xc0\x41\x62\xec\x48\xb6\x45\x53\x9b\xf2\x38\x62\x38\x3c\x77\x38\x0d\x0a\xfd\xf7\xbf\x5c\xdf\xbb\x60\xdb\xfe\xd4\xa1\x3f\xea\xe6\xda\x93\xd3\x2e\xc9\xa9\x7e\x22\xd1\xa4\x2e\x7d\xca\x96\xc6\xc1\x16\xe3\x6b\x31\x47\x17\xd9\x71\x49\x49\x4d\x67\xcb\x64\xff\xc9\xbf\x65\x63\x0e\x6b\xc1\x11\x27\xb5\xf4\x0e\x0d\x44\x49\xa0\x9b\x51\xe7\x57\x9f\xe1\x97\x67\x07\xb6\x94\x9d\xe1\x16\xf8\x94\x49\x6a\xdc\x5f\x90\x9e\xf2\x4b\x4e\x0a\xda\x7d\x18\xb0\x6e\x89\x18\x06\x3a\xa4\x9a\x7b\xc8\x6f\xad\xa2\x65\x0d\x49\x6b\x57\x99\xd9\x6e\xa5\x59\xe6\x6d\xdc\xa7\x3c\xb2\x03\xf2\x79\x9a\x70\x89\x86\x1b\xed\x8e\x2d\x9c\x72\xed\xf4\x44\x11\xec\xbe\xf2\x2b\x78\x7b\x04\xde\xbf\xed\x77\x06\x9f\x16\xbf\x65\x76\xa6\xd0\xd3\xbe\x9f\xba\x0c\x03\x3f\x03\xcb\x4f\x3e\x2f\xea\xc8\x1f\x9a\xf4\xde\xfb\xba\x8a\x3b\x8f\x04\xeb\x39\xdf\xde\x3d\x6d\xf8\x7d\x46\xa3\x17\xbe\x9d\xe3\x10\xfd\x71\xe4\xbc\x4a\x61\x7d\xab\x1d\xcb\x24\x94\xd1\x2b\x18\x6c\x18\x5a\x53\x74\xe4\xf5\xa5\xed\x4b\x1d\x8a\x3c\x94\x7d\xcd\x13\xb0\x0b\xd6\x34\x8d\x30\x4a\xcc\xed\x3a\xfd\x4c\x67\xff\xca\xc8\xb4\x98\x5c\xca\x65\xb8\x4a\xcf\x1c\x5d\x06\xa9\xf4\xde\xed\x32\x51\x97\x43\x42\x97\x23\xcf\x7e\xd3\xbf\xbc\xec\x8e\x23\xc2\x6d\xf0\xaa\x57\x5d\xca\xd3\x74\x57\x89\x96\xd2\x10\x31\xa8\xb5\x4c\xeb\x77\x5c\xf0\x85\xe3\x9e\x85\xcf\x21\x5e\xf8\xd4\x16\xe3\xe8\xff\x4b\xc7\x74\x2f\x4f\x14\xd2\x38\x9a\xd9\x4d\x57\xdd\x4d\x65\x0f\xa9\x04\xff\xf3\xc9\x2a\x43\xf5\x26\xe9\x82\x6b\x06\x7f\x44\xfd\x19\x4f\x97\x90\x17\x7a\x1e\x5c\x65\xac\x89\xe9\xf9\x65\xbd\xda\xa0\x0f\x3f\x47\x26\x41\xe8\xfa\x44\x48\x6f\xbc\x96\x68\x92\x2a\xc3\x23\x76\x9d\xed\xb2\xc0\x2c\x1d\x0d\x7c\x4d\xab\xa6\x62\x90\x81\xd5\x4f\x09\xa1\xd7\x7d\xf7\x7b\x82\xaa\x44\x0b\xc9\xe0\x49\xb1\x29\xe6\x20\xf3\x7e\x97\x38\xf7\xb0\x41\x76\x67\x7c\xfa\xf9\x64\x7a\xae\x7d\x39\x88\x7d\xe3\xf5\xd4\xe8\x37\xa2\xd4\xcb\x18\xf1\x55\x21\xbc\xb9\x5b\xa8\xf7\x1b\x29\x3a\x92\x61\x50\x5f\x23\x94\x80\x28\x4f\x2a\x0d\x73\x01\x72\x84\xb4\xeb\x4c\x91\xc3\xf9\xef\x5b\x9a\x4b\x5f\xed\xc7\xe0\x59\xaf\x73\x9d\xa4\x47\xbc\x96\x20\xb9\x2c\x62\x25\x76\xcb\xba\x33\xeb\x74\x46\x0e\x65\x72\x73\x28\x41\xf1\x51\x47\xf1\x5e\xa7\x9f\x19\x8f\x99\x03\xa1\x34\x65\x37\x16\x03\x11\x6e\x2e\x31\xea\xca\xb9\x48\xab\x8e\xcf\x1f\x48\x13\xa1\x33\x04\xca\x7f\xba\xcc\x7d\x87\x9d\x79\x31\xd7\x01\x87\x86\x65\x13\x8a\x10\x92\x09\x02\x0d\xe7\x50\x1f\x61\x2b\x45\x1d\xcb\x56\xad\x78\xf9\x06\x4f\x03\xca\xb7\x10\x7e\x33\x18\x57\x9e\x6c\xfa\x29\x49\x57\xe8\xc8\x46\x73\x43\xfa\xc5\x90\xb9\x9e\x46\xc7\x45\xe9\xe3\x9f\x38\xae\x93\x90\xf1\x06\x6e\x8e\xe3\xfd\x72\x7f\xbf\x7f\xce\x45\xb9\x13\x52\x6b\x88\x1c\xda\x45\xe0\x29\xd4\x26\xba\xf7\x78\x91\xcf\xa2\x69\xcc\xc2\x4f\xe3\x70\x80\x57\xf7\x1d\x7c\xaf\xfb\x7b\x83\xdd\x39\x87\x99\x0e\xf3\x91\x1b\x9c\x48\x6e\x13\x6b\x60\xcb\x43\x2d\x52\x93\xcf\xbd\x64\xaa\x67\x98\x1b\x7a\xaf\xeb\x12\x0d\x44\x8f\x86\x75\x93\x3f\x1b\x79\xc9\x52\xcb\x3c\x1b\xaa\x3a\x08\xe5\x73\xf8\xdc\x8b\x9d\xe5\x64\x9c\x32\x87\x14\xcf\xd3\x7f\x5e\xf1\x43\x49\xe8\x1b\x91\x28\x5d\xfa\x7e\x45\x3d\xde\x27\x70\xe6\x08\x30\x11\x06\xe5\x5f\x1d\x92\xca\x43\x40\x41\xfa\x8c\xda\x97\xaf\x51\x83\x56\x04\xa1\x1e\x67\x5e\x82\xd6\xdf\xb3\x9b\xcb\x39\x05\x7b\xbd\x1f\x96\x00\x80\x22\x6b\xb8\x91\x2d\x2d\x6f\x75\xf5\xe1\xaa\x74\x0d\x3b\xee\x2a\x75\x76\x24\xe5\x3b\x6f\x3a\xb6\xdf\x65\x8c\x21\x8f\xec\xc4\x7a\xfe\x53\x82\x8e\x50\xc9\x94\x74\xbe\x9e\x27\x29\xd4\xac\x7b\xfa\x3c\x77\x01\x42\xfe\x0c\xf6\x19\x42\xb6\x29\xa5\x94\xf5\x06\xd2\x09\xe0\x77\x54\xc4\x30\x14\x2f\xd5\xa0\xd1\x84\x0f\xe7\xc3\xe4\xc5\x8b\x62\xeb\x52\x0a\x45\xdc\xa5\xdf\xec\x72\x2b\x37\xc2\x1b\x85\xd9\xe0\xef\x1f\x3e\xa5\x36\xa3\xce\x67\x9f\x24\x01\x27\x27\x0f\xcb\x6f\xed\x91\xce\x70\xea\x4d\x42\xa5\x32\x57\x40\xad\xe7\x47\x84\xb8\x2f\x4b\xdd\xb2\x5d\xc3\x62\x15\xf1\x24\x19\xa8\x35\x17\x93\xc3\x93\xa5\x35\x97\x8f\xd5\xfe\x13\xbf\xe4\x29\x8f\xd1\x1f\x59\xc8\x3f\xb3\xde\x49\x52\xcc\xd9\xe4\x72\xc4\xf7\x44\x77\xe3\x12\x8f\x2d\x10\x04\xb7\x77\x0c\x0d\xc0\x5d\xb8\xc1\xb6\xe8\x55\x42\x8f\x39\x03\x06\x7a\xa9\x26\x5d\x2c\x1c\x8c\xa3\xae\x1f\x6e\x84\x54\xf1\xd8\x56\x55\x51\x8d\x62\x85\xd8\x7c\xa6\x2e\x9a\xb8\x31\xea\xe0\x57\xce\xaa\xd1\xe5\xcd\x51\x0b\x8d\x7e\x7b\x91\xdf\x2c\x01\xc1\x37\x3e\x7b\xe1\xc1\x1b\x74\x3d\x5c\x90\x94\xcb\x1e\x80\x70\x25\x4e\x5d\x3d\x79\x51\x4b\x77\x70\xc2\x9a\xf9\x86\x1e\x1f\xd7\xeb\x6b\x0c\x98\x72\xe5\x49\xcc\x42\x48\xa4\xf9\x44\x61\xa2\x66\x8c\x68\xbc\xd4\xd3\x85\x05\x5a\x7f\x47\x04\xbd\x4a\xaf\x7d\x79\xd5\xaa\x12\x04\x35\x2a\x3d\x0a\x8c\x31\xc3\x3d\x56\x0a\xb8\x7a\x6a\xbe\xab\xfb\xdf\xed\x37\x5c\x9c\x25\x80\x7b\x65\x6e\xfd\x6f\x93\x17\x02\xdf\x6d\x86\xdb\xc2\xad\x1f\x38\x82\xa7\xc1\x30\x47\xa7\x05\x4a\xec\xbf\x03\x14\x7c\xef\xa8\xa0\x91\xf5\x78\x1c\x0d\xf5\x7c\x52\x0b\xbb\x60\xfe\xd5\xf4\x9a\xf2\x15\x52\x20\x84\xf9\xa3\xea\x12\x43\xdd\x5d\xca\x9c\xb1\xb7\xbd\xa3\xf1\xf1\x65\xc0\x27\x6f\x18\x06\x1f\xa6\x1f\xac\x79\xab\x70\x90\x77\x11\xaf\x63\xdb\xa6\xd8\x94\x04\x48\xf4\x86\xd7\xca\xb9\x01\x5b\x2f\xc0\xa6\x26\xcb\x9c\xd7\x15\x66\x37\xd7\xc4\x5c\x86\xc3\x7c\xeb\xff\x9c\x90\x9c\x9d\x40\xb6\xc2\x3c\x79\x91\x8a\xb7\x81\xbd\xf2\x00\xc0\x2b\x99\x76\x6f\x47\x5c\x48\x76\xcf\xc4\xb0\x17\xb8\x42\x9e\xa6\x17\x0b\x1b\x12\xac\x34\x8d\xb5\xd1\x75\xf3\x9d\x80\x3f\xfa\xe2\x9d\x19\x16\x9c\x42\x95\x5d\x6e\x25\x3c\x78\xe0\x5e\x79\x28\x49\xd1\xf8\x71\x95\xfb\x66\xa3\x57\x95\xb4\xc6\x0b\xc0\x29\xcd\xc9\x78\xca\xd6\x8b\xfc\x99\x9e\x7f\x56\xaf\x62\x5b\x2d\x77\x95\x08\x67\x15\x35\xdc\xc3\x41\x39\xaa\xdf\xfa\x7e\xe2\xf5\x73\x94\x2c\x4c\x0c\xf2\xe4\x8c\xd0\x8a\x41\x74\xec\xb6\xb3\x62\x46\xb3\xd0\xdb\x67\xa2\x60\x78\x07\x2f\x2d\xd0\xcd\xf4\x4b\xe9\xf6\x0a\xd4\x19\x2d\x2a\x15\x2a\x15\x07\x83\x23\xcd\xbb\x29\x43\x95\xeb\x70\xd5\x59\x34\x2e\xcd\xc0\xa0\xe5\x25\xc1\xf2\x58\xc6\x09\xe3\x23\xc3\x2b\xd7\x6a\x54\xd3\x50\x2f\x89\x4c\x84\x16\x6c\x51\xbe\x9d\x82\xee\xcb\x09\x98\xc1\x52\x0d\x1c\xa9\x69\x62\x11\xb0\x0b\x16\x6d\x5b\x34\x8e\xbc\xe9\x74\x72\x43\x18\xb5\x26\x7e\x94\x6b\x4c\x75\x88\x27\x14\x44\xca\x08\x62\xd8\x87\x87\x28\xd0\xa6\xf4\x3c\x86\x59\x0e\xd9\x48\xda\x2d\x7c\xbc\xdd\xee\x2d\x44\xfa\x21\xf8\x37\x8e\x4f\x60\xdb\x8a\x1a\xd6\x5c\xb9\x52\x1a\xb1\x61\x65\xc4\xda\x01\xe8\xc3\x45\x48\x0f\x34\xd1\x78\x3f\x74\xec\xa5\x2e\x96\xde\xd8\xb3\x1a\xc6\xfa\xf1\xca\x69\x31\xa0\x9d\x65\xca\x7e\x1f\xd9\x65\x73\x0f\x5e\x22\x09\xc1\x5b\x2a\x6b\x3f\x16\x71\x2b\xb2\x64\xea\xf3\x34\xdb\x68\x6d\x16\xa8\x43\x28\xa9\x98\xc4\x57\xa8\x79\x13\xde\x39\xeb\xaa\xf9\x15\xd1\x31\x77\x53\x94\x5a\xb2\x60\xc6\x68\xea\x2c\x8b\xe4\x11\x06\x75\xa0\xef\x1c\x99\x58\x9d\x3e\x5e\x4c\xb9\x17\x19\x4b\xd3\x9d\xfb\x9a\x64\x08\xd7\x32\x6f\x54\x89\x15\x2b\x5d\x44\xe4\xa0\x35\xf8\xa4\xc1\xf8\x91\x6b\x09\xb4\xbb\xed\x1e\xd7\x89\xc4\x1f\x1e\xfe\x7d\x3b\x1f\x83\xf6\xfc\x97\x77\xaa\x10\x1e\xdd\x6b\xb3\x65\x5c\x70\xa9\xe0\x50\x95\xc1\x11\x40\x87\x38\xd8\x25\xbb\x59\x10\xda\xe7\xae\x15\x8b\x62\x85\xf1\xc7\xdf\x9b\x5f\x6a\x3e\x24\xdf\x8a\xfc\x04\xab\xf0\x1c\x27\x65\x4c\x38\x56\xed\x70\xce\x72\xea\xce\x13\x5b\xce\xf8\x32\xbd\x2a\x67\x26\xa1\x9c\xd9\x18\xf0\xe1\xb5\x83\xec\xf2\x40\x84\x08\x9d\x2d\x13\xfb\xfa\xe0\xf6\xc1\x97\xde\x47\xc9\xae\xfc\x36\x3e\x42\x6d\x14\xdf\x5f\xc3\x81\xc5\xc8\x26\x9f\x3d\x4d\xb1\x4e\x98\x9f\x82\x61\xe9\x98\xd8\xe6\x68\x43\x07\x01\xa7\x83\x68\x2a\x9f\x3d\xa0\x03\xda\x7e\xca\x77\x82\x8e\xc8\x3d\x79\x92\xb3\x9a\xfd\x5a\xad\xb4\x94\x34\xd3\x04\x4b\x2b\x33\x9e\xbc\xcd\x2e\x39\x2d\x39\xe5\x64\x1f\x0d\x26\x7b\x5f\xad\xd0\x90\xb0\x87\x5f\xc3\xec\xc3\x4e\xe1\xb1\xd1\x46\xb2\x3a\xd9\x6c\x29\xb5\xee\xc0\xbd\x04\x35\x71\x54\xcd\x64\x57\x3b\xb3\x99\x97\xcb\xef\x34\x38\xa4\x32\xb7\x13\x8b\xb8\xe9\xc5\xaa\x31\xab\x47\x7b\x5d\x37\x76\xa6\xf2\x92\x23\x03\x71\xfa\x99\xaf\xcb\x72\x83\x46\x51\xa5\x30\xea\x6c\xad\xa6\x4d\x92\x47\xc2\x16\x90\xe7\x13\x90\xc3\x3f\xa5\xc2\xd0\xd1\x7e\xc4\x74\xc1\x5f\x3c\xbc\x47\x07\x31\xe7\xa1\xa8\xee\xa3\xe8\x32\x6c\xb9\xa6\x14\x23\x9c\xc9\x6e\x56\x6f\x43\x81\x99\x61\xf2\x94\xa2\x49\xdf\xa0\x2c\x83\x0d\x54\x60\xca\xa4\x15\xe2\xc6\x1f\x63\xd0\x21\xce\x06\x34\x04\xf0\x73\xf5\x38\xe5\x2f\xd5\x6c\x74\x57\x98\x99\xa1\x7a\x05\x95\x22\x52\xd6\x53\x98\xb4\xfc\xce\x50\x70\x05\x04\xc3\xe1\x05\xe9\x48\xdc\xb8\x8a\xf3\x57\xa7\xdd\x5f\x6b\x6d\xbf\x7b\x7d\xd3\x73\x83\xf6\x51\x25\xd4\x70\xbc\xa0\x10\xff\x15\x86\x70\x34\x1c\xd4\xb8\x0f\x54\xcd\xbb\xca\xac\x38\x54\x1c\xac\x10\x40\xe3\x00\x96\x6b\xae\x11\xbc\x14\x69\xc0\x6e\x3e\xaf\xdb\x50\x7f\x57\x24\x1a\x40\x3f\x75\x49\x54\x0f\x5a\xcc\x37\xb0\xc9\x48\x5d\xd6\x6d\xb5\x8f\x1e\x3f\x5d\xf8\x7b\x4a\x43\x5d\x0b\xd1\xdb\xe3\xb5\xac\x0d\xaa\x94\x9e\x16\x16\xa5\x7e\x52\x65\x2d\xd0\xa5\x10\xb6\x1e\xcc\xfc\x66\xc6\xa0\x34\x98\x12\x83\x43\xa6\x65\xae\x59\x62\x04\x2c\x40\x02\x66\xa0\x8a\xaa\x26\xd7\x16\xd6\x1f\xa0\x88\x87\x64\x0c\x51\xe2\xac\x1b\x0c\x24\xc8\x00\x0b\xef\x91\x8d\xc1\xec\x44\x7c\xf3\xf2\xeb\x8b\x71\xa7\x43\x39\x7b\xb2\x0b\x7d\x89\xf9\xc3\x4c\x90\x45\xec\x32\xe3\x42\x18\xc7\xa1\xab\x04\xa6\x61\x91\x4d\x60\xa1\x1d\x64\x16\x88\xe3\x36\xc5\x9a\x0c\x3a\xc7\xcc\xd7\xf6\x60\x84\x8b\x2d\xef\xf6\x06\x59\xb8\xd8\x66\x6b\xd8\xaf\xd1\x3b\x97\x5f\x88\x8e\x32\xc4\x97\x5b\xd4\x9f\xf6\x85\xba\x86\xae\x7b\x2f\x6d\xe2\x70\xf7\xf0\x29\x08\xfe\xc7\x8c\xc8\x75\x8e\x16\x8f\x98\x7d\xb4\x7d\x01\x1f\xab\x46\x4a\x8f\x5b\xb8\xfa\xaf\xce\xd4\xdd\x57\x52\x47\x5d\x57\xf8\xc3\xfb\xd9\x6b\x7d\x5e\x65\xe2\x96\x8e\x5f\x9f\x17\xa5\x7d\xfb\xb9\xc1\x24\x12\x53\xd6\xe0\x51\x25\x71\x5f\x24\x78\x7c\x45\xc3\x58\xa3\xfa\x6c\x66\xb4\xf0\x78\xff\xd0\x04\xc2\x95\x02\x99\x20\x56\x4c\x7f\x6d\xe5\x1c\xfb\xe4\x7b\x32\xde\x86\xfe\xd3\xef\xe7\xff\x74\x15\xa2\xdd\x6e\x4e\xe7\x63\xfb\xfb\xdc\x4b\xdf\x0b\x51\x9d\xfb\x2b\x5f\x2a\xd5\x73\x9b\x0d\x32\xcd\x62\x4c\x5c\xdc\xfa\x06\x1c\xc5\xcb\xf6\x30\xe4\xba\xaa\xf3\x0f\x29\x56\x7c\x61\x30\x2d\x8e\x5a\x25\x3d\xa2\x3d\x7b\x30\xa6\xa1\x86\xf3\xdf\x08\x4a\xdd\x3c\x61\xea\x75\x8b\xa3\x99\x9f\x59\x99\xd7\x10\x4b\x11\x15\xec\xab\xf3\x74\x0d\xe0\xbf\xdb\x5b\x09\xd3\x05\x3a\xe9\x0c\xed\x35\x17\x8c\xe0\xe6\x43\x40\x63\x50\xb9\x1e\xdd\x65\xdc\x6e\x57\x33\xd9\xf0\xf0\x85\xe2\x8e\x73\xae\x5c\x6c\x34\x8a\x71\x43\xbe\xef\x71\xf5\x04\x3d\x76\x69\x4b\xe5\x8e\x95\xb0\x71\x5d\x72\x36\x12\x7b\x8c\x5e\x06\xc3\xbd\xe3\x5f\x71\x4d\x45\x06\x89\x85\x94\x68\x09\xaa\x95\x4a\x5c\x30\x71\x11\x98\x02\x20\x8c\x79\x61\xca\xa0\xce\x69\x1e\x9e\x99\x8d\x60\x68\x12\x8d\x64\x4e\x51\xd6\x3b\x52\x31\x0e\x33\x30\x7c\xa8\x51\xe0\x0f\x98\x5a\x52\xad\x71\x14\x3f\x6f\x1e\xf1\xf0\x46\x43\x0a\xce\xe2\xe2\x05\x18\x4b\x5b\xfd\x61\x4a\x35\xfb\x6c\xd3\x45\xe0\xa7\x86\x62\xea\x2f\x25\x43\x8c\x69\x56\xdb\x15\x9a\x06\xb2\xd7\x0f\xc3\x12\xc6\x12\x47\x81\x40\x3f\x22\xf8\xc7\x2a\x94\xe4\x8c\x6f\x28\x1c\x98\xae\xc1\x94\xa9\x99\xdb\x29\xe6\xad\x40\x97\x0f\xaa\xad\xf1\x09\x70\x2d\x81\xa3\x84\xc5\xf2\x45\xc6\xd2\x17\x8a\x33\xa9\xee\xee\x58\x42\xef\xa5\xe6\x72\x81\xf7\xf7\xb3\x35\x9d\x87\x6a\x1b\xb6\xc5\xee\x6f\x35\x21\xab\x3d\xd0\xd8\xb3\x43\x8c\xfb\x73\x6d\x79\x1b\x63\xc0\xc9\x80\x1c\xc8\xfb\x4e\x34\xd5\x38\x7d\xc3\x58\xbd\x91\xad\x58\xd3\x3a\x74\x30\x44\x28\x20\x0f\xcb\x2c\xb0\xf3\xec\x0c\xd7\xfb\xcf\x8c\x64\xf0\x53\xde\xc4\xc8\x84\xce\x95\xb3\x75\x35\xf9\x4e\x29\xb7\x53\x82\xe8\x94\xd0\xdc\xdd\xe9\x2d\xe5\xbc\xab\xcb\xc0\x15\x9f\x80\x2c\xf3\xc9\x42\xbf\xec\x0b\x01\x2f\x98\xcc\xd7\xf3\xd8\xcb\x89\x58\xcd\xe1\x4d\x27\x5d\x40\xb2\xdb\xca\xde\x40\x09\x25\x56\x2a\xdf\x53\x9b\x65\xe0\xe7\x9b\xa2\x87\x5c\xc4\xf5\x06\xaf\x41\xfa\x93\xf4\x04\x8e\xe8\x33\xf8\x1d\x9e\x0c\xff\xc2\x99\x81\x84\xbd\x88\xbf\x19\xf1\x93\x68\x34\x1a\x5d\x00\xf1\xb3\xd2\x1f\x2f\xc9\xcb\x4e\x96\x3b\xc1\x38\xe4\x93\xf0\x79\x2d\x0d\xb1\x80\xe3\x75\x28\x2b\x32\x83\x2f\xc1\x58\x62\x7d\x87\xdf\xec\x05\xfd\xc7\x7b\xa8\x2c\x82\x55\xbf\xb9\x3c\x31\xde\xe5\x4a\x59\xa1\x30\xa3\x98\xdf\xae\x75\xa5\x7e\x56\x10\x85\x0e\x02\xc4\xfb\x03\x5f\xec\xbe\x39\x71\x3f\x70\xb0\x04\x2f\x6b\x7e\x94\x17\xd0\xe6\x07\x4a\xfe\xbe\x40\x19\x9b\xff\xe0\x80\xf6\xcf\xd6\x65\xaa\xa7\xde\xda\x1f\x6b\x60\xc3\x84\x5b\x12\x2e\xc6\xb4\xdd\x0b\x33\x09\x5a\xcf\x5d\x3e\xb0\x1d\x19\x8d\xfe\x5b\xea\xae\x15\x76\xad\xfe\xf4\x0b\x44\xad\xd1\x06\xd9\x30\x72\x5e\xc0\x39\x1a\x1a\x37\x23\x56\x3d\x80\x67\x1e\x94\x4a\xe0\xd6\x08\xaf\x5b\xde\xd9\xb8\x91\x89\xfa\x2e\x80\xf5\x24\xd4\x76\xbd\x02\x71\xcf\xc5\x36\x03\xd9\x4a\x12\x45\x1f\xc8\xfd\x52\x58\x5e\xab\x53\xcb\xe0\xe0\xcf\x53\x1b\x87\xbc\x34\x9b\xfa\xe5\xb3\x0d\xf6\x70\xff\x2b\xe2\xb8\xd0\xcc\xaa\x93\x34\x29\x1f\x06\x71\xbc\xb4\x7f\x76\x05\x29\xc6\x76\x49\x51\xf7\x90\xa7\x76\xf5\xed\x91\x34\x5d\x5f\x1b\xf8\x83\xfa\x07\xc2\x2b\x5c\xb1\x1b\x08\xa7\x1b\x02\xdb\x4c\x31\xba\xd3\x25\xe8\x0b\xed\x18\xec\xb3\xc0\x85\xc0\x63\xec\x54\x89\x65\x91\x16\x72\x89\xe5\x98\x46\x6d\x73\x70\xf0\x43\x7c\x33\x0c\x53\xdd\x66\xff\x4b\x49\x04\x13\x72\xd4\x53\x76\x7c\x36\x03\x8e\x3f\x64\x68\xf9\x01\x69\x15\xca\xaf\x7c\xbc\x04\x85\x2f\xbc\x8c\xb5\xe0\xde\xe1\xac\xb6\x80\x06\x75\xb3\x1f\x25\xd5\x42\xde\x0a\xfb\xd8\x75\x41\x4b\x40\xb3\xdd\x52\x91\xf0\x27\x06\x76\x53\x47\x49\x85\x02\x15\x36\x79\xaf\x3b\x67\x45\x8f\x9b\xf0\x62\x63\xb7\xf0\xdd\x40\xc8\xfa\xd0\x01\xd8\x00\x94\xf3\x6b\xa3\x55\xfd\x4c\xec\x74\x64\x76\x83\x18\x14\x53\x72\x0c\x15\x26\xd2\x1c\x0d\x78\x32\x5a\x14\x25\x5b\x24\x13\x1f\xbc\x88\x96\x84\xc4\xa1\x46\x90\x7f\x9e\xe3\x9e\xb3\xdf\xca\xf1\xcd\x5e\x77\x90\xa4\x65\xbf\x41\x2b\x7e\x06\x31\xf4\x70\x49\xa8\xed\x5a\xe5\xb2\x64\x49\x7b\x7c\x4e\x73\xb0\x82\x0b\x92\x4c\x3c\x41\x88\xe7\xe0\x59\x75\xa0\xab\x11\xd2\x5c\x42\xd7\xeb\x93\xfa\x91\x5c\x67\x2e\xcf\xdc\xb2\xcc\x4b\x4d\x92\x41\xe7\x0d\xec\xd9\xb1\x69\x9b\xad\xd0\xe9\x31\x89\xff\x5e\x72\xc1\x41\x86\x7c\x0e\x79\xbd\xe0\xc9\xed\xb7\x5b\x85\x01\x59\x95\x76\x34\xa8\x40\x15\xa2\x1f\x45\x41\xd7\x7b\xa4\x27\x05\x8c\x96\x18\xa9\x88\xf8\x41\xdf\xc9\x3f\x81\x58\xee\xe3\xb6\xb0\x69\x5c\x42\x5b\xa0\x5d\x4a\x54\xf8\x6c\x65\xd1\xd9\xe9\xe0\xc1\x3b\x3f\x58\x5e\xf0\xca\x0b\x69\xf5\x00\x56\xde\x47\xf8\x0d\x30\x83\x88\xbf\x0b\x29\x20\x66\xdf\xc7\xf9\xed\x42\xed\x7d\x98\xf3\x08\x09\x4c\xea\x43\xd6\x38\x4d\x9f\x89\x1b\x86\xaa\x48\xa9\x5e\x9b\x7e\xb7\xbb\x4e\x61\x9e\x8b\x3b\x23\xf3\xb4\x07\x1a\xa2\xe9\xb9\xc2\xd6\xa1\x4c\xd6\x9c\x82\x0b\x86\xf3\x2b\xca\x17\x59\xa8\xc4\x54\xb2\x2f\xab\x2f\x8b\x2e\xa3\x2f\xc3\x2f\x57\x2f\xfb\x2e\x4b\x2e\xe3\x3e\xc6\xaf\x43\x97\x23\x85\x99\x4b\x19\xe3\xe9\x1e\x14\x78\xe3\xc5\xe0\xb4\x5c\xde\xc0\x65\xf3\xbb\x8a\x85\x91\xa8\x84\xa8\xa7\x68\x52\xa8\x98\x31\x0f\xe1\x51\x3d\xf0\xe7\xb9\xab\xc4\xfe\x66\x34\x5c\x06\x27\x39\x07\xe3\x46\xad\xdc\xee\x82\x5a\x6d\x47\x97\x4e\x1f\x81\x8b\x25\xeb\xa2\x88\x6d\x3e\x5a\xe5\x2d\x62\x4a\x1d\xdb\x89\x07\xa4\x96\xa1\x24\x07\xaf\x9b\x24\xd2\xca\xf7\x05\xa7\x48\x1a\xc5\x39\x35\xe9\x21\x00\x7d\xf3\xd6\x05\x5d\xb5\x66\x83\x55\x36\x30\xd0\x65\xd3\xe6\x2f\x27\xb0\x34\x38\xeb\x47\xe4\x59\x13\xcb\xbd\xd3\xc6\x05\xe6\x57\xe0\x5a\xb3\x5c\x61\x08\x06\x0a\x5a\xac\x96\xa9\x3d\xcd\x0a\x57\x50\x90\xb1\xfe\x98\x66\xed\xa0\xa2\x07\xc2\x4f\x79\xbb\x21\x21\xcd\x42\xea\x15\x6d\x4c\xc7\xda\x9f\x4e\x63\x61\x43\x70\xde\x65\x79\x65\x36\x56\xb2\x07\x38\xfc\xb4\x9c\xbf\xb0\x63\xb3\x77\x1a\xfa\x83\xb7\x8b\xbd\x50\xb1\x40\x6a\x0b\xbb\x5c\x2c\xbd\x6d\x26\x22\x99\x86\xca\x86\x29\x2a\x82\x17\xe9\x3a\xc1\x2e\x3a\x85\xad\xa8\x6d\xd2\x67\xe3\x58\x0b\x3d\xfd\xbe\xd5\xc0\xc5\xef\x21\x6f\x5c\xc1\x30\x90\xc2\x68\x77\xef\xb0\xf3\x02\x6c\xd8\xdf\x5a\x93\x8f\x76\x9e\xb4\x88\x79\xb9\x94\xc9\x5d\xa4\x4b\xb1\x9e\xbc\x33\x1e\x3b\x72\x65\x69\x31\x62\xe2\xc9\xf4\xc5\x8d\xd1\xbe\xa5\xa6\xb3\x70\x0d\xf0\x68\x14\xbe\x71\x5b\xc6\x43\x78\x53\x23\xfc\x88\x60\x06\x3e\x75\xe0\x55\xb0\x08\x2e\xd0\x8a\x33\x1f\x6b\x60\xa6\x87\x5a\xe5\xe1\x1e\x6d\x98\x2a\xf2\xe3\xe5\x41\x04\xa3\x8a\x08\x41\x64\x15\x16\xa6\xa9\x37\x12\x20\x6a\x85\x62\x02\xbd\xc9\x4d\xb9\x5b\xca\xac\x0a\x1f\xc6\x10\xdb\x83\x0a\x9b\x71\xad\xe6\xd6\x42\xd4\xe1\x5a\xe3\xd7\x22\xe5\x0c\xab\x44\x85\x6d\xa5\x9c\xbf\x05\x4a\xe1\xc3\x10\x16\xd7\x66\xef\x37\xbc\x65\xe8\xaf\x3a\xf7\xe8\x05\xa7\x67\xa5\xa9\x62\xff\xf2\x85\xa3\x12\x03\xd5\x64\x7e\x65\xb0\x78\x44\x8e\x91\x9b\x05\x37\x33\x97\x54\x5a\x31\xc1\xe3\x65\x68\x93\xfa\xf3\x37\xe5\x39\xdc\x98\x2c\xc9\x30\xd5\x98\x7d\x45\x29\xec\x44\x67\x23\xab\xad\xd8\x19\x72\x6b\x70\x7f\xfd\x93\xb1\xdd\x1c\x42\xce\xec\xb3\x0f\x2b\x2c\xf6\x25\xd2\x73\x60\x58\x2a\x6c\xa7\x94\x54\x13\x4e\x17\x61\x2a\x5a\xb3\x08\x73\x5d\xb1\x20\x1e\xd6\x82\xf3\xa3\x33\x2d\xc5\xe6\x39\x5f\xb0\xe5\xcd\x71\x17\x10\xf5\xc8\xd9\x1d\x9b\x97\xc8\xdd\x8d\x3f\x77\xd5\x91\xc3\x7d\xac\x3a\x48\xd1\x7c\x0a\x04\x53\x83\xdf\x6f\x03\x03\x03\xf3\xca\x31\x35\x32\x33\x32\x32\x32\xe6\xe3\xdf\xf7\x13\x37\xe3\xeb\x9f\xd1\x84\x76\xf0\x80\x46\xe9\x30\xf1\x5b\xfd\x29\xf1\xfd\xfd\x9d\x1f\x9c\xfc\x17\x71\xe4\xd8\xc8\xc8\x04\xec\x1c\x0c\xcc\xec\x17\xfc\xda\x7f\xec\x98\x82\xe6\x06\x06\x06\x26\x6f\x89\x7f\x72\xe1\xe2\x06\x91\x4d\x04\x59\xd3\x82\xf9\xc2\x41\xcd\x82\x79\xe5\xc4\x69\xc8\xda\x62\x08\xa3\xd4\x79\x3f\xf2\xc5\x66\xd3\x45\x60\xb2\x43\x6a\x48\xcb\xa5\xd0\x45\x57\x00\xc5\x4f\x1a\x88\x7a\xa3\x88\x10\xa2\xc8\x0e\xc4\xc9\x42\xa8\x5c\x6d\x3e\x70\xbf\x90\x07\x8b\xfb\x65\x7a\x6a\xd5\x59\xd5\xf9\xf7\x5a\x92\x6b\x64\x05\xaa\xba\xbb\xba\x76\x57\x92\xa7\x97\x2c\x0f\x0c\xdf\x92\x7e\xbf\x8a\xab\x2d\x06\xee\xbb\x0f\xb6\xdc\xf2\x2b\xae\xfe\xa0\xf2\x15\xe4\x33\xf5\x73\xcf\x13\xc8\x94\x33\xf6\xc4\xa9\x3b\xd4\xa7\x75\x9b\xf3\xbc\xc9\x9c\xc6\x39\x32\xd8\x3d\x73\x10\x63\x58\xf2\xb7\xdd\x7a\xf1\x59\x89\x84\x9f\xfd\x80\xcc\x24\xb8\xac\x8f\x53\xf7\x9f\xac\x2c\xc7\x71\xe4\x3e\xca\xe5\x79\x24\x9c\x8d\x49\x41\x7b\x3e\xe6\x3d\x04\xd5\xac\x4b\xcc\x57\xe4\xc1\x84\x34\x9d\x2a\xe6\x20\x77\xf2\x8e\x6e\x6b\x21\x61\xa8\x62\xaf\x88\x1c\xc7\xeb\x7a\x45\x15\x4f\x99\xff\x62\x51\x4f\x71\x9c\x82\x58\x2f\x9f\x16\x25\x7a\xcb\x0a\xeb\xf8\x9b\x55\x5f\x27\x28\x78\x90\xd3\x03\xcb\xdd\xa4\xe5\xe3\x8b\xe6\x19\x2d\x90\x0f\xab\xc8\x1a\xb7\x25\xde\x9a\x4f\xf3\x39\xf4\x21\x66\x7e\xdf\x91\x8e\xa3\x0b\xd1\xcf\x7f\x95\x92\xe6\x29\x5e\xcb\xe3\x5a\x6b\x7e\x5e\x29\xcd\xee\x38\x36\x9c\xa7\xb2\x13\xb9\x2e\x99\x53\x3f\x72\x1f\xce\xaf\x2a\xf2\xa1\xd4\x0d\xed\x8a\x36\xeb\xa7\x49\x1c\x47\x0b\x9a\xe8\xc2\x8a\x85\x5d\x03\x64\x06\xf9\xeb\x32\x0d\xed\xda\x1d\xe9\xc7\x31\x6b\x4c\x3d\x35\x94\x17\x07\x04\x6f\xb4\x34\x4b\x9c\x3a\x0e\xbd\x87\xef\xca\x6f\x8c\x2f\xbb\x14\x3d\xd6\x1e\xfd\xb9\x8b\xbf\xe1\x05\x9f\xa2\x0a\x7f\x1b\xba\x47\xcf\x56\x34\xb0\x94\x7b\x19\x3b\xaf\xf5\xee\xb4\x6a\x76\xec\x19\x41\xbe\xff\x9c\x07\xd9\x71\xa2\xd7\x64\x33\x56\xec\x7c\x5e\xe2\x2f\xc5\xba\x94\x3b\xb3\xfa\x43\xf2\x7b\x88\x0e\x7c\x60\x85\x0f\x8a\xd6\xa3\x5f\x49\x21\x4b\xf0\xf7\xa0\x8e\x17\x7a\xa4\x5f\x21\xdc\xe5\x0b\x3d\x58\x3f\xd8\xb9\xec\x33\xbc\xbb\x94\xb0\xf5\x88\x96\xde\xb7\x20\x3d\x2c\xd6\x6b\x80\xca\x9a\x2e\xed\xcc\x34\x86\x6a\xa2\xe5\xa0\xbe\x74\x7b\xcd\x9f\x2f\x14\xbe\x20\xf7\xce\x98\x34\x97\xfb\x91\x8f\x1d\xbb\x30\xe7\x92\xdf\xac\x1d\x5d\xf1\x35\xe3\x3c\x7d\x78\x6a\x7d\xbe\xb6\xcf\x95\xeb\x2b\xb5\xc3\x20\x1e\xb4\x3f\xf3\x59\xdb\x06\xc7\x54\x3e\xbd\xa7\x2f\x64\x49\x22\x05\x04\xf7\x1f\x68\x7f\xdd\x88\xc4\x56\xc7\xbe\xf8\x7d\xc9\x7c\xf6\xd5\xfa\xd8\x94\xc1\xb4\xbe\x11\x85\x1e\x73\x40\x81\xf4\x85\x7a\xd5\xc5\xe8\xfb\x95\x22\x3d\x66\x04\x1c\x00\xdd\xb1\xee\x03\xbc\xa1\xad\xab\x9a\x2f\x5b\x50\xc0\x65\x22\xc5\xda\x7a\x40\xaf\xbc\xb9\x84\x76\xdf\x7c\x73\xca\xda\x95\xde\xba\x9d\x50\x6e\x68\x1d\xcd\x3d\xe9\xf5\x9f\x73\xe4\xde\x0a\x77\xc1\x34\xaa\x0b\xfb\xd8\xee\xa0\x87\xa4\xd9\x1b\xc4\x69\xaa\x93\xa6\x0f\x66\x2e\xf8\xcf\x89\x67\x81\x16\xcf\xc0\xe7\x37\xd1\x8f\xe1\x2c\x3d\x8b\x4e\xf9\xb2\x6e\x53\xff\xc2\x1b\x50\x00\xfb\x6c\x20\xd1\xeb\x0b\x86\xdd\xcc\x0c\x76\x94\xbd\x23\x1d\xc3\x8a\x7f\xee\x0b\xb1\xf6\x4d\xe1\x7d\xb3\x4b\x85\xee\xaa\x6c\x6e\xe0\xd9\xf8\xb4\x85\xde\x13\x8c\x77\x7b\xd1\xa7\x48\xbf\x24\xd2\x95\xf7\xe6\x10\x51\xa3\x63\x6a\xde\xcd\x9a\xa8\x6e\x73\x45\xff\xd7\x19\x22\xe0\x66\x73\xc7\x0f\xf2\xb6\x5f\x1c\x6d\x4e\x5c\x08\xae\xf7\xfa\xac\xee\x48\xcf\xbf\x07\xdd\x8c\x6f\x07\xc3\x67\xf7\x86\xf1\x09\xce\xef\xce\x2b\xa7\x34\xcd\x57\x6d\xce\x92\x60\x7c\x6f\xee\x50\x81\xa1\x33\x02\x05\xcf\x7a\x46\xe4\xaf\x59\x34\x8a\x09\xe9\x21\x4a\x4c\x27\x6b\xb3\x75\xb6\x7c\xc4\x1f\xf3\x58\xf2\xb5\x4e\xb6\xf4\x5a\xf9\x09\xfe\x23\x22\x2a\x36\x17\xe4\xce\xc8\x44\xeb\x3a\xd2\x4b\xf3\x6f\x50\xe0\x45\xce\xcb\xeb\x57\xdf\xdc\x43\x67\xcf\xde\xcd\xdc\x83\xbf\xc2\x62\x7f\x20\xd1\x37\x38\x73\x52\xe5\x4f\x2c\x29\x8e\x1f\x66\x52\xe1\x21\xc2\x79\x6a\x5c\x6a\x34\xe7\x70\x75\x52\xa3\x92\x32\x14\x63\x3f\x9e\x65\x9b\x0c\xfe\x21\xe6\x24\x11\x14\x95\x2c\x42\x94\xb2\xc0\xaa\x68\xef\x4e\xdd\x5d\x4b\x69\x8f\x8f\xaa\x78\xbb\xd0\xcc\x17\x8b\x94\xa9\x39\x93\xfd\x4e\xa4\x59\xa8\x6f\x4a\x57\x2b\xcd\x39\x12\xcb\x53\xed\x52\x73\x6f\x51\xa3\xff\x39\x22\xbd\x72\x76\x3a\xed\x83\x78\x6f\x83\x05\xe3\x54\x25\xce\x98\x8e\x0b\xa6\xd0\x7a\x58\xca\x93\xa7\xa2\x8f\x3d\x99\x8a\xa3\xd9\xb1\x02\x9f\x72\x6e\x29\xeb\xf0\x68\x07\xc6\xe9\x79\xbf\xad\x9a\x28\x89\x9c\x20\xb9\xe8\xfb\xe8\x08\x44\xf6\xea\x23\x46\x5a\x7f\x10\x6b\x3e\x95\xa9\x44\xe5\xc7\x1f\xae\x84\xe5\xef\x05\x1c\x8f\x76\x73\xb6\xf6\xee\x5f\xe4\xd2\xb1\x1f\x7b\x2e\x31\x09\x29\xb0\x72\x71\x88\x96\x27\x40\x14\xc4\xcf\x51\x56\x72\x1b\xb0\x9f\x9e\xf1\x62\x1c\xc9\xd0\x3f\x4b\x05\x00\xad\x61\x05\x6e\x21\x6e\x6d\x46\x0d\x68\x7d\xde\x93\x6f\x14\x73\xc1\x40\x30\x4a\xdd\xee\x8c\x89\x8c\xad\x85\x9e\xf8\x1d\x30\x2a\xb4\x89\xa0\xb6\xcb\xd6\xc3\x5e\x7e\xe7\xab\xe6\x12\x92\x73\x0f\xa1\x40\x49\xe2\x4a\xd5\x22\x0c\x39\x39\x4b\x97\xae\x82\x7e\x78\xbe\x6e\xc0\x7b\xa4\xb4\xca\xcf\x1c\x11\xc0\x1a\x26\xa1\xfe\x5d\x25\x3e\x5f\x37\x73\xe8\xf5\x88\xbb\x65\x5f\xe1\xe5\x4b\x81\x85\xa2\xdf\xa5\xf8\xce\x2e\x68\x19\xc6\xf0\x4d\x89\x17\xa1\xce\xd8\xe9\x4c\x56\x4f\xf0\xe3\x5a\x32\x21\xa1\x12\x35\x3e\x1e\xfc\x08\x79\x60\x3c\x38\x1c\x5c\x0f\x3a\x1c\x6c\x76\x10\xa0\x66\xfd\x93\x3d\x72\xde\x15\x67\x3b\xb2\xd0\x9f\xab\x19\x47\x78\x0f\xd5\x09\x0f\xb6\x5d\xb1\x52\x30\xfa\x63\x6e\x9d\x78\x66\x03\x44\x30\xd7\x5f\xf0\x82\x33\xab\x02\xf9\xf0\x87\xe4\x45\xd6\x65\x4c\x99\x2a\xc9\x15\xfd\x8f\xe0\xa1\x36\xb1\xe2\xb6\xe7\xc2\x22\xe4\x09\xf3\xdf\x56\x69\x05\xb0\xbc\xe4\x3b\xa6\xe8\x0d\x71\xe5\x40\xb8\x4e\x55\x00\x37\x66\x9c\xe0\x3c\x15\xde\xf5\x12\x80\x29\xf7\x03\xd7\x7a\x51\x71\x64\xce\xcc\x11\x8b\x9b\x79\x9a\x39\xa2\x77\x23\x27\x41\x0b\x34\xda\x84\x05\x9f\xaf\xb5\x6a\xc2\x9d\xee\x0a\x14\x8c\xcc\xe1\x62\x1b\x53\xa6\x45\x4a\x38\x19\x0a\x24\x3a\x75\x16\x78\x30\x1c\xa8\xc1\xe2\x91\x8d\x01\x74\x45\xbd\x7e\xc8\xd5\x8f\x82\x9a\xc3\x7c\x64\x37\x74\xa3\x3d\xa7\x32\xb4\xf9\xde\xfb\x01\x73\x2e\x6c\x8c\x92\xc3\x70\x16\x6d\x3f\xf2\x68\x33\xd7\x68\xce\xc9\x9d\x56\x35\x0e\x7d\xc9\x5a\xd1\xee\x5c\x10\x6f\x6c\x5d\x4a\x5a\x1f\x75\x22\xc7\xdc\xa7\x99\x61\x1d\xa4\x73\x2e\x9e\xbc\x5a\xf2\x6e\x4c\x21\xb6\x39\x6f\x09\xed\x82\xf6\x24\x7c\xec\xcd\xb0\xb2\x33\xa6\x2c\x3e\x36\xe5\x76\xe8\x97\x37\x43\x88\x75\xb9\x23\x75\xf7\x73\xe5\x76\x39\x0e\xda\x07\xad\x7d\xdf\x74\x2f\x83\x24\xe1\xb2\x3c\x8b\x1c\xb1\x79\x3c\x55\x1d\x91\x59\xb7\x23\x89\xdf\x6f\x6d\x04\x3f\x54\xce\x52\xa3\xf7\x60\x6e\x6f\xc1\x78\x90\x0f\x02\xf1\x2c\x29\x11\x05\x22\x81\xee\x51\x3c\x91\x95\xae\x90\x7d\x92\x5a\xb2\x91\x53\xf9\x23\x04\xa5\xa7\xca\x6e\x04\xa1\x81\xd0\xad\xf1\xc5\xdf\x5c\x0f\xbc\xc1\xab\xe8\x7c\x8a\x8b\x87\xe4\x17\x54\x0b\x7e\x70\x8a\x0a\xcd\x81\x78\xfd\xb3\x80\x77\xdc\xfb\x59\x96\x72\x39\x37\xcb\xa2\x7d\x02\xdb\x53\x80\x3b\x91\xe3\xdc\xf0\xfe\x8f\x3e\xbd\x02\x49\xac\x9e\x66\x80\xdf\xdf\xf5\x18\x60\x4f\x58\xda\xd4\xa5\xfe\x49\x76\xc7\x8f\xd3\xea\x1a\xc3\xe1\xf4\x0b\xab\x8e\xd9\xce\x89\x88\x43\xc4\x03\x47\x96\x43\xdd\x91\x9d\x22\x4f\xa4\x8b\xf6\x57\xac\x9b\xa0\x6e\x12\xec\xbd\x6b\xe7\xb4\xef\x03\xb9\x5d\xcb\x1b\xf0\x3e\x3e\xb1\xa5\x5f\x2e\xc4\x0f\x84\xfc\x83\x91\x54\xb7\x7e\x32\x01\x02\xbb\xa7\xaa\x17\xb8\x96\x07\xdc\xbd\x06\xf3\xcd\x41\x8e\xa5\x60\xf1\x8c\x0b\x2f\x68\xbb\x8c\xfb\xdf\x70\x33\xf5\x5a\xbe\xfa\x7a\x12\x98\xe6\xd1\x76\x49\xd4\x6f\x52\x65\x5a\x7d\x72\x77\x08\x99\x68\x10\xe6\x32\x69\x10\xf0\x66\x32\xdc\x93\x5c\x18\xd0\xb4\xe6\x32\xbe\x13\x29\xfb\x34\x0c\xf8\xf4\x87\x13\x8e\xe3\x5e\x99\xf7\x67\x2c\x98\x7e\x42\x1c\x6b\x6e\xb1\x72\x14\x9c\x42\x76\xc7\x06\x05\x42\x65\xff\x88\x70\xcb\x7f\x67\x56\x99\x9a\x57\x89\xff\x53\x43\x4e\x75\x16\xa0\x50\x1d\x26\xbe\xad\x91\x56\xa0\x3f\x5f\x33\x99\x0b\xef\xd9\x1c\x59\x23\x6d\x63\xd8\x3e\x8f\x4f\x71\x36\x9f\x4b\x25\x7a\x8a\xfc\xd7\x71\x3c\xd1\x01\x33\xe5\xa5\x54\x4c\x3a\x27\x81\x0a\xb6\x1b\x57\x3f\xc1\x76\x07\x29\xcd\x62\x00\xcb\xb2\x5b\xc3\x49\x51\x96\x59\x8d\xe0\x59\x68\x4d\x44\x7e\x18\x43\xb4\xc7\x97\x89\xf5\xf8\x10\x9a\x60\x58\x26\x47\xcb\xf5\xc6\x3b\x05\x39\xdf\xec\x9e\x25\x87\x8f\xd2\xa1\x55\x46\x7f\x77\x25\xf4\xbe\xc0\x22\xcc\xc7\x3b\x50\x5e\x0c\x2f\x64\x4a\xc5\x05\x53\xdc\xcd\xda\xe7\x26\x2c\xfa\x13\xc0\xc0\xba\x03\x98\xe7\x57\xa2\x4c\xe9\x20\x72\x7a\xff\x4d\x80\xb2\x95\x4c\xd4\xdb\x03\xc6\xdc\xbb\xb0\x88\x7f\xf3\x06\x70\x24\x3e\x18\x9e\xdf\xc6\x26\xfa\x5c\x87\x4f\x48\x3e\x53\xac\xff\xa2\x66\x81\x00\xbc\xc2\x7a\x43\xa0\x9b\x43\x17\x9a\x33\x6d\x46\x9a\x4d\x22\x98\x2b\x0c\x0f\x99\x45\x0c\x5b\x62\xe0\x49\x2c\xf9\x22\xb8\xf7\x89\x6c\xad\x39\x11\xc7\xb4\x39\x56\x7c\x5f\x21\x64\x3a\x1f\x89\xdd\x13\x24\x08\x5c\xd3\xb0\x06\xf7\xc0\x4e\xbb\xfe\x60\xcd\x8b\xaa\x4f\xae\x78\xe7\xbf\x4b\xde\xe7\xc8\xfc\xfc\x7d\x5f\x0e\xd8\x53\x0b\x90\x6c\xe6\x8c\xdb\x26\xce\xbc\x78\xe4\x0c\xda\x93\x63\x9b\x19\xd9\xd2\x06\xe1\x89\xf6\x6f\xe4\x64\x73\x1f\x8d\xdf\xe5\xc4\xd4\x75\x4e\xfb\x10\xb5\x9e\xa2\x77\xa3\xe8\xc7\x54\xb4\x67\x74\x50\x4c\x3b\xc3\xe2\xa5\x37\xb5\x21\xcc\xa5\x31\x0f\x83\xd4\x32\x8f\xa7\xcd\xa1\x7a\x35\x8b\xcc\x31\xfd\x03\x73\x7f\x3f\xe0\xf3\xa3\x01\xa6\x08\xcd\xd0\x5c\xf6\x0e\x3c\x7b\x40\xa1\xae\xad\x78\x8e\x9a\xae\x58\x68\x77\xe6\x88\x7a\xab\xf7\x7d\x58\xbd\x17\xc0\xfe\xf8\x17\xf2\x0f\xa9\x03\x7f\x78\x22\x07\x71\x53\x96\x5d\xa7\xb9\x8c\xab\x4b\xc7\xf1\x3d\xc2\x9c\x48\x42\xa0\x6c\xb0\x2a\x9c\xbf\xe7\xa2\xe3\x1a\x7e\x43\x5b\xb6\x8e\xef\x6d\x20\x23\xc1\xcb\x90\xa3\x20\xf7\x7b\xa6\x27\x8d\x0f\x52\xc1\x2b\xc9\x27\xf2\x10\x05\xe2\x6e\xe4\x80\xf1\x1b\x81\x31\x23\xe1\x8c\xe4\xbe\x5f\xec\x1b\xee\x23\xdf\xac\x9d\x22\x53\x75\x32\x69\x50\xef\xd2\xf4\x19\x42\xef\xac\x4b\xda\xec\x81\x32\xe5\xe9\x13\xdf\x07\xa3\x12\x2b\xbc\x5e\x09\x96\x67\x78\xa7\x58\xef\x94\x53\x67\x34\xf2\xda\xc4\x54\xc4\x38\xe2\xb3\xc3\xdb\xe4\x76\xc8\x1a\xfd\xe3\xf1\x80\x60\x24\xab\x7b\xb6\x80\x27\xd0\x3b\x72\xcf\x73\x3f\x23\x26\xa1\x73\x32\x68\xf3\xa5\xc2\x9d\xd8\xff\x65\x21\x25\x32\x82\xef\xe3\x0d\xdf\x1e\x19\xf0\x90\xd8\x13\x09\xfa\xce\xe8\x52\x04\x05\xe4\x3b\x5d\xe7\x0f\x5d\x51\x0b\x1c\x0f\xdf\xe0\xda\xce\x79\x07\x06\x5b\x42\x8d\x60\x14\x84\xfb\x0e\xf7\x1c\xd1\xf5\x14\x8d\x67\xbf\x1f\xb8\x47\xd4\xdc\x25\xb5\xce\x36\x85\xf3\x99\xc1\x23\xa7\xd2\xbb\xc8\xb4\x69\x45\xd9\xc1\xae\xca\xde\x6f\xed\x47\xdb\x9d\xf1\x6d\x34\x29\x34\x1d\x6b\xb9\x4e\xa7\xd5\x02\xa8\x74\xff\x82\x64\x82\xbe\xeb\xed\x30\x15\xb5\xa9\x88\x37\xaa\xea\x9a\x56\x8a\xcc\xab\x1f\xba\xc7\x28\x37\xb2\x0a\x49\xf4\x57\x29\x54\xda\x38\x5a\x2f\xc8\xff\x75\x41\x4f\xf5\x89\xfa\xf5\x92\x6c\xbc\x8d\x74\xf1\x27\xd9\x33\x89\xae\xe6\xb2\xbf\xd0\x6d\x78\x1e\x9a\xf1\x7b\x71\x94\x68\x0c\xeb\x69\x2b\xce\xff\x96\x69\x6b\x14\xfc\x9d\x68\x9f\x44\x77\x81\x49\x7a\x31\x13\xa0\xea\x92\xdd\x3d\xf1\x96\x74\x03\xbf\x86\x85\x14\x94\x15\xe0\x40\xa2\xda\x46\xb1\xad\x83\x7a\xd3\x2f\xc4\x01\x46\x68\x7f\x60\x0e\x51\xb9\x10\xff\x52\xe0\x24\x14\x00\x03\x82\x2a\xff\x20\xfe\x80\x30\xef\xcd\x77\xfb\xcf\xff\x92\x67\x9a\x7c\xb2\x60\x16\xec\x87\x9c\xd0\xf4\xcf\x30\x04\x04\x24\x23\x01\x08\x30\xc2\xdf\xe0\xf2\x60\x5e\x39\xa9\xc9\x7b\x36\xe8\xc2\x18\x63\xfd\x3b\x25\xf2\xb6\x25\x46\x0b\x2a\x3d\x89\xc2\x62\x83\x31\x3b\x2d\x29\x58\x21\x9c\x5b\x82\x67\xf2\x56\x26\x3f\x4b\x35\xcf\x39\x78\xa5\xd3\x28\xbb\x8d\x3d\x92\x12\x6d\x0d\x85\x6e\xa1\x46\x68\x89\x85\x7a\xb0\x7b\x1e\xd5\x21\x89\x07\x1d\xa9\x4c\xd1\x1b\x45\xe4\xa5\x4e\x38\x2d\x4f\x3e\x5e\x67\x37\xa0\x1a\xae\xf8\xc2\x43\x5f\xc7\xc7\xf1\xa7\x90\xfe\x81\xcc\x36\xc4\x61\xf7\xe8\xb0\x9d\x90\x05\xe9\xb1\x95\x3d\x88\x74\x0c\x06\xcb\x54\xdb\x7b\x64\xde\x97\x5d\x60\x19\x77\x2c\xd3\xd6\x9c\xd6\xfc\x1d\xbd\x09\x3d\xb7\x19\xd3\xa6\xbc\x00\x5f\x0d\x3d\xc1\x92\xe1\x41\xda\x39\x07\x3c\x9e\xf5\x72\x63\x39\x84\x76\xfb\xb9\xe6\xe9\xed\x02\xba\x0c\x00\xe6\x3e\x5d\x06\x93\x29\x67\xfa\x7a\x00\xac\xfb\x8c\x77\xea\xf3\x5a\x9a\x2c\x08\xd8\xd3\xda\x13\x61\xef\x69\xe1\x4d\xf8\xb2\x83\x9c\x36\xe5\x75\x1d\xd0\xda\x13\x8c\x1d\xfe\x23\x3e\xd1\x24\x0c\x17\xc3\xe4\x71\x3e\x32\x62\x80\x59\x44\x8e\x44\xba\xbc\x04\x12\x75\x0e\xca\x43\x79\x10\xe9\x79\xff\x2f\x04\x02\x08\x53\xd6\x20\x73\x43\xba\x2e\xc9\xf6\x9a\xf0\x8e\x32\x7e\x71\x41\x6e\xb4\xb7\x0f\x6b\x7c\x5f\x2c\x7a\x89\xe9\x8f\x85\x49\x7b\x53\xf3\xcd\x1f\x23\x26\x94\x93\xdf\xe8\x32\x16\x2a\xf2\x66\x62\x91\x78\x17\xd2\x38\x8c\x03\xcb\x62\xb2\xcc\x47\xd1\x3a\x59\x40\x23\x9a\x66\xb7\x09\xf9\x98\x34\xa2\xb1\x1a\x12\x33\x86\x16\x33\x47\xbe\x9f\xea\xd7\x5b\x03\xb8\x9b\x15\x4b\xef\x28\xea\xd7\x9b\x2d\xb9\x80\x1f\xf2\x2e\x31\xbc\xcb\x78\x96\x57\x3e\x4e\x5a\xf6\x2d\xb6\x54\xd8\x33\x12\xd5\xfe\xdd\xb1\xa7\x12\xea\x12\xad\xaf\xfa\xc1\xfc\x36\xbc\x80\xfa\xa6\x65\xec\x1c\xd9\xd4\x51\x6b\xb2\xe7\x1e\x88\x7a\x13\xb1\x5d\x06\xaf\x64\x11\xf2\x52\xb3\xb2\x63\x6f\xf4\x6e\xca\xdc\x02\x43\x9b\xaf\xf7\x93\xa3\x32\xe5\x63\x01\xc2\xc5\x9b\xa1\x2e\xbd\x95\x24\xc5\xb5\x93\x39\xfa\x68\x6e\x32\x9d\xc8\x32\x7b\xcd\x96\xf0\x16\x1b\xf4\x9b\xa4\x2b\x3d\x31\xe9\x8e\x93\xee\xf8\xca\x4c\x55\x6b\x24\xb3\x0c\xe9\xd9\x4a\xda\xd4\xf9\xca\x79\x7f\x6a\xac\xe2\x19\x33\xc9\xd3\xa1\xee\x4a\x16\x2a\xfd\x2a\x74\x9d\xf0\xbf\x04\x11\xe7\x32\x61\x3a\xd5\x20\x17\xbb\x3a\xf2\xca\x78\x5e\x96\xe6\x50\x8d\xb2\xa6\x7e\x9f\xe2\x96\x0e\x87\x59\xf9\x39\x32\xac\x39\x34\x39\x62\xb6\x77\x95\x63\xda\x6b\xc3\x0b\xc4\xef\xa8\x33\x5c\x73\xa0\x2d\x7f\xd5\x5b\x80\x81\x01\x57\xc2\xcd\xe8\xd9\xb7\xd8\x2d\x77\xa5\xb7\x26\xda\x92\xf7\x37\x31\xf3\x27\xb8\x38\x65\xe6\xe3\x1d\xfc\x5c\xcc\x3a\xaa\x57\x8e\xbf\x26\x94\xdb\xe1\x44\x93\xbb\x7a\xa6\x09\x15\xae\x56\x59\xfb\x74\xca\x7a\x5a\x0e\x9d\xa2\x51\x66\x66\x6f\xd3\x4e\x1b\x7b\x1a\x7d\x1c\x09\xd3\xd4\xf4\xf4\xf4\x74\x42\xe6\x33\x73\xbf\xff\xf4\x74\x43\x42\x66\x55\xc9\xb3\xdc\xc9\x87\x6b\x80\xc2\x22\xf9\x4e\xdf\x8e\xbf\xa3\x26\x35\xb5\xdc\x67\xbf\x20\x08\x0f\x3b\x71\x08\xa3\xd4\x41\x46\x3f\xbf\x8b\xc1\xdd\xf4\x3c\x6d\xb9\xb6\x12\x5f\xa5\xbd\xd4\x01\x1a\x32\x84\xcd\x8c\x04\x9e\x7b\x62\x18\x05\xa3\xe0\xe7\x30\xd3\x8f\xe2\x06\x84\xb4\x61\x38\x2d\x58\xfc\xc1\xb1\x06\x58\x3b\xb8\xec\xc1\x93\x06\x28\x3b\x58\xdd\xc1\xd5\x06\xc4\x1e\xd8\xb6\xf0\x2b\x23\xdf\x75\x70\x8f\xb0\x5c\x23\xcb\x75\x28\x8f\xf0\x1d\x23\xcf\x75\x88\xe7\xb0\x5e\x23\xc7\x75\x98\xe7\x70\x66\x9c\x48\xb4\x94\xc2\x1f\xd0\x19\x4a\xe1\xb0\x19\x61\x9f\x46\x81\x5c\x60\x48\x61\xa1\x00\x23\x2e\x48\x8d\x41\x0c\xb9\x61\x84\xe9\xa1\x42\x27\x1c\x02\x24\xc9\x81\xbf\x4e\x18\x04\x88\xe3\x03\x8d\x4e\x04\x04\xc8\x54\x03\x7f\x9c\xd0\x72\x10\xca\x07\x2a\x9d\xf0\x72\x90\x2c\x07\x32\x9d\xb0\x72\x10\x4f\x07\x3a\x95\x42\x1f\x06\x42\x7c\x6c\xd8\x9e\x24\x6c\x20\xf1\xe6\x21\xa1\xe8\xad\x44\x61\xec\xb4\x10\xf5\x9d\x0a\x60\xfc\x9d\x06\x43\xd9\x01\xa2\x60\xa4\x62\x4c\x30\x0f\x0d\x60\x31\x0d\x58\xb3\x91\xf0\x00\x91\x8e\x9f\x0c\x11\xb2\x00\x95\x0e\x04\x86\x48\x5a\x80\x4c\x07\x5c\x5d\x84\x2d\x40\xa7\x03\xa9\x2e\x12\x1f\x20\xd1\x01\xeb\x10\xa1\x0b\xd0\xe8\x40\x74\x88\xe4\x05\x28\x74\xc0\x5f\x47\xf8\x02\x0c\x3a\x90\xaf\x23\x61\x00\xc2\x5e\x3f\x89\x22\x24\x01\xca\x5e\x08\x44\x91\x54\x00\x69\x2f\xb8\xbc\x08\x4b\x80\xb6\x17\x52\x5e\x24\x36\x40\xdc\x0b\xd6\x20\x42\x13\xa0\xee\xc5\xda\x03\xb5\x0b\xe7\x18\xda\x3e\xcc\x0b\xc8\xbd\x65\xf0\xe2\xec\x81\xd9\x85\xbf\x09\x7d\x19\x86\x01\x84\xde\x92\x82\x98\x7a\xa0\x89\x83\x13\x86\xc6\x01\x87\xb7\xb0\x20\x72\x3f\x38\x01\xc4\xfc\xe0\xb9\xa1\x53\xc0\xc3\x2d\x14\x88\xac\x07\xc9\x30\x84\x71\x58\x13\x50\x7d\xcb\x0e\xe2\xf1\x83\xe8\x83\xdd\x0b\x71\x1c\xf6\x04\x74\xdf\xf2\x83\x04\x3e\xc0\x02\x7e\x0a\x86\x10\x0f\x2b\x02\xca\x6f\x59\x41\xdc\x1f\x3f\x02\x60\xfb\x43\x0c\x87\x1d\x01\xed\xb7\xd0\x1f\x48\x01\xc8\x81\x41\x82\x43\xf9\x80\xb9\x5b\x6c\x10\xed\x07\xe2\x17\xd2\x77\x50\xe0\x50\x3f\x60\xef\x96\x18\xc4\x58\x86\x82\xf2\x97\x29\x0e\x77\xda\x04\xe9\xa1\x92\xd0\xe9\x27\xbc\xd6\x88\x31\xc1\xa0\xb2\x5e\xc4\x94\x33\x54\xdd\x48\x9c\x93\xe9\x36\x24\xe7\xe8\x8c\x93\xeb\xf6\x8f\xf6\x91\x5a\x27\xdb\x6d\xe8\xbd\xb0\xad\x03\x8f\x0e\xfe\xeb\x20\xde\x03\x85\x0e\xd6\xeb\x90\xee\x03\x87\x0e\xde\xeb\x60\xdf\x03\x83\x0e\xce\xeb\xd0\xf7\x03\x9c\x78\x53\xd8\x29\x2d\x61\x08\xf9\x9a\x03\x48\x85\x83\x80\x0e\x41\xa2\x20\x98\x03\x61\x2f\x26\xa2\x90\x6a\x27\xb8\x72\x67\x68\xcb\x3b\x25\x3e\x04\xe4\xf1\x5f\xb7\x52\x7c\x70\x09\x63\xa6\xb7\x5a\x7c\x48\x09\xe3\xe8\xb7\x62\x7c\xd4\x4f\x3c\x79\xb1\xe5\x80\x4a\x2f\xbc\xbc\x78\x4b\x40\xa6\x17\x56\x5e\xdc\x29\xa0\x53\x6b\xf8\x61\x7e\x88\x87\xa3\xe1\x0f\x9c\xee\xfa\x18\xd2\x66\x07\x5e\x37\xd0\x08\xf9\x1d\x58\x14\x69\x3b\x3f\x0e\x26\x1a\xeb\x84\x74\xea\x0c\x8e\xed\x4c\x9f\x97\x80\x0d\x08\xf7\x42\x35\x88\x4d\x07\x94\x7a\xe1\x1a\xc4\x6b\x02\x52\xbd\x30\x0d\xe2\xd6\x00\xad\x5e\x84\x06\x09\x9c\x80\x38\x2f\xf4\xdd\xd8\x76\x40\xad\x17\xfe\x6e\xbc\x27\x20\xd7\x0b\x7b\x37\xee\x05\xd0\xeb\x45\xbc\x9b\x80\x0c\x08\x05\xa1\x08\xc4\x26\x00\x8a\x41\x38\x02\xf1\x8a\x80\x64\x10\x86\x40\xdc\x1c\xa0\x19\x44\x20\x90\xc0\x08\x88\x01\xa1\xf5\xc5\xd6\x03\xaa\x41\x16\x7e\xf0\x7d\x98\x7b\x11\x8e\xe3\x9e\x00\xde\x3b\x7d\x90\x83\x1f\x72\x1f\xf6\x5e\xe4\xcd\x38\x32\x00\xe6\x4e\x14\x64\xec\x87\x28\x18\x42\x3c\x9a\xb0\x3f\x7e\x87\x0e\x92\xfe\xc0\x08\xc0\x13\x0c\xcd\x1f\x9d\xdb\x3f\xbd\x83\x07\x89\xfb\x11\xf6\x87\x19\x8e\xd5\x03\x34\xef\x6c\x41\xee\x1f\xd0\x01\xe8\xfd\xe1\x7b\x63\x37\x00\xcf\x3b\x5f\x90\xff\x07\xf8\x17\x4a\x60\x98\xe0\x58\x3e\x40\xf1\xce\x12\xe4\xfa\x01\xf5\x85\x16\x18\xde\x3f\xb6\x07\x70\xbc\x43\xfc\x20\xfc\x22\xfa\x0e\x0a\x1c\x11\xdc\xcf\xbf\x63\x04\x69\x7e\xe0\x7f\x11\x7e\x07\x7f\x8f\x04\xee\xf7\xdf\x09\x82\x0c\x65\x50\x51\xd0\x94\xb3\x58\x52\x4a\x09\x8e\xad\xa3\xe0\xd4\x4a\x8c\xf1\x0a\x95\x75\x24\xa6\xac\xa1\x6a\x4b\xe2\xac\x4c\x37\xc3\x38\x4a\x67\xac\x5c\x37\x43\xda\x4a\x6a\xad\x6c\x37\x23\x76\xc5\xb6\x16\x3d\x5a\xf8\xaf\x84\x78\x17\x15\x5a\x58\xaf\x44\xba\x17\x1d\x5a\x78\xaf\x84\x7d\x17\x0d\x5a\x38\xaf\x44\xdf\x17\x71\xe2\x54\xff\xfc\x53\x23\x0d\x95\xab\x5a\x84\x94\x5f\x0c\x68\x11\x24\x14\x82\x59\x14\x76\x63\x22\x14\xa9\xb6\x8a\x2e\xb3\x8e\xb0\x38\x53\xe2\x89\x45\x2a\xff\x05\x94\xe2\x89\x8e\x2f\x33\x05\x6a\xf1\xc4\xc7\x97\xa3\x03\xc5\x78\xfe\x28\x94\xa9\x02\xd5\x78\xe2\x14\xca\x59\x81\x72\x3c\x31\xb3\x65\xae\x40\xbd\xaa\x05\x6f\x33\xe5\x5c\xbc\x65\x72\x71\x7a\x1b\xd5\x48\x3b\x1d\x79\x7d\x97\x0a\x49\x7f\x97\xc9\x62\xf6\x23\x55\x21\x52\x71\x36\xc9\x87\x16\xa1\x98\x96\xb4\xd9\x72\x78\xa0\x48\x57\x14\x43\x99\x2c\x50\xa5\x2b\x96\xa1\x9c\x16\x28\xd3\x15\x5d\x57\x66\x0b\xd4\xe9\x8a\xaf\x2b\xc7\x07\x4a\x74\xfd\x71\x28\xd3\x05\x6a\x74\xc5\x39\x94\xf3\x02\x15\xba\x62\xae\xcb\x7c\x81\x06\x5d\x09\xd7\xe5\x30\x40\x61\x9f\x28\xa2\x32\x49\xa0\xb2\x4f\x2c\x51\x39\x15\x50\xda\x27\x3a\xaf\xcc\x12\xa8\xed\x13\x9f\x57\x8e\x0d\x14\xf7\xf9\x63\x50\xa6\x09\x5c\x59\x26\xcc\x6c\x33\x85\x12\x2e\xc3\x86\xf2\xf8\x85\xff\x7b\xca\xd1\xed\xbe\x4a\xb0\x9c\x60\x4d\x35\x13\xe9\x65\xd8\x0d\x45\x27\x40\x38\x3a\xeb\xdc\x7b\xdf\x84\x07\x2e\x25\xdf\x61\x43\x81\x91\xd8\xc3\x26\xfe\xb8\x1d\x33\x22\x37\xa7\xe5\x8a\x44\xac\x3d\xfb\x49\x7d\x2e\x57\xb5\xb3\xb5\x6e\xab\x7a\xe3\xd3\x4f\xaf\x5b\x59\xca\xa1\x3a\x15\xf1\xd2\x63\xcf\xa5\x62\xbf\x8d\xb5\xd0\x11\x2a\xd7\x6d\xfc\xaa\x92\x6f\xae\xcc\x26\x0d\xbd\x4c\xb4\xbb\x7c\xb1\xcf\x96\x3d\x32\xfb\xda\x6f\x6f\x3f\x02\xe1\x14\x26\xd7\xee\x48\x3a\xb5\xf1\xdd\xdd\xb3\x10\xc8\xbd\x6a\x52\x6b\xfc\x8e\x28\xc9\x5c\x5e\x5e\xc3\x74\x5a\x9d\x56\x1f\xa2\x60\x90\x86\xa6\x08\xec\x88\x73\xe8\x3a\xd6\xba\xfa\xe1\x58\x76\xe6\xbe\xdd\x07\x07\xe7\x5a\x87\xfe\xa4\x16\xb7\xa6\xba\x2c\x4f\x8a\xb3\x78\x35\x31\x55\x77\x87\xef\xa0\x7a\x7c\xae\xa1\xa7\x6a\xd5\xba\xf4\x81\x5d\x72\x51\xb7\x35\x23\xbb\xd0\xfc\xe1\x30\xf6\x70\x15\x90\x61\xaf\xc5\x7f\xac\x7b\x96\xb6\x85\xfc\xda\xb9\x34\xbd\x59\x78\xbc\x1e\x67\x52\x81\x35\xa4\x23\xb9\x71\xa5\xa0\x15\xb5\xf5\xe0\xc1\x7a\x89\x01\xd2\xee\x36\x74\x55\xa3\x25\x50\xc8\x42\x5c\x41\x4e\x35\x94\xe3\xe9\xeb\x11\x48\x6a\xd1\x94\x14\xb6\x6a\xc7\x5a\x6a\x4a\x2f\xda\x71\xbc\xf7\x85\x55\x68\x3f\xf4\x94\xd4\xd5\x10\x9d\xac\x5c\x39\xb9\x2c\x73\x71\xcd\xdb\xf9\xf9\xcb\xd0\x9c\x7f\xc5\x71\x5d\xa1\xd0\xd2\x9b\x5d\xbb\xfa\xbe\x59\x43\x95\xf2\x08\xfd\xc4\xbd\xaa\x8c\xd0\x22\x24\xfe\xb8\x5a\xae\xb8\x18\x14\x26\xd6\xf0\x97\x44\xcd\xa0\xd6\x81\xbd\xeb\x21\x6d\x8f\xc0\x5a\xdb\x2f\x2c\xd4\x20\x60\x5e\x6a\xaa\xd0\x92\x2f\x46\x7e\x60\xcc\xa9\x57\x6f\xea\xc9\xdc\x8f\x2b\xc0\x7f\xfe\x8f\xe5\x62\x6e\xac\x4e\x2d\xde\x3e\xd3\xc3\xf4\xab\x43\xd3\xc3\x5f\x61\xaa\xdd\xa1\xc4\x53\x31\x61\xf9\x58\x65\xe0\x86\xff\x0e\x1d\x25\x65\xf4\x16\x77\x3b\xfe\xda\x2f\x5b\xb2\x51\xc9\x21\xae\x33\xc4\x8d\xcf\xb4\xec\x81\x90\x88\x7a\x35\x41\x60\xc7\x7e\x54\x04\x45\x1d\x8e\x89\xd1\x22\xcd\x72\xed\x57\x81\xf5\x6b\x1f\x2f\x71\x7d\x71\x06\xdb\xa1\xfa\x51\xb2\xc7\xd1\xd9\x69\xe3\xaf\x83\x5f\x68\xc4\x77\x2e\x3f\x7c\x6b\xab\x5a\xc9\xc6\x71\x57\xaf\x0a\x2c\xb9\x67\x5d\x5a\xe7\x9d\x6a\xf2\x5a\x1d\xb4\xcf\xda\x76\x4c\xb6\xa8\xab\x47\x3d\x47\x34\xbd\x5b\x27\x24\x4c\xd9\x23\x4a\x16\x9c\xb6\x85\x10\x1f\x2a\x1f\xaf\x02\x78\x03\xf8\x87\x4f\x37\x34\x5f\x23\x8e\x2b\x02\x96\xee\x9b\xfb\x56\x1c\xbb\x7a\xf5\x86\xaf\x9e\xb4\x0e\xed\xe6\x6c\x5e\xd4\xb5\x70\x72\x34\x8f\x6a\x79\x25\xb5\x89\xb7\xf8\x73\x34\x69\x08\xf6\x6b\x7d\xf3\xe4\x36\x00\xf0\xbc\xdb\x26\xd8\x34\x82\xa4\xb4\xe7\xf1\x74\xc6\x99\x06\xa0\x9c\x7b\xd1\x6c\x5c\x4d\x60\xc0\xf8\xd3\x55\xab\x9d\xe1\x14\xae\xc9\xf8\x1a\x1e\x61\x26\x79\x4e\xbb\xe8\xb3\xb9\xcb\xad\x09\x4b\xa3\xff\x36\xbe\x02\x81\xa1\xa9\xcb\x5e\x69\x9d\x8e\xdc\x83\x3d\xd2\xbd\xcf\xe4\xa0\xd4\xfa\x1f\x9f\xa7\xa0\x35\x1a\x98\x76\xb9\x17\xb3\xce\x45\xe2\x68\x08\xe9\x71\x17\x9d\x51\xae\x2e\x72\x66\x0a\xaa\x07\x97\x28\x1c\xe7\xcb\x80\xf4\x99\x4c\x02\xf3\xd9\x98\x10\x24\x47\xdb\x30\xc7\x84\x7b\x6e\xbb\xe5\x23\x67\x02\x91\xcb\x80\xb4\xc9\xde\x59\x93\x46\x7b\x56\x51\xfe\x3b\x61\x34\xc2\x30\xca\xc3\x06\x64\x90\xd3\x71\x1f\xb6\x69\x0c\x95\x58\x71\xe8\x54\xb6\x1b\xfc\x1d\x3c\x6c\xe6\xae\x53\x40\xc3\x9a\x1d\x8b\x2b\xc7\xb9\x2c\x02\x75\xd3\x28\x68\x71\x02\x9c\x73\x12\xf9\xc7\x39\xdb\xab\x4a\x03\x3e\xe8\xf6\xed\xac\xcb\x25\xc7\x44\x34\xbe\x75\x14\x06\xbf\x4a\x24\xd2\x7c\xf9\x3a\x3e\xfb\xa0\x4d\x6f\x3b\xba\xc7\x4c\x0c\xc9\x4c\xfc\x60\x62\xd3\x47\xb2\x6e\xdb\x88\x3c\xcf\x68\x03\x5a\xf4\x6f\x3b\xa9\x54\xd9\x3e\xce\xf5\xaa\xba\xc7\xee\x29\xef\xde\x64\x98\xc6\x3c\x62\x13\x81\xb2\x37\xab\xa8\xfb\x9e\x46\x6d\x04\x66\x45\x08\x17\x67\x27\x55\x66\xdb\x8d\x84\x81\xce\x2c\xcb\x30\xd1\x9f\xac\x8d\xae\x26\x2e\x11\xa5\x5f\x70\xda\x32\x09\x8a\xa3\xf7\x26\xdf\xeb\x06\x3c\x0d\x27\x6a\xc2\xb3\xe5\x1a\x96\xc5\x1e\x1b\xce\x75\x73\x01\x43\x13\xc2\x6b\xfb\x51\xfb\x5b\xfa\x98\x1e\x5e\x43\x1e\x96\xbf\x0f\x3a\x8e\x1e\x5a\xa2\xd7\x94\x3c\xd5\x22\x66\x6c\x39\xb9\xa6\x25\xe3\xae\x51\xa6\x26\x2e\xf6\x2f\x78\xbb\xea\x30\x89\xdf\xef\xdb\x2e\xda\xbc\x39\x2f\x4c\x84\x9c\x27\x85\x22\xd8\xd5\x62\xa0\x04\x5c\x31\xc7\x78\x67\xa8\xe4\xfb\x4a\xa4\x7f\xf5\x8d\x48\xb3\x0a\xd0\xf6\x71\x12\x0c\xbd\x0b\xf3\x38\xf9\xb7\xe1\x61\x4f\xf2\xff\xd1\xf5\xf3\x86\xce\xa4\x57\xa0\x81\xa8\x2f\xf5\xde\x61\xc0\x2f\x9b\xf9\x72\x74\x91\xa9\xea\xae\x71\x56\xde\xd2\xde\x25\x20\xd2\xe2\x9d\xfd\x4d\x70\x28\xfa\x6c\x5b\xc1\xd5\x76\xb2\xb1\x25\x60\xeb\xe8\x2c\x76\x94\xa1\xe9\x64\x86\xca\xde\x26\xce\x3f\xe7\x1c\xec\xee\x50\xbd\x00\x8a\xb2\x0d\x45\xe0\xc8\x71\x43\x2f\x3f\x21\x4f\x5d\xf5\x99\x21\x33\x1d\x8e\xc7\xbf\xdd\xaf\xf6\x43\xd9\x28\xfc\x9d\x86\xad\x0a\x6b\xda\x36\xf8\x47\x86\x7a\x96\x89\x41\xd2\x7c\x32\xc5\x99\xe7\x2f\xfd\xf2\xaf\xad\x7d\xc2\x96\x07\x84\x67\xf2\x1b\x04\x6d\x7e\x8b\xf6\x37\xc4\xd4\xab\x4a\x8b\x35\xa4\x18\x7a\x6d\xb4\xe6\x1a\x8d\x1e\xb7\x51\xef\x82\xe4\xb0\xca\x55\x2d\xd9\x5a\xab\x2e\x65\xfd\x9a\xe5\x74\xf4\x84\xcf\xf6\x41\xa9\x83\x7e\xc4\x88\xf5\x40\xfc\x47\x73\xc3\xf0\x27\xd0\x01\x9a\x51\x40\xd0\xef\x9a\x40\xf6\x35\x35\xe1\xf4\x25\x89\xd5\x46\xbe\x4a\x93\xe2\xb0\x61\xfe\x76\x86\xf7\x68\xc7\xc3\x86\x67\xcf\xcb\xf6\xa1\xac\x09\xc4\xa7\x65\x69\xd6\x85\x4c\xcf\xad\x9b\x07\x8b\x24\x4f\xd6\x9c\xcf\xdc\xd1\x10\x24\x28\x3f\xa6\xa9\xf4\x88\x01\x2e\x04\x7a\xd8\xd0\x45\xc6\x0a\x28\x45\x07\xe3\x22\x06\x78\x20\xc5\x8d\x79\x08\x11\x23\xf9\xd2\x41\xf5\x4a\x79\xde\xf9\xd1\x26\xc1\x05\x5f\x75\xe6\x29\x13\xf6\x3b\x19\xe3\x1e\xda\xfd\x89\xd5\x76\x94\x28\x7c\x77\x67\xe6\x29\xeb\xc9\xa5\x39\xb7\xf5\xab\x09\x4e\x34\xf6\x48\x3d\xf7\xd4\xea\x28\x2f\x61\x10\x57\x06\xf9\x24\x59\x5f\xff\x19\xb4\x64\x23\x69\xb0\x54\xd7\xa5\x4c\x83\xb1\x66\x99\x6d\xe9\xb9\x99\xb3\xb4\x05\x35\x34\xea\x9e\x54\x5f\x5f\xdb\x78\x5b\xfc\xb9\x74\x8c\x61\xf6\x6f\x64\xdf\x85\xcd\x56\x17\x8f\x36\x9b\xdf\x0a\x05\x2c\x85\x04\x87\xc0\x37\x0b\xfa\xaf\xdb\xf3\xf5\x7f\xd6\xf1\x48\x68\xf2\x4d\x59\x98\x49\x45\x36\x97\x94\xcf\x4a\x66\x30\x84\x02\xca\xf9\xa1\xb9\x49\x23\xcd\xf3\x56\x2e\x41\x8b\x1b\x94\x38\x7e\x2d\x35\xdb\x46\x62\x30\x15\xa5\xa2\x68\x05\x69\xcf\x87\x60\x2b\xb0\xbe\xf1\x7f\x1d\x20\x85\xb9\xa7\x76\x8f\x12\xb5\xa5\x8a\xaa\x38\x98\x25\x29\x67\xe3\xf1\x1b\xf7\xec\x19\x1b\x42\x29\x60\xad\x47\xbb\x1a\x85\x17\x65\xd6\xfe\x99\x1e\x17\x82\x96\x14\x4f\xe6\xee\x49\xea\x3d\xdd\x3e\xd3\x45\x73\xea\x92\x13\x89\x91\x4f\x08\x47\xd3\x0d\xec\x32\xd8\x4c\xc6\x29\xe7\x0e\xe7\xa2\xb8\x6a\xc6\x35\x8b\x34\x88\x18\x31\x93\x52\x88\x2d\x21\xfb\x9e\xfd\x6a\x29\x9a\x29\xa0\xb5\x6f\x30\xda\xea\x7a\xf4\x29\x30\x5f\x97\xeb\x7c\x31\xa0\xe4\x9b\xde\x05\x6a\x9f\xb1\x26\x13\xce\x97\x9f\x4e\x2b\x89\x38\x8e\x58\xb5\x11\x6b\xbb\x9b\xa7\x0e\xb9\xd4\xb0\x4d\xbd\x08\xab\x67\x39\x9b\x34\x18\xe4\xeb\xf4\x38\xf1\x5c\xb8\x6a\x25\x0b\xe1\x38\x3e\xfb\x45\x9b\x6a\xff\x0e\x3a\x11\x84\x6a\xda\xcd\xc7\x98\xaa\xd6\xea\xd5\x49\x19\x23\x30\xba\x70\xc4\x9d\xfb\xfc\xea\x4a\x36\x30\xca\x8c\xc4\x82\xce\x27\xba\xd8\xfd\x3b\x3c\xcd\xbe\x41\xf7\xa1\x3c\x43\x9a\xdb\xff\x08\x3d\x18\xd3\xdf\xd8\xb1\xf7\x5c\x6b\xd0\x36\xba\xd7\xa2\x9f\x5f\x43\x19\x19\x7f\x77\x0e\xb2\xda\x41\xba\xf8\x4b\xd0\x9b\x16\xfc\xab\xf0\x10\x3b\x99\x86\x48\xe7\xa4\x43\xae\x45\x40\x36\x8e\xee\x4c\x72\x77\xb1\xfc\xa0\xfa\x58\xf6\x6d\x12\x33\xff\x74\x4e\xcf\x53\x60\xe2\x8e\xfd\x49\xbf\x3b\x73\x3f\x06\x95\xfe\x96\xe5\xaa\xeb\x28\xad\xa0\x1b\xe8\xac\xe2\xfa\x4b\x50\x0b\xbd\xd1\xe4\x83\x7b\x40\xc3\xb9\x99\x1e\x69\x2a\x5e\x46\x96\x14\x96\xaf\x85\x1f\x8e\xec\xef\x2a\x9b\xeb\xfd\x5c\x1c\x7f\x79\x05\x51\xab\x73\x5d\x76\xa6\xa6\xc7\xce\x71\x20\xc1\xdb\xc7\x14\xa3\x9a\x6c\xf1\xdd\xae\x6d\xe8\xcc\x94\x96\x79\xb2\x99\x74\x68\xce\x05\x39\xb7\x24\x51\x66\xb1\x3c\xa7\xde\xbd\xd0\x18\x65\xc4\x29\x48\x35\xa7\x5f\xe6\x90\xfd\x6e\x62\x64\x5d\x2a\x69\xe3\x20\x38\x8b\x56\x94\x82\xfa\x9f\x4a\x94\x06\x7a\x04\x46\x19\x86\x3a\x35\x65\x49\xc6\xb4\xb8\xff\xfb\xfc\x9d\xba\xa9\xdf\xea\x2a\x57\x82\x1c\x9c\x55\x13\x9d\x3e\xb8\x3c\x9c\x95\x8a\x50\xf2\x8f\x2c\x8c\xf9\x23\xb3\x2e\x0d\xdc\x18\x54\x77\xeb\xd4\x92\xdf\xb2\xca\xd2\x16\xd9\x78\xe9\xf1\xd4\xe2\xea\xd1\xb0\xd4\x90\x6c\x02\x94\xe1\x7c\x84\xd8\xf3\x1d\x41\x63\xb4\x2a\x38\x2a\x3f\x4d\xf4\x50\x0e\x43\x70\xd6\x6c\xb3\x89\x96\x5a\x01\x32\x21\xb4\xb0\x75\xe4\x1d\x49\xff\x29\x4c\xa9\xe1\x95\x74\x51\x4d\x24\xff\x42\x7e\x5f\x1c\xcf\x00\x61\x2d\xc7\xdc\x09\xfb\x49\xe7\x9b\xca\x72\x98\xdd\xec\xcf\x75\x28\xeb\x27\x08\x30\x8d\x6b\x7f\xda\x8a\x6b\xd1\xde\x41\x04\x6b\xb0\xb9\x69\x44\x21\x92\x72\x98\xe9\x88\x0a\x45\x04\x21\x80\xe3\xfe\x60\x81\x34\xfb\x39\x91\x58\x9a\x15\xc2\x04\x65\x0c\x37\x84\x11\x56\x99\xee\x63\xf5\x21\x27\x64\x91\x3a\xd7\x8d\x29\x88\xae\xa4\x4e\xa4\x06\xa5\x86\xf9\xdf\x47\x78\x19\x0d\x9b\xba\xaa\x81\x83\x94\xac\x55\x55\x48\x06\xca\x48\x18\xc9\x08\x36\xe6\x9d\xb8\xb8\x9f\x32\xaa\xa1\xda\x7f\x68\x26\xca\x48\x09\x09\x25\x14\x69\x59\x85\x1c\x9c\x49\x53\x92\x43\xaa\x09\xee\x06\xc6\x76\x34\xf1\x4f\x11\x39\xe3\x06\xea\x0e\x9c\xf4\x22\x72\x71\xed\xe8\x68\x8c\xff\xba\xd2\x34\x35\x52\xf6\x36\x86\x2c\x0e\x4b\x3a\x69\x1a\xd3\x08\x5a\x84\xd6\x10\x8a\x2c\x8e\x09\xac\x28\x9d\x71\x2c\xbc\xb4\xb4\x94\x4c\x08\x0a\x2b\x8e\x09\xb4\xe8\xb4\x51\x14\x2e\x02\x73\x28\xa9\x05\xd3\x08\x42\x44\xc6\xe0\xff\x12\x61\x0d\x25\xb4\x51\xcc\x85\x53\xa0\x48\x89\x98\xfe\x85\x54\xfc\x2c\x22\x8b\x8a\x26\x11\xf3\x11\x2d\xe1\xfc\x2f\xd0\x84\x30\x41\x92\x76\xe1\x17\x75\xff\xdf\x50\x46\x22\x27\x1c\x05\x8c\xa0\xfe\xa9\x8a\x42\xe7\x53\x3d\xf2\x93\x01\x72\xb0\xc8\x55\x16\x85\xac\x8b\xb4\x08\x5f\x5d\x58\x0d\x8a\xb4\x08\xff\x7f\xf8\xff\x0b\xcc\xd4\x3f\xff\x40\x46\x88\xfd\x10\x25\x0b\x1e\x2c\x6a\x97\x51\xc7\xdc\x6a\x61\x63\x2e\xb3\x1d\xcb\x24\xeb\xa5\x5e\xcc\xe6\x21\x4a\xa1\x44\xd0\xcf\x66\xd1\x4a\x35\x11\x81\x3b\x61\x1d\x95\x2d\x03\x3a\x46\x7f\xfd\xff\xc2\x82\xba\x33\xad\x54\xdd\x27\xbc\x7a\xcc\x5d\x7f\xd1\x5d\x7b\xcd\xa7\xb2\xfa\x51\x45\x33\xb3\xab\xee\xdc\x47\x64\x2d\xf4\x55\xe3\xcc\x47\x66\x6d\xa9\x2b\x6f\xe1\xc9\x4e\x45\xd1\x7a\x97\x7a\x86\xb7\xd4\xbb\x9c\xed\x26\xe5\x24\x77\xb1\x47\x35\xcb\x53\xe6\x41\xe1\xff\x88\x9a\x30\x33\x8b\x2d\x27\xb9\xab\x3d\x4b\x59\x9e\x3a\x0f\x0a\xb6\xbb\xd6\x33\xbc\xb5\xde\xe5\xec\x37\xff\x5b\xac\x36\xb5\x95\x1e\x5f\x5d\x8c\x3d\xc9\x5d\xe8\x61\xcd\xd2\x94\x5c\x4f\x8a\x6f\x28\xc5\x9d\xe1\x2d\xf6\xb6\x64\xbb\xf9\x9f\xd5\x53\xe2\x61\xd6\x6a\x57\x7b\x86\xb7\xda\xdb\x92\xfd\xa6\xe6\x24\x77\xa5\xa7\x39\xcb\x53\xe3\x61\x36\x5a\x95\x92\xfd\xac\x86\x32\x77\xa5\xa4\x39\xcb\x4d\x23\x79\xd6\x66\x71\x63\xe3\x1b\xbc\x0b\x16\x26\x16\x0c\x0c\xec\xbf\x05\x00\x00\xff\xff\x18\x33\x7b\xe0\xe8\x7e\x01\x00")
+
+func uiAppLibFontAwesome470FontsFontawesomeWebfontWoffBytes() ([]byte, error) {
+ return bindataRead(
+ _uiAppLibFontAwesome470FontsFontawesomeWebfontWoff,
+ "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.woff",
+ )
+}
+
+func uiAppLibFontAwesome470FontsFontawesomeWebfontWoff() (*asset, error) {
+ bytes, err := uiAppLibFontAwesome470FontsFontawesomeWebfontWoffBytes()
+ if err != nil {
+ return nil, err
+ }
+
+ info := bindataFileInfo{name: "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.woff", size: 98024, mode: os.FileMode(420), modTime: time.Unix(1, 0)}
+ a := &asset{bytes: bytes, info: info}
+ return a, nil
+}
+
+var _uiAppLibFontAwesome470FontsFontawesomeWebfontWoff2 = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x00\x12\x40\xed\xbf\x77\x4f\x46\x32\x00\x01\x00\x00\x00\x01\x2d\x68\x00\x0d\x00\x00\x00\x02\x86\x98\x00\x01\x2d\x0e\x00\x04\x01\xcb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3f\x46\x46\x54\x4d\x1c\x1a\x20\x06\x60\x00\x85\x72\x11\x08\x0a\x89\x99\x28\x87\xb6\x58\x01\x36\x02\x24\x03\x95\x70\x0b\x96\x10\x00\x04\x20\x05\x89\x06\x07\xb4\x75\x5b\x52\x09\x72\x47\x61\xf7\x91\x84\x2a\xba\x0d\x81\x27\xed\x3d\xeb\x3a\xb5\x1a\x26\xd3\xcd\x3d\x72\xb7\x2a\x0a\x02\x19\xe5\x1a\xf1\xf6\x5d\x04\x74\x07\xdc\x45\xaa\x6e\xa3\xb2\xff\xff\xff\xff\xe4\xa4\x31\x46\xdb\x0e\xdc\x40\xe0\xd5\xf4\xfb\x7c\xad\x8a\x14\x08\x66\x93\x6d\x92\x60\x9b\x24\xd8\x91\xa1\x40\x64\x5b\x42\x51\x11\x24\x28\x5b\x55\x3c\x2b\x28\xad\xb8\x40\x50\xd0\x35\x1e\xe4\x60\x81\xb0\x0e\xda\x3e\xf6\x50\x10\x1a\x3b\xe1\x28\x91\xd1\x31\xb3\xfd\x6c\xdb\xfe\x68\xd4\xa8\xa2\xc2\x29\x9f\xdc\x59\x79\x94\xf2\x4a\x69\xe9\xeb\x17\xad\x85\xce\x7c\x25\xdb\x81\xb7\x5e\xac\x14\x47\x82\xa2\x33\xb8\x12\x6e\x9e\x95\xe8\xba\xda\x95\xdc\x0a\xc4\xcd\x90\x44\x8a\x9e\x70\x5c\x59\x72\x20\x94\x4c\xdf\x50\xf4\x0e\x8d\x1b\x83\x74\xa5\x29\xcb\x11\x98\xef\x13\xa7\x36\x52\xc2\x5e\x22\x53\x0b\x4c\x7e\xf1\x59\x52\xd7\x43\x58\x52\x15\x09\x8a\x34\x81\x8e\xe6\x46\xfa\x79\x5c\x5b\xbf\xe8\x37\x6e\xa1\xe2\xae\x7c\x1d\x73\xe0\xbb\x8c\x71\x1e\xa3\x4d\xbb\x8e\x25\x4b\xc9\xff\x17\x2e\xdb\xba\x0e\x2c\x0b\xfa\x84\xf7\xf8\x4c\xd0\x74\xff\x27\xf6\x10\x90\xc9\x4d\x1d\x2c\x11\x15\x63\xf7\x88\x2b\x62\xfa\xc4\xd7\x87\xe7\x4f\xfd\x73\xf9\x5e\xd8\x24\x85\x86\xd7\x7a\x2e\x07\xf5\x6d\xc5\xa0\x0c\xfc\x68\x26\x67\x62\xde\xf0\xe1\x76\xed\x87\xf3\x01\x0e\xc9\x27\x8a\x0f\x36\xa3\x3a\xb0\xbb\xc3\xf3\x73\xeb\x6d\xa3\x62\x8c\x31\xd8\xa8\x6d\x30\x22\xc7\x82\x1a\xb0\xbf\x2a\x56\x8c\xa8\x8d\x1e\xa3\x63\xa3\x24\x2c\x30\x41\x54\x50\x54\xb4\x31\x12\x03\xfb\xf4\xac\x3c\x0b\xed\x3b\xed\xf3\xd2\x60\x10\xe6\xb6\x27\xf1\x48\x0e\x3f\xf1\x73\xce\xa9\x3a\x91\x0f\x4e\x44\x9f\xa8\xfc\xa9\x10\x49\x11\xa4\x24\x8c\x04\x54\x14\x8b\x5b\x81\x82\x62\x34\x8a\x11\xcd\xfc\x7f\xea\xec\xef\x2c\xaf\xce\xbc\xd7\xef\xbd\xa3\x62\x6c\x36\x91\xba\x0b\x49\x4c\xe9\x69\x7d\xdb\x8c\x26\xe0\x34\xe3\x94\x6d\x2c\x27\xcb\x16\xcb\xf3\x23\xbd\xd7\xa5\xb3\x7f\x52\x77\x01\xa2\x62\x75\xc0\xb6\x2c\x4b\x96\x0b\xc6\x06\x9b\xe2\x76\x8b\x03\xdb\x08\x6d\x5f\x2d\xc0\xc0\xe6\x5c\x48\x8b\x9d\xfb\x8e\x48\x48\xfe\xaa\xf3\x93\xea\x07\xc6\xc2\x3f\x98\x96\xd3\x6d\xf3\x0b\x39\x50\x88\xad\xd8\x29\x39\xe7\x4a\xa8\x86\x24\xc6\xbd\x88\x9c\xe7\xb1\xf4\x38\xf8\xe8\xc7\xda\xce\xce\x7e\xb9\x3b\xc4\x72\x15\x8d\x6e\xbf\x3d\x24\x11\x1a\xb5\x1f\x94\x4e\x64\x64\x6e\x1b\x21\x27\xae\xa6\xf0\xe3\x3b\xb3\xf4\xac\x38\x99\xbc\x27\xd9\x4e\xa6\xed\x1e\x21\x7f\x2d\x18\x06\x4a\x19\xca\xb6\xd3\x2e\xe0\xd8\xfa\x91\xee\x58\xaf\x3d\x0c\x2c\x12\x04\x0e\x90\x9b\x1e\x22\x60\x3a\x18\xa2\xff\x1b\x0f\x09\x09\x20\x7b\x8d\xef\x9e\xdc\xe0\xbc\x12\xcb\x4b\x21\x27\x9f\x00\xa1\x2d\x46\x48\x94\x9c\x09\x89\x23\x24\x7e\x9b\x5a\x5f\x84\xb9\x9d\x10\x12\xb5\x03\x4e\x35\x56\x55\x38\x46\xc8\xaf\x1c\xa2\x8e\x25\x14\x50\xd4\xfb\xdd\xab\xda\xdb\xfb\x06\x08\x0c\x86\x43\x70\x08\x02\x24\x04\x51\x19\xa2\xb4\xbb\xda\x10\x9d\x72\xac\xec\xa2\xca\xbd\x9b\xee\xba\x6b\xbb\x6b\xda\x1b\xa7\x33\xd9\xb7\x13\xd1\x3a\x52\x11\x25\x1e\x10\xb6\x81\x32\x7b\xf4\x87\xde\xa9\xf5\x92\x1d\x68\x25\xbb\x29\x38\xc9\x11\xf6\x00\xf8\xf1\x01\x0f\x18\x0a\x49\x4c\x4b\x90\x36\x76\xf4\x23\xed\xfb\xb3\xee\xfe\x06\x2c\x3b\xd0\xa6\x36\x87\xa0\x4e\x9a\x32\xce\x68\x76\xb7\x0f\x0e\x08\xfe\xef\x7f\xcd\xfe\xeb\x0c\x4f\x4f\x91\xa7\x74\x23\x16\x85\x06\xe2\x78\x54\x89\xef\xaa\x42\x66\x02\x9d\x9e\x84\x71\x5e\x16\x23\x9c\xae\x9f\x96\x3f\x7b\xfe\x35\x62\x8a\x49\xe2\xe0\x25\x2d\x57\x5a\x90\xeb\xb9\x62\xa4\x41\xa3\x13\x0c\x5e\xe4\x31\xcd\xd9\x6e\x35\x19\xf9\xae\xe9\x8a\xd7\xa6\x4e\x51\x9d\x59\x27\xfa\xe6\xdd\xcd\x12\x96\x04\xfc\x91\x53\x04\xdc\x18\x1f\xa6\x21\x74\x22\x20\x06\x60\x62\x33\xe9\xf7\x25\x93\x07\xf4\xef\x33\x35\xbb\x02\x14\xd1\x66\x76\x3b\xab\x9d\xd5\xce\x6c\xce\xac\xee\x39\x9c\x3a\x6a\x67\x66\x3f\x67\x72\x9b\xf5\x70\xff\x78\x9f\x20\x80\x0f\x7c\x12\xfc\x20\x24\x08\x20\x65\x12\x94\x1c\x12\x94\x5a\x14\x28\xc5\x14\x24\x77\x28\x5a\x72\x53\x90\xe8\x76\x2b\x9b\x5a\xd9\x1c\xcf\xd6\x71\xf6\x4d\xa2\xec\x1e\x9b\xee\xcd\xea\xdd\x99\x6d\x3f\x26\x73\x5b\xf6\xe5\x74\x99\x53\x92\x53\x6a\x8e\xa7\x39\x9c\xaf\xe3\xf7\x3f\xad\x7c\xda\xea\x0d\xf1\xf0\xc5\x3e\x47\x0e\xcc\x06\x2c\x10\x62\x44\xd5\xb7\x5e\xa9\xf4\xaa\x5e\xa9\xc7\xdd\x1b\x3a\x6c\x8a\x33\x8e\xbd\x4e\x41\x9a\x60\xab\x35\x0b\x9c\x32\x36\xb3\x01\x4c\xf9\x70\x53\xf2\x09\x41\xdf\xa7\x2f\x55\xeb\x0a\xc2\xd6\x98\xb4\xbc\xb3\xb4\x27\x39\x5c\xb4\xa7\xd5\x86\x74\xb8\x85\x10\xaf\x21\xdf\xf6\xf6\xfa\xb7\x1a\xfd\x1b\x81\x6c\x00\x06\x85\x20\x50\x4d\x52\xb4\x9a\x90\x39\x6e\x80\x0a\xcd\x60\x15\x12\x13\x28\xca\x10\x40\xd2\x20\x48\x79\x29\x4d\xd2\x64\x4d\xca\x0d\x90\x1c\x35\xe9\xd4\xa4\x13\x48\x27\xd2\x91\x9a\x1c\xf2\x6d\x53\x3c\xfa\xe8\xdb\x71\x26\x6b\xbc\x29\x5c\xcf\x7b\x3b\xee\x31\xc5\xc3\x6d\xf9\x07\x9b\x38\xdb\x7b\xe1\x8b\xd5\x58\x84\x31\xdd\x2d\x33\xc7\x9a\x90\x91\x29\x82\x42\x28\x84\x91\x2c\xfb\x25\xf5\x93\x10\xb0\xb6\xb6\x8d\x04\xc4\x0b\x05\x05\xdd\xfd\xdb\x77\x9f\x6f\x7e\xbe\x98\x74\xed\xf0\x48\x57\x38\x6c\x90\xd4\x5a\x11\x09\x72\xa4\xe3\xbf\xff\x3d\x65\xb3\x1a\xec\xdf\x31\x2b\xe6\x07\x05\x2f\xc9\x8e\x31\x57\x3f\xd6\xb0\x72\xee\x12\x0e\x38\x39\x50\x4c\xc6\xd2\x01\x3e\x75\x6f\x39\x20\xc5\x18\x31\x20\x74\xc3\x98\xab\xc3\x75\x63\xa7\x9d\x91\xee\xc4\x40\xb3\xf9\x5d\x4b\x14\x10\x52\xef\x7f\x62\x4e\xff\xbb\x92\x76\xfb\x93\xb4\xd4\x1a\xaa\xa8\x28\xb8\x22\x8a\x83\x79\xeb\xbd\xbb\x7b\x1c\x0c\x63\xae\xff\x8f\xe6\xf3\x73\x63\x7a\xa6\x19\x26\xae\x70\x35\xa7\xe5\x04\xa1\x2c\x6a\xb3\x6e\x20\xa2\x6b\x4e\xc4\x21\x83\x2e\x83\x6e\x5e\xf7\xf8\x55\x75\x1f\x00\x40\x7c\xfc\x18\x3f\x76\xb5\x3e\xf7\x07\xb9\x1d\xb9\xdc\x1c\x91\x72\x18\x55\x61\xdc\x48\x52\x20\x0b\x1a\x8f\x10\xfa\xb9\xd7\xf8\xd5\x91\x00\x93\xf3\x49\x0d\x44\x89\xdf\xcb\x8b\x51\xbf\xbd\x7e\x70\xe9\x0a\x80\xdc\x8d\x3b\x3b\xb8\x6e\xf9\xf9\x8d\x4c\x18\x17\x24\xa1\x74\xf9\x09\x3a\x09\x68\x46\x43\x59\xa1\xed\xde\x54\x4f\xa0\x46\x4e\x1d\x4e\x7e\x7d\x17\xf1\x31\x22\x60\xb3\xa8\xfc\x9f\xd8\x61\xcf\x07\xcb\x28\xcd\x3f\x48\x20\x11\x97\x96\x87\x1f\xc4\x5c\x96\xcd\xe5\x75\xca\x30\x13\x4c\xd4\xb5\xf5\xf1\x27\xb5\xed\xba\xbd\xbe\xcd\x94\x50\x62\x6e\x6d\x4f\xbf\x98\xeb\xb6\xdd\xfd\x8d\xbf\x02\x18\x4a\x6c\x8b\x3f\x02\x01\x08\x9e\xe5\x73\xab\xe7\x05\x88\x30\x2c\x0e\x38\x8c\x78\xc9\x42\xf2\xfa\xf6\xbe\x42\x19\xc7\xe5\x91\x46\x89\x10\x14\x9f\x5f\xdf\x1b\x52\x69\x5a\x1d\xf8\xff\xb7\xd4\x7e\x65\x23\x15\x6a\xb0\x11\xb1\x77\xfd\x68\x4f\x63\x2a\x26\x46\x36\x0c\xac\x59\x71\xc1\x92\x05\x7b\x89\x7d\x3f\xc9\xf3\x3e\xf7\x75\x1e\xfb\xb6\x2e\xf3\x34\x0e\xce\x68\x25\x05\x67\x94\x60\x04\xa7\x26\xd7\xe7\x20\xb8\xcb\x12\x29\xa9\xac\x52\x35\x18\xe5\x48\x8c\x7d\xb1\xa7\xff\xcb\xa4\xb0\x6b\xdc\xa9\xdb\x1c\x90\x27\x4a\x99\xde\x4f\xbf\x00\x49\x88\xdb\x13\xb6\x9d\x5f\xef\xb3\x7f\x05\x91\x71\x4f\x62\x27\xd6\x48\xc7\x9f\x00\x42\x59\x45\x4d\xa3\x03\x1c\x36\xc8\x76\x84\x81\x35\xaa\x10\x4e\x4a\x0d\xe5\x15\x01\x4f\x88\x4e\x07\x1a\x46\x0b\x4e\x78\x28\x31\x92\x3a\x01\x5c\xba\xdf\xab\x43\xe0\x6b\x8e\x63\xa0\x62\x38\x05\x51\xf4\x09\x13\x64\xe1\x18\x5b\x4c\x14\x28\x65\x6c\x1c\x2b\x32\x75\x2d\xee\xd0\x61\xd6\x98\x64\xa2\x8e\x35\x3b\xa2\x4e\x24\xd4\xf6\x22\xa2\x48\xaa\x8f\x10\xab\x53\x46\xba\x6f\xeb\x32\x69\xa8\x22\x8a\xd9\x5c\xb3\x68\x04\x37\x49\x8c\xf6\xa0\x3c\x53\x43\x4f\x02\xad\x19\xb8\x96\xc8\x90\x48\xa0\x1e\xe2\x45\x77\x21\x01\x2e\x1f\xd7\xe9\xfd\x21\x42\x53\x12\x43\xaa\x67\x1e\xc4\x9d\x89\x63\xe3\x0e\xb9\xe4\x73\x2a\xd5\xa7\x73\x89\x28\x35\x6d\x94\x3d\x71\xc6\xca\x8a\x65\xa2\xfb\xf1\x59\x91\x0b\x24\xeb\x5c\x3e\x10\x66\x4e\x38\x80\x71\x97\x8c\x78\xea\x23\x76\x0a\xa5\x36\x75\x6d\xef\x09\xe0\x19\x9d\xb0\x60\xdb\x4e\x4d\x2d\x4a\x00\x5c\xf4\x10\x46\xb7\xc7\x72\xe9\x44\x02\x80\x1e\xb5\x5a\xd3\x30\x93\x07\x23\x27\xea\xa5\x88\x6e\xec\x11\xd2\x47\x6a\x4c\x82\xda\x86\x58\x14\x1b\xca\x8c\xa2\x41\xaa\x9d\xf1\x67\x59\x73\x99\x2a\xb2\x59\xca\xdc\x07\xc7\x5e\xd9\xb5\x98\x3b\x22\xd8\x1d\x24\x68\x62\x7f\x3d\xb9\x16\x19\xcf\x9b\x13\x98\x30\xde\x76\x48\x3c\x97\x56\x76\x7f\x81\x63\x9b\x5f\x00\x5c\x59\x8a\x03\xec\xa3\xe8\x77\x3b\x64\x42\x16\x02\x83\x8b\x03\x4e\x83\x84\x33\x1b\x21\x24\xce\xe7\xe7\xb4\xe7\xe2\xde\x49\x7c\x50\x98\x20\x7e\x13\x26\x13\xe4\x03\x64\xc5\x2e\xc8\x03\x1b\xd4\xb0\xe9\x02\x2d\x61\x07\xf3\xfa\x61\x19\x09\x2b\x2b\xc2\x13\x92\x39\xba\x2e\x6d\x52\xf8\xe9\x34\xe3\x63\x79\xaf\x9e\xb9\x23\x8b\x55\xd5\xc2\x46\x57\xee\x08\x75\xbd\x0d\xdc\x09\x17\x69\x2f\xf0\x9c\xaf\x94\x66\x7e\x80\x34\xdd\xf0\x6c\x83\xeb\x0e\x58\x53\xf4\x39\xc3\x84\x1b\xf7\x31\x45\x9d\xf0\xbd\x33\x40\x90\xfd\xda\x6b\x13\x88\xdc\x15\x40\x17\x27\x23\xa3\xbc\xb6\x63\xac\xbd\xd9\x6e\xea\xa9\x20\xba\xf1\x15\xef\x53\x5f\x3b\xac\x25\xfb\xee\x49\x8a\xd0\xc1\x2b\xbb\xf8\x2e\xf3\x4c\x1a\xd8\x43\x02\x78\xb1\xeb\xee\x1e\x1e\xbe\xfa\xea\x86\xb1\x77\x09\xda\xcd\x56\xdb\x82\x80\x81\xba\xa8\xe1\xa4\xc0\xc3\xf9\x45\x78\x66\x7e\x48\x60\xbd\xe9\x30\x1f\xbc\x21\x64\x94\xe8\x40\x51\x7b\x4f\x68\x31\x89\x17\x17\xb1\x48\xc1\xb6\x46\xc3\xab\xd5\x7a\x73\x1a\x8d\x37\xf3\xdd\x89\xb6\xb3\xc6\x9c\x74\x0f\x72\x76\xcc\xe8\xa9\xd2\x6b\x9d\xbb\x86\x68\x65\x53\x33\xb7\xdb\x87\x76\x99\x39\x84\x71\x7c\xab\x4f\x82\xef\x97\x4b\x29\x95\x55\x5c\xf2\x96\x41\xd2\x25\xa3\xb9\xbb\x02\xc4\x6f\x1e\x7b\x6c\x3c\x86\xdb\x4b\xb8\xff\xba\x9d\xcd\x8e\xa2\xa4\x8e\x69\xb3\x8f\xf1\x48\xeb\x47\x80\x49\x85\x7a\x9d\x3d\x36\x9a\x57\x57\x6f\x30\xeb\xd9\x0b\x7c\x15\xde\x25\x41\xf7\x1a\x6a\x64\x44\x29\x21\x0d\x80\xa9\x70\x77\xae\xc8\xee\x5f\x82\xb3\xeb\x3b\xb8\xf1\xa6\xdb\x63\x97\x44\x23\xe9\xff\xcb\x81\x4d\x90\xc0\xde\x4e\x7a\x9c\xf2\x05\xb7\x04\x70\xb0\x5e\x8f\x43\x44\x78\xde\xc2\x78\x6a\x29\x84\x35\x4f\xc8\x39\xfb\x0d\xa1\x60\xd1\xd2\x45\x44\x58\xee\x78\xf1\x8d\x20\xdd\x92\x47\x55\xc8\xc0\xed\xcb\xaf\x0e\xc4\x99\xaa\x04\xa9\xef\xd6\xda\x89\x9c\x2e\x25\x0d\xb7\xbf\xb6\xce\x88\xb1\x7e\x0c\xe3\xf1\xfa\x3d\xff\x08\x1a\x16\x43\x13\x6f\xa6\x29\x0d\x46\x84\x37\xf3\xca\xe7\x24\x5a\xa4\xfd\x28\xb7\x67\xc1\xeb\x6f\x42\xad\xa7\x0d\xdb\xc6\x9c\xc0\x40\xde\xe5\x26\xf2\xc3\xda\x65\xee\x7b\x06\xea\xe2\xe5\x8e\xa3\xa0\x08\x6c\xa0\xb0\x66\x8a\x5f\xc6\x52\x78\x99\x4e\x5b\xa7\x5d\x0c\xae\x9b\x07\x38\x60\x2d\x33\x99\x73\xb4\xa6\xc1\x92\x7b\x7f\x50\x6a\x01\xde\x19\xb8\x57\x75\x63\x39\xef\x85\xb8\xae\xa9\x84\x1b\x5b\x3e\x1d\xea\x2d\x9f\x2e\x44\xa2\xdc\x8e\x59\xfa\x1f\xf7\x9b\x15\x0f\x80\x1e\x64\x87\x0c\xcf\xc2\xd8\x07\xa2\xb2\x2b\x18\x5e\x7b\x93\xae\xb9\x43\xee\xf7\x89\xb1\x6d\xe0\xc4\xd9\xf0\x2c\xa6\xb1\x40\x4e\x3c\xb2\x90\x1d\xda\xd9\xd0\xf8\xf2\x89\xaf\x1f\x7f\x0e\x2e\x8d\x94\x56\xf1\xe6\x4d\xf0\xda\x11\x53\xec\x2b\xd3\x5c\x44\x9e\x2b\xa2\xda\x52\xa2\x7c\xd1\x36\xb5\x0b\xe2\x27\x71\x5c\x54\xe0\xdd\x02\xa6\x95\xf3\x1c\x1e\x39\x87\x44\x84\x06\x58\x3c\x7f\x24\xed\x70\x89\x80\xde\x07\x22\xbb\xe9\x85\xa6\x92\xfc\x24\x9b\xd2\xb7\x0b\xde\x2c\xf9\x70\x1f\xbb\x73\xf9\xa5\x54\xd3\xce\x1a\xdd\xfe\xaf\x62\xbb\xff\xd4\x4e\x6b\x49\x91\x1e\x5f\xe6\xa1\x60\xd5\xe6\x0a\x46\xe8\x88\x1f\xea\x57\x93\x9f\x56\xff\x94\x25\xd9\xd1\x77\x08\xad\x7e\xa9\xa4\xc4\x44\xd4\x90\xd9\xc2\xcb\xdd\x2a\xf3\xb3\x78\x69\xf2\x1e\xb8\x79\x5b\x72\x5a\xaa\x87\x00\x99\x5b\x53\x25\xb4\x47\x9b\xdc\x18\x73\x60\x46\x3c\xe3\x85\xa3\x85\xb3\xac\x20\xa2\xc1\x56\x8b\x2b\xfe\xf3\x21\x2b\xad\x96\xf7\xf5\x8a\xb8\xd8\x8d\x8b\x39\x79\x9f\x6b\xc5\xc1\x66\x62\x91\x38\x32\xde\x06\x73\xde\x7d\x6c\x3b\x5b\x29\x65\x24\xc4\xf8\x89\x54\x9d\x86\x96\x6b\xad\x83\x92\xe0\x29\x9a\x76\x8f\xb6\xa9\x39\xac\x01\x84\xe3\x1b\xa7\x7b\xd3\x75\x13\xf2\x75\x8f\x74\x8f\xc8\xde\xb3\x40\x45\xe3\xf4\x3e\x7c\x43\xf6\xda\x3c\x5c\x34\x25\x08\x97\x52\x76\xe1\x0c\xa5\xb6\xe9\xe5\xc4\xe8\xaa\xda\xf4\x40\xd7\xba\x43\xcc\x38\x5c\x91\xf8\x7e\x29\x14\x23\x6b\x7c\xbe\xb9\x2e\x61\xeb\x6f\xaa\xba\xda\x03\xba\x30\x30\x47\x94\x71\x30\x1d\x14\x25\xf1\xfc\xf0\x13\xa1\x99\x68\x70\x8b\xa9\xba\x0d\x4c\xff\x9c\xde\x22\x8c\x2b\x3e\x8e\xec\xe6\xb5\x25\xaa\x0b\x5e\x4d\xcb\x8a\x98\x4e\x9a\x73\xd3\xc8\x06\x71\x8e\xb4\x3d\x95\x12\xb0\x0f\xbe\xee\xe5\xe4\xa6\x86\xb0\x4b\x11\x34\x72\xe7\x2d\x2a\xef\xe7\x25\xe8\xda\x68\x23\xd7\x25\x3b\x70\x50\xe9\xa6\x94\x68\xd6\x43\x3d\xf7\xce\xfa\xda\xda\x0d\x97\x1a\xe5\x26\x14\x29\xa9\x62\x61\x84\xc6\x4b\x4c\xf8\x40\xbf\xf9\x9e\xe4\x74\xba\x21\xa2\x7e\x32\xed\x53\x5d\x72\x59\x6c\xba\x5a\x36\xd0\x33\xd1\x9e\x4a\xde\x6f\xb4\x98\x4f\xa3\x56\xf5\x3b\xb9\x68\x26\x67\x4f\x35\x92\x52\x54\x88\x2f\x7d\xf9\xc1\xd2\xc6\x7b\xae\xa5\xf2\x17\x17\x41\x5a\xd2\x26\x87\x19\x53\xf3\xe2\xd9\x74\xd8\xca\xf9\x9c\xcf\x03\x0b\xcd\xaf\x01\xe9\xa2\x50\xea\xeb\x43\xa1\xa4\x14\xa2\x30\x13\x08\xb4\xb6\x44\x2c\xfb\x70\x62\x70\xd0\xb7\xd4\x7a\x29\xa7\x20\x5d\x80\x49\xf7\x3e\x1a\x00\x0e\x51\x5c\x42\x6c\xc1\x22\xba\x97\x5e\x33\x52\x3e\x72\xfd\x2a\xfb\xbb\x04\x43\x3e\xc0\x1e\x1e\x83\xa7\xe1\x17\x78\x50\x55\xba\x7a\x1e\xad\x7d\x59\x11\x3d\x02\x0f\xf5\xcc\x95\x16\xbc\x7d\xf5\xd0\xb6\xc7\x10\x9a\x19\x0a\xe7\x0d\x1c\x36\x2d\x60\x2f\x22\x48\x0b\x0a\x6f\x85\x26\x92\x44\x97\x49\x30\xff\x45\x32\x58\x61\x89\x95\x2d\x1f\xa9\x7b\x0e\x35\xc0\x81\x99\x3c\x0d\x2c\x7d\x94\xd1\x13\x60\x60\x36\xfa\xc7\xed\x18\x90\x6a\x69\xa2\xe9\xd8\x69\x6d\x3c\x55\x75\x6a\x59\xa9\x5a\xfa\x6a\x0e\x42\x5c\x40\x8c\x67\xcb\x33\x45\x6a\x66\x70\x96\xf8\x98\x9f\x3a\xba\xda\xed\xea\x10\x57\xdb\xc7\xae\x9f\xba\xd9\xdf\xb3\x8e\x9c\x94\xce\x70\xa5\xc4\xb3\x33\x61\x6f\xaf\xfb\x11\x81\x31\x88\x64\x61\x8b\xf8\x20\x9c\x03\xb7\xdd\xab\xa5\xfd\x88\x99\x4a\x82\xd7\xb2\x3f\x20\x6a\xce\x71\x37\xae\xbe\x4d\xc3\xe6\xce\x66\x66\x99\x59\xb5\x66\xcb\x1c\xd4\x73\x02\x1e\xb0\x1b\x24\x9b\x9c\x09\x84\x95\x48\xfd\x91\x14\xe6\xac\x6c\xa5\x96\xf5\xb9\xbf\xc0\x88\x97\x28\x25\x2e\x9b\x72\x06\xe3\xd2\x77\x3f\x03\xf2\xbe\x6d\x3d\x7e\x0b\x82\x79\xb2\x63\x59\x91\x62\x67\x29\x3c\xcb\x57\x84\x20\x2f\x56\x78\x16\xda\x6b\xa9\xb4\x92\x24\xe7\xf3\x8f\x0c\x42\xf0\x72\x7e\xf1\x86\x01\xa7\xd3\xf0\x39\x13\xde\x36\x8d\x30\xd1\x26\xfe\x99\x5f\x76\x4d\x00\x59\xc2\x25\x84\x93\xd2\x9d\x7b\xe6\x45\x7f\x89\x36\x3c\xc3\xe9\x95\xc7\xc2\xed\xdb\x25\x8b\x25\xab\x34\xad\x8b\x8e\xdf\xa0\x4f\xde\x40\xef\xf3\x4e\xe1\xf9\x08\xa1\x82\xaa\x22\x5a\xb7\x18\xdf\x4f\x44\x7b\x75\x33\x53\x0f\x8c\xc7\x57\x8b\x4d\xb0\x95\x52\xa7\xed\x33\x73\x3c\xc3\xf5\x19\xa7\x91\xd8\xb3\x0d\xa3\x80\xa6\xf1\xb0\x5c\x49\x0e\x30\x8d\xab\x2e\xa0\xc5\x2d\x32\xdd\xad\xec\xcf\xe3\x84\xad\x3b\xaf\x09\xec\x83\x30\xd5\x0e\xb6\x7d\x4e\xab\x2f\x62\xf5\xf6\x1a\x8e\x4e\x7b\x84\x49\x99\xb3\x7c\x62\x5f\x72\xc4\x65\xf8\x9d\x5f\x70\x53\x69\x83\xe3\xca\x14\x0f\x3e\x12\x27\xdc\x77\xac\x35\xfc\xdb\xfa\x52\x46\x2c\xd1\x87\x88\x25\x1e\x53\x59\x96\x84\xbb\xc6\x57\x68\xa3\x36\x4c\x5f\x69\xec\x83\xa3\x3d\x9a\x9b\xbe\x69\x31\xf1\x33\xfe\x59\x49\x37\x4e\xb8\x43\x70\x8d\x49\xc9\xf0\xc4\x94\xbe\xc3\x12\x28\x0f\xa8\x72\xaf\xbe\xbd\x30\xab\xdd\x7b\x6a\x89\x19\xf7\xba\x85\x72\x8b\x4b\xbc\x9e\x99\xe5\xd0\xa2\x6f\x29\x6c\xd9\xc4\xf4\x87\x33\x6e\x61\xbf\x54\x31\x7f\x5c\xa7\xc3\x49\x19\x45\x28\xe9\x6d\xbd\xf7\xb2\xbd\xdf\x83\x9b\x93\xc2\x44\xf4\x6c\xfa\xac\x7f\x65\xb3\xb3\xc7\xe6\x24\xc3\x85\xdf\x77\x58\x9e\x88\xcc\x55\xac\xfc\x28\x40\x95\x84\xae\xf7\x4d\xf5\x61\x22\x6e\xac\x0e\x2c\xe4\x2a\x76\x47\xb3\x1d\x96\x1c\x89\xcc\xa8\x13\x78\xb9\x8a\xae\x3e\x95\x47\xd9\x0c\x53\x82\x11\x83\x80\xee\xbd\x67\xc0\xcc\x89\x22\x94\x51\xcb\x76\xa4\x62\x14\x30\x2a\x7a\xdb\xc8\x50\x45\xf4\x79\xc1\xc9\x89\x8c\x3f\x37\xaf\x24\x13\x0b\xc1\x8e\xd8\xf0\x25\x9e\x1d\x89\x47\x87\xd2\xd1\xe4\x70\xc9\x64\x59\xc8\x26\x66\xe2\x07\x21\xed\xfb\xc7\x61\x36\x94\x8e\x7c\xa8\x08\x29\xbf\x0e\x3b\x75\x37\x23\xc2\x33\xc9\x34\x90\x6d\x4a\xc4\xb3\xdb\xf8\x0a\x6f\xf7\xf6\x89\x4f\xf8\x70\xad\xc8\x81\xa2\x76\x38\x6a\xa0\xea\x99\xfc\x78\x28\x4b\xcb\x2f\x5a\xdc\x64\xbb\x03\x8a\x8f\x78\xc9\xc5\x83\xfd\x6d\x37\x56\xd1\x5f\x5c\xa7\x66\xd7\x4c\xe5\x37\x0c\x70\x9b\x58\xf3\x7a\x16\x1e\xec\x85\x48\x37\xbe\x2d\xab\x0e\x96\xb5\x2c\x28\x31\x4b\x48\x62\xad\x65\x90\xa8\x2c\x72\x2d\x19\x1c\xa3\xa0\x11\x70\xa1\x4c\xcb\xef\xc6\xed\xa0\x33\x3d\xe6\x54\x98\x02\xc6\x32\xa9\x74\x91\x32\xd9\xbc\x58\x96\x6b\x3a\xa9\xb4\xb5\xff\x08\x5a\x80\x35\xc0\xcf\x73\x05\x89\x0e\x70\x0e\x88\xd2\x53\x73\x54\xab\xb8\x05\x1a\xd5\xeb\x3a\x2e\x5d\xb5\xb7\x44\x22\x94\x40\xb0\xf5\x2d\xb6\x45\xb7\xcc\x91\x06\x21\x10\x94\x13\x41\x8d\xf0\x91\x32\xba\xc9\xb6\x2d\xf0\x46\x19\x7d\xb1\xcb\x92\x80\x32\x42\xc7\x83\x92\x8d\x51\x1a\x99\xd5\x17\xe0\x05\x29\x74\xc5\xc3\xa7\x7c\xda\x23\x34\x84\x7c\xdc\x5c\xf7\xe3\xa8\x80\xf0\xc8\x60\xb7\x66\x63\x10\x2c\xb6\x9f\x23\xd4\x07\x67\x89\xe9\x31\x3a\xd9\x2d\xd6\x16\xab\xa1\xb9\x74\x79\x17\x20\xdb\x5d\xfb\x87\x98\xe0\xe4\x32\xaf\x5a\x7e\x02\xb1\x84\x00\x2e\x29\xe3\xe9\xae\xf3\xf4\xb3\xd7\x02\xc7\x8c\xe0\xd6\x1e\xb5\xa1\xdc\x25\x52\xa5\x4b\x8d\x98\xab\xbf\x28\x79\x90\x02\x60\x91\x38\x96\xb6\x43\x1a\xd7\xc7\xd6\x8d\xfa\xb7\xcb\xf7\x7a\x93\xba\x1d\x8a\x4b\x2d\x4e\x8e\x0c\x84\xf3\x01\x0e\xf5\x60\x5e\x2b\xa6\xf5\x8b\x9e\x6e\x08\xa2\xa8\x8b\x33\xb9\xdb\xcf\xb4\x18\xfe\x02\xe5\xf4\x80\x9d\x16\x95\x54\x81\xf2\x33\x82\x74\x51\xe1\xd8\xa3\xa9\x06\x08\x34\x3c\x3e\x3a\x4a\x30\xc3\x88\x25\xe5\xdd\x91\x5a\x61\x62\x60\xe8\xbd\x03\xea\x76\xcd\xac\xfc\x86\x61\xf6\x54\x2f\x5a\x01\x02\xfa\x14\x9c\x61\xde\x9d\xc7\xd0\x93\x49\x69\x09\x9b\x57\x31\x90\x16\xfc\xf1\xfd\x83\x5f\xa9\x90\x10\x3e\x29\xc3\xfa\x97\xbe\x48\x22\x94\x8a\xf9\xe3\xe9\x70\x92\xeb\x0b\x83\x7c\x37\x6d\x14\x46\xb5\x5e\x5a\xcf\xcd\x7e\x66\x8b\x11\x17\x30\x4a\xf1\xea\x5e\x00\xc9\x49\x91\x17\xdc\x33\x56\xb9\x21\xe9\x18\xa5\xdc\x7b\xd3\x3c\x65\xcc\x2f\x3d\xce\x70\x60\xda\xd7\x0c\xde\x71\xad\x9e\x00\x38\x5e\xf6\xd4\xd9\xd3\xc1\x4b\x38\xcc\xeb\x4f\xcd\x39\xf6\x77\x30\xd3\xea\x5a\x90\xb4\x7c\x1e\x8a\xdc\x04\x76\x3f\x91\x6e\xc3\x14\x09\xe0\x0c\x33\x97\x81\x66\x81\x21\xfd\xcb\xdf\xb7\xd1\x7e\x95\xfc\x54\x8a\x20\x1f\xa7\xe4\x1d\xfb\xc1\xca\xf2\x20\x4a\xd3\x9b\xa5\xfb\x84\x07\x11\x1c\xdf\x35\xd7\x0b\xc1\x70\xa6\x8f\x14\xba\x56\x09\xbc\xdf\x33\x87\xcb\xab\xb8\xc5\xd7\xf3\x0f\x2e\x3d\xc6\xf1\xcc\xee\x81\x2d\x7d\xa7\xdc\x5b\xce\x67\xe5\x52\xe1\x35\xab\xf3\x9d\xf3\x6e\xec\xa3\x42\x38\xe1\x91\xf7\x83\x99\x33\x2e\xbb\x08\xd2\x38\x14\x09\x59\x67\xa1\x23\x30\xdf\x26\xb8\xbd\xaf\x53\x84\x2f\x2e\x66\x67\x5c\x0a\x1a\x45\xe2\x66\xe7\x7d\x0e\x90\xc8\x2c\x6b\x87\xa2\x94\xe9\x93\x67\xfc\x06\x14\xfb\x24\x03\xb9\x3f\x58\x59\x93\x07\x2a\x8f\xfa\x94\xa9\xba\x11\xbc\x31\xaf\x90\x70\xad\x97\x45\x28\xbf\xd7\xeb\xf2\x52\x53\x92\xa4\x51\xba\x98\x74\x9e\xee\x03\x36\x2c\xa0\x51\xe3\x6a\x5c\x08\xf0\xe3\x3c\x08\x2f\x5d\x4e\xae\x73\xfb\xcd\x1d\xa5\x3b\xcd\x27\x0c\x18\x48\x58\x5d\x8e\x45\x98\x32\x1e\x39\x90\x87\x64\xa6\x6b\x59\xfd\x0d\xd9\x6a\x90\x8e\xc2\x52\x36\xd1\xd4\xed\xf7\x03\x51\x12\x21\x98\xca\x00\xea\xee\xf7\x20\x56\x86\xbb\x99\x0a\x25\x22\x08\x15\x5e\xd0\x60\x97\x4e\x33\x4f\xf2\x8c\xa2\x0f\xfa\x86\x83\xac\x5b\xf1\x1d\x76\x3a\xe0\xca\x84\x3a\xd9\xe8\x5e\xda\x9c\x72\xd7\xbf\xe7\x11\x40\xea\xd2\xec\x0a\x8d\x46\xc5\x5f\xae\xd7\x11\xe5\x01\x08\x4e\x63\xcc\x42\xd2\x17\xf1\xfd\xc3\x38\x70\xa3\x5c\x69\xaf\xa2\xb5\xd7\x37\xcf\xee\x8b\x67\xe5\xad\x03\x2a\xee\x8f\xd1\xcd\xfd\x2c\x83\x43\xab\x9d\x1a\xc2\x0e\xe1\x5b\x87\x36\xb4\x54\x92\x3f\xba\xba\xb5\x16\x85\x25\xf2\x7a\xfb\xc5\x40\x01\x06\x18\x6a\x41\x70\x42\x4e\x35\xf0\x9e\x22\x34\x54\x9e\xa5\xe0\xf4\x22\x96\x7d\x30\x75\x4a\xf4\x87\x8f\x9e\x96\xc8\x9c\x7e\x33\xf6\x1e\xd9\x0e\xd1\x7b\x7d\x02\x75\x57\xf6\x8c\xe0\xee\x4d\x93\x1e\x6a\xfa\x39\xc8\x2d\x82\x5d\x13\xf5\xab\x9d\x11\x99\x27\x6c\x53\xb2\x20\x2f\xf0\x52\x3e\x3c\xa5\x2b\xe7\x4f\x9f\x95\xdb\xd8\x1f\x65\x42\x23\x95\x42\x63\xd2\x1a\xd9\xc0\x02\xe8\x6a\x4c\x5c\x11\x12\xa3\xc4\x2d\xbe\x5a\x68\x95\x5b\xd7\xfa\x49\x3c\x8d\xaa\xfc\x0f\xf1\x84\x18\x71\xa8\x76\xde\x7e\x96\x6b\x5d\x9b\x47\xc3\xce\xd5\x54\x44\xbf\x3f\x53\xa9\xcb\xd9\xd6\x2f\x1a\xc6\x2d\xd4\xd7\x25\xdd\x92\x89\x94\xd9\xe8\x37\x0c\x88\xfe\x77\xa6\x69\x7c\x43\x16\xcb\x49\xa1\xc4\x71\xf1\x77\x63\xa8\x80\x57\x01\x9b\x14\x78\x0c\x9a\xb1\x20\xcf\x0c\x2f\x37\x04\x81\x78\xac\x82\x48\x4f\x2f\xae\xe5\xb5\x1d\xf0\x6f\x5d\x91\x9e\x0f\x94\x47\x5d\x8a\x79\x8f\xdf\x83\xeb\xfc\x87\xfb\x23\x85\x87\x1f\x37\xa9\x8f\x62\xcd\xe3\x24\x93\x74\xc7\x1c\xaa\x52\xdb\x24\x20\x06\xbe\x98\xe9\x7f\x5d\xe3\xb4\x61\x37\x1b\xcd\x46\xa3\xd1\xae\xaf\xb2\x8f\x2c\x6e\x21\x72\xcb\xdf\x49\x7c\x32\xc0\x10\xbc\xe3\xb8\x38\xea\x92\x78\xff\x36\xe7\x99\x67\x53\xa6\x68\xb1\x09\xb2\x93\x52\x5e\x5e\x93\x44\x2e\xf8\x78\x8a\x4d\xd1\x4d\x53\x3f\xe6\xbc\x9e\x27\x47\xfa\x23\xfc\x7e\xe1\x2b\x9d\xac\xba\xc4\xec\x08\x76\x34\x8a\x64\x21\x46\x79\x54\xdc\x39\xf1\x2d\xb2\x66\x56\x61\x37\x68\xfb\x42\xae\xcb\x17\x34\xfe\xab\x9f\x96\xe8\x17\x2c\xa9\x32\xbc\xc6\x89\xc4\xfd\x15\x26\x76\x54\x48\x4d\x71\x70\xf0\x34\x14\x3f\x02\x52\x5c\xb4\xbd\xb2\xaa\xbe\x58\x61\x3c\x91\xd8\x34\x10\xee\x96\x1c\x40\x4d\x69\xac\x48\xd4\x44\x5f\xbe\xe8\x09\x9b\x45\x11\x67\xaa\xcf\x52\x89\x79\xb1\x4d\x9a\xd3\xd1\x6c\x54\xfe\xd8\xa0\x4a\xdd\xae\x0d\xab\x96\x79\x0f\x63\xca\xce\x22\x99\x48\x4a\xf4\x2c\x20\x36\x8a\x75\xf6\x2f\xda\xb4\x9b\xe2\x0e\xad\x9d\x04\xc0\x0f\x8b\x94\xe9\x89\x79\x8e\x00\x97\x56\xcb\xd9\xe6\x6e\x4a\x6e\xdb\x9f\x48\x5c\x50\xc5\x52\xa3\x42\x64\x7c\xd3\x14\x34\xb9\x5f\xe8\x8e\x24\x6b\xee\x9c\xcb\xc6\xc0\xc6\x2e\xb9\x9a\x77\x12\xea\x96\xca\x1b\xc2\x99\x14\x01\x49\xa0\x70\x53\xbd\xfd\x24\xe4\xfc\x1c\x96\x7c\x7d\x6a\xce\xd6\xf4\x39\xc8\xda\xe4\xa4\xe9\x13\xc3\xfe\x11\xa1\x6d\x87\x7c\x83\x31\xd1\xdf\x98\x9e\xb7\xb7\xfc\x6e\xbe\x39\x33\x83\x39\xbe\x1f\x01\xeb\xee\xac\x90\xd4\x35\x71\x02\x53\xfa\x7c\x86\x9b\x9f\x78\x57\xed\x39\x13\xda\xdc\xec\xcd\xea\x42\xb2\x96\x56\x5a\x21\xba\x99\xb8\xcb\x6d\xa7\x4b\x2f\xfb\x4c\x6e\x3b\x69\xab\xee\x75\xb3\xed\x24\xe6\x15\x2a\xce\x74\x33\x10\xd6\xcd\xb6\x13\x8c\xd7\x40\x7d\x00\x14\xb0\xa4\xb4\x42\x7b\xf5\x59\xef\xe2\xb8\xe4\x9f\xd4\x91\x94\x14\x7a\xab\x32\x4a\xe7\x75\x40\xdf\x61\xf7\x16\x5c\x19\x4d\xfb\x89\x87\x0e\x52\x37\x6f\xb3\xf3\x18\x64\x7a\xe8\xa0\x15\xa8\xa0\x9b\x65\xb3\xf2\x37\xde\x2f\x24\x34\x5d\x5e\x95\xc1\xbf\x32\x6b\x8a\x1c\x68\x24\x8c\x13\x3d\x1c\x25\x00\x89\xe5\x31\xee\x49\xe7\x42\xd2\xd8\x83\x20\x83\xcf\x48\x7c\x08\x02\xf8\x4e\x2e\x5b\xc9\x4d\x5c\x0b\x4c\x97\x8c\xfb\x62\xda\xed\xda\xe9\x31\x4d\x67\xe6\xf2\x1a\x3a\x9d\x4e\x56\x2e\x5f\x30\xb1\x00\x2c\x9e\x2b\x16\xe1\x2c\xb8\xa4\x68\xdd\x74\x37\xb4\x6c\x38\x8d\x73\x7e\x49\x56\x5e\x0d\x4e\xe5\xcb\xbc\x4d\xf2\xb2\xc3\x7f\xf8\xd8\x91\x6a\xe4\xdc\xd9\x83\x2d\xa2\x09\x6f\xdc\xae\xc5\xaf\x51\xe4\xc1\x6f\x10\x5b\x6d\x7f\x88\xa0\x6a\xe9\x3d\x72\x03\x9c\xfc\x6d\x3e\xf1\x7e\x7a\x34\x24\x4d\x9a\xe1\x17\x1b\x7d\x7a\x20\xd5\xef\x9b\x80\x73\x00\x8b\x68\x22\x22\x9e\x87\xec\x75\x37\xb7\x56\x7b\x52\xc3\xbb\xdd\xa6\x00\xb8\x4f\x11\x2d\x9e\x85\x44\x39\x56\xd6\xd9\xa5\x67\x86\x49\xca\x8e\x4b\xec\x4c\x67\xdb\xb6\x42\x10\xff\x54\x0f\xa8\xf3\x50\xb5\x27\x87\x4b\x17\xcf\xca\xcc\xa6\xef\x0a\x0e\x71\x57\x05\x84\xd6\x92\xf3\x33\x65\xb6\xb3\xa5\x12\x04\xff\x70\xe4\x86\x26\x90\x96\x88\xdb\x92\x89\xe6\x4c\x8b\x18\x68\x70\xb3\xaa\xa7\xd5\x4e\x83\x61\x53\xae\xa3\x0c\x77\xf9\xa1\x0a\x26\x98\xd4\xe2\x85\x3b\x65\x28\x87\x2c\x2d\x02\x37\x76\xca\x78\xa3\x2d\xbf\xdb\x77\x24\x57\xa9\x17\xcf\x6e\x58\xf3\x55\x9f\x9e\x87\x85\xb8\x89\xea\xf7\xc6\x74\x38\x89\x9b\x11\xb5\x91\x99\x03\x59\xe7\x11\x8a\xba\x3f\x4b\x4d\x9f\x63\x74\xbb\x59\xd8\x83\xbe\x70\x2a\xd5\x87\x8e\xfa\x89\x05\x8b\xe2\x2d\xed\x84\x1c\xee\xcb\xd0\x91\x66\x4c\xac\x7c\xc2\x5b\x6e\x4c\x8a\xe7\x9c\x0d\x7d\x34\x89\x7b\x35\xd9\x18\xe9\xa0\xa0\xa3\x33\xe1\xa7\x8c\x1d\x15\x0b\x88\x6e\x8a\xb0\x94\x24\x24\x2c\x2b\xa3\x44\x4e\x07\xd4\x84\x2d\x48\xed\x56\x3e\x98\xd7\x48\xa6\x8e\x98\xda\xf9\x4f\x73\x5c\x08\xb7\x05\xff\x95\x2d\xd1\x3b\xc0\x57\x36\x00\x4e\xf8\x95\x4d\x89\xdd\x38\xb2\x9d\x46\x69\x95\x91\xd4\x3b\xbe\x8d\xa5\x37\x19\x6b\xf3\x32\xb1\x36\x25\x02\xd6\x92\xcc\x0f\x1c\x61\x5d\x2c\x3a\x21\x8d\xca\xb2\xda\xbd\x45\x2c\x1d\x9f\xde\x7b\x55\x84\xfe\x01\x0b\x6e\x61\x77\xbb\xb1\xf9\x85\x4e\x67\xa1\x86\x2e\xad\xf2\x49\x07\x39\x72\x3a\x6a\xa0\x84\x15\xff\x92\x8c\x1a\xb0\x3c\x49\x13\x45\xb5\x31\xf0\x60\x24\x60\x4c\x62\x72\xc7\x92\x84\x81\xd7\x9d\xea\xce\x5d\x11\xe5\x78\xe2\x1d\x39\x3d\x52\x19\x76\x26\x2a\x51\x35\xe8\x80\x04\x30\x7a\x7f\x1e\xf3\xcb\xf8\x79\x3c\x88\xe0\x01\xea\x83\x60\x4d\x7c\xf6\xd4\x99\x9a\x64\x4f\x86\xd9\xa5\x69\x5a\xae\xe3\x19\xc5\x24\xae\xee\x19\xbb\x2b\x23\x1e\x4b\x48\xc8\x46\x0a\x8d\xc3\xe9\xc4\xea\xed\xbe\x83\x00\xa7\x8e\x09\xee\xc8\x18\xf8\x89\x1f\xa7\x8f\x29\x2d\x09\xbe\x06\x3a\x4d\x24\xcb\x79\x63\xa0\xae\x45\xc0\x25\x41\x69\x95\x92\x05\x32\x5d\x96\x98\x08\xcc\x6c\xe5\xb6\xa8\x90\x89\x1c\x9a\x19\xcd\x38\x86\x49\x1a\xbc\x79\xb2\xd2\x05\x5a\x17\x47\x4a\xb3\x83\x1a\xa2\x06\xae\x5c\xd5\x1e\x32\x1a\xd6\x99\x58\x62\x18\xbf\x4c\xbe\xf6\xf0\x9f\x49\xc2\x41\x2d\xfd\x47\x72\x52\x00\x21\xcd\x30\xa0\x13\xa0\xdb\x4c\x2b\xc0\x51\x68\xaa\x53\xf3\x59\xd4\xd2\x13\xd7\xf2\x53\xbf\x35\xfd\x5f\x1e\xd8\x28\xa5\x06\x0e\x70\x6f\x46\x9a\xa7\x54\x89\x87\x11\xaf\x23\x6b\x1c\x4e\xdb\xbe\xea\x6c\x7c\x72\x87\x6e\x06\xb3\x64\xd7\x48\xa0\x07\x1e\x96\xdc\x79\x13\xdb\x8a\xe6\xf9\xee\xe4\xc8\x26\xdb\x86\x17\x78\xe3\x70\xb0\xc1\xf7\xe1\xe5\x5b\xe9\x16\x38\x47\x1a\x86\xfe\xd9\x64\x74\xac\xa2\xac\xa3\xb1\x7a\xec\xb0\x83\xd9\xa6\x06\x09\x38\xb4\xb4\x42\xbd\xae\x4b\x50\x22\x40\x32\x65\x8c\x65\x03\xe6\x94\x0b\xac\x79\xe6\x1e\x78\xe7\xa7\x1e\xda\x6a\xbd\xb8\x9c\x06\x95\x4a\x4b\xc2\x88\x68\xc1\x58\xc5\xac\x42\xec\x7d\xea\x11\xa6\x36\x08\xf9\xc3\xa2\xff\xb5\x60\x3f\xb5\x69\x10\x91\x2a\xbc\x5b\x39\x65\x2b\x62\xd1\x56\x4c\xef\x61\x4c\xcd\x99\x13\xb3\xa6\x9f\xe9\x64\x0c\x02\x42\x59\x70\x2e\xb3\xcf\x88\x0a\xc6\x6e\x5c\x34\xec\xe7\xb3\x85\xc6\xa4\x8a\xdc\x1e\x8d\x64\xec\x11\x3c\x77\xa0\xdf\x57\x22\x06\x05\xcf\xd3\x3f\x20\x9f\x27\xb9\x4f\x25\x12\x8f\x61\x01\x32\x19\x4e\xff\x39\x1f\x8b\xad\x2c\xb9\xdf\x9f\xa1\xb6\x0f\xea\x21\x9b\xc5\xe2\x7f\x2e\xd3\x79\x7f\x97\x5a\xf9\xaf\x25\xf2\x34\xf6\x55\xc4\xf5\x5e\xfa\xcb\x75\xa0\xcf\x86\xe2\x67\xa0\x29\x02\x4d\x25\x96\x00\xe7\x43\xf5\xce\x1a\x56\xe9\xa9\x07\x9a\x9e\xca\x4d\x21\x7a\xd4\x26\x90\x9d\xbc\xed\xd9\x7c\x16\x44\xc2\x2c\xa6\x69\xf5\x7e\x52\x2c\x25\xb1\xfa\x7c\x4f\x22\xbe\xfb\xd9\x0c\xe4\xcf\x1d\x68\x5c\x33\x2b\x7f\xa3\xf2\xfc\x61\xab\xbd\x1a\x9c\xe2\xe7\x04\x80\x83\x9e\x05\x88\xd0\x69\x38\x93\x82\x1e\x5c\x14\x24\x03\x21\x31\x99\x4c\x8a\xe5\x61\x36\x73\xb6\x0d\x7a\x12\x2b\x4d\xc2\x52\xad\x62\xe7\xd2\x17\x5f\x0a\x6b\xe0\xb5\x76\xcb\x6a\xc4\xdd\xe9\x8d\x1b\x55\xf8\xaf\xe8\xa3\x92\x2d\x82\xc3\x6a\x58\xfa\x47\x74\x1f\x95\x0b\x98\xbf\xc0\xa6\x95\x62\x98\x7e\x88\xcb\x9a\xc0\x93\x1b\xea\x96\xba\x77\x74\xd1\xf9\xad\x8a\xcd\x9d\xa7\x53\x12\x6b\x50\xd6\x32\xff\x8c\xa0\x28\x3d\x63\x76\x74\xf3\xa2\x22\x9e\x5b\x33\x99\xc9\x17\x26\xb6\xad\x68\xea\x44\x4e\x05\x88\x08\x3d\xb7\xf2\x88\x8e\x8b\x50\xc9\x9b\xf4\x41\xb4\x47\x14\x92\xf9\xc2\x27\x13\x5f\xe8\x52\x23\xa8\xc6\x4d\x3a\x2e\xd7\xec\x11\x9f\x33\x80\x09\xc5\xee\xd6\x74\x4a\x7e\x17\x9c\xe4\x33\x7a\x77\x78\x20\xc0\x94\xd8\x3b\x98\x37\xba\xe9\x02\x4f\xa4\x1c\x0b\x38\x9c\xc9\x59\x29\x0a\xc9\x44\x53\x45\xf8\xae\x84\xdf\x2f\x80\xa4\x13\xd4\xcc\x37\x97\x69\x0f\xe0\x0c\x8d\x21\x77\x79\xca\x36\xc0\xea\xb4\x24\xa0\x13\x8d\x38\x45\x30\xea\x54\x61\xde\x8c\xfb\x7c\x40\x08\xc6\xff\x0d\x67\xfa\xea\xd7\x0f\xf1\x2e\x3b\x6d\xc9\x1d\x07\xb4\xef\x39\xe0\x39\xc1\x73\xdd\x48\x72\x4c\x1e\x37\x26\xaa\xa4\x07\x92\x91\x8e\x33\x1b\x42\x73\x04\xe0\x8e\x7c\x5b\x6f\x10\x01\x26\x12\x6f\x75\xda\x53\x67\xf7\xd5\xad\x18\xae\x2b\x7b\xa1\x41\x45\xbf\xdf\xe5\x6b\x5a\xe2\x09\xa4\x22\x4e\xe2\x8a\x64\xea\x19\x35\x83\xa2\x3a\x9a\x98\x49\x56\xb5\xa2\xda\x8a\x95\x3e\xab\x46\xed\x62\xac\x4b\x85\xc7\xce\xa8\x66\x29\x2a\x63\x96\xa6\x47\x35\x3c\xf3\xcc\x43\xa0\x98\x00\x9f\x95\x2e\x67\xf4\x15\x5d\x04\xa8\xeb\xaf\x6b\x96\x92\x0a\x19\xb6\xa5\x81\x17\x20\x41\x30\xe3\xbe\x2d\xbe\xd3\xd9\xa3\x16\xa6\xa9\x76\x7f\x04\x86\x54\x20\xb8\x05\x06\x0f\x64\x34\x4b\x28\xa8\x16\xc5\x59\x71\x60\xb2\xaa\x9b\x28\x75\xdd\xe5\x7b\x2c\xbd\x3a\x30\x2a\x24\x7c\x32\xec\x0e\x83\x9a\x8b\x2f\x04\x49\xba\xcb\x2c\x93\x60\x45\xbc\x86\xe8\xd8\x14\xf1\x78\x50\x1b\xae\xb3\x23\x71\x84\xb0\xaf\xcf\xcc\x60\x00\x9b\xe0\x2f\xeb\x3a\xea\x80\xc8\xd2\xd3\xd6\x27\x3b\x8d\xd9\x89\x56\x06\x87\x11\x44\x29\xcb\xb4\x0c\xce\x0b\x72\xc9\xfc\xe3\x8f\xf6\x38\x39\xbe\x77\xa2\x7d\x5b\x01\xfa\x86\x46\xac\x88\xcb\x08\xeb\xa2\xf9\xde\x9c\x17\xce\xb7\x0e\x9c\xbe\xa1\x1d\x2b\xe5\xd2\xc2\x9a\x68\x9e\x4b\x48\xde\x5c\xe0\xc7\x9a\x55\x8a\x8e\x1d\xa8\xe4\xac\x82\x4a\xc0\x56\x24\x70\x55\x6a\x99\x7c\x63\x30\xcb\xee\xdc\x7b\xaf\xde\xc7\x4c\xf3\xeb\x41\xab\xda\x3f\xe8\x56\xe6\x3d\xa7\x34\x8d\xf2\xef\x53\xba\x19\xc5\xb4\x74\x60\xf5\xc5\xc6\x64\x99\xff\x89\x6f\xfc\xd9\x64\xa5\x62\x06\x55\x50\x06\x94\x17\xcc\x02\xf0\x4a\xa5\x78\x13\xd1\x67\xa4\xae\x4a\x52\xf8\x72\x9d\x4f\x85\xb9\xcf\x73\x09\xf3\x1d\xc6\xc1\x91\xa1\xda\x18\x34\x4d\x77\x98\xa9\xdc\x1e\x0d\x0f\xe8\x22\x22\xf6\x34\x14\x32\xf7\xe1\xe8\xe0\x60\x4d\xc4\x1a\xf1\x44\xba\x2f\x4e\x21\x89\xd5\x76\x82\x33\xd5\xb9\xb7\xf2\x81\xe1\x2e\x8c\x15\x66\x2b\x93\x40\x78\x4f\x97\x56\xc8\x71\xea\x9b\x6a\x5e\xd7\x43\xdf\xaa\xa9\x4b\x6d\xae\xf7\x9f\x11\x2c\xe2\xb1\x38\x48\x04\x39\x8c\x5a\xa8\xac\x3c\x26\xb8\x6f\xb6\x85\x1f\x28\xd1\x40\xff\xb0\x6b\xa9\xf1\x1e\xdf\xd6\x4d\x35\x9b\xf3\x1f\x8d\xa1\x5d\xb1\x4d\x85\xb8\x55\x32\x0c\x3d\x10\x76\x70\x42\x36\x44\x58\x6a\x60\xa9\x72\xaa\xf2\x3c\xf5\x77\x95\xc6\x31\xe6\x99\x59\xd0\x3a\xd5\x20\xe7\x6f\x91\x3c\xbf\x00\x39\xa2\x3b\x8c\x01\x9d\xf8\x8e\x46\xc0\xd5\xfa\x93\x24\x1c\x3b\x32\xd6\x9c\xd7\x6a\xb4\xb1\x10\xfa\xde\xba\xec\x78\x2c\x16\x12\xcb\x1a\xca\x81\x9d\x43\x04\xc5\x52\xc4\x89\x74\x18\x16\xb8\xb0\x12\x24\x83\x1c\x56\x4a\x66\x1e\xc1\x66\x88\xc5\x39\xc7\x29\x00\xaf\x61\x99\x39\x50\x89\xab\x26\xe0\xf8\xd1\xc5\x36\x4f\x6f\xbe\xd6\x03\x17\x6c\xa9\x3c\x9d\xd4\xf3\xe2\x02\x19\xf2\x19\xef\x64\x73\x3d\x23\x01\x33\xc5\x73\x16\x8f\xb5\x50\x2d\xd0\x62\x44\xa0\xd4\xfc\x22\x8d\x0f\xec\x5b\x3a\xb0\x77\xc9\xba\x5e\x6a\xf9\x89\xd3\x81\xbb\xd0\x51\x65\x6a\x60\x8c\x8b\x97\x54\x71\x92\x05\x3d\xa2\xfa\xb1\x94\x48\x26\xa3\x6f\x8f\x1b\xa1\x1b\x6b\xc4\x89\x4c\x44\xde\x57\xa1\x4f\xfb\x86\xc2\xf9\x94\xeb\xca\x2a\x4a\x33\x73\x5b\x19\xce\x36\x9d\x6a\x31\xf0\x40\xd9\xd8\x6e\x72\x3c\xae\xce\xbe\xdb\x87\x86\x23\x89\xcd\xd2\x40\x09\x88\x30\xbf\x9b\x63\x06\x09\xa2\x9d\x1f\x05\x99\x3f\xef\xb5\x9d\x3c\x32\x8a\x44\xd5\xd3\xa6\x09\xbf\xe8\x7d\xaf\xb0\x54\x73\xcd\xd9\x53\xce\xfd\xd0\x22\xe2\x0b\x52\xcd\x0a\xae\x95\xa4\x2e\x7d\xdf\x6f\x5a\xde\xcd\x18\xe3\x87\xf9\x46\x6f\x2a\x98\x95\xa7\xdd\x97\x87\xb6\xff\xb7\x96\xb5\x3a\xdd\xf4\xd6\x1b\xc1\x93\xbc\xc1\x37\xc9\xed\xf7\x48\xc2\xf2\xe4\x8d\x9a\x0e\xa5\x78\xa1\xb4\x5d\xc5\xdb\xc7\x61\x19\x36\x1e\x76\x35\xed\x12\x52\xfd\xa0\xcc\xbe\x65\x31\x87\xed\x24\x58\x4c\x85\x9b\xba\xc3\x0a\x4a\x89\x61\x61\x9a\x11\x13\xdd\x86\x2c\xc6\xf3\xec\x84\x90\xcc\x1a\x22\x33\x2d\xcf\x47\xe4\x21\x1c\xcb\xa5\x38\xb3\xb7\xf2\x38\x0a\x7c\xe0\x54\x3a\x53\xde\x50\x93\x8c\x02\x1f\xb8\xb6\xf5\xf1\x70\x1c\x4d\x52\xae\x59\xde\x62\xf4\xe6\xa5\x7b\xef\x2b\xbb\x4f\xfd\x65\xdb\x9b\x32\xf6\xf2\xd7\x67\x05\xa7\xa9\xd3\x75\xae\xe7\xf7\x56\x3d\xfa\x55\x3e\x2d\xc5\x01\x6b\x62\x36\x55\x9f\x12\x92\x92\xd0\xa9\x70\x5a\xe2\x4d\xbd\xd0\x4f\xa8\x60\xff\xb2\xdc\x24\x57\xe8\x44\xc1\x79\x1b\x8e\x11\xb9\xf1\x41\xdf\xbb\xa3\x5b\xc0\x34\x05\x8d\xfc\x61\x91\xfc\x4a\x7f\x3f\xae\x66\x44\x3f\x3d\x97\xef\x91\x89\x64\xb0\xaf\x28\x4b\x44\xe4\xb4\xb1\x3a\xe2\x9c\x44\x1e\x93\x2f\x5b\xe5\x23\xa2\x7f\xf5\x24\x41\x0c\xc5\xfb\x23\x4b\x48\x2e\x11\x3a\x95\x9e\x78\x3f\x25\xe6\xdb\x56\xf4\x72\xb7\x15\x40\x01\x5b\x42\x24\xcc\x7d\x9e\x63\xf1\x6f\x18\xe1\x93\xdb\x53\x36\x60\x4c\x50\x66\x4d\x26\xc9\x94\x80\x9b\x41\x3c\x3a\x8a\x07\xae\x76\x90\x9e\xc3\x9a\x0a\x51\xd2\x7e\x50\xdf\x1b\x10\x77\xa1\x92\xef\x5b\xeb\xed\x2b\x08\xf7\x9e\x14\xad\x91\x86\x8f\xfb\x01\x60\x2b\x6a\xa3\x20\x56\xdf\xc7\x2b\x8f\x9e\x52\x2a\xe3\x01\xb6\xb5\x75\xa3\x6c\x7f\x21\x14\x0e\xa3\xfe\xea\x7c\xfe\x2b\x27\xaf\x4b\x59\xfe\x36\x9b\x36\xb6\xcd\x5f\x06\xeb\x96\x75\x64\xd2\x7d\x5f\x03\x87\xac\xdc\x5b\xff\x79\x75\xdb\x98\x95\x6a\x8e\xa5\x00\xb0\xbb\x6f\x24\xc6\xe3\x59\x3d\xa0\x79\x6a\x52\x9c\x11\x69\x29\x8b\x16\x99\x06\x62\x90\xd4\x8b\x4c\x61\x44\x28\xbd\x58\xfd\x55\xca\x77\x49\x08\xab\xda\xbb\x5a\x80\x16\x24\xf4\x37\x02\xda\xbb\xee\x39\x1a\xb9\xfa\x26\x7f\x99\xd6\x34\x5a\xc3\xdd\xd6\x27\x8c\x93\x44\x46\x9f\xf5\xdd\x10\x5b\x4e\x5d\xc5\x7e\xe6\x64\x18\x44\x3f\x56\xf0\xf6\x17\x51\x95\x57\xa1\xcd\xcd\xb2\x81\x7d\x76\x53\x3e\xc1\x4e\x0e\x03\x6d\xf7\xc9\xc3\x2b\x03\x53\xde\x71\xf0\xb8\x0e\x48\xb0\xff\x61\xff\xfa\xca\x55\x21\xf7\xce\x92\xaf\xe6\x86\x1a\x17\x89\xda\x57\x62\x5f\x2b\xa5\xab\x8d\x99\xe8\x55\xf4\xfe\x4f\x5d\x8a\x5e\x1b\xbf\xec\x08\xfc\x6c\x35\x07\x39\x09\x40\xc5\xe4\x31\xe6\x27\x7f\xeb\xe0\xd9\x41\x9f\x5e\xfe\x83\x6d\xec\xaa\x12\xfd\xc9\x11\xb2\x6f\xb1\x12\x3a\x9b\xc1\x39\xb8\xd7\xa3\xa3\x73\x19\x0e\x9b\x2d\x13\xdd\x00\x4e\x3a\x1a\xbb\x11\x98\x80\x74\x44\x01\x2d\xc6\x7a\x6b\x53\xb7\xea\x6a\xb5\x61\x34\xed\x9f\x72\x63\xb4\x7f\x7a\x0f\x46\xfb\xdb\xbb\x20\xde\xbf\xe1\x84\x78\xff\xda\x76\x88\xf7\x37\x5b\x00\xbc\xc3\xa4\x43\x38\x96\x23\x37\xb6\x70\x35\xdf\x2b\xb3\x86\xb3\x20\x1c\xe2\x7e\x1d\x2a\x85\x62\x4a\x4a\x59\xdc\x7a\xd6\xb3\x77\x2b\xfc\xb5\xcd\xd9\x02\xef\x10\x2d\xc8\xea\x70\x99\x2f\x4c\xcc\x4c\x5b\x63\x67\xd8\xf7\xd1\xcd\x6e\xf4\x6c\x63\xb8\x93\x61\xff\x50\x89\x86\xd4\xcb\x48\xab\x46\xe7\xbf\x02\xbb\xbe\x9b\x24\x7d\xd2\x39\x60\x7f\xa3\xa1\xcb\xd6\x18\xb0\x91\x5c\x0a\x82\xf4\x0f\x38\x33\xe6\x12\x59\x6d\xf0\x31\x62\x3e\xbf\x7e\xc6\xbd\x4a\xae\xf9\xd8\x82\xaf\xcf\x8f\xc9\xfc\x79\x42\x73\x3d\x22\x92\x86\xe8\xcc\xc3\x66\xed\x28\x7a\x4b\x89\x05\x1c\xf7\x4d\x7f\xc5\x22\x8d\x1a\x08\x48\x60\xe5\xc6\x77\x08\xb5\x63\xbd\x45\x64\x85\xea\x3a\x62\x38\xae\x36\x28\x02\x39\xb0\x18\x89\x3c\xef\x10\xc9\x63\xff\x6c\x8d\xdd\x98\x1e\x2f\x85\xbd\x16\xfc\x10\x6b\x9d\x9b\x67\xea\x0c\x47\xa4\xb4\xbd\x8c\x01\x91\xb0\xc9\xda\xe0\x5e\x02\x45\x53\x45\x29\x35\xd6\x47\xeb\x5f\x5e\xbd\x8f\x6b\xdf\x87\x0b\xf2\x76\x89\xbf\xd5\xcc\x9a\xd3\x11\x7d\x54\x33\xff\x3b\x36\xf1\x0c\x20\x57\x76\x15\x54\x43\x50\x5f\xa0\xf6\xd0\x6b\xf3\xc2\xea\x8c\x2e\x5f\x65\xbc\xe0\xd1\x94\x4e\x4a\xd3\x4c\x00\x7b\x54\xc9\x21\xb3\x8a\x36\x93\x6a\x3e\x68\xf8\x9c\x30\xdd\x0c\xba\x23\xe7\x86\xdd\xd9\x5b\xaf\xea\xe3\x97\x9a\xa9\xc0\x86\xcc\x4b\xc3\x01\xb1\x7a\x93\x2c\xfe\x21\xda\x13\x33\x88\xa6\xd2\x32\x98\xe7\x06\x81\xb6\x3a\x36\x64\x3e\x1d\xa5\x05\x68\x69\x6d\x45\xd6\x5c\xcc\x3d\xf0\x48\x0c\xba\xd4\x1c\x5a\x2b\x7b\x36\x9c\xac\x40\x57\xca\xca\xaf\x26\x11\x6c\x43\x27\x12\xc2\x2c\x92\x10\x11\xd0\x72\x58\x20\x14\x12\x07\x21\x15\x1a\x38\x9f\x28\x5c\xe3\xcc\xad\x32\x98\x2d\xc1\x50\x38\x0e\x68\xe8\xef\x40\x0e\x92\x14\x43\x34\x0b\x9a\x8d\x3c\x7e\xb3\xa1\x06\xd9\xee\x5a\x37\x6a\x25\x29\x0c\x65\xfe\xb4\xc5\xeb\x65\x46\xcb\xfc\x70\x5a\xea\x27\x31\x35\xb1\x0b\xd3\x5e\x36\x1a\x42\x83\xcd\x05\xc8\x33\xb8\x6e\x63\x99\x6f\x23\x14\x7e\xba\x88\xc2\xc2\xb2\x71\x98\xaf\x52\xdb\x40\x21\xd5\xa1\xf7\xd0\x20\x7a\xc3\x5e\xdd\x4b\x73\x5d\x54\xde\x40\x83\x54\x4e\xb3\x54\x20\x85\x2c\x53\x2a\x40\x01\x37\xd0\x13\xd9\x17\x43\xbe\xaf\x89\xc4\xab\xdb\xc9\x85\x98\x0f\xf6\x93\x92\x4c\x0e\x9d\xa8\x69\x51\x86\x4e\x95\x1c\x2c\x84\xc4\x09\x23\x3a\xe5\xce\x52\xd1\xaa\xbb\x88\xa5\x6a\xf8\x92\x17\x17\x39\x97\x05\x15\xe2\x31\x80\x2d\x82\x59\x99\x97\x50\xc7\x4e\xc2\xbf\x00\x8a\x5c\x26\xb9\x79\x4c\x38\xaf\xd3\xb9\xcd\xf7\x89\x26\x30\xcb\x63\x92\xc1\x76\x08\x14\xf0\xc6\x89\x5c\x8e\xc0\x8a\xa1\xf2\x4a\xb5\x41\xca\xcd\x3b\xa4\xf2\x51\x3b\x1c\x95\x5d\x85\x89\xfd\x49\xb4\x4d\x38\x09\xd9\x73\xaf\x02\xaa\xd8\x14\x4d\x66\xf4\x3f\xd4\xb0\x07\x1c\xa1\x49\x12\x18\x9a\xb2\x72\x1b\xbb\x72\x21\xd2\x4b\x86\x39\xd1\x8f\x38\x70\xd9\x7d\x51\xbf\xec\xbd\x8d\x8b\xe7\x67\xfb\x2d\x84\x2a\x0f\x73\x6d\xb5\x7e\xc5\x58\x06\xd7\x50\x1a\x30\x64\xf8\x4d\x5e\x08\xb5\xf0\x3f\x44\xc5\x18\x64\x49\x82\x6d\x3c\x86\xa8\x70\x3b\xa1\x7f\x06\x79\x8e\x06\x2c\x22\xdb\xa6\xa6\x36\xad\xe4\x76\xca\x70\x07\x54\x5c\x5e\xca\x6e\xf4\xdb\xf7\xbe\x7f\x05\x33\x6d\xa4\x3e\x38\xa4\x65\x43\xae\xf1\xdc\x4e\x7d\x10\xad\xcd\xea\xed\x63\xc3\xa0\xe6\xd9\xad\x24\x73\x37\xdb\xbc\x13\xfa\x9c\x23\xd5\xb5\x3c\x53\x46\x2d\x41\xba\xa7\xa0\x14\xe4\x86\xf9\x7a\xac\xd2\xe2\x89\xb1\x13\xcf\x0a\x80\x42\x81\x09\x2a\x7b\xb8\x06\x36\x63\x67\x1d\x89\x87\xb1\x54\x7a\xad\x47\x07\x58\x1f\x32\x2b\x93\x82\xcd\xf6\xd9\x19\xff\x61\x07\xb6\x9c\x30\x9b\x01\x1b\x86\xa4\xff\x07\x3b\xe6\x1c\x20\x9d\x45\x45\x61\x47\x98\x64\xf1\xce\x98\x00\x06\xd7\xbf\xc0\x5b\xef\xaa\x4d\x00\xbc\xab\x06\xe1\x0a\xae\x69\xf0\x1b\x9e\xd3\x0f\x67\xf4\xd2\x3a\x42\x88\x5b\xc4\x09\x55\xfa\xb9\xad\x12\x33\xbd\x19\x4a\x39\xdd\x0d\x30\x08\xca\x0f\x9a\x49\x06\xbe\x32\x27\x09\x6f\xab\xfd\x93\xd0\x16\x12\x5c\x65\xa0\x25\x34\x5e\x35\x7d\xa3\x86\xb6\x1e\x02\xe6\x35\x82\xd4\x0b\x1d\xfd\x20\xd2\x30\x3d\x07\xf3\x13\x0d\x9e\xc1\x4a\xc7\x7d\x6d\x7f\x1f\xe4\x13\x79\xb0\x12\x26\xa9\xa8\xa9\xcf\x22\x91\xfe\x2e\x63\xd6\x82\x09\x56\xbb\xf1\x7d\x65\xe7\x4a\xdf\xda\xeb\x3a\x34\x32\x71\x60\x47\xcc\x4f\xf4\xa6\x9b\x2d\x13\x14\x95\xf2\x9c\xaf\xc1\xe3\x2d\x42\x94\x8b\xee\x99\x4a\x97\x46\xb8\xe9\x59\xc3\xdb\xbe\xa2\x33\x7c\xff\xc5\x7c\x29\xc9\xe4\x0e\x8a\xe0\xf3\x06\xac\xba\xea\xf6\x49\x47\xee\xcc\xc1\x61\xbe\xe9\x0f\x9e\xa2\x08\x2b\xef\x2a\xbd\xef\x74\x74\x50\x11\x62\xef\xf6\x82\xef\x41\xdd\x1d\x18\x44\x6f\x3f\x04\x43\x10\x8e\xa1\x67\xb4\x74\xf3\xb4\xf5\xd0\x3b\xf2\xb8\xc4\x49\xcb\x5d\x47\x1d\x85\x98\x32\x52\x45\x3c\x5e\x95\x6d\x4b\x33\x94\xac\xf7\x14\xa7\x2b\xe1\x13\xac\x3b\xdf\x0d\x9a\x5b\x8b\xaa\x16\xcb\x33\xcb\xda\xf9\x8f\x19\x5b\x31\xb0\xbc\xc1\xbd\x79\x84\x76\xb8\x85\x8f\x0a\x17\x23\x7f\x0f\xaa\xdc\x70\xdf\x3c\x6a\xd4\x69\x43\xd3\x61\x66\xe6\x7e\x5c\xe7\x1b\x47\xa4\x03\x43\xa5\x34\x1b\xee\xc2\xde\x64\x75\x62\x74\x20\x42\xa0\x4b\x97\xc2\xf5\xd0\xb1\x51\x6d\xbd\x13\x3d\xce\x61\x9b\xa6\x9b\x54\x71\x3c\xad\xf6\x5e\x7a\xe7\xd8\xa1\xf1\xaf\x28\xcb\xde\xb9\x96\x47\x7e\x51\xdb\xbc\x5a\x6f\x4f\x18\xf8\xd6\x63\xe7\x86\xe0\x94\x0f\x72\x3e\x52\xa5\x7b\x62\xba\xb9\x34\xa6\xf7\xcb\x76\x4d\x9d\x71\x84\xb3\x11\x83\x6c\x29\x3c\x8b\x56\x94\x7b\xc4\x9b\xe6\x99\x90\xb1\x32\x50\x99\x00\xfa\x54\x19\x80\x27\x1d\x44\xd8\x0c\x0a\x56\x74\xbb\x02\x90\xbc\xce\xf2\x15\x9d\x87\x6f\x50\xad\x61\x55\x92\xc9\xe3\x36\x60\x88\xa0\x01\xff\x22\xc2\x81\x81\x51\x65\xef\x5d\x6b\x04\x61\x2d\xdf\x5e\x3c\x78\x6a\x9f\x3c\xe4\x47\x2e\xdb\xd9\xd5\x7e\xad\xa5\xb6\xd7\xeb\xc5\xe9\xf4\x35\xdb\xb9\xbd\xdb\xaf\x5d\xd3\x56\xfa\x1d\xbe\x60\x38\xcf\xa6\xbe\x8e\x11\x97\xf8\x25\xb9\xbd\xbb\x72\xd7\x1e\x79\xa3\x76\xd1\xf4\x0e\x02\x18\x02\x9b\xf3\x92\x9c\x3b\xe3\xdb\x70\x63\xff\x19\xf7\x85\xea\xb5\x1c\xfd\xe8\x9b\xfc\xca\xd3\xdd\x60\x00\x9b\xd9\x98\xbd\x75\xd2\x99\xc1\xed\x16\x39\x71\xb9\xef\x71\x10\x9b\x45\xa9\xc4\x7f\xa9\x19\xd2\xb9\xe6\xcd\xec\x42\xc5\x19\xd2\xe7\x15\x14\xa7\x07\xdb\x36\xd8\xc7\x91\x03\x61\xb7\x65\xdc\xc1\xb6\x45\xf5\xd8\xab\x4f\xe2\x59\x94\xfa\xad\xc7\x91\x23\x3a\x79\xeb\x12\x70\x1c\x02\x80\x10\xc6\xe9\x2f\x21\x2f\x1c\xa5\xbf\x35\x73\x91\xa7\x96\x55\x27\x21\x20\xe0\x7f\xeb\x22\x7c\x87\x8d\xa5\x42\xe3\xa1\xaa\xa8\x0a\xe3\x0f\x74\x5c\x1b\x8f\x54\x23\x19\xe2\xf3\xd2\xd2\x9d\x4d\x8e\x24\x2b\x32\x6e\x5f\xc5\xe4\xde\x20\x91\xba\xbe\x62\xd3\xda\x1c\x1c\xe2\x5e\xa7\x26\xf5\xb1\x90\x92\xaa\x99\x8f\xc8\x65\x17\xc3\xe9\x14\x69\x99\x1b\xa6\x63\xe0\x49\xea\x3d\x15\x15\x84\xfa\x05\x75\x25\x45\x16\xa6\xa3\x8c\xc8\xad\xf3\xd6\x93\x1f\x0a\xcd\xca\xd3\x66\x6a\xb0\x61\xd8\xb8\xd6\x90\xa0\x93\xce\xcd\x45\xc0\xd3\x9d\xe0\x13\xe2\xab\x5f\xd1\x65\x02\xf6\x9c\xe0\x28\x72\x7d\xf2\x9e\x6d\x6f\x39\x19\xba\xfb\x55\x50\x36\x7a\x48\x24\x67\xb0\x34\x04\xf1\xd9\xba\x36\xa9\x50\xf3\xf7\x40\x40\xe2\x58\x0d\x28\x31\xcd\xce\x98\xcd\x00\x7f\xe1\x78\x5f\x09\x4a\x79\xbd\x7b\x95\x33\xda\xe6\x13\x03\xad\x27\x2c\xbe\x83\xf1\xe3\x4d\xeb\x31\x6e\x9b\xd8\x15\x85\x3e\x76\xf0\x4f\xea\xf4\x86\xd5\xb3\x86\xfd\xf8\xc4\x6a\xfe\xdf\x12\x98\xd6\xb0\x72\xcd\x31\xe3\x66\x34\x63\x73\xba\x5f\x25\x76\x25\x6c\x93\xe3\x4b\xdf\x5a\x4e\x69\x92\x2b\x56\xf8\xee\x33\xdf\x27\xb7\xa4\xc4\xd4\xe0\x7e\xe7\x94\xeb\x4e\x9b\x4d\xe0\x47\x40\x48\xef\xe4\x1d\x42\xee\x62\x2b\xd3\xfd\xca\xee\xa7\x76\xdd\x56\x46\x71\x40\x18\x9b\xdd\xb1\x75\x4b\x5a\x9d\x68\xaa\x70\x40\xec\xed\x45\x30\xf7\xf8\x81\xbf\xe4\x75\x61\x81\x97\xce\xf2\x53\x58\x64\x84\xee\x85\x55\xb8\x93\x98\x4b\x7d\xd4\xaf\xd2\x38\x47\x81\x58\xc7\x4b\x02\x19\x69\x49\x04\xac\x82\xed\xa3\x25\x9a\x0b\xc7\xfb\x83\x00\x07\x19\x75\x52\x29\xb1\x45\x9e\xe0\x92\x49\x2d\xa8\xda\x96\x38\x9c\xc6\x7c\x0e\x31\x07\xd6\x12\xcb\x47\x12\x80\xce\x9e\xe0\xe6\x66\x36\xeb\xc8\x80\xee\x3d\x21\x16\x4b\xc0\x46\x36\x92\x51\x66\x1e\x5b\x58\xb1\x15\xd2\xda\x7e\xc0\x10\xf4\x97\x5f\x8f\xe0\x6a\xa2\x5c\x5e\xea\xcd\x8b\x5e\x14\x6b\x85\x94\x9a\x9d\x60\x93\x88\xfe\xf9\x44\xf8\xb5\x73\xf5\x05\x05\x06\x47\x5d\x7e\x96\xe3\xa4\x9b\x79\x13\x07\x6f\x10\x02\x01\x8a\x7d\x8e\x7f\xd1\x3b\x2b\x69\x25\x8b\x08\x1a\x4e\x7d\x87\x51\xbc\x9c\x30\xbf\xe5\xfe\xd4\xa5\xed\x55\xbf\xc9\x75\x29\x4d\xb6\xdd\x5b\xc6\x5a\x60\x22\x9f\x37\x0d\xb9\xe2\x1a\x0e\x3f\x2f\x5b\x43\xe4\x7b\xcc\x6c\xf1\x82\x29\xf2\x24\x18\x4d\x72\x89\xf5\xc0\x9a\x7c\x5e\xba\x04\x91\x09\x61\x99\xbb\xe2\xb7\x10\x03\xfe\xa7\x3a\x88\xa0\xcd\x22\xe9\xd6\x8a\x9d\xdb\x61\x09\xc2\x6c\x02\xf2\x3e\x1b\xde\x68\x00\xc7\xe1\x79\xa2\x7f\x80\x14\x61\xd1\xce\x7b\x9e\x32\x3e\xaf\xfe\x43\x50\xae\x89\x90\xb0\x4c\xc5\x0f\x10\x20\x9a\x6a\x3f\xd1\x6e\x08\x74\x67\xe5\x9e\xd8\xd3\x5d\x03\xa6\x16\xe1\x53\x88\xb8\xf8\xf8\x7b\xe1\xb5\x55\xd3\x87\x05\x91\x28\x27\xb3\xb5\x62\xe7\xa3\x27\x66\x8f\xe6\x67\x30\xd3\x83\xdd\xea\x18\x95\xc4\x4c\x50\x41\xa5\x4d\x74\x64\x15\x07\xcc\x29\xe3\xb3\x32\xc3\xba\xe3\x59\x21\xd6\x76\x00\x8e\x26\x60\x6f\x85\xaf\xfe\x32\x12\x50\x5b\x0b\x1b\x9d\x61\xde\x94\x84\xbb\x35\xfb\xc0\x0c\x53\x87\x7c\x23\x2b\x80\xb2\x01\x37\x4a\x05\xa4\x8a\x0a\x23\x1b\xc8\xb8\xcc\x5f\xab\xd5\x64\x55\xa9\xa4\x36\x23\x56\x19\x44\xae\x86\xc0\x9b\x42\x22\x4b\x83\xf7\xd6\x7c\xa2\x1a\xb8\xc0\xc1\x19\x16\x80\x29\x02\x6f\x90\xd0\x10\xaa\x74\x6b\xfd\x6c\x03\x9a\xe6\xc8\x2c\xae\x14\xfb\x6c\x11\xe8\xa1\xeb\x0f\xf3\x55\x1f\xec\x29\xdd\xb9\x65\x98\x35\x81\x3c\x41\xba\x08\xb0\x1e\x5c\x30\x9c\xeb\x9e\x5f\xec\x37\xd8\xd9\xf6\xed\x5e\x7e\x7b\xd8\x24\x0d\x71\x52\x82\xce\xb0\x66\x93\x13\x01\xfb\xeb\x50\x0a\x10\x61\x1a\x21\x66\x97\xb4\xf9\x16\x58\x55\x83\xb2\xb3\x68\x58\x1b\xf2\xa2\x6c\xdb\xbd\x5e\xc1\xf1\x3a\x28\x9f\x03\x6d\xa0\x3f\x92\xc5\x40\x3d\x62\x68\x67\x99\xdd\x4f\xcd\x96\x7b\x2d\x93\x69\xd0\x3a\x92\x27\xb4\x41\x15\x8b\x38\x3f\x67\xc2\xf0\x7a\x48\x46\x7a\x30\x11\x10\xf7\x5b\x0f\x44\x23\xe3\x90\x41\x8c\x19\x2e\xf6\xe0\xba\x25\x27\xb6\x80\x77\xad\x3d\x32\x0f\x33\x1a\xa4\xc9\xb8\xb7\x9d\x5a\x27\xf2\xa1\x48\x78\x86\x93\xaa\xbb\xee\x9b\x26\x07\x49\x9d\x92\x34\xd0\x31\x49\xef\x9d\x4a\x69\xa4\xad\xbf\x9b\x65\xe8\x7a\x94\xda\x1b\xcc\xd3\xcd\x8f\x97\xfd\x6f\xe2\xd9\xb4\x9b\x8f\x7b\x83\xa9\x81\xfe\xb0\x69\xe7\xc3\x9f\x38\x1d\x09\x30\x5b\xcb\x4b\xb8\x2f\xee\x03\x1f\x6e\x2a\xed\xa8\x61\x35\xf3\x11\xd2\xed\xe1\xb0\x89\x10\xea\x2c\x63\x02\x90\x98\xac\xe8\xfb\x98\x18\xb1\x12\xd7\x2b\x9a\xd5\x41\xbe\xb7\x07\x42\x44\x72\x6c\x44\x6f\xb8\x9f\x11\xf1\x22\x24\x1f\x54\x68\xda\x54\x17\xb5\x99\x8a\xa2\x39\xe6\xae\x24\xc6\xe5\xb2\xa3\xe9\xfe\x27\xf7\xf2\xf6\xbc\xf8\xe1\x10\x30\x56\x88\x27\x7c\xe3\x22\xcf\x05\x92\x98\xe2\xeb\x80\xf4\xa1\x1c\x0a\xc0\x91\xd7\x53\x96\x41\x0f\x4a\x21\x94\xd5\x8f\xdf\x91\xd2\x36\xc6\x46\x36\x52\x5c\x8a\x36\x14\x5c\xbf\xbb\x39\xb4\x08\x17\x2d\xf8\x5f\x3d\xa6\xc1\x51\xb3\x22\x39\x49\x57\x2e\x5c\x2e\x0e\x7a\x6d\x6b\x7a\xcb\x46\xcd\xb5\x55\xf4\x78\x0f\x3c\x39\xdf\xd0\xc9\x91\xaa\x24\xc6\x37\x69\xfc\x46\x53\xe9\xef\xcf\xe1\xfe\xca\xa7\x62\xdf\x82\x40\xfe\xdb\xa8\xea\x94\x7d\xfa\xcf\x75\xe5\x01\xf4\x6f\xf6\xa1\xfe\xcf\xbe\xbc\x11\xde\xd1\xaa\x0f\x07\x10\x6a\xbd\x34\x3d\xa4\xee\xfe\xba\xe3\xa5\x6f\x65\x55\x4b\x0b\xe6\x78\x64\xe9\x57\x98\xeb\xbb\xb8\x31\x6e\x44\xa5\x58\xcd\xf5\x98\xe5\x79\x96\x22\x8d\xae\xe9\x35\xe5\x80\x98\xc0\xca\x82\x82\xd7\x14\x95\xd5\x4b\x01\x95\xec\x17\xd1\xfb\xa4\xbf\x14\x2d\xa4\x6f\x37\x42\x22\xb4\xe0\x12\xc4\x9b\x29\x1e\x98\xa5\x75\x57\x0c\xe2\xd1\x1f\x45\xc1\x68\x39\xac\x10\x01\xc0\x62\x29\x1a\x50\xe4\x25\x2e\x96\x24\x84\x47\x9c\xc1\x28\x40\x28\x16\x91\x11\xf1\x75\xa3\xd6\x52\x8d\x1b\xec\x66\x4c\x54\x20\x06\xcf\xaa\x1b\x4a\x36\x0d\xe9\xce\xea\x29\x0f\x48\x2a\x79\xd3\xdf\xf1\x0b\xe8\x9f\x3d\xce\xd2\xcc\x51\x0b\x2f\xab\xdd\xd2\xd8\x75\x49\x2e\xbd\x08\xba\x3c\x8f\xdb\xef\x90\xc1\x18\x2c\x96\xb0\x72\x23\x82\x79\x04\x7c\xbe\x03\x06\x6c\xc9\x3c\x60\xfa\xc6\x51\xf9\x07\xea\x3d\xc4\xfb\xd4\xf9\xeb\xa9\x46\x24\x1b\xe8\xab\xd2\x41\x92\x74\xe9\x98\x8d\x32\xda\xec\x94\x64\x36\x01\x63\xcc\xf3\x82\x57\xc7\xa5\xe4\x87\xa3\x34\x7e\xf6\x25\xef\x76\x1b\x62\x19\xfc\x61\xff\xd0\x95\x5f\x43\xd5\xae\xe3\x59\xde\x6c\x87\xcc\xa8\xce\x76\x1a\x71\xa4\x1a\x80\x73\x10\x24\x6d\x3a\xb0\x47\xdf\xf4\xe3\x5c\xbc\x57\x5b\xf6\xb3\xa9\xb3\x43\x09\x19\xe5\x6c\xf1\xf4\x7d\x0f\xd3\x52\xc5\x5e\x9f\x32\x4a\xa9\x49\x36\xde\x58\xfc\x6c\x39\xa1\xe8\xaf\x3d\xf1\xff\xfb\x83\x11\x8c\x60\x74\x07\xfd\xd3\x91\xef\x15\x2f\xf5\x17\x94\x19\x83\x50\xac\xd9\x6a\x65\x73\x22\x9c\xa9\x5f\xac\x0d\x4c\x19\x8d\xc4\x77\xa7\x6d\xab\xcb\x7e\xc0\xa6\x58\x14\xba\xe2\xcd\x4e\xfb\x16\x4d\xef\x31\x78\xbf\xd5\x16\x7f\xaa\xd9\x9b\x23\x02\xb8\xea\x4e\x6d\x7a\x53\x0f\xef\x8d\x25\x62\xb7\x96\x1f\x2c\xef\xf2\xe3\xa0\xc5\xbd\x9b\x7e\xb2\x42\x9d\xee\x09\x60\xff\x39\xef\xf5\x56\x75\x36\x55\xaa\x7d\xd6\xba\x47\xa6\x7f\x1d\x0c\xac\x75\xf1\x6e\x8b\x77\x4f\xbe\xb5\x03\xaf\x1c\xb0\xe7\x1c\x66\x73\x43\x97\x5c\x1c\x81\xb2\x08\xbd\x1c\xcf\xfe\xdb\xcf\x67\xfd\x1a\xb4\x13\x87\xb8\xfe\xb9\xb3\x56\x97\xeb\xce\xa6\xae\x8f\x40\x9b\xb6\xfd\xe2\xac\x3a\xaa\x5f\x60\x63\x2b\x7d\xf1\xfd\xfe\x4c\x95\x3c\xd1\x5b\xb4\x90\x23\x55\xab\xd6\x2a\x1f\x7c\xd0\xe6\xad\xba\x5b\x93\xdb\x5b\xe5\xa7\x99\xeb\xba\xd4\xa7\x6f\xb8\xca\xc9\xbc\x02\xb9\xbf\x5c\x3d\x47\x52\xf8\x4b\x2c\x21\x5b\x3c\x8b\xbe\x48\xe3\x3f\x8e\x85\x3b\x85\x39\xe1\xf8\xc6\x05\x81\x3a\x91\xd4\x49\xcd\xa3\x2b\xbe\xcc\x61\xfe\x98\xf9\x21\xbf\xb7\xed\x2a\x8f\xc8\x3f\x23\x92\x27\x47\xd0\x07\xe3\x3d\x9f\xed\xc4\x51\x36\x15\x9b\x2c\x1a\xe3\x67\xcb\x6d\x26\x3b\xb6\x87\x88\xd4\xf3\xd7\xce\xeb\xb9\xd9\x58\xe6\x95\x85\x30\xf2\xf5\xe1\x0a\xf9\xc0\x1f\x80\x93\x0e\x9d\xec\x0b\x8f\x3b\x71\x57\xa9\x71\xcd\x27\xab\x34\x8c\xae\x49\x0b\xf0\x0c\x43\xb5\x67\xed\xdc\xf1\xce\x83\x59\xad\x60\xc6\x13\x7e\x1d\x60\x36\x69\x78\x11\x30\x0e\x4f\x47\xba\x19\x67\x60\xce\xee\xde\x5b\x7e\x93\xe0\x3f\x4e\x43\xe0\x51\x40\xea\xf8\xc8\x84\x36\xe6\x90\x4e\xce\x81\x84\xaa\x9e\x41\x7d\x6a\xc0\x8e\x42\x61\xf3\xc1\x1c\x33\xed\xc5\xa5\x29\xea\x15\xc3\xcf\xcb\xb4\x3a\x71\xba\x49\xab\x00\xed\xaf\x9e\xc1\x1d\x67\x5a\xbe\x08\x32\xcf\x76\x1a\x6c\x66\x2c\xdf\x10\xd0\xa3\xa2\xce\x7f\x59\xbf\xf3\x87\xd1\xae\xec\xdd\x62\xd4\xa9\xea\x1c\xf9\x9e\x19\xd9\x58\x6f\xc3\x49\x12\xc4\x97\xcb\x9c\xdd\x58\xa8\x81\xa2\x0e\x5f\x27\x01\xc4\x12\xf2\xc3\x35\xf5\xc7\x15\x5d\x1a\x4a\x84\xb8\xfc\x32\x50\xd2\x08\x39\x32\xb0\xa8\x43\xcd\x89\xfa\xd4\xff\x0c\xfd\x40\xf1\x99\xa6\x43\xa5\xa0\x86\xf9\x9b\x18\x36\x14\x45\x9f\x65\xd1\x00\x42\x40\x8b\x0b\x06\xe8\xac\xdf\x41\x91\x39\x94\xdf\x87\xc3\x02\xe7\xe6\xc7\xb4\xe8\x79\x06\x5d\x00\xf5\x05\x48\xf1\x09\x07\x89\x03\x2d\x1c\xe0\x20\xdb\x62\xb6\xa8\x39\x0d\xd1\xf0\x4f\x1e\xf5\x19\x30\x0c\x75\x77\xa7\xac\x49\xe2\xc8\xf1\xa6\x02\x37\x4a\xa6\x78\x95\xc5\xab\x32\xaf\xf3\x5c\xca\x19\x56\x66\x3d\x6e\x56\x91\x56\x80\xab\xa4\xd0\x22\x23\x39\x93\xac\xd6\x76\x38\x78\x0a\xfb\xb6\x6d\x15\x0f\x14\x70\x41\x68\xf6\xd3\x13\xe8\x79\xe2\x91\x33\x82\xbb\x70\x51\x09\x0e\x25\xe4\xd0\x74\x5e\xaf\x91\xd8\x20\x7c\x83\xc2\x82\x5d\x9d\x59\x42\x38\x6a\x43\xd7\xac\x6e\xc4\x23\x07\x26\xcb\xc9\x87\x0b\xee\xfc\xbd\xf0\xca\xb4\x76\xac\xcb\x92\x50\xa1\x3e\x15\x96\x4f\x03\x7f\xa1\xa9\xa7\x04\x93\x93\xaf\x03\x89\x79\xb5\x55\x41\x74\x32\xd0\x5f\xb7\xe0\xfd\xee\xf1\xd1\xee\x03\x0b\xf2\x6e\x35\x33\x65\x2a\x83\x83\x31\xbb\x93\x93\x76\xf4\x15\xb0\xb4\xde\x28\x4b\x5f\x48\xb5\x76\x56\xcb\xca\x89\x33\x7d\x12\x07\x2c\xd5\xc6\x41\xb4\x43\xe0\x55\xc6\x8d\xd8\x82\x12\x94\x43\x75\x08\x99\xab\xc9\x74\x0e\xac\xf9\x69\xce\x2d\x5d\xb9\x60\xe6\x05\xce\xd6\xe9\xf9\x1b\xcc\x37\x84\x5d\x52\xe6\x0f\x0d\x21\x7a\x73\xb2\x4e\xfb\x96\x74\xa3\x04\x8a\x91\x26\xbe\xc5\xcc\x89\xcc\x84\x6b\x29\xbc\xce\x53\x4c\xa5\xcd\xf4\x9b\x0f\x84\xcc\xb9\xae\x79\x11\x37\x82\xaa\x24\xb4\xb0\xcf\xa5\x44\x4a\xae\x4e\x1f\xca\x64\xe5\xec\x22\x89\xd4\xf9\x7f\x39\x1c\xe9\x0a\xe6\x33\x31\x20\x49\xcd\x17\x97\x5a\x28\x5e\x28\x0d\x6c\x77\x36\x0d\x2f\xf5\x40\x8e\x59\x8a\x42\x8e\x5e\xde\xd8\xd9\x7d\xb0\x4f\x54\x7e\x39\x63\xbe\x63\xc2\xf2\x8e\x5d\xf9\x9a\x95\x7b\xe2\x29\xcb\xdd\x7d\xee\xb9\x44\x38\xed\x24\x13\x7b\x13\xfb\xf0\xde\x13\xc7\x79\x63\x96\x2c\x12\xca\xa4\x80\x7b\xf6\x74\x41\xba\x57\x33\x7a\x10\x48\x49\xba\xab\x6d\xc3\xf0\x44\xc6\x34\xdc\xa4\x55\x04\xfd\xda\x54\x33\x64\xa6\x0f\x49\xd2\x0e\x9d\xf3\x44\x92\x29\x0d\x12\x8c\xe0\x49\xdb\xac\x8d\x2e\x01\x64\xeb\x7e\xe9\x5b\x0c\x2d\xfb\x4b\x96\x5e\x32\x80\x5a\x63\x0c\x93\xda\x0a\xdd\x38\xfd\x83\x75\xbe\x2c\x59\xe9\xb4\x5e\x5c\xd9\x5f\xa6\xac\xd4\x81\xc1\x5f\xf8\x2b\xda\x17\x63\x4a\xa5\xda\x1c\x24\xa3\x5c\x32\x3a\x5a\x57\xe6\x0c\xd5\x62\xd4\x42\xa0\xed\x77\x3d\xd7\xda\x5b\x31\x27\x4e\x03\x9f\x59\x56\x7a\x34\x93\x1e\x3b\xb3\xfc\x28\x97\x66\x7a\x4e\xa7\xc4\x7f\xe0\x55\x81\xf3\x66\x28\x7f\x70\xd6\x99\xe0\x21\x78\xd7\x23\x83\x97\xe0\xb6\xcf\x4c\xa9\x3d\x23\x16\xc5\x8b\x54\xe5\x68\x6e\x05\xd3\x62\x8b\xe4\x61\xcb\xb3\x22\xd6\xc5\x2c\xcc\x54\xe2\x5c\x6f\xd4\x21\x82\xf0\x40\x40\x73\x4e\x25\xa6\xd6\x18\x7c\x0a\x95\xc7\xe7\x74\xe8\xe4\x58\x6a\xbb\x09\x6a\x1b\xb3\xd3\x09\xbf\x51\x6f\x35\xba\xfd\x8a\x9d\x1a\x98\xb9\xb3\xed\x6f\x8f\x65\x46\x03\x29\x19\x6f\x10\xf9\xf4\x81\x90\x20\xeb\x39\xcb\xb7\xcf\x3a\xe1\x68\x2a\x27\x63\x4a\xe5\xf5\xe5\xad\x8f\x98\xbc\x5b\xce\xd9\x7b\x12\xc8\x84\x06\x4e\x66\xa5\x6e\x7a\x99\x5d\x38\x46\x11\xbf\x2f\xea\xa7\x1b\x7c\x92\xba\x31\xca\x76\xed\x0c\xff\x67\x40\xd4\x4a\x3a\xb1\x59\xcc\xef\xd5\xb6\x4e\x75\xda\x3a\xa2\x64\xea\xe6\x68\x48\xac\xa2\xf0\xf6\x6f\x0a\xa1\xf8\xbf\xbb\x74\xbc\x4d\x90\xc6\x60\x84\x84\x52\xcc\x8d\xbf\x52\xf4\xf7\x69\xc1\x3a\x7c\x4e\xdb\x5f\x50\x22\xa0\xa2\xfd\x88\x42\x40\xb0\xb9\xb4\xc8\x20\x6d\x60\x61\x9e\xf5\x8b\xa2\x3a\x4d\xfd\x0b\x8b\xd0\x02\x12\x09\x63\x32\xcb\xc5\xa8\x3c\xc8\x15\xa6\xfd\xd8\x93\xb4\x96\x55\x08\x8f\x4f\x8d\x53\x02\x92\x5c\x9d\x81\x00\x25\x61\x5c\x41\x05\xba\x70\xe7\xf4\x0c\xe4\xf8\xea\x84\xaf\xf2\xb1\xbd\x65\xc6\x5c\xe6\xc8\x41\x92\xac\xa9\xa9\x9b\x2e\xcc\xb0\x7b\xa7\xd6\xeb\xac\x77\x86\xc7\xbf\x7e\x3c\x64\x58\x49\x68\xc1\xfd\x52\x4e\xbd\x67\x6b\x1a\x76\xe0\xe6\x6f\xdc\x7b\x6e\xa6\xd4\x9c\xa2\x7d\x8d\xd7\xee\x1e\x48\x7c\x65\xac\x69\x56\x95\x57\xa9\xa1\xd8\x1c\xc7\x3f\xa1\xcc\x1c\x23\xcd\x28\x4b\x3a\xb4\xb9\x07\x6d\x1d\x60\x11\xef\x26\xe6\x4c\xfe\x78\x5e\x46\xae\x92\x01\x2b\x27\xa5\xdd\x03\x99\xeb\x1e\xc6\xd8\x9c\x5a\xe6\x85\x89\xb2\x94\xc5\x8f\x1a\x1e\x31\x3f\x5e\xeb\x07\x45\x0e\x04\xa6\x28\xa0\xdd\x9d\x1e\xf8\x44\xe0\xa9\xc8\x75\xe4\x89\x16\xf2\x36\xaf\xe1\x54\xc2\x98\xef\xfb\x90\x13\xed\xc1\xa1\x4c\x53\x8e\xbb\x36\x4f\xb1\x61\x6d\xef\xda\x64\xeb\x07\xca\x99\x0e\x79\xc7\x32\xf8\xd0\xfa\x99\x7c\x92\x5e\xd8\x53\x12\xde\x4b\xf0\xa4\xbd\x7d\x2a\x8c\x32\x4c\x2f\xc5\x98\x04\x29\x19\xcf\x00\x68\x08\x7e\xf7\x9b\xc2\xf2\x5c\x31\xed\xc9\x20\x0d\x44\xb9\xcc\x85\x8c\xf7\xe8\x24\xa6\x18\xd5\x31\x93\x47\x2f\xce\x95\x6f\xa9\x80\x30\x03\x5e\x0c\xea\xdb\xfa\x87\xfb\x5f\x7c\x71\x2c\xc1\xad\x0c\x7c\xab\xfc\x60\xfe\xdc\xb7\x07\x06\x2a\x7a\xf0\x7c\x94\xa6\xc6\x27\xec\x75\x1c\x73\x76\x15\x83\x6a\x28\x1f\x71\xe0\xab\x52\xab\x89\x7a\x4c\x3e\xd1\xcd\x36\xff\x8e\xba\x99\xbf\x88\x09\xf8\x1c\x3b\x08\x73\x32\x83\x14\xc5\x8b\x60\xf8\xb1\x85\x57\x8b\x60\xfd\x54\x79\x50\xf7\x67\xa8\x01\x65\x65\x30\x16\x87\xf7\x0c\x11\xed\xf4\x30\x30\xea\x7d\x2f\xc7\x94\xbc\x8d\x3b\x68\x5b\x74\x47\xf9\x44\xbb\x35\xd6\x5e\x45\xbf\xc6\x23\xe3\x68\xf7\xc8\x8d\x3a\x66\x3f\x09\xfb\x05\x75\x33\x7a\x30\xef\xda\x8e\xef\x24\xea\x54\xa8\xa8\x9e\x5e\x54\xcf\x41\x68\x7a\x05\x12\x97\x09\x97\x78\x0a\xe8\x49\x7b\x0f\x81\xdd\x35\x1b\xa6\xe8\xce\xdd\xc0\x8c\x8b\xf8\x27\xe4\x72\xc2\xfc\x19\xa5\x4b\x0a\x80\x9b\x7a\x8e\x6f\x20\x6c\xd6\xa2\x3c\xba\x9e\xd5\x4e\x6c\xb2\x8c\x9d\x10\x66\xa8\xa7\x4d\x7f\x2a\xcc\x7e\xd0\x55\xca\x8f\x87\x57\xf3\xda\x5f\x9f\x04\x3f\x07\x96\x76\x1e\x3b\x28\x41\x80\x19\x85\xa8\xcd\xba\xda\x52\xc3\x5e\xff\x20\x33\xb7\x3d\x36\xd2\x36\x3d\x32\xe6\x6e\xeb\x7e\x7d\x63\xaf\xbd\x15\x07\x90\x4f\x37\x93\x58\x0c\x86\x95\xe0\x64\xba\xac\x01\x4a\x19\xd6\x7c\x8f\xde\x4c\x50\x9c\xde\x9d\x7e\x0f\xcd\x85\xa9\xfa\xf1\x38\x9a\x2b\x51\x44\xec\xf4\xe0\x5c\xaf\xd4\xe6\xd2\xad\x0b\xc3\xad\x53\xc3\x17\x5c\xa7\x3d\xf7\x55\xd9\x76\xcc\x0d\x4d\xe4\x85\x9a\x1e\x63\x22\x61\xfb\xab\x4b\x3b\xcf\x41\xae\x1c\x16\x3d\xd4\xa8\xc4\x9a\xa9\x94\xb9\xd6\x6b\x81\x01\x4a\x84\x4e\x80\x70\x9b\xe8\x4d\x25\x41\x52\x60\xd1\xd9\x88\x3b\xd8\xf9\x28\x13\xfb\xbd\x87\x35\xc3\x10\x57\x9a\xbd\xdb\x3d\xb5\x08\x8b\x86\x59\x20\x9d\x67\x2d\xe4\x5e\x08\x76\x34\x81\xd0\x58\x7f\xae\xd9\x89\xfa\x85\x4a\xd8\x40\xee\xd7\x3d\xf8\x63\xc7\x33\xc5\xea\xfc\xec\x7d\xca\x2a\x29\x12\x08\x75\x92\xd6\xca\xff\x62\x1b\xbc\x54\xb9\x13\x46\x9a\x1b\x27\xd3\x7c\xb9\x4e\x33\x97\xc1\xb9\xe6\x45\xdf\xde\x00\xb2\xce\x39\x89\xbb\xda\xaa\x29\x31\x90\xd0\x21\x12\x47\xdb\x1a\xbd\xf7\x6b\x38\x92\xad\x36\x94\x44\xef\x0a\x7e\x48\xaf\xb8\xbd\x47\x70\xc0\x04\x25\xa8\x46\x7a\x33\xee\x32\xc1\xc4\x4d\x1a\xdf\x4a\xa2\x61\x5a\xde\xd6\x3f\xab\x63\x8d\xe0\x6e\x30\x9e\x29\x3f\x8b\x68\xe1\x04\x4e\x17\x80\xc0\x75\x9e\xcf\x1f\x9a\x05\xb2\x1d\xfe\x0b\x6d\x33\x1f\x48\x8e\x7e\xb2\xc1\x1f\xdb\xca\x31\x72\x44\xfc\x27\xbd\xac\xd6\xd7\x31\xfb\x9e\xe0\xc7\xd5\x7f\x91\x4b\x72\x9d\x74\x9b\x73\x01\x4a\xd4\x4a\x0f\x73\xbe\xa3\xd9\xf6\xb3\xa6\x7f\xbe\xd6\xb8\x55\xd7\x05\xcc\xcf\xcd\xf5\x05\x10\x9e\x32\xb4\xf5\x14\x72\x5e\xa0\x2b\x68\x4e\x7a\x67\x96\xb1\x6c\x30\x27\x5c\x1c\x2f\x65\x91\xdb\x74\x58\xd4\x90\xd3\x76\x9d\x6c\x20\xc9\x6a\xe7\x63\x6d\x7d\x21\x51\xd6\x1d\xcf\xbc\x8e\xe3\x74\x23\xd4\xe6\x7a\x88\xb6\x23\x5d\x16\xdb\xd5\xda\x1f\xa1\x1f\xcf\x95\xd7\xde\x4f\x9c\xd1\xd7\x87\x6a\x45\xe1\x3a\x93\x23\x09\xf7\x36\x81\x6e\x3a\x3c\x91\x4e\xe7\x10\xcd\xd1\x75\xc7\x69\xb1\xa6\x8d\xe1\x18\xc9\x7b\x85\x7a\xde\x18\x0f\xb5\xd7\x31\xca\x9e\xa4\xea\xfe\xe3\xa3\xeb\x55\x56\xc9\xf2\x6c\xfd\x0c\x2b\xd1\x61\xc2\x4e\xf0\xc2\x57\xab\xe4\x8d\xc9\x68\xbb\xcb\x29\x4f\xa7\x32\x79\x6d\x45\x6c\xd9\xa4\xaf\x41\xd6\xd5\x37\x1f\xa4\xa5\xab\x59\x51\x70\xf0\x15\xf6\x06\xb1\x66\x42\xac\x8a\x3c\x38\x8a\x9f\x85\xbb\x3b\x02\xc6\x1f\x05\x8f\xe5\xf4\x96\xf8\x27\x67\x4b\x52\x35\x6e\x99\xf6\xcc\x06\xe6\xbd\x0b\xc1\x54\x40\x09\xae\x6e\xbc\x2a\xb6\x17\x83\x21\x3d\x16\x61\x35\x7f\x89\x9e\xac\xa2\xa1\x83\x88\xb0\x5a\x7e\x43\x57\x97\xd1\x50\x5e\x44\x58\x2d\x58\x66\xa7\x6a\xe8\xfc\x4e\x80\xc5\xb1\x10\xbd\x71\x34\xff\x4f\x12\x06\xc1\x49\x40\x15\xf9\xe8\x53\xd2\x12\xfa\xc0\xfb\x7d\xf2\x58\x68\x2f\xed\x3e\xdc\x2c\x62\x96\xe3\xe7\xf3\x38\x39\xb5\xc9\xf4\xee\x2d\x3a\x47\x7c\x05\x57\x05\x91\x92\x29\xdd\xde\x62\xdf\x1f\xfb\x41\xc7\xea\xf8\x35\x47\x93\xde\x3c\x2a\xd9\x95\xdb\xda\x3a\xc4\x9f\xa3\x06\x21\x14\x5d\x67\x6a\x7e\xab\x4f\x07\xdf\x26\xff\x8b\x55\x87\x4e\xeb\xa2\xb9\x38\xd7\xdb\x20\xae\xf8\x94\xe5\x87\x13\x67\xf1\x0c\x5d\x07\x2d\x57\x1a\x57\x7f\x28\x57\xec\x87\x4e\x49\xbc\x33\xba\xc3\x1a\x4e\xd2\xc6\x0e\x67\x72\xe3\x9e\x33\x7c\xb7\x92\x6d\x0d\xf2\x6d\x8d\xa0\x27\x3d\x5b\x6e\x94\xed\x9e\xac\x4d\x2c\x3f\xe6\x8c\x24\xb0\x08\xd1\x48\x44\xae\x93\x44\xb2\x2d\xae\xdb\x4f\x18\x3f\x35\x75\x08\x58\xad\x5d\xcb\x93\xec\x14\xd3\x33\xfa\x12\x1f\x37\xf9\x3e\xab\x17\x2a\xe6\x87\x77\x80\x01\x67\x3f\x9a\xa8\x95\x2a\x21\x92\xe9\xf8\xfa\x4a\x79\x54\xa2\x40\x0b\x55\xb3\x67\xce\xd3\x7a\xc5\xd1\x49\xf1\xba\x95\xcf\x5f\x17\xa4\x06\x85\x37\xd2\x26\xf2\x5c\x74\x8c\x10\x7f\xf0\x48\x2e\x1f\x59\xf1\x5a\xe6\x28\x34\x59\x27\xeb\x64\xc2\x0c\xd7\x54\x87\x0d\x91\x46\xb8\xd2\x73\xbc\x2d\xec\x71\x79\xba\x61\xad\x12\x37\x1b\xd3\x0d\x5b\x8d\x84\x36\x37\x4b\x26\xc3\x4a\x88\x2f\x24\xe0\xb1\x63\x2f\xc3\xd4\x78\x8c\x10\xf7\xbd\x5b\x17\xc4\x01\xa1\x80\xe1\xb6\x8f\x0e\x3b\x7f\xf7\xc4\xaa\xa2\x7a\x31\x1a\x46\x76\xf8\xa7\x5d\x47\x84\x27\xda\x8f\xea\x51\xaf\x42\x53\x4f\xc2\x03\xfb\x89\x0e\x95\xe5\xbb\xed\xe9\xfd\xd0\x86\x24\xd0\x01\x13\x79\x99\x28\xde\x13\xf0\x54\x53\x93\xfc\x2d\x18\x1e\x3b\x96\x68\xc5\xb1\x7a\xbe\xcc\x11\x54\x9a\xc8\x25\x44\xe1\xa3\xd7\x74\x73\x04\xa0\x88\x22\x89\x89\x3d\xea\x67\x77\x55\x12\x81\x75\x44\x3f\x62\xa1\x18\x24\x1a\x1e\x5a\x16\x72\xfc\x39\xe8\xf7\x47\xbc\xce\xeb\x3c\x99\x8c\x26\xfc\xc3\x91\x61\x3c\xc5\x76\x35\x9f\x93\x30\xd1\x5d\x19\x66\x25\x53\x17\xf2\x89\x08\x9e\x61\x1f\x7f\x6e\x2a\xf1\xd7\xeb\xd8\x8a\x9d\x9d\x1d\xb3\x6f\xd0\xbc\x62\xda\xce\xfd\x82\x38\x70\x4a\x39\x9f\xc1\x82\xd8\xe2\xa0\x9a\xc2\x27\x98\x2d\x73\xce\x40\x86\x72\xd0\xf0\xeb\x84\x85\xbc\xa9\x54\xb0\xba\xa5\x41\x58\x81\xa4\x06\x49\x0c\xd1\x5c\x38\x6d\x5d\x7b\x83\x4f\x66\x0b\x95\x60\x23\x1c\xca\xd6\x13\x58\xb3\x54\x5e\x66\xba\x19\x35\xf7\xd4\x27\x27\x1b\xd9\xec\xc4\xec\xd0\x18\x16\xf8\x57\xca\x32\xcf\xb7\x20\x76\xc5\x73\x45\xe2\x5c\x7f\x9e\xed\x88\x51\x18\x73\xb5\x9e\x28\x99\xcb\x90\x40\x41\xe8\x14\x6a\x52\x14\x1e\x2a\x5a\xe8\xfc\x19\xb0\xe5\x61\x91\x88\xcc\xb3\xe8\x1c\x53\x6c\x01\xd1\x96\xa2\x52\x8c\x5b\xcb\xdc\x9c\x64\xbc\x2a\x29\x9d\xc9\xa9\xbb\x9c\xc0\x0c\x50\xe4\xc2\xa2\xc4\xbd\x48\x74\x18\xa3\x6f\xfd\xbc\x35\x9c\xf4\x38\x89\xc9\x2e\x84\xc2\x5d\xc0\x68\xcb\x5c\x73\xe0\xd0\x86\xd8\x8b\xe1\x0b\xda\x03\x10\xe6\xd7\x3f\x18\xf5\x56\x73\xf1\xd8\xe8\x68\x2d\x55\x83\x27\x89\x23\x45\xf6\x67\xf2\x89\xba\x6d\x5d\xf4\xc4\x32\x4e\x6a\x57\x6c\x19\xf6\x72\x6d\xa9\x5a\xcd\xe3\x12\x97\xa3\xc3\xc3\x23\x32\xe7\xf6\x42\x45\x18\x37\x35\x5e\x5e\x87\xa4\x03\x61\x34\x07\xda\x04\xc5\x77\x55\xa9\xed\x4b\xcb\x27\x67\x3f\x67\x65\x93\x7f\xc8\xdf\x13\x32\x31\x33\xce\xe6\xe7\xb8\xcc\xc7\xb8\x9b\x6f\x60\xd4\xd7\x6c\x4b\x7a\x50\x36\x5e\x97\x20\x88\x24\xf7\x24\x39\x4e\x8a\x90\x14\x8b\x57\x76\x67\x32\xf9\x48\x02\xcf\x8f\x93\xaf\xe6\x43\x52\xef\xdf\x9c\x61\x37\x46\x0e\xa1\x2f\xe3\xb9\xf1\x33\xf1\x5c\x38\xad\xfb\xad\x46\x84\x5c\xb9\x2f\x7a\x0c\x50\xcc\xef\x2f\x3f\xfd\xbd\xec\x1e\xe8\x07\xee\xa7\xe9\xf5\x7b\x78\xd6\xe3\xd3\xbc\xf7\x5d\xaf\x0f\xb3\xbe\xbb\x00\xf9\x89\xeb\x17\x2f\xb4\x17\x5e\x39\xfa\x40\x37\x63\xa3\x7f\xde\xa5\x0e\x1a\x47\x1b\x3c\x48\x17\x6f\x7e\x97\x46\x8a\xf2\x21\xcc\x36\x94\x3a\x86\x6a\x99\x2a\x9a\xaf\x4e\x62\xda\x6c\x4e\x79\xba\x89\xd7\xc3\x43\xc4\x63\x47\xa1\xdc\x64\x32\x5b\x64\x37\x86\x57\x34\x5d\xd3\x0a\xd1\x35\xc0\x34\x69\xcd\x32\xa9\xa6\xc1\x2a\x1a\x80\xdd\x68\xd1\xef\xfb\x70\xb9\x1c\x2a\x82\x1d\x1e\x39\xdb\xce\xd6\xf9\x6d\x59\x6d\xd8\xb7\x8a\x1e\xb7\x6b\x68\x22\x12\xc9\x8b\xc5\x8a\xa3\x57\xde\x0b\x21\xf9\xa8\x41\xf0\x8a\x61\x6e\xfa\xd9\x4a\xae\x7c\xeb\x56\xd7\x4e\xb8\x63\x7c\x87\x75\xaa\xdb\x1f\xef\x6a\x2b\xad\x27\xfa\x1d\xd3\xd0\x19\x37\xb4\x18\x15\x8e\xc8\x14\x0b\xb8\xe4\xd2\x28\x27\x74\x63\x6e\x56\x84\xe3\x64\x13\xaa\x1b\x55\x63\x9e\x0c\x8c\xea\xf7\x29\x90\x49\xe2\x95\xb5\xc0\xe3\x1b\x38\x28\x29\xf5\x4b\xdf\x0f\x19\xce\x96\x39\xdb\x55\x27\xd7\x1c\x18\xb4\x8f\xd5\xba\xc1\x1a\x6a\x84\xe6\x3f\x56\xd7\xa4\x40\x42\x92\x1d\x4f\xcf\x45\xe0\x10\x47\x0d\x19\x2c\xe0\x63\x43\xa4\x22\x51\x5b\x62\xb8\x24\xdf\xf5\x15\x39\x19\x74\x64\xd2\x86\x89\x3d\x94\xe4\x58\xa6\x20\xe0\x64\x4c\x83\x90\xea\x17\x4d\xff\xe5\xe9\xcd\x8b\x08\xb2\x82\x68\xdd\xe9\xb3\x7e\x88\xc9\xf8\xca\x6c\xa3\x63\x8e\x2e\x14\xe6\xcf\xd0\xb6\x9c\x74\xe8\x71\xd5\x0c\x3f\x59\x27\x7b\x12\x27\xde\x88\xea\x41\xe4\x63\x53\xf1\xfd\x56\x81\x4d\x18\xf6\x25\xa9\x6b\x44\x98\x0d\xac\x7b\xc6\xa6\xed\x18\x58\xe4\x3d\xde\x3a\xeb\xc6\x2a\x7c\xa4\xcd\xbc\x65\x22\xee\xee\xd1\xda\xe6\xe5\x7e\xc0\xe4\x4f\x76\x09\x3b\xaf\x47\x5f\x52\x1a\xcf\x9e\xfd\xf4\x5c\xbc\xd4\xdc\x47\x91\x24\x34\x3c\x14\xab\x89\x69\x65\xc5\x66\x33\x7f\xbd\xd2\xc6\x50\x68\xb4\x48\xb6\xfb\x62\x30\xd2\xe8\x36\xc4\x8e\x55\xba\xbe\x92\x18\xb7\x73\xfb\xc1\xb2\xb4\x4c\xd3\xa8\x9f\x1a\x97\xa8\x51\x1e\xf3\x7c\x5f\x50\xe6\xd1\xca\xe7\xdc\x33\xc5\x30\x9e\x7f\x99\xb9\xcb\xf6\x1b\x44\x1e\xad\xe6\xe2\x43\xbe\xd3\x04\x48\xef\xa1\xa1\x1c\xa2\xe9\xc6\x2c\x7f\x41\x31\x5e\x27\xdf\x4d\x34\x8b\x92\x1b\x8b\xe8\xe4\x02\xdb\x5d\x25\xed\x45\x4a\x35\x33\xce\xe8\x95\x82\x0d\x2b\xcd\xaa\x42\x50\x1f\xc9\x5e\x24\x52\xba\xc6\x52\x0a\x44\x42\x2b\xc9\x4d\x2d\xed\xb2\x09\xb1\x73\x02\xda\xe0\x62\x8c\x52\x0c\x88\x56\x46\x65\x50\x05\x9f\x3b\x37\x8b\xba\x82\xae\x49\xf9\x13\xab\x6f\x97\xdb\x6d\xb5\xc2\x5e\xac\xd4\x4d\xa5\x8a\xfd\x8a\x6b\xdf\x0c\xc5\x2b\x2b\x5f\x9b\x95\xa2\xa0\xc0\x5b\x39\x4b\x9e\x92\x11\xc6\x12\xd8\x57\xa4\x83\x52\xba\x03\x76\x0b\x10\x7f\xdb\xa7\xad\x17\x14\x3f\x66\xc8\x71\x32\xca\x05\x73\xaa\xe1\x9e\x7d\xbf\x58\x04\xb9\x40\x79\x9a\x66\xab\xb3\xaa\xba\xc2\xc9\xda\x16\xc5\x48\xca\x2f\x3d\xf7\x98\x9b\x1b\xfb\xca\xd6\xaf\x8c\x41\x7e\x20\xfe\xac\x30\x06\xd5\xcc\x9c\x08\xf5\x19\x78\x72\x61\xa1\x20\x47\x44\xbf\x76\xab\x6c\xbf\x00\x51\xac\xae\xe9\x5a\x5c\x5c\x91\x44\x2c\x68\x95\x69\xbf\x4a\xe2\x14\x19\x5d\x26\x28\x41\x2f\x8d\x22\x46\x62\xdc\x17\x13\x80\x61\xd1\xc6\x9a\xbe\x08\x0d\x0c\x88\xe9\x6d\x32\xa3\x6c\x5d\x82\xe5\x89\x78\x24\xec\xfb\x92\xe8\x45\x35\x78\xcd\xc3\x90\x31\x78\xb5\x93\x7b\x99\x90\xd7\x05\x01\xb9\xe1\x41\x85\x31\x3e\x5e\x32\x9f\xe0\xe6\x5f\x96\xc6\xc2\x42\x65\x9a\x3b\x62\x96\xa2\x7e\xf3\xd6\x83\x29\xc7\xce\x8c\x32\xb3\x6a\x80\x8b\xd0\x20\x0e\x95\x72\xf1\x38\x5d\x27\x87\x37\xda\xf3\xb0\x0d\xf5\x8b\x89\xc9\x20\x62\x8c\x43\xdf\x68\xc7\xfa\x54\xe6\xc5\x64\x97\x87\xee\x98\xb5\x0c\xfd\x29\x04\xa6\x2b\x0b\x92\x89\xc5\x07\x6d\x44\x29\xb2\xf5\xd5\x2e\x35\x87\x31\xd1\x2d\x14\x00\xae\xfc\x1b\xce\x7c\x59\x79\xf5\xf1\x92\xe0\x2a\x12\x01\xb1\xba\x6f\x8d\xda\xa4\x1c\xf2\x4c\x13\x20\xa4\x06\xdf\xf2\x34\x41\xe5\xa5\xb9\x3d\x02\x0a\xc4\xf1\xf6\x54\x83\x98\xb8\x40\x7c\xcc\x58\x24\xa6\x15\x69\x1a\x6e\x2e\x4b\xdc\x49\x7c\xee\x52\x84\x02\xa0\xf7\x40\xdf\x50\x82\x86\xfe\xe6\x40\x85\x91\xdc\x50\x8f\xe3\xbd\x1c\x2a\xb1\x96\x1b\x8a\x61\xb2\x97\xc3\xf5\x04\xb6\x6b\x40\x0c\xce\xdb\x9f\x8c\x0f\x95\x7f\xaf\xa3\x94\x97\xed\x3d\x49\x9a\x84\x09\xe0\x3d\x9b\x6c\x17\x9b\xc1\x01\xbb\x8e\x5b\xbc\xa9\xbc\xd7\x92\x22\xc4\x68\xec\x58\x30\x8f\x51\xd2\x9c\x08\x66\x01\xa7\xfb\xcb\x92\xdc\xe2\xed\x8e\x96\xf7\x63\xdc\x1e\x3c\x1d\x23\x39\x60\x7c\x63\x4f\x7d\x24\x6f\x01\x3e\x65\xa9\x58\x3c\x8c\x60\x2c\xfa\x6f\xbe\x90\x11\xa9\x5f\xb1\xe8\x4b\x89\x33\x0b\xe7\x0c\x8c\x8d\x8e\x83\x15\x70\x96\x7b\x59\x12\xb1\x05\x87\x95\xe1\x1e\x41\x6e\x5b\xed\x19\x39\xab\x4d\xdb\x08\x0d\xa9\x54\x28\x21\x22\xbe\xa8\x06\x3f\x5a\xb0\x5d\x03\x83\x69\x05\x45\xc4\x6d\xb2\x0b\xc4\x9e\xc2\x3e\xd5\x27\x96\x86\x99\xe5\x7b\x47\xc8\x74\x9d\x1a\xaf\x20\xaa\xd7\x2a\x11\x7e\xa6\xfc\xeb\x9a\x79\xb9\x95\xeb\x60\x89\x27\xab\x41\xfb\x3f\xd9\x98\x23\x01\xfc\xd4\x29\x02\xb7\x10\x6f\xc6\x28\x24\xe2\xf5\xe3\xc8\x89\xdb\x95\x4c\x9f\x8d\xd4\xfc\x76\x59\x4f\x31\x6f\x1d\xbc\x9c\xf3\x5f\x3c\xec\x2f\xc7\x90\xb8\x01\x4d\xca\x28\xb9\x80\xb4\x14\x57\x7f\xe8\xaf\xe8\x97\x91\x51\x91\x27\x5e\xea\x1b\x23\x30\xfa\x4d\x7c\x97\x33\x7d\x78\x37\x74\x91\xc9\x3c\x88\xce\x61\xfe\xd6\x40\xbe\xcc\xbb\x00\xcb\x48\x9d\x6c\x8f\x31\xc7\x3e\x81\xc0\x1e\x9f\x26\x20\x2e\x13\xd4\x6d\xf3\x76\xa2\x9a\x21\x2a\xe0\xf4\x29\x24\xf3\x7a\x9f\xdc\x6d\x72\xc7\xd8\x74\xbd\x85\xb4\x15\x28\x88\x3a\x1e\xb0\xb7\x83\x47\x88\x1c\x47\x87\x62\x65\x56\xa6\x77\xa2\x69\x24\x43\xbe\x4f\x31\xf4\xf8\x10\x20\x90\xd0\xdb\x63\xe7\x5a\xdc\x5a\xec\x3c\x47\x63\x3c\x7a\xac\xfe\x40\xb1\x3a\x03\xab\x4a\x2d\xc0\xd5\xc4\xdf\x5f\x60\xe8\xa9\x03\x38\x80\xa1\x99\x7e\x0e\x80\xda\x86\x88\x0c\xe4\x4d\x16\x8a\x09\xa7\xa9\x03\xe8\x29\x0d\x75\x45\x8d\xb4\xb3\x91\x02\x73\x59\x31\xf2\x8d\x8c\x42\xb5\xa3\x37\x16\xd7\x34\x77\xdf\x30\xeb\x47\x97\xd3\x35\x89\xc1\x7a\x8d\xc2\x05\x41\x30\x1f\xef\x7c\xd0\xa0\x96\x9f\x5b\xa7\xe4\x40\x9c\xc4\x56\xf7\xcf\xdc\x9f\xec\xfd\x9f\x51\xcd\x16\x71\x5e\x40\x57\x01\x9c\x72\x2d\x8e\xfd\xd2\x55\x8c\x9e\x4f\xed\xb7\x03\xd9\xfe\xc5\x24\x39\x27\xe7\xc8\x49\x42\x6a\x66\x60\x35\x0d\x9b\x22\x14\xd1\xa6\x0e\x59\x78\xc8\xf8\x5a\xef\xf4\x20\x81\x55\xee\x4f\x2f\x26\x38\x33\xdf\xdc\x2c\xc8\x38\xce\x0e\x6b\xac\x32\xe2\xfa\x1e\x26\xa7\xbe\x20\x27\x99\x3f\x9a\x65\x45\x76\x87\x24\xce\x19\xd5\x4c\x60\x8f\x42\x10\x89\x25\xb6\x3d\xb3\x54\x87\xbd\x66\x74\x46\x35\xe5\xaf\xbe\x38\x91\x2e\xc5\xcf\x1b\xbf\x3c\x31\x3d\x3e\x8e\x30\xcb\x47\xc6\x20\x08\x37\x02\x01\x7a\x40\x4a\x79\x96\xaf\x7e\xc2\xe5\x70\x29\x67\x1f\xd4\x2c\x67\xed\xd9\x59\x1b\x4c\x2e\x24\xb9\x2c\x1f\xab\x05\xf7\x20\x97\xc6\x2d\xde\x3c\xa0\x7f\x6b\x17\xce\xf9\xd2\xf9\x7b\xce\x7f\x79\xfc\x63\x2a\x30\xae\x32\xc6\x2f\x71\x31\xa7\xb5\xce\xe1\xf2\xbb\xc1\xab\xa2\x93\x12\xbf\x67\xc2\x0f\xeb\xba\x16\x81\x83\xe0\xe4\x4b\x16\xbe\x95\xf1\x4d\x26\xc0\x52\x3c\xe8\x0e\xe5\xc7\x37\x78\x43\xe6\x9e\x79\x5b\x4d\xf4\x96\xca\x9b\x0d\x23\xcd\xba\xf9\x00\x8e\xa3\xe7\x44\x18\x79\x61\xb9\xfe\xa9\x33\x5c\xae\xa7\x77\x66\x9e\x77\x72\xc8\x11\x46\x3c\x47\x9a\x57\x3e\xd9\xc4\xb8\xbf\xb7\x4d\x13\xb3\x5d\x0b\x5c\xb3\xa8\x4e\xf8\xd8\x1e\xb0\x73\xb1\x57\xdd\x8d\x64\x9d\x3c\xd3\xa1\xfb\xd2\x00\x83\x57\xe5\x00\xbc\x9d\x08\xaa\x30\x36\x34\xdf\xfe\x74\x07\xd5\xc8\xb4\xef\xd0\x76\xf0\xc8\xbb\x30\x3e\xd4\xaf\x0c\xcc\x04\x88\xef\xd0\x3b\x20\x04\x08\xbd\x93\x29\x66\xaf\x23\xaf\x2a\x09\xa2\x32\x3c\x02\xfb\x0e\x68\xfd\xcd\x20\xf7\x1f\x7e\x27\x42\x18\xc2\x77\xac\x0b\x92\x0f\xba\x6d\xa2\x48\x2f\xe2\x19\x9c\xbd\xd3\xec\xb7\x03\x90\xaf\xe1\x77\x71\x4d\xb0\x1d\x0f\xf0\x14\xc9\xd8\xf6\x6f\xee\x67\x0c\x13\x10\x1b\x43\x29\xcc\xb5\x36\x37\xdb\x23\xe5\x88\x42\xc6\x53\x90\xf8\x3e\x5f\x2d\x15\x5b\xcd\xc4\x4c\x7c\x52\xbe\x52\xcf\xf1\x90\xcb\xd1\x6c\x14\x51\x83\x7d\xee\x1c\x5c\x54\xbe\x48\x29\x0a\x9f\x39\x46\x61\xb1\xbb\x22\x5e\xe0\x62\xa6\x41\x3a\x91\xdd\xb3\x51\x34\xb1\xbb\x27\x20\xca\x3d\xbd\x73\x4f\x09\x0f\xa1\x03\x10\xc3\xf1\x27\x83\x1b\x19\x40\x02\x2e\x9a\xe8\xd9\x59\x26\x38\x7a\x0a\x8a\x2c\x69\x37\x15\x1a\xb2\xb5\xa3\xea\xfd\x33\x79\xd8\xc1\x3b\x8d\x81\xeb\x55\x7d\x70\x2f\xdf\x49\x9f\x0c\x01\xeb\xff\x0b\x78\x56\xf9\x78\xd6\xde\x69\x6c\xf8\x46\xbd\x5a\xc5\xea\x66\x9b\xff\xcb\xf9\x68\x58\xda\x63\x87\x98\xd4\xec\x1e\x2e\x62\x0c\xe8\xea\x42\x2a\xac\x7c\x26\xbf\xe2\x8f\x7c\x67\xab\xb7\x65\x2f\xca\x6b\xc8\x75\xbb\xfe\x76\x5c\x5f\x48\x87\xb6\x9e\x9e\x62\x82\xa0\x0c\x07\xfa\x64\xd9\x70\xe1\x47\x9b\xbe\x2f\xeb\x41\x9a\x7d\xf3\xc0\x08\xe3\xac\xac\x27\xec\xf7\x78\xc8\x9c\xae\xd5\x8b\xe1\xb9\x3b\xd6\x45\xf0\xdd\xd8\xe9\x0a\xcb\x21\x57\xb8\xdc\xdf\xe8\x04\x07\x80\x6a\xcc\xcc\x7b\xaa\xed\x9c\xd9\x5a\x49\x24\xdf\x7a\xbe\x7b\x4f\xde\x14\x70\xaf\x1e\x3b\xe7\x78\xa6\x12\xb0\x3d\xd7\xba\x98\x71\xde\x7b\xfd\xd3\xf5\xa0\xf5\xc9\x35\xfa\x6c\x32\xb8\x33\x4f\x8e\x0c\xe5\x3d\x01\x19\xf9\x40\xed\x13\x6a\x86\x6a\x23\x0c\x13\xf8\x47\x59\xbf\x54\x93\x6e\xa1\x3e\xf9\x26\xde\xac\x0e\xaf\xcd\x23\x83\xcf\x43\x42\xcf\xa9\xff\x7a\x4c\x1e\x75\x79\xb5\xf9\xdd\x6c\x7f\x53\x1f\x02\xef\x61\xbd\x61\x97\xa5\xee\x30\xc7\x4c\x54\x76\x82\xc0\x33\x96\xe2\x2c\x8c\x32\x0a\xe5\x73\x64\x54\x01\x72\xe7\x55\x7d\x45\xdd\x03\x95\x9c\xdd\x6c\x00\x31\xe0\xb7\x7a\xa2\x60\x58\x0f\x61\x2a\x68\x7b\x1f\x9a\x71\x1a\x69\x75\x55\xe3\x5c\xde\x1a\x16\xaa\x22\x4c\xfe\xba\xd0\xb4\x40\xf9\x54\x95\xd6\x58\x00\x00\x40\xff\xbf\xd9\x52\x55\x87\xbe\x46\x03\x67\xf6\x5d\x73\xe5\xc4\xdd\x17\x45\xc1\xce\x14\xb3\x35\xab\x56\x30\xdf\xcb\x58\xac\xd2\x16\x2f\xc6\xef\x75\xeb\xb5\xc6\x6b\xba\x7a\x85\x9d\x42\xf5\xbc\x27\x07\xd9\x83\xc0\x4a\xba\x78\x19\x1b\xa2\xcc\xe7\xdf\x1c\x09\xe6\x49\x7a\xf3\xee\x01\x80\xd2\x37\xfa\x8a\x91\xf5\x8d\x92\xd2\x59\xfe\x86\xce\x95\xed\x31\x74\xb4\xbf\xb6\x79\xaf\x88\xb7\xce\x9a\x5f\x7d\x81\xa1\x7c\xb4\x78\x6d\xe3\x5b\x04\xc0\x78\x02\x4a\x7d\x7a\xfc\x6c\xf3\xc8\xfe\x44\x9b\xd7\x56\x97\xfb\x86\x72\xf3\xd7\x63\x73\x64\x73\x71\xba\x76\xe5\x5b\x91\xe3\xb7\x26\x11\x8e\x8e\x60\x9f\x6f\x55\xb6\x7f\xb8\xbe\x6c\xeb\x3f\x07\x3c\x1c\x6a\xdb\x43\xf4\x21\x09\x4f\x65\x12\x71\x42\x0e\x93\xb6\x3d\x99\x4a\xdc\x5c\x9c\x1e\x60\x9e\xc4\x4c\x72\xb1\xe5\xad\x88\xe1\x64\x31\x4d\x68\x1d\xf7\x6f\xab\x77\xd1\xd1\xb9\x4b\x69\x06\xea\xc4\xa3\xea\x64\x8a\x95\x2a\x3b\x5e\x18\xd2\x8b\xcb\x18\xbf\x24\xb5\xb5\x78\x48\xb1\xef\x18\xc7\x55\xb8\xb3\x55\x60\x5d\x47\xb5\x6b\x43\xad\xea\x86\x82\xe6\xec\xf7\xb3\x03\x06\x9a\xb1\xfd\x4f\x98\xed\x51\x53\x85\x43\x95\xe2\x77\x93\x6f\x8f\x16\x0b\x67\x7e\xe1\x1f\x79\x47\x38\x50\xef\x99\x7b\x7b\x48\xae\xbf\x2e\x24\xf5\xfb\x17\xdf\x15\x36\xc5\x21\x16\x11\x7d\x08\x1c\x64\x34\x2c\x71\x1f\x3e\xe4\x60\x16\x80\x04\x6c\x6c\xb5\x55\x4d\x42\x52\x93\xb9\x50\x65\x02\x86\x32\xe6\x41\x8d\x31\x52\x84\xb9\xe2\x48\xfc\x71\xbc\xe1\x6c\x08\x42\x90\x51\xbf\xa6\xa6\x24\xd2\x57\xa3\x25\x89\xc7\x62\xe2\xb7\x68\x42\x89\xb2\xf9\x0e\xc3\x9a\x56\x1c\x40\x28\x3f\xfc\x1d\x1d\xb6\x7f\x46\xf7\x08\x9e\x41\x98\x51\x7d\x3c\x47\x44\xf4\x32\x1c\xc2\x1a\x3a\xac\x0f\x65\x40\x90\x66\xd4\x24\x22\x03\x8d\x17\x38\xe2\xbd\xf7\xc8\x8d\x46\xfa\x97\xa6\x99\x66\xf3\xeb\xb7\x35\x60\xbc\xea\x7b\xa9\x15\xc0\x82\x0c\x4b\xf4\xf5\x75\x76\xdc\x5c\xa6\xcf\x58\xe7\xb5\x2b\x98\x9f\xf2\x0c\x76\x08\x6a\x13\x85\xe0\xb6\x02\x5e\x34\x3d\xde\xcf\x30\x33\x4f\x93\x83\x28\xe0\xe9\xfa\xbe\xda\x30\x2d\x49\x87\x8d\x66\x4b\xd1\xf5\x52\xa0\x11\xc8\xc7\x6f\xb0\x9b\x82\x4f\xa8\xbc\xcd\x69\xe3\x32\x13\x06\xc2\x29\xd8\x86\x07\x14\xb3\x47\xf2\xc7\x9e\x0a\x58\x3c\xd1\x12\xc7\x98\x65\xc7\x6c\xe7\xea\x1a\x6d\xa3\xc5\x53\xcd\x5c\xa0\xe7\xf6\x87\x50\xcc\xdc\x21\x21\xfa\x6f\x78\xee\x24\xc3\x2b\x0c\x17\x89\x08\x83\x04\x3e\x64\x6c\xed\xc5\xe0\x2b\x8c\xe7\x9d\x62\x8a\x9b\x10\xe1\x4e\x49\x4d\x03\x16\xc3\x64\x54\x22\x2b\x18\x0e\x82\xc6\x8c\xb9\xb0\x18\x6f\x30\xed\xc5\x60\xc4\x18\x38\x39\xc1\xfe\xd7\xcf\xfc\x5c\x7c\x35\x20\xde\xa3\xf4\xbb\xd8\xa6\x28\xc7\xfa\x93\xa0\x8b\x92\xd8\x79\x0b\xf1\x6a\xa5\x71\x94\x19\x6d\x28\xb2\xec\xf7\x80\xe6\xd3\x3c\x5c\x47\x91\x09\x15\xde\x32\xd7\x07\xe9\xf1\x64\x54\x9e\x18\xf3\x50\x9c\x97\x30\xaf\xf4\xe8\x24\x88\xa7\xb6\x6e\xcf\xe5\x1f\x40\xa1\x0a\x02\xc4\x92\x21\x01\xd7\x58\x0c\xbf\xe3\xba\x95\x9f\x96\x96\x1c\x8d\xd3\x4e\xe9\x83\xc6\x19\x6b\xd5\xb3\xad\x78\x69\x6b\x69\x90\xf6\xde\xf3\x9c\x7f\xdd\x9d\xcd\xa8\xd1\x9b\x22\x30\x3f\xce\x5e\x32\xe5\xb6\x58\x46\xe7\x8d\x2c\x7b\x73\xc0\xe6\x72\x5f\x65\x10\x40\x56\xae\xfa\x15\x92\xc1\xf1\x92\x79\x9f\x67\x88\x92\x14\xfe\x1a\x13\x0c\xce\x4e\xca\x5f\xe7\x69\xf4\x08\x8e\x97\xfb\x77\x02\x71\xbd\x3b\x58\xda\xc8\x1c\x45\x44\x83\xa0\x5c\xa1\xad\x62\x31\x1a\x1e\x47\xa3\x92\x28\xb6\xa4\x10\x8d\x8a\x52\x73\xd7\xc0\x92\xaa\x54\xc5\xcb\xdd\xf4\x3c\x1b\x5c\xda\x89\x51\xfe\xf9\x91\x02\x32\x74\x54\x09\x83\x3b\x97\x9f\x0b\x60\x92\xd5\xdc\x5b\x1b\x07\xd9\x2c\xb0\xea\x41\x6b\xbe\xa3\x4b\xa3\xea\x62\x44\x6c\x23\xe3\x62\x38\xcd\x2c\x5d\x99\x69\x5c\xac\x9b\xb1\xfe\x7c\x6b\x43\x89\xd9\xe5\xd0\x78\x4c\x71\x7e\x72\x16\xdd\x0a\xd4\xce\x86\x3e\x7c\x8b\x7a\xcc\x8c\xbb\x0f\x42\x8a\xdc\xc3\xc9\x61\x9f\xe8\x62\xc4\xf7\x3f\x61\xdf\x10\xf0\x80\x87\x61\x0e\x67\x33\xbc\x30\xa0\xe8\x0e\xd2\xe3\x28\x09\x6a\xea\xdc\x22\x46\xb5\x41\x2a\xed\x7b\xdf\xa3\xcb\x64\xb4\x5d\xc5\x99\x2b\x58\x48\xe6\x94\x7a\xc0\x73\xff\xd9\xd6\xf7\x0b\xe5\x0b\x5a\xa9\x02\x53\xe9\xe2\x4c\x1d\x0f\xe0\x0e\x75\x3a\xa7\x99\xcb\x85\xe1\x29\xd2\xd2\xb2\xc0\xdd\x6e\xb8\x4a\x1c\x8e\x45\x42\x0f\x6e\x53\xbe\xf6\xec\x0f\xb4\x3e\xc4\xa6\xf1\x02\x13\x93\xfa\xc2\xcd\x09\x6d\xfd\x68\x2c\xf2\x52\xcd\xfb\xe7\xdd\xd2\x54\x8a\x7e\x7d\xe9\x39\x2c\x09\x90\x2f\x82\xa5\xa7\xbe\xe2\xfb\xb5\xaf\x2e\xee\x84\x02\xe1\xfd\xaa\x48\x80\x7e\x85\x21\xc5\xe0\x85\xcb\x60\xd2\xd7\x02\x45\xf9\xbb\x0f\xbc\x18\x78\x19\xfb\x14\xf8\x14\x4f\xf9\xdb\x96\x20\xdb\x1b\x6d\x04\x77\x01\x49\xb0\x6c\xea\xa7\xb4\xd1\x91\x55\x7a\x9d\x7a\xf6\x6b\x2a\xbd\x2a\x7c\x6d\xe5\x99\xca\x02\x2a\x0b\x2e\x3f\xfd\xf5\xf7\x7e\xe5\xfc\xbe\x0d\xc8\xe5\x63\xeb\xf8\xb9\xc0\x02\x68\x70\xd7\xd3\x3f\x65\xcd\x59\x97\x5d\xb9\x2a\x48\x7c\xcc\x9b\x31\xcf\xf4\x91\xf9\xc8\x65\x3f\xa9\x56\x3b\x09\xd8\xa7\x09\x0e\x32\x11\x9a\x50\x51\x56\x88\xbc\x92\x6c\x57\x36\x6d\x1c\x35\x4f\x11\xa4\x33\x1b\x27\x03\xdb\x5e\xfd\xa2\xab\x1c\x78\x13\x12\xe0\x2c\xa8\xd2\xb9\x1b\xb3\x61\x29\x54\xec\x99\xf3\xa5\x65\x55\xfb\xae\x73\x31\x30\xab\xdb\xd9\x16\x84\x66\x74\x39\x17\x13\x80\xfc\x80\xc3\xfe\x1c\xfc\x54\xbb\xae\x7b\xd2\x21\xb0\x8a\x4c\xc0\xa7\xd1\x40\xef\x4f\x4c\x8e\x97\xd5\x74\xc7\xbd\x21\xc9\x0e\xfa\xb9\x5e\xe3\x4c\x21\x74\xad\xe6\x69\x20\xf6\xa4\x96\x5e\xb8\xf9\x3a\x43\x12\xf8\xcc\x52\xee\xd6\x09\x82\xbd\x99\xf0\x4b\x9c\xfd\x0d\x12\x3f\x32\x54\xc9\xea\x59\x78\xff\xdb\xa9\x46\x71\x23\x1d\x30\x85\x8a\xb0\x0a\x3c\xf2\xbd\x16\xaf\x68\xd1\xad\xce\xfa\x9a\xf5\xc3\x29\x99\x06\xf5\xae\x1b\x6b\x65\x73\xb9\x61\xbd\x54\x93\x6c\xd5\xf1\x0d\x78\x83\xb5\xaa\xc9\xff\x01\x39\xb4\xf1\xbd\xd2\x64\x8f\xc9\x25\x2b\xfe\xb3\x62\x38\x58\xfd\x5a\xca\x20\xeb\xc8\x3b\x67\x9d\x03\x76\x38\x0c\x6e\x17\x37\x93\xcf\xbb\xd4\xd8\x61\x93\x80\x26\xbd\x5e\x1c\x8a\xc1\xd4\x6f\x9c\x62\x7b\x77\x09\x4f\x4f\xe1\x03\xfb\x15\x37\xbf\x6a\xcf\xaf\xb7\xd8\xb2\xce\x9e\xc0\x05\xc3\x2c\xe9\x7e\xa2\xf3\x57\x59\x16\xbe\xf0\xd8\xbb\x71\xc3\x8e\x7a\x9d\x1b\xb0\x8e\xb3\x56\x6f\xce\xbb\xe9\x67\xc6\x27\x35\xc2\x8d\xf7\x28\xab\xea\x22\xd5\xa5\x0c\xc3\x0a\xfe\x41\x96\xd3\x83\x06\x5b\x9d\x3a\x94\xd3\x50\xbf\xf1\x7c\xb9\xd3\x92\x2b\x3e\xa4\xf2\x23\xd1\x06\x32\x3f\x24\x4d\x6e\x64\xbd\x75\xea\xc0\xa8\x65\xd1\x53\x9f\x4a\x25\x9f\x8c\xad\xfe\x12\x65\xd8\x9e\x7e\x9d\xfd\x55\x9f\x71\x97\xd5\xf1\x18\x9a\x0a\xbc\xde\xb3\xd9\xd2\x88\x7a\xd9\x05\x52\x6e\xe0\xd0\xbf\x2c\x37\x84\x05\x8b\xcb\xb1\xe8\xf7\x12\xb5\xf7\xd1\xc5\xc5\x3e\x60\x17\xc5\x15\x06\x0a\xcd\x2f\xeb\x75\x46\x12\x67\x87\x87\x13\x4f\x67\x29\x50\xe7\x95\x4a\xf4\x85\x5c\x29\x58\x1b\xbf\x04\x6b\x20\x56\x46\x22\xf1\xe8\x03\x5c\x74\xf6\xd7\xd8\xca\x72\xd2\x02\x23\xf2\xd8\x77\x45\x5d\xb3\x73\x1a\xac\x3a\x59\xa0\x23\x6e\x87\x9a\x38\xc1\x80\x0b\x4c\x6d\x22\x36\x44\x1b\x8b\xda\x0a\x8e\x1c\x56\x00\x1b\xc4\xa1\xae\x48\x60\x51\x20\xe0\xaf\xa2\xaa\xe0\xa8\xd2\xaf\xee\xad\x51\x17\x6b\x47\x0c\xd3\xff\x5d\x01\xf2\x3c\x32\x92\x4e\x88\x3f\x9d\x91\xa4\xe0\x55\x0d\xe7\xd0\x26\xe4\x19\xf2\x7c\x86\x61\x95\xb9\xbd\x02\x5f\x47\xdc\x8f\xb1\x7d\x9b\x64\x69\x9f\x21\x90\x3a\x60\xc8\xbe\x05\xe5\x85\xd1\xc1\x1b\xa1\xf8\xf5\x5b\x04\xed\x5c\x2c\x59\xa9\xc4\x5d\x4a\xb3\xba\xfe\x19\xe9\xcf\xb9\xdf\x90\x88\xac\xc4\xc3\xac\x7e\xbb\xb6\x97\x4f\x10\x11\x93\x9e\x1c\xde\x41\x25\x3e\x9d\x0b\xb6\xf1\x99\x04\x5d\xd5\xe4\x13\x32\x50\x99\x6c\x35\x70\xb8\xe0\x4f\x93\xc3\xd1\x90\x08\xf6\x81\x5b\xca\x80\x34\x4f\x40\x9f\xc2\xa1\x11\x2c\x00\xc7\x00\xd2\xac\x8a\x87\x83\x2d\x83\x2c\x19\x99\x34\xbd\x1d\xec\x58\x37\x9f\x2d\x23\x3f\x90\x33\x92\xb8\x04\x7f\x7b\x1e\x1f\x8b\xfd\xa9\x16\x4d\xce\x87\xdf\x43\xbf\x8d\x31\xce\x38\xa3\x15\x61\xbd\xaf\x1e\x59\x29\xb3\x4d\xbf\x22\x6b\xea\x13\xad\x61\xe6\x5f\x3d\x34\xa7\x4a\x71\x4d\x85\xe5\x3f\xa2\xcc\x6e\x68\x36\x8e\x6b\x8a\x1d\xc9\x9c\x98\x10\x9d\x50\xff\x1a\x20\x10\x09\x9a\x32\xa0\x3b\x89\x33\x0c\xb3\x67\x82\x34\x01\x1e\xd5\x8d\x5a\xd0\xa6\xd3\xa9\xa7\x47\x5a\xec\x6b\x28\x6d\x8d\x0c\x70\xb6\x76\xab\xeb\xa6\x0c\x72\x69\x5a\x11\x46\xcd\x7d\x8a\xb8\x8b\x69\x3a\xc9\x2f\xeb\xfb\x9a\x10\x1d\x8c\x63\x7a\x50\x9f\xc5\x75\x56\xc5\x51\x39\x45\x8d\xd2\x26\x27\xcc\x2f\xec\x0b\x87\x91\x76\xe5\x9c\xf2\xad\xf9\x04\x3c\x80\x32\x86\xdf\xf4\xdb\x8a\xde\xf6\x8c\x16\x85\xe9\x59\x51\x29\x82\x6a\x2e\x1a\xcd\xf8\x48\x4e\xac\xfb\xa2\xda\x17\x31\x31\x99\x73\xcd\xd5\xca\x97\xad\xe9\x92\xe7\xd8\x8b\xe0\x7b\xe6\x0d\x9d\xa5\x27\x7c\xad\x6b\x83\xaa\x6c\x54\xab\x25\xef\x31\xf2\xea\xaa\x8b\x1d\x43\xa5\xcf\xdd\x67\xf6\x51\x55\x4a\x5b\xee\x27\xf2\xc4\x55\xfa\xd8\x94\xfb\xcc\x9d\x97\xd6\xb6\x7b\xbf\x38\x31\xe9\x20\x1f\x8a\x8d\x72\xa5\x6e\x9a\xef\xe2\x9a\xd2\xb9\x85\x12\xcd\x7d\x1d\xba\xce\x0a\x05\x3a\x13\x11\x00\x2c\xc4\xd0\xb9\xdc\xf7\x36\x1a\x58\x37\xa4\x9f\xae\xef\xac\x66\xac\xc1\x1a\x65\x9b\x27\x05\x0d\x07\x4e\x4d\x19\xa1\x15\x32\x70\x7c\x82\x34\xd9\xf4\x70\x36\x05\x90\xb6\x02\x56\x6e\xeb\x93\x81\x70\x26\x53\x3d\xc8\x5b\x2d\x20\xdf\x9e\xf1\xe0\xbf\x7e\x9d\x4e\x6a\xc6\x49\x9e\xb0\x9c\x59\xf5\x2f\x63\x60\x59\x41\x71\x36\x9a\x2d\xfd\x8b\x59\xae\x33\x30\x23\x56\x7e\x1a\x68\x07\x73\x86\xfe\x45\x50\x54\x3b\xa1\x75\x1d\x97\xf0\x62\x36\xd6\xf8\x86\x57\x44\x23\xc5\x07\x4e\x31\x6f\x3e\xc1\x19\xea\x29\xce\x98\xa9\xff\x43\x1b\x78\x34\x8c\x24\xb5\x2f\x6a\x08\x6c\x31\xf7\x0a\x79\x97\x2e\xd8\x2f\x9b\xad\xf2\x2c\x97\xee\xf2\x8d\x52\x72\xd7\xf9\xe3\x96\xd0\xf7\x5b\x59\x45\x2a\x47\x10\xd0\x95\xe2\x4b\x6d\x2f\xfd\x7c\x37\xfd\xc7\xee\xfc\x0b\xef\xfc\xdf\x53\x49\xb8\xea\x82\x53\xc6\x97\xb8\x71\xa6\x46\xd5\xd7\xe3\x8d\xb9\xf8\x8c\xa8\x36\xfd\xcc\x15\x05\x3a\x05\x63\xe6\xfa\x56\x73\x07\xc2\x0b\x40\xd8\xea\x77\x9a\x80\x2b\xda\x6b\xff\x31\x81\xc4\x63\xcd\x1c\xcf\xf5\x61\xc3\xad\xe2\xe9\xc9\xfe\xa4\xe1\x77\x1e\x30\x0b\x3a\x59\x35\xcd\x51\xb4\x22\x0a\xc0\x8a\xea\x9f\x2b\x16\x67\x22\x12\x25\x2a\x1e\xa3\x32\x1a\x01\xe9\x74\xcb\xf5\x9a\x60\x8d\x47\xa5\x90\xdd\xb4\xa5\x0d\xc0\x66\x3a\x68\x4e\x33\xec\x16\x33\xc6\x16\x5e\x05\x86\x7e\x3c\x50\x10\x03\x4d\xfa\xbf\x5a\x00\xcb\x04\x2a\x77\x82\xf9\xc6\xcf\xd6\xd2\x90\xf2\x49\x30\xa0\x16\x70\x21\x22\x60\x81\x50\x53\xe6\x02\x0b\x4c\xe8\x03\x15\x36\x0b\x0a\x36\xac\x4f\xdc\xd4\x13\x7b\x03\x26\xb8\xbc\xad\x60\x28\x89\x02\xdb\x85\x92\x13\x05\xbf\xb9\x4d\x71\x0b\xb4\x61\x50\xc8\x06\xcc\xd8\xd9\x3d\x50\x9b\xeb\x5a\x5f\x5d\xa3\xde\x70\x76\xf5\x57\x91\x7f\x7b\x6d\xaf\x68\x3a\x0d\xf5\x55\x0c\x75\x06\x2c\x0a\x41\xe9\x87\x6a\x39\xf4\x5e\xf7\xab\x2a\xef\xa5\xd5\x04\x37\x23\xed\xc0\x43\xaf\x66\xa5\x05\x9c\x5d\xb7\x11\x8c\x10\x14\x67\x72\x8b\x7b\x4e\x59\xbc\xb2\xb4\x20\x35\xac\x8f\x14\xc4\x1e\x24\xa0\x4f\x80\x08\x65\xfe\x0d\x47\x6e\xc5\xc6\x73\x98\xe1\x24\x8a\x8c\x5c\x06\xef\x69\xfb\x60\xe3\x44\xd6\xd8\xd9\xd1\xed\x3f\xb4\xdf\xbe\x05\x3b\xf2\x00\xea\xe8\x77\xdc\xcc\xeb\x35\x55\x82\x78\x6a\x7e\xee\xb4\xcc\xa6\xd6\xdc\xb5\x86\xaa\xa7\xf4\xd6\x9d\x9f\x3e\x87\x79\xd3\xa9\xdf\xf6\xe0\x29\x1c\xd2\x6f\x29\x6c\x2a\xde\xee\x91\x48\xf0\x2d\x1d\x96\x3b\xfb\xc8\xf4\x03\x03\x2b\xd9\x7c\x91\x18\xd2\x2b\x5b\xa5\x8a\x2d\xd9\xd8\x15\x5a\x47\xae\x13\x58\xf9\x66\x7e\x3c\x46\x89\x86\xc4\x5f\xce\xf4\xcc\x9d\xe1\x1c\xf7\xfd\x8e\x7f\x72\x1d\xbd\x66\x5e\x05\x10\x52\xcc\x05\xbe\x0d\xdf\x82\x8b\x34\x2f\x29\x2b\x8e\xd8\x31\x4c\x61\x31\x50\x15\x45\x76\x7e\x1a\x92\x3a\x2b\x4c\x3e\x8e\x12\x4d\xc6\x65\x95\x62\x37\x0f\x35\xa4\xb7\xd3\x5b\x09\xde\x48\x6f\x16\x7d\x70\x10\x03\x69\x38\x7f\xf1\x3b\x1d\x60\x7f\x94\x24\x90\x37\xbd\x98\x7e\xef\x59\x77\xa2\x34\xf7\xe5\x52\x79\x70\x06\x4a\x92\x73\x88\xa2\xaa\x03\x82\xbd\xe0\xc1\x87\x86\x02\x7d\xd8\x21\x2a\x59\x66\xd7\x7e\x91\xb0\xf1\xb0\xea\xa6\x57\xf9\x81\x5d\xb4\x54\x4b\x56\x18\xe0\x30\x46\x79\xf9\xda\x6c\x83\x1b\x89\x24\x22\x99\xcf\x5c\xd6\xf9\xc2\x41\x1a\xbb\x83\x45\x3f\xfe\xa2\xd4\x04\x57\x0d\x2c\xdd\x5b\x62\xf2\x12\x1e\x30\x71\xf9\xe6\x10\xd3\x2e\xfb\x7c\x97\xcc\x78\xb5\x5a\x1e\x8d\x2f\xca\xcb\x81\x04\xc1\x95\xff\x5d\x92\xf0\xd5\x50\x2a\x34\x1a\x03\x94\x24\x2a\x28\x93\x94\xc1\x89\x08\x19\x52\x37\xd1\x01\xb4\x4c\xa0\x26\xbe\xa2\xe0\x12\xe5\x60\x67\x6f\x10\x54\xdc\x91\x2e\x19\xa2\x24\x9c\x56\xcc\x87\x89\x68\x16\xb5\x55\xee\x4c\xf0\x48\x6e\xa8\x65\xbe\xfa\x69\x5f\xad\x22\x81\x93\xd8\x03\x6f\xdf\x81\x00\xfd\x16\xb7\x65\x2a\x6d\x62\xee\x9d\xe4\x44\x32\x9a\xa3\x96\x75\x7b\xf4\xf4\x1e\xdd\xb9\xd1\x88\x0d\xdf\xb6\x5c\x1b\x9f\xa8\x89\xef\xd8\xbf\xe8\xa9\xec\x84\xd9\xed\x5a\xa7\x44\xc7\xdc\x9a\xc6\xf4\x0a\x76\xe8\x7a\xfe\x0e\x31\x55\x6c\x87\x10\xe0\x52\x6c\x2d\x77\x6b\x32\x56\xf9\x78\xd9\xd5\x91\x3b\x9d\xd8\x80\x34\xfd\x30\x30\x85\x3d\xd4\x91\x78\x8f\x7e\xde\xbd\xda\xab\x03\x03\xd1\xd7\x0c\x6f\x32\x02\x52\xdb\x6d\x7f\xd4\x94\xb8\xd7\x3d\x7f\xde\xf4\x5f\x7f\x9d\xd1\x72\xd7\x1f\xfb\x96\x5a\x26\x96\xd7\x9f\x2f\x7f\x1b\xdf\xb8\xa7\x9d\xaf\xa1\xab\x28\xe7\xcd\x5b\xcd\xe1\x43\x7b\xe8\x25\x62\x5b\x66\x03\x85\x2e\xe1\xcc\x3c\x4e\x63\x30\x47\x32\xb8\xda\xbc\x6a\xab\xf7\x7e\x48\x92\xe5\x69\x44\x50\x9c\xc2\x63\x65\xde\x7f\x7c\x3a\x50\xdc\x37\x69\xc5\x2f\x71\x18\x97\xd5\xd7\x2d\xda\x8f\xa7\x1b\xcd\x7f\xfa\x5c\xec\x62\xd1\x37\x52\xf4\x3e\xaf\x5c\x6c\x24\x7d\xed\x56\x11\xb5\xf8\x82\xcb\xf7\xda\x86\x1f\x55\xf6\x9f\xc8\x1d\x2a\x42\x33\xfd\x6c\x94\x0e\x14\x52\x50\x66\xeb\x09\xd1\x64\x03\xaf\x27\x0e\xbe\xfa\xcd\x3c\x6a\xc6\xc1\x0e\x14\x45\xad\xec\xc2\xcb\x1f\x78\xfc\x0b\xf7\xb3\x7d\xc4\x36\x66\xad\x73\xd0\x17\x28\xc4\xb0\x53\xc8\xcb\x1b\xee\x65\x7e\x01\x34\x9e\x04\x55\xd8\xe0\xe8\x29\x11\xd3\x43\x31\xe5\x69\x8b\x73\x25\x43\xf5\xac\x72\xa3\x1a\x48\x22\xf7\x33\xd8\xe6\x0e\xda\xd8\x83\x1e\x29\x09\x94\x8b\x4c\x5b\xd8\xe8\xd3\xa9\x29\xcc\x6d\x6a\x0c\x14\xa5\x01\xe6\x03\x55\xed\x86\x1b\x03\xdb\xd9\x9c\x22\xfc\xfe\xc5\xd9\x49\x89\xa7\x52\x0b\xf0\xb7\xc6\x36\xcd\x57\x33\xae\x96\x6e\x50\xa5\xd7\xd1\x48\x8d\x87\xb5\xd5\xdf\x9b\x35\x51\x37\x73\x5c\xea\x40\xbf\x8e\x13\x53\x77\x95\xaf\xae\x52\x68\x14\xc6\x84\xf8\x65\x71\xea\xdc\x8d\x47\x30\x3f\xde\xbd\x7e\xfc\xd8\x91\x5a\x1b\x3e\xd5\x0e\xde\xd6\x02\x47\x4c\xee\xee\xe5\xdb\xd1\xc5\x63\x01\x5b\xc3\x64\xfd\x4e\x0a\x8d\x25\x43\x39\x8b\x58\xa5\x3c\xfa\x51\xed\xed\x5e\x69\xf9\xbb\xda\xef\x8b\x70\x2c\x55\x20\xc8\x91\x14\x17\x0b\x1f\x54\xc3\x89\xf6\x7e\x91\xed\x55\xae\x32\x17\x28\x27\x77\x7c\xd6\x2f\x9a\xab\x42\x33\x14\x00\xc2\xea\xb1\xd7\xe8\xe7\x4a\x08\x2c\xbb\x74\x0a\xea\x1e\xdc\xf1\xac\x57\x67\x4c\x4e\x24\xf2\x20\x5b\xc8\x56\xe3\xfc\x0e\x7c\xde\xbe\x99\x76\xc0\x68\x30\x58\x9d\x58\xfe\x0c\xe9\xec\x9a\xcf\xd0\x3c\xdb\x6a\x8e\x68\xe7\xf9\x9c\xb6\x19\x89\x6a\x30\xd0\xce\x7b\x72\x4c\x4e\x6d\xb3\xad\xe6\x5b\x5b\x4c\x1e\xf6\x33\x53\xb1\x24\x59\x08\x83\x11\xf7\xa5\xf1\xca\x88\x13\x7e\x0d\xdf\x87\xa5\x7f\x92\x91\x4b\x9e\xb0\xba\xad\xf1\x18\xdd\x21\xd5\x51\x45\x28\xd8\x8b\x9a\x93\x8b\xc3\xd9\x50\x3a\x26\x7f\x97\xf9\x7b\xaf\xc6\xbc\xd3\xac\x34\x73\xc5\x93\x89\x85\x57\x4c\x33\x41\x8c\x36\x85\x52\x0d\x11\x69\x76\x2d\x15\x37\x05\x53\x10\x3a\x9f\x4c\xb1\x33\xad\xb0\x65\x06\x9a\xf1\xee\xb9\x3d\x5e\xaa\x8b\x89\xaf\x19\xa2\xc5\xa6\x34\xcb\xb3\xbf\x34\x06\xc2\x4f\x43\xdf\xe9\x52\x7e\xdc\x90\x8c\x85\x4e\x4b\x30\x2b\x63\x24\x26\x33\x96\x4d\xb1\xfc\xd6\xe9\x75\x3c\x3a\xa5\x22\x15\x5a\x93\x94\xe8\x00\x2c\x9d\x8a\xc7\x6e\x32\x4e\x96\xc6\xd4\xce\x45\x47\x96\x10\xeb\xd1\x25\x57\xd5\xa9\x21\x60\x10\xdd\x03\x34\xd9\x89\xc2\x87\xfa\x1b\x0f\xba\x5f\xda\xce\x1c\x60\xd5\xea\x80\x7d\xb4\x2e\xf1\x4b\x71\xdf\xf4\xc5\x7e\x9b\x4a\xc7\x6b\xa6\xa7\x74\xb9\xca\x6b\xcd\xf6\x53\xc3\x79\x2a\xcb\x0d\xb3\xca\xfb\x29\xf7\x49\x8c\xf9\x6b\x24\x51\xee\x86\x8c\xde\xf6\x86\x72\xd5\x71\x33\x89\x54\x94\xb5\x7f\x29\x41\x0a\x52\x73\xfe\xc8\x3d\x5b\x44\xb8\x0a\x6a\x39\x1c\x71\xaa\xef\xe2\x76\x1e\x7f\xcf\x43\xdc\x6e\x6f\x03\xe2\x9d\x4b\x52\x1e\x32\x86\x76\xdf\x29\xc6\xcd\xd4\x31\x64\x9c\x63\x7d\x44\x99\x32\x6b\x3c\x39\x3f\xc0\x5d\x0e\x3b\xc4\x38\xfd\xa1\x7f\xfa\xba\x42\x52\x29\x78\xf6\xcb\xa3\x3b\x48\xd3\x69\xb4\x7d\x7b\xcd\x37\x34\x9e\xcd\xca\x17\x34\xcf\x8f\x5b\x16\xc4\x0b\x0c\xde\x3a\x67\x9a\x56\x07\x2d\x7d\x40\xb8\x20\xdd\xa1\x1a\x5f\xd7\x80\x4a\x50\x7a\x17\xa5\xb3\x8f\xfa\x87\x8d\x95\x58\x3b\x97\x29\x61\x44\x4a\xcd\x3f\xa5\x8f\x9c\x5c\x15\x23\x58\x92\xc1\xec\x72\xe9\x9a\xe7\x77\xf0\x6d\xbe\xc9\xcd\xfe\x41\xf3\xd0\x8e\x32\x5c\xa9\x0d\xdd\x3d\x11\xe6\x36\x39\x6a\x89\x52\xf0\x0b\x4c\x6d\x8a\xa1\x8b\x02\x2e\x49\xc2\x65\x47\xe3\xb5\xfc\xa0\x52\xb0\x27\x9c\x88\x76\xf7\x24\x98\x09\x50\xd0\x19\x3e\x35\x68\x0c\x5f\x0a\x80\xaa\x01\x63\xd5\xd2\xa0\x57\xae\x3f\xbc\x86\x2b\xfa\xc2\xe0\x00\xf5\xff\xbc\xf7\xe3\x60\xde\x83\xcf\x87\xb2\x23\x43\xbd\x80\x97\xcb\x08\x18\xc5\x42\xea\x9b\xe9\x57\x27\x42\xab\xc3\x7e\xb3\xab\x82\xcd\xfd\x63\xe1\x62\x0d\x00\x13\xd2\xfe\xef\xda\x35\x7e\x7d\x60\xf0\xd5\x41\xd6\x45\x28\x12\x28\x72\xa2\x1b\x7b\x32\x6d\x65\x35\xfb\x14\x0a\x74\x3e\x60\x76\xb3\xc3\x03\x03\xef\x64\x02\x2c\x0c\x70\x2a\x3d\xae\xcf\x95\xc6\xbc\x01\x18\x27\xd8\xe1\xb9\x07\x20\x6f\x8e\x24\xdd\xa5\xaa\x3b\x66\xf2\x60\xa2\xcc\xa2\xd8\xfc\x74\xb1\xb9\xc9\x9f\x4a\xaf\x24\xdf\xfb\xe3\xaa\x48\x1f\xfe\xe5\x5a\xe5\x00\x04\x12\x4b\x95\xc3\xd4\x8a\x83\xb1\x1c\xcf\x6b\x03\xc0\x2b\x10\x4c\x01\x6d\xed\xad\x14\xde\xdf\xef\x52\x32\x1e\xa4\xe5\xae\x31\xf4\x2c\xb0\x71\xe1\xc7\xc3\xf5\x88\x95\x87\x46\x1e\xef\x0b\xc1\xa3\x70\x92\xcc\xb9\x2d\x97\xbd\x4a\x25\x62\xc7\xeb\x1f\xa0\x95\xcf\x3d\x67\xf5\x56\xf5\xa3\x8d\x5e\x89\x79\x81\x90\xbd\x7e\xcf\x17\xc3\xd7\xbc\xf5\x15\x30\x7e\x2d\x50\xc7\xcf\xd7\xaa\x7b\xfc\xc6\x9b\x42\xa2\xf8\xc6\x32\x58\xb2\x5a\xda\x3f\xeb\x08\x6f\x47\x21\x78\xcd\x6e\x2e\xca\xdb\x7d\x25\xae\x7d\x4f\x1b\x6f\x09\x5f\xbe\x3f\x62\xb8\x1b\x4a\xdc\x12\xe1\x89\xe7\x4e\xbe\xf9\x76\x1b\xb2\x24\x62\x6c\x3b\x7a\xe9\xce\x60\x86\x26\x4b\xab\x87\x78\x5e\x5d\x22\x11\x92\xe5\x15\xc3\x64\x98\x0f\x2b\x11\xe4\x67\x0b\x01\x65\x49\x32\x80\xf9\xaf\x8b\x04\xf6\x20\xf2\x81\x14\x42\x23\xf0\x28\x69\x6a\x4e\x4e\x3e\x53\x77\x46\xc1\x0c\x57\x00\xd3\x0c\xa1\x7c\x97\x03\x62\xb8\x18\x09\xfe\x02\x88\xc0\x57\xf9\x6f\x57\x5e\x5c\x71\x13\x1a\x8f\x3f\xbf\xa6\x31\x3e\x04\x42\x00\x4c\xd0\x2f\x3d\xd1\x69\x52\xff\xdb\x2c\xbe\xeb\xf8\xe0\xc8\x63\x79\x6b\x57\xbe\x18\x5a\x29\xc7\x42\x55\xbc\xa0\x8e\xd6\x6b\x6a\x79\xd5\x1b\x34\x58\xfe\xf5\xc7\x4b\xc3\xe6\x2c\x0d\x33\xf1\x0a\xee\x46\x00\x02\xfb\xe5\xbc\x39\x18\xe2\x70\x4b\xeb\x75\x8e\xaf\xb0\xd5\xb7\x83\x0b\x97\x8c\xd9\x71\x90\x40\xf7\x9c\x98\x4f\x41\x76\xfe\x79\x47\x34\xf0\xfa\x90\xcb\xde\xde\x2e\x2c\x6d\xb9\xa3\x23\x44\x22\x5e\xcc\xd1\xa3\x87\x01\x38\x6c\xa4\x51\x5a\xf5\xa5\x31\xf5\xf3\x82\xab\xd0\x43\x94\xae\x9f\xe8\x5c\xab\x34\x6f\x4a\xdc\xa8\x8c\xe8\xed\x9e\x8a\x0f\x95\xa6\xa0\x85\x1d\x93\xfd\x64\x44\x36\xe7\x68\x5b\xa6\xbc\x7c\x1a\x99\xd7\x4c\xd1\x1c\x5d\xd5\x56\xf8\x7e\x81\x2e\x86\xd7\x3a\xb6\xe9\x0e\x8c\xc6\x12\xcc\xd4\x30\x7a\x2a\x05\x18\x1c\xfa\x19\x15\x9a\x48\x58\xd7\x2c\x80\xcf\xbf\xcf\x37\x9f\x91\x7a\xae\xf6\x55\xf4\x51\x4e\xbc\x65\x2e\x37\x24\x3a\xba\x86\xc5\x2e\xcd\xca\x30\xd6\xa3\x4d\xbd\xe5\x6a\xb9\x13\xeb\x39\xff\x17\x67\xaa\x0b\x7b\x32\xda\xac\x43\x8d\x1b\xfe\x1b\xab\x4f\x19\xbd\xa2\xe5\xa2\xb8\xd3\xfb\xff\x90\x4e\xd9\x98\x7f\xc3\x40\x2e\x8b\xd4\x57\xd4\x31\x05\x44\xb1\x07\x7a\x1c\x5b\x10\xc1\xb0\xe2\x5b\xb0\x4d\x25\x56\xe6\x35\xec\x72\x21\x34\x26\x55\x99\x72\xab\x0d\x73\xe2\xa0\x37\x25\x79\x7f\x00\xe7\x4e\xd9\x4a\x28\x3f\xa5\x6e\x59\x6d\x89\x1e\x22\x54\x13\xfa\x43\x8d\x4d\x6d\x72\xfb\x2e\x04\xee\x98\xdd\xb4\x7b\x62\x53\x4e\x54\x8c\x1d\xec\x5d\x2a\x19\x7d\xe8\x92\x1b\x76\x60\xaa\xa4\x98\xfb\xa2\x95\x31\xea\x5e\x48\x9d\xe5\xee\x8b\xd3\x76\x93\x4e\x6f\xee\x55\xdb\x86\x41\x53\x36\x57\x99\x4f\xd9\x89\x65\x0b\x5b\x28\xda\xce\x42\x11\x03\xe5\xa2\xcd\x9d\x1e\x85\x74\x6f\x31\x62\xcf\xab\x15\x5a\x48\x82\xe7\xbc\x7b\xd1\xc0\xf5\xa4\x7e\xcb\x4e\x80\x7d\x56\x1d\xcb\x8b\xd9\xb9\x00\x6f\xb2\x92\x15\x3c\x8b\x3e\x23\xc7\xfd\xa2\x6f\xaa\xf0\xee\xbe\x54\x46\x44\x22\xef\x1b\x25\x37\xef\x33\xae\xac\xd7\x2e\xf5\x28\x3f\x15\xbe\x66\xb7\x92\x83\x8a\xe5\xe6\x5d\xdf\xd2\xf5\x60\x21\xf5\x9c\xc0\xb1\xfc\xc0\xbf\xbc\x31\x25\x55\xef\xf4\x71\x4c\x3a\xe8\x9c\xa7\xa8\xcf\xb8\x7c\x92\x04\xfb\x40\x38\x27\xf3\x17\x2b\xae\xf5\x56\xa8\xb6\x57\x1e\x75\xdb\xa0\x82\x9d\x30\x7f\x8b\x0b\xcb\x7d\x20\x2b\x54\x2f\x89\xee\x51\x6e\xe9\x13\xa0\xe2\x6c\x10\xea\x9e\x7e\x86\x63\xbb\xf2\x7b\x97\x70\xab\xfe\x61\xed\x3d\xa6\xe8\xa3\x56\x3a\x23\x76\x6d\xf8\xe9\x7e\x90\xe2\xc8\x31\xee\x81\xcf\xed\x90\xf6\x74\x09\x30\x8d\x53\x50\x48\x81\x5d\xb6\x2f\xc8\x6a\xe2\x67\x2f\x21\xbb\x92\x88\x1b\x7b\x2f\x1b\xa3\x63\x20\xe5\x6a\x9d\xd0\xf7\xc9\x68\x91\x85\xe2\x5b\xe3\x3d\x92\x10\x55\xd5\xfa\x40\xca\x8d\x71\x8b\x49\x67\x36\xce\x4d\x96\xad\xff\xfa\x1f\x97\x95\x6d\x71\xe9\xfb\x25\x59\x38\xec\xbe\x64\x63\x7f\xd5\x60\x22\x17\x8d\xda\x58\x91\x74\xae\xa4\xe5\x01\xb3\x9d\x13\xa4\xaf\x3e\x9d\x17\x07\x22\x03\xb7\xfb\x7b\xe2\x85\xc5\x72\x69\xb8\xc5\x14\xe9\x50\x9d\x4f\x3f\xfb\xac\x30\x3d\x86\x2f\xbf\x39\xb3\xd2\x46\x01\xed\x13\x6e\x1e\x56\x7d\xa6\x4f\x59\x5b\x12\xd5\x9c\x0f\x1b\xbd\xb5\xaf\x22\x49\xee\xd9\x0a\xe9\x7b\x47\x45\x7a\x09\x60\x29\xd3\x87\x72\xca\x12\xec\xc1\x1d\xb6\x4f\x6f\x4b\xf1\xff\x59\x02\xea\xba\xa7\xfe\x53\xef\xe9\xc7\x02\x95\x34\x03\x3b\xa0\xa5\xbb\x94\xbe\xeb\xb7\xd4\x1e\x4c\x27\xf4\xb1\xb9\xa2\x3e\xe1\xb0\x63\xe8\xc4\xe1\x92\x4e\x40\x19\x95\xbd\xe0\xaa\xf1\x38\x20\xe1\x17\xca\x8b\x8a\x7b\xec\x82\x95\x7a\x14\x62\xf6\x04\x38\x05\x5f\x78\x08\x56\xe2\xd4\xf0\xd3\xdc\xda\x28\x1e\x58\x22\x5d\xce\x94\xac\xc4\x9b\x4d\x36\x77\xfe\x2c\xa4\x66\xe8\x67\x66\x94\xd3\x2b\xcd\x9c\x29\x54\xaa\xd5\x4a\x1b\x55\x08\x74\x3e\x0d\x2d\xe8\x5d\x7a\x7d\x03\x1b\x86\x6f\xa3\x2a\x91\x6d\x47\x07\xc5\xb6\x1f\x96\x31\x89\x53\xcd\x1d\x8c\x3c\xbb\xb1\xba\xbb\xdb\xb5\xe5\x87\xfc\xb7\x26\xaa\x85\x15\x3a\x17\x97\x99\x51\x83\x7a\xf1\x48\xed\xe1\x6a\xba\xbd\x6c\x1a\xa6\x6a\xfe\xb9\x4c\x01\xee\x1c\x0d\xd8\x46\x2c\xfb\xff\xc1\xf0\xf8\x8f\x61\xe8\x59\xaa\x22\x27\x4c\xcb\xac\x86\xc9\xb4\xa5\xb2\x62\x4a\x70\x7b\xf6\xbc\x97\x36\xad\xd5\xab\xe6\xa4\x0e\x68\x93\xe6\xd1\x5d\x13\xbf\x8d\x10\x6d\xaa\x0d\xfd\x45\xd2\x3d\xae\x0b\xd2\x7e\x92\xea\x66\xa1\xbb\xda\x04\x46\x76\x1c\x8a\xdf\xea\x87\x45\xbb\x60\x45\x57\x69\x6e\x16\x75\x78\xe0\x38\x21\x47\x56\x59\xe7\x3f\x3f\x37\x4b\x5e\xf6\x15\x2b\x9b\x5b\x32\xb7\x96\xdd\x25\x5f\xac\x6d\x77\xe4\xba\x73\xc3\x5a\xb5\xea\xe9\x4d\x5a\x3f\xdc\x76\xe2\x6c\x9e\xb3\x93\x39\xa3\xb9\x66\xa4\x88\x4f\xca\x0c\xcf\x7b\x1c\xf9\xb2\xaa\x2c\xb3\x27\x39\xab\x2f\x1b\x7d\x15\x00\x0d\x54\x7d\xe5\xcc\x1b\xeb\xca\xe7\x36\xd9\xde\x56\xeb\x7a\xc3\xb4\xff\x76\x55\x12\xb9\x5b\xe2\xd1\x64\x54\x1e\x2c\x5f\x75\xea\x56\xca\xed\xa3\xe4\x45\xcd\x2b\x42\x16\x3a\x81\x78\xe2\xe1\x61\x8f\x59\x2e\x4c\x34\x8d\x72\xdd\x50\xcb\x31\xf2\x22\x11\xad\xa1\x6e\xaf\xef\x6a\x5b\x29\x58\x73\xd6\x11\x35\x34\x8d\xf5\x01\xdb\x20\xc9\x34\x73\xe5\x53\xca\x36\xdd\xc1\xab\xa2\xf2\x0c\x7b\x99\x28\x05\x2c\x89\x6b\x57\xaa\x87\x10\xfb\x0a\xab\x3a\x1a\x44\x6d\xaa\x33\xfc\x88\xb0\x8e\x2f\x0a\xf0\x54\xc5\x2a\xdd\x1f\xd7\x05\xa9\x7a\x27\xa9\x31\x1e\xb6\x6f\xf1\x27\x33\xff\x18\xf8\x6f\x8a\x77\x7c\xd0\x8b\x14\xa5\xa9\x3d\xca\x59\x87\x3c\x10\x0a\x04\x61\x9e\x44\xa8\x6d\x82\x1e\x3f\x46\x5f\xa3\x59\x33\xe7\x66\x02\x5e\xb7\x4c\x12\x95\x66\xeb\x66\x27\x1a\x15\x40\xd4\x18\x26\x4d\x37\xb7\x46\x30\x7b\x82\x8c\xe7\x95\x12\x47\xa7\x8a\xb1\x54\xc8\x42\xc4\xd1\xce\xd3\x2f\xaf\x1f\x66\xb8\xd5\x7a\x71\x63\xf8\x5d\x2e\x4c\x2e\x49\x11\xb2\x6e\x5e\x1e\xbd\xa4\xd9\xd2\x57\xa1\x6b\x94\xd6\x28\xed\x10\x68\x1a\x8a\xdd\x63\xa4\x21\xc8\x9c\xfa\xeb\xae\x7c\xe2\x8a\x25\xd8\x3f\x25\xc0\xd0\x5c\xfd\x84\x36\xdd\x15\x51\xc6\xc0\xb4\x6e\x2a\xb9\x99\x30\xc0\x02\xe4\xb3\x27\x18\xab\x19\x27\x8a\x8d\x8e\xd3\x57\xae\x68\xc4\xa9\xe3\x9f\x3d\xfb\x00\xee\xc5\x9d\x4c\x96\x1a\xdc\x43\x67\x08\x52\x04\xf1\x9b\x99\x8c\x89\xa6\x39\x56\xee\x94\xea\xe7\x8e\xab\xd8\x9b\x41\xa5\x10\xd3\x9a\x54\xbf\x51\xf5\xae\x79\xcc\x05\xc4\x8d\x26\x69\xfd\xd9\xa3\x68\xf5\x9c\xe3\x51\x4a\x2c\x23\xf6\x7c\x64\xe9\xa9\xba\x05\x7a\xcd\xca\xf1\xa2\x7c\x79\x59\x48\xb4\xc8\xe7\xee\xd1\x7b\xaa\x46\x49\x12\x25\x99\xac\x4f\xd8\x11\xe8\x14\x82\x16\x52\x44\x92\x26\xd6\x6b\xea\x27\xce\x09\x17\xf5\x91\x28\xa8\xac\xfd\xf1\x6b\xd5\xcd\xb7\x5f\xdc\x75\xe1\x58\x54\x05\x81\xb0\x34\x83\x4a\xdd\x14\x6f\xad\x81\xdd\x74\xc7\xa0\x80\xf5\x1d\x60\x12\x58\xb3\x7f\xe8\x0b\xec\xf3\x88\x6c\x04\xda\x2f\x84\xde\x2d\xdd\xd4\xa9\xaa\xac\xae\xc1\x19\x0a\x14\x54\x42\x49\x6a\xa2\xd4\x9b\x2f\x03\x9d\x0a\x82\xf8\x4a\xc0\x6e\x30\x2c\xa6\xc4\xa7\x58\x42\xc4\xf7\xdd\x55\xba\x9e\x48\xd5\x68\x1d\xd7\x17\x46\x65\xa8\x02\x25\x0c\xd6\x36\x8e\x25\x0c\xd4\x2f\x12\xc6\xc1\xb5\xc6\x02\x14\x3a\x26\x7a\x4c\x6c\xb1\x19\x64\x4b\x54\xb5\xf4\x0a\xb1\x5e\xbc\x47\x76\xcd\x8a\xa2\xca\x0f\x53\x41\x34\x8a\x3a\xe4\x44\xc1\x04\x49\x81\x06\xf9\xde\x03\xaf\xca\xaf\x91\xf0\xe8\x3c\xb8\x0b\x96\x21\x2e\x94\x31\x3f\x1e\x6e\x54\xe5\x9e\xe0\x19\xc8\x7a\x1d\x07\x68\xd4\x93\xe5\xb0\xb5\x0c\x9f\x5a\x88\x42\xe4\x18\xaa\xf2\xa9\x17\x96\xce\xef\x87\xaf\x43\x6e\x16\xd2\xee\x97\xb5\x1f\xf9\xee\x49\x9d\x9e\x00\xf8\x8f\xb3\x89\x7e\x03\x2b\xdb\xef\x73\x02\x6d\xa6\x38\xb9\x54\x7f\xb0\xc5\x3d\x66\x21\x63\xb7\x28\x9a\x4b\x1b\x48\xf7\x8a\xea\x83\x53\xad\xcb\xe8\x48\x37\x21\x4c\xf0\x53\xbf\x2e\x44\xc4\x02\x34\xe7\x8b\x24\xfe\xd9\x7e\x5d\xcb\xda\xd9\xb4\x61\xbc\x47\xe9\x02\x9a\x73\xaf\x69\x08\x4b\x37\x90\xc0\xe0\x22\x7f\x64\xcf\xb8\x7d\xbf\xac\x89\xb5\x9a\x7c\x9f\x7b\x9d\xa9\xd8\xdc\xb0\x51\x92\x37\xde\x72\x2d\x0f\xca\x1d\x79\xa7\xfb\xc7\xe0\x88\xcc\x82\x7a\xab\x15\x52\x61\x56\xce\x5d\x08\x76\x34\x74\xbc\x96\x9e\xa0\x8f\x8b\xbf\xb0\x05\x32\xfa\x08\xed\xe4\x04\xfa\xc2\x2d\xe6\xc7\xe8\xae\xa8\x59\x44\x8e\xdb\x8c\x19\xed\x53\xd8\x40\xaa\x25\x5f\xd1\x42\x28\x46\xd6\x13\xe3\xdd\x48\x6b\x65\x7f\x25\x26\x04\x35\xfb\xd5\x3d\x27\xbc\x1b\x6a\x46\x2c\xa7\xf7\xfb\x98\xba\x47\xf5\xf4\x6f\x57\xf8\x10\x39\xe8\x3b\xfc\x28\xef\xda\xa4\x90\xc1\xf7\x58\xd0\x33\x7a\x60\xf7\x66\x9d\x4d\x83\xd4\x3c\xb5\x7e\xdf\x31\xea\xcb\xf9\x62\x52\xf4\x36\x74\xa6\xe8\x14\x30\x6c\xbd\x75\xd6\x46\x9a\xa9\xbe\x49\x6a\x11\xcb\xaf\xfb\xe3\xcb\x1e\x4a\x6f\xab\x88\x49\xcc\x71\xa8\xb9\xb6\xc4\xb4\x10\x28\x85\x1b\xae\x63\x7f\x03\xc7\x98\xc7\x55\xef\xc8\x40\xf4\xba\xab\xdb\xd1\x1d\xd1\xa2\x23\x02\x65\xcd\x26\x9b\xb1\x56\x95\xb3\xf7\xa9\xcc\xf3\x79\x28\x18\xfa\x09\xf2\x7b\xcc\xa7\x4b\x75\xa4\xcf\xe1\x98\x57\x4b\x13\x65\x01\x94\x90\x5a\x0a\x5e\x3e\x28\x77\x44\x49\xa6\x19\x92\xdb\x12\x15\xdf\xb9\x7d\x78\xc8\xde\x0a\xfe\xda\xc6\xba\xe2\x35\xbc\x67\x59\x80\x47\x32\xa6\x1c\x32\x0f\xc8\xd3\xfb\x26\x8b\xf3\xfb\x9e\x0c\xd3\x73\xcf\x83\x21\x71\x19\x80\xca\x5c\x09\xa1\xc1\x9e\xbc\xac\x8c\x8e\x19\x43\xdd\x50\x25\x55\x8b\x0d\x66\x62\xeb\x13\xf5\x05\xf7\x53\xb5\xaf\xe5\xda\x27\xb5\x48\x85\x4c\x62\x69\xcc\x2c\x9c\x73\xb5\xe4\x46\x03\xc0\xb9\xf4\x36\xe4\x04\xa6\xae\x37\xdf\xbc\x44\xe4\x0a\xe6\xa6\x67\x1d\xcc\xa3\x6f\x47\x61\x29\x6a\xe8\x53\x2d\x26\x9d\x3e\x37\x94\xd2\x79\xc6\xcf\xe7\x15\x1e\x43\x43\xce\x96\x08\x69\xe2\x5d\x00\x4d\x52\x1c\x93\xa0\xbb\x0c\x41\xf1\x1a\x8f\x30\x99\xf0\x0c\x0d\x4b\x66\x93\xb4\x46\x3d\x7a\x0b\x8c\xc6\x67\x04\x67\x8a\x03\xaf\x74\x66\x9b\x37\x17\x4b\x78\x20\x90\x5b\xd0\x12\xe5\xab\x1f\x0c\x4c\x5e\x2e\x5b\xb3\xa6\xd4\xad\x3e\xf3\x5a\xd1\x01\x63\xfb\x19\x37\xe4\x16\x13\x07\x8d\x85\x33\x36\xfe\x16\x63\x1e\xcd\x97\x99\xd7\x71\xcc\x07\xb2\x77\xac\xb9\x2a\x43\x43\xf9\x56\x3c\xb7\xfc\x0e\x5d\x29\x45\x8d\x1d\xc3\x39\x9a\x9f\x29\xa8\xcf\x9b\xca\x30\x6c\x94\x53\x4d\xeb\x1f\x2e\x24\xf4\x62\x41\x53\x98\xea\x96\x48\x69\x62\x13\x25\x7a\xec\xb2\x71\xdd\x93\x56\x10\x03\xdd\xcf\x1b\xde\xb7\xca\x80\x18\x37\xe4\xf6\x2b\x38\xe0\xfa\x7b\x0a\x5c\xe2\x48\xa6\x41\xe1\x5a\x1e\x00\x23\x5b\x97\x38\xc4\x05\xa4\x30\x9e\x2a\xc6\x0c\xd1\x72\x1f\x5b\x2d\x9c\x73\x77\x1b\x6e\xdb\x78\x50\x2b\xee\x94\xa8\x48\x45\x6c\xfb\x19\x87\xe5\x59\x2e\x2f\xdd\x6b\x36\x77\x19\x4b\x62\xae\x3f\xfb\x38\xd6\x38\x47\xf6\x49\x07\x01\x2e\xdf\x0b\x75\xa1\x01\x96\xb7\x72\xde\xbc\x99\x6c\x39\x8f\x0f\x45\x69\xde\x9c\xf8\x01\x12\xa2\x86\x99\x60\x86\x22\x82\xc6\x83\x9e\x91\x8f\xc8\x87\x9f\xcb\xba\xf3\xf6\x26\x76\xa1\xcc\x49\xcc\xdb\x04\xd5\xa2\x75\x2a\x4a\x5c\x5b\xd5\x5e\x03\x65\x6e\x06\xf4\x51\x05\x25\x6a\x09\x3f\x7b\xeb\x6e\x57\x2b\x9b\x10\xb3\x31\x0b\x82\xb2\x5a\x80\xd8\xdc\x43\xab\xf2\x09\x16\xd2\x24\xaf\xd7\x33\xf7\xaf\x21\xdb\xee\x36\xea\xf7\x95\xa3\xfe\x2f\xa5\x53\x47\xc7\x20\x40\xa9\x34\xce\x8c\x1d\x19\x45\xb8\x21\xc3\x52\x1a\x64\x9e\x1e\x38\x68\x67\x3f\x83\xd3\x4a\x7e\x11\x8f\x10\xa2\xb2\x75\x3f\x0b\x5a\x69\xa1\xbf\x44\x18\x83\x87\x34\xa3\xed\x4b\x7b\x6a\x25\x18\x29\x88\x27\x19\xb7\x05\x78\x9a\xe9\x4d\x61\xfe\xff\x59\x76\x6b\x45\x74\x82\x2c\x6c\xd6\x04\xc5\x01\xfd\x13\x63\x3a\xc9\xc3\x77\xe1\x85\x58\x6b\x7c\x7c\x32\xf3\x9c\x85\x12\xeb\x24\xc2\x2e\x45\x79\x86\x3d\x1f\x06\x78\x92\xc7\x2a\x2d\x4c\x4d\x9a\xb9\x5f\x16\xbe\xb6\xef\x78\x43\x83\xd3\xd3\x7b\x05\xc0\x74\xd3\xe7\x88\x34\x02\x2e\x9f\xa6\x3c\x19\xa0\x04\x50\xf0\x72\xf1\xcd\x99\x99\xe1\x11\x73\xb9\x31\xb9\xbc\x2f\x9c\x16\xd5\x4e\x1d\x38\xb0\x75\x75\xa2\xbd\x2e\xd3\xbf\x53\xaa\x5f\x72\x84\x6a\xab\x5d\xb8\x5c\xad\xa5\x9a\x61\x76\x5e\x95\xe4\x1b\xa2\xa9\xe1\x73\xf6\xf3\x51\x11\x88\x9e\x0c\x5a\xc5\x9c\xf5\x2d\xc5\xd4\x44\x8c\x00\x75\xb5\x53\xdd\x0f\x18\x8d\x67\x8b\x36\x83\x84\x0f\x86\xb2\x7b\x24\x7b\xe6\x16\x72\x0f\xa6\x32\xda\xcf\xf0\x00\xfe\x35\xf3\x3e\xb6\xf8\x1b\x85\x2c\x09\x93\x87\x68\x0f\x63\xa6\x1b\x16\x62\xb1\x4a\xd6\x8a\xcf\x3f\x24\x7b\x6f\x75\x95\x6f\x3e\xcd\xa8\xfe\xa4\x76\x43\x6c\xa1\x92\x28\xb6\xc2\x3c\xdc\x2f\x30\xe7\x78\xfb\x28\x0e\x44\x27\x7f\x61\xd4\xa7\xd8\x52\x99\x30\xdc\xdf\x22\xe0\x6f\x40\x9a\x86\xa8\xa4\x3e\x4e\x08\x9b\x39\xdf\x96\x51\xb9\x5d\xb6\xe2\xa8\x1a\x7d\xb8\xb7\x00\x33\x81\x28\x8b\x20\x7a\x1e\x5e\x29\x28\xd2\xae\x65\xb4\x08\x7d\x45\x31\x17\x5c\x04\x02\xdf\x70\x1a\x9d\x42\x80\x28\x79\xfb\x95\x66\xcc\xb7\x13\xc5\x48\xf0\xf1\xcf\xc8\x59\x84\xc4\x2f\x48\x49\xfe\x8d\x00\x3b\x2c\xff\xa7\x94\x08\x71\xc2\xab\x3d\x95\xa7\xfc\x04\x64\xd6\xc6\x7f\x3c\x7a\x6c\xb0\x68\x69\x20\x66\x7c\x41\x97\xd1\x66\xc0\x67\x5d\x79\x5c\xc5\xe8\x0f\x3a\x65\xd4\xe4\xfd\xce\x7d\x8f\x1f\x8b\xc7\xd5\xaf\x13\xe7\x46\xae\xd9\x4d\xb1\x2e\x4d\x17\xa5\x2d\x4c\xda\x43\xa3\xe4\x45\x88\x66\xe9\xba\xac\xbf\xac\x75\xed\xe2\x5c\x51\x28\x14\x4b\x8d\xdb\x84\xa0\x52\x6a\xad\xab\xb9\x52\xfb\x12\xc7\x8f\xd1\xef\x2f\xb5\xf0\x5b\xcd\x04\xb7\x75\x0e\x54\x4f\x62\x0e\xa4\x8b\x44\x3b\x13\x43\xd8\xb7\x63\x02\x8d\x45\xbb\x96\xbd\x45\xc6\x54\x53\x71\xc3\xdd\xfc\x68\x33\x64\x94\xdb\x2d\x7b\x05\xfc\x66\x58\x70\x16\xc4\xc3\xf0\x36\xa7\xad\x68\x0f\x5d\xa2\xb9\xdb\x56\xa3\x48\x61\x33\x3c\xad\xd5\xdc\x00\x76\x99\xd4\x4a\x40\x58\xa6\xe2\xe9\xbe\xe7\xf6\xcd\x4d\xc4\x7a\x64\x52\xca\x4c\x62\x05\xa3\x33\xa2\x91\x2f\x98\x02\xf4\x08\x98\x87\xb8\x64\x7a\xa8\x22\x97\xf8\xf3\x3f\xd4\x80\x03\x1f\x67\xda\x3a\x44\x5f\xa5\x1d\xd1\xc2\x50\xa8\xbe\x37\xbd\xad\xc2\x5f\xd9\xa0\xcb\x53\x63\x15\x7d\xbe\x15\xa1\x96\xc2\xff\xdf\xa8\xf4\xca\x95\xfc\x30\x90\x24\xf9\x9d\x30\x02\xa5\xa0\x73\xfb\xbb\xe0\x9b\x4d\x47\x25\x5e\xfb\x96\x58\xe2\xc9\x03\x35\xd3\xdd\xfe\x54\x6e\x3b\x9b\xbd\xc0\x3e\x26\x02\x11\x54\xa6\x04\x3c\xe5\x8d\x16\x99\x29\x33\x08\x53\x66\x56\x31\xf3\xe5\xda\x93\x27\xac\xfd\xd4\x76\x68\x92\xca\xca\x44\xe6\xf4\xa4\xfc\x0b\xee\x6e\x86\x24\x34\x6e\xab\xb5\xb7\x27\xdc\x72\x7d\x62\x12\x30\xef\xe4\x44\xdb\x78\x6f\xfc\x56\xea\x0b\xc1\x03\xd0\xfc\x55\x9d\x4a\x67\x49\x1f\x18\x4e\xfe\x89\x9c\xa7\x7d\x06\xb2\xd6\x34\x83\xbb\x2f\x12\xc1\x1b\xee\x8a\x7c\xdf\xa5\x5c\x94\xec\x24\x4d\x95\x8c\x79\x81\xbb\x22\x99\x6a\xa6\x7d\x05\x6a\x8f\xb9\x00\xe8\x91\xc3\x69\x08\x7f\x62\xd3\xf9\x21\xd4\x0f\x4e\xd3\xbd\x10\x53\x42\xb6\x76\xf3\x43\x39\xae\x77\x70\x9d\x37\x7d\xea\xca\x35\xb1\xfd\xf8\xac\x84\x1e\x71\x32\xe8\xd1\xaa\xe0\xc6\xd2\xb4\x00\xf7\x55\xc3\x8d\xbb\x2c\xeb\xd5\xe9\xbc\x81\x1b\x49\x9d\x16\xf5\x7d\xff\x3b\xed\xdd\x59\xcd\x9c\xc8\x9d\x94\x44\x4a\x6d\x5b\xf0\xf6\xe5\xd0\x4f\xac\xad\x73\xde\xa5\x24\x46\x6c\xe5\x58\x8a\x8e\x7e\xa6\x3d\x2f\x5f\x18\xbb\xe1\x53\xe9\x4c\xec\xb1\xec\x17\x4a\xc4\xd3\xdd\x26\xa8\xc7\x5e\x28\x0d\x71\x77\x76\x23\xeb\xe3\xbf\x09\x1e\xef\xea\x92\x8e\xfb\xff\x2e\xd1\x50\xdf\xd9\xe5\x16\x3a\x62\x42\xf8\xb1\x66\x1a\x56\x88\x32\x71\xcb\x67\x6e\x89\xd9\x99\x0b\xaf\x8b\x05\x6c\x38\x56\xd3\x85\xb8\xb4\x62\xd1\xe5\xb4\x30\x17\x83\x61\x47\x2d\x4f\x54\x6c\x4f\x3d\x41\x8c\x66\x93\xb1\x57\xec\x4f\xd7\xad\x4f\x4a\x9f\xfe\x1d\x7b\x9b\xd5\xcc\x91\xcd\xb2\xb9\x67\xc6\xf0\x20\x6b\x19\x3a\x87\xe1\xf9\xed\x49\xfe\xe7\x33\xe4\xcf\x2a\x7a\x10\x15\xe6\x9b\x41\x24\x11\xff\x87\xf3\x95\xbd\xcc\x8a\x6b\xbe\x50\x0d\xc9\x60\xe6\xe6\xb3\x6e\xf5\x46\x47\x78\x29\xeb\x47\xff\x52\x50\x45\x25\xbd\x35\xc4\x5c\xfd\x7d\xb7\xae\xda\x12\xc0\xbc\xa9\x33\xdb\xb5\x52\x75\x75\x9b\xde\x08\x57\xe7\x2d\xcc\xe8\xf1\x1f\x99\xfe\x98\xdf\xfa\x32\xd4\x14\xd4\xe6\xfb\xb9\xfa\xf4\xa5\x47\x89\xa2\x12\xfe\xab\x0f\x9d\x92\x8b\xf4\x1a\x0e\x25\x76\xcd\x6f\x4d\xff\xdd\xcd\x6b\x20\x78\x07\x86\xef\x42\xf8\x75\x46\x8e\xe9\x4e\x37\xd7\x82\x6b\x56\x29\x31\x32\xf0\x64\x42\x21\x08\x34\x0d\xf9\xe0\xae\x2e\x0a\x92\x8a\x4e\x91\x03\x38\x4f\x2c\x66\xbd\xfa\xa7\x12\x9c\x7f\x32\x54\x69\x56\x0d\x75\x8b\xb1\xe4\xc4\x64\xdb\x4c\xf2\xae\xed\x7a\x79\xa7\xf9\x1b\xca\x75\x98\x67\xd1\xf0\xc2\x92\xcc\x3b\xa6\x19\x4b\x73\xdf\x27\x0f\x5e\xa4\xa7\x12\xa0\x79\x2b\x83\x1a\x37\x55\x55\x4f\x9d\xa8\xfb\x42\x99\xf8\xd0\xb6\xea\x2b\xad\x24\xb4\x25\x4f\xbb\x39\x65\x6c\xd5\xa5\x2a\x91\xda\x63\x40\xaa\x89\x05\x46\x89\x04\xf5\x63\x36\x14\x67\x67\x05\xf4\x4d\x55\x7f\x5f\xd9\x7e\x31\x66\x84\xa6\x76\xbd\x56\xbb\x35\x0d\x89\x10\xf3\x2d\x56\x0d\x9b\xdc\x30\x1d\x8f\x18\xc1\x20\x17\x29\x5f\x44\xf1\x7b\xbd\xf3\xd4\xb3\x62\x31\x1b\x19\x96\x23\x51\x7c\xe6\x83\x6b\x9e\x39\x3d\xad\x3f\x87\xf7\xe4\x50\x6f\x99\xc1\x9e\x63\xd6\x73\xbb\x1f\x1f\x83\x24\x26\xf1\x16\x9d\x7d\xd3\x42\x6f\x57\x54\x87\xe2\x22\x4d\xc2\x0c\xa7\xbc\x3d\xa0\x44\x79\x24\x2c\x49\x9c\xd7\x08\x4e\x01\x2c\xda\x86\xb1\x09\x77\x99\x03\x49\xcd\x78\xfb\x45\x8d\x8f\x11\xa7\x36\x90\xbd\x78\xe0\x6e\xa1\x43\xd4\x43\x1f\x2d\xa1\xf8\x1c\x99\x2c\x9d\xcf\x95\xd2\xda\xcc\xb2\x59\x0d\x3a\xdd\x79\xa5\x7e\xb1\xcc\xca\x9d\xcb\x17\xd8\x8c\xa8\x8e\x3d\x59\xa2\x07\xc3\xe2\x9e\x63\xcf\x2c\x54\x78\x65\xa1\x71\x55\xa2\x6b\xe7\xe0\xdd\x2a\x4f\xeb\xe6\x54\x71\xf4\x5c\xb1\x45\x1c\xd8\x07\xac\x80\x2a\x84\xe2\x2f\x00\xd8\x92\x2f\x89\xaa\x4e\x53\xe4\x7f\x55\x1e\x66\x3a\xec\xf5\x89\x96\x62\x8d\xfc\x3f\xd5\xc4\xab\xa7\x48\xd2\x74\x03\x24\xd9\xb6\x55\x66\x75\x87\x86\x64\x48\x22\x85\x1a\xa4\x24\xb6\x32\x6b\x51\x0c\xcc\x2f\x8b\xad\xcf\x57\x17\x69\x58\xfb\xfe\xcd\x1a\x4e\x1b\xee\xb6\xce\x78\x0d\x1c\xb0\x72\x36\xfd\x9c\xba\x5f\x79\x7b\x3f\x32\xc2\x17\xda\xbd\xcd\xf3\x43\x7e\x7b\x93\xee\xda\x75\xd5\x38\xe5\x99\x1b\x7c\x86\x0e\xdc\x81\x1c\xb9\x53\x66\x95\xe9\x2b\xe3\xa2\xef\x7b\x06\x96\xea\x33\x17\x98\x30\x60\xbb\x77\x17\x62\x63\x43\xf3\xd5\x0f\x91\x51\xd8\xf4\x2b\x7a\xc6\xaa\x5c\x54\x9f\x7f\x2d\x0f\x1c\xe9\x1f\x7b\xf8\x5d\xde\x02\xa3\xce\xbe\x36\xd5\xd1\xae\xc2\x63\x91\x3f\xc2\x38\x96\x5a\x7e\x7c\x82\x26\xc4\x65\x13\xf3\x1c\xae\x44\x9d\x96\x39\x71\x57\x93\x32\x52\x2c\x59\x2b\x96\xbd\x13\xb8\x79\x3c\x60\x4f\x77\xef\x41\x9a\x62\x7a\x36\x7c\xb6\x5d\xdc\x3a\x71\xa7\xe4\x5a\xdf\x4f\x17\xf7\x56\xd6\x67\x4d\xf1\xd2\xcc\xa5\x69\x63\xcc\x6b\x4a\xcb\x30\x05\xc0\x3d\x2c\x9e\xfa\x89\xf2\xcc\xd2\x34\xda\x2c\x61\x6d\x22\xd3\x1d\x88\x1a\xa6\xf4\x52\x43\x23\xf8\xdb\x2c\x63\xe1\x0c\x66\xa2\xac\x1a\xca\x5a\x1e\x36\x52\x63\x47\xbd\xc5\xa2\x3a\xba\x29\x11\x1f\x65\x8c\x09\x09\xfd\x9a\xc2\x65\x49\x17\xbd\x16\x1b\xdd\x72\x0f\x36\x2e\xea\x10\xf4\x5a\x3b\x97\xcd\x50\xb0\x2b\x4f\xd3\x29\x88\xd3\x24\x16\x5c\xc1\x77\x49\xa2\x56\xec\xc2\x28\x68\xef\xf6\x60\x7a\xb4\x7b\x25\xcf\x66\x70\xba\xfb\x78\x6c\x09\x7d\xe8\xa5\x1a\x6f\x9f\xd1\x6e\x1b\x72\x0d\xb1\x95\x37\x9a\x25\xd3\xa7\xff\x1c\xb8\x7b\x9e\x1f\xaf\x0d\x9b\x13\xe1\x78\x03\xaa\x6d\xa1\x1d\xa7\x06\xbd\x31\x6f\xd0\x92\xb3\xf4\x69\x83\xf1\x71\x13\xb0\xe4\x20\x12\x4a\xd6\xca\xdc\x4f\x9a\xaf\x27\x56\x21\x89\x99\x22\xb7\x12\xb0\x3d\x89\x24\x15\x0a\x0d\xd1\x97\x34\x84\xc2\xf8\x4b\x53\xba\x2b\xea\x91\xc2\xca\x26\x5a\xda\xdb\x99\x83\x91\x27\xa4\xe6\x86\xa5\x59\x8e\x0e\xe0\xd0\x5e\xdb\x16\xb7\x05\x65\xbe\x05\x02\xcc\xe6\x7e\xff\xff\xf7\x7d\xe2\x96\x2c\x85\xc2\x78\x27\x22\x73\xa3\x6f\xdf\xae\x64\xb1\xc7\xfd\xb1\x1f\xa3\xdf\xbd\x7d\x7b\x2e\x08\xe7\x6b\xe8\xc8\xc8\x54\x4a\x59\x3b\x66\x66\xea\x96\xef\x85\x8e\xd7\x6a\xa7\x4b\x56\x92\xb8\x1c\xbc\x42\xef\x2b\xd1\xf6\x6a\xc5\xdc\x01\x1d\x71\x4d\xae\x57\x4c\xaf\x22\x9b\x1b\x65\xf5\x2f\x9d\xd7\xb6\xbb\xdf\xbb\x59\x66\x99\xfd\x8c\xf4\x78\x77\xa2\x49\xf5\xf2\x3a\x6b\xeb\x91\x49\xeb\xe8\x71\x2e\x86\x87\xc7\xb2\x08\x9c\x64\x4c\x57\x69\x6d\xee\xfc\xb8\xb3\x5d\x1e\x00\xc9\x97\xf5\xc2\xc7\xfb\x5d\x0d\x66\xcf\xe2\xb8\x29\x82\x42\xe1\xea\x7b\x6c\xb2\xd6\xbb\xb7\xc1\x1d\x60\xee\x8c\xb1\xca\x6a\xd6\x7e\xa3\xde\x86\xde\xe9\xaf\x3b\xc4\x81\x3b\x7e\xad\x37\xb1\xc5\x2d\x7a\x41\xc1\xef\xd8\xd7\x58\xc1\x27\xac\xce\x0e\x74\x62\x9f\x8d\xd8\x1c\x83\x57\x4f\xd5\x2e\x98\xcb\x1f\x24\x00\xf4\x06\x47\x53\x30\x52\xc9\xe4\x13\x11\x61\xa1\x11\x23\xe5\x51\xb8\xde\xfe\x08\xfd\x50\xca\x1d\x4f\xc9\x7c\xda\x50\x5b\xaa\x9b\x0c\x86\xe3\xf9\x25\x60\x43\x12\x29\x63\xff\x9a\xc5\xc0\x22\x17\xd6\xcd\xbd\x64\x44\x31\xca\x7f\x78\x70\x5f\x73\x2a\x35\xc5\x61\x63\x3c\x9b\x76\x1f\xfa\xc8\x50\x0b\x1f\xdb\xec\x63\x9b\x71\x60\x7b\x44\x38\x86\x53\x68\x76\x10\x92\xec\x90\x69\x20\xfb\xfa\xce\x57\x03\xd9\x09\xa7\xf3\x77\xfa\x70\x6b\xee\xe0\xe6\x52\x12\x7c\x18\xf6\xbd\x1a\x4f\x9a\x32\x2f\x6e\xd0\x40\x92\x36\x4d\xe1\xb2\x00\xcd\x52\xe8\xd5\xab\x42\x7c\xa9\x10\x98\x5c\x15\x55\x6e\xa1\xa4\x0b\x5e\xc3\x6c\xaf\x73\xdd\xc2\x05\xb4\x3d\x10\x5b\x7b\xac\x97\x1e\xa5\x41\x03\xae\x05\x3f\xb2\xf1\x0c\x7a\x4a\x5f\x10\x52\x36\x02\x04\xad\xfe\x53\x41\x83\xe5\xbf\xe3\x09\xbf\x8c\xfa\x8f\xa0\xb5\xfc\x6f\x98\xa8\xff\x77\x6e\xb6\x96\xfb\x7e\xe1\xe1\x9e\x47\x4b\x0f\x2b\xf7\x28\x75\x68\x4b\xb9\x37\xd9\x03\x01\xfa\xe1\x14\x2c\xb9\x07\x06\x0f\xce\x16\xe7\x48\x81\x0c\xff\xe2\xba\x94\xc7\xf9\xc8\x11\x87\x51\xb8\xdb\x2f\xb0\x9a\x2c\xbf\xa7\xbf\x5a\x8b\xf4\x79\x92\x28\x4e\x5a\xe8\xfd\x8c\xf6\x79\x0a\x88\x8b\xfb\xba\xc9\xa7\xb5\xb3\xe6\xf6\x65\x2b\x75\xce\x68\xad\x43\xbe\x3c\xc6\x2f\xef\x2c\x73\x09\x77\x79\xa8\xbf\x23\xf1\x6a\xd7\xd8\x49\xe7\xf0\xc0\xa6\xe8\xaf\xb5\x9f\x7b\xf1\xd2\x8e\x12\xfe\xb4\xfa\xc9\x2c\xd9\xbf\xf2\x25\xee\xa5\x83\xce\x60\x05\x53\x22\x5b\x3b\xb4\xdd\xfd\x5f\x7e\x60\x1b\x21\x3e\xec\x5d\xfa\xdc\x8e\x13\x2a\xce\xda\x74\x5d\x38\x4a\x99\x75\x1b\xd7\xb7\x0f\xcd\x75\x4f\xc1\x0d\x89\xd5\x0e\xd5\xa1\x48\x3e\x88\x8a\x08\x68\xef\x4c\x6b\x71\x37\x67\xe2\x12\xb8\x52\x32\x16\xf6\x2c\xca\xaa\x91\xba\x18\x5a\x5d\xc6\x7c\xa0\x90\x24\xac\x43\x5a\xa5\xac\xe4\x6d\x0d\xb6\xd6\xee\xf4\xad\xc3\xf2\x71\xa2\x17\x03\x58\x01\xa7\x81\x09\x9c\x4c\x72\x53\xf9\x8f\xdf\x4b\x62\x1f\x9f\xcc\xed\x99\x9e\xfe\x97\x12\xd3\x25\x48\xbe\x89\x85\x2f\xba\xce\xcc\x1a\x77\x8d\x3e\x0f\x47\x9b\x39\xc2\x28\x7c\xf2\x76\xed\x76\x0f\xf3\xa0\x4e\x6e\x4e\x76\x58\x0d\x4e\x0a\xd0\x80\x60\x70\xbb\xd2\xc7\x0e\xc3\x19\xd1\x2b\x03\xc9\x7b\x28\xa4\xbb\x75\x03\x5c\x1f\x9c\x20\x73\x04\x8c\xbb\x51\xc8\xfa\xb3\x70\x0b\x87\x0e\xdd\xa8\x33\xb9\x99\x71\xc5\x5c\x92\xf6\xcd\x9f\x9c\xe8\x24\x12\x19\xd1\xef\xb5\xa7\x8a\x3b\x51\xd8\x53\xc5\x99\x7a\xc1\x0e\x89\x5b\x6a\x6c\x09\x8a\x36\x6e\x98\x20\x06\x38\x85\x44\x54\xe4\x1b\x7d\xb5\xe9\xb9\xe3\x94\xa8\xf6\x50\x8a\x45\x02\x09\x25\x81\xba\x42\x57\xf0\xfe\xaf\xd8\xad\x16\x14\x8e\x59\xab\x1a\x77\x17\x85\xb7\x2e\xc0\xed\x1d\xd1\xe2\xb4\xe5\x89\x21\xa1\x9c\xbd\xa7\x2f\x14\x5e\xb2\x6d\x64\x53\x5a\x7e\x6a\x3d\xb8\x2a\x51\x67\x64\xfd\xe2\xa8\x8e\xd1\x30\x74\xc3\xc6\x1c\xb1\x5d\x86\x9f\x05\x05\xa2\x81\xc3\x71\x16\xc1\x2d\xee\x2e\x50\xa7\x4a\x42\x70\x96\xea\x31\x09\xe0\xd8\xab\xe0\xc4\x61\x74\xff\x6c\x89\x2f\xfa\x83\xf1\x79\xf2\x70\xd7\xf9\x71\xc6\x7b\x7e\xc7\xd1\xf8\x54\x4f\x48\xd3\x05\x8c\xa6\x36\xf7\x04\xd7\xfb\xb4\x1d\x09\x75\x85\x4e\xa2\xff\xa3\x77\x59\xb9\x7c\xc3\xf6\x0a\x41\x98\x56\x72\xcf\xec\x77\x44\x08\x68\x34\x4b\x6b\x96\x16\xa2\xf1\xc1\x2b\x0d\xe1\x2f\xbe\x40\x0d\x40\xd5\xc6\x4f\x1e\x9c\xfb\x07\xfd\x19\x94\xbe\x4a\xfc\xec\x01\x5a\x42\x31\x5b\x87\x3f\x6c\x7b\xf9\x4a\xd5\x8a\xfc\xa3\xad\x1b\x71\xa4\x39\x50\x76\xad\x6f\x00\x59\x36\xc7\x43\x4a\xb0\x82\xba\xb8\x83\xf7\xa9\xfd\xcc\x0e\xd2\xc9\xe7\x24\xb5\xb7\x94\x48\x60\x37\x06\x45\x69\x8d\xaf\xa8\x29\x2a\x65\x4b\xc1\xa3\xd8\x82\x59\x08\x38\x7f\xa9\x97\x7b\x56\xbb\xa2\xab\x29\x62\xa7\xd0\x0c\x70\x4e\x76\x2f\x41\xd9\x25\xe5\x82\x3b\xdd\x75\x1d\x68\x87\x28\x77\xcc\x83\xbc\x6c\x7d\xa2\x2a\xd1\x34\xcb\x79\x7c\x75\x56\x3a\x07\x26\xe0\x2a\x50\x3b\x4c\xf1\x18\x51\xee\x99\xf3\xf3\x67\x2a\x7d\x4f\xbe\xcd\x57\x3b\x13\x78\x54\xbf\x21\xb8\xba\xd8\xf6\x46\x82\x5b\x0c\xa5\xf9\xad\x6f\xe9\x0d\x6c\x95\x88\xbe\x2a\xfa\x1a\xb0\xa7\xb4\xc0\x4b\x06\x01\x95\x84\x4b\x87\xe2\x55\x76\xb6\xdc\xbc\xc6\x8c\xd9\xab\x4e\x59\x34\x9b\x24\x47\x64\x2b\x84\x33\x95\x24\x4b\xc0\x56\x5a\xd1\x18\xbe\x0e\xb8\x46\x26\x11\x46\x75\x52\xf6\xa5\x6a\x2e\x47\x4e\x9b\xac\xdb\x96\xca\x35\xc6\xb4\xca\x08\x72\x65\x19\x13\x76\x76\x16\x9f\x19\x76\xa5\xfc\xfa\x05\xc8\xac\x32\x4d\xfa\xea\x43\x5b\xcc\x29\xcf\x18\x7c\xc8\xdf\x01\x65\x47\x79\x62\x10\x18\xa7\x7b\xf8\x29\xda\xbb\x03\x8e\xbd\x90\x2e\x15\x49\x7b\x6c\xda\x31\xa7\xa6\xfc\xa0\x43\xc0\x06\x97\x65\x85\x73\x5a\xe8\x74\x11\x8d\xc3\x68\xd1\xc6\xc9\xbb\x91\x52\xc3\xa6\x01\x47\x70\xc6\xc3\x15\x37\x3f\xbd\xb8\x28\xa7\x64\xb1\xc6\x57\x84\x5e\x3d\xb7\x0d\x08\x0a\xa0\xc4\xd9\x26\xf5\x66\xf0\x56\x03\xbb\xf1\xcd\x9e\x07\xb7\x69\xcf\x9f\x12\x5c\x1b\xb4\x87\x91\x47\x17\xce\xf5\x9a\x36\x24\xde\x05\xb0\x24\x92\xb8\x75\x50\x3d\x07\x6f\xe7\x75\x38\x37\xbf\xd4\x1e\xbd\xec\x9d\x5b\x9e\x25\x3e\x60\x3c\x15\x0e\x9e\x2e\xf7\xcb\x24\xc7\x4d\x74\xd3\x97\xb6\x42\x29\x47\xaa\x6a\x53\xae\x51\xe3\xe6\xc6\x55\x64\xfc\x60\x8e\xe8\x53\xb6\x22\xb8\xa7\x1f\x33\xb7\x99\x1d\xc9\xbd\x85\x7d\x4d\xd7\xb1\xb3\x54\x0b\x74\x68\x3f\xf4\x17\x37\x9f\xb1\x06\xed\x5d\x9b\xe1\xd0\xf7\x84\xf2\x97\x69\xa2\x45\x48\xe5\x15\x89\x9f\x7a\xc5\x9f\xfd\xe5\x7c\x15\xa7\x2d\x9f\xc1\x19\x14\xd5\x74\x64\x86\xa7\xbf\xdb\x91\x2c\xfd\x3a\xcb\x44\xcf\x07\x9a\x1b\x92\xa9\x16\xd0\x6a\x37\x6c\xc1\xdd\x04\x44\x00\x36\xd9\xa7\x17\x2d\xfc\x86\x8f\x02\xb7\xd4\xc1\x2b\xa7\x7d\x5a\x55\x34\x9f\x5e\xae\xe7\x78\x4f\xb5\xdd\xbc\x9d\x9f\x66\xc5\xfc\xd8\x51\x1e\x48\xf8\x1b\x14\x10\x0b\x8d\xc2\xea\x55\x3b\x22\x49\x7b\xf7\x29\x91\xdc\x31\x85\x04\x8d\x5a\xc0\xb0\xf8\x1a\x2e\xf5\xd8\x17\xc5\x07\xe1\x94\x12\x40\xf3\x88\x9b\x32\xf3\x84\x96\xa9\x62\x03\x2b\x71\xba\x7a\xf3\x56\xf0\x9b\x0b\x81\x73\x5e\xc6\x3e\x9f\x1f\x1e\xaf\x04\x02\x56\x5b\xc5\xb5\xa5\xef\xc5\x2d\x1f\x18\x35\xce\x76\xbe\x80\xa1\xb4\xf1\x5d\xe8\x9a\xae\x96\x97\xda\x63\xa6\xfb\x22\xfc\x8d\x22\x66\x88\xf9\xc4\x5c\xa5\xdf\xac\xaf\xe3\x9c\x3c\x8c\xdb\x8b\x63\x79\x1e\xad\x98\x23\xb6\xc5\x51\x6a\x9f\x36\x64\x72\x7f\x23\x01\xa7\xc8\x91\xb3\x82\xde\x14\x4a\xed\xcb\x34\x6c\x12\x1a\xf2\x4f\x16\x06\xee\xdf\xc6\x28\x79\x0e\x87\x16\xef\x4e\xf5\xcd\x7d\x24\x6d\x8e\x0c\x5b\x9a\x04\x2d\xcb\x7c\xf3\x93\xd4\x88\x2a\xfd\x11\x1d\x94\x53\xf1\x8a\x5c\xf7\xd1\x9c\x8d\xfe\xe8\x87\x89\x40\x12\xff\x0b\xcb\x40\x0a\xdd\xe0\xa4\x08\xa8\x69\x65\x27\x9a\x6d\x82\x9f\x27\x71\x24\x9d\xb4\x12\x73\x27\x42\x03\x9a\x7f\x81\xc6\xe0\xa9\xbb\x41\xa9\xb9\x64\xf3\x29\xf6\xf0\x2e\x06\x88\x2a\x09\xf9\x5f\x79\xb6\x8e\x23\x7a\x5f\x17\x19\xd0\xab\x5f\xee\x0f\xcf\xf1\xf4\x7b\xbd\x13\xea\x5f\x61\xac\x5f\x3d\x2b\xe4\x8a\x92\xd3\x8c\xcf\x9e\x27\x50\xf4\xdc\xba\x77\x0d\x47\xd4\x4a\xee\xd6\x6c\x2e\x8b\xba\xfd\x72\xa8\x71\xfb\x5a\xc8\x76\x1f\x44\x28\x9d\x44\x43\x19\x18\x47\x8f\x26\xe3\x43\xe9\xd8\xb1\xc3\x21\x11\xa1\xf2\x93\xaf\x3d\x92\xc7\xa3\x7a\x34\x85\x82\x8a\x76\x28\xa3\x24\x3b\x03\xbc\x7b\x06\x88\x1b\x32\x1a\x14\x14\x20\x40\x8f\x69\xc7\x98\xfc\x75\xdf\xee\x07\x70\x63\xd2\x45\xc3\x14\xec\x0a\x1a\x09\x68\x68\x00\x09\x73\xe4\xcf\x3e\x0d\x13\x81\xd6\x4c\xb6\x5e\xeb\xa2\x66\xef\xda\xbb\x77\xbe\x0d\x54\x57\xde\x9f\xb6\xff\x07\x52\xd9\x0d\xcc\x2f\x5f\xb9\x49\x1e\xaa\xc4\xa6\xc4\x4d\x27\x42\x7f\x2e\x9e\xb4\xd8\x2c\x50\x9a\x2d\xe8\xfa\x48\xca\x6a\x29\xfd\xfe\x25\x50\x7f\xf9\xbd\xbe\xf4\x44\x70\x32\xdb\xc8\x5e\xed\x5e\x77\x8d\x60\x4b\xd6\xab\x81\x4b\xe8\x03\x50\x61\x3e\xce\xbe\xef\xab\xa5\x6a\xcf\xa8\x67\xea\xf8\x29\xfd\x4b\x53\xfc\xd3\xd9\xbc\x12\xee\x64\x47\x46\x59\x47\xcc\x24\x93\x15\xaa\x95\x15\xf8\x58\x60\x88\x0c\x37\x25\x92\xd2\x80\x63\xb2\x4b\x91\xda\x51\x16\x4f\xb9\x1b\xc1\x8f\x81\x22\x42\xd5\xa1\x1b\x42\x95\x27\xab\xe8\xb6\x5e\x10\x2e\xeb\x60\x22\xf0\x86\x3b\xca\x47\x7f\xa2\x06\xd3\xff\x80\xc8\x6c\x65\xd4\x92\xad\x4f\x5e\x6c\x89\x83\x3a\x99\x51\x19\xa1\x3e\xec\x34\x35\x65\x1b\x16\xf8\x1a\x3d\x5b\x37\x24\x7a\xbd\xa7\x05\x83\xb4\x7f\x0c\xe1\x69\xbf\xe5\x46\xf0\x5c\x2a\x42\xf4\x0e\x14\x27\xc7\x9d\xc6\x41\x96\x0c\x05\x6b\x6f\xde\x02\xb8\x90\xe7\x4d\x46\x63\xbc\xc0\xdd\x10\xbe\x84\x85\xa7\x02\x17\x33\x7c\x80\xd3\xac\x25\x76\xf1\xa2\x3e\x21\xd2\x1c\xb4\xaf\x5d\xd8\xc2\x80\xa5\x9f\xd8\xf6\x89\x27\x21\x09\xf0\x1e\xef\x7d\x3a\x78\x69\x89\x17\x2f\xea\x78\x63\x52\xb1\x5e\x01\x57\xa5\x8b\x49\xab\xf6\x86\xb6\xdf\xe1\x43\xfa\xef\x9b\xa6\xdf\x7a\xe4\xf3\x5f\x60\x7e\x63\xfe\xa2\x9a\x56\xa6\xef\x46\x76\x66\x8f\x5d\x35\x4f\x6e\x14\xfb\xac\x43\x82\xf2\x3f\xc5\xdd\xd2\xb7\xba\x37\xac\x39\xa1\x9f\x27\x5d\xa6\x2f\x67\x7d\xa1\xe7\x82\xd6\x83\x69\x04\x81\xde\x55\x49\xc8\x83\xa9\xae\x4f\x92\x74\x16\xda\xf0\xbe\xad\xcc\x92\x06\xc2\x3f\xcd\xd5\x6b\x8c\xe7\xe7\x17\x02\x3a\xd2\xc8\xd5\xd0\x5b\xf9\xdc\x3e\x54\x53\x69\xc3\xf4\xa1\x10\xa0\x04\x98\x9b\x9c\x1c\x45\x3c\x37\xf7\x1a\x45\x2d\xef\x4e\x09\xd8\x90\x77\x3b\xe7\x6d\x44\x08\x8d\xaf\x75\xd6\xc7\xe4\x5b\xc5\x1d\xea\xca\xc5\xd3\x06\x7a\xc4\x2b\x39\xaa\xc9\x67\x5f\x50\x1a\x4f\x24\x1f\xde\xcb\x55\x59\x4e\x94\x81\x5b\xbb\x23\x6a\xad\xa2\xdc\xfb\x0f\x49\x26\xf5\xc3\xd3\x33\x96\x5c\x65\x34\x6e\x85\xcf\xd7\x11\x85\x29\x1d\x52\x76\x63\x78\xeb\x2f\xf4\x56\xd2\x43\xc4\x3f\xdd\x4b\xf5\x87\x9d\x89\x9b\x67\x7b\x1f\x47\xb9\xfa\x58\xf9\x92\xb2\xb6\x22\x62\x17\xac\xe3\x28\xe3\x36\xce\x0b\xbc\xca\x9b\xbd\x7c\xba\xa9\xf6\xf2\x09\x52\xf0\x72\xd1\x49\x9c\xc9\xe0\x26\xc0\x2d\x4e\xd5\xb1\xdc\xcf\xf9\x2a\xa7\x3f\x8e\x86\x32\x42\x70\x45\x59\x50\x0b\xd1\x17\x5b\x00\xa4\xdd\x2e\xff\xa0\x85\x72\x3f\xfd\x67\x4f\xa3\x01\x68\x92\xbf\x2f\x25\x6c\xe4\xaf\xfd\x52\x4f\xb8\x13\x45\xbc\x0d\xba\x66\x1d\x20\x4e\x3d\x64\x26\xfe\x75\x5f\x71\x62\xc0\x3f\x0c\x58\xc2\xb0\x82\xdc\x13\x66\x04\x3a\xd8\xcc\x4a\x2f\xac\x0b\x93\x7d\x3f\x28\x75\x8b\x36\xbe\x8b\xa3\xcf\x50\x98\x22\xf8\xb3\x4c\x7e\xd7\x69\x56\x2d\xdf\x67\x31\xed\xe8\x59\x42\x1c\x67\x82\x06\x09\x14\x98\x1c\xdc\x18\x14\xfc\x0c\xfe\xec\xa4\x7d\x17\x48\xa4\x4b\x32\xa0\x34\x05\xe9\xb5\x96\x72\x29\x08\xa9\xdb\xa1\xc8\x23\x7c\x74\x69\x08\xeb\x40\x40\xa3\x1d\x86\x4a\xe6\x52\x18\x5b\xc5\x19\xc4\x6b\x0d\x78\xa6\x93\xc9\x0f\xd8\x63\x02\x03\x45\x5e\xf1\xe0\xec\x0e\xf2\x49\x32\xdf\xb8\xb0\x64\x56\x6f\x95\x71\x50\xcd\x1f\x87\xb9\x6b\x5a\x61\x32\xdb\xd7\x48\x82\x2f\x8e\x1b\x3d\x28\xb8\x63\x5b\x6c\x57\x25\x69\xd6\x1b\xb8\x1f\xa3\xb7\x63\x58\x00\x82\x63\x88\x0f\xc1\xa3\x68\x50\xc6\x71\xb7\xd3\xe9\x36\x89\x12\x19\x63\xfc\x4d\xf2\x3f\xbe\x0b\x7d\x1f\x69\x53\x68\x87\x52\x6d\xd0\xe8\x5d\x1e\xf9\xd0\x15\x36\x3b\xf4\xa8\x9f\x96\x8d\xda\x3f\x27\xaf\xac\xf2\x04\x83\x42\x7d\x67\xc5\xd9\x4d\xab\x6d\xf4\xee\xc7\x9e\xeb\xec\xcb\x43\x6a\x2c\x76\xb4\x9c\xcf\xd4\xb1\xaf\xa0\x3e\x89\xfa\xa7\x0f\x97\x47\xf0\xc0\x16\x7f\x92\x2b\x7a\x59\x6c\x3f\x47\xe8\xdc\xa6\x2a\x7b\x82\xb1\x12\x2e\xec\x6d\x37\xe4\x41\xc7\x54\xaa\x5e\x31\x44\xe5\x22\xa5\x3b\x52\x8e\x55\x72\xf0\xa0\x10\x84\x22\x62\x68\xf8\xa6\x0e\x6c\x71\x77\x24\x92\xb1\xd4\x2f\x67\x79\xbe\x52\xbf\x6d\x5a\x70\x87\x25\x14\x8b\x30\x42\xce\x15\xcf\x9d\x23\x34\xff\x62\xc1\xe8\xe8\x5c\x71\x30\x6e\xed\x08\x09\xee\x4e\x5d\x4d\x89\x3c\xbe\x71\xeb\x88\xce\x4e\x97\xd4\xf5\x7b\xd4\x88\x86\xcd\x68\xcc\x40\xfe\xfc\x31\x3f\xbb\xdb\x7e\x8b\x74\xf9\xf2\xc0\xea\xc2\x36\xcd\x9c\xd8\xda\xc1\x54\x9d\xb8\x6b\xa7\x8e\xd5\xcc\x86\x0f\x1e\xd2\x99\x19\x0f\xd2\x87\xfb\x5c\x4d\x08\x00\xe5\x7c\xc0\x74\x20\x10\xd3\x35\x4f\x3c\x34\x3e\x20\x4a\x0e\xe7\x7d\xbe\xde\x19\x2c\xff\x51\x1d\x72\x51\x2a\xcd\xaf\xf6\x9b\x41\x5c\x15\x27\xf5\x29\x79\x05\x7a\xd4\x27\x86\x1d\x13\x4b\x64\xd8\xae\x06\x44\x8d\xf6\x57\x64\x69\xbc\x40\x67\x7a\x75\x27\x31\x5c\x15\x7d\xbb\x5e\x71\xc1\xe7\xcf\x49\x3c\x06\x3e\x65\x5e\xd6\x68\x29\xc8\x51\x2a\x1e\xb9\xf4\x14\x6c\x7a\xad\x7f\x42\x80\x6c\x3f\x0b\x67\xdc\xf9\xb2\x01\xd4\xf7\x8a\x8b\xca\x03\xcd\x47\xd6\xee\x5a\x9b\x1a\x1a\x82\xbe\x30\x60\x12\xb3\x07\xe5\x7e\xfb\xdd\x07\xea\x93\x39\xa3\x3c\x21\x3a\x04\x95\x88\xce\x2b\x92\xa9\x78\xdb\xa3\x22\x22\x70\xaa\x5b\x85\x57\xc5\x7d\xf7\x8f\x15\x22\xe2\x59\x7c\xca\x92\x91\xaa\x3e\xf7\x2f\x69\x65\x2b\x55\xb6\x72\xaf\x1f\x57\x97\xe9\xd1\x57\x73\x36\x0a\x94\x67\xed\x2a\x9d\x44\x7d\xec\x7a\x81\x79\x6e\x2b\xe1\x88\x85\x77\x55\xd3\x8b\xd6\x89\xeb\xcd\x66\xa9\x14\x0f\x47\xbf\x03\x25\x21\xa9\xbb\x88\x4c\x5b\x23\xfe\x83\x22\xd1\x68\x32\x99\x66\x6d\x68\xff\xd2\x7c\x46\x71\x62\x7d\x2a\x95\x48\x88\x08\xa9\x23\x7a\x9c\xb4\xb1\x1f\x6e\x56\xcb\xb4\x80\x99\x5d\xf6\x78\x41\x20\x98\x31\x8d\xae\xa2\xa5\x6d\x01\xb7\xa9\x1f\x6b\xb1\x0a\x09\xd7\x82\x56\x12\x10\x7c\x3d\x08\xc4\x40\xbb\x3d\x85\xc1\x4f\x42\x07\xb0\x7a\xc6\x50\xbc\x64\xf3\xc0\xc9\x35\x56\x72\x6c\x24\x00\xbd\xa1\xd1\x5a\xd5\x84\x38\x90\xbb\x83\xb4\x38\x5e\xcf\x8f\x98\x71\x70\x28\x3a\x41\x36\x4a\x35\x50\x59\x32\x09\x09\xc3\xa8\x56\x1e\x99\xb5\x0e\x27\x47\x94\x89\xce\xcc\x70\x65\xe6\xe1\x9d\xad\x5c\xb6\xaa\x68\x6a\x93\x16\x1f\x1d\x0e\xa2\xd2\x70\xa1\x31\x61\x84\x8e\xca\x77\xc5\xca\x93\x53\xb9\x41\x03\x08\x24\x13\xd3\x7c\xbd\x48\xc1\xf5\x45\x23\x37\xd1\x87\xd5\xd2\xe0\xb4\xdc\x7c\xfe\xd0\x70\xb2\xde\x1c\x2a\xea\xca\xc4\x0a\x9b\x07\x60\xe5\x44\x5d\x5a\xf3\x94\x8c\x42\x2d\x92\x80\x5c\x36\xcb\x13\x69\x57\x0f\x78\xcc\x88\x47\x8d\x04\xfa\x90\xfa\xfe\xef\x0e\x47\x47\x92\x10\xa0\xd7\xae\x7e\x8d\x59\xba\x4a\xa9\xbe\x54\x37\x4d\x71\x5e\xc2\xe8\xba\x23\x82\x30\x81\xa7\xe4\xd8\xc3\xb5\x71\x87\xbe\x04\x1a\xf3\xd7\xcb\xea\x62\x8b\x30\x9a\x4b\x56\x6f\x74\xf1\x5b\x0d\x8a\x19\xd5\x96\x6d\x11\x0e\x5e\xe7\x6b\x20\x17\x6b\xb4\xba\x2d\x64\xcb\x70\xda\xdd\x9f\x7f\xff\xaf\x5e\x0c\x4a\xf4\xdd\x64\xf6\x33\xa2\xc7\xdd\x95\x46\x1a\x13\x8f\x46\xcf\x54\xe6\xcf\xba\xdb\x97\x9d\x39\x6f\x93\x5c\x53\xe3\x02\x38\xe7\x03\x19\xd1\x71\x6b\x10\xea\x22\x81\x02\xcf\x83\x78\x4c\x5f\x3a\xaf\xf8\x1c\x50\x9c\x8a\x4c\x68\xc0\xa5\x30\x21\xdc\xde\x69\xcb\x8c\x0e\xd4\x17\x7b\xe8\xe8\x38\x1b\xb5\x3a\xb9\x9e\xf3\x7a\x45\x0d\x04\x20\x18\xae\x4f\x79\xfa\xab\x8b\x2f\xd0\x98\xe0\x6c\x0d\x2c\x29\xf3\xb4\x47\xbe\x86\xf2\xe7\x8d\xc5\x71\xce\xf2\x51\xb6\x14\x98\x1b\x52\x19\xf3\x0e\x60\x81\xb0\x5c\x15\x0b\x4a\xf9\x3e\x5b\x8b\x1b\x00\x94\xa6\xa1\x69\x70\x26\xd5\x80\x40\xa1\xac\xf1\xad\x1a\xae\xb1\x0d\xae\xa9\x00\x24\xaf\x89\x05\x3a\xc1\x10\x51\x38\xb2\xa2\xa0\x42\x74\x3a\x40\x60\x7b\x3e\xbc\xa7\x85\x16\x27\xfb\x61\xe7\xde\x9d\x75\x39\x07\xe7\xe9\xfe\xf7\x39\x10\xf0\x9e\x27\xa0\x01\x08\xa9\x4c\x1e\x12\xf9\x63\xd0\xb8\xca\xc4\x91\x48\x68\x91\xf4\x64\xcd\x9e\xf2\x87\xeb\xe1\x59\x47\x8f\x66\x99\xa9\x01\x04\xb6\xab\xc1\x12\xd6\xdf\x2f\x9f\x09\x4e\xe6\x02\x3d\xf0\xf8\x53\x66\xbb\x30\x54\xab\x3b\x57\x4a\x26\xc3\x20\xc6\x49\x9c\x0b\x32\xb8\xb4\xf2\xfa\x02\xec\x33\x31\x91\x00\xdb\x6b\xc3\x89\x72\x60\xc8\xd4\x7d\xb2\x92\x41\xcc\xb6\xae\xfc\x99\xbe\xab\x13\x81\x83\xd4\xfc\xeb\x64\x08\x84\xbc\x94\x40\x1d\x0c\x5c\x71\x2d\x10\x9e\x39\x28\xd6\x42\xec\xac\x2c\x76\x11\xd1\xa3\xad\x12\x41\x4c\x58\xc2\x71\xaa\x48\x5b\xa9\x21\xc9\x66\xe4\x85\x2d\x74\x7c\xf8\xef\x9f\xd9\x04\x89\x6e\xb9\x50\xce\xa4\x52\x03\x5e\xb0\x62\xc2\xec\xd5\xf8\xc3\x47\x4f\x9f\x66\x85\x00\x3d\x2b\xa5\x8c\xa4\xe5\x68\xfe\xb4\xb0\x57\xf0\x44\x3b\x4b\x66\xde\x78\x31\x82\xc8\x5e\x17\x0b\x55\xab\x5d\x92\x33\xa0\x40\x6a\xfc\x4b\x38\x7b\x56\xdb\x2e\x20\x22\x6b\x35\x02\x81\x0f\x1d\x11\xb0\xd1\xfe\x68\xa5\x47\xc2\xbe\xb5\x70\x43\xe9\xb9\x92\xb3\x2a\xf9\x36\x04\x06\x69\xaa\xd3\x53\x2b\xd0\xbf\xb8\x75\x34\x34\x39\x35\xea\x64\x6a\x90\x2b\x0c\x86\x9d\x4b\x6b\xb9\xd2\x4e\x71\xe9\x42\xa5\x19\x02\x05\x94\x4d\xf0\x88\x13\x0e\x2b\x2b\x3f\x7b\x07\xc6\x32\x13\x4d\x83\x9b\x4e\x4a\x7f\x56\xf1\x75\x10\xfc\x39\x30\xd1\x24\x23\x64\x56\x9c\x2f\xd5\x2c\x29\x91\xcf\x0d\x41\x6b\x30\x94\xc6\x82\x5e\x1b\x8c\x87\x81\xf9\x46\x1c\x94\xdf\x9b\xcd\x05\xc0\xdc\xdc\x6e\xb1\x02\x8b\xf7\xfb\xba\x94\x3c\x25\xa2\x11\x9c\x4a\xad\xc0\x9c\xf7\x8c\x76\x71\x00\x24\x9c\x9b\xea\x1e\x9f\xc9\xe8\xaf\x64\x09\x40\xe4\x77\x77\xf5\xb8\x3f\x9d\x04\xe5\x52\xc0\xfd\x18\x73\x90\x0a\x44\x31\xab\x46\x13\x2d\xa0\x5f\xf1\x45\x31\x7d\xfd\x7a\x63\xe3\x91\x16\xc6\x9d\x5a\x8c\x19\x68\xd0\xf4\x5b\xdc\x11\x1e\x07\x94\xc6\xcf\x24\xc3\xfd\x9d\x26\x05\x00\x44\x57\x78\x18\x26\x66\x65\xc5\x25\xe9\xed\x20\x7e\x29\x09\x7e\x8e\x12\x83\x58\x4c\xb7\x74\xcb\x9b\xdd\xd2\x85\x96\x8e\x4a\x06\x4b\xdd\x2f\x2f\x28\x97\x46\x5b\x0c\x98\x4b\x59\x3d\x3b\xca\x1f\xca\xd8\x95\x62\xff\xfa\x97\x83\x7e\x24\x56\x64\xb8\x5d\x9a\xa2\x38\xda\xdc\x7c\xd4\xf7\x1a\x02\x81\x62\x4a\xd3\x16\x29\x3a\x76\x20\xff\xfa\xa3\x18\x33\x52\x86\x52\x97\x51\xb4\x8f\x04\x7d\xcb\xba\xe4\x7f\x4f\xed\x0c\xd6\x09\x6b\x06\xc5\x55\x50\xc4\xc1\x8b\x7d\xb3\x9f\x53\x56\x95\xaf\xfd\x0c\xcc\x7f\x78\x7f\x73\x00\x51\xca\x72\x6f\xaf\xb1\x9f\x33\x1e\xa3\xff\x7a\xe7\x90\x32\x89\x46\x10\xa4\x8c\xd2\xfa\x27\xd6\xaf\xa3\xd8\xdd\x6e\x4e\x3f\xf0\x1e\xd7\x7b\x22\x5d\xf5\x31\x16\x42\x2b\x1f\xc4\xd5\xb5\xa5\x0d\xe3\xb0\x3b\x2a\xab\x0a\x8a\xed\xd1\x65\x4f\x5d\xc2\xdd\xd6\x2d\xce\xd2\x4e\x7e\xb5\xbf\xf8\x32\xf5\xcc\x9c\xf2\xa3\x75\x25\x6c\xc5\x28\x5a\xbe\xad\xbb\xa3\x9d\x62\x7f\xa1\x39\x4d\x99\x68\x5d\x5a\x1f\x0e\x33\x27\x29\xa2\x14\x39\xa0\x23\x87\x3e\xcc\x2a\xd7\x03\x3c\x63\x8c\x3b\xda\x1c\xd4\x9a\x7d\x6c\x3e\xe2\xa7\xfb\x25\xfb\x29\xb7\x56\x60\x10\x6c\x65\x59\x17\xee\x2e\x35\x2a\xd0\x0f\xd9\x0f\xa5\x44\x7e\xea\x2d\x0c\x89\xf6\x07\x64\x35\x4a\xe1\xc6\x5a\xf5\x21\x51\x03\xb5\xb9\xd3\xa6\xa7\x5e\x66\x01\x50\x80\xa3\x2f\x66\x6a\xbe\x0b\x81\x54\xca\x58\x91\x12\xa2\x04\x58\x26\x28\x66\x21\x08\x88\xc3\x9d\x5e\x13\xf2\x98\x67\x2f\x6a\x3c\x09\xb3\x2f\xda\xc7\xeb\xa5\x83\x53\x27\x4a\xd6\x93\x35\xe1\x56\x5e\x09\xfe\x95\xfa\xdf\x9f\xbf\x9e\x5e\xc4\x19\x6d\xbc\x7b\xa0\x8f\x06\x32\xbe\xac\x3b\xa2\xa5\x0d\x30\x69\x37\x04\x24\x01\xe0\x0f\x07\x16\x26\xe2\xa9\xb5\xfe\xd3\xb5\x8e\x8d\x8d\xab\x8f\x58\x45\x4f\x53\xe8\x1f\xc0\x78\xc6\x35\x0e\x1e\xc7\xb1\xbd\xd9\x8a\x74\x22\x8e\x15\x68\xaa\x11\x88\x76\xe7\xaf\x5f\x43\xda\x16\x83\xe5\x53\x95\x9b\xbd\x7e\x41\x24\xba\x3c\x86\x40\x0b\xd1\x01\xbc\xe5\x1e\x66\x8a\x5c\x3b\x53\xcc\x61\x8c\x29\x9a\xa6\x36\x43\xd1\xd1\x5f\x9d\xde\xdf\xce\x8a\x0c\x67\x30\x28\x34\x69\x2d\x6b\xc2\x13\x3c\x05\x0a\x23\x35\x74\x8b\x5c\x43\x43\xa3\xab\x19\x68\xf5\x3e\x0c\x3b\x8f\x21\x60\xb6\x08\x90\xa9\xa8\x0b\x20\x33\xaa\xf3\x2d\xd7\x00\x05\x36\x95\x68\x74\x0f\x89\x44\x5d\x1b\xe9\x53\xb0\x65\x4e\x87\xa8\xea\xeb\x0d\x8d\x7d\x83\x7d\x8d\x8d\x8b\xa8\xe6\x22\xad\xde\xce\xcf\x13\x23\x51\x6e\x93\xb7\xb2\x16\xba\x60\x46\x3a\x9f\xc3\x19\x10\x04\x3e\x15\xa1\x37\x39\x24\x6c\x56\xda\xcc\x65\x7e\xcc\xcb\xc7\xcc\x88\x16\x4a\x10\x61\xfa\x25\x93\x89\x71\x7e\xd6\xdc\xa3\xb3\xcb\xb4\xaf\xa7\x5e\x0f\x6c\x87\x43\xb1\xf4\xb3\x03\x0d\x66\x2b\x2f\x0e\xae\x0b\xb9\xfe\xe1\xb4\x65\x42\x61\xbb\xe8\x13\x3c\xed\xba\x27\xb4\x20\x5c\x2a\x00\x46\xf3\x99\x43\xdb\x3b\xad\x8d\x7c\x1c\x84\x63\x0d\xb7\x86\xda\x80\x98\x4e\xba\x7f\xf6\x66\xbe\x21\xe0\xff\xf9\x4c\x32\x69\x7e\x81\x3c\x5b\x0d\xc5\xd8\xc5\xed\x70\xeb\x84\x08\x26\x9a\xd1\x95\x41\xbe\x6b\x6e\xee\x6e\xba\x90\x72\xbe\xed\x8b\xa7\xfd\xec\xe9\x1b\x6e\x26\xbb\x66\x17\x7f\x76\x1c\x6e\x6a\x6e\x94\x2d\xcd\xe8\x32\x1f\xdc\x35\x28\x21\xec\xd1\xf2\xa2\xf4\xd5\xdd\xc4\x72\x43\x7e\x87\xe4\x8a\x44\x04\xb2\x97\xcd\x22\x60\x5c\x54\x9f\x27\x6a\x09\xbe\xcc\x50\x60\x92\x30\x69\x1a\xdc\x4f\xcd\x9a\xe7\x9d\x46\xec\x6b\x72\x66\xed\x75\xc9\x99\xf7\xa2\xda\xa9\x6a\x5c\x27\xaf\x1e\x33\x83\x21\x42\xba\x49\x45\x6c\xdf\x51\x3f\xa6\xf3\x6d\x31\x32\x3c\x54\xbf\xa7\xf3\x12\x52\xe7\xa4\xa5\x7c\xc0\x58\x7d\xdf\xf5\xe7\x0b\xef\x76\x85\xab\x66\xe9\x2a\xb7\x3f\x5f\x88\x4b\x7c\x49\x59\xf5\xde\xc4\xfb\xa3\x92\x85\x7b\xbd\x25\x6d\x60\x2a\x10\x35\xdc\x44\xbb\xa4\xd1\x60\x8c\x87\x4e\x81\x9f\x39\x24\x23\x93\x63\xbd\x87\xa4\x0c\xd8\x14\xa0\x05\x18\x7a\xe1\x4b\x8b\xca\xcf\x17\x84\x74\xb1\xd8\x80\x1f\x0b\x64\x82\xba\x6b\xd8\x81\xdd\x37\xf3\x07\xec\x5b\x83\x33\xa8\x03\x7a\xa2\x19\xdc\x90\x2c\x9e\xa6\xc1\xbd\x62\x3c\xf7\x1a\x7c\x53\x3c\x97\x7e\xd8\xba\x2d\x56\x45\x89\x6c\x0f\xcc\xa4\xaa\x02\xed\x69\x41\x40\x4f\x5b\xb6\xd8\x2e\x35\x3e\xc4\x70\x51\xf5\xa5\xa5\xe2\x65\x8b\x3e\x96\xe1\x52\xc7\x77\xe7\xd8\xaa\x44\xe7\x2e\xdb\x8b\xd0\xde\xe4\x0d\x58\x4e\x23\xb1\x27\x4e\xa2\xa4\xca\x6a\x6a\x01\xa2\x91\xd0\xbe\x34\x17\xd5\x21\x06\x99\xb1\x74\x4b\x5f\xbd\xe2\x93\xcb\x66\xa5\x52\x80\xc0\x21\x40\xe6\xa3\xbc\x43\x12\x94\x4a\x2d\xa8\x12\x6a\x61\xc9\x1e\x48\x2a\xf6\xcd\x0c\xe3\xfb\x8d\x81\x9d\x4e\xee\xcb\x70\xb4\x40\x77\x97\x56\xb4\x5b\x3b\xbb\xdd\x0d\xdd\xea\xe2\x9e\x84\x73\xec\x71\xc2\xe5\xd1\x48\x8a\xa4\x6c\x81\xb6\xda\x9c\x41\xbb\x3f\xd4\xfe\x79\xad\x09\x22\xba\x6a\xfd\x21\x80\xe4\x84\xd6\x3c\x7f\xdc\x55\xb4\x3f\xdd\x68\xbd\xe5\xc0\xe5\x7f\xa6\x6b\xe1\xa7\x31\xb1\xa6\x6f\x61\xde\xbb\xf8\xdb\xd6\x65\xe9\xfd\x38\x53\x80\x9c\x31\xf7\xd0\x9d\xe4\x8b\x84\xb6\x04\x8c\x21\xd3\xf3\xba\xe2\x39\x93\x68\x85\xd8\x49\x0d\x18\x87\xd6\x42\x8e\xeb\x0a\x07\x11\x39\x4b\xab\x6f\x5f\x28\x00\x5b\x01\x66\x19\x30\xb7\xb8\x88\x6f\x21\xfc\x0b\x85\x92\xf9\x33\x31\x1d\x9e\x43\xb7\xbe\xc1\x3b\x58\x0e\x96\x49\x68\x24\xa5\xc9\x80\xe7\xa6\xb9\x40\x84\xc5\x40\x30\x57\x6c\x0d\x1f\xdd\x11\x5d\x86\x26\x29\x73\x36\xf0\xe0\xa8\x34\x77\xf1\xa4\x59\x90\x33\x63\x2e\xfc\xe3\x4d\x02\x67\x0b\x5e\xbc\x14\xc8\x31\xd2\xc7\xe9\xb9\x4f\xb3\x71\x73\x23\x4d\x73\xf1\x82\x33\x5a\x4e\x4c\x4d\x69\xf6\x7d\xf0\xf0\xc6\x0d\xa1\x39\x8d\x7f\x55\x82\x7e\x87\xe8\xb3\x78\x7e\x7b\x16\xae\x24\x36\xba\x08\x9c\xa8\x03\x46\xd5\xc9\xac\x51\xaf\x45\x69\xee\x32\x57\x76\x86\x59\x14\x46\xa6\x0c\x41\xdb\xe7\x9e\x56\x10\x6c\xa8\x0b\x14\xb8\x06\xed\xd6\xe4\x04\x56\x44\x58\x65\x72\xe2\x28\xb4\xc0\xb0\x5a\xba\x65\x9e\x92\xeb\xcd\xb0\x90\x16\x33\x29\xdb\xca\x5c\x74\x00\x1a\x8a\xf9\x35\x5c\x5e\xe1\x22\x72\xf2\x19\xd0\xa8\xe7\x73\xb3\x0a\xdc\x77\xee\x1d\x50\xe4\x35\x8e\xaa\x66\x37\xa1\x4e\xdf\x4b\x24\x66\xb3\xc8\x5e\x71\x7b\xb0\x22\x4c\x8d\x9d\xdc\x5d\xaf\x88\x19\x7a\x60\x40\xf8\x95\x44\x51\x68\x97\xcc\x04\xe6\x36\x66\xb2\x9d\x16\x95\x1c\x7e\x68\xab\x47\xa9\x35\xc6\x75\x55\x04\x37\x47\xe4\xf0\xed\xeb\xb8\xc4\x15\x7e\xf7\x0a\xc1\xb8\xe3\xf5\x2e\x88\x23\x33\xf1\x50\x13\x0b\x8e\xfa\x54\x56\xca\x21\xbc\x1f\x6e\x7f\xac\xaf\xef\xda\x98\x05\x50\x66\x36\xa0\xd5\x89\x3e\x6c\xdb\x36\x09\x39\x40\xdd\xd2\x96\xf7\xa6\x99\x1e\x8f\xa5\x02\xe0\x35\xcf\x9a\x36\x32\xf2\xf9\x74\x40\x37\x0a\x9e\xe1\x4c\x8e\xce\x32\x09\x1d\xf6\xd7\x17\x20\x74\xfc\xf5\xed\x27\xd4\xaf\xc0\x62\x48\xca\xe4\xef\xd4\xbc\x01\x88\x77\x12\xcb\xe6\x57\x66\xf2\xf1\xb7\xc9\x8a\x37\x3d\xcc\xdb\xfc\x2e\x3d\x62\x78\x0d\x25\x05\x64\x3f\x0d\xba\x7f\xc1\xee\x8d\x61\xb3\xca\xcb\x20\x92\x39\xe0\x65\xff\x70\x90\xa7\x8b\xbd\x48\x8f\xd2\xa9\x0c\x4b\xc8\xe5\xf7\x5c\xf0\x90\xc5\xdb\x8f\xfb\x9d\x84\x9e\x84\x8c\x24\xa0\xb0\x98\xe3\x9b\x43\x25\x96\x30\xa8\x96\x1c\xc1\xe6\x0d\xc9\xc6\xca\x05\xe6\x83\x01\x9d\xdd\x6e\x74\x76\xa3\xbc\x3a\x80\xb5\x4d\xc8\x60\xe1\xb3\x91\x42\x84\x8d\xdb\x61\x73\x70\x93\x26\x0b\x29\x02\x22\x2d\x12\x71\x63\x83\xa3\xaa\x09\x9b\x93\x40\xa9\x49\xe2\xc7\xe8\xf3\x62\x6b\xdc\xd9\x14\xb9\x9d\xa9\xcc\x05\x33\x65\x50\x9c\x16\x46\x38\xdd\x01\x89\x5a\x6d\x55\x4c\x28\xd9\x11\x28\x71\x50\x30\x35\xbf\x19\x6e\x19\x27\xbc\xa5\xc1\x43\xf8\xc7\xc2\x56\x89\xb5\x8a\x69\xc0\xb5\xaa\x9b\xda\x12\x93\xa1\x8e\x6a\x95\xd0\xf0\xc9\xbf\x04\x58\x3f\x71\xe9\x67\x5e\x3a\xd3\x9b\xc0\x5b\x5b\x50\xb0\x56\x38\xa9\x9c\x19\xb2\x0b\xa1\x9f\x36\xa4\x00\xda\x3d\x49\xc9\x89\x28\x08\xb5\x63\x06\xcd\x47\x96\x9a\x15\xdb\x40\xa9\x15\x17\xbd\xe0\x4c\x62\x21\x6c\xb7\x6c\x05\xdc\xc6\x38\xdf\xac\x4d\x76\xda\xf9\xfa\x9d\x76\x56\x62\xf5\x71\xdf\x7e\x15\xdc\xd2\x12\x2f\xa4\xda\xcd\x25\xc7\x49\x69\x1f\x88\x85\xc0\xb6\xd2\x82\xcf\xa1\xd6\xa3\x54\xf3\x9d\x3d\xfa\x21\x42\xb3\x83\x04\x50\x06\x53\x06\x3a\xa6\x6d\x9d\x75\xac\x76\x8b\xd0\x04\x05\x50\x04\x9f\xc8\x73\xcf\xcf\xa5\xef\x3b\xa7\xbf\x17\xa6\xcf\x5a\x04\x7c\x73\x2c\x16\x47\x85\x0f\xcb\x3a\xe0\xc6\x70\x48\xf6\x8a\xaf\x67\xd9\xe9\x56\x15\x75\x80\xa3\x17\x5a\x08\x52\x3e\x66\xe6\xcc\x40\x9d\xe2\x00\x65\x14\xe2\x8b\xae\x40\x46\xc3\x3c\x36\xe3\xcd\xb2\xe0\x2e\x1d\x05\x93\xba\x4c\x81\x0d\xd6\x10\x2f\x81\x29\x93\x58\x94\x0b\x04\x33\x22\x4c\x4e\x3e\x94\x5e\x82\x6d\x0b\xd4\x14\x98\x77\x27\xd6\xc1\xe5\x15\x95\xa9\x3e\xdb\xfa\xd4\x1b\x5c\xe3\x43\x3c\xeb\xf1\x85\x43\xfd\x4b\x62\x60\x9e\x28\x2e\xf6\xee\x75\xd6\xc1\xd6\xb0\x9a\x81\xa5\xd6\x54\x9e\x18\x27\xc8\x20\x82\x6f\xef\xd5\x06\xf3\x4d\x47\xf4\x98\x7b\x1d\x78\xb8\x24\x0a\x76\x06\xac\x1b\xfa\x39\xef\x0a\xab\x7c\xe8\x9e\x46\xb0\x8d\xc9\x78\xca\xca\x80\x61\x10\x40\x51\x49\xdb\xd6\xa7\xf3\x27\xed\x7f\x3d\xcf\x7a\x7c\x51\xf9\x6f\xd8\xfc\x5e\x42\xec\x66\xd3\xff\xa2\x2c\xb3\x5a\x66\xfa\x57\xfa\x01\x34\xe6\xa9\x23\x9d\x08\x07\x34\x93\xce\x79\x81\x49\xac\x07\x95\x98\x39\x23\xdb\xf4\x35\x0c\x0e\x5a\xda\xad\x0e\x45\x0c\xa7\xd9\xe6\xc0\x32\x1d\x07\xe2\xb7\x70\x93\x27\xc6\xdb\x16\x42\x87\xa4\x7e\xbb\xa5\xf6\x55\xb8\x6a\x7d\x15\x1a\xdb\xa3\x10\x57\x77\x45\xfd\x60\xee\x09\x0d\x11\x6d\xf7\x27\x3f\xe8\x16\x21\xac\x40\x20\x00\x80\x83\x43\x20\x32\x43\xd9\x1e\xf9\xd1\x00\x70\x63\xad\xc4\x08\x6c\x13\xdd\xbb\x4f\xc5\xa1\xd8\x1f\x7b\x28\xbe\x43\x32\x0e\xc9\xe0\x6b\x43\x89\x83\xf1\xd1\x6b\x81\xf6\x27\x8c\x55\x98\x22\xae\x16\xe9\x43\x3f\x08\xbf\x0c\x54\xf2\x51\x5e\x90\xee\x0c\xda\x9d\xb8\xa4\x6b\x4b\xf1\xe6\x6d\xc5\x33\xce\xe9\x6d\xec\xea\x24\xba\xdb\x9d\x16\x81\x00\x8e\x1f\xcd\xae\xb0\xb4\x5d\xe0\x3c\x69\x28\x00\x51\x26\x77\x6c\x64\x6d\x59\xdd\x31\x9f\x20\x0f\x73\xbb\xe8\x33\xec\x95\x68\x4f\x01\x4a\xa6\xa5\xff\xf1\x3a\x9c\x4e\x89\x49\xa2\x95\x37\x4e\xc1\xd8\x24\xa9\x7a\x16\xda\xb8\xba\xf4\x0b\x23\x23\x1c\x04\x6f\x74\x34\x7a\xcf\x8a\xb9\x70\xe3\xe4\xe9\xa9\x9a\x9c\x30\x8f\xa4\x6b\xfe\x78\xe5\x0c\xc8\xac\x55\xaa\xb7\xb6\x18\xcf\xc3\x9c\x46\x7e\x3a\x28\x7c\xb6\x42\xb9\x8e\xfc\x94\xcb\x6e\xe9\xe9\x6d\xc6\x09\x60\x4e\x0b\x2d\xab\x95\x8f\x64\xcd\xfe\x6c\x9d\x9d\x39\xa3\x2f\x19\x5c\x54\xcc\x26\x31\x89\xcc\xc2\x03\xbe\x17\x01\x39\x9b\x56\x3c\x76\x6e\x1f\x06\x03\xb7\x3a\x7d\x3b\x42\x2b\xd7\x87\x0e\x64\xde\x53\x8e\x5c\x48\xa0\x11\xda\x08\x0c\xc9\x6c\x35\x14\xed\x20\x6a\x8b\xa8\xa6\x66\x65\x5f\x88\x8c\xd6\xe9\xe6\x4e\xcc\x81\x61\xc4\x38\xbf\x82\x7c\x7c\x67\xf5\x80\xc0\x78\xcc\xd4\x57\x46\x8c\x69\xf0\xc8\x25\x11\x43\xcf\x46\x01\x23\xed\xf6\x4d\x6b\xa7\x8c\x31\x97\xe8\xf4\xb1\x11\x06\x9e\x77\x4a\x25\x22\x83\x11\x5c\xd3\xbe\x37\xc5\xdb\xc3\x17\xa4\x52\x0d\x18\x19\xeb\xdc\x36\xbd\x3b\x94\x7b\x3c\xb1\x55\x4b\x91\x39\x60\xdc\x3b\x24\xea\xd1\xbe\xb5\x3c\xe1\xbb\x7b\x62\xf1\x61\x2a\x4d\x77\x66\xd4\xb1\xba\xb3\xa8\x4f\x5f\xee\x67\xa8\x32\xc3\x0f\x0e\xf9\x45\x17\x06\x6a\x89\x5d\x56\x11\x16\x01\xe4\xd7\x34\xf2\x58\x95\x0c\x2a\x8f\xe9\x67\xef\x53\x30\x8c\x4b\xf7\xbc\x88\x63\xfe\xeb\x8e\x41\xa4\x81\x54\x1a\xed\x50\xf9\xdd\x8f\xb8\x60\x7e\x8f\x65\x3f\xa1\x16\x46\xfa\x5b\xbe\xba\x6e\xba\x6a\x58\xcc\x6e\xd8\xb1\xdb\x55\x94\x95\x35\x5a\x20\x1b\x1a\xbc\x22\xa0\x92\x0e\x70\x88\x73\x73\x99\xb4\xd6\x34\x31\xd8\x40\xb7\x84\xcf\x01\x06\x94\xd6\x10\x47\x69\xc0\x3c\x4a\xdb\xc4\x3c\x7b\xa6\xc9\x7a\xd3\xe5\x01\x9f\x0e\x0b\xde\xa2\x4d\xd6\x7d\xa0\x0c\x61\x9b\xcf\x21\x42\x65\x3a\xe1\xdc\x8d\x6f\xb9\x60\x2d\x93\x43\x5c\xd8\x2e\x79\x6b\xac\x1a\xfe\x24\x03\xf6\xec\x82\x65\x78\xc7\xb3\x80\x4e\xf0\x48\x95\x01\x1e\xd2\xe8\x90\x28\x81\xcb\xc8\x5f\x8c\xa3\xbd\x9d\x01\x21\xcb\x4b\x46\xb3\xab\xd7\x08\x6f\x74\x76\x57\xd5\xd8\x77\x2d\xe5\xc4\x73\xb4\x4c\x00\xd2\x3e\x89\xcc\x5d\x39\x62\xf3\xb0\x09\x88\x4a\x6e\x12\x99\x29\x73\x6e\x9c\x74\x5f\xf2\xf2\x19\xeb\x5f\x0f\x78\x45\x4b\xad\x94\x44\x94\x06\x20\xa5\xbc\x42\x09\x99\x24\x67\x59\x98\x41\xbf\x56\x3e\x1f\x67\x24\x95\x25\x4c\xd0\x30\x4c\x23\xee\xe3\x7b\x1b\x26\xce\x9d\x98\x96\x46\x74\x0f\x64\xeb\x5c\xc0\xa5\x50\x94\x13\x3d\x9c\xd2\x1b\x61\x34\xe2\xca\x0d\x8f\x1f\x0f\x38\x22\x9c\x3c\xdc\x9d\x8a\x8b\x73\xfc\x4c\x5e\x5e\x4e\xdf\xdc\xf2\x45\x63\x9c\xc7\x76\xb9\xac\xed\x48\x2d\x5f\x3e\xe9\x97\xf2\xa7\xf1\xd6\x8b\xd8\xda\xf8\x02\x3b\x7c\x2b\x87\x63\xa9\xc8\x21\x8b\xa9\x04\xbf\xb6\xbf\xde\xea\x0b\x38\xbe\x1f\x4f\x2f\xd2\x2e\xe8\xa7\x84\xc1\xf7\x4a\x6e\xc6\x38\xbc\x26\xa8\x2c\xec\x11\x81\x96\x25\xeb\x73\xf3\x74\x90\x5d\x36\x28\x0b\x6b\x07\x96\x48\x36\xf1\x0c\x89\x46\x71\x23\x28\xdb\x89\x5b\x96\x79\x97\x8c\x8f\xa6\x7b\xfb\xc1\x30\x28\x93\x5e\xe0\xca\x0b\xd6\xbf\xc1\x62\xd6\xf8\xeb\xd7\xa3\xac\xc5\xac\x0e\x03\x83\x92\x80\xe4\x17\x14\x00\xdc\xda\x0b\x9d\x9d\xfd\xb4\x91\x26\x66\x86\xce\x7a\x43\x71\x49\x89\xcf\x12\x10\x15\xdd\x3c\xce\x9c\x24\x92\xab\x28\x28\x68\x5c\xd2\x45\x44\xe9\x43\xd1\xf4\x1f\x01\x1d\x15\xad\xdd\x1c\xdc\xf3\xe9\x63\x5f\xe8\x78\xf6\x2f\xc1\x83\x45\x82\x2e\x3a\xe4\x1c\xfd\xfc\x69\x5e\xf8\xc6\x2b\x8a\xce\x9f\x9e\x31\x7f\x18\xd7\xa6\xc9\xf3\xd2\x82\x4a\x69\x34\x40\x60\x6c\x87\x78\x10\x4e\xef\x4c\x24\xe6\x90\x98\x36\xc3\xd2\x54\x97\xaa\xc5\x12\x2e\x9d\x96\x3f\xd0\xea\x8f\xe4\x0f\x34\x07\x5d\x0c\x8d\x58\xa4\x31\x68\x7c\x7d\x67\x38\x3c\x31\xc8\xa4\x3c\x0b\xee\x40\x4b\x02\x8d\x9a\x2f\x16\xc7\xf5\xa2\x2f\x0b\xe3\xa5\xd1\x35\xed\x70\x01\xc8\x7f\xd7\x9c\xca\x6f\xeb\xe8\x91\x74\x92\xae\x70\x87\x10\x61\x20\x6a\xe9\xa5\x74\xe0\x62\x45\x91\x12\x9c\x0b\x45\xa9\x79\xf6\xb7\x26\xd0\xa6\x34\x60\xd8\xaf\x11\x89\xbd\xb5\x24\xd2\x4c\x87\x04\x9d\xf9\x22\xab\x85\x7f\xad\xe7\x83\x4a\x76\x69\xbe\x0c\xc1\x6c\xee\x00\x6a\xa3\x5a\x25\x3d\x27\x29\xbe\x96\x38\x96\x18\x65\xe6\x88\x14\xc8\xe1\x60\x38\xfc\x54\xca\xe1\xc7\xec\x2a\x8f\x4d\xe7\x38\xf5\x9b\xbb\x2e\xac\x80\x87\xbb\x8d\xd6\x77\xb8\x7e\x0f\xc9\xe2\xf5\x5c\x28\x48\x94\x74\xa4\x76\x0b\x72\xab\x22\x6a\x44\x6f\xbd\x47\x10\x47\x0d\xe6\x98\x69\x03\xfe\xb2\x84\x6c\x03\x48\x65\x8c\x86\x25\x69\x61\x26\x39\xb3\x64\x89\xb6\xcf\x1c\x64\x3e\xf3\xfc\x0e\x2d\x69\x0d\xb7\x6c\x4d\x12\xee\xbe\xdc\xb0\xd9\x16\xa1\x54\x41\xef\x94\x24\xb6\x9c\x56\x48\x47\x7c\xe7\xb3\xec\x0a\x88\x17\x24\xc7\x0f\x0b\x0b\xea\xf9\x3a\x1d\xc7\x12\x31\x52\x0c\x15\x73\x5c\xf0\x5a\x20\x14\x24\x91\x50\x6a\xd7\xdb\x87\xbd\x8f\x5d\xd9\x8b\xc6\x67\xd8\x38\x60\xe7\xb0\x86\x20\x16\xfb\x7a\xdf\x92\xf2\xa4\xcb\x56\xd4\x58\x8f\x19\x15\xa3\xdd\x95\x78\xba\x72\x74\x58\x2f\xa0\x41\xd1\x70\xd7\x32\xb4\x0f\x08\x5e\x5b\x31\x7e\x52\x7b\xef\x08\xeb\x9a\xac\x97\x19\xb2\xbc\xc9\x87\xa2\x3a\x6b\x0e\x43\x11\x55\x12\x27\x35\x6e\x98\x90\x1c\x25\xa1\x27\xd7\x43\x58\x02\x50\x30\x36\x47\x83\xdb\xae\x91\xfb\x6c\x5b\xe9\x3c\x96\x1b\x4e\x83\x73\x63\x4f\x46\x65\x51\xfa\xca\x2d\x92\x67\x69\x24\xf3\x18\x52\x4e\xe8\x13\xb2\xfd\x6f\x19\x37\xd2\x57\x7a\x9a\x0d\x5f\x74\xba\xb9\x22\x3f\xea\x7a\x3c\x51\xd5\xeb\x6c\x26\xb5\x91\x42\x2c\x35\xec\xa5\x22\xfa\x7d\x12\x5c\xd9\x11\xdb\x69\x5e\x93\x7c\x7d\xc3\xf0\xb1\xa2\x52\x9f\x9c\xbd\xd8\x19\xe8\xb4\x6c\x0f\x3b\x7f\x24\x89\x8c\xd1\xbb\xf9\x27\x64\x78\x77\xe1\xf2\x41\x2a\xc6\xcd\xba\x31\x0f\x5f\x77\xf0\x66\x24\x6f\x72\x97\x77\xa6\x56\xa5\x15\x24\x0a\xc8\xe9\x54\x1d\xdb\x48\x06\x69\xf9\xf3\x03\xfa\xf2\xd3\x4c\x16\xdb\xe2\x16\xfc\xe4\x6c\x56\x07\x63\x5c\xa0\xa7\xbc\xbe\x37\x4f\x0b\xec\x8a\x9a\x0e\xb7\xf4\xc5\xb9\x52\x86\x44\x29\xd7\x5d\xee\xf8\xbc\x8c\x42\xee\xd1\x01\xd3\xe4\xb6\x3d\x33\x95\xe8\xe9\x71\x46\xc9\x4d\x4d\xc9\xe8\xc8\x93\x86\x42\xca\xfc\x67\xb7\xc9\xd8\xdb\x0a\xad\x4f\x4d\x5b\xfa\xd4\xb0\x60\x12\x10\xf4\xad\x57\x5b\x70\x42\xce\x89\x74\x0c\xbb\xdf\x02\x69\xca\x5c\xf6\xf1\x00\x04\x40\xfb\xbf\x60\xde\x7b\x19\x58\xea\xd1\xf1\x2f\x29\xd3\xc6\xa9\x63\x44\xbb\x52\xa7\xff\x50\x76\x7a\xee\x8b\x78\x9f\xee\xa6\x34\x39\x48\x13\x86\x5f\x9f\xc1\xd9\x87\x85\x23\xe9\xba\x31\xa2\xf9\x26\xd3\xeb\x50\xc2\x2f\xd6\xd5\xd6\xa1\xa7\xd5\x26\xae\x7f\x55\x9c\xa8\x75\x8e\xa8\xe0\x29\x96\xef\x6c\x39\xf6\xd0\xad\xf6\x3a\x21\xe5\x7d\xc9\x91\xbc\x3d\x5b\xf2\x12\x2a\xb2\x99\x3b\xa7\xad\xb2\x01\x84\x75\x7b\xb0\xb4\xb1\x03\xeb\x2e\x1a\xa4\x96\x70\x11\xbd\xe2\x22\xea\x21\xea\xe2\x06\x2c\xfe\xbc\x7c\x1c\x76\x0e\xab\x0f\x6e\x4e\x19\x9b\x4b\x0c\x13\xed\x36\x33\x75\x00\x64\x3e\x83\xf6\x36\x8c\x97\x04\xbb\xcf\x79\x2f\x48\x16\xa2\x7d\xdc\x13\x1e\x92\xf1\xd1\x91\x83\x02\x7b\x71\x4c\x81\x1d\x9c\xf1\x24\x92\xf2\x0d\x0a\xe7\x9c\xe0\x2d\xc4\xc4\xf4\x61\xa1\x8f\x5b\x8e\xfe\xf9\x73\x74\x0b\xdd\x6e\x53\x8c\x6e\x32\x8e\xc4\x9f\xe0\x40\xa1\x7f\x92\xee\x1a\xd1\xb7\x8a\x8d\x0f\xbf\x0e\x0f\x8f\x8c\x78\x48\x4e\x70\xc1\xa2\x89\xc7\xe3\xb5\xde\x10\x1e\xd2\x32\xf1\xd0\xe3\x08\x26\x04\xe1\xe9\x0b\x33\x03\x09\xa7\xf1\x84\xf3\x91\xcd\xc0\xc6\x66\x8c\xf7\x78\xe3\x0f\x29\xe7\xfa\x0c\x11\x01\x57\x50\x27\x68\x82\x37\x66\xf2\x3e\x91\xda\x20\x96\x02\x73\x21\xa8\x3b\x15\xfc\x70\x81\xd5\x26\x51\xfd\xb1\xb7\xce\x63\x0e\x4e\x1f\x04\x3e\x4f\x67\x64\x48\xf7\x45\xde\x31\x75\x09\x10\x7b\x84\xcc\x5e\xcb\xda\xaf\xfc\x56\xe4\x7d\xf1\xe8\xe3\x32\xdb\x40\xe7\x4a\xca\x48\x05\x95\x53\xe1\x16\x1e\xf6\x14\x3e\x21\x7e\xf5\x16\x9b\x4c\xe9\x5e\x64\x1b\x10\x09\x98\xe6\x72\xc0\xd2\x35\x2f\xe7\x1d\x90\x47\x79\x4e\x0f\x57\xfe\x08\x2d\xf5\x60\x05\xa4\xb1\x1b\xe2\xe4\xc9\x9a\x4c\x4a\x03\x9e\x8b\x3d\xa9\xd4\x28\x52\xa5\x56\x32\xc3\xc8\x8f\xec\x4d\x3b\xbe\x3a\x8b\x2d\xcf\xec\x41\x08\x30\x3c\x19\xc8\xa4\x09\x4c\xc3\x07\x31\x4c\x3c\x46\x28\xd2\x4a\xee\xad\xf4\x14\x4c\x0e\x86\xee\x43\x6c\xa8\x59\xf7\xf6\xc3\x4e\x8f\xfc\x03\x5f\x37\xed\x00\x3a\x2a\x95\x5c\x38\xcd\x8f\xde\x77\x08\xa0\xea\x0b\x0d\x64\x35\x27\x4c\xb2\xdf\xcf\xe5\xa6\xee\xf5\x48\xf7\x73\x35\x4d\x20\x9e\x32\x49\x44\x8e\x25\x9e\xb6\x57\x50\x5c\x70\x79\x72\xa2\x7e\x85\x83\xd2\x8d\xe9\x29\x71\x4e\x30\x07\xc5\x45\xf7\x7c\x29\x89\x28\xf5\x40\x01\xfc\xd6\x28\x22\x3b\x91\x4a\x47\x5a\x90\x21\xa3\xa3\x97\x55\xa5\xdb\x2c\x57\x4c\x8a\x23\x45\xd7\xac\xd2\x45\xb6\xad\x84\x87\x1c\x18\x99\x4f\x35\x2e\x4b\xfa\xc1\x91\xb1\x91\xa6\xf9\x99\x53\x6c\x73\x6f\x02\x8c\xc5\x7a\x89\x64\x92\x13\x37\xe3\xe9\xd3\xb3\x3b\x25\x05\x6e\x3c\x8f\x0f\x35\xff\x2a\x8f\x14\x0f\xf7\xd9\x69\x75\xb8\x8e\xb6\x3f\x6f\x8c\x93\x6d\x49\x96\x97\x22\x6d\x90\xf7\x2e\x1d\xe7\x14\x58\x4c\xf3\xde\xf7\xc6\x46\xa5\x91\xb5\xb5\x91\x8e\x19\x72\xe2\xc7\xf5\x73\x0c\xea\x96\x0b\xbd\x9f\xf9\xb4\x8e\x0d\x38\xb3\x21\xa2\xc8\xcb\x7b\x4e\x93\x63\xc6\x79\xd9\x97\xa3\xed\x04\x8a\xf9\x4e\x66\x80\xe7\x32\xe3\xfd\x21\xfc\x6e\x1b\x22\x35\x68\x55\xc4\x46\xf8\x86\x4a\x27\xd0\x64\x84\x42\x00\xc4\x32\xe5\xf2\x73\x76\x35\x11\xde\x09\xd6\xd7\xe5\x8b\xf0\xca\x43\xa1\x72\x13\x3e\x7e\x18\x2e\x81\xac\x1c\xb5\xdc\xa4\x10\x89\x6b\x67\xc7\xcf\x4c\x69\x6e\x4e\xf1\x64\x9b\x90\x8f\xf3\xbd\x75\x27\xad\xf2\xd2\xe3\x66\x5d\xa1\x1e\xf1\xb5\x42\xfb\x73\x14\x4c\xb7\xb7\x41\xc9\x01\x35\x53\x87\x68\xd5\x4b\xa3\x76\xe6\x9c\x76\x6e\x2d\xca\x5f\x65\xbc\x39\x10\x65\xf5\x56\x07\x22\x6d\x93\xaf\x07\x89\x42\x12\x3a\xef\x47\x03\xce\xab\xbe\x78\xd6\x63\xf5\x5a\x58\x0a\xae\xbe\xc9\x6f\x1a\x1b\xe9\xda\x79\xfe\xe5\xf9\x00\xf2\xc2\x48\x10\x4b\x67\x54\x9c\x1c\x7e\x63\x4e\x07\xc2\xb8\x17\xed\xe2\x00\x87\x4f\x5a\x4b\x3a\xdc\x62\xdc\x41\x07\x80\x25\x39\x43\x09\x5d\x9d\xc3\x6f\xf2\x15\xca\x97\x17\x98\xb9\xc8\xd5\x77\xdb\x31\x8d\xdd\x29\x1b\x28\xa3\x74\xb8\x98\x5e\xb2\x3f\xb1\x81\x75\x80\xc6\xa6\x98\x03\x2d\x14\x41\x01\x9d\xba\x8a\x39\xaf\x19\x8b\xa3\x00\xa7\xe9\x39\x4e\xd6\xd9\x84\x1d\x4c\xad\xf6\xc1\xbd\x23\xda\x41\x32\x59\x75\xda\xe9\xe1\xe1\xbd\x35\xc7\xc6\x2f\x5f\x1e\x1f\x3d\x66\x12\x71\x6c\x14\xca\xc7\x6a\xf6\xc6\xe5\xde\x87\x88\xbf\x11\xbe\xcb\xa1\x3f\x75\xf6\xfd\x41\x72\xa9\x5a\x99\x9a\x16\xcd\x02\xd1\x5d\xd3\x41\xeb\x58\x20\x14\x5f\xd5\x76\xef\x4d\x0f\xbc\x8f\x31\x56\x1c\x96\xbf\x26\x19\x50\x5c\xef\xea\x1d\xc5\x36\x58\xa3\x93\x32\xeb\xeb\x9d\x6d\x37\xe4\xa5\xb1\x5b\x6c\xd2\x8f\x27\xbb\x1e\x41\xa9\xc9\x51\x36\x52\xbb\x0b\x53\x0b\xed\x51\x7d\xeb\xeb\x94\xad\x53\x87\xec\x65\x7f\x95\xec\xef\x53\x1c\x5c\x44\x2d\x77\x4c\x72\x54\x43\x5d\xb9\xd3\x8e\x6f\x72\x6c\x79\xbd\xdd\x82\x58\xa5\xcd\xdb\x4a\x5e\x66\x6f\xee\xa3\x0c\x2d\x8a\xe9\x0b\xf0\xcb\xb0\x87\x95\x28\x95\x58\x33\xd3\x52\x3e\x5c\xd6\x23\xea\x96\x09\x39\xe2\x16\x89\x56\x50\xe9\xa5\x98\x51\xd5\x90\xdb\x91\x1e\x2c\x1e\x61\xf9\x65\xa4\xcf\xe4\xa6\x58\x9b\x23\xbf\x2a\x85\xdf\xe7\x67\x56\xec\x54\x6e\x71\xf9\x8f\xcd\x47\x4c\x97\x28\x98\xc2\x5a\x29\xd3\x6f\x84\x4d\xf3\xc1\x69\x8e\xe5\x21\x23\x5a\xd1\x18\x04\xca\x48\x05\x2e\x83\xd0\x24\xf1\x89\xc9\x80\x57\xfa\xf5\xb4\xa0\xaf\x5c\xb0\x70\xa9\xb8\x15\xd0\x2a\xc8\xb6\xf5\x8d\x0b\x17\x2f\x0f\x94\x95\x2e\x67\xbe\xd2\x79\x20\x39\x93\xef\x4c\x32\x97\x81\x1a\x70\xa7\x28\xd1\x23\x5a\x2d\x29\x69\x8e\xc1\xb8\xf3\xb5\xdd\x6a\xeb\xb4\xd2\x6a\xd4\xad\x19\x3d\x1f\x1a\xbc\x30\x62\x93\xf3\xf2\x1b\x60\x6e\xa3\x30\xe0\x61\x5d\x9c\x6b\x32\x93\x49\x29\xba\x58\xed\x45\xdb\x38\x66\x96\x6e\x44\xb1\xce\xb7\xbb\x25\x38\x92\x43\x53\x2e\xde\x6f\xda\x15\x8b\xc4\x9b\x18\xf6\x4e\x67\xdf\x27\x7f\x64\xdd\x70\xad\x2d\x9d\xd9\x4a\x93\x3d\x61\xba\x8a\xbd\x59\x3c\x6c\xdc\xec\xc7\xa0\x0c\xa3\x4f\x1a\x59\x64\x62\xc9\x48\x6c\x5f\x4c\x01\x43\x0a\x06\x5e\x1b\x5d\xc7\xca\xd2\x1d\xd1\x6f\x0e\xaa\xf1\xc7\xe0\x8f\x3e\xab\xc9\xb9\xd8\xa8\xa8\xfc\x4e\x6b\xb1\x59\x09\xa5\x91\xd4\xb5\x3d\x81\x9a\xd4\xc3\xe3\xf5\x17\x66\x85\xe7\x4e\xa5\xac\xec\x03\x48\xce\x5e\x95\xb9\x03\x9f\xce\x19\x9f\x66\xe3\xa8\x3c\x96\x97\x1f\x89\x28\x7c\xe2\x45\xd3\xe4\x28\x53\x4c\xb5\xd7\x5c\xf9\x9f\x8a\x3e\x9c\x75\xc2\x34\x0f\x76\x64\x4e\x97\xe9\xbe\xf5\x7e\xb4\x48\x4e\xf2\x00\xab\x5b\xb1\x6e\x44\xc4\xcc\xca\x65\x68\x2f\xda\x88\x28\x32\xa9\x31\xa2\x68\x65\x5f\xca\x94\x51\x6e\x56\x3d\x91\x43\xe4\xf6\xf0\x92\xa8\xf9\x48\xff\x1c\x1b\x7f\x45\x8d\xef\x67\x1b\x69\x7e\xa7\x25\xaa\x42\xa5\xe3\x31\x35\xfe\xc6\xe0\x63\x7a\xc5\x95\x0b\x76\x0d\x81\x3e\x61\xeb\x59\x80\xf1\x25\xb1\x65\xbe\x26\x63\x21\xa0\x89\x15\x70\x49\x42\x0d\xcb\x38\xd0\xb3\x5d\x7e\x41\x2d\x6c\xa1\x36\x34\xc3\x31\xa5\x98\x92\x2f\x15\xb0\x5b\x5c\x12\x5c\x5a\x08\x0c\x49\xf5\x0a\x54\x34\xd0\x1c\x57\xb9\xf9\xf0\x61\x61\x38\x27\x6c\xfa\x88\x78\x52\x59\xac\xdf\x4e\x92\x65\xfb\x00\xc6\x6a\x33\x3a\xdc\xed\x2d\x06\x3a\x47\x90\xdb\x36\x17\xe5\x19\x76\xd3\xe1\x61\x64\x24\x24\x60\x83\x4d\x2c\xdc\x94\x43\xf4\xf6\xbe\x04\x7a\xf0\x33\xb7\x21\x71\x86\x31\x93\x98\xf7\x8f\xe0\x5d\xd3\x8b\xd9\x17\xdf\x6e\x23\x78\x8e\xb5\x42\x0e\x8d\xca\xe7\xc6\xc0\x6c\x5d\xb8\xbe\x4b\xc3\x5e\xb7\x0f\x74\x0e\x95\xf4\xb9\xd6\xc2\x13\x5f\x40\x59\xd0\xfc\x17\x75\xec\x9c\x67\x53\xfa\xb5\x6b\xae\xe7\x5d\xd0\x02\x4f\xc6\xa4\x97\x26\x76\x3a\xf5\x98\x1f\x4e\x83\xdb\x61\xfa\x4c\x19\xd8\x11\x65\x77\xc9\x8b\x9e\xf5\x2d\x68\x59\x7d\x3a\x1e\xa8\xc1\x78\x69\x20\x4f\xb9\x05\x20\x95\x8a\x78\x7c\x2b\x5e\x8b\xc3\xb1\xb2\x43\x71\x01\x25\x84\x7f\x03\xe6\xb8\x5d\x7b\x5b\x5b\x1b\x1e\xd8\x71\x22\x9a\x09\xdc\x78\x40\x4c\x07\xd6\x75\x70\xd5\x94\x1d\xd5\xc3\x6a\xbb\xea\x83\x0b\x0b\xdc\xd6\x2d\x01\xdd\xe8\xa3\x5b\x3d\xc9\x7f\x8b\xc0\xf5\x93\xd8\xa6\xb2\x5c\x0c\xf1\x65\x89\x8b\x6a\x71\x5b\xfe\x25\xef\x1c\xb3\x5e\x57\xa5\x87\x94\x1a\x19\x27\xe2\x48\x6a\xd3\x79\xc2\x63\xea\xf4\x25\x4a\x38\x8a\x18\x49\x6d\x78\x95\xc2\xe5\x3d\xe8\x43\x2f\xfa\x5d\x2e\x26\xc1\x77\x34\xcd\x44\xde\xc3\x2c\xc6\x98\x17\xce\x13\xca\x1c\x33\xf9\xb9\xea\x94\x22\xb6\x7a\x96\x14\x9f\x83\x60\xc5\x55\xa9\x90\x16\xea\xc1\x0d\x7c\x4d\x3a\x1f\x33\x51\x63\x21\x93\x5f\xc7\xa3\xe5\xf1\x57\x28\x01\x18\x57\x6a\x87\x90\xd3\xf9\x71\xeb\xd6\x53\xf2\x23\x66\x28\x47\x34\x47\xde\x97\x49\x3e\xb4\xa7\xd4\xe0\x85\xe4\x6e\xd5\xda\x84\x45\x92\x06\x0e\xfc\xd9\xa9\xff\xf7\x8d\xf2\x5e\x84\x9b\x92\x80\xe6\x97\xcb\x97\x8b\xda\x3c\x44\x24\x3e\x6e\xf1\x48\x47\x5b\xc7\x16\x4d\x89\x27\xc9\x43\xd4\x26\x92\xc7\xb8\x27\x6f\xf8\x72\x55\x6d\x08\x05\x80\x1c\x8a\xc6\x11\xfb\xcd\x4e\xcb\xcf\xdd\xbe\x7f\x77\x4a\x01\x3f\x89\x12\xe5\x36\x97\x5c\x41\x3c\x88\x8f\x4e\xc1\xb6\xf7\x0e\x5a\x4b\x35\x12\xa2\x44\xc1\x29\x98\xfc\x85\xef\x1d\x48\x69\x3d\x17\x82\x69\xd9\x71\x6c\x53\x05\xce\xd5\x3a\x9c\x42\x1a\x32\xb6\x26\x79\x59\x91\xed\x5e\x1b\xd9\x06\x17\x62\xd8\xae\x75\x7d\xe6\x10\x59\x2b\x6c\x7f\x63\xfc\xbe\x5a\xdb\x6d\x4c\xc7\xd5\x25\x39\xa4\x15\xe3\xa6\x73\xc1\xc6\xcc\xaa\x59\xef\x4f\xf2\x31\xe9\xdf\xba\x59\x44\x32\x0e\x4c\xb6\x0a\xbf\xfd\xbf\xca\xa2\x25\xf8\xa2\xf5\x63\x15\x2b\x37\x9d\x07\x56\x94\x5f\x2e\x72\x73\x49\x71\x0d\x70\x1b\xd7\xa9\xf0\xb9\xe5\xba\x20\x3e\x10\x04\xc9\x62\x47\xec\x4e\x7a\x95\xc5\xbd\x32\xb2\x71\x96\x58\x93\xfd\x44\xf9\x49\xae\xd6\x61\x8a\xf6\x96\xda\x27\x48\xff\x10\x56\x83\x54\xa2\xad\xec\x9c\xbc\x99\x9f\x1f\x95\x45\xc9\x74\x8f\x7c\xfa\xda\x47\xb5\x33\x96\x28\x0d\x6f\x4f\x74\x72\x4a\x6c\x0f\x97\x12\x73\x02\x3c\xe5\x3b\xd5\xf2\xdc\x33\x29\x59\x51\xf9\xe8\x81\x60\x67\x77\x87\x38\x05\x22\x6f\xbd\x26\xef\xdf\x37\x3e\x17\xee\x63\xd1\xad\x82\x88\x5e\xa2\xf5\x40\x26\x0b\xe6\xd1\x74\xea\x54\x93\x07\x12\x7d\x67\xbb\x1c\xb1\x24\x82\x7d\x88\xec\xb0\x30\x68\xba\x68\xbd\x13\x29\x88\x47\x54\xfa\x01\xbe\x00\xc7\x73\x94\xe3\x79\x34\x72\xec\xc7\x00\x0d\x20\x14\x00\x7f\x6f\xea\x0d\x4d\xf2\x48\x3b\x0b\xce\xa6\x77\xea\x7e\x7c\xaa\x20\x21\x28\xeb\xef\xf2\xf7\xcf\xf9\x0b\xf6\x86\xd9\xe0\xb6\x19\xf7\x61\x64\xd8\x07\x22\x09\xb9\x91\x0b\xdb\x2d\x73\x51\x67\x23\xe2\x2c\x31\x4d\xb0\x16\x9c\x7c\xaf\xad\x2f\xa9\x75\xcd\x68\xf6\x52\x94\xb1\xd3\x2d\xc7\x2e\x6b\x24\x47\xf8\x4b\x2c\xdd\x85\x31\x61\x15\x3d\x61\xab\xfc\x8c\x59\x50\xc7\x41\xc6\x2c\x71\x94\x25\x21\x11\xd6\xff\x0a\x4f\x4e\x05\x15\x7a\x76\x4e\x36\xd7\x5e\xa5\xc6\x03\x3e\xf0\xee\xc6\xac\x41\xe9\x76\xdc\x4a\x87\x46\xf0\xd3\xbd\xcd\x29\xb0\xc9\x0a\x2f\x9d\x99\x8a\xde\xaa\x6c\xcc\x92\xa9\x42\x33\x47\x4d\x19\x9c\xaf\x27\x5b\x18\x90\x1a\x2c\x6e\x5c\x16\xbe\xe7\x8c\x5c\x1d\x6b\xde\xd1\xa3\x0d\x6d\x31\x05\xa5\x68\x6d\xb4\x6f\xb5\x3e\x21\xd3\x1a\xf4\xbb\xf0\xd5\x6a\x4d\x30\x43\x20\x3c\xa6\xe9\xe7\xff\xf3\x07\xe5\x9f\xb5\x80\xb9\xdf\x8e\x5c\xbd\xbc\xbb\xbb\x91\xbe\x60\x4b\x7f\x7c\x07\x5f\x78\x4e\xf4\x11\x11\x60\xc7\x80\x9c\xb8\x9e\x70\x57\x1d\x1d\x4a\x0c\xe8\x0c\x6a\x48\x4c\xf6\x4d\x0f\xa9\x3c\x94\xea\x5f\x94\x92\x89\x3d\x07\xf9\x7f\x9f\xaa\x90\x43\x05\x14\xa8\x8a\x06\x4d\x40\x07\x57\xde\x85\xce\x25\xea\x89\xb7\x16\xb8\xfd\xc7\x86\x82\xf4\xe1\x93\x66\x14\x97\x7f\xa3\x8e\x25\xe4\xa7\x4d\x6e\xd8\x70\xe6\xa1\x0b\x5a\x00\xd4\x33\xfd\x40\x3e\x27\xf6\x4d\xbc\xf0\x64\x0d\xfe\x59\xba\x2c\x42\x04\x54\xb3\x97\x75\xb1\xc2\x4a\xf5\x3a\xf9\x03\x1b\x83\xe6\xd8\x6f\x3e\xaf\xb5\x62\x5e\x1d\xd5\xb9\xe1\xc8\x91\x92\xde\x8b\x47\x78\x8e\xba\x5f\x57\xeb\x60\xcf\x04\x48\x0c\x04\x8f\x92\x22\x3d\xb4\xcf\x9f\xa3\xfe\x01\x7a\x26\x3d\xde\x05\x08\x1c\x40\xfe\x25\xd3\x8c\x48\xd9\xf3\xd8\x71\x69\x93\x78\x17\xb0\x44\x48\xba\x58\x78\xcf\x6a\xea\x84\xaf\x4b\x01\x20\x16\x7c\x40\x00\x04\x51\x54\x16\xb0\xc6\x50\xa8\xe4\x2b\x07\x18\xe3\x3a\x75\x1e\xee\xb2\x63\xdd\x7d\xd0\x9e\xbd\x54\xb2\x9b\xcb\x0b\xa1\xf0\x85\x42\x35\x8c\xda\xa8\xca\x02\x38\x31\x82\xd6\x68\xc8\xa9\xaa\xaa\x9c\xa7\x61\xb7\x99\x46\x75\xf6\x58\x4c\x63\x5b\xa1\x6e\x4e\xd7\xa8\x78\x74\x4e\xdf\x44\x9b\x58\xd8\xc5\x2a\x11\x4e\x38\x04\x02\xfd\xf0\xc6\xdc\xe1\xc3\x73\x37\x1e\x02\x16\x89\x15\x7c\xf8\xf6\x18\x86\xcd\x32\x0d\x7f\x90\x05\x52\x7b\x3e\x7d\x37\x38\xf8\xd8\x2e\xc7\xe1\xb9\x47\x8e\x9d\x04\xd5\x79\x11\xd5\x82\xb0\x9f\x4f\x67\xc1\x23\xf8\x51\x0e\x96\x91\x9a\x71\xf3\x27\xa0\x67\x12\x0a\xcf\x66\x92\xaa\xb8\x12\xc2\x07\x18\x4b\xf8\x59\x88\xb4\x60\xb2\x39\x8f\x68\xf3\x32\xea\xc2\x84\xc9\x36\xda\xfd\x24\x7d\x93\x1e\xae\x0e\x1e\x20\x97\x83\x28\xc3\x54\x3f\xbb\xef\xb2\x18\x7d\x41\xad\x60\xf7\x0f\x37\x1b\xd4\x05\x38\x94\xe8\x80\x18\x4c\x19\x48\x46\x52\x12\x03\x89\x47\x8a\x0a\x0b\x45\xfd\x46\x4a\x08\x58\x77\x21\x53\xc3\x4b\xd2\x72\x86\x1d\x8e\x00\x04\xde\x40\x45\x4b\x61\xfa\xdc\x32\xcb\xf6\x27\xbe\xe9\xb1\xca\x8c\x94\x25\x76\x5b\xd8\x9f\x5b\x37\xbe\x82\x1f\x53\xae\x46\xb3\x6a\xbc\x01\xe8\x6a\x86\x14\x87\x5b\x35\xe8\x68\xa1\x4d\x06\x74\x2c\xa1\xb9\xe1\x5e\xff\xa1\xd2\x69\x23\xda\xe1\x43\x6f\xaf\xb4\xce\x71\xc2\xa7\xfb\x5a\xa7\x65\xe8\xe6\xf3\x9a\xbd\x74\xac\xbf\x65\xe3\x19\x57\x69\xfe\x95\xb7\x87\xee\x70\x5f\xd7\x74\xa8\xff\x5e\x2a\x3e\xb2\xb8\xb1\xf9\x56\x6c\x68\xf1\xf9\x17\x5a\x9a\x51\xa3\x6a\x58\x07\xa7\xcf\x1c\x42\xdf\xe3\xa8\xaa\x82\x39\xa9\x71\x02\x37\xd6\x40\xf9\x19\xb1\x8b\x82\xaf\xb8\x27\xb4\x12\xd0\xed\x16\x1e\xe3\x9e\xe1\xfa\x1d\xab\x5b\x3d\x65\x1e\x1c\x89\xc4\x48\x2b\x5e\xd1\x97\xba\xc5\xde\xea\x61\x2f\xf5\x47\x85\x13\x36\x8c\x7a\xd5\x3c\xf0\x36\x29\x79\xd0\xb6\x87\xe5\x44\x48\xe4\x77\x46\xcb\xcf\xf3\xe3\x13\x76\xe5\xfa\xfa\x32\x6e\x46\xbd\x29\x25\xc3\x64\xf8\xf3\xef\x03\xb9\xee\x2e\x9d\x29\xe1\x08\x14\xc6\xdb\x95\x50\x36\x5e\xc3\xb7\x72\x09\x8d\xe3\x04\x7b\xaa\x68\xf7\xc8\x3c\x8a\x4c\xca\x3f\xb3\x49\x68\x2e\xa7\xb7\x98\x8e\xb4\x64\x68\x74\x5b\x24\x9d\xe5\x1e\xe3\x16\x5d\x09\xec\xe2\xb2\x66\xc5\x98\xb0\x39\x26\x34\x2e\xda\x3b\x00\xe6\x73\x3b\x8f\x42\x8c\xaf\x95\xfd\xf6\x0a\x12\x9a\x6b\xf6\xf5\x19\xdc\xe6\xf5\xf5\x95\x7e\xcf\x3e\xa8\x6a\x29\xcf\xb0\x79\x22\x54\xcb\xe3\x9d\xbc\x6a\xbd\x4d\x55\x1b\x81\x02\xe9\x64\xce\x82\x4d\xbc\xdd\xb1\xad\xb4\x5b\xff\x84\x44\xf1\x67\x34\x0f\x7b\x1a\x2b\xe1\xdd\x9d\x1f\xa9\x8c\x02\xa1\x17\x3a\xaa\x3c\x83\x39\x71\xa9\x02\xb7\x01\xfe\x41\xcf\x7f\x14\x02\x05\x7f\xa1\x15\x77\x07\x09\x4c\x7d\xbb\xc5\x41\x3d\xc2\xa3\x36\x13\x1b\xaf\xdb\xa0\x65\x76\xf8\xdd\x41\x75\x11\x94\x2b\x55\xfa\x5f\xff\x1f\xf6\x51\xde\x33\x66\xde\x3f\x9f\xe4\xe2\x95\x1b\x52\xb7\x5c\x97\x08\x30\x05\x52\xc6\x00\x18\x7f\x0d\xa4\x52\x5e\x20\xf3\x2c\xf7\x98\xeb\x56\xd1\x77\x85\xdc\x57\xa2\x1b\x1d\x15\x82\x7f\xb2\xee\x32\xe2\x60\x41\x09\x1f\xe5\x76\xa9\x47\xa9\x3c\x39\x0b\x0f\x93\xca\x34\x6e\x58\x3b\xa1\x3f\xbb\x0b\x89\x3f\xf2\xa7\x1b\x2a\x75\x56\x30\xfb\xab\xe4\xb4\xd3\xed\x03\x7b\x5b\x01\x34\x22\xae\x10\xc3\xce\x82\x2c\xb6\x17\xc4\xee\x82\x15\x1a\x71\xd3\xbc\xb1\xe7\x3c\xec\xe7\x92\x52\x4b\x9a\x2b\x82\x08\x07\xdf\x1d\x86\x6b\x35\xc8\x57\x78\x63\x46\xec\x84\xf0\x18\x50\x08\x4f\xfc\x7f\x1f\x3d\x2a\xc2\xf0\xa5\x3b\x45\x12\xfb\x83\x05\x99\xd5\x18\x44\x83\x7e\xbf\xcf\x3a\x17\xd4\x09\x92\x6d\x5c\x41\xb6\xbe\x70\xf8\xb2\xda\xfd\xcb\xeb\x19\x5c\x58\x58\xa7\x08\x64\xb7\xff\xab\xf5\x2b\xbf\x48\x0e\x6b\x36\xfb\xff\x5a\x62\xde\xec\xdf\x57\x73\x58\x0c\xe4\xac\x2f\xd4\xcd\x03\x24\x5f\xba\xad\x51\x84\x13\x12\xf1\x84\x5a\x5f\x97\xa9\xbd\x68\x68\x90\x4c\xf5\x75\x7c\xd7\xc6\x10\x38\xf9\x0d\x09\xc2\xd6\xe4\x5a\x94\xa6\xc2\xd4\x7d\xf1\x49\x48\xc2\x3a\xc6\x8b\x6f\x4b\x7d\xbb\x8c\x0a\xcc\x61\x2f\x2d\xd5\x6b\xa3\xf3\x78\x56\x71\x30\xc4\x02\xc2\x72\xca\xce\x7f\x4c\x43\x90\x5f\xe0\x84\x08\x14\x44\x10\x36\x68\x26\xe8\xbb\x93\x53\xa5\x71\x7d\x70\xdf\xa8\xf2\x3d\x9a\x18\xb8\x7e\x33\x38\xbe\x10\xa1\xf1\x5e\x78\x8e\x53\xdf\xa1\x63\xbe\xa8\xd5\x38\x55\x6d\x11\xb1\xf7\x65\x7e\x37\xb0\xb8\xb6\x1e\xf4\x99\x56\x55\x5a\xc7\x3a\xf4\x76\xc6\xaf\x0b\xe4\x5b\x6d\xe9\x3e\x85\xbf\x13\x80\x3f\xd3\x0d\xd1\x08\xe0\x70\x1b\x7d\xf4\x5f\x06\xe1\xf9\x10\x67\x4b\x06\x42\xdd\xf4\xa1\xfa\xc3\x5f\x0a\x25\xeb\x5f\xa4\x67\x3d\xf7\x49\x68\x7c\x2e\xdd\xa5\xc4\x85\xf2\xfe\x56\x0e\x5e\x31\xe4\x93\xba\x30\x09\x22\x7b\x93\x96\x37\x86\x83\x6d\x86\x73\xd0\x39\xc8\x0f\xea\x9b\xa6\xb3\xf4\xd1\x42\xe0\xf5\xec\x4e\x9e\x94\x49\xc1\x13\x70\x87\xcc\x69\x7b\x0a\x5d\x4a\xac\x20\xea\x10\xf6\x3a\x4d\xb8\xaa\xa5\xd2\x79\xe4\x25\x89\xc5\x75\x86\xe7\xd5\x06\x00\xbf\xfa\x47\xe6\x04\xcd\xff\x56\xd6\x81\xa1\x02\xb5\x0b\xe6\xd2\x01\x6b\x02\x6b\x3c\x6f\x29\x1a\xce\x7b\x3c\x1d\x4f\xf1\x47\x4a\xd7\xa5\xa1\x78\x43\x4e\x6a\x33\x2d\xcb\xaa\x1b\xaa\xef\xf1\x10\x57\x2d\x37\x17\x33\x39\x8a\x1f\x42\xc6\x92\x28\x54\x0a\x60\xda\x50\x0c\x1e\xaa\xaf\x88\x58\x1f\xe9\xbe\x69\x8a\x91\x0b\x77\x08\x51\xe5\x3a\xe5\x9d\xd7\xc1\xdb\xf0\x80\x36\xe3\xb8\x29\x12\x22\x53\x11\x20\x23\x13\x16\xb7\x2d\xe8\x8f\x0c\x08\x8f\x2c\xae\x22\x76\x09\x08\xf5\x84\x5c\xee\x1a\xea\x64\x7e\x6e\x15\xb0\x91\x32\x72\x72\x32\x4f\x62\xbb\x36\x82\x5b\x96\x54\x81\xd6\xd2\x0a\x52\x18\x0f\xab\x4b\x63\xcb\x59\xf3\xe7\x8a\x8b\xf8\xaf\x34\x63\x5d\x91\x3e\xb4\x14\xa4\x8d\x06\x8c\x70\x79\xe0\xa7\xe6\x81\x6a\x06\x70\x3a\x1a\x04\x47\x5d\xaf\x5a\xd0\xe8\xd8\xc8\x24\x12\x30\x0a\x8b\xf4\xfa\x5f\xea\x4e\x2b\x4d\x37\xfa\x59\x32\x18\x6c\x15\x0a\x40\x07\x78\x87\xea\x36\x07\x71\x9d\xe1\x09\xb7\x9d\x34\x9f\xd5\xdf\x35\x39\x4f\xd4\xd0\xa2\x9c\x7d\x11\x54\x93\x90\x72\xfc\x66\x35\xfa\x9f\x32\xff\x6b\x16\x20\x74\x01\xaa\xdf\xb2\xba\x7d\xbb\x70\xc4\x55\x5c\xd2\x75\x72\xba\x9b\xb7\xb1\x73\x56\x6c\xb8\xd7\xaa\x85\x61\x87\xf5\xbc\xde\xb2\x8e\x0d\x7d\x56\x6d\xda\xf1\xc7\x7e\x33\xff\x67\x6d\x86\x8d\xcd\x2c\x18\x5c\x37\x6d\x7d\x95\x2d\x8e\xc1\x84\x2a\xe3\x9a\x10\x2c\x45\x48\x9b\x71\x03\xe7\x24\x59\x78\xb8\x3d\x0e\x45\x15\x98\xfc\xfe\x5f\x56\x27\x9e\xf6\x43\xea\x19\xb2\x52\x99\x69\x87\x4e\x44\xb5\xfa\x39\xf5\x03\x9d\x91\x2f\x00\x0b\x43\x19\x62\xb2\xb3\xc1\xd8\xf8\x78\x9d\xa1\x40\x38\x60\xc1\x32\x49\xcc\xaa\x2c\x21\xf1\xd1\xc2\x03\x66\xdd\x84\xb2\x6e\x45\xf1\xf3\x38\xde\x62\xf1\xfa\x2b\x12\x51\x90\x94\x32\xec\xaa\x98\xeb\xbd\x43\x5a\x5e\x3f\x47\xf7\xf8\x56\x66\xe2\xec\xf6\xe7\xa0\xb1\xb2\x04\xfb\x17\x28\x42\xeb\xe0\x49\x65\xf3\xfc\x2b\x14\x89\x39\xad\x16\xee\x3a\x0d\x41\x0c\x0e\x0b\xc3\xf5\x9c\xef\x0a\xff\xbc\x76\xa8\xa5\xd4\xd0\x34\xd4\x52\x42\xb7\x48\x20\xd7\x7a\xe7\xd1\xb3\x79\xec\x7c\xff\x78\x1b\xbe\xae\x9c\xd6\xa3\xdb\x57\x3f\x80\x45\x1b\xfb\x12\x1a\x74\xb4\xd0\x46\x4f\x0e\xcf\xdc\x94\xe1\x93\x63\x1e\xfb\x94\x3d\xf5\x9a\x31\x45\xe5\x24\x56\x28\x54\xf3\x92\x9a\xd7\xc1\x7d\x0b\xe6\xab\x72\x59\x18\x0e\xa3\x21\x48\x1c\x68\x51\x21\x2e\x46\x2f\x0d\x64\x10\x9e\xf6\xf4\xd5\xab\x47\xb4\x83\x9e\x30\xff\xef\xd4\xd1\x3b\x6a\x17\x07\x38\x36\x74\x1d\xfe\xc0\xc4\xea\xaa\xc5\x16\xae\xec\xd0\x09\x38\xdc\xd5\x79\xe4\xf8\x0b\xdf\x51\x47\xb4\xfd\x2f\x5a\xb5\x90\x61\x33\x06\x3d\x06\x0a\xcb\xcf\xf4\x4f\x81\xaa\x87\xc2\x5f\xd5\xd8\xa4\x4a\x9a\x99\x50\xd7\x92\xa2\x49\xb1\x52\x73\xa3\x5a\x3d\x8e\x90\x7c\xda\xbc\x41\x23\x91\x8c\xac\xac\x8c\xf0\x0e\x23\x91\x73\x75\xeb\xee\xe6\x9b\xbb\x3b\x2e\xeb\xe9\xdd\x1a\x06\xbb\xfa\x2e\x74\x8a\xd7\xa9\x3a\xea\x4b\x16\x49\x54\x27\x17\x81\x36\x98\x1a\x95\xca\x6d\x37\x98\xd2\x22\xf2\x3a\xef\x1a\xec\xe2\xbe\x73\x07\x03\xc5\x62\x12\xc7\x71\xd7\x79\x4c\xe2\x40\x5a\x2c\x59\xaf\x09\x62\x67\x98\x8e\xdd\xc5\x2c\xc1\xfe\xbf\x6e\x9f\x06\xfb\x89\x98\x7b\x0e\x4f\xb8\x3b\x5d\x93\xc9\xaa\x21\x5f\xe3\x22\x3d\x63\x17\xf8\xd3\xba\x02\x86\x9a\x82\x64\x69\x6a\x9b\x32\xa4\x47\xec\x42\xbf\x58\xb5\x24\x80\xe3\xb5\xe0\x7c\xa9\xab\x17\x7f\x69\xdb\x21\xb1\xa1\x82\x2a\x6e\x54\xee\x01\x25\x9b\x02\x13\xfb\x3b\xcf\x15\x2a\xea\xc5\xf6\xe4\x5e\x33\xce\x2f\x63\xed\xae\xb9\x45\xc0\x9f\x13\x73\x9f\x08\x34\xf6\xba\x43\x03\x77\x4c\x6a\x7d\x29\x19\xb1\xf9\xe2\x3c\x28\x86\x9e\x59\x70\x48\x77\xe2\xdd\xf3\x57\x8b\x5e\x92\xfd\x48\x4c\x8c\x2d\x0b\x76\xcb\xdb\x70\x84\xf9\xc4\x91\x40\x01\x77\xde\xc4\xd0\x9f\x70\xc5\xcc\xb9\x9d\x55\xfa\x4b\xb8\x97\xc0\xa1\x3e\x31\xeb\xb7\x80\xf1\xc4\x4c\xcb\xbe\xa9\x66\xe2\x04\x30\x70\x89\xd0\xce\x8e\x97\x1b\x3d\xd4\x5f\xeb\x8c\xf1\x9f\x21\x0b\x09\x39\xfe\x71\xc6\x5b\xba\xba\xc1\xc6\xad\xae\xf9\x74\x84\x2d\x63\x5c\x0d\xd5\x09\x40\xd5\x71\xf1\x5d\xb2\x92\xe0\x43\x41\x4a\xb4\xaf\x70\xcd\x50\x61\x6f\x7c\x1e\x79\xa9\x6c\x4e\xde\xea\x91\x7b\x0f\x46\x86\xf3\x2a\x33\xb3\x46\xd0\xf8\xcb\x78\x4c\x7f\x54\x76\xa2\xb4\xd0\x30\xd4\x9b\x56\x2c\x91\x90\xbb\xe4\xde\xfb\xf3\xd4\x6a\x48\xf5\x41\x28\x5c\xc9\xf4\xd4\x78\xe2\x07\xfa\xfb\x9f\xbe\x07\x78\x74\x50\xbd\x0d\xf5\xaf\xaa\x52\xa5\x5e\xa9\xd7\xe5\xe5\x00\x53\xbf\xef\x68\x22\x91\x48\xb0\xc6\xfd\x4a\x6e\x23\x5f\x70\xbf\x2e\xc2\x24\xad\xb2\x02\x19\x8d\x73\x32\xf0\x69\xa8\xf1\xfb\x42\xcc\xe6\xe6\xf1\x7b\x54\xd1\x75\x5a\x4b\x0b\x74\x5c\xd4\x4c\x1a\x49\x87\x19\x25\xbe\xed\xf1\x2a\x9a\x0b\x8c\xbf\x50\xf8\x3d\x16\x7b\xf9\x62\xe0\x22\x55\xb8\x51\x87\x22\x56\xd3\x52\x7d\x09\x3e\x5a\x82\xd6\xf1\x8a\xd2\x0c\xa5\x81\xc5\x8a\x4e\xb1\xb3\x56\xdd\xae\x02\xe9\x2d\xfb\x4a\xc9\xec\x68\x02\x0c\xcf\x83\xe1\xcd\x0d\xc3\x5e\xa9\xd9\xd5\xc1\x0c\x11\x8c\x3b\x92\xa6\x46\x51\xc3\xd4\x2c\x2a\x2b\xe8\xad\x22\xf5\x22\xd5\x30\x30\x29\xb6\x3a\x3b\x3a\x56\x94\xa7\x12\x50\x38\x2a\x65\x28\x37\xd2\x4a\x6c\x97\xbd\x8e\x8b\x9b\x30\x6f\x48\x65\x5e\xc6\x8a\xe2\xe5\x79\x25\x81\x60\xbc\x93\x1d\x34\xa7\xc7\x59\xd2\x5b\x65\x58\x16\x7d\xb2\x36\x4b\xfc\x4a\x05\xcb\xa9\x84\x91\x12\xcc\x00\x00\x5e\x23\x3c\xc9\x9d\xc9\x08\xcf\x49\xdf\x5f\x2f\xee\xae\x32\x33\x2d\x40\xb1\x6c\xb3\x34\x96\xcb\xfb\x60\xca\xec\x50\xe2\x3d\x01\xe6\x4b\x26\x3d\x2e\x29\xe9\xcd\xd5\x9c\x58\x76\x4c\xaa\x88\xc5\x66\xb1\x6f\xd9\x0b\x9d\x8b\x42\x47\x5d\xde\xae\x8d\x16\xd2\x2b\x02\xf2\x8b\xe6\xd8\x82\x50\x79\xb8\xd0\x49\x8e\x6e\xa9\x56\x60\xe6\x6b\x2d\x7e\x53\x8c\xc5\x64\xd0\xed\x11\x64\xfd\x02\xd8\x63\x55\xb7\x97\x2e\xda\x67\xc6\x97\x27\xdd\x20\x31\x4e\x8a\xfd\xf5\xad\x30\x50\x21\xf4\x00\x08\xa1\xce\xaf\x82\x87\x48\x95\xed\xa8\x5d\x48\x66\xb0\x12\x9e\x0f\x5b\xb4\x5a\xc2\x78\xcb\x1d\xe2\xc5\x05\x5c\x2e\xc2\x20\x91\xe0\x80\xbd\x2b\xa2\x5c\x5f\x16\x34\x13\x62\x98\xa6\x4f\x76\xaf\x1a\xff\x82\x8a\x92\x23\xbb\xae\xf6\xb1\x88\xc5\x76\x21\x82\x6c\xcc\x04\x2c\xd4\x78\x3c\xec\x1a\x44\x13\x78\x49\x4e\x02\x2d\x46\x13\x82\xec\x65\x2c\x2f\x89\x5c\x6d\x82\xde\xd3\x64\xb4\x50\x79\x98\x12\xc4\x49\x72\x86\x83\xc7\x90\x26\x24\x8a\x11\x47\x1b\xbc\x4b\xf1\x4b\xb6\x16\x84\xd6\x87\x31\xc4\x71\x12\x97\x7a\x47\x9f\x21\xaf\xa3\xb2\xb5\x41\x05\xed\xbb\xc0\x11\xb9\x33\x38\xad\x11\xcc\x8d\xcd\x04\x39\x37\x55\x3b\xc8\xb4\x56\x65\xe6\x67\x20\xb0\xe9\xdd\x8c\x1e\xbf\x4c\xbb\xf8\xce\x90\x6f\x9c\x74\x70\x92\x52\x3c\x73\x9a\xe5\x6b\x30\x04\x55\xe0\x2d\x0b\x82\xa2\xc0\x82\xb0\xe6\x9c\x3d\x43\x98\xcb\x01\xbe\x43\xb1\x9e\x9e\xd1\xf6\x1c\x57\x6a\x41\x9c\xb2\xb5\x0c\xda\x4f\x69\xc3\xed\x9f\x8c\xa5\x92\x69\x6c\x30\x07\x18\x47\x74\x63\x3d\x07\x54\xa3\x09\xac\x75\x35\x9d\x3c\xd9\x84\xf1\x85\xfa\x27\x4d\x8a\x3e\x23\x05\x8e\xab\x0d\xee\x41\xa7\x44\x88\x16\xa2\xc3\xe4\xb6\x85\x10\xa2\x29\xe8\x6d\x83\x22\xc7\x9b\xf1\x19\x58\x21\x10\x0e\x2d\xea\x97\xce\x9c\x61\xbe\x52\x1e\x95\xaa\x82\xb9\x99\x5f\xad\xf4\x91\x7d\x29\x3b\xcd\x3b\x36\x13\xc5\xef\xd0\x9f\xb2\x28\x8e\x8e\x6f\x3a\xd6\x94\xfc\x71\x43\x5e\xfd\xf9\xc7\x95\xed\xa9\xfb\xad\xdb\xb5\xe9\xad\x41\x3d\x8e\x7a\xf9\x1a\x4f\xef\x07\x62\xca\x09\x85\x64\x84\x7e\xf8\xca\xc5\xdb\xdb\xfb\xb6\x8d\xd7\xee\x68\x7a\x97\x6e\x2f\x4a\x7e\x98\xc7\xaa\xc5\xa4\x7a\x53\xe8\x2c\x4a\x82\xa6\x4a\x23\x32\xc5\xad\xc3\xf3\x10\x69\x0b\xe1\xff\x5a\x7e\x5f\xa2\x7b\x63\xbb\x8c\x1e\x5d\x6f\x07\x96\x62\x52\x3a\xf4\x76\x3a\xeb\xa3\xe2\xf6\x3f\x65\x3f\x09\x74\x5a\x5d\xd6\xb8\xdf\xd5\xa0\xdf\x67\xd5\xaa\x4d\x6b\x0e\xea\x16\x14\x26\x8e\x7a\x7a\x9f\x71\xb3\x1f\xe5\x25\xc3\x55\x43\x57\x5c\x59\xde\xda\xbb\x65\x73\xf5\xb6\x86\x37\x69\x76\xa2\xe4\x07\xb9\xac\x5a\x97\x64\xef\x08\x1a\x14\x11\x9f\x54\xa9\x16\x56\xe6\xac\x51\xcc\x43\x8e\x1c\x24\x6d\x04\xc4\x8c\x6b\xc0\x69\x0c\xdd\x77\xb4\xc6\xbf\x05\x12\x23\xf3\xe6\xaf\x3b\x0f\xcd\xf8\xcc\x8b\xc9\x09\x25\x79\xcb\x47\x1f\xad\x38\x40\x35\x3a\x79\x71\x29\xb4\xa8\xac\x7c\xe2\x8c\xac\x4e\xdd\xe7\x3d\xfd\xb4\xc6\xec\xc5\xdd\x42\xd6\x81\xc5\x5e\x5c\xfe\xa9\x53\xf9\x38\x5d\x07\x02\xeb\xf5\xaa\x5d\x9a\x3f\x7b\xbc\xa0\x72\x57\xf9\xb5\xf2\xd2\x5b\x7f\x2d\xec\xb9\x2b\x57\x0f\x18\xa4\x71\xd9\x29\x5e\x32\xd5\xf8\xdf\xfd\xc7\x2d\xc8\xcc\x1b\x4b\x4b\xa0\x14\x30\x67\x34\x89\x4c\xd2\xbc\xee\x26\x4f\xf9\xb2\x53\x50\xbc\x64\xed\xe0\x02\x9d\xc5\x9e\x2d\x6d\xb2\x15\x80\x05\xc7\x3e\xf7\xb8\xdd\xf3\x80\x87\x6e\xec\x78\x1b\xca\x51\x79\x59\xe5\xb4\x8e\x00\x62\xe1\x1c\xe2\x89\x79\xa6\x43\x12\x51\x9a\x08\x9b\xce\xc7\xfa\x41\x00\xcf\x19\x93\x29\x08\x98\x8f\x42\xcb\xeb\x44\x60\x3c\x60\x92\x88\xec\x99\xc1\xd7\x18\xb3\xb1\xb2\xf0\x05\xe9\xbf\xfe\x37\x9e\xc9\x07\x91\xbb\x25\x66\x22\xa5\x59\x89\x16\x93\x15\x8d\xfb\x3e\xb6\x92\xd9\xd0\xa8\x47\x5d\xdc\x54\x7d\xea\x5f\xf3\xe2\xfa\x9d\xc3\xea\xc8\x54\x18\xc4\x2c\x61\x7f\xd2\xec\xdf\x5e\x26\x78\xd4\xa0\xab\x91\xe7\x2c\x76\xa5\x34\x98\x45\x70\x57\xf0\xc2\xb6\x9f\xf2\x53\x84\x41\x14\xfd\x4e\xef\xe2\x85\xad\x08\x67\x6a\xde\x29\xde\xc9\xec\xe2\x26\xaa\x8a\x64\x99\x00\x0c\xba\x35\x0b\xb8\x34\xad\x7f\xe4\xfe\x28\xda\x04\x08\xe7\xe4\x24\xc1\xfd\xe3\x73\x44\xe2\x42\xdd\xa6\x78\x9d\xf0\x4f\x9f\x68\x11\xaa\x58\x51\x9f\xcc\x4c\xe2\xb2\x77\x98\x05\x8a\x60\xed\x1f\x71\x8e\x6e\x1d\x50\xee\x88\x73\x54\xa1\x17\x73\xdb\xd5\x27\x40\xc7\x54\x7a\xc0\xbd\x2c\xed\x32\x1f\xcc\xe8\x4a\xb5\x2a\x6e\x6a\xde\x88\xfb\x34\x5f\x98\x7d\x33\xb9\xb8\x17\x9d\x9c\xbb\xd7\x99\xc7\x6a\xc5\xd2\xab\x2d\xab\x25\x69\xf9\xa8\xf2\xa5\xbd\xe9\x0a\x80\xf2\xb7\x01\xbd\xc2\x50\x92\x4f\xf3\xa4\x46\x3f\x8f\xad\x6b\x6a\x53\xdb\x23\xed\x07\x04\x47\xfa\x27\xeb\xca\x70\x1b\xf6\x31\xe6\x8e\x1d\xbd\x4a\xc3\x18\x6d\xea\x62\x06\xda\xf6\xcd\xd5\x61\x5b\xef\x32\xef\xb1\xe5\x3f\x6b\x4b\x71\x01\x1c\xa7\xb2\x21\x8c\x88\x40\x2d\x5e\x59\x39\x37\xf7\x2a\x9d\x96\x6f\x30\xf0\x81\x91\x69\xc5\x4d\xd2\x6c\xe4\x3d\xf5\xdf\xba\xfc\xb6\xb4\xed\xaa\xbf\xa5\x92\xf6\xbe\x28\xe9\x37\x67\xa9\xbc\xbf\x5f\xab\xdf\xc7\x99\xc7\x04\x57\xe5\xd8\xa3\xa4\xd3\x2e\x2e\xfb\x8d\x0a\x8c\x0e\x70\xcd\xdb\x1e\xe8\x6b\xa4\x8c\x03\x9f\xae\x0b\xee\x23\x0f\xac\xf3\xf8\xf8\xc1\x63\x5d\x06\x40\xe0\xf9\x03\xee\x97\x92\x8d\x71\x03\x8b\x6f\x9a\x73\x16\x5d\xac\x76\x4b\x8e\xc0\x69\x5d\xd3\x43\x15\x2b\x1d\x9a\x4b\x36\xd6\x0b\x2d\xed\x2f\x27\x53\xa2\xcb\xe8\x7b\x56\xaa\xe1\x46\x23\x70\x05\xc6\xa6\x75\x4f\x26\xe1\xe5\x67\x1e\xf4\x7a\x89\xa9\x75\xf2\xe0\x74\x92\xaa\x78\x65\x4c\x94\x2e\x8a\xa8\x76\xde\x73\xdc\x4d\x66\xef\xd1\x9f\x40\x2f\xe3\xce\x29\xf6\x75\x95\xb0\xef\xc8\x1b\x41\xe3\x29\x1b\x30\x21\xdb\xbd\xf8\x00\x29\x2f\x59\xb8\x08\xa2\xc6\x5f\x24\x6d\x55\x3f\x53\x7f\x5e\x15\xde\x09\x47\x71\xd1\x01\xda\xcb\x13\xc8\x56\xc4\x8b\x6a\x2e\x76\xdd\xd6\xf1\x55\x48\xa1\xf3\x30\xc1\xca\x6d\xc7\x95\xd6\xd8\x2a\x33\x12\xa8\xbc\x87\xd0\x62\x07\x74\x33\x80\xa3\xda\xc9\x28\xe1\xcf\x24\x46\x23\xb1\xc4\x50\x83\x68\x7a\x5a\x98\xb2\xb2\x6f\x11\xb6\x14\xda\x5c\xa2\xc8\x64\xf9\xe6\xb2\xa0\x70\x6d\x1c\x4c\x91\x7e\xf6\x4c\x0c\x6a\x0e\x13\x62\x10\xcb\x6d\x10\x6d\x4b\xe5\xd0\xc7\x09\xa8\x71\x73\x4e\xf1\xb6\x22\x51\x5f\x51\x68\x39\xd1\x09\x2d\x91\x1b\xdb\xe3\xb3\x9f\x43\x55\xcf\x03\x01\xd1\x9f\xfd\x8f\x4f\xea\x3d\xde\x86\xf6\x79\xd4\x35\xf1\x84\xd1\x0c\x59\x6b\xc8\xed\xd4\x1f\x8a\xc3\x4e\x2e\x65\x1c\x75\x9b\x69\xad\x23\x75\xb9\xe5\xda\x92\xe0\xa0\xa0\xb9\xad\x92\x70\xd5\x0c\x2a\x93\xd8\x21\xa1\xf4\x43\x5f\xdf\xbb\x33\x8c\xd5\x51\xda\x70\x83\x61\x7a\x04\x6d\xa6\x67\x1a\xe7\x2d\x96\x8c\x99\x09\xb9\x2d\xe5\x89\xf3\xf4\x07\x00\x02\x6b\x0a\x0b\x38\x89\xab\x5a\x07\xc4\xc3\xe8\x8e\xa7\x16\x96\x59\x50\x94\x64\xcc\x1f\x4d\xaa\x9c\xb1\xf1\x60\x54\x47\xbc\xb5\xd0\x1c\x68\xd1\xa4\x5d\x3a\xab\x64\xf8\xd4\xd0\x56\x4e\xcd\x76\x02\x63\xaa\x57\x3a\x77\x99\x13\xeb\x8d\x7c\x6b\xd2\x81\x2e\x3a\xd3\xab\x1e\x8d\x4f\xdd\xda\x91\x73\x80\x77\x1c\x20\x70\x00\x54\x12\xca\xd2\x1f\x0c\x80\xb6\x25\x7a\xce\x81\xd9\x87\xc1\x2a\xec\x30\x29\xd8\x0c\xea\x1e\x41\x07\x26\x33\xaf\x92\x13\x50\x50\x51\x5f\x69\x2e\xde\x2d\x5a\xe9\x21\xe1\x8d\xd1\xf6\xbd\x25\xd1\x54\x74\xf6\xa8\xf8\x66\x33\xeb\x6b\xd7\xb4\xde\x2b\xb4\xf0\xb4\xff\x66\x83\xd0\xdd\x36\x8b\x9d\xe3\xb5\x07\xa5\x0b\xab\xd5\x36\x6d\x50\xd0\xd1\x8f\x48\x34\xb1\xd7\x87\x18\x85\xc3\x32\xfe\xd5\xfc\x0a\xb1\x75\x6d\x4d\x43\xcd\xa5\x06\xe7\xa1\x70\x6d\x2a\x59\xcb\xad\xab\x8b\xd2\x39\x0e\x01\xc2\x5f\xbb\x9d\xf2\xe2\x15\x4a\x11\x5b\xc4\xf3\xf3\xba\x2e\x39\xb4\xd7\x26\xf3\xe1\x2c\x72\x80\x48\xb8\x69\xdf\x83\x38\xc9\x85\xa0\xef\x61\xc2\xcd\xd6\xc8\xdf\x19\x97\x5b\xbf\x4e\x1e\x98\x6e\xb3\xfe\x3c\x8e\x43\x72\x78\x4c\xb5\xef\x72\xf9\x4a\x32\xe2\x76\x63\x18\x14\xfe\xe4\x3e\x78\xcd\x09\xfc\x9c\xee\xd6\x11\xe4\x4a\x1e\x82\x23\x75\xe3\xa4\x07\xb7\x3a\x6e\x59\x93\x16\x9d\x98\x7d\x1a\x6c\xf4\x7a\xc2\xd3\xae\xb4\xe9\x5e\x59\x3b\x9e\xb6\xe4\xb1\x7a\xb4\xea\xb3\x17\xd3\x89\xac\x31\xc0\x60\x37\x7a\x83\x76\x2f\x9a\x98\x5f\xe7\x9c\x93\xb0\xca\x0e\x7b\x90\xcf\x1b\x3d\x27\x54\x87\x20\x60\x4a\xd9\xbc\x5d\x18\x02\xf8\xc8\x87\x55\xcb\x02\x29\x4b\x7b\x76\xfb\x5b\xa5\x84\x14\xb0\xd5\x9d\x79\xac\x60\xd7\x2d\x30\x2d\xd3\x3f\x9d\x9a\xc1\x5e\x82\x9a\xff\xc7\x5b\xc9\x6d\x03\x0f\x53\xc6\x90\x1e\xc2\x3d\xf9\x03\x4f\x23\x5f\x44\xad\xad\x9d\x71\xc8\x71\x1a\x8e\x6d\x52\x1f\x30\x0e\xcd\x1a\xc2\xd3\x29\x95\x0a\x69\xa2\x62\x11\x4a\x9d\xb1\x7d\xe7\xce\xed\xf8\x3c\xdd\x77\xf8\x6f\xe2\x61\x81\x01\x19\x36\xba\x5b\x9e\xf6\x81\xbb\x5e\x44\x85\xde\x1c\x84\x5a\x7a\x60\xaf\xab\x9c\xe0\xcc\xb6\x2e\x44\xe6\x4b\xcf\xf2\xa7\x7f\xcd\x1a\x3d\x62\xb1\x05\x09\x9b\xc6\xe2\xee\x62\x88\x00\xe4\x9d\x6c\xad\xde\xb2\x77\xed\x97\x82\x4d\xe2\x18\x9a\xd3\x06\x37\x64\x18\xd6\x86\xa5\xa3\x08\x85\x80\x15\x80\xed\x23\x77\x51\x5d\x21\xb0\xf6\xd8\xcb\x98\x98\x14\xf3\x67\x31\x7d\x42\x4a\xda\x39\x89\x86\xfa\xc4\xc2\xd4\x8e\xf1\x49\xae\xf3\x3d\x43\x56\x52\x8d\xb9\x25\xce\x4c\xd5\x4d\x55\xa2\x5d\x43\x28\xf5\x2b\x23\x4f\xf7\x31\x51\xae\x64\x6a\xca\x32\xbe\xb9\x7e\x12\x26\xc7\x42\x27\xd9\xa9\x70\xbe\xd9\x63\xf0\x51\xde\x1c\x34\xcc\x1b\x31\x23\xb0\x96\x9a\x71\x1d\xca\xb8\x4c\x8f\xc9\xcc\xae\xae\x4c\x9b\xe2\x9e\x92\x16\x08\x9b\x86\x19\x0e\x47\x5a\x74\x2a\x6a\x18\x96\x1e\x49\xb6\x60\xe8\x16\xdb\x51\xb5\xa2\x8d\x2f\xd0\x02\x48\x4a\x65\x7f\xd6\x6c\xb9\xe8\x87\xd2\x1f\xe8\xb1\x8e\x95\x9b\x94\x78\x5b\x30\x94\x44\xa3\xd6\x8c\x31\xc2\xc0\x53\x54\x4b\x89\x61\x66\xd4\x3b\xa2\x0c\xf8\xd9\x33\x60\x17\x4c\x98\xb0\x7d\xe4\x8d\x7b\xd8\xa7\x4a\x11\x26\x35\xb3\x80\xb1\xc4\xd9\xea\x4a\x84\x5e\xb7\xfc\xf5\xb4\x47\xbd\x8f\x86\xa1\x86\xeb\x26\xf5\xf6\x9e\x78\xad\xee\xb2\x25\x6e\x86\x71\x23\x23\xe9\x47\xb3\xa1\x37\x96\xa4\xff\x70\x28\x2f\x38\xf9\x84\x9d\xd7\xca\xb6\x4a\x1b\x47\x79\xd1\x1b\xbe\xf6\x38\xd1\x3f\x96\xa4\xff\xb0\xc8\x2b\x3e\x49\x08\xb4\xa5\xae\xf8\x8f\x10\xe5\x85\x8b\x57\xe2\xbb\x54\xdc\x6d\x0a\x41\x6a\x98\xf7\x2f\x62\x88\x07\xa6\x88\xb3\x59\x46\x4e\x47\xff\x75\x17\x63\xfe\x04\xf7\xb5\x8e\x5c\xae\xc1\x8b\x88\xcf\x3a\xeb\x69\x25\xba\x96\xe1\x66\x55\x2c\x70\x17\xe6\x82\x49\xec\x8d\x70\x20\xff\x96\x5e\x79\xb6\xeb\x95\x1f\x08\xf7\x42\xc0\x63\x78\xc2\x32\x8a\xd0\xec\x1b\xf7\xca\x16\x0d\x56\x62\xe0\xa7\x36\x4e\x01\xbf\x64\x0b\xd6\xd9\x8d\xd3\x99\x54\x80\xe4\xe6\x9d\x6c\x14\xc6\x57\x86\x7b\x74\xc4\x88\x54\x7b\xf0\x96\xe8\x53\x11\x1e\x2f\xa5\x51\x95\x59\xfe\xa5\x4b\xfd\x8e\x15\xd5\x37\xb7\xe4\x23\x12\xae\xbb\x70\x16\x51\x63\x47\x6f\x91\xde\xf0\x67\xfb\x51\xa0\x80\x47\x3f\x65\x3c\x80\xf3\xb4\xe8\x05\x74\x19\x86\xfd\xe7\x4a\xa0\xf8\xe9\xac\x38\xb7\x33\xd7\x59\xb5\xb5\xde\xa8\xfc\x46\x5e\x3a\x9e\xcc\x8a\xe3\x7c\xee\x8e\xca\x9a\x38\x60\x72\x7d\xe0\x51\xe7\xc1\x68\x46\xe9\x34\xd5\xeb\xa2\xba\x6a\x22\xb3\x3a\x6b\xa2\x32\x3b\x6b\xa3\xce\x2e\x2c\xef\x26\xfe\xd6\x7a\xdb\x54\x49\x46\xb7\x54\x79\xf8\x3d\x9d\x4b\x99\xc2\x3b\xc2\x70\x72\x02\x24\xdc\xd1\xb2\x80\x38\x66\x5f\x9b\x93\x54\x49\x1f\x56\x5b\x85\x8a\x5b\x01\xb2\xc5\xba\x60\xf6\xc2\xe6\x2e\x4e\x0f\x30\xce\x55\xb8\xa9\xe3\x38\x49\x00\x59\x9e\x97\x0d\xc7\x44\x35\x0f\x95\x37\xf6\x6f\x2d\x0a\x1c\x21\xf3\x6d\x76\x39\xa9\x8f\x1c\x5c\x2f\xb5\x4b\x52\x99\x9d\xb1\xe2\x21\xfd\x1e\x8c\xff\x36\xff\x88\x0c\x81\x62\xe9\x1e\xc9\x5c\xb5\x2b\x27\x49\xe7\x65\x2f\xb1\x9d\x61\xf6\xca\x46\x7a\x1b\xcd\xb7\x10\xfb\xb5\x7b\xed\x8b\xf3\xf0\x50\x7c\xf3\xb5\x77\x8d\xc3\x34\x65\x6a\x2d\xa5\xa0\x74\xc2\xdb\xa0\x5e\xc2\x5c\xdf\x53\x4b\xd7\x2b\x27\xbc\x4a\xe6\xfb\x52\x9b\x82\x53\xf4\x8e\x00\x1d\x66\x99\xf0\x0e\xc8\xe6\x82\x03\x34\xbe\x96\xd4\x96\x2b\xc6\x65\xf9\xd0\xc7\x22\xd3\x83\xd6\x6a\x1a\x5c\x91\xf3\xca\x8c\xe0\x45\xcd\x2e\x02\xc5\x3e\x70\xb6\xe6\xed\x97\x21\xcd\x5c\xec\xbe\xf5\x42\xf5\xe0\xb8\xc3\x7d\x76\xda\x86\x4e\x21\x07\x22\x66\xc5\xeb\xba\xe3\x52\x8b\x30\x72\xd6\x47\xc0\xdf\xbb\xc0\x2a\xb9\xd0\xfd\x1f\x20\xad\xc6\xf6\x95\x8d\x2f\x4a\x95\xe4\xf3\xe2\x36\x1b\x98\x4d\x9a\xfe\xf1\x6e\xff\xeb\xca\x7e\x8b\xab\x7d\x7d\x18\x3c\xf1\xed\x8e\x1d\x6f\x13\xe1\xb0\xe0\x98\xe7\x6c\xcf\xb8\xfb\x70\xef\xfc\xbd\x66\x25\xed\xde\xff\x10\x6e\x7e\xdd\xd8\x57\xd5\x58\xee\x55\xe1\xbc\x6c\x11\x41\x21\xb9\xcb\x8d\x21\xd3\xab\xc2\xfd\xfd\x38\xeb\x69\x44\x2a\xb9\x7a\x12\x33\xc9\xd9\x40\xb8\x85\x45\x59\x6f\xca\x05\x4a\xd2\x4e\xf1\x43\x38\x66\xa4\x04\xb7\x92\x2c\x03\xe3\x52\x1d\x12\x09\x9c\xc6\x8f\x83\x6d\xd6\x77\xf0\xac\x45\x1b\x0e\xc1\xf1\x28\xc9\x69\xfd\x77\x4c\x8c\x05\xdf\x65\xee\xe3\x37\xeb\x78\xd0\xac\xbb\xf2\xd3\x32\xed\xe7\x4c\x7a\x00\xac\x20\x42\xa2\x08\xc1\x2c\xe4\x27\x1a\x5c\x6e\x40\x4f\xde\xa4\x6c\x0b\xef\xf7\xff\x18\x6f\x3c\x69\x91\xbd\xe3\x59\x55\xc8\xd7\xca\xa3\x96\x3a\x87\x38\x96\xde\x70\xec\x80\x75\xa3\x88\x5a\xe5\x13\x38\xf3\xb9\x26\x3e\xe6\x73\x34\x50\x63\x58\xa1\x59\xfb\x13\x96\xc5\xdf\xcf\xef\x0b\xe5\x11\x8f\x7d\x74\xf2\xac\x70\x8f\x2d\xb4\x09\x89\x8e\x79\x43\x1c\x26\xea\x1f\x83\x7a\xa5\xb1\xca\x0a\x0e\x5a\x60\x37\xa1\x29\xaa\x3c\x69\x9f\x1d\xa9\xa2\x36\x4f\x67\x67\x74\x7f\x78\xbc\x0a\x68\x54\x49\xba\x1f\x77\x31\x61\xee\x72\xcc\xcc\xde\x33\x3b\x65\xae\x17\x1e\xbb\x99\xe5\x30\x74\xfe\xd0\xeb\xfc\x1e\xfd\x59\x73\x6d\x76\xcb\x59\x45\xf6\x8d\xde\xc3\x1a\x7b\x29\xae\x4b\x1e\x92\x92\xf6\x59\x1b\x68\x01\xf4\xa3\x1d\x26\x8d\xdb\x91\xc7\xb6\x85\xf7\x1b\x58\x9e\xee\xd6\xe1\xb1\x3e\x54\x29\xab\x30\xff\x6a\x4a\xa2\xf9\xd8\xd7\xaf\x8f\x24\x37\x0a\xa0\xbf\x93\xa2\x80\xdb\xb7\x6f\x12\xc1\x55\x63\x6b\x97\xb1\x77\xf1\xd4\x59\x3b\x38\xa0\xb6\x3e\xcc\xeb\x80\xf1\x2b\x67\xd1\x36\x77\x26\x24\x1d\xd1\x3e\xde\x82\x75\xcb\xeb\xb6\xee\xfa\x3e\x1b\xc2\x0a\xdd\x56\x5a\xeb\xc1\x88\x4a\xb4\x05\xa3\x91\x1a\xb4\xb8\x67\x82\xcb\xbf\xe5\x3d\x8a\xfe\x83\x3e\x4f\x8b\x01\xe5\x69\xe9\xb6\x5d\x40\x9c\xc9\x01\xff\xe5\x51\x59\xd6\xf7\x86\xf9\xa7\xf7\xd8\x4f\xda\xe6\xda\xf2\xbf\xd2\xc6\xbd\x0c\x41\x49\xae\x4e\x25\x46\x28\x9d\xe0\x9a\x04\x59\xfe\x39\xcc\x39\xa3\xde\x4a\xd5\x43\x08\x34\xce\x51\x40\x4a\xfd\xb8\xb6\x39\xa0\xe1\x75\xae\x33\x70\x3d\x05\x82\x30\x41\xa3\x8a\x31\x0a\xb8\xe4\x2c\x5e\x19\xf5\x3e\x05\x84\x28\xb5\xda\x48\x52\xa9\xd4\x42\x78\x8d\xb5\x4c\xd4\x87\x88\x6a\x2d\x18\xf0\xed\xef\x61\xda\x70\x33\xad\xff\xfb\x37\x75\x62\x03\xf0\x4e\x56\x34\x7c\x07\x11\x75\x87\xa0\xe7\xa0\x8b\x61\x6c\x65\x0c\x8d\x9a\x7a\x08\xa2\xf6\xa8\x4a\x40\xea\xd5\x35\xfa\xab\xe2\x79\xb8\x43\x17\x07\x8d\x51\x40\x52\x52\x71\x82\x4f\xf9\xa7\xb0\x3c\x2f\x1d\xe4\x26\xf1\x1d\x49\x47\x26\x02\x2d\x70\x40\x5f\x53\x2f\xbb\x6d\x6e\xa6\xf5\xbf\xd8\xc2\x03\x63\xa6\x90\x5a\x35\x3b\xf5\x3c\x79\x04\x09\x18\xe3\xcb\x18\x2f\xe9\xaa\x9e\x50\x96\xc8\x65\x7f\x20\xe0\x9d\xb6\xfa\x81\xad\x02\xf0\xa2\x04\x94\xd3\x07\x96\x50\x2e\x57\x6b\xf4\x59\x89\x44\x34\xce\x01\x3c\xed\x1f\x41\x8a\xfa\xa5\xd3\x17\xa6\x90\x4e\xc7\xac\x95\x9a\x69\xc5\x44\x95\xf6\x0e\x4e\x24\x7f\xc2\x37\x20\xed\xf7\x2e\x86\x20\xd2\x2b\xcb\xc0\x67\x1c\x49\x9c\x67\xa1\xc6\x3a\xb5\x23\x3f\xe1\xb8\xa4\x50\x75\x47\x97\x17\x71\x2b\x35\x3c\x28\x93\x19\xcf\xda\xae\x2d\x48\xbb\x4a\x44\x9f\x1b\xaf\xb8\xe0\x55\x31\x26\x67\xec\xbb\xce\xbe\x23\x59\xb9\x02\x18\x23\x7d\xc4\x83\x90\x89\x07\x2d\x94\x73\xa3\x15\x3c\x49\x9a\xca\xb9\x8d\x60\xce\x7b\x36\xc2\x81\x70\xd8\x53\xa4\xfb\x9a\x75\x41\xeb\x9c\x6d\x6d\x16\x8b\x47\x83\x70\x3c\x10\xed\x99\xdc\xfa\x73\xf8\x4f\x69\x63\x30\x02\xca\xb6\x82\x75\xbf\x18\xf8\x05\x9d\x94\x9c\x66\x1e\xc2\x35\x6f\x23\x0f\xac\x92\x9c\x92\x1f\xda\xd5\x2e\xef\x6f\x5d\x85\x6c\xae\x3c\x28\x7f\x49\xeb\xd5\x96\x2b\xd0\x20\x5b\x14\x44\x2d\x96\xb1\xd3\x12\x64\xa1\xf1\x04\xbf\x71\x1d\xea\x9d\xbb\xe1\x29\x19\xcb\x3c\x55\x50\x71\x79\x6f\x51\x5e\x34\x39\x4b\x1c\x9b\x12\x23\x09\x2a\xc1\xbf\xf1\x25\x5e\xfe\xe6\xf6\x8f\x22\x56\x1f\x76\x84\x1c\x2a\x2d\xc2\xe6\xea\x73\xd9\x79\x31\x22\x4e\xa4\x21\xc3\x34\xc6\x08\xf0\x5c\x55\x24\xd1\x9f\xca\x8b\x5b\xad\xcc\xc0\x4d\x7d\x81\xdf\x91\x4f\xbe\x7f\x72\x02\x3d\x99\xf5\x4b\x2d\x91\x07\x0a\x89\xbf\x38\x32\x49\xe5\xad\xfe\xde\x2b\x91\x08\xca\x28\xb1\x1d\x59\x64\x6d\x68\xaf\xa6\xc5\x90\x88\x9c\x05\x4c\x61\xa0\xbc\x24\x55\x99\x54\x97\xae\x0a\xf6\x94\x43\xf7\x28\x06\x0f\x04\xbe\xda\xe5\x8a\x1d\x8e\x1d\x27\x20\x48\x28\x04\x78\x0e\x08\x19\xcb\x15\xb5\x0a\xf6\x03\x03\xca\x3d\x9e\xaa\x3c\x58\x55\x97\xae\x51\x94\xa4\xca\x03\x89\xc2\x05\x4c\x0e\x29\x46\x4d\x8b\x87\x5e\xab\x3e\x86\xc2\xbc\x85\x70\xc5\xde\x18\x85\xef\x31\x03\xcc\x42\xb8\x8f\x6a\xb0\x2a\xbd\x0e\x08\x19\x4f\xf2\x80\xed\x7c\x4f\xb1\x0e\x0c\x14\x2c\x82\xee\x02\x8a\xfd\x91\xee\x30\xc9\xdf\xb0\xaf\xca\xb9\x02\xd0\xbd\xf3\x88\x2c\x1c\x75\xee\x89\x80\xc3\xe8\x84\xfc\xc0\xc2\x0a\xb4\x48\x73\xfe\x12\x35\xbd\xde\xc4\xb2\xd9\xca\x52\xa5\xd5\xea\x28\xa5\x87\xf3\xf5\x8d\x2b\xa4\xd0\x46\xbb\x4c\xc7\x1f\x3f\x46\x68\x23\x7e\x4a\x17\xf4\xf2\xbd\x31\x0f\xf5\x94\x96\x96\x02\x1c\x0b\x94\xb4\xa1\x10\x70\x29\x4f\x22\xcd\x2d\x4a\xc8\x12\xfd\x71\x10\x0d\x9b\x02\xc9\x83\x37\xc7\x75\x36\x95\xd7\x28\xdb\x84\xa2\xbf\xf7\xab\xec\xff\xee\x96\x21\x50\x40\x81\xea\x08\x3e\x1a\xc3\x81\x31\x94\x0a\x00\xa4\x26\x14\x19\x27\x8e\x73\x33\xad\xd9\x87\x86\x58\x2c\xeb\x39\x59\x83\x17\x7c\xbf\x73\x1a\xab\xd3\x41\xc8\x43\x45\x76\x70\xc6\x7c\xcc\xba\x25\x14\x98\xb3\x04\x33\xb8\x37\x1f\x7f\x94\x5f\x2a\x78\x43\xeb\xe6\x38\xcf\x0a\x3c\xa3\x22\x8c\x1f\x1b\x27\x22\x47\xc1\xb5\xf1\xe7\xd2\x21\x07\xdd\xc2\xa3\xc4\x10\xa4\xe7\x56\xf5\xeb\xb3\xa9\xe0\x73\xc0\x26\x3c\x36\x44\x2d\x6d\x9e\x8f\xc1\x9b\xa1\x8b\x0e\x81\x74\xae\x74\x9e\x7a\xe8\x71\x35\xfe\xb7\x22\x6d\xf7\x8c\xaf\xbc\x4a\xeb\xdc\xec\x7d\x5f\xfc\x28\x5e\x0e\xbd\x6d\xed\x27\x56\xa0\xb3\x9b\x9b\x73\x12\xde\x02\xdb\xb4\x46\xf7\x3e\x12\x0f\x7d\x2a\x73\xd6\x56\xc9\x15\xd3\x87\x03\x16\x22\xb0\xa6\xa0\xcc\xf7\x6d\xfc\xb7\xb7\xad\x06\xef\xfc\xfc\xa8\xd5\x16\xf4\xa9\x39\x6f\x71\xa8\xb9\xa7\xba\xd1\xf9\x7b\xc1\x94\x6f\xac\x90\x21\x0c\x3c\x0e\xa2\x7f\x5d\x77\x07\xbf\x40\x61\x0e\xf0\x23\x61\x8c\xc4\xe9\xb9\x59\xd7\x59\x7d\x69\xc1\xa2\x94\xc4\x7c\x23\xd2\x72\xef\xd2\x5c\xf6\x06\xf2\x89\x97\x49\x0c\x02\x94\x5f\xdf\x99\x89\x57\x2b\xdb\xcb\x22\xed\x91\x8e\xff\xdc\x4e\xdc\x9e\x82\x30\x97\x7c\x97\xe7\xa7\x39\xa7\x38\xe8\xd6\xbd\x0a\x2e\xc5\x79\x66\x90\xa4\xb8\x08\xef\x6e\xec\xfe\x73\xcb\xa1\x00\xe8\x62\x98\xbf\xce\x7e\x1d\x70\x2a\x35\x45\x23\x01\xf2\x05\x73\x0a\xcb\x76\x4e\xde\x39\x3e\xd0\x63\xc9\xe4\xe8\xb3\x51\x47\xd5\x21\xeb\x80\xc3\x9a\xc7\x0f\x81\x38\xfe\xfc\xd0\x8a\x91\x79\xb3\x36\x26\xaa\xca\x0c\xbd\x2d\x32\xb3\x7e\x51\xfb\x96\xcb\x00\x81\x5b\xf4\x61\xe1\xb9\x96\x98\xeb\xd0\xbe\x29\x35\xd5\x1f\xe3\xe3\xd9\xe9\x5f\x5b\x97\x91\x7a\xef\x5f\x69\x1e\xef\x74\xaa\xe5\xf3\x62\x28\xdf\xad\x1e\x1a\x4f\xa4\x8d\x3d\xe8\x43\x2f\xfa\xc9\xe0\x9c\x0c\xed\x0e\xb0\x19\x50\x34\x3f\x0c\x0f\x39\xe6\x54\xcb\x2c\x02\xee\x31\x00\xa2\xaf\xd5\xac\xd2\x14\x86\x39\xd1\xcd\x22\xf5\x66\xbd\xe0\xc9\x50\xee\xac\xa6\x5d\x53\xbb\xf5\xdb\x1f\xd4\x9c\x7f\x28\x1f\x30\x76\x34\xfb\x73\xcf\x4a\x07\x73\x62\xb5\x99\x6e\x51\xb7\x7b\xe9\xec\xfc\x06\x7d\xcd\x0c\x23\xc1\x40\xa4\xfd\xf2\xf7\xee\xc9\x8f\xa0\xf1\x9f\x19\x98\x55\xd9\xc1\xfb\x13\xbd\xa6\x5e\xbe\x9c\x52\x2b\x18\x81\x2f\x36\xf7\x27\x0a\x12\xa4\x97\x90\x19\x8b\x8b\x11\xc8\x4b\x68\xa7\xf7\x2d\xed\xdf\x46\xf8\x73\x81\x35\x93\x58\xfe\xb4\xde\x96\x58\xfc\x79\x58\x51\xf7\x33\x88\xd5\xfe\x07\xd2\xe9\x0d\x80\xb8\x9d\xed\x57\x4b\xfd\x8a\xd4\x62\x22\x8d\xa8\x26\xcb\xc3\xa2\xd1\x7b\xd6\x5b\xed\x6d\x13\x96\x70\xdb\xda\x1a\x5a\xa2\xbe\xe2\xd6\xb6\x2f\xca\xb2\x96\xc3\x5a\x5b\xcb\xdb\x5a\x2d\x6c\x24\xde\x4e\x8a\x65\x94\x57\x48\x57\x06\xcf\x4d\xc8\x5f\x18\xd1\x0a\x56\xd3\xa7\xe4\x78\xe6\x73\x93\xe4\x80\xb1\x58\x0d\x29\xe4\xd6\x1c\x1f\x99\x6f\xc1\x43\x26\xa9\x36\xd9\x6c\x98\x6b\x74\x49\x70\x89\xa1\x5d\x00\x2e\x40\x3f\x77\x1a\x53\xb9\x9e\x86\x68\x97\x73\x2d\xe2\x86\x24\xe1\x39\xec\xe8\x6e\xb1\x50\x5b\x03\xb6\x9f\xf8\xf5\xb0\x8e\x70\x83\x59\x8f\xd3\xb2\x47\xe6\xf5\x1f\x3a\xf5\xa5\xaf\xf5\xf5\x99\x45\xeb\x74\xd1\xd7\xe7\xee\x03\x62\x26\xb8\x3c\x0d\x98\x45\xe8\x5f\xeb\xf1\xd1\x70\xd1\x30\x4a\x74\x7a\x1f\xc0\x58\x0c\xa7\xad\x42\xb4\xb2\xf5\xac\x2e\x52\xf6\xed\xfa\xf5\x0a\x2e\x45\xc2\xe2\xc4\x8e\xa0\x94\x75\x2d\x30\x4f\x53\x42\xc3\xbe\x18\x6d\x09\xe2\xdb\xd5\xc7\xa2\x9c\xa0\xf1\xe2\x93\xec\x1a\x07\x5d\x76\x94\x16\xdf\x64\x9d\x60\xb7\x7f\xcb\xc3\x9d\x58\x19\xff\x50\xff\xe0\x9c\xe2\xfa\x9b\x5b\x0d\x17\x8c\xea\x56\xee\x43\xd3\x34\x4f\x10\x91\x8c\x91\xb5\x90\xbf\xf7\x30\x26\x7a\xcd\xcd\x75\xa0\xc0\x34\xc6\x26\xd1\x10\xd4\x45\xa1\xca\x99\x27\x74\xd9\x41\xee\xf6\xcd\x42\xc1\xb5\x25\xda\x2b\x87\x44\xcb\x8e\x47\x1c\x7f\x7e\x41\xed\x78\xd6\x1e\xf0\xbc\x43\x50\x4b\x5a\xaa\x00\x97\x6e\x16\xac\x9f\xe7\xbe\x52\x67\xbc\xbc\x78\xc2\x2b\xce\xf4\x1b\x69\x7c\x1b\xb8\x6f\xf1\xca\x9c\xe2\xf1\x92\x38\xac\xb7\x6f\x9c\x17\x71\x4a\xb3\x60\x03\x9c\x14\xeb\xfc\x47\x14\xdc\xe1\x7e\x0c\x86\x89\xc9\x95\x6f\x20\x50\x0a\xe7\x38\x10\xb0\x79\x0f\x75\x71\x82\xeb\xa2\xb5\xd9\xc2\x08\xcc\xfa\xd6\xf0\x90\xa0\xb5\xfa\x99\xa7\x8d\x8d\x9f\x99\xd5\x8c\x3d\xc6\xb6\x9f\x13\x9b\x54\xdc\xc2\xb7\x6e\x32\x70\xad\x12\xb9\xbf\x61\x41\x1d\x2f\xe1\x46\x5b\x0d\x5d\x2b\x70\x5e\xb6\xb5\x46\xb5\x17\x9b\xc4\x28\xca\xf3\xfd\xc2\x3f\xc9\xac\x33\x67\x67\x01\xf3\xb3\xf5\xd9\x0e\x04\xec\x51\x29\xb4\x01\xc3\xc4\xc4\x8a\xb5\x0e\x44\x4c\x6d\x34\xf7\x98\x47\x3b\xbf\x3f\x38\x31\xd7\x5b\xd1\xab\xd4\x54\xd8\x3e\x20\x3d\xb1\x51\x38\x1a\xe3\x13\xaa\x29\xca\x92\xde\x35\xc1\xa8\x63\x6b\x2b\x67\x64\x52\xbe\xf6\x00\x86\x88\x1d\xc3\x12\x41\x7c\x86\x76\xe4\xec\xfd\x61\xea\xae\x6b\x42\x63\x7a\xff\xed\xe5\x5b\x95\xe9\xc9\x43\x38\x94\x5e\x27\xb3\xd5\xa4\x86\xd4\xcf\x4f\x07\x80\x53\x30\xb7\x83\x2a\x20\x29\x9b\x35\x72\x8f\xeb\x7c\x9f\x80\xc8\xa4\x8a\x93\x5e\xcc\x3f\xf8\x7a\x7d\xb7\x5b\xf0\xa2\xc0\x81\x53\x57\x07\x55\xf7\xbd\x1e\xf6\x1b\xb1\x04\xec\x54\x7d\x1a\x81\x8d\x3f\x4c\xd7\xc0\xf6\xf9\x0e\x55\xcd\x5e\xbb\xc0\x8c\xcd\x7d\x18\x4c\x09\xd2\x36\x68\xb8\x38\xdb\x0d\xee\x62\xe2\x8d\xc7\x8e\x45\xda\xb0\x02\x6e\xbc\x2f\x84\x4d\x01\xd1\xd9\x41\x85\x0e\x04\xec\x36\xca\xe2\xeb\xfb\xb6\x93\x36\x4d\x6b\x14\x3c\xe9\xcc\x75\x39\x8d\x6f\x35\x29\x3f\x71\xa9\x09\x23\xc6\x30\x31\x39\x75\xa3\x41\x2e\xca\x6d\x58\x02\x16\xa9\x69\xc8\xaa\xf2\x66\x67\xc6\x51\x7f\x1a\x93\xb7\xba\x57\x6f\xf1\xfe\x67\xad\x40\xc6\xeb\x18\x75\xac\x3b\xc3\x09\xc9\x6f\x17\x23\x08\x96\xa5\xcc\xf5\x26\x8f\x6f\x34\x8e\x11\x4f\x91\x3a\x6f\x6e\xd3\xf4\x4d\x5e\xa9\x9d\xa2\x3b\x3e\x9e\xe7\x72\x82\x30\xb6\x2e\x27\x9a\x7d\x17\xbc\x29\x58\xf5\xe4\x0c\x22\xa2\x39\x99\xba\x4f\xe7\x0c\xb0\x8a\x8b\x7e\xa9\x2e\x37\x40\x33\xbc\xb4\xf2\xf1\x9a\xbf\x5f\x7e\x49\x2a\xfa\x8f\x95\x60\xfa\x85\x0e\xeb\xd6\xa3\xc1\xb1\x12\x71\xad\x14\xc1\xca\x5e\x0c\x51\x28\x54\x86\x95\xcf\x03\xd8\x04\xdf\xa0\x31\xf7\x60\x60\x06\xc2\xf3\x77\x32\x8d\xbe\xde\xc6\x75\xad\xa4\xe0\xaf\xd5\x93\x05\xaf\xd7\x05\xd8\xa3\x08\xcb\xda\xc5\x30\x06\x12\x8c\x46\xef\xb5\x28\x7a\x63\x3c\xb9\xc8\x6d\x4c\xa9\x68\x63\xf2\xf5\x2d\x70\x13\x14\x86\x3a\x92\x7c\x6d\x03\xe9\xde\x2e\xc7\xa2\xb9\x56\x66\x68\x4a\xe2\xea\x4d\xf8\x7e\x9a\x20\xed\x5b\xd0\xb5\xb4\x7d\xfc\xf4\x72\x8a\xca\x32\x8b\x04\xb8\x7e\xfc\xe8\xa0\x77\x7a\x4a\x05\x90\x3a\xd5\x8d\x7b\xe9\x73\x09\x10\x9e\x33\x11\xf6\xf7\x78\xd4\xba\xd7\x2c\x47\xb7\x20\x9d\x4d\x4b\x64\xbc\x9a\xb0\x76\x17\x25\x62\xed\xb1\x6f\xbe\x83\x7f\x07\xd6\x7c\x02\xe0\xfc\xad\xda\x6c\x36\xa5\x7a\x09\x5e\x61\x43\x47\x3b\x7a\x56\x6c\xb8\x0e\x20\x7c\x5f\xf5\xc3\x0f\xa6\xfd\x6d\xe0\xaf\xb7\x45\xa9\x5a\x51\x6c\x9c\xee\x5a\x1c\xeb\xee\x3e\x67\xb7\xe9\x10\x73\x53\x6f\x98\xac\xbf\x6c\x07\x9b\x03\x87\xf3\x50\x8f\xe4\xae\x1b\x38\xff\x43\xe8\x34\x3e\x40\x15\x9a\x8f\xf2\x80\x65\x31\x62\x14\xcf\x82\x1f\xdc\x1d\x9c\xe0\x09\x20\x0e\xfe\xcc\x7a\xd0\xd7\xf7\xe0\x46\x08\x5d\xb5\x35\xb6\x03\x51\xc6\x83\x8c\x2f\x59\x0d\xe1\x76\x41\x66\x47\xdb\x57\x12\x4a\x3b\xff\xa8\x3d\xde\x79\x77\x16\x40\xbc\x52\xbf\xdb\xe5\xfe\x71\xba\x19\x5c\x03\x12\x6b\x4b\x30\x7b\x32\x74\x76\xed\x30\x06\x3d\x22\x77\x0d\x30\x7f\xc4\x4e\xde\x17\x94\x03\xf5\xbc\x72\x0d\xaf\x44\xee\x6e\xda\x06\x83\x4a\x60\x33\xc4\x37\xf9\x25\x2f\x2d\xc3\x2a\x9d\x52\x9e\xee\x80\x2e\x55\x2b\xfc\x5b\x6c\xaf\x51\x9d\x86\x37\x48\xc2\x16\x7f\xc1\xd7\xf3\x30\x78\x1b\xf8\x2f\x7b\xc7\x86\x01\x71\xb0\x90\xc1\x38\x3e\x36\x46\xb2\xbe\x0e\x27\x30\x2a\x08\x47\x5c\xf2\x51\xdb\x61\xd7\x24\x3b\x03\x9e\x68\x89\x66\x14\x00\x45\x42\xd7\xfc\xa7\x99\x43\x12\xba\x96\x84\xb7\x2d\x60\x19\x30\x81\xdd\x01\x29\xf0\x8f\x83\x79\x94\x5b\x68\xca\x91\x91\xf6\x13\xbf\xc4\x56\xea\x95\x0a\x48\x32\x9e\x70\x43\x8a\x19\xb4\x78\x51\xb5\x50\xc2\xa5\xf0\xe8\x39\x9a\x12\x3e\x26\x7a\x67\xe1\x80\xad\x8f\x2a\x95\x2b\x6b\xc9\xbc\x84\x27\xc5\x14\xbf\xca\x57\x5f\xa4\x7e\x49\xf9\xb5\x8e\xc1\x50\x67\x5f\xf7\x10\x43\x4f\x7b\x62\xf1\xe2\xce\xcc\x96\x89\xa3\xaa\x61\xd5\xb7\xf3\xb6\x4e\xc9\xc8\x20\xf0\xd0\xf4\x0a\xa7\xfb\x7e\x41\x27\x0e\x95\x2f\x02\x49\xd9\xe5\xed\x8c\x9f\x6f\xb2\x99\xf5\xea\x1f\x22\xa7\x0c\xda\xdc\xac\x1a\x2a\x30\x77\x02\xa7\xc1\xb9\xf3\xb0\x81\xeb\x8e\x4b\x1a\xa3\x4f\x4c\x78\x8b\xfb\x89\x69\x31\xc0\x4d\x2a\x7f\xcb\x80\x7a\xdc\x97\xb1\x7b\x99\x20\x9b\x6d\xcd\x65\x4a\xba\x21\x2c\x4f\x27\xf6\xa8\x5a\x32\x4e\x8a\x6d\x0e\xc2\x0f\x06\xe2\x3a\xa8\xb4\x8e\xdc\xa2\x2a\x47\xc7\x60\xe0\xf4\x78\x5d\x73\xd2\xb6\x23\x66\x44\x5c\x98\x10\xfd\x01\xf2\xba\x15\xa3\xc4\x46\x49\x82\x9d\x48\x77\xf3\xed\x5d\x12\xab\xaa\x00\x92\x49\x0b\xfb\xa2\x91\x3f\xb8\x37\x23\x15\xc8\x82\x55\x89\x2e\xf1\x35\x77\x35\xc9\xae\xce\x52\x3f\x37\xfb\xd6\x17\x90\x0f\xae\xe4\x30\x1c\x91\x3a\xbd\x33\xa9\xbf\x6e\x13\x01\x70\x26\x39\x26\xe7\x56\x75\x70\xb0\x1d\xb4\xa4\x41\x46\x73\x90\x14\x9b\x8c\x1b\x55\x63\x3b\x49\x7d\xbb\x21\x5c\x8f\x18\xae\x55\x76\xc2\x1b\xb4\xe5\x7d\xa8\x84\x01\x62\x82\xbf\x0f\x99\x7a\x3a\xcd\xcd\xce\x39\x79\x1e\xdc\x21\x20\x52\xd9\xd4\xd8\xd7\xce\xbe\x93\xee\x93\xde\xfc\xa9\xca\x0a\x4e\x40\x29\x89\x30\xdf\x97\x44\x64\x3b\x28\x41\xb0\x58\x72\xb4\x5b\x42\xf9\x12\x4e\xfe\x61\x1d\x1f\x2b\x96\xe3\x7b\xc7\xcd\x3f\x58\x81\x87\x13\xfe\xdf\x2f\xa7\xaa\x4a\xda\xbd\xd5\x9c\x76\xd6\xdd\xb6\xc3\x36\xf6\x6c\xd2\xa4\x67\x8c\xb4\x87\x4f\x25\xba\xa5\xc1\x50\x0a\x28\xc5\x2f\x56\xab\xcd\x20\xea\x6a\x0e\x84\xfe\x3e\x4d\x54\x8d\xf2\x63\x37\x34\x62\xc9\xa4\x5e\xec\x7e\x5e\xec\x28\x29\x79\xc7\x14\x49\xbd\x8a\xc7\xd8\xd0\x84\x65\x37\x61\x27\x78\x8c\x55\x24\x75\x38\x95\x91\xe6\x2f\xa1\x9c\xe2\x9c\xf4\x4e\xf2\xce\xa8\x27\x16\x6e\xba\xe0\xce\x68\xe8\xb4\x91\x9e\x35\x31\xdb\xe8\x19\x3b\xbe\x5e\x6e\x34\x8b\x38\xeb\xbe\xdf\x96\x53\xcd\x71\xcf\x46\x3b\xe2\x20\x4a\x78\x0e\x89\xa4\xdc\xca\xf0\x5d\xf0\x5d\xe6\xe6\xfe\x59\x20\xee\x1d\xd6\x4d\x47\x2d\x57\x4d\xa8\xc6\xd5\x5f\xc9\x09\x4b\x0f\xe3\xa6\xc7\xe9\x56\xa4\x67\x47\x67\x17\xc7\xe4\xe3\xd3\x3e\x84\x95\xdd\x57\x26\xfa\xc2\x19\x19\x69\xbd\x26\x0d\xfb\x0c\xc9\x99\xdb\xa3\xce\xba\x35\xcb\x58\x98\x6e\xbc\x13\xd6\x17\x46\x3e\x67\x6c\x61\xd1\xe2\xa7\xb2\x8f\x30\xc3\xe6\x11\xc2\x78\x29\x7b\x93\xe5\x1b\xe2\x38\xdc\xdc\x7d\x3e\x3b\x7c\xce\xc4\x39\x09\x69\xb8\x20\x37\x3f\xc4\xc9\x6b\x4e\xc1\xbc\x1b\xce\xc1\x57\xb6\xbd\xa6\xe6\xff\x16\xe2\xb3\xfc\x20\xf9\xd5\x41\xf2\xf2\x50\xf9\x45\x6a\xf6\x87\x70\xe5\xa6\x59\xd2\x72\xd2\x8a\xd2\x13\xf2\x1d\x92\x4a\x16\xe1\x12\x70\x18\x37\xc3\x7e\x56\xa1\xbb\xda\xc0\xb7\x38\xe0\xb4\xcb\x6f\x9f\x3f\x97\xa3\xda\xef\xbb\xcb\xd7\xfe\xeb\x20\x87\xab\xda\xe7\xad\xfc\x33\x23\x4a\x46\x09\x3b\x53\x6c\x36\x10\x51\x41\x80\x69\x12\xdd\x7f\xab\x04\xa4\xf1\x05\x43\xdf\x0f\xec\x66\x7f\x54\x30\x59\xf2\x77\x1e\x02\xc2\x49\xfb\xf7\xb4\x2b\x7e\xd4\x1e\xb4\x5b\x97\xb0\x6b\x42\x1d\xb1\x05\xe2\x93\x34\xd1\x31\x4c\xf9\xa8\x5b\xa1\x2a\xf3\xc6\x3b\x2f\x6a\xd3\xfa\x4c\x01\x41\x4d\x30\x58\xe5\x7d\x3e\xfd\x10\xb1\xb9\xa4\xb2\xf5\x2e\xe4\x74\xd8\xba\x75\x15\xc8\xc3\x74\x1f\x6a\x8d\xb2\xc4\x69\x5a\x8d\xb8\xea\x36\xc4\xec\xa1\x29\xe3\x10\xb1\xa4\x75\x11\xec\x1e\x64\xf8\x9a\xf8\x6e\xe3\xae\xfc\x04\xc0\xb9\x95\xab\xbf\x9e\x7f\x3f\x94\xb4\xd9\xca\xca\x15\xee\x0a\x83\x7c\x6e\x34\x6f\x5a\xbb\xf3\x38\x48\xdb\x2f\xa3\xd0\x68\xd5\x21\xab\xdd\x04\x06\x7d\x83\x49\x3e\xa9\xd7\x16\x1f\xde\xfc\xdf\x64\xfe\xe4\x09\xe4\x7f\x5f\xe3\x15\x08\x59\xf6\x33\xa3\x72\x44\x90\x77\x63\x36\xd3\x5a\xf9\xb5\xcf\x4b\xe5\x05\xd8\xac\xf8\xf7\xc6\x41\x1e\xbf\x3b\xf8\x9f\x54\xc9\xf8\x9d\x05\x01\x20\x47\x58\x19\x4b\x62\x34\xee\x70\x00\x3a\x49\x39\xe8\xeb\x6d\x8d\xca\x7b\x23\x3f\x7b\xff\xc7\x58\x25\xf6\xa5\x43\xb0\x87\x4b\x4d\x3b\xe1\x8c\xeb\xc2\x00\x45\x8d\x28\x7b\x76\x54\x12\x36\x0b\x4c\x61\x9b\x59\x7d\xc6\x6a\xe3\x4f\x93\x8c\xd1\xad\x54\xf6\xd0\xb2\xbf\x60\x10\x75\x20\xb1\xb9\x00\x84\x95\xed\xbb\xcb\x1f\x4a\xc4\xda\xdb\x83\xf5\x32\x66\x84\x31\xf6\xdf\x44\x9a\xe9\xe3\xae\x2f\x9f\x4d\x1a\xfc\xe8\x52\x8d\x31\xb3\x43\x62\x87\x16\x20\x40\x23\x0f\xc4\x5e\x24\x79\x48\x22\xb6\x63\x03\xe1\x25\x1b\xdf\x80\x1b\xe4\xc0\x90\xe2\x2e\x13\x4d\x74\xbe\xd8\x42\x9b\xc9\x6c\x37\x20\xea\x94\xd5\x5e\x84\xa7\xc8\x5d\x5d\x5d\xbd\x2a\x97\x02\xbf\x08\x10\x18\x12\x65\xc2\x67\x5e\x31\x3a\x8e\xb3\x09\x76\x22\x74\xaa\xbc\xc5\x32\xed\xe5\x3d\x4d\x40\x66\x5d\xe7\x4d\xba\xcc\x9f\x44\x5f\x9c\xf1\x77\x60\x74\xd1\x98\xfc\xef\x02\x86\xc1\xff\xa6\x6d\x9d\xac\xaa\x95\xc8\x75\x1e\x4a\x77\xa5\x22\x42\x68\x9b\x96\x85\xb4\x4f\x3b\x93\x1b\x1b\xfc\xd6\xbd\x04\x2e\x84\x85\x77\x89\x33\x2c\xc3\x65\x4a\xfb\x56\x4b\x6d\x04\xc4\x43\x32\x4c\x43\x14\x79\xd3\x9d\x4f\xd8\x07\x11\x4c\xfd\x81\x55\x95\x7b\xca\x2f\x5c\x22\x88\xe6\xf1\xef\x4b\xb1\x09\x68\x81\x9e\x90\xaa\x09\xbf\x62\x78\x1a\x5a\x88\xbf\xeb\x4c\x52\x12\xbe\x9a\xba\x69\xbd\x4f\xc7\x28\x3d\xee\xb6\x7c\xd2\xed\xa4\xfc\xc7\x56\x7d\x88\xba\x29\xf0\xb5\xd7\xbe\x9d\xe0\x5b\x5b\x01\xe9\x1f\xda\x50\xf6\x5b\xcf\xf3\xee\xf1\x6e\x1d\xcc\xf3\xe4\x32\xec\x36\x59\x17\x9d\x4b\xaa\x95\x09\xbf\x55\x18\x4c\x13\x9a\x7d\x03\x92\x57\x19\x30\x24\x7f\xda\x83\x52\x3a\xa0\xa7\x0c\xa5\x4f\x00\xfd\x33\x49\x6a\xba\x28\xce\x92\x1f\x52\xd6\x85\x4a\x8d\x80\x0b\xf0\x91\x29\xa7\x9d\xd4\x16\xf9\xed\xb7\xa6\xb1\xb1\x05\xfb\x06\x48\x9b\x49\xfb\x83\xd9\x6e\x9c\x53\xb7\x28\xcb\x67\x98\x4b\xea\x70\x0b\xa5\xa8\xef\x32\x9b\x5c\x9f\x8f\xa6\x0e\x6f\x4e\xdd\xef\x81\x1d\x79\x61\xe8\xbb\x9a\xf6\xaf\xc1\x9e\x38\x94\x27\xe4\x90\xda\x70\xb6\x0e\xb1\x25\x1b\x7f\xd7\x01\x4b\xab\x45\x45\xa9\x67\x4f\x18\xc5\x5b\x3a\x2a\xcc\xd7\xb8\x10\x00\xcf\x0f\x70\xba\x98\xe2\xb3\x87\x04\x57\xde\x1f\xde\xfa\xfc\x19\xc7\xc8\x46\xcb\xe4\x74\xf8\xb5\x21\x03\x57\xe5\x6f\xe3\xf6\xda\xa7\x82\x22\xb2\xcb\xb2\x22\x43\xd6\x80\x6f\x88\xc5\x6f\xbe\xe5\x42\xad\x4a\xe6\x64\x86\x97\x3b\x27\x4b\xcd\x92\xe0\x5f\x5f\xf6\xfa\x9e\x68\xa1\x76\xea\x2b\xdb\xf3\x93\x17\x0c\x0c\x81\x64\xc0\x81\x03\xb6\xe4\xc8\xde\x8d\x8a\x8b\x20\x27\x01\x7f\x97\xac\x9c\x87\x92\x86\x56\x94\xaf\xe1\xb8\x6d\xac\x19\xb3\x0e\xaa\x49\x2e\x5e\xc5\xcb\x85\x09\xc1\xbc\x1e\x38\xdf\xf0\x42\x9f\xe3\xaf\x73\x7f\xad\x66\x89\x47\x30\xd8\xfe\x38\xe3\xd5\xbc\x1a\xb2\x2a\xca\xae\x20\xbc\x99\x14\xea\xa9\x90\xad\x11\x54\xd2\x95\x84\xa3\x63\xbe\x1b\xb3\x36\x88\x73\x7e\xf8\x07\xa0\xee\x02\x4a\x69\x6d\xb0\x17\x16\xe9\xb1\x16\xa4\x78\x59\x7e\xad\xea\x56\xd3\x29\x89\x49\xba\xb7\xc6\x9b\x15\xaf\xc0\x2b\x08\xd4\xe1\x1e\x68\x17\xfc\xf3\x81\xca\xce\x9c\xc5\x3b\x5d\xf5\x9e\x45\x9e\xc4\xd0\x1c\x42\x01\x41\xd0\x90\x05\x51\x99\x89\x6c\x22\x94\x55\xd5\xda\x7f\x86\xf0\xb5\x2c\xde\x43\xec\x29\xfe\x10\xe4\x27\x66\x9b\x43\x7b\xdc\x4b\x44\x86\x5d\xda\x70\x23\x28\x1c\x05\x5e\xf1\xce\xdf\x1e\x15\xba\xe5\x79\xf7\x0e\x73\x3d\xbc\x99\x18\x3d\x55\xb9\xdc\x6a\x6f\x16\x6e\xfe\x10\xf0\x6c\x56\x65\x14\xf6\x75\xc9\xf8\x69\x4a\x2b\x24\xcf\xda\x64\xc5\x55\xdd\x23\xba\x3b\xf5\xb6\x05\x4f\xeb\xed\x9c\x0a\x09\x3f\x39\xaf\x32\x9c\x0b\x95\x3c\xd7\x3b\xb2\x71\x3e\x6f\x09\x54\xaf\x72\xa4\x1e\x78\x26\xd6\x0a\x5b\xb5\xbb\x27\x2d\xd2\x78\xa6\x70\xa8\x30\x6a\xa7\x5b\xf0\x3b\x33\x0e\x9c\x49\x77\xe9\x8a\x0e\xbc\xb5\x80\x36\x4e\x3f\x3b\x9b\xb1\x3c\x6d\x27\x2a\x8c\x78\x44\xd7\xfd\x3f\x24\x41\xe0\xca\x82\xf1\x1a\x38\x0f\x89\x66\x22\x22\x30\xc6\xef\xbb\xca\x5a\x49\xf9\x3b\x8c\xa3\x20\x5f\xdf\xa2\x55\x12\x63\x47\x6b\xa8\x22\xc9\x0c\x06\x23\x98\x2b\x0b\x51\x45\x09\xfa\xa0\x70\x0f\x9b\x58\x64\x0b\x7c\xc4\xad\xcc\xa7\xc6\x21\x78\x33\xa3\x66\x32\xf6\xf9\x5b\xd0\xf4\x46\x83\x87\xd7\xc9\x4b\xe0\x11\xc1\x6f\x61\x00\x9d\xe6\x0c\xad\x4b\x7e\xb6\xdb\xb7\x52\xa9\x36\x09\xdc\x59\xc3\x63\x6a\xfc\xd3\x3c\x84\x97\x4c\x5d\xe8\x17\x83\x25\xa1\xd2\x11\xd2\x54\x53\xcb\xb6\x52\xe7\x4f\x8d\x9e\x57\xc3\xb6\x62\x63\xbb\xc2\xa3\xc7\x65\xd0\x50\x84\x7d\x8e\x53\x0c\x02\x16\xbd\xae\xbc\x10\x5c\x16\xf5\xdc\x0a\x1e\xde\xe1\xfb\x54\x84\x1f\xdd\xf6\xd1\x75\xe1\xa4\x20\x68\xc1\x8c\xb9\xd0\xab\x6b\xa6\xbb\x2e\x78\x08\x06\xfb\x7f\x7b\x07\xc8\xe8\x08\xdf\x13\x7a\x5a\x09\x4a\x0e\x54\x6f\x8c\x3b\xc7\x38\xe6\xcd\x48\xcb\x10\xaf\x89\x0e\x80\xcb\x50\x1f\x5e\x45\x73\x54\x0a\x12\x27\x4b\x9c\x40\xc1\xe4\x06\xee\xcf\x04\xf7\x0c\x0a\x84\x74\xf6\x81\x42\xf3\x25\x46\x6a\xe4\x64\x43\xd3\x7f\x83\xd7\xd7\xaa\x06\x16\x0d\x6f\xb1\x1d\xa3\xae\x86\x40\x58\x56\x2b\xae\x17\xe3\xea\xb0\x7a\x2e\x05\x93\x07\x54\xad\x14\x04\xf3\x22\x21\x22\xa6\xc6\x1b\x8d\xd4\xc3\x42\xc3\x9e\xb2\xe0\x02\xba\xcc\x46\xf3\x8b\x2e\x7e\x8b\x5f\x87\x1c\x99\x61\x63\xa8\x61\x0b\x1b\x3b\xa1\xd8\x00\x0d\x10\xf4\x3b\x25\x23\x09\x4f\x36\x90\x4c\x9b\xf7\x3d\x42\x0d\x1e\x64\x58\x98\x99\xe1\x6f\xda\xc0\x0a\x08\xf4\xdf\xa1\xbc\x73\xea\xef\xe5\x4c\x9e\x21\x2e\x88\x41\x32\x9d\x52\xf7\x20\x0f\x20\x9b\x34\x0a\xa3\x19\xa9\x98\x82\x3a\x1d\x67\xb5\x5f\x8d\x2a\x5b\x74\x04\x97\x88\xf4\x53\x2a\x5d\x8e\xbf\x36\x15\xec\x2c\x81\x1b\x4f\x39\xbb\x33\x03\xa6\xa4\xe3\xb6\xdf\x35\xfe\xb7\xd8\x96\x23\x5e\xa1\x9e\x6c\x83\x1b\xe9\x81\x6d\xbc\x17\x04\x93\x5b\xca\x65\xa2\x85\xd0\x9f\xbe\xa8\x05\x57\xa8\x0a\x07\x3d\xe8\x36\x38\x75\xc7\x50\xbc\x1b\xdd\xa4\xe4\x5f\x97\xe7\x0d\xd9\xc7\x4d\xee\xd4\x70\x82\x22\x07\x4b\x8e\x7d\x71\x14\x9d\xdc\x66\x19\x6e\x8e\x56\x7d\x14\x5b\xe0\x5b\xa0\x21\x71\xa8\x65\x8b\xae\xa3\x2a\x60\x67\x20\x69\x66\xcd\xf2\xa0\x7c\x16\x54\xec\x11\xdb\x2f\x5c\x0b\x77\x84\x47\x33\xeb\x09\x95\xb9\x7a\x43\xea\x55\x6c\x72\x8e\xb9\xb3\xe2\xba\xce\xcd\x13\x51\x48\xe4\x24\x71\xfe\x7d\x72\x60\x96\x93\xfa\x6f\x67\x1e\xaa\xd5\x9a\x67\xc9\x4f\x33\xcb\x19\x3d\xe9\xaa\xc4\xfa\xba\x2b\xe5\x7f\x1b\xbc\x1b\xdc\xf9\x1e\xf6\xc6\xbb\x81\xdf\x7b\x00\x04\xdf\x4e\x9f\x62\x01\xdc\xf3\x2d\x70\xa9\x67\x5b\x72\xef\x3a\xa6\xf4\x8f\x83\xbd\xaf\xeb\xec\x96\xf0\x7e\x44\x66\x1a\x2c\xb0\x15\x21\xb3\x3e\xa1\x11\xa9\x4b\x06\x9a\xa3\x9a\x39\x59\x52\x32\xba\xf0\x76\xf1\x72\xf9\x44\x33\xef\xc4\x27\xfa\x0a\xc3\xf8\x99\x0f\x4b\xb6\x67\xd5\x82\x3f\x68\x3f\xcb\x72\x5f\xfa\xd4\xf8\x4b\x26\x0c\x60\x74\xcd\xa1\xf1\x9f\x9e\x89\xa8\xce\xed\x79\x37\x85\xd4\x26\x2e\x9f\x3e\xfd\x74\xf5\x01\xf4\x75\xe7\x34\x98\xdf\x9b\xcd\x14\x47\xb7\x0a\xb9\xee\xdd\x3a\xe8\x5e\x16\x4d\x8a\x70\x76\x84\xef\x77\xda\xb4\xdc\x59\x7a\x7e\x1c\xda\x87\xd5\xb1\xf7\x4d\xd9\xaa\xe5\x21\xc1\x52\x57\x9b\x64\xc5\x3b\xb3\x23\xf4\xdf\x09\x5e\x83\x7a\x1c\xd7\xca\x88\x83\xb4\xf0\xc5\x06\x51\x15\xa9\xdb\x0c\x74\x5c\xa3\x57\x79\x02\xbb\x5c\x14\x4f\x4a\x17\x31\x34\xbe\xc7\x3a\x35\xd2\x5c\xb2\xfe\x0c\xf0\x97\x53\x58\x54\x85\xb7\xdd\x20\xdd\x93\x12\x1c\x9a\xf9\x67\xe7\x76\xb7\x1e\x56\x39\x8f\x55\x6b\x58\x2c\x6d\xb6\x69\x4d\xb2\x5c\xea\xe8\xb6\xfe\x0f\xc6\xee\x28\x6e\x8e\x9e\x3e\x45\x9d\x49\x0f\xa1\x20\x61\xbb\xb7\xef\x49\xe7\x69\x85\x5f\x14\x1f\x93\xbd\x2c\x83\x98\xda\xe2\xc7\xea\x1f\x28\xf7\x0d\x15\x3b\x2e\x73\x9e\x29\xb0\x3d\x35\x9e\x41\x9e\x49\x9e\xe9\x28\xdc\xcb\x77\x58\xa1\x67\xa7\x7d\x34\x59\x93\x94\xb1\x91\x44\x70\xc4\x34\x97\xac\x7b\x1a\xea\x6a\x71\x28\x51\x0a\xcc\xb7\x5a\x4a\xb2\x55\x8d\x5a\x66\xb1\x4b\xb1\xf5\x2a\xc5\x78\x00\x43\x7e\x70\x22\xd2\x12\x32\xaf\xac\x72\x83\x23\xeb\x24\x21\x0e\x8c\x4a\x1e\x86\x1d\xe4\x7a\x5a\x05\x59\xd1\x2e\x0e\xa0\x5e\x7c\x12\x68\xd0\xfd\x7d\xa0\x9d\xc8\x7a\x8e\xc0\x1b\xb2\x58\x61\xe3\x8e\x15\x49\xa7\x8b\xa8\x45\xaa\x58\x67\xd0\x74\x5e\x34\xab\x52\x7b\xfe\xb3\x66\x14\x1a\x8a\x4c\xc9\x11\x79\xd3\x7f\x70\x08\xd1\xe1\x9a\x9a\xc9\x06\x00\x31\xde\xa8\x7c\xb0\x4f\x07\x0d\xde\x14\x32\xdb\xe0\x35\xde\x22\x0c\x0c\xf2\x74\xc9\x55\xe3\x92\x41\xe9\xde\x97\xf2\x95\x40\xf6\xff\x11\x75\xfb\x1b\x52\xe4\xa1\xfd\x50\x1a\x04\x4e\xb6\x58\xc6\x31\xa2\x5a\x4e\x06\x81\xfe\xff\x2f\xa8\xdc\xa8\xbf\x78\xa6\xf6\xfd\xaa\x95\x49\x51\xaf\xc3\x97\x07\x06\x96\xc3\x5f\x03\x04\x8e\x79\x36\x90\x45\x4b\xf8\xaa\xa1\xa5\x20\x2f\xbc\xba\xa1\x11\xb5\xf7\xc7\x20\x63\x75\x44\x96\x6f\xbf\xba\x80\x37\xd5\xa4\xaf\x09\xd0\xfc\x07\xd6\x1d\xdb\x7c\x32\xfc\xd0\x56\xe6\xfc\x43\xe5\x0b\xce\x66\x2b\x48\x8c\xbd\x0a\xb5\x3a\x60\xbe\x77\x9f\xf9\x01\x69\xf2\xc4\x79\xdb\xff\x7e\x77\x6b\xb8\xe5\x93\xd6\x74\x40\xcb\x34\x4f\x45\x5d\x2c\xfb\x3c\xbb\xfa\xff\xc9\xcd\xa6\x3f\x0f\x73\xe6\x12\xa1\x62\x18\x31\x2d\xab\x84\x0d\xf2\x4a\xbf\x92\xdf\xc3\x41\x9c\xb4\xa7\xa8\x8c\xd2\xf1\xfe\x41\x32\xe0\xd2\x2d\x3d\x86\xc9\x74\xed\xec\xb9\x99\x43\xc2\xc3\xb5\xcc\x8d\xe0\x7f\x3a\xf0\xc0\x0f\x0a\xe9\x9d\x42\x61\xb3\x3b\x05\xf5\x57\x17\xe9\x92\x43\x45\xa2\xce\x9e\x16\x72\xff\xe5\x7b\xe7\x60\xc9\x26\x89\xc4\x2c\x1f\x27\xf4\xdb\x74\xff\xdd\xec\x15\x8e\x8a\x5b\x38\xc1\x17\x71\xe1\x89\x75\xee\xf8\x0a\x2d\x28\xc7\x4a\xec\x5d\xbb\x98\x34\x0d\xa8\xda\xf3\x99\xb2\xeb\xca\xb9\x35\xab\xe7\xf0\x61\x79\xfc\xb7\x0a\x68\x68\xfa\x59\xb1\xfd\x99\xb8\x2e\xef\xfe\xcb\x34\x9d\x07\x6a\x26\xb0\xb6\x1a\x93\x34\xdf\xf2\x82\xb6\x61\xf6\x1c\xa2\xf6\x0b\x83\x71\xcb\x27\x28\x9a\x0b\x85\x35\xe0\x97\x15\x13\x1d\x84\xf2\xb8\x14\x73\x1a\x8a\x58\xc3\x47\xf4\x6a\x57\x42\x99\xec\x86\xde\x7e\xad\x92\x85\xc9\x63\x6d\x08\xdb\xb6\x18\x8c\x2f\xfd\x99\x2e\x01\x36\x1d\xca\x61\xff\x5f\x1b\x41\x35\xbc\xfd\xfb\x2b\x3d\x64\xbc\xdc\xe3\x0c\x3e\xc4\xb9\x5f\x2e\x19\xee\xaa\x68\xcf\xcf\xc8\xe8\x38\x74\x42\xe1\x73\xb8\xe8\x30\xc4\x0f\x48\x4a\xc6\x1f\x8a\x6c\x9c\xe1\xa1\x6c\x5b\x55\x48\x34\xf6\x76\x2e\x09\xbb\xca\x3e\x5d\xc6\x28\x0a\x6b\x8c\x39\x2e\xa0\x20\x55\x94\x41\x3a\x2c\x41\x2d\x15\xac\xbf\xc6\x77\xe6\x85\x79\xca\xb0\x90\xd2\x89\xcb\xf1\x56\xe0\x6a\x56\x55\x0c\x9c\x5e\xbe\x98\x81\x7d\xb0\x7c\x77\x7f\x54\x48\xc1\xd3\x98\x2c\x1f\x03\x41\x71\xc8\x30\x3b\x2c\xf3\x5a\x44\x2a\xae\xdc\x23\x7b\x9f\xbc\xad\x6c\xcc\x48\x37\xe0\xd5\x62\x1e\x52\x58\xef\x30\x43\x81\xc7\x64\xcd\x75\x42\xd1\xa2\xf5\x35\xd2\x64\xa8\x3d\xcd\x56\xb0\x5c\x54\x3d\x9b\x51\x33\x00\x13\x8b\x37\x6f\x0b\xed\x71\x13\x41\xcc\x90\x41\xfb\x8c\xeb\x4f\xfc\xfc\x06\x6c\xee\xdc\xbf\xa2\x9f\xe7\x21\xfb\xad\x7b\x5f\x75\x44\x0c\x47\x5f\x93\xad\xce\x72\x6b\xf6\xaf\xdf\x98\x54\x94\x5e\x98\x90\xa2\x7d\x57\xd0\x6f\x29\x18\x2e\x38\x1a\x98\x98\xac\xa5\x7c\x67\x57\x0f\x50\x95\x43\x65\xee\x4a\x9f\xbd\xf6\x9c\x78\xee\x36\x4e\xb2\xd3\xfe\xff\x07\xdf\x1f\x28\xc3\x7e\x76\x07\xfc\x5f\x99\x3b\xa2\xce\x9e\x0e\xaa\xfe\xe0\x53\x3f\x08\x8b\x99\x8b\x57\x23\x18\x4d\xfc\xcb\xbf\xdf\xd7\x5e\x8a\xdb\x7f\x53\xe9\xc8\x16\xa1\xcf\x6d\x47\xff\x0d\x1b\xce\xb8\x4a\x7f\x9f\xed\x51\x35\x30\x07\x06\x20\xe5\x99\x69\xba\x3c\xa5\x26\x2b\xae\xc8\x3b\x17\x1e\x85\xf1\x56\x3d\xf4\x4b\xae\x72\x55\x84\xbc\x0a\x9c\x1f\x65\x0f\x93\xb6\x83\xa0\xe6\xc4\x23\xf6\x02\xa7\x2c\xcb\x10\x74\xac\x9e\x46\xa4\x6a\xc3\xab\xaa\xc2\xce\x93\x1a\x98\x55\xb2\x04\xc9\x7c\x4e\x27\x75\x4c\xa4\xe2\xc3\x1c\xa1\xd1\x78\xa5\x87\x26\x8a\x29\x0a\xa9\x36\x77\x72\x72\x6f\x47\xe6\xa0\x34\x01\x17\x0d\xb1\xbe\xde\x4c\xdb\x52\xb7\xba\x09\x67\x6e\x94\x88\x5a\x61\x9f\xa3\xb9\xc0\x94\x23\x74\x2b\x15\x32\xe4\x3e\x69\x66\x21\x08\x7f\x12\xcf\xa5\xbd\x1c\x11\x29\xc7\xbe\xf9\x3e\x30\x24\x26\xdb\xcb\x04\x71\xa4\xc0\xbc\xd8\xed\x71\x4a\x59\x5c\x92\xa7\xda\x49\x02\xd6\x53\x28\xa5\xcb\xa4\x37\xb8\x5e\x1c\x2b\x0f\xad\x27\xd5\xc0\xd6\x19\x83\xc4\x77\x94\xd9\x9a\xea\x7a\x65\x0c\x02\x8d\x21\xf8\x65\x95\x86\x2d\xcb\xe1\xcf\xdd\x99\x7b\x98\x85\x61\xba\x05\x8e\x77\x1c\x03\xcf\x84\xc4\xfc\x18\x20\xa4\xed\xbd\x4b\x1c\x22\xab\x4a\x64\x0d\xc1\xe6\x1d\x4c\x79\x22\x46\x89\xcd\xd5\xbb\x0f\xe3\x50\x8c\x00\x1c\x6e\x88\x29\x0f\x87\xd0\xb6\xf3\xdc\xf5\x0c\x77\x97\x2d\x59\x55\xb8\xff\x36\x4c\xfa\x38\x22\xb8\x21\xd1\xa1\xff\x19\xde\x7c\xce\x46\x15\xfc\x6a\x3d\x63\xf4\xe8\xc8\xa0\xec\xc0\x80\xec\xe0\x81\x45\x9d\xed\xf6\xc8\xce\x52\xfa\xd0\xc3\x7a\x21\xf9\x3c\xab\x6e\x55\x17\x3c\xa4\x51\x63\xaa\xe6\x8c\xe7\xf0\xda\xf0\xf7\xf7\x6f\x2b\xf1\xfc\x2d\x60\x28\x7c\xc9\x8d\x20\x87\xc8\xee\xa1\x4f\x2c\xf0\x8a\x74\x1c\x0b\x16\x63\x52\xd2\x87\x13\x9f\xd3\x86\xae\x9e\x05\x8a\x2f\x6a\xe4\x6e\xed\x40\x3c\x97\x51\xa0\x67\xd8\x1a\x9b\x18\xab\xf9\xf7\x34\xf4\xfc\x36\x9f\xa1\x9f\x57\x3d\x5a\x8d\xda\x92\x92\x39\x99\xae\x9d\x34\x63\x4b\xa8\xb6\xd6\x26\x7b\x9e\xdb\xde\x7d\xee\x38\x23\x5a\xf3\x58\xf3\x1e\xed\x57\x55\x17\x55\x2b\xe9\xfc\x51\x47\xce\xd1\xf9\x51\xf3\xdc\xc6\xdf\xe4\x33\x2c\xe4\xeb\x2f\xe0\x25\x8a\x45\x6f\x9c\xa3\x02\x8e\xdf\xc3\xde\x87\x0e\x14\xd5\xbc\xe8\x0e\xe7\xf4\x95\x64\xcd\x37\x7a\x7d\x04\x0d\x23\x1d\x4f\xb7\x74\x7b\x79\x44\x22\x33\xe1\xac\x0b\xbb\xc2\xf4\x4b\x9e\xce\x64\xae\x95\xf0\x20\x7b\x43\x75\x37\xfd\x90\x27\xd2\x0d\x1a\x43\x29\x6e\x84\x30\x7b\x1e\xcf\x34\xac\x6b\xa6\xad\x90\x28\x7c\x09\x75\x28\x35\xfd\x95\x75\x29\x22\xeb\x7c\xb6\x14\x56\x20\xfe\x94\x57\x72\x14\x9e\x9c\xf0\x65\xae\x14\xf1\x6e\xdd\x7f\x6e\x93\xde\xeb\x58\x57\x84\x4f\x1e\xa4\x7b\x8f\x84\x92\x42\x75\x99\x57\x55\x87\x06\x1f\xa9\x92\x2c\x32\x4c\x21\x8d\x28\x8b\x4b\x7d\xb8\xa2\xe4\x8a\xf6\x3d\xef\xf3\xa3\x86\x09\xb2\x5b\xff\x4d\x50\x29\xe2\x73\x32\xf1\xdb\x6c\xa2\x36\x25\xe0\x18\x6a\x0d\x23\x5c\x4a\x7f\x67\x31\x61\x5e\x1c\x39\x51\xec\x1a\x1f\x1e\x17\x2e\x99\xfd\xd8\x46\xce\x2f\x0a\xf6\x0a\x79\x7c\x78\xa4\xe4\xf8\x26\x8e\x3e\x7a\xd4\x7c\x25\x25\x4e\xa9\x88\x7b\x90\x06\x39\xb4\xb5\x63\xd7\x89\x53\x27\x49\xe6\x23\xe6\xfa\xc0\xdc\xb3\x26\x91\x51\x46\xbe\xe5\x8c\x6e\xb6\xe0\xb9\x95\x92\x12\x19\xa1\x0c\x21\x1a\x4a\xc6\x84\x65\x03\x99\x65\x91\x6f\x1c\x7d\x2c\xdd\xd0\x58\xd6\x4d\x30\x63\xec\x7f\x02\x73\x39\x5d\xe9\x98\xc3\x65\x03\x30\x38\x75\xf8\x78\xac\xe4\xe3\xc1\xde\xbe\xfd\x42\xe4\xa6\x82\xc0\xe2\x40\x68\x7e\x54\x24\xc5\x25\x0a\x3f\xee\xcf\x2d\x26\xec\xb9\x3d\xa5\xdd\xc4\x45\x73\x9b\x02\xa6\x6e\xcf\xa8\xdb\xec\x66\x27\x24\x82\xf6\xd0\x84\x60\x39\xe5\xcf\x77\xa7\xa3\xdf\xe5\xfb\x76\xc8\x92\x9c\xdf\x96\xd3\xd2\xe2\x24\x73\x4e\x79\xb1\x37\x7a\xd4\xaf\xe9\x33\x2e\xc9\x89\x41\xbb\x3e\x85\xf2\x63\xbe\x9f\xf2\xb1\x2c\x76\x99\xfc\x41\xe8\xe2\xc5\x3f\x70\x2d\x3f\xda\xf5\x23\xfe\x47\xce\x76\xcb\xa7\xa6\x68\x6d\x2c\xdd\x14\x51\x76\x96\xa6\x47\xa2\x3d\x4b\xd4\xbe\x09\x86\xff\x6e\xbc\x6b\x40\x70\x2a\x83\x3b\x72\xf4\xde\x51\xfb\xfc\xb3\x77\x9c\x5a\xba\x2a\xda\x93\xf8\xc7\xa4\xcd\xe6\xf4\x20\xfa\x33\xce\xbd\x93\xd5\xa5\x77\x52\xf2\x01\x2d\x85\x60\x51\x7a\x5c\xef\xd3\xa7\x8d\x76\xe9\x00\x81\x63\xf4\x8f\x3c\x80\x73\x08\x00\x89\xb8\xd0\x2a\x29\x7f\xe2\xc6\xdf\x25\x6d\xe7\xbf\x67\x4e\xdc\xa6\xee\xba\xad\x49\x79\xb2\x7e\x23\xe7\xe5\x2b\x55\x60\xee\xb7\xb9\x7e\x82\x55\x8f\xce\xed\xf2\xaf\xe7\x8d\xab\x6c\x27\xe3\x7f\x2d\x07\x71\x12\xf4\x27\x12\x89\x84\xd6\xa3\xa2\xd5\x01\x8f\xdb\x68\x26\xc9\x9a\x02\x2c\xd8\x42\xbf\x4c\x13\xa4\x07\xc0\x3c\xaf\x67\xe4\x4d\x49\x4d\x7f\x09\x00\xd9\xa7\x00\xe5\xfb\x8e\x12\x18\x08\xe1\xce\xc2\x40\x6e\x66\xe0\x00\x86\x5c\xa0\xf8\x7d\xc1\xb4\x64\x1e\x1c\x6f\x98\xc2\x87\x89\x8c\xed\x8c\x5b\x17\x36\x5b\xae\x42\x24\xac\xba\x39\x2d\xb7\x9e\x52\x5d\xd5\x82\x93\xe2\x06\x06\x54\xcd\x7d\xed\x75\x12\x41\x24\x9b\x2b\xc1\x65\xd2\xa2\x14\x34\xc6\x6b\x00\xfa\xbb\x8e\x76\x27\xef\xea\xe9\xfc\x9f\x96\x5e\x4b\x08\xce\xec\xd2\xca\x1c\x18\x36\x0d\x61\x3b\x38\x64\x2d\x78\x2b\xb5\xd5\xe1\x4a\x07\x5f\x86\x75\x15\x5f\x32\x0c\xce\xa2\x47\xaf\x01\x07\xca\x72\x03\x65\x3d\x1d\x9d\x3f\xc0\xdc\xfb\xdb\x28\xb6\xfd\xfd\x03\x81\x8a\x13\x77\x87\x94\x1b\x2f\x2f\x94\x28\xc7\x02\x5f\x60\xbd\x35\xfa\x77\xce\x2f\x9e\x2f\x2b\x3a\x58\x7d\xb7\x5a\xfc\x58\xd6\xc2\x2e\x72\x75\xc8\x90\x51\x96\x80\x97\x81\x57\x26\xed\x03\xdc\x65\x55\x73\x3f\x7f\x81\x7a\xf0\x7f\x4e\x83\xd2\x7c\x6a\x6a\x04\x1a\x5f\xc8\x4d\x77\x33\x31\x87\xe4\xc7\x11\x1f\x0f\x23\x71\x16\x4a\x5b\x75\xff\x57\x46\xf0\x78\xf9\xd4\x8e\xb0\x7d\x08\x07\xda\x79\x7d\x4d\x85\x72\xbd\x2e\x29\x72\xe8\xbe\x31\x2b\x89\x1b\xb5\x17\x29\x09\xf3\xa5\x51\x6e\xb5\x22\x7c\x44\x1f\xc2\x55\x17\x29\x5e\x38\x73\x36\xdc\xfe\xed\x0c\xfd\x63\xab\xc4\x23\xfb\x92\x0f\xa8\x41\xec\x3b\x7d\x97\x2f\x0b\xdf\x0a\xa3\xc2\x09\xcf\x1b\xb9\xd2\x3f\xef\x1b\xd6\x4b\x7f\xe4\xf0\x80\xce\xb8\xc4\xbb\xec\x47\x9f\x9f\xfa\x4d\x67\xdd\x69\xbd\xa0\x0f\x39\x5e\x23\x30\xf3\xcf\x3b\xd8\x8e\x97\x12\x4a\x62\x18\x8b\x8f\xea\x98\x99\xd8\xda\xf6\x23\xb2\x3c\x9f\xe8\xeb\x4d\xeb\x7a\x7d\x1e\x74\x75\x6d\xfe\xb8\x6b\xfb\x8e\x70\x87\x96\x61\x53\x16\xac\x98\xae\x9e\xd3\x16\x20\x32\xf3\x70\x18\x2e\x41\x5e\x53\x31\x9e\x5f\x2e\x77\x47\x1f\x61\x6f\x25\x37\xae\x2c\x53\x55\x57\xa9\x94\xd5\x95\x0a\x37\xe7\x6d\x64\xb4\x25\x45\xf6\x3d\x2c\xdb\x50\x85\xde\xea\xa9\x5b\xd2\xb0\xd3\xe5\x8a\x9a\xaa\xf5\xed\x6c\x8a\xed\xe7\xf1\x4b\x90\x3d\x33\xba\x3e\x68\x3a\x70\x5a\x37\x7f\xd7\x9f\x1f\xbb\x67\x7e\xff\xde\x23\xef\x8a\xd4\x3b\x1c\x78\x44\xaf\x74\xdb\xdf\x4f\xbb\xa6\xfe\x7c\xd9\xde\x74\xd2\xba\x7d\xd4\xd5\x26\x59\x39\xfd\xe7\xe7\x14\xba\xc6\xae\x70\x62\x75\x55\x5b\x5d\x90\x89\xf1\x98\x54\xba\xa2\xd8\xce\xb9\x23\xc2\xe1\xaa\x55\xd6\x46\x6f\x7f\x7e\xf9\x16\x79\xce\xd5\xa5\xaa\xa5\x6a\xd8\xcc\x60\x61\xee\xb2\xea\xe5\x85\xcb\x7e\xaa\x2e\x3b\x15\x26\x5c\x55\x42\xc1\x44\xae\xc8\x08\x19\xbd\x93\x3c\xe1\xa2\x12\xf0\x03\x6a\xc0\x9a\xc1\x35\x79\xa4\xd1\x83\x6f\xe5\x29\x5d\xba\x8d\xef\xb1\x2c\xbd\x84\xb6\x2b\xe8\x5d\xc7\x2a\xd1\x44\x8c\xac\x38\x39\xbb\xc5\xbc\xe2\x9a\xf6\x15\xa6\xa0\x6d\x53\x8a\xdd\x54\xa5\x49\xcc\xf6\x39\xe2\xba\xb9\x03\xe3\xec\xdb\x22\xaa\xfe\xad\xc4\x5f\x4b\x4b\x67\x68\xc5\xf0\x26\xc3\x5c\x5e\x61\x3d\xa4\x0b\x12\x58\x86\xa7\x1e\x10\xc6\xfd\x28\x89\x1c\x75\x60\xee\xb3\x1d\xa5\x6d\x67\x4f\x1b\x2c\x8b\xd3\x89\x86\x02\x68\x7d\x81\xfb\x92\xde\x79\xa8\x06\x24\x99\x03\xdb\x92\x12\xa4\x24\x0c\xdf\x45\xc6\xfb\x5b\xd3\xe9\x62\x92\xc7\xe6\x0c\xb3\x5c\x1d\xda\x8a\xc8\x78\x6c\x7e\x5b\xc5\xf0\xbe\x00\xd1\xd3\x6c\x3a\xb2\x0e\xe9\x88\xbc\xf6\x2c\xb5\x12\xb3\xdd\xcd\x67\x03\x9f\x5c\x6a\x81\x1b\x11\xad\x67\x59\x13\xea\x09\x8e\x88\x27\x07\xb4\x1c\xe5\x26\x66\x29\xe1\x8b\x47\x4c\x7c\x9f\xc6\xad\x2a\xe1\x87\x1c\x51\xdb\xdc\x70\x72\xa5\xa3\x83\x7e\xee\x1a\x3b\xce\x5a\xf1\xb4\x92\x7f\xc3\x49\x5d\xac\xdd\x0d\x21\x3c\xf9\x61\x50\x7f\x42\xb7\x49\xee\xf3\x0e\x62\xb8\x43\x55\x78\xd0\x8f\x1c\x0e\xf6\xfd\x45\x67\xff\xc6\x43\x7f\xff\x28\xa6\x3c\x15\x7f\x67\xb7\x64\xef\xdb\xd7\xd0\xa0\x72\x4d\x7b\x4c\x57\xd2\xae\x47\x07\x68\x12\x37\xfc\x39\xb3\x57\xf7\x46\xc9\x9c\x2c\x73\x52\x06\x85\xcb\xdf\x95\x7a\x48\x37\xd2\x7a\xcf\x99\xcc\x46\x72\x63\x48\x4b\xfc\xff\xf8\x1a\xdf\x6f\x19\x53\xae\xe1\xe3\x46\x61\x30\x19\xc3\x16\xad\x7a\xb2\x81\x95\x68\xc7\x43\xaa\x1c\xce\xd7\x3a\x2b\x06\x2f\xa1\x9d\xaf\xd5\xd2\xad\xfd\x5b\x2d\x57\x98\xc0\x20\x70\x02\x94\x04\xc0\xd0\x33\x14\x76\xe8\xed\x5c\x75\x71\xc7\x47\x47\x2b\xd4\x9b\x44\x58\x29\xdd\xe0\x9e\x03\x27\xd6\x06\xe3\xb7\x26\x4d\xeb\x75\x19\xc6\x97\xd3\xc3\x9b\x7e\x45\xad\xbc\xde\x88\x8c\x57\x7f\x17\x70\xa7\xf6\xdb\x35\x02\x4a\xd9\x70\x47\xd5\xa0\xd3\xd2\xf4\xb4\x30\xcc\xea\x8c\x5f\xd5\xd4\x8d\xaa\x8e\x00\xdf\x71\x57\xff\xc4\x98\x94\x98\x0a\x7f\x5d\x35\x98\x78\x0c\x92\x00\xc9\xf6\xa0\x9e\x16\xe0\xf9\x31\xcb\x79\x75\xd2\x26\xe6\xa7\x0e\xaf\x38\x48\xc8\x8f\x27\x13\x9f\xfe\x3b\xa4\xd2\x40\xbb\x3c\x51\xee\x76\xf5\x38\xb9\x84\x8c\xad\xbe\x75\x56\xac\x3c\x1e\xe6\xb7\xc9\xa6\x45\x59\x29\x16\x2b\x99\xef\x74\x6e\xb9\xb1\x7c\xce\xdf\xb2\xd5\x4b\xb5\xf4\x95\x0c\xd4\x1f\xdd\xe9\xb5\xd5\x33\x2a\x89\xcb\x16\xa8\xea\x22\xdb\xfc\xb6\x02\xf6\xde\xab\x23\x23\x1b\xfa\x1e\xf0\xb8\xdb\x0d\x92\xd0\x8e\x4e\xd9\x69\x22\x4d\x43\xa3\x46\x00\x04\x40\xfb\xbf\x98\x5a\xc1\x75\x54\x08\x0a\xdd\xc1\x83\xa6\x37\xf4\xed\x10\xea\x79\x5c\x3d\xf7\xd1\x86\xbe\xd1\x91\x63\x04\x95\x0f\x58\x59\x24\x2a\xe6\x5e\xda\x49\x4e\xeb\x68\xee\x71\x1c\x05\xc1\x87\x68\xc9\x3c\x87\xb0\xec\x87\xa2\xd2\xea\x1c\x5b\xb7\x00\xe7\xad\x86\x91\xb5\x25\xc1\x89\xc5\x55\x59\xf6\xce\x41\xee\x47\xf4\x38\x9c\x6d\x1b\x5e\x8e\xd0\x73\x1f\xad\xb2\x75\x17\xd6\xc2\xb6\x93\x93\x24\x36\x09\x79\xc0\x37\x59\x56\x50\xb3\xdf\xbe\xd4\xc0\xd0\x03\x02\xf6\x74\x46\xf3\x28\x6a\x7f\x91\x3a\xa8\xaf\xc1\xda\xb8\xe7\x15\x24\x6a\x1a\x1a\xc1\xc2\xef\xa0\x85\x96\xd1\x7b\x77\x25\x70\x68\x11\xec\x42\xb6\x4c\x91\xdd\x1e\xf1\x5c\x3d\x40\x92\x22\x30\x1d\xb8\x8b\xe1\x34\x29\x55\x16\x10\xaa\x0c\x77\xf1\x04\x27\x20\xaa\x4f\xaa\x77\x1e\x34\x07\xca\xca\xf5\x23\x1f\xe2\x99\xf0\x4e\x3e\x71\xa2\xa6\xd9\x98\xec\xee\x0b\xaf\x3e\xc4\xea\x30\x53\x7c\xdb\x5f\x41\x65\x91\x67\xae\x3c\x32\xcc\x38\x10\xfd\x40\xad\x2b\xe9\xb1\x35\x94\x09\x33\xfb\x67\x4b\x70\x3a\xd6\xe9\xf0\xac\x45\x07\xea\x4c\xde\xff\x42\x76\xff\x4b\xaf\xae\x8b\x89\x6a\xfb\x3a\xe2\xbd\xee\x2a\x26\x7a\x85\x94\xdd\xe0\xa9\xfa\x30\xe2\x0e\x56\x20\x0b\x3e\x0e\xa1\xcd\x47\xb4\x58\x1d\xfe\x43\x4a\xa3\xea\x49\xf2\x4f\xb2\xf7\x45\x72\xb2\x03\xb2\xf0\xe3\x10\x13\x57\xdf\xed\xc6\x02\xed\x62\x95\x24\x9f\x57\x2b\xc2\x5e\x6a\x92\xc9\x92\xac\xfb\xfb\xf6\xf5\xcf\x96\xf6\x9e\x10\x88\x85\x36\xe0\x1d\x48\xd3\x58\x23\x31\x38\x0b\x8d\xcb\x8c\x35\x98\x91\x15\xd6\x03\x14\x97\xd4\x8b\xa2\xf4\x96\xd9\x60\xa2\xd6\xa9\x8e\x77\x47\xae\x55\x17\xca\x03\x2c\xf0\xb7\x9f\xfe\x30\x33\x09\x8f\xa0\xab\xec\xab\xf4\xda\xe7\xcc\xb5\x31\x0b\xc1\xd0\x51\x99\x26\xc8\x1e\xa2\x9c\x67\x3b\x21\x8f\xd0\x5d\x76\x9a\x58\xe6\xeb\x7e\x30\x9c\x61\xf6\xb9\x0b\xb9\x9b\xc1\xd5\x09\x8f\xf8\x5c\xbd\x4d\x81\xb8\xfc\xa1\x86\x46\x34\x43\x26\x68\xe2\x99\x20\x8d\x56\xd4\xd3\xbe\xd3\x97\x7c\x8e\xac\xae\xe6\x80\x99\x77\x39\xea\xa3\x7d\xc1\x9c\x39\x8d\x2f\xb5\xed\x48\x86\x14\x59\xbc\xb4\xa5\x9a\x31\xea\xe6\x95\xcb\x9a\xb5\x57\x05\x85\x28\xd4\x75\x32\x69\x67\x16\x6f\xd4\x7d\x39\xa8\x7e\x21\x56\x37\x1b\xd6\x3b\x9d\x3a\x48\xa9\x09\xf3\x78\xc7\x97\xd7\x13\x7e\x08\xe3\xb2\xbf\xa7\x8a\x0f\x76\x05\x57\xdc\xd8\xb2\xfb\x6a\xa1\xcb\x0d\xfb\x77\x8f\x24\x19\xe2\xc4\x6b\xca\xaa\x65\x9a\xbe\x88\x31\x5a\x5e\x9d\x57\x24\x53\xd7\x2b\xc4\xbc\xd1\x9a\x2c\xa9\x2d\xab\x33\xad\xd6\x07\x21\xec\x63\x6d\xee\x99\x68\x16\xfc\xba\x39\x95\x8e\x9b\xa1\x25\x06\x20\x51\x2a\x3b\x25\x81\x5f\x96\x0f\xee\x00\xa8\x38\x88\x46\x56\x28\xb3\xd5\xf8\x86\x9b\x73\xf8\xdf\xb7\x66\xcc\x38\x14\x64\xf5\x9b\x9d\x17\x9f\x10\x9c\xd8\xb4\x67\x6d\x35\x40\x40\x37\x56\xd6\x89\xb5\xc9\x21\x29\x91\xde\xc2\x5e\x60\xac\xd6\x23\x6d\x8c\x13\xdc\x8a\xa5\xbb\xbe\x87\x47\xb1\x6b\x82\x21\xbd\x06\xe3\x06\x79\xc3\x75\xe8\xa8\xa6\x19\xb3\xe4\xd4\x28\x2b\xcb\x71\xfe\xd1\x3a\xde\xc2\xad\xd1\x44\xdd\x89\x35\x2f\x80\xcb\x62\x8d\xb3\x77\x19\xed\x9e\xeb\xf0\xf2\x89\xf9\xd4\xc8\x62\x2b\x19\xed\x62\x0f\x16\x9f\xf8\xe1\x8e\x81\x9a\xed\xbb\xd7\x36\xce\x7d\xeb\x48\xaf\xd0\x9b\x87\x6d\x24\x9c\x9a\x74\x65\xd6\x31\x2d\x1e\xc4\x9b\x0a\xee\xfc\xb5\xbc\xbb\x08\x47\x5d\x69\xb9\xdc\x98\xf0\xa8\x99\xe0\xb9\x24\xbb\xba\x51\x3a\x6e\x1a\x70\x79\xeb\xfe\x73\x86\xc7\xa9\x89\xe9\x42\xd9\xe0\x71\x38\xf9\xa6\x7f\x48\xaf\x72\x2d\x3b\xa1\x2d\x63\xff\x4e\xbf\x2a\xef\x9a\x8d\xa5\x12\x72\xb3\x4a\x5d\x15\x63\xc4\xf2\xf3\xe8\xfd\x47\xd6\x1b\x59\xf9\xce\xed\x75\x63\x79\x55\x6b\xdb\x75\x0c\xd4\xca\x18\xbf\x44\x51\xa0\x1a\x29\x8d\x9f\x3a\x34\x5e\x9c\x9e\xad\x4b\x3c\x7c\xe7\x58\x45\x95\xde\x9a\x2e\x14\x48\x78\xa3\x72\xe4\xba\x9e\xa9\x6a\xc9\xf8\xce\x9a\xc6\xa1\xf1\x86\x05\xfb\xe3\x2d\x9b\x5d\xfd\xc9\x65\x55\x36\xa5\xff\xa3\x78\xac\x62\x6b\xae\x17\x13\xe4\x1e\xa0\x5f\x6c\x6f\x9f\x18\xd3\xe2\xb0\xaf\x75\x76\xa6\xb8\x6f\x4c\x0e\x94\x7a\x41\x2b\xd4\x24\x5e\xd2\x95\x5c\x77\xea\x02\x25\x3e\xea\x5b\xa1\x50\xa0\x8f\x47\x3c\xaa\x9a\x99\xa9\x32\x1a\x95\xd3\xe2\xf6\x8f\x3c\xbd\x55\xc7\xe4\xe5\x8e\xee\x77\xb0\x95\x9c\x98\xae\x2b\x3d\xdc\xa7\x54\xf3\x32\x62\x77\xdd\xa0\x77\x78\xb6\xbd\x9f\xf2\x0a\xc8\x61\x79\x99\x23\x47\xe5\xe5\xc1\xa8\xe7\x74\xc6\x73\x2b\xc7\x73\xaa\xe4\x8a\xca\xca\xf1\x0f\x96\x5b\xf2\xab\x55\xd1\x59\x31\x8b\xcd\x6e\x1e\x2c\xa6\x2c\x28\xa7\x34\x9c\xf7\x63\x24\xa1\x55\xcc\x53\x99\xeb\x39\x93\x91\x9d\x42\xe7\x8c\x25\xc5\x5a\xfd\x48\xab\x5c\x52\xe8\xb7\x15\xd7\xae\xf5\xc2\x19\x6d\xe8\x59\x5a\x84\x2c\x5d\xe1\x4b\x48\x92\x5b\xda\x45\xb7\x10\xc3\xbf\xc7\xe4\x2f\x6c\x3b\xdf\x66\xbd\xeb\x12\x0a\xe8\x9f\x24\x80\x36\xa8\xc2\x21\x5b\x61\x42\x85\x72\xef\xeb\xd6\x64\x07\xb7\x5a\xf5\x0c\x8c\xcc\x56\xcf\x7a\x6f\xd9\x92\x88\x04\x81\x6e\xd0\x48\xef\xa5\xf6\xa5\x1d\x4b\xb0\x56\x16\x55\x85\x25\xb6\xce\x0f\xd2\xc3\x29\x47\x92\x8e\x42\x99\x24\xbe\x45\x37\x5c\x66\xfc\x59\xd6\xb5\x54\xe4\xae\xed\xb8\xc7\x0a\xf5\x06\x4b\x67\xde\xdf\xc9\xb7\x3b\xa2\x37\x1b\xef\x20\x77\xaf\xa9\x42\x68\xfe\x29\xf9\x6b\x85\xcd\xcd\x34\xb2\x8d\x97\xff\xe9\x5c\xf3\xb3\x72\x3c\xc2\x7a\x75\xc1\xab\x74\xab\x53\xe5\x6f\xd7\xf9\x3f\x28\x18\x23\xad\x08\x22\xa4\x2a\x47\x84\x99\x0c\xb6\x1d\xba\x07\x3c\x4b\x3f\xbe\x27\x03\x3c\x69\xeb\xf3\xf8\x9c\x54\x3f\xfa\x99\x9a\xef\x5a\x6d\x0d\x6c\xcb\x15\x15\x94\xd7\xb1\xfe\x7f\x6b\xa6\xc6\xb0\x43\xd2\xeb\x64\xb5\x09\x40\xd2\x50\xb6\x4a\xea\x8b\x1a\x1e\xfa\xf5\x94\xac\x75\x55\xb9\x20\x37\x22\x43\x08\x2a\x89\x00\xa8\xa6\xc9\x6c\xce\x65\xbc\xd5\x10\x80\xf1\x41\xb5\x49\x18\xe6\x90\xe0\xc8\x11\xe5\xcc\xae\x42\x5a\x7c\x47\xd5\x7e\x10\xdb\x99\xe7\x07\xd9\xe0\x51\xb6\xbe\x02\xac\xef\x65\x63\x29\x58\x48\xa8\xdf\x23\x0f\xbb\xc0\x95\xfa\x95\x6b\x86\xba\x9e\xe9\xe6\x33\xa4\x93\x4b\x56\xc3\x20\x3d\x5b\x12\xdd\xf4\xf2\xe3\x58\xc0\x5f\xc6\xc7\xdf\x90\xe6\xfd\xef\xe9\x57\x1f\xd6\x43\x6f\xa7\x98\xff\xd8\x46\xab\x78\xb6\x23\x29\xc8\x81\x74\x38\xe6\xad\x36\xeb\x5d\x9b\xe5\x48\xaf\xce\x77\x33\x2c\x11\x6b\x79\xab\x94\xd1\xa1\x78\xad\xbc\xc2\x81\xca\x2c\x41\x86\xd7\xb7\x09\x65\xe2\xa9\xcb\x23\x86\x85\x2f\xd4\xe8\xfd\x74\xdb\x73\x75\xac\x9d\x23\xfa\x9c\xc2\x38\x89\xb3\xe7\xe6\xcb\xe1\xf9\x3b\x67\xcc\x97\x0c\x9d\xda\x5d\xc7\xfe\x1c\x5b\x87\x7f\x64\x60\x14\xc6\x6f\xb3\xae\x41\x81\x08\x6c\x88\xfb\x18\x67\x23\xb7\x20\x6f\xfd\x40\xde\x5e\x1e\xf3\xd1\x76\x49\x0e\xa3\x43\xb5\xb9\x86\x12\xe1\xcf\x17\xe0\x6b\xcf\xe3\x11\x72\x02\x88\xfc\x6b\x88\x4d\x70\x0b\x16\xd5\xd4\x80\xe1\xf3\x4b\x9d\x8d\xce\x6d\x6e\x0e\x4a\xf8\x36\xa4\xd1\xcd\x21\xc4\x09\x7b\x85\x7a\x51\x49\x56\x4e\x9e\x72\x81\x72\x45\xce\x5a\x96\xba\x70\xe4\xb5\xd2\x57\xa5\x77\x28\x5b\x79\x1a\xf9\x1d\xf9\xab\xb2\x0d\x2a\x0a\x4e\xf9\x43\xf9\x53\xc5\x0e\x83\x21\x7f\x21\x7f\xc3\xd8\xa3\x63\xd4\xee\x90\x84\xa3\xfe\xc2\xc2\x2d\x71\xad\xbd\xd0\x1e\x55\x77\x4a\xfb\x3d\x6a\x2c\xc2\x1b\xf0\x05\x9d\xd0\xd8\xeb\xbd\xd0\x6c\x00\x1e\xed\xb1\x5b\x5e\x73\x4d\xee\x1c\xe4\x75\xe7\x8b\x3b\xd7\x9b\xce\xa7\xbf\x3a\x7d\xe1\xbd\xd2\x9c\xf5\x09\xf1\x09\x71\x67\xfb\xe1\xb9\x06\xb6\xfb\xce\x17\xe2\x63\x4e\x68\x9b\xfb\x94\xfd\x54\xc2\x7f\x76\xd7\x29\x57\x9b\xe3\x64\xc2\xc9\x19\xed\x5d\xc7\x5d\xc7\x1d\x2a\x49\xd9\x1d\xc7\x1d\xc6\x12\x9c\x6e\xbe\xa4\x0f\xc1\xe5\x4d\xf3\x3a\xc5\x32\xb1\xd2\xb1\x81\x75\x78\xe4\x76\x87\x3e\xeb\x0f\xa7\xaa\x19\x8b\x46\xa1\xac\x6e\xe3\x44\x21\xea\x24\x01\x53\xab\x78\x38\x90\xa0\x3b\xad\x8a\xc4\xcf\x3b\xc5\x28\xba\x93\x00\xa5\x7e\x1b\x0d\xaa\x57\x6f\x75\xba\x5c\x18\xcb\x1d\x07\x48\x74\xda\x2a\x47\xc4\x9e\x0e\x76\xca\x3a\xaa\xd3\x5b\xe3\xbe\x4c\xd7\x72\x98\xde\x2d\xa0\xab\xa9\x79\xfc\x47\xd0\x6d\x0a\x6b\x83\x2d\x36\x4b\x17\xbf\x3d\x82\x39\x01\xd8\x44\x3e\xb9\x47\x6b\xf6\xbe\xe2\x0e\x9b\x61\x44\x18\xee\x6c\x39\xe0\x3c\x6a\xdd\x1b\x55\x98\x14\x72\xaf\x9d\x00\x37\x0b\x8c\xac\xe0\xf4\x6a\xb4\xb9\x2a\xed\x06\x4e\x6c\xa5\xbb\xc0\x14\x8f\x93\x17\x29\x38\xc1\x11\x6a\x90\x32\x94\xd0\x62\xe2\xe9\x53\xcb\xc0\x1e\x2d\x61\x8a\x9b\x73\xf3\xef\xe8\x34\x64\x20\x2c\x19\xa6\x01\x60\x04\x82\x38\x06\x01\x1b\x1e\x6a\x30\x5f\x46\x43\x2a\xb8\x12\x36\xa5\x14\xa7\x89\x2a\xbf\x5b\x24\x5f\x5c\x20\x71\x27\x3b\x18\x43\x32\x6c\x44\xd6\x49\xd2\xf9\x13\x3d\x23\xe2\x17\xf1\x3a\xde\x56\x70\x2d\x28\x5f\x9b\xe9\x48\x61\xcc\xb9\x24\xa4\x24\x3d\x77\xbf\x23\x16\x6d\x06\x43\x2a\x41\xe1\x31\x4a\x8b\x19\xd5\x50\xb9\x25\x9a\x73\xe0\x64\x2a\xa7\x3a\xd4\xe1\x25\x09\x7d\xe8\xba\xeb\xd1\x34\xaa\x41\x52\x38\xee\xbc\xc4\x05\x06\x85\x99\x93\xf8\x7a\x1f\xc3\xb8\xa7\xc1\xc7\xc0\x3d\x81\x3f\x45\x75\x2c\x71\x2d\x11\x17\xae\xb5\xd8\xa3\x81\x82\xc3\xcc\xc3\xb7\xa5\xae\xf5\x2c\x21\x96\x70\x8f\xe2\x4e\xd0\xfe\x99\x3a\xbe\x0b\xda\xc5\x90\x35\xd9\xec\xb9\x56\x80\x49\x34\xaa\x94\xa2\x86\x3f\x3e\xab\x2a\x4b\x32\x83\xcd\x14\x8b\xed\x4a\x38\x4f\x73\xfc\xd3\x1e\xbf\x8f\xb2\xf5\x50\x22\xe5\x81\x99\x13\xf3\x62\x4e\xdb\x25\xae\x0d\xbe\x16\x04\x70\xee\x06\x78\x63\xc8\xcc\x4e\x92\x26\x61\x08\x79\x8d\x7b\x7f\x4d\x8b\x6c\xc6\xaa\x07\x33\x1e\x23\x4c\x8d\x6d\x4e\xcc\x95\x26\xd5\x3e\x18\xec\xf4\xb3\x34\x77\x12\xcd\x10\xd8\xd5\x99\xde\xa8\xc3\x17\x86\x96\x18\x7c\x33\x91\xe0\xe4\x96\xda\x7d\x2b\xad\x65\xd5\xff\x7d\x87\xe8\xfe\xa6\xe1\x8d\xf8\xfa\x5f\x83\xc8\x10\xd7\x2c\xbe\x2c\x41\xcb\x4c\xe8\xe3\x75\xb4\x5b\x99\x9a\x9c\xf9\x1d\xcf\xb2\x51\x4a\x35\xda\x27\x7a\x99\x95\x0f\x9a\x40\x4e\xd4\x9d\xcf\x5a\xcc\x89\xa7\x45\x44\xce\x40\xa3\x28\x50\x56\x64\x6c\x93\xac\x5c\x38\x4e\xe9\x26\x2c\x9c\xb0\x29\x49\x5d\xb6\x64\xab\xe6\xa4\x4e\xf3\xfe\xcf\xde\x59\x16\x38\x2b\xbb\xca\x9e\xea\x5f\xbb\x06\x77\xa0\x04\xce\xfb\xec\xff\x75\xe2\xa5\x8a\xec\x38\xd7\x23\xfb\xe4\x2b\xf3\x31\x02\x64\xed\x38\x73\x36\x81\x92\x03\xf5\x9e\xc7\xac\x1b\x7d\xe5\xa3\xaf\x0c\x9f\xe2\xd1\xf4\x55\x79\x8b\xf2\x66\x63\x90\xc1\x99\xb8\x2b\xca\xd4\xfb\x21\x29\x8d\xc8\xa6\xb3\xde\x31\x9b\xb7\x15\xbe\x5b\xe7\xb2\x4e\xeb\xb0\xf4\xea\xd7\x7d\x33\xc7\xae\x49\x47\xac\xdb\x75\x5d\x8e\xdb\x78\x7e\xde\x5e\x85\xca\x94\x98\x34\x0a\x9d\x99\x9b\x71\x64\xe9\xe6\x98\x03\xb8\x5b\x1e\x3e\x94\x2c\x7b\xec\xae\x31\x23\xf1\x5e\x33\xaa\xef\x49\x44\xef\x9b\xeb\x3d\xeb\x71\x07\x24\xb1\x25\xf2\xa0\xc9\xa5\xc2\xf3\x3a\x41\x2a\x81\xde\x43\x67\x0a\x0b\x52\xc9\xc1\xc4\x40\x0c\x95\x42\x94\x86\x48\xfd\x8e\x98\x40\xe4\x21\x1e\x54\x6e\xfd\x9b\x15\xda\x77\xb6\x6c\xe2\xcd\xcb\xad\xf0\x15\xd8\x61\x08\x14\xb1\x5d\xee\xcd\xf3\xc9\xac\xb2\xc3\x11\xf4\x03\x7a\x35\x13\x9b\x0b\xb5\xd2\x18\xf1\x08\x7b\x7a\xdf\x16\xc5\xf1\x31\xd2\x04\x52\x26\x80\x8f\x6c\x9e\x5c\x57\xd1\x9f\x94\xfb\x67\x82\xf0\x98\x00\x92\x45\x49\xd9\x91\x74\x29\x87\x1e\xa2\x08\x84\x38\x90\x52\xa8\x54\x70\x2a\x03\x59\x4d\x9b\xda\x8b\x9b\x46\x66\x52\xbe\x38\x56\x97\x59\xc2\x62\x4a\x69\x72\x16\x35\x46\xc4\x8d\x09\x4e\x34\x65\xac\x67\x48\x25\xa7\x3c\x90\xd9\xbc\xa5\x0d\x84\xbc\x08\x6e\x8a\x6a\xcc\x63\x2a\x76\x84\x9d\x3c\xe1\xa7\xbc\x15\x20\x2f\xef\xab\xe3\xe2\x55\xf6\xdb\x6a\x61\x6f\x2e\x6c\x47\x05\x8b\xe5\x92\x76\x41\xb3\x76\x50\xc0\x02\xb2\xf2\x04\xd8\xa0\x84\x5a\xab\x6a\xaa\x89\xfb\xea\x39\xb7\x49\x64\x41\xe0\xe7\x76\xea\xc6\x89\x3c\x9f\x8f\x0b\x6a\x4f\xef\xeb\x33\xb5\xaf\x6a\x1a\x0f\x89\x35\xcf\x4b\x68\xf4\x69\x03\x4d\x74\x7c\xb2\x06\xa8\x07\x65\x6e\xdf\x2a\x3d\x2d\x41\x00\x42\x8a\xf3\x98\x05\x51\xf5\xf8\x95\xf0\x1e\xd7\x8d\x2e\x7c\xa7\x22\x3f\xa9\xe3\xc3\x8f\x73\xb9\xee\x9d\xd8\x5c\x5a\xde\xe5\xfb\x1b\x25\xd2\xfe\x1b\x67\x92\xf3\x74\x32\x5e\x4c\x90\x23\x3b\x4b\x9e\x30\x3e\x3b\xb2\x1f\xc3\xce\x21\x90\x93\x12\xf9\x53\x53\x49\xd5\xc7\xfc\x04\x21\x21\xaf\xd5\x07\x48\x87\x3e\xa0\x53\xd5\x14\xce\x7c\xbc\x42\xbe\xcf\xb5\xc5\xb5\x1e\x51\x4e\xaf\x08\x2c\x24\xab\x16\x2c\x4a\xef\xcb\x2c\x01\xad\x9f\x79\xf3\x61\x8e\x3e\x41\xa2\xf0\x02\xf7\x22\x54\x07\xe0\x53\xe8\x83\x4d\x9d\xcf\xd6\x0e\x4b\x96\xbe\xfe\xd1\xed\x07\x22\xc3\x49\xec\xab\x88\x9c\x2b\xa9\x3b\x3b\xa5\xd3\xbc\xe8\xa5\x5b\xef\xe9\xe1\x35\x90\xad\x2a\x5e\xe5\x9e\x31\x21\x89\xdd\x3b\x00\x6d\xc9\x2d\x2d\x3f\x77\x62\x5e\x65\x99\xa2\x43\x69\xe8\x4f\x15\x7b\xe5\x2a\x82\x9d\x03\xd9\x4e\xf8\x43\x2f\xfa\x8d\xef\x2e\x4d\x7f\xe3\x73\x27\xf8\xce\x0b\x1f\xb5\x0c\xb6\xf4\xd0\x66\x2b\x76\x9a\x53\xf8\x27\xeb\xcc\x98\x88\x0c\x81\x02\x0a\x54\xeb\x6b\x4f\xf4\x48\x8c\x4c\x96\xc4\x54\xda\x70\x52\xa4\x8f\x73\x19\x87\x23\x32\x04\x1c\x94\x59\xdf\xd6\x14\x40\xb0\x32\xbc\xe6\x81\x4e\xf7\x36\x5e\x54\x9a\xbf\x29\x75\x5b\xcc\x15\x3e\x34\x28\x6e\x23\xe3\x11\x2a\x77\x9f\xc2\xb2\x4a\x62\x9e\xd2\xdd\xff\xae\x24\xc8\xa4\x95\xd6\x46\x0f\xfa\x54\x78\x4d\x33\x04\x13\x2c\x22\x26\x0d\xf4\xdc\xb4\x79\xb6\xcf\x57\x6d\x1b\xc2\x01\x02\xc7\xc0\x81\xce\x0c\xe7\xaa\xfe\x6b\x21\x6f\xbf\x20\xaa\x84\x09\xe5\x16\xfa\x2c\x0b\x12\xcb\x92\xd2\x65\xbe\xaa\x8d\xac\x36\x99\x47\x8c\x47\x5c\x72\x5d\x55\x32\x25\xb6\xe8\x38\xcc\x57\x48\xef\x85\xe5\xb0\x0a\x43\xfd\xd9\x1c\xa2\xc4\x51\x6f\xe5\xa8\xa3\x96\x29\xb3\x9f\xc0\x2a\xe9\x5b\x7a\x62\xc3\x32\xe5\x6e\xa3\xae\xfc\xb5\xcd\xb4\xa8\x2e\x43\x4c\x3f\x9b\xdc\x67\xfa\x9f\x6c\xd3\x32\xdb\x5c\xf5\x94\x23\xa7\x2e\x57\x98\xaa\xf2\x59\x60\xe9\x1d\x1e\x57\x47\x81\xc1\x3e\x72\x38\xf4\x8e\xa6\x13\xee\x65\x31\x1b\x8a\xba\xcf\xfa\xee\x6a\xae\xc9\x42\xf3\xcd\xe3\xfd\xf3\x0d\xff\xd5\x55\x95\x98\xbf\x71\x38\xa5\x60\x7b\x1f\x6c\x5f\x64\x3c\x43\xc9\x68\x1d\x6a\xac\x68\xb0\xbb\x7c\xd1\x76\xfb\x6f\x1d\xe3\xd0\x4c\x39\xa6\xa1\xc0\xdf\xfb\x17\x67\x8a\x06\xad\xf1\xe4\x87\x84\xa8\x62\xc8\x25\xbc\x26\xb7\xb2\x68\xc8\x20\xde\x78\xc0\xd6\x4c\xa0\xad\x29\x7b\x0b\x17\x28\x66\x6f\xf6\x9b\x7f\xec\x50\x9b\x48\x19\x96\xeb\x9e\xc7\x7e\x6c\x17\x96\x93\x1d\xf1\xd8\x38\xa2\x20\x2d\x73\xea\xb4\x33\xbb\x28\x21\xcd\xdf\xdd\x43\x6b\x19\x62\xab\x85\xc3\x65\x72\x91\x0a\x41\xc7\x45\xd2\x48\xd5\xf3\xd0\x8a\x6d\xc7\x71\xb5\xd8\xa0\xcc\xae\x90\x78\x82\x19\xb6\xc0\x2b\x39\x26\x56\x9e\x1c\xcb\x48\x4c\x61\xc4\x02\xca\x0e\xb2\xf5\xe7\xe0\x6a\x4b\x23\x23\x30\x63\x95\x65\xa3\xc5\x5b\x61\x62\x68\xcd\x40\xf6\x2f\x39\xda\xf3\xe4\xf1\xdc\x4a\x79\x1c\x31\x9e\x4d\x4b\xfc\xbb\x3a\xe4\x35\x62\x9c\x6f\x4e\xbe\x4b\xc2\x54\x92\xbf\x68\x1e\x77\xda\xe7\xd8\x51\x1e\x97\xc6\x17\x7f\x09\xba\xb0\x29\xe5\x9d\x81\xdd\x28\x0a\xbd\x69\x98\xc7\xb6\x17\x26\x70\x39\x91\x9c\x90\x98\x9c\xdd\x1e\x46\xa3\x64\xf7\x49\x80\xc0\xf6\x53\xf0\x9f\x7a\xb1\xd5\xd4\xa2\xa5\xe7\x02\xd6\x75\x71\x9b\x17\x15\x67\xde\xdd\xb4\xe9\x56\x44\xd1\x5a\xf4\x26\x60\xff\x57\x9e\x3a\x3a\xed\x2a\xc2\xfe\x5e\xeb\x21\xdd\x56\xc6\x00\xff\x70\x7d\x9d\x85\x99\x9f\xf9\x61\x13\x19\x81\xe7\x95\xeb\x2c\x3f\x0c\xb7\xf0\xe7\x38\x90\xd0\x10\x16\x07\xe6\x99\x9b\xfc\x4b\x86\x9e\x5f\x95\xaf\xb5\x37\xcc\x67\xe2\x3f\x04\xd0\x72\x9b\x11\x57\x2e\x55\xe5\x5b\xd6\xe4\x1c\xc5\x63\xea\x3e\x98\xe7\x39\x29\x5c\xbe\x3c\xad\xba\xfe\xb1\x72\xc1\x2e\x2d\x95\x0f\x07\x5e\x88\x0d\xa0\x42\x74\x52\x40\xe4\xbb\xcd\x93\xc6\x66\x9d\x04\x38\xf1\x77\xf1\xd1\x05\x01\x3c\x5f\x49\xc8\xee\x82\xc0\xad\x18\x05\x61\xce\xc0\xb7\xc2\xc6\x9f\x10\x18\xcc\xa2\x04\xf8\xb3\x28\xc1\x81\x11\x43\x9b\x55\x82\x03\xdc\x2f\x29\xab\x5c\x52\xd6\x0e\x7e\xfb\xde\x1f\x82\x3f\x7e\xdb\xa8\x0a\xc3\xbf\xb7\x64\x5a\x0c\xeb\xed\xab\x5a\xdb\x95\x47\xc6\x90\x83\xde\x18\x11\x91\x80\xfb\x72\x67\xc2\x0f\xd9\xf1\xb7\x4a\x70\x5f\xfd\x22\x7d\xfb\x49\x65\xcf\xf5\x67\xa6\xac\xba\xae\xbd\xcc\x92\x16\x36\x2d\x17\x04\x47\xee\x3b\x9b\xd1\xcb\xe2\x0e\x4b\x0b\xc6\x3e\xa9\x01\x24\x6e\xdf\x1c\xde\xd6\xed\xf8\x0c\xca\x2b\xff\xb2\x4c\xc1\x5b\x80\x91\x6f\xdd\x22\xa0\x4e\x9f\x3e\xf4\x89\x8d\xf1\xb6\xaf\x65\xeb\xd0\x59\x91\x66\x1a\x82\x9b\x43\x2d\x9b\xbd\x02\x5c\x51\x7a\x84\xf4\x25\x81\xec\x73\x65\xec\x1d\x1d\x67\xb4\xa7\x83\xac\x40\x9f\xb9\x25\xed\xa9\xf0\xf3\xf9\x07\x20\x16\x49\xf3\xc5\xfe\xb6\x5e\xd8\x84\xad\xbc\xcf\xfc\x8b\xd8\xf3\xb9\x2a\xcd\xd3\xac\x88\x95\x1c\xe5\xec\x1e\x44\xe7\x80\x06\x98\x3c\x92\xad\xc3\xf5\x8a\xe5\x21\xaa\xd8\x30\xe9\x4f\x21\x0d\xf4\x77\x21\xf5\x95\x86\xa9\xde\x9e\x7b\xfb\x7f\xc1\x1b\xc0\xbc\x44\xeb\x53\x9a\xe3\xec\xd3\x72\x2e\xa0\xfa\x7e\xa7\xff\xfe\x42\xb6\x7a\xe3\xe6\x2b\x85\x1f\x42\x1a\xea\x6d\x41\xea\x2a\xf6\x2b\x79\xbd\xaf\x0b\xfb\x1d\xd9\x28\x6b\x00\xc3\xc8\x13\xf8\xf5\x77\xeb\x5f\xed\x33\x64\xdc\x1f\xde\xe2\x16\x56\xae\xbb\x79\xfe\xd4\xf9\x34\x2f\xdc\xba\xc2\xdf\x59\xad\x80\x99\x68\x73\x92\x76\x84\x7a\x4a\xde\x05\x30\xef\x61\xe1\x14\x70\x36\x1b\x37\x9f\x9a\x58\xbd\xde\x36\xa4\x9e\xaf\xc5\x09\x9e\xe9\x79\xc5\x6e\x01\xce\x6f\x15\xa3\xff\x9b\x7d\x6c\xa7\x86\x6b\x01\xf2\x83\x8e\x6e\x9e\x72\x37\x0a\x79\x79\x68\x10\xdd\x44\xa5\x62\x4b\xa5\xf4\x53\xeb\x4f\x52\x35\x70\xa5\x38\x1f\xec\xa7\x2e\x54\xac\x61\x5b\x0c\xab\x91\x59\xbb\x68\x4b\x48\x43\x4a\x5d\x63\x40\xb9\x2f\xe5\x89\x73\x01\x2d\x1d\x60\xcf\xbc\xb8\xa2\x8b\x45\xb6\x8e\x61\xa4\x47\x6b\xa6\x59\x72\x9a\x01\xca\x87\x85\x4b\x3c\xf3\x45\xc3\xc1\x08\x65\x8e\x9b\x57\xf0\x56\x03\x90\x52\x50\xad\x85\xfc\x74\xac\x47\x2b\x24\xef\x8d\xd0\xb4\xf7\x20\xb4\x8a\xf1\xe5\x52\xb0\x93\x62\xa0\xcd\xcd\x87\x1e\x50\xe0\xc7\x54\x45\x5b\x6a\xd2\x85\x8f\x0d\xde\x0e\xf4\xe8\xbd\x10\x18\x2a\xb1\x85\xb5\x4e\x55\xb6\xa6\x5a\x9a\xf2\x7b\x01\xa6\x56\x3c\xca\xd5\xf7\x8e\xf4\xb6\x0c\xad\x1c\x51\xf1\xe6\xca\xfe\xe0\xad\xd8\x77\xfc\x2a\x93\x3f\x9b\xd3\x83\x37\x4e\xea\x95\x0c\x73\xfb\x4f\xa3\x82\x14\x09\x6a\x93\x24\x80\x30\x60\xdb\xb1\xfb\xc1\x97\x2f\x1c\x0e\x91\x4e\x9c\x4b\x1d\x9f\x5d\xcf\xab\x92\x5d\x0d\x69\x5a\x3f\x3b\x1a\x3a\x77\x88\x81\xd9\xfe\x1f\x3c\x82\xc6\xf4\x87\xa7\xf5\xd3\xfa\x37\xd2\x86\xc3\xd2\x87\x95\x1f\xbc\xdf\xa6\xb4\xd9\xa8\x1f\x6e\x56\xee\x77\x6c\xe7\x7d\x44\xc5\xc9\x41\x84\x25\xfc\x79\x76\x8f\x98\x04\x88\x2b\x84\x77\x24\x2c\xc6\xc8\x58\x6c\x1b\x0f\x3e\xdd\x2f\x6a\xfd\x1d\x31\xc3\x27\x0f\x24\x59\xa7\x10\x46\x9d\x97\x0f\xf5\x5c\xfc\x83\x28\x08\xfd\xf8\xc8\x41\xd0\x83\xea\x5d\x78\xef\xc1\x69\xf1\x5a\x6b\x90\xb0\xe3\x24\x35\xa0\xec\x05\x55\xdc\x88\x88\x3f\x03\x5a\xaa\xb5\x4e\xfe\x03\x3a\x35\xdc\x5a\xbf\xbf\x01\x02\x43\xe6\x05\x27\x5a\xea\xdc\xa4\xca\x7d\x1f\x14\x77\xa1\xa7\xda\x7e\x48\x45\xe3\xde\x01\xad\x56\x4e\x27\xf3\x4f\x3a\xa9\x52\xc5\xfd\x18\xa8\x7c\x4a\x25\xac\x12\x14\xd8\xa1\x18\x02\xcc\xd4\x43\x2e\x5e\xe0\xb9\xc7\xda\x8e\xe5\x60\xcb\xda\x67\xcd\x90\x28\x33\x21\xb6\x8f\x61\x0d\x8c\x5b\x30\xc9\x98\x0e\x10\xc2\xbb\x00\x23\xa0\xa8\x63\x5d\x6a\xa1\xdb\x1b\x29\x98\x81\x60\x12\x1b\xef\xd2\x72\x73\x4a\x21\xa5\x2a\x6a\xb6\x05\x12\x13\x63\xf5\x08\x66\x60\x14\x94\xbd\x6f\xcb\x2b\xe6\x0d\xae\xef\xed\x1d\x19\x19\x1b\x3b\x6d\x78\xa8\xbc\xb8\x78\xff\x81\x20\xb5\x1c\x32\x3c\x73\xc6\x15\x35\xd5\xfa\x8e\x40\x83\x48\x54\xc2\x7d\x89\xaf\x5e\x8d\xe0\x50\x81\xc8\x3a\x15\x75\x7b\xfd\x1e\xac\x50\x27\xb5\xd7\xed\xd9\xf8\x2f\xb5\xba\xad\x3e\x3d\x0d\x7d\x08\x4a\x4b\x6f\xab\x9b\x95\x19\x0d\x61\x0a\xe5\xa9\xea\x58\x4e\xe6\xba\x2d\xe1\x04\xbe\x4b\xba\x03\x3b\x14\x78\x4c\x40\x40\x1d\xc1\xb6\x89\x94\x61\x1d\x8b\xf0\x2c\x04\xe2\x89\xc8\x11\xa8\xaa\xcc\x75\x5d\x1d\xcf\xba\xa9\x9d\x55\x2c\x59\xf6\x3b\x49\xed\x61\xd8\xcb\xaf\xac\x25\x16\x79\xcb\xc2\x5c\x09\x88\x1c\xc0\x23\xb9\x32\x22\xa0\x64\xb9\xc1\x11\x89\x61\x45\xde\xb5\x3e\x50\x95\x7e\xaf\x3f\x6e\xc5\xa0\x76\x5d\x77\x5a\xc4\xef\xcc\x59\xd7\xac\x02\xce\xef\x8e\xb1\xb0\xf0\x80\xb7\x61\x29\x88\xe6\xde\x33\x9d\x33\x74\x32\xd0\xf1\xe3\xef\x0f\xf7\xad\x54\xfe\xfd\xdb\xb7\x4d\x4e\xef\xf8\x36\x3d\xed\x9c\x3f\x43\xdd\xb9\xd3\xde\x90\x81\x07\x64\xff\x7d\x31\xf0\x19\x79\x22\x39\xf5\x67\x56\xe0\x15\x0e\xca\xcb\x9a\x21\x5a\x31\x03\xb1\x71\x7a\x26\xdf\x57\xba\xb1\x77\x95\x8d\x2d\x66\xa3\x52\x9c\x08\x84\x43\x7c\x4b\x0f\xc2\x3e\x1d\x0e\xc1\xfe\xa8\x27\xdf\x63\x77\x00\x41\x3f\x60\x36\x24\x2c\xd8\x7c\x43\xc3\x6b\xd9\x9d\xed\xe4\x30\xe9\x2d\x3e\x5c\xf7\x23\xa8\xcb\xbd\xc8\xf7\xc2\xd5\xef\x9f\xf4\x35\x4b\x1c\xef\xb0\x4c\x69\xd2\x54\x6f\x6d\xf1\xcc\x5c\x5b\xda\xa9\x4e\x4a\x58\x75\x8e\x7d\xea\x95\xb5\x07\xdb\xa1\x18\x92\x78\xfd\xc6\xc3\x5b\x40\x34\xab\x75\xab\x09\xab\x67\x86\xf7\xf7\xf2\xfb\xa1\x00\xe2\x40\xc0\x1d\x8b\xfc\x2b\xfa\x22\x80\x05\x93\x52\x2e\x13\x41\x53\x90\x54\x9b\x2b\xae\x07\x38\x53\x07\x80\x99\xb1\x33\x72\x0a\x50\x2c\x71\xdd\x95\x56\x5e\x84\x66\x05\xba\x00\xdd\xd3\x62\x99\xf6\xda\x9d\x5d\x64\x7c\x6b\xb0\x0a\x1a\x78\x74\x51\x0b\xdc\xc3\xa4\x3d\xa2\x13\x3a\xe2\x08\x04\x71\x43\x2f\xd1\xbe\xdf\x4b\xfa\x36\xe4\x39\x40\xce\x11\xcc\xa6\xb4\xff\x38\xdb\x83\x8d\x29\xaf\xe3\x36\x06\x6d\xd5\x6b\x8f\xcf\x8b\x1f\x85\x12\x7a\x7b\x89\x76\xfd\xb5\xb5\xc5\x43\x12\x0b\xeb\xed\x47\x13\xad\xfa\x1f\xd6\x76\xdb\xcc\xa0\x64\xf8\xbc\x85\x0d\x6c\x43\x11\x88\xc8\x87\xe7\x60\x97\x68\x16\x96\x95\x72\x80\xb1\xa4\xae\xfc\x00\x2e\xba\x53\xa7\x1e\x46\xdb\x6d\xee\xd8\xa5\x3e\x32\xed\x91\x88\xba\x95\x6e\xfc\x99\x5c\x8f\x79\x0a\x96\xbc\xd9\x33\xc3\x6b\xd8\x1a\x90\x34\x33\x62\x91\x3f\xef\x82\xec\x73\xcd\x4e\x6a\x97\x86\xe4\xe9\x87\xfa\x54\x85\x88\x12\x99\xe6\x25\xd2\x61\xbf\x29\xb4\xf9\xf6\x32\x9f\x10\xb2\x7d\x1e\x37\x0a\xfd\xba\xea\x20\x49\x94\x9d\xec\x0a\x7d\x41\x36\x6d\x85\x22\x6f\x27\x82\x69\x4c\x49\x8c\x1d\x9e\x49\x0f\x35\xf9\xbc\x79\xe0\x97\xe3\x3f\x00\x81\x84\x87\x81\x7c\xaf\xd6\x55\x65\x2d\x87\xd2\xa2\xcc\x68\x62\xeb\xe7\x3d\xcf\xaa\x06\x13\xdb\xb1\x5f\xd2\x02\x2a\x27\x80\x7b\x9d\x88\x10\x68\x9d\x1e\x33\x72\xbc\xea\xd0\x07\xb3\x79\x22\x3a\x96\x55\x40\x3e\xe7\x71\xc2\xdb\x7c\x4a\xd9\xff\x21\xec\xf9\xb5\x80\x95\xf6\xd7\x8e\xba\xef\x98\xed\xa7\xb4\x37\x32\x10\x5a\xce\x9d\xbc\xcd\x09\x5d\x82\x70\x1f\x1b\x25\x7d\x05\x8e\x19\x80\x2c\x72\x09\xe4\x54\x0f\x83\x96\xe5\xc4\x81\x65\xb3\x75\xda\x31\x27\x74\x0e\x84\xcc\x96\x58\xfb\x6d\xe4\xd9\xa9\x58\x24\x3a\x44\x6c\x3e\x80\x4f\xc5\xf2\xea\xea\x05\x1e\xf3\xfe\xed\x85\x4b\x58\x1d\x5b\x92\x3b\xb6\xf4\xe1\x84\x34\x45\xcb\x68\x21\xc8\x42\x41\xad\xcb\xdf\x6a\x17\xaf\x13\x5a\xc9\x3c\x7c\x3a\x66\xb1\x1b\xa1\xa2\x03\xac\x5e\x03\x8b\x4f\x9b\xef\x68\x35\xad\x80\x01\x61\x95\x20\xf5\xf0\xfc\x80\x84\xaf\xf9\x4b\xb2\x93\xa9\xbd\xe5\x84\x75\x1b\x90\x85\x9d\xa4\x2f\x62\x03\x7a\xac\x74\x9a\x80\x77\x7e\x9b\x38\x69\x24\xf9\xa8\x6f\x6f\xa3\xef\x74\xb2\x5e\x04\x33\x51\x3f\x72\xd5\xed\x4c\xcb\x8a\xcb\x66\xac\xf7\x6f\xcb\xcd\x08\x49\x0f\x6e\xcf\xf5\x48\xd8\x15\x99\xcd\x1d\x69\xd9\x71\x55\x67\x67\xea\x8d\xe5\x29\xd3\x87\xa6\x14\x69\x1e\xf5\x2d\x1a\x61\xab\xfd\x75\x69\xcc\xcb\x34\x2c\x61\x7b\x9e\x20\x6e\xbe\x59\x24\xb0\xb8\x9b\xf9\x48\xed\x6b\x4a\x19\x63\xd4\xce\x4a\x08\x01\x38\x40\x89\x74\x31\x41\x92\x79\x8f\xea\xfb\xa5\x38\xa3\x52\x51\xce\x29\x28\xe7\x0d\xc1\x71\x72\xfe\x3c\xb5\xc2\xe9\xab\x27\x54\xc4\xff\x94\x32\x51\x55\x45\xbe\xf3\x54\x88\xa8\x87\x14\xbf\x17\xa2\x0c\xd4\xab\x0a\x9e\xe9\xd2\x2a\x44\x3c\x21\x04\x94\x12\xe2\xa5\x98\x60\xf2\x94\xab\x05\xb9\x5d\x92\x30\x5e\xdf\xa2\x2b\x3d\xc7\xab\xf5\xaa\x49\x7c\x09\x5e\xbe\x12\x4f\xfd\x61\x78\xa3\xbb\x27\x97\xe3\x89\x44\xd0\x54\x53\x12\x52\x3c\x3d\x9e\x4f\x2b\x12\x5f\x2e\xc5\xcb\xe3\xa8\x8a\xb1\x07\xa3\x08\xb8\xbb\x64\xf5\x97\x27\xf2\xe5\x09\x74\x6c\xfc\x39\x89\xba\xa7\x65\x35\xa6\xe4\x2c\xc6\x99\x12\x4f\x76\x27\x07\x7a\x05\x7a\xb8\x7b\xc4\x53\xc2\x5d\xf2\x17\xaa\xa6\x78\xe3\x0b\xbd\x08\xaa\xdb\x6a\x0a\x44\x5d\x81\x1d\xc3\xa2\x4b\x71\x6f\x22\x0a\xa9\x8f\xa7\x4d\x7e\xab\x10\x13\x8a\xfe\x37\xf7\xf0\xbb\x2a\x00\x35\xd7\xaf\x08\xe5\xfc\xed\x16\x53\x85\x70\xb9\x45\x8d\xcb\xf1\x42\x3e\x57\x56\x2d\x4a\x28\xf2\xf4\xb8\x59\x57\x5a\x7e\x5d\xcf\x5e\xd5\x05\xcc\x6f\x1f\x50\xe5\x36\x7b\x0a\x9e\x5b\xa5\xc4\xe9\x3d\x3c\x6f\x7a\x11\x51\x0f\x25\x1e\xaf\xc1\x08\x67\x84\x66\x78\x0b\x19\xf7\x10\x8f\x07\x3e\x92\x05\xf2\x00\xdf\xca\xa4\xc3\x05\xc6\x94\xda\x97\x8b\xf2\x89\x3e\xfa\xa2\x19\xf9\x82\x1d\xe1\x21\xc1\xfe\x88\x43\x05\xb0\x2f\xe1\x39\x17\xa0\x99\x86\x6b\x79\xee\x79\x99\x72\xad\x4c\x2b\x3e\x3b\xa3\x9a\xca\x92\xb1\x98\xaf\xb5\x5b\xe3\x2f\xf0\xb1\xf8\x09\x05\xcf\x66\xf7\x6e\xeb\x90\x03\xda\x3e\xd1\x4f\x3c\x0b\x83\x31\xe8\x23\x14\x72\xc9\xca\x79\x17\xea\x77\x85\x00\x19\x37\x30\x22\x01\xa2\x90\x13\xd8\x61\xc1\x1a\x59\x4d\x80\xb8\x30\x7f\x49\x62\xbe\x38\x48\x5e\x2d\x72\xe4\x69\xad\x0d\x61\x0c\x05\x9b\xde\xb4\x42\x8c\xe2\x90\x00\x37\x91\x4e\x39\xb3\x21\xb5\xf8\x67\x49\x20\x32\xeb\x83\x04\x69\x4f\x42\x1f\xb9\xac\x0b\xba\x2a\x7b\xc8\xaa\x21\xbd\x26\xba\x46\xdc\x10\x73\xa8\xc1\x53\xa1\x9f\xef\xe1\xe8\x6d\x74\xd3\x2a\x56\xc6\xea\x91\x63\x68\x7c\xb5\x92\xca\xa2\x8c\x26\x10\x45\x3d\xa3\xad\x45\x04\x96\x2b\x82\xd3\x42\x4a\xa0\x26\x51\x22\x2f\x71\xc2\x64\x91\xe5\x22\x8b\x38\x59\x6e\xd9\xfd\xa3\xb6\x84\x80\x24\x9e\x3a\x10\xef\xef\x19\xa4\x8a\x57\x06\xbb\x7c\x0e\xa6\x38\x9d\x8b\x9a\x61\xc1\x25\x09\xe3\x46\x8e\x82\xe5\xa8\xeb\xd6\xee\x7e\xbd\x5c\xd7\xda\xd8\xea\x5c\xe3\x20\xca\x04\xb0\x05\x81\x07\x3d\x0f\xf6\xe9\xa1\x77\xc0\x8e\x16\xe5\xb8\x99\xe4\x22\xaa\xe4\x69\xaa\x34\xe0\xc8\x7d\x42\x95\xa9\x57\x33\x99\xdf\xac\xee\xe3\xee\x5b\x6f\x34\x59\x66\xb9\xcc\x22\x8b\x1d\xfe\xd2\xd2\x33\x31\x03\x44\x7f\x6f\xda\x94\xbd\xc0\x72\xc1\x5d\x43\x83\xaa\x84\x70\xcf\xbc\x41\x79\x6c\xb0\xa2\x6b\xc9\x37\x53\x20\x4c\xae\xcd\x6a\xc1\xaa\x0d\xf5\x40\xd9\x3e\xfd\xf9\x73\xfa\x25\xff\xf1\xea\x30\xdb\x29\x75\x11\xb5\x41\xba\x20\xdd\x39\xfd\x88\x2d\x5e\x7b\x1a\x23\x78\xf8\x2f\xa1\xde\xa6\x4c\x5b\x16\x60\xe2\x30\x2f\xad\x96\x28\x89\xdc\x3f\xc2\xa8\x59\xcd\x29\x86\xd8\x9b\x61\x0a\x8c\x77\x49\x7b\xe2\xad\x64\xcd\x64\x43\x08\x31\xaf\x95\xb6\xd9\xdd\xf8\xed\xda\x90\xda\x47\xf0\x8c\x64\x85\x12\x6a\x89\xbc\x3c\x96\xe3\x80\xf1\x1a\xf2\xa4\x52\xaf\xeb\x30\xf0\x2a\x65\x59\x43\xb1\x4e\x73\x49\x28\x7e\x2e\xe4\xb8\x11\x44\x3c\x81\x9f\x6f\x75\x0f\x77\xcf\xaa\x2f\xdb\x9f\x45\x50\x9b\x71\x02\xdc\xf7\x7b\x82\x0b\xdb\x63\xdb\x89\x58\x24\x36\x02\xe3\xe2\xeb\x1f\x13\xd0\x69\xdd\xe0\x8b\x45\x06\x00\xf3\xec\xf7\x98\x82\x3c\xa8\x2d\xb6\x8d\x80\xb5\x6f\xe5\x6d\x70\xef\x56\xf3\x17\x05\x74\x58\xd7\xfb\x62\xd1\x4b\xbd\xcd\xbb\xf9\x0e\x91\xa5\x17\x2f\xd5\x6d\x6a\x68\xf5\xe8\xa8\x6f\xa9\xe7\x32\x2c\x3b\x57\x9e\xcc\x81\xcc\x78\xbf\x49\x96\x67\xc6\xad\xd8\x8c\x39\x30\x73\xd9\xf4\x51\xf0\xa6\x4e\x13\x4f\xf2\x0c\xf7\x20\xa1\x48\x1e\x50\x04\xb2\x31\xe8\x98\xfe\x27\xbc\x01\x67\x4b\xa4\x2c\x2d\xc8\xde\xcc\x22\xf8\x7a\x32\xf1\xf3\xd7\x98\xda\x6d\xa5\xb4\x84\x71\x12\x0a\x5a\x89\x28\x45\x7a\x92\x51\x4e\x65\x96\x73\x44\xa4\x12\x11\x1c\xab\xa3\x3d\xd5\x86\x3b\xec\x07\x2c\x63\xab\x50\x98\x5f\x22\x62\x70\x79\xb1\x1e\x07\x49\x0c\x6b\x3c\xc6\x89\x74\x92\x2c\x5f\x82\xf0\x42\xa5\xa6\x8e\xea\x2d\xf7\x71\x92\x98\x97\x20\xa0\xec\xdc\x90\x2e\x98\x5f\xb6\x15\x06\xd3\xd6\xff\xaf\x68\x8b\x22\x7b\xd8\x18\xf9\x67\xf2\x47\xdb\x11\x6a\xae\xdd\xe7\x14\xe1\x79\x10\x06\xe1\xc2\x15\xad\x87\x3b\x21\x58\x8c\x3b\x8a\xc6\x1b\x83\xfc\x16\x43\x0a\x48\xa8\x92\x2a\x67\xf6\x72\x2d\x90\xfe\x3b\x32\x49\x3b\xb2\x81\xf0\x64\xe3\xfa\x54\x92\xd7\x58\xea\xc4\x25\x12\x5c\xdd\x66\x17\x54\xac\xf7\x07\x95\x9b\xc7\x9a\x52\x73\xa0\xdf\x6d\xf9\x10\xc7\x2d\xee\x2f\x2c\x8e\x1d\xcb\xc2\x3b\x55\xb0\xbd\x55\xb2\xdb\xdf\xf9\xb1\x10\xc4\x76\x2d\x7b\x85\xa7\x93\x3d\x95\x6e\x4f\x09\x39\x82\x00\x9d\xf2\x6b\x80\x1f\x11\x55\xae\xeb\x95\x90\x9d\xaa\xee\xe2\x93\x12\x1e\x04\xee\x8b\x12\xe1\xff\x28\xfa\x6e\x17\x64\x7a\xb6\x49\x69\xfe\x13\x0c\xfe\xc3\x50\x5f\xed\xad\x0d\xa6\x6b\xad\x90\x61\x8a\x15\xb7\x36\x64\x3e\x2a\x3b\x9f\xef\x02\x09\xda\xbb\xeb\x7b\x95\x56\xda\xe0\xd5\xfe\x71\xd0\xcd\x53\x82\x07\xfd\x1b\xea\x87\x02\x5b\x98\x42\xee\x4f\xef\x6c\x5d\x79\x57\x9e\xe9\x4d\x52\x5a\xc1\x24\x2e\xa9\xdd\x25\x98\x92\x9b\xf8\xaf\xa7\x71\x6a\x22\xb6\xcc\x99\xb1\xdd\x2e\xef\xdd\x39\x2a\xed\xb7\xab\xa7\x07\x14\xab\x9d\x48\x2a\xee\x3a\x9c\x48\xa8\xc9\x66\x63\xa1\x45\x70\xdf\xe6\x52\xb5\x96\x6f\xa5\xbe\xb9\x51\x23\x22\x68\xd5\xe2\x74\x4c\xc2\xc9\x5c\x97\x56\x97\x09\xb0\xa8\xc1\x4f\x66\xf5\xda\xe2\xda\xcf\xc0\x94\x7d\x05\x3d\x51\x5d\xaf\x9a\x4c\xbd\xa5\xf1\xbe\x48\xaf\x97\x7c\x9b\x3c\x6c\xe7\x98\x25\x8a\xcb\x43\xd3\x36\x07\x68\xff\x25\x60\x74\x34\xa8\x35\x7b\xdb\x29\xcf\x44\xbc\x17\x24\xef\x43\x9d\x82\xbd\x57\x32\x4d\x85\xb2\xea\xa0\x46\x97\x98\xcb\x44\x85\xab\x97\x70\x8e\x97\x98\xfe\x56\x49\x34\x65\x40\x94\x20\xb4\x0c\x89\xac\x47\x22\xf9\xc1\x9d\xc6\xc2\x05\x53\xb3\x5d\x7d\xb3\xa7\xdb\x85\xf3\x8d\x82\xf8\x96\x4d\xc8\x62\xe4\x46\xdc\x29\xbd\x4b\x74\xdd\xb8\xcf\x7f\x95\x1a\x9a\xb2\x99\x4d\x71\x39\x25\x71\x1b\x63\x2b\x8f\x8f\xa2\x39\xba\xb1\xba\xc0\x73\x66\xf8\x0a\xd1\xb6\xb2\x9c\xf9\xa6\x62\x18\x92\x21\x13\xf3\x74\x8a\x4f\x65\xad\x0d\xc9\x5e\x37\x75\x7c\xcf\x50\xad\xdc\xe3\x81\xfa\x90\x5e\x67\x2d\x6a\x12\xd1\x8a\x28\x42\x94\x09\x71\x0d\x05\x02\x37\xff\x7e\xc6\xd4\xc6\x10\x3f\x56\x5c\x78\x5d\xa2\x6f\x46\x86\x6f\x67\x26\x9e\x77\x35\x4f\xa7\xd6\x6f\xeb\x2c\x33\x95\xdb\xaa\x6c\x4c\x54\xfd\x9f\xd6\xc3\xb5\xdc\x19\x86\x4e\x6e\x05\xf9\x55\x60\x7a\xa7\x5c\x54\xe4\xec\xc3\xe4\x64\x1a\x91\xad\x53\xf4\xe9\xe9\x5c\xfa\xaf\x6b\xc6\xde\xfb\x2b\x5d\x28\x50\x58\x9c\xd1\xf1\x98\xf4\x78\x25\x32\x8a\xba\x5f\xca\xe5\x9e\x98\xe7\x32\x67\x40\xfe\x45\xc0\x9f\x97\xc9\x67\x86\xa4\x48\x6a\xbb\xcb\x74\xe9\x4d\xed\xfb\x0e\x89\x4d\x11\xea\x36\xf6\x46\x4e\xbe\x0d\xdb\x63\x5e\xba\xca\x05\xf0\xd9\xb2\xbc\xed\xad\xf2\x63\x91\xd5\xeb\xac\x7f\x2d\x4a\xe0\x44\xd4\x5f\xc7\x05\x2e\x2b\xf1\xa1\x4c\x51\x6c\x81\x4f\x91\x03\x08\xc2\x64\xe5\x00\x60\x75\x93\xbb\xa7\x1f\xbc\x3b\xa9\xe1\xd6\xa6\x55\xfd\x62\xed\x68\x98\x2b\xe8\x11\x7d\x4f\x90\x5d\xe6\xe6\xb3\xf1\xee\xc1\xf0\x13\x0e\xda\x89\xc3\xb5\x21\xcc\x19\x7f\x62\x68\x98\x09\xc5\xfc\xe2\x1f\xd3\x06\x12\x8e\xc7\x79\x32\x2f\xf6\x24\x7d\x2d\x34\x03\xbe\xad\x90\x2d\x02\x81\xf7\x12\xa8\xa2\xdb\x1c\x7d\x96\xe0\x19\x7c\x90\x7e\x5c\xc7\xcf\x2f\x6d\xe9\xda\x88\xcf\xb1\xc0\x04\x20\x5e\x84\x24\x32\x03\x9e\xcd\x94\xe2\x35\x23\xdc\xe7\xbe\xc0\x5c\x0f\x81\x50\x5c\x82\x6b\x58\xb3\xb4\x0e\x8c\xbf\x74\x78\x4d\xac\x29\xc6\x95\x14\x4f\x6c\x06\xc0\x29\x5e\xf8\x56\x39\x66\x2b\xfb\x14\x74\x73\x8d\x6a\xbc\x11\xda\xc8\xcb\x97\x23\x23\xf3\xf3\xae\xc2\x81\x78\xf5\xea\xd5\x3f\x67\xe1\x42\x1b\xe5\xff\x98\x50\x7c\xc1\x43\x76\x0d\xde\xb6\xb1\x13\x71\xd3\x3f\x2f\xb9\x26\xed\xb5\xd5\xfb\xca\xe8\x92\xec\x08\x79\x74\xbb\x67\x22\xb9\x67\x27\x5d\x11\xab\x4f\x49\x69\xf0\x57\xe9\x76\x64\x15\xec\x16\x8d\x2f\xbf\x1f\x9a\xf6\xcd\x6e\xdf\x10\xb0\xf2\xf1\x29\xd0\xf9\x30\xa4\xfb\xeb\x50\x23\x58\x32\x3f\xf9\x42\xc7\x86\xb3\x11\xa9\x29\x8b\x35\x0b\xe3\x93\x73\x62\xf2\x62\x7b\x74\xaa\x63\x86\x7a\x63\xce\x37\xfb\x55\xeb\x14\x41\x19\x1f\xfd\xd4\x92\x31\x29\x21\xa2\xd8\x28\xbd\x8d\x93\x91\x53\xf9\xce\xf1\x2c\x84\x17\x34\x90\xf2\x1f\xe4\x48\xf8\x43\x8e\x24\x6e\x70\x3f\x24\xc1\x3d\x82\xc7\x02\x69\x5b\x9e\xee\x7e\xc5\xd7\x89\xab\x9d\x0f\xb5\xa3\xc1\x59\x58\x96\x85\x03\xc4\x41\x23\x93\x5f\x30\x82\x16\x92\xa8\x8a\x96\x6a\x85\x25\x1d\x17\x23\x4a\xc9\xf3\x38\x5f\xa5\xbc\x99\x66\x2e\xe7\xef\xc4\xc8\xe1\x2d\xce\x8a\x5e\xc6\x2e\xe0\xd6\x27\x0a\x8c\x64\x75\xc1\xfe\xec\xe2\x83\xd0\x78\x08\x2c\x3d\x72\xff\xee\x9c\xb2\x23\x91\x65\xb1\x93\xb6\xa5\x81\xf2\x2a\x41\x5a\xcd\xca\xdd\x85\xc5\x13\x5b\x53\x2a\x6b\x0c\xa1\xf5\xb5\xc4\xec\xb4\x80\xf4\xe8\x48\x4e\xbd\x04\x17\x54\xb2\xb2\x25\xf9\x45\x9d\x84\x1d\x95\x16\xf9\x76\x8c\x41\x82\xe6\xc8\x63\x8a\x52\xdf\x59\x94\x36\x80\xe2\x00\x64\xeb\xcc\xbb\xab\x59\xdc\xb2\x01\xa5\x00\x1b\x14\x87\x0e\x02\xfc\xf4\xca\xef\x81\x1f\x8a\x8d\x47\x26\x07\xff\x19\x63\x03\x88\x3c\xe3\xf4\x6f\x9e\x97\x90\x26\xe2\x6c\xf3\x77\x75\x8c\xbd\x3f\x4c\x48\x5a\x94\xb3\x94\x6e\x9c\x8d\xab\x4d\x29\x44\x2f\xf3\x55\x9c\x71\xd6\xb2\x3b\xbf\x1b\xf6\xbc\x3b\xea\x0f\x05\x0d\x8f\xec\x8f\x8c\xee\x0c\xbc\xc6\xf6\x67\x1e\x8d\xb7\xb3\x11\x9b\xb8\xdd\x29\x01\xca\xd1\xdd\xa2\xaa\x9f\xa5\x8c\xff\xb9\xb7\x79\x0e\x77\x7c\x5e\x7e\x64\xdf\x6c\x03\xaf\x16\x26\xc9\xbe\x40\xe3\xe3\xc1\x53\x0a\x08\xfd\x6c\xd6\x87\x07\x17\x1c\x06\xc6\xce\x8d\x72\xb8\x53\x1e\xef\x5a\x1e\xb6\x2e\x62\x7e\x88\xeb\x0a\xc5\x10\x7e\x8e\x94\x65\x79\xf9\x79\x65\xbd\xe2\xbf\xc5\x66\xfa\x1f\x69\xfd\xb6\x89\x08\x53\x07\xdf\xd5\xc0\xd4\x91\x44\x54\xba\x95\x17\x9e\x95\x95\x4d\x15\xe2\x18\xc9\x00\x81\x4f\x25\xe5\x2c\x25\x11\x64\x2c\x7f\xee\x4c\xf4\x3d\xce\x42\xfd\xa9\x2d\x83\x82\x31\xea\x3b\x2c\x82\x8f\x7b\xea\x7d\x17\x84\x2c\xd2\x9c\xdc\x3d\xad\xbf\x73\x8f\xde\x6e\x8c\x89\x3d\xc7\xba\x4f\x49\x3b\xf6\x24\x7f\xaa\xee\xd2\x70\xf2\xed\xc2\x27\x69\x26\x6b\x8c\x1f\xdc\x37\xae\xd9\xfa\xbd\x47\x2e\xee\xf6\xb1\x12\xe6\xfd\x8d\xba\x0f\xdd\xf6\xcd\x74\xf4\x00\x14\x30\xea\x1b\x72\x05\xb5\xe8\x0d\x27\x1d\xad\xfc\x62\x5c\x39\x83\xaa\x72\x7f\x91\xdb\xee\x0d\x6c\x67\x6a\x4f\xdc\xda\x2d\x72\x0c\xdc\xfe\x92\x6c\xf1\x03\x63\x12\xc5\xec\x8b\xc3\x37\x69\x63\x6d\x2b\xd3\x21\x15\xab\x44\x97\x5d\xd5\xf4\x89\xce\x61\x31\x3d\xd1\xa4\x35\x71\x81\x8b\x6c\x06\x7f\x8e\x0f\xad\x0e\x6c\xef\xdb\x06\xd5\xa3\xa3\x25\x11\x95\x91\xb4\x1a\xd2\x91\xfd\x6a\xc4\x09\x47\xf7\x64\x54\x0a\xc2\x0f\x76\x02\x2f\xa3\xf4\xf9\x09\xf5\x88\x23\xf6\xec\x8f\x1f\xa9\xbd\x4e\xde\xbe\xd5\x5e\xc1\x0c\x78\x93\x9c\xec\x42\xae\x3a\xc6\xc1\xdc\x57\x18\xa9\xda\xbc\xc9\x8f\x08\x98\x1b\xa4\x45\xd1\x76\x52\x34\x71\xcf\x03\x55\x3d\x7a\x6a\x55\x64\x41\x52\x4b\x16\xd6\x5d\xe4\x95\xd0\xd4\x14\xef\xb9\x68\x6c\x21\xd5\x57\x99\x9f\xd8\x75\x42\xe8\xeb\xa2\x0d\x6d\x0f\x28\x63\x0f\xda\xe7\x27\x0a\x48\x02\x65\x8e\xa8\x74\xed\xdc\x15\x6f\x7b\x52\x96\x7d\x24\x6f\x45\x14\x62\xfb\xb1\x3f\x99\xc3\xd9\x15\x81\xcb\xac\xee\xa3\x41\xa1\x0f\x79\x15\xb3\x66\xdb\xfe\x9a\xb1\x43\x2f\xce\x9f\x9c\x7b\xdd\xd6\xb3\x75\x37\x7a\xe4\x92\x8f\x1d\x8f\x1a\x93\xd0\x58\x47\xb6\x76\xa1\xb2\xd5\xfe\xda\xdb\x2d\x57\x3e\xbf\xb9\xad\x5f\x7e\x99\x6b\xcf\xa3\x94\xc8\xf1\x8f\x88\x94\x94\xee\xbf\xaa\x76\xee\x72\xc8\x9b\x69\x82\x26\x21\xaf\x2a\x29\x81\xb3\x08\x1d\x72\x49\xf5\xec\xd2\x62\x40\xe5\xec\xaa\x96\x25\x4d\x35\xd0\x9d\x73\x93\x21\x4e\x9b\xbd\xeb\x3d\xd5\x33\x68\xc4\x25\x60\x81\x1d\x55\x33\x06\xb2\x8e\x8f\xf5\x79\x56\x7c\x0c\x8e\x8d\xe4\x70\x88\x0f\x08\xd3\x6b\x2c\x36\xae\xd6\xd5\xad\x8a\x5d\x2b\x7b\x13\xf6\xf4\xc6\x45\xce\x97\x5c\xc0\x13\xd4\x5e\xd9\xd3\x04\xca\xd6\x03\x79\x6e\xdb\x94\x2e\x2a\x1d\x51\x7a\x95\x4d\x4f\xb3\xf3\xd5\xbf\xff\xe9\x10\x44\xef\x11\xee\xdd\x27\xec\x54\x95\xff\x53\x5c\xa2\x30\x98\x57\x55\x27\x35\xfb\x94\xbe\x3a\x99\x23\xe1\x68\xce\x85\x41\x15\x25\xca\x45\x5a\xb7\xca\x9c\x35\x62\xb5\xd2\x9c\xab\x14\x36\x4d\x2e\xfb\x5e\x71\xe7\xd5\xed\xd3\xb6\xda\x58\xd7\xdb\x28\x92\xa6\x02\x31\x85\xa7\xd8\x5d\x6c\x87\xee\xd4\x28\x34\x17\x1c\xa2\xa7\x41\xd4\xe6\x98\xe2\x8d\xd2\xa2\xed\xdb\x8b\xc0\xc2\x02\x13\xad\x56\x58\x6b\x76\x29\x5e\xdb\x9a\xdc\x6e\x36\xe3\xab\x65\xa5\x08\x51\xa2\x7e\xee\x80\x71\x60\xeb\x61\x34\x45\xa4\x9b\x95\xad\xd4\xdb\x6c\x11\xd9\x5a\x7b\x21\x9e\xb3\xce\xde\x65\xa7\xd9\xb9\x10\x08\x0c\xc2\x52\xbb\x96\x66\x6d\xa5\x84\x77\xc5\xa1\x17\x7c\xb5\xf8\xda\x4e\xf6\x77\x00\x64\x61\x7b\x25\x51\xf4\x09\x63\x9f\x79\xd8\xd1\x67\x91\xfd\x52\xb3\x9e\xa0\x9c\xc5\x41\x39\x7a\xef\xa0\x58\xb5\x07\x42\x4e\x9e\x7c\x35\xf9\xd9\x91\xb3\x11\x87\x4f\x9c\xfb\x34\x39\x5f\x77\xec\x9c\xce\x39\xa5\xb5\x90\xa0\xaf\xbb\x10\x1c\x2e\x07\x99\xe8\xe5\xa2\xff\x66\xed\x6f\xfa\xb1\x28\xfb\x1b\x44\xdf\xe6\x99\x5c\x13\x03\x1c\x45\x50\x6c\x9d\x9c\x7e\x8b\x50\xbc\x84\xcb\xa2\x41\xab\x27\xa5\xf7\xc7\x8f\x6d\x9d\xb2\xa4\xc3\x20\x10\x7c\xc5\xd6\x29\xcc\x5d\xcb\x8d\x83\xda\x31\x8f\xdf\x3c\x7c\x60\x29\x7b\xd9\xed\xf8\x79\x3f\xcb\x4a\x3b\x7c\xc6\x93\xe5\x15\x3d\xed\xd8\xc8\x04\x7f\x4a\x37\xb6\xb1\x4d\xe5\xe5\xfd\x4d\x41\xbe\xbd\xef\x7e\x77\x65\xfb\x82\xa4\x8d\x48\xf8\xad\x62\x5e\xcd\xbe\x2b\xe6\xce\x34\xd8\xf7\x96\xf5\x54\x1b\xb3\xe2\x89\x31\x1a\xe7\xba\xb2\xd1\xb3\xea\x27\x5a\x4e\x57\x52\xa8\x66\x10\xc3\x1d\x5a\xa6\x78\xa9\x92\x0d\x52\xb7\xcd\x1e\xaf\x7d\x1e\x93\x08\xcc\xf7\xd4\xcd\x1e\xab\x45\xd7\xda\xa2\x75\x5e\xc0\xf7\xad\x7d\xdb\x0d\x99\xac\xb0\x17\xff\x3d\xd6\xbc\x33\xe4\xb1\x43\x41\xec\x6c\x43\x5c\xe3\xa3\x27\x45\x0e\xce\xa9\x29\xd7\x2e\x8b\x62\x2e\x2d\xfa\xc7\xf7\x47\x42\xfc\xb4\xee\x9c\xd8\x84\xf2\xee\x48\x41\x7c\x5a\x45\x87\x79\x8c\xcb\xad\xd3\x79\xf1\x48\xe7\xdc\x3a\xff\x0c\xfb\x24\x8d\x86\x13\x27\x8a\x58\x85\xf6\x76\x1f\xc9\x33\x26\xbb\x79\xf3\x02\x56\x51\x4a\x2f\xb9\xb9\xff\x9a\x49\x5e\xe9\xd3\xc5\xdb\x09\xea\x27\x34\x5a\xef\xff\x59\x5b\x19\x7d\x3e\xfc\xc4\x93\x6e\x16\x9f\x9c\xd8\xeb\xc4\xd1\xad\xe6\x19\xc5\xa3\x76\xe8\xab\xfe\x54\x6f\xe4\x77\x28\xf2\x6b\x78\xc7\x82\xd5\x20\xcf\xf2\xd4\xbf\xad\x5e\x67\x57\x7a\xdb\xbc\xb8\x72\xc6\x31\x6b\x0d\x7d\x50\x63\xf0\x2e\x66\xfa\xc5\x9d\xe9\xf6\x12\xfb\x4c\x40\xe4\xb7\x5e\x83\x2d\xdd\xd0\x37\xf0\x70\x6a\x84\x6f\xa9\xb1\xbb\x9c\x72\xcd\xa4\xf0\xfa\x44\xe2\xb6\xb4\x0b\x70\x70\x4b\x74\xf2\x81\xc2\x03\x72\x14\xfa\x8f\x55\x7d\xca\x24\x67\x6d\x4a\x74\x90\x41\x50\x83\xb4\xc3\x76\xad\xdd\xcb\x0c\x1c\x68\x13\x2a\xd9\xb2\xe5\xcd\x9b\x2d\xf7\xb5\xfd\x5a\xd0\x76\x26\xc5\x64\x48\xab\x6a\x7c\x34\xb7\x50\xc6\x0e\x39\xa0\xf3\xfb\xb1\xde\x3f\x5d\x5d\x7f\x7a\x05\x77\x1b\x18\xdb\xee\x02\x20\x11\x00\x80\x08\x1a\x77\xf8\xff\xa3\x4c\x9b\xe1\x0f\x07\x98\xc0\xda\x7a\xcd\x20\x7a\xc0\x85\xe9\x1e\xb8\xa0\xd0\xa9\x21\xd5\xf8\x2e\x05\x2b\x27\x2c\x7a\x9c\x62\x38\xfb\xee\x08\x83\xa7\x0f\x2a\xdf\xae\x24\x8b\xde\xea\x86\xce\x6a\xce\x86\x2c\x82\xb5\x37\xea\x62\x43\xe6\x85\x01\x15\xe3\xeb\x92\x6f\x9e\x2f\xda\xf7\x5d\xc1\x45\xac\x68\x2b\x1e\xba\x12\xb7\x23\x50\x4e\xaa\x19\xc8\x3a\x0d\x1f\xd2\xc7\x3c\x9f\x44\xe2\x53\x10\x5f\x53\x34\x10\x3b\x0e\xce\xd6\x4c\x47\x1f\xac\xae\x99\xdd\xef\xb3\xec\x56\x5f\xfd\x21\x47\xb3\xa9\x38\x97\x88\xca\x9c\x25\xb0\xf7\x02\x1d\xad\x67\x71\x5d\xb0\x77\x58\xb9\xdc\xc2\x1b\x18\x12\x5c\x7a\x0b\x5d\x88\x42\x97\x57\xb0\xfb\x0c\x87\xce\xbb\xd7\x7a\xfd\xec\x54\x53\xf9\x76\xa0\xf4\x6c\xd3\xca\xf0\xf0\xca\x10\x85\x86\x56\xb8\x2b\x23\xfa\x8a\xe1\xa1\x9c\xaa\xb5\xa7\xa5\x06\xb7\x02\xe6\x15\xfa\x1f\x0c\xf2\x4c\x20\xf4\x94\xbe\x15\xbe\x57\xff\xa7\xfe\xba\xcf\x9b\x3d\xdd\x75\x35\x0e\xd2\x66\x1e\x86\x5d\xea\x59\x3a\xdd\x35\x74\x67\x71\x38\x68\xc4\xa2\x29\xa3\xaa\xa1\xa8\x2b\xa9\xdb\x3c\x1e\x35\x64\xac\xb4\x50\xaf\x3a\x39\xdb\x3f\x74\x75\x6e\x24\xe1\xae\x7b\x60\x1c\xe7\xfb\x1e\x59\xac\x10\xab\xb4\x3f\x21\xc5\x26\x5d\xdc\xb3\x92\xdf\x70\xa3\x61\x81\x86\xbb\x52\xb2\x1c\x3c\xd4\xd2\xb1\xa5\x6e\x6b\x7d\xcb\x44\x70\x7a\x61\x77\x59\x81\xd6\x24\xd6\x7a\x15\xfa\x3a\xa1\xdf\x93\x89\x48\x19\x7a\xec\xe6\xd5\x11\x1b\x83\xef\xaf\x64\x59\x9c\x10\x47\x6a\xb1\x61\xef\x72\xcd\x3e\xf1\xef\xf7\x71\xcd\xb8\x45\x40\xca\xd8\x47\xe3\xac\x34\x8d\xde\x13\x9b\xbf\xda\x2b\xee\x80\xfc\xd4\xdb\xed\x93\x02\xb7\xf3\x35\x7c\xa8\xd9\x22\xc3\x45\x40\x9f\x9f\xe2\xe0\xcf\xe2\x38\x1f\xfd\x78\x8f\x79\x3e\xd7\xc1\x58\x03\x71\x49\xa7\xa6\x33\x25\xe5\x34\x26\x8d\x95\xc5\x55\x65\xd1\xa3\x78\x8c\xde\x9c\x2b\x1f\xd6\x1b\x56\x5b\x0a\x57\xb8\x0e\x3f\xd2\x24\xfe\x55\x8c\xa4\x8b\x99\x37\xa9\x8a\xec\x48\x9d\x95\xec\x90\x32\xb1\xdc\x98\xee\x6d\x0a\x87\x26\x1a\xe7\xae\x7b\x7d\xb4\x33\x03\xf1\x7d\x9d\xbd\xf7\x8c\xd7\xf5\xa2\x1d\x96\x60\x52\x07\x55\x05\xce\xd5\x3d\x7d\x69\x69\x2a\xf6\xa3\x22\x51\x3a\xb3\xeb\x2c\x20\x21\x38\xa9\xf3\xa0\x36\x8b\xdc\xa4\x50\xa5\x27\xe0\x54\x94\x73\xa4\xeb\xd6\x72\x76\x77\xa6\xac\x83\x4d\x12\x00\x44\x4b\x4f\x78\xef\xdb\xc9\x69\x6e\x4d\x82\x27\x5c\x57\xa7\xad\x09\x6d\x46\x93\x88\xd9\x66\x8a\x50\x82\xaa\x4f\xc4\x1c\x56\xa6\x0d\x09\xbb\xe6\x5c\x84\xb3\xd3\xca\x60\xbe\x0e\x95\xe3\x91\x13\x25\x7e\xf2\x4a\xc2\xf9\x4a\x76\x43\x6d\xa2\x38\x8f\x6b\x1d\x76\x39\xbd\x05\x45\x8a\xb7\x67\xdd\x66\x76\x9e\x47\xd9\xa1\xce\x77\x32\xef\xb1\x30\xf1\x24\xdb\x2d\xa7\x5c\xe6\xb4\xc6\x49\x98\x4d\x44\x37\x9c\x4f\x16\xdb\xba\xd2\xe3\xad\x72\x55\xfa\x0c\xca\x14\x3a\x51\xda\x83\x9b\x31\x3c\x3b\xd2\x09\x2d\xab\x98\xeb\x3a\x18\xe1\x7a\xeb\xaf\xfa\x5e\x25\xf1\x71\x90\xbc\x42\xbe\x5a\x4b\x8a\x51\x44\xeb\xe8\xc6\x7b\x05\xd2\x97\x96\x78\xc7\x6f\x65\x25\xb4\x2a\x70\x0c\xd7\x0e\x16\x37\x7c\xb5\x2d\x74\x3c\x5e\xdd\x78\xd8\xa3\xd0\x62\x54\xfe\xed\x2a\x6e\x0c\x95\xe5\x7d\xce\xdb\x99\x6f\xd0\xca\xcb\x9e\xd7\x28\xf3\xdd\x01\xef\xb4\xb2\x83\xa7\x04\xd7\xda\x5c\xb6\x9f\xa7\x5e\x28\xef\x1e\x5a\x6e\xc4\xd1\x33\xa0\x66\x82\xf1\xb1\x5a\xa4\x2c\x32\xcb\xed\x87\x3a\x83\xa7\xaf\xaa\x22\xba\x17\xd0\x6e\xbb\x40\x7b\xf3\xb6\xd5\x38\x2c\xa6\x2d\xa2\x5e\xb8\x9d\x77\x12\x51\xb3\xb7\x83\x52\x1e\xeb\x93\xe0\xed\xd0\x45\x7e\xa7\x7f\xea\xeb\x0b\x05\xc0\x27\x3e\xd1\x15\x40\x5e\x55\xb6\x3e\xff\x92\xdd\x57\x35\x0b\x80\xc0\x25\x33\x23\x58\x89\x35\xf4\x06\x22\xdf\xb6\xe7\xb8\xb5\xe8\x6d\x77\x7f\x0c\xae\xb7\xe8\x23\x2c\xe8\x7f\x2c\xb1\x43\xf5\x38\xe9\x96\x85\x9d\x57\x8e\xcf\x4f\x3d\xc4\xbb\xe2\x86\x18\xdc\x48\xf7\x1b\x37\xeb\xe3\x3d\xce\xb6\xc5\xcc\x1a\x3a\x2b\xd1\x0d\xe1\x93\x9e\x28\x4e\xe5\xac\x3c\xcd\xc2\x6e\x22\x5d\x3b\xd9\xac\xe1\x44\x0a\x0a\x0a\x2b\x87\x4d\x7d\x04\xb5\x59\x60\xd6\xe7\x2a\x4c\x10\x97\xe7\x76\x6c\x20\x00\x8b\x71\xc1\xaa\x87\x9e\x5a\x66\xa3\xfc\xb6\x75\x26\xad\xca\x2d\x7f\x98\xa3\x41\x38\xb3\x4d\xb2\xfb\xd4\xee\x80\xc0\x10\x1c\xb7\xe6\xea\xd6\xca\x36\x75\x0a\x74\x13\x10\x32\x69\x7b\xe6\x35\xf0\x95\xe2\xfe\x04\xc6\x6b\x10\xbe\x1c\xf7\xf9\x0d\x09\xc1\x76\x40\xbe\xbe\xe5\xd9\x4a\x67\x1d\x76\x3b\x31\x70\x68\xb7\x02\x04\x50\x02\x75\xda\x32\x5b\xeb\x70\x8c\x07\xbf\x43\x91\x95\x55\x6d\xa3\x97\x0a\xa9\x5e\x48\x85\xbf\x6e\xaa\x7c\x3a\xcc\x7d\xe5\xea\xf4\x4a\x08\x74\xa0\x1e\x38\xdd\xe1\x32\x45\x9e\xa4\xb0\x9e\x6c\x3d\xeb\x55\x2d\xbb\xd3\xad\x7d\xe8\xd5\xdb\x10\x93\x30\x15\x13\xe4\xc4\x73\xa9\x09\x2e\x3e\x51\xfd\x16\xa0\xa6\x1a\xcf\x78\xa7\xa0\x54\xae\xe6\x19\x16\x61\x37\x24\xee\x6d\x12\xfa\x7d\x1c\x89\x3b\x61\xc3\xbf\xff\x6d\x6b\x2e\xc4\x34\xd3\x1e\xdc\xe7\x37\xaa\xf1\xb6\x03\xb8\x4b\x74\xdd\x8b\x94\x42\xfb\x7b\xfc\x10\xde\xcf\x1f\xf3\x9e\xb9\x5a\x3d\xa3\x91\x7f\xfb\x2b\xf8\x49\xa1\x17\xfa\xa6\xe1\xe4\x97\xf7\x77\xf4\xfd\xe9\x93\x6f\x4e\xa9\x2e\xaf\x90\x52\xf1\x22\x6b\xae\x4f\x35\x68\xb2\xbc\x15\x61\xb9\xbd\x43\x95\x4b\x90\x30\x1b\x4f\xaf\x8a\xfd\x1f\x50\xab\x24\x84\x2f\xbb\x7b\x71\xcb\x75\x5b\xc1\x12\xd6\xc0\x5f\x66\xeb\x5f\x22\x2e\x90\x77\xe4\x79\x24\xec\x38\x29\x22\x6f\x58\x88\x3b\x33\xc0\x34\x5a\x27\xe4\xf2\x93\xa2\x47\x26\x9e\xac\xf4\x6f\xd9\xec\x35\x1b\xa0\xf2\x67\xc8\xac\x09\x5b\xe4\xed\x91\x82\x70\xae\x78\xa3\x24\x7e\x56\x6c\x59\x79\xd2\x3f\x41\x3a\xa7\x4f\x30\x4f\x2e\x3f\x49\x76\xc2\x7b\x05\xb1\xd7\x7e\x0c\x6c\x96\x7a\x5d\x25\xf2\xbe\xe0\x78\x81\xf9\xd5\xa4\xae\x31\x9f\x47\x32\xf5\xb2\x0d\xcd\xaf\x1e\xf7\x34\x60\x0b\x31\x77\xf9\xa1\xb3\xb9\x0f\x5e\xf8\x0e\xb1\x22\x42\xf6\x7e\xd9\xce\x3c\xd7\x8e\x6b\xd5\x68\xfa\x3a\xa5\xfb\xbf\x26\xf5\x39\x44\x83\xc9\x97\x1f\xfc\xd9\x40\x09\xf1\xba\x81\x49\xb8\xc8\xe2\x34\x3c\xec\x6c\x9c\x43\x22\xed\x60\xbf\xc8\x36\xe7\xfc\xa5\xc1\xde\x37\x16\xd0\x8b\x95\xec\xbd\x80\x7b\xef\x95\x85\xed\xa7\x3d\x56\x9f\x2b\xaf\x95\x0d\x60\x97\xe1\x54\x03\xf8\x7f\x0f\x55\x10\x30\xeb\x94\x8e\xa0\xb1\x73\x2a\x4f\xca\x8f\x1b\x12\xed\xbc\xb0\x74\x6a\x8d\xe1\xd4\x79\xe8\x32\x96\xcf\xa0\x8a\xc2\x7c\x2a\x05\x28\x54\x77\xd8\x6c\xa9\x64\xb6\xc5\x62\xe2\x6e\x51\x2f\xc8\xcb\x37\x5a\x5b\x9b\x69\x7d\x0f\x9a\x68\xc3\xad\x6d\x5e\x89\x9b\x57\xa3\x4c\xb6\x6d\xa7\x3f\xe4\x01\x2c\x2f\x6f\x6b\x6b\x02\x58\xc5\x46\x74\x06\xbb\x15\x02\x87\xb6\x13\xbb\xb1\x2b\x9d\x2d\xcf\xe4\x7b\x56\x9a\xaa\xba\x58\x37\x8c\x4e\x46\x64\x0c\xf7\x14\xfd\x17\xce\x33\x39\xc4\xc8\x91\x85\x56\xbd\xd1\x7b\x07\x5c\x8f\x14\xa8\x6f\xcc\x14\xac\x6f\x1f\xfd\xca\xfd\x97\x37\x2a\x0f\x1f\x3a\xc4\x5e\xcb\x2e\x66\x9d\xe2\x3d\x67\xf6\xa3\xad\x0a\x3b\x3a\x75\x50\x5b\xb0\x75\x9d\x2b\xcf\x5a\xea\xe5\x07\x50\x04\xc9\xee\xcf\xb8\xe5\x75\x7e\x28\x7b\x9c\xb9\xb4\xb7\xcb\xcd\xca\xfd\x9e\x08\x52\xa4\xfc\xee\xca\x91\xd0\xb3\x25\xa4\x3f\xce\x4c\xd8\xe1\x27\x6d\xa3\x4f\x23\x8d\xc8\x00\x1b\x38\xb4\x78\x0a\x80\xf4\x0f\x24\x1a\x4e\x3e\xc0\x7c\x92\xdf\x96\x5e\x1e\xb9\xaa\x1f\x79\x7e\x72\x07\xdb\x16\x89\x8f\xd7\xae\xdb\x99\x7c\xd6\x2c\x79\x2d\xae\x6e\xfb\xbf\x51\x11\xe9\xa0\xdf\x96\x42\xd3\x4e\xcf\x22\x6e\x0f\xf7\xfc\x06\x8d\x25\x3b\x54\x73\xd3\x03\x95\x11\x42\xd6\xad\x66\xec\x20\x3d\x33\xe8\x45\x58\x58\x99\x37\xa4\x57\x17\x0d\xf9\xc6\x73\x14\x09\xec\x94\xff\x12\x98\x69\x2a\x28\x2a\x2b\x22\x41\x43\x2e\xc2\xd5\xda\xa5\x18\xed\xb8\x2b\x9d\x3a\x8f\x82\x9f\xd3\x57\x52\x5e\x6d\x91\x53\x51\x4d\xc3\xc0\x9f\x18\x7a\x2b\x83\x0c\x2e\xa5\x20\xee\x73\x53\xda\xe6\x10\x21\xda\x46\x5d\xfe\xfb\x62\x5a\x78\x4c\xb7\x7d\x4e\xc8\xe2\x4e\x8f\x0a\x81\x01\x24\xeb\xd0\x70\x67\x76\x9d\x87\x45\x9e\x0c\xe9\x6d\x41\x7e\x44\xaf\x8c\x82\x50\x68\x23\xe3\xa2\x2e\xe4\x30\x6b\xb3\xc3\x0f\xc8\xe3\xb2\xa7\xc4\x6f\xe2\xb7\x6e\x8d\x7f\xf3\x3f\xef\xcd\xd6\xad\x6c\xff\x0f\x8d\x89\x2f\x15\x4f\x78\xbf\xf9\x24\x5d\x93\x0c\xd7\x4c\xa2\x60\x1a\x2e\x5c\x28\xa6\x50\x00\x82\x2b\x3a\x72\x6a\x7b\xd4\x78\x7d\x63\x4f\xfa\xee\xeb\xfd\x23\x56\x20\xa2\x06\xfb\x1d\xcc\xa5\x29\x9d\x3a\x0c\xcf\xee\x66\xa0\x9e\xa8\x28\xc3\xbd\xf2\x51\x1e\xea\xf0\x20\x1c\xf4\xc7\x80\xde\x2a\xa9\xca\x5b\xc3\xd5\xb5\x9f\x92\xac\xe1\x7e\xc4\x2d\x60\x68\xf8\xc0\x31\x29\x3a\xbf\x88\xc3\x05\x86\xd2\x99\x9c\x18\xb7\xc2\x6e\x0f\x40\x2d\xc8\xce\xdd\x81\xda\x27\x3e\x63\x13\x28\xb2\x9f\xf1\xef\xcf\x3e\x2c\xa6\xa9\xb1\x91\x55\x30\x8e\x2e\x51\x9f\xee\xaf\x7f\xee\xdb\x2f\x8c\xa4\x73\x55\x2a\xb6\x6b\xa2\xde\x91\x52\x31\x26\x26\x3b\x7b\x9c\x3d\x3c\xa4\x1e\x09\x51\x01\xa5\x16\xb5\x90\x64\xc3\x85\x52\x15\x18\x25\xa4\x95\x1d\xa5\xb1\x52\xaf\x09\xc0\xa4\xbd\xc5\xe2\xa7\x46\x40\x22\x12\x89\xce\xf8\x7a\x86\x86\x45\x47\x31\xe3\x4d\xeb\x7d\x3c\x2a\x3a\x51\xdf\x15\x35\x09\x83\xd5\x7a\x57\x9a\xc1\xa3\x0b\xd5\x9f\xa8\x90\xf8\x44\x16\x8b\x0e\xd7\x4b\x6a\x7e\x1f\xdc\x07\x5f\xbe\xf0\xff\x1f\x0c\x1e\xf3\xcf\xff\x0c\x81\xc2\x5b\x23\xa9\xd7\xc7\xcc\xe1\x10\xbc\x5a\x06\xb7\xee\xda\x2f\xc0\x84\x10\x39\x58\x4d\x46\x9d\xa8\xdb\x87\x7b\x12\xe0\xc1\xdc\x37\xf2\xfe\x1e\x02\xc8\x99\x90\xb1\x9c\xda\xa9\xe4\xf4\xcf\xe2\x1b\xb7\x2b\x8a\x05\x68\x86\xb3\xc3\xc3\xff\x73\x44\x66\x21\x21\x2f\xd7\xc5\xda\x79\xc6\xd9\x0b\x7b\xdc\xb8\xf4\xd0\x3d\xf5\xee\x67\x30\x3c\x89\x15\xcc\xef\x29\xe5\x38\xa0\x34\xb0\x07\x54\xec\x4d\xca\xa6\x7a\x6a\xb7\x5e\x4b\x22\x19\xc3\x7f\x03\xe2\x24\x4c\x9f\x2b\xca\xdc\x8f\xbf\x21\x5e\xa5\x86\x5c\x2a\x92\xfc\x64\x25\x5c\xc1\xff\x25\x1e\xa0\x8a\x4e\xb9\x18\xcc\x73\xbb\xe4\xc6\x24\x84\xcd\xcb\xf8\x5a\x1b\x96\x94\x3a\xcb\xbc\x18\x04\x8d\x86\x26\x85\x2c\x13\xc0\x74\x0c\x27\x55\xdc\x7d\x94\x7e\xb4\x23\xce\xce\xe2\x0a\xbd\x5c\x11\xe8\xb2\xe9\x80\xf4\xc9\x9d\xb8\x8c\x2f\x21\x2d\xec\x6d\x59\xc2\x56\xf3\x42\x2d\x45\x69\x38\xc9\xb7\x39\xac\xd0\xc9\x32\x3c\xc7\xc8\x53\x7e\x4e\x09\x4b\xdb\xa9\xc4\x70\xd3\x27\x87\xc3\x82\xa0\x87\x07\x80\x2a\x91\x15\xd6\x9c\xd6\x77\x63\x57\x46\xdf\xf6\x63\xa7\x1e\xa8\x9e\x4b\x3f\xc2\x5a\x41\x4a\x10\xd9\xc6\xba\xa5\x70\x37\xd4\xb7\xbc\xf3\x62\x20\xd1\x69\x87\xf8\xf6\xcb\x4b\x4c\xd2\x60\x5d\xc7\xeb\x67\xc9\x8e\x70\x24\x6c\x29\x87\x71\xfc\x0b\xb9\xa2\xc1\xb1\xd2\x8d\x56\xb1\x42\x1f\xa6\x43\x8f\x2a\x63\xef\x80\xfc\x4b\xaf\x69\x72\x7a\x7f\x21\x91\x33\xe8\xda\x87\xb6\x1c\xb6\xb3\x7c\x30\xe3\xdf\x46\xb3\x8a\x0d\x60\xf4\x07\x5a\x9b\x42\x04\x99\x51\x5e\x9e\xf6\x7a\x7d\x22\x21\xd5\xa9\x4d\x8f\xae\xf8\x72\x22\x0b\xbf\x5b\xde\x19\x52\xb2\x8c\x1a\xef\x91\xc0\x4d\x3f\xed\xc7\xf0\x0f\x86\xb8\x20\x13\xbd\x1f\x37\x96\xec\x0b\xe1\x09\x87\x64\x4c\x64\x1c\x48\x2b\x58\xd3\xe9\xf7\x54\x70\x9d\xbb\xb6\xf5\x97\x1f\x3b\x9d\x8c\xdf\xbb\x57\xb5\xcf\xcf\xdb\x33\x8f\x86\x6b\x3e\x6a\xfa\xa7\x57\x5d\xa0\x5b\xf7\x05\x01\xfa\xd1\x82\x97\x51\x54\x7e\xf8\x07\x37\x39\xb5\x45\x9d\x3c\x9b\x72\x05\x95\xa3\xa3\x6a\x4f\x02\x3e\xc2\x33\xaf\x53\xd1\xa7\x8a\x42\x30\x8f\x6e\x2b\xf9\x0f\x5c\x71\xc4\x5c\x58\x68\x1d\xc0\x3b\x65\x64\x91\x87\xe0\x49\xe6\x78\xf6\xe5\x36\xe5\x3e\xf1\xa7\x20\xa1\xa1\x58\x43\xa7\xfd\xa0\x56\x1d\x72\x01\x93\x70\x4e\xa6\x46\xaf\x13\x95\x4b\xef\x7c\x39\x39\x51\x50\xe7\x98\xf6\x1a\x62\x61\x2d\xfd\x7e\x0a\x24\x15\x02\x91\x47\x16\x6e\x58\x90\x80\x3f\x3a\x61\x2e\x70\x01\x66\x2e\x1f\x1e\x02\x0b\x21\xc2\xae\x43\xe1\x66\x88\x00\x84\xdf\x84\x5a\x0f\x24\xf9\xdc\xef\x80\xfa\xbe\x17\x0a\xea\xe1\xd6\xdd\x9e\x5c\xd8\x89\x6a\xb6\xb4\xab\x8d\x72\x76\xd2\x62\x9b\x31\xfa\xe4\xc0\x46\x34\x0b\x0a\x25\x42\x20\x10\x08\x1f\xb9\x42\x0d\x6b\x22\xbd\x72\xb2\x2c\x1d\x24\xa7\xf4\x24\xec\xc9\xfd\x5c\x89\x37\x4b\x95\xad\x35\xde\x73\xf7\xf3\x6e\x5f\xc4\x0c\xbe\xd1\x2b\xf5\xf5\xb1\xa3\x15\x76\xb5\xbd\xa7\x20\x8a\xf2\x50\x24\x92\xcf\xa9\x33\xcc\x2f\xa1\xa5\x18\x78\xbe\x1d\x3e\x4a\x82\x86\x61\x77\x2f\xcb\xf2\x54\xce\x69\xbb\x58\xea\x86\x46\x91\x4e\xad\x87\x29\x40\x1f\xd7\xcc\x1e\x1e\xd4\x85\x41\xfc\xa1\x02\xf5\xa4\x4b\x24\x72\x3e\xfa\x47\xd7\x6e\x63\x09\x51\xee\x52\x5d\x0d\xa1\xbf\x5d\x65\x5c\x15\x43\x20\x10\x77\x10\x5e\xea\xca\xba\xcd\x00\xf0\x91\x9e\xaf\x57\x36\xde\xaa\x7d\x4c\x42\x7c\xf9\xe8\xd2\xb1\x99\xa8\xb3\x36\x31\xf3\x9d\x52\x0c\x0d\xb4\xd1\x70\x6e\x3d\x92\x87\x0c\x1d\x0c\x62\x10\x94\x1d\x3e\x40\x6b\x06\xb3\xfe\x16\x44\xb6\x52\xd7\xd7\xc6\x8c\x42\x0c\xc0\x3c\x64\xeb\x16\x44\xcc\x4f\x4b\x9d\xe7\xde\x67\x7a\x4a\xeb\x32\x85\x6d\x6f\x05\xbf\xdd\x7a\x4d\x6e\x05\x45\xe7\x7d\x45\x4b\x47\xc0\x57\x94\xe4\xb7\x94\x48\xa1\x43\x83\x09\x69\xa7\xa2\xf3\x33\xb3\xb5\x05\x3c\x05\x49\x3e\xed\x4d\x19\x51\xfb\x81\x9b\x82\x6e\x85\x68\xe0\xee\xa9\x1e\x35\xeb\x30\xad\x16\x71\x62\x39\x6a\x0b\x43\x5f\xc0\x7e\x50\xea\x6f\xd6\xf5\xf0\x61\xad\x99\xca\x80\xc0\x31\xf0\x94\x3e\x62\xd7\xa9\x8a\x91\xd3\xdc\x69\xd6\x76\x86\xff\x9b\x36\x33\x19\x75\x5f\x08\x9c\xc9\x3b\x66\x6a\x1e\x03\xb8\x2f\x31\x27\x79\xb0\x19\x39\xb7\x44\x38\x9b\x61\xd1\x20\x05\xad\xba\x6e\x2b\x16\x2e\x5a\xc0\xf2\x18\x66\x71\xff\xb9\x3e\xc1\x5a\x0e\xcc\xc3\xf3\x54\x90\x9a\x16\xce\x9f\xce\xac\x04\xf5\x73\x36\xa7\xea\xe9\xcb\x1a\x0d\xd7\xee\x1f\xed\xa0\x77\xa3\x56\x0c\x1f\xac\x40\x29\xf8\xc1\xea\x08\x81\xf6\xe0\x77\x17\x31\xa8\x11\xfe\xbb\xb3\x60\xd2\x68\xef\x09\x03\xa6\x7c\x5a\x77\xb2\x90\x8b\xaa\x86\xf7\x55\xb3\xff\x69\xf3\xb7\x0f\x1e\x61\xae\x7f\x7b\xf8\x5d\xe7\xb2\xfe\x22\xaa\x97\x10\x35\x0b\x88\x58\xf7\x20\xaf\x4d\xf7\xa1\x44\x58\x66\x6c\x7c\x36\xcf\x62\xa6\xc9\x33\xcf\xd2\x5a\x1f\x3d\x63\xa1\x64\xf8\xc7\x86\x2f\xc0\xe2\x62\x57\x4f\xfc\xd0\xc5\xe2\xda\x67\x16\xc4\x4c\x20\x15\x0b\x0c\xd8\xc3\x81\x5e\xb0\x0c\x7e\xd0\x87\x6f\x94\x3b\x4c\x78\x9f\xd4\x30\x65\xb7\x5f\x08\xca\x5a\x9a\x92\x2c\x99\x90\xbb\x43\xc3\xb5\xdd\xb7\x25\xf7\x22\x98\xc4\x08\x87\xb9\x11\x28\x1b\x7b\xc1\x16\x9a\xcc\x3e\xd4\xed\x39\x82\x36\x07\x3f\xc2\xc1\x83\x04\xa5\x03\x98\xbc\x05\xfc\xfb\xef\x85\xe9\x43\x87\x8e\x60\x06\x19\x19\x2f\x87\xa0\xc6\x7d\xbd\x47\xd7\x28\x10\x01\x06\x3f\x04\xa4\x00\x11\x94\x0c\x9a\x5a\x69\xb4\x17\x09\xb9\x36\xfd\x6d\xfd\xf2\xb9\x09\x76\x7b\x4c\xaf\xc7\x33\xec\x5a\xab\x5b\x61\xa3\x90\x78\xb7\xca\xd9\xfa\x27\xb0\x39\x36\x12\x21\xa7\xb4\x31\xb6\x32\xb1\x17\x27\xe9\x70\xbd\xc0\xc8\xcd\xa5\xe6\x5b\xa4\xcb\x94\xc6\x1e\x29\xcd\x29\xb1\x4c\x40\xc6\x99\x56\x7e\x2b\x72\x98\x9e\xae\x32\x9f\xd5\xca\x91\x07\x6b\x6b\x83\xb5\x39\xf2\x03\x5a\xed\xe6\x09\x30\x4e\x47\xbb\x85\x86\xcb\x32\x83\x35\x72\xd9\x61\x51\x4a\x16\x0b\x0e\xc3\x23\xce\xfd\x7f\x2b\x8e\x16\x5a\xc1\x2c\xaa\x4f\xa8\xe9\xcf\x68\xed\x4f\x0d\xe8\x3a\xfa\x1a\xd6\x58\x15\x07\x3d\x60\xa7\x4f\xbf\xe6\x30\x88\xc1\x0c\x8e\x14\xdf\x8b\x1c\x1c\x8c\xbc\x57\x3c\xf2\x4e\x1d\xcc\x3b\xc0\xca\x7b\x5b\xb3\xbe\x1e\x9c\xfc\x1c\xd3\x65\x30\xc5\x5e\xb7\x47\xe7\xc8\xce\xdd\xac\xc0\x2d\x7b\x0c\x3a\xbe\x26\x1c\xdc\x96\xf5\x56\xa1\x16\x19\x4f\x1e\x3d\x74\x5d\x86\xf3\xbc\xb5\xc7\xd1\xf6\x34\xc6\x8f\x4b\x46\x7d\x31\x51\xac\x57\x01\x50\xca\x79\xe2\x13\x40\x4f\xa5\x7e\x6b\xf7\xf1\xa6\x5b\xef\x2b\x81\xb9\x63\x9f\x11\x0c\x04\xc0\x14\x44\x99\xc6\xca\xf7\xb7\xde\x40\xf9\x8d\x6b\x2c\xbf\x15\x55\x42\xd4\x23\xc5\xb1\x26\xd6\x72\x43\x8c\xb8\x65\xd6\x2c\xe4\x2f\x61\x74\x5b\x10\x58\x4f\x64\xeb\xd4\x9a\x7b\x2d\xfe\x40\xf2\x61\x0b\xa4\x14\x19\x69\x60\x20\x51\xee\xbc\x2f\xb0\x0d\xa2\x06\xa9\x42\x82\x58\xee\x18\x49\xf5\x48\x55\x88\x2c\x7d\xa3\xc8\xa4\x5d\xb4\x0b\x4f\x79\xaa\x2c\xae\xaa\xde\xed\xf4\xb9\x1b\x74\x47\x64\x08\x14\xb7\x8a\x9f\x2e\x40\xe7\x87\xeb\xbe\x84\x8c\xac\x00\xf6\x7d\xef\xdb\x80\xf9\xee\x1a\xc7\x0f\x39\x53\xad\x55\x12\xaf\x57\x00\x81\x21\x4f\xca\x1a\xa2\xd2\x95\xa4\xe9\x60\x68\xc0\xba\x3f\x9b\x2f\x98\x3d\x9f\xa4\xf3\x0a\x20\xf0\x6f\xc7\xf9\x22\xf7\x99\x1a\x06\x8f\x3a\x38\x82\xf8\x41\x36\x02\x56\x4b\xc6\x23\xa6\x91\x58\xae\x1f\xb6\x88\xa0\x89\x49\x71\xf4\x71\x8f\x4b\x85\x8e\xed\xdc\x79\x2c\xd1\xb8\x83\x3a\x5e\x50\x41\x75\x10\x7e\xdf\xdd\xf2\x5b\xb0\x01\xb9\x35\xa0\x80\xdf\x3c\x8b\x60\x64\x91\x99\x6c\x32\x75\xd8\xda\x1d\xff\x76\x0d\x36\x9d\x35\x62\xd2\xfd\x0b\x99\xc7\xad\xad\xb0\x81\x4b\xd3\xf7\x76\xeb\xfc\xed\xd1\x16\x8f\x6f\x0b\x88\x80\x8a\xae\xcb\x0d\x9d\x6f\x13\xa3\x99\x0a\x49\xd1\x90\xa5\x38\x10\x8a\xe8\x10\x30\x8a\xe8\xc8\x4d\x8c\xfc\xf9\xed\x09\x7f\x53\x7f\xc9\xd8\x17\x12\x4e\x1f\xf6\xfc\x05\x96\xd4\x26\x51\xfd\x25\xc2\xc2\xd9\xf8\xb6\xb6\x78\x5b\x1e\x22\xba\xa5\x3a\x86\x76\xcb\x45\x08\x62\x0e\x4a\xda\x93\xf5\x30\x90\x94\x4b\x22\x90\x60\xe4\x47\x7f\x5e\xba\xa4\xe0\x21\xf1\xdc\xbe\xf5\x14\x33\x23\x47\xb2\xcc\xc7\xfd\x8b\x57\x54\xa0\x62\xf8\x41\xc3\xbd\x27\x9a\xf2\xf8\xef\x34\x14\x49\xce\xc3\x49\x6f\xbe\xa1\x35\xf5\x4b\x40\xb3\x64\x29\xc6\xbb\xa2\x48\x39\x65\x57\x1a\x99\x60\x9c\xa3\x70\x92\x5b\xcb\xf1\x27\x3a\xed\xf1\x71\xce\x5c\x7d\xde\x01\x8e\xc7\x34\x3d\xee\xb0\x40\x44\x37\x7f\xe0\x5a\xc0\xf3\x13\x99\x77\xb6\x16\x59\x35\xe5\xe6\x9e\xde\xe9\x1b\x30\x14\x36\x93\xff\xbe\xd3\x98\xcd\xea\xd0\x92\x81\x20\xb4\x2a\x29\x03\xb3\xe8\xec\x80\xf3\x7a\xb7\x47\x16\xea\x53\x3c\x01\x2e\x46\x39\x22\xe7\xe0\x43\x61\xce\x21\x7a\x84\xae\xa3\x8a\x5b\xbe\x7e\xc5\x50\x3e\x9a\x92\xdd\xb4\x63\x03\x91\xd8\x5a\x42\xff\x8f\x62\xcc\x34\x6c\x1e\x10\xc2\x92\xd9\x9f\xe3\xdd\x73\x9f\x9d\xeb\x9b\xd4\xb3\xdc\xbb\x59\x89\x16\xa7\x81\x6a\x28\x4a\x95\xb4\xd5\x9c\x1b\xb2\x3a\x88\x71\x5a\x6f\x25\x39\x22\x20\x8c\x15\x9f\xc9\xe2\x85\x5d\x63\x2c\x3a\xb7\x5a\x72\x15\xf4\xa0\x50\x41\x3c\xd3\x05\x40\x70\x11\xc4\x2f\x8e\x22\xfb\x9c\xc6\xd4\x0d\x9f\x8f\x67\xcb\x5d\xbf\x5b\x75\x11\xb3\x6f\xc5\x57\x9c\x28\xbe\x41\xc7\xb8\x33\x61\x49\x83\x4c\x1c\x2f\xb1\x08\x8f\x29\x5e\x6a\xc1\x8b\x5f\x13\xd9\xee\x73\x13\x93\xc7\x3b\x91\x5f\x13\x22\xfe\x80\xad\xd5\x14\x4b\x95\x59\xb5\x09\x09\x6d\x11\xc4\x84\x9a\x22\xb8\x6f\x6a\xe9\xcd\x3d\x31\x48\xf6\x9e\x66\xc6\xce\xa4\x3b\x46\x20\xcf\xd9\x0d\x55\x5c\x56\x3e\xb3\xf0\x1f\x7b\xc0\xc5\x39\x59\x63\x36\x4a\x9c\x3f\x78\xde\xcc\x80\x57\xf3\x30\x4d\x2d\xab\xa5\x37\xd2\x1a\x1f\xd8\x99\x9e\xa2\xee\x48\x72\x56\xa8\x32\x0a\xb7\x91\x14\x1d\x49\xea\xb4\xee\x3c\xfb\xe0\x08\xeb\xe2\xe6\x28\xb7\xdc\xe6\xb9\x15\x06\xed\x0f\x9c\x0d\x35\x75\x79\x77\x6a\x42\x74\x85\xcb\xff\xe5\x1c\x8a\x06\x41\x91\xb0\xaf\xd6\x8f\x6f\x17\x0f\x86\xf5\x5c\x65\x1b\x33\x59\xe1\x8e\xfa\xb5\x4c\x5c\xee\xca\xba\x6b\x6c\x23\x73\xff\x73\xd0\xcb\x7f\x94\x0e\xcb\xaf\xcc\x1b\x14\x47\x13\x0e\xe8\x62\xff\x2f\x6b\xe6\xd0\xc4\x42\x5a\x30\x96\xf2\x72\x15\xce\x44\xb9\x68\x85\x44\xd8\x1a\x71\x39\xe1\xfe\x57\xeb\xf3\x9f\xd2\x7a\xb3\x43\x1d\x8c\x1d\x38\x20\x40\xac\xc9\x13\x00\xd3\x43\x17\xea\x05\x34\x91\x84\xb6\xe2\x9c\xf1\x15\x8a\x2e\x37\xa3\xc2\x55\x9b\x7b\x5f\xa7\x5c\xd1\x10\x80\x8f\x5f\x7d\x23\x21\x7c\x7a\x94\x28\x31\x32\xb8\x4f\x87\x8f\x9d\xaf\x04\xba\xb1\x64\xd9\x40\xfa\x43\x3f\xf9\x78\x37\xee\x0b\x4e\x2e\x3f\x79\x93\x6a\x76\x47\x43\xf4\xfd\x02\xe5\xd2\x8c\x8a\xb9\x22\x05\xfb\xca\x9a\x14\x59\xbc\x6c\x43\xaa\x60\xbd\x86\xc8\x32\xeb\x27\x25\x12\xc6\xf7\xec\x80\x62\x5b\x69\xdc\xab\x36\x87\x89\xe9\x68\x4c\x46\x92\x0a\xad\x19\x48\x4f\x5d\xbd\xfe\x84\x86\xde\xe7\xa3\x0d\x8d\x4d\x15\x9d\xe1\xee\x22\xdb\xdc\x55\xed\xd2\x31\x9f\x50\xe0\xd5\x0a\x0f\x5b\x10\xf2\x1e\xb9\x8d\x39\xaf\xb2\xa4\xc8\x13\x06\xfb\xfd\x96\xd2\xc2\x58\xac\x9d\x0d\x14\xb9\x7c\x55\xee\xaf\xb5\xea\xc3\x42\xd8\xf1\xb9\x1c\x89\xe9\x20\x53\x7e\x7a\x7c\x2e\xc2\x34\xfc\xd3\xef\x54\x50\xbe\x83\x7b\x2e\xf5\xa5\x62\x39\x8e\x70\xde\x79\xcc\x2d\xbe\x7e\x00\x5e\x7a\xac\xb3\x0a\xfa\x5c\xfa\xd6\x40\x15\x4a\xa8\xca\x58\x60\x6e\xee\x62\x10\x44\x57\x70\x6b\x0e\x39\x5f\x63\x2c\x1a\x3a\xb1\x32\xe3\x59\x61\x01\x11\x88\xca\x46\xce\xbc\xd2\xa6\xd7\xad\x14\x62\xd4\x31\xba\xfa\xf6\x44\x4c\x63\xf6\x61\xf5\x75\x22\xd2\x9d\x54\xe9\x54\x0c\x93\x37\x2b\x6f\x76\xfd\x04\x7a\xa0\x1f\xd3\x80\xc6\xa3\x0c\x3c\x8e\x6e\xcb\x73\x69\x44\x77\x1e\xd9\xa1\x2f\xb3\xc5\xa3\x07\xc3\xfa\x9b\xb1\xf0\xd5\x13\x33\x6d\x57\x2e\xc9\x7b\x32\x2b\x07\xd8\xa7\xac\xee\xcb\x74\x92\x17\x62\xf0\x80\x95\xc5\x4a\x9d\x82\x04\x96\x63\xd7\x0b\x04\x22\xea\xbd\xcb\x05\x39\x0b\xc5\xce\xc3\xe4\xca\x93\x19\x9b\xa2\xf3\x0b\xb9\xd3\x38\xe3\x6c\xc9\xad\x40\xb5\x9c\xd1\xa4\xcc\xa4\x25\xae\x3e\x69\xf0\xeb\x16\xfa\x8e\x05\xa7\x4f\x17\xe0\xf4\x01\x02\xc7\xc0\x81\xde\xd9\xdf\x14\xf6\x7e\x97\xd9\x7d\x24\xb9\xe8\xfa\x66\x7d\x65\xa6\xf3\xe7\x5d\xa6\xd4\xb7\x0e\xbb\xef\x39\x93\xa4\x39\x79\x32\xa9\x36\x57\x4c\xe2\xba\xff\xf8\xb7\x75\xe5\x53\x0b\x4d\x76\xfa\x89\xc6\xda\x71\xa1\xd2\x39\x74\xd9\x29\x69\x47\xd7\x89\xe3\xe8\x30\xa6\xce\xef\x87\x36\xf8\xf2\xa5\xa7\x47\x09\x2d\x30\x49\xe5\x00\x23\xc8\x17\x19\x75\xe0\xc9\x13\x31\x97\x8d\x7d\xc5\xad\x5b\x63\xb4\x02\xc1\x93\x7a\xa9\x94\xa1\x36\x12\x57\xc5\x81\x21\x2d\x70\x69\x3f\x16\x4b\xa1\xa4\xa4\x9c\x38\xfe\x27\x60\xb8\x50\x43\x72\x72\xbb\xf1\xec\x19\xd3\x13\xc7\xcf\x70\x5c\xfc\x8d\x9b\x42\x3b\xf9\x6b\x16\xc9\x03\x69\xfe\x85\x7e\x38\xd4\xdf\xaf\x49\x88\x87\x7b\x27\xd1\x44\x05\x89\xf1\x83\xd1\xf2\xca\xaa\xf1\x9c\x4a\xe0\x13\x22\x61\x6d\x40\x21\xaf\x42\x95\xb6\x53\xd2\x82\xb1\xb1\xfc\x20\x8f\x3f\x1f\x1f\x7b\xbe\xe3\x1d\x01\xe6\xc5\x82\x1a\x6b\x7d\xee\xa4\x4d\x71\xba\x57\x85\xc5\xce\x57\xde\x2c\x2f\xbf\xf5\x1b\xa0\x52\x2b\x4f\xd8\xec\x43\xfd\x5b\x12\xc6\xfc\x91\x59\x77\x33\x7c\x63\x7f\xf8\xcd\xc2\xfc\xe4\x6b\x3d\x7d\x0b\x51\xbe\xff\xb6\xdb\x63\x3b\x59\xa9\x34\xc0\xe5\xe2\x19\xfb\xf6\xce\xcc\x15\x87\x07\xfb\x65\x64\x36\x6e\xaa\x7f\x91\xed\x93\xfb\xda\xaf\x6c\x63\x60\xe3\xd7\x2c\xbd\xc9\xa9\xdf\xa4\x40\x15\x07\x0f\x37\x69\x4d\x8f\x91\x3d\x99\xcb\xe2\x47\x73\x9e\xad\x34\x67\x03\xea\xe7\x85\x25\xd6\x72\x47\x8e\x06\xa6\xdd\x70\xf4\x48\xea\xaa\x43\x1c\x03\x08\x35\x70\xbe\x23\xb3\x82\x53\x2f\xda\x9d\x2a\x91\xa6\xe4\x09\xcf\x93\x5d\x05\x36\xf2\x0f\x83\x1f\x1c\x7d\x17\xfc\x4e\xe0\x78\xfe\x9c\xbc\xed\xbb\xa1\xcb\xf7\xbd\xbc\x8d\x8b\xcb\x45\x72\xae\x50\x3f\x53\x72\xca\xee\x62\xb7\xfd\x8f\x4f\xd6\x1c\x7b\x16\x51\x80\xad\x70\x89\xc9\xd8\x68\x2a\x4c\xb5\xfe\xd4\x16\x0f\x62\xce\xfd\xef\x8e\xcc\xfc\x59\x0c\x53\xeb\x6e\xcb\x0d\x2f\xfb\x42\x5a\xfc\x3b\x0b\x7d\xd6\x6d\x7e\x39\x61\xb9\x34\xb2\x99\x1d\xac\xa2\x2d\xc2\x68\xac\x5b\x87\x0b\xb2\xd7\xf4\xe9\xcd\x8e\x1f\xcf\xad\x96\x4a\x24\xc5\x31\xb3\x05\x98\x00\x4e\xc7\x26\xcd\x7c\x27\xbb\x63\xc7\xe4\xac\xa5\x2f\xca\xba\xe9\xe7\xfc\x26\xe1\xa7\xa5\xb3\x2c\xa7\x1a\xb9\x2f\x9e\x39\x34\xec\x9d\x0a\xe2\xb3\x67\x87\x91\x29\x19\x5e\x44\x06\x14\x82\x0e\x08\xc7\x2f\xad\x15\x50\x22\xb8\xdc\x88\x45\x64\xd3\xbd\x0b\x1f\x26\x1d\x08\x53\x23\x96\xd5\x02\x70\x4b\xa0\xc8\xef\x80\x44\x1e\x98\xdb\x01\x44\xfc\xa4\x0a\xfb\xc8\x9a\x0b\xfc\xf0\xea\x1a\x4d\x88\x39\x42\xd6\xc5\x34\x47\xe1\x1e\xf3\x65\x40\xf1\x66\x8e\x7e\xde\xbb\x3b\x03\x61\x7e\xb7\x57\x4f\x6b\x0a\xd7\x43\x4c\x01\xe8\xf1\x8e\x20\x54\x86\xe7\x95\x7c\xa0\x3b\x96\xdd\x76\xe8\x29\xe2\x90\xb3\x61\x48\x16\x92\xb7\x0c\x96\xc0\xb9\xf0\x7a\xae\x3d\x6c\x79\x4e\xfa\x14\xa2\x53\x5e\xfa\xeb\x06\xdf\x78\x47\x87\xe9\xaf\x30\x18\xaa\x05\x66\xdf\xc6\x78\x21\x65\xb8\x03\xc6\xb8\x2e\x9a\x39\x95\xa6\xc0\xe2\x5c\x28\x0a\x07\xff\x28\x6e\x6f\x41\x69\x4f\xf9\x40\x75\x74\x3a\x29\x93\x53\xd8\x50\xd6\x55\x36\xbf\x26\x2a\xbd\xdf\xf6\x42\xf2\x76\xf5\xdd\xed\x70\x0c\x46\x7e\xb3\x5b\xc5\xc3\xc1\x1a\xba\xa3\x40\x0e\x8b\x08\x87\xe1\x1c\x5d\x1c\xdc\xcf\xed\x4a\x81\x15\x18\x98\x61\x30\xc8\xc8\x64\x54\xa5\x78\xcd\x8a\x5a\xad\xd0\xa1\x0b\x8d\x98\xe4\x71\x1c\x30\x2e\x8e\x57\x32\x76\xe1\xcd\xf7\xc2\x31\x68\x64\x8d\x2d\x43\x5a\xf1\xa4\xbf\x56\xd5\x41\x40\xb5\x47\x84\xc3\xb1\x7c\x67\x3b\xee\xe5\x3d\x19\x45\xd6\x18\x34\xca\x27\x4b\x3c\xfc\x40\xad\xba\x7c\x08\x8b\x98\x34\x5e\x80\x71\x09\x7c\xe5\x5c\xe5\x7f\xfb\x86\x56\x15\x1f\xe2\xed\x1b\x9f\x31\x70\xa0\x0f\x25\x5b\xc6\x23\x53\xd4\xef\xe0\x23\xec\x46\xe9\x8b\xfa\xe2\xf7\xcf\xd8\x23\xb2\xa8\x2d\xa6\x43\xa4\x49\xf1\xda\xcc\xed\xcc\xa5\xbe\x2b\x5c\x16\x29\x2c\xed\x57\x79\x79\xf2\x3a\x23\xec\xdf\x73\xed\xf7\x51\xa5\xbc\xa8\x98\xe5\x50\x5e\x3c\xf1\xf2\xdf\x45\xfe\x2f\xeb\x50\x98\x9e\xac\x94\x4e\x79\x87\x84\xba\xf3\x88\xff\xdf\x9e\x92\x3f\x29\x81\xe8\x65\xc0\xfd\x53\xfd\x92\x7f\x62\x3a\x09\x6a\x1e\x77\xa5\x6e\x61\xa6\x8d\xd2\xee\x5c\xb8\x54\xc7\xf7\x5d\x6e\x3e\x2c\xb2\xe6\x4a\x7a\xa3\xbb\x8d\x46\x20\x22\xe7\xa9\xbc\xa2\xc6\xb9\x30\x2d\xbc\xc9\xe1\x68\x8b\x00\x87\x96\xfa\xcb\x71\xf3\xb4\xb3\x28\x42\x3f\xd6\xe9\xe6\x5a\x08\x7b\x29\xb2\xb1\xcb\x36\x7b\xb3\x6f\xab\x8d\x9b\xdd\x94\xee\x98\xda\x32\x57\x43\xc1\x06\xdd\x74\xcb\x8b\x82\xdd\x67\x82\x35\xf3\x54\x38\xbe\xc3\xf6\x8e\xb0\xbe\x2c\x2b\x4f\xcd\x65\x30\x1b\x48\x55\xe0\xdc\xba\x07\xb7\x76\x52\x72\x41\xd6\x44\x8f\x0d\x99\xa7\x36\x91\x86\x12\xdb\xc5\x99\xa9\xff\x21\x16\xe8\x02\x04\x86\x44\x29\x6e\x3a\xa9\x9f\x6e\x63\x09\xa5\x61\x8b\xea\xb5\x3d\x32\xb6\xdd\xab\xef\xea\x1d\x77\x73\x39\xf4\x4f\xdd\x59\xd8\x56\x40\x5e\x8d\xe3\x58\x49\xfb\x03\x7b\x2b\x8b\x12\xea\xfb\x0b\xd5\x23\x96\xe7\x62\x9f\xae\x9e\x89\xed\xb7\xaa\x57\xf5\x16\x1b\xa0\x79\x15\x2b\x02\x40\x25\x0d\xb1\xaa\x30\x2e\xb9\x7b\xba\x27\x7e\x7b\x64\x84\x7a\xd2\x72\xed\xd3\x2f\x11\xdd\xdb\x8e\x6c\xf3\x7f\x9e\xbf\xe5\x9d\x4c\x8d\xfe\x18\x2a\x62\xdb\xd9\x64\xd2\x5f\x07\xbd\xbf\xa0\x12\x9c\x0e\x45\x63\xbd\x66\xff\xd7\xee\xe1\x15\x61\x93\x22\xc3\x73\xd8\xb5\xe2\x2d\x09\xfb\x9d\x76\x05\x14\xe7\x24\x95\x0e\x39\x35\x86\x5d\xdc\x26\x2c\xa7\xcc\x8b\xdf\x50\x17\xac\xcb\x4c\xae\x59\xe1\xdf\x24\x38\xf0\xc0\xa0\x3e\xf6\xd2\x0f\xd1\x3d\xf8\xc2\x5b\xc7\xd6\x77\xdc\x3c\x06\x2a\x09\x43\x18\x7e\xce\x24\x02\x5c\x98\xa5\x9e\x59\xc9\x59\x37\xff\x9b\x57\x24\x59\xe1\x93\x7f\xb1\xac\x5e\x90\x9c\x71\xe2\x46\x25\x45\x85\xd6\xd9\xd7\x41\xd3\x14\x57\x13\xb2\x51\xa9\x14\x37\xca\x7b\xd5\xf0\xe8\xad\xd1\x45\x48\x32\x87\x43\x06\xe6\x29\x43\xda\x1b\x8e\x75\xcd\x94\xbc\xe7\xfa\x12\x2e\x77\x39\x41\xc5\x59\x14\xc8\x93\x92\x4b\x9a\xb1\x12\xd6\xff\x81\x9c\xb8\x63\xea\xeb\x99\xeb\xc9\xe7\xe5\x64\x0a\xd1\x49\xcc\xa3\x97\x3c\xe5\x1b\x0c\xf1\x8e\xd7\xe3\x1d\x77\x82\x94\x1a\x54\x50\x4e\xe5\x90\xfd\x08\x77\x62\xb2\x8f\xbb\xd4\xa1\xbc\xa2\xb2\x22\x7e\x48\xa7\xd0\x36\xc8\x36\xca\x5f\x02\x10\xde\x30\x77\x6e\x44\x4b\x41\x41\x4e\x8e\x91\xde\x65\x39\xb8\xbe\xce\xd2\x18\xa9\xd3\x69\x46\x56\x67\x04\xb4\x3f\xfc\xf8\xac\x0f\xc2\x23\xc0\xd1\xde\x7c\x9f\xcf\xe7\xda\xe0\xd6\xbc\x5e\x0e\x32\xa5\x7c\x88\xc5\x9a\x7b\xe8\x84\x41\x26\xf0\x58\x10\x84\x7c\xb4\xe3\xac\x5b\x51\x68\x59\x88\x5e\xa1\x90\xcb\x6f\x47\x7c\xbe\x9d\xe1\x23\x57\x2a\x83\x8a\x66\x65\x60\x2d\xc6\xde\xa3\xac\x5c\x06\x07\x16\x00\x85\x36\xc6\x69\xf5\x85\xcb\xba\xaf\x2e\x74\x75\x2f\x5e\xed\xb2\xd1\x1e\x79\xfc\xf9\xe0\xb5\x6b\x41\xa8\x94\xf5\xed\xc9\x05\x02\x1e\x9f\xaf\x2f\xe1\xcb\x99\x82\xd4\x35\x99\xec\x6e\xd1\x6e\xd7\x9e\x7a\xd7\x5d\x31\xe7\xda\xda\x5a\x5b\xcf\x9d\x6f\x6d\x15\x56\x39\x35\x0f\xcb\x85\x08\x5f\xe1\x36\xe3\x9c\x09\x65\x5e\xe5\x5e\xc1\xcf\x21\x4d\xe5\xea\x1b\x19\x06\xcd\x4d\xb1\xfd\xe9\x48\xa1\x08\xd1\x87\x56\x78\x5d\x6d\x24\xef\xda\xd5\x8f\x91\x4b\x4a\x4d\xcf\x0f\x34\x46\x2d\xab\x97\x18\x6f\x51\xeb\x43\x1b\x9d\xaa\xb6\xda\x32\xd1\xc7\xed\xb3\x06\xba\x33\x71\x2f\x83\x54\x9f\x5d\xbd\x29\xf1\x1d\x16\x3c\x36\x2e\x6a\x78\x6f\xbf\x2f\x7c\x43\x41\x5e\xa6\x5b\x63\x42\xea\x32\xa9\xe3\x7c\x41\x09\xb9\x7b\x6f\x7f\xd0\x31\xad\x95\x4b\x7b\xf1\x06\x32\x41\x15\x60\x4f\xad\xf1\x0c\x1b\x46\x38\xbb\xc2\x3b\xa7\xd5\x27\x20\xbe\x8b\x39\x12\x04\x12\xc6\x80\x40\x62\x52\xc3\x5d\xee\x94\xa3\xca\xb7\xd1\x71\x2c\x56\xda\x6f\x17\x9f\x3c\x2a\xf0\x92\xfa\xf8\x6c\xbd\x11\x5e\x94\xdc\xab\xb5\x18\x51\x63\x54\xa4\x8a\x5f\x14\x91\x14\x35\x3f\x24\xb3\x55\xd8\x10\x30\x5f\x39\xd7\x8a\x20\x66\xc9\xd1\x29\x16\xfc\x03\x1c\x86\x12\x43\xc2\xc5\x05\xd7\xa5\x95\xb4\x29\xa7\x8c\x0b\xf3\xd7\x99\xe8\x84\x50\xa6\x5b\x22\x71\x2c\x36\x99\x17\xc6\x0a\x16\xba\xa8\xdd\x3c\x73\x1e\x5a\x8d\x6d\x4e\x76\x2e\x0d\x83\xb2\x81\x2e\x27\xa0\xeb\xba\x0d\x1f\xd4\x9c\x96\x11\xb9\xdf\xd5\xfc\x7d\x39\x89\xb5\x50\xcc\x82\xbc\x24\x0d\xfc\xb9\xc8\x68\x3f\xfa\xf7\xea\xcb\x83\x1b\x32\x3d\xf7\xf3\x82\x2b\x0b\x2e\xc5\x23\x47\x3d\x77\x4f\x93\x99\x1c\x47\x3e\x84\x23\xcc\x61\xc8\x00\xe6\xea\x9b\x00\x63\x64\x24\xa0\x5c\x1e\xc7\xd9\x80\x87\xee\x9d\xf8\xb5\xef\xdd\xbb\xfa\x8a\xe1\x67\xe3\xb5\x79\xb4\x5a\xba\x67\x8b\xeb\x76\x8c\x62\x9f\xbc\xf7\xd4\xb7\x61\x7a\x02\x38\x16\xa9\x7b\xc8\x9b\x7d\x0e\x42\x68\xd2\x41\xb7\x7b\x6d\x44\x03\xfe\x86\xae\x85\x85\x2e\x83\x1c\xf4\x27\x2a\x4b\xb8\xdb\x4f\x1b\x69\x6b\x3b\xa2\x9d\x44\x20\x96\x23\x99\x13\x81\x80\x9d\x1c\xae\x2f\x00\x68\x90\x86\x90\xba\x3b\x93\x40\x1a\xff\xe0\xc2\xb1\x0d\x21\xf4\xdb\x2b\xff\xda\xab\x0e\xcc\x2d\xb2\x16\x63\x9c\x6b\x6e\x2e\xfa\xcb\xef\x76\x19\x96\x24\x3f\x3a\x8b\xef\x89\xa6\x81\xef\xdc\x97\xdf\xc5\xc0\xfe\x62\xc7\x7b\xdf\x13\xcd\x61\x7a\x03\xc0\x4b\xc0\xc3\xea\xde\xa3\x64\x99\x47\x6b\x79\x56\xd6\xb6\xbc\xc1\x85\xa7\x5a\xf9\xaf\xcd\xa5\x3a\xb7\xcc\x27\x5a\x8e\x15\x73\x67\x9b\x2e\x02\xbb\x01\x4f\x5c\x17\x2f\x2b\xdf\x69\xfb\x2e\x84\xa5\x35\x6a\xca\x3e\x28\xa1\x8e\x0b\x3d\x82\xff\x3e\xf2\x08\xcb\x76\x1e\x0a\xdb\xf4\x77\x3d\x37\x5c\x83\x34\xbe\x1f\xd9\xe0\xdf\x88\x79\xf1\xfa\x7e\x29\xd8\xc9\x71\x19\x4e\x4b\x01\x02\x17\x02\x73\xa9\x73\x7e\xf2\x39\x7f\x3c\xa2\xd8\x0b\x6b\x0d\x9c\xe0\xb7\x7b\x64\x01\x86\xa6\xdf\xd6\x6f\xf9\xc3\x9e\x3b\x9f\xb5\xc7\x5a\xe8\x8d\x84\xb0\x04\xe6\x41\xc4\x52\x89\x34\xa7\x76\x72\xc3\xad\x4d\xcd\x81\x96\xd1\xb2\xf9\x12\xca\x80\x9e\x97\x8b\x26\xf2\x5f\x3e\xb5\x70\x3c\x61\x5c\x26\x10\xdd\x52\x16\xf3\x5f\x71\x9f\xbf\xcd\x6f\x0d\x40\x58\x22\x50\x5d\x54\x55\xde\x30\x79\xbf\xe8\xbe\x76\x19\xe0\x76\xb4\x0b\x77\xd6\xea\xfd\xa5\x74\xca\x5d\xe5\x55\xd5\x97\x16\xed\x69\xdf\x0b\x87\x3c\x15\x43\xd3\xe2\xf1\x69\xae\x78\x3d\x63\x31\x76\x37\x39\x8a\x28\x66\xf9\x0a\xec\x4d\xea\x6b\xf3\xda\x84\x3a\x93\x27\xda\xaa\x0a\xbb\x49\xea\x8a\x0c\x95\x06\xf7\x60\x7c\x79\xce\x08\x39\x44\xed\xbc\xa6\xf1\x35\x92\x6e\x8e\xf0\x55\x0e\x3a\xba\x43\x2b\x2f\x3e\x39\x55\xc7\x46\x28\x23\x65\x49\x94\x7c\x95\x4b\x21\xba\xda\xe1\xd0\x92\x93\x6c\x30\xa8\xa4\x33\x36\xb1\xd9\x6e\xc7\x4c\x47\x97\x65\x2a\x36\x4e\x65\x0d\x2f\xcb\x8c\x1a\xed\xd4\x8e\xd7\xc5\xaa\x6a\x6a\xd5\x9a\xe3\x77\xfa\xb4\xad\xf3\x65\xf5\xc5\x37\x72\x7c\xd1\x82\x90\xe0\x84\x94\xe4\xd6\x94\x94\xd6\xe4\xe4\x04\x99\xa8\xe8\xae\x9e\xec\xdd\x0d\x83\x41\xea\x9a\x5a\xcd\x53\xaa\x43\x72\x0a\xd6\x94\x42\xe3\x49\x9b\xb2\x6e\x74\x87\xda\xd6\x7e\xb5\x2d\xcd\x23\x5a\xe3\x56\xbb\x7f\xbb\xda\xc8\x76\xfa\xd6\x1d\x1b\x4c\xb2\xac\x42\x01\x1b\x72\xf9\xa7\x22\x39\xc5\x97\x35\x9e\xd8\xc3\x39\xe0\x1e\x80\x38\x56\x06\xbe\xea\xb8\x78\xac\x07\x68\xea\x5f\x64\x5e\xcb\x3a\x93\x7c\x78\x6d\x57\x01\x28\x9f\xb7\x7e\xab\xdf\x0d\xfa\x4d\xea\x79\x81\x2b\xa5\x29\x23\x12\x25\xca\x82\xb5\x99\x1f\x75\xfd\xaa\x85\x9d\x82\x7e\xde\xaf\xbe\x16\xfb\x87\xd1\x89\x8b\x2a\xb7\xf4\xa4\xb7\xc5\x4b\x13\xa3\x94\x58\x8e\x83\xaf\xef\x3c\xf8\xcf\xd1\x67\xab\xfb\x37\x00\x7c\x60\x10\x80\xcd\xda\xd6\x7a\x12\xb0\xc6\x48\x30\x95\x1c\xb4\xcf\x69\x6b\x59\x98\x3d\x32\xc7\x16\x16\xe4\xe1\xef\xfb\xe5\x6e\x0d\x5f\xfb\xd7\x75\xff\x58\xbf\xfe\x47\x57\x56\xd2\xb9\x8e\x8e\xb3\x81\x59\x5d\x2f\x4b\x3c\x4a\xee\x54\x64\x6e\x16\x9d\xb8\xb8\x59\xb3\xed\xe6\xf5\x4a\x4d\x36\x40\xe0\xe7\x72\xdd\x8d\x9c\x1b\xf3\x4e\xfb\x62\x6a\xbe\xef\xd3\x44\x1d\x38\xb5\x7c\x20\xcd\xc2\x27\xe4\x2b\x5e\x0e\xb7\x6a\x8d\x8b\x74\x7d\x8c\xf3\x07\xfb\xce\x81\xb4\x62\x46\x41\x47\xc4\x8a\x90\xa4\xbd\xcc\x83\xf9\xe9\xa2\x2f\xaf\x9d\x63\x96\x44\xa7\x3b\x27\x66\xb4\x7b\x73\x88\x29\x79\xb1\xc0\x18\x27\xfa\x09\xf9\x4b\x31\x37\xb4\xfa\x93\x45\xe5\xd3\x6d\xfa\xe8\x98\xb7\xd2\x94\xd3\x7f\x1b\x6b\xe1\x3c\x23\xfa\x04\xeb\xfd\xaf\xe1\xea\xa8\x8f\x53\xd4\xf8\x49\xb8\xc0\x56\x90\x3a\xe0\x09\xc7\x65\xf0\xf8\x1b\x38\x1e\x5a\x99\x28\x74\x20\x69\xbb\xf7\x40\x3e\x06\xf6\x38\x5b\x84\xe6\xc0\xeb\x34\x58\x4c\xef\xfd\xf0\xfb\x87\x7b\xa2\xc0\x4a\x2e\xfe\x17\xca\x14\x2e\x0a\x35\x7c\x45\xbc\xcf\x5e\x5d\x73\xd2\x9d\x63\x9d\x43\x11\x7e\xe9\xe1\x1b\x07\xd8\x12\x4c\x40\xfe\x21\x3d\xe1\x49\xa5\x14\x17\x75\x7f\x7a\xea\x6d\x0e\x9a\xca\x90\x5e\xbd\xdb\x49\x55\x3a\x94\x10\x80\xe9\x98\x6c\xd1\x63\x50\x25\x00\xdb\x37\xf0\xec\xad\xcd\xb6\xed\x4e\x3e\xb5\xd9\xb6\x6d\x6f\x9b\x6b\xdb\x6c\x9b\x9b\x6d\xdb\xd6\xc9\x6e\x33\x4e\xb6\x7b\xe7\x79\xef\x79\x66\x9e\x0f\xf7\xef\xeb\x35\x73\xe9\x6f\xfe\x15\x33\xb8\x15\x8d\x61\x82\x0a\x34\xe1\xb0\x86\x62\x8d\xaf\x1b\xb2\xb9\xf4\x1a\x16\x58\x5d\x71\x84\x53\xe9\x88\x78\x3e\x76\x22\x5b\xbd\x8a\x4f\xa2\x8b\xfa\x0c\x7c\x01\x11\xd2\x20\xe7\x09\x69\x0b\x30\xaf\x01\xe3\x7e\xd9\x89\x4d\xd0\xbf\xe7\xe5\x20\x13\x5a\x3a\xf0\xad\x6d\xce\xe7\x49\xdc\xa5\x9c\x5b\x1a\x12\x13\x14\x5c\x87\x30\x2b\xac\xa4\xca\x4e\x1e\x0b\x5d\x72\x39\x31\xb9\xa4\x4d\x26\xfe\xb5\x31\x0c\xd4\xd6\xb7\xd7\xde\x6e\xdc\xdc\x48\x0a\x4d\x48\x4b\x43\xf3\x61\xe6\x0f\xa8\xc9\x69\x38\x1c\x7c\xbb\xf8\x38\xd6\xf4\xc1\xda\x43\x5b\x07\x02\x1f\x68\x36\x51\xef\x18\x8c\x6c\x9e\xaf\x6b\x13\x0d\x0a\x86\x0b\x44\x5a\xe3\xfb\xf7\xd5\xfd\xd1\x37\xf9\xf0\x7d\xa6\xce\x89\x35\x9a\x9c\xab\xdf\x15\x3e\xd6\xb4\x89\x57\xe2\xff\xc2\xda\xbe\x0e\x8d\xab\x9d\x66\x95\x6b\xf1\xf3\x5f\x81\x44\x34\xb1\x92\x34\xd7\x7a\x6a\x2b\x84\x98\xbb\xbb\xfd\x8c\x2c\xde\xb2\xf6\xbd\x50\xa1\x7d\x22\x87\x62\x73\x0c\x7b\xad\x48\x16\x6d\x2c\x8f\xad\x4f\x6c\x0b\x5c\xd1\x52\x17\x6b\x50\x72\x6e\x57\xd8\xe8\x22\x46\x3d\xb0\xf8\xd8\x1a\x63\x8b\x7c\x8e\xd4\x97\x99\x94\xd4\x77\x05\xfd\xbf\x45\x46\x8e\xa1\xa0\x63\xc4\x0a\xcf\xb6\x6a\xe3\x69\x6a\x63\xcf\xe1\xe6\xe0\xd5\xf1\x76\x35\x1a\xfe\x9c\xa9\xa8\xba\xe9\xca\x18\x62\xad\x4e\x2f\x2a\x0d\xf5\x42\x6a\x95\x24\xa1\xe9\x4b\xa0\xd2\x95\x1f\xba\x80\x2e\x3a\x18\x8b\x23\x17\x47\xd8\x3b\x1a\x81\x9f\x90\x76\x9c\x0c\xe2\xdd\x75\xa8\x1f\x27\xc1\x68\x5d\x3e\x91\xef\x88\x7f\x69\xe5\x8f\x33\xbf\x90\x85\xa1\xad\x20\x87\x33\xd3\x07\x2e\x08\x8e\xb4\xf8\x0d\x11\xf5\xc6\x8a\xf8\xed\xee\x10\xcf\x40\x6c\x8f\xaf\xcf\x1c\x81\xb6\x02\x91\x28\xa0\x68\x77\x7d\x7d\x27\x39\x5e\x8c\xfc\xea\x9e\xb5\x10\x39\xf9\xd3\x0f\xc0\xe5\xf0\xf9\x7e\x3c\xf4\xda\x4d\x2c\x6d\xa7\x7f\xc2\xd3\x64\x92\xa0\xf2\x2a\x2d\xa2\x1d\xe0\x86\xb3\xa6\x21\xf4\xe6\xf8\xb7\x73\x70\x5b\x8f\x5c\xc3\x1d\xaa\xa2\xe5\x29\xad\xcd\xc9\xd2\x53\xcd\x0c\x9d\x8a\x7f\xa3\x97\x40\xe4\x0b\x80\x78\x76\xfb\x76\x23\x4d\x16\x9f\xc9\x1d\xaa\x9e\xf0\x9a\x17\xe4\xd7\xd5\x22\x42\x88\xf7\x91\x84\x53\x1d\x87\x26\x14\x99\x3b\x8e\xae\x21\x6c\x69\x37\xf9\xf0\x7e\x28\xbf\xfc\xd8\xd9\xa1\x00\x2c\x51\x13\x51\x94\x4c\xcd\xca\xe6\x09\xde\x47\x25\xed\xa2\xc2\x62\xe9\x96\xd6\xee\xd0\x47\x23\xf9\x95\xc2\xfd\x40\xdc\xd3\x83\x54\xfb\x08\x8e\x7c\xb9\xb7\x5a\x4c\x32\xa7\x0e\x4c\x28\x24\x02\x7c\x5b\x53\x6a\x40\x56\xc8\xff\x8e\xe5\x60\x79\x93\xa5\x1b\x63\xae\x02\xec\xbf\x2d\xe5\xb5\x4b\xce\x9d\x3b\xfe\x56\xd7\xc8\xab\xb9\xf7\x9b\x60\xce\x56\xab\xb3\xd3\xc7\x7b\x1d\x02\x29\x89\x9b\xb0\xdd\x7b\x29\x38\x21\xf9\xe6\x2b\xc0\xd2\x92\x83\x1c\x2d\xc8\xe0\x4e\x76\x18\x0f\xd0\xf1\x9e\x76\x71\xc8\x39\xb2\x03\x09\x25\x36\x12\xc2\xa1\x0c\xdf\x7a\x75\xbf\xcc\x54\xa6\xe0\x11\x1e\x37\xda\x9e\xb7\xb2\xcc\x40\x5f\x5e\xce\x2d\xbd\x7a\xfa\x72\x87\x97\xdf\x47\x0d\x49\xe6\xf6\x87\x6f\x3e\xee\xe7\xa5\xcc\x8d\x3a\xb2\xf4\xd1\x38\x2d\x2c\x42\x04\xaa\x3f\x51\x21\x9c\x8d\x59\xd8\x96\x1c\x24\xce\x06\x11\x45\x87\xbf\x76\x1d\x58\xc8\x5f\x4e\x3a\xdf\xf0\x94\x5c\xe9\x1d\x02\x06\xdf\x85\xe6\x13\xe9\x80\x22\x92\xc0\xb0\xe6\xf9\x36\x40\x8d\xcf\x8c\xc1\xde\xf8\xe7\xf8\x59\x20\x3b\x47\x07\xc7\x84\x4a\x88\x39\xce\x0b\x8a\x08\x41\x5f\xef\x9a\x2e\xfb\x9c\x62\xea\x57\xa1\x1e\x12\xff\x67\x59\x7c\x95\xb4\x7e\xff\xd4\xcf\xcd\xd0\x39\xa8\x7d\x82\x93\x20\x31\x8b\x34\xb5\x2a\xb5\x6b\x55\x5f\x71\x9c\x49\x54\xec\xbd\x78\x6d\x09\x31\x2f\xf3\xd3\x20\x6b\xe7\x5d\x3e\x11\x38\x08\x41\xba\x17\xc6\x97\xbb\x9d\xe7\xad\x31\xaa\xa9\x0c\xae\x92\xbe\x61\x01\x16\x7c\x3e\x70\x74\x14\x3d\x77\xc6\x93\x79\xa9\x05\x7e\xb1\xdb\x4a\xab\x37\x15\x64\x6f\xc3\xce\xa7\x46\xd6\x8a\x25\xe9\xd9\xd6\xdc\xbc\x4f\xc0\xe7\xa1\x20\xcd\xd6\x2f\x84\x79\xaa\x64\x84\x82\x53\xd3\x5b\x7a\xb9\xde\x40\x64\xad\xbb\x88\x03\xf5\xaf\xfa\xa9\xdb\x1d\x0c\x0c\xd5\x0e\x5e\x9d\x7e\xdb\xa4\xe2\x17\xda\xf2\x2e\x60\x80\x9c\xa1\x94\x56\xe0\xaa\x4f\xba\x13\x2a\x35\xef\xe5\x5d\xf4\xcb\x92\xb9\x47\x33\x7c\x61\xc3\x60\x40\xf3\xb4\x2c\x18\x1e\xce\x6a\x53\xe1\xdd\x1b\x91\x93\x25\x3b\x12\xa0\x36\xad\xf7\x61\x58\xe6\x18\x06\xec\x5f\x2c\x84\x9e\x83\x8c\xb4\xef\xd9\x9e\x16\xe3\xcb\xd7\x36\xef\xc5\x9c\x17\x03\x12\xc1\x24\x4e\x72\xfb\xb0\x3e\x0e\x5c\xa4\x4c\x9d\xfb\xb0\x5e\x6e\x2c\xf9\x0c\x90\x0d\xe2\x70\x88\xfb\x88\x7f\x73\x3f\xf6\x70\x8a\x3e\xad\x1d\x3e\xfb\x9a\x2a\x45\xfb\x47\xf8\x27\xfe\xdb\x7d\xe0\x7b\x80\x18\x91\x6d\x96\x59\x28\x38\xf9\x65\x55\x7d\x93\x72\x2c\x13\x65\x03\x13\xae\xbb\x06\xec\xc5\x28\x9f\x70\x27\xe2\xc1\x3e\x76\xfd\x71\x0a\x7a\xc8\x31\xeb\x13\x99\x35\xd8\x3a\x05\x9e\x17\xfb\x7e\xe6\x0c\xca\xa1\x3c\x46\xf1\xd5\x06\x99\x4f\x69\xd7\x07\x45\x6c\x6c\x58\x30\xb9\x46\x3f\x75\x00\xb8\xb9\x43\x8e\x67\xc1\x5d\x5d\x73\x6b\xf1\xe9\xa0\x15\x7d\x7d\x6e\xd1\xc6\x45\x30\xe2\x36\x20\x12\x31\x50\xef\x6e\xfa\xc7\xa7\x7f\x5b\x73\x3f\xc8\xf4\x14\x36\xc6\x8d\x68\xd6\xd0\xe3\x45\x82\x84\xde\xd8\x4d\xc9\x15\x14\x47\x6f\xb1\x5d\x02\x6b\x2f\xa6\xbb\x29\x22\x67\xf5\x59\x9f\xbb\x93\x93\xd3\xeb\x1d\x7b\xc4\xea\x60\x53\xaf\x40\x4f\xd8\xe1\x8b\x2f\x8e\xbe\xa3\x9a\x03\xea\x4d\xaa\x15\x2a\x2e\x9b\x60\x3d\x47\x7d\xf7\xed\x80\x19\x75\xf6\xd6\x2a\x52\x16\x13\xec\x7f\xf7\x5c\x73\x27\x15\xa2\xe3\x4b\xc5\x71\xe0\x75\x58\x8d\x6c\x65\x96\xd7\xaa\xa9\x63\x71\xe4\xaf\xd7\xf5\xf3\x38\xca\xc9\xe7\xe9\x40\xf2\xf8\xf7\x87\x8a\x22\x07\x76\x4d\x89\xbb\xe4\xfa\x67\x38\xf7\x57\xcf\x69\x74\xdf\xa1\xe2\x72\xe0\xbd\x00\xcd\x54\xc1\x45\x31\x34\x19\xad\xaf\x21\xdb\xce\xfb\x19\xca\xd2\x83\x6a\x25\xcb\xad\x3a\x9d\x2f\x95\xf3\x9f\x97\xb1\x86\x2c\xbc\xd2\x49\xf2\x9e\x10\x05\xfe\xbe\x6f\x3f\x9d\xd4\x87\x4a\xe4\x3e\x33\x92\x15\xa4\x69\xff\xcc\x13\x27\x75\xa4\x9c\x2a\x45\x46\xf9\x72\x34\xf3\x28\xd6\x72\x5f\x45\xd8\x91\xb1\xcb\x32\xaf\xb1\xa3\x9f\xe9\xe8\xb8\x3d\x74\x10\x6b\xda\x68\x6c\xf0\x3a\xe1\xbd\xc0\x0c\x58\xea\x38\x8f\xbb\x11\xd6\x31\xa4\xd8\x23\x8e\xb3\x2e\x4b\xfc\x72\xe3\x90\xad\xd8\x63\xfd\x0d\x24\xf6\xad\x6b\x1d\x6e\x0b\x92\x2c\x32\x65\x06\x69\x8a\x9a\x49\x5e\x81\xf9\x0b\x16\xfb\xa7\xec\xcf\xec\xa7\xaf\x7c\x8e\xeb\x3b\x31\xdf\xb0\x59\xe4\xee\x5f\x7a\x14\xe8\xf0\x78\x14\x74\x70\xb5\x7a\x97\x98\x38\x3b\x48\x2a\x3d\x50\xd2\xd2\xd2\x24\xcc\x06\xca\xf1\x55\x72\x76\xfb\xa3\xce\x09\x05\x91\x12\xca\x57\xc5\xd4\x81\x3b\xf6\xef\x00\x0d\xdd\x96\x1d\xa2\xa7\xea\x48\x06\x10\xc1\x94\x0f\x8c\x44\xcc\xad\x8d\xb3\x98\x7a\x13\x57\x8f\x19\xbd\xe5\x1a\x1d\x3b\x2b\xdc\x23\x82\x2e\x3a\xd3\x8d\x52\x7e\xc1\x77\x26\xe4\xae\x31\xf5\x4c\x0b\x89\xe5\xb7\x11\x1c\xb1\x94\xd7\x39\xbb\xd5\x54\x0c\xa2\xa7\x69\x0c\xb9\x77\xa6\x1b\x54\x39\x69\xfe\x52\x9a\xb1\x6b\x4a\x42\xe9\xa7\x7a\x88\x53\x71\x6e\x07\x57\xe9\xda\x9b\xfe\x7d\x20\x67\xbd\xca\x8e\x24\x45\x75\x6f\x97\xf8\xc2\x5c\x44\x5c\xd1\x00\xcf\xea\x4d\xe4\x70\xab\xf2\xac\x70\xdb\xce\x1e\x22\x79\x17\xb6\x86\x4b\xa8\xfb\x2d\xcb\xd5\x96\xe5\xa6\xd9\xb1\xe1\x41\xd3\xcf\xad\xab\xbe\xdf\xda\x55\xfa\xba\xba\xfb\xb2\x8d\x75\x7c\x10\x9a\x06\xd5\x73\xf5\x6b\xe1\x8c\x68\xbe\x77\x96\x57\x07\x2e\x81\x4c\x43\xc7\xf3\x71\x37\x87\xa2\x35\x46\xac\x87\xc1\xe9\x87\x74\x94\x60\x32\xfe\xe4\x99\xa4\x88\x14\xbb\xdf\x2a\x9b\x8e\xb3\x93\xfe\x62\x7f\x91\x32\xb2\xb2\x32\x71\x04\x6b\x67\x1b\x15\x9e\x2c\x63\x02\xc7\x8b\x4b\xa8\x60\x04\x05\x30\x43\x0e\xc1\xc9\xa8\x16\x71\x05\x07\x33\xeb\x45\xec\x78\xc4\xd4\x11\x11\x36\x93\x77\x20\x09\x0d\x54\xab\x1b\x17\x06\x81\xbb\x38\xd5\xa3\x23\x76\x21\xed\xd8\x41\x6b\x2d\xe3\x30\x4d\x8d\x55\x57\x40\xeb\xd5\x0c\x8b\x0e\x06\xc5\x8c\xcb\x53\x09\x94\xd7\xb4\x56\x23\x5d\x1e\xb4\x42\xd5\x25\x4d\xde\xa7\x4b\xd3\xe7\x6c\xf8\x53\x1a\xbc\xe9\x6d\xcf\x27\x36\xfd\x97\x19\xda\xef\x96\xdb\xe5\x25\x51\x47\xdb\x6d\x99\x0d\x2d\x2e\xaf\x62\x82\x8c\x9f\xf0\xf3\x39\x2b\xec\x65\xeb\xe7\x2a\x13\x38\x50\x9b\x41\x91\x01\xe7\xb6\x8f\x88\x3c\xd0\x93\x44\xd1\x4f\x5a\xe4\xd6\x97\xe6\x00\x5c\x5c\xc0\x6d\x14\x85\x62\x5b\x57\xed\x64\xd3\xf3\x7d\x2c\xff\xa5\xd8\x8d\x82\x3e\xc4\xcf\xe0\x4e\x1b\x76\xd7\xfa\x32\x3d\x12\xe0\x5c\x90\xd3\x94\xcf\x7e\x8c\xba\x84\x77\xb7\x6b\x03\xe2\x3e\x4f\x25\xee\xbe\x1d\x50\xb7\xe3\xbd\x4a\x45\xaf\x13\xbc\x03\x98\x65\x8d\x0e\xef\x8b\xc4\x1f\xd3\xfc\xf2\x61\x59\x41\x10\x5a\xaa\xd9\xa4\x68\xc0\x66\xcc\xaa\x78\x5c\xe0\x13\x02\x93\xc9\x2d\xc8\x5b\x30\x19\xab\x9d\xa2\x34\x78\x4c\xf3\x39\x69\x4d\xff\x1d\x4f\x7a\xb7\x1f\x59\x47\x22\x6e\xc3\x37\x5a\x9c\x97\x4a\x5b\x09\x35\x51\x4d\x64\xeb\x48\xb7\x18\xdc\x1b\x9f\x27\x30\x1a\x0d\x24\x75\x7f\x8c\x68\x81\xe6\x86\x4d\x9a\xd4\xe6\x08\x39\xb7\xcb\x15\xc6\x41\x28\xc9\x58\xd0\x6b\xe5\x0f\xf8\x03\x8b\xf1\x69\xb7\x0b\x4a\x63\x05\xf0\xdf\xe9\x0c\x26\x26\xdf\xdf\x33\x6a\xb1\xb0\x8b\x9a\x2f\xa3\x59\x08\xf4\x5b\x5e\xdc\xe5\x70\x3d\xb6\x45\x54\xc7\xe8\xb0\x24\x4f\x6c\x1c\x49\xf3\x97\x9c\x40\x1a\xe6\x0e\x4e\x4c\xcc\xb4\x19\x53\x10\x08\xe6\x48\x1f\x94\xbe\x6b\xe5\x6d\x3d\x4a\x91\xa7\xb9\xb7\x29\x8c\x32\xe1\x13\x9f\x95\xe8\x8a\xc8\x63\xa9\x03\xb6\xcc\xc4\x82\x06\xb6\x30\x6a\xb7\x63\x43\xfb\x12\x91\xda\x49\xb6\x85\x41\x44\x00\x6a\xf6\xe6\x3a\x2a\x09\xee\xe4\x4c\x7e\xf1\x54\x3b\xe5\xf2\xae\x7f\x31\x21\xd1\x1c\xae\x05\x98\x22\xe1\x25\x41\xab\x6f\xdc\x01\x21\x98\x2d\x1f\x15\x89\x5b\x29\x8c\x91\xba\x21\xaf\xe9\x18\x95\x96\x7e\x45\x13\x52\x23\xdf\x90\x01\x59\x99\x7b\xd1\xaa\xc4\x42\xed\x5c\x52\x4a\xa6\xaf\xc7\xea\x93\xad\x0d\x48\x01\xed\xfb\xb3\xb1\x49\xf0\x94\x46\x6f\x1e\x95\x28\xea\x26\xf3\x8d\x25\xb6\xaf\x25\x85\x3f\xbb\x07\xf5\x32\xa7\x3e\xa2\xc7\x5f\xa5\x7b\x11\x03\x99\x61\xbc\xdc\x22\x2e\xf7\xa4\xea\xcc\xf1\xc6\x30\xad\x33\x44\xdd\x59\x74\x13\xb8\xb9\x14\x0d\x7b\xa0\x1b\x5e\xc1\xe0\x46\xd5\xdd\x85\x06\x4c\xa9\x0d\x0e\x15\x50\xc2\xc3\xab\xbe\x0c\x4e\x58\x3a\x69\xf7\xb6\x30\xfe\x5d\xac\x81\x37\x91\xf2\xec\xf0\xbf\x15\xa1\x13\x61\x5a\x81\xa6\x6e\xd7\xac\xc9\xb3\x74\x60\x0f\xaf\xf8\xb0\xa7\x9e\x1d\xb7\x6d\x12\x97\x0c\x42\x87\x7a\xa9\x06\x62\xa3\x16\x98\xad\x8e\xa1\xb2\xb0\xb4\x02\xc7\x7a\xbd\x6a\x55\xd2\xaa\xf8\x43\x5e\xd5\xea\x55\x9b\x69\x7a\x74\xd3\x4c\x34\x9a\x3c\xf2\xea\xfc\x88\xe1\xfd\xdc\x8f\x3a\xe9\x00\xd9\x0d\xfb\x49\xc7\xf7\xd5\x07\x66\x4c\xb2\x73\x0b\x7c\xcc\x98\xf0\x3e\xe3\x6e\xf0\x4c\xb5\x6a\xe4\x24\x53\xe5\x8a\xc1\x08\xef\x36\xdc\x81\xff\xf1\x8b\xb7\x3b\xfd\xb2\xbd\xcc\xad\xf3\x38\x20\x2e\x55\xf5\x4f\xd9\x26\x90\x89\x1a\xcf\x28\xb2\x9d\x56\x91\x09\x37\x88\x97\x91\x6c\x72\x0d\xa6\xde\x6e\xa8\xf4\x46\x72\xc7\xca\x9c\x95\x4a\x2f\x94\x3b\x0d\x95\x36\xbb\x46\x77\x66\xf4\x2f\x09\x7d\x4a\x56\x13\x81\xe8\x9e\x8f\x72\x52\xfe\xc9\x37\x9f\x6a\x0e\xf3\xcf\x65\xcb\xcd\xe2\xd3\x56\x31\xba\xb2\xa0\x5e\x15\x8d\x0c\x2b\xf6\x19\xd7\x17\x7d\x81\x3d\xe9\x97\x28\x04\xd3\x9e\x69\x6c\xd3\x15\x64\xf8\xd9\xe0\xfb\x90\x2f\xd2\x9a\x7f\x24\xc9\x85\x16\x8c\xf6\x32\x71\x14\x9b\x14\x4f\x0b\xd9\x45\x29\xdf\xaa\x02\x58\xba\x80\x08\x49\xe5\xc2\x36\x76\x17\xc7\xa0\x43\x4d\x0e\x9d\x65\x57\x2c\x96\xb8\x01\x9e\x53\x50\xd4\xac\x20\xc1\xa6\x92\xa4\x9f\xdc\xce\xa1\xbd\xd9\x08\x23\x55\x29\xe5\x64\x29\x82\xcf\x78\x3a\x12\x8f\x5a\x1d\xdf\x7c\xbc\x7b\xd3\xc2\xd1\xae\x79\xf0\x29\xc8\xf8\xed\xf2\x94\xa1\x09\x63\x2d\x05\x46\x7b\xf6\xbc\x7d\x89\x7b\x53\xe8\xf5\xdd\xe2\xf8\xe4\xbe\x17\xc3\xc9\x1d\xe0\xff\xc5\xb5\xc8\x3c\xef\xf9\x31\x66\xd9\x3e\x49\x93\xe7\xbb\xd1\x65\x76\x58\xfd\x55\xd8\x2a\x30\xd0\x55\xcc\xd4\xa9\x7b\x91\x6d\xb4\x55\x3c\x48\x63\xb7\x5f\x5b\x3e\xf0\x71\x7a\x81\xac\x4f\xf3\x50\x6b\xe6\x21\x79\x8d\x90\x60\x86\x03\xce\xaf\x01\x9c\x91\x84\xad\x26\x7f\xbe\xcf\x68\xc9\x0d\x3f\x45\x19\xac\xfb\xa9\x04\xea\x94\xf2\xcf\x6f\x4a\xa3\x60\x88\x0a\xb9\xb2\xca\xb9\x6b\xa9\xcf\xe3\x00\x3e\x1a\xa6\x34\x9d\x6c\x8a\x21\xeb\x72\x5f\xfe\x55\x4f\x5d\x08\x1c\xc0\x2f\xc5\x44\x77\x13\xe1\x31\x56\xe1\x6f\xa5\x2a\x01\x2d\x92\x7a\xe2\x7a\xcf\x26\x1c\xa2\x18\x57\xf8\xb4\x52\x4b\xbf\x18\x42\x39\xab\xa3\x96\xe0\x14\x2a\x92\xdc\x85\xa0\x70\xb3\x3a\x99\x9f\x75\x55\xe9\x07\x46\x8f\xfb\x42\xc3\x55\x22\x7e\x91\x4b\x7c\xcf\x57\x31\x69\xa3\xe3\x4b\xc3\x56\x66\xfc\xf1\x6b\xd4\x47\x64\x11\x56\x82\x08\x83\x3b\x95\x01\xd3\xa5\xda\x00\x58\xb5\x40\xfa\x35\x3e\xfb\x4b\x2d\x71\x15\x35\x82\x5c\x6b\x3f\xbe\x6d\x08\x80\x8f\x65\x45\xbe\xae\x18\xfd\xe7\x78\xa0\x50\xc6\xb5\x2d\x54\x4b\xa9\xee\xa8\x6b\x14\x66\x31\xcc\x1c\xc7\xc1\x34\xa8\x26\x51\x6b\xee\x47\x67\x72\x8f\xc2\x10\xf9\x7e\xdb\xc7\x03\x83\x4c\x7a\x9d\x30\xec\xcf\x05\x4e\x41\x5d\xc2\xca\x1b\xa7\x91\x35\x4e\x36\xed\x7f\xed\x9f\x79\xa1\x41\x38\x70\x01\xdd\xe9\x9b\xa5\x10\x9f\xc0\x28\xaf\xec\x62\x64\x19\xa1\x36\x6e\xe3\xa5\xae\x62\xae\x4d\xdb\x0f\x05\xa6\xc8\x38\x31\xaf\x0a\xa1\x6b\xa7\xad\x88\x5a\x75\x67\x29\xed\x89\x19\x49\xa7\xf7\xa6\x69\x7f\x8d\x4f\xa7\xe8\x26\xb8\x4c\x46\x5d\x07\x29\xd0\xf9\xa7\x37\xf3\x83\x26\x1e\x73\x62\x6a\xa4\x00\xa9\xf7\x85\x4d\x5c\x49\xd6\x44\xa0\x48\x31\x37\xbe\xbf\x19\xaf\xcf\x65\x6b\xc6\xe3\xed\xa5\xe3\xb2\xb2\xfc\xbe\x7a\xae\x4f\xfc\x67\x3e\xe3\x82\x20\xf1\x8b\x3a\xd7\x59\xec\xf9\x8f\xfd\x23\xe6\xcd\x1e\xbd\x62\x11\xd1\x92\x79\x73\x56\x2f\x11\x8b\x96\x3b\xd1\x27\x06\x87\x61\xeb\xf1\xac\xd4\x70\x36\xce\x13\x54\x45\xe1\x63\xbe\xbf\x64\x77\x9c\x4f\x27\xe2\xf9\xcb\x93\x49\xcd\x01\xe9\x24\x44\xa1\x13\x55\x08\x57\x3b\x67\x70\x24\x85\x41\xa0\x7f\x5e\x50\xe7\x0c\xa4\x3e\x8c\x28\x97\x32\xf8\xf7\x96\xe2\x54\x50\xdc\x1e\xbd\x08\x78\xc9\xf9\x05\x7a\x12\x70\x51\x52\x98\x25\x16\x49\xa1\xf2\x3b\x16\x3d\xee\xae\xbf\xa5\x6f\xff\x75\xa0\x8d\x1f\x43\xb1\x47\xe7\xa0\x37\x11\xa6\x90\x76\xa9\x7f\xf9\xcf\x94\x12\xff\xd4\xf2\xf2\x68\xa4\xfa\xe5\x66\x8b\x87\x51\x65\xc9\x41\xf7\x61\x7e\xb2\x71\x25\xb9\x62\x65\x60\xa7\xe6\x4d\xee\x9f\x4f\x6b\x40\xc2\xcf\x05\x6b\x0c\x13\x61\xef\x65\xc3\x9e\xa7\x33\xd1\xf6\xbb\x0f\xe0\x75\x87\x50\xad\xbe\x5b\x38\x44\x8f\x21\x23\x0b\xba\xcd\x72\x8f\x9a\x26\x4b\x6d\x28\xee\x31\x1c\x1a\x80\x5e\x6a\xc4\x08\x1a\x6a\x4d\xa7\x35\x14\xff\x4b\x7a\xfc\x6b\x7e\x71\x0e\xf4\x14\xb4\x20\xe3\xa1\xe8\xc3\x48\x25\x3c\xea\x8b\x72\xbb\xb8\xda\x7b\xe7\x7d\x2e\x69\xfe\x82\xbb\x8d\x9f\xbd\x6d\x82\x72\x41\xd2\x91\x30\x75\x54\x00\xa3\xd4\xb5\x63\x2a\x2e\x4f\x0a\xf2\x99\xaa\x7a\x6a\x76\xea\xeb\xc9\x11\xe4\xf6\xfd\x9a\x88\x4f\xfd\xcd\x2c\x2e\x93\x97\xbf\x93\x69\xf7\x52\xbd\xe2\x05\x6e\xfe\xe1\xa4\x35\xcc\xf8\xe4\x94\x32\x39\x6e\x78\x32\x44\x6b\xa8\x08\xbc\xe9\x3f\x21\xc3\x11\xe2\xd5\xf7\x05\xb8\x3a\xb3\xed\xf9\xcb\xb8\xf4\x21\x87\x69\x77\x3d\x46\x66\x9e\x57\xbc\x36\x16\x4e\x70\x56\x23\x69\x27\xe7\xae\x9b\x7b\x79\xf7\x55\xd9\x67\x8c\x8f\xb3\x55\x4b\xe0\xa5\x23\x3b\xd3\x3f\x6c\xc8\x61\x47\x9b\x57\x93\x4c\xfc\x18\x4a\x66\x8a\x12\x3f\x94\x0b\xfe\x8b\x3c\x93\x6b\x17\xd4\xfe\xe1\xf0\x75\x73\x09\x34\xa4\x0a\x43\xb1\x54\x35\xe7\x53\xa0\x50\x29\x1b\xa3\x7e\x06\x97\x8e\x94\x81\x0a\x2d\xef\xa5\x2b\x46\x07\x4b\xc3\x0c\x4e\xf9\x8c\x54\x37\x5f\x34\xb2\xea\x44\x5d\xee\xfc\x04\x37\x57\x5f\x82\x97\x85\x7e\x1b\xde\x8c\x48\x32\xaf\x47\x2d\x6a\x66\x76\xde\x76\xc1\x9d\x67\x76\x6b\xba\xf4\x30\x0c\xe5\x54\xb0\x06\xb8\x6d\x42\xb8\x26\x67\x1e\xbf\x6f\xc1\xa3\x15\xd5\x81\xa7\xf1\xdd\xc9\x8d\xc5\xc1\x9b\xdb\xb7\x7a\x32\x60\x8f\x67\x21\x7a\x44\x09\xbb\xc8\x5f\xdb\x04\x95\xcb\x76\x63\xbd\x56\x4e\xee\x1f\x6a\xc9\x4c\xc6\x2f\xc7\x60\x10\x03\xea\x71\x63\x21\x7f\x38\xb2\x95\x60\xb0\x62\x6b\x61\x44\xc2\x6c\x0f\x95\xcf\x72\xf9\x7a\x9a\x43\x7a\xcf\x4e\x4a\xce\x64\x27\x3f\xc0\x61\x42\x7e\x2a\x47\x53\xb9\x0c\x31\xe2\x05\x2d\x58\xd7\x29\xc7\x73\x3f\xf4\x5e\x7f\xcd\x94\x56\xec\x79\x5d\xde\xcf\xdb\x85\x5c\x08\x5b\xc2\xa3\x00\xc9\x9a\xb7\x22\x3d\xe9\x67\x64\xa2\x5e\xbf\x24\xa7\xb6\x59\xf0\xd2\xae\xb6\xab\xfb\x35\x4b\x37\x15\x8c\x9c\xef\x2a\x67\xa4\x69\xd2\x02\x6f\xf1\x43\x86\x2b\x6c\xf1\x7c\x54\xe5\xc7\x06\x50\x81\xc8\xdb\x74\xbb\xac\x42\x94\x74\x7f\xb1\x14\x38\x61\xc7\xa8\xd2\x88\x7f\xf6\x5d\x28\x52\x56\x57\x40\xfd\xd9\xca\xf5\xa5\xd7\x40\x81\x00\xd3\x47\x6c\xd1\xef\x87\xdc\xd0\x22\x36\x0d\x5b\x5e\xb4\xa4\xbf\x7f\x81\x0e\x78\x9f\x3f\x46\xd9\x20\x53\x7f\xec\x00\xe9\x47\x4b\x74\xa2\x7a\x11\x03\x4d\xfd\x07\x93\x24\x69\x9e\x3b\xcc\xbd\x46\xab\x57\x5a\xc9\xbe\xb1\x74\xe0\x87\x63\xe3\x37\x47\x92\xfa\xcc\x6f\xc8\x92\x9f\xfb\x7d\xbe\x13\x72\x71\xf6\x8e\xa1\x20\xcf\xbe\x48\x7c\x7d\x96\xc3\x98\xeb\xf4\x6d\x69\xdf\x9a\xc1\x79\x19\x87\x58\xa6\x61\x1b\x83\x46\x1a\x82\x52\x48\x46\xb1\xc8\x76\xbe\xbb\xe7\x52\x42\x71\x54\xdd\x88\xd0\x93\x40\x40\x10\xe3\xd1\x9b\xd5\x47\x5c\xfc\xa8\xb8\x5b\xff\xa5\x70\x76\x79\xc8\x35\x64\x2e\x4c\x68\xe4\x41\xe3\x32\x8a\x83\x69\x7a\x80\xaf\xcf\x79\xa8\x8f\xcb\x6f\x25\x77\x2f\x8b\xbd\xb0\xf5\x2a\x3a\x46\x00\xcc\xce\x81\xd3\x44\xb8\x37\x1b\xed\x35\x25\x47\xbd\xa6\x0a\x7c\x43\xee\xea\x68\x1a\x96\x42\xa8\x44\x63\xad\x5f\x2e\x12\x11\x69\x65\x98\xbc\xdc\x15\xd7\x22\xc2\xb2\xff\xa3\x4c\x04\x7f\xce\x72\xc3\x68\x34\x37\xad\xec\x9c\x05\x9f\x87\x9b\x85\xb0\x8f\xb5\x72\x46\xa4\x55\x4c\x14\x4e\x32\x53\x65\xb8\x25\x79\x89\xdd\xe1\xe4\xea\x61\x76\x9e\xe1\xea\xc0\x48\x68\xf4\x89\xbd\x6f\x9f\xc7\xbb\xbb\xef\x60\xc2\x4e\x55\x87\xa0\xc5\xe2\x2d\xc6\x74\xd6\xe2\x33\xdc\x62\x8e\xaf\x87\xae\x88\xd2\x9e\x0d\x81\xf2\xf8\x6d\x0d\xe2\x6f\xfb\x7b\x38\x47\x37\x10\x71\xae\x1a\x4a\xdc\x72\x72\xfb\xdf\x22\xf9\x99\x71\x1c\xdf\xc4\xb7\x91\x1f\xae\x13\xff\xa8\x65\x92\xe7\xf2\x0b\xdd\x97\xff\x0a\x48\x6c\x4c\xa9\x32\xc5\xbe\x0d\x2b\xd8\x02\x2a\xb3\xd2\xec\xfd\x7a\x98\xf5\xfa\x67\x30\x7e\x1b\x63\x1d\x38\x3f\xee\xbe\xf6\xbf\x8f\xd7\x74\xe1\xb1\xad\x05\xb2\xb8\xe7\xa1\x0d\xca\xe0\x50\xb8\xa3\x8b\x89\xa1\xf3\x94\xca\x43\x64\x64\x60\xb7\x2b\x06\x1c\x1e\x31\x27\xca\x12\x17\x9b\x4e\x09\xfc\x08\x26\xef\x27\xcb\x3c\xf5\xa7\x8f\x4a\x8f\x3c\xe2\x32\x77\x4c\x34\x57\xb4\x05\xb8\x65\xd2\xb6\x48\x20\x3a\xc5\xf2\xc9\xee\xc7\x21\x23\x3a\xb2\x85\x27\xc6\x3b\x6f\x72\xe6\x42\x0b\x24\xf5\x34\x83\xa7\x72\x40\x6c\xd8\x00\x06\x03\xac\x67\xd5\xad\xb0\xe6\x91\x88\x13\x58\xb1\x15\xa2\x37\xb2\xcd\x0c\x41\xe0\x66\x7f\x40\x3c\xd7\x6b\xd1\x5f\x20\x5e\x8b\xcf\xcf\x4c\x97\xca\xdc\x86\x8a\xc6\x82\xbe\x67\xc2\xdc\x11\xd3\x15\xed\xdd\x3a\xd2\xb9\xad\x3a\xd2\x80\xae\xbb\x9b\xc0\xef\x16\x68\xdf\x77\x07\x1c\x1e\x00\xad\xa9\x88\x69\x88\x1e\x07\xbd\xbf\xda\xc5\xca\x02\x1a\xec\x0f\xde\x1f\xb4\x42\x6d\x37\x1d\x50\x68\x8f\x7c\xf5\xcc\x5b\x88\x1e\x85\xc7\x09\x4b\x4a\xc4\x13\x54\x92\x3c\x61\x39\xc5\xec\x76\x9c\x71\xe8\x3b\xb3\xef\x2c\x50\x6b\x73\x63\xc4\x84\xcb\x0e\x17\x73\xa9\x48\xd6\x39\x2c\x85\x76\x0f\xde\x8f\x6e\xf8\xa5\x27\x5e\xad\xb9\xd7\x0b\x10\x30\xfe\xbe\x5a\x4b\x9e\xbf\x67\xef\xca\xb7\x30\x89\xa4\xf7\xf0\x67\xc7\xe7\x15\x36\xe0\x49\xa4\x37\xf8\x03\x02\x8f\x7e\x68\x02\x55\x28\x13\xd2\xbb\x38\x55\x44\x8f\x58\x40\xe9\xeb\x55\xf1\x97\x9e\x5a\x17\xee\xb6\xd3\xea\xd0\x7f\x4c\x00\x44\xc6\x8a\x1d\x14\x85\x0c\xd1\x76\x72\xa6\x3a\x7d\x93\xb2\xe2\x44\xcd\xfc\x48\xb9\x11\x58\x4c\xea\xaf\x8d\xbd\x33\x9c\x6e\x2e\x63\xd4\xd3\x41\xe4\xf2\xb1\x4e\x28\x30\x18\x4e\xca\xd1\x0a\x5d\xba\xfe\xbc\x46\x24\x3f\x34\xc0\xb9\xd6\xdd\x1c\xbe\xc5\x0f\xd2\x58\x22\x29\x61\xc1\x77\xdd\xb7\x0e\x7b\xd5\x12\xb6\x06\x82\x58\xb5\xcb\x0e\xa4\x63\x78\x97\x9d\x88\x1e\x92\xe3\x61\x9d\xbe\x67\xe4\x7a\x85\x13\x54\x55\xb0\x47\x2a\x51\xc5\x94\xb3\xde\x0f\xa9\xe9\x60\x08\xf5\x6d\x82\xe5\x5c\xc5\x93\x09\x1e\x8c\x60\x44\xc4\xab\x93\x9a\xd8\xbf\xd2\x68\xc4\x8a\xa6\xe4\x84\xa6\xb4\x38\xae\x63\x9a\xbb\x13\xc3\xe4\xaa\xb0\x29\x8e\x24\xb5\x34\xc2\x1e\x3d\x11\x5b\x1e\x9f\x55\x9d\xeb\x24\xe9\x6d\x15\xf4\x45\xae\xaa\xf8\xc6\xb7\xc2\x82\xfa\x1d\xc7\xbe\x37\x25\x26\x10\x09\x64\x88\xfd\xdf\xe3\x19\xe3\x62\x55\x02\x36\xda\x9d\x0a\x2f\xaf\x7b\x84\x02\xa0\x4c\xa9\x64\xad\x93\x32\x36\x13\x29\x44\x0f\xda\x82\x0b\xdd\xdd\x81\x2f\x30\x30\xfa\x24\x57\xb9\x43\xd6\x52\xe4\x97\x00\xec\x89\xc9\x6e\x1a\x39\xe1\x8a\x1a\x67\x6e\xb6\x4a\x89\x8c\x4a\x86\xc3\xc5\x75\x7f\x4a\xe1\xa1\x22\xd5\x64\x61\x67\x5e\xea\x1d\x62\x97\xf7\x2c\x9f\xaf\x69\xbf\x49\x4a\xe4\xce\x5b\xe7\xb0\x88\x85\x21\x97\xa4\xe9\xde\x11\x4b\x25\x29\x3d\x67\x4d\x93\xfc\x23\x57\x74\xc5\x7f\xbf\xc6\xbe\x90\x44\x8c\xa5\x93\x5d\xcf\x5c\x5b\x73\x34\xa4\xed\x32\x67\xaa\x7d\xbd\xab\xd2\xad\x98\x7e\x7e\x5d\xab\x34\x5c\xff\x3b\x9f\xae\x3e\x51\x34\x7d\x87\x47\x6d\xa2\x3f\xbc\xd0\xc1\x1b\x62\x93\xda\xf1\xf3\x70\x13\x4a\x0b\x00\xa2\xb3\x7f\x18\xc0\x3d\xcf\xe4\x91\xb0\xf0\x1f\x2f\x1c\x81\xb4\x51\x20\x23\xae\x16\x3a\xa9\x0a\xa7\x88\x34\x5b\xb7\x63\xd6\x03\xdd\x3c\x56\x60\x59\xa3\xf7\x44\xaa\x45\x20\x61\xcf\x2e\xb7\x7d\xb4\x98\xfc\x7e\xed\x65\x17\x53\x2c\xb6\x79\xcf\x41\xdf\x2f\x2e\x4b\xc8\x90\xc2\xcb\xc8\xc5\x13\x6b\x5c\x40\x04\x0e\xc7\xc9\x58\x64\x29\x43\x24\x18\x47\x64\x59\xba\xa4\x73\x9d\x25\xfe\x16\x94\xf8\xd9\xa4\xef\x8b\xc6\xc5\x2f\x46\xe7\x8d\x46\xec\x50\x26\xe0\x88\x98\x6c\x63\x4d\xcc\x06\x48\x6f\xc7\x66\xa7\x8b\xd2\xd6\xfe\x32\x15\x5e\xf3\x32\xa0\x36\xb8\xee\x20\xcb\x44\x60\x26\xa2\x58\x4a\xe2\x43\xdf\x75\x0b\x3b\xf2\xfe\x8e\xa7\x6a\x83\x9e\x42\xf6\x6d\xad\x82\x74\x21\x06\x9c\x57\xc4\x8e\x19\x4d\x5e\xa4\x66\x7b\xc3\xf9\xed\x69\xd4\xb0\xaa\x94\x59\xcd\x58\x87\x0f\x02\x26\x38\x9b\xb4\x1e\xe6\x37\xf5\x54\xf1\x44\x62\xa0\x70\x01\x47\x1a\x4b\x0f\xb3\x5f\xab\x33\xa8\xf5\xf4\x0e\xf0\xd4\x6e\x88\x73\xc4\xac\xda\xb6\xc4\x71\xaa\x71\xd5\xa8\xb7\x77\xfb\x84\x2a\xa7\x19\x47\x6a\xd8\xdc\x12\xd7\x69\x7b\x33\x67\x80\x71\xa9\x78\x1c\x11\x42\x12\x68\x12\x3b\x42\xe1\xf7\xda\xd2\xc1\x7c\x7a\xee\xfb\xd8\xf0\xda\xd0\x41\x66\x47\xba\xc5\x61\xf2\x0a\x65\x58\x92\x9f\x9b\x4c\x6e\x4a\xcf\x2c\xde\x34\x8f\xcd\xc0\x8d\x36\x0b\xb0\x76\x5a\x03\xe5\xbf\x9d\xfc\x91\xfd\xbc\x9d\x07\xea\xcf\xb4\x38\x0a\x12\xdc\x3b\x7d\xdd\xa8\x64\x7d\x36\xb1\x19\x96\xb0\xf1\xe4\x52\xc3\x59\xdd\x62\x0b\xd3\xf7\x59\x6e\x8f\x6a\x4c\x31\x00\x60\xb7\x06\x46\x35\x4e\x3e\xb2\xbf\x68\xdb\x03\xc2\x15\xa8\x18\xc1\xb3\x1f\x23\x3c\x46\x00\xc4\xc5\xa2\xfc\x57\x52\x9d\x25\x78\x5f\xdb\x87\xfb\xbb\xe8\x7e\x1b\xe7\xd7\x2f\x0d\xef\xd1\x66\xd1\xf8\x0d\xcc\x8a\xb1\xb7\xd9\xe5\xdb\xb8\x26\x54\xbd\x79\x14\x94\xa4\x44\x96\xef\xc6\x08\xf7\x3e\x28\x96\x9d\x14\x7a\x67\x65\x41\x85\x8f\xd9\x3b\xd2\xec\x80\x65\xb6\xa0\x1a\x77\x32\x0b\x8b\xf1\x06\xe9\x76\x3b\x96\xc4\x9e\x01\x13\x36\x41\x90\xa9\x94\xca\x9c\xac\x4d\x06\x75\x7b\x82\xd1\x04\x23\xf9\xca\xc2\x89\x9f\xd6\x93\xed\x46\x82\x3b\x9d\x94\x9d\xe5\xde\xa6\x84\x9b\x64\x3a\x6b\xa1\xeb\x1a\xa4\x97\xd7\x30\x65\xa4\x76\x00\xf7\xba\x64\xc6\x2c\xa6\xf4\xde\x48\x0d\xf7\xf7\xb7\x3c\x02\x9d\x49\x8b\x8c\x33\x5e\xc1\x5b\x76\x12\xab\x8b\xec\x32\x82\x74\x3f\x4b\xe5\x4a\xbf\x25\x26\xe6\x12\x43\xa3\x48\xd9\xf5\x11\x92\xd9\x56\x1a\x3f\xaa\x9b\x0d\x9e\xd1\x5f\x23\x6d\x1b\x97\x45\x50\xf5\x5f\x16\x2b\x9f\xcb\x43\x4e\x09\x6c\xb5\x51\x24\x40\x30\x29\x12\xa4\xcf\xa2\xf9\x40\xea\x2e\x05\xc4\xde\x23\x23\x5c\x0a\x96\x50\xc6\x73\x62\x0f\x43\xe9\xba\x59\x34\x96\x57\xc5\x9e\xa7\xd7\xa4\x2e\x75\xb5\xd0\x2f\x35\x4a\xb1\x91\x53\x3e\x24\x67\x0a\x5e\x86\x73\x43\x62\x5d\xcf\xa1\x2d\x80\xda\xf2\x74\xa4\xc0\xec\xda\xf0\xab\x5b\x57\x7b\x9b\x11\x45\xca\x54\xad\x4d\xef\x0a\x25\xed\x38\x23\xc3\xa8\x0b\x07\x01\xa6\x0c\xec\x3c\x49\xb2\x97\x3d\x35\x72\x5a\xa4\x44\x6c\x5b\x51\xa1\xa1\xde\x48\xc4\x73\x08\xa0\x8e\x57\xb4\x8a\x19\x6a\x01\x87\x8b\xe8\x6e\x3f\xaa\xe1\x9d\xa5\xf2\x59\x74\xc1\x9d\x44\xf2\x2c\x46\x42\x49\x37\xd3\x64\x1b\x4f\x40\x95\x53\x0a\x76\x49\xf2\xf8\x60\x04\x0f\xef\xd4\x1f\x0b\x9a\x32\x61\x20\x17\xef\x24\x42\xbd\xc3\x40\xdf\xc7\xd6\xea\xaf\xd6\x7d\x34\x9a\x36\x7c\x23\x82\xff\xa3\x20\x4a\x96\xb3\xb8\x43\xbd\xc4\xc4\x56\xf5\xde\xfd\x85\x4a\x28\x41\xac\x54\x37\x8a\x18\x0c\x21\xda\xed\x75\xf8\xf3\xb1\x90\x73\x04\x95\x9b\x58\xa5\x3a\x45\x67\x42\xb4\x0e\x69\x93\xbb\x14\x70\x73\x99\xdd\x7b\x32\xdf\xb3\xf2\xdd\x06\xb2\xf9\x57\x02\x37\xff\x89\x75\x95\xf1\x3c\x42\xd8\x41\x47\x1e\x65\x1e\x03\x71\x7c\x7c\x42\x66\x34\xd3\x53\x47\x21\x1e\x38\xd1\x12\xee\xfb\x33\x25\xb6\x30\xa7\x45\xa3\xba\xfb\x45\xd2\xa2\x3b\x23\xdd\x55\xa0\x7d\x08\xff\xc2\x24\x83\xd3\xaa\xc7\xc8\xc1\xdc\x27\xf4\xab\x4a\xd2\xdb\xe1\x44\x42\xdc\x82\x94\x87\x44\x2f\x54\x35\xef\x73\xc8\x4d\x9d\x47\x4d\x56\x6d\xaf\x46\x4a\xc3\x52\xd6\xbb\x23\xb8\x14\x4d\x2e\x9a\xb9\x95\x6c\x03\x79\x3a\x56\xee\xaf\xc2\x45\xc3\xbe\x6b\x28\x5f\xaf\x41\xb5\x89\xd7\x6b\x0b\xe3\xfd\x1c\x47\x4b\xcb\xb6\x33\xe3\x7c\xfb\x25\x69\x55\x47\x99\x67\x51\x1a\xf0\xc0\x48\xc5\xe7\x39\x9a\x6e\xb4\x05\x55\x20\x00\x69\x8b\x19\x97\x3c\xfd\x80\x5d\x52\x95\x90\xcf\xf1\x0b\xcb\x32\x0a\xe5\x89\xbc\x7a\x2e\x73\x7d\x14\x2d\xb3\x02\x1d\x9c\x00\x74\x04\x3f\x23\x1c\x45\x23\x41\x90\x99\x41\x8b\x53\x09\xc9\xc5\xb6\x38\x32\x29\x47\xe8\x58\x7d\x4e\x12\x78\xba\xcc\x4e\x97\x83\x68\xc5\x6e\xe6\xe0\xc8\x90\xb6\xfd\x96\xa5\x76\xa9\x39\xc5\xac\xaa\x55\x5e\x16\xb2\xcd\x50\xa9\x96\x1d\x9f\xa8\xed\xcd\x2c\x4f\xaa\x34\x26\xa3\xf3\x15\xcf\x5a\x51\x0d\x1f\xb7\x8b\x48\x3a\x10\x0a\x15\x42\x99\x2f\x69\xe5\x34\xbb\x66\x33\xa7\xf9\xda\xbc\x12\xee\x2c\x6e\xbd\xeb\x4d\x55\xa0\x4b\x7a\xc6\x9a\xff\x7e\x6f\x1c\x89\xf3\x54\xdf\x57\x9d\x53\x29\x49\x2b\xe1\xf6\xff\x66\x98\x13\xe3\xce\x67\x85\x7e\x74\xcd\xf9\x45\x64\x49\x36\xe5\x13\x51\x43\x43\xa9\x1e\x19\xee\xbe\x20\x9d\x13\x00\xc3\x4b\x8d\xfd\x5c\xb2\xc5\xf1\xf3\x96\x9e\xff\x41\x91\x72\x3f\xcc\x2d\x13\x08\xa4\x4e\x04\x97\x01\xd9\xb8\x8b\x31\x4a\x5b\xe6\x41\x19\x4d\xea\x0c\xd5\xd0\xaa\x9d\xd0\x55\x56\x0b\xf4\x6a\x2b\xf1\x5e\x04\x14\xf3\x61\x6a\xa2\x9b\x9d\x13\xa7\xd1\x15\xb5\xb8\xf4\x2e\x9f\x4f\xc5\xaa\x0b\x72\x42\x5a\xdf\xd3\xa4\x87\x30\xe2\x73\x84\xea\xba\x58\xe8\x04\x7b\x17\x27\x85\xe5\xfd\xbe\x98\x66\xf0\x01\xd7\x47\xf5\x95\xd3\x23\xb1\x04\x69\x6d\xca\xa5\xb9\x79\x64\x01\x6e\x17\x8c\x24\x47\x96\x32\x50\xdd\x73\xda\xfa\xd6\xa9\x71\xb9\x02\x6e\x23\xa6\xf4\xf7\xdd\x2c\x9a\x10\xbb\xb5\x0b\x43\x25\x4c\xe7\x4b\xbe\xce\x1a\x4f\xef\x19\xa7\x3a\x3a\xcd\x78\xdf\x9a\x6b\xfc\xe6\xd9\x16\xe2\xd5\x8b\xbc\x71\xde\xaa\x5d\xd6\x15\x72\x2d\x54\x9d\x51\xde\x91\xd1\xfb\x66\x71\x98\x15\xa1\xd4\xf4\xc9\xfe\xf5\xb1\xec\x1b\x5c\x23\x27\x5d\xbc\x48\x87\x99\xc7\xfd\x82\x1f\xb5\xd9\x31\x97\xe3\xf3\xbb\x32\x77\xf1\x0e\x44\xdb\xdb\x93\x9b\xf8\xce\x7d\xe7\xa8\x4d\x66\x11\x76\xfc\xfd\x9d\xdb\x54\xb2\x37\xbf\x9f\xa7\x7c\x22\xc6\x21\x4c\x6c\x62\x51\x44\xe0\x10\xd8\xea\x73\x15\x5e\xa3\xca\x64\x5f\x27\xb4\xfd\x9a\x19\xea\x3c\xf4\x61\x91\x71\x1d\x4e\x77\x85\x53\x2b\xa9\xc0\xbc\xb3\x62\x86\x33\x24\xd8\xc9\x8f\x2c\x35\x36\x97\x43\xe8\x38\x06\x3a\x4c\x8d\x84\xdd\x3e\xc2\xda\xd8\xa4\xc1\x53\x1d\x31\x51\xd5\x9c\x59\xf2\xc6\x62\x60\x0d\x9a\x6f\x52\xcf\xa0\xbc\xcb\x96\xe6\x41\xa8\xfa\x7d\xf3\xf7\xfc\xd7\xda\x7d\x75\xd3\x06\xe5\x04\x9a\xcc\x16\xdd\xca\xee\xc6\xa9\x26\xb9\xca\x7c\x7e\xf0\x34\x9e\xd4\xf1\x75\xc0\xe9\x4e\x70\x0e\x0c\x2e\xa3\xe7\x90\x03\x87\x1d\x67\x59\x09\x34\x5e\xe7\xae\xb7\xc6\x11\x27\xf7\x52\x5d\x29\x74\xc8\x53\x03\x87\x13\x41\x86\xbf\x94\x4b\x38\xd8\x35\xf9\x17\x19\x1a\x4c\x7f\x63\xcf\x9f\x3b\x34\x86\xfd\x6f\xc5\xcd\x7a\x4b\x89\xbb\x62\x67\x55\x7a\xfe\xfc\x60\x07\x9a\x94\x2d\xaa\x6d\x78\x2e\x1b\xdb\xe2\xab\x1f\xbc\xb5\x5c\xbe\x69\x1d\xaf\xab\x31\xce\xd2\x9b\x47\xae\x79\x84\x2b\x4b\x8c\x23\x1d\x2a\xf4\xe5\xeb\x6f\xab\x7f\x32\x64\xb6\x91\x6e\x05\xc5\x1d\x48\xac\xb7\x66\x10\xed\x1b\xdb\xa5\x49\xf6\x01\x32\x5e\x28\x15\x62\xb1\x87\xb8\xb6\x8d\x2f\xb3\xef\xdd\xef\xa2\x52\x7f\x45\x08\xeb\x86\x26\x0c\x0f\x5c\x35\x60\x2c\xb8\xe3\x1f\x07\x9b\xcc\x5e\xa5\x08\x29\xf5\xc8\xc5\xc6\x29\x64\xa1\x4f\xd5\x37\x3b\x5d\x01\x8c\xf2\xd0\x1a\x13\x9d\xaf\xf1\xbe\xd4\x57\x94\x8a\xbf\x15\x5a\x79\x96\x7e\x02\x31\x68\x1a\x82\x9e\x7f\x7c\x5c\x57\x8b\x77\x3b\xbd\x86\x08\x1c\xc2\x09\x0a\x8f\xcf\x59\x35\x48\x17\xab\xc1\x4f\x9e\xd5\x98\x9a\x30\xbb\xdb\x30\x07\x92\x8e\xd8\x7f\xfd\xdd\xb8\x7f\x66\x9d\xeb\x99\x63\x2b\xd1\x57\x98\xf4\x93\x7b\x06\x1e\x48\x9a\x8b\x27\xa5\xfa\x08\x8d\xf9\x08\xc2\x2f\xc6\x90\x06\x1c\x5e\x21\x44\x1a\x82\xf2\x13\xaf\xa2\x05\xae\x23\xb1\x9f\x7c\x3d\x3b\xb7\xa2\x10\xd3\x08\x6e\x5f\x0c\x88\xf9\xb8\x6c\xdf\xa6\x36\x09\xd1\x25\xd1\x4d\x5e\xff\x5a\xee\xf8\x62\x8c\xd8\xeb\xe3\x10\x76\xa9\x34\x92\xc7\xba\x72\xb7\xdf\x73\xca\x6f\x91\x9a\x11\xf2\x64\x02\x4d\xf6\x4d\x1e\xdb\x07\xb9\x77\xcc\x62\xa6\xa5\x7c\x6b\x99\x9f\x21\x47\xfb\xc2\xd6\xec\xdd\x0c\x57\xee\x2a\x87\x78\x33\xa9\x27\x71\x79\xdc\xff\x65\x29\x85\x1e\xf3\xed\xab\xb4\xf5\x8c\xe6\x21\xa7\xc5\x3a\x6a\xcb\x78\xd6\x7e\xc4\xdc\x72\x39\x9b\x6c\x76\x13\x58\x76\xcf\xb4\x6c\x3d\xca\xf9\x4f\x00\x89\x18\x39\xbc\x64\x60\x4d\xe9\x0b\xea\x05\x8e\xe8\x5e\x08\x0e\x65\xdf\x13\x62\x67\x52\xe6\x24\xa5\x3b\xce\x12\x9e\x6f\x66\x56\x19\xff\x05\x33\xb0\xd3\x50\x8c\xd7\xed\xee\x8e\xc7\x54\xd5\x6d\x29\x43\x8d\x98\xcc\x50\xd3\x3a\xc1\x25\x58\x02\xbb\x89\x52\x82\xcd\x94\x26\x94\xfa\xe5\x90\x0f\xce\x89\x77\x06\x78\xb3\x35\xbd\xcf\xce\x15\x52\xa2\x07\xcb\x13\xcc\xac\xc2\x67\x96\x4b\x31\x1f\x88\x78\x74\x8c\xfc\x9e\x10\x37\x50\x9d\xde\x93\x1d\xba\xee\xbe\x18\xbd\xad\xd4\x7d\x2f\x43\x34\x55\x80\xb4\xe5\x0f\xe8\xb1\xa7\x19\x14\x09\x9e\x25\x78\xb8\x07\xaa\x71\x02\x56\x4a\x86\x8b\xf2\x1b\x43\xbc\x02\x8b\xdb\x2e\x23\x9b\xdb\x26\x75\x61\x3b\xe9\xf6\xd5\xf2\xa6\xd1\xf2\xfa\xaf\x5a\x1e\x63\xc2\x76\x75\x2f\xa1\xfe\x7a\x56\x1e\x76\xfb\x37\xb0\xfc\x1b\x20\x61\x18\x0e\x3f\xdd\xa8\x1f\x79\x3e\x39\x85\x5a\x98\x48\x4c\xb7\x09\x1e\xdd\x34\xeb\x6a\x35\x64\x76\x2b\x93\x38\xb8\x26\x22\xa9\x8b\x6d\x77\xc0\x76\x1e\x61\xce\xc2\xbf\x2d\x09\x8e\x42\xf4\x40\x9f\x3e\x8e\xe7\x4d\xc8\xe2\xe0\x89\xcb\xeb\xfb\xd0\xcc\x11\x69\x0e\x62\x26\x64\x7a\x97\xa4\x01\x69\x04\x63\x94\xd7\x9e\xed\x94\x0e\x4e\x5b\x3b\xf5\xa1\xdc\x1f\xf8\x24\xaf\xe9\x63\xc0\x44\x8c\x6d\x15\x07\x2a\xea\x4d\xfa\xd7\xf8\xe4\xfb\x5d\x3f\x53\x8d\x75\x17\xa3\xc3\x7a\xb3\x1e\x17\x1d\x44\xe6\x60\xc2\x95\xc5\x49\x4c\x04\xa3\x29\xf6\x85\xc0\x1e\x7a\xdb\x65\x20\x76\x59\x69\x98\x84\x10\x40\xb8\x74\x9f\x99\xef\x80\xe7\xd0\x3e\x2f\x1e\x26\x89\xa5\x22\x8b\xcc\xed\x26\xf5\x8f\x27\xc5\xae\xf5\xbf\xd4\x3f\x31\x66\x3d\xad\x6d\x7a\x7d\xb3\x5e\xb9\x9d\x80\x30\x60\x95\xe2\x37\xe6\x4f\x9c\xfa\xdf\x4b\x18\x4d\x78\x05\x64\xea\x07\x37\xdf\xe5\xa6\x9f\xe7\x87\x61\xff\xdc\x3f\x01\x9e\x60\xf8\x0e\x7d\xeb\x41\x75\x9e\x78\xde\xc9\xb6\xf3\x56\x0e\xd6\x44\x07\x32\x4f\x8e\xad\xd2\x3b\x4e\x89\x56\xf4\xe0\xf0\x5f\x61\x15\x6b\xfe\xeb\x38\x0f\x57\x8d\x84\xe0\x6f\x62\x5f\x02\xdf\xe5\x33\x65\x5d\x2e\x72\x08\xdc\x91\xef\xb2\xe6\x9d\x6b\x61\x3f\x1c\xb4\x8e\x05\xb1\x9f\x5a\x1a\x27\xd3\x84\x70\xed\x19\xe9\x82\xed\xc5\x94\xdf\x6f\xf0\x73\x1d\x98\xd3\xf4\x64\x1a\xa5\x9f\xa4\xe5\xe8\x42\x92\x7c\xe5\x55\xec\xfe\x59\xa1\x05\x0e\x54\x00\xc5\x9e\x25\xd0\x7f\x78\xb6\xf5\xfa\xa9\x28\xfe\xa3\x98\xbe\x11\x68\xa9\x93\x54\xd4\xa8\x8f\x34\x93\x40\x3b\x2f\xd7\xb7\xe3\x96\xd8\x95\x42\x9a\xeb\x1e\xc3\x30\x94\xfd\xb5\x2a\x18\xcc\x98\x56\x2a\x6e\xd7\x8d\x1c\x32\xeb\x5a\x23\x77\x2e\x56\xad\xf8\x2d\xa0\xdb\x63\xa0\x9d\xa1\xc6\x27\xfa\xa6\x3f\x60\xe0\xb1\xad\x72\x36\xf3\xa6\x5c\xf8\x04\x0e\x27\xc6\xf6\xef\xbe\xf5\xf3\xd7\x60\x44\xb7\x96\x7f\x80\x4f\xad\xef\xbd\x5d\xd6\x60\x6f\xe5\x2c\x15\x9c\xc9\x97\x50\x7b\xfd\xe7\xd8\xbe\xd5\x03\xfb\x9a\x0d\x9a\xf7\xf1\x56\x5f\x90\xe5\x7c\xa8\x42\x55\x94\x43\x63\x31\x1c\x19\x24\x18\xe5\x1a\x44\xea\x6d\x3c\xff\x56\xc5\x46\xa0\xfd\xfd\x8b\xa1\x69\x92\x51\x6a\x3f\xa0\xcc\x91\x00\x04\x22\x03\xca\xa2\x11\xa3\x80\x85\xa1\xc7\xe0\x20\xf4\xd4\x7e\x06\x9a\xd7\x09\xd3\xe3\xc6\x60\x40\x1b\x7b\x9b\x2b\x90\x26\xb4\x35\x31\x8e\xf1\xfd\xe9\xaf\x61\xd2\xa5\x65\x22\x1b\xaa\x15\xc6\xff\x6e\xe6\xee\xe7\xd8\x57\xe1\x30\x14\xbf\xaa\x78\x1a\x2f\x94\xe1\xcd\x0b\x49\x85\xae\x0a\xb5\x54\x38\xc5\x79\x6b\x86\x52\x5f\x86\xcb\x0e\xa9\x20\xf1\xbd\x6a\x48\xae\x48\xa7\x9b\xaa\xb5\x25\x26\xaa\x70\xe1\x3a\x74\x15\xe6\xef\xe2\x37\xee\x33\xa4\x03\x03\x22\x1d\x41\xef\x70\xba\xba\x98\xc6\xce\x72\x7e\x92\x59\x25\xd3\x33\xc5\xb2\x6e\xd1\x2c\x89\x68\x68\xee\xd5\x62\xa6\xce\x58\xd6\x5c\xc8\x39\x54\x78\x08\xe6\xa2\xfa\x6d\x71\x94\xb5\x89\xba\x23\xc8\x06\x48\xcc\x6a\x37\x8d\x60\x0e\x24\xd3\x29\x31\xa1\xb0\xb0\x14\xba\x3a\xc9\x71\x37\x0d\xc8\x15\x81\xc9\x38\x3a\x96\x3b\xec\x03\x9a\x88\x2b\x91\xc1\x56\x74\xa0\x5c\x2a\x03\x2e\xe4\x6a\xca\x04\x7b\xd1\x7b\x9b\x84\x60\x18\x12\x5a\x84\xaf\xd5\x8a\x60\x13\x35\xaa\x3b\x05\x52\x52\x5d\x26\x8c\x9d\xd8\xb5\x38\x3e\xf5\x44\x65\xc2\xb4\xf3\x6f\x6f\x89\x72\x83\x2b\x6b\x60\x11\x83\x79\xa3\xb2\xd5\x98\xfe\x1b\x09\xba\x2a\x92\xf8\xc6\x50\x18\xc4\x99\x46\x07\x95\x64\x5f\x21\x0d\xc8\xa6\xec\xa8\x3c\xec\xa6\x56\x57\xd8\x50\x08\xdb\x73\x33\xff\x28\x5c\x4e\x5a\x43\xd1\x0b\x2f\x2e\xbb\x22\xdc\x53\xa3\xa9\xff\x11\xc6\x25\xf3\x48\x67\x1c\x6a\xec\xd9\x9c\x61\xc9\xca\x0a\xec\x00\xe5\x28\x8f\xdd\x46\x5d\x13\xe4\x8a\x73\x50\xd7\x45\xbe\x2e\x92\xbc\xa8\x4b\x81\x39\x72\x9b\xad\x47\x42\x41\x77\x3b\x9d\xee\x6c\x79\x36\x6b\x57\x93\x4a\x48\xf1\x2b\xec\xcf\x3f\x42\x2a\xd4\x9e\xd9\x40\x3e\x9a\x00\xf9\x2c\x99\x26\x15\xa2\xbf\x09\x57\xff\x34\xdf\xf9\x7b\xba\x1b\xb4\x64\x74\x17\xed\x22\x01\x47\x50\xfb\xea\xea\x3d\xe4\x53\xda\x59\xdc\x1c\x2a\xe5\x65\x9b\x32\xfd\xa7\xfd\x16\x74\x51\xba\xc1\xb0\x25\xa1\xca\x59\xcf\x30\xd8\x48\xa6\xa5\xc3\x7e\xf2\xf2\x5b\xb3\x75\x3b\xfc\xcb\x2c\xb4\xb5\xb3\x50\x81\x78\xea\x18\xac\x28\x11\x76\xe1\x6a\x38\xcc\x51\xc2\x15\xfd\xd9\xf6\x55\x09\xea\x18\x20\x8c\x51\x6e\x90\x9f\x3a\xcc\x8a\x2b\x34\x6c\xe4\x19\xe5\x90\xc5\x01\x5d\xe9\xbb\x5a\xb6\x54\x5c\x36\x3f\x4e\x0d\xad\x16\xba\x43\xa6\x32\x19\x04\xef\xcb\x6e\x9e\x93\x66\x8a\xe6\xe8\x43\xef\x1c\x31\xc1\x65\x2c\x40\x2d\x80\xa1\x22\x12\x0a\x97\x67\x2f\xaa\x32\x28\x91\xf9\xcf\x57\x19\xc0\x6e\x50\xe6\x1f\xb7\xb2\x2f\xf3\xb1\x07\x08\x2d\x3d\xe4\x9f\x5a\xb6\x76\x05\x68\xfc\xa2\xfb\x84\x19\xc3\xaa\x68\xe9\x16\xd9\x98\x0e\x61\x5d\xbd\x2a\xce\x5b\x26\x80\x0e\xd3\x16\x63\xc3\x44\x37\xd1\xcc\x30\xd9\x83\x25\x23\x95\xb7\x36\x13\xcb\x8a\x79\xdc\x52\x33\x63\xe0\xb1\xca\xc0\xda\xfe\x91\x93\xc5\x4b\x29\xc4\x9d\x68\x8f\x83\xe6\x71\x7d\xe3\xa9\x06\xb7\xa3\x18\x9e\x57\x42\x54\xdc\x57\xde\x57\x77\x9d\xb3\x6d\xfc\x6f\xf1\x1c\x88\x63\xd9\xe0\x74\x23\xe1\x81\xfb\x5c\xce\x45\x29\x4f\xef\xef\x6a\xd3\x66\x33\x13\x0c\xe9\x52\xb0\xf0\x96\x1d\x43\xc6\xd2\x90\xed\x32\x49\x13\xaa\xdb\x4c\x75\x26\x22\x43\xcc\x36\xa8\xc6\x57\xff\x02\x4d\x54\x0f\x29\x75\x54\xfd\xaa\x66\x12\x16\x39\xa2\x5c\x69\x6a\x4b\x88\xbb\x46\x84\xf6\x03\x6d\x77\x7e\xd9\x3b\xfb\x08\x4a\xc8\x40\x97\x4e\x8c\x50\x0a\x4e\xe2\x74\xc7\x12\x5d\xa1\xe5\x82\x97\x38\x59\xea\x36\x48\x2b\x6c\x5c\x99\xd1\xa5\x5e\x51\xe2\x77\xab\xc3\x95\x24\x1b\xcf\x3e\xaf\x2e\x3f\x86\x29\xa0\x7d\x76\x98\x39\x9a\x60\xae\x2a\xab\x89\x3a\x60\xc4\x27\x7d\x5a\xcc\x7a\x14\xbf\xae\xf0\x2a\x98\x3d\xe7\xc9\xf0\xe7\xf0\xb6\x03\x93\x6a\x55\x39\xa9\x7e\x1c\xec\x89\xf4\x1e\x8a\x3a\x64\xa1\x2e\xa5\x67\xdd\x7e\x4d\x77\x44\xda\x98\xf1\xce\xb9\x4e\x23\xed\xe5\xe6\x53\x83\x1f\xb0\xbe\xeb\x31\x17\xcf\x0f\xb2\xf0\xdc\xc6\xc9\x9d\x77\x4a\x6e\x75\x59\x99\x1d\x3c\x70\x8b\xd0\xd9\xbd\x5f\x9c\x71\x58\x14\x2a\xd6\xd0\x3e\x01\x91\x49\xd2\x7b\xb1\xb7\x01\xae\xeb\x4b\xd4\x4d\xa0\x68\xe4\x85\x8b\x69\xac\x2a\x5d\x5e\x15\xf1\x5c\x41\xc2\x1b\x68\x66\x9e\x35\x36\xce\x56\xb6\x8d\xf6\xe3\x91\xb7\x4f\x53\xcd\x7c\x79\xbb\xd7\xd0\xbf\x7c\x0b\xe2\xd1\x43\x99\x06\x89\xe9\x56\xb7\xe6\x75\x86\x2b\x6e\x52\x10\xdf\x8f\x31\xe8\x34\x82\x08\x1f\x84\x48\x88\x39\xc5\x92\xc6\x7a\x38\x87\xef\xee\x53\xd7\x0b\x03\xb7\x3c\xfd\x6b\xe7\x30\xde\x98\xcc\x48\x2d\x08\xbb\xa5\xe0\x23\x73\xb1\x90\x05\xd2\x98\xb8\x67\x54\x85\x35\x1a\x3d\x8e\xc2\x79\x16\xbb\x9a\xd4\x44\x55\x01\xbe\x30\x26\x2e\x4f\xa7\xee\x30\x61\xd7\x86\xab\xeb\x81\x78\x02\x9a\x0d\xc6\x1b\x5d\x82\x35\x35\x9a\x09\x8f\xdd\x37\x89\x57\xf9\x9a\x0b\xd2\xe3\x15\x12\xcc\x67\x9c\x7b\x18\x71\x3f\xf9\xc6\x43\xac\x53\xd1\x43\xa5\xc0\x02\x23\xbb\x99\xfe\xf8\x98\x9a\x27\x8e\x82\xae\x90\xcc\x93\xc5\xcb\x47\x63\x97\x01\x98\xe1\xa1\x9a\x43\xcb\xc0\x3e\xea\x48\x68\x13\x37\xd5\x0f\xf6\xd6\x64\x61\xfe\xb4\xf4\xe0\x0c\x9f\x55\xff\x8d\x64\xcf\x0f\x04\x3e\xfe\x65\x80\xe2\xc6\x1b\xa3\x03\xfb\xd6\xf6\xf2\xbe\x25\x80\xdb\x1c\x5f\x0a\xd7\x75\x76\xd4\x7b\xed\x2a\x4d\x57\x72\xab\x8a\x8e\x7f\x63\x87\xba\x55\x39\x0f\x07\x89\xef\xb6\xb3\x4c\xaa\x2a\xd4\x24\xdb\x53\x5e\xe6\x1f\xb4\xab\x3d\x87\x5f\x04\x68\x5d\x18\x47\xa1\xca\x11\xb8\x3c\x2b\xf7\xe6\x21\xc1\xba\x86\x99\xc8\xaf\xbe\x2f\xb2\x02\xd5\xab\x63\xd4\x3a\x7a\x95\x64\x72\x79\x79\x65\xa8\x04\xf1\x0a\xab\x20\x61\xc8\x99\x8f\xd8\x1b\x1e\x97\xae\x54\x1a\xaf\xff\xbd\x6d\x0e\x3a\x30\x29\xbb\x2f\x30\xcd\x0d\xe9\x9b\xd1\x11\x8a\x61\xf6\x38\x1f\x11\x15\x33\xee\x75\x42\x82\xca\x11\x6a\xf5\x38\x77\x74\xb1\x57\x3b\x2a\x6d\xf5\xa4\x43\xdd\x02\x9a\x1b\x3c\xc6\xe9\xf8\x71\x07\x28\xf0\x1b\xd4\xa0\xd9\xe6\xaf\x5d\x4d\xb2\x43\x18\x99\xb2\x88\xa6\x81\x9d\xb0\x6c\x72\x4c\xe0\x11\x91\x4c\xf0\x11\xd4\x1a\x15\x60\x62\xf3\xef\x99\xfe\x60\xa3\xb9\x5e\x0d\x65\x48\xcd\xa4\x83\x74\xfe\xee\x66\xe0\xcc\x7d\xe3\xd7\xa5\x64\xc0\xc8\x36\x0d\x2f\xd1\x15\xd5\x77\x86\xe6\xa2\x3a\x88\x47\xe7\x89\x65\x0f\xa6\xa3\xe0\xb8\x73\x6b\x1b\x42\xeb\xa9\xd2\x9f\x3b\xcc\x70\x4c\x3c\xe8\x83\x10\x36\x6c\x0d\x15\xa8\x32\x44\xa7\x86\xb5\x4c\xc6\x71\xc3\x99\x70\x80\xa2\x6b\x1f\xff\x0a\x6e\x95\x77\x55\x64\x41\xa0\xd2\x58\xa4\x19\xb5\x5a\x58\x7c\x24\x5d\x66\xbe\xb8\x20\x3a\xe1\x82\xd8\x78\xd2\x4c\xd5\xde\xe8\xe5\x0a\x43\x06\x1c\x54\x81\x2b\x41\xf6\xd3\xbb\x16\x6b\x8f\x20\xf7\x5d\x86\x8c\x7a\x7a\x58\x0d\xd3\x87\x57\x14\xa9\xf2\xc9\x17\xe2\xcb\xed\x03\x57\x8e\x82\x61\xaf\xe6\x64\x6f\xeb\x4a\x5c\x6d\xa5\x05\x90\xfd\x40\x81\xe8\xe9\xfd\x87\xd2\xa0\x72\x47\xb5\xa0\xcb\x0f\x75\xbf\xca\x15\x3c\x1e\x5d\x44\x5f\x78\x16\xc1\x80\xc2\x2c\x14\x22\x4e\xe7\x31\xa9\x49\x0e\x97\x5a\x5d\xa7\xad\xf6\x74\x67\x5f\x0d\x45\x53\x0d\x17\xbb\x93\x21\x0f\x7f\x87\x2a\xec\x76\x3e\xe3\x11\xf9\x54\x89\x25\x09\x11\x39\x13\xbf\xd4\x09\x72\x14\x26\xd8\xa6\x68\xd6\xc8\x78\x48\xe7\xd6\xfc\x0c\x40\x64\xca\x83\x69\x54\x35\x99\xc1\xf6\xf7\x5d\x29\xcc\x66\x9f\x7f\x63\x17\xf5\xf1\x8d\x75\x4a\xec\x3d\x78\xaa\xec\x9b\x6b\xdf\x04\x86\x62\xa2\x0f\x44\x41\x9b\x8f\x34\x99\xdd\x45\xee\xc4\x03\x8d\x92\x15\xd9\x10\xc0\x30\x07\xc4\x81\xcf\x11\x82\x81\x1c\x83\xdf\x60\x22\xf6\x2c\xf0\xd3\x3c\xca\x6c\x16\x56\x8f\x94\x15\xe9\xc7\xfa\xe0\x1a\x38\xae\xe7\xfd\x4b\x46\xa7\x28\xe5\xb0\x6d\x24\x08\xfd\x8d\x52\xb6\xa1\xc0\xb6\xc3\x44\xb7\x65\xdf\x1b\x82\x42\x9e\x6e\xff\x87\xb7\xff\x77\x49\x97\x82\xa6\x7a\x9b\x54\x5c\x0b\x0d\x80\xc3\x0a\xda\x3e\x17\x2b\xb8\x85\xf4\xd8\x1d\x78\x75\x0c\x21\xf2\x1d\x0f\x2a\xa4\x1f\x5d\x1a\x8b\x20\x68\x78\x17\x51\x1c\x23\xe3\x47\x31\x08\x5f\x1e\x27\x6b\xf0\xf0\x06\x76\x80\xcd\x8f\xa1\x47\x9b\x22\x65\x1c\x5b\x36\x45\xb7\x70\xe9\xf4\x9b\x64\xd2\x9a\x69\xf3\x1a\xb1\x62\xda\xc6\xe8\x3e\x18\x56\x04\x41\x52\x19\x85\x56\x3a\xd2\x52\x3b\x16\x57\x5c\x46\x53\x5d\x01\x20\x3f\xf9\x4b\x7f\x16\x6d\x80\x4e\x71\x9e\x89\x75\xa2\xc2\x71\xbd\x86\x74\xc4\xc6\x70\xd9\x01\x38\x03\xf6\xdf\xde\xd9\xf9\xbf\x05\xf8\xef\x26\x3f\xf0\x71\x55\x6d\xcc\xb6\xd8\x14\xef\x1a\x1c\xdf\x5c\x0c\x9f\xee\xfc\x81\xf5\x65\x5e\xe6\x0f\xe7\x42\x94\x58\xc0\xa2\x02\xdb\x0e\xf4\x89\x9d\x26\xfb\xd1\x07\x5f\x88\x60\x63\x98\x61\xe7\x3f\x07\x37\xb0\x3f\x12\xb4\x7f\x80\x50\x18\xff\xdb\x42\xfb\x0f\x2e\x10\x64\x08\x28\x81\x03\xff\x10\xa8\x90\x62\xfa\xf7\xae\x61\x28\xe8\x21\xf2\x95\x6d\x7e\xc2\x25\x0d\x1f\x39\x7b\xf9\x06\x2a\x53\xa5\x4a\x5b\xb8\x86\xa8\x16\x2f\x5b\xbb\x7b\x07\x81\xcc\x5b\xb4\x1d\x7e\x85\x2d\x1c\x3e\xde\x3c\x7b\x43\xfe\x97\x27\xe8\xe4\xce\x18\x37\xac\x12\xb1\xc4\xb1\x7e\x8f\x1c\xc2\x28\x97\xaf\x51\xae\x58\x24\xa8\x56\x74\x62\xcb\x9c\xc2\xa9\x9c\xbe\x74\xee\xd8\x24\xa9\xcd\x03\x1a\x91\x61\x45\x50\xab\x66\xe8\xff\x55\x2f\xe7\xd6\xcd\x21\x81\x20\xc7\x13\x65\xcf\x26\xa3\xcf\x34\xe1\xfb\x3f\x13\x3c\xfd\xfc\x83\x11\x2d\xf4\xa5\x8b\x63\xdc\x49\xb2\xb0\xa1\x17\x1a\x0c\x1c\x47\xf7\x1f\xe8\x7b\x71\x20\xd0\x69\x92\x5d\xc8\x85\x80\x08\x85\xbc\x2a\xeb\xab\x5c\x93\x51\x0d\x15\x59\x2d\xe0\x30\x97\xcc\x34\xf7\x8d\xb8\xbb\x8e\xbc\x27\x37\x08\x84\x7e\x84\xc8\x5d\x18\x19\x10\xca\xe4\xcd\x1f\xba\xf1\xc8\x8a\xd3\x50\x9b\xb5\x58\xf0\x8b\x28\xde\xb0\x4c\xe6\xa1\x84\xce\x92\xc2\xc6\xc3\x20\xef\xf4\x64\xc7\xc5\xa8\xd7\x56\xde\xf1\x1b\x14\x19\x0c\x25\x5d\x28\x26\x95\x04\x27\xd3\x28\x72\x01\x15\x63\x45\x09\x61\x89\x85\x40\xcd\x31\xbc\x09\x16\xed\xff\xc6\x4f\x3a\xc3\x4a\x9e\xbe\xe4\x40\x6f\xed\xaa\xe3\x6d\x9a\xf9\xc9\x49\x70\xc1\xb9\xad\x16\x2b\x6d\x6c\x20\x3a\xa0\xe0\xc9\x2e\xda\x50\xf3\x5b\xd8\x20\x30\xfc\x95\x3b\xc7\x36\x30\xc7\x90\x58\xf2\xd0\xa6\x59\x5d\x1f\xc8\x2b\xe1\xbb\x90\x12\x51\x6f\x94\x64\xb1\x74\xe5\x24\xed\xa3\x11\x1b\x37\x94\xff\x51\xaa\x7e\x4a\x23\xff\x97\x99\xf3\x9f\x8a\xd6\xb4\x63\x77\xe2\x62\x11\x14\xba\x3b\xec\x27\xb8\x19\xbe\x32\x56\xa1\xf9\x33\x21\xbc\xf7\x95\x01\x69\xa3\xb8\xb5\xb0\xe2\xb2\xa0\xa5\x52\x7c\x73\x99\x91\x24\x9c\xba\xd3\x56\xe0\xc4\xf4\xdf\x74\x4d\x3e\x3c\x2d\x99\x0e\x5a\x83\xf0\x37\xba\xd5\xbc\x54\xae\xd8\x4b\x64\x5c\x8f\x3b\x03\x5f\xdc\x7b\xd2\xe7\x2a\xd6\x8c\x81\xb7\x50\x59\x2d\xca\xb1\x22\x88\x91\x07\x5d\x33\x13\xc0\x50\x7f\x6e\x78\x62\xe7\x0f\x5a\x5e\x7e\x9f\x6d\x3f\xb2\x84\x75\x45\xe2\xf3\x07\xaa\x3f\xbc\xc5\x4e\x89\xe9\x98\x2a\xbe\x5a\x81\xbd\xb9\xef\x64\x73\x0e\x4a\x8e\xf2\xad\x58\xf4\xcf\xd1\x2a\x86\xe4\xc4\x5a\xd9\x75\x62\x0a\xbc\x61\x7e\xfc\x8a\x71\xd6\x1b\x09\x66\x34\x5c\x6b\x39\x2e\x2d\x4e\xf1\x01\xbd\x25\x46\x97\xcb\x22\xa9\x9e\xdb\x11\x84\x90\x6f\xe3\xf1\x9d\xc3\xdc\xb0\x0d\x57\xa1\x63\xeb\xdf\x54\x5a\x19\xb1\x52\xe1\x7e\x5e\x31\xe8\xaf\x43\xf6\x1b\x40\x47\x79\x20\x2e\xbe\x8a\x91\x0f\x6a\x81\x06\x0d\x29\x7e\x7b\x79\x8c\x6c\x3b\x7e\xce\xdd\xc2\x87\x0c\x1c\xa5\xa1\x5b\x9c\x57\xb2\x82\x9f\x37\x55\x2b\x84\xd2\x8d\x7b\x09\x5a\x2e\x19\x8a\xf7\x42\xb9\x4d\x3f\x64\x6b\x60\x40\x4f\x89\x39\xde\xb5\xd0\x0a\x1e\xba\x15\x81\xcf\x24\x8a\x88\xd6\x5b\xfd\x28\x9f\xca\x08\xa8\x2a\x19\x80\x80\xed\x26\xac\xe5\x5d\x9c\x60\xe6\xee\xbd\xf8\xec\xbf\x12\xf3\x3b\x56\x8f\x5d\x71\xd9\x90\x6b\x62\xc5\x1c\x7c\x13\xb7\x0c\xda\x3b\x5b\x01\x98\x23\x4f\x97\x3a\x72\x6d\x1a\x76\x43\x34\xb0\xe2\xb7\x68\xd0\x31\x17\x08\xfa\x53\x5c\xb9\x15\xbf\xdf\x0d\xa6\xe1\x4d\x02\x3c\xe2\x98\x73\x51\xb9\x87\x68\x8c\xec\xc4\xaf\x23\x44\x46\x04\x82\x62\x6a\x65\xd8\x2d\x9b\xa7\x2b\x1b\x7d\x66\xc4\x22\xf5\x86\xe3\x74\xfc\x24\xca\xa1\x03\x3d\xb1\xcd\x1f\xd4\x66\xf9\xc6\xc3\xc2\x37\x3f\x44\xee\xfd\x1b\x3a\xa8\x48\xae\xd2\x8c\x83\xe4\xde\x37\x95\xdb\x0a\xef\x60\xd3\xe5\xfc\xc6\xee\x13\x27\x84\x60\x13\x3d\x7e\xe1\xc6\x2c\x7d\xea\xaa\x22\x01\x95\x3b\xca\xad\x7d\x4a\xa9\xeb\x72\x7b\x75\xcd\x67\x33\x8e\x68\x49\x5b\x4c\x6d\x4a\xd0\x21\x83\xbc\xdc\x98\xe5\xac\x95\x92\x07\xbb\x72\x1f\x09\x20\x96\x70\x59\xde\x8f\xc8\xf4\x02\xb8\x58\xa9\xd9\xbc\x52\x0c\x16\x7d\xb1\x76\x49\xe9\x42\x92\x8f\xe3\x2a\xc5\x73\x9e\x66\x60\x7f\x4c\xfe\xa6\xcb\x15\x8f\x59\xc0\x06\x77\xb4\xdf\x12\x53\xdc\x98\x0d\x1f\xe6\x59\x7a\x84\x86\xf3\xd6\x37\x2b\x5a\x15\x28\xe3\x26\x3b\xbc\x25\x10\x85\x79\x9b\x5f\x3a\xa1\x30\x0c\x15\xd8\xf2\x58\x9f\x46\x38\xce\xd8\xe8\x41\xce\xf9\xad\xd8\xe8\x20\xc9\x9f\xac\xd5\xdf\x48\xc4\x5a\xbe\xf3\x6d\xdd\x11\x58\x48\x76\xf0\xee\x17\x9a\x7f\x8c\x16\x26\xad\x28\xdd\x15\xd8\xe5\x89\xa4\x39\x27\x0f\x5c\x80\x29\x89\x7f\xe8\xbf\xe1\x97\x1f\xd0\x42\x29\x38\xc1\x7d\x0a\x35\xd1\xc3\x96\x7e\x73\x1f\x8a\x97\xe8\xfe\x21\xcc\x7f\x36\xfd\xca\xa3\x62\xef\x14\x92\x55\x31\x85\x9d\xcc\xd3\x7c\x1f\x6f\x50\xaa\xcb\x40\x56\x44\x7f\xf0\x6d\xb2\xcd\x6e\x1c\x12\x7d\xb9\xf7\x39\xfe\xa1\xff\x94\x6c\x8b\x35\xd4\x1c\xc8\x43\x74\xf9\x4d\x65\x85\x70\x7e\x0c\x20\x1e\x1f\xb0\xec\x59\xf1\xb8\xbf\x4f\x6b\xe1\xc5\x7f\x37\x41\x2a\xf7\x71\xd5\x81\x2d\x66\xa2\x10\xb8\xd1\xbd\xa4\x4e\xf3\xe1\x6e\x39\x0b\x56\x0f\x1c\x87\xd9\x9f\xf2\x34\x0a\xac\xed\xc9\xc4\xed\xd0\xfa\x14\x1f\xa6\xf7\xe1\x3e\x53\x96\x05\x64\x89\xb6\xc0\x86\x4e\x5d\xb5\xa2\x04\x71\x04\x75\x78\x68\xa5\xba\x24\xbf\x39\x31\x8b\x35\x5d\x59\x31\x24\xcd\xef\x2c\xae\xfd\x24\xb4\xf8\xfa\x76\x9f\x16\xb9\x32\x64\x8b\x6c\x48\xb1\xe5\x7f\xc5\x75\xe2\x23\x60\xe9\xc4\xdc\xad\x75\x0b\x0c\x4a\x62\xf0\x28\xd4\x3a\x60\x6f\xf3\x19\x9e\xc4\xb8\xf3\x5d\x1a\x7a\xbc\xb1\x2b\x67\x51\x69\xd3\xa5\x18\x79\x47\xd2\xbe\x65\xbe\x4f\x3c\x91\x1d\xfb\x4c\x64\xf5\xaf\xc6\x3f\x9a\x45\x49\xff\x40\xdb\xdc\x68\x8e\x33\x77\x6e\x4b\x10\xb8\x81\x10\xd4\xaa\xa9\x87\x1a\xbe\xe1\x5a\x52\x58\x54\xeb\x7a\x40\x63\xdd\xbc\x65\x2c\x97\x70\x4c\x02\x37\x2f\xaf\x36\x1d\xb1\x5d\x08\xa4\xc7\x0a\xb5\x82\x15\x2b\x1e\x40\xc4\x3e\xe9\x9c\x31\x1f\x95\x45\xe4\xbd\x2a\xf4\x7c\x06\x42\x54\x7e\x49\x99\x27\xdb\xcd\xe3\x4b\x53\x1c\xfb\x68\x69\xc3\xb8\x59\x72\x44\xdd\x05\xca\x98\xc4\x56\x74\x1b\x95\xca\x3a\x09\xf4\x76\xc7\x47\x71\x99\xf9\x96\x98\x08\x49\x4c\x35\x7e\xaf\x16\x72\x50\xef\x8b\x96\xd6\x8b\x78\x7d\x68\x94\x68\xa7\xcd\x0c\x41\x9c\x5a\xff\xa2\x2a\xaa\x45\x19\xdf\xdb\x82\xcf\x36\x10\x3c\x7f\xbd\xe7\x5b\x5a\xe0\xb4\xa6\x33\xa2\xbf\x31\x6e\x32\xa5\xd7\x5b\xaa\xbb\x5e\xfa\xdb\x82\xdb\x6e\xe8\x11\x6f\xc3\x3a\xf4\xd4\x71\x1c\x13\xa7\x77\x4f\x18\xf6\x2f\xe2\xb8\x9c\xc7\xae\x42\x0c\x4a\x9f\x3a\xb4\xd8\x47\x1b\xf3\xa8\x51\x5a\x2c\x9b\x4a\xb9\x19\xbc\x3e\xaf\x47\x8e\xaf\x9e\xb4\x08\x11\xf7\x23\xef\x11\x45\x74\x56\xf9\xfc\x33\xde\x4f\x2b\xce\x06\xa3\x9e\x76\x57\xc7\x83\xd3\xd5\x71\xb9\x57\xb5\x67\xd7\x1a\x6d\x8c\x62\x71\x5d\x28\xc9\x3e\x09\x04\x72\xde\xb7\xd0\xc0\x21\x13\x72\x74\xc4\xd5\xdc\x3c\xd5\x7c\xf2\x6f\xa8\x92\x2a\x53\x10\xac\xef\x01\xaa\x23\xb7\x57\xf2\xd0\x75\x7f\x25\x24\x68\x54\x91\xbd\x4b\x87\x94\xde\x25\x08\xe5\x7a\xe6\x98\x73\x54\xfc\x74\xd2\x50\xed\x60\x7f\x6d\xfd\x3b\xfc\x86\x10\x72\x51\x94\x55\x37\x73\x53\x02\xb9\xeb\xe2\xa6\x44\x28\x6f\xf6\x24\x85\x5f\x84\xc6\x31\x7e\x59\xd8\xfb\xdd\x7a\x7e\x7c\x13\xb6\xd3\x71\xaf\xa2\xb3\x94\x8c\xdf\x18\x01\x21\x7f\xb9\xb8\x70\x97\x2a\x2a\xf3\x36\x21\x60\x75\x34\x1d\xa0\x01\xaa\x72\x25\x4a\xae\x9b\x34\x92\xfd\x52\x21\xf7\x90\x0d\x49\x2b\x28\x0f\xab\xe0\xe7\x79\x58\x9a\x71\x98\x3b\xee\x88\xb3\xc6\x7f\xa0\xae\x03\x9b\xe6\xb5\x70\x35\x61\xd4\xcd\xee\x20\x26\xaa\x87\x29\x2c\x7e\xd6\x18\x41\x15\x72\xea\xdb\x0e\x78\x67\x9c\x49\xba\xb1\x5b\x3d\xb2\xa0\xbf\x9b\xc1\xc6\x9a\xe6\x44\x4b\x65\x99\x03\x39\x54\x75\x8c\x21\x9d\x2e\xe6\x05\x86\x16\x1f\x5b\x43\x2b\x39\xdc\x0b\xd3\xa9\xdb\x7d\x32\xda\x0c\x5d\x03\xda\xe9\x8d\x19\xaf\x7f\x1d\x13\x63\x37\x6f\x34\xe6\x44\xfd\x83\x7d\x01\x6d\x01\x9e\x24\xdd\x84\x22\x48\xf3\xd7\xc4\xdc\xc5\xae\xbb\x7d\xb6\xc5\x58\x96\x84\x08\x75\x79\xed\x34\xfb\x74\x2c\x60\x42\x13\xf1\x57\x8d\x1f\x17\x6b\x8c\x74\x22\xce\x92\x0a\x35\xdc\x45\xe6\x6c\xfa\x82\x55\x09\x7d\xf9\x13\x7e\xc3\x62\x19\xce\x79\xd5\x2e\x52\x57\xa6\x47\x3d\xfc\xf1\x63\x59\xf8\x4d\xaa\xce\xa5\x14\xd6\x3d\x00\xcd\x62\xe0\xe2\x52\xac\xcb\xfc\x8b\x85\xd0\xe3\xb4\xc6\x22\xfc\xc1\xa6\x7b\x7d\x30\x80\x30\xa1\xb7\xa9\xef\xc8\xe9\x2d\xb6\x9d\x7f\xe0\x95\xf0\xc8\x92\x95\x84\x5d\xc6\x57\x72\xcb\x74\xaf\x05\x73\x7f\x4d\x7c\x5e\xfb\x2b\x6e\xef\x10\x5e\x4c\xa2\x6a\x1a\xe8\x93\xfb\x15\xa5\xf1\xc6\xac\xe8\xf9\x79\x70\xd7\xce\x16\xe5\x11\x99\x1a\xc3\xb3\xe1\xaf\x41\xd4\xed\xef\xc7\xe2\xf9\x5c\x16\x9f\x7b\xf5\x62\xb6\xb6\x60\x79\x9e\x4b\x0e\x89\x5d\xcf\xf3\xe4\xd9\x2d\xbc\xe7\x97\x0b\x0d\x01\x01\x81\xac\x25\x2a\x2e\x68\xb3\x01\xe6\x7c\xbf\x6d\x59\x69\xa2\x8f\x13\xbe\xf7\x55\x19\x6a\x8d\x39\xf2\x5f\x7f\x8d\x4c\x0e\x45\x0d\x89\xd4\xce\xaa\xef\x14\x83\xda\xbe\x78\x7f\xde\x9e\xb9\xf2\x1b\xb8\xdb\x11\x14\x8d\x13\xc6\xca\x2f\x38\x84\x5e\xb9\x9a\xc5\x0f\xe1\x31\x43\x85\x50\x1f\x5a\x9f\x12\xb0\xab\xde\x7a\xcc\xa2\x04\xb0\xf8\x00\xcc\x6a\xce\x0a\x78\xb3\x61\xd4\x87\xd6\xdf\xb7\x16\x3e\x8c\xb2\xf6\xdf\xa7\xb8\x7e\xff\x4f\x1f\x81\x1f\x50\x0c\xa6\x0e\x23\x97\xd1\xa7\x94\x14\x14\x14\x0c\xc5\xc9\xaa\xb2\xf4\x12\xe2\xe2\xe2\xe2\x43\x53\x53\x53\x53\x59\x40\xbe\x8a\x52\xc0\xf4\xf2\xe8\x4f\x4e\x5d\xbb\x6a\xab\x40\x4c\xf4\xff\x01\x0a\x2c\xb3\xf6\x7e\x8c\xec\x25\xfa\x68\x8d\xfe\xfc\x49\xb3\x5d\xeb\xc1\x12\x3b\xb8\xab\x93\xa5\xf8\x32\x19\xb5\xd4\x83\xdf\x69\x25\x2d\x22\x51\x35\xbd\x4a\xfc\xff\xef\x8a\x8b\x79\x7c\xc0\xf1\xc7\x37\x4d\x71\xdd\x6a\xea\xcf\x1b\xf3\xde\x18\x37\x10\xff\x0f\xcb\xff\xd0\xd4\xf8\x8f\x46\x9b\x8e\x0e\x1f\xef\xb7\x92\xa4\xec\x80\x60\x9e\x6e\x45\xf3\x6a\x48\x88\xff\x17\x00\x00\xff\xff\xa7\xc3\x17\x55\x68\x2d\x01\x00")
+
+func uiAppLibFontAwesome470FontsFontawesomeWebfontWoff2Bytes() ([]byte, error) {
+ return bindataRead(
+ _uiAppLibFontAwesome470FontsFontawesomeWebfontWoff2,
+ "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2",
+ )
+}
+
+func uiAppLibFontAwesome470FontsFontawesomeWebfontWoff2() (*asset, error) {
+ bytes, err := uiAppLibFontAwesome470FontsFontawesomeWebfontWoff2Bytes()
+ if err != nil {
+ return nil, err
+ }
+
+ info := bindataFileInfo{name: "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2", size: 77160, mode: os.FileMode(420), modTime: time.Unix(1, 0)}
+ a := &asset{bytes: bytes, info: info}
+ return a, nil
+}
+
+// Asset loads and returns the asset for the given name.
+// It returns an error if the asset could not be found or
+// could not be loaded.
+func Asset(name string) ([]byte, error) {
+ cannonicalName := strings.Replace(name, "\\", "/", -1)
+ if f, ok := _bindata[cannonicalName]; ok {
+ a, err := f()
+ if err != nil {
+ return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
+ }
+ return a.bytes, nil
+ }
+ return nil, fmt.Errorf("Asset %s not found", name)
+}
+
+// MustAsset is like Asset but panics when Asset would return an error.
+// It simplifies safe initialization of global variables.
+func MustAsset(name string) []byte {
+ a, err := Asset(name)
+ if err != nil {
+ panic("asset: Asset(" + name + "): " + err.Error())
+ }
+
+ return a
+}
+
+// AssetInfo loads and returns the asset info for the given name.
+// It returns an error if the asset could not be found or
+// could not be loaded.
+func AssetInfo(name string) (os.FileInfo, error) {
+ cannonicalName := strings.Replace(name, "\\", "/", -1)
+ if f, ok := _bindata[cannonicalName]; ok {
+ a, err := f()
+ if err != nil {
+ return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
+ }
+ return a.info, nil
+ }
+ return nil, fmt.Errorf("AssetInfo %s not found", name)
+}
+
+// AssetNames returns the names of the assets.
+func AssetNames() []string {
+ names := make([]string, 0, len(_bindata))
+ for name := range _bindata {
+ names = append(names, name)
+ }
+ return names
+}
+
+// _bindata is a table, holding each asset generator, mapped to its name.
+var _bindata = map[string]func() (*asset, error){
+ "ui/app/script.js": uiAppScriptJs,
+ "ui/app/index.html": uiAppIndexHtml,
+ "ui/app/favicon.ico": uiAppFaviconIco,
+ "ui/app/lib/bootstrap-4.0.0-alpha.6-dist/css/bootstrap.min.css": uiAppLibBootstrap400Alpha6DistCssBootstrapMinCss,
+ "ui/app/lib/bootstrap-4.0.0-alpha.6-dist/css/bootstrap.min.css.map": uiAppLibBootstrap400Alpha6DistCssBootstrapMinCssMap,
+ "ui/app/lib/font-awesome-4.7.0/css/font-awesome.css": uiAppLibFontAwesome470CssFontAwesomeCss,
+ "ui/app/lib/font-awesome-4.7.0/css/font-awesome.min.css": uiAppLibFontAwesome470CssFontAwesomeMinCss,
+ "ui/app/lib/font-awesome-4.7.0/fonts/FontAwesome.otf": uiAppLibFontAwesome470FontsFontawesomeOtf,
+ "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.eot": uiAppLibFontAwesome470FontsFontawesomeWebfontEot,
+ "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.svg": uiAppLibFontAwesome470FontsFontawesomeWebfontSvg,
+ "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.ttf": uiAppLibFontAwesome470FontsFontawesomeWebfontTtf,
+ "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.woff": uiAppLibFontAwesome470FontsFontawesomeWebfontWoff,
+ "ui/app/lib/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2": uiAppLibFontAwesome470FontsFontawesomeWebfontWoff2,
+}
+
+// AssetDir returns the file names below a certain
+// directory embedded in the file by go-bindata.
+// For example if you run go-bindata on data/... and data contains the
+// following hierarchy:
+// data/
+// foo.txt
+// img/
+// a.png
+// b.png
+// then AssetDir("data") would return []string{"foo.txt", "img"}
+// AssetDir("data/img") would return []string{"a.png", "b.png"}
+// AssetDir("foo.txt") and AssetDir("notexist") would return an error
+// AssetDir("") will return []string{"data"}.
+func AssetDir(name string) ([]string, error) {
+ node := _bintree
+ if len(name) != 0 {
+ cannonicalName := strings.Replace(name, "\\", "/", -1)
+ pathList := strings.Split(cannonicalName, "/")
+ for _, p := range pathList {
+ node = node.Children[p]
+ if node == nil {
+ return nil, fmt.Errorf("Asset %s not found", name)
+ }
+ }
+ }
+ if node.Func != nil {
+ return nil, fmt.Errorf("Asset %s not found", name)
+ }
+ rv := make([]string, 0, len(node.Children))
+ for childName := range node.Children {
+ rv = append(rv, childName)
+ }
+ return rv, nil
+}
+
+type bintree struct {
+ Func func() (*asset, error)
+ Children map[string]*bintree
+}
+
+var _bintree = &bintree{nil, map[string]*bintree{
+ "ui": &bintree{nil, map[string]*bintree{
+ "app": &bintree{nil, map[string]*bintree{
+ "favicon.ico": &bintree{uiAppFaviconIco, map[string]*bintree{}},
+ "index.html": &bintree{uiAppIndexHtml, map[string]*bintree{}},
+ "lib": &bintree{nil, map[string]*bintree{
+ "bootstrap-4.0.0-alpha.6-dist": &bintree{nil, map[string]*bintree{
+ "css": &bintree{nil, map[string]*bintree{
+ "bootstrap.min.css": &bintree{uiAppLibBootstrap400Alpha6DistCssBootstrapMinCss, map[string]*bintree{}},
+ "bootstrap.min.css.map": &bintree{uiAppLibBootstrap400Alpha6DistCssBootstrapMinCssMap, map[string]*bintree{}},
+ }},
+ }},
+ "font-awesome-4.7.0": &bintree{nil, map[string]*bintree{
+ "css": &bintree{nil, map[string]*bintree{
+ "font-awesome.css": &bintree{uiAppLibFontAwesome470CssFontAwesomeCss, map[string]*bintree{}},
+ "font-awesome.min.css": &bintree{uiAppLibFontAwesome470CssFontAwesomeMinCss, map[string]*bintree{}},
+ }},
+ "fonts": &bintree{nil, map[string]*bintree{
+ "FontAwesome.otf": &bintree{uiAppLibFontAwesome470FontsFontawesomeOtf, map[string]*bintree{}},
+ "fontawesome-webfont.eot": &bintree{uiAppLibFontAwesome470FontsFontawesomeWebfontEot, map[string]*bintree{}},
+ "fontawesome-webfont.svg": &bintree{uiAppLibFontAwesome470FontsFontawesomeWebfontSvg, map[string]*bintree{}},
+ "fontawesome-webfont.ttf": &bintree{uiAppLibFontAwesome470FontsFontawesomeWebfontTtf, map[string]*bintree{}},
+ "fontawesome-webfont.woff": &bintree{uiAppLibFontAwesome470FontsFontawesomeWebfontWoff, map[string]*bintree{}},
+ "fontawesome-webfont.woff2": &bintree{uiAppLibFontAwesome470FontsFontawesomeWebfontWoff2, map[string]*bintree{}},
+ }},
+ }},
+ }},
+ "script.js": &bintree{uiAppScriptJs, map[string]*bintree{}},
+ }},
+ }},
+}}
+
+// RestoreAsset restores an asset under the given directory
+func RestoreAsset(dir, name string) error {
+ data, err := Asset(name)
+ if err != nil {
+ return err
+ }
+ info, err := AssetInfo(name)
+ if err != nil {
+ return err
+ }
+ err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
+ if err != nil {
+ return err
+ }
+ err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
+ if err != nil {
+ return err
+ }
+ err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// RestoreAssets restores an asset under the given directory recursively
+func RestoreAssets(dir, name string) error {
+ children, err := AssetDir(name)
+ // File
+ if err != nil {
+ return RestoreAsset(dir, name)
+ }
+ // Dir
+ for _, child := range children {
+ err = RestoreAssets(dir, filepath.Join(name, child))
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func _filePath(dir, name string) string {
+ cannonicalName := strings.Replace(name, "\\", "/", -1)
+ return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
+}
--- /dev/null
+// Copyright 2015 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ui
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "net/http"
+ _ "net/http/pprof" // Comment this line to disable pprof endpoint.
+ "path/filepath"
+
+ "github.com/go-kit/kit/log"
+ "github.com/go-kit/kit/log/level"
+ "github.com/prometheus/client_golang/prometheus/promhttp"
+ "github.com/prometheus/common/route"
+)
+
+func serveAsset(w http.ResponseWriter, req *http.Request, fp string, logger log.Logger) {
+ info, err := AssetInfo(fp)
+ if err != nil {
+ level.Warn(logger).Log("msg", "Could not get file", "err", err)
+ w.WriteHeader(http.StatusNotFound)
+ return
+ }
+ file, err := Asset(fp)
+ if err != nil {
+ if err != io.EOF {
+ level.Warn(logger).Log("msg", "Could not get file", "file", fp, "err", err)
+ }
+ w.WriteHeader(http.StatusNotFound)
+ return
+ }
+
+ w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
+ http.ServeContent(w, req, info.Name(), info.ModTime(), bytes.NewReader(file))
+}
+
+// Register registers handlers to serve files for the web interface.
+func Register(r *route.Router, reloadCh chan<- chan error, logger log.Logger) {
+ r.Get("/metrics", promhttp.Handler().ServeHTTP)
+
+ r.Get("/", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ serveAsset(w, req, "ui/app/index.html", logger)
+ }))
+
+ r.Get("/script.js", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ serveAsset(w, req, "ui/app/script.js", logger)
+ }))
+
+ r.Get("/favicon.ico", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ serveAsset(w, req, "ui/app/favicon.ico", logger)
+ }))
+
+ r.Get("/lib/*filepath", http.HandlerFunc(
+ func(w http.ResponseWriter, req *http.Request) {
+ fp := route.Param(req.Context(), "filepath")
+ serveAsset(w, req, filepath.Join("ui/app/lib", fp), logger)
+ },
+ ))
+
+ r.Post("/-/reload", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ errc := make(chan error)
+ defer close(errc)
+
+ reloadCh <- errc
+ if err := <-errc; err != nil {
+ http.Error(w, fmt.Sprintf("failed to reload config: %s", err), http.StatusInternalServerError)
+ }
+ }))
+
+ r.Get("/-/healthy", http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
+ w.WriteHeader(http.StatusOK)
+ fmt.Fprintf(w, "OK")
+ }))
+ r.Get("/-/ready", http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
+ w.WriteHeader(http.StatusOK)
+ fmt.Fprintf(w, "OK")
+ }))
+
+ r.Get("/debug/*subpath", http.DefaultServeMux.ServeHTTP)
+ r.Post("/debug/*subpath", http.DefaultServeMux.ServeHTTP)
+}
--- /dev/null
+Copyright (c) 2012 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- /dev/null
+# Go's `text/template` package with newline elision
+
+This is a fork of Go 1.4's [text/template](http://golang.org/pkg/text/template/) package with one addition: a backslash immediately after a closing delimiter will delete all subsequent newlines until a non-newline.
+
+eg.
+
+```
+{{if true}}\
+hello
+{{end}}\
+```
+
+Will result in:
+
+```
+hello\n
+```
+
+Rather than:
+
+```
+\n
+hello\n
+\n
+```
--- /dev/null
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package template implements data-driven templates for generating textual output.
+
+To generate HTML output, see package html/template, which has the same interface
+as this package but automatically secures HTML output against certain attacks.
+
+Templates are executed by applying them to a data structure. Annotations in the
+template refer to elements of the data structure (typically a field of a struct
+or a key in a map) to control execution and derive values to be displayed.
+Execution of the template walks the structure and sets the cursor, represented
+by a period '.' and called "dot", to the value at the current location in the
+structure as execution proceeds.
+
+The input text for a template is UTF-8-encoded text in any format.
+"Actions"--data evaluations or control structures--are delimited by
+"{{" and "}}"; all text outside actions is copied to the output unchanged.
+Actions may not span newlines, although comments can.
+
+Once parsed, a template may be executed safely in parallel.
+
+Here is a trivial example that prints "17 items are made of wool".
+
+ type Inventory struct {
+ Material string
+ Count uint
+ }
+ sweaters := Inventory{"wool", 17}
+ tmpl, err := template.New("test").Parse("{{.Count}} items are made of {{.Material}}")
+ if err != nil { panic(err) }
+ err = tmpl.Execute(os.Stdout, sweaters)
+ if err != nil { panic(err) }
+
+More intricate examples appear below.
+
+Actions
+
+Here is the list of actions. "Arguments" and "pipelines" are evaluations of
+data, defined in detail below.
+
+*/
+// {{/* a comment */}}
+// A comment; discarded. May contain newlines.
+// Comments do not nest and must start and end at the
+// delimiters, as shown here.
+/*
+
+ {{pipeline}}
+ The default textual representation of the value of the pipeline
+ is copied to the output.
+
+ {{if pipeline}} T1 {{end}}
+ If the value of the pipeline is empty, no output is generated;
+ otherwise, T1 is executed. The empty values are false, 0, any
+ nil pointer or interface value, and any array, slice, map, or
+ string of length zero.
+ Dot is unaffected.
+
+ {{if pipeline}} T1 {{else}} T0 {{end}}
+ If the value of the pipeline is empty, T0 is executed;
+ otherwise, T1 is executed. Dot is unaffected.
+
+ {{if pipeline}} T1 {{else if pipeline}} T0 {{end}}
+ To simplify the appearance of if-else chains, the else action
+ of an if may include another if directly; the effect is exactly
+ the same as writing
+ {{if pipeline}} T1 {{else}}{{if pipeline}} T0 {{end}}{{end}}
+
+ {{range pipeline}} T1 {{end}}
+ The value of the pipeline must be an array, slice, map, or channel.
+ If the value of the pipeline has length zero, nothing is output;
+ otherwise, dot is set to the successive elements of the array,
+ slice, or map and T1 is executed. If the value is a map and the
+ keys are of basic type with a defined order ("comparable"), the
+ elements will be visited in sorted key order.
+
+ {{range pipeline}} T1 {{else}} T0 {{end}}
+ The value of the pipeline must be an array, slice, map, or channel.
+ If the value of the pipeline has length zero, dot is unaffected and
+ T0 is executed; otherwise, dot is set to the successive elements
+ of the array, slice, or map and T1 is executed.
+
+ {{template "name"}}
+ The template with the specified name is executed with nil data.
+
+ {{template "name" pipeline}}
+ The template with the specified name is executed with dot set
+ to the value of the pipeline.
+
+ {{with pipeline}} T1 {{end}}
+ If the value of the pipeline is empty, no output is generated;
+ otherwise, dot is set to the value of the pipeline and T1 is
+ executed.
+
+ {{with pipeline}} T1 {{else}} T0 {{end}}
+ If the value of the pipeline is empty, dot is unaffected and T0
+ is executed; otherwise, dot is set to the value of the pipeline
+ and T1 is executed.
+
+Arguments
+
+An argument is a simple value, denoted by one of the following.
+
+ - A boolean, string, character, integer, floating-point, imaginary
+ or complex constant in Go syntax. These behave like Go's untyped
+ constants, although raw strings may not span newlines.
+ - The keyword nil, representing an untyped Go nil.
+ - The character '.' (period):
+ .
+ The result is the value of dot.
+ - A variable name, which is a (possibly empty) alphanumeric string
+ preceded by a dollar sign, such as
+ $piOver2
+ or
+ $
+ The result is the value of the variable.
+ Variables are described below.
+ - The name of a field of the data, which must be a struct, preceded
+ by a period, such as
+ .Field
+ The result is the value of the field. Field invocations may be
+ chained:
+ .Field1.Field2
+ Fields can also be evaluated on variables, including chaining:
+ $x.Field1.Field2
+ - The name of a key of the data, which must be a map, preceded
+ by a period, such as
+ .Key
+ The result is the map element value indexed by the key.
+ Key invocations may be chained and combined with fields to any
+ depth:
+ .Field1.Key1.Field2.Key2
+ Although the key must be an alphanumeric identifier, unlike with
+ field names they do not need to start with an upper case letter.
+ Keys can also be evaluated on variables, including chaining:
+ $x.key1.key2
+ - The name of a niladic method of the data, preceded by a period,
+ such as
+ .Method
+ The result is the value of invoking the method with dot as the
+ receiver, dot.Method(). Such a method must have one return value (of
+ any type) or two return values, the second of which is an error.
+ If it has two and the returned error is non-nil, execution terminates
+ and an error is returned to the caller as the value of Execute.
+ Method invocations may be chained and combined with fields and keys
+ to any depth:
+ .Field1.Key1.Method1.Field2.Key2.Method2
+ Methods can also be evaluated on variables, including chaining:
+ $x.Method1.Field
+ - The name of a niladic function, such as
+ fun
+ The result is the value of invoking the function, fun(). The return
+ types and values behave as in methods. Functions and function
+ names are described below.
+ - A parenthesized instance of one the above, for grouping. The result
+ may be accessed by a field or map key invocation.
+ print (.F1 arg1) (.F2 arg2)
+ (.StructValuedMethod "arg").Field
+
+Arguments may evaluate to any type; if they are pointers the implementation
+automatically indirects to the base type when required.
+If an evaluation yields a function value, such as a function-valued
+field of a struct, the function is not invoked automatically, but it
+can be used as a truth value for an if action and the like. To invoke
+it, use the call function, defined below.
+
+A pipeline is a possibly chained sequence of "commands". A command is a simple
+value (argument) or a function or method call, possibly with multiple arguments:
+
+ Argument
+ The result is the value of evaluating the argument.
+ .Method [Argument...]
+ The method can be alone or the last element of a chain but,
+ unlike methods in the middle of a chain, it can take arguments.
+ The result is the value of calling the method with the
+ arguments:
+ dot.Method(Argument1, etc.)
+ functionName [Argument...]
+ The result is the value of calling the function associated
+ with the name:
+ function(Argument1, etc.)
+ Functions and function names are described below.
+
+Pipelines
+
+A pipeline may be "chained" by separating a sequence of commands with pipeline
+characters '|'. In a chained pipeline, the result of the each command is
+passed as the last argument of the following command. The output of the final
+command in the pipeline is the value of the pipeline.
+
+The output of a command will be either one value or two values, the second of
+which has type error. If that second value is present and evaluates to
+non-nil, execution terminates and the error is returned to the caller of
+Execute.
+
+Variables
+
+A pipeline inside an action may initialize a variable to capture the result.
+The initialization has syntax
+
+ $variable := pipeline
+
+where $variable is the name of the variable. An action that declares a
+variable produces no output.
+
+If a "range" action initializes a variable, the variable is set to the
+successive elements of the iteration. Also, a "range" may declare two
+variables, separated by a comma:
+
+ range $index, $element := pipeline
+
+in which case $index and $element are set to the successive values of the
+array/slice index or map key and element, respectively. Note that if there is
+only one variable, it is assigned the element; this is opposite to the
+convention in Go range clauses.
+
+A variable's scope extends to the "end" action of the control structure ("if",
+"with", or "range") in which it is declared, or to the end of the template if
+there is no such control structure. A template invocation does not inherit
+variables from the point of its invocation.
+
+When execution begins, $ is set to the data argument passed to Execute, that is,
+to the starting value of dot.
+
+Examples
+
+Here are some example one-line templates demonstrating pipelines and variables.
+All produce the quoted word "output":
+
+ {{"\"output\""}}
+ A string constant.
+ {{`"output"`}}
+ A raw string constant.
+ {{printf "%q" "output"}}
+ A function call.
+ {{"output" | printf "%q"}}
+ A function call whose final argument comes from the previous
+ command.
+ {{printf "%q" (print "out" "put")}}
+ A parenthesized argument.
+ {{"put" | printf "%s%s" "out" | printf "%q"}}
+ A more elaborate call.
+ {{"output" | printf "%s" | printf "%q"}}
+ A longer chain.
+ {{with "output"}}{{printf "%q" .}}{{end}}
+ A with action using dot.
+ {{with $x := "output" | printf "%q"}}{{$x}}{{end}}
+ A with action that creates and uses a variable.
+ {{with $x := "output"}}{{printf "%q" $x}}{{end}}
+ A with action that uses the variable in another action.
+ {{with $x := "output"}}{{$x | printf "%q"}}{{end}}
+ The same, but pipelined.
+
+Functions
+
+During execution functions are found in two function maps: first in the
+template, then in the global function map. By default, no functions are defined
+in the template but the Funcs method can be used to add them.
+
+Predefined global functions are named as follows.
+
+ and
+ Returns the boolean AND of its arguments by returning the
+ first empty argument or the last argument, that is,
+ "and x y" behaves as "if x then y else x". All the
+ arguments are evaluated.
+ call
+ Returns the result of calling the first argument, which
+ must be a function, with the remaining arguments as parameters.
+ Thus "call .X.Y 1 2" is, in Go notation, dot.X.Y(1, 2) where
+ Y is a func-valued field, map entry, or the like.
+ The first argument must be the result of an evaluation
+ that yields a value of function type (as distinct from
+ a predefined function such as print). The function must
+ return either one or two result values, the second of which
+ is of type error. If the arguments don't match the function
+ or the returned error value is non-nil, execution stops.
+ html
+ Returns the escaped HTML equivalent of the textual
+ representation of its arguments.
+ index
+ Returns the result of indexing its first argument by the
+ following arguments. Thus "index x 1 2 3" is, in Go syntax,
+ x[1][2][3]. Each indexed item must be a map, slice, or array.
+ js
+ Returns the escaped JavaScript equivalent of the textual
+ representation of its arguments.
+ len
+ Returns the integer length of its argument.
+ not
+ Returns the boolean negation of its single argument.
+ or
+ Returns the boolean OR of its arguments by returning the
+ first non-empty argument or the last argument, that is,
+ "or x y" behaves as "if x then x else y". All the
+ arguments are evaluated.
+ print
+ An alias for fmt.Sprint
+ printf
+ An alias for fmt.Sprintf
+ println
+ An alias for fmt.Sprintln
+ urlquery
+ Returns the escaped value of the textual representation of
+ its arguments in a form suitable for embedding in a URL query.
+
+The boolean functions take any zero value to be false and a non-zero
+value to be true.
+
+There is also a set of binary comparison operators defined as
+functions:
+
+ eq
+ Returns the boolean truth of arg1 == arg2
+ ne
+ Returns the boolean truth of arg1 != arg2
+ lt
+ Returns the boolean truth of arg1 < arg2
+ le
+ Returns the boolean truth of arg1 <= arg2
+ gt
+ Returns the boolean truth of arg1 > arg2
+ ge
+ Returns the boolean truth of arg1 >= arg2
+
+For simpler multi-way equality tests, eq (only) accepts two or more
+arguments and compares the second and subsequent to the first,
+returning in effect
+
+ arg1==arg2 || arg1==arg3 || arg1==arg4 ...
+
+(Unlike with || in Go, however, eq is a function call and all the
+arguments will be evaluated.)
+
+The comparison functions work on basic types only (or named basic
+types, such as "type Celsius float32"). They implement the Go rules
+for comparison of values, except that size and exact type are
+ignored, so any integer value, signed or unsigned, may be compared
+with any other integer value. (The arithmetic value is compared,
+not the bit pattern, so all negative integers are less than all
+unsigned integers.) However, as usual, one may not compare an int
+with a float32 and so on.
+
+Associated templates
+
+Each template is named by a string specified when it is created. Also, each
+template is associated with zero or more other templates that it may invoke by
+name; such associations are transitive and form a name space of templates.
+
+A template may use a template invocation to instantiate another associated
+template; see the explanation of the "template" action above. The name must be
+that of a template associated with the template that contains the invocation.
+
+Nested template definitions
+
+When parsing a template, another template may be defined and associated with the
+template being parsed. Template definitions must appear at the top level of the
+template, much like global variables in a Go program.
+
+The syntax of such definitions is to surround each template declaration with a
+"define" and "end" action.
+
+The define action names the template being created by providing a string
+constant. Here is a simple example:
+
+ `{{define "T1"}}ONE{{end}}
+ {{define "T2"}}TWO{{end}}
+ {{define "T3"}}{{template "T1"}} {{template "T2"}}{{end}}
+ {{template "T3"}}`
+
+This defines two templates, T1 and T2, and a third T3 that invokes the other two
+when it is executed. Finally it invokes T3. If executed this template will
+produce the text
+
+ ONE TWO
+
+By construction, a template may reside in only one association. If it's
+necessary to have a template addressable from multiple associations, the
+template definition must be parsed multiple times to create distinct *Template
+values, or must be copied with the Clone or AddParseTree method.
+
+Parse may be called multiple times to assemble the various associated templates;
+see the ParseFiles and ParseGlob functions and methods for simple ways to parse
+related templates stored in files.
+
+A template may be executed directly or through ExecuteTemplate, which executes
+an associated template identified by name. To invoke our example above, we
+might write,
+
+ err := tmpl.Execute(os.Stdout, "no data needed")
+ if err != nil {
+ log.Fatalf("execution failed: %s", err)
+ }
+
+or to invoke a particular template explicitly by name,
+
+ err := tmpl.ExecuteTemplate(os.Stdout, "T2", "no data needed")
+ if err != nil {
+ log.Fatalf("execution failed: %s", err)
+ }
+
+*/
+package template
--- /dev/null
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package template
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "reflect"
+ "runtime"
+ "sort"
+ "strings"
+
+ "github.com/alecthomas/template/parse"
+)
+
+// state represents the state of an execution. It's not part of the
+// template so that multiple executions of the same template
+// can execute in parallel.
+type state struct {
+ tmpl *Template
+ wr io.Writer
+ node parse.Node // current node, for errors
+ vars []variable // push-down stack of variable values.
+}
+
+// variable holds the dynamic value of a variable such as $, $x etc.
+type variable struct {
+ name string
+ value reflect.Value
+}
+
+// push pushes a new variable on the stack.
+func (s *state) push(name string, value reflect.Value) {
+ s.vars = append(s.vars, variable{name, value})
+}
+
+// mark returns the length of the variable stack.
+func (s *state) mark() int {
+ return len(s.vars)
+}
+
+// pop pops the variable stack up to the mark.
+func (s *state) pop(mark int) {
+ s.vars = s.vars[0:mark]
+}
+
+// setVar overwrites the top-nth variable on the stack. Used by range iterations.
+func (s *state) setVar(n int, value reflect.Value) {
+ s.vars[len(s.vars)-n].value = value
+}
+
+// varValue returns the value of the named variable.
+func (s *state) varValue(name string) reflect.Value {
+ for i := s.mark() - 1; i >= 0; i-- {
+ if s.vars[i].name == name {
+ return s.vars[i].value
+ }
+ }
+ s.errorf("undefined variable: %s", name)
+ return zero
+}
+
+var zero reflect.Value
+
+// at marks the state to be on node n, for error reporting.
+func (s *state) at(node parse.Node) {
+ s.node = node
+}
+
+// doublePercent returns the string with %'s replaced by %%, if necessary,
+// so it can be used safely inside a Printf format string.
+func doublePercent(str string) string {
+ if strings.Contains(str, "%") {
+ str = strings.Replace(str, "%", "%%", -1)
+ }
+ return str
+}
+
+// errorf formats the error and terminates processing.
+func (s *state) errorf(format string, args ...interface{}) {
+ name := doublePercent(s.tmpl.Name())
+ if s.node == nil {
+ format = fmt.Sprintf("template: %s: %s", name, format)
+ } else {
+ location, context := s.tmpl.ErrorContext(s.node)
+ format = fmt.Sprintf("template: %s: executing %q at <%s>: %s", location, name, doublePercent(context), format)
+ }
+ panic(fmt.Errorf(format, args...))
+}
+
+// errRecover is the handler that turns panics into returns from the top
+// level of Parse.
+func errRecover(errp *error) {
+ e := recover()
+ if e != nil {
+ switch err := e.(type) {
+ case runtime.Error:
+ panic(e)
+ case error:
+ *errp = err
+ default:
+ panic(e)
+ }
+ }
+}
+
+// ExecuteTemplate applies the template associated with t that has the given name
+// to the specified data object and writes the output to wr.
+// If an error occurs executing the template or writing its output,
+// execution stops, but partial results may already have been written to
+// the output writer.
+// A template may be executed safely in parallel.
+func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
+ tmpl := t.tmpl[name]
+ if tmpl == nil {
+ return fmt.Errorf("template: no template %q associated with template %q", name, t.name)
+ }
+ return tmpl.Execute(wr, data)
+}
+
+// Execute applies a parsed template to the specified data object,
+// and writes the output to wr.
+// If an error occurs executing the template or writing its output,
+// execution stops, but partial results may already have been written to
+// the output writer.
+// A template may be executed safely in parallel.
+func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
+ defer errRecover(&err)
+ value := reflect.ValueOf(data)
+ state := &state{
+ tmpl: t,
+ wr: wr,
+ vars: []variable{{"$", value}},
+ }
+ t.init()
+ if t.Tree == nil || t.Root == nil {
+ var b bytes.Buffer
+ for name, tmpl := range t.tmpl {
+ if tmpl.Tree == nil || tmpl.Root == nil {
+ continue
+ }
+ if b.Len() > 0 {
+ b.WriteString(", ")
+ }
+ fmt.Fprintf(&b, "%q", name)
+ }
+ var s string
+ if b.Len() > 0 {
+ s = "; defined templates are: " + b.String()
+ }
+ state.errorf("%q is an incomplete or empty template%s", t.Name(), s)
+ }
+ state.walk(value, t.Root)
+ return
+}
+
+// Walk functions step through the major pieces of the template structure,
+// generating output as they go.
+func (s *state) walk(dot reflect.Value, node parse.Node) {
+ s.at(node)
+ switch node := node.(type) {
+ case *parse.ActionNode:
+ // Do not pop variables so they persist until next end.
+ // Also, if the action declares variables, don't print the result.
+ val := s.evalPipeline(dot, node.Pipe)
+ if len(node.Pipe.Decl) == 0 {
+ s.printValue(node, val)
+ }
+ case *parse.IfNode:
+ s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList)
+ case *parse.ListNode:
+ for _, node := range node.Nodes {
+ s.walk(dot, node)
+ }
+ case *parse.RangeNode:
+ s.walkRange(dot, node)
+ case *parse.TemplateNode:
+ s.walkTemplate(dot, node)
+ case *parse.TextNode:
+ if _, err := s.wr.Write(node.Text); err != nil {
+ s.errorf("%s", err)
+ }
+ case *parse.WithNode:
+ s.walkIfOrWith(parse.NodeWith, dot, node.Pipe, node.List, node.ElseList)
+ default:
+ s.errorf("unknown node: %s", node)
+ }
+}
+
+// walkIfOrWith walks an 'if' or 'with' node. The two control structures
+// are identical in behavior except that 'with' sets dot.
+func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse.PipeNode, list, elseList *parse.ListNode) {
+ defer s.pop(s.mark())
+ val := s.evalPipeline(dot, pipe)
+ truth, ok := isTrue(val)
+ if !ok {
+ s.errorf("if/with can't use %v", val)
+ }
+ if truth {
+ if typ == parse.NodeWith {
+ s.walk(val, list)
+ } else {
+ s.walk(dot, list)
+ }
+ } else if elseList != nil {
+ s.walk(dot, elseList)
+ }
+}
+
+// isTrue reports whether the value is 'true', in the sense of not the zero of its type,
+// and whether the value has a meaningful truth value.
+func isTrue(val reflect.Value) (truth, ok bool) {
+ if !val.IsValid() {
+ // Something like var x interface{}, never set. It's a form of nil.
+ return false, true
+ }
+ switch val.Kind() {
+ case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+ truth = val.Len() > 0
+ case reflect.Bool:
+ truth = val.Bool()
+ case reflect.Complex64, reflect.Complex128:
+ truth = val.Complex() != 0
+ case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Interface:
+ truth = !val.IsNil()
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ truth = val.Int() != 0
+ case reflect.Float32, reflect.Float64:
+ truth = val.Float() != 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ truth = val.Uint() != 0
+ case reflect.Struct:
+ truth = true // Struct values are always true.
+ default:
+ return
+ }
+ return truth, true
+}
+
+func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
+ s.at(r)
+ defer s.pop(s.mark())
+ val, _ := indirect(s.evalPipeline(dot, r.Pipe))
+ // mark top of stack before any variables in the body are pushed.
+ mark := s.mark()
+ oneIteration := func(index, elem reflect.Value) {
+ // Set top var (lexically the second if there are two) to the element.
+ if len(r.Pipe.Decl) > 0 {
+ s.setVar(1, elem)
+ }
+ // Set next var (lexically the first if there are two) to the index.
+ if len(r.Pipe.Decl) > 1 {
+ s.setVar(2, index)
+ }
+ s.walk(elem, r.List)
+ s.pop(mark)
+ }
+ switch val.Kind() {
+ case reflect.Array, reflect.Slice:
+ if val.Len() == 0 {
+ break
+ }
+ for i := 0; i < val.Len(); i++ {
+ oneIteration(reflect.ValueOf(i), val.Index(i))
+ }
+ return
+ case reflect.Map:
+ if val.Len() == 0 {
+ break
+ }
+ for _, key := range sortKeys(val.MapKeys()) {
+ oneIteration(key, val.MapIndex(key))
+ }
+ return
+ case reflect.Chan:
+ if val.IsNil() {
+ break
+ }
+ i := 0
+ for ; ; i++ {
+ elem, ok := val.Recv()
+ if !ok {
+ break
+ }
+ oneIteration(reflect.ValueOf(i), elem)
+ }
+ if i == 0 {
+ break
+ }
+ return
+ case reflect.Invalid:
+ break // An invalid value is likely a nil map, etc. and acts like an empty map.
+ default:
+ s.errorf("range can't iterate over %v", val)
+ }
+ if r.ElseList != nil {
+ s.walk(dot, r.ElseList)
+ }
+}
+
+func (s *state) walkTemplate(dot reflect.Value, t *parse.TemplateNode) {
+ s.at(t)
+ tmpl := s.tmpl.tmpl[t.Name]
+ if tmpl == nil {
+ s.errorf("template %q not defined", t.Name)
+ }
+ // Variables declared by the pipeline persist.
+ dot = s.evalPipeline(dot, t.Pipe)
+ newState := *s
+ newState.tmpl = tmpl
+ // No dynamic scoping: template invocations inherit no variables.
+ newState.vars = []variable{{"$", dot}}
+ newState.walk(dot, tmpl.Root)
+}
+
+// Eval functions evaluate pipelines, commands, and their elements and extract
+// values from the data structure by examining fields, calling methods, and so on.
+// The printing of those values happens only through walk functions.
+
+// evalPipeline returns the value acquired by evaluating a pipeline. If the
+// pipeline has a variable declaration, the variable will be pushed on the
+// stack. Callers should therefore pop the stack after they are finished
+// executing commands depending on the pipeline value.
+func (s *state) evalPipeline(dot reflect.Value, pipe *parse.PipeNode) (value reflect.Value) {
+ if pipe == nil {
+ return
+ }
+ s.at(pipe)
+ for _, cmd := range pipe.Cmds {
+ value = s.evalCommand(dot, cmd, value) // previous value is this one's final arg.
+ // If the object has type interface{}, dig down one level to the thing inside.
+ if value.Kind() == reflect.Interface && value.Type().NumMethod() == 0 {
+ value = reflect.ValueOf(value.Interface()) // lovely!
+ }
+ }
+ for _, variable := range pipe.Decl {
+ s.push(variable.Ident[0], value)
+ }
+ return value
+}
+
+func (s *state) notAFunction(args []parse.Node, final reflect.Value) {
+ if len(args) > 1 || final.IsValid() {
+ s.errorf("can't give argument to non-function %s", args[0])
+ }
+}
+
+func (s *state) evalCommand(dot reflect.Value, cmd *parse.CommandNode, final reflect.Value) reflect.Value {
+ firstWord := cmd.Args[0]
+ switch n := firstWord.(type) {
+ case *parse.FieldNode:
+ return s.evalFieldNode(dot, n, cmd.Args, final)
+ case *parse.ChainNode:
+ return s.evalChainNode(dot, n, cmd.Args, final)
+ case *parse.IdentifierNode:
+ // Must be a function.
+ return s.evalFunction(dot, n, cmd, cmd.Args, final)
+ case *parse.PipeNode:
+ // Parenthesized pipeline. The arguments are all inside the pipeline; final is ignored.
+ return s.evalPipeline(dot, n)
+ case *parse.VariableNode:
+ return s.evalVariableNode(dot, n, cmd.Args, final)
+ }
+ s.at(firstWord)
+ s.notAFunction(cmd.Args, final)
+ switch word := firstWord.(type) {
+ case *parse.BoolNode:
+ return reflect.ValueOf(word.True)
+ case *parse.DotNode:
+ return dot
+ case *parse.NilNode:
+ s.errorf("nil is not a command")
+ case *parse.NumberNode:
+ return s.idealConstant(word)
+ case *parse.StringNode:
+ return reflect.ValueOf(word.Text)
+ }
+ s.errorf("can't evaluate command %q", firstWord)
+ panic("not reached")
+}
+
+// idealConstant is called to return the value of a number in a context where
+// we don't know the type. In that case, the syntax of the number tells us
+// its type, and we use Go rules to resolve. Note there is no such thing as
+// a uint ideal constant in this situation - the value must be of int type.
+func (s *state) idealConstant(constant *parse.NumberNode) reflect.Value {
+ // These are ideal constants but we don't know the type
+ // and we have no context. (If it was a method argument,
+ // we'd know what we need.) The syntax guides us to some extent.
+ s.at(constant)
+ switch {
+ case constant.IsComplex:
+ return reflect.ValueOf(constant.Complex128) // incontrovertible.
+ case constant.IsFloat && !isHexConstant(constant.Text) && strings.IndexAny(constant.Text, ".eE") >= 0:
+ return reflect.ValueOf(constant.Float64)
+ case constant.IsInt:
+ n := int(constant.Int64)
+ if int64(n) != constant.Int64 {
+ s.errorf("%s overflows int", constant.Text)
+ }
+ return reflect.ValueOf(n)
+ case constant.IsUint:
+ s.errorf("%s overflows int", constant.Text)
+ }
+ return zero
+}
+
+func isHexConstant(s string) bool {
+ return len(s) > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')
+}
+
+func (s *state) evalFieldNode(dot reflect.Value, field *parse.FieldNode, args []parse.Node, final reflect.Value) reflect.Value {
+ s.at(field)
+ return s.evalFieldChain(dot, dot, field, field.Ident, args, final)
+}
+
+func (s *state) evalChainNode(dot reflect.Value, chain *parse.ChainNode, args []parse.Node, final reflect.Value) reflect.Value {
+ s.at(chain)
+ // (pipe).Field1.Field2 has pipe as .Node, fields as .Field. Eval the pipeline, then the fields.
+ pipe := s.evalArg(dot, nil, chain.Node)
+ if len(chain.Field) == 0 {
+ s.errorf("internal error: no fields in evalChainNode")
+ }
+ return s.evalFieldChain(dot, pipe, chain, chain.Field, args, final)
+}
+
+func (s *state) evalVariableNode(dot reflect.Value, variable *parse.VariableNode, args []parse.Node, final reflect.Value) reflect.Value {
+ // $x.Field has $x as the first ident, Field as the second. Eval the var, then the fields.
+ s.at(variable)
+ value := s.varValue(variable.Ident[0])
+ if len(variable.Ident) == 1 {
+ s.notAFunction(args, final)
+ return value
+ }
+ return s.evalFieldChain(dot, value, variable, variable.Ident[1:], args, final)
+}
+
+// evalFieldChain evaluates .X.Y.Z possibly followed by arguments.
+// dot is the environment in which to evaluate arguments, while
+// receiver is the value being walked along the chain.
+func (s *state) evalFieldChain(dot, receiver reflect.Value, node parse.Node, ident []string, args []parse.Node, final reflect.Value) reflect.Value {
+ n := len(ident)
+ for i := 0; i < n-1; i++ {
+ receiver = s.evalField(dot, ident[i], node, nil, zero, receiver)
+ }
+ // Now if it's a method, it gets the arguments.
+ return s.evalField(dot, ident[n-1], node, args, final, receiver)
+}
+
+func (s *state) evalFunction(dot reflect.Value, node *parse.IdentifierNode, cmd parse.Node, args []parse.Node, final reflect.Value) reflect.Value {
+ s.at(node)
+ name := node.Ident
+ function, ok := findFunction(name, s.tmpl)
+ if !ok {
+ s.errorf("%q is not a defined function", name)
+ }
+ return s.evalCall(dot, function, cmd, name, args, final)
+}
+
+// evalField evaluates an expression like (.Field) or (.Field arg1 arg2).
+// The 'final' argument represents the return value from the preceding
+// value of the pipeline, if any.
+func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, args []parse.Node, final, receiver reflect.Value) reflect.Value {
+ if !receiver.IsValid() {
+ return zero
+ }
+ typ := receiver.Type()
+ receiver, _ = indirect(receiver)
+ // Unless it's an interface, need to get to a value of type *T to guarantee
+ // we see all methods of T and *T.
+ ptr := receiver
+ if ptr.Kind() != reflect.Interface && ptr.CanAddr() {
+ ptr = ptr.Addr()
+ }
+ if method := ptr.MethodByName(fieldName); method.IsValid() {
+ return s.evalCall(dot, method, node, fieldName, args, final)
+ }
+ hasArgs := len(args) > 1 || final.IsValid()
+ // It's not a method; must be a field of a struct or an element of a map. The receiver must not be nil.
+ receiver, isNil := indirect(receiver)
+ if isNil {
+ s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
+ }
+ switch receiver.Kind() {
+ case reflect.Struct:
+ tField, ok := receiver.Type().FieldByName(fieldName)
+ if ok {
+ field := receiver.FieldByIndex(tField.Index)
+ if tField.PkgPath != "" { // field is unexported
+ s.errorf("%s is an unexported field of struct type %s", fieldName, typ)
+ }
+ // If it's a function, we must call it.
+ if hasArgs {
+ s.errorf("%s has arguments but cannot be invoked as function", fieldName)
+ }
+ return field
+ }
+ s.errorf("%s is not a field of struct type %s", fieldName, typ)
+ case reflect.Map:
+ // If it's a map, attempt to use the field name as a key.
+ nameVal := reflect.ValueOf(fieldName)
+ if nameVal.Type().AssignableTo(receiver.Type().Key()) {
+ if hasArgs {
+ s.errorf("%s is not a method but has arguments", fieldName)
+ }
+ return receiver.MapIndex(nameVal)
+ }
+ }
+ s.errorf("can't evaluate field %s in type %s", fieldName, typ)
+ panic("not reached")
+}
+
+var (
+ errorType = reflect.TypeOf((*error)(nil)).Elem()
+ fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
+)
+
+// evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so
+// it looks just like a function call. The arg list, if non-nil, includes (in the manner of the shell), arg[0]
+// as the function itself.
+func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, args []parse.Node, final reflect.Value) reflect.Value {
+ if args != nil {
+ args = args[1:] // Zeroth arg is function name/node; not passed to function.
+ }
+ typ := fun.Type()
+ numIn := len(args)
+ if final.IsValid() {
+ numIn++
+ }
+ numFixed := len(args)
+ if typ.IsVariadic() {
+ numFixed = typ.NumIn() - 1 // last arg is the variadic one.
+ if numIn < numFixed {
+ s.errorf("wrong number of args for %s: want at least %d got %d", name, typ.NumIn()-1, len(args))
+ }
+ } else if numIn < typ.NumIn()-1 || !typ.IsVariadic() && numIn != typ.NumIn() {
+ s.errorf("wrong number of args for %s: want %d got %d", name, typ.NumIn(), len(args))
+ }
+ if !goodFunc(typ) {
+ // TODO: This could still be a confusing error; maybe goodFunc should provide info.
+ s.errorf("can't call method/function %q with %d results", name, typ.NumOut())
+ }
+ // Build the arg list.
+ argv := make([]reflect.Value, numIn)
+ // Args must be evaluated. Fixed args first.
+ i := 0
+ for ; i < numFixed && i < len(args); i++ {
+ argv[i] = s.evalArg(dot, typ.In(i), args[i])
+ }
+ // Now the ... args.
+ if typ.IsVariadic() {
+ argType := typ.In(typ.NumIn() - 1).Elem() // Argument is a slice.
+ for ; i < len(args); i++ {
+ argv[i] = s.evalArg(dot, argType, args[i])
+ }
+ }
+ // Add final value if necessary.
+ if final.IsValid() {
+ t := typ.In(typ.NumIn() - 1)
+ if typ.IsVariadic() {
+ t = t.Elem()
+ }
+ argv[i] = s.validateType(final, t)
+ }
+ result := fun.Call(argv)
+ // If we have an error that is not nil, stop execution and return that error to the caller.
+ if len(result) == 2 && !result[1].IsNil() {
+ s.at(node)
+ s.errorf("error calling %s: %s", name, result[1].Interface().(error))
+ }
+ return result[0]
+}
+
+// canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero.
+func canBeNil(typ reflect.Type) bool {
+ switch typ.Kind() {
+ case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
+ return true
+ }
+ return false
+}
+
+// validateType guarantees that the value is valid and assignable to the type.
+func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Value {
+ if !value.IsValid() {
+ if typ == nil || canBeNil(typ) {
+ // An untyped nil interface{}. Accept as a proper nil value.
+ return reflect.Zero(typ)
+ }
+ s.errorf("invalid value; expected %s", typ)
+ }
+ if typ != nil && !value.Type().AssignableTo(typ) {
+ if value.Kind() == reflect.Interface && !value.IsNil() {
+ value = value.Elem()
+ if value.Type().AssignableTo(typ) {
+ return value
+ }
+ // fallthrough
+ }
+ // Does one dereference or indirection work? We could do more, as we
+ // do with method receivers, but that gets messy and method receivers
+ // are much more constrained, so it makes more sense there than here.
+ // Besides, one is almost always all you need.
+ switch {
+ case value.Kind() == reflect.Ptr && value.Type().Elem().AssignableTo(typ):
+ value = value.Elem()
+ if !value.IsValid() {
+ s.errorf("dereference of nil pointer of type %s", typ)
+ }
+ case reflect.PtrTo(value.Type()).AssignableTo(typ) && value.CanAddr():
+ value = value.Addr()
+ default:
+ s.errorf("wrong type for value; expected %s; got %s", typ, value.Type())
+ }
+ }
+ return value
+}
+
+func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) reflect.Value {
+ s.at(n)
+ switch arg := n.(type) {
+ case *parse.DotNode:
+ return s.validateType(dot, typ)
+ case *parse.NilNode:
+ if canBeNil(typ) {
+ return reflect.Zero(typ)
+ }
+ s.errorf("cannot assign nil to %s", typ)
+ case *parse.FieldNode:
+ return s.validateType(s.evalFieldNode(dot, arg, []parse.Node{n}, zero), typ)
+ case *parse.VariableNode:
+ return s.validateType(s.evalVariableNode(dot, arg, nil, zero), typ)
+ case *parse.PipeNode:
+ return s.validateType(s.evalPipeline(dot, arg), typ)
+ case *parse.IdentifierNode:
+ return s.evalFunction(dot, arg, arg, nil, zero)
+ case *parse.ChainNode:
+ return s.validateType(s.evalChainNode(dot, arg, nil, zero), typ)
+ }
+ switch typ.Kind() {
+ case reflect.Bool:
+ return s.evalBool(typ, n)
+ case reflect.Complex64, reflect.Complex128:
+ return s.evalComplex(typ, n)
+ case reflect.Float32, reflect.Float64:
+ return s.evalFloat(typ, n)
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return s.evalInteger(typ, n)
+ case reflect.Interface:
+ if typ.NumMethod() == 0 {
+ return s.evalEmptyInterface(dot, n)
+ }
+ case reflect.String:
+ return s.evalString(typ, n)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return s.evalUnsignedInteger(typ, n)
+ }
+ s.errorf("can't handle %s for arg of type %s", n, typ)
+ panic("not reached")
+}
+
+func (s *state) evalBool(typ reflect.Type, n parse.Node) reflect.Value {
+ s.at(n)
+ if n, ok := n.(*parse.BoolNode); ok {
+ value := reflect.New(typ).Elem()
+ value.SetBool(n.True)
+ return value
+ }
+ s.errorf("expected bool; found %s", n)
+ panic("not reached")
+}
+
+func (s *state) evalString(typ reflect.Type, n parse.Node) reflect.Value {
+ s.at(n)
+ if n, ok := n.(*parse.StringNode); ok {
+ value := reflect.New(typ).Elem()
+ value.SetString(n.Text)
+ return value
+ }
+ s.errorf("expected string; found %s", n)
+ panic("not reached")
+}
+
+func (s *state) evalInteger(typ reflect.Type, n parse.Node) reflect.Value {
+ s.at(n)
+ if n, ok := n.(*parse.NumberNode); ok && n.IsInt {
+ value := reflect.New(typ).Elem()
+ value.SetInt(n.Int64)
+ return value
+ }
+ s.errorf("expected integer; found %s", n)
+ panic("not reached")
+}
+
+func (s *state) evalUnsignedInteger(typ reflect.Type, n parse.Node) reflect.Value {
+ s.at(n)
+ if n, ok := n.(*parse.NumberNode); ok && n.IsUint {
+ value := reflect.New(typ).Elem()
+ value.SetUint(n.Uint64)
+ return value
+ }
+ s.errorf("expected unsigned integer; found %s", n)
+ panic("not reached")
+}
+
+func (s *state) evalFloat(typ reflect.Type, n parse.Node) reflect.Value {
+ s.at(n)
+ if n, ok := n.(*parse.NumberNode); ok && n.IsFloat {
+ value := reflect.New(typ).Elem()
+ value.SetFloat(n.Float64)
+ return value
+ }
+ s.errorf("expected float; found %s", n)
+ panic("not reached")
+}
+
+func (s *state) evalComplex(typ reflect.Type, n parse.Node) reflect.Value {
+ if n, ok := n.(*parse.NumberNode); ok && n.IsComplex {
+ value := reflect.New(typ).Elem()
+ value.SetComplex(n.Complex128)
+ return value
+ }
+ s.errorf("expected complex; found %s", n)
+ panic("not reached")
+}
+
+func (s *state) evalEmptyInterface(dot reflect.Value, n parse.Node) reflect.Value {
+ s.at(n)
+ switch n := n.(type) {
+ case *parse.BoolNode:
+ return reflect.ValueOf(n.True)
+ case *parse.DotNode:
+ return dot
+ case *parse.FieldNode:
+ return s.evalFieldNode(dot, n, nil, zero)
+ case *parse.IdentifierNode:
+ return s.evalFunction(dot, n, n, nil, zero)
+ case *parse.NilNode:
+ // NilNode is handled in evalArg, the only place that calls here.
+ s.errorf("evalEmptyInterface: nil (can't happen)")
+ case *parse.NumberNode:
+ return s.idealConstant(n)
+ case *parse.StringNode:
+ return reflect.ValueOf(n.Text)
+ case *parse.VariableNode:
+ return s.evalVariableNode(dot, n, nil, zero)
+ case *parse.PipeNode:
+ return s.evalPipeline(dot, n)
+ }
+ s.errorf("can't handle assignment of %s to empty interface argument", n)
+ panic("not reached")
+}
+
+// indirect returns the item at the end of indirection, and a bool to indicate if it's nil.
+// We indirect through pointers and empty interfaces (only) because
+// non-empty interfaces have methods we might need.
+func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
+ for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() {
+ if v.IsNil() {
+ return v, true
+ }
+ if v.Kind() == reflect.Interface && v.NumMethod() > 0 {
+ break
+ }
+ }
+ return v, false
+}
+
+// printValue writes the textual representation of the value to the output of
+// the template.
+func (s *state) printValue(n parse.Node, v reflect.Value) {
+ s.at(n)
+ iface, ok := printableValue(v)
+ if !ok {
+ s.errorf("can't print %s of type %s", n, v.Type())
+ }
+ fmt.Fprint(s.wr, iface)
+}
+
+// printableValue returns the, possibly indirected, interface value inside v that
+// is best for a call to formatted printer.
+func printableValue(v reflect.Value) (interface{}, bool) {
+ if v.Kind() == reflect.Ptr {
+ v, _ = indirect(v) // fmt.Fprint handles nil.
+ }
+ if !v.IsValid() {
+ return "<no value>", true
+ }
+
+ if !v.Type().Implements(errorType) && !v.Type().Implements(fmtStringerType) {
+ if v.CanAddr() && (reflect.PtrTo(v.Type()).Implements(errorType) || reflect.PtrTo(v.Type()).Implements(fmtStringerType)) {
+ v = v.Addr()
+ } else {
+ switch v.Kind() {
+ case reflect.Chan, reflect.Func:
+ return nil, false
+ }
+ }
+ }
+ return v.Interface(), true
+}
+
+// Types to help sort the keys in a map for reproducible output.
+
+type rvs []reflect.Value
+
+func (x rvs) Len() int { return len(x) }
+func (x rvs) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+
+type rvInts struct{ rvs }
+
+func (x rvInts) Less(i, j int) bool { return x.rvs[i].Int() < x.rvs[j].Int() }
+
+type rvUints struct{ rvs }
+
+func (x rvUints) Less(i, j int) bool { return x.rvs[i].Uint() < x.rvs[j].Uint() }
+
+type rvFloats struct{ rvs }
+
+func (x rvFloats) Less(i, j int) bool { return x.rvs[i].Float() < x.rvs[j].Float() }
+
+type rvStrings struct{ rvs }
+
+func (x rvStrings) Less(i, j int) bool { return x.rvs[i].String() < x.rvs[j].String() }
+
+// sortKeys sorts (if it can) the slice of reflect.Values, which is a slice of map keys.
+func sortKeys(v []reflect.Value) []reflect.Value {
+ if len(v) <= 1 {
+ return v
+ }
+ switch v[0].Kind() {
+ case reflect.Float32, reflect.Float64:
+ sort.Sort(rvFloats{v})
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ sort.Sort(rvInts{v})
+ case reflect.String:
+ sort.Sort(rvStrings{v})
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ sort.Sort(rvUints{v})
+ }
+ return v
+}
--- /dev/null
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package template
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "net/url"
+ "reflect"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+)
+
+// FuncMap is the type of the map defining the mapping from names to functions.
+// Each function must have either a single return value, or two return values of
+// which the second has type error. In that case, if the second (error)
+// return value evaluates to non-nil during execution, execution terminates and
+// Execute returns that error.
+type FuncMap map[string]interface{}
+
+var builtins = FuncMap{
+ "and": and,
+ "call": call,
+ "html": HTMLEscaper,
+ "index": index,
+ "js": JSEscaper,
+ "len": length,
+ "not": not,
+ "or": or,
+ "print": fmt.Sprint,
+ "printf": fmt.Sprintf,
+ "println": fmt.Sprintln,
+ "urlquery": URLQueryEscaper,
+
+ // Comparisons
+ "eq": eq, // ==
+ "ge": ge, // >=
+ "gt": gt, // >
+ "le": le, // <=
+ "lt": lt, // <
+ "ne": ne, // !=
+}
+
+var builtinFuncs = createValueFuncs(builtins)
+
+// createValueFuncs turns a FuncMap into a map[string]reflect.Value
+func createValueFuncs(funcMap FuncMap) map[string]reflect.Value {
+ m := make(map[string]reflect.Value)
+ addValueFuncs(m, funcMap)
+ return m
+}
+
+// addValueFuncs adds to values the functions in funcs, converting them to reflect.Values.
+func addValueFuncs(out map[string]reflect.Value, in FuncMap) {
+ for name, fn := range in {
+ v := reflect.ValueOf(fn)
+ if v.Kind() != reflect.Func {
+ panic("value for " + name + " not a function")
+ }
+ if !goodFunc(v.Type()) {
+ panic(fmt.Errorf("can't install method/function %q with %d results", name, v.Type().NumOut()))
+ }
+ out[name] = v
+ }
+}
+
+// addFuncs adds to values the functions in funcs. It does no checking of the input -
+// call addValueFuncs first.
+func addFuncs(out, in FuncMap) {
+ for name, fn := range in {
+ out[name] = fn
+ }
+}
+
+// goodFunc checks that the function or method has the right result signature.
+func goodFunc(typ reflect.Type) bool {
+ // We allow functions with 1 result or 2 results where the second is an error.
+ switch {
+ case typ.NumOut() == 1:
+ return true
+ case typ.NumOut() == 2 && typ.Out(1) == errorType:
+ return true
+ }
+ return false
+}
+
+// findFunction looks for a function in the template, and global map.
+func findFunction(name string, tmpl *Template) (reflect.Value, bool) {
+ if tmpl != nil && tmpl.common != nil {
+ if fn := tmpl.execFuncs[name]; fn.IsValid() {
+ return fn, true
+ }
+ }
+ if fn := builtinFuncs[name]; fn.IsValid() {
+ return fn, true
+ }
+ return reflect.Value{}, false
+}
+
+// Indexing.
+
+// index returns the result of indexing its first argument by the following
+// arguments. Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each
+// indexed item must be a map, slice, or array.
+func index(item interface{}, indices ...interface{}) (interface{}, error) {
+ v := reflect.ValueOf(item)
+ for _, i := range indices {
+ index := reflect.ValueOf(i)
+ var isNil bool
+ if v, isNil = indirect(v); isNil {
+ return nil, fmt.Errorf("index of nil pointer")
+ }
+ switch v.Kind() {
+ case reflect.Array, reflect.Slice, reflect.String:
+ var x int64
+ switch index.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ x = index.Int()
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ x = int64(index.Uint())
+ default:
+ return nil, fmt.Errorf("cannot index slice/array with type %s", index.Type())
+ }
+ if x < 0 || x >= int64(v.Len()) {
+ return nil, fmt.Errorf("index out of range: %d", x)
+ }
+ v = v.Index(int(x))
+ case reflect.Map:
+ if !index.IsValid() {
+ index = reflect.Zero(v.Type().Key())
+ }
+ if !index.Type().AssignableTo(v.Type().Key()) {
+ return nil, fmt.Errorf("%s is not index type for %s", index.Type(), v.Type())
+ }
+ if x := v.MapIndex(index); x.IsValid() {
+ v = x
+ } else {
+ v = reflect.Zero(v.Type().Elem())
+ }
+ default:
+ return nil, fmt.Errorf("can't index item of type %s", v.Type())
+ }
+ }
+ return v.Interface(), nil
+}
+
+// Length
+
+// length returns the length of the item, with an error if it has no defined length.
+func length(item interface{}) (int, error) {
+ v, isNil := indirect(reflect.ValueOf(item))
+ if isNil {
+ return 0, fmt.Errorf("len of nil pointer")
+ }
+ switch v.Kind() {
+ case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
+ return v.Len(), nil
+ }
+ return 0, fmt.Errorf("len of type %s", v.Type())
+}
+
+// Function invocation
+
+// call returns the result of evaluating the first argument as a function.
+// The function must return 1 result, or 2 results, the second of which is an error.
+func call(fn interface{}, args ...interface{}) (interface{}, error) {
+ v := reflect.ValueOf(fn)
+ typ := v.Type()
+ if typ.Kind() != reflect.Func {
+ return nil, fmt.Errorf("non-function of type %s", typ)
+ }
+ if !goodFunc(typ) {
+ return nil, fmt.Errorf("function called with %d args; should be 1 or 2", typ.NumOut())
+ }
+ numIn := typ.NumIn()
+ var dddType reflect.Type
+ if typ.IsVariadic() {
+ if len(args) < numIn-1 {
+ return nil, fmt.Errorf("wrong number of args: got %d want at least %d", len(args), numIn-1)
+ }
+ dddType = typ.In(numIn - 1).Elem()
+ } else {
+ if len(args) != numIn {
+ return nil, fmt.Errorf("wrong number of args: got %d want %d", len(args), numIn)
+ }
+ }
+ argv := make([]reflect.Value, len(args))
+ for i, arg := range args {
+ value := reflect.ValueOf(arg)
+ // Compute the expected type. Clumsy because of variadics.
+ var argType reflect.Type
+ if !typ.IsVariadic() || i < numIn-1 {
+ argType = typ.In(i)
+ } else {
+ argType = dddType
+ }
+ if !value.IsValid() && canBeNil(argType) {
+ value = reflect.Zero(argType)
+ }
+ if !value.Type().AssignableTo(argType) {
+ return nil, fmt.Errorf("arg %d has type %s; should be %s", i, value.Type(), argType)
+ }
+ argv[i] = value
+ }
+ result := v.Call(argv)
+ if len(result) == 2 && !result[1].IsNil() {
+ return result[0].Interface(), result[1].Interface().(error)
+ }
+ return result[0].Interface(), nil
+}
+
+// Boolean logic.
+
+func truth(a interface{}) bool {
+ t, _ := isTrue(reflect.ValueOf(a))
+ return t
+}
+
+// and computes the Boolean AND of its arguments, returning
+// the first false argument it encounters, or the last argument.
+func and(arg0 interface{}, args ...interface{}) interface{} {
+ if !truth(arg0) {
+ return arg0
+ }
+ for i := range args {
+ arg0 = args[i]
+ if !truth(arg0) {
+ break
+ }
+ }
+ return arg0
+}
+
+// or computes the Boolean OR of its arguments, returning
+// the first true argument it encounters, or the last argument.
+func or(arg0 interface{}, args ...interface{}) interface{} {
+ if truth(arg0) {
+ return arg0
+ }
+ for i := range args {
+ arg0 = args[i]
+ if truth(arg0) {
+ break
+ }
+ }
+ return arg0
+}
+
+// not returns the Boolean negation of its argument.
+func not(arg interface{}) (truth bool) {
+ truth, _ = isTrue(reflect.ValueOf(arg))
+ return !truth
+}
+
+// Comparison.
+
+// TODO: Perhaps allow comparison between signed and unsigned integers.
+
+var (
+ errBadComparisonType = errors.New("invalid type for comparison")
+ errBadComparison = errors.New("incompatible types for comparison")
+ errNoComparison = errors.New("missing argument for comparison")
+)
+
+type kind int
+
+const (
+ invalidKind kind = iota
+ boolKind
+ complexKind
+ intKind
+ floatKind
+ integerKind
+ stringKind
+ uintKind
+)
+
+func basicKind(v reflect.Value) (kind, error) {
+ switch v.Kind() {
+ case reflect.Bool:
+ return boolKind, nil
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return intKind, nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return uintKind, nil
+ case reflect.Float32, reflect.Float64:
+ return floatKind, nil
+ case reflect.Complex64, reflect.Complex128:
+ return complexKind, nil
+ case reflect.String:
+ return stringKind, nil
+ }
+ return invalidKind, errBadComparisonType
+}
+
+// eq evaluates the comparison a == b || a == c || ...
+func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) {
+ v1 := reflect.ValueOf(arg1)
+ k1, err := basicKind(v1)
+ if err != nil {
+ return false, err
+ }
+ if len(arg2) == 0 {
+ return false, errNoComparison
+ }
+ for _, arg := range arg2 {
+ v2 := reflect.ValueOf(arg)
+ k2, err := basicKind(v2)
+ if err != nil {
+ return false, err
+ }
+ truth := false
+ if k1 != k2 {
+ // Special case: Can compare integer values regardless of type's sign.
+ switch {
+ case k1 == intKind && k2 == uintKind:
+ truth = v1.Int() >= 0 && uint64(v1.Int()) == v2.Uint()
+ case k1 == uintKind && k2 == intKind:
+ truth = v2.Int() >= 0 && v1.Uint() == uint64(v2.Int())
+ default:
+ return false, errBadComparison
+ }
+ } else {
+ switch k1 {
+ case boolKind:
+ truth = v1.Bool() == v2.Bool()
+ case complexKind:
+ truth = v1.Complex() == v2.Complex()
+ case floatKind:
+ truth = v1.Float() == v2.Float()
+ case intKind:
+ truth = v1.Int() == v2.Int()
+ case stringKind:
+ truth = v1.String() == v2.String()
+ case uintKind:
+ truth = v1.Uint() == v2.Uint()
+ default:
+ panic("invalid kind")
+ }
+ }
+ if truth {
+ return true, nil
+ }
+ }
+ return false, nil
+}
+
+// ne evaluates the comparison a != b.
+func ne(arg1, arg2 interface{}) (bool, error) {
+ // != is the inverse of ==.
+ equal, err := eq(arg1, arg2)
+ return !equal, err
+}
+
+// lt evaluates the comparison a < b.
+func lt(arg1, arg2 interface{}) (bool, error) {
+ v1 := reflect.ValueOf(arg1)
+ k1, err := basicKind(v1)
+ if err != nil {
+ return false, err
+ }
+ v2 := reflect.ValueOf(arg2)
+ k2, err := basicKind(v2)
+ if err != nil {
+ return false, err
+ }
+ truth := false
+ if k1 != k2 {
+ // Special case: Can compare integer values regardless of type's sign.
+ switch {
+ case k1 == intKind && k2 == uintKind:
+ truth = v1.Int() < 0 || uint64(v1.Int()) < v2.Uint()
+ case k1 == uintKind && k2 == intKind:
+ truth = v2.Int() >= 0 && v1.Uint() < uint64(v2.Int())
+ default:
+ return false, errBadComparison
+ }
+ } else {
+ switch k1 {
+ case boolKind, complexKind:
+ return false, errBadComparisonType
+ case floatKind:
+ truth = v1.Float() < v2.Float()
+ case intKind:
+ truth = v1.Int() < v2.Int()
+ case stringKind:
+ truth = v1.String() < v2.String()
+ case uintKind:
+ truth = v1.Uint() < v2.Uint()
+ default:
+ panic("invalid kind")
+ }
+ }
+ return truth, nil
+}
+
+// le evaluates the comparison <= b.
+func le(arg1, arg2 interface{}) (bool, error) {
+ // <= is < or ==.
+ lessThan, err := lt(arg1, arg2)
+ if lessThan || err != nil {
+ return lessThan, err
+ }
+ return eq(arg1, arg2)
+}
+
+// gt evaluates the comparison a > b.
+func gt(arg1, arg2 interface{}) (bool, error) {
+ // > is the inverse of <=.
+ lessOrEqual, err := le(arg1, arg2)
+ if err != nil {
+ return false, err
+ }
+ return !lessOrEqual, nil
+}
+
+// ge evaluates the comparison a >= b.
+func ge(arg1, arg2 interface{}) (bool, error) {
+ // >= is the inverse of <.
+ lessThan, err := lt(arg1, arg2)
+ if err != nil {
+ return false, err
+ }
+ return !lessThan, nil
+}
+
+// HTML escaping.
+
+var (
+ htmlQuot = []byte(""") // shorter than """
+ htmlApos = []byte("'") // shorter than "'" and apos was not in HTML until HTML5
+ htmlAmp = []byte("&")
+ htmlLt = []byte("<")
+ htmlGt = []byte(">")
+)
+
+// HTMLEscape writes to w the escaped HTML equivalent of the plain text data b.
+func HTMLEscape(w io.Writer, b []byte) {
+ last := 0
+ for i, c := range b {
+ var html []byte
+ switch c {
+ case '"':
+ html = htmlQuot
+ case '\'':
+ html = htmlApos
+ case '&':
+ html = htmlAmp
+ case '<':
+ html = htmlLt
+ case '>':
+ html = htmlGt
+ default:
+ continue
+ }
+ w.Write(b[last:i])
+ w.Write(html)
+ last = i + 1
+ }
+ w.Write(b[last:])
+}
+
+// HTMLEscapeString returns the escaped HTML equivalent of the plain text data s.
+func HTMLEscapeString(s string) string {
+ // Avoid allocation if we can.
+ if strings.IndexAny(s, `'"&<>`) < 0 {
+ return s
+ }
+ var b bytes.Buffer
+ HTMLEscape(&b, []byte(s))
+ return b.String()
+}
+
+// HTMLEscaper returns the escaped HTML equivalent of the textual
+// representation of its arguments.
+func HTMLEscaper(args ...interface{}) string {
+ return HTMLEscapeString(evalArgs(args))
+}
+
+// JavaScript escaping.
+
+var (
+ jsLowUni = []byte(`\u00`)
+ hex = []byte("0123456789ABCDEF")
+
+ jsBackslash = []byte(`\\`)
+ jsApos = []byte(`\'`)
+ jsQuot = []byte(`\"`)
+ jsLt = []byte(`\x3C`)
+ jsGt = []byte(`\x3E`)
+)
+
+// JSEscape writes to w the escaped JavaScript equivalent of the plain text data b.
+func JSEscape(w io.Writer, b []byte) {
+ last := 0
+ for i := 0; i < len(b); i++ {
+ c := b[i]
+
+ if !jsIsSpecial(rune(c)) {
+ // fast path: nothing to do
+ continue
+ }
+ w.Write(b[last:i])
+
+ if c < utf8.RuneSelf {
+ // Quotes, slashes and angle brackets get quoted.
+ // Control characters get written as \u00XX.
+ switch c {
+ case '\\':
+ w.Write(jsBackslash)
+ case '\'':
+ w.Write(jsApos)
+ case '"':
+ w.Write(jsQuot)
+ case '<':
+ w.Write(jsLt)
+ case '>':
+ w.Write(jsGt)
+ default:
+ w.Write(jsLowUni)
+ t, b := c>>4, c&0x0f
+ w.Write(hex[t : t+1])
+ w.Write(hex[b : b+1])
+ }
+ } else {
+ // Unicode rune.
+ r, size := utf8.DecodeRune(b[i:])
+ if unicode.IsPrint(r) {
+ w.Write(b[i : i+size])
+ } else {
+ fmt.Fprintf(w, "\\u%04X", r)
+ }
+ i += size - 1
+ }
+ last = i + 1
+ }
+ w.Write(b[last:])
+}
+
+// JSEscapeString returns the escaped JavaScript equivalent of the plain text data s.
+func JSEscapeString(s string) string {
+ // Avoid allocation if we can.
+ if strings.IndexFunc(s, jsIsSpecial) < 0 {
+ return s
+ }
+ var b bytes.Buffer
+ JSEscape(&b, []byte(s))
+ return b.String()
+}
+
+func jsIsSpecial(r rune) bool {
+ switch r {
+ case '\\', '\'', '"', '<', '>':
+ return true
+ }
+ return r < ' ' || utf8.RuneSelf <= r
+}
+
+// JSEscaper returns the escaped JavaScript equivalent of the textual
+// representation of its arguments.
+func JSEscaper(args ...interface{}) string {
+ return JSEscapeString(evalArgs(args))
+}
+
+// URLQueryEscaper returns the escaped value of the textual representation of
+// its arguments in a form suitable for embedding in a URL query.
+func URLQueryEscaper(args ...interface{}) string {
+ return url.QueryEscape(evalArgs(args))
+}
+
+// evalArgs formats the list of arguments into a string. It is therefore equivalent to
+// fmt.Sprint(args...)
+// except that each argument is indirected (if a pointer), as required,
+// using the same rules as the default string evaluation during template
+// execution.
+func evalArgs(args []interface{}) string {
+ ok := false
+ var s string
+ // Fast path for simple common case.
+ if len(args) == 1 {
+ s, ok = args[0].(string)
+ }
+ if !ok {
+ for i, arg := range args {
+ a, ok := printableValue(reflect.ValueOf(arg))
+ if ok {
+ args[i] = a
+ } // else left fmt do its thing
+ }
+ s = fmt.Sprint(args...)
+ }
+ return s
+}
--- /dev/null
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Helper functions to make constructing templates easier.
+
+package template
+
+import (
+ "fmt"
+ "io/ioutil"
+ "path/filepath"
+)
+
+// Functions and methods to parse templates.
+
+// Must is a helper that wraps a call to a function returning (*Template, error)
+// and panics if the error is non-nil. It is intended for use in variable
+// initializations such as
+// var t = template.Must(template.New("name").Parse("text"))
+func Must(t *Template, err error) *Template {
+ if err != nil {
+ panic(err)
+ }
+ return t
+}
+
+// ParseFiles creates a new Template and parses the template definitions from
+// the named files. The returned template's name will have the (base) name and
+// (parsed) contents of the first file. There must be at least one file.
+// If an error occurs, parsing stops and the returned *Template is nil.
+func ParseFiles(filenames ...string) (*Template, error) {
+ return parseFiles(nil, filenames...)
+}
+
+// ParseFiles parses the named files and associates the resulting templates with
+// t. If an error occurs, parsing stops and the returned template is nil;
+// otherwise it is t. There must be at least one file.
+func (t *Template) ParseFiles(filenames ...string) (*Template, error) {
+ return parseFiles(t, filenames...)
+}
+
+// parseFiles is the helper for the method and function. If the argument
+// template is nil, it is created from the first file.
+func parseFiles(t *Template, filenames ...string) (*Template, error) {
+ if len(filenames) == 0 {
+ // Not really a problem, but be consistent.
+ return nil, fmt.Errorf("template: no files named in call to ParseFiles")
+ }
+ for _, filename := range filenames {
+ b, err := ioutil.ReadFile(filename)
+ if err != nil {
+ return nil, err
+ }
+ s := string(b)
+ name := filepath.Base(filename)
+ // First template becomes return value if not already defined,
+ // and we use that one for subsequent New calls to associate
+ // all the templates together. Also, if this file has the same name
+ // as t, this file becomes the contents of t, so
+ // t, err := New(name).Funcs(xxx).ParseFiles(name)
+ // works. Otherwise we create a new template associated with t.
+ var tmpl *Template
+ if t == nil {
+ t = New(name)
+ }
+ if name == t.Name() {
+ tmpl = t
+ } else {
+ tmpl = t.New(name)
+ }
+ _, err = tmpl.Parse(s)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return t, nil
+}
+
+// ParseGlob creates a new Template and parses the template definitions from the
+// files identified by the pattern, which must match at least one file. The
+// returned template will have the (base) name and (parsed) contents of the
+// first file matched by the pattern. ParseGlob is equivalent to calling
+// ParseFiles with the list of files matched by the pattern.
+func ParseGlob(pattern string) (*Template, error) {
+ return parseGlob(nil, pattern)
+}
+
+// ParseGlob parses the template definitions in the files identified by the
+// pattern and associates the resulting templates with t. The pattern is
+// processed by filepath.Glob and must match at least one file. ParseGlob is
+// equivalent to calling t.ParseFiles with the list of files matched by the
+// pattern.
+func (t *Template) ParseGlob(pattern string) (*Template, error) {
+ return parseGlob(t, pattern)
+}
+
+// parseGlob is the implementation of the function and method ParseGlob.
+func parseGlob(t *Template, pattern string) (*Template, error) {
+ filenames, err := filepath.Glob(pattern)
+ if err != nil {
+ return nil, err
+ }
+ if len(filenames) == 0 {
+ return nil, fmt.Errorf("template: pattern matches no files: %#q", pattern)
+ }
+ return parseFiles(t, filenames...)
+}
--- /dev/null
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package parse
+
+import (
+ "fmt"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+)
+
+// item represents a token or text string returned from the scanner.
+type item struct {
+ typ itemType // The type of this item.
+ pos Pos // The starting position, in bytes, of this item in the input string.
+ val string // The value of this item.
+}
+
+func (i item) String() string {
+ switch {
+ case i.typ == itemEOF:
+ return "EOF"
+ case i.typ == itemError:
+ return i.val
+ case i.typ > itemKeyword:
+ return fmt.Sprintf("<%s>", i.val)
+ case len(i.val) > 10:
+ return fmt.Sprintf("%.10q...", i.val)
+ }
+ return fmt.Sprintf("%q", i.val)
+}
+
+// itemType identifies the type of lex items.
+type itemType int
+
+const (
+ itemError itemType = iota // error occurred; value is text of error
+ itemBool // boolean constant
+ itemChar // printable ASCII character; grab bag for comma etc.
+ itemCharConstant // character constant
+ itemComplex // complex constant (1+2i); imaginary is just a number
+ itemColonEquals // colon-equals (':=') introducing a declaration
+ itemEOF
+ itemField // alphanumeric identifier starting with '.'
+ itemIdentifier // alphanumeric identifier not starting with '.'
+ itemLeftDelim // left action delimiter
+ itemLeftParen // '(' inside action
+ itemNumber // simple number, including imaginary
+ itemPipe // pipe symbol
+ itemRawString // raw quoted string (includes quotes)
+ itemRightDelim // right action delimiter
+ itemElideNewline // elide newline after right delim
+ itemRightParen // ')' inside action
+ itemSpace // run of spaces separating arguments
+ itemString // quoted string (includes quotes)
+ itemText // plain text
+ itemVariable // variable starting with '$', such as '$' or '$1' or '$hello'
+ // Keywords appear after all the rest.
+ itemKeyword // used only to delimit the keywords
+ itemDot // the cursor, spelled '.'
+ itemDefine // define keyword
+ itemElse // else keyword
+ itemEnd // end keyword
+ itemIf // if keyword
+ itemNil // the untyped nil constant, easiest to treat as a keyword
+ itemRange // range keyword
+ itemTemplate // template keyword
+ itemWith // with keyword
+)
+
+var key = map[string]itemType{
+ ".": itemDot,
+ "define": itemDefine,
+ "else": itemElse,
+ "end": itemEnd,
+ "if": itemIf,
+ "range": itemRange,
+ "nil": itemNil,
+ "template": itemTemplate,
+ "with": itemWith,
+}
+
+const eof = -1
+
+// stateFn represents the state of the scanner as a function that returns the next state.
+type stateFn func(*lexer) stateFn
+
+// lexer holds the state of the scanner.
+type lexer struct {
+ name string // the name of the input; used only for error reports
+ input string // the string being scanned
+ leftDelim string // start of action
+ rightDelim string // end of action
+ state stateFn // the next lexing function to enter
+ pos Pos // current position in the input
+ start Pos // start position of this item
+ width Pos // width of last rune read from input
+ lastPos Pos // position of most recent item returned by nextItem
+ items chan item // channel of scanned items
+ parenDepth int // nesting depth of ( ) exprs
+}
+
+// next returns the next rune in the input.
+func (l *lexer) next() rune {
+ if int(l.pos) >= len(l.input) {
+ l.width = 0
+ return eof
+ }
+ r, w := utf8.DecodeRuneInString(l.input[l.pos:])
+ l.width = Pos(w)
+ l.pos += l.width
+ return r
+}
+
+// peek returns but does not consume the next rune in the input.
+func (l *lexer) peek() rune {
+ r := l.next()
+ l.backup()
+ return r
+}
+
+// backup steps back one rune. Can only be called once per call of next.
+func (l *lexer) backup() {
+ l.pos -= l.width
+}
+
+// emit passes an item back to the client.
+func (l *lexer) emit(t itemType) {
+ l.items <- item{t, l.start, l.input[l.start:l.pos]}
+ l.start = l.pos
+}
+
+// ignore skips over the pending input before this point.
+func (l *lexer) ignore() {
+ l.start = l.pos
+}
+
+// accept consumes the next rune if it's from the valid set.
+func (l *lexer) accept(valid string) bool {
+ if strings.IndexRune(valid, l.next()) >= 0 {
+ return true
+ }
+ l.backup()
+ return false
+}
+
+// acceptRun consumes a run of runes from the valid set.
+func (l *lexer) acceptRun(valid string) {
+ for strings.IndexRune(valid, l.next()) >= 0 {
+ }
+ l.backup()
+}
+
+// lineNumber reports which line we're on, based on the position of
+// the previous item returned by nextItem. Doing it this way
+// means we don't have to worry about peek double counting.
+func (l *lexer) lineNumber() int {
+ return 1 + strings.Count(l.input[:l.lastPos], "\n")
+}
+
+// errorf returns an error token and terminates the scan by passing
+// back a nil pointer that will be the next state, terminating l.nextItem.
+func (l *lexer) errorf(format string, args ...interface{}) stateFn {
+ l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)}
+ return nil
+}
+
+// nextItem returns the next item from the input.
+func (l *lexer) nextItem() item {
+ item := <-l.items
+ l.lastPos = item.pos
+ return item
+}
+
+// lex creates a new scanner for the input string.
+func lex(name, input, left, right string) *lexer {
+ if left == "" {
+ left = leftDelim
+ }
+ if right == "" {
+ right = rightDelim
+ }
+ l := &lexer{
+ name: name,
+ input: input,
+ leftDelim: left,
+ rightDelim: right,
+ items: make(chan item),
+ }
+ go l.run()
+ return l
+}
+
+// run runs the state machine for the lexer.
+func (l *lexer) run() {
+ for l.state = lexText; l.state != nil; {
+ l.state = l.state(l)
+ }
+}
+
+// state functions
+
+const (
+ leftDelim = "{{"
+ rightDelim = "}}"
+ leftComment = "/*"
+ rightComment = "*/"
+)
+
+// lexText scans until an opening action delimiter, "{{".
+func lexText(l *lexer) stateFn {
+ for {
+ if strings.HasPrefix(l.input[l.pos:], l.leftDelim) {
+ if l.pos > l.start {
+ l.emit(itemText)
+ }
+ return lexLeftDelim
+ }
+ if l.next() == eof {
+ break
+ }
+ }
+ // Correctly reached EOF.
+ if l.pos > l.start {
+ l.emit(itemText)
+ }
+ l.emit(itemEOF)
+ return nil
+}
+
+// lexLeftDelim scans the left delimiter, which is known to be present.
+func lexLeftDelim(l *lexer) stateFn {
+ l.pos += Pos(len(l.leftDelim))
+ if strings.HasPrefix(l.input[l.pos:], leftComment) {
+ return lexComment
+ }
+ l.emit(itemLeftDelim)
+ l.parenDepth = 0
+ return lexInsideAction
+}
+
+// lexComment scans a comment. The left comment marker is known to be present.
+func lexComment(l *lexer) stateFn {
+ l.pos += Pos(len(leftComment))
+ i := strings.Index(l.input[l.pos:], rightComment)
+ if i < 0 {
+ return l.errorf("unclosed comment")
+ }
+ l.pos += Pos(i + len(rightComment))
+ if !strings.HasPrefix(l.input[l.pos:], l.rightDelim) {
+ return l.errorf("comment ends before closing delimiter")
+
+ }
+ l.pos += Pos(len(l.rightDelim))
+ l.ignore()
+ return lexText
+}
+
+// lexRightDelim scans the right delimiter, which is known to be present.
+func lexRightDelim(l *lexer) stateFn {
+ l.pos += Pos(len(l.rightDelim))
+ l.emit(itemRightDelim)
+ if l.peek() == '\\' {
+ l.pos++
+ l.emit(itemElideNewline)
+ }
+ return lexText
+}
+
+// lexInsideAction scans the elements inside action delimiters.
+func lexInsideAction(l *lexer) stateFn {
+ // Either number, quoted string, or identifier.
+ // Spaces separate arguments; runs of spaces turn into itemSpace.
+ // Pipe symbols separate and are emitted.
+ if strings.HasPrefix(l.input[l.pos:], l.rightDelim+"\\") || strings.HasPrefix(l.input[l.pos:], l.rightDelim) {
+ if l.parenDepth == 0 {
+ return lexRightDelim
+ }
+ return l.errorf("unclosed left paren")
+ }
+ switch r := l.next(); {
+ case r == eof || isEndOfLine(r):
+ return l.errorf("unclosed action")
+ case isSpace(r):
+ return lexSpace
+ case r == ':':
+ if l.next() != '=' {
+ return l.errorf("expected :=")
+ }
+ l.emit(itemColonEquals)
+ case r == '|':
+ l.emit(itemPipe)
+ case r == '"':
+ return lexQuote
+ case r == '`':
+ return lexRawQuote
+ case r == '$':
+ return lexVariable
+ case r == '\'':
+ return lexChar
+ case r == '.':
+ // special look-ahead for ".field" so we don't break l.backup().
+ if l.pos < Pos(len(l.input)) {
+ r := l.input[l.pos]
+ if r < '0' || '9' < r {
+ return lexField
+ }
+ }
+ fallthrough // '.' can start a number.
+ case r == '+' || r == '-' || ('0' <= r && r <= '9'):
+ l.backup()
+ return lexNumber
+ case isAlphaNumeric(r):
+ l.backup()
+ return lexIdentifier
+ case r == '(':
+ l.emit(itemLeftParen)
+ l.parenDepth++
+ return lexInsideAction
+ case r == ')':
+ l.emit(itemRightParen)
+ l.parenDepth--
+ if l.parenDepth < 0 {
+ return l.errorf("unexpected right paren %#U", r)
+ }
+ return lexInsideAction
+ case r <= unicode.MaxASCII && unicode.IsPrint(r):
+ l.emit(itemChar)
+ return lexInsideAction
+ default:
+ return l.errorf("unrecognized character in action: %#U", r)
+ }
+ return lexInsideAction
+}
+
+// lexSpace scans a run of space characters.
+// One space has already been seen.
+func lexSpace(l *lexer) stateFn {
+ for isSpace(l.peek()) {
+ l.next()
+ }
+ l.emit(itemSpace)
+ return lexInsideAction
+}
+
+// lexIdentifier scans an alphanumeric.
+func lexIdentifier(l *lexer) stateFn {
+Loop:
+ for {
+ switch r := l.next(); {
+ case isAlphaNumeric(r):
+ // absorb.
+ default:
+ l.backup()
+ word := l.input[l.start:l.pos]
+ if !l.atTerminator() {
+ return l.errorf("bad character %#U", r)
+ }
+ switch {
+ case key[word] > itemKeyword:
+ l.emit(key[word])
+ case word[0] == '.':
+ l.emit(itemField)
+ case word == "true", word == "false":
+ l.emit(itemBool)
+ default:
+ l.emit(itemIdentifier)
+ }
+ break Loop
+ }
+ }
+ return lexInsideAction
+}
+
+// lexField scans a field: .Alphanumeric.
+// The . has been scanned.
+func lexField(l *lexer) stateFn {
+ return lexFieldOrVariable(l, itemField)
+}
+
+// lexVariable scans a Variable: $Alphanumeric.
+// The $ has been scanned.
+func lexVariable(l *lexer) stateFn {
+ if l.atTerminator() { // Nothing interesting follows -> "$".
+ l.emit(itemVariable)
+ return lexInsideAction
+ }
+ return lexFieldOrVariable(l, itemVariable)
+}
+
+// lexVariable scans a field or variable: [.$]Alphanumeric.
+// The . or $ has been scanned.
+func lexFieldOrVariable(l *lexer, typ itemType) stateFn {
+ if l.atTerminator() { // Nothing interesting follows -> "." or "$".
+ if typ == itemVariable {
+ l.emit(itemVariable)
+ } else {
+ l.emit(itemDot)
+ }
+ return lexInsideAction
+ }
+ var r rune
+ for {
+ r = l.next()
+ if !isAlphaNumeric(r) {
+ l.backup()
+ break
+ }
+ }
+ if !l.atTerminator() {
+ return l.errorf("bad character %#U", r)
+ }
+ l.emit(typ)
+ return lexInsideAction
+}
+
+// atTerminator reports whether the input is at valid termination character to
+// appear after an identifier. Breaks .X.Y into two pieces. Also catches cases
+// like "$x+2" not being acceptable without a space, in case we decide one
+// day to implement arithmetic.
+func (l *lexer) atTerminator() bool {
+ r := l.peek()
+ if isSpace(r) || isEndOfLine(r) {
+ return true
+ }
+ switch r {
+ case eof, '.', ',', '|', ':', ')', '(':
+ return true
+ }
+ // Does r start the delimiter? This can be ambiguous (with delim=="//", $x/2 will
+ // succeed but should fail) but only in extremely rare cases caused by willfully
+ // bad choice of delimiter.
+ if rd, _ := utf8.DecodeRuneInString(l.rightDelim); rd == r {
+ return true
+ }
+ return false
+}
+
+// lexChar scans a character constant. The initial quote is already
+// scanned. Syntax checking is done by the parser.
+func lexChar(l *lexer) stateFn {
+Loop:
+ for {
+ switch l.next() {
+ case '\\':
+ if r := l.next(); r != eof && r != '\n' {
+ break
+ }
+ fallthrough
+ case eof, '\n':
+ return l.errorf("unterminated character constant")
+ case '\'':
+ break Loop
+ }
+ }
+ l.emit(itemCharConstant)
+ return lexInsideAction
+}
+
+// lexNumber scans a number: decimal, octal, hex, float, or imaginary. This
+// isn't a perfect number scanner - for instance it accepts "." and "0x0.2"
+// and "089" - but when it's wrong the input is invalid and the parser (via
+// strconv) will notice.
+func lexNumber(l *lexer) stateFn {
+ if !l.scanNumber() {
+ return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
+ }
+ if sign := l.peek(); sign == '+' || sign == '-' {
+ // Complex: 1+2i. No spaces, must end in 'i'.
+ if !l.scanNumber() || l.input[l.pos-1] != 'i' {
+ return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
+ }
+ l.emit(itemComplex)
+ } else {
+ l.emit(itemNumber)
+ }
+ return lexInsideAction
+}
+
+func (l *lexer) scanNumber() bool {
+ // Optional leading sign.
+ l.accept("+-")
+ // Is it hex?
+ digits := "0123456789"
+ if l.accept("0") && l.accept("xX") {
+ digits = "0123456789abcdefABCDEF"
+ }
+ l.acceptRun(digits)
+ if l.accept(".") {
+ l.acceptRun(digits)
+ }
+ if l.accept("eE") {
+ l.accept("+-")
+ l.acceptRun("0123456789")
+ }
+ // Is it imaginary?
+ l.accept("i")
+ // Next thing mustn't be alphanumeric.
+ if isAlphaNumeric(l.peek()) {
+ l.next()
+ return false
+ }
+ return true
+}
+
+// lexQuote scans a quoted string.
+func lexQuote(l *lexer) stateFn {
+Loop:
+ for {
+ switch l.next() {
+ case '\\':
+ if r := l.next(); r != eof && r != '\n' {
+ break
+ }
+ fallthrough
+ case eof, '\n':
+ return l.errorf("unterminated quoted string")
+ case '"':
+ break Loop
+ }
+ }
+ l.emit(itemString)
+ return lexInsideAction
+}
+
+// lexRawQuote scans a raw quoted string.
+func lexRawQuote(l *lexer) stateFn {
+Loop:
+ for {
+ switch l.next() {
+ case eof, '\n':
+ return l.errorf("unterminated raw quoted string")
+ case '`':
+ break Loop
+ }
+ }
+ l.emit(itemRawString)
+ return lexInsideAction
+}
+
+// isSpace reports whether r is a space character.
+func isSpace(r rune) bool {
+ return r == ' ' || r == '\t'
+}
+
+// isEndOfLine reports whether r is an end-of-line character.
+func isEndOfLine(r rune) bool {
+ return r == '\r' || r == '\n'
+}
+
+// isAlphaNumeric reports whether r is an alphabetic, digit, or underscore.
+func isAlphaNumeric(r rune) bool {
+ return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r)
+}
--- /dev/null
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Parse nodes.
+
+package parse
+
+import (
+ "bytes"
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+var textFormat = "%s" // Changed to "%q" in tests for better error messages.
+
+// A Node is an element in the parse tree. The interface is trivial.
+// The interface contains an unexported method so that only
+// types local to this package can satisfy it.
+type Node interface {
+ Type() NodeType
+ String() string
+ // Copy does a deep copy of the Node and all its components.
+ // To avoid type assertions, some XxxNodes also have specialized
+ // CopyXxx methods that return *XxxNode.
+ Copy() Node
+ Position() Pos // byte position of start of node in full original input string
+ // tree returns the containing *Tree.
+ // It is unexported so all implementations of Node are in this package.
+ tree() *Tree
+}
+
+// NodeType identifies the type of a parse tree node.
+type NodeType int
+
+// Pos represents a byte position in the original input text from which
+// this template was parsed.
+type Pos int
+
+func (p Pos) Position() Pos {
+ return p
+}
+
+// Type returns itself and provides an easy default implementation
+// for embedding in a Node. Embedded in all non-trivial Nodes.
+func (t NodeType) Type() NodeType {
+ return t
+}
+
+const (
+ NodeText NodeType = iota // Plain text.
+ NodeAction // A non-control action such as a field evaluation.
+ NodeBool // A boolean constant.
+ NodeChain // A sequence of field accesses.
+ NodeCommand // An element of a pipeline.
+ NodeDot // The cursor, dot.
+ nodeElse // An else action. Not added to tree.
+ nodeEnd // An end action. Not added to tree.
+ NodeField // A field or method name.
+ NodeIdentifier // An identifier; always a function name.
+ NodeIf // An if action.
+ NodeList // A list of Nodes.
+ NodeNil // An untyped nil constant.
+ NodeNumber // A numerical constant.
+ NodePipe // A pipeline of commands.
+ NodeRange // A range action.
+ NodeString // A string constant.
+ NodeTemplate // A template invocation action.
+ NodeVariable // A $ variable.
+ NodeWith // A with action.
+)
+
+// Nodes.
+
+// ListNode holds a sequence of nodes.
+type ListNode struct {
+ NodeType
+ Pos
+ tr *Tree
+ Nodes []Node // The element nodes in lexical order.
+}
+
+func (t *Tree) newList(pos Pos) *ListNode {
+ return &ListNode{tr: t, NodeType: NodeList, Pos: pos}
+}
+
+func (l *ListNode) append(n Node) {
+ l.Nodes = append(l.Nodes, n)
+}
+
+func (l *ListNode) tree() *Tree {
+ return l.tr
+}
+
+func (l *ListNode) String() string {
+ b := new(bytes.Buffer)
+ for _, n := range l.Nodes {
+ fmt.Fprint(b, n)
+ }
+ return b.String()
+}
+
+func (l *ListNode) CopyList() *ListNode {
+ if l == nil {
+ return l
+ }
+ n := l.tr.newList(l.Pos)
+ for _, elem := range l.Nodes {
+ n.append(elem.Copy())
+ }
+ return n
+}
+
+func (l *ListNode) Copy() Node {
+ return l.CopyList()
+}
+
+// TextNode holds plain text.
+type TextNode struct {
+ NodeType
+ Pos
+ tr *Tree
+ Text []byte // The text; may span newlines.
+}
+
+func (t *Tree) newText(pos Pos, text string) *TextNode {
+ return &TextNode{tr: t, NodeType: NodeText, Pos: pos, Text: []byte(text)}
+}
+
+func (t *TextNode) String() string {
+ return fmt.Sprintf(textFormat, t.Text)
+}
+
+func (t *TextNode) tree() *Tree {
+ return t.tr
+}
+
+func (t *TextNode) Copy() Node {
+ return &TextNode{tr: t.tr, NodeType: NodeText, Pos: t.Pos, Text: append([]byte{}, t.Text...)}
+}
+
+// PipeNode holds a pipeline with optional declaration
+type PipeNode struct {
+ NodeType
+ Pos
+ tr *Tree
+ Line int // The line number in the input (deprecated; kept for compatibility)
+ Decl []*VariableNode // Variable declarations in lexical order.
+ Cmds []*CommandNode // The commands in lexical order.
+}
+
+func (t *Tree) newPipeline(pos Pos, line int, decl []*VariableNode) *PipeNode {
+ return &PipeNode{tr: t, NodeType: NodePipe, Pos: pos, Line: line, Decl: decl}
+}
+
+func (p *PipeNode) append(command *CommandNode) {
+ p.Cmds = append(p.Cmds, command)
+}
+
+func (p *PipeNode) String() string {
+ s := ""
+ if len(p.Decl) > 0 {
+ for i, v := range p.Decl {
+ if i > 0 {
+ s += ", "
+ }
+ s += v.String()
+ }
+ s += " := "
+ }
+ for i, c := range p.Cmds {
+ if i > 0 {
+ s += " | "
+ }
+ s += c.String()
+ }
+ return s
+}
+
+func (p *PipeNode) tree() *Tree {
+ return p.tr
+}
+
+func (p *PipeNode) CopyPipe() *PipeNode {
+ if p == nil {
+ return p
+ }
+ var decl []*VariableNode
+ for _, d := range p.Decl {
+ decl = append(decl, d.Copy().(*VariableNode))
+ }
+ n := p.tr.newPipeline(p.Pos, p.Line, decl)
+ for _, c := range p.Cmds {
+ n.append(c.Copy().(*CommandNode))
+ }
+ return n
+}
+
+func (p *PipeNode) Copy() Node {
+ return p.CopyPipe()
+}
+
+// ActionNode holds an action (something bounded by delimiters).
+// Control actions have their own nodes; ActionNode represents simple
+// ones such as field evaluations and parenthesized pipelines.
+type ActionNode struct {
+ NodeType
+ Pos
+ tr *Tree
+ Line int // The line number in the input (deprecated; kept for compatibility)
+ Pipe *PipeNode // The pipeline in the action.
+}
+
+func (t *Tree) newAction(pos Pos, line int, pipe *PipeNode) *ActionNode {
+ return &ActionNode{tr: t, NodeType: NodeAction, Pos: pos, Line: line, Pipe: pipe}
+}
+
+func (a *ActionNode) String() string {
+ return fmt.Sprintf("{{%s}}", a.Pipe)
+
+}
+
+func (a *ActionNode) tree() *Tree {
+ return a.tr
+}
+
+func (a *ActionNode) Copy() Node {
+ return a.tr.newAction(a.Pos, a.Line, a.Pipe.CopyPipe())
+
+}
+
+// CommandNode holds a command (a pipeline inside an evaluating action).
+type CommandNode struct {
+ NodeType
+ Pos
+ tr *Tree
+ Args []Node // Arguments in lexical order: Identifier, field, or constant.
+}
+
+func (t *Tree) newCommand(pos Pos) *CommandNode {
+ return &CommandNode{tr: t, NodeType: NodeCommand, Pos: pos}
+}
+
+func (c *CommandNode) append(arg Node) {
+ c.Args = append(c.Args, arg)
+}
+
+func (c *CommandNode) String() string {
+ s := ""
+ for i, arg := range c.Args {
+ if i > 0 {
+ s += " "
+ }
+ if arg, ok := arg.(*PipeNode); ok {
+ s += "(" + arg.String() + ")"
+ continue
+ }
+ s += arg.String()
+ }
+ return s
+}
+
+func (c *CommandNode) tree() *Tree {
+ return c.tr
+}
+
+func (c *CommandNode) Copy() Node {
+ if c == nil {
+ return c
+ }
+ n := c.tr.newCommand(c.Pos)
+ for _, c := range c.Args {
+ n.append(c.Copy())
+ }
+ return n
+}
+
+// IdentifierNode holds an identifier.
+type IdentifierNode struct {
+ NodeType
+ Pos
+ tr *Tree
+ Ident string // The identifier's name.
+}
+
+// NewIdentifier returns a new IdentifierNode with the given identifier name.
+func NewIdentifier(ident string) *IdentifierNode {
+ return &IdentifierNode{NodeType: NodeIdentifier, Ident: ident}
+}
+
+// SetPos sets the position. NewIdentifier is a public method so we can't modify its signature.
+// Chained for convenience.
+// TODO: fix one day?
+func (i *IdentifierNode) SetPos(pos Pos) *IdentifierNode {
+ i.Pos = pos
+ return i
+}
+
+// SetTree sets the parent tree for the node. NewIdentifier is a public method so we can't modify its signature.
+// Chained for convenience.
+// TODO: fix one day?
+func (i *IdentifierNode) SetTree(t *Tree) *IdentifierNode {
+ i.tr = t
+ return i
+}
+
+func (i *IdentifierNode) String() string {
+ return i.Ident
+}
+
+func (i *IdentifierNode) tree() *Tree {
+ return i.tr
+}
+
+func (i *IdentifierNode) Copy() Node {
+ return NewIdentifier(i.Ident).SetTree(i.tr).SetPos(i.Pos)
+}
+
+// VariableNode holds a list of variable names, possibly with chained field
+// accesses. The dollar sign is part of the (first) name.
+type VariableNode struct {
+ NodeType
+ Pos
+ tr *Tree
+ Ident []string // Variable name and fields in lexical order.
+}
+
+func (t *Tree) newVariable(pos Pos, ident string) *VariableNode {
+ return &VariableNode{tr: t, NodeType: NodeVariable, Pos: pos, Ident: strings.Split(ident, ".")}
+}
+
+func (v *VariableNode) String() string {
+ s := ""
+ for i, id := range v.Ident {
+ if i > 0 {
+ s += "."
+ }
+ s += id
+ }
+ return s
+}
+
+func (v *VariableNode) tree() *Tree {
+ return v.tr
+}
+
+func (v *VariableNode) Copy() Node {
+ return &VariableNode{tr: v.tr, NodeType: NodeVariable, Pos: v.Pos, Ident: append([]string{}, v.Ident...)}
+}
+
+// DotNode holds the special identifier '.'.
+type DotNode struct {
+ NodeType
+ Pos
+ tr *Tree
+}
+
+func (t *Tree) newDot(pos Pos) *DotNode {
+ return &DotNode{tr: t, NodeType: NodeDot, Pos: pos}
+}
+
+func (d *DotNode) Type() NodeType {
+ // Override method on embedded NodeType for API compatibility.
+ // TODO: Not really a problem; could change API without effect but
+ // api tool complains.
+ return NodeDot
+}
+
+func (d *DotNode) String() string {
+ return "."
+}
+
+func (d *DotNode) tree() *Tree {
+ return d.tr
+}
+
+func (d *DotNode) Copy() Node {
+ return d.tr.newDot(d.Pos)
+}
+
+// NilNode holds the special identifier 'nil' representing an untyped nil constant.
+type NilNode struct {
+ NodeType
+ Pos
+ tr *Tree
+}
+
+func (t *Tree) newNil(pos Pos) *NilNode {
+ return &NilNode{tr: t, NodeType: NodeNil, Pos: pos}
+}
+
+func (n *NilNode) Type() NodeType {
+ // Override method on embedded NodeType for API compatibility.
+ // TODO: Not really a problem; could change API without effect but
+ // api tool complains.
+ return NodeNil
+}
+
+func (n *NilNode) String() string {
+ return "nil"
+}
+
+func (n *NilNode) tree() *Tree {
+ return n.tr
+}
+
+func (n *NilNode) Copy() Node {
+ return n.tr.newNil(n.Pos)
+}
+
+// FieldNode holds a field (identifier starting with '.').
+// The names may be chained ('.x.y').
+// The period is dropped from each ident.
+type FieldNode struct {
+ NodeType
+ Pos
+ tr *Tree
+ Ident []string // The identifiers in lexical order.
+}
+
+func (t *Tree) newField(pos Pos, ident string) *FieldNode {
+ return &FieldNode{tr: t, NodeType: NodeField, Pos: pos, Ident: strings.Split(ident[1:], ".")} // [1:] to drop leading period
+}
+
+func (f *FieldNode) String() string {
+ s := ""
+ for _, id := range f.Ident {
+ s += "." + id
+ }
+ return s
+}
+
+func (f *FieldNode) tree() *Tree {
+ return f.tr
+}
+
+func (f *FieldNode) Copy() Node {
+ return &FieldNode{tr: f.tr, NodeType: NodeField, Pos: f.Pos, Ident: append([]string{}, f.Ident...)}
+}
+
+// ChainNode holds a term followed by a chain of field accesses (identifier starting with '.').
+// The names may be chained ('.x.y').
+// The periods are dropped from each ident.
+type ChainNode struct {
+ NodeType
+ Pos
+ tr *Tree
+ Node Node
+ Field []string // The identifiers in lexical order.
+}
+
+func (t *Tree) newChain(pos Pos, node Node) *ChainNode {
+ return &ChainNode{tr: t, NodeType: NodeChain, Pos: pos, Node: node}
+}
+
+// Add adds the named field (which should start with a period) to the end of the chain.
+func (c *ChainNode) Add(field string) {
+ if len(field) == 0 || field[0] != '.' {
+ panic("no dot in field")
+ }
+ field = field[1:] // Remove leading dot.
+ if field == "" {
+ panic("empty field")
+ }
+ c.Field = append(c.Field, field)
+}
+
+func (c *ChainNode) String() string {
+ s := c.Node.String()
+ if _, ok := c.Node.(*PipeNode); ok {
+ s = "(" + s + ")"
+ }
+ for _, field := range c.Field {
+ s += "." + field
+ }
+ return s
+}
+
+func (c *ChainNode) tree() *Tree {
+ return c.tr
+}
+
+func (c *ChainNode) Copy() Node {
+ return &ChainNode{tr: c.tr, NodeType: NodeChain, Pos: c.Pos, Node: c.Node, Field: append([]string{}, c.Field...)}
+}
+
+// BoolNode holds a boolean constant.
+type BoolNode struct {
+ NodeType
+ Pos
+ tr *Tree
+ True bool // The value of the boolean constant.
+}
+
+func (t *Tree) newBool(pos Pos, true bool) *BoolNode {
+ return &BoolNode{tr: t, NodeType: NodeBool, Pos: pos, True: true}
+}
+
+func (b *BoolNode) String() string {
+ if b.True {
+ return "true"
+ }
+ return "false"
+}
+
+func (b *BoolNode) tree() *Tree {
+ return b.tr
+}
+
+func (b *BoolNode) Copy() Node {
+ return b.tr.newBool(b.Pos, b.True)
+}
+
+// NumberNode holds a number: signed or unsigned integer, float, or complex.
+// The value is parsed and stored under all the types that can represent the value.
+// This simulates in a small amount of code the behavior of Go's ideal constants.
+type NumberNode struct {
+ NodeType
+ Pos
+ tr *Tree
+ IsInt bool // Number has an integral value.
+ IsUint bool // Number has an unsigned integral value.
+ IsFloat bool // Number has a floating-point value.
+ IsComplex bool // Number is complex.
+ Int64 int64 // The signed integer value.
+ Uint64 uint64 // The unsigned integer value.
+ Float64 float64 // The floating-point value.
+ Complex128 complex128 // The complex value.
+ Text string // The original textual representation from the input.
+}
+
+func (t *Tree) newNumber(pos Pos, text string, typ itemType) (*NumberNode, error) {
+ n := &NumberNode{tr: t, NodeType: NodeNumber, Pos: pos, Text: text}
+ switch typ {
+ case itemCharConstant:
+ rune, _, tail, err := strconv.UnquoteChar(text[1:], text[0])
+ if err != nil {
+ return nil, err
+ }
+ if tail != "'" {
+ return nil, fmt.Errorf("malformed character constant: %s", text)
+ }
+ n.Int64 = int64(rune)
+ n.IsInt = true
+ n.Uint64 = uint64(rune)
+ n.IsUint = true
+ n.Float64 = float64(rune) // odd but those are the rules.
+ n.IsFloat = true
+ return n, nil
+ case itemComplex:
+ // fmt.Sscan can parse the pair, so let it do the work.
+ if _, err := fmt.Sscan(text, &n.Complex128); err != nil {
+ return nil, err
+ }
+ n.IsComplex = true
+ n.simplifyComplex()
+ return n, nil
+ }
+ // Imaginary constants can only be complex unless they are zero.
+ if len(text) > 0 && text[len(text)-1] == 'i' {
+ f, err := strconv.ParseFloat(text[:len(text)-1], 64)
+ if err == nil {
+ n.IsComplex = true
+ n.Complex128 = complex(0, f)
+ n.simplifyComplex()
+ return n, nil
+ }
+ }
+ // Do integer test first so we get 0x123 etc.
+ u, err := strconv.ParseUint(text, 0, 64) // will fail for -0; fixed below.
+ if err == nil {
+ n.IsUint = true
+ n.Uint64 = u
+ }
+ i, err := strconv.ParseInt(text, 0, 64)
+ if err == nil {
+ n.IsInt = true
+ n.Int64 = i
+ if i == 0 {
+ n.IsUint = true // in case of -0.
+ n.Uint64 = u
+ }
+ }
+ // If an integer extraction succeeded, promote the float.
+ if n.IsInt {
+ n.IsFloat = true
+ n.Float64 = float64(n.Int64)
+ } else if n.IsUint {
+ n.IsFloat = true
+ n.Float64 = float64(n.Uint64)
+ } else {
+ f, err := strconv.ParseFloat(text, 64)
+ if err == nil {
+ n.IsFloat = true
+ n.Float64 = f
+ // If a floating-point extraction succeeded, extract the int if needed.
+ if !n.IsInt && float64(int64(f)) == f {
+ n.IsInt = true
+ n.Int64 = int64(f)
+ }
+ if !n.IsUint && float64(uint64(f)) == f {
+ n.IsUint = true
+ n.Uint64 = uint64(f)
+ }
+ }
+ }
+ if !n.IsInt && !n.IsUint && !n.IsFloat {
+ return nil, fmt.Errorf("illegal number syntax: %q", text)
+ }
+ return n, nil
+}
+
+// simplifyComplex pulls out any other types that are represented by the complex number.
+// These all require that the imaginary part be zero.
+func (n *NumberNode) simplifyComplex() {
+ n.IsFloat = imag(n.Complex128) == 0
+ if n.IsFloat {
+ n.Float64 = real(n.Complex128)
+ n.IsInt = float64(int64(n.Float64)) == n.Float64
+ if n.IsInt {
+ n.Int64 = int64(n.Float64)
+ }
+ n.IsUint = float64(uint64(n.Float64)) == n.Float64
+ if n.IsUint {
+ n.Uint64 = uint64(n.Float64)
+ }
+ }
+}
+
+func (n *NumberNode) String() string {
+ return n.Text
+}
+
+func (n *NumberNode) tree() *Tree {
+ return n.tr
+}
+
+func (n *NumberNode) Copy() Node {
+ nn := new(NumberNode)
+ *nn = *n // Easy, fast, correct.
+ return nn
+}
+
+// StringNode holds a string constant. The value has been "unquoted".
+type StringNode struct {
+ NodeType
+ Pos
+ tr *Tree
+ Quoted string // The original text of the string, with quotes.
+ Text string // The string, after quote processing.
+}
+
+func (t *Tree) newString(pos Pos, orig, text string) *StringNode {
+ return &StringNode{tr: t, NodeType: NodeString, Pos: pos, Quoted: orig, Text: text}
+}
+
+func (s *StringNode) String() string {
+ return s.Quoted
+}
+
+func (s *StringNode) tree() *Tree {
+ return s.tr
+}
+
+func (s *StringNode) Copy() Node {
+ return s.tr.newString(s.Pos, s.Quoted, s.Text)
+}
+
+// endNode represents an {{end}} action.
+// It does not appear in the final parse tree.
+type endNode struct {
+ NodeType
+ Pos
+ tr *Tree
+}
+
+func (t *Tree) newEnd(pos Pos) *endNode {
+ return &endNode{tr: t, NodeType: nodeEnd, Pos: pos}
+}
+
+func (e *endNode) String() string {
+ return "{{end}}"
+}
+
+func (e *endNode) tree() *Tree {
+ return e.tr
+}
+
+func (e *endNode) Copy() Node {
+ return e.tr.newEnd(e.Pos)
+}
+
+// elseNode represents an {{else}} action. Does not appear in the final tree.
+type elseNode struct {
+ NodeType
+ Pos
+ tr *Tree
+ Line int // The line number in the input (deprecated; kept for compatibility)
+}
+
+func (t *Tree) newElse(pos Pos, line int) *elseNode {
+ return &elseNode{tr: t, NodeType: nodeElse, Pos: pos, Line: line}
+}
+
+func (e *elseNode) Type() NodeType {
+ return nodeElse
+}
+
+func (e *elseNode) String() string {
+ return "{{else}}"
+}
+
+func (e *elseNode) tree() *Tree {
+ return e.tr
+}
+
+func (e *elseNode) Copy() Node {
+ return e.tr.newElse(e.Pos, e.Line)
+}
+
+// BranchNode is the common representation of if, range, and with.
+type BranchNode struct {
+ NodeType
+ Pos
+ tr *Tree
+ Line int // The line number in the input (deprecated; kept for compatibility)
+ Pipe *PipeNode // The pipeline to be evaluated.
+ List *ListNode // What to execute if the value is non-empty.
+ ElseList *ListNode // What to execute if the value is empty (nil if absent).
+}
+
+func (b *BranchNode) String() string {
+ name := ""
+ switch b.NodeType {
+ case NodeIf:
+ name = "if"
+ case NodeRange:
+ name = "range"
+ case NodeWith:
+ name = "with"
+ default:
+ panic("unknown branch type")
+ }
+ if b.ElseList != nil {
+ return fmt.Sprintf("{{%s %s}}%s{{else}}%s{{end}}", name, b.Pipe, b.List, b.ElseList)
+ }
+ return fmt.Sprintf("{{%s %s}}%s{{end}}", name, b.Pipe, b.List)
+}
+
+func (b *BranchNode) tree() *Tree {
+ return b.tr
+}
+
+func (b *BranchNode) Copy() Node {
+ switch b.NodeType {
+ case NodeIf:
+ return b.tr.newIf(b.Pos, b.Line, b.Pipe, b.List, b.ElseList)
+ case NodeRange:
+ return b.tr.newRange(b.Pos, b.Line, b.Pipe, b.List, b.ElseList)
+ case NodeWith:
+ return b.tr.newWith(b.Pos, b.Line, b.Pipe, b.List, b.ElseList)
+ default:
+ panic("unknown branch type")
+ }
+}
+
+// IfNode represents an {{if}} action and its commands.
+type IfNode struct {
+ BranchNode
+}
+
+func (t *Tree) newIf(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *IfNode {
+ return &IfNode{BranchNode{tr: t, NodeType: NodeIf, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+}
+
+func (i *IfNode) Copy() Node {
+ return i.tr.newIf(i.Pos, i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList())
+}
+
+// RangeNode represents a {{range}} action and its commands.
+type RangeNode struct {
+ BranchNode
+}
+
+func (t *Tree) newRange(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode {
+ return &RangeNode{BranchNode{tr: t, NodeType: NodeRange, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+}
+
+func (r *RangeNode) Copy() Node {
+ return r.tr.newRange(r.Pos, r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList())
+}
+
+// WithNode represents a {{with}} action and its commands.
+type WithNode struct {
+ BranchNode
+}
+
+func (t *Tree) newWith(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *WithNode {
+ return &WithNode{BranchNode{tr: t, NodeType: NodeWith, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+}
+
+func (w *WithNode) Copy() Node {
+ return w.tr.newWith(w.Pos, w.Line, w.Pipe.CopyPipe(), w.List.CopyList(), w.ElseList.CopyList())
+}
+
+// TemplateNode represents a {{template}} action.
+type TemplateNode struct {
+ NodeType
+ Pos
+ tr *Tree
+ Line int // The line number in the input (deprecated; kept for compatibility)
+ Name string // The name of the template (unquoted).
+ Pipe *PipeNode // The command to evaluate as dot for the template.
+}
+
+func (t *Tree) newTemplate(pos Pos, line int, name string, pipe *PipeNode) *TemplateNode {
+ return &TemplateNode{tr: t, NodeType: NodeTemplate, Pos: pos, Line: line, Name: name, Pipe: pipe}
+}
+
+func (t *TemplateNode) String() string {
+ if t.Pipe == nil {
+ return fmt.Sprintf("{{template %q}}", t.Name)
+ }
+ return fmt.Sprintf("{{template %q %s}}", t.Name, t.Pipe)
+}
+
+func (t *TemplateNode) tree() *Tree {
+ return t.tr
+}
+
+func (t *TemplateNode) Copy() Node {
+ return t.tr.newTemplate(t.Pos, t.Line, t.Name, t.Pipe.CopyPipe())
+}
--- /dev/null
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package parse builds parse trees for templates as defined by text/template
+// and html/template. Clients should use those packages to construct templates
+// rather than this one, which provides shared internal data structures not
+// intended for general use.
+package parse
+
+import (
+ "bytes"
+ "fmt"
+ "runtime"
+ "strconv"
+ "strings"
+)
+
+// Tree is the representation of a single parsed template.
+type Tree struct {
+ Name string // name of the template represented by the tree.
+ ParseName string // name of the top-level template during parsing, for error messages.
+ Root *ListNode // top-level root of the tree.
+ text string // text parsed to create the template (or its parent)
+ // Parsing only; cleared after parse.
+ funcs []map[string]interface{}
+ lex *lexer
+ token [3]item // three-token lookahead for parser.
+ peekCount int
+ vars []string // variables defined at the moment.
+}
+
+// Copy returns a copy of the Tree. Any parsing state is discarded.
+func (t *Tree) Copy() *Tree {
+ if t == nil {
+ return nil
+ }
+ return &Tree{
+ Name: t.Name,
+ ParseName: t.ParseName,
+ Root: t.Root.CopyList(),
+ text: t.text,
+ }
+}
+
+// Parse returns a map from template name to parse.Tree, created by parsing the
+// templates described in the argument string. The top-level template will be
+// given the specified name. If an error is encountered, parsing stops and an
+// empty map is returned with the error.
+func Parse(name, text, leftDelim, rightDelim string, funcs ...map[string]interface{}) (treeSet map[string]*Tree, err error) {
+ treeSet = make(map[string]*Tree)
+ t := New(name)
+ t.text = text
+ _, err = t.Parse(text, leftDelim, rightDelim, treeSet, funcs...)
+ return
+}
+
+// next returns the next token.
+func (t *Tree) next() item {
+ if t.peekCount > 0 {
+ t.peekCount--
+ } else {
+ t.token[0] = t.lex.nextItem()
+ }
+ return t.token[t.peekCount]
+}
+
+// backup backs the input stream up one token.
+func (t *Tree) backup() {
+ t.peekCount++
+}
+
+// backup2 backs the input stream up two tokens.
+// The zeroth token is already there.
+func (t *Tree) backup2(t1 item) {
+ t.token[1] = t1
+ t.peekCount = 2
+}
+
+// backup3 backs the input stream up three tokens
+// The zeroth token is already there.
+func (t *Tree) backup3(t2, t1 item) { // Reverse order: we're pushing back.
+ t.token[1] = t1
+ t.token[2] = t2
+ t.peekCount = 3
+}
+
+// peek returns but does not consume the next token.
+func (t *Tree) peek() item {
+ if t.peekCount > 0 {
+ return t.token[t.peekCount-1]
+ }
+ t.peekCount = 1
+ t.token[0] = t.lex.nextItem()
+ return t.token[0]
+}
+
+// nextNonSpace returns the next non-space token.
+func (t *Tree) nextNonSpace() (token item) {
+ for {
+ token = t.next()
+ if token.typ != itemSpace {
+ break
+ }
+ }
+ return token
+}
+
+// peekNonSpace returns but does not consume the next non-space token.
+func (t *Tree) peekNonSpace() (token item) {
+ for {
+ token = t.next()
+ if token.typ != itemSpace {
+ break
+ }
+ }
+ t.backup()
+ return token
+}
+
+// Parsing.
+
+// New allocates a new parse tree with the given name.
+func New(name string, funcs ...map[string]interface{}) *Tree {
+ return &Tree{
+ Name: name,
+ funcs: funcs,
+ }
+}
+
+// ErrorContext returns a textual representation of the location of the node in the input text.
+// The receiver is only used when the node does not have a pointer to the tree inside,
+// which can occur in old code.
+func (t *Tree) ErrorContext(n Node) (location, context string) {
+ pos := int(n.Position())
+ tree := n.tree()
+ if tree == nil {
+ tree = t
+ }
+ text := tree.text[:pos]
+ byteNum := strings.LastIndex(text, "\n")
+ if byteNum == -1 {
+ byteNum = pos // On first line.
+ } else {
+ byteNum++ // After the newline.
+ byteNum = pos - byteNum
+ }
+ lineNum := 1 + strings.Count(text, "\n")
+ context = n.String()
+ if len(context) > 20 {
+ context = fmt.Sprintf("%.20s...", context)
+ }
+ return fmt.Sprintf("%s:%d:%d", tree.ParseName, lineNum, byteNum), context
+}
+
+// errorf formats the error and terminates processing.
+func (t *Tree) errorf(format string, args ...interface{}) {
+ t.Root = nil
+ format = fmt.Sprintf("template: %s:%d: %s", t.ParseName, t.lex.lineNumber(), format)
+ panic(fmt.Errorf(format, args...))
+}
+
+// error terminates processing.
+func (t *Tree) error(err error) {
+ t.errorf("%s", err)
+}
+
+// expect consumes the next token and guarantees it has the required type.
+func (t *Tree) expect(expected itemType, context string) item {
+ token := t.nextNonSpace()
+ if token.typ != expected {
+ t.unexpected(token, context)
+ }
+ return token
+}
+
+// expectOneOf consumes the next token and guarantees it has one of the required types.
+func (t *Tree) expectOneOf(expected1, expected2 itemType, context string) item {
+ token := t.nextNonSpace()
+ if token.typ != expected1 && token.typ != expected2 {
+ t.unexpected(token, context)
+ }
+ return token
+}
+
+// unexpected complains about the token and terminates processing.
+func (t *Tree) unexpected(token item, context string) {
+ t.errorf("unexpected %s in %s", token, context)
+}
+
+// recover is the handler that turns panics into returns from the top level of Parse.
+func (t *Tree) recover(errp *error) {
+ e := recover()
+ if e != nil {
+ if _, ok := e.(runtime.Error); ok {
+ panic(e)
+ }
+ if t != nil {
+ t.stopParse()
+ }
+ *errp = e.(error)
+ }
+ return
+}
+
+// startParse initializes the parser, using the lexer.
+func (t *Tree) startParse(funcs []map[string]interface{}, lex *lexer) {
+ t.Root = nil
+ t.lex = lex
+ t.vars = []string{"$"}
+ t.funcs = funcs
+}
+
+// stopParse terminates parsing.
+func (t *Tree) stopParse() {
+ t.lex = nil
+ t.vars = nil
+ t.funcs = nil
+}
+
+// Parse parses the template definition string to construct a representation of
+// the template for execution. If either action delimiter string is empty, the
+// default ("{{" or "}}") is used. Embedded template definitions are added to
+// the treeSet map.
+func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error) {
+ defer t.recover(&err)
+ t.ParseName = t.Name
+ t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim))
+ t.text = text
+ t.parse(treeSet)
+ t.add(treeSet)
+ t.stopParse()
+ return t, nil
+}
+
+// add adds tree to the treeSet.
+func (t *Tree) add(treeSet map[string]*Tree) {
+ tree := treeSet[t.Name]
+ if tree == nil || IsEmptyTree(tree.Root) {
+ treeSet[t.Name] = t
+ return
+ }
+ if !IsEmptyTree(t.Root) {
+ t.errorf("template: multiple definition of template %q", t.Name)
+ }
+}
+
+// IsEmptyTree reports whether this tree (node) is empty of everything but space.
+func IsEmptyTree(n Node) bool {
+ switch n := n.(type) {
+ case nil:
+ return true
+ case *ActionNode:
+ case *IfNode:
+ case *ListNode:
+ for _, node := range n.Nodes {
+ if !IsEmptyTree(node) {
+ return false
+ }
+ }
+ return true
+ case *RangeNode:
+ case *TemplateNode:
+ case *TextNode:
+ return len(bytes.TrimSpace(n.Text)) == 0
+ case *WithNode:
+ default:
+ panic("unknown node: " + n.String())
+ }
+ return false
+}
+
+// parse is the top-level parser for a template, essentially the same
+// as itemList except it also parses {{define}} actions.
+// It runs to EOF.
+func (t *Tree) parse(treeSet map[string]*Tree) (next Node) {
+ t.Root = t.newList(t.peek().pos)
+ for t.peek().typ != itemEOF {
+ if t.peek().typ == itemLeftDelim {
+ delim := t.next()
+ if t.nextNonSpace().typ == itemDefine {
+ newT := New("definition") // name will be updated once we know it.
+ newT.text = t.text
+ newT.ParseName = t.ParseName
+ newT.startParse(t.funcs, t.lex)
+ newT.parseDefinition(treeSet)
+ continue
+ }
+ t.backup2(delim)
+ }
+ n := t.textOrAction()
+ if n.Type() == nodeEnd {
+ t.errorf("unexpected %s", n)
+ }
+ t.Root.append(n)
+ }
+ return nil
+}
+
+// parseDefinition parses a {{define}} ... {{end}} template definition and
+// installs the definition in the treeSet map. The "define" keyword has already
+// been scanned.
+func (t *Tree) parseDefinition(treeSet map[string]*Tree) {
+ const context = "define clause"
+ name := t.expectOneOf(itemString, itemRawString, context)
+ var err error
+ t.Name, err = strconv.Unquote(name.val)
+ if err != nil {
+ t.error(err)
+ }
+ t.expect(itemRightDelim, context)
+ var end Node
+ t.Root, end = t.itemList()
+ if end.Type() != nodeEnd {
+ t.errorf("unexpected %s in %s", end, context)
+ }
+ t.add(treeSet)
+ t.stopParse()
+}
+
+// itemList:
+// textOrAction*
+// Terminates at {{end}} or {{else}}, returned separately.
+func (t *Tree) itemList() (list *ListNode, next Node) {
+ list = t.newList(t.peekNonSpace().pos)
+ for t.peekNonSpace().typ != itemEOF {
+ n := t.textOrAction()
+ switch n.Type() {
+ case nodeEnd, nodeElse:
+ return list, n
+ }
+ list.append(n)
+ }
+ t.errorf("unexpected EOF")
+ return
+}
+
+// textOrAction:
+// text | action
+func (t *Tree) textOrAction() Node {
+ switch token := t.nextNonSpace(); token.typ {
+ case itemElideNewline:
+ return t.elideNewline()
+ case itemText:
+ return t.newText(token.pos, token.val)
+ case itemLeftDelim:
+ return t.action()
+ default:
+ t.unexpected(token, "input")
+ }
+ return nil
+}
+
+// elideNewline:
+// Remove newlines trailing rightDelim if \\ is present.
+func (t *Tree) elideNewline() Node {
+ token := t.peek()
+ if token.typ != itemText {
+ t.unexpected(token, "input")
+ return nil
+ }
+
+ t.next()
+ stripped := strings.TrimLeft(token.val, "\n\r")
+ diff := len(token.val) - len(stripped)
+ if diff > 0 {
+ // This is a bit nasty. We mutate the token in-place to remove
+ // preceding newlines.
+ token.pos += Pos(diff)
+ token.val = stripped
+ }
+ return t.newText(token.pos, token.val)
+}
+
+// Action:
+// control
+// command ("|" command)*
+// Left delim is past. Now get actions.
+// First word could be a keyword such as range.
+func (t *Tree) action() (n Node) {
+ switch token := t.nextNonSpace(); token.typ {
+ case itemElse:
+ return t.elseControl()
+ case itemEnd:
+ return t.endControl()
+ case itemIf:
+ return t.ifControl()
+ case itemRange:
+ return t.rangeControl()
+ case itemTemplate:
+ return t.templateControl()
+ case itemWith:
+ return t.withControl()
+ }
+ t.backup()
+ // Do not pop variables; they persist until "end".
+ return t.newAction(t.peek().pos, t.lex.lineNumber(), t.pipeline("command"))
+}
+
+// Pipeline:
+// declarations? command ('|' command)*
+func (t *Tree) pipeline(context string) (pipe *PipeNode) {
+ var decl []*VariableNode
+ pos := t.peekNonSpace().pos
+ // Are there declarations?
+ for {
+ if v := t.peekNonSpace(); v.typ == itemVariable {
+ t.next()
+ // Since space is a token, we need 3-token look-ahead here in the worst case:
+ // in "$x foo" we need to read "foo" (as opposed to ":=") to know that $x is an
+ // argument variable rather than a declaration. So remember the token
+ // adjacent to the variable so we can push it back if necessary.
+ tokenAfterVariable := t.peek()
+ if next := t.peekNonSpace(); next.typ == itemColonEquals || (next.typ == itemChar && next.val == ",") {
+ t.nextNonSpace()
+ variable := t.newVariable(v.pos, v.val)
+ decl = append(decl, variable)
+ t.vars = append(t.vars, v.val)
+ if next.typ == itemChar && next.val == "," {
+ if context == "range" && len(decl) < 2 {
+ continue
+ }
+ t.errorf("too many declarations in %s", context)
+ }
+ } else if tokenAfterVariable.typ == itemSpace {
+ t.backup3(v, tokenAfterVariable)
+ } else {
+ t.backup2(v)
+ }
+ }
+ break
+ }
+ pipe = t.newPipeline(pos, t.lex.lineNumber(), decl)
+ for {
+ switch token := t.nextNonSpace(); token.typ {
+ case itemRightDelim, itemRightParen:
+ if len(pipe.Cmds) == 0 {
+ t.errorf("missing value for %s", context)
+ }
+ if token.typ == itemRightParen {
+ t.backup()
+ }
+ return
+ case itemBool, itemCharConstant, itemComplex, itemDot, itemField, itemIdentifier,
+ itemNumber, itemNil, itemRawString, itemString, itemVariable, itemLeftParen:
+ t.backup()
+ pipe.append(t.command())
+ default:
+ t.unexpected(token, context)
+ }
+ }
+}
+
+func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) {
+ defer t.popVars(len(t.vars))
+ line = t.lex.lineNumber()
+ pipe = t.pipeline(context)
+ var next Node
+ list, next = t.itemList()
+ switch next.Type() {
+ case nodeEnd: //done
+ case nodeElse:
+ if allowElseIf {
+ // Special case for "else if". If the "else" is followed immediately by an "if",
+ // the elseControl will have left the "if" token pending. Treat
+ // {{if a}}_{{else if b}}_{{end}}
+ // as
+ // {{if a}}_{{else}}{{if b}}_{{end}}{{end}}.
+ // To do this, parse the if as usual and stop at it {{end}}; the subsequent{{end}}
+ // is assumed. This technique works even for long if-else-if chains.
+ // TODO: Should we allow else-if in with and range?
+ if t.peek().typ == itemIf {
+ t.next() // Consume the "if" token.
+ elseList = t.newList(next.Position())
+ elseList.append(t.ifControl())
+ // Do not consume the next item - only one {{end}} required.
+ break
+ }
+ }
+ elseList, next = t.itemList()
+ if next.Type() != nodeEnd {
+ t.errorf("expected end; found %s", next)
+ }
+ }
+ return pipe.Position(), line, pipe, list, elseList
+}
+
+// If:
+// {{if pipeline}} itemList {{end}}
+// {{if pipeline}} itemList {{else}} itemList {{end}}
+// If keyword is past.
+func (t *Tree) ifControl() Node {
+ return t.newIf(t.parseControl(true, "if"))
+}
+
+// Range:
+// {{range pipeline}} itemList {{end}}
+// {{range pipeline}} itemList {{else}} itemList {{end}}
+// Range keyword is past.
+func (t *Tree) rangeControl() Node {
+ return t.newRange(t.parseControl(false, "range"))
+}
+
+// With:
+// {{with pipeline}} itemList {{end}}
+// {{with pipeline}} itemList {{else}} itemList {{end}}
+// If keyword is past.
+func (t *Tree) withControl() Node {
+ return t.newWith(t.parseControl(false, "with"))
+}
+
+// End:
+// {{end}}
+// End keyword is past.
+func (t *Tree) endControl() Node {
+ return t.newEnd(t.expect(itemRightDelim, "end").pos)
+}
+
+// Else:
+// {{else}}
+// Else keyword is past.
+func (t *Tree) elseControl() Node {
+ // Special case for "else if".
+ peek := t.peekNonSpace()
+ if peek.typ == itemIf {
+ // We see "{{else if ... " but in effect rewrite it to {{else}}{{if ... ".
+ return t.newElse(peek.pos, t.lex.lineNumber())
+ }
+ return t.newElse(t.expect(itemRightDelim, "else").pos, t.lex.lineNumber())
+}
+
+// Template:
+// {{template stringValue pipeline}}
+// Template keyword is past. The name must be something that can evaluate
+// to a string.
+func (t *Tree) templateControl() Node {
+ var name string
+ token := t.nextNonSpace()
+ switch token.typ {
+ case itemString, itemRawString:
+ s, err := strconv.Unquote(token.val)
+ if err != nil {
+ t.error(err)
+ }
+ name = s
+ default:
+ t.unexpected(token, "template invocation")
+ }
+ var pipe *PipeNode
+ if t.nextNonSpace().typ != itemRightDelim {
+ t.backup()
+ // Do not pop variables; they persist until "end".
+ pipe = t.pipeline("template")
+ }
+ return t.newTemplate(token.pos, t.lex.lineNumber(), name, pipe)
+}
+
+// command:
+// operand (space operand)*
+// space-separated arguments up to a pipeline character or right delimiter.
+// we consume the pipe character but leave the right delim to terminate the action.
+func (t *Tree) command() *CommandNode {
+ cmd := t.newCommand(t.peekNonSpace().pos)
+ for {
+ t.peekNonSpace() // skip leading spaces.
+ operand := t.operand()
+ if operand != nil {
+ cmd.append(operand)
+ }
+ switch token := t.next(); token.typ {
+ case itemSpace:
+ continue
+ case itemError:
+ t.errorf("%s", token.val)
+ case itemRightDelim, itemRightParen:
+ t.backup()
+ case itemPipe:
+ default:
+ t.errorf("unexpected %s in operand; missing space?", token)
+ }
+ break
+ }
+ if len(cmd.Args) == 0 {
+ t.errorf("empty command")
+ }
+ return cmd
+}
+
+// operand:
+// term .Field*
+// An operand is a space-separated component of a command,
+// a term possibly followed by field accesses.
+// A nil return means the next item is not an operand.
+func (t *Tree) operand() Node {
+ node := t.term()
+ if node == nil {
+ return nil
+ }
+ if t.peek().typ == itemField {
+ chain := t.newChain(t.peek().pos, node)
+ for t.peek().typ == itemField {
+ chain.Add(t.next().val)
+ }
+ // Compatibility with original API: If the term is of type NodeField
+ // or NodeVariable, just put more fields on the original.
+ // Otherwise, keep the Chain node.
+ // TODO: Switch to Chains always when we can.
+ switch node.Type() {
+ case NodeField:
+ node = t.newField(chain.Position(), chain.String())
+ case NodeVariable:
+ node = t.newVariable(chain.Position(), chain.String())
+ default:
+ node = chain
+ }
+ }
+ return node
+}
+
+// term:
+// literal (number, string, nil, boolean)
+// function (identifier)
+// .
+// .Field
+// $
+// '(' pipeline ')'
+// A term is a simple "expression".
+// A nil return means the next item is not a term.
+func (t *Tree) term() Node {
+ switch token := t.nextNonSpace(); token.typ {
+ case itemError:
+ t.errorf("%s", token.val)
+ case itemIdentifier:
+ if !t.hasFunction(token.val) {
+ t.errorf("function %q not defined", token.val)
+ }
+ return NewIdentifier(token.val).SetTree(t).SetPos(token.pos)
+ case itemDot:
+ return t.newDot(token.pos)
+ case itemNil:
+ return t.newNil(token.pos)
+ case itemVariable:
+ return t.useVar(token.pos, token.val)
+ case itemField:
+ return t.newField(token.pos, token.val)
+ case itemBool:
+ return t.newBool(token.pos, token.val == "true")
+ case itemCharConstant, itemComplex, itemNumber:
+ number, err := t.newNumber(token.pos, token.val, token.typ)
+ if err != nil {
+ t.error(err)
+ }
+ return number
+ case itemLeftParen:
+ pipe := t.pipeline("parenthesized pipeline")
+ if token := t.next(); token.typ != itemRightParen {
+ t.errorf("unclosed right paren: unexpected %s", token)
+ }
+ return pipe
+ case itemString, itemRawString:
+ s, err := strconv.Unquote(token.val)
+ if err != nil {
+ t.error(err)
+ }
+ return t.newString(token.pos, token.val, s)
+ }
+ t.backup()
+ return nil
+}
+
+// hasFunction reports if a function name exists in the Tree's maps.
+func (t *Tree) hasFunction(name string) bool {
+ for _, funcMap := range t.funcs {
+ if funcMap == nil {
+ continue
+ }
+ if funcMap[name] != nil {
+ return true
+ }
+ }
+ return false
+}
+
+// popVars trims the variable list to the specified length
+func (t *Tree) popVars(n int) {
+ t.vars = t.vars[:n]
+}
+
+// useVar returns a node for a variable reference. It errors if the
+// variable is not defined.
+func (t *Tree) useVar(pos Pos, name string) Node {
+ v := t.newVariable(pos, name)
+ for _, varName := range t.vars {
+ if varName == v.Ident[0] {
+ return v
+ }
+ }
+ t.errorf("undefined variable %q", v.Ident[0])
+ return nil
+}
--- /dev/null
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package template
+
+import (
+ "fmt"
+ "reflect"
+
+ "github.com/alecthomas/template/parse"
+)
+
+// common holds the information shared by related templates.
+type common struct {
+ tmpl map[string]*Template
+ // We use two maps, one for parsing and one for execution.
+ // This separation makes the API cleaner since it doesn't
+ // expose reflection to the client.
+ parseFuncs FuncMap
+ execFuncs map[string]reflect.Value
+}
+
+// Template is the representation of a parsed template. The *parse.Tree
+// field is exported only for use by html/template and should be treated
+// as unexported by all other clients.
+type Template struct {
+ name string
+ *parse.Tree
+ *common
+ leftDelim string
+ rightDelim string
+}
+
+// New allocates a new template with the given name.
+func New(name string) *Template {
+ return &Template{
+ name: name,
+ }
+}
+
+// Name returns the name of the template.
+func (t *Template) Name() string {
+ return t.name
+}
+
+// New allocates a new template associated with the given one and with the same
+// delimiters. The association, which is transitive, allows one template to
+// invoke another with a {{template}} action.
+func (t *Template) New(name string) *Template {
+ t.init()
+ return &Template{
+ name: name,
+ common: t.common,
+ leftDelim: t.leftDelim,
+ rightDelim: t.rightDelim,
+ }
+}
+
+func (t *Template) init() {
+ if t.common == nil {
+ t.common = new(common)
+ t.tmpl = make(map[string]*Template)
+ t.parseFuncs = make(FuncMap)
+ t.execFuncs = make(map[string]reflect.Value)
+ }
+}
+
+// Clone returns a duplicate of the template, including all associated
+// templates. The actual representation is not copied, but the name space of
+// associated templates is, so further calls to Parse in the copy will add
+// templates to the copy but not to the original. Clone can be used to prepare
+// common templates and use them with variant definitions for other templates
+// by adding the variants after the clone is made.
+func (t *Template) Clone() (*Template, error) {
+ nt := t.copy(nil)
+ nt.init()
+ nt.tmpl[t.name] = nt
+ for k, v := range t.tmpl {
+ if k == t.name { // Already installed.
+ continue
+ }
+ // The associated templates share nt's common structure.
+ tmpl := v.copy(nt.common)
+ nt.tmpl[k] = tmpl
+ }
+ for k, v := range t.parseFuncs {
+ nt.parseFuncs[k] = v
+ }
+ for k, v := range t.execFuncs {
+ nt.execFuncs[k] = v
+ }
+ return nt, nil
+}
+
+// copy returns a shallow copy of t, with common set to the argument.
+func (t *Template) copy(c *common) *Template {
+ nt := New(t.name)
+ nt.Tree = t.Tree
+ nt.common = c
+ nt.leftDelim = t.leftDelim
+ nt.rightDelim = t.rightDelim
+ return nt
+}
+
+// AddParseTree creates a new template with the name and parse tree
+// and associates it with t.
+func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) {
+ if t.common != nil && t.tmpl[name] != nil {
+ return nil, fmt.Errorf("template: redefinition of template %q", name)
+ }
+ nt := t.New(name)
+ nt.Tree = tree
+ t.tmpl[name] = nt
+ return nt, nil
+}
+
+// Templates returns a slice of the templates associated with t, including t
+// itself.
+func (t *Template) Templates() []*Template {
+ if t.common == nil {
+ return nil
+ }
+ // Return a slice so we don't expose the map.
+ m := make([]*Template, 0, len(t.tmpl))
+ for _, v := range t.tmpl {
+ m = append(m, v)
+ }
+ return m
+}
+
+// Delims sets the action delimiters to the specified strings, to be used in
+// subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template
+// definitions will inherit the settings. An empty delimiter stands for the
+// corresponding default: {{ or }}.
+// The return value is the template, so calls can be chained.
+func (t *Template) Delims(left, right string) *Template {
+ t.leftDelim = left
+ t.rightDelim = right
+ return t
+}
+
+// Funcs adds the elements of the argument map to the template's function map.
+// It panics if a value in the map is not a function with appropriate return
+// type. However, it is legal to overwrite elements of the map. The return
+// value is the template, so calls can be chained.
+func (t *Template) Funcs(funcMap FuncMap) *Template {
+ t.init()
+ addValueFuncs(t.execFuncs, funcMap)
+ addFuncs(t.parseFuncs, funcMap)
+ return t
+}
+
+// Lookup returns the template with the given name that is associated with t,
+// or nil if there is no such template.
+func (t *Template) Lookup(name string) *Template {
+ if t.common == nil {
+ return nil
+ }
+ return t.tmpl[name]
+}
+
+// Parse parses a string into a template. Nested template definitions will be
+// associated with the top-level template t. Parse may be called multiple times
+// to parse definitions of templates to associate with t. It is an error if a
+// resulting template is non-empty (contains content other than template
+// definitions) and would replace a non-empty template with the same name.
+// (In multiple calls to Parse with the same receiver template, only one call
+// can contain text other than space, comments, and template definitions.)
+func (t *Template) Parse(text string) (*Template, error) {
+ t.init()
+ trees, err := parse.Parse(t.name, text, t.leftDelim, t.rightDelim, t.parseFuncs, builtins)
+ if err != nil {
+ return nil, err
+ }
+ // Add the newly parsed trees, including the one for t, into our common structure.
+ for name, tree := range trees {
+ // If the name we parsed is the name of this template, overwrite this template.
+ // The associate method checks it's not a redefinition.
+ tmpl := t
+ if name != t.name {
+ tmpl = t.New(name)
+ }
+ // Even if t == tmpl, we need to install it in the common.tmpl map.
+ if replace, err := t.associate(tmpl, tree); err != nil {
+ return nil, err
+ } else if replace {
+ tmpl.Tree = tree
+ }
+ tmpl.leftDelim = t.leftDelim
+ tmpl.rightDelim = t.rightDelim
+ }
+ return t, nil
+}
+
+// associate installs the new template into the group of templates associated
+// with t. It is an error to reuse a name except to overwrite an empty
+// template. The two are already known to share the common structure.
+// The boolean return value reports wither to store this tree as t.Tree.
+func (t *Template) associate(new *Template, tree *parse.Tree) (bool, error) {
+ if new.common != t.common {
+ panic("internal error: associate not common")
+ }
+ name := new.name
+ if old := t.tmpl[name]; old != nil {
+ oldIsEmpty := parse.IsEmptyTree(old.Root)
+ newIsEmpty := parse.IsEmptyTree(tree.Root)
+ if newIsEmpty {
+ // Whether old is empty or not, new is empty; no reason to replace old.
+ return false, nil
+ }
+ if !oldIsEmpty {
+ return false, fmt.Errorf("template: redefinition of template %q", name)
+ }
+ }
+ t.tmpl[name] = new
+ return true, nil
+}
--- /dev/null
+Copyright (C) 2014 Alec Thomas
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
--- /dev/null
+# Units - Helpful unit multipliers and functions for Go
+
+The goal of this package is to have functionality similar to the [time](http://golang.org/pkg/time/) package.
+
+It allows for code like this:
+
+```go
+n, err := ParseBase2Bytes("1KB")
+// n == 1024
+n = units.Mebibyte * 512
+```
--- /dev/null
+package units
+
+// Base2Bytes is the old non-SI power-of-2 byte scale (1024 bytes in a kilobyte,
+// etc.).
+type Base2Bytes int64
+
+// Base-2 byte units.
+const (
+ Kibibyte Base2Bytes = 1024
+ KiB = Kibibyte
+ Mebibyte = Kibibyte * 1024
+ MiB = Mebibyte
+ Gibibyte = Mebibyte * 1024
+ GiB = Gibibyte
+ Tebibyte = Gibibyte * 1024
+ TiB = Tebibyte
+ Pebibyte = Tebibyte * 1024
+ PiB = Pebibyte
+ Exbibyte = Pebibyte * 1024
+ EiB = Exbibyte
+)
+
+var (
+ bytesUnitMap = MakeUnitMap("iB", "B", 1024)
+ oldBytesUnitMap = MakeUnitMap("B", "B", 1024)
+)
+
+// ParseBase2Bytes supports both iB and B in base-2 multipliers. That is, KB
+// and KiB are both 1024.
+func ParseBase2Bytes(s string) (Base2Bytes, error) {
+ n, err := ParseUnit(s, bytesUnitMap)
+ if err != nil {
+ n, err = ParseUnit(s, oldBytesUnitMap)
+ }
+ return Base2Bytes(n), err
+}
+
+func (b Base2Bytes) String() string {
+ return ToString(int64(b), 1024, "iB", "B")
+}
+
+var (
+ metricBytesUnitMap = MakeUnitMap("B", "B", 1000)
+)
+
+// MetricBytes are SI byte units (1000 bytes in a kilobyte).
+type MetricBytes SI
+
+// SI base-10 byte units.
+const (
+ Kilobyte MetricBytes = 1000
+ KB = Kilobyte
+ Megabyte = Kilobyte * 1000
+ MB = Megabyte
+ Gigabyte = Megabyte * 1000
+ GB = Gigabyte
+ Terabyte = Gigabyte * 1000
+ TB = Terabyte
+ Petabyte = Terabyte * 1000
+ PB = Petabyte
+ Exabyte = Petabyte * 1000
+ EB = Exabyte
+)
+
+// ParseMetricBytes parses base-10 metric byte units. That is, KB is 1000 bytes.
+func ParseMetricBytes(s string) (MetricBytes, error) {
+ n, err := ParseUnit(s, metricBytesUnitMap)
+ return MetricBytes(n), err
+}
+
+func (m MetricBytes) String() string {
+ return ToString(int64(m), 1000, "B", "B")
+}
+
+// ParseStrictBytes supports both iB and B suffixes for base 2 and metric,
+// respectively. That is, KiB represents 1024 and KB represents 1000.
+func ParseStrictBytes(s string) (int64, error) {
+ n, err := ParseUnit(s, bytesUnitMap)
+ if err != nil {
+ n, err = ParseUnit(s, metricBytesUnitMap)
+ }
+ return int64(n), err
+}
--- /dev/null
+// Package units provides helpful unit multipliers and functions for Go.
+//
+// The goal of this package is to have functionality similar to the time [1] package.
+//
+//
+// [1] http://golang.org/pkg/time/
+//
+// It allows for code like this:
+//
+// n, err := ParseBase2Bytes("1KB")
+// // n == 1024
+// n = units.Mebibyte * 512
+package units
--- /dev/null
+package units
+
+// SI units.
+type SI int64
+
+// SI unit multiples.
+const (
+ Kilo SI = 1000
+ Mega = Kilo * 1000
+ Giga = Mega * 1000
+ Tera = Giga * 1000
+ Peta = Tera * 1000
+ Exa = Peta * 1000
+)
+
+func MakeUnitMap(suffix, shortSuffix string, scale int64) map[string]float64 {
+ return map[string]float64{
+ shortSuffix: 1,
+ "K" + suffix: float64(scale),
+ "M" + suffix: float64(scale * scale),
+ "G" + suffix: float64(scale * scale * scale),
+ "T" + suffix: float64(scale * scale * scale * scale),
+ "P" + suffix: float64(scale * scale * scale * scale * scale),
+ "E" + suffix: float64(scale * scale * scale * scale * scale * scale),
+ }
+}
--- /dev/null
+package units
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+)
+
+var (
+ siUnits = []string{"", "K", "M", "G", "T", "P", "E"}
+)
+
+func ToString(n int64, scale int64, suffix, baseSuffix string) string {
+ mn := len(siUnits)
+ out := make([]string, mn)
+ for i, m := range siUnits {
+ if n%scale != 0 || i == 0 && n == 0 {
+ s := suffix
+ if i == 0 {
+ s = baseSuffix
+ }
+ out[mn-1-i] = fmt.Sprintf("%d%s%s", n%scale, m, s)
+ }
+ n /= scale
+ if n == 0 {
+ break
+ }
+ }
+ return strings.Join(out, "")
+}
+
+// Below code ripped straight from http://golang.org/src/pkg/time/format.go?s=33392:33438#L1123
+var errLeadingInt = errors.New("units: bad [0-9]*") // never printed
+
+// leadingInt consumes the leading [0-9]* from s.
+func leadingInt(s string) (x int64, rem string, err error) {
+ i := 0
+ for ; i < len(s); i++ {
+ c := s[i]
+ if c < '0' || c > '9' {
+ break
+ }
+ if x >= (1<<63-10)/10 {
+ // overflow
+ return 0, "", errLeadingInt
+ }
+ x = x*10 + int64(c) - '0'
+ }
+ return x, s[i:], nil
+}
+
+func ParseUnit(s string, unitMap map[string]float64) (int64, error) {
+ // [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+
+ orig := s
+ f := float64(0)
+ neg := false
+
+ // Consume [-+]?
+ if s != "" {
+ c := s[0]
+ if c == '-' || c == '+' {
+ neg = c == '-'
+ s = s[1:]
+ }
+ }
+ // Special case: if all that is left is "0", this is zero.
+ if s == "0" {
+ return 0, nil
+ }
+ if s == "" {
+ return 0, errors.New("units: invalid " + orig)
+ }
+ for s != "" {
+ g := float64(0) // this element of the sequence
+
+ var x int64
+ var err error
+
+ // The next character must be [0-9.]
+ if !(s[0] == '.' || ('0' <= s[0] && s[0] <= '9')) {
+ return 0, errors.New("units: invalid " + orig)
+ }
+ // Consume [0-9]*
+ pl := len(s)
+ x, s, err = leadingInt(s)
+ if err != nil {
+ return 0, errors.New("units: invalid " + orig)
+ }
+ g = float64(x)
+ pre := pl != len(s) // whether we consumed anything before a period
+
+ // Consume (\.[0-9]*)?
+ post := false
+ if s != "" && s[0] == '.' {
+ s = s[1:]
+ pl := len(s)
+ x, s, err = leadingInt(s)
+ if err != nil {
+ return 0, errors.New("units: invalid " + orig)
+ }
+ scale := 1.0
+ for n := pl - len(s); n > 0; n-- {
+ scale *= 10
+ }
+ g += float64(x) / scale
+ post = pl != len(s)
+ }
+ if !pre && !post {
+ // no digits (e.g. ".s" or "-.s")
+ return 0, errors.New("units: invalid " + orig)
+ }
+
+ // Consume unit.
+ i := 0
+ for ; i < len(s); i++ {
+ c := s[i]
+ if c == '.' || ('0' <= c && c <= '9') {
+ break
+ }
+ }
+ u := s[:i]
+ s = s[i:]
+ unit, ok := unitMap[u]
+ if !ok {
+ return 0, errors.New("units: unknown unit " + u + " in " + orig)
+ }
+
+ f += g * unit
+ }
+
+ if neg {
+ f = -f
+ }
+ if f < float64(-1<<63) || f > float64(1<<63-1) {
+ return 0, errors.New("units: overflow parsing unit")
+ }
+ return int64(f), nil
+}
--- /dev/null
+The MIT License (MIT)
+
+Copyright (c) 2013 Armon Dadgar
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--- /dev/null
+go-metrics
+==========
+
+This library provides a `metrics` package which can be used to instrument code,
+expose application metrics, and profile runtime performance in a flexible manner.
+
+Current API: [](https://godoc.org/github.com/armon/go-metrics)
+
+Sinks
+=====
+
+The `metrics` package makes use of a `MetricSink` interface to support delivery
+to any type of backend. Currently the following sinks are provided:
+
+* StatsiteSink : Sinks to a [statsite](https://github.com/armon/statsite/) instance (TCP)
+* StatsdSink: Sinks to a [StatsD](https://github.com/etsy/statsd/) / statsite instance (UDP)
+* PrometheusSink: Sinks to a [Prometheus](http://prometheus.io/) metrics endpoint (exposed via HTTP for scrapes)
+* InmemSink : Provides in-memory aggregation, can be used to export stats
+* FanoutSink : Sinks to multiple sinks. Enables writing to multiple statsite instances for example.
+* BlackholeSink : Sinks to nowhere
+
+In addition to the sinks, the `InmemSignal` can be used to catch a signal,
+and dump a formatted output of recent metrics. For example, when a process gets
+a SIGUSR1, it can dump to stderr recent performance metrics for debugging.
+
+Examples
+========
+
+Here is an example of using the package:
+
+```go
+func SlowMethod() {
+ // Profiling the runtime of a method
+ defer metrics.MeasureSince([]string{"SlowMethod"}, time.Now())
+}
+
+// Configure a statsite sink as the global metrics sink
+sink, _ := metrics.NewStatsiteSink("statsite:8125")
+metrics.NewGlobal(metrics.DefaultConfig("service-name"), sink)
+
+// Emit a Key/Value pair
+metrics.EmitKey([]string{"questions", "meaning of life"}, 42)
+```
+
+Here is an example of setting up a signal handler:
+
+```go
+// Setup the inmem sink and signal handler
+inm := metrics.NewInmemSink(10*time.Second, time.Minute)
+sig := metrics.DefaultInmemSignal(inm)
+metrics.NewGlobal(metrics.DefaultConfig("service-name"), inm)
+
+// Run some code
+inm.SetGauge([]string{"foo"}, 42)
+inm.EmitKey([]string{"bar"}, 30)
+
+inm.IncrCounter([]string{"baz"}, 42)
+inm.IncrCounter([]string{"baz"}, 1)
+inm.IncrCounter([]string{"baz"}, 80)
+
+inm.AddSample([]string{"method", "wow"}, 42)
+inm.AddSample([]string{"method", "wow"}, 100)
+inm.AddSample([]string{"method", "wow"}, 22)
+
+....
+```
+
+When a signal comes in, output like the following will be dumped to stderr:
+
+ [2014-01-28 14:57:33.04 -0800 PST][G] 'foo': 42.000
+ [2014-01-28 14:57:33.04 -0800 PST][P] 'bar': 30.000
+ [2014-01-28 14:57:33.04 -0800 PST][C] 'baz': Count: 3 Min: 1.000 Mean: 41.000 Max: 80.000 Stddev: 39.509
+ [2014-01-28 14:57:33.04 -0800 PST][S] 'method.wow': Count: 3 Min: 22.000 Mean: 54.667 Max: 100.000 Stddev: 40.513
+
--- /dev/null
+// +build !windows
+
+package metrics
+
+import (
+ "syscall"
+)
+
+const (
+ // DefaultSignal is used with DefaultInmemSignal
+ DefaultSignal = syscall.SIGUSR1
+)
--- /dev/null
+// +build windows
+
+package metrics
+
+import (
+ "syscall"
+)
+
+const (
+ // DefaultSignal is used with DefaultInmemSignal
+ // Windows has no SIGUSR1, use SIGBREAK
+ DefaultSignal = syscall.Signal(21)
+)
--- /dev/null
+package metrics
+
+import (
+ "bytes"
+ "fmt"
+ "math"
+ "net/url"
+ "strings"
+ "sync"
+ "time"
+)
+
+// InmemSink provides a MetricSink that does in-memory aggregation
+// without sending metrics over a network. It can be embedded within
+// an application to provide profiling information.
+type InmemSink struct {
+ // How long is each aggregation interval
+ interval time.Duration
+
+ // Retain controls how many metrics interval we keep
+ retain time.Duration
+
+ // maxIntervals is the maximum length of intervals.
+ // It is retain / interval.
+ maxIntervals int
+
+ // intervals is a slice of the retained intervals
+ intervals []*IntervalMetrics
+ intervalLock sync.RWMutex
+
+ rateDenom float64
+}
+
+// IntervalMetrics stores the aggregated metrics
+// for a specific interval
+type IntervalMetrics struct {
+ sync.RWMutex
+
+ // The start time of the interval
+ Interval time.Time
+
+ // Gauges maps the key to the last set value
+ Gauges map[string]GaugeValue
+
+ // Points maps the string to the list of emitted values
+ // from EmitKey
+ Points map[string][]float32
+
+ // Counters maps the string key to a sum of the counter
+ // values
+ Counters map[string]SampledValue
+
+ // Samples maps the key to an AggregateSample,
+ // which has the rolled up view of a sample
+ Samples map[string]SampledValue
+}
+
+// NewIntervalMetrics creates a new IntervalMetrics for a given interval
+func NewIntervalMetrics(intv time.Time) *IntervalMetrics {
+ return &IntervalMetrics{
+ Interval: intv,
+ Gauges: make(map[string]GaugeValue),
+ Points: make(map[string][]float32),
+ Counters: make(map[string]SampledValue),
+ Samples: make(map[string]SampledValue),
+ }
+}
+
+// AggregateSample is used to hold aggregate metrics
+// about a sample
+type AggregateSample struct {
+ Count int // The count of emitted pairs
+ Rate float64 // The values rate per time unit (usually 1 second)
+ Sum float64 // The sum of values
+ SumSq float64 `json:"-"` // The sum of squared values
+ Min float64 // Minimum value
+ Max float64 // Maximum value
+ LastUpdated time.Time `json:"-"` // When value was last updated
+}
+
+// Computes a Stddev of the values
+func (a *AggregateSample) Stddev() float64 {
+ num := (float64(a.Count) * a.SumSq) - math.Pow(a.Sum, 2)
+ div := float64(a.Count * (a.Count - 1))
+ if div == 0 {
+ return 0
+ }
+ return math.Sqrt(num / div)
+}
+
+// Computes a mean of the values
+func (a *AggregateSample) Mean() float64 {
+ if a.Count == 0 {
+ return 0
+ }
+ return a.Sum / float64(a.Count)
+}
+
+// Ingest is used to update a sample
+func (a *AggregateSample) Ingest(v float64, rateDenom float64) {
+ a.Count++
+ a.Sum += v
+ a.SumSq += (v * v)
+ if v < a.Min || a.Count == 1 {
+ a.Min = v
+ }
+ if v > a.Max || a.Count == 1 {
+ a.Max = v
+ }
+ a.Rate = float64(a.Sum) / rateDenom
+ a.LastUpdated = time.Now()
+}
+
+func (a *AggregateSample) String() string {
+ if a.Count == 0 {
+ return "Count: 0"
+ } else if a.Stddev() == 0 {
+ return fmt.Sprintf("Count: %d Sum: %0.3f LastUpdated: %s", a.Count, a.Sum, a.LastUpdated)
+ } else {
+ return fmt.Sprintf("Count: %d Min: %0.3f Mean: %0.3f Max: %0.3f Stddev: %0.3f Sum: %0.3f LastUpdated: %s",
+ a.Count, a.Min, a.Mean(), a.Max, a.Stddev(), a.Sum, a.LastUpdated)
+ }
+}
+
+// NewInmemSinkFromURL creates an InmemSink from a URL. It is used
+// (and tested) from NewMetricSinkFromURL.
+func NewInmemSinkFromURL(u *url.URL) (MetricSink, error) {
+ params := u.Query()
+
+ interval, err := time.ParseDuration(params.Get("interval"))
+ if err != nil {
+ return nil, fmt.Errorf("Bad 'interval' param: %s", err)
+ }
+
+ retain, err := time.ParseDuration(params.Get("retain"))
+ if err != nil {
+ return nil, fmt.Errorf("Bad 'retain' param: %s", err)
+ }
+
+ return NewInmemSink(interval, retain), nil
+}
+
+// NewInmemSink is used to construct a new in-memory sink.
+// Uses an aggregation interval and maximum retention period.
+func NewInmemSink(interval, retain time.Duration) *InmemSink {
+ rateTimeUnit := time.Second
+ i := &InmemSink{
+ interval: interval,
+ retain: retain,
+ maxIntervals: int(retain / interval),
+ rateDenom: float64(interval.Nanoseconds()) / float64(rateTimeUnit.Nanoseconds()),
+ }
+ i.intervals = make([]*IntervalMetrics, 0, i.maxIntervals)
+ return i
+}
+
+func (i *InmemSink) SetGauge(key []string, val float32) {
+ i.SetGaugeWithLabels(key, val, nil)
+}
+
+func (i *InmemSink) SetGaugeWithLabels(key []string, val float32, labels []Label) {
+ k, name := i.flattenKeyLabels(key, labels)
+ intv := i.getInterval()
+
+ intv.Lock()
+ defer intv.Unlock()
+ intv.Gauges[k] = GaugeValue{Name: name, Value: val, Labels: labels}
+}
+
+func (i *InmemSink) EmitKey(key []string, val float32) {
+ k := i.flattenKey(key)
+ intv := i.getInterval()
+
+ intv.Lock()
+ defer intv.Unlock()
+ vals := intv.Points[k]
+ intv.Points[k] = append(vals, val)
+}
+
+func (i *InmemSink) IncrCounter(key []string, val float32) {
+ i.IncrCounterWithLabels(key, val, nil)
+}
+
+func (i *InmemSink) IncrCounterWithLabels(key []string, val float32, labels []Label) {
+ k, name := i.flattenKeyLabels(key, labels)
+ intv := i.getInterval()
+
+ intv.Lock()
+ defer intv.Unlock()
+
+ agg, ok := intv.Counters[k]
+ if !ok {
+ agg = SampledValue{
+ Name: name,
+ AggregateSample: &AggregateSample{},
+ Labels: labels,
+ }
+ intv.Counters[k] = agg
+ }
+ agg.Ingest(float64(val), i.rateDenom)
+}
+
+func (i *InmemSink) AddSample(key []string, val float32) {
+ i.AddSampleWithLabels(key, val, nil)
+}
+
+func (i *InmemSink) AddSampleWithLabels(key []string, val float32, labels []Label) {
+ k, name := i.flattenKeyLabels(key, labels)
+ intv := i.getInterval()
+
+ intv.Lock()
+ defer intv.Unlock()
+
+ agg, ok := intv.Samples[k]
+ if !ok {
+ agg = SampledValue{
+ Name: name,
+ AggregateSample: &AggregateSample{},
+ Labels: labels,
+ }
+ intv.Samples[k] = agg
+ }
+ agg.Ingest(float64(val), i.rateDenom)
+}
+
+// Data is used to retrieve all the aggregated metrics
+// Intervals may be in use, and a read lock should be acquired
+func (i *InmemSink) Data() []*IntervalMetrics {
+ // Get the current interval, forces creation
+ i.getInterval()
+
+ i.intervalLock.RLock()
+ defer i.intervalLock.RUnlock()
+
+ intervals := make([]*IntervalMetrics, len(i.intervals))
+ copy(intervals, i.intervals)
+ return intervals
+}
+
+func (i *InmemSink) getExistingInterval(intv time.Time) *IntervalMetrics {
+ i.intervalLock.RLock()
+ defer i.intervalLock.RUnlock()
+
+ n := len(i.intervals)
+ if n > 0 && i.intervals[n-1].Interval == intv {
+ return i.intervals[n-1]
+ }
+ return nil
+}
+
+func (i *InmemSink) createInterval(intv time.Time) *IntervalMetrics {
+ i.intervalLock.Lock()
+ defer i.intervalLock.Unlock()
+
+ // Check for an existing interval
+ n := len(i.intervals)
+ if n > 0 && i.intervals[n-1].Interval == intv {
+ return i.intervals[n-1]
+ }
+
+ // Add the current interval
+ current := NewIntervalMetrics(intv)
+ i.intervals = append(i.intervals, current)
+ n++
+
+ // Truncate the intervals if they are too long
+ if n >= i.maxIntervals {
+ copy(i.intervals[0:], i.intervals[n-i.maxIntervals:])
+ i.intervals = i.intervals[:i.maxIntervals]
+ }
+ return current
+}
+
+// getInterval returns the current interval to write to
+func (i *InmemSink) getInterval() *IntervalMetrics {
+ intv := time.Now().Truncate(i.interval)
+ if m := i.getExistingInterval(intv); m != nil {
+ return m
+ }
+ return i.createInterval(intv)
+}
+
+// Flattens the key for formatting, removes spaces
+func (i *InmemSink) flattenKey(parts []string) string {
+ buf := &bytes.Buffer{}
+ replacer := strings.NewReplacer(" ", "_")
+
+ if len(parts) > 0 {
+ replacer.WriteString(buf, parts[0])
+ }
+ for _, part := range parts[1:] {
+ replacer.WriteString(buf, ".")
+ replacer.WriteString(buf, part)
+ }
+
+ return buf.String()
+}
+
+// Flattens the key for formatting along with its labels, removes spaces
+func (i *InmemSink) flattenKeyLabels(parts []string, labels []Label) (string, string) {
+ buf := &bytes.Buffer{}
+ replacer := strings.NewReplacer(" ", "_")
+
+ if len(parts) > 0 {
+ replacer.WriteString(buf, parts[0])
+ }
+ for _, part := range parts[1:] {
+ replacer.WriteString(buf, ".")
+ replacer.WriteString(buf, part)
+ }
+
+ key := buf.String()
+
+ for _, label := range labels {
+ replacer.WriteString(buf, fmt.Sprintf(";%s=%s", label.Name, label.Value))
+ }
+
+ return buf.String(), key
+}
--- /dev/null
+package metrics
+
+import (
+ "fmt"
+ "net/http"
+ "sort"
+ "time"
+)
+
+// MetricsSummary holds a roll-up of metrics info for a given interval
+type MetricsSummary struct {
+ Timestamp string
+ Gauges []GaugeValue
+ Points []PointValue
+ Counters []SampledValue
+ Samples []SampledValue
+}
+
+type GaugeValue struct {
+ Name string
+ Hash string `json:"-"`
+ Value float32
+
+ Labels []Label `json:"-"`
+ DisplayLabels map[string]string `json:"Labels"`
+}
+
+type PointValue struct {
+ Name string
+ Points []float32
+}
+
+type SampledValue struct {
+ Name string
+ Hash string `json:"-"`
+ *AggregateSample
+ Mean float64
+ Stddev float64
+
+ Labels []Label `json:"-"`
+ DisplayLabels map[string]string `json:"Labels"`
+}
+
+// DisplayMetrics returns a summary of the metrics from the most recent finished interval.
+func (i *InmemSink) DisplayMetrics(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
+ data := i.Data()
+
+ var interval *IntervalMetrics
+ n := len(data)
+ switch {
+ case n == 0:
+ return nil, fmt.Errorf("no metric intervals have been initialized yet")
+ case n == 1:
+ // Show the current interval if it's all we have
+ interval = i.intervals[0]
+ default:
+ // Show the most recent finished interval if we have one
+ interval = i.intervals[n-2]
+ }
+
+ summary := MetricsSummary{
+ Timestamp: interval.Interval.Round(time.Second).UTC().String(),
+ Gauges: make([]GaugeValue, 0, len(interval.Gauges)),
+ Points: make([]PointValue, 0, len(interval.Points)),
+ }
+
+ // Format and sort the output of each metric type, so it gets displayed in a
+ // deterministic order.
+ for name, points := range interval.Points {
+ summary.Points = append(summary.Points, PointValue{name, points})
+ }
+ sort.Slice(summary.Points, func(i, j int) bool {
+ return summary.Points[i].Name < summary.Points[j].Name
+ })
+
+ for hash, value := range interval.Gauges {
+ value.Hash = hash
+ value.DisplayLabels = make(map[string]string)
+ for _, label := range value.Labels {
+ value.DisplayLabels[label.Name] = label.Value
+ }
+ value.Labels = nil
+
+ summary.Gauges = append(summary.Gauges, value)
+ }
+ sort.Slice(summary.Gauges, func(i, j int) bool {
+ return summary.Gauges[i].Hash < summary.Gauges[j].Hash
+ })
+
+ summary.Counters = formatSamples(interval.Counters)
+ summary.Samples = formatSamples(interval.Samples)
+
+ return summary, nil
+}
+
+func formatSamples(source map[string]SampledValue) []SampledValue {
+ output := make([]SampledValue, 0, len(source))
+ for hash, sample := range source {
+ displayLabels := make(map[string]string)
+ for _, label := range sample.Labels {
+ displayLabels[label.Name] = label.Value
+ }
+
+ output = append(output, SampledValue{
+ Name: sample.Name,
+ Hash: hash,
+ AggregateSample: sample.AggregateSample,
+ Mean: sample.AggregateSample.Mean(),
+ Stddev: sample.AggregateSample.Stddev(),
+ DisplayLabels: displayLabels,
+ })
+ }
+ sort.Slice(output, func(i, j int) bool {
+ return output[i].Hash < output[j].Hash
+ })
+
+ return output
+}
--- /dev/null
+package metrics
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "os"
+ "os/signal"
+ "strings"
+ "sync"
+ "syscall"
+)
+
+// InmemSignal is used to listen for a given signal, and when received,
+// to dump the current metrics from the InmemSink to an io.Writer
+type InmemSignal struct {
+ signal syscall.Signal
+ inm *InmemSink
+ w io.Writer
+ sigCh chan os.Signal
+
+ stop bool
+ stopCh chan struct{}
+ stopLock sync.Mutex
+}
+
+// NewInmemSignal creates a new InmemSignal which listens for a given signal,
+// and dumps the current metrics out to a writer
+func NewInmemSignal(inmem *InmemSink, sig syscall.Signal, w io.Writer) *InmemSignal {
+ i := &InmemSignal{
+ signal: sig,
+ inm: inmem,
+ w: w,
+ sigCh: make(chan os.Signal, 1),
+ stopCh: make(chan struct{}),
+ }
+ signal.Notify(i.sigCh, sig)
+ go i.run()
+ return i
+}
+
+// DefaultInmemSignal returns a new InmemSignal that responds to SIGUSR1
+// and writes output to stderr. Windows uses SIGBREAK
+func DefaultInmemSignal(inmem *InmemSink) *InmemSignal {
+ return NewInmemSignal(inmem, DefaultSignal, os.Stderr)
+}
+
+// Stop is used to stop the InmemSignal from listening
+func (i *InmemSignal) Stop() {
+ i.stopLock.Lock()
+ defer i.stopLock.Unlock()
+
+ if i.stop {
+ return
+ }
+ i.stop = true
+ close(i.stopCh)
+ signal.Stop(i.sigCh)
+}
+
+// run is a long running routine that handles signals
+func (i *InmemSignal) run() {
+ for {
+ select {
+ case <-i.sigCh:
+ i.dumpStats()
+ case <-i.stopCh:
+ return
+ }
+ }
+}
+
+// dumpStats is used to dump the data to output writer
+func (i *InmemSignal) dumpStats() {
+ buf := bytes.NewBuffer(nil)
+
+ data := i.inm.Data()
+ // Skip the last period which is still being aggregated
+ for j := 0; j < len(data)-1; j++ {
+ intv := data[j]
+ intv.RLock()
+ for _, val := range intv.Gauges {
+ name := i.flattenLabels(val.Name, val.Labels)
+ fmt.Fprintf(buf, "[%v][G] '%s': %0.3f\n", intv.Interval, name, val.Value)
+ }
+ for name, vals := range intv.Points {
+ for _, val := range vals {
+ fmt.Fprintf(buf, "[%v][P] '%s': %0.3f\n", intv.Interval, name, val)
+ }
+ }
+ for _, agg := range intv.Counters {
+ name := i.flattenLabels(agg.Name, agg.Labels)
+ fmt.Fprintf(buf, "[%v][C] '%s': %s\n", intv.Interval, name, agg.AggregateSample)
+ }
+ for _, agg := range intv.Samples {
+ name := i.flattenLabels(agg.Name, agg.Labels)
+ fmt.Fprintf(buf, "[%v][S] '%s': %s\n", intv.Interval, name, agg.AggregateSample)
+ }
+ intv.RUnlock()
+ }
+
+ // Write out the bytes
+ i.w.Write(buf.Bytes())
+}
+
+// Flattens the key for formatting along with its labels, removes spaces
+func (i *InmemSignal) flattenLabels(name string, labels []Label) string {
+ buf := bytes.NewBufferString(name)
+ replacer := strings.NewReplacer(" ", "_", ":", "_")
+
+ for _, label := range labels {
+ replacer.WriteString(buf, ".")
+ replacer.WriteString(buf, label.Value)
+ }
+
+ return buf.String()
+}
--- /dev/null
+package metrics
+
+import (
+ "runtime"
+ "strings"
+ "time"
+
+ "github.com/hashicorp/go-immutable-radix"
+)
+
+type Label struct {
+ Name string
+ Value string
+}
+
+func (m *Metrics) SetGauge(key []string, val float32) {
+ m.SetGaugeWithLabels(key, val, nil)
+}
+
+func (m *Metrics) SetGaugeWithLabels(key []string, val float32, labels []Label) {
+ if m.HostName != "" {
+ if m.EnableHostnameLabel {
+ labels = append(labels, Label{"host", m.HostName})
+ } else if m.EnableHostname {
+ key = insert(0, m.HostName, key)
+ }
+ }
+ if m.EnableTypePrefix {
+ key = insert(0, "gauge", key)
+ }
+ if m.ServiceName != "" {
+ if m.EnableServiceLabel {
+ labels = append(labels, Label{"service", m.ServiceName})
+ } else {
+ key = insert(0, m.ServiceName, key)
+ }
+ }
+ if !m.allowMetric(key) {
+ return
+ }
+ m.sink.SetGaugeWithLabels(key, val, labels)
+}
+
+func (m *Metrics) EmitKey(key []string, val float32) {
+ if m.EnableTypePrefix {
+ key = insert(0, "kv", key)
+ }
+ if m.ServiceName != "" {
+ key = insert(0, m.ServiceName, key)
+ }
+ if !m.allowMetric(key) {
+ return
+ }
+ m.sink.EmitKey(key, val)
+}
+
+func (m *Metrics) IncrCounter(key []string, val float32) {
+ m.IncrCounterWithLabels(key, val, nil)
+}
+
+func (m *Metrics) IncrCounterWithLabels(key []string, val float32, labels []Label) {
+ if m.HostName != "" && m.EnableHostnameLabel {
+ labels = append(labels, Label{"host", m.HostName})
+ }
+ if m.EnableTypePrefix {
+ key = insert(0, "counter", key)
+ }
+ if m.ServiceName != "" {
+ if m.EnableServiceLabel {
+ labels = append(labels, Label{"service", m.ServiceName})
+ } else {
+ key = insert(0, m.ServiceName, key)
+ }
+ }
+ if !m.allowMetric(key) {
+ return
+ }
+ m.sink.IncrCounterWithLabels(key, val, labels)
+}
+
+func (m *Metrics) AddSample(key []string, val float32) {
+ m.AddSampleWithLabels(key, val, nil)
+}
+
+func (m *Metrics) AddSampleWithLabels(key []string, val float32, labels []Label) {
+ if m.HostName != "" && m.EnableHostnameLabel {
+ labels = append(labels, Label{"host", m.HostName})
+ }
+ if m.EnableTypePrefix {
+ key = insert(0, "sample", key)
+ }
+ if m.ServiceName != "" {
+ if m.EnableServiceLabel {
+ labels = append(labels, Label{"service", m.ServiceName})
+ } else {
+ key = insert(0, m.ServiceName, key)
+ }
+ }
+ if !m.allowMetric(key) {
+ return
+ }
+ m.sink.AddSampleWithLabels(key, val, labels)
+}
+
+func (m *Metrics) MeasureSince(key []string, start time.Time) {
+ m.MeasureSinceWithLabels(key, start, nil)
+}
+
+func (m *Metrics) MeasureSinceWithLabels(key []string, start time.Time, labels []Label) {
+ if m.HostName != "" && m.EnableHostnameLabel {
+ labels = append(labels, Label{"host", m.HostName})
+ }
+ if m.EnableTypePrefix {
+ key = insert(0, "timer", key)
+ }
+ if m.ServiceName != "" {
+ if m.EnableServiceLabel {
+ labels = append(labels, Label{"service", m.ServiceName})
+ } else {
+ key = insert(0, m.ServiceName, key)
+ }
+ }
+ if !m.allowMetric(key) {
+ return
+ }
+ now := time.Now()
+ elapsed := now.Sub(start)
+ msec := float32(elapsed.Nanoseconds()) / float32(m.TimerGranularity)
+ m.sink.AddSampleWithLabels(key, msec, labels)
+}
+
+// UpdateFilter overwrites the existing filter with the given rules.
+func (m *Metrics) UpdateFilter(allow, block []string) {
+ m.filterLock.Lock()
+ defer m.filterLock.Unlock()
+
+ m.AllowedPrefixes = allow
+ m.BlockedPrefixes = block
+
+ m.filter = iradix.New()
+ for _, prefix := range m.AllowedPrefixes {
+ m.filter, _, _ = m.filter.Insert([]byte(prefix), true)
+ }
+ for _, prefix := range m.BlockedPrefixes {
+ m.filter, _, _ = m.filter.Insert([]byte(prefix), false)
+ }
+}
+
+// Returns whether the metric should be allowed based on configured prefix filters
+func (m *Metrics) allowMetric(key []string) bool {
+ m.filterLock.RLock()
+ defer m.filterLock.RUnlock()
+
+ if m.filter == nil || m.filter.Len() == 0 {
+ return m.Config.FilterDefault
+ }
+
+ _, allowed, ok := m.filter.Root().LongestPrefix([]byte(strings.Join(key, ".")))
+ if !ok {
+ return m.Config.FilterDefault
+ }
+ return allowed.(bool)
+}
+
+// Periodically collects runtime stats to publish
+func (m *Metrics) collectStats() {
+ for {
+ time.Sleep(m.ProfileInterval)
+ m.emitRuntimeStats()
+ }
+}
+
+// Emits various runtime statsitics
+func (m *Metrics) emitRuntimeStats() {
+ // Export number of Goroutines
+ numRoutines := runtime.NumGoroutine()
+ m.SetGauge([]string{"runtime", "num_goroutines"}, float32(numRoutines))
+
+ // Export memory stats
+ var stats runtime.MemStats
+ runtime.ReadMemStats(&stats)
+ m.SetGauge([]string{"runtime", "alloc_bytes"}, float32(stats.Alloc))
+ m.SetGauge([]string{"runtime", "sys_bytes"}, float32(stats.Sys))
+ m.SetGauge([]string{"runtime", "malloc_count"}, float32(stats.Mallocs))
+ m.SetGauge([]string{"runtime", "free_count"}, float32(stats.Frees))
+ m.SetGauge([]string{"runtime", "heap_objects"}, float32(stats.HeapObjects))
+ m.SetGauge([]string{"runtime", "total_gc_pause_ns"}, float32(stats.PauseTotalNs))
+ m.SetGauge([]string{"runtime", "total_gc_runs"}, float32(stats.NumGC))
+
+ // Export info about the last few GC runs
+ num := stats.NumGC
+
+ // Handle wrap around
+ if num < m.lastNumGC {
+ m.lastNumGC = 0
+ }
+
+ // Ensure we don't scan more than 256
+ if num-m.lastNumGC >= 256 {
+ m.lastNumGC = num - 255
+ }
+
+ for i := m.lastNumGC; i < num; i++ {
+ pause := stats.PauseNs[i%256]
+ m.AddSample([]string{"runtime", "gc_pause_ns"}, float32(pause))
+ }
+ m.lastNumGC = num
+}
+
+// Inserts a string value at an index into the slice
+func insert(i int, v string, s []string) []string {
+ s = append(s, "")
+ copy(s[i+1:], s[i:])
+ s[i] = v
+ return s
+}
--- /dev/null
+package metrics
+
+import (
+ "fmt"
+ "net/url"
+)
+
+// The MetricSink interface is used to transmit metrics information
+// to an external system
+type MetricSink interface {
+ // A Gauge should retain the last value it is set to
+ SetGauge(key []string, val float32)
+ SetGaugeWithLabels(key []string, val float32, labels []Label)
+
+ // Should emit a Key/Value pair for each call
+ EmitKey(key []string, val float32)
+
+ // Counters should accumulate values
+ IncrCounter(key []string, val float32)
+ IncrCounterWithLabels(key []string, val float32, labels []Label)
+
+ // Samples are for timing information, where quantiles are used
+ AddSample(key []string, val float32)
+ AddSampleWithLabels(key []string, val float32, labels []Label)
+}
+
+// BlackholeSink is used to just blackhole messages
+type BlackholeSink struct{}
+
+func (*BlackholeSink) SetGauge(key []string, val float32) {}
+func (*BlackholeSink) SetGaugeWithLabels(key []string, val float32, labels []Label) {}
+func (*BlackholeSink) EmitKey(key []string, val float32) {}
+func (*BlackholeSink) IncrCounter(key []string, val float32) {}
+func (*BlackholeSink) IncrCounterWithLabels(key []string, val float32, labels []Label) {}
+func (*BlackholeSink) AddSample(key []string, val float32) {}
+func (*BlackholeSink) AddSampleWithLabels(key []string, val float32, labels []Label) {}
+
+// FanoutSink is used to sink to fanout values to multiple sinks
+type FanoutSink []MetricSink
+
+func (fh FanoutSink) SetGauge(key []string, val float32) {
+ fh.SetGaugeWithLabels(key, val, nil)
+}
+
+func (fh FanoutSink) SetGaugeWithLabels(key []string, val float32, labels []Label) {
+ for _, s := range fh {
+ s.SetGaugeWithLabels(key, val, labels)
+ }
+}
+
+func (fh FanoutSink) EmitKey(key []string, val float32) {
+ for _, s := range fh {
+ s.EmitKey(key, val)
+ }
+}
+
+func (fh FanoutSink) IncrCounter(key []string, val float32) {
+ fh.IncrCounterWithLabels(key, val, nil)
+}
+
+func (fh FanoutSink) IncrCounterWithLabels(key []string, val float32, labels []Label) {
+ for _, s := range fh {
+ s.IncrCounterWithLabels(key, val, labels)
+ }
+}
+
+func (fh FanoutSink) AddSample(key []string, val float32) {
+ fh.AddSampleWithLabels(key, val, nil)
+}
+
+func (fh FanoutSink) AddSampleWithLabels(key []string, val float32, labels []Label) {
+ for _, s := range fh {
+ s.AddSampleWithLabels(key, val, labels)
+ }
+}
+
+// sinkURLFactoryFunc is an generic interface around the *SinkFromURL() function provided
+// by each sink type
+type sinkURLFactoryFunc func(*url.URL) (MetricSink, error)
+
+// sinkRegistry supports the generic NewMetricSink function by mapping URL
+// schemes to metric sink factory functions
+var sinkRegistry = map[string]sinkURLFactoryFunc{
+ "statsd": NewStatsdSinkFromURL,
+ "statsite": NewStatsiteSinkFromURL,
+ "inmem": NewInmemSinkFromURL,
+}
+
+// NewMetricSinkFromURL allows a generic URL input to configure any of the
+// supported sinks. The scheme of the URL identifies the type of the sink, the
+// and query parameters are used to set options.
+//
+// "statsd://" - Initializes a StatsdSink. The host and port are passed through
+// as the "addr" of the sink
+//
+// "statsite://" - Initializes a StatsiteSink. The host and port become the
+// "addr" of the sink
+//
+// "inmem://" - Initializes an InmemSink. The host and port are ignored. The
+// "interval" and "duration" query parameters must be specified with valid
+// durations, see NewInmemSink for details.
+func NewMetricSinkFromURL(urlStr string) (MetricSink, error) {
+ u, err := url.Parse(urlStr)
+ if err != nil {
+ return nil, err
+ }
+
+ sinkURLFactoryFunc := sinkRegistry[u.Scheme]
+ if sinkURLFactoryFunc == nil {
+ return nil, fmt.Errorf(
+ "cannot create metric sink, unrecognized sink name: %q", u.Scheme)
+ }
+
+ return sinkURLFactoryFunc(u)
+}
--- /dev/null
+package metrics
+
+import (
+ "os"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "github.com/hashicorp/go-immutable-radix"
+)
+
+// Config is used to configure metrics settings
+type Config struct {
+ ServiceName string // Prefixed with keys to seperate services
+ HostName string // Hostname to use. If not provided and EnableHostname, it will be os.Hostname
+ EnableHostname bool // Enable prefixing gauge values with hostname
+ EnableHostnameLabel bool // Enable adding hostname to labels
+ EnableServiceLabel bool // Enable adding service to labels
+ EnableRuntimeMetrics bool // Enables profiling of runtime metrics (GC, Goroutines, Memory)
+ EnableTypePrefix bool // Prefixes key with a type ("counter", "gauge", "timer")
+ TimerGranularity time.Duration // Granularity of timers.
+ ProfileInterval time.Duration // Interval to profile runtime metrics
+
+ AllowedPrefixes []string // A list of metric prefixes to allow, with '.' as the separator
+ BlockedPrefixes []string // A list of metric prefixes to block, with '.' as the separator
+ FilterDefault bool // Whether to allow metrics by default
+}
+
+// Metrics represents an instance of a metrics sink that can
+// be used to emit
+type Metrics struct {
+ Config
+ lastNumGC uint32
+ sink MetricSink
+ filter *iradix.Tree
+ filterLock sync.RWMutex
+}
+
+// Shared global metrics instance
+var globalMetrics atomic.Value // *Metrics
+
+func init() {
+ // Initialize to a blackhole sink to avoid errors
+ globalMetrics.Store(&Metrics{sink: &BlackholeSink{}})
+}
+
+// DefaultConfig provides a sane default configuration
+func DefaultConfig(serviceName string) *Config {
+ c := &Config{
+ ServiceName: serviceName, // Use client provided service
+ HostName: "",
+ EnableHostname: true, // Enable hostname prefix
+ EnableRuntimeMetrics: true, // Enable runtime profiling
+ EnableTypePrefix: false, // Disable type prefix
+ TimerGranularity: time.Millisecond, // Timers are in milliseconds
+ ProfileInterval: time.Second, // Poll runtime every second
+ FilterDefault: true, // Don't filter metrics by default
+ }
+
+ // Try to get the hostname
+ name, _ := os.Hostname()
+ c.HostName = name
+ return c
+}
+
+// New is used to create a new instance of Metrics
+func New(conf *Config, sink MetricSink) (*Metrics, error) {
+ met := &Metrics{}
+ met.Config = *conf
+ met.sink = sink
+ met.UpdateFilter(conf.AllowedPrefixes, conf.BlockedPrefixes)
+
+ // Start the runtime collector
+ if conf.EnableRuntimeMetrics {
+ go met.collectStats()
+ }
+ return met, nil
+}
+
+// NewGlobal is the same as New, but it assigns the metrics object to be
+// used globally as well as returning it.
+func NewGlobal(conf *Config, sink MetricSink) (*Metrics, error) {
+ metrics, err := New(conf, sink)
+ if err == nil {
+ globalMetrics.Store(metrics)
+ }
+ return metrics, err
+}
+
+// Proxy all the methods to the globalMetrics instance
+func SetGauge(key []string, val float32) {
+ globalMetrics.Load().(*Metrics).SetGauge(key, val)
+}
+
+func SetGaugeWithLabels(key []string, val float32, labels []Label) {
+ globalMetrics.Load().(*Metrics).SetGaugeWithLabels(key, val, labels)
+}
+
+func EmitKey(key []string, val float32) {
+ globalMetrics.Load().(*Metrics).EmitKey(key, val)
+}
+
+func IncrCounter(key []string, val float32) {
+ globalMetrics.Load().(*Metrics).IncrCounter(key, val)
+}
+
+func IncrCounterWithLabels(key []string, val float32, labels []Label) {
+ globalMetrics.Load().(*Metrics).IncrCounterWithLabels(key, val, labels)
+}
+
+func AddSample(key []string, val float32) {
+ globalMetrics.Load().(*Metrics).AddSample(key, val)
+}
+
+func AddSampleWithLabels(key []string, val float32, labels []Label) {
+ globalMetrics.Load().(*Metrics).AddSampleWithLabels(key, val, labels)
+}
+
+func MeasureSince(key []string, start time.Time) {
+ globalMetrics.Load().(*Metrics).MeasureSince(key, start)
+}
+
+func MeasureSinceWithLabels(key []string, start time.Time, labels []Label) {
+ globalMetrics.Load().(*Metrics).MeasureSinceWithLabels(key, start, labels)
+}
+
+func UpdateFilter(allow, block []string) {
+ globalMetrics.Load().(*Metrics).UpdateFilter(allow, block)
+}
--- /dev/null
+package metrics
+
+import (
+ "bytes"
+ "fmt"
+ "log"
+ "net"
+ "net/url"
+ "strings"
+ "time"
+)
+
+const (
+ // statsdMaxLen is the maximum size of a packet
+ // to send to statsd
+ statsdMaxLen = 1400
+)
+
+// StatsdSink provides a MetricSink that can be used
+// with a statsite or statsd metrics server. It uses
+// only UDP packets, while StatsiteSink uses TCP.
+type StatsdSink struct {
+ addr string
+ metricQueue chan string
+}
+
+// NewStatsdSinkFromURL creates an StatsdSink from a URL. It is used
+// (and tested) from NewMetricSinkFromURL.
+func NewStatsdSinkFromURL(u *url.URL) (MetricSink, error) {
+ return NewStatsdSink(u.Host)
+}
+
+// NewStatsdSink is used to create a new StatsdSink
+func NewStatsdSink(addr string) (*StatsdSink, error) {
+ s := &StatsdSink{
+ addr: addr,
+ metricQueue: make(chan string, 4096),
+ }
+ go s.flushMetrics()
+ return s, nil
+}
+
+// Close is used to stop flushing to statsd
+func (s *StatsdSink) Shutdown() {
+ close(s.metricQueue)
+}
+
+func (s *StatsdSink) SetGauge(key []string, val float32) {
+ flatKey := s.flattenKey(key)
+ s.pushMetric(fmt.Sprintf("%s:%f|g\n", flatKey, val))
+}
+
+func (s *StatsdSink) SetGaugeWithLabels(key []string, val float32, labels []Label) {
+ flatKey := s.flattenKeyLabels(key, labels)
+ s.pushMetric(fmt.Sprintf("%s:%f|g\n", flatKey, val))
+}
+
+func (s *StatsdSink) EmitKey(key []string, val float32) {
+ flatKey := s.flattenKey(key)
+ s.pushMetric(fmt.Sprintf("%s:%f|kv\n", flatKey, val))
+}
+
+func (s *StatsdSink) IncrCounter(key []string, val float32) {
+ flatKey := s.flattenKey(key)
+ s.pushMetric(fmt.Sprintf("%s:%f|c\n", flatKey, val))
+}
+
+func (s *StatsdSink) IncrCounterWithLabels(key []string, val float32, labels []Label) {
+ flatKey := s.flattenKeyLabels(key, labels)
+ s.pushMetric(fmt.Sprintf("%s:%f|c\n", flatKey, val))
+}
+
+func (s *StatsdSink) AddSample(key []string, val float32) {
+ flatKey := s.flattenKey(key)
+ s.pushMetric(fmt.Sprintf("%s:%f|ms\n", flatKey, val))
+}
+
+func (s *StatsdSink) AddSampleWithLabels(key []string, val float32, labels []Label) {
+ flatKey := s.flattenKeyLabels(key, labels)
+ s.pushMetric(fmt.Sprintf("%s:%f|ms\n", flatKey, val))
+}
+
+// Flattens the key for formatting, removes spaces
+func (s *StatsdSink) flattenKey(parts []string) string {
+ joined := strings.Join(parts, ".")
+ return strings.Map(func(r rune) rune {
+ switch r {
+ case ':':
+ fallthrough
+ case ' ':
+ return '_'
+ default:
+ return r
+ }
+ }, joined)
+}
+
+// Flattens the key along with labels for formatting, removes spaces
+func (s *StatsdSink) flattenKeyLabels(parts []string, labels []Label) string {
+ for _, label := range labels {
+ parts = append(parts, label.Value)
+ }
+ return s.flattenKey(parts)
+}
+
+// Does a non-blocking push to the metrics queue
+func (s *StatsdSink) pushMetric(m string) {
+ select {
+ case s.metricQueue <- m:
+ default:
+ }
+}
+
+// Flushes metrics
+func (s *StatsdSink) flushMetrics() {
+ var sock net.Conn
+ var err error
+ var wait <-chan time.Time
+ ticker := time.NewTicker(flushInterval)
+ defer ticker.Stop()
+
+CONNECT:
+ // Create a buffer
+ buf := bytes.NewBuffer(nil)
+
+ // Attempt to connect
+ sock, err = net.Dial("udp", s.addr)
+ if err != nil {
+ log.Printf("[ERR] Error connecting to statsd! Err: %s", err)
+ goto WAIT
+ }
+
+ for {
+ select {
+ case metric, ok := <-s.metricQueue:
+ // Get a metric from the queue
+ if !ok {
+ goto QUIT
+ }
+
+ // Check if this would overflow the packet size
+ if len(metric)+buf.Len() > statsdMaxLen {
+ _, err := sock.Write(buf.Bytes())
+ buf.Reset()
+ if err != nil {
+ log.Printf("[ERR] Error writing to statsd! Err: %s", err)
+ goto WAIT
+ }
+ }
+
+ // Append to the buffer
+ buf.WriteString(metric)
+
+ case <-ticker.C:
+ if buf.Len() == 0 {
+ continue
+ }
+
+ _, err := sock.Write(buf.Bytes())
+ buf.Reset()
+ if err != nil {
+ log.Printf("[ERR] Error flushing to statsd! Err: %s", err)
+ goto WAIT
+ }
+ }
+ }
+
+WAIT:
+ // Wait for a while
+ wait = time.After(time.Duration(5) * time.Second)
+ for {
+ select {
+ // Dequeue the messages to avoid backlog
+ case _, ok := <-s.metricQueue:
+ if !ok {
+ goto QUIT
+ }
+ case <-wait:
+ goto CONNECT
+ }
+ }
+QUIT:
+ s.metricQueue = nil
+}
--- /dev/null
+package metrics
+
+import (
+ "bufio"
+ "fmt"
+ "log"
+ "net"
+ "net/url"
+ "strings"
+ "time"
+)
+
+const (
+ // We force flush the statsite metrics after this period of
+ // inactivity. Prevents stats from getting stuck in a buffer
+ // forever.
+ flushInterval = 100 * time.Millisecond
+)
+
+// NewStatsiteSinkFromURL creates an StatsiteSink from a URL. It is used
+// (and tested) from NewMetricSinkFromURL.
+func NewStatsiteSinkFromURL(u *url.URL) (MetricSink, error) {
+ return NewStatsiteSink(u.Host)
+}
+
+// StatsiteSink provides a MetricSink that can be used with a
+// statsite metrics server
+type StatsiteSink struct {
+ addr string
+ metricQueue chan string
+}
+
+// NewStatsiteSink is used to create a new StatsiteSink
+func NewStatsiteSink(addr string) (*StatsiteSink, error) {
+ s := &StatsiteSink{
+ addr: addr,
+ metricQueue: make(chan string, 4096),
+ }
+ go s.flushMetrics()
+ return s, nil
+}
+
+// Close is used to stop flushing to statsite
+func (s *StatsiteSink) Shutdown() {
+ close(s.metricQueue)
+}
+
+func (s *StatsiteSink) SetGauge(key []string, val float32) {
+ flatKey := s.flattenKey(key)
+ s.pushMetric(fmt.Sprintf("%s:%f|g\n", flatKey, val))
+}
+
+func (s *StatsiteSink) SetGaugeWithLabels(key []string, val float32, labels []Label) {
+ flatKey := s.flattenKeyLabels(key, labels)
+ s.pushMetric(fmt.Sprintf("%s:%f|g\n", flatKey, val))
+}
+
+func (s *StatsiteSink) EmitKey(key []string, val float32) {
+ flatKey := s.flattenKey(key)
+ s.pushMetric(fmt.Sprintf("%s:%f|kv\n", flatKey, val))
+}
+
+func (s *StatsiteSink) IncrCounter(key []string, val float32) {
+ flatKey := s.flattenKey(key)
+ s.pushMetric(fmt.Sprintf("%s:%f|c\n", flatKey, val))
+}
+
+func (s *StatsiteSink) IncrCounterWithLabels(key []string, val float32, labels []Label) {
+ flatKey := s.flattenKeyLabels(key, labels)
+ s.pushMetric(fmt.Sprintf("%s:%f|c\n", flatKey, val))
+}
+
+func (s *StatsiteSink) AddSample(key []string, val float32) {
+ flatKey := s.flattenKey(key)
+ s.pushMetric(fmt.Sprintf("%s:%f|ms\n", flatKey, val))
+}
+
+func (s *StatsiteSink) AddSampleWithLabels(key []string, val float32, labels []Label) {
+ flatKey := s.flattenKeyLabels(key, labels)
+ s.pushMetric(fmt.Sprintf("%s:%f|ms\n", flatKey, val))
+}
+
+// Flattens the key for formatting, removes spaces
+func (s *StatsiteSink) flattenKey(parts []string) string {
+ joined := strings.Join(parts, ".")
+ return strings.Map(func(r rune) rune {
+ switch r {
+ case ':':
+ fallthrough
+ case ' ':
+ return '_'
+ default:
+ return r
+ }
+ }, joined)
+}
+
+// Flattens the key along with labels for formatting, removes spaces
+func (s *StatsiteSink) flattenKeyLabels(parts []string, labels []Label) string {
+ for _, label := range labels {
+ parts = append(parts, label.Value)
+ }
+ return s.flattenKey(parts)
+}
+
+// Does a non-blocking push to the metrics queue
+func (s *StatsiteSink) pushMetric(m string) {
+ select {
+ case s.metricQueue <- m:
+ default:
+ }
+}
+
+// Flushes metrics
+func (s *StatsiteSink) flushMetrics() {
+ var sock net.Conn
+ var err error
+ var wait <-chan time.Time
+ var buffered *bufio.Writer
+ ticker := time.NewTicker(flushInterval)
+ defer ticker.Stop()
+
+CONNECT:
+ // Attempt to connect
+ sock, err = net.Dial("tcp", s.addr)
+ if err != nil {
+ log.Printf("[ERR] Error connecting to statsite! Err: %s", err)
+ goto WAIT
+ }
+
+ // Create a buffered writer
+ buffered = bufio.NewWriter(sock)
+
+ for {
+ select {
+ case metric, ok := <-s.metricQueue:
+ // Get a metric from the queue
+ if !ok {
+ goto QUIT
+ }
+
+ // Try to send to statsite
+ _, err := buffered.Write([]byte(metric))
+ if err != nil {
+ log.Printf("[ERR] Error writing to statsite! Err: %s", err)
+ goto WAIT
+ }
+ case <-ticker.C:
+ if err := buffered.Flush(); err != nil {
+ log.Printf("[ERR] Error flushing to statsite! Err: %s", err)
+ goto WAIT
+ }
+ }
+ }
+
+WAIT:
+ // Wait for a while
+ wait = time.After(time.Duration(5) * time.Second)
+ for {
+ select {
+ // Dequeue the messages to avoid backlog
+ case _, ok := <-s.metricQueue:
+ if !ok {
+ goto QUIT
+ }
+ case <-wait:
+ goto CONNECT
+ }
+ }
+QUIT:
+ s.metricQueue = nil
+}
--- /dev/null
+8
+5
+26
+12
+5
+235
+13
+6
+28
+30
+3
+3
+3
+3
+5
+2
+33
+7
+2
+4
+7
+12
+14
+5
+8
+3
+10
+4
+5
+3
+6
+6
+209
+20
+3
+10
+14
+3
+4
+6
+8
+5
+11
+7
+3
+2
+3
+3
+212
+5
+222
+4
+10
+10
+5
+6
+3
+8
+3
+10
+254
+220
+2
+3
+5
+24
+5
+4
+222
+7
+3
+3
+223
+8
+15
+12
+14
+14
+3
+2
+2
+3
+13
+3
+11
+4
+4
+6
+5
+7
+13
+5
+3
+5
+2
+5
+3
+5
+2
+7
+15
+17
+14
+3
+6
+6
+3
+17
+5
+4
+7
+6
+4
+4
+8
+6
+8
+3
+9
+3
+6
+3
+4
+5
+3
+3
+660
+4
+6
+10
+3
+6
+3
+2
+5
+13
+2
+4
+4
+10
+4
+8
+4
+3
+7
+9
+9
+3
+10
+37
+3
+13
+4
+12
+3
+6
+10
+8
+5
+21
+2
+3
+8
+3
+2
+3
+3
+4
+12
+2
+4
+8
+8
+4
+3
+2
+20
+1
+6
+32
+2
+11
+6
+18
+3
+8
+11
+3
+212
+3
+4
+2
+6
+7
+12
+11
+3
+2
+16
+10
+6
+4
+6
+3
+2
+7
+3
+2
+2
+2
+2
+5
+6
+4
+3
+10
+3
+4
+6
+5
+3
+4
+4
+5
+6
+4
+3
+4
+4
+5
+7
+5
+5
+3
+2
+7
+2
+4
+12
+4
+5
+6
+2
+4
+4
+8
+4
+15
+13
+7
+16
+5
+3
+23
+5
+5
+7
+3
+2
+9
+8
+7
+5
+8
+11
+4
+10
+76
+4
+47
+4
+3
+2
+7
+4
+2
+3
+37
+10
+4
+2
+20
+5
+4
+4
+10
+10
+4
+3
+7
+23
+240
+7
+13
+5
+5
+3
+3
+2
+5
+4
+2
+8
+7
+19
+2
+23
+8
+7
+2
+5
+3
+8
+3
+8
+13
+5
+5
+5
+2
+3
+23
+4
+9
+8
+4
+3
+3
+5
+220
+2
+3
+4
+6
+14
+3
+53
+6
+2
+5
+18
+6
+3
+219
+6
+5
+2
+5
+3
+6
+5
+15
+4
+3
+17
+3
+2
+4
+7
+2
+3
+3
+4
+4
+3
+2
+664
+6
+3
+23
+5
+5
+16
+5
+8
+2
+4
+2
+24
+12
+3
+2
+3
+5
+8
+3
+5
+4
+3
+14
+3
+5
+8
+2
+3
+7
+9
+4
+2
+3
+6
+8
+4
+3
+4
+6
+5
+3
+3
+6
+3
+19
+4
+4
+6
+3
+6
+3
+5
+22
+5
+4
+4
+3
+8
+11
+4
+9
+7
+6
+13
+4
+4
+4
+6
+17
+9
+3
+3
+3
+4
+3
+221
+5
+11
+3
+4
+2
+12
+6
+3
+5
+7
+5
+7
+4
+9
+7
+14
+37
+19
+217
+16
+3
+5
+2
+2
+7
+19
+7
+6
+7
+4
+24
+5
+11
+4
+7
+7
+9
+13
+3
+4
+3
+6
+28
+4
+4
+5
+5
+2
+5
+6
+4
+4
+6
+10
+5
+4
+3
+2
+3
+3
+6
+5
+5
+4
+3
+2
+3
+7
+4
+6
+18
+16
+8
+16
+4
+5
+8
+6
+9
+13
+1545
+6
+215
+6
+5
+6
+3
+45
+31
+5
+2
+2
+4
+3
+3
+2
+5
+4
+3
+5
+7
+7
+4
+5
+8
+5
+4
+749
+2
+31
+9
+11
+2
+11
+5
+4
+4
+7
+9
+11
+4
+5
+4
+7
+3
+4
+6
+2
+15
+3
+4
+3
+4
+3
+5
+2
+13
+5
+5
+3
+3
+23
+4
+4
+5
+7
+4
+13
+2
+4
+3
+4
+2
+6
+2
+7
+3
+5
+5
+3
+29
+5
+4
+4
+3
+10
+2
+3
+79
+16
+6
+6
+7
+7
+3
+5
+5
+7
+4
+3
+7
+9
+5
+6
+5
+9
+6
+3
+6
+4
+17
+2
+10
+9
+3
+6
+2
+3
+21
+22
+5
+11
+4
+2
+17
+2
+224
+2
+14
+3
+4
+4
+2
+4
+4
+4
+4
+5
+3
+4
+4
+10
+2
+6
+3
+3
+5
+7
+2
+7
+5
+6
+3
+218
+2
+2
+5
+2
+6
+3
+5
+222
+14
+6
+33
+3
+2
+5
+3
+3
+3
+9
+5
+3
+3
+2
+7
+4
+3
+4
+3
+5
+6
+5
+26
+4
+13
+9
+7
+3
+221
+3
+3
+4
+4
+4
+4
+2
+18
+5
+3
+7
+9
+6
+8
+3
+10
+3
+11
+9
+5
+4
+17
+5
+5
+6
+6
+3
+2
+4
+12
+17
+6
+7
+218
+4
+2
+4
+10
+3
+5
+15
+3
+9
+4
+3
+3
+6
+29
+3
+3
+4
+5
+5
+3
+8
+5
+6
+6
+7
+5
+3
+5
+3
+29
+2
+31
+5
+15
+24
+16
+5
+207
+4
+3
+3
+2
+15
+4
+4
+13
+5
+5
+4
+6
+10
+2
+7
+8
+4
+6
+20
+5
+3
+4
+3
+12
+12
+5
+17
+7
+3
+3
+3
+6
+10
+3
+5
+25
+80
+4
+9
+3
+2
+11
+3
+3
+2
+3
+8
+7
+5
+5
+19
+5
+3
+3
+12
+11
+2
+6
+5
+5
+5
+3
+3
+3
+4
+209
+14
+3
+2
+5
+19
+4
+4
+3
+4
+14
+5
+6
+4
+13
+9
+7
+4
+7
+10
+2
+9
+5
+7
+2
+8
+4
+6
+5
+5
+222
+8
+7
+12
+5
+216
+3
+4
+4
+6
+3
+14
+8
+7
+13
+4
+3
+3
+3
+3
+17
+5
+4
+3
+33
+6
+6
+33
+7
+5
+3
+8
+7
+5
+2
+9
+4
+2
+233
+24
+7
+4
+8
+10
+3
+4
+15
+2
+16
+3
+3
+13
+12
+7
+5
+4
+207
+4
+2
+4
+27
+15
+2
+5
+2
+25
+6
+5
+5
+6
+13
+6
+18
+6
+4
+12
+225
+10
+7
+5
+2
+2
+11
+4
+14
+21
+8
+10
+3
+5
+4
+232
+2
+5
+5
+3
+7
+17
+11
+6
+6
+23
+4
+6
+3
+5
+4
+2
+17
+3
+6
+5
+8
+3
+2
+2
+14
+9
+4
+4
+2
+5
+5
+3
+7
+6
+12
+6
+10
+3
+6
+2
+2
+19
+5
+4
+4
+9
+2
+4
+13
+3
+5
+6
+3
+6
+5
+4
+9
+6
+3
+5
+7
+3
+6
+6
+4
+3
+10
+6
+3
+221
+3
+5
+3
+6
+4
+8
+5
+3
+6
+4
+4
+2
+54
+5
+6
+11
+3
+3
+4
+4
+4
+3
+7
+3
+11
+11
+7
+10
+6
+13
+223
+213
+15
+231
+7
+3
+7
+228
+2
+3
+4
+4
+5
+6
+7
+4
+13
+3
+4
+5
+3
+6
+4
+6
+7
+2
+4
+3
+4
+3
+3
+6
+3
+7
+3
+5
+18
+5
+6
+8
+10
+3
+3
+3
+2
+4
+2
+4
+4
+5
+6
+6
+4
+10
+13
+3
+12
+5
+12
+16
+8
+4
+19
+11
+2
+4
+5
+6
+8
+5
+6
+4
+18
+10
+4
+2
+216
+6
+6
+6
+2
+4
+12
+8
+3
+11
+5
+6
+14
+5
+3
+13
+4
+5
+4
+5
+3
+28
+6
+3
+7
+219
+3
+9
+7
+3
+10
+6
+3
+4
+19
+5
+7
+11
+6
+15
+19
+4
+13
+11
+3
+7
+5
+10
+2
+8
+11
+2
+6
+4
+6
+24
+6
+3
+3
+3
+3
+6
+18
+4
+11
+4
+2
+5
+10
+8
+3
+9
+5
+3
+4
+5
+6
+2
+5
+7
+4
+4
+14
+6
+4
+4
+5
+5
+7
+2
+4
+3
+7
+3
+3
+6
+4
+5
+4
+4
+4
+3
+3
+3
+3
+8
+14
+2
+3
+5
+3
+2
+4
+5
+3
+7
+3
+3
+18
+3
+4
+4
+5
+7
+3
+3
+3
+13
+5
+4
+8
+211
+5
+5
+3
+5
+2
+5
+4
+2
+655
+6
+3
+5
+11
+2
+5
+3
+12
+9
+15
+11
+5
+12
+217
+2
+6
+17
+3
+3
+207
+5
+5
+4
+5
+9
+3
+2
+8
+5
+4
+3
+2
+5
+12
+4
+14
+5
+4
+2
+13
+5
+8
+4
+225
+4
+3
+4
+5
+4
+3
+3
+6
+23
+9
+2
+6
+7
+233
+4
+4
+6
+18
+3
+4
+6
+3
+4
+4
+2
+3
+7
+4
+13
+227
+4
+3
+5
+4
+2
+12
+9
+17
+3
+7
+14
+6
+4
+5
+21
+4
+8
+9
+2
+9
+25
+16
+3
+6
+4
+7
+8
+5
+2
+3
+5
+4
+3
+3
+5
+3
+3
+3
+2
+3
+19
+2
+4
+3
+4
+2
+3
+4
+4
+2
+4
+3
+3
+3
+2
+6
+3
+17
+5
+6
+4
+3
+13
+5
+3
+3
+3
+4
+9
+4
+2
+14
+12
+4
+5
+24
+4
+3
+37
+12
+11
+21
+3
+4
+3
+13
+4
+2
+3
+15
+4
+11
+4
+4
+3
+8
+3
+4
+4
+12
+8
+5
+3
+3
+4
+2
+220
+3
+5
+223
+3
+3
+3
+10
+3
+15
+4
+241
+9
+7
+3
+6
+6
+23
+4
+13
+7
+3
+4
+7
+4
+9
+3
+3
+4
+10
+5
+5
+1
+5
+24
+2
+4
+5
+5
+6
+14
+3
+8
+2
+3
+5
+13
+13
+3
+5
+2
+3
+15
+3
+4
+2
+10
+4
+4
+4
+5
+5
+3
+5
+3
+4
+7
+4
+27
+3
+6
+4
+15
+3
+5
+6
+6
+5
+4
+8
+3
+9
+2
+6
+3
+4
+3
+7
+4
+18
+3
+11
+3
+3
+8
+9
+7
+24
+3
+219
+7
+10
+4
+5
+9
+12
+2
+5
+4
+4
+4
+3
+3
+19
+5
+8
+16
+8
+6
+22
+3
+23
+3
+242
+9
+4
+3
+3
+5
+7
+3
+3
+5
+8
+3
+7
+5
+14
+8
+10
+3
+4
+3
+7
+4
+6
+7
+4
+10
+4
+3
+11
+3
+7
+10
+3
+13
+6
+8
+12
+10
+5
+7
+9
+3
+4
+7
+7
+10
+8
+30
+9
+19
+4
+3
+19
+15
+4
+13
+3
+215
+223
+4
+7
+4
+8
+17
+16
+3
+7
+6
+5
+5
+4
+12
+3
+7
+4
+4
+13
+4
+5
+2
+5
+6
+5
+6
+6
+7
+10
+18
+23
+9
+3
+3
+6
+5
+2
+4
+2
+7
+3
+3
+2
+5
+5
+14
+10
+224
+6
+3
+4
+3
+7
+5
+9
+3
+6
+4
+2
+5
+11
+4
+3
+3
+2
+8
+4
+7
+4
+10
+7
+3
+3
+18
+18
+17
+3
+3
+3
+4
+5
+3
+3
+4
+12
+7
+3
+11
+13
+5
+4
+7
+13
+5
+4
+11
+3
+12
+3
+6
+4
+4
+21
+4
+6
+9
+5
+3
+10
+8
+4
+6
+4
+4
+6
+5
+4
+8
+6
+4
+6
+4
+4
+5
+9
+6
+3
+4
+2
+9
+3
+18
+2
+4
+3
+13
+3
+6
+6
+8
+7
+9
+3
+2
+16
+3
+4
+6
+3
+2
+33
+22
+14
+4
+9
+12
+4
+5
+6
+3
+23
+9
+4
+3
+5
+5
+3
+4
+5
+3
+5
+3
+10
+4
+5
+5
+8
+4
+4
+6
+8
+5
+4
+3
+4
+6
+3
+3
+3
+5
+9
+12
+6
+5
+9
+3
+5
+3
+2
+2
+2
+18
+3
+2
+21
+2
+5
+4
+6
+4
+5
+10
+3
+9
+3
+2
+10
+7
+3
+6
+6
+4
+4
+8
+12
+7
+3
+7
+3
+3
+9
+3
+4
+5
+4
+4
+5
+5
+10
+15
+4
+4
+14
+6
+227
+3
+14
+5
+216
+22
+5
+4
+2
+2
+6
+3
+4
+2
+9
+9
+4
+3
+28
+13
+11
+4
+5
+3
+3
+2
+3
+3
+5
+3
+4
+3
+5
+23
+26
+3
+4
+5
+6
+4
+6
+3
+5
+5
+3
+4
+3
+2
+2
+2
+7
+14
+3
+6
+7
+17
+2
+2
+15
+14
+16
+4
+6
+7
+13
+6
+4
+5
+6
+16
+3
+3
+28
+3
+6
+15
+3
+9
+2
+4
+6
+3
+3
+22
+4
+12
+6
+7
+2
+5
+4
+10
+3
+16
+6
+9
+2
+5
+12
+7
+5
+5
+5
+5
+2
+11
+9
+17
+4
+3
+11
+7
+3
+5
+15
+4
+3
+4
+211
+8
+7
+5
+4
+7
+6
+7
+6
+3
+6
+5
+6
+5
+3
+4
+4
+26
+4
+6
+10
+4
+4
+3
+2
+3
+3
+4
+5
+9
+3
+9
+4
+4
+5
+5
+8
+2
+4
+2
+3
+8
+4
+11
+19
+5
+8
+6
+3
+5
+6
+12
+3
+2
+4
+16
+12
+3
+4
+4
+8
+6
+5
+6
+6
+219
+8
+222
+6
+16
+3
+13
+19
+5
+4
+3
+11
+6
+10
+4
+7
+7
+12
+5
+3
+3
+5
+6
+10
+3
+8
+2
+5
+4
+7
+2
+4
+4
+2
+12
+9
+6
+4
+2
+40
+2
+4
+10
+4
+223
+4
+2
+20
+6
+7
+24
+5
+4
+5
+2
+20
+16
+6
+5
+13
+2
+3
+3
+19
+3
+2
+4
+5
+6
+7
+11
+12
+5
+6
+7
+7
+3
+5
+3
+5
+3
+14
+3
+4
+4
+2
+11
+1
+7
+3
+9
+6
+11
+12
+5
+8
+6
+221
+4
+2
+12
+4
+3
+15
+4
+5
+226
+7
+218
+7
+5
+4
+5
+18
+4
+5
+9
+4
+4
+2
+9
+18
+18
+9
+5
+6
+6
+3
+3
+7
+3
+5
+4
+4
+4
+12
+3
+6
+31
+5
+4
+7
+3
+6
+5
+6
+5
+11
+2
+2
+11
+11
+6
+7
+5
+8
+7
+10
+5
+23
+7
+4
+3
+5
+34
+2
+5
+23
+7
+3
+6
+8
+4
+4
+4
+2
+5
+3
+8
+5
+4
+8
+25
+2
+3
+17
+8
+3
+4
+8
+7
+3
+15
+6
+5
+7
+21
+9
+5
+6
+6
+5
+3
+2
+3
+10
+3
+6
+3
+14
+7
+4
+4
+8
+7
+8
+2
+6
+12
+4
+213
+6
+5
+21
+8
+2
+5
+23
+3
+11
+2
+3
+6
+25
+2
+3
+6
+7
+6
+6
+4
+4
+6
+3
+17
+9
+7
+6
+4
+3
+10
+7
+2
+3
+3
+3
+11
+8
+3
+7
+6
+4
+14
+36
+3
+4
+3
+3
+22
+13
+21
+4
+2
+7
+4
+4
+17
+15
+3
+7
+11
+2
+4
+7
+6
+209
+6
+3
+2
+2
+24
+4
+9
+4
+3
+3
+3
+29
+2
+2
+4
+3
+3
+5
+4
+6
+3
+3
+2
+4
--- /dev/null
+// Package quantile computes approximate quantiles over an unbounded data
+// stream within low memory and CPU bounds.
+//
+// A small amount of accuracy is traded to achieve the above properties.
+//
+// Multiple streams can be merged before calling Query to generate a single set
+// of results. This is meaningful when the streams represent the same type of
+// data. See Merge and Samples.
+//
+// For more detailed information about the algorithm used, see:
+//
+// Effective Computation of Biased Quantiles over Data Streams
+//
+// http://www.cs.rutgers.edu/~muthu/bquant.pdf
+package quantile
+
+import (
+ "math"
+ "sort"
+)
+
+// Sample holds an observed value and meta information for compression. JSON
+// tags have been added for convenience.
+type Sample struct {
+ Value float64 `json:",string"`
+ Width float64 `json:",string"`
+ Delta float64 `json:",string"`
+}
+
+// Samples represents a slice of samples. It implements sort.Interface.
+type Samples []Sample
+
+func (a Samples) Len() int { return len(a) }
+func (a Samples) Less(i, j int) bool { return a[i].Value < a[j].Value }
+func (a Samples) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+type invariant func(s *stream, r float64) float64
+
+// NewLowBiased returns an initialized Stream for low-biased quantiles
+// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but
+// error guarantees can still be given even for the lower ranks of the data
+// distribution.
+//
+// The provided epsilon is a relative error, i.e. the true quantile of a value
+// returned by a query is guaranteed to be within (1±Epsilon)*Quantile.
+//
+// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error
+// properties.
+func NewLowBiased(epsilon float64) *Stream {
+ ƒ := func(s *stream, r float64) float64 {
+ return 2 * epsilon * r
+ }
+ return newStream(ƒ)
+}
+
+// NewHighBiased returns an initialized Stream for high-biased quantiles
+// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but
+// error guarantees can still be given even for the higher ranks of the data
+// distribution.
+//
+// The provided epsilon is a relative error, i.e. the true quantile of a value
+// returned by a query is guaranteed to be within 1-(1±Epsilon)*(1-Quantile).
+//
+// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error
+// properties.
+func NewHighBiased(epsilon float64) *Stream {
+ ƒ := func(s *stream, r float64) float64 {
+ return 2 * epsilon * (s.n - r)
+ }
+ return newStream(ƒ)
+}
+
+// NewTargeted returns an initialized Stream concerned with a particular set of
+// quantile values that are supplied a priori. Knowing these a priori reduces
+// space and computation time. The targets map maps the desired quantiles to
+// their absolute errors, i.e. the true quantile of a value returned by a query
+// is guaranteed to be within (Quantile±Epsilon).
+//
+// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error properties.
+func NewTargeted(targets map[float64]float64) *Stream {
+ ƒ := func(s *stream, r float64) float64 {
+ var m = math.MaxFloat64
+ var f float64
+ for quantile, epsilon := range targets {
+ if quantile*s.n <= r {
+ f = (2 * epsilon * r) / quantile
+ } else {
+ f = (2 * epsilon * (s.n - r)) / (1 - quantile)
+ }
+ if f < m {
+ m = f
+ }
+ }
+ return m
+ }
+ return newStream(ƒ)
+}
+
+// Stream computes quantiles for a stream of float64s. It is not thread-safe by
+// design. Take care when using across multiple goroutines.
+type Stream struct {
+ *stream
+ b Samples
+ sorted bool
+}
+
+func newStream(ƒ invariant) *Stream {
+ x := &stream{ƒ: ƒ}
+ return &Stream{x, make(Samples, 0, 500), true}
+}
+
+// Insert inserts v into the stream.
+func (s *Stream) Insert(v float64) {
+ s.insert(Sample{Value: v, Width: 1})
+}
+
+func (s *Stream) insert(sample Sample) {
+ s.b = append(s.b, sample)
+ s.sorted = false
+ if len(s.b) == cap(s.b) {
+ s.flush()
+ }
+}
+
+// Query returns the computed qth percentiles value. If s was created with
+// NewTargeted, and q is not in the set of quantiles provided a priori, Query
+// will return an unspecified result.
+func (s *Stream) Query(q float64) float64 {
+ if !s.flushed() {
+ // Fast path when there hasn't been enough data for a flush;
+ // this also yields better accuracy for small sets of data.
+ l := len(s.b)
+ if l == 0 {
+ return 0
+ }
+ i := int(float64(l) * q)
+ if i > 0 {
+ i -= 1
+ }
+ s.maybeSort()
+ return s.b[i].Value
+ }
+ s.flush()
+ return s.stream.query(q)
+}
+
+// Merge merges samples into the underlying streams samples. This is handy when
+// merging multiple streams from separate threads, database shards, etc.
+//
+// ATTENTION: This method is broken and does not yield correct results. The
+// underlying algorithm is not capable of merging streams correctly.
+func (s *Stream) Merge(samples Samples) {
+ sort.Sort(samples)
+ s.stream.merge(samples)
+}
+
+// Reset reinitializes and clears the list reusing the samples buffer memory.
+func (s *Stream) Reset() {
+ s.stream.reset()
+ s.b = s.b[:0]
+}
+
+// Samples returns stream samples held by s.
+func (s *Stream) Samples() Samples {
+ if !s.flushed() {
+ return s.b
+ }
+ s.flush()
+ return s.stream.samples()
+}
+
+// Count returns the total number of samples observed in the stream
+// since initialization.
+func (s *Stream) Count() int {
+ return len(s.b) + s.stream.count()
+}
+
+func (s *Stream) flush() {
+ s.maybeSort()
+ s.stream.merge(s.b)
+ s.b = s.b[:0]
+}
+
+func (s *Stream) maybeSort() {
+ if !s.sorted {
+ s.sorted = true
+ sort.Sort(s.b)
+ }
+}
+
+func (s *Stream) flushed() bool {
+ return len(s.stream.l) > 0
+}
+
+type stream struct {
+ n float64
+ l []Sample
+ ƒ invariant
+}
+
+func (s *stream) reset() {
+ s.l = s.l[:0]
+ s.n = 0
+}
+
+func (s *stream) insert(v float64) {
+ s.merge(Samples{{v, 1, 0}})
+}
+
+func (s *stream) merge(samples Samples) {
+ // TODO(beorn7): This tries to merge not only individual samples, but
+ // whole summaries. The paper doesn't mention merging summaries at
+ // all. Unittests show that the merging is inaccurate. Find out how to
+ // do merges properly.
+ var r float64
+ i := 0
+ for _, sample := range samples {
+ for ; i < len(s.l); i++ {
+ c := s.l[i]
+ if c.Value > sample.Value {
+ // Insert at position i.
+ s.l = append(s.l, Sample{})
+ copy(s.l[i+1:], s.l[i:])
+ s.l[i] = Sample{
+ sample.Value,
+ sample.Width,
+ math.Max(sample.Delta, math.Floor(s.ƒ(s, r))-1),
+ // TODO(beorn7): How to calculate delta correctly?
+ }
+ i++
+ goto inserted
+ }
+ r += c.Width
+ }
+ s.l = append(s.l, Sample{sample.Value, sample.Width, 0})
+ i++
+ inserted:
+ s.n += sample.Width
+ r += sample.Width
+ }
+ s.compress()
+}
+
+func (s *stream) count() int {
+ return int(s.n)
+}
+
+func (s *stream) query(q float64) float64 {
+ t := math.Ceil(q * s.n)
+ t += math.Ceil(s.ƒ(s, t) / 2)
+ p := s.l[0]
+ var r float64
+ for _, c := range s.l[1:] {
+ r += p.Width
+ if r+c.Width+c.Delta > t {
+ return p.Value
+ }
+ p = c
+ }
+ return p.Value
+}
+
+func (s *stream) compress() {
+ if len(s.l) < 2 {
+ return
+ }
+ x := s.l[len(s.l)-1]
+ xi := len(s.l) - 1
+ r := s.n - 1 - x.Width
+
+ for i := len(s.l) - 2; i >= 0; i-- {
+ c := s.l[i]
+ if c.Width+x.Width+x.Delta <= s.ƒ(s, r) {
+ x.Width += c.Width
+ s.l[xi] = x
+ // Remove element at i.
+ copy(s.l[i:], s.l[i+1:])
+ s.l = s.l[:len(s.l)-1]
+ xi -= 1
+ } else {
+ x = c
+ xi = i
+ }
+ r -= c.Width
+ }
+}
+
+func (s *stream) samples() Samples {
+ samples := make(Samples, len(s.l))
+ copy(samples, s.l)
+ return samples
+}
--- /dev/null
+The MIT License (MIT)
+
+Copyright (c) 2014 Cenk Altı
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--- /dev/null
+# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis]
+
+This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client].
+
+[Exponential backoff][exponential backoff wiki]
+is an algorithm that uses feedback to multiplicatively decrease the rate of some process,
+in order to gradually find an acceptable rate.
+The retries exponentially increase and stop increasing when a certain threshold is met.
+
+## How To
+
+We define two functions, `Retry()` and `RetryNotify()`.
+They receive an `Operation` to execute, a `BackOff` algorithm,
+and an optional `Notify` error handler.
+
+The operation will be executed, and will be retried on failure with delay
+as given by the backoff algorithm. The backoff algorithm can also decide when to stop
+retrying.
+In addition, the notify error handler will be called after each failed attempt,
+except for the last time, whose error should be handled by the caller.
+
+```go
+// An Operation is executing by Retry() or RetryNotify().
+// The operation will be retried using a backoff policy if it returns an error.
+type Operation func() error
+
+// Notify is a notify-on-error function. It receives an operation error and
+// backoff delay if the operation failed (with an error).
+//
+// NOTE that if the backoff policy stated to stop retrying,
+// the notify function isn't called.
+type Notify func(error, time.Duration)
+
+func Retry(Operation, BackOff) error
+func RetryNotify(Operation, BackOff, Notify)
+```
+
+## Examples
+
+See more advanced examples in the [godoc][advanced example].
+
+### Retry
+
+Simple retry helper that uses the default exponential backoff algorithm:
+
+```go
+operation := func() error {
+ // An operation that might fail.
+ return nil // or return errors.New("some error")
+}
+
+err := Retry(operation, NewExponentialBackOff())
+if err != nil {
+ // Handle error.
+ return err
+}
+
+// Operation is successful.
+return nil
+```
+
+### Ticker
+
+```go
+operation := func() error {
+ // An operation that might fail
+ return nil // or return errors.New("some error")
+}
+
+b := NewExponentialBackOff()
+ticker := NewTicker(b)
+
+var err error
+
+// Ticks will continue to arrive when the previous operation is still running,
+// so operations that take a while to fail could run in quick succession.
+for range ticker.C {
+ if err = operation(); err != nil {
+ log.Println(err, "will retry...")
+ continue
+ }
+
+ ticker.Stop()
+ break
+}
+
+if err != nil {
+ // Operation has failed.
+ return err
+}
+
+// Operation is successful.
+return nil
+```
+
+## Getting Started
+
+```bash
+# install
+$ go get github.com/cenkalti/backoff
+
+# test
+$ cd $GOPATH/src/github.com/cenkalti/backoff
+$ go get -t ./...
+$ go test -v -cover
+```
+
+[godoc]: https://godoc.org/github.com/cenkalti/backoff
+[godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png
+[travis]: https://travis-ci.org/cenkalti/backoff
+[travis image]: https://travis-ci.org/cenkalti/backoff.png
+
+[google-http-java-client]: https://github.com/google/google-http-java-client
+[exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff
+
+[advanced example]: https://godoc.org/github.com/cenkalti/backoff#example_
--- /dev/null
+// Package backoff implements backoff algorithms for retrying operations.
+//
+// Also has a Retry() helper for retrying operations that may fail.
+package backoff
+
+import "time"
+
+// BackOff is a backoff policy for retrying an operation.
+type BackOff interface {
+ // NextBackOff returns the duration to wait before retrying the operation,
+ // or backoff.Stop to indicate that no more retries should be made.
+ //
+ // Example usage:
+ //
+ // duration := backoff.NextBackOff();
+ // if (duration == backoff.Stop) {
+ // // Do not retry operation.
+ // } else {
+ // // Sleep for duration and retry operation.
+ // }
+ //
+ NextBackOff() time.Duration
+
+ // Reset to initial state.
+ Reset()
+}
+
+// Indicates that no more retries should be made for use in NextBackOff().
+const Stop time.Duration = -1
+
+// ZeroBackOff is a fixed backoff policy whose backoff time is always zero,
+// meaning that the operation is retried immediately without waiting, indefinitely.
+type ZeroBackOff struct{}
+
+func (b *ZeroBackOff) Reset() {}
+
+func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 }
+
+// StopBackOff is a fixed backoff policy that always returns backoff.Stop for
+// NextBackOff(), meaning that the operation should never be retried.
+type StopBackOff struct{}
+
+func (b *StopBackOff) Reset() {}
+
+func (b *StopBackOff) NextBackOff() time.Duration { return Stop }
+
+// ConstantBackOff is a backoff policy that always returns the same backoff delay.
+// This is in contrast to an exponential backoff policy,
+// which returns a delay that grows longer as you call NextBackOff() over and over again.
+type ConstantBackOff struct {
+ Interval time.Duration
+}
+
+func (b *ConstantBackOff) Reset() {}
+func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Interval }
+
+func NewConstantBackOff(d time.Duration) *ConstantBackOff {
+ return &ConstantBackOff{Interval: d}
+}
--- /dev/null
+package backoff
+
+import (
+ "math/rand"
+ "time"
+)
+
+/*
+ExponentialBackOff is a backoff implementation that increases the backoff
+period for each retry attempt using a randomization function that grows exponentially.
+
+NextBackOff() is calculated using the following formula:
+
+ randomized interval =
+ RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor])
+
+In other words NextBackOff() will range between the randomization factor
+percentage below and above the retry interval.
+
+For example, given the following parameters:
+
+ RetryInterval = 2
+ RandomizationFactor = 0.5
+ Multiplier = 2
+
+the actual backoff period used in the next retry attempt will range between 1 and 3 seconds,
+multiplied by the exponential, that is, between 2 and 6 seconds.
+
+Note: MaxInterval caps the RetryInterval and not the randomized interval.
+
+If the time elapsed since an ExponentialBackOff instance is created goes past the
+MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop.
+
+The elapsed time can be reset by calling Reset().
+
+Example: Given the following default arguments, for 10 tries the sequence will be,
+and assuming we go over the MaxElapsedTime on the 10th try:
+
+ Request # RetryInterval (seconds) Randomized Interval (seconds)
+
+ 1 0.5 [0.25, 0.75]
+ 2 0.75 [0.375, 1.125]
+ 3 1.125 [0.562, 1.687]
+ 4 1.687 [0.8435, 2.53]
+ 5 2.53 [1.265, 3.795]
+ 6 3.795 [1.897, 5.692]
+ 7 5.692 [2.846, 8.538]
+ 8 8.538 [4.269, 12.807]
+ 9 12.807 [6.403, 19.210]
+ 10 19.210 backoff.Stop
+
+Note: Implementation is not thread-safe.
+*/
+type ExponentialBackOff struct {
+ InitialInterval time.Duration
+ RandomizationFactor float64
+ Multiplier float64
+ MaxInterval time.Duration
+ // After MaxElapsedTime the ExponentialBackOff stops.
+ // It never stops if MaxElapsedTime == 0.
+ MaxElapsedTime time.Duration
+ Clock Clock
+
+ currentInterval time.Duration
+ startTime time.Time
+}
+
+// Clock is an interface that returns current time for BackOff.
+type Clock interface {
+ Now() time.Time
+}
+
+// Default values for ExponentialBackOff.
+const (
+ DefaultInitialInterval = 500 * time.Millisecond
+ DefaultRandomizationFactor = 0.5
+ DefaultMultiplier = 1.5
+ DefaultMaxInterval = 60 * time.Second
+ DefaultMaxElapsedTime = 15 * time.Minute
+)
+
+// NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
+func NewExponentialBackOff() *ExponentialBackOff {
+ b := &ExponentialBackOff{
+ InitialInterval: DefaultInitialInterval,
+ RandomizationFactor: DefaultRandomizationFactor,
+ Multiplier: DefaultMultiplier,
+ MaxInterval: DefaultMaxInterval,
+ MaxElapsedTime: DefaultMaxElapsedTime,
+ Clock: SystemClock,
+ }
+ b.Reset()
+ return b
+}
+
+type systemClock struct{}
+
+func (t systemClock) Now() time.Time {
+ return time.Now()
+}
+
+// SystemClock implements Clock interface that uses time.Now().
+var SystemClock = systemClock{}
+
+// Reset the interval back to the initial retry interval and restarts the timer.
+func (b *ExponentialBackOff) Reset() {
+ b.currentInterval = b.InitialInterval
+ b.startTime = b.Clock.Now()
+}
+
+// NextBackOff calculates the next backoff interval using the formula:
+// Randomized interval = RetryInterval +/- (RandomizationFactor * RetryInterval)
+func (b *ExponentialBackOff) NextBackOff() time.Duration {
+ // Make sure we have not gone over the maximum elapsed time.
+ if b.MaxElapsedTime != 0 && b.GetElapsedTime() > b.MaxElapsedTime {
+ return Stop
+ }
+ defer b.incrementCurrentInterval()
+ return getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval)
+}
+
+// GetElapsedTime returns the elapsed time since an ExponentialBackOff instance
+// is created and is reset when Reset() is called.
+//
+// The elapsed time is computed using time.Now().UnixNano().
+func (b *ExponentialBackOff) GetElapsedTime() time.Duration {
+ return b.Clock.Now().Sub(b.startTime)
+}
+
+// Increments the current interval by multiplying it with the multiplier.
+func (b *ExponentialBackOff) incrementCurrentInterval() {
+ // Check for overflow, if overflow is detected set the current interval to the max interval.
+ if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier {
+ b.currentInterval = b.MaxInterval
+ } else {
+ b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier)
+ }
+}
+
+// Returns a random value from the following interval:
+// [randomizationFactor * currentInterval, randomizationFactor * currentInterval].
+func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration {
+ var delta = randomizationFactor * float64(currentInterval)
+ var minInterval = float64(currentInterval) - delta
+ var maxInterval = float64(currentInterval) + delta
+
+ // Get a random value from the range [minInterval, maxInterval].
+ // The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then
+ // we want a 33% chance for selecting either 1, 2 or 3.
+ return time.Duration(minInterval + (random * (maxInterval - minInterval + 1)))
+}
--- /dev/null
+package backoff
+
+import "time"
+
+// An Operation is executing by Retry() or RetryNotify().
+// The operation will be retried using a backoff policy if it returns an error.
+type Operation func() error
+
+// Notify is a notify-on-error function. It receives an operation error and
+// backoff delay if the operation failed (with an error).
+//
+// NOTE that if the backoff policy stated to stop retrying,
+// the notify function isn't called.
+type Notify func(error, time.Duration)
+
+// Retry the function f until it does not return error or BackOff stops.
+// f is guaranteed to be run at least once.
+// It is the caller's responsibility to reset b after Retry returns.
+//
+// Retry sleeps the goroutine for the duration returned by BackOff after a
+// failed operation returns.
+func Retry(o Operation, b BackOff) error { return RetryNotify(o, b, nil) }
+
+// RetryNotify calls notify function with the error and wait duration
+// for each failed attempt before sleep.
+func RetryNotify(operation Operation, b BackOff, notify Notify) error {
+ var err error
+ var next time.Duration
+
+ b.Reset()
+ for {
+ if err = operation(); err == nil {
+ return nil
+ }
+
+ if next = b.NextBackOff(); next == Stop {
+ return err
+ }
+
+ if notify != nil {
+ notify(err, next)
+ }
+
+ time.Sleep(next)
+ }
+}
--- /dev/null
+package backoff
+
+import (
+ "runtime"
+ "sync"
+ "time"
+)
+
+// Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff.
+//
+// Ticks will continue to arrive when the previous operation is still running,
+// so operations that take a while to fail could run in quick succession.
+type Ticker struct {
+ C <-chan time.Time
+ c chan time.Time
+ b BackOff
+ stop chan struct{}
+ stopOnce sync.Once
+}
+
+// NewTicker returns a new Ticker containing a channel that will send the time at times
+// specified by the BackOff argument. Ticker is guaranteed to tick at least once.
+// The channel is closed when Stop method is called or BackOff stops.
+func NewTicker(b BackOff) *Ticker {
+ c := make(chan time.Time)
+ t := &Ticker{
+ C: c,
+ c: c,
+ b: b,
+ stop: make(chan struct{}),
+ }
+ go t.run()
+ runtime.SetFinalizer(t, (*Ticker).Stop)
+ return t
+}
+
+// Stop turns off a ticker. After Stop, no more ticks will be sent.
+func (t *Ticker) Stop() {
+ t.stopOnce.Do(func() { close(t.stop) })
+}
+
+func (t *Ticker) run() {
+ c := t.c
+ defer close(c)
+ t.b.Reset()
+
+ // Ticker is guaranteed to tick at least once.
+ afterC := t.send(time.Now())
+
+ for {
+ if afterC == nil {
+ return
+ }
+
+ select {
+ case tick := <-afterC:
+ afterC = t.send(tick)
+ case <-t.stop:
+ t.c = nil // Prevent future ticks from being sent to the channel.
+ return
+ }
+ }
+}
+
+func (t *Ticker) send(tick time.Time) <-chan time.Time {
+ select {
+ case t.c <- tick:
+ case <-t.stop:
+ return nil
+ }
+
+ next := t.b.NextBackOff()
+ if next == Stop {
+ t.Stop()
+ return nil
+ }
+
+ return time.After(next)
+}
--- /dev/null
+Copyright (c) 2016 Caleb Spare
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--- /dev/null
+# xxhash
+
+[](https://godoc.org/github.com/cespare/xxhash)
+
+xxhash is a Go implementation of the 64-bit
+[xxHash](http://cyan4973.github.io/xxHash/) algorithm, XXH64. This is a
+high-quality hashing algorithm that is much faster than anything in the Go
+standard library.
+
+The API is very small, taking its cue from the other hashing packages in the
+standard library:
+
+ $ go doc github.com/cespare/xxhash !
+ package xxhash // import "github.com/cespare/xxhash"
+
+ Package xxhash implements the 64-bit variant of xxHash (XXH64) as described
+ at http://cyan4973.github.io/xxHash/.
+
+ func New() hash.Hash64
+ func Sum64(b []byte) uint64
+ func Sum64String(s string) uint64
+
+This implementation provides a fast pure-Go implementation and an even faster
+assembly implementation for amd64.
+
+## Benchmarks
+
+Here are some quick benchmarks comparing the pure-Go and assembly
+implementations of Sum64 against another popular Go XXH64 implementation,
+[github.com/OneOfOne/xxhash](https://github.com/OneOfOne/xxhash):
+
+| input size | OneOfOne | cespare (noasm) | cespare |
+| --- | --- | --- | --- |
+| 5 B | 438.34 MB/s | 596.40 MB/s | 711.11 MB/s |
+| 100 B | 3676.54 MB/s | 4301.40 MB/s | 4598.95 MB/s |
+| 4 KB | 8128.64 MB/s | 8840.83 MB/s | 10549.72 MB/s |
+| 10 MB | 7335.19 MB/s | 7736.64 MB/s | 9024.04 MB/s |
+
+## Projects using this package
+
+- [InfluxDB](https://github.com/influxdata/influxdb)
--- /dev/null
+// Package xxhash implements the 64-bit variant of xxHash (XXH64) as described
+// at http://cyan4973.github.io/xxHash/.
+package xxhash
+
+import (
+ "encoding/binary"
+ "hash"
+ "reflect"
+ "unsafe"
+)
+
+const (
+ prime1 uint64 = 11400714785074694791
+ prime2 uint64 = 14029467366897019727
+ prime3 uint64 = 1609587929392839161
+ prime4 uint64 = 9650029242287828579
+ prime5 uint64 = 2870177450012600261
+)
+
+// NOTE(caleb): I'm using both consts and vars of the primes. Using consts where
+// possible in the Go code is worth a small (but measurable) performance boost
+// by avoiding some MOVQs. Vars are needed for the asm and also are useful for
+// convenience in the Go code in a few places where we need to intentionally
+// avoid constant arithmetic (e.g., v1 := prime1 + prime2 fails because the
+// result overflows a uint64).
+var (
+ prime1v = prime1
+ prime2v = prime2
+ prime3v = prime3
+ prime4v = prime4
+ prime5v = prime5
+)
+
+// Sum64String computes the 64-bit xxHash digest of s.
+// It may be faster than Sum64([]byte(s)) by avoiding a copy.
+//
+// TODO(caleb): Consider removing this if an optimization is ever added to make
+// it unnecessary: https://golang.org/issue//2205.
+//
+// TODO(caleb): We still have a function call; we could instead write Go/asm
+// copies of Sum64 for strings to squeeze out a bit more speed.
+func Sum64String(s string) uint64 {
+ var b []byte
+ sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
+ bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
+ bh.Data = uintptr(unsafe.Pointer(sh.Data))
+ bh.Len = sh.Len
+ bh.Cap = sh.Len
+ return Sum64(b)
+}
+
+type xxh struct {
+ v1 uint64
+ v2 uint64
+ v3 uint64
+ v4 uint64
+ total int
+ mem [32]byte
+ n int // how much of mem is used
+}
+
+// New creates a new hash.Hash64 that implements the 64-bit xxHash algorithm.
+func New() hash.Hash64 {
+ var x xxh
+ x.Reset()
+ return &x
+}
+
+func (x *xxh) Reset() {
+ x.n = 0
+ x.total = 0
+ x.v1 = prime1v + prime2
+ x.v2 = prime2
+ x.v3 = 0
+ x.v4 = -prime1v
+}
+
+func (x *xxh) Size() int { return 8 }
+func (x *xxh) BlockSize() int { return 32 }
+
+// Write adds more data to x. It always returns len(b), nil.
+func (x *xxh) Write(b []byte) (n int, err error) {
+ n = len(b)
+ x.total += len(b)
+
+ if x.n+len(b) < 32 {
+ // This new data doesn't even fill the current block.
+ copy(x.mem[x.n:], b)
+ x.n += len(b)
+ return
+ }
+
+ if x.n > 0 {
+ // Finish off the partial block.
+ copy(x.mem[x.n:], b)
+ x.v1 = round(x.v1, u64(x.mem[0:8]))
+ x.v2 = round(x.v2, u64(x.mem[8:16]))
+ x.v3 = round(x.v3, u64(x.mem[16:24]))
+ x.v4 = round(x.v4, u64(x.mem[24:32]))
+ b = b[32-x.n:]
+ x.n = 0
+ }
+
+ if len(b) >= 32 {
+ // One or more full blocks left.
+ b = writeBlocks(x, b)
+ }
+
+ // Store any remaining partial block.
+ copy(x.mem[:], b)
+ x.n = len(b)
+
+ return
+}
+
+func (x *xxh) Sum(b []byte) []byte {
+ s := x.Sum64()
+ return append(
+ b,
+ byte(s>>56),
+ byte(s>>48),
+ byte(s>>40),
+ byte(s>>32),
+ byte(s>>24),
+ byte(s>>16),
+ byte(s>>8),
+ byte(s),
+ )
+}
+
+func (x *xxh) Sum64() uint64 {
+ var h uint64
+
+ if x.total >= 32 {
+ v1, v2, v3, v4 := x.v1, x.v2, x.v3, x.v4
+ h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4)
+ h = mergeRound(h, v1)
+ h = mergeRound(h, v2)
+ h = mergeRound(h, v3)
+ h = mergeRound(h, v4)
+ } else {
+ h = x.v3 + prime5
+ }
+
+ h += uint64(x.total)
+
+ i, end := 0, x.n
+ for ; i+8 <= end; i += 8 {
+ k1 := round(0, u64(x.mem[i:i+8]))
+ h ^= k1
+ h = rol27(h)*prime1 + prime4
+ }
+ if i+4 <= end {
+ h ^= uint64(u32(x.mem[i:i+4])) * prime1
+ h = rol23(h)*prime2 + prime3
+ i += 4
+ }
+ for i < end {
+ h ^= uint64(x.mem[i]) * prime5
+ h = rol11(h) * prime1
+ i++
+ }
+
+ h ^= h >> 33
+ h *= prime2
+ h ^= h >> 29
+ h *= prime3
+ h ^= h >> 32
+
+ return h
+}
+
+func u64(b []byte) uint64 { return binary.LittleEndian.Uint64(b) }
+func u32(b []byte) uint32 { return binary.LittleEndian.Uint32(b) }
+
+func round(acc, input uint64) uint64 {
+ acc += input * prime2
+ acc = rol31(acc)
+ acc *= prime1
+ return acc
+}
+
+func mergeRound(acc, val uint64) uint64 {
+ val = round(0, val)
+ acc ^= val
+ acc = acc*prime1 + prime4
+ return acc
+}
+
+// It's important for performance to get the rotates to actually compile to
+// ROLQs. gc will do this for us but only if rotate amount is a constant.
+//
+// TODO(caleb): In Go 1.9 a single function
+// rol(x uint64, k uint) uint64
+// should do instead. See https://golang.org/issue/18254.
+//
+// TODO(caleb): In Go 1.x (1.9?) consider using the new math/bits package to be more
+// explicit about things. See https://golang.org/issue/18616.
+
+func rol1(x uint64) uint64 { return (x << 1) | (x >> (64 - 1)) }
+func rol7(x uint64) uint64 { return (x << 7) | (x >> (64 - 7)) }
+func rol11(x uint64) uint64 { return (x << 11) | (x >> (64 - 11)) }
+func rol12(x uint64) uint64 { return (x << 12) | (x >> (64 - 12)) }
+func rol18(x uint64) uint64 { return (x << 18) | (x >> (64 - 18)) }
+func rol23(x uint64) uint64 { return (x << 23) | (x >> (64 - 23)) }
+func rol27(x uint64) uint64 { return (x << 27) | (x >> (64 - 27)) }
+func rol31(x uint64) uint64 { return (x << 31) | (x >> (64 - 31)) }
--- /dev/null
+// +build !appengine
+// +build gc
+// +build !noasm
+
+package xxhash
+
+// Sum64 computes the 64-bit xxHash digest of b.
+//
+//go:noescape
+func Sum64(b []byte) uint64
+
+func writeBlocks(x *xxh, b []byte) []byte
--- /dev/null
+// +build !appengine
+// +build gc
+// +build !noasm
+
+#include "textflag.h"
+
+// Register allocation:
+// AX h
+// CX pointer to advance through b
+// DX n
+// BX loop end
+// R8 v1, k1
+// R9 v2
+// R10 v3
+// R11 v4
+// R12 tmp
+// R13 prime1v
+// R14 prime2v
+// R15 prime4v
+
+// round reads from and advances the buffer pointer in CX.
+// It assumes that R13 has prime1v and R14 has prime2v.
+#define round(r) \
+ MOVQ (CX), R12 \
+ ADDQ $8, CX \
+ IMULQ R14, R12 \
+ ADDQ R12, r \
+ ROLQ $31, r \
+ IMULQ R13, r
+
+// mergeRound applies a merge round on the two registers acc and val.
+// It assumes that R13 has prime1v, R14 has prime2v, and R15 has prime4v.
+#define mergeRound(acc, val) \
+ IMULQ R14, val \
+ ROLQ $31, val \
+ IMULQ R13, val \
+ XORQ val, acc \
+ IMULQ R13, acc \
+ ADDQ R15, acc
+
+// func Sum64(b []byte) uint64
+TEXT ·Sum64(SB), NOSPLIT, $0-32
+ // Load fixed primes.
+ MOVQ ·prime1v(SB), R13
+ MOVQ ·prime2v(SB), R14
+ MOVQ ·prime4v(SB), R15
+
+ // Load slice.
+ MOVQ b_base+0(FP), CX
+ MOVQ b_len+8(FP), DX
+ LEAQ (CX)(DX*1), BX
+
+ // The first loop limit will be len(b)-32.
+ SUBQ $32, BX
+
+ // Check whether we have at least one block.
+ CMPQ DX, $32
+ JLT noBlocks
+
+ // Set up initial state (v1, v2, v3, v4).
+ MOVQ R13, R8
+ ADDQ R14, R8
+ MOVQ R14, R9
+ XORQ R10, R10
+ XORQ R11, R11
+ SUBQ R13, R11
+
+ // Loop until CX > BX.
+blockLoop:
+ round(R8)
+ round(R9)
+ round(R10)
+ round(R11)
+
+ CMPQ CX, BX
+ JLE blockLoop
+
+ MOVQ R8, AX
+ ROLQ $1, AX
+ MOVQ R9, R12
+ ROLQ $7, R12
+ ADDQ R12, AX
+ MOVQ R10, R12
+ ROLQ $12, R12
+ ADDQ R12, AX
+ MOVQ R11, R12
+ ROLQ $18, R12
+ ADDQ R12, AX
+
+ mergeRound(AX, R8)
+ mergeRound(AX, R9)
+ mergeRound(AX, R10)
+ mergeRound(AX, R11)
+
+ JMP afterBlocks
+
+noBlocks:
+ MOVQ ·prime5v(SB), AX
+
+afterBlocks:
+ ADDQ DX, AX
+
+ // Right now BX has len(b)-32, and we want to loop until CX > len(b)-8.
+ ADDQ $24, BX
+
+ CMPQ CX, BX
+ JG fourByte
+
+wordLoop:
+ // Calculate k1.
+ MOVQ (CX), R8
+ ADDQ $8, CX
+ IMULQ R14, R8
+ ROLQ $31, R8
+ IMULQ R13, R8
+
+ XORQ R8, AX
+ ROLQ $27, AX
+ IMULQ R13, AX
+ ADDQ R15, AX
+
+ CMPQ CX, BX
+ JLE wordLoop
+
+fourByte:
+ ADDQ $4, BX
+ CMPQ CX, BX
+ JG singles
+
+ MOVL (CX), R8
+ ADDQ $4, CX
+ IMULQ R13, R8
+ XORQ R8, AX
+
+ ROLQ $23, AX
+ IMULQ R14, AX
+ ADDQ ·prime3v(SB), AX
+
+singles:
+ ADDQ $4, BX
+ CMPQ CX, BX
+ JGE finalize
+
+singlesLoop:
+ MOVBQZX (CX), R12
+ ADDQ $1, CX
+ IMULQ ·prime5v(SB), R12
+ XORQ R12, AX
+
+ ROLQ $11, AX
+ IMULQ R13, AX
+
+ CMPQ CX, BX
+ JL singlesLoop
+
+finalize:
+ MOVQ AX, R12
+ SHRQ $33, R12
+ XORQ R12, AX
+ IMULQ R14, AX
+ MOVQ AX, R12
+ SHRQ $29, R12
+ XORQ R12, AX
+ IMULQ ·prime3v(SB), AX
+ MOVQ AX, R12
+ SHRQ $32, R12
+ XORQ R12, AX
+
+ MOVQ AX, ret+24(FP)
+ RET
+
+// writeBlocks uses the same registers as above except that it uses AX to store
+// the x pointer.
+
+// func writeBlocks(x *xxh, b []byte) []byte
+TEXT ·writeBlocks(SB), NOSPLIT, $0-56
+ // Load fixed primes needed for round.
+ MOVQ ·prime1v(SB), R13
+ MOVQ ·prime2v(SB), R14
+
+ // Load slice.
+ MOVQ b_base+8(FP), CX
+ MOVQ CX, ret_base+32(FP) // initialize return base pointer; see NOTE below
+ MOVQ b_len+16(FP), DX
+ LEAQ (CX)(DX*1), BX
+ SUBQ $32, BX
+
+ // Load vN from x.
+ MOVQ x+0(FP), AX
+ MOVQ 0(AX), R8 // v1
+ MOVQ 8(AX), R9 // v2
+ MOVQ 16(AX), R10 // v3
+ MOVQ 24(AX), R11 // v4
+
+ // We don't need to check the loop condition here; this function is
+ // always called with at least one block of data to process.
+blockLoop:
+ round(R8)
+ round(R9)
+ round(R10)
+ round(R11)
+
+ CMPQ CX, BX
+ JLE blockLoop
+
+ // Copy vN back to x.
+ MOVQ R8, 0(AX)
+ MOVQ R9, 8(AX)
+ MOVQ R10, 16(AX)
+ MOVQ R11, 24(AX)
+
+ // Construct return slice.
+ // NOTE: It's important that we don't construct a slice that has a base
+ // pointer off the end of the original slice, as in Go 1.7+ this will
+ // cause runtime crashes. (See discussion in, for example,
+ // https://github.com/golang/go/issues/16772.)
+ // Therefore, we calculate the length/cap first, and if they're zero, we
+ // keep the old base. This is what the compiler does as well if you
+ // write code like
+ // b = b[len(b):]
+
+ // New length is 32 - (CX - BX) -> BX+32 - CX.
+ ADDQ $32, BX
+ SUBQ CX, BX
+ JZ afterSetBase
+
+ MOVQ CX, ret_base+32(FP)
+
+afterSetBase:
+ MOVQ BX, ret_len+40(FP)
+ MOVQ BX, ret_cap+48(FP) // set cap == len
+
+ RET
--- /dev/null
+// +build !amd64 appengine !gc noasm
+
+package xxhash
+
+// Sum64 computes the 64-bit xxHash digest of b.
+func Sum64(b []byte) uint64 {
+ // A simpler version would be
+ // x := New()
+ // x.Write(b)
+ // return x.Sum64()
+ // but this is faster, particularly for small inputs.
+
+ n := len(b)
+ var h uint64
+
+ if n >= 32 {
+ v1 := prime1v + prime2
+ v2 := prime2
+ v3 := uint64(0)
+ v4 := -prime1v
+ for len(b) >= 32 {
+ v1 = round(v1, u64(b[0:8:len(b)]))
+ v2 = round(v2, u64(b[8:16:len(b)]))
+ v3 = round(v3, u64(b[16:24:len(b)]))
+ v4 = round(v4, u64(b[24:32:len(b)]))
+ b = b[32:len(b):len(b)]
+ }
+ h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4)
+ h = mergeRound(h, v1)
+ h = mergeRound(h, v2)
+ h = mergeRound(h, v3)
+ h = mergeRound(h, v4)
+ } else {
+ h = prime5
+ }
+
+ h += uint64(n)
+
+ i, end := 0, len(b)
+ for ; i+8 <= end; i += 8 {
+ k1 := round(0, u64(b[i:i+8:len(b)]))
+ h ^= k1
+ h = rol27(h)*prime1 + prime4
+ }
+ if i+4 <= end {
+ h ^= uint64(u32(b[i:i+4:len(b)])) * prime1
+ h = rol23(h)*prime2 + prime3
+ i += 4
+ }
+ for ; i < end; i++ {
+ h ^= uint64(b[i]) * prime5
+ h = rol11(h) * prime1
+ }
+
+ h ^= h >> 33
+ h *= prime2
+ h ^= h >> 29
+ h *= prime3
+ h ^= h >> 32
+
+ return h
+}
+
+func writeBlocks(x *xxh, b []byte) []byte {
+ v1, v2, v3, v4 := x.v1, x.v2, x.v3, x.v4
+ for len(b) >= 32 {
+ v1 = round(v1, u64(b[0:8:len(b)]))
+ v2 = round(v2, u64(b[8:16:len(b)]))
+ v3 = round(v3, u64(b[16:24:len(b)]))
+ v4 = round(v4, u64(b[24:32:len(b)]))
+ b = b[32:len(b):len(b)]
+ }
+ x.v1, x.v2, x.v3, x.v4 = v1, v2, v3, v4
+ return b
+}
--- /dev/null
+ISC License
+
+Copyright (c) 2012-2016 Dave Collins <dave@davec.name>
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
--- /dev/null
+// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// NOTE: Due to the following build constraints, this file will only be compiled
+// when the code is not running on Google App Engine, compiled by GopherJS, and
+// "-tags safe" is not added to the go build command line. The "disableunsafe"
+// tag is deprecated and thus should not be used.
+// +build !js,!appengine,!safe,!disableunsafe
+
+package spew
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+const (
+ // UnsafeDisabled is a build-time constant which specifies whether or
+ // not access to the unsafe package is available.
+ UnsafeDisabled = false
+
+ // ptrSize is the size of a pointer on the current arch.
+ ptrSize = unsafe.Sizeof((*byte)(nil))
+)
+
+var (
+ // offsetPtr, offsetScalar, and offsetFlag are the offsets for the
+ // internal reflect.Value fields. These values are valid before golang
+ // commit ecccf07e7f9d which changed the format. The are also valid
+ // after commit 82f48826c6c7 which changed the format again to mirror
+ // the original format. Code in the init function updates these offsets
+ // as necessary.
+ offsetPtr = uintptr(ptrSize)
+ offsetScalar = uintptr(0)
+ offsetFlag = uintptr(ptrSize * 2)
+
+ // flagKindWidth and flagKindShift indicate various bits that the
+ // reflect package uses internally to track kind information.
+ //
+ // flagRO indicates whether or not the value field of a reflect.Value is
+ // read-only.
+ //
+ // flagIndir indicates whether the value field of a reflect.Value is
+ // the actual data or a pointer to the data.
+ //
+ // These values are valid before golang commit 90a7c3c86944 which
+ // changed their positions. Code in the init function updates these
+ // flags as necessary.
+ flagKindWidth = uintptr(5)
+ flagKindShift = uintptr(flagKindWidth - 1)
+ flagRO = uintptr(1 << 0)
+ flagIndir = uintptr(1 << 1)
+)
+
+func init() {
+ // Older versions of reflect.Value stored small integers directly in the
+ // ptr field (which is named val in the older versions). Versions
+ // between commits ecccf07e7f9d and 82f48826c6c7 added a new field named
+ // scalar for this purpose which unfortunately came before the flag
+ // field, so the offset of the flag field is different for those
+ // versions.
+ //
+ // This code constructs a new reflect.Value from a known small integer
+ // and checks if the size of the reflect.Value struct indicates it has
+ // the scalar field. When it does, the offsets are updated accordingly.
+ vv := reflect.ValueOf(0xf00)
+ if unsafe.Sizeof(vv) == (ptrSize * 4) {
+ offsetScalar = ptrSize * 2
+ offsetFlag = ptrSize * 3
+ }
+
+ // Commit 90a7c3c86944 changed the flag positions such that the low
+ // order bits are the kind. This code extracts the kind from the flags
+ // field and ensures it's the correct type. When it's not, the flag
+ // order has been changed to the newer format, so the flags are updated
+ // accordingly.
+ upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag)
+ upfv := *(*uintptr)(upf)
+ flagKindMask := uintptr((1<<flagKindWidth - 1) << flagKindShift)
+ if (upfv&flagKindMask)>>flagKindShift != uintptr(reflect.Int) {
+ flagKindShift = 0
+ flagRO = 1 << 5
+ flagIndir = 1 << 6
+
+ // Commit adf9b30e5594 modified the flags to separate the
+ // flagRO flag into two bits which specifies whether or not the
+ // field is embedded. This causes flagIndir to move over a bit
+ // and means that flagRO is the combination of either of the
+ // original flagRO bit and the new bit.
+ //
+ // This code detects the change by extracting what used to be
+ // the indirect bit to ensure it's set. When it's not, the flag
+ // order has been changed to the newer format, so the flags are
+ // updated accordingly.
+ if upfv&flagIndir == 0 {
+ flagRO = 3 << 5
+ flagIndir = 1 << 7
+ }
+ }
+}
+
+// unsafeReflectValue converts the passed reflect.Value into a one that bypasses
+// the typical safety restrictions preventing access to unaddressable and
+// unexported data. It works by digging the raw pointer to the underlying
+// value out of the protected value and generating a new unprotected (unsafe)
+// reflect.Value to it.
+//
+// This allows us to check for implementations of the Stringer and error
+// interfaces to be used for pretty printing ordinarily unaddressable and
+// inaccessible values such as unexported struct fields.
+func unsafeReflectValue(v reflect.Value) (rv reflect.Value) {
+ indirects := 1
+ vt := v.Type()
+ upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr)
+ rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag))
+ if rvf&flagIndir != 0 {
+ vt = reflect.PtrTo(v.Type())
+ indirects++
+ } else if offsetScalar != 0 {
+ // The value is in the scalar field when it's not one of the
+ // reference types.
+ switch vt.Kind() {
+ case reflect.Uintptr:
+ case reflect.Chan:
+ case reflect.Func:
+ case reflect.Map:
+ case reflect.Ptr:
+ case reflect.UnsafePointer:
+ default:
+ upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) +
+ offsetScalar)
+ }
+ }
+
+ pv := reflect.NewAt(vt, upv)
+ rv = pv
+ for i := 0; i < indirects; i++ {
+ rv = rv.Elem()
+ }
+ return rv
+}
--- /dev/null
+// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// NOTE: Due to the following build constraints, this file will only be compiled
+// when the code is running on Google App Engine, compiled by GopherJS, or
+// "-tags safe" is added to the go build command line. The "disableunsafe"
+// tag is deprecated and thus should not be used.
+// +build js appengine safe disableunsafe
+
+package spew
+
+import "reflect"
+
+const (
+ // UnsafeDisabled is a build-time constant which specifies whether or
+ // not access to the unsafe package is available.
+ UnsafeDisabled = true
+)
+
+// unsafeReflectValue typically converts the passed reflect.Value into a one
+// that bypasses the typical safety restrictions preventing access to
+// unaddressable and unexported data. However, doing this relies on access to
+// the unsafe package. This is a stub version which simply returns the passed
+// reflect.Value when the unsafe package is not available.
+func unsafeReflectValue(v reflect.Value) reflect.Value {
+ return v
+}
--- /dev/null
+/*
+ * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package spew
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "reflect"
+ "sort"
+ "strconv"
+)
+
+// Some constants in the form of bytes to avoid string overhead. This mirrors
+// the technique used in the fmt package.
+var (
+ panicBytes = []byte("(PANIC=")
+ plusBytes = []byte("+")
+ iBytes = []byte("i")
+ trueBytes = []byte("true")
+ falseBytes = []byte("false")
+ interfaceBytes = []byte("(interface {})")
+ commaNewlineBytes = []byte(",\n")
+ newlineBytes = []byte("\n")
+ openBraceBytes = []byte("{")
+ openBraceNewlineBytes = []byte("{\n")
+ closeBraceBytes = []byte("}")
+ asteriskBytes = []byte("*")
+ colonBytes = []byte(":")
+ colonSpaceBytes = []byte(": ")
+ openParenBytes = []byte("(")
+ closeParenBytes = []byte(")")
+ spaceBytes = []byte(" ")
+ pointerChainBytes = []byte("->")
+ nilAngleBytes = []byte("<nil>")
+ maxNewlineBytes = []byte("<max depth reached>\n")
+ maxShortBytes = []byte("<max>")
+ circularBytes = []byte("<already shown>")
+ circularShortBytes = []byte("<shown>")
+ invalidAngleBytes = []byte("<invalid>")
+ openBracketBytes = []byte("[")
+ closeBracketBytes = []byte("]")
+ percentBytes = []byte("%")
+ precisionBytes = []byte(".")
+ openAngleBytes = []byte("<")
+ closeAngleBytes = []byte(">")
+ openMapBytes = []byte("map[")
+ closeMapBytes = []byte("]")
+ lenEqualsBytes = []byte("len=")
+ capEqualsBytes = []byte("cap=")
+)
+
+// hexDigits is used to map a decimal value to a hex digit.
+var hexDigits = "0123456789abcdef"
+
+// catchPanic handles any panics that might occur during the handleMethods
+// calls.
+func catchPanic(w io.Writer, v reflect.Value) {
+ if err := recover(); err != nil {
+ w.Write(panicBytes)
+ fmt.Fprintf(w, "%v", err)
+ w.Write(closeParenBytes)
+ }
+}
+
+// handleMethods attempts to call the Error and String methods on the underlying
+// type the passed reflect.Value represents and outputes the result to Writer w.
+//
+// It handles panics in any called methods by catching and displaying the error
+// as the formatted value.
+func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) {
+ // We need an interface to check if the type implements the error or
+ // Stringer interface. However, the reflect package won't give us an
+ // interface on certain things like unexported struct fields in order
+ // to enforce visibility rules. We use unsafe, when it's available,
+ // to bypass these restrictions since this package does not mutate the
+ // values.
+ if !v.CanInterface() {
+ if UnsafeDisabled {
+ return false
+ }
+
+ v = unsafeReflectValue(v)
+ }
+
+ // Choose whether or not to do error and Stringer interface lookups against
+ // the base type or a pointer to the base type depending on settings.
+ // Technically calling one of these methods with a pointer receiver can
+ // mutate the value, however, types which choose to satisify an error or
+ // Stringer interface with a pointer receiver should not be mutating their
+ // state inside these interface methods.
+ if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() {
+ v = unsafeReflectValue(v)
+ }
+ if v.CanAddr() {
+ v = v.Addr()
+ }
+
+ // Is it an error or Stringer?
+ switch iface := v.Interface().(type) {
+ case error:
+ defer catchPanic(w, v)
+ if cs.ContinueOnMethod {
+ w.Write(openParenBytes)
+ w.Write([]byte(iface.Error()))
+ w.Write(closeParenBytes)
+ w.Write(spaceBytes)
+ return false
+ }
+
+ w.Write([]byte(iface.Error()))
+ return true
+
+ case fmt.Stringer:
+ defer catchPanic(w, v)
+ if cs.ContinueOnMethod {
+ w.Write(openParenBytes)
+ w.Write([]byte(iface.String()))
+ w.Write(closeParenBytes)
+ w.Write(spaceBytes)
+ return false
+ }
+ w.Write([]byte(iface.String()))
+ return true
+ }
+ return false
+}
+
+// printBool outputs a boolean value as true or false to Writer w.
+func printBool(w io.Writer, val bool) {
+ if val {
+ w.Write(trueBytes)
+ } else {
+ w.Write(falseBytes)
+ }
+}
+
+// printInt outputs a signed integer value to Writer w.
+func printInt(w io.Writer, val int64, base int) {
+ w.Write([]byte(strconv.FormatInt(val, base)))
+}
+
+// printUint outputs an unsigned integer value to Writer w.
+func printUint(w io.Writer, val uint64, base int) {
+ w.Write([]byte(strconv.FormatUint(val, base)))
+}
+
+// printFloat outputs a floating point value using the specified precision,
+// which is expected to be 32 or 64bit, to Writer w.
+func printFloat(w io.Writer, val float64, precision int) {
+ w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision)))
+}
+
+// printComplex outputs a complex value using the specified float precision
+// for the real and imaginary parts to Writer w.
+func printComplex(w io.Writer, c complex128, floatPrecision int) {
+ r := real(c)
+ w.Write(openParenBytes)
+ w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision)))
+ i := imag(c)
+ if i >= 0 {
+ w.Write(plusBytes)
+ }
+ w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision)))
+ w.Write(iBytes)
+ w.Write(closeParenBytes)
+}
+
+// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x'
+// prefix to Writer w.
+func printHexPtr(w io.Writer, p uintptr) {
+ // Null pointer.
+ num := uint64(p)
+ if num == 0 {
+ w.Write(nilAngleBytes)
+ return
+ }
+
+ // Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix
+ buf := make([]byte, 18)
+
+ // It's simpler to construct the hex string right to left.
+ base := uint64(16)
+ i := len(buf) - 1
+ for num >= base {
+ buf[i] = hexDigits[num%base]
+ num /= base
+ i--
+ }
+ buf[i] = hexDigits[num]
+
+ // Add '0x' prefix.
+ i--
+ buf[i] = 'x'
+ i--
+ buf[i] = '0'
+
+ // Strip unused leading bytes.
+ buf = buf[i:]
+ w.Write(buf)
+}
+
+// valuesSorter implements sort.Interface to allow a slice of reflect.Value
+// elements to be sorted.
+type valuesSorter struct {
+ values []reflect.Value
+ strings []string // either nil or same len and values
+ cs *ConfigState
+}
+
+// newValuesSorter initializes a valuesSorter instance, which holds a set of
+// surrogate keys on which the data should be sorted. It uses flags in
+// ConfigState to decide if and how to populate those surrogate keys.
+func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface {
+ vs := &valuesSorter{values: values, cs: cs}
+ if canSortSimply(vs.values[0].Kind()) {
+ return vs
+ }
+ if !cs.DisableMethods {
+ vs.strings = make([]string, len(values))
+ for i := range vs.values {
+ b := bytes.Buffer{}
+ if !handleMethods(cs, &b, vs.values[i]) {
+ vs.strings = nil
+ break
+ }
+ vs.strings[i] = b.String()
+ }
+ }
+ if vs.strings == nil && cs.SpewKeys {
+ vs.strings = make([]string, len(values))
+ for i := range vs.values {
+ vs.strings[i] = Sprintf("%#v", vs.values[i].Interface())
+ }
+ }
+ return vs
+}
+
+// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted
+// directly, or whether it should be considered for sorting by surrogate keys
+// (if the ConfigState allows it).
+func canSortSimply(kind reflect.Kind) bool {
+ // This switch parallels valueSortLess, except for the default case.
+ switch kind {
+ case reflect.Bool:
+ return true
+ case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
+ return true
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
+ return true
+ case reflect.Float32, reflect.Float64:
+ return true
+ case reflect.String:
+ return true
+ case reflect.Uintptr:
+ return true
+ case reflect.Array:
+ return true
+ }
+ return false
+}
+
+// Len returns the number of values in the slice. It is part of the
+// sort.Interface implementation.
+func (s *valuesSorter) Len() int {
+ return len(s.values)
+}
+
+// Swap swaps the values at the passed indices. It is part of the
+// sort.Interface implementation.
+func (s *valuesSorter) Swap(i, j int) {
+ s.values[i], s.values[j] = s.values[j], s.values[i]
+ if s.strings != nil {
+ s.strings[i], s.strings[j] = s.strings[j], s.strings[i]
+ }
+}
+
+// valueSortLess returns whether the first value should sort before the second
+// value. It is used by valueSorter.Less as part of the sort.Interface
+// implementation.
+func valueSortLess(a, b reflect.Value) bool {
+ switch a.Kind() {
+ case reflect.Bool:
+ return !a.Bool() && b.Bool()
+ case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
+ return a.Int() < b.Int()
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
+ return a.Uint() < b.Uint()
+ case reflect.Float32, reflect.Float64:
+ return a.Float() < b.Float()
+ case reflect.String:
+ return a.String() < b.String()
+ case reflect.Uintptr:
+ return a.Uint() < b.Uint()
+ case reflect.Array:
+ // Compare the contents of both arrays.
+ l := a.Len()
+ for i := 0; i < l; i++ {
+ av := a.Index(i)
+ bv := b.Index(i)
+ if av.Interface() == bv.Interface() {
+ continue
+ }
+ return valueSortLess(av, bv)
+ }
+ }
+ return a.String() < b.String()
+}
+
+// Less returns whether the value at index i should sort before the
+// value at index j. It is part of the sort.Interface implementation.
+func (s *valuesSorter) Less(i, j int) bool {
+ if s.strings == nil {
+ return valueSortLess(s.values[i], s.values[j])
+ }
+ return s.strings[i] < s.strings[j]
+}
+
+// sortValues is a sort function that handles both native types and any type that
+// can be converted to error or Stringer. Other inputs are sorted according to
+// their Value.String() value to ensure display stability.
+func sortValues(values []reflect.Value, cs *ConfigState) {
+ if len(values) == 0 {
+ return
+ }
+ sort.Sort(newValuesSorter(values, cs))
+}
--- /dev/null
+/*
+ * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package spew
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "os"
+)
+
+// ConfigState houses the configuration options used by spew to format and
+// display values. There is a global instance, Config, that is used to control
+// all top-level Formatter and Dump functionality. Each ConfigState instance
+// provides methods equivalent to the top-level functions.
+//
+// The zero value for ConfigState provides no indentation. You would typically
+// want to set it to a space or a tab.
+//
+// Alternatively, you can use NewDefaultConfig to get a ConfigState instance
+// with default settings. See the documentation of NewDefaultConfig for default
+// values.
+type ConfigState struct {
+ // Indent specifies the string to use for each indentation level. The
+ // global config instance that all top-level functions use set this to a
+ // single space by default. If you would like more indentation, you might
+ // set this to a tab with "\t" or perhaps two spaces with " ".
+ Indent string
+
+ // MaxDepth controls the maximum number of levels to descend into nested
+ // data structures. The default, 0, means there is no limit.
+ //
+ // NOTE: Circular data structures are properly detected, so it is not
+ // necessary to set this value unless you specifically want to limit deeply
+ // nested data structures.
+ MaxDepth int
+
+ // DisableMethods specifies whether or not error and Stringer interfaces are
+ // invoked for types that implement them.
+ DisableMethods bool
+
+ // DisablePointerMethods specifies whether or not to check for and invoke
+ // error and Stringer interfaces on types which only accept a pointer
+ // receiver when the current type is not a pointer.
+ //
+ // NOTE: This might be an unsafe action since calling one of these methods
+ // with a pointer receiver could technically mutate the value, however,
+ // in practice, types which choose to satisify an error or Stringer
+ // interface with a pointer receiver should not be mutating their state
+ // inside these interface methods. As a result, this option relies on
+ // access to the unsafe package, so it will not have any effect when
+ // running in environments without access to the unsafe package such as
+ // Google App Engine or with the "safe" build tag specified.
+ DisablePointerMethods bool
+
+ // DisablePointerAddresses specifies whether to disable the printing of
+ // pointer addresses. This is useful when diffing data structures in tests.
+ DisablePointerAddresses bool
+
+ // DisableCapacities specifies whether to disable the printing of capacities
+ // for arrays, slices, maps and channels. This is useful when diffing
+ // data structures in tests.
+ DisableCapacities bool
+
+ // ContinueOnMethod specifies whether or not recursion should continue once
+ // a custom error or Stringer interface is invoked. The default, false,
+ // means it will print the results of invoking the custom error or Stringer
+ // interface and return immediately instead of continuing to recurse into
+ // the internals of the data type.
+ //
+ // NOTE: This flag does not have any effect if method invocation is disabled
+ // via the DisableMethods or DisablePointerMethods options.
+ ContinueOnMethod bool
+
+ // SortKeys specifies map keys should be sorted before being printed. Use
+ // this to have a more deterministic, diffable output. Note that only
+ // native types (bool, int, uint, floats, uintptr and string) and types
+ // that support the error or Stringer interfaces (if methods are
+ // enabled) are supported, with other types sorted according to the
+ // reflect.Value.String() output which guarantees display stability.
+ SortKeys bool
+
+ // SpewKeys specifies that, as a last resort attempt, map keys should
+ // be spewed to strings and sorted by those strings. This is only
+ // considered if SortKeys is true.
+ SpewKeys bool
+}
+
+// Config is the active configuration of the top-level functions.
+// The configuration can be changed by modifying the contents of spew.Config.
+var Config = ConfigState{Indent: " "}
+
+// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter. It returns
+// the formatted string as a value that satisfies error. See NewFormatter
+// for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) {
+ return fmt.Errorf(format, c.convertArgs(a)...)
+}
+
+// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter. It returns
+// the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
+ return fmt.Fprint(w, c.convertArgs(a)...)
+}
+
+// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter. It returns
+// the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
+ return fmt.Fprintf(w, format, c.convertArgs(a)...)
+}
+
+// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
+// passed with a Formatter interface returned by c.NewFormatter. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
+ return fmt.Fprintln(w, c.convertArgs(a)...)
+}
+
+// Print is a wrapper for fmt.Print that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter. It returns
+// the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Print(c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Print(a ...interface{}) (n int, err error) {
+ return fmt.Print(c.convertArgs(a)...)
+}
+
+// Printf is a wrapper for fmt.Printf that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter. It returns
+// the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) {
+ return fmt.Printf(format, c.convertArgs(a)...)
+}
+
+// Println is a wrapper for fmt.Println that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter. It returns
+// the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Println(c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Println(a ...interface{}) (n int, err error) {
+ return fmt.Println(c.convertArgs(a)...)
+}
+
+// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter. It returns
+// the resulting string. See NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Sprint(a ...interface{}) string {
+ return fmt.Sprint(c.convertArgs(a)...)
+}
+
+// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter. It returns
+// the resulting string. See NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Sprintf(format string, a ...interface{}) string {
+ return fmt.Sprintf(format, c.convertArgs(a)...)
+}
+
+// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
+// were passed with a Formatter interface returned by c.NewFormatter. It
+// returns the resulting string. See NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Sprintln(a ...interface{}) string {
+ return fmt.Sprintln(c.convertArgs(a)...)
+}
+
+/*
+NewFormatter returns a custom formatter that satisfies the fmt.Formatter
+interface. As a result, it integrates cleanly with standard fmt package
+printing functions. The formatter is useful for inline printing of smaller data
+types similar to the standard %v format specifier.
+
+The custom formatter only responds to the %v (most compact), %+v (adds pointer
+addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb
+combinations. Any other verbs such as %x and %q will be sent to the the
+standard fmt package for formatting. In addition, the custom formatter ignores
+the width and precision arguments (however they will still work on the format
+specifiers not handled by the custom formatter).
+
+Typically this function shouldn't be called directly. It is much easier to make
+use of the custom formatter by calling one of the convenience functions such as
+c.Printf, c.Println, or c.Printf.
+*/
+func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter {
+ return newFormatter(c, v)
+}
+
+// Fdump formats and displays the passed arguments to io.Writer w. It formats
+// exactly the same as Dump.
+func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) {
+ fdump(c, w, a...)
+}
+
+/*
+Dump displays the passed parameters to standard out with newlines, customizable
+indentation, and additional debug information such as complete types and all
+pointer addresses used to indirect to the final value. It provides the
+following features over the built-in printing facilities provided by the fmt
+package:
+
+ * Pointers are dereferenced and followed
+ * Circular data structures are detected and handled properly
+ * Custom Stringer/error interfaces are optionally invoked, including
+ on unexported types
+ * Custom types which only implement the Stringer/error interfaces via
+ a pointer receiver are optionally invoked when passing non-pointer
+ variables
+ * Byte arrays and slices are dumped like the hexdump -C command which
+ includes offsets, byte values in hex, and ASCII output
+
+The configuration options are controlled by modifying the public members
+of c. See ConfigState for options documentation.
+
+See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
+get the formatted result as a string.
+*/
+func (c *ConfigState) Dump(a ...interface{}) {
+ fdump(c, os.Stdout, a...)
+}
+
+// Sdump returns a string with the passed arguments formatted exactly the same
+// as Dump.
+func (c *ConfigState) Sdump(a ...interface{}) string {
+ var buf bytes.Buffer
+ fdump(c, &buf, a...)
+ return buf.String()
+}
+
+// convertArgs accepts a slice of arguments and returns a slice of the same
+// length with each argument converted to a spew Formatter interface using
+// the ConfigState associated with s.
+func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) {
+ formatters = make([]interface{}, len(args))
+ for index, arg := range args {
+ formatters[index] = newFormatter(c, arg)
+ }
+ return formatters
+}
+
+// NewDefaultConfig returns a ConfigState with the following default settings.
+//
+// Indent: " "
+// MaxDepth: 0
+// DisableMethods: false
+// DisablePointerMethods: false
+// ContinueOnMethod: false
+// SortKeys: false
+func NewDefaultConfig() *ConfigState {
+ return &ConfigState{Indent: " "}
+}
--- /dev/null
+/*
+ * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+Package spew implements a deep pretty printer for Go data structures to aid in
+debugging.
+
+A quick overview of the additional features spew provides over the built-in
+printing facilities for Go data types are as follows:
+
+ * Pointers are dereferenced and followed
+ * Circular data structures are detected and handled properly
+ * Custom Stringer/error interfaces are optionally invoked, including
+ on unexported types
+ * Custom types which only implement the Stringer/error interfaces via
+ a pointer receiver are optionally invoked when passing non-pointer
+ variables
+ * Byte arrays and slices are dumped like the hexdump -C command which
+ includes offsets, byte values in hex, and ASCII output (only when using
+ Dump style)
+
+There are two different approaches spew allows for dumping Go data structures:
+
+ * Dump style which prints with newlines, customizable indentation,
+ and additional debug information such as types and all pointer addresses
+ used to indirect to the final value
+ * A custom Formatter interface that integrates cleanly with the standard fmt
+ package and replaces %v, %+v, %#v, and %#+v to provide inline printing
+ similar to the default %v while providing the additional functionality
+ outlined above and passing unsupported format verbs such as %x and %q
+ along to fmt
+
+Quick Start
+
+This section demonstrates how to quickly get started with spew. See the
+sections below for further details on formatting and configuration options.
+
+To dump a variable with full newlines, indentation, type, and pointer
+information use Dump, Fdump, or Sdump:
+ spew.Dump(myVar1, myVar2, ...)
+ spew.Fdump(someWriter, myVar1, myVar2, ...)
+ str := spew.Sdump(myVar1, myVar2, ...)
+
+Alternatively, if you would prefer to use format strings with a compacted inline
+printing style, use the convenience wrappers Printf, Fprintf, etc with
+%v (most compact), %+v (adds pointer addresses), %#v (adds types), or
+%#+v (adds types and pointer addresses):
+ spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
+ spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
+ spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
+ spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
+
+Configuration Options
+
+Configuration of spew is handled by fields in the ConfigState type. For
+convenience, all of the top-level functions use a global state available
+via the spew.Config global.
+
+It is also possible to create a ConfigState instance that provides methods
+equivalent to the top-level functions. This allows concurrent configuration
+options. See the ConfigState documentation for more details.
+
+The following configuration options are available:
+ * Indent
+ String to use for each indentation level for Dump functions.
+ It is a single space by default. A popular alternative is "\t".
+
+ * MaxDepth
+ Maximum number of levels to descend into nested data structures.
+ There is no limit by default.
+
+ * DisableMethods
+ Disables invocation of error and Stringer interface methods.
+ Method invocation is enabled by default.
+
+ * DisablePointerMethods
+ Disables invocation of error and Stringer interface methods on types
+ which only accept pointer receivers from non-pointer variables.
+ Pointer method invocation is enabled by default.
+
+ * DisablePointerAddresses
+ DisablePointerAddresses specifies whether to disable the printing of
+ pointer addresses. This is useful when diffing data structures in tests.
+
+ * DisableCapacities
+ DisableCapacities specifies whether to disable the printing of
+ capacities for arrays, slices, maps and channels. This is useful when
+ diffing data structures in tests.
+
+ * ContinueOnMethod
+ Enables recursion into types after invoking error and Stringer interface
+ methods. Recursion after method invocation is disabled by default.
+
+ * SortKeys
+ Specifies map keys should be sorted before being printed. Use
+ this to have a more deterministic, diffable output. Note that
+ only native types (bool, int, uint, floats, uintptr and string)
+ and types which implement error or Stringer interfaces are
+ supported with other types sorted according to the
+ reflect.Value.String() output which guarantees display
+ stability. Natural map order is used by default.
+
+ * SpewKeys
+ Specifies that, as a last resort attempt, map keys should be
+ spewed to strings and sorted by those strings. This is only
+ considered if SortKeys is true.
+
+Dump Usage
+
+Simply call spew.Dump with a list of variables you want to dump:
+
+ spew.Dump(myVar1, myVar2, ...)
+
+You may also call spew.Fdump if you would prefer to output to an arbitrary
+io.Writer. For example, to dump to standard error:
+
+ spew.Fdump(os.Stderr, myVar1, myVar2, ...)
+
+A third option is to call spew.Sdump to get the formatted output as a string:
+
+ str := spew.Sdump(myVar1, myVar2, ...)
+
+Sample Dump Output
+
+See the Dump example for details on the setup of the types and variables being
+shown here.
+
+ (main.Foo) {
+ unexportedField: (*main.Bar)(0xf84002e210)({
+ flag: (main.Flag) flagTwo,
+ data: (uintptr) <nil>
+ }),
+ ExportedField: (map[interface {}]interface {}) (len=1) {
+ (string) (len=3) "one": (bool) true
+ }
+ }
+
+Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C
+command as shown.
+ ([]uint8) (len=32 cap=32) {
+ 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... |
+ 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0|
+ 00000020 31 32 |12|
+ }
+
+Custom Formatter
+
+Spew provides a custom formatter that implements the fmt.Formatter interface
+so that it integrates cleanly with standard fmt package printing functions. The
+formatter is useful for inline printing of smaller data types similar to the
+standard %v format specifier.
+
+The custom formatter only responds to the %v (most compact), %+v (adds pointer
+addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
+combinations. Any other verbs such as %x and %q will be sent to the the
+standard fmt package for formatting. In addition, the custom formatter ignores
+the width and precision arguments (however they will still work on the format
+specifiers not handled by the custom formatter).
+
+Custom Formatter Usage
+
+The simplest way to make use of the spew custom formatter is to call one of the
+convenience functions such as spew.Printf, spew.Println, or spew.Printf. The
+functions have syntax you are most likely already familiar with:
+
+ spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
+ spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
+ spew.Println(myVar, myVar2)
+ spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
+ spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
+
+See the Index for the full list convenience functions.
+
+Sample Formatter Output
+
+Double pointer to a uint8:
+ %v: <**>5
+ %+v: <**>(0xf8400420d0->0xf8400420c8)5
+ %#v: (**uint8)5
+ %#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5
+
+Pointer to circular struct with a uint8 field and a pointer to itself:
+ %v: <*>{1 <*><shown>}
+ %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)<shown>}
+ %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)<shown>}
+ %#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)<shown>}
+
+See the Printf example for details on the setup of variables being shown
+here.
+
+Errors
+
+Since it is possible for custom Stringer/error interfaces to panic, spew
+detects them and handles them internally by printing the panic information
+inline with the output. Since spew is intended to provide deep pretty printing
+capabilities on structures, it intentionally does not return any errors.
+*/
+package spew
--- /dev/null
+/*
+ * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package spew
+
+import (
+ "bytes"
+ "encoding/hex"
+ "fmt"
+ "io"
+ "os"
+ "reflect"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+var (
+ // uint8Type is a reflect.Type representing a uint8. It is used to
+ // convert cgo types to uint8 slices for hexdumping.
+ uint8Type = reflect.TypeOf(uint8(0))
+
+ // cCharRE is a regular expression that matches a cgo char.
+ // It is used to detect character arrays to hexdump them.
+ cCharRE = regexp.MustCompile("^.*\\._Ctype_char$")
+
+ // cUnsignedCharRE is a regular expression that matches a cgo unsigned
+ // char. It is used to detect unsigned character arrays to hexdump
+ // them.
+ cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$")
+
+ // cUint8tCharRE is a regular expression that matches a cgo uint8_t.
+ // It is used to detect uint8_t arrays to hexdump them.
+ cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$")
+)
+
+// dumpState contains information about the state of a dump operation.
+type dumpState struct {
+ w io.Writer
+ depth int
+ pointers map[uintptr]int
+ ignoreNextType bool
+ ignoreNextIndent bool
+ cs *ConfigState
+}
+
+// indent performs indentation according to the depth level and cs.Indent
+// option.
+func (d *dumpState) indent() {
+ if d.ignoreNextIndent {
+ d.ignoreNextIndent = false
+ return
+ }
+ d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth))
+}
+
+// unpackValue returns values inside of non-nil interfaces when possible.
+// This is useful for data types like structs, arrays, slices, and maps which
+// can contain varying types packed inside an interface.
+func (d *dumpState) unpackValue(v reflect.Value) reflect.Value {
+ if v.Kind() == reflect.Interface && !v.IsNil() {
+ v = v.Elem()
+ }
+ return v
+}
+
+// dumpPtr handles formatting of pointers by indirecting them as necessary.
+func (d *dumpState) dumpPtr(v reflect.Value) {
+ // Remove pointers at or below the current depth from map used to detect
+ // circular refs.
+ for k, depth := range d.pointers {
+ if depth >= d.depth {
+ delete(d.pointers, k)
+ }
+ }
+
+ // Keep list of all dereferenced pointers to show later.
+ pointerChain := make([]uintptr, 0)
+
+ // Figure out how many levels of indirection there are by dereferencing
+ // pointers and unpacking interfaces down the chain while detecting circular
+ // references.
+ nilFound := false
+ cycleFound := false
+ indirects := 0
+ ve := v
+ for ve.Kind() == reflect.Ptr {
+ if ve.IsNil() {
+ nilFound = true
+ break
+ }
+ indirects++
+ addr := ve.Pointer()
+ pointerChain = append(pointerChain, addr)
+ if pd, ok := d.pointers[addr]; ok && pd < d.depth {
+ cycleFound = true
+ indirects--
+ break
+ }
+ d.pointers[addr] = d.depth
+
+ ve = ve.Elem()
+ if ve.Kind() == reflect.Interface {
+ if ve.IsNil() {
+ nilFound = true
+ break
+ }
+ ve = ve.Elem()
+ }
+ }
+
+ // Display type information.
+ d.w.Write(openParenBytes)
+ d.w.Write(bytes.Repeat(asteriskBytes, indirects))
+ d.w.Write([]byte(ve.Type().String()))
+ d.w.Write(closeParenBytes)
+
+ // Display pointer information.
+ if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 {
+ d.w.Write(openParenBytes)
+ for i, addr := range pointerChain {
+ if i > 0 {
+ d.w.Write(pointerChainBytes)
+ }
+ printHexPtr(d.w, addr)
+ }
+ d.w.Write(closeParenBytes)
+ }
+
+ // Display dereferenced value.
+ d.w.Write(openParenBytes)
+ switch {
+ case nilFound == true:
+ d.w.Write(nilAngleBytes)
+
+ case cycleFound == true:
+ d.w.Write(circularBytes)
+
+ default:
+ d.ignoreNextType = true
+ d.dump(ve)
+ }
+ d.w.Write(closeParenBytes)
+}
+
+// dumpSlice handles formatting of arrays and slices. Byte (uint8 under
+// reflection) arrays and slices are dumped in hexdump -C fashion.
+func (d *dumpState) dumpSlice(v reflect.Value) {
+ // Determine whether this type should be hex dumped or not. Also,
+ // for types which should be hexdumped, try to use the underlying data
+ // first, then fall back to trying to convert them to a uint8 slice.
+ var buf []uint8
+ doConvert := false
+ doHexDump := false
+ numEntries := v.Len()
+ if numEntries > 0 {
+ vt := v.Index(0).Type()
+ vts := vt.String()
+ switch {
+ // C types that need to be converted.
+ case cCharRE.MatchString(vts):
+ fallthrough
+ case cUnsignedCharRE.MatchString(vts):
+ fallthrough
+ case cUint8tCharRE.MatchString(vts):
+ doConvert = true
+
+ // Try to use existing uint8 slices and fall back to converting
+ // and copying if that fails.
+ case vt.Kind() == reflect.Uint8:
+ // We need an addressable interface to convert the type
+ // to a byte slice. However, the reflect package won't
+ // give us an interface on certain things like
+ // unexported struct fields in order to enforce
+ // visibility rules. We use unsafe, when available, to
+ // bypass these restrictions since this package does not
+ // mutate the values.
+ vs := v
+ if !vs.CanInterface() || !vs.CanAddr() {
+ vs = unsafeReflectValue(vs)
+ }
+ if !UnsafeDisabled {
+ vs = vs.Slice(0, numEntries)
+
+ // Use the existing uint8 slice if it can be
+ // type asserted.
+ iface := vs.Interface()
+ if slice, ok := iface.([]uint8); ok {
+ buf = slice
+ doHexDump = true
+ break
+ }
+ }
+
+ // The underlying data needs to be converted if it can't
+ // be type asserted to a uint8 slice.
+ doConvert = true
+ }
+
+ // Copy and convert the underlying type if needed.
+ if doConvert && vt.ConvertibleTo(uint8Type) {
+ // Convert and copy each element into a uint8 byte
+ // slice.
+ buf = make([]uint8, numEntries)
+ for i := 0; i < numEntries; i++ {
+ vv := v.Index(i)
+ buf[i] = uint8(vv.Convert(uint8Type).Uint())
+ }
+ doHexDump = true
+ }
+ }
+
+ // Hexdump the entire slice as needed.
+ if doHexDump {
+ indent := strings.Repeat(d.cs.Indent, d.depth)
+ str := indent + hex.Dump(buf)
+ str = strings.Replace(str, "\n", "\n"+indent, -1)
+ str = strings.TrimRight(str, d.cs.Indent)
+ d.w.Write([]byte(str))
+ return
+ }
+
+ // Recursively call dump for each item.
+ for i := 0; i < numEntries; i++ {
+ d.dump(d.unpackValue(v.Index(i)))
+ if i < (numEntries - 1) {
+ d.w.Write(commaNewlineBytes)
+ } else {
+ d.w.Write(newlineBytes)
+ }
+ }
+}
+
+// dump is the main workhorse for dumping a value. It uses the passed reflect
+// value to figure out what kind of object we are dealing with and formats it
+// appropriately. It is a recursive function, however circular data structures
+// are detected and handled properly.
+func (d *dumpState) dump(v reflect.Value) {
+ // Handle invalid reflect values immediately.
+ kind := v.Kind()
+ if kind == reflect.Invalid {
+ d.w.Write(invalidAngleBytes)
+ return
+ }
+
+ // Handle pointers specially.
+ if kind == reflect.Ptr {
+ d.indent()
+ d.dumpPtr(v)
+ return
+ }
+
+ // Print type information unless already handled elsewhere.
+ if !d.ignoreNextType {
+ d.indent()
+ d.w.Write(openParenBytes)
+ d.w.Write([]byte(v.Type().String()))
+ d.w.Write(closeParenBytes)
+ d.w.Write(spaceBytes)
+ }
+ d.ignoreNextType = false
+
+ // Display length and capacity if the built-in len and cap functions
+ // work with the value's kind and the len/cap itself is non-zero.
+ valueLen, valueCap := 0, 0
+ switch v.Kind() {
+ case reflect.Array, reflect.Slice, reflect.Chan:
+ valueLen, valueCap = v.Len(), v.Cap()
+ case reflect.Map, reflect.String:
+ valueLen = v.Len()
+ }
+ if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 {
+ d.w.Write(openParenBytes)
+ if valueLen != 0 {
+ d.w.Write(lenEqualsBytes)
+ printInt(d.w, int64(valueLen), 10)
+ }
+ if !d.cs.DisableCapacities && valueCap != 0 {
+ if valueLen != 0 {
+ d.w.Write(spaceBytes)
+ }
+ d.w.Write(capEqualsBytes)
+ printInt(d.w, int64(valueCap), 10)
+ }
+ d.w.Write(closeParenBytes)
+ d.w.Write(spaceBytes)
+ }
+
+ // Call Stringer/error interfaces if they exist and the handle methods flag
+ // is enabled
+ if !d.cs.DisableMethods {
+ if (kind != reflect.Invalid) && (kind != reflect.Interface) {
+ if handled := handleMethods(d.cs, d.w, v); handled {
+ return
+ }
+ }
+ }
+
+ switch kind {
+ case reflect.Invalid:
+ // Do nothing. We should never get here since invalid has already
+ // been handled above.
+
+ case reflect.Bool:
+ printBool(d.w, v.Bool())
+
+ case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
+ printInt(d.w, v.Int(), 10)
+
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
+ printUint(d.w, v.Uint(), 10)
+
+ case reflect.Float32:
+ printFloat(d.w, v.Float(), 32)
+
+ case reflect.Float64:
+ printFloat(d.w, v.Float(), 64)
+
+ case reflect.Complex64:
+ printComplex(d.w, v.Complex(), 32)
+
+ case reflect.Complex128:
+ printComplex(d.w, v.Complex(), 64)
+
+ case reflect.Slice:
+ if v.IsNil() {
+ d.w.Write(nilAngleBytes)
+ break
+ }
+ fallthrough
+
+ case reflect.Array:
+ d.w.Write(openBraceNewlineBytes)
+ d.depth++
+ if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
+ d.indent()
+ d.w.Write(maxNewlineBytes)
+ } else {
+ d.dumpSlice(v)
+ }
+ d.depth--
+ d.indent()
+ d.w.Write(closeBraceBytes)
+
+ case reflect.String:
+ d.w.Write([]byte(strconv.Quote(v.String())))
+
+ case reflect.Interface:
+ // The only time we should get here is for nil interfaces due to
+ // unpackValue calls.
+ if v.IsNil() {
+ d.w.Write(nilAngleBytes)
+ }
+
+ case reflect.Ptr:
+ // Do nothing. We should never get here since pointers have already
+ // been handled above.
+
+ case reflect.Map:
+ // nil maps should be indicated as different than empty maps
+ if v.IsNil() {
+ d.w.Write(nilAngleBytes)
+ break
+ }
+
+ d.w.Write(openBraceNewlineBytes)
+ d.depth++
+ if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
+ d.indent()
+ d.w.Write(maxNewlineBytes)
+ } else {
+ numEntries := v.Len()
+ keys := v.MapKeys()
+ if d.cs.SortKeys {
+ sortValues(keys, d.cs)
+ }
+ for i, key := range keys {
+ d.dump(d.unpackValue(key))
+ d.w.Write(colonSpaceBytes)
+ d.ignoreNextIndent = true
+ d.dump(d.unpackValue(v.MapIndex(key)))
+ if i < (numEntries - 1) {
+ d.w.Write(commaNewlineBytes)
+ } else {
+ d.w.Write(newlineBytes)
+ }
+ }
+ }
+ d.depth--
+ d.indent()
+ d.w.Write(closeBraceBytes)
+
+ case reflect.Struct:
+ d.w.Write(openBraceNewlineBytes)
+ d.depth++
+ if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
+ d.indent()
+ d.w.Write(maxNewlineBytes)
+ } else {
+ vt := v.Type()
+ numFields := v.NumField()
+ for i := 0; i < numFields; i++ {
+ d.indent()
+ vtf := vt.Field(i)
+ d.w.Write([]byte(vtf.Name))
+ d.w.Write(colonSpaceBytes)
+ d.ignoreNextIndent = true
+ d.dump(d.unpackValue(v.Field(i)))
+ if i < (numFields - 1) {
+ d.w.Write(commaNewlineBytes)
+ } else {
+ d.w.Write(newlineBytes)
+ }
+ }
+ }
+ d.depth--
+ d.indent()
+ d.w.Write(closeBraceBytes)
+
+ case reflect.Uintptr:
+ printHexPtr(d.w, uintptr(v.Uint()))
+
+ case reflect.UnsafePointer, reflect.Chan, reflect.Func:
+ printHexPtr(d.w, v.Pointer())
+
+ // There were not any other types at the time this code was written, but
+ // fall back to letting the default fmt package handle it in case any new
+ // types are added.
+ default:
+ if v.CanInterface() {
+ fmt.Fprintf(d.w, "%v", v.Interface())
+ } else {
+ fmt.Fprintf(d.w, "%v", v.String())
+ }
+ }
+}
+
+// fdump is a helper function to consolidate the logic from the various public
+// methods which take varying writers and config states.
+func fdump(cs *ConfigState, w io.Writer, a ...interface{}) {
+ for _, arg := range a {
+ if arg == nil {
+ w.Write(interfaceBytes)
+ w.Write(spaceBytes)
+ w.Write(nilAngleBytes)
+ w.Write(newlineBytes)
+ continue
+ }
+
+ d := dumpState{w: w, cs: cs}
+ d.pointers = make(map[uintptr]int)
+ d.dump(reflect.ValueOf(arg))
+ d.w.Write(newlineBytes)
+ }
+}
+
+// Fdump formats and displays the passed arguments to io.Writer w. It formats
+// exactly the same as Dump.
+func Fdump(w io.Writer, a ...interface{}) {
+ fdump(&Config, w, a...)
+}
+
+// Sdump returns a string with the passed arguments formatted exactly the same
+// as Dump.
+func Sdump(a ...interface{}) string {
+ var buf bytes.Buffer
+ fdump(&Config, &buf, a...)
+ return buf.String()
+}
+
+/*
+Dump displays the passed parameters to standard out with newlines, customizable
+indentation, and additional debug information such as complete types and all
+pointer addresses used to indirect to the final value. It provides the
+following features over the built-in printing facilities provided by the fmt
+package:
+
+ * Pointers are dereferenced and followed
+ * Circular data structures are detected and handled properly
+ * Custom Stringer/error interfaces are optionally invoked, including
+ on unexported types
+ * Custom types which only implement the Stringer/error interfaces via
+ a pointer receiver are optionally invoked when passing non-pointer
+ variables
+ * Byte arrays and slices are dumped like the hexdump -C command which
+ includes offsets, byte values in hex, and ASCII output
+
+The configuration options are controlled by an exported package global,
+spew.Config. See ConfigState for options documentation.
+
+See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
+get the formatted result as a string.
+*/
+func Dump(a ...interface{}) {
+ fdump(&Config, os.Stdout, a...)
+}
--- /dev/null
+/*
+ * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package spew
+
+import (
+ "bytes"
+ "fmt"
+ "reflect"
+ "strconv"
+ "strings"
+)
+
+// supportedFlags is a list of all the character flags supported by fmt package.
+const supportedFlags = "0-+# "
+
+// formatState implements the fmt.Formatter interface and contains information
+// about the state of a formatting operation. The NewFormatter function can
+// be used to get a new Formatter which can be used directly as arguments
+// in standard fmt package printing calls.
+type formatState struct {
+ value interface{}
+ fs fmt.State
+ depth int
+ pointers map[uintptr]int
+ ignoreNextType bool
+ cs *ConfigState
+}
+
+// buildDefaultFormat recreates the original format string without precision
+// and width information to pass in to fmt.Sprintf in the case of an
+// unrecognized type. Unless new types are added to the language, this
+// function won't ever be called.
+func (f *formatState) buildDefaultFormat() (format string) {
+ buf := bytes.NewBuffer(percentBytes)
+
+ for _, flag := range supportedFlags {
+ if f.fs.Flag(int(flag)) {
+ buf.WriteRune(flag)
+ }
+ }
+
+ buf.WriteRune('v')
+
+ format = buf.String()
+ return format
+}
+
+// constructOrigFormat recreates the original format string including precision
+// and width information to pass along to the standard fmt package. This allows
+// automatic deferral of all format strings this package doesn't support.
+func (f *formatState) constructOrigFormat(verb rune) (format string) {
+ buf := bytes.NewBuffer(percentBytes)
+
+ for _, flag := range supportedFlags {
+ if f.fs.Flag(int(flag)) {
+ buf.WriteRune(flag)
+ }
+ }
+
+ if width, ok := f.fs.Width(); ok {
+ buf.WriteString(strconv.Itoa(width))
+ }
+
+ if precision, ok := f.fs.Precision(); ok {
+ buf.Write(precisionBytes)
+ buf.WriteString(strconv.Itoa(precision))
+ }
+
+ buf.WriteRune(verb)
+
+ format = buf.String()
+ return format
+}
+
+// unpackValue returns values inside of non-nil interfaces when possible and
+// ensures that types for values which have been unpacked from an interface
+// are displayed when the show types flag is also set.
+// This is useful for data types like structs, arrays, slices, and maps which
+// can contain varying types packed inside an interface.
+func (f *formatState) unpackValue(v reflect.Value) reflect.Value {
+ if v.Kind() == reflect.Interface {
+ f.ignoreNextType = false
+ if !v.IsNil() {
+ v = v.Elem()
+ }
+ }
+ return v
+}
+
+// formatPtr handles formatting of pointers by indirecting them as necessary.
+func (f *formatState) formatPtr(v reflect.Value) {
+ // Display nil if top level pointer is nil.
+ showTypes := f.fs.Flag('#')
+ if v.IsNil() && (!showTypes || f.ignoreNextType) {
+ f.fs.Write(nilAngleBytes)
+ return
+ }
+
+ // Remove pointers at or below the current depth from map used to detect
+ // circular refs.
+ for k, depth := range f.pointers {
+ if depth >= f.depth {
+ delete(f.pointers, k)
+ }
+ }
+
+ // Keep list of all dereferenced pointers to possibly show later.
+ pointerChain := make([]uintptr, 0)
+
+ // Figure out how many levels of indirection there are by derferencing
+ // pointers and unpacking interfaces down the chain while detecting circular
+ // references.
+ nilFound := false
+ cycleFound := false
+ indirects := 0
+ ve := v
+ for ve.Kind() == reflect.Ptr {
+ if ve.IsNil() {
+ nilFound = true
+ break
+ }
+ indirects++
+ addr := ve.Pointer()
+ pointerChain = append(pointerChain, addr)
+ if pd, ok := f.pointers[addr]; ok && pd < f.depth {
+ cycleFound = true
+ indirects--
+ break
+ }
+ f.pointers[addr] = f.depth
+
+ ve = ve.Elem()
+ if ve.Kind() == reflect.Interface {
+ if ve.IsNil() {
+ nilFound = true
+ break
+ }
+ ve = ve.Elem()
+ }
+ }
+
+ // Display type or indirection level depending on flags.
+ if showTypes && !f.ignoreNextType {
+ f.fs.Write(openParenBytes)
+ f.fs.Write(bytes.Repeat(asteriskBytes, indirects))
+ f.fs.Write([]byte(ve.Type().String()))
+ f.fs.Write(closeParenBytes)
+ } else {
+ if nilFound || cycleFound {
+ indirects += strings.Count(ve.Type().String(), "*")
+ }
+ f.fs.Write(openAngleBytes)
+ f.fs.Write([]byte(strings.Repeat("*", indirects)))
+ f.fs.Write(closeAngleBytes)
+ }
+
+ // Display pointer information depending on flags.
+ if f.fs.Flag('+') && (len(pointerChain) > 0) {
+ f.fs.Write(openParenBytes)
+ for i, addr := range pointerChain {
+ if i > 0 {
+ f.fs.Write(pointerChainBytes)
+ }
+ printHexPtr(f.fs, addr)
+ }
+ f.fs.Write(closeParenBytes)
+ }
+
+ // Display dereferenced value.
+ switch {
+ case nilFound == true:
+ f.fs.Write(nilAngleBytes)
+
+ case cycleFound == true:
+ f.fs.Write(circularShortBytes)
+
+ default:
+ f.ignoreNextType = true
+ f.format(ve)
+ }
+}
+
+// format is the main workhorse for providing the Formatter interface. It
+// uses the passed reflect value to figure out what kind of object we are
+// dealing with and formats it appropriately. It is a recursive function,
+// however circular data structures are detected and handled properly.
+func (f *formatState) format(v reflect.Value) {
+ // Handle invalid reflect values immediately.
+ kind := v.Kind()
+ if kind == reflect.Invalid {
+ f.fs.Write(invalidAngleBytes)
+ return
+ }
+
+ // Handle pointers specially.
+ if kind == reflect.Ptr {
+ f.formatPtr(v)
+ return
+ }
+
+ // Print type information unless already handled elsewhere.
+ if !f.ignoreNextType && f.fs.Flag('#') {
+ f.fs.Write(openParenBytes)
+ f.fs.Write([]byte(v.Type().String()))
+ f.fs.Write(closeParenBytes)
+ }
+ f.ignoreNextType = false
+
+ // Call Stringer/error interfaces if they exist and the handle methods
+ // flag is enabled.
+ if !f.cs.DisableMethods {
+ if (kind != reflect.Invalid) && (kind != reflect.Interface) {
+ if handled := handleMethods(f.cs, f.fs, v); handled {
+ return
+ }
+ }
+ }
+
+ switch kind {
+ case reflect.Invalid:
+ // Do nothing. We should never get here since invalid has already
+ // been handled above.
+
+ case reflect.Bool:
+ printBool(f.fs, v.Bool())
+
+ case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
+ printInt(f.fs, v.Int(), 10)
+
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
+ printUint(f.fs, v.Uint(), 10)
+
+ case reflect.Float32:
+ printFloat(f.fs, v.Float(), 32)
+
+ case reflect.Float64:
+ printFloat(f.fs, v.Float(), 64)
+
+ case reflect.Complex64:
+ printComplex(f.fs, v.Complex(), 32)
+
+ case reflect.Complex128:
+ printComplex(f.fs, v.Complex(), 64)
+
+ case reflect.Slice:
+ if v.IsNil() {
+ f.fs.Write(nilAngleBytes)
+ break
+ }
+ fallthrough
+
+ case reflect.Array:
+ f.fs.Write(openBracketBytes)
+ f.depth++
+ if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
+ f.fs.Write(maxShortBytes)
+ } else {
+ numEntries := v.Len()
+ for i := 0; i < numEntries; i++ {
+ if i > 0 {
+ f.fs.Write(spaceBytes)
+ }
+ f.ignoreNextType = true
+ f.format(f.unpackValue(v.Index(i)))
+ }
+ }
+ f.depth--
+ f.fs.Write(closeBracketBytes)
+
+ case reflect.String:
+ f.fs.Write([]byte(v.String()))
+
+ case reflect.Interface:
+ // The only time we should get here is for nil interfaces due to
+ // unpackValue calls.
+ if v.IsNil() {
+ f.fs.Write(nilAngleBytes)
+ }
+
+ case reflect.Ptr:
+ // Do nothing. We should never get here since pointers have already
+ // been handled above.
+
+ case reflect.Map:
+ // nil maps should be indicated as different than empty maps
+ if v.IsNil() {
+ f.fs.Write(nilAngleBytes)
+ break
+ }
+
+ f.fs.Write(openMapBytes)
+ f.depth++
+ if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
+ f.fs.Write(maxShortBytes)
+ } else {
+ keys := v.MapKeys()
+ if f.cs.SortKeys {
+ sortValues(keys, f.cs)
+ }
+ for i, key := range keys {
+ if i > 0 {
+ f.fs.Write(spaceBytes)
+ }
+ f.ignoreNextType = true
+ f.format(f.unpackValue(key))
+ f.fs.Write(colonBytes)
+ f.ignoreNextType = true
+ f.format(f.unpackValue(v.MapIndex(key)))
+ }
+ }
+ f.depth--
+ f.fs.Write(closeMapBytes)
+
+ case reflect.Struct:
+ numFields := v.NumField()
+ f.fs.Write(openBraceBytes)
+ f.depth++
+ if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
+ f.fs.Write(maxShortBytes)
+ } else {
+ vt := v.Type()
+ for i := 0; i < numFields; i++ {
+ if i > 0 {
+ f.fs.Write(spaceBytes)
+ }
+ vtf := vt.Field(i)
+ if f.fs.Flag('+') || f.fs.Flag('#') {
+ f.fs.Write([]byte(vtf.Name))
+ f.fs.Write(colonBytes)
+ }
+ f.format(f.unpackValue(v.Field(i)))
+ }
+ }
+ f.depth--
+ f.fs.Write(closeBraceBytes)
+
+ case reflect.Uintptr:
+ printHexPtr(f.fs, uintptr(v.Uint()))
+
+ case reflect.UnsafePointer, reflect.Chan, reflect.Func:
+ printHexPtr(f.fs, v.Pointer())
+
+ // There were not any other types at the time this code was written, but
+ // fall back to letting the default fmt package handle it if any get added.
+ default:
+ format := f.buildDefaultFormat()
+ if v.CanInterface() {
+ fmt.Fprintf(f.fs, format, v.Interface())
+ } else {
+ fmt.Fprintf(f.fs, format, v.String())
+ }
+ }
+}
+
+// Format satisfies the fmt.Formatter interface. See NewFormatter for usage
+// details.
+func (f *formatState) Format(fs fmt.State, verb rune) {
+ f.fs = fs
+
+ // Use standard formatting for verbs that are not v.
+ if verb != 'v' {
+ format := f.constructOrigFormat(verb)
+ fmt.Fprintf(fs, format, f.value)
+ return
+ }
+
+ if f.value == nil {
+ if fs.Flag('#') {
+ fs.Write(interfaceBytes)
+ }
+ fs.Write(nilAngleBytes)
+ return
+ }
+
+ f.format(reflect.ValueOf(f.value))
+}
+
+// newFormatter is a helper function to consolidate the logic from the various
+// public methods which take varying config states.
+func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter {
+ fs := &formatState{value: v, cs: cs}
+ fs.pointers = make(map[uintptr]int)
+ return fs
+}
+
+/*
+NewFormatter returns a custom formatter that satisfies the fmt.Formatter
+interface. As a result, it integrates cleanly with standard fmt package
+printing functions. The formatter is useful for inline printing of smaller data
+types similar to the standard %v format specifier.
+
+The custom formatter only responds to the %v (most compact), %+v (adds pointer
+addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
+combinations. Any other verbs such as %x and %q will be sent to the the
+standard fmt package for formatting. In addition, the custom formatter ignores
+the width and precision arguments (however they will still work on the format
+specifiers not handled by the custom formatter).
+
+Typically this function shouldn't be called directly. It is much easier to make
+use of the custom formatter by calling one of the convenience functions such as
+Printf, Println, or Fprintf.
+*/
+func NewFormatter(v interface{}) fmt.Formatter {
+ return newFormatter(&Config, v)
+}
--- /dev/null
+/*
+ * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package spew
+
+import (
+ "fmt"
+ "io"
+)
+
+// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter. It
+// returns the formatted string as a value that satisfies error. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b))
+func Errorf(format string, a ...interface{}) (err error) {
+ return fmt.Errorf(format, convertArgs(a)...)
+}
+
+// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter. It
+// returns the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b))
+func Fprint(w io.Writer, a ...interface{}) (n int, err error) {
+ return fmt.Fprint(w, convertArgs(a)...)
+}
+
+// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter. It
+// returns the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b))
+func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
+ return fmt.Fprintf(w, format, convertArgs(a)...)
+}
+
+// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
+// passed with a default Formatter interface returned by NewFormatter. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b))
+func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
+ return fmt.Fprintln(w, convertArgs(a)...)
+}
+
+// Print is a wrapper for fmt.Print that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter. It
+// returns the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b))
+func Print(a ...interface{}) (n int, err error) {
+ return fmt.Print(convertArgs(a)...)
+}
+
+// Printf is a wrapper for fmt.Printf that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter. It
+// returns the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b))
+func Printf(format string, a ...interface{}) (n int, err error) {
+ return fmt.Printf(format, convertArgs(a)...)
+}
+
+// Println is a wrapper for fmt.Println that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter. It
+// returns the number of bytes written and any write error encountered. See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b))
+func Println(a ...interface{}) (n int, err error) {
+ return fmt.Println(convertArgs(a)...)
+}
+
+// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter. It
+// returns the resulting string. See NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b))
+func Sprint(a ...interface{}) string {
+ return fmt.Sprint(convertArgs(a)...)
+}
+
+// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter. It
+// returns the resulting string. See NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b))
+func Sprintf(format string, a ...interface{}) string {
+ return fmt.Sprintf(format, convertArgs(a)...)
+}
+
+// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
+// were passed with a default Formatter interface returned by NewFormatter. It
+// returns the resulting string. See NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+// fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b))
+func Sprintln(a ...interface{}) string {
+ return fmt.Sprintln(convertArgs(a)...)
+}
+
+// convertArgs accepts a slice of arguments and returns a slice of the same
+// length with each argument converted to a default spew Formatter interface.
+func convertArgs(args []interface{}) (formatters []interface{}) {
+ formatters = make([]interface{}, len(args))
+ for index, arg := range args {
+ formatters[index] = NewFormatter(arg)
+ }
+ return formatters
+}
--- /dev/null
+The MIT License (MIT)
+
+Copyright (c) 2015 Peter Bourgon
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
--- /dev/null
+# package log
+
+`package log` provides a minimal interface for structured logging in services.
+It may be wrapped to encode conventions, enforce type-safety, provide leveled
+logging, and so on. It can be used for both typical application log events,
+and log-structured data streams.
+
+## Structured logging
+
+Structured logging is, basically, conceding to the reality that logs are
+_data_, and warrant some level of schematic rigor. Using a stricter,
+key/value-oriented message format for our logs, containing contextual and
+semantic information, makes it much easier to get insight into the
+operational activity of the systems we build. Consequently, `package log` is
+of the strong belief that "[the benefits of structured logging outweigh the
+minimal effort involved](https://www.thoughtworks.com/radar/techniques/structured-logging)".
+
+Migrating from unstructured to structured logging is probably a lot easier
+than you'd expect.
+
+```go
+// Unstructured
+log.Printf("HTTP server listening on %s", addr)
+
+// Structured
+logger.Log("transport", "HTTP", "addr", addr, "msg", "listening")
+```
+
+## Usage
+
+### Typical application logging
+
+```go
+w := log.NewSyncWriter(os.Stderr)
+logger := log.NewLogfmtLogger(w)
+logger.Log("question", "what is the meaning of life?", "answer", 42)
+
+// Output:
+// question="what is the meaning of life?" answer=42
+```
+
+### Contextual Loggers
+
+```go
+func main() {
+ var logger log.Logger
+ logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
+ logger = log.With(logger, "instance_id", 123)
+
+ logger.Log("msg", "starting")
+ NewWorker(log.With(logger, "component", "worker")).Run()
+ NewSlacker(log.With(logger, "component", "slacker")).Run()
+}
+
+// Output:
+// instance_id=123 msg=starting
+// instance_id=123 component=worker msg=running
+// instance_id=123 component=slacker msg=running
+```
+
+### Interact with stdlib logger
+
+Redirect stdlib logger to Go kit logger.
+
+```go
+import (
+ "os"
+ stdlog "log"
+ kitlog "github.com/go-kit/kit/log"
+)
+
+func main() {
+ logger := kitlog.NewJSONLogger(kitlog.NewSyncWriter(os.Stdout))
+ stdlog.SetOutput(kitlog.NewStdlibAdapter(logger))
+ stdlog.Print("I sure like pie")
+}
+
+// Output:
+// {"msg":"I sure like pie","ts":"2016/01/01 12:34:56"}
+```
+
+Or, if, for legacy reasons, you need to pipe all of your logging through the
+stdlib log package, you can redirect Go kit logger to the stdlib logger.
+
+```go
+logger := kitlog.NewLogfmtLogger(kitlog.StdlibWriter{})
+logger.Log("legacy", true, "msg", "at least it's something")
+
+// Output:
+// 2016/01/01 12:34:56 legacy=true msg="at least it's something"
+```
+
+### Timestamps and callers
+
+```go
+var logger log.Logger
+logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
+logger = log.With(logger, "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller)
+
+logger.Log("msg", "hello")
+
+// Output:
+// ts=2016-01-01T12:34:56Z caller=main.go:15 msg=hello
+```
+
+## Supported output formats
+
+- [Logfmt](https://brandur.org/logfmt) ([see also](https://blog.codeship.com/logfmt-a-log-format-thats-easy-to-read-and-write))
+- JSON
+
+## Enhancements
+
+`package log` is centered on the one-method Logger interface.
+
+```go
+type Logger interface {
+ Log(keyvals ...interface{}) error
+}
+```
+
+This interface, and its supporting code like is the product of much iteration
+and evaluation. For more details on the evolution of the Logger interface,
+see [The Hunt for a Logger Interface](http://go-talks.appspot.com/github.com/ChrisHines/talks/structured-logging/structured-logging.slide#1),
+a talk by [Chris Hines](https://github.com/ChrisHines).
+Also, please see
+[#63](https://github.com/go-kit/kit/issues/63),
+[#76](https://github.com/go-kit/kit/pull/76),
+[#131](https://github.com/go-kit/kit/issues/131),
+[#157](https://github.com/go-kit/kit/pull/157),
+[#164](https://github.com/go-kit/kit/issues/164), and
+[#252](https://github.com/go-kit/kit/pull/252)
+to review historical conversations about package log and the Logger interface.
+
+Value-add packages and suggestions,
+like improvements to [the leveled logger](https://godoc.org/github.com/go-kit/kit/log/level),
+are of course welcome. Good proposals should
+
+- Be composable with [contextual loggers](https://godoc.org/github.com/go-kit/kit/log#With),
+- Not break the behavior of [log.Caller](https://godoc.org/github.com/go-kit/kit/log#Caller) in any wrapped contextual loggers, and
+- Be friendly to packages that accept only an unadorned log.Logger.
+
+## Benchmarks & comparisons
+
+There are a few Go logging benchmarks and comparisons that include Go kit's package log.
+
+- [imkira/go-loggers-bench](https://github.com/imkira/go-loggers-bench) includes kit/log
+- [uber-common/zap](https://github.com/uber-common/zap), a zero-alloc logging library, includes a comparison with kit/log
--- /dev/null
+// Package log provides a structured logger.
+//
+// Structured logging produces logs easily consumed later by humans or
+// machines. Humans might be interested in debugging errors, or tracing
+// specific requests. Machines might be interested in counting interesting
+// events, or aggregating information for off-line processing. In both cases,
+// it is important that the log messages are structured and actionable.
+// Package log is designed to encourage both of these best practices.
+//
+// Basic Usage
+//
+// The fundamental interface is Logger. Loggers create log events from
+// key/value data. The Logger interface has a single method, Log, which
+// accepts a sequence of alternating key/value pairs, which this package names
+// keyvals.
+//
+// type Logger interface {
+// Log(keyvals ...interface{}) error
+// }
+//
+// Here is an example of a function using a Logger to create log events.
+//
+// func RunTask(task Task, logger log.Logger) string {
+// logger.Log("taskID", task.ID, "event", "starting task")
+// ...
+// logger.Log("taskID", task.ID, "event", "task complete")
+// }
+//
+// The keys in the above example are "taskID" and "event". The values are
+// task.ID, "starting task", and "task complete". Every key is followed
+// immediately by its value.
+//
+// Keys are usually plain strings. Values may be any type that has a sensible
+// encoding in the chosen log format. With structured logging it is a good
+// idea to log simple values without formatting them. This practice allows
+// the chosen logger to encode values in the most appropriate way.
+//
+// Contextual Loggers
+//
+// A contextual logger stores keyvals that it includes in all log events.
+// Building appropriate contextual loggers reduces repetition and aids
+// consistency in the resulting log output. With and WithPrefix add context to
+// a logger. We can use With to improve the RunTask example.
+//
+// func RunTask(task Task, logger log.Logger) string {
+// logger = log.With(logger, "taskID", task.ID)
+// logger.Log("event", "starting task")
+// ...
+// taskHelper(task.Cmd, logger)
+// ...
+// logger.Log("event", "task complete")
+// }
+//
+// The improved version emits the same log events as the original for the
+// first and last calls to Log. Passing the contextual logger to taskHelper
+// enables each log event created by taskHelper to include the task.ID even
+// though taskHelper does not have access to that value. Using contextual
+// loggers this way simplifies producing log output that enables tracing the
+// life cycle of individual tasks. (See the Contextual example for the full
+// code of the above snippet.)
+//
+// Dynamic Contextual Values
+//
+// A Valuer function stored in a contextual logger generates a new value each
+// time an event is logged. The Valuer example demonstrates how this feature
+// works.
+//
+// Valuers provide the basis for consistently logging timestamps and source
+// code location. The log package defines several valuers for that purpose.
+// See Timestamp, DefaultTimestamp, DefaultTimestampUTC, Caller, and
+// DefaultCaller. A common logger initialization sequence that ensures all log
+// entries contain a timestamp and source location looks like this:
+//
+// logger := log.NewLogfmtLogger(log.NewSyncWriter(os.Stdout))
+// logger = log.With(logger, "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller)
+//
+// Concurrent Safety
+//
+// Applications with multiple goroutines want each log event written to the
+// same logger to remain separate from other log events. Package log provides
+// two simple solutions for concurrent safe logging.
+//
+// NewSyncWriter wraps an io.Writer and serializes each call to its Write
+// method. Using a SyncWriter has the benefit that the smallest practical
+// portion of the logging logic is performed within a mutex, but it requires
+// the formatting Logger to make only one call to Write per log event.
+//
+// NewSyncLogger wraps any Logger and serializes each call to its Log method.
+// Using a SyncLogger has the benefit that it guarantees each log event is
+// handled atomically within the wrapped logger, but it typically serializes
+// both the formatting and output logic. Use a SyncLogger if the formatting
+// logger may perform multiple writes per log event.
+//
+// Error Handling
+//
+// This package relies on the practice of wrapping or decorating loggers with
+// other loggers to provide composable pieces of functionality. It also means
+// that Logger.Log must return an error because some
+// implementations—especially those that output log data to an io.Writer—may
+// encounter errors that cannot be handled locally. This in turn means that
+// Loggers that wrap other loggers should return errors from the wrapped
+// logger up the stack.
+//
+// Fortunately, the decorator pattern also provides a way to avoid the
+// necessity to check for errors every time an application calls Logger.Log.
+// An application required to panic whenever its Logger encounters
+// an error could initialize its logger as follows.
+//
+// fmtlogger := log.NewLogfmtLogger(log.NewSyncWriter(os.Stdout))
+// logger := log.LoggerFunc(func(keyvals ...interface{}) error {
+// if err := fmtlogger.Log(keyvals...); err != nil {
+// panic(err)
+// }
+// return nil
+// })
+package log
--- /dev/null
+package log
+
+import (
+ "encoding"
+ "encoding/json"
+ "fmt"
+ "io"
+ "reflect"
+)
+
+type jsonLogger struct {
+ io.Writer
+}
+
+// NewJSONLogger returns a Logger that encodes keyvals to the Writer as a
+// single JSON object. Each log event produces no more than one call to
+// w.Write. The passed Writer must be safe for concurrent use by multiple
+// goroutines if the returned Logger will be used concurrently.
+func NewJSONLogger(w io.Writer) Logger {
+ return &jsonLogger{w}
+}
+
+func (l *jsonLogger) Log(keyvals ...interface{}) error {
+ n := (len(keyvals) + 1) / 2 // +1 to handle case when len is odd
+ m := make(map[string]interface{}, n)
+ for i := 0; i < len(keyvals); i += 2 {
+ k := keyvals[i]
+ var v interface{} = ErrMissingValue
+ if i+1 < len(keyvals) {
+ v = keyvals[i+1]
+ }
+ merge(m, k, v)
+ }
+ return json.NewEncoder(l.Writer).Encode(m)
+}
+
+func merge(dst map[string]interface{}, k, v interface{}) {
+ var key string
+ switch x := k.(type) {
+ case string:
+ key = x
+ case fmt.Stringer:
+ key = safeString(x)
+ default:
+ key = fmt.Sprint(x)
+ }
+
+ // We want json.Marshaler and encoding.TextMarshaller to take priority over
+ // err.Error() and v.String(). But json.Marshall (called later) does that by
+ // default so we force a no-op if it's one of those 2 case.
+ switch x := v.(type) {
+ case json.Marshaler:
+ case encoding.TextMarshaler:
+ case error:
+ v = safeError(x)
+ case fmt.Stringer:
+ v = safeString(x)
+ }
+
+ dst[key] = v
+}
+
+func safeString(str fmt.Stringer) (s string) {
+ defer func() {
+ if panicVal := recover(); panicVal != nil {
+ if v := reflect.ValueOf(str); v.Kind() == reflect.Ptr && v.IsNil() {
+ s = "NULL"
+ } else {
+ panic(panicVal)
+ }
+ }
+ }()
+ s = str.String()
+ return
+}
+
+func safeError(err error) (s interface{}) {
+ defer func() {
+ if panicVal := recover(); panicVal != nil {
+ if v := reflect.ValueOf(err); v.Kind() == reflect.Ptr && v.IsNil() {
+ s = nil
+ } else {
+ panic(panicVal)
+ }
+ }
+ }()
+ s = err.Error()
+ return
+}
--- /dev/null
+// Package level implements leveled logging on top of package log. To use the
+// level package, create a logger as per normal in your func main, and wrap it
+// with level.NewFilter.
+//
+// var logger log.Logger
+// logger = log.NewLogfmtLogger(os.Stderr)
+// logger = level.NewFilter(logger, level.AllowInfoAndAbove()) // <--
+// logger = log.With(logger, "ts", log.DefaultTimestampUTC)
+//
+// Then, at the callsites, use one of the level.Debug, Info, Warn, or Error
+// helper methods to emit leveled log events.
+//
+// logger.Log("foo", "bar") // as normal, no level
+// level.Debug(logger).Log("request_id", reqID, "trace_data", trace.Get())
+// if value > 100 {
+// level.Error(logger).Log("value", value)
+// }
+//
+// NewFilter allows precise control over what happens when a log event is
+// emitted without a level key, or if a squelched level is used. Check the
+// Option functions for details.
+package level
--- /dev/null
+package level
+
+import "github.com/go-kit/kit/log"
+
+// Error returns a logger that includes a Key/ErrorValue pair.
+func Error(logger log.Logger) log.Logger {
+ return log.WithPrefix(logger, Key(), ErrorValue())
+}
+
+// Warn returns a logger that includes a Key/WarnValue pair.
+func Warn(logger log.Logger) log.Logger {
+ return log.WithPrefix(logger, Key(), WarnValue())
+}
+
+// Info returns a logger that includes a Key/InfoValue pair.
+func Info(logger log.Logger) log.Logger {
+ return log.WithPrefix(logger, Key(), InfoValue())
+}
+
+// Debug returns a logger that includes a Key/DebugValue pair.
+func Debug(logger log.Logger) log.Logger {
+ return log.WithPrefix(logger, Key(), DebugValue())
+}
+
+// NewFilter wraps next and implements level filtering. See the commentary on
+// the Option functions for a detailed description of how to configure levels.
+// If no options are provided, all leveled log events created with Debug,
+// Info, Warn or Error helper methods are squelched and non-leveled log
+// events are passed to next unmodified.
+func NewFilter(next log.Logger, options ...Option) log.Logger {
+ l := &logger{
+ next: next,
+ }
+ for _, option := range options {
+ option(l)
+ }
+ return l
+}
+
+type logger struct {
+ next log.Logger
+ allowed level
+ squelchNoLevel bool
+ errNotAllowed error
+ errNoLevel error
+}
+
+func (l *logger) Log(keyvals ...interface{}) error {
+ var hasLevel, levelAllowed bool
+ for i := 1; i < len(keyvals); i += 2 {
+ if v, ok := keyvals[i].(*levelValue); ok {
+ hasLevel = true
+ levelAllowed = l.allowed&v.level != 0
+ break
+ }
+ }
+ if !hasLevel && l.squelchNoLevel {
+ return l.errNoLevel
+ }
+ if hasLevel && !levelAllowed {
+ return l.errNotAllowed
+ }
+ return l.next.Log(keyvals...)
+}
+
+// Option sets a parameter for the leveled logger.
+type Option func(*logger)
+
+// AllowAll is an alias for AllowDebug.
+func AllowAll() Option {
+ return AllowDebug()
+}
+
+// AllowDebug allows error, warn, info and debug level log events to pass.
+func AllowDebug() Option {
+ return allowed(levelError | levelWarn | levelInfo | levelDebug)
+}
+
+// AllowInfo allows error, warn and info level log events to pass.
+func AllowInfo() Option {
+ return allowed(levelError | levelWarn | levelInfo)
+}
+
+// AllowWarn allows error and warn level log events to pass.
+func AllowWarn() Option {
+ return allowed(levelError | levelWarn)
+}
+
+// AllowError allows only error level log events to pass.
+func AllowError() Option {
+ return allowed(levelError)
+}
+
+// AllowNone allows no leveled log events to pass.
+func AllowNone() Option {
+ return allowed(0)
+}
+
+func allowed(allowed level) Option {
+ return func(l *logger) { l.allowed = allowed }
+}
+
+// ErrNotAllowed sets the error to return from Log when it squelches a log
+// event disallowed by the configured Allow[Level] option. By default,
+// ErrNotAllowed is nil; in this case the log event is squelched with no
+// error.
+func ErrNotAllowed(err error) Option {
+ return func(l *logger) { l.errNotAllowed = err }
+}
+
+// SquelchNoLevel instructs Log to squelch log events with no level, so that
+// they don't proceed through to the wrapped logger. If SquelchNoLevel is set
+// to true and a log event is squelched in this way, the error value
+// configured with ErrNoLevel is returned to the caller.
+func SquelchNoLevel(squelch bool) Option {
+ return func(l *logger) { l.squelchNoLevel = squelch }
+}
+
+// ErrNoLevel sets the error to return from Log when it squelches a log event
+// with no level. By default, ErrNoLevel is nil; in this case the log event is
+// squelched with no error.
+func ErrNoLevel(err error) Option {
+ return func(l *logger) { l.errNoLevel = err }
+}
+
+// NewInjector wraps next and returns a logger that adds a Key/level pair to
+// the beginning of log events that don't already contain a level. In effect,
+// this gives a default level to logs without a level.
+func NewInjector(next log.Logger, level Value) log.Logger {
+ return &injector{
+ next: next,
+ level: level,
+ }
+}
+
+type injector struct {
+ next log.Logger
+ level interface{}
+}
+
+func (l *injector) Log(keyvals ...interface{}) error {
+ for i := 1; i < len(keyvals); i += 2 {
+ if _, ok := keyvals[i].(*levelValue); ok {
+ return l.next.Log(keyvals...)
+ }
+ }
+ kvs := make([]interface{}, len(keyvals)+2)
+ kvs[0], kvs[1] = key, l.level
+ copy(kvs[2:], keyvals)
+ return l.next.Log(kvs...)
+}
+
+// Value is the interface that each of the canonical level values implement.
+// It contains unexported methods that prevent types from other packages from
+// implementing it and guaranteeing that NewFilter can distinguish the levels
+// defined in this package from all other values.
+type Value interface {
+ String() string
+ levelVal()
+}
+
+// Key returns the unique key added to log events by the loggers in this
+// package.
+func Key() interface{} { return key }
+
+// ErrorValue returns the unique value added to log events by Error.
+func ErrorValue() Value { return errorValue }
+
+// WarnValue returns the unique value added to log events by Warn.
+func WarnValue() Value { return warnValue }
+
+// InfoValue returns the unique value added to log events by Info.
+func InfoValue() Value { return infoValue }
+
+// DebugValue returns the unique value added to log events by Warn.
+func DebugValue() Value { return debugValue }
+
+var (
+ // key is of type interfae{} so that it allocates once during package
+ // initialization and avoids allocating every type the value is added to a
+ // []interface{} later.
+ key interface{} = "level"
+
+ errorValue = &levelValue{level: levelError, name: "error"}
+ warnValue = &levelValue{level: levelWarn, name: "warn"}
+ infoValue = &levelValue{level: levelInfo, name: "info"}
+ debugValue = &levelValue{level: levelDebug, name: "debug"}
+)
+
+type level byte
+
+const (
+ levelDebug level = 1 << iota
+ levelInfo
+ levelWarn
+ levelError
+)
+
+type levelValue struct {
+ name string
+ level
+}
+
+func (v *levelValue) String() string { return v.name }
+func (v *levelValue) levelVal() {}
--- /dev/null
+package log
+
+import "errors"
+
+// Logger is the fundamental interface for all log operations. Log creates a
+// log event from keyvals, a variadic sequence of alternating keys and values.
+// Implementations must be safe for concurrent use by multiple goroutines. In
+// particular, any implementation of Logger that appends to keyvals or
+// modifies or retains any of its elements must make a copy first.
+type Logger interface {
+ Log(keyvals ...interface{}) error
+}
+
+// ErrMissingValue is appended to keyvals slices with odd length to substitute
+// the missing value.
+var ErrMissingValue = errors.New("(MISSING)")
+
+// With returns a new contextual logger with keyvals prepended to those passed
+// to calls to Log. If logger is also a contextual logger created by With or
+// WithPrefix, keyvals is appended to the existing context.
+//
+// The returned Logger replaces all value elements (odd indexes) containing a
+// Valuer with their generated value for each call to its Log method.
+func With(logger Logger, keyvals ...interface{}) Logger {
+ if len(keyvals) == 0 {
+ return logger
+ }
+ l := newContext(logger)
+ kvs := append(l.keyvals, keyvals...)
+ if len(kvs)%2 != 0 {
+ kvs = append(kvs, ErrMissingValue)
+ }
+ return &context{
+ logger: l.logger,
+ // Limiting the capacity of the stored keyvals ensures that a new
+ // backing array is created if the slice must grow in Log or With.
+ // Using the extra capacity without copying risks a data race that
+ // would violate the Logger interface contract.
+ keyvals: kvs[:len(kvs):len(kvs)],
+ hasValuer: l.hasValuer || containsValuer(keyvals),
+ }
+}
+
+// WithPrefix returns a new contextual logger with keyvals prepended to those
+// passed to calls to Log. If logger is also a contextual logger created by
+// With or WithPrefix, keyvals is prepended to the existing context.
+//
+// The returned Logger replaces all value elements (odd indexes) containing a
+// Valuer with their generated value for each call to its Log method.
+func WithPrefix(logger Logger, keyvals ...interface{}) Logger {
+ if len(keyvals) == 0 {
+ return logger
+ }
+ l := newContext(logger)
+ // Limiting the capacity of the stored keyvals ensures that a new
+ // backing array is created if the slice must grow in Log or With.
+ // Using the extra capacity without copying risks a data race that
+ // would violate the Logger interface contract.
+ n := len(l.keyvals) + len(keyvals)
+ if len(keyvals)%2 != 0 {
+ n++
+ }
+ kvs := make([]interface{}, 0, n)
+ kvs = append(kvs, keyvals...)
+ if len(kvs)%2 != 0 {
+ kvs = append(kvs, ErrMissingValue)
+ }
+ kvs = append(kvs, l.keyvals...)
+ return &context{
+ logger: l.logger,
+ keyvals: kvs,
+ hasValuer: l.hasValuer || containsValuer(keyvals),
+ }
+}
+
+// context is the Logger implementation returned by With and WithPrefix. It
+// wraps a Logger and holds keyvals that it includes in all log events. Its
+// Log method calls bindValues to generate values for each Valuer in the
+// context keyvals.
+//
+// A context must always have the same number of stack frames between calls to
+// its Log method and the eventual binding of Valuers to their value. This
+// requirement comes from the functional requirement to allow a context to
+// resolve application call site information for a Caller stored in the
+// context. To do this we must be able to predict the number of logging
+// functions on the stack when bindValues is called.
+//
+// Two implementation details provide the needed stack depth consistency.
+//
+// 1. newContext avoids introducing an additional layer when asked to
+// wrap another context.
+// 2. With and WithPrefix avoid introducing an additional layer by
+// returning a newly constructed context with a merged keyvals rather
+// than simply wrapping the existing context.
+type context struct {
+ logger Logger
+ keyvals []interface{}
+ hasValuer bool
+}
+
+func newContext(logger Logger) *context {
+ if c, ok := logger.(*context); ok {
+ return c
+ }
+ return &context{logger: logger}
+}
+
+// Log replaces all value elements (odd indexes) containing a Valuer in the
+// stored context with their generated value, appends keyvals, and passes the
+// result to the wrapped Logger.
+func (l *context) Log(keyvals ...interface{}) error {
+ kvs := append(l.keyvals, keyvals...)
+ if len(kvs)%2 != 0 {
+ kvs = append(kvs, ErrMissingValue)
+ }
+ if l.hasValuer {
+ // If no keyvals were appended above then we must copy l.keyvals so
+ // that future log events will reevaluate the stored Valuers.
+ if len(keyvals) == 0 {
+ kvs = append([]interface{}{}, l.keyvals...)
+ }
+ bindValues(kvs[:len(l.keyvals)])
+ }
+ return l.logger.Log(kvs...)
+}
+
+// LoggerFunc is an adapter to allow use of ordinary functions as Loggers. If
+// f is a function with the appropriate signature, LoggerFunc(f) is a Logger
+// object that calls f.
+type LoggerFunc func(...interface{}) error
+
+// Log implements Logger by calling f(keyvals...).
+func (f LoggerFunc) Log(keyvals ...interface{}) error {
+ return f(keyvals...)
+}
--- /dev/null
+package log
+
+import (
+ "bytes"
+ "io"
+ "sync"
+
+ "github.com/go-logfmt/logfmt"
+)
+
+type logfmtEncoder struct {
+ *logfmt.Encoder
+ buf bytes.Buffer
+}
+
+func (l *logfmtEncoder) Reset() {
+ l.Encoder.Reset()
+ l.buf.Reset()
+}
+
+var logfmtEncoderPool = sync.Pool{
+ New: func() interface{} {
+ var enc logfmtEncoder
+ enc.Encoder = logfmt.NewEncoder(&enc.buf)
+ return &enc
+ },
+}
+
+type logfmtLogger struct {
+ w io.Writer
+}
+
+// NewLogfmtLogger returns a logger that encodes keyvals to the Writer in
+// logfmt format. Each log event produces no more than one call to w.Write.
+// The passed Writer must be safe for concurrent use by multiple goroutines if
+// the returned Logger will be used concurrently.
+func NewLogfmtLogger(w io.Writer) Logger {
+ return &logfmtLogger{w}
+}
+
+func (l logfmtLogger) Log(keyvals ...interface{}) error {
+ enc := logfmtEncoderPool.Get().(*logfmtEncoder)
+ enc.Reset()
+ defer logfmtEncoderPool.Put(enc)
+
+ if err := enc.EncodeKeyvals(keyvals...); err != nil {
+ return err
+ }
+
+ // Add newline to the end of the buffer
+ if err := enc.EndRecord(); err != nil {
+ return err
+ }
+
+ // The Logger interface requires implementations to be safe for concurrent
+ // use by multiple goroutines. For this implementation that means making
+ // only one call to l.w.Write() for each call to Log.
+ if _, err := l.w.Write(enc.buf.Bytes()); err != nil {
+ return err
+ }
+ return nil
+}
--- /dev/null
+package log
+
+type nopLogger struct{}
+
+// NewNopLogger returns a logger that doesn't do anything.
+func NewNopLogger() Logger { return nopLogger{} }
+
+func (nopLogger) Log(...interface{}) error { return nil }
--- /dev/null
+package log
+
+import (
+ "io"
+ "log"
+ "regexp"
+ "strings"
+)
+
+// StdlibWriter implements io.Writer by invoking the stdlib log.Print. It's
+// designed to be passed to a Go kit logger as the writer, for cases where
+// it's necessary to redirect all Go kit log output to the stdlib logger.
+//
+// If you have any choice in the matter, you shouldn't use this. Prefer to
+// redirect the stdlib log to the Go kit logger via NewStdlibAdapter.
+type StdlibWriter struct{}
+
+// Write implements io.Writer.
+func (w StdlibWriter) Write(p []byte) (int, error) {
+ log.Print(strings.TrimSpace(string(p)))
+ return len(p), nil
+}
+
+// StdlibAdapter wraps a Logger and allows it to be passed to the stdlib
+// logger's SetOutput. It will extract date/timestamps, filenames, and
+// messages, and place them under relevant keys.
+type StdlibAdapter struct {
+ Logger
+ timestampKey string
+ fileKey string
+ messageKey string
+}
+
+// StdlibAdapterOption sets a parameter for the StdlibAdapter.
+type StdlibAdapterOption func(*StdlibAdapter)
+
+// TimestampKey sets the key for the timestamp field. By default, it's "ts".
+func TimestampKey(key string) StdlibAdapterOption {
+ return func(a *StdlibAdapter) { a.timestampKey = key }
+}
+
+// FileKey sets the key for the file and line field. By default, it's "caller".
+func FileKey(key string) StdlibAdapterOption {
+ return func(a *StdlibAdapter) { a.fileKey = key }
+}
+
+// MessageKey sets the key for the actual log message. By default, it's "msg".
+func MessageKey(key string) StdlibAdapterOption {
+ return func(a *StdlibAdapter) { a.messageKey = key }
+}
+
+// NewStdlibAdapter returns a new StdlibAdapter wrapper around the passed
+// logger. It's designed to be passed to log.SetOutput.
+func NewStdlibAdapter(logger Logger, options ...StdlibAdapterOption) io.Writer {
+ a := StdlibAdapter{
+ Logger: logger,
+ timestampKey: "ts",
+ fileKey: "caller",
+ messageKey: "msg",
+ }
+ for _, option := range options {
+ option(&a)
+ }
+ return a
+}
+
+func (a StdlibAdapter) Write(p []byte) (int, error) {
+ result := subexps(p)
+ keyvals := []interface{}{}
+ var timestamp string
+ if date, ok := result["date"]; ok && date != "" {
+ timestamp = date
+ }
+ if time, ok := result["time"]; ok && time != "" {
+ if timestamp != "" {
+ timestamp += " "
+ }
+ timestamp += time
+ }
+ if timestamp != "" {
+ keyvals = append(keyvals, a.timestampKey, timestamp)
+ }
+ if file, ok := result["file"]; ok && file != "" {
+ keyvals = append(keyvals, a.fileKey, file)
+ }
+ if msg, ok := result["msg"]; ok {
+ keyvals = append(keyvals, a.messageKey, msg)
+ }
+ if err := a.Logger.Log(keyvals...); err != nil {
+ return 0, err
+ }
+ return len(p), nil
+}
+
+const (
+ logRegexpDate = `(?P<date>[0-9]{4}/[0-9]{2}/[0-9]{2})?[ ]?`
+ logRegexpTime = `(?P<time>[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?)?[ ]?`
+ logRegexpFile = `(?P<file>.+?:[0-9]+)?`
+ logRegexpMsg = `(: )?(?P<msg>.*)`
+)
+
+var (
+ logRegexp = regexp.MustCompile(logRegexpDate + logRegexpTime + logRegexpFile + logRegexpMsg)
+)
+
+func subexps(line []byte) map[string]string {
+ m := logRegexp.FindSubmatch(line)
+ if len(m) < len(logRegexp.SubexpNames()) {
+ return map[string]string{}
+ }
+ result := map[string]string{}
+ for i, name := range logRegexp.SubexpNames() {
+ result[name] = string(m[i])
+ }
+ return result
+}
--- /dev/null
+package log
+
+import (
+ "io"
+ "sync"
+ "sync/atomic"
+)
+
+// SwapLogger wraps another logger that may be safely replaced while other
+// goroutines use the SwapLogger concurrently. The zero value for a SwapLogger
+// will discard all log events without error.
+//
+// SwapLogger serves well as a package global logger that can be changed by
+// importers.
+type SwapLogger struct {
+ logger atomic.Value
+}
+
+type loggerStruct struct {
+ Logger
+}
+
+// Log implements the Logger interface by forwarding keyvals to the currently
+// wrapped logger. It does not log anything if the wrapped logger is nil.
+func (l *SwapLogger) Log(keyvals ...interface{}) error {
+ s, ok := l.logger.Load().(loggerStruct)
+ if !ok || s.Logger == nil {
+ return nil
+ }
+ return s.Log(keyvals...)
+}
+
+// Swap replaces the currently wrapped logger with logger. Swap may be called
+// concurrently with calls to Log from other goroutines.
+func (l *SwapLogger) Swap(logger Logger) {
+ l.logger.Store(loggerStruct{logger})
+}
+
+// NewSyncWriter returns a new writer that is safe for concurrent use by
+// multiple goroutines. Writes to the returned writer are passed on to w. If
+// another write is already in progress, the calling goroutine blocks until
+// the writer is available.
+//
+// If w implements the following interface, so does the returned writer.
+//
+// interface {
+// Fd() uintptr
+// }
+func NewSyncWriter(w io.Writer) io.Writer {
+ switch w := w.(type) {
+ case fdWriter:
+ return &fdSyncWriter{fdWriter: w}
+ default:
+ return &syncWriter{Writer: w}
+ }
+}
+
+// syncWriter synchronizes concurrent writes to an io.Writer.
+type syncWriter struct {
+ sync.Mutex
+ io.Writer
+}
+
+// Write writes p to the underlying io.Writer. If another write is already in
+// progress, the calling goroutine blocks until the syncWriter is available.
+func (w *syncWriter) Write(p []byte) (n int, err error) {
+ w.Lock()
+ n, err = w.Writer.Write(p)
+ w.Unlock()
+ return n, err
+}
+
+// fdWriter is an io.Writer that also has an Fd method. The most common
+// example of an fdWriter is an *os.File.
+type fdWriter interface {
+ io.Writer
+ Fd() uintptr
+}
+
+// fdSyncWriter synchronizes concurrent writes to an fdWriter.
+type fdSyncWriter struct {
+ sync.Mutex
+ fdWriter
+}
+
+// Write writes p to the underlying io.Writer. If another write is already in
+// progress, the calling goroutine blocks until the fdSyncWriter is available.
+func (w *fdSyncWriter) Write(p []byte) (n int, err error) {
+ w.Lock()
+ n, err = w.fdWriter.Write(p)
+ w.Unlock()
+ return n, err
+}
+
+// syncLogger provides concurrent safe logging for another Logger.
+type syncLogger struct {
+ mu sync.Mutex
+ logger Logger
+}
+
+// NewSyncLogger returns a logger that synchronizes concurrent use of the
+// wrapped logger. When multiple goroutines use the SyncLogger concurrently
+// only one goroutine will be allowed to log to the wrapped logger at a time.
+// The other goroutines will block until the logger is available.
+func NewSyncLogger(logger Logger) Logger {
+ return &syncLogger{logger: logger}
+}
+
+// Log logs keyvals to the underlying Logger. If another log is already in
+// progress, the calling goroutine blocks until the syncLogger is available.
+func (l *syncLogger) Log(keyvals ...interface{}) error {
+ l.mu.Lock()
+ err := l.logger.Log(keyvals...)
+ l.mu.Unlock()
+ return err
+}
--- /dev/null
+package log
+
+import (
+ "time"
+
+ "github.com/go-stack/stack"
+)
+
+// A Valuer generates a log value. When passed to With or WithPrefix in a
+// value element (odd indexes), it represents a dynamic value which is re-
+// evaluated with each log event.
+type Valuer func() interface{}
+
+// bindValues replaces all value elements (odd indexes) containing a Valuer
+// with their generated value.
+func bindValues(keyvals []interface{}) {
+ for i := 1; i < len(keyvals); i += 2 {
+ if v, ok := keyvals[i].(Valuer); ok {
+ keyvals[i] = v()
+ }
+ }
+}
+
+// containsValuer returns true if any of the value elements (odd indexes)
+// contain a Valuer.
+func containsValuer(keyvals []interface{}) bool {
+ for i := 1; i < len(keyvals); i += 2 {
+ if _, ok := keyvals[i].(Valuer); ok {
+ return true
+ }
+ }
+ return false
+}
+
+// Timestamp returns a timestamp Valuer. It invokes the t function to get the
+// time; unless you are doing something tricky, pass time.Now.
+//
+// Most users will want to use DefaultTimestamp or DefaultTimestampUTC, which
+// are TimestampFormats that use the RFC3339Nano format.
+func Timestamp(t func() time.Time) Valuer {
+ return func() interface{} { return t() }
+}
+
+// TimestampFormat returns a timestamp Valuer with a custom time format. It
+// invokes the t function to get the time to format; unless you are doing
+// something tricky, pass time.Now. The layout string is passed to
+// Time.Format.
+//
+// Most users will want to use DefaultTimestamp or DefaultTimestampUTC, which
+// are TimestampFormats that use the RFC3339Nano format.
+func TimestampFormat(t func() time.Time, layout string) Valuer {
+ return func() interface{} {
+ return timeFormat{
+ time: t(),
+ layout: layout,
+ }
+ }
+}
+
+// A timeFormat represents an instant in time and a layout used when
+// marshaling to a text format.
+type timeFormat struct {
+ time time.Time
+ layout string
+}
+
+func (tf timeFormat) String() string {
+ return tf.time.Format(tf.layout)
+}
+
+// MarshalText implements encoding.TextMarshaller.
+func (tf timeFormat) MarshalText() (text []byte, err error) {
+ // The following code adapted from the standard library time.Time.Format
+ // method. Using the same undocumented magic constant to extend the size
+ // of the buffer as seen there.
+ b := make([]byte, 0, len(tf.layout)+10)
+ b = tf.time.AppendFormat(b, tf.layout)
+ return b, nil
+}
+
+// Caller returns a Valuer that returns a file and line from a specified depth
+// in the callstack. Users will probably want to use DefaultCaller.
+func Caller(depth int) Valuer {
+ return func() interface{} { return stack.Caller(depth) }
+}
+
+var (
+ // DefaultTimestamp is a Valuer that returns the current wallclock time,
+ // respecting time zones, when bound.
+ DefaultTimestamp = TimestampFormat(time.Now, time.RFC3339Nano)
+
+ // DefaultTimestampUTC is a Valuer that returns the current time in UTC
+ // when bound.
+ DefaultTimestampUTC = TimestampFormat(
+ func() time.Time { return time.Now().UTC() },
+ time.RFC3339Nano,
+ )
+
+ // DefaultCaller is a Valuer that returns the file and line where the Log
+ // method was invoked. It can only be used with log.With.
+ DefaultCaller = Caller(3)
+)
--- /dev/null
+The MIT License (MIT)
+
+Copyright (c) 2015 go-logfmt
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
--- /dev/null
+[](https://godoc.org/github.com/go-logfmt/logfmt)
+[](https://goreportcard.com/report/go-logfmt/logfmt)
+[](https://travis-ci.org/go-logfmt/logfmt)
+[](https://coveralls.io/github/go-logfmt/logfmt?branch=master)
+
+# logfmt
+
+Package logfmt implements utilities to marshal and unmarshal data in the [logfmt
+format](https://brandur.org/logfmt). It provides an API similar to
+[encoding/json](http://golang.org/pkg/encoding/json/) and
+[encoding/xml](http://golang.org/pkg/encoding/xml/).
+
+The logfmt format was first documented by Brandur Leach in [this
+article](https://brandur.org/logfmt). The format has not been formally
+standardized. The most authoritative public specification to date has been the
+documentation of a Go Language [package](http://godoc.org/github.com/kr/logfmt)
+written by Blake Mizerany and Keith Rarick.
+
+## Goals
+
+This project attempts to conform as closely as possible to the prior art, while
+also removing ambiguity where necessary to provide well behaved encoder and
+decoder implementations.
+
+## Non-goals
+
+This project does not attempt to formally standardize the logfmt format. In the
+event that logfmt is standardized this project would take conforming to the
+standard as a goal.
+
+## Versioning
+
+Package logfmt publishes releases via [semver](http://semver.org/) compatible Git tags prefixed with a single 'v'.
--- /dev/null
+package logfmt
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "unicode/utf8"
+)
+
+// A Decoder reads and decodes logfmt records from an input stream.
+type Decoder struct {
+ pos int
+ key []byte
+ value []byte
+ lineNum int
+ s *bufio.Scanner
+ err error
+}
+
+// NewDecoder returns a new decoder that reads from r.
+//
+// The decoder introduces its own buffering and may read data from r beyond
+// the logfmt records requested.
+func NewDecoder(r io.Reader) *Decoder {
+ dec := &Decoder{
+ s: bufio.NewScanner(r),
+ }
+ return dec
+}
+
+// ScanRecord advances the Decoder to the next record, which can then be
+// parsed with the ScanKeyval method. It returns false when decoding stops,
+// either by reaching the end of the input or an error. After ScanRecord
+// returns false, the Err method will return any error that occurred during
+// decoding, except that if it was io.EOF, Err will return nil.
+func (dec *Decoder) ScanRecord() bool {
+ if dec.err != nil {
+ return false
+ }
+ if !dec.s.Scan() {
+ dec.err = dec.s.Err()
+ return false
+ }
+ dec.lineNum++
+ dec.pos = 0
+ return true
+}
+
+// ScanKeyval advances the Decoder to the next key/value pair of the current
+// record, which can then be retrieved with the Key and Value methods. It
+// returns false when decoding stops, either by reaching the end of the
+// current record or an error.
+func (dec *Decoder) ScanKeyval() bool {
+ dec.key, dec.value = nil, nil
+ if dec.err != nil {
+ return false
+ }
+
+ line := dec.s.Bytes()
+
+ // garbage
+ for p, c := range line[dec.pos:] {
+ if c > ' ' {
+ dec.pos += p
+ goto key
+ }
+ }
+ dec.pos = len(line)
+ return false
+
+key:
+ const invalidKeyError = "invalid key"
+
+ start, multibyte := dec.pos, false
+ for p, c := range line[dec.pos:] {
+ switch {
+ case c == '=':
+ dec.pos += p
+ if dec.pos > start {
+ dec.key = line[start:dec.pos]
+ if multibyte && bytes.IndexRune(dec.key, utf8.RuneError) != -1 {
+ dec.syntaxError(invalidKeyError)
+ return false
+ }
+ }
+ if dec.key == nil {
+ dec.unexpectedByte(c)
+ return false
+ }
+ goto equal
+ case c == '"':
+ dec.pos += p
+ dec.unexpectedByte(c)
+ return false
+ case c <= ' ':
+ dec.pos += p
+ if dec.pos > start {
+ dec.key = line[start:dec.pos]
+ if multibyte && bytes.IndexRune(dec.key, utf8.RuneError) != -1 {
+ dec.syntaxError(invalidKeyError)
+ return false
+ }
+ }
+ return true
+ case c >= utf8.RuneSelf:
+ multibyte = true
+ }
+ }
+ dec.pos = len(line)
+ if dec.pos > start {
+ dec.key = line[start:dec.pos]
+ if multibyte && bytes.IndexRune(dec.key, utf8.RuneError) != -1 {
+ dec.syntaxError(invalidKeyError)
+ return false
+ }
+ }
+ return true
+
+equal:
+ dec.pos++
+ if dec.pos >= len(line) {
+ return true
+ }
+ switch c := line[dec.pos]; {
+ case c <= ' ':
+ return true
+ case c == '"':
+ goto qvalue
+ }
+
+ // value
+ start = dec.pos
+ for p, c := range line[dec.pos:] {
+ switch {
+ case c == '=' || c == '"':
+ dec.pos += p
+ dec.unexpectedByte(c)
+ return false
+ case c <= ' ':
+ dec.pos += p
+ if dec.pos > start {
+ dec.value = line[start:dec.pos]
+ }
+ return true
+ }
+ }
+ dec.pos = len(line)
+ if dec.pos > start {
+ dec.value = line[start:dec.pos]
+ }
+ return true
+
+qvalue:
+ const (
+ untermQuote = "unterminated quoted value"
+ invalidQuote = "invalid quoted value"
+ )
+
+ hasEsc, esc := false, false
+ start = dec.pos
+ for p, c := range line[dec.pos+1:] {
+ switch {
+ case esc:
+ esc = false
+ case c == '\\':
+ hasEsc, esc = true, true
+ case c == '"':
+ dec.pos += p + 2
+ if hasEsc {
+ v, ok := unquoteBytes(line[start:dec.pos])
+ if !ok {
+ dec.syntaxError(invalidQuote)
+ return false
+ }
+ dec.value = v
+ } else {
+ start++
+ end := dec.pos - 1
+ if end > start {
+ dec.value = line[start:end]
+ }
+ }
+ return true
+ }
+ }
+ dec.pos = len(line)
+ dec.syntaxError(untermQuote)
+ return false
+}
+
+// Key returns the most recent key found by a call to ScanKeyval. The returned
+// slice may point to internal buffers and is only valid until the next call
+// to ScanRecord. It does no allocation.
+func (dec *Decoder) Key() []byte {
+ return dec.key
+}
+
+// Value returns the most recent value found by a call to ScanKeyval. The
+// returned slice may point to internal buffers and is only valid until the
+// next call to ScanRecord. It does no allocation when the value has no
+// escape sequences.
+func (dec *Decoder) Value() []byte {
+ return dec.value
+}
+
+// Err returns the first non-EOF error that was encountered by the Scanner.
+func (dec *Decoder) Err() error {
+ return dec.err
+}
+
+func (dec *Decoder) syntaxError(msg string) {
+ dec.err = &SyntaxError{
+ Msg: msg,
+ Line: dec.lineNum,
+ Pos: dec.pos + 1,
+ }
+}
+
+func (dec *Decoder) unexpectedByte(c byte) {
+ dec.err = &SyntaxError{
+ Msg: fmt.Sprintf("unexpected %q", c),
+ Line: dec.lineNum,
+ Pos: dec.pos + 1,
+ }
+}
+
+// A SyntaxError represents a syntax error in the logfmt input stream.
+type SyntaxError struct {
+ Msg string
+ Line int
+ Pos int
+}
+
+func (e *SyntaxError) Error() string {
+ return fmt.Sprintf("logfmt syntax error at pos %d on line %d: %s", e.Pos, e.Line, e.Msg)
+}
--- /dev/null
+// Package logfmt implements utilities to marshal and unmarshal data in the
+// logfmt format. The logfmt format records key/value pairs in a way that
+// balances readability for humans and simplicity of computer parsing. It is
+// most commonly used as a more human friendly alternative to JSON for
+// structured logging.
+package logfmt
--- /dev/null
+package logfmt
+
+import (
+ "bytes"
+ "encoding"
+ "errors"
+ "fmt"
+ "io"
+ "reflect"
+ "strings"
+ "unicode/utf8"
+)
+
+// MarshalKeyvals returns the logfmt encoding of keyvals, a variadic sequence
+// of alternating keys and values.
+func MarshalKeyvals(keyvals ...interface{}) ([]byte, error) {
+ buf := &bytes.Buffer{}
+ if err := NewEncoder(buf).EncodeKeyvals(keyvals...); err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+// An Encoder writes logfmt data to an output stream.
+type Encoder struct {
+ w io.Writer
+ scratch bytes.Buffer
+ needSep bool
+}
+
+// NewEncoder returns a new encoder that writes to w.
+func NewEncoder(w io.Writer) *Encoder {
+ return &Encoder{
+ w: w,
+ }
+}
+
+var (
+ space = []byte(" ")
+ equals = []byte("=")
+ newline = []byte("\n")
+ null = []byte("null")
+)
+
+// EncodeKeyval writes the logfmt encoding of key and value to the stream. A
+// single space is written before the second and subsequent keys in a record.
+// Nothing is written if a non-nil error is returned.
+func (enc *Encoder) EncodeKeyval(key, value interface{}) error {
+ enc.scratch.Reset()
+ if enc.needSep {
+ if _, err := enc.scratch.Write(space); err != nil {
+ return err
+ }
+ }
+ if err := writeKey(&enc.scratch, key); err != nil {
+ return err
+ }
+ if _, err := enc.scratch.Write(equals); err != nil {
+ return err
+ }
+ if err := writeValue(&enc.scratch, value); err != nil {
+ return err
+ }
+ _, err := enc.w.Write(enc.scratch.Bytes())
+ enc.needSep = true
+ return err
+}
+
+// EncodeKeyvals writes the logfmt encoding of keyvals to the stream. Keyvals
+// is a variadic sequence of alternating keys and values. Keys of unsupported
+// type are skipped along with their corresponding value. Values of
+// unsupported type or that cause a MarshalerError are replaced by their error
+// but do not cause EncodeKeyvals to return an error. If a non-nil error is
+// returned some key/value pairs may not have be written.
+func (enc *Encoder) EncodeKeyvals(keyvals ...interface{}) error {
+ if len(keyvals) == 0 {
+ return nil
+ }
+ if len(keyvals)%2 == 1 {
+ keyvals = append(keyvals, nil)
+ }
+ for i := 0; i < len(keyvals); i += 2 {
+ k, v := keyvals[i], keyvals[i+1]
+ err := enc.EncodeKeyval(k, v)
+ if err == ErrUnsupportedKeyType {
+ continue
+ }
+ if _, ok := err.(*MarshalerError); ok || err == ErrUnsupportedValueType {
+ v = err
+ err = enc.EncodeKeyval(k, v)
+ }
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// MarshalerError represents an error encountered while marshaling a value.
+type MarshalerError struct {
+ Type reflect.Type
+ Err error
+}
+
+func (e *MarshalerError) Error() string {
+ return "error marshaling value of type " + e.Type.String() + ": " + e.Err.Error()
+}
+
+// ErrNilKey is returned by Marshal functions and Encoder methods if a key is
+// a nil interface or pointer value.
+var ErrNilKey = errors.New("nil key")
+
+// ErrInvalidKey is returned by Marshal functions and Encoder methods if a key
+// contains an invalid character.
+var ErrInvalidKey = errors.New("invalid key")
+
+// ErrUnsupportedKeyType is returned by Encoder methods if a key has an
+// unsupported type.
+var ErrUnsupportedKeyType = errors.New("unsupported key type")
+
+// ErrUnsupportedValueType is returned by Encoder methods if a value has an
+// unsupported type.
+var ErrUnsupportedValueType = errors.New("unsupported value type")
+
+func writeKey(w io.Writer, key interface{}) error {
+ if key == nil {
+ return ErrNilKey
+ }
+
+ switch k := key.(type) {
+ case string:
+ return writeStringKey(w, k)
+ case []byte:
+ if k == nil {
+ return ErrNilKey
+ }
+ return writeBytesKey(w, k)
+ case encoding.TextMarshaler:
+ kb, err := safeMarshal(k)
+ if err != nil {
+ return err
+ }
+ if kb == nil {
+ return ErrNilKey
+ }
+ return writeBytesKey(w, kb)
+ case fmt.Stringer:
+ ks, ok := safeString(k)
+ if !ok {
+ return ErrNilKey
+ }
+ return writeStringKey(w, ks)
+ default:
+ rkey := reflect.ValueOf(key)
+ switch rkey.Kind() {
+ case reflect.Array, reflect.Chan, reflect.Func, reflect.Map, reflect.Slice, reflect.Struct:
+ return ErrUnsupportedKeyType
+ case reflect.Ptr:
+ if rkey.IsNil() {
+ return ErrNilKey
+ }
+ return writeKey(w, rkey.Elem().Interface())
+ }
+ return writeStringKey(w, fmt.Sprint(k))
+ }
+}
+
+func invalidKeyRune(r rune) bool {
+ return r <= ' ' || r == '=' || r == '"' || r == utf8.RuneError
+}
+
+func invalidKeyString(key string) bool {
+ return len(key) == 0 || strings.IndexFunc(key, invalidKeyRune) != -1
+}
+
+func invalidKey(key []byte) bool {
+ return len(key) == 0 || bytes.IndexFunc(key, invalidKeyRune) != -1
+}
+
+func writeStringKey(w io.Writer, key string) error {
+ if invalidKeyString(key) {
+ return ErrInvalidKey
+ }
+ _, err := io.WriteString(w, key)
+ return err
+}
+
+func writeBytesKey(w io.Writer, key []byte) error {
+ if invalidKey(key) {
+ return ErrInvalidKey
+ }
+ _, err := w.Write(key)
+ return err
+}
+
+func writeValue(w io.Writer, value interface{}) error {
+ switch v := value.(type) {
+ case nil:
+ return writeBytesValue(w, null)
+ case string:
+ return writeStringValue(w, v, true)
+ case []byte:
+ return writeBytesValue(w, v)
+ case encoding.TextMarshaler:
+ vb, err := safeMarshal(v)
+ if err != nil {
+ return err
+ }
+ if vb == nil {
+ vb = null
+ }
+ return writeBytesValue(w, vb)
+ case error:
+ se, ok := safeError(v)
+ return writeStringValue(w, se, ok)
+ case fmt.Stringer:
+ ss, ok := safeString(v)
+ return writeStringValue(w, ss, ok)
+ default:
+ rvalue := reflect.ValueOf(value)
+ switch rvalue.Kind() {
+ case reflect.Array, reflect.Chan, reflect.Func, reflect.Map, reflect.Slice, reflect.Struct:
+ return ErrUnsupportedValueType
+ case reflect.Ptr:
+ if rvalue.IsNil() {
+ return writeBytesValue(w, null)
+ }
+ return writeValue(w, rvalue.Elem().Interface())
+ }
+ return writeStringValue(w, fmt.Sprint(v), true)
+ }
+}
+
+func needsQuotedValueRune(r rune) bool {
+ return r <= ' ' || r == '=' || r == '"' || r == utf8.RuneError
+}
+
+func writeStringValue(w io.Writer, value string, ok bool) error {
+ var err error
+ if ok && value == "null" {
+ _, err = io.WriteString(w, `"null"`)
+ } else if strings.IndexFunc(value, needsQuotedValueRune) != -1 {
+ _, err = writeQuotedString(w, value)
+ } else {
+ _, err = io.WriteString(w, value)
+ }
+ return err
+}
+
+func writeBytesValue(w io.Writer, value []byte) error {
+ var err error
+ if bytes.IndexFunc(value, needsQuotedValueRune) != -1 {
+ _, err = writeQuotedBytes(w, value)
+ } else {
+ _, err = w.Write(value)
+ }
+ return err
+}
+
+// EndRecord writes a newline character to the stream and resets the encoder
+// to the beginning of a new record.
+func (enc *Encoder) EndRecord() error {
+ _, err := enc.w.Write(newline)
+ if err == nil {
+ enc.needSep = false
+ }
+ return err
+}
+
+// Reset resets the encoder to the beginning of a new record.
+func (enc *Encoder) Reset() {
+ enc.needSep = false
+}
+
+func safeError(err error) (s string, ok bool) {
+ defer func() {
+ if panicVal := recover(); panicVal != nil {
+ if v := reflect.ValueOf(err); v.Kind() == reflect.Ptr && v.IsNil() {
+ s, ok = "null", false
+ } else {
+ panic(panicVal)
+ }
+ }
+ }()
+ s, ok = err.Error(), true
+ return
+}
+
+func safeString(str fmt.Stringer) (s string, ok bool) {
+ defer func() {
+ if panicVal := recover(); panicVal != nil {
+ if v := reflect.ValueOf(str); v.Kind() == reflect.Ptr && v.IsNil() {
+ s, ok = "null", false
+ } else {
+ panic(panicVal)
+ }
+ }
+ }()
+ s, ok = str.String(), true
+ return
+}
+
+func safeMarshal(tm encoding.TextMarshaler) (b []byte, err error) {
+ defer func() {
+ if panicVal := recover(); panicVal != nil {
+ if v := reflect.ValueOf(tm); v.Kind() == reflect.Ptr && v.IsNil() {
+ b, err = nil, nil
+ } else {
+ panic(panicVal)
+ }
+ }
+ }()
+ b, err = tm.MarshalText()
+ if err != nil {
+ return nil, &MarshalerError{
+ Type: reflect.TypeOf(tm),
+ Err: err,
+ }
+ }
+ return
+}
--- /dev/null
+// +build gofuzz
+
+package logfmt
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "reflect"
+
+ kr "github.com/kr/logfmt"
+)
+
+// Fuzz checks reserialized data matches
+func Fuzz(data []byte) int {
+ parsed, err := parse(data)
+ if err != nil {
+ return 0
+ }
+ var w1 bytes.Buffer
+ if err = write(parsed, &w1); err != nil {
+ panic(err)
+ }
+ parsed, err = parse(w1.Bytes())
+ if err != nil {
+ panic(err)
+ }
+ var w2 bytes.Buffer
+ if err = write(parsed, &w2); err != nil {
+ panic(err)
+ }
+ if !bytes.Equal(w1.Bytes(), w2.Bytes()) {
+ panic(fmt.Sprintf("reserialized data does not match:\n%q\n%q\n", w1.Bytes(), w2.Bytes()))
+ }
+ return 1
+}
+
+// FuzzVsKR checks go-logfmt/logfmt against kr/logfmt
+func FuzzVsKR(data []byte) int {
+ parsed, err := parse(data)
+ parsedKR, errKR := parseKR(data)
+
+ // github.com/go-logfmt/logfmt is a stricter parser. It returns errors for
+ // more inputs than github.com/kr/logfmt. Ignore any inputs that have a
+ // stict error.
+ if err != nil {
+ return 0
+ }
+
+ // Fail if the more forgiving parser finds an error not found by the
+ // stricter parser.
+ if errKR != nil {
+ panic(fmt.Sprintf("unmatched error: %v", errKR))
+ }
+
+ if !reflect.DeepEqual(parsed, parsedKR) {
+ panic(fmt.Sprintf("parsers disagree:\n%+v\n%+v\n", parsed, parsedKR))
+ }
+ return 1
+}
+
+type kv struct {
+ k, v []byte
+}
+
+func parse(data []byte) ([][]kv, error) {
+ var got [][]kv
+ dec := NewDecoder(bytes.NewReader(data))
+ for dec.ScanRecord() {
+ var kvs []kv
+ for dec.ScanKeyval() {
+ kvs = append(kvs, kv{dec.Key(), dec.Value()})
+ }
+ got = append(got, kvs)
+ }
+ return got, dec.Err()
+}
+
+func parseKR(data []byte) ([][]kv, error) {
+ var (
+ s = bufio.NewScanner(bytes.NewReader(data))
+ err error
+ h saveHandler
+ got [][]kv
+ )
+ for err == nil && s.Scan() {
+ h.kvs = nil
+ err = kr.Unmarshal(s.Bytes(), &h)
+ got = append(got, h.kvs)
+ }
+ if err == nil {
+ err = s.Err()
+ }
+ return got, err
+}
+
+type saveHandler struct {
+ kvs []kv
+}
+
+func (h *saveHandler) HandleLogfmt(key, val []byte) error {
+ if len(key) == 0 {
+ key = nil
+ }
+ if len(val) == 0 {
+ val = nil
+ }
+ h.kvs = append(h.kvs, kv{key, val})
+ return nil
+}
+
+func write(recs [][]kv, w io.Writer) error {
+ enc := NewEncoder(w)
+ for _, rec := range recs {
+ for _, f := range rec {
+ if err := enc.EncodeKeyval(f.k, f.v); err != nil {
+ return err
+ }
+ }
+ if err := enc.EndRecord(); err != nil {
+ return err
+ }
+ }
+ return nil
+}
--- /dev/null
+package logfmt
+
+import (
+ "bytes"
+ "io"
+ "strconv"
+ "sync"
+ "unicode"
+ "unicode/utf16"
+ "unicode/utf8"
+)
+
+// Taken from Go's encoding/json and modified for use here.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var hex = "0123456789abcdef"
+
+var bufferPool = sync.Pool{
+ New: func() interface{} {
+ return &bytes.Buffer{}
+ },
+}
+
+func getBuffer() *bytes.Buffer {
+ return bufferPool.Get().(*bytes.Buffer)
+}
+
+func poolBuffer(buf *bytes.Buffer) {
+ buf.Reset()
+ bufferPool.Put(buf)
+}
+
+// NOTE: keep in sync with writeQuotedBytes below.
+func writeQuotedString(w io.Writer, s string) (int, error) {
+ buf := getBuffer()
+ buf.WriteByte('"')
+ start := 0
+ for i := 0; i < len(s); {
+ if b := s[i]; b < utf8.RuneSelf {
+ if 0x20 <= b && b != '\\' && b != '"' {
+ i++
+ continue
+ }
+ if start < i {
+ buf.WriteString(s[start:i])
+ }
+ switch b {
+ case '\\', '"':
+ buf.WriteByte('\\')
+ buf.WriteByte(b)
+ case '\n':
+ buf.WriteByte('\\')
+ buf.WriteByte('n')
+ case '\r':
+ buf.WriteByte('\\')
+ buf.WriteByte('r')
+ case '\t':
+ buf.WriteByte('\\')
+ buf.WriteByte('t')
+ default:
+ // This encodes bytes < 0x20 except for \n, \r, and \t.
+ buf.WriteString(`\u00`)
+ buf.WriteByte(hex[b>>4])
+ buf.WriteByte(hex[b&0xF])
+ }
+ i++
+ start = i
+ continue
+ }
+ c, size := utf8.DecodeRuneInString(s[i:])
+ if c == utf8.RuneError {
+ if start < i {
+ buf.WriteString(s[start:i])
+ }
+ buf.WriteString(`\ufffd`)
+ i += size
+ start = i
+ continue
+ }
+ i += size
+ }
+ if start < len(s) {
+ buf.WriteString(s[start:])
+ }
+ buf.WriteByte('"')
+ n, err := w.Write(buf.Bytes())
+ poolBuffer(buf)
+ return n, err
+}
+
+// NOTE: keep in sync with writeQuoteString above.
+func writeQuotedBytes(w io.Writer, s []byte) (int, error) {
+ buf := getBuffer()
+ buf.WriteByte('"')
+ start := 0
+ for i := 0; i < len(s); {
+ if b := s[i]; b < utf8.RuneSelf {
+ if 0x20 <= b && b != '\\' && b != '"' {
+ i++
+ continue
+ }
+ if start < i {
+ buf.Write(s[start:i])
+ }
+ switch b {
+ case '\\', '"':
+ buf.WriteByte('\\')
+ buf.WriteByte(b)
+ case '\n':
+ buf.WriteByte('\\')
+ buf.WriteByte('n')
+ case '\r':
+ buf.WriteByte('\\')
+ buf.WriteByte('r')
+ case '\t':
+ buf.WriteByte('\\')
+ buf.WriteByte('t')
+ default:
+ // This encodes bytes < 0x20 except for \n, \r, and \t.
+ buf.WriteString(`\u00`)
+ buf.WriteByte(hex[b>>4])
+ buf.WriteByte(hex[b&0xF])
+ }
+ i++
+ start = i
+ continue
+ }
+ c, size := utf8.DecodeRune(s[i:])
+ if c == utf8.RuneError {
+ if start < i {
+ buf.Write(s[start:i])
+ }
+ buf.WriteString(`\ufffd`)
+ i += size
+ start = i
+ continue
+ }
+ i += size
+ }
+ if start < len(s) {
+ buf.Write(s[start:])
+ }
+ buf.WriteByte('"')
+ n, err := w.Write(buf.Bytes())
+ poolBuffer(buf)
+ return n, err
+}
+
+// getu4 decodes \uXXXX from the beginning of s, returning the hex value,
+// or it returns -1.
+func getu4(s []byte) rune {
+ if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
+ return -1
+ }
+ r, err := strconv.ParseUint(string(s[2:6]), 16, 64)
+ if err != nil {
+ return -1
+ }
+ return rune(r)
+}
+
+func unquoteBytes(s []byte) (t []byte, ok bool) {
+ if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {
+ return
+ }
+ s = s[1 : len(s)-1]
+
+ // Check for unusual characters. If there are none,
+ // then no unquoting is needed, so return a slice of the
+ // original bytes.
+ r := 0
+ for r < len(s) {
+ c := s[r]
+ if c == '\\' || c == '"' || c < ' ' {
+ break
+ }
+ if c < utf8.RuneSelf {
+ r++
+ continue
+ }
+ rr, size := utf8.DecodeRune(s[r:])
+ if rr == utf8.RuneError {
+ break
+ }
+ r += size
+ }
+ if r == len(s) {
+ return s, true
+ }
+
+ b := make([]byte, len(s)+2*utf8.UTFMax)
+ w := copy(b, s[0:r])
+ for r < len(s) {
+ // Out of room? Can only happen if s is full of
+ // malformed UTF-8 and we're replacing each
+ // byte with RuneError.
+ if w >= len(b)-2*utf8.UTFMax {
+ nb := make([]byte, (len(b)+utf8.UTFMax)*2)
+ copy(nb, b[0:w])
+ b = nb
+ }
+ switch c := s[r]; {
+ case c == '\\':
+ r++
+ if r >= len(s) {
+ return
+ }
+ switch s[r] {
+ default:
+ return
+ case '"', '\\', '/', '\'':
+ b[w] = s[r]
+ r++
+ w++
+ case 'b':
+ b[w] = '\b'
+ r++
+ w++
+ case 'f':
+ b[w] = '\f'
+ r++
+ w++
+ case 'n':
+ b[w] = '\n'
+ r++
+ w++
+ case 'r':
+ b[w] = '\r'
+ r++
+ w++
+ case 't':
+ b[w] = '\t'
+ r++
+ w++
+ case 'u':
+ r--
+ rr := getu4(s[r:])
+ if rr < 0 {
+ return
+ }
+ r += 6
+ if utf16.IsSurrogate(rr) {
+ rr1 := getu4(s[r:])
+ if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar {
+ // A valid pair; consume.
+ r += 6
+ w += utf8.EncodeRune(b[w:], dec)
+ break
+ }
+ // Invalid surrogate; fall back to replacement rune.
+ rr = unicode.ReplacementChar
+ }
+ w += utf8.EncodeRune(b[w:], rr)
+ }
+
+ // Quote, control characters are invalid.
+ case c == '"', c < ' ':
+ return
+
+ // ASCII
+ case c < utf8.RuneSelf:
+ b[w] = c
+ r++
+ w++
+
+ // Coerce to well-formed UTF-8.
+ default:
+ rr, size := utf8.DecodeRune(s[r:])
+ r += size
+ w += utf8.EncodeRune(b[w:], rr)
+ }
+ }
+ return b[0:w], true
+}
--- /dev/null
+The MIT License (MIT)
+
+Copyright (c) 2014 Chris Hines
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
--- /dev/null
+[](https://godoc.org/github.com/go-stack/stack)
+[](https://goreportcard.com/report/go-stack/stack)
+[](https://travis-ci.org/go-stack/stack)
+[](https://coveralls.io/github/go-stack/stack?branch=master)
+
+# stack
+
+Package stack implements utilities to capture, manipulate, and format call
+stacks. It provides a simpler API than package runtime.
+
+The implementation takes care of the minutia and special cases of interpreting
+the program counter (pc) values returned by runtime.Callers.
+
+## Versioning
+
+Package stack publishes releases via [semver](http://semver.org/) compatible Git
+tags prefixed with a single 'v'. The master branch always contains the latest
+release. The develop branch contains unreleased commits.
+
+## Formatting
+
+Package stack's types implement fmt.Formatter, which provides a simple and
+flexible way to declaratively configure formatting when used with logging or
+error tracking packages.
+
+```go
+func DoTheThing() {
+ c := stack.Caller(0)
+ log.Print(c) // "source.go:10"
+ log.Printf("%+v", c) // "pkg/path/source.go:10"
+ log.Printf("%n", c) // "DoTheThing"
+
+ s := stack.Trace().TrimRuntime()
+ log.Print(s) // "[source.go:15 caller.go:42 main.go:14]"
+}
+```
+
+See the docs for all of the supported formatting options.
--- /dev/null
+// Package stack implements utilities to capture, manipulate, and format call
+// stacks. It provides a simpler API than package runtime.
+//
+// The implementation takes care of the minutia and special cases of
+// interpreting the program counter (pc) values returned by runtime.Callers.
+//
+// Package stack's types implement fmt.Formatter, which provides a simple and
+// flexible way to declaratively configure formatting when used with logging
+// or error tracking packages.
+package stack
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "runtime"
+ "strconv"
+ "strings"
+)
+
+// Call records a single function invocation from a goroutine stack.
+type Call struct {
+ fn *runtime.Func
+ pc uintptr
+}
+
+// Caller returns a Call from the stack of the current goroutine. The argument
+// skip is the number of stack frames to ascend, with 0 identifying the
+// calling function.
+func Caller(skip int) Call {
+ var pcs [2]uintptr
+ n := runtime.Callers(skip+1, pcs[:])
+
+ var c Call
+
+ if n < 2 {
+ return c
+ }
+
+ c.pc = pcs[1]
+ if runtime.FuncForPC(pcs[0]).Name() != "runtime.sigpanic" {
+ c.pc--
+ }
+ c.fn = runtime.FuncForPC(c.pc)
+ return c
+}
+
+// String implements fmt.Stinger. It is equivalent to fmt.Sprintf("%v", c).
+func (c Call) String() string {
+ return fmt.Sprint(c)
+}
+
+// MarshalText implements encoding.TextMarshaler. It formats the Call the same
+// as fmt.Sprintf("%v", c).
+func (c Call) MarshalText() ([]byte, error) {
+ if c.fn == nil {
+ return nil, ErrNoFunc
+ }
+ buf := bytes.Buffer{}
+ fmt.Fprint(&buf, c)
+ return buf.Bytes(), nil
+}
+
+// ErrNoFunc means that the Call has a nil *runtime.Func. The most likely
+// cause is a Call with the zero value.
+var ErrNoFunc = errors.New("no call stack information")
+
+// Format implements fmt.Formatter with support for the following verbs.
+//
+// %s source file
+// %d line number
+// %n function name
+// %k last segment of the package path
+// %v equivalent to %s:%d
+//
+// It accepts the '+' and '#' flags for most of the verbs as follows.
+//
+// %+s path of source file relative to the compile time GOPATH
+// %#s full path of source file
+// %+n import path qualified function name
+// %+k full package path
+// %+v equivalent to %+s:%d
+// %#v equivalent to %#s:%d
+func (c Call) Format(s fmt.State, verb rune) {
+ if c.fn == nil {
+ fmt.Fprintf(s, "%%!%c(NOFUNC)", verb)
+ return
+ }
+
+ switch verb {
+ case 's', 'v':
+ file, line := c.fn.FileLine(c.pc)
+ switch {
+ case s.Flag('#'):
+ // done
+ case s.Flag('+'):
+ file = file[pkgIndex(file, c.fn.Name()):]
+ default:
+ const sep = "/"
+ if i := strings.LastIndex(file, sep); i != -1 {
+ file = file[i+len(sep):]
+ }
+ }
+ io.WriteString(s, file)
+ if verb == 'v' {
+ buf := [7]byte{':'}
+ s.Write(strconv.AppendInt(buf[:1], int64(line), 10))
+ }
+
+ case 'd':
+ _, line := c.fn.FileLine(c.pc)
+ buf := [6]byte{}
+ s.Write(strconv.AppendInt(buf[:0], int64(line), 10))
+
+ case 'k':
+ name := c.fn.Name()
+ const pathSep = "/"
+ start, end := 0, len(name)
+ if i := strings.LastIndex(name, pathSep); i != -1 {
+ start = i + len(pathSep)
+ }
+ const pkgSep = "."
+ if i := strings.Index(name[start:], pkgSep); i != -1 {
+ end = start + i
+ }
+ if s.Flag('+') {
+ start = 0
+ }
+ io.WriteString(s, name[start:end])
+
+ case 'n':
+ name := c.fn.Name()
+ if !s.Flag('+') {
+ const pathSep = "/"
+ if i := strings.LastIndex(name, pathSep); i != -1 {
+ name = name[i+len(pathSep):]
+ }
+ const pkgSep = "."
+ if i := strings.Index(name, pkgSep); i != -1 {
+ name = name[i+len(pkgSep):]
+ }
+ }
+ io.WriteString(s, name)
+ }
+}
+
+// PC returns the program counter for this call frame; multiple frames may
+// have the same PC value.
+func (c Call) PC() uintptr {
+ return c.pc
+}
+
+// name returns the import path qualified name of the function containing the
+// call.
+func (c Call) name() string {
+ if c.fn == nil {
+ return "???"
+ }
+ return c.fn.Name()
+}
+
+func (c Call) file() string {
+ if c.fn == nil {
+ return "???"
+ }
+ file, _ := c.fn.FileLine(c.pc)
+ return file
+}
+
+func (c Call) line() int {
+ if c.fn == nil {
+ return 0
+ }
+ _, line := c.fn.FileLine(c.pc)
+ return line
+}
+
+// CallStack records a sequence of function invocations from a goroutine
+// stack.
+type CallStack []Call
+
+// String implements fmt.Stinger. It is equivalent to fmt.Sprintf("%v", cs).
+func (cs CallStack) String() string {
+ return fmt.Sprint(cs)
+}
+
+var (
+ openBracketBytes = []byte("[")
+ closeBracketBytes = []byte("]")
+ spaceBytes = []byte(" ")
+)
+
+// MarshalText implements encoding.TextMarshaler. It formats the CallStack the
+// same as fmt.Sprintf("%v", cs).
+func (cs CallStack) MarshalText() ([]byte, error) {
+ buf := bytes.Buffer{}
+ buf.Write(openBracketBytes)
+ for i, pc := range cs {
+ if pc.fn == nil {
+ return nil, ErrNoFunc
+ }
+ if i > 0 {
+ buf.Write(spaceBytes)
+ }
+ fmt.Fprint(&buf, pc)
+ }
+ buf.Write(closeBracketBytes)
+ return buf.Bytes(), nil
+}
+
+// Format implements fmt.Formatter by printing the CallStack as square brackets
+// ([, ]) surrounding a space separated list of Calls each formatted with the
+// supplied verb and options.
+func (cs CallStack) Format(s fmt.State, verb rune) {
+ s.Write(openBracketBytes)
+ for i, pc := range cs {
+ if i > 0 {
+ s.Write(spaceBytes)
+ }
+ pc.Format(s, verb)
+ }
+ s.Write(closeBracketBytes)
+}
+
+// Trace returns a CallStack for the current goroutine with element 0
+// identifying the calling function.
+func Trace() CallStack {
+ var pcs [512]uintptr
+ n := runtime.Callers(2, pcs[:])
+ cs := make([]Call, n)
+
+ for i, pc := range pcs[:n] {
+ pcFix := pc
+ if i > 0 && cs[i-1].fn.Name() != "runtime.sigpanic" {
+ pcFix--
+ }
+ cs[i] = Call{
+ fn: runtime.FuncForPC(pcFix),
+ pc: pcFix,
+ }
+ }
+
+ return cs
+}
+
+// TrimBelow returns a slice of the CallStack with all entries below c
+// removed.
+func (cs CallStack) TrimBelow(c Call) CallStack {
+ for len(cs) > 0 && cs[0].pc != c.pc {
+ cs = cs[1:]
+ }
+ return cs
+}
+
+// TrimAbove returns a slice of the CallStack with all entries above c
+// removed.
+func (cs CallStack) TrimAbove(c Call) CallStack {
+ for len(cs) > 0 && cs[len(cs)-1].pc != c.pc {
+ cs = cs[:len(cs)-1]
+ }
+ return cs
+}
+
+// pkgIndex returns the index that results in file[index:] being the path of
+// file relative to the compile time GOPATH, and file[:index] being the
+// $GOPATH/src/ portion of file. funcName must be the name of a function in
+// file as returned by runtime.Func.Name.
+func pkgIndex(file, funcName string) int {
+ // As of Go 1.6.2 there is no direct way to know the compile time GOPATH
+ // at runtime, but we can infer the number of path segments in the GOPATH.
+ // We note that runtime.Func.Name() returns the function name qualified by
+ // the import path, which does not include the GOPATH. Thus we can trim
+ // segments from the beginning of the file path until the number of path
+ // separators remaining is one more than the number of path separators in
+ // the function name. For example, given:
+ //
+ // GOPATH /home/user
+ // file /home/user/src/pkg/sub/file.go
+ // fn.Name() pkg/sub.Type.Method
+ //
+ // We want to produce:
+ //
+ // file[:idx] == /home/user/src/
+ // file[idx:] == pkg/sub/file.go
+ //
+ // From this we can easily see that fn.Name() has one less path separator
+ // than our desired result for file[idx:]. We count separators from the
+ // end of the file path until it finds two more than in the function name
+ // and then move one character forward to preserve the initial path
+ // segment without a leading separator.
+ const sep = "/"
+ i := len(file)
+ for n := strings.Count(funcName, sep) + 2; n > 0; n-- {
+ i = strings.LastIndex(file[:i], sep)
+ if i == -1 {
+ i = -len(sep)
+ break
+ }
+ }
+ // get back to 0 or trim the leading separator
+ return i + len(sep)
+}
+
+var runtimePath string
+
+func init() {
+ var pcs [1]uintptr
+ runtime.Callers(0, pcs[:])
+ fn := runtime.FuncForPC(pcs[0])
+ file, _ := fn.FileLine(pcs[0])
+
+ idx := pkgIndex(file, fn.Name())
+
+ runtimePath = file[:idx]
+ if runtime.GOOS == "windows" {
+ runtimePath = strings.ToLower(runtimePath)
+ }
+}
+
+func inGoroot(c Call) bool {
+ file := c.file()
+ if len(file) == 0 || file[0] == '?' {
+ return true
+ }
+ if runtime.GOOS == "windows" {
+ file = strings.ToLower(file)
+ }
+ return strings.HasPrefix(file, runtimePath) || strings.HasSuffix(file, "/_testmain.go")
+}
+
+// TrimRuntime returns a slice of the CallStack with the topmost entries from
+// the go runtime removed. It considers any calls originating from unknown
+// files, files under GOROOT, or _testmain.go as part of the runtime.
+func (cs CallStack) TrimRuntime() CallStack {
+ for len(cs) > 0 && inGoroot(cs[len(cs)-1]) {
+ cs = cs[:len(cs)-1]
+ }
+ return cs
+}
--- /dev/null
+Protocol Buffers for Go with Gadgets
+
+Copyright (c) 2013, The GoGo Authors. All rights reserved.
+http://github.com/gogo/protobuf
+
+Go support for Protocol Buffers - Google's data interchange format
+
+Copyright 2010 The Go Authors. All rights reserved.
+https://github.com/golang/protobuf
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
--- /dev/null
+# Protocol Buffers for Go with Gadgets
+#
+# Copyright (c) 2013, The GoGo Authors. All rights reserved.
+# http://github.com/gogo/protobuf
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+regenerate:
+ go install github.com/gogo/protobuf/protoc-gen-gogo
+ protoc --gogo_out=Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor:../../../../ --proto_path=../../../../:../protobuf/:. *.proto
+
+restore:
+ cp gogo.pb.golden gogo.pb.go
+
+preserve:
+ cp gogo.pb.go gogo.pb.golden
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/*
+Package gogoproto provides extensions for protocol buffers to achieve:
+
+ - fast marshalling and unmarshalling.
+ - peace of mind by optionally generating test and benchmark code.
+ - more canonical Go structures.
+ - less typing by optionally generating extra helper code.
+ - goprotobuf compatibility
+
+More Canonical Go Structures
+
+A lot of time working with a goprotobuf struct will lead you to a place where you create another struct that is easier to work with and then have a function to copy the values between the two structs.
+You might also find that basic structs that started their life as part of an API need to be sent over the wire. With gob, you could just send it. With goprotobuf, you need to make a parallel struct.
+Gogoprotobuf tries to fix these problems with the nullable, embed, customtype and customname field extensions.
+
+ - nullable, if false, a field is generated without a pointer (see warning below).
+ - embed, if true, the field is generated as an embedded field.
+ - customtype, It works with the Marshal and Unmarshal methods, to allow you to have your own types in your struct, but marshal to bytes. For example, custom.Uuid or custom.Fixed128
+ - customname (beta), Changes the generated fieldname. This is especially useful when generated methods conflict with fieldnames.
+ - casttype (beta), Changes the generated fieldtype. All generated code assumes that this type is castable to the protocol buffer field type. It does not work for structs or enums.
+ - castkey (beta), Changes the generated fieldtype for a map key. All generated code assumes that this type is castable to the protocol buffer field type. Only supported on maps.
+ - castvalue (beta), Changes the generated fieldtype for a map value. All generated code assumes that this type is castable to the protocol buffer field type. Only supported on maps.
+
+Warning about nullable: According to the Protocol Buffer specification, you should be able to tell whether a field is set or unset. With the option nullable=false this feature is lost, since your non-nullable fields will always be set. It can be seen as a layer on top of Protocol Buffers, where before and after marshalling all non-nullable fields are set and they cannot be unset.
+
+Let us look at:
+
+ github.com/gogo/protobuf/test/example/example.proto
+
+for a quicker overview.
+
+The following message:
+
+ package test;
+
+ import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+ message A {
+ optional string Description = 1 [(gogoproto.nullable) = false];
+ optional int64 Number = 2 [(gogoproto.nullable) = false];
+ optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
+ }
+
+Will generate a go struct which looks a lot like this:
+
+ type A struct {
+ Description string
+ Number int64
+ Id github_com_gogo_protobuf_test_custom.Uuid
+ }
+
+You will see there are no pointers, since all fields are non-nullable.
+You will also see a custom type which marshals to a string.
+Be warned it is your responsibility to test your custom types thoroughly.
+You should think of every possible empty and nil case for your marshaling, unmarshaling and size methods.
+
+Next we will embed the message A in message B.
+
+ message B {
+ optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
+ repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
+ }
+
+See below that A is embedded in B.
+
+ type B struct {
+ A
+ G []github_com_gogo_protobuf_test_custom.Uint128
+ }
+
+Also see the repeated custom type.
+
+ type Uint128 [2]uint64
+
+Next we will create a custom name for one of our fields.
+
+ message C {
+ optional int64 size = 1 [(gogoproto.customname) = "MySize"];
+ }
+
+See below that the field's name is MySize and not Size.
+
+ type C struct {
+ MySize *int64
+ }
+
+The is useful when having a protocol buffer message with a field name which conflicts with a generated method.
+As an example, having a field name size and using the sizer plugin to generate a Size method will cause a go compiler error.
+Using customname you can fix this error without changing the field name.
+This is typically useful when working with a protocol buffer that was designed before these methods and/or the go language were avialable.
+
+Gogoprotobuf also has some more subtle changes, these could be changed back:
+
+ - the generated package name for imports do not have the extra /filename.pb,
+ but are actually the imports specified in the .proto file.
+
+Gogoprotobuf also has lost some features which should be brought back with time:
+
+ - Marshalling and unmarshalling with reflect and without the unsafe package,
+ this requires work in pointer_reflect.go
+
+Why does nullable break protocol buffer specifications:
+
+The protocol buffer specification states, somewhere, that you should be able to tell whether a
+field is set or unset. With the option nullable=false this feature is lost,
+since your non-nullable fields will always be set. It can be seen as a layer on top of
+protocol buffers, where before and after marshalling all non-nullable fields are set
+and they cannot be unset.
+
+Goprotobuf Compatibility:
+
+Gogoprotobuf is compatible with Goprotobuf, because it is compatible with protocol buffers.
+Gogoprotobuf generates the same code as goprotobuf if no extensions are used.
+The enumprefix, getters and stringer extensions can be used to remove some of the unnecessary code generated by goprotobuf:
+
+ - gogoproto_import, if false, the generated code imports github.com/golang/protobuf/proto instead of github.com/gogo/protobuf/proto.
+ - goproto_enum_prefix, if false, generates the enum constant names without the messagetype prefix
+ - goproto_enum_stringer (experimental), if false, the enum is generated without the default string method, this is useful for rather using enum_stringer, or allowing you to write your own string method.
+ - goproto_getters, if false, the message is generated without get methods, this is useful when you would rather want to use face
+ - goproto_stringer, if false, the message is generated without the default string method, this is useful for rather using stringer, or allowing you to write your own string method.
+ - goproto_extensions_map (beta), if false, the extensions field is generated as type []byte instead of type map[int32]proto.Extension
+ - goproto_unrecognized (beta), if false, XXX_unrecognized field is not generated. This is useful in conjunction with gogoproto.nullable=false, to generate structures completely devoid of pointers and reduce GC pressure at the cost of losing information about unrecognized fields.
+ - goproto_registration (beta), if true, the generated files will register all messages and types against both gogo/protobuf and golang/protobuf. This is necessary when using third-party packages which read registrations from golang/protobuf (such as the grpc-gateway).
+
+Less Typing and Peace of Mind is explained in their specific plugin folders godoc:
+
+ - github.com/gogo/protobuf/plugin/<extension_name>
+
+If you do not use any of these extension the code that is generated
+will be the same as if goprotobuf has generated it.
+
+The most complete way to see examples is to look at
+
+ github.com/gogo/protobuf/test/thetest.proto
+
+Gogoprototest is a seperate project,
+because we want to keep gogoprotobuf independant of goprotobuf,
+but we still want to test it thoroughly.
+
+*/
+package gogoproto
--- /dev/null
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: gogo.proto
+
+/*
+Package gogoproto is a generated protocol buffer package.
+
+It is generated from these files:
+ gogo.proto
+
+It has these top-level messages:
+*/
+package gogoproto
+
+import proto "github.com/gogo/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import google_protobuf "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
+
+var E_GoprotoEnumPrefix = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.EnumOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 62001,
+ Name: "gogoproto.goproto_enum_prefix",
+ Tag: "varint,62001,opt,name=goproto_enum_prefix,json=goprotoEnumPrefix",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoEnumStringer = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.EnumOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 62021,
+ Name: "gogoproto.goproto_enum_stringer",
+ Tag: "varint,62021,opt,name=goproto_enum_stringer,json=goprotoEnumStringer",
+ Filename: "gogo.proto",
+}
+
+var E_EnumStringer = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.EnumOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 62022,
+ Name: "gogoproto.enum_stringer",
+ Tag: "varint,62022,opt,name=enum_stringer,json=enumStringer",
+ Filename: "gogo.proto",
+}
+
+var E_EnumCustomname = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.EnumOptions)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 62023,
+ Name: "gogoproto.enum_customname",
+ Tag: "bytes,62023,opt,name=enum_customname,json=enumCustomname",
+ Filename: "gogo.proto",
+}
+
+var E_Enumdecl = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.EnumOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 62024,
+ Name: "gogoproto.enumdecl",
+ Tag: "varint,62024,opt,name=enumdecl",
+ Filename: "gogo.proto",
+}
+
+var E_EnumvalueCustomname = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.EnumValueOptions)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 66001,
+ Name: "gogoproto.enumvalue_customname",
+ Tag: "bytes,66001,opt,name=enumvalue_customname,json=enumvalueCustomname",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoGettersAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63001,
+ Name: "gogoproto.goproto_getters_all",
+ Tag: "varint,63001,opt,name=goproto_getters_all,json=goprotoGettersAll",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoEnumPrefixAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63002,
+ Name: "gogoproto.goproto_enum_prefix_all",
+ Tag: "varint,63002,opt,name=goproto_enum_prefix_all,json=goprotoEnumPrefixAll",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoStringerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63003,
+ Name: "gogoproto.goproto_stringer_all",
+ Tag: "varint,63003,opt,name=goproto_stringer_all,json=goprotoStringerAll",
+ Filename: "gogo.proto",
+}
+
+var E_VerboseEqualAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63004,
+ Name: "gogoproto.verbose_equal_all",
+ Tag: "varint,63004,opt,name=verbose_equal_all,json=verboseEqualAll",
+ Filename: "gogo.proto",
+}
+
+var E_FaceAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63005,
+ Name: "gogoproto.face_all",
+ Tag: "varint,63005,opt,name=face_all,json=faceAll",
+ Filename: "gogo.proto",
+}
+
+var E_GostringAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63006,
+ Name: "gogoproto.gostring_all",
+ Tag: "varint,63006,opt,name=gostring_all,json=gostringAll",
+ Filename: "gogo.proto",
+}
+
+var E_PopulateAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63007,
+ Name: "gogoproto.populate_all",
+ Tag: "varint,63007,opt,name=populate_all,json=populateAll",
+ Filename: "gogo.proto",
+}
+
+var E_StringerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63008,
+ Name: "gogoproto.stringer_all",
+ Tag: "varint,63008,opt,name=stringer_all,json=stringerAll",
+ Filename: "gogo.proto",
+}
+
+var E_OnlyoneAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63009,
+ Name: "gogoproto.onlyone_all",
+ Tag: "varint,63009,opt,name=onlyone_all,json=onlyoneAll",
+ Filename: "gogo.proto",
+}
+
+var E_EqualAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63013,
+ Name: "gogoproto.equal_all",
+ Tag: "varint,63013,opt,name=equal_all,json=equalAll",
+ Filename: "gogo.proto",
+}
+
+var E_DescriptionAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63014,
+ Name: "gogoproto.description_all",
+ Tag: "varint,63014,opt,name=description_all,json=descriptionAll",
+ Filename: "gogo.proto",
+}
+
+var E_TestgenAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63015,
+ Name: "gogoproto.testgen_all",
+ Tag: "varint,63015,opt,name=testgen_all,json=testgenAll",
+ Filename: "gogo.proto",
+}
+
+var E_BenchgenAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63016,
+ Name: "gogoproto.benchgen_all",
+ Tag: "varint,63016,opt,name=benchgen_all,json=benchgenAll",
+ Filename: "gogo.proto",
+}
+
+var E_MarshalerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63017,
+ Name: "gogoproto.marshaler_all",
+ Tag: "varint,63017,opt,name=marshaler_all,json=marshalerAll",
+ Filename: "gogo.proto",
+}
+
+var E_UnmarshalerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63018,
+ Name: "gogoproto.unmarshaler_all",
+ Tag: "varint,63018,opt,name=unmarshaler_all,json=unmarshalerAll",
+ Filename: "gogo.proto",
+}
+
+var E_StableMarshalerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63019,
+ Name: "gogoproto.stable_marshaler_all",
+ Tag: "varint,63019,opt,name=stable_marshaler_all,json=stableMarshalerAll",
+ Filename: "gogo.proto",
+}
+
+var E_SizerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63020,
+ Name: "gogoproto.sizer_all",
+ Tag: "varint,63020,opt,name=sizer_all,json=sizerAll",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoEnumStringerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63021,
+ Name: "gogoproto.goproto_enum_stringer_all",
+ Tag: "varint,63021,opt,name=goproto_enum_stringer_all,json=goprotoEnumStringerAll",
+ Filename: "gogo.proto",
+}
+
+var E_EnumStringerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63022,
+ Name: "gogoproto.enum_stringer_all",
+ Tag: "varint,63022,opt,name=enum_stringer_all,json=enumStringerAll",
+ Filename: "gogo.proto",
+}
+
+var E_UnsafeMarshalerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63023,
+ Name: "gogoproto.unsafe_marshaler_all",
+ Tag: "varint,63023,opt,name=unsafe_marshaler_all,json=unsafeMarshalerAll",
+ Filename: "gogo.proto",
+}
+
+var E_UnsafeUnmarshalerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63024,
+ Name: "gogoproto.unsafe_unmarshaler_all",
+ Tag: "varint,63024,opt,name=unsafe_unmarshaler_all,json=unsafeUnmarshalerAll",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoExtensionsMapAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63025,
+ Name: "gogoproto.goproto_extensions_map_all",
+ Tag: "varint,63025,opt,name=goproto_extensions_map_all,json=goprotoExtensionsMapAll",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoUnrecognizedAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63026,
+ Name: "gogoproto.goproto_unrecognized_all",
+ Tag: "varint,63026,opt,name=goproto_unrecognized_all,json=goprotoUnrecognizedAll",
+ Filename: "gogo.proto",
+}
+
+var E_GogoprotoImport = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63027,
+ Name: "gogoproto.gogoproto_import",
+ Tag: "varint,63027,opt,name=gogoproto_import,json=gogoprotoImport",
+ Filename: "gogo.proto",
+}
+
+var E_ProtosizerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63028,
+ Name: "gogoproto.protosizer_all",
+ Tag: "varint,63028,opt,name=protosizer_all,json=protosizerAll",
+ Filename: "gogo.proto",
+}
+
+var E_CompareAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63029,
+ Name: "gogoproto.compare_all",
+ Tag: "varint,63029,opt,name=compare_all,json=compareAll",
+ Filename: "gogo.proto",
+}
+
+var E_TypedeclAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63030,
+ Name: "gogoproto.typedecl_all",
+ Tag: "varint,63030,opt,name=typedecl_all,json=typedeclAll",
+ Filename: "gogo.proto",
+}
+
+var E_EnumdeclAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63031,
+ Name: "gogoproto.enumdecl_all",
+ Tag: "varint,63031,opt,name=enumdecl_all,json=enumdeclAll",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoRegistration = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63032,
+ Name: "gogoproto.goproto_registration",
+ Tag: "varint,63032,opt,name=goproto_registration,json=goprotoRegistration",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoGetters = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64001,
+ Name: "gogoproto.goproto_getters",
+ Tag: "varint,64001,opt,name=goproto_getters,json=goprotoGetters",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoStringer = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64003,
+ Name: "gogoproto.goproto_stringer",
+ Tag: "varint,64003,opt,name=goproto_stringer,json=goprotoStringer",
+ Filename: "gogo.proto",
+}
+
+var E_VerboseEqual = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64004,
+ Name: "gogoproto.verbose_equal",
+ Tag: "varint,64004,opt,name=verbose_equal,json=verboseEqual",
+ Filename: "gogo.proto",
+}
+
+var E_Face = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64005,
+ Name: "gogoproto.face",
+ Tag: "varint,64005,opt,name=face",
+ Filename: "gogo.proto",
+}
+
+var E_Gostring = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64006,
+ Name: "gogoproto.gostring",
+ Tag: "varint,64006,opt,name=gostring",
+ Filename: "gogo.proto",
+}
+
+var E_Populate = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64007,
+ Name: "gogoproto.populate",
+ Tag: "varint,64007,opt,name=populate",
+ Filename: "gogo.proto",
+}
+
+var E_Stringer = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 67008,
+ Name: "gogoproto.stringer",
+ Tag: "varint,67008,opt,name=stringer",
+ Filename: "gogo.proto",
+}
+
+var E_Onlyone = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64009,
+ Name: "gogoproto.onlyone",
+ Tag: "varint,64009,opt,name=onlyone",
+ Filename: "gogo.proto",
+}
+
+var E_Equal = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64013,
+ Name: "gogoproto.equal",
+ Tag: "varint,64013,opt,name=equal",
+ Filename: "gogo.proto",
+}
+
+var E_Description = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64014,
+ Name: "gogoproto.description",
+ Tag: "varint,64014,opt,name=description",
+ Filename: "gogo.proto",
+}
+
+var E_Testgen = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64015,
+ Name: "gogoproto.testgen",
+ Tag: "varint,64015,opt,name=testgen",
+ Filename: "gogo.proto",
+}
+
+var E_Benchgen = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64016,
+ Name: "gogoproto.benchgen",
+ Tag: "varint,64016,opt,name=benchgen",
+ Filename: "gogo.proto",
+}
+
+var E_Marshaler = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64017,
+ Name: "gogoproto.marshaler",
+ Tag: "varint,64017,opt,name=marshaler",
+ Filename: "gogo.proto",
+}
+
+var E_Unmarshaler = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64018,
+ Name: "gogoproto.unmarshaler",
+ Tag: "varint,64018,opt,name=unmarshaler",
+ Filename: "gogo.proto",
+}
+
+var E_StableMarshaler = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64019,
+ Name: "gogoproto.stable_marshaler",
+ Tag: "varint,64019,opt,name=stable_marshaler,json=stableMarshaler",
+ Filename: "gogo.proto",
+}
+
+var E_Sizer = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64020,
+ Name: "gogoproto.sizer",
+ Tag: "varint,64020,opt,name=sizer",
+ Filename: "gogo.proto",
+}
+
+var E_UnsafeMarshaler = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64023,
+ Name: "gogoproto.unsafe_marshaler",
+ Tag: "varint,64023,opt,name=unsafe_marshaler,json=unsafeMarshaler",
+ Filename: "gogo.proto",
+}
+
+var E_UnsafeUnmarshaler = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64024,
+ Name: "gogoproto.unsafe_unmarshaler",
+ Tag: "varint,64024,opt,name=unsafe_unmarshaler,json=unsafeUnmarshaler",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoExtensionsMap = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64025,
+ Name: "gogoproto.goproto_extensions_map",
+ Tag: "varint,64025,opt,name=goproto_extensions_map,json=goprotoExtensionsMap",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoUnrecognized = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64026,
+ Name: "gogoproto.goproto_unrecognized",
+ Tag: "varint,64026,opt,name=goproto_unrecognized,json=goprotoUnrecognized",
+ Filename: "gogo.proto",
+}
+
+var E_Protosizer = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64028,
+ Name: "gogoproto.protosizer",
+ Tag: "varint,64028,opt,name=protosizer",
+ Filename: "gogo.proto",
+}
+
+var E_Compare = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64029,
+ Name: "gogoproto.compare",
+ Tag: "varint,64029,opt,name=compare",
+ Filename: "gogo.proto",
+}
+
+var E_Typedecl = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64030,
+ Name: "gogoproto.typedecl",
+ Tag: "varint,64030,opt,name=typedecl",
+ Filename: "gogo.proto",
+}
+
+var E_Nullable = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 65001,
+ Name: "gogoproto.nullable",
+ Tag: "varint,65001,opt,name=nullable",
+ Filename: "gogo.proto",
+}
+
+var E_Embed = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 65002,
+ Name: "gogoproto.embed",
+ Tag: "varint,65002,opt,name=embed",
+ Filename: "gogo.proto",
+}
+
+var E_Customtype = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 65003,
+ Name: "gogoproto.customtype",
+ Tag: "bytes,65003,opt,name=customtype",
+ Filename: "gogo.proto",
+}
+
+var E_Customname = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 65004,
+ Name: "gogoproto.customname",
+ Tag: "bytes,65004,opt,name=customname",
+ Filename: "gogo.proto",
+}
+
+var E_Jsontag = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 65005,
+ Name: "gogoproto.jsontag",
+ Tag: "bytes,65005,opt,name=jsontag",
+ Filename: "gogo.proto",
+}
+
+var E_Moretags = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 65006,
+ Name: "gogoproto.moretags",
+ Tag: "bytes,65006,opt,name=moretags",
+ Filename: "gogo.proto",
+}
+
+var E_Casttype = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 65007,
+ Name: "gogoproto.casttype",
+ Tag: "bytes,65007,opt,name=casttype",
+ Filename: "gogo.proto",
+}
+
+var E_Castkey = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 65008,
+ Name: "gogoproto.castkey",
+ Tag: "bytes,65008,opt,name=castkey",
+ Filename: "gogo.proto",
+}
+
+var E_Castvalue = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 65009,
+ Name: "gogoproto.castvalue",
+ Tag: "bytes,65009,opt,name=castvalue",
+ Filename: "gogo.proto",
+}
+
+var E_Stdtime = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 65010,
+ Name: "gogoproto.stdtime",
+ Tag: "varint,65010,opt,name=stdtime",
+ Filename: "gogo.proto",
+}
+
+var E_Stdduration = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 65011,
+ Name: "gogoproto.stdduration",
+ Tag: "varint,65011,opt,name=stdduration",
+ Filename: "gogo.proto",
+}
+
+func init() {
+ proto.RegisterExtension(E_GoprotoEnumPrefix)
+ proto.RegisterExtension(E_GoprotoEnumStringer)
+ proto.RegisterExtension(E_EnumStringer)
+ proto.RegisterExtension(E_EnumCustomname)
+ proto.RegisterExtension(E_Enumdecl)
+ proto.RegisterExtension(E_EnumvalueCustomname)
+ proto.RegisterExtension(E_GoprotoGettersAll)
+ proto.RegisterExtension(E_GoprotoEnumPrefixAll)
+ proto.RegisterExtension(E_GoprotoStringerAll)
+ proto.RegisterExtension(E_VerboseEqualAll)
+ proto.RegisterExtension(E_FaceAll)
+ proto.RegisterExtension(E_GostringAll)
+ proto.RegisterExtension(E_PopulateAll)
+ proto.RegisterExtension(E_StringerAll)
+ proto.RegisterExtension(E_OnlyoneAll)
+ proto.RegisterExtension(E_EqualAll)
+ proto.RegisterExtension(E_DescriptionAll)
+ proto.RegisterExtension(E_TestgenAll)
+ proto.RegisterExtension(E_BenchgenAll)
+ proto.RegisterExtension(E_MarshalerAll)
+ proto.RegisterExtension(E_UnmarshalerAll)
+ proto.RegisterExtension(E_StableMarshalerAll)
+ proto.RegisterExtension(E_SizerAll)
+ proto.RegisterExtension(E_GoprotoEnumStringerAll)
+ proto.RegisterExtension(E_EnumStringerAll)
+ proto.RegisterExtension(E_UnsafeMarshalerAll)
+ proto.RegisterExtension(E_UnsafeUnmarshalerAll)
+ proto.RegisterExtension(E_GoprotoExtensionsMapAll)
+ proto.RegisterExtension(E_GoprotoUnrecognizedAll)
+ proto.RegisterExtension(E_GogoprotoImport)
+ proto.RegisterExtension(E_ProtosizerAll)
+ proto.RegisterExtension(E_CompareAll)
+ proto.RegisterExtension(E_TypedeclAll)
+ proto.RegisterExtension(E_EnumdeclAll)
+ proto.RegisterExtension(E_GoprotoRegistration)
+ proto.RegisterExtension(E_GoprotoGetters)
+ proto.RegisterExtension(E_GoprotoStringer)
+ proto.RegisterExtension(E_VerboseEqual)
+ proto.RegisterExtension(E_Face)
+ proto.RegisterExtension(E_Gostring)
+ proto.RegisterExtension(E_Populate)
+ proto.RegisterExtension(E_Stringer)
+ proto.RegisterExtension(E_Onlyone)
+ proto.RegisterExtension(E_Equal)
+ proto.RegisterExtension(E_Description)
+ proto.RegisterExtension(E_Testgen)
+ proto.RegisterExtension(E_Benchgen)
+ proto.RegisterExtension(E_Marshaler)
+ proto.RegisterExtension(E_Unmarshaler)
+ proto.RegisterExtension(E_StableMarshaler)
+ proto.RegisterExtension(E_Sizer)
+ proto.RegisterExtension(E_UnsafeMarshaler)
+ proto.RegisterExtension(E_UnsafeUnmarshaler)
+ proto.RegisterExtension(E_GoprotoExtensionsMap)
+ proto.RegisterExtension(E_GoprotoUnrecognized)
+ proto.RegisterExtension(E_Protosizer)
+ proto.RegisterExtension(E_Compare)
+ proto.RegisterExtension(E_Typedecl)
+ proto.RegisterExtension(E_Nullable)
+ proto.RegisterExtension(E_Embed)
+ proto.RegisterExtension(E_Customtype)
+ proto.RegisterExtension(E_Customname)
+ proto.RegisterExtension(E_Jsontag)
+ proto.RegisterExtension(E_Moretags)
+ proto.RegisterExtension(E_Casttype)
+ proto.RegisterExtension(E_Castkey)
+ proto.RegisterExtension(E_Castvalue)
+ proto.RegisterExtension(E_Stdtime)
+ proto.RegisterExtension(E_Stdduration)
+}
+
+func init() { proto.RegisterFile("gogo.proto", fileDescriptorGogo) }
+
+var fileDescriptorGogo = []byte{
+ // 1220 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x98, 0x4b, 0x6f, 0x1c, 0x45,
+ 0x10, 0x80, 0x85, 0x48, 0x14, 0x6f, 0xd9, 0x8e, 0xf1, 0xda, 0x98, 0x10, 0x81, 0x08, 0x9c, 0x38,
+ 0xd9, 0xa7, 0x08, 0xa5, 0xad, 0xc8, 0x72, 0x2c, 0xc7, 0x4a, 0x84, 0xc1, 0x98, 0x38, 0xbc, 0x0e,
+ 0xab, 0xd9, 0xdd, 0xf6, 0x78, 0x60, 0x66, 0x7a, 0x98, 0xe9, 0x89, 0xe2, 0xdc, 0x50, 0x78, 0x08,
+ 0x21, 0xde, 0x48, 0x90, 0x90, 0x04, 0x38, 0xf0, 0x7e, 0x86, 0xf7, 0x91, 0x0b, 0x8f, 0x2b, 0xff,
+ 0x81, 0x0b, 0x60, 0xde, 0xbe, 0xf9, 0x82, 0x6a, 0xb6, 0x6a, 0xb6, 0x67, 0xbd, 0x52, 0xf7, 0xde,
+ 0xc6, 0xeb, 0xfe, 0xbe, 0xad, 0xa9, 0x9a, 0xae, 0xea, 0x59, 0x00, 0x5f, 0xf9, 0x6a, 0x3a, 0x49,
+ 0x95, 0x56, 0xf5, 0x1a, 0x5e, 0x17, 0x97, 0x07, 0x0f, 0xf9, 0x4a, 0xf9, 0xa1, 0x9c, 0x29, 0xfe,
+ 0x6a, 0xe6, 0xeb, 0x33, 0x6d, 0x99, 0xb5, 0xd2, 0x20, 0xd1, 0x2a, 0xed, 0x2c, 0x16, 0x77, 0xc1,
+ 0x04, 0x2d, 0x6e, 0xc8, 0x38, 0x8f, 0x1a, 0x49, 0x2a, 0xd7, 0x83, 0xb3, 0xf5, 0x9b, 0xa6, 0x3b,
+ 0xe4, 0x34, 0x93, 0xd3, 0x8b, 0x71, 0x1e, 0xdd, 0x9d, 0xe8, 0x40, 0xc5, 0xd9, 0x81, 0xab, 0xbf,
+ 0x5c, 0x7b, 0xe8, 0x9a, 0xdb, 0x87, 0x56, 0xc7, 0x09, 0xc5, 0xff, 0xad, 0x14, 0xa0, 0x58, 0x85,
+ 0xeb, 0x2b, 0xbe, 0x4c, 0xa7, 0x41, 0xec, 0xcb, 0xd4, 0x62, 0xfc, 0x9e, 0x8c, 0x13, 0x86, 0xf1,
+ 0x5e, 0x42, 0xc5, 0x02, 0x8c, 0x0e, 0xe2, 0xfa, 0x81, 0x5c, 0x23, 0xd2, 0x94, 0x2c, 0xc1, 0x58,
+ 0x21, 0x69, 0xe5, 0x99, 0x56, 0x51, 0xec, 0x45, 0xd2, 0xa2, 0xf9, 0xb1, 0xd0, 0xd4, 0x56, 0xf7,
+ 0x23, 0xb6, 0x50, 0x52, 0x42, 0xc0, 0x10, 0x7e, 0xd2, 0x96, 0xad, 0xd0, 0x62, 0xf8, 0x89, 0x02,
+ 0x29, 0xd7, 0x8b, 0xd3, 0x30, 0x89, 0xd7, 0x67, 0xbc, 0x30, 0x97, 0x66, 0x24, 0xb7, 0xf6, 0xf5,
+ 0x9c, 0xc6, 0x65, 0x2c, 0xfb, 0xf9, 0xfc, 0x9e, 0x22, 0x9c, 0x89, 0x52, 0x60, 0xc4, 0x64, 0x54,
+ 0xd1, 0x97, 0x5a, 0xcb, 0x34, 0x6b, 0x78, 0x61, 0xbf, 0xf0, 0x8e, 0x07, 0x61, 0x69, 0xbc, 0xb0,
+ 0x55, 0xad, 0xe2, 0x52, 0x87, 0x9c, 0x0f, 0x43, 0xb1, 0x06, 0x37, 0xf4, 0x79, 0x2a, 0x1c, 0x9c,
+ 0x17, 0xc9, 0x39, 0xb9, 0xeb, 0xc9, 0x40, 0xed, 0x0a, 0xf0, 0xe7, 0x65, 0x2d, 0x1d, 0x9c, 0xaf,
+ 0x93, 0xb3, 0x4e, 0x2c, 0x97, 0x14, 0x8d, 0x27, 0x61, 0xfc, 0x8c, 0x4c, 0x9b, 0x2a, 0x93, 0x0d,
+ 0xf9, 0x68, 0xee, 0x85, 0x0e, 0xba, 0x4b, 0xa4, 0x1b, 0x23, 0x70, 0x11, 0x39, 0x74, 0x1d, 0x81,
+ 0xa1, 0x75, 0xaf, 0x25, 0x1d, 0x14, 0x97, 0x49, 0xb1, 0x0f, 0xd7, 0x23, 0x3a, 0x0f, 0x23, 0xbe,
+ 0xea, 0xdc, 0x92, 0x03, 0x7e, 0x85, 0xf0, 0x61, 0x66, 0x48, 0x91, 0xa8, 0x24, 0x0f, 0x3d, 0xed,
+ 0x12, 0xc1, 0x1b, 0xac, 0x60, 0x86, 0x14, 0x03, 0xa4, 0xf5, 0x4d, 0x56, 0x64, 0x46, 0x3e, 0xe7,
+ 0x60, 0x58, 0xc5, 0xe1, 0xa6, 0x8a, 0x5d, 0x82, 0x78, 0x8b, 0x0c, 0x40, 0x08, 0x0a, 0x66, 0xa1,
+ 0xe6, 0x5a, 0x88, 0xb7, 0xb7, 0x78, 0x7b, 0x70, 0x05, 0x96, 0x60, 0x8c, 0x1b, 0x54, 0xa0, 0x62,
+ 0x07, 0xc5, 0x3b, 0xa4, 0xd8, 0x6f, 0x60, 0x74, 0x1b, 0x5a, 0x66, 0xda, 0x97, 0x2e, 0x92, 0x77,
+ 0xf9, 0x36, 0x08, 0xa1, 0x54, 0x36, 0x65, 0xdc, 0xda, 0x70, 0x33, 0xbc, 0xc7, 0xa9, 0x64, 0x06,
+ 0x15, 0x0b, 0x30, 0x1a, 0x79, 0x69, 0xb6, 0xe1, 0x85, 0x4e, 0xe5, 0x78, 0x9f, 0x1c, 0x23, 0x25,
+ 0x44, 0x19, 0xc9, 0xe3, 0x41, 0x34, 0x1f, 0x70, 0x46, 0x0c, 0x8c, 0xb6, 0x5e, 0xa6, 0xbd, 0x66,
+ 0x28, 0x1b, 0x83, 0xd8, 0x3e, 0xe4, 0xad, 0xd7, 0x61, 0x97, 0x4d, 0xe3, 0x2c, 0xd4, 0xb2, 0xe0,
+ 0x9c, 0x93, 0xe6, 0x23, 0xae, 0x74, 0x01, 0x20, 0xfc, 0x00, 0xdc, 0xd8, 0x77, 0x4c, 0x38, 0xc8,
+ 0x3e, 0x26, 0xd9, 0x54, 0x9f, 0x51, 0x41, 0x2d, 0x61, 0x50, 0xe5, 0x27, 0xdc, 0x12, 0x64, 0x8f,
+ 0x6b, 0x05, 0x26, 0xf3, 0x38, 0xf3, 0xd6, 0x07, 0xcb, 0xda, 0xa7, 0x9c, 0xb5, 0x0e, 0x5b, 0xc9,
+ 0xda, 0x29, 0x98, 0x22, 0xe3, 0x60, 0x75, 0xfd, 0x8c, 0x1b, 0x6b, 0x87, 0x5e, 0xab, 0x56, 0xf7,
+ 0x21, 0x38, 0x58, 0xa6, 0xf3, 0xac, 0x96, 0x71, 0x86, 0x4c, 0x23, 0xf2, 0x12, 0x07, 0xf3, 0x55,
+ 0x32, 0x73, 0xc7, 0x5f, 0x2c, 0x05, 0xcb, 0x5e, 0x82, 0xf2, 0xfb, 0xe1, 0x00, 0xcb, 0xf3, 0x38,
+ 0x95, 0x2d, 0xe5, 0xc7, 0xc1, 0x39, 0xd9, 0x76, 0x50, 0x7f, 0xde, 0x53, 0xaa, 0x35, 0x03, 0x47,
+ 0xf3, 0x09, 0xb8, 0xae, 0x3c, 0xab, 0x34, 0x82, 0x28, 0x51, 0xa9, 0xb6, 0x18, 0xbf, 0xe0, 0x4a,
+ 0x95, 0xdc, 0x89, 0x02, 0x13, 0x8b, 0xb0, 0xbf, 0xf8, 0xd3, 0xf5, 0x91, 0xfc, 0x92, 0x44, 0xa3,
+ 0x5d, 0x8a, 0x1a, 0x47, 0x4b, 0x45, 0x89, 0x97, 0xba, 0xf4, 0xbf, 0xaf, 0xb8, 0x71, 0x10, 0x42,
+ 0x8d, 0x43, 0x6f, 0x26, 0x12, 0xa7, 0xbd, 0x83, 0xe1, 0x6b, 0x6e, 0x1c, 0xcc, 0x90, 0x82, 0x0f,
+ 0x0c, 0x0e, 0x8a, 0x6f, 0x58, 0xc1, 0x0c, 0x2a, 0xee, 0xe9, 0x0e, 0xda, 0x54, 0xfa, 0x41, 0xa6,
+ 0x53, 0x0f, 0x57, 0x5b, 0x54, 0xdf, 0x6e, 0x55, 0x0f, 0x61, 0xab, 0x06, 0x2a, 0x4e, 0xc2, 0x58,
+ 0xcf, 0x11, 0xa3, 0x7e, 0xcb, 0x2e, 0xdb, 0xb2, 0xcc, 0x32, 0xcf, 0x2f, 0x85, 0x8f, 0x6d, 0x53,
+ 0x33, 0xaa, 0x9e, 0x30, 0xc4, 0x9d, 0x58, 0xf7, 0xea, 0x39, 0xc0, 0x2e, 0x3b, 0xbf, 0x5d, 0x96,
+ 0xbe, 0x72, 0x0c, 0x10, 0xc7, 0x61, 0xb4, 0x72, 0x06, 0xb0, 0xab, 0x1e, 0x27, 0xd5, 0x88, 0x79,
+ 0x04, 0x10, 0x87, 0x61, 0x0f, 0xce, 0x73, 0x3b, 0xfe, 0x04, 0xe1, 0xc5, 0x72, 0x71, 0x14, 0x86,
+ 0x78, 0x8e, 0xdb, 0xd1, 0x27, 0x09, 0x2d, 0x11, 0xc4, 0x79, 0x86, 0xdb, 0xf1, 0xa7, 0x18, 0x67,
+ 0x04, 0x71, 0xf7, 0x14, 0x7e, 0xf7, 0xcc, 0x1e, 0xea, 0xc3, 0x9c, 0xbb, 0x59, 0xd8, 0x47, 0xc3,
+ 0xdb, 0x4e, 0x3f, 0x4d, 0x5f, 0xce, 0x84, 0xb8, 0x03, 0xf6, 0x3a, 0x26, 0xfc, 0x59, 0x42, 0x3b,
+ 0xeb, 0xc5, 0x02, 0x0c, 0x1b, 0x03, 0xdb, 0x8e, 0x3f, 0x47, 0xb8, 0x49, 0x61, 0xe8, 0x34, 0xb0,
+ 0xed, 0x82, 0xe7, 0x39, 0x74, 0x22, 0x30, 0x6d, 0x3c, 0xab, 0xed, 0xf4, 0x0b, 0x9c, 0x75, 0x46,
+ 0xc4, 0x1c, 0xd4, 0xca, 0xfe, 0x6b, 0xe7, 0x5f, 0x24, 0xbe, 0xcb, 0x60, 0x06, 0x8c, 0xfe, 0x6f,
+ 0x57, 0xbc, 0xc4, 0x19, 0x30, 0x28, 0xdc, 0x46, 0xbd, 0x33, 0xdd, 0x6e, 0x7a, 0x99, 0xb7, 0x51,
+ 0xcf, 0x48, 0xc7, 0x6a, 0x16, 0x6d, 0xd0, 0xae, 0x78, 0x85, 0xab, 0x59, 0xac, 0xc7, 0x30, 0x7a,
+ 0x87, 0xa4, 0xdd, 0xf1, 0x2a, 0x87, 0xd1, 0x33, 0x23, 0xc5, 0x0a, 0xd4, 0x77, 0x0f, 0x48, 0xbb,
+ 0xef, 0x35, 0xf2, 0x8d, 0xef, 0x9a, 0x8f, 0xe2, 0x3e, 0x98, 0xea, 0x3f, 0x1c, 0xed, 0xd6, 0x0b,
+ 0xdb, 0x3d, 0xaf, 0x33, 0xe6, 0x6c, 0x14, 0xa7, 0xba, 0x5d, 0xd6, 0x1c, 0x8c, 0x76, 0xed, 0xc5,
+ 0xed, 0x6a, 0xa3, 0x35, 0xe7, 0xa2, 0x98, 0x07, 0xe8, 0xce, 0x24, 0xbb, 0xeb, 0x12, 0xb9, 0x0c,
+ 0x08, 0xb7, 0x06, 0x8d, 0x24, 0x3b, 0x7f, 0x99, 0xb7, 0x06, 0x11, 0xb8, 0x35, 0x78, 0x1a, 0xd9,
+ 0xe9, 0x2b, 0xbc, 0x35, 0x18, 0x11, 0xb3, 0x30, 0x14, 0xe7, 0x61, 0x88, 0xcf, 0x56, 0xfd, 0xe6,
+ 0x3e, 0xe3, 0x46, 0x86, 0x6d, 0x86, 0x7f, 0xdd, 0x21, 0x98, 0x01, 0x71, 0x18, 0xf6, 0xca, 0xa8,
+ 0x29, 0xdb, 0x36, 0xf2, 0xb7, 0x1d, 0xee, 0x27, 0xb8, 0x5a, 0xcc, 0x01, 0x74, 0x5e, 0xa6, 0x31,
+ 0x0a, 0x1b, 0xfb, 0xfb, 0x4e, 0xe7, 0xbd, 0xde, 0x40, 0xba, 0x82, 0xe2, 0x6d, 0xdc, 0x22, 0xd8,
+ 0xaa, 0x0a, 0x8a, 0x17, 0xf0, 0x23, 0xb0, 0xef, 0xe1, 0x4c, 0xc5, 0xda, 0xf3, 0x6d, 0xf4, 0x1f,
+ 0x44, 0xf3, 0x7a, 0x4c, 0x58, 0xa4, 0x52, 0xa9, 0x3d, 0x3f, 0xb3, 0xb1, 0x7f, 0x12, 0x5b, 0x02,
+ 0x08, 0xb7, 0xbc, 0x4c, 0xbb, 0xdc, 0xf7, 0x5f, 0x0c, 0x33, 0x80, 0x41, 0xe3, 0xf5, 0x23, 0x72,
+ 0xd3, 0xc6, 0xfe, 0xcd, 0x41, 0xd3, 0x7a, 0x71, 0x14, 0x6a, 0x78, 0x59, 0xfc, 0x0e, 0x61, 0x83,
+ 0xff, 0x21, 0xb8, 0x4b, 0xe0, 0x37, 0x67, 0xba, 0xad, 0x03, 0x7b, 0xb2, 0xff, 0xa5, 0x4a, 0xf3,
+ 0x7a, 0x31, 0x0f, 0xc3, 0x99, 0x6e, 0xb7, 0x73, 0x3a, 0xd1, 0x58, 0xf0, 0xff, 0x76, 0xca, 0x97,
+ 0xdc, 0x92, 0x39, 0xb6, 0x08, 0x13, 0x2d, 0x15, 0xf5, 0x82, 0xc7, 0x60, 0x49, 0x2d, 0xa9, 0x95,
+ 0x62, 0x17, 0x3d, 0x78, 0x9b, 0x1f, 0xe8, 0x8d, 0xbc, 0x39, 0xdd, 0x52, 0xd1, 0x0c, 0x1e, 0x35,
+ 0xbb, 0xbf, 0xa0, 0x95, 0x07, 0xcf, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0xed, 0x5f, 0x6c, 0x20,
+ 0x74, 0x13, 0x00, 0x00,
+}
--- /dev/null
+// Code generated by protoc-gen-go.
+// source: gogo.proto
+// DO NOT EDIT!
+
+package gogoproto
+
+import proto "github.com/gogo/protobuf/proto"
+import json "encoding/json"
+import math "math"
+import google_protobuf "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+
+// Reference proto, json, and math imports to suppress error if they are not otherwise used.
+var _ = proto.Marshal
+var _ = &json.SyntaxError{}
+var _ = math.Inf
+
+var E_Nullable = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 51235,
+ Name: "gogoproto.nullable",
+ Tag: "varint,51235,opt,name=nullable",
+}
+
+var E_Embed = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 51236,
+ Name: "gogoproto.embed",
+ Tag: "varint,51236,opt,name=embed",
+}
+
+var E_Customtype = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 51237,
+ Name: "gogoproto.customtype",
+ Tag: "bytes,51237,opt,name=customtype",
+}
+
+func init() {
+ proto.RegisterExtension(E_Nullable)
+ proto.RegisterExtension(E_Embed)
+ proto.RegisterExtension(E_Customtype)
+}
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+package gogoproto;
+
+import "google/protobuf/descriptor.proto";
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "GoGoProtos";
+option go_package = "github.com/gogo/protobuf/gogoproto";
+
+extend google.protobuf.EnumOptions {
+ optional bool goproto_enum_prefix = 62001;
+ optional bool goproto_enum_stringer = 62021;
+ optional bool enum_stringer = 62022;
+ optional string enum_customname = 62023;
+ optional bool enumdecl = 62024;
+}
+
+extend google.protobuf.EnumValueOptions {
+ optional string enumvalue_customname = 66001;
+}
+
+extend google.protobuf.FileOptions {
+ optional bool goproto_getters_all = 63001;
+ optional bool goproto_enum_prefix_all = 63002;
+ optional bool goproto_stringer_all = 63003;
+ optional bool verbose_equal_all = 63004;
+ optional bool face_all = 63005;
+ optional bool gostring_all = 63006;
+ optional bool populate_all = 63007;
+ optional bool stringer_all = 63008;
+ optional bool onlyone_all = 63009;
+
+ optional bool equal_all = 63013;
+ optional bool description_all = 63014;
+ optional bool testgen_all = 63015;
+ optional bool benchgen_all = 63016;
+ optional bool marshaler_all = 63017;
+ optional bool unmarshaler_all = 63018;
+ optional bool stable_marshaler_all = 63019;
+
+ optional bool sizer_all = 63020;
+
+ optional bool goproto_enum_stringer_all = 63021;
+ optional bool enum_stringer_all = 63022;
+
+ optional bool unsafe_marshaler_all = 63023;
+ optional bool unsafe_unmarshaler_all = 63024;
+
+ optional bool goproto_extensions_map_all = 63025;
+ optional bool goproto_unrecognized_all = 63026;
+ optional bool gogoproto_import = 63027;
+ optional bool protosizer_all = 63028;
+ optional bool compare_all = 63029;
+ optional bool typedecl_all = 63030;
+ optional bool enumdecl_all = 63031;
+
+ optional bool goproto_registration = 63032;
+}
+
+extend google.protobuf.MessageOptions {
+ optional bool goproto_getters = 64001;
+ optional bool goproto_stringer = 64003;
+ optional bool verbose_equal = 64004;
+ optional bool face = 64005;
+ optional bool gostring = 64006;
+ optional bool populate = 64007;
+ optional bool stringer = 67008;
+ optional bool onlyone = 64009;
+
+ optional bool equal = 64013;
+ optional bool description = 64014;
+ optional bool testgen = 64015;
+ optional bool benchgen = 64016;
+ optional bool marshaler = 64017;
+ optional bool unmarshaler = 64018;
+ optional bool stable_marshaler = 64019;
+
+ optional bool sizer = 64020;
+
+ optional bool unsafe_marshaler = 64023;
+ optional bool unsafe_unmarshaler = 64024;
+
+ optional bool goproto_extensions_map = 64025;
+ optional bool goproto_unrecognized = 64026;
+
+ optional bool protosizer = 64028;
+ optional bool compare = 64029;
+
+ optional bool typedecl = 64030;
+}
+
+extend google.protobuf.FieldOptions {
+ optional bool nullable = 65001;
+ optional bool embed = 65002;
+ optional string customtype = 65003;
+ optional string customname = 65004;
+ optional string jsontag = 65005;
+ optional string moretags = 65006;
+ optional string casttype = 65007;
+ optional string castkey = 65008;
+ optional string castvalue = 65009;
+
+ optional bool stdtime = 65010;
+ optional bool stdduration = 65011;
+}
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package gogoproto
+
+import google_protobuf "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+import proto "github.com/gogo/protobuf/proto"
+
+func IsEmbed(field *google_protobuf.FieldDescriptorProto) bool {
+ return proto.GetBoolExtension(field.Options, E_Embed, false)
+}
+
+func IsNullable(field *google_protobuf.FieldDescriptorProto) bool {
+ return proto.GetBoolExtension(field.Options, E_Nullable, true)
+}
+
+func IsStdTime(field *google_protobuf.FieldDescriptorProto) bool {
+ return proto.GetBoolExtension(field.Options, E_Stdtime, false)
+}
+
+func IsStdDuration(field *google_protobuf.FieldDescriptorProto) bool {
+ return proto.GetBoolExtension(field.Options, E_Stdduration, false)
+}
+
+func NeedsNilCheck(proto3 bool, field *google_protobuf.FieldDescriptorProto) bool {
+ nullable := IsNullable(field)
+ if field.IsMessage() || IsCustomType(field) {
+ return nullable
+ }
+ if proto3 {
+ return false
+ }
+ return nullable || *field.Type == google_protobuf.FieldDescriptorProto_TYPE_BYTES
+}
+
+func IsCustomType(field *google_protobuf.FieldDescriptorProto) bool {
+ typ := GetCustomType(field)
+ if len(typ) > 0 {
+ return true
+ }
+ return false
+}
+
+func IsCastType(field *google_protobuf.FieldDescriptorProto) bool {
+ typ := GetCastType(field)
+ if len(typ) > 0 {
+ return true
+ }
+ return false
+}
+
+func IsCastKey(field *google_protobuf.FieldDescriptorProto) bool {
+ typ := GetCastKey(field)
+ if len(typ) > 0 {
+ return true
+ }
+ return false
+}
+
+func IsCastValue(field *google_protobuf.FieldDescriptorProto) bool {
+ typ := GetCastValue(field)
+ if len(typ) > 0 {
+ return true
+ }
+ return false
+}
+
+func HasEnumDecl(file *google_protobuf.FileDescriptorProto, enum *google_protobuf.EnumDescriptorProto) bool {
+ return proto.GetBoolExtension(enum.Options, E_Enumdecl, proto.GetBoolExtension(file.Options, E_EnumdeclAll, true))
+}
+
+func HasTypeDecl(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Typedecl, proto.GetBoolExtension(file.Options, E_TypedeclAll, true))
+}
+
+func GetCustomType(field *google_protobuf.FieldDescriptorProto) string {
+ if field == nil {
+ return ""
+ }
+ if field.Options != nil {
+ v, err := proto.GetExtension(field.Options, E_Customtype)
+ if err == nil && v.(*string) != nil {
+ return *(v.(*string))
+ }
+ }
+ return ""
+}
+
+func GetCastType(field *google_protobuf.FieldDescriptorProto) string {
+ if field == nil {
+ return ""
+ }
+ if field.Options != nil {
+ v, err := proto.GetExtension(field.Options, E_Casttype)
+ if err == nil && v.(*string) != nil {
+ return *(v.(*string))
+ }
+ }
+ return ""
+}
+
+func GetCastKey(field *google_protobuf.FieldDescriptorProto) string {
+ if field == nil {
+ return ""
+ }
+ if field.Options != nil {
+ v, err := proto.GetExtension(field.Options, E_Castkey)
+ if err == nil && v.(*string) != nil {
+ return *(v.(*string))
+ }
+ }
+ return ""
+}
+
+func GetCastValue(field *google_protobuf.FieldDescriptorProto) string {
+ if field == nil {
+ return ""
+ }
+ if field.Options != nil {
+ v, err := proto.GetExtension(field.Options, E_Castvalue)
+ if err == nil && v.(*string) != nil {
+ return *(v.(*string))
+ }
+ }
+ return ""
+}
+
+func IsCustomName(field *google_protobuf.FieldDescriptorProto) bool {
+ name := GetCustomName(field)
+ if len(name) > 0 {
+ return true
+ }
+ return false
+}
+
+func IsEnumCustomName(field *google_protobuf.EnumDescriptorProto) bool {
+ name := GetEnumCustomName(field)
+ if len(name) > 0 {
+ return true
+ }
+ return false
+}
+
+func IsEnumValueCustomName(field *google_protobuf.EnumValueDescriptorProto) bool {
+ name := GetEnumValueCustomName(field)
+ if len(name) > 0 {
+ return true
+ }
+ return false
+}
+
+func GetCustomName(field *google_protobuf.FieldDescriptorProto) string {
+ if field == nil {
+ return ""
+ }
+ if field.Options != nil {
+ v, err := proto.GetExtension(field.Options, E_Customname)
+ if err == nil && v.(*string) != nil {
+ return *(v.(*string))
+ }
+ }
+ return ""
+}
+
+func GetEnumCustomName(field *google_protobuf.EnumDescriptorProto) string {
+ if field == nil {
+ return ""
+ }
+ if field.Options != nil {
+ v, err := proto.GetExtension(field.Options, E_EnumCustomname)
+ if err == nil && v.(*string) != nil {
+ return *(v.(*string))
+ }
+ }
+ return ""
+}
+
+func GetEnumValueCustomName(field *google_protobuf.EnumValueDescriptorProto) string {
+ if field == nil {
+ return ""
+ }
+ if field.Options != nil {
+ v, err := proto.GetExtension(field.Options, E_EnumvalueCustomname)
+ if err == nil && v.(*string) != nil {
+ return *(v.(*string))
+ }
+ }
+ return ""
+}
+
+func GetJsonTag(field *google_protobuf.FieldDescriptorProto) *string {
+ if field == nil {
+ return nil
+ }
+ if field.Options != nil {
+ v, err := proto.GetExtension(field.Options, E_Jsontag)
+ if err == nil && v.(*string) != nil {
+ return (v.(*string))
+ }
+ }
+ return nil
+}
+
+func GetMoreTags(field *google_protobuf.FieldDescriptorProto) *string {
+ if field == nil {
+ return nil
+ }
+ if field.Options != nil {
+ v, err := proto.GetExtension(field.Options, E_Moretags)
+ if err == nil && v.(*string) != nil {
+ return (v.(*string))
+ }
+ }
+ return nil
+}
+
+type EnableFunc func(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool
+
+func EnabledGoEnumPrefix(file *google_protobuf.FileDescriptorProto, enum *google_protobuf.EnumDescriptorProto) bool {
+ return proto.GetBoolExtension(enum.Options, E_GoprotoEnumPrefix, proto.GetBoolExtension(file.Options, E_GoprotoEnumPrefixAll, true))
+}
+
+func EnabledGoStringer(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_GoprotoStringer, proto.GetBoolExtension(file.Options, E_GoprotoStringerAll, true))
+}
+
+func HasGoGetters(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_GoprotoGetters, proto.GetBoolExtension(file.Options, E_GoprotoGettersAll, true))
+}
+
+func IsUnion(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Onlyone, proto.GetBoolExtension(file.Options, E_OnlyoneAll, false))
+}
+
+func HasGoString(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Gostring, proto.GetBoolExtension(file.Options, E_GostringAll, false))
+}
+
+func HasEqual(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Equal, proto.GetBoolExtension(file.Options, E_EqualAll, false))
+}
+
+func HasVerboseEqual(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_VerboseEqual, proto.GetBoolExtension(file.Options, E_VerboseEqualAll, false))
+}
+
+func IsStringer(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Stringer, proto.GetBoolExtension(file.Options, E_StringerAll, false))
+}
+
+func IsFace(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Face, proto.GetBoolExtension(file.Options, E_FaceAll, false))
+}
+
+func HasDescription(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Description, proto.GetBoolExtension(file.Options, E_DescriptionAll, false))
+}
+
+func HasPopulate(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Populate, proto.GetBoolExtension(file.Options, E_PopulateAll, false))
+}
+
+func HasTestGen(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Testgen, proto.GetBoolExtension(file.Options, E_TestgenAll, false))
+}
+
+func HasBenchGen(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Benchgen, proto.GetBoolExtension(file.Options, E_BenchgenAll, false))
+}
+
+func IsMarshaler(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Marshaler, proto.GetBoolExtension(file.Options, E_MarshalerAll, false))
+}
+
+func IsUnmarshaler(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Unmarshaler, proto.GetBoolExtension(file.Options, E_UnmarshalerAll, false))
+}
+
+func IsStableMarshaler(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_StableMarshaler, proto.GetBoolExtension(file.Options, E_StableMarshalerAll, false))
+}
+
+func IsSizer(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Sizer, proto.GetBoolExtension(file.Options, E_SizerAll, false))
+}
+
+func IsProtoSizer(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Protosizer, proto.GetBoolExtension(file.Options, E_ProtosizerAll, false))
+}
+
+func IsGoEnumStringer(file *google_protobuf.FileDescriptorProto, enum *google_protobuf.EnumDescriptorProto) bool {
+ return proto.GetBoolExtension(enum.Options, E_GoprotoEnumStringer, proto.GetBoolExtension(file.Options, E_GoprotoEnumStringerAll, true))
+}
+
+func IsEnumStringer(file *google_protobuf.FileDescriptorProto, enum *google_protobuf.EnumDescriptorProto) bool {
+ return proto.GetBoolExtension(enum.Options, E_EnumStringer, proto.GetBoolExtension(file.Options, E_EnumStringerAll, false))
+}
+
+func IsUnsafeMarshaler(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_UnsafeMarshaler, proto.GetBoolExtension(file.Options, E_UnsafeMarshalerAll, false))
+}
+
+func IsUnsafeUnmarshaler(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_UnsafeUnmarshaler, proto.GetBoolExtension(file.Options, E_UnsafeUnmarshalerAll, false))
+}
+
+func HasExtensionsMap(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_GoprotoExtensionsMap, proto.GetBoolExtension(file.Options, E_GoprotoExtensionsMapAll, true))
+}
+
+func HasUnrecognized(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ if IsProto3(file) {
+ return false
+ }
+ return proto.GetBoolExtension(message.Options, E_GoprotoUnrecognized, proto.GetBoolExtension(file.Options, E_GoprotoUnrecognizedAll, true))
+}
+
+func IsProto3(file *google_protobuf.FileDescriptorProto) bool {
+ return file.GetSyntax() == "proto3"
+}
+
+func ImportsGoGoProto(file *google_protobuf.FileDescriptorProto) bool {
+ return proto.GetBoolExtension(file.Options, E_GogoprotoImport, true)
+}
+
+func HasCompare(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Compare, proto.GetBoolExtension(file.Options, E_CompareAll, false))
+}
+
+func RegistersGolangProto(file *google_protobuf.FileDescriptorProto) bool {
+ return proto.GetBoolExtension(file.Options, E_GoprotoRegistration, false)
+}
--- /dev/null
+# Go support for Protocol Buffers - Google's data interchange format
+#
+# Copyright 2010 The Go Authors. All rights reserved.
+# https://github.com/golang/protobuf
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+install:
+ go install
+
+test: install generate-test-pbs
+ go test
+
+
+generate-test-pbs:
+ make install
+ make -C testdata
+ protoc-min-version --version="3.0.0" --proto_path=.:../../../../:../protobuf --gogo_out=Mtestdata/test.proto=github.com/gogo/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/gogo/protobuf/types:. proto3_proto/proto3.proto
+ make
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2011 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Protocol buffer deep copy and merge.
+// TODO: RawMessage.
+
+package proto
+
+import (
+ "log"
+ "reflect"
+ "strings"
+)
+
+// Clone returns a deep copy of a protocol buffer.
+func Clone(pb Message) Message {
+ in := reflect.ValueOf(pb)
+ if in.IsNil() {
+ return pb
+ }
+
+ out := reflect.New(in.Type().Elem())
+ // out is empty so a merge is a deep copy.
+ mergeStruct(out.Elem(), in.Elem())
+ return out.Interface().(Message)
+}
+
+// Merge merges src into dst.
+// Required and optional fields that are set in src will be set to that value in dst.
+// Elements of repeated fields will be appended.
+// Merge panics if src and dst are not the same type, or if dst is nil.
+func Merge(dst, src Message) {
+ in := reflect.ValueOf(src)
+ out := reflect.ValueOf(dst)
+ if out.IsNil() {
+ panic("proto: nil destination")
+ }
+ if in.Type() != out.Type() {
+ // Explicit test prior to mergeStruct so that mistyped nils will fail
+ panic("proto: type mismatch")
+ }
+ if in.IsNil() {
+ // Merging nil into non-nil is a quiet no-op
+ return
+ }
+ mergeStruct(out.Elem(), in.Elem())
+}
+
+func mergeStruct(out, in reflect.Value) {
+ sprop := GetProperties(in.Type())
+ for i := 0; i < in.NumField(); i++ {
+ f := in.Type().Field(i)
+ if strings.HasPrefix(f.Name, "XXX_") {
+ continue
+ }
+ mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i])
+ }
+
+ if emIn, ok := in.Addr().Interface().(extensionsBytes); ok {
+ emOut := out.Addr().Interface().(extensionsBytes)
+ bIn := emIn.GetExtensions()
+ bOut := emOut.GetExtensions()
+ *bOut = append(*bOut, *bIn...)
+ } else if emIn, ok := extendable(in.Addr().Interface()); ok {
+ emOut, _ := extendable(out.Addr().Interface())
+ mIn, muIn := emIn.extensionsRead()
+ if mIn != nil {
+ mOut := emOut.extensionsWrite()
+ muIn.Lock()
+ mergeExtension(mOut, mIn)
+ muIn.Unlock()
+ }
+ }
+
+ uf := in.FieldByName("XXX_unrecognized")
+ if !uf.IsValid() {
+ return
+ }
+ uin := uf.Bytes()
+ if len(uin) > 0 {
+ out.FieldByName("XXX_unrecognized").SetBytes(append([]byte(nil), uin...))
+ }
+}
+
+// mergeAny performs a merge between two values of the same type.
+// viaPtr indicates whether the values were indirected through a pointer (implying proto2).
+// prop is set if this is a struct field (it may be nil).
+func mergeAny(out, in reflect.Value, viaPtr bool, prop *Properties) {
+ if in.Type() == protoMessageType {
+ if !in.IsNil() {
+ if out.IsNil() {
+ out.Set(reflect.ValueOf(Clone(in.Interface().(Message))))
+ } else {
+ Merge(out.Interface().(Message), in.Interface().(Message))
+ }
+ }
+ return
+ }
+ switch in.Kind() {
+ case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
+ reflect.String, reflect.Uint32, reflect.Uint64:
+ if !viaPtr && isProto3Zero(in) {
+ return
+ }
+ out.Set(in)
+ case reflect.Interface:
+ // Probably a oneof field; copy non-nil values.
+ if in.IsNil() {
+ return
+ }
+ // Allocate destination if it is not set, or set to a different type.
+ // Otherwise we will merge as normal.
+ if out.IsNil() || out.Elem().Type() != in.Elem().Type() {
+ out.Set(reflect.New(in.Elem().Elem().Type())) // interface -> *T -> T -> new(T)
+ }
+ mergeAny(out.Elem(), in.Elem(), false, nil)
+ case reflect.Map:
+ if in.Len() == 0 {
+ return
+ }
+ if out.IsNil() {
+ out.Set(reflect.MakeMap(in.Type()))
+ }
+ // For maps with value types of *T or []byte we need to deep copy each value.
+ elemKind := in.Type().Elem().Kind()
+ for _, key := range in.MapKeys() {
+ var val reflect.Value
+ switch elemKind {
+ case reflect.Ptr:
+ val = reflect.New(in.Type().Elem().Elem())
+ mergeAny(val, in.MapIndex(key), false, nil)
+ case reflect.Slice:
+ val = in.MapIndex(key)
+ val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
+ default:
+ val = in.MapIndex(key)
+ }
+ out.SetMapIndex(key, val)
+ }
+ case reflect.Ptr:
+ if in.IsNil() {
+ return
+ }
+ if out.IsNil() {
+ out.Set(reflect.New(in.Elem().Type()))
+ }
+ mergeAny(out.Elem(), in.Elem(), true, nil)
+ case reflect.Slice:
+ if in.IsNil() {
+ return
+ }
+ if in.Type().Elem().Kind() == reflect.Uint8 {
+ // []byte is a scalar bytes field, not a repeated field.
+
+ // Edge case: if this is in a proto3 message, a zero length
+ // bytes field is considered the zero value, and should not
+ // be merged.
+ if prop != nil && prop.proto3 && in.Len() == 0 {
+ return
+ }
+
+ // Make a deep copy.
+ // Append to []byte{} instead of []byte(nil) so that we never end up
+ // with a nil result.
+ out.SetBytes(append([]byte{}, in.Bytes()...))
+ return
+ }
+ n := in.Len()
+ if out.IsNil() {
+ out.Set(reflect.MakeSlice(in.Type(), 0, n))
+ }
+ switch in.Type().Elem().Kind() {
+ case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
+ reflect.String, reflect.Uint32, reflect.Uint64:
+ out.Set(reflect.AppendSlice(out, in))
+ default:
+ for i := 0; i < n; i++ {
+ x := reflect.Indirect(reflect.New(in.Type().Elem()))
+ mergeAny(x, in.Index(i), false, nil)
+ out.Set(reflect.Append(out, x))
+ }
+ }
+ case reflect.Struct:
+ mergeStruct(out, in)
+ default:
+ // unknown type, so not a protocol buffer
+ log.Printf("proto: don't know how to copy %v", in)
+ }
+}
+
+func mergeExtension(out, in map[int32]Extension) {
+ for extNum, eIn := range in {
+ eOut := Extension{desc: eIn.desc}
+ if eIn.value != nil {
+ v := reflect.New(reflect.TypeOf(eIn.value)).Elem()
+ mergeAny(v, reflect.ValueOf(eIn.value), false, nil)
+ eOut.value = v.Interface()
+ }
+ if eIn.enc != nil {
+ eOut.enc = make([]byte, len(eIn.enc))
+ copy(eOut.enc, eIn.enc)
+ }
+
+ out[extNum] = eOut
+ }
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+/*
+ * Routines for decoding protocol buffer data to construct in-memory representations.
+ */
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "reflect"
+)
+
+// errOverflow is returned when an integer is too large to be represented.
+var errOverflow = errors.New("proto: integer overflow")
+
+// ErrInternalBadWireType is returned by generated code when an incorrect
+// wire type is encountered. It does not get returned to user code.
+var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
+
+// The fundamental decoders that interpret bytes on the wire.
+// Those that take integer types all return uint64 and are
+// therefore of type valueDecoder.
+
+// DecodeVarint reads a varint-encoded integer from the slice.
+// It returns the integer and the number of bytes consumed, or
+// zero if there is not enough.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+func DecodeVarint(buf []byte) (x uint64, n int) {
+ for shift := uint(0); shift < 64; shift += 7 {
+ if n >= len(buf) {
+ return 0, 0
+ }
+ b := uint64(buf[n])
+ n++
+ x |= (b & 0x7F) << shift
+ if (b & 0x80) == 0 {
+ return x, n
+ }
+ }
+
+ // The number is too large to represent in a 64-bit value.
+ return 0, 0
+}
+
+func (p *Buffer) decodeVarintSlow() (x uint64, err error) {
+ i := p.index
+ l := len(p.buf)
+
+ for shift := uint(0); shift < 64; shift += 7 {
+ if i >= l {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+ b := p.buf[i]
+ i++
+ x |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ p.index = i
+ return
+ }
+ }
+
+ // The number is too large to represent in a 64-bit value.
+ err = errOverflow
+ return
+}
+
+// DecodeVarint reads a varint-encoded integer from the Buffer.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+func (p *Buffer) DecodeVarint() (x uint64, err error) {
+ i := p.index
+ buf := p.buf
+
+ if i >= len(buf) {
+ return 0, io.ErrUnexpectedEOF
+ } else if buf[i] < 0x80 {
+ p.index++
+ return uint64(buf[i]), nil
+ } else if len(buf)-i < 10 {
+ return p.decodeVarintSlow()
+ }
+
+ var b uint64
+ // we already checked the first byte
+ x = uint64(buf[i]) - 0x80
+ i++
+
+ b = uint64(buf[i])
+ i++
+ x += b << 7
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 7
+
+ b = uint64(buf[i])
+ i++
+ x += b << 14
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 14
+
+ b = uint64(buf[i])
+ i++
+ x += b << 21
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 21
+
+ b = uint64(buf[i])
+ i++
+ x += b << 28
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 28
+
+ b = uint64(buf[i])
+ i++
+ x += b << 35
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 35
+
+ b = uint64(buf[i])
+ i++
+ x += b << 42
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 42
+
+ b = uint64(buf[i])
+ i++
+ x += b << 49
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 49
+
+ b = uint64(buf[i])
+ i++
+ x += b << 56
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 56
+
+ b = uint64(buf[i])
+ i++
+ x += b << 63
+ if b&0x80 == 0 {
+ goto done
+ }
+ // x -= 0x80 << 63 // Always zero.
+
+ return 0, errOverflow
+
+done:
+ p.index = i
+ return x, nil
+}
+
+// DecodeFixed64 reads a 64-bit integer from the Buffer.
+// This is the format for the
+// fixed64, sfixed64, and double protocol buffer types.
+func (p *Buffer) DecodeFixed64() (x uint64, err error) {
+ // x, err already 0
+ i := p.index + 8
+ if i < 0 || i > len(p.buf) {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+ p.index = i
+
+ x = uint64(p.buf[i-8])
+ x |= uint64(p.buf[i-7]) << 8
+ x |= uint64(p.buf[i-6]) << 16
+ x |= uint64(p.buf[i-5]) << 24
+ x |= uint64(p.buf[i-4]) << 32
+ x |= uint64(p.buf[i-3]) << 40
+ x |= uint64(p.buf[i-2]) << 48
+ x |= uint64(p.buf[i-1]) << 56
+ return
+}
+
+// DecodeFixed32 reads a 32-bit integer from the Buffer.
+// This is the format for the
+// fixed32, sfixed32, and float protocol buffer types.
+func (p *Buffer) DecodeFixed32() (x uint64, err error) {
+ // x, err already 0
+ i := p.index + 4
+ if i < 0 || i > len(p.buf) {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+ p.index = i
+
+ x = uint64(p.buf[i-4])
+ x |= uint64(p.buf[i-3]) << 8
+ x |= uint64(p.buf[i-2]) << 16
+ x |= uint64(p.buf[i-1]) << 24
+ return
+}
+
+// DecodeZigzag64 reads a zigzag-encoded 64-bit integer
+// from the Buffer.
+// This is the format used for the sint64 protocol buffer type.
+func (p *Buffer) DecodeZigzag64() (x uint64, err error) {
+ x, err = p.DecodeVarint()
+ if err != nil {
+ return
+ }
+ x = (x >> 1) ^ uint64((int64(x&1)<<63)>>63)
+ return
+}
+
+// DecodeZigzag32 reads a zigzag-encoded 32-bit integer
+// from the Buffer.
+// This is the format used for the sint32 protocol buffer type.
+func (p *Buffer) DecodeZigzag32() (x uint64, err error) {
+ x, err = p.DecodeVarint()
+ if err != nil {
+ return
+ }
+ x = uint64((uint32(x) >> 1) ^ uint32((int32(x&1)<<31)>>31))
+ return
+}
+
+// These are not ValueDecoders: they produce an array of bytes or a string.
+// bytes, embedded messages
+
+// DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
+// This is the format used for the bytes protocol buffer
+// type and for embedded messages.
+func (p *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err error) {
+ n, err := p.DecodeVarint()
+ if err != nil {
+ return nil, err
+ }
+
+ nb := int(n)
+ if nb < 0 {
+ return nil, fmt.Errorf("proto: bad byte length %d", nb)
+ }
+ end := p.index + nb
+ if end < p.index || end > len(p.buf) {
+ return nil, io.ErrUnexpectedEOF
+ }
+
+ if !alloc {
+ // todo: check if can get more uses of alloc=false
+ buf = p.buf[p.index:end]
+ p.index += nb
+ return
+ }
+
+ buf = make([]byte, nb)
+ copy(buf, p.buf[p.index:])
+ p.index += nb
+ return
+}
+
+// DecodeStringBytes reads an encoded string from the Buffer.
+// This is the format used for the proto2 string type.
+func (p *Buffer) DecodeStringBytes() (s string, err error) {
+ buf, err := p.DecodeRawBytes(false)
+ if err != nil {
+ return
+ }
+ return string(buf), nil
+}
+
+// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
+// If the protocol buffer has extensions, and the field matches, add it as an extension.
+// Otherwise, if the XXX_unrecognized field exists, append the skipped data there.
+func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base structPointer, unrecField field) error {
+ oi := o.index
+
+ err := o.skip(t, tag, wire)
+ if err != nil {
+ return err
+ }
+
+ if !unrecField.IsValid() {
+ return nil
+ }
+
+ ptr := structPointer_Bytes(base, unrecField)
+
+ // Add the skipped field to struct field
+ obuf := o.buf
+
+ o.buf = *ptr
+ o.EncodeVarint(uint64(tag<<3 | wire))
+ *ptr = append(o.buf, obuf[oi:o.index]...)
+
+ o.buf = obuf
+
+ return nil
+}
+
+// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
+func (o *Buffer) skip(t reflect.Type, tag, wire int) error {
+
+ var u uint64
+ var err error
+
+ switch wire {
+ case WireVarint:
+ _, err = o.DecodeVarint()
+ case WireFixed64:
+ _, err = o.DecodeFixed64()
+ case WireBytes:
+ _, err = o.DecodeRawBytes(false)
+ case WireFixed32:
+ _, err = o.DecodeFixed32()
+ case WireStartGroup:
+ for {
+ u, err = o.DecodeVarint()
+ if err != nil {
+ break
+ }
+ fwire := int(u & 0x7)
+ if fwire == WireEndGroup {
+ break
+ }
+ ftag := int(u >> 3)
+ err = o.skip(t, ftag, fwire)
+ if err != nil {
+ break
+ }
+ }
+ default:
+ err = fmt.Errorf("proto: can't skip unknown wire type %d for %s", wire, t)
+ }
+ return err
+}
+
+// Unmarshaler is the interface representing objects that can
+// unmarshal themselves. The method should reset the receiver before
+// decoding starts. The argument points to data that may be
+// overwritten, so implementations should not keep references to the
+// buffer.
+type Unmarshaler interface {
+ Unmarshal([]byte) error
+}
+
+// Unmarshal parses the protocol buffer representation in buf and places the
+// decoded result in pb. If the struct underlying pb does not match
+// the data in buf, the results can be unpredictable.
+//
+// Unmarshal resets pb before starting to unmarshal, so any
+// existing data in pb is always removed. Use UnmarshalMerge
+// to preserve and append to existing data.
+func Unmarshal(buf []byte, pb Message) error {
+ pb.Reset()
+ return UnmarshalMerge(buf, pb)
+}
+
+// UnmarshalMerge parses the protocol buffer representation in buf and
+// writes the decoded result to pb. If the struct underlying pb does not match
+// the data in buf, the results can be unpredictable.
+//
+// UnmarshalMerge merges into existing data in pb.
+// Most code should use Unmarshal instead.
+func UnmarshalMerge(buf []byte, pb Message) error {
+ // If the object can unmarshal itself, let it.
+ if u, ok := pb.(Unmarshaler); ok {
+ return u.Unmarshal(buf)
+ }
+ return NewBuffer(buf).Unmarshal(pb)
+}
+
+// DecodeMessage reads a count-delimited message from the Buffer.
+func (p *Buffer) DecodeMessage(pb Message) error {
+ enc, err := p.DecodeRawBytes(false)
+ if err != nil {
+ return err
+ }
+ return NewBuffer(enc).Unmarshal(pb)
+}
+
+// DecodeGroup reads a tag-delimited group from the Buffer.
+func (p *Buffer) DecodeGroup(pb Message) error {
+ typ, base, err := getbase(pb)
+ if err != nil {
+ return err
+ }
+ return p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), true, base)
+}
+
+// Unmarshal parses the protocol buffer representation in the
+// Buffer and places the decoded result in pb. If the struct
+// underlying pb does not match the data in the buffer, the results can be
+// unpredictable.
+//
+// Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal.
+func (p *Buffer) Unmarshal(pb Message) error {
+ // If the object can unmarshal itself, let it.
+ if u, ok := pb.(Unmarshaler); ok {
+ err := u.Unmarshal(p.buf[p.index:])
+ p.index = len(p.buf)
+ return err
+ }
+
+ typ, base, err := getbase(pb)
+ if err != nil {
+ return err
+ }
+
+ err = p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), false, base)
+
+ if collectStats {
+ stats.Decode++
+ }
+
+ return err
+}
+
+// unmarshalType does the work of unmarshaling a structure.
+func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group bool, base structPointer) error {
+ var state errorState
+ required, reqFields := prop.reqCount, uint64(0)
+
+ var err error
+ for err == nil && o.index < len(o.buf) {
+ oi := o.index
+ var u uint64
+ u, err = o.DecodeVarint()
+ if err != nil {
+ break
+ }
+ wire := int(u & 0x7)
+ if wire == WireEndGroup {
+ if is_group {
+ if required > 0 {
+ // Not enough information to determine the exact field.
+ // (See below.)
+ return &RequiredNotSetError{"{Unknown}"}
+ }
+ return nil // input is satisfied
+ }
+ return fmt.Errorf("proto: %s: wiretype end group for non-group", st)
+ }
+ tag := int(u >> 3)
+ if tag <= 0 {
+ return fmt.Errorf("proto: %s: illegal tag %d (wire type %d)", st, tag, wire)
+ }
+ fieldnum, ok := prop.decoderTags.get(tag)
+ if !ok {
+ // Maybe it's an extension?
+ if prop.extendable {
+ if e, eok := structPointer_Interface(base, st).(extensionsBytes); eok {
+ if isExtensionField(e, int32(tag)) {
+ if err = o.skip(st, tag, wire); err == nil {
+ ext := e.GetExtensions()
+ *ext = append(*ext, o.buf[oi:o.index]...)
+ }
+ continue
+ }
+ } else if e, _ := extendable(structPointer_Interface(base, st)); isExtensionField(e, int32(tag)) {
+ if err = o.skip(st, tag, wire); err == nil {
+ extmap := e.extensionsWrite()
+ ext := extmap[int32(tag)] // may be missing
+ ext.enc = append(ext.enc, o.buf[oi:o.index]...)
+ extmap[int32(tag)] = ext
+ }
+ continue
+ }
+ }
+ // Maybe it's a oneof?
+ if prop.oneofUnmarshaler != nil {
+ m := structPointer_Interface(base, st).(Message)
+ // First return value indicates whether tag is a oneof field.
+ ok, err = prop.oneofUnmarshaler(m, tag, wire, o)
+ if err == ErrInternalBadWireType {
+ // Map the error to something more descriptive.
+ // Do the formatting here to save generated code space.
+ err = fmt.Errorf("bad wiretype for oneof field in %T", m)
+ }
+ if ok {
+ continue
+ }
+ }
+ err = o.skipAndSave(st, tag, wire, base, prop.unrecField)
+ continue
+ }
+ p := prop.Prop[fieldnum]
+
+ if p.dec == nil {
+ fmt.Fprintf(os.Stderr, "proto: no protobuf decoder for %s.%s\n", st, st.Field(fieldnum).Name)
+ continue
+ }
+ dec := p.dec
+ if wire != WireStartGroup && wire != p.WireType {
+ if wire == WireBytes && p.packedDec != nil {
+ // a packable field
+ dec = p.packedDec
+ } else {
+ err = fmt.Errorf("proto: bad wiretype for field %s.%s: got wiretype %d, want %d", st, st.Field(fieldnum).Name, wire, p.WireType)
+ continue
+ }
+ }
+ decErr := dec(o, p, base)
+ if decErr != nil && !state.shouldContinue(decErr, p) {
+ err = decErr
+ }
+ if err == nil && p.Required {
+ // Successfully decoded a required field.
+ if tag <= 64 {
+ // use bitmap for fields 1-64 to catch field reuse.
+ var mask uint64 = 1 << uint64(tag-1)
+ if reqFields&mask == 0 {
+ // new required field
+ reqFields |= mask
+ required--
+ }
+ } else {
+ // This is imprecise. It can be fooled by a required field
+ // with a tag > 64 that is encoded twice; that's very rare.
+ // A fully correct implementation would require allocating
+ // a data structure, which we would like to avoid.
+ required--
+ }
+ }
+ }
+ if err == nil {
+ if is_group {
+ return io.ErrUnexpectedEOF
+ }
+ if state.err != nil {
+ return state.err
+ }
+ if required > 0 {
+ // Not enough information to determine the exact field. If we use extra
+ // CPU, we could determine the field only if the missing required field
+ // has a tag <= 64 and we check reqFields.
+ return &RequiredNotSetError{"{Unknown}"}
+ }
+ }
+ return err
+}
+
+// Individual type decoders
+// For each,
+// u is the decoded value,
+// v is a pointer to the field (pointer) in the struct
+
+// Sizes of the pools to allocate inside the Buffer.
+// The goal is modest amortization and allocation
+// on at least 16-byte boundaries.
+const (
+ boolPoolSize = 16
+ uint32PoolSize = 8
+ uint64PoolSize = 4
+)
+
+// Decode a bool.
+func (o *Buffer) dec_bool(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ if len(o.bools) == 0 {
+ o.bools = make([]bool, boolPoolSize)
+ }
+ o.bools[0] = u != 0
+ *structPointer_Bool(base, p.field) = &o.bools[0]
+ o.bools = o.bools[1:]
+ return nil
+}
+
+func (o *Buffer) dec_proto3_bool(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ *structPointer_BoolVal(base, p.field) = u != 0
+ return nil
+}
+
+// Decode an int32.
+func (o *Buffer) dec_int32(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ word32_Set(structPointer_Word32(base, p.field), o, uint32(u))
+ return nil
+}
+
+func (o *Buffer) dec_proto3_int32(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ word32Val_Set(structPointer_Word32Val(base, p.field), uint32(u))
+ return nil
+}
+
+// Decode an int64.
+func (o *Buffer) dec_int64(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ word64_Set(structPointer_Word64(base, p.field), o, u)
+ return nil
+}
+
+func (o *Buffer) dec_proto3_int64(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ word64Val_Set(structPointer_Word64Val(base, p.field), o, u)
+ return nil
+}
+
+// Decode a string.
+func (o *Buffer) dec_string(p *Properties, base structPointer) error {
+ s, err := o.DecodeStringBytes()
+ if err != nil {
+ return err
+ }
+ *structPointer_String(base, p.field) = &s
+ return nil
+}
+
+func (o *Buffer) dec_proto3_string(p *Properties, base structPointer) error {
+ s, err := o.DecodeStringBytes()
+ if err != nil {
+ return err
+ }
+ *structPointer_StringVal(base, p.field) = s
+ return nil
+}
+
+// Decode a slice of bytes ([]byte).
+func (o *Buffer) dec_slice_byte(p *Properties, base structPointer) error {
+ b, err := o.DecodeRawBytes(true)
+ if err != nil {
+ return err
+ }
+ *structPointer_Bytes(base, p.field) = b
+ return nil
+}
+
+// Decode a slice of bools ([]bool).
+func (o *Buffer) dec_slice_bool(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ v := structPointer_BoolSlice(base, p.field)
+ *v = append(*v, u != 0)
+ return nil
+}
+
+// Decode a slice of bools ([]bool) in packed format.
+func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer) error {
+ v := structPointer_BoolSlice(base, p.field)
+
+ nn, err := o.DecodeVarint()
+ if err != nil {
+ return err
+ }
+ nb := int(nn) // number of bytes of encoded bools
+ fin := o.index + nb
+ if fin < o.index {
+ return errOverflow
+ }
+
+ y := *v
+ for o.index < fin {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ y = append(y, u != 0)
+ }
+
+ *v = y
+ return nil
+}
+
+// Decode a slice of int32s ([]int32).
+func (o *Buffer) dec_slice_int32(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ structPointer_Word32Slice(base, p.field).Append(uint32(u))
+ return nil
+}
+
+// Decode a slice of int32s ([]int32) in packed format.
+func (o *Buffer) dec_slice_packed_int32(p *Properties, base structPointer) error {
+ v := structPointer_Word32Slice(base, p.field)
+
+ nn, err := o.DecodeVarint()
+ if err != nil {
+ return err
+ }
+ nb := int(nn) // number of bytes of encoded int32s
+
+ fin := o.index + nb
+ if fin < o.index {
+ return errOverflow
+ }
+ for o.index < fin {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ v.Append(uint32(u))
+ }
+ return nil
+}
+
+// Decode a slice of int64s ([]int64).
+func (o *Buffer) dec_slice_int64(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+
+ structPointer_Word64Slice(base, p.field).Append(u)
+ return nil
+}
+
+// Decode a slice of int64s ([]int64) in packed format.
+func (o *Buffer) dec_slice_packed_int64(p *Properties, base structPointer) error {
+ v := structPointer_Word64Slice(base, p.field)
+
+ nn, err := o.DecodeVarint()
+ if err != nil {
+ return err
+ }
+ nb := int(nn) // number of bytes of encoded int64s
+
+ fin := o.index + nb
+ if fin < o.index {
+ return errOverflow
+ }
+ for o.index < fin {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ v.Append(u)
+ }
+ return nil
+}
+
+// Decode a slice of strings ([]string).
+func (o *Buffer) dec_slice_string(p *Properties, base structPointer) error {
+ s, err := o.DecodeStringBytes()
+ if err != nil {
+ return err
+ }
+ v := structPointer_StringSlice(base, p.field)
+ *v = append(*v, s)
+ return nil
+}
+
+// Decode a slice of slice of bytes ([][]byte).
+func (o *Buffer) dec_slice_slice_byte(p *Properties, base structPointer) error {
+ b, err := o.DecodeRawBytes(true)
+ if err != nil {
+ return err
+ }
+ v := structPointer_BytesSlice(base, p.field)
+ *v = append(*v, b)
+ return nil
+}
+
+// Decode a map field.
+func (o *Buffer) dec_new_map(p *Properties, base structPointer) error {
+ raw, err := o.DecodeRawBytes(false)
+ if err != nil {
+ return err
+ }
+ oi := o.index // index at the end of this map entry
+ o.index -= len(raw) // move buffer back to start of map entry
+
+ mptr := structPointer_NewAt(base, p.field, p.mtype) // *map[K]V
+ if mptr.Elem().IsNil() {
+ mptr.Elem().Set(reflect.MakeMap(mptr.Type().Elem()))
+ }
+ v := mptr.Elem() // map[K]V
+
+ // Prepare addressable doubly-indirect placeholders for the key and value types.
+ // See enc_new_map for why.
+ keyptr := reflect.New(reflect.PtrTo(p.mtype.Key())).Elem() // addressable *K
+ keybase := toStructPointer(keyptr.Addr()) // **K
+
+ var valbase structPointer
+ var valptr reflect.Value
+ switch p.mtype.Elem().Kind() {
+ case reflect.Slice:
+ // []byte
+ var dummy []byte
+ valptr = reflect.ValueOf(&dummy) // *[]byte
+ valbase = toStructPointer(valptr) // *[]byte
+ case reflect.Ptr:
+ // message; valptr is **Msg; need to allocate the intermediate pointer
+ valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V
+ valptr.Set(reflect.New(valptr.Type().Elem()))
+ valbase = toStructPointer(valptr)
+ default:
+ // everything else
+ valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V
+ valbase = toStructPointer(valptr.Addr()) // **V
+ }
+
+ // Decode.
+ // This parses a restricted wire format, namely the encoding of a message
+ // with two fields. See enc_new_map for the format.
+ for o.index < oi {
+ // tagcode for key and value properties are always a single byte
+ // because they have tags 1 and 2.
+ tagcode := o.buf[o.index]
+ o.index++
+ switch tagcode {
+ case p.mkeyprop.tagcode[0]:
+ if err := p.mkeyprop.dec(o, p.mkeyprop, keybase); err != nil {
+ return err
+ }
+ case p.mvalprop.tagcode[0]:
+ if err := p.mvalprop.dec(o, p.mvalprop, valbase); err != nil {
+ return err
+ }
+ default:
+ // TODO: Should we silently skip this instead?
+ return fmt.Errorf("proto: bad map data tag %d", raw[0])
+ }
+ }
+ keyelem, valelem := keyptr.Elem(), valptr.Elem()
+ if !keyelem.IsValid() {
+ keyelem = reflect.Zero(p.mtype.Key())
+ }
+ if !valelem.IsValid() {
+ valelem = reflect.Zero(p.mtype.Elem())
+ }
+
+ v.SetMapIndex(keyelem, valelem)
+ return nil
+}
+
+// Decode a group.
+func (o *Buffer) dec_struct_group(p *Properties, base structPointer) error {
+ bas := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(bas) {
+ // allocate new nested message
+ bas = toStructPointer(reflect.New(p.stype))
+ structPointer_SetStructPointer(base, p.field, bas)
+ }
+ return o.unmarshalType(p.stype, p.sprop, true, bas)
+}
+
+// Decode an embedded message.
+func (o *Buffer) dec_struct_message(p *Properties, base structPointer) (err error) {
+ raw, e := o.DecodeRawBytes(false)
+ if e != nil {
+ return e
+ }
+
+ bas := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(bas) {
+ // allocate new nested message
+ bas = toStructPointer(reflect.New(p.stype))
+ structPointer_SetStructPointer(base, p.field, bas)
+ }
+
+ // If the object can unmarshal itself, let it.
+ if p.isUnmarshaler {
+ iv := structPointer_Interface(bas, p.stype)
+ return iv.(Unmarshaler).Unmarshal(raw)
+ }
+
+ obuf := o.buf
+ oi := o.index
+ o.buf = raw
+ o.index = 0
+
+ err = o.unmarshalType(p.stype, p.sprop, false, bas)
+ o.buf = obuf
+ o.index = oi
+
+ return err
+}
+
+// Decode a slice of embedded messages.
+func (o *Buffer) dec_slice_struct_message(p *Properties, base structPointer) error {
+ return o.dec_slice_struct(p, false, base)
+}
+
+// Decode a slice of embedded groups.
+func (o *Buffer) dec_slice_struct_group(p *Properties, base structPointer) error {
+ return o.dec_slice_struct(p, true, base)
+}
+
+// Decode a slice of structs ([]*struct).
+func (o *Buffer) dec_slice_struct(p *Properties, is_group bool, base structPointer) error {
+ v := reflect.New(p.stype)
+ bas := toStructPointer(v)
+ structPointer_StructPointerSlice(base, p.field).Append(bas)
+
+ if is_group {
+ err := o.unmarshalType(p.stype, p.sprop, is_group, bas)
+ return err
+ }
+
+ raw, err := o.DecodeRawBytes(false)
+ if err != nil {
+ return err
+ }
+
+ // If the object can unmarshal itself, let it.
+ if p.isUnmarshaler {
+ iv := v.Interface()
+ return iv.(Unmarshaler).Unmarshal(raw)
+ }
+
+ obuf := o.buf
+ oi := o.index
+ o.buf = raw
+ o.index = 0
+
+ err = o.unmarshalType(p.stype, p.sprop, is_group, bas)
+
+ o.buf = obuf
+ o.index = oi
+
+ return err
+}
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+import (
+ "reflect"
+)
+
+// Decode a reference to a struct pointer.
+func (o *Buffer) dec_ref_struct_message(p *Properties, base structPointer) (err error) {
+ raw, e := o.DecodeRawBytes(false)
+ if e != nil {
+ return e
+ }
+
+ // If the object can unmarshal itself, let it.
+ if p.isUnmarshaler {
+ panic("not supported, since this is a pointer receiver")
+ }
+
+ obuf := o.buf
+ oi := o.index
+ o.buf = raw
+ o.index = 0
+
+ bas := structPointer_FieldPointer(base, p.field)
+
+ err = o.unmarshalType(p.stype, p.sprop, false, bas)
+ o.buf = obuf
+ o.index = oi
+
+ return err
+}
+
+// Decode a slice of references to struct pointers ([]struct).
+func (o *Buffer) dec_slice_ref_struct(p *Properties, is_group bool, base structPointer) error {
+ newBas := appendStructPointer(base, p.field, p.sstype)
+
+ if is_group {
+ panic("not supported, maybe in future, if requested.")
+ }
+
+ raw, err := o.DecodeRawBytes(false)
+ if err != nil {
+ return err
+ }
+
+ // If the object can unmarshal itself, let it.
+ if p.isUnmarshaler {
+ panic("not supported, since this is not a pointer receiver.")
+ }
+
+ obuf := o.buf
+ oi := o.index
+ o.buf = raw
+ o.index = 0
+
+ err = o.unmarshalType(p.stype, p.sprop, is_group, newBas)
+
+ o.buf = obuf
+ o.index = oi
+
+ return err
+}
+
+// Decode a slice of references to struct pointers.
+func (o *Buffer) dec_slice_ref_struct_message(p *Properties, base structPointer) error {
+ return o.dec_slice_ref_struct(p, false, base)
+}
+
+func setPtrCustomType(base structPointer, f field, v interface{}) {
+ if v == nil {
+ return
+ }
+ structPointer_SetStructPointer(base, f, toStructPointer(reflect.ValueOf(v)))
+}
+
+func setCustomType(base structPointer, f field, value interface{}) {
+ if value == nil {
+ return
+ }
+ v := reflect.ValueOf(value).Elem()
+ t := reflect.TypeOf(value).Elem()
+ kind := t.Kind()
+ switch kind {
+ case reflect.Slice:
+ slice := reflect.MakeSlice(t, v.Len(), v.Cap())
+ reflect.Copy(slice, v)
+ oldHeader := structPointer_GetSliceHeader(base, f)
+ oldHeader.Data = slice.Pointer()
+ oldHeader.Len = v.Len()
+ oldHeader.Cap = v.Cap()
+ default:
+ size := reflect.TypeOf(value).Elem().Size()
+ structPointer_Copy(toStructPointer(reflect.ValueOf(value)), structPointer_Add(base, f), int(size))
+ }
+}
+
+func (o *Buffer) dec_custom_bytes(p *Properties, base structPointer) error {
+ b, err := o.DecodeRawBytes(true)
+ if err != nil {
+ return err
+ }
+ i := reflect.New(p.ctype.Elem()).Interface()
+ custom := (i).(Unmarshaler)
+ if err := custom.Unmarshal(b); err != nil {
+ return err
+ }
+ setPtrCustomType(base, p.field, custom)
+ return nil
+}
+
+func (o *Buffer) dec_custom_ref_bytes(p *Properties, base structPointer) error {
+ b, err := o.DecodeRawBytes(true)
+ if err != nil {
+ return err
+ }
+ i := reflect.New(p.ctype).Interface()
+ custom := (i).(Unmarshaler)
+ if err := custom.Unmarshal(b); err != nil {
+ return err
+ }
+ if custom != nil {
+ setCustomType(base, p.field, custom)
+ }
+ return nil
+}
+
+// Decode a slice of bytes ([]byte) into a slice of custom types.
+func (o *Buffer) dec_custom_slice_bytes(p *Properties, base structPointer) error {
+ b, err := o.DecodeRawBytes(true)
+ if err != nil {
+ return err
+ }
+ i := reflect.New(p.ctype.Elem()).Interface()
+ custom := (i).(Unmarshaler)
+ if err := custom.Unmarshal(b); err != nil {
+ return err
+ }
+ newBas := appendStructPointer(base, p.field, p.ctype)
+
+ var zero field
+ setCustomType(newBas, zero, custom)
+
+ return nil
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+// This file implements conversions between google.protobuf.Duration
+// and time.Duration.
+
+import (
+ "errors"
+ "fmt"
+ "time"
+)
+
+const (
+ // Range of a Duration in seconds, as specified in
+ // google/protobuf/duration.proto. This is about 10,000 years in seconds.
+ maxSeconds = int64(10000 * 365.25 * 24 * 60 * 60)
+ minSeconds = -maxSeconds
+)
+
+// validateDuration determines whether the Duration is valid according to the
+// definition in google/protobuf/duration.proto. A valid Duration
+// may still be too large to fit into a time.Duration (the range of Duration
+// is about 10,000 years, and the range of time.Duration is about 290).
+func validateDuration(d *duration) error {
+ if d == nil {
+ return errors.New("duration: nil Duration")
+ }
+ if d.Seconds < minSeconds || d.Seconds > maxSeconds {
+ return fmt.Errorf("duration: %#v: seconds out of range", d)
+ }
+ if d.Nanos <= -1e9 || d.Nanos >= 1e9 {
+ return fmt.Errorf("duration: %#v: nanos out of range", d)
+ }
+ // Seconds and Nanos must have the same sign, unless d.Nanos is zero.
+ if (d.Seconds < 0 && d.Nanos > 0) || (d.Seconds > 0 && d.Nanos < 0) {
+ return fmt.Errorf("duration: %#v: seconds and nanos have different signs", d)
+ }
+ return nil
+}
+
+// DurationFromProto converts a Duration to a time.Duration. DurationFromProto
+// returns an error if the Duration is invalid or is too large to be
+// represented in a time.Duration.
+func durationFromProto(p *duration) (time.Duration, error) {
+ if err := validateDuration(p); err != nil {
+ return 0, err
+ }
+ d := time.Duration(p.Seconds) * time.Second
+ if int64(d/time.Second) != p.Seconds {
+ return 0, fmt.Errorf("duration: %#v is out of range for time.Duration", p)
+ }
+ if p.Nanos != 0 {
+ d += time.Duration(p.Nanos)
+ if (d < 0) != (p.Nanos < 0) {
+ return 0, fmt.Errorf("duration: %#v is out of range for time.Duration", p)
+ }
+ }
+ return d, nil
+}
+
+// DurationProto converts a time.Duration to a Duration.
+func durationProto(d time.Duration) *duration {
+ nanos := d.Nanoseconds()
+ secs := nanos / 1e9
+ nanos -= secs * 1e9
+ return &duration{
+ Seconds: secs,
+ Nanos: int32(nanos),
+ }
+}
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2016, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+import (
+ "reflect"
+ "time"
+)
+
+var durationType = reflect.TypeOf((*time.Duration)(nil)).Elem()
+
+type duration struct {
+ Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
+ Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
+}
+
+func (m *duration) Reset() { *m = duration{} }
+func (*duration) ProtoMessage() {}
+func (*duration) String() string { return "duration<string>" }
+
+func init() {
+ RegisterType((*duration)(nil), "gogo.protobuf.proto.duration")
+}
+
+func (o *Buffer) decDuration() (time.Duration, error) {
+ b, err := o.DecodeRawBytes(true)
+ if err != nil {
+ return 0, err
+ }
+ dproto := &duration{}
+ if err := Unmarshal(b, dproto); err != nil {
+ return 0, err
+ }
+ return durationFromProto(dproto)
+}
+
+func (o *Buffer) dec_duration(p *Properties, base structPointer) error {
+ d, err := o.decDuration()
+ if err != nil {
+ return err
+ }
+ word64_Set(structPointer_Word64(base, p.field), o, uint64(d))
+ return nil
+}
+
+func (o *Buffer) dec_ref_duration(p *Properties, base structPointer) error {
+ d, err := o.decDuration()
+ if err != nil {
+ return err
+ }
+ word64Val_Set(structPointer_Word64Val(base, p.field), o, uint64(d))
+ return nil
+}
+
+func (o *Buffer) dec_slice_duration(p *Properties, base structPointer) error {
+ d, err := o.decDuration()
+ if err != nil {
+ return err
+ }
+ newBas := appendStructPointer(base, p.field, reflect.SliceOf(reflect.PtrTo(durationType)))
+ var zero field
+ setPtrCustomType(newBas, zero, &d)
+ return nil
+}
+
+func (o *Buffer) dec_slice_ref_duration(p *Properties, base structPointer) error {
+ d, err := o.decDuration()
+ if err != nil {
+ return err
+ }
+ structPointer_Word64Slice(base, p.field).Append(uint64(d))
+ return nil
+}
+
+func size_duration(p *Properties, base structPointer) (n int) {
+ structp := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(structp) {
+ return 0
+ }
+ dur := structPointer_Interface(structp, durationType).(*time.Duration)
+ d := durationProto(*dur)
+ size := Size(d)
+ return size + sizeVarint(uint64(size)) + len(p.tagcode)
+}
+
+func (o *Buffer) enc_duration(p *Properties, base structPointer) error {
+ structp := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(structp) {
+ return ErrNil
+ }
+ dur := structPointer_Interface(structp, durationType).(*time.Duration)
+ d := durationProto(*dur)
+ data, err := Marshal(d)
+ if err != nil {
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ return nil
+}
+
+func size_ref_duration(p *Properties, base structPointer) (n int) {
+ dur := structPointer_InterfaceAt(base, p.field, durationType).(*time.Duration)
+ d := durationProto(*dur)
+ size := Size(d)
+ return size + sizeVarint(uint64(size)) + len(p.tagcode)
+}
+
+func (o *Buffer) enc_ref_duration(p *Properties, base structPointer) error {
+ dur := structPointer_InterfaceAt(base, p.field, durationType).(*time.Duration)
+ d := durationProto(*dur)
+ data, err := Marshal(d)
+ if err != nil {
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ return nil
+}
+
+func size_slice_duration(p *Properties, base structPointer) (n int) {
+ pdurs := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(reflect.PtrTo(durationType))).(*[]*time.Duration)
+ durs := *pdurs
+ for i := 0; i < len(durs); i++ {
+ if durs[i] == nil {
+ return 0
+ }
+ dproto := durationProto(*durs[i])
+ size := Size(dproto)
+ n += len(p.tagcode) + size + sizeVarint(uint64(size))
+ }
+ return n
+}
+
+func (o *Buffer) enc_slice_duration(p *Properties, base structPointer) error {
+ pdurs := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(reflect.PtrTo(durationType))).(*[]*time.Duration)
+ durs := *pdurs
+ for i := 0; i < len(durs); i++ {
+ if durs[i] == nil {
+ return errRepeatedHasNil
+ }
+ dproto := durationProto(*durs[i])
+ data, err := Marshal(dproto)
+ if err != nil {
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ }
+ return nil
+}
+
+func size_slice_ref_duration(p *Properties, base structPointer) (n int) {
+ pdurs := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(durationType)).(*[]time.Duration)
+ durs := *pdurs
+ for i := 0; i < len(durs); i++ {
+ dproto := durationProto(durs[i])
+ size := Size(dproto)
+ n += len(p.tagcode) + size + sizeVarint(uint64(size))
+ }
+ return n
+}
+
+func (o *Buffer) enc_slice_ref_duration(p *Properties, base structPointer) error {
+ pdurs := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(durationType)).(*[]time.Duration)
+ durs := *pdurs
+ for i := 0; i < len(durs); i++ {
+ dproto := durationProto(durs[i])
+ data, err := Marshal(dproto)
+ if err != nil {
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ }
+ return nil
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+/*
+ * Routines for encoding data into the wire format for protocol buffers.
+ */
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+ "sort"
+)
+
+// RequiredNotSetError is the error returned if Marshal is called with
+// a protocol buffer struct whose required fields have not
+// all been initialized. It is also the error returned if Unmarshal is
+// called with an encoded protocol buffer that does not include all the
+// required fields.
+//
+// When printed, RequiredNotSetError reports the first unset required field in a
+// message. If the field cannot be precisely determined, it is reported as
+// "{Unknown}".
+type RequiredNotSetError struct {
+ field string
+}
+
+func (e *RequiredNotSetError) Error() string {
+ return fmt.Sprintf("proto: required field %q not set", e.field)
+}
+
+var (
+ // errRepeatedHasNil is the error returned if Marshal is called with
+ // a struct with a repeated field containing a nil element.
+ errRepeatedHasNil = errors.New("proto: repeated field has nil element")
+
+ // errOneofHasNil is the error returned if Marshal is called with
+ // a struct with a oneof field containing a nil element.
+ errOneofHasNil = errors.New("proto: oneof field has nil value")
+
+ // ErrNil is the error returned if Marshal is called with nil.
+ ErrNil = errors.New("proto: Marshal called with nil")
+
+ // ErrTooLarge is the error returned if Marshal is called with a
+ // message that encodes to >2GB.
+ ErrTooLarge = errors.New("proto: message encodes to over 2 GB")
+)
+
+// The fundamental encoders that put bytes on the wire.
+// Those that take integer types all accept uint64 and are
+// therefore of type valueEncoder.
+
+const maxVarintBytes = 10 // maximum length of a varint
+
+// maxMarshalSize is the largest allowed size of an encoded protobuf,
+// since C++ and Java use signed int32s for the size.
+const maxMarshalSize = 1<<31 - 1
+
+// EncodeVarint returns the varint encoding of x.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+// Not used by the package itself, but helpful to clients
+// wishing to use the same encoding.
+func EncodeVarint(x uint64) []byte {
+ var buf [maxVarintBytes]byte
+ var n int
+ for n = 0; x > 127; n++ {
+ buf[n] = 0x80 | uint8(x&0x7F)
+ x >>= 7
+ }
+ buf[n] = uint8(x)
+ n++
+ return buf[0:n]
+}
+
+// EncodeVarint writes a varint-encoded integer to the Buffer.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+func (p *Buffer) EncodeVarint(x uint64) error {
+ for x >= 1<<7 {
+ p.buf = append(p.buf, uint8(x&0x7f|0x80))
+ x >>= 7
+ }
+ p.buf = append(p.buf, uint8(x))
+ return nil
+}
+
+// SizeVarint returns the varint encoding size of an integer.
+func SizeVarint(x uint64) int {
+ return sizeVarint(x)
+}
+
+func sizeVarint(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+
+// EncodeFixed64 writes a 64-bit integer to the Buffer.
+// This is the format for the
+// fixed64, sfixed64, and double protocol buffer types.
+func (p *Buffer) EncodeFixed64(x uint64) error {
+ p.buf = append(p.buf,
+ uint8(x),
+ uint8(x>>8),
+ uint8(x>>16),
+ uint8(x>>24),
+ uint8(x>>32),
+ uint8(x>>40),
+ uint8(x>>48),
+ uint8(x>>56))
+ return nil
+}
+
+func sizeFixed64(x uint64) int {
+ return 8
+}
+
+// EncodeFixed32 writes a 32-bit integer to the Buffer.
+// This is the format for the
+// fixed32, sfixed32, and float protocol buffer types.
+func (p *Buffer) EncodeFixed32(x uint64) error {
+ p.buf = append(p.buf,
+ uint8(x),
+ uint8(x>>8),
+ uint8(x>>16),
+ uint8(x>>24))
+ return nil
+}
+
+func sizeFixed32(x uint64) int {
+ return 4
+}
+
+// EncodeZigzag64 writes a zigzag-encoded 64-bit integer
+// to the Buffer.
+// This is the format used for the sint64 protocol buffer type.
+func (p *Buffer) EncodeZigzag64(x uint64) error {
+ // use signed number to get arithmetic right shift.
+ return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+
+func sizeZigzag64(x uint64) int {
+ return sizeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+
+// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
+// to the Buffer.
+// This is the format used for the sint32 protocol buffer type.
+func (p *Buffer) EncodeZigzag32(x uint64) error {
+ // use signed number to get arithmetic right shift.
+ return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
+}
+
+func sizeZigzag32(x uint64) int {
+ return sizeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
+}
+
+// EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
+// This is the format used for the bytes protocol buffer
+// type and for embedded messages.
+func (p *Buffer) EncodeRawBytes(b []byte) error {
+ p.EncodeVarint(uint64(len(b)))
+ p.buf = append(p.buf, b...)
+ return nil
+}
+
+func sizeRawBytes(b []byte) int {
+ return sizeVarint(uint64(len(b))) +
+ len(b)
+}
+
+// EncodeStringBytes writes an encoded string to the Buffer.
+// This is the format used for the proto2 string type.
+func (p *Buffer) EncodeStringBytes(s string) error {
+ p.EncodeVarint(uint64(len(s)))
+ p.buf = append(p.buf, s...)
+ return nil
+}
+
+func sizeStringBytes(s string) int {
+ return sizeVarint(uint64(len(s))) +
+ len(s)
+}
+
+// Marshaler is the interface representing objects that can marshal themselves.
+type Marshaler interface {
+ Marshal() ([]byte, error)
+}
+
+// Marshal takes the protocol buffer
+// and encodes it into the wire format, returning the data.
+func Marshal(pb Message) ([]byte, error) {
+ // Can the object marshal itself?
+ if m, ok := pb.(Marshaler); ok {
+ return m.Marshal()
+ }
+ p := NewBuffer(nil)
+ err := p.Marshal(pb)
+ if p.buf == nil && err == nil {
+ // Return a non-nil slice on success.
+ return []byte{}, nil
+ }
+ return p.buf, err
+}
+
+// EncodeMessage writes the protocol buffer to the Buffer,
+// prefixed by a varint-encoded length.
+func (p *Buffer) EncodeMessage(pb Message) error {
+ t, base, err := getbase(pb)
+ if structPointer_IsNil(base) {
+ return ErrNil
+ }
+ if err == nil {
+ var state errorState
+ err = p.enc_len_struct(GetProperties(t.Elem()), base, &state)
+ }
+ return err
+}
+
+// Marshal takes the protocol buffer
+// and encodes it into the wire format, writing the result to the
+// Buffer.
+func (p *Buffer) Marshal(pb Message) error {
+ // Can the object marshal itself?
+ if m, ok := pb.(Marshaler); ok {
+ data, err := m.Marshal()
+ p.buf = append(p.buf, data...)
+ return err
+ }
+
+ t, base, err := getbase(pb)
+ if structPointer_IsNil(base) {
+ return ErrNil
+ }
+ if err == nil {
+ err = p.enc_struct(GetProperties(t.Elem()), base)
+ }
+
+ if collectStats {
+ (stats).Encode++ // Parens are to work around a goimports bug.
+ }
+
+ if len(p.buf) > maxMarshalSize {
+ return ErrTooLarge
+ }
+ return err
+}
+
+// Size returns the encoded size of a protocol buffer.
+func Size(pb Message) (n int) {
+ // Can the object marshal itself? If so, Size is slow.
+ // TODO: add Size to Marshaler, or add a Sizer interface.
+ if m, ok := pb.(Marshaler); ok {
+ b, _ := m.Marshal()
+ return len(b)
+ }
+
+ t, base, err := getbase(pb)
+ if structPointer_IsNil(base) {
+ return 0
+ }
+ if err == nil {
+ n = size_struct(GetProperties(t.Elem()), base)
+ }
+
+ if collectStats {
+ (stats).Size++ // Parens are to work around a goimports bug.
+ }
+
+ return
+}
+
+// Individual type encoders.
+
+// Encode a bool.
+func (o *Buffer) enc_bool(p *Properties, base structPointer) error {
+ v := *structPointer_Bool(base, p.field)
+ if v == nil {
+ return ErrNil
+ }
+ x := 0
+ if *v {
+ x = 1
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+func (o *Buffer) enc_proto3_bool(p *Properties, base structPointer) error {
+ v := *structPointer_BoolVal(base, p.field)
+ if !v {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, 1)
+ return nil
+}
+
+func size_bool(p *Properties, base structPointer) int {
+ v := *structPointer_Bool(base, p.field)
+ if v == nil {
+ return 0
+ }
+ return len(p.tagcode) + 1 // each bool takes exactly one byte
+}
+
+func size_proto3_bool(p *Properties, base structPointer) int {
+ v := *structPointer_BoolVal(base, p.field)
+ if !v && !p.oneof {
+ return 0
+ }
+ return len(p.tagcode) + 1 // each bool takes exactly one byte
+}
+
+// Encode an int32.
+func (o *Buffer) enc_int32(p *Properties, base structPointer) error {
+ v := structPointer_Word32(base, p.field)
+ if word32_IsNil(v) {
+ return ErrNil
+ }
+ x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+func (o *Buffer) enc_proto3_int32(p *Properties, base structPointer) error {
+ v := structPointer_Word32Val(base, p.field)
+ x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range
+ if x == 0 {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+func size_int32(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word32(base, p.field)
+ if word32_IsNil(v) {
+ return 0
+ }
+ x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range
+ n += len(p.tagcode)
+ n += p.valSize(uint64(x))
+ return
+}
+
+func size_proto3_int32(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word32Val(base, p.field)
+ x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range
+ if x == 0 && !p.oneof {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += p.valSize(uint64(x))
+ return
+}
+
+// Encode a uint32.
+// Exactly the same as int32, except for no sign extension.
+func (o *Buffer) enc_uint32(p *Properties, base structPointer) error {
+ v := structPointer_Word32(base, p.field)
+ if word32_IsNil(v) {
+ return ErrNil
+ }
+ x := word32_Get(v)
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+func (o *Buffer) enc_proto3_uint32(p *Properties, base structPointer) error {
+ v := structPointer_Word32Val(base, p.field)
+ x := word32Val_Get(v)
+ if x == 0 {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+func size_uint32(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word32(base, p.field)
+ if word32_IsNil(v) {
+ return 0
+ }
+ x := word32_Get(v)
+ n += len(p.tagcode)
+ n += p.valSize(uint64(x))
+ return
+}
+
+func size_proto3_uint32(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word32Val(base, p.field)
+ x := word32Val_Get(v)
+ if x == 0 && !p.oneof {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += p.valSize(uint64(x))
+ return
+}
+
+// Encode an int64.
+func (o *Buffer) enc_int64(p *Properties, base structPointer) error {
+ v := structPointer_Word64(base, p.field)
+ if word64_IsNil(v) {
+ return ErrNil
+ }
+ x := word64_Get(v)
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, x)
+ return nil
+}
+
+func (o *Buffer) enc_proto3_int64(p *Properties, base structPointer) error {
+ v := structPointer_Word64Val(base, p.field)
+ x := word64Val_Get(v)
+ if x == 0 {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, x)
+ return nil
+}
+
+func size_int64(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word64(base, p.field)
+ if word64_IsNil(v) {
+ return 0
+ }
+ x := word64_Get(v)
+ n += len(p.tagcode)
+ n += p.valSize(x)
+ return
+}
+
+func size_proto3_int64(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word64Val(base, p.field)
+ x := word64Val_Get(v)
+ if x == 0 && !p.oneof {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += p.valSize(x)
+ return
+}
+
+// Encode a string.
+func (o *Buffer) enc_string(p *Properties, base structPointer) error {
+ v := *structPointer_String(base, p.field)
+ if v == nil {
+ return ErrNil
+ }
+ x := *v
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeStringBytes(x)
+ return nil
+}
+
+func (o *Buffer) enc_proto3_string(p *Properties, base structPointer) error {
+ v := *structPointer_StringVal(base, p.field)
+ if v == "" {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeStringBytes(v)
+ return nil
+}
+
+func size_string(p *Properties, base structPointer) (n int) {
+ v := *structPointer_String(base, p.field)
+ if v == nil {
+ return 0
+ }
+ x := *v
+ n += len(p.tagcode)
+ n += sizeStringBytes(x)
+ return
+}
+
+func size_proto3_string(p *Properties, base structPointer) (n int) {
+ v := *structPointer_StringVal(base, p.field)
+ if v == "" && !p.oneof {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += sizeStringBytes(v)
+ return
+}
+
+// All protocol buffer fields are nillable, but be careful.
+func isNil(v reflect.Value) bool {
+ switch v.Kind() {
+ case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
+ return v.IsNil()
+ }
+ return false
+}
+
+// Encode a message struct.
+func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error {
+ var state errorState
+ structp := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(structp) {
+ return ErrNil
+ }
+
+ // Can the object marshal itself?
+ if p.isMarshaler {
+ m := structPointer_Interface(structp, p.stype).(Marshaler)
+ data, err := m.Marshal()
+ if err != nil && !state.shouldContinue(err, nil) {
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ return state.err
+ }
+
+ o.buf = append(o.buf, p.tagcode...)
+ return o.enc_len_struct(p.sprop, structp, &state)
+}
+
+func size_struct_message(p *Properties, base structPointer) int {
+ structp := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(structp) {
+ return 0
+ }
+
+ // Can the object marshal itself?
+ if p.isMarshaler {
+ m := structPointer_Interface(structp, p.stype).(Marshaler)
+ data, _ := m.Marshal()
+ n0 := len(p.tagcode)
+ n1 := sizeRawBytes(data)
+ return n0 + n1
+ }
+
+ n0 := len(p.tagcode)
+ n1 := size_struct(p.sprop, structp)
+ n2 := sizeVarint(uint64(n1)) // size of encoded length
+ return n0 + n1 + n2
+}
+
+// Encode a group struct.
+func (o *Buffer) enc_struct_group(p *Properties, base structPointer) error {
+ var state errorState
+ b := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(b) {
+ return ErrNil
+ }
+
+ o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
+ err := o.enc_struct(p.sprop, b)
+ if err != nil && !state.shouldContinue(err, nil) {
+ return err
+ }
+ o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
+ return state.err
+}
+
+func size_struct_group(p *Properties, base structPointer) (n int) {
+ b := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(b) {
+ return 0
+ }
+
+ n += sizeVarint(uint64((p.Tag << 3) | WireStartGroup))
+ n += size_struct(p.sprop, b)
+ n += sizeVarint(uint64((p.Tag << 3) | WireEndGroup))
+ return
+}
+
+// Encode a slice of bools ([]bool).
+func (o *Buffer) enc_slice_bool(p *Properties, base structPointer) error {
+ s := *structPointer_BoolSlice(base, p.field)
+ l := len(s)
+ if l == 0 {
+ return ErrNil
+ }
+ for _, x := range s {
+ o.buf = append(o.buf, p.tagcode...)
+ v := uint64(0)
+ if x {
+ v = 1
+ }
+ p.valEnc(o, v)
+ }
+ return nil
+}
+
+func size_slice_bool(p *Properties, base structPointer) int {
+ s := *structPointer_BoolSlice(base, p.field)
+ l := len(s)
+ if l == 0 {
+ return 0
+ }
+ return l * (len(p.tagcode) + 1) // each bool takes exactly one byte
+}
+
+// Encode a slice of bools ([]bool) in packed format.
+func (o *Buffer) enc_slice_packed_bool(p *Properties, base structPointer) error {
+ s := *structPointer_BoolSlice(base, p.field)
+ l := len(s)
+ if l == 0 {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeVarint(uint64(l)) // each bool takes exactly one byte
+ for _, x := range s {
+ v := uint64(0)
+ if x {
+ v = 1
+ }
+ p.valEnc(o, v)
+ }
+ return nil
+}
+
+func size_slice_packed_bool(p *Properties, base structPointer) (n int) {
+ s := *structPointer_BoolSlice(base, p.field)
+ l := len(s)
+ if l == 0 {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += sizeVarint(uint64(l))
+ n += l // each bool takes exactly one byte
+ return
+}
+
+// Encode a slice of bytes ([]byte).
+func (o *Buffer) enc_slice_byte(p *Properties, base structPointer) error {
+ s := *structPointer_Bytes(base, p.field)
+ if s == nil {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(s)
+ return nil
+}
+
+func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer) error {
+ s := *structPointer_Bytes(base, p.field)
+ if len(s) == 0 {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(s)
+ return nil
+}
+
+func size_slice_byte(p *Properties, base structPointer) (n int) {
+ s := *structPointer_Bytes(base, p.field)
+ if s == nil && !p.oneof {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += sizeRawBytes(s)
+ return
+}
+
+func size_proto3_slice_byte(p *Properties, base structPointer) (n int) {
+ s := *structPointer_Bytes(base, p.field)
+ if len(s) == 0 && !p.oneof {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += sizeRawBytes(s)
+ return
+}
+
+// Encode a slice of int32s ([]int32).
+func (o *Buffer) enc_slice_int32(p *Properties, base structPointer) error {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return ErrNil
+ }
+ for i := 0; i < l; i++ {
+ o.buf = append(o.buf, p.tagcode...)
+ x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
+ p.valEnc(o, uint64(x))
+ }
+ return nil
+}
+
+func size_slice_int32(p *Properties, base structPointer) (n int) {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return 0
+ }
+ for i := 0; i < l; i++ {
+ n += len(p.tagcode)
+ x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
+ n += p.valSize(uint64(x))
+ }
+ return
+}
+
+// Encode a slice of int32s ([]int32) in packed format.
+func (o *Buffer) enc_slice_packed_int32(p *Properties, base structPointer) error {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return ErrNil
+ }
+ // TODO: Reuse a Buffer.
+ buf := NewBuffer(nil)
+ for i := 0; i < l; i++ {
+ x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
+ p.valEnc(buf, uint64(x))
+ }
+
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeVarint(uint64(len(buf.buf)))
+ o.buf = append(o.buf, buf.buf...)
+ return nil
+}
+
+func size_slice_packed_int32(p *Properties, base structPointer) (n int) {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return 0
+ }
+ var bufSize int
+ for i := 0; i < l; i++ {
+ x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
+ bufSize += p.valSize(uint64(x))
+ }
+
+ n += len(p.tagcode)
+ n += sizeVarint(uint64(bufSize))
+ n += bufSize
+ return
+}
+
+// Encode a slice of uint32s ([]uint32).
+// Exactly the same as int32, except for no sign extension.
+func (o *Buffer) enc_slice_uint32(p *Properties, base structPointer) error {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return ErrNil
+ }
+ for i := 0; i < l; i++ {
+ o.buf = append(o.buf, p.tagcode...)
+ x := s.Index(i)
+ p.valEnc(o, uint64(x))
+ }
+ return nil
+}
+
+func size_slice_uint32(p *Properties, base structPointer) (n int) {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return 0
+ }
+ for i := 0; i < l; i++ {
+ n += len(p.tagcode)
+ x := s.Index(i)
+ n += p.valSize(uint64(x))
+ }
+ return
+}
+
+// Encode a slice of uint32s ([]uint32) in packed format.
+// Exactly the same as int32, except for no sign extension.
+func (o *Buffer) enc_slice_packed_uint32(p *Properties, base structPointer) error {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return ErrNil
+ }
+ // TODO: Reuse a Buffer.
+ buf := NewBuffer(nil)
+ for i := 0; i < l; i++ {
+ p.valEnc(buf, uint64(s.Index(i)))
+ }
+
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeVarint(uint64(len(buf.buf)))
+ o.buf = append(o.buf, buf.buf...)
+ return nil
+}
+
+func size_slice_packed_uint32(p *Properties, base structPointer) (n int) {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return 0
+ }
+ var bufSize int
+ for i := 0; i < l; i++ {
+ bufSize += p.valSize(uint64(s.Index(i)))
+ }
+
+ n += len(p.tagcode)
+ n += sizeVarint(uint64(bufSize))
+ n += bufSize
+ return
+}
+
+// Encode a slice of int64s ([]int64).
+func (o *Buffer) enc_slice_int64(p *Properties, base structPointer) error {
+ s := structPointer_Word64Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return ErrNil
+ }
+ for i := 0; i < l; i++ {
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, s.Index(i))
+ }
+ return nil
+}
+
+func size_slice_int64(p *Properties, base structPointer) (n int) {
+ s := structPointer_Word64Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return 0
+ }
+ for i := 0; i < l; i++ {
+ n += len(p.tagcode)
+ n += p.valSize(s.Index(i))
+ }
+ return
+}
+
+// Encode a slice of int64s ([]int64) in packed format.
+func (o *Buffer) enc_slice_packed_int64(p *Properties, base structPointer) error {
+ s := structPointer_Word64Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return ErrNil
+ }
+ // TODO: Reuse a Buffer.
+ buf := NewBuffer(nil)
+ for i := 0; i < l; i++ {
+ p.valEnc(buf, s.Index(i))
+ }
+
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeVarint(uint64(len(buf.buf)))
+ o.buf = append(o.buf, buf.buf...)
+ return nil
+}
+
+func size_slice_packed_int64(p *Properties, base structPointer) (n int) {
+ s := structPointer_Word64Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return 0
+ }
+ var bufSize int
+ for i := 0; i < l; i++ {
+ bufSize += p.valSize(s.Index(i))
+ }
+
+ n += len(p.tagcode)
+ n += sizeVarint(uint64(bufSize))
+ n += bufSize
+ return
+}
+
+// Encode a slice of slice of bytes ([][]byte).
+func (o *Buffer) enc_slice_slice_byte(p *Properties, base structPointer) error {
+ ss := *structPointer_BytesSlice(base, p.field)
+ l := len(ss)
+ if l == 0 {
+ return ErrNil
+ }
+ for i := 0; i < l; i++ {
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(ss[i])
+ }
+ return nil
+}
+
+func size_slice_slice_byte(p *Properties, base structPointer) (n int) {
+ ss := *structPointer_BytesSlice(base, p.field)
+ l := len(ss)
+ if l == 0 {
+ return 0
+ }
+ n += l * len(p.tagcode)
+ for i := 0; i < l; i++ {
+ n += sizeRawBytes(ss[i])
+ }
+ return
+}
+
+// Encode a slice of strings ([]string).
+func (o *Buffer) enc_slice_string(p *Properties, base structPointer) error {
+ ss := *structPointer_StringSlice(base, p.field)
+ l := len(ss)
+ for i := 0; i < l; i++ {
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeStringBytes(ss[i])
+ }
+ return nil
+}
+
+func size_slice_string(p *Properties, base structPointer) (n int) {
+ ss := *structPointer_StringSlice(base, p.field)
+ l := len(ss)
+ n += l * len(p.tagcode)
+ for i := 0; i < l; i++ {
+ n += sizeStringBytes(ss[i])
+ }
+ return
+}
+
+// Encode a slice of message structs ([]*struct).
+func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) error {
+ var state errorState
+ s := structPointer_StructPointerSlice(base, p.field)
+ l := s.Len()
+
+ for i := 0; i < l; i++ {
+ structp := s.Index(i)
+ if structPointer_IsNil(structp) {
+ return errRepeatedHasNil
+ }
+
+ // Can the object marshal itself?
+ if p.isMarshaler {
+ m := structPointer_Interface(structp, p.stype).(Marshaler)
+ data, err := m.Marshal()
+ if err != nil && !state.shouldContinue(err, nil) {
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ continue
+ }
+
+ o.buf = append(o.buf, p.tagcode...)
+ err := o.enc_len_struct(p.sprop, structp, &state)
+ if err != nil && !state.shouldContinue(err, nil) {
+ if err == ErrNil {
+ return errRepeatedHasNil
+ }
+ return err
+ }
+ }
+ return state.err
+}
+
+func size_slice_struct_message(p *Properties, base structPointer) (n int) {
+ s := structPointer_StructPointerSlice(base, p.field)
+ l := s.Len()
+ n += l * len(p.tagcode)
+ for i := 0; i < l; i++ {
+ structp := s.Index(i)
+ if structPointer_IsNil(structp) {
+ return // return the size up to this point
+ }
+
+ // Can the object marshal itself?
+ if p.isMarshaler {
+ m := structPointer_Interface(structp, p.stype).(Marshaler)
+ data, _ := m.Marshal()
+ n += sizeRawBytes(data)
+ continue
+ }
+
+ n0 := size_struct(p.sprop, structp)
+ n1 := sizeVarint(uint64(n0)) // size of encoded length
+ n += n0 + n1
+ }
+ return
+}
+
+// Encode a slice of group structs ([]*struct).
+func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error {
+ var state errorState
+ s := structPointer_StructPointerSlice(base, p.field)
+ l := s.Len()
+
+ for i := 0; i < l; i++ {
+ b := s.Index(i)
+ if structPointer_IsNil(b) {
+ return errRepeatedHasNil
+ }
+
+ o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
+
+ err := o.enc_struct(p.sprop, b)
+
+ if err != nil && !state.shouldContinue(err, nil) {
+ if err == ErrNil {
+ return errRepeatedHasNil
+ }
+ return err
+ }
+
+ o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
+ }
+ return state.err
+}
+
+func size_slice_struct_group(p *Properties, base structPointer) (n int) {
+ s := structPointer_StructPointerSlice(base, p.field)
+ l := s.Len()
+
+ n += l * sizeVarint(uint64((p.Tag<<3)|WireStartGroup))
+ n += l * sizeVarint(uint64((p.Tag<<3)|WireEndGroup))
+ for i := 0; i < l; i++ {
+ b := s.Index(i)
+ if structPointer_IsNil(b) {
+ return // return size up to this point
+ }
+
+ n += size_struct(p.sprop, b)
+ }
+ return
+}
+
+// Encode an extension map.
+func (o *Buffer) enc_map(p *Properties, base structPointer) error {
+ exts := structPointer_ExtMap(base, p.field)
+ if err := encodeExtensionsMap(*exts); err != nil {
+ return err
+ }
+
+ return o.enc_map_body(*exts)
+}
+
+func (o *Buffer) enc_exts(p *Properties, base structPointer) error {
+ exts := structPointer_Extensions(base, p.field)
+
+ v, mu := exts.extensionsRead()
+ if v == nil {
+ return nil
+ }
+
+ mu.Lock()
+ defer mu.Unlock()
+ if err := encodeExtensionsMap(v); err != nil {
+ return err
+ }
+
+ return o.enc_map_body(v)
+}
+
+func (o *Buffer) enc_map_body(v map[int32]Extension) error {
+ // Fast-path for common cases: zero or one extensions.
+ if len(v) <= 1 {
+ for _, e := range v {
+ o.buf = append(o.buf, e.enc...)
+ }
+ return nil
+ }
+
+ // Sort keys to provide a deterministic encoding.
+ keys := make([]int, 0, len(v))
+ for k := range v {
+ keys = append(keys, int(k))
+ }
+ sort.Ints(keys)
+
+ for _, k := range keys {
+ o.buf = append(o.buf, v[int32(k)].enc...)
+ }
+ return nil
+}
+
+func size_map(p *Properties, base structPointer) int {
+ v := structPointer_ExtMap(base, p.field)
+ return extensionsMapSize(*v)
+}
+
+func size_exts(p *Properties, base structPointer) int {
+ v := structPointer_Extensions(base, p.field)
+ return extensionsSize(v)
+}
+
+// Encode a map field.
+func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
+ var state errorState // XXX: or do we need to plumb this through?
+
+ /*
+ A map defined as
+ map<key_type, value_type> map_field = N;
+ is encoded in the same way as
+ message MapFieldEntry {
+ key_type key = 1;
+ value_type value = 2;
+ }
+ repeated MapFieldEntry map_field = N;
+ */
+
+ v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V
+ if v.Len() == 0 {
+ return nil
+ }
+
+ keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype)
+
+ enc := func() error {
+ if err := p.mkeyprop.enc(o, p.mkeyprop, keybase); err != nil {
+ return err
+ }
+ if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil && err != ErrNil {
+ return err
+ }
+ return nil
+ }
+
+ // Don't sort map keys. It is not required by the spec, and C++ doesn't do it.
+ for _, key := range v.MapKeys() {
+ val := v.MapIndex(key)
+
+ keycopy.Set(key)
+ valcopy.Set(val)
+
+ o.buf = append(o.buf, p.tagcode...)
+ if err := o.enc_len_thing(enc, &state); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func size_new_map(p *Properties, base structPointer) int {
+ v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V
+
+ keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype)
+
+ n := 0
+ for _, key := range v.MapKeys() {
+ val := v.MapIndex(key)
+ keycopy.Set(key)
+ valcopy.Set(val)
+
+ // Tag codes for key and val are the responsibility of the sub-sizer.
+ keysize := p.mkeyprop.size(p.mkeyprop, keybase)
+ valsize := p.mvalprop.size(p.mvalprop, valbase)
+ entry := keysize + valsize
+ // Add on tag code and length of map entry itself.
+ n += len(p.tagcode) + sizeVarint(uint64(entry)) + entry
+ }
+ return n
+}
+
+// mapEncodeScratch returns a new reflect.Value matching the map's value type,
+// and a structPointer suitable for passing to an encoder or sizer.
+func mapEncodeScratch(mapType reflect.Type) (keycopy, valcopy reflect.Value, keybase, valbase structPointer) {
+ // Prepare addressable doubly-indirect placeholders for the key and value types.
+ // This is needed because the element-type encoders expect **T, but the map iteration produces T.
+
+ keycopy = reflect.New(mapType.Key()).Elem() // addressable K
+ keyptr := reflect.New(reflect.PtrTo(keycopy.Type())).Elem() // addressable *K
+ keyptr.Set(keycopy.Addr()) //
+ keybase = toStructPointer(keyptr.Addr()) // **K
+
+ // Value types are more varied and require special handling.
+ switch mapType.Elem().Kind() {
+ case reflect.Slice:
+ // []byte
+ var dummy []byte
+ valcopy = reflect.ValueOf(&dummy).Elem() // addressable []byte
+ valbase = toStructPointer(valcopy.Addr())
+ case reflect.Ptr:
+ // message; the generated field type is map[K]*Msg (so V is *Msg),
+ // so we only need one level of indirection.
+ valcopy = reflect.New(mapType.Elem()).Elem() // addressable V
+ valbase = toStructPointer(valcopy.Addr())
+ default:
+ // everything else
+ valcopy = reflect.New(mapType.Elem()).Elem() // addressable V
+ valptr := reflect.New(reflect.PtrTo(valcopy.Type())).Elem() // addressable *V
+ valptr.Set(valcopy.Addr()) //
+ valbase = toStructPointer(valptr.Addr()) // **V
+ }
+ return
+}
+
+// Encode a struct.
+func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
+ var state errorState
+ // Encode fields in tag order so that decoders may use optimizations
+ // that depend on the ordering.
+ // https://developers.google.com/protocol-buffers/docs/encoding#order
+ for _, i := range prop.order {
+ p := prop.Prop[i]
+ if p.enc != nil {
+ err := p.enc(o, p, base)
+ if err != nil {
+ if err == ErrNil {
+ if p.Required && state.err == nil {
+ state.err = &RequiredNotSetError{p.Name}
+ }
+ } else if err == errRepeatedHasNil {
+ // Give more context to nil values in repeated fields.
+ return errors.New("repeated field " + p.OrigName + " has nil element")
+ } else if !state.shouldContinue(err, p) {
+ return err
+ }
+ }
+ if len(o.buf) > maxMarshalSize {
+ return ErrTooLarge
+ }
+ }
+ }
+
+ // Do oneof fields.
+ if prop.oneofMarshaler != nil {
+ m := structPointer_Interface(base, prop.stype).(Message)
+ if err := prop.oneofMarshaler(m, o); err == ErrNil {
+ return errOneofHasNil
+ } else if err != nil {
+ return err
+ }
+ }
+
+ // Add unrecognized fields at the end.
+ if prop.unrecField.IsValid() {
+ v := *structPointer_Bytes(base, prop.unrecField)
+ if len(o.buf)+len(v) > maxMarshalSize {
+ return ErrTooLarge
+ }
+ if len(v) > 0 {
+ o.buf = append(o.buf, v...)
+ }
+ }
+
+ return state.err
+}
+
+func size_struct(prop *StructProperties, base structPointer) (n int) {
+ for _, i := range prop.order {
+ p := prop.Prop[i]
+ if p.size != nil {
+ n += p.size(p, base)
+ }
+ }
+
+ // Add unrecognized fields at the end.
+ if prop.unrecField.IsValid() {
+ v := *structPointer_Bytes(base, prop.unrecField)
+ n += len(v)
+ }
+
+ // Factor in any oneof fields.
+ if prop.oneofSizer != nil {
+ m := structPointer_Interface(base, prop.stype).(Message)
+ n += prop.oneofSizer(m)
+ }
+
+ return
+}
+
+var zeroes [20]byte // longer than any conceivable sizeVarint
+
+// Encode a struct, preceded by its encoded length (as a varint).
+func (o *Buffer) enc_len_struct(prop *StructProperties, base structPointer, state *errorState) error {
+ return o.enc_len_thing(func() error { return o.enc_struct(prop, base) }, state)
+}
+
+// Encode something, preceded by its encoded length (as a varint).
+func (o *Buffer) enc_len_thing(enc func() error, state *errorState) error {
+ iLen := len(o.buf)
+ o.buf = append(o.buf, 0, 0, 0, 0) // reserve four bytes for length
+ iMsg := len(o.buf)
+ err := enc()
+ if err != nil && !state.shouldContinue(err, nil) {
+ return err
+ }
+ lMsg := len(o.buf) - iMsg
+ lLen := sizeVarint(uint64(lMsg))
+ switch x := lLen - (iMsg - iLen); {
+ case x > 0: // actual length is x bytes larger than the space we reserved
+ // Move msg x bytes right.
+ o.buf = append(o.buf, zeroes[:x]...)
+ copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg])
+ case x < 0: // actual length is x bytes smaller than the space we reserved
+ // Move msg x bytes left.
+ copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg])
+ o.buf = o.buf[:len(o.buf)+x] // x is negative
+ }
+ // Encode the length in the reserved space.
+ o.buf = o.buf[:iLen]
+ o.EncodeVarint(uint64(lMsg))
+ o.buf = o.buf[:len(o.buf)+lMsg]
+ return state.err
+}
+
+// errorState maintains the first error that occurs and updates that error
+// with additional context.
+type errorState struct {
+ err error
+}
+
+// shouldContinue reports whether encoding should continue upon encountering the
+// given error. If the error is RequiredNotSetError, shouldContinue returns true
+// and, if this is the first appearance of that error, remembers it for future
+// reporting.
+//
+// If prop is not nil, it may update any error with additional context about the
+// field with the error.
+func (s *errorState) shouldContinue(err error, prop *Properties) bool {
+ // Ignore unset required fields.
+ reqNotSet, ok := err.(*RequiredNotSetError)
+ if !ok {
+ return false
+ }
+ if s.err == nil {
+ if prop != nil {
+ err = &RequiredNotSetError{prop.Name + "." + reqNotSet.field}
+ }
+ s.err = err
+ }
+ return true
+}
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// http://github.com/golang/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+import (
+ "reflect"
+)
+
+func NewRequiredNotSetError(field string) *RequiredNotSetError {
+ return &RequiredNotSetError{field}
+}
+
+type Sizer interface {
+ Size() int
+}
+
+func (o *Buffer) enc_ext_slice_byte(p *Properties, base structPointer) error {
+ s := *structPointer_Bytes(base, p.field)
+ if s == nil {
+ return ErrNil
+ }
+ o.buf = append(o.buf, s...)
+ return nil
+}
+
+func size_ext_slice_byte(p *Properties, base structPointer) (n int) {
+ s := *structPointer_Bytes(base, p.field)
+ if s == nil {
+ return 0
+ }
+ n += len(s)
+ return
+}
+
+// Encode a reference to bool pointer.
+func (o *Buffer) enc_ref_bool(p *Properties, base structPointer) error {
+ v := *structPointer_BoolVal(base, p.field)
+ x := 0
+ if v {
+ x = 1
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+func size_ref_bool(p *Properties, base structPointer) int {
+ return len(p.tagcode) + 1 // each bool takes exactly one byte
+}
+
+// Encode a reference to int32 pointer.
+func (o *Buffer) enc_ref_int32(p *Properties, base structPointer) error {
+ v := structPointer_Word32Val(base, p.field)
+ x := int32(word32Val_Get(v))
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+func size_ref_int32(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word32Val(base, p.field)
+ x := int32(word32Val_Get(v))
+ n += len(p.tagcode)
+ n += p.valSize(uint64(x))
+ return
+}
+
+func (o *Buffer) enc_ref_uint32(p *Properties, base structPointer) error {
+ v := structPointer_Word32Val(base, p.field)
+ x := word32Val_Get(v)
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+func size_ref_uint32(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word32Val(base, p.field)
+ x := word32Val_Get(v)
+ n += len(p.tagcode)
+ n += p.valSize(uint64(x))
+ return
+}
+
+// Encode a reference to an int64 pointer.
+func (o *Buffer) enc_ref_int64(p *Properties, base structPointer) error {
+ v := structPointer_Word64Val(base, p.field)
+ x := word64Val_Get(v)
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, x)
+ return nil
+}
+
+func size_ref_int64(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word64Val(base, p.field)
+ x := word64Val_Get(v)
+ n += len(p.tagcode)
+ n += p.valSize(x)
+ return
+}
+
+// Encode a reference to a string pointer.
+func (o *Buffer) enc_ref_string(p *Properties, base structPointer) error {
+ v := *structPointer_StringVal(base, p.field)
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeStringBytes(v)
+ return nil
+}
+
+func size_ref_string(p *Properties, base structPointer) (n int) {
+ v := *structPointer_StringVal(base, p.field)
+ n += len(p.tagcode)
+ n += sizeStringBytes(v)
+ return
+}
+
+// Encode a reference to a message struct.
+func (o *Buffer) enc_ref_struct_message(p *Properties, base structPointer) error {
+ var state errorState
+ structp := structPointer_GetRefStructPointer(base, p.field)
+ if structPointer_IsNil(structp) {
+ return ErrNil
+ }
+
+ // Can the object marshal itself?
+ if p.isMarshaler {
+ m := structPointer_Interface(structp, p.stype).(Marshaler)
+ data, err := m.Marshal()
+ if err != nil && !state.shouldContinue(err, nil) {
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ return nil
+ }
+
+ o.buf = append(o.buf, p.tagcode...)
+ return o.enc_len_struct(p.sprop, structp, &state)
+}
+
+//TODO this is only copied, please fix this
+func size_ref_struct_message(p *Properties, base structPointer) int {
+ structp := structPointer_GetRefStructPointer(base, p.field)
+ if structPointer_IsNil(structp) {
+ return 0
+ }
+
+ // Can the object marshal itself?
+ if p.isMarshaler {
+ m := structPointer_Interface(structp, p.stype).(Marshaler)
+ data, _ := m.Marshal()
+ n0 := len(p.tagcode)
+ n1 := sizeRawBytes(data)
+ return n0 + n1
+ }
+
+ n0 := len(p.tagcode)
+ n1 := size_struct(p.sprop, structp)
+ n2 := sizeVarint(uint64(n1)) // size of encoded length
+ return n0 + n1 + n2
+}
+
+// Encode a slice of references to message struct pointers ([]struct).
+func (o *Buffer) enc_slice_ref_struct_message(p *Properties, base structPointer) error {
+ var state errorState
+ ss := structPointer_StructRefSlice(base, p.field, p.stype.Size())
+ l := ss.Len()
+ for i := 0; i < l; i++ {
+ structp := ss.Index(i)
+ if structPointer_IsNil(structp) {
+ return errRepeatedHasNil
+ }
+
+ // Can the object marshal itself?
+ if p.isMarshaler {
+ m := structPointer_Interface(structp, p.stype).(Marshaler)
+ data, err := m.Marshal()
+ if err != nil && !state.shouldContinue(err, nil) {
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ continue
+ }
+
+ o.buf = append(o.buf, p.tagcode...)
+ err := o.enc_len_struct(p.sprop, structp, &state)
+ if err != nil && !state.shouldContinue(err, nil) {
+ if err == ErrNil {
+ return errRepeatedHasNil
+ }
+ return err
+ }
+
+ }
+ return state.err
+}
+
+//TODO this is only copied, please fix this
+func size_slice_ref_struct_message(p *Properties, base structPointer) (n int) {
+ ss := structPointer_StructRefSlice(base, p.field, p.stype.Size())
+ l := ss.Len()
+ n += l * len(p.tagcode)
+ for i := 0; i < l; i++ {
+ structp := ss.Index(i)
+ if structPointer_IsNil(structp) {
+ return // return the size up to this point
+ }
+
+ // Can the object marshal itself?
+ if p.isMarshaler {
+ m := structPointer_Interface(structp, p.stype).(Marshaler)
+ data, _ := m.Marshal()
+ n += len(p.tagcode)
+ n += sizeRawBytes(data)
+ continue
+ }
+
+ n0 := size_struct(p.sprop, structp)
+ n1 := sizeVarint(uint64(n0)) // size of encoded length
+ n += n0 + n1
+ }
+ return
+}
+
+func (o *Buffer) enc_custom_bytes(p *Properties, base structPointer) error {
+ i := structPointer_InterfaceRef(base, p.field, p.ctype)
+ if i == nil {
+ return ErrNil
+ }
+ custom := i.(Marshaler)
+ data, err := custom.Marshal()
+ if err != nil {
+ return err
+ }
+ if data == nil {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ return nil
+}
+
+func size_custom_bytes(p *Properties, base structPointer) (n int) {
+ n += len(p.tagcode)
+ i := structPointer_InterfaceRef(base, p.field, p.ctype)
+ if i == nil {
+ return 0
+ }
+ custom := i.(Marshaler)
+ data, _ := custom.Marshal()
+ n += sizeRawBytes(data)
+ return
+}
+
+func (o *Buffer) enc_custom_ref_bytes(p *Properties, base structPointer) error {
+ custom := structPointer_InterfaceAt(base, p.field, p.ctype).(Marshaler)
+ data, err := custom.Marshal()
+ if err != nil {
+ return err
+ }
+ if data == nil {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ return nil
+}
+
+func size_custom_ref_bytes(p *Properties, base structPointer) (n int) {
+ n += len(p.tagcode)
+ i := structPointer_InterfaceAt(base, p.field, p.ctype)
+ if i == nil {
+ return 0
+ }
+ custom := i.(Marshaler)
+ data, _ := custom.Marshal()
+ n += sizeRawBytes(data)
+ return
+}
+
+func (o *Buffer) enc_custom_slice_bytes(p *Properties, base structPointer) error {
+ inter := structPointer_InterfaceRef(base, p.field, p.ctype)
+ if inter == nil {
+ return ErrNil
+ }
+ slice := reflect.ValueOf(inter)
+ l := slice.Len()
+ for i := 0; i < l; i++ {
+ v := slice.Index(i)
+ custom := v.Interface().(Marshaler)
+ data, err := custom.Marshal()
+ if err != nil {
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ }
+ return nil
+}
+
+func size_custom_slice_bytes(p *Properties, base structPointer) (n int) {
+ inter := structPointer_InterfaceRef(base, p.field, p.ctype)
+ if inter == nil {
+ return 0
+ }
+ slice := reflect.ValueOf(inter)
+ l := slice.Len()
+ n += l * len(p.tagcode)
+ for i := 0; i < l; i++ {
+ v := slice.Index(i)
+ custom := v.Interface().(Marshaler)
+ data, _ := custom.Marshal()
+ n += sizeRawBytes(data)
+ }
+ return
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2011 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Protocol buffer comparison.
+
+package proto
+
+import (
+ "bytes"
+ "log"
+ "reflect"
+ "strings"
+)
+
+/*
+Equal returns true iff protocol buffers a and b are equal.
+The arguments must both be pointers to protocol buffer structs.
+
+Equality is defined in this way:
+ - Two messages are equal iff they are the same type,
+ corresponding fields are equal, unknown field sets
+ are equal, and extensions sets are equal.
+ - Two set scalar fields are equal iff their values are equal.
+ If the fields are of a floating-point type, remember that
+ NaN != x for all x, including NaN. If the message is defined
+ in a proto3 .proto file, fields are not "set"; specifically,
+ zero length proto3 "bytes" fields are equal (nil == {}).
+ - Two repeated fields are equal iff their lengths are the same,
+ and their corresponding elements are equal. Note a "bytes" field,
+ although represented by []byte, is not a repeated field and the
+ rule for the scalar fields described above applies.
+ - Two unset fields are equal.
+ - Two unknown field sets are equal if their current
+ encoded state is equal.
+ - Two extension sets are equal iff they have corresponding
+ elements that are pairwise equal.
+ - Two map fields are equal iff their lengths are the same,
+ and they contain the same set of elements. Zero-length map
+ fields are equal.
+ - Every other combination of things are not equal.
+
+The return value is undefined if a and b are not protocol buffers.
+*/
+func Equal(a, b Message) bool {
+ if a == nil || b == nil {
+ return a == b
+ }
+ v1, v2 := reflect.ValueOf(a), reflect.ValueOf(b)
+ if v1.Type() != v2.Type() {
+ return false
+ }
+ if v1.Kind() == reflect.Ptr {
+ if v1.IsNil() {
+ return v2.IsNil()
+ }
+ if v2.IsNil() {
+ return false
+ }
+ v1, v2 = v1.Elem(), v2.Elem()
+ }
+ if v1.Kind() != reflect.Struct {
+ return false
+ }
+ return equalStruct(v1, v2)
+}
+
+// v1 and v2 are known to have the same type.
+func equalStruct(v1, v2 reflect.Value) bool {
+ sprop := GetProperties(v1.Type())
+ for i := 0; i < v1.NumField(); i++ {
+ f := v1.Type().Field(i)
+ if strings.HasPrefix(f.Name, "XXX_") {
+ continue
+ }
+ f1, f2 := v1.Field(i), v2.Field(i)
+ if f.Type.Kind() == reflect.Ptr {
+ if n1, n2 := f1.IsNil(), f2.IsNil(); n1 && n2 {
+ // both unset
+ continue
+ } else if n1 != n2 {
+ // set/unset mismatch
+ return false
+ }
+ b1, ok := f1.Interface().(raw)
+ if ok {
+ b2 := f2.Interface().(raw)
+ // RawMessage
+ if !bytes.Equal(b1.Bytes(), b2.Bytes()) {
+ return false
+ }
+ continue
+ }
+ f1, f2 = f1.Elem(), f2.Elem()
+ }
+ if !equalAny(f1, f2, sprop.Prop[i]) {
+ return false
+ }
+ }
+
+ if em1 := v1.FieldByName("XXX_InternalExtensions"); em1.IsValid() {
+ em2 := v2.FieldByName("XXX_InternalExtensions")
+ if !equalExtensions(v1.Type(), em1.Interface().(XXX_InternalExtensions), em2.Interface().(XXX_InternalExtensions)) {
+ return false
+ }
+ }
+
+ if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() {
+ em2 := v2.FieldByName("XXX_extensions")
+ if !equalExtMap(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) {
+ return false
+ }
+ }
+
+ uf := v1.FieldByName("XXX_unrecognized")
+ if !uf.IsValid() {
+ return true
+ }
+
+ u1 := uf.Bytes()
+ u2 := v2.FieldByName("XXX_unrecognized").Bytes()
+ if !bytes.Equal(u1, u2) {
+ return false
+ }
+
+ return true
+}
+
+// v1 and v2 are known to have the same type.
+// prop may be nil.
+func equalAny(v1, v2 reflect.Value, prop *Properties) bool {
+ if v1.Type() == protoMessageType {
+ m1, _ := v1.Interface().(Message)
+ m2, _ := v2.Interface().(Message)
+ return Equal(m1, m2)
+ }
+ switch v1.Kind() {
+ case reflect.Bool:
+ return v1.Bool() == v2.Bool()
+ case reflect.Float32, reflect.Float64:
+ return v1.Float() == v2.Float()
+ case reflect.Int32, reflect.Int64:
+ return v1.Int() == v2.Int()
+ case reflect.Interface:
+ // Probably a oneof field; compare the inner values.
+ n1, n2 := v1.IsNil(), v2.IsNil()
+ if n1 || n2 {
+ return n1 == n2
+ }
+ e1, e2 := v1.Elem(), v2.Elem()
+ if e1.Type() != e2.Type() {
+ return false
+ }
+ return equalAny(e1, e2, nil)
+ case reflect.Map:
+ if v1.Len() != v2.Len() {
+ return false
+ }
+ for _, key := range v1.MapKeys() {
+ val2 := v2.MapIndex(key)
+ if !val2.IsValid() {
+ // This key was not found in the second map.
+ return false
+ }
+ if !equalAny(v1.MapIndex(key), val2, nil) {
+ return false
+ }
+ }
+ return true
+ case reflect.Ptr:
+ // Maps may have nil values in them, so check for nil.
+ if v1.IsNil() && v2.IsNil() {
+ return true
+ }
+ if v1.IsNil() != v2.IsNil() {
+ return false
+ }
+ return equalAny(v1.Elem(), v2.Elem(), prop)
+ case reflect.Slice:
+ if v1.Type().Elem().Kind() == reflect.Uint8 {
+ // short circuit: []byte
+
+ // Edge case: if this is in a proto3 message, a zero length
+ // bytes field is considered the zero value.
+ if prop != nil && prop.proto3 && v1.Len() == 0 && v2.Len() == 0 {
+ return true
+ }
+ if v1.IsNil() != v2.IsNil() {
+ return false
+ }
+ return bytes.Equal(v1.Interface().([]byte), v2.Interface().([]byte))
+ }
+
+ if v1.Len() != v2.Len() {
+ return false
+ }
+ for i := 0; i < v1.Len(); i++ {
+ if !equalAny(v1.Index(i), v2.Index(i), prop) {
+ return false
+ }
+ }
+ return true
+ case reflect.String:
+ return v1.Interface().(string) == v2.Interface().(string)
+ case reflect.Struct:
+ return equalStruct(v1, v2)
+ case reflect.Uint32, reflect.Uint64:
+ return v1.Uint() == v2.Uint()
+ }
+
+ // unknown type, so not a protocol buffer
+ log.Printf("proto: don't know how to compare %v", v1)
+ return false
+}
+
+// base is the struct type that the extensions are based on.
+// x1 and x2 are InternalExtensions.
+func equalExtensions(base reflect.Type, x1, x2 XXX_InternalExtensions) bool {
+ em1, _ := x1.extensionsRead()
+ em2, _ := x2.extensionsRead()
+ return equalExtMap(base, em1, em2)
+}
+
+func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
+ if len(em1) != len(em2) {
+ return false
+ }
+
+ for extNum, e1 := range em1 {
+ e2, ok := em2[extNum]
+ if !ok {
+ return false
+ }
+
+ m1, m2 := e1.value, e2.value
+
+ if m1 != nil && m2 != nil {
+ // Both are unencoded.
+ if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
+ return false
+ }
+ continue
+ }
+
+ // At least one is encoded. To do a semantically correct comparison
+ // we need to unmarshal them first.
+ var desc *ExtensionDesc
+ if m := extensionMaps[base]; m != nil {
+ desc = m[extNum]
+ }
+ if desc == nil {
+ log.Printf("proto: don't know how to compare extension %d of %v", extNum, base)
+ continue
+ }
+ var err error
+ if m1 == nil {
+ m1, err = decodeExtension(e1.enc, desc)
+ }
+ if m2 == nil && err == nil {
+ m2, err = decodeExtension(e2.enc, desc)
+ }
+ if err != nil {
+ // The encoded form is invalid.
+ log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err)
+ return false
+ }
+ if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
+ return false
+ }
+ }
+
+ return true
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+/*
+ * Types and routines for supporting protocol buffer extensions.
+ */
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+ "strconv"
+ "sync"
+)
+
+// ErrMissingExtension is the error returned by GetExtension if the named extension is not in the message.
+var ErrMissingExtension = errors.New("proto: missing extension")
+
+// ExtensionRange represents a range of message extensions for a protocol buffer.
+// Used in code generated by the protocol compiler.
+type ExtensionRange struct {
+ Start, End int32 // both inclusive
+}
+
+// extendableProto is an interface implemented by any protocol buffer generated by the current
+// proto compiler that may be extended.
+type extendableProto interface {
+ Message
+ ExtensionRangeArray() []ExtensionRange
+ extensionsWrite() map[int32]Extension
+ extensionsRead() (map[int32]Extension, sync.Locker)
+}
+
+// extendableProtoV1 is an interface implemented by a protocol buffer generated by the previous
+// version of the proto compiler that may be extended.
+type extendableProtoV1 interface {
+ Message
+ ExtensionRangeArray() []ExtensionRange
+ ExtensionMap() map[int32]Extension
+}
+
+type extensionsBytes interface {
+ Message
+ ExtensionRangeArray() []ExtensionRange
+ GetExtensions() *[]byte
+}
+
+// extensionAdapter is a wrapper around extendableProtoV1 that implements extendableProto.
+type extensionAdapter struct {
+ extendableProtoV1
+}
+
+func (e extensionAdapter) extensionsWrite() map[int32]Extension {
+ return e.ExtensionMap()
+}
+
+func (e extensionAdapter) extensionsRead() (map[int32]Extension, sync.Locker) {
+ return e.ExtensionMap(), notLocker{}
+}
+
+// notLocker is a sync.Locker whose Lock and Unlock methods are nops.
+type notLocker struct{}
+
+func (n notLocker) Lock() {}
+func (n notLocker) Unlock() {}
+
+// extendable returns the extendableProto interface for the given generated proto message.
+// If the proto message has the old extension format, it returns a wrapper that implements
+// the extendableProto interface.
+func extendable(p interface{}) (extendableProto, bool) {
+ if ep, ok := p.(extendableProto); ok {
+ return ep, ok
+ }
+ if ep, ok := p.(extendableProtoV1); ok {
+ return extensionAdapter{ep}, ok
+ }
+ return nil, false
+}
+
+// XXX_InternalExtensions is an internal representation of proto extensions.
+//
+// Each generated message struct type embeds an anonymous XXX_InternalExtensions field,
+// thus gaining the unexported 'extensions' method, which can be called only from the proto package.
+//
+// The methods of XXX_InternalExtensions are not concurrency safe in general,
+// but calls to logically read-only methods such as has and get may be executed concurrently.
+type XXX_InternalExtensions struct {
+ // The struct must be indirect so that if a user inadvertently copies a
+ // generated message and its embedded XXX_InternalExtensions, they
+ // avoid the mayhem of a copied mutex.
+ //
+ // The mutex serializes all logically read-only operations to p.extensionMap.
+ // It is up to the client to ensure that write operations to p.extensionMap are
+ // mutually exclusive with other accesses.
+ p *struct {
+ mu sync.Mutex
+ extensionMap map[int32]Extension
+ }
+}
+
+// extensionsWrite returns the extension map, creating it on first use.
+func (e *XXX_InternalExtensions) extensionsWrite() map[int32]Extension {
+ if e.p == nil {
+ e.p = new(struct {
+ mu sync.Mutex
+ extensionMap map[int32]Extension
+ })
+ e.p.extensionMap = make(map[int32]Extension)
+ }
+ return e.p.extensionMap
+}
+
+// extensionsRead returns the extensions map for read-only use. It may be nil.
+// The caller must hold the returned mutex's lock when accessing Elements within the map.
+func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Locker) {
+ if e.p == nil {
+ return nil, nil
+ }
+ return e.p.extensionMap, &e.p.mu
+}
+
+type extensionRange interface {
+ Message
+ ExtensionRangeArray() []ExtensionRange
+}
+
+var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem()
+var extendableProtoV1Type = reflect.TypeOf((*extendableProtoV1)(nil)).Elem()
+var extendableBytesType = reflect.TypeOf((*extensionsBytes)(nil)).Elem()
+var extensionRangeType = reflect.TypeOf((*extensionRange)(nil)).Elem()
+
+// ExtensionDesc represents an extension specification.
+// Used in generated code from the protocol compiler.
+type ExtensionDesc struct {
+ ExtendedType Message // nil pointer to the type that is being extended
+ ExtensionType interface{} // nil pointer to the extension type
+ Field int32 // field number
+ Name string // fully-qualified name of extension, for text formatting
+ Tag string // protobuf tag style
+ Filename string // name of the file in which the extension is defined
+}
+
+func (ed *ExtensionDesc) repeated() bool {
+ t := reflect.TypeOf(ed.ExtensionType)
+ return t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8
+}
+
+// Extension represents an extension in a message.
+type Extension struct {
+ // When an extension is stored in a message using SetExtension
+ // only desc and value are set. When the message is marshaled
+ // enc will be set to the encoded form of the message.
+ //
+ // When a message is unmarshaled and contains extensions, each
+ // extension will have only enc set. When such an extension is
+ // accessed using GetExtension (or GetExtensions) desc and value
+ // will be set.
+ desc *ExtensionDesc
+ value interface{}
+ enc []byte
+}
+
+// SetRawExtension is for testing only.
+func SetRawExtension(base Message, id int32, b []byte) {
+ if ebase, ok := base.(extensionsBytes); ok {
+ clearExtension(base, id)
+ ext := ebase.GetExtensions()
+ *ext = append(*ext, b...)
+ return
+ }
+ epb, ok := extendable(base)
+ if !ok {
+ return
+ }
+ extmap := epb.extensionsWrite()
+ extmap[id] = Extension{enc: b}
+}
+
+// isExtensionField returns true iff the given field number is in an extension range.
+func isExtensionField(pb extensionRange, field int32) bool {
+ for _, er := range pb.ExtensionRangeArray() {
+ if er.Start <= field && field <= er.End {
+ return true
+ }
+ }
+ return false
+}
+
+// checkExtensionTypes checks that the given extension is valid for pb.
+func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error {
+ var pbi interface{} = pb
+ // Check the extended type.
+ if ea, ok := pbi.(extensionAdapter); ok {
+ pbi = ea.extendableProtoV1
+ }
+ if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b {
+ return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String())
+ }
+ // Check the range.
+ if !isExtensionField(pb, extension.Field) {
+ return errors.New("proto: bad extension number; not in declared ranges")
+ }
+ return nil
+}
+
+// extPropKey is sufficient to uniquely identify an extension.
+type extPropKey struct {
+ base reflect.Type
+ field int32
+}
+
+var extProp = struct {
+ sync.RWMutex
+ m map[extPropKey]*Properties
+}{
+ m: make(map[extPropKey]*Properties),
+}
+
+func extensionProperties(ed *ExtensionDesc) *Properties {
+ key := extPropKey{base: reflect.TypeOf(ed.ExtendedType), field: ed.Field}
+
+ extProp.RLock()
+ if prop, ok := extProp.m[key]; ok {
+ extProp.RUnlock()
+ return prop
+ }
+ extProp.RUnlock()
+
+ extProp.Lock()
+ defer extProp.Unlock()
+ // Check again.
+ if prop, ok := extProp.m[key]; ok {
+ return prop
+ }
+
+ prop := new(Properties)
+ prop.Init(reflect.TypeOf(ed.ExtensionType), "unknown_name", ed.Tag, nil)
+ extProp.m[key] = prop
+ return prop
+}
+
+// encode encodes any unmarshaled (unencoded) extensions in e.
+func encodeExtensions(e *XXX_InternalExtensions) error {
+ m, mu := e.extensionsRead()
+ if m == nil {
+ return nil // fast path
+ }
+ mu.Lock()
+ defer mu.Unlock()
+ return encodeExtensionsMap(m)
+}
+
+// encode encodes any unmarshaled (unencoded) extensions in e.
+func encodeExtensionsMap(m map[int32]Extension) error {
+ for k, e := range m {
+ if e.value == nil || e.desc == nil {
+ // Extension is only in its encoded form.
+ continue
+ }
+
+ // We don't skip extensions that have an encoded form set,
+ // because the extension value may have been mutated after
+ // the last time this function was called.
+
+ et := reflect.TypeOf(e.desc.ExtensionType)
+ props := extensionProperties(e.desc)
+
+ p := NewBuffer(nil)
+ // If e.value has type T, the encoder expects a *struct{ X T }.
+ // Pass a *T with a zero field and hope it all works out.
+ x := reflect.New(et)
+ x.Elem().Set(reflect.ValueOf(e.value))
+ if err := props.enc(p, props, toStructPointer(x)); err != nil {
+ return err
+ }
+ e.enc = p.buf
+ m[k] = e
+ }
+ return nil
+}
+
+func extensionsSize(e *XXX_InternalExtensions) (n int) {
+ m, mu := e.extensionsRead()
+ if m == nil {
+ return 0
+ }
+ mu.Lock()
+ defer mu.Unlock()
+ return extensionsMapSize(m)
+}
+
+func extensionsMapSize(m map[int32]Extension) (n int) {
+ for _, e := range m {
+ if e.value == nil || e.desc == nil {
+ // Extension is only in its encoded form.
+ n += len(e.enc)
+ continue
+ }
+
+ // We don't skip extensions that have an encoded form set,
+ // because the extension value may have been mutated after
+ // the last time this function was called.
+
+ et := reflect.TypeOf(e.desc.ExtensionType)
+ props := extensionProperties(e.desc)
+
+ // If e.value has type T, the encoder expects a *struct{ X T }.
+ // Pass a *T with a zero field and hope it all works out.
+ x := reflect.New(et)
+ x.Elem().Set(reflect.ValueOf(e.value))
+ n += props.size(props, toStructPointer(x))
+ }
+ return
+}
+
+// HasExtension returns whether the given extension is present in pb.
+func HasExtension(pb Message, extension *ExtensionDesc) bool {
+ if epb, doki := pb.(extensionsBytes); doki {
+ ext := epb.GetExtensions()
+ buf := *ext
+ o := 0
+ for o < len(buf) {
+ tag, n := DecodeVarint(buf[o:])
+ fieldNum := int32(tag >> 3)
+ if int32(fieldNum) == extension.Field {
+ return true
+ }
+ wireType := int(tag & 0x7)
+ o += n
+ l, err := size(buf[o:], wireType)
+ if err != nil {
+ return false
+ }
+ o += l
+ }
+ return false
+ }
+ // TODO: Check types, field numbers, etc.?
+ epb, ok := extendable(pb)
+ if !ok {
+ return false
+ }
+ extmap, mu := epb.extensionsRead()
+ if extmap == nil {
+ return false
+ }
+ mu.Lock()
+ _, ok = extmap[extension.Field]
+ mu.Unlock()
+ return ok
+}
+
+func deleteExtension(pb extensionsBytes, theFieldNum int32, offset int) int {
+ ext := pb.GetExtensions()
+ for offset < len(*ext) {
+ tag, n1 := DecodeVarint((*ext)[offset:])
+ fieldNum := int32(tag >> 3)
+ wireType := int(tag & 0x7)
+ n2, err := size((*ext)[offset+n1:], wireType)
+ if err != nil {
+ panic(err)
+ }
+ newOffset := offset + n1 + n2
+ if fieldNum == theFieldNum {
+ *ext = append((*ext)[:offset], (*ext)[newOffset:]...)
+ return offset
+ }
+ offset = newOffset
+ }
+ return -1
+}
+
+// ClearExtension removes the given extension from pb.
+func ClearExtension(pb Message, extension *ExtensionDesc) {
+ clearExtension(pb, extension.Field)
+}
+
+func clearExtension(pb Message, fieldNum int32) {
+ if epb, doki := pb.(extensionsBytes); doki {
+ offset := 0
+ for offset != -1 {
+ offset = deleteExtension(epb, fieldNum, offset)
+ }
+ return
+ }
+ epb, ok := extendable(pb)
+ if !ok {
+ return
+ }
+ // TODO: Check types, field numbers, etc.?
+ extmap := epb.extensionsWrite()
+ delete(extmap, fieldNum)
+}
+
+// GetExtension parses and returns the given extension of pb.
+// If the extension is not present and has no default value it returns ErrMissingExtension.
+func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
+ if epb, doki := pb.(extensionsBytes); doki {
+ ext := epb.GetExtensions()
+ o := 0
+ for o < len(*ext) {
+ tag, n := DecodeVarint((*ext)[o:])
+ fieldNum := int32(tag >> 3)
+ wireType := int(tag & 0x7)
+ l, err := size((*ext)[o+n:], wireType)
+ if err != nil {
+ return nil, err
+ }
+ if int32(fieldNum) == extension.Field {
+ v, err := decodeExtension((*ext)[o:o+n+l], extension)
+ if err != nil {
+ return nil, err
+ }
+ return v, nil
+ }
+ o += n + l
+ }
+ return defaultExtensionValue(extension)
+ }
+ epb, ok := extendable(pb)
+ if !ok {
+ return nil, errors.New("proto: not an extendable proto")
+ }
+ if err := checkExtensionTypes(epb, extension); err != nil {
+ return nil, err
+ }
+
+ emap, mu := epb.extensionsRead()
+ if emap == nil {
+ return defaultExtensionValue(extension)
+ }
+ mu.Lock()
+ defer mu.Unlock()
+ e, ok := emap[extension.Field]
+ if !ok {
+ // defaultExtensionValue returns the default value or
+ // ErrMissingExtension if there is no default.
+ return defaultExtensionValue(extension)
+ }
+
+ if e.value != nil {
+ // Already decoded. Check the descriptor, though.
+ if e.desc != extension {
+ // This shouldn't happen. If it does, it means that
+ // GetExtension was called twice with two different
+ // descriptors with the same field number.
+ return nil, errors.New("proto: descriptor conflict")
+ }
+ return e.value, nil
+ }
+
+ v, err := decodeExtension(e.enc, extension)
+ if err != nil {
+ return nil, err
+ }
+
+ // Remember the decoded version and drop the encoded version.
+ // That way it is safe to mutate what we return.
+ e.value = v
+ e.desc = extension
+ e.enc = nil
+ emap[extension.Field] = e
+ return e.value, nil
+}
+
+// defaultExtensionValue returns the default value for extension.
+// If no default for an extension is defined ErrMissingExtension is returned.
+func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
+ t := reflect.TypeOf(extension.ExtensionType)
+ props := extensionProperties(extension)
+
+ sf, _, err := fieldDefault(t, props)
+ if err != nil {
+ return nil, err
+ }
+
+ if sf == nil || sf.value == nil {
+ // There is no default value.
+ return nil, ErrMissingExtension
+ }
+
+ if t.Kind() != reflect.Ptr {
+ // We do not need to return a Ptr, we can directly return sf.value.
+ return sf.value, nil
+ }
+
+ // We need to return an interface{} that is a pointer to sf.value.
+ value := reflect.New(t).Elem()
+ value.Set(reflect.New(value.Type().Elem()))
+ if sf.kind == reflect.Int32 {
+ // We may have an int32 or an enum, but the underlying data is int32.
+ // Since we can't set an int32 into a non int32 reflect.value directly
+ // set it as a int32.
+ value.Elem().SetInt(int64(sf.value.(int32)))
+ } else {
+ value.Elem().Set(reflect.ValueOf(sf.value))
+ }
+ return value.Interface(), nil
+}
+
+// decodeExtension decodes an extension encoded in b.
+func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
+ o := NewBuffer(b)
+
+ t := reflect.TypeOf(extension.ExtensionType)
+
+ props := extensionProperties(extension)
+
+ // t is a pointer to a struct, pointer to basic type or a slice.
+ // Allocate a "field" to store the pointer/slice itself; the
+ // pointer/slice will be stored here. We pass
+ // the address of this field to props.dec.
+ // This passes a zero field and a *t and lets props.dec
+ // interpret it as a *struct{ x t }.
+ value := reflect.New(t).Elem()
+
+ for {
+ // Discard wire type and field number varint. It isn't needed.
+ if _, err := o.DecodeVarint(); err != nil {
+ return nil, err
+ }
+
+ if err := props.dec(o, props, toStructPointer(value.Addr())); err != nil {
+ return nil, err
+ }
+
+ if o.index >= len(o.buf) {
+ break
+ }
+ }
+ return value.Interface(), nil
+}
+
+// GetExtensions returns a slice of the extensions present in pb that are also listed in es.
+// The returned slice has the same length as es; missing extensions will appear as nil elements.
+func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) {
+ extensions = make([]interface{}, len(es))
+ for i, e := range es {
+ extensions[i], err = GetExtension(pb, e)
+ if err == ErrMissingExtension {
+ err = nil
+ }
+ if err != nil {
+ return
+ }
+ }
+ return
+}
+
+// ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order.
+// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing
+// just the Field field, which defines the extension's field number.
+func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
+ epb, ok := extendable(pb)
+ if !ok {
+ return nil, fmt.Errorf("proto: %T is not an extendable proto.Message", pb)
+ }
+ registeredExtensions := RegisteredExtensions(pb)
+
+ emap, mu := epb.extensionsRead()
+ if emap == nil {
+ return nil, nil
+ }
+ mu.Lock()
+ defer mu.Unlock()
+ extensions := make([]*ExtensionDesc, 0, len(emap))
+ for extid, e := range emap {
+ desc := e.desc
+ if desc == nil {
+ desc = registeredExtensions[extid]
+ if desc == nil {
+ desc = &ExtensionDesc{Field: extid}
+ }
+ }
+
+ extensions = append(extensions, desc)
+ }
+ return extensions, nil
+}
+
+// SetExtension sets the specified extension of pb to the specified value.
+func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error {
+ if epb, doki := pb.(extensionsBytes); doki {
+ ClearExtension(pb, extension)
+ ext := epb.GetExtensions()
+ et := reflect.TypeOf(extension.ExtensionType)
+ props := extensionProperties(extension)
+ p := NewBuffer(nil)
+ x := reflect.New(et)
+ x.Elem().Set(reflect.ValueOf(value))
+ if err := props.enc(p, props, toStructPointer(x)); err != nil {
+ return err
+ }
+ *ext = append(*ext, p.buf...)
+ return nil
+ }
+ epb, ok := extendable(pb)
+ if !ok {
+ return errors.New("proto: not an extendable proto")
+ }
+ if err := checkExtensionTypes(epb, extension); err != nil {
+ return err
+ }
+ typ := reflect.TypeOf(extension.ExtensionType)
+ if typ != reflect.TypeOf(value) {
+ return errors.New("proto: bad extension value type")
+ }
+ // nil extension values need to be caught early, because the
+ // encoder can't distinguish an ErrNil due to a nil extension
+ // from an ErrNil due to a missing field. Extensions are
+ // always optional, so the encoder would just swallow the error
+ // and drop all the extensions from the encoded message.
+ if reflect.ValueOf(value).IsNil() {
+ return fmt.Errorf("proto: SetExtension called with nil value of type %T", value)
+ }
+
+ extmap := epb.extensionsWrite()
+ extmap[extension.Field] = Extension{desc: extension, value: value}
+ return nil
+}
+
+// ClearAllExtensions clears all extensions from pb.
+func ClearAllExtensions(pb Message) {
+ if epb, doki := pb.(extensionsBytes); doki {
+ ext := epb.GetExtensions()
+ *ext = []byte{}
+ return
+ }
+ epb, ok := extendable(pb)
+ if !ok {
+ return
+ }
+ m := epb.extensionsWrite()
+ for k := range m {
+ delete(m, k)
+ }
+}
+
+// A global registry of extensions.
+// The generated code will register the generated descriptors by calling RegisterExtension.
+
+var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc)
+
+// RegisterExtension is called from the generated code.
+func RegisterExtension(desc *ExtensionDesc) {
+ st := reflect.TypeOf(desc.ExtendedType).Elem()
+ m := extensionMaps[st]
+ if m == nil {
+ m = make(map[int32]*ExtensionDesc)
+ extensionMaps[st] = m
+ }
+ if _, ok := m[desc.Field]; ok {
+ panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field)))
+ }
+ m[desc.Field] = desc
+}
+
+// RegisteredExtensions returns a map of the registered extensions of a
+// protocol buffer struct, indexed by the extension number.
+// The argument pb should be a nil pointer to the struct type.
+func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {
+ return extensionMaps[reflect.TypeOf(pb).Elem()]
+}
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "reflect"
+ "sort"
+ "strings"
+ "sync"
+)
+
+func GetBoolExtension(pb Message, extension *ExtensionDesc, ifnotset bool) bool {
+ if reflect.ValueOf(pb).IsNil() {
+ return ifnotset
+ }
+ value, err := GetExtension(pb, extension)
+ if err != nil {
+ return ifnotset
+ }
+ if value == nil {
+ return ifnotset
+ }
+ if value.(*bool) == nil {
+ return ifnotset
+ }
+ return *(value.(*bool))
+}
+
+func (this *Extension) Equal(that *Extension) bool {
+ return bytes.Equal(this.enc, that.enc)
+}
+
+func (this *Extension) Compare(that *Extension) int {
+ return bytes.Compare(this.enc, that.enc)
+}
+
+func SizeOfInternalExtension(m extendableProto) (n int) {
+ return SizeOfExtensionMap(m.extensionsWrite())
+}
+
+func SizeOfExtensionMap(m map[int32]Extension) (n int) {
+ return extensionsMapSize(m)
+}
+
+type sortableMapElem struct {
+ field int32
+ ext Extension
+}
+
+func newSortableExtensionsFromMap(m map[int32]Extension) sortableExtensions {
+ s := make(sortableExtensions, 0, len(m))
+ for k, v := range m {
+ s = append(s, &sortableMapElem{field: k, ext: v})
+ }
+ return s
+}
+
+type sortableExtensions []*sortableMapElem
+
+func (this sortableExtensions) Len() int { return len(this) }
+
+func (this sortableExtensions) Swap(i, j int) { this[i], this[j] = this[j], this[i] }
+
+func (this sortableExtensions) Less(i, j int) bool { return this[i].field < this[j].field }
+
+func (this sortableExtensions) String() string {
+ sort.Sort(this)
+ ss := make([]string, len(this))
+ for i := range this {
+ ss[i] = fmt.Sprintf("%d: %v", this[i].field, this[i].ext)
+ }
+ return "map[" + strings.Join(ss, ",") + "]"
+}
+
+func StringFromInternalExtension(m extendableProto) string {
+ return StringFromExtensionsMap(m.extensionsWrite())
+}
+
+func StringFromExtensionsMap(m map[int32]Extension) string {
+ return newSortableExtensionsFromMap(m).String()
+}
+
+func StringFromExtensionsBytes(ext []byte) string {
+ m, err := BytesToExtensionsMap(ext)
+ if err != nil {
+ panic(err)
+ }
+ return StringFromExtensionsMap(m)
+}
+
+func EncodeInternalExtension(m extendableProto, data []byte) (n int, err error) {
+ return EncodeExtensionMap(m.extensionsWrite(), data)
+}
+
+func EncodeExtensionMap(m map[int32]Extension, data []byte) (n int, err error) {
+ if err := encodeExtensionsMap(m); err != nil {
+ return 0, err
+ }
+ keys := make([]int, 0, len(m))
+ for k := range m {
+ keys = append(keys, int(k))
+ }
+ sort.Ints(keys)
+ for _, k := range keys {
+ n += copy(data[n:], m[int32(k)].enc)
+ }
+ return n, nil
+}
+
+func GetRawExtension(m map[int32]Extension, id int32) ([]byte, error) {
+ if m[id].value == nil || m[id].desc == nil {
+ return m[id].enc, nil
+ }
+ if err := encodeExtensionsMap(m); err != nil {
+ return nil, err
+ }
+ return m[id].enc, nil
+}
+
+func size(buf []byte, wire int) (int, error) {
+ switch wire {
+ case WireVarint:
+ _, n := DecodeVarint(buf)
+ return n, nil
+ case WireFixed64:
+ return 8, nil
+ case WireBytes:
+ v, n := DecodeVarint(buf)
+ return int(v) + n, nil
+ case WireFixed32:
+ return 4, nil
+ case WireStartGroup:
+ offset := 0
+ for {
+ u, n := DecodeVarint(buf[offset:])
+ fwire := int(u & 0x7)
+ offset += n
+ if fwire == WireEndGroup {
+ return offset, nil
+ }
+ s, err := size(buf[offset:], wire)
+ if err != nil {
+ return 0, err
+ }
+ offset += s
+ }
+ }
+ return 0, fmt.Errorf("proto: can't get size for unknown wire type %d", wire)
+}
+
+func BytesToExtensionsMap(buf []byte) (map[int32]Extension, error) {
+ m := make(map[int32]Extension)
+ i := 0
+ for i < len(buf) {
+ tag, n := DecodeVarint(buf[i:])
+ if n <= 0 {
+ return nil, fmt.Errorf("unable to decode varint")
+ }
+ fieldNum := int32(tag >> 3)
+ wireType := int(tag & 0x7)
+ l, err := size(buf[i+n:], wireType)
+ if err != nil {
+ return nil, err
+ }
+ end := i + int(l) + n
+ m[int32(fieldNum)] = Extension{enc: buf[i:end]}
+ i = end
+ }
+ return m, nil
+}
+
+func NewExtension(e []byte) Extension {
+ ee := Extension{enc: make([]byte, len(e))}
+ copy(ee.enc, e)
+ return ee
+}
+
+func AppendExtension(e Message, tag int32, buf []byte) {
+ if ee, eok := e.(extensionsBytes); eok {
+ ext := ee.GetExtensions()
+ *ext = append(*ext, buf...)
+ return
+ }
+ if ee, eok := e.(extendableProto); eok {
+ m := ee.extensionsWrite()
+ ext := m[int32(tag)] // may be missing
+ ext.enc = append(ext.enc, buf...)
+ m[int32(tag)] = ext
+ }
+}
+
+func encodeExtension(e *Extension) error {
+ if e.value == nil || e.desc == nil {
+ // Extension is only in its encoded form.
+ return nil
+ }
+ // We don't skip extensions that have an encoded form set,
+ // because the extension value may have been mutated after
+ // the last time this function was called.
+
+ et := reflect.TypeOf(e.desc.ExtensionType)
+ props := extensionProperties(e.desc)
+
+ p := NewBuffer(nil)
+ // If e.value has type T, the encoder expects a *struct{ X T }.
+ // Pass a *T with a zero field and hope it all works out.
+ x := reflect.New(et)
+ x.Elem().Set(reflect.ValueOf(e.value))
+ if err := props.enc(p, props, toStructPointer(x)); err != nil {
+ return err
+ }
+ e.enc = p.buf
+ return nil
+}
+
+func (this Extension) GoString() string {
+ if this.enc == nil {
+ if err := encodeExtension(&this); err != nil {
+ panic(err)
+ }
+ }
+ return fmt.Sprintf("proto.NewExtension(%#v)", this.enc)
+}
+
+func SetUnsafeExtension(pb Message, fieldNum int32, value interface{}) error {
+ typ := reflect.TypeOf(pb).Elem()
+ ext, ok := extensionMaps[typ]
+ if !ok {
+ return fmt.Errorf("proto: bad extended type; %s is not extendable", typ.String())
+ }
+ desc, ok := ext[fieldNum]
+ if !ok {
+ return errors.New("proto: bad extension number; not in declared ranges")
+ }
+ return SetExtension(pb, desc, value)
+}
+
+func GetUnsafeExtension(pb Message, fieldNum int32) (interface{}, error) {
+ typ := reflect.TypeOf(pb).Elem()
+ ext, ok := extensionMaps[typ]
+ if !ok {
+ return nil, fmt.Errorf("proto: bad extended type; %s is not extendable", typ.String())
+ }
+ desc, ok := ext[fieldNum]
+ if !ok {
+ return nil, fmt.Errorf("unregistered field number %d", fieldNum)
+ }
+ return GetExtension(pb, desc)
+}
+
+func NewUnsafeXXX_InternalExtensions(m map[int32]Extension) XXX_InternalExtensions {
+ x := &XXX_InternalExtensions{
+ p: new(struct {
+ mu sync.Mutex
+ extensionMap map[int32]Extension
+ }),
+ }
+ x.p.extensionMap = m
+ return *x
+}
+
+func GetUnsafeExtensionsMap(extendable Message) map[int32]Extension {
+ pb := extendable.(extendableProto)
+ return pb.extensionsWrite()
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/*
+Package proto converts data structures to and from the wire format of
+protocol buffers. It works in concert with the Go source code generated
+for .proto files by the protocol compiler.
+
+A summary of the properties of the protocol buffer interface
+for a protocol buffer variable v:
+
+ - Names are turned from camel_case to CamelCase for export.
+ - There are no methods on v to set fields; just treat
+ them as structure fields.
+ - There are getters that return a field's value if set,
+ and return the field's default value if unset.
+ The getters work even if the receiver is a nil message.
+ - The zero value for a struct is its correct initialization state.
+ All desired fields must be set before marshaling.
+ - A Reset() method will restore a protobuf struct to its zero state.
+ - Non-repeated fields are pointers to the values; nil means unset.
+ That is, optional or required field int32 f becomes F *int32.
+ - Repeated fields are slices.
+ - Helper functions are available to aid the setting of fields.
+ msg.Foo = proto.String("hello") // set field
+ - Constants are defined to hold the default values of all fields that
+ have them. They have the form Default_StructName_FieldName.
+ Because the getter methods handle defaulted values,
+ direct use of these constants should be rare.
+ - Enums are given type names and maps from names to values.
+ Enum values are prefixed by the enclosing message's name, or by the
+ enum's type name if it is a top-level enum. Enum types have a String
+ method, and a Enum method to assist in message construction.
+ - Nested messages, groups and enums have type names prefixed with the name of
+ the surrounding message type.
+ - Extensions are given descriptor names that start with E_,
+ followed by an underscore-delimited list of the nested messages
+ that contain it (if any) followed by the CamelCased name of the
+ extension field itself. HasExtension, ClearExtension, GetExtension
+ and SetExtension are functions for manipulating extensions.
+ - Oneof field sets are given a single field in their message,
+ with distinguished wrapper types for each possible field value.
+ - Marshal and Unmarshal are functions to encode and decode the wire format.
+
+When the .proto file specifies `syntax="proto3"`, there are some differences:
+
+ - Non-repeated fields of non-message type are values instead of pointers.
+ - Getters are only generated for message and oneof fields.
+ - Enum types do not get an Enum method.
+
+The simplest way to describe this is to see an example.
+Given file test.proto, containing
+
+ package example;
+
+ enum FOO { X = 17; }
+
+ message Test {
+ required string label = 1;
+ optional int32 type = 2 [default=77];
+ repeated int64 reps = 3;
+ optional group OptionalGroup = 4 {
+ required string RequiredField = 5;
+ }
+ oneof union {
+ int32 number = 6;
+ string name = 7;
+ }
+ }
+
+The resulting file, test.pb.go, is:
+
+ package example
+
+ import proto "github.com/gogo/protobuf/proto"
+ import math "math"
+
+ type FOO int32
+ const (
+ FOO_X FOO = 17
+ )
+ var FOO_name = map[int32]string{
+ 17: "X",
+ }
+ var FOO_value = map[string]int32{
+ "X": 17,
+ }
+
+ func (x FOO) Enum() *FOO {
+ p := new(FOO)
+ *p = x
+ return p
+ }
+ func (x FOO) String() string {
+ return proto.EnumName(FOO_name, int32(x))
+ }
+ func (x *FOO) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FOO_value, data)
+ if err != nil {
+ return err
+ }
+ *x = FOO(value)
+ return nil
+ }
+
+ type Test struct {
+ Label *string `protobuf:"bytes,1,req,name=label" json:"label,omitempty"`
+ Type *int32 `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"`
+ Reps []int64 `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"`
+ Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"`
+ // Types that are valid to be assigned to Union:
+ // *Test_Number
+ // *Test_Name
+ Union isTest_Union `protobuf_oneof:"union"`
+ XXX_unrecognized []byte `json:"-"`
+ }
+ func (m *Test) Reset() { *m = Test{} }
+ func (m *Test) String() string { return proto.CompactTextString(m) }
+ func (*Test) ProtoMessage() {}
+
+ type isTest_Union interface {
+ isTest_Union()
+ }
+
+ type Test_Number struct {
+ Number int32 `protobuf:"varint,6,opt,name=number"`
+ }
+ type Test_Name struct {
+ Name string `protobuf:"bytes,7,opt,name=name"`
+ }
+
+ func (*Test_Number) isTest_Union() {}
+ func (*Test_Name) isTest_Union() {}
+
+ func (m *Test) GetUnion() isTest_Union {
+ if m != nil {
+ return m.Union
+ }
+ return nil
+ }
+ const Default_Test_Type int32 = 77
+
+ func (m *Test) GetLabel() string {
+ if m != nil && m.Label != nil {
+ return *m.Label
+ }
+ return ""
+ }
+
+ func (m *Test) GetType() int32 {
+ if m != nil && m.Type != nil {
+ return *m.Type
+ }
+ return Default_Test_Type
+ }
+
+ func (m *Test) GetOptionalgroup() *Test_OptionalGroup {
+ if m != nil {
+ return m.Optionalgroup
+ }
+ return nil
+ }
+
+ type Test_OptionalGroup struct {
+ RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"`
+ }
+ func (m *Test_OptionalGroup) Reset() { *m = Test_OptionalGroup{} }
+ func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) }
+
+ func (m *Test_OptionalGroup) GetRequiredField() string {
+ if m != nil && m.RequiredField != nil {
+ return *m.RequiredField
+ }
+ return ""
+ }
+
+ func (m *Test) GetNumber() int32 {
+ if x, ok := m.GetUnion().(*Test_Number); ok {
+ return x.Number
+ }
+ return 0
+ }
+
+ func (m *Test) GetName() string {
+ if x, ok := m.GetUnion().(*Test_Name); ok {
+ return x.Name
+ }
+ return ""
+ }
+
+ func init() {
+ proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
+ }
+
+To create and play with a Test object:
+
+ package main
+
+ import (
+ "log"
+
+ "github.com/gogo/protobuf/proto"
+ pb "./example.pb"
+ )
+
+ func main() {
+ test := &pb.Test{
+ Label: proto.String("hello"),
+ Type: proto.Int32(17),
+ Reps: []int64{1, 2, 3},
+ Optionalgroup: &pb.Test_OptionalGroup{
+ RequiredField: proto.String("good bye"),
+ },
+ Union: &pb.Test_Name{"fred"},
+ }
+ data, err := proto.Marshal(test)
+ if err != nil {
+ log.Fatal("marshaling error: ", err)
+ }
+ newTest := &pb.Test{}
+ err = proto.Unmarshal(data, newTest)
+ if err != nil {
+ log.Fatal("unmarshaling error: ", err)
+ }
+ // Now test and newTest contain the same data.
+ if test.GetLabel() != newTest.GetLabel() {
+ log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
+ }
+ // Use a type switch to determine which oneof was set.
+ switch u := test.Union.(type) {
+ case *pb.Test_Number: // u.Number contains the number.
+ case *pb.Test_Name: // u.Name contains the string.
+ }
+ // etc.
+ }
+*/
+package proto
+
+import (
+ "encoding/json"
+ "fmt"
+ "log"
+ "reflect"
+ "sort"
+ "strconv"
+ "sync"
+)
+
+// Message is implemented by generated protocol buffer messages.
+type Message interface {
+ Reset()
+ String() string
+ ProtoMessage()
+}
+
+// Stats records allocation details about the protocol buffer encoders
+// and decoders. Useful for tuning the library itself.
+type Stats struct {
+ Emalloc uint64 // mallocs in encode
+ Dmalloc uint64 // mallocs in decode
+ Encode uint64 // number of encodes
+ Decode uint64 // number of decodes
+ Chit uint64 // number of cache hits
+ Cmiss uint64 // number of cache misses
+ Size uint64 // number of sizes
+}
+
+// Set to true to enable stats collection.
+const collectStats = false
+
+var stats Stats
+
+// GetStats returns a copy of the global Stats structure.
+func GetStats() Stats { return stats }
+
+// A Buffer is a buffer manager for marshaling and unmarshaling
+// protocol buffers. It may be reused between invocations to
+// reduce memory usage. It is not necessary to use a Buffer;
+// the global functions Marshal and Unmarshal create a
+// temporary Buffer and are fine for most applications.
+type Buffer struct {
+ buf []byte // encode/decode byte stream
+ index int // read point
+
+ // pools of basic types to amortize allocation.
+ bools []bool
+ uint32s []uint32
+ uint64s []uint64
+
+ // extra pools, only used with pointer_reflect.go
+ int32s []int32
+ int64s []int64
+ float32s []float32
+ float64s []float64
+}
+
+// NewBuffer allocates a new Buffer and initializes its internal data to
+// the contents of the argument slice.
+func NewBuffer(e []byte) *Buffer {
+ return &Buffer{buf: e}
+}
+
+// Reset resets the Buffer, ready for marshaling a new protocol buffer.
+func (p *Buffer) Reset() {
+ p.buf = p.buf[0:0] // for reading/writing
+ p.index = 0 // for reading
+}
+
+// SetBuf replaces the internal buffer with the slice,
+// ready for unmarshaling the contents of the slice.
+func (p *Buffer) SetBuf(s []byte) {
+ p.buf = s
+ p.index = 0
+}
+
+// Bytes returns the contents of the Buffer.
+func (p *Buffer) Bytes() []byte { return p.buf }
+
+/*
+ * Helper routines for simplifying the creation of optional fields of basic type.
+ */
+
+// Bool is a helper routine that allocates a new bool value
+// to store v and returns a pointer to it.
+func Bool(v bool) *bool {
+ return &v
+}
+
+// Int32 is a helper routine that allocates a new int32 value
+// to store v and returns a pointer to it.
+func Int32(v int32) *int32 {
+ return &v
+}
+
+// Int is a helper routine that allocates a new int32 value
+// to store v and returns a pointer to it, but unlike Int32
+// its argument value is an int.
+func Int(v int) *int32 {
+ p := new(int32)
+ *p = int32(v)
+ return p
+}
+
+// Int64 is a helper routine that allocates a new int64 value
+// to store v and returns a pointer to it.
+func Int64(v int64) *int64 {
+ return &v
+}
+
+// Float32 is a helper routine that allocates a new float32 value
+// to store v and returns a pointer to it.
+func Float32(v float32) *float32 {
+ return &v
+}
+
+// Float64 is a helper routine that allocates a new float64 value
+// to store v and returns a pointer to it.
+func Float64(v float64) *float64 {
+ return &v
+}
+
+// Uint32 is a helper routine that allocates a new uint32 value
+// to store v and returns a pointer to it.
+func Uint32(v uint32) *uint32 {
+ return &v
+}
+
+// Uint64 is a helper routine that allocates a new uint64 value
+// to store v and returns a pointer to it.
+func Uint64(v uint64) *uint64 {
+ return &v
+}
+
+// String is a helper routine that allocates a new string value
+// to store v and returns a pointer to it.
+func String(v string) *string {
+ return &v
+}
+
+// EnumName is a helper function to simplify printing protocol buffer enums
+// by name. Given an enum map and a value, it returns a useful string.
+func EnumName(m map[int32]string, v int32) string {
+ s, ok := m[v]
+ if ok {
+ return s
+ }
+ return strconv.Itoa(int(v))
+}
+
+// UnmarshalJSONEnum is a helper function to simplify recovering enum int values
+// from their JSON-encoded representation. Given a map from the enum's symbolic
+// names to its int values, and a byte buffer containing the JSON-encoded
+// value, it returns an int32 that can be cast to the enum type by the caller.
+//
+// The function can deal with both JSON representations, numeric and symbolic.
+func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) {
+ if data[0] == '"' {
+ // New style: enums are strings.
+ var repr string
+ if err := json.Unmarshal(data, &repr); err != nil {
+ return -1, err
+ }
+ val, ok := m[repr]
+ if !ok {
+ return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr)
+ }
+ return val, nil
+ }
+ // Old style: enums are ints.
+ var val int32
+ if err := json.Unmarshal(data, &val); err != nil {
+ return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName)
+ }
+ return val, nil
+}
+
+// DebugPrint dumps the encoded data in b in a debugging format with a header
+// including the string s. Used in testing but made available for general debugging.
+func (p *Buffer) DebugPrint(s string, b []byte) {
+ var u uint64
+
+ obuf := p.buf
+ sindex := p.index
+ p.buf = b
+ p.index = 0
+ depth := 0
+
+ fmt.Printf("\n--- %s ---\n", s)
+
+out:
+ for {
+ for i := 0; i < depth; i++ {
+ fmt.Print(" ")
+ }
+
+ index := p.index
+ if index == len(p.buf) {
+ break
+ }
+
+ op, err := p.DecodeVarint()
+ if err != nil {
+ fmt.Printf("%3d: fetching op err %v\n", index, err)
+ break out
+ }
+ tag := op >> 3
+ wire := op & 7
+
+ switch wire {
+ default:
+ fmt.Printf("%3d: t=%3d unknown wire=%d\n",
+ index, tag, wire)
+ break out
+
+ case WireBytes:
+ var r []byte
+
+ r, err = p.DecodeRawBytes(false)
+ if err != nil {
+ break out
+ }
+ fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r))
+ if len(r) <= 6 {
+ for i := 0; i < len(r); i++ {
+ fmt.Printf(" %.2x", r[i])
+ }
+ } else {
+ for i := 0; i < 3; i++ {
+ fmt.Printf(" %.2x", r[i])
+ }
+ fmt.Printf(" ..")
+ for i := len(r) - 3; i < len(r); i++ {
+ fmt.Printf(" %.2x", r[i])
+ }
+ }
+ fmt.Printf("\n")
+
+ case WireFixed32:
+ u, err = p.DecodeFixed32()
+ if err != nil {
+ fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err)
+ break out
+ }
+ fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u)
+
+ case WireFixed64:
+ u, err = p.DecodeFixed64()
+ if err != nil {
+ fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err)
+ break out
+ }
+ fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u)
+
+ case WireVarint:
+ u, err = p.DecodeVarint()
+ if err != nil {
+ fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err)
+ break out
+ }
+ fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u)
+
+ case WireStartGroup:
+ fmt.Printf("%3d: t=%3d start\n", index, tag)
+ depth++
+
+ case WireEndGroup:
+ depth--
+ fmt.Printf("%3d: t=%3d end\n", index, tag)
+ }
+ }
+
+ if depth != 0 {
+ fmt.Printf("%3d: start-end not balanced %d\n", p.index, depth)
+ }
+ fmt.Printf("\n")
+
+ p.buf = obuf
+ p.index = sindex
+}
+
+// SetDefaults sets unset protocol buffer fields to their default values.
+// It only modifies fields that are both unset and have defined defaults.
+// It recursively sets default values in any non-nil sub-messages.
+func SetDefaults(pb Message) {
+ setDefaults(reflect.ValueOf(pb), true, false)
+}
+
+// v is a pointer to a struct.
+func setDefaults(v reflect.Value, recur, zeros bool) {
+ v = v.Elem()
+
+ defaultMu.RLock()
+ dm, ok := defaults[v.Type()]
+ defaultMu.RUnlock()
+ if !ok {
+ dm = buildDefaultMessage(v.Type())
+ defaultMu.Lock()
+ defaults[v.Type()] = dm
+ defaultMu.Unlock()
+ }
+
+ for _, sf := range dm.scalars {
+ f := v.Field(sf.index)
+ if !f.IsNil() {
+ // field already set
+ continue
+ }
+ dv := sf.value
+ if dv == nil && !zeros {
+ // no explicit default, and don't want to set zeros
+ continue
+ }
+ fptr := f.Addr().Interface() // **T
+ // TODO: Consider batching the allocations we do here.
+ switch sf.kind {
+ case reflect.Bool:
+ b := new(bool)
+ if dv != nil {
+ *b = dv.(bool)
+ }
+ *(fptr.(**bool)) = b
+ case reflect.Float32:
+ f := new(float32)
+ if dv != nil {
+ *f = dv.(float32)
+ }
+ *(fptr.(**float32)) = f
+ case reflect.Float64:
+ f := new(float64)
+ if dv != nil {
+ *f = dv.(float64)
+ }
+ *(fptr.(**float64)) = f
+ case reflect.Int32:
+ // might be an enum
+ if ft := f.Type(); ft != int32PtrType {
+ // enum
+ f.Set(reflect.New(ft.Elem()))
+ if dv != nil {
+ f.Elem().SetInt(int64(dv.(int32)))
+ }
+ } else {
+ // int32 field
+ i := new(int32)
+ if dv != nil {
+ *i = dv.(int32)
+ }
+ *(fptr.(**int32)) = i
+ }
+ case reflect.Int64:
+ i := new(int64)
+ if dv != nil {
+ *i = dv.(int64)
+ }
+ *(fptr.(**int64)) = i
+ case reflect.String:
+ s := new(string)
+ if dv != nil {
+ *s = dv.(string)
+ }
+ *(fptr.(**string)) = s
+ case reflect.Uint8:
+ // exceptional case: []byte
+ var b []byte
+ if dv != nil {
+ db := dv.([]byte)
+ b = make([]byte, len(db))
+ copy(b, db)
+ } else {
+ b = []byte{}
+ }
+ *(fptr.(*[]byte)) = b
+ case reflect.Uint32:
+ u := new(uint32)
+ if dv != nil {
+ *u = dv.(uint32)
+ }
+ *(fptr.(**uint32)) = u
+ case reflect.Uint64:
+ u := new(uint64)
+ if dv != nil {
+ *u = dv.(uint64)
+ }
+ *(fptr.(**uint64)) = u
+ default:
+ log.Printf("proto: can't set default for field %v (sf.kind=%v)", f, sf.kind)
+ }
+ }
+
+ for _, ni := range dm.nested {
+ f := v.Field(ni)
+ // f is *T or []*T or map[T]*T
+ switch f.Kind() {
+ case reflect.Ptr:
+ if f.IsNil() {
+ continue
+ }
+ setDefaults(f, recur, zeros)
+
+ case reflect.Slice:
+ for i := 0; i < f.Len(); i++ {
+ e := f.Index(i)
+ if e.IsNil() {
+ continue
+ }
+ setDefaults(e, recur, zeros)
+ }
+
+ case reflect.Map:
+ for _, k := range f.MapKeys() {
+ e := f.MapIndex(k)
+ if e.IsNil() {
+ continue
+ }
+ setDefaults(e, recur, zeros)
+ }
+ }
+ }
+}
+
+var (
+ // defaults maps a protocol buffer struct type to a slice of the fields,
+ // with its scalar fields set to their proto-declared non-zero default values.
+ defaultMu sync.RWMutex
+ defaults = make(map[reflect.Type]defaultMessage)
+
+ int32PtrType = reflect.TypeOf((*int32)(nil))
+)
+
+// defaultMessage represents information about the default values of a message.
+type defaultMessage struct {
+ scalars []scalarField
+ nested []int // struct field index of nested messages
+}
+
+type scalarField struct {
+ index int // struct field index
+ kind reflect.Kind // element type (the T in *T or []T)
+ value interface{} // the proto-declared default value, or nil
+}
+
+// t is a struct type.
+func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
+ sprop := GetProperties(t)
+ for _, prop := range sprop.Prop {
+ fi, ok := sprop.decoderTags.get(prop.Tag)
+ if !ok {
+ // XXX_unrecognized
+ continue
+ }
+ ft := t.Field(fi).Type
+
+ sf, nested, err := fieldDefault(ft, prop)
+ switch {
+ case err != nil:
+ log.Print(err)
+ case nested:
+ dm.nested = append(dm.nested, fi)
+ case sf != nil:
+ sf.index = fi
+ dm.scalars = append(dm.scalars, *sf)
+ }
+ }
+
+ return dm
+}
+
+// fieldDefault returns the scalarField for field type ft.
+// sf will be nil if the field can not have a default.
+// nestedMessage will be true if this is a nested message.
+// Note that sf.index is not set on return.
+func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) {
+ var canHaveDefault bool
+ switch ft.Kind() {
+ case reflect.Ptr:
+ if ft.Elem().Kind() == reflect.Struct {
+ nestedMessage = true
+ } else {
+ canHaveDefault = true // proto2 scalar field
+ }
+
+ case reflect.Slice:
+ switch ft.Elem().Kind() {
+ case reflect.Ptr:
+ nestedMessage = true // repeated message
+ case reflect.Uint8:
+ canHaveDefault = true // bytes field
+ }
+
+ case reflect.Map:
+ if ft.Elem().Kind() == reflect.Ptr {
+ nestedMessage = true // map with message values
+ }
+ }
+
+ if !canHaveDefault {
+ if nestedMessage {
+ return nil, true, nil
+ }
+ return nil, false, nil
+ }
+
+ // We now know that ft is a pointer or slice.
+ sf = &scalarField{kind: ft.Elem().Kind()}
+
+ // scalar fields without defaults
+ if !prop.HasDefault {
+ return sf, false, nil
+ }
+
+ // a scalar field: either *T or []byte
+ switch ft.Elem().Kind() {
+ case reflect.Bool:
+ x, err := strconv.ParseBool(prop.Default)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default bool %q: %v", prop.Default, err)
+ }
+ sf.value = x
+ case reflect.Float32:
+ x, err := strconv.ParseFloat(prop.Default, 32)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default float32 %q: %v", prop.Default, err)
+ }
+ sf.value = float32(x)
+ case reflect.Float64:
+ x, err := strconv.ParseFloat(prop.Default, 64)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default float64 %q: %v", prop.Default, err)
+ }
+ sf.value = x
+ case reflect.Int32:
+ x, err := strconv.ParseInt(prop.Default, 10, 32)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default int32 %q: %v", prop.Default, err)
+ }
+ sf.value = int32(x)
+ case reflect.Int64:
+ x, err := strconv.ParseInt(prop.Default, 10, 64)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default int64 %q: %v", prop.Default, err)
+ }
+ sf.value = x
+ case reflect.String:
+ sf.value = prop.Default
+ case reflect.Uint8:
+ // []byte (not *uint8)
+ sf.value = []byte(prop.Default)
+ case reflect.Uint32:
+ x, err := strconv.ParseUint(prop.Default, 10, 32)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default uint32 %q: %v", prop.Default, err)
+ }
+ sf.value = uint32(x)
+ case reflect.Uint64:
+ x, err := strconv.ParseUint(prop.Default, 10, 64)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default uint64 %q: %v", prop.Default, err)
+ }
+ sf.value = x
+ default:
+ return nil, false, fmt.Errorf("proto: unhandled def kind %v", ft.Elem().Kind())
+ }
+
+ return sf, false, nil
+}
+
+// Map fields may have key types of non-float scalars, strings and enums.
+// The easiest way to sort them in some deterministic order is to use fmt.
+// If this turns out to be inefficient we can always consider other options,
+// such as doing a Schwartzian transform.
+
+func mapKeys(vs []reflect.Value) sort.Interface {
+ s := mapKeySorter{
+ vs: vs,
+ // default Less function: textual comparison
+ less: func(a, b reflect.Value) bool {
+ return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface())
+ },
+ }
+
+ // Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps;
+ // numeric keys are sorted numerically.
+ if len(vs) == 0 {
+ return s
+ }
+ switch vs[0].Kind() {
+ case reflect.Int32, reflect.Int64:
+ s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
+ case reflect.Uint32, reflect.Uint64:
+ s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
+ }
+
+ return s
+}
+
+type mapKeySorter struct {
+ vs []reflect.Value
+ less func(a, b reflect.Value) bool
+}
+
+func (s mapKeySorter) Len() int { return len(s.vs) }
+func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] }
+func (s mapKeySorter) Less(i, j int) bool {
+ return s.less(s.vs[i], s.vs[j])
+}
+
+// isProto3Zero reports whether v is a zero proto3 value.
+func isProto3Zero(v reflect.Value) bool {
+ switch v.Kind() {
+ case reflect.Bool:
+ return !v.Bool()
+ case reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Uint32, reflect.Uint64:
+ return v.Uint() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ case reflect.String:
+ return v.String() == ""
+ }
+ return false
+}
+
+// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
+// to assert that that code is compatible with this version of the proto package.
+const GoGoProtoPackageIsVersion2 = true
+
+// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
+// to assert that that code is compatible with this version of the proto package.
+const GoGoProtoPackageIsVersion1 = true
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+import (
+ "encoding/json"
+ "strconv"
+)
+
+func MarshalJSONEnum(m map[int32]string, value int32) ([]byte, error) {
+ s, ok := m[value]
+ if !ok {
+ s = strconv.Itoa(int(value))
+ }
+ return json.Marshal(s)
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+/*
+ * Support for message sets.
+ */
+
+import (
+ "bytes"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "reflect"
+ "sort"
+)
+
+// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
+// A message type ID is required for storing a protocol buffer in a message set.
+var errNoMessageTypeID = errors.New("proto does not have a message type ID")
+
+// The first two types (_MessageSet_Item and messageSet)
+// model what the protocol compiler produces for the following protocol message:
+// message MessageSet {
+// repeated group Item = 1 {
+// required int32 type_id = 2;
+// required string message = 3;
+// };
+// }
+// That is the MessageSet wire format. We can't use a proto to generate these
+// because that would introduce a circular dependency between it and this package.
+
+type _MessageSet_Item struct {
+ TypeId *int32 `protobuf:"varint,2,req,name=type_id"`
+ Message []byte `protobuf:"bytes,3,req,name=message"`
+}
+
+type messageSet struct {
+ Item []*_MessageSet_Item `protobuf:"group,1,rep"`
+ XXX_unrecognized []byte
+ // TODO: caching?
+}
+
+// Make sure messageSet is a Message.
+var _ Message = (*messageSet)(nil)
+
+// messageTypeIder is an interface satisfied by a protocol buffer type
+// that may be stored in a MessageSet.
+type messageTypeIder interface {
+ MessageTypeId() int32
+}
+
+func (ms *messageSet) find(pb Message) *_MessageSet_Item {
+ mti, ok := pb.(messageTypeIder)
+ if !ok {
+ return nil
+ }
+ id := mti.MessageTypeId()
+ for _, item := range ms.Item {
+ if *item.TypeId == id {
+ return item
+ }
+ }
+ return nil
+}
+
+func (ms *messageSet) Has(pb Message) bool {
+ if ms.find(pb) != nil {
+ return true
+ }
+ return false
+}
+
+func (ms *messageSet) Unmarshal(pb Message) error {
+ if item := ms.find(pb); item != nil {
+ return Unmarshal(item.Message, pb)
+ }
+ if _, ok := pb.(messageTypeIder); !ok {
+ return errNoMessageTypeID
+ }
+ return nil // TODO: return error instead?
+}
+
+func (ms *messageSet) Marshal(pb Message) error {
+ msg, err := Marshal(pb)
+ if err != nil {
+ return err
+ }
+ if item := ms.find(pb); item != nil {
+ // reuse existing item
+ item.Message = msg
+ return nil
+ }
+
+ mti, ok := pb.(messageTypeIder)
+ if !ok {
+ return errNoMessageTypeID
+ }
+
+ mtid := mti.MessageTypeId()
+ ms.Item = append(ms.Item, &_MessageSet_Item{
+ TypeId: &mtid,
+ Message: msg,
+ })
+ return nil
+}
+
+func (ms *messageSet) Reset() { *ms = messageSet{} }
+func (ms *messageSet) String() string { return CompactTextString(ms) }
+func (*messageSet) ProtoMessage() {}
+
+// Support for the message_set_wire_format message option.
+
+func skipVarint(buf []byte) []byte {
+ i := 0
+ for ; buf[i]&0x80 != 0; i++ {
+ }
+ return buf[i+1:]
+}
+
+// MarshalMessageSet encodes the extension map represented by m in the message set wire format.
+// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
+func MarshalMessageSet(exts interface{}) ([]byte, error) {
+ var m map[int32]Extension
+ switch exts := exts.(type) {
+ case *XXX_InternalExtensions:
+ if err := encodeExtensions(exts); err != nil {
+ return nil, err
+ }
+ m, _ = exts.extensionsRead()
+ case map[int32]Extension:
+ if err := encodeExtensionsMap(exts); err != nil {
+ return nil, err
+ }
+ m = exts
+ default:
+ return nil, errors.New("proto: not an extension map")
+ }
+
+ // Sort extension IDs to provide a deterministic encoding.
+ // See also enc_map in encode.go.
+ ids := make([]int, 0, len(m))
+ for id := range m {
+ ids = append(ids, int(id))
+ }
+ sort.Ints(ids)
+
+ ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))}
+ for _, id := range ids {
+ e := m[int32(id)]
+ // Remove the wire type and field number varint, as well as the length varint.
+ msg := skipVarint(skipVarint(e.enc))
+
+ ms.Item = append(ms.Item, &_MessageSet_Item{
+ TypeId: Int32(int32(id)),
+ Message: msg,
+ })
+ }
+ return Marshal(ms)
+}
+
+// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
+// It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
+func UnmarshalMessageSet(buf []byte, exts interface{}) error {
+ var m map[int32]Extension
+ switch exts := exts.(type) {
+ case *XXX_InternalExtensions:
+ m = exts.extensionsWrite()
+ case map[int32]Extension:
+ m = exts
+ default:
+ return errors.New("proto: not an extension map")
+ }
+
+ ms := new(messageSet)
+ if err := Unmarshal(buf, ms); err != nil {
+ return err
+ }
+ for _, item := range ms.Item {
+ id := *item.TypeId
+ msg := item.Message
+
+ // Restore wire type and field number varint, plus length varint.
+ // Be careful to preserve duplicate items.
+ b := EncodeVarint(uint64(id)<<3 | WireBytes)
+ if ext, ok := m[id]; ok {
+ // Existing data; rip off the tag and length varint
+ // so we join the new data correctly.
+ // We can assume that ext.enc is set because we are unmarshaling.
+ o := ext.enc[len(b):] // skip wire type and field number
+ _, n := DecodeVarint(o) // calculate length of length varint
+ o = o[n:] // skip length varint
+ msg = append(o, msg...) // join old data and new data
+ }
+ b = append(b, EncodeVarint(uint64(len(msg)))...)
+ b = append(b, msg...)
+
+ m[id] = Extension{enc: b}
+ }
+ return nil
+}
+
+// MarshalMessageSetJSON encodes the extension map represented by m in JSON format.
+// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
+func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
+ var m map[int32]Extension
+ switch exts := exts.(type) {
+ case *XXX_InternalExtensions:
+ m, _ = exts.extensionsRead()
+ case map[int32]Extension:
+ m = exts
+ default:
+ return nil, errors.New("proto: not an extension map")
+ }
+ var b bytes.Buffer
+ b.WriteByte('{')
+
+ // Process the map in key order for deterministic output.
+ ids := make([]int32, 0, len(m))
+ for id := range m {
+ ids = append(ids, id)
+ }
+ sort.Sort(int32Slice(ids)) // int32Slice defined in text.go
+
+ for i, id := range ids {
+ ext := m[id]
+ if i > 0 {
+ b.WriteByte(',')
+ }
+
+ msd, ok := messageSetMap[id]
+ if !ok {
+ // Unknown type; we can't render it, so skip it.
+ continue
+ }
+ fmt.Fprintf(&b, `"[%s]":`, msd.name)
+
+ x := ext.value
+ if x == nil {
+ x = reflect.New(msd.t.Elem()).Interface()
+ if err := Unmarshal(ext.enc, x.(Message)); err != nil {
+ return nil, err
+ }
+ }
+ d, err := json.Marshal(x)
+ if err != nil {
+ return nil, err
+ }
+ b.Write(d)
+ }
+ b.WriteByte('}')
+ return b.Bytes(), nil
+}
+
+// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format.
+// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
+func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error {
+ // Common-case fast path.
+ if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) {
+ return nil
+ }
+
+ // This is fairly tricky, and it's not clear that it is needed.
+ return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented")
+}
+
+// A global registry of types that can be used in a MessageSet.
+
+var messageSetMap = make(map[int32]messageSetDesc)
+
+type messageSetDesc struct {
+ t reflect.Type // pointer to struct
+ name string
+}
+
+// RegisterMessageSetType is called from the generated code.
+func RegisterMessageSetType(m Message, fieldNum int32, name string) {
+ messageSetMap[fieldNum] = messageSetDesc{
+ t: reflect.TypeOf(m),
+ name: name,
+ }
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2012 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// +build appengine js
+
+// This file contains an implementation of proto field accesses using package reflect.
+// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can
+// be used on App Engine.
+
+package proto
+
+import (
+ "math"
+ "reflect"
+)
+
+// A structPointer is a pointer to a struct.
+type structPointer struct {
+ v reflect.Value
+}
+
+// toStructPointer returns a structPointer equivalent to the given reflect value.
+// The reflect value must itself be a pointer to a struct.
+func toStructPointer(v reflect.Value) structPointer {
+ return structPointer{v}
+}
+
+// IsNil reports whether p is nil.
+func structPointer_IsNil(p structPointer) bool {
+ return p.v.IsNil()
+}
+
+// Interface returns the struct pointer as an interface value.
+func structPointer_Interface(p structPointer, _ reflect.Type) interface{} {
+ return p.v.Interface()
+}
+
+// A field identifies a field in a struct, accessible from a structPointer.
+// In this implementation, a field is identified by the sequence of field indices
+// passed to reflect's FieldByIndex.
+type field []int
+
+// toField returns a field equivalent to the given reflect field.
+func toField(f *reflect.StructField) field {
+ return f.Index
+}
+
+// invalidField is an invalid field identifier.
+var invalidField = field(nil)
+
+// IsValid reports whether the field identifier is valid.
+func (f field) IsValid() bool { return f != nil }
+
+// field returns the given field in the struct as a reflect value.
+func structPointer_field(p structPointer, f field) reflect.Value {
+ // Special case: an extension map entry with a value of type T
+ // passes a *T to the struct-handling code with a zero field,
+ // expecting that it will be treated as equivalent to *struct{ X T },
+ // which has the same memory layout. We have to handle that case
+ // specially, because reflect will panic if we call FieldByIndex on a
+ // non-struct.
+ if f == nil {
+ return p.v.Elem()
+ }
+
+ return p.v.Elem().FieldByIndex(f)
+}
+
+// ifield returns the given field in the struct as an interface value.
+func structPointer_ifield(p structPointer, f field) interface{} {
+ return structPointer_field(p, f).Addr().Interface()
+}
+
+// Bytes returns the address of a []byte field in the struct.
+func structPointer_Bytes(p structPointer, f field) *[]byte {
+ return structPointer_ifield(p, f).(*[]byte)
+}
+
+// BytesSlice returns the address of a [][]byte field in the struct.
+func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
+ return structPointer_ifield(p, f).(*[][]byte)
+}
+
+// Bool returns the address of a *bool field in the struct.
+func structPointer_Bool(p structPointer, f field) **bool {
+ return structPointer_ifield(p, f).(**bool)
+}
+
+// BoolVal returns the address of a bool field in the struct.
+func structPointer_BoolVal(p structPointer, f field) *bool {
+ return structPointer_ifield(p, f).(*bool)
+}
+
+// BoolSlice returns the address of a []bool field in the struct.
+func structPointer_BoolSlice(p structPointer, f field) *[]bool {
+ return structPointer_ifield(p, f).(*[]bool)
+}
+
+// String returns the address of a *string field in the struct.
+func structPointer_String(p structPointer, f field) **string {
+ return structPointer_ifield(p, f).(**string)
+}
+
+// StringVal returns the address of a string field in the struct.
+func structPointer_StringVal(p structPointer, f field) *string {
+ return structPointer_ifield(p, f).(*string)
+}
+
+// StringSlice returns the address of a []string field in the struct.
+func structPointer_StringSlice(p structPointer, f field) *[]string {
+ return structPointer_ifield(p, f).(*[]string)
+}
+
+// Extensions returns the address of an extension map field in the struct.
+func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
+ return structPointer_ifield(p, f).(*XXX_InternalExtensions)
+}
+
+// ExtMap returns the address of an extension map field in the struct.
+func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
+ return structPointer_ifield(p, f).(*map[int32]Extension)
+}
+
+// NewAt returns the reflect.Value for a pointer to a field in the struct.
+func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
+ return structPointer_field(p, f).Addr()
+}
+
+// SetStructPointer writes a *struct field in the struct.
+func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
+ structPointer_field(p, f).Set(q.v)
+}
+
+// GetStructPointer reads a *struct field in the struct.
+func structPointer_GetStructPointer(p structPointer, f field) structPointer {
+ return structPointer{structPointer_field(p, f)}
+}
+
+// StructPointerSlice the address of a []*struct field in the struct.
+func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice {
+ return structPointerSlice{structPointer_field(p, f)}
+}
+
+// A structPointerSlice represents the address of a slice of pointers to structs
+// (themselves messages or groups). That is, v.Type() is *[]*struct{...}.
+type structPointerSlice struct {
+ v reflect.Value
+}
+
+func (p structPointerSlice) Len() int { return p.v.Len() }
+func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} }
+func (p structPointerSlice) Append(q structPointer) {
+ p.v.Set(reflect.Append(p.v, q.v))
+}
+
+var (
+ int32Type = reflect.TypeOf(int32(0))
+ uint32Type = reflect.TypeOf(uint32(0))
+ float32Type = reflect.TypeOf(float32(0))
+ int64Type = reflect.TypeOf(int64(0))
+ uint64Type = reflect.TypeOf(uint64(0))
+ float64Type = reflect.TypeOf(float64(0))
+)
+
+// A word32 represents a field of type *int32, *uint32, *float32, or *enum.
+// That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable.
+type word32 struct {
+ v reflect.Value
+}
+
+// IsNil reports whether p is nil.
+func word32_IsNil(p word32) bool {
+ return p.v.IsNil()
+}
+
+// Set sets p to point at a newly allocated word with bits set to x.
+func word32_Set(p word32, o *Buffer, x uint32) {
+ t := p.v.Type().Elem()
+ switch t {
+ case int32Type:
+ if len(o.int32s) == 0 {
+ o.int32s = make([]int32, uint32PoolSize)
+ }
+ o.int32s[0] = int32(x)
+ p.v.Set(reflect.ValueOf(&o.int32s[0]))
+ o.int32s = o.int32s[1:]
+ return
+ case uint32Type:
+ if len(o.uint32s) == 0 {
+ o.uint32s = make([]uint32, uint32PoolSize)
+ }
+ o.uint32s[0] = x
+ p.v.Set(reflect.ValueOf(&o.uint32s[0]))
+ o.uint32s = o.uint32s[1:]
+ return
+ case float32Type:
+ if len(o.float32s) == 0 {
+ o.float32s = make([]float32, uint32PoolSize)
+ }
+ o.float32s[0] = math.Float32frombits(x)
+ p.v.Set(reflect.ValueOf(&o.float32s[0]))
+ o.float32s = o.float32s[1:]
+ return
+ }
+
+ // must be enum
+ p.v.Set(reflect.New(t))
+ p.v.Elem().SetInt(int64(int32(x)))
+}
+
+// Get gets the bits pointed at by p, as a uint32.
+func word32_Get(p word32) uint32 {
+ elem := p.v.Elem()
+ switch elem.Kind() {
+ case reflect.Int32:
+ return uint32(elem.Int())
+ case reflect.Uint32:
+ return uint32(elem.Uint())
+ case reflect.Float32:
+ return math.Float32bits(float32(elem.Float()))
+ }
+ panic("unreachable")
+}
+
+// Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct.
+func structPointer_Word32(p structPointer, f field) word32 {
+ return word32{structPointer_field(p, f)}
+}
+
+// A word32Val represents a field of type int32, uint32, float32, or enum.
+// That is, v.Type() is int32, uint32, float32, or enum and v is assignable.
+type word32Val struct {
+ v reflect.Value
+}
+
+// Set sets *p to x.
+func word32Val_Set(p word32Val, x uint32) {
+ switch p.v.Type() {
+ case int32Type:
+ p.v.SetInt(int64(x))
+ return
+ case uint32Type:
+ p.v.SetUint(uint64(x))
+ return
+ case float32Type:
+ p.v.SetFloat(float64(math.Float32frombits(x)))
+ return
+ }
+
+ // must be enum
+ p.v.SetInt(int64(int32(x)))
+}
+
+// Get gets the bits pointed at by p, as a uint32.
+func word32Val_Get(p word32Val) uint32 {
+ elem := p.v
+ switch elem.Kind() {
+ case reflect.Int32:
+ return uint32(elem.Int())
+ case reflect.Uint32:
+ return uint32(elem.Uint())
+ case reflect.Float32:
+ return math.Float32bits(float32(elem.Float()))
+ }
+ panic("unreachable")
+}
+
+// Word32Val returns a reference to a int32, uint32, float32, or enum field in the struct.
+func structPointer_Word32Val(p structPointer, f field) word32Val {
+ return word32Val{structPointer_field(p, f)}
+}
+
+// A word32Slice is a slice of 32-bit values.
+// That is, v.Type() is []int32, []uint32, []float32, or []enum.
+type word32Slice struct {
+ v reflect.Value
+}
+
+func (p word32Slice) Append(x uint32) {
+ n, m := p.v.Len(), p.v.Cap()
+ if n < m {
+ p.v.SetLen(n + 1)
+ } else {
+ t := p.v.Type().Elem()
+ p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
+ }
+ elem := p.v.Index(n)
+ switch elem.Kind() {
+ case reflect.Int32:
+ elem.SetInt(int64(int32(x)))
+ case reflect.Uint32:
+ elem.SetUint(uint64(x))
+ case reflect.Float32:
+ elem.SetFloat(float64(math.Float32frombits(x)))
+ }
+}
+
+func (p word32Slice) Len() int {
+ return p.v.Len()
+}
+
+func (p word32Slice) Index(i int) uint32 {
+ elem := p.v.Index(i)
+ switch elem.Kind() {
+ case reflect.Int32:
+ return uint32(elem.Int())
+ case reflect.Uint32:
+ return uint32(elem.Uint())
+ case reflect.Float32:
+ return math.Float32bits(float32(elem.Float()))
+ }
+ panic("unreachable")
+}
+
+// Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct.
+func structPointer_Word32Slice(p structPointer, f field) word32Slice {
+ return word32Slice{structPointer_field(p, f)}
+}
+
+// word64 is like word32 but for 64-bit values.
+type word64 struct {
+ v reflect.Value
+}
+
+func word64_Set(p word64, o *Buffer, x uint64) {
+ t := p.v.Type().Elem()
+ switch t {
+ case int64Type:
+ if len(o.int64s) == 0 {
+ o.int64s = make([]int64, uint64PoolSize)
+ }
+ o.int64s[0] = int64(x)
+ p.v.Set(reflect.ValueOf(&o.int64s[0]))
+ o.int64s = o.int64s[1:]
+ return
+ case uint64Type:
+ if len(o.uint64s) == 0 {
+ o.uint64s = make([]uint64, uint64PoolSize)
+ }
+ o.uint64s[0] = x
+ p.v.Set(reflect.ValueOf(&o.uint64s[0]))
+ o.uint64s = o.uint64s[1:]
+ return
+ case float64Type:
+ if len(o.float64s) == 0 {
+ o.float64s = make([]float64, uint64PoolSize)
+ }
+ o.float64s[0] = math.Float64frombits(x)
+ p.v.Set(reflect.ValueOf(&o.float64s[0]))
+ o.float64s = o.float64s[1:]
+ return
+ }
+ panic("unreachable")
+}
+
+func word64_IsNil(p word64) bool {
+ return p.v.IsNil()
+}
+
+func word64_Get(p word64) uint64 {
+ elem := p.v.Elem()
+ switch elem.Kind() {
+ case reflect.Int64:
+ return uint64(elem.Int())
+ case reflect.Uint64:
+ return elem.Uint()
+ case reflect.Float64:
+ return math.Float64bits(elem.Float())
+ }
+ panic("unreachable")
+}
+
+func structPointer_Word64(p structPointer, f field) word64 {
+ return word64{structPointer_field(p, f)}
+}
+
+// word64Val is like word32Val but for 64-bit values.
+type word64Val struct {
+ v reflect.Value
+}
+
+func word64Val_Set(p word64Val, o *Buffer, x uint64) {
+ switch p.v.Type() {
+ case int64Type:
+ p.v.SetInt(int64(x))
+ return
+ case uint64Type:
+ p.v.SetUint(x)
+ return
+ case float64Type:
+ p.v.SetFloat(math.Float64frombits(x))
+ return
+ }
+ panic("unreachable")
+}
+
+func word64Val_Get(p word64Val) uint64 {
+ elem := p.v
+ switch elem.Kind() {
+ case reflect.Int64:
+ return uint64(elem.Int())
+ case reflect.Uint64:
+ return elem.Uint()
+ case reflect.Float64:
+ return math.Float64bits(elem.Float())
+ }
+ panic("unreachable")
+}
+
+func structPointer_Word64Val(p structPointer, f field) word64Val {
+ return word64Val{structPointer_field(p, f)}
+}
+
+type word64Slice struct {
+ v reflect.Value
+}
+
+func (p word64Slice) Append(x uint64) {
+ n, m := p.v.Len(), p.v.Cap()
+ if n < m {
+ p.v.SetLen(n + 1)
+ } else {
+ t := p.v.Type().Elem()
+ p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
+ }
+ elem := p.v.Index(n)
+ switch elem.Kind() {
+ case reflect.Int64:
+ elem.SetInt(int64(int64(x)))
+ case reflect.Uint64:
+ elem.SetUint(uint64(x))
+ case reflect.Float64:
+ elem.SetFloat(float64(math.Float64frombits(x)))
+ }
+}
+
+func (p word64Slice) Len() int {
+ return p.v.Len()
+}
+
+func (p word64Slice) Index(i int) uint64 {
+ elem := p.v.Index(i)
+ switch elem.Kind() {
+ case reflect.Int64:
+ return uint64(elem.Int())
+ case reflect.Uint64:
+ return uint64(elem.Uint())
+ case reflect.Float64:
+ return math.Float64bits(float64(elem.Float()))
+ }
+ panic("unreachable")
+}
+
+func structPointer_Word64Slice(p structPointer, f field) word64Slice {
+ return word64Slice{structPointer_field(p, f)}
+}
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2016, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// +build appengine js
+
+package proto
+
+import (
+ "reflect"
+)
+
+func structPointer_FieldPointer(p structPointer, f field) structPointer {
+ panic("not implemented")
+}
+
+func appendStructPointer(base structPointer, f field, typ reflect.Type) structPointer {
+ panic("not implemented")
+}
+
+func structPointer_InterfaceAt(p structPointer, f field, t reflect.Type) interface{} {
+ panic("not implemented")
+}
+
+func structPointer_InterfaceRef(p structPointer, f field, t reflect.Type) interface{} {
+ panic("not implemented")
+}
+
+func structPointer_GetRefStructPointer(p structPointer, f field) structPointer {
+ panic("not implemented")
+}
+
+func structPointer_Add(p structPointer, size field) structPointer {
+ panic("not implemented")
+}
+
+func structPointer_Len(p structPointer, f field) int {
+ panic("not implemented")
+}
+
+func structPointer_GetSliceHeader(p structPointer, f field) *reflect.SliceHeader {
+ panic("not implemented")
+}
+
+func structPointer_Copy(oldptr structPointer, newptr structPointer, size int) {
+ panic("not implemented")
+}
+
+func structPointer_StructRefSlice(p structPointer, f field, size uintptr) *structRefSlice {
+ panic("not implemented")
+}
+
+type structRefSlice struct{}
+
+func (v *structRefSlice) Len() int {
+ panic("not implemented")
+}
+
+func (v *structRefSlice) Index(i int) structPointer {
+ panic("not implemented")
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2012 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// +build !appengine,!js
+
+// This file contains the implementation of the proto field accesses using package unsafe.
+
+package proto
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+// NOTE: These type_Foo functions would more idiomatically be methods,
+// but Go does not allow methods on pointer types, and we must preserve
+// some pointer type for the garbage collector. We use these
+// funcs with clunky names as our poor approximation to methods.
+//
+// An alternative would be
+// type structPointer struct { p unsafe.Pointer }
+// but that does not registerize as well.
+
+// A structPointer is a pointer to a struct.
+type structPointer unsafe.Pointer
+
+// toStructPointer returns a structPointer equivalent to the given reflect value.
+func toStructPointer(v reflect.Value) structPointer {
+ return structPointer(unsafe.Pointer(v.Pointer()))
+}
+
+// IsNil reports whether p is nil.
+func structPointer_IsNil(p structPointer) bool {
+ return p == nil
+}
+
+// Interface returns the struct pointer, assumed to have element type t,
+// as an interface value.
+func structPointer_Interface(p structPointer, t reflect.Type) interface{} {
+ return reflect.NewAt(t, unsafe.Pointer(p)).Interface()
+}
+
+// A field identifies a field in a struct, accessible from a structPointer.
+// In this implementation, a field is identified by its byte offset from the start of the struct.
+type field uintptr
+
+// toField returns a field equivalent to the given reflect field.
+func toField(f *reflect.StructField) field {
+ return field(f.Offset)
+}
+
+// invalidField is an invalid field identifier.
+const invalidField = ^field(0)
+
+// IsValid reports whether the field identifier is valid.
+func (f field) IsValid() bool {
+ return f != ^field(0)
+}
+
+// Bytes returns the address of a []byte field in the struct.
+func structPointer_Bytes(p structPointer, f field) *[]byte {
+ return (*[]byte)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// BytesSlice returns the address of a [][]byte field in the struct.
+func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
+ return (*[][]byte)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// Bool returns the address of a *bool field in the struct.
+func structPointer_Bool(p structPointer, f field) **bool {
+ return (**bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// BoolVal returns the address of a bool field in the struct.
+func structPointer_BoolVal(p structPointer, f field) *bool {
+ return (*bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// BoolSlice returns the address of a []bool field in the struct.
+func structPointer_BoolSlice(p structPointer, f field) *[]bool {
+ return (*[]bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// String returns the address of a *string field in the struct.
+func structPointer_String(p structPointer, f field) **string {
+ return (**string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// StringVal returns the address of a string field in the struct.
+func structPointer_StringVal(p structPointer, f field) *string {
+ return (*string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// StringSlice returns the address of a []string field in the struct.
+func structPointer_StringSlice(p structPointer, f field) *[]string {
+ return (*[]string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// ExtMap returns the address of an extension map field in the struct.
+func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
+ return (*XXX_InternalExtensions)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
+ return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// NewAt returns the reflect.Value for a pointer to a field in the struct.
+func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
+ return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f)))
+}
+
+// SetStructPointer writes a *struct field in the struct.
+func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
+ *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) = q
+}
+
+// GetStructPointer reads a *struct field in the struct.
+func structPointer_GetStructPointer(p structPointer, f field) structPointer {
+ return *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// StructPointerSlice the address of a []*struct field in the struct.
+func structPointer_StructPointerSlice(p structPointer, f field) *structPointerSlice {
+ return (*structPointerSlice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// A structPointerSlice represents a slice of pointers to structs (themselves submessages or groups).
+type structPointerSlice []structPointer
+
+func (v *structPointerSlice) Len() int { return len(*v) }
+func (v *structPointerSlice) Index(i int) structPointer { return (*v)[i] }
+func (v *structPointerSlice) Append(p structPointer) { *v = append(*v, p) }
+
+// A word32 is the address of a "pointer to 32-bit value" field.
+type word32 **uint32
+
+// IsNil reports whether *v is nil.
+func word32_IsNil(p word32) bool {
+ return *p == nil
+}
+
+// Set sets *v to point at a newly allocated word set to x.
+func word32_Set(p word32, o *Buffer, x uint32) {
+ if len(o.uint32s) == 0 {
+ o.uint32s = make([]uint32, uint32PoolSize)
+ }
+ o.uint32s[0] = x
+ *p = &o.uint32s[0]
+ o.uint32s = o.uint32s[1:]
+}
+
+// Get gets the value pointed at by *v.
+func word32_Get(p word32) uint32 {
+ return **p
+}
+
+// Word32 returns the address of a *int32, *uint32, *float32, or *enum field in the struct.
+func structPointer_Word32(p structPointer, f field) word32 {
+ return word32((**uint32)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+}
+
+// A word32Val is the address of a 32-bit value field.
+type word32Val *uint32
+
+// Set sets *p to x.
+func word32Val_Set(p word32Val, x uint32) {
+ *p = x
+}
+
+// Get gets the value pointed at by p.
+func word32Val_Get(p word32Val) uint32 {
+ return *p
+}
+
+// Word32Val returns the address of a *int32, *uint32, *float32, or *enum field in the struct.
+func structPointer_Word32Val(p structPointer, f field) word32Val {
+ return word32Val((*uint32)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+}
+
+// A word32Slice is a slice of 32-bit values.
+type word32Slice []uint32
+
+func (v *word32Slice) Append(x uint32) { *v = append(*v, x) }
+func (v *word32Slice) Len() int { return len(*v) }
+func (v *word32Slice) Index(i int) uint32 { return (*v)[i] }
+
+// Word32Slice returns the address of a []int32, []uint32, []float32, or []enum field in the struct.
+func structPointer_Word32Slice(p structPointer, f field) *word32Slice {
+ return (*word32Slice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// word64 is like word32 but for 64-bit values.
+type word64 **uint64
+
+func word64_Set(p word64, o *Buffer, x uint64) {
+ if len(o.uint64s) == 0 {
+ o.uint64s = make([]uint64, uint64PoolSize)
+ }
+ o.uint64s[0] = x
+ *p = &o.uint64s[0]
+ o.uint64s = o.uint64s[1:]
+}
+
+func word64_IsNil(p word64) bool {
+ return *p == nil
+}
+
+func word64_Get(p word64) uint64 {
+ return **p
+}
+
+func structPointer_Word64(p structPointer, f field) word64 {
+ return word64((**uint64)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+}
+
+// word64Val is like word32Val but for 64-bit values.
+type word64Val *uint64
+
+func word64Val_Set(p word64Val, o *Buffer, x uint64) {
+ *p = x
+}
+
+func word64Val_Get(p word64Val) uint64 {
+ return *p
+}
+
+func structPointer_Word64Val(p structPointer, f field) word64Val {
+ return word64Val((*uint64)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+}
+
+// word64Slice is like word32Slice but for 64-bit values.
+type word64Slice []uint64
+
+func (v *word64Slice) Append(x uint64) { *v = append(*v, x) }
+func (v *word64Slice) Len() int { return len(*v) }
+func (v *word64Slice) Index(i int) uint64 { return (*v)[i] }
+
+func structPointer_Word64Slice(p structPointer, f field) *word64Slice {
+ return (*word64Slice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// +build !appengine,!js
+
+// This file contains the implementation of the proto field accesses using package unsafe.
+
+package proto
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+func structPointer_InterfaceAt(p structPointer, f field, t reflect.Type) interface{} {
+ point := unsafe.Pointer(uintptr(p) + uintptr(f))
+ r := reflect.NewAt(t, point)
+ return r.Interface()
+}
+
+func structPointer_InterfaceRef(p structPointer, f field, t reflect.Type) interface{} {
+ point := unsafe.Pointer(uintptr(p) + uintptr(f))
+ r := reflect.NewAt(t, point)
+ if r.Elem().IsNil() {
+ return nil
+ }
+ return r.Elem().Interface()
+}
+
+func copyUintPtr(oldptr, newptr uintptr, size int) {
+ oldbytes := make([]byte, 0)
+ oldslice := (*reflect.SliceHeader)(unsafe.Pointer(&oldbytes))
+ oldslice.Data = oldptr
+ oldslice.Len = size
+ oldslice.Cap = size
+ newbytes := make([]byte, 0)
+ newslice := (*reflect.SliceHeader)(unsafe.Pointer(&newbytes))
+ newslice.Data = newptr
+ newslice.Len = size
+ newslice.Cap = size
+ copy(newbytes, oldbytes)
+}
+
+func structPointer_Copy(oldptr structPointer, newptr structPointer, size int) {
+ copyUintPtr(uintptr(oldptr), uintptr(newptr), size)
+}
+
+func appendStructPointer(base structPointer, f field, typ reflect.Type) structPointer {
+ size := typ.Elem().Size()
+
+ oldHeader := structPointer_GetSliceHeader(base, f)
+ oldSlice := reflect.NewAt(typ, unsafe.Pointer(oldHeader)).Elem()
+ newLen := oldHeader.Len + 1
+ newSlice := reflect.MakeSlice(typ, newLen, newLen)
+ reflect.Copy(newSlice, oldSlice)
+ bas := toStructPointer(newSlice)
+ oldHeader.Data = uintptr(bas)
+ oldHeader.Len = newLen
+ oldHeader.Cap = newLen
+
+ return structPointer(unsafe.Pointer(uintptr(unsafe.Pointer(bas)) + uintptr(uintptr(newLen-1)*size)))
+}
+
+func structPointer_FieldPointer(p structPointer, f field) structPointer {
+ return structPointer(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+func structPointer_GetRefStructPointer(p structPointer, f field) structPointer {
+ return structPointer((*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+}
+
+func structPointer_GetSliceHeader(p structPointer, f field) *reflect.SliceHeader {
+ return (*reflect.SliceHeader)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+func structPointer_Add(p structPointer, size field) structPointer {
+ return structPointer(unsafe.Pointer(uintptr(p) + uintptr(size)))
+}
+
+func structPointer_Len(p structPointer, f field) int {
+ return len(*(*[]interface{})(unsafe.Pointer(structPointer_GetRefStructPointer(p, f))))
+}
+
+func structPointer_StructRefSlice(p structPointer, f field, size uintptr) *structRefSlice {
+ return &structRefSlice{p: p, f: f, size: size}
+}
+
+// A structRefSlice represents a slice of structs (themselves submessages or groups).
+type structRefSlice struct {
+ p structPointer
+ f field
+ size uintptr
+}
+
+func (v *structRefSlice) Len() int {
+ return structPointer_Len(v.p, v.f)
+}
+
+func (v *structRefSlice) Index(i int) structPointer {
+ ss := structPointer_GetStructPointer(v.p, v.f)
+ ss1 := structPointer_GetRefStructPointer(ss, 0)
+ return structPointer_Add(ss1, field(uintptr(i)*v.size))
+}
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+/*
+ * Routines for encoding data into the wire format for protocol buffers.
+ */
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "reflect"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+)
+
+const debug bool = false
+
+// Constants that identify the encoding of a value on the wire.
+const (
+ WireVarint = 0
+ WireFixed64 = 1
+ WireBytes = 2
+ WireStartGroup = 3
+ WireEndGroup = 4
+ WireFixed32 = 5
+)
+
+const startSize = 10 // initial slice/string sizes
+
+// Encoders are defined in encode.go
+// An encoder outputs the full representation of a field, including its
+// tag and encoder type.
+type encoder func(p *Buffer, prop *Properties, base structPointer) error
+
+// A valueEncoder encodes a single integer in a particular encoding.
+type valueEncoder func(o *Buffer, x uint64) error
+
+// Sizers are defined in encode.go
+// A sizer returns the encoded size of a field, including its tag and encoder
+// type.
+type sizer func(prop *Properties, base structPointer) int
+
+// A valueSizer returns the encoded size of a single integer in a particular
+// encoding.
+type valueSizer func(x uint64) int
+
+// Decoders are defined in decode.go
+// A decoder creates a value from its wire representation.
+// Unrecognized subelements are saved in unrec.
+type decoder func(p *Buffer, prop *Properties, base structPointer) error
+
+// A valueDecoder decodes a single integer in a particular encoding.
+type valueDecoder func(o *Buffer) (x uint64, err error)
+
+// A oneofMarshaler does the marshaling for all oneof fields in a message.
+type oneofMarshaler func(Message, *Buffer) error
+
+// A oneofUnmarshaler does the unmarshaling for a oneof field in a message.
+type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error)
+
+// A oneofSizer does the sizing for all oneof fields in a message.
+type oneofSizer func(Message) int
+
+// tagMap is an optimization over map[int]int for typical protocol buffer
+// use-cases. Encoded protocol buffers are often in tag order with small tag
+// numbers.
+type tagMap struct {
+ fastTags []int
+ slowTags map[int]int
+}
+
+// tagMapFastLimit is the upper bound on the tag number that will be stored in
+// the tagMap slice rather than its map.
+const tagMapFastLimit = 1024
+
+func (p *tagMap) get(t int) (int, bool) {
+ if t > 0 && t < tagMapFastLimit {
+ if t >= len(p.fastTags) {
+ return 0, false
+ }
+ fi := p.fastTags[t]
+ return fi, fi >= 0
+ }
+ fi, ok := p.slowTags[t]
+ return fi, ok
+}
+
+func (p *tagMap) put(t int, fi int) {
+ if t > 0 && t < tagMapFastLimit {
+ for len(p.fastTags) < t+1 {
+ p.fastTags = append(p.fastTags, -1)
+ }
+ p.fastTags[t] = fi
+ return
+ }
+ if p.slowTags == nil {
+ p.slowTags = make(map[int]int)
+ }
+ p.slowTags[t] = fi
+}
+
+// StructProperties represents properties for all the fields of a struct.
+// decoderTags and decoderOrigNames should only be used by the decoder.
+type StructProperties struct {
+ Prop []*Properties // properties for each field
+ reqCount int // required count
+ decoderTags tagMap // map from proto tag to struct field number
+ decoderOrigNames map[string]int // map from original name to struct field number
+ order []int // list of struct field numbers in tag order
+ unrecField field // field id of the XXX_unrecognized []byte field
+ extendable bool // is this an extendable proto
+
+ oneofMarshaler oneofMarshaler
+ oneofUnmarshaler oneofUnmarshaler
+ oneofSizer oneofSizer
+ stype reflect.Type
+
+ // OneofTypes contains information about the oneof fields in this message.
+ // It is keyed by the original name of a field.
+ OneofTypes map[string]*OneofProperties
+}
+
+// OneofProperties represents information about a specific field in a oneof.
+type OneofProperties struct {
+ Type reflect.Type // pointer to generated struct type for this oneof field
+ Field int // struct field number of the containing oneof in the message
+ Prop *Properties
+}
+
+// Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec.
+// See encode.go, (*Buffer).enc_struct.
+
+func (sp *StructProperties) Len() int { return len(sp.order) }
+func (sp *StructProperties) Less(i, j int) bool {
+ return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag
+}
+func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] }
+
+// Properties represents the protocol-specific behavior of a single struct field.
+type Properties struct {
+ Name string // name of the field, for error messages
+ OrigName string // original name before protocol compiler (always set)
+ JSONName string // name to use for JSON; determined by protoc
+ Wire string
+ WireType int
+ Tag int
+ Required bool
+ Optional bool
+ Repeated bool
+ Packed bool // relevant for repeated primitives only
+ Enum string // set for enum types only
+ proto3 bool // whether this is known to be a proto3 field; set for []byte only
+ oneof bool // whether this is a oneof field
+
+ Default string // default value
+ HasDefault bool // whether an explicit default was provided
+ CustomType string
+ StdTime bool
+ StdDuration bool
+
+ enc encoder
+ valEnc valueEncoder // set for bool and numeric types only
+ field field
+ tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType)
+ tagbuf [8]byte
+ stype reflect.Type // set for struct types only
+ sstype reflect.Type // set for slices of structs types only
+ ctype reflect.Type // set for custom types only
+ sprop *StructProperties // set for struct types only
+ isMarshaler bool
+ isUnmarshaler bool
+
+ mtype reflect.Type // set for map types only
+ mkeyprop *Properties // set for map types only
+ mvalprop *Properties // set for map types only
+
+ size sizer
+ valSize valueSizer // set for bool and numeric types only
+
+ dec decoder
+ valDec valueDecoder // set for bool and numeric types only
+
+ // If this is a packable field, this will be the decoder for the packed version of the field.
+ packedDec decoder
+}
+
+// String formats the properties in the protobuf struct field tag style.
+func (p *Properties) String() string {
+ s := p.Wire
+ s = ","
+ s += strconv.Itoa(p.Tag)
+ if p.Required {
+ s += ",req"
+ }
+ if p.Optional {
+ s += ",opt"
+ }
+ if p.Repeated {
+ s += ",rep"
+ }
+ if p.Packed {
+ s += ",packed"
+ }
+ s += ",name=" + p.OrigName
+ if p.JSONName != p.OrigName {
+ s += ",json=" + p.JSONName
+ }
+ if p.proto3 {
+ s += ",proto3"
+ }
+ if p.oneof {
+ s += ",oneof"
+ }
+ if len(p.Enum) > 0 {
+ s += ",enum=" + p.Enum
+ }
+ if p.HasDefault {
+ s += ",def=" + p.Default
+ }
+ return s
+}
+
+// Parse populates p by parsing a string in the protobuf struct field tag style.
+func (p *Properties) Parse(s string) {
+ // "bytes,49,opt,name=foo,def=hello!"
+ fields := strings.Split(s, ",") // breaks def=, but handled below.
+ if len(fields) < 2 {
+ fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s)
+ return
+ }
+
+ p.Wire = fields[0]
+ switch p.Wire {
+ case "varint":
+ p.WireType = WireVarint
+ p.valEnc = (*Buffer).EncodeVarint
+ p.valDec = (*Buffer).DecodeVarint
+ p.valSize = sizeVarint
+ case "fixed32":
+ p.WireType = WireFixed32
+ p.valEnc = (*Buffer).EncodeFixed32
+ p.valDec = (*Buffer).DecodeFixed32
+ p.valSize = sizeFixed32
+ case "fixed64":
+ p.WireType = WireFixed64
+ p.valEnc = (*Buffer).EncodeFixed64
+ p.valDec = (*Buffer).DecodeFixed64
+ p.valSize = sizeFixed64
+ case "zigzag32":
+ p.WireType = WireVarint
+ p.valEnc = (*Buffer).EncodeZigzag32
+ p.valDec = (*Buffer).DecodeZigzag32
+ p.valSize = sizeZigzag32
+ case "zigzag64":
+ p.WireType = WireVarint
+ p.valEnc = (*Buffer).EncodeZigzag64
+ p.valDec = (*Buffer).DecodeZigzag64
+ p.valSize = sizeZigzag64
+ case "bytes", "group":
+ p.WireType = WireBytes
+ // no numeric converter for non-numeric types
+ default:
+ fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s)
+ return
+ }
+
+ var err error
+ p.Tag, err = strconv.Atoi(fields[1])
+ if err != nil {
+ return
+ }
+
+ for i := 2; i < len(fields); i++ {
+ f := fields[i]
+ switch {
+ case f == "req":
+ p.Required = true
+ case f == "opt":
+ p.Optional = true
+ case f == "rep":
+ p.Repeated = true
+ case f == "packed":
+ p.Packed = true
+ case strings.HasPrefix(f, "name="):
+ p.OrigName = f[5:]
+ case strings.HasPrefix(f, "json="):
+ p.JSONName = f[5:]
+ case strings.HasPrefix(f, "enum="):
+ p.Enum = f[5:]
+ case f == "proto3":
+ p.proto3 = true
+ case f == "oneof":
+ p.oneof = true
+ case strings.HasPrefix(f, "def="):
+ p.HasDefault = true
+ p.Default = f[4:] // rest of string
+ if i+1 < len(fields) {
+ // Commas aren't escaped, and def is always last.
+ p.Default += "," + strings.Join(fields[i+1:], ",")
+ break
+ }
+ case strings.HasPrefix(f, "embedded="):
+ p.OrigName = strings.Split(f, "=")[1]
+ case strings.HasPrefix(f, "customtype="):
+ p.CustomType = strings.Split(f, "=")[1]
+ case f == "stdtime":
+ p.StdTime = true
+ case f == "stdduration":
+ p.StdDuration = true
+ }
+ }
+}
+
+func logNoSliceEnc(t1, t2 reflect.Type) {
+ fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2)
+}
+
+var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
+
+// Initialize the fields for encoding and decoding.
+func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
+ p.enc = nil
+ p.dec = nil
+ p.size = nil
+ isMap := typ.Kind() == reflect.Map
+ if len(p.CustomType) > 0 && !isMap {
+ p.setCustomEncAndDec(typ)
+ p.setTag(lockGetProp)
+ return
+ }
+ if p.StdTime && !isMap {
+ p.setTimeEncAndDec(typ)
+ p.setTag(lockGetProp)
+ return
+ }
+ if p.StdDuration && !isMap {
+ p.setDurationEncAndDec(typ)
+ p.setTag(lockGetProp)
+ return
+ }
+ switch t1 := typ; t1.Kind() {
+ default:
+ fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1)
+
+ // proto3 scalar types
+
+ case reflect.Bool:
+ if p.proto3 {
+ p.enc = (*Buffer).enc_proto3_bool
+ p.dec = (*Buffer).dec_proto3_bool
+ p.size = size_proto3_bool
+ } else {
+ p.enc = (*Buffer).enc_ref_bool
+ p.dec = (*Buffer).dec_proto3_bool
+ p.size = size_ref_bool
+ }
+ case reflect.Int32:
+ if p.proto3 {
+ p.enc = (*Buffer).enc_proto3_int32
+ p.dec = (*Buffer).dec_proto3_int32
+ p.size = size_proto3_int32
+ } else {
+ p.enc = (*Buffer).enc_ref_int32
+ p.dec = (*Buffer).dec_proto3_int32
+ p.size = size_ref_int32
+ }
+ case reflect.Uint32:
+ if p.proto3 {
+ p.enc = (*Buffer).enc_proto3_uint32
+ p.dec = (*Buffer).dec_proto3_int32 // can reuse
+ p.size = size_proto3_uint32
+ } else {
+ p.enc = (*Buffer).enc_ref_uint32
+ p.dec = (*Buffer).dec_proto3_int32 // can reuse
+ p.size = size_ref_uint32
+ }
+ case reflect.Int64, reflect.Uint64:
+ if p.proto3 {
+ p.enc = (*Buffer).enc_proto3_int64
+ p.dec = (*Buffer).dec_proto3_int64
+ p.size = size_proto3_int64
+ } else {
+ p.enc = (*Buffer).enc_ref_int64
+ p.dec = (*Buffer).dec_proto3_int64
+ p.size = size_ref_int64
+ }
+ case reflect.Float32:
+ if p.proto3 {
+ p.enc = (*Buffer).enc_proto3_uint32 // can just treat them as bits
+ p.dec = (*Buffer).dec_proto3_int32
+ p.size = size_proto3_uint32
+ } else {
+ p.enc = (*Buffer).enc_ref_uint32 // can just treat them as bits
+ p.dec = (*Buffer).dec_proto3_int32
+ p.size = size_ref_uint32
+ }
+ case reflect.Float64:
+ if p.proto3 {
+ p.enc = (*Buffer).enc_proto3_int64 // can just treat them as bits
+ p.dec = (*Buffer).dec_proto3_int64
+ p.size = size_proto3_int64
+ } else {
+ p.enc = (*Buffer).enc_ref_int64 // can just treat them as bits
+ p.dec = (*Buffer).dec_proto3_int64
+ p.size = size_ref_int64
+ }
+ case reflect.String:
+ if p.proto3 {
+ p.enc = (*Buffer).enc_proto3_string
+ p.dec = (*Buffer).dec_proto3_string
+ p.size = size_proto3_string
+ } else {
+ p.enc = (*Buffer).enc_ref_string
+ p.dec = (*Buffer).dec_proto3_string
+ p.size = size_ref_string
+ }
+ case reflect.Struct:
+ p.stype = typ
+ p.isMarshaler = isMarshaler(typ)
+ p.isUnmarshaler = isUnmarshaler(typ)
+ if p.Wire == "bytes" {
+ p.enc = (*Buffer).enc_ref_struct_message
+ p.dec = (*Buffer).dec_ref_struct_message
+ p.size = size_ref_struct_message
+ } else {
+ fmt.Fprintf(os.Stderr, "proto: no coders for struct %T\n", typ)
+ }
+
+ case reflect.Ptr:
+ switch t2 := t1.Elem(); t2.Kind() {
+ default:
+ fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2)
+ break
+ case reflect.Bool:
+ p.enc = (*Buffer).enc_bool
+ p.dec = (*Buffer).dec_bool
+ p.size = size_bool
+ case reflect.Int32:
+ p.enc = (*Buffer).enc_int32
+ p.dec = (*Buffer).dec_int32
+ p.size = size_int32
+ case reflect.Uint32:
+ p.enc = (*Buffer).enc_uint32
+ p.dec = (*Buffer).dec_int32 // can reuse
+ p.size = size_uint32
+ case reflect.Int64, reflect.Uint64:
+ p.enc = (*Buffer).enc_int64
+ p.dec = (*Buffer).dec_int64
+ p.size = size_int64
+ case reflect.Float32:
+ p.enc = (*Buffer).enc_uint32 // can just treat them as bits
+ p.dec = (*Buffer).dec_int32
+ p.size = size_uint32
+ case reflect.Float64:
+ p.enc = (*Buffer).enc_int64 // can just treat them as bits
+ p.dec = (*Buffer).dec_int64
+ p.size = size_int64
+ case reflect.String:
+ p.enc = (*Buffer).enc_string
+ p.dec = (*Buffer).dec_string
+ p.size = size_string
+ case reflect.Struct:
+ p.stype = t1.Elem()
+ p.isMarshaler = isMarshaler(t1)
+ p.isUnmarshaler = isUnmarshaler(t1)
+ if p.Wire == "bytes" {
+ p.enc = (*Buffer).enc_struct_message
+ p.dec = (*Buffer).dec_struct_message
+ p.size = size_struct_message
+ } else {
+ p.enc = (*Buffer).enc_struct_group
+ p.dec = (*Buffer).dec_struct_group
+ p.size = size_struct_group
+ }
+ }
+
+ case reflect.Slice:
+ switch t2 := t1.Elem(); t2.Kind() {
+ default:
+ logNoSliceEnc(t1, t2)
+ break
+ case reflect.Bool:
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_bool
+ p.size = size_slice_packed_bool
+ } else {
+ p.enc = (*Buffer).enc_slice_bool
+ p.size = size_slice_bool
+ }
+ p.dec = (*Buffer).dec_slice_bool
+ p.packedDec = (*Buffer).dec_slice_packed_bool
+ case reflect.Int32:
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_int32
+ p.size = size_slice_packed_int32
+ } else {
+ p.enc = (*Buffer).enc_slice_int32
+ p.size = size_slice_int32
+ }
+ p.dec = (*Buffer).dec_slice_int32
+ p.packedDec = (*Buffer).dec_slice_packed_int32
+ case reflect.Uint32:
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_uint32
+ p.size = size_slice_packed_uint32
+ } else {
+ p.enc = (*Buffer).enc_slice_uint32
+ p.size = size_slice_uint32
+ }
+ p.dec = (*Buffer).dec_slice_int32
+ p.packedDec = (*Buffer).dec_slice_packed_int32
+ case reflect.Int64, reflect.Uint64:
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_int64
+ p.size = size_slice_packed_int64
+ } else {
+ p.enc = (*Buffer).enc_slice_int64
+ p.size = size_slice_int64
+ }
+ p.dec = (*Buffer).dec_slice_int64
+ p.packedDec = (*Buffer).dec_slice_packed_int64
+ case reflect.Uint8:
+ p.dec = (*Buffer).dec_slice_byte
+ if p.proto3 {
+ p.enc = (*Buffer).enc_proto3_slice_byte
+ p.size = size_proto3_slice_byte
+ } else {
+ p.enc = (*Buffer).enc_slice_byte
+ p.size = size_slice_byte
+ }
+ case reflect.Float32, reflect.Float64:
+ switch t2.Bits() {
+ case 32:
+ // can just treat them as bits
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_uint32
+ p.size = size_slice_packed_uint32
+ } else {
+ p.enc = (*Buffer).enc_slice_uint32
+ p.size = size_slice_uint32
+ }
+ p.dec = (*Buffer).dec_slice_int32
+ p.packedDec = (*Buffer).dec_slice_packed_int32
+ case 64:
+ // can just treat them as bits
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_int64
+ p.size = size_slice_packed_int64
+ } else {
+ p.enc = (*Buffer).enc_slice_int64
+ p.size = size_slice_int64
+ }
+ p.dec = (*Buffer).dec_slice_int64
+ p.packedDec = (*Buffer).dec_slice_packed_int64
+ default:
+ logNoSliceEnc(t1, t2)
+ break
+ }
+ case reflect.String:
+ p.enc = (*Buffer).enc_slice_string
+ p.dec = (*Buffer).dec_slice_string
+ p.size = size_slice_string
+ case reflect.Ptr:
+ switch t3 := t2.Elem(); t3.Kind() {
+ default:
+ fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3)
+ break
+ case reflect.Struct:
+ p.stype = t2.Elem()
+ p.isMarshaler = isMarshaler(t2)
+ p.isUnmarshaler = isUnmarshaler(t2)
+ if p.Wire == "bytes" {
+ p.enc = (*Buffer).enc_slice_struct_message
+ p.dec = (*Buffer).dec_slice_struct_message
+ p.size = size_slice_struct_message
+ } else {
+ p.enc = (*Buffer).enc_slice_struct_group
+ p.dec = (*Buffer).dec_slice_struct_group
+ p.size = size_slice_struct_group
+ }
+ }
+ case reflect.Slice:
+ switch t2.Elem().Kind() {
+ default:
+ fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem())
+ break
+ case reflect.Uint8:
+ p.enc = (*Buffer).enc_slice_slice_byte
+ p.dec = (*Buffer).dec_slice_slice_byte
+ p.size = size_slice_slice_byte
+ }
+ case reflect.Struct:
+ p.setSliceOfNonPointerStructs(t1)
+ }
+
+ case reflect.Map:
+ p.enc = (*Buffer).enc_new_map
+ p.dec = (*Buffer).dec_new_map
+ p.size = size_new_map
+
+ p.mtype = t1
+ p.mkeyprop = &Properties{}
+ p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
+ p.mvalprop = &Properties{}
+ vtype := p.mtype.Elem()
+ if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice {
+ // The value type is not a message (*T) or bytes ([]byte),
+ // so we need encoders for the pointer to this type.
+ vtype = reflect.PtrTo(vtype)
+ }
+
+ p.mvalprop.CustomType = p.CustomType
+ p.mvalprop.StdDuration = p.StdDuration
+ p.mvalprop.StdTime = p.StdTime
+ p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
+ }
+ p.setTag(lockGetProp)
+}
+
+func (p *Properties) setTag(lockGetProp bool) {
+ // precalculate tag code
+ wire := p.WireType
+ if p.Packed {
+ wire = WireBytes
+ }
+ x := uint32(p.Tag)<<3 | uint32(wire)
+ i := 0
+ for i = 0; x > 127; i++ {
+ p.tagbuf[i] = 0x80 | uint8(x&0x7F)
+ x >>= 7
+ }
+ p.tagbuf[i] = uint8(x)
+ p.tagcode = p.tagbuf[0 : i+1]
+
+ if p.stype != nil {
+ if lockGetProp {
+ p.sprop = GetProperties(p.stype)
+ } else {
+ p.sprop = getPropertiesLocked(p.stype)
+ }
+ }
+}
+
+var (
+ marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
+ unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
+)
+
+// isMarshaler reports whether type t implements Marshaler.
+func isMarshaler(t reflect.Type) bool {
+ return t.Implements(marshalerType)
+}
+
+// isUnmarshaler reports whether type t implements Unmarshaler.
+func isUnmarshaler(t reflect.Type) bool {
+ return t.Implements(unmarshalerType)
+}
+
+// Init populates the properties from a protocol buffer struct tag.
+func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
+ p.init(typ, name, tag, f, true)
+}
+
+func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) {
+ // "bytes,49,opt,def=hello!"
+ p.Name = name
+ p.OrigName = name
+ if f != nil {
+ p.field = toField(f)
+ }
+ if tag == "" {
+ return
+ }
+ p.Parse(tag)
+ p.setEncAndDec(typ, f, lockGetProp)
+}
+
+var (
+ propertiesMu sync.RWMutex
+ propertiesMap = make(map[reflect.Type]*StructProperties)
+)
+
+// GetProperties returns the list of properties for the type represented by t.
+// t must represent a generated struct type of a protocol message.
+func GetProperties(t reflect.Type) *StructProperties {
+ if t.Kind() != reflect.Struct {
+ panic("proto: type must have kind struct")
+ }
+
+ // Most calls to GetProperties in a long-running program will be
+ // retrieving details for types we have seen before.
+ propertiesMu.RLock()
+ sprop, ok := propertiesMap[t]
+ propertiesMu.RUnlock()
+ if ok {
+ if collectStats {
+ stats.Chit++
+ }
+ return sprop
+ }
+
+ propertiesMu.Lock()
+ sprop = getPropertiesLocked(t)
+ propertiesMu.Unlock()
+ return sprop
+}
+
+// getPropertiesLocked requires that propertiesMu is held.
+func getPropertiesLocked(t reflect.Type) *StructProperties {
+ if prop, ok := propertiesMap[t]; ok {
+ if collectStats {
+ stats.Chit++
+ }
+ return prop
+ }
+ if collectStats {
+ stats.Cmiss++
+ }
+
+ prop := new(StructProperties)
+ // in case of recursive protos, fill this in now.
+ propertiesMap[t] = prop
+
+ // build properties
+ prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) ||
+ reflect.PtrTo(t).Implements(extendableProtoV1Type) ||
+ reflect.PtrTo(t).Implements(extendableBytesType)
+ prop.unrecField = invalidField
+ prop.Prop = make([]*Properties, t.NumField())
+ prop.order = make([]int, t.NumField())
+
+ isOneofMessage := false
+ for i := 0; i < t.NumField(); i++ {
+ f := t.Field(i)
+ p := new(Properties)
+ name := f.Name
+ p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
+
+ if f.Name == "XXX_InternalExtensions" { // special case
+ p.enc = (*Buffer).enc_exts
+ p.dec = nil // not needed
+ p.size = size_exts
+ } else if f.Name == "XXX_extensions" { // special case
+ if len(f.Tag.Get("protobuf")) > 0 {
+ p.enc = (*Buffer).enc_ext_slice_byte
+ p.dec = nil // not needed
+ p.size = size_ext_slice_byte
+ } else {
+ p.enc = (*Buffer).enc_map
+ p.dec = nil // not needed
+ p.size = size_map
+ }
+ } else if f.Name == "XXX_unrecognized" { // special case
+ prop.unrecField = toField(&f)
+ }
+ oneof := f.Tag.Get("protobuf_oneof") // special case
+ if oneof != "" {
+ isOneofMessage = true
+ // Oneof fields don't use the traditional protobuf tag.
+ p.OrigName = oneof
+ }
+ prop.Prop[i] = p
+ prop.order[i] = i
+ if debug {
+ print(i, " ", f.Name, " ", t.String(), " ")
+ if p.Tag > 0 {
+ print(p.String())
+ }
+ print("\n")
+ }
+ if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && oneof == "" {
+ fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]")
+ }
+ }
+
+ // Re-order prop.order.
+ sort.Sort(prop)
+
+ type oneofMessage interface {
+ XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
+ }
+ if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); isOneofMessage && ok {
+ var oots []interface{}
+ prop.oneofMarshaler, prop.oneofUnmarshaler, prop.oneofSizer, oots = om.XXX_OneofFuncs()
+ prop.stype = t
+
+ // Interpret oneof metadata.
+ prop.OneofTypes = make(map[string]*OneofProperties)
+ for _, oot := range oots {
+ oop := &OneofProperties{
+ Type: reflect.ValueOf(oot).Type(), // *T
+ Prop: new(Properties),
+ }
+ sft := oop.Type.Elem().Field(0)
+ oop.Prop.Name = sft.Name
+ oop.Prop.Parse(sft.Tag.Get("protobuf"))
+ // There will be exactly one interface field that
+ // this new value is assignable to.
+ for i := 0; i < t.NumField(); i++ {
+ f := t.Field(i)
+ if f.Type.Kind() != reflect.Interface {
+ continue
+ }
+ if !oop.Type.AssignableTo(f.Type) {
+ continue
+ }
+ oop.Field = i
+ break
+ }
+ prop.OneofTypes[oop.Prop.OrigName] = oop
+ }
+ }
+
+ // build required counts
+ // build tags
+ reqCount := 0
+ prop.decoderOrigNames = make(map[string]int)
+ for i, p := range prop.Prop {
+ if strings.HasPrefix(p.Name, "XXX_") {
+ // Internal fields should not appear in tags/origNames maps.
+ // They are handled specially when encoding and decoding.
+ continue
+ }
+ if p.Required {
+ reqCount++
+ }
+ prop.decoderTags.put(p.Tag, i)
+ prop.decoderOrigNames[p.OrigName] = i
+ }
+ prop.reqCount = reqCount
+
+ return prop
+}
+
+// Return the Properties object for the x[0]'th field of the structure.
+func propByIndex(t reflect.Type, x []int) *Properties {
+ if len(x) != 1 {
+ fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t)
+ return nil
+ }
+ prop := GetProperties(t)
+ return prop.Prop[x[0]]
+}
+
+// Get the address and type of a pointer to a struct from an interface.
+func getbase(pb Message) (t reflect.Type, b structPointer, err error) {
+ if pb == nil {
+ err = ErrNil
+ return
+ }
+ // get the reflect type of the pointer to the struct.
+ t = reflect.TypeOf(pb)
+ // get the address of the struct.
+ value := reflect.ValueOf(pb)
+ b = toStructPointer(value)
+ return
+}
+
+// A global registry of enum types.
+// The generated code will register the generated maps by calling RegisterEnum.
+
+var enumValueMaps = make(map[string]map[string]int32)
+var enumStringMaps = make(map[string]map[int32]string)
+
+// RegisterEnum is called from the generated code to install the enum descriptor
+// maps into the global table to aid parsing text format protocol buffers.
+func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) {
+ if _, ok := enumValueMaps[typeName]; ok {
+ panic("proto: duplicate enum registered: " + typeName)
+ }
+ enumValueMaps[typeName] = valueMap
+ if _, ok := enumStringMaps[typeName]; ok {
+ panic("proto: duplicate enum registered: " + typeName)
+ }
+ enumStringMaps[typeName] = unusedNameMap
+}
+
+// EnumValueMap returns the mapping from names to integers of the
+// enum type enumType, or a nil if not found.
+func EnumValueMap(enumType string) map[string]int32 {
+ return enumValueMaps[enumType]
+}
+
+// A registry of all linked message types.
+// The string is a fully-qualified proto name ("pkg.Message").
+var (
+ protoTypes = make(map[string]reflect.Type)
+ revProtoTypes = make(map[reflect.Type]string)
+)
+
+// RegisterType is called from generated code and maps from the fully qualified
+// proto name to the type (pointer to struct) of the protocol buffer.
+func RegisterType(x Message, name string) {
+ if _, ok := protoTypes[name]; ok {
+ // TODO: Some day, make this a panic.
+ log.Printf("proto: duplicate proto type registered: %s", name)
+ return
+ }
+ t := reflect.TypeOf(x)
+ protoTypes[name] = t
+ revProtoTypes[t] = name
+}
+
+// MessageName returns the fully-qualified proto name for the given message type.
+func MessageName(x Message) string {
+ type xname interface {
+ XXX_MessageName() string
+ }
+ if m, ok := x.(xname); ok {
+ return m.XXX_MessageName()
+ }
+ return revProtoTypes[reflect.TypeOf(x)]
+}
+
+// MessageType returns the message type (pointer to struct) for a named message.
+func MessageType(name string) reflect.Type { return protoTypes[name] }
+
+// A registry of all linked proto files.
+var (
+ protoFiles = make(map[string][]byte) // file name => fileDescriptor
+)
+
+// RegisterFile is called from generated code and maps from the
+// full file name of a .proto file to its compressed FileDescriptorProto.
+func RegisterFile(filename string, fileDescriptor []byte) {
+ protoFiles[filename] = fileDescriptor
+}
+
+// FileDescriptor returns the compressed FileDescriptorProto for a .proto file.
+func FileDescriptor(filename string) []byte { return protoFiles[filename] }
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+import (
+ "fmt"
+ "os"
+ "reflect"
+)
+
+func (p *Properties) setCustomEncAndDec(typ reflect.Type) {
+ p.ctype = typ
+ if p.Repeated {
+ p.enc = (*Buffer).enc_custom_slice_bytes
+ p.dec = (*Buffer).dec_custom_slice_bytes
+ p.size = size_custom_slice_bytes
+ } else if typ.Kind() == reflect.Ptr {
+ p.enc = (*Buffer).enc_custom_bytes
+ p.dec = (*Buffer).dec_custom_bytes
+ p.size = size_custom_bytes
+ } else {
+ p.enc = (*Buffer).enc_custom_ref_bytes
+ p.dec = (*Buffer).dec_custom_ref_bytes
+ p.size = size_custom_ref_bytes
+ }
+}
+
+func (p *Properties) setDurationEncAndDec(typ reflect.Type) {
+ if p.Repeated {
+ if typ.Elem().Kind() == reflect.Ptr {
+ p.enc = (*Buffer).enc_slice_duration
+ p.dec = (*Buffer).dec_slice_duration
+ p.size = size_slice_duration
+ } else {
+ p.enc = (*Buffer).enc_slice_ref_duration
+ p.dec = (*Buffer).dec_slice_ref_duration
+ p.size = size_slice_ref_duration
+ }
+ } else if typ.Kind() == reflect.Ptr {
+ p.enc = (*Buffer).enc_duration
+ p.dec = (*Buffer).dec_duration
+ p.size = size_duration
+ } else {
+ p.enc = (*Buffer).enc_ref_duration
+ p.dec = (*Buffer).dec_ref_duration
+ p.size = size_ref_duration
+ }
+}
+
+func (p *Properties) setTimeEncAndDec(typ reflect.Type) {
+ if p.Repeated {
+ if typ.Elem().Kind() == reflect.Ptr {
+ p.enc = (*Buffer).enc_slice_time
+ p.dec = (*Buffer).dec_slice_time
+ p.size = size_slice_time
+ } else {
+ p.enc = (*Buffer).enc_slice_ref_time
+ p.dec = (*Buffer).dec_slice_ref_time
+ p.size = size_slice_ref_time
+ }
+ } else if typ.Kind() == reflect.Ptr {
+ p.enc = (*Buffer).enc_time
+ p.dec = (*Buffer).dec_time
+ p.size = size_time
+ } else {
+ p.enc = (*Buffer).enc_ref_time
+ p.dec = (*Buffer).dec_ref_time
+ p.size = size_ref_time
+ }
+
+}
+
+func (p *Properties) setSliceOfNonPointerStructs(typ reflect.Type) {
+ t2 := typ.Elem()
+ p.sstype = typ
+ p.stype = t2
+ p.isMarshaler = isMarshaler(t2)
+ p.isUnmarshaler = isUnmarshaler(t2)
+ p.enc = (*Buffer).enc_slice_ref_struct_message
+ p.dec = (*Buffer).dec_slice_ref_struct_message
+ p.size = size_slice_ref_struct_message
+ if p.Wire != "bytes" {
+ fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T \n", typ, t2)
+ }
+}
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+import (
+ "fmt"
+ "io"
+)
+
+func Skip(data []byte) (n int, err error) {
+ l := len(data)
+ index := 0
+ for index < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if index >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := data[index]
+ index++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for {
+ if index >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ index++
+ if data[index-1] < 0x80 {
+ break
+ }
+ }
+ return index, nil
+ case 1:
+ index += 8
+ return index, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if index >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := data[index]
+ index++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ index += length
+ return index, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = index
+ for shift := uint(0); ; shift += 7 {
+ if index >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := data[index]
+ index++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := Skip(data[start:])
+ if err != nil {
+ return 0, err
+ }
+ index = start + next
+ }
+ return index, nil
+ case 4:
+ return index, nil
+ case 5:
+ index += 4
+ return index, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+// Functions for writing the text protocol buffer format.
+
+import (
+ "bufio"
+ "bytes"
+ "encoding"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "math"
+ "reflect"
+ "sort"
+ "strings"
+ "sync"
+ "time"
+)
+
+var (
+ newline = []byte("\n")
+ spaces = []byte(" ")
+ gtNewline = []byte(">\n")
+ endBraceNewline = []byte("}\n")
+ backslashN = []byte{'\\', 'n'}
+ backslashR = []byte{'\\', 'r'}
+ backslashT = []byte{'\\', 't'}
+ backslashDQ = []byte{'\\', '"'}
+ backslashBS = []byte{'\\', '\\'}
+ posInf = []byte("inf")
+ negInf = []byte("-inf")
+ nan = []byte("nan")
+)
+
+type writer interface {
+ io.Writer
+ WriteByte(byte) error
+}
+
+// textWriter is an io.Writer that tracks its indentation level.
+type textWriter struct {
+ ind int
+ complete bool // if the current position is a complete line
+ compact bool // whether to write out as a one-liner
+ w writer
+}
+
+func (w *textWriter) WriteString(s string) (n int, err error) {
+ if !strings.Contains(s, "\n") {
+ if !w.compact && w.complete {
+ w.writeIndent()
+ }
+ w.complete = false
+ return io.WriteString(w.w, s)
+ }
+ // WriteString is typically called without newlines, so this
+ // codepath and its copy are rare. We copy to avoid
+ // duplicating all of Write's logic here.
+ return w.Write([]byte(s))
+}
+
+func (w *textWriter) Write(p []byte) (n int, err error) {
+ newlines := bytes.Count(p, newline)
+ if newlines == 0 {
+ if !w.compact && w.complete {
+ w.writeIndent()
+ }
+ n, err = w.w.Write(p)
+ w.complete = false
+ return n, err
+ }
+
+ frags := bytes.SplitN(p, newline, newlines+1)
+ if w.compact {
+ for i, frag := range frags {
+ if i > 0 {
+ if err := w.w.WriteByte(' '); err != nil {
+ return n, err
+ }
+ n++
+ }
+ nn, err := w.w.Write(frag)
+ n += nn
+ if err != nil {
+ return n, err
+ }
+ }
+ return n, nil
+ }
+
+ for i, frag := range frags {
+ if w.complete {
+ w.writeIndent()
+ }
+ nn, err := w.w.Write(frag)
+ n += nn
+ if err != nil {
+ return n, err
+ }
+ if i+1 < len(frags) {
+ if err := w.w.WriteByte('\n'); err != nil {
+ return n, err
+ }
+ n++
+ }
+ }
+ w.complete = len(frags[len(frags)-1]) == 0
+ return n, nil
+}
+
+func (w *textWriter) WriteByte(c byte) error {
+ if w.compact && c == '\n' {
+ c = ' '
+ }
+ if !w.compact && w.complete {
+ w.writeIndent()
+ }
+ err := w.w.WriteByte(c)
+ w.complete = c == '\n'
+ return err
+}
+
+func (w *textWriter) indent() { w.ind++ }
+
+func (w *textWriter) unindent() {
+ if w.ind == 0 {
+ log.Print("proto: textWriter unindented too far")
+ return
+ }
+ w.ind--
+}
+
+func writeName(w *textWriter, props *Properties) error {
+ if _, err := w.WriteString(props.OrigName); err != nil {
+ return err
+ }
+ if props.Wire != "group" {
+ return w.WriteByte(':')
+ }
+ return nil
+}
+
+// raw is the interface satisfied by RawMessage.
+type raw interface {
+ Bytes() []byte
+}
+
+func requiresQuotes(u string) bool {
+ // When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
+ for _, ch := range u {
+ switch {
+ case ch == '.' || ch == '/' || ch == '_':
+ continue
+ case '0' <= ch && ch <= '9':
+ continue
+ case 'A' <= ch && ch <= 'Z':
+ continue
+ case 'a' <= ch && ch <= 'z':
+ continue
+ default:
+ return true
+ }
+ }
+ return false
+}
+
+// isAny reports whether sv is a google.protobuf.Any message
+func isAny(sv reflect.Value) bool {
+ type wkt interface {
+ XXX_WellKnownType() string
+ }
+ t, ok := sv.Addr().Interface().(wkt)
+ return ok && t.XXX_WellKnownType() == "Any"
+}
+
+// writeProto3Any writes an expanded google.protobuf.Any message.
+//
+// It returns (false, nil) if sv value can't be unmarshaled (e.g. because
+// required messages are not linked in).
+//
+// It returns (true, error) when sv was written in expanded format or an error
+// was encountered.
+func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) {
+ turl := sv.FieldByName("TypeUrl")
+ val := sv.FieldByName("Value")
+ if !turl.IsValid() || !val.IsValid() {
+ return true, errors.New("proto: invalid google.protobuf.Any message")
+ }
+
+ b, ok := val.Interface().([]byte)
+ if !ok {
+ return true, errors.New("proto: invalid google.protobuf.Any message")
+ }
+
+ parts := strings.Split(turl.String(), "/")
+ mt := MessageType(parts[len(parts)-1])
+ if mt == nil {
+ return false, nil
+ }
+ m := reflect.New(mt.Elem())
+ if err := Unmarshal(b, m.Interface().(Message)); err != nil {
+ return false, nil
+ }
+ w.Write([]byte("["))
+ u := turl.String()
+ if requiresQuotes(u) {
+ writeString(w, u)
+ } else {
+ w.Write([]byte(u))
+ }
+ if w.compact {
+ w.Write([]byte("]:<"))
+ } else {
+ w.Write([]byte("]: <\n"))
+ w.ind++
+ }
+ if err := tm.writeStruct(w, m.Elem()); err != nil {
+ return true, err
+ }
+ if w.compact {
+ w.Write([]byte("> "))
+ } else {
+ w.ind--
+ w.Write([]byte(">\n"))
+ }
+ return true, nil
+}
+
+func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
+ if tm.ExpandAny && isAny(sv) {
+ if canExpand, err := tm.writeProto3Any(w, sv); canExpand {
+ return err
+ }
+ }
+ st := sv.Type()
+ sprops := GetProperties(st)
+ for i := 0; i < sv.NumField(); i++ {
+ fv := sv.Field(i)
+ props := sprops.Prop[i]
+ name := st.Field(i).Name
+
+ if strings.HasPrefix(name, "XXX_") {
+ // There are two XXX_ fields:
+ // XXX_unrecognized []byte
+ // XXX_extensions map[int32]proto.Extension
+ // The first is handled here;
+ // the second is handled at the bottom of this function.
+ if name == "XXX_unrecognized" && !fv.IsNil() {
+ if err := writeUnknownStruct(w, fv.Interface().([]byte)); err != nil {
+ return err
+ }
+ }
+ continue
+ }
+ if fv.Kind() == reflect.Ptr && fv.IsNil() {
+ // Field not filled in. This could be an optional field or
+ // a required field that wasn't filled in. Either way, there
+ // isn't anything we can show for it.
+ continue
+ }
+ if fv.Kind() == reflect.Slice && fv.IsNil() {
+ // Repeated field that is empty, or a bytes field that is unused.
+ continue
+ }
+
+ if props.Repeated && fv.Kind() == reflect.Slice {
+ // Repeated field.
+ for j := 0; j < fv.Len(); j++ {
+ if err := writeName(w, props); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ v := fv.Index(j)
+ if v.Kind() == reflect.Ptr && v.IsNil() {
+ // A nil message in a repeated field is not valid,
+ // but we can handle that more gracefully than panicking.
+ if _, err := w.Write([]byte("<nil>\n")); err != nil {
+ return err
+ }
+ continue
+ }
+ if len(props.Enum) > 0 {
+ if err := tm.writeEnum(w, v, props); err != nil {
+ return err
+ }
+ } else if err := tm.writeAny(w, v, props); err != nil {
+ return err
+ }
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ continue
+ }
+ if fv.Kind() == reflect.Map {
+ // Map fields are rendered as a repeated struct with key/value fields.
+ keys := fv.MapKeys()
+ sort.Sort(mapKeys(keys))
+ for _, key := range keys {
+ val := fv.MapIndex(key)
+ if err := writeName(w, props); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ // open struct
+ if err := w.WriteByte('<'); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ w.indent()
+ // key
+ if _, err := w.WriteString("key:"); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ if err := tm.writeAny(w, key, props.mkeyprop); err != nil {
+ return err
+ }
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ // nil values aren't legal, but we can avoid panicking because of them.
+ if val.Kind() != reflect.Ptr || !val.IsNil() {
+ // value
+ if _, err := w.WriteString("value:"); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ if err := tm.writeAny(w, val, props.mvalprop); err != nil {
+ return err
+ }
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ // close struct
+ w.unindent()
+ if err := w.WriteByte('>'); err != nil {
+ return err
+ }
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ continue
+ }
+ if props.proto3 && fv.Kind() == reflect.Slice && fv.Len() == 0 {
+ // empty bytes field
+ continue
+ }
+ if props.proto3 && fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice {
+ // proto3 non-repeated scalar field; skip if zero value
+ if isProto3Zero(fv) {
+ continue
+ }
+ }
+
+ if fv.Kind() == reflect.Interface {
+ // Check if it is a oneof.
+ if st.Field(i).Tag.Get("protobuf_oneof") != "" {
+ // fv is nil, or holds a pointer to generated struct.
+ // That generated struct has exactly one field,
+ // which has a protobuf struct tag.
+ if fv.IsNil() {
+ continue
+ }
+ inner := fv.Elem().Elem() // interface -> *T -> T
+ tag := inner.Type().Field(0).Tag.Get("protobuf")
+ props = new(Properties) // Overwrite the outer props var, but not its pointee.
+ props.Parse(tag)
+ // Write the value in the oneof, not the oneof itself.
+ fv = inner.Field(0)
+
+ // Special case to cope with malformed messages gracefully:
+ // If the value in the oneof is a nil pointer, don't panic
+ // in writeAny.
+ if fv.Kind() == reflect.Ptr && fv.IsNil() {
+ // Use errors.New so writeAny won't render quotes.
+ msg := errors.New("/* nil */")
+ fv = reflect.ValueOf(&msg).Elem()
+ }
+ }
+ }
+
+ if err := writeName(w, props); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ if b, ok := fv.Interface().(raw); ok {
+ if err := writeRaw(w, b.Bytes()); err != nil {
+ return err
+ }
+ continue
+ }
+
+ if len(props.Enum) > 0 {
+ if err := tm.writeEnum(w, fv, props); err != nil {
+ return err
+ }
+ } else if err := tm.writeAny(w, fv, props); err != nil {
+ return err
+ }
+
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+
+ // Extensions (the XXX_extensions field).
+ pv := sv
+ if pv.CanAddr() {
+ pv = sv.Addr()
+ } else {
+ pv = reflect.New(sv.Type())
+ pv.Elem().Set(sv)
+ }
+ if pv.Type().Implements(extensionRangeType) {
+ if err := tm.writeExtensions(w, pv); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// writeRaw writes an uninterpreted raw message.
+func writeRaw(w *textWriter, b []byte) error {
+ if err := w.WriteByte('<'); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ w.indent()
+ if err := writeUnknownStruct(w, b); err != nil {
+ return err
+ }
+ w.unindent()
+ if err := w.WriteByte('>'); err != nil {
+ return err
+ }
+ return nil
+}
+
+// writeAny writes an arbitrary field.
+func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
+ v = reflect.Indirect(v)
+
+ if props != nil {
+ if len(props.CustomType) > 0 {
+ custom, ok := v.Interface().(Marshaler)
+ if ok {
+ data, err := custom.Marshal()
+ if err != nil {
+ return err
+ }
+ if err := writeString(w, string(data)); err != nil {
+ return err
+ }
+ return nil
+ }
+ } else if props.StdTime {
+ t, ok := v.Interface().(time.Time)
+ if !ok {
+ return fmt.Errorf("stdtime is not time.Time, but %T", v.Interface())
+ }
+ tproto, err := timestampProto(t)
+ if err != nil {
+ return err
+ }
+ props.StdTime = false
+ err = tm.writeAny(w, reflect.ValueOf(tproto), props)
+ props.StdTime = true
+ return err
+ } else if props.StdDuration {
+ d, ok := v.Interface().(time.Duration)
+ if !ok {
+ return fmt.Errorf("stdtime is not time.Duration, but %T", v.Interface())
+ }
+ dproto := durationProto(d)
+ props.StdDuration = false
+ err := tm.writeAny(w, reflect.ValueOf(dproto), props)
+ props.StdDuration = true
+ return err
+ }
+ }
+
+ // Floats have special cases.
+ if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 {
+ x := v.Float()
+ var b []byte
+ switch {
+ case math.IsInf(x, 1):
+ b = posInf
+ case math.IsInf(x, -1):
+ b = negInf
+ case math.IsNaN(x):
+ b = nan
+ }
+ if b != nil {
+ _, err := w.Write(b)
+ return err
+ }
+ // Other values are handled below.
+ }
+
+ // We don't attempt to serialise every possible value type; only those
+ // that can occur in protocol buffers.
+ switch v.Kind() {
+ case reflect.Slice:
+ // Should only be a []byte; repeated fields are handled in writeStruct.
+ if err := writeString(w, string(v.Bytes())); err != nil {
+ return err
+ }
+ case reflect.String:
+ if err := writeString(w, v.String()); err != nil {
+ return err
+ }
+ case reflect.Struct:
+ // Required/optional group/message.
+ var bra, ket byte = '<', '>'
+ if props != nil && props.Wire == "group" {
+ bra, ket = '{', '}'
+ }
+ if err := w.WriteByte(bra); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ w.indent()
+ if etm, ok := v.Interface().(encoding.TextMarshaler); ok {
+ text, err := etm.MarshalText()
+ if err != nil {
+ return err
+ }
+ if _, err = w.Write(text); err != nil {
+ return err
+ }
+ } else if err := tm.writeStruct(w, v); err != nil {
+ return err
+ }
+ w.unindent()
+ if err := w.WriteByte(ket); err != nil {
+ return err
+ }
+ default:
+ _, err := fmt.Fprint(w, v.Interface())
+ return err
+ }
+ return nil
+}
+
+// equivalent to C's isprint.
+func isprint(c byte) bool {
+ return c >= 0x20 && c < 0x7f
+}
+
+// writeString writes a string in the protocol buffer text format.
+// It is similar to strconv.Quote except we don't use Go escape sequences,
+// we treat the string as a byte sequence, and we use octal escapes.
+// These differences are to maintain interoperability with the other
+// languages' implementations of the text format.
+func writeString(w *textWriter, s string) error {
+ // use WriteByte here to get any needed indent
+ if err := w.WriteByte('"'); err != nil {
+ return err
+ }
+ // Loop over the bytes, not the runes.
+ for i := 0; i < len(s); i++ {
+ var err error
+ // Divergence from C++: we don't escape apostrophes.
+ // There's no need to escape them, and the C++ parser
+ // copes with a naked apostrophe.
+ switch c := s[i]; c {
+ case '\n':
+ _, err = w.w.Write(backslashN)
+ case '\r':
+ _, err = w.w.Write(backslashR)
+ case '\t':
+ _, err = w.w.Write(backslashT)
+ case '"':
+ _, err = w.w.Write(backslashDQ)
+ case '\\':
+ _, err = w.w.Write(backslashBS)
+ default:
+ if isprint(c) {
+ err = w.w.WriteByte(c)
+ } else {
+ _, err = fmt.Fprintf(w.w, "\\%03o", c)
+ }
+ }
+ if err != nil {
+ return err
+ }
+ }
+ return w.WriteByte('"')
+}
+
+func writeUnknownStruct(w *textWriter, data []byte) (err error) {
+ if !w.compact {
+ if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil {
+ return err
+ }
+ }
+ b := NewBuffer(data)
+ for b.index < len(b.buf) {
+ x, err := b.DecodeVarint()
+ if err != nil {
+ _, ferr := fmt.Fprintf(w, "/* %v */\n", err)
+ return ferr
+ }
+ wire, tag := x&7, x>>3
+ if wire == WireEndGroup {
+ w.unindent()
+ if _, werr := w.Write(endBraceNewline); werr != nil {
+ return werr
+ }
+ continue
+ }
+ if _, ferr := fmt.Fprint(w, tag); ferr != nil {
+ return ferr
+ }
+ if wire != WireStartGroup {
+ if err = w.WriteByte(':'); err != nil {
+ return err
+ }
+ }
+ if !w.compact || wire == WireStartGroup {
+ if err = w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ switch wire {
+ case WireBytes:
+ buf, e := b.DecodeRawBytes(false)
+ if e == nil {
+ _, err = fmt.Fprintf(w, "%q", buf)
+ } else {
+ _, err = fmt.Fprintf(w, "/* %v */", e)
+ }
+ case WireFixed32:
+ x, err = b.DecodeFixed32()
+ err = writeUnknownInt(w, x, err)
+ case WireFixed64:
+ x, err = b.DecodeFixed64()
+ err = writeUnknownInt(w, x, err)
+ case WireStartGroup:
+ err = w.WriteByte('{')
+ w.indent()
+ case WireVarint:
+ x, err = b.DecodeVarint()
+ err = writeUnknownInt(w, x, err)
+ default:
+ _, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire)
+ }
+ if err != nil {
+ return err
+ }
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func writeUnknownInt(w *textWriter, x uint64, err error) error {
+ if err == nil {
+ _, err = fmt.Fprint(w, x)
+ } else {
+ _, err = fmt.Fprintf(w, "/* %v */", err)
+ }
+ return err
+}
+
+type int32Slice []int32
+
+func (s int32Slice) Len() int { return len(s) }
+func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
+func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// writeExtensions writes all the extensions in pv.
+// pv is assumed to be a pointer to a protocol message struct that is extendable.
+func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error {
+ emap := extensionMaps[pv.Type().Elem()]
+ e := pv.Interface().(Message)
+
+ var m map[int32]Extension
+ var mu sync.Locker
+ if em, ok := e.(extensionsBytes); ok {
+ eb := em.GetExtensions()
+ var err error
+ m, err = BytesToExtensionsMap(*eb)
+ if err != nil {
+ return err
+ }
+ mu = notLocker{}
+ } else if _, ok := e.(extendableProto); ok {
+ ep, _ := extendable(e)
+ m, mu = ep.extensionsRead()
+ if m == nil {
+ return nil
+ }
+ }
+
+ // Order the extensions by ID.
+ // This isn't strictly necessary, but it will give us
+ // canonical output, which will also make testing easier.
+
+ mu.Lock()
+ ids := make([]int32, 0, len(m))
+ for id := range m {
+ ids = append(ids, id)
+ }
+ sort.Sort(int32Slice(ids))
+ mu.Unlock()
+
+ for _, extNum := range ids {
+ ext := m[extNum]
+ var desc *ExtensionDesc
+ if emap != nil {
+ desc = emap[extNum]
+ }
+ if desc == nil {
+ // Unknown extension.
+ if err := writeUnknownStruct(w, ext.enc); err != nil {
+ return err
+ }
+ continue
+ }
+
+ pb, err := GetExtension(e, desc)
+ if err != nil {
+ return fmt.Errorf("failed getting extension: %v", err)
+ }
+
+ // Repeated extensions will appear as a slice.
+ if !desc.repeated() {
+ if err := tm.writeExtension(w, desc.Name, pb); err != nil {
+ return err
+ }
+ } else {
+ v := reflect.ValueOf(pb)
+ for i := 0; i < v.Len(); i++ {
+ if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil {
+ return err
+ }
+ }
+ }
+ }
+ return nil
+}
+
+func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error {
+ if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil {
+ return err
+ }
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (w *textWriter) writeIndent() {
+ if !w.complete {
+ return
+ }
+ remain := w.ind * 2
+ for remain > 0 {
+ n := remain
+ if n > len(spaces) {
+ n = len(spaces)
+ }
+ w.w.Write(spaces[:n])
+ remain -= n
+ }
+ w.complete = false
+}
+
+// TextMarshaler is a configurable text format marshaler.
+type TextMarshaler struct {
+ Compact bool // use compact text format (one line).
+ ExpandAny bool // expand google.protobuf.Any messages of known types
+}
+
+// Marshal writes a given protocol buffer in text format.
+// The only errors returned are from w.
+func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error {
+ val := reflect.ValueOf(pb)
+ if pb == nil || val.IsNil() {
+ w.Write([]byte("<nil>"))
+ return nil
+ }
+ var bw *bufio.Writer
+ ww, ok := w.(writer)
+ if !ok {
+ bw = bufio.NewWriter(w)
+ ww = bw
+ }
+ aw := &textWriter{
+ w: ww,
+ complete: true,
+ compact: tm.Compact,
+ }
+
+ if etm, ok := pb.(encoding.TextMarshaler); ok {
+ text, err := etm.MarshalText()
+ if err != nil {
+ return err
+ }
+ if _, err = aw.Write(text); err != nil {
+ return err
+ }
+ if bw != nil {
+ return bw.Flush()
+ }
+ return nil
+ }
+ // Dereference the received pointer so we don't have outer < and >.
+ v := reflect.Indirect(val)
+ if err := tm.writeStruct(aw, v); err != nil {
+ return err
+ }
+ if bw != nil {
+ return bw.Flush()
+ }
+ return nil
+}
+
+// Text is the same as Marshal, but returns the string directly.
+func (tm *TextMarshaler) Text(pb Message) string {
+ var buf bytes.Buffer
+ tm.Marshal(&buf, pb)
+ return buf.String()
+}
+
+var (
+ defaultTextMarshaler = TextMarshaler{}
+ compactTextMarshaler = TextMarshaler{Compact: true}
+)
+
+// TODO: consider removing some of the Marshal functions below.
+
+// MarshalText writes a given protocol buffer in text format.
+// The only errors returned are from w.
+func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) }
+
+// MarshalTextString is the same as MarshalText, but returns the string directly.
+func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) }
+
+// CompactText writes a given protocol buffer in compact text format (one line).
+func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) }
+
+// CompactTextString is the same as CompactText, but returns the string directly.
+func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) }
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+import (
+ "fmt"
+ "reflect"
+)
+
+func (tm *TextMarshaler) writeEnum(w *textWriter, v reflect.Value, props *Properties) error {
+ m, ok := enumStringMaps[props.Enum]
+ if !ok {
+ if err := tm.writeAny(w, v, props); err != nil {
+ return err
+ }
+ }
+ key := int32(0)
+ if v.Kind() == reflect.Ptr {
+ key = int32(v.Elem().Int())
+ } else {
+ key = int32(v.Int())
+ }
+ s, ok := m[key]
+ if !ok {
+ if err := tm.writeAny(w, v, props); err != nil {
+ return err
+ }
+ }
+ _, err := fmt.Fprint(w, s)
+ return err
+}
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+// Functions for parsing the Text protocol buffer format.
+// TODO: message sets.
+
+import (
+ "encoding"
+ "errors"
+ "fmt"
+ "reflect"
+ "strconv"
+ "strings"
+ "time"
+ "unicode/utf8"
+)
+
+// Error string emitted when deserializing Any and fields are already set
+const anyRepeatedlyUnpacked = "Any message unpacked multiple times, or %q already set"
+
+type ParseError struct {
+ Message string
+ Line int // 1-based line number
+ Offset int // 0-based byte offset from start of input
+}
+
+func (p *ParseError) Error() string {
+ if p.Line == 1 {
+ // show offset only for first line
+ return fmt.Sprintf("line 1.%d: %v", p.Offset, p.Message)
+ }
+ return fmt.Sprintf("line %d: %v", p.Line, p.Message)
+}
+
+type token struct {
+ value string
+ err *ParseError
+ line int // line number
+ offset int // byte number from start of input, not start of line
+ unquoted string // the unquoted version of value, if it was a quoted string
+}
+
+func (t *token) String() string {
+ if t.err == nil {
+ return fmt.Sprintf("%q (line=%d, offset=%d)", t.value, t.line, t.offset)
+ }
+ return fmt.Sprintf("parse error: %v", t.err)
+}
+
+type textParser struct {
+ s string // remaining input
+ done bool // whether the parsing is finished (success or error)
+ backed bool // whether back() was called
+ offset, line int
+ cur token
+}
+
+func newTextParser(s string) *textParser {
+ p := new(textParser)
+ p.s = s
+ p.line = 1
+ p.cur.line = 1
+ return p
+}
+
+func (p *textParser) errorf(format string, a ...interface{}) *ParseError {
+ pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset}
+ p.cur.err = pe
+ p.done = true
+ return pe
+}
+
+// Numbers and identifiers are matched by [-+._A-Za-z0-9]
+func isIdentOrNumberChar(c byte) bool {
+ switch {
+ case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z':
+ return true
+ case '0' <= c && c <= '9':
+ return true
+ }
+ switch c {
+ case '-', '+', '.', '_':
+ return true
+ }
+ return false
+}
+
+func isWhitespace(c byte) bool {
+ switch c {
+ case ' ', '\t', '\n', '\r':
+ return true
+ }
+ return false
+}
+
+func isQuote(c byte) bool {
+ switch c {
+ case '"', '\'':
+ return true
+ }
+ return false
+}
+
+func (p *textParser) skipWhitespace() {
+ i := 0
+ for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') {
+ if p.s[i] == '#' {
+ // comment; skip to end of line or input
+ for i < len(p.s) && p.s[i] != '\n' {
+ i++
+ }
+ if i == len(p.s) {
+ break
+ }
+ }
+ if p.s[i] == '\n' {
+ p.line++
+ }
+ i++
+ }
+ p.offset += i
+ p.s = p.s[i:len(p.s)]
+ if len(p.s) == 0 {
+ p.done = true
+ }
+}
+
+func (p *textParser) advance() {
+ // Skip whitespace
+ p.skipWhitespace()
+ if p.done {
+ return
+ }
+
+ // Start of non-whitespace
+ p.cur.err = nil
+ p.cur.offset, p.cur.line = p.offset, p.line
+ p.cur.unquoted = ""
+ switch p.s[0] {
+ case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/':
+ // Single symbol
+ p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)]
+ case '"', '\'':
+ // Quoted string
+ i := 1
+ for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' {
+ if p.s[i] == '\\' && i+1 < len(p.s) {
+ // skip escaped char
+ i++
+ }
+ i++
+ }
+ if i >= len(p.s) || p.s[i] != p.s[0] {
+ p.errorf("unmatched quote")
+ return
+ }
+ unq, err := unquoteC(p.s[1:i], rune(p.s[0]))
+ if err != nil {
+ p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err)
+ return
+ }
+ p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)]
+ p.cur.unquoted = unq
+ default:
+ i := 0
+ for i < len(p.s) && isIdentOrNumberChar(p.s[i]) {
+ i++
+ }
+ if i == 0 {
+ p.errorf("unexpected byte %#x", p.s[0])
+ return
+ }
+ p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)]
+ }
+ p.offset += len(p.cur.value)
+}
+
+var (
+ errBadUTF8 = errors.New("proto: bad UTF-8")
+ errBadHex = errors.New("proto: bad hexadecimal")
+)
+
+func unquoteC(s string, quote rune) (string, error) {
+ // This is based on C++'s tokenizer.cc.
+ // Despite its name, this is *not* parsing C syntax.
+ // For instance, "\0" is an invalid quoted string.
+
+ // Avoid allocation in trivial cases.
+ simple := true
+ for _, r := range s {
+ if r == '\\' || r == quote {
+ simple = false
+ break
+ }
+ }
+ if simple {
+ return s, nil
+ }
+
+ buf := make([]byte, 0, 3*len(s)/2)
+ for len(s) > 0 {
+ r, n := utf8.DecodeRuneInString(s)
+ if r == utf8.RuneError && n == 1 {
+ return "", errBadUTF8
+ }
+ s = s[n:]
+ if r != '\\' {
+ if r < utf8.RuneSelf {
+ buf = append(buf, byte(r))
+ } else {
+ buf = append(buf, string(r)...)
+ }
+ continue
+ }
+
+ ch, tail, err := unescape(s)
+ if err != nil {
+ return "", err
+ }
+ buf = append(buf, ch...)
+ s = tail
+ }
+ return string(buf), nil
+}
+
+func unescape(s string) (ch string, tail string, err error) {
+ r, n := utf8.DecodeRuneInString(s)
+ if r == utf8.RuneError && n == 1 {
+ return "", "", errBadUTF8
+ }
+ s = s[n:]
+ switch r {
+ case 'a':
+ return "\a", s, nil
+ case 'b':
+ return "\b", s, nil
+ case 'f':
+ return "\f", s, nil
+ case 'n':
+ return "\n", s, nil
+ case 'r':
+ return "\r", s, nil
+ case 't':
+ return "\t", s, nil
+ case 'v':
+ return "\v", s, nil
+ case '?':
+ return "?", s, nil // trigraph workaround
+ case '\'', '"', '\\':
+ return string(r), s, nil
+ case '0', '1', '2', '3', '4', '5', '6', '7', 'x', 'X':
+ if len(s) < 2 {
+ return "", "", fmt.Errorf(`\%c requires 2 following digits`, r)
+ }
+ base := 8
+ ss := s[:2]
+ s = s[2:]
+ if r == 'x' || r == 'X' {
+ base = 16
+ } else {
+ ss = string(r) + ss
+ }
+ i, err := strconv.ParseUint(ss, base, 8)
+ if err != nil {
+ return "", "", err
+ }
+ return string([]byte{byte(i)}), s, nil
+ case 'u', 'U':
+ n := 4
+ if r == 'U' {
+ n = 8
+ }
+ if len(s) < n {
+ return "", "", fmt.Errorf(`\%c requires %d digits`, r, n)
+ }
+
+ bs := make([]byte, n/2)
+ for i := 0; i < n; i += 2 {
+ a, ok1 := unhex(s[i])
+ b, ok2 := unhex(s[i+1])
+ if !ok1 || !ok2 {
+ return "", "", errBadHex
+ }
+ bs[i/2] = a<<4 | b
+ }
+ s = s[n:]
+ return string(bs), s, nil
+ }
+ return "", "", fmt.Errorf(`unknown escape \%c`, r)
+}
+
+// Adapted from src/pkg/strconv/quote.go.
+func unhex(b byte) (v byte, ok bool) {
+ switch {
+ case '0' <= b && b <= '9':
+ return b - '0', true
+ case 'a' <= b && b <= 'f':
+ return b - 'a' + 10, true
+ case 'A' <= b && b <= 'F':
+ return b - 'A' + 10, true
+ }
+ return 0, false
+}
+
+// Back off the parser by one token. Can only be done between calls to next().
+// It makes the next advance() a no-op.
+func (p *textParser) back() { p.backed = true }
+
+// Advances the parser and returns the new current token.
+func (p *textParser) next() *token {
+ if p.backed || p.done {
+ p.backed = false
+ return &p.cur
+ }
+ p.advance()
+ if p.done {
+ p.cur.value = ""
+ } else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) {
+ // Look for multiple quoted strings separated by whitespace,
+ // and concatenate them.
+ cat := p.cur
+ for {
+ p.skipWhitespace()
+ if p.done || !isQuote(p.s[0]) {
+ break
+ }
+ p.advance()
+ if p.cur.err != nil {
+ return &p.cur
+ }
+ cat.value += " " + p.cur.value
+ cat.unquoted += p.cur.unquoted
+ }
+ p.done = false // parser may have seen EOF, but we want to return cat
+ p.cur = cat
+ }
+ return &p.cur
+}
+
+func (p *textParser) consumeToken(s string) error {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value != s {
+ p.back()
+ return p.errorf("expected %q, found %q", s, tok.value)
+ }
+ return nil
+}
+
+// Return a RequiredNotSetError indicating which required field was not set.
+func (p *textParser) missingRequiredFieldError(sv reflect.Value) *RequiredNotSetError {
+ st := sv.Type()
+ sprops := GetProperties(st)
+ for i := 0; i < st.NumField(); i++ {
+ if !isNil(sv.Field(i)) {
+ continue
+ }
+
+ props := sprops.Prop[i]
+ if props.Required {
+ return &RequiredNotSetError{fmt.Sprintf("%v.%v", st, props.OrigName)}
+ }
+ }
+ return &RequiredNotSetError{fmt.Sprintf("%v.<unknown field name>", st)} // should not happen
+}
+
+// Returns the index in the struct for the named field, as well as the parsed tag properties.
+func structFieldByName(sprops *StructProperties, name string) (int, *Properties, bool) {
+ i, ok := sprops.decoderOrigNames[name]
+ if ok {
+ return i, sprops.Prop[i], true
+ }
+ return -1, nil, false
+}
+
+// Consume a ':' from the input stream (if the next token is a colon),
+// returning an error if a colon is needed but not present.
+func (p *textParser) checkForColon(props *Properties, typ reflect.Type) *ParseError {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value != ":" {
+ // Colon is optional when the field is a group or message.
+ needColon := true
+ switch props.Wire {
+ case "group":
+ needColon = false
+ case "bytes":
+ // A "bytes" field is either a message, a string, or a repeated field;
+ // those three become *T, *string and []T respectively, so we can check for
+ // this field being a pointer to a non-string.
+ if typ.Kind() == reflect.Ptr {
+ // *T or *string
+ if typ.Elem().Kind() == reflect.String {
+ break
+ }
+ } else if typ.Kind() == reflect.Slice {
+ // []T or []*T
+ if typ.Elem().Kind() != reflect.Ptr {
+ break
+ }
+ } else if typ.Kind() == reflect.String {
+ // The proto3 exception is for a string field,
+ // which requires a colon.
+ break
+ }
+ needColon = false
+ }
+ if needColon {
+ return p.errorf("expected ':', found %q", tok.value)
+ }
+ p.back()
+ }
+ return nil
+}
+
+func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
+ st := sv.Type()
+ sprops := GetProperties(st)
+ reqCount := sprops.reqCount
+ var reqFieldErr error
+ fieldSet := make(map[string]bool)
+ // A struct is a sequence of "name: value", terminated by one of
+ // '>' or '}', or the end of the input. A name may also be
+ // "[extension]" or "[type/url]".
+ //
+ // The whole struct can also be an expanded Any message, like:
+ // [type/url] < ... struct contents ... >
+ for {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value == terminator {
+ break
+ }
+ if tok.value == "[" {
+ // Looks like an extension or an Any.
+ //
+ // TODO: Check whether we need to handle
+ // namespace rooted names (e.g. ".something.Foo").
+ extName, err := p.consumeExtName()
+ if err != nil {
+ return err
+ }
+
+ if s := strings.LastIndex(extName, "/"); s >= 0 {
+ // If it contains a slash, it's an Any type URL.
+ messageName := extName[s+1:]
+ mt := MessageType(messageName)
+ if mt == nil {
+ return p.errorf("unrecognized message %q in google.protobuf.Any", messageName)
+ }
+ tok = p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ // consume an optional colon
+ if tok.value == ":" {
+ tok = p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ }
+ var terminator string
+ switch tok.value {
+ case "<":
+ terminator = ">"
+ case "{":
+ terminator = "}"
+ default:
+ return p.errorf("expected '{' or '<', found %q", tok.value)
+ }
+ v := reflect.New(mt.Elem())
+ if pe := p.readStruct(v.Elem(), terminator); pe != nil {
+ return pe
+ }
+ b, err := Marshal(v.Interface().(Message))
+ if err != nil {
+ return p.errorf("failed to marshal message of type %q: %v", messageName, err)
+ }
+ if fieldSet["type_url"] {
+ return p.errorf(anyRepeatedlyUnpacked, "type_url")
+ }
+ if fieldSet["value"] {
+ return p.errorf(anyRepeatedlyUnpacked, "value")
+ }
+ sv.FieldByName("TypeUrl").SetString(extName)
+ sv.FieldByName("Value").SetBytes(b)
+ fieldSet["type_url"] = true
+ fieldSet["value"] = true
+ continue
+ }
+
+ var desc *ExtensionDesc
+ // This could be faster, but it's functional.
+ // TODO: Do something smarter than a linear scan.
+ for _, d := range RegisteredExtensions(reflect.New(st).Interface().(Message)) {
+ if d.Name == extName {
+ desc = d
+ break
+ }
+ }
+ if desc == nil {
+ return p.errorf("unrecognized extension %q", extName)
+ }
+
+ props := &Properties{}
+ props.Parse(desc.Tag)
+
+ typ := reflect.TypeOf(desc.ExtensionType)
+ if err := p.checkForColon(props, typ); err != nil {
+ return err
+ }
+
+ rep := desc.repeated()
+
+ // Read the extension structure, and set it in
+ // the value we're constructing.
+ var ext reflect.Value
+ if !rep {
+ ext = reflect.New(typ).Elem()
+ } else {
+ ext = reflect.New(typ.Elem()).Elem()
+ }
+ if err := p.readAny(ext, props); err != nil {
+ if _, ok := err.(*RequiredNotSetError); !ok {
+ return err
+ }
+ reqFieldErr = err
+ }
+ ep := sv.Addr().Interface().(Message)
+ if !rep {
+ SetExtension(ep, desc, ext.Interface())
+ } else {
+ old, err := GetExtension(ep, desc)
+ var sl reflect.Value
+ if err == nil {
+ sl = reflect.ValueOf(old) // existing slice
+ } else {
+ sl = reflect.MakeSlice(typ, 0, 1)
+ }
+ sl = reflect.Append(sl, ext)
+ SetExtension(ep, desc, sl.Interface())
+ }
+ if err := p.consumeOptionalSeparator(); err != nil {
+ return err
+ }
+ continue
+ }
+
+ // This is a normal, non-extension field.
+ name := tok.value
+ var dst reflect.Value
+ fi, props, ok := structFieldByName(sprops, name)
+ if ok {
+ dst = sv.Field(fi)
+ } else if oop, ok := sprops.OneofTypes[name]; ok {
+ // It is a oneof.
+ props = oop.Prop
+ nv := reflect.New(oop.Type.Elem())
+ dst = nv.Elem().Field(0)
+ field := sv.Field(oop.Field)
+ if !field.IsNil() {
+ return p.errorf("field '%s' would overwrite already parsed oneof '%s'", name, sv.Type().Field(oop.Field).Name)
+ }
+ field.Set(nv)
+ }
+ if !dst.IsValid() {
+ return p.errorf("unknown field name %q in %v", name, st)
+ }
+
+ if dst.Kind() == reflect.Map {
+ // Consume any colon.
+ if err := p.checkForColon(props, dst.Type()); err != nil {
+ return err
+ }
+
+ // Construct the map if it doesn't already exist.
+ if dst.IsNil() {
+ dst.Set(reflect.MakeMap(dst.Type()))
+ }
+ key := reflect.New(dst.Type().Key()).Elem()
+ val := reflect.New(dst.Type().Elem()).Elem()
+
+ // The map entry should be this sequence of tokens:
+ // < key : KEY value : VALUE >
+ // However, implementations may omit key or value, and technically
+ // we should support them in any order. See b/28924776 for a time
+ // this went wrong.
+
+ tok := p.next()
+ var terminator string
+ switch tok.value {
+ case "<":
+ terminator = ">"
+ case "{":
+ terminator = "}"
+ default:
+ return p.errorf("expected '{' or '<', found %q", tok.value)
+ }
+ for {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value == terminator {
+ break
+ }
+ switch tok.value {
+ case "key":
+ if err := p.consumeToken(":"); err != nil {
+ return err
+ }
+ if err := p.readAny(key, props.mkeyprop); err != nil {
+ return err
+ }
+ if err := p.consumeOptionalSeparator(); err != nil {
+ return err
+ }
+ case "value":
+ if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil {
+ return err
+ }
+ if err := p.readAny(val, props.mvalprop); err != nil {
+ return err
+ }
+ if err := p.consumeOptionalSeparator(); err != nil {
+ return err
+ }
+ default:
+ p.back()
+ return p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value)
+ }
+ }
+
+ dst.SetMapIndex(key, val)
+ continue
+ }
+
+ // Check that it's not already set if it's not a repeated field.
+ if !props.Repeated && fieldSet[name] {
+ return p.errorf("non-repeated field %q was repeated", name)
+ }
+
+ if err := p.checkForColon(props, dst.Type()); err != nil {
+ return err
+ }
+
+ // Parse into the field.
+ fieldSet[name] = true
+ if err := p.readAny(dst, props); err != nil {
+ if _, ok := err.(*RequiredNotSetError); !ok {
+ return err
+ }
+ reqFieldErr = err
+ }
+ if props.Required {
+ reqCount--
+ }
+
+ if err := p.consumeOptionalSeparator(); err != nil {
+ return err
+ }
+
+ }
+
+ if reqCount > 0 {
+ return p.missingRequiredFieldError(sv)
+ }
+ return reqFieldErr
+}
+
+// consumeExtName consumes extension name or expanded Any type URL and the
+// following ']'. It returns the name or URL consumed.
+func (p *textParser) consumeExtName() (string, error) {
+ tok := p.next()
+ if tok.err != nil {
+ return "", tok.err
+ }
+
+ // If extension name or type url is quoted, it's a single token.
+ if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] {
+ name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0]))
+ if err != nil {
+ return "", err
+ }
+ return name, p.consumeToken("]")
+ }
+
+ // Consume everything up to "]"
+ var parts []string
+ for tok.value != "]" {
+ parts = append(parts, tok.value)
+ tok = p.next()
+ if tok.err != nil {
+ return "", p.errorf("unrecognized type_url or extension name: %s", tok.err)
+ }
+ }
+ return strings.Join(parts, ""), nil
+}
+
+// consumeOptionalSeparator consumes an optional semicolon or comma.
+// It is used in readStruct to provide backward compatibility.
+func (p *textParser) consumeOptionalSeparator() error {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value != ";" && tok.value != "," {
+ p.back()
+ }
+ return nil
+}
+
+func (p *textParser) readAny(v reflect.Value, props *Properties) error {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value == "" {
+ return p.errorf("unexpected EOF")
+ }
+ if len(props.CustomType) > 0 {
+ if props.Repeated {
+ t := reflect.TypeOf(v.Interface())
+ if t.Kind() == reflect.Slice {
+ tc := reflect.TypeOf(new(Marshaler))
+ ok := t.Elem().Implements(tc.Elem())
+ if ok {
+ fv := v
+ flen := fv.Len()
+ if flen == fv.Cap() {
+ nav := reflect.MakeSlice(v.Type(), flen, 2*flen+1)
+ reflect.Copy(nav, fv)
+ fv.Set(nav)
+ }
+ fv.SetLen(flen + 1)
+
+ // Read one.
+ p.back()
+ return p.readAny(fv.Index(flen), props)
+ }
+ }
+ }
+ if reflect.TypeOf(v.Interface()).Kind() == reflect.Ptr {
+ custom := reflect.New(props.ctype.Elem()).Interface().(Unmarshaler)
+ err := custom.Unmarshal([]byte(tok.unquoted))
+ if err != nil {
+ return p.errorf("%v %v: %v", err, v.Type(), tok.value)
+ }
+ v.Set(reflect.ValueOf(custom))
+ } else {
+ custom := reflect.New(reflect.TypeOf(v.Interface())).Interface().(Unmarshaler)
+ err := custom.Unmarshal([]byte(tok.unquoted))
+ if err != nil {
+ return p.errorf("%v %v: %v", err, v.Type(), tok.value)
+ }
+ v.Set(reflect.Indirect(reflect.ValueOf(custom)))
+ }
+ return nil
+ }
+ if props.StdTime {
+ fv := v
+ p.back()
+ props.StdTime = false
+ tproto := ×tamp{}
+ err := p.readAny(reflect.ValueOf(tproto).Elem(), props)
+ props.StdTime = true
+ if err != nil {
+ return err
+ }
+ tim, err := timestampFromProto(tproto)
+ if err != nil {
+ return err
+ }
+ if props.Repeated {
+ t := reflect.TypeOf(v.Interface())
+ if t.Kind() == reflect.Slice {
+ if t.Elem().Kind() == reflect.Ptr {
+ ts := fv.Interface().([]*time.Time)
+ ts = append(ts, &tim)
+ fv.Set(reflect.ValueOf(ts))
+ return nil
+ } else {
+ ts := fv.Interface().([]time.Time)
+ ts = append(ts, tim)
+ fv.Set(reflect.ValueOf(ts))
+ return nil
+ }
+ }
+ }
+ if reflect.TypeOf(v.Interface()).Kind() == reflect.Ptr {
+ v.Set(reflect.ValueOf(&tim))
+ } else {
+ v.Set(reflect.Indirect(reflect.ValueOf(&tim)))
+ }
+ return nil
+ }
+ if props.StdDuration {
+ fv := v
+ p.back()
+ props.StdDuration = false
+ dproto := &duration{}
+ err := p.readAny(reflect.ValueOf(dproto).Elem(), props)
+ props.StdDuration = true
+ if err != nil {
+ return err
+ }
+ dur, err := durationFromProto(dproto)
+ if err != nil {
+ return err
+ }
+ if props.Repeated {
+ t := reflect.TypeOf(v.Interface())
+ if t.Kind() == reflect.Slice {
+ if t.Elem().Kind() == reflect.Ptr {
+ ds := fv.Interface().([]*time.Duration)
+ ds = append(ds, &dur)
+ fv.Set(reflect.ValueOf(ds))
+ return nil
+ } else {
+ ds := fv.Interface().([]time.Duration)
+ ds = append(ds, dur)
+ fv.Set(reflect.ValueOf(ds))
+ return nil
+ }
+ }
+ }
+ if reflect.TypeOf(v.Interface()).Kind() == reflect.Ptr {
+ v.Set(reflect.ValueOf(&dur))
+ } else {
+ v.Set(reflect.Indirect(reflect.ValueOf(&dur)))
+ }
+ return nil
+ }
+ switch fv := v; fv.Kind() {
+ case reflect.Slice:
+ at := v.Type()
+ if at.Elem().Kind() == reflect.Uint8 {
+ // Special case for []byte
+ if tok.value[0] != '"' && tok.value[0] != '\'' {
+ // Deliberately written out here, as the error after
+ // this switch statement would write "invalid []byte: ...",
+ // which is not as user-friendly.
+ return p.errorf("invalid string: %v", tok.value)
+ }
+ bytes := []byte(tok.unquoted)
+ fv.Set(reflect.ValueOf(bytes))
+ return nil
+ }
+ // Repeated field.
+ if tok.value == "[" {
+ // Repeated field with list notation, like [1,2,3].
+ for {
+ fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
+ err := p.readAny(fv.Index(fv.Len()-1), props)
+ if err != nil {
+ return err
+ }
+ ntok := p.next()
+ if ntok.err != nil {
+ return ntok.err
+ }
+ if ntok.value == "]" {
+ break
+ }
+ if ntok.value != "," {
+ return p.errorf("Expected ']' or ',' found %q", ntok.value)
+ }
+ }
+ return nil
+ }
+ // One value of the repeated field.
+ p.back()
+ fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
+ return p.readAny(fv.Index(fv.Len()-1), props)
+ case reflect.Bool:
+ // true/1/t/True or false/f/0/False.
+ switch tok.value {
+ case "true", "1", "t", "True":
+ fv.SetBool(true)
+ return nil
+ case "false", "0", "f", "False":
+ fv.SetBool(false)
+ return nil
+ }
+ case reflect.Float32, reflect.Float64:
+ v := tok.value
+ // Ignore 'f' for compatibility with output generated by C++, but don't
+ // remove 'f' when the value is "-inf" or "inf".
+ if strings.HasSuffix(v, "f") && tok.value != "-inf" && tok.value != "inf" {
+ v = v[:len(v)-1]
+ }
+ if f, err := strconv.ParseFloat(v, fv.Type().Bits()); err == nil {
+ fv.SetFloat(f)
+ return nil
+ }
+ case reflect.Int32:
+ if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
+ fv.SetInt(x)
+ return nil
+ }
+
+ if len(props.Enum) == 0 {
+ break
+ }
+ m, ok := enumValueMaps[props.Enum]
+ if !ok {
+ break
+ }
+ x, ok := m[tok.value]
+ if !ok {
+ break
+ }
+ fv.SetInt(int64(x))
+ return nil
+ case reflect.Int64:
+ if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil {
+ fv.SetInt(x)
+ return nil
+ }
+
+ case reflect.Ptr:
+ // A basic field (indirected through pointer), or a repeated message/group
+ p.back()
+ fv.Set(reflect.New(fv.Type().Elem()))
+ return p.readAny(fv.Elem(), props)
+ case reflect.String:
+ if tok.value[0] == '"' || tok.value[0] == '\'' {
+ fv.SetString(tok.unquoted)
+ return nil
+ }
+ case reflect.Struct:
+ var terminator string
+ switch tok.value {
+ case "{":
+ terminator = "}"
+ case "<":
+ terminator = ">"
+ default:
+ return p.errorf("expected '{' or '<', found %q", tok.value)
+ }
+ // TODO: Handle nested messages which implement encoding.TextUnmarshaler.
+ return p.readStruct(fv, terminator)
+ case reflect.Uint32:
+ if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
+ fv.SetUint(uint64(x))
+ return nil
+ }
+ case reflect.Uint64:
+ if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil {
+ fv.SetUint(x)
+ return nil
+ }
+ }
+ return p.errorf("invalid %v: %v", v.Type(), tok.value)
+}
+
+// UnmarshalText reads a protocol buffer in Text format. UnmarshalText resets pb
+// before starting to unmarshal, so any existing data in pb is always removed.
+// If a required field is not set and no other error occurs,
+// UnmarshalText returns *RequiredNotSetError.
+func UnmarshalText(s string, pb Message) error {
+ if um, ok := pb.(encoding.TextUnmarshaler); ok {
+ err := um.UnmarshalText([]byte(s))
+ return err
+ }
+ pb.Reset()
+ v := reflect.ValueOf(pb)
+ if pe := newTextParser(s).readStruct(v.Elem(), ""); pe != nil {
+ return pe
+ }
+ return nil
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+// This file implements operations on google.protobuf.Timestamp.
+
+import (
+ "errors"
+ "fmt"
+ "time"
+)
+
+const (
+ // Seconds field of the earliest valid Timestamp.
+ // This is time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC).Unix().
+ minValidSeconds = -62135596800
+ // Seconds field just after the latest valid Timestamp.
+ // This is time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Unix().
+ maxValidSeconds = 253402300800
+)
+
+// validateTimestamp determines whether a Timestamp is valid.
+// A valid timestamp represents a time in the range
+// [0001-01-01, 10000-01-01) and has a Nanos field
+// in the range [0, 1e9).
+//
+// If the Timestamp is valid, validateTimestamp returns nil.
+// Otherwise, it returns an error that describes
+// the problem.
+//
+// Every valid Timestamp can be represented by a time.Time, but the converse is not true.
+func validateTimestamp(ts *timestamp) error {
+ if ts == nil {
+ return errors.New("timestamp: nil Timestamp")
+ }
+ if ts.Seconds < minValidSeconds {
+ return fmt.Errorf("timestamp: %#v before 0001-01-01", ts)
+ }
+ if ts.Seconds >= maxValidSeconds {
+ return fmt.Errorf("timestamp: %#v after 10000-01-01", ts)
+ }
+ if ts.Nanos < 0 || ts.Nanos >= 1e9 {
+ return fmt.Errorf("timestamp: %#v: nanos not in range [0, 1e9)", ts)
+ }
+ return nil
+}
+
+// TimestampFromProto converts a google.protobuf.Timestamp proto to a time.Time.
+// It returns an error if the argument is invalid.
+//
+// Unlike most Go functions, if Timestamp returns an error, the first return value
+// is not the zero time.Time. Instead, it is the value obtained from the
+// time.Unix function when passed the contents of the Timestamp, in the UTC
+// locale. This may or may not be a meaningful time; many invalid Timestamps
+// do map to valid time.Times.
+//
+// A nil Timestamp returns an error. The first return value in that case is
+// undefined.
+func timestampFromProto(ts *timestamp) (time.Time, error) {
+ // Don't return the zero value on error, because corresponds to a valid
+ // timestamp. Instead return whatever time.Unix gives us.
+ var t time.Time
+ if ts == nil {
+ t = time.Unix(0, 0).UTC() // treat nil like the empty Timestamp
+ } else {
+ t = time.Unix(ts.Seconds, int64(ts.Nanos)).UTC()
+ }
+ return t, validateTimestamp(ts)
+}
+
+// TimestampProto converts the time.Time to a google.protobuf.Timestamp proto.
+// It returns an error if the resulting Timestamp is invalid.
+func timestampProto(t time.Time) (*timestamp, error) {
+ seconds := t.Unix()
+ nanos := int32(t.Sub(time.Unix(seconds, 0)))
+ ts := ×tamp{
+ Seconds: seconds,
+ Nanos: nanos,
+ }
+ if err := validateTimestamp(ts); err != nil {
+ return nil, err
+ }
+ return ts, nil
+}
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2016, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+import (
+ "reflect"
+ "time"
+)
+
+var timeType = reflect.TypeOf((*time.Time)(nil)).Elem()
+
+type timestamp struct {
+ Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
+ Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
+}
+
+func (m *timestamp) Reset() { *m = timestamp{} }
+func (*timestamp) ProtoMessage() {}
+func (*timestamp) String() string { return "timestamp<string>" }
+
+func init() {
+ RegisterType((*timestamp)(nil), "gogo.protobuf.proto.timestamp")
+}
+
+func (o *Buffer) decTimestamp() (time.Time, error) {
+ b, err := o.DecodeRawBytes(true)
+ if err != nil {
+ return time.Time{}, err
+ }
+ tproto := ×tamp{}
+ if err := Unmarshal(b, tproto); err != nil {
+ return time.Time{}, err
+ }
+ return timestampFromProto(tproto)
+}
+
+func (o *Buffer) dec_time(p *Properties, base structPointer) error {
+ t, err := o.decTimestamp()
+ if err != nil {
+ return err
+ }
+ setPtrCustomType(base, p.field, &t)
+ return nil
+}
+
+func (o *Buffer) dec_ref_time(p *Properties, base structPointer) error {
+ t, err := o.decTimestamp()
+ if err != nil {
+ return err
+ }
+ setCustomType(base, p.field, &t)
+ return nil
+}
+
+func (o *Buffer) dec_slice_time(p *Properties, base structPointer) error {
+ t, err := o.decTimestamp()
+ if err != nil {
+ return err
+ }
+ newBas := appendStructPointer(base, p.field, reflect.SliceOf(reflect.PtrTo(timeType)))
+ var zero field
+ setPtrCustomType(newBas, zero, &t)
+ return nil
+}
+
+func (o *Buffer) dec_slice_ref_time(p *Properties, base structPointer) error {
+ t, err := o.decTimestamp()
+ if err != nil {
+ return err
+ }
+ newBas := appendStructPointer(base, p.field, reflect.SliceOf(timeType))
+ var zero field
+ setCustomType(newBas, zero, &t)
+ return nil
+}
+
+func size_time(p *Properties, base structPointer) (n int) {
+ structp := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(structp) {
+ return 0
+ }
+ tim := structPointer_Interface(structp, timeType).(*time.Time)
+ t, err := timestampProto(*tim)
+ if err != nil {
+ return 0
+ }
+ size := Size(t)
+ return size + sizeVarint(uint64(size)) + len(p.tagcode)
+}
+
+func (o *Buffer) enc_time(p *Properties, base structPointer) error {
+ structp := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(structp) {
+ return ErrNil
+ }
+ tim := structPointer_Interface(structp, timeType).(*time.Time)
+ t, err := timestampProto(*tim)
+ if err != nil {
+ return err
+ }
+ data, err := Marshal(t)
+ if err != nil {
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ return nil
+}
+
+func size_ref_time(p *Properties, base structPointer) (n int) {
+ tim := structPointer_InterfaceAt(base, p.field, timeType).(*time.Time)
+ t, err := timestampProto(*tim)
+ if err != nil {
+ return 0
+ }
+ size := Size(t)
+ return size + sizeVarint(uint64(size)) + len(p.tagcode)
+}
+
+func (o *Buffer) enc_ref_time(p *Properties, base structPointer) error {
+ tim := structPointer_InterfaceAt(base, p.field, timeType).(*time.Time)
+ t, err := timestampProto(*tim)
+ if err != nil {
+ return err
+ }
+ data, err := Marshal(t)
+ if err != nil {
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ return nil
+}
+
+func size_slice_time(p *Properties, base structPointer) (n int) {
+ ptims := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(reflect.PtrTo(timeType))).(*[]*time.Time)
+ tims := *ptims
+ for i := 0; i < len(tims); i++ {
+ if tims[i] == nil {
+ return 0
+ }
+ tproto, err := timestampProto(*tims[i])
+ if err != nil {
+ return 0
+ }
+ size := Size(tproto)
+ n += len(p.tagcode) + size + sizeVarint(uint64(size))
+ }
+ return n
+}
+
+func (o *Buffer) enc_slice_time(p *Properties, base structPointer) error {
+ ptims := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(reflect.PtrTo(timeType))).(*[]*time.Time)
+ tims := *ptims
+ for i := 0; i < len(tims); i++ {
+ if tims[i] == nil {
+ return errRepeatedHasNil
+ }
+ tproto, err := timestampProto(*tims[i])
+ if err != nil {
+ return err
+ }
+ data, err := Marshal(tproto)
+ if err != nil {
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ }
+ return nil
+}
+
+func size_slice_ref_time(p *Properties, base structPointer) (n int) {
+ ptims := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(timeType)).(*[]time.Time)
+ tims := *ptims
+ for i := 0; i < len(tims); i++ {
+ tproto, err := timestampProto(tims[i])
+ if err != nil {
+ return 0
+ }
+ size := Size(tproto)
+ n += len(p.tagcode) + size + sizeVarint(uint64(size))
+ }
+ return n
+}
+
+func (o *Buffer) enc_slice_ref_time(p *Properties, base structPointer) error {
+ ptims := structPointer_InterfaceAt(base, p.field, reflect.SliceOf(timeType)).(*[]time.Time)
+ tims := *ptims
+ for i := 0; i < len(tims); i++ {
+ tproto, err := timestampProto(tims[i])
+ if err != nil {
+ return err
+ }
+ data, err := Marshal(tproto)
+ if err != nil {
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ }
+ return nil
+}
--- /dev/null
+# Go support for Protocol Buffers - Google's data interchange format
+#
+# Copyright 2010 The Go Authors. All rights reserved.
+# https://github.com/golang/protobuf
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+regenerate:
+ go install github.com/gogo/protobuf/protoc-gen-gogo
+ go install github.com/gogo/protobuf/protoc-gen-gostring
+ protoc --gogo_out=. -I=../../protobuf/google/protobuf ../../protobuf/google/protobuf/descriptor.proto
+ protoc --gostring_out=. -I=../../protobuf/google/protobuf ../../protobuf/google/protobuf/descriptor.proto
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Package descriptor provides functions for obtaining protocol buffer
+// descriptors for generated Go types.
+//
+// These functions cannot go in package proto because they depend on the
+// generated protobuf descriptor messages, which themselves depend on proto.
+package descriptor
+
+import (
+ "bytes"
+ "compress/gzip"
+ "fmt"
+ "io/ioutil"
+
+ "github.com/gogo/protobuf/proto"
+)
+
+// extractFile extracts a FileDescriptorProto from a gzip'd buffer.
+func extractFile(gz []byte) (*FileDescriptorProto, error) {
+ r, err := gzip.NewReader(bytes.NewReader(gz))
+ if err != nil {
+ return nil, fmt.Errorf("failed to open gzip reader: %v", err)
+ }
+ defer r.Close()
+
+ b, err := ioutil.ReadAll(r)
+ if err != nil {
+ return nil, fmt.Errorf("failed to uncompress descriptor: %v", err)
+ }
+
+ fd := new(FileDescriptorProto)
+ if err := proto.Unmarshal(b, fd); err != nil {
+ return nil, fmt.Errorf("malformed FileDescriptorProto: %v", err)
+ }
+
+ return fd, nil
+}
+
+// Message is a proto.Message with a method to return its descriptor.
+//
+// Message types generated by the protocol compiler always satisfy
+// the Message interface.
+type Message interface {
+ proto.Message
+ Descriptor() ([]byte, []int)
+}
+
+// ForMessage returns a FileDescriptorProto and a DescriptorProto from within it
+// describing the given message.
+func ForMessage(msg Message) (fd *FileDescriptorProto, md *DescriptorProto) {
+ gz, path := msg.Descriptor()
+ fd, err := extractFile(gz)
+ if err != nil {
+ panic(fmt.Sprintf("invalid FileDescriptorProto for %T: %v", msg, err))
+ }
+
+ md = fd.MessageType[path[0]]
+ for _, i := range path[1:] {
+ md = md.NestedType[i]
+ }
+ return fd, md
+}
+
+// Is this field a scalar numeric type?
+func (field *FieldDescriptorProto) IsScalar() bool {
+ if field.Type == nil {
+ return false
+ }
+ switch *field.Type {
+ case FieldDescriptorProto_TYPE_DOUBLE,
+ FieldDescriptorProto_TYPE_FLOAT,
+ FieldDescriptorProto_TYPE_INT64,
+ FieldDescriptorProto_TYPE_UINT64,
+ FieldDescriptorProto_TYPE_INT32,
+ FieldDescriptorProto_TYPE_FIXED64,
+ FieldDescriptorProto_TYPE_FIXED32,
+ FieldDescriptorProto_TYPE_BOOL,
+ FieldDescriptorProto_TYPE_UINT32,
+ FieldDescriptorProto_TYPE_ENUM,
+ FieldDescriptorProto_TYPE_SFIXED32,
+ FieldDescriptorProto_TYPE_SFIXED64,
+ FieldDescriptorProto_TYPE_SINT32,
+ FieldDescriptorProto_TYPE_SINT64:
+ return true
+ default:
+ return false
+ }
+}
--- /dev/null
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: descriptor.proto
+
+/*
+Package descriptor is a generated protocol buffer package.
+
+It is generated from these files:
+ descriptor.proto
+
+It has these top-level messages:
+ FileDescriptorSet
+ FileDescriptorProto
+ DescriptorProto
+ ExtensionRangeOptions
+ FieldDescriptorProto
+ OneofDescriptorProto
+ EnumDescriptorProto
+ EnumValueDescriptorProto
+ ServiceDescriptorProto
+ MethodDescriptorProto
+ FileOptions
+ MessageOptions
+ FieldOptions
+ OneofOptions
+ EnumOptions
+ EnumValueOptions
+ ServiceOptions
+ MethodOptions
+ UninterpretedOption
+ SourceCodeInfo
+ GeneratedCodeInfo
+*/
+package descriptor
+
+import proto "github.com/gogo/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
+
+type FieldDescriptorProto_Type int32
+
+const (
+ // 0 is reserved for errors.
+ // Order is weird for historical reasons.
+ FieldDescriptorProto_TYPE_DOUBLE FieldDescriptorProto_Type = 1
+ FieldDescriptorProto_TYPE_FLOAT FieldDescriptorProto_Type = 2
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if
+ // negative values are likely.
+ FieldDescriptorProto_TYPE_INT64 FieldDescriptorProto_Type = 3
+ FieldDescriptorProto_TYPE_UINT64 FieldDescriptorProto_Type = 4
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if
+ // negative values are likely.
+ FieldDescriptorProto_TYPE_INT32 FieldDescriptorProto_Type = 5
+ FieldDescriptorProto_TYPE_FIXED64 FieldDescriptorProto_Type = 6
+ FieldDescriptorProto_TYPE_FIXED32 FieldDescriptorProto_Type = 7
+ FieldDescriptorProto_TYPE_BOOL FieldDescriptorProto_Type = 8
+ FieldDescriptorProto_TYPE_STRING FieldDescriptorProto_Type = 9
+ // Tag-delimited aggregate.
+ // Group type is deprecated and not supported in proto3. However, Proto3
+ // implementations should still be able to parse the group wire format and
+ // treat group fields as unknown fields.
+ FieldDescriptorProto_TYPE_GROUP FieldDescriptorProto_Type = 10
+ FieldDescriptorProto_TYPE_MESSAGE FieldDescriptorProto_Type = 11
+ // New in version 2.
+ FieldDescriptorProto_TYPE_BYTES FieldDescriptorProto_Type = 12
+ FieldDescriptorProto_TYPE_UINT32 FieldDescriptorProto_Type = 13
+ FieldDescriptorProto_TYPE_ENUM FieldDescriptorProto_Type = 14
+ FieldDescriptorProto_TYPE_SFIXED32 FieldDescriptorProto_Type = 15
+ FieldDescriptorProto_TYPE_SFIXED64 FieldDescriptorProto_Type = 16
+ FieldDescriptorProto_TYPE_SINT32 FieldDescriptorProto_Type = 17
+ FieldDescriptorProto_TYPE_SINT64 FieldDescriptorProto_Type = 18
+)
+
+var FieldDescriptorProto_Type_name = map[int32]string{
+ 1: "TYPE_DOUBLE",
+ 2: "TYPE_FLOAT",
+ 3: "TYPE_INT64",
+ 4: "TYPE_UINT64",
+ 5: "TYPE_INT32",
+ 6: "TYPE_FIXED64",
+ 7: "TYPE_FIXED32",
+ 8: "TYPE_BOOL",
+ 9: "TYPE_STRING",
+ 10: "TYPE_GROUP",
+ 11: "TYPE_MESSAGE",
+ 12: "TYPE_BYTES",
+ 13: "TYPE_UINT32",
+ 14: "TYPE_ENUM",
+ 15: "TYPE_SFIXED32",
+ 16: "TYPE_SFIXED64",
+ 17: "TYPE_SINT32",
+ 18: "TYPE_SINT64",
+}
+var FieldDescriptorProto_Type_value = map[string]int32{
+ "TYPE_DOUBLE": 1,
+ "TYPE_FLOAT": 2,
+ "TYPE_INT64": 3,
+ "TYPE_UINT64": 4,
+ "TYPE_INT32": 5,
+ "TYPE_FIXED64": 6,
+ "TYPE_FIXED32": 7,
+ "TYPE_BOOL": 8,
+ "TYPE_STRING": 9,
+ "TYPE_GROUP": 10,
+ "TYPE_MESSAGE": 11,
+ "TYPE_BYTES": 12,
+ "TYPE_UINT32": 13,
+ "TYPE_ENUM": 14,
+ "TYPE_SFIXED32": 15,
+ "TYPE_SFIXED64": 16,
+ "TYPE_SINT32": 17,
+ "TYPE_SINT64": 18,
+}
+
+func (x FieldDescriptorProto_Type) Enum() *FieldDescriptorProto_Type {
+ p := new(FieldDescriptorProto_Type)
+ *p = x
+ return p
+}
+func (x FieldDescriptorProto_Type) String() string {
+ return proto.EnumName(FieldDescriptorProto_Type_name, int32(x))
+}
+func (x *FieldDescriptorProto_Type) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FieldDescriptorProto_Type_value, data, "FieldDescriptorProto_Type")
+ if err != nil {
+ return err
+ }
+ *x = FieldDescriptorProto_Type(value)
+ return nil
+}
+func (FieldDescriptorProto_Type) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{4, 0}
+}
+
+type FieldDescriptorProto_Label int32
+
+const (
+ // 0 is reserved for errors
+ FieldDescriptorProto_LABEL_OPTIONAL FieldDescriptorProto_Label = 1
+ FieldDescriptorProto_LABEL_REQUIRED FieldDescriptorProto_Label = 2
+ FieldDescriptorProto_LABEL_REPEATED FieldDescriptorProto_Label = 3
+)
+
+var FieldDescriptorProto_Label_name = map[int32]string{
+ 1: "LABEL_OPTIONAL",
+ 2: "LABEL_REQUIRED",
+ 3: "LABEL_REPEATED",
+}
+var FieldDescriptorProto_Label_value = map[string]int32{
+ "LABEL_OPTIONAL": 1,
+ "LABEL_REQUIRED": 2,
+ "LABEL_REPEATED": 3,
+}
+
+func (x FieldDescriptorProto_Label) Enum() *FieldDescriptorProto_Label {
+ p := new(FieldDescriptorProto_Label)
+ *p = x
+ return p
+}
+func (x FieldDescriptorProto_Label) String() string {
+ return proto.EnumName(FieldDescriptorProto_Label_name, int32(x))
+}
+func (x *FieldDescriptorProto_Label) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FieldDescriptorProto_Label_value, data, "FieldDescriptorProto_Label")
+ if err != nil {
+ return err
+ }
+ *x = FieldDescriptorProto_Label(value)
+ return nil
+}
+func (FieldDescriptorProto_Label) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{4, 1}
+}
+
+// Generated classes can be optimized for speed or code size.
+type FileOptions_OptimizeMode int32
+
+const (
+ FileOptions_SPEED FileOptions_OptimizeMode = 1
+ // etc.
+ FileOptions_CODE_SIZE FileOptions_OptimizeMode = 2
+ FileOptions_LITE_RUNTIME FileOptions_OptimizeMode = 3
+)
+
+var FileOptions_OptimizeMode_name = map[int32]string{
+ 1: "SPEED",
+ 2: "CODE_SIZE",
+ 3: "LITE_RUNTIME",
+}
+var FileOptions_OptimizeMode_value = map[string]int32{
+ "SPEED": 1,
+ "CODE_SIZE": 2,
+ "LITE_RUNTIME": 3,
+}
+
+func (x FileOptions_OptimizeMode) Enum() *FileOptions_OptimizeMode {
+ p := new(FileOptions_OptimizeMode)
+ *p = x
+ return p
+}
+func (x FileOptions_OptimizeMode) String() string {
+ return proto.EnumName(FileOptions_OptimizeMode_name, int32(x))
+}
+func (x *FileOptions_OptimizeMode) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FileOptions_OptimizeMode_value, data, "FileOptions_OptimizeMode")
+ if err != nil {
+ return err
+ }
+ *x = FileOptions_OptimizeMode(value)
+ return nil
+}
+func (FileOptions_OptimizeMode) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{10, 0}
+}
+
+type FieldOptions_CType int32
+
+const (
+ // Default mode.
+ FieldOptions_STRING FieldOptions_CType = 0
+ FieldOptions_CORD FieldOptions_CType = 1
+ FieldOptions_STRING_PIECE FieldOptions_CType = 2
+)
+
+var FieldOptions_CType_name = map[int32]string{
+ 0: "STRING",
+ 1: "CORD",
+ 2: "STRING_PIECE",
+}
+var FieldOptions_CType_value = map[string]int32{
+ "STRING": 0,
+ "CORD": 1,
+ "STRING_PIECE": 2,
+}
+
+func (x FieldOptions_CType) Enum() *FieldOptions_CType {
+ p := new(FieldOptions_CType)
+ *p = x
+ return p
+}
+func (x FieldOptions_CType) String() string {
+ return proto.EnumName(FieldOptions_CType_name, int32(x))
+}
+func (x *FieldOptions_CType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FieldOptions_CType_value, data, "FieldOptions_CType")
+ if err != nil {
+ return err
+ }
+ *x = FieldOptions_CType(value)
+ return nil
+}
+func (FieldOptions_CType) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{12, 0}
+}
+
+type FieldOptions_JSType int32
+
+const (
+ // Use the default type.
+ FieldOptions_JS_NORMAL FieldOptions_JSType = 0
+ // Use JavaScript strings.
+ FieldOptions_JS_STRING FieldOptions_JSType = 1
+ // Use JavaScript numbers.
+ FieldOptions_JS_NUMBER FieldOptions_JSType = 2
+)
+
+var FieldOptions_JSType_name = map[int32]string{
+ 0: "JS_NORMAL",
+ 1: "JS_STRING",
+ 2: "JS_NUMBER",
+}
+var FieldOptions_JSType_value = map[string]int32{
+ "JS_NORMAL": 0,
+ "JS_STRING": 1,
+ "JS_NUMBER": 2,
+}
+
+func (x FieldOptions_JSType) Enum() *FieldOptions_JSType {
+ p := new(FieldOptions_JSType)
+ *p = x
+ return p
+}
+func (x FieldOptions_JSType) String() string {
+ return proto.EnumName(FieldOptions_JSType_name, int32(x))
+}
+func (x *FieldOptions_JSType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FieldOptions_JSType_value, data, "FieldOptions_JSType")
+ if err != nil {
+ return err
+ }
+ *x = FieldOptions_JSType(value)
+ return nil
+}
+func (FieldOptions_JSType) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{12, 1}
+}
+
+// Is this method side-effect-free (or safe in HTTP parlance), or idempotent,
+// or neither? HTTP based RPC implementation may choose GET verb for safe
+// methods, and PUT verb for idempotent methods instead of the default POST.
+type MethodOptions_IdempotencyLevel int32
+
+const (
+ MethodOptions_IDEMPOTENCY_UNKNOWN MethodOptions_IdempotencyLevel = 0
+ MethodOptions_NO_SIDE_EFFECTS MethodOptions_IdempotencyLevel = 1
+ MethodOptions_IDEMPOTENT MethodOptions_IdempotencyLevel = 2
+)
+
+var MethodOptions_IdempotencyLevel_name = map[int32]string{
+ 0: "IDEMPOTENCY_UNKNOWN",
+ 1: "NO_SIDE_EFFECTS",
+ 2: "IDEMPOTENT",
+}
+var MethodOptions_IdempotencyLevel_value = map[string]int32{
+ "IDEMPOTENCY_UNKNOWN": 0,
+ "NO_SIDE_EFFECTS": 1,
+ "IDEMPOTENT": 2,
+}
+
+func (x MethodOptions_IdempotencyLevel) Enum() *MethodOptions_IdempotencyLevel {
+ p := new(MethodOptions_IdempotencyLevel)
+ *p = x
+ return p
+}
+func (x MethodOptions_IdempotencyLevel) String() string {
+ return proto.EnumName(MethodOptions_IdempotencyLevel_name, int32(x))
+}
+func (x *MethodOptions_IdempotencyLevel) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(MethodOptions_IdempotencyLevel_value, data, "MethodOptions_IdempotencyLevel")
+ if err != nil {
+ return err
+ }
+ *x = MethodOptions_IdempotencyLevel(value)
+ return nil
+}
+func (MethodOptions_IdempotencyLevel) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{17, 0}
+}
+
+// The protocol compiler can output a FileDescriptorSet containing the .proto
+// files it parses.
+type FileDescriptorSet struct {
+ File []*FileDescriptorProto `protobuf:"bytes,1,rep,name=file" json:"file,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *FileDescriptorSet) Reset() { *m = FileDescriptorSet{} }
+func (m *FileDescriptorSet) String() string { return proto.CompactTextString(m) }
+func (*FileDescriptorSet) ProtoMessage() {}
+func (*FileDescriptorSet) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{0} }
+
+func (m *FileDescriptorSet) GetFile() []*FileDescriptorProto {
+ if m != nil {
+ return m.File
+ }
+ return nil
+}
+
+// Describes a complete .proto file.
+type FileDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Package *string `protobuf:"bytes,2,opt,name=package" json:"package,omitempty"`
+ // Names of files imported by this file.
+ Dependency []string `protobuf:"bytes,3,rep,name=dependency" json:"dependency,omitempty"`
+ // Indexes of the public imported files in the dependency list above.
+ PublicDependency []int32 `protobuf:"varint,10,rep,name=public_dependency,json=publicDependency" json:"public_dependency,omitempty"`
+ // Indexes of the weak imported files in the dependency list.
+ // For Google-internal migration only. Do not use.
+ WeakDependency []int32 `protobuf:"varint,11,rep,name=weak_dependency,json=weakDependency" json:"weak_dependency,omitempty"`
+ // All top-level definitions in this file.
+ MessageType []*DescriptorProto `protobuf:"bytes,4,rep,name=message_type,json=messageType" json:"message_type,omitempty"`
+ EnumType []*EnumDescriptorProto `protobuf:"bytes,5,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"`
+ Service []*ServiceDescriptorProto `protobuf:"bytes,6,rep,name=service" json:"service,omitempty"`
+ Extension []*FieldDescriptorProto `protobuf:"bytes,7,rep,name=extension" json:"extension,omitempty"`
+ Options *FileOptions `protobuf:"bytes,8,opt,name=options" json:"options,omitempty"`
+ // This field contains optional information about the original source code.
+ // You may safely remove this entire field without harming runtime
+ // functionality of the descriptors -- the information is needed only by
+ // development tools.
+ SourceCodeInfo *SourceCodeInfo `protobuf:"bytes,9,opt,name=source_code_info,json=sourceCodeInfo" json:"source_code_info,omitempty"`
+ // The syntax of the proto file.
+ // The supported values are "proto2" and "proto3".
+ Syntax *string `protobuf:"bytes,12,opt,name=syntax" json:"syntax,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *FileDescriptorProto) Reset() { *m = FileDescriptorProto{} }
+func (m *FileDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*FileDescriptorProto) ProtoMessage() {}
+func (*FileDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{1} }
+
+func (m *FileDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *FileDescriptorProto) GetPackage() string {
+ if m != nil && m.Package != nil {
+ return *m.Package
+ }
+ return ""
+}
+
+func (m *FileDescriptorProto) GetDependency() []string {
+ if m != nil {
+ return m.Dependency
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetPublicDependency() []int32 {
+ if m != nil {
+ return m.PublicDependency
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetWeakDependency() []int32 {
+ if m != nil {
+ return m.WeakDependency
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetMessageType() []*DescriptorProto {
+ if m != nil {
+ return m.MessageType
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetEnumType() []*EnumDescriptorProto {
+ if m != nil {
+ return m.EnumType
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetService() []*ServiceDescriptorProto {
+ if m != nil {
+ return m.Service
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetExtension() []*FieldDescriptorProto {
+ if m != nil {
+ return m.Extension
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetOptions() *FileOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetSourceCodeInfo() *SourceCodeInfo {
+ if m != nil {
+ return m.SourceCodeInfo
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetSyntax() string {
+ if m != nil && m.Syntax != nil {
+ return *m.Syntax
+ }
+ return ""
+}
+
+// Describes a message type.
+type DescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Field []*FieldDescriptorProto `protobuf:"bytes,2,rep,name=field" json:"field,omitempty"`
+ Extension []*FieldDescriptorProto `protobuf:"bytes,6,rep,name=extension" json:"extension,omitempty"`
+ NestedType []*DescriptorProto `protobuf:"bytes,3,rep,name=nested_type,json=nestedType" json:"nested_type,omitempty"`
+ EnumType []*EnumDescriptorProto `protobuf:"bytes,4,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"`
+ ExtensionRange []*DescriptorProto_ExtensionRange `protobuf:"bytes,5,rep,name=extension_range,json=extensionRange" json:"extension_range,omitempty"`
+ OneofDecl []*OneofDescriptorProto `protobuf:"bytes,8,rep,name=oneof_decl,json=oneofDecl" json:"oneof_decl,omitempty"`
+ Options *MessageOptions `protobuf:"bytes,7,opt,name=options" json:"options,omitempty"`
+ ReservedRange []*DescriptorProto_ReservedRange `protobuf:"bytes,9,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"`
+ // Reserved field names, which may not be used by fields in the same message.
+ // A given name may only be reserved once.
+ ReservedName []string `protobuf:"bytes,10,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DescriptorProto) Reset() { *m = DescriptorProto{} }
+func (m *DescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*DescriptorProto) ProtoMessage() {}
+func (*DescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{2} }
+
+func (m *DescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *DescriptorProto) GetField() []*FieldDescriptorProto {
+ if m != nil {
+ return m.Field
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetExtension() []*FieldDescriptorProto {
+ if m != nil {
+ return m.Extension
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetNestedType() []*DescriptorProto {
+ if m != nil {
+ return m.NestedType
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetEnumType() []*EnumDescriptorProto {
+ if m != nil {
+ return m.EnumType
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetExtensionRange() []*DescriptorProto_ExtensionRange {
+ if m != nil {
+ return m.ExtensionRange
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetOneofDecl() []*OneofDescriptorProto {
+ if m != nil {
+ return m.OneofDecl
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetOptions() *MessageOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetReservedRange() []*DescriptorProto_ReservedRange {
+ if m != nil {
+ return m.ReservedRange
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetReservedName() []string {
+ if m != nil {
+ return m.ReservedName
+ }
+ return nil
+}
+
+type DescriptorProto_ExtensionRange struct {
+ Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"`
+ End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"`
+ Options *ExtensionRangeOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DescriptorProto_ExtensionRange) Reset() { *m = DescriptorProto_ExtensionRange{} }
+func (m *DescriptorProto_ExtensionRange) String() string { return proto.CompactTextString(m) }
+func (*DescriptorProto_ExtensionRange) ProtoMessage() {}
+func (*DescriptorProto_ExtensionRange) Descriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{2, 0}
+}
+
+func (m *DescriptorProto_ExtensionRange) GetStart() int32 {
+ if m != nil && m.Start != nil {
+ return *m.Start
+ }
+ return 0
+}
+
+func (m *DescriptorProto_ExtensionRange) GetEnd() int32 {
+ if m != nil && m.End != nil {
+ return *m.End
+ }
+ return 0
+}
+
+func (m *DescriptorProto_ExtensionRange) GetOptions() *ExtensionRangeOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+// Range of reserved tag numbers. Reserved tag numbers may not be used by
+// fields or extension ranges in the same message. Reserved ranges may
+// not overlap.
+type DescriptorProto_ReservedRange struct {
+ Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"`
+ End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DescriptorProto_ReservedRange) Reset() { *m = DescriptorProto_ReservedRange{} }
+func (m *DescriptorProto_ReservedRange) String() string { return proto.CompactTextString(m) }
+func (*DescriptorProto_ReservedRange) ProtoMessage() {}
+func (*DescriptorProto_ReservedRange) Descriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{2, 1}
+}
+
+func (m *DescriptorProto_ReservedRange) GetStart() int32 {
+ if m != nil && m.Start != nil {
+ return *m.Start
+ }
+ return 0
+}
+
+func (m *DescriptorProto_ReservedRange) GetEnd() int32 {
+ if m != nil && m.End != nil {
+ return *m.End
+ }
+ return 0
+}
+
+type ExtensionRangeOptions struct {
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *ExtensionRangeOptions) Reset() { *m = ExtensionRangeOptions{} }
+func (m *ExtensionRangeOptions) String() string { return proto.CompactTextString(m) }
+func (*ExtensionRangeOptions) ProtoMessage() {}
+func (*ExtensionRangeOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{3} }
+
+var extRange_ExtensionRangeOptions = []proto.ExtensionRange{
+ {Start: 1000, End: 536870911},
+}
+
+func (*ExtensionRangeOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_ExtensionRangeOptions
+}
+
+func (m *ExtensionRangeOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+// Describes a field within a message.
+type FieldDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Number *int32 `protobuf:"varint,3,opt,name=number" json:"number,omitempty"`
+ Label *FieldDescriptorProto_Label `protobuf:"varint,4,opt,name=label,enum=google.protobuf.FieldDescriptorProto_Label" json:"label,omitempty"`
+ // If type_name is set, this need not be set. If both this and type_name
+ // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
+ Type *FieldDescriptorProto_Type `protobuf:"varint,5,opt,name=type,enum=google.protobuf.FieldDescriptorProto_Type" json:"type,omitempty"`
+ // For message and enum types, this is the name of the type. If the name
+ // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping
+ // rules are used to find the type (i.e. first the nested types within this
+ // message are searched, then within the parent, on up to the root
+ // namespace).
+ TypeName *string `protobuf:"bytes,6,opt,name=type_name,json=typeName" json:"type_name,omitempty"`
+ // For extensions, this is the name of the type being extended. It is
+ // resolved in the same manner as type_name.
+ Extendee *string `protobuf:"bytes,2,opt,name=extendee" json:"extendee,omitempty"`
+ // For numeric types, contains the original text representation of the value.
+ // For booleans, "true" or "false".
+ // For strings, contains the default text contents (not escaped in any way).
+ // For bytes, contains the C escaped value. All bytes >= 128 are escaped.
+ // TODO(kenton): Base-64 encode?
+ DefaultValue *string `protobuf:"bytes,7,opt,name=default_value,json=defaultValue" json:"default_value,omitempty"`
+ // If set, gives the index of a oneof in the containing type's oneof_decl
+ // list. This field is a member of that oneof.
+ OneofIndex *int32 `protobuf:"varint,9,opt,name=oneof_index,json=oneofIndex" json:"oneof_index,omitempty"`
+ // JSON name of this field. The value is set by protocol compiler. If the
+ // user has set a "json_name" option on this field, that option's value
+ // will be used. Otherwise, it's deduced from the field's name by converting
+ // it to camelCase.
+ JsonName *string `protobuf:"bytes,10,opt,name=json_name,json=jsonName" json:"json_name,omitempty"`
+ Options *FieldOptions `protobuf:"bytes,8,opt,name=options" json:"options,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *FieldDescriptorProto) Reset() { *m = FieldDescriptorProto{} }
+func (m *FieldDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*FieldDescriptorProto) ProtoMessage() {}
+func (*FieldDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{4} }
+
+func (m *FieldDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *FieldDescriptorProto) GetNumber() int32 {
+ if m != nil && m.Number != nil {
+ return *m.Number
+ }
+ return 0
+}
+
+func (m *FieldDescriptorProto) GetLabel() FieldDescriptorProto_Label {
+ if m != nil && m.Label != nil {
+ return *m.Label
+ }
+ return FieldDescriptorProto_LABEL_OPTIONAL
+}
+
+func (m *FieldDescriptorProto) GetType() FieldDescriptorProto_Type {
+ if m != nil && m.Type != nil {
+ return *m.Type
+ }
+ return FieldDescriptorProto_TYPE_DOUBLE
+}
+
+func (m *FieldDescriptorProto) GetTypeName() string {
+ if m != nil && m.TypeName != nil {
+ return *m.TypeName
+ }
+ return ""
+}
+
+func (m *FieldDescriptorProto) GetExtendee() string {
+ if m != nil && m.Extendee != nil {
+ return *m.Extendee
+ }
+ return ""
+}
+
+func (m *FieldDescriptorProto) GetDefaultValue() string {
+ if m != nil && m.DefaultValue != nil {
+ return *m.DefaultValue
+ }
+ return ""
+}
+
+func (m *FieldDescriptorProto) GetOneofIndex() int32 {
+ if m != nil && m.OneofIndex != nil {
+ return *m.OneofIndex
+ }
+ return 0
+}
+
+func (m *FieldDescriptorProto) GetJsonName() string {
+ if m != nil && m.JsonName != nil {
+ return *m.JsonName
+ }
+ return ""
+}
+
+func (m *FieldDescriptorProto) GetOptions() *FieldOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+// Describes a oneof.
+type OneofDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Options *OneofOptions `protobuf:"bytes,2,opt,name=options" json:"options,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *OneofDescriptorProto) Reset() { *m = OneofDescriptorProto{} }
+func (m *OneofDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*OneofDescriptorProto) ProtoMessage() {}
+func (*OneofDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{5} }
+
+func (m *OneofDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *OneofDescriptorProto) GetOptions() *OneofOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+// Describes an enum type.
+type EnumDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Value []*EnumValueDescriptorProto `protobuf:"bytes,2,rep,name=value" json:"value,omitempty"`
+ Options *EnumOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"`
+ // Range of reserved numeric values. Reserved numeric values may not be used
+ // by enum values in the same enum declaration. Reserved ranges may not
+ // overlap.
+ ReservedRange []*EnumDescriptorProto_EnumReservedRange `protobuf:"bytes,4,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"`
+ // Reserved enum value names, which may not be reused. A given name may only
+ // be reserved once.
+ ReservedName []string `protobuf:"bytes,5,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EnumDescriptorProto) Reset() { *m = EnumDescriptorProto{} }
+func (m *EnumDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*EnumDescriptorProto) ProtoMessage() {}
+func (*EnumDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{6} }
+
+func (m *EnumDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *EnumDescriptorProto) GetValue() []*EnumValueDescriptorProto {
+ if m != nil {
+ return m.Value
+ }
+ return nil
+}
+
+func (m *EnumDescriptorProto) GetOptions() *EnumOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+func (m *EnumDescriptorProto) GetReservedRange() []*EnumDescriptorProto_EnumReservedRange {
+ if m != nil {
+ return m.ReservedRange
+ }
+ return nil
+}
+
+func (m *EnumDescriptorProto) GetReservedName() []string {
+ if m != nil {
+ return m.ReservedName
+ }
+ return nil
+}
+
+// Range of reserved numeric values. Reserved values may not be used by
+// entries in the same enum. Reserved ranges may not overlap.
+//
+// Note that this is distinct from DescriptorProto.ReservedRange in that it
+// is inclusive such that it can appropriately represent the entire int32
+// domain.
+type EnumDescriptorProto_EnumReservedRange struct {
+ Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"`
+ End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EnumDescriptorProto_EnumReservedRange) Reset() { *m = EnumDescriptorProto_EnumReservedRange{} }
+func (m *EnumDescriptorProto_EnumReservedRange) String() string { return proto.CompactTextString(m) }
+func (*EnumDescriptorProto_EnumReservedRange) ProtoMessage() {}
+func (*EnumDescriptorProto_EnumReservedRange) Descriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{6, 0}
+}
+
+func (m *EnumDescriptorProto_EnumReservedRange) GetStart() int32 {
+ if m != nil && m.Start != nil {
+ return *m.Start
+ }
+ return 0
+}
+
+func (m *EnumDescriptorProto_EnumReservedRange) GetEnd() int32 {
+ if m != nil && m.End != nil {
+ return *m.End
+ }
+ return 0
+}
+
+// Describes a value within an enum.
+type EnumValueDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Number *int32 `protobuf:"varint,2,opt,name=number" json:"number,omitempty"`
+ Options *EnumValueOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EnumValueDescriptorProto) Reset() { *m = EnumValueDescriptorProto{} }
+func (m *EnumValueDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*EnumValueDescriptorProto) ProtoMessage() {}
+func (*EnumValueDescriptorProto) Descriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{7}
+}
+
+func (m *EnumValueDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *EnumValueDescriptorProto) GetNumber() int32 {
+ if m != nil && m.Number != nil {
+ return *m.Number
+ }
+ return 0
+}
+
+func (m *EnumValueDescriptorProto) GetOptions() *EnumValueOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+// Describes a service.
+type ServiceDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Method []*MethodDescriptorProto `protobuf:"bytes,2,rep,name=method" json:"method,omitempty"`
+ Options *ServiceOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *ServiceDescriptorProto) Reset() { *m = ServiceDescriptorProto{} }
+func (m *ServiceDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*ServiceDescriptorProto) ProtoMessage() {}
+func (*ServiceDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{8} }
+
+func (m *ServiceDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *ServiceDescriptorProto) GetMethod() []*MethodDescriptorProto {
+ if m != nil {
+ return m.Method
+ }
+ return nil
+}
+
+func (m *ServiceDescriptorProto) GetOptions() *ServiceOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+// Describes a method of a service.
+type MethodDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ // Input and output type names. These are resolved in the same way as
+ // FieldDescriptorProto.type_name, but must refer to a message type.
+ InputType *string `protobuf:"bytes,2,opt,name=input_type,json=inputType" json:"input_type,omitempty"`
+ OutputType *string `protobuf:"bytes,3,opt,name=output_type,json=outputType" json:"output_type,omitempty"`
+ Options *MethodOptions `protobuf:"bytes,4,opt,name=options" json:"options,omitempty"`
+ // Identifies if client streams multiple client messages
+ ClientStreaming *bool `protobuf:"varint,5,opt,name=client_streaming,json=clientStreaming,def=0" json:"client_streaming,omitempty"`
+ // Identifies if server streams multiple server messages
+ ServerStreaming *bool `protobuf:"varint,6,opt,name=server_streaming,json=serverStreaming,def=0" json:"server_streaming,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MethodDescriptorProto) Reset() { *m = MethodDescriptorProto{} }
+func (m *MethodDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*MethodDescriptorProto) ProtoMessage() {}
+func (*MethodDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{9} }
+
+const Default_MethodDescriptorProto_ClientStreaming bool = false
+const Default_MethodDescriptorProto_ServerStreaming bool = false
+
+func (m *MethodDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *MethodDescriptorProto) GetInputType() string {
+ if m != nil && m.InputType != nil {
+ return *m.InputType
+ }
+ return ""
+}
+
+func (m *MethodDescriptorProto) GetOutputType() string {
+ if m != nil && m.OutputType != nil {
+ return *m.OutputType
+ }
+ return ""
+}
+
+func (m *MethodDescriptorProto) GetOptions() *MethodOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+func (m *MethodDescriptorProto) GetClientStreaming() bool {
+ if m != nil && m.ClientStreaming != nil {
+ return *m.ClientStreaming
+ }
+ return Default_MethodDescriptorProto_ClientStreaming
+}
+
+func (m *MethodDescriptorProto) GetServerStreaming() bool {
+ if m != nil && m.ServerStreaming != nil {
+ return *m.ServerStreaming
+ }
+ return Default_MethodDescriptorProto_ServerStreaming
+}
+
+type FileOptions struct {
+ // Sets the Java package where classes generated from this .proto will be
+ // placed. By default, the proto package is used, but this is often
+ // inappropriate because proto packages do not normally start with backwards
+ // domain names.
+ JavaPackage *string `protobuf:"bytes,1,opt,name=java_package,json=javaPackage" json:"java_package,omitempty"`
+ // If set, all the classes from the .proto file are wrapped in a single
+ // outer class with the given name. This applies to both Proto1
+ // (equivalent to the old "--one_java_file" option) and Proto2 (where
+ // a .proto always translates to a single class, but you may want to
+ // explicitly choose the class name).
+ JavaOuterClassname *string `protobuf:"bytes,8,opt,name=java_outer_classname,json=javaOuterClassname" json:"java_outer_classname,omitempty"`
+ // If set true, then the Java code generator will generate a separate .java
+ // file for each top-level message, enum, and service defined in the .proto
+ // file. Thus, these types will *not* be nested inside the outer class
+ // named by java_outer_classname. However, the outer class will still be
+ // generated to contain the file's getDescriptor() method as well as any
+ // top-level extensions defined in the file.
+ JavaMultipleFiles *bool `protobuf:"varint,10,opt,name=java_multiple_files,json=javaMultipleFiles,def=0" json:"java_multiple_files,omitempty"`
+ // This option does nothing.
+ JavaGenerateEqualsAndHash *bool `protobuf:"varint,20,opt,name=java_generate_equals_and_hash,json=javaGenerateEqualsAndHash" json:"java_generate_equals_and_hash,omitempty"`
+ // If set true, then the Java2 code generator will generate code that
+ // throws an exception whenever an attempt is made to assign a non-UTF-8
+ // byte sequence to a string field.
+ // Message reflection will do the same.
+ // However, an extension field still accepts non-UTF-8 byte sequences.
+ // This option has no effect on when used with the lite runtime.
+ JavaStringCheckUtf8 *bool `protobuf:"varint,27,opt,name=java_string_check_utf8,json=javaStringCheckUtf8,def=0" json:"java_string_check_utf8,omitempty"`
+ OptimizeFor *FileOptions_OptimizeMode `protobuf:"varint,9,opt,name=optimize_for,json=optimizeFor,enum=google.protobuf.FileOptions_OptimizeMode,def=1" json:"optimize_for,omitempty"`
+ // Sets the Go package where structs generated from this .proto will be
+ // placed. If omitted, the Go package will be derived from the following:
+ // - The basename of the package import path, if provided.
+ // - Otherwise, the package statement in the .proto file, if present.
+ // - Otherwise, the basename of the .proto file, without extension.
+ GoPackage *string `protobuf:"bytes,11,opt,name=go_package,json=goPackage" json:"go_package,omitempty"`
+ // Should generic services be generated in each language? "Generic" services
+ // are not specific to any particular RPC system. They are generated by the
+ // main code generators in each language (without additional plugins).
+ // Generic services were the only kind of service generation supported by
+ // early versions of google.protobuf.
+ //
+ // Generic services are now considered deprecated in favor of using plugins
+ // that generate code specific to your particular RPC system. Therefore,
+ // these default to false. Old code which depends on generic services should
+ // explicitly set them to true.
+ CcGenericServices *bool `protobuf:"varint,16,opt,name=cc_generic_services,json=ccGenericServices,def=0" json:"cc_generic_services,omitempty"`
+ JavaGenericServices *bool `protobuf:"varint,17,opt,name=java_generic_services,json=javaGenericServices,def=0" json:"java_generic_services,omitempty"`
+ PyGenericServices *bool `protobuf:"varint,18,opt,name=py_generic_services,json=pyGenericServices,def=0" json:"py_generic_services,omitempty"`
+ PhpGenericServices *bool `protobuf:"varint,42,opt,name=php_generic_services,json=phpGenericServices,def=0" json:"php_generic_services,omitempty"`
+ // Is this file deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for everything in the file, or it will be completely ignored; in the very
+ // least, this is a formalization for deprecating files.
+ Deprecated *bool `protobuf:"varint,23,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ // Enables the use of arenas for the proto messages in this file. This applies
+ // only to generated classes for C++.
+ CcEnableArenas *bool `protobuf:"varint,31,opt,name=cc_enable_arenas,json=ccEnableArenas,def=0" json:"cc_enable_arenas,omitempty"`
+ // Sets the objective c class prefix which is prepended to all objective c
+ // generated classes from this .proto. There is no default.
+ ObjcClassPrefix *string `protobuf:"bytes,36,opt,name=objc_class_prefix,json=objcClassPrefix" json:"objc_class_prefix,omitempty"`
+ // Namespace for generated classes; defaults to the package.
+ CsharpNamespace *string `protobuf:"bytes,37,opt,name=csharp_namespace,json=csharpNamespace" json:"csharp_namespace,omitempty"`
+ // By default Swift generators will take the proto package and CamelCase it
+ // replacing '.' with underscore and use that to prefix the types/symbols
+ // defined. When this options is provided, they will use this value instead
+ // to prefix the types/symbols defined.
+ SwiftPrefix *string `protobuf:"bytes,39,opt,name=swift_prefix,json=swiftPrefix" json:"swift_prefix,omitempty"`
+ // Sets the php class prefix which is prepended to all php generated classes
+ // from this .proto. Default is empty.
+ PhpClassPrefix *string `protobuf:"bytes,40,opt,name=php_class_prefix,json=phpClassPrefix" json:"php_class_prefix,omitempty"`
+ // Use this option to change the namespace of php generated classes. Default
+ // is empty. When this option is empty, the package name will be used for
+ // determining the namespace.
+ PhpNamespace *string `protobuf:"bytes,41,opt,name=php_namespace,json=phpNamespace" json:"php_namespace,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *FileOptions) Reset() { *m = FileOptions{} }
+func (m *FileOptions) String() string { return proto.CompactTextString(m) }
+func (*FileOptions) ProtoMessage() {}
+func (*FileOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{10} }
+
+var extRange_FileOptions = []proto.ExtensionRange{
+ {Start: 1000, End: 536870911},
+}
+
+func (*FileOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_FileOptions
+}
+
+const Default_FileOptions_JavaMultipleFiles bool = false
+const Default_FileOptions_JavaStringCheckUtf8 bool = false
+const Default_FileOptions_OptimizeFor FileOptions_OptimizeMode = FileOptions_SPEED
+const Default_FileOptions_CcGenericServices bool = false
+const Default_FileOptions_JavaGenericServices bool = false
+const Default_FileOptions_PyGenericServices bool = false
+const Default_FileOptions_PhpGenericServices bool = false
+const Default_FileOptions_Deprecated bool = false
+const Default_FileOptions_CcEnableArenas bool = false
+
+func (m *FileOptions) GetJavaPackage() string {
+ if m != nil && m.JavaPackage != nil {
+ return *m.JavaPackage
+ }
+ return ""
+}
+
+func (m *FileOptions) GetJavaOuterClassname() string {
+ if m != nil && m.JavaOuterClassname != nil {
+ return *m.JavaOuterClassname
+ }
+ return ""
+}
+
+func (m *FileOptions) GetJavaMultipleFiles() bool {
+ if m != nil && m.JavaMultipleFiles != nil {
+ return *m.JavaMultipleFiles
+ }
+ return Default_FileOptions_JavaMultipleFiles
+}
+
+func (m *FileOptions) GetJavaGenerateEqualsAndHash() bool {
+ if m != nil && m.JavaGenerateEqualsAndHash != nil {
+ return *m.JavaGenerateEqualsAndHash
+ }
+ return false
+}
+
+func (m *FileOptions) GetJavaStringCheckUtf8() bool {
+ if m != nil && m.JavaStringCheckUtf8 != nil {
+ return *m.JavaStringCheckUtf8
+ }
+ return Default_FileOptions_JavaStringCheckUtf8
+}
+
+func (m *FileOptions) GetOptimizeFor() FileOptions_OptimizeMode {
+ if m != nil && m.OptimizeFor != nil {
+ return *m.OptimizeFor
+ }
+ return Default_FileOptions_OptimizeFor
+}
+
+func (m *FileOptions) GetGoPackage() string {
+ if m != nil && m.GoPackage != nil {
+ return *m.GoPackage
+ }
+ return ""
+}
+
+func (m *FileOptions) GetCcGenericServices() bool {
+ if m != nil && m.CcGenericServices != nil {
+ return *m.CcGenericServices
+ }
+ return Default_FileOptions_CcGenericServices
+}
+
+func (m *FileOptions) GetJavaGenericServices() bool {
+ if m != nil && m.JavaGenericServices != nil {
+ return *m.JavaGenericServices
+ }
+ return Default_FileOptions_JavaGenericServices
+}
+
+func (m *FileOptions) GetPyGenericServices() bool {
+ if m != nil && m.PyGenericServices != nil {
+ return *m.PyGenericServices
+ }
+ return Default_FileOptions_PyGenericServices
+}
+
+func (m *FileOptions) GetPhpGenericServices() bool {
+ if m != nil && m.PhpGenericServices != nil {
+ return *m.PhpGenericServices
+ }
+ return Default_FileOptions_PhpGenericServices
+}
+
+func (m *FileOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_FileOptions_Deprecated
+}
+
+func (m *FileOptions) GetCcEnableArenas() bool {
+ if m != nil && m.CcEnableArenas != nil {
+ return *m.CcEnableArenas
+ }
+ return Default_FileOptions_CcEnableArenas
+}
+
+func (m *FileOptions) GetObjcClassPrefix() string {
+ if m != nil && m.ObjcClassPrefix != nil {
+ return *m.ObjcClassPrefix
+ }
+ return ""
+}
+
+func (m *FileOptions) GetCsharpNamespace() string {
+ if m != nil && m.CsharpNamespace != nil {
+ return *m.CsharpNamespace
+ }
+ return ""
+}
+
+func (m *FileOptions) GetSwiftPrefix() string {
+ if m != nil && m.SwiftPrefix != nil {
+ return *m.SwiftPrefix
+ }
+ return ""
+}
+
+func (m *FileOptions) GetPhpClassPrefix() string {
+ if m != nil && m.PhpClassPrefix != nil {
+ return *m.PhpClassPrefix
+ }
+ return ""
+}
+
+func (m *FileOptions) GetPhpNamespace() string {
+ if m != nil && m.PhpNamespace != nil {
+ return *m.PhpNamespace
+ }
+ return ""
+}
+
+func (m *FileOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type MessageOptions struct {
+ // Set true to use the old proto1 MessageSet wire format for extensions.
+ // This is provided for backwards-compatibility with the MessageSet wire
+ // format. You should not use this for any other reason: It's less
+ // efficient, has fewer features, and is more complicated.
+ //
+ // The message must be defined exactly as follows:
+ // message Foo {
+ // option message_set_wire_format = true;
+ // extensions 4 to max;
+ // }
+ // Note that the message cannot have any defined fields; MessageSets only
+ // have extensions.
+ //
+ // All extensions of your type must be singular messages; e.g. they cannot
+ // be int32s, enums, or repeated messages.
+ //
+ // Because this is an option, the above two restrictions are not enforced by
+ // the protocol compiler.
+ MessageSetWireFormat *bool `protobuf:"varint,1,opt,name=message_set_wire_format,json=messageSetWireFormat,def=0" json:"message_set_wire_format,omitempty"`
+ // Disables the generation of the standard "descriptor()" accessor, which can
+ // conflict with a field of the same name. This is meant to make migration
+ // from proto1 easier; new code should avoid fields named "descriptor".
+ NoStandardDescriptorAccessor *bool `protobuf:"varint,2,opt,name=no_standard_descriptor_accessor,json=noStandardDescriptorAccessor,def=0" json:"no_standard_descriptor_accessor,omitempty"`
+ // Is this message deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the message, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating messages.
+ Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ // Whether the message is an automatically generated map entry type for the
+ // maps field.
+ //
+ // For maps fields:
+ // map<KeyType, ValueType> map_field = 1;
+ // The parsed descriptor looks like:
+ // message MapFieldEntry {
+ // option map_entry = true;
+ // optional KeyType key = 1;
+ // optional ValueType value = 2;
+ // }
+ // repeated MapFieldEntry map_field = 1;
+ //
+ // Implementations may choose not to generate the map_entry=true message, but
+ // use a native map in the target language to hold the keys and values.
+ // The reflection APIs in such implementions still need to work as
+ // if the field is a repeated message field.
+ //
+ // NOTE: Do not set the option in .proto files. Always use the maps syntax
+ // instead. The option should only be implicitly set by the proto compiler
+ // parser.
+ MapEntry *bool `protobuf:"varint,7,opt,name=map_entry,json=mapEntry" json:"map_entry,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MessageOptions) Reset() { *m = MessageOptions{} }
+func (m *MessageOptions) String() string { return proto.CompactTextString(m) }
+func (*MessageOptions) ProtoMessage() {}
+func (*MessageOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{11} }
+
+var extRange_MessageOptions = []proto.ExtensionRange{
+ {Start: 1000, End: 536870911},
+}
+
+func (*MessageOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_MessageOptions
+}
+
+const Default_MessageOptions_MessageSetWireFormat bool = false
+const Default_MessageOptions_NoStandardDescriptorAccessor bool = false
+const Default_MessageOptions_Deprecated bool = false
+
+func (m *MessageOptions) GetMessageSetWireFormat() bool {
+ if m != nil && m.MessageSetWireFormat != nil {
+ return *m.MessageSetWireFormat
+ }
+ return Default_MessageOptions_MessageSetWireFormat
+}
+
+func (m *MessageOptions) GetNoStandardDescriptorAccessor() bool {
+ if m != nil && m.NoStandardDescriptorAccessor != nil {
+ return *m.NoStandardDescriptorAccessor
+ }
+ return Default_MessageOptions_NoStandardDescriptorAccessor
+}
+
+func (m *MessageOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_MessageOptions_Deprecated
+}
+
+func (m *MessageOptions) GetMapEntry() bool {
+ if m != nil && m.MapEntry != nil {
+ return *m.MapEntry
+ }
+ return false
+}
+
+func (m *MessageOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type FieldOptions struct {
+ // The ctype option instructs the C++ code generator to use a different
+ // representation of the field than it normally would. See the specific
+ // options below. This option is not yet implemented in the open source
+ // release -- sorry, we'll try to include it in a future version!
+ Ctype *FieldOptions_CType `protobuf:"varint,1,opt,name=ctype,enum=google.protobuf.FieldOptions_CType,def=0" json:"ctype,omitempty"`
+ // The packed option can be enabled for repeated primitive fields to enable
+ // a more efficient representation on the wire. Rather than repeatedly
+ // writing the tag and type for each element, the entire array is encoded as
+ // a single length-delimited blob. In proto3, only explicit setting it to
+ // false will avoid using packed encoding.
+ Packed *bool `protobuf:"varint,2,opt,name=packed" json:"packed,omitempty"`
+ // The jstype option determines the JavaScript type used for values of the
+ // field. The option is permitted only for 64 bit integral and fixed types
+ // (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING
+ // is represented as JavaScript string, which avoids loss of precision that
+ // can happen when a large value is converted to a floating point JavaScript.
+ // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to
+ // use the JavaScript "number" type. The behavior of the default option
+ // JS_NORMAL is implementation dependent.
+ //
+ // This option is an enum to permit additional types to be added, e.g.
+ // goog.math.Integer.
+ Jstype *FieldOptions_JSType `protobuf:"varint,6,opt,name=jstype,enum=google.protobuf.FieldOptions_JSType,def=0" json:"jstype,omitempty"`
+ // Should this field be parsed lazily? Lazy applies only to message-type
+ // fields. It means that when the outer message is initially parsed, the
+ // inner message's contents will not be parsed but instead stored in encoded
+ // form. The inner message will actually be parsed when it is first accessed.
+ //
+ // This is only a hint. Implementations are free to choose whether to use
+ // eager or lazy parsing regardless of the value of this option. However,
+ // setting this option true suggests that the protocol author believes that
+ // using lazy parsing on this field is worth the additional bookkeeping
+ // overhead typically needed to implement it.
+ //
+ // This option does not affect the public interface of any generated code;
+ // all method signatures remain the same. Furthermore, thread-safety of the
+ // interface is not affected by this option; const methods remain safe to
+ // call from multiple threads concurrently, while non-const methods continue
+ // to require exclusive access.
+ //
+ //
+ // Note that implementations may choose not to check required fields within
+ // a lazy sub-message. That is, calling IsInitialized() on the outer message
+ // may return true even if the inner message has missing required fields.
+ // This is necessary because otherwise the inner message would have to be
+ // parsed in order to perform the check, defeating the purpose of lazy
+ // parsing. An implementation which chooses not to check required fields
+ // must be consistent about it. That is, for any particular sub-message, the
+ // implementation must either *always* check its required fields, or *never*
+ // check its required fields, regardless of whether or not the message has
+ // been parsed.
+ Lazy *bool `protobuf:"varint,5,opt,name=lazy,def=0" json:"lazy,omitempty"`
+ // Is this field deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for accessors, or it will be completely ignored; in the very least, this
+ // is a formalization for deprecating fields.
+ Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ // For Google-internal migration only. Do not use.
+ Weak *bool `protobuf:"varint,10,opt,name=weak,def=0" json:"weak,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *FieldOptions) Reset() { *m = FieldOptions{} }
+func (m *FieldOptions) String() string { return proto.CompactTextString(m) }
+func (*FieldOptions) ProtoMessage() {}
+func (*FieldOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{12} }
+
+var extRange_FieldOptions = []proto.ExtensionRange{
+ {Start: 1000, End: 536870911},
+}
+
+func (*FieldOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_FieldOptions
+}
+
+const Default_FieldOptions_Ctype FieldOptions_CType = FieldOptions_STRING
+const Default_FieldOptions_Jstype FieldOptions_JSType = FieldOptions_JS_NORMAL
+const Default_FieldOptions_Lazy bool = false
+const Default_FieldOptions_Deprecated bool = false
+const Default_FieldOptions_Weak bool = false
+
+func (m *FieldOptions) GetCtype() FieldOptions_CType {
+ if m != nil && m.Ctype != nil {
+ return *m.Ctype
+ }
+ return Default_FieldOptions_Ctype
+}
+
+func (m *FieldOptions) GetPacked() bool {
+ if m != nil && m.Packed != nil {
+ return *m.Packed
+ }
+ return false
+}
+
+func (m *FieldOptions) GetJstype() FieldOptions_JSType {
+ if m != nil && m.Jstype != nil {
+ return *m.Jstype
+ }
+ return Default_FieldOptions_Jstype
+}
+
+func (m *FieldOptions) GetLazy() bool {
+ if m != nil && m.Lazy != nil {
+ return *m.Lazy
+ }
+ return Default_FieldOptions_Lazy
+}
+
+func (m *FieldOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_FieldOptions_Deprecated
+}
+
+func (m *FieldOptions) GetWeak() bool {
+ if m != nil && m.Weak != nil {
+ return *m.Weak
+ }
+ return Default_FieldOptions_Weak
+}
+
+func (m *FieldOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type OneofOptions struct {
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *OneofOptions) Reset() { *m = OneofOptions{} }
+func (m *OneofOptions) String() string { return proto.CompactTextString(m) }
+func (*OneofOptions) ProtoMessage() {}
+func (*OneofOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{13} }
+
+var extRange_OneofOptions = []proto.ExtensionRange{
+ {Start: 1000, End: 536870911},
+}
+
+func (*OneofOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_OneofOptions
+}
+
+func (m *OneofOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type EnumOptions struct {
+ // Set this option to true to allow mapping different tag names to the same
+ // value.
+ AllowAlias *bool `protobuf:"varint,2,opt,name=allow_alias,json=allowAlias" json:"allow_alias,omitempty"`
+ // Is this enum deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the enum, or it will be completely ignored; in the very least, this
+ // is a formalization for deprecating enums.
+ Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EnumOptions) Reset() { *m = EnumOptions{} }
+func (m *EnumOptions) String() string { return proto.CompactTextString(m) }
+func (*EnumOptions) ProtoMessage() {}
+func (*EnumOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{14} }
+
+var extRange_EnumOptions = []proto.ExtensionRange{
+ {Start: 1000, End: 536870911},
+}
+
+func (*EnumOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_EnumOptions
+}
+
+const Default_EnumOptions_Deprecated bool = false
+
+func (m *EnumOptions) GetAllowAlias() bool {
+ if m != nil && m.AllowAlias != nil {
+ return *m.AllowAlias
+ }
+ return false
+}
+
+func (m *EnumOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_EnumOptions_Deprecated
+}
+
+func (m *EnumOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type EnumValueOptions struct {
+ // Is this enum value deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the enum value, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating enum values.
+ Deprecated *bool `protobuf:"varint,1,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EnumValueOptions) Reset() { *m = EnumValueOptions{} }
+func (m *EnumValueOptions) String() string { return proto.CompactTextString(m) }
+func (*EnumValueOptions) ProtoMessage() {}
+func (*EnumValueOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{15} }
+
+var extRange_EnumValueOptions = []proto.ExtensionRange{
+ {Start: 1000, End: 536870911},
+}
+
+func (*EnumValueOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_EnumValueOptions
+}
+
+const Default_EnumValueOptions_Deprecated bool = false
+
+func (m *EnumValueOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_EnumValueOptions_Deprecated
+}
+
+func (m *EnumValueOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type ServiceOptions struct {
+ // Is this service deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the service, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating services.
+ Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *ServiceOptions) Reset() { *m = ServiceOptions{} }
+func (m *ServiceOptions) String() string { return proto.CompactTextString(m) }
+func (*ServiceOptions) ProtoMessage() {}
+func (*ServiceOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{16} }
+
+var extRange_ServiceOptions = []proto.ExtensionRange{
+ {Start: 1000, End: 536870911},
+}
+
+func (*ServiceOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_ServiceOptions
+}
+
+const Default_ServiceOptions_Deprecated bool = false
+
+func (m *ServiceOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_ServiceOptions_Deprecated
+}
+
+func (m *ServiceOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type MethodOptions struct {
+ // Is this method deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the method, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating methods.
+ Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ IdempotencyLevel *MethodOptions_IdempotencyLevel `protobuf:"varint,34,opt,name=idempotency_level,json=idempotencyLevel,enum=google.protobuf.MethodOptions_IdempotencyLevel,def=0" json:"idempotency_level,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MethodOptions) Reset() { *m = MethodOptions{} }
+func (m *MethodOptions) String() string { return proto.CompactTextString(m) }
+func (*MethodOptions) ProtoMessage() {}
+func (*MethodOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{17} }
+
+var extRange_MethodOptions = []proto.ExtensionRange{
+ {Start: 1000, End: 536870911},
+}
+
+func (*MethodOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_MethodOptions
+}
+
+const Default_MethodOptions_Deprecated bool = false
+const Default_MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel = MethodOptions_IDEMPOTENCY_UNKNOWN
+
+func (m *MethodOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_MethodOptions_Deprecated
+}
+
+func (m *MethodOptions) GetIdempotencyLevel() MethodOptions_IdempotencyLevel {
+ if m != nil && m.IdempotencyLevel != nil {
+ return *m.IdempotencyLevel
+ }
+ return Default_MethodOptions_IdempotencyLevel
+}
+
+func (m *MethodOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+// A message representing a option the parser does not recognize. This only
+// appears in options protos created by the compiler::Parser class.
+// DescriptorPool resolves these when building Descriptor objects. Therefore,
+// options protos in descriptor objects (e.g. returned by Descriptor::options(),
+// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
+// in them.
+type UninterpretedOption struct {
+ Name []*UninterpretedOption_NamePart `protobuf:"bytes,2,rep,name=name" json:"name,omitempty"`
+ // The value of the uninterpreted option, in whatever type the tokenizer
+ // identified it as during parsing. Exactly one of these should be set.
+ IdentifierValue *string `protobuf:"bytes,3,opt,name=identifier_value,json=identifierValue" json:"identifier_value,omitempty"`
+ PositiveIntValue *uint64 `protobuf:"varint,4,opt,name=positive_int_value,json=positiveIntValue" json:"positive_int_value,omitempty"`
+ NegativeIntValue *int64 `protobuf:"varint,5,opt,name=negative_int_value,json=negativeIntValue" json:"negative_int_value,omitempty"`
+ DoubleValue *float64 `protobuf:"fixed64,6,opt,name=double_value,json=doubleValue" json:"double_value,omitempty"`
+ StringValue []byte `protobuf:"bytes,7,opt,name=string_value,json=stringValue" json:"string_value,omitempty"`
+ AggregateValue *string `protobuf:"bytes,8,opt,name=aggregate_value,json=aggregateValue" json:"aggregate_value,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *UninterpretedOption) Reset() { *m = UninterpretedOption{} }
+func (m *UninterpretedOption) String() string { return proto.CompactTextString(m) }
+func (*UninterpretedOption) ProtoMessage() {}
+func (*UninterpretedOption) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{18} }
+
+func (m *UninterpretedOption) GetName() []*UninterpretedOption_NamePart {
+ if m != nil {
+ return m.Name
+ }
+ return nil
+}
+
+func (m *UninterpretedOption) GetIdentifierValue() string {
+ if m != nil && m.IdentifierValue != nil {
+ return *m.IdentifierValue
+ }
+ return ""
+}
+
+func (m *UninterpretedOption) GetPositiveIntValue() uint64 {
+ if m != nil && m.PositiveIntValue != nil {
+ return *m.PositiveIntValue
+ }
+ return 0
+}
+
+func (m *UninterpretedOption) GetNegativeIntValue() int64 {
+ if m != nil && m.NegativeIntValue != nil {
+ return *m.NegativeIntValue
+ }
+ return 0
+}
+
+func (m *UninterpretedOption) GetDoubleValue() float64 {
+ if m != nil && m.DoubleValue != nil {
+ return *m.DoubleValue
+ }
+ return 0
+}
+
+func (m *UninterpretedOption) GetStringValue() []byte {
+ if m != nil {
+ return m.StringValue
+ }
+ return nil
+}
+
+func (m *UninterpretedOption) GetAggregateValue() string {
+ if m != nil && m.AggregateValue != nil {
+ return *m.AggregateValue
+ }
+ return ""
+}
+
+// The name of the uninterpreted option. Each string represents a segment in
+// a dot-separated name. is_extension is true iff a segment represents an
+// extension (denoted with parentheses in options specs in .proto files).
+// E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
+// "foo.(bar.baz).qux".
+type UninterpretedOption_NamePart struct {
+ NamePart *string `protobuf:"bytes,1,req,name=name_part,json=namePart" json:"name_part,omitempty"`
+ IsExtension *bool `protobuf:"varint,2,req,name=is_extension,json=isExtension" json:"is_extension,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *UninterpretedOption_NamePart) Reset() { *m = UninterpretedOption_NamePart{} }
+func (m *UninterpretedOption_NamePart) String() string { return proto.CompactTextString(m) }
+func (*UninterpretedOption_NamePart) ProtoMessage() {}
+func (*UninterpretedOption_NamePart) Descriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{18, 0}
+}
+
+func (m *UninterpretedOption_NamePart) GetNamePart() string {
+ if m != nil && m.NamePart != nil {
+ return *m.NamePart
+ }
+ return ""
+}
+
+func (m *UninterpretedOption_NamePart) GetIsExtension() bool {
+ if m != nil && m.IsExtension != nil {
+ return *m.IsExtension
+ }
+ return false
+}
+
+// Encapsulates information about the original source file from which a
+// FileDescriptorProto was generated.
+type SourceCodeInfo struct {
+ // A Location identifies a piece of source code in a .proto file which
+ // corresponds to a particular definition. This information is intended
+ // to be useful to IDEs, code indexers, documentation generators, and similar
+ // tools.
+ //
+ // For example, say we have a file like:
+ // message Foo {
+ // optional string foo = 1;
+ // }
+ // Let's look at just the field definition:
+ // optional string foo = 1;
+ // ^ ^^ ^^ ^ ^^^
+ // a bc de f ghi
+ // We have the following locations:
+ // span path represents
+ // [a,i) [ 4, 0, 2, 0 ] The whole field definition.
+ // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional).
+ // [c,d) [ 4, 0, 2, 0, 5 ] The type (string).
+ // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo).
+ // [g,h) [ 4, 0, 2, 0, 3 ] The number (1).
+ //
+ // Notes:
+ // - A location may refer to a repeated field itself (i.e. not to any
+ // particular index within it). This is used whenever a set of elements are
+ // logically enclosed in a single code segment. For example, an entire
+ // extend block (possibly containing multiple extension definitions) will
+ // have an outer location whose path refers to the "extensions" repeated
+ // field without an index.
+ // - Multiple locations may have the same path. This happens when a single
+ // logical declaration is spread out across multiple places. The most
+ // obvious example is the "extend" block again -- there may be multiple
+ // extend blocks in the same scope, each of which will have the same path.
+ // - A location's span is not always a subset of its parent's span. For
+ // example, the "extendee" of an extension declaration appears at the
+ // beginning of the "extend" block and is shared by all extensions within
+ // the block.
+ // - Just because a location's span is a subset of some other location's span
+ // does not mean that it is a descendent. For example, a "group" defines
+ // both a type and a field in a single declaration. Thus, the locations
+ // corresponding to the type and field and their components will overlap.
+ // - Code which tries to interpret locations should probably be designed to
+ // ignore those that it doesn't understand, as more types of locations could
+ // be recorded in the future.
+ Location []*SourceCodeInfo_Location `protobuf:"bytes,1,rep,name=location" json:"location,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *SourceCodeInfo) Reset() { *m = SourceCodeInfo{} }
+func (m *SourceCodeInfo) String() string { return proto.CompactTextString(m) }
+func (*SourceCodeInfo) ProtoMessage() {}
+func (*SourceCodeInfo) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{19} }
+
+func (m *SourceCodeInfo) GetLocation() []*SourceCodeInfo_Location {
+ if m != nil {
+ return m.Location
+ }
+ return nil
+}
+
+type SourceCodeInfo_Location struct {
+ // Identifies which part of the FileDescriptorProto was defined at this
+ // location.
+ //
+ // Each element is a field number or an index. They form a path from
+ // the root FileDescriptorProto to the place where the definition. For
+ // example, this path:
+ // [ 4, 3, 2, 7, 1 ]
+ // refers to:
+ // file.message_type(3) // 4, 3
+ // .field(7) // 2, 7
+ // .name() // 1
+ // This is because FileDescriptorProto.message_type has field number 4:
+ // repeated DescriptorProto message_type = 4;
+ // and DescriptorProto.field has field number 2:
+ // repeated FieldDescriptorProto field = 2;
+ // and FieldDescriptorProto.name has field number 1:
+ // optional string name = 1;
+ //
+ // Thus, the above path gives the location of a field name. If we removed
+ // the last element:
+ // [ 4, 3, 2, 7 ]
+ // this path refers to the whole field declaration (from the beginning
+ // of the label to the terminating semicolon).
+ Path []int32 `protobuf:"varint,1,rep,packed,name=path" json:"path,omitempty"`
+ // Always has exactly three or four elements: start line, start column,
+ // end line (optional, otherwise assumed same as start line), end column.
+ // These are packed into a single field for efficiency. Note that line
+ // and column numbers are zero-based -- typically you will want to add
+ // 1 to each before displaying to a user.
+ Span []int32 `protobuf:"varint,2,rep,packed,name=span" json:"span,omitempty"`
+ // If this SourceCodeInfo represents a complete declaration, these are any
+ // comments appearing before and after the declaration which appear to be
+ // attached to the declaration.
+ //
+ // A series of line comments appearing on consecutive lines, with no other
+ // tokens appearing on those lines, will be treated as a single comment.
+ //
+ // leading_detached_comments will keep paragraphs of comments that appear
+ // before (but not connected to) the current element. Each paragraph,
+ // separated by empty lines, will be one comment element in the repeated
+ // field.
+ //
+ // Only the comment content is provided; comment markers (e.g. //) are
+ // stripped out. For block comments, leading whitespace and an asterisk
+ // will be stripped from the beginning of each line other than the first.
+ // Newlines are included in the output.
+ //
+ // Examples:
+ //
+ // optional int32 foo = 1; // Comment attached to foo.
+ // // Comment attached to bar.
+ // optional int32 bar = 2;
+ //
+ // optional string baz = 3;
+ // // Comment attached to baz.
+ // // Another line attached to baz.
+ //
+ // // Comment attached to qux.
+ // //
+ // // Another line attached to qux.
+ // optional double qux = 4;
+ //
+ // // Detached comment for corge. This is not leading or trailing comments
+ // // to qux or corge because there are blank lines separating it from
+ // // both.
+ //
+ // // Detached comment for corge paragraph 2.
+ //
+ // optional string corge = 5;
+ // /* Block comment attached
+ // * to corge. Leading asterisks
+ // * will be removed. */
+ // /* Block comment attached to
+ // * grault. */
+ // optional int32 grault = 6;
+ //
+ // // ignored detached comments.
+ LeadingComments *string `protobuf:"bytes,3,opt,name=leading_comments,json=leadingComments" json:"leading_comments,omitempty"`
+ TrailingComments *string `protobuf:"bytes,4,opt,name=trailing_comments,json=trailingComments" json:"trailing_comments,omitempty"`
+ LeadingDetachedComments []string `protobuf:"bytes,6,rep,name=leading_detached_comments,json=leadingDetachedComments" json:"leading_detached_comments,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *SourceCodeInfo_Location) Reset() { *m = SourceCodeInfo_Location{} }
+func (m *SourceCodeInfo_Location) String() string { return proto.CompactTextString(m) }
+func (*SourceCodeInfo_Location) ProtoMessage() {}
+func (*SourceCodeInfo_Location) Descriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{19, 0}
+}
+
+func (m *SourceCodeInfo_Location) GetPath() []int32 {
+ if m != nil {
+ return m.Path
+ }
+ return nil
+}
+
+func (m *SourceCodeInfo_Location) GetSpan() []int32 {
+ if m != nil {
+ return m.Span
+ }
+ return nil
+}
+
+func (m *SourceCodeInfo_Location) GetLeadingComments() string {
+ if m != nil && m.LeadingComments != nil {
+ return *m.LeadingComments
+ }
+ return ""
+}
+
+func (m *SourceCodeInfo_Location) GetTrailingComments() string {
+ if m != nil && m.TrailingComments != nil {
+ return *m.TrailingComments
+ }
+ return ""
+}
+
+func (m *SourceCodeInfo_Location) GetLeadingDetachedComments() []string {
+ if m != nil {
+ return m.LeadingDetachedComments
+ }
+ return nil
+}
+
+// Describes the relationship between generated code and its original source
+// file. A GeneratedCodeInfo message is associated with only one generated
+// source file, but may contain references to different source .proto files.
+type GeneratedCodeInfo struct {
+ // An Annotation connects some span of text in generated code to an element
+ // of its generating .proto file.
+ Annotation []*GeneratedCodeInfo_Annotation `protobuf:"bytes,1,rep,name=annotation" json:"annotation,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GeneratedCodeInfo) Reset() { *m = GeneratedCodeInfo{} }
+func (m *GeneratedCodeInfo) String() string { return proto.CompactTextString(m) }
+func (*GeneratedCodeInfo) ProtoMessage() {}
+func (*GeneratedCodeInfo) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{20} }
+
+func (m *GeneratedCodeInfo) GetAnnotation() []*GeneratedCodeInfo_Annotation {
+ if m != nil {
+ return m.Annotation
+ }
+ return nil
+}
+
+type GeneratedCodeInfo_Annotation struct {
+ // Identifies the element in the original source .proto file. This field
+ // is formatted the same as SourceCodeInfo.Location.path.
+ Path []int32 `protobuf:"varint,1,rep,packed,name=path" json:"path,omitempty"`
+ // Identifies the filesystem path to the original source .proto.
+ SourceFile *string `protobuf:"bytes,2,opt,name=source_file,json=sourceFile" json:"source_file,omitempty"`
+ // Identifies the starting offset in bytes in the generated code
+ // that relates to the identified object.
+ Begin *int32 `protobuf:"varint,3,opt,name=begin" json:"begin,omitempty"`
+ // Identifies the ending offset in bytes in the generated code that
+ // relates to the identified offset. The end offset should be one past
+ // the last relevant byte (so the length of the text = end - begin).
+ End *int32 `protobuf:"varint,4,opt,name=end" json:"end,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GeneratedCodeInfo_Annotation) Reset() { *m = GeneratedCodeInfo_Annotation{} }
+func (m *GeneratedCodeInfo_Annotation) String() string { return proto.CompactTextString(m) }
+func (*GeneratedCodeInfo_Annotation) ProtoMessage() {}
+func (*GeneratedCodeInfo_Annotation) Descriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{20, 0}
+}
+
+func (m *GeneratedCodeInfo_Annotation) GetPath() []int32 {
+ if m != nil {
+ return m.Path
+ }
+ return nil
+}
+
+func (m *GeneratedCodeInfo_Annotation) GetSourceFile() string {
+ if m != nil && m.SourceFile != nil {
+ return *m.SourceFile
+ }
+ return ""
+}
+
+func (m *GeneratedCodeInfo_Annotation) GetBegin() int32 {
+ if m != nil && m.Begin != nil {
+ return *m.Begin
+ }
+ return 0
+}
+
+func (m *GeneratedCodeInfo_Annotation) GetEnd() int32 {
+ if m != nil && m.End != nil {
+ return *m.End
+ }
+ return 0
+}
+
+func init() {
+ proto.RegisterType((*FileDescriptorSet)(nil), "google.protobuf.FileDescriptorSet")
+ proto.RegisterType((*FileDescriptorProto)(nil), "google.protobuf.FileDescriptorProto")
+ proto.RegisterType((*DescriptorProto)(nil), "google.protobuf.DescriptorProto")
+ proto.RegisterType((*DescriptorProto_ExtensionRange)(nil), "google.protobuf.DescriptorProto.ExtensionRange")
+ proto.RegisterType((*DescriptorProto_ReservedRange)(nil), "google.protobuf.DescriptorProto.ReservedRange")
+ proto.RegisterType((*ExtensionRangeOptions)(nil), "google.protobuf.ExtensionRangeOptions")
+ proto.RegisterType((*FieldDescriptorProto)(nil), "google.protobuf.FieldDescriptorProto")
+ proto.RegisterType((*OneofDescriptorProto)(nil), "google.protobuf.OneofDescriptorProto")
+ proto.RegisterType((*EnumDescriptorProto)(nil), "google.protobuf.EnumDescriptorProto")
+ proto.RegisterType((*EnumDescriptorProto_EnumReservedRange)(nil), "google.protobuf.EnumDescriptorProto.EnumReservedRange")
+ proto.RegisterType((*EnumValueDescriptorProto)(nil), "google.protobuf.EnumValueDescriptorProto")
+ proto.RegisterType((*ServiceDescriptorProto)(nil), "google.protobuf.ServiceDescriptorProto")
+ proto.RegisterType((*MethodDescriptorProto)(nil), "google.protobuf.MethodDescriptorProto")
+ proto.RegisterType((*FileOptions)(nil), "google.protobuf.FileOptions")
+ proto.RegisterType((*MessageOptions)(nil), "google.protobuf.MessageOptions")
+ proto.RegisterType((*FieldOptions)(nil), "google.protobuf.FieldOptions")
+ proto.RegisterType((*OneofOptions)(nil), "google.protobuf.OneofOptions")
+ proto.RegisterType((*EnumOptions)(nil), "google.protobuf.EnumOptions")
+ proto.RegisterType((*EnumValueOptions)(nil), "google.protobuf.EnumValueOptions")
+ proto.RegisterType((*ServiceOptions)(nil), "google.protobuf.ServiceOptions")
+ proto.RegisterType((*MethodOptions)(nil), "google.protobuf.MethodOptions")
+ proto.RegisterType((*UninterpretedOption)(nil), "google.protobuf.UninterpretedOption")
+ proto.RegisterType((*UninterpretedOption_NamePart)(nil), "google.protobuf.UninterpretedOption.NamePart")
+ proto.RegisterType((*SourceCodeInfo)(nil), "google.protobuf.SourceCodeInfo")
+ proto.RegisterType((*SourceCodeInfo_Location)(nil), "google.protobuf.SourceCodeInfo.Location")
+ proto.RegisterType((*GeneratedCodeInfo)(nil), "google.protobuf.GeneratedCodeInfo")
+ proto.RegisterType((*GeneratedCodeInfo_Annotation)(nil), "google.protobuf.GeneratedCodeInfo.Annotation")
+ proto.RegisterEnum("google.protobuf.FieldDescriptorProto_Type", FieldDescriptorProto_Type_name, FieldDescriptorProto_Type_value)
+ proto.RegisterEnum("google.protobuf.FieldDescriptorProto_Label", FieldDescriptorProto_Label_name, FieldDescriptorProto_Label_value)
+ proto.RegisterEnum("google.protobuf.FileOptions_OptimizeMode", FileOptions_OptimizeMode_name, FileOptions_OptimizeMode_value)
+ proto.RegisterEnum("google.protobuf.FieldOptions_CType", FieldOptions_CType_name, FieldOptions_CType_value)
+ proto.RegisterEnum("google.protobuf.FieldOptions_JSType", FieldOptions_JSType_name, FieldOptions_JSType_value)
+ proto.RegisterEnum("google.protobuf.MethodOptions_IdempotencyLevel", MethodOptions_IdempotencyLevel_name, MethodOptions_IdempotencyLevel_value)
+}
+
+func init() { proto.RegisterFile("descriptor.proto", fileDescriptorDescriptor) }
+
+var fileDescriptorDescriptor = []byte{
+ // 2487 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0xcd, 0x6f, 0xdb, 0xc8,
+ 0x15, 0x5f, 0x7d, 0x5a, 0x7a, 0x92, 0xe5, 0xf1, 0xd8, 0x9b, 0x30, 0xde, 0x8f, 0x38, 0xda, 0x8f,
+ 0x38, 0x49, 0xab, 0x2c, 0x9c, 0xc4, 0xc9, 0x3a, 0xc5, 0xb6, 0xb2, 0xc4, 0x78, 0x95, 0xca, 0x92,
+ 0x4a, 0xc9, 0xdd, 0x64, 0x8b, 0x82, 0x18, 0x93, 0x23, 0x89, 0x09, 0x45, 0x72, 0x49, 0x2a, 0x89,
+ 0x83, 0x1e, 0x02, 0xf4, 0xd4, 0xff, 0xa0, 0x28, 0x8a, 0x1e, 0x7a, 0x59, 0xa0, 0xd7, 0x02, 0x05,
+ 0xda, 0x7b, 0xaf, 0x05, 0x7a, 0xef, 0xa1, 0x40, 0x0b, 0xb4, 0x7f, 0x42, 0x8f, 0xc5, 0xcc, 0x90,
+ 0x14, 0xf5, 0x95, 0x78, 0x17, 0x48, 0xf6, 0x64, 0xcf, 0xef, 0xfd, 0xde, 0xe3, 0x9b, 0x37, 0x6f,
+ 0xde, 0xbc, 0x19, 0x01, 0xd2, 0xa9, 0xa7, 0xb9, 0x86, 0xe3, 0xdb, 0x6e, 0xc5, 0x71, 0x6d, 0xdf,
+ 0xc6, 0x6b, 0x03, 0xdb, 0x1e, 0x98, 0x54, 0x8c, 0x4e, 0xc6, 0xfd, 0xf2, 0x11, 0xac, 0xdf, 0x33,
+ 0x4c, 0x5a, 0x8f, 0x88, 0x5d, 0xea, 0xe3, 0x3b, 0x90, 0xee, 0x1b, 0x26, 0x95, 0x12, 0xdb, 0xa9,
+ 0x9d, 0xc2, 0xee, 0x87, 0x95, 0x19, 0xa5, 0xca, 0xb4, 0x46, 0x87, 0xc1, 0x0a, 0xd7, 0x28, 0xff,
+ 0x3b, 0x0d, 0x1b, 0x0b, 0xa4, 0x18, 0x43, 0xda, 0x22, 0x23, 0x66, 0x31, 0xb1, 0x93, 0x57, 0xf8,
+ 0xff, 0x58, 0x82, 0x15, 0x87, 0x68, 0x8f, 0xc9, 0x80, 0x4a, 0x49, 0x0e, 0x87, 0x43, 0xfc, 0x3e,
+ 0x80, 0x4e, 0x1d, 0x6a, 0xe9, 0xd4, 0xd2, 0x4e, 0xa5, 0xd4, 0x76, 0x6a, 0x27, 0xaf, 0xc4, 0x10,
+ 0x7c, 0x0d, 0xd6, 0x9d, 0xf1, 0x89, 0x69, 0x68, 0x6a, 0x8c, 0x06, 0xdb, 0xa9, 0x9d, 0x8c, 0x82,
+ 0x84, 0xa0, 0x3e, 0x21, 0x5f, 0x86, 0xb5, 0xa7, 0x94, 0x3c, 0x8e, 0x53, 0x0b, 0x9c, 0x5a, 0x62,
+ 0x70, 0x8c, 0x58, 0x83, 0xe2, 0x88, 0x7a, 0x1e, 0x19, 0x50, 0xd5, 0x3f, 0x75, 0xa8, 0x94, 0xe6,
+ 0xb3, 0xdf, 0x9e, 0x9b, 0xfd, 0xec, 0xcc, 0x0b, 0x81, 0x56, 0xef, 0xd4, 0xa1, 0xb8, 0x0a, 0x79,
+ 0x6a, 0x8d, 0x47, 0xc2, 0x42, 0x66, 0x49, 0xfc, 0x64, 0x6b, 0x3c, 0x9a, 0xb5, 0x92, 0x63, 0x6a,
+ 0x81, 0x89, 0x15, 0x8f, 0xba, 0x4f, 0x0c, 0x8d, 0x4a, 0x59, 0x6e, 0xe0, 0xf2, 0x9c, 0x81, 0xae,
+ 0x90, 0xcf, 0xda, 0x08, 0xf5, 0x70, 0x0d, 0xf2, 0xf4, 0x99, 0x4f, 0x2d, 0xcf, 0xb0, 0x2d, 0x69,
+ 0x85, 0x1b, 0xf9, 0x68, 0xc1, 0x2a, 0x52, 0x53, 0x9f, 0x35, 0x31, 0xd1, 0xc3, 0x7b, 0xb0, 0x62,
+ 0x3b, 0xbe, 0x61, 0x5b, 0x9e, 0x94, 0xdb, 0x4e, 0xec, 0x14, 0x76, 0xdf, 0x5d, 0x98, 0x08, 0x6d,
+ 0xc1, 0x51, 0x42, 0x32, 0x6e, 0x00, 0xf2, 0xec, 0xb1, 0xab, 0x51, 0x55, 0xb3, 0x75, 0xaa, 0x1a,
+ 0x56, 0xdf, 0x96, 0xf2, 0xdc, 0xc0, 0xc5, 0xf9, 0x89, 0x70, 0x62, 0xcd, 0xd6, 0x69, 0xc3, 0xea,
+ 0xdb, 0x4a, 0xc9, 0x9b, 0x1a, 0xe3, 0x73, 0x90, 0xf5, 0x4e, 0x2d, 0x9f, 0x3c, 0x93, 0x8a, 0x3c,
+ 0x43, 0x82, 0x51, 0xf9, 0xcf, 0x59, 0x58, 0x3b, 0x4b, 0x8a, 0xdd, 0x85, 0x4c, 0x9f, 0xcd, 0x52,
+ 0x4a, 0x7e, 0x93, 0x18, 0x08, 0x9d, 0xe9, 0x20, 0x66, 0xbf, 0x65, 0x10, 0xab, 0x50, 0xb0, 0xa8,
+ 0xe7, 0x53, 0x5d, 0x64, 0x44, 0xea, 0x8c, 0x39, 0x05, 0x42, 0x69, 0x3e, 0xa5, 0xd2, 0xdf, 0x2a,
+ 0xa5, 0x1e, 0xc0, 0x5a, 0xe4, 0x92, 0xea, 0x12, 0x6b, 0x10, 0xe6, 0xe6, 0xf5, 0x57, 0x79, 0x52,
+ 0x91, 0x43, 0x3d, 0x85, 0xa9, 0x29, 0x25, 0x3a, 0x35, 0xc6, 0x75, 0x00, 0xdb, 0xa2, 0x76, 0x5f,
+ 0xd5, 0xa9, 0x66, 0x4a, 0xb9, 0x25, 0x51, 0x6a, 0x33, 0xca, 0x5c, 0x94, 0x6c, 0x81, 0x6a, 0x26,
+ 0xfe, 0x74, 0x92, 0x6a, 0x2b, 0x4b, 0x32, 0xe5, 0x48, 0x6c, 0xb2, 0xb9, 0x6c, 0x3b, 0x86, 0x92,
+ 0x4b, 0x59, 0xde, 0x53, 0x3d, 0x98, 0x59, 0x9e, 0x3b, 0x51, 0x79, 0xe5, 0xcc, 0x94, 0x40, 0x4d,
+ 0x4c, 0x6c, 0xd5, 0x8d, 0x0f, 0xf1, 0x07, 0x10, 0x01, 0x2a, 0x4f, 0x2b, 0xe0, 0x55, 0xa8, 0x18,
+ 0x82, 0x2d, 0x32, 0xa2, 0x5b, 0xcf, 0xa1, 0x34, 0x1d, 0x1e, 0xbc, 0x09, 0x19, 0xcf, 0x27, 0xae,
+ 0xcf, 0xb3, 0x30, 0xa3, 0x88, 0x01, 0x46, 0x90, 0xa2, 0x96, 0xce, 0xab, 0x5c, 0x46, 0x61, 0xff,
+ 0xe2, 0x1f, 0x4d, 0x26, 0x9c, 0xe2, 0x13, 0xfe, 0x78, 0x7e, 0x45, 0xa7, 0x2c, 0xcf, 0xce, 0x7b,
+ 0xeb, 0x36, 0xac, 0x4e, 0x4d, 0xe0, 0xac, 0x9f, 0x2e, 0xff, 0x02, 0xde, 0x5e, 0x68, 0x1a, 0x3f,
+ 0x80, 0xcd, 0xb1, 0x65, 0x58, 0x3e, 0x75, 0x1d, 0x97, 0xb2, 0x8c, 0x15, 0x9f, 0x92, 0xfe, 0xb3,
+ 0xb2, 0x24, 0xe7, 0x8e, 0xe3, 0x6c, 0x61, 0x45, 0xd9, 0x18, 0xcf, 0x83, 0x57, 0xf3, 0xb9, 0xff,
+ 0xae, 0xa0, 0x17, 0x2f, 0x5e, 0xbc, 0x48, 0x96, 0x7f, 0x9d, 0x85, 0xcd, 0x45, 0x7b, 0x66, 0xe1,
+ 0xf6, 0x3d, 0x07, 0x59, 0x6b, 0x3c, 0x3a, 0xa1, 0x2e, 0x0f, 0x52, 0x46, 0x09, 0x46, 0xb8, 0x0a,
+ 0x19, 0x93, 0x9c, 0x50, 0x53, 0x4a, 0x6f, 0x27, 0x76, 0x4a, 0xbb, 0xd7, 0xce, 0xb4, 0x2b, 0x2b,
+ 0x4d, 0xa6, 0xa2, 0x08, 0x4d, 0xfc, 0x19, 0xa4, 0x83, 0x12, 0xcd, 0x2c, 0x5c, 0x3d, 0x9b, 0x05,
+ 0xb6, 0x97, 0x14, 0xae, 0x87, 0xdf, 0x81, 0x3c, 0xfb, 0x2b, 0x72, 0x23, 0xcb, 0x7d, 0xce, 0x31,
+ 0x80, 0xe5, 0x05, 0xde, 0x82, 0x1c, 0xdf, 0x26, 0x3a, 0x0d, 0x8f, 0xb6, 0x68, 0xcc, 0x12, 0x4b,
+ 0xa7, 0x7d, 0x32, 0x36, 0x7d, 0xf5, 0x09, 0x31, 0xc7, 0x94, 0x27, 0x7c, 0x5e, 0x29, 0x06, 0xe0,
+ 0x4f, 0x19, 0x86, 0x2f, 0x42, 0x41, 0xec, 0x2a, 0xc3, 0xd2, 0xe9, 0x33, 0x5e, 0x3d, 0x33, 0x8a,
+ 0xd8, 0x68, 0x0d, 0x86, 0xb0, 0xcf, 0x3f, 0xf2, 0x6c, 0x2b, 0x4c, 0x4d, 0xfe, 0x09, 0x06, 0xf0,
+ 0xcf, 0xdf, 0x9e, 0x2d, 0xdc, 0xef, 0x2d, 0x9e, 0xde, 0x6c, 0x4e, 0x95, 0xff, 0x94, 0x84, 0x34,
+ 0xaf, 0x17, 0x6b, 0x50, 0xe8, 0x3d, 0xec, 0xc8, 0x6a, 0xbd, 0x7d, 0x7c, 0xd0, 0x94, 0x51, 0x02,
+ 0x97, 0x00, 0x38, 0x70, 0xaf, 0xd9, 0xae, 0xf6, 0x50, 0x32, 0x1a, 0x37, 0x5a, 0xbd, 0xbd, 0x9b,
+ 0x28, 0x15, 0x29, 0x1c, 0x0b, 0x20, 0x1d, 0x27, 0xdc, 0xd8, 0x45, 0x19, 0x8c, 0xa0, 0x28, 0x0c,
+ 0x34, 0x1e, 0xc8, 0xf5, 0xbd, 0x9b, 0x28, 0x3b, 0x8d, 0xdc, 0xd8, 0x45, 0x2b, 0x78, 0x15, 0xf2,
+ 0x1c, 0x39, 0x68, 0xb7, 0x9b, 0x28, 0x17, 0xd9, 0xec, 0xf6, 0x94, 0x46, 0xeb, 0x10, 0xe5, 0x23,
+ 0x9b, 0x87, 0x4a, 0xfb, 0xb8, 0x83, 0x20, 0xb2, 0x70, 0x24, 0x77, 0xbb, 0xd5, 0x43, 0x19, 0x15,
+ 0x22, 0xc6, 0xc1, 0xc3, 0x9e, 0xdc, 0x45, 0xc5, 0x29, 0xb7, 0x6e, 0xec, 0xa2, 0xd5, 0xe8, 0x13,
+ 0x72, 0xeb, 0xf8, 0x08, 0x95, 0xf0, 0x3a, 0xac, 0x8a, 0x4f, 0x84, 0x4e, 0xac, 0xcd, 0x40, 0x7b,
+ 0x37, 0x11, 0x9a, 0x38, 0x22, 0xac, 0xac, 0x4f, 0x01, 0x7b, 0x37, 0x11, 0x2e, 0xd7, 0x20, 0xc3,
+ 0xb3, 0x0b, 0x63, 0x28, 0x35, 0xab, 0x07, 0x72, 0x53, 0x6d, 0x77, 0x7a, 0x8d, 0x76, 0xab, 0xda,
+ 0x44, 0x89, 0x09, 0xa6, 0xc8, 0x3f, 0x39, 0x6e, 0x28, 0x72, 0x1d, 0x25, 0xe3, 0x58, 0x47, 0xae,
+ 0xf6, 0xe4, 0x3a, 0x4a, 0x95, 0x35, 0xd8, 0x5c, 0x54, 0x27, 0x17, 0xee, 0x8c, 0xd8, 0x12, 0x27,
+ 0x97, 0x2c, 0x31, 0xb7, 0x35, 0xb7, 0xc4, 0xff, 0x4a, 0xc2, 0xc6, 0x82, 0xb3, 0x62, 0xe1, 0x47,
+ 0x7e, 0x08, 0x19, 0x91, 0xa2, 0xe2, 0xf4, 0xbc, 0xb2, 0xf0, 0xd0, 0xe1, 0x09, 0x3b, 0x77, 0x82,
+ 0x72, 0xbd, 0x78, 0x07, 0x91, 0x5a, 0xd2, 0x41, 0x30, 0x13, 0x73, 0x35, 0xfd, 0xe7, 0x73, 0x35,
+ 0x5d, 0x1c, 0x7b, 0x7b, 0x67, 0x39, 0xf6, 0x38, 0xf6, 0xcd, 0x6a, 0x7b, 0x66, 0x41, 0x6d, 0xbf,
+ 0x0b, 0xeb, 0x73, 0x86, 0xce, 0x5c, 0x63, 0x7f, 0x99, 0x00, 0x69, 0x59, 0x70, 0x5e, 0x51, 0xe9,
+ 0x92, 0x53, 0x95, 0xee, 0xee, 0x6c, 0x04, 0x2f, 0x2d, 0x5f, 0x84, 0xb9, 0xb5, 0xfe, 0x3a, 0x01,
+ 0xe7, 0x16, 0x77, 0x8a, 0x0b, 0x7d, 0xf8, 0x0c, 0xb2, 0x23, 0xea, 0x0f, 0xed, 0xb0, 0x5b, 0xfa,
+ 0x78, 0xc1, 0x19, 0xcc, 0xc4, 0xb3, 0x8b, 0x1d, 0x68, 0xc5, 0x0f, 0xf1, 0xd4, 0xb2, 0x76, 0x4f,
+ 0x78, 0x33, 0xe7, 0xe9, 0xaf, 0x92, 0xf0, 0xf6, 0x42, 0xe3, 0x0b, 0x1d, 0x7d, 0x0f, 0xc0, 0xb0,
+ 0x9c, 0xb1, 0x2f, 0x3a, 0x22, 0x51, 0x60, 0xf3, 0x1c, 0xe1, 0xc5, 0x8b, 0x15, 0xcf, 0xb1, 0x1f,
+ 0xc9, 0x53, 0x5c, 0x0e, 0x02, 0xe2, 0x84, 0x3b, 0x13, 0x47, 0xd3, 0xdc, 0xd1, 0xf7, 0x97, 0xcc,
+ 0x74, 0x2e, 0x31, 0x3f, 0x01, 0xa4, 0x99, 0x06, 0xb5, 0x7c, 0xd5, 0xf3, 0x5d, 0x4a, 0x46, 0x86,
+ 0x35, 0xe0, 0x27, 0x48, 0x6e, 0x3f, 0xd3, 0x27, 0xa6, 0x47, 0x95, 0x35, 0x21, 0xee, 0x86, 0x52,
+ 0xa6, 0xc1, 0x13, 0xc8, 0x8d, 0x69, 0x64, 0xa7, 0x34, 0x84, 0x38, 0xd2, 0x28, 0xff, 0x31, 0x07,
+ 0x85, 0x58, 0x5f, 0x8d, 0x2f, 0x41, 0xf1, 0x11, 0x79, 0x42, 0xd4, 0xf0, 0xae, 0x24, 0x22, 0x51,
+ 0x60, 0x58, 0x27, 0xb8, 0x2f, 0x7d, 0x02, 0x9b, 0x9c, 0x62, 0x8f, 0x7d, 0xea, 0xaa, 0x9a, 0x49,
+ 0x3c, 0x8f, 0x07, 0x2d, 0xc7, 0xa9, 0x98, 0xc9, 0xda, 0x4c, 0x54, 0x0b, 0x25, 0xf8, 0x16, 0x6c,
+ 0x70, 0x8d, 0xd1, 0xd8, 0xf4, 0x0d, 0xc7, 0xa4, 0x2a, 0xbb, 0xbd, 0x79, 0xfc, 0x24, 0x89, 0x3c,
+ 0x5b, 0x67, 0x8c, 0xa3, 0x80, 0xc0, 0x3c, 0xf2, 0x70, 0x1d, 0xde, 0xe3, 0x6a, 0x03, 0x6a, 0x51,
+ 0x97, 0xf8, 0x54, 0xa5, 0x5f, 0x8d, 0x89, 0xe9, 0xa9, 0xc4, 0xd2, 0xd5, 0x21, 0xf1, 0x86, 0xd2,
+ 0x26, 0x33, 0x70, 0x90, 0x94, 0x12, 0xca, 0x05, 0x46, 0x3c, 0x0c, 0x78, 0x32, 0xa7, 0x55, 0x2d,
+ 0xfd, 0x73, 0xe2, 0x0d, 0xf1, 0x3e, 0x9c, 0xe3, 0x56, 0x3c, 0xdf, 0x35, 0xac, 0x81, 0xaa, 0x0d,
+ 0xa9, 0xf6, 0x58, 0x1d, 0xfb, 0xfd, 0x3b, 0xd2, 0x3b, 0xf1, 0xef, 0x73, 0x0f, 0xbb, 0x9c, 0x53,
+ 0x63, 0x94, 0x63, 0xbf, 0x7f, 0x07, 0x77, 0xa1, 0xc8, 0x16, 0x63, 0x64, 0x3c, 0xa7, 0x6a, 0xdf,
+ 0x76, 0xf9, 0xd1, 0x58, 0x5a, 0x50, 0x9a, 0x62, 0x11, 0xac, 0xb4, 0x03, 0x85, 0x23, 0x5b, 0xa7,
+ 0xfb, 0x99, 0x6e, 0x47, 0x96, 0xeb, 0x4a, 0x21, 0xb4, 0x72, 0xcf, 0x76, 0x59, 0x42, 0x0d, 0xec,
+ 0x28, 0xc0, 0x05, 0x91, 0x50, 0x03, 0x3b, 0x0c, 0xef, 0x2d, 0xd8, 0xd0, 0x34, 0x31, 0x67, 0x43,
+ 0x53, 0x83, 0x3b, 0x96, 0x27, 0xa1, 0xa9, 0x60, 0x69, 0xda, 0xa1, 0x20, 0x04, 0x39, 0xee, 0xe1,
+ 0x4f, 0xe1, 0xed, 0x49, 0xb0, 0xe2, 0x8a, 0xeb, 0x73, 0xb3, 0x9c, 0x55, 0xbd, 0x05, 0x1b, 0xce,
+ 0xe9, 0xbc, 0x22, 0x9e, 0xfa, 0xa2, 0x73, 0x3a, 0xab, 0x76, 0x1b, 0x36, 0x9d, 0xa1, 0x33, 0xaf,
+ 0x77, 0x35, 0xae, 0x87, 0x9d, 0xa1, 0x33, 0xab, 0xf8, 0x11, 0xbf, 0x70, 0xbb, 0x54, 0x23, 0x3e,
+ 0xd5, 0xa5, 0xf3, 0x71, 0x7a, 0x4c, 0x80, 0xaf, 0x03, 0xd2, 0x34, 0x95, 0x5a, 0xe4, 0xc4, 0xa4,
+ 0x2a, 0x71, 0xa9, 0x45, 0x3c, 0xe9, 0x62, 0x9c, 0x5c, 0xd2, 0x34, 0x99, 0x4b, 0xab, 0x5c, 0x88,
+ 0xaf, 0xc2, 0xba, 0x7d, 0xf2, 0x48, 0x13, 0x29, 0xa9, 0x3a, 0x2e, 0xed, 0x1b, 0xcf, 0xa4, 0x0f,
+ 0x79, 0x7c, 0xd7, 0x98, 0x80, 0x27, 0x64, 0x87, 0xc3, 0xf8, 0x0a, 0x20, 0xcd, 0x1b, 0x12, 0xd7,
+ 0xe1, 0x35, 0xd9, 0x73, 0x88, 0x46, 0xa5, 0x8f, 0x04, 0x55, 0xe0, 0xad, 0x10, 0x66, 0x5b, 0xc2,
+ 0x7b, 0x6a, 0xf4, 0xfd, 0xd0, 0xe2, 0x65, 0xb1, 0x25, 0x38, 0x16, 0x58, 0xdb, 0x01, 0xc4, 0x42,
+ 0x31, 0xf5, 0xe1, 0x1d, 0x4e, 0x2b, 0x39, 0x43, 0x27, 0xfe, 0xdd, 0x0f, 0x60, 0x95, 0x31, 0x27,
+ 0x1f, 0xbd, 0x22, 0x1a, 0x32, 0x67, 0x18, 0xfb, 0xe2, 0x6b, 0xeb, 0x8d, 0xcb, 0xfb, 0x50, 0x8c,
+ 0xe7, 0x27, 0xce, 0x83, 0xc8, 0x50, 0x94, 0x60, 0xcd, 0x4a, 0xad, 0x5d, 0x67, 0x6d, 0xc6, 0x97,
+ 0x32, 0x4a, 0xb2, 0x76, 0xa7, 0xd9, 0xe8, 0xc9, 0xaa, 0x72, 0xdc, 0xea, 0x35, 0x8e, 0x64, 0x94,
+ 0x8a, 0xf7, 0xd5, 0x7f, 0x4d, 0x42, 0x69, 0xfa, 0x8a, 0x84, 0x7f, 0x00, 0xe7, 0xc3, 0xf7, 0x0c,
+ 0x8f, 0xfa, 0xea, 0x53, 0xc3, 0xe5, 0x5b, 0x66, 0x44, 0xc4, 0xf1, 0x15, 0x2d, 0xda, 0x66, 0xc0,
+ 0xea, 0x52, 0xff, 0x0b, 0xc3, 0x65, 0x1b, 0x62, 0x44, 0x7c, 0xdc, 0x84, 0x8b, 0x96, 0xad, 0x7a,
+ 0x3e, 0xb1, 0x74, 0xe2, 0xea, 0xea, 0xe4, 0x25, 0x49, 0x25, 0x9a, 0x46, 0x3d, 0xcf, 0x16, 0x47,
+ 0x55, 0x64, 0xe5, 0x5d, 0xcb, 0xee, 0x06, 0xe4, 0x49, 0x0d, 0xaf, 0x06, 0xd4, 0x99, 0x04, 0x4b,
+ 0x2d, 0x4b, 0xb0, 0x77, 0x20, 0x3f, 0x22, 0x8e, 0x4a, 0x2d, 0xdf, 0x3d, 0xe5, 0x8d, 0x71, 0x4e,
+ 0xc9, 0x8d, 0x88, 0x23, 0xb3, 0xf1, 0x9b, 0xb9, 0x9f, 0xfc, 0x23, 0x05, 0xc5, 0x78, 0x73, 0xcc,
+ 0xee, 0x1a, 0x1a, 0x3f, 0x47, 0x12, 0xbc, 0xd2, 0x7c, 0xf0, 0xd2, 0x56, 0xba, 0x52, 0x63, 0x07,
+ 0xcc, 0x7e, 0x56, 0xb4, 0xac, 0x8a, 0xd0, 0x64, 0x87, 0x3b, 0xab, 0x2d, 0x54, 0xb4, 0x08, 0x39,
+ 0x25, 0x18, 0xe1, 0x43, 0xc8, 0x3e, 0xf2, 0xb8, 0xed, 0x2c, 0xb7, 0xfd, 0xe1, 0xcb, 0x6d, 0xdf,
+ 0xef, 0x72, 0xe3, 0xf9, 0xfb, 0x5d, 0xb5, 0xd5, 0x56, 0x8e, 0xaa, 0x4d, 0x25, 0x50, 0xc7, 0x17,
+ 0x20, 0x6d, 0x92, 0xe7, 0xa7, 0xd3, 0x47, 0x11, 0x87, 0xce, 0x1a, 0xf8, 0x0b, 0x90, 0x7e, 0x4a,
+ 0xc9, 0xe3, 0xe9, 0x03, 0x80, 0x43, 0xaf, 0x31, 0xf5, 0xaf, 0x43, 0x86, 0xc7, 0x0b, 0x03, 0x04,
+ 0x11, 0x43, 0x6f, 0xe1, 0x1c, 0xa4, 0x6b, 0x6d, 0x85, 0xa5, 0x3f, 0x82, 0xa2, 0x40, 0xd5, 0x4e,
+ 0x43, 0xae, 0xc9, 0x28, 0x59, 0xbe, 0x05, 0x59, 0x11, 0x04, 0xb6, 0x35, 0xa2, 0x30, 0xa0, 0xb7,
+ 0x82, 0x61, 0x60, 0x23, 0x11, 0x4a, 0x8f, 0x8f, 0x0e, 0x64, 0x05, 0x25, 0xe3, 0xcb, 0xeb, 0x41,
+ 0x31, 0xde, 0x17, 0xbf, 0x99, 0x9c, 0xfa, 0x4b, 0x02, 0x0a, 0xb1, 0x3e, 0x97, 0x35, 0x28, 0xc4,
+ 0x34, 0xed, 0xa7, 0x2a, 0x31, 0x0d, 0xe2, 0x05, 0x49, 0x01, 0x1c, 0xaa, 0x32, 0xe4, 0xac, 0x8b,
+ 0xf6, 0x46, 0x9c, 0xff, 0x5d, 0x02, 0xd0, 0x6c, 0x8b, 0x39, 0xe3, 0x60, 0xe2, 0x3b, 0x75, 0xf0,
+ 0xb7, 0x09, 0x28, 0x4d, 0xf7, 0x95, 0x33, 0xee, 0x5d, 0xfa, 0x4e, 0xdd, 0xfb, 0x67, 0x12, 0x56,
+ 0xa7, 0xba, 0xc9, 0xb3, 0x7a, 0xf7, 0x15, 0xac, 0x1b, 0x3a, 0x1d, 0x39, 0xb6, 0x4f, 0x2d, 0xed,
+ 0x54, 0x35, 0xe9, 0x13, 0x6a, 0x4a, 0x65, 0x5e, 0x28, 0xae, 0xbf, 0xbc, 0x5f, 0xad, 0x34, 0x26,
+ 0x7a, 0x4d, 0xa6, 0xb6, 0xbf, 0xd1, 0xa8, 0xcb, 0x47, 0x9d, 0x76, 0x4f, 0x6e, 0xd5, 0x1e, 0xaa,
+ 0xc7, 0xad, 0x1f, 0xb7, 0xda, 0x5f, 0xb4, 0x14, 0x64, 0xcc, 0xd0, 0x5e, 0xe3, 0x56, 0xef, 0x00,
+ 0x9a, 0x75, 0x0a, 0x9f, 0x87, 0x45, 0x6e, 0xa1, 0xb7, 0xf0, 0x06, 0xac, 0xb5, 0xda, 0x6a, 0xb7,
+ 0x51, 0x97, 0x55, 0xf9, 0xde, 0x3d, 0xb9, 0xd6, 0xeb, 0x8a, 0x17, 0x88, 0x88, 0xdd, 0x9b, 0xde,
+ 0xd4, 0xbf, 0x49, 0xc1, 0xc6, 0x02, 0x4f, 0x70, 0x35, 0xb8, 0x3b, 0x88, 0xeb, 0xcc, 0xf7, 0xcf,
+ 0xe2, 0x7d, 0x85, 0x1d, 0xf9, 0x1d, 0xe2, 0xfa, 0xc1, 0x55, 0xe3, 0x0a, 0xb0, 0x28, 0x59, 0xbe,
+ 0xd1, 0x37, 0xa8, 0x1b, 0x3c, 0xd8, 0x88, 0x0b, 0xc5, 0xda, 0x04, 0x17, 0x6f, 0x36, 0xdf, 0x03,
+ 0xec, 0xd8, 0x9e, 0xe1, 0x1b, 0x4f, 0xa8, 0x6a, 0x58, 0xe1, 0xeb, 0x0e, 0xbb, 0x60, 0xa4, 0x15,
+ 0x14, 0x4a, 0x1a, 0x96, 0x1f, 0xb1, 0x2d, 0x3a, 0x20, 0x33, 0x6c, 0x56, 0xc0, 0x53, 0x0a, 0x0a,
+ 0x25, 0x11, 0xfb, 0x12, 0x14, 0x75, 0x7b, 0xcc, 0xba, 0x2e, 0xc1, 0x63, 0xe7, 0x45, 0x42, 0x29,
+ 0x08, 0x2c, 0xa2, 0x04, 0xfd, 0xf4, 0xe4, 0x59, 0xa9, 0xa8, 0x14, 0x04, 0x26, 0x28, 0x97, 0x61,
+ 0x8d, 0x0c, 0x06, 0x2e, 0x33, 0x1e, 0x1a, 0x12, 0x37, 0x84, 0x52, 0x04, 0x73, 0xe2, 0xd6, 0x7d,
+ 0xc8, 0x85, 0x71, 0x60, 0x47, 0x32, 0x8b, 0x84, 0xea, 0x88, 0x6b, 0x6f, 0x72, 0x27, 0xaf, 0xe4,
+ 0xac, 0x50, 0x78, 0x09, 0x8a, 0x86, 0xa7, 0x4e, 0x5e, 0xc9, 0x93, 0xdb, 0xc9, 0x9d, 0x9c, 0x52,
+ 0x30, 0xbc, 0xe8, 0x85, 0xb1, 0xfc, 0x75, 0x12, 0x4a, 0xd3, 0xaf, 0xfc, 0xb8, 0x0e, 0x39, 0xd3,
+ 0xd6, 0x08, 0x4f, 0x2d, 0xf1, 0x13, 0xd3, 0xce, 0x2b, 0x7e, 0x18, 0xa8, 0x34, 0x03, 0xbe, 0x12,
+ 0x69, 0x6e, 0xfd, 0x2d, 0x01, 0xb9, 0x10, 0xc6, 0xe7, 0x20, 0xed, 0x10, 0x7f, 0xc8, 0xcd, 0x65,
+ 0x0e, 0x92, 0x28, 0xa1, 0xf0, 0x31, 0xc3, 0x3d, 0x87, 0x58, 0x3c, 0x05, 0x02, 0x9c, 0x8d, 0xd9,
+ 0xba, 0x9a, 0x94, 0xe8, 0xfc, 0xfa, 0x61, 0x8f, 0x46, 0xd4, 0xf2, 0xbd, 0x70, 0x5d, 0x03, 0xbc,
+ 0x16, 0xc0, 0xf8, 0x1a, 0xac, 0xfb, 0x2e, 0x31, 0xcc, 0x29, 0x6e, 0x9a, 0x73, 0x51, 0x28, 0x88,
+ 0xc8, 0xfb, 0x70, 0x21, 0xb4, 0xab, 0x53, 0x9f, 0x68, 0x43, 0xaa, 0x4f, 0x94, 0xb2, 0xfc, 0x99,
+ 0xe1, 0x7c, 0x40, 0xa8, 0x07, 0xf2, 0x50, 0xb7, 0xfc, 0xf7, 0x04, 0xac, 0x87, 0x17, 0x26, 0x3d,
+ 0x0a, 0xd6, 0x11, 0x00, 0xb1, 0x2c, 0xdb, 0x8f, 0x87, 0x6b, 0x3e, 0x95, 0xe7, 0xf4, 0x2a, 0xd5,
+ 0x48, 0x49, 0x89, 0x19, 0xd8, 0x1a, 0x01, 0x4c, 0x24, 0x4b, 0xc3, 0x76, 0x11, 0x0a, 0xc1, 0x4f,
+ 0x38, 0xfc, 0x77, 0x40, 0x71, 0xc5, 0x06, 0x01, 0xb1, 0x9b, 0x15, 0xde, 0x84, 0xcc, 0x09, 0x1d,
+ 0x18, 0x56, 0xf0, 0x30, 0x2b, 0x06, 0xe1, 0x43, 0x48, 0x3a, 0x7a, 0x08, 0x39, 0xf8, 0x19, 0x6c,
+ 0x68, 0xf6, 0x68, 0xd6, 0xdd, 0x03, 0x34, 0x73, 0xcd, 0xf7, 0x3e, 0x4f, 0x7c, 0x09, 0x93, 0x16,
+ 0xf3, 0x7f, 0x89, 0xc4, 0xef, 0x93, 0xa9, 0xc3, 0xce, 0xc1, 0x1f, 0x92, 0x5b, 0x87, 0x42, 0xb5,
+ 0x13, 0xce, 0x54, 0xa1, 0x7d, 0x93, 0x6a, 0xcc, 0xfb, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, 0xa3,
+ 0x58, 0x22, 0x30, 0xdf, 0x1c, 0x00, 0x00,
+}
--- /dev/null
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: descriptor.proto
+
+/*
+Package descriptor is a generated protocol buffer package.
+
+It is generated from these files:
+ descriptor.proto
+
+It has these top-level messages:
+ FileDescriptorSet
+ FileDescriptorProto
+ DescriptorProto
+ ExtensionRangeOptions
+ FieldDescriptorProto
+ OneofDescriptorProto
+ EnumDescriptorProto
+ EnumValueDescriptorProto
+ ServiceDescriptorProto
+ MethodDescriptorProto
+ FileOptions
+ MessageOptions
+ FieldOptions
+ OneofOptions
+ EnumOptions
+ EnumValueOptions
+ ServiceOptions
+ MethodOptions
+ UninterpretedOption
+ SourceCodeInfo
+ GeneratedCodeInfo
+*/
+package descriptor
+
+import fmt "fmt"
+import strings "strings"
+import proto "github.com/gogo/protobuf/proto"
+import sort "sort"
+import strconv "strconv"
+import reflect "reflect"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+func (this *FileDescriptorSet) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&descriptor.FileDescriptorSet{")
+ if this.File != nil {
+ s = append(s, "File: "+fmt.Sprintf("%#v", this.File)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *FileDescriptorProto) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 16)
+ s = append(s, "&descriptor.FileDescriptorProto{")
+ if this.Name != nil {
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
+ }
+ if this.Package != nil {
+ s = append(s, "Package: "+valueToGoStringDescriptor(this.Package, "string")+",\n")
+ }
+ if this.Dependency != nil {
+ s = append(s, "Dependency: "+fmt.Sprintf("%#v", this.Dependency)+",\n")
+ }
+ if this.PublicDependency != nil {
+ s = append(s, "PublicDependency: "+fmt.Sprintf("%#v", this.PublicDependency)+",\n")
+ }
+ if this.WeakDependency != nil {
+ s = append(s, "WeakDependency: "+fmt.Sprintf("%#v", this.WeakDependency)+",\n")
+ }
+ if this.MessageType != nil {
+ s = append(s, "MessageType: "+fmt.Sprintf("%#v", this.MessageType)+",\n")
+ }
+ if this.EnumType != nil {
+ s = append(s, "EnumType: "+fmt.Sprintf("%#v", this.EnumType)+",\n")
+ }
+ if this.Service != nil {
+ s = append(s, "Service: "+fmt.Sprintf("%#v", this.Service)+",\n")
+ }
+ if this.Extension != nil {
+ s = append(s, "Extension: "+fmt.Sprintf("%#v", this.Extension)+",\n")
+ }
+ if this.Options != nil {
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
+ }
+ if this.SourceCodeInfo != nil {
+ s = append(s, "SourceCodeInfo: "+fmt.Sprintf("%#v", this.SourceCodeInfo)+",\n")
+ }
+ if this.Syntax != nil {
+ s = append(s, "Syntax: "+valueToGoStringDescriptor(this.Syntax, "string")+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *DescriptorProto) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 14)
+ s = append(s, "&descriptor.DescriptorProto{")
+ if this.Name != nil {
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
+ }
+ if this.Field != nil {
+ s = append(s, "Field: "+fmt.Sprintf("%#v", this.Field)+",\n")
+ }
+ if this.Extension != nil {
+ s = append(s, "Extension: "+fmt.Sprintf("%#v", this.Extension)+",\n")
+ }
+ if this.NestedType != nil {
+ s = append(s, "NestedType: "+fmt.Sprintf("%#v", this.NestedType)+",\n")
+ }
+ if this.EnumType != nil {
+ s = append(s, "EnumType: "+fmt.Sprintf("%#v", this.EnumType)+",\n")
+ }
+ if this.ExtensionRange != nil {
+ s = append(s, "ExtensionRange: "+fmt.Sprintf("%#v", this.ExtensionRange)+",\n")
+ }
+ if this.OneofDecl != nil {
+ s = append(s, "OneofDecl: "+fmt.Sprintf("%#v", this.OneofDecl)+",\n")
+ }
+ if this.Options != nil {
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
+ }
+ if this.ReservedRange != nil {
+ s = append(s, "ReservedRange: "+fmt.Sprintf("%#v", this.ReservedRange)+",\n")
+ }
+ if this.ReservedName != nil {
+ s = append(s, "ReservedName: "+fmt.Sprintf("%#v", this.ReservedName)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *DescriptorProto_ExtensionRange) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 7)
+ s = append(s, "&descriptor.DescriptorProto_ExtensionRange{")
+ if this.Start != nil {
+ s = append(s, "Start: "+valueToGoStringDescriptor(this.Start, "int32")+",\n")
+ }
+ if this.End != nil {
+ s = append(s, "End: "+valueToGoStringDescriptor(this.End, "int32")+",\n")
+ }
+ if this.Options != nil {
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *DescriptorProto_ReservedRange) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 6)
+ s = append(s, "&descriptor.DescriptorProto_ReservedRange{")
+ if this.Start != nil {
+ s = append(s, "Start: "+valueToGoStringDescriptor(this.Start, "int32")+",\n")
+ }
+ if this.End != nil {
+ s = append(s, "End: "+valueToGoStringDescriptor(this.End, "int32")+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *ExtensionRangeOptions) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&descriptor.ExtensionRangeOptions{")
+ if this.UninterpretedOption != nil {
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
+ }
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *FieldDescriptorProto) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 14)
+ s = append(s, "&descriptor.FieldDescriptorProto{")
+ if this.Name != nil {
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
+ }
+ if this.Number != nil {
+ s = append(s, "Number: "+valueToGoStringDescriptor(this.Number, "int32")+",\n")
+ }
+ if this.Label != nil {
+ s = append(s, "Label: "+valueToGoStringDescriptor(this.Label, "FieldDescriptorProto_Label")+",\n")
+ }
+ if this.Type != nil {
+ s = append(s, "Type: "+valueToGoStringDescriptor(this.Type, "FieldDescriptorProto_Type")+",\n")
+ }
+ if this.TypeName != nil {
+ s = append(s, "TypeName: "+valueToGoStringDescriptor(this.TypeName, "string")+",\n")
+ }
+ if this.Extendee != nil {
+ s = append(s, "Extendee: "+valueToGoStringDescriptor(this.Extendee, "string")+",\n")
+ }
+ if this.DefaultValue != nil {
+ s = append(s, "DefaultValue: "+valueToGoStringDescriptor(this.DefaultValue, "string")+",\n")
+ }
+ if this.OneofIndex != nil {
+ s = append(s, "OneofIndex: "+valueToGoStringDescriptor(this.OneofIndex, "int32")+",\n")
+ }
+ if this.JsonName != nil {
+ s = append(s, "JsonName: "+valueToGoStringDescriptor(this.JsonName, "string")+",\n")
+ }
+ if this.Options != nil {
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *OneofDescriptorProto) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 6)
+ s = append(s, "&descriptor.OneofDescriptorProto{")
+ if this.Name != nil {
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
+ }
+ if this.Options != nil {
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *EnumDescriptorProto) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 9)
+ s = append(s, "&descriptor.EnumDescriptorProto{")
+ if this.Name != nil {
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
+ }
+ if this.Value != nil {
+ s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n")
+ }
+ if this.Options != nil {
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
+ }
+ if this.ReservedRange != nil {
+ s = append(s, "ReservedRange: "+fmt.Sprintf("%#v", this.ReservedRange)+",\n")
+ }
+ if this.ReservedName != nil {
+ s = append(s, "ReservedName: "+fmt.Sprintf("%#v", this.ReservedName)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *EnumDescriptorProto_EnumReservedRange) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 6)
+ s = append(s, "&descriptor.EnumDescriptorProto_EnumReservedRange{")
+ if this.Start != nil {
+ s = append(s, "Start: "+valueToGoStringDescriptor(this.Start, "int32")+",\n")
+ }
+ if this.End != nil {
+ s = append(s, "End: "+valueToGoStringDescriptor(this.End, "int32")+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *EnumValueDescriptorProto) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 7)
+ s = append(s, "&descriptor.EnumValueDescriptorProto{")
+ if this.Name != nil {
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
+ }
+ if this.Number != nil {
+ s = append(s, "Number: "+valueToGoStringDescriptor(this.Number, "int32")+",\n")
+ }
+ if this.Options != nil {
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *ServiceDescriptorProto) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 7)
+ s = append(s, "&descriptor.ServiceDescriptorProto{")
+ if this.Name != nil {
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
+ }
+ if this.Method != nil {
+ s = append(s, "Method: "+fmt.Sprintf("%#v", this.Method)+",\n")
+ }
+ if this.Options != nil {
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *MethodDescriptorProto) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 10)
+ s = append(s, "&descriptor.MethodDescriptorProto{")
+ if this.Name != nil {
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
+ }
+ if this.InputType != nil {
+ s = append(s, "InputType: "+valueToGoStringDescriptor(this.InputType, "string")+",\n")
+ }
+ if this.OutputType != nil {
+ s = append(s, "OutputType: "+valueToGoStringDescriptor(this.OutputType, "string")+",\n")
+ }
+ if this.Options != nil {
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
+ }
+ if this.ClientStreaming != nil {
+ s = append(s, "ClientStreaming: "+valueToGoStringDescriptor(this.ClientStreaming, "bool")+",\n")
+ }
+ if this.ServerStreaming != nil {
+ s = append(s, "ServerStreaming: "+valueToGoStringDescriptor(this.ServerStreaming, "bool")+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *FileOptions) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 23)
+ s = append(s, "&descriptor.FileOptions{")
+ if this.JavaPackage != nil {
+ s = append(s, "JavaPackage: "+valueToGoStringDescriptor(this.JavaPackage, "string")+",\n")
+ }
+ if this.JavaOuterClassname != nil {
+ s = append(s, "JavaOuterClassname: "+valueToGoStringDescriptor(this.JavaOuterClassname, "string")+",\n")
+ }
+ if this.JavaMultipleFiles != nil {
+ s = append(s, "JavaMultipleFiles: "+valueToGoStringDescriptor(this.JavaMultipleFiles, "bool")+",\n")
+ }
+ if this.JavaGenerateEqualsAndHash != nil {
+ s = append(s, "JavaGenerateEqualsAndHash: "+valueToGoStringDescriptor(this.JavaGenerateEqualsAndHash, "bool")+",\n")
+ }
+ if this.JavaStringCheckUtf8 != nil {
+ s = append(s, "JavaStringCheckUtf8: "+valueToGoStringDescriptor(this.JavaStringCheckUtf8, "bool")+",\n")
+ }
+ if this.OptimizeFor != nil {
+ s = append(s, "OptimizeFor: "+valueToGoStringDescriptor(this.OptimizeFor, "FileOptions_OptimizeMode")+",\n")
+ }
+ if this.GoPackage != nil {
+ s = append(s, "GoPackage: "+valueToGoStringDescriptor(this.GoPackage, "string")+",\n")
+ }
+ if this.CcGenericServices != nil {
+ s = append(s, "CcGenericServices: "+valueToGoStringDescriptor(this.CcGenericServices, "bool")+",\n")
+ }
+ if this.JavaGenericServices != nil {
+ s = append(s, "JavaGenericServices: "+valueToGoStringDescriptor(this.JavaGenericServices, "bool")+",\n")
+ }
+ if this.PyGenericServices != nil {
+ s = append(s, "PyGenericServices: "+valueToGoStringDescriptor(this.PyGenericServices, "bool")+",\n")
+ }
+ if this.PhpGenericServices != nil {
+ s = append(s, "PhpGenericServices: "+valueToGoStringDescriptor(this.PhpGenericServices, "bool")+",\n")
+ }
+ if this.Deprecated != nil {
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
+ }
+ if this.CcEnableArenas != nil {
+ s = append(s, "CcEnableArenas: "+valueToGoStringDescriptor(this.CcEnableArenas, "bool")+",\n")
+ }
+ if this.ObjcClassPrefix != nil {
+ s = append(s, "ObjcClassPrefix: "+valueToGoStringDescriptor(this.ObjcClassPrefix, "string")+",\n")
+ }
+ if this.CsharpNamespace != nil {
+ s = append(s, "CsharpNamespace: "+valueToGoStringDescriptor(this.CsharpNamespace, "string")+",\n")
+ }
+ if this.SwiftPrefix != nil {
+ s = append(s, "SwiftPrefix: "+valueToGoStringDescriptor(this.SwiftPrefix, "string")+",\n")
+ }
+ if this.PhpClassPrefix != nil {
+ s = append(s, "PhpClassPrefix: "+valueToGoStringDescriptor(this.PhpClassPrefix, "string")+",\n")
+ }
+ if this.PhpNamespace != nil {
+ s = append(s, "PhpNamespace: "+valueToGoStringDescriptor(this.PhpNamespace, "string")+",\n")
+ }
+ if this.UninterpretedOption != nil {
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
+ }
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *MessageOptions) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 9)
+ s = append(s, "&descriptor.MessageOptions{")
+ if this.MessageSetWireFormat != nil {
+ s = append(s, "MessageSetWireFormat: "+valueToGoStringDescriptor(this.MessageSetWireFormat, "bool")+",\n")
+ }
+ if this.NoStandardDescriptorAccessor != nil {
+ s = append(s, "NoStandardDescriptorAccessor: "+valueToGoStringDescriptor(this.NoStandardDescriptorAccessor, "bool")+",\n")
+ }
+ if this.Deprecated != nil {
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
+ }
+ if this.MapEntry != nil {
+ s = append(s, "MapEntry: "+valueToGoStringDescriptor(this.MapEntry, "bool")+",\n")
+ }
+ if this.UninterpretedOption != nil {
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
+ }
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *FieldOptions) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 11)
+ s = append(s, "&descriptor.FieldOptions{")
+ if this.Ctype != nil {
+ s = append(s, "Ctype: "+valueToGoStringDescriptor(this.Ctype, "FieldOptions_CType")+",\n")
+ }
+ if this.Packed != nil {
+ s = append(s, "Packed: "+valueToGoStringDescriptor(this.Packed, "bool")+",\n")
+ }
+ if this.Jstype != nil {
+ s = append(s, "Jstype: "+valueToGoStringDescriptor(this.Jstype, "FieldOptions_JSType")+",\n")
+ }
+ if this.Lazy != nil {
+ s = append(s, "Lazy: "+valueToGoStringDescriptor(this.Lazy, "bool")+",\n")
+ }
+ if this.Deprecated != nil {
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
+ }
+ if this.Weak != nil {
+ s = append(s, "Weak: "+valueToGoStringDescriptor(this.Weak, "bool")+",\n")
+ }
+ if this.UninterpretedOption != nil {
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
+ }
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *OneofOptions) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&descriptor.OneofOptions{")
+ if this.UninterpretedOption != nil {
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
+ }
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *EnumOptions) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 7)
+ s = append(s, "&descriptor.EnumOptions{")
+ if this.AllowAlias != nil {
+ s = append(s, "AllowAlias: "+valueToGoStringDescriptor(this.AllowAlias, "bool")+",\n")
+ }
+ if this.Deprecated != nil {
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
+ }
+ if this.UninterpretedOption != nil {
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
+ }
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *EnumValueOptions) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 6)
+ s = append(s, "&descriptor.EnumValueOptions{")
+ if this.Deprecated != nil {
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
+ }
+ if this.UninterpretedOption != nil {
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
+ }
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *ServiceOptions) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 6)
+ s = append(s, "&descriptor.ServiceOptions{")
+ if this.Deprecated != nil {
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
+ }
+ if this.UninterpretedOption != nil {
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
+ }
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *MethodOptions) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 7)
+ s = append(s, "&descriptor.MethodOptions{")
+ if this.Deprecated != nil {
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
+ }
+ if this.IdempotencyLevel != nil {
+ s = append(s, "IdempotencyLevel: "+valueToGoStringDescriptor(this.IdempotencyLevel, "MethodOptions_IdempotencyLevel")+",\n")
+ }
+ if this.UninterpretedOption != nil {
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
+ }
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *UninterpretedOption) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 11)
+ s = append(s, "&descriptor.UninterpretedOption{")
+ if this.Name != nil {
+ s = append(s, "Name: "+fmt.Sprintf("%#v", this.Name)+",\n")
+ }
+ if this.IdentifierValue != nil {
+ s = append(s, "IdentifierValue: "+valueToGoStringDescriptor(this.IdentifierValue, "string")+",\n")
+ }
+ if this.PositiveIntValue != nil {
+ s = append(s, "PositiveIntValue: "+valueToGoStringDescriptor(this.PositiveIntValue, "uint64")+",\n")
+ }
+ if this.NegativeIntValue != nil {
+ s = append(s, "NegativeIntValue: "+valueToGoStringDescriptor(this.NegativeIntValue, "int64")+",\n")
+ }
+ if this.DoubleValue != nil {
+ s = append(s, "DoubleValue: "+valueToGoStringDescriptor(this.DoubleValue, "float64")+",\n")
+ }
+ if this.StringValue != nil {
+ s = append(s, "StringValue: "+valueToGoStringDescriptor(this.StringValue, "byte")+",\n")
+ }
+ if this.AggregateValue != nil {
+ s = append(s, "AggregateValue: "+valueToGoStringDescriptor(this.AggregateValue, "string")+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *UninterpretedOption_NamePart) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 6)
+ s = append(s, "&descriptor.UninterpretedOption_NamePart{")
+ if this.NamePart != nil {
+ s = append(s, "NamePart: "+valueToGoStringDescriptor(this.NamePart, "string")+",\n")
+ }
+ if this.IsExtension != nil {
+ s = append(s, "IsExtension: "+valueToGoStringDescriptor(this.IsExtension, "bool")+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *SourceCodeInfo) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&descriptor.SourceCodeInfo{")
+ if this.Location != nil {
+ s = append(s, "Location: "+fmt.Sprintf("%#v", this.Location)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *SourceCodeInfo_Location) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 9)
+ s = append(s, "&descriptor.SourceCodeInfo_Location{")
+ if this.Path != nil {
+ s = append(s, "Path: "+fmt.Sprintf("%#v", this.Path)+",\n")
+ }
+ if this.Span != nil {
+ s = append(s, "Span: "+fmt.Sprintf("%#v", this.Span)+",\n")
+ }
+ if this.LeadingComments != nil {
+ s = append(s, "LeadingComments: "+valueToGoStringDescriptor(this.LeadingComments, "string")+",\n")
+ }
+ if this.TrailingComments != nil {
+ s = append(s, "TrailingComments: "+valueToGoStringDescriptor(this.TrailingComments, "string")+",\n")
+ }
+ if this.LeadingDetachedComments != nil {
+ s = append(s, "LeadingDetachedComments: "+fmt.Sprintf("%#v", this.LeadingDetachedComments)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *GeneratedCodeInfo) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&descriptor.GeneratedCodeInfo{")
+ if this.Annotation != nil {
+ s = append(s, "Annotation: "+fmt.Sprintf("%#v", this.Annotation)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *GeneratedCodeInfo_Annotation) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 8)
+ s = append(s, "&descriptor.GeneratedCodeInfo_Annotation{")
+ if this.Path != nil {
+ s = append(s, "Path: "+fmt.Sprintf("%#v", this.Path)+",\n")
+ }
+ if this.SourceFile != nil {
+ s = append(s, "SourceFile: "+valueToGoStringDescriptor(this.SourceFile, "string")+",\n")
+ }
+ if this.Begin != nil {
+ s = append(s, "Begin: "+valueToGoStringDescriptor(this.Begin, "int32")+",\n")
+ }
+ if this.End != nil {
+ s = append(s, "End: "+valueToGoStringDescriptor(this.End, "int32")+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func valueToGoStringDescriptor(v interface{}, typ string) string {
+ rv := reflect.ValueOf(v)
+ if rv.IsNil() {
+ return "nil"
+ }
+ pv := reflect.Indirect(rv).Interface()
+ return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
+}
+func extensionToGoStringDescriptor(m proto.Message) string {
+ e := proto.GetUnsafeExtensionsMap(m)
+ if e == nil {
+ return "nil"
+ }
+ s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{"
+ keys := make([]int, 0, len(e))
+ for k := range e {
+ keys = append(keys, int(k))
+ }
+ sort.Ints(keys)
+ ss := []string{}
+ for _, k := range keys {
+ ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString())
+ }
+ s += strings.Join(ss, ",") + "})"
+ return s
+}
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package descriptor
+
+import (
+ "strings"
+)
+
+func (msg *DescriptorProto) GetMapFields() (*FieldDescriptorProto, *FieldDescriptorProto) {
+ if !msg.GetOptions().GetMapEntry() {
+ return nil, nil
+ }
+ return msg.GetField()[0], msg.GetField()[1]
+}
+
+func dotToUnderscore(r rune) rune {
+ if r == '.' {
+ return '_'
+ }
+ return r
+}
+
+func (field *FieldDescriptorProto) WireType() (wire int) {
+ switch *field.Type {
+ case FieldDescriptorProto_TYPE_DOUBLE:
+ return 1
+ case FieldDescriptorProto_TYPE_FLOAT:
+ return 5
+ case FieldDescriptorProto_TYPE_INT64:
+ return 0
+ case FieldDescriptorProto_TYPE_UINT64:
+ return 0
+ case FieldDescriptorProto_TYPE_INT32:
+ return 0
+ case FieldDescriptorProto_TYPE_UINT32:
+ return 0
+ case FieldDescriptorProto_TYPE_FIXED64:
+ return 1
+ case FieldDescriptorProto_TYPE_FIXED32:
+ return 5
+ case FieldDescriptorProto_TYPE_BOOL:
+ return 0
+ case FieldDescriptorProto_TYPE_STRING:
+ return 2
+ case FieldDescriptorProto_TYPE_GROUP:
+ return 2
+ case FieldDescriptorProto_TYPE_MESSAGE:
+ return 2
+ case FieldDescriptorProto_TYPE_BYTES:
+ return 2
+ case FieldDescriptorProto_TYPE_ENUM:
+ return 0
+ case FieldDescriptorProto_TYPE_SFIXED32:
+ return 5
+ case FieldDescriptorProto_TYPE_SFIXED64:
+ return 1
+ case FieldDescriptorProto_TYPE_SINT32:
+ return 0
+ case FieldDescriptorProto_TYPE_SINT64:
+ return 0
+ }
+ panic("unreachable")
+}
+
+func (field *FieldDescriptorProto) GetKeyUint64() (x uint64) {
+ packed := field.IsPacked()
+ wireType := field.WireType()
+ fieldNumber := field.GetNumber()
+ if packed {
+ wireType = 2
+ }
+ x = uint64(uint32(fieldNumber)<<3 | uint32(wireType))
+ return x
+}
+
+func (field *FieldDescriptorProto) GetKey3Uint64() (x uint64) {
+ packed := field.IsPacked3()
+ wireType := field.WireType()
+ fieldNumber := field.GetNumber()
+ if packed {
+ wireType = 2
+ }
+ x = uint64(uint32(fieldNumber)<<3 | uint32(wireType))
+ return x
+}
+
+func (field *FieldDescriptorProto) GetKey() []byte {
+ x := field.GetKeyUint64()
+ i := 0
+ keybuf := make([]byte, 0)
+ for i = 0; x > 127; i++ {
+ keybuf = append(keybuf, 0x80|uint8(x&0x7F))
+ x >>= 7
+ }
+ keybuf = append(keybuf, uint8(x))
+ return keybuf
+}
+
+func (field *FieldDescriptorProto) GetKey3() []byte {
+ x := field.GetKey3Uint64()
+ i := 0
+ keybuf := make([]byte, 0)
+ for i = 0; x > 127; i++ {
+ keybuf = append(keybuf, 0x80|uint8(x&0x7F))
+ x >>= 7
+ }
+ keybuf = append(keybuf, uint8(x))
+ return keybuf
+}
+
+func (desc *FileDescriptorSet) GetField(packageName, messageName, fieldName string) *FieldDescriptorProto {
+ msg := desc.GetMessage(packageName, messageName)
+ if msg == nil {
+ return nil
+ }
+ for _, field := range msg.GetField() {
+ if field.GetName() == fieldName {
+ return field
+ }
+ }
+ return nil
+}
+
+func (file *FileDescriptorProto) GetMessage(typeName string) *DescriptorProto {
+ for _, msg := range file.GetMessageType() {
+ if msg.GetName() == typeName {
+ return msg
+ }
+ nes := file.GetNestedMessage(msg, strings.TrimPrefix(typeName, msg.GetName()+"."))
+ if nes != nil {
+ return nes
+ }
+ }
+ return nil
+}
+
+func (file *FileDescriptorProto) GetNestedMessage(msg *DescriptorProto, typeName string) *DescriptorProto {
+ for _, nes := range msg.GetNestedType() {
+ if nes.GetName() == typeName {
+ return nes
+ }
+ res := file.GetNestedMessage(nes, strings.TrimPrefix(typeName, nes.GetName()+"."))
+ if res != nil {
+ return res
+ }
+ }
+ return nil
+}
+
+func (desc *FileDescriptorSet) GetMessage(packageName string, typeName string) *DescriptorProto {
+ for _, file := range desc.GetFile() {
+ if strings.Map(dotToUnderscore, file.GetPackage()) != strings.Map(dotToUnderscore, packageName) {
+ continue
+ }
+ for _, msg := range file.GetMessageType() {
+ if msg.GetName() == typeName {
+ return msg
+ }
+ }
+ for _, msg := range file.GetMessageType() {
+ for _, nes := range msg.GetNestedType() {
+ if nes.GetName() == typeName {
+ return nes
+ }
+ if msg.GetName()+"."+nes.GetName() == typeName {
+ return nes
+ }
+ }
+ }
+ }
+ return nil
+}
+
+func (desc *FileDescriptorSet) IsProto3(packageName string, typeName string) bool {
+ for _, file := range desc.GetFile() {
+ if strings.Map(dotToUnderscore, file.GetPackage()) != strings.Map(dotToUnderscore, packageName) {
+ continue
+ }
+ for _, msg := range file.GetMessageType() {
+ if msg.GetName() == typeName {
+ return file.GetSyntax() == "proto3"
+ }
+ }
+ for _, msg := range file.GetMessageType() {
+ for _, nes := range msg.GetNestedType() {
+ if nes.GetName() == typeName {
+ return file.GetSyntax() == "proto3"
+ }
+ if msg.GetName()+"."+nes.GetName() == typeName {
+ return file.GetSyntax() == "proto3"
+ }
+ }
+ }
+ }
+ return false
+}
+
+func (msg *DescriptorProto) IsExtendable() bool {
+ return len(msg.GetExtensionRange()) > 0
+}
+
+func (desc *FileDescriptorSet) FindExtension(packageName string, typeName string, fieldName string) (extPackageName string, field *FieldDescriptorProto) {
+ parent := desc.GetMessage(packageName, typeName)
+ if parent == nil {
+ return "", nil
+ }
+ if !parent.IsExtendable() {
+ return "", nil
+ }
+ extendee := "." + packageName + "." + typeName
+ for _, file := range desc.GetFile() {
+ for _, ext := range file.GetExtension() {
+ if strings.Map(dotToUnderscore, file.GetPackage()) == strings.Map(dotToUnderscore, packageName) {
+ if !(ext.GetExtendee() == typeName || ext.GetExtendee() == extendee) {
+ continue
+ }
+ } else {
+ if ext.GetExtendee() != extendee {
+ continue
+ }
+ }
+ if ext.GetName() == fieldName {
+ return file.GetPackage(), ext
+ }
+ }
+ }
+ return "", nil
+}
+
+func (desc *FileDescriptorSet) FindExtensionByFieldNumber(packageName string, typeName string, fieldNum int32) (extPackageName string, field *FieldDescriptorProto) {
+ parent := desc.GetMessage(packageName, typeName)
+ if parent == nil {
+ return "", nil
+ }
+ if !parent.IsExtendable() {
+ return "", nil
+ }
+ extendee := "." + packageName + "." + typeName
+ for _, file := range desc.GetFile() {
+ for _, ext := range file.GetExtension() {
+ if strings.Map(dotToUnderscore, file.GetPackage()) == strings.Map(dotToUnderscore, packageName) {
+ if !(ext.GetExtendee() == typeName || ext.GetExtendee() == extendee) {
+ continue
+ }
+ } else {
+ if ext.GetExtendee() != extendee {
+ continue
+ }
+ }
+ if ext.GetNumber() == fieldNum {
+ return file.GetPackage(), ext
+ }
+ }
+ }
+ return "", nil
+}
+
+func (desc *FileDescriptorSet) FindMessage(packageName string, typeName string, fieldName string) (msgPackageName string, msgName string) {
+ parent := desc.GetMessage(packageName, typeName)
+ if parent == nil {
+ return "", ""
+ }
+ field := parent.GetFieldDescriptor(fieldName)
+ if field == nil {
+ var extPackageName string
+ extPackageName, field = desc.FindExtension(packageName, typeName, fieldName)
+ if field == nil {
+ return "", ""
+ }
+ packageName = extPackageName
+ }
+ typeNames := strings.Split(field.GetTypeName(), ".")
+ if len(typeNames) == 1 {
+ msg := desc.GetMessage(packageName, typeName)
+ if msg == nil {
+ return "", ""
+ }
+ return packageName, msg.GetName()
+ }
+ if len(typeNames) > 2 {
+ for i := 1; i < len(typeNames)-1; i++ {
+ packageName = strings.Join(typeNames[1:len(typeNames)-i], ".")
+ typeName = strings.Join(typeNames[len(typeNames)-i:], ".")
+ msg := desc.GetMessage(packageName, typeName)
+ if msg != nil {
+ typeNames := strings.Split(msg.GetName(), ".")
+ if len(typeNames) == 1 {
+ return packageName, msg.GetName()
+ }
+ return strings.Join(typeNames[1:len(typeNames)-1], "."), typeNames[len(typeNames)-1]
+ }
+ }
+ }
+ return "", ""
+}
+
+func (msg *DescriptorProto) GetFieldDescriptor(fieldName string) *FieldDescriptorProto {
+ for _, field := range msg.GetField() {
+ if field.GetName() == fieldName {
+ return field
+ }
+ }
+ return nil
+}
+
+func (desc *FileDescriptorSet) GetEnum(packageName string, typeName string) *EnumDescriptorProto {
+ for _, file := range desc.GetFile() {
+ if strings.Map(dotToUnderscore, file.GetPackage()) != strings.Map(dotToUnderscore, packageName) {
+ continue
+ }
+ for _, enum := range file.GetEnumType() {
+ if enum.GetName() == typeName {
+ return enum
+ }
+ }
+ }
+ return nil
+}
+
+func (f *FieldDescriptorProto) IsEnum() bool {
+ return *f.Type == FieldDescriptorProto_TYPE_ENUM
+}
+
+func (f *FieldDescriptorProto) IsMessage() bool {
+ return *f.Type == FieldDescriptorProto_TYPE_MESSAGE
+}
+
+func (f *FieldDescriptorProto) IsBytes() bool {
+ return *f.Type == FieldDescriptorProto_TYPE_BYTES
+}
+
+func (f *FieldDescriptorProto) IsRepeated() bool {
+ return f.Label != nil && *f.Label == FieldDescriptorProto_LABEL_REPEATED
+}
+
+func (f *FieldDescriptorProto) IsString() bool {
+ return *f.Type == FieldDescriptorProto_TYPE_STRING
+}
+
+func (f *FieldDescriptorProto) IsBool() bool {
+ return *f.Type == FieldDescriptorProto_TYPE_BOOL
+}
+
+func (f *FieldDescriptorProto) IsRequired() bool {
+ return f.Label != nil && *f.Label == FieldDescriptorProto_LABEL_REQUIRED
+}
+
+func (f *FieldDescriptorProto) IsPacked() bool {
+ return f.Options != nil && f.GetOptions().GetPacked()
+}
+
+func (f *FieldDescriptorProto) IsPacked3() bool {
+ if f.IsRepeated() && f.IsScalar() {
+ if f.Options == nil || f.GetOptions().Packed == nil {
+ return true
+ }
+ return f.Options != nil && f.GetOptions().GetPacked()
+ }
+ return false
+}
+
+func (m *DescriptorProto) HasExtension() bool {
+ return len(m.ExtensionRange) > 0
+}
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package sortkeys
+
+import (
+ "sort"
+)
+
+func Strings(l []string) {
+ sort.Strings(l)
+}
+
+func Float64s(l []float64) {
+ sort.Float64s(l)
+}
+
+func Float32s(l []float32) {
+ sort.Sort(Float32Slice(l))
+}
+
+func Int64s(l []int64) {
+ sort.Sort(Int64Slice(l))
+}
+
+func Int32s(l []int32) {
+ sort.Sort(Int32Slice(l))
+}
+
+func Uint64s(l []uint64) {
+ sort.Sort(Uint64Slice(l))
+}
+
+func Uint32s(l []uint32) {
+ sort.Sort(Uint32Slice(l))
+}
+
+func Bools(l []bool) {
+ sort.Sort(BoolSlice(l))
+}
+
+type BoolSlice []bool
+
+func (p BoolSlice) Len() int { return len(p) }
+func (p BoolSlice) Less(i, j int) bool { return p[j] }
+func (p BoolSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+type Int64Slice []int64
+
+func (p Int64Slice) Len() int { return len(p) }
+func (p Int64Slice) Less(i, j int) bool { return p[i] < p[j] }
+func (p Int64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+type Int32Slice []int32
+
+func (p Int32Slice) Len() int { return len(p) }
+func (p Int32Slice) Less(i, j int) bool { return p[i] < p[j] }
+func (p Int32Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+type Uint64Slice []uint64
+
+func (p Uint64Slice) Len() int { return len(p) }
+func (p Uint64Slice) Less(i, j int) bool { return p[i] < p[j] }
+func (p Uint64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+type Uint32Slice []uint32
+
+func (p Uint32Slice) Len() int { return len(p) }
+func (p Uint32Slice) Less(i, j int) bool { return p[i] < p[j] }
+func (p Uint32Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+type Float32Slice []float32
+
+func (p Float32Slice) Len() int { return len(p) }
+func (p Float32Slice) Less(i, j int) bool { return p[i] < p[j] }
+func (p Float32Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
--- /dev/null
+# Protocol Buffers for Go with Gadgets
+#
+# Copyright (c) 2016, The GoGo Authors. All rights reserved.
+# http://github.com/gogo/protobuf
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+regenerate:
+ go install github.com/gogo/protobuf/protoc-gen-gogotypes
+ go install github.com/gogo/protobuf/protoc-min-version
+
+ protoc-min-version --version="3.0.0" --gogotypes_out=. -I=../protobuf/google/protobuf ../protobuf/google/protobuf/any.proto
+ protoc-min-version --version="3.0.0" --gogotypes_out=. -I=../protobuf/google/protobuf ../protobuf/google/protobuf/empty.proto
+ protoc-min-version --version="3.0.0" --gogotypes_out=. -I=../protobuf/google/protobuf ../protobuf/google/protobuf/timestamp.proto
+ protoc-min-version --version="3.0.0" --gogotypes_out=. -I=../protobuf/google/protobuf ../protobuf/google/protobuf/duration.proto
+ protoc-min-version --version="3.0.0" --gogotypes_out=. -I=../protobuf/google/protobuf ../protobuf/google/protobuf/struct.proto
+ protoc-min-version --version="3.0.0" --gogotypes_out=. -I=../protobuf/google/protobuf ../protobuf/google/protobuf/wrappers.proto
+ protoc-min-version --version="3.0.0" --gogotypes_out=. -I=../protobuf/google/protobuf ../protobuf/google/protobuf/field_mask.proto
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package types
+
+// This file implements functions to marshal proto.Message to/from
+// google.protobuf.Any message.
+
+import (
+ "fmt"
+ "reflect"
+ "strings"
+
+ "github.com/gogo/protobuf/proto"
+)
+
+const googleApis = "type.googleapis.com/"
+
+// AnyMessageName returns the name of the message contained in a google.protobuf.Any message.
+//
+// Note that regular type assertions should be done using the Is
+// function. AnyMessageName is provided for less common use cases like filtering a
+// sequence of Any messages based on a set of allowed message type names.
+func AnyMessageName(any *Any) (string, error) {
+ slash := strings.LastIndex(any.TypeUrl, "/")
+ if slash < 0 {
+ return "", fmt.Errorf("message type url %q is invalid", any.TypeUrl)
+ }
+ return any.TypeUrl[slash+1:], nil
+}
+
+// MarshalAny takes the protocol buffer and encodes it into google.protobuf.Any.
+func MarshalAny(pb proto.Message) (*Any, error) {
+ value, err := proto.Marshal(pb)
+ if err != nil {
+ return nil, err
+ }
+ return &Any{TypeUrl: googleApis + proto.MessageName(pb), Value: value}, nil
+}
+
+// DynamicAny is a value that can be passed to UnmarshalAny to automatically
+// allocate a proto.Message for the type specified in a google.protobuf.Any
+// message. The allocated message is stored in the embedded proto.Message.
+//
+// Example:
+//
+// var x ptypes.DynamicAny
+// if err := ptypes.UnmarshalAny(a, &x); err != nil { ... }
+// fmt.Printf("unmarshaled message: %v", x.Message)
+type DynamicAny struct {
+ proto.Message
+}
+
+// Empty returns a new proto.Message of the type specified in a
+// google.protobuf.Any message. It returns an error if corresponding message
+// type isn't linked in.
+func EmptyAny(any *Any) (proto.Message, error) {
+ aname, err := AnyMessageName(any)
+ if err != nil {
+ return nil, err
+ }
+
+ t := proto.MessageType(aname)
+ if t == nil {
+ return nil, fmt.Errorf("any: message type %q isn't linked in", aname)
+ }
+ return reflect.New(t.Elem()).Interface().(proto.Message), nil
+}
+
+// UnmarshalAny parses the protocol buffer representation in a google.protobuf.Any
+// message and places the decoded result in pb. It returns an error if type of
+// contents of Any message does not match type of pb message.
+//
+// pb can be a proto.Message, or a *DynamicAny.
+func UnmarshalAny(any *Any, pb proto.Message) error {
+ if d, ok := pb.(*DynamicAny); ok {
+ if d.Message == nil {
+ var err error
+ d.Message, err = EmptyAny(any)
+ if err != nil {
+ return err
+ }
+ }
+ return UnmarshalAny(any, d.Message)
+ }
+
+ aname, err := AnyMessageName(any)
+ if err != nil {
+ return err
+ }
+
+ mname := proto.MessageName(pb)
+ if aname != mname {
+ return fmt.Errorf("mismatched message type: got %q want %q", aname, mname)
+ }
+ return proto.Unmarshal(any.Value, pb)
+}
+
+// Is returns true if any value contains a given message type.
+func Is(any *Any, pb proto.Message) bool {
+ aname, err := AnyMessageName(any)
+ if err != nil {
+ return false
+ }
+
+ return aname == proto.MessageName(pb)
+}
--- /dev/null
+// Code generated by protoc-gen-gogo.
+// source: any.proto
+// DO NOT EDIT!
+
+/*
+ Package types is a generated protocol buffer package.
+
+ It is generated from these files:
+ any.proto
+
+ It has these top-level messages:
+ Any
+*/
+package types
+
+import proto "github.com/gogo/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+import bytes "bytes"
+
+import strings "strings"
+import reflect "reflect"
+
+import io "io"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
+
+// `Any` contains an arbitrary serialized protocol buffer message along with a
+// URL that describes the type of the serialized message.
+//
+// Protobuf library provides support to pack/unpack Any values in the form
+// of utility functions or additional generated methods of the Any type.
+//
+// Example 1: Pack and unpack a message in C++.
+//
+// Foo foo = ...;
+// Any any;
+// any.PackFrom(foo);
+// ...
+// if (any.UnpackTo(&foo)) {
+// ...
+// }
+//
+// Example 2: Pack and unpack a message in Java.
+//
+// Foo foo = ...;
+// Any any = Any.pack(foo);
+// ...
+// if (any.is(Foo.class)) {
+// foo = any.unpack(Foo.class);
+// }
+//
+// Example 3: Pack and unpack a message in Python.
+//
+// foo = Foo(...)
+// any = Any()
+// any.Pack(foo)
+// ...
+// if any.Is(Foo.DESCRIPTOR):
+// any.Unpack(foo)
+// ...
+//
+// The pack methods provided by protobuf library will by default use
+// 'type.googleapis.com/full.type.name' as the type URL and the unpack
+// methods only use the fully qualified type name after the last '/'
+// in the type URL, for example "foo.bar.com/x/y.z" will yield type
+// name "y.z".
+//
+//
+// JSON
+// ====
+// The JSON representation of an `Any` value uses the regular
+// representation of the deserialized, embedded message, with an
+// additional field `@type` which contains the type URL. Example:
+//
+// package google.profile;
+// message Person {
+// string first_name = 1;
+// string last_name = 2;
+// }
+//
+// {
+// "@type": "type.googleapis.com/google.profile.Person",
+// "firstName": <string>,
+// "lastName": <string>
+// }
+//
+// If the embedded message type is well-known and has a custom JSON
+// representation, that representation will be embedded adding a field
+// `value` which holds the custom JSON in addition to the `@type`
+// field. Example (for message [google.protobuf.Duration][]):
+//
+// {
+// "@type": "type.googleapis.com/google.protobuf.Duration",
+// "value": "1.212s"
+// }
+//
+type Any struct {
+ // A URL/resource name whose content describes the type of the
+ // serialized protocol buffer message.
+ //
+ // For URLs which use the scheme `http`, `https`, or no scheme, the
+ // following restrictions and interpretations apply:
+ //
+ // * If no scheme is provided, `https` is assumed.
+ // * The last segment of the URL's path must represent the fully
+ // qualified name of the type (as in `path/google.protobuf.Duration`).
+ // The name should be in a canonical form (e.g., leading "." is
+ // not accepted).
+ // * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+ // value in binary format, or produce an error.
+ // * Applications are allowed to cache lookup results based on the
+ // URL, or have them precompiled into a binary to avoid any
+ // lookup. Therefore, binary compatibility needs to be preserved
+ // on changes to types. (Use versioned type names to manage
+ // breaking changes.)
+ //
+ // Schemes other than `http`, `https` (or the empty scheme) might be
+ // used with implementation specific semantics.
+ //
+ TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"`
+ // Must be a valid serialized protocol buffer of the above specified type.
+ Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (m *Any) Reset() { *m = Any{} }
+func (*Any) ProtoMessage() {}
+func (*Any) Descriptor() ([]byte, []int) { return fileDescriptorAny, []int{0} }
+func (*Any) XXX_WellKnownType() string { return "Any" }
+
+func (m *Any) GetTypeUrl() string {
+ if m != nil {
+ return m.TypeUrl
+ }
+ return ""
+}
+
+func (m *Any) GetValue() []byte {
+ if m != nil {
+ return m.Value
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*Any)(nil), "google.protobuf.Any")
+}
+func (this *Any) Compare(that interface{}) int {
+ if that == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ }
+
+ that1, ok := that.(*Any)
+ if !ok {
+ that2, ok := that.(Any)
+ if ok {
+ that1 = &that2
+ } else {
+ return 1
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ } else if this == nil {
+ return -1
+ }
+ if this.TypeUrl != that1.TypeUrl {
+ if this.TypeUrl < that1.TypeUrl {
+ return -1
+ }
+ return 1
+ }
+ if c := bytes.Compare(this.Value, that1.Value); c != 0 {
+ return c
+ }
+ return 0
+}
+func (this *Any) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*Any)
+ if !ok {
+ that2, ok := that.(Any)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if this.TypeUrl != that1.TypeUrl {
+ return false
+ }
+ if !bytes.Equal(this.Value, that1.Value) {
+ return false
+ }
+ return true
+}
+func (this *Any) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 6)
+ s = append(s, "&types.Any{")
+ s = append(s, "TypeUrl: "+fmt.Sprintf("%#v", this.TypeUrl)+",\n")
+ s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n")
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func valueToGoStringAny(v interface{}, typ string) string {
+ rv := reflect.ValueOf(v)
+ if rv.IsNil() {
+ return "nil"
+ }
+ pv := reflect.Indirect(rv).Interface()
+ return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
+}
+func (m *Any) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Any) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.TypeUrl) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintAny(dAtA, i, uint64(len(m.TypeUrl)))
+ i += copy(dAtA[i:], m.TypeUrl)
+ }
+ if len(m.Value) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintAny(dAtA, i, uint64(len(m.Value)))
+ i += copy(dAtA[i:], m.Value)
+ }
+ return i, nil
+}
+
+func encodeFixed64Any(dAtA []byte, offset int, v uint64) int {
+ dAtA[offset] = uint8(v)
+ dAtA[offset+1] = uint8(v >> 8)
+ dAtA[offset+2] = uint8(v >> 16)
+ dAtA[offset+3] = uint8(v >> 24)
+ dAtA[offset+4] = uint8(v >> 32)
+ dAtA[offset+5] = uint8(v >> 40)
+ dAtA[offset+6] = uint8(v >> 48)
+ dAtA[offset+7] = uint8(v >> 56)
+ return offset + 8
+}
+func encodeFixed32Any(dAtA []byte, offset int, v uint32) int {
+ dAtA[offset] = uint8(v)
+ dAtA[offset+1] = uint8(v >> 8)
+ dAtA[offset+2] = uint8(v >> 16)
+ dAtA[offset+3] = uint8(v >> 24)
+ return offset + 4
+}
+func encodeVarintAny(dAtA []byte, offset int, v uint64) int {
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return offset + 1
+}
+func NewPopulatedAny(r randyAny, easy bool) *Any {
+ this := &Any{}
+ this.TypeUrl = string(randStringAny(r))
+ v1 := r.Intn(100)
+ this.Value = make([]byte, v1)
+ for i := 0; i < v1; i++ {
+ this.Value[i] = byte(r.Intn(256))
+ }
+ if !easy && r.Intn(10) != 0 {
+ }
+ return this
+}
+
+type randyAny interface {
+ Float32() float32
+ Float64() float64
+ Int63() int64
+ Int31() int32
+ Uint32() uint32
+ Intn(n int) int
+}
+
+func randUTF8RuneAny(r randyAny) rune {
+ ru := r.Intn(62)
+ if ru < 10 {
+ return rune(ru + 48)
+ } else if ru < 36 {
+ return rune(ru + 55)
+ }
+ return rune(ru + 61)
+}
+func randStringAny(r randyAny) string {
+ v2 := r.Intn(100)
+ tmps := make([]rune, v2)
+ for i := 0; i < v2; i++ {
+ tmps[i] = randUTF8RuneAny(r)
+ }
+ return string(tmps)
+}
+func randUnrecognizedAny(r randyAny, maxFieldNumber int) (dAtA []byte) {
+ l := r.Intn(5)
+ for i := 0; i < l; i++ {
+ wire := r.Intn(4)
+ if wire == 3 {
+ wire = 5
+ }
+ fieldNumber := maxFieldNumber + r.Intn(100)
+ dAtA = randFieldAny(dAtA, r, fieldNumber, wire)
+ }
+ return dAtA
+}
+func randFieldAny(dAtA []byte, r randyAny, fieldNumber int, wire int) []byte {
+ key := uint32(fieldNumber)<<3 | uint32(wire)
+ switch wire {
+ case 0:
+ dAtA = encodeVarintPopulateAny(dAtA, uint64(key))
+ v3 := r.Int63()
+ if r.Intn(2) == 0 {
+ v3 *= -1
+ }
+ dAtA = encodeVarintPopulateAny(dAtA, uint64(v3))
+ case 1:
+ dAtA = encodeVarintPopulateAny(dAtA, uint64(key))
+ dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))
+ case 2:
+ dAtA = encodeVarintPopulateAny(dAtA, uint64(key))
+ ll := r.Intn(100)
+ dAtA = encodeVarintPopulateAny(dAtA, uint64(ll))
+ for j := 0; j < ll; j++ {
+ dAtA = append(dAtA, byte(r.Intn(256)))
+ }
+ default:
+ dAtA = encodeVarintPopulateAny(dAtA, uint64(key))
+ dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))
+ }
+ return dAtA
+}
+func encodeVarintPopulateAny(dAtA []byte, v uint64) []byte {
+ for v >= 1<<7 {
+ dAtA = append(dAtA, uint8(uint64(v)&0x7f|0x80))
+ v >>= 7
+ }
+ dAtA = append(dAtA, uint8(v))
+ return dAtA
+}
+func (m *Any) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.TypeUrl)
+ if l > 0 {
+ n += 1 + l + sovAny(uint64(l))
+ }
+ l = len(m.Value)
+ if l > 0 {
+ n += 1 + l + sovAny(uint64(l))
+ }
+ return n
+}
+
+func sovAny(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+func sozAny(x uint64) (n int) {
+ return sovAny(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (this *Any) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&Any{`,
+ `TypeUrl:` + fmt.Sprintf("%v", this.TypeUrl) + `,`,
+ `Value:` + fmt.Sprintf("%v", this.Value) + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func valueToStringAny(v interface{}) string {
+ rv := reflect.ValueOf(v)
+ if rv.IsNil() {
+ return "nil"
+ }
+ pv := reflect.Indirect(rv).Interface()
+ return fmt.Sprintf("*%v", pv)
+}
+func (m *Any) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowAny
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Any: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Any: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field TypeUrl", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowAny
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthAny
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.TypeUrl = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowAny
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthAny
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Value = append(m.Value[:0], dAtA[iNdEx:postIndex]...)
+ if m.Value == nil {
+ m.Value = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipAny(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthAny
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipAny(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowAny
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowAny
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ return iNdEx, nil
+ case 1:
+ iNdEx += 8
+ return iNdEx, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowAny
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ iNdEx += length
+ if length < 0 {
+ return 0, ErrInvalidLengthAny
+ }
+ return iNdEx, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = iNdEx
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowAny
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := skipAny(dAtA[start:])
+ if err != nil {
+ return 0, err
+ }
+ iNdEx = start + next
+ }
+ return iNdEx, nil
+ case 4:
+ return iNdEx, nil
+ case 5:
+ iNdEx += 4
+ return iNdEx, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
+
+var (
+ ErrInvalidLengthAny = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowAny = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("any.proto", fileDescriptorAny) }
+
+var fileDescriptorAny = []byte{
+ // 204 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4c, 0xcc, 0xab, 0xd4,
+ 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x4f, 0xcf, 0xcf, 0x4f, 0xcf, 0x49, 0x85, 0xf0, 0x92,
+ 0x4a, 0xd3, 0x94, 0xcc, 0xb8, 0x98, 0x1d, 0xf3, 0x2a, 0x85, 0x24, 0xb9, 0x38, 0x4a, 0x2a, 0x0b,
+ 0x52, 0xe3, 0x4b, 0x8b, 0x72, 0x24, 0x18, 0x15, 0x18, 0x35, 0x38, 0x83, 0xd8, 0x41, 0xfc, 0xd0,
+ 0xa2, 0x1c, 0x21, 0x11, 0x2e, 0xd6, 0xb2, 0xc4, 0x9c, 0xd2, 0x54, 0x09, 0x26, 0x05, 0x46, 0x0d,
+ 0x9e, 0x20, 0x08, 0xc7, 0xa9, 0xfe, 0xc2, 0x43, 0x39, 0x86, 0x1b, 0x0f, 0xe5, 0x18, 0x3e, 0x3c,
+ 0x94, 0x63, 0xfc, 0xf1, 0x50, 0x8e, 0xb1, 0xe1, 0x91, 0x1c, 0xe3, 0x8a, 0x47, 0x72, 0x8c, 0x27,
+ 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x8b, 0x47, 0x72, 0x0c,
+ 0x1f, 0x40, 0xe2, 0x8f, 0xe5, 0x18, 0xb9, 0x84, 0x93, 0xf3, 0x73, 0xf5, 0xd0, 0xac, 0x77, 0xe2,
+ 0x70, 0xcc, 0xab, 0x0c, 0x00, 0x71, 0x02, 0x18, 0xa3, 0x58, 0x41, 0x36, 0x16, 0x2f, 0x62, 0x62,
+ 0x76, 0x0f, 0x70, 0x5a, 0xc5, 0x24, 0xe7, 0x0e, 0x51, 0x1a, 0x00, 0x55, 0xaa, 0x17, 0x9e, 0x9a,
+ 0x93, 0xe3, 0x9d, 0x97, 0x5f, 0x9e, 0x17, 0x02, 0x52, 0x96, 0xc4, 0x06, 0x36, 0xc3, 0x18, 0x10,
+ 0x00, 0x00, 0xff, 0xff, 0xb7, 0x39, 0x2f, 0x89, 0xdd, 0x00, 0x00, 0x00,
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/*
+Package types contains code for interacting with well-known types.
+*/
+package types
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package types
+
+// This file implements conversions between google.protobuf.Duration
+// and time.Duration.
+
+import (
+ "errors"
+ "fmt"
+ "time"
+)
+
+const (
+ // Range of a Duration in seconds, as specified in
+ // google/protobuf/duration.proto. This is about 10,000 years in seconds.
+ maxSeconds = int64(10000 * 365.25 * 24 * 60 * 60)
+ minSeconds = -maxSeconds
+)
+
+// validateDuration determines whether the Duration is valid according to the
+// definition in google/protobuf/duration.proto. A valid Duration
+// may still be too large to fit into a time.Duration (the range of Duration
+// is about 10,000 years, and the range of time.Duration is about 290).
+func validateDuration(d *Duration) error {
+ if d == nil {
+ return errors.New("duration: nil Duration")
+ }
+ if d.Seconds < minSeconds || d.Seconds > maxSeconds {
+ return fmt.Errorf("duration: %#v: seconds out of range", d)
+ }
+ if d.Nanos <= -1e9 || d.Nanos >= 1e9 {
+ return fmt.Errorf("duration: %#v: nanos out of range", d)
+ }
+ // Seconds and Nanos must have the same sign, unless d.Nanos is zero.
+ if (d.Seconds < 0 && d.Nanos > 0) || (d.Seconds > 0 && d.Nanos < 0) {
+ return fmt.Errorf("duration: %#v: seconds and nanos have different signs", d)
+ }
+ return nil
+}
+
+// DurationFromProto converts a Duration to a time.Duration. DurationFromProto
+// returns an error if the Duration is invalid or is too large to be
+// represented in a time.Duration.
+func DurationFromProto(p *Duration) (time.Duration, error) {
+ if err := validateDuration(p); err != nil {
+ return 0, err
+ }
+ d := time.Duration(p.Seconds) * time.Second
+ if int64(d/time.Second) != p.Seconds {
+ return 0, fmt.Errorf("duration: %#v is out of range for time.Duration", p)
+ }
+ if p.Nanos != 0 {
+ d += time.Duration(p.Nanos)
+ if (d < 0) != (p.Nanos < 0) {
+ return 0, fmt.Errorf("duration: %#v is out of range for time.Duration", p)
+ }
+ }
+ return d, nil
+}
+
+// DurationProto converts a time.Duration to a Duration.
+func DurationProto(d time.Duration) *Duration {
+ nanos := d.Nanoseconds()
+ secs := nanos / 1e9
+ nanos -= secs * 1e9
+ return &Duration{
+ Seconds: secs,
+ Nanos: int32(nanos),
+ }
+}
--- /dev/null
+// Code generated by protoc-gen-gogo.
+// source: duration.proto
+// DO NOT EDIT!
+
+/*
+ Package types is a generated protocol buffer package.
+
+ It is generated from these files:
+ duration.proto
+
+ It has these top-level messages:
+ Duration
+*/
+package types
+
+import proto "github.com/gogo/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+import strings "strings"
+import reflect "reflect"
+
+import io "io"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
+
+// A Duration represents a signed, fixed-length span of time represented
+// as a count of seconds and fractions of seconds at nanosecond
+// resolution. It is independent of any calendar and concepts like "day"
+// or "month". It is related to Timestamp in that the difference between
+// two Timestamp values is a Duration and it can be added or subtracted
+// from a Timestamp. Range is approximately +-10,000 years.
+//
+// Example 1: Compute Duration from two Timestamps in pseudo code.
+//
+// Timestamp start = ...;
+// Timestamp end = ...;
+// Duration duration = ...;
+//
+// duration.seconds = end.seconds - start.seconds;
+// duration.nanos = end.nanos - start.nanos;
+//
+// if (duration.seconds < 0 && duration.nanos > 0) {
+// duration.seconds += 1;
+// duration.nanos -= 1000000000;
+// } else if (durations.seconds > 0 && duration.nanos < 0) {
+// duration.seconds -= 1;
+// duration.nanos += 1000000000;
+// }
+//
+// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
+//
+// Timestamp start = ...;
+// Duration duration = ...;
+// Timestamp end = ...;
+//
+// end.seconds = start.seconds + duration.seconds;
+// end.nanos = start.nanos + duration.nanos;
+//
+// if (end.nanos < 0) {
+// end.seconds -= 1;
+// end.nanos += 1000000000;
+// } else if (end.nanos >= 1000000000) {
+// end.seconds += 1;
+// end.nanos -= 1000000000;
+// }
+//
+// Example 3: Compute Duration from datetime.timedelta in Python.
+//
+// td = datetime.timedelta(days=3, minutes=10)
+// duration = Duration()
+// duration.FromTimedelta(td)
+//
+//
+type Duration struct {
+ // Signed seconds of the span of time. Must be from -315,576,000,000
+ // to +315,576,000,000 inclusive.
+ Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
+ // Signed fractions of a second at nanosecond resolution of the span
+ // of time. Durations less than one second are represented with a 0
+ // `seconds` field and a positive or negative `nanos` field. For durations
+ // of one second or more, a non-zero value for the `nanos` field must be
+ // of the same sign as the `seconds` field. Must be from -999,999,999
+ // to +999,999,999 inclusive.
+ Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
+}
+
+func (m *Duration) Reset() { *m = Duration{} }
+func (*Duration) ProtoMessage() {}
+func (*Duration) Descriptor() ([]byte, []int) { return fileDescriptorDuration, []int{0} }
+func (*Duration) XXX_WellKnownType() string { return "Duration" }
+
+func (m *Duration) GetSeconds() int64 {
+ if m != nil {
+ return m.Seconds
+ }
+ return 0
+}
+
+func (m *Duration) GetNanos() int32 {
+ if m != nil {
+ return m.Nanos
+ }
+ return 0
+}
+
+func init() {
+ proto.RegisterType((*Duration)(nil), "google.protobuf.Duration")
+}
+func (this *Duration) Compare(that interface{}) int {
+ if that == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ }
+
+ that1, ok := that.(*Duration)
+ if !ok {
+ that2, ok := that.(Duration)
+ if ok {
+ that1 = &that2
+ } else {
+ return 1
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ } else if this == nil {
+ return -1
+ }
+ if this.Seconds != that1.Seconds {
+ if this.Seconds < that1.Seconds {
+ return -1
+ }
+ return 1
+ }
+ if this.Nanos != that1.Nanos {
+ if this.Nanos < that1.Nanos {
+ return -1
+ }
+ return 1
+ }
+ return 0
+}
+func (this *Duration) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*Duration)
+ if !ok {
+ that2, ok := that.(Duration)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if this.Seconds != that1.Seconds {
+ return false
+ }
+ if this.Nanos != that1.Nanos {
+ return false
+ }
+ return true
+}
+func (this *Duration) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 6)
+ s = append(s, "&types.Duration{")
+ s = append(s, "Seconds: "+fmt.Sprintf("%#v", this.Seconds)+",\n")
+ s = append(s, "Nanos: "+fmt.Sprintf("%#v", this.Nanos)+",\n")
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func valueToGoStringDuration(v interface{}, typ string) string {
+ rv := reflect.ValueOf(v)
+ if rv.IsNil() {
+ return "nil"
+ }
+ pv := reflect.Indirect(rv).Interface()
+ return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
+}
+func (m *Duration) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Duration) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Seconds != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintDuration(dAtA, i, uint64(m.Seconds))
+ }
+ if m.Nanos != 0 {
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintDuration(dAtA, i, uint64(m.Nanos))
+ }
+ return i, nil
+}
+
+func encodeFixed64Duration(dAtA []byte, offset int, v uint64) int {
+ dAtA[offset] = uint8(v)
+ dAtA[offset+1] = uint8(v >> 8)
+ dAtA[offset+2] = uint8(v >> 16)
+ dAtA[offset+3] = uint8(v >> 24)
+ dAtA[offset+4] = uint8(v >> 32)
+ dAtA[offset+5] = uint8(v >> 40)
+ dAtA[offset+6] = uint8(v >> 48)
+ dAtA[offset+7] = uint8(v >> 56)
+ return offset + 8
+}
+func encodeFixed32Duration(dAtA []byte, offset int, v uint32) int {
+ dAtA[offset] = uint8(v)
+ dAtA[offset+1] = uint8(v >> 8)
+ dAtA[offset+2] = uint8(v >> 16)
+ dAtA[offset+3] = uint8(v >> 24)
+ return offset + 4
+}
+func encodeVarintDuration(dAtA []byte, offset int, v uint64) int {
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return offset + 1
+}
+func (m *Duration) Size() (n int) {
+ var l int
+ _ = l
+ if m.Seconds != 0 {
+ n += 1 + sovDuration(uint64(m.Seconds))
+ }
+ if m.Nanos != 0 {
+ n += 1 + sovDuration(uint64(m.Nanos))
+ }
+ return n
+}
+
+func sovDuration(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+func sozDuration(x uint64) (n int) {
+ return sovDuration(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Duration) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowDuration
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Duration: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Duration: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Seconds", wireType)
+ }
+ m.Seconds = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowDuration
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Seconds |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Nanos", wireType)
+ }
+ m.Nanos = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowDuration
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Nanos |= (int32(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipDuration(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthDuration
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipDuration(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowDuration
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowDuration
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ return iNdEx, nil
+ case 1:
+ iNdEx += 8
+ return iNdEx, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowDuration
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ iNdEx += length
+ if length < 0 {
+ return 0, ErrInvalidLengthDuration
+ }
+ return iNdEx, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = iNdEx
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowDuration
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := skipDuration(dAtA[start:])
+ if err != nil {
+ return 0, err
+ }
+ iNdEx = start + next
+ }
+ return iNdEx, nil
+ case 4:
+ return iNdEx, nil
+ case 5:
+ iNdEx += 4
+ return iNdEx, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
+
+var (
+ ErrInvalidLengthDuration = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowDuration = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("duration.proto", fileDescriptorDuration) }
+
+var fileDescriptorDuration = []byte{
+ // 203 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4b, 0x29, 0x2d, 0x4a,
+ 0x2c, 0xc9, 0xcc, 0xcf, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x4f, 0xcf, 0xcf, 0x4f,
+ 0xcf, 0x49, 0x85, 0xf0, 0x92, 0x4a, 0xd3, 0x94, 0xac, 0xb8, 0x38, 0x5c, 0xa0, 0x4a, 0x84, 0x24,
+ 0xb8, 0xd8, 0x8b, 0x53, 0x93, 0xf3, 0xf3, 0x52, 0x8a, 0x25, 0x18, 0x15, 0x18, 0x35, 0x98, 0x83,
+ 0x60, 0x5c, 0x21, 0x11, 0x2e, 0xd6, 0xbc, 0xc4, 0xbc, 0xfc, 0x62, 0x09, 0x26, 0x05, 0x46, 0x0d,
+ 0xd6, 0x20, 0x08, 0xc7, 0xa9, 0xfe, 0xc2, 0x43, 0x39, 0x86, 0x1b, 0x0f, 0xe5, 0x18, 0x3e, 0x3c,
+ 0x94, 0x63, 0x5c, 0xf1, 0x48, 0x8e, 0xf1, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f,
+ 0x3c, 0x92, 0x63, 0x7c, 0xf1, 0x48, 0x8e, 0xe1, 0xc3, 0x23, 0x39, 0xc6, 0x15, 0x8f, 0xe5, 0x18,
+ 0xb9, 0x84, 0x93, 0xf3, 0x73, 0xf5, 0xd0, 0xac, 0x76, 0xe2, 0x85, 0x59, 0x1c, 0x00, 0x12, 0x09,
+ 0x60, 0x8c, 0x62, 0x2d, 0xa9, 0x2c, 0x48, 0x2d, 0xfe, 0xc1, 0xc8, 0xb8, 0x88, 0x89, 0xd9, 0x3d,
+ 0xc0, 0x69, 0x15, 0x93, 0x9c, 0x3b, 0x44, 0x4b, 0x00, 0x54, 0x8b, 0x5e, 0x78, 0x6a, 0x4e, 0x8e,
+ 0x77, 0x5e, 0x7e, 0x79, 0x5e, 0x08, 0x48, 0x65, 0x12, 0x1b, 0xd8, 0x2c, 0x63, 0x40, 0x00, 0x00,
+ 0x00, 0xff, 0xff, 0x9d, 0x5a, 0x25, 0xa5, 0xe6, 0x00, 0x00, 0x00,
+}
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2016, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package types
+
+import (
+ "fmt"
+ "time"
+)
+
+func NewPopulatedDuration(r interface {
+ Int63() int64
+}, easy bool) *Duration {
+ this := &Duration{}
+ maxSecs := time.Hour.Nanoseconds() / 1e9
+ max := 2 * maxSecs
+ s := int64(r.Int63()) % max
+ s -= maxSecs
+ neg := int64(1)
+ if s < 0 {
+ neg = -1
+ }
+ this.Seconds = s
+ this.Nanos = int32(neg * (r.Int63() % 1e9))
+ return this
+}
+
+func (d *Duration) String() string {
+ td, err := DurationFromProto(d)
+ if err != nil {
+ return fmt.Sprintf("(%v)", err)
+ }
+ return td.String()
+}
+
+func NewPopulatedStdDuration(r interface {
+ Int63() int64
+}, easy bool) *time.Duration {
+ dur := NewPopulatedDuration(r, easy)
+ d, err := DurationFromProto(dur)
+ if err != nil {
+ return nil
+ }
+ return &d
+}
+
+func SizeOfStdDuration(d time.Duration) int {
+ dur := DurationProto(d)
+ return dur.Size()
+}
+
+func StdDurationMarshal(d time.Duration) ([]byte, error) {
+ size := SizeOfStdDuration(d)
+ buf := make([]byte, size)
+ _, err := StdDurationMarshalTo(d, buf)
+ return buf, err
+}
+
+func StdDurationMarshalTo(d time.Duration, data []byte) (int, error) {
+ dur := DurationProto(d)
+ return dur.MarshalTo(data)
+}
+
+func StdDurationUnmarshal(d *time.Duration, data []byte) error {
+ dur := &Duration{}
+ if err := dur.Unmarshal(data); err != nil {
+ return err
+ }
+ dd, err := DurationFromProto(dur)
+ if err != nil {
+ return err
+ }
+ *d = dd
+ return nil
+}
--- /dev/null
+// Code generated by protoc-gen-gogo.
+// source: empty.proto
+// DO NOT EDIT!
+
+/*
+Package types is a generated protocol buffer package.
+
+It is generated from these files:
+ empty.proto
+
+It has these top-level messages:
+ Empty
+*/
+package types
+
+import proto "github.com/gogo/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+import strings "strings"
+import reflect "reflect"
+
+import io "io"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
+
+// A generic empty message that you can re-use to avoid defining duplicated
+// empty messages in your APIs. A typical example is to use it as the request
+// or the response type of an API method. For instance:
+//
+// service Foo {
+// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
+// }
+//
+// The JSON representation for `Empty` is empty JSON object `{}`.
+type Empty struct {
+}
+
+func (m *Empty) Reset() { *m = Empty{} }
+func (*Empty) ProtoMessage() {}
+func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptorEmpty, []int{0} }
+func (*Empty) XXX_WellKnownType() string { return "Empty" }
+
+func init() {
+ proto.RegisterType((*Empty)(nil), "google.protobuf.Empty")
+}
+func (this *Empty) Compare(that interface{}) int {
+ if that == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ }
+
+ that1, ok := that.(*Empty)
+ if !ok {
+ that2, ok := that.(Empty)
+ if ok {
+ that1 = &that2
+ } else {
+ return 1
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ } else if this == nil {
+ return -1
+ }
+ return 0
+}
+func (this *Empty) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*Empty)
+ if !ok {
+ that2, ok := that.(Empty)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ return true
+}
+func (this *Empty) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 4)
+ s = append(s, "&types.Empty{")
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func valueToGoStringEmpty(v interface{}, typ string) string {
+ rv := reflect.ValueOf(v)
+ if rv.IsNil() {
+ return "nil"
+ }
+ pv := reflect.Indirect(rv).Interface()
+ return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
+}
+func (m *Empty) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Empty) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ return i, nil
+}
+
+func encodeFixed64Empty(dAtA []byte, offset int, v uint64) int {
+ dAtA[offset] = uint8(v)
+ dAtA[offset+1] = uint8(v >> 8)
+ dAtA[offset+2] = uint8(v >> 16)
+ dAtA[offset+3] = uint8(v >> 24)
+ dAtA[offset+4] = uint8(v >> 32)
+ dAtA[offset+5] = uint8(v >> 40)
+ dAtA[offset+6] = uint8(v >> 48)
+ dAtA[offset+7] = uint8(v >> 56)
+ return offset + 8
+}
+func encodeFixed32Empty(dAtA []byte, offset int, v uint32) int {
+ dAtA[offset] = uint8(v)
+ dAtA[offset+1] = uint8(v >> 8)
+ dAtA[offset+2] = uint8(v >> 16)
+ dAtA[offset+3] = uint8(v >> 24)
+ return offset + 4
+}
+func encodeVarintEmpty(dAtA []byte, offset int, v uint64) int {
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return offset + 1
+}
+func NewPopulatedEmpty(r randyEmpty, easy bool) *Empty {
+ this := &Empty{}
+ if !easy && r.Intn(10) != 0 {
+ }
+ return this
+}
+
+type randyEmpty interface {
+ Float32() float32
+ Float64() float64
+ Int63() int64
+ Int31() int32
+ Uint32() uint32
+ Intn(n int) int
+}
+
+func randUTF8RuneEmpty(r randyEmpty) rune {
+ ru := r.Intn(62)
+ if ru < 10 {
+ return rune(ru + 48)
+ } else if ru < 36 {
+ return rune(ru + 55)
+ }
+ return rune(ru + 61)
+}
+func randStringEmpty(r randyEmpty) string {
+ v1 := r.Intn(100)
+ tmps := make([]rune, v1)
+ for i := 0; i < v1; i++ {
+ tmps[i] = randUTF8RuneEmpty(r)
+ }
+ return string(tmps)
+}
+func randUnrecognizedEmpty(r randyEmpty, maxFieldNumber int) (dAtA []byte) {
+ l := r.Intn(5)
+ for i := 0; i < l; i++ {
+ wire := r.Intn(4)
+ if wire == 3 {
+ wire = 5
+ }
+ fieldNumber := maxFieldNumber + r.Intn(100)
+ dAtA = randFieldEmpty(dAtA, r, fieldNumber, wire)
+ }
+ return dAtA
+}
+func randFieldEmpty(dAtA []byte, r randyEmpty, fieldNumber int, wire int) []byte {
+ key := uint32(fieldNumber)<<3 | uint32(wire)
+ switch wire {
+ case 0:
+ dAtA = encodeVarintPopulateEmpty(dAtA, uint64(key))
+ v2 := r.Int63()
+ if r.Intn(2) == 0 {
+ v2 *= -1
+ }
+ dAtA = encodeVarintPopulateEmpty(dAtA, uint64(v2))
+ case 1:
+ dAtA = encodeVarintPopulateEmpty(dAtA, uint64(key))
+ dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))
+ case 2:
+ dAtA = encodeVarintPopulateEmpty(dAtA, uint64(key))
+ ll := r.Intn(100)
+ dAtA = encodeVarintPopulateEmpty(dAtA, uint64(ll))
+ for j := 0; j < ll; j++ {
+ dAtA = append(dAtA, byte(r.Intn(256)))
+ }
+ default:
+ dAtA = encodeVarintPopulateEmpty(dAtA, uint64(key))
+ dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))
+ }
+ return dAtA
+}
+func encodeVarintPopulateEmpty(dAtA []byte, v uint64) []byte {
+ for v >= 1<<7 {
+ dAtA = append(dAtA, uint8(uint64(v)&0x7f|0x80))
+ v >>= 7
+ }
+ dAtA = append(dAtA, uint8(v))
+ return dAtA
+}
+func (m *Empty) Size() (n int) {
+ var l int
+ _ = l
+ return n
+}
+
+func sovEmpty(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+func sozEmpty(x uint64) (n int) {
+ return sovEmpty(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (this *Empty) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&Empty{`,
+ `}`,
+ }, "")
+ return s
+}
+func valueToStringEmpty(v interface{}) string {
+ rv := reflect.ValueOf(v)
+ if rv.IsNil() {
+ return "nil"
+ }
+ pv := reflect.Indirect(rv).Interface()
+ return fmt.Sprintf("*%v", pv)
+}
+func (m *Empty) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEmpty
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Empty: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Empty: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEmpty(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthEmpty
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipEmpty(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEmpty
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEmpty
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ return iNdEx, nil
+ case 1:
+ iNdEx += 8
+ return iNdEx, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEmpty
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ iNdEx += length
+ if length < 0 {
+ return 0, ErrInvalidLengthEmpty
+ }
+ return iNdEx, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = iNdEx
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEmpty
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := skipEmpty(dAtA[start:])
+ if err != nil {
+ return 0, err
+ }
+ iNdEx = start + next
+ }
+ return iNdEx, nil
+ case 4:
+ return iNdEx, nil
+ case 5:
+ iNdEx += 4
+ return iNdEx, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
+
+var (
+ ErrInvalidLengthEmpty = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowEmpty = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("empty.proto", fileDescriptorEmpty) }
+
+var fileDescriptorEmpty = []byte{
+ // 169 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4e, 0xcd, 0x2d, 0x28,
+ 0xa9, 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x4f, 0xcf, 0xcf, 0x4f, 0xcf, 0x49, 0x85,
+ 0xf0, 0x92, 0x4a, 0xd3, 0x94, 0xd8, 0xb9, 0x58, 0x5d, 0x41, 0xf2, 0x4e, 0x2d, 0x8c, 0x17, 0x1e,
+ 0xca, 0x31, 0xdc, 0x78, 0x28, 0xc7, 0xf0, 0xe1, 0xa1, 0x1c, 0xe3, 0x8f, 0x87, 0x72, 0x8c, 0x0d,
+ 0x8f, 0xe4, 0x18, 0x57, 0x3c, 0x92, 0x63, 0x3c, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6,
+ 0x07, 0x8f, 0xe4, 0x18, 0x5f, 0x3c, 0x92, 0x63, 0xf8, 0x00, 0x12, 0x7f, 0x2c, 0xc7, 0xc8, 0x25,
+ 0x9c, 0x9c, 0x9f, 0xab, 0x87, 0x66, 0xa0, 0x13, 0x17, 0xd8, 0xb8, 0x00, 0x10, 0x37, 0x80, 0x31,
+ 0x8a, 0xb5, 0xa4, 0xb2, 0x20, 0xb5, 0xf8, 0x07, 0x23, 0xe3, 0x22, 0x26, 0x66, 0xf7, 0x00, 0xa7,
+ 0x55, 0x4c, 0x72, 0xee, 0x10, 0xf5, 0x01, 0x50, 0xf5, 0x7a, 0xe1, 0xa9, 0x39, 0x39, 0xde, 0x79,
+ 0xf9, 0xe5, 0x79, 0x21, 0x20, 0x95, 0x49, 0x6c, 0x60, 0x83, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff,
+ 0xff, 0x7c, 0xa8, 0xf0, 0xc4, 0xb6, 0x00, 0x00, 0x00,
+}
--- /dev/null
+// Code generated by protoc-gen-gogo.
+// source: field_mask.proto
+// DO NOT EDIT!
+
+/*
+Package types is a generated protocol buffer package.
+
+It is generated from these files:
+ field_mask.proto
+
+It has these top-level messages:
+ FieldMask
+*/
+package types
+
+import proto "github.com/gogo/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+import strings "strings"
+import reflect "reflect"
+
+import io "io"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
+
+// `FieldMask` represents a set of symbolic field paths, for example:
+//
+// paths: "f.a"
+// paths: "f.b.d"
+//
+// Here `f` represents a field in some root message, `a` and `b`
+// fields in the message found in `f`, and `d` a field found in the
+// message in `f.b`.
+//
+// Field masks are used to specify a subset of fields that should be
+// returned by a get operation or modified by an update operation.
+// Field masks also have a custom JSON encoding (see below).
+//
+// # Field Masks in Projections
+//
+// When used in the context of a projection, a response message or
+// sub-message is filtered by the API to only contain those fields as
+// specified in the mask. For example, if the mask in the previous
+// example is applied to a response message as follows:
+//
+// f {
+// a : 22
+// b {
+// d : 1
+// x : 2
+// }
+// y : 13
+// }
+// z: 8
+//
+// The result will not contain specific values for fields x,y and z
+// (their value will be set to the default, and omitted in proto text
+// output):
+//
+//
+// f {
+// a : 22
+// b {
+// d : 1
+// }
+// }
+//
+// A repeated field is not allowed except at the last position of a
+// paths string.
+//
+// If a FieldMask object is not present in a get operation, the
+// operation applies to all fields (as if a FieldMask of all fields
+// had been specified).
+//
+// Note that a field mask does not necessarily apply to the
+// top-level response message. In case of a REST get operation, the
+// field mask applies directly to the response, but in case of a REST
+// list operation, the mask instead applies to each individual message
+// in the returned resource list. In case of a REST custom method,
+// other definitions may be used. Where the mask applies will be
+// clearly documented together with its declaration in the API. In
+// any case, the effect on the returned resource/resources is required
+// behavior for APIs.
+//
+// # Field Masks in Update Operations
+//
+// A field mask in update operations specifies which fields of the
+// targeted resource are going to be updated. The API is required
+// to only change the values of the fields as specified in the mask
+// and leave the others untouched. If a resource is passed in to
+// describe the updated values, the API ignores the values of all
+// fields not covered by the mask.
+//
+// If a repeated field is specified for an update operation, the existing
+// repeated values in the target resource will be overwritten by the new values.
+// Note that a repeated field is only allowed in the last position of a `paths`
+// string.
+//
+// If a sub-message is specified in the last position of the field mask for an
+// update operation, then the existing sub-message in the target resource is
+// overwritten. Given the target message:
+//
+// f {
+// b {
+// d : 1
+// x : 2
+// }
+// c : 1
+// }
+//
+// And an update message:
+//
+// f {
+// b {
+// d : 10
+// }
+// }
+//
+// then if the field mask is:
+//
+// paths: "f.b"
+//
+// then the result will be:
+//
+// f {
+// b {
+// d : 10
+// }
+// c : 1
+// }
+//
+// However, if the update mask was:
+//
+// paths: "f.b.d"
+//
+// then the result would be:
+//
+// f {
+// b {
+// d : 10
+// x : 2
+// }
+// c : 1
+// }
+//
+// In order to reset a field's value to the default, the field must
+// be in the mask and set to the default value in the provided resource.
+// Hence, in order to reset all fields of a resource, provide a default
+// instance of the resource and set all fields in the mask, or do
+// not provide a mask as described below.
+//
+// If a field mask is not present on update, the operation applies to
+// all fields (as if a field mask of all fields has been specified).
+// Note that in the presence of schema evolution, this may mean that
+// fields the client does not know and has therefore not filled into
+// the request will be reset to their default. If this is unwanted
+// behavior, a specific service may require a client to always specify
+// a field mask, producing an error if not.
+//
+// As with get operations, the location of the resource which
+// describes the updated values in the request message depends on the
+// operation kind. In any case, the effect of the field mask is
+// required to be honored by the API.
+//
+// ## Considerations for HTTP REST
+//
+// The HTTP kind of an update operation which uses a field mask must
+// be set to PATCH instead of PUT in order to satisfy HTTP semantics
+// (PUT must only be used for full updates).
+//
+// # JSON Encoding of Field Masks
+//
+// In JSON, a field mask is encoded as a single string where paths are
+// separated by a comma. Fields name in each path are converted
+// to/from lower-camel naming conventions.
+//
+// As an example, consider the following message declarations:
+//
+// message Profile {
+// User user = 1;
+// Photo photo = 2;
+// }
+// message User {
+// string display_name = 1;
+// string address = 2;
+// }
+//
+// In proto a field mask for `Profile` may look as such:
+//
+// mask {
+// paths: "user.display_name"
+// paths: "photo"
+// }
+//
+// In JSON, the same mask is represented as below:
+//
+// {
+// mask: "user.displayName,photo"
+// }
+//
+// # Field Masks and Oneof Fields
+//
+// Field masks treat fields in oneofs just as regular fields. Consider the
+// following message:
+//
+// message SampleMessage {
+// oneof test_oneof {
+// string name = 4;
+// SubMessage sub_message = 9;
+// }
+// }
+//
+// The field mask can be:
+//
+// mask {
+// paths: "name"
+// }
+//
+// Or:
+//
+// mask {
+// paths: "sub_message"
+// }
+//
+// Note that oneof type names ("test_oneof" in this case) cannot be used in
+// paths.
+type FieldMask struct {
+ // The set of field mask paths.
+ Paths []string `protobuf:"bytes,1,rep,name=paths" json:"paths,omitempty"`
+}
+
+func (m *FieldMask) Reset() { *m = FieldMask{} }
+func (*FieldMask) ProtoMessage() {}
+func (*FieldMask) Descriptor() ([]byte, []int) { return fileDescriptorFieldMask, []int{0} }
+
+func (m *FieldMask) GetPaths() []string {
+ if m != nil {
+ return m.Paths
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*FieldMask)(nil), "google.protobuf.FieldMask")
+}
+func (this *FieldMask) Compare(that interface{}) int {
+ if that == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ }
+
+ that1, ok := that.(*FieldMask)
+ if !ok {
+ that2, ok := that.(FieldMask)
+ if ok {
+ that1 = &that2
+ } else {
+ return 1
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ } else if this == nil {
+ return -1
+ }
+ if len(this.Paths) != len(that1.Paths) {
+ if len(this.Paths) < len(that1.Paths) {
+ return -1
+ }
+ return 1
+ }
+ for i := range this.Paths {
+ if this.Paths[i] != that1.Paths[i] {
+ if this.Paths[i] < that1.Paths[i] {
+ return -1
+ }
+ return 1
+ }
+ }
+ return 0
+}
+func (this *FieldMask) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*FieldMask)
+ if !ok {
+ that2, ok := that.(FieldMask)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if len(this.Paths) != len(that1.Paths) {
+ return false
+ }
+ for i := range this.Paths {
+ if this.Paths[i] != that1.Paths[i] {
+ return false
+ }
+ }
+ return true
+}
+func (this *FieldMask) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&types.FieldMask{")
+ s = append(s, "Paths: "+fmt.Sprintf("%#v", this.Paths)+",\n")
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func valueToGoStringFieldMask(v interface{}, typ string) string {
+ rv := reflect.ValueOf(v)
+ if rv.IsNil() {
+ return "nil"
+ }
+ pv := reflect.Indirect(rv).Interface()
+ return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
+}
+func (m *FieldMask) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *FieldMask) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Paths) > 0 {
+ for _, s := range m.Paths {
+ dAtA[i] = 0xa
+ i++
+ l = len(s)
+ for l >= 1<<7 {
+ dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
+ l >>= 7
+ i++
+ }
+ dAtA[i] = uint8(l)
+ i++
+ i += copy(dAtA[i:], s)
+ }
+ }
+ return i, nil
+}
+
+func encodeFixed64FieldMask(dAtA []byte, offset int, v uint64) int {
+ dAtA[offset] = uint8(v)
+ dAtA[offset+1] = uint8(v >> 8)
+ dAtA[offset+2] = uint8(v >> 16)
+ dAtA[offset+3] = uint8(v >> 24)
+ dAtA[offset+4] = uint8(v >> 32)
+ dAtA[offset+5] = uint8(v >> 40)
+ dAtA[offset+6] = uint8(v >> 48)
+ dAtA[offset+7] = uint8(v >> 56)
+ return offset + 8
+}
+func encodeFixed32FieldMask(dAtA []byte, offset int, v uint32) int {
+ dAtA[offset] = uint8(v)
+ dAtA[offset+1] = uint8(v >> 8)
+ dAtA[offset+2] = uint8(v >> 16)
+ dAtA[offset+3] = uint8(v >> 24)
+ return offset + 4
+}
+func encodeVarintFieldMask(dAtA []byte, offset int, v uint64) int {
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return offset + 1
+}
+func NewPopulatedFieldMask(r randyFieldMask, easy bool) *FieldMask {
+ this := &FieldMask{}
+ v1 := r.Intn(10)
+ this.Paths = make([]string, v1)
+ for i := 0; i < v1; i++ {
+ this.Paths[i] = string(randStringFieldMask(r))
+ }
+ if !easy && r.Intn(10) != 0 {
+ }
+ return this
+}
+
+type randyFieldMask interface {
+ Float32() float32
+ Float64() float64
+ Int63() int64
+ Int31() int32
+ Uint32() uint32
+ Intn(n int) int
+}
+
+func randUTF8RuneFieldMask(r randyFieldMask) rune {
+ ru := r.Intn(62)
+ if ru < 10 {
+ return rune(ru + 48)
+ } else if ru < 36 {
+ return rune(ru + 55)
+ }
+ return rune(ru + 61)
+}
+func randStringFieldMask(r randyFieldMask) string {
+ v2 := r.Intn(100)
+ tmps := make([]rune, v2)
+ for i := 0; i < v2; i++ {
+ tmps[i] = randUTF8RuneFieldMask(r)
+ }
+ return string(tmps)
+}
+func randUnrecognizedFieldMask(r randyFieldMask, maxFieldNumber int) (dAtA []byte) {
+ l := r.Intn(5)
+ for i := 0; i < l; i++ {
+ wire := r.Intn(4)
+ if wire == 3 {
+ wire = 5
+ }
+ fieldNumber := maxFieldNumber + r.Intn(100)
+ dAtA = randFieldFieldMask(dAtA, r, fieldNumber, wire)
+ }
+ return dAtA
+}
+func randFieldFieldMask(dAtA []byte, r randyFieldMask, fieldNumber int, wire int) []byte {
+ key := uint32(fieldNumber)<<3 | uint32(wire)
+ switch wire {
+ case 0:
+ dAtA = encodeVarintPopulateFieldMask(dAtA, uint64(key))
+ v3 := r.Int63()
+ if r.Intn(2) == 0 {
+ v3 *= -1
+ }
+ dAtA = encodeVarintPopulateFieldMask(dAtA, uint64(v3))
+ case 1:
+ dAtA = encodeVarintPopulateFieldMask(dAtA, uint64(key))
+ dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))
+ case 2:
+ dAtA = encodeVarintPopulateFieldMask(dAtA, uint64(key))
+ ll := r.Intn(100)
+ dAtA = encodeVarintPopulateFieldMask(dAtA, uint64(ll))
+ for j := 0; j < ll; j++ {
+ dAtA = append(dAtA, byte(r.Intn(256)))
+ }
+ default:
+ dAtA = encodeVarintPopulateFieldMask(dAtA, uint64(key))
+ dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))
+ }
+ return dAtA
+}
+func encodeVarintPopulateFieldMask(dAtA []byte, v uint64) []byte {
+ for v >= 1<<7 {
+ dAtA = append(dAtA, uint8(uint64(v)&0x7f|0x80))
+ v >>= 7
+ }
+ dAtA = append(dAtA, uint8(v))
+ return dAtA
+}
+func (m *FieldMask) Size() (n int) {
+ var l int
+ _ = l
+ if len(m.Paths) > 0 {
+ for _, s := range m.Paths {
+ l = len(s)
+ n += 1 + l + sovFieldMask(uint64(l))
+ }
+ }
+ return n
+}
+
+func sovFieldMask(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+func sozFieldMask(x uint64) (n int) {
+ return sovFieldMask(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (this *FieldMask) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&FieldMask{`,
+ `Paths:` + fmt.Sprintf("%v", this.Paths) + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func valueToStringFieldMask(v interface{}) string {
+ rv := reflect.ValueOf(v)
+ if rv.IsNil() {
+ return "nil"
+ }
+ pv := reflect.Indirect(rv).Interface()
+ return fmt.Sprintf("*%v", pv)
+}
+func (m *FieldMask) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowFieldMask
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: FieldMask: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: FieldMask: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Paths", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowFieldMask
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthFieldMask
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Paths = append(m.Paths, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipFieldMask(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthFieldMask
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipFieldMask(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowFieldMask
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowFieldMask
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ return iNdEx, nil
+ case 1:
+ iNdEx += 8
+ return iNdEx, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowFieldMask
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ iNdEx += length
+ if length < 0 {
+ return 0, ErrInvalidLengthFieldMask
+ }
+ return iNdEx, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = iNdEx
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowFieldMask
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := skipFieldMask(dAtA[start:])
+ if err != nil {
+ return 0, err
+ }
+ iNdEx = start + next
+ }
+ return iNdEx, nil
+ case 4:
+ return iNdEx, nil
+ case 5:
+ iNdEx += 4
+ return iNdEx, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
+
+var (
+ ErrInvalidLengthFieldMask = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowFieldMask = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("field_mask.proto", fileDescriptorFieldMask) }
+
+var fileDescriptorFieldMask = []byte{
+ // 193 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x48, 0xcb, 0x4c, 0xcd,
+ 0x49, 0x89, 0xcf, 0x4d, 0x2c, 0xce, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x4f, 0xcf,
+ 0xcf, 0x4f, 0xcf, 0x49, 0x85, 0xf0, 0x92, 0x4a, 0xd3, 0x94, 0x14, 0xb9, 0x38, 0xdd, 0x40, 0x8a,
+ 0x7c, 0x13, 0x8b, 0xb3, 0x85, 0x44, 0xb8, 0x58, 0x0b, 0x12, 0x4b, 0x32, 0x8a, 0x25, 0x18, 0x15,
+ 0x98, 0x35, 0x38, 0x83, 0x20, 0x1c, 0xa7, 0x56, 0xc6, 0x0b, 0x0f, 0xe5, 0x18, 0x6e, 0x3c, 0x94,
+ 0x63, 0xf8, 0xf0, 0x50, 0x8e, 0xf1, 0xc7, 0x43, 0x39, 0xc6, 0x86, 0x47, 0x72, 0x8c, 0x2b, 0x1e,
+ 0xc9, 0x31, 0x9e, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x2f,
+ 0x1e, 0xc9, 0x31, 0x7c, 0x00, 0x89, 0x3f, 0x96, 0x63, 0xe4, 0x12, 0x4e, 0xce, 0xcf, 0xd5, 0x43,
+ 0xb3, 0xca, 0x89, 0x0f, 0x6e, 0x51, 0x00, 0x48, 0x28, 0x80, 0x31, 0x8a, 0xb5, 0xa4, 0xb2, 0x20,
+ 0xb5, 0x78, 0x11, 0x13, 0xb3, 0x7b, 0x80, 0xd3, 0x2a, 0x26, 0x39, 0x77, 0x88, 0x86, 0x00, 0xa8,
+ 0x06, 0xbd, 0xf0, 0xd4, 0x9c, 0x1c, 0xef, 0xbc, 0xfc, 0xf2, 0xbc, 0x10, 0x90, 0xb2, 0x24, 0x36,
+ 0xb0, 0x49, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x51, 0x31, 0x89, 0xb5, 0xd6, 0x00, 0x00,
+ 0x00,
+}
--- /dev/null
+// Code generated by protoc-gen-gogo.
+// source: struct.proto
+// DO NOT EDIT!
+
+/*
+ Package types is a generated protocol buffer package.
+
+ It is generated from these files:
+ struct.proto
+
+ It has these top-level messages:
+ Struct
+ Value
+ ListValue
+*/
+package types
+
+import proto "github.com/gogo/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+import strconv "strconv"
+
+import strings "strings"
+import reflect "reflect"
+import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
+
+import io "io"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
+
+// `NullValue` is a singleton enumeration to represent the null value for the
+// `Value` type union.
+//
+// The JSON representation for `NullValue` is JSON `null`.
+type NullValue int32
+
+const (
+ // Null value.
+ NULL_VALUE NullValue = 0
+)
+
+var NullValue_name = map[int32]string{
+ 0: "NULL_VALUE",
+}
+var NullValue_value = map[string]int32{
+ "NULL_VALUE": 0,
+}
+
+func (NullValue) EnumDescriptor() ([]byte, []int) { return fileDescriptorStruct, []int{0} }
+func (NullValue) XXX_WellKnownType() string { return "NullValue" }
+
+// `Struct` represents a structured data value, consisting of fields
+// which map to dynamically typed values. In some languages, `Struct`
+// might be supported by a native representation. For example, in
+// scripting languages like JS a struct is represented as an
+// object. The details of that representation are described together
+// with the proto support for the language.
+//
+// The JSON representation for `Struct` is JSON object.
+type Struct struct {
+ // Unordered map of dynamically typed values.
+ Fields map[string]*Value `protobuf:"bytes,1,rep,name=fields" json:"fields,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"`
+}
+
+func (m *Struct) Reset() { *m = Struct{} }
+func (*Struct) ProtoMessage() {}
+func (*Struct) Descriptor() ([]byte, []int) { return fileDescriptorStruct, []int{0} }
+func (*Struct) XXX_WellKnownType() string { return "Struct" }
+
+func (m *Struct) GetFields() map[string]*Value {
+ if m != nil {
+ return m.Fields
+ }
+ return nil
+}
+
+// `Value` represents a dynamically typed value which can be either
+// null, a number, a string, a boolean, a recursive struct value, or a
+// list of values. A producer of value is expected to set one of that
+// variants, absence of any variant indicates an error.
+//
+// The JSON representation for `Value` is JSON value.
+type Value struct {
+ // The kind of value.
+ //
+ // Types that are valid to be assigned to Kind:
+ // *Value_NullValue
+ // *Value_NumberValue
+ // *Value_StringValue
+ // *Value_BoolValue
+ // *Value_StructValue
+ // *Value_ListValue
+ Kind isValue_Kind `protobuf_oneof:"kind"`
+}
+
+func (m *Value) Reset() { *m = Value{} }
+func (*Value) ProtoMessage() {}
+func (*Value) Descriptor() ([]byte, []int) { return fileDescriptorStruct, []int{1} }
+func (*Value) XXX_WellKnownType() string { return "Value" }
+
+type isValue_Kind interface {
+ isValue_Kind()
+ Equal(interface{}) bool
+ MarshalTo([]byte) (int, error)
+ Size() int
+}
+
+type Value_NullValue struct {
+ NullValue NullValue `protobuf:"varint,1,opt,name=null_value,json=nullValue,proto3,enum=google.protobuf.NullValue,oneof"`
+}
+type Value_NumberValue struct {
+ NumberValue float64 `protobuf:"fixed64,2,opt,name=number_value,json=numberValue,proto3,oneof"`
+}
+type Value_StringValue struct {
+ StringValue string `protobuf:"bytes,3,opt,name=string_value,json=stringValue,proto3,oneof"`
+}
+type Value_BoolValue struct {
+ BoolValue bool `protobuf:"varint,4,opt,name=bool_value,json=boolValue,proto3,oneof"`
+}
+type Value_StructValue struct {
+ StructValue *Struct `protobuf:"bytes,5,opt,name=struct_value,json=structValue,oneof"`
+}
+type Value_ListValue struct {
+ ListValue *ListValue `protobuf:"bytes,6,opt,name=list_value,json=listValue,oneof"`
+}
+
+func (*Value_NullValue) isValue_Kind() {}
+func (*Value_NumberValue) isValue_Kind() {}
+func (*Value_StringValue) isValue_Kind() {}
+func (*Value_BoolValue) isValue_Kind() {}
+func (*Value_StructValue) isValue_Kind() {}
+func (*Value_ListValue) isValue_Kind() {}
+
+func (m *Value) GetKind() isValue_Kind {
+ if m != nil {
+ return m.Kind
+ }
+ return nil
+}
+
+func (m *Value) GetNullValue() NullValue {
+ if x, ok := m.GetKind().(*Value_NullValue); ok {
+ return x.NullValue
+ }
+ return NULL_VALUE
+}
+
+func (m *Value) GetNumberValue() float64 {
+ if x, ok := m.GetKind().(*Value_NumberValue); ok {
+ return x.NumberValue
+ }
+ return 0
+}
+
+func (m *Value) GetStringValue() string {
+ if x, ok := m.GetKind().(*Value_StringValue); ok {
+ return x.StringValue
+ }
+ return ""
+}
+
+func (m *Value) GetBoolValue() bool {
+ if x, ok := m.GetKind().(*Value_BoolValue); ok {
+ return x.BoolValue
+ }
+ return false
+}
+
+func (m *Value) GetStructValue() *Struct {
+ if x, ok := m.GetKind().(*Value_StructValue); ok {
+ return x.StructValue
+ }
+ return nil
+}
+
+func (m *Value) GetListValue() *ListValue {
+ if x, ok := m.GetKind().(*Value_ListValue); ok {
+ return x.ListValue
+ }
+ return nil
+}
+
+// XXX_OneofFuncs is for the internal use of the proto package.
+func (*Value) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
+ return _Value_OneofMarshaler, _Value_OneofUnmarshaler, _Value_OneofSizer, []interface{}{
+ (*Value_NullValue)(nil),
+ (*Value_NumberValue)(nil),
+ (*Value_StringValue)(nil),
+ (*Value_BoolValue)(nil),
+ (*Value_StructValue)(nil),
+ (*Value_ListValue)(nil),
+ }
+}
+
+func _Value_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
+ m := msg.(*Value)
+ // kind
+ switch x := m.Kind.(type) {
+ case *Value_NullValue:
+ _ = b.EncodeVarint(1<<3 | proto.WireVarint)
+ _ = b.EncodeVarint(uint64(x.NullValue))
+ case *Value_NumberValue:
+ _ = b.EncodeVarint(2<<3 | proto.WireFixed64)
+ _ = b.EncodeFixed64(math.Float64bits(x.NumberValue))
+ case *Value_StringValue:
+ _ = b.EncodeVarint(3<<3 | proto.WireBytes)
+ _ = b.EncodeStringBytes(x.StringValue)
+ case *Value_BoolValue:
+ t := uint64(0)
+ if x.BoolValue {
+ t = 1
+ }
+ _ = b.EncodeVarint(4<<3 | proto.WireVarint)
+ _ = b.EncodeVarint(t)
+ case *Value_StructValue:
+ _ = b.EncodeVarint(5<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.StructValue); err != nil {
+ return err
+ }
+ case *Value_ListValue:
+ _ = b.EncodeVarint(6<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.ListValue); err != nil {
+ return err
+ }
+ case nil:
+ default:
+ return fmt.Errorf("Value.Kind has unexpected type %T", x)
+ }
+ return nil
+}
+
+func _Value_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
+ m := msg.(*Value)
+ switch tag {
+ case 1: // kind.null_value
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeVarint()
+ m.Kind = &Value_NullValue{NullValue(x)}
+ return true, err
+ case 2: // kind.number_value
+ if wire != proto.WireFixed64 {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeFixed64()
+ m.Kind = &Value_NumberValue{math.Float64frombits(x)}
+ return true, err
+ case 3: // kind.string_value
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeStringBytes()
+ m.Kind = &Value_StringValue{x}
+ return true, err
+ case 4: // kind.bool_value
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeVarint()
+ m.Kind = &Value_BoolValue{x != 0}
+ return true, err
+ case 5: // kind.struct_value
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(Struct)
+ err := b.DecodeMessage(msg)
+ m.Kind = &Value_StructValue{msg}
+ return true, err
+ case 6: // kind.list_value
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(ListValue)
+ err := b.DecodeMessage(msg)
+ m.Kind = &Value_ListValue{msg}
+ return true, err
+ default:
+ return false, nil
+ }
+}
+
+func _Value_OneofSizer(msg proto.Message) (n int) {
+ m := msg.(*Value)
+ // kind
+ switch x := m.Kind.(type) {
+ case *Value_NullValue:
+ n += proto.SizeVarint(1<<3 | proto.WireVarint)
+ n += proto.SizeVarint(uint64(x.NullValue))
+ case *Value_NumberValue:
+ n += proto.SizeVarint(2<<3 | proto.WireFixed64)
+ n += 8
+ case *Value_StringValue:
+ n += proto.SizeVarint(3<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(len(x.StringValue)))
+ n += len(x.StringValue)
+ case *Value_BoolValue:
+ n += proto.SizeVarint(4<<3 | proto.WireVarint)
+ n += 1
+ case *Value_StructValue:
+ s := proto.Size(x.StructValue)
+ n += proto.SizeVarint(5<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case *Value_ListValue:
+ s := proto.Size(x.ListValue)
+ n += proto.SizeVarint(6<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case nil:
+ default:
+ panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
+ }
+ return n
+}
+
+// `ListValue` is a wrapper around a repeated field of values.
+//
+// The JSON representation for `ListValue` is JSON array.
+type ListValue struct {
+ // Repeated field of dynamically typed values.
+ Values []*Value `protobuf:"bytes,1,rep,name=values" json:"values,omitempty"`
+}
+
+func (m *ListValue) Reset() { *m = ListValue{} }
+func (*ListValue) ProtoMessage() {}
+func (*ListValue) Descriptor() ([]byte, []int) { return fileDescriptorStruct, []int{2} }
+func (*ListValue) XXX_WellKnownType() string { return "ListValue" }
+
+func (m *ListValue) GetValues() []*Value {
+ if m != nil {
+ return m.Values
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*Struct)(nil), "google.protobuf.Struct")
+ proto.RegisterType((*Value)(nil), "google.protobuf.Value")
+ proto.RegisterType((*ListValue)(nil), "google.protobuf.ListValue")
+ proto.RegisterEnum("google.protobuf.NullValue", NullValue_name, NullValue_value)
+}
+func (x NullValue) String() string {
+ s, ok := NullValue_name[int32(x)]
+ if ok {
+ return s
+ }
+ return strconv.Itoa(int(x))
+}
+func (this *Struct) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*Struct)
+ if !ok {
+ that2, ok := that.(Struct)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if len(this.Fields) != len(that1.Fields) {
+ return false
+ }
+ for i := range this.Fields {
+ if !this.Fields[i].Equal(that1.Fields[i]) {
+ return false
+ }
+ }
+ return true
+}
+func (this *Value) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*Value)
+ if !ok {
+ that2, ok := that.(Value)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if that1.Kind == nil {
+ if this.Kind != nil {
+ return false
+ }
+ } else if this.Kind == nil {
+ return false
+ } else if !this.Kind.Equal(that1.Kind) {
+ return false
+ }
+ return true
+}
+func (this *Value_NullValue) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*Value_NullValue)
+ if !ok {
+ that2, ok := that.(Value_NullValue)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if this.NullValue != that1.NullValue {
+ return false
+ }
+ return true
+}
+func (this *Value_NumberValue) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*Value_NumberValue)
+ if !ok {
+ that2, ok := that.(Value_NumberValue)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if this.NumberValue != that1.NumberValue {
+ return false
+ }
+ return true
+}
+func (this *Value_StringValue) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*Value_StringValue)
+ if !ok {
+ that2, ok := that.(Value_StringValue)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if this.StringValue != that1.StringValue {
+ return false
+ }
+ return true
+}
+func (this *Value_BoolValue) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*Value_BoolValue)
+ if !ok {
+ that2, ok := that.(Value_BoolValue)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if this.BoolValue != that1.BoolValue {
+ return false
+ }
+ return true
+}
+func (this *Value_StructValue) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*Value_StructValue)
+ if !ok {
+ that2, ok := that.(Value_StructValue)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if !this.StructValue.Equal(that1.StructValue) {
+ return false
+ }
+ return true
+}
+func (this *Value_ListValue) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*Value_ListValue)
+ if !ok {
+ that2, ok := that.(Value_ListValue)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if !this.ListValue.Equal(that1.ListValue) {
+ return false
+ }
+ return true
+}
+func (this *ListValue) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*ListValue)
+ if !ok {
+ that2, ok := that.(ListValue)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if len(this.Values) != len(that1.Values) {
+ return false
+ }
+ for i := range this.Values {
+ if !this.Values[i].Equal(that1.Values[i]) {
+ return false
+ }
+ }
+ return true
+}
+func (this *Struct) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&types.Struct{")
+ keysForFields := make([]string, 0, len(this.Fields))
+ for k := range this.Fields {
+ keysForFields = append(keysForFields, k)
+ }
+ github_com_gogo_protobuf_sortkeys.Strings(keysForFields)
+ mapStringForFields := "map[string]*Value{"
+ for _, k := range keysForFields {
+ mapStringForFields += fmt.Sprintf("%#v: %#v,", k, this.Fields[k])
+ }
+ mapStringForFields += "}"
+ if this.Fields != nil {
+ s = append(s, "Fields: "+mapStringForFields+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *Value) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 10)
+ s = append(s, "&types.Value{")
+ if this.Kind != nil {
+ s = append(s, "Kind: "+fmt.Sprintf("%#v", this.Kind)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *Value_NullValue) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&types.Value_NullValue{` +
+ `NullValue:` + fmt.Sprintf("%#v", this.NullValue) + `}`}, ", ")
+ return s
+}
+func (this *Value_NumberValue) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&types.Value_NumberValue{` +
+ `NumberValue:` + fmt.Sprintf("%#v", this.NumberValue) + `}`}, ", ")
+ return s
+}
+func (this *Value_StringValue) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&types.Value_StringValue{` +
+ `StringValue:` + fmt.Sprintf("%#v", this.StringValue) + `}`}, ", ")
+ return s
+}
+func (this *Value_BoolValue) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&types.Value_BoolValue{` +
+ `BoolValue:` + fmt.Sprintf("%#v", this.BoolValue) + `}`}, ", ")
+ return s
+}
+func (this *Value_StructValue) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&types.Value_StructValue{` +
+ `StructValue:` + fmt.Sprintf("%#v", this.StructValue) + `}`}, ", ")
+ return s
+}
+func (this *Value_ListValue) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&types.Value_ListValue{` +
+ `ListValue:` + fmt.Sprintf("%#v", this.ListValue) + `}`}, ", ")
+ return s
+}
+func (this *ListValue) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&types.ListValue{")
+ if this.Values != nil {
+ s = append(s, "Values: "+fmt.Sprintf("%#v", this.Values)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func valueToGoStringStruct(v interface{}, typ string) string {
+ rv := reflect.ValueOf(v)
+ if rv.IsNil() {
+ return "nil"
+ }
+ pv := reflect.Indirect(rv).Interface()
+ return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
+}
+func (m *Struct) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Struct) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Fields) > 0 {
+ for k := range m.Fields {
+ dAtA[i] = 0xa
+ i++
+ v := m.Fields[k]
+ msgSize := 0
+ if v != nil {
+ msgSize = v.Size()
+ msgSize += 1 + sovStruct(uint64(msgSize))
+ }
+ mapSize := 1 + len(k) + sovStruct(uint64(len(k))) + msgSize
+ i = encodeVarintStruct(dAtA, i, uint64(mapSize))
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintStruct(dAtA, i, uint64(len(k)))
+ i += copy(dAtA[i:], k)
+ if v != nil {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintStruct(dAtA, i, uint64(v.Size()))
+ n1, err := v.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n1
+ }
+ }
+ }
+ return i, nil
+}
+
+func (m *Value) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Value) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Kind != nil {
+ nn2, err := m.Kind.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += nn2
+ }
+ return i, nil
+}
+
+func (m *Value_NullValue) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintStruct(dAtA, i, uint64(m.NullValue))
+ return i, nil
+}
+func (m *Value_NumberValue) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ dAtA[i] = 0x11
+ i++
+ i = encodeFixed64Struct(dAtA, i, uint64(math.Float64bits(float64(m.NumberValue))))
+ return i, nil
+}
+func (m *Value_StringValue) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintStruct(dAtA, i, uint64(len(m.StringValue)))
+ i += copy(dAtA[i:], m.StringValue)
+ return i, nil
+}
+func (m *Value_BoolValue) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ dAtA[i] = 0x20
+ i++
+ if m.BoolValue {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ return i, nil
+}
+func (m *Value_StructValue) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ if m.StructValue != nil {
+ dAtA[i] = 0x2a
+ i++
+ i = encodeVarintStruct(dAtA, i, uint64(m.StructValue.Size()))
+ n3, err := m.StructValue.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n3
+ }
+ return i, nil
+}
+func (m *Value_ListValue) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ if m.ListValue != nil {
+ dAtA[i] = 0x32
+ i++
+ i = encodeVarintStruct(dAtA, i, uint64(m.ListValue.Size()))
+ n4, err := m.ListValue.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n4
+ }
+ return i, nil
+}
+func (m *ListValue) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *ListValue) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Values) > 0 {
+ for _, msg := range m.Values {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintStruct(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ return i, nil
+}
+
+func encodeFixed64Struct(dAtA []byte, offset int, v uint64) int {
+ dAtA[offset] = uint8(v)
+ dAtA[offset+1] = uint8(v >> 8)
+ dAtA[offset+2] = uint8(v >> 16)
+ dAtA[offset+3] = uint8(v >> 24)
+ dAtA[offset+4] = uint8(v >> 32)
+ dAtA[offset+5] = uint8(v >> 40)
+ dAtA[offset+6] = uint8(v >> 48)
+ dAtA[offset+7] = uint8(v >> 56)
+ return offset + 8
+}
+func encodeFixed32Struct(dAtA []byte, offset int, v uint32) int {
+ dAtA[offset] = uint8(v)
+ dAtA[offset+1] = uint8(v >> 8)
+ dAtA[offset+2] = uint8(v >> 16)
+ dAtA[offset+3] = uint8(v >> 24)
+ return offset + 4
+}
+func encodeVarintStruct(dAtA []byte, offset int, v uint64) int {
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return offset + 1
+}
+func NewPopulatedStruct(r randyStruct, easy bool) *Struct {
+ this := &Struct{}
+ if r.Intn(10) == 0 {
+ v1 := r.Intn(10)
+ this.Fields = make(map[string]*Value)
+ for i := 0; i < v1; i++ {
+ this.Fields[randStringStruct(r)] = NewPopulatedValue(r, easy)
+ }
+ }
+ if !easy && r.Intn(10) != 0 {
+ }
+ return this
+}
+
+func NewPopulatedValue(r randyStruct, easy bool) *Value {
+ this := &Value{}
+ oneofNumber_Kind := []int32{1, 2, 3, 4, 5, 6}[r.Intn(6)]
+ switch oneofNumber_Kind {
+ case 1:
+ this.Kind = NewPopulatedValue_NullValue(r, easy)
+ case 2:
+ this.Kind = NewPopulatedValue_NumberValue(r, easy)
+ case 3:
+ this.Kind = NewPopulatedValue_StringValue(r, easy)
+ case 4:
+ this.Kind = NewPopulatedValue_BoolValue(r, easy)
+ case 5:
+ this.Kind = NewPopulatedValue_StructValue(r, easy)
+ case 6:
+ this.Kind = NewPopulatedValue_ListValue(r, easy)
+ }
+ if !easy && r.Intn(10) != 0 {
+ }
+ return this
+}
+
+func NewPopulatedValue_NullValue(r randyStruct, easy bool) *Value_NullValue {
+ this := &Value_NullValue{}
+ this.NullValue = NullValue([]int32{0}[r.Intn(1)])
+ return this
+}
+func NewPopulatedValue_NumberValue(r randyStruct, easy bool) *Value_NumberValue {
+ this := &Value_NumberValue{}
+ this.NumberValue = float64(r.Float64())
+ if r.Intn(2) == 0 {
+ this.NumberValue *= -1
+ }
+ return this
+}
+func NewPopulatedValue_StringValue(r randyStruct, easy bool) *Value_StringValue {
+ this := &Value_StringValue{}
+ this.StringValue = string(randStringStruct(r))
+ return this
+}
+func NewPopulatedValue_BoolValue(r randyStruct, easy bool) *Value_BoolValue {
+ this := &Value_BoolValue{}
+ this.BoolValue = bool(bool(r.Intn(2) == 0))
+ return this
+}
+func NewPopulatedValue_StructValue(r randyStruct, easy bool) *Value_StructValue {
+ this := &Value_StructValue{}
+ this.StructValue = NewPopulatedStruct(r, easy)
+ return this
+}
+func NewPopulatedValue_ListValue(r randyStruct, easy bool) *Value_ListValue {
+ this := &Value_ListValue{}
+ this.ListValue = NewPopulatedListValue(r, easy)
+ return this
+}
+func NewPopulatedListValue(r randyStruct, easy bool) *ListValue {
+ this := &ListValue{}
+ if r.Intn(10) == 0 {
+ v2 := r.Intn(5)
+ this.Values = make([]*Value, v2)
+ for i := 0; i < v2; i++ {
+ this.Values[i] = NewPopulatedValue(r, easy)
+ }
+ }
+ if !easy && r.Intn(10) != 0 {
+ }
+ return this
+}
+
+type randyStruct interface {
+ Float32() float32
+ Float64() float64
+ Int63() int64
+ Int31() int32
+ Uint32() uint32
+ Intn(n int) int
+}
+
+func randUTF8RuneStruct(r randyStruct) rune {
+ ru := r.Intn(62)
+ if ru < 10 {
+ return rune(ru + 48)
+ } else if ru < 36 {
+ return rune(ru + 55)
+ }
+ return rune(ru + 61)
+}
+func randStringStruct(r randyStruct) string {
+ v3 := r.Intn(100)
+ tmps := make([]rune, v3)
+ for i := 0; i < v3; i++ {
+ tmps[i] = randUTF8RuneStruct(r)
+ }
+ return string(tmps)
+}
+func randUnrecognizedStruct(r randyStruct, maxFieldNumber int) (dAtA []byte) {
+ l := r.Intn(5)
+ for i := 0; i < l; i++ {
+ wire := r.Intn(4)
+ if wire == 3 {
+ wire = 5
+ }
+ fieldNumber := maxFieldNumber + r.Intn(100)
+ dAtA = randFieldStruct(dAtA, r, fieldNumber, wire)
+ }
+ return dAtA
+}
+func randFieldStruct(dAtA []byte, r randyStruct, fieldNumber int, wire int) []byte {
+ key := uint32(fieldNumber)<<3 | uint32(wire)
+ switch wire {
+ case 0:
+ dAtA = encodeVarintPopulateStruct(dAtA, uint64(key))
+ v4 := r.Int63()
+ if r.Intn(2) == 0 {
+ v4 *= -1
+ }
+ dAtA = encodeVarintPopulateStruct(dAtA, uint64(v4))
+ case 1:
+ dAtA = encodeVarintPopulateStruct(dAtA, uint64(key))
+ dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))
+ case 2:
+ dAtA = encodeVarintPopulateStruct(dAtA, uint64(key))
+ ll := r.Intn(100)
+ dAtA = encodeVarintPopulateStruct(dAtA, uint64(ll))
+ for j := 0; j < ll; j++ {
+ dAtA = append(dAtA, byte(r.Intn(256)))
+ }
+ default:
+ dAtA = encodeVarintPopulateStruct(dAtA, uint64(key))
+ dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))
+ }
+ return dAtA
+}
+func encodeVarintPopulateStruct(dAtA []byte, v uint64) []byte {
+ for v >= 1<<7 {
+ dAtA = append(dAtA, uint8(uint64(v)&0x7f|0x80))
+ v >>= 7
+ }
+ dAtA = append(dAtA, uint8(v))
+ return dAtA
+}
+func (m *Struct) Size() (n int) {
+ var l int
+ _ = l
+ if len(m.Fields) > 0 {
+ for k, v := range m.Fields {
+ _ = k
+ _ = v
+ l = 0
+ if v != nil {
+ l = v.Size()
+ l += 1 + sovStruct(uint64(l))
+ }
+ mapEntrySize := 1 + len(k) + sovStruct(uint64(len(k))) + l
+ n += mapEntrySize + 1 + sovStruct(uint64(mapEntrySize))
+ }
+ }
+ return n
+}
+
+func (m *Value) Size() (n int) {
+ var l int
+ _ = l
+ if m.Kind != nil {
+ n += m.Kind.Size()
+ }
+ return n
+}
+
+func (m *Value_NullValue) Size() (n int) {
+ var l int
+ _ = l
+ n += 1 + sovStruct(uint64(m.NullValue))
+ return n
+}
+func (m *Value_NumberValue) Size() (n int) {
+ var l int
+ _ = l
+ n += 9
+ return n
+}
+func (m *Value_StringValue) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.StringValue)
+ n += 1 + l + sovStruct(uint64(l))
+ return n
+}
+func (m *Value_BoolValue) Size() (n int) {
+ var l int
+ _ = l
+ n += 2
+ return n
+}
+func (m *Value_StructValue) Size() (n int) {
+ var l int
+ _ = l
+ if m.StructValue != nil {
+ l = m.StructValue.Size()
+ n += 1 + l + sovStruct(uint64(l))
+ }
+ return n
+}
+func (m *Value_ListValue) Size() (n int) {
+ var l int
+ _ = l
+ if m.ListValue != nil {
+ l = m.ListValue.Size()
+ n += 1 + l + sovStruct(uint64(l))
+ }
+ return n
+}
+func (m *ListValue) Size() (n int) {
+ var l int
+ _ = l
+ if len(m.Values) > 0 {
+ for _, e := range m.Values {
+ l = e.Size()
+ n += 1 + l + sovStruct(uint64(l))
+ }
+ }
+ return n
+}
+
+func sovStruct(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+func sozStruct(x uint64) (n int) {
+ return sovStruct(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (this *Struct) String() string {
+ if this == nil {
+ return "nil"
+ }
+ keysForFields := make([]string, 0, len(this.Fields))
+ for k := range this.Fields {
+ keysForFields = append(keysForFields, k)
+ }
+ github_com_gogo_protobuf_sortkeys.Strings(keysForFields)
+ mapStringForFields := "map[string]*Value{"
+ for _, k := range keysForFields {
+ mapStringForFields += fmt.Sprintf("%v: %v,", k, this.Fields[k])
+ }
+ mapStringForFields += "}"
+ s := strings.Join([]string{`&Struct{`,
+ `Fields:` + mapStringForFields + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func (this *Value) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&Value{`,
+ `Kind:` + fmt.Sprintf("%v", this.Kind) + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func (this *Value_NullValue) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&Value_NullValue{`,
+ `NullValue:` + fmt.Sprintf("%v", this.NullValue) + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func (this *Value_NumberValue) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&Value_NumberValue{`,
+ `NumberValue:` + fmt.Sprintf("%v", this.NumberValue) + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func (this *Value_StringValue) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&Value_StringValue{`,
+ `StringValue:` + fmt.Sprintf("%v", this.StringValue) + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func (this *Value_BoolValue) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&Value_BoolValue{`,
+ `BoolValue:` + fmt.Sprintf("%v", this.BoolValue) + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func (this *Value_StructValue) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&Value_StructValue{`,
+ `StructValue:` + strings.Replace(fmt.Sprintf("%v", this.StructValue), "Struct", "Struct", 1) + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func (this *Value_ListValue) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&Value_ListValue{`,
+ `ListValue:` + strings.Replace(fmt.Sprintf("%v", this.ListValue), "ListValue", "ListValue", 1) + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func (this *ListValue) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&ListValue{`,
+ `Values:` + strings.Replace(fmt.Sprintf("%v", this.Values), "Value", "Value", 1) + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func valueToStringStruct(v interface{}) string {
+ rv := reflect.ValueOf(v)
+ if rv.IsNil() {
+ return "nil"
+ }
+ pv := reflect.Indirect(rv).Interface()
+ return fmt.Sprintf("*%v", pv)
+}
+func (m *Struct) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowStruct
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Struct: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Struct: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Fields", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowStruct
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthStruct
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var keykey uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowStruct
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ keykey |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ var stringLenmapkey uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowStruct
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLenmapkey |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLenmapkey := int(stringLenmapkey)
+ if intStringLenmapkey < 0 {
+ return ErrInvalidLengthStruct
+ }
+ postStringIndexmapkey := iNdEx + intStringLenmapkey
+ if postStringIndexmapkey > l {
+ return io.ErrUnexpectedEOF
+ }
+ mapkey := string(dAtA[iNdEx:postStringIndexmapkey])
+ iNdEx = postStringIndexmapkey
+ if m.Fields == nil {
+ m.Fields = make(map[string]*Value)
+ }
+ if iNdEx < postIndex {
+ var valuekey uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowStruct
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ valuekey |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ var mapmsglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowStruct
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ mapmsglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if mapmsglen < 0 {
+ return ErrInvalidLengthStruct
+ }
+ postmsgIndex := iNdEx + mapmsglen
+ if mapmsglen < 0 {
+ return ErrInvalidLengthStruct
+ }
+ if postmsgIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ mapvalue := &Value{}
+ if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil {
+ return err
+ }
+ iNdEx = postmsgIndex
+ m.Fields[mapkey] = mapvalue
+ } else {
+ var mapvalue *Value
+ m.Fields[mapkey] = mapvalue
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipStruct(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthStruct
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *Value) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowStruct
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Value: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Value: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field NullValue", wireType)
+ }
+ var v NullValue
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowStruct
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (NullValue(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Kind = &Value_NullValue{v}
+ case 2:
+ if wireType != 1 {
+ return fmt.Errorf("proto: wrong wireType = %d for field NumberValue", wireType)
+ }
+ var v uint64
+ if (iNdEx + 8) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += 8
+ v = uint64(dAtA[iNdEx-8])
+ v |= uint64(dAtA[iNdEx-7]) << 8
+ v |= uint64(dAtA[iNdEx-6]) << 16
+ v |= uint64(dAtA[iNdEx-5]) << 24
+ v |= uint64(dAtA[iNdEx-4]) << 32
+ v |= uint64(dAtA[iNdEx-3]) << 40
+ v |= uint64(dAtA[iNdEx-2]) << 48
+ v |= uint64(dAtA[iNdEx-1]) << 56
+ m.Kind = &Value_NumberValue{float64(math.Float64frombits(v))}
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field StringValue", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowStruct
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthStruct
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Kind = &Value_StringValue{string(dAtA[iNdEx:postIndex])}
+ iNdEx = postIndex
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field BoolValue", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowStruct
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ b := bool(v != 0)
+ m.Kind = &Value_BoolValue{b}
+ case 5:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field StructValue", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowStruct
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthStruct
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ v := &Struct{}
+ if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ m.Kind = &Value_StructValue{v}
+ iNdEx = postIndex
+ case 6:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ListValue", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowStruct
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthStruct
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ v := &ListValue{}
+ if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ m.Kind = &Value_ListValue{v}
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipStruct(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthStruct
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *ListValue) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowStruct
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: ListValue: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: ListValue: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Values", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowStruct
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthStruct
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Values = append(m.Values, &Value{})
+ if err := m.Values[len(m.Values)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipStruct(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthStruct
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipStruct(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowStruct
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowStruct
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ return iNdEx, nil
+ case 1:
+ iNdEx += 8
+ return iNdEx, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowStruct
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ iNdEx += length
+ if length < 0 {
+ return 0, ErrInvalidLengthStruct
+ }
+ return iNdEx, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = iNdEx
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowStruct
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := skipStruct(dAtA[start:])
+ if err != nil {
+ return 0, err
+ }
+ iNdEx = start + next
+ }
+ return iNdEx, nil
+ case 4:
+ return iNdEx, nil
+ case 5:
+ iNdEx += 4
+ return iNdEx, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
+
+var (
+ ErrInvalidLengthStruct = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowStruct = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("struct.proto", fileDescriptorStruct) }
+
+var fileDescriptorStruct = []byte{
+ // 432 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0xb1, 0x6f, 0xd3, 0x40,
+ 0x14, 0xc6, 0xfd, 0x9c, 0xc6, 0x22, 0xcf, 0x55, 0xa9, 0x0e, 0x09, 0xa2, 0x22, 0x1d, 0x51, 0xba,
+ 0x58, 0x08, 0x79, 0x08, 0x0b, 0x22, 0x2c, 0x58, 0x2a, 0xad, 0x84, 0x55, 0x19, 0x43, 0x8b, 0xc4,
+ 0x12, 0xe1, 0xd4, 0x8d, 0xac, 0x5e, 0xef, 0x2a, 0xfb, 0x0c, 0xca, 0x06, 0xff, 0x05, 0x33, 0x13,
+ 0x62, 0xe4, 0xaf, 0x60, 0xec, 0xc8, 0x88, 0x3d, 0x31, 0x76, 0xec, 0x88, 0xee, 0xce, 0x36, 0xa8,
+ 0x51, 0x36, 0xbf, 0xcf, 0xbf, 0xf7, 0xbd, 0xf7, 0xbd, 0xc3, 0xcd, 0x42, 0xe6, 0xe5, 0x5c, 0xfa,
+ 0x17, 0xb9, 0x90, 0x82, 0xdc, 0x5e, 0x08, 0xb1, 0x60, 0xa9, 0xa9, 0x92, 0xf2, 0x74, 0xfc, 0x05,
+ 0xd0, 0x79, 0xad, 0x09, 0x32, 0x45, 0xe7, 0x34, 0x4b, 0xd9, 0x49, 0x31, 0x84, 0x51, 0xcf, 0x73,
+ 0x27, 0xbb, 0xfe, 0x0d, 0xd8, 0x37, 0xa0, 0xff, 0x42, 0x53, 0x7b, 0x5c, 0xe6, 0xcb, 0xb8, 0x69,
+ 0xd9, 0x79, 0x85, 0xee, 0x7f, 0x32, 0xd9, 0xc6, 0xde, 0x59, 0xba, 0x1c, 0xc2, 0x08, 0xbc, 0x41,
+ 0xac, 0x3e, 0xc9, 0x23, 0xec, 0x7f, 0x78, 0xcf, 0xca, 0x74, 0x68, 0x8f, 0xc0, 0x73, 0x27, 0x77,
+ 0x57, 0xcc, 0x8f, 0xd5, 0xdf, 0xd8, 0x40, 0x4f, 0xed, 0x27, 0x30, 0xfe, 0x61, 0x63, 0x5f, 0x8b,
+ 0x64, 0x8a, 0xc8, 0x4b, 0xc6, 0x66, 0xc6, 0x40, 0x99, 0x6e, 0x4d, 0x76, 0x56, 0x0c, 0x0e, 0x4b,
+ 0xc6, 0x34, 0x7f, 0x60, 0xc5, 0x03, 0xde, 0x16, 0x64, 0x17, 0x37, 0x79, 0x79, 0x9e, 0xa4, 0xf9,
+ 0xec, 0xdf, 0x7c, 0x38, 0xb0, 0x62, 0xd7, 0xa8, 0x1d, 0x54, 0xc8, 0x3c, 0xe3, 0x8b, 0x06, 0xea,
+ 0xa9, 0xc5, 0x15, 0x64, 0x54, 0x03, 0x3d, 0x40, 0x4c, 0x84, 0x68, 0xd7, 0xd8, 0x18, 0x81, 0x77,
+ 0x4b, 0x8d, 0x52, 0x9a, 0x01, 0x9e, 0xb5, 0xd7, 0x6e, 0x90, 0xbe, 0x8e, 0x7a, 0x6f, 0xcd, 0x1d,
+ 0x1b, 0xfb, 0x72, 0x2e, 0xbb, 0x94, 0x2c, 0x2b, 0xda, 0x5e, 0x47, 0xf7, 0xae, 0xa6, 0x0c, 0xb3,
+ 0x42, 0x76, 0x29, 0x59, 0x5b, 0x04, 0x0e, 0x6e, 0x9c, 0x65, 0xfc, 0x64, 0x3c, 0xc5, 0x41, 0x47,
+ 0x10, 0x1f, 0x1d, 0x6d, 0xd6, 0xbe, 0xe8, 0xba, 0xa3, 0x37, 0xd4, 0xc3, 0xfb, 0x38, 0xe8, 0x8e,
+ 0x48, 0xb6, 0x10, 0x0f, 0x8f, 0xc2, 0x70, 0x76, 0xfc, 0x3c, 0x3c, 0xda, 0xdb, 0xb6, 0x82, 0xcf,
+ 0x70, 0x59, 0x51, 0xeb, 0x57, 0x45, 0xad, 0xab, 0x8a, 0xc2, 0x75, 0x45, 0xe1, 0x53, 0x4d, 0xe1,
+ 0x5b, 0x4d, 0xe1, 0x67, 0x4d, 0xe1, 0xb2, 0xa6, 0xf0, 0xbb, 0xa6, 0xf0, 0xa7, 0xa6, 0xd6, 0x55,
+ 0x4d, 0x01, 0xef, 0xcc, 0xc5, 0xf9, 0xcd, 0x71, 0x81, 0x6b, 0x92, 0x47, 0xaa, 0x8e, 0xe0, 0x5d,
+ 0x5f, 0x2e, 0x2f, 0xd2, 0xe2, 0x1a, 0xe0, 0xab, 0xdd, 0xdb, 0x8f, 0x82, 0xef, 0x36, 0xdd, 0x37,
+ 0x0d, 0x51, 0xbb, 0xdf, 0xdb, 0x94, 0xb1, 0x97, 0x5c, 0x7c, 0xe4, 0x6f, 0x14, 0x99, 0x38, 0xda,
+ 0xe9, 0xf1, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x75, 0xc5, 0x1c, 0x3b, 0xd5, 0x02, 0x00, 0x00,
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package types
+
+// This file implements operations on google.protobuf.Timestamp.
+
+import (
+ "errors"
+ "fmt"
+ "time"
+)
+
+const (
+ // Seconds field of the earliest valid Timestamp.
+ // This is time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC).Unix().
+ minValidSeconds = -62135596800
+ // Seconds field just after the latest valid Timestamp.
+ // This is time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Unix().
+ maxValidSeconds = 253402300800
+)
+
+// validateTimestamp determines whether a Timestamp is valid.
+// A valid timestamp represents a time in the range
+// [0001-01-01, 10000-01-01) and has a Nanos field
+// in the range [0, 1e9).
+//
+// If the Timestamp is valid, validateTimestamp returns nil.
+// Otherwise, it returns an error that describes
+// the problem.
+//
+// Every valid Timestamp can be represented by a time.Time, but the converse is not true.
+func validateTimestamp(ts *Timestamp) error {
+ if ts == nil {
+ return errors.New("timestamp: nil Timestamp")
+ }
+ if ts.Seconds < minValidSeconds {
+ return fmt.Errorf("timestamp: %#v before 0001-01-01", ts)
+ }
+ if ts.Seconds >= maxValidSeconds {
+ return fmt.Errorf("timestamp: %#v after 10000-01-01", ts)
+ }
+ if ts.Nanos < 0 || ts.Nanos >= 1e9 {
+ return fmt.Errorf("timestamp: %#v: nanos not in range [0, 1e9)", ts)
+ }
+ return nil
+}
+
+// TimestampFromProto converts a google.protobuf.Timestamp proto to a time.Time.
+// It returns an error if the argument is invalid.
+//
+// Unlike most Go functions, if Timestamp returns an error, the first return value
+// is not the zero time.Time. Instead, it is the value obtained from the
+// time.Unix function when passed the contents of the Timestamp, in the UTC
+// locale. This may or may not be a meaningful time; many invalid Timestamps
+// do map to valid time.Times.
+//
+// A nil Timestamp returns an error. The first return value in that case is
+// undefined.
+func TimestampFromProto(ts *Timestamp) (time.Time, error) {
+ // Don't return the zero value on error, because corresponds to a valid
+ // timestamp. Instead return whatever time.Unix gives us.
+ var t time.Time
+ if ts == nil {
+ t = time.Unix(0, 0).UTC() // treat nil like the empty Timestamp
+ } else {
+ t = time.Unix(ts.Seconds, int64(ts.Nanos)).UTC()
+ }
+ return t, validateTimestamp(ts)
+}
+
+// TimestampProto converts the time.Time to a google.protobuf.Timestamp proto.
+// It returns an error if the resulting Timestamp is invalid.
+func TimestampProto(t time.Time) (*Timestamp, error) {
+ seconds := t.Unix()
+ nanos := int32(t.Sub(time.Unix(seconds, 0)))
+ ts := &Timestamp{
+ Seconds: seconds,
+ Nanos: nanos,
+ }
+ if err := validateTimestamp(ts); err != nil {
+ return nil, err
+ }
+ return ts, nil
+}
+
+// TimestampString returns the RFC 3339 string for valid Timestamps. For invalid
+// Timestamps, it returns an error message in parentheses.
+func TimestampString(ts *Timestamp) string {
+ t, err := TimestampFromProto(ts)
+ if err != nil {
+ return fmt.Sprintf("(%v)", err)
+ }
+ return t.Format(time.RFC3339Nano)
+}
--- /dev/null
+// Code generated by protoc-gen-gogo.
+// source: timestamp.proto
+// DO NOT EDIT!
+
+/*
+ Package types is a generated protocol buffer package.
+
+ It is generated from these files:
+ timestamp.proto
+
+ It has these top-level messages:
+ Timestamp
+*/
+package types
+
+import proto "github.com/gogo/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+import strings "strings"
+import reflect "reflect"
+
+import io "io"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
+
+// A Timestamp represents a point in time independent of any time zone
+// or calendar, represented as seconds and fractions of seconds at
+// nanosecond resolution in UTC Epoch time. It is encoded using the
+// Proleptic Gregorian Calendar which extends the Gregorian calendar
+// backwards to year one. It is encoded assuming all minutes are 60
+// seconds long, i.e. leap seconds are "smeared" so that no leap second
+// table is needed for interpretation. Range is from
+// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
+// By restricting to that range, we ensure that we can convert to
+// and from RFC 3339 date strings.
+// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
+//
+// Example 1: Compute Timestamp from POSIX `time()`.
+//
+// Timestamp timestamp;
+// timestamp.set_seconds(time(NULL));
+// timestamp.set_nanos(0);
+//
+// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
+//
+// struct timeval tv;
+// gettimeofday(&tv, NULL);
+//
+// Timestamp timestamp;
+// timestamp.set_seconds(tv.tv_sec);
+// timestamp.set_nanos(tv.tv_usec * 1000);
+//
+// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
+//
+// FILETIME ft;
+// GetSystemTimeAsFileTime(&ft);
+// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+//
+// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
+// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
+// Timestamp timestamp;
+// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
+// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
+//
+// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
+//
+// long millis = System.currentTimeMillis();
+//
+// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
+// .setNanos((int) ((millis % 1000) * 1000000)).build();
+//
+//
+// Example 5: Compute Timestamp from current time in Python.
+//
+// timestamp = Timestamp()
+// timestamp.GetCurrentTime()
+//
+//
+type Timestamp struct {
+ // Represents seconds of UTC time since Unix epoch
+ // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
+ // 9999-12-31T23:59:59Z inclusive.
+ Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
+ // Non-negative fractions of a second at nanosecond resolution. Negative
+ // second values with fractions must still have non-negative nanos values
+ // that count forward in time. Must be from 0 to 999,999,999
+ // inclusive.
+ Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
+}
+
+func (m *Timestamp) Reset() { *m = Timestamp{} }
+func (*Timestamp) ProtoMessage() {}
+func (*Timestamp) Descriptor() ([]byte, []int) { return fileDescriptorTimestamp, []int{0} }
+func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" }
+
+func (m *Timestamp) GetSeconds() int64 {
+ if m != nil {
+ return m.Seconds
+ }
+ return 0
+}
+
+func (m *Timestamp) GetNanos() int32 {
+ if m != nil {
+ return m.Nanos
+ }
+ return 0
+}
+
+func init() {
+ proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp")
+}
+func (this *Timestamp) Compare(that interface{}) int {
+ if that == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ }
+
+ that1, ok := that.(*Timestamp)
+ if !ok {
+ that2, ok := that.(Timestamp)
+ if ok {
+ that1 = &that2
+ } else {
+ return 1
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ } else if this == nil {
+ return -1
+ }
+ if this.Seconds != that1.Seconds {
+ if this.Seconds < that1.Seconds {
+ return -1
+ }
+ return 1
+ }
+ if this.Nanos != that1.Nanos {
+ if this.Nanos < that1.Nanos {
+ return -1
+ }
+ return 1
+ }
+ return 0
+}
+func (this *Timestamp) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*Timestamp)
+ if !ok {
+ that2, ok := that.(Timestamp)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if this.Seconds != that1.Seconds {
+ return false
+ }
+ if this.Nanos != that1.Nanos {
+ return false
+ }
+ return true
+}
+func (this *Timestamp) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 6)
+ s = append(s, "&types.Timestamp{")
+ s = append(s, "Seconds: "+fmt.Sprintf("%#v", this.Seconds)+",\n")
+ s = append(s, "Nanos: "+fmt.Sprintf("%#v", this.Nanos)+",\n")
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func valueToGoStringTimestamp(v interface{}, typ string) string {
+ rv := reflect.ValueOf(v)
+ if rv.IsNil() {
+ return "nil"
+ }
+ pv := reflect.Indirect(rv).Interface()
+ return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
+}
+func (m *Timestamp) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Timestamp) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Seconds != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintTimestamp(dAtA, i, uint64(m.Seconds))
+ }
+ if m.Nanos != 0 {
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintTimestamp(dAtA, i, uint64(m.Nanos))
+ }
+ return i, nil
+}
+
+func encodeFixed64Timestamp(dAtA []byte, offset int, v uint64) int {
+ dAtA[offset] = uint8(v)
+ dAtA[offset+1] = uint8(v >> 8)
+ dAtA[offset+2] = uint8(v >> 16)
+ dAtA[offset+3] = uint8(v >> 24)
+ dAtA[offset+4] = uint8(v >> 32)
+ dAtA[offset+5] = uint8(v >> 40)
+ dAtA[offset+6] = uint8(v >> 48)
+ dAtA[offset+7] = uint8(v >> 56)
+ return offset + 8
+}
+func encodeFixed32Timestamp(dAtA []byte, offset int, v uint32) int {
+ dAtA[offset] = uint8(v)
+ dAtA[offset+1] = uint8(v >> 8)
+ dAtA[offset+2] = uint8(v >> 16)
+ dAtA[offset+3] = uint8(v >> 24)
+ return offset + 4
+}
+func encodeVarintTimestamp(dAtA []byte, offset int, v uint64) int {
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return offset + 1
+}
+func (m *Timestamp) Size() (n int) {
+ var l int
+ _ = l
+ if m.Seconds != 0 {
+ n += 1 + sovTimestamp(uint64(m.Seconds))
+ }
+ if m.Nanos != 0 {
+ n += 1 + sovTimestamp(uint64(m.Nanos))
+ }
+ return n
+}
+
+func sovTimestamp(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+func sozTimestamp(x uint64) (n int) {
+ return sovTimestamp(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Timestamp) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTimestamp
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Timestamp: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Timestamp: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Seconds", wireType)
+ }
+ m.Seconds = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTimestamp
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Seconds |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Nanos", wireType)
+ }
+ m.Nanos = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTimestamp
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Nanos |= (int32(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipTimestamp(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthTimestamp
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipTimestamp(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowTimestamp
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowTimestamp
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ return iNdEx, nil
+ case 1:
+ iNdEx += 8
+ return iNdEx, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowTimestamp
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ iNdEx += length
+ if length < 0 {
+ return 0, ErrInvalidLengthTimestamp
+ }
+ return iNdEx, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = iNdEx
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowTimestamp
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := skipTimestamp(dAtA[start:])
+ if err != nil {
+ return 0, err
+ }
+ iNdEx = start + next
+ }
+ return iNdEx, nil
+ case 4:
+ return iNdEx, nil
+ case 5:
+ iNdEx += 4
+ return iNdEx, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
+
+var (
+ ErrInvalidLengthTimestamp = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowTimestamp = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("timestamp.proto", fileDescriptorTimestamp) }
+
+var fileDescriptorTimestamp = []byte{
+ // 205 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2f, 0xc9, 0xcc, 0x4d,
+ 0x2d, 0x2e, 0x49, 0xcc, 0x2d, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x4f, 0xcf, 0xcf,
+ 0x4f, 0xcf, 0x49, 0x85, 0xf0, 0x92, 0x4a, 0xd3, 0x94, 0xac, 0xb9, 0x38, 0x43, 0x60, 0x6a, 0x84,
+ 0x24, 0xb8, 0xd8, 0x8b, 0x53, 0x93, 0xf3, 0xf3, 0x52, 0x8a, 0x25, 0x18, 0x15, 0x18, 0x35, 0x98,
+ 0x83, 0x60, 0x5c, 0x21, 0x11, 0x2e, 0xd6, 0xbc, 0xc4, 0xbc, 0xfc, 0x62, 0x09, 0x26, 0x05, 0x46,
+ 0x0d, 0xd6, 0x20, 0x08, 0xc7, 0xa9, 0x81, 0xf1, 0xc2, 0x43, 0x39, 0x86, 0x1b, 0x0f, 0xe5, 0x18,
+ 0x3e, 0x3c, 0x94, 0x63, 0x5c, 0xf1, 0x48, 0x8e, 0xf1, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4,
+ 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x7c, 0xf1, 0x48, 0x8e, 0xe1, 0xc3, 0x23, 0x39, 0xc6, 0x15, 0x8f,
+ 0xe5, 0x18, 0xb9, 0x84, 0x93, 0xf3, 0x73, 0xf5, 0xd0, 0x2c, 0x77, 0xe2, 0x83, 0x5b, 0x1d, 0x00,
+ 0x12, 0x0a, 0x60, 0x8c, 0x62, 0x2d, 0xa9, 0x2c, 0x48, 0x2d, 0xfe, 0xc1, 0xc8, 0xb8, 0x88, 0x89,
+ 0xd9, 0x3d, 0xc0, 0x69, 0x15, 0x93, 0x9c, 0x3b, 0x44, 0x4f, 0x00, 0x54, 0x8f, 0x5e, 0x78, 0x6a,
+ 0x4e, 0x8e, 0x77, 0x5e, 0x7e, 0x79, 0x5e, 0x08, 0x48, 0x65, 0x12, 0x1b, 0xd8, 0x30, 0x63, 0x40,
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0x9b, 0xa2, 0x42, 0xda, 0xea, 0x00, 0x00, 0x00,
+}
--- /dev/null
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2016, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package types
+
+import (
+ "time"
+)
+
+func NewPopulatedTimestamp(r interface {
+ Int63() int64
+}, easy bool) *Timestamp {
+ this := &Timestamp{}
+ ns := int64(r.Int63())
+ this.Seconds = ns / 1e9
+ this.Nanos = int32(ns % 1e9)
+ return this
+}
+
+func (ts *Timestamp) String() string {
+ return TimestampString(ts)
+}
+
+func NewPopulatedStdTime(r interface {
+ Int63() int64
+}, easy bool) *time.Time {
+ timestamp := NewPopulatedTimestamp(r, easy)
+ t, err := TimestampFromProto(timestamp)
+ if err != nil {
+ return nil
+ }
+ return &t
+}
+
+func SizeOfStdTime(t time.Time) int {
+ ts, err := TimestampProto(t)
+ if err != nil {
+ return 0
+ }
+ return ts.Size()
+}
+
+func StdTimeMarshal(t time.Time) ([]byte, error) {
+ size := SizeOfStdTime(t)
+ buf := make([]byte, size)
+ _, err := StdTimeMarshalTo(t, buf)
+ return buf, err
+}
+
+func StdTimeMarshalTo(t time.Time, data []byte) (int, error) {
+ ts, err := TimestampProto(t)
+ if err != nil {
+ return 0, err
+ }
+ return ts.MarshalTo(data)
+}
+
+func StdTimeUnmarshal(t *time.Time, data []byte) error {
+ ts := &Timestamp{}
+ if err := ts.Unmarshal(data); err != nil {
+ return err
+ }
+ tt, err := TimestampFromProto(ts)
+ if err != nil {
+ return err
+ }
+ *t = tt
+ return nil
+}
--- /dev/null
+// Code generated by protoc-gen-gogo.
+// source: wrappers.proto
+// DO NOT EDIT!
+
+/*
+Package types is a generated protocol buffer package.
+
+It is generated from these files:
+ wrappers.proto
+
+It has these top-level messages:
+ DoubleValue
+ FloatValue
+ Int64Value
+ UInt64Value
+ Int32Value
+ UInt32Value
+ BoolValue
+ StringValue
+ BytesValue
+*/
+package types
+
+import proto "github.com/gogo/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+import bytes "bytes"
+
+import strings "strings"
+import reflect "reflect"
+
+import io "io"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
+
+// Wrapper message for `double`.
+//
+// The JSON representation for `DoubleValue` is JSON number.
+type DoubleValue struct {
+ // The double value.
+ Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (m *DoubleValue) Reset() { *m = DoubleValue{} }
+func (*DoubleValue) ProtoMessage() {}
+func (*DoubleValue) Descriptor() ([]byte, []int) { return fileDescriptorWrappers, []int{0} }
+func (*DoubleValue) XXX_WellKnownType() string { return "DoubleValue" }
+
+func (m *DoubleValue) GetValue() float64 {
+ if m != nil {
+ return m.Value
+ }
+ return 0
+}
+
+// Wrapper message for `float`.
+//
+// The JSON representation for `FloatValue` is JSON number.
+type FloatValue struct {
+ // The float value.
+ Value float32 `protobuf:"fixed32,1,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (m *FloatValue) Reset() { *m = FloatValue{} }
+func (*FloatValue) ProtoMessage() {}
+func (*FloatValue) Descriptor() ([]byte, []int) { return fileDescriptorWrappers, []int{1} }
+func (*FloatValue) XXX_WellKnownType() string { return "FloatValue" }
+
+func (m *FloatValue) GetValue() float32 {
+ if m != nil {
+ return m.Value
+ }
+ return 0
+}
+
+// Wrapper message for `int64`.
+//
+// The JSON representation for `Int64Value` is JSON string.
+type Int64Value struct {
+ // The int64 value.
+ Value int64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (m *Int64Value) Reset() { *m = Int64Value{} }
+func (*Int64Value) ProtoMessage() {}
+func (*Int64Value) Descriptor() ([]byte, []int) { return fileDescriptorWrappers, []int{2} }
+func (*Int64Value) XXX_WellKnownType() string { return "Int64Value" }
+
+func (m *Int64Value) GetValue() int64 {
+ if m != nil {
+ return m.Value
+ }
+ return 0
+}
+
+// Wrapper message for `uint64`.
+//
+// The JSON representation for `UInt64Value` is JSON string.
+type UInt64Value struct {
+ // The uint64 value.
+ Value uint64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (m *UInt64Value) Reset() { *m = UInt64Value{} }
+func (*UInt64Value) ProtoMessage() {}
+func (*UInt64Value) Descriptor() ([]byte, []int) { return fileDescriptorWrappers, []int{3} }
+func (*UInt64Value) XXX_WellKnownType() string { return "UInt64Value" }
+
+func (m *UInt64Value) GetValue() uint64 {
+ if m != nil {
+ return m.Value
+ }
+ return 0
+}
+
+// Wrapper message for `int32`.
+//
+// The JSON representation for `Int32Value` is JSON number.
+type Int32Value struct {
+ // The int32 value.
+ Value int32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (m *Int32Value) Reset() { *m = Int32Value{} }
+func (*Int32Value) ProtoMessage() {}
+func (*Int32Value) Descriptor() ([]byte, []int) { return fileDescriptorWrappers, []int{4} }
+func (*Int32Value) XXX_WellKnownType() string { return "Int32Value" }
+
+func (m *Int32Value) GetValue() int32 {
+ if m != nil {
+ return m.Value
+ }
+ return 0
+}
+
+// Wrapper message for `uint32`.
+//
+// The JSON representation for `UInt32Value` is JSON number.
+type UInt32Value struct {
+ // The uint32 value.
+ Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (m *UInt32Value) Reset() { *m = UInt32Value{} }
+func (*UInt32Value) ProtoMessage() {}
+func (*UInt32Value) Descriptor() ([]byte, []int) { return fileDescriptorWrappers, []int{5} }
+func (*UInt32Value) XXX_WellKnownType() string { return "UInt32Value" }
+
+func (m *UInt32Value) GetValue() uint32 {
+ if m != nil {
+ return m.Value
+ }
+ return 0
+}
+
+// Wrapper message for `bool`.
+//
+// The JSON representation for `BoolValue` is JSON `true` and `false`.
+type BoolValue struct {
+ // The bool value.
+ Value bool `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (m *BoolValue) Reset() { *m = BoolValue{} }
+func (*BoolValue) ProtoMessage() {}
+func (*BoolValue) Descriptor() ([]byte, []int) { return fileDescriptorWrappers, []int{6} }
+func (*BoolValue) XXX_WellKnownType() string { return "BoolValue" }
+
+func (m *BoolValue) GetValue() bool {
+ if m != nil {
+ return m.Value
+ }
+ return false
+}
+
+// Wrapper message for `string`.
+//
+// The JSON representation for `StringValue` is JSON string.
+type StringValue struct {
+ // The string value.
+ Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (m *StringValue) Reset() { *m = StringValue{} }
+func (*StringValue) ProtoMessage() {}
+func (*StringValue) Descriptor() ([]byte, []int) { return fileDescriptorWrappers, []int{7} }
+func (*StringValue) XXX_WellKnownType() string { return "StringValue" }
+
+func (m *StringValue) GetValue() string {
+ if m != nil {
+ return m.Value
+ }
+ return ""
+}
+
+// Wrapper message for `bytes`.
+//
+// The JSON representation for `BytesValue` is JSON string.
+type BytesValue struct {
+ // The bytes value.
+ Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (m *BytesValue) Reset() { *m = BytesValue{} }
+func (*BytesValue) ProtoMessage() {}
+func (*BytesValue) Descriptor() ([]byte, []int) { return fileDescriptorWrappers, []int{8} }
+func (*BytesValue) XXX_WellKnownType() string { return "BytesValue" }
+
+func (m *BytesValue) GetValue() []byte {
+ if m != nil {
+ return m.Value
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*DoubleValue)(nil), "google.protobuf.DoubleValue")
+ proto.RegisterType((*FloatValue)(nil), "google.protobuf.FloatValue")
+ proto.RegisterType((*Int64Value)(nil), "google.protobuf.Int64Value")
+ proto.RegisterType((*UInt64Value)(nil), "google.protobuf.UInt64Value")
+ proto.RegisterType((*Int32Value)(nil), "google.protobuf.Int32Value")
+ proto.RegisterType((*UInt32Value)(nil), "google.protobuf.UInt32Value")
+ proto.RegisterType((*BoolValue)(nil), "google.protobuf.BoolValue")
+ proto.RegisterType((*StringValue)(nil), "google.protobuf.StringValue")
+ proto.RegisterType((*BytesValue)(nil), "google.protobuf.BytesValue")
+}
+func (this *DoubleValue) Compare(that interface{}) int {
+ if that == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ }
+
+ that1, ok := that.(*DoubleValue)
+ if !ok {
+ that2, ok := that.(DoubleValue)
+ if ok {
+ that1 = &that2
+ } else {
+ return 1
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ } else if this == nil {
+ return -1
+ }
+ if this.Value != that1.Value {
+ if this.Value < that1.Value {
+ return -1
+ }
+ return 1
+ }
+ return 0
+}
+func (this *FloatValue) Compare(that interface{}) int {
+ if that == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ }
+
+ that1, ok := that.(*FloatValue)
+ if !ok {
+ that2, ok := that.(FloatValue)
+ if ok {
+ that1 = &that2
+ } else {
+ return 1
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ } else if this == nil {
+ return -1
+ }
+ if this.Value != that1.Value {
+ if this.Value < that1.Value {
+ return -1
+ }
+ return 1
+ }
+ return 0
+}
+func (this *Int64Value) Compare(that interface{}) int {
+ if that == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ }
+
+ that1, ok := that.(*Int64Value)
+ if !ok {
+ that2, ok := that.(Int64Value)
+ if ok {
+ that1 = &that2
+ } else {
+ return 1
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ } else if this == nil {
+ return -1
+ }
+ if this.Value != that1.Value {
+ if this.Value < that1.Value {
+ return -1
+ }
+ return 1
+ }
+ return 0
+}
+func (this *UInt64Value) Compare(that interface{}) int {
+ if that == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ }
+
+ that1, ok := that.(*UInt64Value)
+ if !ok {
+ that2, ok := that.(UInt64Value)
+ if ok {
+ that1 = &that2
+ } else {
+ return 1
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ } else if this == nil {
+ return -1
+ }
+ if this.Value != that1.Value {
+ if this.Value < that1.Value {
+ return -1
+ }
+ return 1
+ }
+ return 0
+}
+func (this *Int32Value) Compare(that interface{}) int {
+ if that == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ }
+
+ that1, ok := that.(*Int32Value)
+ if !ok {
+ that2, ok := that.(Int32Value)
+ if ok {
+ that1 = &that2
+ } else {
+ return 1
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ } else if this == nil {
+ return -1
+ }
+ if this.Value != that1.Value {
+ if this.Value < that1.Value {
+ return -1
+ }
+ return 1
+ }
+ return 0
+}
+func (this *UInt32Value) Compare(that interface{}) int {
+ if that == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ }
+
+ that1, ok := that.(*UInt32Value)
+ if !ok {
+ that2, ok := that.(UInt32Value)
+ if ok {
+ that1 = &that2
+ } else {
+ return 1
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ } else if this == nil {
+ return -1
+ }
+ if this.Value != that1.Value {
+ if this.Value < that1.Value {
+ return -1
+ }
+ return 1
+ }
+ return 0
+}
+func (this *BoolValue) Compare(that interface{}) int {
+ if that == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ }
+
+ that1, ok := that.(*BoolValue)
+ if !ok {
+ that2, ok := that.(BoolValue)
+ if ok {
+ that1 = &that2
+ } else {
+ return 1
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ } else if this == nil {
+ return -1
+ }
+ if this.Value != that1.Value {
+ if !this.Value {
+ return -1
+ }
+ return 1
+ }
+ return 0
+}
+func (this *StringValue) Compare(that interface{}) int {
+ if that == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ }
+
+ that1, ok := that.(*StringValue)
+ if !ok {
+ that2, ok := that.(StringValue)
+ if ok {
+ that1 = &that2
+ } else {
+ return 1
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ } else if this == nil {
+ return -1
+ }
+ if this.Value != that1.Value {
+ if this.Value < that1.Value {
+ return -1
+ }
+ return 1
+ }
+ return 0
+}
+func (this *BytesValue) Compare(that interface{}) int {
+ if that == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ }
+
+ that1, ok := that.(*BytesValue)
+ if !ok {
+ that2, ok := that.(BytesValue)
+ if ok {
+ that1 = &that2
+ } else {
+ return 1
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return 0
+ }
+ return 1
+ } else if this == nil {
+ return -1
+ }
+ if c := bytes.Compare(this.Value, that1.Value); c != 0 {
+ return c
+ }
+ return 0
+}
+func (this *DoubleValue) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*DoubleValue)
+ if !ok {
+ that2, ok := that.(DoubleValue)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if this.Value != that1.Value {
+ return false
+ }
+ return true
+}
+func (this *FloatValue) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*FloatValue)
+ if !ok {
+ that2, ok := that.(FloatValue)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if this.Value != that1.Value {
+ return false
+ }
+ return true
+}
+func (this *Int64Value) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*Int64Value)
+ if !ok {
+ that2, ok := that.(Int64Value)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if this.Value != that1.Value {
+ return false
+ }
+ return true
+}
+func (this *UInt64Value) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*UInt64Value)
+ if !ok {
+ that2, ok := that.(UInt64Value)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if this.Value != that1.Value {
+ return false
+ }
+ return true
+}
+func (this *Int32Value) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*Int32Value)
+ if !ok {
+ that2, ok := that.(Int32Value)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if this.Value != that1.Value {
+ return false
+ }
+ return true
+}
+func (this *UInt32Value) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*UInt32Value)
+ if !ok {
+ that2, ok := that.(UInt32Value)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if this.Value != that1.Value {
+ return false
+ }
+ return true
+}
+func (this *BoolValue) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*BoolValue)
+ if !ok {
+ that2, ok := that.(BoolValue)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if this.Value != that1.Value {
+ return false
+ }
+ return true
+}
+func (this *StringValue) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*StringValue)
+ if !ok {
+ that2, ok := that.(StringValue)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if this.Value != that1.Value {
+ return false
+ }
+ return true
+}
+func (this *BytesValue) Equal(that interface{}) bool {
+ if that == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ }
+
+ that1, ok := that.(*BytesValue)
+ if !ok {
+ that2, ok := that.(BytesValue)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ if this == nil {
+ return true
+ }
+ return false
+ } else if this == nil {
+ return false
+ }
+ if !bytes.Equal(this.Value, that1.Value) {
+ return false
+ }
+ return true
+}
+func (this *DoubleValue) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&types.DoubleValue{")
+ s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n")
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *FloatValue) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&types.FloatValue{")
+ s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n")
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *Int64Value) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&types.Int64Value{")
+ s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n")
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *UInt64Value) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&types.UInt64Value{")
+ s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n")
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *Int32Value) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&types.Int32Value{")
+ s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n")
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *UInt32Value) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&types.UInt32Value{")
+ s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n")
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *BoolValue) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&types.BoolValue{")
+ s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n")
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *StringValue) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&types.StringValue{")
+ s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n")
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *BytesValue) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&types.BytesValue{")
+ s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n")
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func valueToGoStringWrappers(v interface{}, typ string) string {
+ rv := reflect.ValueOf(v)
+ if rv.IsNil() {
+ return "nil"
+ }
+ pv := reflect.Indirect(rv).Interface()
+ return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
+}
+func (m *DoubleValue) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *DoubleValue) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Value != 0 {
+ dAtA[i] = 0x9
+ i++
+ i = encodeFixed64Wrappers(dAtA, i, uint64(math.Float64bits(float64(m.Value))))
+ }
+ return i, nil
+}
+
+func (m *FloatValue) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *FloatValue) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Value != 0 {
+ dAtA[i] = 0xd
+ i++
+ i = encodeFixed32Wrappers(dAtA, i, uint32(math.Float32bits(float32(m.Value))))
+ }
+ return i, nil
+}
+
+func (m *Int64Value) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Int64Value) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Value != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintWrappers(dAtA, i, uint64(m.Value))
+ }
+ return i, nil
+}
+
+func (m *UInt64Value) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *UInt64Value) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Value != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintWrappers(dAtA, i, uint64(m.Value))
+ }
+ return i, nil
+}
+
+func (m *Int32Value) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Int32Value) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Value != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintWrappers(dAtA, i, uint64(m.Value))
+ }
+ return i, nil
+}
+
+func (m *UInt32Value) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *UInt32Value) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Value != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintWrappers(dAtA, i, uint64(m.Value))
+ }
+ return i, nil
+}
+
+func (m *BoolValue) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *BoolValue) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Value {
+ dAtA[i] = 0x8
+ i++
+ if m.Value {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ }
+ return i, nil
+}
+
+func (m *StringValue) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *StringValue) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Value) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintWrappers(dAtA, i, uint64(len(m.Value)))
+ i += copy(dAtA[i:], m.Value)
+ }
+ return i, nil
+}
+
+func (m *BytesValue) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *BytesValue) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Value) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintWrappers(dAtA, i, uint64(len(m.Value)))
+ i += copy(dAtA[i:], m.Value)
+ }
+ return i, nil
+}
+
+func encodeFixed64Wrappers(dAtA []byte, offset int, v uint64) int {
+ dAtA[offset] = uint8(v)
+ dAtA[offset+1] = uint8(v >> 8)
+ dAtA[offset+2] = uint8(v >> 16)
+ dAtA[offset+3] = uint8(v >> 24)
+ dAtA[offset+4] = uint8(v >> 32)
+ dAtA[offset+5] = uint8(v >> 40)
+ dAtA[offset+6] = uint8(v >> 48)
+ dAtA[offset+7] = uint8(v >> 56)
+ return offset + 8
+}
+func encodeFixed32Wrappers(dAtA []byte, offset int, v uint32) int {
+ dAtA[offset] = uint8(v)
+ dAtA[offset+1] = uint8(v >> 8)
+ dAtA[offset+2] = uint8(v >> 16)
+ dAtA[offset+3] = uint8(v >> 24)
+ return offset + 4
+}
+func encodeVarintWrappers(dAtA []byte, offset int, v uint64) int {
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return offset + 1
+}
+func NewPopulatedDoubleValue(r randyWrappers, easy bool) *DoubleValue {
+ this := &DoubleValue{}
+ this.Value = float64(r.Float64())
+ if r.Intn(2) == 0 {
+ this.Value *= -1
+ }
+ if !easy && r.Intn(10) != 0 {
+ }
+ return this
+}
+
+func NewPopulatedFloatValue(r randyWrappers, easy bool) *FloatValue {
+ this := &FloatValue{}
+ this.Value = float32(r.Float32())
+ if r.Intn(2) == 0 {
+ this.Value *= -1
+ }
+ if !easy && r.Intn(10) != 0 {
+ }
+ return this
+}
+
+func NewPopulatedInt64Value(r randyWrappers, easy bool) *Int64Value {
+ this := &Int64Value{}
+ this.Value = int64(r.Int63())
+ if r.Intn(2) == 0 {
+ this.Value *= -1
+ }
+ if !easy && r.Intn(10) != 0 {
+ }
+ return this
+}
+
+func NewPopulatedUInt64Value(r randyWrappers, easy bool) *UInt64Value {
+ this := &UInt64Value{}
+ this.Value = uint64(uint64(r.Uint32()))
+ if !easy && r.Intn(10) != 0 {
+ }
+ return this
+}
+
+func NewPopulatedInt32Value(r randyWrappers, easy bool) *Int32Value {
+ this := &Int32Value{}
+ this.Value = int32(r.Int31())
+ if r.Intn(2) == 0 {
+ this.Value *= -1
+ }
+ if !easy && r.Intn(10) != 0 {
+ }
+ return this
+}
+
+func NewPopulatedUInt32Value(r randyWrappers, easy bool) *UInt32Value {
+ this := &UInt32Value{}
+ this.Value = uint32(r.Uint32())
+ if !easy && r.Intn(10) != 0 {
+ }
+ return this
+}
+
+func NewPopulatedBoolValue(r randyWrappers, easy bool) *BoolValue {
+ this := &BoolValue{}
+ this.Value = bool(bool(r.Intn(2) == 0))
+ if !easy && r.Intn(10) != 0 {
+ }
+ return this
+}
+
+func NewPopulatedStringValue(r randyWrappers, easy bool) *StringValue {
+ this := &StringValue{}
+ this.Value = string(randStringWrappers(r))
+ if !easy && r.Intn(10) != 0 {
+ }
+ return this
+}
+
+func NewPopulatedBytesValue(r randyWrappers, easy bool) *BytesValue {
+ this := &BytesValue{}
+ v1 := r.Intn(100)
+ this.Value = make([]byte, v1)
+ for i := 0; i < v1; i++ {
+ this.Value[i] = byte(r.Intn(256))
+ }
+ if !easy && r.Intn(10) != 0 {
+ }
+ return this
+}
+
+type randyWrappers interface {
+ Float32() float32
+ Float64() float64
+ Int63() int64
+ Int31() int32
+ Uint32() uint32
+ Intn(n int) int
+}
+
+func randUTF8RuneWrappers(r randyWrappers) rune {
+ ru := r.Intn(62)
+ if ru < 10 {
+ return rune(ru + 48)
+ } else if ru < 36 {
+ return rune(ru + 55)
+ }
+ return rune(ru + 61)
+}
+func randStringWrappers(r randyWrappers) string {
+ v2 := r.Intn(100)
+ tmps := make([]rune, v2)
+ for i := 0; i < v2; i++ {
+ tmps[i] = randUTF8RuneWrappers(r)
+ }
+ return string(tmps)
+}
+func randUnrecognizedWrappers(r randyWrappers, maxFieldNumber int) (dAtA []byte) {
+ l := r.Intn(5)
+ for i := 0; i < l; i++ {
+ wire := r.Intn(4)
+ if wire == 3 {
+ wire = 5
+ }
+ fieldNumber := maxFieldNumber + r.Intn(100)
+ dAtA = randFieldWrappers(dAtA, r, fieldNumber, wire)
+ }
+ return dAtA
+}
+func randFieldWrappers(dAtA []byte, r randyWrappers, fieldNumber int, wire int) []byte {
+ key := uint32(fieldNumber)<<3 | uint32(wire)
+ switch wire {
+ case 0:
+ dAtA = encodeVarintPopulateWrappers(dAtA, uint64(key))
+ v3 := r.Int63()
+ if r.Intn(2) == 0 {
+ v3 *= -1
+ }
+ dAtA = encodeVarintPopulateWrappers(dAtA, uint64(v3))
+ case 1:
+ dAtA = encodeVarintPopulateWrappers(dAtA, uint64(key))
+ dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))
+ case 2:
+ dAtA = encodeVarintPopulateWrappers(dAtA, uint64(key))
+ ll := r.Intn(100)
+ dAtA = encodeVarintPopulateWrappers(dAtA, uint64(ll))
+ for j := 0; j < ll; j++ {
+ dAtA = append(dAtA, byte(r.Intn(256)))
+ }
+ default:
+ dAtA = encodeVarintPopulateWrappers(dAtA, uint64(key))
+ dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))
+ }
+ return dAtA
+}
+func encodeVarintPopulateWrappers(dAtA []byte, v uint64) []byte {
+ for v >= 1<<7 {
+ dAtA = append(dAtA, uint8(uint64(v)&0x7f|0x80))
+ v >>= 7
+ }
+ dAtA = append(dAtA, uint8(v))
+ return dAtA
+}
+func (m *DoubleValue) Size() (n int) {
+ var l int
+ _ = l
+ if m.Value != 0 {
+ n += 9
+ }
+ return n
+}
+
+func (m *FloatValue) Size() (n int) {
+ var l int
+ _ = l
+ if m.Value != 0 {
+ n += 5
+ }
+ return n
+}
+
+func (m *Int64Value) Size() (n int) {
+ var l int
+ _ = l
+ if m.Value != 0 {
+ n += 1 + sovWrappers(uint64(m.Value))
+ }
+ return n
+}
+
+func (m *UInt64Value) Size() (n int) {
+ var l int
+ _ = l
+ if m.Value != 0 {
+ n += 1 + sovWrappers(uint64(m.Value))
+ }
+ return n
+}
+
+func (m *Int32Value) Size() (n int) {
+ var l int
+ _ = l
+ if m.Value != 0 {
+ n += 1 + sovWrappers(uint64(m.Value))
+ }
+ return n
+}
+
+func (m *UInt32Value) Size() (n int) {
+ var l int
+ _ = l
+ if m.Value != 0 {
+ n += 1 + sovWrappers(uint64(m.Value))
+ }
+ return n
+}
+
+func (m *BoolValue) Size() (n int) {
+ var l int
+ _ = l
+ if m.Value {
+ n += 2
+ }
+ return n
+}
+
+func (m *StringValue) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Value)
+ if l > 0 {
+ n += 1 + l + sovWrappers(uint64(l))
+ }
+ return n
+}
+
+func (m *BytesValue) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Value)
+ if l > 0 {
+ n += 1 + l + sovWrappers(uint64(l))
+ }
+ return n
+}
+
+func sovWrappers(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+func sozWrappers(x uint64) (n int) {
+ return sovWrappers(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (this *DoubleValue) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&DoubleValue{`,
+ `Value:` + fmt.Sprintf("%v", this.Value) + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func (this *FloatValue) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&FloatValue{`,
+ `Value:` + fmt.Sprintf("%v", this.Value) + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func (this *Int64Value) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&Int64Value{`,
+ `Value:` + fmt.Sprintf("%v", this.Value) + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func (this *UInt64Value) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&UInt64Value{`,
+ `Value:` + fmt.Sprintf("%v", this.Value) + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func (this *Int32Value) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&Int32Value{`,
+ `Value:` + fmt.Sprintf("%v", this.Value) + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func (this *UInt32Value) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&UInt32Value{`,
+ `Value:` + fmt.Sprintf("%v", this.Value) + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func (this *BoolValue) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&BoolValue{`,
+ `Value:` + fmt.Sprintf("%v", this.Value) + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func (this *StringValue) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&StringValue{`,
+ `Value:` + fmt.Sprintf("%v", this.Value) + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func (this *BytesValue) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&BytesValue{`,
+ `Value:` + fmt.Sprintf("%v", this.Value) + `,`,
+ `}`,
+ }, "")
+ return s
+}
+func valueToStringWrappers(v interface{}) string {
+ rv := reflect.ValueOf(v)
+ if rv.IsNil() {
+ return "nil"
+ }
+ pv := reflect.Indirect(rv).Interface()
+ return fmt.Sprintf("*%v", pv)
+}
+func (m *DoubleValue) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: DoubleValue: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: DoubleValue: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 1 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+ }
+ var v uint64
+ if (iNdEx + 8) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += 8
+ v = uint64(dAtA[iNdEx-8])
+ v |= uint64(dAtA[iNdEx-7]) << 8
+ v |= uint64(dAtA[iNdEx-6]) << 16
+ v |= uint64(dAtA[iNdEx-5]) << 24
+ v |= uint64(dAtA[iNdEx-4]) << 32
+ v |= uint64(dAtA[iNdEx-3]) << 40
+ v |= uint64(dAtA[iNdEx-2]) << 48
+ v |= uint64(dAtA[iNdEx-1]) << 56
+ m.Value = float64(math.Float64frombits(v))
+ default:
+ iNdEx = preIndex
+ skippy, err := skipWrappers(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthWrappers
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *FloatValue) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: FloatValue: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: FloatValue: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 5 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+ }
+ var v uint32
+ if (iNdEx + 4) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += 4
+ v = uint32(dAtA[iNdEx-4])
+ v |= uint32(dAtA[iNdEx-3]) << 8
+ v |= uint32(dAtA[iNdEx-2]) << 16
+ v |= uint32(dAtA[iNdEx-1]) << 24
+ m.Value = float32(math.Float32frombits(v))
+ default:
+ iNdEx = preIndex
+ skippy, err := skipWrappers(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthWrappers
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *Int64Value) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Int64Value: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Int64Value: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+ }
+ m.Value = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Value |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipWrappers(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthWrappers
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *UInt64Value) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: UInt64Value: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: UInt64Value: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+ }
+ m.Value = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Value |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipWrappers(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthWrappers
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *Int32Value) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Int32Value: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Int32Value: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+ }
+ m.Value = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Value |= (int32(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipWrappers(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthWrappers
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *UInt32Value) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: UInt32Value: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: UInt32Value: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+ }
+ m.Value = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Value |= (uint32(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipWrappers(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthWrappers
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *BoolValue) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: BoolValue: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: BoolValue: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Value = bool(v != 0)
+ default:
+ iNdEx = preIndex
+ skippy, err := skipWrappers(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthWrappers
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *StringValue) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: StringValue: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: StringValue: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthWrappers
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Value = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipWrappers(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthWrappers
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *BytesValue) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: BytesValue: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: BytesValue: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthWrappers
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Value = append(m.Value[:0], dAtA[iNdEx:postIndex]...)
+ if m.Value == nil {
+ m.Value = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipWrappers(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthWrappers
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipWrappers(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ return iNdEx, nil
+ case 1:
+ iNdEx += 8
+ return iNdEx, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ iNdEx += length
+ if length < 0 {
+ return 0, ErrInvalidLengthWrappers
+ }
+ return iNdEx, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = iNdEx
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowWrappers
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := skipWrappers(dAtA[start:])
+ if err != nil {
+ return 0, err
+ }
+ iNdEx = start + next
+ }
+ return iNdEx, nil
+ case 4:
+ return iNdEx, nil
+ case 5:
+ iNdEx += 4
+ return iNdEx, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
+
+var (
+ ErrInvalidLengthWrappers = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowWrappers = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("wrappers.proto", fileDescriptorWrappers) }
+
+var fileDescriptorWrappers = []byte{
+ // 278 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2b, 0x2f, 0x4a, 0x2c,
+ 0x28, 0x48, 0x2d, 0x2a, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x4f, 0xcf, 0xcf, 0x4f,
+ 0xcf, 0x49, 0x85, 0xf0, 0x92, 0x4a, 0xd3, 0x94, 0x94, 0xb9, 0xb8, 0x5d, 0xf2, 0x4b, 0x93, 0x72,
+ 0x52, 0xc3, 0x12, 0x73, 0x4a, 0x53, 0x85, 0x44, 0xb8, 0x58, 0xcb, 0x40, 0x0c, 0x09, 0x46, 0x05,
+ 0x46, 0x0d, 0xc6, 0x20, 0x08, 0x47, 0x49, 0x89, 0x8b, 0xcb, 0x2d, 0x27, 0x3f, 0xb1, 0x04, 0x8b,
+ 0x1a, 0x26, 0x24, 0x35, 0x9e, 0x79, 0x25, 0x66, 0x26, 0x58, 0xd4, 0x30, 0xc3, 0xd4, 0x28, 0x73,
+ 0x71, 0x87, 0xe2, 0x52, 0xc4, 0x82, 0x6a, 0x90, 0xb1, 0x11, 0x16, 0x35, 0xac, 0x68, 0x06, 0x61,
+ 0x55, 0xc4, 0x0b, 0x53, 0xa4, 0xc8, 0xc5, 0xe9, 0x94, 0x9f, 0x9f, 0x83, 0x45, 0x09, 0x07, 0x92,
+ 0x39, 0xc1, 0x25, 0x45, 0x99, 0x79, 0xe9, 0x58, 0x14, 0x71, 0x22, 0x39, 0xc8, 0xa9, 0xb2, 0x24,
+ 0xb5, 0x18, 0x8b, 0x1a, 0x1e, 0xa8, 0x1a, 0xa7, 0x76, 0xc6, 0x0b, 0x0f, 0xe5, 0x18, 0x6e, 0x3c,
+ 0x94, 0x63, 0xf8, 0xf0, 0x50, 0x8e, 0xf1, 0xc7, 0x43, 0x39, 0xc6, 0x86, 0x47, 0x72, 0x8c, 0x2b,
+ 0x1e, 0xc9, 0x31, 0x9e, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c,
+ 0x2f, 0x1e, 0xc9, 0x31, 0x7c, 0x00, 0x89, 0x3f, 0x96, 0x63, 0xe4, 0x12, 0x4e, 0xce, 0xcf, 0xd5,
+ 0x43, 0x8b, 0x0e, 0x27, 0xde, 0x70, 0x68, 0x7c, 0x05, 0x80, 0x44, 0x02, 0x18, 0xa3, 0x58, 0x4b,
+ 0x2a, 0x0b, 0x52, 0x8b, 0x7f, 0x30, 0x32, 0x2e, 0x62, 0x62, 0x76, 0x0f, 0x70, 0x5a, 0xc5, 0x24,
+ 0xe7, 0x0e, 0xd1, 0x12, 0x00, 0xd5, 0xa2, 0x17, 0x9e, 0x9a, 0x93, 0xe3, 0x9d, 0x97, 0x5f, 0x9e,
+ 0x17, 0x02, 0x52, 0x99, 0xc4, 0x06, 0x36, 0xcb, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x23, 0x27,
+ 0x6c, 0x5f, 0xfa, 0x01, 0x00, 0x00,
+}
--- /dev/null
+Go support for Protocol Buffers - Google's data interchange format
+
+Copyright 2010 The Go Authors. All rights reserved.
+https://github.com/golang/protobuf
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
--- /dev/null
+# Go support for Protocol Buffers - Google's data interchange format
+#
+# Copyright 2010 The Go Authors. All rights reserved.
+# https://github.com/golang/protobuf
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+install:
+ go install
+
+test: install generate-test-pbs
+ go test
+
+
+generate-test-pbs:
+ make install
+ make -C testdata
+ protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. proto3_proto/proto3.proto
+ make
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2011 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Protocol buffer deep copy and merge.
+// TODO: RawMessage.
+
+package proto
+
+import (
+ "log"
+ "reflect"
+ "strings"
+)
+
+// Clone returns a deep copy of a protocol buffer.
+func Clone(pb Message) Message {
+ in := reflect.ValueOf(pb)
+ if in.IsNil() {
+ return pb
+ }
+
+ out := reflect.New(in.Type().Elem())
+ // out is empty so a merge is a deep copy.
+ mergeStruct(out.Elem(), in.Elem())
+ return out.Interface().(Message)
+}
+
+// Merge merges src into dst.
+// Required and optional fields that are set in src will be set to that value in dst.
+// Elements of repeated fields will be appended.
+// Merge panics if src and dst are not the same type, or if dst is nil.
+func Merge(dst, src Message) {
+ in := reflect.ValueOf(src)
+ out := reflect.ValueOf(dst)
+ if out.IsNil() {
+ panic("proto: nil destination")
+ }
+ if in.Type() != out.Type() {
+ // Explicit test prior to mergeStruct so that mistyped nils will fail
+ panic("proto: type mismatch")
+ }
+ if in.IsNil() {
+ // Merging nil into non-nil is a quiet no-op
+ return
+ }
+ mergeStruct(out.Elem(), in.Elem())
+}
+
+func mergeStruct(out, in reflect.Value) {
+ sprop := GetProperties(in.Type())
+ for i := 0; i < in.NumField(); i++ {
+ f := in.Type().Field(i)
+ if strings.HasPrefix(f.Name, "XXX_") {
+ continue
+ }
+ mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i])
+ }
+
+ if emIn, ok := extendable(in.Addr().Interface()); ok {
+ emOut, _ := extendable(out.Addr().Interface())
+ mIn, muIn := emIn.extensionsRead()
+ if mIn != nil {
+ mOut := emOut.extensionsWrite()
+ muIn.Lock()
+ mergeExtension(mOut, mIn)
+ muIn.Unlock()
+ }
+ }
+
+ uf := in.FieldByName("XXX_unrecognized")
+ if !uf.IsValid() {
+ return
+ }
+ uin := uf.Bytes()
+ if len(uin) > 0 {
+ out.FieldByName("XXX_unrecognized").SetBytes(append([]byte(nil), uin...))
+ }
+}
+
+// mergeAny performs a merge between two values of the same type.
+// viaPtr indicates whether the values were indirected through a pointer (implying proto2).
+// prop is set if this is a struct field (it may be nil).
+func mergeAny(out, in reflect.Value, viaPtr bool, prop *Properties) {
+ if in.Type() == protoMessageType {
+ if !in.IsNil() {
+ if out.IsNil() {
+ out.Set(reflect.ValueOf(Clone(in.Interface().(Message))))
+ } else {
+ Merge(out.Interface().(Message), in.Interface().(Message))
+ }
+ }
+ return
+ }
+ switch in.Kind() {
+ case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
+ reflect.String, reflect.Uint32, reflect.Uint64:
+ if !viaPtr && isProto3Zero(in) {
+ return
+ }
+ out.Set(in)
+ case reflect.Interface:
+ // Probably a oneof field; copy non-nil values.
+ if in.IsNil() {
+ return
+ }
+ // Allocate destination if it is not set, or set to a different type.
+ // Otherwise we will merge as normal.
+ if out.IsNil() || out.Elem().Type() != in.Elem().Type() {
+ out.Set(reflect.New(in.Elem().Elem().Type())) // interface -> *T -> T -> new(T)
+ }
+ mergeAny(out.Elem(), in.Elem(), false, nil)
+ case reflect.Map:
+ if in.Len() == 0 {
+ return
+ }
+ if out.IsNil() {
+ out.Set(reflect.MakeMap(in.Type()))
+ }
+ // For maps with value types of *T or []byte we need to deep copy each value.
+ elemKind := in.Type().Elem().Kind()
+ for _, key := range in.MapKeys() {
+ var val reflect.Value
+ switch elemKind {
+ case reflect.Ptr:
+ val = reflect.New(in.Type().Elem().Elem())
+ mergeAny(val, in.MapIndex(key), false, nil)
+ case reflect.Slice:
+ val = in.MapIndex(key)
+ val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
+ default:
+ val = in.MapIndex(key)
+ }
+ out.SetMapIndex(key, val)
+ }
+ case reflect.Ptr:
+ if in.IsNil() {
+ return
+ }
+ if out.IsNil() {
+ out.Set(reflect.New(in.Elem().Type()))
+ }
+ mergeAny(out.Elem(), in.Elem(), true, nil)
+ case reflect.Slice:
+ if in.IsNil() {
+ return
+ }
+ if in.Type().Elem().Kind() == reflect.Uint8 {
+ // []byte is a scalar bytes field, not a repeated field.
+
+ // Edge case: if this is in a proto3 message, a zero length
+ // bytes field is considered the zero value, and should not
+ // be merged.
+ if prop != nil && prop.proto3 && in.Len() == 0 {
+ return
+ }
+
+ // Make a deep copy.
+ // Append to []byte{} instead of []byte(nil) so that we never end up
+ // with a nil result.
+ out.SetBytes(append([]byte{}, in.Bytes()...))
+ return
+ }
+ n := in.Len()
+ if out.IsNil() {
+ out.Set(reflect.MakeSlice(in.Type(), 0, n))
+ }
+ switch in.Type().Elem().Kind() {
+ case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
+ reflect.String, reflect.Uint32, reflect.Uint64:
+ out.Set(reflect.AppendSlice(out, in))
+ default:
+ for i := 0; i < n; i++ {
+ x := reflect.Indirect(reflect.New(in.Type().Elem()))
+ mergeAny(x, in.Index(i), false, nil)
+ out.Set(reflect.Append(out, x))
+ }
+ }
+ case reflect.Struct:
+ mergeStruct(out, in)
+ default:
+ // unknown type, so not a protocol buffer
+ log.Printf("proto: don't know how to copy %v", in)
+ }
+}
+
+func mergeExtension(out, in map[int32]Extension) {
+ for extNum, eIn := range in {
+ eOut := Extension{desc: eIn.desc}
+ if eIn.value != nil {
+ v := reflect.New(reflect.TypeOf(eIn.value)).Elem()
+ mergeAny(v, reflect.ValueOf(eIn.value), false, nil)
+ eOut.value = v.Interface()
+ }
+ if eIn.enc != nil {
+ eOut.enc = make([]byte, len(eIn.enc))
+ copy(eOut.enc, eIn.enc)
+ }
+
+ out[extNum] = eOut
+ }
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+/*
+ * Routines for decoding protocol buffer data to construct in-memory representations.
+ */
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "reflect"
+)
+
+// errOverflow is returned when an integer is too large to be represented.
+var errOverflow = errors.New("proto: integer overflow")
+
+// ErrInternalBadWireType is returned by generated code when an incorrect
+// wire type is encountered. It does not get returned to user code.
+var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
+
+// The fundamental decoders that interpret bytes on the wire.
+// Those that take integer types all return uint64 and are
+// therefore of type valueDecoder.
+
+// DecodeVarint reads a varint-encoded integer from the slice.
+// It returns the integer and the number of bytes consumed, or
+// zero if there is not enough.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+func DecodeVarint(buf []byte) (x uint64, n int) {
+ // x, n already 0
+ for shift := uint(0); shift < 64; shift += 7 {
+ if n >= len(buf) {
+ return 0, 0
+ }
+ b := uint64(buf[n])
+ n++
+ x |= (b & 0x7F) << shift
+ if (b & 0x80) == 0 {
+ return x, n
+ }
+ }
+
+ // The number is too large to represent in a 64-bit value.
+ return 0, 0
+}
+
+// DecodeVarint reads a varint-encoded integer from the Buffer.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+func (p *Buffer) DecodeVarint() (x uint64, err error) {
+ // x, err already 0
+
+ i := p.index
+ l := len(p.buf)
+
+ for shift := uint(0); shift < 64; shift += 7 {
+ if i >= l {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+ b := p.buf[i]
+ i++
+ x |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ p.index = i
+ return
+ }
+ }
+
+ // The number is too large to represent in a 64-bit value.
+ err = errOverflow
+ return
+}
+
+// DecodeFixed64 reads a 64-bit integer from the Buffer.
+// This is the format for the
+// fixed64, sfixed64, and double protocol buffer types.
+func (p *Buffer) DecodeFixed64() (x uint64, err error) {
+ // x, err already 0
+ i := p.index + 8
+ if i < 0 || i > len(p.buf) {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+ p.index = i
+
+ x = uint64(p.buf[i-8])
+ x |= uint64(p.buf[i-7]) << 8
+ x |= uint64(p.buf[i-6]) << 16
+ x |= uint64(p.buf[i-5]) << 24
+ x |= uint64(p.buf[i-4]) << 32
+ x |= uint64(p.buf[i-3]) << 40
+ x |= uint64(p.buf[i-2]) << 48
+ x |= uint64(p.buf[i-1]) << 56
+ return
+}
+
+// DecodeFixed32 reads a 32-bit integer from the Buffer.
+// This is the format for the
+// fixed32, sfixed32, and float protocol buffer types.
+func (p *Buffer) DecodeFixed32() (x uint64, err error) {
+ // x, err already 0
+ i := p.index + 4
+ if i < 0 || i > len(p.buf) {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+ p.index = i
+
+ x = uint64(p.buf[i-4])
+ x |= uint64(p.buf[i-3]) << 8
+ x |= uint64(p.buf[i-2]) << 16
+ x |= uint64(p.buf[i-1]) << 24
+ return
+}
+
+// DecodeZigzag64 reads a zigzag-encoded 64-bit integer
+// from the Buffer.
+// This is the format used for the sint64 protocol buffer type.
+func (p *Buffer) DecodeZigzag64() (x uint64, err error) {
+ x, err = p.DecodeVarint()
+ if err != nil {
+ return
+ }
+ x = (x >> 1) ^ uint64((int64(x&1)<<63)>>63)
+ return
+}
+
+// DecodeZigzag32 reads a zigzag-encoded 32-bit integer
+// from the Buffer.
+// This is the format used for the sint32 protocol buffer type.
+func (p *Buffer) DecodeZigzag32() (x uint64, err error) {
+ x, err = p.DecodeVarint()
+ if err != nil {
+ return
+ }
+ x = uint64((uint32(x) >> 1) ^ uint32((int32(x&1)<<31)>>31))
+ return
+}
+
+// These are not ValueDecoders: they produce an array of bytes or a string.
+// bytes, embedded messages
+
+// DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
+// This is the format used for the bytes protocol buffer
+// type and for embedded messages.
+func (p *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err error) {
+ n, err := p.DecodeVarint()
+ if err != nil {
+ return nil, err
+ }
+
+ nb := int(n)
+ if nb < 0 {
+ return nil, fmt.Errorf("proto: bad byte length %d", nb)
+ }
+ end := p.index + nb
+ if end < p.index || end > len(p.buf) {
+ return nil, io.ErrUnexpectedEOF
+ }
+
+ if !alloc {
+ // todo: check if can get more uses of alloc=false
+ buf = p.buf[p.index:end]
+ p.index += nb
+ return
+ }
+
+ buf = make([]byte, nb)
+ copy(buf, p.buf[p.index:])
+ p.index += nb
+ return
+}
+
+// DecodeStringBytes reads an encoded string from the Buffer.
+// This is the format used for the proto2 string type.
+func (p *Buffer) DecodeStringBytes() (s string, err error) {
+ buf, err := p.DecodeRawBytes(false)
+ if err != nil {
+ return
+ }
+ return string(buf), nil
+}
+
+// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
+// If the protocol buffer has extensions, and the field matches, add it as an extension.
+// Otherwise, if the XXX_unrecognized field exists, append the skipped data there.
+func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base structPointer, unrecField field) error {
+ oi := o.index
+
+ err := o.skip(t, tag, wire)
+ if err != nil {
+ return err
+ }
+
+ if !unrecField.IsValid() {
+ return nil
+ }
+
+ ptr := structPointer_Bytes(base, unrecField)
+
+ // Add the skipped field to struct field
+ obuf := o.buf
+
+ o.buf = *ptr
+ o.EncodeVarint(uint64(tag<<3 | wire))
+ *ptr = append(o.buf, obuf[oi:o.index]...)
+
+ o.buf = obuf
+
+ return nil
+}
+
+// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
+func (o *Buffer) skip(t reflect.Type, tag, wire int) error {
+
+ var u uint64
+ var err error
+
+ switch wire {
+ case WireVarint:
+ _, err = o.DecodeVarint()
+ case WireFixed64:
+ _, err = o.DecodeFixed64()
+ case WireBytes:
+ _, err = o.DecodeRawBytes(false)
+ case WireFixed32:
+ _, err = o.DecodeFixed32()
+ case WireStartGroup:
+ for {
+ u, err = o.DecodeVarint()
+ if err != nil {
+ break
+ }
+ fwire := int(u & 0x7)
+ if fwire == WireEndGroup {
+ break
+ }
+ ftag := int(u >> 3)
+ err = o.skip(t, ftag, fwire)
+ if err != nil {
+ break
+ }
+ }
+ default:
+ err = fmt.Errorf("proto: can't skip unknown wire type %d for %s", wire, t)
+ }
+ return err
+}
+
+// Unmarshaler is the interface representing objects that can
+// unmarshal themselves. The method should reset the receiver before
+// decoding starts. The argument points to data that may be
+// overwritten, so implementations should not keep references to the
+// buffer.
+type Unmarshaler interface {
+ Unmarshal([]byte) error
+}
+
+// Unmarshal parses the protocol buffer representation in buf and places the
+// decoded result in pb. If the struct underlying pb does not match
+// the data in buf, the results can be unpredictable.
+//
+// Unmarshal resets pb before starting to unmarshal, so any
+// existing data in pb is always removed. Use UnmarshalMerge
+// to preserve and append to existing data.
+func Unmarshal(buf []byte, pb Message) error {
+ pb.Reset()
+ return UnmarshalMerge(buf, pb)
+}
+
+// UnmarshalMerge parses the protocol buffer representation in buf and
+// writes the decoded result to pb. If the struct underlying pb does not match
+// the data in buf, the results can be unpredictable.
+//
+// UnmarshalMerge merges into existing data in pb.
+// Most code should use Unmarshal instead.
+func UnmarshalMerge(buf []byte, pb Message) error {
+ // If the object can unmarshal itself, let it.
+ if u, ok := pb.(Unmarshaler); ok {
+ return u.Unmarshal(buf)
+ }
+ return NewBuffer(buf).Unmarshal(pb)
+}
+
+// DecodeMessage reads a count-delimited message from the Buffer.
+func (p *Buffer) DecodeMessage(pb Message) error {
+ enc, err := p.DecodeRawBytes(false)
+ if err != nil {
+ return err
+ }
+ return NewBuffer(enc).Unmarshal(pb)
+}
+
+// DecodeGroup reads a tag-delimited group from the Buffer.
+func (p *Buffer) DecodeGroup(pb Message) error {
+ typ, base, err := getbase(pb)
+ if err != nil {
+ return err
+ }
+ return p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), true, base)
+}
+
+// Unmarshal parses the protocol buffer representation in the
+// Buffer and places the decoded result in pb. If the struct
+// underlying pb does not match the data in the buffer, the results can be
+// unpredictable.
+func (p *Buffer) Unmarshal(pb Message) error {
+ // If the object can unmarshal itself, let it.
+ if u, ok := pb.(Unmarshaler); ok {
+ err := u.Unmarshal(p.buf[p.index:])
+ p.index = len(p.buf)
+ return err
+ }
+
+ typ, base, err := getbase(pb)
+ if err != nil {
+ return err
+ }
+
+ err = p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), false, base)
+
+ if collectStats {
+ stats.Decode++
+ }
+
+ return err
+}
+
+// unmarshalType does the work of unmarshaling a structure.
+func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group bool, base structPointer) error {
+ var state errorState
+ required, reqFields := prop.reqCount, uint64(0)
+
+ var err error
+ for err == nil && o.index < len(o.buf) {
+ oi := o.index
+ var u uint64
+ u, err = o.DecodeVarint()
+ if err != nil {
+ break
+ }
+ wire := int(u & 0x7)
+ if wire == WireEndGroup {
+ if is_group {
+ return nil // input is satisfied
+ }
+ return fmt.Errorf("proto: %s: wiretype end group for non-group", st)
+ }
+ tag := int(u >> 3)
+ if tag <= 0 {
+ return fmt.Errorf("proto: %s: illegal tag %d (wire type %d)", st, tag, wire)
+ }
+ fieldnum, ok := prop.decoderTags.get(tag)
+ if !ok {
+ // Maybe it's an extension?
+ if prop.extendable {
+ if e, _ := extendable(structPointer_Interface(base, st)); isExtensionField(e, int32(tag)) {
+ if err = o.skip(st, tag, wire); err == nil {
+ extmap := e.extensionsWrite()
+ ext := extmap[int32(tag)] // may be missing
+ ext.enc = append(ext.enc, o.buf[oi:o.index]...)
+ extmap[int32(tag)] = ext
+ }
+ continue
+ }
+ }
+ // Maybe it's a oneof?
+ if prop.oneofUnmarshaler != nil {
+ m := structPointer_Interface(base, st).(Message)
+ // First return value indicates whether tag is a oneof field.
+ ok, err = prop.oneofUnmarshaler(m, tag, wire, o)
+ if err == ErrInternalBadWireType {
+ // Map the error to something more descriptive.
+ // Do the formatting here to save generated code space.
+ err = fmt.Errorf("bad wiretype for oneof field in %T", m)
+ }
+ if ok {
+ continue
+ }
+ }
+ err = o.skipAndSave(st, tag, wire, base, prop.unrecField)
+ continue
+ }
+ p := prop.Prop[fieldnum]
+
+ if p.dec == nil {
+ fmt.Fprintf(os.Stderr, "proto: no protobuf decoder for %s.%s\n", st, st.Field(fieldnum).Name)
+ continue
+ }
+ dec := p.dec
+ if wire != WireStartGroup && wire != p.WireType {
+ if wire == WireBytes && p.packedDec != nil {
+ // a packable field
+ dec = p.packedDec
+ } else {
+ err = fmt.Errorf("proto: bad wiretype for field %s.%s: got wiretype %d, want %d", st, st.Field(fieldnum).Name, wire, p.WireType)
+ continue
+ }
+ }
+ decErr := dec(o, p, base)
+ if decErr != nil && !state.shouldContinue(decErr, p) {
+ err = decErr
+ }
+ if err == nil && p.Required {
+ // Successfully decoded a required field.
+ if tag <= 64 {
+ // use bitmap for fields 1-64 to catch field reuse.
+ var mask uint64 = 1 << uint64(tag-1)
+ if reqFields&mask == 0 {
+ // new required field
+ reqFields |= mask
+ required--
+ }
+ } else {
+ // This is imprecise. It can be fooled by a required field
+ // with a tag > 64 that is encoded twice; that's very rare.
+ // A fully correct implementation would require allocating
+ // a data structure, which we would like to avoid.
+ required--
+ }
+ }
+ }
+ if err == nil {
+ if is_group {
+ return io.ErrUnexpectedEOF
+ }
+ if state.err != nil {
+ return state.err
+ }
+ if required > 0 {
+ // Not enough information to determine the exact field. If we use extra
+ // CPU, we could determine the field only if the missing required field
+ // has a tag <= 64 and we check reqFields.
+ return &RequiredNotSetError{"{Unknown}"}
+ }
+ }
+ return err
+}
+
+// Individual type decoders
+// For each,
+// u is the decoded value,
+// v is a pointer to the field (pointer) in the struct
+
+// Sizes of the pools to allocate inside the Buffer.
+// The goal is modest amortization and allocation
+// on at least 16-byte boundaries.
+const (
+ boolPoolSize = 16
+ uint32PoolSize = 8
+ uint64PoolSize = 4
+)
+
+// Decode a bool.
+func (o *Buffer) dec_bool(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ if len(o.bools) == 0 {
+ o.bools = make([]bool, boolPoolSize)
+ }
+ o.bools[0] = u != 0
+ *structPointer_Bool(base, p.field) = &o.bools[0]
+ o.bools = o.bools[1:]
+ return nil
+}
+
+func (o *Buffer) dec_proto3_bool(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ *structPointer_BoolVal(base, p.field) = u != 0
+ return nil
+}
+
+// Decode an int32.
+func (o *Buffer) dec_int32(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ word32_Set(structPointer_Word32(base, p.field), o, uint32(u))
+ return nil
+}
+
+func (o *Buffer) dec_proto3_int32(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ word32Val_Set(structPointer_Word32Val(base, p.field), uint32(u))
+ return nil
+}
+
+// Decode an int64.
+func (o *Buffer) dec_int64(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ word64_Set(structPointer_Word64(base, p.field), o, u)
+ return nil
+}
+
+func (o *Buffer) dec_proto3_int64(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ word64Val_Set(structPointer_Word64Val(base, p.field), o, u)
+ return nil
+}
+
+// Decode a string.
+func (o *Buffer) dec_string(p *Properties, base structPointer) error {
+ s, err := o.DecodeStringBytes()
+ if err != nil {
+ return err
+ }
+ *structPointer_String(base, p.field) = &s
+ return nil
+}
+
+func (o *Buffer) dec_proto3_string(p *Properties, base structPointer) error {
+ s, err := o.DecodeStringBytes()
+ if err != nil {
+ return err
+ }
+ *structPointer_StringVal(base, p.field) = s
+ return nil
+}
+
+// Decode a slice of bytes ([]byte).
+func (o *Buffer) dec_slice_byte(p *Properties, base structPointer) error {
+ b, err := o.DecodeRawBytes(true)
+ if err != nil {
+ return err
+ }
+ *structPointer_Bytes(base, p.field) = b
+ return nil
+}
+
+// Decode a slice of bools ([]bool).
+func (o *Buffer) dec_slice_bool(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ v := structPointer_BoolSlice(base, p.field)
+ *v = append(*v, u != 0)
+ return nil
+}
+
+// Decode a slice of bools ([]bool) in packed format.
+func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer) error {
+ v := structPointer_BoolSlice(base, p.field)
+
+ nn, err := o.DecodeVarint()
+ if err != nil {
+ return err
+ }
+ nb := int(nn) // number of bytes of encoded bools
+ fin := o.index + nb
+ if fin < o.index {
+ return errOverflow
+ }
+
+ y := *v
+ for o.index < fin {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ y = append(y, u != 0)
+ }
+
+ *v = y
+ return nil
+}
+
+// Decode a slice of int32s ([]int32).
+func (o *Buffer) dec_slice_int32(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ structPointer_Word32Slice(base, p.field).Append(uint32(u))
+ return nil
+}
+
+// Decode a slice of int32s ([]int32) in packed format.
+func (o *Buffer) dec_slice_packed_int32(p *Properties, base structPointer) error {
+ v := structPointer_Word32Slice(base, p.field)
+
+ nn, err := o.DecodeVarint()
+ if err != nil {
+ return err
+ }
+ nb := int(nn) // number of bytes of encoded int32s
+
+ fin := o.index + nb
+ if fin < o.index {
+ return errOverflow
+ }
+ for o.index < fin {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ v.Append(uint32(u))
+ }
+ return nil
+}
+
+// Decode a slice of int64s ([]int64).
+func (o *Buffer) dec_slice_int64(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+
+ structPointer_Word64Slice(base, p.field).Append(u)
+ return nil
+}
+
+// Decode a slice of int64s ([]int64) in packed format.
+func (o *Buffer) dec_slice_packed_int64(p *Properties, base structPointer) error {
+ v := structPointer_Word64Slice(base, p.field)
+
+ nn, err := o.DecodeVarint()
+ if err != nil {
+ return err
+ }
+ nb := int(nn) // number of bytes of encoded int64s
+
+ fin := o.index + nb
+ if fin < o.index {
+ return errOverflow
+ }
+ for o.index < fin {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ v.Append(u)
+ }
+ return nil
+}
+
+// Decode a slice of strings ([]string).
+func (o *Buffer) dec_slice_string(p *Properties, base structPointer) error {
+ s, err := o.DecodeStringBytes()
+ if err != nil {
+ return err
+ }
+ v := structPointer_StringSlice(base, p.field)
+ *v = append(*v, s)
+ return nil
+}
+
+// Decode a slice of slice of bytes ([][]byte).
+func (o *Buffer) dec_slice_slice_byte(p *Properties, base structPointer) error {
+ b, err := o.DecodeRawBytes(true)
+ if err != nil {
+ return err
+ }
+ v := structPointer_BytesSlice(base, p.field)
+ *v = append(*v, b)
+ return nil
+}
+
+// Decode a map field.
+func (o *Buffer) dec_new_map(p *Properties, base structPointer) error {
+ raw, err := o.DecodeRawBytes(false)
+ if err != nil {
+ return err
+ }
+ oi := o.index // index at the end of this map entry
+ o.index -= len(raw) // move buffer back to start of map entry
+
+ mptr := structPointer_NewAt(base, p.field, p.mtype) // *map[K]V
+ if mptr.Elem().IsNil() {
+ mptr.Elem().Set(reflect.MakeMap(mptr.Type().Elem()))
+ }
+ v := mptr.Elem() // map[K]V
+
+ // Prepare addressable doubly-indirect placeholders for the key and value types.
+ // See enc_new_map for why.
+ keyptr := reflect.New(reflect.PtrTo(p.mtype.Key())).Elem() // addressable *K
+ keybase := toStructPointer(keyptr.Addr()) // **K
+
+ var valbase structPointer
+ var valptr reflect.Value
+ switch p.mtype.Elem().Kind() {
+ case reflect.Slice:
+ // []byte
+ var dummy []byte
+ valptr = reflect.ValueOf(&dummy) // *[]byte
+ valbase = toStructPointer(valptr) // *[]byte
+ case reflect.Ptr:
+ // message; valptr is **Msg; need to allocate the intermediate pointer
+ valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V
+ valptr.Set(reflect.New(valptr.Type().Elem()))
+ valbase = toStructPointer(valptr)
+ default:
+ // everything else
+ valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V
+ valbase = toStructPointer(valptr.Addr()) // **V
+ }
+
+ // Decode.
+ // This parses a restricted wire format, namely the encoding of a message
+ // with two fields. See enc_new_map for the format.
+ for o.index < oi {
+ // tagcode for key and value properties are always a single byte
+ // because they have tags 1 and 2.
+ tagcode := o.buf[o.index]
+ o.index++
+ switch tagcode {
+ case p.mkeyprop.tagcode[0]:
+ if err := p.mkeyprop.dec(o, p.mkeyprop, keybase); err != nil {
+ return err
+ }
+ case p.mvalprop.tagcode[0]:
+ if err := p.mvalprop.dec(o, p.mvalprop, valbase); err != nil {
+ return err
+ }
+ default:
+ // TODO: Should we silently skip this instead?
+ return fmt.Errorf("proto: bad map data tag %d", raw[0])
+ }
+ }
+ keyelem, valelem := keyptr.Elem(), valptr.Elem()
+ if !keyelem.IsValid() {
+ keyelem = reflect.Zero(p.mtype.Key())
+ }
+ if !valelem.IsValid() {
+ valelem = reflect.Zero(p.mtype.Elem())
+ }
+
+ v.SetMapIndex(keyelem, valelem)
+ return nil
+}
+
+// Decode a group.
+func (o *Buffer) dec_struct_group(p *Properties, base structPointer) error {
+ bas := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(bas) {
+ // allocate new nested message
+ bas = toStructPointer(reflect.New(p.stype))
+ structPointer_SetStructPointer(base, p.field, bas)
+ }
+ return o.unmarshalType(p.stype, p.sprop, true, bas)
+}
+
+// Decode an embedded message.
+func (o *Buffer) dec_struct_message(p *Properties, base structPointer) (err error) {
+ raw, e := o.DecodeRawBytes(false)
+ if e != nil {
+ return e
+ }
+
+ bas := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(bas) {
+ // allocate new nested message
+ bas = toStructPointer(reflect.New(p.stype))
+ structPointer_SetStructPointer(base, p.field, bas)
+ }
+
+ // If the object can unmarshal itself, let it.
+ if p.isUnmarshaler {
+ iv := structPointer_Interface(bas, p.stype)
+ return iv.(Unmarshaler).Unmarshal(raw)
+ }
+
+ obuf := o.buf
+ oi := o.index
+ o.buf = raw
+ o.index = 0
+
+ err = o.unmarshalType(p.stype, p.sprop, false, bas)
+ o.buf = obuf
+ o.index = oi
+
+ return err
+}
+
+// Decode a slice of embedded messages.
+func (o *Buffer) dec_slice_struct_message(p *Properties, base structPointer) error {
+ return o.dec_slice_struct(p, false, base)
+}
+
+// Decode a slice of embedded groups.
+func (o *Buffer) dec_slice_struct_group(p *Properties, base structPointer) error {
+ return o.dec_slice_struct(p, true, base)
+}
+
+// Decode a slice of structs ([]*struct).
+func (o *Buffer) dec_slice_struct(p *Properties, is_group bool, base structPointer) error {
+ v := reflect.New(p.stype)
+ bas := toStructPointer(v)
+ structPointer_StructPointerSlice(base, p.field).Append(bas)
+
+ if is_group {
+ err := o.unmarshalType(p.stype, p.sprop, is_group, bas)
+ return err
+ }
+
+ raw, err := o.DecodeRawBytes(false)
+ if err != nil {
+ return err
+ }
+
+ // If the object can unmarshal itself, let it.
+ if p.isUnmarshaler {
+ iv := v.Interface()
+ return iv.(Unmarshaler).Unmarshal(raw)
+ }
+
+ obuf := o.buf
+ oi := o.index
+ o.buf = raw
+ o.index = 0
+
+ err = o.unmarshalType(p.stype, p.sprop, is_group, bas)
+
+ o.buf = obuf
+ o.index = oi
+
+ return err
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+/*
+ * Routines for encoding data into the wire format for protocol buffers.
+ */
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+ "sort"
+)
+
+// RequiredNotSetError is the error returned if Marshal is called with
+// a protocol buffer struct whose required fields have not
+// all been initialized. It is also the error returned if Unmarshal is
+// called with an encoded protocol buffer that does not include all the
+// required fields.
+//
+// When printed, RequiredNotSetError reports the first unset required field in a
+// message. If the field cannot be precisely determined, it is reported as
+// "{Unknown}".
+type RequiredNotSetError struct {
+ field string
+}
+
+func (e *RequiredNotSetError) Error() string {
+ return fmt.Sprintf("proto: required field %q not set", e.field)
+}
+
+var (
+ // errRepeatedHasNil is the error returned if Marshal is called with
+ // a struct with a repeated field containing a nil element.
+ errRepeatedHasNil = errors.New("proto: repeated field has nil element")
+
+ // errOneofHasNil is the error returned if Marshal is called with
+ // a struct with a oneof field containing a nil element.
+ errOneofHasNil = errors.New("proto: oneof field has nil value")
+
+ // ErrNil is the error returned if Marshal is called with nil.
+ ErrNil = errors.New("proto: Marshal called with nil")
+
+ // ErrTooLarge is the error returned if Marshal is called with a
+ // message that encodes to >2GB.
+ ErrTooLarge = errors.New("proto: message encodes to over 2 GB")
+)
+
+// The fundamental encoders that put bytes on the wire.
+// Those that take integer types all accept uint64 and are
+// therefore of type valueEncoder.
+
+const maxVarintBytes = 10 // maximum length of a varint
+
+// maxMarshalSize is the largest allowed size of an encoded protobuf,
+// since C++ and Java use signed int32s for the size.
+const maxMarshalSize = 1<<31 - 1
+
+// EncodeVarint returns the varint encoding of x.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+// Not used by the package itself, but helpful to clients
+// wishing to use the same encoding.
+func EncodeVarint(x uint64) []byte {
+ var buf [maxVarintBytes]byte
+ var n int
+ for n = 0; x > 127; n++ {
+ buf[n] = 0x80 | uint8(x&0x7F)
+ x >>= 7
+ }
+ buf[n] = uint8(x)
+ n++
+ return buf[0:n]
+}
+
+// EncodeVarint writes a varint-encoded integer to the Buffer.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+func (p *Buffer) EncodeVarint(x uint64) error {
+ for x >= 1<<7 {
+ p.buf = append(p.buf, uint8(x&0x7f|0x80))
+ x >>= 7
+ }
+ p.buf = append(p.buf, uint8(x))
+ return nil
+}
+
+// SizeVarint returns the varint encoding size of an integer.
+func SizeVarint(x uint64) int {
+ return sizeVarint(x)
+}
+
+func sizeVarint(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+
+// EncodeFixed64 writes a 64-bit integer to the Buffer.
+// This is the format for the
+// fixed64, sfixed64, and double protocol buffer types.
+func (p *Buffer) EncodeFixed64(x uint64) error {
+ p.buf = append(p.buf,
+ uint8(x),
+ uint8(x>>8),
+ uint8(x>>16),
+ uint8(x>>24),
+ uint8(x>>32),
+ uint8(x>>40),
+ uint8(x>>48),
+ uint8(x>>56))
+ return nil
+}
+
+func sizeFixed64(x uint64) int {
+ return 8
+}
+
+// EncodeFixed32 writes a 32-bit integer to the Buffer.
+// This is the format for the
+// fixed32, sfixed32, and float protocol buffer types.
+func (p *Buffer) EncodeFixed32(x uint64) error {
+ p.buf = append(p.buf,
+ uint8(x),
+ uint8(x>>8),
+ uint8(x>>16),
+ uint8(x>>24))
+ return nil
+}
+
+func sizeFixed32(x uint64) int {
+ return 4
+}
+
+// EncodeZigzag64 writes a zigzag-encoded 64-bit integer
+// to the Buffer.
+// This is the format used for the sint64 protocol buffer type.
+func (p *Buffer) EncodeZigzag64(x uint64) error {
+ // use signed number to get arithmetic right shift.
+ return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+
+func sizeZigzag64(x uint64) int {
+ return sizeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+
+// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
+// to the Buffer.
+// This is the format used for the sint32 protocol buffer type.
+func (p *Buffer) EncodeZigzag32(x uint64) error {
+ // use signed number to get arithmetic right shift.
+ return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
+}
+
+func sizeZigzag32(x uint64) int {
+ return sizeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
+}
+
+// EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
+// This is the format used for the bytes protocol buffer
+// type and for embedded messages.
+func (p *Buffer) EncodeRawBytes(b []byte) error {
+ p.EncodeVarint(uint64(len(b)))
+ p.buf = append(p.buf, b...)
+ return nil
+}
+
+func sizeRawBytes(b []byte) int {
+ return sizeVarint(uint64(len(b))) +
+ len(b)
+}
+
+// EncodeStringBytes writes an encoded string to the Buffer.
+// This is the format used for the proto2 string type.
+func (p *Buffer) EncodeStringBytes(s string) error {
+ p.EncodeVarint(uint64(len(s)))
+ p.buf = append(p.buf, s...)
+ return nil
+}
+
+func sizeStringBytes(s string) int {
+ return sizeVarint(uint64(len(s))) +
+ len(s)
+}
+
+// Marshaler is the interface representing objects that can marshal themselves.
+type Marshaler interface {
+ Marshal() ([]byte, error)
+}
+
+// Marshal takes the protocol buffer
+// and encodes it into the wire format, returning the data.
+func Marshal(pb Message) ([]byte, error) {
+ // Can the object marshal itself?
+ if m, ok := pb.(Marshaler); ok {
+ return m.Marshal()
+ }
+ p := NewBuffer(nil)
+ err := p.Marshal(pb)
+ var state errorState
+ if err != nil && !state.shouldContinue(err, nil) {
+ return nil, err
+ }
+ if p.buf == nil && err == nil {
+ // Return a non-nil slice on success.
+ return []byte{}, nil
+ }
+ return p.buf, err
+}
+
+// EncodeMessage writes the protocol buffer to the Buffer,
+// prefixed by a varint-encoded length.
+func (p *Buffer) EncodeMessage(pb Message) error {
+ t, base, err := getbase(pb)
+ if structPointer_IsNil(base) {
+ return ErrNil
+ }
+ if err == nil {
+ var state errorState
+ err = p.enc_len_struct(GetProperties(t.Elem()), base, &state)
+ }
+ return err
+}
+
+// Marshal takes the protocol buffer
+// and encodes it into the wire format, writing the result to the
+// Buffer.
+func (p *Buffer) Marshal(pb Message) error {
+ // Can the object marshal itself?
+ if m, ok := pb.(Marshaler); ok {
+ data, err := m.Marshal()
+ if err != nil {
+ return err
+ }
+ p.buf = append(p.buf, data...)
+ return nil
+ }
+
+ t, base, err := getbase(pb)
+ if structPointer_IsNil(base) {
+ return ErrNil
+ }
+ if err == nil {
+ err = p.enc_struct(GetProperties(t.Elem()), base)
+ }
+
+ if collectStats {
+ stats.Encode++
+ }
+
+ if len(p.buf) > maxMarshalSize {
+ return ErrTooLarge
+ }
+ return err
+}
+
+// Size returns the encoded size of a protocol buffer.
+func Size(pb Message) (n int) {
+ // Can the object marshal itself? If so, Size is slow.
+ // TODO: add Size to Marshaler, or add a Sizer interface.
+ if m, ok := pb.(Marshaler); ok {
+ b, _ := m.Marshal()
+ return len(b)
+ }
+
+ t, base, err := getbase(pb)
+ if structPointer_IsNil(base) {
+ return 0
+ }
+ if err == nil {
+ n = size_struct(GetProperties(t.Elem()), base)
+ }
+
+ if collectStats {
+ stats.Size++
+ }
+
+ return
+}
+
+// Individual type encoders.
+
+// Encode a bool.
+func (o *Buffer) enc_bool(p *Properties, base structPointer) error {
+ v := *structPointer_Bool(base, p.field)
+ if v == nil {
+ return ErrNil
+ }
+ x := 0
+ if *v {
+ x = 1
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+func (o *Buffer) enc_proto3_bool(p *Properties, base structPointer) error {
+ v := *structPointer_BoolVal(base, p.field)
+ if !v {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, 1)
+ return nil
+}
+
+func size_bool(p *Properties, base structPointer) int {
+ v := *structPointer_Bool(base, p.field)
+ if v == nil {
+ return 0
+ }
+ return len(p.tagcode) + 1 // each bool takes exactly one byte
+}
+
+func size_proto3_bool(p *Properties, base structPointer) int {
+ v := *structPointer_BoolVal(base, p.field)
+ if !v && !p.oneof {
+ return 0
+ }
+ return len(p.tagcode) + 1 // each bool takes exactly one byte
+}
+
+// Encode an int32.
+func (o *Buffer) enc_int32(p *Properties, base structPointer) error {
+ v := structPointer_Word32(base, p.field)
+ if word32_IsNil(v) {
+ return ErrNil
+ }
+ x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+func (o *Buffer) enc_proto3_int32(p *Properties, base structPointer) error {
+ v := structPointer_Word32Val(base, p.field)
+ x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range
+ if x == 0 {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+func size_int32(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word32(base, p.field)
+ if word32_IsNil(v) {
+ return 0
+ }
+ x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range
+ n += len(p.tagcode)
+ n += p.valSize(uint64(x))
+ return
+}
+
+func size_proto3_int32(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word32Val(base, p.field)
+ x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range
+ if x == 0 && !p.oneof {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += p.valSize(uint64(x))
+ return
+}
+
+// Encode a uint32.
+// Exactly the same as int32, except for no sign extension.
+func (o *Buffer) enc_uint32(p *Properties, base structPointer) error {
+ v := structPointer_Word32(base, p.field)
+ if word32_IsNil(v) {
+ return ErrNil
+ }
+ x := word32_Get(v)
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+func (o *Buffer) enc_proto3_uint32(p *Properties, base structPointer) error {
+ v := structPointer_Word32Val(base, p.field)
+ x := word32Val_Get(v)
+ if x == 0 {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+func size_uint32(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word32(base, p.field)
+ if word32_IsNil(v) {
+ return 0
+ }
+ x := word32_Get(v)
+ n += len(p.tagcode)
+ n += p.valSize(uint64(x))
+ return
+}
+
+func size_proto3_uint32(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word32Val(base, p.field)
+ x := word32Val_Get(v)
+ if x == 0 && !p.oneof {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += p.valSize(uint64(x))
+ return
+}
+
+// Encode an int64.
+func (o *Buffer) enc_int64(p *Properties, base structPointer) error {
+ v := structPointer_Word64(base, p.field)
+ if word64_IsNil(v) {
+ return ErrNil
+ }
+ x := word64_Get(v)
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, x)
+ return nil
+}
+
+func (o *Buffer) enc_proto3_int64(p *Properties, base structPointer) error {
+ v := structPointer_Word64Val(base, p.field)
+ x := word64Val_Get(v)
+ if x == 0 {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, x)
+ return nil
+}
+
+func size_int64(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word64(base, p.field)
+ if word64_IsNil(v) {
+ return 0
+ }
+ x := word64_Get(v)
+ n += len(p.tagcode)
+ n += p.valSize(x)
+ return
+}
+
+func size_proto3_int64(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word64Val(base, p.field)
+ x := word64Val_Get(v)
+ if x == 0 && !p.oneof {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += p.valSize(x)
+ return
+}
+
+// Encode a string.
+func (o *Buffer) enc_string(p *Properties, base structPointer) error {
+ v := *structPointer_String(base, p.field)
+ if v == nil {
+ return ErrNil
+ }
+ x := *v
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeStringBytes(x)
+ return nil
+}
+
+func (o *Buffer) enc_proto3_string(p *Properties, base structPointer) error {
+ v := *structPointer_StringVal(base, p.field)
+ if v == "" {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeStringBytes(v)
+ return nil
+}
+
+func size_string(p *Properties, base structPointer) (n int) {
+ v := *structPointer_String(base, p.field)
+ if v == nil {
+ return 0
+ }
+ x := *v
+ n += len(p.tagcode)
+ n += sizeStringBytes(x)
+ return
+}
+
+func size_proto3_string(p *Properties, base structPointer) (n int) {
+ v := *structPointer_StringVal(base, p.field)
+ if v == "" && !p.oneof {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += sizeStringBytes(v)
+ return
+}
+
+// All protocol buffer fields are nillable, but be careful.
+func isNil(v reflect.Value) bool {
+ switch v.Kind() {
+ case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
+ return v.IsNil()
+ }
+ return false
+}
+
+// Encode a message struct.
+func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error {
+ var state errorState
+ structp := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(structp) {
+ return ErrNil
+ }
+
+ // Can the object marshal itself?
+ if p.isMarshaler {
+ m := structPointer_Interface(structp, p.stype).(Marshaler)
+ data, err := m.Marshal()
+ if err != nil && !state.shouldContinue(err, nil) {
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ return state.err
+ }
+
+ o.buf = append(o.buf, p.tagcode...)
+ return o.enc_len_struct(p.sprop, structp, &state)
+}
+
+func size_struct_message(p *Properties, base structPointer) int {
+ structp := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(structp) {
+ return 0
+ }
+
+ // Can the object marshal itself?
+ if p.isMarshaler {
+ m := structPointer_Interface(structp, p.stype).(Marshaler)
+ data, _ := m.Marshal()
+ n0 := len(p.tagcode)
+ n1 := sizeRawBytes(data)
+ return n0 + n1
+ }
+
+ n0 := len(p.tagcode)
+ n1 := size_struct(p.sprop, structp)
+ n2 := sizeVarint(uint64(n1)) // size of encoded length
+ return n0 + n1 + n2
+}
+
+// Encode a group struct.
+func (o *Buffer) enc_struct_group(p *Properties, base structPointer) error {
+ var state errorState
+ b := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(b) {
+ return ErrNil
+ }
+
+ o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
+ err := o.enc_struct(p.sprop, b)
+ if err != nil && !state.shouldContinue(err, nil) {
+ return err
+ }
+ o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
+ return state.err
+}
+
+func size_struct_group(p *Properties, base structPointer) (n int) {
+ b := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(b) {
+ return 0
+ }
+
+ n += sizeVarint(uint64((p.Tag << 3) | WireStartGroup))
+ n += size_struct(p.sprop, b)
+ n += sizeVarint(uint64((p.Tag << 3) | WireEndGroup))
+ return
+}
+
+// Encode a slice of bools ([]bool).
+func (o *Buffer) enc_slice_bool(p *Properties, base structPointer) error {
+ s := *structPointer_BoolSlice(base, p.field)
+ l := len(s)
+ if l == 0 {
+ return ErrNil
+ }
+ for _, x := range s {
+ o.buf = append(o.buf, p.tagcode...)
+ v := uint64(0)
+ if x {
+ v = 1
+ }
+ p.valEnc(o, v)
+ }
+ return nil
+}
+
+func size_slice_bool(p *Properties, base structPointer) int {
+ s := *structPointer_BoolSlice(base, p.field)
+ l := len(s)
+ if l == 0 {
+ return 0
+ }
+ return l * (len(p.tagcode) + 1) // each bool takes exactly one byte
+}
+
+// Encode a slice of bools ([]bool) in packed format.
+func (o *Buffer) enc_slice_packed_bool(p *Properties, base structPointer) error {
+ s := *structPointer_BoolSlice(base, p.field)
+ l := len(s)
+ if l == 0 {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeVarint(uint64(l)) // each bool takes exactly one byte
+ for _, x := range s {
+ v := uint64(0)
+ if x {
+ v = 1
+ }
+ p.valEnc(o, v)
+ }
+ return nil
+}
+
+func size_slice_packed_bool(p *Properties, base structPointer) (n int) {
+ s := *structPointer_BoolSlice(base, p.field)
+ l := len(s)
+ if l == 0 {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += sizeVarint(uint64(l))
+ n += l // each bool takes exactly one byte
+ return
+}
+
+// Encode a slice of bytes ([]byte).
+func (o *Buffer) enc_slice_byte(p *Properties, base structPointer) error {
+ s := *structPointer_Bytes(base, p.field)
+ if s == nil {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(s)
+ return nil
+}
+
+func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer) error {
+ s := *structPointer_Bytes(base, p.field)
+ if len(s) == 0 {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(s)
+ return nil
+}
+
+func size_slice_byte(p *Properties, base structPointer) (n int) {
+ s := *structPointer_Bytes(base, p.field)
+ if s == nil && !p.oneof {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += sizeRawBytes(s)
+ return
+}
+
+func size_proto3_slice_byte(p *Properties, base structPointer) (n int) {
+ s := *structPointer_Bytes(base, p.field)
+ if len(s) == 0 && !p.oneof {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += sizeRawBytes(s)
+ return
+}
+
+// Encode a slice of int32s ([]int32).
+func (o *Buffer) enc_slice_int32(p *Properties, base structPointer) error {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return ErrNil
+ }
+ for i := 0; i < l; i++ {
+ o.buf = append(o.buf, p.tagcode...)
+ x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
+ p.valEnc(o, uint64(x))
+ }
+ return nil
+}
+
+func size_slice_int32(p *Properties, base structPointer) (n int) {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return 0
+ }
+ for i := 0; i < l; i++ {
+ n += len(p.tagcode)
+ x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
+ n += p.valSize(uint64(x))
+ }
+ return
+}
+
+// Encode a slice of int32s ([]int32) in packed format.
+func (o *Buffer) enc_slice_packed_int32(p *Properties, base structPointer) error {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return ErrNil
+ }
+ // TODO: Reuse a Buffer.
+ buf := NewBuffer(nil)
+ for i := 0; i < l; i++ {
+ x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
+ p.valEnc(buf, uint64(x))
+ }
+
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeVarint(uint64(len(buf.buf)))
+ o.buf = append(o.buf, buf.buf...)
+ return nil
+}
+
+func size_slice_packed_int32(p *Properties, base structPointer) (n int) {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return 0
+ }
+ var bufSize int
+ for i := 0; i < l; i++ {
+ x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
+ bufSize += p.valSize(uint64(x))
+ }
+
+ n += len(p.tagcode)
+ n += sizeVarint(uint64(bufSize))
+ n += bufSize
+ return
+}
+
+// Encode a slice of uint32s ([]uint32).
+// Exactly the same as int32, except for no sign extension.
+func (o *Buffer) enc_slice_uint32(p *Properties, base structPointer) error {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return ErrNil
+ }
+ for i := 0; i < l; i++ {
+ o.buf = append(o.buf, p.tagcode...)
+ x := s.Index(i)
+ p.valEnc(o, uint64(x))
+ }
+ return nil
+}
+
+func size_slice_uint32(p *Properties, base structPointer) (n int) {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return 0
+ }
+ for i := 0; i < l; i++ {
+ n += len(p.tagcode)
+ x := s.Index(i)
+ n += p.valSize(uint64(x))
+ }
+ return
+}
+
+// Encode a slice of uint32s ([]uint32) in packed format.
+// Exactly the same as int32, except for no sign extension.
+func (o *Buffer) enc_slice_packed_uint32(p *Properties, base structPointer) error {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return ErrNil
+ }
+ // TODO: Reuse a Buffer.
+ buf := NewBuffer(nil)
+ for i := 0; i < l; i++ {
+ p.valEnc(buf, uint64(s.Index(i)))
+ }
+
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeVarint(uint64(len(buf.buf)))
+ o.buf = append(o.buf, buf.buf...)
+ return nil
+}
+
+func size_slice_packed_uint32(p *Properties, base structPointer) (n int) {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return 0
+ }
+ var bufSize int
+ for i := 0; i < l; i++ {
+ bufSize += p.valSize(uint64(s.Index(i)))
+ }
+
+ n += len(p.tagcode)
+ n += sizeVarint(uint64(bufSize))
+ n += bufSize
+ return
+}
+
+// Encode a slice of int64s ([]int64).
+func (o *Buffer) enc_slice_int64(p *Properties, base structPointer) error {
+ s := structPointer_Word64Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return ErrNil
+ }
+ for i := 0; i < l; i++ {
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, s.Index(i))
+ }
+ return nil
+}
+
+func size_slice_int64(p *Properties, base structPointer) (n int) {
+ s := structPointer_Word64Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return 0
+ }
+ for i := 0; i < l; i++ {
+ n += len(p.tagcode)
+ n += p.valSize(s.Index(i))
+ }
+ return
+}
+
+// Encode a slice of int64s ([]int64) in packed format.
+func (o *Buffer) enc_slice_packed_int64(p *Properties, base structPointer) error {
+ s := structPointer_Word64Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return ErrNil
+ }
+ // TODO: Reuse a Buffer.
+ buf := NewBuffer(nil)
+ for i := 0; i < l; i++ {
+ p.valEnc(buf, s.Index(i))
+ }
+
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeVarint(uint64(len(buf.buf)))
+ o.buf = append(o.buf, buf.buf...)
+ return nil
+}
+
+func size_slice_packed_int64(p *Properties, base structPointer) (n int) {
+ s := structPointer_Word64Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return 0
+ }
+ var bufSize int
+ for i := 0; i < l; i++ {
+ bufSize += p.valSize(s.Index(i))
+ }
+
+ n += len(p.tagcode)
+ n += sizeVarint(uint64(bufSize))
+ n += bufSize
+ return
+}
+
+// Encode a slice of slice of bytes ([][]byte).
+func (o *Buffer) enc_slice_slice_byte(p *Properties, base structPointer) error {
+ ss := *structPointer_BytesSlice(base, p.field)
+ l := len(ss)
+ if l == 0 {
+ return ErrNil
+ }
+ for i := 0; i < l; i++ {
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(ss[i])
+ }
+ return nil
+}
+
+func size_slice_slice_byte(p *Properties, base structPointer) (n int) {
+ ss := *structPointer_BytesSlice(base, p.field)
+ l := len(ss)
+ if l == 0 {
+ return 0
+ }
+ n += l * len(p.tagcode)
+ for i := 0; i < l; i++ {
+ n += sizeRawBytes(ss[i])
+ }
+ return
+}
+
+// Encode a slice of strings ([]string).
+func (o *Buffer) enc_slice_string(p *Properties, base structPointer) error {
+ ss := *structPointer_StringSlice(base, p.field)
+ l := len(ss)
+ for i := 0; i < l; i++ {
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeStringBytes(ss[i])
+ }
+ return nil
+}
+
+func size_slice_string(p *Properties, base structPointer) (n int) {
+ ss := *structPointer_StringSlice(base, p.field)
+ l := len(ss)
+ n += l * len(p.tagcode)
+ for i := 0; i < l; i++ {
+ n += sizeStringBytes(ss[i])
+ }
+ return
+}
+
+// Encode a slice of message structs ([]*struct).
+func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) error {
+ var state errorState
+ s := structPointer_StructPointerSlice(base, p.field)
+ l := s.Len()
+
+ for i := 0; i < l; i++ {
+ structp := s.Index(i)
+ if structPointer_IsNil(structp) {
+ return errRepeatedHasNil
+ }
+
+ // Can the object marshal itself?
+ if p.isMarshaler {
+ m := structPointer_Interface(structp, p.stype).(Marshaler)
+ data, err := m.Marshal()
+ if err != nil && !state.shouldContinue(err, nil) {
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ continue
+ }
+
+ o.buf = append(o.buf, p.tagcode...)
+ err := o.enc_len_struct(p.sprop, structp, &state)
+ if err != nil && !state.shouldContinue(err, nil) {
+ if err == ErrNil {
+ return errRepeatedHasNil
+ }
+ return err
+ }
+ }
+ return state.err
+}
+
+func size_slice_struct_message(p *Properties, base structPointer) (n int) {
+ s := structPointer_StructPointerSlice(base, p.field)
+ l := s.Len()
+ n += l * len(p.tagcode)
+ for i := 0; i < l; i++ {
+ structp := s.Index(i)
+ if structPointer_IsNil(structp) {
+ return // return the size up to this point
+ }
+
+ // Can the object marshal itself?
+ if p.isMarshaler {
+ m := structPointer_Interface(structp, p.stype).(Marshaler)
+ data, _ := m.Marshal()
+ n += len(p.tagcode)
+ n += sizeRawBytes(data)
+ continue
+ }
+
+ n0 := size_struct(p.sprop, structp)
+ n1 := sizeVarint(uint64(n0)) // size of encoded length
+ n += n0 + n1
+ }
+ return
+}
+
+// Encode a slice of group structs ([]*struct).
+func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error {
+ var state errorState
+ s := structPointer_StructPointerSlice(base, p.field)
+ l := s.Len()
+
+ for i := 0; i < l; i++ {
+ b := s.Index(i)
+ if structPointer_IsNil(b) {
+ return errRepeatedHasNil
+ }
+
+ o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
+
+ err := o.enc_struct(p.sprop, b)
+
+ if err != nil && !state.shouldContinue(err, nil) {
+ if err == ErrNil {
+ return errRepeatedHasNil
+ }
+ return err
+ }
+
+ o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
+ }
+ return state.err
+}
+
+func size_slice_struct_group(p *Properties, base structPointer) (n int) {
+ s := structPointer_StructPointerSlice(base, p.field)
+ l := s.Len()
+
+ n += l * sizeVarint(uint64((p.Tag<<3)|WireStartGroup))
+ n += l * sizeVarint(uint64((p.Tag<<3)|WireEndGroup))
+ for i := 0; i < l; i++ {
+ b := s.Index(i)
+ if structPointer_IsNil(b) {
+ return // return size up to this point
+ }
+
+ n += size_struct(p.sprop, b)
+ }
+ return
+}
+
+// Encode an extension map.
+func (o *Buffer) enc_map(p *Properties, base structPointer) error {
+ exts := structPointer_ExtMap(base, p.field)
+ if err := encodeExtensionsMap(*exts); err != nil {
+ return err
+ }
+
+ return o.enc_map_body(*exts)
+}
+
+func (o *Buffer) enc_exts(p *Properties, base structPointer) error {
+ exts := structPointer_Extensions(base, p.field)
+ if err := encodeExtensions(exts); err != nil {
+ return err
+ }
+ v, _ := exts.extensionsRead()
+
+ return o.enc_map_body(v)
+}
+
+func (o *Buffer) enc_map_body(v map[int32]Extension) error {
+ // Fast-path for common cases: zero or one extensions.
+ if len(v) <= 1 {
+ for _, e := range v {
+ o.buf = append(o.buf, e.enc...)
+ }
+ return nil
+ }
+
+ // Sort keys to provide a deterministic encoding.
+ keys := make([]int, 0, len(v))
+ for k := range v {
+ keys = append(keys, int(k))
+ }
+ sort.Ints(keys)
+
+ for _, k := range keys {
+ o.buf = append(o.buf, v[int32(k)].enc...)
+ }
+ return nil
+}
+
+func size_map(p *Properties, base structPointer) int {
+ v := structPointer_ExtMap(base, p.field)
+ return extensionsMapSize(*v)
+}
+
+func size_exts(p *Properties, base structPointer) int {
+ v := structPointer_Extensions(base, p.field)
+ return extensionsSize(v)
+}
+
+// Encode a map field.
+func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
+ var state errorState // XXX: or do we need to plumb this through?
+
+ /*
+ A map defined as
+ map<key_type, value_type> map_field = N;
+ is encoded in the same way as
+ message MapFieldEntry {
+ key_type key = 1;
+ value_type value = 2;
+ }
+ repeated MapFieldEntry map_field = N;
+ */
+
+ v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V
+ if v.Len() == 0 {
+ return nil
+ }
+
+ keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype)
+
+ enc := func() error {
+ if err := p.mkeyprop.enc(o, p.mkeyprop, keybase); err != nil {
+ return err
+ }
+ if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil && err != ErrNil {
+ return err
+ }
+ return nil
+ }
+
+ // Don't sort map keys. It is not required by the spec, and C++ doesn't do it.
+ for _, key := range v.MapKeys() {
+ val := v.MapIndex(key)
+
+ keycopy.Set(key)
+ valcopy.Set(val)
+
+ o.buf = append(o.buf, p.tagcode...)
+ if err := o.enc_len_thing(enc, &state); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func size_new_map(p *Properties, base structPointer) int {
+ v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V
+
+ keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype)
+
+ n := 0
+ for _, key := range v.MapKeys() {
+ val := v.MapIndex(key)
+ keycopy.Set(key)
+ valcopy.Set(val)
+
+ // Tag codes for key and val are the responsibility of the sub-sizer.
+ keysize := p.mkeyprop.size(p.mkeyprop, keybase)
+ valsize := p.mvalprop.size(p.mvalprop, valbase)
+ entry := keysize + valsize
+ // Add on tag code and length of map entry itself.
+ n += len(p.tagcode) + sizeVarint(uint64(entry)) + entry
+ }
+ return n
+}
+
+// mapEncodeScratch returns a new reflect.Value matching the map's value type,
+// and a structPointer suitable for passing to an encoder or sizer.
+func mapEncodeScratch(mapType reflect.Type) (keycopy, valcopy reflect.Value, keybase, valbase structPointer) {
+ // Prepare addressable doubly-indirect placeholders for the key and value types.
+ // This is needed because the element-type encoders expect **T, but the map iteration produces T.
+
+ keycopy = reflect.New(mapType.Key()).Elem() // addressable K
+ keyptr := reflect.New(reflect.PtrTo(keycopy.Type())).Elem() // addressable *K
+ keyptr.Set(keycopy.Addr()) //
+ keybase = toStructPointer(keyptr.Addr()) // **K
+
+ // Value types are more varied and require special handling.
+ switch mapType.Elem().Kind() {
+ case reflect.Slice:
+ // []byte
+ var dummy []byte
+ valcopy = reflect.ValueOf(&dummy).Elem() // addressable []byte
+ valbase = toStructPointer(valcopy.Addr())
+ case reflect.Ptr:
+ // message; the generated field type is map[K]*Msg (so V is *Msg),
+ // so we only need one level of indirection.
+ valcopy = reflect.New(mapType.Elem()).Elem() // addressable V
+ valbase = toStructPointer(valcopy.Addr())
+ default:
+ // everything else
+ valcopy = reflect.New(mapType.Elem()).Elem() // addressable V
+ valptr := reflect.New(reflect.PtrTo(valcopy.Type())).Elem() // addressable *V
+ valptr.Set(valcopy.Addr()) //
+ valbase = toStructPointer(valptr.Addr()) // **V
+ }
+ return
+}
+
+// Encode a struct.
+func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
+ var state errorState
+ // Encode fields in tag order so that decoders may use optimizations
+ // that depend on the ordering.
+ // https://developers.google.com/protocol-buffers/docs/encoding#order
+ for _, i := range prop.order {
+ p := prop.Prop[i]
+ if p.enc != nil {
+ err := p.enc(o, p, base)
+ if err != nil {
+ if err == ErrNil {
+ if p.Required && state.err == nil {
+ state.err = &RequiredNotSetError{p.Name}
+ }
+ } else if err == errRepeatedHasNil {
+ // Give more context to nil values in repeated fields.
+ return errors.New("repeated field " + p.OrigName + " has nil element")
+ } else if !state.shouldContinue(err, p) {
+ return err
+ }
+ }
+ if len(o.buf) > maxMarshalSize {
+ return ErrTooLarge
+ }
+ }
+ }
+
+ // Do oneof fields.
+ if prop.oneofMarshaler != nil {
+ m := structPointer_Interface(base, prop.stype).(Message)
+ if err := prop.oneofMarshaler(m, o); err == ErrNil {
+ return errOneofHasNil
+ } else if err != nil {
+ return err
+ }
+ }
+
+ // Add unrecognized fields at the end.
+ if prop.unrecField.IsValid() {
+ v := *structPointer_Bytes(base, prop.unrecField)
+ if len(o.buf)+len(v) > maxMarshalSize {
+ return ErrTooLarge
+ }
+ if len(v) > 0 {
+ o.buf = append(o.buf, v...)
+ }
+ }
+
+ return state.err
+}
+
+func size_struct(prop *StructProperties, base structPointer) (n int) {
+ for _, i := range prop.order {
+ p := prop.Prop[i]
+ if p.size != nil {
+ n += p.size(p, base)
+ }
+ }
+
+ // Add unrecognized fields at the end.
+ if prop.unrecField.IsValid() {
+ v := *structPointer_Bytes(base, prop.unrecField)
+ n += len(v)
+ }
+
+ // Factor in any oneof fields.
+ if prop.oneofSizer != nil {
+ m := structPointer_Interface(base, prop.stype).(Message)
+ n += prop.oneofSizer(m)
+ }
+
+ return
+}
+
+var zeroes [20]byte // longer than any conceivable sizeVarint
+
+// Encode a struct, preceded by its encoded length (as a varint).
+func (o *Buffer) enc_len_struct(prop *StructProperties, base structPointer, state *errorState) error {
+ return o.enc_len_thing(func() error { return o.enc_struct(prop, base) }, state)
+}
+
+// Encode something, preceded by its encoded length (as a varint).
+func (o *Buffer) enc_len_thing(enc func() error, state *errorState) error {
+ iLen := len(o.buf)
+ o.buf = append(o.buf, 0, 0, 0, 0) // reserve four bytes for length
+ iMsg := len(o.buf)
+ err := enc()
+ if err != nil && !state.shouldContinue(err, nil) {
+ return err
+ }
+ lMsg := len(o.buf) - iMsg
+ lLen := sizeVarint(uint64(lMsg))
+ switch x := lLen - (iMsg - iLen); {
+ case x > 0: // actual length is x bytes larger than the space we reserved
+ // Move msg x bytes right.
+ o.buf = append(o.buf, zeroes[:x]...)
+ copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg])
+ case x < 0: // actual length is x bytes smaller than the space we reserved
+ // Move msg x bytes left.
+ copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg])
+ o.buf = o.buf[:len(o.buf)+x] // x is negative
+ }
+ // Encode the length in the reserved space.
+ o.buf = o.buf[:iLen]
+ o.EncodeVarint(uint64(lMsg))
+ o.buf = o.buf[:len(o.buf)+lMsg]
+ return state.err
+}
+
+// errorState maintains the first error that occurs and updates that error
+// with additional context.
+type errorState struct {
+ err error
+}
+
+// shouldContinue reports whether encoding should continue upon encountering the
+// given error. If the error is RequiredNotSetError, shouldContinue returns true
+// and, if this is the first appearance of that error, remembers it for future
+// reporting.
+//
+// If prop is not nil, it may update any error with additional context about the
+// field with the error.
+func (s *errorState) shouldContinue(err error, prop *Properties) bool {
+ // Ignore unset required fields.
+ reqNotSet, ok := err.(*RequiredNotSetError)
+ if !ok {
+ return false
+ }
+ if s.err == nil {
+ if prop != nil {
+ err = &RequiredNotSetError{prop.Name + "." + reqNotSet.field}
+ }
+ s.err = err
+ }
+ return true
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2011 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Protocol buffer comparison.
+
+package proto
+
+import (
+ "bytes"
+ "log"
+ "reflect"
+ "strings"
+)
+
+/*
+Equal returns true iff protocol buffers a and b are equal.
+The arguments must both be pointers to protocol buffer structs.
+
+Equality is defined in this way:
+ - Two messages are equal iff they are the same type,
+ corresponding fields are equal, unknown field sets
+ are equal, and extensions sets are equal.
+ - Two set scalar fields are equal iff their values are equal.
+ If the fields are of a floating-point type, remember that
+ NaN != x for all x, including NaN. If the message is defined
+ in a proto3 .proto file, fields are not "set"; specifically,
+ zero length proto3 "bytes" fields are equal (nil == {}).
+ - Two repeated fields are equal iff their lengths are the same,
+ and their corresponding elements are equal (a "bytes" field,
+ although represented by []byte, is not a repeated field)
+ - Two unset fields are equal.
+ - Two unknown field sets are equal if their current
+ encoded state is equal.
+ - Two extension sets are equal iff they have corresponding
+ elements that are pairwise equal.
+ - Every other combination of things are not equal.
+
+The return value is undefined if a and b are not protocol buffers.
+*/
+func Equal(a, b Message) bool {
+ if a == nil || b == nil {
+ return a == b
+ }
+ v1, v2 := reflect.ValueOf(a), reflect.ValueOf(b)
+ if v1.Type() != v2.Type() {
+ return false
+ }
+ if v1.Kind() == reflect.Ptr {
+ if v1.IsNil() {
+ return v2.IsNil()
+ }
+ if v2.IsNil() {
+ return false
+ }
+ v1, v2 = v1.Elem(), v2.Elem()
+ }
+ if v1.Kind() != reflect.Struct {
+ return false
+ }
+ return equalStruct(v1, v2)
+}
+
+// v1 and v2 are known to have the same type.
+func equalStruct(v1, v2 reflect.Value) bool {
+ sprop := GetProperties(v1.Type())
+ for i := 0; i < v1.NumField(); i++ {
+ f := v1.Type().Field(i)
+ if strings.HasPrefix(f.Name, "XXX_") {
+ continue
+ }
+ f1, f2 := v1.Field(i), v2.Field(i)
+ if f.Type.Kind() == reflect.Ptr {
+ if n1, n2 := f1.IsNil(), f2.IsNil(); n1 && n2 {
+ // both unset
+ continue
+ } else if n1 != n2 {
+ // set/unset mismatch
+ return false
+ }
+ b1, ok := f1.Interface().(raw)
+ if ok {
+ b2 := f2.Interface().(raw)
+ // RawMessage
+ if !bytes.Equal(b1.Bytes(), b2.Bytes()) {
+ return false
+ }
+ continue
+ }
+ f1, f2 = f1.Elem(), f2.Elem()
+ }
+ if !equalAny(f1, f2, sprop.Prop[i]) {
+ return false
+ }
+ }
+
+ if em1 := v1.FieldByName("XXX_InternalExtensions"); em1.IsValid() {
+ em2 := v2.FieldByName("XXX_InternalExtensions")
+ if !equalExtensions(v1.Type(), em1.Interface().(XXX_InternalExtensions), em2.Interface().(XXX_InternalExtensions)) {
+ return false
+ }
+ }
+
+ if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() {
+ em2 := v2.FieldByName("XXX_extensions")
+ if !equalExtMap(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) {
+ return false
+ }
+ }
+
+ uf := v1.FieldByName("XXX_unrecognized")
+ if !uf.IsValid() {
+ return true
+ }
+
+ u1 := uf.Bytes()
+ u2 := v2.FieldByName("XXX_unrecognized").Bytes()
+ if !bytes.Equal(u1, u2) {
+ return false
+ }
+
+ return true
+}
+
+// v1 and v2 are known to have the same type.
+// prop may be nil.
+func equalAny(v1, v2 reflect.Value, prop *Properties) bool {
+ if v1.Type() == protoMessageType {
+ m1, _ := v1.Interface().(Message)
+ m2, _ := v2.Interface().(Message)
+ return Equal(m1, m2)
+ }
+ switch v1.Kind() {
+ case reflect.Bool:
+ return v1.Bool() == v2.Bool()
+ case reflect.Float32, reflect.Float64:
+ return v1.Float() == v2.Float()
+ case reflect.Int32, reflect.Int64:
+ return v1.Int() == v2.Int()
+ case reflect.Interface:
+ // Probably a oneof field; compare the inner values.
+ n1, n2 := v1.IsNil(), v2.IsNil()
+ if n1 || n2 {
+ return n1 == n2
+ }
+ e1, e2 := v1.Elem(), v2.Elem()
+ if e1.Type() != e2.Type() {
+ return false
+ }
+ return equalAny(e1, e2, nil)
+ case reflect.Map:
+ if v1.Len() != v2.Len() {
+ return false
+ }
+ for _, key := range v1.MapKeys() {
+ val2 := v2.MapIndex(key)
+ if !val2.IsValid() {
+ // This key was not found in the second map.
+ return false
+ }
+ if !equalAny(v1.MapIndex(key), val2, nil) {
+ return false
+ }
+ }
+ return true
+ case reflect.Ptr:
+ // Maps may have nil values in them, so check for nil.
+ if v1.IsNil() && v2.IsNil() {
+ return true
+ }
+ if v1.IsNil() != v2.IsNil() {
+ return false
+ }
+ return equalAny(v1.Elem(), v2.Elem(), prop)
+ case reflect.Slice:
+ if v1.Type().Elem().Kind() == reflect.Uint8 {
+ // short circuit: []byte
+
+ // Edge case: if this is in a proto3 message, a zero length
+ // bytes field is considered the zero value.
+ if prop != nil && prop.proto3 && v1.Len() == 0 && v2.Len() == 0 {
+ return true
+ }
+ if v1.IsNil() != v2.IsNil() {
+ return false
+ }
+ return bytes.Equal(v1.Interface().([]byte), v2.Interface().([]byte))
+ }
+
+ if v1.Len() != v2.Len() {
+ return false
+ }
+ for i := 0; i < v1.Len(); i++ {
+ if !equalAny(v1.Index(i), v2.Index(i), prop) {
+ return false
+ }
+ }
+ return true
+ case reflect.String:
+ return v1.Interface().(string) == v2.Interface().(string)
+ case reflect.Struct:
+ return equalStruct(v1, v2)
+ case reflect.Uint32, reflect.Uint64:
+ return v1.Uint() == v2.Uint()
+ }
+
+ // unknown type, so not a protocol buffer
+ log.Printf("proto: don't know how to compare %v", v1)
+ return false
+}
+
+// base is the struct type that the extensions are based on.
+// x1 and x2 are InternalExtensions.
+func equalExtensions(base reflect.Type, x1, x2 XXX_InternalExtensions) bool {
+ em1, _ := x1.extensionsRead()
+ em2, _ := x2.extensionsRead()
+ return equalExtMap(base, em1, em2)
+}
+
+func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
+ if len(em1) != len(em2) {
+ return false
+ }
+
+ for extNum, e1 := range em1 {
+ e2, ok := em2[extNum]
+ if !ok {
+ return false
+ }
+
+ m1, m2 := e1.value, e2.value
+
+ if m1 != nil && m2 != nil {
+ // Both are unencoded.
+ if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
+ return false
+ }
+ continue
+ }
+
+ // At least one is encoded. To do a semantically correct comparison
+ // we need to unmarshal them first.
+ var desc *ExtensionDesc
+ if m := extensionMaps[base]; m != nil {
+ desc = m[extNum]
+ }
+ if desc == nil {
+ log.Printf("proto: don't know how to compare extension %d of %v", extNum, base)
+ continue
+ }
+ var err error
+ if m1 == nil {
+ m1, err = decodeExtension(e1.enc, desc)
+ }
+ if m2 == nil && err == nil {
+ m2, err = decodeExtension(e2.enc, desc)
+ }
+ if err != nil {
+ // The encoded form is invalid.
+ log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err)
+ return false
+ }
+ if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
+ return false
+ }
+ }
+
+ return true
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+/*
+ * Types and routines for supporting protocol buffer extensions.
+ */
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+ "strconv"
+ "sync"
+)
+
+// ErrMissingExtension is the error returned by GetExtension if the named extension is not in the message.
+var ErrMissingExtension = errors.New("proto: missing extension")
+
+// ExtensionRange represents a range of message extensions for a protocol buffer.
+// Used in code generated by the protocol compiler.
+type ExtensionRange struct {
+ Start, End int32 // both inclusive
+}
+
+// extendableProto is an interface implemented by any protocol buffer generated by the current
+// proto compiler that may be extended.
+type extendableProto interface {
+ Message
+ ExtensionRangeArray() []ExtensionRange
+ extensionsWrite() map[int32]Extension
+ extensionsRead() (map[int32]Extension, sync.Locker)
+}
+
+// extendableProtoV1 is an interface implemented by a protocol buffer generated by the previous
+// version of the proto compiler that may be extended.
+type extendableProtoV1 interface {
+ Message
+ ExtensionRangeArray() []ExtensionRange
+ ExtensionMap() map[int32]Extension
+}
+
+// extensionAdapter is a wrapper around extendableProtoV1 that implements extendableProto.
+type extensionAdapter struct {
+ extendableProtoV1
+}
+
+func (e extensionAdapter) extensionsWrite() map[int32]Extension {
+ return e.ExtensionMap()
+}
+
+func (e extensionAdapter) extensionsRead() (map[int32]Extension, sync.Locker) {
+ return e.ExtensionMap(), notLocker{}
+}
+
+// notLocker is a sync.Locker whose Lock and Unlock methods are nops.
+type notLocker struct{}
+
+func (n notLocker) Lock() {}
+func (n notLocker) Unlock() {}
+
+// extendable returns the extendableProto interface for the given generated proto message.
+// If the proto message has the old extension format, it returns a wrapper that implements
+// the extendableProto interface.
+func extendable(p interface{}) (extendableProto, bool) {
+ if ep, ok := p.(extendableProto); ok {
+ return ep, ok
+ }
+ if ep, ok := p.(extendableProtoV1); ok {
+ return extensionAdapter{ep}, ok
+ }
+ return nil, false
+}
+
+// XXX_InternalExtensions is an internal representation of proto extensions.
+//
+// Each generated message struct type embeds an anonymous XXX_InternalExtensions field,
+// thus gaining the unexported 'extensions' method, which can be called only from the proto package.
+//
+// The methods of XXX_InternalExtensions are not concurrency safe in general,
+// but calls to logically read-only methods such as has and get may be executed concurrently.
+type XXX_InternalExtensions struct {
+ // The struct must be indirect so that if a user inadvertently copies a
+ // generated message and its embedded XXX_InternalExtensions, they
+ // avoid the mayhem of a copied mutex.
+ //
+ // The mutex serializes all logically read-only operations to p.extensionMap.
+ // It is up to the client to ensure that write operations to p.extensionMap are
+ // mutually exclusive with other accesses.
+ p *struct {
+ mu sync.Mutex
+ extensionMap map[int32]Extension
+ }
+}
+
+// extensionsWrite returns the extension map, creating it on first use.
+func (e *XXX_InternalExtensions) extensionsWrite() map[int32]Extension {
+ if e.p == nil {
+ e.p = new(struct {
+ mu sync.Mutex
+ extensionMap map[int32]Extension
+ })
+ e.p.extensionMap = make(map[int32]Extension)
+ }
+ return e.p.extensionMap
+}
+
+// extensionsRead returns the extensions map for read-only use. It may be nil.
+// The caller must hold the returned mutex's lock when accessing Elements within the map.
+func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Locker) {
+ if e.p == nil {
+ return nil, nil
+ }
+ return e.p.extensionMap, &e.p.mu
+}
+
+var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem()
+var extendableProtoV1Type = reflect.TypeOf((*extendableProtoV1)(nil)).Elem()
+
+// ExtensionDesc represents an extension specification.
+// Used in generated code from the protocol compiler.
+type ExtensionDesc struct {
+ ExtendedType Message // nil pointer to the type that is being extended
+ ExtensionType interface{} // nil pointer to the extension type
+ Field int32 // field number
+ Name string // fully-qualified name of extension, for text formatting
+ Tag string // protobuf tag style
+}
+
+func (ed *ExtensionDesc) repeated() bool {
+ t := reflect.TypeOf(ed.ExtensionType)
+ return t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8
+}
+
+// Extension represents an extension in a message.
+type Extension struct {
+ // When an extension is stored in a message using SetExtension
+ // only desc and value are set. When the message is marshaled
+ // enc will be set to the encoded form of the message.
+ //
+ // When a message is unmarshaled and contains extensions, each
+ // extension will have only enc set. When such an extension is
+ // accessed using GetExtension (or GetExtensions) desc and value
+ // will be set.
+ desc *ExtensionDesc
+ value interface{}
+ enc []byte
+}
+
+// SetRawExtension is for testing only.
+func SetRawExtension(base Message, id int32, b []byte) {
+ epb, ok := extendable(base)
+ if !ok {
+ return
+ }
+ extmap := epb.extensionsWrite()
+ extmap[id] = Extension{enc: b}
+}
+
+// isExtensionField returns true iff the given field number is in an extension range.
+func isExtensionField(pb extendableProto, field int32) bool {
+ for _, er := range pb.ExtensionRangeArray() {
+ if er.Start <= field && field <= er.End {
+ return true
+ }
+ }
+ return false
+}
+
+// checkExtensionTypes checks that the given extension is valid for pb.
+func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error {
+ var pbi interface{} = pb
+ // Check the extended type.
+ if ea, ok := pbi.(extensionAdapter); ok {
+ pbi = ea.extendableProtoV1
+ }
+ if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b {
+ return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String())
+ }
+ // Check the range.
+ if !isExtensionField(pb, extension.Field) {
+ return errors.New("proto: bad extension number; not in declared ranges")
+ }
+ return nil
+}
+
+// extPropKey is sufficient to uniquely identify an extension.
+type extPropKey struct {
+ base reflect.Type
+ field int32
+}
+
+var extProp = struct {
+ sync.RWMutex
+ m map[extPropKey]*Properties
+}{
+ m: make(map[extPropKey]*Properties),
+}
+
+func extensionProperties(ed *ExtensionDesc) *Properties {
+ key := extPropKey{base: reflect.TypeOf(ed.ExtendedType), field: ed.Field}
+
+ extProp.RLock()
+ if prop, ok := extProp.m[key]; ok {
+ extProp.RUnlock()
+ return prop
+ }
+ extProp.RUnlock()
+
+ extProp.Lock()
+ defer extProp.Unlock()
+ // Check again.
+ if prop, ok := extProp.m[key]; ok {
+ return prop
+ }
+
+ prop := new(Properties)
+ prop.Init(reflect.TypeOf(ed.ExtensionType), "unknown_name", ed.Tag, nil)
+ extProp.m[key] = prop
+ return prop
+}
+
+// encode encodes any unmarshaled (unencoded) extensions in e.
+func encodeExtensions(e *XXX_InternalExtensions) error {
+ m, mu := e.extensionsRead()
+ if m == nil {
+ return nil // fast path
+ }
+ mu.Lock()
+ defer mu.Unlock()
+ return encodeExtensionsMap(m)
+}
+
+// encode encodes any unmarshaled (unencoded) extensions in e.
+func encodeExtensionsMap(m map[int32]Extension) error {
+ for k, e := range m {
+ if e.value == nil || e.desc == nil {
+ // Extension is only in its encoded form.
+ continue
+ }
+
+ // We don't skip extensions that have an encoded form set,
+ // because the extension value may have been mutated after
+ // the last time this function was called.
+
+ et := reflect.TypeOf(e.desc.ExtensionType)
+ props := extensionProperties(e.desc)
+
+ p := NewBuffer(nil)
+ // If e.value has type T, the encoder expects a *struct{ X T }.
+ // Pass a *T with a zero field and hope it all works out.
+ x := reflect.New(et)
+ x.Elem().Set(reflect.ValueOf(e.value))
+ if err := props.enc(p, props, toStructPointer(x)); err != nil {
+ return err
+ }
+ e.enc = p.buf
+ m[k] = e
+ }
+ return nil
+}
+
+func extensionsSize(e *XXX_InternalExtensions) (n int) {
+ m, mu := e.extensionsRead()
+ if m == nil {
+ return 0
+ }
+ mu.Lock()
+ defer mu.Unlock()
+ return extensionsMapSize(m)
+}
+
+func extensionsMapSize(m map[int32]Extension) (n int) {
+ for _, e := range m {
+ if e.value == nil || e.desc == nil {
+ // Extension is only in its encoded form.
+ n += len(e.enc)
+ continue
+ }
+
+ // We don't skip extensions that have an encoded form set,
+ // because the extension value may have been mutated after
+ // the last time this function was called.
+
+ et := reflect.TypeOf(e.desc.ExtensionType)
+ props := extensionProperties(e.desc)
+
+ // If e.value has type T, the encoder expects a *struct{ X T }.
+ // Pass a *T with a zero field and hope it all works out.
+ x := reflect.New(et)
+ x.Elem().Set(reflect.ValueOf(e.value))
+ n += props.size(props, toStructPointer(x))
+ }
+ return
+}
+
+// HasExtension returns whether the given extension is present in pb.
+func HasExtension(pb Message, extension *ExtensionDesc) bool {
+ // TODO: Check types, field numbers, etc.?
+ epb, ok := extendable(pb)
+ if !ok {
+ return false
+ }
+ extmap, mu := epb.extensionsRead()
+ if extmap == nil {
+ return false
+ }
+ mu.Lock()
+ _, ok = extmap[extension.Field]
+ mu.Unlock()
+ return ok
+}
+
+// ClearExtension removes the given extension from pb.
+func ClearExtension(pb Message, extension *ExtensionDesc) {
+ epb, ok := extendable(pb)
+ if !ok {
+ return
+ }
+ // TODO: Check types, field numbers, etc.?
+ extmap := epb.extensionsWrite()
+ delete(extmap, extension.Field)
+}
+
+// GetExtension parses and returns the given extension of pb.
+// If the extension is not present and has no default value it returns ErrMissingExtension.
+func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
+ epb, ok := extendable(pb)
+ if !ok {
+ return nil, errors.New("proto: not an extendable proto")
+ }
+
+ if err := checkExtensionTypes(epb, extension); err != nil {
+ return nil, err
+ }
+
+ emap, mu := epb.extensionsRead()
+ if emap == nil {
+ return defaultExtensionValue(extension)
+ }
+ mu.Lock()
+ defer mu.Unlock()
+ e, ok := emap[extension.Field]
+ if !ok {
+ // defaultExtensionValue returns the default value or
+ // ErrMissingExtension if there is no default.
+ return defaultExtensionValue(extension)
+ }
+
+ if e.value != nil {
+ // Already decoded. Check the descriptor, though.
+ if e.desc != extension {
+ // This shouldn't happen. If it does, it means that
+ // GetExtension was called twice with two different
+ // descriptors with the same field number.
+ return nil, errors.New("proto: descriptor conflict")
+ }
+ return e.value, nil
+ }
+
+ v, err := decodeExtension(e.enc, extension)
+ if err != nil {
+ return nil, err
+ }
+
+ // Remember the decoded version and drop the encoded version.
+ // That way it is safe to mutate what we return.
+ e.value = v
+ e.desc = extension
+ e.enc = nil
+ emap[extension.Field] = e
+ return e.value, nil
+}
+
+// defaultExtensionValue returns the default value for extension.
+// If no default for an extension is defined ErrMissingExtension is returned.
+func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
+ t := reflect.TypeOf(extension.ExtensionType)
+ props := extensionProperties(extension)
+
+ sf, _, err := fieldDefault(t, props)
+ if err != nil {
+ return nil, err
+ }
+
+ if sf == nil || sf.value == nil {
+ // There is no default value.
+ return nil, ErrMissingExtension
+ }
+
+ if t.Kind() != reflect.Ptr {
+ // We do not need to return a Ptr, we can directly return sf.value.
+ return sf.value, nil
+ }
+
+ // We need to return an interface{} that is a pointer to sf.value.
+ value := reflect.New(t).Elem()
+ value.Set(reflect.New(value.Type().Elem()))
+ if sf.kind == reflect.Int32 {
+ // We may have an int32 or an enum, but the underlying data is int32.
+ // Since we can't set an int32 into a non int32 reflect.value directly
+ // set it as a int32.
+ value.Elem().SetInt(int64(sf.value.(int32)))
+ } else {
+ value.Elem().Set(reflect.ValueOf(sf.value))
+ }
+ return value.Interface(), nil
+}
+
+// decodeExtension decodes an extension encoded in b.
+func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
+ o := NewBuffer(b)
+
+ t := reflect.TypeOf(extension.ExtensionType)
+
+ props := extensionProperties(extension)
+
+ // t is a pointer to a struct, pointer to basic type or a slice.
+ // Allocate a "field" to store the pointer/slice itself; the
+ // pointer/slice will be stored here. We pass
+ // the address of this field to props.dec.
+ // This passes a zero field and a *t and lets props.dec
+ // interpret it as a *struct{ x t }.
+ value := reflect.New(t).Elem()
+
+ for {
+ // Discard wire type and field number varint. It isn't needed.
+ if _, err := o.DecodeVarint(); err != nil {
+ return nil, err
+ }
+
+ if err := props.dec(o, props, toStructPointer(value.Addr())); err != nil {
+ return nil, err
+ }
+
+ if o.index >= len(o.buf) {
+ break
+ }
+ }
+ return value.Interface(), nil
+}
+
+// GetExtensions returns a slice of the extensions present in pb that are also listed in es.
+// The returned slice has the same length as es; missing extensions will appear as nil elements.
+func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) {
+ epb, ok := extendable(pb)
+ if !ok {
+ return nil, errors.New("proto: not an extendable proto")
+ }
+ extensions = make([]interface{}, len(es))
+ for i, e := range es {
+ extensions[i], err = GetExtension(epb, e)
+ if err == ErrMissingExtension {
+ err = nil
+ }
+ if err != nil {
+ return
+ }
+ }
+ return
+}
+
+// ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order.
+// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing
+// just the Field field, which defines the extension's field number.
+func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
+ epb, ok := extendable(pb)
+ if !ok {
+ return nil, fmt.Errorf("proto: %T is not an extendable proto.Message", pb)
+ }
+ registeredExtensions := RegisteredExtensions(pb)
+
+ emap, mu := epb.extensionsRead()
+ mu.Lock()
+ defer mu.Unlock()
+ extensions := make([]*ExtensionDesc, 0, len(emap))
+ for extid, e := range emap {
+ desc := e.desc
+ if desc == nil {
+ desc = registeredExtensions[extid]
+ if desc == nil {
+ desc = &ExtensionDesc{Field: extid}
+ }
+ }
+
+ extensions = append(extensions, desc)
+ }
+ return extensions, nil
+}
+
+// SetExtension sets the specified extension of pb to the specified value.
+func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error {
+ epb, ok := extendable(pb)
+ if !ok {
+ return errors.New("proto: not an extendable proto")
+ }
+ if err := checkExtensionTypes(epb, extension); err != nil {
+ return err
+ }
+ typ := reflect.TypeOf(extension.ExtensionType)
+ if typ != reflect.TypeOf(value) {
+ return errors.New("proto: bad extension value type")
+ }
+ // nil extension values need to be caught early, because the
+ // encoder can't distinguish an ErrNil due to a nil extension
+ // from an ErrNil due to a missing field. Extensions are
+ // always optional, so the encoder would just swallow the error
+ // and drop all the extensions from the encoded message.
+ if reflect.ValueOf(value).IsNil() {
+ return fmt.Errorf("proto: SetExtension called with nil value of type %T", value)
+ }
+
+ extmap := epb.extensionsWrite()
+ extmap[extension.Field] = Extension{desc: extension, value: value}
+ return nil
+}
+
+// ClearAllExtensions clears all extensions from pb.
+func ClearAllExtensions(pb Message) {
+ epb, ok := extendable(pb)
+ if !ok {
+ return
+ }
+ m := epb.extensionsWrite()
+ for k := range m {
+ delete(m, k)
+ }
+}
+
+// A global registry of extensions.
+// The generated code will register the generated descriptors by calling RegisterExtension.
+
+var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc)
+
+// RegisterExtension is called from the generated code.
+func RegisterExtension(desc *ExtensionDesc) {
+ st := reflect.TypeOf(desc.ExtendedType).Elem()
+ m := extensionMaps[st]
+ if m == nil {
+ m = make(map[int32]*ExtensionDesc)
+ extensionMaps[st] = m
+ }
+ if _, ok := m[desc.Field]; ok {
+ panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field)))
+ }
+ m[desc.Field] = desc
+}
+
+// RegisteredExtensions returns a map of the registered extensions of a
+// protocol buffer struct, indexed by the extension number.
+// The argument pb should be a nil pointer to the struct type.
+func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {
+ return extensionMaps[reflect.TypeOf(pb).Elem()]
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/*
+Package proto converts data structures to and from the wire format of
+protocol buffers. It works in concert with the Go source code generated
+for .proto files by the protocol compiler.
+
+A summary of the properties of the protocol buffer interface
+for a protocol buffer variable v:
+
+ - Names are turned from camel_case to CamelCase for export.
+ - There are no methods on v to set fields; just treat
+ them as structure fields.
+ - There are getters that return a field's value if set,
+ and return the field's default value if unset.
+ The getters work even if the receiver is a nil message.
+ - The zero value for a struct is its correct initialization state.
+ All desired fields must be set before marshaling.
+ - A Reset() method will restore a protobuf struct to its zero state.
+ - Non-repeated fields are pointers to the values; nil means unset.
+ That is, optional or required field int32 f becomes F *int32.
+ - Repeated fields are slices.
+ - Helper functions are available to aid the setting of fields.
+ msg.Foo = proto.String("hello") // set field
+ - Constants are defined to hold the default values of all fields that
+ have them. They have the form Default_StructName_FieldName.
+ Because the getter methods handle defaulted values,
+ direct use of these constants should be rare.
+ - Enums are given type names and maps from names to values.
+ Enum values are prefixed by the enclosing message's name, or by the
+ enum's type name if it is a top-level enum. Enum types have a String
+ method, and a Enum method to assist in message construction.
+ - Nested messages, groups and enums have type names prefixed with the name of
+ the surrounding message type.
+ - Extensions are given descriptor names that start with E_,
+ followed by an underscore-delimited list of the nested messages
+ that contain it (if any) followed by the CamelCased name of the
+ extension field itself. HasExtension, ClearExtension, GetExtension
+ and SetExtension are functions for manipulating extensions.
+ - Oneof field sets are given a single field in their message,
+ with distinguished wrapper types for each possible field value.
+ - Marshal and Unmarshal are functions to encode and decode the wire format.
+
+When the .proto file specifies `syntax="proto3"`, there are some differences:
+
+ - Non-repeated fields of non-message type are values instead of pointers.
+ - Getters are only generated for message and oneof fields.
+ - Enum types do not get an Enum method.
+
+The simplest way to describe this is to see an example.
+Given file test.proto, containing
+
+ package example;
+
+ enum FOO { X = 17; }
+
+ message Test {
+ required string label = 1;
+ optional int32 type = 2 [default=77];
+ repeated int64 reps = 3;
+ optional group OptionalGroup = 4 {
+ required string RequiredField = 5;
+ }
+ oneof union {
+ int32 number = 6;
+ string name = 7;
+ }
+ }
+
+The resulting file, test.pb.go, is:
+
+ package example
+
+ import proto "github.com/golang/protobuf/proto"
+ import math "math"
+
+ type FOO int32
+ const (
+ FOO_X FOO = 17
+ )
+ var FOO_name = map[int32]string{
+ 17: "X",
+ }
+ var FOO_value = map[string]int32{
+ "X": 17,
+ }
+
+ func (x FOO) Enum() *FOO {
+ p := new(FOO)
+ *p = x
+ return p
+ }
+ func (x FOO) String() string {
+ return proto.EnumName(FOO_name, int32(x))
+ }
+ func (x *FOO) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FOO_value, data)
+ if err != nil {
+ return err
+ }
+ *x = FOO(value)
+ return nil
+ }
+
+ type Test struct {
+ Label *string `protobuf:"bytes,1,req,name=label" json:"label,omitempty"`
+ Type *int32 `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"`
+ Reps []int64 `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"`
+ Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"`
+ // Types that are valid to be assigned to Union:
+ // *Test_Number
+ // *Test_Name
+ Union isTest_Union `protobuf_oneof:"union"`
+ XXX_unrecognized []byte `json:"-"`
+ }
+ func (m *Test) Reset() { *m = Test{} }
+ func (m *Test) String() string { return proto.CompactTextString(m) }
+ func (*Test) ProtoMessage() {}
+
+ type isTest_Union interface {
+ isTest_Union()
+ }
+
+ type Test_Number struct {
+ Number int32 `protobuf:"varint,6,opt,name=number"`
+ }
+ type Test_Name struct {
+ Name string `protobuf:"bytes,7,opt,name=name"`
+ }
+
+ func (*Test_Number) isTest_Union() {}
+ func (*Test_Name) isTest_Union() {}
+
+ func (m *Test) GetUnion() isTest_Union {
+ if m != nil {
+ return m.Union
+ }
+ return nil
+ }
+ const Default_Test_Type int32 = 77
+
+ func (m *Test) GetLabel() string {
+ if m != nil && m.Label != nil {
+ return *m.Label
+ }
+ return ""
+ }
+
+ func (m *Test) GetType() int32 {
+ if m != nil && m.Type != nil {
+ return *m.Type
+ }
+ return Default_Test_Type
+ }
+
+ func (m *Test) GetOptionalgroup() *Test_OptionalGroup {
+ if m != nil {
+ return m.Optionalgroup
+ }
+ return nil
+ }
+
+ type Test_OptionalGroup struct {
+ RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"`
+ }
+ func (m *Test_OptionalGroup) Reset() { *m = Test_OptionalGroup{} }
+ func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) }
+
+ func (m *Test_OptionalGroup) GetRequiredField() string {
+ if m != nil && m.RequiredField != nil {
+ return *m.RequiredField
+ }
+ return ""
+ }
+
+ func (m *Test) GetNumber() int32 {
+ if x, ok := m.GetUnion().(*Test_Number); ok {
+ return x.Number
+ }
+ return 0
+ }
+
+ func (m *Test) GetName() string {
+ if x, ok := m.GetUnion().(*Test_Name); ok {
+ return x.Name
+ }
+ return ""
+ }
+
+ func init() {
+ proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
+ }
+
+To create and play with a Test object:
+
+ package main
+
+ import (
+ "log"
+
+ "github.com/golang/protobuf/proto"
+ pb "./example.pb"
+ )
+
+ func main() {
+ test := &pb.Test{
+ Label: proto.String("hello"),
+ Type: proto.Int32(17),
+ Reps: []int64{1, 2, 3},
+ Optionalgroup: &pb.Test_OptionalGroup{
+ RequiredField: proto.String("good bye"),
+ },
+ Union: &pb.Test_Name{"fred"},
+ }
+ data, err := proto.Marshal(test)
+ if err != nil {
+ log.Fatal("marshaling error: ", err)
+ }
+ newTest := &pb.Test{}
+ err = proto.Unmarshal(data, newTest)
+ if err != nil {
+ log.Fatal("unmarshaling error: ", err)
+ }
+ // Now test and newTest contain the same data.
+ if test.GetLabel() != newTest.GetLabel() {
+ log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
+ }
+ // Use a type switch to determine which oneof was set.
+ switch u := test.Union.(type) {
+ case *pb.Test_Number: // u.Number contains the number.
+ case *pb.Test_Name: // u.Name contains the string.
+ }
+ // etc.
+ }
+*/
+package proto
+
+import (
+ "encoding/json"
+ "fmt"
+ "log"
+ "reflect"
+ "sort"
+ "strconv"
+ "sync"
+)
+
+// Message is implemented by generated protocol buffer messages.
+type Message interface {
+ Reset()
+ String() string
+ ProtoMessage()
+}
+
+// Stats records allocation details about the protocol buffer encoders
+// and decoders. Useful for tuning the library itself.
+type Stats struct {
+ Emalloc uint64 // mallocs in encode
+ Dmalloc uint64 // mallocs in decode
+ Encode uint64 // number of encodes
+ Decode uint64 // number of decodes
+ Chit uint64 // number of cache hits
+ Cmiss uint64 // number of cache misses
+ Size uint64 // number of sizes
+}
+
+// Set to true to enable stats collection.
+const collectStats = false
+
+var stats Stats
+
+// GetStats returns a copy of the global Stats structure.
+func GetStats() Stats { return stats }
+
+// A Buffer is a buffer manager for marshaling and unmarshaling
+// protocol buffers. It may be reused between invocations to
+// reduce memory usage. It is not necessary to use a Buffer;
+// the global functions Marshal and Unmarshal create a
+// temporary Buffer and are fine for most applications.
+type Buffer struct {
+ buf []byte // encode/decode byte stream
+ index int // write point
+
+ // pools of basic types to amortize allocation.
+ bools []bool
+ uint32s []uint32
+ uint64s []uint64
+
+ // extra pools, only used with pointer_reflect.go
+ int32s []int32
+ int64s []int64
+ float32s []float32
+ float64s []float64
+}
+
+// NewBuffer allocates a new Buffer and initializes its internal data to
+// the contents of the argument slice.
+func NewBuffer(e []byte) *Buffer {
+ return &Buffer{buf: e}
+}
+
+// Reset resets the Buffer, ready for marshaling a new protocol buffer.
+func (p *Buffer) Reset() {
+ p.buf = p.buf[0:0] // for reading/writing
+ p.index = 0 // for reading
+}
+
+// SetBuf replaces the internal buffer with the slice,
+// ready for unmarshaling the contents of the slice.
+func (p *Buffer) SetBuf(s []byte) {
+ p.buf = s
+ p.index = 0
+}
+
+// Bytes returns the contents of the Buffer.
+func (p *Buffer) Bytes() []byte { return p.buf }
+
+/*
+ * Helper routines for simplifying the creation of optional fields of basic type.
+ */
+
+// Bool is a helper routine that allocates a new bool value
+// to store v and returns a pointer to it.
+func Bool(v bool) *bool {
+ return &v
+}
+
+// Int32 is a helper routine that allocates a new int32 value
+// to store v and returns a pointer to it.
+func Int32(v int32) *int32 {
+ return &v
+}
+
+// Int is a helper routine that allocates a new int32 value
+// to store v and returns a pointer to it, but unlike Int32
+// its argument value is an int.
+func Int(v int) *int32 {
+ p := new(int32)
+ *p = int32(v)
+ return p
+}
+
+// Int64 is a helper routine that allocates a new int64 value
+// to store v and returns a pointer to it.
+func Int64(v int64) *int64 {
+ return &v
+}
+
+// Float32 is a helper routine that allocates a new float32 value
+// to store v and returns a pointer to it.
+func Float32(v float32) *float32 {
+ return &v
+}
+
+// Float64 is a helper routine that allocates a new float64 value
+// to store v and returns a pointer to it.
+func Float64(v float64) *float64 {
+ return &v
+}
+
+// Uint32 is a helper routine that allocates a new uint32 value
+// to store v and returns a pointer to it.
+func Uint32(v uint32) *uint32 {
+ return &v
+}
+
+// Uint64 is a helper routine that allocates a new uint64 value
+// to store v and returns a pointer to it.
+func Uint64(v uint64) *uint64 {
+ return &v
+}
+
+// String is a helper routine that allocates a new string value
+// to store v and returns a pointer to it.
+func String(v string) *string {
+ return &v
+}
+
+// EnumName is a helper function to simplify printing protocol buffer enums
+// by name. Given an enum map and a value, it returns a useful string.
+func EnumName(m map[int32]string, v int32) string {
+ s, ok := m[v]
+ if ok {
+ return s
+ }
+ return strconv.Itoa(int(v))
+}
+
+// UnmarshalJSONEnum is a helper function to simplify recovering enum int values
+// from their JSON-encoded representation. Given a map from the enum's symbolic
+// names to its int values, and a byte buffer containing the JSON-encoded
+// value, it returns an int32 that can be cast to the enum type by the caller.
+//
+// The function can deal with both JSON representations, numeric and symbolic.
+func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) {
+ if data[0] == '"' {
+ // New style: enums are strings.
+ var repr string
+ if err := json.Unmarshal(data, &repr); err != nil {
+ return -1, err
+ }
+ val, ok := m[repr]
+ if !ok {
+ return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr)
+ }
+ return val, nil
+ }
+ // Old style: enums are ints.
+ var val int32
+ if err := json.Unmarshal(data, &val); err != nil {
+ return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName)
+ }
+ return val, nil
+}
+
+// DebugPrint dumps the encoded data in b in a debugging format with a header
+// including the string s. Used in testing but made available for general debugging.
+func (p *Buffer) DebugPrint(s string, b []byte) {
+ var u uint64
+
+ obuf := p.buf
+ index := p.index
+ p.buf = b
+ p.index = 0
+ depth := 0
+
+ fmt.Printf("\n--- %s ---\n", s)
+
+out:
+ for {
+ for i := 0; i < depth; i++ {
+ fmt.Print(" ")
+ }
+
+ index := p.index
+ if index == len(p.buf) {
+ break
+ }
+
+ op, err := p.DecodeVarint()
+ if err != nil {
+ fmt.Printf("%3d: fetching op err %v\n", index, err)
+ break out
+ }
+ tag := op >> 3
+ wire := op & 7
+
+ switch wire {
+ default:
+ fmt.Printf("%3d: t=%3d unknown wire=%d\n",
+ index, tag, wire)
+ break out
+
+ case WireBytes:
+ var r []byte
+
+ r, err = p.DecodeRawBytes(false)
+ if err != nil {
+ break out
+ }
+ fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r))
+ if len(r) <= 6 {
+ for i := 0; i < len(r); i++ {
+ fmt.Printf(" %.2x", r[i])
+ }
+ } else {
+ for i := 0; i < 3; i++ {
+ fmt.Printf(" %.2x", r[i])
+ }
+ fmt.Printf(" ..")
+ for i := len(r) - 3; i < len(r); i++ {
+ fmt.Printf(" %.2x", r[i])
+ }
+ }
+ fmt.Printf("\n")
+
+ case WireFixed32:
+ u, err = p.DecodeFixed32()
+ if err != nil {
+ fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err)
+ break out
+ }
+ fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u)
+
+ case WireFixed64:
+ u, err = p.DecodeFixed64()
+ if err != nil {
+ fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err)
+ break out
+ }
+ fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u)
+
+ case WireVarint:
+ u, err = p.DecodeVarint()
+ if err != nil {
+ fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err)
+ break out
+ }
+ fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u)
+
+ case WireStartGroup:
+ fmt.Printf("%3d: t=%3d start\n", index, tag)
+ depth++
+
+ case WireEndGroup:
+ depth--
+ fmt.Printf("%3d: t=%3d end\n", index, tag)
+ }
+ }
+
+ if depth != 0 {
+ fmt.Printf("%3d: start-end not balanced %d\n", p.index, depth)
+ }
+ fmt.Printf("\n")
+
+ p.buf = obuf
+ p.index = index
+}
+
+// SetDefaults sets unset protocol buffer fields to their default values.
+// It only modifies fields that are both unset and have defined defaults.
+// It recursively sets default values in any non-nil sub-messages.
+func SetDefaults(pb Message) {
+ setDefaults(reflect.ValueOf(pb), true, false)
+}
+
+// v is a pointer to a struct.
+func setDefaults(v reflect.Value, recur, zeros bool) {
+ v = v.Elem()
+
+ defaultMu.RLock()
+ dm, ok := defaults[v.Type()]
+ defaultMu.RUnlock()
+ if !ok {
+ dm = buildDefaultMessage(v.Type())
+ defaultMu.Lock()
+ defaults[v.Type()] = dm
+ defaultMu.Unlock()
+ }
+
+ for _, sf := range dm.scalars {
+ f := v.Field(sf.index)
+ if !f.IsNil() {
+ // field already set
+ continue
+ }
+ dv := sf.value
+ if dv == nil && !zeros {
+ // no explicit default, and don't want to set zeros
+ continue
+ }
+ fptr := f.Addr().Interface() // **T
+ // TODO: Consider batching the allocations we do here.
+ switch sf.kind {
+ case reflect.Bool:
+ b := new(bool)
+ if dv != nil {
+ *b = dv.(bool)
+ }
+ *(fptr.(**bool)) = b
+ case reflect.Float32:
+ f := new(float32)
+ if dv != nil {
+ *f = dv.(float32)
+ }
+ *(fptr.(**float32)) = f
+ case reflect.Float64:
+ f := new(float64)
+ if dv != nil {
+ *f = dv.(float64)
+ }
+ *(fptr.(**float64)) = f
+ case reflect.Int32:
+ // might be an enum
+ if ft := f.Type(); ft != int32PtrType {
+ // enum
+ f.Set(reflect.New(ft.Elem()))
+ if dv != nil {
+ f.Elem().SetInt(int64(dv.(int32)))
+ }
+ } else {
+ // int32 field
+ i := new(int32)
+ if dv != nil {
+ *i = dv.(int32)
+ }
+ *(fptr.(**int32)) = i
+ }
+ case reflect.Int64:
+ i := new(int64)
+ if dv != nil {
+ *i = dv.(int64)
+ }
+ *(fptr.(**int64)) = i
+ case reflect.String:
+ s := new(string)
+ if dv != nil {
+ *s = dv.(string)
+ }
+ *(fptr.(**string)) = s
+ case reflect.Uint8:
+ // exceptional case: []byte
+ var b []byte
+ if dv != nil {
+ db := dv.([]byte)
+ b = make([]byte, len(db))
+ copy(b, db)
+ } else {
+ b = []byte{}
+ }
+ *(fptr.(*[]byte)) = b
+ case reflect.Uint32:
+ u := new(uint32)
+ if dv != nil {
+ *u = dv.(uint32)
+ }
+ *(fptr.(**uint32)) = u
+ case reflect.Uint64:
+ u := new(uint64)
+ if dv != nil {
+ *u = dv.(uint64)
+ }
+ *(fptr.(**uint64)) = u
+ default:
+ log.Printf("proto: can't set default for field %v (sf.kind=%v)", f, sf.kind)
+ }
+ }
+
+ for _, ni := range dm.nested {
+ f := v.Field(ni)
+ // f is *T or []*T or map[T]*T
+ switch f.Kind() {
+ case reflect.Ptr:
+ if f.IsNil() {
+ continue
+ }
+ setDefaults(f, recur, zeros)
+
+ case reflect.Slice:
+ for i := 0; i < f.Len(); i++ {
+ e := f.Index(i)
+ if e.IsNil() {
+ continue
+ }
+ setDefaults(e, recur, zeros)
+ }
+
+ case reflect.Map:
+ for _, k := range f.MapKeys() {
+ e := f.MapIndex(k)
+ if e.IsNil() {
+ continue
+ }
+ setDefaults(e, recur, zeros)
+ }
+ }
+ }
+}
+
+var (
+ // defaults maps a protocol buffer struct type to a slice of the fields,
+ // with its scalar fields set to their proto-declared non-zero default values.
+ defaultMu sync.RWMutex
+ defaults = make(map[reflect.Type]defaultMessage)
+
+ int32PtrType = reflect.TypeOf((*int32)(nil))
+)
+
+// defaultMessage represents information about the default values of a message.
+type defaultMessage struct {
+ scalars []scalarField
+ nested []int // struct field index of nested messages
+}
+
+type scalarField struct {
+ index int // struct field index
+ kind reflect.Kind // element type (the T in *T or []T)
+ value interface{} // the proto-declared default value, or nil
+}
+
+// t is a struct type.
+func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
+ sprop := GetProperties(t)
+ for _, prop := range sprop.Prop {
+ fi, ok := sprop.decoderTags.get(prop.Tag)
+ if !ok {
+ // XXX_unrecognized
+ continue
+ }
+ ft := t.Field(fi).Type
+
+ sf, nested, err := fieldDefault(ft, prop)
+ switch {
+ case err != nil:
+ log.Print(err)
+ case nested:
+ dm.nested = append(dm.nested, fi)
+ case sf != nil:
+ sf.index = fi
+ dm.scalars = append(dm.scalars, *sf)
+ }
+ }
+
+ return dm
+}
+
+// fieldDefault returns the scalarField for field type ft.
+// sf will be nil if the field can not have a default.
+// nestedMessage will be true if this is a nested message.
+// Note that sf.index is not set on return.
+func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) {
+ var canHaveDefault bool
+ switch ft.Kind() {
+ case reflect.Ptr:
+ if ft.Elem().Kind() == reflect.Struct {
+ nestedMessage = true
+ } else {
+ canHaveDefault = true // proto2 scalar field
+ }
+
+ case reflect.Slice:
+ switch ft.Elem().Kind() {
+ case reflect.Ptr:
+ nestedMessage = true // repeated message
+ case reflect.Uint8:
+ canHaveDefault = true // bytes field
+ }
+
+ case reflect.Map:
+ if ft.Elem().Kind() == reflect.Ptr {
+ nestedMessage = true // map with message values
+ }
+ }
+
+ if !canHaveDefault {
+ if nestedMessage {
+ return nil, true, nil
+ }
+ return nil, false, nil
+ }
+
+ // We now know that ft is a pointer or slice.
+ sf = &scalarField{kind: ft.Elem().Kind()}
+
+ // scalar fields without defaults
+ if !prop.HasDefault {
+ return sf, false, nil
+ }
+
+ // a scalar field: either *T or []byte
+ switch ft.Elem().Kind() {
+ case reflect.Bool:
+ x, err := strconv.ParseBool(prop.Default)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default bool %q: %v", prop.Default, err)
+ }
+ sf.value = x
+ case reflect.Float32:
+ x, err := strconv.ParseFloat(prop.Default, 32)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default float32 %q: %v", prop.Default, err)
+ }
+ sf.value = float32(x)
+ case reflect.Float64:
+ x, err := strconv.ParseFloat(prop.Default, 64)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default float64 %q: %v", prop.Default, err)
+ }
+ sf.value = x
+ case reflect.Int32:
+ x, err := strconv.ParseInt(prop.Default, 10, 32)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default int32 %q: %v", prop.Default, err)
+ }
+ sf.value = int32(x)
+ case reflect.Int64:
+ x, err := strconv.ParseInt(prop.Default, 10, 64)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default int64 %q: %v", prop.Default, err)
+ }
+ sf.value = x
+ case reflect.String:
+ sf.value = prop.Default
+ case reflect.Uint8:
+ // []byte (not *uint8)
+ sf.value = []byte(prop.Default)
+ case reflect.Uint32:
+ x, err := strconv.ParseUint(prop.Default, 10, 32)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default uint32 %q: %v", prop.Default, err)
+ }
+ sf.value = uint32(x)
+ case reflect.Uint64:
+ x, err := strconv.ParseUint(prop.Default, 10, 64)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default uint64 %q: %v", prop.Default, err)
+ }
+ sf.value = x
+ default:
+ return nil, false, fmt.Errorf("proto: unhandled def kind %v", ft.Elem().Kind())
+ }
+
+ return sf, false, nil
+}
+
+// Map fields may have key types of non-float scalars, strings and enums.
+// The easiest way to sort them in some deterministic order is to use fmt.
+// If this turns out to be inefficient we can always consider other options,
+// such as doing a Schwartzian transform.
+
+func mapKeys(vs []reflect.Value) sort.Interface {
+ s := mapKeySorter{
+ vs: vs,
+ // default Less function: textual comparison
+ less: func(a, b reflect.Value) bool {
+ return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface())
+ },
+ }
+
+ // Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps;
+ // numeric keys are sorted numerically.
+ if len(vs) == 0 {
+ return s
+ }
+ switch vs[0].Kind() {
+ case reflect.Int32, reflect.Int64:
+ s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
+ case reflect.Uint32, reflect.Uint64:
+ s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
+ }
+
+ return s
+}
+
+type mapKeySorter struct {
+ vs []reflect.Value
+ less func(a, b reflect.Value) bool
+}
+
+func (s mapKeySorter) Len() int { return len(s.vs) }
+func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] }
+func (s mapKeySorter) Less(i, j int) bool {
+ return s.less(s.vs[i], s.vs[j])
+}
+
+// isProto3Zero reports whether v is a zero proto3 value.
+func isProto3Zero(v reflect.Value) bool {
+ switch v.Kind() {
+ case reflect.Bool:
+ return !v.Bool()
+ case reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Uint32, reflect.Uint64:
+ return v.Uint() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ case reflect.String:
+ return v.String() == ""
+ }
+ return false
+}
+
+// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
+// to assert that that code is compatible with this version of the proto package.
+const ProtoPackageIsVersion2 = true
+
+// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
+// to assert that that code is compatible with this version of the proto package.
+const ProtoPackageIsVersion1 = true
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+/*
+ * Support for message sets.
+ */
+
+import (
+ "bytes"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "reflect"
+ "sort"
+)
+
+// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
+// A message type ID is required for storing a protocol buffer in a message set.
+var errNoMessageTypeID = errors.New("proto does not have a message type ID")
+
+// The first two types (_MessageSet_Item and messageSet)
+// model what the protocol compiler produces for the following protocol message:
+// message MessageSet {
+// repeated group Item = 1 {
+// required int32 type_id = 2;
+// required string message = 3;
+// };
+// }
+// That is the MessageSet wire format. We can't use a proto to generate these
+// because that would introduce a circular dependency between it and this package.
+
+type _MessageSet_Item struct {
+ TypeId *int32 `protobuf:"varint,2,req,name=type_id"`
+ Message []byte `protobuf:"bytes,3,req,name=message"`
+}
+
+type messageSet struct {
+ Item []*_MessageSet_Item `protobuf:"group,1,rep"`
+ XXX_unrecognized []byte
+ // TODO: caching?
+}
+
+// Make sure messageSet is a Message.
+var _ Message = (*messageSet)(nil)
+
+// messageTypeIder is an interface satisfied by a protocol buffer type
+// that may be stored in a MessageSet.
+type messageTypeIder interface {
+ MessageTypeId() int32
+}
+
+func (ms *messageSet) find(pb Message) *_MessageSet_Item {
+ mti, ok := pb.(messageTypeIder)
+ if !ok {
+ return nil
+ }
+ id := mti.MessageTypeId()
+ for _, item := range ms.Item {
+ if *item.TypeId == id {
+ return item
+ }
+ }
+ return nil
+}
+
+func (ms *messageSet) Has(pb Message) bool {
+ if ms.find(pb) != nil {
+ return true
+ }
+ return false
+}
+
+func (ms *messageSet) Unmarshal(pb Message) error {
+ if item := ms.find(pb); item != nil {
+ return Unmarshal(item.Message, pb)
+ }
+ if _, ok := pb.(messageTypeIder); !ok {
+ return errNoMessageTypeID
+ }
+ return nil // TODO: return error instead?
+}
+
+func (ms *messageSet) Marshal(pb Message) error {
+ msg, err := Marshal(pb)
+ if err != nil {
+ return err
+ }
+ if item := ms.find(pb); item != nil {
+ // reuse existing item
+ item.Message = msg
+ return nil
+ }
+
+ mti, ok := pb.(messageTypeIder)
+ if !ok {
+ return errNoMessageTypeID
+ }
+
+ mtid := mti.MessageTypeId()
+ ms.Item = append(ms.Item, &_MessageSet_Item{
+ TypeId: &mtid,
+ Message: msg,
+ })
+ return nil
+}
+
+func (ms *messageSet) Reset() { *ms = messageSet{} }
+func (ms *messageSet) String() string { return CompactTextString(ms) }
+func (*messageSet) ProtoMessage() {}
+
+// Support for the message_set_wire_format message option.
+
+func skipVarint(buf []byte) []byte {
+ i := 0
+ for ; buf[i]&0x80 != 0; i++ {
+ }
+ return buf[i+1:]
+}
+
+// MarshalMessageSet encodes the extension map represented by m in the message set wire format.
+// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
+func MarshalMessageSet(exts interface{}) ([]byte, error) {
+ var m map[int32]Extension
+ switch exts := exts.(type) {
+ case *XXX_InternalExtensions:
+ if err := encodeExtensions(exts); err != nil {
+ return nil, err
+ }
+ m, _ = exts.extensionsRead()
+ case map[int32]Extension:
+ if err := encodeExtensionsMap(exts); err != nil {
+ return nil, err
+ }
+ m = exts
+ default:
+ return nil, errors.New("proto: not an extension map")
+ }
+
+ // Sort extension IDs to provide a deterministic encoding.
+ // See also enc_map in encode.go.
+ ids := make([]int, 0, len(m))
+ for id := range m {
+ ids = append(ids, int(id))
+ }
+ sort.Ints(ids)
+
+ ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))}
+ for _, id := range ids {
+ e := m[int32(id)]
+ // Remove the wire type and field number varint, as well as the length varint.
+ msg := skipVarint(skipVarint(e.enc))
+
+ ms.Item = append(ms.Item, &_MessageSet_Item{
+ TypeId: Int32(int32(id)),
+ Message: msg,
+ })
+ }
+ return Marshal(ms)
+}
+
+// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
+// It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
+func UnmarshalMessageSet(buf []byte, exts interface{}) error {
+ var m map[int32]Extension
+ switch exts := exts.(type) {
+ case *XXX_InternalExtensions:
+ m = exts.extensionsWrite()
+ case map[int32]Extension:
+ m = exts
+ default:
+ return errors.New("proto: not an extension map")
+ }
+
+ ms := new(messageSet)
+ if err := Unmarshal(buf, ms); err != nil {
+ return err
+ }
+ for _, item := range ms.Item {
+ id := *item.TypeId
+ msg := item.Message
+
+ // Restore wire type and field number varint, plus length varint.
+ // Be careful to preserve duplicate items.
+ b := EncodeVarint(uint64(id)<<3 | WireBytes)
+ if ext, ok := m[id]; ok {
+ // Existing data; rip off the tag and length varint
+ // so we join the new data correctly.
+ // We can assume that ext.enc is set because we are unmarshaling.
+ o := ext.enc[len(b):] // skip wire type and field number
+ _, n := DecodeVarint(o) // calculate length of length varint
+ o = o[n:] // skip length varint
+ msg = append(o, msg...) // join old data and new data
+ }
+ b = append(b, EncodeVarint(uint64(len(msg)))...)
+ b = append(b, msg...)
+
+ m[id] = Extension{enc: b}
+ }
+ return nil
+}
+
+// MarshalMessageSetJSON encodes the extension map represented by m in JSON format.
+// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
+func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
+ var m map[int32]Extension
+ switch exts := exts.(type) {
+ case *XXX_InternalExtensions:
+ m, _ = exts.extensionsRead()
+ case map[int32]Extension:
+ m = exts
+ default:
+ return nil, errors.New("proto: not an extension map")
+ }
+ var b bytes.Buffer
+ b.WriteByte('{')
+
+ // Process the map in key order for deterministic output.
+ ids := make([]int32, 0, len(m))
+ for id := range m {
+ ids = append(ids, id)
+ }
+ sort.Sort(int32Slice(ids)) // int32Slice defined in text.go
+
+ for i, id := range ids {
+ ext := m[id]
+ if i > 0 {
+ b.WriteByte(',')
+ }
+
+ msd, ok := messageSetMap[id]
+ if !ok {
+ // Unknown type; we can't render it, so skip it.
+ continue
+ }
+ fmt.Fprintf(&b, `"[%s]":`, msd.name)
+
+ x := ext.value
+ if x == nil {
+ x = reflect.New(msd.t.Elem()).Interface()
+ if err := Unmarshal(ext.enc, x.(Message)); err != nil {
+ return nil, err
+ }
+ }
+ d, err := json.Marshal(x)
+ if err != nil {
+ return nil, err
+ }
+ b.Write(d)
+ }
+ b.WriteByte('}')
+ return b.Bytes(), nil
+}
+
+// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format.
+// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
+func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error {
+ // Common-case fast path.
+ if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) {
+ return nil
+ }
+
+ // This is fairly tricky, and it's not clear that it is needed.
+ return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented")
+}
+
+// A global registry of types that can be used in a MessageSet.
+
+var messageSetMap = make(map[int32]messageSetDesc)
+
+type messageSetDesc struct {
+ t reflect.Type // pointer to struct
+ name string
+}
+
+// RegisterMessageSetType is called from the generated code.
+func RegisterMessageSetType(m Message, fieldNum int32, name string) {
+ messageSetMap[fieldNum] = messageSetDesc{
+ t: reflect.TypeOf(m),
+ name: name,
+ }
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2012 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// +build appengine js
+
+// This file contains an implementation of proto field accesses using package reflect.
+// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can
+// be used on App Engine.
+
+package proto
+
+import (
+ "math"
+ "reflect"
+)
+
+// A structPointer is a pointer to a struct.
+type structPointer struct {
+ v reflect.Value
+}
+
+// toStructPointer returns a structPointer equivalent to the given reflect value.
+// The reflect value must itself be a pointer to a struct.
+func toStructPointer(v reflect.Value) structPointer {
+ return structPointer{v}
+}
+
+// IsNil reports whether p is nil.
+func structPointer_IsNil(p structPointer) bool {
+ return p.v.IsNil()
+}
+
+// Interface returns the struct pointer as an interface value.
+func structPointer_Interface(p structPointer, _ reflect.Type) interface{} {
+ return p.v.Interface()
+}
+
+// A field identifies a field in a struct, accessible from a structPointer.
+// In this implementation, a field is identified by the sequence of field indices
+// passed to reflect's FieldByIndex.
+type field []int
+
+// toField returns a field equivalent to the given reflect field.
+func toField(f *reflect.StructField) field {
+ return f.Index
+}
+
+// invalidField is an invalid field identifier.
+var invalidField = field(nil)
+
+// IsValid reports whether the field identifier is valid.
+func (f field) IsValid() bool { return f != nil }
+
+// field returns the given field in the struct as a reflect value.
+func structPointer_field(p structPointer, f field) reflect.Value {
+ // Special case: an extension map entry with a value of type T
+ // passes a *T to the struct-handling code with a zero field,
+ // expecting that it will be treated as equivalent to *struct{ X T },
+ // which has the same memory layout. We have to handle that case
+ // specially, because reflect will panic if we call FieldByIndex on a
+ // non-struct.
+ if f == nil {
+ return p.v.Elem()
+ }
+
+ return p.v.Elem().FieldByIndex(f)
+}
+
+// ifield returns the given field in the struct as an interface value.
+func structPointer_ifield(p structPointer, f field) interface{} {
+ return structPointer_field(p, f).Addr().Interface()
+}
+
+// Bytes returns the address of a []byte field in the struct.
+func structPointer_Bytes(p structPointer, f field) *[]byte {
+ return structPointer_ifield(p, f).(*[]byte)
+}
+
+// BytesSlice returns the address of a [][]byte field in the struct.
+func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
+ return structPointer_ifield(p, f).(*[][]byte)
+}
+
+// Bool returns the address of a *bool field in the struct.
+func structPointer_Bool(p structPointer, f field) **bool {
+ return structPointer_ifield(p, f).(**bool)
+}
+
+// BoolVal returns the address of a bool field in the struct.
+func structPointer_BoolVal(p structPointer, f field) *bool {
+ return structPointer_ifield(p, f).(*bool)
+}
+
+// BoolSlice returns the address of a []bool field in the struct.
+func structPointer_BoolSlice(p structPointer, f field) *[]bool {
+ return structPointer_ifield(p, f).(*[]bool)
+}
+
+// String returns the address of a *string field in the struct.
+func structPointer_String(p structPointer, f field) **string {
+ return structPointer_ifield(p, f).(**string)
+}
+
+// StringVal returns the address of a string field in the struct.
+func structPointer_StringVal(p structPointer, f field) *string {
+ return structPointer_ifield(p, f).(*string)
+}
+
+// StringSlice returns the address of a []string field in the struct.
+func structPointer_StringSlice(p structPointer, f field) *[]string {
+ return structPointer_ifield(p, f).(*[]string)
+}
+
+// Extensions returns the address of an extension map field in the struct.
+func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
+ return structPointer_ifield(p, f).(*XXX_InternalExtensions)
+}
+
+// ExtMap returns the address of an extension map field in the struct.
+func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
+ return structPointer_ifield(p, f).(*map[int32]Extension)
+}
+
+// NewAt returns the reflect.Value for a pointer to a field in the struct.
+func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
+ return structPointer_field(p, f).Addr()
+}
+
+// SetStructPointer writes a *struct field in the struct.
+func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
+ structPointer_field(p, f).Set(q.v)
+}
+
+// GetStructPointer reads a *struct field in the struct.
+func structPointer_GetStructPointer(p structPointer, f field) structPointer {
+ return structPointer{structPointer_field(p, f)}
+}
+
+// StructPointerSlice the address of a []*struct field in the struct.
+func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice {
+ return structPointerSlice{structPointer_field(p, f)}
+}
+
+// A structPointerSlice represents the address of a slice of pointers to structs
+// (themselves messages or groups). That is, v.Type() is *[]*struct{...}.
+type structPointerSlice struct {
+ v reflect.Value
+}
+
+func (p structPointerSlice) Len() int { return p.v.Len() }
+func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} }
+func (p structPointerSlice) Append(q structPointer) {
+ p.v.Set(reflect.Append(p.v, q.v))
+}
+
+var (
+ int32Type = reflect.TypeOf(int32(0))
+ uint32Type = reflect.TypeOf(uint32(0))
+ float32Type = reflect.TypeOf(float32(0))
+ int64Type = reflect.TypeOf(int64(0))
+ uint64Type = reflect.TypeOf(uint64(0))
+ float64Type = reflect.TypeOf(float64(0))
+)
+
+// A word32 represents a field of type *int32, *uint32, *float32, or *enum.
+// That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable.
+type word32 struct {
+ v reflect.Value
+}
+
+// IsNil reports whether p is nil.
+func word32_IsNil(p word32) bool {
+ return p.v.IsNil()
+}
+
+// Set sets p to point at a newly allocated word with bits set to x.
+func word32_Set(p word32, o *Buffer, x uint32) {
+ t := p.v.Type().Elem()
+ switch t {
+ case int32Type:
+ if len(o.int32s) == 0 {
+ o.int32s = make([]int32, uint32PoolSize)
+ }
+ o.int32s[0] = int32(x)
+ p.v.Set(reflect.ValueOf(&o.int32s[0]))
+ o.int32s = o.int32s[1:]
+ return
+ case uint32Type:
+ if len(o.uint32s) == 0 {
+ o.uint32s = make([]uint32, uint32PoolSize)
+ }
+ o.uint32s[0] = x
+ p.v.Set(reflect.ValueOf(&o.uint32s[0]))
+ o.uint32s = o.uint32s[1:]
+ return
+ case float32Type:
+ if len(o.float32s) == 0 {
+ o.float32s = make([]float32, uint32PoolSize)
+ }
+ o.float32s[0] = math.Float32frombits(x)
+ p.v.Set(reflect.ValueOf(&o.float32s[0]))
+ o.float32s = o.float32s[1:]
+ return
+ }
+
+ // must be enum
+ p.v.Set(reflect.New(t))
+ p.v.Elem().SetInt(int64(int32(x)))
+}
+
+// Get gets the bits pointed at by p, as a uint32.
+func word32_Get(p word32) uint32 {
+ elem := p.v.Elem()
+ switch elem.Kind() {
+ case reflect.Int32:
+ return uint32(elem.Int())
+ case reflect.Uint32:
+ return uint32(elem.Uint())
+ case reflect.Float32:
+ return math.Float32bits(float32(elem.Float()))
+ }
+ panic("unreachable")
+}
+
+// Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct.
+func structPointer_Word32(p structPointer, f field) word32 {
+ return word32{structPointer_field(p, f)}
+}
+
+// A word32Val represents a field of type int32, uint32, float32, or enum.
+// That is, v.Type() is int32, uint32, float32, or enum and v is assignable.
+type word32Val struct {
+ v reflect.Value
+}
+
+// Set sets *p to x.
+func word32Val_Set(p word32Val, x uint32) {
+ switch p.v.Type() {
+ case int32Type:
+ p.v.SetInt(int64(x))
+ return
+ case uint32Type:
+ p.v.SetUint(uint64(x))
+ return
+ case float32Type:
+ p.v.SetFloat(float64(math.Float32frombits(x)))
+ return
+ }
+
+ // must be enum
+ p.v.SetInt(int64(int32(x)))
+}
+
+// Get gets the bits pointed at by p, as a uint32.
+func word32Val_Get(p word32Val) uint32 {
+ elem := p.v
+ switch elem.Kind() {
+ case reflect.Int32:
+ return uint32(elem.Int())
+ case reflect.Uint32:
+ return uint32(elem.Uint())
+ case reflect.Float32:
+ return math.Float32bits(float32(elem.Float()))
+ }
+ panic("unreachable")
+}
+
+// Word32Val returns a reference to a int32, uint32, float32, or enum field in the struct.
+func structPointer_Word32Val(p structPointer, f field) word32Val {
+ return word32Val{structPointer_field(p, f)}
+}
+
+// A word32Slice is a slice of 32-bit values.
+// That is, v.Type() is []int32, []uint32, []float32, or []enum.
+type word32Slice struct {
+ v reflect.Value
+}
+
+func (p word32Slice) Append(x uint32) {
+ n, m := p.v.Len(), p.v.Cap()
+ if n < m {
+ p.v.SetLen(n + 1)
+ } else {
+ t := p.v.Type().Elem()
+ p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
+ }
+ elem := p.v.Index(n)
+ switch elem.Kind() {
+ case reflect.Int32:
+ elem.SetInt(int64(int32(x)))
+ case reflect.Uint32:
+ elem.SetUint(uint64(x))
+ case reflect.Float32:
+ elem.SetFloat(float64(math.Float32frombits(x)))
+ }
+}
+
+func (p word32Slice) Len() int {
+ return p.v.Len()
+}
+
+func (p word32Slice) Index(i int) uint32 {
+ elem := p.v.Index(i)
+ switch elem.Kind() {
+ case reflect.Int32:
+ return uint32(elem.Int())
+ case reflect.Uint32:
+ return uint32(elem.Uint())
+ case reflect.Float32:
+ return math.Float32bits(float32(elem.Float()))
+ }
+ panic("unreachable")
+}
+
+// Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct.
+func structPointer_Word32Slice(p structPointer, f field) word32Slice {
+ return word32Slice{structPointer_field(p, f)}
+}
+
+// word64 is like word32 but for 64-bit values.
+type word64 struct {
+ v reflect.Value
+}
+
+func word64_Set(p word64, o *Buffer, x uint64) {
+ t := p.v.Type().Elem()
+ switch t {
+ case int64Type:
+ if len(o.int64s) == 0 {
+ o.int64s = make([]int64, uint64PoolSize)
+ }
+ o.int64s[0] = int64(x)
+ p.v.Set(reflect.ValueOf(&o.int64s[0]))
+ o.int64s = o.int64s[1:]
+ return
+ case uint64Type:
+ if len(o.uint64s) == 0 {
+ o.uint64s = make([]uint64, uint64PoolSize)
+ }
+ o.uint64s[0] = x
+ p.v.Set(reflect.ValueOf(&o.uint64s[0]))
+ o.uint64s = o.uint64s[1:]
+ return
+ case float64Type:
+ if len(o.float64s) == 0 {
+ o.float64s = make([]float64, uint64PoolSize)
+ }
+ o.float64s[0] = math.Float64frombits(x)
+ p.v.Set(reflect.ValueOf(&o.float64s[0]))
+ o.float64s = o.float64s[1:]
+ return
+ }
+ panic("unreachable")
+}
+
+func word64_IsNil(p word64) bool {
+ return p.v.IsNil()
+}
+
+func word64_Get(p word64) uint64 {
+ elem := p.v.Elem()
+ switch elem.Kind() {
+ case reflect.Int64:
+ return uint64(elem.Int())
+ case reflect.Uint64:
+ return elem.Uint()
+ case reflect.Float64:
+ return math.Float64bits(elem.Float())
+ }
+ panic("unreachable")
+}
+
+func structPointer_Word64(p structPointer, f field) word64 {
+ return word64{structPointer_field(p, f)}
+}
+
+// word64Val is like word32Val but for 64-bit values.
+type word64Val struct {
+ v reflect.Value
+}
+
+func word64Val_Set(p word64Val, o *Buffer, x uint64) {
+ switch p.v.Type() {
+ case int64Type:
+ p.v.SetInt(int64(x))
+ return
+ case uint64Type:
+ p.v.SetUint(x)
+ return
+ case float64Type:
+ p.v.SetFloat(math.Float64frombits(x))
+ return
+ }
+ panic("unreachable")
+}
+
+func word64Val_Get(p word64Val) uint64 {
+ elem := p.v
+ switch elem.Kind() {
+ case reflect.Int64:
+ return uint64(elem.Int())
+ case reflect.Uint64:
+ return elem.Uint()
+ case reflect.Float64:
+ return math.Float64bits(elem.Float())
+ }
+ panic("unreachable")
+}
+
+func structPointer_Word64Val(p structPointer, f field) word64Val {
+ return word64Val{structPointer_field(p, f)}
+}
+
+type word64Slice struct {
+ v reflect.Value
+}
+
+func (p word64Slice) Append(x uint64) {
+ n, m := p.v.Len(), p.v.Cap()
+ if n < m {
+ p.v.SetLen(n + 1)
+ } else {
+ t := p.v.Type().Elem()
+ p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
+ }
+ elem := p.v.Index(n)
+ switch elem.Kind() {
+ case reflect.Int64:
+ elem.SetInt(int64(int64(x)))
+ case reflect.Uint64:
+ elem.SetUint(uint64(x))
+ case reflect.Float64:
+ elem.SetFloat(float64(math.Float64frombits(x)))
+ }
+}
+
+func (p word64Slice) Len() int {
+ return p.v.Len()
+}
+
+func (p word64Slice) Index(i int) uint64 {
+ elem := p.v.Index(i)
+ switch elem.Kind() {
+ case reflect.Int64:
+ return uint64(elem.Int())
+ case reflect.Uint64:
+ return uint64(elem.Uint())
+ case reflect.Float64:
+ return math.Float64bits(float64(elem.Float()))
+ }
+ panic("unreachable")
+}
+
+func structPointer_Word64Slice(p structPointer, f field) word64Slice {
+ return word64Slice{structPointer_field(p, f)}
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2012 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// +build !appengine,!js
+
+// This file contains the implementation of the proto field accesses using package unsafe.
+
+package proto
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+// NOTE: These type_Foo functions would more idiomatically be methods,
+// but Go does not allow methods on pointer types, and we must preserve
+// some pointer type for the garbage collector. We use these
+// funcs with clunky names as our poor approximation to methods.
+//
+// An alternative would be
+// type structPointer struct { p unsafe.Pointer }
+// but that does not registerize as well.
+
+// A structPointer is a pointer to a struct.
+type structPointer unsafe.Pointer
+
+// toStructPointer returns a structPointer equivalent to the given reflect value.
+func toStructPointer(v reflect.Value) structPointer {
+ return structPointer(unsafe.Pointer(v.Pointer()))
+}
+
+// IsNil reports whether p is nil.
+func structPointer_IsNil(p structPointer) bool {
+ return p == nil
+}
+
+// Interface returns the struct pointer, assumed to have element type t,
+// as an interface value.
+func structPointer_Interface(p structPointer, t reflect.Type) interface{} {
+ return reflect.NewAt(t, unsafe.Pointer(p)).Interface()
+}
+
+// A field identifies a field in a struct, accessible from a structPointer.
+// In this implementation, a field is identified by its byte offset from the start of the struct.
+type field uintptr
+
+// toField returns a field equivalent to the given reflect field.
+func toField(f *reflect.StructField) field {
+ return field(f.Offset)
+}
+
+// invalidField is an invalid field identifier.
+const invalidField = ^field(0)
+
+// IsValid reports whether the field identifier is valid.
+func (f field) IsValid() bool {
+ return f != ^field(0)
+}
+
+// Bytes returns the address of a []byte field in the struct.
+func structPointer_Bytes(p structPointer, f field) *[]byte {
+ return (*[]byte)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// BytesSlice returns the address of a [][]byte field in the struct.
+func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
+ return (*[][]byte)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// Bool returns the address of a *bool field in the struct.
+func structPointer_Bool(p structPointer, f field) **bool {
+ return (**bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// BoolVal returns the address of a bool field in the struct.
+func structPointer_BoolVal(p structPointer, f field) *bool {
+ return (*bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// BoolSlice returns the address of a []bool field in the struct.
+func structPointer_BoolSlice(p structPointer, f field) *[]bool {
+ return (*[]bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// String returns the address of a *string field in the struct.
+func structPointer_String(p structPointer, f field) **string {
+ return (**string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// StringVal returns the address of a string field in the struct.
+func structPointer_StringVal(p structPointer, f field) *string {
+ return (*string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// StringSlice returns the address of a []string field in the struct.
+func structPointer_StringSlice(p structPointer, f field) *[]string {
+ return (*[]string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// ExtMap returns the address of an extension map field in the struct.
+func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
+ return (*XXX_InternalExtensions)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
+ return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// NewAt returns the reflect.Value for a pointer to a field in the struct.
+func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
+ return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f)))
+}
+
+// SetStructPointer writes a *struct field in the struct.
+func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
+ *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) = q
+}
+
+// GetStructPointer reads a *struct field in the struct.
+func structPointer_GetStructPointer(p structPointer, f field) structPointer {
+ return *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// StructPointerSlice the address of a []*struct field in the struct.
+func structPointer_StructPointerSlice(p structPointer, f field) *structPointerSlice {
+ return (*structPointerSlice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// A structPointerSlice represents a slice of pointers to structs (themselves submessages or groups).
+type structPointerSlice []structPointer
+
+func (v *structPointerSlice) Len() int { return len(*v) }
+func (v *structPointerSlice) Index(i int) structPointer { return (*v)[i] }
+func (v *structPointerSlice) Append(p structPointer) { *v = append(*v, p) }
+
+// A word32 is the address of a "pointer to 32-bit value" field.
+type word32 **uint32
+
+// IsNil reports whether *v is nil.
+func word32_IsNil(p word32) bool {
+ return *p == nil
+}
+
+// Set sets *v to point at a newly allocated word set to x.
+func word32_Set(p word32, o *Buffer, x uint32) {
+ if len(o.uint32s) == 0 {
+ o.uint32s = make([]uint32, uint32PoolSize)
+ }
+ o.uint32s[0] = x
+ *p = &o.uint32s[0]
+ o.uint32s = o.uint32s[1:]
+}
+
+// Get gets the value pointed at by *v.
+func word32_Get(p word32) uint32 {
+ return **p
+}
+
+// Word32 returns the address of a *int32, *uint32, *float32, or *enum field in the struct.
+func structPointer_Word32(p structPointer, f field) word32 {
+ return word32((**uint32)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+}
+
+// A word32Val is the address of a 32-bit value field.
+type word32Val *uint32
+
+// Set sets *p to x.
+func word32Val_Set(p word32Val, x uint32) {
+ *p = x
+}
+
+// Get gets the value pointed at by p.
+func word32Val_Get(p word32Val) uint32 {
+ return *p
+}
+
+// Word32Val returns the address of a *int32, *uint32, *float32, or *enum field in the struct.
+func structPointer_Word32Val(p structPointer, f field) word32Val {
+ return word32Val((*uint32)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+}
+
+// A word32Slice is a slice of 32-bit values.
+type word32Slice []uint32
+
+func (v *word32Slice) Append(x uint32) { *v = append(*v, x) }
+func (v *word32Slice) Len() int { return len(*v) }
+func (v *word32Slice) Index(i int) uint32 { return (*v)[i] }
+
+// Word32Slice returns the address of a []int32, []uint32, []float32, or []enum field in the struct.
+func structPointer_Word32Slice(p structPointer, f field) *word32Slice {
+ return (*word32Slice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// word64 is like word32 but for 64-bit values.
+type word64 **uint64
+
+func word64_Set(p word64, o *Buffer, x uint64) {
+ if len(o.uint64s) == 0 {
+ o.uint64s = make([]uint64, uint64PoolSize)
+ }
+ o.uint64s[0] = x
+ *p = &o.uint64s[0]
+ o.uint64s = o.uint64s[1:]
+}
+
+func word64_IsNil(p word64) bool {
+ return *p == nil
+}
+
+func word64_Get(p word64) uint64 {
+ return **p
+}
+
+func structPointer_Word64(p structPointer, f field) word64 {
+ return word64((**uint64)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+}
+
+// word64Val is like word32Val but for 64-bit values.
+type word64Val *uint64
+
+func word64Val_Set(p word64Val, o *Buffer, x uint64) {
+ *p = x
+}
+
+func word64Val_Get(p word64Val) uint64 {
+ return *p
+}
+
+func structPointer_Word64Val(p structPointer, f field) word64Val {
+ return word64Val((*uint64)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+}
+
+// word64Slice is like word32Slice but for 64-bit values.
+type word64Slice []uint64
+
+func (v *word64Slice) Append(x uint64) { *v = append(*v, x) }
+func (v *word64Slice) Len() int { return len(*v) }
+func (v *word64Slice) Index(i int) uint64 { return (*v)[i] }
+
+func structPointer_Word64Slice(p structPointer, f field) *word64Slice {
+ return (*word64Slice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+/*
+ * Routines for encoding data into the wire format for protocol buffers.
+ */
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "reflect"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+)
+
+const debug bool = false
+
+// Constants that identify the encoding of a value on the wire.
+const (
+ WireVarint = 0
+ WireFixed64 = 1
+ WireBytes = 2
+ WireStartGroup = 3
+ WireEndGroup = 4
+ WireFixed32 = 5
+)
+
+const startSize = 10 // initial slice/string sizes
+
+// Encoders are defined in encode.go
+// An encoder outputs the full representation of a field, including its
+// tag and encoder type.
+type encoder func(p *Buffer, prop *Properties, base structPointer) error
+
+// A valueEncoder encodes a single integer in a particular encoding.
+type valueEncoder func(o *Buffer, x uint64) error
+
+// Sizers are defined in encode.go
+// A sizer returns the encoded size of a field, including its tag and encoder
+// type.
+type sizer func(prop *Properties, base structPointer) int
+
+// A valueSizer returns the encoded size of a single integer in a particular
+// encoding.
+type valueSizer func(x uint64) int
+
+// Decoders are defined in decode.go
+// A decoder creates a value from its wire representation.
+// Unrecognized subelements are saved in unrec.
+type decoder func(p *Buffer, prop *Properties, base structPointer) error
+
+// A valueDecoder decodes a single integer in a particular encoding.
+type valueDecoder func(o *Buffer) (x uint64, err error)
+
+// A oneofMarshaler does the marshaling for all oneof fields in a message.
+type oneofMarshaler func(Message, *Buffer) error
+
+// A oneofUnmarshaler does the unmarshaling for a oneof field in a message.
+type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error)
+
+// A oneofSizer does the sizing for all oneof fields in a message.
+type oneofSizer func(Message) int
+
+// tagMap is an optimization over map[int]int for typical protocol buffer
+// use-cases. Encoded protocol buffers are often in tag order with small tag
+// numbers.
+type tagMap struct {
+ fastTags []int
+ slowTags map[int]int
+}
+
+// tagMapFastLimit is the upper bound on the tag number that will be stored in
+// the tagMap slice rather than its map.
+const tagMapFastLimit = 1024
+
+func (p *tagMap) get(t int) (int, bool) {
+ if t > 0 && t < tagMapFastLimit {
+ if t >= len(p.fastTags) {
+ return 0, false
+ }
+ fi := p.fastTags[t]
+ return fi, fi >= 0
+ }
+ fi, ok := p.slowTags[t]
+ return fi, ok
+}
+
+func (p *tagMap) put(t int, fi int) {
+ if t > 0 && t < tagMapFastLimit {
+ for len(p.fastTags) < t+1 {
+ p.fastTags = append(p.fastTags, -1)
+ }
+ p.fastTags[t] = fi
+ return
+ }
+ if p.slowTags == nil {
+ p.slowTags = make(map[int]int)
+ }
+ p.slowTags[t] = fi
+}
+
+// StructProperties represents properties for all the fields of a struct.
+// decoderTags and decoderOrigNames should only be used by the decoder.
+type StructProperties struct {
+ Prop []*Properties // properties for each field
+ reqCount int // required count
+ decoderTags tagMap // map from proto tag to struct field number
+ decoderOrigNames map[string]int // map from original name to struct field number
+ order []int // list of struct field numbers in tag order
+ unrecField field // field id of the XXX_unrecognized []byte field
+ extendable bool // is this an extendable proto
+
+ oneofMarshaler oneofMarshaler
+ oneofUnmarshaler oneofUnmarshaler
+ oneofSizer oneofSizer
+ stype reflect.Type
+
+ // OneofTypes contains information about the oneof fields in this message.
+ // It is keyed by the original name of a field.
+ OneofTypes map[string]*OneofProperties
+}
+
+// OneofProperties represents information about a specific field in a oneof.
+type OneofProperties struct {
+ Type reflect.Type // pointer to generated struct type for this oneof field
+ Field int // struct field number of the containing oneof in the message
+ Prop *Properties
+}
+
+// Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec.
+// See encode.go, (*Buffer).enc_struct.
+
+func (sp *StructProperties) Len() int { return len(sp.order) }
+func (sp *StructProperties) Less(i, j int) bool {
+ return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag
+}
+func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] }
+
+// Properties represents the protocol-specific behavior of a single struct field.
+type Properties struct {
+ Name string // name of the field, for error messages
+ OrigName string // original name before protocol compiler (always set)
+ JSONName string // name to use for JSON; determined by protoc
+ Wire string
+ WireType int
+ Tag int
+ Required bool
+ Optional bool
+ Repeated bool
+ Packed bool // relevant for repeated primitives only
+ Enum string // set for enum types only
+ proto3 bool // whether this is known to be a proto3 field; set for []byte only
+ oneof bool // whether this is a oneof field
+
+ Default string // default value
+ HasDefault bool // whether an explicit default was provided
+ def_uint64 uint64
+
+ enc encoder
+ valEnc valueEncoder // set for bool and numeric types only
+ field field
+ tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType)
+ tagbuf [8]byte
+ stype reflect.Type // set for struct types only
+ sprop *StructProperties // set for struct types only
+ isMarshaler bool
+ isUnmarshaler bool
+
+ mtype reflect.Type // set for map types only
+ mkeyprop *Properties // set for map types only
+ mvalprop *Properties // set for map types only
+
+ size sizer
+ valSize valueSizer // set for bool and numeric types only
+
+ dec decoder
+ valDec valueDecoder // set for bool and numeric types only
+
+ // If this is a packable field, this will be the decoder for the packed version of the field.
+ packedDec decoder
+}
+
+// String formats the properties in the protobuf struct field tag style.
+func (p *Properties) String() string {
+ s := p.Wire
+ s = ","
+ s += strconv.Itoa(p.Tag)
+ if p.Required {
+ s += ",req"
+ }
+ if p.Optional {
+ s += ",opt"
+ }
+ if p.Repeated {
+ s += ",rep"
+ }
+ if p.Packed {
+ s += ",packed"
+ }
+ s += ",name=" + p.OrigName
+ if p.JSONName != p.OrigName {
+ s += ",json=" + p.JSONName
+ }
+ if p.proto3 {
+ s += ",proto3"
+ }
+ if p.oneof {
+ s += ",oneof"
+ }
+ if len(p.Enum) > 0 {
+ s += ",enum=" + p.Enum
+ }
+ if p.HasDefault {
+ s += ",def=" + p.Default
+ }
+ return s
+}
+
+// Parse populates p by parsing a string in the protobuf struct field tag style.
+func (p *Properties) Parse(s string) {
+ // "bytes,49,opt,name=foo,def=hello!"
+ fields := strings.Split(s, ",") // breaks def=, but handled below.
+ if len(fields) < 2 {
+ fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s)
+ return
+ }
+
+ p.Wire = fields[0]
+ switch p.Wire {
+ case "varint":
+ p.WireType = WireVarint
+ p.valEnc = (*Buffer).EncodeVarint
+ p.valDec = (*Buffer).DecodeVarint
+ p.valSize = sizeVarint
+ case "fixed32":
+ p.WireType = WireFixed32
+ p.valEnc = (*Buffer).EncodeFixed32
+ p.valDec = (*Buffer).DecodeFixed32
+ p.valSize = sizeFixed32
+ case "fixed64":
+ p.WireType = WireFixed64
+ p.valEnc = (*Buffer).EncodeFixed64
+ p.valDec = (*Buffer).DecodeFixed64
+ p.valSize = sizeFixed64
+ case "zigzag32":
+ p.WireType = WireVarint
+ p.valEnc = (*Buffer).EncodeZigzag32
+ p.valDec = (*Buffer).DecodeZigzag32
+ p.valSize = sizeZigzag32
+ case "zigzag64":
+ p.WireType = WireVarint
+ p.valEnc = (*Buffer).EncodeZigzag64
+ p.valDec = (*Buffer).DecodeZigzag64
+ p.valSize = sizeZigzag64
+ case "bytes", "group":
+ p.WireType = WireBytes
+ // no numeric converter for non-numeric types
+ default:
+ fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s)
+ return
+ }
+
+ var err error
+ p.Tag, err = strconv.Atoi(fields[1])
+ if err != nil {
+ return
+ }
+
+ for i := 2; i < len(fields); i++ {
+ f := fields[i]
+ switch {
+ case f == "req":
+ p.Required = true
+ case f == "opt":
+ p.Optional = true
+ case f == "rep":
+ p.Repeated = true
+ case f == "packed":
+ p.Packed = true
+ case strings.HasPrefix(f, "name="):
+ p.OrigName = f[5:]
+ case strings.HasPrefix(f, "json="):
+ p.JSONName = f[5:]
+ case strings.HasPrefix(f, "enum="):
+ p.Enum = f[5:]
+ case f == "proto3":
+ p.proto3 = true
+ case f == "oneof":
+ p.oneof = true
+ case strings.HasPrefix(f, "def="):
+ p.HasDefault = true
+ p.Default = f[4:] // rest of string
+ if i+1 < len(fields) {
+ // Commas aren't escaped, and def is always last.
+ p.Default += "," + strings.Join(fields[i+1:], ",")
+ break
+ }
+ }
+ }
+}
+
+func logNoSliceEnc(t1, t2 reflect.Type) {
+ fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2)
+}
+
+var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
+
+// Initialize the fields for encoding and decoding.
+func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
+ p.enc = nil
+ p.dec = nil
+ p.size = nil
+
+ switch t1 := typ; t1.Kind() {
+ default:
+ fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1)
+
+ // proto3 scalar types
+
+ case reflect.Bool:
+ p.enc = (*Buffer).enc_proto3_bool
+ p.dec = (*Buffer).dec_proto3_bool
+ p.size = size_proto3_bool
+ case reflect.Int32:
+ p.enc = (*Buffer).enc_proto3_int32
+ p.dec = (*Buffer).dec_proto3_int32
+ p.size = size_proto3_int32
+ case reflect.Uint32:
+ p.enc = (*Buffer).enc_proto3_uint32
+ p.dec = (*Buffer).dec_proto3_int32 // can reuse
+ p.size = size_proto3_uint32
+ case reflect.Int64, reflect.Uint64:
+ p.enc = (*Buffer).enc_proto3_int64
+ p.dec = (*Buffer).dec_proto3_int64
+ p.size = size_proto3_int64
+ case reflect.Float32:
+ p.enc = (*Buffer).enc_proto3_uint32 // can just treat them as bits
+ p.dec = (*Buffer).dec_proto3_int32
+ p.size = size_proto3_uint32
+ case reflect.Float64:
+ p.enc = (*Buffer).enc_proto3_int64 // can just treat them as bits
+ p.dec = (*Buffer).dec_proto3_int64
+ p.size = size_proto3_int64
+ case reflect.String:
+ p.enc = (*Buffer).enc_proto3_string
+ p.dec = (*Buffer).dec_proto3_string
+ p.size = size_proto3_string
+
+ case reflect.Ptr:
+ switch t2 := t1.Elem(); t2.Kind() {
+ default:
+ fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2)
+ break
+ case reflect.Bool:
+ p.enc = (*Buffer).enc_bool
+ p.dec = (*Buffer).dec_bool
+ p.size = size_bool
+ case reflect.Int32:
+ p.enc = (*Buffer).enc_int32
+ p.dec = (*Buffer).dec_int32
+ p.size = size_int32
+ case reflect.Uint32:
+ p.enc = (*Buffer).enc_uint32
+ p.dec = (*Buffer).dec_int32 // can reuse
+ p.size = size_uint32
+ case reflect.Int64, reflect.Uint64:
+ p.enc = (*Buffer).enc_int64
+ p.dec = (*Buffer).dec_int64
+ p.size = size_int64
+ case reflect.Float32:
+ p.enc = (*Buffer).enc_uint32 // can just treat them as bits
+ p.dec = (*Buffer).dec_int32
+ p.size = size_uint32
+ case reflect.Float64:
+ p.enc = (*Buffer).enc_int64 // can just treat them as bits
+ p.dec = (*Buffer).dec_int64
+ p.size = size_int64
+ case reflect.String:
+ p.enc = (*Buffer).enc_string
+ p.dec = (*Buffer).dec_string
+ p.size = size_string
+ case reflect.Struct:
+ p.stype = t1.Elem()
+ p.isMarshaler = isMarshaler(t1)
+ p.isUnmarshaler = isUnmarshaler(t1)
+ if p.Wire == "bytes" {
+ p.enc = (*Buffer).enc_struct_message
+ p.dec = (*Buffer).dec_struct_message
+ p.size = size_struct_message
+ } else {
+ p.enc = (*Buffer).enc_struct_group
+ p.dec = (*Buffer).dec_struct_group
+ p.size = size_struct_group
+ }
+ }
+
+ case reflect.Slice:
+ switch t2 := t1.Elem(); t2.Kind() {
+ default:
+ logNoSliceEnc(t1, t2)
+ break
+ case reflect.Bool:
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_bool
+ p.size = size_slice_packed_bool
+ } else {
+ p.enc = (*Buffer).enc_slice_bool
+ p.size = size_slice_bool
+ }
+ p.dec = (*Buffer).dec_slice_bool
+ p.packedDec = (*Buffer).dec_slice_packed_bool
+ case reflect.Int32:
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_int32
+ p.size = size_slice_packed_int32
+ } else {
+ p.enc = (*Buffer).enc_slice_int32
+ p.size = size_slice_int32
+ }
+ p.dec = (*Buffer).dec_slice_int32
+ p.packedDec = (*Buffer).dec_slice_packed_int32
+ case reflect.Uint32:
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_uint32
+ p.size = size_slice_packed_uint32
+ } else {
+ p.enc = (*Buffer).enc_slice_uint32
+ p.size = size_slice_uint32
+ }
+ p.dec = (*Buffer).dec_slice_int32
+ p.packedDec = (*Buffer).dec_slice_packed_int32
+ case reflect.Int64, reflect.Uint64:
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_int64
+ p.size = size_slice_packed_int64
+ } else {
+ p.enc = (*Buffer).enc_slice_int64
+ p.size = size_slice_int64
+ }
+ p.dec = (*Buffer).dec_slice_int64
+ p.packedDec = (*Buffer).dec_slice_packed_int64
+ case reflect.Uint8:
+ p.dec = (*Buffer).dec_slice_byte
+ if p.proto3 {
+ p.enc = (*Buffer).enc_proto3_slice_byte
+ p.size = size_proto3_slice_byte
+ } else {
+ p.enc = (*Buffer).enc_slice_byte
+ p.size = size_slice_byte
+ }
+ case reflect.Float32, reflect.Float64:
+ switch t2.Bits() {
+ case 32:
+ // can just treat them as bits
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_uint32
+ p.size = size_slice_packed_uint32
+ } else {
+ p.enc = (*Buffer).enc_slice_uint32
+ p.size = size_slice_uint32
+ }
+ p.dec = (*Buffer).dec_slice_int32
+ p.packedDec = (*Buffer).dec_slice_packed_int32
+ case 64:
+ // can just treat them as bits
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_int64
+ p.size = size_slice_packed_int64
+ } else {
+ p.enc = (*Buffer).enc_slice_int64
+ p.size = size_slice_int64
+ }
+ p.dec = (*Buffer).dec_slice_int64
+ p.packedDec = (*Buffer).dec_slice_packed_int64
+ default:
+ logNoSliceEnc(t1, t2)
+ break
+ }
+ case reflect.String:
+ p.enc = (*Buffer).enc_slice_string
+ p.dec = (*Buffer).dec_slice_string
+ p.size = size_slice_string
+ case reflect.Ptr:
+ switch t3 := t2.Elem(); t3.Kind() {
+ default:
+ fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3)
+ break
+ case reflect.Struct:
+ p.stype = t2.Elem()
+ p.isMarshaler = isMarshaler(t2)
+ p.isUnmarshaler = isUnmarshaler(t2)
+ if p.Wire == "bytes" {
+ p.enc = (*Buffer).enc_slice_struct_message
+ p.dec = (*Buffer).dec_slice_struct_message
+ p.size = size_slice_struct_message
+ } else {
+ p.enc = (*Buffer).enc_slice_struct_group
+ p.dec = (*Buffer).dec_slice_struct_group
+ p.size = size_slice_struct_group
+ }
+ }
+ case reflect.Slice:
+ switch t2.Elem().Kind() {
+ default:
+ fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem())
+ break
+ case reflect.Uint8:
+ p.enc = (*Buffer).enc_slice_slice_byte
+ p.dec = (*Buffer).dec_slice_slice_byte
+ p.size = size_slice_slice_byte
+ }
+ }
+
+ case reflect.Map:
+ p.enc = (*Buffer).enc_new_map
+ p.dec = (*Buffer).dec_new_map
+ p.size = size_new_map
+
+ p.mtype = t1
+ p.mkeyprop = &Properties{}
+ p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
+ p.mvalprop = &Properties{}
+ vtype := p.mtype.Elem()
+ if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice {
+ // The value type is not a message (*T) or bytes ([]byte),
+ // so we need encoders for the pointer to this type.
+ vtype = reflect.PtrTo(vtype)
+ }
+ p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
+ }
+
+ // precalculate tag code
+ wire := p.WireType
+ if p.Packed {
+ wire = WireBytes
+ }
+ x := uint32(p.Tag)<<3 | uint32(wire)
+ i := 0
+ for i = 0; x > 127; i++ {
+ p.tagbuf[i] = 0x80 | uint8(x&0x7F)
+ x >>= 7
+ }
+ p.tagbuf[i] = uint8(x)
+ p.tagcode = p.tagbuf[0 : i+1]
+
+ if p.stype != nil {
+ if lockGetProp {
+ p.sprop = GetProperties(p.stype)
+ } else {
+ p.sprop = getPropertiesLocked(p.stype)
+ }
+ }
+}
+
+var (
+ marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
+ unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
+)
+
+// isMarshaler reports whether type t implements Marshaler.
+func isMarshaler(t reflect.Type) bool {
+ // We're checking for (likely) pointer-receiver methods
+ // so if t is not a pointer, something is very wrong.
+ // The calls above only invoke isMarshaler on pointer types.
+ if t.Kind() != reflect.Ptr {
+ panic("proto: misuse of isMarshaler")
+ }
+ return t.Implements(marshalerType)
+}
+
+// isUnmarshaler reports whether type t implements Unmarshaler.
+func isUnmarshaler(t reflect.Type) bool {
+ // We're checking for (likely) pointer-receiver methods
+ // so if t is not a pointer, something is very wrong.
+ // The calls above only invoke isUnmarshaler on pointer types.
+ if t.Kind() != reflect.Ptr {
+ panic("proto: misuse of isUnmarshaler")
+ }
+ return t.Implements(unmarshalerType)
+}
+
+// Init populates the properties from a protocol buffer struct tag.
+func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
+ p.init(typ, name, tag, f, true)
+}
+
+func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) {
+ // "bytes,49,opt,def=hello!"
+ p.Name = name
+ p.OrigName = name
+ if f != nil {
+ p.field = toField(f)
+ }
+ if tag == "" {
+ return
+ }
+ p.Parse(tag)
+ p.setEncAndDec(typ, f, lockGetProp)
+}
+
+var (
+ propertiesMu sync.RWMutex
+ propertiesMap = make(map[reflect.Type]*StructProperties)
+)
+
+// GetProperties returns the list of properties for the type represented by t.
+// t must represent a generated struct type of a protocol message.
+func GetProperties(t reflect.Type) *StructProperties {
+ if t.Kind() != reflect.Struct {
+ panic("proto: type must have kind struct")
+ }
+
+ // Most calls to GetProperties in a long-running program will be
+ // retrieving details for types we have seen before.
+ propertiesMu.RLock()
+ sprop, ok := propertiesMap[t]
+ propertiesMu.RUnlock()
+ if ok {
+ if collectStats {
+ stats.Chit++
+ }
+ return sprop
+ }
+
+ propertiesMu.Lock()
+ sprop = getPropertiesLocked(t)
+ propertiesMu.Unlock()
+ return sprop
+}
+
+// getPropertiesLocked requires that propertiesMu is held.
+func getPropertiesLocked(t reflect.Type) *StructProperties {
+ if prop, ok := propertiesMap[t]; ok {
+ if collectStats {
+ stats.Chit++
+ }
+ return prop
+ }
+ if collectStats {
+ stats.Cmiss++
+ }
+
+ prop := new(StructProperties)
+ // in case of recursive protos, fill this in now.
+ propertiesMap[t] = prop
+
+ // build properties
+ prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) ||
+ reflect.PtrTo(t).Implements(extendableProtoV1Type)
+ prop.unrecField = invalidField
+ prop.Prop = make([]*Properties, t.NumField())
+ prop.order = make([]int, t.NumField())
+
+ for i := 0; i < t.NumField(); i++ {
+ f := t.Field(i)
+ p := new(Properties)
+ name := f.Name
+ p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
+
+ if f.Name == "XXX_InternalExtensions" { // special case
+ p.enc = (*Buffer).enc_exts
+ p.dec = nil // not needed
+ p.size = size_exts
+ } else if f.Name == "XXX_extensions" { // special case
+ p.enc = (*Buffer).enc_map
+ p.dec = nil // not needed
+ p.size = size_map
+ } else if f.Name == "XXX_unrecognized" { // special case
+ prop.unrecField = toField(&f)
+ }
+ oneof := f.Tag.Get("protobuf_oneof") // special case
+ if oneof != "" {
+ // Oneof fields don't use the traditional protobuf tag.
+ p.OrigName = oneof
+ }
+ prop.Prop[i] = p
+ prop.order[i] = i
+ if debug {
+ print(i, " ", f.Name, " ", t.String(), " ")
+ if p.Tag > 0 {
+ print(p.String())
+ }
+ print("\n")
+ }
+ if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && oneof == "" {
+ fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]")
+ }
+ }
+
+ // Re-order prop.order.
+ sort.Sort(prop)
+
+ type oneofMessage interface {
+ XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
+ }
+ if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
+ var oots []interface{}
+ prop.oneofMarshaler, prop.oneofUnmarshaler, prop.oneofSizer, oots = om.XXX_OneofFuncs()
+ prop.stype = t
+
+ // Interpret oneof metadata.
+ prop.OneofTypes = make(map[string]*OneofProperties)
+ for _, oot := range oots {
+ oop := &OneofProperties{
+ Type: reflect.ValueOf(oot).Type(), // *T
+ Prop: new(Properties),
+ }
+ sft := oop.Type.Elem().Field(0)
+ oop.Prop.Name = sft.Name
+ oop.Prop.Parse(sft.Tag.Get("protobuf"))
+ // There will be exactly one interface field that
+ // this new value is assignable to.
+ for i := 0; i < t.NumField(); i++ {
+ f := t.Field(i)
+ if f.Type.Kind() != reflect.Interface {
+ continue
+ }
+ if !oop.Type.AssignableTo(f.Type) {
+ continue
+ }
+ oop.Field = i
+ break
+ }
+ prop.OneofTypes[oop.Prop.OrigName] = oop
+ }
+ }
+
+ // build required counts
+ // build tags
+ reqCount := 0
+ prop.decoderOrigNames = make(map[string]int)
+ for i, p := range prop.Prop {
+ if strings.HasPrefix(p.Name, "XXX_") {
+ // Internal fields should not appear in tags/origNames maps.
+ // They are handled specially when encoding and decoding.
+ continue
+ }
+ if p.Required {
+ reqCount++
+ }
+ prop.decoderTags.put(p.Tag, i)
+ prop.decoderOrigNames[p.OrigName] = i
+ }
+ prop.reqCount = reqCount
+
+ return prop
+}
+
+// Return the Properties object for the x[0]'th field of the structure.
+func propByIndex(t reflect.Type, x []int) *Properties {
+ if len(x) != 1 {
+ fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t)
+ return nil
+ }
+ prop := GetProperties(t)
+ return prop.Prop[x[0]]
+}
+
+// Get the address and type of a pointer to a struct from an interface.
+func getbase(pb Message) (t reflect.Type, b structPointer, err error) {
+ if pb == nil {
+ err = ErrNil
+ return
+ }
+ // get the reflect type of the pointer to the struct.
+ t = reflect.TypeOf(pb)
+ // get the address of the struct.
+ value := reflect.ValueOf(pb)
+ b = toStructPointer(value)
+ return
+}
+
+// A global registry of enum types.
+// The generated code will register the generated maps by calling RegisterEnum.
+
+var enumValueMaps = make(map[string]map[string]int32)
+
+// RegisterEnum is called from the generated code to install the enum descriptor
+// maps into the global table to aid parsing text format protocol buffers.
+func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) {
+ if _, ok := enumValueMaps[typeName]; ok {
+ panic("proto: duplicate enum registered: " + typeName)
+ }
+ enumValueMaps[typeName] = valueMap
+}
+
+// EnumValueMap returns the mapping from names to integers of the
+// enum type enumType, or a nil if not found.
+func EnumValueMap(enumType string) map[string]int32 {
+ return enumValueMaps[enumType]
+}
+
+// A registry of all linked message types.
+// The string is a fully-qualified proto name ("pkg.Message").
+var (
+ protoTypes = make(map[string]reflect.Type)
+ revProtoTypes = make(map[reflect.Type]string)
+)
+
+// RegisterType is called from generated code and maps from the fully qualified
+// proto name to the type (pointer to struct) of the protocol buffer.
+func RegisterType(x Message, name string) {
+ if _, ok := protoTypes[name]; ok {
+ // TODO: Some day, make this a panic.
+ log.Printf("proto: duplicate proto type registered: %s", name)
+ return
+ }
+ t := reflect.TypeOf(x)
+ protoTypes[name] = t
+ revProtoTypes[t] = name
+}
+
+// MessageName returns the fully-qualified proto name for the given message type.
+func MessageName(x Message) string { return revProtoTypes[reflect.TypeOf(x)] }
+
+// MessageType returns the message type (pointer to struct) for a named message.
+func MessageType(name string) reflect.Type { return protoTypes[name] }
+
+// A registry of all linked proto files.
+var (
+ protoFiles = make(map[string][]byte) // file name => fileDescriptor
+)
+
+// RegisterFile is called from generated code and maps from the
+// full file name of a .proto file to its compressed FileDescriptorProto.
+func RegisterFile(filename string, fileDescriptor []byte) {
+ protoFiles[filename] = fileDescriptor
+}
+
+// FileDescriptor returns the compressed FileDescriptorProto for a .proto file.
+func FileDescriptor(filename string) []byte { return protoFiles[filename] }
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+// Functions for writing the text protocol buffer format.
+
+import (
+ "bufio"
+ "bytes"
+ "encoding"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "math"
+ "reflect"
+ "sort"
+ "strings"
+)
+
+var (
+ newline = []byte("\n")
+ spaces = []byte(" ")
+ gtNewline = []byte(">\n")
+ endBraceNewline = []byte("}\n")
+ backslashN = []byte{'\\', 'n'}
+ backslashR = []byte{'\\', 'r'}
+ backslashT = []byte{'\\', 't'}
+ backslashDQ = []byte{'\\', '"'}
+ backslashBS = []byte{'\\', '\\'}
+ posInf = []byte("inf")
+ negInf = []byte("-inf")
+ nan = []byte("nan")
+)
+
+type writer interface {
+ io.Writer
+ WriteByte(byte) error
+}
+
+// textWriter is an io.Writer that tracks its indentation level.
+type textWriter struct {
+ ind int
+ complete bool // if the current position is a complete line
+ compact bool // whether to write out as a one-liner
+ w writer
+}
+
+func (w *textWriter) WriteString(s string) (n int, err error) {
+ if !strings.Contains(s, "\n") {
+ if !w.compact && w.complete {
+ w.writeIndent()
+ }
+ w.complete = false
+ return io.WriteString(w.w, s)
+ }
+ // WriteString is typically called without newlines, so this
+ // codepath and its copy are rare. We copy to avoid
+ // duplicating all of Write's logic here.
+ return w.Write([]byte(s))
+}
+
+func (w *textWriter) Write(p []byte) (n int, err error) {
+ newlines := bytes.Count(p, newline)
+ if newlines == 0 {
+ if !w.compact && w.complete {
+ w.writeIndent()
+ }
+ n, err = w.w.Write(p)
+ w.complete = false
+ return n, err
+ }
+
+ frags := bytes.SplitN(p, newline, newlines+1)
+ if w.compact {
+ for i, frag := range frags {
+ if i > 0 {
+ if err := w.w.WriteByte(' '); err != nil {
+ return n, err
+ }
+ n++
+ }
+ nn, err := w.w.Write(frag)
+ n += nn
+ if err != nil {
+ return n, err
+ }
+ }
+ return n, nil
+ }
+
+ for i, frag := range frags {
+ if w.complete {
+ w.writeIndent()
+ }
+ nn, err := w.w.Write(frag)
+ n += nn
+ if err != nil {
+ return n, err
+ }
+ if i+1 < len(frags) {
+ if err := w.w.WriteByte('\n'); err != nil {
+ return n, err
+ }
+ n++
+ }
+ }
+ w.complete = len(frags[len(frags)-1]) == 0
+ return n, nil
+}
+
+func (w *textWriter) WriteByte(c byte) error {
+ if w.compact && c == '\n' {
+ c = ' '
+ }
+ if !w.compact && w.complete {
+ w.writeIndent()
+ }
+ err := w.w.WriteByte(c)
+ w.complete = c == '\n'
+ return err
+}
+
+func (w *textWriter) indent() { w.ind++ }
+
+func (w *textWriter) unindent() {
+ if w.ind == 0 {
+ log.Print("proto: textWriter unindented too far")
+ return
+ }
+ w.ind--
+}
+
+func writeName(w *textWriter, props *Properties) error {
+ if _, err := w.WriteString(props.OrigName); err != nil {
+ return err
+ }
+ if props.Wire != "group" {
+ return w.WriteByte(':')
+ }
+ return nil
+}
+
+// raw is the interface satisfied by RawMessage.
+type raw interface {
+ Bytes() []byte
+}
+
+func requiresQuotes(u string) bool {
+ // When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
+ for _, ch := range u {
+ switch {
+ case ch == '.' || ch == '/' || ch == '_':
+ continue
+ case '0' <= ch && ch <= '9':
+ continue
+ case 'A' <= ch && ch <= 'Z':
+ continue
+ case 'a' <= ch && ch <= 'z':
+ continue
+ default:
+ return true
+ }
+ }
+ return false
+}
+
+// isAny reports whether sv is a google.protobuf.Any message
+func isAny(sv reflect.Value) bool {
+ type wkt interface {
+ XXX_WellKnownType() string
+ }
+ t, ok := sv.Addr().Interface().(wkt)
+ return ok && t.XXX_WellKnownType() == "Any"
+}
+
+// writeProto3Any writes an expanded google.protobuf.Any message.
+//
+// It returns (false, nil) if sv value can't be unmarshaled (e.g. because
+// required messages are not linked in).
+//
+// It returns (true, error) when sv was written in expanded format or an error
+// was encountered.
+func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) {
+ turl := sv.FieldByName("TypeUrl")
+ val := sv.FieldByName("Value")
+ if !turl.IsValid() || !val.IsValid() {
+ return true, errors.New("proto: invalid google.protobuf.Any message")
+ }
+
+ b, ok := val.Interface().([]byte)
+ if !ok {
+ return true, errors.New("proto: invalid google.protobuf.Any message")
+ }
+
+ parts := strings.Split(turl.String(), "/")
+ mt := MessageType(parts[len(parts)-1])
+ if mt == nil {
+ return false, nil
+ }
+ m := reflect.New(mt.Elem())
+ if err := Unmarshal(b, m.Interface().(Message)); err != nil {
+ return false, nil
+ }
+ w.Write([]byte("["))
+ u := turl.String()
+ if requiresQuotes(u) {
+ writeString(w, u)
+ } else {
+ w.Write([]byte(u))
+ }
+ if w.compact {
+ w.Write([]byte("]:<"))
+ } else {
+ w.Write([]byte("]: <\n"))
+ w.ind++
+ }
+ if err := tm.writeStruct(w, m.Elem()); err != nil {
+ return true, err
+ }
+ if w.compact {
+ w.Write([]byte("> "))
+ } else {
+ w.ind--
+ w.Write([]byte(">\n"))
+ }
+ return true, nil
+}
+
+func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
+ if tm.ExpandAny && isAny(sv) {
+ if canExpand, err := tm.writeProto3Any(w, sv); canExpand {
+ return err
+ }
+ }
+ st := sv.Type()
+ sprops := GetProperties(st)
+ for i := 0; i < sv.NumField(); i++ {
+ fv := sv.Field(i)
+ props := sprops.Prop[i]
+ name := st.Field(i).Name
+
+ if strings.HasPrefix(name, "XXX_") {
+ // There are two XXX_ fields:
+ // XXX_unrecognized []byte
+ // XXX_extensions map[int32]proto.Extension
+ // The first is handled here;
+ // the second is handled at the bottom of this function.
+ if name == "XXX_unrecognized" && !fv.IsNil() {
+ if err := writeUnknownStruct(w, fv.Interface().([]byte)); err != nil {
+ return err
+ }
+ }
+ continue
+ }
+ if fv.Kind() == reflect.Ptr && fv.IsNil() {
+ // Field not filled in. This could be an optional field or
+ // a required field that wasn't filled in. Either way, there
+ // isn't anything we can show for it.
+ continue
+ }
+ if fv.Kind() == reflect.Slice && fv.IsNil() {
+ // Repeated field that is empty, or a bytes field that is unused.
+ continue
+ }
+
+ if props.Repeated && fv.Kind() == reflect.Slice {
+ // Repeated field.
+ for j := 0; j < fv.Len(); j++ {
+ if err := writeName(w, props); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ v := fv.Index(j)
+ if v.Kind() == reflect.Ptr && v.IsNil() {
+ // A nil message in a repeated field is not valid,
+ // but we can handle that more gracefully than panicking.
+ if _, err := w.Write([]byte("<nil>\n")); err != nil {
+ return err
+ }
+ continue
+ }
+ if err := tm.writeAny(w, v, props); err != nil {
+ return err
+ }
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ continue
+ }
+ if fv.Kind() == reflect.Map {
+ // Map fields are rendered as a repeated struct with key/value fields.
+ keys := fv.MapKeys()
+ sort.Sort(mapKeys(keys))
+ for _, key := range keys {
+ val := fv.MapIndex(key)
+ if err := writeName(w, props); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ // open struct
+ if err := w.WriteByte('<'); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ w.indent()
+ // key
+ if _, err := w.WriteString("key:"); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ if err := tm.writeAny(w, key, props.mkeyprop); err != nil {
+ return err
+ }
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ // nil values aren't legal, but we can avoid panicking because of them.
+ if val.Kind() != reflect.Ptr || !val.IsNil() {
+ // value
+ if _, err := w.WriteString("value:"); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ if err := tm.writeAny(w, val, props.mvalprop); err != nil {
+ return err
+ }
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ // close struct
+ w.unindent()
+ if err := w.WriteByte('>'); err != nil {
+ return err
+ }
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ continue
+ }
+ if props.proto3 && fv.Kind() == reflect.Slice && fv.Len() == 0 {
+ // empty bytes field
+ continue
+ }
+ if fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice {
+ // proto3 non-repeated scalar field; skip if zero value
+ if isProto3Zero(fv) {
+ continue
+ }
+ }
+
+ if fv.Kind() == reflect.Interface {
+ // Check if it is a oneof.
+ if st.Field(i).Tag.Get("protobuf_oneof") != "" {
+ // fv is nil, or holds a pointer to generated struct.
+ // That generated struct has exactly one field,
+ // which has a protobuf struct tag.
+ if fv.IsNil() {
+ continue
+ }
+ inner := fv.Elem().Elem() // interface -> *T -> T
+ tag := inner.Type().Field(0).Tag.Get("protobuf")
+ props = new(Properties) // Overwrite the outer props var, but not its pointee.
+ props.Parse(tag)
+ // Write the value in the oneof, not the oneof itself.
+ fv = inner.Field(0)
+
+ // Special case to cope with malformed messages gracefully:
+ // If the value in the oneof is a nil pointer, don't panic
+ // in writeAny.
+ if fv.Kind() == reflect.Ptr && fv.IsNil() {
+ // Use errors.New so writeAny won't render quotes.
+ msg := errors.New("/* nil */")
+ fv = reflect.ValueOf(&msg).Elem()
+ }
+ }
+ }
+
+ if err := writeName(w, props); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ if b, ok := fv.Interface().(raw); ok {
+ if err := writeRaw(w, b.Bytes()); err != nil {
+ return err
+ }
+ continue
+ }
+
+ // Enums have a String method, so writeAny will work fine.
+ if err := tm.writeAny(w, fv, props); err != nil {
+ return err
+ }
+
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+
+ // Extensions (the XXX_extensions field).
+ pv := sv.Addr()
+ if _, ok := extendable(pv.Interface()); ok {
+ if err := tm.writeExtensions(w, pv); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// writeRaw writes an uninterpreted raw message.
+func writeRaw(w *textWriter, b []byte) error {
+ if err := w.WriteByte('<'); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ w.indent()
+ if err := writeUnknownStruct(w, b); err != nil {
+ return err
+ }
+ w.unindent()
+ if err := w.WriteByte('>'); err != nil {
+ return err
+ }
+ return nil
+}
+
+// writeAny writes an arbitrary field.
+func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
+ v = reflect.Indirect(v)
+
+ // Floats have special cases.
+ if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 {
+ x := v.Float()
+ var b []byte
+ switch {
+ case math.IsInf(x, 1):
+ b = posInf
+ case math.IsInf(x, -1):
+ b = negInf
+ case math.IsNaN(x):
+ b = nan
+ }
+ if b != nil {
+ _, err := w.Write(b)
+ return err
+ }
+ // Other values are handled below.
+ }
+
+ // We don't attempt to serialise every possible value type; only those
+ // that can occur in protocol buffers.
+ switch v.Kind() {
+ case reflect.Slice:
+ // Should only be a []byte; repeated fields are handled in writeStruct.
+ if err := writeString(w, string(v.Bytes())); err != nil {
+ return err
+ }
+ case reflect.String:
+ if err := writeString(w, v.String()); err != nil {
+ return err
+ }
+ case reflect.Struct:
+ // Required/optional group/message.
+ var bra, ket byte = '<', '>'
+ if props != nil && props.Wire == "group" {
+ bra, ket = '{', '}'
+ }
+ if err := w.WriteByte(bra); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ w.indent()
+ if etm, ok := v.Interface().(encoding.TextMarshaler); ok {
+ text, err := etm.MarshalText()
+ if err != nil {
+ return err
+ }
+ if _, err = w.Write(text); err != nil {
+ return err
+ }
+ } else if err := tm.writeStruct(w, v); err != nil {
+ return err
+ }
+ w.unindent()
+ if err := w.WriteByte(ket); err != nil {
+ return err
+ }
+ default:
+ _, err := fmt.Fprint(w, v.Interface())
+ return err
+ }
+ return nil
+}
+
+// equivalent to C's isprint.
+func isprint(c byte) bool {
+ return c >= 0x20 && c < 0x7f
+}
+
+// writeString writes a string in the protocol buffer text format.
+// It is similar to strconv.Quote except we don't use Go escape sequences,
+// we treat the string as a byte sequence, and we use octal escapes.
+// These differences are to maintain interoperability with the other
+// languages' implementations of the text format.
+func writeString(w *textWriter, s string) error {
+ // use WriteByte here to get any needed indent
+ if err := w.WriteByte('"'); err != nil {
+ return err
+ }
+ // Loop over the bytes, not the runes.
+ for i := 0; i < len(s); i++ {
+ var err error
+ // Divergence from C++: we don't escape apostrophes.
+ // There's no need to escape them, and the C++ parser
+ // copes with a naked apostrophe.
+ switch c := s[i]; c {
+ case '\n':
+ _, err = w.w.Write(backslashN)
+ case '\r':
+ _, err = w.w.Write(backslashR)
+ case '\t':
+ _, err = w.w.Write(backslashT)
+ case '"':
+ _, err = w.w.Write(backslashDQ)
+ case '\\':
+ _, err = w.w.Write(backslashBS)
+ default:
+ if isprint(c) {
+ err = w.w.WriteByte(c)
+ } else {
+ _, err = fmt.Fprintf(w.w, "\\%03o", c)
+ }
+ }
+ if err != nil {
+ return err
+ }
+ }
+ return w.WriteByte('"')
+}
+
+func writeUnknownStruct(w *textWriter, data []byte) (err error) {
+ if !w.compact {
+ if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil {
+ return err
+ }
+ }
+ b := NewBuffer(data)
+ for b.index < len(b.buf) {
+ x, err := b.DecodeVarint()
+ if err != nil {
+ _, err := fmt.Fprintf(w, "/* %v */\n", err)
+ return err
+ }
+ wire, tag := x&7, x>>3
+ if wire == WireEndGroup {
+ w.unindent()
+ if _, err := w.Write(endBraceNewline); err != nil {
+ return err
+ }
+ continue
+ }
+ if _, err := fmt.Fprint(w, tag); err != nil {
+ return err
+ }
+ if wire != WireStartGroup {
+ if err := w.WriteByte(':'); err != nil {
+ return err
+ }
+ }
+ if !w.compact || wire == WireStartGroup {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ switch wire {
+ case WireBytes:
+ buf, e := b.DecodeRawBytes(false)
+ if e == nil {
+ _, err = fmt.Fprintf(w, "%q", buf)
+ } else {
+ _, err = fmt.Fprintf(w, "/* %v */", e)
+ }
+ case WireFixed32:
+ x, err = b.DecodeFixed32()
+ err = writeUnknownInt(w, x, err)
+ case WireFixed64:
+ x, err = b.DecodeFixed64()
+ err = writeUnknownInt(w, x, err)
+ case WireStartGroup:
+ err = w.WriteByte('{')
+ w.indent()
+ case WireVarint:
+ x, err = b.DecodeVarint()
+ err = writeUnknownInt(w, x, err)
+ default:
+ _, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire)
+ }
+ if err != nil {
+ return err
+ }
+ if err = w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func writeUnknownInt(w *textWriter, x uint64, err error) error {
+ if err == nil {
+ _, err = fmt.Fprint(w, x)
+ } else {
+ _, err = fmt.Fprintf(w, "/* %v */", err)
+ }
+ return err
+}
+
+type int32Slice []int32
+
+func (s int32Slice) Len() int { return len(s) }
+func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
+func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// writeExtensions writes all the extensions in pv.
+// pv is assumed to be a pointer to a protocol message struct that is extendable.
+func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error {
+ emap := extensionMaps[pv.Type().Elem()]
+ ep, _ := extendable(pv.Interface())
+
+ // Order the extensions by ID.
+ // This isn't strictly necessary, but it will give us
+ // canonical output, which will also make testing easier.
+ m, mu := ep.extensionsRead()
+ if m == nil {
+ return nil
+ }
+ mu.Lock()
+ ids := make([]int32, 0, len(m))
+ for id := range m {
+ ids = append(ids, id)
+ }
+ sort.Sort(int32Slice(ids))
+ mu.Unlock()
+
+ for _, extNum := range ids {
+ ext := m[extNum]
+ var desc *ExtensionDesc
+ if emap != nil {
+ desc = emap[extNum]
+ }
+ if desc == nil {
+ // Unknown extension.
+ if err := writeUnknownStruct(w, ext.enc); err != nil {
+ return err
+ }
+ continue
+ }
+
+ pb, err := GetExtension(ep, desc)
+ if err != nil {
+ return fmt.Errorf("failed getting extension: %v", err)
+ }
+
+ // Repeated extensions will appear as a slice.
+ if !desc.repeated() {
+ if err := tm.writeExtension(w, desc.Name, pb); err != nil {
+ return err
+ }
+ } else {
+ v := reflect.ValueOf(pb)
+ for i := 0; i < v.Len(); i++ {
+ if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil {
+ return err
+ }
+ }
+ }
+ }
+ return nil
+}
+
+func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error {
+ if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil {
+ return err
+ }
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (w *textWriter) writeIndent() {
+ if !w.complete {
+ return
+ }
+ remain := w.ind * 2
+ for remain > 0 {
+ n := remain
+ if n > len(spaces) {
+ n = len(spaces)
+ }
+ w.w.Write(spaces[:n])
+ remain -= n
+ }
+ w.complete = false
+}
+
+// TextMarshaler is a configurable text format marshaler.
+type TextMarshaler struct {
+ Compact bool // use compact text format (one line).
+ ExpandAny bool // expand google.protobuf.Any messages of known types
+}
+
+// Marshal writes a given protocol buffer in text format.
+// The only errors returned are from w.
+func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error {
+ val := reflect.ValueOf(pb)
+ if pb == nil || val.IsNil() {
+ w.Write([]byte("<nil>"))
+ return nil
+ }
+ var bw *bufio.Writer
+ ww, ok := w.(writer)
+ if !ok {
+ bw = bufio.NewWriter(w)
+ ww = bw
+ }
+ aw := &textWriter{
+ w: ww,
+ complete: true,
+ compact: tm.Compact,
+ }
+
+ if etm, ok := pb.(encoding.TextMarshaler); ok {
+ text, err := etm.MarshalText()
+ if err != nil {
+ return err
+ }
+ if _, err = aw.Write(text); err != nil {
+ return err
+ }
+ if bw != nil {
+ return bw.Flush()
+ }
+ return nil
+ }
+ // Dereference the received pointer so we don't have outer < and >.
+ v := reflect.Indirect(val)
+ if err := tm.writeStruct(aw, v); err != nil {
+ return err
+ }
+ if bw != nil {
+ return bw.Flush()
+ }
+ return nil
+}
+
+// Text is the same as Marshal, but returns the string directly.
+func (tm *TextMarshaler) Text(pb Message) string {
+ var buf bytes.Buffer
+ tm.Marshal(&buf, pb)
+ return buf.String()
+}
+
+var (
+ defaultTextMarshaler = TextMarshaler{}
+ compactTextMarshaler = TextMarshaler{Compact: true}
+)
+
+// TODO: consider removing some of the Marshal functions below.
+
+// MarshalText writes a given protocol buffer in text format.
+// The only errors returned are from w.
+func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) }
+
+// MarshalTextString is the same as MarshalText, but returns the string directly.
+func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) }
+
+// CompactText writes a given protocol buffer in compact text format (one line).
+func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) }
+
+// CompactTextString is the same as CompactText, but returns the string directly.
+func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) }
--- /dev/null
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+// Functions for parsing the Text protocol buffer format.
+// TODO: message sets.
+
+import (
+ "encoding"
+ "errors"
+ "fmt"
+ "reflect"
+ "strconv"
+ "strings"
+ "unicode/utf8"
+)
+
+type ParseError struct {
+ Message string
+ Line int // 1-based line number
+ Offset int // 0-based byte offset from start of input
+}
+
+func (p *ParseError) Error() string {
+ if p.Line == 1 {
+ // show offset only for first line
+ return fmt.Sprintf("line 1.%d: %v", p.Offset, p.Message)
+ }
+ return fmt.Sprintf("line %d: %v", p.Line, p.Message)
+}
+
+type token struct {
+ value string
+ err *ParseError
+ line int // line number
+ offset int // byte number from start of input, not start of line
+ unquoted string // the unquoted version of value, if it was a quoted string
+}
+
+func (t *token) String() string {
+ if t.err == nil {
+ return fmt.Sprintf("%q (line=%d, offset=%d)", t.value, t.line, t.offset)
+ }
+ return fmt.Sprintf("parse error: %v", t.err)
+}
+
+type textParser struct {
+ s string // remaining input
+ done bool // whether the parsing is finished (success or error)
+ backed bool // whether back() was called
+ offset, line int
+ cur token
+}
+
+func newTextParser(s string) *textParser {
+ p := new(textParser)
+ p.s = s
+ p.line = 1
+ p.cur.line = 1
+ return p
+}
+
+func (p *textParser) errorf(format string, a ...interface{}) *ParseError {
+ pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset}
+ p.cur.err = pe
+ p.done = true
+ return pe
+}
+
+// Numbers and identifiers are matched by [-+._A-Za-z0-9]
+func isIdentOrNumberChar(c byte) bool {
+ switch {
+ case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z':
+ return true
+ case '0' <= c && c <= '9':
+ return true
+ }
+ switch c {
+ case '-', '+', '.', '_':
+ return true
+ }
+ return false
+}
+
+func isWhitespace(c byte) bool {
+ switch c {
+ case ' ', '\t', '\n', '\r':
+ return true
+ }
+ return false
+}
+
+func isQuote(c byte) bool {
+ switch c {
+ case '"', '\'':
+ return true
+ }
+ return false
+}
+
+func (p *textParser) skipWhitespace() {
+ i := 0
+ for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') {
+ if p.s[i] == '#' {
+ // comment; skip to end of line or input
+ for i < len(p.s) && p.s[i] != '\n' {
+ i++
+ }
+ if i == len(p.s) {
+ break
+ }
+ }
+ if p.s[i] == '\n' {
+ p.line++
+ }
+ i++
+ }
+ p.offset += i
+ p.s = p.s[i:len(p.s)]
+ if len(p.s) == 0 {
+ p.done = true
+ }
+}
+
+func (p *textParser) advance() {
+ // Skip whitespace
+ p.skipWhitespace()
+ if p.done {
+ return
+ }
+
+ // Start of non-whitespace
+ p.cur.err = nil
+ p.cur.offset, p.cur.line = p.offset, p.line
+ p.cur.unquoted = ""
+ switch p.s[0] {
+ case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/':
+ // Single symbol
+ p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)]
+ case '"', '\'':
+ // Quoted string
+ i := 1
+ for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' {
+ if p.s[i] == '\\' && i+1 < len(p.s) {
+ // skip escaped char
+ i++
+ }
+ i++
+ }
+ if i >= len(p.s) || p.s[i] != p.s[0] {
+ p.errorf("unmatched quote")
+ return
+ }
+ unq, err := unquoteC(p.s[1:i], rune(p.s[0]))
+ if err != nil {
+ p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err)
+ return
+ }
+ p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)]
+ p.cur.unquoted = unq
+ default:
+ i := 0
+ for i < len(p.s) && isIdentOrNumberChar(p.s[i]) {
+ i++
+ }
+ if i == 0 {
+ p.errorf("unexpected byte %#x", p.s[0])
+ return
+ }
+ p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)]
+ }
+ p.offset += len(p.cur.value)
+}
+
+var (
+ errBadUTF8 = errors.New("proto: bad UTF-8")
+ errBadHex = errors.New("proto: bad hexadecimal")
+)
+
+func unquoteC(s string, quote rune) (string, error) {
+ // This is based on C++'s tokenizer.cc.
+ // Despite its name, this is *not* parsing C syntax.
+ // For instance, "\0" is an invalid quoted string.
+
+ // Avoid allocation in trivial cases.
+ simple := true
+ for _, r := range s {
+ if r == '\\' || r == quote {
+ simple = false
+ break
+ }
+ }
+ if simple {
+ return s, nil
+ }
+
+ buf := make([]byte, 0, 3*len(s)/2)
+ for len(s) > 0 {
+ r, n := utf8.DecodeRuneInString(s)
+ if r == utf8.RuneError && n == 1 {
+ return "", errBadUTF8
+ }
+ s = s[n:]
+ if r != '\\' {
+ if r < utf8.RuneSelf {
+ buf = append(buf, byte(r))
+ } else {
+ buf = append(buf, string(r)...)
+ }
+ continue
+ }
+
+ ch, tail, err := unescape(s)
+ if err != nil {
+ return "", err
+ }
+ buf = append(buf, ch...)
+ s = tail
+ }
+ return string(buf), nil
+}
+
+func unescape(s string) (ch string, tail string, err error) {
+ r, n := utf8.DecodeRuneInString(s)
+ if r == utf8.RuneError && n == 1 {
+ return "", "", errBadUTF8
+ }
+ s = s[n:]
+ switch r {
+ case 'a':
+ return "\a", s, nil
+ case 'b':
+ return "\b", s, nil
+ case 'f':
+ return "\f", s, nil
+ case 'n':
+ return "\n", s, nil
+ case 'r':
+ return "\r", s, nil
+ case 't':
+ return "\t", s, nil
+ case 'v':
+ return "\v", s, nil
+ case '?':
+ return "?", s, nil // trigraph workaround
+ case '\'', '"', '\\':
+ return string(r), s, nil
+ case '0', '1', '2', '3', '4', '5', '6', '7', 'x', 'X':
+ if len(s) < 2 {
+ return "", "", fmt.Errorf(`\%c requires 2 following digits`, r)
+ }
+ base := 8
+ ss := s[:2]
+ s = s[2:]
+ if r == 'x' || r == 'X' {
+ base = 16
+ } else {
+ ss = string(r) + ss
+ }
+ i, err := strconv.ParseUint(ss, base, 8)
+ if err != nil {
+ return "", "", err
+ }
+ return string([]byte{byte(i)}), s, nil
+ case 'u', 'U':
+ n := 4
+ if r == 'U' {
+ n = 8
+ }
+ if len(s) < n {
+ return "", "", fmt.Errorf(`\%c requires %d digits`, r, n)
+ }
+
+ bs := make([]byte, n/2)
+ for i := 0; i < n; i += 2 {
+ a, ok1 := unhex(s[i])
+ b, ok2 := unhex(s[i+1])
+ if !ok1 || !ok2 {
+ return "", "", errBadHex
+ }
+ bs[i/2] = a<<4 | b
+ }
+ s = s[n:]
+ return string(bs), s, nil
+ }
+ return "", "", fmt.Errorf(`unknown escape \%c`, r)
+}
+
+// Adapted from src/pkg/strconv/quote.go.
+func unhex(b byte) (v byte, ok bool) {
+ switch {
+ case '0' <= b && b <= '9':
+ return b - '0', true
+ case 'a' <= b && b <= 'f':
+ return b - 'a' + 10, true
+ case 'A' <= b && b <= 'F':
+ return b - 'A' + 10, true
+ }
+ return 0, false
+}
+
+// Back off the parser by one token. Can only be done between calls to next().
+// It makes the next advance() a no-op.
+func (p *textParser) back() { p.backed = true }
+
+// Advances the parser and returns the new current token.
+func (p *textParser) next() *token {
+ if p.backed || p.done {
+ p.backed = false
+ return &p.cur
+ }
+ p.advance()
+ if p.done {
+ p.cur.value = ""
+ } else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) {
+ // Look for multiple quoted strings separated by whitespace,
+ // and concatenate them.
+ cat := p.cur
+ for {
+ p.skipWhitespace()
+ if p.done || !isQuote(p.s[0]) {
+ break
+ }
+ p.advance()
+ if p.cur.err != nil {
+ return &p.cur
+ }
+ cat.value += " " + p.cur.value
+ cat.unquoted += p.cur.unquoted
+ }
+ p.done = false // parser may have seen EOF, but we want to return cat
+ p.cur = cat
+ }
+ return &p.cur
+}
+
+func (p *textParser) consumeToken(s string) error {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value != s {
+ p.back()
+ return p.errorf("expected %q, found %q", s, tok.value)
+ }
+ return nil
+}
+
+// Return a RequiredNotSetError indicating which required field was not set.
+func (p *textParser) missingRequiredFieldError(sv reflect.Value) *RequiredNotSetError {
+ st := sv.Type()
+ sprops := GetProperties(st)
+ for i := 0; i < st.NumField(); i++ {
+ if !isNil(sv.Field(i)) {
+ continue
+ }
+
+ props := sprops.Prop[i]
+ if props.Required {
+ return &RequiredNotSetError{fmt.Sprintf("%v.%v", st, props.OrigName)}
+ }
+ }
+ return &RequiredNotSetError{fmt.Sprintf("%v.<unknown field name>", st)} // should not happen
+}
+
+// Returns the index in the struct for the named field, as well as the parsed tag properties.
+func structFieldByName(sprops *StructProperties, name string) (int, *Properties, bool) {
+ i, ok := sprops.decoderOrigNames[name]
+ if ok {
+ return i, sprops.Prop[i], true
+ }
+ return -1, nil, false
+}
+
+// Consume a ':' from the input stream (if the next token is a colon),
+// returning an error if a colon is needed but not present.
+func (p *textParser) checkForColon(props *Properties, typ reflect.Type) *ParseError {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value != ":" {
+ // Colon is optional when the field is a group or message.
+ needColon := true
+ switch props.Wire {
+ case "group":
+ needColon = false
+ case "bytes":
+ // A "bytes" field is either a message, a string, or a repeated field;
+ // those three become *T, *string and []T respectively, so we can check for
+ // this field being a pointer to a non-string.
+ if typ.Kind() == reflect.Ptr {
+ // *T or *string
+ if typ.Elem().Kind() == reflect.String {
+ break
+ }
+ } else if typ.Kind() == reflect.Slice {
+ // []T or []*T
+ if typ.Elem().Kind() != reflect.Ptr {
+ break
+ }
+ } else if typ.Kind() == reflect.String {
+ // The proto3 exception is for a string field,
+ // which requires a colon.
+ break
+ }
+ needColon = false
+ }
+ if needColon {
+ return p.errorf("expected ':', found %q", tok.value)
+ }
+ p.back()
+ }
+ return nil
+}
+
+func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
+ st := sv.Type()
+ sprops := GetProperties(st)
+ reqCount := sprops.reqCount
+ var reqFieldErr error
+ fieldSet := make(map[string]bool)
+ // A struct is a sequence of "name: value", terminated by one of
+ // '>' or '}', or the end of the input. A name may also be
+ // "[extension]" or "[type/url]".
+ //
+ // The whole struct can also be an expanded Any message, like:
+ // [type/url] < ... struct contents ... >
+ for {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value == terminator {
+ break
+ }
+ if tok.value == "[" {
+ // Looks like an extension or an Any.
+ //
+ // TODO: Check whether we need to handle
+ // namespace rooted names (e.g. ".something.Foo").
+ extName, err := p.consumeExtName()
+ if err != nil {
+ return err
+ }
+
+ if s := strings.LastIndex(extName, "/"); s >= 0 {
+ // If it contains a slash, it's an Any type URL.
+ messageName := extName[s+1:]
+ mt := MessageType(messageName)
+ if mt == nil {
+ return p.errorf("unrecognized message %q in google.protobuf.Any", messageName)
+ }
+ tok = p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ // consume an optional colon
+ if tok.value == ":" {
+ tok = p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ }
+ var terminator string
+ switch tok.value {
+ case "<":
+ terminator = ">"
+ case "{":
+ terminator = "}"
+ default:
+ return p.errorf("expected '{' or '<', found %q", tok.value)
+ }
+ v := reflect.New(mt.Elem())
+ if pe := p.readStruct(v.Elem(), terminator); pe != nil {
+ return pe
+ }
+ b, err := Marshal(v.Interface().(Message))
+ if err != nil {
+ return p.errorf("failed to marshal message of type %q: %v", messageName, err)
+ }
+ sv.FieldByName("TypeUrl").SetString(extName)
+ sv.FieldByName("Value").SetBytes(b)
+ continue
+ }
+
+ var desc *ExtensionDesc
+ // This could be faster, but it's functional.
+ // TODO: Do something smarter than a linear scan.
+ for _, d := range RegisteredExtensions(reflect.New(st).Interface().(Message)) {
+ if d.Name == extName {
+ desc = d
+ break
+ }
+ }
+ if desc == nil {
+ return p.errorf("unrecognized extension %q", extName)
+ }
+
+ props := &Properties{}
+ props.Parse(desc.Tag)
+
+ typ := reflect.TypeOf(desc.ExtensionType)
+ if err := p.checkForColon(props, typ); err != nil {
+ return err
+ }
+
+ rep := desc.repeated()
+
+ // Read the extension structure, and set it in
+ // the value we're constructing.
+ var ext reflect.Value
+ if !rep {
+ ext = reflect.New(typ).Elem()
+ } else {
+ ext = reflect.New(typ.Elem()).Elem()
+ }
+ if err := p.readAny(ext, props); err != nil {
+ if _, ok := err.(*RequiredNotSetError); !ok {
+ return err
+ }
+ reqFieldErr = err
+ }
+ ep := sv.Addr().Interface().(Message)
+ if !rep {
+ SetExtension(ep, desc, ext.Interface())
+ } else {
+ old, err := GetExtension(ep, desc)
+ var sl reflect.Value
+ if err == nil {
+ sl = reflect.ValueOf(old) // existing slice
+ } else {
+ sl = reflect.MakeSlice(typ, 0, 1)
+ }
+ sl = reflect.Append(sl, ext)
+ SetExtension(ep, desc, sl.Interface())
+ }
+ if err := p.consumeOptionalSeparator(); err != nil {
+ return err
+ }
+ continue
+ }
+
+ // This is a normal, non-extension field.
+ name := tok.value
+ var dst reflect.Value
+ fi, props, ok := structFieldByName(sprops, name)
+ if ok {
+ dst = sv.Field(fi)
+ } else if oop, ok := sprops.OneofTypes[name]; ok {
+ // It is a oneof.
+ props = oop.Prop
+ nv := reflect.New(oop.Type.Elem())
+ dst = nv.Elem().Field(0)
+ sv.Field(oop.Field).Set(nv)
+ }
+ if !dst.IsValid() {
+ return p.errorf("unknown field name %q in %v", name, st)
+ }
+
+ if dst.Kind() == reflect.Map {
+ // Consume any colon.
+ if err := p.checkForColon(props, dst.Type()); err != nil {
+ return err
+ }
+
+ // Construct the map if it doesn't already exist.
+ if dst.IsNil() {
+ dst.Set(reflect.MakeMap(dst.Type()))
+ }
+ key := reflect.New(dst.Type().Key()).Elem()
+ val := reflect.New(dst.Type().Elem()).Elem()
+
+ // The map entry should be this sequence of tokens:
+ // < key : KEY value : VALUE >
+ // However, implementations may omit key or value, and technically
+ // we should support them in any order. See b/28924776 for a time
+ // this went wrong.
+
+ tok := p.next()
+ var terminator string
+ switch tok.value {
+ case "<":
+ terminator = ">"
+ case "{":
+ terminator = "}"
+ default:
+ return p.errorf("expected '{' or '<', found %q", tok.value)
+ }
+ for {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value == terminator {
+ break
+ }
+ switch tok.value {
+ case "key":
+ if err := p.consumeToken(":"); err != nil {
+ return err
+ }
+ if err := p.readAny(key, props.mkeyprop); err != nil {
+ return err
+ }
+ if err := p.consumeOptionalSeparator(); err != nil {
+ return err
+ }
+ case "value":
+ if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil {
+ return err
+ }
+ if err := p.readAny(val, props.mvalprop); err != nil {
+ return err
+ }
+ if err := p.consumeOptionalSeparator(); err != nil {
+ return err
+ }
+ default:
+ p.back()
+ return p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value)
+ }
+ }
+
+ dst.SetMapIndex(key, val)
+ continue
+ }
+
+ // Check that it's not already set if it's not a repeated field.
+ if !props.Repeated && fieldSet[name] {
+ return p.errorf("non-repeated field %q was repeated", name)
+ }
+
+ if err := p.checkForColon(props, dst.Type()); err != nil {
+ return err
+ }
+
+ // Parse into the field.
+ fieldSet[name] = true
+ if err := p.readAny(dst, props); err != nil {
+ if _, ok := err.(*RequiredNotSetError); !ok {
+ return err
+ }
+ reqFieldErr = err
+ }
+ if props.Required {
+ reqCount--
+ }
+
+ if err := p.consumeOptionalSeparator(); err != nil {
+ return err
+ }
+
+ }
+
+ if reqCount > 0 {
+ return p.missingRequiredFieldError(sv)
+ }
+ return reqFieldErr
+}
+
+// consumeExtName consumes extension name or expanded Any type URL and the
+// following ']'. It returns the name or URL consumed.
+func (p *textParser) consumeExtName() (string, error) {
+ tok := p.next()
+ if tok.err != nil {
+ return "", tok.err
+ }
+
+ // If extension name or type url is quoted, it's a single token.
+ if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] {
+ name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0]))
+ if err != nil {
+ return "", err
+ }
+ return name, p.consumeToken("]")
+ }
+
+ // Consume everything up to "]"
+ var parts []string
+ for tok.value != "]" {
+ parts = append(parts, tok.value)
+ tok = p.next()
+ if tok.err != nil {
+ return "", p.errorf("unrecognized type_url or extension name: %s", tok.err)
+ }
+ }
+ return strings.Join(parts, ""), nil
+}
+
+// consumeOptionalSeparator consumes an optional semicolon or comma.
+// It is used in readStruct to provide backward compatibility.
+func (p *textParser) consumeOptionalSeparator() error {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value != ";" && tok.value != "," {
+ p.back()
+ }
+ return nil
+}
+
+func (p *textParser) readAny(v reflect.Value, props *Properties) error {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value == "" {
+ return p.errorf("unexpected EOF")
+ }
+
+ switch fv := v; fv.Kind() {
+ case reflect.Slice:
+ at := v.Type()
+ if at.Elem().Kind() == reflect.Uint8 {
+ // Special case for []byte
+ if tok.value[0] != '"' && tok.value[0] != '\'' {
+ // Deliberately written out here, as the error after
+ // this switch statement would write "invalid []byte: ...",
+ // which is not as user-friendly.
+ return p.errorf("invalid string: %v", tok.value)
+ }
+ bytes := []byte(tok.unquoted)
+ fv.Set(reflect.ValueOf(bytes))
+ return nil
+ }
+ // Repeated field.
+ if tok.value == "[" {
+ // Repeated field with list notation, like [1,2,3].
+ for {
+ fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
+ err := p.readAny(fv.Index(fv.Len()-1), props)
+ if err != nil {
+ return err
+ }
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value == "]" {
+ break
+ }
+ if tok.value != "," {
+ return p.errorf("Expected ']' or ',' found %q", tok.value)
+ }
+ }
+ return nil
+ }
+ // One value of the repeated field.
+ p.back()
+ fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
+ return p.readAny(fv.Index(fv.Len()-1), props)
+ case reflect.Bool:
+ // Either "true", "false", 1 or 0.
+ switch tok.value {
+ case "true", "1":
+ fv.SetBool(true)
+ return nil
+ case "false", "0":
+ fv.SetBool(false)
+ return nil
+ }
+ case reflect.Float32, reflect.Float64:
+ v := tok.value
+ // Ignore 'f' for compatibility with output generated by C++, but don't
+ // remove 'f' when the value is "-inf" or "inf".
+ if strings.HasSuffix(v, "f") && tok.value != "-inf" && tok.value != "inf" {
+ v = v[:len(v)-1]
+ }
+ if f, err := strconv.ParseFloat(v, fv.Type().Bits()); err == nil {
+ fv.SetFloat(f)
+ return nil
+ }
+ case reflect.Int32:
+ if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
+ fv.SetInt(x)
+ return nil
+ }
+
+ if len(props.Enum) == 0 {
+ break
+ }
+ m, ok := enumValueMaps[props.Enum]
+ if !ok {
+ break
+ }
+ x, ok := m[tok.value]
+ if !ok {
+ break
+ }
+ fv.SetInt(int64(x))
+ return nil
+ case reflect.Int64:
+ if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil {
+ fv.SetInt(x)
+ return nil
+ }
+
+ case reflect.Ptr:
+ // A basic field (indirected through pointer), or a repeated message/group
+ p.back()
+ fv.Set(reflect.New(fv.Type().Elem()))
+ return p.readAny(fv.Elem(), props)
+ case reflect.String:
+ if tok.value[0] == '"' || tok.value[0] == '\'' {
+ fv.SetString(tok.unquoted)
+ return nil
+ }
+ case reflect.Struct:
+ var terminator string
+ switch tok.value {
+ case "{":
+ terminator = "}"
+ case "<":
+ terminator = ">"
+ default:
+ return p.errorf("expected '{' or '<', found %q", tok.value)
+ }
+ // TODO: Handle nested messages which implement encoding.TextUnmarshaler.
+ return p.readStruct(fv, terminator)
+ case reflect.Uint32:
+ if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
+ fv.SetUint(uint64(x))
+ return nil
+ }
+ case reflect.Uint64:
+ if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil {
+ fv.SetUint(x)
+ return nil
+ }
+ }
+ return p.errorf("invalid %v: %v", v.Type(), tok.value)
+}
+
+// UnmarshalText reads a protocol buffer in Text format. UnmarshalText resets pb
+// before starting to unmarshal, so any existing data in pb is always removed.
+// If a required field is not set and no other error occurs,
+// UnmarshalText returns *RequiredNotSetError.
+func UnmarshalText(s string, pb Message) error {
+ if um, ok := pb.(encoding.TextUnmarshaler); ok {
+ err := um.UnmarshalText([]byte(s))
+ return err
+ }
+ pb.Reset()
+ v := reflect.ValueOf(pb)
+ if pe := newTextParser(s).readStruct(v.Elem(), ""); pe != nil {
+ return pe
+ }
+ return nil
+}
--- /dev/null
+Mozilla Public License, version 2.0
+
+1. Definitions
+
+1.1. “Contributor”
+
+ means each individual or legal entity that creates, contributes to the
+ creation of, or owns Covered Software.
+
+1.2. “Contributor Version”
+
+ means the combination of the Contributions of others (if any) used by a
+ Contributor and that particular Contributor’s Contribution.
+
+1.3. “Contribution”
+
+ means Covered Software of a particular Contributor.
+
+1.4. “Covered Software”
+
+ means Source Code Form to which the initial Contributor has attached the
+ notice in Exhibit A, the Executable Form of such Source Code Form, and
+ Modifications of such Source Code Form, in each case including portions
+ thereof.
+
+1.5. “Incompatible With Secondary Licenses”
+ means
+
+ a. that the initial Contributor has attached the notice described in
+ Exhibit B to the Covered Software; or
+
+ b. that the Covered Software was made available under the terms of version
+ 1.1 or earlier of the License, but not also under the terms of a
+ Secondary License.
+
+1.6. “Executable Form”
+
+ means any form of the work other than Source Code Form.
+
+1.7. “Larger Work”
+
+ means a work that combines Covered Software with other material, in a separate
+ file or files, that is not Covered Software.
+
+1.8. “License”
+
+ means this document.
+
+1.9. “Licensable”
+
+ means having the right to grant, to the maximum extent possible, whether at the
+ time of the initial grant or subsequently, any and all of the rights conveyed by
+ this License.
+
+1.10. “Modifications”
+
+ means any of the following:
+
+ a. any file in Source Code Form that results from an addition to, deletion
+ from, or modification of the contents of Covered Software; or
+
+ b. any new file in Source Code Form that contains any Covered Software.
+
+1.11. “Patent Claims” of a Contributor
+
+ means any patent claim(s), including without limitation, method, process,
+ and apparatus claims, in any patent Licensable by such Contributor that
+ would be infringed, but for the grant of the License, by the making,
+ using, selling, offering for sale, having made, import, or transfer of
+ either its Contributions or its Contributor Version.
+
+1.12. “Secondary License”
+
+ means either the GNU General Public License, Version 2.0, the GNU Lesser
+ General Public License, Version 2.1, the GNU Affero General Public
+ License, Version 3.0, or any later versions of those licenses.
+
+1.13. “Source Code Form”
+
+ means the form of the work preferred for making modifications.
+
+1.14. “You” (or “Your”)
+
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, “You” includes any entity that controls, is
+ controlled by, or is under common control with You. For purposes of this
+ definition, “control” means (a) the power, direct or indirect, to cause
+ the direction or management of such entity, whether by contract or
+ otherwise, or (b) ownership of more than fifty percent (50%) of the
+ outstanding shares or beneficial ownership of such entity.
+
+
+2. License Grants and Conditions
+
+2.1. Grants
+
+ Each Contributor hereby grants You a world-wide, royalty-free,
+ non-exclusive license:
+
+ a. under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or as
+ part of a Larger Work; and
+
+ b. under Patent Claims of such Contributor to make, use, sell, offer for
+ sale, have made, import, and otherwise transfer either its Contributions
+ or its Contributor Version.
+
+2.2. Effective Date
+
+ The licenses granted in Section 2.1 with respect to any Contribution become
+ effective for each Contribution on the date the Contributor first distributes
+ such Contribution.
+
+2.3. Limitations on Grant Scope
+
+ The licenses granted in this Section 2 are the only rights granted under this
+ License. No additional rights or licenses will be implied from the distribution
+ or licensing of Covered Software under this License. Notwithstanding Section
+ 2.1(b) above, no patent license is granted by a Contributor:
+
+ a. for any code that a Contributor has removed from Covered Software; or
+
+ b. for infringements caused by: (i) Your and any other third party’s
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+ c. under Patent Claims infringed by Covered Software in the absence of its
+ Contributions.
+
+ This License does not grant any rights in the trademarks, service marks, or
+ logos of any Contributor (except as may be necessary to comply with the
+ notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+ No Contributor makes additional grants as a result of Your choice to
+ distribute the Covered Software under a subsequent version of this License
+ (see Section 10.2) or under the terms of a Secondary License (if permitted
+ under the terms of Section 3.3).
+
+2.5. Representation
+
+ Each Contributor represents that the Contributor believes its Contributions
+ are its original creation(s) or it has sufficient rights to grant the
+ rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+ This License is not intended to limit any rights You have under applicable
+ copyright doctrines of fair use, fair dealing, or other equivalents.
+
+2.7. Conditions
+
+ Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
+ Section 2.1.
+
+
+3. Responsibilities
+
+3.1. Distribution of Source Form
+
+ All distribution of Covered Software in Source Code Form, including any
+ Modifications that You create or to which You contribute, must be under the
+ terms of this License. You must inform recipients that the Source Code Form
+ of the Covered Software is governed by the terms of this License, and how
+ they can obtain a copy of this License. You may not attempt to alter or
+ restrict the recipients’ rights in the Source Code Form.
+
+3.2. Distribution of Executable Form
+
+ If You distribute Covered Software in Executable Form then:
+
+ a. such Covered Software must also be made available in Source Code Form,
+ as described in Section 3.1, and You must inform recipients of the
+ Executable Form how they can obtain a copy of such Source Code Form by
+ reasonable means in a timely manner, at a charge no more than the cost
+ of distribution to the recipient; and
+
+ b. You may distribute such Executable Form under the terms of this License,
+ or sublicense it under different terms, provided that the license for
+ the Executable Form does not attempt to limit or alter the recipients’
+ rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+ You may create and distribute a Larger Work under terms of Your choice,
+ provided that You also comply with the requirements of this License for the
+ Covered Software. If the Larger Work is a combination of Covered Software
+ with a work governed by one or more Secondary Licenses, and the Covered
+ Software is not Incompatible With Secondary Licenses, this License permits
+ You to additionally distribute such Covered Software under the terms of
+ such Secondary License(s), so that the recipient of the Larger Work may, at
+ their option, further distribute the Covered Software under the terms of
+ either this License or such Secondary License(s).
+
+3.4. Notices
+
+ You may not remove or alter the substance of any license notices (including
+ copyright notices, patent notices, disclaimers of warranty, or limitations
+ of liability) contained within the Source Code Form of the Covered
+ Software, except that You may alter any license notices to the extent
+ required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+ You may choose to offer, and to charge a fee for, warranty, support,
+ indemnity or liability obligations to one or more recipients of Covered
+ Software. However, You may do so only on Your own behalf, and not on behalf
+ of any Contributor. You must make it absolutely clear that any such
+ warranty, support, indemnity, or liability obligation is offered by You
+ alone, and You hereby agree to indemnify every Contributor for any
+ liability incurred by such Contributor as a result of warranty, support,
+ indemnity or liability terms You offer. You may include additional
+ disclaimers of warranty and limitations of liability specific to any
+ jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+
+ If it is impossible for You to comply with any of the terms of this License
+ with respect to some or all of the Covered Software due to statute, judicial
+ order, or regulation then You must: (a) comply with the terms of this License
+ to the maximum extent possible; and (b) describe the limitations and the code
+ they affect. Such description must be placed in a text file included with all
+ distributions of the Covered Software under this License. Except to the
+ extent prohibited by statute or regulation, such description must be
+ sufficiently detailed for a recipient of ordinary skill to be able to
+ understand it.
+
+5. Termination
+
+5.1. The rights granted under this License will terminate automatically if You
+ fail to comply with any of its terms. However, if You become compliant,
+ then the rights granted under this License from a particular Contributor
+ are reinstated (a) provisionally, unless and until such Contributor
+ explicitly and finally terminates Your grants, and (b) on an ongoing basis,
+ if such Contributor fails to notify You of the non-compliance by some
+ reasonable means prior to 60 days after You have come back into compliance.
+ Moreover, Your grants from a particular Contributor are reinstated on an
+ ongoing basis if such Contributor notifies You of the non-compliance by
+ some reasonable means, this is the first time You have received notice of
+ non-compliance with this License from such Contributor, and You become
+ compliant prior to 30 days after Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+ infringement claim (excluding declaratory judgment actions, counter-claims,
+ and cross-claims) alleging that a Contributor Version directly or
+ indirectly infringes any patent, then the rights granted to You by any and
+ all Contributors for the Covered Software under Section 2.1 of this License
+ shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
+ license agreements (excluding distributors and resellers) which have been
+ validly granted by You or Your distributors under this License prior to
+ termination shall survive termination.
+
+6. Disclaimer of Warranty
+
+ Covered Software is provided under this License on an “as is” basis, without
+ warranty of any kind, either expressed, implied, or statutory, including,
+ without limitation, warranties that the Covered Software is free of defects,
+ merchantable, fit for a particular purpose or non-infringing. The entire
+ risk as to the quality and performance of the Covered Software is with You.
+ Should any Covered Software prove defective in any respect, You (not any
+ Contributor) assume the cost of any necessary servicing, repair, or
+ correction. This disclaimer of warranty constitutes an essential part of this
+ License. No use of any Covered Software is authorized under this License
+ except under this disclaimer.
+
+7. Limitation of Liability
+
+ Under no circumstances and under no legal theory, whether tort (including
+ negligence), contract, or otherwise, shall any Contributor, or anyone who
+ distributes Covered Software as permitted above, be liable to You for any
+ direct, indirect, special, incidental, or consequential damages of any
+ character including, without limitation, damages for lost profits, loss of
+ goodwill, work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses, even if such party shall have been
+ informed of the possibility of such damages. This limitation of liability
+ shall not apply to liability for death or personal injury resulting from such
+ party’s negligence to the extent applicable law prohibits such limitation.
+ Some jurisdictions do not allow the exclusion or limitation of incidental or
+ consequential damages, so this exclusion and limitation may not apply to You.
+
+8. Litigation
+
+ Any litigation relating to this License may be brought only in the courts of
+ a jurisdiction where the defendant maintains its principal place of business
+ and such litigation shall be governed by laws of that jurisdiction, without
+ reference to its conflict-of-law provisions. Nothing in this Section shall
+ prevent a party’s ability to bring cross-claims or counter-claims.
+
+9. Miscellaneous
+
+ This License represents the complete agreement concerning the subject matter
+ hereof. If any provision of this License is held to be unenforceable, such
+ provision shall be reformed only to the extent necessary to make it
+ enforceable. Any law or regulation which provides that the language of a
+ contract shall be construed against the drafter shall not be used to construe
+ this License against a Contributor.
+
+
+10. Versions of the License
+
+10.1. New Versions
+
+ Mozilla Foundation is the license steward. Except as provided in Section
+ 10.3, no one other than the license steward has the right to modify or
+ publish new versions of this License. Each version will be given a
+ distinguishing version number.
+
+10.2. Effect of New Versions
+
+ You may distribute the Covered Software under the terms of the version of
+ the License under which You originally received the Covered Software, or
+ under the terms of any subsequent version published by the license
+ steward.
+
+10.3. Modified Versions
+
+ If you create software not governed by this License, and you want to
+ create a new license for such software, you may create and use a modified
+ version of this License if you rename the license and remove any
+ references to the name of the license steward (except to note that such
+ modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
+ If You choose to distribute Source Code Form that is Incompatible With
+ Secondary Licenses under the terms of this version of the License, the
+ notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+
+ This Source Code Form is subject to the
+ terms of the Mozilla Public License, v.
+ 2.0. If a copy of the MPL was not
+ distributed with this file, You can
+ obtain one at
+ http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular file, then
+You may include the notice in a location (such as a LICENSE file in a relevant
+directory) where a recipient would be likely to look for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - “Incompatible With Secondary Licenses” Notice
+
+ This Source Code Form is “Incompatible
+ With Secondary Licenses”, as defined by
+ the Mozilla Public License, v. 2.0.
+
--- /dev/null
+# errwrap
+
+`errwrap` is a package for Go that formalizes the pattern of wrapping errors
+and checking if an error contains another error.
+
+There is a common pattern in Go of taking a returned `error` value and
+then wrapping it (such as with `fmt.Errorf`) before returning it. The problem
+with this pattern is that you completely lose the original `error` structure.
+
+Arguably the _correct_ approach is that you should make a custom structure
+implementing the `error` interface, and have the original error as a field
+on that structure, such [as this example](http://golang.org/pkg/os/#PathError).
+This is a good approach, but you have to know the entire chain of possible
+rewrapping that happens, when you might just care about one.
+
+`errwrap` formalizes this pattern (it doesn't matter what approach you use
+above) by giving a single interface for wrapping errors, checking if a specific
+error is wrapped, and extracting that error.
+
+## Installation and Docs
+
+Install using `go get github.com/hashicorp/errwrap`.
+
+Full documentation is available at
+http://godoc.org/github.com/hashicorp/errwrap
+
+## Usage
+
+#### Basic Usage
+
+Below is a very basic example of its usage:
+
+```go
+// A function that always returns an error, but wraps it, like a real
+// function might.
+func tryOpen() error {
+ _, err := os.Open("/i/dont/exist")
+ if err != nil {
+ return errwrap.Wrapf("Doesn't exist: {{err}}", err)
+ }
+
+ return nil
+}
+
+func main() {
+ err := tryOpen()
+
+ // We can use the Contains helpers to check if an error contains
+ // another error. It is safe to do this with a nil error, or with
+ // an error that doesn't even use the errwrap package.
+ if errwrap.Contains(err, ErrNotExist) {
+ // Do something
+ }
+ if errwrap.ContainsType(err, new(os.PathError)) {
+ // Do something
+ }
+
+ // Or we can use the associated `Get` functions to just extract
+ // a specific error. This would return nil if that specific error doesn't
+ // exist.
+ perr := errwrap.GetType(err, new(os.PathError))
+}
+```
+
+#### Custom Types
+
+If you're already making custom types that properly wrap errors, then
+you can get all the functionality of `errwraps.Contains` and such by
+implementing the `Wrapper` interface with just one function. Example:
+
+```go
+type AppError {
+ Code ErrorCode
+ Err error
+}
+
+func (e *AppError) WrappedErrors() []error {
+ return []error{e.Err}
+}
+```
+
+Now this works:
+
+```go
+err := &AppError{Err: fmt.Errorf("an error")}
+if errwrap.ContainsType(err, fmt.Errorf("")) {
+ // This will work!
+}
+```
--- /dev/null
+// Package errwrap implements methods to formalize error wrapping in Go.
+//
+// All of the top-level functions that take an `error` are built to be able
+// to take any error, not just wrapped errors. This allows you to use errwrap
+// without having to type-check and type-cast everywhere.
+package errwrap
+
+import (
+ "errors"
+ "reflect"
+ "strings"
+)
+
+// WalkFunc is the callback called for Walk.
+type WalkFunc func(error)
+
+// Wrapper is an interface that can be implemented by custom types to
+// have all the Contains, Get, etc. functions in errwrap work.
+//
+// When Walk reaches a Wrapper, it will call the callback for every
+// wrapped error in addition to the wrapper itself. Since all the top-level
+// functions in errwrap use Walk, this means that all those functions work
+// with your custom type.
+type Wrapper interface {
+ WrappedErrors() []error
+}
+
+// Wrap defines that outer wraps inner, returning an error type that
+// can be cleanly used with the other methods in this package, such as
+// Contains, GetAll, etc.
+//
+// This function won't modify the error message at all (the outer message
+// will be used).
+func Wrap(outer, inner error) error {
+ return &wrappedError{
+ Outer: outer,
+ Inner: inner,
+ }
+}
+
+// Wrapf wraps an error with a formatting message. This is similar to using
+// `fmt.Errorf` to wrap an error. If you're using `fmt.Errorf` to wrap
+// errors, you should replace it with this.
+//
+// format is the format of the error message. The string '{{err}}' will
+// be replaced with the original error message.
+func Wrapf(format string, err error) error {
+ outerMsg := "<nil>"
+ if err != nil {
+ outerMsg = err.Error()
+ }
+
+ outer := errors.New(strings.Replace(
+ format, "{{err}}", outerMsg, -1))
+
+ return Wrap(outer, err)
+}
+
+// Contains checks if the given error contains an error with the
+// message msg. If err is not a wrapped error, this will always return
+// false unless the error itself happens to match this msg.
+func Contains(err error, msg string) bool {
+ return len(GetAll(err, msg)) > 0
+}
+
+// ContainsType checks if the given error contains an error with
+// the same concrete type as v. If err is not a wrapped error, this will
+// check the err itself.
+func ContainsType(err error, v interface{}) bool {
+ return len(GetAllType(err, v)) > 0
+}
+
+// Get is the same as GetAll but returns the deepest matching error.
+func Get(err error, msg string) error {
+ es := GetAll(err, msg)
+ if len(es) > 0 {
+ return es[len(es)-1]
+ }
+
+ return nil
+}
+
+// GetType is the same as GetAllType but returns the deepest matching error.
+func GetType(err error, v interface{}) error {
+ es := GetAllType(err, v)
+ if len(es) > 0 {
+ return es[len(es)-1]
+ }
+
+ return nil
+}
+
+// GetAll gets all the errors that might be wrapped in err with the
+// given message. The order of the errors is such that the outermost
+// matching error (the most recent wrap) is index zero, and so on.
+func GetAll(err error, msg string) []error {
+ var result []error
+
+ Walk(err, func(err error) {
+ if err.Error() == msg {
+ result = append(result, err)
+ }
+ })
+
+ return result
+}
+
+// GetAllType gets all the errors that are the same type as v.
+//
+// The order of the return value is the same as described in GetAll.
+func GetAllType(err error, v interface{}) []error {
+ var result []error
+
+ var search string
+ if v != nil {
+ search = reflect.TypeOf(v).String()
+ }
+ Walk(err, func(err error) {
+ var needle string
+ if err != nil {
+ needle = reflect.TypeOf(err).String()
+ }
+
+ if needle == search {
+ result = append(result, err)
+ }
+ })
+
+ return result
+}
+
+// Walk walks all the wrapped errors in err and calls the callback. If
+// err isn't a wrapped error, this will be called once for err. If err
+// is a wrapped error, the callback will be called for both the wrapper
+// that implements error as well as the wrapped error itself.
+func Walk(err error, cb WalkFunc) {
+ if err == nil {
+ return
+ }
+
+ switch e := err.(type) {
+ case *wrappedError:
+ cb(e.Outer)
+ Walk(e.Inner, cb)
+ case Wrapper:
+ cb(err)
+
+ for _, err := range e.WrappedErrors() {
+ Walk(err, cb)
+ }
+ default:
+ cb(err)
+ }
+}
+
+// wrappedError is an implementation of error that has both the
+// outer and inner errors.
+type wrappedError struct {
+ Outer error
+ Inner error
+}
+
+func (w *wrappedError) Error() string {
+ return w.Outer.Error()
+}
+
+func (w *wrappedError) WrappedErrors() []error {
+ return []error{w.Outer, w.Inner}
+}
--- /dev/null
+Mozilla Public License, version 2.0
+
+1. Definitions
+
+1.1. "Contributor"
+
+ means each individual or legal entity that creates, contributes to the
+ creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+
+ means the combination of the Contributions of others (if any) used by a
+ Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+
+ means Source Code Form to which the initial Contributor has attached the
+ notice in Exhibit A, the Executable Form of such Source Code Form, and
+ Modifications of such Source Code Form, in each case including portions
+ thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ a. that the initial Contributor has attached the notice described in
+ Exhibit B to the Covered Software; or
+
+ b. that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the terms of
+ a Secondary License.
+
+1.6. "Executable Form"
+
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+
+ means a work that combines Covered Software with other material, in a
+ separate file or files, that is not Covered Software.
+
+1.8. "License"
+
+ means this document.
+
+1.9. "Licensable"
+
+ means having the right to grant, to the maximum extent possible, whether
+ at the time of the initial grant or subsequently, any and all of the
+ rights conveyed by this License.
+
+1.10. "Modifications"
+
+ means any of the following:
+
+ a. any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered Software; or
+
+ b. any new file in Source Code Form that contains any Covered Software.
+
+1.11. "Patent Claims" of a Contributor
+
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the License,
+ by the making, using, selling, offering for sale, having made, import,
+ or transfer of either its Contributions or its Contributor Version.
+
+1.12. "Secondary License"
+
+ means either the GNU General Public License, Version 2.0, the GNU Lesser
+ General Public License, Version 2.1, the GNU Affero General Public
+ License, Version 3.0, or any later versions of those licenses.
+
+1.13. "Source Code Form"
+
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that controls, is
+ controlled by, or is under common control with You. For purposes of this
+ definition, "control" means (a) the power, direct or indirect, to cause
+ the direction or management of such entity, whether by contract or
+ otherwise, or (b) ownership of more than fifty percent (50%) of the
+ outstanding shares or beneficial ownership of such entity.
+
+
+2. License Grants and Conditions
+
+2.1. Grants
+
+ Each Contributor hereby grants You a world-wide, royalty-free,
+ non-exclusive license:
+
+ a. under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+ b. under Patent Claims of such Contributor to make, use, sell, offer for
+ sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+ The licenses granted in Section 2.1 with respect to any Contribution
+ become effective for each Contribution on the date the Contributor first
+ distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+ The licenses granted in this Section 2 are the only rights granted under
+ this License. No additional rights or licenses will be implied from the
+ distribution or licensing of Covered Software under this License.
+ Notwithstanding Section 2.1(b) above, no patent license is granted by a
+ Contributor:
+
+ a. for any code that a Contributor has removed from Covered Software; or
+
+ b. for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+ c. under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+ This License does not grant any rights in the trademarks, service marks,
+ or logos of any Contributor (except as may be necessary to comply with
+ the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+ No Contributor makes additional grants as a result of Your choice to
+ distribute the Covered Software under a subsequent version of this
+ License (see Section 10.2) or under the terms of a Secondary License (if
+ permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+ Each Contributor represents that the Contributor believes its
+ Contributions are its original creation(s) or it has sufficient rights to
+ grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+ This License is not intended to limit any rights You have under
+ applicable copyright doctrines of fair use, fair dealing, or other
+ equivalents.
+
+2.7. Conditions
+
+ Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
+ Section 2.1.
+
+
+3. Responsibilities
+
+3.1. Distribution of Source Form
+
+ All distribution of Covered Software in Source Code Form, including any
+ Modifications that You create or to which You contribute, must be under
+ the terms of this License. You must inform recipients that the Source
+ Code Form of the Covered Software is governed by the terms of this
+ License, and how they can obtain a copy of this License. You may not
+ attempt to alter or restrict the recipients' rights in the Source Code
+ Form.
+
+3.2. Distribution of Executable Form
+
+ If You distribute Covered Software in Executable Form then:
+
+ a. such Covered Software must also be made available in Source Code Form,
+ as described in Section 3.1, and You must inform recipients of the
+ Executable Form how they can obtain a copy of such Source Code Form by
+ reasonable means in a timely manner, at a charge no more than the cost
+ of distribution to the recipient; and
+
+ b. You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter the
+ recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+ You may create and distribute a Larger Work under terms of Your choice,
+ provided that You also comply with the requirements of this License for
+ the Covered Software. If the Larger Work is a combination of Covered
+ Software with a work governed by one or more Secondary Licenses, and the
+ Covered Software is not Incompatible With Secondary Licenses, this
+ License permits You to additionally distribute such Covered Software
+ under the terms of such Secondary License(s), so that the recipient of
+ the Larger Work may, at their option, further distribute the Covered
+ Software under the terms of either this License or such Secondary
+ License(s).
+
+3.4. Notices
+
+ You may not remove or alter the substance of any license notices
+ (including copyright notices, patent notices, disclaimers of warranty, or
+ limitations of liability) contained within the Source Code Form of the
+ Covered Software, except that You may alter any license notices to the
+ extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+ You may choose to offer, and to charge a fee for, warranty, support,
+ indemnity or liability obligations to one or more recipients of Covered
+ Software. However, You may do so only on Your own behalf, and not on
+ behalf of any Contributor. You must make it absolutely clear that any
+ such warranty, support, indemnity, or liability obligation is offered by
+ You alone, and You hereby agree to indemnify every Contributor for any
+ liability incurred by such Contributor as a result of warranty, support,
+ indemnity or liability terms You offer. You may include additional
+ disclaimers of warranty and limitations of liability specific to any
+ jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+
+ If it is impossible for You to comply with any of the terms of this License
+ with respect to some or all of the Covered Software due to statute,
+ judicial order, or regulation then You must: (a) comply with the terms of
+ this License to the maximum extent possible; and (b) describe the
+ limitations and the code they affect. Such description must be placed in a
+ text file included with all distributions of the Covered Software under
+ this License. Except to the extent prohibited by statute or regulation,
+ such description must be sufficiently detailed for a recipient of ordinary
+ skill to be able to understand it.
+
+5. Termination
+
+5.1. The rights granted under this License will terminate automatically if You
+ fail to comply with any of its terms. However, if You become compliant,
+ then the rights granted under this License from a particular Contributor
+ are reinstated (a) provisionally, unless and until such Contributor
+ explicitly and finally terminates Your grants, and (b) on an ongoing
+ basis, if such Contributor fails to notify You of the non-compliance by
+ some reasonable means prior to 60 days after You have come back into
+ compliance. Moreover, Your grants from a particular Contributor are
+ reinstated on an ongoing basis if such Contributor notifies You of the
+ non-compliance by some reasonable means, this is the first time You have
+ received notice of non-compliance with this License from such
+ Contributor, and You become compliant prior to 30 days after Your receipt
+ of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+ infringement claim (excluding declaratory judgment actions,
+ counter-claims, and cross-claims) alleging that a Contributor Version
+ directly or indirectly infringes any patent, then the rights granted to
+ You by any and all Contributors for the Covered Software under Section
+ 2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
+ license agreements (excluding distributors and resellers) which have been
+ validly granted by You or Your distributors under this License prior to
+ termination shall survive termination.
+
+6. Disclaimer of Warranty
+
+ Covered Software is provided under this License on an "as is" basis,
+ without warranty of any kind, either expressed, implied, or statutory,
+ including, without limitation, warranties that the Covered Software is free
+ of defects, merchantable, fit for a particular purpose or non-infringing.
+ The entire risk as to the quality and performance of the Covered Software
+ is with You. Should any Covered Software prove defective in any respect,
+ You (not any Contributor) assume the cost of any necessary servicing,
+ repair, or correction. This disclaimer of warranty constitutes an essential
+ part of this License. No use of any Covered Software is authorized under
+ this License except under this disclaimer.
+
+7. Limitation of Liability
+
+ Under no circumstances and under no legal theory, whether tort (including
+ negligence), contract, or otherwise, shall any Contributor, or anyone who
+ distributes Covered Software as permitted above, be liable to You for any
+ direct, indirect, special, incidental, or consequential damages of any
+ character including, without limitation, damages for lost profits, loss of
+ goodwill, work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses, even if such party shall have been
+ informed of the possibility of such damages. This limitation of liability
+ shall not apply to liability for death or personal injury resulting from
+ such party's negligence to the extent applicable law prohibits such
+ limitation. Some jurisdictions do not allow the exclusion or limitation of
+ incidental or consequential damages, so this exclusion and limitation may
+ not apply to You.
+
+8. Litigation
+
+ Any litigation relating to this License may be brought only in the courts
+ of a jurisdiction where the defendant maintains its principal place of
+ business and such litigation shall be governed by laws of that
+ jurisdiction, without reference to its conflict-of-law provisions. Nothing
+ in this Section shall prevent a party's ability to bring cross-claims or
+ counter-claims.
+
+9. Miscellaneous
+
+ This License represents the complete agreement concerning the subject
+ matter hereof. If any provision of this License is held to be
+ unenforceable, such provision shall be reformed only to the extent
+ necessary to make it enforceable. Any law or regulation which provides that
+ the language of a contract shall be construed against the drafter shall not
+ be used to construe this License against a Contributor.
+
+
+10. Versions of the License
+
+10.1. New Versions
+
+ Mozilla Foundation is the license steward. Except as provided in Section
+ 10.3, no one other than the license steward has the right to modify or
+ publish new versions of this License. Each version will be given a
+ distinguishing version number.
+
+10.2. Effect of New Versions
+
+ You may distribute the Covered Software under the terms of the version
+ of the License under which You originally received the Covered Software,
+ or under the terms of any subsequent version published by the license
+ steward.
+
+10.3. Modified Versions
+
+ If you create software not governed by this License, and you want to
+ create a new license for such software, you may create and use a
+ modified version of this License if you rename the license and remove
+ any references to the name of the license steward (except to note that
+ such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+ Licenses If You choose to distribute Source Code Form that is
+ Incompatible With Secondary Licenses under the terms of this version of
+ the License, the notice described in Exhibit B of this License must be
+ attached.
+
+Exhibit A - Source Code Form License Notice
+
+ This Source Code Form is subject to the
+ terms of the Mozilla Public License, v.
+ 2.0. If a copy of the MPL was not
+ distributed with this file, You can
+ obtain one at
+ http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular file,
+then You may include the notice in a location (such as a LICENSE file in a
+relevant directory) where a recipient would be likely to look for such a
+notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+
+ This Source Code Form is "Incompatible
+ With Secondary Licenses", as defined by
+ the Mozilla Public License, v. 2.0.
+
--- /dev/null
+go-immutable-radix [](https://travis-ci.org/hashicorp/go-immutable-radix)
+=========
+
+Provides the `iradix` package that implements an immutable [radix tree](http://en.wikipedia.org/wiki/Radix_tree).
+The package only provides a single `Tree` implementation, optimized for sparse nodes.
+
+As a radix tree, it provides the following:
+ * O(k) operations. In many cases, this can be faster than a hash table since
+ the hash function is an O(k) operation, and hash tables have very poor cache locality.
+ * Minimum / Maximum value lookups
+ * Ordered iteration
+
+A tree supports using a transaction to batch multiple updates (insert, delete)
+in a more efficient manner than performing each operation one at a time.
+
+For a mutable variant, see [go-radix](https://github.com/armon/go-radix).
+
+Documentation
+=============
+
+The full documentation is available on [Godoc](http://godoc.org/github.com/hashicorp/go-immutable-radix).
+
+Example
+=======
+
+Below is a simple example of usage
+
+```go
+// Create a tree
+r := iradix.New()
+r, _, _ = r.Insert([]byte("foo"), 1)
+r, _, _ = r.Insert([]byte("bar"), 2)
+r, _, _ = r.Insert([]byte("foobar"), 2)
+
+// Find the longest prefix match
+m, _, _ := r.Root().LongestPrefix([]byte("foozip"))
+if string(m) != "foo" {
+ panic("should be foo")
+}
+```
+
--- /dev/null
+package iradix
+
+import "sort"
+
+type edges []edge
+
+func (e edges) Len() int {
+ return len(e)
+}
+
+func (e edges) Less(i, j int) bool {
+ return e[i].label < e[j].label
+}
+
+func (e edges) Swap(i, j int) {
+ e[i], e[j] = e[j], e[i]
+}
+
+func (e edges) Sort() {
+ sort.Sort(e)
+}
--- /dev/null
+package iradix
+
+import (
+ "bytes"
+ "strings"
+
+ "github.com/hashicorp/golang-lru/simplelru"
+)
+
+const (
+ // defaultModifiedCache is the default size of the modified node
+ // cache used per transaction. This is used to cache the updates
+ // to the nodes near the root, while the leaves do not need to be
+ // cached. This is important for very large transactions to prevent
+ // the modified cache from growing to be enormous. This is also used
+ // to set the max size of the mutation notify maps since those should
+ // also be bounded in a similar way.
+ defaultModifiedCache = 8192
+)
+
+// Tree implements an immutable radix tree. This can be treated as a
+// Dictionary abstract data type. The main advantage over a standard
+// hash map is prefix-based lookups and ordered iteration. The immutability
+// means that it is safe to concurrently read from a Tree without any
+// coordination.
+type Tree struct {
+ root *Node
+ size int
+}
+
+// New returns an empty Tree
+func New() *Tree {
+ t := &Tree{
+ root: &Node{
+ mutateCh: make(chan struct{}),
+ },
+ }
+ return t
+}
+
+// Len is used to return the number of elements in the tree
+func (t *Tree) Len() int {
+ return t.size
+}
+
+// Txn is a transaction on the tree. This transaction is applied
+// atomically and returns a new tree when committed. A transaction
+// is not thread safe, and should only be used by a single goroutine.
+type Txn struct {
+ // root is the modified root for the transaction.
+ root *Node
+
+ // snap is a snapshot of the root node for use if we have to run the
+ // slow notify algorithm.
+ snap *Node
+
+ // size tracks the size of the tree as it is modified during the
+ // transaction.
+ size int
+
+ // writable is a cache of writable nodes that have been created during
+ // the course of the transaction. This allows us to re-use the same
+ // nodes for further writes and avoid unnecessary copies of nodes that
+ // have never been exposed outside the transaction. This will only hold
+ // up to defaultModifiedCache number of entries.
+ writable *simplelru.LRU
+
+ // trackChannels is used to hold channels that need to be notified to
+ // signal mutation of the tree. This will only hold up to
+ // defaultModifiedCache number of entries, after which we will set the
+ // trackOverflow flag, which will cause us to use a more expensive
+ // algorithm to perform the notifications. Mutation tracking is only
+ // performed if trackMutate is true.
+ trackChannels map[chan struct{}]struct{}
+ trackOverflow bool
+ trackMutate bool
+}
+
+// Txn starts a new transaction that can be used to mutate the tree
+func (t *Tree) Txn() *Txn {
+ txn := &Txn{
+ root: t.root,
+ snap: t.root,
+ size: t.size,
+ }
+ return txn
+}
+
+// TrackMutate can be used to toggle if mutations are tracked. If this is enabled
+// then notifications will be issued for affected internal nodes and leaves when
+// the transaction is committed.
+func (t *Txn) TrackMutate(track bool) {
+ t.trackMutate = track
+}
+
+// trackChannel safely attempts to track the given mutation channel, setting the
+// overflow flag if we can no longer track any more. This limits the amount of
+// state that will accumulate during a transaction and we have a slower algorithm
+// to switch to if we overflow.
+func (t *Txn) trackChannel(ch chan struct{}) {
+ // In overflow, make sure we don't store any more objects.
+ if t.trackOverflow {
+ return
+ }
+
+ // If this would overflow the state we reject it and set the flag (since
+ // we aren't tracking everything that's required any longer).
+ if len(t.trackChannels) >= defaultModifiedCache {
+ // Mark that we are in the overflow state
+ t.trackOverflow = true
+
+ // Clear the map so that the channels can be garbage collected. It is
+ // safe to do this since we have already overflowed and will be using
+ // the slow notify algorithm.
+ t.trackChannels = nil
+ return
+ }
+
+ // Create the map on the fly when we need it.
+ if t.trackChannels == nil {
+ t.trackChannels = make(map[chan struct{}]struct{})
+ }
+
+ // Otherwise we are good to track it.
+ t.trackChannels[ch] = struct{}{}
+}
+
+// writeNode returns a node to be modified, if the current node has already been
+// modified during the course of the transaction, it is used in-place. Set
+// forLeafUpdate to true if you are getting a write node to update the leaf,
+// which will set leaf mutation tracking appropriately as well.
+func (t *Txn) writeNode(n *Node, forLeafUpdate bool) *Node {
+ // Ensure the writable set exists.
+ if t.writable == nil {
+ lru, err := simplelru.NewLRU(defaultModifiedCache, nil)
+ if err != nil {
+ panic(err)
+ }
+ t.writable = lru
+ }
+
+ // If this node has already been modified, we can continue to use it
+ // during this transaction. We know that we don't need to track it for
+ // a node update since the node is writable, but if this is for a leaf
+ // update we track it, in case the initial write to this node didn't
+ // update the leaf.
+ if _, ok := t.writable.Get(n); ok {
+ if t.trackMutate && forLeafUpdate && n.leaf != nil {
+ t.trackChannel(n.leaf.mutateCh)
+ }
+ return n
+ }
+
+ // Mark this node as being mutated.
+ if t.trackMutate {
+ t.trackChannel(n.mutateCh)
+ }
+
+ // Mark its leaf as being mutated, if appropriate.
+ if t.trackMutate && forLeafUpdate && n.leaf != nil {
+ t.trackChannel(n.leaf.mutateCh)
+ }
+
+ // Copy the existing node. If you have set forLeafUpdate it will be
+ // safe to replace this leaf with another after you get your node for
+ // writing. You MUST replace it, because the channel associated with
+ // this leaf will be closed when this transaction is committed.
+ nc := &Node{
+ mutateCh: make(chan struct{}),
+ leaf: n.leaf,
+ }
+ if n.prefix != nil {
+ nc.prefix = make([]byte, len(n.prefix))
+ copy(nc.prefix, n.prefix)
+ }
+ if len(n.edges) != 0 {
+ nc.edges = make([]edge, len(n.edges))
+ copy(nc.edges, n.edges)
+ }
+
+ // Mark this node as writable.
+ t.writable.Add(nc, nil)
+ return nc
+}
+
+// Visit all the nodes in the tree under n, and add their mutateChannels to the transaction
+// Returns the size of the subtree visited
+func (t *Txn) trackChannelsAndCount(n *Node) int {
+ // Count only leaf nodes
+ leaves := 0
+ if n.leaf != nil {
+ leaves = 1
+ }
+ // Mark this node as being mutated.
+ if t.trackMutate {
+ t.trackChannel(n.mutateCh)
+ }
+
+ // Mark its leaf as being mutated, if appropriate.
+ if t.trackMutate && n.leaf != nil {
+ t.trackChannel(n.leaf.mutateCh)
+ }
+
+ // Recurse on the children
+ for _, e := range n.edges {
+ leaves += t.trackChannelsAndCount(e.node)
+ }
+ return leaves
+}
+
+// mergeChild is called to collapse the given node with its child. This is only
+// called when the given node is not a leaf and has a single edge.
+func (t *Txn) mergeChild(n *Node) {
+ // Mark the child node as being mutated since we are about to abandon
+ // it. We don't need to mark the leaf since we are retaining it if it
+ // is there.
+ e := n.edges[0]
+ child := e.node
+ if t.trackMutate {
+ t.trackChannel(child.mutateCh)
+ }
+
+ // Merge the nodes.
+ n.prefix = concat(n.prefix, child.prefix)
+ n.leaf = child.leaf
+ if len(child.edges) != 0 {
+ n.edges = make([]edge, len(child.edges))
+ copy(n.edges, child.edges)
+ } else {
+ n.edges = nil
+ }
+}
+
+// insert does a recursive insertion
+func (t *Txn) insert(n *Node, k, search []byte, v interface{}) (*Node, interface{}, bool) {
+ // Handle key exhaustion
+ if len(search) == 0 {
+ var oldVal interface{}
+ didUpdate := false
+ if n.isLeaf() {
+ oldVal = n.leaf.val
+ didUpdate = true
+ }
+
+ nc := t.writeNode(n, true)
+ nc.leaf = &leafNode{
+ mutateCh: make(chan struct{}),
+ key: k,
+ val: v,
+ }
+ return nc, oldVal, didUpdate
+ }
+
+ // Look for the edge
+ idx, child := n.getEdge(search[0])
+
+ // No edge, create one
+ if child == nil {
+ e := edge{
+ label: search[0],
+ node: &Node{
+ mutateCh: make(chan struct{}),
+ leaf: &leafNode{
+ mutateCh: make(chan struct{}),
+ key: k,
+ val: v,
+ },
+ prefix: search,
+ },
+ }
+ nc := t.writeNode(n, false)
+ nc.addEdge(e)
+ return nc, nil, false
+ }
+
+ // Determine longest prefix of the search key on match
+ commonPrefix := longestPrefix(search, child.prefix)
+ if commonPrefix == len(child.prefix) {
+ search = search[commonPrefix:]
+ newChild, oldVal, didUpdate := t.insert(child, k, search, v)
+ if newChild != nil {
+ nc := t.writeNode(n, false)
+ nc.edges[idx].node = newChild
+ return nc, oldVal, didUpdate
+ }
+ return nil, oldVal, didUpdate
+ }
+
+ // Split the node
+ nc := t.writeNode(n, false)
+ splitNode := &Node{
+ mutateCh: make(chan struct{}),
+ prefix: search[:commonPrefix],
+ }
+ nc.replaceEdge(edge{
+ label: search[0],
+ node: splitNode,
+ })
+
+ // Restore the existing child node
+ modChild := t.writeNode(child, false)
+ splitNode.addEdge(edge{
+ label: modChild.prefix[commonPrefix],
+ node: modChild,
+ })
+ modChild.prefix = modChild.prefix[commonPrefix:]
+
+ // Create a new leaf node
+ leaf := &leafNode{
+ mutateCh: make(chan struct{}),
+ key: k,
+ val: v,
+ }
+
+ // If the new key is a subset, add to to this node
+ search = search[commonPrefix:]
+ if len(search) == 0 {
+ splitNode.leaf = leaf
+ return nc, nil, false
+ }
+
+ // Create a new edge for the node
+ splitNode.addEdge(edge{
+ label: search[0],
+ node: &Node{
+ mutateCh: make(chan struct{}),
+ leaf: leaf,
+ prefix: search,
+ },
+ })
+ return nc, nil, false
+}
+
+// delete does a recursive deletion
+func (t *Txn) delete(parent, n *Node, search []byte) (*Node, *leafNode) {
+ // Check for key exhaustion
+ if len(search) == 0 {
+ if !n.isLeaf() {
+ return nil, nil
+ }
+
+ // Remove the leaf node
+ nc := t.writeNode(n, true)
+ nc.leaf = nil
+
+ // Check if this node should be merged
+ if n != t.root && len(nc.edges) == 1 {
+ t.mergeChild(nc)
+ }
+ return nc, n.leaf
+ }
+
+ // Look for an edge
+ label := search[0]
+ idx, child := n.getEdge(label)
+ if child == nil || !bytes.HasPrefix(search, child.prefix) {
+ return nil, nil
+ }
+
+ // Consume the search prefix
+ search = search[len(child.prefix):]
+ newChild, leaf := t.delete(n, child, search)
+ if newChild == nil {
+ return nil, nil
+ }
+
+ // Copy this node. WATCH OUT - it's safe to pass "false" here because we
+ // will only ADD a leaf via nc.mergeChild() if there isn't one due to
+ // the !nc.isLeaf() check in the logic just below. This is pretty subtle,
+ // so be careful if you change any of the logic here.
+ nc := t.writeNode(n, false)
+
+ // Delete the edge if the node has no edges
+ if newChild.leaf == nil && len(newChild.edges) == 0 {
+ nc.delEdge(label)
+ if n != t.root && len(nc.edges) == 1 && !nc.isLeaf() {
+ t.mergeChild(nc)
+ }
+ } else {
+ nc.edges[idx].node = newChild
+ }
+ return nc, leaf
+}
+
+// delete does a recursive deletion
+func (t *Txn) deletePrefix(parent, n *Node, search []byte) (*Node, int) {
+ // Check for key exhaustion
+ if len(search) == 0 {
+ nc := t.writeNode(n, true)
+ if n.isLeaf() {
+ nc.leaf = nil
+ }
+ nc.edges = nil
+ return nc, t.trackChannelsAndCount(n)
+ }
+
+ // Look for an edge
+ label := search[0]
+ idx, child := n.getEdge(label)
+ // We make sure that either the child node's prefix starts with the search term, or the search term starts with the child node's prefix
+ // Need to do both so that we can delete prefixes that don't correspond to any node in the tree
+ if child == nil || (!bytes.HasPrefix(child.prefix, search) && !bytes.HasPrefix(search, child.prefix)) {
+ return nil, 0
+ }
+
+ // Consume the search prefix
+ if len(child.prefix) > len(search) {
+ search = []byte("")
+ } else {
+ search = search[len(child.prefix):]
+ }
+ newChild, numDeletions := t.deletePrefix(n, child, search)
+ if newChild == nil {
+ return nil, 0
+ }
+ // Copy this node. WATCH OUT - it's safe to pass "false" here because we
+ // will only ADD a leaf via nc.mergeChild() if there isn't one due to
+ // the !nc.isLeaf() check in the logic just below. This is pretty subtle,
+ // so be careful if you change any of the logic here.
+
+ nc := t.writeNode(n, false)
+
+ // Delete the edge if the node has no edges
+ if newChild.leaf == nil && len(newChild.edges) == 0 {
+ nc.delEdge(label)
+ if n != t.root && len(nc.edges) == 1 && !nc.isLeaf() {
+ t.mergeChild(nc)
+ }
+ } else {
+ nc.edges[idx].node = newChild
+ }
+ return nc, numDeletions
+}
+
+// Insert is used to add or update a given key. The return provides
+// the previous value and a bool indicating if any was set.
+func (t *Txn) Insert(k []byte, v interface{}) (interface{}, bool) {
+ newRoot, oldVal, didUpdate := t.insert(t.root, k, k, v)
+ if newRoot != nil {
+ t.root = newRoot
+ }
+ if !didUpdate {
+ t.size++
+ }
+ return oldVal, didUpdate
+}
+
+// Delete is used to delete a given key. Returns the old value if any,
+// and a bool indicating if the key was set.
+func (t *Txn) Delete(k []byte) (interface{}, bool) {
+ newRoot, leaf := t.delete(nil, t.root, k)
+ if newRoot != nil {
+ t.root = newRoot
+ }
+ if leaf != nil {
+ t.size--
+ return leaf.val, true
+ }
+ return nil, false
+}
+
+// DeletePrefix is used to delete an entire subtree that matches the prefix
+// This will delete all nodes under that prefix
+func (t *Txn) DeletePrefix(prefix []byte) bool {
+ newRoot, numDeletions := t.deletePrefix(nil, t.root, prefix)
+ if newRoot != nil {
+ t.root = newRoot
+ t.size = t.size - numDeletions
+ return true
+ }
+ return false
+
+}
+
+// Root returns the current root of the radix tree within this
+// transaction. The root is not safe across insert and delete operations,
+// but can be used to read the current state during a transaction.
+func (t *Txn) Root() *Node {
+ return t.root
+}
+
+// Get is used to lookup a specific key, returning
+// the value and if it was found
+func (t *Txn) Get(k []byte) (interface{}, bool) {
+ return t.root.Get(k)
+}
+
+// GetWatch is used to lookup a specific key, returning
+// the watch channel, value and if it was found
+func (t *Txn) GetWatch(k []byte) (<-chan struct{}, interface{}, bool) {
+ return t.root.GetWatch(k)
+}
+
+// Commit is used to finalize the transaction and return a new tree. If mutation
+// tracking is turned on then notifications will also be issued.
+func (t *Txn) Commit() *Tree {
+ nt := t.CommitOnly()
+ if t.trackMutate {
+ t.Notify()
+ }
+ return nt
+}
+
+// CommitOnly is used to finalize the transaction and return a new tree, but
+// does not issue any notifications until Notify is called.
+func (t *Txn) CommitOnly() *Tree {
+ nt := &Tree{t.root, t.size}
+ t.writable = nil
+ return nt
+}
+
+// slowNotify does a complete comparison of the before and after trees in order
+// to trigger notifications. This doesn't require any additional state but it
+// is very expensive to compute.
+func (t *Txn) slowNotify() {
+ snapIter := t.snap.rawIterator()
+ rootIter := t.root.rawIterator()
+ for snapIter.Front() != nil || rootIter.Front() != nil {
+ // If we've exhausted the nodes in the old snapshot, we know
+ // there's nothing remaining to notify.
+ if snapIter.Front() == nil {
+ return
+ }
+ snapElem := snapIter.Front()
+
+ // If we've exhausted the nodes in the new root, we know we need
+ // to invalidate everything that remains in the old snapshot. We
+ // know from the loop condition there's something in the old
+ // snapshot.
+ if rootIter.Front() == nil {
+ close(snapElem.mutateCh)
+ if snapElem.isLeaf() {
+ close(snapElem.leaf.mutateCh)
+ }
+ snapIter.Next()
+ continue
+ }
+
+ // Do one string compare so we can check the various conditions
+ // below without repeating the compare.
+ cmp := strings.Compare(snapIter.Path(), rootIter.Path())
+
+ // If the snapshot is behind the root, then we must have deleted
+ // this node during the transaction.
+ if cmp < 0 {
+ close(snapElem.mutateCh)
+ if snapElem.isLeaf() {
+ close(snapElem.leaf.mutateCh)
+ }
+ snapIter.Next()
+ continue
+ }
+
+ // If the snapshot is ahead of the root, then we must have added
+ // this node during the transaction.
+ if cmp > 0 {
+ rootIter.Next()
+ continue
+ }
+
+ // If we have the same path, then we need to see if we mutated a
+ // node and possibly the leaf.
+ rootElem := rootIter.Front()
+ if snapElem != rootElem {
+ close(snapElem.mutateCh)
+ if snapElem.leaf != nil && (snapElem.leaf != rootElem.leaf) {
+ close(snapElem.leaf.mutateCh)
+ }
+ }
+ snapIter.Next()
+ rootIter.Next()
+ }
+}
+
+// Notify is used along with TrackMutate to trigger notifications. This must
+// only be done once a transaction is committed via CommitOnly, and it is called
+// automatically by Commit.
+func (t *Txn) Notify() {
+ if !t.trackMutate {
+ return
+ }
+
+ // If we've overflowed the tracking state we can't use it in any way and
+ // need to do a full tree compare.
+ if t.trackOverflow {
+ t.slowNotify()
+ } else {
+ for ch := range t.trackChannels {
+ close(ch)
+ }
+ }
+
+ // Clean up the tracking state so that a re-notify is safe (will trigger
+ // the else clause above which will be a no-op).
+ t.trackChannels = nil
+ t.trackOverflow = false
+}
+
+// Insert is used to add or update a given key. The return provides
+// the new tree, previous value and a bool indicating if any was set.
+func (t *Tree) Insert(k []byte, v interface{}) (*Tree, interface{}, bool) {
+ txn := t.Txn()
+ old, ok := txn.Insert(k, v)
+ return txn.Commit(), old, ok
+}
+
+// Delete is used to delete a given key. Returns the new tree,
+// old value if any, and a bool indicating if the key was set.
+func (t *Tree) Delete(k []byte) (*Tree, interface{}, bool) {
+ txn := t.Txn()
+ old, ok := txn.Delete(k)
+ return txn.Commit(), old, ok
+}
+
+// DeletePrefix is used to delete all nodes starting with a given prefix. Returns the new tree,
+// and a bool indicating if the prefix matched any nodes
+func (t *Tree) DeletePrefix(k []byte) (*Tree, bool) {
+ txn := t.Txn()
+ ok := txn.DeletePrefix(k)
+ return txn.Commit(), ok
+}
+
+// Root returns the root node of the tree which can be used for richer
+// query operations.
+func (t *Tree) Root() *Node {
+ return t.root
+}
+
+// Get is used to lookup a specific key, returning
+// the value and if it was found
+func (t *Tree) Get(k []byte) (interface{}, bool) {
+ return t.root.Get(k)
+}
+
+// longestPrefix finds the length of the shared prefix
+// of two strings
+func longestPrefix(k1, k2 []byte) int {
+ max := len(k1)
+ if l := len(k2); l < max {
+ max = l
+ }
+ var i int
+ for i = 0; i < max; i++ {
+ if k1[i] != k2[i] {
+ break
+ }
+ }
+ return i
+}
+
+// concat two byte slices, returning a third new copy
+func concat(a, b []byte) []byte {
+ c := make([]byte, len(a)+len(b))
+ copy(c, a)
+ copy(c[len(a):], b)
+ return c
+}
--- /dev/null
+package iradix
+
+import "bytes"
+
+// Iterator is used to iterate over a set of nodes
+// in pre-order
+type Iterator struct {
+ node *Node
+ stack []edges
+}
+
+// SeekPrefixWatch is used to seek the iterator to a given prefix
+// and returns the watch channel of the finest granularity
+func (i *Iterator) SeekPrefixWatch(prefix []byte) (watch <-chan struct{}) {
+ // Wipe the stack
+ i.stack = nil
+ n := i.node
+ watch = n.mutateCh
+ search := prefix
+ for {
+ // Check for key exhaution
+ if len(search) == 0 {
+ i.node = n
+ return
+ }
+
+ // Look for an edge
+ _, n = n.getEdge(search[0])
+ if n == nil {
+ i.node = nil
+ return
+ }
+
+ // Update to the finest granularity as the search makes progress
+ watch = n.mutateCh
+
+ // Consume the search prefix
+ if bytes.HasPrefix(search, n.prefix) {
+ search = search[len(n.prefix):]
+
+ } else if bytes.HasPrefix(n.prefix, search) {
+ i.node = n
+ return
+ } else {
+ i.node = nil
+ return
+ }
+ }
+}
+
+// SeekPrefix is used to seek the iterator to a given prefix
+func (i *Iterator) SeekPrefix(prefix []byte) {
+ i.SeekPrefixWatch(prefix)
+}
+
+// Next returns the next node in order
+func (i *Iterator) Next() ([]byte, interface{}, bool) {
+ // Initialize our stack if needed
+ if i.stack == nil && i.node != nil {
+ i.stack = []edges{
+ edges{
+ edge{node: i.node},
+ },
+ }
+ }
+
+ for len(i.stack) > 0 {
+ // Inspect the last element of the stack
+ n := len(i.stack)
+ last := i.stack[n-1]
+ elem := last[0].node
+
+ // Update the stack
+ if len(last) > 1 {
+ i.stack[n-1] = last[1:]
+ } else {
+ i.stack = i.stack[:n-1]
+ }
+
+ // Push the edges onto the frontier
+ if len(elem.edges) > 0 {
+ i.stack = append(i.stack, elem.edges)
+ }
+
+ // Return the leaf values if any
+ if elem.leaf != nil {
+ return elem.leaf.key, elem.leaf.val, true
+ }
+ }
+ return nil, nil, false
+}
--- /dev/null
+package iradix
+
+import (
+ "bytes"
+ "sort"
+)
+
+// WalkFn is used when walking the tree. Takes a
+// key and value, returning if iteration should
+// be terminated.
+type WalkFn func(k []byte, v interface{}) bool
+
+// leafNode is used to represent a value
+type leafNode struct {
+ mutateCh chan struct{}
+ key []byte
+ val interface{}
+}
+
+// edge is used to represent an edge node
+type edge struct {
+ label byte
+ node *Node
+}
+
+// Node is an immutable node in the radix tree
+type Node struct {
+ // mutateCh is closed if this node is modified
+ mutateCh chan struct{}
+
+ // leaf is used to store possible leaf
+ leaf *leafNode
+
+ // prefix is the common prefix we ignore
+ prefix []byte
+
+ // Edges should be stored in-order for iteration.
+ // We avoid a fully materialized slice to save memory,
+ // since in most cases we expect to be sparse
+ edges edges
+}
+
+func (n *Node) isLeaf() bool {
+ return n.leaf != nil
+}
+
+func (n *Node) addEdge(e edge) {
+ num := len(n.edges)
+ idx := sort.Search(num, func(i int) bool {
+ return n.edges[i].label >= e.label
+ })
+ n.edges = append(n.edges, e)
+ if idx != num {
+ copy(n.edges[idx+1:], n.edges[idx:num])
+ n.edges[idx] = e
+ }
+}
+
+func (n *Node) replaceEdge(e edge) {
+ num := len(n.edges)
+ idx := sort.Search(num, func(i int) bool {
+ return n.edges[i].label >= e.label
+ })
+ if idx < num && n.edges[idx].label == e.label {
+ n.edges[idx].node = e.node
+ return
+ }
+ panic("replacing missing edge")
+}
+
+func (n *Node) getEdge(label byte) (int, *Node) {
+ num := len(n.edges)
+ idx := sort.Search(num, func(i int) bool {
+ return n.edges[i].label >= label
+ })
+ if idx < num && n.edges[idx].label == label {
+ return idx, n.edges[idx].node
+ }
+ return -1, nil
+}
+
+func (n *Node) delEdge(label byte) {
+ num := len(n.edges)
+ idx := sort.Search(num, func(i int) bool {
+ return n.edges[i].label >= label
+ })
+ if idx < num && n.edges[idx].label == label {
+ copy(n.edges[idx:], n.edges[idx+1:])
+ n.edges[len(n.edges)-1] = edge{}
+ n.edges = n.edges[:len(n.edges)-1]
+ }
+}
+
+func (n *Node) GetWatch(k []byte) (<-chan struct{}, interface{}, bool) {
+ search := k
+ watch := n.mutateCh
+ for {
+ // Check for key exhaustion
+ if len(search) == 0 {
+ if n.isLeaf() {
+ return n.leaf.mutateCh, n.leaf.val, true
+ }
+ break
+ }
+
+ // Look for an edge
+ _, n = n.getEdge(search[0])
+ if n == nil {
+ break
+ }
+
+ // Update to the finest granularity as the search makes progress
+ watch = n.mutateCh
+
+ // Consume the search prefix
+ if bytes.HasPrefix(search, n.prefix) {
+ search = search[len(n.prefix):]
+ } else {
+ break
+ }
+ }
+ return watch, nil, false
+}
+
+func (n *Node) Get(k []byte) (interface{}, bool) {
+ _, val, ok := n.GetWatch(k)
+ return val, ok
+}
+
+// LongestPrefix is like Get, but instead of an
+// exact match, it will return the longest prefix match.
+func (n *Node) LongestPrefix(k []byte) ([]byte, interface{}, bool) {
+ var last *leafNode
+ search := k
+ for {
+ // Look for a leaf node
+ if n.isLeaf() {
+ last = n.leaf
+ }
+
+ // Check for key exhaution
+ if len(search) == 0 {
+ break
+ }
+
+ // Look for an edge
+ _, n = n.getEdge(search[0])
+ if n == nil {
+ break
+ }
+
+ // Consume the search prefix
+ if bytes.HasPrefix(search, n.prefix) {
+ search = search[len(n.prefix):]
+ } else {
+ break
+ }
+ }
+ if last != nil {
+ return last.key, last.val, true
+ }
+ return nil, nil, false
+}
+
+// Minimum is used to return the minimum value in the tree
+func (n *Node) Minimum() ([]byte, interface{}, bool) {
+ for {
+ if n.isLeaf() {
+ return n.leaf.key, n.leaf.val, true
+ }
+ if len(n.edges) > 0 {
+ n = n.edges[0].node
+ } else {
+ break
+ }
+ }
+ return nil, nil, false
+}
+
+// Maximum is used to return the maximum value in the tree
+func (n *Node) Maximum() ([]byte, interface{}, bool) {
+ for {
+ if num := len(n.edges); num > 0 {
+ n = n.edges[num-1].node
+ continue
+ }
+ if n.isLeaf() {
+ return n.leaf.key, n.leaf.val, true
+ } else {
+ break
+ }
+ }
+ return nil, nil, false
+}
+
+// Iterator is used to return an iterator at
+// the given node to walk the tree
+func (n *Node) Iterator() *Iterator {
+ return &Iterator{node: n}
+}
+
+// rawIterator is used to return a raw iterator at the given node to walk the
+// tree.
+func (n *Node) rawIterator() *rawIterator {
+ iter := &rawIterator{node: n}
+ iter.Next()
+ return iter
+}
+
+// Walk is used to walk the tree
+func (n *Node) Walk(fn WalkFn) {
+ recursiveWalk(n, fn)
+}
+
+// WalkPrefix is used to walk the tree under a prefix
+func (n *Node) WalkPrefix(prefix []byte, fn WalkFn) {
+ search := prefix
+ for {
+ // Check for key exhaution
+ if len(search) == 0 {
+ recursiveWalk(n, fn)
+ return
+ }
+
+ // Look for an edge
+ _, n = n.getEdge(search[0])
+ if n == nil {
+ break
+ }
+
+ // Consume the search prefix
+ if bytes.HasPrefix(search, n.prefix) {
+ search = search[len(n.prefix):]
+
+ } else if bytes.HasPrefix(n.prefix, search) {
+ // Child may be under our search prefix
+ recursiveWalk(n, fn)
+ return
+ } else {
+ break
+ }
+ }
+}
+
+// WalkPath is used to walk the tree, but only visiting nodes
+// from the root down to a given leaf. Where WalkPrefix walks
+// all the entries *under* the given prefix, this walks the
+// entries *above* the given prefix.
+func (n *Node) WalkPath(path []byte, fn WalkFn) {
+ search := path
+ for {
+ // Visit the leaf values if any
+ if n.leaf != nil && fn(n.leaf.key, n.leaf.val) {
+ return
+ }
+
+ // Check for key exhaution
+ if len(search) == 0 {
+ return
+ }
+
+ // Look for an edge
+ _, n = n.getEdge(search[0])
+ if n == nil {
+ return
+ }
+
+ // Consume the search prefix
+ if bytes.HasPrefix(search, n.prefix) {
+ search = search[len(n.prefix):]
+ } else {
+ break
+ }
+ }
+}
+
+// recursiveWalk is used to do a pre-order walk of a node
+// recursively. Returns true if the walk should be aborted
+func recursiveWalk(n *Node, fn WalkFn) bool {
+ // Visit the leaf values if any
+ if n.leaf != nil && fn(n.leaf.key, n.leaf.val) {
+ return true
+ }
+
+ // Recurse on the children
+ for _, e := range n.edges {
+ if recursiveWalk(e.node, fn) {
+ return true
+ }
+ }
+ return false
+}
--- /dev/null
+package iradix
+
+// rawIterator visits each of the nodes in the tree, even the ones that are not
+// leaves. It keeps track of the effective path (what a leaf at a given node
+// would be called), which is useful for comparing trees.
+type rawIterator struct {
+ // node is the starting node in the tree for the iterator.
+ node *Node
+
+ // stack keeps track of edges in the frontier.
+ stack []rawStackEntry
+
+ // pos is the current position of the iterator.
+ pos *Node
+
+ // path is the effective path of the current iterator position,
+ // regardless of whether the current node is a leaf.
+ path string
+}
+
+// rawStackEntry is used to keep track of the cumulative common path as well as
+// its associated edges in the frontier.
+type rawStackEntry struct {
+ path string
+ edges edges
+}
+
+// Front returns the current node that has been iterated to.
+func (i *rawIterator) Front() *Node {
+ return i.pos
+}
+
+// Path returns the effective path of the current node, even if it's not actually
+// a leaf.
+func (i *rawIterator) Path() string {
+ return i.path
+}
+
+// Next advances the iterator to the next node.
+func (i *rawIterator) Next() {
+ // Initialize our stack if needed.
+ if i.stack == nil && i.node != nil {
+ i.stack = []rawStackEntry{
+ rawStackEntry{
+ edges: edges{
+ edge{node: i.node},
+ },
+ },
+ }
+ }
+
+ for len(i.stack) > 0 {
+ // Inspect the last element of the stack.
+ n := len(i.stack)
+ last := i.stack[n-1]
+ elem := last.edges[0].node
+
+ // Update the stack.
+ if len(last.edges) > 1 {
+ i.stack[n-1].edges = last.edges[1:]
+ } else {
+ i.stack = i.stack[:n-1]
+ }
+
+ // Push the edges onto the frontier.
+ if len(elem.edges) > 0 {
+ path := last.path + string(elem.prefix)
+ i.stack = append(i.stack, rawStackEntry{path, elem.edges})
+ }
+
+ i.pos = elem
+ i.path = last.path + string(elem.prefix)
+ return
+ }
+
+ i.pos = nil
+ i.path = ""
+}
--- /dev/null
+Copyright (c) 2012, 2013 Ugorji Nwoke.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+* Neither the name of the author nor the names of its contributors may be used
+ to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- /dev/null
+// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a BSD-style license found in the LICENSE file.
+
+/*
+High Performance, Feature-Rich Idiomatic Go encoding library for msgpack and binc .
+
+Supported Serialization formats are:
+
+ - msgpack: [https://github.com/msgpack/msgpack]
+ - binc: [http://github.com/ugorji/binc]
+
+To install:
+
+ go get github.com/ugorji/go/codec
+
+The idiomatic Go support is as seen in other encoding packages in
+the standard library (ie json, xml, gob, etc).
+
+Rich Feature Set includes:
+
+ - Simple but extremely powerful and feature-rich API
+ - Very High Performance.
+ Our extensive benchmarks show us outperforming Gob, Json and Bson by 2-4X.
+ This was achieved by taking extreme care on:
+ - managing allocation
+ - function frame size (important due to Go's use of split stacks),
+ - reflection use (and by-passing reflection for common types)
+ - recursion implications
+ - zero-copy mode (encoding/decoding to byte slice without using temp buffers)
+ - Correct.
+ Care was taken to precisely handle corner cases like:
+ overflows, nil maps and slices, nil value in stream, etc.
+ - Efficient zero-copying into temporary byte buffers
+ when encoding into or decoding from a byte slice.
+ - Standard field renaming via tags
+ - Encoding from any value
+ (struct, slice, map, primitives, pointers, interface{}, etc)
+ - Decoding into pointer to any non-nil typed value
+ (struct, slice, map, int, float32, bool, string, reflect.Value, etc)
+ - Supports extension functions to handle the encode/decode of custom types
+ - Support Go 1.2 encoding.BinaryMarshaler/BinaryUnmarshaler
+ - Schema-less decoding
+ (decode into a pointer to a nil interface{} as opposed to a typed non-nil value).
+ Includes Options to configure what specific map or slice type to use
+ when decoding an encoded list or map into a nil interface{}
+ - Provides a RPC Server and Client Codec for net/rpc communication protocol.
+ - Msgpack Specific:
+ - Provides extension functions to handle spec-defined extensions (binary, timestamp)
+ - Options to resolve ambiguities in handling raw bytes (as string or []byte)
+ during schema-less decoding (decoding into a nil interface{})
+ - RPC Server/Client Codec for msgpack-rpc protocol defined at:
+ https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md
+ - Fast Paths for some container types:
+ For some container types, we circumvent reflection and its associated overhead
+ and allocation costs, and encode/decode directly. These types are:
+ []interface{}
+ []int
+ []string
+ map[interface{}]interface{}
+ map[int]interface{}
+ map[string]interface{}
+
+Extension Support
+
+Users can register a function to handle the encoding or decoding of
+their custom types.
+
+There are no restrictions on what the custom type can be. Some examples:
+
+ type BisSet []int
+ type BitSet64 uint64
+ type UUID string
+ type MyStructWithUnexportedFields struct { a int; b bool; c []int; }
+ type GifImage struct { ... }
+
+As an illustration, MyStructWithUnexportedFields would normally be
+encoded as an empty map because it has no exported fields, while UUID
+would be encoded as a string. However, with extension support, you can
+encode any of these however you like.
+
+RPC
+
+RPC Client and Server Codecs are implemented, so the codecs can be used
+with the standard net/rpc package.
+
+Usage
+
+Typical usage model:
+
+ // create and configure Handle
+ var (
+ bh codec.BincHandle
+ mh codec.MsgpackHandle
+ )
+
+ mh.MapType = reflect.TypeOf(map[string]interface{}(nil))
+
+ // configure extensions
+ // e.g. for msgpack, define functions and enable Time support for tag 1
+ // mh.AddExt(reflect.TypeOf(time.Time{}), 1, myMsgpackTimeEncodeExtFn, myMsgpackTimeDecodeExtFn)
+
+ // create and use decoder/encoder
+ var (
+ r io.Reader
+ w io.Writer
+ b []byte
+ h = &bh // or mh to use msgpack
+ )
+
+ dec = codec.NewDecoder(r, h)
+ dec = codec.NewDecoderBytes(b, h)
+ err = dec.Decode(&v)
+
+ enc = codec.NewEncoder(w, h)
+ enc = codec.NewEncoderBytes(&b, h)
+ err = enc.Encode(v)
+
+ //RPC Server
+ go func() {
+ for {
+ conn, err := listener.Accept()
+ rpcCodec := codec.GoRpc.ServerCodec(conn, h)
+ //OR rpcCodec := codec.MsgpackSpecRpc.ServerCodec(conn, h)
+ rpc.ServeCodec(rpcCodec)
+ }
+ }()
+
+ //RPC Communication (client side)
+ conn, err = net.Dial("tcp", "localhost:5555")
+ rpcCodec := codec.GoRpc.ClientCodec(conn, h)
+ //OR rpcCodec := codec.MsgpackSpecRpc.ClientCodec(conn, h)
+ client := rpc.NewClientWithCodec(rpcCodec)
+
+Representative Benchmark Results
+
+Run the benchmark suite using:
+ go test -bi -bench=. -benchmem
+
+To run full benchmark suite (including against vmsgpack and bson),
+see notes in ext_dep_test.go
+
+*/
+package codec
--- /dev/null
+# Codec
+
+High Performance and Feature-Rich Idiomatic Go Library providing
+encode/decode support for different serialization formats.
+
+Supported Serialization formats are:
+
+ - msgpack: [https://github.com/msgpack/msgpack]
+ - binc: [http://github.com/ugorji/binc]
+
+To install:
+
+ go get github.com/ugorji/go/codec
+
+Online documentation: [http://godoc.org/github.com/ugorji/go/codec]
+
+The idiomatic Go support is as seen in other encoding packages in
+the standard library (ie json, xml, gob, etc).
+
+Rich Feature Set includes:
+
+ - Simple but extremely powerful and feature-rich API
+ - Very High Performance.
+ Our extensive benchmarks show us outperforming Gob, Json and Bson by 2-4X.
+ This was achieved by taking extreme care on:
+ - managing allocation
+ - function frame size (important due to Go's use of split stacks),
+ - reflection use (and by-passing reflection for common types)
+ - recursion implications
+ - zero-copy mode (encoding/decoding to byte slice without using temp buffers)
+ - Correct.
+ Care was taken to precisely handle corner cases like:
+ overflows, nil maps and slices, nil value in stream, etc.
+ - Efficient zero-copying into temporary byte buffers
+ when encoding into or decoding from a byte slice.
+ - Standard field renaming via tags
+ - Encoding from any value
+ (struct, slice, map, primitives, pointers, interface{}, etc)
+ - Decoding into pointer to any non-nil typed value
+ (struct, slice, map, int, float32, bool, string, reflect.Value, etc)
+ - Supports extension functions to handle the encode/decode of custom types
+ - Support Go 1.2 encoding.BinaryMarshaler/BinaryUnmarshaler
+ - Schema-less decoding
+ (decode into a pointer to a nil interface{} as opposed to a typed non-nil value).
+ Includes Options to configure what specific map or slice type to use
+ when decoding an encoded list or map into a nil interface{}
+ - Provides a RPC Server and Client Codec for net/rpc communication protocol.
+ - Msgpack Specific:
+ - Provides extension functions to handle spec-defined extensions (binary, timestamp)
+ - Options to resolve ambiguities in handling raw bytes (as string or []byte)
+ during schema-less decoding (decoding into a nil interface{})
+ - RPC Server/Client Codec for msgpack-rpc protocol defined at:
+ https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md
+ - Fast Paths for some container types:
+ For some container types, we circumvent reflection and its associated overhead
+ and allocation costs, and encode/decode directly. These types are:
+ []interface{}
+ []int
+ []string
+ map[interface{}]interface{}
+ map[int]interface{}
+ map[string]interface{}
+
+## Extension Support
+
+Users can register a function to handle the encoding or decoding of
+their custom types.
+
+There are no restrictions on what the custom type can be. Some examples:
+
+ type BisSet []int
+ type BitSet64 uint64
+ type UUID string
+ type MyStructWithUnexportedFields struct { a int; b bool; c []int; }
+ type GifImage struct { ... }
+
+As an illustration, MyStructWithUnexportedFields would normally be
+encoded as an empty map because it has no exported fields, while UUID
+would be encoded as a string. However, with extension support, you can
+encode any of these however you like.
+
+## RPC
+
+RPC Client and Server Codecs are implemented, so the codecs can be used
+with the standard net/rpc package.
+
+## Usage
+
+Typical usage model:
+
+ // create and configure Handle
+ var (
+ bh codec.BincHandle
+ mh codec.MsgpackHandle
+ )
+
+ mh.MapType = reflect.TypeOf(map[string]interface{}(nil))
+
+ // configure extensions
+ // e.g. for msgpack, define functions and enable Time support for tag 1
+ // mh.AddExt(reflect.TypeOf(time.Time{}), 1, myMsgpackTimeEncodeExtFn, myMsgpackTimeDecodeExtFn)
+
+ // create and use decoder/encoder
+ var (
+ r io.Reader
+ w io.Writer
+ b []byte
+ h = &bh // or mh to use msgpack
+ )
+
+ dec = codec.NewDecoder(r, h)
+ dec = codec.NewDecoderBytes(b, h)
+ err = dec.Decode(&v)
+
+ enc = codec.NewEncoder(w, h)
+ enc = codec.NewEncoderBytes(&b, h)
+ err = enc.Encode(v)
+
+ //RPC Server
+ go func() {
+ for {
+ conn, err := listener.Accept()
+ rpcCodec := codec.GoRpc.ServerCodec(conn, h)
+ //OR rpcCodec := codec.MsgpackSpecRpc.ServerCodec(conn, h)
+ rpc.ServeCodec(rpcCodec)
+ }
+ }()
+
+ //RPC Communication (client side)
+ conn, err = net.Dial("tcp", "localhost:5555")
+ rpcCodec := codec.GoRpc.ClientCodec(conn, h)
+ //OR rpcCodec := codec.MsgpackSpecRpc.ClientCodec(conn, h)
+ client := rpc.NewClientWithCodec(rpcCodec)
+
+## Representative Benchmark Results
+
+A sample run of benchmark using "go test -bi -bench=. -benchmem":
+
+ /proc/cpuinfo: Intel(R) Core(TM) i7-2630QM CPU @ 2.00GHz (HT)
+
+ ..............................................
+ BENCHMARK INIT: 2013-10-16 11:02:50.345970786 -0400 EDT
+ To run full benchmark comparing encodings (MsgPack, Binc, JSON, GOB, etc), use: "go test -bench=."
+ Benchmark:
+ Struct recursive Depth: 1
+ ApproxDeepSize Of benchmark Struct: 4694 bytes
+ Benchmark One-Pass Run:
+ v-msgpack: len: 1600 bytes
+ bson: len: 3025 bytes
+ msgpack: len: 1560 bytes
+ binc: len: 1187 bytes
+ gob: len: 1972 bytes
+ json: len: 2538 bytes
+ ..............................................
+ PASS
+ Benchmark__Msgpack____Encode 50000 54359 ns/op 14953 B/op 83 allocs/op
+ Benchmark__Msgpack____Decode 10000 106531 ns/op 14990 B/op 410 allocs/op
+ Benchmark__Binc_NoSym_Encode 50000 53956 ns/op 14966 B/op 83 allocs/op
+ Benchmark__Binc_NoSym_Decode 10000 103751 ns/op 14529 B/op 386 allocs/op
+ Benchmark__Binc_Sym___Encode 50000 65961 ns/op 17130 B/op 88 allocs/op
+ Benchmark__Binc_Sym___Decode 10000 106310 ns/op 15857 B/op 287 allocs/op
+ Benchmark__Gob________Encode 10000 135944 ns/op 21189 B/op 237 allocs/op
+ Benchmark__Gob________Decode 5000 405390 ns/op 83460 B/op 1841 allocs/op
+ Benchmark__Json_______Encode 20000 79412 ns/op 13874 B/op 102 allocs/op
+ Benchmark__Json_______Decode 10000 247979 ns/op 14202 B/op 493 allocs/op
+ Benchmark__Bson_______Encode 10000 121762 ns/op 27814 B/op 514 allocs/op
+ Benchmark__Bson_______Decode 10000 162126 ns/op 16514 B/op 789 allocs/op
+ Benchmark__VMsgpack___Encode 50000 69155 ns/op 12370 B/op 344 allocs/op
+ Benchmark__VMsgpack___Decode 10000 151609 ns/op 20307 B/op 571 allocs/op
+ ok ugorji.net/codec 30.827s
+
+To run full benchmark suite (including against vmsgpack and bson),
+see notes in ext\_dep\_test.go
+
--- /dev/null
+// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a BSD-style license found in the LICENSE file.
+
+package codec
+
+import (
+ "math"
+ // "reflect"
+ // "sync/atomic"
+ "time"
+ //"fmt"
+)
+
+const bincDoPrune = true // No longer needed. Needed before as C lib did not support pruning.
+
+//var _ = fmt.Printf
+
+// vd as low 4 bits (there are 16 slots)
+const (
+ bincVdSpecial byte = iota
+ bincVdPosInt
+ bincVdNegInt
+ bincVdFloat
+
+ bincVdString
+ bincVdByteArray
+ bincVdArray
+ bincVdMap
+
+ bincVdTimestamp
+ bincVdSmallInt
+ bincVdUnicodeOther
+ bincVdSymbol
+
+ bincVdDecimal
+ _ // open slot
+ _ // open slot
+ bincVdCustomExt = 0x0f
+)
+
+const (
+ bincSpNil byte = iota
+ bincSpFalse
+ bincSpTrue
+ bincSpNan
+ bincSpPosInf
+ bincSpNegInf
+ bincSpZeroFloat
+ bincSpZero
+ bincSpNegOne
+)
+
+const (
+ bincFlBin16 byte = iota
+ bincFlBin32
+ _ // bincFlBin32e
+ bincFlBin64
+ _ // bincFlBin64e
+ // others not currently supported
+)
+
+type bincEncDriver struct {
+ w encWriter
+ m map[string]uint16 // symbols
+ s uint32 // symbols sequencer
+ b [8]byte
+}
+
+func (e *bincEncDriver) isBuiltinType(rt uintptr) bool {
+ return rt == timeTypId
+}
+
+func (e *bincEncDriver) encodeBuiltin(rt uintptr, v interface{}) {
+ switch rt {
+ case timeTypId:
+ bs := encodeTime(v.(time.Time))
+ e.w.writen1(bincVdTimestamp<<4 | uint8(len(bs)))
+ e.w.writeb(bs)
+ }
+}
+
+func (e *bincEncDriver) encodeNil() {
+ e.w.writen1(bincVdSpecial<<4 | bincSpNil)
+}
+
+func (e *bincEncDriver) encodeBool(b bool) {
+ if b {
+ e.w.writen1(bincVdSpecial<<4 | bincSpTrue)
+ } else {
+ e.w.writen1(bincVdSpecial<<4 | bincSpFalse)
+ }
+}
+
+func (e *bincEncDriver) encodeFloat32(f float32) {
+ if f == 0 {
+ e.w.writen1(bincVdSpecial<<4 | bincSpZeroFloat)
+ return
+ }
+ e.w.writen1(bincVdFloat<<4 | bincFlBin32)
+ e.w.writeUint32(math.Float32bits(f))
+}
+
+func (e *bincEncDriver) encodeFloat64(f float64) {
+ if f == 0 {
+ e.w.writen1(bincVdSpecial<<4 | bincSpZeroFloat)
+ return
+ }
+ bigen.PutUint64(e.b[:], math.Float64bits(f))
+ if bincDoPrune {
+ i := 7
+ for ; i >= 0 && (e.b[i] == 0); i-- {
+ }
+ i++
+ if i <= 6 {
+ e.w.writen1(bincVdFloat<<4 | 0x8 | bincFlBin64)
+ e.w.writen1(byte(i))
+ e.w.writeb(e.b[:i])
+ return
+ }
+ }
+ e.w.writen1(bincVdFloat<<4 | bincFlBin64)
+ e.w.writeb(e.b[:])
+}
+
+func (e *bincEncDriver) encIntegerPrune(bd byte, pos bool, v uint64, lim uint8) {
+ if lim == 4 {
+ bigen.PutUint32(e.b[:lim], uint32(v))
+ } else {
+ bigen.PutUint64(e.b[:lim], v)
+ }
+ if bincDoPrune {
+ i := pruneSignExt(e.b[:lim], pos)
+ e.w.writen1(bd | lim - 1 - byte(i))
+ e.w.writeb(e.b[i:lim])
+ } else {
+ e.w.writen1(bd | lim - 1)
+ e.w.writeb(e.b[:lim])
+ }
+}
+
+func (e *bincEncDriver) encodeInt(v int64) {
+ const nbd byte = bincVdNegInt << 4
+ switch {
+ case v >= 0:
+ e.encUint(bincVdPosInt<<4, true, uint64(v))
+ case v == -1:
+ e.w.writen1(bincVdSpecial<<4 | bincSpNegOne)
+ default:
+ e.encUint(bincVdNegInt<<4, false, uint64(-v))
+ }
+}
+
+func (e *bincEncDriver) encodeUint(v uint64) {
+ e.encUint(bincVdPosInt<<4, true, v)
+}
+
+func (e *bincEncDriver) encUint(bd byte, pos bool, v uint64) {
+ switch {
+ case v == 0:
+ e.w.writen1(bincVdSpecial<<4 | bincSpZero)
+ case pos && v >= 1 && v <= 16:
+ e.w.writen1(bincVdSmallInt<<4 | byte(v-1))
+ case v <= math.MaxUint8:
+ e.w.writen2(bd|0x0, byte(v))
+ case v <= math.MaxUint16:
+ e.w.writen1(bd | 0x01)
+ e.w.writeUint16(uint16(v))
+ case v <= math.MaxUint32:
+ e.encIntegerPrune(bd, pos, v, 4)
+ default:
+ e.encIntegerPrune(bd, pos, v, 8)
+ }
+}
+
+func (e *bincEncDriver) encodeExtPreamble(xtag byte, length int) {
+ e.encLen(bincVdCustomExt<<4, uint64(length))
+ e.w.writen1(xtag)
+}
+
+func (e *bincEncDriver) encodeArrayPreamble(length int) {
+ e.encLen(bincVdArray<<4, uint64(length))
+}
+
+func (e *bincEncDriver) encodeMapPreamble(length int) {
+ e.encLen(bincVdMap<<4, uint64(length))
+}
+
+func (e *bincEncDriver) encodeString(c charEncoding, v string) {
+ l := uint64(len(v))
+ e.encBytesLen(c, l)
+ if l > 0 {
+ e.w.writestr(v)
+ }
+}
+
+func (e *bincEncDriver) encodeSymbol(v string) {
+ // if WriteSymbolsNoRefs {
+ // e.encodeString(c_UTF8, v)
+ // return
+ // }
+
+ //symbols only offer benefit when string length > 1.
+ //This is because strings with length 1 take only 2 bytes to store
+ //(bd with embedded length, and single byte for string val).
+
+ l := len(v)
+ switch l {
+ case 0:
+ e.encBytesLen(c_UTF8, 0)
+ return
+ case 1:
+ e.encBytesLen(c_UTF8, 1)
+ e.w.writen1(v[0])
+ return
+ }
+ if e.m == nil {
+ e.m = make(map[string]uint16, 16)
+ }
+ ui, ok := e.m[v]
+ if ok {
+ if ui <= math.MaxUint8 {
+ e.w.writen2(bincVdSymbol<<4, byte(ui))
+ } else {
+ e.w.writen1(bincVdSymbol<<4 | 0x8)
+ e.w.writeUint16(ui)
+ }
+ } else {
+ e.s++
+ ui = uint16(e.s)
+ //ui = uint16(atomic.AddUint32(&e.s, 1))
+ e.m[v] = ui
+ var lenprec uint8
+ switch {
+ case l <= math.MaxUint8:
+ // lenprec = 0
+ case l <= math.MaxUint16:
+ lenprec = 1
+ case int64(l) <= math.MaxUint32:
+ lenprec = 2
+ default:
+ lenprec = 3
+ }
+ if ui <= math.MaxUint8 {
+ e.w.writen2(bincVdSymbol<<4|0x0|0x4|lenprec, byte(ui))
+ } else {
+ e.w.writen1(bincVdSymbol<<4 | 0x8 | 0x4 | lenprec)
+ e.w.writeUint16(ui)
+ }
+ switch lenprec {
+ case 0:
+ e.w.writen1(byte(l))
+ case 1:
+ e.w.writeUint16(uint16(l))
+ case 2:
+ e.w.writeUint32(uint32(l))
+ default:
+ e.w.writeUint64(uint64(l))
+ }
+ e.w.writestr(v)
+ }
+}
+
+func (e *bincEncDriver) encodeStringBytes(c charEncoding, v []byte) {
+ l := uint64(len(v))
+ e.encBytesLen(c, l)
+ if l > 0 {
+ e.w.writeb(v)
+ }
+}
+
+func (e *bincEncDriver) encBytesLen(c charEncoding, length uint64) {
+ //TODO: support bincUnicodeOther (for now, just use string or bytearray)
+ if c == c_RAW {
+ e.encLen(bincVdByteArray<<4, length)
+ } else {
+ e.encLen(bincVdString<<4, length)
+ }
+}
+
+func (e *bincEncDriver) encLen(bd byte, l uint64) {
+ if l < 12 {
+ e.w.writen1(bd | uint8(l+4))
+ } else {
+ e.encLenNumber(bd, l)
+ }
+}
+
+func (e *bincEncDriver) encLenNumber(bd byte, v uint64) {
+ switch {
+ case v <= math.MaxUint8:
+ e.w.writen2(bd, byte(v))
+ case v <= math.MaxUint16:
+ e.w.writen1(bd | 0x01)
+ e.w.writeUint16(uint16(v))
+ case v <= math.MaxUint32:
+ e.w.writen1(bd | 0x02)
+ e.w.writeUint32(uint32(v))
+ default:
+ e.w.writen1(bd | 0x03)
+ e.w.writeUint64(uint64(v))
+ }
+}
+
+//------------------------------------
+
+type bincDecDriver struct {
+ r decReader
+ bdRead bool
+ bdType valueType
+ bd byte
+ vd byte
+ vs byte
+ b [8]byte
+ m map[uint32]string // symbols (use uint32 as key, as map optimizes for it)
+}
+
+func (d *bincDecDriver) initReadNext() {
+ if d.bdRead {
+ return
+ }
+ d.bd = d.r.readn1()
+ d.vd = d.bd >> 4
+ d.vs = d.bd & 0x0f
+ d.bdRead = true
+ d.bdType = valueTypeUnset
+}
+
+func (d *bincDecDriver) currentEncodedType() valueType {
+ if d.bdType == valueTypeUnset {
+ switch d.vd {
+ case bincVdSpecial:
+ switch d.vs {
+ case bincSpNil:
+ d.bdType = valueTypeNil
+ case bincSpFalse, bincSpTrue:
+ d.bdType = valueTypeBool
+ case bincSpNan, bincSpNegInf, bincSpPosInf, bincSpZeroFloat:
+ d.bdType = valueTypeFloat
+ case bincSpZero:
+ d.bdType = valueTypeUint
+ case bincSpNegOne:
+ d.bdType = valueTypeInt
+ default:
+ decErr("currentEncodedType: Unrecognized special value 0x%x", d.vs)
+ }
+ case bincVdSmallInt:
+ d.bdType = valueTypeUint
+ case bincVdPosInt:
+ d.bdType = valueTypeUint
+ case bincVdNegInt:
+ d.bdType = valueTypeInt
+ case bincVdFloat:
+ d.bdType = valueTypeFloat
+ case bincVdString:
+ d.bdType = valueTypeString
+ case bincVdSymbol:
+ d.bdType = valueTypeSymbol
+ case bincVdByteArray:
+ d.bdType = valueTypeBytes
+ case bincVdTimestamp:
+ d.bdType = valueTypeTimestamp
+ case bincVdCustomExt:
+ d.bdType = valueTypeExt
+ case bincVdArray:
+ d.bdType = valueTypeArray
+ case bincVdMap:
+ d.bdType = valueTypeMap
+ default:
+ decErr("currentEncodedType: Unrecognized d.vd: 0x%x", d.vd)
+ }
+ }
+ return d.bdType
+}
+
+func (d *bincDecDriver) tryDecodeAsNil() bool {
+ if d.bd == bincVdSpecial<<4|bincSpNil {
+ d.bdRead = false
+ return true
+ }
+ return false
+}
+
+func (d *bincDecDriver) isBuiltinType(rt uintptr) bool {
+ return rt == timeTypId
+}
+
+func (d *bincDecDriver) decodeBuiltin(rt uintptr, v interface{}) {
+ switch rt {
+ case timeTypId:
+ if d.vd != bincVdTimestamp {
+ decErr("Invalid d.vd. Expecting 0x%x. Received: 0x%x", bincVdTimestamp, d.vd)
+ }
+ tt, err := decodeTime(d.r.readn(int(d.vs)))
+ if err != nil {
+ panic(err)
+ }
+ var vt *time.Time = v.(*time.Time)
+ *vt = tt
+ d.bdRead = false
+ }
+}
+
+func (d *bincDecDriver) decFloatPre(vs, defaultLen byte) {
+ if vs&0x8 == 0 {
+ d.r.readb(d.b[0:defaultLen])
+ } else {
+ l := d.r.readn1()
+ if l > 8 {
+ decErr("At most 8 bytes used to represent float. Received: %v bytes", l)
+ }
+ for i := l; i < 8; i++ {
+ d.b[i] = 0
+ }
+ d.r.readb(d.b[0:l])
+ }
+}
+
+func (d *bincDecDriver) decFloat() (f float64) {
+ //if true { f = math.Float64frombits(d.r.readUint64()); break; }
+ switch vs := d.vs; vs & 0x7 {
+ case bincFlBin32:
+ d.decFloatPre(vs, 4)
+ f = float64(math.Float32frombits(bigen.Uint32(d.b[0:4])))
+ case bincFlBin64:
+ d.decFloatPre(vs, 8)
+ f = math.Float64frombits(bigen.Uint64(d.b[0:8]))
+ default:
+ decErr("only float32 and float64 are supported. d.vd: 0x%x, d.vs: 0x%x", d.vd, d.vs)
+ }
+ return
+}
+
+func (d *bincDecDriver) decUint() (v uint64) {
+ // need to inline the code (interface conversion and type assertion expensive)
+ switch d.vs {
+ case 0:
+ v = uint64(d.r.readn1())
+ case 1:
+ d.r.readb(d.b[6:])
+ v = uint64(bigen.Uint16(d.b[6:]))
+ case 2:
+ d.b[4] = 0
+ d.r.readb(d.b[5:])
+ v = uint64(bigen.Uint32(d.b[4:]))
+ case 3:
+ d.r.readb(d.b[4:])
+ v = uint64(bigen.Uint32(d.b[4:]))
+ case 4, 5, 6:
+ lim := int(7 - d.vs)
+ d.r.readb(d.b[lim:])
+ for i := 0; i < lim; i++ {
+ d.b[i] = 0
+ }
+ v = uint64(bigen.Uint64(d.b[:]))
+ case 7:
+ d.r.readb(d.b[:])
+ v = uint64(bigen.Uint64(d.b[:]))
+ default:
+ decErr("unsigned integers with greater than 64 bits of precision not supported")
+ }
+ return
+}
+
+func (d *bincDecDriver) decIntAny() (ui uint64, i int64, neg bool) {
+ switch d.vd {
+ case bincVdPosInt:
+ ui = d.decUint()
+ i = int64(ui)
+ case bincVdNegInt:
+ ui = d.decUint()
+ i = -(int64(ui))
+ neg = true
+ case bincVdSmallInt:
+ i = int64(d.vs) + 1
+ ui = uint64(d.vs) + 1
+ case bincVdSpecial:
+ switch d.vs {
+ case bincSpZero:
+ //i = 0
+ case bincSpNegOne:
+ neg = true
+ ui = 1
+ i = -1
+ default:
+ decErr("numeric decode fails for special value: d.vs: 0x%x", d.vs)
+ }
+ default:
+ decErr("number can only be decoded from uint or int values. d.bd: 0x%x, d.vd: 0x%x", d.bd, d.vd)
+ }
+ return
+}
+
+func (d *bincDecDriver) decodeInt(bitsize uint8) (i int64) {
+ _, i, _ = d.decIntAny()
+ checkOverflow(0, i, bitsize)
+ d.bdRead = false
+ return
+}
+
+func (d *bincDecDriver) decodeUint(bitsize uint8) (ui uint64) {
+ ui, i, neg := d.decIntAny()
+ if neg {
+ decErr("Assigning negative signed value: %v, to unsigned type", i)
+ }
+ checkOverflow(ui, 0, bitsize)
+ d.bdRead = false
+ return
+}
+
+func (d *bincDecDriver) decodeFloat(chkOverflow32 bool) (f float64) {
+ switch d.vd {
+ case bincVdSpecial:
+ d.bdRead = false
+ switch d.vs {
+ case bincSpNan:
+ return math.NaN()
+ case bincSpPosInf:
+ return math.Inf(1)
+ case bincSpZeroFloat, bincSpZero:
+ return
+ case bincSpNegInf:
+ return math.Inf(-1)
+ default:
+ decErr("Invalid d.vs decoding float where d.vd=bincVdSpecial: %v", d.vs)
+ }
+ case bincVdFloat:
+ f = d.decFloat()
+ default:
+ _, i, _ := d.decIntAny()
+ f = float64(i)
+ }
+ checkOverflowFloat32(f, chkOverflow32)
+ d.bdRead = false
+ return
+}
+
+// bool can be decoded from bool only (single byte).
+func (d *bincDecDriver) decodeBool() (b bool) {
+ switch d.bd {
+ case (bincVdSpecial | bincSpFalse):
+ // b = false
+ case (bincVdSpecial | bincSpTrue):
+ b = true
+ default:
+ decErr("Invalid single-byte value for bool: %s: %x", msgBadDesc, d.bd)
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *bincDecDriver) readMapLen() (length int) {
+ if d.vd != bincVdMap {
+ decErr("Invalid d.vd for map. Expecting 0x%x. Got: 0x%x", bincVdMap, d.vd)
+ }
+ length = d.decLen()
+ d.bdRead = false
+ return
+}
+
+func (d *bincDecDriver) readArrayLen() (length int) {
+ if d.vd != bincVdArray {
+ decErr("Invalid d.vd for array. Expecting 0x%x. Got: 0x%x", bincVdArray, d.vd)
+ }
+ length = d.decLen()
+ d.bdRead = false
+ return
+}
+
+func (d *bincDecDriver) decLen() int {
+ if d.vs <= 3 {
+ return int(d.decUint())
+ }
+ return int(d.vs - 4)
+}
+
+func (d *bincDecDriver) decodeString() (s string) {
+ switch d.vd {
+ case bincVdString, bincVdByteArray:
+ if length := d.decLen(); length > 0 {
+ s = string(d.r.readn(length))
+ }
+ case bincVdSymbol:
+ //from vs: extract numSymbolBytes, containsStringVal, strLenPrecision,
+ //extract symbol
+ //if containsStringVal, read it and put in map
+ //else look in map for string value
+ var symbol uint32
+ vs := d.vs
+ //fmt.Printf(">>>> d.vs: 0b%b, & 0x8: %v, & 0x4: %v\n", d.vs, vs & 0x8, vs & 0x4)
+ if vs&0x8 == 0 {
+ symbol = uint32(d.r.readn1())
+ } else {
+ symbol = uint32(d.r.readUint16())
+ }
+ if d.m == nil {
+ d.m = make(map[uint32]string, 16)
+ }
+
+ if vs&0x4 == 0 {
+ s = d.m[symbol]
+ } else {
+ var slen int
+ switch vs & 0x3 {
+ case 0:
+ slen = int(d.r.readn1())
+ case 1:
+ slen = int(d.r.readUint16())
+ case 2:
+ slen = int(d.r.readUint32())
+ case 3:
+ slen = int(d.r.readUint64())
+ }
+ s = string(d.r.readn(slen))
+ d.m[symbol] = s
+ }
+ default:
+ decErr("Invalid d.vd for string. Expecting string:0x%x, bytearray:0x%x or symbol: 0x%x. Got: 0x%x",
+ bincVdString, bincVdByteArray, bincVdSymbol, d.vd)
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *bincDecDriver) decodeBytes(bs []byte) (bsOut []byte, changed bool) {
+ var clen int
+ switch d.vd {
+ case bincVdString, bincVdByteArray:
+ clen = d.decLen()
+ default:
+ decErr("Invalid d.vd for bytes. Expecting string:0x%x or bytearray:0x%x. Got: 0x%x",
+ bincVdString, bincVdByteArray, d.vd)
+ }
+ if clen > 0 {
+ // if no contents in stream, don't update the passed byteslice
+ if len(bs) != clen {
+ if len(bs) > clen {
+ bs = bs[:clen]
+ } else {
+ bs = make([]byte, clen)
+ }
+ bsOut = bs
+ changed = true
+ }
+ d.r.readb(bs)
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *bincDecDriver) decodeExt(verifyTag bool, tag byte) (xtag byte, xbs []byte) {
+ switch d.vd {
+ case bincVdCustomExt:
+ l := d.decLen()
+ xtag = d.r.readn1()
+ if verifyTag && xtag != tag {
+ decErr("Wrong extension tag. Got %b. Expecting: %v", xtag, tag)
+ }
+ xbs = d.r.readn(l)
+ case bincVdByteArray:
+ xbs, _ = d.decodeBytes(nil)
+ default:
+ decErr("Invalid d.vd for extensions (Expecting extensions or byte array). Got: 0x%x", d.vd)
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *bincDecDriver) decodeNaked() (v interface{}, vt valueType, decodeFurther bool) {
+ d.initReadNext()
+
+ switch d.vd {
+ case bincVdSpecial:
+ switch d.vs {
+ case bincSpNil:
+ vt = valueTypeNil
+ case bincSpFalse:
+ vt = valueTypeBool
+ v = false
+ case bincSpTrue:
+ vt = valueTypeBool
+ v = true
+ case bincSpNan:
+ vt = valueTypeFloat
+ v = math.NaN()
+ case bincSpPosInf:
+ vt = valueTypeFloat
+ v = math.Inf(1)
+ case bincSpNegInf:
+ vt = valueTypeFloat
+ v = math.Inf(-1)
+ case bincSpZeroFloat:
+ vt = valueTypeFloat
+ v = float64(0)
+ case bincSpZero:
+ vt = valueTypeUint
+ v = int64(0) // int8(0)
+ case bincSpNegOne:
+ vt = valueTypeInt
+ v = int64(-1) // int8(-1)
+ default:
+ decErr("decodeNaked: Unrecognized special value 0x%x", d.vs)
+ }
+ case bincVdSmallInt:
+ vt = valueTypeUint
+ v = uint64(int8(d.vs)) + 1 // int8(d.vs) + 1
+ case bincVdPosInt:
+ vt = valueTypeUint
+ v = d.decUint()
+ case bincVdNegInt:
+ vt = valueTypeInt
+ v = -(int64(d.decUint()))
+ case bincVdFloat:
+ vt = valueTypeFloat
+ v = d.decFloat()
+ case bincVdSymbol:
+ vt = valueTypeSymbol
+ v = d.decodeString()
+ case bincVdString:
+ vt = valueTypeString
+ v = d.decodeString()
+ case bincVdByteArray:
+ vt = valueTypeBytes
+ v, _ = d.decodeBytes(nil)
+ case bincVdTimestamp:
+ vt = valueTypeTimestamp
+ tt, err := decodeTime(d.r.readn(int(d.vs)))
+ if err != nil {
+ panic(err)
+ }
+ v = tt
+ case bincVdCustomExt:
+ vt = valueTypeExt
+ l := d.decLen()
+ var re RawExt
+ re.Tag = d.r.readn1()
+ re.Data = d.r.readn(l)
+ v = &re
+ vt = valueTypeExt
+ case bincVdArray:
+ vt = valueTypeArray
+ decodeFurther = true
+ case bincVdMap:
+ vt = valueTypeMap
+ decodeFurther = true
+ default:
+ decErr("decodeNaked: Unrecognized d.vd: 0x%x", d.vd)
+ }
+
+ if !decodeFurther {
+ d.bdRead = false
+ }
+ return
+}
+
+//------------------------------------
+
+//BincHandle is a Handle for the Binc Schema-Free Encoding Format
+//defined at https://github.com/ugorji/binc .
+//
+//BincHandle currently supports all Binc features with the following EXCEPTIONS:
+// - only integers up to 64 bits of precision are supported.
+// big integers are unsupported.
+// - Only IEEE 754 binary32 and binary64 floats are supported (ie Go float32 and float64 types).
+// extended precision and decimal IEEE 754 floats are unsupported.
+// - Only UTF-8 strings supported.
+// Unicode_Other Binc types (UTF16, UTF32) are currently unsupported.
+//Note that these EXCEPTIONS are temporary and full support is possible and may happen soon.
+type BincHandle struct {
+ BasicHandle
+}
+
+func (h *BincHandle) newEncDriver(w encWriter) encDriver {
+ return &bincEncDriver{w: w}
+}
+
+func (h *BincHandle) newDecDriver(r decReader) decDriver {
+ return &bincDecDriver{r: r}
+}
+
+func (_ *BincHandle) writeExt() bool {
+ return true
+}
+
+func (h *BincHandle) getBasicHandle() *BasicHandle {
+ return &h.BasicHandle
+}
--- /dev/null
+// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a BSD-style license found in the LICENSE file.
+
+package codec
+
+import (
+ "io"
+ "reflect"
+ // "runtime/debug"
+)
+
+// Some tagging information for error messages.
+const (
+ msgTagDec = "codec.decoder"
+ msgBadDesc = "Unrecognized descriptor byte"
+ msgDecCannotExpandArr = "cannot expand go array from %v to stream length: %v"
+)
+
+// decReader abstracts the reading source, allowing implementations that can
+// read from an io.Reader or directly off a byte slice with zero-copying.
+type decReader interface {
+ readn(n int) []byte
+ readb([]byte)
+ readn1() uint8
+ readUint16() uint16
+ readUint32() uint32
+ readUint64() uint64
+}
+
+type decDriver interface {
+ initReadNext()
+ tryDecodeAsNil() bool
+ currentEncodedType() valueType
+ isBuiltinType(rt uintptr) bool
+ decodeBuiltin(rt uintptr, v interface{})
+ //decodeNaked: Numbers are decoded as int64, uint64, float64 only (no smaller sized number types).
+ decodeNaked() (v interface{}, vt valueType, decodeFurther bool)
+ decodeInt(bitsize uint8) (i int64)
+ decodeUint(bitsize uint8) (ui uint64)
+ decodeFloat(chkOverflow32 bool) (f float64)
+ decodeBool() (b bool)
+ // decodeString can also decode symbols
+ decodeString() (s string)
+ decodeBytes(bs []byte) (bsOut []byte, changed bool)
+ decodeExt(verifyTag bool, tag byte) (xtag byte, xbs []byte)
+ readMapLen() int
+ readArrayLen() int
+}
+
+type DecodeOptions struct {
+ // An instance of MapType is used during schema-less decoding of a map in the stream.
+ // If nil, we use map[interface{}]interface{}
+ MapType reflect.Type
+ // An instance of SliceType is used during schema-less decoding of an array in the stream.
+ // If nil, we use []interface{}
+ SliceType reflect.Type
+ // ErrorIfNoField controls whether an error is returned when decoding a map
+ // from a codec stream into a struct, and no matching struct field is found.
+ ErrorIfNoField bool
+}
+
+// ------------------------------------
+
+// ioDecReader is a decReader that reads off an io.Reader
+type ioDecReader struct {
+ r io.Reader
+ br io.ByteReader
+ x [8]byte //temp byte array re-used internally for efficiency
+}
+
+func (z *ioDecReader) readn(n int) (bs []byte) {
+ if n <= 0 {
+ return
+ }
+ bs = make([]byte, n)
+ if _, err := io.ReadAtLeast(z.r, bs, n); err != nil {
+ panic(err)
+ }
+ return
+}
+
+func (z *ioDecReader) readb(bs []byte) {
+ if _, err := io.ReadAtLeast(z.r, bs, len(bs)); err != nil {
+ panic(err)
+ }
+}
+
+func (z *ioDecReader) readn1() uint8 {
+ if z.br != nil {
+ b, err := z.br.ReadByte()
+ if err != nil {
+ panic(err)
+ }
+ return b
+ }
+ z.readb(z.x[:1])
+ return z.x[0]
+}
+
+func (z *ioDecReader) readUint16() uint16 {
+ z.readb(z.x[:2])
+ return bigen.Uint16(z.x[:2])
+}
+
+func (z *ioDecReader) readUint32() uint32 {
+ z.readb(z.x[:4])
+ return bigen.Uint32(z.x[:4])
+}
+
+func (z *ioDecReader) readUint64() uint64 {
+ z.readb(z.x[:8])
+ return bigen.Uint64(z.x[:8])
+}
+
+// ------------------------------------
+
+// bytesDecReader is a decReader that reads off a byte slice with zero copying
+type bytesDecReader struct {
+ b []byte // data
+ c int // cursor
+ a int // available
+}
+
+func (z *bytesDecReader) consume(n int) (oldcursor int) {
+ if z.a == 0 {
+ panic(io.EOF)
+ }
+ if n > z.a {
+ decErr("Trying to read %v bytes. Only %v available", n, z.a)
+ }
+ // z.checkAvailable(n)
+ oldcursor = z.c
+ z.c = oldcursor + n
+ z.a = z.a - n
+ return
+}
+
+func (z *bytesDecReader) readn(n int) (bs []byte) {
+ if n <= 0 {
+ return
+ }
+ c0 := z.consume(n)
+ bs = z.b[c0:z.c]
+ return
+}
+
+func (z *bytesDecReader) readb(bs []byte) {
+ copy(bs, z.readn(len(bs)))
+}
+
+func (z *bytesDecReader) readn1() uint8 {
+ c0 := z.consume(1)
+ return z.b[c0]
+}
+
+// Use binaryEncoding helper for 4 and 8 bits, but inline it for 2 bits
+// creating temp slice variable and copying it to helper function is expensive
+// for just 2 bits.
+
+func (z *bytesDecReader) readUint16() uint16 {
+ c0 := z.consume(2)
+ return uint16(z.b[c0+1]) | uint16(z.b[c0])<<8
+}
+
+func (z *bytesDecReader) readUint32() uint32 {
+ c0 := z.consume(4)
+ return bigen.Uint32(z.b[c0:z.c])
+}
+
+func (z *bytesDecReader) readUint64() uint64 {
+ c0 := z.consume(8)
+ return bigen.Uint64(z.b[c0:z.c])
+}
+
+// ------------------------------------
+
+// decFnInfo has methods for registering handling decoding of a specific type
+// based on some characteristics (builtin, extension, reflect Kind, etc)
+type decFnInfo struct {
+ ti *typeInfo
+ d *Decoder
+ dd decDriver
+ xfFn func(reflect.Value, []byte) error
+ xfTag byte
+ array bool
+}
+
+func (f *decFnInfo) builtin(rv reflect.Value) {
+ f.dd.decodeBuiltin(f.ti.rtid, rv.Addr().Interface())
+}
+
+func (f *decFnInfo) rawExt(rv reflect.Value) {
+ xtag, xbs := f.dd.decodeExt(false, 0)
+ rv.Field(0).SetUint(uint64(xtag))
+ rv.Field(1).SetBytes(xbs)
+}
+
+func (f *decFnInfo) ext(rv reflect.Value) {
+ _, xbs := f.dd.decodeExt(true, f.xfTag)
+ if fnerr := f.xfFn(rv, xbs); fnerr != nil {
+ panic(fnerr)
+ }
+}
+
+func (f *decFnInfo) binaryMarshal(rv reflect.Value) {
+ var bm binaryUnmarshaler
+ if f.ti.unmIndir == -1 {
+ bm = rv.Addr().Interface().(binaryUnmarshaler)
+ } else if f.ti.unmIndir == 0 {
+ bm = rv.Interface().(binaryUnmarshaler)
+ } else {
+ for j, k := int8(0), f.ti.unmIndir; j < k; j++ {
+ if rv.IsNil() {
+ rv.Set(reflect.New(rv.Type().Elem()))
+ }
+ rv = rv.Elem()
+ }
+ bm = rv.Interface().(binaryUnmarshaler)
+ }
+ xbs, _ := f.dd.decodeBytes(nil)
+ if fnerr := bm.UnmarshalBinary(xbs); fnerr != nil {
+ panic(fnerr)
+ }
+}
+
+func (f *decFnInfo) kErr(rv reflect.Value) {
+ decErr("Unhandled value for kind: %v: %s", rv.Kind(), msgBadDesc)
+}
+
+func (f *decFnInfo) kString(rv reflect.Value) {
+ rv.SetString(f.dd.decodeString())
+}
+
+func (f *decFnInfo) kBool(rv reflect.Value) {
+ rv.SetBool(f.dd.decodeBool())
+}
+
+func (f *decFnInfo) kInt(rv reflect.Value) {
+ rv.SetInt(f.dd.decodeInt(intBitsize))
+}
+
+func (f *decFnInfo) kInt64(rv reflect.Value) {
+ rv.SetInt(f.dd.decodeInt(64))
+}
+
+func (f *decFnInfo) kInt32(rv reflect.Value) {
+ rv.SetInt(f.dd.decodeInt(32))
+}
+
+func (f *decFnInfo) kInt8(rv reflect.Value) {
+ rv.SetInt(f.dd.decodeInt(8))
+}
+
+func (f *decFnInfo) kInt16(rv reflect.Value) {
+ rv.SetInt(f.dd.decodeInt(16))
+}
+
+func (f *decFnInfo) kFloat32(rv reflect.Value) {
+ rv.SetFloat(f.dd.decodeFloat(true))
+}
+
+func (f *decFnInfo) kFloat64(rv reflect.Value) {
+ rv.SetFloat(f.dd.decodeFloat(false))
+}
+
+func (f *decFnInfo) kUint8(rv reflect.Value) {
+ rv.SetUint(f.dd.decodeUint(8))
+}
+
+func (f *decFnInfo) kUint64(rv reflect.Value) {
+ rv.SetUint(f.dd.decodeUint(64))
+}
+
+func (f *decFnInfo) kUint(rv reflect.Value) {
+ rv.SetUint(f.dd.decodeUint(uintBitsize))
+}
+
+func (f *decFnInfo) kUint32(rv reflect.Value) {
+ rv.SetUint(f.dd.decodeUint(32))
+}
+
+func (f *decFnInfo) kUint16(rv reflect.Value) {
+ rv.SetUint(f.dd.decodeUint(16))
+}
+
+// func (f *decFnInfo) kPtr(rv reflect.Value) {
+// debugf(">>>>>>> ??? decode kPtr called - shouldn't get called")
+// if rv.IsNil() {
+// rv.Set(reflect.New(rv.Type().Elem()))
+// }
+// f.d.decodeValue(rv.Elem())
+// }
+
+func (f *decFnInfo) kInterface(rv reflect.Value) {
+ // debugf("\t===> kInterface")
+ if !rv.IsNil() {
+ f.d.decodeValue(rv.Elem())
+ return
+ }
+ // nil interface:
+ // use some hieristics to set the nil interface to an
+ // appropriate value based on the first byte read (byte descriptor bd)
+ v, vt, decodeFurther := f.dd.decodeNaked()
+ if vt == valueTypeNil {
+ return
+ }
+ // Cannot decode into nil interface with methods (e.g. error, io.Reader, etc)
+ // if non-nil value in stream.
+ if num := f.ti.rt.NumMethod(); num > 0 {
+ decErr("decodeValue: Cannot decode non-nil codec value into nil %v (%v methods)",
+ f.ti.rt, num)
+ }
+ var rvn reflect.Value
+ var useRvn bool
+ switch vt {
+ case valueTypeMap:
+ if f.d.h.MapType == nil {
+ var m2 map[interface{}]interface{}
+ v = &m2
+ } else {
+ rvn = reflect.New(f.d.h.MapType).Elem()
+ useRvn = true
+ }
+ case valueTypeArray:
+ if f.d.h.SliceType == nil {
+ var m2 []interface{}
+ v = &m2
+ } else {
+ rvn = reflect.New(f.d.h.SliceType).Elem()
+ useRvn = true
+ }
+ case valueTypeExt:
+ re := v.(*RawExt)
+ var bfn func(reflect.Value, []byte) error
+ rvn, bfn = f.d.h.getDecodeExtForTag(re.Tag)
+ if bfn == nil {
+ rvn = reflect.ValueOf(*re)
+ } else if fnerr := bfn(rvn, re.Data); fnerr != nil {
+ panic(fnerr)
+ }
+ rv.Set(rvn)
+ return
+ }
+ if decodeFurther {
+ if useRvn {
+ f.d.decodeValue(rvn)
+ } else if v != nil {
+ // this v is a pointer, so we need to dereference it when done
+ f.d.decode(v)
+ rvn = reflect.ValueOf(v).Elem()
+ useRvn = true
+ }
+ }
+ if useRvn {
+ rv.Set(rvn)
+ } else if v != nil {
+ rv.Set(reflect.ValueOf(v))
+ }
+}
+
+func (f *decFnInfo) kStruct(rv reflect.Value) {
+ fti := f.ti
+ if currEncodedType := f.dd.currentEncodedType(); currEncodedType == valueTypeMap {
+ containerLen := f.dd.readMapLen()
+ if containerLen == 0 {
+ return
+ }
+ tisfi := fti.sfi
+ for j := 0; j < containerLen; j++ {
+ // var rvkencname string
+ // ddecode(&rvkencname)
+ f.dd.initReadNext()
+ rvkencname := f.dd.decodeString()
+ // rvksi := ti.getForEncName(rvkencname)
+ if k := fti.indexForEncName(rvkencname); k > -1 {
+ sfik := tisfi[k]
+ if sfik.i != -1 {
+ f.d.decodeValue(rv.Field(int(sfik.i)))
+ } else {
+ f.d.decEmbeddedField(rv, sfik.is)
+ }
+ // f.d.decodeValue(ti.field(k, rv))
+ } else {
+ if f.d.h.ErrorIfNoField {
+ decErr("No matching struct field found when decoding stream map with key: %v",
+ rvkencname)
+ } else {
+ var nilintf0 interface{}
+ f.d.decodeValue(reflect.ValueOf(&nilintf0).Elem())
+ }
+ }
+ }
+ } else if currEncodedType == valueTypeArray {
+ containerLen := f.dd.readArrayLen()
+ if containerLen == 0 {
+ return
+ }
+ for j, si := range fti.sfip {
+ if j == containerLen {
+ break
+ }
+ if si.i != -1 {
+ f.d.decodeValue(rv.Field(int(si.i)))
+ } else {
+ f.d.decEmbeddedField(rv, si.is)
+ }
+ }
+ if containerLen > len(fti.sfip) {
+ // read remaining values and throw away
+ for j := len(fti.sfip); j < containerLen; j++ {
+ var nilintf0 interface{}
+ f.d.decodeValue(reflect.ValueOf(&nilintf0).Elem())
+ }
+ }
+ } else {
+ decErr("Only encoded map or array can be decoded into a struct. (valueType: %x)",
+ currEncodedType)
+ }
+}
+
+func (f *decFnInfo) kSlice(rv reflect.Value) {
+ // A slice can be set from a map or array in stream.
+ currEncodedType := f.dd.currentEncodedType()
+
+ switch currEncodedType {
+ case valueTypeBytes, valueTypeString:
+ if f.ti.rtid == uint8SliceTypId || f.ti.rt.Elem().Kind() == reflect.Uint8 {
+ if bs2, changed2 := f.dd.decodeBytes(rv.Bytes()); changed2 {
+ rv.SetBytes(bs2)
+ }
+ return
+ }
+ }
+
+ if shortCircuitReflectToFastPath && rv.CanAddr() {
+ switch f.ti.rtid {
+ case intfSliceTypId:
+ f.d.decSliceIntf(rv.Addr().Interface().(*[]interface{}), currEncodedType, f.array)
+ return
+ case uint64SliceTypId:
+ f.d.decSliceUint64(rv.Addr().Interface().(*[]uint64), currEncodedType, f.array)
+ return
+ case int64SliceTypId:
+ f.d.decSliceInt64(rv.Addr().Interface().(*[]int64), currEncodedType, f.array)
+ return
+ case strSliceTypId:
+ f.d.decSliceStr(rv.Addr().Interface().(*[]string), currEncodedType, f.array)
+ return
+ }
+ }
+
+ containerLen, containerLenS := decContLens(f.dd, currEncodedType)
+
+ // an array can never return a nil slice. so no need to check f.array here.
+
+ if rv.IsNil() {
+ rv.Set(reflect.MakeSlice(f.ti.rt, containerLenS, containerLenS))
+ }
+
+ if containerLen == 0 {
+ return
+ }
+
+ if rvcap, rvlen := rv.Len(), rv.Cap(); containerLenS > rvcap {
+ if f.array { // !rv.CanSet()
+ decErr(msgDecCannotExpandArr, rvcap, containerLenS)
+ }
+ rvn := reflect.MakeSlice(f.ti.rt, containerLenS, containerLenS)
+ if rvlen > 0 {
+ reflect.Copy(rvn, rv)
+ }
+ rv.Set(rvn)
+ } else if containerLenS > rvlen {
+ rv.SetLen(containerLenS)
+ }
+
+ for j := 0; j < containerLenS; j++ {
+ f.d.decodeValue(rv.Index(j))
+ }
+}
+
+func (f *decFnInfo) kArray(rv reflect.Value) {
+ // f.d.decodeValue(rv.Slice(0, rv.Len()))
+ f.kSlice(rv.Slice(0, rv.Len()))
+}
+
+func (f *decFnInfo) kMap(rv reflect.Value) {
+ if shortCircuitReflectToFastPath && rv.CanAddr() {
+ switch f.ti.rtid {
+ case mapStrIntfTypId:
+ f.d.decMapStrIntf(rv.Addr().Interface().(*map[string]interface{}))
+ return
+ case mapIntfIntfTypId:
+ f.d.decMapIntfIntf(rv.Addr().Interface().(*map[interface{}]interface{}))
+ return
+ case mapInt64IntfTypId:
+ f.d.decMapInt64Intf(rv.Addr().Interface().(*map[int64]interface{}))
+ return
+ case mapUint64IntfTypId:
+ f.d.decMapUint64Intf(rv.Addr().Interface().(*map[uint64]interface{}))
+ return
+ }
+ }
+
+ containerLen := f.dd.readMapLen()
+
+ if rv.IsNil() {
+ rv.Set(reflect.MakeMap(f.ti.rt))
+ }
+
+ if containerLen == 0 {
+ return
+ }
+
+ ktype, vtype := f.ti.rt.Key(), f.ti.rt.Elem()
+ ktypeId := reflect.ValueOf(ktype).Pointer()
+ for j := 0; j < containerLen; j++ {
+ rvk := reflect.New(ktype).Elem()
+ f.d.decodeValue(rvk)
+
+ // special case if a byte array.
+ // if ktype == intfTyp {
+ if ktypeId == intfTypId {
+ rvk = rvk.Elem()
+ if rvk.Type() == uint8SliceTyp {
+ rvk = reflect.ValueOf(string(rvk.Bytes()))
+ }
+ }
+ rvv := rv.MapIndex(rvk)
+ if !rvv.IsValid() {
+ rvv = reflect.New(vtype).Elem()
+ }
+
+ f.d.decodeValue(rvv)
+ rv.SetMapIndex(rvk, rvv)
+ }
+}
+
+// ----------------------------------------
+
+type decFn struct {
+ i *decFnInfo
+ f func(*decFnInfo, reflect.Value)
+}
+
+// A Decoder reads and decodes an object from an input stream in the codec format.
+type Decoder struct {
+ r decReader
+ d decDriver
+ h *BasicHandle
+ f map[uintptr]decFn
+ x []uintptr
+ s []decFn
+}
+
+// NewDecoder returns a Decoder for decoding a stream of bytes from an io.Reader.
+//
+// For efficiency, Users are encouraged to pass in a memory buffered writer
+// (eg bufio.Reader, bytes.Buffer).
+func NewDecoder(r io.Reader, h Handle) *Decoder {
+ z := ioDecReader{
+ r: r,
+ }
+ z.br, _ = r.(io.ByteReader)
+ return &Decoder{r: &z, d: h.newDecDriver(&z), h: h.getBasicHandle()}
+}
+
+// NewDecoderBytes returns a Decoder which efficiently decodes directly
+// from a byte slice with zero copying.
+func NewDecoderBytes(in []byte, h Handle) *Decoder {
+ z := bytesDecReader{
+ b: in,
+ a: len(in),
+ }
+ return &Decoder{r: &z, d: h.newDecDriver(&z), h: h.getBasicHandle()}
+}
+
+// Decode decodes the stream from reader and stores the result in the
+// value pointed to by v. v cannot be a nil pointer. v can also be
+// a reflect.Value of a pointer.
+//
+// Note that a pointer to a nil interface is not a nil pointer.
+// If you do not know what type of stream it is, pass in a pointer to a nil interface.
+// We will decode and store a value in that nil interface.
+//
+// Sample usages:
+// // Decoding into a non-nil typed value
+// var f float32
+// err = codec.NewDecoder(r, handle).Decode(&f)
+//
+// // Decoding into nil interface
+// var v interface{}
+// dec := codec.NewDecoder(r, handle)
+// err = dec.Decode(&v)
+//
+// When decoding into a nil interface{}, we will decode into an appropriate value based
+// on the contents of the stream:
+// - Numbers are decoded as float64, int64 or uint64.
+// - Other values are decoded appropriately depending on the type:
+// bool, string, []byte, time.Time, etc
+// - Extensions are decoded as RawExt (if no ext function registered for the tag)
+// Configurations exist on the Handle to override defaults
+// (e.g. for MapType, SliceType and how to decode raw bytes).
+//
+// When decoding into a non-nil interface{} value, the mode of encoding is based on the
+// type of the value. When a value is seen:
+// - If an extension is registered for it, call that extension function
+// - If it implements BinaryUnmarshaler, call its UnmarshalBinary(data []byte) error
+// - Else decode it based on its reflect.Kind
+//
+// There are some special rules when decoding into containers (slice/array/map/struct).
+// Decode will typically use the stream contents to UPDATE the container.
+// - A map can be decoded from a stream map, by updating matching keys.
+// - A slice can be decoded from a stream array,
+// by updating the first n elements, where n is length of the stream.
+// - A slice can be decoded from a stream map, by decoding as if
+// it contains a sequence of key-value pairs.
+// - A struct can be decoded from a stream map, by updating matching fields.
+// - A struct can be decoded from a stream array,
+// by updating fields as they occur in the struct (by index).
+//
+// When decoding a stream map or array with length of 0 into a nil map or slice,
+// we reset the destination map or slice to a zero-length value.
+//
+// However, when decoding a stream nil, we reset the destination container
+// to its "zero" value (e.g. nil for slice/map, etc).
+//
+func (d *Decoder) Decode(v interface{}) (err error) {
+ defer panicToErr(&err)
+ d.decode(v)
+ return
+}
+
+func (d *Decoder) decode(iv interface{}) {
+ d.d.initReadNext()
+
+ switch v := iv.(type) {
+ case nil:
+ decErr("Cannot decode into nil.")
+
+ case reflect.Value:
+ d.chkPtrValue(v)
+ d.decodeValue(v.Elem())
+
+ case *string:
+ *v = d.d.decodeString()
+ case *bool:
+ *v = d.d.decodeBool()
+ case *int:
+ *v = int(d.d.decodeInt(intBitsize))
+ case *int8:
+ *v = int8(d.d.decodeInt(8))
+ case *int16:
+ *v = int16(d.d.decodeInt(16))
+ case *int32:
+ *v = int32(d.d.decodeInt(32))
+ case *int64:
+ *v = d.d.decodeInt(64)
+ case *uint:
+ *v = uint(d.d.decodeUint(uintBitsize))
+ case *uint8:
+ *v = uint8(d.d.decodeUint(8))
+ case *uint16:
+ *v = uint16(d.d.decodeUint(16))
+ case *uint32:
+ *v = uint32(d.d.decodeUint(32))
+ case *uint64:
+ *v = d.d.decodeUint(64)
+ case *float32:
+ *v = float32(d.d.decodeFloat(true))
+ case *float64:
+ *v = d.d.decodeFloat(false)
+ case *[]byte:
+ *v, _ = d.d.decodeBytes(*v)
+
+ case *[]interface{}:
+ d.decSliceIntf(v, valueTypeInvalid, false)
+ case *[]uint64:
+ d.decSliceUint64(v, valueTypeInvalid, false)
+ case *[]int64:
+ d.decSliceInt64(v, valueTypeInvalid, false)
+ case *[]string:
+ d.decSliceStr(v, valueTypeInvalid, false)
+ case *map[string]interface{}:
+ d.decMapStrIntf(v)
+ case *map[interface{}]interface{}:
+ d.decMapIntfIntf(v)
+ case *map[uint64]interface{}:
+ d.decMapUint64Intf(v)
+ case *map[int64]interface{}:
+ d.decMapInt64Intf(v)
+
+ case *interface{}:
+ d.decodeValue(reflect.ValueOf(iv).Elem())
+
+ default:
+ rv := reflect.ValueOf(iv)
+ d.chkPtrValue(rv)
+ d.decodeValue(rv.Elem())
+ }
+}
+
+func (d *Decoder) decodeValue(rv reflect.Value) {
+ d.d.initReadNext()
+
+ if d.d.tryDecodeAsNil() {
+ // If value in stream is nil, set the dereferenced value to its "zero" value (if settable)
+ if rv.Kind() == reflect.Ptr {
+ if !rv.IsNil() {
+ rv.Set(reflect.Zero(rv.Type()))
+ }
+ return
+ }
+ // for rv.Kind() == reflect.Ptr {
+ // rv = rv.Elem()
+ // }
+ if rv.IsValid() { // rv.CanSet() // always settable, except it's invalid
+ rv.Set(reflect.Zero(rv.Type()))
+ }
+ return
+ }
+
+ // If stream is not containing a nil value, then we can deref to the base
+ // non-pointer value, and decode into that.
+ for rv.Kind() == reflect.Ptr {
+ if rv.IsNil() {
+ rv.Set(reflect.New(rv.Type().Elem()))
+ }
+ rv = rv.Elem()
+ }
+
+ rt := rv.Type()
+ rtid := reflect.ValueOf(rt).Pointer()
+
+ // retrieve or register a focus'ed function for this type
+ // to eliminate need to do the retrieval multiple times
+
+ // if d.f == nil && d.s == nil { debugf("---->Creating new dec f map for type: %v\n", rt) }
+ var fn decFn
+ var ok bool
+ if useMapForCodecCache {
+ fn, ok = d.f[rtid]
+ } else {
+ for i, v := range d.x {
+ if v == rtid {
+ fn, ok = d.s[i], true
+ break
+ }
+ }
+ }
+ if !ok {
+ // debugf("\tCreating new dec fn for type: %v\n", rt)
+ fi := decFnInfo{ti: getTypeInfo(rtid, rt), d: d, dd: d.d}
+ fn.i = &fi
+ // An extension can be registered for any type, regardless of the Kind
+ // (e.g. type BitSet int64, type MyStruct { / * unexported fields * / }, type X []int, etc.
+ //
+ // We can't check if it's an extension byte here first, because the user may have
+ // registered a pointer or non-pointer type, meaning we may have to recurse first
+ // before matching a mapped type, even though the extension byte is already detected.
+ //
+ // NOTE: if decoding into a nil interface{}, we return a non-nil
+ // value except even if the container registers a length of 0.
+ if rtid == rawExtTypId {
+ fn.f = (*decFnInfo).rawExt
+ } else if d.d.isBuiltinType(rtid) {
+ fn.f = (*decFnInfo).builtin
+ } else if xfTag, xfFn := d.h.getDecodeExt(rtid); xfFn != nil {
+ fi.xfTag, fi.xfFn = xfTag, xfFn
+ fn.f = (*decFnInfo).ext
+ } else if supportBinaryMarshal && fi.ti.unm {
+ fn.f = (*decFnInfo).binaryMarshal
+ } else {
+ switch rk := rt.Kind(); rk {
+ case reflect.String:
+ fn.f = (*decFnInfo).kString
+ case reflect.Bool:
+ fn.f = (*decFnInfo).kBool
+ case reflect.Int:
+ fn.f = (*decFnInfo).kInt
+ case reflect.Int64:
+ fn.f = (*decFnInfo).kInt64
+ case reflect.Int32:
+ fn.f = (*decFnInfo).kInt32
+ case reflect.Int8:
+ fn.f = (*decFnInfo).kInt8
+ case reflect.Int16:
+ fn.f = (*decFnInfo).kInt16
+ case reflect.Float32:
+ fn.f = (*decFnInfo).kFloat32
+ case reflect.Float64:
+ fn.f = (*decFnInfo).kFloat64
+ case reflect.Uint8:
+ fn.f = (*decFnInfo).kUint8
+ case reflect.Uint64:
+ fn.f = (*decFnInfo).kUint64
+ case reflect.Uint:
+ fn.f = (*decFnInfo).kUint
+ case reflect.Uint32:
+ fn.f = (*decFnInfo).kUint32
+ case reflect.Uint16:
+ fn.f = (*decFnInfo).kUint16
+ // case reflect.Ptr:
+ // fn.f = (*decFnInfo).kPtr
+ case reflect.Interface:
+ fn.f = (*decFnInfo).kInterface
+ case reflect.Struct:
+ fn.f = (*decFnInfo).kStruct
+ case reflect.Slice:
+ fn.f = (*decFnInfo).kSlice
+ case reflect.Array:
+ fi.array = true
+ fn.f = (*decFnInfo).kArray
+ case reflect.Map:
+ fn.f = (*decFnInfo).kMap
+ default:
+ fn.f = (*decFnInfo).kErr
+ }
+ }
+ if useMapForCodecCache {
+ if d.f == nil {
+ d.f = make(map[uintptr]decFn, 16)
+ }
+ d.f[rtid] = fn
+ } else {
+ d.s = append(d.s, fn)
+ d.x = append(d.x, rtid)
+ }
+ }
+
+ fn.f(fn.i, rv)
+
+ return
+}
+
+func (d *Decoder) chkPtrValue(rv reflect.Value) {
+ // We can only decode into a non-nil pointer
+ if rv.Kind() == reflect.Ptr && !rv.IsNil() {
+ return
+ }
+ if !rv.IsValid() {
+ decErr("Cannot decode into a zero (ie invalid) reflect.Value")
+ }
+ if !rv.CanInterface() {
+ decErr("Cannot decode into a value without an interface: %v", rv)
+ }
+ rvi := rv.Interface()
+ decErr("Cannot decode into non-pointer or nil pointer. Got: %v, %T, %v",
+ rv.Kind(), rvi, rvi)
+}
+
+func (d *Decoder) decEmbeddedField(rv reflect.Value, index []int) {
+ // d.decodeValue(rv.FieldByIndex(index))
+ // nil pointers may be here; so reproduce FieldByIndex logic + enhancements
+ for _, j := range index {
+ if rv.Kind() == reflect.Ptr {
+ if rv.IsNil() {
+ rv.Set(reflect.New(rv.Type().Elem()))
+ }
+ // If a pointer, it must be a pointer to struct (based on typeInfo contract)
+ rv = rv.Elem()
+ }
+ rv = rv.Field(j)
+ }
+ d.decodeValue(rv)
+}
+
+// --------------------------------------------------
+
+// short circuit functions for common maps and slices
+
+func (d *Decoder) decSliceIntf(v *[]interface{}, currEncodedType valueType, doNotReset bool) {
+ _, containerLenS := decContLens(d.d, currEncodedType)
+ s := *v
+ if s == nil {
+ s = make([]interface{}, containerLenS, containerLenS)
+ } else if containerLenS > cap(s) {
+ if doNotReset {
+ decErr(msgDecCannotExpandArr, cap(s), containerLenS)
+ }
+ s = make([]interface{}, containerLenS, containerLenS)
+ copy(s, *v)
+ } else if containerLenS > len(s) {
+ s = s[:containerLenS]
+ }
+ for j := 0; j < containerLenS; j++ {
+ d.decode(&s[j])
+ }
+ *v = s
+}
+
+func (d *Decoder) decSliceInt64(v *[]int64, currEncodedType valueType, doNotReset bool) {
+ _, containerLenS := decContLens(d.d, currEncodedType)
+ s := *v
+ if s == nil {
+ s = make([]int64, containerLenS, containerLenS)
+ } else if containerLenS > cap(s) {
+ if doNotReset {
+ decErr(msgDecCannotExpandArr, cap(s), containerLenS)
+ }
+ s = make([]int64, containerLenS, containerLenS)
+ copy(s, *v)
+ } else if containerLenS > len(s) {
+ s = s[:containerLenS]
+ }
+ for j := 0; j < containerLenS; j++ {
+ // d.decode(&s[j])
+ d.d.initReadNext()
+ s[j] = d.d.decodeInt(intBitsize)
+ }
+ *v = s
+}
+
+func (d *Decoder) decSliceUint64(v *[]uint64, currEncodedType valueType, doNotReset bool) {
+ _, containerLenS := decContLens(d.d, currEncodedType)
+ s := *v
+ if s == nil {
+ s = make([]uint64, containerLenS, containerLenS)
+ } else if containerLenS > cap(s) {
+ if doNotReset {
+ decErr(msgDecCannotExpandArr, cap(s), containerLenS)
+ }
+ s = make([]uint64, containerLenS, containerLenS)
+ copy(s, *v)
+ } else if containerLenS > len(s) {
+ s = s[:containerLenS]
+ }
+ for j := 0; j < containerLenS; j++ {
+ // d.decode(&s[j])
+ d.d.initReadNext()
+ s[j] = d.d.decodeUint(intBitsize)
+ }
+ *v = s
+}
+
+func (d *Decoder) decSliceStr(v *[]string, currEncodedType valueType, doNotReset bool) {
+ _, containerLenS := decContLens(d.d, currEncodedType)
+ s := *v
+ if s == nil {
+ s = make([]string, containerLenS, containerLenS)
+ } else if containerLenS > cap(s) {
+ if doNotReset {
+ decErr(msgDecCannotExpandArr, cap(s), containerLenS)
+ }
+ s = make([]string, containerLenS, containerLenS)
+ copy(s, *v)
+ } else if containerLenS > len(s) {
+ s = s[:containerLenS]
+ }
+ for j := 0; j < containerLenS; j++ {
+ // d.decode(&s[j])
+ d.d.initReadNext()
+ s[j] = d.d.decodeString()
+ }
+ *v = s
+}
+
+func (d *Decoder) decMapIntfIntf(v *map[interface{}]interface{}) {
+ containerLen := d.d.readMapLen()
+ m := *v
+ if m == nil {
+ m = make(map[interface{}]interface{}, containerLen)
+ *v = m
+ }
+ for j := 0; j < containerLen; j++ {
+ var mk interface{}
+ d.decode(&mk)
+ // special case if a byte array.
+ if bv, bok := mk.([]byte); bok {
+ mk = string(bv)
+ }
+ mv := m[mk]
+ d.decode(&mv)
+ m[mk] = mv
+ }
+}
+
+func (d *Decoder) decMapInt64Intf(v *map[int64]interface{}) {
+ containerLen := d.d.readMapLen()
+ m := *v
+ if m == nil {
+ m = make(map[int64]interface{}, containerLen)
+ *v = m
+ }
+ for j := 0; j < containerLen; j++ {
+ d.d.initReadNext()
+ mk := d.d.decodeInt(intBitsize)
+ mv := m[mk]
+ d.decode(&mv)
+ m[mk] = mv
+ }
+}
+
+func (d *Decoder) decMapUint64Intf(v *map[uint64]interface{}) {
+ containerLen := d.d.readMapLen()
+ m := *v
+ if m == nil {
+ m = make(map[uint64]interface{}, containerLen)
+ *v = m
+ }
+ for j := 0; j < containerLen; j++ {
+ d.d.initReadNext()
+ mk := d.d.decodeUint(intBitsize)
+ mv := m[mk]
+ d.decode(&mv)
+ m[mk] = mv
+ }
+}
+
+func (d *Decoder) decMapStrIntf(v *map[string]interface{}) {
+ containerLen := d.d.readMapLen()
+ m := *v
+ if m == nil {
+ m = make(map[string]interface{}, containerLen)
+ *v = m
+ }
+ for j := 0; j < containerLen; j++ {
+ d.d.initReadNext()
+ mk := d.d.decodeString()
+ mv := m[mk]
+ d.decode(&mv)
+ m[mk] = mv
+ }
+}
+
+// ----------------------------------------
+
+func decContLens(dd decDriver, currEncodedType valueType) (containerLen, containerLenS int) {
+ if currEncodedType == valueTypeInvalid {
+ currEncodedType = dd.currentEncodedType()
+ }
+ switch currEncodedType {
+ case valueTypeArray:
+ containerLen = dd.readArrayLen()
+ containerLenS = containerLen
+ case valueTypeMap:
+ containerLen = dd.readMapLen()
+ containerLenS = containerLen * 2
+ default:
+ decErr("Only encoded map or array can be decoded into a slice. (valueType: %0x)",
+ currEncodedType)
+ }
+ return
+}
+
+func decErr(format string, params ...interface{}) {
+ doPanic(msgTagDec, format, params...)
+}
--- /dev/null
+// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a BSD-style license found in the LICENSE file.
+
+package codec
+
+import (
+ "io"
+ "reflect"
+)
+
+const (
+ // Some tagging information for error messages.
+ msgTagEnc = "codec.encoder"
+ defEncByteBufSize = 1 << 6 // 4:16, 6:64, 8:256, 10:1024
+ // maxTimeSecs32 = math.MaxInt32 / 60 / 24 / 366
+)
+
+// AsSymbolFlag defines what should be encoded as symbols.
+type AsSymbolFlag uint8
+
+const (
+ // AsSymbolDefault is default.
+ // Currently, this means only encode struct field names as symbols.
+ // The default is subject to change.
+ AsSymbolDefault AsSymbolFlag = iota
+
+ // AsSymbolAll means encode anything which could be a symbol as a symbol.
+ AsSymbolAll = 0xfe
+
+ // AsSymbolNone means do not encode anything as a symbol.
+ AsSymbolNone = 1 << iota
+
+ // AsSymbolMapStringKeys means encode keys in map[string]XXX as symbols.
+ AsSymbolMapStringKeysFlag
+
+ // AsSymbolStructFieldName means encode struct field names as symbols.
+ AsSymbolStructFieldNameFlag
+)
+
+// encWriter abstracting writing to a byte array or to an io.Writer.
+type encWriter interface {
+ writeUint16(uint16)
+ writeUint32(uint32)
+ writeUint64(uint64)
+ writeb([]byte)
+ writestr(string)
+ writen1(byte)
+ writen2(byte, byte)
+ atEndOfEncode()
+}
+
+// encDriver abstracts the actual codec (binc vs msgpack, etc)
+type encDriver interface {
+ isBuiltinType(rt uintptr) bool
+ encodeBuiltin(rt uintptr, v interface{})
+ encodeNil()
+ encodeInt(i int64)
+ encodeUint(i uint64)
+ encodeBool(b bool)
+ encodeFloat32(f float32)
+ encodeFloat64(f float64)
+ encodeExtPreamble(xtag byte, length int)
+ encodeArrayPreamble(length int)
+ encodeMapPreamble(length int)
+ encodeString(c charEncoding, v string)
+ encodeSymbol(v string)
+ encodeStringBytes(c charEncoding, v []byte)
+ //TODO
+ //encBignum(f *big.Int)
+ //encStringRunes(c charEncoding, v []rune)
+}
+
+type ioEncWriterWriter interface {
+ WriteByte(c byte) error
+ WriteString(s string) (n int, err error)
+ Write(p []byte) (n int, err error)
+}
+
+type ioEncStringWriter interface {
+ WriteString(s string) (n int, err error)
+}
+
+type EncodeOptions struct {
+ // Encode a struct as an array, and not as a map.
+ StructToArray bool
+
+ // AsSymbols defines what should be encoded as symbols.
+ //
+ // Encoding as symbols can reduce the encoded size significantly.
+ //
+ // However, during decoding, each string to be encoded as a symbol must
+ // be checked to see if it has been seen before. Consequently, encoding time
+ // will increase if using symbols, because string comparisons has a clear cost.
+ //
+ // Sample values:
+ // AsSymbolNone
+ // AsSymbolAll
+ // AsSymbolMapStringKeys
+ // AsSymbolMapStringKeysFlag | AsSymbolStructFieldNameFlag
+ AsSymbols AsSymbolFlag
+}
+
+// ---------------------------------------------
+
+type simpleIoEncWriterWriter struct {
+ w io.Writer
+ bw io.ByteWriter
+ sw ioEncStringWriter
+}
+
+func (o *simpleIoEncWriterWriter) WriteByte(c byte) (err error) {
+ if o.bw != nil {
+ return o.bw.WriteByte(c)
+ }
+ _, err = o.w.Write([]byte{c})
+ return
+}
+
+func (o *simpleIoEncWriterWriter) WriteString(s string) (n int, err error) {
+ if o.sw != nil {
+ return o.sw.WriteString(s)
+ }
+ return o.w.Write([]byte(s))
+}
+
+func (o *simpleIoEncWriterWriter) Write(p []byte) (n int, err error) {
+ return o.w.Write(p)
+}
+
+// ----------------------------------------
+
+// ioEncWriter implements encWriter and can write to an io.Writer implementation
+type ioEncWriter struct {
+ w ioEncWriterWriter
+ x [8]byte // temp byte array re-used internally for efficiency
+}
+
+func (z *ioEncWriter) writeUint16(v uint16) {
+ bigen.PutUint16(z.x[:2], v)
+ z.writeb(z.x[:2])
+}
+
+func (z *ioEncWriter) writeUint32(v uint32) {
+ bigen.PutUint32(z.x[:4], v)
+ z.writeb(z.x[:4])
+}
+
+func (z *ioEncWriter) writeUint64(v uint64) {
+ bigen.PutUint64(z.x[:8], v)
+ z.writeb(z.x[:8])
+}
+
+func (z *ioEncWriter) writeb(bs []byte) {
+ if len(bs) == 0 {
+ return
+ }
+ n, err := z.w.Write(bs)
+ if err != nil {
+ panic(err)
+ }
+ if n != len(bs) {
+ encErr("write: Incorrect num bytes written. Expecting: %v, Wrote: %v", len(bs), n)
+ }
+}
+
+func (z *ioEncWriter) writestr(s string) {
+ n, err := z.w.WriteString(s)
+ if err != nil {
+ panic(err)
+ }
+ if n != len(s) {
+ encErr("write: Incorrect num bytes written. Expecting: %v, Wrote: %v", len(s), n)
+ }
+}
+
+func (z *ioEncWriter) writen1(b byte) {
+ if err := z.w.WriteByte(b); err != nil {
+ panic(err)
+ }
+}
+
+func (z *ioEncWriter) writen2(b1 byte, b2 byte) {
+ z.writen1(b1)
+ z.writen1(b2)
+}
+
+func (z *ioEncWriter) atEndOfEncode() {}
+
+// ----------------------------------------
+
+// bytesEncWriter implements encWriter and can write to an byte slice.
+// It is used by Marshal function.
+type bytesEncWriter struct {
+ b []byte
+ c int // cursor
+ out *[]byte // write out on atEndOfEncode
+}
+
+func (z *bytesEncWriter) writeUint16(v uint16) {
+ c := z.grow(2)
+ z.b[c] = byte(v >> 8)
+ z.b[c+1] = byte(v)
+}
+
+func (z *bytesEncWriter) writeUint32(v uint32) {
+ c := z.grow(4)
+ z.b[c] = byte(v >> 24)
+ z.b[c+1] = byte(v >> 16)
+ z.b[c+2] = byte(v >> 8)
+ z.b[c+3] = byte(v)
+}
+
+func (z *bytesEncWriter) writeUint64(v uint64) {
+ c := z.grow(8)
+ z.b[c] = byte(v >> 56)
+ z.b[c+1] = byte(v >> 48)
+ z.b[c+2] = byte(v >> 40)
+ z.b[c+3] = byte(v >> 32)
+ z.b[c+4] = byte(v >> 24)
+ z.b[c+5] = byte(v >> 16)
+ z.b[c+6] = byte(v >> 8)
+ z.b[c+7] = byte(v)
+}
+
+func (z *bytesEncWriter) writeb(s []byte) {
+ if len(s) == 0 {
+ return
+ }
+ c := z.grow(len(s))
+ copy(z.b[c:], s)
+}
+
+func (z *bytesEncWriter) writestr(s string) {
+ c := z.grow(len(s))
+ copy(z.b[c:], s)
+}
+
+func (z *bytesEncWriter) writen1(b1 byte) {
+ c := z.grow(1)
+ z.b[c] = b1
+}
+
+func (z *bytesEncWriter) writen2(b1 byte, b2 byte) {
+ c := z.grow(2)
+ z.b[c] = b1
+ z.b[c+1] = b2
+}
+
+func (z *bytesEncWriter) atEndOfEncode() {
+ *(z.out) = z.b[:z.c]
+}
+
+func (z *bytesEncWriter) grow(n int) (oldcursor int) {
+ oldcursor = z.c
+ z.c = oldcursor + n
+ if z.c > cap(z.b) {
+ // Tried using appendslice logic: (if cap < 1024, *2, else *1.25).
+ // However, it was too expensive, causing too many iterations of copy.
+ // Using bytes.Buffer model was much better (2*cap + n)
+ bs := make([]byte, 2*cap(z.b)+n)
+ copy(bs, z.b[:oldcursor])
+ z.b = bs
+ } else if z.c > len(z.b) {
+ z.b = z.b[:cap(z.b)]
+ }
+ return
+}
+
+// ---------------------------------------------
+
+type encFnInfo struct {
+ ti *typeInfo
+ e *Encoder
+ ee encDriver
+ xfFn func(reflect.Value) ([]byte, error)
+ xfTag byte
+}
+
+func (f *encFnInfo) builtin(rv reflect.Value) {
+ f.ee.encodeBuiltin(f.ti.rtid, rv.Interface())
+}
+
+func (f *encFnInfo) rawExt(rv reflect.Value) {
+ f.e.encRawExt(rv.Interface().(RawExt))
+}
+
+func (f *encFnInfo) ext(rv reflect.Value) {
+ bs, fnerr := f.xfFn(rv)
+ if fnerr != nil {
+ panic(fnerr)
+ }
+ if bs == nil {
+ f.ee.encodeNil()
+ return
+ }
+ if f.e.hh.writeExt() {
+ f.ee.encodeExtPreamble(f.xfTag, len(bs))
+ f.e.w.writeb(bs)
+ } else {
+ f.ee.encodeStringBytes(c_RAW, bs)
+ }
+
+}
+
+func (f *encFnInfo) binaryMarshal(rv reflect.Value) {
+ var bm binaryMarshaler
+ if f.ti.mIndir == 0 {
+ bm = rv.Interface().(binaryMarshaler)
+ } else if f.ti.mIndir == -1 {
+ bm = rv.Addr().Interface().(binaryMarshaler)
+ } else {
+ for j, k := int8(0), f.ti.mIndir; j < k; j++ {
+ if rv.IsNil() {
+ f.ee.encodeNil()
+ return
+ }
+ rv = rv.Elem()
+ }
+ bm = rv.Interface().(binaryMarshaler)
+ }
+ // debugf(">>>> binaryMarshaler: %T", rv.Interface())
+ bs, fnerr := bm.MarshalBinary()
+ if fnerr != nil {
+ panic(fnerr)
+ }
+ if bs == nil {
+ f.ee.encodeNil()
+ } else {
+ f.ee.encodeStringBytes(c_RAW, bs)
+ }
+}
+
+func (f *encFnInfo) kBool(rv reflect.Value) {
+ f.ee.encodeBool(rv.Bool())
+}
+
+func (f *encFnInfo) kString(rv reflect.Value) {
+ f.ee.encodeString(c_UTF8, rv.String())
+}
+
+func (f *encFnInfo) kFloat64(rv reflect.Value) {
+ f.ee.encodeFloat64(rv.Float())
+}
+
+func (f *encFnInfo) kFloat32(rv reflect.Value) {
+ f.ee.encodeFloat32(float32(rv.Float()))
+}
+
+func (f *encFnInfo) kInt(rv reflect.Value) {
+ f.ee.encodeInt(rv.Int())
+}
+
+func (f *encFnInfo) kUint(rv reflect.Value) {
+ f.ee.encodeUint(rv.Uint())
+}
+
+func (f *encFnInfo) kInvalid(rv reflect.Value) {
+ f.ee.encodeNil()
+}
+
+func (f *encFnInfo) kErr(rv reflect.Value) {
+ encErr("Unsupported kind: %s, for: %#v", rv.Kind(), rv)
+}
+
+func (f *encFnInfo) kSlice(rv reflect.Value) {
+ if rv.IsNil() {
+ f.ee.encodeNil()
+ return
+ }
+
+ if shortCircuitReflectToFastPath {
+ switch f.ti.rtid {
+ case intfSliceTypId:
+ f.e.encSliceIntf(rv.Interface().([]interface{}))
+ return
+ case strSliceTypId:
+ f.e.encSliceStr(rv.Interface().([]string))
+ return
+ case uint64SliceTypId:
+ f.e.encSliceUint64(rv.Interface().([]uint64))
+ return
+ case int64SliceTypId:
+ f.e.encSliceInt64(rv.Interface().([]int64))
+ return
+ }
+ }
+
+ // If in this method, then there was no extension function defined.
+ // So it's okay to treat as []byte.
+ if f.ti.rtid == uint8SliceTypId || f.ti.rt.Elem().Kind() == reflect.Uint8 {
+ f.ee.encodeStringBytes(c_RAW, rv.Bytes())
+ return
+ }
+
+ l := rv.Len()
+ if f.ti.mbs {
+ if l%2 == 1 {
+ encErr("mapBySlice: invalid length (must be divisible by 2): %v", l)
+ }
+ f.ee.encodeMapPreamble(l / 2)
+ } else {
+ f.ee.encodeArrayPreamble(l)
+ }
+ if l == 0 {
+ return
+ }
+ for j := 0; j < l; j++ {
+ // TODO: Consider perf implication of encoding odd index values as symbols if type is string
+ f.e.encodeValue(rv.Index(j))
+ }
+}
+
+func (f *encFnInfo) kArray(rv reflect.Value) {
+ // We cannot share kSlice method, because the array may be non-addressable.
+ // E.g. type struct S{B [2]byte}; Encode(S{}) will bomb on "panic: slice of unaddressable array".
+ // So we have to duplicate the functionality here.
+ // f.e.encodeValue(rv.Slice(0, rv.Len()))
+ // f.kSlice(rv.Slice(0, rv.Len()))
+
+ l := rv.Len()
+ // Handle an array of bytes specially (in line with what is done for slices)
+ if f.ti.rt.Elem().Kind() == reflect.Uint8 {
+ if l == 0 {
+ f.ee.encodeStringBytes(c_RAW, nil)
+ return
+ }
+ var bs []byte
+ if rv.CanAddr() {
+ bs = rv.Slice(0, l).Bytes()
+ } else {
+ bs = make([]byte, l)
+ for i := 0; i < l; i++ {
+ bs[i] = byte(rv.Index(i).Uint())
+ }
+ }
+ f.ee.encodeStringBytes(c_RAW, bs)
+ return
+ }
+
+ if f.ti.mbs {
+ if l%2 == 1 {
+ encErr("mapBySlice: invalid length (must be divisible by 2): %v", l)
+ }
+ f.ee.encodeMapPreamble(l / 2)
+ } else {
+ f.ee.encodeArrayPreamble(l)
+ }
+ if l == 0 {
+ return
+ }
+ for j := 0; j < l; j++ {
+ // TODO: Consider perf implication of encoding odd index values as symbols if type is string
+ f.e.encodeValue(rv.Index(j))
+ }
+}
+
+func (f *encFnInfo) kStruct(rv reflect.Value) {
+ fti := f.ti
+ newlen := len(fti.sfi)
+ rvals := make([]reflect.Value, newlen)
+ var encnames []string
+ e := f.e
+ tisfi := fti.sfip
+ toMap := !(fti.toArray || e.h.StructToArray)
+ // if toMap, use the sorted array. If toArray, use unsorted array (to match sequence in struct)
+ if toMap {
+ tisfi = fti.sfi
+ encnames = make([]string, newlen)
+ }
+ newlen = 0
+ for _, si := range tisfi {
+ if si.i != -1 {
+ rvals[newlen] = rv.Field(int(si.i))
+ } else {
+ rvals[newlen] = rv.FieldByIndex(si.is)
+ }
+ if toMap {
+ if si.omitEmpty && isEmptyValue(rvals[newlen]) {
+ continue
+ }
+ encnames[newlen] = si.encName
+ } else {
+ if si.omitEmpty && isEmptyValue(rvals[newlen]) {
+ rvals[newlen] = reflect.Value{} //encode as nil
+ }
+ }
+ newlen++
+ }
+
+ // debugf(">>>> kStruct: newlen: %v", newlen)
+ if toMap {
+ ee := f.ee //don't dereference everytime
+ ee.encodeMapPreamble(newlen)
+ // asSymbols := e.h.AsSymbols&AsSymbolStructFieldNameFlag != 0
+ asSymbols := e.h.AsSymbols == AsSymbolDefault || e.h.AsSymbols&AsSymbolStructFieldNameFlag != 0
+ for j := 0; j < newlen; j++ {
+ if asSymbols {
+ ee.encodeSymbol(encnames[j])
+ } else {
+ ee.encodeString(c_UTF8, encnames[j])
+ }
+ e.encodeValue(rvals[j])
+ }
+ } else {
+ f.ee.encodeArrayPreamble(newlen)
+ for j := 0; j < newlen; j++ {
+ e.encodeValue(rvals[j])
+ }
+ }
+}
+
+// func (f *encFnInfo) kPtr(rv reflect.Value) {
+// debugf(">>>>>>> ??? encode kPtr called - shouldn't get called")
+// if rv.IsNil() {
+// f.ee.encodeNil()
+// return
+// }
+// f.e.encodeValue(rv.Elem())
+// }
+
+func (f *encFnInfo) kInterface(rv reflect.Value) {
+ if rv.IsNil() {
+ f.ee.encodeNil()
+ return
+ }
+ f.e.encodeValue(rv.Elem())
+}
+
+func (f *encFnInfo) kMap(rv reflect.Value) {
+ if rv.IsNil() {
+ f.ee.encodeNil()
+ return
+ }
+
+ if shortCircuitReflectToFastPath {
+ switch f.ti.rtid {
+ case mapIntfIntfTypId:
+ f.e.encMapIntfIntf(rv.Interface().(map[interface{}]interface{}))
+ return
+ case mapStrIntfTypId:
+ f.e.encMapStrIntf(rv.Interface().(map[string]interface{}))
+ return
+ case mapStrStrTypId:
+ f.e.encMapStrStr(rv.Interface().(map[string]string))
+ return
+ case mapInt64IntfTypId:
+ f.e.encMapInt64Intf(rv.Interface().(map[int64]interface{}))
+ return
+ case mapUint64IntfTypId:
+ f.e.encMapUint64Intf(rv.Interface().(map[uint64]interface{}))
+ return
+ }
+ }
+
+ l := rv.Len()
+ f.ee.encodeMapPreamble(l)
+ if l == 0 {
+ return
+ }
+ // keyTypeIsString := f.ti.rt.Key().Kind() == reflect.String
+ keyTypeIsString := f.ti.rt.Key() == stringTyp
+ var asSymbols bool
+ if keyTypeIsString {
+ asSymbols = f.e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0
+ }
+ mks := rv.MapKeys()
+ // for j, lmks := 0, len(mks); j < lmks; j++ {
+ for j := range mks {
+ if keyTypeIsString {
+ if asSymbols {
+ f.ee.encodeSymbol(mks[j].String())
+ } else {
+ f.ee.encodeString(c_UTF8, mks[j].String())
+ }
+ } else {
+ f.e.encodeValue(mks[j])
+ }
+ f.e.encodeValue(rv.MapIndex(mks[j]))
+ }
+
+}
+
+// --------------------------------------------------
+
+// encFn encapsulates the captured variables and the encode function.
+// This way, we only do some calculations one times, and pass to the
+// code block that should be called (encapsulated in a function)
+// instead of executing the checks every time.
+type encFn struct {
+ i *encFnInfo
+ f func(*encFnInfo, reflect.Value)
+}
+
+// --------------------------------------------------
+
+// An Encoder writes an object to an output stream in the codec format.
+type Encoder struct {
+ w encWriter
+ e encDriver
+ h *BasicHandle
+ hh Handle
+ f map[uintptr]encFn
+ x []uintptr
+ s []encFn
+}
+
+// NewEncoder returns an Encoder for encoding into an io.Writer.
+//
+// For efficiency, Users are encouraged to pass in a memory buffered writer
+// (eg bufio.Writer, bytes.Buffer).
+func NewEncoder(w io.Writer, h Handle) *Encoder {
+ ww, ok := w.(ioEncWriterWriter)
+ if !ok {
+ sww := simpleIoEncWriterWriter{w: w}
+ sww.bw, _ = w.(io.ByteWriter)
+ sww.sw, _ = w.(ioEncStringWriter)
+ ww = &sww
+ //ww = bufio.NewWriterSize(w, defEncByteBufSize)
+ }
+ z := ioEncWriter{
+ w: ww,
+ }
+ return &Encoder{w: &z, hh: h, h: h.getBasicHandle(), e: h.newEncDriver(&z)}
+}
+
+// NewEncoderBytes returns an encoder for encoding directly and efficiently
+// into a byte slice, using zero-copying to temporary slices.
+//
+// It will potentially replace the output byte slice pointed to.
+// After encoding, the out parameter contains the encoded contents.
+func NewEncoderBytes(out *[]byte, h Handle) *Encoder {
+ in := *out
+ if in == nil {
+ in = make([]byte, defEncByteBufSize)
+ }
+ z := bytesEncWriter{
+ b: in,
+ out: out,
+ }
+ return &Encoder{w: &z, hh: h, h: h.getBasicHandle(), e: h.newEncDriver(&z)}
+}
+
+// Encode writes an object into a stream in the codec format.
+//
+// Encoding can be configured via the "codec" struct tag for the fields.
+//
+// The "codec" key in struct field's tag value is the key name,
+// followed by an optional comma and options.
+//
+// To set an option on all fields (e.g. omitempty on all fields), you
+// can create a field called _struct, and set flags on it.
+//
+// Struct values "usually" encode as maps. Each exported struct field is encoded unless:
+// - the field's codec tag is "-", OR
+// - the field is empty and its codec tag specifies the "omitempty" option.
+//
+// When encoding as a map, the first string in the tag (before the comma)
+// is the map key string to use when encoding.
+//
+// However, struct values may encode as arrays. This happens when:
+// - StructToArray Encode option is set, OR
+// - the codec tag on the _struct field sets the "toarray" option
+//
+// Values with types that implement MapBySlice are encoded as stream maps.
+//
+// The empty values (for omitempty option) are false, 0, any nil pointer
+// or interface value, and any array, slice, map, or string of length zero.
+//
+// Anonymous fields are encoded inline if no struct tag is present.
+// Else they are encoded as regular fields.
+//
+// Examples:
+//
+// type MyStruct struct {
+// _struct bool `codec:",omitempty"` //set omitempty for every field
+// Field1 string `codec:"-"` //skip this field
+// Field2 int `codec:"myName"` //Use key "myName" in encode stream
+// Field3 int32 `codec:",omitempty"` //use key "Field3". Omit if empty.
+// Field4 bool `codec:"f4,omitempty"` //use key "f4". Omit if empty.
+// ...
+// }
+//
+// type MyStruct struct {
+// _struct bool `codec:",omitempty,toarray"` //set omitempty for every field
+// //and encode struct as an array
+// }
+//
+// The mode of encoding is based on the type of the value. When a value is seen:
+// - If an extension is registered for it, call that extension function
+// - If it implements BinaryMarshaler, call its MarshalBinary() (data []byte, err error)
+// - Else encode it based on its reflect.Kind
+//
+// Note that struct field names and keys in map[string]XXX will be treated as symbols.
+// Some formats support symbols (e.g. binc) and will properly encode the string
+// only once in the stream, and use a tag to refer to it thereafter.
+func (e *Encoder) Encode(v interface{}) (err error) {
+ defer panicToErr(&err)
+ e.encode(v)
+ e.w.atEndOfEncode()
+ return
+}
+
+func (e *Encoder) encode(iv interface{}) {
+ switch v := iv.(type) {
+ case nil:
+ e.e.encodeNil()
+
+ case reflect.Value:
+ e.encodeValue(v)
+
+ case string:
+ e.e.encodeString(c_UTF8, v)
+ case bool:
+ e.e.encodeBool(v)
+ case int:
+ e.e.encodeInt(int64(v))
+ case int8:
+ e.e.encodeInt(int64(v))
+ case int16:
+ e.e.encodeInt(int64(v))
+ case int32:
+ e.e.encodeInt(int64(v))
+ case int64:
+ e.e.encodeInt(v)
+ case uint:
+ e.e.encodeUint(uint64(v))
+ case uint8:
+ e.e.encodeUint(uint64(v))
+ case uint16:
+ e.e.encodeUint(uint64(v))
+ case uint32:
+ e.e.encodeUint(uint64(v))
+ case uint64:
+ e.e.encodeUint(v)
+ case float32:
+ e.e.encodeFloat32(v)
+ case float64:
+ e.e.encodeFloat64(v)
+
+ case []interface{}:
+ e.encSliceIntf(v)
+ case []string:
+ e.encSliceStr(v)
+ case []int64:
+ e.encSliceInt64(v)
+ case []uint64:
+ e.encSliceUint64(v)
+ case []uint8:
+ e.e.encodeStringBytes(c_RAW, v)
+
+ case map[interface{}]interface{}:
+ e.encMapIntfIntf(v)
+ case map[string]interface{}:
+ e.encMapStrIntf(v)
+ case map[string]string:
+ e.encMapStrStr(v)
+ case map[int64]interface{}:
+ e.encMapInt64Intf(v)
+ case map[uint64]interface{}:
+ e.encMapUint64Intf(v)
+
+ case *string:
+ e.e.encodeString(c_UTF8, *v)
+ case *bool:
+ e.e.encodeBool(*v)
+ case *int:
+ e.e.encodeInt(int64(*v))
+ case *int8:
+ e.e.encodeInt(int64(*v))
+ case *int16:
+ e.e.encodeInt(int64(*v))
+ case *int32:
+ e.e.encodeInt(int64(*v))
+ case *int64:
+ e.e.encodeInt(*v)
+ case *uint:
+ e.e.encodeUint(uint64(*v))
+ case *uint8:
+ e.e.encodeUint(uint64(*v))
+ case *uint16:
+ e.e.encodeUint(uint64(*v))
+ case *uint32:
+ e.e.encodeUint(uint64(*v))
+ case *uint64:
+ e.e.encodeUint(*v)
+ case *float32:
+ e.e.encodeFloat32(*v)
+ case *float64:
+ e.e.encodeFloat64(*v)
+
+ case *[]interface{}:
+ e.encSliceIntf(*v)
+ case *[]string:
+ e.encSliceStr(*v)
+ case *[]int64:
+ e.encSliceInt64(*v)
+ case *[]uint64:
+ e.encSliceUint64(*v)
+ case *[]uint8:
+ e.e.encodeStringBytes(c_RAW, *v)
+
+ case *map[interface{}]interface{}:
+ e.encMapIntfIntf(*v)
+ case *map[string]interface{}:
+ e.encMapStrIntf(*v)
+ case *map[string]string:
+ e.encMapStrStr(*v)
+ case *map[int64]interface{}:
+ e.encMapInt64Intf(*v)
+ case *map[uint64]interface{}:
+ e.encMapUint64Intf(*v)
+
+ default:
+ e.encodeValue(reflect.ValueOf(iv))
+ }
+}
+
+func (e *Encoder) encodeValue(rv reflect.Value) {
+ for rv.Kind() == reflect.Ptr {
+ if rv.IsNil() {
+ e.e.encodeNil()
+ return
+ }
+ rv = rv.Elem()
+ }
+
+ rt := rv.Type()
+ rtid := reflect.ValueOf(rt).Pointer()
+
+ // if e.f == nil && e.s == nil { debugf("---->Creating new enc f map for type: %v\n", rt) }
+ var fn encFn
+ var ok bool
+ if useMapForCodecCache {
+ fn, ok = e.f[rtid]
+ } else {
+ for i, v := range e.x {
+ if v == rtid {
+ fn, ok = e.s[i], true
+ break
+ }
+ }
+ }
+ if !ok {
+ // debugf("\tCreating new enc fn for type: %v\n", rt)
+ fi := encFnInfo{ti: getTypeInfo(rtid, rt), e: e, ee: e.e}
+ fn.i = &fi
+ if rtid == rawExtTypId {
+ fn.f = (*encFnInfo).rawExt
+ } else if e.e.isBuiltinType(rtid) {
+ fn.f = (*encFnInfo).builtin
+ } else if xfTag, xfFn := e.h.getEncodeExt(rtid); xfFn != nil {
+ fi.xfTag, fi.xfFn = xfTag, xfFn
+ fn.f = (*encFnInfo).ext
+ } else if supportBinaryMarshal && fi.ti.m {
+ fn.f = (*encFnInfo).binaryMarshal
+ } else {
+ switch rk := rt.Kind(); rk {
+ case reflect.Bool:
+ fn.f = (*encFnInfo).kBool
+ case reflect.String:
+ fn.f = (*encFnInfo).kString
+ case reflect.Float64:
+ fn.f = (*encFnInfo).kFloat64
+ case reflect.Float32:
+ fn.f = (*encFnInfo).kFloat32
+ case reflect.Int, reflect.Int8, reflect.Int64, reflect.Int32, reflect.Int16:
+ fn.f = (*encFnInfo).kInt
+ case reflect.Uint8, reflect.Uint64, reflect.Uint, reflect.Uint32, reflect.Uint16:
+ fn.f = (*encFnInfo).kUint
+ case reflect.Invalid:
+ fn.f = (*encFnInfo).kInvalid
+ case reflect.Slice:
+ fn.f = (*encFnInfo).kSlice
+ case reflect.Array:
+ fn.f = (*encFnInfo).kArray
+ case reflect.Struct:
+ fn.f = (*encFnInfo).kStruct
+ // case reflect.Ptr:
+ // fn.f = (*encFnInfo).kPtr
+ case reflect.Interface:
+ fn.f = (*encFnInfo).kInterface
+ case reflect.Map:
+ fn.f = (*encFnInfo).kMap
+ default:
+ fn.f = (*encFnInfo).kErr
+ }
+ }
+ if useMapForCodecCache {
+ if e.f == nil {
+ e.f = make(map[uintptr]encFn, 16)
+ }
+ e.f[rtid] = fn
+ } else {
+ e.s = append(e.s, fn)
+ e.x = append(e.x, rtid)
+ }
+ }
+
+ fn.f(fn.i, rv)
+
+}
+
+func (e *Encoder) encRawExt(re RawExt) {
+ if re.Data == nil {
+ e.e.encodeNil()
+ return
+ }
+ if e.hh.writeExt() {
+ e.e.encodeExtPreamble(re.Tag, len(re.Data))
+ e.w.writeb(re.Data)
+ } else {
+ e.e.encodeStringBytes(c_RAW, re.Data)
+ }
+}
+
+// ---------------------------------------------
+// short circuit functions for common maps and slices
+
+func (e *Encoder) encSliceIntf(v []interface{}) {
+ e.e.encodeArrayPreamble(len(v))
+ for _, v2 := range v {
+ e.encode(v2)
+ }
+}
+
+func (e *Encoder) encSliceStr(v []string) {
+ e.e.encodeArrayPreamble(len(v))
+ for _, v2 := range v {
+ e.e.encodeString(c_UTF8, v2)
+ }
+}
+
+func (e *Encoder) encSliceInt64(v []int64) {
+ e.e.encodeArrayPreamble(len(v))
+ for _, v2 := range v {
+ e.e.encodeInt(v2)
+ }
+}
+
+func (e *Encoder) encSliceUint64(v []uint64) {
+ e.e.encodeArrayPreamble(len(v))
+ for _, v2 := range v {
+ e.e.encodeUint(v2)
+ }
+}
+
+func (e *Encoder) encMapStrStr(v map[string]string) {
+ e.e.encodeMapPreamble(len(v))
+ asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0
+ for k2, v2 := range v {
+ if asSymbols {
+ e.e.encodeSymbol(k2)
+ } else {
+ e.e.encodeString(c_UTF8, k2)
+ }
+ e.e.encodeString(c_UTF8, v2)
+ }
+}
+
+func (e *Encoder) encMapStrIntf(v map[string]interface{}) {
+ e.e.encodeMapPreamble(len(v))
+ asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0
+ for k2, v2 := range v {
+ if asSymbols {
+ e.e.encodeSymbol(k2)
+ } else {
+ e.e.encodeString(c_UTF8, k2)
+ }
+ e.encode(v2)
+ }
+}
+
+func (e *Encoder) encMapInt64Intf(v map[int64]interface{}) {
+ e.e.encodeMapPreamble(len(v))
+ for k2, v2 := range v {
+ e.e.encodeInt(k2)
+ e.encode(v2)
+ }
+}
+
+func (e *Encoder) encMapUint64Intf(v map[uint64]interface{}) {
+ e.e.encodeMapPreamble(len(v))
+ for k2, v2 := range v {
+ e.e.encodeUint(uint64(k2))
+ e.encode(v2)
+ }
+}
+
+func (e *Encoder) encMapIntfIntf(v map[interface{}]interface{}) {
+ e.e.encodeMapPreamble(len(v))
+ for k2, v2 := range v {
+ e.encode(k2)
+ e.encode(v2)
+ }
+}
+
+// ----------------------------------------
+
+func encErr(format string, params ...interface{}) {
+ doPanic(msgTagEnc, format, params...)
+}
--- /dev/null
+// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a BSD-style license found in the LICENSE file.
+
+package codec
+
+// Contains code shared by both encode and decode.
+
+import (
+ "encoding/binary"
+ "fmt"
+ "math"
+ "reflect"
+ "sort"
+ "strings"
+ "sync"
+ "time"
+ "unicode"
+ "unicode/utf8"
+)
+
+const (
+ structTagName = "codec"
+
+ // Support
+ // encoding.BinaryMarshaler: MarshalBinary() (data []byte, err error)
+ // encoding.BinaryUnmarshaler: UnmarshalBinary(data []byte) error
+ // This constant flag will enable or disable it.
+ supportBinaryMarshal = true
+
+ // Each Encoder or Decoder uses a cache of functions based on conditionals,
+ // so that the conditionals are not run every time.
+ //
+ // Either a map or a slice is used to keep track of the functions.
+ // The map is more natural, but has a higher cost than a slice/array.
+ // This flag (useMapForCodecCache) controls which is used.
+ useMapForCodecCache = false
+
+ // For some common container types, we can short-circuit an elaborate
+ // reflection dance and call encode/decode directly.
+ // The currently supported types are:
+ // - slices of strings, or id's (int64,uint64) or interfaces.
+ // - maps of str->str, str->intf, id(int64,uint64)->intf, intf->intf
+ shortCircuitReflectToFastPath = true
+
+ // for debugging, set this to false, to catch panic traces.
+ // Note that this will always cause rpc tests to fail, since they need io.EOF sent via panic.
+ recoverPanicToErr = true
+)
+
+type charEncoding uint8
+
+const (
+ c_RAW charEncoding = iota
+ c_UTF8
+ c_UTF16LE
+ c_UTF16BE
+ c_UTF32LE
+ c_UTF32BE
+)
+
+// valueType is the stream type
+type valueType uint8
+
+const (
+ valueTypeUnset valueType = iota
+ valueTypeNil
+ valueTypeInt
+ valueTypeUint
+ valueTypeFloat
+ valueTypeBool
+ valueTypeString
+ valueTypeSymbol
+ valueTypeBytes
+ valueTypeMap
+ valueTypeArray
+ valueTypeTimestamp
+ valueTypeExt
+
+ valueTypeInvalid = 0xff
+)
+
+var (
+ bigen = binary.BigEndian
+ structInfoFieldName = "_struct"
+
+ cachedTypeInfo = make(map[uintptr]*typeInfo, 4)
+ cachedTypeInfoMutex sync.RWMutex
+
+ intfSliceTyp = reflect.TypeOf([]interface{}(nil))
+ intfTyp = intfSliceTyp.Elem()
+
+ strSliceTyp = reflect.TypeOf([]string(nil))
+ boolSliceTyp = reflect.TypeOf([]bool(nil))
+ uintSliceTyp = reflect.TypeOf([]uint(nil))
+ uint8SliceTyp = reflect.TypeOf([]uint8(nil))
+ uint16SliceTyp = reflect.TypeOf([]uint16(nil))
+ uint32SliceTyp = reflect.TypeOf([]uint32(nil))
+ uint64SliceTyp = reflect.TypeOf([]uint64(nil))
+ intSliceTyp = reflect.TypeOf([]int(nil))
+ int8SliceTyp = reflect.TypeOf([]int8(nil))
+ int16SliceTyp = reflect.TypeOf([]int16(nil))
+ int32SliceTyp = reflect.TypeOf([]int32(nil))
+ int64SliceTyp = reflect.TypeOf([]int64(nil))
+ float32SliceTyp = reflect.TypeOf([]float32(nil))
+ float64SliceTyp = reflect.TypeOf([]float64(nil))
+
+ mapIntfIntfTyp = reflect.TypeOf(map[interface{}]interface{}(nil))
+ mapStrIntfTyp = reflect.TypeOf(map[string]interface{}(nil))
+ mapStrStrTyp = reflect.TypeOf(map[string]string(nil))
+
+ mapIntIntfTyp = reflect.TypeOf(map[int]interface{}(nil))
+ mapInt64IntfTyp = reflect.TypeOf(map[int64]interface{}(nil))
+ mapUintIntfTyp = reflect.TypeOf(map[uint]interface{}(nil))
+ mapUint64IntfTyp = reflect.TypeOf(map[uint64]interface{}(nil))
+
+ stringTyp = reflect.TypeOf("")
+ timeTyp = reflect.TypeOf(time.Time{})
+ rawExtTyp = reflect.TypeOf(RawExt{})
+
+ mapBySliceTyp = reflect.TypeOf((*MapBySlice)(nil)).Elem()
+ binaryMarshalerTyp = reflect.TypeOf((*binaryMarshaler)(nil)).Elem()
+ binaryUnmarshalerTyp = reflect.TypeOf((*binaryUnmarshaler)(nil)).Elem()
+
+ rawExtTypId = reflect.ValueOf(rawExtTyp).Pointer()
+ intfTypId = reflect.ValueOf(intfTyp).Pointer()
+ timeTypId = reflect.ValueOf(timeTyp).Pointer()
+
+ intfSliceTypId = reflect.ValueOf(intfSliceTyp).Pointer()
+ strSliceTypId = reflect.ValueOf(strSliceTyp).Pointer()
+
+ boolSliceTypId = reflect.ValueOf(boolSliceTyp).Pointer()
+ uintSliceTypId = reflect.ValueOf(uintSliceTyp).Pointer()
+ uint8SliceTypId = reflect.ValueOf(uint8SliceTyp).Pointer()
+ uint16SliceTypId = reflect.ValueOf(uint16SliceTyp).Pointer()
+ uint32SliceTypId = reflect.ValueOf(uint32SliceTyp).Pointer()
+ uint64SliceTypId = reflect.ValueOf(uint64SliceTyp).Pointer()
+ intSliceTypId = reflect.ValueOf(intSliceTyp).Pointer()
+ int8SliceTypId = reflect.ValueOf(int8SliceTyp).Pointer()
+ int16SliceTypId = reflect.ValueOf(int16SliceTyp).Pointer()
+ int32SliceTypId = reflect.ValueOf(int32SliceTyp).Pointer()
+ int64SliceTypId = reflect.ValueOf(int64SliceTyp).Pointer()
+ float32SliceTypId = reflect.ValueOf(float32SliceTyp).Pointer()
+ float64SliceTypId = reflect.ValueOf(float64SliceTyp).Pointer()
+
+ mapStrStrTypId = reflect.ValueOf(mapStrStrTyp).Pointer()
+ mapIntfIntfTypId = reflect.ValueOf(mapIntfIntfTyp).Pointer()
+ mapStrIntfTypId = reflect.ValueOf(mapStrIntfTyp).Pointer()
+ mapIntIntfTypId = reflect.ValueOf(mapIntIntfTyp).Pointer()
+ mapInt64IntfTypId = reflect.ValueOf(mapInt64IntfTyp).Pointer()
+ mapUintIntfTypId = reflect.ValueOf(mapUintIntfTyp).Pointer()
+ mapUint64IntfTypId = reflect.ValueOf(mapUint64IntfTyp).Pointer()
+ // Id = reflect.ValueOf().Pointer()
+ // mapBySliceTypId = reflect.ValueOf(mapBySliceTyp).Pointer()
+
+ binaryMarshalerTypId = reflect.ValueOf(binaryMarshalerTyp).Pointer()
+ binaryUnmarshalerTypId = reflect.ValueOf(binaryUnmarshalerTyp).Pointer()
+
+ intBitsize uint8 = uint8(reflect.TypeOf(int(0)).Bits())
+ uintBitsize uint8 = uint8(reflect.TypeOf(uint(0)).Bits())
+
+ bsAll0x00 = []byte{0, 0, 0, 0, 0, 0, 0, 0}
+ bsAll0xff = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+)
+
+type binaryUnmarshaler interface {
+ UnmarshalBinary(data []byte) error
+}
+
+type binaryMarshaler interface {
+ MarshalBinary() (data []byte, err error)
+}
+
+// MapBySlice represents a slice which should be encoded as a map in the stream.
+// The slice contains a sequence of key-value pairs.
+type MapBySlice interface {
+ MapBySlice()
+}
+
+// WARNING: DO NOT USE DIRECTLY. EXPORTED FOR GODOC BENEFIT. WILL BE REMOVED.
+//
+// BasicHandle encapsulates the common options and extension functions.
+type BasicHandle struct {
+ extHandle
+ EncodeOptions
+ DecodeOptions
+}
+
+// Handle is the interface for a specific encoding format.
+//
+// Typically, a Handle is pre-configured before first time use,
+// and not modified while in use. Such a pre-configured Handle
+// is safe for concurrent access.
+type Handle interface {
+ writeExt() bool
+ getBasicHandle() *BasicHandle
+ newEncDriver(w encWriter) encDriver
+ newDecDriver(r decReader) decDriver
+}
+
+// RawExt represents raw unprocessed extension data.
+type RawExt struct {
+ Tag byte
+ Data []byte
+}
+
+type extTypeTagFn struct {
+ rtid uintptr
+ rt reflect.Type
+ tag byte
+ encFn func(reflect.Value) ([]byte, error)
+ decFn func(reflect.Value, []byte) error
+}
+
+type extHandle []*extTypeTagFn
+
+// AddExt registers an encode and decode function for a reflect.Type.
+// Note that the type must be a named type, and specifically not
+// a pointer or Interface. An error is returned if that is not honored.
+//
+// To Deregister an ext, call AddExt with 0 tag, nil encfn and nil decfn.
+func (o *extHandle) AddExt(
+ rt reflect.Type,
+ tag byte,
+ encfn func(reflect.Value) ([]byte, error),
+ decfn func(reflect.Value, []byte) error,
+) (err error) {
+ // o is a pointer, because we may need to initialize it
+ if rt.PkgPath() == "" || rt.Kind() == reflect.Interface {
+ err = fmt.Errorf("codec.Handle.AddExt: Takes named type, especially not a pointer or interface: %T",
+ reflect.Zero(rt).Interface())
+ return
+ }
+
+ // o cannot be nil, since it is always embedded in a Handle.
+ // if nil, let it panic.
+ // if o == nil {
+ // err = errors.New("codec.Handle.AddExt: extHandle cannot be a nil pointer.")
+ // return
+ // }
+
+ rtid := reflect.ValueOf(rt).Pointer()
+ for _, v := range *o {
+ if v.rtid == rtid {
+ v.tag, v.encFn, v.decFn = tag, encfn, decfn
+ return
+ }
+ }
+
+ *o = append(*o, &extTypeTagFn{rtid, rt, tag, encfn, decfn})
+ return
+}
+
+func (o extHandle) getExt(rtid uintptr) *extTypeTagFn {
+ for _, v := range o {
+ if v.rtid == rtid {
+ return v
+ }
+ }
+ return nil
+}
+
+func (o extHandle) getExtForTag(tag byte) *extTypeTagFn {
+ for _, v := range o {
+ if v.tag == tag {
+ return v
+ }
+ }
+ return nil
+}
+
+func (o extHandle) getDecodeExtForTag(tag byte) (
+ rv reflect.Value, fn func(reflect.Value, []byte) error) {
+ if x := o.getExtForTag(tag); x != nil {
+ // ext is only registered for base
+ rv = reflect.New(x.rt).Elem()
+ fn = x.decFn
+ }
+ return
+}
+
+func (o extHandle) getDecodeExt(rtid uintptr) (tag byte, fn func(reflect.Value, []byte) error) {
+ if x := o.getExt(rtid); x != nil {
+ tag = x.tag
+ fn = x.decFn
+ }
+ return
+}
+
+func (o extHandle) getEncodeExt(rtid uintptr) (tag byte, fn func(reflect.Value) ([]byte, error)) {
+ if x := o.getExt(rtid); x != nil {
+ tag = x.tag
+ fn = x.encFn
+ }
+ return
+}
+
+type structFieldInfo struct {
+ encName string // encode name
+
+ // only one of 'i' or 'is' can be set. If 'i' is -1, then 'is' has been set.
+
+ is []int // (recursive/embedded) field index in struct
+ i int16 // field index in struct
+ omitEmpty bool
+ toArray bool // if field is _struct, is the toArray set?
+
+ // tag string // tag
+ // name string // field name
+ // encNameBs []byte // encoded name as byte stream
+ // ikind int // kind of the field as an int i.e. int(reflect.Kind)
+}
+
+func parseStructFieldInfo(fname string, stag string) *structFieldInfo {
+ if fname == "" {
+ panic("parseStructFieldInfo: No Field Name")
+ }
+ si := structFieldInfo{
+ // name: fname,
+ encName: fname,
+ // tag: stag,
+ }
+
+ if stag != "" {
+ for i, s := range strings.Split(stag, ",") {
+ if i == 0 {
+ if s != "" {
+ si.encName = s
+ }
+ } else {
+ switch s {
+ case "omitempty":
+ si.omitEmpty = true
+ case "toarray":
+ si.toArray = true
+ }
+ }
+ }
+ }
+ // si.encNameBs = []byte(si.encName)
+ return &si
+}
+
+type sfiSortedByEncName []*structFieldInfo
+
+func (p sfiSortedByEncName) Len() int {
+ return len(p)
+}
+
+func (p sfiSortedByEncName) Less(i, j int) bool {
+ return p[i].encName < p[j].encName
+}
+
+func (p sfiSortedByEncName) Swap(i, j int) {
+ p[i], p[j] = p[j], p[i]
+}
+
+// typeInfo keeps information about each type referenced in the encode/decode sequence.
+//
+// During an encode/decode sequence, we work as below:
+// - If base is a built in type, en/decode base value
+// - If base is registered as an extension, en/decode base value
+// - If type is binary(M/Unm)arshaler, call Binary(M/Unm)arshal method
+// - Else decode appropriately based on the reflect.Kind
+type typeInfo struct {
+ sfi []*structFieldInfo // sorted. Used when enc/dec struct to map.
+ sfip []*structFieldInfo // unsorted. Used when enc/dec struct to array.
+
+ rt reflect.Type
+ rtid uintptr
+
+ // baseId gives pointer to the base reflect.Type, after deferencing
+ // the pointers. E.g. base type of ***time.Time is time.Time.
+ base reflect.Type
+ baseId uintptr
+ baseIndir int8 // number of indirections to get to base
+
+ mbs bool // base type (T or *T) is a MapBySlice
+
+ m bool // base type (T or *T) is a binaryMarshaler
+ unm bool // base type (T or *T) is a binaryUnmarshaler
+ mIndir int8 // number of indirections to get to binaryMarshaler type
+ unmIndir int8 // number of indirections to get to binaryUnmarshaler type
+ toArray bool // whether this (struct) type should be encoded as an array
+}
+
+func (ti *typeInfo) indexForEncName(name string) int {
+ //tisfi := ti.sfi
+ const binarySearchThreshold = 16
+ if sfilen := len(ti.sfi); sfilen < binarySearchThreshold {
+ // linear search. faster than binary search in my testing up to 16-field structs.
+ for i, si := range ti.sfi {
+ if si.encName == name {
+ return i
+ }
+ }
+ } else {
+ // binary search. adapted from sort/search.go.
+ h, i, j := 0, 0, sfilen
+ for i < j {
+ h = i + (j-i)/2
+ if ti.sfi[h].encName < name {
+ i = h + 1
+ } else {
+ j = h
+ }
+ }
+ if i < sfilen && ti.sfi[i].encName == name {
+ return i
+ }
+ }
+ return -1
+}
+
+func getTypeInfo(rtid uintptr, rt reflect.Type) (pti *typeInfo) {
+ var ok bool
+ cachedTypeInfoMutex.RLock()
+ pti, ok = cachedTypeInfo[rtid]
+ cachedTypeInfoMutex.RUnlock()
+ if ok {
+ return
+ }
+
+ cachedTypeInfoMutex.Lock()
+ defer cachedTypeInfoMutex.Unlock()
+ if pti, ok = cachedTypeInfo[rtid]; ok {
+ return
+ }
+
+ ti := typeInfo{rt: rt, rtid: rtid}
+ pti = &ti
+
+ var indir int8
+ if ok, indir = implementsIntf(rt, binaryMarshalerTyp); ok {
+ ti.m, ti.mIndir = true, indir
+ }
+ if ok, indir = implementsIntf(rt, binaryUnmarshalerTyp); ok {
+ ti.unm, ti.unmIndir = true, indir
+ }
+ if ok, _ = implementsIntf(rt, mapBySliceTyp); ok {
+ ti.mbs = true
+ }
+
+ pt := rt
+ var ptIndir int8
+ // for ; pt.Kind() == reflect.Ptr; pt, ptIndir = pt.Elem(), ptIndir+1 { }
+ for pt.Kind() == reflect.Ptr {
+ pt = pt.Elem()
+ ptIndir++
+ }
+ if ptIndir == 0 {
+ ti.base = rt
+ ti.baseId = rtid
+ } else {
+ ti.base = pt
+ ti.baseId = reflect.ValueOf(pt).Pointer()
+ ti.baseIndir = ptIndir
+ }
+
+ if rt.Kind() == reflect.Struct {
+ var siInfo *structFieldInfo
+ if f, ok := rt.FieldByName(structInfoFieldName); ok {
+ siInfo = parseStructFieldInfo(structInfoFieldName, f.Tag.Get(structTagName))
+ ti.toArray = siInfo.toArray
+ }
+ sfip := make([]*structFieldInfo, 0, rt.NumField())
+ rgetTypeInfo(rt, nil, make(map[string]bool), &sfip, siInfo)
+
+ // // try to put all si close together
+ // const tryToPutAllStructFieldInfoTogether = true
+ // if tryToPutAllStructFieldInfoTogether {
+ // sfip2 := make([]structFieldInfo, len(sfip))
+ // for i, si := range sfip {
+ // sfip2[i] = *si
+ // }
+ // for i := range sfip {
+ // sfip[i] = &sfip2[i]
+ // }
+ // }
+
+ ti.sfip = make([]*structFieldInfo, len(sfip))
+ ti.sfi = make([]*structFieldInfo, len(sfip))
+ copy(ti.sfip, sfip)
+ sort.Sort(sfiSortedByEncName(sfip))
+ copy(ti.sfi, sfip)
+ }
+ // sfi = sfip
+ cachedTypeInfo[rtid] = pti
+ return
+}
+
+func rgetTypeInfo(rt reflect.Type, indexstack []int, fnameToHastag map[string]bool,
+ sfi *[]*structFieldInfo, siInfo *structFieldInfo,
+) {
+ // for rt.Kind() == reflect.Ptr {
+ // // indexstack = append(indexstack, 0)
+ // rt = rt.Elem()
+ // }
+ for j := 0; j < rt.NumField(); j++ {
+ f := rt.Field(j)
+ stag := f.Tag.Get(structTagName)
+ if stag == "-" {
+ continue
+ }
+ if r1, _ := utf8.DecodeRuneInString(f.Name); r1 == utf8.RuneError || !unicode.IsUpper(r1) {
+ continue
+ }
+ // if anonymous and there is no struct tag and its a struct (or pointer to struct), inline it.
+ if f.Anonymous && stag == "" {
+ ft := f.Type
+ for ft.Kind() == reflect.Ptr {
+ ft = ft.Elem()
+ }
+ if ft.Kind() == reflect.Struct {
+ indexstack2 := append(append(make([]int, 0, len(indexstack)+4), indexstack...), j)
+ rgetTypeInfo(ft, indexstack2, fnameToHastag, sfi, siInfo)
+ continue
+ }
+ }
+ // do not let fields with same name in embedded structs override field at higher level.
+ // this must be done after anonymous check, to allow anonymous field
+ // still include their child fields
+ if _, ok := fnameToHastag[f.Name]; ok {
+ continue
+ }
+ si := parseStructFieldInfo(f.Name, stag)
+ // si.ikind = int(f.Type.Kind())
+ if len(indexstack) == 0 {
+ si.i = int16(j)
+ } else {
+ si.i = -1
+ si.is = append(append(make([]int, 0, len(indexstack)+4), indexstack...), j)
+ }
+
+ if siInfo != nil {
+ if siInfo.omitEmpty {
+ si.omitEmpty = true
+ }
+ }
+ *sfi = append(*sfi, si)
+ fnameToHastag[f.Name] = stag != ""
+ }
+}
+
+func panicToErr(err *error) {
+ if recoverPanicToErr {
+ if x := recover(); x != nil {
+ //debug.PrintStack()
+ panicValToErr(x, err)
+ }
+ }
+}
+
+func doPanic(tag string, format string, params ...interface{}) {
+ params2 := make([]interface{}, len(params)+1)
+ params2[0] = tag
+ copy(params2[1:], params)
+ panic(fmt.Errorf("%s: "+format, params2...))
+}
+
+func checkOverflowFloat32(f float64, doCheck bool) {
+ if !doCheck {
+ return
+ }
+ // check overflow (logic adapted from std pkg reflect/value.go OverflowFloat()
+ f2 := f
+ if f2 < 0 {
+ f2 = -f
+ }
+ if math.MaxFloat32 < f2 && f2 <= math.MaxFloat64 {
+ decErr("Overflow float32 value: %v", f2)
+ }
+}
+
+func checkOverflow(ui uint64, i int64, bitsize uint8) {
+ // check overflow (logic adapted from std pkg reflect/value.go OverflowUint()
+ if bitsize == 0 {
+ return
+ }
+ if i != 0 {
+ if trunc := (i << (64 - bitsize)) >> (64 - bitsize); i != trunc {
+ decErr("Overflow int value: %v", i)
+ }
+ }
+ if ui != 0 {
+ if trunc := (ui << (64 - bitsize)) >> (64 - bitsize); ui != trunc {
+ decErr("Overflow uint value: %v", ui)
+ }
+ }
+}
--- /dev/null
+// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a BSD-style license found in the LICENSE file.
+
+package codec
+
+// All non-std package dependencies live in this file,
+// so porting to different environment is easy (just update functions).
+
+import (
+ "errors"
+ "fmt"
+ "math"
+ "reflect"
+)
+
+var (
+ raisePanicAfterRecover = false
+ debugging = true
+)
+
+func panicValToErr(panicVal interface{}, err *error) {
+ switch xerr := panicVal.(type) {
+ case error:
+ *err = xerr
+ case string:
+ *err = errors.New(xerr)
+ default:
+ *err = fmt.Errorf("%v", panicVal)
+ }
+ if raisePanicAfterRecover {
+ panic(panicVal)
+ }
+ return
+}
+
+func isEmptyValueDeref(v reflect.Value, deref bool) bool {
+ switch v.Kind() {
+ case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+ return v.Len() == 0
+ case reflect.Bool:
+ return !v.Bool()
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return v.Uint() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ case reflect.Interface, reflect.Ptr:
+ if deref {
+ if v.IsNil() {
+ return true
+ }
+ return isEmptyValueDeref(v.Elem(), deref)
+ } else {
+ return v.IsNil()
+ }
+ case reflect.Struct:
+ // return true if all fields are empty. else return false.
+
+ // we cannot use equality check, because some fields may be maps/slices/etc
+ // and consequently the structs are not comparable.
+ // return v.Interface() == reflect.Zero(v.Type()).Interface()
+ for i, n := 0, v.NumField(); i < n; i++ {
+ if !isEmptyValueDeref(v.Field(i), deref) {
+ return false
+ }
+ }
+ return true
+ }
+ return false
+}
+
+func isEmptyValue(v reflect.Value) bool {
+ return isEmptyValueDeref(v, true)
+}
+
+func debugf(format string, args ...interface{}) {
+ if debugging {
+ if len(format) == 0 || format[len(format)-1] != '\n' {
+ format = format + "\n"
+ }
+ fmt.Printf(format, args...)
+ }
+}
+
+func pruneSignExt(v []byte, pos bool) (n int) {
+ if len(v) < 2 {
+ } else if pos && v[0] == 0 {
+ for ; v[n] == 0 && n+1 < len(v) && (v[n+1]&(1<<7) == 0); n++ {
+ }
+ } else if !pos && v[0] == 0xff {
+ for ; v[n] == 0xff && n+1 < len(v) && (v[n+1]&(1<<7) != 0); n++ {
+ }
+ }
+ return
+}
+
+func implementsIntf(typ, iTyp reflect.Type) (success bool, indir int8) {
+ if typ == nil {
+ return
+ }
+ rt := typ
+ // The type might be a pointer and we need to keep
+ // dereferencing to the base type until we find an implementation.
+ for {
+ if rt.Implements(iTyp) {
+ return true, indir
+ }
+ if p := rt; p.Kind() == reflect.Ptr {
+ indir++
+ if indir >= math.MaxInt8 { // insane number of indirections
+ return false, 0
+ }
+ rt = p.Elem()
+ continue
+ }
+ break
+ }
+ // No luck yet, but if this is a base type (non-pointer), the pointer might satisfy.
+ if typ.Kind() != reflect.Ptr {
+ // Not a pointer, but does the pointer work?
+ if reflect.PtrTo(typ).Implements(iTyp) {
+ return true, -1
+ }
+ }
+ return false, 0
+}
--- /dev/null
+// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a BSD-style license found in the LICENSE file.
+
+/*
+MSGPACK
+
+Msgpack-c implementation powers the c, c++, python, ruby, etc libraries.
+We need to maintain compatibility with it and how it encodes integer values
+without caring about the type.
+
+For compatibility with behaviour of msgpack-c reference implementation:
+ - Go intX (>0) and uintX
+ IS ENCODED AS
+ msgpack +ve fixnum, unsigned
+ - Go intX (<0)
+ IS ENCODED AS
+ msgpack -ve fixnum, signed
+
+*/
+package codec
+
+import (
+ "fmt"
+ "io"
+ "math"
+ "net/rpc"
+)
+
+const (
+ mpPosFixNumMin byte = 0x00
+ mpPosFixNumMax = 0x7f
+ mpFixMapMin = 0x80
+ mpFixMapMax = 0x8f
+ mpFixArrayMin = 0x90
+ mpFixArrayMax = 0x9f
+ mpFixStrMin = 0xa0
+ mpFixStrMax = 0xbf
+ mpNil = 0xc0
+ _ = 0xc1
+ mpFalse = 0xc2
+ mpTrue = 0xc3
+ mpFloat = 0xca
+ mpDouble = 0xcb
+ mpUint8 = 0xcc
+ mpUint16 = 0xcd
+ mpUint32 = 0xce
+ mpUint64 = 0xcf
+ mpInt8 = 0xd0
+ mpInt16 = 0xd1
+ mpInt32 = 0xd2
+ mpInt64 = 0xd3
+
+ // extensions below
+ mpBin8 = 0xc4
+ mpBin16 = 0xc5
+ mpBin32 = 0xc6
+ mpExt8 = 0xc7
+ mpExt16 = 0xc8
+ mpExt32 = 0xc9
+ mpFixExt1 = 0xd4
+ mpFixExt2 = 0xd5
+ mpFixExt4 = 0xd6
+ mpFixExt8 = 0xd7
+ mpFixExt16 = 0xd8
+
+ mpStr8 = 0xd9 // new
+ mpStr16 = 0xda
+ mpStr32 = 0xdb
+
+ mpArray16 = 0xdc
+ mpArray32 = 0xdd
+
+ mpMap16 = 0xde
+ mpMap32 = 0xdf
+
+ mpNegFixNumMin = 0xe0
+ mpNegFixNumMax = 0xff
+)
+
+// MsgpackSpecRpcMultiArgs is a special type which signifies to the MsgpackSpecRpcCodec
+// that the backend RPC service takes multiple arguments, which have been arranged
+// in sequence in the slice.
+//
+// The Codec then passes it AS-IS to the rpc service (without wrapping it in an
+// array of 1 element).
+type MsgpackSpecRpcMultiArgs []interface{}
+
+// A MsgpackContainer type specifies the different types of msgpackContainers.
+type msgpackContainerType struct {
+ fixCutoff int
+ bFixMin, b8, b16, b32 byte
+ hasFixMin, has8, has8Always bool
+}
+
+var (
+ msgpackContainerStr = msgpackContainerType{32, mpFixStrMin, mpStr8, mpStr16, mpStr32, true, true, false}
+ msgpackContainerBin = msgpackContainerType{0, 0, mpBin8, mpBin16, mpBin32, false, true, true}
+ msgpackContainerList = msgpackContainerType{16, mpFixArrayMin, 0, mpArray16, mpArray32, true, false, false}
+ msgpackContainerMap = msgpackContainerType{16, mpFixMapMin, 0, mpMap16, mpMap32, true, false, false}
+)
+
+//---------------------------------------------
+
+type msgpackEncDriver struct {
+ w encWriter
+ h *MsgpackHandle
+}
+
+func (e *msgpackEncDriver) isBuiltinType(rt uintptr) bool {
+ //no builtin types. All encodings are based on kinds. Types supported as extensions.
+ return false
+}
+
+func (e *msgpackEncDriver) encodeBuiltin(rt uintptr, v interface{}) {}
+
+func (e *msgpackEncDriver) encodeNil() {
+ e.w.writen1(mpNil)
+}
+
+func (e *msgpackEncDriver) encodeInt(i int64) {
+
+ switch {
+ case i >= 0:
+ e.encodeUint(uint64(i))
+ case i >= -32:
+ e.w.writen1(byte(i))
+ case i >= math.MinInt8:
+ e.w.writen2(mpInt8, byte(i))
+ case i >= math.MinInt16:
+ e.w.writen1(mpInt16)
+ e.w.writeUint16(uint16(i))
+ case i >= math.MinInt32:
+ e.w.writen1(mpInt32)
+ e.w.writeUint32(uint32(i))
+ default:
+ e.w.writen1(mpInt64)
+ e.w.writeUint64(uint64(i))
+ }
+}
+
+func (e *msgpackEncDriver) encodeUint(i uint64) {
+ switch {
+ case i <= math.MaxInt8:
+ e.w.writen1(byte(i))
+ case i <= math.MaxUint8:
+ e.w.writen2(mpUint8, byte(i))
+ case i <= math.MaxUint16:
+ e.w.writen1(mpUint16)
+ e.w.writeUint16(uint16(i))
+ case i <= math.MaxUint32:
+ e.w.writen1(mpUint32)
+ e.w.writeUint32(uint32(i))
+ default:
+ e.w.writen1(mpUint64)
+ e.w.writeUint64(uint64(i))
+ }
+}
+
+func (e *msgpackEncDriver) encodeBool(b bool) {
+ if b {
+ e.w.writen1(mpTrue)
+ } else {
+ e.w.writen1(mpFalse)
+ }
+}
+
+func (e *msgpackEncDriver) encodeFloat32(f float32) {
+ e.w.writen1(mpFloat)
+ e.w.writeUint32(math.Float32bits(f))
+}
+
+func (e *msgpackEncDriver) encodeFloat64(f float64) {
+ e.w.writen1(mpDouble)
+ e.w.writeUint64(math.Float64bits(f))
+}
+
+func (e *msgpackEncDriver) encodeExtPreamble(xtag byte, l int) {
+ switch {
+ case l == 1:
+ e.w.writen2(mpFixExt1, xtag)
+ case l == 2:
+ e.w.writen2(mpFixExt2, xtag)
+ case l == 4:
+ e.w.writen2(mpFixExt4, xtag)
+ case l == 8:
+ e.w.writen2(mpFixExt8, xtag)
+ case l == 16:
+ e.w.writen2(mpFixExt16, xtag)
+ case l < 256:
+ e.w.writen2(mpExt8, byte(l))
+ e.w.writen1(xtag)
+ case l < 65536:
+ e.w.writen1(mpExt16)
+ e.w.writeUint16(uint16(l))
+ e.w.writen1(xtag)
+ default:
+ e.w.writen1(mpExt32)
+ e.w.writeUint32(uint32(l))
+ e.w.writen1(xtag)
+ }
+}
+
+func (e *msgpackEncDriver) encodeArrayPreamble(length int) {
+ e.writeContainerLen(msgpackContainerList, length)
+}
+
+func (e *msgpackEncDriver) encodeMapPreamble(length int) {
+ e.writeContainerLen(msgpackContainerMap, length)
+}
+
+func (e *msgpackEncDriver) encodeString(c charEncoding, s string) {
+ if c == c_RAW && e.h.WriteExt {
+ e.writeContainerLen(msgpackContainerBin, len(s))
+ } else {
+ e.writeContainerLen(msgpackContainerStr, len(s))
+ }
+ if len(s) > 0 {
+ e.w.writestr(s)
+ }
+}
+
+func (e *msgpackEncDriver) encodeSymbol(v string) {
+ e.encodeString(c_UTF8, v)
+}
+
+func (e *msgpackEncDriver) encodeStringBytes(c charEncoding, bs []byte) {
+ if c == c_RAW && e.h.WriteExt {
+ e.writeContainerLen(msgpackContainerBin, len(bs))
+ } else {
+ e.writeContainerLen(msgpackContainerStr, len(bs))
+ }
+ if len(bs) > 0 {
+ e.w.writeb(bs)
+ }
+}
+
+func (e *msgpackEncDriver) writeContainerLen(ct msgpackContainerType, l int) {
+ switch {
+ case ct.hasFixMin && l < ct.fixCutoff:
+ e.w.writen1(ct.bFixMin | byte(l))
+ case ct.has8 && l < 256 && (ct.has8Always || e.h.WriteExt):
+ e.w.writen2(ct.b8, uint8(l))
+ case l < 65536:
+ e.w.writen1(ct.b16)
+ e.w.writeUint16(uint16(l))
+ default:
+ e.w.writen1(ct.b32)
+ e.w.writeUint32(uint32(l))
+ }
+}
+
+//---------------------------------------------
+
+type msgpackDecDriver struct {
+ r decReader
+ h *MsgpackHandle
+ bd byte
+ bdRead bool
+ bdType valueType
+}
+
+func (d *msgpackDecDriver) isBuiltinType(rt uintptr) bool {
+ //no builtin types. All encodings are based on kinds. Types supported as extensions.
+ return false
+}
+
+func (d *msgpackDecDriver) decodeBuiltin(rt uintptr, v interface{}) {}
+
+// Note: This returns either a primitive (int, bool, etc) for non-containers,
+// or a containerType, or a specific type denoting nil or extension.
+// It is called when a nil interface{} is passed, leaving it up to the DecDriver
+// to introspect the stream and decide how best to decode.
+// It deciphers the value by looking at the stream first.
+func (d *msgpackDecDriver) decodeNaked() (v interface{}, vt valueType, decodeFurther bool) {
+ d.initReadNext()
+ bd := d.bd
+
+ switch bd {
+ case mpNil:
+ vt = valueTypeNil
+ d.bdRead = false
+ case mpFalse:
+ vt = valueTypeBool
+ v = false
+ case mpTrue:
+ vt = valueTypeBool
+ v = true
+
+ case mpFloat:
+ vt = valueTypeFloat
+ v = float64(math.Float32frombits(d.r.readUint32()))
+ case mpDouble:
+ vt = valueTypeFloat
+ v = math.Float64frombits(d.r.readUint64())
+
+ case mpUint8:
+ vt = valueTypeUint
+ v = uint64(d.r.readn1())
+ case mpUint16:
+ vt = valueTypeUint
+ v = uint64(d.r.readUint16())
+ case mpUint32:
+ vt = valueTypeUint
+ v = uint64(d.r.readUint32())
+ case mpUint64:
+ vt = valueTypeUint
+ v = uint64(d.r.readUint64())
+
+ case mpInt8:
+ vt = valueTypeInt
+ v = int64(int8(d.r.readn1()))
+ case mpInt16:
+ vt = valueTypeInt
+ v = int64(int16(d.r.readUint16()))
+ case mpInt32:
+ vt = valueTypeInt
+ v = int64(int32(d.r.readUint32()))
+ case mpInt64:
+ vt = valueTypeInt
+ v = int64(int64(d.r.readUint64()))
+
+ default:
+ switch {
+ case bd >= mpPosFixNumMin && bd <= mpPosFixNumMax:
+ // positive fixnum (always signed)
+ vt = valueTypeInt
+ v = int64(int8(bd))
+ case bd >= mpNegFixNumMin && bd <= mpNegFixNumMax:
+ // negative fixnum
+ vt = valueTypeInt
+ v = int64(int8(bd))
+ case bd == mpStr8, bd == mpStr16, bd == mpStr32, bd >= mpFixStrMin && bd <= mpFixStrMax:
+ if d.h.RawToString {
+ var rvm string
+ vt = valueTypeString
+ v = &rvm
+ } else {
+ var rvm = []byte{}
+ vt = valueTypeBytes
+ v = &rvm
+ }
+ decodeFurther = true
+ case bd == mpBin8, bd == mpBin16, bd == mpBin32:
+ var rvm = []byte{}
+ vt = valueTypeBytes
+ v = &rvm
+ decodeFurther = true
+ case bd == mpArray16, bd == mpArray32, bd >= mpFixArrayMin && bd <= mpFixArrayMax:
+ vt = valueTypeArray
+ decodeFurther = true
+ case bd == mpMap16, bd == mpMap32, bd >= mpFixMapMin && bd <= mpFixMapMax:
+ vt = valueTypeMap
+ decodeFurther = true
+ case bd >= mpFixExt1 && bd <= mpFixExt16, bd >= mpExt8 && bd <= mpExt32:
+ clen := d.readExtLen()
+ var re RawExt
+ re.Tag = d.r.readn1()
+ re.Data = d.r.readn(clen)
+ v = &re
+ vt = valueTypeExt
+ default:
+ decErr("Nil-Deciphered DecodeValue: %s: hex: %x, dec: %d", msgBadDesc, bd, bd)
+ }
+ }
+ if !decodeFurther {
+ d.bdRead = false
+ }
+ return
+}
+
+// int can be decoded from msgpack type: intXXX or uintXXX
+func (d *msgpackDecDriver) decodeInt(bitsize uint8) (i int64) {
+ switch d.bd {
+ case mpUint8:
+ i = int64(uint64(d.r.readn1()))
+ case mpUint16:
+ i = int64(uint64(d.r.readUint16()))
+ case mpUint32:
+ i = int64(uint64(d.r.readUint32()))
+ case mpUint64:
+ i = int64(d.r.readUint64())
+ case mpInt8:
+ i = int64(int8(d.r.readn1()))
+ case mpInt16:
+ i = int64(int16(d.r.readUint16()))
+ case mpInt32:
+ i = int64(int32(d.r.readUint32()))
+ case mpInt64:
+ i = int64(d.r.readUint64())
+ default:
+ switch {
+ case d.bd >= mpPosFixNumMin && d.bd <= mpPosFixNumMax:
+ i = int64(int8(d.bd))
+ case d.bd >= mpNegFixNumMin && d.bd <= mpNegFixNumMax:
+ i = int64(int8(d.bd))
+ default:
+ decErr("Unhandled single-byte unsigned integer value: %s: %x", msgBadDesc, d.bd)
+ }
+ }
+ // check overflow (logic adapted from std pkg reflect/value.go OverflowUint()
+ if bitsize > 0 {
+ if trunc := (i << (64 - bitsize)) >> (64 - bitsize); i != trunc {
+ decErr("Overflow int value: %v", i)
+ }
+ }
+ d.bdRead = false
+ return
+}
+
+// uint can be decoded from msgpack type: intXXX or uintXXX
+func (d *msgpackDecDriver) decodeUint(bitsize uint8) (ui uint64) {
+ switch d.bd {
+ case mpUint8:
+ ui = uint64(d.r.readn1())
+ case mpUint16:
+ ui = uint64(d.r.readUint16())
+ case mpUint32:
+ ui = uint64(d.r.readUint32())
+ case mpUint64:
+ ui = d.r.readUint64()
+ case mpInt8:
+ if i := int64(int8(d.r.readn1())); i >= 0 {
+ ui = uint64(i)
+ } else {
+ decErr("Assigning negative signed value: %v, to unsigned type", i)
+ }
+ case mpInt16:
+ if i := int64(int16(d.r.readUint16())); i >= 0 {
+ ui = uint64(i)
+ } else {
+ decErr("Assigning negative signed value: %v, to unsigned type", i)
+ }
+ case mpInt32:
+ if i := int64(int32(d.r.readUint32())); i >= 0 {
+ ui = uint64(i)
+ } else {
+ decErr("Assigning negative signed value: %v, to unsigned type", i)
+ }
+ case mpInt64:
+ if i := int64(d.r.readUint64()); i >= 0 {
+ ui = uint64(i)
+ } else {
+ decErr("Assigning negative signed value: %v, to unsigned type", i)
+ }
+ default:
+ switch {
+ case d.bd >= mpPosFixNumMin && d.bd <= mpPosFixNumMax:
+ ui = uint64(d.bd)
+ case d.bd >= mpNegFixNumMin && d.bd <= mpNegFixNumMax:
+ decErr("Assigning negative signed value: %v, to unsigned type", int(d.bd))
+ default:
+ decErr("Unhandled single-byte unsigned integer value: %s: %x", msgBadDesc, d.bd)
+ }
+ }
+ // check overflow (logic adapted from std pkg reflect/value.go OverflowUint()
+ if bitsize > 0 {
+ if trunc := (ui << (64 - bitsize)) >> (64 - bitsize); ui != trunc {
+ decErr("Overflow uint value: %v", ui)
+ }
+ }
+ d.bdRead = false
+ return
+}
+
+// float can either be decoded from msgpack type: float, double or intX
+func (d *msgpackDecDriver) decodeFloat(chkOverflow32 bool) (f float64) {
+ switch d.bd {
+ case mpFloat:
+ f = float64(math.Float32frombits(d.r.readUint32()))
+ case mpDouble:
+ f = math.Float64frombits(d.r.readUint64())
+ default:
+ f = float64(d.decodeInt(0))
+ }
+ checkOverflowFloat32(f, chkOverflow32)
+ d.bdRead = false
+ return
+}
+
+// bool can be decoded from bool, fixnum 0 or 1.
+func (d *msgpackDecDriver) decodeBool() (b bool) {
+ switch d.bd {
+ case mpFalse, 0:
+ // b = false
+ case mpTrue, 1:
+ b = true
+ default:
+ decErr("Invalid single-byte value for bool: %s: %x", msgBadDesc, d.bd)
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *msgpackDecDriver) decodeString() (s string) {
+ clen := d.readContainerLen(msgpackContainerStr)
+ if clen > 0 {
+ s = string(d.r.readn(clen))
+ }
+ d.bdRead = false
+ return
+}
+
+// Callers must check if changed=true (to decide whether to replace the one they have)
+func (d *msgpackDecDriver) decodeBytes(bs []byte) (bsOut []byte, changed bool) {
+ // bytes can be decoded from msgpackContainerStr or msgpackContainerBin
+ var clen int
+ switch d.bd {
+ case mpBin8, mpBin16, mpBin32:
+ clen = d.readContainerLen(msgpackContainerBin)
+ default:
+ clen = d.readContainerLen(msgpackContainerStr)
+ }
+ // if clen < 0 {
+ // changed = true
+ // panic("length cannot be zero. this cannot be nil.")
+ // }
+ if clen > 0 {
+ // if no contents in stream, don't update the passed byteslice
+ if len(bs) != clen {
+ // Return changed=true if length of passed slice diff from length of bytes in stream
+ if len(bs) > clen {
+ bs = bs[:clen]
+ } else {
+ bs = make([]byte, clen)
+ }
+ bsOut = bs
+ changed = true
+ }
+ d.r.readb(bs)
+ }
+ d.bdRead = false
+ return
+}
+
+// Every top-level decode funcs (i.e. decodeValue, decode) must call this first.
+func (d *msgpackDecDriver) initReadNext() {
+ if d.bdRead {
+ return
+ }
+ d.bd = d.r.readn1()
+ d.bdRead = true
+ d.bdType = valueTypeUnset
+}
+
+func (d *msgpackDecDriver) currentEncodedType() valueType {
+ if d.bdType == valueTypeUnset {
+ bd := d.bd
+ switch bd {
+ case mpNil:
+ d.bdType = valueTypeNil
+ case mpFalse, mpTrue:
+ d.bdType = valueTypeBool
+ case mpFloat, mpDouble:
+ d.bdType = valueTypeFloat
+ case mpUint8, mpUint16, mpUint32, mpUint64:
+ d.bdType = valueTypeUint
+ case mpInt8, mpInt16, mpInt32, mpInt64:
+ d.bdType = valueTypeInt
+ default:
+ switch {
+ case bd >= mpPosFixNumMin && bd <= mpPosFixNumMax:
+ d.bdType = valueTypeInt
+ case bd >= mpNegFixNumMin && bd <= mpNegFixNumMax:
+ d.bdType = valueTypeInt
+ case bd == mpStr8, bd == mpStr16, bd == mpStr32, bd >= mpFixStrMin && bd <= mpFixStrMax:
+ if d.h.RawToString {
+ d.bdType = valueTypeString
+ } else {
+ d.bdType = valueTypeBytes
+ }
+ case bd == mpBin8, bd == mpBin16, bd == mpBin32:
+ d.bdType = valueTypeBytes
+ case bd == mpArray16, bd == mpArray32, bd >= mpFixArrayMin && bd <= mpFixArrayMax:
+ d.bdType = valueTypeArray
+ case bd == mpMap16, bd == mpMap32, bd >= mpFixMapMin && bd <= mpFixMapMax:
+ d.bdType = valueTypeMap
+ case bd >= mpFixExt1 && bd <= mpFixExt16, bd >= mpExt8 && bd <= mpExt32:
+ d.bdType = valueTypeExt
+ default:
+ decErr("currentEncodedType: Undeciphered descriptor: %s: hex: %x, dec: %d", msgBadDesc, bd, bd)
+ }
+ }
+ }
+ return d.bdType
+}
+
+func (d *msgpackDecDriver) tryDecodeAsNil() bool {
+ if d.bd == mpNil {
+ d.bdRead = false
+ return true
+ }
+ return false
+}
+
+func (d *msgpackDecDriver) readContainerLen(ct msgpackContainerType) (clen int) {
+ bd := d.bd
+ switch {
+ case bd == mpNil:
+ clen = -1 // to represent nil
+ case bd == ct.b8:
+ clen = int(d.r.readn1())
+ case bd == ct.b16:
+ clen = int(d.r.readUint16())
+ case bd == ct.b32:
+ clen = int(d.r.readUint32())
+ case (ct.bFixMin & bd) == ct.bFixMin:
+ clen = int(ct.bFixMin ^ bd)
+ default:
+ decErr("readContainerLen: %s: hex: %x, dec: %d", msgBadDesc, bd, bd)
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *msgpackDecDriver) readMapLen() int {
+ return d.readContainerLen(msgpackContainerMap)
+}
+
+func (d *msgpackDecDriver) readArrayLen() int {
+ return d.readContainerLen(msgpackContainerList)
+}
+
+func (d *msgpackDecDriver) readExtLen() (clen int) {
+ switch d.bd {
+ case mpNil:
+ clen = -1 // to represent nil
+ case mpFixExt1:
+ clen = 1
+ case mpFixExt2:
+ clen = 2
+ case mpFixExt4:
+ clen = 4
+ case mpFixExt8:
+ clen = 8
+ case mpFixExt16:
+ clen = 16
+ case mpExt8:
+ clen = int(d.r.readn1())
+ case mpExt16:
+ clen = int(d.r.readUint16())
+ case mpExt32:
+ clen = int(d.r.readUint32())
+ default:
+ decErr("decoding ext bytes: found unexpected byte: %x", d.bd)
+ }
+ return
+}
+
+func (d *msgpackDecDriver) decodeExt(verifyTag bool, tag byte) (xtag byte, xbs []byte) {
+ xbd := d.bd
+ switch {
+ case xbd == mpBin8, xbd == mpBin16, xbd == mpBin32:
+ xbs, _ = d.decodeBytes(nil)
+ case xbd == mpStr8, xbd == mpStr16, xbd == mpStr32,
+ xbd >= mpFixStrMin && xbd <= mpFixStrMax:
+ xbs = []byte(d.decodeString())
+ default:
+ clen := d.readExtLen()
+ xtag = d.r.readn1()
+ if verifyTag && xtag != tag {
+ decErr("Wrong extension tag. Got %b. Expecting: %v", xtag, tag)
+ }
+ xbs = d.r.readn(clen)
+ }
+ d.bdRead = false
+ return
+}
+
+//--------------------------------------------------
+
+//MsgpackHandle is a Handle for the Msgpack Schema-Free Encoding Format.
+type MsgpackHandle struct {
+ BasicHandle
+
+ // RawToString controls how raw bytes are decoded into a nil interface{}.
+ RawToString bool
+ // WriteExt flag supports encoding configured extensions with extension tags.
+ // It also controls whether other elements of the new spec are encoded (ie Str8).
+ //
+ // With WriteExt=false, configured extensions are serialized as raw bytes
+ // and Str8 is not encoded.
+ //
+ // A stream can still be decoded into a typed value, provided an appropriate value
+ // is provided, but the type cannot be inferred from the stream. If no appropriate
+ // type is provided (e.g. decoding into a nil interface{}), you get back
+ // a []byte or string based on the setting of RawToString.
+ WriteExt bool
+}
+
+func (h *MsgpackHandle) newEncDriver(w encWriter) encDriver {
+ return &msgpackEncDriver{w: w, h: h}
+}
+
+func (h *MsgpackHandle) newDecDriver(r decReader) decDriver {
+ return &msgpackDecDriver{r: r, h: h}
+}
+
+func (h *MsgpackHandle) writeExt() bool {
+ return h.WriteExt
+}
+
+func (h *MsgpackHandle) getBasicHandle() *BasicHandle {
+ return &h.BasicHandle
+}
+
+//--------------------------------------------------
+
+type msgpackSpecRpcCodec struct {
+ rpcCodec
+}
+
+// /////////////// Spec RPC Codec ///////////////////
+func (c *msgpackSpecRpcCodec) WriteRequest(r *rpc.Request, body interface{}) error {
+ // WriteRequest can write to both a Go service, and other services that do
+ // not abide by the 1 argument rule of a Go service.
+ // We discriminate based on if the body is a MsgpackSpecRpcMultiArgs
+ var bodyArr []interface{}
+ if m, ok := body.(MsgpackSpecRpcMultiArgs); ok {
+ bodyArr = ([]interface{})(m)
+ } else {
+ bodyArr = []interface{}{body}
+ }
+ r2 := []interface{}{0, uint32(r.Seq), r.ServiceMethod, bodyArr}
+ return c.write(r2, nil, false, true)
+}
+
+func (c *msgpackSpecRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error {
+ var moe interface{}
+ if r.Error != "" {
+ moe = r.Error
+ }
+ if moe != nil && body != nil {
+ body = nil
+ }
+ r2 := []interface{}{1, uint32(r.Seq), moe, body}
+ return c.write(r2, nil, false, true)
+}
+
+func (c *msgpackSpecRpcCodec) ReadResponseHeader(r *rpc.Response) error {
+ return c.parseCustomHeader(1, &r.Seq, &r.Error)
+}
+
+func (c *msgpackSpecRpcCodec) ReadRequestHeader(r *rpc.Request) error {
+ return c.parseCustomHeader(0, &r.Seq, &r.ServiceMethod)
+}
+
+func (c *msgpackSpecRpcCodec) ReadRequestBody(body interface{}) error {
+ if body == nil { // read and discard
+ return c.read(nil)
+ }
+ bodyArr := []interface{}{body}
+ return c.read(&bodyArr)
+}
+
+func (c *msgpackSpecRpcCodec) parseCustomHeader(expectTypeByte byte, msgid *uint64, methodOrError *string) (err error) {
+
+ if c.cls {
+ return io.EOF
+ }
+
+ // We read the response header by hand
+ // so that the body can be decoded on its own from the stream at a later time.
+
+ const fia byte = 0x94 //four item array descriptor value
+ // Not sure why the panic of EOF is swallowed above.
+ // if bs1 := c.dec.r.readn1(); bs1 != fia {
+ // err = fmt.Errorf("Unexpected value for array descriptor: Expecting %v. Received %v", fia, bs1)
+ // return
+ // }
+ var b byte
+ b, err = c.br.ReadByte()
+ if err != nil {
+ return
+ }
+ if b != fia {
+ err = fmt.Errorf("Unexpected value for array descriptor: Expecting %v. Received %v", fia, b)
+ return
+ }
+
+ if err = c.read(&b); err != nil {
+ return
+ }
+ if b != expectTypeByte {
+ err = fmt.Errorf("Unexpected byte descriptor in header. Expecting %v. Received %v", expectTypeByte, b)
+ return
+ }
+ if err = c.read(msgid); err != nil {
+ return
+ }
+ if err = c.read(methodOrError); err != nil {
+ return
+ }
+ return
+}
+
+//--------------------------------------------------
+
+// msgpackSpecRpc is the implementation of Rpc that uses custom communication protocol
+// as defined in the msgpack spec at https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md
+type msgpackSpecRpc struct{}
+
+// MsgpackSpecRpc implements Rpc using the communication protocol defined in
+// the msgpack spec at https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md .
+// Its methods (ServerCodec and ClientCodec) return values that implement RpcCodecBuffered.
+var MsgpackSpecRpc msgpackSpecRpc
+
+func (x msgpackSpecRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {
+ return &msgpackSpecRpcCodec{newRPCCodec(conn, h)}
+}
+
+func (x msgpackSpecRpc) ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec {
+ return &msgpackSpecRpcCodec{newRPCCodec(conn, h)}
+}
+
+var _ decDriver = (*msgpackDecDriver)(nil)
+var _ encDriver = (*msgpackEncDriver)(nil)
--- /dev/null
+#!/usr/bin/env python
+
+# This will create golden files in a directory passed to it.
+# A Test calls this internally to create the golden files
+# So it can process them (so we don't have to checkin the files).
+
+import msgpack, msgpackrpc, sys, os, threading
+
+def get_test_data_list():
+ # get list with all primitive types, and a combo type
+ l0 = [
+ -8,
+ -1616,
+ -32323232,
+ -6464646464646464,
+ 192,
+ 1616,
+ 32323232,
+ 6464646464646464,
+ 192,
+ -3232.0,
+ -6464646464.0,
+ 3232.0,
+ 6464646464.0,
+ False,
+ True,
+ None,
+ "someday",
+ "",
+ "bytestring",
+ 1328176922000002000,
+ -2206187877999998000,
+ 0,
+ -6795364578871345152
+ ]
+ l1 = [
+ { "true": True,
+ "false": False },
+ { "true": "True",
+ "false": False,
+ "uint16(1616)": 1616 },
+ { "list": [1616, 32323232, True, -3232.0, {"TRUE":True, "FALSE":False}, [True, False] ],
+ "int32":32323232, "bool": True,
+ "LONG STRING": "123456789012345678901234567890123456789012345678901234567890",
+ "SHORT STRING": "1234567890" },
+ { True: "true", 8: False, "false": 0 }
+ ]
+
+ l = []
+ l.extend(l0)
+ l.append(l0)
+ l.extend(l1)
+ return l
+
+def build_test_data(destdir):
+ l = get_test_data_list()
+ for i in range(len(l)):
+ packer = msgpack.Packer()
+ serialized = packer.pack(l[i])
+ f = open(os.path.join(destdir, str(i) + '.golden'), 'wb')
+ f.write(serialized)
+ f.close()
+
+def doRpcServer(port, stopTimeSec):
+ class EchoHandler(object):
+ def Echo123(self, msg1, msg2, msg3):
+ return ("1:%s 2:%s 3:%s" % (msg1, msg2, msg3))
+ def EchoStruct(self, msg):
+ return ("%s" % msg)
+
+ addr = msgpackrpc.Address('localhost', port)
+ server = msgpackrpc.Server(EchoHandler())
+ server.listen(addr)
+ # run thread to stop it after stopTimeSec seconds if > 0
+ if stopTimeSec > 0:
+ def myStopRpcServer():
+ server.stop()
+ t = threading.Timer(stopTimeSec, myStopRpcServer)
+ t.start()
+ server.start()
+
+def doRpcClientToPythonSvc(port):
+ address = msgpackrpc.Address('localhost', port)
+ client = msgpackrpc.Client(address, unpack_encoding='utf-8')
+ print client.call("Echo123", "A1", "B2", "C3")
+ print client.call("EchoStruct", {"A" :"Aa", "B":"Bb", "C":"Cc"})
+
+def doRpcClientToGoSvc(port):
+ # print ">>>> port: ", port, " <<<<<"
+ address = msgpackrpc.Address('localhost', port)
+ client = msgpackrpc.Client(address, unpack_encoding='utf-8')
+ print client.call("TestRpcInt.Echo123", ["A1", "B2", "C3"])
+ print client.call("TestRpcInt.EchoStruct", {"A" :"Aa", "B":"Bb", "C":"Cc"})
+
+def doMain(args):
+ if len(args) == 2 and args[0] == "testdata":
+ build_test_data(args[1])
+ elif len(args) == 3 and args[0] == "rpc-server":
+ doRpcServer(int(args[1]), int(args[2]))
+ elif len(args) == 2 and args[0] == "rpc-client-python-service":
+ doRpcClientToPythonSvc(int(args[1]))
+ elif len(args) == 2 and args[0] == "rpc-client-go-service":
+ doRpcClientToGoSvc(int(args[1]))
+ else:
+ print("Usage: msgpack_test.py " +
+ "[testdata|rpc-server|rpc-client-python-service|rpc-client-go-service] ...")
+
+if __name__ == "__main__":
+ doMain(sys.argv[1:])
+
--- /dev/null
+// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a BSD-style license found in the LICENSE file.
+
+package codec
+
+import (
+ "bufio"
+ "io"
+ "net/rpc"
+ "sync"
+)
+
+// Rpc provides a rpc Server or Client Codec for rpc communication.
+type Rpc interface {
+ ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec
+ ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec
+}
+
+// RpcCodecBuffered allows access to the underlying bufio.Reader/Writer
+// used by the rpc connection. It accomodates use-cases where the connection
+// should be used by rpc and non-rpc functions, e.g. streaming a file after
+// sending an rpc response.
+type RpcCodecBuffered interface {
+ BufferedReader() *bufio.Reader
+ BufferedWriter() *bufio.Writer
+}
+
+// -------------------------------------
+
+// rpcCodec defines the struct members and common methods.
+type rpcCodec struct {
+ rwc io.ReadWriteCloser
+ dec *Decoder
+ enc *Encoder
+ bw *bufio.Writer
+ br *bufio.Reader
+ mu sync.Mutex
+ cls bool
+}
+
+func newRPCCodec(conn io.ReadWriteCloser, h Handle) rpcCodec {
+ bw := bufio.NewWriter(conn)
+ br := bufio.NewReader(conn)
+ return rpcCodec{
+ rwc: conn,
+ bw: bw,
+ br: br,
+ enc: NewEncoder(bw, h),
+ dec: NewDecoder(br, h),
+ }
+}
+
+func (c *rpcCodec) BufferedReader() *bufio.Reader {
+ return c.br
+}
+
+func (c *rpcCodec) BufferedWriter() *bufio.Writer {
+ return c.bw
+}
+
+func (c *rpcCodec) write(obj1, obj2 interface{}, writeObj2, doFlush bool) (err error) {
+ if c.cls {
+ return io.EOF
+ }
+ if err = c.enc.Encode(obj1); err != nil {
+ return
+ }
+ if writeObj2 {
+ if err = c.enc.Encode(obj2); err != nil {
+ return
+ }
+ }
+ if doFlush && c.bw != nil {
+ return c.bw.Flush()
+ }
+ return
+}
+
+func (c *rpcCodec) read(obj interface{}) (err error) {
+ if c.cls {
+ return io.EOF
+ }
+ //If nil is passed in, we should still attempt to read content to nowhere.
+ if obj == nil {
+ var obj2 interface{}
+ return c.dec.Decode(&obj2)
+ }
+ return c.dec.Decode(obj)
+}
+
+func (c *rpcCodec) Close() error {
+ if c.cls {
+ return io.EOF
+ }
+ c.cls = true
+ return c.rwc.Close()
+}
+
+func (c *rpcCodec) ReadResponseBody(body interface{}) error {
+ return c.read(body)
+}
+
+// -------------------------------------
+
+type goRpcCodec struct {
+ rpcCodec
+}
+
+func (c *goRpcCodec) WriteRequest(r *rpc.Request, body interface{}) error {
+ // Must protect for concurrent access as per API
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ return c.write(r, body, true, true)
+}
+
+func (c *goRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ return c.write(r, body, true, true)
+}
+
+func (c *goRpcCodec) ReadResponseHeader(r *rpc.Response) error {
+ return c.read(r)
+}
+
+func (c *goRpcCodec) ReadRequestHeader(r *rpc.Request) error {
+ return c.read(r)
+}
+
+func (c *goRpcCodec) ReadRequestBody(body interface{}) error {
+ return c.read(body)
+}
+
+// -------------------------------------
+
+// goRpc is the implementation of Rpc that uses the communication protocol
+// as defined in net/rpc package.
+type goRpc struct{}
+
+// GoRpc implements Rpc using the communication protocol defined in net/rpc package.
+// Its methods (ServerCodec and ClientCodec) return values that implement RpcCodecBuffered.
+var GoRpc goRpc
+
+func (x goRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {
+ return &goRpcCodec{newRPCCodec(conn, h)}
+}
+
+func (x goRpc) ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec {
+ return &goRpcCodec{newRPCCodec(conn, h)}
+}
+
+var _ RpcCodecBuffered = (*rpcCodec)(nil) // ensure *rpcCodec implements RpcCodecBuffered
--- /dev/null
+// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a BSD-style license found in the LICENSE file.
+
+package codec
+
+import "math"
+
+const (
+ _ uint8 = iota
+ simpleVdNil = 1
+ simpleVdFalse = 2
+ simpleVdTrue = 3
+ simpleVdFloat32 = 4
+ simpleVdFloat64 = 5
+
+ // each lasts for 4 (ie n, n+1, n+2, n+3)
+ simpleVdPosInt = 8
+ simpleVdNegInt = 12
+
+ // containers: each lasts for 4 (ie n, n+1, n+2, ... n+7)
+ simpleVdString = 216
+ simpleVdByteArray = 224
+ simpleVdArray = 232
+ simpleVdMap = 240
+ simpleVdExt = 248
+)
+
+type simpleEncDriver struct {
+ h *SimpleHandle
+ w encWriter
+ //b [8]byte
+}
+
+func (e *simpleEncDriver) isBuiltinType(rt uintptr) bool {
+ return false
+}
+
+func (e *simpleEncDriver) encodeBuiltin(rt uintptr, v interface{}) {
+}
+
+func (e *simpleEncDriver) encodeNil() {
+ e.w.writen1(simpleVdNil)
+}
+
+func (e *simpleEncDriver) encodeBool(b bool) {
+ if b {
+ e.w.writen1(simpleVdTrue)
+ } else {
+ e.w.writen1(simpleVdFalse)
+ }
+}
+
+func (e *simpleEncDriver) encodeFloat32(f float32) {
+ e.w.writen1(simpleVdFloat32)
+ e.w.writeUint32(math.Float32bits(f))
+}
+
+func (e *simpleEncDriver) encodeFloat64(f float64) {
+ e.w.writen1(simpleVdFloat64)
+ e.w.writeUint64(math.Float64bits(f))
+}
+
+func (e *simpleEncDriver) encodeInt(v int64) {
+ if v < 0 {
+ e.encUint(uint64(-v), simpleVdNegInt)
+ } else {
+ e.encUint(uint64(v), simpleVdPosInt)
+ }
+}
+
+func (e *simpleEncDriver) encodeUint(v uint64) {
+ e.encUint(v, simpleVdPosInt)
+}
+
+func (e *simpleEncDriver) encUint(v uint64, bd uint8) {
+ switch {
+ case v <= math.MaxUint8:
+ e.w.writen2(bd, uint8(v))
+ case v <= math.MaxUint16:
+ e.w.writen1(bd + 1)
+ e.w.writeUint16(uint16(v))
+ case v <= math.MaxUint32:
+ e.w.writen1(bd + 2)
+ e.w.writeUint32(uint32(v))
+ case v <= math.MaxUint64:
+ e.w.writen1(bd + 3)
+ e.w.writeUint64(v)
+ }
+}
+
+func (e *simpleEncDriver) encLen(bd byte, length int) {
+ switch {
+ case length == 0:
+ e.w.writen1(bd)
+ case length <= math.MaxUint8:
+ e.w.writen1(bd + 1)
+ e.w.writen1(uint8(length))
+ case length <= math.MaxUint16:
+ e.w.writen1(bd + 2)
+ e.w.writeUint16(uint16(length))
+ case int64(length) <= math.MaxUint32:
+ e.w.writen1(bd + 3)
+ e.w.writeUint32(uint32(length))
+ default:
+ e.w.writen1(bd + 4)
+ e.w.writeUint64(uint64(length))
+ }
+}
+
+func (e *simpleEncDriver) encodeExtPreamble(xtag byte, length int) {
+ e.encLen(simpleVdExt, length)
+ e.w.writen1(xtag)
+}
+
+func (e *simpleEncDriver) encodeArrayPreamble(length int) {
+ e.encLen(simpleVdArray, length)
+}
+
+func (e *simpleEncDriver) encodeMapPreamble(length int) {
+ e.encLen(simpleVdMap, length)
+}
+
+func (e *simpleEncDriver) encodeString(c charEncoding, v string) {
+ e.encLen(simpleVdString, len(v))
+ e.w.writestr(v)
+}
+
+func (e *simpleEncDriver) encodeSymbol(v string) {
+ e.encodeString(c_UTF8, v)
+}
+
+func (e *simpleEncDriver) encodeStringBytes(c charEncoding, v []byte) {
+ e.encLen(simpleVdByteArray, len(v))
+ e.w.writeb(v)
+}
+
+//------------------------------------
+
+type simpleDecDriver struct {
+ h *SimpleHandle
+ r decReader
+ bdRead bool
+ bdType valueType
+ bd byte
+ //b [8]byte
+}
+
+func (d *simpleDecDriver) initReadNext() {
+ if d.bdRead {
+ return
+ }
+ d.bd = d.r.readn1()
+ d.bdRead = true
+ d.bdType = valueTypeUnset
+}
+
+func (d *simpleDecDriver) currentEncodedType() valueType {
+ if d.bdType == valueTypeUnset {
+ switch d.bd {
+ case simpleVdNil:
+ d.bdType = valueTypeNil
+ case simpleVdTrue, simpleVdFalse:
+ d.bdType = valueTypeBool
+ case simpleVdPosInt, simpleVdPosInt + 1, simpleVdPosInt + 2, simpleVdPosInt + 3:
+ d.bdType = valueTypeUint
+ case simpleVdNegInt, simpleVdNegInt + 1, simpleVdNegInt + 2, simpleVdNegInt + 3:
+ d.bdType = valueTypeInt
+ case simpleVdFloat32, simpleVdFloat64:
+ d.bdType = valueTypeFloat
+ case simpleVdString, simpleVdString + 1, simpleVdString + 2, simpleVdString + 3, simpleVdString + 4:
+ d.bdType = valueTypeString
+ case simpleVdByteArray, simpleVdByteArray + 1, simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
+ d.bdType = valueTypeBytes
+ case simpleVdExt, simpleVdExt + 1, simpleVdExt + 2, simpleVdExt + 3, simpleVdExt + 4:
+ d.bdType = valueTypeExt
+ case simpleVdArray, simpleVdArray + 1, simpleVdArray + 2, simpleVdArray + 3, simpleVdArray + 4:
+ d.bdType = valueTypeArray
+ case simpleVdMap, simpleVdMap + 1, simpleVdMap + 2, simpleVdMap + 3, simpleVdMap + 4:
+ d.bdType = valueTypeMap
+ default:
+ decErr("currentEncodedType: Unrecognized d.vd: 0x%x", d.bd)
+ }
+ }
+ return d.bdType
+}
+
+func (d *simpleDecDriver) tryDecodeAsNil() bool {
+ if d.bd == simpleVdNil {
+ d.bdRead = false
+ return true
+ }
+ return false
+}
+
+func (d *simpleDecDriver) isBuiltinType(rt uintptr) bool {
+ return false
+}
+
+func (d *simpleDecDriver) decodeBuiltin(rt uintptr, v interface{}) {
+}
+
+func (d *simpleDecDriver) decIntAny() (ui uint64, i int64, neg bool) {
+ switch d.bd {
+ case simpleVdPosInt:
+ ui = uint64(d.r.readn1())
+ i = int64(ui)
+ case simpleVdPosInt + 1:
+ ui = uint64(d.r.readUint16())
+ i = int64(ui)
+ case simpleVdPosInt + 2:
+ ui = uint64(d.r.readUint32())
+ i = int64(ui)
+ case simpleVdPosInt + 3:
+ ui = uint64(d.r.readUint64())
+ i = int64(ui)
+ case simpleVdNegInt:
+ ui = uint64(d.r.readn1())
+ i = -(int64(ui))
+ neg = true
+ case simpleVdNegInt + 1:
+ ui = uint64(d.r.readUint16())
+ i = -(int64(ui))
+ neg = true
+ case simpleVdNegInt + 2:
+ ui = uint64(d.r.readUint32())
+ i = -(int64(ui))
+ neg = true
+ case simpleVdNegInt + 3:
+ ui = uint64(d.r.readUint64())
+ i = -(int64(ui))
+ neg = true
+ default:
+ decErr("decIntAny: Integer only valid from pos/neg integer1..8. Invalid descriptor: %v", d.bd)
+ }
+ // don't do this check, because callers may only want the unsigned value.
+ // if ui > math.MaxInt64 {
+ // decErr("decIntAny: Integer out of range for signed int64: %v", ui)
+ // }
+ return
+}
+
+func (d *simpleDecDriver) decodeInt(bitsize uint8) (i int64) {
+ _, i, _ = d.decIntAny()
+ checkOverflow(0, i, bitsize)
+ d.bdRead = false
+ return
+}
+
+func (d *simpleDecDriver) decodeUint(bitsize uint8) (ui uint64) {
+ ui, i, neg := d.decIntAny()
+ if neg {
+ decErr("Assigning negative signed value: %v, to unsigned type", i)
+ }
+ checkOverflow(ui, 0, bitsize)
+ d.bdRead = false
+ return
+}
+
+func (d *simpleDecDriver) decodeFloat(chkOverflow32 bool) (f float64) {
+ switch d.bd {
+ case simpleVdFloat32:
+ f = float64(math.Float32frombits(d.r.readUint32()))
+ case simpleVdFloat64:
+ f = math.Float64frombits(d.r.readUint64())
+ default:
+ if d.bd >= simpleVdPosInt && d.bd <= simpleVdNegInt+3 {
+ _, i, _ := d.decIntAny()
+ f = float64(i)
+ } else {
+ decErr("Float only valid from float32/64: Invalid descriptor: %v", d.bd)
+ }
+ }
+ checkOverflowFloat32(f, chkOverflow32)
+ d.bdRead = false
+ return
+}
+
+// bool can be decoded from bool only (single byte).
+func (d *simpleDecDriver) decodeBool() (b bool) {
+ switch d.bd {
+ case simpleVdTrue:
+ b = true
+ case simpleVdFalse:
+ default:
+ decErr("Invalid single-byte value for bool: %s: %x", msgBadDesc, d.bd)
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *simpleDecDriver) readMapLen() (length int) {
+ d.bdRead = false
+ return d.decLen()
+}
+
+func (d *simpleDecDriver) readArrayLen() (length int) {
+ d.bdRead = false
+ return d.decLen()
+}
+
+func (d *simpleDecDriver) decLen() int {
+ switch d.bd % 8 {
+ case 0:
+ return 0
+ case 1:
+ return int(d.r.readn1())
+ case 2:
+ return int(d.r.readUint16())
+ case 3:
+ ui := uint64(d.r.readUint32())
+ checkOverflow(ui, 0, intBitsize)
+ return int(ui)
+ case 4:
+ ui := d.r.readUint64()
+ checkOverflow(ui, 0, intBitsize)
+ return int(ui)
+ }
+ decErr("decLen: Cannot read length: bd%8 must be in range 0..4. Got: %d", d.bd%8)
+ return -1
+}
+
+func (d *simpleDecDriver) decodeString() (s string) {
+ s = string(d.r.readn(d.decLen()))
+ d.bdRead = false
+ return
+}
+
+func (d *simpleDecDriver) decodeBytes(bs []byte) (bsOut []byte, changed bool) {
+ if clen := d.decLen(); clen > 0 {
+ // if no contents in stream, don't update the passed byteslice
+ if len(bs) != clen {
+ if len(bs) > clen {
+ bs = bs[:clen]
+ } else {
+ bs = make([]byte, clen)
+ }
+ bsOut = bs
+ changed = true
+ }
+ d.r.readb(bs)
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *simpleDecDriver) decodeExt(verifyTag bool, tag byte) (xtag byte, xbs []byte) {
+ switch d.bd {
+ case simpleVdExt, simpleVdExt + 1, simpleVdExt + 2, simpleVdExt + 3, simpleVdExt + 4:
+ l := d.decLen()
+ xtag = d.r.readn1()
+ if verifyTag && xtag != tag {
+ decErr("Wrong extension tag. Got %b. Expecting: %v", xtag, tag)
+ }
+ xbs = d.r.readn(l)
+ case simpleVdByteArray, simpleVdByteArray + 1, simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
+ xbs, _ = d.decodeBytes(nil)
+ default:
+ decErr("Invalid d.vd for extensions (Expecting extensions or byte array). Got: 0x%x", d.bd)
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *simpleDecDriver) decodeNaked() (v interface{}, vt valueType, decodeFurther bool) {
+ d.initReadNext()
+
+ switch d.bd {
+ case simpleVdNil:
+ vt = valueTypeNil
+ case simpleVdFalse:
+ vt = valueTypeBool
+ v = false
+ case simpleVdTrue:
+ vt = valueTypeBool
+ v = true
+ case simpleVdPosInt, simpleVdPosInt + 1, simpleVdPosInt + 2, simpleVdPosInt + 3:
+ vt = valueTypeUint
+ ui, _, _ := d.decIntAny()
+ v = ui
+ case simpleVdNegInt, simpleVdNegInt + 1, simpleVdNegInt + 2, simpleVdNegInt + 3:
+ vt = valueTypeInt
+ _, i, _ := d.decIntAny()
+ v = i
+ case simpleVdFloat32:
+ vt = valueTypeFloat
+ v = d.decodeFloat(true)
+ case simpleVdFloat64:
+ vt = valueTypeFloat
+ v = d.decodeFloat(false)
+ case simpleVdString, simpleVdString + 1, simpleVdString + 2, simpleVdString + 3, simpleVdString + 4:
+ vt = valueTypeString
+ v = d.decodeString()
+ case simpleVdByteArray, simpleVdByteArray + 1, simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
+ vt = valueTypeBytes
+ v, _ = d.decodeBytes(nil)
+ case simpleVdExt, simpleVdExt + 1, simpleVdExt + 2, simpleVdExt + 3, simpleVdExt + 4:
+ vt = valueTypeExt
+ l := d.decLen()
+ var re RawExt
+ re.Tag = d.r.readn1()
+ re.Data = d.r.readn(l)
+ v = &re
+ vt = valueTypeExt
+ case simpleVdArray, simpleVdArray + 1, simpleVdArray + 2, simpleVdArray + 3, simpleVdArray + 4:
+ vt = valueTypeArray
+ decodeFurther = true
+ case simpleVdMap, simpleVdMap + 1, simpleVdMap + 2, simpleVdMap + 3, simpleVdMap + 4:
+ vt = valueTypeMap
+ decodeFurther = true
+ default:
+ decErr("decodeNaked: Unrecognized d.vd: 0x%x", d.bd)
+ }
+
+ if !decodeFurther {
+ d.bdRead = false
+ }
+ return
+}
+
+//------------------------------------
+
+// SimpleHandle is a Handle for a very simple encoding format.
+//
+// simple is a simplistic codec similar to binc, but not as compact.
+// - Encoding of a value is always preceeded by the descriptor byte (bd)
+// - True, false, nil are encoded fully in 1 byte (the descriptor)
+// - Integers (intXXX, uintXXX) are encoded in 1, 2, 4 or 8 bytes (plus a descriptor byte).
+// There are positive (uintXXX and intXXX >= 0) and negative (intXXX < 0) integers.
+// - Floats are encoded in 4 or 8 bytes (plus a descriptor byte)
+// - Lenght of containers (strings, bytes, array, map, extensions)
+// are encoded in 0, 1, 2, 4 or 8 bytes.
+// Zero-length containers have no length encoded.
+// For others, the number of bytes is given by pow(2, bd%3)
+// - maps are encoded as [bd] [length] [[key][value]]...
+// - arrays are encoded as [bd] [length] [value]...
+// - extensions are encoded as [bd] [length] [tag] [byte]...
+// - strings/bytearrays are encoded as [bd] [length] [byte]...
+//
+// The full spec will be published soon.
+type SimpleHandle struct {
+ BasicHandle
+}
+
+func (h *SimpleHandle) newEncDriver(w encWriter) encDriver {
+ return &simpleEncDriver{w: w, h: h}
+}
+
+func (h *SimpleHandle) newDecDriver(r decReader) decDriver {
+ return &simpleDecDriver{r: r, h: h}
+}
+
+func (_ *SimpleHandle) writeExt() bool {
+ return true
+}
+
+func (h *SimpleHandle) getBasicHandle() *BasicHandle {
+ return &h.BasicHandle
+}
+
+var _ decDriver = (*simpleDecDriver)(nil)
+var _ encDriver = (*simpleEncDriver)(nil)
--- /dev/null
+// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a BSD-style license found in the LICENSE file.
+
+package codec
+
+import (
+ "time"
+)
+
+var (
+ timeDigits = [...]byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
+)
+
+// EncodeTime encodes a time.Time as a []byte, including
+// information on the instant in time and UTC offset.
+//
+// Format Description
+//
+// A timestamp is composed of 3 components:
+//
+// - secs: signed integer representing seconds since unix epoch
+// - nsces: unsigned integer representing fractional seconds as a
+// nanosecond offset within secs, in the range 0 <= nsecs < 1e9
+// - tz: signed integer representing timezone offset in minutes east of UTC,
+// and a dst (daylight savings time) flag
+//
+// When encoding a timestamp, the first byte is the descriptor, which
+// defines which components are encoded and how many bytes are used to
+// encode secs and nsecs components. *If secs/nsecs is 0 or tz is UTC, it
+// is not encoded in the byte array explicitly*.
+//
+// Descriptor 8 bits are of the form `A B C DDD EE`:
+// A: Is secs component encoded? 1 = true
+// B: Is nsecs component encoded? 1 = true
+// C: Is tz component encoded? 1 = true
+// DDD: Number of extra bytes for secs (range 0-7).
+// If A = 1, secs encoded in DDD+1 bytes.
+// If A = 0, secs is not encoded, and is assumed to be 0.
+// If A = 1, then we need at least 1 byte to encode secs.
+// DDD says the number of extra bytes beyond that 1.
+// E.g. if DDD=0, then secs is represented in 1 byte.
+// if DDD=2, then secs is represented in 3 bytes.
+// EE: Number of extra bytes for nsecs (range 0-3).
+// If B = 1, nsecs encoded in EE+1 bytes (similar to secs/DDD above)
+//
+// Following the descriptor bytes, subsequent bytes are:
+//
+// secs component encoded in `DDD + 1` bytes (if A == 1)
+// nsecs component encoded in `EE + 1` bytes (if B == 1)
+// tz component encoded in 2 bytes (if C == 1)
+//
+// secs and nsecs components are integers encoded in a BigEndian
+// 2-complement encoding format.
+//
+// tz component is encoded as 2 bytes (16 bits). Most significant bit 15 to
+// Least significant bit 0 are described below:
+//
+// Timezone offset has a range of -12:00 to +14:00 (ie -720 to +840 minutes).
+// Bit 15 = have\_dst: set to 1 if we set the dst flag.
+// Bit 14 = dst\_on: set to 1 if dst is in effect at the time, or 0 if not.
+// Bits 13..0 = timezone offset in minutes. It is a signed integer in Big Endian format.
+//
+func encodeTime(t time.Time) []byte {
+ //t := rv.Interface().(time.Time)
+ tsecs, tnsecs := t.Unix(), t.Nanosecond()
+ var (
+ bd byte
+ btmp [8]byte
+ bs [16]byte
+ i int = 1
+ )
+ l := t.Location()
+ if l == time.UTC {
+ l = nil
+ }
+ if tsecs != 0 {
+ bd = bd | 0x80
+ bigen.PutUint64(btmp[:], uint64(tsecs))
+ f := pruneSignExt(btmp[:], tsecs >= 0)
+ bd = bd | (byte(7-f) << 2)
+ copy(bs[i:], btmp[f:])
+ i = i + (8 - f)
+ }
+ if tnsecs != 0 {
+ bd = bd | 0x40
+ bigen.PutUint32(btmp[:4], uint32(tnsecs))
+ f := pruneSignExt(btmp[:4], true)
+ bd = bd | byte(3-f)
+ copy(bs[i:], btmp[f:4])
+ i = i + (4 - f)
+ }
+ if l != nil {
+ bd = bd | 0x20
+ // Note that Go Libs do not give access to dst flag.
+ _, zoneOffset := t.Zone()
+ //zoneName, zoneOffset := t.Zone()
+ zoneOffset /= 60
+ z := uint16(zoneOffset)
+ bigen.PutUint16(btmp[:2], z)
+ // clear dst flags
+ bs[i] = btmp[0] & 0x3f
+ bs[i+1] = btmp[1]
+ i = i + 2
+ }
+ bs[0] = bd
+ return bs[0:i]
+}
+
+// DecodeTime decodes a []byte into a time.Time.
+func decodeTime(bs []byte) (tt time.Time, err error) {
+ bd := bs[0]
+ var (
+ tsec int64
+ tnsec uint32
+ tz uint16
+ i byte = 1
+ i2 byte
+ n byte
+ )
+ if bd&(1<<7) != 0 {
+ var btmp [8]byte
+ n = ((bd >> 2) & 0x7) + 1
+ i2 = i + n
+ copy(btmp[8-n:], bs[i:i2])
+ //if first bit of bs[i] is set, then fill btmp[0..8-n] with 0xff (ie sign extend it)
+ if bs[i]&(1<<7) != 0 {
+ copy(btmp[0:8-n], bsAll0xff)
+ //for j,k := byte(0), 8-n; j < k; j++ { btmp[j] = 0xff }
+ }
+ i = i2
+ tsec = int64(bigen.Uint64(btmp[:]))
+ }
+ if bd&(1<<6) != 0 {
+ var btmp [4]byte
+ n = (bd & 0x3) + 1
+ i2 = i + n
+ copy(btmp[4-n:], bs[i:i2])
+ i = i2
+ tnsec = bigen.Uint32(btmp[:])
+ }
+ if bd&(1<<5) == 0 {
+ tt = time.Unix(tsec, int64(tnsec)).UTC()
+ return
+ }
+ // In stdlib time.Parse, when a date is parsed without a zone name, it uses "" as zone name.
+ // However, we need name here, so it can be shown when time is printed.
+ // Zone name is in form: UTC-08:00.
+ // Note that Go Libs do not give access to dst flag, so we ignore dst bits
+
+ i2 = i + 2
+ tz = bigen.Uint16(bs[i:i2])
+ i = i2
+ // sign extend sign bit into top 2 MSB (which were dst bits):
+ if tz&(1<<13) == 0 { // positive
+ tz = tz & 0x3fff //clear 2 MSBs: dst bits
+ } else { // negative
+ tz = tz | 0xc000 //set 2 MSBs: dst bits
+ //tzname[3] = '-' (TODO: verify. this works here)
+ }
+ tzint := int16(tz)
+ if tzint == 0 {
+ tt = time.Unix(tsec, int64(tnsec)).UTC()
+ } else {
+ // For Go Time, do not use a descriptive timezone.
+ // It's unnecessary, and makes it harder to do a reflect.DeepEqual.
+ // The Offset already tells what the offset should be, if not on UTC and unknown zone name.
+ // var zoneName = timeLocUTCName(tzint)
+ tt = time.Unix(tsec, int64(tnsec)).In(time.FixedZone("", int(tzint)*60))
+ }
+ return
+}
+
+func timeLocUTCName(tzint int16) string {
+ if tzint == 0 {
+ return "UTC"
+ }
+ var tzname = []byte("UTC+00:00")
+ //tzname := fmt.Sprintf("UTC%s%02d:%02d", tzsign, tz/60, tz%60) //perf issue using Sprintf. inline below.
+ //tzhr, tzmin := tz/60, tz%60 //faster if u convert to int first
+ var tzhr, tzmin int16
+ if tzint < 0 {
+ tzname[3] = '-' // (TODO: verify. this works here)
+ tzhr, tzmin = -tzint/60, (-tzint)%60
+ } else {
+ tzhr, tzmin = tzint/60, tzint%60
+ }
+ tzname[4] = timeDigits[tzhr/10]
+ tzname[5] = timeDigits[tzhr%10]
+ tzname[7] = timeDigits[tzmin/10]
+ tzname[8] = timeDigits[tzmin%10]
+ return string(tzname)
+ //return time.FixedZone(string(tzname), int(tzint)*60)
+}
--- /dev/null
+Mozilla Public License, version 2.0
+
+1. Definitions
+
+1.1. “Contributor”
+
+ means each individual or legal entity that creates, contributes to the
+ creation of, or owns Covered Software.
+
+1.2. “Contributor Version”
+
+ means the combination of the Contributions of others (if any) used by a
+ Contributor and that particular Contributor’s Contribution.
+
+1.3. “Contribution”
+
+ means Covered Software of a particular Contributor.
+
+1.4. “Covered Software”
+
+ means Source Code Form to which the initial Contributor has attached the
+ notice in Exhibit A, the Executable Form of such Source Code Form, and
+ Modifications of such Source Code Form, in each case including portions
+ thereof.
+
+1.5. “Incompatible With Secondary Licenses”
+ means
+
+ a. that the initial Contributor has attached the notice described in
+ Exhibit B to the Covered Software; or
+
+ b. that the Covered Software was made available under the terms of version
+ 1.1 or earlier of the License, but not also under the terms of a
+ Secondary License.
+
+1.6. “Executable Form”
+
+ means any form of the work other than Source Code Form.
+
+1.7. “Larger Work”
+
+ means a work that combines Covered Software with other material, in a separate
+ file or files, that is not Covered Software.
+
+1.8. “License”
+
+ means this document.
+
+1.9. “Licensable”
+
+ means having the right to grant, to the maximum extent possible, whether at the
+ time of the initial grant or subsequently, any and all of the rights conveyed by
+ this License.
+
+1.10. “Modifications”
+
+ means any of the following:
+
+ a. any file in Source Code Form that results from an addition to, deletion
+ from, or modification of the contents of Covered Software; or
+
+ b. any new file in Source Code Form that contains any Covered Software.
+
+1.11. “Patent Claims” of a Contributor
+
+ means any patent claim(s), including without limitation, method, process,
+ and apparatus claims, in any patent Licensable by such Contributor that
+ would be infringed, but for the grant of the License, by the making,
+ using, selling, offering for sale, having made, import, or transfer of
+ either its Contributions or its Contributor Version.
+
+1.12. “Secondary License”
+
+ means either the GNU General Public License, Version 2.0, the GNU Lesser
+ General Public License, Version 2.1, the GNU Affero General Public
+ License, Version 3.0, or any later versions of those licenses.
+
+1.13. “Source Code Form”
+
+ means the form of the work preferred for making modifications.
+
+1.14. “You” (or “Your”)
+
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, “You” includes any entity that controls, is
+ controlled by, or is under common control with You. For purposes of this
+ definition, “control” means (a) the power, direct or indirect, to cause
+ the direction or management of such entity, whether by contract or
+ otherwise, or (b) ownership of more than fifty percent (50%) of the
+ outstanding shares or beneficial ownership of such entity.
+
+
+2. License Grants and Conditions
+
+2.1. Grants
+
+ Each Contributor hereby grants You a world-wide, royalty-free,
+ non-exclusive license:
+
+ a. under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or as
+ part of a Larger Work; and
+
+ b. under Patent Claims of such Contributor to make, use, sell, offer for
+ sale, have made, import, and otherwise transfer either its Contributions
+ or its Contributor Version.
+
+2.2. Effective Date
+
+ The licenses granted in Section 2.1 with respect to any Contribution become
+ effective for each Contribution on the date the Contributor first distributes
+ such Contribution.
+
+2.3. Limitations on Grant Scope
+
+ The licenses granted in this Section 2 are the only rights granted under this
+ License. No additional rights or licenses will be implied from the distribution
+ or licensing of Covered Software under this License. Notwithstanding Section
+ 2.1(b) above, no patent license is granted by a Contributor:
+
+ a. for any code that a Contributor has removed from Covered Software; or
+
+ b. for infringements caused by: (i) Your and any other third party’s
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+ c. under Patent Claims infringed by Covered Software in the absence of its
+ Contributions.
+
+ This License does not grant any rights in the trademarks, service marks, or
+ logos of any Contributor (except as may be necessary to comply with the
+ notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+ No Contributor makes additional grants as a result of Your choice to
+ distribute the Covered Software under a subsequent version of this License
+ (see Section 10.2) or under the terms of a Secondary License (if permitted
+ under the terms of Section 3.3).
+
+2.5. Representation
+
+ Each Contributor represents that the Contributor believes its Contributions
+ are its original creation(s) or it has sufficient rights to grant the
+ rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+ This License is not intended to limit any rights You have under applicable
+ copyright doctrines of fair use, fair dealing, or other equivalents.
+
+2.7. Conditions
+
+ Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
+ Section 2.1.
+
+
+3. Responsibilities
+
+3.1. Distribution of Source Form
+
+ All distribution of Covered Software in Source Code Form, including any
+ Modifications that You create or to which You contribute, must be under the
+ terms of this License. You must inform recipients that the Source Code Form
+ of the Covered Software is governed by the terms of this License, and how
+ they can obtain a copy of this License. You may not attempt to alter or
+ restrict the recipients’ rights in the Source Code Form.
+
+3.2. Distribution of Executable Form
+
+ If You distribute Covered Software in Executable Form then:
+
+ a. such Covered Software must also be made available in Source Code Form,
+ as described in Section 3.1, and You must inform recipients of the
+ Executable Form how they can obtain a copy of such Source Code Form by
+ reasonable means in a timely manner, at a charge no more than the cost
+ of distribution to the recipient; and
+
+ b. You may distribute such Executable Form under the terms of this License,
+ or sublicense it under different terms, provided that the license for
+ the Executable Form does not attempt to limit or alter the recipients’
+ rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+ You may create and distribute a Larger Work under terms of Your choice,
+ provided that You also comply with the requirements of this License for the
+ Covered Software. If the Larger Work is a combination of Covered Software
+ with a work governed by one or more Secondary Licenses, and the Covered
+ Software is not Incompatible With Secondary Licenses, this License permits
+ You to additionally distribute such Covered Software under the terms of
+ such Secondary License(s), so that the recipient of the Larger Work may, at
+ their option, further distribute the Covered Software under the terms of
+ either this License or such Secondary License(s).
+
+3.4. Notices
+
+ You may not remove or alter the substance of any license notices (including
+ copyright notices, patent notices, disclaimers of warranty, or limitations
+ of liability) contained within the Source Code Form of the Covered
+ Software, except that You may alter any license notices to the extent
+ required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+ You may choose to offer, and to charge a fee for, warranty, support,
+ indemnity or liability obligations to one or more recipients of Covered
+ Software. However, You may do so only on Your own behalf, and not on behalf
+ of any Contributor. You must make it absolutely clear that any such
+ warranty, support, indemnity, or liability obligation is offered by You
+ alone, and You hereby agree to indemnify every Contributor for any
+ liability incurred by such Contributor as a result of warranty, support,
+ indemnity or liability terms You offer. You may include additional
+ disclaimers of warranty and limitations of liability specific to any
+ jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+
+ If it is impossible for You to comply with any of the terms of this License
+ with respect to some or all of the Covered Software due to statute, judicial
+ order, or regulation then You must: (a) comply with the terms of this License
+ to the maximum extent possible; and (b) describe the limitations and the code
+ they affect. Such description must be placed in a text file included with all
+ distributions of the Covered Software under this License. Except to the
+ extent prohibited by statute or regulation, such description must be
+ sufficiently detailed for a recipient of ordinary skill to be able to
+ understand it.
+
+5. Termination
+
+5.1. The rights granted under this License will terminate automatically if You
+ fail to comply with any of its terms. However, if You become compliant,
+ then the rights granted under this License from a particular Contributor
+ are reinstated (a) provisionally, unless and until such Contributor
+ explicitly and finally terminates Your grants, and (b) on an ongoing basis,
+ if such Contributor fails to notify You of the non-compliance by some
+ reasonable means prior to 60 days after You have come back into compliance.
+ Moreover, Your grants from a particular Contributor are reinstated on an
+ ongoing basis if such Contributor notifies You of the non-compliance by
+ some reasonable means, this is the first time You have received notice of
+ non-compliance with this License from such Contributor, and You become
+ compliant prior to 30 days after Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+ infringement claim (excluding declaratory judgment actions, counter-claims,
+ and cross-claims) alleging that a Contributor Version directly or
+ indirectly infringes any patent, then the rights granted to You by any and
+ all Contributors for the Covered Software under Section 2.1 of this License
+ shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
+ license agreements (excluding distributors and resellers) which have been
+ validly granted by You or Your distributors under this License prior to
+ termination shall survive termination.
+
+6. Disclaimer of Warranty
+
+ Covered Software is provided under this License on an “as is” basis, without
+ warranty of any kind, either expressed, implied, or statutory, including,
+ without limitation, warranties that the Covered Software is free of defects,
+ merchantable, fit for a particular purpose or non-infringing. The entire
+ risk as to the quality and performance of the Covered Software is with You.
+ Should any Covered Software prove defective in any respect, You (not any
+ Contributor) assume the cost of any necessary servicing, repair, or
+ correction. This disclaimer of warranty constitutes an essential part of this
+ License. No use of any Covered Software is authorized under this License
+ except under this disclaimer.
+
+7. Limitation of Liability
+
+ Under no circumstances and under no legal theory, whether tort (including
+ negligence), contract, or otherwise, shall any Contributor, or anyone who
+ distributes Covered Software as permitted above, be liable to You for any
+ direct, indirect, special, incidental, or consequential damages of any
+ character including, without limitation, damages for lost profits, loss of
+ goodwill, work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses, even if such party shall have been
+ informed of the possibility of such damages. This limitation of liability
+ shall not apply to liability for death or personal injury resulting from such
+ party’s negligence to the extent applicable law prohibits such limitation.
+ Some jurisdictions do not allow the exclusion or limitation of incidental or
+ consequential damages, so this exclusion and limitation may not apply to You.
+
+8. Litigation
+
+ Any litigation relating to this License may be brought only in the courts of
+ a jurisdiction where the defendant maintains its principal place of business
+ and such litigation shall be governed by laws of that jurisdiction, without
+ reference to its conflict-of-law provisions. Nothing in this Section shall
+ prevent a party’s ability to bring cross-claims or counter-claims.
+
+9. Miscellaneous
+
+ This License represents the complete agreement concerning the subject matter
+ hereof. If any provision of this License is held to be unenforceable, such
+ provision shall be reformed only to the extent necessary to make it
+ enforceable. Any law or regulation which provides that the language of a
+ contract shall be construed against the drafter shall not be used to construe
+ this License against a Contributor.
+
+
+10. Versions of the License
+
+10.1. New Versions
+
+ Mozilla Foundation is the license steward. Except as provided in Section
+ 10.3, no one other than the license steward has the right to modify or
+ publish new versions of this License. Each version will be given a
+ distinguishing version number.
+
+10.2. Effect of New Versions
+
+ You may distribute the Covered Software under the terms of the version of
+ the License under which You originally received the Covered Software, or
+ under the terms of any subsequent version published by the license
+ steward.
+
+10.3. Modified Versions
+
+ If you create software not governed by this License, and you want to
+ create a new license for such software, you may create and use a modified
+ version of this License if you rename the license and remove any
+ references to the name of the license steward (except to note that such
+ modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
+ If You choose to distribute Source Code Form that is Incompatible With
+ Secondary Licenses under the terms of this version of the License, the
+ notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+
+ This Source Code Form is subject to the
+ terms of the Mozilla Public License, v.
+ 2.0. If a copy of the MPL was not
+ distributed with this file, You can
+ obtain one at
+ http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular file, then
+You may include the notice in a location (such as a LICENSE file in a relevant
+directory) where a recipient would be likely to look for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - “Incompatible With Secondary Licenses” Notice
+
+ This Source Code Form is “Incompatible
+ With Secondary Licenses”, as defined by
+ the Mozilla Public License, v. 2.0.
--- /dev/null
+TEST?=./...
+
+default: test
+
+# test runs the test suite and vets the code.
+test: generate
+ @echo "==> Running tests..."
+ @go list $(TEST) \
+ | grep -v "/vendor/" \
+ | xargs -n1 go test -timeout=60s -parallel=10 ${TESTARGS}
+
+# testrace runs the race checker
+testrace: generate
+ @echo "==> Running tests (race)..."
+ @go list $(TEST) \
+ | grep -v "/vendor/" \
+ | xargs -n1 go test -timeout=60s -race ${TESTARGS}
+
+# updatedeps installs all the dependencies needed to run and build.
+updatedeps:
+ @sh -c "'${CURDIR}/scripts/deps.sh' '${NAME}'"
+
+# generate runs `go generate` to build the dynamically generated source files.
+generate:
+ @echo "==> Generating..."
+ @find . -type f -name '.DS_Store' -delete
+ @go list ./... \
+ | grep -v "/vendor/" \
+ | xargs -n1 go generate
+
+.PHONY: default test testrace updatedeps generate
--- /dev/null
+# go-multierror
+
+[][travis]
+[][godocs]
+
+[travis]: https://travis-ci.org/hashicorp/go-multierror
+[godocs]: https://godoc.org/github.com/hashicorp/go-multierror
+
+`go-multierror` is a package for Go that provides a mechanism for
+representing a list of `error` values as a single `error`.
+
+This allows a function in Go to return an `error` that might actually
+be a list of errors. If the caller knows this, they can unwrap the
+list and access the errors. If the caller doesn't know, the error
+formats to a nice human-readable format.
+
+`go-multierror` implements the
+[errwrap](https://github.com/hashicorp/errwrap) interface so that it can
+be used with that library, as well.
+
+## Installation and Docs
+
+Install using `go get github.com/hashicorp/go-multierror`.
+
+Full documentation is available at
+http://godoc.org/github.com/hashicorp/go-multierror
+
+## Usage
+
+go-multierror is easy to use and purposely built to be unobtrusive in
+existing Go applications/libraries that may not be aware of it.
+
+**Building a list of errors**
+
+The `Append` function is used to create a list of errors. This function
+behaves a lot like the Go built-in `append` function: it doesn't matter
+if the first argument is nil, a `multierror.Error`, or any other `error`,
+the function behaves as you would expect.
+
+```go
+var result error
+
+if err := step1(); err != nil {
+ result = multierror.Append(result, err)
+}
+if err := step2(); err != nil {
+ result = multierror.Append(result, err)
+}
+
+return result
+```
+
+**Customizing the formatting of the errors**
+
+By specifying a custom `ErrorFormat`, you can customize the format
+of the `Error() string` function:
+
+```go
+var result *multierror.Error
+
+// ... accumulate errors here, maybe using Append
+
+if result != nil {
+ result.ErrorFormat = func([]error) string {
+ return "errors!"
+ }
+}
+```
+
+**Accessing the list of errors**
+
+`multierror.Error` implements `error` so if the caller doesn't know about
+multierror, it will work just fine. But if you're aware a multierror might
+be returned, you can use type switches to access the list of errors:
+
+```go
+if err := something(); err != nil {
+ if merr, ok := err.(*multierror.Error); ok {
+ // Use merr.Errors
+ }
+}
+```
+
+**Returning a multierror only if there are errors**
+
+If you build a `multierror.Error`, you can use the `ErrorOrNil` function
+to return an `error` implementation only if there are errors to return:
+
+```go
+var result *multierror.Error
+
+// ... accumulate errors here
+
+// Return the `error` only if errors were added to the multierror, otherwise
+// return nil since there are no errors.
+return result.ErrorOrNil()
+```
--- /dev/null
+package multierror
+
+// Append is a helper function that will append more errors
+// onto an Error in order to create a larger multi-error.
+//
+// If err is not a multierror.Error, then it will be turned into
+// one. If any of the errs are multierr.Error, they will be flattened
+// one level into err.
+func Append(err error, errs ...error) *Error {
+ switch err := err.(type) {
+ case *Error:
+ // Typed nils can reach here, so initialize if we are nil
+ if err == nil {
+ err = new(Error)
+ }
+
+ // Go through each error and flatten
+ for _, e := range errs {
+ switch e := e.(type) {
+ case *Error:
+ if e != nil {
+ err.Errors = append(err.Errors, e.Errors...)
+ }
+ default:
+ if e != nil {
+ err.Errors = append(err.Errors, e)
+ }
+ }
+ }
+
+ return err
+ default:
+ newErrs := make([]error, 0, len(errs)+1)
+ if err != nil {
+ newErrs = append(newErrs, err)
+ }
+ newErrs = append(newErrs, errs...)
+
+ return Append(&Error{}, newErrs...)
+ }
+}
--- /dev/null
+package multierror
+
+// Flatten flattens the given error, merging any *Errors together into
+// a single *Error.
+func Flatten(err error) error {
+ // If it isn't an *Error, just return the error as-is
+ if _, ok := err.(*Error); !ok {
+ return err
+ }
+
+ // Otherwise, make the result and flatten away!
+ flatErr := new(Error)
+ flatten(err, flatErr)
+ return flatErr
+}
+
+func flatten(err error, flatErr *Error) {
+ switch err := err.(type) {
+ case *Error:
+ for _, e := range err.Errors {
+ flatten(e, flatErr)
+ }
+ default:
+ flatErr.Errors = append(flatErr.Errors, err)
+ }
+}
--- /dev/null
+package multierror
+
+import (
+ "fmt"
+ "strings"
+)
+
+// ErrorFormatFunc is a function callback that is called by Error to
+// turn the list of errors into a string.
+type ErrorFormatFunc func([]error) string
+
+// ListFormatFunc is a basic formatter that outputs the number of errors
+// that occurred along with a bullet point list of the errors.
+func ListFormatFunc(es []error) string {
+ if len(es) == 1 {
+ return fmt.Sprintf("1 error occurred:\n\n* %s", es[0])
+ }
+
+ points := make([]string, len(es))
+ for i, err := range es {
+ points[i] = fmt.Sprintf("* %s", err)
+ }
+
+ return fmt.Sprintf(
+ "%d errors occurred:\n\n%s",
+ len(es), strings.Join(points, "\n"))
+}
--- /dev/null
+package multierror
+
+import (
+ "fmt"
+)
+
+// Error is an error type to track multiple errors. This is used to
+// accumulate errors in cases and return them as a single "error".
+type Error struct {
+ Errors []error
+ ErrorFormat ErrorFormatFunc
+}
+
+func (e *Error) Error() string {
+ fn := e.ErrorFormat
+ if fn == nil {
+ fn = ListFormatFunc
+ }
+
+ return fn(e.Errors)
+}
+
+// ErrorOrNil returns an error interface if this Error represents
+// a list of errors, or returns nil if the list of errors is empty. This
+// function is useful at the end of accumulation to make sure that the value
+// returned represents the existence of errors.
+func (e *Error) ErrorOrNil() error {
+ if e == nil {
+ return nil
+ }
+ if len(e.Errors) == 0 {
+ return nil
+ }
+
+ return e
+}
+
+func (e *Error) GoString() string {
+ return fmt.Sprintf("*%#v", *e)
+}
+
+// WrappedErrors returns the list of errors that this Error is wrapping.
+// It is an implementation of the errwrap.Wrapper interface so that
+// multierror.Error can be used with that library.
+//
+// This method is not safe to be called concurrently and is no different
+// than accessing the Errors field directly. It is implemented only to
+// satisfy the errwrap.Wrapper interface.
+func (e *Error) WrappedErrors() []error {
+ return e.Errors
+}
--- /dev/null
+package multierror
+
+import (
+ "fmt"
+
+ "github.com/hashicorp/errwrap"
+)
+
+// Prefix is a helper function that will prefix some text
+// to the given error. If the error is a multierror.Error, then
+// it will be prefixed to each wrapped error.
+//
+// This is useful to use when appending multiple multierrors
+// together in order to give better scoping.
+func Prefix(err error, prefix string) error {
+ if err == nil {
+ return nil
+ }
+
+ format := fmt.Sprintf("%s {{err}}", prefix)
+ switch err := err.(type) {
+ case *Error:
+ // Typed nils can reach here, so initialize if we are nil
+ if err == nil {
+ err = new(Error)
+ }
+
+ // Wrap each of the errors
+ for i, e := range err.Errors {
+ err.Errors[i] = errwrap.Wrapf(format, e)
+ }
+
+ return err
+ default:
+ return errwrap.Wrapf(format, err)
+ }
+}
--- /dev/null
+TOOLS= golang.org/x/tools/cover
+GOCOVER_TMPFILE?= $(GOCOVER_FILE).tmp
+GOCOVER_FILE?= .cover.out
+GOCOVERHTML?= coverage.html
+FIND=`/usr/bin/which 2> /dev/null gfind find | /usr/bin/grep -v ^no | /usr/bin/head -n 1`
+XARGS=`/usr/bin/which 2> /dev/null gxargs xargs | /usr/bin/grep -v ^no | /usr/bin/head -n 1`
+
+test:: $(GOCOVER_FILE)
+ @$(MAKE) -C cmd/sockaddr test
+
+cover:: coverage_report
+
+$(GOCOVER_FILE)::
+ @${FIND} . -type d ! -path '*cmd*' ! -path '*.git*' -print0 | ${XARGS} -0 -I % sh -ec "cd % && rm -f $(GOCOVER_TMPFILE) && go test -coverprofile=$(GOCOVER_TMPFILE)"
+
+ @echo 'mode: set' > $(GOCOVER_FILE)
+ @${FIND} . -type f ! -path '*cmd*' ! -path '*.git*' -name "$(GOCOVER_TMPFILE)" -print0 | ${XARGS} -0 -n1 cat $(GOCOVER_TMPFILE) | grep -v '^mode: ' >> ${PWD}/$(GOCOVER_FILE)
+
+$(GOCOVERHTML): $(GOCOVER_FILE)
+ go tool cover -html=$(GOCOVER_FILE) -o $(GOCOVERHTML)
+
+coverage_report:: $(GOCOVER_FILE)
+ go tool cover -html=$(GOCOVER_FILE)
+
+audit_tools::
+ @go get -u github.com/golang/lint/golint && echo "Installed golint:"
+ @go get -u github.com/fzipp/gocyclo && echo "Installed gocyclo:"
+ @go get -u github.com/remyoudompheng/go-misc/deadcode && echo "Installed deadcode:"
+ @go get -u github.com/client9/misspell/cmd/misspell && echo "Installed misspell:"
+ @go get -u github.com/gordonklaus/ineffassign && echo "Installed ineffassign:"
+
+audit::
+ deadcode
+ go tool vet -all *.go
+ go tool vet -shadow=true *.go
+ golint *.go
+ ineffassign .
+ gocyclo -over 65 *.go
+ misspell *.go
+
+clean::
+ rm -f $(GOCOVER_FILE) $(GOCOVERHTML)
+
+dev::
+ @go build
+ @$(MAKE) -B -C cmd/sockaddr sockaddr
+
+install::
+ @go install
+ @$(MAKE) -C cmd/sockaddr install
+
+doc::
+ @echo Visit: http://127.0.0.1:6161/pkg/github.com/hashicorp/go-sockaddr/
+ godoc -http=:6161 -goroot $GOROOT
+
+world::
+ @set -e; \
+ for os in solaris darwin freebsd linux windows; do \
+ for arch in amd64; do \
+ printf "Building on %s-%s\n" "$${os}" "$${arch}" ; \
+ env GOOS="$${os}" GOARCH="$${arch}" go build -o /dev/null; \
+ done; \
+ done
+
+ $(MAKE) -C cmd/sockaddr world
--- /dev/null
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
--- /dev/null
+# go-sockaddr
+
+## `sockaddr` Library
+
+Socket address convenience functions for Go. `go-sockaddr` is a convenience
+library that makes doing the right thing with IP addresses easy. `go-sockaddr`
+is loosely modeled after the UNIX `sockaddr_t` and creates a union of the family
+of `sockaddr_t` types (see below for an ascii diagram). Library documentation
+is available
+at
+[https://godoc.org/github.com/hashicorp/go-sockaddr](https://godoc.org/github.com/hashicorp/go-sockaddr).
+The primary intent of the library was to make it possible to define heuristics
+for selecting the correct IP addresses when a configuration is evaluated at
+runtime. See
+the
+[docs](https://godoc.org/github.com/hashicorp/go-sockaddr),
+[`template` package](https://godoc.org/github.com/hashicorp/go-sockaddr/template),
+tests,
+and
+[CLI utility](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr)
+for details and hints as to how to use this library.
+
+For example, with this library it is possible to find an IP address that:
+
+* is attached to a default route
+ ([`GetDefaultInterfaces()`](https://godoc.org/github.com/hashicorp/go-sockaddr#GetDefaultInterfaces))
+* is contained within a CIDR block ([`IfByNetwork()`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByNetwork))
+* is an RFC1918 address
+ ([`IfByRFC("1918")`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByRFC))
+* is ordered
+ ([`OrderedIfAddrBy(args)`](https://godoc.org/github.com/hashicorp/go-sockaddr#OrderedIfAddrBy) where
+ `args` includes, but is not limited
+ to,
+ [`AscIfType`](https://godoc.org/github.com/hashicorp/go-sockaddr#AscIfType),
+ [`AscNetworkSize`](https://godoc.org/github.com/hashicorp/go-sockaddr#AscNetworkSize))
+* excludes all IPv6 addresses
+ ([`IfByType("^(IPv4)$")`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByType))
+* is larger than a `/32`
+ ([`IfByMaskSize(32)`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByMaskSize))
+* is not on a `down` interface
+ ([`ExcludeIfs("flags", "down")`](https://godoc.org/github.com/hashicorp/go-sockaddr#ExcludeIfs))
+* preferences an IPv6 address over an IPv4 address
+ ([`SortIfByType()`](https://godoc.org/github.com/hashicorp/go-sockaddr#SortIfByType) +
+ [`ReverseIfAddrs()`](https://godoc.org/github.com/hashicorp/go-sockaddr#ReverseIfAddrs)); and
+* excludes any IP in RFC6890 address
+ ([`IfByRFC("6890")`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByRFC))
+
+Or any combination or variation therein.
+
+There are also a few simple helper functions such as `GetPublicIP` and
+`GetPrivateIP` which both return strings and select the first public or private
+IP address on the default interface, respectively. Similarly, there is also a
+helper function called `GetInterfaceIP` which returns the first usable IP
+address on the named interface.
+
+## `sockaddr` CLI
+
+Given the possible complexity of the `sockaddr` library, there is a CLI utility
+that accompanies the library, also
+called
+[`sockaddr`](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr).
+The
+[`sockaddr`](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr)
+utility exposes nearly all of the functionality of the library and can be used
+either as an administrative tool or testing tool. To install
+the
+[`sockaddr`](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr),
+run:
+
+```text
+$ go get -u github.com/hashicorp/go-sockaddr/cmd/sockaddr
+```
+
+If you're familiar with UNIX's `sockaddr` struct's, the following diagram
+mapping the C `sockaddr` (top) to `go-sockaddr` structs (bottom) and
+interfaces will be helpful:
+
+```
++-------------------------------------------------------+
+| |
+| sockaddr |
+| SockAddr |
+| |
+| +--------------+ +----------------------------------+ |
+| | sockaddr_un | | | |
+| | SockAddrUnix | | sockaddr_in{,6} | |
+| +--------------+ | IPAddr | |
+| | | |
+| | +-------------+ +--------------+ | |
+| | | sockaddr_in | | sockaddr_in6 | | |
+| | | IPv4Addr | | IPv6Addr | | |
+| | +-------------+ +--------------+ | |
+| | | |
+| +----------------------------------+ |
+| |
++-------------------------------------------------------+
+```
+
+## Inspiration and Design
+
+There were many subtle inspirations that led to this design, but the most direct
+inspiration for the filtering syntax was
+OpenBSD's
+[`pf.conf(5)`](https://www.freebsd.org/cgi/man.cgi?query=pf.conf&apropos=0&sektion=0&arch=default&format=html#PARAMETERS) firewall
+syntax that lets you select the first IP address on a given named interface.
+The original problem stemmed from:
+
+* needing to create immutable images using [Packer](https://www.packer.io) that
+ ran the [Consul](https://www.consul.io) process (Consul can only use one IP
+ address at a time);
+* images that may or may not have multiple interfaces or IP addresses at
+ runtime; and
+* we didn't want to rely on configuration management to render out the correct
+ IP address if the VM image was being used in an auto-scaling group.
+
+Instead we needed some way to codify a heuristic that would correctly select the
+right IP address but the input parameters were not known when the image was
+created.
--- /dev/null
+/*
+Package sockaddr is a Go implementation of the UNIX socket family data types and
+related helper functions.
+*/
+package sockaddr
--- /dev/null
+package sockaddr
+
+import "strings"
+
+// ifAddrAttrMap is a map of the IfAddr type-specific attributes.
+var ifAddrAttrMap map[AttrName]func(IfAddr) string
+var ifAddrAttrs []AttrName
+
+func init() {
+ ifAddrAttrInit()
+}
+
+// GetPrivateIP returns a string with a single IP address that is part of RFC
+// 6890 and has a default route. If the system can't determine its IP address
+// or find an RFC 6890 IP address, an empty string will be returned instead.
+// This function is the `eval` equivalent of:
+//
+// ```
+// $ sockaddr eval -r '{{GetPrivateInterfaces | attr "address"}}'
+/// ```
+func GetPrivateIP() (string, error) {
+ privateIfs, err := GetPrivateInterfaces()
+ if err != nil {
+ return "", err
+ }
+ if len(privateIfs) < 1 {
+ return "", nil
+ }
+
+ ifAddr := privateIfs[0]
+ ip := *ToIPAddr(ifAddr.SockAddr)
+ return ip.NetIP().String(), nil
+}
+
+// GetPrivateIPs returns a string with all IP addresses that are part of RFC
+// 6890 (regardless of whether or not there is a default route, unlike
+// GetPublicIP). If the system can't find any RFC 6890 IP addresses, an empty
+// string will be returned instead. This function is the `eval` equivalent of:
+//
+// ```
+// $ sockaddr eval -r '{{GetAllInterfaces | include "RFC" "6890" | join "address" " "}}'
+/// ```
+func GetPrivateIPs() (string, error) {
+ ifAddrs, err := GetAllInterfaces()
+ if err != nil {
+ return "", err
+ } else if len(ifAddrs) < 1 {
+ return "", nil
+ }
+
+ ifAddrs, _ = FilterIfByType(ifAddrs, TypeIP)
+ if len(ifAddrs) == 0 {
+ return "", nil
+ }
+
+ OrderedIfAddrBy(AscIfType, AscIfNetworkSize).Sort(ifAddrs)
+
+ ifAddrs, _, err = IfByRFC("6890", ifAddrs)
+ if err != nil {
+ return "", err
+ } else if len(ifAddrs) == 0 {
+ return "", nil
+ }
+
+ _, ifAddrs, err = IfByRFC(ForwardingBlacklistRFC, ifAddrs)
+ if err != nil {
+ return "", err
+ } else if len(ifAddrs) == 0 {
+ return "", nil
+ }
+
+ ips := make([]string, 0, len(ifAddrs))
+ for _, ifAddr := range ifAddrs {
+ ip := *ToIPAddr(ifAddr.SockAddr)
+ s := ip.NetIP().String()
+ ips = append(ips, s)
+ }
+
+ return strings.Join(ips, " "), nil
+}
+
+// GetPublicIP returns a string with a single IP address that is NOT part of RFC
+// 6890 and has a default route. If the system can't determine its IP address
+// or find a non RFC 6890 IP address, an empty string will be returned instead.
+// This function is the `eval` equivalent of:
+//
+// ```
+// $ sockaddr eval -r '{{GetPublicInterfaces | attr "address"}}'
+/// ```
+func GetPublicIP() (string, error) {
+ publicIfs, err := GetPublicInterfaces()
+ if err != nil {
+ return "", err
+ } else if len(publicIfs) < 1 {
+ return "", nil
+ }
+
+ ifAddr := publicIfs[0]
+ ip := *ToIPAddr(ifAddr.SockAddr)
+ return ip.NetIP().String(), nil
+}
+
+// GetPublicIPs returns a string with all IP addresses that are NOT part of RFC
+// 6890 (regardless of whether or not there is a default route, unlike
+// GetPublicIP). If the system can't find any non RFC 6890 IP addresses, an
+// empty string will be returned instead. This function is the `eval`
+// equivalent of:
+//
+// ```
+// $ sockaddr eval -r '{{GetAllInterfaces | exclude "RFC" "6890" | join "address" " "}}'
+/// ```
+func GetPublicIPs() (string, error) {
+ ifAddrs, err := GetAllInterfaces()
+ if err != nil {
+ return "", err
+ } else if len(ifAddrs) < 1 {
+ return "", nil
+ }
+
+ ifAddrs, _ = FilterIfByType(ifAddrs, TypeIP)
+ if len(ifAddrs) == 0 {
+ return "", nil
+ }
+
+ OrderedIfAddrBy(AscIfType, AscIfNetworkSize).Sort(ifAddrs)
+
+ _, ifAddrs, err = IfByRFC("6890", ifAddrs)
+ if err != nil {
+ return "", err
+ } else if len(ifAddrs) == 0 {
+ return "", nil
+ }
+
+ ips := make([]string, 0, len(ifAddrs))
+ for _, ifAddr := range ifAddrs {
+ ip := *ToIPAddr(ifAddr.SockAddr)
+ s := ip.NetIP().String()
+ ips = append(ips, s)
+ }
+
+ return strings.Join(ips, " "), nil
+}
+
+// GetInterfaceIP returns a string with a single IP address sorted by the size
+// of the network (i.e. IP addresses with a smaller netmask, larger network
+// size, are sorted first). This function is the `eval` equivalent of:
+//
+// ```
+// $ sockaddr eval -r '{{GetAllInterfaces | include "name" <<ARG>> | sort "type,size" | include "flag" "forwardable" | attr "address" }}'
+/// ```
+func GetInterfaceIP(namedIfRE string) (string, error) {
+ ifAddrs, err := GetAllInterfaces()
+ if err != nil {
+ return "", err
+ }
+
+ ifAddrs, _, err = IfByName(namedIfRE, ifAddrs)
+ if err != nil {
+ return "", err
+ }
+
+ ifAddrs, _, err = IfByFlag("forwardable", ifAddrs)
+ if err != nil {
+ return "", err
+ }
+
+ ifAddrs, err = SortIfBy("+type,+size", ifAddrs)
+ if err != nil {
+ return "", err
+ }
+
+ if len(ifAddrs) == 0 {
+ return "", err
+ }
+
+ ip := ToIPAddr(ifAddrs[0].SockAddr)
+ if ip == nil {
+ return "", err
+ }
+
+ return IPAddrAttr(*ip, "address"), nil
+}
+
+// GetInterfaceIPs returns a string with all IPs, sorted by the size of the
+// network (i.e. IP addresses with a smaller netmask, larger network size, are
+// sorted first), on a named interface. This function is the `eval` equivalent
+// of:
+//
+// ```
+// $ sockaddr eval -r '{{GetAllInterfaces | include "name" <<ARG>> | sort "type,size" | join "address" " "}}'
+/// ```
+func GetInterfaceIPs(namedIfRE string) (string, error) {
+ ifAddrs, err := GetAllInterfaces()
+ if err != nil {
+ return "", err
+ }
+
+ ifAddrs, _, err = IfByName(namedIfRE, ifAddrs)
+ if err != nil {
+ return "", err
+ }
+
+ ifAddrs, err = SortIfBy("+type,+size", ifAddrs)
+ if err != nil {
+ return "", err
+ }
+
+ if len(ifAddrs) == 0 {
+ return "", err
+ }
+
+ ips := make([]string, 0, len(ifAddrs))
+ for _, ifAddr := range ifAddrs {
+ ip := *ToIPAddr(ifAddr.SockAddr)
+ s := ip.NetIP().String()
+ ips = append(ips, s)
+ }
+
+ return strings.Join(ips, " "), nil
+}
+
+// IfAddrAttrs returns a list of attributes supported by the IfAddr type
+func IfAddrAttrs() []AttrName {
+ return ifAddrAttrs
+}
+
+// IfAddrAttr returns a string representation of an attribute for the given
+// IfAddr.
+func IfAddrAttr(ifAddr IfAddr, attrName AttrName) string {
+ fn, found := ifAddrAttrMap[attrName]
+ if !found {
+ return ""
+ }
+
+ return fn(ifAddr)
+}
+
+// ifAddrAttrInit is called once at init()
+func ifAddrAttrInit() {
+ // Sorted for human readability
+ ifAddrAttrs = []AttrName{
+ "flags",
+ "name",
+ }
+
+ ifAddrAttrMap = map[AttrName]func(ifAddr IfAddr) string{
+ "flags": func(ifAddr IfAddr) string {
+ return ifAddr.Interface.Flags.String()
+ },
+ "name": func(ifAddr IfAddr) string {
+ return ifAddr.Interface.Name
+ },
+ }
+}
--- /dev/null
+package sockaddr
+
+import (
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "math/big"
+ "net"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+)
+
+var (
+ // Centralize all regexps and regexp.Copy() where necessary.
+ signRE *regexp.Regexp = regexp.MustCompile(`^[\s]*[+-]`)
+ whitespaceRE *regexp.Regexp = regexp.MustCompile(`[\s]+`)
+ ifNameRE *regexp.Regexp = regexp.MustCompile(`^Ethernet adapter ([^\s:]+):`)
+ ipAddrRE *regexp.Regexp = regexp.MustCompile(`^ IPv[46] Address\. \. \. \. \. \. \. \. \. \. \. : ([^\s]+)`)
+)
+
+// IfAddrs is a slice of IfAddr
+type IfAddrs []IfAddr
+
+func (ifs IfAddrs) Len() int { return len(ifs) }
+
+// CmpIfFunc is the function signature that must be met to be used in the
+// OrderedIfAddrBy multiIfAddrSorter
+type CmpIfAddrFunc func(p1, p2 *IfAddr) int
+
+// multiIfAddrSorter implements the Sort interface, sorting the IfAddrs within.
+type multiIfAddrSorter struct {
+ ifAddrs IfAddrs
+ cmp []CmpIfAddrFunc
+}
+
+// Sort sorts the argument slice according to the Cmp functions passed to
+// OrderedIfAddrBy.
+func (ms *multiIfAddrSorter) Sort(ifAddrs IfAddrs) {
+ ms.ifAddrs = ifAddrs
+ sort.Sort(ms)
+}
+
+// OrderedIfAddrBy sorts SockAddr by the list of sort function pointers.
+func OrderedIfAddrBy(cmpFuncs ...CmpIfAddrFunc) *multiIfAddrSorter {
+ return &multiIfAddrSorter{
+ cmp: cmpFuncs,
+ }
+}
+
+// Len is part of sort.Interface.
+func (ms *multiIfAddrSorter) Len() int {
+ return len(ms.ifAddrs)
+}
+
+// Less is part of sort.Interface. It is implemented by looping along the Cmp()
+// functions until it finds a comparison that is either less than or greater
+// than. A return value of 0 defers sorting to the next function in the
+// multisorter (which means the results of sorting may leave the resutls in a
+// non-deterministic order).
+func (ms *multiIfAddrSorter) Less(i, j int) bool {
+ p, q := &ms.ifAddrs[i], &ms.ifAddrs[j]
+ // Try all but the last comparison.
+ var k int
+ for k = 0; k < len(ms.cmp)-1; k++ {
+ cmp := ms.cmp[k]
+ x := cmp(p, q)
+ switch x {
+ case -1:
+ // p < q, so we have a decision.
+ return true
+ case 1:
+ // p > q, so we have a decision.
+ return false
+ }
+ // p == q; try the next comparison.
+ }
+ // All comparisons to here said "equal", so just return whatever the
+ // final comparison reports.
+ switch ms.cmp[k](p, q) {
+ case -1:
+ return true
+ case 1:
+ return false
+ default:
+ // Still a tie! Now what?
+ return false
+ panic("undefined sort order for remaining items in the list")
+ }
+}
+
+// Swap is part of sort.Interface.
+func (ms *multiIfAddrSorter) Swap(i, j int) {
+ ms.ifAddrs[i], ms.ifAddrs[j] = ms.ifAddrs[j], ms.ifAddrs[i]
+}
+
+// AscIfAddress is a sorting function to sort IfAddrs by their respective
+// address type. Non-equal types are deferred in the sort.
+func AscIfAddress(p1Ptr, p2Ptr *IfAddr) int {
+ return AscAddress(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
+}
+
+// AscIfDefault is a sorting function to sort IfAddrs by whether or not they
+// have a default route or not. Non-equal types are deferred in the sort.
+//
+// FIXME: This is a particularly expensive sorting operation because of the
+// non-memoized calls to NewRouteInfo(). In an ideal world the routeInfo data
+// once at the start of the sort and pass it along as a context or by wrapping
+// the IfAddr type with this information (this would also solve the inability to
+// return errors and the possibility of failing silently). Fortunately,
+// N*log(N) where N = 3 is only ~6.2 invocations. Not ideal, but not worth
+// optimizing today. The common case is this gets called once or twice.
+// Patches welcome.
+func AscIfDefault(p1Ptr, p2Ptr *IfAddr) int {
+ ri, err := NewRouteInfo()
+ if err != nil {
+ return sortDeferDecision
+ }
+
+ defaultIfName, err := ri.GetDefaultInterfaceName()
+ if err != nil {
+ return sortDeferDecision
+ }
+
+ switch {
+ case p1Ptr.Interface.Name == defaultIfName && p2Ptr.Interface.Name == defaultIfName:
+ return sortDeferDecision
+ case p1Ptr.Interface.Name == defaultIfName:
+ return sortReceiverBeforeArg
+ case p2Ptr.Interface.Name == defaultIfName:
+ return sortArgBeforeReceiver
+ default:
+ return sortDeferDecision
+ }
+}
+
+// AscIfName is a sorting function to sort IfAddrs by their interface names.
+func AscIfName(p1Ptr, p2Ptr *IfAddr) int {
+ return strings.Compare(p1Ptr.Name, p2Ptr.Name)
+}
+
+// AscIfNetworkSize is a sorting function to sort IfAddrs by their respective
+// network mask size.
+func AscIfNetworkSize(p1Ptr, p2Ptr *IfAddr) int {
+ return AscNetworkSize(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
+}
+
+// AscIfPort is a sorting function to sort IfAddrs by their respective
+// port type. Non-equal types are deferred in the sort.
+func AscIfPort(p1Ptr, p2Ptr *IfAddr) int {
+ return AscPort(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
+}
+
+// AscIfPrivate is a sorting function to sort IfAddrs by "private" values before
+// "public" values. Both IPv4 and IPv6 are compared against RFC6890 (RFC6890
+// includes, and is not limited to, RFC1918 and RFC6598 for IPv4, and IPv6
+// includes RFC4193).
+func AscIfPrivate(p1Ptr, p2Ptr *IfAddr) int {
+ return AscPrivate(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
+}
+
+// AscIfType is a sorting function to sort IfAddrs by their respective address
+// type. Non-equal types are deferred in the sort.
+func AscIfType(p1Ptr, p2Ptr *IfAddr) int {
+ return AscType(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
+}
+
+// DescIfAddress is identical to AscIfAddress but reverse ordered.
+func DescIfAddress(p1Ptr, p2Ptr *IfAddr) int {
+ return -1 * AscAddress(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
+}
+
+// DescIfDefault is identical to AscIfDefault but reverse ordered.
+func DescIfDefault(p1Ptr, p2Ptr *IfAddr) int {
+ return -1 * AscIfDefault(p1Ptr, p2Ptr)
+}
+
+// DescIfName is identical to AscIfName but reverse ordered.
+func DescIfName(p1Ptr, p2Ptr *IfAddr) int {
+ return -1 * strings.Compare(p1Ptr.Name, p2Ptr.Name)
+}
+
+// DescIfNetworkSize is identical to AscIfNetworkSize but reverse ordered.
+func DescIfNetworkSize(p1Ptr, p2Ptr *IfAddr) int {
+ return -1 * AscNetworkSize(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
+}
+
+// DescIfPort is identical to AscIfPort but reverse ordered.
+func DescIfPort(p1Ptr, p2Ptr *IfAddr) int {
+ return -1 * AscPort(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
+}
+
+// DescIfPrivate is identical to AscIfPrivate but reverse ordered.
+func DescIfPrivate(p1Ptr, p2Ptr *IfAddr) int {
+ return -1 * AscPrivate(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
+}
+
+// DescIfType is identical to AscIfType but reverse ordered.
+func DescIfType(p1Ptr, p2Ptr *IfAddr) int {
+ return -1 * AscType(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
+}
+
+// FilterIfByType filters IfAddrs and returns a list of the matching type
+func FilterIfByType(ifAddrs IfAddrs, type_ SockAddrType) (matchedIfs, excludedIfs IfAddrs) {
+ excludedIfs = make(IfAddrs, 0, len(ifAddrs))
+ matchedIfs = make(IfAddrs, 0, len(ifAddrs))
+
+ for _, ifAddr := range ifAddrs {
+ if ifAddr.SockAddr.Type()&type_ != 0 {
+ matchedIfs = append(matchedIfs, ifAddr)
+ } else {
+ excludedIfs = append(excludedIfs, ifAddr)
+ }
+ }
+ return matchedIfs, excludedIfs
+}
+
+// IfAttr forwards the selector to IfAttr.Attr() for resolution. If there is
+// more than one IfAddr, only the first IfAddr is used.
+func IfAttr(selectorName string, ifAddr IfAddr) (string, error) {
+ attrName := AttrName(strings.ToLower(selectorName))
+ attrVal, err := ifAddr.Attr(attrName)
+ return attrVal, err
+}
+
+// IfAttrs forwards the selector to IfAttrs.Attr() for resolution. If there is
+// more than one IfAddr, only the first IfAddr is used.
+func IfAttrs(selectorName string, ifAddrs IfAddrs) (string, error) {
+ if len(ifAddrs) == 0 {
+ return "", nil
+ }
+
+ attrName := AttrName(strings.ToLower(selectorName))
+ attrVal, err := ifAddrs[0].Attr(attrName)
+ return attrVal, err
+}
+
+// GetAllInterfaces iterates over all available network interfaces and finds all
+// available IP addresses on each interface and converts them to
+// sockaddr.IPAddrs, and returning the result as an array of IfAddr.
+func GetAllInterfaces() (IfAddrs, error) {
+ ifs, err := net.Interfaces()
+ if err != nil {
+ return nil, err
+ }
+
+ ifAddrs := make(IfAddrs, 0, len(ifs))
+ for _, intf := range ifs {
+ addrs, err := intf.Addrs()
+ if err != nil {
+ return nil, err
+ }
+
+ for _, addr := range addrs {
+ var ipAddr IPAddr
+ ipAddr, err = NewIPAddr(addr.String())
+ if err != nil {
+ return IfAddrs{}, fmt.Errorf("unable to create an IP address from %q", addr.String())
+ }
+
+ ifAddr := IfAddr{
+ SockAddr: ipAddr,
+ Interface: intf,
+ }
+ ifAddrs = append(ifAddrs, ifAddr)
+ }
+ }
+
+ return ifAddrs, nil
+}
+
+// GetDefaultInterfaces returns IfAddrs of the addresses attached to the default
+// route.
+func GetDefaultInterfaces() (IfAddrs, error) {
+ ri, err := NewRouteInfo()
+ if err != nil {
+ return nil, err
+ }
+
+ defaultIfName, err := ri.GetDefaultInterfaceName()
+ if err != nil {
+ return nil, err
+ }
+
+ var defaultIfs, ifAddrs IfAddrs
+ ifAddrs, err = GetAllInterfaces()
+ for _, ifAddr := range ifAddrs {
+ if ifAddr.Name == defaultIfName {
+ defaultIfs = append(defaultIfs, ifAddr)
+ }
+ }
+
+ return defaultIfs, nil
+}
+
+// GetPrivateInterfaces returns an IfAddrs that are part of RFC 6890 and have a
+// default route. If the system can't determine its IP address or find an RFC
+// 6890 IP address, an empty IfAddrs will be returned instead. This function is
+// the `eval` equivalent of:
+//
+// ```
+// $ sockaddr eval -r '{{GetAllInterfaces | include "type" "ip" | include "flags" "forwardable" | include "flags" "up" | sort "default,type,size" | include "RFC" "6890" }}'
+/// ```
+func GetPrivateInterfaces() (IfAddrs, error) {
+ privateIfs, err := GetAllInterfaces()
+ if err != nil {
+ return IfAddrs{}, err
+ }
+ if len(privateIfs) == 0 {
+ return IfAddrs{}, nil
+ }
+
+ privateIfs, _ = FilterIfByType(privateIfs, TypeIP)
+ if len(privateIfs) == 0 {
+ return IfAddrs{}, nil
+ }
+
+ privateIfs, _, err = IfByFlag("forwardable", privateIfs)
+ if err != nil {
+ return IfAddrs{}, err
+ }
+
+ privateIfs, _, err = IfByFlag("up", privateIfs)
+ if err != nil {
+ return IfAddrs{}, err
+ }
+
+ if len(privateIfs) == 0 {
+ return IfAddrs{}, nil
+ }
+
+ OrderedIfAddrBy(AscIfDefault, AscIfType, AscIfNetworkSize).Sort(privateIfs)
+
+ privateIfs, _, err = IfByRFC("6890", privateIfs)
+ if err != nil {
+ return IfAddrs{}, err
+ } else if len(privateIfs) == 0 {
+ return IfAddrs{}, nil
+ }
+
+ return privateIfs, nil
+}
+
+// GetPublicInterfaces returns an IfAddrs that are NOT part of RFC 6890 and has a
+// default route. If the system can't determine its IP address or find a non
+// RFC 6890 IP address, an empty IfAddrs will be returned instead. This
+// function is the `eval` equivalent of:
+//
+// ```
+// $ sockaddr eval -r '{{GetAllInterfaces | include "type" "ip" | include "flags" "forwardable" | include "flags" "up" | sort "default,type,size" | exclude "RFC" "6890" }}'
+/// ```
+func GetPublicInterfaces() (IfAddrs, error) {
+ publicIfs, err := GetAllInterfaces()
+ if err != nil {
+ return IfAddrs{}, err
+ }
+ if len(publicIfs) == 0 {
+ return IfAddrs{}, nil
+ }
+
+ publicIfs, _ = FilterIfByType(publicIfs, TypeIP)
+ if len(publicIfs) == 0 {
+ return IfAddrs{}, nil
+ }
+
+ publicIfs, _, err = IfByFlag("forwardable", publicIfs)
+ if err != nil {
+ return IfAddrs{}, err
+ }
+
+ publicIfs, _, err = IfByFlag("up", publicIfs)
+ if err != nil {
+ return IfAddrs{}, err
+ }
+
+ if len(publicIfs) == 0 {
+ return IfAddrs{}, nil
+ }
+
+ OrderedIfAddrBy(AscIfDefault, AscIfType, AscIfNetworkSize).Sort(publicIfs)
+
+ _, publicIfs, err = IfByRFC("6890", publicIfs)
+ if err != nil {
+ return IfAddrs{}, err
+ } else if len(publicIfs) == 0 {
+ return IfAddrs{}, nil
+ }
+
+ return publicIfs, nil
+}
+
+// IfByAddress returns a list of matched and non-matched IfAddrs, or an error if
+// the regexp fails to compile.
+func IfByAddress(inputRe string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
+ re, err := regexp.Compile(inputRe)
+ if err != nil {
+ return nil, nil, fmt.Errorf("Unable to compile address regexp %+q: %v", inputRe, err)
+ }
+
+ matchedAddrs := make(IfAddrs, 0, len(ifAddrs))
+ excludedAddrs := make(IfAddrs, 0, len(ifAddrs))
+ for _, addr := range ifAddrs {
+ if re.MatchString(addr.SockAddr.String()) {
+ matchedAddrs = append(matchedAddrs, addr)
+ } else {
+ excludedAddrs = append(excludedAddrs, addr)
+ }
+ }
+
+ return matchedAddrs, excludedAddrs, nil
+}
+
+// IfByName returns a list of matched and non-matched IfAddrs, or an error if
+// the regexp fails to compile.
+func IfByName(inputRe string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
+ re, err := regexp.Compile(inputRe)
+ if err != nil {
+ return nil, nil, fmt.Errorf("Unable to compile name regexp %+q: %v", inputRe, err)
+ }
+
+ matchedAddrs := make(IfAddrs, 0, len(ifAddrs))
+ excludedAddrs := make(IfAddrs, 0, len(ifAddrs))
+ for _, addr := range ifAddrs {
+ if re.MatchString(addr.Name) {
+ matchedAddrs = append(matchedAddrs, addr)
+ } else {
+ excludedAddrs = append(excludedAddrs, addr)
+ }
+ }
+
+ return matchedAddrs, excludedAddrs, nil
+}
+
+// IfByPort returns a list of matched and non-matched IfAddrs, or an error if
+// the regexp fails to compile.
+func IfByPort(inputRe string, ifAddrs IfAddrs) (matchedIfs, excludedIfs IfAddrs, err error) {
+ re, err := regexp.Compile(inputRe)
+ if err != nil {
+ return nil, nil, fmt.Errorf("Unable to compile port regexp %+q: %v", inputRe, err)
+ }
+
+ ipIfs, nonIfs := FilterIfByType(ifAddrs, TypeIP)
+ matchedIfs = make(IfAddrs, 0, len(ipIfs))
+ excludedIfs = append(IfAddrs(nil), nonIfs...)
+ for _, addr := range ipIfs {
+ ipAddr := ToIPAddr(addr.SockAddr)
+ if ipAddr == nil {
+ continue
+ }
+
+ port := strconv.FormatInt(int64((*ipAddr).IPPort()), 10)
+ if re.MatchString(port) {
+ matchedIfs = append(matchedIfs, addr)
+ } else {
+ excludedIfs = append(excludedIfs, addr)
+ }
+ }
+
+ return matchedIfs, excludedIfs, nil
+}
+
+// IfByRFC returns a list of matched and non-matched IfAddrs that contain the
+// relevant RFC-specified traits.
+func IfByRFC(selectorParam string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
+ inputRFC, err := strconv.ParseUint(selectorParam, 10, 64)
+ if err != nil {
+ return IfAddrs{}, IfAddrs{}, fmt.Errorf("unable to parse RFC number %q: %v", selectorParam, err)
+ }
+
+ matchedIfAddrs := make(IfAddrs, 0, len(ifAddrs))
+ remainingIfAddrs := make(IfAddrs, 0, len(ifAddrs))
+
+ rfcNetMap := KnownRFCs()
+ rfcNets, ok := rfcNetMap[uint(inputRFC)]
+ if !ok {
+ return nil, nil, fmt.Errorf("unsupported RFC %d", inputRFC)
+ }
+
+ for _, ifAddr := range ifAddrs {
+ var contained bool
+ for _, rfcNet := range rfcNets {
+ if rfcNet.Contains(ifAddr.SockAddr) {
+ matchedIfAddrs = append(matchedIfAddrs, ifAddr)
+ contained = true
+ break
+ }
+ }
+ if !contained {
+ remainingIfAddrs = append(remainingIfAddrs, ifAddr)
+ }
+ }
+
+ return matchedIfAddrs, remainingIfAddrs, nil
+}
+
+// IfByRFCs returns a list of matched and non-matched IfAddrs that contain the
+// relevant RFC-specified traits. Multiple RFCs can be specified and separated
+// by the `|` symbol. No protection is taken to ensure an IfAddr does not end
+// up in both the included and excluded list.
+func IfByRFCs(selectorParam string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
+ var includedIfs, excludedIfs IfAddrs
+ for _, rfcStr := range strings.Split(selectorParam, "|") {
+ includedRFCIfs, excludedRFCIfs, err := IfByRFC(rfcStr, ifAddrs)
+ if err != nil {
+ return IfAddrs{}, IfAddrs{}, fmt.Errorf("unable to lookup RFC number %q: %v", rfcStr, err)
+ }
+ includedIfs = append(includedIfs, includedRFCIfs...)
+ excludedIfs = append(excludedIfs, excludedRFCIfs...)
+ }
+
+ return includedIfs, excludedIfs, nil
+}
+
+// IfByMaskSize returns a list of matched and non-matched IfAddrs that have the
+// matching mask size.
+func IfByMaskSize(selectorParam string, ifAddrs IfAddrs) (matchedIfs, excludedIfs IfAddrs, err error) {
+ maskSize, err := strconv.ParseUint(selectorParam, 10, 64)
+ if err != nil {
+ return IfAddrs{}, IfAddrs{}, fmt.Errorf("invalid exclude size argument (%q): %v", selectorParam, err)
+ }
+
+ ipIfs, nonIfs := FilterIfByType(ifAddrs, TypeIP)
+ matchedIfs = make(IfAddrs, 0, len(ipIfs))
+ excludedIfs = append(IfAddrs(nil), nonIfs...)
+ for _, addr := range ipIfs {
+ ipAddr := ToIPAddr(addr.SockAddr)
+ if ipAddr == nil {
+ return IfAddrs{}, IfAddrs{}, fmt.Errorf("unable to filter mask sizes on non-IP type %s: %v", addr.SockAddr.Type().String(), addr.SockAddr.String())
+ }
+
+ switch {
+ case (*ipAddr).Type()&TypeIPv4 != 0 && maskSize > 32:
+ return IfAddrs{}, IfAddrs{}, fmt.Errorf("mask size out of bounds for IPv4 address: %d", maskSize)
+ case (*ipAddr).Type()&TypeIPv6 != 0 && maskSize > 128:
+ return IfAddrs{}, IfAddrs{}, fmt.Errorf("mask size out of bounds for IPv6 address: %d", maskSize)
+ }
+
+ if (*ipAddr).Maskbits() == int(maskSize) {
+ matchedIfs = append(matchedIfs, addr)
+ } else {
+ excludedIfs = append(excludedIfs, addr)
+ }
+ }
+
+ return matchedIfs, excludedIfs, nil
+}
+
+// IfByType returns a list of matching and non-matching IfAddr that match the
+// specified type. For instance:
+//
+// include "type" "IPv4,IPv6"
+//
+// will include any IfAddrs that is either an IPv4 or IPv6 address. Any
+// addresses on those interfaces that don't match will be included in the
+// remainder results.
+func IfByType(inputTypes string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
+ matchingIfAddrs := make(IfAddrs, 0, len(ifAddrs))
+ remainingIfAddrs := make(IfAddrs, 0, len(ifAddrs))
+
+ ifTypes := strings.Split(strings.ToLower(inputTypes), "|")
+ for _, ifType := range ifTypes {
+ switch ifType {
+ case "ip", "ipv4", "ipv6", "unix":
+ // Valid types
+ default:
+ return nil, nil, fmt.Errorf("unsupported type %q %q", ifType, inputTypes)
+ }
+ }
+
+ for _, ifAddr := range ifAddrs {
+ for _, ifType := range ifTypes {
+ var matched bool
+ switch {
+ case ifType == "ip" && ifAddr.SockAddr.Type()&TypeIP != 0:
+ matched = true
+ case ifType == "ipv4" && ifAddr.SockAddr.Type()&TypeIPv4 != 0:
+ matched = true
+ case ifType == "ipv6" && ifAddr.SockAddr.Type()&TypeIPv6 != 0:
+ matched = true
+ case ifType == "unix" && ifAddr.SockAddr.Type()&TypeUnix != 0:
+ matched = true
+ }
+
+ if matched {
+ matchingIfAddrs = append(matchingIfAddrs, ifAddr)
+ } else {
+ remainingIfAddrs = append(remainingIfAddrs, ifAddr)
+ }
+ }
+ }
+
+ return matchingIfAddrs, remainingIfAddrs, nil
+}
+
+// IfByFlag returns a list of matching and non-matching IfAddrs that match the
+// specified type. For instance:
+//
+// include "flag" "up,broadcast"
+//
+// will include any IfAddrs that have both the "up" and "broadcast" flags set.
+// Any addresses on those interfaces that don't match will be omitted from the
+// results.
+func IfByFlag(inputFlags string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
+ matchedAddrs := make(IfAddrs, 0, len(ifAddrs))
+ excludedAddrs := make(IfAddrs, 0, len(ifAddrs))
+
+ var wantForwardable,
+ wantGlobalUnicast,
+ wantInterfaceLocalMulticast,
+ wantLinkLocalMulticast,
+ wantLinkLocalUnicast,
+ wantLoopback,
+ wantMulticast,
+ wantUnspecified bool
+ var ifFlags net.Flags
+ var checkFlags, checkAttrs bool
+ for _, flagName := range strings.Split(strings.ToLower(inputFlags), "|") {
+ switch flagName {
+ case "broadcast":
+ checkFlags = true
+ ifFlags = ifFlags | net.FlagBroadcast
+ case "down":
+ checkFlags = true
+ ifFlags = (ifFlags &^ net.FlagUp)
+ case "forwardable":
+ checkAttrs = true
+ wantForwardable = true
+ case "global unicast":
+ checkAttrs = true
+ wantGlobalUnicast = true
+ case "interface-local multicast":
+ checkAttrs = true
+ wantInterfaceLocalMulticast = true
+ case "link-local multicast":
+ checkAttrs = true
+ wantLinkLocalMulticast = true
+ case "link-local unicast":
+ checkAttrs = true
+ wantLinkLocalUnicast = true
+ case "loopback":
+ checkAttrs = true
+ checkFlags = true
+ ifFlags = ifFlags | net.FlagLoopback
+ wantLoopback = true
+ case "multicast":
+ checkAttrs = true
+ checkFlags = true
+ ifFlags = ifFlags | net.FlagMulticast
+ wantMulticast = true
+ case "point-to-point":
+ checkFlags = true
+ ifFlags = ifFlags | net.FlagPointToPoint
+ case "unspecified":
+ checkAttrs = true
+ wantUnspecified = true
+ case "up":
+ checkFlags = true
+ ifFlags = ifFlags | net.FlagUp
+ default:
+ return nil, nil, fmt.Errorf("Unknown interface flag: %+q", flagName)
+ }
+ }
+
+ for _, ifAddr := range ifAddrs {
+ var matched bool
+ if checkFlags && ifAddr.Interface.Flags&ifFlags == ifFlags {
+ matched = true
+ }
+ if checkAttrs {
+ if ip := ToIPAddr(ifAddr.SockAddr); ip != nil {
+ netIP := (*ip).NetIP()
+ switch {
+ case wantGlobalUnicast && netIP.IsGlobalUnicast():
+ matched = true
+ case wantInterfaceLocalMulticast && netIP.IsInterfaceLocalMulticast():
+ matched = true
+ case wantLinkLocalMulticast && netIP.IsLinkLocalMulticast():
+ matched = true
+ case wantLinkLocalUnicast && netIP.IsLinkLocalUnicast():
+ matched = true
+ case wantLoopback && netIP.IsLoopback():
+ matched = true
+ case wantMulticast && netIP.IsMulticast():
+ matched = true
+ case wantUnspecified && netIP.IsUnspecified():
+ matched = true
+ case wantForwardable && !IsRFC(ForwardingBlacklist, ifAddr.SockAddr):
+ matched = true
+ }
+ }
+ }
+ if matched {
+ matchedAddrs = append(matchedAddrs, ifAddr)
+ } else {
+ excludedAddrs = append(excludedAddrs, ifAddr)
+ }
+ }
+ return matchedAddrs, excludedAddrs, nil
+}
+
+// IfByNetwork returns an IfAddrs that are equal to or included within the
+// network passed in by selector.
+func IfByNetwork(selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, IfAddrs, error) {
+ var includedIfs, excludedIfs IfAddrs
+ for _, netStr := range strings.Split(selectorParam, "|") {
+ netAddr, err := NewIPAddr(netStr)
+ if err != nil {
+ return nil, nil, fmt.Errorf("unable to create an IP address from %+q: %v", netStr, err)
+ }
+
+ for _, ifAddr := range inputIfAddrs {
+ if netAddr.Contains(ifAddr.SockAddr) {
+ includedIfs = append(includedIfs, ifAddr)
+ } else {
+ excludedIfs = append(excludedIfs, ifAddr)
+ }
+ }
+ }
+
+ return includedIfs, excludedIfs, nil
+}
+
+// IfAddrMath will return a new IfAddr struct with a mutated value.
+func IfAddrMath(operation, value string, inputIfAddr IfAddr) (IfAddr, error) {
+ // Regexp used to enforce the sign being a required part of the grammar for
+ // some values.
+ signRe := signRE.Copy()
+
+ switch strings.ToLower(operation) {
+ case "address":
+ // "address" operates on the IP address and is allowed to overflow or
+ // underflow networks, however it will wrap along the underlying address's
+ // underlying type.
+
+ if !signRe.MatchString(value) {
+ return IfAddr{}, fmt.Errorf("sign (+/-) is required for operation %q", operation)
+ }
+
+ switch sockType := inputIfAddr.SockAddr.Type(); sockType {
+ case TypeIPv4:
+ // 33 == Accept any uint32 value
+ // TODO(seanc@): Add the ability to parse hex
+ i, err := strconv.ParseInt(value, 10, 33)
+ if err != nil {
+ return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
+ }
+
+ ipv4 := *ToIPv4Addr(inputIfAddr.SockAddr)
+ ipv4Uint32 := uint32(ipv4.Address)
+ ipv4Uint32 += uint32(i)
+ return IfAddr{
+ SockAddr: IPv4Addr{
+ Address: IPv4Address(ipv4Uint32),
+ Mask: ipv4.Mask,
+ },
+ Interface: inputIfAddr.Interface,
+ }, nil
+ case TypeIPv6:
+ // 64 == Accept any int32 value
+ // TODO(seanc@): Add the ability to parse hex. Also parse a bignum int.
+ i, err := strconv.ParseInt(value, 10, 64)
+ if err != nil {
+ return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
+ }
+
+ ipv6 := *ToIPv6Addr(inputIfAddr.SockAddr)
+ ipv6BigIntA := new(big.Int)
+ ipv6BigIntA.Set(ipv6.Address)
+ ipv6BigIntB := big.NewInt(i)
+
+ ipv6Addr := ipv6BigIntA.Add(ipv6BigIntA, ipv6BigIntB)
+ ipv6Addr.And(ipv6Addr, ipv6HostMask)
+
+ return IfAddr{
+ SockAddr: IPv6Addr{
+ Address: IPv6Address(ipv6Addr),
+ Mask: ipv6.Mask,
+ },
+ Interface: inputIfAddr.Interface,
+ }, nil
+ default:
+ return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType)
+ }
+ case "network":
+ // "network" operates on the network address. Positive values start at the
+ // network address and negative values wrap at the network address, which
+ // means a "-1" value on a network will be the broadcast address after
+ // wrapping is applied.
+
+ if !signRe.MatchString(value) {
+ return IfAddr{}, fmt.Errorf("sign (+/-) is required for operation %q", operation)
+ }
+
+ switch sockType := inputIfAddr.SockAddr.Type(); sockType {
+ case TypeIPv4:
+ // 33 == Accept any uint32 value
+ // TODO(seanc@): Add the ability to parse hex
+ i, err := strconv.ParseInt(value, 10, 33)
+ if err != nil {
+ return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
+ }
+
+ ipv4 := *ToIPv4Addr(inputIfAddr.SockAddr)
+ ipv4Uint32 := uint32(ipv4.NetworkAddress())
+
+ // Wrap along network mask boundaries. EZ-mode wrapping made possible by
+ // use of int64 vs a uint.
+ var wrappedMask int64
+ if i >= 0 {
+ wrappedMask = i
+ } else {
+ wrappedMask = 1 + i + int64(^uint32(ipv4.Mask))
+ }
+
+ ipv4Uint32 = ipv4Uint32 + (uint32(wrappedMask) &^ uint32(ipv4.Mask))
+
+ return IfAddr{
+ SockAddr: IPv4Addr{
+ Address: IPv4Address(ipv4Uint32),
+ Mask: ipv4.Mask,
+ },
+ Interface: inputIfAddr.Interface,
+ }, nil
+ case TypeIPv6:
+ // 64 == Accept any int32 value
+ // TODO(seanc@): Add the ability to parse hex. Also parse a bignum int.
+ i, err := strconv.ParseInt(value, 10, 64)
+ if err != nil {
+ return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
+ }
+
+ ipv6 := *ToIPv6Addr(inputIfAddr.SockAddr)
+ ipv6BigInt := new(big.Int)
+ ipv6BigInt.Set(ipv6.NetworkAddress())
+
+ mask := new(big.Int)
+ mask.Set(ipv6.Mask)
+ if i > 0 {
+ wrappedMask := new(big.Int)
+ wrappedMask.SetInt64(i)
+
+ wrappedMask.AndNot(wrappedMask, mask)
+ ipv6BigInt.Add(ipv6BigInt, wrappedMask)
+ } else {
+ // Mask off any bits that exceed the network size. Subtract the
+ // wrappedMask from the last usable - 1
+ wrappedMask := new(big.Int)
+ wrappedMask.SetInt64(-1 * i)
+ wrappedMask.Sub(wrappedMask, big.NewInt(1))
+
+ wrappedMask.AndNot(wrappedMask, mask)
+
+ lastUsable := new(big.Int)
+ lastUsable.Set(ipv6.LastUsable().(IPv6Addr).Address)
+
+ ipv6BigInt = lastUsable.Sub(lastUsable, wrappedMask)
+ }
+
+ return IfAddr{
+ SockAddr: IPv6Addr{
+ Address: IPv6Address(ipv6BigInt),
+ Mask: ipv6.Mask,
+ },
+ Interface: inputIfAddr.Interface,
+ }, nil
+ default:
+ return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType)
+ }
+ case "mask":
+ // "mask" operates on the IP address and returns the IP address on
+ // which the given integer mask has been applied. If the applied mask
+ // corresponds to a larger network than the mask of the IP address,
+ // the latter will be replaced by the former.
+ switch sockType := inputIfAddr.SockAddr.Type(); sockType {
+ case TypeIPv4:
+ i, err := strconv.ParseUint(value, 10, 32)
+ if err != nil {
+ return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
+ }
+
+ if i > 32 {
+ return IfAddr{}, fmt.Errorf("parameter for operation %q on ipv4 addresses must be between 0 and 32", operation)
+ }
+
+ ipv4 := *ToIPv4Addr(inputIfAddr.SockAddr)
+
+ ipv4Mask := net.CIDRMask(int(i), 32)
+ ipv4MaskUint32 := binary.BigEndian.Uint32(ipv4Mask)
+
+ maskedIpv4 := ipv4.NetIP().Mask(ipv4Mask)
+ maskedIpv4Uint32 := binary.BigEndian.Uint32(maskedIpv4)
+
+ maskedIpv4MaskUint32 := uint32(ipv4.Mask)
+
+ if ipv4MaskUint32 < maskedIpv4MaskUint32 {
+ maskedIpv4MaskUint32 = ipv4MaskUint32
+ }
+
+ return IfAddr{
+ SockAddr: IPv4Addr{
+ Address: IPv4Address(maskedIpv4Uint32),
+ Mask: IPv4Mask(maskedIpv4MaskUint32),
+ },
+ Interface: inputIfAddr.Interface,
+ }, nil
+ case TypeIPv6:
+ i, err := strconv.ParseUint(value, 10, 32)
+ if err != nil {
+ return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
+ }
+
+ if i > 128 {
+ return IfAddr{}, fmt.Errorf("parameter for operation %q on ipv6 addresses must be between 0 and 64", operation)
+ }
+
+ ipv6 := *ToIPv6Addr(inputIfAddr.SockAddr)
+
+ ipv6Mask := net.CIDRMask(int(i), 128)
+ ipv6MaskBigInt := new(big.Int)
+ ipv6MaskBigInt.SetBytes(ipv6Mask)
+
+ maskedIpv6 := ipv6.NetIP().Mask(ipv6Mask)
+ maskedIpv6BigInt := new(big.Int)
+ maskedIpv6BigInt.SetBytes(maskedIpv6)
+
+ maskedIpv6MaskBigInt := new(big.Int)
+ maskedIpv6MaskBigInt.Set(ipv6.Mask)
+
+ if ipv6MaskBigInt.Cmp(maskedIpv6MaskBigInt) == -1 {
+ maskedIpv6MaskBigInt = ipv6MaskBigInt
+ }
+
+ return IfAddr{
+ SockAddr: IPv6Addr{
+ Address: IPv6Address(maskedIpv6BigInt),
+ Mask: IPv6Mask(maskedIpv6MaskBigInt),
+ },
+ Interface: inputIfAddr.Interface,
+ }, nil
+ default:
+ return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType)
+ }
+ default:
+ return IfAddr{}, fmt.Errorf("unsupported math operation: %q", operation)
+ }
+}
+
+// IfAddrsMath will apply an IfAddrMath operation each IfAddr struct. Any
+// failure will result in zero results.
+func IfAddrsMath(operation, value string, inputIfAddrs IfAddrs) (IfAddrs, error) {
+ outputAddrs := make(IfAddrs, 0, len(inputIfAddrs))
+ for _, ifAddr := range inputIfAddrs {
+ result, err := IfAddrMath(operation, value, ifAddr)
+ if err != nil {
+ return IfAddrs{}, fmt.Errorf("unable to perform an IPMath operation on %s: %v", ifAddr, err)
+ }
+ outputAddrs = append(outputAddrs, result)
+ }
+ return outputAddrs, nil
+}
+
+// IncludeIfs returns an IfAddrs based on the passed in selector.
+func IncludeIfs(selectorName, selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) {
+ var includedIfs IfAddrs
+ var err error
+
+ switch strings.ToLower(selectorName) {
+ case "address":
+ includedIfs, _, err = IfByAddress(selectorParam, inputIfAddrs)
+ case "flag", "flags":
+ includedIfs, _, err = IfByFlag(selectorParam, inputIfAddrs)
+ case "name":
+ includedIfs, _, err = IfByName(selectorParam, inputIfAddrs)
+ case "network":
+ includedIfs, _, err = IfByNetwork(selectorParam, inputIfAddrs)
+ case "port":
+ includedIfs, _, err = IfByPort(selectorParam, inputIfAddrs)
+ case "rfc", "rfcs":
+ includedIfs, _, err = IfByRFCs(selectorParam, inputIfAddrs)
+ case "size":
+ includedIfs, _, err = IfByMaskSize(selectorParam, inputIfAddrs)
+ case "type":
+ includedIfs, _, err = IfByType(selectorParam, inputIfAddrs)
+ default:
+ return IfAddrs{}, fmt.Errorf("invalid include selector %q", selectorName)
+ }
+
+ if err != nil {
+ return IfAddrs{}, err
+ }
+
+ return includedIfs, nil
+}
+
+// ExcludeIfs returns an IfAddrs based on the passed in selector.
+func ExcludeIfs(selectorName, selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) {
+ var excludedIfs IfAddrs
+ var err error
+
+ switch strings.ToLower(selectorName) {
+ case "address":
+ _, excludedIfs, err = IfByAddress(selectorParam, inputIfAddrs)
+ case "flag", "flags":
+ _, excludedIfs, err = IfByFlag(selectorParam, inputIfAddrs)
+ case "name":
+ _, excludedIfs, err = IfByName(selectorParam, inputIfAddrs)
+ case "network":
+ _, excludedIfs, err = IfByNetwork(selectorParam, inputIfAddrs)
+ case "port":
+ _, excludedIfs, err = IfByPort(selectorParam, inputIfAddrs)
+ case "rfc", "rfcs":
+ _, excludedIfs, err = IfByRFCs(selectorParam, inputIfAddrs)
+ case "size":
+ _, excludedIfs, err = IfByMaskSize(selectorParam, inputIfAddrs)
+ case "type":
+ _, excludedIfs, err = IfByType(selectorParam, inputIfAddrs)
+ default:
+ return IfAddrs{}, fmt.Errorf("invalid exclude selector %q", selectorName)
+ }
+
+ if err != nil {
+ return IfAddrs{}, err
+ }
+
+ return excludedIfs, nil
+}
+
+// SortIfBy returns an IfAddrs sorted based on the passed in selector. Multiple
+// sort clauses can be passed in as a comma delimited list without whitespace.
+func SortIfBy(selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) {
+ sortedIfs := append(IfAddrs(nil), inputIfAddrs...)
+
+ clauses := strings.Split(selectorParam, ",")
+ sortFuncs := make([]CmpIfAddrFunc, len(clauses))
+
+ for i, clause := range clauses {
+ switch strings.TrimSpace(strings.ToLower(clause)) {
+ case "+address", "address":
+ // The "address" selector returns an array of IfAddrs
+ // ordered by the network address. IfAddrs that are not
+ // comparable will be at the end of the list and in a
+ // non-deterministic order.
+ sortFuncs[i] = AscIfAddress
+ case "-address":
+ sortFuncs[i] = DescIfAddress
+ case "+default", "default":
+ sortFuncs[i] = AscIfDefault
+ case "-default":
+ sortFuncs[i] = DescIfDefault
+ case "+name", "name":
+ // The "name" selector returns an array of IfAddrs
+ // ordered by the interface name.
+ sortFuncs[i] = AscIfName
+ case "-name":
+ sortFuncs[i] = DescIfName
+ case "+port", "port":
+ // The "port" selector returns an array of IfAddrs
+ // ordered by the port, if included in the IfAddr.
+ // IfAddrs that are not comparable will be at the end of
+ // the list and in a non-deterministic order.
+ sortFuncs[i] = AscIfPort
+ case "-port":
+ sortFuncs[i] = DescIfPort
+ case "+private", "private":
+ // The "private" selector returns an array of IfAddrs
+ // ordered by private addresses first. IfAddrs that are
+ // not comparable will be at the end of the list and in
+ // a non-deterministic order.
+ sortFuncs[i] = AscIfPrivate
+ case "-private":
+ sortFuncs[i] = DescIfPrivate
+ case "+size", "size":
+ // The "size" selector returns an array of IfAddrs
+ // ordered by the size of the network mask, smaller mask
+ // (larger number of hosts per network) to largest
+ // (e.g. a /24 sorts before a /32).
+ sortFuncs[i] = AscIfNetworkSize
+ case "-size":
+ sortFuncs[i] = DescIfNetworkSize
+ case "+type", "type":
+ // The "type" selector returns an array of IfAddrs
+ // ordered by the type of the IfAddr. The sort order is
+ // Unix, IPv4, then IPv6.
+ sortFuncs[i] = AscIfType
+ case "-type":
+ sortFuncs[i] = DescIfType
+ default:
+ // Return an empty list for invalid sort types.
+ return IfAddrs{}, fmt.Errorf("unknown sort type: %q", clause)
+ }
+ }
+
+ OrderedIfAddrBy(sortFuncs...).Sort(sortedIfs)
+
+ return sortedIfs, nil
+}
+
+// UniqueIfAddrsBy creates a unique set of IfAddrs based on the matching
+// selector. UniqueIfAddrsBy assumes the input has already been sorted.
+func UniqueIfAddrsBy(selectorName string, inputIfAddrs IfAddrs) (IfAddrs, error) {
+ attrName := strings.ToLower(selectorName)
+
+ ifs := make(IfAddrs, 0, len(inputIfAddrs))
+ var lastMatch string
+ for _, ifAddr := range inputIfAddrs {
+ var out string
+ switch attrName {
+ case "address":
+ out = ifAddr.SockAddr.String()
+ case "name":
+ out = ifAddr.Name
+ default:
+ return nil, fmt.Errorf("unsupported unique constraint %+q", selectorName)
+ }
+
+ switch {
+ case lastMatch == "", lastMatch != out:
+ lastMatch = out
+ ifs = append(ifs, ifAddr)
+ case lastMatch == out:
+ continue
+ }
+ }
+
+ return ifs, nil
+}
+
+// JoinIfAddrs joins an IfAddrs and returns a string
+func JoinIfAddrs(selectorName string, joinStr string, inputIfAddrs IfAddrs) (string, error) {
+ outputs := make([]string, 0, len(inputIfAddrs))
+ attrName := AttrName(strings.ToLower(selectorName))
+
+ for _, ifAddr := range inputIfAddrs {
+ var attrVal string
+ var err error
+ attrVal, err = ifAddr.Attr(attrName)
+ if err != nil {
+ return "", err
+ }
+ outputs = append(outputs, attrVal)
+ }
+ return strings.Join(outputs, joinStr), nil
+}
+
+// LimitIfAddrs returns a slice of IfAddrs based on the specified limit.
+func LimitIfAddrs(lim uint, in IfAddrs) (IfAddrs, error) {
+ // Clamp the limit to the length of the array
+ if int(lim) > len(in) {
+ lim = uint(len(in))
+ }
+
+ return in[0:lim], nil
+}
+
+// OffsetIfAddrs returns a slice of IfAddrs based on the specified offset.
+func OffsetIfAddrs(off int, in IfAddrs) (IfAddrs, error) {
+ var end bool
+ if off < 0 {
+ end = true
+ off = off * -1
+ }
+
+ if off > len(in) {
+ return IfAddrs{}, fmt.Errorf("unable to seek past the end of the interface array: offset (%d) exceeds the number of interfaces (%d)", off, len(in))
+ }
+
+ if end {
+ return in[len(in)-off:], nil
+ }
+ return in[off:], nil
+}
+
+func (ifAddr IfAddr) String() string {
+ return fmt.Sprintf("%s %v", ifAddr.SockAddr, ifAddr.Interface)
+}
+
+// parseDefaultIfNameFromRoute parses standard route(8)'s output for the *BSDs
+// and Solaris.
+func parseDefaultIfNameFromRoute(routeOut string) (string, error) {
+ lines := strings.Split(routeOut, "\n")
+ for _, line := range lines {
+ kvs := strings.SplitN(line, ":", 2)
+ if len(kvs) != 2 {
+ continue
+ }
+
+ if strings.TrimSpace(kvs[0]) == "interface" {
+ ifName := strings.TrimSpace(kvs[1])
+ return ifName, nil
+ }
+ }
+
+ return "", errors.New("No default interface found")
+}
+
+// parseDefaultIfNameFromIPCmd parses the default interface from ip(8) for
+// Linux.
+func parseDefaultIfNameFromIPCmd(routeOut string) (string, error) {
+ lines := strings.Split(routeOut, "\n")
+ re := whitespaceRE.Copy()
+ for _, line := range lines {
+ kvs := re.Split(line, -1)
+ if len(kvs) < 5 {
+ continue
+ }
+
+ if kvs[0] == "default" &&
+ kvs[1] == "via" &&
+ kvs[3] == "dev" {
+ ifName := strings.TrimSpace(kvs[4])
+ return ifName, nil
+ }
+ }
+
+ return "", errors.New("No default interface found")
+}
+
+// parseDefaultIfNameWindows parses the default interface from `netstat -rn` and
+// `ipconfig` on Windows.
+func parseDefaultIfNameWindows(routeOut, ipconfigOut string) (string, error) {
+ defaultIPAddr, err := parseDefaultIPAddrWindowsRoute(routeOut)
+ if err != nil {
+ return "", err
+ }
+
+ ifName, err := parseDefaultIfNameWindowsIPConfig(defaultIPAddr, ipconfigOut)
+ if err != nil {
+ return "", err
+ }
+
+ return ifName, nil
+}
+
+// parseDefaultIPAddrWindowsRoute parses the IP address on the default interface
+// `netstat -rn`.
+//
+// NOTES(sean): Only IPv4 addresses are parsed at this time. If you have an
+// IPv6 connected host, submit an issue on github.com/hashicorp/go-sockaddr with
+// the output from `netstat -rn`, `ipconfig`, and version of Windows to see IPv6
+// support added.
+func parseDefaultIPAddrWindowsRoute(routeOut string) (string, error) {
+ lines := strings.Split(routeOut, "\n")
+ re := whitespaceRE.Copy()
+ for _, line := range lines {
+ kvs := re.Split(strings.TrimSpace(line), -1)
+ if len(kvs) < 3 {
+ continue
+ }
+
+ if kvs[0] == "0.0.0.0" && kvs[1] == "0.0.0.0" {
+ defaultIPAddr := strings.TrimSpace(kvs[3])
+ return defaultIPAddr, nil
+ }
+ }
+
+ return "", errors.New("No IP on default interface found")
+}
+
+// parseDefaultIfNameWindowsIPConfig parses the output of `ipconfig` to find the
+// interface name forwarding traffic to the default gateway.
+func parseDefaultIfNameWindowsIPConfig(defaultIPAddr, routeOut string) (string, error) {
+ lines := strings.Split(routeOut, "\n")
+ ifNameRe := ifNameRE.Copy()
+ ipAddrRe := ipAddrRE.Copy()
+ var ifName string
+ for _, line := range lines {
+ switch ifNameMatches := ifNameRe.FindStringSubmatch(line); {
+ case len(ifNameMatches) > 1:
+ ifName = ifNameMatches[1]
+ continue
+ }
+
+ switch ipAddrMatches := ipAddrRe.FindStringSubmatch(line); {
+ case len(ipAddrMatches) > 1 && ipAddrMatches[1] == defaultIPAddr:
+ return ifName, nil
+ }
+ }
+
+ return "", errors.New("No default interface found with matching IP")
+}
--- /dev/null
+package sockaddr
+
+import (
+ "fmt"
+ "net"
+)
+
+// IfAddr is a union of a SockAddr and a net.Interface.
+type IfAddr struct {
+ SockAddr
+ net.Interface
+}
+
+// Attr returns the named attribute as a string
+func (ifAddr IfAddr) Attr(attrName AttrName) (string, error) {
+ val := IfAddrAttr(ifAddr, attrName)
+ if val != "" {
+ return val, nil
+ }
+
+ return Attr(ifAddr.SockAddr, attrName)
+}
+
+// Attr returns the named attribute as a string
+func Attr(sa SockAddr, attrName AttrName) (string, error) {
+ switch sockType := sa.Type(); {
+ case sockType&TypeIP != 0:
+ ip := *ToIPAddr(sa)
+ attrVal := IPAddrAttr(ip, attrName)
+ if attrVal != "" {
+ return attrVal, nil
+ }
+
+ if sockType == TypeIPv4 {
+ ipv4 := *ToIPv4Addr(sa)
+ attrVal := IPv4AddrAttr(ipv4, attrName)
+ if attrVal != "" {
+ return attrVal, nil
+ }
+ } else if sockType == TypeIPv6 {
+ ipv6 := *ToIPv6Addr(sa)
+ attrVal := IPv6AddrAttr(ipv6, attrName)
+ if attrVal != "" {
+ return attrVal, nil
+ }
+ }
+
+ case sockType == TypeUnix:
+ us := *ToUnixSock(sa)
+ attrVal := UnixSockAttr(us, attrName)
+ if attrVal != "" {
+ return attrVal, nil
+ }
+ }
+
+ // Non type-specific attributes
+ switch attrName {
+ case "string":
+ return sa.String(), nil
+ case "type":
+ return sa.Type().String(), nil
+ }
+
+ return "", fmt.Errorf("unsupported attribute name %q", attrName)
+}
--- /dev/null
+package sockaddr
+
+import (
+ "fmt"
+ "math/big"
+ "net"
+ "strings"
+)
+
+// Constants for the sizes of IPv3, IPv4, and IPv6 address types.
+const (
+ IPv3len = 6
+ IPv4len = 4
+ IPv6len = 16
+)
+
+// IPAddr is a generic IP address interface for IPv4 and IPv6 addresses,
+// networks, and socket endpoints.
+type IPAddr interface {
+ SockAddr
+ AddressBinString() string
+ AddressHexString() string
+ Cmp(SockAddr) int
+ CmpAddress(SockAddr) int
+ CmpPort(SockAddr) int
+ FirstUsable() IPAddr
+ Host() IPAddr
+ IPPort() IPPort
+ LastUsable() IPAddr
+ Maskbits() int
+ NetIP() *net.IP
+ NetIPMask() *net.IPMask
+ NetIPNet() *net.IPNet
+ Network() IPAddr
+ Octets() []int
+}
+
+// IPPort is the type for an IP port number for the TCP and UDP IP transports.
+type IPPort uint16
+
+// IPPrefixLen is a typed integer representing the prefix length for a given
+// IPAddr.
+type IPPrefixLen byte
+
+// ipAddrAttrMap is a map of the IPAddr type-specific attributes.
+var ipAddrAttrMap map[AttrName]func(IPAddr) string
+var ipAddrAttrs []AttrName
+
+func init() {
+ ipAddrInit()
+}
+
+// NewIPAddr creates a new IPAddr from a string. Returns nil if the string is
+// not an IPv4 or an IPv6 address.
+func NewIPAddr(addr string) (IPAddr, error) {
+ ipv4Addr, err := NewIPv4Addr(addr)
+ if err == nil {
+ return ipv4Addr, nil
+ }
+
+ ipv6Addr, err := NewIPv6Addr(addr)
+ if err == nil {
+ return ipv6Addr, nil
+ }
+
+ return nil, fmt.Errorf("invalid IPAddr %v", addr)
+}
+
+// IPAddrAttr returns a string representation of an attribute for the given
+// IPAddr.
+func IPAddrAttr(ip IPAddr, selector AttrName) string {
+ fn, found := ipAddrAttrMap[selector]
+ if !found {
+ return ""
+ }
+
+ return fn(ip)
+}
+
+// IPAttrs returns a list of attributes supported by the IPAddr type
+func IPAttrs() []AttrName {
+ return ipAddrAttrs
+}
+
+// MustIPAddr is a helper method that must return an IPAddr or panic on invalid
+// input.
+func MustIPAddr(addr string) IPAddr {
+ ip, err := NewIPAddr(addr)
+ if err != nil {
+ panic(fmt.Sprintf("Unable to create an IPAddr from %+q: %v", addr, err))
+ }
+ return ip
+}
+
+// ipAddrInit is called once at init()
+func ipAddrInit() {
+ // Sorted for human readability
+ ipAddrAttrs = []AttrName{
+ "host",
+ "address",
+ "port",
+ "netmask",
+ "network",
+ "mask_bits",
+ "binary",
+ "hex",
+ "first_usable",
+ "last_usable",
+ "octets",
+ }
+
+ ipAddrAttrMap = map[AttrName]func(ip IPAddr) string{
+ "address": func(ip IPAddr) string {
+ return ip.NetIP().String()
+ },
+ "binary": func(ip IPAddr) string {
+ return ip.AddressBinString()
+ },
+ "first_usable": func(ip IPAddr) string {
+ return ip.FirstUsable().String()
+ },
+ "hex": func(ip IPAddr) string {
+ return ip.AddressHexString()
+ },
+ "host": func(ip IPAddr) string {
+ return ip.Host().String()
+ },
+ "last_usable": func(ip IPAddr) string {
+ return ip.LastUsable().String()
+ },
+ "mask_bits": func(ip IPAddr) string {
+ return fmt.Sprintf("%d", ip.Maskbits())
+ },
+ "netmask": func(ip IPAddr) string {
+ switch v := ip.(type) {
+ case IPv4Addr:
+ ipv4Mask := IPv4Addr{
+ Address: IPv4Address(v.Mask),
+ Mask: IPv4HostMask,
+ }
+ return ipv4Mask.String()
+ case IPv6Addr:
+ ipv6Mask := new(big.Int)
+ ipv6Mask.Set(v.Mask)
+ ipv6MaskAddr := IPv6Addr{
+ Address: IPv6Address(ipv6Mask),
+ Mask: ipv6HostMask,
+ }
+ return ipv6MaskAddr.String()
+ default:
+ return fmt.Sprintf("<unsupported type: %T>", ip)
+ }
+ },
+ "network": func(ip IPAddr) string {
+ return ip.Network().NetIP().String()
+ },
+ "octets": func(ip IPAddr) string {
+ octets := ip.Octets()
+ octetStrs := make([]string, 0, len(octets))
+ for _, octet := range octets {
+ octetStrs = append(octetStrs, fmt.Sprintf("%d", octet))
+ }
+ return strings.Join(octetStrs, " ")
+ },
+ "port": func(ip IPAddr) string {
+ return fmt.Sprintf("%d", ip.IPPort())
+ },
+ }
+}
--- /dev/null
+package sockaddr
+
+import "bytes"
+
+type IPAddrs []IPAddr
+
+func (s IPAddrs) Len() int { return len(s) }
+func (s IPAddrs) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// // SortIPAddrsByCmp is a type that satisfies sort.Interface and can be used
+// // by the routines in this package. The SortIPAddrsByCmp type is used to
+// // sort IPAddrs by Cmp()
+// type SortIPAddrsByCmp struct{ IPAddrs }
+
+// // Less reports whether the element with index i should sort before the
+// // element with index j.
+// func (s SortIPAddrsByCmp) Less(i, j int) bool {
+// // Sort by Type, then address, then port number.
+// return Less(s.IPAddrs[i], s.IPAddrs[j])
+// }
+
+// SortIPAddrsBySpecificMaskLen is a type that satisfies sort.Interface and
+// can be used by the routines in this package. The
+// SortIPAddrsBySpecificMaskLen type is used to sort IPAddrs by smallest
+// network (most specific to largest network).
+type SortIPAddrsByNetworkSize struct{ IPAddrs }
+
+// Less reports whether the element with index i should sort before the
+// element with index j.
+func (s SortIPAddrsByNetworkSize) Less(i, j int) bool {
+ // Sort masks with a larger binary value (i.e. fewer hosts per network
+ // prefix) after masks with a smaller value (larger number of hosts per
+ // prefix).
+ switch bytes.Compare([]byte(*s.IPAddrs[i].NetIPMask()), []byte(*s.IPAddrs[j].NetIPMask())) {
+ case 0:
+ // Fall through to the second test if the net.IPMasks are the
+ // same.
+ break
+ case 1:
+ return true
+ case -1:
+ return false
+ default:
+ panic("bad, m'kay?")
+ }
+
+ // Sort IPs based on the length (i.e. prefer IPv4 over IPv6).
+ iLen := len(*s.IPAddrs[i].NetIP())
+ jLen := len(*s.IPAddrs[j].NetIP())
+ if iLen != jLen {
+ return iLen > jLen
+ }
+
+ // Sort IPs based on their network address from lowest to highest.
+ switch bytes.Compare(s.IPAddrs[i].NetIPNet().IP, s.IPAddrs[j].NetIPNet().IP) {
+ case 0:
+ break
+ case 1:
+ return false
+ case -1:
+ return true
+ default:
+ panic("lol wut?")
+ }
+
+ // If a host does not have a port set, it always sorts after hosts
+ // that have a port (e.g. a host with a /32 and port number is more
+ // specific and should sort first over a host with a /32 but no port
+ // set).
+ if s.IPAddrs[i].IPPort() == 0 || s.IPAddrs[j].IPPort() == 0 {
+ return false
+ }
+ return s.IPAddrs[i].IPPort() < s.IPAddrs[j].IPPort()
+}
+
+// SortIPAddrsBySpecificMaskLen is a type that satisfies sort.Interface and
+// can be used by the routines in this package. The
+// SortIPAddrsBySpecificMaskLen type is used to sort IPAddrs by smallest
+// network (most specific to largest network).
+type SortIPAddrsBySpecificMaskLen struct{ IPAddrs }
+
+// Less reports whether the element with index i should sort before the
+// element with index j.
+func (s SortIPAddrsBySpecificMaskLen) Less(i, j int) bool {
+ return s.IPAddrs[i].Maskbits() > s.IPAddrs[j].Maskbits()
+}
+
+// SortIPAddrsByBroadMaskLen is a type that satisfies sort.Interface and can
+// be used by the routines in this package. The SortIPAddrsByBroadMaskLen
+// type is used to sort IPAddrs by largest network (i.e. largest subnets
+// first).
+type SortIPAddrsByBroadMaskLen struct{ IPAddrs }
+
+// Less reports whether the element with index i should sort before the
+// element with index j.
+func (s SortIPAddrsByBroadMaskLen) Less(i, j int) bool {
+ return s.IPAddrs[i].Maskbits() < s.IPAddrs[j].Maskbits()
+}
--- /dev/null
+package sockaddr
+
+import (
+ "encoding/binary"
+ "fmt"
+ "net"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+type (
+ // IPv4Address is a named type representing an IPv4 address.
+ IPv4Address uint32
+
+ // IPv4Network is a named type representing an IPv4 network.
+ IPv4Network uint32
+
+ // IPv4Mask is a named type representing an IPv4 network mask.
+ IPv4Mask uint32
+)
+
+// IPv4HostMask is a constant represents a /32 IPv4 Address
+// (i.e. 255.255.255.255).
+const IPv4HostMask = IPv4Mask(0xffffffff)
+
+// ipv4AddrAttrMap is a map of the IPv4Addr type-specific attributes.
+var ipv4AddrAttrMap map[AttrName]func(IPv4Addr) string
+var ipv4AddrAttrs []AttrName
+var trailingHexNetmaskRE *regexp.Regexp
+
+// IPv4Addr implements a convenience wrapper around the union of Go's
+// built-in net.IP and net.IPNet types. In UNIX-speak, IPv4Addr implements
+// `sockaddr` when the the address family is set to AF_INET
+// (i.e. `sockaddr_in`).
+type IPv4Addr struct {
+ IPAddr
+ Address IPv4Address
+ Mask IPv4Mask
+ Port IPPort
+}
+
+func init() {
+ ipv4AddrInit()
+ trailingHexNetmaskRE = regexp.MustCompile(`/([0f]{8})$`)
+}
+
+// NewIPv4Addr creates an IPv4Addr from a string. String can be in the form
+// of either an IPv4:port (e.g. `1.2.3.4:80`, in which case the mask is
+// assumed to be a `/32`), an IPv4 address (e.g. `1.2.3.4`, also with a `/32`
+// mask), or an IPv4 CIDR (e.g. `1.2.3.4/24`, which has its IP port
+// initialized to zero). ipv4Str can not be a hostname.
+//
+// NOTE: Many net.*() routines will initialize and return an IPv6 address.
+// To create uint32 values from net.IP, always test to make sure the address
+// returned can be converted to a 4 byte array using To4().
+func NewIPv4Addr(ipv4Str string) (IPv4Addr, error) {
+ // Strip off any bogus hex-encoded netmasks that will be mis-parsed by Go. In
+ // particular, clients with the Barracuda VPN client will see something like:
+ // `192.168.3.51/00ffffff` as their IP address.
+ trailingHexNetmaskRe := trailingHexNetmaskRE.Copy()
+ if match := trailingHexNetmaskRe.FindStringIndex(ipv4Str); match != nil {
+ ipv4Str = ipv4Str[:match[0]]
+ }
+
+ // Parse as an IPv4 CIDR
+ ipAddr, network, err := net.ParseCIDR(ipv4Str)
+ if err == nil {
+ ipv4 := ipAddr.To4()
+ if ipv4 == nil {
+ return IPv4Addr{}, fmt.Errorf("Unable to convert %s to an IPv4 address", ipv4Str)
+ }
+
+ // If we see an IPv6 netmask, convert it to an IPv4 mask.
+ netmaskSepPos := strings.LastIndexByte(ipv4Str, '/')
+ if netmaskSepPos != -1 && netmaskSepPos+1 < len(ipv4Str) {
+ netMask, err := strconv.ParseUint(ipv4Str[netmaskSepPos+1:], 10, 8)
+ if err != nil {
+ return IPv4Addr{}, fmt.Errorf("Unable to convert %s to an IPv4 address: unable to parse CIDR netmask: %v", ipv4Str, err)
+ } else if netMask > 128 {
+ return IPv4Addr{}, fmt.Errorf("Unable to convert %s to an IPv4 address: invalid CIDR netmask", ipv4Str)
+ }
+
+ if netMask >= 96 {
+ // Convert the IPv6 netmask to an IPv4 netmask
+ network.Mask = net.CIDRMask(int(netMask-96), IPv4len*8)
+ }
+ }
+ ipv4Addr := IPv4Addr{
+ Address: IPv4Address(binary.BigEndian.Uint32(ipv4)),
+ Mask: IPv4Mask(binary.BigEndian.Uint32(network.Mask)),
+ }
+ return ipv4Addr, nil
+ }
+
+ // Attempt to parse ipv4Str as a /32 host with a port number.
+ tcpAddr, err := net.ResolveTCPAddr("tcp4", ipv4Str)
+ if err == nil {
+ ipv4 := tcpAddr.IP.To4()
+ if ipv4 == nil {
+ return IPv4Addr{}, fmt.Errorf("Unable to resolve %+q as an IPv4 address", ipv4Str)
+ }
+
+ ipv4Uint32 := binary.BigEndian.Uint32(ipv4)
+ ipv4Addr := IPv4Addr{
+ Address: IPv4Address(ipv4Uint32),
+ Mask: IPv4HostMask,
+ Port: IPPort(tcpAddr.Port),
+ }
+
+ return ipv4Addr, nil
+ }
+
+ // Parse as a naked IPv4 address
+ ip := net.ParseIP(ipv4Str)
+ if ip != nil {
+ ipv4 := ip.To4()
+ if ipv4 == nil {
+ return IPv4Addr{}, fmt.Errorf("Unable to string convert %+q to an IPv4 address", ipv4Str)
+ }
+
+ ipv4Uint32 := binary.BigEndian.Uint32(ipv4)
+ ipv4Addr := IPv4Addr{
+ Address: IPv4Address(ipv4Uint32),
+ Mask: IPv4HostMask,
+ }
+ return ipv4Addr, nil
+ }
+
+ return IPv4Addr{}, fmt.Errorf("Unable to parse %+q to an IPv4 address: %v", ipv4Str, err)
+}
+
+// AddressBinString returns a string with the IPv4Addr's Address represented
+// as a sequence of '0' and '1' characters. This method is useful for
+// debugging or by operators who want to inspect an address.
+func (ipv4 IPv4Addr) AddressBinString() string {
+ return fmt.Sprintf("%032s", strconv.FormatUint(uint64(ipv4.Address), 2))
+}
+
+// AddressHexString returns a string with the IPv4Addr address represented as
+// a sequence of hex characters. This method is useful for debugging or by
+// operators who want to inspect an address.
+func (ipv4 IPv4Addr) AddressHexString() string {
+ return fmt.Sprintf("%08s", strconv.FormatUint(uint64(ipv4.Address), 16))
+}
+
+// Broadcast is an IPv4Addr-only method that returns the broadcast address of
+// the network.
+//
+// NOTE: IPv6 only supports multicast, so this method only exists for
+// IPv4Addr.
+func (ipv4 IPv4Addr) Broadcast() IPAddr {
+ // Nothing should listen on a broadcast address.
+ return IPv4Addr{
+ Address: IPv4Address(ipv4.BroadcastAddress()),
+ Mask: IPv4HostMask,
+ }
+}
+
+// BroadcastAddress returns a IPv4Network of the IPv4Addr's broadcast
+// address.
+func (ipv4 IPv4Addr) BroadcastAddress() IPv4Network {
+ return IPv4Network(uint32(ipv4.Address)&uint32(ipv4.Mask) | ^uint32(ipv4.Mask))
+}
+
+// CmpAddress follows the Cmp() standard protocol and returns:
+//
+// - -1 If the receiver should sort first because its address is lower than arg
+// - 0 if the SockAddr arg is equal to the receiving IPv4Addr or the argument is
+// of a different type.
+// - 1 If the argument should sort first.
+func (ipv4 IPv4Addr) CmpAddress(sa SockAddr) int {
+ ipv4b, ok := sa.(IPv4Addr)
+ if !ok {
+ return sortDeferDecision
+ }
+
+ switch {
+ case ipv4.Address == ipv4b.Address:
+ return sortDeferDecision
+ case ipv4.Address < ipv4b.Address:
+ return sortReceiverBeforeArg
+ default:
+ return sortArgBeforeReceiver
+ }
+}
+
+// CmpPort follows the Cmp() standard protocol and returns:
+//
+// - -1 If the receiver should sort first because its port is lower than arg
+// - 0 if the SockAddr arg's port number is equal to the receiving IPv4Addr,
+// regardless of type.
+// - 1 If the argument should sort first.
+func (ipv4 IPv4Addr) CmpPort(sa SockAddr) int {
+ var saPort IPPort
+ switch v := sa.(type) {
+ case IPv4Addr:
+ saPort = v.Port
+ case IPv6Addr:
+ saPort = v.Port
+ default:
+ return sortDeferDecision
+ }
+
+ switch {
+ case ipv4.Port == saPort:
+ return sortDeferDecision
+ case ipv4.Port < saPort:
+ return sortReceiverBeforeArg
+ default:
+ return sortArgBeforeReceiver
+ }
+}
+
+// CmpRFC follows the Cmp() standard protocol and returns:
+//
+// - -1 If the receiver should sort first because it belongs to the RFC and its
+// arg does not
+// - 0 if the receiver and arg both belong to the same RFC or neither do.
+// - 1 If the arg belongs to the RFC but receiver does not.
+func (ipv4 IPv4Addr) CmpRFC(rfcNum uint, sa SockAddr) int {
+ recvInRFC := IsRFC(rfcNum, ipv4)
+ ipv4b, ok := sa.(IPv4Addr)
+ if !ok {
+ // If the receiver is part of the desired RFC and the SockAddr
+ // argument is not, return -1 so that the receiver sorts before
+ // the non-IPv4 SockAddr. Conversely, if the receiver is not
+ // part of the RFC, punt on sorting and leave it for the next
+ // sorter.
+ if recvInRFC {
+ return sortReceiverBeforeArg
+ } else {
+ return sortDeferDecision
+ }
+ }
+
+ argInRFC := IsRFC(rfcNum, ipv4b)
+ switch {
+ case (recvInRFC && argInRFC), (!recvInRFC && !argInRFC):
+ // If a and b both belong to the RFC, or neither belong to
+ // rfcNum, defer sorting to the next sorter.
+ return sortDeferDecision
+ case recvInRFC && !argInRFC:
+ return sortReceiverBeforeArg
+ default:
+ return sortArgBeforeReceiver
+ }
+}
+
+// Contains returns true if the SockAddr is contained within the receiver.
+func (ipv4 IPv4Addr) Contains(sa SockAddr) bool {
+ ipv4b, ok := sa.(IPv4Addr)
+ if !ok {
+ return false
+ }
+
+ return ipv4.ContainsNetwork(ipv4b)
+}
+
+// ContainsAddress returns true if the IPv4Address is contained within the
+// receiver.
+func (ipv4 IPv4Addr) ContainsAddress(x IPv4Address) bool {
+ return IPv4Address(ipv4.NetworkAddress()) <= x &&
+ IPv4Address(ipv4.BroadcastAddress()) >= x
+}
+
+// ContainsNetwork returns true if the network from IPv4Addr is contained
+// within the receiver.
+func (ipv4 IPv4Addr) ContainsNetwork(x IPv4Addr) bool {
+ return ipv4.NetworkAddress() <= x.NetworkAddress() &&
+ ipv4.BroadcastAddress() >= x.BroadcastAddress()
+}
+
+// DialPacketArgs returns the arguments required to be passed to
+// net.DialUDP(). If the Mask of ipv4 is not a /32 or the Port is 0,
+// DialPacketArgs() will fail. See Host() to create an IPv4Addr with its
+// mask set to /32.
+func (ipv4 IPv4Addr) DialPacketArgs() (network, dialArgs string) {
+ if ipv4.Mask != IPv4HostMask || ipv4.Port == 0 {
+ return "udp4", ""
+ }
+ return "udp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port)
+}
+
+// DialStreamArgs returns the arguments required to be passed to
+// net.DialTCP(). If the Mask of ipv4 is not a /32 or the Port is 0,
+// DialStreamArgs() will fail. See Host() to create an IPv4Addr with its
+// mask set to /32.
+func (ipv4 IPv4Addr) DialStreamArgs() (network, dialArgs string) {
+ if ipv4.Mask != IPv4HostMask || ipv4.Port == 0 {
+ return "tcp4", ""
+ }
+ return "tcp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port)
+}
+
+// Equal returns true if a SockAddr is equal to the receiving IPv4Addr.
+func (ipv4 IPv4Addr) Equal(sa SockAddr) bool {
+ ipv4b, ok := sa.(IPv4Addr)
+ if !ok {
+ return false
+ }
+
+ if ipv4.Port != ipv4b.Port {
+ return false
+ }
+
+ if ipv4.Address != ipv4b.Address {
+ return false
+ }
+
+ if ipv4.NetIPNet().String() != ipv4b.NetIPNet().String() {
+ return false
+ }
+
+ return true
+}
+
+// FirstUsable returns an IPv4Addr set to the first address following the
+// network prefix. The first usable address in a network is normally the
+// gateway and should not be used except by devices forwarding packets
+// between two administratively distinct networks (i.e. a router). This
+// function does not discriminate against first usable vs "first address that
+// should be used." For example, FirstUsable() on "192.168.1.10/24" would
+// return the address "192.168.1.1/24".
+func (ipv4 IPv4Addr) FirstUsable() IPAddr {
+ addr := ipv4.NetworkAddress()
+
+ // If /32, return the address itself. If /31 assume a point-to-point
+ // link and return the lower address.
+ if ipv4.Maskbits() < 31 {
+ addr++
+ }
+
+ return IPv4Addr{
+ Address: IPv4Address(addr),
+ Mask: IPv4HostMask,
+ }
+}
+
+// Host returns a copy of ipv4 with its mask set to /32 so that it can be
+// used by DialPacketArgs(), DialStreamArgs(), ListenPacketArgs(), or
+// ListenStreamArgs().
+func (ipv4 IPv4Addr) Host() IPAddr {
+ // Nothing should listen on a broadcast address.
+ return IPv4Addr{
+ Address: ipv4.Address,
+ Mask: IPv4HostMask,
+ Port: ipv4.Port,
+ }
+}
+
+// IPPort returns the Port number attached to the IPv4Addr
+func (ipv4 IPv4Addr) IPPort() IPPort {
+ return ipv4.Port
+}
+
+// LastUsable returns the last address before the broadcast address in a
+// given network.
+func (ipv4 IPv4Addr) LastUsable() IPAddr {
+ addr := ipv4.BroadcastAddress()
+
+ // If /32, return the address itself. If /31 assume a point-to-point
+ // link and return the upper address.
+ if ipv4.Maskbits() < 31 {
+ addr--
+ }
+
+ return IPv4Addr{
+ Address: IPv4Address(addr),
+ Mask: IPv4HostMask,
+ }
+}
+
+// ListenPacketArgs returns the arguments required to be passed to
+// net.ListenUDP(). If the Mask of ipv4 is not a /32, ListenPacketArgs()
+// will fail. See Host() to create an IPv4Addr with its mask set to /32.
+func (ipv4 IPv4Addr) ListenPacketArgs() (network, listenArgs string) {
+ if ipv4.Mask != IPv4HostMask {
+ return "udp4", ""
+ }
+ return "udp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port)
+}
+
+// ListenStreamArgs returns the arguments required to be passed to
+// net.ListenTCP(). If the Mask of ipv4 is not a /32, ListenStreamArgs()
+// will fail. See Host() to create an IPv4Addr with its mask set to /32.
+func (ipv4 IPv4Addr) ListenStreamArgs() (network, listenArgs string) {
+ if ipv4.Mask != IPv4HostMask {
+ return "tcp4", ""
+ }
+ return "tcp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port)
+}
+
+// Maskbits returns the number of network mask bits in a given IPv4Addr. For
+// example, the Maskbits() of "192.168.1.1/24" would return 24.
+func (ipv4 IPv4Addr) Maskbits() int {
+ mask := make(net.IPMask, IPv4len)
+ binary.BigEndian.PutUint32(mask, uint32(ipv4.Mask))
+ maskOnes, _ := mask.Size()
+ return maskOnes
+}
+
+// MustIPv4Addr is a helper method that must return an IPv4Addr or panic on
+// invalid input.
+func MustIPv4Addr(addr string) IPv4Addr {
+ ipv4, err := NewIPv4Addr(addr)
+ if err != nil {
+ panic(fmt.Sprintf("Unable to create an IPv4Addr from %+q: %v", addr, err))
+ }
+ return ipv4
+}
+
+// NetIP returns the address as a net.IP (address is always presized to
+// IPv4).
+func (ipv4 IPv4Addr) NetIP() *net.IP {
+ x := make(net.IP, IPv4len)
+ binary.BigEndian.PutUint32(x, uint32(ipv4.Address))
+ return &x
+}
+
+// NetIPMask create a new net.IPMask from the IPv4Addr.
+func (ipv4 IPv4Addr) NetIPMask() *net.IPMask {
+ ipv4Mask := net.IPMask{}
+ ipv4Mask = make(net.IPMask, IPv4len)
+ binary.BigEndian.PutUint32(ipv4Mask, uint32(ipv4.Mask))
+ return &ipv4Mask
+}
+
+// NetIPNet create a new net.IPNet from the IPv4Addr.
+func (ipv4 IPv4Addr) NetIPNet() *net.IPNet {
+ ipv4net := &net.IPNet{}
+ ipv4net.IP = make(net.IP, IPv4len)
+ binary.BigEndian.PutUint32(ipv4net.IP, uint32(ipv4.NetworkAddress()))
+ ipv4net.Mask = *ipv4.NetIPMask()
+ return ipv4net
+}
+
+// Network returns the network prefix or network address for a given network.
+func (ipv4 IPv4Addr) Network() IPAddr {
+ return IPv4Addr{
+ Address: IPv4Address(ipv4.NetworkAddress()),
+ Mask: ipv4.Mask,
+ }
+}
+
+// NetworkAddress returns an IPv4Network of the IPv4Addr's network address.
+func (ipv4 IPv4Addr) NetworkAddress() IPv4Network {
+ return IPv4Network(uint32(ipv4.Address) & uint32(ipv4.Mask))
+}
+
+// Octets returns a slice of the four octets in an IPv4Addr's Address. The
+// order of the bytes is big endian.
+func (ipv4 IPv4Addr) Octets() []int {
+ return []int{
+ int(ipv4.Address >> 24),
+ int((ipv4.Address >> 16) & 0xff),
+ int((ipv4.Address >> 8) & 0xff),
+ int(ipv4.Address & 0xff),
+ }
+}
+
+// String returns a string representation of the IPv4Addr
+func (ipv4 IPv4Addr) String() string {
+ if ipv4.Port != 0 {
+ return fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port)
+ }
+
+ if ipv4.Maskbits() == 32 {
+ return ipv4.NetIP().String()
+ }
+
+ return fmt.Sprintf("%s/%d", ipv4.NetIP().String(), ipv4.Maskbits())
+}
+
+// Type is used as a type switch and returns TypeIPv4
+func (IPv4Addr) Type() SockAddrType {
+ return TypeIPv4
+}
+
+// IPv4AddrAttr returns a string representation of an attribute for the given
+// IPv4Addr.
+func IPv4AddrAttr(ipv4 IPv4Addr, selector AttrName) string {
+ fn, found := ipv4AddrAttrMap[selector]
+ if !found {
+ return ""
+ }
+
+ return fn(ipv4)
+}
+
+// IPv4Attrs returns a list of attributes supported by the IPv4Addr type
+func IPv4Attrs() []AttrName {
+ return ipv4AddrAttrs
+}
+
+// ipv4AddrInit is called once at init()
+func ipv4AddrInit() {
+ // Sorted for human readability
+ ipv4AddrAttrs = []AttrName{
+ "size", // Same position as in IPv6 for output consistency
+ "broadcast",
+ "uint32",
+ }
+
+ ipv4AddrAttrMap = map[AttrName]func(ipv4 IPv4Addr) string{
+ "broadcast": func(ipv4 IPv4Addr) string {
+ return ipv4.Broadcast().String()
+ },
+ "size": func(ipv4 IPv4Addr) string {
+ return fmt.Sprintf("%d", 1<<uint(IPv4len*8-ipv4.Maskbits()))
+ },
+ "uint32": func(ipv4 IPv4Addr) string {
+ return fmt.Sprintf("%d", uint32(ipv4.Address))
+ },
+ }
+}
--- /dev/null
+package sockaddr
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "math/big"
+ "net"
+)
+
+type (
+ // IPv6Address is a named type representing an IPv6 address.
+ IPv6Address *big.Int
+
+ // IPv6Network is a named type representing an IPv6 network.
+ IPv6Network *big.Int
+
+ // IPv6Mask is a named type representing an IPv6 network mask.
+ IPv6Mask *big.Int
+)
+
+// IPv6HostPrefix is a constant represents a /128 IPv6 Prefix.
+const IPv6HostPrefix = IPPrefixLen(128)
+
+// ipv6HostMask is an unexported big.Int representing a /128 IPv6 address.
+// This value must be a constant and always set to all ones.
+var ipv6HostMask IPv6Mask
+
+// ipv6AddrAttrMap is a map of the IPv6Addr type-specific attributes.
+var ipv6AddrAttrMap map[AttrName]func(IPv6Addr) string
+var ipv6AddrAttrs []AttrName
+
+func init() {
+ biMask := new(big.Int)
+ biMask.SetBytes([]byte{
+ 0xff, 0xff,
+ 0xff, 0xff,
+ 0xff, 0xff,
+ 0xff, 0xff,
+ 0xff, 0xff,
+ 0xff, 0xff,
+ 0xff, 0xff,
+ 0xff, 0xff,
+ },
+ )
+ ipv6HostMask = IPv6Mask(biMask)
+
+ ipv6AddrInit()
+}
+
+// IPv6Addr implements a convenience wrapper around the union of Go's
+// built-in net.IP and net.IPNet types. In UNIX-speak, IPv6Addr implements
+// `sockaddr` when the the address family is set to AF_INET6
+// (i.e. `sockaddr_in6`).
+type IPv6Addr struct {
+ IPAddr
+ Address IPv6Address
+ Mask IPv6Mask
+ Port IPPort
+}
+
+// NewIPv6Addr creates an IPv6Addr from a string. String can be in the form of
+// an an IPv6:port (e.g. `[2001:4860:0:2001::68]:80`, in which case the mask is
+// assumed to be a /128), an IPv6 address (e.g. `2001:4860:0:2001::68`, also
+// with a `/128` mask), an IPv6 CIDR (e.g. `2001:4860:0:2001::68/64`, which has
+// its IP port initialized to zero). ipv6Str can not be a hostname.
+//
+// NOTE: Many net.*() routines will initialize and return an IPv4 address.
+// Always test to make sure the address returned cannot be converted to a 4 byte
+// array using To4().
+func NewIPv6Addr(ipv6Str string) (IPv6Addr, error) {
+ v6Addr := false
+LOOP:
+ for i := 0; i < len(ipv6Str); i++ {
+ switch ipv6Str[i] {
+ case '.':
+ break LOOP
+ case ':':
+ v6Addr = true
+ break LOOP
+ }
+ }
+
+ if !v6Addr {
+ return IPv6Addr{}, fmt.Errorf("Unable to resolve %+q as an IPv6 address, appears to be an IPv4 address", ipv6Str)
+ }
+
+ // Attempt to parse ipv6Str as a /128 host with a port number.
+ tcpAddr, err := net.ResolveTCPAddr("tcp6", ipv6Str)
+ if err == nil {
+ ipv6 := tcpAddr.IP.To16()
+ if ipv6 == nil {
+ return IPv6Addr{}, fmt.Errorf("Unable to resolve %+q as a 16byte IPv6 address", ipv6Str)
+ }
+
+ ipv6BigIntAddr := new(big.Int)
+ ipv6BigIntAddr.SetBytes(ipv6)
+
+ ipv6BigIntMask := new(big.Int)
+ ipv6BigIntMask.Set(ipv6HostMask)
+
+ ipv6Addr := IPv6Addr{
+ Address: IPv6Address(ipv6BigIntAddr),
+ Mask: IPv6Mask(ipv6BigIntMask),
+ Port: IPPort(tcpAddr.Port),
+ }
+
+ return ipv6Addr, nil
+ }
+
+ // Parse as a naked IPv6 address. Trim square brackets if present.
+ if len(ipv6Str) > 2 && ipv6Str[0] == '[' && ipv6Str[len(ipv6Str)-1] == ']' {
+ ipv6Str = ipv6Str[1 : len(ipv6Str)-1]
+ }
+ ip := net.ParseIP(ipv6Str)
+ if ip != nil {
+ ipv6 := ip.To16()
+ if ipv6 == nil {
+ return IPv6Addr{}, fmt.Errorf("Unable to string convert %+q to a 16byte IPv6 address", ipv6Str)
+ }
+
+ ipv6BigIntAddr := new(big.Int)
+ ipv6BigIntAddr.SetBytes(ipv6)
+
+ ipv6BigIntMask := new(big.Int)
+ ipv6BigIntMask.Set(ipv6HostMask)
+
+ return IPv6Addr{
+ Address: IPv6Address(ipv6BigIntAddr),
+ Mask: IPv6Mask(ipv6BigIntMask),
+ }, nil
+ }
+
+ // Parse as an IPv6 CIDR
+ ipAddr, network, err := net.ParseCIDR(ipv6Str)
+ if err == nil {
+ ipv6 := ipAddr.To16()
+ if ipv6 == nil {
+ return IPv6Addr{}, fmt.Errorf("Unable to convert %+q to a 16byte IPv6 address", ipv6Str)
+ }
+
+ ipv6BigIntAddr := new(big.Int)
+ ipv6BigIntAddr.SetBytes(ipv6)
+
+ ipv6BigIntMask := new(big.Int)
+ ipv6BigIntMask.SetBytes(network.Mask)
+
+ ipv6Addr := IPv6Addr{
+ Address: IPv6Address(ipv6BigIntAddr),
+ Mask: IPv6Mask(ipv6BigIntMask),
+ }
+ return ipv6Addr, nil
+ }
+
+ return IPv6Addr{}, fmt.Errorf("Unable to parse %+q to an IPv6 address: %v", ipv6Str, err)
+}
+
+// AddressBinString returns a string with the IPv6Addr's Address represented
+// as a sequence of '0' and '1' characters. This method is useful for
+// debugging or by operators who want to inspect an address.
+func (ipv6 IPv6Addr) AddressBinString() string {
+ bi := big.Int(*ipv6.Address)
+ return fmt.Sprintf("%0128s", bi.Text(2))
+}
+
+// AddressHexString returns a string with the IPv6Addr address represented as
+// a sequence of hex characters. This method is useful for debugging or by
+// operators who want to inspect an address.
+func (ipv6 IPv6Addr) AddressHexString() string {
+ bi := big.Int(*ipv6.Address)
+ return fmt.Sprintf("%032s", bi.Text(16))
+}
+
+// CmpAddress follows the Cmp() standard protocol and returns:
+//
+// - -1 If the receiver should sort first because its address is lower than arg
+// - 0 if the SockAddr arg equal to the receiving IPv6Addr or the argument is of a
+// different type.
+// - 1 If the argument should sort first.
+func (ipv6 IPv6Addr) CmpAddress(sa SockAddr) int {
+ ipv6b, ok := sa.(IPv6Addr)
+ if !ok {
+ return sortDeferDecision
+ }
+
+ ipv6aBigInt := new(big.Int)
+ ipv6aBigInt.Set(ipv6.Address)
+ ipv6bBigInt := new(big.Int)
+ ipv6bBigInt.Set(ipv6b.Address)
+
+ return ipv6aBigInt.Cmp(ipv6bBigInt)
+}
+
+// CmpPort follows the Cmp() standard protocol and returns:
+//
+// - -1 If the receiver should sort first because its port is lower than arg
+// - 0 if the SockAddr arg's port number is equal to the receiving IPv6Addr,
+// regardless of type.
+// - 1 If the argument should sort first.
+func (ipv6 IPv6Addr) CmpPort(sa SockAddr) int {
+ var saPort IPPort
+ switch v := sa.(type) {
+ case IPv4Addr:
+ saPort = v.Port
+ case IPv6Addr:
+ saPort = v.Port
+ default:
+ return sortDeferDecision
+ }
+
+ switch {
+ case ipv6.Port == saPort:
+ return sortDeferDecision
+ case ipv6.Port < saPort:
+ return sortReceiverBeforeArg
+ default:
+ return sortArgBeforeReceiver
+ }
+}
+
+// CmpRFC follows the Cmp() standard protocol and returns:
+//
+// - -1 If the receiver should sort first because it belongs to the RFC and its
+// arg does not
+// - 0 if the receiver and arg both belong to the same RFC or neither do.
+// - 1 If the arg belongs to the RFC but receiver does not.
+func (ipv6 IPv6Addr) CmpRFC(rfcNum uint, sa SockAddr) int {
+ recvInRFC := IsRFC(rfcNum, ipv6)
+ ipv6b, ok := sa.(IPv6Addr)
+ if !ok {
+ // If the receiver is part of the desired RFC and the SockAddr
+ // argument is not, sort receiver before the non-IPv6 SockAddr.
+ // Conversely, if the receiver is not part of the RFC, punt on
+ // sorting and leave it for the next sorter.
+ if recvInRFC {
+ return sortReceiverBeforeArg
+ } else {
+ return sortDeferDecision
+ }
+ }
+
+ argInRFC := IsRFC(rfcNum, ipv6b)
+ switch {
+ case (recvInRFC && argInRFC), (!recvInRFC && !argInRFC):
+ // If a and b both belong to the RFC, or neither belong to
+ // rfcNum, defer sorting to the next sorter.
+ return sortDeferDecision
+ case recvInRFC && !argInRFC:
+ return sortReceiverBeforeArg
+ default:
+ return sortArgBeforeReceiver
+ }
+}
+
+// Contains returns true if the SockAddr is contained within the receiver.
+func (ipv6 IPv6Addr) Contains(sa SockAddr) bool {
+ ipv6b, ok := sa.(IPv6Addr)
+ if !ok {
+ return false
+ }
+
+ return ipv6.ContainsNetwork(ipv6b)
+}
+
+// ContainsAddress returns true if the IPv6Address is contained within the
+// receiver.
+func (ipv6 IPv6Addr) ContainsAddress(x IPv6Address) bool {
+ xAddr := IPv6Addr{
+ Address: x,
+ Mask: ipv6HostMask,
+ }
+
+ {
+ xIPv6 := xAddr.FirstUsable().(IPv6Addr)
+ yIPv6 := ipv6.FirstUsable().(IPv6Addr)
+ if xIPv6.CmpAddress(yIPv6) >= 1 {
+ return false
+ }
+ }
+
+ {
+ xIPv6 := xAddr.LastUsable().(IPv6Addr)
+ yIPv6 := ipv6.LastUsable().(IPv6Addr)
+ if xIPv6.CmpAddress(yIPv6) <= -1 {
+ return false
+ }
+ }
+ return true
+}
+
+// ContainsNetwork returns true if the network from IPv6Addr is contained within
+// the receiver.
+func (x IPv6Addr) ContainsNetwork(y IPv6Addr) bool {
+ {
+ xIPv6 := x.FirstUsable().(IPv6Addr)
+ yIPv6 := y.FirstUsable().(IPv6Addr)
+ if ret := xIPv6.CmpAddress(yIPv6); ret >= 1 {
+ return false
+ }
+ }
+
+ {
+ xIPv6 := x.LastUsable().(IPv6Addr)
+ yIPv6 := y.LastUsable().(IPv6Addr)
+ if ret := xIPv6.CmpAddress(yIPv6); ret <= -1 {
+ return false
+ }
+ }
+ return true
+}
+
+// DialPacketArgs returns the arguments required to be passed to
+// net.DialUDP(). If the Mask of ipv6 is not a /128 or the Port is 0,
+// DialPacketArgs() will fail. See Host() to create an IPv6Addr with its
+// mask set to /128.
+func (ipv6 IPv6Addr) DialPacketArgs() (network, dialArgs string) {
+ ipv6Mask := big.Int(*ipv6.Mask)
+ if ipv6Mask.Cmp(ipv6HostMask) != 0 || ipv6.Port == 0 {
+ return "udp6", ""
+ }
+ return "udp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port)
+}
+
+// DialStreamArgs returns the arguments required to be passed to
+// net.DialTCP(). If the Mask of ipv6 is not a /128 or the Port is 0,
+// DialStreamArgs() will fail. See Host() to create an IPv6Addr with its
+// mask set to /128.
+func (ipv6 IPv6Addr) DialStreamArgs() (network, dialArgs string) {
+ ipv6Mask := big.Int(*ipv6.Mask)
+ if ipv6Mask.Cmp(ipv6HostMask) != 0 || ipv6.Port == 0 {
+ return "tcp6", ""
+ }
+ return "tcp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port)
+}
+
+// Equal returns true if a SockAddr is equal to the receiving IPv4Addr.
+func (ipv6a IPv6Addr) Equal(sa SockAddr) bool {
+ ipv6b, ok := sa.(IPv6Addr)
+ if !ok {
+ return false
+ }
+
+ if ipv6a.NetIP().String() != ipv6b.NetIP().String() {
+ return false
+ }
+
+ if ipv6a.NetIPNet().String() != ipv6b.NetIPNet().String() {
+ return false
+ }
+
+ if ipv6a.Port != ipv6b.Port {
+ return false
+ }
+
+ return true
+}
+
+// FirstUsable returns an IPv6Addr set to the first address following the
+// network prefix. The first usable address in a network is normally the
+// gateway and should not be used except by devices forwarding packets
+// between two administratively distinct networks (i.e. a router). This
+// function does not discriminate against first usable vs "first address that
+// should be used." For example, FirstUsable() on "2001:0db8::0003/64" would
+// return "2001:0db8::00011".
+func (ipv6 IPv6Addr) FirstUsable() IPAddr {
+ return IPv6Addr{
+ Address: IPv6Address(ipv6.NetworkAddress()),
+ Mask: ipv6HostMask,
+ }
+}
+
+// Host returns a copy of ipv6 with its mask set to /128 so that it can be
+// used by DialPacketArgs(), DialStreamArgs(), ListenPacketArgs(), or
+// ListenStreamArgs().
+func (ipv6 IPv6Addr) Host() IPAddr {
+ // Nothing should listen on a broadcast address.
+ return IPv6Addr{
+ Address: ipv6.Address,
+ Mask: ipv6HostMask,
+ Port: ipv6.Port,
+ }
+}
+
+// IPPort returns the Port number attached to the IPv6Addr
+func (ipv6 IPv6Addr) IPPort() IPPort {
+ return ipv6.Port
+}
+
+// LastUsable returns the last address in a given network.
+func (ipv6 IPv6Addr) LastUsable() IPAddr {
+ addr := new(big.Int)
+ addr.Set(ipv6.Address)
+
+ mask := new(big.Int)
+ mask.Set(ipv6.Mask)
+
+ negMask := new(big.Int)
+ negMask.Xor(ipv6HostMask, mask)
+
+ lastAddr := new(big.Int)
+ lastAddr.And(addr, mask)
+ lastAddr.Or(lastAddr, negMask)
+
+ return IPv6Addr{
+ Address: IPv6Address(lastAddr),
+ Mask: ipv6HostMask,
+ }
+}
+
+// ListenPacketArgs returns the arguments required to be passed to
+// net.ListenUDP(). If the Mask of ipv6 is not a /128, ListenPacketArgs()
+// will fail. See Host() to create an IPv6Addr with its mask set to /128.
+func (ipv6 IPv6Addr) ListenPacketArgs() (network, listenArgs string) {
+ ipv6Mask := big.Int(*ipv6.Mask)
+ if ipv6Mask.Cmp(ipv6HostMask) != 0 {
+ return "udp6", ""
+ }
+ return "udp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port)
+}
+
+// ListenStreamArgs returns the arguments required to be passed to
+// net.ListenTCP(). If the Mask of ipv6 is not a /128, ListenStreamArgs()
+// will fail. See Host() to create an IPv6Addr with its mask set to /128.
+func (ipv6 IPv6Addr) ListenStreamArgs() (network, listenArgs string) {
+ ipv6Mask := big.Int(*ipv6.Mask)
+ if ipv6Mask.Cmp(ipv6HostMask) != 0 {
+ return "tcp6", ""
+ }
+ return "tcp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port)
+}
+
+// Maskbits returns the number of network mask bits in a given IPv6Addr. For
+// example, the Maskbits() of "2001:0db8::0003/64" would return 64.
+func (ipv6 IPv6Addr) Maskbits() int {
+ maskOnes, _ := ipv6.NetIPNet().Mask.Size()
+
+ return maskOnes
+}
+
+// MustIPv6Addr is a helper method that must return an IPv6Addr or panic on
+// invalid input.
+func MustIPv6Addr(addr string) IPv6Addr {
+ ipv6, err := NewIPv6Addr(addr)
+ if err != nil {
+ panic(fmt.Sprintf("Unable to create an IPv6Addr from %+q: %v", addr, err))
+ }
+ return ipv6
+}
+
+// NetIP returns the address as a net.IP.
+func (ipv6 IPv6Addr) NetIP() *net.IP {
+ return bigIntToNetIPv6(ipv6.Address)
+}
+
+// NetIPMask create a new net.IPMask from the IPv6Addr.
+func (ipv6 IPv6Addr) NetIPMask() *net.IPMask {
+ ipv6Mask := make(net.IPMask, IPv6len)
+ m := big.Int(*ipv6.Mask)
+ copy(ipv6Mask, m.Bytes())
+ return &ipv6Mask
+}
+
+// Network returns a pointer to the net.IPNet within IPv4Addr receiver.
+func (ipv6 IPv6Addr) NetIPNet() *net.IPNet {
+ ipv6net := &net.IPNet{}
+ ipv6net.IP = make(net.IP, IPv6len)
+ copy(ipv6net.IP, *ipv6.NetIP())
+ ipv6net.Mask = *ipv6.NetIPMask()
+ return ipv6net
+}
+
+// Network returns the network prefix or network address for a given network.
+func (ipv6 IPv6Addr) Network() IPAddr {
+ return IPv6Addr{
+ Address: IPv6Address(ipv6.NetworkAddress()),
+ Mask: ipv6.Mask,
+ }
+}
+
+// NetworkAddress returns an IPv6Network of the IPv6Addr's network address.
+func (ipv6 IPv6Addr) NetworkAddress() IPv6Network {
+ addr := new(big.Int)
+ addr.SetBytes((*ipv6.Address).Bytes())
+
+ mask := new(big.Int)
+ mask.SetBytes(*ipv6.NetIPMask())
+
+ netAddr := new(big.Int)
+ netAddr.And(addr, mask)
+
+ return IPv6Network(netAddr)
+}
+
+// Octets returns a slice of the 16 octets in an IPv6Addr's Address. The
+// order of the bytes is big endian.
+func (ipv6 IPv6Addr) Octets() []int {
+ x := make([]int, IPv6len)
+ for i, b := range *bigIntToNetIPv6(ipv6.Address) {
+ x[i] = int(b)
+ }
+
+ return x
+}
+
+// String returns a string representation of the IPv6Addr
+func (ipv6 IPv6Addr) String() string {
+ if ipv6.Port != 0 {
+ return fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port)
+ }
+
+ if ipv6.Maskbits() == 128 {
+ return ipv6.NetIP().String()
+ }
+
+ return fmt.Sprintf("%s/%d", ipv6.NetIP().String(), ipv6.Maskbits())
+}
+
+// Type is used as a type switch and returns TypeIPv6
+func (IPv6Addr) Type() SockAddrType {
+ return TypeIPv6
+}
+
+// IPv6Attrs returns a list of attributes supported by the IPv6Addr type
+func IPv6Attrs() []AttrName {
+ return ipv6AddrAttrs
+}
+
+// IPv6AddrAttr returns a string representation of an attribute for the given
+// IPv6Addr.
+func IPv6AddrAttr(ipv6 IPv6Addr, selector AttrName) string {
+ fn, found := ipv6AddrAttrMap[selector]
+ if !found {
+ return ""
+ }
+
+ return fn(ipv6)
+}
+
+// ipv6AddrInit is called once at init()
+func ipv6AddrInit() {
+ // Sorted for human readability
+ ipv6AddrAttrs = []AttrName{
+ "size", // Same position as in IPv6 for output consistency
+ "uint128",
+ }
+
+ ipv6AddrAttrMap = map[AttrName]func(ipv6 IPv6Addr) string{
+ "size": func(ipv6 IPv6Addr) string {
+ netSize := big.NewInt(1)
+ netSize = netSize.Lsh(netSize, uint(IPv6len*8-ipv6.Maskbits()))
+ return netSize.Text(10)
+ },
+ "uint128": func(ipv6 IPv6Addr) string {
+ b := big.Int(*ipv6.Address)
+ return b.Text(10)
+ },
+ }
+}
+
+// bigIntToNetIPv6 is a helper function that correctly returns a net.IP with the
+// correctly padded values.
+func bigIntToNetIPv6(bi *big.Int) *net.IP {
+ x := make(net.IP, IPv6len)
+ ipv6Bytes := bi.Bytes()
+
+ // It's possibe for ipv6Bytes to be less than IPv6len bytes in size. If
+ // they are different sizes we to pad the size of response.
+ if len(ipv6Bytes) < IPv6len {
+ buf := new(bytes.Buffer)
+ buf.Grow(IPv6len)
+
+ for i := len(ipv6Bytes); i < IPv6len; i++ {
+ if err := binary.Write(buf, binary.BigEndian, byte(0)); err != nil {
+ panic(fmt.Sprintf("Unable to pad byte %d of input %v: %v", i, bi, err))
+ }
+ }
+
+ for _, b := range ipv6Bytes {
+ if err := binary.Write(buf, binary.BigEndian, b); err != nil {
+ panic(fmt.Sprintf("Unable to preserve endianness of input %v: %v", bi, err))
+ }
+ }
+
+ ipv6Bytes = buf.Bytes()
+ }
+ i := copy(x, ipv6Bytes)
+ if i != IPv6len {
+ panic("IPv6 wrong size")
+ }
+ return &x
+}
--- /dev/null
+package sockaddr
+
+// ForwardingBlacklist is a faux RFC that includes a list of non-forwardable IP
+// blocks.
+const ForwardingBlacklist = 4294967295
+const ForwardingBlacklistRFC = "4294967295"
+
+// IsRFC tests to see if an SockAddr matches the specified RFC
+func IsRFC(rfcNum uint, sa SockAddr) bool {
+ rfcNetMap := KnownRFCs()
+ rfcNets, ok := rfcNetMap[rfcNum]
+ if !ok {
+ return false
+ }
+
+ var contained bool
+ for _, rfcNet := range rfcNets {
+ if rfcNet.Contains(sa) {
+ contained = true
+ break
+ }
+ }
+ return contained
+}
+
+// KnownRFCs returns an initial set of known RFCs.
+//
+// NOTE (sean@): As this list evolves over time, please submit patches to keep
+// this list current. If something isn't right, inquire, as it may just be a
+// bug on my part. Some of the inclusions were based on my judgement as to what
+// would be a useful value (e.g. RFC3330).
+//
+// Useful resources:
+//
+// * https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml
+// * https://www.iana.org/assignments/ipv6-unicast-address-assignments/ipv6-unicast-address-assignments.xhtml
+// * https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml
+func KnownRFCs() map[uint]SockAddrs {
+ // NOTE(sean@): Multiple SockAddrs per RFC lend themselves well to a
+ // RADIX tree, but `ENOTIME`. Patches welcome.
+ return map[uint]SockAddrs{
+ 919: {
+ // [RFC919] Broadcasting Internet Datagrams
+ MustIPv4Addr("255.255.255.255/32"), // [RFC1122], §7 Broadcast IP Addressing - Proposed Standards
+ },
+ 1122: {
+ // [RFC1122] Requirements for Internet Hosts -- Communication Layers
+ MustIPv4Addr("0.0.0.0/8"), // [RFC1122], §3.2.1.3
+ MustIPv4Addr("127.0.0.0/8"), // [RFC1122], §3.2.1.3
+ },
+ 1112: {
+ // [RFC1112] Host Extensions for IP Multicasting
+ MustIPv4Addr("224.0.0.0/4"), // [RFC1112], §4 Host Group Addresses
+ },
+ 1918: {
+ // [RFC1918] Address Allocation for Private Internets
+ MustIPv4Addr("10.0.0.0/8"),
+ MustIPv4Addr("172.16.0.0/12"),
+ MustIPv4Addr("192.168.0.0/16"),
+ },
+ 2544: {
+ // [RFC2544] Benchmarking Methodology for Network
+ // Interconnect Devices
+ MustIPv4Addr("198.18.0.0/15"),
+ },
+ 2765: {
+ // [RFC2765] Stateless IP/ICMP Translation Algorithm
+ // (SIIT) (obsoleted by RFCs 6145, which itself was
+ // later obsoleted by 7915).
+
+ // [RFC2765], §2.1 Addresses
+ MustIPv6Addr("0:0:0:0:0:ffff:0:0/96"),
+ },
+ 2928: {
+ // [RFC2928] Initial IPv6 Sub-TLA ID Assignments
+ MustIPv6Addr("2001::/16"), // Superblock
+ //MustIPv6Addr("2001:0000::/23"), // IANA
+ //MustIPv6Addr("2001:0200::/23"), // APNIC
+ //MustIPv6Addr("2001:0400::/23"), // ARIN
+ //MustIPv6Addr("2001:0600::/23"), // RIPE NCC
+ //MustIPv6Addr("2001:0800::/23"), // (future assignment)
+ // ...
+ //MustIPv6Addr("2001:FE00::/23"), // (future assignment)
+ },
+ 3056: { // 6to4 address
+ // [RFC3056] Connection of IPv6 Domains via IPv4 Clouds
+
+ // [RFC3056], §2 IPv6 Prefix Allocation
+ MustIPv6Addr("2002::/16"),
+ },
+ 3068: {
+ // [RFC3068] An Anycast Prefix for 6to4 Relay Routers
+ // (obsolete by RFC7526)
+
+ // [RFC3068], § 6to4 Relay anycast address
+ MustIPv4Addr("192.88.99.0/24"),
+
+ // [RFC3068], §2.5 6to4 IPv6 relay anycast address
+ //
+ // NOTE: /120 == 128-(32-24)
+ MustIPv6Addr("2002:c058:6301::/120"),
+ },
+ 3171: {
+ // [RFC3171] IANA Guidelines for IPv4 Multicast Address Assignments
+ MustIPv4Addr("224.0.0.0/4"),
+ },
+ 3330: {
+ // [RFC3330] Special-Use IPv4 Addresses
+
+ // Addresses in this block refer to source hosts on
+ // "this" network. Address 0.0.0.0/32 may be used as a
+ // source address for this host on this network; other
+ // addresses within 0.0.0.0/8 may be used to refer to
+ // specified hosts on this network [RFC1700, page 4].
+ MustIPv4Addr("0.0.0.0/8"),
+
+ // 10.0.0.0/8 - This block is set aside for use in
+ // private networks. Its intended use is documented in
+ // [RFC1918]. Addresses within this block should not
+ // appear on the public Internet.
+ MustIPv4Addr("10.0.0.0/8"),
+
+ // 14.0.0.0/8 - This block is set aside for assignments
+ // to the international system of Public Data Networks
+ // [RFC1700, page 181]. The registry of assignments
+ // within this block can be accessed from the "Public
+ // Data Network Numbers" link on the web page at
+ // http://www.iana.org/numbers.html. Addresses within
+ // this block are assigned to users and should be
+ // treated as such.
+
+ // 24.0.0.0/8 - This block was allocated in early 1996
+ // for use in provisioning IP service over cable
+ // television systems. Although the IANA initially was
+ // involved in making assignments to cable operators,
+ // this responsibility was transferred to American
+ // Registry for Internet Numbers (ARIN) in May 2001.
+ // Addresses within this block are assigned in the
+ // normal manner and should be treated as such.
+
+ // 39.0.0.0/8 - This block was used in the "Class A
+ // Subnet Experiment" that commenced in May 1995, as
+ // documented in [RFC1797]. The experiment has been
+ // completed and this block has been returned to the
+ // pool of addresses reserved for future allocation or
+ // assignment. This block therefore no longer has a
+ // special use and is subject to allocation to a
+ // Regional Internet Registry for assignment in the
+ // normal manner.
+
+ // 127.0.0.0/8 - This block is assigned for use as the Internet host
+ // loopback address. A datagram sent by a higher level protocol to an
+ // address anywhere within this block should loop back inside the host.
+ // This is ordinarily implemented using only 127.0.0.1/32 for loopback,
+ // but no addresses within this block should ever appear on any network
+ // anywhere [RFC1700, page 5].
+ MustIPv4Addr("127.0.0.0/8"),
+
+ // 128.0.0.0/16 - This block, corresponding to the
+ // numerically lowest of the former Class B addresses,
+ // was initially and is still reserved by the IANA.
+ // Given the present classless nature of the IP address
+ // space, the basis for the reservation no longer
+ // applies and addresses in this block are subject to
+ // future allocation to a Regional Internet Registry for
+ // assignment in the normal manner.
+
+ // 169.254.0.0/16 - This is the "link local" block. It
+ // is allocated for communication between hosts on a
+ // single link. Hosts obtain these addresses by
+ // auto-configuration, such as when a DHCP server may
+ // not be found.
+ MustIPv4Addr("169.254.0.0/16"),
+
+ // 172.16.0.0/12 - This block is set aside for use in
+ // private networks. Its intended use is documented in
+ // [RFC1918]. Addresses within this block should not
+ // appear on the public Internet.
+ MustIPv4Addr("172.16.0.0/12"),
+
+ // 191.255.0.0/16 - This block, corresponding to the numerically highest
+ // to the former Class B addresses, was initially and is still reserved
+ // by the IANA. Given the present classless nature of the IP address
+ // space, the basis for the reservation no longer applies and addresses
+ // in this block are subject to future allocation to a Regional Internet
+ // Registry for assignment in the normal manner.
+
+ // 192.0.0.0/24 - This block, corresponding to the
+ // numerically lowest of the former Class C addresses,
+ // was initially and is still reserved by the IANA.
+ // Given the present classless nature of the IP address
+ // space, the basis for the reservation no longer
+ // applies and addresses in this block are subject to
+ // future allocation to a Regional Internet Registry for
+ // assignment in the normal manner.
+
+ // 192.0.2.0/24 - This block is assigned as "TEST-NET" for use in
+ // documentation and example code. It is often used in conjunction with
+ // domain names example.com or example.net in vendor and protocol
+ // documentation. Addresses within this block should not appear on the
+ // public Internet.
+ MustIPv4Addr("192.0.2.0/24"),
+
+ // 192.88.99.0/24 - This block is allocated for use as 6to4 relay
+ // anycast addresses, according to [RFC3068].
+ MustIPv4Addr("192.88.99.0/24"),
+
+ // 192.168.0.0/16 - This block is set aside for use in private networks.
+ // Its intended use is documented in [RFC1918]. Addresses within this
+ // block should not appear on the public Internet.
+ MustIPv4Addr("192.168.0.0/16"),
+
+ // 198.18.0.0/15 - This block has been allocated for use
+ // in benchmark tests of network interconnect devices.
+ // Its use is documented in [RFC2544].
+ MustIPv4Addr("198.18.0.0/15"),
+
+ // 223.255.255.0/24 - This block, corresponding to the
+ // numerically highest of the former Class C addresses,
+ // was initially and is still reserved by the IANA.
+ // Given the present classless nature of the IP address
+ // space, the basis for the reservation no longer
+ // applies and addresses in this block are subject to
+ // future allocation to a Regional Internet Registry for
+ // assignment in the normal manner.
+
+ // 224.0.0.0/4 - This block, formerly known as the Class
+ // D address space, is allocated for use in IPv4
+ // multicast address assignments. The IANA guidelines
+ // for assignments from this space are described in
+ // [RFC3171].
+ MustIPv4Addr("224.0.0.0/4"),
+
+ // 240.0.0.0/4 - This block, formerly known as the Class E address
+ // space, is reserved. The "limited broadcast" destination address
+ // 255.255.255.255 should never be forwarded outside the (sub-)net of
+ // the source. The remainder of this space is reserved
+ // for future use. [RFC1700, page 4]
+ MustIPv4Addr("240.0.0.0/4"),
+ },
+ 3849: {
+ // [RFC3849] IPv6 Address Prefix Reserved for Documentation
+ MustIPv6Addr("2001:db8::/32"), // [RFC3849], §4 IANA Considerations
+ },
+ 3927: {
+ // [RFC3927] Dynamic Configuration of IPv4 Link-Local Addresses
+ MustIPv4Addr("169.254.0.0/16"), // [RFC3927], §2.1 Link-Local Address Selection
+ },
+ 4038: {
+ // [RFC4038] Application Aspects of IPv6 Transition
+
+ // [RFC4038], §4.2. IPv6 Applications in a Dual-Stack Node
+ MustIPv6Addr("0:0:0:0:0:ffff::/96"),
+ },
+ 4193: {
+ // [RFC4193] Unique Local IPv6 Unicast Addresses
+ MustIPv6Addr("fc00::/7"),
+ },
+ 4291: {
+ // [RFC4291] IP Version 6 Addressing Architecture
+
+ // [RFC4291], §2.5.2 The Unspecified Address
+ MustIPv6Addr("::/128"),
+
+ // [RFC4291], §2.5.3 The Loopback Address
+ MustIPv6Addr("::1/128"),
+
+ // [RFC4291], §2.5.5.1. IPv4-Compatible IPv6 Address
+ MustIPv6Addr("::/96"),
+
+ // [RFC4291], §2.5.5.2. IPv4-Mapped IPv6 Address
+ MustIPv6Addr("::ffff:0:0/96"),
+
+ // [RFC4291], §2.5.6 Link-Local IPv6 Unicast Addresses
+ MustIPv6Addr("fe80::/10"),
+
+ // [RFC4291], §2.5.7 Site-Local IPv6 Unicast Addresses
+ // (depreciated)
+ MustIPv6Addr("fec0::/10"),
+
+ // [RFC4291], §2.7 Multicast Addresses
+ MustIPv6Addr("ff00::/8"),
+
+ // IPv6 Multicast Information.
+ //
+ // In the following "table" below, `ff0x` is replaced
+ // with the following values depending on the scope of
+ // the query:
+ //
+ // IPv6 Multicast Scopes:
+ // * ff00/9 // reserved
+ // * ff01/9 // interface-local
+ // * ff02/9 // link-local
+ // * ff03/9 // realm-local
+ // * ff04/9 // admin-local
+ // * ff05/9 // site-local
+ // * ff08/9 // organization-local
+ // * ff0e/9 // global
+ // * ff0f/9 // reserved
+ //
+ // IPv6 Multicast Addresses:
+ // * ff0x::2 // All routers
+ // * ff02::5 // OSPFIGP
+ // * ff02::6 // OSPFIGP Designated Routers
+ // * ff02::9 // RIP Routers
+ // * ff02::a // EIGRP Routers
+ // * ff02::d // All PIM Routers
+ // * ff02::1a // All RPL Routers
+ // * ff0x::fb // mDNSv6
+ // * ff0x::101 // All Network Time Protocol (NTP) servers
+ // * ff02::1:1 // Link Name
+ // * ff02::1:2 // All-dhcp-agents
+ // * ff02::1:3 // Link-local Multicast Name Resolution
+ // * ff05::1:3 // All-dhcp-servers
+ // * ff02::1:ff00:0/104 // Solicited-node multicast address.
+ // * ff02::2:ff00:0/104 // Node Information Queries
+ },
+ 4380: {
+ // [RFC4380] Teredo: Tunneling IPv6 over UDP through
+ // Network Address Translations (NATs)
+
+ // [RFC4380], §2.6 Global Teredo IPv6 Service Prefix
+ MustIPv6Addr("2001:0000::/32"),
+ },
+ 4773: {
+ // [RFC4773] Administration of the IANA Special Purpose IPv6 Address Block
+ MustIPv6Addr("2001:0000::/23"), // IANA
+ },
+ 4843: {
+ // [RFC4843] An IPv6 Prefix for Overlay Routable Cryptographic Hash Identifiers (ORCHID)
+ MustIPv6Addr("2001:10::/28"), // [RFC4843], §7 IANA Considerations
+ },
+ 5180: {
+ // [RFC5180] IPv6 Benchmarking Methodology for Network Interconnect Devices
+ MustIPv6Addr("2001:0200::/48"), // [RFC5180], §8 IANA Considerations
+ },
+ 5735: {
+ // [RFC5735] Special Use IPv4 Addresses
+ MustIPv4Addr("192.0.2.0/24"), // TEST-NET-1
+ MustIPv4Addr("198.51.100.0/24"), // TEST-NET-2
+ MustIPv4Addr("203.0.113.0/24"), // TEST-NET-3
+ MustIPv4Addr("198.18.0.0/15"), // Benchmarks
+ },
+ 5737: {
+ // [RFC5737] IPv4 Address Blocks Reserved for Documentation
+ MustIPv4Addr("192.0.2.0/24"), // TEST-NET-1
+ MustIPv4Addr("198.51.100.0/24"), // TEST-NET-2
+ MustIPv4Addr("203.0.113.0/24"), // TEST-NET-3
+ },
+ 6052: {
+ // [RFC6052] IPv6 Addressing of IPv4/IPv6 Translators
+ MustIPv6Addr("64:ff9b::/96"), // [RFC6052], §2.1. Well-Known Prefix
+ },
+ 6333: {
+ // [RFC6333] Dual-Stack Lite Broadband Deployments Following IPv4 Exhaustion
+ MustIPv4Addr("192.0.0.0/29"), // [RFC6333], §5.7 Well-Known IPv4 Address
+ },
+ 6598: {
+ // [RFC6598] IANA-Reserved IPv4 Prefix for Shared Address Space
+ MustIPv4Addr("100.64.0.0/10"),
+ },
+ 6666: {
+ // [RFC6666] A Discard Prefix for IPv6
+ MustIPv6Addr("0100::/64"),
+ },
+ 6890: {
+ // [RFC6890] Special-Purpose IP Address Registries
+
+ // From "RFC6890 §2.2.1 Information Requirements":
+ /*
+ The IPv4 and IPv6 Special-Purpose Address Registries maintain the
+ following information regarding each entry:
+
+ o Address Block - A block of IPv4 or IPv6 addresses that has been
+ registered for a special purpose.
+
+ o Name - A descriptive name for the special-purpose address block.
+
+ o RFC - The RFC through which the special-purpose address block was
+ requested.
+
+ o Allocation Date - The date upon which the special-purpose address
+ block was allocated.
+
+ o Termination Date - The date upon which the allocation is to be
+ terminated. This field is applicable for limited-use allocations
+ only.
+
+ o Source - A boolean value indicating whether an address from the
+ allocated special-purpose address block is valid when used as the
+ source address of an IP datagram that transits two devices.
+
+ o Destination - A boolean value indicating whether an address from
+ the allocated special-purpose address block is valid when used as
+ the destination address of an IP datagram that transits two
+ devices.
+
+ o Forwardable - A boolean value indicating whether a router may
+ forward an IP datagram whose destination address is drawn from the
+ allocated special-purpose address block between external
+ interfaces.
+
+ o Global - A boolean value indicating whether an IP datagram whose
+ destination address is drawn from the allocated special-purpose
+ address block is forwardable beyond a specified administrative
+ domain.
+
+ o Reserved-by-Protocol - A boolean value indicating whether the
+ special-purpose address block is reserved by IP, itself. This
+ value is "TRUE" if the RFC that created the special-purpose
+ address block requires all compliant IP implementations to behave
+ in a special way when processing packets either to or from
+ addresses contained by the address block.
+
+ If the value of "Destination" is FALSE, the values of "Forwardable"
+ and "Global" must also be false.
+ */
+
+ /*+----------------------+----------------------------+
+ * | Attribute | Value |
+ * +----------------------+----------------------------+
+ * | Address Block | 0.0.0.0/8 |
+ * | Name | "This host on this network"|
+ * | RFC | [RFC1122], Section 3.2.1.3 |
+ * | Allocation Date | September 1981 |
+ * | Termination Date | N/A |
+ * | Source | True |
+ * | Destination | False |
+ * | Forwardable | False |
+ * | Global | False |
+ * | Reserved-by-Protocol | True |
+ * +----------------------+----------------------------+*/
+ MustIPv4Addr("0.0.0.0/8"),
+
+ /*+----------------------+---------------+
+ * | Attribute | Value |
+ * +----------------------+---------------+
+ * | Address Block | 10.0.0.0/8 |
+ * | Name | Private-Use |
+ * | RFC | [RFC1918] |
+ * | Allocation Date | February 1996 |
+ * | Termination Date | N/A |
+ * | Source | True |
+ * | Destination | True |
+ * | Forwardable | True |
+ * | Global | False |
+ * | Reserved-by-Protocol | False |
+ * +----------------------+---------------+ */
+ MustIPv4Addr("10.0.0.0/8"),
+
+ /*+----------------------+----------------------+
+ | Attribute | Value |
+ +----------------------+----------------------+
+ | Address Block | 100.64.0.0/10 |
+ | Name | Shared Address Space |
+ | RFC | [RFC6598] |
+ | Allocation Date | April 2012 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+----------------------+*/
+ MustIPv4Addr("100.64.0.0/10"),
+
+ /*+----------------------+----------------------------+
+ | Attribute | Value |
+ +----------------------+----------------------------+
+ | Address Block | 127.0.0.0/8 |
+ | Name | Loopback |
+ | RFC | [RFC1122], Section 3.2.1.3 |
+ | Allocation Date | September 1981 |
+ | Termination Date | N/A |
+ | Source | False [1] |
+ | Destination | False [1] |
+ | Forwardable | False [1] |
+ | Global | False [1] |
+ | Reserved-by-Protocol | True |
+ +----------------------+----------------------------+*/
+ // [1] Several protocols have been granted exceptions to
+ // this rule. For examples, see [RFC4379] and
+ // [RFC5884].
+ MustIPv4Addr("127.0.0.0/8"),
+
+ /*+----------------------+----------------+
+ | Attribute | Value |
+ +----------------------+----------------+
+ | Address Block | 169.254.0.0/16 |
+ | Name | Link Local |
+ | RFC | [RFC3927] |
+ | Allocation Date | May 2005 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | True |
+ +----------------------+----------------+*/
+ MustIPv4Addr("169.254.0.0/16"),
+
+ /*+----------------------+---------------+
+ | Attribute | Value |
+ +----------------------+---------------+
+ | Address Block | 172.16.0.0/12 |
+ | Name | Private-Use |
+ | RFC | [RFC1918] |
+ | Allocation Date | February 1996 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+---------------+*/
+ MustIPv4Addr("172.16.0.0/12"),
+
+ /*+----------------------+---------------------------------+
+ | Attribute | Value |
+ +----------------------+---------------------------------+
+ | Address Block | 192.0.0.0/24 [2] |
+ | Name | IETF Protocol Assignments |
+ | RFC | Section 2.1 of this document |
+ | Allocation Date | January 2010 |
+ | Termination Date | N/A |
+ | Source | False |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+---------------------------------+*/
+ // [2] Not usable unless by virtue of a more specific
+ // reservation.
+ MustIPv4Addr("192.0.0.0/24"),
+
+ /*+----------------------+--------------------------------+
+ | Attribute | Value |
+ +----------------------+--------------------------------+
+ | Address Block | 192.0.0.0/29 |
+ | Name | IPv4 Service Continuity Prefix |
+ | RFC | [RFC6333], [RFC7335] |
+ | Allocation Date | June 2011 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+--------------------------------+*/
+ MustIPv4Addr("192.0.0.0/29"),
+
+ /*+----------------------+----------------------------+
+ | Attribute | Value |
+ +----------------------+----------------------------+
+ | Address Block | 192.0.2.0/24 |
+ | Name | Documentation (TEST-NET-1) |
+ | RFC | [RFC5737] |
+ | Allocation Date | January 2010 |
+ | Termination Date | N/A |
+ | Source | False |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+----------------------------+*/
+ MustIPv4Addr("192.0.2.0/24"),
+
+ /*+----------------------+--------------------+
+ | Attribute | Value |
+ +----------------------+--------------------+
+ | Address Block | 192.88.99.0/24 |
+ | Name | 6to4 Relay Anycast |
+ | RFC | [RFC3068] |
+ | Allocation Date | June 2001 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | True |
+ | Reserved-by-Protocol | False |
+ +----------------------+--------------------+*/
+ MustIPv4Addr("192.88.99.0/24"),
+
+ /*+----------------------+----------------+
+ | Attribute | Value |
+ +----------------------+----------------+
+ | Address Block | 192.168.0.0/16 |
+ | Name | Private-Use |
+ | RFC | [RFC1918] |
+ | Allocation Date | February 1996 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+----------------+*/
+ MustIPv4Addr("192.168.0.0/16"),
+
+ /*+----------------------+---------------+
+ | Attribute | Value |
+ +----------------------+---------------+
+ | Address Block | 198.18.0.0/15 |
+ | Name | Benchmarking |
+ | RFC | [RFC2544] |
+ | Allocation Date | March 1999 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+---------------+*/
+ MustIPv4Addr("198.18.0.0/15"),
+
+ /*+----------------------+----------------------------+
+ | Attribute | Value |
+ +----------------------+----------------------------+
+ | Address Block | 198.51.100.0/24 |
+ | Name | Documentation (TEST-NET-2) |
+ | RFC | [RFC5737] |
+ | Allocation Date | January 2010 |
+ | Termination Date | N/A |
+ | Source | False |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+----------------------------+*/
+ MustIPv4Addr("198.51.100.0/24"),
+
+ /*+----------------------+----------------------------+
+ | Attribute | Value |
+ +----------------------+----------------------------+
+ | Address Block | 203.0.113.0/24 |
+ | Name | Documentation (TEST-NET-3) |
+ | RFC | [RFC5737] |
+ | Allocation Date | January 2010 |
+ | Termination Date | N/A |
+ | Source | False |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+----------------------------+*/
+ MustIPv4Addr("203.0.113.0/24"),
+
+ /*+----------------------+----------------------+
+ | Attribute | Value |
+ +----------------------+----------------------+
+ | Address Block | 240.0.0.0/4 |
+ | Name | Reserved |
+ | RFC | [RFC1112], Section 4 |
+ | Allocation Date | August 1989 |
+ | Termination Date | N/A |
+ | Source | False |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | True |
+ +----------------------+----------------------+*/
+ MustIPv4Addr("240.0.0.0/4"),
+
+ /*+----------------------+----------------------+
+ | Attribute | Value |
+ +----------------------+----------------------+
+ | Address Block | 255.255.255.255/32 |
+ | Name | Limited Broadcast |
+ | RFC | [RFC0919], Section 7 |
+ | Allocation Date | October 1984 |
+ | Termination Date | N/A |
+ | Source | False |
+ | Destination | True |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+----------------------+*/
+ MustIPv4Addr("255.255.255.255/32"),
+
+ /*+----------------------+------------------+
+ | Attribute | Value |
+ +----------------------+------------------+
+ | Address Block | ::1/128 |
+ | Name | Loopback Address |
+ | RFC | [RFC4291] |
+ | Allocation Date | February 2006 |
+ | Termination Date | N/A |
+ | Source | False |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | True |
+ +----------------------+------------------+*/
+ MustIPv6Addr("::1/128"),
+
+ /*+----------------------+---------------------+
+ | Attribute | Value |
+ +----------------------+---------------------+
+ | Address Block | ::/128 |
+ | Name | Unspecified Address |
+ | RFC | [RFC4291] |
+ | Allocation Date | February 2006 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | True |
+ +----------------------+---------------------+*/
+ MustIPv6Addr("::/128"),
+
+ /*+----------------------+---------------------+
+ | Attribute | Value |
+ +----------------------+---------------------+
+ | Address Block | 64:ff9b::/96 |
+ | Name | IPv4-IPv6 Translat. |
+ | RFC | [RFC6052] |
+ | Allocation Date | October 2010 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | True |
+ | Reserved-by-Protocol | False |
+ +----------------------+---------------------+*/
+ MustIPv6Addr("64:ff9b::/96"),
+
+ /*+----------------------+---------------------+
+ | Attribute | Value |
+ +----------------------+---------------------+
+ | Address Block | ::ffff:0:0/96 |
+ | Name | IPv4-mapped Address |
+ | RFC | [RFC4291] |
+ | Allocation Date | February 2006 |
+ | Termination Date | N/A |
+ | Source | False |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | True |
+ +----------------------+---------------------+*/
+ MustIPv6Addr("::ffff:0:0/96"),
+
+ /*+----------------------+----------------------------+
+ | Attribute | Value |
+ +----------------------+----------------------------+
+ | Address Block | 100::/64 |
+ | Name | Discard-Only Address Block |
+ | RFC | [RFC6666] |
+ | Allocation Date | June 2012 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+----------------------------+*/
+ MustIPv6Addr("100::/64"),
+
+ /*+----------------------+---------------------------+
+ | Attribute | Value |
+ +----------------------+---------------------------+
+ | Address Block | 2001::/23 |
+ | Name | IETF Protocol Assignments |
+ | RFC | [RFC2928] |
+ | Allocation Date | September 2000 |
+ | Termination Date | N/A |
+ | Source | False[1] |
+ | Destination | False[1] |
+ | Forwardable | False[1] |
+ | Global | False[1] |
+ | Reserved-by-Protocol | False |
+ +----------------------+---------------------------+*/
+ // [1] Unless allowed by a more specific allocation.
+ MustIPv6Addr("2001::/16"),
+
+ /*+----------------------+----------------+
+ | Attribute | Value |
+ +----------------------+----------------+
+ | Address Block | 2001::/32 |
+ | Name | TEREDO |
+ | RFC | [RFC4380] |
+ | Allocation Date | January 2006 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+----------------+*/
+ // Covered by previous entry, included for completeness.
+ //
+ // MustIPv6Addr("2001::/16"),
+
+ /*+----------------------+----------------+
+ | Attribute | Value |
+ +----------------------+----------------+
+ | Address Block | 2001:2::/48 |
+ | Name | Benchmarking |
+ | RFC | [RFC5180] |
+ | Allocation Date | April 2008 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+----------------+*/
+ // Covered by previous entry, included for completeness.
+ //
+ // MustIPv6Addr("2001:2::/48"),
+
+ /*+----------------------+---------------+
+ | Attribute | Value |
+ +----------------------+---------------+
+ | Address Block | 2001:db8::/32 |
+ | Name | Documentation |
+ | RFC | [RFC3849] |
+ | Allocation Date | July 2004 |
+ | Termination Date | N/A |
+ | Source | False |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+---------------+*/
+ // Covered by previous entry, included for completeness.
+ //
+ // MustIPv6Addr("2001:db8::/32"),
+
+ /*+----------------------+--------------+
+ | Attribute | Value |
+ +----------------------+--------------+
+ | Address Block | 2001:10::/28 |
+ | Name | ORCHID |
+ | RFC | [RFC4843] |
+ | Allocation Date | March 2007 |
+ | Termination Date | March 2014 |
+ | Source | False |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+--------------+*/
+ // Covered by previous entry, included for completeness.
+ //
+ // MustIPv6Addr("2001:10::/28"),
+
+ /*+----------------------+---------------+
+ | Attribute | Value |
+ +----------------------+---------------+
+ | Address Block | 2002::/16 [2] |
+ | Name | 6to4 |
+ | RFC | [RFC3056] |
+ | Allocation Date | February 2001 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | N/A [2] |
+ | Reserved-by-Protocol | False |
+ +----------------------+---------------+*/
+ // [2] See [RFC3056] for details.
+ MustIPv6Addr("2002::/16"),
+
+ /*+----------------------+--------------+
+ | Attribute | Value |
+ +----------------------+--------------+
+ | Address Block | fc00::/7 |
+ | Name | Unique-Local |
+ | RFC | [RFC4193] |
+ | Allocation Date | October 2005 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+--------------+*/
+ MustIPv6Addr("fc00::/7"),
+
+ /*+----------------------+-----------------------+
+ | Attribute | Value |
+ +----------------------+-----------------------+
+ | Address Block | fe80::/10 |
+ | Name | Linked-Scoped Unicast |
+ | RFC | [RFC4291] |
+ | Allocation Date | February 2006 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | True |
+ +----------------------+-----------------------+*/
+ MustIPv6Addr("fe80::/10"),
+ },
+ 7335: {
+ // [RFC7335] IPv4 Service Continuity Prefix
+ MustIPv4Addr("192.0.0.0/29"), // [RFC7335], §6 IANA Considerations
+ },
+ ForwardingBlacklist: { // Pseudo-RFC
+ // Blacklist of non-forwardable IP blocks taken from RFC6890
+ //
+ // TODO: the attributes for forwardable should be
+ // searcahble and embedded in the main list of RFCs
+ // above.
+ MustIPv4Addr("0.0.0.0/8"),
+ MustIPv4Addr("127.0.0.0/8"),
+ MustIPv4Addr("169.254.0.0/16"),
+ MustIPv4Addr("192.0.0.0/24"),
+ MustIPv4Addr("192.0.2.0/24"),
+ MustIPv4Addr("198.51.100.0/24"),
+ MustIPv4Addr("203.0.113.0/24"),
+ MustIPv4Addr("240.0.0.0/4"),
+ MustIPv4Addr("255.255.255.255/32"),
+ MustIPv6Addr("::1/128"),
+ MustIPv6Addr("::/128"),
+ MustIPv6Addr("::ffff:0:0/96"),
+
+ // There is no way of expressing a whitelist per RFC2928
+ // atm without creating a negative mask, which I don't
+ // want to do atm.
+ //MustIPv6Addr("2001::/23"),
+
+ MustIPv6Addr("2001:db8::/32"),
+ MustIPv6Addr("2001:10::/28"),
+ MustIPv6Addr("fe80::/10"),
+ },
+ }
+}
+
+// VisitAllRFCs iterates over all known RFCs and calls the visitor
+func VisitAllRFCs(fn func(rfcNum uint, sockaddrs SockAddrs)) {
+ rfcNetMap := KnownRFCs()
+
+ // Blacklist of faux-RFCs. Don't show the world that we're abusing the
+ // RFC system in this library.
+ rfcBlacklist := map[uint]struct{}{
+ ForwardingBlacklist: {},
+ }
+
+ for rfcNum, sas := range rfcNetMap {
+ if _, found := rfcBlacklist[rfcNum]; !found {
+ fn(rfcNum, sas)
+ }
+ }
+}
--- /dev/null
+package sockaddr
+
+// RouteInterface specifies an interface for obtaining memoized route table and
+// network information from a given OS.
+type RouteInterface interface {
+ // GetDefaultInterfaceName returns the name of the interface that has a
+ // default route or an error and an empty string if a problem was
+ // encountered.
+ GetDefaultInterfaceName() (string, error)
+}
+
+// VisitCommands visits each command used by the platform-specific RouteInfo
+// implementation.
+func (ri routeInfo) VisitCommands(fn func(name string, cmd []string)) {
+ for k, v := range ri.cmds {
+ cmds := append([]string(nil), v...)
+ fn(k, cmds)
+ }
+}
--- /dev/null
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package sockaddr
+
+import "os/exec"
+
+var cmds map[string][]string = map[string][]string{
+ "route": {"/sbin/route", "-n", "get", "default"},
+}
+
+type routeInfo struct {
+ cmds map[string][]string
+}
+
+// NewRouteInfo returns a BSD-specific implementation of the RouteInfo
+// interface.
+func NewRouteInfo() (routeInfo, error) {
+ return routeInfo{
+ cmds: cmds,
+ }, nil
+}
+
+// GetDefaultInterfaceName returns the interface name attached to the default
+// route on the default interface.
+func (ri routeInfo) GetDefaultInterfaceName() (string, error) {
+ out, err := exec.Command(cmds["route"][0], cmds["route"][1:]...).Output()
+ if err != nil {
+ return "", err
+ }
+
+ var ifName string
+ if ifName, err = parseDefaultIfNameFromRoute(string(out)); err != nil {
+ return "", err
+ }
+ return ifName, nil
+}
--- /dev/null
+// +build android nacl plan9
+
+package sockaddr
+
+import "errors"
+
+// getDefaultIfName is the default interface function for unsupported platforms.
+func getDefaultIfName() (string, error) {
+ return "", errors.New("No default interface found (unsupported platform)")
+}
--- /dev/null
+package sockaddr
+
+import (
+ "errors"
+ "os/exec"
+)
+
+type routeInfo struct {
+ cmds map[string][]string
+}
+
+// NewRouteInfo returns a Linux-specific implementation of the RouteInfo
+// interface.
+func NewRouteInfo() (routeInfo, error) {
+ // CoreOS Container Linux moved ip to /usr/bin/ip, so look it up on
+ // $PATH and fallback to /sbin/ip on error.
+ path, _ := exec.LookPath("ip")
+ if path == "" {
+ path = "/sbin/ip"
+ }
+
+ return routeInfo{
+ cmds: map[string][]string{"ip": {path, "route"}},
+ }, nil
+}
+
+// GetDefaultInterfaceName returns the interface name attached to the default
+// route on the default interface.
+func (ri routeInfo) GetDefaultInterfaceName() (string, error) {
+ out, err := exec.Command(ri.cmds["ip"][0], ri.cmds["ip"][1:]...).Output()
+ if err != nil {
+ return "", err
+ }
+
+ var ifName string
+ if ifName, err = parseDefaultIfNameFromIPCmd(string(out)); err != nil {
+ return "", errors.New("No default interface found")
+ }
+ return ifName, nil
+}
--- /dev/null
+package sockaddr
+
+import (
+ "errors"
+ "os/exec"
+)
+
+var cmds map[string][]string = map[string][]string{
+ "route": {"/usr/sbin/route", "-n", "get", "default"},
+}
+
+type routeInfo struct {
+ cmds map[string][]string
+}
+
+// NewRouteInfo returns a BSD-specific implementation of the RouteInfo
+// interface.
+func NewRouteInfo() (routeInfo, error) {
+ return routeInfo{
+ cmds: cmds,
+ }, nil
+}
+
+// GetDefaultInterfaceName returns the interface name attached to the default
+// route on the default interface.
+func (ri routeInfo) GetDefaultInterfaceName() (string, error) {
+ out, err := exec.Command(cmds["route"][0], cmds["route"][1:]...).Output()
+ if err != nil {
+ return "", err
+ }
+
+ var ifName string
+ if ifName, err = parseDefaultIfNameFromRoute(string(out)); err != nil {
+ return "", errors.New("No default interface found")
+ }
+ return ifName, nil
+}
--- /dev/null
+package sockaddr
+
+import "os/exec"
+
+var cmds map[string][]string = map[string][]string{
+ "netstat": {"netstat", "-rn"},
+ "ipconfig": {"ipconfig"},
+}
+
+type routeInfo struct {
+ cmds map[string][]string
+}
+
+// NewRouteInfo returns a BSD-specific implementation of the RouteInfo
+// interface.
+func NewRouteInfo() (routeInfo, error) {
+ return routeInfo{
+ cmds: cmds,
+ }, nil
+}
+
+// GetDefaultInterfaceName returns the interface name attached to the default
+// route on the default interface.
+func (ri routeInfo) GetDefaultInterfaceName() (string, error) {
+ ifNameOut, err := exec.Command(cmds["netstat"][0], cmds["netstat"][1:]...).Output()
+ if err != nil {
+ return "", err
+ }
+
+ ipconfigOut, err := exec.Command(cmds["ipconfig"][0], cmds["ipconfig"][1:]...).Output()
+ if err != nil {
+ return "", err
+ }
+
+ ifName, err := parseDefaultIfNameWindows(string(ifNameOut), string(ipconfigOut))
+ if err != nil {
+ return "", err
+ }
+
+ return ifName, nil
+}
--- /dev/null
+package sockaddr
+
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+)
+
+type SockAddrType int
+type AttrName string
+
+const (
+ TypeUnknown SockAddrType = 0x0
+ TypeUnix = 0x1
+ TypeIPv4 = 0x2
+ TypeIPv6 = 0x4
+
+ // TypeIP is the union of TypeIPv4 and TypeIPv6
+ TypeIP = 0x6
+)
+
+type SockAddr interface {
+ // CmpRFC returns 0 if SockAddr exactly matches one of the matched RFC
+ // networks, -1 if the receiver is contained within the RFC network, or
+ // 1 if the address is not contained within the RFC.
+ CmpRFC(rfcNum uint, sa SockAddr) int
+
+ // Contains returns true if the SockAddr arg is contained within the
+ // receiver
+ Contains(SockAddr) bool
+
+ // Equal allows for the comparison of two SockAddrs
+ Equal(SockAddr) bool
+
+ DialPacketArgs() (string, string)
+ DialStreamArgs() (string, string)
+ ListenPacketArgs() (string, string)
+ ListenStreamArgs() (string, string)
+
+ // String returns the string representation of SockAddr
+ String() string
+
+ // Type returns the SockAddrType
+ Type() SockAddrType
+}
+
+// sockAddrAttrMap is a map of the SockAddr type-specific attributes.
+var sockAddrAttrMap map[AttrName]func(SockAddr) string
+var sockAddrAttrs []AttrName
+
+func init() {
+ sockAddrInit()
+}
+
+// New creates a new SockAddr from the string. The order in which New()
+// attempts to construct a SockAddr is: IPv4Addr, IPv6Addr, SockAddrUnix.
+//
+// NOTE: New() relies on the heuristic wherein if the path begins with either a
+// '.' or '/' character before creating a new UnixSock. For UNIX sockets that
+// are absolute paths or are nested within a sub-directory, this works as
+// expected, however if the UNIX socket is contained in the current working
+// directory, this will fail unless the path begins with "./"
+// (e.g. "./my-local-socket"). Calls directly to NewUnixSock() do not suffer
+// this limitation. Invalid IP addresses such as "256.0.0.0/-1" will run afoul
+// of this heuristic and be assumed to be a valid UNIX socket path (which they
+// are, but it is probably not what you want and you won't realize it until you
+// stat(2) the file system to discover it doesn't exist).
+func NewSockAddr(s string) (SockAddr, error) {
+ ipv4Addr, err := NewIPv4Addr(s)
+ if err == nil {
+ return ipv4Addr, nil
+ }
+
+ ipv6Addr, err := NewIPv6Addr(s)
+ if err == nil {
+ return ipv6Addr, nil
+ }
+
+ // Check to make sure the string begins with either a '.' or '/', or
+ // contains a '/'.
+ if len(s) > 1 && (strings.IndexAny(s[0:1], "./") != -1 || strings.IndexByte(s, '/') != -1) {
+ unixSock, err := NewUnixSock(s)
+ if err == nil {
+ return unixSock, nil
+ }
+ }
+
+ return nil, fmt.Errorf("Unable to convert %q to an IPv4 or IPv6 address, or a UNIX Socket", s)
+}
+
+// ToIPAddr returns an IPAddr type or nil if the type conversion fails.
+func ToIPAddr(sa SockAddr) *IPAddr {
+ ipa, ok := sa.(IPAddr)
+ if !ok {
+ return nil
+ }
+ return &ipa
+}
+
+// ToIPv4Addr returns an IPv4Addr type or nil if the type conversion fails.
+func ToIPv4Addr(sa SockAddr) *IPv4Addr {
+ switch v := sa.(type) {
+ case IPv4Addr:
+ return &v
+ default:
+ return nil
+ }
+}
+
+// ToIPv6Addr returns an IPv6Addr type or nil if the type conversion fails.
+func ToIPv6Addr(sa SockAddr) *IPv6Addr {
+ switch v := sa.(type) {
+ case IPv6Addr:
+ return &v
+ default:
+ return nil
+ }
+}
+
+// ToUnixSock returns a UnixSock type or nil if the type conversion fails.
+func ToUnixSock(sa SockAddr) *UnixSock {
+ switch v := sa.(type) {
+ case UnixSock:
+ return &v
+ default:
+ return nil
+ }
+}
+
+// SockAddrAttr returns a string representation of an attribute for the given
+// SockAddr.
+func SockAddrAttr(sa SockAddr, selector AttrName) string {
+ fn, found := sockAddrAttrMap[selector]
+ if !found {
+ return ""
+ }
+
+ return fn(sa)
+}
+
+// String() for SockAddrType returns a string representation of the
+// SockAddrType (e.g. "IPv4", "IPv6", "UNIX", "IP", or "unknown").
+func (sat SockAddrType) String() string {
+ switch sat {
+ case TypeIPv4:
+ return "IPv4"
+ case TypeIPv6:
+ return "IPv6"
+ // There is no concrete "IP" type. Leaving here as a reminder.
+ // case TypeIP:
+ // return "IP"
+ case TypeUnix:
+ return "UNIX"
+ default:
+ panic("unsupported type")
+ }
+}
+
+// sockAddrInit is called once at init()
+func sockAddrInit() {
+ sockAddrAttrs = []AttrName{
+ "type", // type should be first
+ "string",
+ }
+
+ sockAddrAttrMap = map[AttrName]func(sa SockAddr) string{
+ "string": func(sa SockAddr) string {
+ return sa.String()
+ },
+ "type": func(sa SockAddr) string {
+ return sa.Type().String()
+ },
+ }
+}
+
+// UnixSockAttrs returns a list of attributes supported by the UnixSock type
+func SockAddrAttrs() []AttrName {
+ return sockAddrAttrs
+}
+
+// Although this is pretty trivial to do in a program, having the logic here is
+// useful all around. Note that this marshals into a *string* -- the underlying
+// string representation of the sockaddr. If you then unmarshal into this type
+// in Go, all will work as expected, but externally you can take what comes out
+// and use the string value directly.
+type SockAddrMarshaler struct {
+ SockAddr
+}
+
+func (s *SockAddrMarshaler) MarshalJSON() ([]byte, error) {
+ return json.Marshal(s.SockAddr.String())
+}
+
+func (s *SockAddrMarshaler) UnmarshalJSON(in []byte) error {
+ var str string
+ err := json.Unmarshal(in, &str)
+ if err != nil {
+ return err
+ }
+ sa, err := NewSockAddr(str)
+ if err != nil {
+ return err
+ }
+ s.SockAddr = sa
+ return nil
+}
--- /dev/null
+package sockaddr
+
+import (
+ "bytes"
+ "sort"
+)
+
+// SockAddrs is a slice of SockAddrs
+type SockAddrs []SockAddr
+
+func (s SockAddrs) Len() int { return len(s) }
+func (s SockAddrs) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// CmpAddrFunc is the function signature that must be met to be used in the
+// OrderedAddrBy multiAddrSorter
+type CmpAddrFunc func(p1, p2 *SockAddr) int
+
+// multiAddrSorter implements the Sort interface, sorting the SockAddrs within.
+type multiAddrSorter struct {
+ addrs SockAddrs
+ cmp []CmpAddrFunc
+}
+
+// Sort sorts the argument slice according to the Cmp functions passed to
+// OrderedAddrBy.
+func (ms *multiAddrSorter) Sort(sockAddrs SockAddrs) {
+ ms.addrs = sockAddrs
+ sort.Sort(ms)
+}
+
+// OrderedAddrBy sorts SockAddr by the list of sort function pointers.
+func OrderedAddrBy(cmpFuncs ...CmpAddrFunc) *multiAddrSorter {
+ return &multiAddrSorter{
+ cmp: cmpFuncs,
+ }
+}
+
+// Len is part of sort.Interface.
+func (ms *multiAddrSorter) Len() int {
+ return len(ms.addrs)
+}
+
+// Less is part of sort.Interface. It is implemented by looping along the
+// Cmp() functions until it finds a comparison that is either less than,
+// equal to, or greater than.
+func (ms *multiAddrSorter) Less(i, j int) bool {
+ p, q := &ms.addrs[i], &ms.addrs[j]
+ // Try all but the last comparison.
+ var k int
+ for k = 0; k < len(ms.cmp)-1; k++ {
+ cmp := ms.cmp[k]
+ x := cmp(p, q)
+ switch x {
+ case -1:
+ // p < q, so we have a decision.
+ return true
+ case 1:
+ // p > q, so we have a decision.
+ return false
+ }
+ // p == q; try the next comparison.
+ }
+ // All comparisons to here said "equal", so just return whatever the
+ // final comparison reports.
+ switch ms.cmp[k](p, q) {
+ case -1:
+ return true
+ case 1:
+ return false
+ default:
+ // Still a tie! Now what?
+ return false
+ }
+}
+
+// Swap is part of sort.Interface.
+func (ms *multiAddrSorter) Swap(i, j int) {
+ ms.addrs[i], ms.addrs[j] = ms.addrs[j], ms.addrs[i]
+}
+
+const (
+ // NOTE (sean@): These constants are here for code readability only and
+ // are sprucing up the code for readability purposes. Some of the
+ // Cmp*() variants have confusing logic (especially when dealing with
+ // mixed-type comparisons) and this, I think, has made it easier to grok
+ // the code faster.
+ sortReceiverBeforeArg = -1
+ sortDeferDecision = 0
+ sortArgBeforeReceiver = 1
+)
+
+// AscAddress is a sorting function to sort SockAddrs by their respective
+// address type. Non-equal types are deferred in the sort.
+func AscAddress(p1Ptr, p2Ptr *SockAddr) int {
+ p1 := *p1Ptr
+ p2 := *p2Ptr
+
+ switch v := p1.(type) {
+ case IPv4Addr:
+ return v.CmpAddress(p2)
+ case IPv6Addr:
+ return v.CmpAddress(p2)
+ case UnixSock:
+ return v.CmpAddress(p2)
+ default:
+ return sortDeferDecision
+ }
+}
+
+// AscPort is a sorting function to sort SockAddrs by their respective address
+// type. Non-equal types are deferred in the sort.
+func AscPort(p1Ptr, p2Ptr *SockAddr) int {
+ p1 := *p1Ptr
+ p2 := *p2Ptr
+
+ switch v := p1.(type) {
+ case IPv4Addr:
+ return v.CmpPort(p2)
+ case IPv6Addr:
+ return v.CmpPort(p2)
+ default:
+ return sortDeferDecision
+ }
+}
+
+// AscPrivate is a sorting function to sort "more secure" private values before
+// "more public" values. Both IPv4 and IPv6 are compared against RFC6890
+// (RFC6890 includes, and is not limited to, RFC1918 and RFC6598 for IPv4, and
+// IPv6 includes RFC4193).
+func AscPrivate(p1Ptr, p2Ptr *SockAddr) int {
+ p1 := *p1Ptr
+ p2 := *p2Ptr
+
+ switch v := p1.(type) {
+ case IPv4Addr, IPv6Addr:
+ return v.CmpRFC(6890, p2)
+ default:
+ return sortDeferDecision
+ }
+}
+
+// AscNetworkSize is a sorting function to sort SockAddrs based on their network
+// size. Non-equal types are deferred in the sort.
+func AscNetworkSize(p1Ptr, p2Ptr *SockAddr) int {
+ p1 := *p1Ptr
+ p2 := *p2Ptr
+ p1Type := p1.Type()
+ p2Type := p2.Type()
+
+ // Network size operations on non-IP types make no sense
+ if p1Type != p2Type && p1Type != TypeIP {
+ return sortDeferDecision
+ }
+
+ ipA := p1.(IPAddr)
+ ipB := p2.(IPAddr)
+
+ return bytes.Compare([]byte(*ipA.NetIPMask()), []byte(*ipB.NetIPMask()))
+}
+
+// AscType is a sorting function to sort "more secure" types before
+// "less-secure" types.
+func AscType(p1Ptr, p2Ptr *SockAddr) int {
+ p1 := *p1Ptr
+ p2 := *p2Ptr
+ p1Type := p1.Type()
+ p2Type := p2.Type()
+ switch {
+ case p1Type < p2Type:
+ return sortReceiverBeforeArg
+ case p1Type == p2Type:
+ return sortDeferDecision
+ case p1Type > p2Type:
+ return sortArgBeforeReceiver
+ default:
+ return sortDeferDecision
+ }
+}
+
+// FilterByType returns two lists: a list of matched and unmatched SockAddrs
+func (sas SockAddrs) FilterByType(type_ SockAddrType) (matched, excluded SockAddrs) {
+ matched = make(SockAddrs, 0, len(sas))
+ excluded = make(SockAddrs, 0, len(sas))
+
+ for _, sa := range sas {
+ if sa.Type()&type_ != 0 {
+ matched = append(matched, sa)
+ } else {
+ excluded = append(excluded, sa)
+ }
+ }
+ return matched, excluded
+}
--- /dev/null
+package sockaddr
+
+import (
+ "fmt"
+ "strings"
+)
+
+type UnixSock struct {
+ SockAddr
+ path string
+}
+type UnixSocks []*UnixSock
+
+// unixAttrMap is a map of the UnixSockAddr type-specific attributes.
+var unixAttrMap map[AttrName]func(UnixSock) string
+var unixAttrs []AttrName
+
+func init() {
+ unixAttrInit()
+}
+
+// NewUnixSock creates an UnixSock from a string path. String can be in the
+// form of either URI-based string (e.g. `file:///etc/passwd`), an absolute
+// path (e.g. `/etc/passwd`), or a relative path (e.g. `./foo`).
+func NewUnixSock(s string) (ret UnixSock, err error) {
+ ret.path = s
+ return ret, nil
+}
+
+// CmpAddress follows the Cmp() standard protocol and returns:
+//
+// - -1 If the receiver should sort first because its name lexically sorts before arg
+// - 0 if the SockAddr arg is not a UnixSock, or is a UnixSock with the same path.
+// - 1 If the argument should sort first.
+func (us UnixSock) CmpAddress(sa SockAddr) int {
+ usb, ok := sa.(UnixSock)
+ if !ok {
+ return sortDeferDecision
+ }
+
+ return strings.Compare(us.Path(), usb.Path())
+}
+
+// DialPacketArgs returns the arguments required to be passed to net.DialUnix()
+// with the `unixgram` network type.
+func (us UnixSock) DialPacketArgs() (network, dialArgs string) {
+ return "unixgram", us.path
+}
+
+// DialStreamArgs returns the arguments required to be passed to net.DialUnix()
+// with the `unix` network type.
+func (us UnixSock) DialStreamArgs() (network, dialArgs string) {
+ return "unix", us.path
+}
+
+// Equal returns true if a SockAddr is equal to the receiving UnixSock.
+func (us UnixSock) Equal(sa SockAddr) bool {
+ usb, ok := sa.(UnixSock)
+ if !ok {
+ return false
+ }
+
+ if us.Path() != usb.Path() {
+ return false
+ }
+
+ return true
+}
+
+// ListenPacketArgs returns the arguments required to be passed to
+// net.ListenUnixgram() with the `unixgram` network type.
+func (us UnixSock) ListenPacketArgs() (network, dialArgs string) {
+ return "unixgram", us.path
+}
+
+// ListenStreamArgs returns the arguments required to be passed to
+// net.ListenUnix() with the `unix` network type.
+func (us UnixSock) ListenStreamArgs() (network, dialArgs string) {
+ return "unix", us.path
+}
+
+// MustUnixSock is a helper method that must return an UnixSock or panic on
+// invalid input.
+func MustUnixSock(addr string) UnixSock {
+ us, err := NewUnixSock(addr)
+ if err != nil {
+ panic(fmt.Sprintf("Unable to create a UnixSock from %+q: %v", addr, err))
+ }
+ return us
+}
+
+// Path returns the given path of the UnixSock
+func (us UnixSock) Path() string {
+ return us.path
+}
+
+// String returns the path of the UnixSock
+func (us UnixSock) String() string {
+ return fmt.Sprintf("%+q", us.path)
+}
+
+// Type is used as a type switch and returns TypeUnix
+func (UnixSock) Type() SockAddrType {
+ return TypeUnix
+}
+
+// UnixSockAttrs returns a list of attributes supported by the UnixSockAddr type
+func UnixSockAttrs() []AttrName {
+ return unixAttrs
+}
+
+// UnixSockAttr returns a string representation of an attribute for the given
+// UnixSock.
+func UnixSockAttr(us UnixSock, attrName AttrName) string {
+ fn, found := unixAttrMap[attrName]
+ if !found {
+ return ""
+ }
+
+ return fn(us)
+}
+
+// unixAttrInit is called once at init()
+func unixAttrInit() {
+ // Sorted for human readability
+ unixAttrs = []AttrName{
+ "path",
+ }
+
+ unixAttrMap = map[AttrName]func(us UnixSock) string{
+ "path": func(us UnixSock) string {
+ return us.Path()
+ },
+ }
+}
--- /dev/null
+Mozilla Public License, version 2.0
+
+1. Definitions
+
+1.1. "Contributor"
+
+ means each individual or legal entity that creates, contributes to the
+ creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+
+ means the combination of the Contributions of others (if any) used by a
+ Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+
+ means Source Code Form to which the initial Contributor has attached the
+ notice in Exhibit A, the Executable Form of such Source Code Form, and
+ Modifications of such Source Code Form, in each case including portions
+ thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ a. that the initial Contributor has attached the notice described in
+ Exhibit B to the Covered Software; or
+
+ b. that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the terms of
+ a Secondary License.
+
+1.6. "Executable Form"
+
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+
+ means a work that combines Covered Software with other material, in a
+ separate file or files, that is not Covered Software.
+
+1.8. "License"
+
+ means this document.
+
+1.9. "Licensable"
+
+ means having the right to grant, to the maximum extent possible, whether
+ at the time of the initial grant or subsequently, any and all of the
+ rights conveyed by this License.
+
+1.10. "Modifications"
+
+ means any of the following:
+
+ a. any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered Software; or
+
+ b. any new file in Source Code Form that contains any Covered Software.
+
+1.11. "Patent Claims" of a Contributor
+
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the License,
+ by the making, using, selling, offering for sale, having made, import,
+ or transfer of either its Contributions or its Contributor Version.
+
+1.12. "Secondary License"
+
+ means either the GNU General Public License, Version 2.0, the GNU Lesser
+ General Public License, Version 2.1, the GNU Affero General Public
+ License, Version 3.0, or any later versions of those licenses.
+
+1.13. "Source Code Form"
+
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that controls, is
+ controlled by, or is under common control with You. For purposes of this
+ definition, "control" means (a) the power, direct or indirect, to cause
+ the direction or management of such entity, whether by contract or
+ otherwise, or (b) ownership of more than fifty percent (50%) of the
+ outstanding shares or beneficial ownership of such entity.
+
+
+2. License Grants and Conditions
+
+2.1. Grants
+
+ Each Contributor hereby grants You a world-wide, royalty-free,
+ non-exclusive license:
+
+ a. under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+ b. under Patent Claims of such Contributor to make, use, sell, offer for
+ sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+ The licenses granted in Section 2.1 with respect to any Contribution
+ become effective for each Contribution on the date the Contributor first
+ distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+ The licenses granted in this Section 2 are the only rights granted under
+ this License. No additional rights or licenses will be implied from the
+ distribution or licensing of Covered Software under this License.
+ Notwithstanding Section 2.1(b) above, no patent license is granted by a
+ Contributor:
+
+ a. for any code that a Contributor has removed from Covered Software; or
+
+ b. for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+ c. under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+ This License does not grant any rights in the trademarks, service marks,
+ or logos of any Contributor (except as may be necessary to comply with
+ the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+ No Contributor makes additional grants as a result of Your choice to
+ distribute the Covered Software under a subsequent version of this
+ License (see Section 10.2) or under the terms of a Secondary License (if
+ permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+ Each Contributor represents that the Contributor believes its
+ Contributions are its original creation(s) or it has sufficient rights to
+ grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+ This License is not intended to limit any rights You have under
+ applicable copyright doctrines of fair use, fair dealing, or other
+ equivalents.
+
+2.7. Conditions
+
+ Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
+ Section 2.1.
+
+
+3. Responsibilities
+
+3.1. Distribution of Source Form
+
+ All distribution of Covered Software in Source Code Form, including any
+ Modifications that You create or to which You contribute, must be under
+ the terms of this License. You must inform recipients that the Source
+ Code Form of the Covered Software is governed by the terms of this
+ License, and how they can obtain a copy of this License. You may not
+ attempt to alter or restrict the recipients' rights in the Source Code
+ Form.
+
+3.2. Distribution of Executable Form
+
+ If You distribute Covered Software in Executable Form then:
+
+ a. such Covered Software must also be made available in Source Code Form,
+ as described in Section 3.1, and You must inform recipients of the
+ Executable Form how they can obtain a copy of such Source Code Form by
+ reasonable means in a timely manner, at a charge no more than the cost
+ of distribution to the recipient; and
+
+ b. You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter the
+ recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+ You may create and distribute a Larger Work under terms of Your choice,
+ provided that You also comply with the requirements of this License for
+ the Covered Software. If the Larger Work is a combination of Covered
+ Software with a work governed by one or more Secondary Licenses, and the
+ Covered Software is not Incompatible With Secondary Licenses, this
+ License permits You to additionally distribute such Covered Software
+ under the terms of such Secondary License(s), so that the recipient of
+ the Larger Work may, at their option, further distribute the Covered
+ Software under the terms of either this License or such Secondary
+ License(s).
+
+3.4. Notices
+
+ You may not remove or alter the substance of any license notices
+ (including copyright notices, patent notices, disclaimers of warranty, or
+ limitations of liability) contained within the Source Code Form of the
+ Covered Software, except that You may alter any license notices to the
+ extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+ You may choose to offer, and to charge a fee for, warranty, support,
+ indemnity or liability obligations to one or more recipients of Covered
+ Software. However, You may do so only on Your own behalf, and not on
+ behalf of any Contributor. You must make it absolutely clear that any
+ such warranty, support, indemnity, or liability obligation is offered by
+ You alone, and You hereby agree to indemnify every Contributor for any
+ liability incurred by such Contributor as a result of warranty, support,
+ indemnity or liability terms You offer. You may include additional
+ disclaimers of warranty and limitations of liability specific to any
+ jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+
+ If it is impossible for You to comply with any of the terms of this License
+ with respect to some or all of the Covered Software due to statute,
+ judicial order, or regulation then You must: (a) comply with the terms of
+ this License to the maximum extent possible; and (b) describe the
+ limitations and the code they affect. Such description must be placed in a
+ text file included with all distributions of the Covered Software under
+ this License. Except to the extent prohibited by statute or regulation,
+ such description must be sufficiently detailed for a recipient of ordinary
+ skill to be able to understand it.
+
+5. Termination
+
+5.1. The rights granted under this License will terminate automatically if You
+ fail to comply with any of its terms. However, if You become compliant,
+ then the rights granted under this License from a particular Contributor
+ are reinstated (a) provisionally, unless and until such Contributor
+ explicitly and finally terminates Your grants, and (b) on an ongoing
+ basis, if such Contributor fails to notify You of the non-compliance by
+ some reasonable means prior to 60 days after You have come back into
+ compliance. Moreover, Your grants from a particular Contributor are
+ reinstated on an ongoing basis if such Contributor notifies You of the
+ non-compliance by some reasonable means, this is the first time You have
+ received notice of non-compliance with this License from such
+ Contributor, and You become compliant prior to 30 days after Your receipt
+ of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+ infringement claim (excluding declaratory judgment actions,
+ counter-claims, and cross-claims) alleging that a Contributor Version
+ directly or indirectly infringes any patent, then the rights granted to
+ You by any and all Contributors for the Covered Software under Section
+ 2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
+ license agreements (excluding distributors and resellers) which have been
+ validly granted by You or Your distributors under this License prior to
+ termination shall survive termination.
+
+6. Disclaimer of Warranty
+
+ Covered Software is provided under this License on an "as is" basis,
+ without warranty of any kind, either expressed, implied, or statutory,
+ including, without limitation, warranties that the Covered Software is free
+ of defects, merchantable, fit for a particular purpose or non-infringing.
+ The entire risk as to the quality and performance of the Covered Software
+ is with You. Should any Covered Software prove defective in any respect,
+ You (not any Contributor) assume the cost of any necessary servicing,
+ repair, or correction. This disclaimer of warranty constitutes an essential
+ part of this License. No use of any Covered Software is authorized under
+ this License except under this disclaimer.
+
+7. Limitation of Liability
+
+ Under no circumstances and under no legal theory, whether tort (including
+ negligence), contract, or otherwise, shall any Contributor, or anyone who
+ distributes Covered Software as permitted above, be liable to You for any
+ direct, indirect, special, incidental, or consequential damages of any
+ character including, without limitation, damages for lost profits, loss of
+ goodwill, work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses, even if such party shall have been
+ informed of the possibility of such damages. This limitation of liability
+ shall not apply to liability for death or personal injury resulting from
+ such party's negligence to the extent applicable law prohibits such
+ limitation. Some jurisdictions do not allow the exclusion or limitation of
+ incidental or consequential damages, so this exclusion and limitation may
+ not apply to You.
+
+8. Litigation
+
+ Any litigation relating to this License may be brought only in the courts
+ of a jurisdiction where the defendant maintains its principal place of
+ business and such litigation shall be governed by laws of that
+ jurisdiction, without reference to its conflict-of-law provisions. Nothing
+ in this Section shall prevent a party's ability to bring cross-claims or
+ counter-claims.
+
+9. Miscellaneous
+
+ This License represents the complete agreement concerning the subject
+ matter hereof. If any provision of this License is held to be
+ unenforceable, such provision shall be reformed only to the extent
+ necessary to make it enforceable. Any law or regulation which provides that
+ the language of a contract shall be construed against the drafter shall not
+ be used to construe this License against a Contributor.
+
+
+10. Versions of the License
+
+10.1. New Versions
+
+ Mozilla Foundation is the license steward. Except as provided in Section
+ 10.3, no one other than the license steward has the right to modify or
+ publish new versions of this License. Each version will be given a
+ distinguishing version number.
+
+10.2. Effect of New Versions
+
+ You may distribute the Covered Software under the terms of the version
+ of the License under which You originally received the Covered Software,
+ or under the terms of any subsequent version published by the license
+ steward.
+
+10.3. Modified Versions
+
+ If you create software not governed by this License, and you want to
+ create a new license for such software, you may create and use a
+ modified version of this License if you rename the license and remove
+ any references to the name of the license steward (except to note that
+ such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+ Licenses If You choose to distribute Source Code Form that is
+ Incompatible With Secondary Licenses under the terms of this version of
+ the License, the notice described in Exhibit B of this License must be
+ attached.
+
+Exhibit A - Source Code Form License Notice
+
+ This Source Code Form is subject to the
+ terms of the Mozilla Public License, v.
+ 2.0. If a copy of the MPL was not
+ distributed with this file, You can
+ obtain one at
+ http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular file,
+then You may include the notice in a location (such as a LICENSE file in a
+relevant directory) where a recipient would be likely to look for such a
+notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+
+ This Source Code Form is "Incompatible
+ With Secondary Licenses", as defined by
+ the Mozilla Public License, v. 2.0.
--- /dev/null
+package simplelru
+
+import (
+ "container/list"
+ "errors"
+)
+
+// EvictCallback is used to get a callback when a cache entry is evicted
+type EvictCallback func(key interface{}, value interface{})
+
+// LRU implements a non-thread safe fixed size LRU cache
+type LRU struct {
+ size int
+ evictList *list.List
+ items map[interface{}]*list.Element
+ onEvict EvictCallback
+}
+
+// entry is used to hold a value in the evictList
+type entry struct {
+ key interface{}
+ value interface{}
+}
+
+// NewLRU constructs an LRU of the given size
+func NewLRU(size int, onEvict EvictCallback) (*LRU, error) {
+ if size <= 0 {
+ return nil, errors.New("Must provide a positive size")
+ }
+ c := &LRU{
+ size: size,
+ evictList: list.New(),
+ items: make(map[interface{}]*list.Element),
+ onEvict: onEvict,
+ }
+ return c, nil
+}
+
+// Purge is used to completely clear the cache
+func (c *LRU) Purge() {
+ for k, v := range c.items {
+ if c.onEvict != nil {
+ c.onEvict(k, v.Value.(*entry).value)
+ }
+ delete(c.items, k)
+ }
+ c.evictList.Init()
+}
+
+// Add adds a value to the cache. Returns true if an eviction occurred.
+func (c *LRU) Add(key, value interface{}) bool {
+ // Check for existing item
+ if ent, ok := c.items[key]; ok {
+ c.evictList.MoveToFront(ent)
+ ent.Value.(*entry).value = value
+ return false
+ }
+
+ // Add new item
+ ent := &entry{key, value}
+ entry := c.evictList.PushFront(ent)
+ c.items[key] = entry
+
+ evict := c.evictList.Len() > c.size
+ // Verify size not exceeded
+ if evict {
+ c.removeOldest()
+ }
+ return evict
+}
+
+// Get looks up a key's value from the cache.
+func (c *LRU) Get(key interface{}) (value interface{}, ok bool) {
+ if ent, ok := c.items[key]; ok {
+ c.evictList.MoveToFront(ent)
+ return ent.Value.(*entry).value, true
+ }
+ return
+}
+
+// Check if a key is in the cache, without updating the recent-ness
+// or deleting it for being stale.
+func (c *LRU) Contains(key interface{}) (ok bool) {
+ _, ok = c.items[key]
+ return ok
+}
+
+// Returns the key value (or undefined if not found) without updating
+// the "recently used"-ness of the key.
+func (c *LRU) Peek(key interface{}) (value interface{}, ok bool) {
+ if ent, ok := c.items[key]; ok {
+ return ent.Value.(*entry).value, true
+ }
+ return nil, ok
+}
+
+// Remove removes the provided key from the cache, returning if the
+// key was contained.
+func (c *LRU) Remove(key interface{}) bool {
+ if ent, ok := c.items[key]; ok {
+ c.removeElement(ent)
+ return true
+ }
+ return false
+}
+
+// RemoveOldest removes the oldest item from the cache.
+func (c *LRU) RemoveOldest() (interface{}, interface{}, bool) {
+ ent := c.evictList.Back()
+ if ent != nil {
+ c.removeElement(ent)
+ kv := ent.Value.(*entry)
+ return kv.key, kv.value, true
+ }
+ return nil, nil, false
+}
+
+// GetOldest returns the oldest entry
+func (c *LRU) GetOldest() (interface{}, interface{}, bool) {
+ ent := c.evictList.Back()
+ if ent != nil {
+ kv := ent.Value.(*entry)
+ return kv.key, kv.value, true
+ }
+ return nil, nil, false
+}
+
+// Keys returns a slice of the keys in the cache, from oldest to newest.
+func (c *LRU) Keys() []interface{} {
+ keys := make([]interface{}, len(c.items))
+ i := 0
+ for ent := c.evictList.Back(); ent != nil; ent = ent.Prev() {
+ keys[i] = ent.Value.(*entry).key
+ i++
+ }
+ return keys
+}
+
+// Len returns the number of items in the cache.
+func (c *LRU) Len() int {
+ return c.evictList.Len()
+}
+
+// removeOldest removes the oldest item from the cache.
+func (c *LRU) removeOldest() {
+ ent := c.evictList.Back()
+ if ent != nil {
+ c.removeElement(ent)
+ }
+}
+
+// removeElement is used to remove a given list element from the cache
+func (c *LRU) removeElement(e *list.Element) {
+ c.evictList.Remove(e)
+ kv := e.Value.(*entry)
+ delete(c.items, kv.key)
+ if c.onEvict != nil {
+ c.onEvict(kv.key, kv.value)
+ }
+}
--- /dev/null
+Mozilla Public License, version 2.0
+
+1. Definitions
+
+1.1. “Contributor”
+
+ means each individual or legal entity that creates, contributes to the
+ creation of, or owns Covered Software.
+
+1.2. “Contributor Version”
+
+ means the combination of the Contributions of others (if any) used by a
+ Contributor and that particular Contributor’s Contribution.
+
+1.3. “Contribution”
+
+ means Covered Software of a particular Contributor.
+
+1.4. “Covered Software”
+
+ means Source Code Form to which the initial Contributor has attached the
+ notice in Exhibit A, the Executable Form of such Source Code Form, and
+ Modifications of such Source Code Form, in each case including portions
+ thereof.
+
+1.5. “Incompatible With Secondary Licenses”
+ means
+
+ a. that the initial Contributor has attached the notice described in
+ Exhibit B to the Covered Software; or
+
+ b. that the Covered Software was made available under the terms of version
+ 1.1 or earlier of the License, but not also under the terms of a
+ Secondary License.
+
+1.6. “Executable Form”
+
+ means any form of the work other than Source Code Form.
+
+1.7. “Larger Work”
+
+ means a work that combines Covered Software with other material, in a separate
+ file or files, that is not Covered Software.
+
+1.8. “License”
+
+ means this document.
+
+1.9. “Licensable”
+
+ means having the right to grant, to the maximum extent possible, whether at the
+ time of the initial grant or subsequently, any and all of the rights conveyed by
+ this License.
+
+1.10. “Modifications”
+
+ means any of the following:
+
+ a. any file in Source Code Form that results from an addition to, deletion
+ from, or modification of the contents of Covered Software; or
+
+ b. any new file in Source Code Form that contains any Covered Software.
+
+1.11. “Patent Claims” of a Contributor
+
+ means any patent claim(s), including without limitation, method, process,
+ and apparatus claims, in any patent Licensable by such Contributor that
+ would be infringed, but for the grant of the License, by the making,
+ using, selling, offering for sale, having made, import, or transfer of
+ either its Contributions or its Contributor Version.
+
+1.12. “Secondary License”
+
+ means either the GNU General Public License, Version 2.0, the GNU Lesser
+ General Public License, Version 2.1, the GNU Affero General Public
+ License, Version 3.0, or any later versions of those licenses.
+
+1.13. “Source Code Form”
+
+ means the form of the work preferred for making modifications.
+
+1.14. “You” (or “Your”)
+
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, “You” includes any entity that controls, is
+ controlled by, or is under common control with You. For purposes of this
+ definition, “control” means (a) the power, direct or indirect, to cause
+ the direction or management of such entity, whether by contract or
+ otherwise, or (b) ownership of more than fifty percent (50%) of the
+ outstanding shares or beneficial ownership of such entity.
+
+
+2. License Grants and Conditions
+
+2.1. Grants
+
+ Each Contributor hereby grants You a world-wide, royalty-free,
+ non-exclusive license:
+
+ a. under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or as
+ part of a Larger Work; and
+
+ b. under Patent Claims of such Contributor to make, use, sell, offer for
+ sale, have made, import, and otherwise transfer either its Contributions
+ or its Contributor Version.
+
+2.2. Effective Date
+
+ The licenses granted in Section 2.1 with respect to any Contribution become
+ effective for each Contribution on the date the Contributor first distributes
+ such Contribution.
+
+2.3. Limitations on Grant Scope
+
+ The licenses granted in this Section 2 are the only rights granted under this
+ License. No additional rights or licenses will be implied from the distribution
+ or licensing of Covered Software under this License. Notwithstanding Section
+ 2.1(b) above, no patent license is granted by a Contributor:
+
+ a. for any code that a Contributor has removed from Covered Software; or
+
+ b. for infringements caused by: (i) Your and any other third party’s
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+ c. under Patent Claims infringed by Covered Software in the absence of its
+ Contributions.
+
+ This License does not grant any rights in the trademarks, service marks, or
+ logos of any Contributor (except as may be necessary to comply with the
+ notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+ No Contributor makes additional grants as a result of Your choice to
+ distribute the Covered Software under a subsequent version of this License
+ (see Section 10.2) or under the terms of a Secondary License (if permitted
+ under the terms of Section 3.3).
+
+2.5. Representation
+
+ Each Contributor represents that the Contributor believes its Contributions
+ are its original creation(s) or it has sufficient rights to grant the
+ rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+ This License is not intended to limit any rights You have under applicable
+ copyright doctrines of fair use, fair dealing, or other equivalents.
+
+2.7. Conditions
+
+ Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
+ Section 2.1.
+
+
+3. Responsibilities
+
+3.1. Distribution of Source Form
+
+ All distribution of Covered Software in Source Code Form, including any
+ Modifications that You create or to which You contribute, must be under the
+ terms of this License. You must inform recipients that the Source Code Form
+ of the Covered Software is governed by the terms of this License, and how
+ they can obtain a copy of this License. You may not attempt to alter or
+ restrict the recipients’ rights in the Source Code Form.
+
+3.2. Distribution of Executable Form
+
+ If You distribute Covered Software in Executable Form then:
+
+ a. such Covered Software must also be made available in Source Code Form,
+ as described in Section 3.1, and You must inform recipients of the
+ Executable Form how they can obtain a copy of such Source Code Form by
+ reasonable means in a timely manner, at a charge no more than the cost
+ of distribution to the recipient; and
+
+ b. You may distribute such Executable Form under the terms of this License,
+ or sublicense it under different terms, provided that the license for
+ the Executable Form does not attempt to limit or alter the recipients’
+ rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+ You may create and distribute a Larger Work under terms of Your choice,
+ provided that You also comply with the requirements of this License for the
+ Covered Software. If the Larger Work is a combination of Covered Software
+ with a work governed by one or more Secondary Licenses, and the Covered
+ Software is not Incompatible With Secondary Licenses, this License permits
+ You to additionally distribute such Covered Software under the terms of
+ such Secondary License(s), so that the recipient of the Larger Work may, at
+ their option, further distribute the Covered Software under the terms of
+ either this License or such Secondary License(s).
+
+3.4. Notices
+
+ You may not remove or alter the substance of any license notices (including
+ copyright notices, patent notices, disclaimers of warranty, or limitations
+ of liability) contained within the Source Code Form of the Covered
+ Software, except that You may alter any license notices to the extent
+ required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+ You may choose to offer, and to charge a fee for, warranty, support,
+ indemnity or liability obligations to one or more recipients of Covered
+ Software. However, You may do so only on Your own behalf, and not on behalf
+ of any Contributor. You must make it absolutely clear that any such
+ warranty, support, indemnity, or liability obligation is offered by You
+ alone, and You hereby agree to indemnify every Contributor for any
+ liability incurred by such Contributor as a result of warranty, support,
+ indemnity or liability terms You offer. You may include additional
+ disclaimers of warranty and limitations of liability specific to any
+ jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+
+ If it is impossible for You to comply with any of the terms of this License
+ with respect to some or all of the Covered Software due to statute, judicial
+ order, or regulation then You must: (a) comply with the terms of this License
+ to the maximum extent possible; and (b) describe the limitations and the code
+ they affect. Such description must be placed in a text file included with all
+ distributions of the Covered Software under this License. Except to the
+ extent prohibited by statute or regulation, such description must be
+ sufficiently detailed for a recipient of ordinary skill to be able to
+ understand it.
+
+5. Termination
+
+5.1. The rights granted under this License will terminate automatically if You
+ fail to comply with any of its terms. However, if You become compliant,
+ then the rights granted under this License from a particular Contributor
+ are reinstated (a) provisionally, unless and until such Contributor
+ explicitly and finally terminates Your grants, and (b) on an ongoing basis,
+ if such Contributor fails to notify You of the non-compliance by some
+ reasonable means prior to 60 days after You have come back into compliance.
+ Moreover, Your grants from a particular Contributor are reinstated on an
+ ongoing basis if such Contributor notifies You of the non-compliance by
+ some reasonable means, this is the first time You have received notice of
+ non-compliance with this License from such Contributor, and You become
+ compliant prior to 30 days after Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+ infringement claim (excluding declaratory judgment actions, counter-claims,
+ and cross-claims) alleging that a Contributor Version directly or
+ indirectly infringes any patent, then the rights granted to You by any and
+ all Contributors for the Covered Software under Section 2.1 of this License
+ shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
+ license agreements (excluding distributors and resellers) which have been
+ validly granted by You or Your distributors under this License prior to
+ termination shall survive termination.
+
+6. Disclaimer of Warranty
+
+ Covered Software is provided under this License on an “as is” basis, without
+ warranty of any kind, either expressed, implied, or statutory, including,
+ without limitation, warranties that the Covered Software is free of defects,
+ merchantable, fit for a particular purpose or non-infringing. The entire
+ risk as to the quality and performance of the Covered Software is with You.
+ Should any Covered Software prove defective in any respect, You (not any
+ Contributor) assume the cost of any necessary servicing, repair, or
+ correction. This disclaimer of warranty constitutes an essential part of this
+ License. No use of any Covered Software is authorized under this License
+ except under this disclaimer.
+
+7. Limitation of Liability
+
+ Under no circumstances and under no legal theory, whether tort (including
+ negligence), contract, or otherwise, shall any Contributor, or anyone who
+ distributes Covered Software as permitted above, be liable to You for any
+ direct, indirect, special, incidental, or consequential damages of any
+ character including, without limitation, damages for lost profits, loss of
+ goodwill, work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses, even if such party shall have been
+ informed of the possibility of such damages. This limitation of liability
+ shall not apply to liability for death or personal injury resulting from such
+ party’s negligence to the extent applicable law prohibits such limitation.
+ Some jurisdictions do not allow the exclusion or limitation of incidental or
+ consequential damages, so this exclusion and limitation may not apply to You.
+
+8. Litigation
+
+ Any litigation relating to this License may be brought only in the courts of
+ a jurisdiction where the defendant maintains its principal place of business
+ and such litigation shall be governed by laws of that jurisdiction, without
+ reference to its conflict-of-law provisions. Nothing in this Section shall
+ prevent a party’s ability to bring cross-claims or counter-claims.
+
+9. Miscellaneous
+
+ This License represents the complete agreement concerning the subject matter
+ hereof. If any provision of this License is held to be unenforceable, such
+ provision shall be reformed only to the extent necessary to make it
+ enforceable. Any law or regulation which provides that the language of a
+ contract shall be construed against the drafter shall not be used to construe
+ this License against a Contributor.
+
+
+10. Versions of the License
+
+10.1. New Versions
+
+ Mozilla Foundation is the license steward. Except as provided in Section
+ 10.3, no one other than the license steward has the right to modify or
+ publish new versions of this License. Each version will be given a
+ distinguishing version number.
+
+10.2. Effect of New Versions
+
+ You may distribute the Covered Software under the terms of the version of
+ the License under which You originally received the Covered Software, or
+ under the terms of any subsequent version published by the license
+ steward.
+
+10.3. Modified Versions
+
+ If you create software not governed by this License, and you want to
+ create a new license for such software, you may create and use a modified
+ version of this License if you rename the license and remove any
+ references to the name of the license steward (except to note that such
+ modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
+ If You choose to distribute Source Code Form that is Incompatible With
+ Secondary Licenses under the terms of this version of the License, the
+ notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+
+ This Source Code Form is subject to the
+ terms of the Mozilla Public License, v.
+ 2.0. If a copy of the MPL was not
+ distributed with this file, You can
+ obtain one at
+ http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular file, then
+You may include the notice in a location (such as a LICENSE file in a relevant
+directory) where a recipient would be likely to look for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - “Incompatible With Secondary Licenses” Notice
+
+ This Source Code Form is “Incompatible
+ With Secondary Licenses”, as defined by
+ the Mozilla Public License, v. 2.0.
+
--- /dev/null
+DEPS = $(go list -f '{{range .Imports}}{{.}} {{end}}' ./...)
+test: subnet
+ go test ./...
+
+integ: subnet
+ INTEG_TESTS=yes go test ./...
+
+subnet:
+ ./test/setup_subnet.sh
+
+cov:
+ gocov test github.com/hashicorp/memberlist | gocov-html > /tmp/coverage.html
+ open /tmp/coverage.html
+
+deps:
+ go get -d -v ./...
+ echo $(DEPS) | xargs -n1 go get -d
+
+.PNONY: test cov integ
--- /dev/null
+# memberlist [](https://godoc.org/github.com/hashicorp/memberlist)
+
+memberlist is a [Go](http://www.golang.org) library that manages cluster
+membership and member failure detection using a gossip based protocol.
+
+The use cases for such a library are far-reaching: all distributed systems
+require membership, and memberlist is a re-usable solution to managing
+cluster membership and node failure detection.
+
+memberlist is eventually consistent but converges quickly on average.
+The speed at which it converges can be heavily tuned via various knobs
+on the protocol. Node failures are detected and network partitions are partially
+tolerated by attempting to communicate to potentially dead nodes through
+multiple routes.
+
+## Building
+
+If you wish to build memberlist you'll need Go version 1.2+ installed.
+
+Please check your installation with:
+
+```
+go version
+```
+
+Run `make deps` to fetch dependencies before building
+
+## Usage
+
+Memberlist is surprisingly simple to use. An example is shown below:
+
+```go
+/* Create the initial memberlist from a safe configuration.
+ Please reference the godoc for other default config types.
+ http://godoc.org/github.com/hashicorp/memberlist#Config
+*/
+list, err := memberlist.Create(memberlist.DefaultLocalConfig())
+if err != nil {
+ panic("Failed to create memberlist: " + err.Error())
+}
+
+// Join an existing cluster by specifying at least one known member.
+n, err := list.Join([]string{"1.2.3.4"})
+if err != nil {
+ panic("Failed to join cluster: " + err.Error())
+}
+
+// Ask for members of the cluster
+for _, member := range list.Members() {
+ fmt.Printf("Member: %s %s\n", member.Name, member.Addr)
+}
+
+// Continue doing whatever you need, memberlist will maintain membership
+// information in the background. Delegates can be used for receiving
+// events when members join or leave.
+```
+
+The most difficult part of memberlist is configuring it since it has many
+available knobs in order to tune state propagation delay and convergence times.
+Memberlist provides a default configuration that offers a good starting point,
+but errs on the side of caution, choosing values that are optimized for
+higher convergence at the cost of higher bandwidth usage.
+
+For complete documentation, see the associated [Godoc](http://godoc.org/github.com/hashicorp/memberlist).
+
+## Protocol
+
+memberlist is based on ["SWIM: Scalable Weakly-consistent Infection-style Process Group Membership Protocol"](http://www.cs.cornell.edu/~asdas/research/dsn02-swim.pdf). However, we extend the protocol in a number of ways:
+
+* Several extensions are made to increase propagation speed and
+convergence rate.
+* Another set of extensions, that we call Lifeguard, are made to make memberlist more robust in the presence of slow message processing (due to factors such as CPU starvation, and network delay or loss).
+
+For details on all of these extensions, please read our paper "[Lifeguard : SWIM-ing with Situational Awareness](https://arxiv.org/abs/1707.00788)", along with the memberlist source. We welcome any questions related
+to the protocol on our issue tracker.
--- /dev/null
+package memberlist
+
+// AliveDelegate is used to involve a client in processing
+// a node "alive" message. When a node joins, either through
+// a UDP gossip or TCP push/pull, we update the state of
+// that node via an alive message. This can be used to filter
+// a node out and prevent it from being considered a peer
+// using application specific logic.
+type AliveDelegate interface {
+ // NotifyMerge is invoked when a merge could take place.
+ // Provides a list of the nodes known by the peer. If
+ // the return value is non-nil, the merge is canceled.
+ NotifyAlive(peer *Node) error
+}
--- /dev/null
+package memberlist
+
+import (
+ "sync"
+ "time"
+
+ "github.com/armon/go-metrics"
+)
+
+// awareness manages a simple metric for tracking the estimated health of the
+// local node. Health is primary the node's ability to respond in the soft
+// real-time manner required for correct health checking of other nodes in the
+// cluster.
+type awareness struct {
+ sync.RWMutex
+
+ // max is the upper threshold for the timeout scale (the score will be
+ // constrained to be from 0 <= score < max).
+ max int
+
+ // score is the current awareness score. Lower values are healthier and
+ // zero is the minimum value.
+ score int
+}
+
+// newAwareness returns a new awareness object.
+func newAwareness(max int) *awareness {
+ return &awareness{
+ max: max,
+ score: 0,
+ }
+}
+
+// ApplyDelta takes the given delta and applies it to the score in a thread-safe
+// manner. It also enforces a floor of zero and a max of max, so deltas may not
+// change the overall score if it's railed at one of the extremes.
+func (a *awareness) ApplyDelta(delta int) {
+ a.Lock()
+ initial := a.score
+ a.score += delta
+ if a.score < 0 {
+ a.score = 0
+ } else if a.score > (a.max - 1) {
+ a.score = (a.max - 1)
+ }
+ final := a.score
+ a.Unlock()
+
+ if initial != final {
+ metrics.SetGauge([]string{"memberlist", "health", "score"}, float32(final))
+ }
+}
+
+// GetHealthScore returns the raw health score.
+func (a *awareness) GetHealthScore() int {
+ a.RLock()
+ score := a.score
+ a.RUnlock()
+ return score
+}
+
+// ScaleTimeout takes the given duration and scales it based on the current
+// score. Less healthyness will lead to longer timeouts.
+func (a *awareness) ScaleTimeout(timeout time.Duration) time.Duration {
+ a.RLock()
+ score := a.score
+ a.RUnlock()
+ return timeout * (time.Duration(score) + 1)
+}
--- /dev/null
+package memberlist
+
+/*
+The broadcast mechanism works by maintaining a sorted list of messages to be
+sent out. When a message is to be broadcast, the retransmit count
+is set to zero and appended to the queue. The retransmit count serves
+as the "priority", ensuring that newer messages get sent first. Once
+a message hits the retransmit limit, it is removed from the queue.
+
+Additionally, older entries can be invalidated by new messages that
+are contradictory. For example, if we send "{suspect M1 inc: 1},
+then a following {alive M1 inc: 2} will invalidate that message
+*/
+
+type memberlistBroadcast struct {
+ node string
+ msg []byte
+ notify chan struct{}
+}
+
+func (b *memberlistBroadcast) Invalidates(other Broadcast) bool {
+ // Check if that broadcast is a memberlist type
+ mb, ok := other.(*memberlistBroadcast)
+ if !ok {
+ return false
+ }
+
+ // Invalidates any message about the same node
+ return b.node == mb.node
+}
+
+func (b *memberlistBroadcast) Message() []byte {
+ return b.msg
+}
+
+func (b *memberlistBroadcast) Finished() {
+ select {
+ case b.notify <- struct{}{}:
+ default:
+ }
+}
+
+// encodeAndBroadcast encodes a message and enqueues it for broadcast. Fails
+// silently if there is an encoding error.
+func (m *Memberlist) encodeAndBroadcast(node string, msgType messageType, msg interface{}) {
+ m.encodeBroadcastNotify(node, msgType, msg, nil)
+}
+
+// encodeBroadcastNotify encodes a message and enqueues it for broadcast
+// and notifies the given channel when transmission is finished. Fails
+// silently if there is an encoding error.
+func (m *Memberlist) encodeBroadcastNotify(node string, msgType messageType, msg interface{}, notify chan struct{}) {
+ buf, err := encode(msgType, msg)
+ if err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to encode message for broadcast: %s", err)
+ } else {
+ m.queueBroadcast(node, buf.Bytes(), notify)
+ }
+}
+
+// queueBroadcast is used to start dissemination of a message. It will be
+// sent up to a configured number of times. The message could potentially
+// be invalidated by a future message about the same node
+func (m *Memberlist) queueBroadcast(node string, msg []byte, notify chan struct{}) {
+ b := &memberlistBroadcast{node, msg, notify}
+ m.broadcasts.QueueBroadcast(b)
+}
+
+// getBroadcasts is used to return a slice of broadcasts to send up to
+// a maximum byte size, while imposing a per-broadcast overhead. This is used
+// to fill a UDP packet with piggybacked data
+func (m *Memberlist) getBroadcasts(overhead, limit int) [][]byte {
+ // Get memberlist messages first
+ toSend := m.broadcasts.GetBroadcasts(overhead, limit)
+
+ // Check if the user has anything to broadcast
+ d := m.config.Delegate
+ if d != nil {
+ // Determine the bytes used already
+ bytesUsed := 0
+ for _, msg := range toSend {
+ bytesUsed += len(msg) + overhead
+ }
+
+ // Check space remaining for user messages
+ avail := limit - bytesUsed
+ if avail > overhead+userMsgOverhead {
+ userMsgs := d.GetBroadcasts(overhead+userMsgOverhead, avail)
+
+ // Frame each user message
+ for _, msg := range userMsgs {
+ buf := make([]byte, 1, len(msg)+1)
+ buf[0] = byte(userMsg)
+ buf = append(buf, msg...)
+ toSend = append(toSend, buf)
+ }
+ }
+ }
+ return toSend
+}
--- /dev/null
+package memberlist
+
+import (
+ "io"
+ "log"
+ "os"
+ "time"
+)
+
+type Config struct {
+ // The name of this node. This must be unique in the cluster.
+ Name string
+
+ // Transport is a hook for providing custom code to communicate with
+ // other nodes. If this is left nil, then memberlist will by default
+ // make a NetTransport using BindAddr and BindPort from this structure.
+ Transport Transport
+
+ // Configuration related to what address to bind to and ports to
+ // listen on. The port is used for both UDP and TCP gossip. It is
+ // assumed other nodes are running on this port, but they do not need
+ // to.
+ BindAddr string
+ BindPort int
+
+ // Configuration related to what address to advertise to other
+ // cluster members. Used for nat traversal.
+ AdvertiseAddr string
+ AdvertisePort int
+
+ // ProtocolVersion is the configured protocol version that we
+ // will _speak_. This must be between ProtocolVersionMin and
+ // ProtocolVersionMax.
+ ProtocolVersion uint8
+
+ // TCPTimeout is the timeout for establishing a stream connection with
+ // a remote node for a full state sync, and for stream read and write
+ // operations. This is a legacy name for backwards compatibility, but
+ // should really be called StreamTimeout now that we have generalized
+ // the transport.
+ TCPTimeout time.Duration
+
+ // IndirectChecks is the number of nodes that will be asked to perform
+ // an indirect probe of a node in the case a direct probe fails. Memberlist
+ // waits for an ack from any single indirect node, so increasing this
+ // number will increase the likelihood that an indirect probe will succeed
+ // at the expense of bandwidth.
+ IndirectChecks int
+
+ // RetransmitMult is the multiplier for the number of retransmissions
+ // that are attempted for messages broadcasted over gossip. The actual
+ // count of retransmissions is calculated using the formula:
+ //
+ // Retransmits = RetransmitMult * log(N+1)
+ //
+ // This allows the retransmits to scale properly with cluster size. The
+ // higher the multiplier, the more likely a failed broadcast is to converge
+ // at the expense of increased bandwidth.
+ RetransmitMult int
+
+ // SuspicionMult is the multiplier for determining the time an
+ // inaccessible node is considered suspect before declaring it dead.
+ // The actual timeout is calculated using the formula:
+ //
+ // SuspicionTimeout = SuspicionMult * log(N+1) * ProbeInterval
+ //
+ // This allows the timeout to scale properly with expected propagation
+ // delay with a larger cluster size. The higher the multiplier, the longer
+ // an inaccessible node is considered part of the cluster before declaring
+ // it dead, giving that suspect node more time to refute if it is indeed
+ // still alive.
+ SuspicionMult int
+
+ // SuspicionMaxTimeoutMult is the multiplier applied to the
+ // SuspicionTimeout used as an upper bound on detection time. This max
+ // timeout is calculated using the formula:
+ //
+ // SuspicionMaxTimeout = SuspicionMaxTimeoutMult * SuspicionTimeout
+ //
+ // If everything is working properly, confirmations from other nodes will
+ // accelerate suspicion timers in a manner which will cause the timeout
+ // to reach the base SuspicionTimeout before that elapses, so this value
+ // will typically only come into play if a node is experiencing issues
+ // communicating with other nodes. It should be set to a something fairly
+ // large so that a node having problems will have a lot of chances to
+ // recover before falsely declaring other nodes as failed, but short
+ // enough for a legitimately isolated node to still make progress marking
+ // nodes failed in a reasonable amount of time.
+ SuspicionMaxTimeoutMult int
+
+ // PushPullInterval is the interval between complete state syncs.
+ // Complete state syncs are done with a single node over TCP and are
+ // quite expensive relative to standard gossiped messages. Setting this
+ // to zero will disable state push/pull syncs completely.
+ //
+ // Setting this interval lower (more frequent) will increase convergence
+ // speeds across larger clusters at the expense of increased bandwidth
+ // usage.
+ PushPullInterval time.Duration
+
+ // ProbeInterval and ProbeTimeout are used to configure probing
+ // behavior for memberlist.
+ //
+ // ProbeInterval is the interval between random node probes. Setting
+ // this lower (more frequent) will cause the memberlist cluster to detect
+ // failed nodes more quickly at the expense of increased bandwidth usage.
+ //
+ // ProbeTimeout is the timeout to wait for an ack from a probed node
+ // before assuming it is unhealthy. This should be set to 99-percentile
+ // of RTT (round-trip time) on your network.
+ ProbeInterval time.Duration
+ ProbeTimeout time.Duration
+
+ // DisableTcpPings will turn off the fallback TCP pings that are attempted
+ // if the direct UDP ping fails. These get pipelined along with the
+ // indirect UDP pings.
+ DisableTcpPings bool
+
+ // AwarenessMaxMultiplier will increase the probe interval if the node
+ // becomes aware that it might be degraded and not meeting the soft real
+ // time requirements to reliably probe other nodes.
+ AwarenessMaxMultiplier int
+
+ // GossipInterval and GossipNodes are used to configure the gossip
+ // behavior of memberlist.
+ //
+ // GossipInterval is the interval between sending messages that need
+ // to be gossiped that haven't been able to piggyback on probing messages.
+ // If this is set to zero, non-piggyback gossip is disabled. By lowering
+ // this value (more frequent) gossip messages are propagated across
+ // the cluster more quickly at the expense of increased bandwidth.
+ //
+ // GossipNodes is the number of random nodes to send gossip messages to
+ // per GossipInterval. Increasing this number causes the gossip messages
+ // to propagate across the cluster more quickly at the expense of
+ // increased bandwidth.
+ //
+ // GossipToTheDeadTime is the interval after which a node has died that
+ // we will still try to gossip to it. This gives it a chance to refute.
+ GossipInterval time.Duration
+ GossipNodes int
+ GossipToTheDeadTime time.Duration
+
+ // GossipVerifyIncoming controls whether to enforce encryption for incoming
+ // gossip. It is used for upshifting from unencrypted to encrypted gossip on
+ // a running cluster.
+ GossipVerifyIncoming bool
+
+ // GossipVerifyOutgoing controls whether to enforce encryption for outgoing
+ // gossip. It is used for upshifting from unencrypted to encrypted gossip on
+ // a running cluster.
+ GossipVerifyOutgoing bool
+
+ // EnableCompression is used to control message compression. This can
+ // be used to reduce bandwidth usage at the cost of slightly more CPU
+ // utilization. This is only available starting at protocol version 1.
+ EnableCompression bool
+
+ // SecretKey is used to initialize the primary encryption key in a keyring.
+ // The primary encryption key is the only key used to encrypt messages and
+ // the first key used while attempting to decrypt messages. Providing a
+ // value for this primary key will enable message-level encryption and
+ // verification, and automatically install the key onto the keyring.
+ // The value should be either 16, 24, or 32 bytes to select AES-128,
+ // AES-192, or AES-256.
+ SecretKey []byte
+
+ // The keyring holds all of the encryption keys used internally. It is
+ // automatically initialized using the SecretKey and SecretKeys values.
+ Keyring *Keyring
+
+ // Delegate and Events are delegates for receiving and providing
+ // data to memberlist via callback mechanisms. For Delegate, see
+ // the Delegate interface. For Events, see the EventDelegate interface.
+ //
+ // The DelegateProtocolMin/Max are used to guarantee protocol-compatibility
+ // for any custom messages that the delegate might do (broadcasts,
+ // local/remote state, etc.). If you don't set these, then the protocol
+ // versions will just be zero, and version compliance won't be done.
+ Delegate Delegate
+ DelegateProtocolVersion uint8
+ DelegateProtocolMin uint8
+ DelegateProtocolMax uint8
+ Events EventDelegate
+ Conflict ConflictDelegate
+ Merge MergeDelegate
+ Ping PingDelegate
+ Alive AliveDelegate
+
+ // DNSConfigPath points to the system's DNS config file, usually located
+ // at /etc/resolv.conf. It can be overridden via config for easier testing.
+ DNSConfigPath string
+
+ // LogOutput is the writer where logs should be sent. If this is not
+ // set, logging will go to stderr by default. You cannot specify both LogOutput
+ // and Logger at the same time.
+ LogOutput io.Writer
+
+ // Logger is a custom logger which you provide. If Logger is set, it will use
+ // this for the internal logger. If Logger is not set, it will fall back to the
+ // behavior for using LogOutput. You cannot specify both LogOutput and Logger
+ // at the same time.
+ Logger *log.Logger
+
+ // Size of Memberlist's internal channel which handles UDP messages. The
+ // size of this determines the size of the queue which Memberlist will keep
+ // while UDP messages are handled.
+ HandoffQueueDepth int
+
+ // Maximum number of bytes that memberlist will put in a packet (this
+ // will be for UDP packets by default with a NetTransport). A safe value
+ // for this is typically 1400 bytes (which is the default). However,
+ // depending on your network's MTU (Maximum Transmission Unit) you may
+ // be able to increase this to get more content into each gossip packet.
+ // This is a legacy name for backward compatibility but should really be
+ // called PacketBufferSize now that we have generalized the transport.
+ UDPBufferSize int
+}
+
+// DefaultLANConfig returns a sane set of configurations for Memberlist.
+// It uses the hostname as the node name, and otherwise sets very conservative
+// values that are sane for most LAN environments. The default configuration
+// errs on the side of caution, choosing values that are optimized
+// for higher convergence at the cost of higher bandwidth usage. Regardless,
+// these values are a good starting point when getting started with memberlist.
+func DefaultLANConfig() *Config {
+ hostname, _ := os.Hostname()
+ return &Config{
+ Name: hostname,
+ BindAddr: "0.0.0.0",
+ BindPort: 7946,
+ AdvertiseAddr: "",
+ AdvertisePort: 7946,
+ ProtocolVersion: ProtocolVersion2Compatible,
+ TCPTimeout: 10 * time.Second, // Timeout after 10 seconds
+ IndirectChecks: 3, // Use 3 nodes for the indirect ping
+ RetransmitMult: 4, // Retransmit a message 4 * log(N+1) nodes
+ SuspicionMult: 4, // Suspect a node for 4 * log(N+1) * Interval
+ SuspicionMaxTimeoutMult: 6, // For 10k nodes this will give a max timeout of 120 seconds
+ PushPullInterval: 30 * time.Second, // Low frequency
+ ProbeTimeout: 500 * time.Millisecond, // Reasonable RTT time for LAN
+ ProbeInterval: 1 * time.Second, // Failure check every second
+ DisableTcpPings: false, // TCP pings are safe, even with mixed versions
+ AwarenessMaxMultiplier: 8, // Probe interval backs off to 8 seconds
+
+ GossipNodes: 3, // Gossip to 3 nodes
+ GossipInterval: 200 * time.Millisecond, // Gossip more rapidly
+ GossipToTheDeadTime: 30 * time.Second, // Same as push/pull
+ GossipVerifyIncoming: true,
+ GossipVerifyOutgoing: true,
+
+ EnableCompression: true, // Enable compression by default
+
+ SecretKey: nil,
+ Keyring: nil,
+
+ DNSConfigPath: "/etc/resolv.conf",
+
+ HandoffQueueDepth: 1024,
+ UDPBufferSize: 1400,
+ }
+}
+
+// DefaultWANConfig works like DefaultConfig, however it returns a configuration
+// that is optimized for most WAN environments. The default configuration is
+// still very conservative and errs on the side of caution.
+func DefaultWANConfig() *Config {
+ conf := DefaultLANConfig()
+ conf.TCPTimeout = 30 * time.Second
+ conf.SuspicionMult = 6
+ conf.PushPullInterval = 60 * time.Second
+ conf.ProbeTimeout = 3 * time.Second
+ conf.ProbeInterval = 5 * time.Second
+ conf.GossipNodes = 4 // Gossip less frequently, but to an additional node
+ conf.GossipInterval = 500 * time.Millisecond
+ conf.GossipToTheDeadTime = 60 * time.Second
+ return conf
+}
+
+// DefaultLocalConfig works like DefaultConfig, however it returns a configuration
+// that is optimized for a local loopback environments. The default configuration is
+// still very conservative and errs on the side of caution.
+func DefaultLocalConfig() *Config {
+ conf := DefaultLANConfig()
+ conf.TCPTimeout = time.Second
+ conf.IndirectChecks = 1
+ conf.RetransmitMult = 2
+ conf.SuspicionMult = 3
+ conf.PushPullInterval = 15 * time.Second
+ conf.ProbeTimeout = 200 * time.Millisecond
+ conf.ProbeInterval = time.Second
+ conf.GossipInterval = 100 * time.Millisecond
+ conf.GossipToTheDeadTime = 15 * time.Second
+ return conf
+}
+
+// Returns whether or not encryption is enabled
+func (c *Config) EncryptionEnabled() bool {
+ return c.Keyring != nil && len(c.Keyring.GetKeys()) > 0
+}
--- /dev/null
+package memberlist
+
+// ConflictDelegate is a used to inform a client that
+// a node has attempted to join which would result in a
+// name conflict. This happens if two clients are configured
+// with the same name but different addresses.
+type ConflictDelegate interface {
+ // NotifyConflict is invoked when a name conflict is detected
+ NotifyConflict(existing, other *Node)
+}
--- /dev/null
+package memberlist
+
+// Delegate is the interface that clients must implement if they want to hook
+// into the gossip layer of Memberlist. All the methods must be thread-safe,
+// as they can and generally will be called concurrently.
+type Delegate interface {
+ // NodeMeta is used to retrieve meta-data about the current node
+ // when broadcasting an alive message. It's length is limited to
+ // the given byte size. This metadata is available in the Node structure.
+ NodeMeta(limit int) []byte
+
+ // NotifyMsg is called when a user-data message is received.
+ // Care should be taken that this method does not block, since doing
+ // so would block the entire UDP packet receive loop. Additionally, the byte
+ // slice may be modified after the call returns, so it should be copied if needed
+ NotifyMsg([]byte)
+
+ // GetBroadcasts is called when user data messages can be broadcast.
+ // It can return a list of buffers to send. Each buffer should assume an
+ // overhead as provided with a limit on the total byte size allowed.
+ // The total byte size of the resulting data to send must not exceed
+ // the limit. Care should be taken that this method does not block,
+ // since doing so would block the entire UDP packet receive loop.
+ GetBroadcasts(overhead, limit int) [][]byte
+
+ // LocalState is used for a TCP Push/Pull. This is sent to
+ // the remote side in addition to the membership information. Any
+ // data can be sent here. See MergeRemoteState as well. The `join`
+ // boolean indicates this is for a join instead of a push/pull.
+ LocalState(join bool) []byte
+
+ // MergeRemoteState is invoked after a TCP Push/Pull. This is the
+ // state received from the remote side and is the result of the
+ // remote side's LocalState call. The 'join'
+ // boolean indicates this is for a join instead of a push/pull.
+ MergeRemoteState(buf []byte, join bool)
+}
--- /dev/null
+package memberlist
+
+// EventDelegate is a simpler delegate that is used only to receive
+// notifications about members joining and leaving. The methods in this
+// delegate may be called by multiple goroutines, but never concurrently.
+// This allows you to reason about ordering.
+type EventDelegate interface {
+ // NotifyJoin is invoked when a node is detected to have joined.
+ // The Node argument must not be modified.
+ NotifyJoin(*Node)
+
+ // NotifyLeave is invoked when a node is detected to have left.
+ // The Node argument must not be modified.
+ NotifyLeave(*Node)
+
+ // NotifyUpdate is invoked when a node is detected to have
+ // updated, usually involving the meta data. The Node argument
+ // must not be modified.
+ NotifyUpdate(*Node)
+}
+
+// ChannelEventDelegate is used to enable an application to receive
+// events about joins and leaves over a channel instead of a direct
+// function call.
+//
+// Care must be taken that events are processed in a timely manner from
+// the channel, since this delegate will block until an event can be sent.
+type ChannelEventDelegate struct {
+ Ch chan<- NodeEvent
+}
+
+// NodeEventType are the types of events that can be sent from the
+// ChannelEventDelegate.
+type NodeEventType int
+
+const (
+ NodeJoin NodeEventType = iota
+ NodeLeave
+ NodeUpdate
+)
+
+// NodeEvent is a single event related to node activity in the memberlist.
+// The Node member of this struct must not be directly modified. It is passed
+// as a pointer to avoid unnecessary copies. If you wish to modify the node,
+// make a copy first.
+type NodeEvent struct {
+ Event NodeEventType
+ Node *Node
+}
+
+func (c *ChannelEventDelegate) NotifyJoin(n *Node) {
+ c.Ch <- NodeEvent{NodeJoin, n}
+}
+
+func (c *ChannelEventDelegate) NotifyLeave(n *Node) {
+ c.Ch <- NodeEvent{NodeLeave, n}
+}
+
+func (c *ChannelEventDelegate) NotifyUpdate(n *Node) {
+ c.Ch <- NodeEvent{NodeUpdate, n}
+}
--- /dev/null
+package memberlist
+
+import (
+ "bytes"
+ "fmt"
+ "sync"
+)
+
+type Keyring struct {
+ // Keys stores the key data used during encryption and decryption. It is
+ // ordered in such a way where the first key (index 0) is the primary key,
+ // which is used for encrypting messages, and is the first key tried during
+ // message decryption.
+ keys [][]byte
+
+ // The keyring lock is used while performing IO operations on the keyring.
+ l sync.Mutex
+}
+
+// Init allocates substructures
+func (k *Keyring) init() {
+ k.keys = make([][]byte, 0)
+}
+
+// NewKeyring constructs a new container for a set of encryption keys. The
+// keyring contains all key data used internally by memberlist.
+//
+// While creating a new keyring, you must do one of:
+// - Omit keys and primary key, effectively disabling encryption
+// - Pass a set of keys plus the primary key
+// - Pass only a primary key
+//
+// If only a primary key is passed, then it will be automatically added to the
+// keyring. If creating a keyring with multiple keys, one key must be designated
+// primary by passing it as the primaryKey. If the primaryKey does not exist in
+// the list of secondary keys, it will be automatically added at position 0.
+//
+// A key should be either 16, 24, or 32 bytes to select AES-128,
+// AES-192, or AES-256.
+func NewKeyring(keys [][]byte, primaryKey []byte) (*Keyring, error) {
+ keyring := &Keyring{}
+ keyring.init()
+
+ if len(keys) > 0 || len(primaryKey) > 0 {
+ if len(primaryKey) == 0 {
+ return nil, fmt.Errorf("Empty primary key not allowed")
+ }
+ if err := keyring.AddKey(primaryKey); err != nil {
+ return nil, err
+ }
+ for _, key := range keys {
+ if err := keyring.AddKey(key); err != nil {
+ return nil, err
+ }
+ }
+ }
+
+ return keyring, nil
+}
+
+// ValidateKey will check to see if the key is valid and returns an error if not.
+//
+// key should be either 16, 24, or 32 bytes to select AES-128,
+// AES-192, or AES-256.
+func ValidateKey(key []byte) error {
+ if l := len(key); l != 16 && l != 24 && l != 32 {
+ return fmt.Errorf("key size must be 16, 24 or 32 bytes")
+ }
+ return nil
+}
+
+// AddKey will install a new key on the ring. Adding a key to the ring will make
+// it available for use in decryption. If the key already exists on the ring,
+// this function will just return noop.
+//
+// key should be either 16, 24, or 32 bytes to select AES-128,
+// AES-192, or AES-256.
+func (k *Keyring) AddKey(key []byte) error {
+ if err := ValidateKey(key); err != nil {
+ return err
+ }
+
+ // No-op if key is already installed
+ for _, installedKey := range k.keys {
+ if bytes.Equal(installedKey, key) {
+ return nil
+ }
+ }
+
+ keys := append(k.keys, key)
+ primaryKey := k.GetPrimaryKey()
+ if primaryKey == nil {
+ primaryKey = key
+ }
+ k.installKeys(keys, primaryKey)
+ return nil
+}
+
+// UseKey changes the key used to encrypt messages. This is the only key used to
+// encrypt messages, so peers should know this key before this method is called.
+func (k *Keyring) UseKey(key []byte) error {
+ for _, installedKey := range k.keys {
+ if bytes.Equal(key, installedKey) {
+ k.installKeys(k.keys, key)
+ return nil
+ }
+ }
+ return fmt.Errorf("Requested key is not in the keyring")
+}
+
+// RemoveKey drops a key from the keyring. This will return an error if the key
+// requested for removal is currently at position 0 (primary key).
+func (k *Keyring) RemoveKey(key []byte) error {
+ if bytes.Equal(key, k.keys[0]) {
+ return fmt.Errorf("Removing the primary key is not allowed")
+ }
+ for i, installedKey := range k.keys {
+ if bytes.Equal(key, installedKey) {
+ keys := append(k.keys[:i], k.keys[i+1:]...)
+ k.installKeys(keys, k.keys[0])
+ }
+ }
+ return nil
+}
+
+// installKeys will take out a lock on the keyring, and replace the keys with a
+// new set of keys. The key indicated by primaryKey will be installed as the new
+// primary key.
+func (k *Keyring) installKeys(keys [][]byte, primaryKey []byte) {
+ k.l.Lock()
+ defer k.l.Unlock()
+
+ newKeys := [][]byte{primaryKey}
+ for _, key := range keys {
+ if !bytes.Equal(key, primaryKey) {
+ newKeys = append(newKeys, key)
+ }
+ }
+ k.keys = newKeys
+}
+
+// GetKeys returns the current set of keys on the ring.
+func (k *Keyring) GetKeys() [][]byte {
+ k.l.Lock()
+ defer k.l.Unlock()
+
+ return k.keys
+}
+
+// GetPrimaryKey returns the key on the ring at position 0. This is the key used
+// for encrypting messages, and is the first key tried for decrypting messages.
+func (k *Keyring) GetPrimaryKey() (key []byte) {
+ k.l.Lock()
+ defer k.l.Unlock()
+
+ if len(k.keys) > 0 {
+ key = k.keys[0]
+ }
+ return
+}
--- /dev/null
+package memberlist
+
+import (
+ "fmt"
+ "net"
+)
+
+func LogAddress(addr net.Addr) string {
+ if addr == nil {
+ return "from=<unknown address>"
+ }
+
+ return fmt.Sprintf("from=%s", addr.String())
+}
+
+func LogConn(conn net.Conn) string {
+ if conn == nil {
+ return LogAddress(nil)
+ }
+
+ return LogAddress(conn.RemoteAddr())
+}
--- /dev/null
+/*
+memberlist is a library that manages cluster
+membership and member failure detection using a gossip based protocol.
+
+The use cases for such a library are far-reaching: all distributed systems
+require membership, and memberlist is a re-usable solution to managing
+cluster membership and node failure detection.
+
+memberlist is eventually consistent but converges quickly on average.
+The speed at which it converges can be heavily tuned via various knobs
+on the protocol. Node failures are detected and network partitions are partially
+tolerated by attempting to communicate to potentially dead nodes through
+multiple routes.
+*/
+package memberlist
+
+import (
+ "fmt"
+ "log"
+ "net"
+ "os"
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ multierror "github.com/hashicorp/go-multierror"
+ sockaddr "github.com/hashicorp/go-sockaddr"
+ "github.com/miekg/dns"
+)
+
+type Memberlist struct {
+ sequenceNum uint32 // Local sequence number
+ incarnation uint32 // Local incarnation number
+ numNodes uint32 // Number of known nodes (estimate)
+
+ config *Config
+ shutdown int32 // Used as an atomic boolean value
+ shutdownCh chan struct{}
+ leave int32 // Used as an atomic boolean value
+ leaveBroadcast chan struct{}
+
+ shutdownLock sync.Mutex // Serializes calls to Shutdown
+ leaveLock sync.Mutex // Serializes calls to Leave
+
+ transport Transport
+ handoff chan msgHandoff
+
+ nodeLock sync.RWMutex
+ nodes []*nodeState // Known nodes
+ nodeMap map[string]*nodeState // Maps Addr.String() -> NodeState
+ nodeTimers map[string]*suspicion // Maps Addr.String() -> suspicion timer
+ awareness *awareness
+
+ tickerLock sync.Mutex
+ tickers []*time.Ticker
+ stopTick chan struct{}
+ probeIndex int
+
+ ackLock sync.Mutex
+ ackHandlers map[uint32]*ackHandler
+
+ broadcasts *TransmitLimitedQueue
+
+ logger *log.Logger
+}
+
+// newMemberlist creates the network listeners.
+// Does not schedule execution of background maintenance.
+func newMemberlist(conf *Config) (*Memberlist, error) {
+ if conf.ProtocolVersion < ProtocolVersionMin {
+ return nil, fmt.Errorf("Protocol version '%d' too low. Must be in range: [%d, %d]",
+ conf.ProtocolVersion, ProtocolVersionMin, ProtocolVersionMax)
+ } else if conf.ProtocolVersion > ProtocolVersionMax {
+ return nil, fmt.Errorf("Protocol version '%d' too high. Must be in range: [%d, %d]",
+ conf.ProtocolVersion, ProtocolVersionMin, ProtocolVersionMax)
+ }
+
+ if len(conf.SecretKey) > 0 {
+ if conf.Keyring == nil {
+ keyring, err := NewKeyring(nil, conf.SecretKey)
+ if err != nil {
+ return nil, err
+ }
+ conf.Keyring = keyring
+ } else {
+ if err := conf.Keyring.AddKey(conf.SecretKey); err != nil {
+ return nil, err
+ }
+ if err := conf.Keyring.UseKey(conf.SecretKey); err != nil {
+ return nil, err
+ }
+ }
+ }
+
+ if conf.LogOutput != nil && conf.Logger != nil {
+ return nil, fmt.Errorf("Cannot specify both LogOutput and Logger. Please choose a single log configuration setting.")
+ }
+
+ logDest := conf.LogOutput
+ if logDest == nil {
+ logDest = os.Stderr
+ }
+
+ logger := conf.Logger
+ if logger == nil {
+ logger = log.New(logDest, "", log.LstdFlags)
+ }
+
+ // Set up a network transport by default if a custom one wasn't given
+ // by the config.
+ transport := conf.Transport
+ if transport == nil {
+ nc := &NetTransportConfig{
+ BindAddrs: []string{conf.BindAddr},
+ BindPort: conf.BindPort,
+ Logger: logger,
+ }
+
+ // See comment below for details about the retry in here.
+ makeNetRetry := func(limit int) (*NetTransport, error) {
+ var err error
+ for try := 0; try < limit; try++ {
+ var nt *NetTransport
+ if nt, err = NewNetTransport(nc); err == nil {
+ return nt, nil
+ }
+ if strings.Contains(err.Error(), "address already in use") {
+ logger.Printf("[DEBUG] memberlist: Got bind error: %v", err)
+ continue
+ }
+ }
+
+ return nil, fmt.Errorf("failed to obtain an address: %v", err)
+ }
+
+ // The dynamic bind port operation is inherently racy because
+ // even though we are using the kernel to find a port for us, we
+ // are attempting to bind multiple protocols (and potentially
+ // multiple addresses) with the same port number. We build in a
+ // few retries here since this often gets transient errors in
+ // busy unit tests.
+ limit := 1
+ if conf.BindPort == 0 {
+ limit = 10
+ }
+
+ nt, err := makeNetRetry(limit)
+ if err != nil {
+ return nil, fmt.Errorf("Could not set up network transport: %v", err)
+ }
+ if conf.BindPort == 0 {
+ port := nt.GetAutoBindPort()
+ conf.BindPort = port
+ conf.AdvertisePort = port
+ logger.Printf("[DEBUG] memberlist: Using dynamic bind port %d", port)
+ }
+ transport = nt
+ }
+
+ m := &Memberlist{
+ config: conf,
+ shutdownCh: make(chan struct{}),
+ leaveBroadcast: make(chan struct{}, 1),
+ transport: transport,
+ handoff: make(chan msgHandoff, conf.HandoffQueueDepth),
+ nodeMap: make(map[string]*nodeState),
+ nodeTimers: make(map[string]*suspicion),
+ awareness: newAwareness(conf.AwarenessMaxMultiplier),
+ ackHandlers: make(map[uint32]*ackHandler),
+ broadcasts: &TransmitLimitedQueue{RetransmitMult: conf.RetransmitMult},
+ logger: logger,
+ }
+ m.broadcasts.NumNodes = func() int {
+ return m.estNumNodes()
+ }
+ go m.streamListen()
+ go m.packetListen()
+ go m.packetHandler()
+ return m, nil
+}
+
+// Create will create a new Memberlist using the given configuration.
+// This will not connect to any other node (see Join) yet, but will start
+// all the listeners to allow other nodes to join this memberlist.
+// After creating a Memberlist, the configuration given should not be
+// modified by the user anymore.
+func Create(conf *Config) (*Memberlist, error) {
+ m, err := newMemberlist(conf)
+ if err != nil {
+ return nil, err
+ }
+ if err := m.setAlive(); err != nil {
+ m.Shutdown()
+ return nil, err
+ }
+ m.schedule()
+ return m, nil
+}
+
+// Join is used to take an existing Memberlist and attempt to join a cluster
+// by contacting all the given hosts and performing a state sync. Initially,
+// the Memberlist only contains our own state, so doing this will cause
+// remote nodes to become aware of the existence of this node, effectively
+// joining the cluster.
+//
+// This returns the number of hosts successfully contacted and an error if
+// none could be reached. If an error is returned, the node did not successfully
+// join the cluster.
+func (m *Memberlist) Join(existing []string) (int, error) {
+ numSuccess := 0
+ var errs error
+ for _, exist := range existing {
+ addrs, err := m.resolveAddr(exist)
+ if err != nil {
+ err = fmt.Errorf("Failed to resolve %s: %v", exist, err)
+ errs = multierror.Append(errs, err)
+ m.logger.Printf("[WARN] memberlist: %v", err)
+ continue
+ }
+
+ for _, addr := range addrs {
+ hp := joinHostPort(addr.ip.String(), addr.port)
+ if err := m.pushPullNode(hp, true); err != nil {
+ err = fmt.Errorf("Failed to join %s: %v", addr.ip, err)
+ errs = multierror.Append(errs, err)
+ m.logger.Printf("[DEBUG] memberlist: %v", err)
+ continue
+ }
+ numSuccess++
+ }
+
+ }
+ if numSuccess > 0 {
+ errs = nil
+ }
+ return numSuccess, errs
+}
+
+// ipPort holds information about a node we want to try to join.
+type ipPort struct {
+ ip net.IP
+ port uint16
+}
+
+// tcpLookupIP is a helper to initiate a TCP-based DNS lookup for the given host.
+// The built-in Go resolver will do a UDP lookup first, and will only use TCP if
+// the response has the truncate bit set, which isn't common on DNS servers like
+// Consul's. By doing the TCP lookup directly, we get the best chance for the
+// largest list of hosts to join. Since joins are relatively rare events, it's ok
+// to do this rather expensive operation.
+func (m *Memberlist) tcpLookupIP(host string, defaultPort uint16) ([]ipPort, error) {
+ // Don't attempt any TCP lookups against non-fully qualified domain
+ // names, since those will likely come from the resolv.conf file.
+ if !strings.Contains(host, ".") {
+ return nil, nil
+ }
+
+ // Make sure the domain name is terminated with a dot (we know there's
+ // at least one character at this point).
+ dn := host
+ if dn[len(dn)-1] != '.' {
+ dn = dn + "."
+ }
+
+ // See if we can find a server to try.
+ cc, err := dns.ClientConfigFromFile(m.config.DNSConfigPath)
+ if err != nil {
+ return nil, err
+ }
+ if len(cc.Servers) > 0 {
+ // We support host:port in the DNS config, but need to add the
+ // default port if one is not supplied.
+ server := cc.Servers[0]
+ if !hasPort(server) {
+ server = net.JoinHostPort(server, cc.Port)
+ }
+
+ // Do the lookup.
+ c := new(dns.Client)
+ c.Net = "tcp"
+ msg := new(dns.Msg)
+ msg.SetQuestion(dn, dns.TypeANY)
+ in, _, err := c.Exchange(msg, server)
+ if err != nil {
+ return nil, err
+ }
+
+ // Handle any IPs we get back that we can attempt to join.
+ var ips []ipPort
+ for _, r := range in.Answer {
+ switch rr := r.(type) {
+ case (*dns.A):
+ ips = append(ips, ipPort{rr.A, defaultPort})
+ case (*dns.AAAA):
+ ips = append(ips, ipPort{rr.AAAA, defaultPort})
+ case (*dns.CNAME):
+ m.logger.Printf("[DEBUG] memberlist: Ignoring CNAME RR in TCP-first answer for '%s'", host)
+ }
+ }
+ return ips, nil
+ }
+
+ return nil, nil
+}
+
+// resolveAddr is used to resolve the address into an address,
+// port, and error. If no port is given, use the default
+func (m *Memberlist) resolveAddr(hostStr string) ([]ipPort, error) {
+ // Normalize the incoming string to host:port so we can apply Go's
+ // parser to it.
+ port := uint16(0)
+ if !hasPort(hostStr) {
+ hostStr += ":" + strconv.Itoa(m.config.BindPort)
+ }
+ host, sport, err := net.SplitHostPort(hostStr)
+ if err != nil {
+ return nil, err
+ }
+
+ // This will capture the supplied port, or the default one added above.
+ lport, err := strconv.ParseUint(sport, 10, 16)
+ if err != nil {
+ return nil, err
+ }
+ port = uint16(lport)
+
+ // If it looks like an IP address we are done. The SplitHostPort() above
+ // will make sure the host part is in good shape for parsing, even for
+ // IPv6 addresses.
+ if ip := net.ParseIP(host); ip != nil {
+ return []ipPort{ipPort{ip, port}}, nil
+ }
+
+ // First try TCP so we have the best chance for the largest list of
+ // hosts to join. If this fails it's not fatal since this isn't a standard
+ // way to query DNS, and we have a fallback below.
+ ips, err := m.tcpLookupIP(host, port)
+ if err != nil {
+ m.logger.Printf("[DEBUG] memberlist: TCP-first lookup failed for '%s', falling back to UDP: %s", hostStr, err)
+ }
+ if len(ips) > 0 {
+ return ips, nil
+ }
+
+ // If TCP didn't yield anything then use the normal Go resolver which
+ // will try UDP, then might possibly try TCP again if the UDP response
+ // indicates it was truncated.
+ ans, err := net.LookupIP(host)
+ if err != nil {
+ return nil, err
+ }
+ ips = make([]ipPort, 0, len(ans))
+ for _, ip := range ans {
+ ips = append(ips, ipPort{ip, port})
+ }
+ return ips, nil
+}
+
+// setAlive is used to mark this node as being alive. This is the same
+// as if we received an alive notification our own network channel for
+// ourself.
+func (m *Memberlist) setAlive() error {
+ // Get the final advertise address from the transport, which may need
+ // to see which address we bound to.
+ addr, port, err := m.transport.FinalAdvertiseAddr(
+ m.config.AdvertiseAddr, m.config.AdvertisePort)
+ if err != nil {
+ return fmt.Errorf("Failed to get final advertise address: %v", err)
+ }
+
+ // Check if this is a public address without encryption
+ ipAddr, err := sockaddr.NewIPAddr(addr.String())
+ if err != nil {
+ return fmt.Errorf("Failed to parse interface addresses: %v", err)
+ }
+ ifAddrs := []sockaddr.IfAddr{
+ sockaddr.IfAddr{
+ SockAddr: ipAddr,
+ },
+ }
+ _, publicIfs, err := sockaddr.IfByRFC("6890", ifAddrs)
+ if len(publicIfs) > 0 && !m.config.EncryptionEnabled() {
+ m.logger.Printf("[WARN] memberlist: Binding to public address without encryption!")
+ }
+
+ // Set any metadata from the delegate.
+ var meta []byte
+ if m.config.Delegate != nil {
+ meta = m.config.Delegate.NodeMeta(MetaMaxSize)
+ if len(meta) > MetaMaxSize {
+ panic("Node meta data provided is longer than the limit")
+ }
+ }
+
+ a := alive{
+ Incarnation: m.nextIncarnation(),
+ Node: m.config.Name,
+ Addr: addr,
+ Port: uint16(port),
+ Meta: meta,
+ Vsn: []uint8{
+ ProtocolVersionMin, ProtocolVersionMax, m.config.ProtocolVersion,
+ m.config.DelegateProtocolMin, m.config.DelegateProtocolMax,
+ m.config.DelegateProtocolVersion,
+ },
+ }
+ m.aliveNode(&a, nil, true)
+ return nil
+}
+
+// LocalNode is used to return the local Node
+func (m *Memberlist) LocalNode() *Node {
+ m.nodeLock.RLock()
+ defer m.nodeLock.RUnlock()
+ state := m.nodeMap[m.config.Name]
+ return &state.Node
+}
+
+// UpdateNode is used to trigger re-advertising the local node. This is
+// primarily used with a Delegate to support dynamic updates to the local
+// meta data. This will block until the update message is successfully
+// broadcasted to a member of the cluster, if any exist or until a specified
+// timeout is reached.
+func (m *Memberlist) UpdateNode(timeout time.Duration) error {
+ // Get the node meta data
+ var meta []byte
+ if m.config.Delegate != nil {
+ meta = m.config.Delegate.NodeMeta(MetaMaxSize)
+ if len(meta) > MetaMaxSize {
+ panic("Node meta data provided is longer than the limit")
+ }
+ }
+
+ // Get the existing node
+ m.nodeLock.RLock()
+ state := m.nodeMap[m.config.Name]
+ m.nodeLock.RUnlock()
+
+ // Format a new alive message
+ a := alive{
+ Incarnation: m.nextIncarnation(),
+ Node: m.config.Name,
+ Addr: state.Addr,
+ Port: state.Port,
+ Meta: meta,
+ Vsn: []uint8{
+ ProtocolVersionMin, ProtocolVersionMax, m.config.ProtocolVersion,
+ m.config.DelegateProtocolMin, m.config.DelegateProtocolMax,
+ m.config.DelegateProtocolVersion,
+ },
+ }
+ notifyCh := make(chan struct{})
+ m.aliveNode(&a, notifyCh, true)
+
+ // Wait for the broadcast or a timeout
+ if m.anyAlive() {
+ var timeoutCh <-chan time.Time
+ if timeout > 0 {
+ timeoutCh = time.After(timeout)
+ }
+ select {
+ case <-notifyCh:
+ case <-timeoutCh:
+ return fmt.Errorf("timeout waiting for update broadcast")
+ }
+ }
+ return nil
+}
+
+// SendTo is deprecated in favor of SendBestEffort, which requires a node to
+// target.
+func (m *Memberlist) SendTo(to net.Addr, msg []byte) error {
+ // Encode as a user message
+ buf := make([]byte, 1, len(msg)+1)
+ buf[0] = byte(userMsg)
+ buf = append(buf, msg...)
+
+ // Send the message
+ return m.rawSendMsgPacket(to.String(), nil, buf)
+}
+
+// SendToUDP is deprecated in favor of SendBestEffort.
+func (m *Memberlist) SendToUDP(to *Node, msg []byte) error {
+ return m.SendBestEffort(to, msg)
+}
+
+// SendToTCP is deprecated in favor of SendReliable.
+func (m *Memberlist) SendToTCP(to *Node, msg []byte) error {
+ return m.SendReliable(to, msg)
+}
+
+// SendBestEffort uses the unreliable packet-oriented interface of the transport
+// to target a user message at the given node (this does not use the gossip
+// mechanism). The maximum size of the message depends on the configured
+// UDPBufferSize for this memberlist instance.
+func (m *Memberlist) SendBestEffort(to *Node, msg []byte) error {
+ // Encode as a user message
+ buf := make([]byte, 1, len(msg)+1)
+ buf[0] = byte(userMsg)
+ buf = append(buf, msg...)
+
+ // Send the message
+ return m.rawSendMsgPacket(to.Address(), to, buf)
+}
+
+// SendReliable uses the reliable stream-oriented interface of the transport to
+// target a user message at the given node (this does not use the gossip
+// mechanism). Delivery is guaranteed if no error is returned, and there is no
+// limit on the size of the message.
+func (m *Memberlist) SendReliable(to *Node, msg []byte) error {
+ return m.sendUserMsg(to.Address(), msg)
+}
+
+// Members returns a list of all known live nodes. The node structures
+// returned must not be modified. If you wish to modify a Node, make a
+// copy first.
+func (m *Memberlist) Members() []*Node {
+ m.nodeLock.RLock()
+ defer m.nodeLock.RUnlock()
+
+ nodes := make([]*Node, 0, len(m.nodes))
+ for _, n := range m.nodes {
+ if n.State != stateDead {
+ nodes = append(nodes, &n.Node)
+ }
+ }
+
+ return nodes
+}
+
+// NumMembers returns the number of alive nodes currently known. Between
+// the time of calling this and calling Members, the number of alive nodes
+// may have changed, so this shouldn't be used to determine how many
+// members will be returned by Members.
+func (m *Memberlist) NumMembers() (alive int) {
+ m.nodeLock.RLock()
+ defer m.nodeLock.RUnlock()
+
+ for _, n := range m.nodes {
+ if n.State != stateDead {
+ alive++
+ }
+ }
+
+ return
+}
+
+// Leave will broadcast a leave message but will not shutdown the background
+// listeners, meaning the node will continue participating in gossip and state
+// updates.
+//
+// This will block until the leave message is successfully broadcasted to
+// a member of the cluster, if any exist or until a specified timeout
+// is reached.
+//
+// This method is safe to call multiple times, but must not be called
+// after the cluster is already shut down.
+func (m *Memberlist) Leave(timeout time.Duration) error {
+ m.leaveLock.Lock()
+ defer m.leaveLock.Unlock()
+
+ if m.hasShutdown() {
+ panic("leave after shutdown")
+ }
+
+ if !m.hasLeft() {
+ atomic.StoreInt32(&m.leave, 1)
+
+ m.nodeLock.Lock()
+ state, ok := m.nodeMap[m.config.Name]
+ m.nodeLock.Unlock()
+ if !ok {
+ m.logger.Printf("[WARN] memberlist: Leave but we're not in the node map.")
+ return nil
+ }
+
+ d := dead{
+ Incarnation: state.Incarnation,
+ Node: state.Name,
+ }
+ m.deadNode(&d)
+
+ // Block until the broadcast goes out
+ if m.anyAlive() {
+ var timeoutCh <-chan time.Time
+ if timeout > 0 {
+ timeoutCh = time.After(timeout)
+ }
+ select {
+ case <-m.leaveBroadcast:
+ case <-timeoutCh:
+ return fmt.Errorf("timeout waiting for leave broadcast")
+ }
+ }
+ }
+
+ return nil
+}
+
+// Check for any other alive node.
+func (m *Memberlist) anyAlive() bool {
+ m.nodeLock.RLock()
+ defer m.nodeLock.RUnlock()
+ for _, n := range m.nodes {
+ if n.State != stateDead && n.Name != m.config.Name {
+ return true
+ }
+ }
+ return false
+}
+
+// GetHealthScore gives this instance's idea of how well it is meeting the soft
+// real-time requirements of the protocol. Lower numbers are better, and zero
+// means "totally healthy".
+func (m *Memberlist) GetHealthScore() int {
+ return m.awareness.GetHealthScore()
+}
+
+// ProtocolVersion returns the protocol version currently in use by
+// this memberlist.
+func (m *Memberlist) ProtocolVersion() uint8 {
+ // NOTE: This method exists so that in the future we can control
+ // any locking if necessary, if we change the protocol version at
+ // runtime, etc.
+ return m.config.ProtocolVersion
+}
+
+// Shutdown will stop any background maintanence of network activity
+// for this memberlist, causing it to appear "dead". A leave message
+// will not be broadcasted prior, so the cluster being left will have
+// to detect this node's shutdown using probing. If you wish to more
+// gracefully exit the cluster, call Leave prior to shutting down.
+//
+// This method is safe to call multiple times.
+func (m *Memberlist) Shutdown() error {
+ m.shutdownLock.Lock()
+ defer m.shutdownLock.Unlock()
+
+ if m.hasShutdown() {
+ return nil
+ }
+
+ // Shut down the transport first, which should block until it's
+ // completely torn down. If we kill the memberlist-side handlers
+ // those I/O handlers might get stuck.
+ m.transport.Shutdown()
+
+ // Now tear down everything else.
+ atomic.StoreInt32(&m.shutdown, 1)
+ close(m.shutdownCh)
+ m.deschedule()
+ return nil
+}
+
+func (m *Memberlist) hasShutdown() bool {
+ return atomic.LoadInt32(&m.shutdown) == 1
+}
+
+func (m *Memberlist) hasLeft() bool {
+ return atomic.LoadInt32(&m.leave) == 1
+}
--- /dev/null
+package memberlist
+
+// MergeDelegate is used to involve a client in
+// a potential cluster merge operation. Namely, when
+// a node does a TCP push/pull (as part of a join),
+// the delegate is involved and allowed to cancel the join
+// based on custom logic. The merge delegate is NOT invoked
+// as part of the push-pull anti-entropy.
+type MergeDelegate interface {
+ // NotifyMerge is invoked when a merge could take place.
+ // Provides a list of the nodes known by the peer. If
+ // the return value is non-nil, the merge is canceled.
+ NotifyMerge(peers []*Node) error
+}
--- /dev/null
+package memberlist
+
+import (
+ "fmt"
+ "net"
+ "strconv"
+ "time"
+)
+
+// MockNetwork is used as a factory that produces MockTransport instances which
+// are uniquely addressed and wired up to talk to each other.
+type MockNetwork struct {
+ transports map[string]*MockTransport
+ port int
+}
+
+// NewTransport returns a new MockTransport with a unique address, wired up to
+// talk to the other transports in the MockNetwork.
+func (n *MockNetwork) NewTransport() *MockTransport {
+ n.port += 1
+ addr := fmt.Sprintf("127.0.0.1:%d", n.port)
+ transport := &MockTransport{
+ net: n,
+ addr: &MockAddress{addr},
+ packetCh: make(chan *Packet),
+ streamCh: make(chan net.Conn),
+ }
+
+ if n.transports == nil {
+ n.transports = make(map[string]*MockTransport)
+ }
+ n.transports[addr] = transport
+ return transport
+}
+
+// MockAddress is a wrapper which adds the net.Addr interface to our mock
+// address scheme.
+type MockAddress struct {
+ addr string
+}
+
+// See net.Addr.
+func (a *MockAddress) Network() string {
+ return "mock"
+}
+
+// See net.Addr.
+func (a *MockAddress) String() string {
+ return a.addr
+}
+
+// MockTransport directly plumbs messages to other transports its MockNetwork.
+type MockTransport struct {
+ net *MockNetwork
+ addr *MockAddress
+ packetCh chan *Packet
+ streamCh chan net.Conn
+}
+
+// See Transport.
+func (t *MockTransport) FinalAdvertiseAddr(string, int) (net.IP, int, error) {
+ host, portStr, err := net.SplitHostPort(t.addr.String())
+ if err != nil {
+ return nil, 0, err
+ }
+
+ ip := net.ParseIP(host)
+ if ip == nil {
+ return nil, 0, fmt.Errorf("Failed to parse IP %q", host)
+ }
+
+ port, err := strconv.ParseInt(portStr, 10, 16)
+ if err != nil {
+ return nil, 0, err
+ }
+
+ return ip, int(port), nil
+}
+
+// See Transport.
+func (t *MockTransport) WriteTo(b []byte, addr string) (time.Time, error) {
+ dest, ok := t.net.transports[addr]
+ if !ok {
+ return time.Time{}, fmt.Errorf("No route to %q", addr)
+ }
+
+ now := time.Now()
+ dest.packetCh <- &Packet{
+ Buf: b,
+ From: t.addr,
+ Timestamp: now,
+ }
+ return now, nil
+}
+
+// See Transport.
+func (t *MockTransport) PacketCh() <-chan *Packet {
+ return t.packetCh
+}
+
+// See Transport.
+func (t *MockTransport) DialTimeout(addr string, timeout time.Duration) (net.Conn, error) {
+ dest, ok := t.net.transports[addr]
+ if !ok {
+ return nil, fmt.Errorf("No route to %q", addr)
+ }
+
+ p1, p2 := net.Pipe()
+ dest.streamCh <- p1
+ return p2, nil
+}
+
+// See Transport.
+func (t *MockTransport) StreamCh() <-chan net.Conn {
+ return t.streamCh
+}
+
+// See Transport.
+func (t *MockTransport) Shutdown() error {
+ return nil
+}
--- /dev/null
+package memberlist
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "hash/crc32"
+ "io"
+ "net"
+ "time"
+
+ "github.com/armon/go-metrics"
+ "github.com/hashicorp/go-msgpack/codec"
+)
+
+// This is the minimum and maximum protocol version that we can
+// _understand_. We're allowed to speak at any version within this
+// range. This range is inclusive.
+const (
+ ProtocolVersionMin uint8 = 1
+
+ // Version 3 added support for TCP pings but we kept the default
+ // protocol version at 2 to ease transition to this new feature.
+ // A memberlist speaking version 2 of the protocol will attempt
+ // to TCP ping another memberlist who understands version 3 or
+ // greater.
+ //
+ // Version 4 added support for nacks as part of indirect probes.
+ // A memberlist speaking version 2 of the protocol will expect
+ // nacks from another memberlist who understands version 4 or
+ // greater, and likewise nacks will be sent to memberlists who
+ // understand version 4 or greater.
+ ProtocolVersion2Compatible = 2
+
+ ProtocolVersionMax = 5
+)
+
+// messageType is an integer ID of a type of message that can be received
+// on network channels from other members.
+type messageType uint8
+
+// The list of available message types.
+const (
+ pingMsg messageType = iota
+ indirectPingMsg
+ ackRespMsg
+ suspectMsg
+ aliveMsg
+ deadMsg
+ pushPullMsg
+ compoundMsg
+ userMsg // User mesg, not handled by us
+ compressMsg
+ encryptMsg
+ nackRespMsg
+ hasCrcMsg
+ errMsg
+)
+
+// compressionType is used to specify the compression algorithm
+type compressionType uint8
+
+const (
+ lzwAlgo compressionType = iota
+)
+
+const (
+ MetaMaxSize = 512 // Maximum size for node meta data
+ compoundHeaderOverhead = 2 // Assumed header overhead
+ compoundOverhead = 2 // Assumed overhead per entry in compoundHeader
+ userMsgOverhead = 1
+ blockingWarning = 10 * time.Millisecond // Warn if a UDP packet takes this long to process
+ maxPushStateBytes = 10 * 1024 * 1024
+)
+
+// ping request sent directly to node
+type ping struct {
+ SeqNo uint32
+
+ // Node is sent so the target can verify they are
+ // the intended recipient. This is to protect again an agent
+ // restart with a new name.
+ Node string
+}
+
+// indirect ping sent to an indirect ndoe
+type indirectPingReq struct {
+ SeqNo uint32
+ Target []byte
+ Port uint16
+ Node string
+ Nack bool // true if we'd like a nack back
+}
+
+// ack response is sent for a ping
+type ackResp struct {
+ SeqNo uint32
+ Payload []byte
+}
+
+// nack response is sent for an indirect ping when the pinger doesn't hear from
+// the ping-ee within the configured timeout. This lets the original node know
+// that the indirect ping attempt happened but didn't succeed.
+type nackResp struct {
+ SeqNo uint32
+}
+
+// err response is sent to relay the error from the remote end
+type errResp struct {
+ Error string
+}
+
+// suspect is broadcast when we suspect a node is dead
+type suspect struct {
+ Incarnation uint32
+ Node string
+ From string // Include who is suspecting
+}
+
+// alive is broadcast when we know a node is alive.
+// Overloaded for nodes joining
+type alive struct {
+ Incarnation uint32
+ Node string
+ Addr []byte
+ Port uint16
+ Meta []byte
+
+ // The versions of the protocol/delegate that are being spoken, order:
+ // pmin, pmax, pcur, dmin, dmax, dcur
+ Vsn []uint8
+}
+
+// dead is broadcast when we confirm a node is dead
+// Overloaded for nodes leaving
+type dead struct {
+ Incarnation uint32
+ Node string
+ From string // Include who is suspecting
+}
+
+// pushPullHeader is used to inform the
+// otherside how many states we are transferring
+type pushPullHeader struct {
+ Nodes int
+ UserStateLen int // Encodes the byte lengh of user state
+ Join bool // Is this a join request or a anti-entropy run
+}
+
+// userMsgHeader is used to encapsulate a userMsg
+type userMsgHeader struct {
+ UserMsgLen int // Encodes the byte lengh of user state
+}
+
+// pushNodeState is used for pushPullReq when we are
+// transferring out node states
+type pushNodeState struct {
+ Name string
+ Addr []byte
+ Port uint16
+ Meta []byte
+ Incarnation uint32
+ State nodeStateType
+ Vsn []uint8 // Protocol versions
+}
+
+// compress is used to wrap an underlying payload
+// using a specified compression algorithm
+type compress struct {
+ Algo compressionType
+ Buf []byte
+}
+
+// msgHandoff is used to transfer a message between goroutines
+type msgHandoff struct {
+ msgType messageType
+ buf []byte
+ from net.Addr
+}
+
+// encryptionVersion returns the encryption version to use
+func (m *Memberlist) encryptionVersion() encryptionVersion {
+ switch m.ProtocolVersion() {
+ case 1:
+ return 0
+ default:
+ return 1
+ }
+}
+
+// streamListen is a long running goroutine that pulls incoming streams from the
+// transport and hands them off for processing.
+func (m *Memberlist) streamListen() {
+ for {
+ select {
+ case conn := <-m.transport.StreamCh():
+ go m.handleConn(conn)
+
+ case <-m.shutdownCh:
+ return
+ }
+ }
+}
+
+// handleConn handles a single incoming stream connection from the transport.
+func (m *Memberlist) handleConn(conn net.Conn) {
+ m.logger.Printf("[DEBUG] memberlist: Stream connection %s", LogConn(conn))
+
+ defer conn.Close()
+ metrics.IncrCounter([]string{"memberlist", "tcp", "accept"}, 1)
+
+ conn.SetDeadline(time.Now().Add(m.config.TCPTimeout))
+ msgType, bufConn, dec, err := m.readStream(conn)
+ if err != nil {
+ if err != io.EOF {
+ m.logger.Printf("[ERR] memberlist: failed to receive: %s %s", err, LogConn(conn))
+
+ resp := errResp{err.Error()}
+ out, err := encode(errMsg, &resp)
+ if err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to encode error response: %s", err)
+ return
+ }
+
+ err = m.rawSendMsgStream(conn, out.Bytes())
+ if err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to send error: %s %s", err, LogConn(conn))
+ return
+ }
+ }
+ return
+ }
+
+ switch msgType {
+ case userMsg:
+ if err := m.readUserMsg(bufConn, dec); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to receive user message: %s %s", err, LogConn(conn))
+ }
+ case pushPullMsg:
+ join, remoteNodes, userState, err := m.readRemoteState(bufConn, dec)
+ if err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to read remote state: %s %s", err, LogConn(conn))
+ return
+ }
+
+ if err := m.sendLocalState(conn, join); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to push local state: %s %s", err, LogConn(conn))
+ return
+ }
+
+ if err := m.mergeRemoteState(join, remoteNodes, userState); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed push/pull merge: %s %s", err, LogConn(conn))
+ return
+ }
+ case pingMsg:
+ var p ping
+ if err := dec.Decode(&p); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to decode ping: %s %s", err, LogConn(conn))
+ return
+ }
+
+ if p.Node != "" && p.Node != m.config.Name {
+ m.logger.Printf("[WARN] memberlist: Got ping for unexpected node %s %s", p.Node, LogConn(conn))
+ return
+ }
+
+ ack := ackResp{p.SeqNo, nil}
+ out, err := encode(ackRespMsg, &ack)
+ if err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to encode ack: %s", err)
+ return
+ }
+
+ err = m.rawSendMsgStream(conn, out.Bytes())
+ if err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to send ack: %s %s", err, LogConn(conn))
+ return
+ }
+ default:
+ m.logger.Printf("[ERR] memberlist: Received invalid msgType (%d) %s", msgType, LogConn(conn))
+ }
+}
+
+// packetListen is a long running goroutine that pulls packets out of the
+// transport and hands them off for processing.
+func (m *Memberlist) packetListen() {
+ for {
+ select {
+ case packet := <-m.transport.PacketCh():
+ m.ingestPacket(packet.Buf, packet.From, packet.Timestamp)
+
+ case <-m.shutdownCh:
+ return
+ }
+ }
+}
+
+func (m *Memberlist) ingestPacket(buf []byte, from net.Addr, timestamp time.Time) {
+ // Check if encryption is enabled
+ if m.config.EncryptionEnabled() {
+ // Decrypt the payload
+ plain, err := decryptPayload(m.config.Keyring.GetKeys(), buf, nil)
+ if err != nil {
+ if !m.config.GossipVerifyIncoming {
+ // Treat the message as plaintext
+ plain = buf
+ } else {
+ m.logger.Printf("[ERR] memberlist: Decrypt packet failed: %v %s", err, LogAddress(from))
+ return
+ }
+ }
+
+ // Continue processing the plaintext buffer
+ buf = plain
+ }
+
+ // See if there's a checksum included to verify the contents of the message
+ if len(buf) >= 5 && messageType(buf[0]) == hasCrcMsg {
+ crc := crc32.ChecksumIEEE(buf[5:])
+ expected := binary.BigEndian.Uint32(buf[1:5])
+ if crc != expected {
+ m.logger.Printf("[WARN] memberlist: Got invalid checksum for UDP packet: %x, %x", crc, expected)
+ return
+ }
+ m.handleCommand(buf[5:], from, timestamp)
+ } else {
+ m.handleCommand(buf, from, timestamp)
+ }
+}
+
+func (m *Memberlist) handleCommand(buf []byte, from net.Addr, timestamp time.Time) {
+ // Decode the message type
+ msgType := messageType(buf[0])
+ buf = buf[1:]
+
+ // Switch on the msgType
+ switch msgType {
+ case compoundMsg:
+ m.handleCompound(buf, from, timestamp)
+ case compressMsg:
+ m.handleCompressed(buf, from, timestamp)
+
+ case pingMsg:
+ m.handlePing(buf, from)
+ case indirectPingMsg:
+ m.handleIndirectPing(buf, from)
+ case ackRespMsg:
+ m.handleAck(buf, from, timestamp)
+ case nackRespMsg:
+ m.handleNack(buf, from)
+
+ case suspectMsg:
+ fallthrough
+ case aliveMsg:
+ fallthrough
+ case deadMsg:
+ fallthrough
+ case userMsg:
+ select {
+ case m.handoff <- msgHandoff{msgType, buf, from}:
+ default:
+ m.logger.Printf("[WARN] memberlist: handler queue full, dropping message (%d) %s", msgType, LogAddress(from))
+ }
+
+ default:
+ m.logger.Printf("[ERR] memberlist: msg type (%d) not supported %s", msgType, LogAddress(from))
+ }
+}
+
+// packetHandler is a long running goroutine that processes messages received
+// over the packet interface, but is decoupled from the listener to avoid
+// blocking the listener which may cause ping/ack messages to be delayed.
+func (m *Memberlist) packetHandler() {
+ for {
+ select {
+ case msg := <-m.handoff:
+ msgType := msg.msgType
+ buf := msg.buf
+ from := msg.from
+
+ switch msgType {
+ case suspectMsg:
+ m.handleSuspect(buf, from)
+ case aliveMsg:
+ m.handleAlive(buf, from)
+ case deadMsg:
+ m.handleDead(buf, from)
+ case userMsg:
+ m.handleUser(buf, from)
+ default:
+ m.logger.Printf("[ERR] memberlist: Message type (%d) not supported %s (packet handler)", msgType, LogAddress(from))
+ }
+
+ case <-m.shutdownCh:
+ return
+ }
+ }
+}
+
+func (m *Memberlist) handleCompound(buf []byte, from net.Addr, timestamp time.Time) {
+ // Decode the parts
+ trunc, parts, err := decodeCompoundMessage(buf)
+ if err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to decode compound request: %s %s", err, LogAddress(from))
+ return
+ }
+
+ // Log any truncation
+ if trunc > 0 {
+ m.logger.Printf("[WARN] memberlist: Compound request had %d truncated messages %s", trunc, LogAddress(from))
+ }
+
+ // Handle each message
+ for _, part := range parts {
+ m.handleCommand(part, from, timestamp)
+ }
+}
+
+func (m *Memberlist) handlePing(buf []byte, from net.Addr) {
+ var p ping
+ if err := decode(buf, &p); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to decode ping request: %s %s", err, LogAddress(from))
+ return
+ }
+ // If node is provided, verify that it is for us
+ if p.Node != "" && p.Node != m.config.Name {
+ m.logger.Printf("[WARN] memberlist: Got ping for unexpected node '%s' %s", p.Node, LogAddress(from))
+ return
+ }
+ var ack ackResp
+ ack.SeqNo = p.SeqNo
+ if m.config.Ping != nil {
+ ack.Payload = m.config.Ping.AckPayload()
+ }
+ if err := m.encodeAndSendMsg(from.String(), ackRespMsg, &ack); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to send ack: %s %s", err, LogAddress(from))
+ }
+}
+
+func (m *Memberlist) handleIndirectPing(buf []byte, from net.Addr) {
+ var ind indirectPingReq
+ if err := decode(buf, &ind); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to decode indirect ping request: %s %s", err, LogAddress(from))
+ return
+ }
+
+ // For proto versions < 2, there is no port provided. Mask old
+ // behavior by using the configured port.
+ if m.ProtocolVersion() < 2 || ind.Port == 0 {
+ ind.Port = uint16(m.config.BindPort)
+ }
+
+ // Send a ping to the correct host.
+ localSeqNo := m.nextSeqNo()
+ ping := ping{SeqNo: localSeqNo, Node: ind.Node}
+
+ // Setup a response handler to relay the ack
+ cancelCh := make(chan struct{})
+ respHandler := func(payload []byte, timestamp time.Time) {
+ // Try to prevent the nack if we've caught it in time.
+ close(cancelCh)
+
+ // Forward the ack back to the requestor.
+ ack := ackResp{ind.SeqNo, nil}
+ if err := m.encodeAndSendMsg(from.String(), ackRespMsg, &ack); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to forward ack: %s %s", err, LogAddress(from))
+ }
+ }
+ m.setAckHandler(localSeqNo, respHandler, m.config.ProbeTimeout)
+
+ // Send the ping.
+ addr := joinHostPort(net.IP(ind.Target).String(), ind.Port)
+ if err := m.encodeAndSendMsg(addr, pingMsg, &ping); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to send ping: %s %s", err, LogAddress(from))
+ }
+
+ // Setup a timer to fire off a nack if no ack is seen in time.
+ if ind.Nack {
+ go func() {
+ select {
+ case <-cancelCh:
+ return
+ case <-time.After(m.config.ProbeTimeout):
+ nack := nackResp{ind.SeqNo}
+ if err := m.encodeAndSendMsg(from.String(), nackRespMsg, &nack); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to send nack: %s %s", err, LogAddress(from))
+ }
+ }
+ }()
+ }
+}
+
+func (m *Memberlist) handleAck(buf []byte, from net.Addr, timestamp time.Time) {
+ var ack ackResp
+ if err := decode(buf, &ack); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to decode ack response: %s %s", err, LogAddress(from))
+ return
+ }
+ m.invokeAckHandler(ack, timestamp)
+}
+
+func (m *Memberlist) handleNack(buf []byte, from net.Addr) {
+ var nack nackResp
+ if err := decode(buf, &nack); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to decode nack response: %s %s", err, LogAddress(from))
+ return
+ }
+ m.invokeNackHandler(nack)
+}
+
+func (m *Memberlist) handleSuspect(buf []byte, from net.Addr) {
+ var sus suspect
+ if err := decode(buf, &sus); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to decode suspect message: %s %s", err, LogAddress(from))
+ return
+ }
+ m.suspectNode(&sus)
+}
+
+func (m *Memberlist) handleAlive(buf []byte, from net.Addr) {
+ var live alive
+ if err := decode(buf, &live); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to decode alive message: %s %s", err, LogAddress(from))
+ return
+ }
+
+ // For proto versions < 2, there is no port provided. Mask old
+ // behavior by using the configured port
+ if m.ProtocolVersion() < 2 || live.Port == 0 {
+ live.Port = uint16(m.config.BindPort)
+ }
+
+ m.aliveNode(&live, nil, false)
+}
+
+func (m *Memberlist) handleDead(buf []byte, from net.Addr) {
+ var d dead
+ if err := decode(buf, &d); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to decode dead message: %s %s", err, LogAddress(from))
+ return
+ }
+ m.deadNode(&d)
+}
+
+// handleUser is used to notify channels of incoming user data
+func (m *Memberlist) handleUser(buf []byte, from net.Addr) {
+ d := m.config.Delegate
+ if d != nil {
+ d.NotifyMsg(buf)
+ }
+}
+
+// handleCompressed is used to unpack a compressed message
+func (m *Memberlist) handleCompressed(buf []byte, from net.Addr, timestamp time.Time) {
+ // Try to decode the payload
+ payload, err := decompressPayload(buf)
+ if err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to decompress payload: %v %s", err, LogAddress(from))
+ return
+ }
+
+ // Recursively handle the payload
+ m.handleCommand(payload, from, timestamp)
+}
+
+// encodeAndSendMsg is used to combine the encoding and sending steps
+func (m *Memberlist) encodeAndSendMsg(addr string, msgType messageType, msg interface{}) error {
+ out, err := encode(msgType, msg)
+ if err != nil {
+ return err
+ }
+ if err := m.sendMsg(addr, out.Bytes()); err != nil {
+ return err
+ }
+ return nil
+}
+
+// sendMsg is used to send a message via packet to another host. It will
+// opportunistically create a compoundMsg and piggy back other broadcasts.
+func (m *Memberlist) sendMsg(addr string, msg []byte) error {
+ // Check if we can piggy back any messages
+ bytesAvail := m.config.UDPBufferSize - len(msg) - compoundHeaderOverhead
+ if m.config.EncryptionEnabled() && m.config.GossipVerifyOutgoing {
+ bytesAvail -= encryptOverhead(m.encryptionVersion())
+ }
+ extra := m.getBroadcasts(compoundOverhead, bytesAvail)
+
+ // Fast path if nothing to piggypack
+ if len(extra) == 0 {
+ return m.rawSendMsgPacket(addr, nil, msg)
+ }
+
+ // Join all the messages
+ msgs := make([][]byte, 0, 1+len(extra))
+ msgs = append(msgs, msg)
+ msgs = append(msgs, extra...)
+
+ // Create a compound message
+ compound := makeCompoundMessage(msgs)
+
+ // Send the message
+ return m.rawSendMsgPacket(addr, nil, compound.Bytes())
+}
+
+// rawSendMsgPacket is used to send message via packet to another host without
+// modification, other than compression or encryption if enabled.
+func (m *Memberlist) rawSendMsgPacket(addr string, node *Node, msg []byte) error {
+ // Check if we have compression enabled
+ if m.config.EnableCompression {
+ buf, err := compressPayload(msg)
+ if err != nil {
+ m.logger.Printf("[WARN] memberlist: Failed to compress payload: %v", err)
+ } else {
+ // Only use compression if it reduced the size
+ if buf.Len() < len(msg) {
+ msg = buf.Bytes()
+ }
+ }
+ }
+
+ // Try to look up the destination node
+ if node == nil {
+ toAddr, _, err := net.SplitHostPort(addr)
+ if err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to parse address %q: %v", addr, err)
+ return err
+ }
+ m.nodeLock.RLock()
+ nodeState, ok := m.nodeMap[toAddr]
+ m.nodeLock.RUnlock()
+ if ok {
+ node = &nodeState.Node
+ }
+ }
+
+ // Add a CRC to the end of the payload if the recipient understands
+ // ProtocolVersion >= 5
+ if node != nil && node.PMax >= 5 {
+ crc := crc32.ChecksumIEEE(msg)
+ header := make([]byte, 5, 5+len(msg))
+ header[0] = byte(hasCrcMsg)
+ binary.BigEndian.PutUint32(header[1:], crc)
+ msg = append(header, msg...)
+ }
+
+ // Check if we have encryption enabled
+ if m.config.EncryptionEnabled() && m.config.GossipVerifyOutgoing {
+ // Encrypt the payload
+ var buf bytes.Buffer
+ primaryKey := m.config.Keyring.GetPrimaryKey()
+ err := encryptPayload(m.encryptionVersion(), primaryKey, msg, nil, &buf)
+ if err != nil {
+ m.logger.Printf("[ERR] memberlist: Encryption of message failed: %v", err)
+ return err
+ }
+ msg = buf.Bytes()
+ }
+
+ metrics.IncrCounter([]string{"memberlist", "udp", "sent"}, float32(len(msg)))
+ _, err := m.transport.WriteTo(msg, addr)
+ return err
+}
+
+// rawSendMsgStream is used to stream a message to another host without
+// modification, other than applying compression and encryption if enabled.
+func (m *Memberlist) rawSendMsgStream(conn net.Conn, sendBuf []byte) error {
+ // Check if compresion is enabled
+ if m.config.EnableCompression {
+ compBuf, err := compressPayload(sendBuf)
+ if err != nil {
+ m.logger.Printf("[ERROR] memberlist: Failed to compress payload: %v", err)
+ } else {
+ sendBuf = compBuf.Bytes()
+ }
+ }
+
+ // Check if encryption is enabled
+ if m.config.EncryptionEnabled() && m.config.GossipVerifyOutgoing {
+ crypt, err := m.encryptLocalState(sendBuf)
+ if err != nil {
+ m.logger.Printf("[ERROR] memberlist: Failed to encrypt local state: %v", err)
+ return err
+ }
+ sendBuf = crypt
+ }
+
+ // Write out the entire send buffer
+ metrics.IncrCounter([]string{"memberlist", "tcp", "sent"}, float32(len(sendBuf)))
+
+ if n, err := conn.Write(sendBuf); err != nil {
+ return err
+ } else if n != len(sendBuf) {
+ return fmt.Errorf("only %d of %d bytes written", n, len(sendBuf))
+ }
+
+ return nil
+}
+
+// sendUserMsg is used to stream a user message to another host.
+func (m *Memberlist) sendUserMsg(addr string, sendBuf []byte) error {
+ conn, err := m.transport.DialTimeout(addr, m.config.TCPTimeout)
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+
+ bufConn := bytes.NewBuffer(nil)
+ if err := bufConn.WriteByte(byte(userMsg)); err != nil {
+ return err
+ }
+
+ header := userMsgHeader{UserMsgLen: len(sendBuf)}
+ hd := codec.MsgpackHandle{}
+ enc := codec.NewEncoder(bufConn, &hd)
+ if err := enc.Encode(&header); err != nil {
+ return err
+ }
+ if _, err := bufConn.Write(sendBuf); err != nil {
+ return err
+ }
+ return m.rawSendMsgStream(conn, bufConn.Bytes())
+}
+
+// sendAndReceiveState is used to initiate a push/pull over a stream with a
+// remote host.
+func (m *Memberlist) sendAndReceiveState(addr string, join bool) ([]pushNodeState, []byte, error) {
+ // Attempt to connect
+ conn, err := m.transport.DialTimeout(addr, m.config.TCPTimeout)
+ if err != nil {
+ return nil, nil, err
+ }
+ defer conn.Close()
+ m.logger.Printf("[DEBUG] memberlist: Initiating push/pull sync with: %s", conn.RemoteAddr())
+ metrics.IncrCounter([]string{"memberlist", "tcp", "connect"}, 1)
+
+ // Send our state
+ if err := m.sendLocalState(conn, join); err != nil {
+ return nil, nil, err
+ }
+
+ conn.SetDeadline(time.Now().Add(m.config.TCPTimeout))
+ msgType, bufConn, dec, err := m.readStream(conn)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ if msgType == errMsg {
+ var resp errResp
+ if err := dec.Decode(&resp); err != nil {
+ return nil, nil, err
+ }
+ return nil, nil, fmt.Errorf("remote error: %v", resp.Error)
+ }
+
+ // Quit if not push/pull
+ if msgType != pushPullMsg {
+ err := fmt.Errorf("received invalid msgType (%d), expected pushPullMsg (%d) %s", msgType, pushPullMsg, LogConn(conn))
+ return nil, nil, err
+ }
+
+ // Read remote state
+ _, remoteNodes, userState, err := m.readRemoteState(bufConn, dec)
+ return remoteNodes, userState, err
+}
+
+// sendLocalState is invoked to send our local state over a stream connection.
+func (m *Memberlist) sendLocalState(conn net.Conn, join bool) error {
+ // Setup a deadline
+ conn.SetDeadline(time.Now().Add(m.config.TCPTimeout))
+
+ // Prepare the local node state
+ m.nodeLock.RLock()
+ localNodes := make([]pushNodeState, len(m.nodes))
+ for idx, n := range m.nodes {
+ localNodes[idx].Name = n.Name
+ localNodes[idx].Addr = n.Addr
+ localNodes[idx].Port = n.Port
+ localNodes[idx].Incarnation = n.Incarnation
+ localNodes[idx].State = n.State
+ localNodes[idx].Meta = n.Meta
+ localNodes[idx].Vsn = []uint8{
+ n.PMin, n.PMax, n.PCur,
+ n.DMin, n.DMax, n.DCur,
+ }
+ }
+ m.nodeLock.RUnlock()
+
+ // Get the delegate state
+ var userData []byte
+ if m.config.Delegate != nil {
+ userData = m.config.Delegate.LocalState(join)
+ }
+
+ // Create a bytes buffer writer
+ bufConn := bytes.NewBuffer(nil)
+
+ // Send our node state
+ header := pushPullHeader{Nodes: len(localNodes), UserStateLen: len(userData), Join: join}
+ hd := codec.MsgpackHandle{}
+ enc := codec.NewEncoder(bufConn, &hd)
+
+ // Begin state push
+ if _, err := bufConn.Write([]byte{byte(pushPullMsg)}); err != nil {
+ return err
+ }
+
+ if err := enc.Encode(&header); err != nil {
+ return err
+ }
+ for i := 0; i < header.Nodes; i++ {
+ if err := enc.Encode(&localNodes[i]); err != nil {
+ return err
+ }
+ }
+
+ // Write the user state as well
+ if userData != nil {
+ if _, err := bufConn.Write(userData); err != nil {
+ return err
+ }
+ }
+
+ // Get the send buffer
+ return m.rawSendMsgStream(conn, bufConn.Bytes())
+}
+
+// encryptLocalState is used to help encrypt local state before sending
+func (m *Memberlist) encryptLocalState(sendBuf []byte) ([]byte, error) {
+ var buf bytes.Buffer
+
+ // Write the encryptMsg byte
+ buf.WriteByte(byte(encryptMsg))
+
+ // Write the size of the message
+ sizeBuf := make([]byte, 4)
+ encVsn := m.encryptionVersion()
+ encLen := encryptedLength(encVsn, len(sendBuf))
+ binary.BigEndian.PutUint32(sizeBuf, uint32(encLen))
+ buf.Write(sizeBuf)
+
+ // Write the encrypted cipher text to the buffer
+ key := m.config.Keyring.GetPrimaryKey()
+ err := encryptPayload(encVsn, key, sendBuf, buf.Bytes()[:5], &buf)
+ if err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+// decryptRemoteState is used to help decrypt the remote state
+func (m *Memberlist) decryptRemoteState(bufConn io.Reader) ([]byte, error) {
+ // Read in enough to determine message length
+ cipherText := bytes.NewBuffer(nil)
+ cipherText.WriteByte(byte(encryptMsg))
+ _, err := io.CopyN(cipherText, bufConn, 4)
+ if err != nil {
+ return nil, err
+ }
+
+ // Ensure we aren't asked to download too much. This is to guard against
+ // an attack vector where a huge amount of state is sent
+ moreBytes := binary.BigEndian.Uint32(cipherText.Bytes()[1:5])
+ if moreBytes > maxPushStateBytes {
+ return nil, fmt.Errorf("Remote node state is larger than limit (%d)", moreBytes)
+ }
+
+ // Read in the rest of the payload
+ _, err = io.CopyN(cipherText, bufConn, int64(moreBytes))
+ if err != nil {
+ return nil, err
+ }
+
+ // Decrypt the cipherText
+ dataBytes := cipherText.Bytes()[:5]
+ cipherBytes := cipherText.Bytes()[5:]
+
+ // Decrypt the payload
+ keys := m.config.Keyring.GetKeys()
+ return decryptPayload(keys, cipherBytes, dataBytes)
+}
+
+// readStream is used to read from a stream connection, decrypting and
+// decompressing the stream if necessary.
+func (m *Memberlist) readStream(conn net.Conn) (messageType, io.Reader, *codec.Decoder, error) {
+ // Created a buffered reader
+ var bufConn io.Reader = bufio.NewReader(conn)
+
+ // Read the message type
+ buf := [1]byte{0}
+ if _, err := bufConn.Read(buf[:]); err != nil {
+ return 0, nil, nil, err
+ }
+ msgType := messageType(buf[0])
+
+ // Check if the message is encrypted
+ if msgType == encryptMsg {
+ if !m.config.EncryptionEnabled() {
+ return 0, nil, nil,
+ fmt.Errorf("Remote state is encrypted and encryption is not configured")
+ }
+
+ plain, err := m.decryptRemoteState(bufConn)
+ if err != nil {
+ return 0, nil, nil, err
+ }
+
+ // Reset message type and bufConn
+ msgType = messageType(plain[0])
+ bufConn = bytes.NewReader(plain[1:])
+ } else if m.config.EncryptionEnabled() && m.config.GossipVerifyIncoming {
+ return 0, nil, nil,
+ fmt.Errorf("Encryption is configured but remote state is not encrypted")
+ }
+
+ // Get the msgPack decoders
+ hd := codec.MsgpackHandle{}
+ dec := codec.NewDecoder(bufConn, &hd)
+
+ // Check if we have a compressed message
+ if msgType == compressMsg {
+ var c compress
+ if err := dec.Decode(&c); err != nil {
+ return 0, nil, nil, err
+ }
+ decomp, err := decompressBuffer(&c)
+ if err != nil {
+ return 0, nil, nil, err
+ }
+
+ // Reset the message type
+ msgType = messageType(decomp[0])
+
+ // Create a new bufConn
+ bufConn = bytes.NewReader(decomp[1:])
+
+ // Create a new decoder
+ dec = codec.NewDecoder(bufConn, &hd)
+ }
+
+ return msgType, bufConn, dec, nil
+}
+
+// readRemoteState is used to read the remote state from a connection
+func (m *Memberlist) readRemoteState(bufConn io.Reader, dec *codec.Decoder) (bool, []pushNodeState, []byte, error) {
+ // Read the push/pull header
+ var header pushPullHeader
+ if err := dec.Decode(&header); err != nil {
+ return false, nil, nil, err
+ }
+
+ // Allocate space for the transfer
+ remoteNodes := make([]pushNodeState, header.Nodes)
+
+ // Try to decode all the states
+ for i := 0; i < header.Nodes; i++ {
+ if err := dec.Decode(&remoteNodes[i]); err != nil {
+ return false, nil, nil, err
+ }
+ }
+
+ // Read the remote user state into a buffer
+ var userBuf []byte
+ if header.UserStateLen > 0 {
+ userBuf = make([]byte, header.UserStateLen)
+ bytes, err := io.ReadAtLeast(bufConn, userBuf, header.UserStateLen)
+ if err == nil && bytes != header.UserStateLen {
+ err = fmt.Errorf(
+ "Failed to read full user state (%d / %d)",
+ bytes, header.UserStateLen)
+ }
+ if err != nil {
+ return false, nil, nil, err
+ }
+ }
+
+ // For proto versions < 2, there is no port provided. Mask old
+ // behavior by using the configured port
+ for idx := range remoteNodes {
+ if m.ProtocolVersion() < 2 || remoteNodes[idx].Port == 0 {
+ remoteNodes[idx].Port = uint16(m.config.BindPort)
+ }
+ }
+
+ return header.Join, remoteNodes, userBuf, nil
+}
+
+// mergeRemoteState is used to merge the remote state with our local state
+func (m *Memberlist) mergeRemoteState(join bool, remoteNodes []pushNodeState, userBuf []byte) error {
+ if err := m.verifyProtocol(remoteNodes); err != nil {
+ return err
+ }
+
+ // Invoke the merge delegate if any
+ if join && m.config.Merge != nil {
+ nodes := make([]*Node, len(remoteNodes))
+ for idx, n := range remoteNodes {
+ nodes[idx] = &Node{
+ Name: n.Name,
+ Addr: n.Addr,
+ Port: n.Port,
+ Meta: n.Meta,
+ PMin: n.Vsn[0],
+ PMax: n.Vsn[1],
+ PCur: n.Vsn[2],
+ DMin: n.Vsn[3],
+ DMax: n.Vsn[4],
+ DCur: n.Vsn[5],
+ }
+ }
+ if err := m.config.Merge.NotifyMerge(nodes); err != nil {
+ return err
+ }
+ }
+
+ // Merge the membership state
+ m.mergeState(remoteNodes)
+
+ // Invoke the delegate for user state
+ if userBuf != nil && m.config.Delegate != nil {
+ m.config.Delegate.MergeRemoteState(userBuf, join)
+ }
+ return nil
+}
+
+// readUserMsg is used to decode a userMsg from a stream.
+func (m *Memberlist) readUserMsg(bufConn io.Reader, dec *codec.Decoder) error {
+ // Read the user message header
+ var header userMsgHeader
+ if err := dec.Decode(&header); err != nil {
+ return err
+ }
+
+ // Read the user message into a buffer
+ var userBuf []byte
+ if header.UserMsgLen > 0 {
+ userBuf = make([]byte, header.UserMsgLen)
+ bytes, err := io.ReadAtLeast(bufConn, userBuf, header.UserMsgLen)
+ if err == nil && bytes != header.UserMsgLen {
+ err = fmt.Errorf(
+ "Failed to read full user message (%d / %d)",
+ bytes, header.UserMsgLen)
+ }
+ if err != nil {
+ return err
+ }
+
+ d := m.config.Delegate
+ if d != nil {
+ d.NotifyMsg(userBuf)
+ }
+ }
+
+ return nil
+}
+
+// sendPingAndWaitForAck makes a stream connection to the given address, sends
+// a ping, and waits for an ack. All of this is done as a series of blocking
+// operations, given the deadline. The bool return parameter is true if we
+// we able to round trip a ping to the other node.
+func (m *Memberlist) sendPingAndWaitForAck(addr string, ping ping, deadline time.Time) (bool, error) {
+ conn, err := m.transport.DialTimeout(addr, m.config.TCPTimeout)
+ if err != nil {
+ // If the node is actually dead we expect this to fail, so we
+ // shouldn't spam the logs with it. After this point, errors
+ // with the connection are real, unexpected errors and should
+ // get propagated up.
+ return false, nil
+ }
+ defer conn.Close()
+ conn.SetDeadline(deadline)
+
+ out, err := encode(pingMsg, &ping)
+ if err != nil {
+ return false, err
+ }
+
+ if err = m.rawSendMsgStream(conn, out.Bytes()); err != nil {
+ return false, err
+ }
+
+ msgType, _, dec, err := m.readStream(conn)
+ if err != nil {
+ return false, err
+ }
+
+ if msgType != ackRespMsg {
+ return false, fmt.Errorf("Unexpected msgType (%d) from ping %s", msgType, LogConn(conn))
+ }
+
+ var ack ackResp
+ if err = dec.Decode(&ack); err != nil {
+ return false, err
+ }
+
+ if ack.SeqNo != ping.SeqNo {
+ return false, fmt.Errorf("Sequence number from ack (%d) doesn't match ping (%d)", ack.SeqNo, ping.SeqNo, LogConn(conn))
+ }
+
+ return true, nil
+}
--- /dev/null
+package memberlist
+
+import (
+ "fmt"
+ "log"
+ "net"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "github.com/armon/go-metrics"
+ sockaddr "github.com/hashicorp/go-sockaddr"
+)
+
+const (
+ // udpPacketBufSize is used to buffer incoming packets during read
+ // operations.
+ udpPacketBufSize = 65536
+
+ // udpRecvBufSize is a large buffer size that we attempt to set UDP
+ // sockets to in order to handle a large volume of messages.
+ udpRecvBufSize = 2 * 1024 * 1024
+)
+
+// NetTransportConfig is used to configure a net transport.
+type NetTransportConfig struct {
+ // BindAddrs is a list of addresses to bind to for both TCP and UDP
+ // communications.
+ BindAddrs []string
+
+ // BindPort is the port to listen on, for each address above.
+ BindPort int
+
+ // Logger is a logger for operator messages.
+ Logger *log.Logger
+}
+
+// NetTransport is a Transport implementation that uses connectionless UDP for
+// packet operations, and ad-hoc TCP connections for stream operations.
+type NetTransport struct {
+ config *NetTransportConfig
+ packetCh chan *Packet
+ streamCh chan net.Conn
+ logger *log.Logger
+ wg sync.WaitGroup
+ tcpListeners []*net.TCPListener
+ udpListeners []*net.UDPConn
+ shutdown int32
+}
+
+// NewNetTransport returns a net transport with the given configuration. On
+// success all the network listeners will be created and listening.
+func NewNetTransport(config *NetTransportConfig) (*NetTransport, error) {
+ // If we reject the empty list outright we can assume that there's at
+ // least one listener of each type later during operation.
+ if len(config.BindAddrs) == 0 {
+ return nil, fmt.Errorf("At least one bind address is required")
+ }
+
+ // Build out the new transport.
+ var ok bool
+ t := NetTransport{
+ config: config,
+ packetCh: make(chan *Packet),
+ streamCh: make(chan net.Conn),
+ logger: config.Logger,
+ }
+
+ // Clean up listeners if there's an error.
+ defer func() {
+ if !ok {
+ t.Shutdown()
+ }
+ }()
+
+ // Build all the TCP and UDP listeners.
+ port := config.BindPort
+ for _, addr := range config.BindAddrs {
+ ip := net.ParseIP(addr)
+
+ tcpAddr := &net.TCPAddr{IP: ip, Port: port}
+ tcpLn, err := net.ListenTCP("tcp", tcpAddr)
+ if err != nil {
+ return nil, fmt.Errorf("Failed to start TCP listener on %q port %d: %v", addr, port, err)
+ }
+ t.tcpListeners = append(t.tcpListeners, tcpLn)
+
+ // If the config port given was zero, use the first TCP listener
+ // to pick an available port and then apply that to everything
+ // else.
+ if port == 0 {
+ port = tcpLn.Addr().(*net.TCPAddr).Port
+ }
+
+ udpAddr := &net.UDPAddr{IP: ip, Port: port}
+ udpLn, err := net.ListenUDP("udp", udpAddr)
+ if err != nil {
+ return nil, fmt.Errorf("Failed to start UDP listener on %q port %d: %v", addr, port, err)
+ }
+ if err := setUDPRecvBuf(udpLn); err != nil {
+ return nil, fmt.Errorf("Failed to resize UDP buffer: %v", err)
+ }
+ t.udpListeners = append(t.udpListeners, udpLn)
+ }
+
+ // Fire them up now that we've been able to create them all.
+ for i := 0; i < len(config.BindAddrs); i++ {
+ t.wg.Add(2)
+ go t.tcpListen(t.tcpListeners[i])
+ go t.udpListen(t.udpListeners[i])
+ }
+
+ ok = true
+ return &t, nil
+}
+
+// GetAutoBindPort returns the bind port that was automatically given by the
+// kernel, if a bind port of 0 was given.
+func (t *NetTransport) GetAutoBindPort() int {
+ // We made sure there's at least one TCP listener, and that one's
+ // port was applied to all the others for the dynamic bind case.
+ return t.tcpListeners[0].Addr().(*net.TCPAddr).Port
+}
+
+// See Transport.
+func (t *NetTransport) FinalAdvertiseAddr(ip string, port int) (net.IP, int, error) {
+ var advertiseAddr net.IP
+ var advertisePort int
+ if ip != "" {
+ // If they've supplied an address, use that.
+ advertiseAddr = net.ParseIP(ip)
+ if advertiseAddr == nil {
+ return nil, 0, fmt.Errorf("Failed to parse advertise address %q", ip)
+ }
+
+ // Ensure IPv4 conversion if necessary.
+ if ip4 := advertiseAddr.To4(); ip4 != nil {
+ advertiseAddr = ip4
+ }
+ advertisePort = port
+ } else {
+ if t.config.BindAddrs[0] == "0.0.0.0" {
+ // Otherwise, if we're not bound to a specific IP, let's
+ // use a suitable private IP address.
+ var err error
+ ip, err = sockaddr.GetPrivateIP()
+ if err != nil {
+ return nil, 0, fmt.Errorf("Failed to get interface addresses: %v", err)
+ }
+ if ip == "" {
+ return nil, 0, fmt.Errorf("No private IP address found, and explicit IP not provided")
+ }
+
+ advertiseAddr = net.ParseIP(ip)
+ if advertiseAddr == nil {
+ return nil, 0, fmt.Errorf("Failed to parse advertise address: %q", ip)
+ }
+ } else {
+ // Use the IP that we're bound to, based on the first
+ // TCP listener, which we already ensure is there.
+ advertiseAddr = t.tcpListeners[0].Addr().(*net.TCPAddr).IP
+ }
+
+ // Use the port we are bound to.
+ advertisePort = t.GetAutoBindPort()
+ }
+
+ return advertiseAddr, advertisePort, nil
+}
+
+// See Transport.
+func (t *NetTransport) WriteTo(b []byte, addr string) (time.Time, error) {
+ udpAddr, err := net.ResolveUDPAddr("udp", addr)
+ if err != nil {
+ return time.Time{}, err
+ }
+
+ // We made sure there's at least one UDP listener, so just use the
+ // packet sending interface on the first one. Take the time after the
+ // write call comes back, which will underestimate the time a little,
+ // but help account for any delays before the write occurs.
+ _, err = t.udpListeners[0].WriteTo(b, udpAddr)
+ return time.Now(), err
+}
+
+// See Transport.
+func (t *NetTransport) PacketCh() <-chan *Packet {
+ return t.packetCh
+}
+
+// See Transport.
+func (t *NetTransport) DialTimeout(addr string, timeout time.Duration) (net.Conn, error) {
+ dialer := net.Dialer{Timeout: timeout}
+ return dialer.Dial("tcp", addr)
+}
+
+// See Transport.
+func (t *NetTransport) StreamCh() <-chan net.Conn {
+ return t.streamCh
+}
+
+// See Transport.
+func (t *NetTransport) Shutdown() error {
+ // This will avoid log spam about errors when we shut down.
+ atomic.StoreInt32(&t.shutdown, 1)
+
+ // Rip through all the connections and shut them down.
+ for _, conn := range t.tcpListeners {
+ conn.Close()
+ }
+ for _, conn := range t.udpListeners {
+ conn.Close()
+ }
+
+ // Block until all the listener threads have died.
+ t.wg.Wait()
+ return nil
+}
+
+// tcpListen is a long running goroutine that accepts incoming TCP connections
+// and hands them off to the stream channel.
+func (t *NetTransport) tcpListen(tcpLn *net.TCPListener) {
+ defer t.wg.Done()
+ for {
+ conn, err := tcpLn.AcceptTCP()
+ if err != nil {
+ if s := atomic.LoadInt32(&t.shutdown); s == 1 {
+ break
+ }
+
+ t.logger.Printf("[ERR] memberlist: Error accepting TCP connection: %v", err)
+ continue
+ }
+
+ t.streamCh <- conn
+ }
+}
+
+// udpListen is a long running goroutine that accepts incoming UDP packets and
+// hands them off to the packet channel.
+func (t *NetTransport) udpListen(udpLn *net.UDPConn) {
+ defer t.wg.Done()
+ for {
+ // Do a blocking read into a fresh buffer. Grab a time stamp as
+ // close as possible to the I/O.
+ buf := make([]byte, udpPacketBufSize)
+ n, addr, err := udpLn.ReadFrom(buf)
+ ts := time.Now()
+ if err != nil {
+ if s := atomic.LoadInt32(&t.shutdown); s == 1 {
+ break
+ }
+
+ t.logger.Printf("[ERR] memberlist: Error reading UDP packet: %v", err)
+ continue
+ }
+
+ // Check the length - it needs to have at least one byte to be a
+ // proper message.
+ if n < 1 {
+ t.logger.Printf("[ERR] memberlist: UDP packet too short (%d bytes) %s",
+ len(buf), LogAddress(addr))
+ continue
+ }
+
+ // Ingest the packet.
+ metrics.IncrCounter([]string{"memberlist", "udp", "received"}, float32(n))
+ t.packetCh <- &Packet{
+ Buf: buf[:n],
+ From: addr,
+ Timestamp: ts,
+ }
+ }
+}
+
+// setUDPRecvBuf is used to resize the UDP receive window. The function
+// attempts to set the read buffer to `udpRecvBuf` but backs off until
+// the read buffer can be set.
+func setUDPRecvBuf(c *net.UDPConn) error {
+ size := udpRecvBufSize
+ var err error
+ for size > 0 {
+ if err = c.SetReadBuffer(size); err == nil {
+ return nil
+ }
+ size = size / 2
+ }
+ return err
+}
--- /dev/null
+package memberlist
+
+import "time"
+
+// PingDelegate is used to notify an observer how long it took for a ping message to
+// complete a round trip. It can also be used for writing arbitrary byte slices
+// into ack messages. Note that in order to be meaningful for RTT estimates, this
+// delegate does not apply to indirect pings, nor fallback pings sent over TCP.
+type PingDelegate interface {
+ // AckPayload is invoked when an ack is being sent; the returned bytes will be appended to the ack
+ AckPayload() []byte
+ // NotifyPing is invoked when an ack for a ping is received
+ NotifyPingComplete(other *Node, rtt time.Duration, payload []byte)
+}
--- /dev/null
+package memberlist
+
+import (
+ "sort"
+ "sync"
+)
+
+// TransmitLimitedQueue is used to queue messages to broadcast to
+// the cluster (via gossip) but limits the number of transmits per
+// message. It also prioritizes messages with lower transmit counts
+// (hence newer messages).
+type TransmitLimitedQueue struct {
+ // NumNodes returns the number of nodes in the cluster. This is
+ // used to determine the retransmit count, which is calculated
+ // based on the log of this.
+ NumNodes func() int
+
+ // RetransmitMult is the multiplier used to determine the maximum
+ // number of retransmissions attempted.
+ RetransmitMult int
+
+ sync.Mutex
+ bcQueue limitedBroadcasts
+}
+
+type limitedBroadcast struct {
+ transmits int // Number of transmissions attempted.
+ b Broadcast
+}
+type limitedBroadcasts []*limitedBroadcast
+
+// Broadcast is something that can be broadcasted via gossip to
+// the memberlist cluster.
+type Broadcast interface {
+ // Invalidates checks if enqueuing the current broadcast
+ // invalidates a previous broadcast
+ Invalidates(b Broadcast) bool
+
+ // Returns a byte form of the message
+ Message() []byte
+
+ // Finished is invoked when the message will no longer
+ // be broadcast, either due to invalidation or to the
+ // transmit limit being reached
+ Finished()
+}
+
+// QueueBroadcast is used to enqueue a broadcast
+func (q *TransmitLimitedQueue) QueueBroadcast(b Broadcast) {
+ q.Lock()
+ defer q.Unlock()
+
+ // Check if this message invalidates another
+ n := len(q.bcQueue)
+ for i := 0; i < n; i++ {
+ if b.Invalidates(q.bcQueue[i].b) {
+ q.bcQueue[i].b.Finished()
+ copy(q.bcQueue[i:], q.bcQueue[i+1:])
+ q.bcQueue[n-1] = nil
+ q.bcQueue = q.bcQueue[:n-1]
+ n--
+ }
+ }
+
+ // Append to the queue
+ q.bcQueue = append(q.bcQueue, &limitedBroadcast{0, b})
+}
+
+// GetBroadcasts is used to get a number of broadcasts, up to a byte limit
+// and applying a per-message overhead as provided.
+func (q *TransmitLimitedQueue) GetBroadcasts(overhead, limit int) [][]byte {
+ q.Lock()
+ defer q.Unlock()
+
+ // Fast path the default case
+ if len(q.bcQueue) == 0 {
+ return nil
+ }
+
+ transmitLimit := retransmitLimit(q.RetransmitMult, q.NumNodes())
+ bytesUsed := 0
+ var toSend [][]byte
+
+ for i := len(q.bcQueue) - 1; i >= 0; i-- {
+ // Check if this is within our limits
+ b := q.bcQueue[i]
+ msg := b.b.Message()
+ if bytesUsed+overhead+len(msg) > limit {
+ continue
+ }
+
+ // Add to slice to send
+ bytesUsed += overhead + len(msg)
+ toSend = append(toSend, msg)
+
+ // Check if we should stop transmission
+ b.transmits++
+ if b.transmits >= transmitLimit {
+ b.b.Finished()
+ n := len(q.bcQueue)
+ q.bcQueue[i], q.bcQueue[n-1] = q.bcQueue[n-1], nil
+ q.bcQueue = q.bcQueue[:n-1]
+ }
+ }
+
+ // If we are sending anything, we need to re-sort to deal
+ // with adjusted transmit counts
+ if len(toSend) > 0 {
+ q.bcQueue.Sort()
+ }
+ return toSend
+}
+
+// NumQueued returns the number of queued messages
+func (q *TransmitLimitedQueue) NumQueued() int {
+ q.Lock()
+ defer q.Unlock()
+ return len(q.bcQueue)
+}
+
+// Reset clears all the queued messages
+func (q *TransmitLimitedQueue) Reset() {
+ q.Lock()
+ defer q.Unlock()
+ for _, b := range q.bcQueue {
+ b.b.Finished()
+ }
+ q.bcQueue = nil
+}
+
+// Prune will retain the maxRetain latest messages, and the rest
+// will be discarded. This can be used to prevent unbounded queue sizes
+func (q *TransmitLimitedQueue) Prune(maxRetain int) {
+ q.Lock()
+ defer q.Unlock()
+
+ // Do nothing if queue size is less than the limit
+ n := len(q.bcQueue)
+ if n < maxRetain {
+ return
+ }
+
+ // Invalidate the messages we will be removing
+ for i := 0; i < n-maxRetain; i++ {
+ q.bcQueue[i].b.Finished()
+ }
+
+ // Move the messages, and retain only the last maxRetain
+ copy(q.bcQueue[0:], q.bcQueue[n-maxRetain:])
+ q.bcQueue = q.bcQueue[:maxRetain]
+}
+
+func (b limitedBroadcasts) Len() int {
+ return len(b)
+}
+
+func (b limitedBroadcasts) Less(i, j int) bool {
+ return b[i].transmits < b[j].transmits
+}
+
+func (b limitedBroadcasts) Swap(i, j int) {
+ b[i], b[j] = b[j], b[i]
+}
+
+func (b limitedBroadcasts) Sort() {
+ sort.Sort(sort.Reverse(b))
+}
--- /dev/null
+package memberlist
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/rand"
+ "fmt"
+ "io"
+)
+
+/*
+
+Encrypted messages are prefixed with an encryptionVersion byte
+that is used for us to be able to properly encode/decode. We
+currently support the following versions:
+
+ 0 - AES-GCM 128, using PKCS7 padding
+ 1 - AES-GCM 128, no padding. Padding not needed, caused bloat.
+
+*/
+type encryptionVersion uint8
+
+const (
+ minEncryptionVersion encryptionVersion = 0
+ maxEncryptionVersion encryptionVersion = 1
+)
+
+const (
+ versionSize = 1
+ nonceSize = 12
+ tagSize = 16
+ maxPadOverhead = 16
+ blockSize = aes.BlockSize
+)
+
+// pkcs7encode is used to pad a byte buffer to a specific block size using
+// the PKCS7 algorithm. "Ignores" some bytes to compensate for IV
+func pkcs7encode(buf *bytes.Buffer, ignore, blockSize int) {
+ n := buf.Len() - ignore
+ more := blockSize - (n % blockSize)
+ for i := 0; i < more; i++ {
+ buf.WriteByte(byte(more))
+ }
+}
+
+// pkcs7decode is used to decode a buffer that has been padded
+func pkcs7decode(buf []byte, blockSize int) []byte {
+ if len(buf) == 0 {
+ panic("Cannot decode a PKCS7 buffer of zero length")
+ }
+ n := len(buf)
+ last := buf[n-1]
+ n -= int(last)
+ return buf[:n]
+}
+
+// encryptOverhead returns the maximum possible overhead of encryption by version
+func encryptOverhead(vsn encryptionVersion) int {
+ switch vsn {
+ case 0:
+ return 45 // Version: 1, IV: 12, Padding: 16, Tag: 16
+ case 1:
+ return 29 // Version: 1, IV: 12, Tag: 16
+ default:
+ panic("unsupported version")
+ }
+}
+
+// encryptedLength is used to compute the buffer size needed
+// for a message of given length
+func encryptedLength(vsn encryptionVersion, inp int) int {
+ // If we are on version 1, there is no padding
+ if vsn >= 1 {
+ return versionSize + nonceSize + inp + tagSize
+ }
+
+ // Determine the padding size
+ padding := blockSize - (inp % blockSize)
+
+ // Sum the extra parts to get total size
+ return versionSize + nonceSize + inp + padding + tagSize
+}
+
+// encryptPayload is used to encrypt a message with a given key.
+// We make use of AES-128 in GCM mode. New byte buffer is the version,
+// nonce, ciphertext and tag
+func encryptPayload(vsn encryptionVersion, key []byte, msg []byte, data []byte, dst *bytes.Buffer) error {
+ // Get the AES block cipher
+ aesBlock, err := aes.NewCipher(key)
+ if err != nil {
+ return err
+ }
+
+ // Get the GCM cipher mode
+ gcm, err := cipher.NewGCM(aesBlock)
+ if err != nil {
+ return err
+ }
+
+ // Grow the buffer to make room for everything
+ offset := dst.Len()
+ dst.Grow(encryptedLength(vsn, len(msg)))
+
+ // Write the encryption version
+ dst.WriteByte(byte(vsn))
+
+ // Add a random nonce
+ io.CopyN(dst, rand.Reader, nonceSize)
+ afterNonce := dst.Len()
+
+ // Ensure we are correctly padded (only version 0)
+ if vsn == 0 {
+ io.Copy(dst, bytes.NewReader(msg))
+ pkcs7encode(dst, offset+versionSize+nonceSize, aes.BlockSize)
+ }
+
+ // Encrypt message using GCM
+ slice := dst.Bytes()[offset:]
+ nonce := slice[versionSize : versionSize+nonceSize]
+
+ // Message source depends on the encryption version.
+ // Version 0 uses padding, version 1 does not
+ var src []byte
+ if vsn == 0 {
+ src = slice[versionSize+nonceSize:]
+ } else {
+ src = msg
+ }
+ out := gcm.Seal(nil, nonce, src, data)
+
+ // Truncate the plaintext, and write the cipher text
+ dst.Truncate(afterNonce)
+ dst.Write(out)
+ return nil
+}
+
+// decryptMessage performs the actual decryption of ciphertext. This is in its
+// own function to allow it to be called on all keys easily.
+func decryptMessage(key, msg []byte, data []byte) ([]byte, error) {
+ // Get the AES block cipher
+ aesBlock, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ // Get the GCM cipher mode
+ gcm, err := cipher.NewGCM(aesBlock)
+ if err != nil {
+ return nil, err
+ }
+
+ // Decrypt the message
+ nonce := msg[versionSize : versionSize+nonceSize]
+ ciphertext := msg[versionSize+nonceSize:]
+ plain, err := gcm.Open(nil, nonce, ciphertext, data)
+ if err != nil {
+ return nil, err
+ }
+
+ // Success!
+ return plain, nil
+}
+
+// decryptPayload is used to decrypt a message with a given key,
+// and verify it's contents. Any padding will be removed, and a
+// slice to the plaintext is returned. Decryption is done IN PLACE!
+func decryptPayload(keys [][]byte, msg []byte, data []byte) ([]byte, error) {
+ // Ensure we have at least one byte
+ if len(msg) == 0 {
+ return nil, fmt.Errorf("Cannot decrypt empty payload")
+ }
+
+ // Verify the version
+ vsn := encryptionVersion(msg[0])
+ if vsn > maxEncryptionVersion {
+ return nil, fmt.Errorf("Unsupported encryption version %d", msg[0])
+ }
+
+ // Ensure the length is sane
+ if len(msg) < encryptedLength(vsn, 0) {
+ return nil, fmt.Errorf("Payload is too small to decrypt: %d", len(msg))
+ }
+
+ for _, key := range keys {
+ plain, err := decryptMessage(key, msg, data)
+ if err == nil {
+ // Remove the PKCS7 padding for vsn 0
+ if vsn == 0 {
+ return pkcs7decode(plain, aes.BlockSize), nil
+ } else {
+ return plain, nil
+ }
+ }
+ }
+
+ return nil, fmt.Errorf("No installed keys could decrypt the message")
+}
--- /dev/null
+package memberlist
+
+import (
+ "bytes"
+ "fmt"
+ "math"
+ "math/rand"
+ "net"
+ "sync/atomic"
+ "time"
+
+ "github.com/armon/go-metrics"
+)
+
+type nodeStateType int
+
+const (
+ stateAlive nodeStateType = iota
+ stateSuspect
+ stateDead
+)
+
+// Node represents a node in the cluster.
+type Node struct {
+ Name string
+ Addr net.IP
+ Port uint16
+ Meta []byte // Metadata from the delegate for this node.
+ PMin uint8 // Minimum protocol version this understands
+ PMax uint8 // Maximum protocol version this understands
+ PCur uint8 // Current version node is speaking
+ DMin uint8 // Min protocol version for the delegate to understand
+ DMax uint8 // Max protocol version for the delegate to understand
+ DCur uint8 // Current version delegate is speaking
+}
+
+// Address returns the host:port form of a node's address, suitable for use
+// with a transport.
+func (n *Node) Address() string {
+ return joinHostPort(n.Addr.String(), n.Port)
+}
+
+// String returns the node name
+func (n *Node) String() string {
+ return n.Name
+}
+
+// NodeState is used to manage our state view of another node
+type nodeState struct {
+ Node
+ Incarnation uint32 // Last known incarnation number
+ State nodeStateType // Current state
+ StateChange time.Time // Time last state change happened
+}
+
+// Address returns the host:port form of a node's address, suitable for use
+// with a transport.
+func (n *nodeState) Address() string {
+ return n.Node.Address()
+}
+
+// ackHandler is used to register handlers for incoming acks and nacks.
+type ackHandler struct {
+ ackFn func([]byte, time.Time)
+ nackFn func()
+ timer *time.Timer
+}
+
+// NoPingResponseError is used to indicate a 'ping' packet was
+// successfully issued but no response was received
+type NoPingResponseError struct {
+ node string
+}
+
+func (f NoPingResponseError) Error() string {
+ return fmt.Sprintf("No response from node %s", f.node)
+}
+
+// Schedule is used to ensure the Tick is performed periodically. This
+// function is safe to call multiple times. If the memberlist is already
+// scheduled, then it won't do anything.
+func (m *Memberlist) schedule() {
+ m.tickerLock.Lock()
+ defer m.tickerLock.Unlock()
+
+ // If we already have tickers, then don't do anything, since we're
+ // scheduled
+ if len(m.tickers) > 0 {
+ return
+ }
+
+ // Create the stop tick channel, a blocking channel. We close this
+ // when we should stop the tickers.
+ stopCh := make(chan struct{})
+
+ // Create a new probeTicker
+ if m.config.ProbeInterval > 0 {
+ t := time.NewTicker(m.config.ProbeInterval)
+ go m.triggerFunc(m.config.ProbeInterval, t.C, stopCh, m.probe)
+ m.tickers = append(m.tickers, t)
+ }
+
+ // Create a push pull ticker if needed
+ if m.config.PushPullInterval > 0 {
+ go m.pushPullTrigger(stopCh)
+ }
+
+ // Create a gossip ticker if needed
+ if m.config.GossipInterval > 0 && m.config.GossipNodes > 0 {
+ t := time.NewTicker(m.config.GossipInterval)
+ go m.triggerFunc(m.config.GossipInterval, t.C, stopCh, m.gossip)
+ m.tickers = append(m.tickers, t)
+ }
+
+ // If we made any tickers, then record the stopTick channel for
+ // later.
+ if len(m.tickers) > 0 {
+ m.stopTick = stopCh
+ }
+}
+
+// triggerFunc is used to trigger a function call each time a
+// message is received until a stop tick arrives.
+func (m *Memberlist) triggerFunc(stagger time.Duration, C <-chan time.Time, stop <-chan struct{}, f func()) {
+ // Use a random stagger to avoid syncronizing
+ randStagger := time.Duration(uint64(rand.Int63()) % uint64(stagger))
+ select {
+ case <-time.After(randStagger):
+ case <-stop:
+ return
+ }
+ for {
+ select {
+ case <-C:
+ f()
+ case <-stop:
+ return
+ }
+ }
+}
+
+// pushPullTrigger is used to periodically trigger a push/pull until
+// a stop tick arrives. We don't use triggerFunc since the push/pull
+// timer is dynamically scaled based on cluster size to avoid network
+// saturation
+func (m *Memberlist) pushPullTrigger(stop <-chan struct{}) {
+ interval := m.config.PushPullInterval
+
+ // Use a random stagger to avoid syncronizing
+ randStagger := time.Duration(uint64(rand.Int63()) % uint64(interval))
+ select {
+ case <-time.After(randStagger):
+ case <-stop:
+ return
+ }
+
+ // Tick using a dynamic timer
+ for {
+ tickTime := pushPullScale(interval, m.estNumNodes())
+ select {
+ case <-time.After(tickTime):
+ m.pushPull()
+ case <-stop:
+ return
+ }
+ }
+}
+
+// Deschedule is used to stop the background maintenance. This is safe
+// to call multiple times.
+func (m *Memberlist) deschedule() {
+ m.tickerLock.Lock()
+ defer m.tickerLock.Unlock()
+
+ // If we have no tickers, then we aren't scheduled.
+ if len(m.tickers) == 0 {
+ return
+ }
+
+ // Close the stop channel so all the ticker listeners stop.
+ close(m.stopTick)
+
+ // Explicitly stop all the tickers themselves so they don't take
+ // up any more resources, and get rid of the list.
+ for _, t := range m.tickers {
+ t.Stop()
+ }
+ m.tickers = nil
+}
+
+// Tick is used to perform a single round of failure detection and gossip
+func (m *Memberlist) probe() {
+ // Track the number of indexes we've considered probing
+ numCheck := 0
+START:
+ m.nodeLock.RLock()
+
+ // Make sure we don't wrap around infinitely
+ if numCheck >= len(m.nodes) {
+ m.nodeLock.RUnlock()
+ return
+ }
+
+ // Handle the wrap around case
+ if m.probeIndex >= len(m.nodes) {
+ m.nodeLock.RUnlock()
+ m.resetNodes()
+ m.probeIndex = 0
+ numCheck++
+ goto START
+ }
+
+ // Determine if we should probe this node
+ skip := false
+ var node nodeState
+
+ node = *m.nodes[m.probeIndex]
+ if node.Name == m.config.Name {
+ skip = true
+ } else if node.State == stateDead {
+ skip = true
+ }
+
+ // Potentially skip
+ m.nodeLock.RUnlock()
+ m.probeIndex++
+ if skip {
+ numCheck++
+ goto START
+ }
+
+ // Probe the specific node
+ m.probeNode(&node)
+}
+
+// probeNode handles a single round of failure checking on a node.
+func (m *Memberlist) probeNode(node *nodeState) {
+ defer metrics.MeasureSince([]string{"memberlist", "probeNode"}, time.Now())
+
+ // We use our health awareness to scale the overall probe interval, so we
+ // slow down if we detect problems. The ticker that calls us can handle
+ // us running over the base interval, and will skip missed ticks.
+ probeInterval := m.awareness.ScaleTimeout(m.config.ProbeInterval)
+ if probeInterval > m.config.ProbeInterval {
+ metrics.IncrCounter([]string{"memberlist", "degraded", "probe"}, 1)
+ }
+
+ // Prepare a ping message and setup an ack handler.
+ ping := ping{SeqNo: m.nextSeqNo(), Node: node.Name}
+ ackCh := make(chan ackMessage, m.config.IndirectChecks+1)
+ nackCh := make(chan struct{}, m.config.IndirectChecks+1)
+ m.setProbeChannels(ping.SeqNo, ackCh, nackCh, probeInterval)
+
+ // Send a ping to the node. If this node looks like it's suspect or dead,
+ // also tack on a suspect message so that it has a chance to refute as
+ // soon as possible.
+ deadline := time.Now().Add(probeInterval)
+ addr := node.Address()
+ if node.State == stateAlive {
+ if err := m.encodeAndSendMsg(addr, pingMsg, &ping); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to send ping: %s", err)
+ return
+ }
+ } else {
+ var msgs [][]byte
+ if buf, err := encode(pingMsg, &ping); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to encode ping message: %s", err)
+ return
+ } else {
+ msgs = append(msgs, buf.Bytes())
+ }
+ s := suspect{Incarnation: node.Incarnation, Node: node.Name, From: m.config.Name}
+ if buf, err := encode(suspectMsg, &s); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to encode suspect message: %s", err)
+ return
+ } else {
+ msgs = append(msgs, buf.Bytes())
+ }
+
+ compound := makeCompoundMessage(msgs)
+ if err := m.rawSendMsgPacket(addr, &node.Node, compound.Bytes()); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to send compound ping and suspect message to %s: %s", addr, err)
+ return
+ }
+ }
+
+ // Mark the sent time here, which should be after any pre-processing and
+ // system calls to do the actual send. This probably under-reports a bit,
+ // but it's the best we can do.
+ sent := time.Now()
+
+ // Arrange for our self-awareness to get updated. At this point we've
+ // sent the ping, so any return statement means the probe succeeded
+ // which will improve our health until we get to the failure scenarios
+ // at the end of this function, which will alter this delta variable
+ // accordingly.
+ awarenessDelta := -1
+ defer func() {
+ m.awareness.ApplyDelta(awarenessDelta)
+ }()
+
+ // Wait for response or round-trip-time.
+ select {
+ case v := <-ackCh:
+ if v.Complete == true {
+ if m.config.Ping != nil {
+ rtt := v.Timestamp.Sub(sent)
+ m.config.Ping.NotifyPingComplete(&node.Node, rtt, v.Payload)
+ }
+ return
+ }
+
+ // As an edge case, if we get a timeout, we need to re-enqueue it
+ // here to break out of the select below.
+ if v.Complete == false {
+ ackCh <- v
+ }
+ case <-time.After(m.config.ProbeTimeout):
+ // Note that we don't scale this timeout based on awareness and
+ // the health score. That's because we don't really expect waiting
+ // longer to help get UDP through. Since health does extend the
+ // probe interval it will give the TCP fallback more time, which
+ // is more active in dealing with lost packets, and it gives more
+ // time to wait for indirect acks/nacks.
+ m.logger.Printf("[DEBUG] memberlist: Failed ping: %v (timeout reached)", node.Name)
+ }
+
+ // Get some random live nodes.
+ m.nodeLock.RLock()
+ kNodes := kRandomNodes(m.config.IndirectChecks, m.nodes, func(n *nodeState) bool {
+ return n.Name == m.config.Name ||
+ n.Name == node.Name ||
+ n.State != stateAlive
+ })
+ m.nodeLock.RUnlock()
+
+ // Attempt an indirect ping.
+ expectedNacks := 0
+ ind := indirectPingReq{SeqNo: ping.SeqNo, Target: node.Addr, Port: node.Port, Node: node.Name}
+ for _, peer := range kNodes {
+ // We only expect nack to be sent from peers who understand
+ // version 4 of the protocol.
+ if ind.Nack = peer.PMax >= 4; ind.Nack {
+ expectedNacks++
+ }
+
+ if err := m.encodeAndSendMsg(peer.Address(), indirectPingMsg, &ind); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to send indirect ping: %s", err)
+ }
+ }
+
+ // Also make an attempt to contact the node directly over TCP. This
+ // helps prevent confused clients who get isolated from UDP traffic
+ // but can still speak TCP (which also means they can possibly report
+ // misinformation to other nodes via anti-entropy), avoiding flapping in
+ // the cluster.
+ //
+ // This is a little unusual because we will attempt a TCP ping to any
+ // member who understands version 3 of the protocol, regardless of
+ // which protocol version we are speaking. That's why we've included a
+ // config option to turn this off if desired.
+ fallbackCh := make(chan bool, 1)
+ if (!m.config.DisableTcpPings) && (node.PMax >= 3) {
+ go func() {
+ defer close(fallbackCh)
+ didContact, err := m.sendPingAndWaitForAck(node.Address(), ping, deadline)
+ if err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed fallback ping: %s", err)
+ } else {
+ fallbackCh <- didContact
+ }
+ }()
+ } else {
+ close(fallbackCh)
+ }
+
+ // Wait for the acks or timeout. Note that we don't check the fallback
+ // channel here because we want to issue a warning below if that's the
+ // *only* way we hear back from the peer, so we have to let this time
+ // out first to allow the normal UDP-based acks to come in.
+ select {
+ case v := <-ackCh:
+ if v.Complete == true {
+ return
+ }
+ }
+
+ // Finally, poll the fallback channel. The timeouts are set such that
+ // the channel will have something or be closed without having to wait
+ // any additional time here.
+ for didContact := range fallbackCh {
+ if didContact {
+ m.logger.Printf("[WARN] memberlist: Was able to connect to %s but other probes failed, network may be misconfigured", node.Name)
+ return
+ }
+ }
+
+ // Update our self-awareness based on the results of this failed probe.
+ // If we don't have peers who will send nacks then we penalize for any
+ // failed probe as a simple health metric. If we do have peers to nack
+ // verify, then we can use that as a more sophisticated measure of self-
+ // health because we assume them to be working, and they can help us
+ // decide if the probed node was really dead or if it was something wrong
+ // with ourselves.
+ awarenessDelta = 0
+ if expectedNacks > 0 {
+ if nackCount := len(nackCh); nackCount < expectedNacks {
+ awarenessDelta += (expectedNacks - nackCount)
+ }
+ } else {
+ awarenessDelta += 1
+ }
+
+ // No acks received from target, suspect it as failed.
+ m.logger.Printf("[INFO] memberlist: Suspect %s has failed, no acks received", node.Name)
+ s := suspect{Incarnation: node.Incarnation, Node: node.Name, From: m.config.Name}
+ m.suspectNode(&s)
+}
+
+// Ping initiates a ping to the node with the specified name.
+func (m *Memberlist) Ping(node string, addr net.Addr) (time.Duration, error) {
+ // Prepare a ping message and setup an ack handler.
+ ping := ping{SeqNo: m.nextSeqNo(), Node: node}
+ ackCh := make(chan ackMessage, m.config.IndirectChecks+1)
+ m.setProbeChannels(ping.SeqNo, ackCh, nil, m.config.ProbeInterval)
+
+ // Send a ping to the node.
+ if err := m.encodeAndSendMsg(addr.String(), pingMsg, &ping); err != nil {
+ return 0, err
+ }
+
+ // Mark the sent time here, which should be after any pre-processing and
+ // system calls to do the actual send. This probably under-reports a bit,
+ // but it's the best we can do.
+ sent := time.Now()
+
+ // Wait for response or timeout.
+ select {
+ case v := <-ackCh:
+ if v.Complete == true {
+ return v.Timestamp.Sub(sent), nil
+ }
+ case <-time.After(m.config.ProbeTimeout):
+ // Timeout, return an error below.
+ }
+
+ m.logger.Printf("[DEBUG] memberlist: Failed UDP ping: %v (timeout reached)", node)
+ return 0, NoPingResponseError{ping.Node}
+}
+
+// resetNodes is used when the tick wraps around. It will reap the
+// dead nodes and shuffle the node list.
+func (m *Memberlist) resetNodes() {
+ m.nodeLock.Lock()
+ defer m.nodeLock.Unlock()
+
+ // Move dead nodes, but respect gossip to the dead interval
+ deadIdx := moveDeadNodes(m.nodes, m.config.GossipToTheDeadTime)
+
+ // Deregister the dead nodes
+ for i := deadIdx; i < len(m.nodes); i++ {
+ delete(m.nodeMap, m.nodes[i].Name)
+ m.nodes[i] = nil
+ }
+
+ // Trim the nodes to exclude the dead nodes
+ m.nodes = m.nodes[0:deadIdx]
+
+ // Update numNodes after we've trimmed the dead nodes
+ atomic.StoreUint32(&m.numNodes, uint32(deadIdx))
+
+ // Shuffle live nodes
+ shuffleNodes(m.nodes)
+}
+
+// gossip is invoked every GossipInterval period to broadcast our gossip
+// messages to a few random nodes.
+func (m *Memberlist) gossip() {
+ defer metrics.MeasureSince([]string{"memberlist", "gossip"}, time.Now())
+
+ // Get some random live, suspect, or recently dead nodes
+ m.nodeLock.RLock()
+ kNodes := kRandomNodes(m.config.GossipNodes, m.nodes, func(n *nodeState) bool {
+ if n.Name == m.config.Name {
+ return true
+ }
+
+ switch n.State {
+ case stateAlive, stateSuspect:
+ return false
+
+ case stateDead:
+ return time.Since(n.StateChange) > m.config.GossipToTheDeadTime
+
+ default:
+ return true
+ }
+ })
+ m.nodeLock.RUnlock()
+
+ // Compute the bytes available
+ bytesAvail := m.config.UDPBufferSize - compoundHeaderOverhead
+ if m.config.EncryptionEnabled() {
+ bytesAvail -= encryptOverhead(m.encryptionVersion())
+ }
+
+ for _, node := range kNodes {
+ // Get any pending broadcasts
+ msgs := m.getBroadcasts(compoundOverhead, bytesAvail)
+ if len(msgs) == 0 {
+ return
+ }
+
+ addr := node.Address()
+ if len(msgs) == 1 {
+ // Send single message as is
+ if err := m.rawSendMsgPacket(addr, &node.Node, msgs[0]); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to send gossip to %s: %s", addr, err)
+ }
+ } else {
+ // Otherwise create and send a compound message
+ compound := makeCompoundMessage(msgs)
+ if err := m.rawSendMsgPacket(addr, &node.Node, compound.Bytes()); err != nil {
+ m.logger.Printf("[ERR] memberlist: Failed to send gossip to %s: %s", addr, err)
+ }
+ }
+ }
+}
+
+// pushPull is invoked periodically to randomly perform a complete state
+// exchange. Used to ensure a high level of convergence, but is also
+// reasonably expensive as the entire state of this node is exchanged
+// with the other node.
+func (m *Memberlist) pushPull() {
+ // Get a random live node
+ m.nodeLock.RLock()
+ nodes := kRandomNodes(1, m.nodes, func(n *nodeState) bool {
+ return n.Name == m.config.Name ||
+ n.State != stateAlive
+ })
+ m.nodeLock.RUnlock()
+
+ // If no nodes, bail
+ if len(nodes) == 0 {
+ return
+ }
+ node := nodes[0]
+
+ // Attempt a push pull
+ if err := m.pushPullNode(node.Address(), false); err != nil {
+ m.logger.Printf("[ERR] memberlist: Push/Pull with %s failed: %s", node.Name, err)
+ }
+}
+
+// pushPullNode does a complete state exchange with a specific node.
+func (m *Memberlist) pushPullNode(addr string, join bool) error {
+ defer metrics.MeasureSince([]string{"memberlist", "pushPullNode"}, time.Now())
+
+ // Attempt to send and receive with the node
+ remote, userState, err := m.sendAndReceiveState(addr, join)
+ if err != nil {
+ return err
+ }
+
+ if err := m.mergeRemoteState(join, remote, userState); err != nil {
+ return err
+ }
+ return nil
+}
+
+// verifyProtocol verifies that all the remote nodes can speak with our
+// nodes and vice versa on both the core protocol as well as the
+// delegate protocol level.
+//
+// The verification works by finding the maximum minimum and
+// minimum maximum understood protocol and delegate versions. In other words,
+// it finds the common denominator of protocol and delegate version ranges
+// for the entire cluster.
+//
+// After this, it goes through the entire cluster (local and remote) and
+// verifies that everyone's speaking protocol versions satisfy this range.
+// If this passes, it means that every node can understand each other.
+func (m *Memberlist) verifyProtocol(remote []pushNodeState) error {
+ m.nodeLock.RLock()
+ defer m.nodeLock.RUnlock()
+
+ // Maximum minimum understood and minimum maximum understood for both
+ // the protocol and delegate versions. We use this to verify everyone
+ // can be understood.
+ var maxpmin, minpmax uint8
+ var maxdmin, mindmax uint8
+ minpmax = math.MaxUint8
+ mindmax = math.MaxUint8
+
+ for _, rn := range remote {
+ // If the node isn't alive, then skip it
+ if rn.State != stateAlive {
+ continue
+ }
+
+ // Skip nodes that don't have versions set, it just means
+ // their version is zero.
+ if len(rn.Vsn) == 0 {
+ continue
+ }
+
+ if rn.Vsn[0] > maxpmin {
+ maxpmin = rn.Vsn[0]
+ }
+
+ if rn.Vsn[1] < minpmax {
+ minpmax = rn.Vsn[1]
+ }
+
+ if rn.Vsn[3] > maxdmin {
+ maxdmin = rn.Vsn[3]
+ }
+
+ if rn.Vsn[4] < mindmax {
+ mindmax = rn.Vsn[4]
+ }
+ }
+
+ for _, n := range m.nodes {
+ // Ignore non-alive nodes
+ if n.State != stateAlive {
+ continue
+ }
+
+ if n.PMin > maxpmin {
+ maxpmin = n.PMin
+ }
+
+ if n.PMax < minpmax {
+ minpmax = n.PMax
+ }
+
+ if n.DMin > maxdmin {
+ maxdmin = n.DMin
+ }
+
+ if n.DMax < mindmax {
+ mindmax = n.DMax
+ }
+ }
+
+ // Now that we definitively know the minimum and maximum understood
+ // version that satisfies the whole cluster, we verify that every
+ // node in the cluster satisifies this.
+ for _, n := range remote {
+ var nPCur, nDCur uint8
+ if len(n.Vsn) > 0 {
+ nPCur = n.Vsn[2]
+ nDCur = n.Vsn[5]
+ }
+
+ if nPCur < maxpmin || nPCur > minpmax {
+ return fmt.Errorf(
+ "Node '%s' protocol version (%d) is incompatible: [%d, %d]",
+ n.Name, nPCur, maxpmin, minpmax)
+ }
+
+ if nDCur < maxdmin || nDCur > mindmax {
+ return fmt.Errorf(
+ "Node '%s' delegate protocol version (%d) is incompatible: [%d, %d]",
+ n.Name, nDCur, maxdmin, mindmax)
+ }
+ }
+
+ for _, n := range m.nodes {
+ nPCur := n.PCur
+ nDCur := n.DCur
+
+ if nPCur < maxpmin || nPCur > minpmax {
+ return fmt.Errorf(
+ "Node '%s' protocol version (%d) is incompatible: [%d, %d]",
+ n.Name, nPCur, maxpmin, minpmax)
+ }
+
+ if nDCur < maxdmin || nDCur > mindmax {
+ return fmt.Errorf(
+ "Node '%s' delegate protocol version (%d) is incompatible: [%d, %d]",
+ n.Name, nDCur, maxdmin, mindmax)
+ }
+ }
+
+ return nil
+}
+
+// nextSeqNo returns a usable sequence number in a thread safe way
+func (m *Memberlist) nextSeqNo() uint32 {
+ return atomic.AddUint32(&m.sequenceNum, 1)
+}
+
+// nextIncarnation returns the next incarnation number in a thread safe way
+func (m *Memberlist) nextIncarnation() uint32 {
+ return atomic.AddUint32(&m.incarnation, 1)
+}
+
+// skipIncarnation adds the positive offset to the incarnation number.
+func (m *Memberlist) skipIncarnation(offset uint32) uint32 {
+ return atomic.AddUint32(&m.incarnation, offset)
+}
+
+// estNumNodes is used to get the current estimate of the number of nodes
+func (m *Memberlist) estNumNodes() int {
+ return int(atomic.LoadUint32(&m.numNodes))
+}
+
+type ackMessage struct {
+ Complete bool
+ Payload []byte
+ Timestamp time.Time
+}
+
+// setProbeChannels is used to attach the ackCh to receive a message when an ack
+// with a given sequence number is received. The `complete` field of the message
+// will be false on timeout. Any nack messages will cause an empty struct to be
+// passed to the nackCh, which can be nil if not needed.
+func (m *Memberlist) setProbeChannels(seqNo uint32, ackCh chan ackMessage, nackCh chan struct{}, timeout time.Duration) {
+ // Create handler functions for acks and nacks
+ ackFn := func(payload []byte, timestamp time.Time) {
+ select {
+ case ackCh <- ackMessage{true, payload, timestamp}:
+ default:
+ }
+ }
+ nackFn := func() {
+ select {
+ case nackCh <- struct{}{}:
+ default:
+ }
+ }
+
+ // Add the handlers
+ ah := &ackHandler{ackFn, nackFn, nil}
+ m.ackLock.Lock()
+ m.ackHandlers[seqNo] = ah
+ m.ackLock.Unlock()
+
+ // Setup a reaping routing
+ ah.timer = time.AfterFunc(timeout, func() {
+ m.ackLock.Lock()
+ delete(m.ackHandlers, seqNo)
+ m.ackLock.Unlock()
+ select {
+ case ackCh <- ackMessage{false, nil, time.Now()}:
+ default:
+ }
+ })
+}
+
+// setAckHandler is used to attach a handler to be invoked when an ack with a
+// given sequence number is received. If a timeout is reached, the handler is
+// deleted. This is used for indirect pings so does not configure a function
+// for nacks.
+func (m *Memberlist) setAckHandler(seqNo uint32, ackFn func([]byte, time.Time), timeout time.Duration) {
+ // Add the handler
+ ah := &ackHandler{ackFn, nil, nil}
+ m.ackLock.Lock()
+ m.ackHandlers[seqNo] = ah
+ m.ackLock.Unlock()
+
+ // Setup a reaping routing
+ ah.timer = time.AfterFunc(timeout, func() {
+ m.ackLock.Lock()
+ delete(m.ackHandlers, seqNo)
+ m.ackLock.Unlock()
+ })
+}
+
+// Invokes an ack handler if any is associated, and reaps the handler immediately
+func (m *Memberlist) invokeAckHandler(ack ackResp, timestamp time.Time) {
+ m.ackLock.Lock()
+ ah, ok := m.ackHandlers[ack.SeqNo]
+ delete(m.ackHandlers, ack.SeqNo)
+ m.ackLock.Unlock()
+ if !ok {
+ return
+ }
+ ah.timer.Stop()
+ ah.ackFn(ack.Payload, timestamp)
+}
+
+// Invokes nack handler if any is associated.
+func (m *Memberlist) invokeNackHandler(nack nackResp) {
+ m.ackLock.Lock()
+ ah, ok := m.ackHandlers[nack.SeqNo]
+ m.ackLock.Unlock()
+ if !ok || ah.nackFn == nil {
+ return
+ }
+ ah.nackFn()
+}
+
+// refute gossips an alive message in response to incoming information that we
+// are suspect or dead. It will make sure the incarnation number beats the given
+// accusedInc value, or you can supply 0 to just get the next incarnation number.
+// This alters the node state that's passed in so this MUST be called while the
+// nodeLock is held.
+func (m *Memberlist) refute(me *nodeState, accusedInc uint32) {
+ // Make sure the incarnation number beats the accusation.
+ inc := m.nextIncarnation()
+ if accusedInc >= inc {
+ inc = m.skipIncarnation(accusedInc - inc + 1)
+ }
+ me.Incarnation = inc
+
+ // Decrease our health because we are being asked to refute a problem.
+ m.awareness.ApplyDelta(1)
+
+ // Format and broadcast an alive message.
+ a := alive{
+ Incarnation: inc,
+ Node: me.Name,
+ Addr: me.Addr,
+ Port: me.Port,
+ Meta: me.Meta,
+ Vsn: []uint8{
+ me.PMin, me.PMax, me.PCur,
+ me.DMin, me.DMax, me.DCur,
+ },
+ }
+ m.encodeAndBroadcast(me.Addr.String(), aliveMsg, a)
+}
+
+// aliveNode is invoked by the network layer when we get a message about a
+// live node.
+func (m *Memberlist) aliveNode(a *alive, notify chan struct{}, bootstrap bool) {
+ m.nodeLock.Lock()
+ defer m.nodeLock.Unlock()
+ state, ok := m.nodeMap[a.Node]
+
+ // It is possible that during a Leave(), there is already an aliveMsg
+ // in-queue to be processed but blocked by the locks above. If we let
+ // that aliveMsg process, it'll cause us to re-join the cluster. This
+ // ensures that we don't.
+ if m.hasLeft() && a.Node == m.config.Name {
+ return
+ }
+
+ // Invoke the Alive delegate if any. This can be used to filter out
+ // alive messages based on custom logic. For example, using a cluster name.
+ // Using a merge delegate is not enough, as it is possible for passive
+ // cluster merging to still occur.
+ if m.config.Alive != nil {
+ node := &Node{
+ Name: a.Node,
+ Addr: a.Addr,
+ Port: a.Port,
+ Meta: a.Meta,
+ PMin: a.Vsn[0],
+ PMax: a.Vsn[1],
+ PCur: a.Vsn[2],
+ DMin: a.Vsn[3],
+ DMax: a.Vsn[4],
+ DCur: a.Vsn[5],
+ }
+ if err := m.config.Alive.NotifyAlive(node); err != nil {
+ m.logger.Printf("[WARN] memberlist: ignoring alive message for '%s': %s",
+ a.Node, err)
+ return
+ }
+ }
+
+ // Check if we've never seen this node before, and if not, then
+ // store this node in our node map.
+ if !ok {
+ state = &nodeState{
+ Node: Node{
+ Name: a.Node,
+ Addr: a.Addr,
+ Port: a.Port,
+ Meta: a.Meta,
+ },
+ State: stateDead,
+ }
+
+ // Add to map
+ m.nodeMap[a.Node] = state
+
+ // Get a random offset. This is important to ensure
+ // the failure detection bound is low on average. If all
+ // nodes did an append, failure detection bound would be
+ // very high.
+ n := len(m.nodes)
+ offset := randomOffset(n)
+
+ // Add at the end and swap with the node at the offset
+ m.nodes = append(m.nodes, state)
+ m.nodes[offset], m.nodes[n] = m.nodes[n], m.nodes[offset]
+
+ // Update numNodes after we've added a new node
+ atomic.AddUint32(&m.numNodes, 1)
+ }
+
+ // Check if this address is different than the existing node
+ if !bytes.Equal([]byte(state.Addr), a.Addr) || state.Port != a.Port {
+ m.logger.Printf("[ERR] memberlist: Conflicting address for %s. Mine: %v:%d Theirs: %v:%d",
+ state.Name, state.Addr, state.Port, net.IP(a.Addr), a.Port)
+
+ // Inform the conflict delegate if provided
+ if m.config.Conflict != nil {
+ other := Node{
+ Name: a.Node,
+ Addr: a.Addr,
+ Port: a.Port,
+ Meta: a.Meta,
+ }
+ m.config.Conflict.NotifyConflict(&state.Node, &other)
+ }
+ return
+ }
+
+ // Bail if the incarnation number is older, and this is not about us
+ isLocalNode := state.Name == m.config.Name
+ if a.Incarnation <= state.Incarnation && !isLocalNode {
+ return
+ }
+
+ // Bail if strictly less and this is about us
+ if a.Incarnation < state.Incarnation && isLocalNode {
+ return
+ }
+
+ // Clear out any suspicion timer that may be in effect.
+ delete(m.nodeTimers, a.Node)
+
+ // Store the old state and meta data
+ oldState := state.State
+ oldMeta := state.Meta
+
+ // If this is us we need to refute, otherwise re-broadcast
+ if !bootstrap && isLocalNode {
+ // Compute the version vector
+ versions := []uint8{
+ state.PMin, state.PMax, state.PCur,
+ state.DMin, state.DMax, state.DCur,
+ }
+
+ // If the Incarnation is the same, we need special handling, since it
+ // possible for the following situation to happen:
+ // 1) Start with configuration C, join cluster
+ // 2) Hard fail / Kill / Shutdown
+ // 3) Restart with configuration C', join cluster
+ //
+ // In this case, other nodes and the local node see the same incarnation,
+ // but the values may not be the same. For this reason, we always
+ // need to do an equality check for this Incarnation. In most cases,
+ // we just ignore, but we may need to refute.
+ //
+ if a.Incarnation == state.Incarnation &&
+ bytes.Equal(a.Meta, state.Meta) &&
+ bytes.Equal(a.Vsn, versions) {
+ return
+ }
+
+ m.refute(state, a.Incarnation)
+ m.logger.Printf("[WARN] memberlist: Refuting an alive message")
+ } else {
+ m.encodeBroadcastNotify(a.Node, aliveMsg, a, notify)
+
+ // Update protocol versions if it arrived
+ if len(a.Vsn) > 0 {
+ state.PMin = a.Vsn[0]
+ state.PMax = a.Vsn[1]
+ state.PCur = a.Vsn[2]
+ state.DMin = a.Vsn[3]
+ state.DMax = a.Vsn[4]
+ state.DCur = a.Vsn[5]
+ }
+
+ // Update the state and incarnation number
+ state.Incarnation = a.Incarnation
+ state.Meta = a.Meta
+ if state.State != stateAlive {
+ state.State = stateAlive
+ state.StateChange = time.Now()
+ }
+ }
+
+ // Update metrics
+ metrics.IncrCounter([]string{"memberlist", "msg", "alive"}, 1)
+
+ // Notify the delegate of any relevant updates
+ if m.config.Events != nil {
+ if oldState == stateDead {
+ // if Dead -> Alive, notify of join
+ m.config.Events.NotifyJoin(&state.Node)
+
+ } else if !bytes.Equal(oldMeta, state.Meta) {
+ // if Meta changed, trigger an update notification
+ m.config.Events.NotifyUpdate(&state.Node)
+ }
+ }
+}
+
+// suspectNode is invoked by the network layer when we get a message
+// about a suspect node
+func (m *Memberlist) suspectNode(s *suspect) {
+ m.nodeLock.Lock()
+ defer m.nodeLock.Unlock()
+ state, ok := m.nodeMap[s.Node]
+
+ // If we've never heard about this node before, ignore it
+ if !ok {
+ return
+ }
+
+ // Ignore old incarnation numbers
+ if s.Incarnation < state.Incarnation {
+ return
+ }
+
+ // See if there's a suspicion timer we can confirm. If the info is new
+ // to us we will go ahead and re-gossip it. This allows for multiple
+ // independent confirmations to flow even when a node probes a node
+ // that's already suspect.
+ if timer, ok := m.nodeTimers[s.Node]; ok {
+ if timer.Confirm(s.From) {
+ m.encodeAndBroadcast(s.Node, suspectMsg, s)
+ }
+ return
+ }
+
+ // Ignore non-alive nodes
+ if state.State != stateAlive {
+ return
+ }
+
+ // If this is us we need to refute, otherwise re-broadcast
+ if state.Name == m.config.Name {
+ m.refute(state, s.Incarnation)
+ m.logger.Printf("[WARN] memberlist: Refuting a suspect message (from: %s)", s.From)
+ return // Do not mark ourself suspect
+ } else {
+ m.encodeAndBroadcast(s.Node, suspectMsg, s)
+ }
+
+ // Update metrics
+ metrics.IncrCounter([]string{"memberlist", "msg", "suspect"}, 1)
+
+ // Update the state
+ state.Incarnation = s.Incarnation
+ state.State = stateSuspect
+ changeTime := time.Now()
+ state.StateChange = changeTime
+
+ // Setup a suspicion timer. Given that we don't have any known phase
+ // relationship with our peers, we set up k such that we hit the nominal
+ // timeout two probe intervals short of what we expect given the suspicion
+ // multiplier.
+ k := m.config.SuspicionMult - 2
+
+ // If there aren't enough nodes to give the expected confirmations, just
+ // set k to 0 to say that we don't expect any. Note we subtract 2 from n
+ // here to take out ourselves and the node being probed.
+ n := m.estNumNodes()
+ if n-2 < k {
+ k = 0
+ }
+
+ // Compute the timeouts based on the size of the cluster.
+ min := suspicionTimeout(m.config.SuspicionMult, n, m.config.ProbeInterval)
+ max := time.Duration(m.config.SuspicionMaxTimeoutMult) * min
+ fn := func(numConfirmations int) {
+ m.nodeLock.Lock()
+ state, ok := m.nodeMap[s.Node]
+ timeout := ok && state.State == stateSuspect && state.StateChange == changeTime
+ m.nodeLock.Unlock()
+
+ if timeout {
+ if k > 0 && numConfirmations < k {
+ metrics.IncrCounter([]string{"memberlist", "degraded", "timeout"}, 1)
+ }
+
+ m.logger.Printf("[INFO] memberlist: Marking %s as failed, suspect timeout reached (%d peer confirmations)",
+ state.Name, numConfirmations)
+ d := dead{Incarnation: state.Incarnation, Node: state.Name, From: m.config.Name}
+ m.deadNode(&d)
+ }
+ }
+ m.nodeTimers[s.Node] = newSuspicion(s.From, k, min, max, fn)
+}
+
+// deadNode is invoked by the network layer when we get a message
+// about a dead node
+func (m *Memberlist) deadNode(d *dead) {
+ m.nodeLock.Lock()
+ defer m.nodeLock.Unlock()
+ state, ok := m.nodeMap[d.Node]
+
+ // If we've never heard about this node before, ignore it
+ if !ok {
+ return
+ }
+
+ // Ignore old incarnation numbers
+ if d.Incarnation < state.Incarnation {
+ return
+ }
+
+ // Clear out any suspicion timer that may be in effect.
+ delete(m.nodeTimers, d.Node)
+
+ // Ignore if node is already dead
+ if state.State == stateDead {
+ return
+ }
+
+ // Check if this is us
+ if state.Name == m.config.Name {
+ // If we are not leaving we need to refute
+ if !m.hasLeft() {
+ m.refute(state, d.Incarnation)
+ m.logger.Printf("[WARN] memberlist: Refuting a dead message (from: %s)", d.From)
+ return // Do not mark ourself dead
+ }
+
+ // If we are leaving, we broadcast and wait
+ m.encodeBroadcastNotify(d.Node, deadMsg, d, m.leaveBroadcast)
+ } else {
+ m.encodeAndBroadcast(d.Node, deadMsg, d)
+ }
+
+ // Update metrics
+ metrics.IncrCounter([]string{"memberlist", "msg", "dead"}, 1)
+
+ // Update the state
+ state.Incarnation = d.Incarnation
+ state.State = stateDead
+ state.StateChange = time.Now()
+
+ // Notify of death
+ if m.config.Events != nil {
+ m.config.Events.NotifyLeave(&state.Node)
+ }
+}
+
+// mergeState is invoked by the network layer when we get a Push/Pull
+// state transfer
+func (m *Memberlist) mergeState(remote []pushNodeState) {
+ for _, r := range remote {
+ switch r.State {
+ case stateAlive:
+ a := alive{
+ Incarnation: r.Incarnation,
+ Node: r.Name,
+ Addr: r.Addr,
+ Port: r.Port,
+ Meta: r.Meta,
+ Vsn: r.Vsn,
+ }
+ m.aliveNode(&a, nil, false)
+
+ case stateDead:
+ // If the remote node believes a node is dead, we prefer to
+ // suspect that node instead of declaring it dead instantly
+ fallthrough
+ case stateSuspect:
+ s := suspect{Incarnation: r.Incarnation, Node: r.Name, From: m.config.Name}
+ m.suspectNode(&s)
+ }
+ }
+}
--- /dev/null
+package memberlist
+
+import (
+ "math"
+ "sync/atomic"
+ "time"
+)
+
+// suspicion manages the suspect timer for a node and provides an interface
+// to accelerate the timeout as we get more independent confirmations that
+// a node is suspect.
+type suspicion struct {
+ // n is the number of independent confirmations we've seen. This must
+ // be updated using atomic instructions to prevent contention with the
+ // timer callback.
+ n int32
+
+ // k is the number of independent confirmations we'd like to see in
+ // order to drive the timer to its minimum value.
+ k int32
+
+ // min is the minimum timer value.
+ min time.Duration
+
+ // max is the maximum timer value.
+ max time.Duration
+
+ // start captures the timestamp when we began the timer. This is used
+ // so we can calculate durations to feed the timer during updates in
+ // a way the achieves the overall time we'd like.
+ start time.Time
+
+ // timer is the underlying timer that implements the timeout.
+ timer *time.Timer
+
+ // f is the function to call when the timer expires. We hold on to this
+ // because there are cases where we call it directly.
+ timeoutFn func()
+
+ // confirmations is a map of "from" nodes that have confirmed a given
+ // node is suspect. This prevents double counting.
+ confirmations map[string]struct{}
+}
+
+// newSuspicion returns a timer started with the max time, and that will drive
+// to the min time after seeing k or more confirmations. The from node will be
+// excluded from confirmations since we might get our own suspicion message
+// gossiped back to us. The minimum time will be used if no confirmations are
+// called for (k <= 0).
+func newSuspicion(from string, k int, min time.Duration, max time.Duration, fn func(int)) *suspicion {
+ s := &suspicion{
+ k: int32(k),
+ min: min,
+ max: max,
+ confirmations: make(map[string]struct{}),
+ }
+
+ // Exclude the from node from any confirmations.
+ s.confirmations[from] = struct{}{}
+
+ // Pass the number of confirmations into the timeout function for
+ // easy telemetry.
+ s.timeoutFn = func() {
+ fn(int(atomic.LoadInt32(&s.n)))
+ }
+
+ // If there aren't any confirmations to be made then take the min
+ // time from the start.
+ timeout := max
+ if k < 1 {
+ timeout = min
+ }
+ s.timer = time.AfterFunc(timeout, s.timeoutFn)
+
+ // Capture the start time right after starting the timer above so
+ // we should always err on the side of a little longer timeout if
+ // there's any preemption that separates this and the step above.
+ s.start = time.Now()
+ return s
+}
+
+// remainingSuspicionTime takes the state variables of the suspicion timer and
+// calculates the remaining time to wait before considering a node dead. The
+// return value can be negative, so be prepared to fire the timer immediately in
+// that case.
+func remainingSuspicionTime(n, k int32, elapsed time.Duration, min, max time.Duration) time.Duration {
+ frac := math.Log(float64(n)+1.0) / math.Log(float64(k)+1.0)
+ raw := max.Seconds() - frac*(max.Seconds()-min.Seconds())
+ timeout := time.Duration(math.Floor(1000.0*raw)) * time.Millisecond
+ if timeout < min {
+ timeout = min
+ }
+
+ // We have to take into account the amount of time that has passed so
+ // far, so we get the right overall timeout.
+ return timeout - elapsed
+}
+
+// Confirm registers that a possibly new peer has also determined the given
+// node is suspect. This returns true if this was new information, and false
+// if it was a duplicate confirmation, or if we've got enough confirmations to
+// hit the minimum.
+func (s *suspicion) Confirm(from string) bool {
+ // If we've got enough confirmations then stop accepting them.
+ if atomic.LoadInt32(&s.n) >= s.k {
+ return false
+ }
+
+ // Only allow one confirmation from each possible peer.
+ if _, ok := s.confirmations[from]; ok {
+ return false
+ }
+ s.confirmations[from] = struct{}{}
+
+ // Compute the new timeout given the current number of confirmations and
+ // adjust the timer. If the timeout becomes negative *and* we can cleanly
+ // stop the timer then we will call the timeout function directly from
+ // here.
+ n := atomic.AddInt32(&s.n, 1)
+ elapsed := time.Now().Sub(s.start)
+ remaining := remainingSuspicionTime(n, s.k, elapsed, s.min, s.max)
+ if s.timer.Stop() {
+ if remaining > 0 {
+ s.timer.Reset(remaining)
+ } else {
+ go s.timeoutFn()
+ }
+ }
+ return true
+}
--- /dev/null
+#!/usr/bin/env bash
+set -e
+
+# The version must be supplied from the environment. Do not include the
+# leading "v".
+if [ -z $VERSION ]; then
+ echo "Please specify a version."
+ exit 1
+fi
+
+# Generate the tag.
+echo "==> Tagging version $VERSION..."
+git commit --allow-empty -a --gpg-sign=348FFC4C -m "Release v$VERSION"
+git tag -a -m "Version $VERSION" -s -u 348FFC4C "v${VERSION}" master
+
+exit 0
--- /dev/null
+# TODO
+* Dynamic RTT discovery
+ * Compute 99th percentile for ping/ack
+ * Better lower bound for ping/ack, faster failure detection
+* Dynamic MTU discovery
+ * Prevent lost updates, increases efficiency
--- /dev/null
+package memberlist
+
+import (
+ "net"
+ "time"
+)
+
+// Packet is used to provide some metadata about incoming packets from peers
+// over a packet connection, as well as the packet payload.
+type Packet struct {
+ // Buf has the raw contents of the packet.
+ Buf []byte
+
+ // From has the address of the peer. This is an actual net.Addr so we
+ // can expose some concrete details about incoming packets.
+ From net.Addr
+
+ // Timestamp is the time when the packet was received. This should be
+ // taken as close as possible to the actual receipt time to help make an
+ // accurate RTT measurements during probes.
+ Timestamp time.Time
+}
+
+// Transport is used to abstract over communicating with other peers. The packet
+// interface is assumed to be best-effort and the stream interface is assumed to
+// be reliable.
+type Transport interface {
+ // FinalAdvertiseAddr is given the user's configured values (which
+ // might be empty) and returns the desired IP and port to advertise to
+ // the rest of the cluster.
+ FinalAdvertiseAddr(ip string, port int) (net.IP, int, error)
+
+ // WriteTo is a packet-oriented interface that fires off the given
+ // payload to the given address in a connectionless fashion. This should
+ // return a time stamp that's as close as possible to when the packet
+ // was transmitted to help make accurate RTT measurements during probes.
+ //
+ // This is similar to net.PacketConn, though we didn't want to expose
+ // that full set of required methods to keep assumptions about the
+ // underlying plumbing to a minimum. We also treat the address here as a
+ // string, similar to Dial, so it's network neutral, so this usually is
+ // in the form of "host:port".
+ WriteTo(b []byte, addr string) (time.Time, error)
+
+ // PacketCh returns a channel that can be read to receive incoming
+ // packets from other peers. How this is set up for listening is left as
+ // an exercise for the concrete transport implementations.
+ PacketCh() <-chan *Packet
+
+ // DialTimeout is used to create a connection that allows us to perform
+ // two-way communication with a peer. This is generally more expensive
+ // than packet connections so is used for more infrequent operations
+ // such as anti-entropy or fallback probes if the packet-oriented probe
+ // failed.
+ DialTimeout(addr string, timeout time.Duration) (net.Conn, error)
+
+ // StreamCh returns a channel that can be read to handle incoming stream
+ // connections from other peers. How this is set up for listening is
+ // left as an exercise for the concrete transport implementations.
+ StreamCh() <-chan net.Conn
+
+ // Shutdown is called when memberlist is shutting down; this gives the
+ // transport a chance to clean up any listeners.
+ Shutdown() error
+}
--- /dev/null
+package memberlist
+
+import (
+ "bytes"
+ "compress/lzw"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "math"
+ "math/rand"
+ "net"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/hashicorp/go-msgpack/codec"
+ "github.com/sean-/seed"
+)
+
+// pushPullScale is the minimum number of nodes
+// before we start scaling the push/pull timing. The scale
+// effect is the log2(Nodes) - log2(pushPullScale). This means
+// that the 33rd node will cause us to double the interval,
+// while the 65th will triple it.
+const pushPullScaleThreshold = 32
+
+const (
+ // Constant litWidth 2-8
+ lzwLitWidth = 8
+)
+
+func init() {
+ seed.Init()
+}
+
+// Decode reverses the encode operation on a byte slice input
+func decode(buf []byte, out interface{}) error {
+ r := bytes.NewReader(buf)
+ hd := codec.MsgpackHandle{}
+ dec := codec.NewDecoder(r, &hd)
+ return dec.Decode(out)
+}
+
+// Encode writes an encoded object to a new bytes buffer
+func encode(msgType messageType, in interface{}) (*bytes.Buffer, error) {
+ buf := bytes.NewBuffer(nil)
+ buf.WriteByte(uint8(msgType))
+ hd := codec.MsgpackHandle{}
+ enc := codec.NewEncoder(buf, &hd)
+ err := enc.Encode(in)
+ return buf, err
+}
+
+// Returns a random offset between 0 and n
+func randomOffset(n int) int {
+ if n == 0 {
+ return 0
+ }
+ return int(rand.Uint32() % uint32(n))
+}
+
+// suspicionTimeout computes the timeout that should be used when
+// a node is suspected
+func suspicionTimeout(suspicionMult, n int, interval time.Duration) time.Duration {
+ nodeScale := math.Max(1.0, math.Log10(math.Max(1.0, float64(n))))
+ // multiply by 1000 to keep some precision because time.Duration is an int64 type
+ timeout := time.Duration(suspicionMult) * time.Duration(nodeScale*1000) * interval / 1000
+ return timeout
+}
+
+// retransmitLimit computes the limit of retransmissions
+func retransmitLimit(retransmitMult, n int) int {
+ nodeScale := math.Ceil(math.Log10(float64(n + 1)))
+ limit := retransmitMult * int(nodeScale)
+ return limit
+}
+
+// shuffleNodes randomly shuffles the input nodes using the Fisher-Yates shuffle
+func shuffleNodes(nodes []*nodeState) {
+ n := len(nodes)
+ for i := n - 1; i > 0; i-- {
+ j := rand.Intn(i + 1)
+ nodes[i], nodes[j] = nodes[j], nodes[i]
+ }
+}
+
+// pushPushScale is used to scale the time interval at which push/pull
+// syncs take place. It is used to prevent network saturation as the
+// cluster size grows
+func pushPullScale(interval time.Duration, n int) time.Duration {
+ // Don't scale until we cross the threshold
+ if n <= pushPullScaleThreshold {
+ return interval
+ }
+
+ multiplier := math.Ceil(math.Log2(float64(n))-math.Log2(pushPullScaleThreshold)) + 1.0
+ return time.Duration(multiplier) * interval
+}
+
+// moveDeadNodes moves nodes that are dead and beyond the gossip to the dead interval
+// to the end of the slice and returns the index of the first moved node.
+func moveDeadNodes(nodes []*nodeState, gossipToTheDeadTime time.Duration) int {
+ numDead := 0
+ n := len(nodes)
+ for i := 0; i < n-numDead; i++ {
+ if nodes[i].State != stateDead {
+ continue
+ }
+
+ // Respect the gossip to the dead interval
+ if time.Since(nodes[i].StateChange) <= gossipToTheDeadTime {
+ continue
+ }
+
+ // Move this node to the end
+ nodes[i], nodes[n-numDead-1] = nodes[n-numDead-1], nodes[i]
+ numDead++
+ i--
+ }
+ return n - numDead
+}
+
+// kRandomNodes is used to select up to k random nodes, excluding any nodes where
+// the filter function returns true. It is possible that less than k nodes are
+// returned.
+func kRandomNodes(k int, nodes []*nodeState, filterFn func(*nodeState) bool) []*nodeState {
+ n := len(nodes)
+ kNodes := make([]*nodeState, 0, k)
+OUTER:
+ // Probe up to 3*n times, with large n this is not necessary
+ // since k << n, but with small n we want search to be
+ // exhaustive
+ for i := 0; i < 3*n && len(kNodes) < k; i++ {
+ // Get random node
+ idx := randomOffset(n)
+ node := nodes[idx]
+
+ // Give the filter a shot at it.
+ if filterFn != nil && filterFn(node) {
+ continue OUTER
+ }
+
+ // Check if we have this node already
+ for j := 0; j < len(kNodes); j++ {
+ if node == kNodes[j] {
+ continue OUTER
+ }
+ }
+
+ // Append the node
+ kNodes = append(kNodes, node)
+ }
+ return kNodes
+}
+
+// makeCompoundMessage takes a list of messages and generates
+// a single compound message containing all of them
+func makeCompoundMessage(msgs [][]byte) *bytes.Buffer {
+ // Create a local buffer
+ buf := bytes.NewBuffer(nil)
+
+ // Write out the type
+ buf.WriteByte(uint8(compoundMsg))
+
+ // Write out the number of message
+ buf.WriteByte(uint8(len(msgs)))
+
+ // Add the message lengths
+ for _, m := range msgs {
+ binary.Write(buf, binary.BigEndian, uint16(len(m)))
+ }
+
+ // Append the messages
+ for _, m := range msgs {
+ buf.Write(m)
+ }
+
+ return buf
+}
+
+// decodeCompoundMessage splits a compound message and returns
+// the slices of individual messages. Also returns the number
+// of truncated messages and any potential error
+func decodeCompoundMessage(buf []byte) (trunc int, parts [][]byte, err error) {
+ if len(buf) < 1 {
+ err = fmt.Errorf("missing compound length byte")
+ return
+ }
+ numParts := uint8(buf[0])
+ buf = buf[1:]
+
+ // Check we have enough bytes
+ if len(buf) < int(numParts*2) {
+ err = fmt.Errorf("truncated len slice")
+ return
+ }
+
+ // Decode the lengths
+ lengths := make([]uint16, numParts)
+ for i := 0; i < int(numParts); i++ {
+ lengths[i] = binary.BigEndian.Uint16(buf[i*2 : i*2+2])
+ }
+ buf = buf[numParts*2:]
+
+ // Split each message
+ for idx, msgLen := range lengths {
+ if len(buf) < int(msgLen) {
+ trunc = int(numParts) - idx
+ return
+ }
+
+ // Extract the slice, seek past on the buffer
+ slice := buf[:msgLen]
+ buf = buf[msgLen:]
+ parts = append(parts, slice)
+ }
+ return
+}
+
+// Given a string of the form "host", "host:port",
+// "ipv6::addr" or "[ipv6::address]:port",
+// return true if the string includes a port.
+func hasPort(s string) bool {
+ last := strings.LastIndex(s, ":")
+ if last == -1 {
+ return false
+ }
+ if s[0] == '[' {
+ return s[last-1] == ']'
+ }
+ return strings.Index(s, ":") == last
+}
+
+// compressPayload takes an opaque input buffer, compresses it
+// and wraps it in a compress{} message that is encoded.
+func compressPayload(inp []byte) (*bytes.Buffer, error) {
+ var buf bytes.Buffer
+ compressor := lzw.NewWriter(&buf, lzw.LSB, lzwLitWidth)
+
+ _, err := compressor.Write(inp)
+ if err != nil {
+ return nil, err
+ }
+
+ // Ensure we flush everything out
+ if err := compressor.Close(); err != nil {
+ return nil, err
+ }
+
+ // Create a compressed message
+ c := compress{
+ Algo: lzwAlgo,
+ Buf: buf.Bytes(),
+ }
+ return encode(compressMsg, &c)
+}
+
+// decompressPayload is used to unpack an encoded compress{}
+// message and return its payload uncompressed
+func decompressPayload(msg []byte) ([]byte, error) {
+ // Decode the message
+ var c compress
+ if err := decode(msg, &c); err != nil {
+ return nil, err
+ }
+ return decompressBuffer(&c)
+}
+
+// decompressBuffer is used to decompress the buffer of
+// a single compress message, handling multiple algorithms
+func decompressBuffer(c *compress) ([]byte, error) {
+ // Verify the algorithm
+ if c.Algo != lzwAlgo {
+ return nil, fmt.Errorf("Cannot decompress unknown algorithm %d", c.Algo)
+ }
+
+ // Create a uncompressor
+ uncomp := lzw.NewReader(bytes.NewReader(c.Buf), lzw.LSB, lzwLitWidth)
+ defer uncomp.Close()
+
+ // Read all the data
+ var b bytes.Buffer
+ _, err := io.Copy(&b, uncomp)
+ if err != nil {
+ return nil, err
+ }
+
+ // Return the uncompressed bytes
+ return b.Bytes(), nil
+}
+
+// joinHostPort returns the host:port form of an address, for use with a
+// transport.
+func joinHostPort(host string, port uint16) string {
+ return net.JoinHostPort(host, strconv.Itoa(int(port)))
+}
--- /dev/null
+Copyright (c) 2013 Julien Schmidt. All rights reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * The names of the contributors may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL JULIEN SCHMIDT BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
--- /dev/null
+# HttpRouter [](https://travis-ci.org/julienschmidt/httprouter) [](https://coveralls.io/github/julienschmidt/httprouter?branch=master) [](http://godoc.org/github.com/julienschmidt/httprouter)
+
+HttpRouter is a lightweight high performance HTTP request router (also called *multiplexer* or just *mux* for short) for [Go](https://golang.org/).
+
+In contrast to the [default mux](https://golang.org/pkg/net/http/#ServeMux) of Go's `net/http` package, this router supports variables in the routing pattern and matches against the request method. It also scales better.
+
+The router is optimized for high performance and a small memory footprint. It scales well even with very long paths and a large number of routes. A compressing dynamic trie (radix tree) structure is used for efficient matching.
+
+## Features
+
+**Only explicit matches:** With other routers, like [`http.ServeMux`](https://golang.org/pkg/net/http/#ServeMux), a requested URL path could match multiple patterns. Therefore they have some awkward pattern priority rules, like *longest match* or *first registered, first matched*. By design of this router, a request can only match exactly one or no route. As a result, there are also no unintended matches, which makes it great for SEO and improves the user experience.
+
+**Stop caring about trailing slashes:** Choose the URL style you like, the router automatically redirects the client if a trailing slash is missing or if there is one extra. Of course it only does so, if the new path has a handler. If you don't like it, you can [turn off this behavior](https://godoc.org/github.com/julienschmidt/httprouter#Router.RedirectTrailingSlash).
+
+**Path auto-correction:** Besides detecting the missing or additional trailing slash at no extra cost, the router can also fix wrong cases and remove superfluous path elements (like `../` or `//`). Is [CAPTAIN CAPS LOCK](http://www.urbandictionary.com/define.php?term=Captain+Caps+Lock) one of your users? HttpRouter can help him by making a case-insensitive look-up and redirecting him to the correct URL.
+
+**Parameters in your routing pattern:** Stop parsing the requested URL path, just give the path segment a name and the router delivers the dynamic value to you. Because of the design of the router, path parameters are very cheap.
+
+**Zero Garbage:** The matching and dispatching process generates zero bytes of garbage. In fact, the only heap allocations that are made, is by building the slice of the key-value pairs for path parameters. If the request path contains no parameters, not a single heap allocation is necessary.
+
+**Best Performance:** [Benchmarks speak for themselves](https://github.com/julienschmidt/go-http-routing-benchmark). See below for technical details of the implementation.
+
+**No more server crashes:** You can set a [Panic handler](https://godoc.org/github.com/julienschmidt/httprouter#Router.PanicHandler) to deal with panics occurring during handling a HTTP request. The router then recovers and lets the `PanicHandler` log what happened and deliver a nice error page.
+
+**Perfect for APIs:** The router design encourages to build sensible, hierarchical RESTful APIs. Moreover it has builtin native support for [OPTIONS requests](http://zacstewart.com/2012/04/14/http-options-method.html) and `405 Method Not Allowed` replies.
+
+Of course you can also set **custom [`NotFound`](https://godoc.org/github.com/julienschmidt/httprouter#Router.NotFound) and [`MethodNotAllowed`](https://godoc.org/github.com/julienschmidt/httprouter#Router.MethodNotAllowed) handlers** and [**serve static files**](https://godoc.org/github.com/julienschmidt/httprouter#Router.ServeFiles).
+
+## Usage
+
+This is just a quick introduction, view the [GoDoc](http://godoc.org/github.com/julienschmidt/httprouter) for details.
+
+Let's start with a trivial example:
+
+```go
+package main
+
+import (
+ "fmt"
+ "github.com/julienschmidt/httprouter"
+ "net/http"
+ "log"
+)
+
+func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
+ fmt.Fprint(w, "Welcome!\n")
+}
+
+func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
+ fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name"))
+}
+
+func main() {
+ router := httprouter.New()
+ router.GET("/", Index)
+ router.GET("/hello/:name", Hello)
+
+ log.Fatal(http.ListenAndServe(":8080", router))
+}
+```
+
+### Named parameters
+
+As you can see, `:name` is a *named parameter*. The values are accessible via `httprouter.Params`, which is just a slice of `httprouter.Param`s. You can get the value of a parameter either by its index in the slice, or by using the `ByName(name)` method: `:name` can be retrived by `ByName("name")`.
+
+Named parameters only match a single path segment:
+
+```
+Pattern: /user/:user
+
+ /user/gordon match
+ /user/you match
+ /user/gordon/profile no match
+ /user/ no match
+```
+
+**Note:** Since this router has only explicit matches, you can not register static routes and parameters for the same path segment. For example you can not register the patterns `/user/new` and `/user/:user` for the same request method at the same time. The routing of different request methods is independent from each other.
+
+### Catch-All parameters
+
+The second type are *catch-all* parameters and have the form `*name`. Like the name suggests, they match everything. Therefore they must always be at the **end** of the pattern:
+
+```
+Pattern: /src/*filepath
+
+ /src/ match
+ /src/somefile.go match
+ /src/subdir/somefile.go match
+```
+
+## How does it work?
+
+The router relies on a tree structure which makes heavy use of *common prefixes*, it is basically a *compact* [*prefix tree*](https://en.wikipedia.org/wiki/Trie) (or just [*Radix tree*](https://en.wikipedia.org/wiki/Radix_tree)). Nodes with a common prefix also share a common parent. Here is a short example what the routing tree for the `GET` request method could look like:
+
+```
+Priority Path Handle
+9 \ *<1>
+3 ├s nil
+2 |├earch\ *<2>
+1 |└upport\ *<3>
+2 ├blog\ *<4>
+1 | └:post nil
+1 | └\ *<5>
+2 ├about-us\ *<6>
+1 | └team\ *<7>
+1 └contact\ *<8>
+```
+
+Every `*<num>` represents the memory address of a handler function (a pointer). If you follow a path trough the tree from the root to the leaf, you get the complete route path, e.g `\blog\:post\`, where `:post` is just a placeholder ([*parameter*](#named-parameters)) for an actual post name. Unlike hash-maps, a tree structure also allows us to use dynamic parts like the `:post` parameter, since we actually match against the routing patterns instead of just comparing hashes. [As benchmarks show](https://github.com/julienschmidt/go-http-routing-benchmark), this works very well and efficient.
+
+Since URL paths have a hierarchical structure and make use only of a limited set of characters (byte values), it is very likely that there are a lot of common prefixes. This allows us to easily reduce the routing into ever smaller problems. Moreover the router manages a separate tree for every request method. For one thing it is more space efficient than holding a method->handle map in every single node, for another thing is also allows us to greatly reduce the routing problem before even starting the look-up in the prefix-tree.
+
+For even better scalability, the child nodes on each tree level are ordered by priority, where the priority is just the number of handles registered in sub nodes (children, grandchildren, and so on..). This helps in two ways:
+
+1. Nodes which are part of the most routing paths are evaluated first. This helps to make as much routes as possible to be reachable as fast as possible.
+2. It is some sort of cost compensation. The longest reachable path (highest cost) can always be evaluated first. The following scheme visualizes the tree structure. Nodes are evaluated from top to bottom and from left to right.
+
+```
+├------------
+├---------
+├-----
+├----
+├--
+├--
+└-
+```
+
+## Why doesn't this work with `http.Handler`?
+
+**It does!** The router itself implements the `http.Handler` interface. Moreover the router provides convenient [adapters for `http.Handler`](https://godoc.org/github.com/julienschmidt/httprouter#Router.Handler)s and [`http.HandlerFunc`](https://godoc.org/github.com/julienschmidt/httprouter#Router.HandlerFunc)s which allows them to be used as a [`httprouter.Handle`](https://godoc.org/github.com/julienschmidt/httprouter#Router.Handle) when registering a route. The only disadvantage is, that no parameter values can be retrieved when a `http.Handler` or `http.HandlerFunc` is used, since there is no efficient way to pass the values with the existing function parameters. Therefore [`httprouter.Handle`](https://godoc.org/github.com/julienschmidt/httprouter#Router.Handle) has a third function parameter.
+
+Just try it out for yourself, the usage of HttpRouter is very straightforward. The package is compact and minimalistic, but also probably one of the easiest routers to set up.
+
+## Where can I find Middleware *X*?
+
+This package just provides a very efficient request router with a few extra features. The router is just a [`http.Handler`](https://golang.org/pkg/net/http/#Handler), you can chain any http.Handler compatible middleware before the router, for example the [Gorilla handlers](http://www.gorillatoolkit.org/pkg/handlers). Or you could [just write your own](https://justinas.org/writing-http-middleware-in-go/), it's very easy!
+
+Alternatively, you could try [a web framework based on HttpRouter](#web-frameworks-based-on-httprouter).
+
+### Multi-domain / Sub-domains
+
+Here is a quick example: Does your server serve multiple domains / hosts?
+You want to use sub-domains?
+Define a router per host!
+
+```go
+// We need an object that implements the http.Handler interface.
+// Therefore we need a type for which we implement the ServeHTTP method.
+// We just use a map here, in which we map host names (with port) to http.Handlers
+type HostSwitch map[string]http.Handler
+
+// Implement the ServerHTTP method on our new type
+func (hs HostSwitch) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ // Check if a http.Handler is registered for the given host.
+ // If yes, use it to handle the request.
+ if handler := hs[r.Host]; handler != nil {
+ handler.ServeHTTP(w, r)
+ } else {
+ // Handle host names for wich no handler is registered
+ http.Error(w, "Forbidden", 403) // Or Redirect?
+ }
+}
+
+func main() {
+ // Initialize a router as usual
+ router := httprouter.New()
+ router.GET("/", Index)
+ router.GET("/hello/:name", Hello)
+
+ // Make a new HostSwitch and insert the router (our http handler)
+ // for example.com and port 12345
+ hs := make(HostSwitch)
+ hs["example.com:12345"] = router
+
+ // Use the HostSwitch to listen and serve on port 12345
+ log.Fatal(http.ListenAndServe(":12345", hs))
+}
+```
+
+### Basic Authentication
+
+Another quick example: Basic Authentication (RFC 2617) for handles:
+
+```go
+package main
+
+import (
+ "fmt"
+ "log"
+ "net/http"
+
+ "github.com/julienschmidt/httprouter"
+)
+
+func BasicAuth(h httprouter.Handle, requiredUser, requiredPassword string) httprouter.Handle {
+ return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
+ // Get the Basic Authentication credentials
+ user, password, hasAuth := r.BasicAuth()
+
+ if hasAuth && user == requiredUser && password == requiredPassword {
+ // Delegate request to the given handle
+ h(w, r, ps)
+ } else {
+ // Request Basic Authentication otherwise
+ w.Header().Set("WWW-Authenticate", "Basic realm=Restricted")
+ http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
+ }
+ }
+}
+
+func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
+ fmt.Fprint(w, "Not protected!\n")
+}
+
+func Protected(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
+ fmt.Fprint(w, "Protected!\n")
+}
+
+func main() {
+ user := "gordon"
+ pass := "secret!"
+
+ router := httprouter.New()
+ router.GET("/", Index)
+ router.GET("/protected/", BasicAuth(Protected, user, pass))
+
+ log.Fatal(http.ListenAndServe(":8080", router))
+}
+```
+
+## Chaining with the NotFound handler
+
+**NOTE: It might be required to set [`Router.HandleMethodNotAllowed`](https://godoc.org/github.com/julienschmidt/httprouter#Router.HandleMethodNotAllowed) to `false` to avoid problems.**
+
+You can use another [`http.Handler`](https://golang.org/pkg/net/http/#Handler), for example another router, to handle requests which could not be matched by this router by using the [`Router.NotFound`](https://godoc.org/github.com/julienschmidt/httprouter#Router.NotFound) handler. This allows chaining.
+
+### Static files
+
+The `NotFound` handler can for example be used to serve static files from the root path `/` (like an `index.html` file along with other assets):
+
+```go
+// Serve static files from the ./public directory
+router.NotFound = http.FileServer(http.Dir("public"))
+```
+
+But this approach sidesteps the strict core rules of this router to avoid routing problems. A cleaner approach is to use a distinct sub-path for serving files, like `/static/*filepath` or `/files/*filepath`.
+
+## Web Frameworks based on HttpRouter
+
+If the HttpRouter is a bit too minimalistic for you, you might try one of the following more high-level 3rd-party web frameworks building upon the HttpRouter package:
+
+* [Ace](https://github.com/plimble/ace): Blazing fast Go Web Framework
+* [api2go](https://github.com/manyminds/api2go): A JSON API Implementation for Go
+* [Gin](https://github.com/gin-gonic/gin): Features a martini-like API with much better performance
+* [Goat](https://github.com/bahlo/goat): A minimalistic REST API server in Go
+* [goMiddlewareChain](https://github.com/TobiEiss/goMiddlewareChain): An express.js-like-middleware-chain
+* [Hikaru](https://github.com/najeira/hikaru): Supports standalone and Google AppEngine
+* [Hitch](https://github.com/nbio/hitch): Hitch ties httprouter, [httpcontext](https://github.com/nbio/httpcontext), and middleware up in a bow
+* [httpway](https://github.com/corneldamian/httpway): Simple middleware extension with context for httprouter and a server with gracefully shutdown support
+* [kami](https://github.com/guregu/kami): A tiny web framework using x/net/context
+* [Medeina](https://github.com/imdario/medeina): Inspired by Ruby's Roda and Cuba
+* [Neko](https://github.com/rocwong/neko): A lightweight web application framework for Golang
+* [River](https://github.com/abiosoft/river): River is a simple and lightweight REST server
+* [Roxanna](https://github.com/iamthemuffinman/Roxanna): An amalgamation of httprouter, better logging, and hot reload
+* [siesta](https://github.com/VividCortex/siesta): Composable HTTP handlers with contexts
+* [xmux](https://github.com/rs/xmux): xmux is a httprouter fork on top of xhandler (net/context aware)
--- /dev/null
+// Copyright 2013 Julien Schmidt. All rights reserved.
+// Based on the path package, Copyright 2009 The Go Authors.
+// Use of this source code is governed by a BSD-style license that can be found
+// in the LICENSE file.
+
+package httprouter
+
+// CleanPath is the URL version of path.Clean, it returns a canonical URL path
+// for p, eliminating . and .. elements.
+//
+// The following rules are applied iteratively until no further processing can
+// be done:
+// 1. Replace multiple slashes with a single slash.
+// 2. Eliminate each . path name element (the current directory).
+// 3. Eliminate each inner .. path name element (the parent directory)
+// along with the non-.. element that precedes it.
+// 4. Eliminate .. elements that begin a rooted path:
+// that is, replace "/.." by "/" at the beginning of a path.
+//
+// If the result of this process is an empty string, "/" is returned
+func CleanPath(p string) string {
+ // Turn empty string into "/"
+ if p == "" {
+ return "/"
+ }
+
+ n := len(p)
+ var buf []byte
+
+ // Invariants:
+ // reading from path; r is index of next byte to process.
+ // writing to buf; w is index of next byte to write.
+
+ // path must start with '/'
+ r := 1
+ w := 1
+
+ if p[0] != '/' {
+ r = 0
+ buf = make([]byte, n+1)
+ buf[0] = '/'
+ }
+
+ trailing := n > 2 && p[n-1] == '/'
+
+ // A bit more clunky without a 'lazybuf' like the path package, but the loop
+ // gets completely inlined (bufApp). So in contrast to the path package this
+ // loop has no expensive function calls (except 1x make)
+
+ for r < n {
+ switch {
+ case p[r] == '/':
+ // empty path element, trailing slash is added after the end
+ r++
+
+ case p[r] == '.' && r+1 == n:
+ trailing = true
+ r++
+
+ case p[r] == '.' && p[r+1] == '/':
+ // . element
+ r++
+
+ case p[r] == '.' && p[r+1] == '.' && (r+2 == n || p[r+2] == '/'):
+ // .. element: remove to last /
+ r += 2
+
+ if w > 1 {
+ // can backtrack
+ w--
+
+ if buf == nil {
+ for w > 1 && p[w] != '/' {
+ w--
+ }
+ } else {
+ for w > 1 && buf[w] != '/' {
+ w--
+ }
+ }
+ }
+
+ default:
+ // real path element.
+ // add slash if needed
+ if w > 1 {
+ bufApp(&buf, p, w, '/')
+ w++
+ }
+
+ // copy element
+ for r < n && p[r] != '/' {
+ bufApp(&buf, p, w, p[r])
+ w++
+ r++
+ }
+ }
+ }
+
+ // re-append trailing slash
+ if trailing && w > 1 {
+ bufApp(&buf, p, w, '/')
+ w++
+ }
+
+ if buf == nil {
+ return p[:w]
+ }
+ return string(buf[:w])
+}
+
+// internal helper to lazily create a buffer if necessary
+func bufApp(buf *[]byte, s string, w int, c byte) {
+ if *buf == nil {
+ if s[w] == c {
+ return
+ }
+
+ *buf = make([]byte, len(s))
+ copy(*buf, s[:w])
+ }
+ (*buf)[w] = c
+}
--- /dev/null
+// Copyright 2013 Julien Schmidt. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be found
+// in the LICENSE file.
+
+// Package httprouter is a trie based high performance HTTP request router.
+//
+// A trivial example is:
+//
+// package main
+//
+// import (
+// "fmt"
+// "github.com/julienschmidt/httprouter"
+// "net/http"
+// "log"
+// )
+//
+// func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
+// fmt.Fprint(w, "Welcome!\n")
+// }
+//
+// func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
+// fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name"))
+// }
+//
+// func main() {
+// router := httprouter.New()
+// router.GET("/", Index)
+// router.GET("/hello/:name", Hello)
+//
+// log.Fatal(http.ListenAndServe(":8080", router))
+// }
+//
+// The router matches incoming requests by the request method and the path.
+// If a handle is registered for this path and method, the router delegates the
+// request to that function.
+// For the methods GET, POST, PUT, PATCH and DELETE shortcut functions exist to
+// register handles, for all other methods router.Handle can be used.
+//
+// The registered path, against which the router matches incoming requests, can
+// contain two types of parameters:
+// Syntax Type
+// :name named parameter
+// *name catch-all parameter
+//
+// Named parameters are dynamic path segments. They match anything until the
+// next '/' or the path end:
+// Path: /blog/:category/:post
+//
+// Requests:
+// /blog/go/request-routers match: category="go", post="request-routers"
+// /blog/go/request-routers/ no match, but the router would redirect
+// /blog/go/ no match
+// /blog/go/request-routers/comments no match
+//
+// Catch-all parameters match anything until the path end, including the
+// directory index (the '/' before the catch-all). Since they match anything
+// until the end, catch-all parameters must always be the final path element.
+// Path: /files/*filepath
+//
+// Requests:
+// /files/ match: filepath="/"
+// /files/LICENSE match: filepath="/LICENSE"
+// /files/templates/article.html match: filepath="/templates/article.html"
+// /files no match, but the router would redirect
+//
+// The value of parameters is saved as a slice of the Param struct, consisting
+// each of a key and a value. The slice is passed to the Handle func as a third
+// parameter.
+// There are two ways to retrieve the value of a parameter:
+// // by the name of the parameter
+// user := ps.ByName("user") // defined by :user or *user
+//
+// // by the index of the parameter. This way you can also get the name (key)
+// thirdKey := ps[2].Key // the name of the 3rd parameter
+// thirdValue := ps[2].Value // the value of the 3rd parameter
+package httprouter
+
+import (
+ "net/http"
+)
+
+// Handle is a function that can be registered to a route to handle HTTP
+// requests. Like http.HandlerFunc, but has a third parameter for the values of
+// wildcards (variables).
+type Handle func(http.ResponseWriter, *http.Request, Params)
+
+// Param is a single URL parameter, consisting of a key and a value.
+type Param struct {
+ Key string
+ Value string
+}
+
+// Params is a Param-slice, as returned by the router.
+// The slice is ordered, the first URL parameter is also the first slice value.
+// It is therefore safe to read values by the index.
+type Params []Param
+
+// ByName returns the value of the first Param which key matches the given name.
+// If no matching Param is found, an empty string is returned.
+func (ps Params) ByName(name string) string {
+ for i := range ps {
+ if ps[i].Key == name {
+ return ps[i].Value
+ }
+ }
+ return ""
+}
+
+// Router is a http.Handler which can be used to dispatch requests to different
+// handler functions via configurable routes
+type Router struct {
+ trees map[string]*node
+
+ // Enables automatic redirection if the current route can't be matched but a
+ // handler for the path with (without) the trailing slash exists.
+ // For example if /foo/ is requested but a route only exists for /foo, the
+ // client is redirected to /foo with http status code 301 for GET requests
+ // and 307 for all other request methods.
+ RedirectTrailingSlash bool
+
+ // If enabled, the router tries to fix the current request path, if no
+ // handle is registered for it.
+ // First superfluous path elements like ../ or // are removed.
+ // Afterwards the router does a case-insensitive lookup of the cleaned path.
+ // If a handle can be found for this route, the router makes a redirection
+ // to the corrected path with status code 301 for GET requests and 307 for
+ // all other request methods.
+ // For example /FOO and /..//Foo could be redirected to /foo.
+ // RedirectTrailingSlash is independent of this option.
+ RedirectFixedPath bool
+
+ // If enabled, the router checks if another method is allowed for the
+ // current route, if the current request can not be routed.
+ // If this is the case, the request is answered with 'Method Not Allowed'
+ // and HTTP status code 405.
+ // If no other Method is allowed, the request is delegated to the NotFound
+ // handler.
+ HandleMethodNotAllowed bool
+
+ // If enabled, the router automatically replies to OPTIONS requests.
+ // Custom OPTIONS handlers take priority over automatic replies.
+ HandleOPTIONS bool
+
+ // Configurable http.Handler which is called when no matching route is
+ // found. If it is not set, http.NotFound is used.
+ NotFound http.Handler
+
+ // Configurable http.Handler which is called when a request
+ // cannot be routed and HandleMethodNotAllowed is true.
+ // If it is not set, http.Error with http.StatusMethodNotAllowed is used.
+ // The "Allow" header with allowed request methods is set before the handler
+ // is called.
+ MethodNotAllowed http.Handler
+
+ // Function to handle panics recovered from http handlers.
+ // It should be used to generate a error page and return the http error code
+ // 500 (Internal Server Error).
+ // The handler can be used to keep your server from crashing because of
+ // unrecovered panics.
+ PanicHandler func(http.ResponseWriter, *http.Request, interface{})
+}
+
+// Make sure the Router conforms with the http.Handler interface
+var _ http.Handler = New()
+
+// New returns a new initialized Router.
+// Path auto-correction, including trailing slashes, is enabled by default.
+func New() *Router {
+ return &Router{
+ RedirectTrailingSlash: true,
+ RedirectFixedPath: true,
+ HandleMethodNotAllowed: true,
+ HandleOPTIONS: true,
+ }
+}
+
+// GET is a shortcut for router.Handle("GET", path, handle)
+func (r *Router) GET(path string, handle Handle) {
+ r.Handle("GET", path, handle)
+}
+
+// HEAD is a shortcut for router.Handle("HEAD", path, handle)
+func (r *Router) HEAD(path string, handle Handle) {
+ r.Handle("HEAD", path, handle)
+}
+
+// OPTIONS is a shortcut for router.Handle("OPTIONS", path, handle)
+func (r *Router) OPTIONS(path string, handle Handle) {
+ r.Handle("OPTIONS", path, handle)
+}
+
+// POST is a shortcut for router.Handle("POST", path, handle)
+func (r *Router) POST(path string, handle Handle) {
+ r.Handle("POST", path, handle)
+}
+
+// PUT is a shortcut for router.Handle("PUT", path, handle)
+func (r *Router) PUT(path string, handle Handle) {
+ r.Handle("PUT", path, handle)
+}
+
+// PATCH is a shortcut for router.Handle("PATCH", path, handle)
+func (r *Router) PATCH(path string, handle Handle) {
+ r.Handle("PATCH", path, handle)
+}
+
+// DELETE is a shortcut for router.Handle("DELETE", path, handle)
+func (r *Router) DELETE(path string, handle Handle) {
+ r.Handle("DELETE", path, handle)
+}
+
+// Handle registers a new request handle with the given path and method.
+//
+// For GET, POST, PUT, PATCH and DELETE requests the respective shortcut
+// functions can be used.
+//
+// This function is intended for bulk loading and to allow the usage of less
+// frequently used, non-standardized or custom methods (e.g. for internal
+// communication with a proxy).
+func (r *Router) Handle(method, path string, handle Handle) {
+ if path[0] != '/' {
+ panic("path must begin with '/' in path '" + path + "'")
+ }
+
+ if r.trees == nil {
+ r.trees = make(map[string]*node)
+ }
+
+ root := r.trees[method]
+ if root == nil {
+ root = new(node)
+ r.trees[method] = root
+ }
+
+ root.addRoute(path, handle)
+}
+
+// Handler is an adapter which allows the usage of an http.Handler as a
+// request handle.
+func (r *Router) Handler(method, path string, handler http.Handler) {
+ r.Handle(method, path,
+ func(w http.ResponseWriter, req *http.Request, _ Params) {
+ handler.ServeHTTP(w, req)
+ },
+ )
+}
+
+// HandlerFunc is an adapter which allows the usage of an http.HandlerFunc as a
+// request handle.
+func (r *Router) HandlerFunc(method, path string, handler http.HandlerFunc) {
+ r.Handler(method, path, handler)
+}
+
+// ServeFiles serves files from the given file system root.
+// The path must end with "/*filepath", files are then served from the local
+// path /defined/root/dir/*filepath.
+// For example if root is "/etc" and *filepath is "passwd", the local file
+// "/etc/passwd" would be served.
+// Internally a http.FileServer is used, therefore http.NotFound is used instead
+// of the Router's NotFound handler.
+// To use the operating system's file system implementation,
+// use http.Dir:
+// router.ServeFiles("/src/*filepath", http.Dir("/var/www"))
+func (r *Router) ServeFiles(path string, root http.FileSystem) {
+ if len(path) < 10 || path[len(path)-10:] != "/*filepath" {
+ panic("path must end with /*filepath in path '" + path + "'")
+ }
+
+ fileServer := http.FileServer(root)
+
+ r.GET(path, func(w http.ResponseWriter, req *http.Request, ps Params) {
+ req.URL.Path = ps.ByName("filepath")
+ fileServer.ServeHTTP(w, req)
+ })
+}
+
+func (r *Router) recv(w http.ResponseWriter, req *http.Request) {
+ if rcv := recover(); rcv != nil {
+ r.PanicHandler(w, req, rcv)
+ }
+}
+
+// Lookup allows the manual lookup of a method + path combo.
+// This is e.g. useful to build a framework around this router.
+// If the path was found, it returns the handle function and the path parameter
+// values. Otherwise the third return value indicates whether a redirection to
+// the same path with an extra / without the trailing slash should be performed.
+func (r *Router) Lookup(method, path string) (Handle, Params, bool) {
+ if root := r.trees[method]; root != nil {
+ return root.getValue(path)
+ }
+ return nil, nil, false
+}
+
+func (r *Router) allowed(path, reqMethod string) (allow string) {
+ if path == "*" { // server-wide
+ for method := range r.trees {
+ if method == "OPTIONS" {
+ continue
+ }
+
+ // add request method to list of allowed methods
+ if len(allow) == 0 {
+ allow = method
+ } else {
+ allow += ", " + method
+ }
+ }
+ } else { // specific path
+ for method := range r.trees {
+ // Skip the requested method - we already tried this one
+ if method == reqMethod || method == "OPTIONS" {
+ continue
+ }
+
+ handle, _, _ := r.trees[method].getValue(path)
+ if handle != nil {
+ // add request method to list of allowed methods
+ if len(allow) == 0 {
+ allow = method
+ } else {
+ allow += ", " + method
+ }
+ }
+ }
+ }
+ if len(allow) > 0 {
+ allow += ", OPTIONS"
+ }
+ return
+}
+
+// ServeHTTP makes the router implement the http.Handler interface.
+func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ if r.PanicHandler != nil {
+ defer r.recv(w, req)
+ }
+
+ path := req.URL.Path
+
+ if root := r.trees[req.Method]; root != nil {
+ if handle, ps, tsr := root.getValue(path); handle != nil {
+ handle(w, req, ps)
+ return
+ } else if req.Method != "CONNECT" && path != "/" {
+ code := 301 // Permanent redirect, request with GET method
+ if req.Method != "GET" {
+ // Temporary redirect, request with same method
+ // As of Go 1.3, Go does not support status code 308.
+ code = 307
+ }
+
+ if tsr && r.RedirectTrailingSlash {
+ if len(path) > 1 && path[len(path)-1] == '/' {
+ req.URL.Path = path[:len(path)-1]
+ } else {
+ req.URL.Path = path + "/"
+ }
+ http.Redirect(w, req, req.URL.String(), code)
+ return
+ }
+
+ // Try to fix the request path
+ if r.RedirectFixedPath {
+ fixedPath, found := root.findCaseInsensitivePath(
+ CleanPath(path),
+ r.RedirectTrailingSlash,
+ )
+ if found {
+ req.URL.Path = string(fixedPath)
+ http.Redirect(w, req, req.URL.String(), code)
+ return
+ }
+ }
+ }
+ }
+
+ if req.Method == "OPTIONS" {
+ // Handle OPTIONS requests
+ if r.HandleOPTIONS {
+ if allow := r.allowed(path, req.Method); len(allow) > 0 {
+ w.Header().Set("Allow", allow)
+ return
+ }
+ }
+ } else {
+ // Handle 405
+ if r.HandleMethodNotAllowed {
+ if allow := r.allowed(path, req.Method); len(allow) > 0 {
+ w.Header().Set("Allow", allow)
+ if r.MethodNotAllowed != nil {
+ r.MethodNotAllowed.ServeHTTP(w, req)
+ } else {
+ http.Error(w,
+ http.StatusText(http.StatusMethodNotAllowed),
+ http.StatusMethodNotAllowed,
+ )
+ }
+ return
+ }
+ }
+ }
+
+ // Handle 404
+ if r.NotFound != nil {
+ r.NotFound.ServeHTTP(w, req)
+ } else {
+ http.NotFound(w, req)
+ }
+}
--- /dev/null
+// Copyright 2013 Julien Schmidt. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be found
+// in the LICENSE file.
+
+package httprouter
+
+import (
+ "strings"
+ "unicode"
+ "unicode/utf8"
+)
+
+func min(a, b int) int {
+ if a <= b {
+ return a
+ }
+ return b
+}
+
+func countParams(path string) uint8 {
+ var n uint
+ for i := 0; i < len(path); i++ {
+ if path[i] != ':' && path[i] != '*' {
+ continue
+ }
+ n++
+ }
+ if n >= 255 {
+ return 255
+ }
+ return uint8(n)
+}
+
+type nodeType uint8
+
+const (
+ static nodeType = iota // default
+ root
+ param
+ catchAll
+)
+
+type node struct {
+ path string
+ wildChild bool
+ nType nodeType
+ maxParams uint8
+ indices string
+ children []*node
+ handle Handle
+ priority uint32
+}
+
+// increments priority of the given child and reorders if necessary
+func (n *node) incrementChildPrio(pos int) int {
+ n.children[pos].priority++
+ prio := n.children[pos].priority
+
+ // adjust position (move to front)
+ newPos := pos
+ for newPos > 0 && n.children[newPos-1].priority < prio {
+ // swap node positions
+ n.children[newPos-1], n.children[newPos] = n.children[newPos], n.children[newPos-1]
+
+ newPos--
+ }
+
+ // build new index char string
+ if newPos != pos {
+ n.indices = n.indices[:newPos] + // unchanged prefix, might be empty
+ n.indices[pos:pos+1] + // the index char we move
+ n.indices[newPos:pos] + n.indices[pos+1:] // rest without char at 'pos'
+ }
+
+ return newPos
+}
+
+// addRoute adds a node with the given handle to the path.
+// Not concurrency-safe!
+func (n *node) addRoute(path string, handle Handle) {
+ fullPath := path
+ n.priority++
+ numParams := countParams(path)
+
+ // non-empty tree
+ if len(n.path) > 0 || len(n.children) > 0 {
+ walk:
+ for {
+ // Update maxParams of the current node
+ if numParams > n.maxParams {
+ n.maxParams = numParams
+ }
+
+ // Find the longest common prefix.
+ // This also implies that the common prefix contains no ':' or '*'
+ // since the existing key can't contain those chars.
+ i := 0
+ max := min(len(path), len(n.path))
+ for i < max && path[i] == n.path[i] {
+ i++
+ }
+
+ // Split edge
+ if i < len(n.path) {
+ child := node{
+ path: n.path[i:],
+ wildChild: n.wildChild,
+ nType: static,
+ indices: n.indices,
+ children: n.children,
+ handle: n.handle,
+ priority: n.priority - 1,
+ }
+
+ // Update maxParams (max of all children)
+ for i := range child.children {
+ if child.children[i].maxParams > child.maxParams {
+ child.maxParams = child.children[i].maxParams
+ }
+ }
+
+ n.children = []*node{&child}
+ // []byte for proper unicode char conversion, see #65
+ n.indices = string([]byte{n.path[i]})
+ n.path = path[:i]
+ n.handle = nil
+ n.wildChild = false
+ }
+
+ // Make new node a child of this node
+ if i < len(path) {
+ path = path[i:]
+
+ if n.wildChild {
+ n = n.children[0]
+ n.priority++
+
+ // Update maxParams of the child node
+ if numParams > n.maxParams {
+ n.maxParams = numParams
+ }
+ numParams--
+
+ // Check if the wildcard matches
+ if len(path) >= len(n.path) && n.path == path[:len(n.path)] &&
+ // Check for longer wildcard, e.g. :name and :names
+ (len(n.path) >= len(path) || path[len(n.path)] == '/') {
+ continue walk
+ } else {
+ // Wildcard conflict
+ var pathSeg string
+ if n.nType == catchAll {
+ pathSeg = path
+ } else {
+ pathSeg = strings.SplitN(path, "/", 2)[0]
+ }
+ prefix := fullPath[:strings.Index(fullPath, pathSeg)] + n.path
+ panic("'" + pathSeg +
+ "' in new path '" + fullPath +
+ "' conflicts with existing wildcard '" + n.path +
+ "' in existing prefix '" + prefix +
+ "'")
+ }
+ }
+
+ c := path[0]
+
+ // slash after param
+ if n.nType == param && c == '/' && len(n.children) == 1 {
+ n = n.children[0]
+ n.priority++
+ continue walk
+ }
+
+ // Check if a child with the next path byte exists
+ for i := 0; i < len(n.indices); i++ {
+ if c == n.indices[i] {
+ i = n.incrementChildPrio(i)
+ n = n.children[i]
+ continue walk
+ }
+ }
+
+ // Otherwise insert it
+ if c != ':' && c != '*' {
+ // []byte for proper unicode char conversion, see #65
+ n.indices += string([]byte{c})
+ child := &node{
+ maxParams: numParams,
+ }
+ n.children = append(n.children, child)
+ n.incrementChildPrio(len(n.indices) - 1)
+ n = child
+ }
+ n.insertChild(numParams, path, fullPath, handle)
+ return
+
+ } else if i == len(path) { // Make node a (in-path) leaf
+ if n.handle != nil {
+ panic("a handle is already registered for path '" + fullPath + "'")
+ }
+ n.handle = handle
+ }
+ return
+ }
+ } else { // Empty tree
+ n.insertChild(numParams, path, fullPath, handle)
+ n.nType = root
+ }
+}
+
+func (n *node) insertChild(numParams uint8, path, fullPath string, handle Handle) {
+ var offset int // already handled bytes of the path
+
+ // find prefix until first wildcard (beginning with ':'' or '*'')
+ for i, max := 0, len(path); numParams > 0; i++ {
+ c := path[i]
+ if c != ':' && c != '*' {
+ continue
+ }
+
+ // find wildcard end (either '/' or path end)
+ end := i + 1
+ for end < max && path[end] != '/' {
+ switch path[end] {
+ // the wildcard name must not contain ':' and '*'
+ case ':', '*':
+ panic("only one wildcard per path segment is allowed, has: '" +
+ path[i:] + "' in path '" + fullPath + "'")
+ default:
+ end++
+ }
+ }
+
+ // check if this Node existing children which would be
+ // unreachable if we insert the wildcard here
+ if len(n.children) > 0 {
+ panic("wildcard route '" + path[i:end] +
+ "' conflicts with existing children in path '" + fullPath + "'")
+ }
+
+ // check if the wildcard has a name
+ if end-i < 2 {
+ panic("wildcards must be named with a non-empty name in path '" + fullPath + "'")
+ }
+
+ if c == ':' { // param
+ // split path at the beginning of the wildcard
+ if i > 0 {
+ n.path = path[offset:i]
+ offset = i
+ }
+
+ child := &node{
+ nType: param,
+ maxParams: numParams,
+ }
+ n.children = []*node{child}
+ n.wildChild = true
+ n = child
+ n.priority++
+ numParams--
+
+ // if the path doesn't end with the wildcard, then there
+ // will be another non-wildcard subpath starting with '/'
+ if end < max {
+ n.path = path[offset:end]
+ offset = end
+
+ child := &node{
+ maxParams: numParams,
+ priority: 1,
+ }
+ n.children = []*node{child}
+ n = child
+ }
+
+ } else { // catchAll
+ if end != max || numParams > 1 {
+ panic("catch-all routes are only allowed at the end of the path in path '" + fullPath + "'")
+ }
+
+ if len(n.path) > 0 && n.path[len(n.path)-1] == '/' {
+ panic("catch-all conflicts with existing handle for the path segment root in path '" + fullPath + "'")
+ }
+
+ // currently fixed width 1 for '/'
+ i--
+ if path[i] != '/' {
+ panic("no / before catch-all in path '" + fullPath + "'")
+ }
+
+ n.path = path[offset:i]
+
+ // first node: catchAll node with empty path
+ child := &node{
+ wildChild: true,
+ nType: catchAll,
+ maxParams: 1,
+ }
+ n.children = []*node{child}
+ n.indices = string(path[i])
+ n = child
+ n.priority++
+
+ // second node: node holding the variable
+ child = &node{
+ path: path[i:],
+ nType: catchAll,
+ maxParams: 1,
+ handle: handle,
+ priority: 1,
+ }
+ n.children = []*node{child}
+
+ return
+ }
+ }
+
+ // insert remaining path part and handle to the leaf
+ n.path = path[offset:]
+ n.handle = handle
+}
+
+// Returns the handle registered with the given path (key). The values of
+// wildcards are saved to a map.
+// If no handle can be found, a TSR (trailing slash redirect) recommendation is
+// made if a handle exists with an extra (without the) trailing slash for the
+// given path.
+func (n *node) getValue(path string) (handle Handle, p Params, tsr bool) {
+walk: // outer loop for walking the tree
+ for {
+ if len(path) > len(n.path) {
+ if path[:len(n.path)] == n.path {
+ path = path[len(n.path):]
+ // If this node does not have a wildcard (param or catchAll)
+ // child, we can just look up the next child node and continue
+ // to walk down the tree
+ if !n.wildChild {
+ c := path[0]
+ for i := 0; i < len(n.indices); i++ {
+ if c == n.indices[i] {
+ n = n.children[i]
+ continue walk
+ }
+ }
+
+ // Nothing found.
+ // We can recommend to redirect to the same URL without a
+ // trailing slash if a leaf exists for that path.
+ tsr = (path == "/" && n.handle != nil)
+ return
+
+ }
+
+ // handle wildcard child
+ n = n.children[0]
+ switch n.nType {
+ case param:
+ // find param end (either '/' or path end)
+ end := 0
+ for end < len(path) && path[end] != '/' {
+ end++
+ }
+
+ // save param value
+ if p == nil {
+ // lazy allocation
+ p = make(Params, 0, n.maxParams)
+ }
+ i := len(p)
+ p = p[:i+1] // expand slice within preallocated capacity
+ p[i].Key = n.path[1:]
+ p[i].Value = path[:end]
+
+ // we need to go deeper!
+ if end < len(path) {
+ if len(n.children) > 0 {
+ path = path[end:]
+ n = n.children[0]
+ continue walk
+ }
+
+ // ... but we can't
+ tsr = (len(path) == end+1)
+ return
+ }
+
+ if handle = n.handle; handle != nil {
+ return
+ } else if len(n.children) == 1 {
+ // No handle found. Check if a handle for this path + a
+ // trailing slash exists for TSR recommendation
+ n = n.children[0]
+ tsr = (n.path == "/" && n.handle != nil)
+ }
+
+ return
+
+ case catchAll:
+ // save param value
+ if p == nil {
+ // lazy allocation
+ p = make(Params, 0, n.maxParams)
+ }
+ i := len(p)
+ p = p[:i+1] // expand slice within preallocated capacity
+ p[i].Key = n.path[2:]
+ p[i].Value = path
+
+ handle = n.handle
+ return
+
+ default:
+ panic("invalid node type")
+ }
+ }
+ } else if path == n.path {
+ // We should have reached the node containing the handle.
+ // Check if this node has a handle registered.
+ if handle = n.handle; handle != nil {
+ return
+ }
+
+ if path == "/" && n.wildChild && n.nType != root {
+ tsr = true
+ return
+ }
+
+ // No handle found. Check if a handle for this path + a
+ // trailing slash exists for trailing slash recommendation
+ for i := 0; i < len(n.indices); i++ {
+ if n.indices[i] == '/' {
+ n = n.children[i]
+ tsr = (len(n.path) == 1 && n.handle != nil) ||
+ (n.nType == catchAll && n.children[0].handle != nil)
+ return
+ }
+ }
+
+ return
+ }
+
+ // Nothing found. We can recommend to redirect to the same URL with an
+ // extra trailing slash if a leaf exists for that path
+ tsr = (path == "/") ||
+ (len(n.path) == len(path)+1 && n.path[len(path)] == '/' &&
+ path == n.path[:len(n.path)-1] && n.handle != nil)
+ return
+ }
+}
+
+// Makes a case-insensitive lookup of the given path and tries to find a handler.
+// It can optionally also fix trailing slashes.
+// It returns the case-corrected path and a bool indicating whether the lookup
+// was successful.
+func (n *node) findCaseInsensitivePath(path string, fixTrailingSlash bool) (ciPath []byte, found bool) {
+ return n.findCaseInsensitivePathRec(
+ path,
+ strings.ToLower(path),
+ make([]byte, 0, len(path)+1), // preallocate enough memory for new path
+ [4]byte{}, // empty rune buffer
+ fixTrailingSlash,
+ )
+}
+
+// shift bytes in array by n bytes left
+func shiftNRuneBytes(rb [4]byte, n int) [4]byte {
+ switch n {
+ case 0:
+ return rb
+ case 1:
+ return [4]byte{rb[1], rb[2], rb[3], 0}
+ case 2:
+ return [4]byte{rb[2], rb[3]}
+ case 3:
+ return [4]byte{rb[3]}
+ default:
+ return [4]byte{}
+ }
+}
+
+// recursive case-insensitive lookup function used by n.findCaseInsensitivePath
+func (n *node) findCaseInsensitivePathRec(path, loPath string, ciPath []byte, rb [4]byte, fixTrailingSlash bool) ([]byte, bool) {
+ loNPath := strings.ToLower(n.path)
+
+walk: // outer loop for walking the tree
+ for len(loPath) >= len(loNPath) && (len(loNPath) == 0 || loPath[1:len(loNPath)] == loNPath[1:]) {
+ // add common path to result
+ ciPath = append(ciPath, n.path...)
+
+ if path = path[len(n.path):]; len(path) > 0 {
+ loOld := loPath
+ loPath = loPath[len(loNPath):]
+
+ // If this node does not have a wildcard (param or catchAll) child,
+ // we can just look up the next child node and continue to walk down
+ // the tree
+ if !n.wildChild {
+ // skip rune bytes already processed
+ rb = shiftNRuneBytes(rb, len(loNPath))
+
+ if rb[0] != 0 {
+ // old rune not finished
+ for i := 0; i < len(n.indices); i++ {
+ if n.indices[i] == rb[0] {
+ // continue with child node
+ n = n.children[i]
+ loNPath = strings.ToLower(n.path)
+ continue walk
+ }
+ }
+ } else {
+ // process a new rune
+ var rv rune
+
+ // find rune start
+ // runes are up to 4 byte long,
+ // -4 would definitely be another rune
+ var off int
+ for max := min(len(loNPath), 3); off < max; off++ {
+ if i := len(loNPath) - off; utf8.RuneStart(loOld[i]) {
+ // read rune from cached lowercase path
+ rv, _ = utf8.DecodeRuneInString(loOld[i:])
+ break
+ }
+ }
+
+ // calculate lowercase bytes of current rune
+ utf8.EncodeRune(rb[:], rv)
+ // skipp already processed bytes
+ rb = shiftNRuneBytes(rb, off)
+
+ for i := 0; i < len(n.indices); i++ {
+ // lowercase matches
+ if n.indices[i] == rb[0] {
+ // must use a recursive approach since both the
+ // uppercase byte and the lowercase byte might exist
+ // as an index
+ if out, found := n.children[i].findCaseInsensitivePathRec(
+ path, loPath, ciPath, rb, fixTrailingSlash,
+ ); found {
+ return out, true
+ }
+ break
+ }
+ }
+
+ // same for uppercase rune, if it differs
+ if up := unicode.ToUpper(rv); up != rv {
+ utf8.EncodeRune(rb[:], up)
+ rb = shiftNRuneBytes(rb, off)
+
+ for i := 0; i < len(n.indices); i++ {
+ // uppercase matches
+ if n.indices[i] == rb[0] {
+ // continue with child node
+ n = n.children[i]
+ loNPath = strings.ToLower(n.path)
+ continue walk
+ }
+ }
+ }
+ }
+
+ // Nothing found. We can recommend to redirect to the same URL
+ // without a trailing slash if a leaf exists for that path
+ return ciPath, (fixTrailingSlash && path == "/" && n.handle != nil)
+ }
+
+ n = n.children[0]
+ switch n.nType {
+ case param:
+ // find param end (either '/' or path end)
+ k := 0
+ for k < len(path) && path[k] != '/' {
+ k++
+ }
+
+ // add param value to case insensitive path
+ ciPath = append(ciPath, path[:k]...)
+
+ // we need to go deeper!
+ if k < len(path) {
+ if len(n.children) > 0 {
+ // continue with child node
+ n = n.children[0]
+ loNPath = strings.ToLower(n.path)
+ loPath = loPath[k:]
+ path = path[k:]
+ continue
+ }
+
+ // ... but we can't
+ if fixTrailingSlash && len(path) == k+1 {
+ return ciPath, true
+ }
+ return ciPath, false
+ }
+
+ if n.handle != nil {
+ return ciPath, true
+ } else if fixTrailingSlash && len(n.children) == 1 {
+ // No handle found. Check if a handle for this path + a
+ // trailing slash exists
+ n = n.children[0]
+ if n.path == "/" && n.handle != nil {
+ return append(ciPath, '/'), true
+ }
+ }
+ return ciPath, false
+
+ case catchAll:
+ return append(ciPath, path...), true
+
+ default:
+ panic("invalid node type")
+ }
+ } else {
+ // We should have reached the node containing the handle.
+ // Check if this node has a handle registered.
+ if n.handle != nil {
+ return ciPath, true
+ }
+
+ // No handle found.
+ // Try to fix the path by adding a trailing slash
+ if fixTrailingSlash {
+ for i := 0; i < len(n.indices); i++ {
+ if n.indices[i] == '/' {
+ n = n.children[i]
+ if (len(n.path) == 1 && n.handle != nil) ||
+ (n.nType == catchAll && n.children[0].handle != nil) {
+ return append(ciPath, '/'), true
+ }
+ return ciPath, false
+ }
+ }
+ }
+ return ciPath, false
+ }
+ }
+
+ // Nothing found.
+ // Try to fix the path by adding / removing a trailing slash
+ if fixTrailingSlash {
+ if path == "/" {
+ return ciPath, true
+ }
+ if len(loPath)+1 == len(loNPath) && loNPath[len(loPath)] == '/' &&
+ loPath[1:] == loNPath[1:len(loPath)] && n.handle != nil {
+ return append(ciPath, n.path...), true
+ }
+ }
+ return ciPath, false
+}
--- /dev/null
+Go package for parsing (and, eventually, generating)
+log lines in the logfmt style.
+
+See http://godoc.org/github.com/kr/logfmt for format, and other documentation and examples.
+
+Copyright (C) 2013 Keith Rarick, Blake Mizerany
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--- /dev/null
+// Package implements the decoding of logfmt key-value pairs.
+//
+// Example logfmt message:
+//
+// foo=bar a=14 baz="hello kitty" cool%story=bro f %^asdf
+//
+// Example result in JSON:
+//
+// { "foo": "bar", "a": 14, "baz": "hello kitty", "cool%story": "bro", "f": true, "%^asdf": true }
+//
+// EBNFish:
+//
+// ident_byte = any byte greater than ' ', excluding '=' and '"'
+// string_byte = any byte excluding '"' and '\'
+// garbage = !ident_byte
+// ident = ident_byte, { ident byte }
+// key = ident
+// value = ident | '"', { string_byte | '\', '"' }, '"'
+// pair = key, '=', value | key, '=' | key
+// message = { garbage, pair }, garbage
+package logfmt
+
+import (
+ "reflect"
+ "strconv"
+ "strings"
+ "time"
+)
+
+// Handler is the interface implemented by objects that accept logfmt
+// key-value pairs. HandleLogfmt must copy the logfmt data if it
+// wishes to retain the data after returning.
+type Handler interface {
+ HandleLogfmt(key, val []byte) error
+}
+
+// The HandlerFunc type is an adapter to allow the use of ordinary functions as
+// logfmt handlers. If f is a function with the appropriate signature,
+// HandlerFunc(f) is a Handler object that calls f.
+type HandlerFunc func(key, val []byte) error
+
+func (f HandlerFunc) HandleLogfmt(key, val []byte) error {
+ return f(key, val)
+}
+
+// Unmarshal parses the logfmt encoding data and stores the result in the value
+// pointed to by v. If v is an Handler, HandleLogfmt will be called for each
+// key-value pair.
+//
+// If v is not a Handler, it will pass v to NewStructHandler and use the
+// returned StructHandler for decoding.
+func Unmarshal(data []byte, v interface{}) (err error) {
+ h, ok := v.(Handler)
+ if !ok {
+ h, err = NewStructHandler(v)
+ if err != nil {
+ return err
+ }
+ }
+ return gotoScanner(data, h)
+}
+
+// StructHandler unmarshals logfmt into a struct. It matches incoming keys to
+// the the struct's fields (either the struct field name or its tag, preferring
+// an exact match but also accepting a case-insensitive match.
+//
+// Field types supported by StructHandler are:
+//
+// all numeric types (e.g. float32, int, etc.)
+// []byte
+// string
+// bool - true if key is present, false otherwise (the value is ignored).
+// time.Duration - uses time.ParseDuration
+//
+// If a field is a pointer to an above type, and a matching key is not present
+// in the logfmt data, the pointer will be untouched.
+//
+// If v is not a pointer to an Handler or struct, Unmarshal will return an
+// error.
+type StructHandler struct {
+ rv reflect.Value
+}
+
+func NewStructHandler(v interface{}) (Handler, error) {
+ rv := reflect.ValueOf(v)
+ if rv.Kind() != reflect.Ptr || rv.IsNil() {
+ return nil, &InvalidUnmarshalError{reflect.TypeOf(v)}
+ }
+ return &StructHandler{rv: rv}, nil
+}
+
+func (h *StructHandler) HandleLogfmt(key, val []byte) error {
+ el := h.rv.Elem()
+ skey := string(key)
+ for i := 0; i < el.NumField(); i++ {
+ fv := el.Field(i)
+ ft := el.Type().Field(i)
+ switch {
+ case ft.Name == skey:
+ case ft.Tag.Get("logfmt") == skey:
+ case strings.EqualFold(ft.Name, skey):
+ default:
+ continue
+ }
+ if fv.Kind() == reflect.Ptr {
+ if fv.IsNil() {
+ t := fv.Type().Elem()
+ v := reflect.New(t)
+ fv.Set(v)
+ fv = v
+ }
+ fv = fv.Elem()
+ }
+ switch fv.Interface().(type) {
+ case time.Duration:
+ d, err := time.ParseDuration(string(val))
+ if err != nil {
+ return &UnmarshalTypeError{string(val), fv.Type()}
+ }
+ fv.Set(reflect.ValueOf(d))
+ case string:
+ fv.SetString(string(val))
+ case []byte:
+ b := make([]byte, len(val))
+ copy(b, val)
+ fv.SetBytes(b)
+ case bool:
+ fv.SetBool(true)
+ default:
+ switch {
+ case reflect.Int <= fv.Kind() && fv.Kind() <= reflect.Int64:
+ v, err := strconv.ParseInt(string(val), 10, 64)
+ if err != nil {
+ return err
+ }
+ fv.SetInt(v)
+ case reflect.Uint32 <= fv.Kind() && fv.Kind() <= reflect.Uint64:
+ v, err := strconv.ParseUint(string(val), 10, 64)
+ if err != nil {
+ return err
+ }
+ fv.SetUint(v)
+ case reflect.Float32 <= fv.Kind() && fv.Kind() <= reflect.Float64:
+ v, err := strconv.ParseFloat(string(val), 10)
+ if err != nil {
+ return err
+ }
+ fv.SetFloat(v)
+ default:
+ return &UnmarshalTypeError{string(val), fv.Type()}
+ }
+ }
+
+ }
+ return nil
+}
+
+// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
+// (The argument to Unmarshal must be a non-nil pointer.)
+type InvalidUnmarshalError struct {
+ Type reflect.Type
+}
+
+func (e *InvalidUnmarshalError) Error() string {
+ if e.Type == nil {
+ return "logfmt: Unmarshal(nil)"
+ }
+
+ if e.Type.Kind() != reflect.Ptr {
+ return "logfmt: Unmarshal(non-pointer " + e.Type.String() + ")"
+ }
+ return "logfmt: Unmarshal(nil " + e.Type.String() + ")"
+}
+
+// An UnmarshalTypeError describes a logfmt value that was
+// not appropriate for a value of a specific Go type.
+type UnmarshalTypeError struct {
+ Value string // the logfmt value
+ Type reflect.Type // type of Go value it could not be assigned to
+}
+
+func (e *UnmarshalTypeError) Error() string {
+ return "logfmt: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String()
+}
--- /dev/null
+package logfmt
+
+import (
+ "errors"
+ "fmt"
+)
+
+var ErrUnterminatedString = errors.New("logfmt: unterminated string")
+
+func gotoScanner(data []byte, h Handler) (err error) {
+ saveError := func(e error) {
+ if err == nil {
+ err = e
+ }
+ }
+
+ var c byte
+ var i int
+ var m int
+ var key []byte
+ var val []byte
+ var ok bool
+ var esc bool
+
+garbage:
+ if i == len(data) {
+ return
+ }
+
+ c = data[i]
+ switch {
+ case c > ' ' && c != '"' && c != '=':
+ key, val = nil, nil
+ m = i
+ i++
+ goto key
+ default:
+ i++
+ goto garbage
+ }
+
+key:
+ if i >= len(data) {
+ if m >= 0 {
+ key = data[m:i]
+ saveError(h.HandleLogfmt(key, nil))
+ }
+ return
+ }
+
+ c = data[i]
+ switch {
+ case c > ' ' && c != '"' && c != '=':
+ i++
+ goto key
+ case c == '=':
+ key = data[m:i]
+ i++
+ goto equal
+ default:
+ key = data[m:i]
+ i++
+ saveError(h.HandleLogfmt(key, nil))
+ goto garbage
+ }
+
+equal:
+ if i >= len(data) {
+ if m >= 0 {
+ i--
+ key = data[m:i]
+ saveError(h.HandleLogfmt(key, nil))
+ }
+ return
+ }
+
+ c = data[i]
+ switch {
+ case c > ' ' && c != '"' && c != '=':
+ m = i
+ i++
+ goto ivalue
+ case c == '"':
+ m = i
+ i++
+ esc = false
+ goto qvalue
+ default:
+ if key != nil {
+ saveError(h.HandleLogfmt(key, val))
+ }
+ i++
+ goto garbage
+ }
+
+ivalue:
+ if i >= len(data) {
+ if m >= 0 {
+ val = data[m:i]
+ saveError(h.HandleLogfmt(key, val))
+ }
+ return
+ }
+
+ c = data[i]
+ switch {
+ case c > ' ' && c != '"' && c != '=':
+ i++
+ goto ivalue
+ default:
+ val = data[m:i]
+ saveError(h.HandleLogfmt(key, val))
+ i++
+ goto garbage
+ }
+
+qvalue:
+ if i >= len(data) {
+ if m >= 0 {
+ saveError(ErrUnterminatedString)
+ }
+ return
+ }
+
+ c = data[i]
+ switch c {
+ case '\\':
+ i += 2
+ esc = true
+ goto qvalue
+ case '"':
+ i++
+ val = data[m:i]
+ if esc {
+ val, ok = unquoteBytes(val)
+ if !ok {
+ saveError(fmt.Errorf("logfmt: error unquoting bytes %q", string(val)))
+ goto garbage
+ }
+ } else {
+ val = val[1 : len(val)-1]
+ }
+ saveError(h.HandleLogfmt(key, val))
+ goto garbage
+ default:
+ i++
+ goto qvalue
+ }
+}
--- /dev/null
+package logfmt
+
+import (
+ "strconv"
+ "unicode"
+ "unicode/utf16"
+ "unicode/utf8"
+)
+
+// Taken from Go's encoding/json
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// getu4 decodes \uXXXX from the beginning of s, returning the hex value,
+// or it returns -1.
+func getu4(s []byte) rune {
+ if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
+ return -1
+ }
+ r, err := strconv.ParseUint(string(s[2:6]), 16, 64)
+ if err != nil {
+ return -1
+ }
+ return rune(r)
+}
+
+// unquote converts a quoted JSON string literal s into an actual string t.
+// The rules are different than for Go, so cannot use strconv.Unquote.
+func unquote(s []byte) (t string, ok bool) {
+ s, ok = unquoteBytes(s)
+ t = string(s)
+ return
+}
+
+func unquoteBytes(s []byte) (t []byte, ok bool) {
+ if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {
+ return
+ }
+ s = s[1 : len(s)-1]
+
+ // Check for unusual characters. If there are none,
+ // then no unquoting is needed, so return a slice of the
+ // original bytes.
+ r := 0
+ for r < len(s) {
+ c := s[r]
+ if c == '\\' || c == '"' || c < ' ' {
+ break
+ }
+ if c < utf8.RuneSelf {
+ r++
+ continue
+ }
+ rr, size := utf8.DecodeRune(s[r:])
+ if rr == utf8.RuneError && size == 1 {
+ break
+ }
+ r += size
+ }
+ if r == len(s) {
+ return s, true
+ }
+
+ b := make([]byte, len(s)+2*utf8.UTFMax)
+ w := copy(b, s[0:r])
+ for r < len(s) {
+ // Out of room? Can only happen if s is full of
+ // malformed UTF-8 and we're replacing each
+ // byte with RuneError.
+ if w >= len(b)-2*utf8.UTFMax {
+ nb := make([]byte, (len(b)+utf8.UTFMax)*2)
+ copy(nb, b[0:w])
+ b = nb
+ }
+ switch c := s[r]; {
+ case c == '\\':
+ r++
+ if r >= len(s) {
+ return
+ }
+ switch s[r] {
+ default:
+ return
+ case '"', '\\', '/', '\'':
+ b[w] = s[r]
+ r++
+ w++
+ case 'b':
+ b[w] = '\b'
+ r++
+ w++
+ case 'f':
+ b[w] = '\f'
+ r++
+ w++
+ case 'n':
+ b[w] = '\n'
+ r++
+ w++
+ case 'r':
+ b[w] = '\r'
+ r++
+ w++
+ case 't':
+ b[w] = '\t'
+ r++
+ w++
+ case 'u':
+ r--
+ rr := getu4(s[r:])
+ if rr < 0 {
+ return
+ }
+ r += 6
+ if utf16.IsSurrogate(rr) {
+ rr1 := getu4(s[r:])
+ if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar {
+ // A valid pair; consume.
+ r += 6
+ w += utf8.EncodeRune(b[w:], dec)
+ break
+ }
+ // Invalid surrogate; fall back to replacement rune.
+ rr = unicode.ReplacementChar
+ }
+ w += utf8.EncodeRune(b[w:], rr)
+ }
+
+ // Quote, control characters are invalid.
+ case c == '"', c < ' ':
+ return
+
+ // ASCII
+ case c < utf8.RuneSelf:
+ b[w] = c
+ r++
+ w++
+
+ // Coerce to well-formed UTF-8.
+ default:
+ rr, size := utf8.DecodeRune(s[r:])
+ r += size
+ w += utf8.EncodeRune(b[w:], rr)
+ }
+ }
+ return b[0:w], true
+}
--- /dev/null
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
--- /dev/null
+// Copyright 2013 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package diff implements a linewise diff algorithm.
+package diff
+
+import (
+ "bytes"
+ "fmt"
+ "strings"
+)
+
+// Chunk represents a piece of the diff. A chunk will not have both added and
+// deleted lines. Equal lines are always after any added or deleted lines.
+// A Chunk may or may not have any lines in it, especially for the first or last
+// chunk in a computation.
+type Chunk struct {
+ Added []string
+ Deleted []string
+ Equal []string
+}
+
+// Diff returns a string containing a line-by-line unified diff of the linewise
+// changes required to make A into B. Each line is prefixed with '+', '-', or
+// ' ' to indicate if it should be added, removed, or is correct respectively.
+func Diff(A, B string) string {
+ aLines := strings.Split(A, "\n")
+ bLines := strings.Split(B, "\n")
+
+ chunks := DiffChunks(aLines, bLines)
+
+ buf := new(bytes.Buffer)
+ for _, c := range chunks {
+ for _, line := range c.Added {
+ fmt.Fprintf(buf, "+%s\n", line)
+ }
+ for _, line := range c.Deleted {
+ fmt.Fprintf(buf, "-%s\n", line)
+ }
+ for _, line := range c.Equal {
+ fmt.Fprintf(buf, " %s\n", line)
+ }
+ }
+ return strings.TrimRight(buf.String(), "\n")
+}
+
+// DiffChunks uses an O(D(N+M)) shortest-edit-script algorithm
+// to compute the edits required from A to B and returns the
+// edit chunks.
+func DiffChunks(A, B []string) []Chunk {
+ // algorithm: http://www.xmailserver.org/diff2.pdf
+
+ N, M := len(A), len(B)
+ MAX := N + M
+ V := make([]int, 2*MAX+1)
+ Vs := make([][]int, 0, 8)
+
+ var D int
+dLoop:
+ for D = 0; D <= MAX; D++ {
+ for k := -D; k <= D; k += 2 {
+ var x int
+ if k == -D || (k != D && V[MAX+k-1] < V[MAX+k+1]) {
+ x = V[MAX+k+1]
+ } else {
+ x = V[MAX+k-1] + 1
+ }
+ y := x - k
+ for x < N && y < M && A[x] == B[y] {
+ x++
+ y++
+ }
+ V[MAX+k] = x
+ if x >= N && y >= M {
+ Vs = append(Vs, append(make([]int, 0, len(V)), V...))
+ break dLoop
+ }
+ }
+ Vs = append(Vs, append(make([]int, 0, len(V)), V...))
+ }
+ if D == 0 {
+ return nil
+ }
+ chunks := make([]Chunk, D+1)
+
+ x, y := N, M
+ for d := D; d > 0; d-- {
+ V := Vs[d]
+ k := x - y
+ insert := k == -d || (k != d && V[MAX+k-1] < V[MAX+k+1])
+
+ x1 := V[MAX+k]
+ var x0, xM, kk int
+ if insert {
+ kk = k + 1
+ x0 = V[MAX+kk]
+ xM = x0
+ } else {
+ kk = k - 1
+ x0 = V[MAX+kk]
+ xM = x0 + 1
+ }
+ y0 := x0 - kk
+
+ var c Chunk
+ if insert {
+ c.Added = B[y0:][:1]
+ } else {
+ c.Deleted = A[x0:][:1]
+ }
+ if xM < x1 {
+ c.Equal = A[xM:][:x1-xM]
+ }
+
+ x, y = x0, y0
+ chunks[d] = c
+ }
+ if x > 0 {
+ chunks[0].Equal = A[:x]
+ }
+ return chunks
+}
--- /dev/null
+// Copyright 2013 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package pretty pretty-prints Go structures.
+//
+// This package uses reflection to examine a Go value and can
+// print out in a nice, aligned fashion. It supports three
+// modes (normal, compact, and extended) for advanced use.
+//
+// See the Reflect and Print examples for what the output looks like.
+package pretty
+
+// TODO:
+// - Catch cycles
--- /dev/null
+// Copyright 2013 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package pretty
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "reflect"
+
+ "github.com/kylelemons/godebug/diff"
+)
+
+// A Config represents optional configuration parameters for formatting.
+//
+// Some options, notably ShortList, dramatically increase the overhead
+// of pretty-printing a value.
+type Config struct {
+ // Verbosity options
+ Compact bool // One-line output. Overrides Diffable.
+ Diffable bool // Adds extra newlines for more easily diffable output.
+
+ // Field and value options
+ IncludeUnexported bool // Include unexported fields in output
+ PrintStringers bool // Call String on a fmt.Stringer
+ PrintTextMarshalers bool // Call MarshalText on an encoding.TextMarshaler
+ SkipZeroFields bool // Skip struct fields that have a zero value.
+
+ // Output transforms
+ ShortList int // Maximum character length for short lists if nonzero.
+}
+
+// Default Config objects
+var (
+ // CompareConfig is the default configuration used for Compare.
+ CompareConfig = &Config{
+ Diffable: true,
+ IncludeUnexported: true,
+ }
+
+ // DefaultConfig is the default configuration used for all other top-level functions.
+ DefaultConfig = &Config{}
+)
+
+func (cfg *Config) fprint(buf *bytes.Buffer, vals ...interface{}) {
+ for i, val := range vals {
+ if i > 0 {
+ buf.WriteByte('\n')
+ }
+ cfg.val2node(reflect.ValueOf(val)).WriteTo(buf, "", cfg)
+ }
+}
+
+// Print writes the DefaultConfig representation of the given values to standard output.
+func Print(vals ...interface{}) {
+ DefaultConfig.Print(vals...)
+}
+
+// Print writes the configured presentation of the given values to standard output.
+func (cfg *Config) Print(vals ...interface{}) {
+ fmt.Println(cfg.Sprint(vals...))
+}
+
+// Sprint returns a string representation of the given value according to the DefaultConfig.
+func Sprint(vals ...interface{}) string {
+ return DefaultConfig.Sprint(vals...)
+}
+
+// Sprint returns a string representation of the given value according to cfg.
+func (cfg *Config) Sprint(vals ...interface{}) string {
+ buf := new(bytes.Buffer)
+ cfg.fprint(buf, vals...)
+ return buf.String()
+}
+
+// Fprint writes the representation of the given value to the writer according to the DefaultConfig.
+func Fprint(w io.Writer, vals ...interface{}) (n int64, err error) {
+ return DefaultConfig.Fprint(w, vals...)
+}
+
+// Fprint writes the representation of the given value to the writer according to the cfg.
+func (cfg *Config) Fprint(w io.Writer, vals ...interface{}) (n int64, err error) {
+ buf := new(bytes.Buffer)
+ cfg.fprint(buf, vals...)
+ return buf.WriteTo(w)
+}
+
+// Compare returns a string containing a line-by-line unified diff of the
+// values in got and want, using the CompareConfig.
+//
+// Each line in the output is prefixed with '+', '-', or ' ' to indicate if it
+// should be added to, removed from, or is correct for the "got" value with
+// respect to the "want" value.
+func Compare(got, want interface{}) string {
+ return CompareConfig.Compare(got, want)
+}
+
+// Compare returns a string containing a line-by-line unified diff of the
+// values in got and want according to the cfg.
+func (cfg *Config) Compare(got, want interface{}) string {
+ diffCfg := *cfg
+ diffCfg.Diffable = true
+ return diff.Diff(cfg.Sprint(got), cfg.Sprint(want))
+}
--- /dev/null
+// Copyright 2013 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package pretty
+
+import (
+ "encoding"
+ "fmt"
+ "reflect"
+ "sort"
+)
+
+func isZeroVal(val reflect.Value) bool {
+ if !val.CanInterface() {
+ return false
+ }
+ z := reflect.Zero(val.Type()).Interface()
+ return reflect.DeepEqual(val.Interface(), z)
+}
+
+func (c *Config) val2node(val reflect.Value) node {
+ // TODO(kevlar): pointer tracking?
+
+ if !val.IsValid() {
+ return rawVal("nil")
+ }
+
+ if val.CanInterface() {
+ v := val.Interface()
+ if s, ok := v.(fmt.Stringer); ok && c.PrintStringers {
+ return stringVal(s.String())
+ }
+ if t, ok := v.(encoding.TextMarshaler); ok && c.PrintTextMarshalers {
+ if raw, err := t.MarshalText(); err == nil { // if NOT an error
+ return stringVal(string(raw))
+ }
+ }
+ }
+
+ switch kind := val.Kind(); kind {
+ case reflect.Ptr, reflect.Interface:
+ if val.IsNil() {
+ return rawVal("nil")
+ }
+ return c.val2node(val.Elem())
+ case reflect.String:
+ return stringVal(val.String())
+ case reflect.Slice, reflect.Array:
+ n := list{}
+ length := val.Len()
+ for i := 0; i < length; i++ {
+ n = append(n, c.val2node(val.Index(i)))
+ }
+ return n
+ case reflect.Map:
+ n := keyvals{}
+ keys := val.MapKeys()
+ for _, key := range keys {
+ // TODO(kevlar): Support arbitrary type keys?
+ n = append(n, keyval{compactString(c.val2node(key)), c.val2node(val.MapIndex(key))})
+ }
+ sort.Sort(n)
+ return n
+ case reflect.Struct:
+ n := keyvals{}
+ typ := val.Type()
+ fields := typ.NumField()
+ for i := 0; i < fields; i++ {
+ sf := typ.Field(i)
+ if !c.IncludeUnexported && sf.PkgPath != "" {
+ continue
+ }
+ field := val.Field(i)
+ if c.SkipZeroFields && isZeroVal(field) {
+ continue
+ }
+ n = append(n, keyval{sf.Name, c.val2node(field)})
+ }
+ return n
+ case reflect.Bool:
+ if val.Bool() {
+ return rawVal("true")
+ }
+ return rawVal("false")
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return rawVal(fmt.Sprintf("%d", val.Int()))
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return rawVal(fmt.Sprintf("%d", val.Uint()))
+ case reflect.Uintptr:
+ return rawVal(fmt.Sprintf("0x%X", val.Uint()))
+ case reflect.Float32, reflect.Float64:
+ return rawVal(fmt.Sprintf("%v", val.Float()))
+ case reflect.Complex64, reflect.Complex128:
+ return rawVal(fmt.Sprintf("%v", val.Complex()))
+ }
+
+ // Fall back to the default %#v if we can
+ if val.CanInterface() {
+ return rawVal(fmt.Sprintf("%#v", val.Interface()))
+ }
+
+ return rawVal(val.String())
+}
--- /dev/null
+// Copyright 2013 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package pretty
+
+import (
+ "bytes"
+ "strconv"
+ "strings"
+)
+
+type node interface {
+ WriteTo(w *bytes.Buffer, indent string, cfg *Config)
+}
+
+func compactString(n node) string {
+ switch k := n.(type) {
+ case stringVal:
+ return string(k)
+ case rawVal:
+ return string(k)
+ }
+
+ buf := new(bytes.Buffer)
+ n.WriteTo(buf, "", &Config{Compact: true})
+ return buf.String()
+}
+
+type stringVal string
+
+func (str stringVal) WriteTo(w *bytes.Buffer, indent string, cfg *Config) {
+ w.WriteString(strconv.Quote(string(str)))
+}
+
+type rawVal string
+
+func (r rawVal) WriteTo(w *bytes.Buffer, indent string, cfg *Config) {
+ w.WriteString(string(r))
+}
+
+type keyval struct {
+ key string
+ val node
+}
+
+type keyvals []keyval
+
+func (l keyvals) Len() int { return len(l) }
+func (l keyvals) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
+func (l keyvals) Less(i, j int) bool { return l[i].key < l[j].key }
+
+func (l keyvals) WriteTo(w *bytes.Buffer, indent string, cfg *Config) {
+ w.WriteByte('{')
+
+ switch {
+ case cfg.Compact:
+ // All on one line:
+ for i, kv := range l {
+ if i > 0 {
+ w.WriteByte(',')
+ }
+ w.WriteString(kv.key)
+ w.WriteByte(':')
+ kv.val.WriteTo(w, indent, cfg)
+ }
+ case cfg.Diffable:
+ w.WriteByte('\n')
+ inner := indent + " "
+ // Each value gets its own line:
+ for _, kv := range l {
+ w.WriteString(inner)
+ w.WriteString(kv.key)
+ w.WriteString(": ")
+ kv.val.WriteTo(w, inner, cfg)
+ w.WriteString(",\n")
+ }
+ w.WriteString(indent)
+ default:
+ keyWidth := 0
+ for _, kv := range l {
+ if kw := len(kv.key); kw > keyWidth {
+ keyWidth = kw
+ }
+ }
+ alignKey := indent + " "
+ alignValue := strings.Repeat(" ", keyWidth)
+ inner := alignKey + alignValue + " "
+ // First and last line shared with bracket:
+ for i, kv := range l {
+ if i > 0 {
+ w.WriteString(",\n")
+ w.WriteString(alignKey)
+ }
+ w.WriteString(kv.key)
+ w.WriteString(": ")
+ w.WriteString(alignValue[len(kv.key):])
+ kv.val.WriteTo(w, inner, cfg)
+ }
+ }
+
+ w.WriteByte('}')
+}
+
+type list []node
+
+func (l list) WriteTo(w *bytes.Buffer, indent string, cfg *Config) {
+ if max := cfg.ShortList; max > 0 {
+ short := compactString(l)
+ if len(short) <= max {
+ w.WriteString(short)
+ return
+ }
+ }
+
+ w.WriteByte('[')
+
+ switch {
+ case cfg.Compact:
+ // All on one line:
+ for i, v := range l {
+ if i > 0 {
+ w.WriteByte(',')
+ }
+ v.WriteTo(w, indent, cfg)
+ }
+ case cfg.Diffable:
+ w.WriteByte('\n')
+ inner := indent + " "
+ // Each value gets its own line:
+ for _, v := range l {
+ w.WriteString(inner)
+ v.WriteTo(w, inner, cfg)
+ w.WriteString(",\n")
+ }
+ w.WriteString(indent)
+ default:
+ inner := indent + " "
+ // First and last line shared with bracket:
+ for i, v := range l {
+ if i > 0 {
+ w.WriteString(",\n")
+ w.WriteString(inner)
+ }
+ v.WriteTo(w, inner, cfg)
+ }
+ }
+
+ w.WriteByte(']')
+}
--- /dev/null
+// Copyright 2013 Matt T. Proud
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package pbutil
+
+import (
+ "encoding/binary"
+ "errors"
+ "io"
+
+ "github.com/golang/protobuf/proto"
+)
+
+var errInvalidVarint = errors.New("invalid varint32 encountered")
+
+// ReadDelimited decodes a message from the provided length-delimited stream,
+// where the length is encoded as 32-bit varint prefix to the message body.
+// It returns the total number of bytes read and any applicable error. This is
+// roughly equivalent to the companion Java API's
+// MessageLite#parseDelimitedFrom. As per the reader contract, this function
+// calls r.Read repeatedly as required until exactly one message including its
+// prefix is read and decoded (or an error has occurred). The function never
+// reads more bytes from the stream than required. The function never returns
+// an error if a message has been read and decoded correctly, even if the end
+// of the stream has been reached in doing so. In that case, any subsequent
+// calls return (0, io.EOF).
+func ReadDelimited(r io.Reader, m proto.Message) (n int, err error) {
+ // Per AbstractParser#parsePartialDelimitedFrom with
+ // CodedInputStream#readRawVarint32.
+ headerBuf := make([]byte, binary.MaxVarintLen32)
+ var bytesRead, varIntBytes int
+ var messageLength uint64
+ for varIntBytes == 0 { // i.e. no varint has been decoded yet.
+ if bytesRead >= len(headerBuf) {
+ return bytesRead, errInvalidVarint
+ }
+ // We have to read byte by byte here to avoid reading more bytes
+ // than required. Each read byte is appended to what we have
+ // read before.
+ newBytesRead, err := r.Read(headerBuf[bytesRead : bytesRead+1])
+ if newBytesRead == 0 {
+ if err != nil {
+ return bytesRead, err
+ }
+ // A Reader should not return (0, nil), but if it does,
+ // it should be treated as no-op (according to the
+ // Reader contract). So let's go on...
+ continue
+ }
+ bytesRead += newBytesRead
+ // Now present everything read so far to the varint decoder and
+ // see if a varint can be decoded already.
+ messageLength, varIntBytes = proto.DecodeVarint(headerBuf[:bytesRead])
+ }
+
+ messageBuf := make([]byte, messageLength)
+ newBytesRead, err := io.ReadFull(r, messageBuf)
+ bytesRead += newBytesRead
+ if err != nil {
+ return bytesRead, err
+ }
+
+ return bytesRead, proto.Unmarshal(messageBuf, m)
+}
--- /dev/null
+// Copyright 2013 Matt T. Proud
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package pbutil provides record length-delimited Protocol Buffer streaming.
+package pbutil
--- /dev/null
+// Copyright 2013 Matt T. Proud
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package pbutil
+
+import (
+ "encoding/binary"
+ "io"
+
+ "github.com/golang/protobuf/proto"
+)
+
+// WriteDelimited encodes and dumps a message to the provided writer prefixed
+// with a 32-bit varint indicating the length of the encoded message, producing
+// a length-delimited record stream, which can be used to chain together
+// encoded messages of the same type together in a file. It returns the total
+// number of bytes written and any applicable error. This is roughly
+// equivalent to the companion Java API's MessageLite#writeDelimitedTo.
+func WriteDelimited(w io.Writer, m proto.Message) (n int, err error) {
+ buffer, err := proto.Marshal(m)
+ if err != nil {
+ return 0, err
+ }
+
+ buf := make([]byte, binary.MaxVarintLen32)
+ encodedLength := binary.PutUvarint(buf, uint64(len(buffer)))
+
+ sync, err := w.Write(buf[:encodedLength])
+ if err != nil {
+ return sync, err
+ }
+
+ n, err = w.Write(buffer)
+ return n + sync, err
+}
--- /dev/null
+Miek Gieben <miek@miek.nl>
--- /dev/null
+Alex A. Skinner
+Andrew Tunnell-Jones
+Ask Bjørn Hansen
+Dave Cheney
+Dusty Wilson
+Marek Majkowski
+Peter van Dijk
+Omri Bahumi
+Alex Sergeyev
+James Hartig
--- /dev/null
+Copyright 2009 The Go Authors. All rights reserved. Use of this source code
+is governed by a BSD-style license that can be found in the LICENSE file.
+Extensions of the original work are copyright (c) 2011 Miek Gieben
+
+Copyright 2011 Miek Gieben. All rights reserved. Use of this source code is
+governed by a BSD-style license that can be found in the LICENSE file.
+
+Copyright 2014 CloudFlare. All rights reserved. Use of this source code is
+governed by a BSD-style license that can be found in the LICENSE file.
--- /dev/null
+Extensions of the original work are copyright (c) 2011 Miek Gieben
+
+As this is fork of the official Go code the same license applies:
+
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
--- /dev/null
+[](https://travis-ci.org/miekg/dns)
+[](https://codecov.io/github/miekg/dns?branch=master)
+[](https://goreportcard.com/report/miekg/dns)
+[](https://godoc.org/github.com/miekg/dns)
+
+# Alternative (more granular) approach to a DNS library
+
+> Less is more.
+
+Complete and usable DNS library. All widely used Resource Records are supported, including the
+DNSSEC types. It follows a lean and mean philosophy. If there is stuff you should know as a DNS
+programmer there isn't a convenience function for it. Server side and client side programming is
+supported, i.e. you can build servers and resolvers with it.
+
+We try to keep the "master" branch as sane as possible and at the bleeding edge of standards,
+avoiding breaking changes wherever reasonable. We support the last two versions of Go.
+
+# Goals
+
+* KISS;
+* Fast;
+* Small API. If it's easy to code in Go, don't make a function for it.
+
+# Users
+
+A not-so-up-to-date-list-that-may-be-actually-current:
+
+* https://github.com/coredns/coredns
+* https://cloudflare.com
+* https://github.com/abh/geodns
+* http://www.statdns.com/
+* http://www.dnsinspect.com/
+* https://github.com/chuangbo/jianbing-dictionary-dns
+* http://www.dns-lg.com/
+* https://github.com/fcambus/rrda
+* https://github.com/kenshinx/godns
+* https://github.com/skynetservices/skydns
+* https://github.com/hashicorp/consul
+* https://github.com/DevelopersPL/godnsagent
+* https://github.com/duedil-ltd/discodns
+* https://github.com/StalkR/dns-reverse-proxy
+* https://github.com/tianon/rawdns
+* https://mesosphere.github.io/mesos-dns/
+* https://pulse.turbobytes.com/
+* https://play.google.com/store/apps/details?id=com.turbobytes.dig
+* https://github.com/fcambus/statzone
+* https://github.com/benschw/dns-clb-go
+* https://github.com/corny/dnscheck for http://public-dns.info/
+* https://namesmith.io
+* https://github.com/miekg/unbound
+* https://github.com/miekg/exdns
+* https://dnslookup.org
+* https://github.com/looterz/grimd
+* https://github.com/phamhongviet/serf-dns
+* https://github.com/mehrdadrad/mylg
+* https://github.com/bamarni/dockness
+* https://github.com/fffaraz/microdns
+* http://kelda.io
+* https://github.com/ipdcode/hades (JD.COM)
+* https://github.com/StackExchange/dnscontrol/
+* https://www.dnsperf.com/
+* https://dnssectest.net/
+* https://dns.apebits.com
+* https://github.com/oif/apex
+
+Send pull request if you want to be listed here.
+
+# Features
+
+* UDP/TCP queries, IPv4 and IPv6;
+* RFC 1035 zone file parsing ($INCLUDE, $ORIGIN, $TTL and $GENERATE (for all record types) are supported;
+* Fast:
+ * Reply speed around ~ 80K qps (faster hardware results in more qps);
+ * Parsing RRs ~ 100K RR/s, that's 5M records in about 50 seconds;
+* Server side programming (mimicking the net/http package);
+* Client side programming;
+* DNSSEC: signing, validating and key generation for DSA, RSA and ECDSA;
+* EDNS0, NSID, Cookies;
+* AXFR/IXFR;
+* TSIG, SIG(0);
+* DNS over TLS: optional encrypted connection between client and server;
+* DNS name compression;
+* Depends only on the standard library.
+
+Have fun!
+
+Miek Gieben - 2010-2012 - <miek@miek.nl>
+
+# Building
+
+Building is done with the `go` tool. If you have setup your GOPATH correctly, the following should
+work:
+
+ go get github.com/miekg/dns
+ go build github.com/miekg/dns
+
+## Examples
+
+A short "how to use the API" is at the beginning of doc.go (this also will show
+when you call `godoc github.com/miekg/dns`).
+
+Example programs can be found in the `github.com/miekg/exdns` repository.
+
+## Supported RFCs
+
+*all of them*
+
+* 103{4,5} - DNS standard
+* 1348 - NSAP record (removed the record)
+* 1982 - Serial Arithmetic
+* 1876 - LOC record
+* 1995 - IXFR
+* 1996 - DNS notify
+* 2136 - DNS Update (dynamic updates)
+* 2181 - RRset definition - there is no RRset type though, just []RR
+* 2537 - RSAMD5 DNS keys
+* 2065 - DNSSEC (updated in later RFCs)
+* 2671 - EDNS record
+* 2782 - SRV record
+* 2845 - TSIG record
+* 2915 - NAPTR record
+* 2929 - DNS IANA Considerations
+* 3110 - RSASHA1 DNS keys
+* 3225 - DO bit (DNSSEC OK)
+* 340{1,2,3} - NAPTR record
+* 3445 - Limiting the scope of (DNS)KEY
+* 3597 - Unknown RRs
+* 403{3,4,5} - DNSSEC + validation functions
+* 4255 - SSHFP record
+* 4343 - Case insensitivity
+* 4408 - SPF record
+* 4509 - SHA256 Hash in DS
+* 4592 - Wildcards in the DNS
+* 4635 - HMAC SHA TSIG
+* 4701 - DHCID
+* 4892 - id.server
+* 5001 - NSID
+* 5155 - NSEC3 record
+* 5205 - HIP record
+* 5702 - SHA2 in the DNS
+* 5936 - AXFR
+* 5966 - TCP implementation recommendations
+* 6605 - ECDSA
+* 6725 - IANA Registry Update
+* 6742 - ILNP DNS
+* 6840 - Clarifications and Implementation Notes for DNS Security
+* 6844 - CAA record
+* 6891 - EDNS0 update
+* 6895 - DNS IANA considerations
+* 6975 - Algorithm Understanding in DNSSEC
+* 7043 - EUI48/EUI64 records
+* 7314 - DNS (EDNS) EXPIRE Option
+* 7828 - edns-tcp-keepalive EDNS0 Option
+* 7553 - URI record
+* 7858 - DNS over TLS: Initiation and Performance Considerations
+* 7873 - Domain Name System (DNS) Cookies (draft-ietf-dnsop-cookies)
+
+## Loosely based upon
+
+* `ldns`
+* `NSD`
+* `Net::DNS`
+* `GRONG`
--- /dev/null
+package dns
+
+// A client implementation.
+
+import (
+ "bytes"
+ "context"
+ "crypto/tls"
+ "encoding/binary"
+ "io"
+ "net"
+ "strings"
+ "time"
+)
+
+const dnsTimeout time.Duration = 2 * time.Second
+const tcpIdleTimeout time.Duration = 8 * time.Second
+
+// A Conn represents a connection to a DNS server.
+type Conn struct {
+ net.Conn // a net.Conn holding the connection
+ UDPSize uint16 // minimum receive buffer for UDP messages
+ TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
+ rtt time.Duration
+ t time.Time
+ tsigRequestMAC string
+}
+
+// A Client defines parameters for a DNS client.
+type Client struct {
+ Net string // if "tcp" or "tcp-tls" (DNS over TLS) a TCP query will be initiated, otherwise an UDP one (default is "" for UDP)
+ UDPSize uint16 // minimum receive buffer for UDP messages
+ TLSConfig *tls.Config // TLS connection configuration
+ Dialer *net.Dialer // a net.Dialer used to set local address, timeouts and more
+ // Timeout is a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout,
+ // WriteTimeout when non-zero. Can be overridden with net.Dialer.Timeout (see Client.ExchangeWithDialer and
+ // Client.Dialer) or context.Context.Deadline (see the deprecated ExchangeContext)
+ Timeout time.Duration
+ DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero
+ ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
+ WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
+ TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
+ SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
+ group singleflight
+}
+
+// Exchange performs a synchronous UDP query. It sends the message m to the address
+// contained in a and waits for a reply. Exchange does not retry a failed query, nor
+// will it fall back to TCP in case of truncation.
+// See client.Exchange for more information on setting larger buffer sizes.
+func Exchange(m *Msg, a string) (r *Msg, err error) {
+ client := Client{Net: "udp"}
+ r, _, err = client.Exchange(m, a)
+ return r, err
+}
+
+func (c *Client) dialTimeout() time.Duration {
+ if c.Timeout != 0 {
+ return c.Timeout
+ }
+ if c.DialTimeout != 0 {
+ return c.DialTimeout
+ }
+ return dnsTimeout
+}
+
+func (c *Client) readTimeout() time.Duration {
+ if c.ReadTimeout != 0 {
+ return c.ReadTimeout
+ }
+ return dnsTimeout
+}
+
+func (c *Client) writeTimeout() time.Duration {
+ if c.WriteTimeout != 0 {
+ return c.WriteTimeout
+ }
+ return dnsTimeout
+}
+
+// Dial connects to the address on the named network.
+func (c *Client) Dial(address string) (conn *Conn, err error) {
+ // create a new dialer with the appropriate timeout
+ var d net.Dialer
+ if c.Dialer == nil {
+ d = net.Dialer{}
+ } else {
+ d = net.Dialer(*c.Dialer)
+ }
+ d.Timeout = c.getTimeoutForRequest(c.writeTimeout())
+
+ network := "udp"
+ useTLS := false
+
+ switch c.Net {
+ case "tcp-tls":
+ network = "tcp"
+ useTLS = true
+ case "tcp4-tls":
+ network = "tcp4"
+ useTLS = true
+ case "tcp6-tls":
+ network = "tcp6"
+ useTLS = true
+ default:
+ if c.Net != "" {
+ network = c.Net
+ }
+ }
+
+ conn = new(Conn)
+ if useTLS {
+ conn.Conn, err = tls.DialWithDialer(&d, network, address, c.TLSConfig)
+ } else {
+ conn.Conn, err = d.Dial(network, address)
+ }
+ if err != nil {
+ return nil, err
+ }
+ return conn, nil
+}
+
+// Exchange performs a synchronous query. It sends the message m to the address
+// contained in a and waits for a reply. Basic use pattern with a *dns.Client:
+//
+// c := new(dns.Client)
+// in, rtt, err := c.Exchange(message, "127.0.0.1:53")
+//
+// Exchange does not retry a failed query, nor will it fall back to TCP in
+// case of truncation.
+// It is up to the caller to create a message that allows for larger responses to be
+// returned. Specifically this means adding an EDNS0 OPT RR that will advertise a larger
+// buffer, see SetEdns0. Messages without an OPT RR will fallback to the historic limit
+// of 512 bytes
+// To specify a local address or a timeout, the caller has to set the `Client.Dialer`
+// attribute appropriately
+func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, err error) {
+ if !c.SingleInflight {
+ return c.exchange(m, address)
+ }
+
+ t := "nop"
+ if t1, ok := TypeToString[m.Question[0].Qtype]; ok {
+ t = t1
+ }
+ cl := "nop"
+ if cl1, ok := ClassToString[m.Question[0].Qclass]; ok {
+ cl = cl1
+ }
+ r, rtt, err, shared := c.group.Do(m.Question[0].Name+t+cl, func() (*Msg, time.Duration, error) {
+ return c.exchange(m, address)
+ })
+ if r != nil && shared {
+ r = r.Copy()
+ }
+ return r, rtt, err
+}
+
+func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
+ var co *Conn
+
+ co, err = c.Dial(a)
+
+ if err != nil {
+ return nil, 0, err
+ }
+ defer co.Close()
+
+ opt := m.IsEdns0()
+ // If EDNS0 is used use that for size.
+ if opt != nil && opt.UDPSize() >= MinMsgSize {
+ co.UDPSize = opt.UDPSize()
+ }
+ // Otherwise use the client's configured UDP size.
+ if opt == nil && c.UDPSize >= MinMsgSize {
+ co.UDPSize = c.UDPSize
+ }
+
+ co.TsigSecret = c.TsigSecret
+ // write with the appropriate write timeout
+ co.SetWriteDeadline(time.Now().Add(c.getTimeoutForRequest(c.writeTimeout())))
+ if err = co.WriteMsg(m); err != nil {
+ return nil, 0, err
+ }
+
+ co.SetReadDeadline(time.Now().Add(c.getTimeoutForRequest(c.readTimeout())))
+ r, err = co.ReadMsg()
+ if err == nil && r.Id != m.Id {
+ err = ErrId
+ }
+ return r, co.rtt, err
+}
+
+// ReadMsg reads a message from the connection co.
+// If the received message contains a TSIG record the transaction
+// signature is verified.
+func (co *Conn) ReadMsg() (*Msg, error) {
+ p, err := co.ReadMsgHeader(nil)
+ if err != nil {
+ return nil, err
+ }
+
+ m := new(Msg)
+ if err := m.Unpack(p); err != nil {
+ // If ErrTruncated was returned, we still want to allow the user to use
+ // the message, but naively they can just check err if they don't want
+ // to use a truncated message
+ if err == ErrTruncated {
+ return m, err
+ }
+ return nil, err
+ }
+ if t := m.IsTsig(); t != nil {
+ if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
+ return m, ErrSecret
+ }
+ // Need to work on the original message p, as that was used to calculate the tsig.
+ err = TsigVerify(p, co.TsigSecret[t.Hdr.Name], co.tsigRequestMAC, false)
+ }
+ return m, err
+}
+
+// ReadMsgHeader reads a DNS message, parses and populates hdr (when hdr is not nil).
+// Returns message as a byte slice to be parsed with Msg.Unpack later on.
+// Note that error handling on the message body is not possible as only the header is parsed.
+func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
+ var (
+ p []byte
+ n int
+ err error
+ )
+
+ switch t := co.Conn.(type) {
+ case *net.TCPConn, *tls.Conn:
+ r := t.(io.Reader)
+
+ // First two bytes specify the length of the entire message.
+ l, err := tcpMsgLen(r)
+ if err != nil {
+ return nil, err
+ }
+ p = make([]byte, l)
+ n, err = tcpRead(r, p)
+ co.rtt = time.Since(co.t)
+ default:
+ if co.UDPSize > MinMsgSize {
+ p = make([]byte, co.UDPSize)
+ } else {
+ p = make([]byte, MinMsgSize)
+ }
+ n, err = co.Read(p)
+ co.rtt = time.Since(co.t)
+ }
+
+ if err != nil {
+ return nil, err
+ } else if n < headerSize {
+ return nil, ErrShortRead
+ }
+
+ p = p[:n]
+ if hdr != nil {
+ dh, _, err := unpackMsgHdr(p, 0)
+ if err != nil {
+ return nil, err
+ }
+ *hdr = dh
+ }
+ return p, err
+}
+
+// tcpMsgLen is a helper func to read first two bytes of stream as uint16 packet length.
+func tcpMsgLen(t io.Reader) (int, error) {
+ p := []byte{0, 0}
+ n, err := t.Read(p)
+ if err != nil {
+ return 0, err
+ }
+
+ // As seen with my local router/switch, returns 1 byte on the above read,
+ // resulting a a ShortRead. Just write it out (instead of loop) and read the
+ // other byte.
+ if n == 1 {
+ n1, err := t.Read(p[1:])
+ if err != nil {
+ return 0, err
+ }
+ n += n1
+ }
+
+ if n != 2 {
+ return 0, ErrShortRead
+ }
+ l := binary.BigEndian.Uint16(p)
+ if l == 0 {
+ return 0, ErrShortRead
+ }
+ return int(l), nil
+}
+
+// tcpRead calls TCPConn.Read enough times to fill allocated buffer.
+func tcpRead(t io.Reader, p []byte) (int, error) {
+ n, err := t.Read(p)
+ if err != nil {
+ return n, err
+ }
+ for n < len(p) {
+ j, err := t.Read(p[n:])
+ if err != nil {
+ return n, err
+ }
+ n += j
+ }
+ return n, err
+}
+
+// Read implements the net.Conn read method.
+func (co *Conn) Read(p []byte) (n int, err error) {
+ if co.Conn == nil {
+ return 0, ErrConnEmpty
+ }
+ if len(p) < 2 {
+ return 0, io.ErrShortBuffer
+ }
+ switch t := co.Conn.(type) {
+ case *net.TCPConn, *tls.Conn:
+ r := t.(io.Reader)
+
+ l, err := tcpMsgLen(r)
+ if err != nil {
+ return 0, err
+ }
+ if l > len(p) {
+ return int(l), io.ErrShortBuffer
+ }
+ return tcpRead(r, p[:l])
+ }
+ // UDP connection
+ n, err = co.Conn.Read(p)
+ if err != nil {
+ return n, err
+ }
+ return n, err
+}
+
+// WriteMsg sends a message through the connection co.
+// If the message m contains a TSIG record the transaction
+// signature is calculated.
+func (co *Conn) WriteMsg(m *Msg) (err error) {
+ var out []byte
+ if t := m.IsTsig(); t != nil {
+ mac := ""
+ if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
+ return ErrSecret
+ }
+ out, mac, err = TsigGenerate(m, co.TsigSecret[t.Hdr.Name], co.tsigRequestMAC, false)
+ // Set for the next read, although only used in zone transfers
+ co.tsigRequestMAC = mac
+ } else {
+ out, err = m.Pack()
+ }
+ if err != nil {
+ return err
+ }
+ co.t = time.Now()
+ if _, err = co.Write(out); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Write implements the net.Conn Write method.
+func (co *Conn) Write(p []byte) (n int, err error) {
+ switch t := co.Conn.(type) {
+ case *net.TCPConn, *tls.Conn:
+ w := t.(io.Writer)
+
+ lp := len(p)
+ if lp < 2 {
+ return 0, io.ErrShortBuffer
+ }
+ if lp > MaxMsgSize {
+ return 0, &Error{err: "message too large"}
+ }
+ l := make([]byte, 2, lp+2)
+ binary.BigEndian.PutUint16(l, uint16(lp))
+ p = append(l, p...)
+ n, err := io.Copy(w, bytes.NewReader(p))
+ return int(n), err
+ }
+ n, err = co.Conn.Write(p)
+ return n, err
+}
+
+// Return the appropriate timeout for a specific request
+func (c *Client) getTimeoutForRequest(timeout time.Duration) time.Duration {
+ var requestTimeout time.Duration
+ if c.Timeout != 0 {
+ requestTimeout = c.Timeout
+ } else {
+ requestTimeout = timeout
+ }
+ // net.Dialer.Timeout has priority if smaller than the timeouts computed so
+ // far
+ if c.Dialer != nil && c.Dialer.Timeout != 0 {
+ if c.Dialer.Timeout < requestTimeout {
+ requestTimeout = c.Dialer.Timeout
+ }
+ }
+ return requestTimeout
+}
+
+// Dial connects to the address on the named network.
+func Dial(network, address string) (conn *Conn, err error) {
+ conn = new(Conn)
+ conn.Conn, err = net.Dial(network, address)
+ if err != nil {
+ return nil, err
+ }
+ return conn, nil
+}
+
+// ExchangeContext performs a synchronous UDP query, like Exchange. It
+// additionally obeys deadlines from the passed Context.
+func ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, err error) {
+ client := Client{Net: "udp"}
+ r, _, err = client.ExchangeContext(ctx, m, a)
+ // ignorint rtt to leave the original ExchangeContext API unchanged, but
+ // this function will go away
+ return r, err
+}
+
+// ExchangeConn performs a synchronous query. It sends the message m via the connection
+// c and waits for a reply. The connection c is not closed by ExchangeConn.
+// This function is going away, but can easily be mimicked:
+//
+// co := &dns.Conn{Conn: c} // c is your net.Conn
+// co.WriteMsg(m)
+// in, _ := co.ReadMsg()
+// co.Close()
+//
+func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
+ println("dns: ExchangeConn: this function is deprecated")
+ co := new(Conn)
+ co.Conn = c
+ if err = co.WriteMsg(m); err != nil {
+ return nil, err
+ }
+ r, err = co.ReadMsg()
+ if err == nil && r.Id != m.Id {
+ err = ErrId
+ }
+ return r, err
+}
+
+// DialTimeout acts like Dial but takes a timeout.
+func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) {
+ client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}}
+ conn, err = client.Dial(address)
+ if err != nil {
+ return nil, err
+ }
+ return conn, nil
+}
+
+// DialWithTLS connects to the address on the named network with TLS.
+func DialWithTLS(network, address string, tlsConfig *tls.Config) (conn *Conn, err error) {
+ if !strings.HasSuffix(network, "-tls") {
+ network += "-tls"
+ }
+ client := Client{Net: network, TLSConfig: tlsConfig}
+ conn, err = client.Dial(address)
+
+ if err != nil {
+ return nil, err
+ }
+ return conn, nil
+}
+
+// DialTimeoutWithTLS acts like DialWithTLS but takes a timeout.
+func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout time.Duration) (conn *Conn, err error) {
+ if !strings.HasSuffix(network, "-tls") {
+ network += "-tls"
+ }
+ client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}, TLSConfig: tlsConfig}
+ conn, err = client.Dial(address)
+ if err != nil {
+ return nil, err
+ }
+ return conn, nil
+}
+
+// ExchangeContext acts like Exchange, but honors the deadline on the provided
+// context, if present. If there is both a context deadline and a configured
+// timeout on the client, the earliest of the two takes effect.
+func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
+ var timeout time.Duration
+ if deadline, ok := ctx.Deadline(); !ok {
+ timeout = 0
+ } else {
+ timeout = deadline.Sub(time.Now())
+ }
+ // not passing the context to the underlying calls, as the API does not support
+ // context. For timeouts you should set up Client.Dialer and call Client.Exchange.
+ c.Dialer = &net.Dialer{Timeout: timeout}
+ return c.Exchange(m, a)
+}
--- /dev/null
+package dns
+
+import (
+ "bufio"
+ "io"
+ "os"
+ "strconv"
+ "strings"
+)
+
+// ClientConfig wraps the contents of the /etc/resolv.conf file.
+type ClientConfig struct {
+ Servers []string // servers to use
+ Search []string // suffixes to append to local name
+ Port string // what port to use
+ Ndots int // number of dots in name to trigger absolute lookup
+ Timeout int // seconds before giving up on packet
+ Attempts int // lost packets before giving up on server, not used in the package dns
+}
+
+// ClientConfigFromFile parses a resolv.conf(5) like file and returns
+// a *ClientConfig.
+func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) {
+ file, err := os.Open(resolvconf)
+ if err != nil {
+ return nil, err
+ }
+ defer file.Close()
+ return ClientConfigFromReader(file)
+}
+
+// ClientConfigFromReader works like ClientConfigFromFile but takes an io.Reader as argument
+func ClientConfigFromReader(resolvconf io.Reader) (*ClientConfig, error) {
+ c := new(ClientConfig)
+ scanner := bufio.NewScanner(resolvconf)
+ c.Servers = make([]string, 0)
+ c.Search = make([]string, 0)
+ c.Port = "53"
+ c.Ndots = 1
+ c.Timeout = 5
+ c.Attempts = 2
+
+ for scanner.Scan() {
+ if err := scanner.Err(); err != nil {
+ return nil, err
+ }
+ line := scanner.Text()
+ f := strings.Fields(line)
+ if len(f) < 1 {
+ continue
+ }
+ switch f[0] {
+ case "nameserver": // add one name server
+ if len(f) > 1 {
+ // One more check: make sure server name is
+ // just an IP address. Otherwise we need DNS
+ // to look it up.
+ name := f[1]
+ c.Servers = append(c.Servers, name)
+ }
+
+ case "domain": // set search path to just this domain
+ if len(f) > 1 {
+ c.Search = make([]string, 1)
+ c.Search[0] = f[1]
+ } else {
+ c.Search = make([]string, 0)
+ }
+
+ case "search": // set search path to given servers
+ c.Search = make([]string, len(f)-1)
+ for i := 0; i < len(c.Search); i++ {
+ c.Search[i] = f[i+1]
+ }
+
+ case "options": // magic options
+ for i := 1; i < len(f); i++ {
+ s := f[i]
+ switch {
+ case len(s) >= 6 && s[:6] == "ndots:":
+ n, _ := strconv.Atoi(s[6:])
+ if n < 1 {
+ n = 1
+ }
+ c.Ndots = n
+ case len(s) >= 8 && s[:8] == "timeout:":
+ n, _ := strconv.Atoi(s[8:])
+ if n < 1 {
+ n = 1
+ }
+ c.Timeout = n
+ case len(s) >= 8 && s[:9] == "attempts:":
+ n, _ := strconv.Atoi(s[9:])
+ if n < 1 {
+ n = 1
+ }
+ c.Attempts = n
+ case s == "rotate":
+ /* not imp */
+ }
+ }
+ }
+ }
+ return c, nil
+}
+
+// NameList returns all of the names that should be queried based on the
+// config. It is based off of go's net/dns name building, but it does not
+// check the length of the resulting names.
+func (c *ClientConfig) NameList(name string) []string {
+ // if this domain is already fully qualified, no append needed.
+ if IsFqdn(name) {
+ return []string{name}
+ }
+
+ // Check to see if the name has more labels than Ndots. Do this before making
+ // the domain fully qualified.
+ hasNdots := CountLabel(name) > c.Ndots
+ // Make the domain fully qualified.
+ name = Fqdn(name)
+
+ // Make a list of names based off search.
+ names := []string{}
+
+ // If name has enough dots, try that first.
+ if hasNdots {
+ names = append(names, name)
+ }
+ for _, s := range c.Search {
+ names = append(names, Fqdn(name+s))
+ }
+ // If we didn't have enough dots, try after suffixes.
+ if !hasNdots {
+ names = append(names, name)
+ }
+ return names
+}
--- /dev/null
+//+build ignore
+
+// compression_generate.go is meant to run with go generate. It will use
+// go/{importer,types} to track down all the RR struct types. Then for each type
+// it will look to see if there are (compressible) names, if so it will add that
+// type to compressionLenHelperType and comressionLenSearchType which "fake" the
+// compression so that Len() is fast.
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/format"
+ "go/importer"
+ "go/types"
+ "log"
+ "os"
+)
+
+var packageHdr = `
+// *** DO NOT MODIFY ***
+// AUTOGENERATED BY go generate from compress_generate.go
+
+package dns
+
+`
+
+// getTypeStruct will take a type and the package scope, and return the
+// (innermost) struct if the type is considered a RR type (currently defined as
+// those structs beginning with a RR_Header, could be redefined as implementing
+// the RR interface). The bool return value indicates if embedded structs were
+// resolved.
+func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
+ st, ok := t.Underlying().(*types.Struct)
+ if !ok {
+ return nil, false
+ }
+ if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
+ return st, false
+ }
+ if st.Field(0).Anonymous() {
+ st, _ := getTypeStruct(st.Field(0).Type(), scope)
+ return st, true
+ }
+ return nil, false
+}
+
+func main() {
+ // Import and type-check the package
+ pkg, err := importer.Default().Import("github.com/miekg/dns")
+ fatalIfErr(err)
+ scope := pkg.Scope()
+
+ var domainTypes []string // Types that have a domain name in them (either compressible or not).
+ var cdomainTypes []string // Types that have a compressible domain name in them (subset of domainType)
+Names:
+ for _, name := range scope.Names() {
+ o := scope.Lookup(name)
+ if o == nil || !o.Exported() {
+ continue
+ }
+ st, _ := getTypeStruct(o.Type(), scope)
+ if st == nil {
+ continue
+ }
+ if name == "PrivateRR" {
+ continue
+ }
+
+ if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
+ log.Fatalf("Constant Type%s does not exist.", o.Name())
+ }
+
+ for i := 1; i < st.NumFields(); i++ {
+ if _, ok := st.Field(i).Type().(*types.Slice); ok {
+ if st.Tag(i) == `dns:"domain-name"` {
+ domainTypes = append(domainTypes, o.Name())
+ continue Names
+ }
+ if st.Tag(i) == `dns:"cdomain-name"` {
+ cdomainTypes = append(cdomainTypes, o.Name())
+ domainTypes = append(domainTypes, o.Name())
+ continue Names
+ }
+ continue
+ }
+
+ switch {
+ case st.Tag(i) == `dns:"domain-name"`:
+ domainTypes = append(domainTypes, o.Name())
+ continue Names
+ case st.Tag(i) == `dns:"cdomain-name"`:
+ cdomainTypes = append(cdomainTypes, o.Name())
+ domainTypes = append(domainTypes, o.Name())
+ continue Names
+ }
+ }
+ }
+
+ b := &bytes.Buffer{}
+ b.WriteString(packageHdr)
+
+ // compressionLenHelperType - all types that have domain-name/cdomain-name can be used for compressing names
+
+ fmt.Fprint(b, "func compressionLenHelperType(c map[string]int, r RR) {\n")
+ fmt.Fprint(b, "switch x := r.(type) {\n")
+ for _, name := range domainTypes {
+ o := scope.Lookup(name)
+ st, _ := getTypeStruct(o.Type(), scope)
+
+ fmt.Fprintf(b, "case *%s:\n", name)
+ for i := 1; i < st.NumFields(); i++ {
+ out := func(s string) { fmt.Fprintf(b, "compressionLenHelper(c, x.%s)\n", st.Field(i).Name()) }
+
+ if _, ok := st.Field(i).Type().(*types.Slice); ok {
+ switch st.Tag(i) {
+ case `dns:"domain-name"`:
+ fallthrough
+ case `dns:"cdomain-name"`:
+ // For HIP we need to slice over the elements in this slice.
+ fmt.Fprintf(b, `for i := range x.%s {
+ compressionLenHelper(c, x.%s[i])
+ }
+`, st.Field(i).Name(), st.Field(i).Name())
+ }
+ continue
+ }
+
+ switch {
+ case st.Tag(i) == `dns:"cdomain-name"`:
+ fallthrough
+ case st.Tag(i) == `dns:"domain-name"`:
+ out(st.Field(i).Name())
+ }
+ }
+ }
+ fmt.Fprintln(b, "}\n}\n\n")
+
+ // compressionLenSearchType - search cdomain-tags types for compressible names.
+
+ fmt.Fprint(b, "func compressionLenSearchType(c map[string]int, r RR) (int, bool) {\n")
+ fmt.Fprint(b, "switch x := r.(type) {\n")
+ for _, name := range cdomainTypes {
+ o := scope.Lookup(name)
+ st, _ := getTypeStruct(o.Type(), scope)
+
+ fmt.Fprintf(b, "case *%s:\n", name)
+ j := 1
+ for i := 1; i < st.NumFields(); i++ {
+ out := func(s string, j int) {
+ fmt.Fprintf(b, "k%d, ok%d := compressionLenSearch(c, x.%s)\n", j, j, st.Field(i).Name())
+ }
+
+ // There are no slice types with names that can be compressed.
+
+ switch {
+ case st.Tag(i) == `dns:"cdomain-name"`:
+ out(st.Field(i).Name(), j)
+ j++
+ }
+ }
+ k := "k1"
+ ok := "ok1"
+ for i := 2; i < j; i++ {
+ k += fmt.Sprintf(" + k%d", i)
+ ok += fmt.Sprintf(" && ok%d", i)
+ }
+ fmt.Fprintf(b, "return %s, %s\n", k, ok)
+ }
+ fmt.Fprintln(b, "}\nreturn 0, false\n}\n\n")
+
+ // gofmt
+ res, err := format.Source(b.Bytes())
+ if err != nil {
+ b.WriteTo(os.Stderr)
+ log.Fatal(err)
+ }
+
+ f, err := os.Create("zcompress.go")
+ fatalIfErr(err)
+ defer f.Close()
+ f.Write(res)
+}
+
+func fatalIfErr(err error) {
+ if err != nil {
+ log.Fatal(err)
+ }
+}
--- /dev/null
+package dns
+
+import (
+ "crypto/sha256"
+ "crypto/sha512"
+ "crypto/x509"
+ "encoding/hex"
+ "errors"
+)
+
+// CertificateToDANE converts a certificate to a hex string as used in the TLSA or SMIMEA records.
+func CertificateToDANE(selector, matchingType uint8, cert *x509.Certificate) (string, error) {
+ switch matchingType {
+ case 0:
+ switch selector {
+ case 0:
+ return hex.EncodeToString(cert.Raw), nil
+ case 1:
+ return hex.EncodeToString(cert.RawSubjectPublicKeyInfo), nil
+ }
+ case 1:
+ h := sha256.New()
+ switch selector {
+ case 0:
+ h.Write(cert.Raw)
+ return hex.EncodeToString(h.Sum(nil)), nil
+ case 1:
+ h.Write(cert.RawSubjectPublicKeyInfo)
+ return hex.EncodeToString(h.Sum(nil)), nil
+ }
+ case 2:
+ h := sha512.New()
+ switch selector {
+ case 0:
+ h.Write(cert.Raw)
+ return hex.EncodeToString(h.Sum(nil)), nil
+ case 1:
+ h.Write(cert.RawSubjectPublicKeyInfo)
+ return hex.EncodeToString(h.Sum(nil)), nil
+ }
+ }
+ return "", errors.New("dns: bad MatchingType or Selector")
+}
--- /dev/null
+package dns
+
+import (
+ "errors"
+ "net"
+ "strconv"
+)
+
+const hexDigit = "0123456789abcdef"
+
+// Everything is assumed in ClassINET.
+
+// SetReply creates a reply message from a request message.
+func (dns *Msg) SetReply(request *Msg) *Msg {
+ dns.Id = request.Id
+ dns.Response = true
+ dns.Opcode = request.Opcode
+ if dns.Opcode == OpcodeQuery {
+ dns.RecursionDesired = request.RecursionDesired // Copy rd bit
+ dns.CheckingDisabled = request.CheckingDisabled // Copy cd bit
+ }
+ dns.Rcode = RcodeSuccess
+ if len(request.Question) > 0 {
+ dns.Question = make([]Question, 1)
+ dns.Question[0] = request.Question[0]
+ }
+ return dns
+}
+
+// SetQuestion creates a question message, it sets the Question
+// section, generates an Id and sets the RecursionDesired (RD)
+// bit to true.
+func (dns *Msg) SetQuestion(z string, t uint16) *Msg {
+ dns.Id = Id()
+ dns.RecursionDesired = true
+ dns.Question = make([]Question, 1)
+ dns.Question[0] = Question{z, t, ClassINET}
+ return dns
+}
+
+// SetNotify creates a notify message, it sets the Question
+// section, generates an Id and sets the Authoritative (AA)
+// bit to true.
+func (dns *Msg) SetNotify(z string) *Msg {
+ dns.Opcode = OpcodeNotify
+ dns.Authoritative = true
+ dns.Id = Id()
+ dns.Question = make([]Question, 1)
+ dns.Question[0] = Question{z, TypeSOA, ClassINET}
+ return dns
+}
+
+// SetRcode creates an error message suitable for the request.
+func (dns *Msg) SetRcode(request *Msg, rcode int) *Msg {
+ dns.SetReply(request)
+ dns.Rcode = rcode
+ return dns
+}
+
+// SetRcodeFormatError creates a message with FormError set.
+func (dns *Msg) SetRcodeFormatError(request *Msg) *Msg {
+ dns.Rcode = RcodeFormatError
+ dns.Opcode = OpcodeQuery
+ dns.Response = true
+ dns.Authoritative = false
+ dns.Id = request.Id
+ return dns
+}
+
+// SetUpdate makes the message a dynamic update message. It
+// sets the ZONE section to: z, TypeSOA, ClassINET.
+func (dns *Msg) SetUpdate(z string) *Msg {
+ dns.Id = Id()
+ dns.Response = false
+ dns.Opcode = OpcodeUpdate
+ dns.Compress = false // BIND9 cannot handle compression
+ dns.Question = make([]Question, 1)
+ dns.Question[0] = Question{z, TypeSOA, ClassINET}
+ return dns
+}
+
+// SetIxfr creates message for requesting an IXFR.
+func (dns *Msg) SetIxfr(z string, serial uint32, ns, mbox string) *Msg {
+ dns.Id = Id()
+ dns.Question = make([]Question, 1)
+ dns.Ns = make([]RR, 1)
+ s := new(SOA)
+ s.Hdr = RR_Header{z, TypeSOA, ClassINET, defaultTtl, 0}
+ s.Serial = serial
+ s.Ns = ns
+ s.Mbox = mbox
+ dns.Question[0] = Question{z, TypeIXFR, ClassINET}
+ dns.Ns[0] = s
+ return dns
+}
+
+// SetAxfr creates message for requesting an AXFR.
+func (dns *Msg) SetAxfr(z string) *Msg {
+ dns.Id = Id()
+ dns.Question = make([]Question, 1)
+ dns.Question[0] = Question{z, TypeAXFR, ClassINET}
+ return dns
+}
+
+// SetTsig appends a TSIG RR to the message.
+// This is only a skeleton TSIG RR that is added as the last RR in the
+// additional section. The Tsig is calculated when the message is being send.
+func (dns *Msg) SetTsig(z, algo string, fudge uint16, timesigned int64) *Msg {
+ t := new(TSIG)
+ t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0}
+ t.Algorithm = algo
+ t.Fudge = fudge
+ t.TimeSigned = uint64(timesigned)
+ t.OrigId = dns.Id
+ dns.Extra = append(dns.Extra, t)
+ return dns
+}
+
+// SetEdns0 appends a EDNS0 OPT RR to the message.
+// TSIG should always the last RR in a message.
+func (dns *Msg) SetEdns0(udpsize uint16, do bool) *Msg {
+ e := new(OPT)
+ e.Hdr.Name = "."
+ e.Hdr.Rrtype = TypeOPT
+ e.SetUDPSize(udpsize)
+ if do {
+ e.SetDo()
+ }
+ dns.Extra = append(dns.Extra, e)
+ return dns
+}
+
+// IsTsig checks if the message has a TSIG record as the last record
+// in the additional section. It returns the TSIG record found or nil.
+func (dns *Msg) IsTsig() *TSIG {
+ if len(dns.Extra) > 0 {
+ if dns.Extra[len(dns.Extra)-1].Header().Rrtype == TypeTSIG {
+ return dns.Extra[len(dns.Extra)-1].(*TSIG)
+ }
+ }
+ return nil
+}
+
+// IsEdns0 checks if the message has a EDNS0 (OPT) record, any EDNS0
+// record in the additional section will do. It returns the OPT record
+// found or nil.
+func (dns *Msg) IsEdns0() *OPT {
+ // EDNS0 is at the end of the additional section, start there.
+ // We might want to change this to *only* look at the last two
+ // records. So we see TSIG and/or OPT - this a slightly bigger
+ // change though.
+ for i := len(dns.Extra) - 1; i >= 0; i-- {
+ if dns.Extra[i].Header().Rrtype == TypeOPT {
+ return dns.Extra[i].(*OPT)
+ }
+ }
+ return nil
+}
+
+// IsDomainName checks if s is a valid domain name, it returns the number of
+// labels and true, when a domain name is valid. Note that non fully qualified
+// domain name is considered valid, in this case the last label is counted in
+// the number of labels. When false is returned the number of labels is not
+// defined. Also note that this function is extremely liberal; almost any
+// string is a valid domain name as the DNS is 8 bit protocol. It checks if each
+// label fits in 63 characters, but there is no length check for the entire
+// string s. I.e. a domain name longer than 255 characters is considered valid.
+func IsDomainName(s string) (labels int, ok bool) {
+ _, labels, err := packDomainName(s, nil, 0, nil, false)
+ return labels, err == nil
+}
+
+// IsSubDomain checks if child is indeed a child of the parent. If child and parent
+// are the same domain true is returned as well.
+func IsSubDomain(parent, child string) bool {
+ // Entire child is contained in parent
+ return CompareDomainName(parent, child) == CountLabel(parent)
+}
+
+// IsMsg sanity checks buf and returns an error if it isn't a valid DNS packet.
+// The checking is performed on the binary payload.
+func IsMsg(buf []byte) error {
+ // Header
+ if len(buf) < 12 {
+ return errors.New("dns: bad message header")
+ }
+ // Header: Opcode
+ // TODO(miek): more checks here, e.g. check all header bits.
+ return nil
+}
+
+// IsFqdn checks if a domain name is fully qualified.
+func IsFqdn(s string) bool {
+ l := len(s)
+ if l == 0 {
+ return false
+ }
+ return s[l-1] == '.'
+}
+
+// IsRRset checks if a set of RRs is a valid RRset as defined by RFC 2181.
+// This means the RRs need to have the same type, name, and class. Returns true
+// if the RR set is valid, otherwise false.
+func IsRRset(rrset []RR) bool {
+ if len(rrset) == 0 {
+ return false
+ }
+ if len(rrset) == 1 {
+ return true
+ }
+ rrHeader := rrset[0].Header()
+ rrType := rrHeader.Rrtype
+ rrClass := rrHeader.Class
+ rrName := rrHeader.Name
+
+ for _, rr := range rrset[1:] {
+ curRRHeader := rr.Header()
+ if curRRHeader.Rrtype != rrType || curRRHeader.Class != rrClass || curRRHeader.Name != rrName {
+ // Mismatch between the records, so this is not a valid rrset for
+ //signing/verifying
+ return false
+ }
+ }
+
+ return true
+}
+
+// Fqdn return the fully qualified domain name from s.
+// If s is already fully qualified, it behaves as the identity function.
+func Fqdn(s string) string {
+ if IsFqdn(s) {
+ return s
+ }
+ return s + "."
+}
+
+// Copied from the official Go code.
+
+// ReverseAddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP
+// address suitable for reverse DNS (PTR) record lookups or an error if it fails
+// to parse the IP address.
+func ReverseAddr(addr string) (arpa string, err error) {
+ ip := net.ParseIP(addr)
+ if ip == nil {
+ return "", &Error{err: "unrecognized address: " + addr}
+ }
+ if ip.To4() != nil {
+ return strconv.Itoa(int(ip[15])) + "." + strconv.Itoa(int(ip[14])) + "." + strconv.Itoa(int(ip[13])) + "." +
+ strconv.Itoa(int(ip[12])) + ".in-addr.arpa.", nil
+ }
+ // Must be IPv6
+ buf := make([]byte, 0, len(ip)*4+len("ip6.arpa."))
+ // Add it, in reverse, to the buffer
+ for i := len(ip) - 1; i >= 0; i-- {
+ v := ip[i]
+ buf = append(buf, hexDigit[v&0xF])
+ buf = append(buf, '.')
+ buf = append(buf, hexDigit[v>>4])
+ buf = append(buf, '.')
+ }
+ // Append "ip6.arpa." and return (buf already has the final .)
+ buf = append(buf, "ip6.arpa."...)
+ return string(buf), nil
+}
+
+// String returns the string representation for the type t.
+func (t Type) String() string {
+ if t1, ok := TypeToString[uint16(t)]; ok {
+ return t1
+ }
+ return "TYPE" + strconv.Itoa(int(t))
+}
+
+// String returns the string representation for the class c.
+func (c Class) String() string {
+ if c1, ok := ClassToString[uint16(c)]; ok {
+ return c1
+ }
+ return "CLASS" + strconv.Itoa(int(c))
+}
+
+// String returns the string representation for the name n.
+func (n Name) String() string {
+ return sprintName(string(n))
+}
--- /dev/null
+package dns
+
+import "strconv"
+
+const (
+ year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits.
+ defaultTtl = 3600 // Default internal TTL.
+
+ // DefaultMsgSize is the standard default for messages larger than 512 bytes.
+ DefaultMsgSize = 4096
+ // MinMsgSize is the minimal size of a DNS packet.
+ MinMsgSize = 512
+ // MaxMsgSize is the largest possible DNS packet.
+ MaxMsgSize = 65535
+)
+
+// Error represents a DNS error.
+type Error struct{ err string }
+
+func (e *Error) Error() string {
+ if e == nil {
+ return "dns: <nil>"
+ }
+ return "dns: " + e.err
+}
+
+// An RR represents a resource record.
+type RR interface {
+ // Header returns the header of an resource record. The header contains
+ // everything up to the rdata.
+ Header() *RR_Header
+ // String returns the text representation of the resource record.
+ String() string
+
+ // copy returns a copy of the RR
+ copy() RR
+ // len returns the length (in octets) of the uncompressed RR in wire format.
+ len() int
+ // pack packs an RR into wire format.
+ pack([]byte, int, map[string]int, bool) (int, error)
+}
+
+// RR_Header is the header all DNS resource records share.
+type RR_Header struct {
+ Name string `dns:"cdomain-name"`
+ Rrtype uint16
+ Class uint16
+ Ttl uint32
+ Rdlength uint16 // Length of data after header.
+}
+
+// Header returns itself. This is here to make RR_Header implements the RR interface.
+func (h *RR_Header) Header() *RR_Header { return h }
+
+// Just to implement the RR interface.
+func (h *RR_Header) copy() RR { return nil }
+
+func (h *RR_Header) copyHeader() *RR_Header {
+ r := new(RR_Header)
+ r.Name = h.Name
+ r.Rrtype = h.Rrtype
+ r.Class = h.Class
+ r.Ttl = h.Ttl
+ r.Rdlength = h.Rdlength
+ return r
+}
+
+func (h *RR_Header) String() string {
+ var s string
+
+ if h.Rrtype == TypeOPT {
+ s = ";"
+ // and maybe other things
+ }
+
+ s += sprintName(h.Name) + "\t"
+ s += strconv.FormatInt(int64(h.Ttl), 10) + "\t"
+ s += Class(h.Class).String() + "\t"
+ s += Type(h.Rrtype).String() + "\t"
+ return s
+}
+
+func (h *RR_Header) len() int {
+ l := len(h.Name) + 1
+ l += 10 // rrtype(2) + class(2) + ttl(4) + rdlength(2)
+ return l
+}
+
+// ToRFC3597 converts a known RR to the unknown RR representation from RFC 3597.
+func (rr *RFC3597) ToRFC3597(r RR) error {
+ buf := make([]byte, r.len()*2)
+ off, err := PackRR(r, buf, 0, nil, false)
+ if err != nil {
+ return err
+ }
+ buf = buf[:off]
+ if int(r.Header().Rdlength) > off {
+ return ErrBuf
+ }
+
+ rfc3597, _, err := unpackRFC3597(*r.Header(), buf, off-int(r.Header().Rdlength))
+ if err != nil {
+ return err
+ }
+ *rr = *rfc3597.(*RFC3597)
+ return nil
+}
--- /dev/null
+package dns
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/dsa"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ _ "crypto/md5"
+ "crypto/rand"
+ "crypto/rsa"
+ _ "crypto/sha1"
+ _ "crypto/sha256"
+ _ "crypto/sha512"
+ "encoding/asn1"
+ "encoding/binary"
+ "encoding/hex"
+ "math/big"
+ "sort"
+ "strings"
+ "time"
+)
+
+// DNSSEC encryption algorithm codes.
+const (
+ _ uint8 = iota
+ RSAMD5
+ DH
+ DSA
+ _ // Skip 4, RFC 6725, section 2.1
+ RSASHA1
+ DSANSEC3SHA1
+ RSASHA1NSEC3SHA1
+ RSASHA256
+ _ // Skip 9, RFC 6725, section 2.1
+ RSASHA512
+ _ // Skip 11, RFC 6725, section 2.1
+ ECCGOST
+ ECDSAP256SHA256
+ ECDSAP384SHA384
+ INDIRECT uint8 = 252
+ PRIVATEDNS uint8 = 253 // Private (experimental keys)
+ PRIVATEOID uint8 = 254
+)
+
+// AlgorithmToString is a map of algorithm IDs to algorithm names.
+var AlgorithmToString = map[uint8]string{
+ RSAMD5: "RSAMD5",
+ DH: "DH",
+ DSA: "DSA",
+ RSASHA1: "RSASHA1",
+ DSANSEC3SHA1: "DSA-NSEC3-SHA1",
+ RSASHA1NSEC3SHA1: "RSASHA1-NSEC3-SHA1",
+ RSASHA256: "RSASHA256",
+ RSASHA512: "RSASHA512",
+ ECCGOST: "ECC-GOST",
+ ECDSAP256SHA256: "ECDSAP256SHA256",
+ ECDSAP384SHA384: "ECDSAP384SHA384",
+ INDIRECT: "INDIRECT",
+ PRIVATEDNS: "PRIVATEDNS",
+ PRIVATEOID: "PRIVATEOID",
+}
+
+// StringToAlgorithm is the reverse of AlgorithmToString.
+var StringToAlgorithm = reverseInt8(AlgorithmToString)
+
+// AlgorithmToHash is a map of algorithm crypto hash IDs to crypto.Hash's.
+var AlgorithmToHash = map[uint8]crypto.Hash{
+ RSAMD5: crypto.MD5, // Deprecated in RFC 6725
+ RSASHA1: crypto.SHA1,
+ RSASHA1NSEC3SHA1: crypto.SHA1,
+ RSASHA256: crypto.SHA256,
+ ECDSAP256SHA256: crypto.SHA256,
+ ECDSAP384SHA384: crypto.SHA384,
+ RSASHA512: crypto.SHA512,
+}
+
+// DNSSEC hashing algorithm codes.
+const (
+ _ uint8 = iota
+ SHA1 // RFC 4034
+ SHA256 // RFC 4509
+ GOST94 // RFC 5933
+ SHA384 // Experimental
+ SHA512 // Experimental
+)
+
+// HashToString is a map of hash IDs to names.
+var HashToString = map[uint8]string{
+ SHA1: "SHA1",
+ SHA256: "SHA256",
+ GOST94: "GOST94",
+ SHA384: "SHA384",
+ SHA512: "SHA512",
+}
+
+// StringToHash is a map of names to hash IDs.
+var StringToHash = reverseInt8(HashToString)
+
+// DNSKEY flag values.
+const (
+ SEP = 1
+ REVOKE = 1 << 7
+ ZONE = 1 << 8
+)
+
+// The RRSIG needs to be converted to wireformat with some of the rdata (the signature) missing.
+type rrsigWireFmt struct {
+ TypeCovered uint16
+ Algorithm uint8
+ Labels uint8
+ OrigTtl uint32
+ Expiration uint32
+ Inception uint32
+ KeyTag uint16
+ SignerName string `dns:"domain-name"`
+ /* No Signature */
+}
+
+// Used for converting DNSKEY's rdata to wirefmt.
+type dnskeyWireFmt struct {
+ Flags uint16
+ Protocol uint8
+ Algorithm uint8
+ PublicKey string `dns:"base64"`
+ /* Nothing is left out */
+}
+
+func divRoundUp(a, b int) int {
+ return (a + b - 1) / b
+}
+
+// KeyTag calculates the keytag (or key-id) of the DNSKEY.
+func (k *DNSKEY) KeyTag() uint16 {
+ if k == nil {
+ return 0
+ }
+ var keytag int
+ switch k.Algorithm {
+ case RSAMD5:
+ // Look at the bottom two bytes of the modules, which the last
+ // item in the pubkey. We could do this faster by looking directly
+ // at the base64 values. But I'm lazy.
+ modulus, _ := fromBase64([]byte(k.PublicKey))
+ if len(modulus) > 1 {
+ x := binary.BigEndian.Uint16(modulus[len(modulus)-2:])
+ keytag = int(x)
+ }
+ default:
+ keywire := new(dnskeyWireFmt)
+ keywire.Flags = k.Flags
+ keywire.Protocol = k.Protocol
+ keywire.Algorithm = k.Algorithm
+ keywire.PublicKey = k.PublicKey
+ wire := make([]byte, DefaultMsgSize)
+ n, err := packKeyWire(keywire, wire)
+ if err != nil {
+ return 0
+ }
+ wire = wire[:n]
+ for i, v := range wire {
+ if i&1 != 0 {
+ keytag += int(v) // must be larger than uint32
+ } else {
+ keytag += int(v) << 8
+ }
+ }
+ keytag += (keytag >> 16) & 0xFFFF
+ keytag &= 0xFFFF
+ }
+ return uint16(keytag)
+}
+
+// ToDS converts a DNSKEY record to a DS record.
+func (k *DNSKEY) ToDS(h uint8) *DS {
+ if k == nil {
+ return nil
+ }
+ ds := new(DS)
+ ds.Hdr.Name = k.Hdr.Name
+ ds.Hdr.Class = k.Hdr.Class
+ ds.Hdr.Rrtype = TypeDS
+ ds.Hdr.Ttl = k.Hdr.Ttl
+ ds.Algorithm = k.Algorithm
+ ds.DigestType = h
+ ds.KeyTag = k.KeyTag()
+
+ keywire := new(dnskeyWireFmt)
+ keywire.Flags = k.Flags
+ keywire.Protocol = k.Protocol
+ keywire.Algorithm = k.Algorithm
+ keywire.PublicKey = k.PublicKey
+ wire := make([]byte, DefaultMsgSize)
+ n, err := packKeyWire(keywire, wire)
+ if err != nil {
+ return nil
+ }
+ wire = wire[:n]
+
+ owner := make([]byte, 255)
+ off, err1 := PackDomainName(strings.ToLower(k.Hdr.Name), owner, 0, nil, false)
+ if err1 != nil {
+ return nil
+ }
+ owner = owner[:off]
+ // RFC4034:
+ // digest = digest_algorithm( DNSKEY owner name | DNSKEY RDATA);
+ // "|" denotes concatenation
+ // DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key.
+
+ var hash crypto.Hash
+ switch h {
+ case SHA1:
+ hash = crypto.SHA1
+ case SHA256:
+ hash = crypto.SHA256
+ case SHA384:
+ hash = crypto.SHA384
+ case SHA512:
+ hash = crypto.SHA512
+ default:
+ return nil
+ }
+
+ s := hash.New()
+ s.Write(owner)
+ s.Write(wire)
+ ds.Digest = hex.EncodeToString(s.Sum(nil))
+ return ds
+}
+
+// ToCDNSKEY converts a DNSKEY record to a CDNSKEY record.
+func (k *DNSKEY) ToCDNSKEY() *CDNSKEY {
+ c := &CDNSKEY{DNSKEY: *k}
+ c.Hdr = *k.Hdr.copyHeader()
+ c.Hdr.Rrtype = TypeCDNSKEY
+ return c
+}
+
+// ToCDS converts a DS record to a CDS record.
+func (d *DS) ToCDS() *CDS {
+ c := &CDS{DS: *d}
+ c.Hdr = *d.Hdr.copyHeader()
+ c.Hdr.Rrtype = TypeCDS
+ return c
+}
+
+// Sign signs an RRSet. The signature needs to be filled in with the values:
+// Inception, Expiration, KeyTag, SignerName and Algorithm. The rest is copied
+// from the RRset. Sign returns a non-nill error when the signing went OK.
+// There is no check if RRSet is a proper (RFC 2181) RRSet. If OrigTTL is non
+// zero, it is used as-is, otherwise the TTL of the RRset is used as the
+// OrigTTL.
+func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
+ if k == nil {
+ return ErrPrivKey
+ }
+ // s.Inception and s.Expiration may be 0 (rollover etc.), the rest must be set
+ if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 {
+ return ErrKey
+ }
+
+ rr.Hdr.Rrtype = TypeRRSIG
+ rr.Hdr.Name = rrset[0].Header().Name
+ rr.Hdr.Class = rrset[0].Header().Class
+ if rr.OrigTtl == 0 { // If set don't override
+ rr.OrigTtl = rrset[0].Header().Ttl
+ }
+ rr.TypeCovered = rrset[0].Header().Rrtype
+ rr.Labels = uint8(CountLabel(rrset[0].Header().Name))
+
+ if strings.HasPrefix(rrset[0].Header().Name, "*") {
+ rr.Labels-- // wildcard, remove from label count
+ }
+
+ sigwire := new(rrsigWireFmt)
+ sigwire.TypeCovered = rr.TypeCovered
+ sigwire.Algorithm = rr.Algorithm
+ sigwire.Labels = rr.Labels
+ sigwire.OrigTtl = rr.OrigTtl
+ sigwire.Expiration = rr.Expiration
+ sigwire.Inception = rr.Inception
+ sigwire.KeyTag = rr.KeyTag
+ // For signing, lowercase this name
+ sigwire.SignerName = strings.ToLower(rr.SignerName)
+
+ // Create the desired binary blob
+ signdata := make([]byte, DefaultMsgSize)
+ n, err := packSigWire(sigwire, signdata)
+ if err != nil {
+ return err
+ }
+ signdata = signdata[:n]
+ wire, err := rawSignatureData(rrset, rr)
+ if err != nil {
+ return err
+ }
+
+ hash, ok := AlgorithmToHash[rr.Algorithm]
+ if !ok {
+ return ErrAlg
+ }
+
+ h := hash.New()
+ h.Write(signdata)
+ h.Write(wire)
+
+ signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm)
+ if err != nil {
+ return err
+ }
+
+ rr.Signature = toBase64(signature)
+
+ return nil
+}
+
+func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte, error) {
+ signature, err := k.Sign(rand.Reader, hashed, hash)
+ if err != nil {
+ return nil, err
+ }
+
+ switch alg {
+ case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512:
+ return signature, nil
+
+ case ECDSAP256SHA256, ECDSAP384SHA384:
+ ecdsaSignature := &struct {
+ R, S *big.Int
+ }{}
+ if _, err := asn1.Unmarshal(signature, ecdsaSignature); err != nil {
+ return nil, err
+ }
+
+ var intlen int
+ switch alg {
+ case ECDSAP256SHA256:
+ intlen = 32
+ case ECDSAP384SHA384:
+ intlen = 48
+ }
+
+ signature := intToBytes(ecdsaSignature.R, intlen)
+ signature = append(signature, intToBytes(ecdsaSignature.S, intlen)...)
+ return signature, nil
+
+ // There is no defined interface for what a DSA backed crypto.Signer returns
+ case DSA, DSANSEC3SHA1:
+ // t := divRoundUp(divRoundUp(p.PublicKey.Y.BitLen(), 8)-64, 8)
+ // signature := []byte{byte(t)}
+ // signature = append(signature, intToBytes(r1, 20)...)
+ // signature = append(signature, intToBytes(s1, 20)...)
+ // rr.Signature = signature
+ }
+
+ return nil, ErrAlg
+}
+
+// Verify validates an RRSet with the signature and key. This is only the
+// cryptographic test, the signature validity period must be checked separately.
+// This function copies the rdata of some RRs (to lowercase domain names) for the validation to work.
+func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
+ // First the easy checks
+ if !IsRRset(rrset) {
+ return ErrRRset
+ }
+ if rr.KeyTag != k.KeyTag() {
+ return ErrKey
+ }
+ if rr.Hdr.Class != k.Hdr.Class {
+ return ErrKey
+ }
+ if rr.Algorithm != k.Algorithm {
+ return ErrKey
+ }
+ if strings.ToLower(rr.SignerName) != strings.ToLower(k.Hdr.Name) {
+ return ErrKey
+ }
+ if k.Protocol != 3 {
+ return ErrKey
+ }
+
+ // IsRRset checked that we have at least one RR and that the RRs in
+ // the set have consistent type, class, and name. Also check that type and
+ // class matches the RRSIG record.
+ if rrset[0].Header().Class != rr.Hdr.Class {
+ return ErrRRset
+ }
+ if rrset[0].Header().Rrtype != rr.TypeCovered {
+ return ErrRRset
+ }
+
+ // RFC 4035 5.3.2. Reconstructing the Signed Data
+ // Copy the sig, except the rrsig data
+ sigwire := new(rrsigWireFmt)
+ sigwire.TypeCovered = rr.TypeCovered
+ sigwire.Algorithm = rr.Algorithm
+ sigwire.Labels = rr.Labels
+ sigwire.OrigTtl = rr.OrigTtl
+ sigwire.Expiration = rr.Expiration
+ sigwire.Inception = rr.Inception
+ sigwire.KeyTag = rr.KeyTag
+ sigwire.SignerName = strings.ToLower(rr.SignerName)
+ // Create the desired binary blob
+ signeddata := make([]byte, DefaultMsgSize)
+ n, err := packSigWire(sigwire, signeddata)
+ if err != nil {
+ return err
+ }
+ signeddata = signeddata[:n]
+ wire, err := rawSignatureData(rrset, rr)
+ if err != nil {
+ return err
+ }
+
+ sigbuf := rr.sigBuf() // Get the binary signature data
+ if rr.Algorithm == PRIVATEDNS { // PRIVATEOID
+ // TODO(miek)
+ // remove the domain name and assume its ours?
+ }
+
+ hash, ok := AlgorithmToHash[rr.Algorithm]
+ if !ok {
+ return ErrAlg
+ }
+
+ switch rr.Algorithm {
+ case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512, RSAMD5:
+ // TODO(mg): this can be done quicker, ie. cache the pubkey data somewhere??
+ pubkey := k.publicKeyRSA() // Get the key
+ if pubkey == nil {
+ return ErrKey
+ }
+
+ h := hash.New()
+ h.Write(signeddata)
+ h.Write(wire)
+ return rsa.VerifyPKCS1v15(pubkey, hash, h.Sum(nil), sigbuf)
+
+ case ECDSAP256SHA256, ECDSAP384SHA384:
+ pubkey := k.publicKeyECDSA()
+ if pubkey == nil {
+ return ErrKey
+ }
+
+ // Split sigbuf into the r and s coordinates
+ r := new(big.Int).SetBytes(sigbuf[:len(sigbuf)/2])
+ s := new(big.Int).SetBytes(sigbuf[len(sigbuf)/2:])
+
+ h := hash.New()
+ h.Write(signeddata)
+ h.Write(wire)
+ if ecdsa.Verify(pubkey, h.Sum(nil), r, s) {
+ return nil
+ }
+ return ErrSig
+
+ default:
+ return ErrAlg
+ }
+}
+
+// ValidityPeriod uses RFC1982 serial arithmetic to calculate
+// if a signature period is valid. If t is the zero time, the
+// current time is taken other t is. Returns true if the signature
+// is valid at the given time, otherwise returns false.
+func (rr *RRSIG) ValidityPeriod(t time.Time) bool {
+ var utc int64
+ if t.IsZero() {
+ utc = time.Now().UTC().Unix()
+ } else {
+ utc = t.UTC().Unix()
+ }
+ modi := (int64(rr.Inception) - utc) / year68
+ mode := (int64(rr.Expiration) - utc) / year68
+ ti := int64(rr.Inception) + (modi * year68)
+ te := int64(rr.Expiration) + (mode * year68)
+ return ti <= utc && utc <= te
+}
+
+// Return the signatures base64 encodedig sigdata as a byte slice.
+func (rr *RRSIG) sigBuf() []byte {
+ sigbuf, err := fromBase64([]byte(rr.Signature))
+ if err != nil {
+ return nil
+ }
+ return sigbuf
+}
+
+// publicKeyRSA returns the RSA public key from a DNSKEY record.
+func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
+ keybuf, err := fromBase64([]byte(k.PublicKey))
+ if err != nil {
+ return nil
+ }
+
+ // RFC 2537/3110, section 2. RSA Public KEY Resource Records
+ // Length is in the 0th byte, unless its zero, then it
+ // it in bytes 1 and 2 and its a 16 bit number
+ explen := uint16(keybuf[0])
+ keyoff := 1
+ if explen == 0 {
+ explen = uint16(keybuf[1])<<8 | uint16(keybuf[2])
+ keyoff = 3
+ }
+ pubkey := new(rsa.PublicKey)
+
+ pubkey.N = big.NewInt(0)
+ shift := uint64((explen - 1) * 8)
+ expo := uint64(0)
+ for i := int(explen - 1); i > 0; i-- {
+ expo += uint64(keybuf[keyoff+i]) << shift
+ shift -= 8
+ }
+ // Remainder
+ expo += uint64(keybuf[keyoff])
+ if expo > (2<<31)+1 {
+ // Larger expo than supported.
+ // println("dns: F5 primes (or larger) are not supported")
+ return nil
+ }
+ pubkey.E = int(expo)
+
+ pubkey.N.SetBytes(keybuf[keyoff+int(explen):])
+ return pubkey
+}
+
+// publicKeyECDSA returns the Curve public key from the DNSKEY record.
+func (k *DNSKEY) publicKeyECDSA() *ecdsa.PublicKey {
+ keybuf, err := fromBase64([]byte(k.PublicKey))
+ if err != nil {
+ return nil
+ }
+ pubkey := new(ecdsa.PublicKey)
+ switch k.Algorithm {
+ case ECDSAP256SHA256:
+ pubkey.Curve = elliptic.P256()
+ if len(keybuf) != 64 {
+ // wrongly encoded key
+ return nil
+ }
+ case ECDSAP384SHA384:
+ pubkey.Curve = elliptic.P384()
+ if len(keybuf) != 96 {
+ // Wrongly encoded key
+ return nil
+ }
+ }
+ pubkey.X = big.NewInt(0)
+ pubkey.X.SetBytes(keybuf[:len(keybuf)/2])
+ pubkey.Y = big.NewInt(0)
+ pubkey.Y.SetBytes(keybuf[len(keybuf)/2:])
+ return pubkey
+}
+
+func (k *DNSKEY) publicKeyDSA() *dsa.PublicKey {
+ keybuf, err := fromBase64([]byte(k.PublicKey))
+ if err != nil {
+ return nil
+ }
+ if len(keybuf) < 22 {
+ return nil
+ }
+ t, keybuf := int(keybuf[0]), keybuf[1:]
+ size := 64 + t*8
+ q, keybuf := keybuf[:20], keybuf[20:]
+ if len(keybuf) != 3*size {
+ return nil
+ }
+ p, keybuf := keybuf[:size], keybuf[size:]
+ g, y := keybuf[:size], keybuf[size:]
+ pubkey := new(dsa.PublicKey)
+ pubkey.Parameters.Q = big.NewInt(0).SetBytes(q)
+ pubkey.Parameters.P = big.NewInt(0).SetBytes(p)
+ pubkey.Parameters.G = big.NewInt(0).SetBytes(g)
+ pubkey.Y = big.NewInt(0).SetBytes(y)
+ return pubkey
+}
+
+type wireSlice [][]byte
+
+func (p wireSlice) Len() int { return len(p) }
+func (p wireSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+func (p wireSlice) Less(i, j int) bool {
+ _, ioff, _ := UnpackDomainName(p[i], 0)
+ _, joff, _ := UnpackDomainName(p[j], 0)
+ return bytes.Compare(p[i][ioff+10:], p[j][joff+10:]) < 0
+}
+
+// Return the raw signature data.
+func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
+ wires := make(wireSlice, len(rrset))
+ for i, r := range rrset {
+ r1 := r.copy()
+ r1.Header().Ttl = s.OrigTtl
+ labels := SplitDomainName(r1.Header().Name)
+ // 6.2. Canonical RR Form. (4) - wildcards
+ if len(labels) > int(s.Labels) {
+ // Wildcard
+ r1.Header().Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "."
+ }
+ // RFC 4034: 6.2. Canonical RR Form. (2) - domain name to lowercase
+ r1.Header().Name = strings.ToLower(r1.Header().Name)
+ // 6.2. Canonical RR Form. (3) - domain rdata to lowercase.
+ // NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
+ // HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
+ // SRV, DNAME, A6
+ //
+ // RFC 6840 - Clarifications and Implementation Notes for DNS Security (DNSSEC):
+ // Section 6.2 of [RFC4034] also erroneously lists HINFO as a record
+ // that needs conversion to lowercase, and twice at that. Since HINFO
+ // records contain no domain names, they are not subject to case
+ // conversion.
+ switch x := r1.(type) {
+ case *NS:
+ x.Ns = strings.ToLower(x.Ns)
+ case *CNAME:
+ x.Target = strings.ToLower(x.Target)
+ case *SOA:
+ x.Ns = strings.ToLower(x.Ns)
+ x.Mbox = strings.ToLower(x.Mbox)
+ case *MB:
+ x.Mb = strings.ToLower(x.Mb)
+ case *MG:
+ x.Mg = strings.ToLower(x.Mg)
+ case *MR:
+ x.Mr = strings.ToLower(x.Mr)
+ case *PTR:
+ x.Ptr = strings.ToLower(x.Ptr)
+ case *MINFO:
+ x.Rmail = strings.ToLower(x.Rmail)
+ x.Email = strings.ToLower(x.Email)
+ case *MX:
+ x.Mx = strings.ToLower(x.Mx)
+ case *NAPTR:
+ x.Replacement = strings.ToLower(x.Replacement)
+ case *KX:
+ x.Exchanger = strings.ToLower(x.Exchanger)
+ case *SRV:
+ x.Target = strings.ToLower(x.Target)
+ case *DNAME:
+ x.Target = strings.ToLower(x.Target)
+ }
+ // 6.2. Canonical RR Form. (5) - origTTL
+ wire := make([]byte, r1.len()+1) // +1 to be safe(r)
+ off, err1 := PackRR(r1, wire, 0, nil, false)
+ if err1 != nil {
+ return nil, err1
+ }
+ wire = wire[:off]
+ wires[i] = wire
+ }
+ sort.Sort(wires)
+ for i, wire := range wires {
+ if i > 0 && bytes.Equal(wire, wires[i-1]) {
+ continue
+ }
+ buf = append(buf, wire...)
+ }
+ return buf, nil
+}
+
+func packSigWire(sw *rrsigWireFmt, msg []byte) (int, error) {
+ // copied from zmsg.go RRSIG packing
+ off, err := packUint16(sw.TypeCovered, msg, 0)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(sw.Algorithm, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(sw.Labels, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(sw.OrigTtl, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(sw.Expiration, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(sw.Inception, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(sw.KeyTag, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = PackDomainName(sw.SignerName, msg, off, nil, false)
+ if err != nil {
+ return off, err
+ }
+ return off, nil
+}
+
+func packKeyWire(dw *dnskeyWireFmt, msg []byte) (int, error) {
+ // copied from zmsg.go DNSKEY packing
+ off, err := packUint16(dw.Flags, msg, 0)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(dw.Protocol, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(dw.Algorithm, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringBase64(dw.PublicKey, msg, off)
+ if err != nil {
+ return off, err
+ }
+ return off, nil
+}
--- /dev/null
+package dns
+
+import (
+ "crypto"
+ "crypto/dsa"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/rsa"
+ "math/big"
+)
+
+// Generate generates a DNSKEY of the given bit size.
+// The public part is put inside the DNSKEY record.
+// The Algorithm in the key must be set as this will define
+// what kind of DNSKEY will be generated.
+// The ECDSA algorithms imply a fixed keysize, in that case
+// bits should be set to the size of the algorithm.
+func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
+ switch k.Algorithm {
+ case DSA, DSANSEC3SHA1:
+ if bits != 1024 {
+ return nil, ErrKeySize
+ }
+ case RSAMD5, RSASHA1, RSASHA256, RSASHA1NSEC3SHA1:
+ if bits < 512 || bits > 4096 {
+ return nil, ErrKeySize
+ }
+ case RSASHA512:
+ if bits < 1024 || bits > 4096 {
+ return nil, ErrKeySize
+ }
+ case ECDSAP256SHA256:
+ if bits != 256 {
+ return nil, ErrKeySize
+ }
+ case ECDSAP384SHA384:
+ if bits != 384 {
+ return nil, ErrKeySize
+ }
+ }
+
+ switch k.Algorithm {
+ case DSA, DSANSEC3SHA1:
+ params := new(dsa.Parameters)
+ if err := dsa.GenerateParameters(params, rand.Reader, dsa.L1024N160); err != nil {
+ return nil, err
+ }
+ priv := new(dsa.PrivateKey)
+ priv.PublicKey.Parameters = *params
+ err := dsa.GenerateKey(priv, rand.Reader)
+ if err != nil {
+ return nil, err
+ }
+ k.setPublicKeyDSA(params.Q, params.P, params.G, priv.PublicKey.Y)
+ return priv, nil
+ case RSAMD5, RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1:
+ priv, err := rsa.GenerateKey(rand.Reader, bits)
+ if err != nil {
+ return nil, err
+ }
+ k.setPublicKeyRSA(priv.PublicKey.E, priv.PublicKey.N)
+ return priv, nil
+ case ECDSAP256SHA256, ECDSAP384SHA384:
+ var c elliptic.Curve
+ switch k.Algorithm {
+ case ECDSAP256SHA256:
+ c = elliptic.P256()
+ case ECDSAP384SHA384:
+ c = elliptic.P384()
+ }
+ priv, err := ecdsa.GenerateKey(c, rand.Reader)
+ if err != nil {
+ return nil, err
+ }
+ k.setPublicKeyECDSA(priv.PublicKey.X, priv.PublicKey.Y)
+ return priv, nil
+ default:
+ return nil, ErrAlg
+ }
+}
+
+// Set the public key (the value E and N)
+func (k *DNSKEY) setPublicKeyRSA(_E int, _N *big.Int) bool {
+ if _E == 0 || _N == nil {
+ return false
+ }
+ buf := exponentToBuf(_E)
+ buf = append(buf, _N.Bytes()...)
+ k.PublicKey = toBase64(buf)
+ return true
+}
+
+// Set the public key for Elliptic Curves
+func (k *DNSKEY) setPublicKeyECDSA(_X, _Y *big.Int) bool {
+ if _X == nil || _Y == nil {
+ return false
+ }
+ var intlen int
+ switch k.Algorithm {
+ case ECDSAP256SHA256:
+ intlen = 32
+ case ECDSAP384SHA384:
+ intlen = 48
+ }
+ k.PublicKey = toBase64(curveToBuf(_X, _Y, intlen))
+ return true
+}
+
+// Set the public key for DSA
+func (k *DNSKEY) setPublicKeyDSA(_Q, _P, _G, _Y *big.Int) bool {
+ if _Q == nil || _P == nil || _G == nil || _Y == nil {
+ return false
+ }
+ buf := dsaToBuf(_Q, _P, _G, _Y)
+ k.PublicKey = toBase64(buf)
+ return true
+}
+
+// Set the public key (the values E and N) for RSA
+// RFC 3110: Section 2. RSA Public KEY Resource Records
+func exponentToBuf(_E int) []byte {
+ var buf []byte
+ i := big.NewInt(int64(_E)).Bytes()
+ if len(i) < 256 {
+ buf = make([]byte, 1, 1+len(i))
+ buf[0] = uint8(len(i))
+ } else {
+ buf = make([]byte, 3, 3+len(i))
+ buf[0] = 0
+ buf[1] = uint8(len(i) >> 8)
+ buf[2] = uint8(len(i))
+ }
+ buf = append(buf, i...)
+ return buf
+}
+
+// Set the public key for X and Y for Curve. The two
+// values are just concatenated.
+func curveToBuf(_X, _Y *big.Int, intlen int) []byte {
+ buf := intToBytes(_X, intlen)
+ buf = append(buf, intToBytes(_Y, intlen)...)
+ return buf
+}
+
+// Set the public key for X and Y for Curve. The two
+// values are just concatenated.
+func dsaToBuf(_Q, _P, _G, _Y *big.Int) []byte {
+ t := divRoundUp(divRoundUp(_G.BitLen(), 8)-64, 8)
+ buf := []byte{byte(t)}
+ buf = append(buf, intToBytes(_Q, 20)...)
+ buf = append(buf, intToBytes(_P, 64+t*8)...)
+ buf = append(buf, intToBytes(_G, 64+t*8)...)
+ buf = append(buf, intToBytes(_Y, 64+t*8)...)
+ return buf
+}
--- /dev/null
+package dns
+
+import (
+ "crypto"
+ "crypto/dsa"
+ "crypto/ecdsa"
+ "crypto/rsa"
+ "io"
+ "math/big"
+ "strconv"
+ "strings"
+)
+
+// NewPrivateKey returns a PrivateKey by parsing the string s.
+// s should be in the same form of the BIND private key files.
+func (k *DNSKEY) NewPrivateKey(s string) (crypto.PrivateKey, error) {
+ if s == "" || s[len(s)-1] != '\n' { // We need a closing newline
+ return k.ReadPrivateKey(strings.NewReader(s+"\n"), "")
+ }
+ return k.ReadPrivateKey(strings.NewReader(s), "")
+}
+
+// ReadPrivateKey reads a private key from the io.Reader q. The string file is
+// only used in error reporting.
+// The public key must be known, because some cryptographic algorithms embed
+// the public inside the privatekey.
+func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, error) {
+ m, err := parseKey(q, file)
+ if m == nil {
+ return nil, err
+ }
+ if _, ok := m["private-key-format"]; !ok {
+ return nil, ErrPrivKey
+ }
+ if m["private-key-format"] != "v1.2" && m["private-key-format"] != "v1.3" {
+ return nil, ErrPrivKey
+ }
+ // TODO(mg): check if the pubkey matches the private key
+ algo, err := strconv.ParseUint(strings.SplitN(m["algorithm"], " ", 2)[0], 10, 8)
+ if err != nil {
+ return nil, ErrPrivKey
+ }
+ switch uint8(algo) {
+ case DSA:
+ priv, err := readPrivateKeyDSA(m)
+ if err != nil {
+ return nil, err
+ }
+ pub := k.publicKeyDSA()
+ if pub == nil {
+ return nil, ErrKey
+ }
+ priv.PublicKey = *pub
+ return priv, nil
+ case RSAMD5:
+ fallthrough
+ case RSASHA1:
+ fallthrough
+ case RSASHA1NSEC3SHA1:
+ fallthrough
+ case RSASHA256:
+ fallthrough
+ case RSASHA512:
+ priv, err := readPrivateKeyRSA(m)
+ if err != nil {
+ return nil, err
+ }
+ pub := k.publicKeyRSA()
+ if pub == nil {
+ return nil, ErrKey
+ }
+ priv.PublicKey = *pub
+ return priv, nil
+ case ECCGOST:
+ return nil, ErrPrivKey
+ case ECDSAP256SHA256:
+ fallthrough
+ case ECDSAP384SHA384:
+ priv, err := readPrivateKeyECDSA(m)
+ if err != nil {
+ return nil, err
+ }
+ pub := k.publicKeyECDSA()
+ if pub == nil {
+ return nil, ErrKey
+ }
+ priv.PublicKey = *pub
+ return priv, nil
+ default:
+ return nil, ErrPrivKey
+ }
+}
+
+// Read a private key (file) string and create a public key. Return the private key.
+func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
+ p := new(rsa.PrivateKey)
+ p.Primes = []*big.Int{nil, nil}
+ for k, v := range m {
+ switch k {
+ case "modulus", "publicexponent", "privateexponent", "prime1", "prime2":
+ v1, err := fromBase64([]byte(v))
+ if err != nil {
+ return nil, err
+ }
+ switch k {
+ case "modulus":
+ p.PublicKey.N = big.NewInt(0)
+ p.PublicKey.N.SetBytes(v1)
+ case "publicexponent":
+ i := big.NewInt(0)
+ i.SetBytes(v1)
+ p.PublicKey.E = int(i.Int64()) // int64 should be large enough
+ case "privateexponent":
+ p.D = big.NewInt(0)
+ p.D.SetBytes(v1)
+ case "prime1":
+ p.Primes[0] = big.NewInt(0)
+ p.Primes[0].SetBytes(v1)
+ case "prime2":
+ p.Primes[1] = big.NewInt(0)
+ p.Primes[1].SetBytes(v1)
+ }
+ case "exponent1", "exponent2", "coefficient":
+ // not used in Go (yet)
+ case "created", "publish", "activate":
+ // not used in Go (yet)
+ }
+ }
+ return p, nil
+}
+
+func readPrivateKeyDSA(m map[string]string) (*dsa.PrivateKey, error) {
+ p := new(dsa.PrivateKey)
+ p.X = big.NewInt(0)
+ for k, v := range m {
+ switch k {
+ case "private_value(x)":
+ v1, err := fromBase64([]byte(v))
+ if err != nil {
+ return nil, err
+ }
+ p.X.SetBytes(v1)
+ case "created", "publish", "activate":
+ /* not used in Go (yet) */
+ }
+ }
+ return p, nil
+}
+
+func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) {
+ p := new(ecdsa.PrivateKey)
+ p.D = big.NewInt(0)
+ // TODO: validate that the required flags are present
+ for k, v := range m {
+ switch k {
+ case "privatekey":
+ v1, err := fromBase64([]byte(v))
+ if err != nil {
+ return nil, err
+ }
+ p.D.SetBytes(v1)
+ case "created", "publish", "activate":
+ /* not used in Go (yet) */
+ }
+ }
+ return p, nil
+}
+
+// parseKey reads a private key from r. It returns a map[string]string,
+// with the key-value pairs, or an error when the file is not correct.
+func parseKey(r io.Reader, file string) (map[string]string, error) {
+ s := scanInit(r)
+ m := make(map[string]string)
+ c := make(chan lex)
+ k := ""
+ // Start the lexer
+ go klexer(s, c)
+ for l := range c {
+ // It should alternate
+ switch l.value {
+ case zKey:
+ k = l.token
+ case zValue:
+ if k == "" {
+ return nil, &ParseError{file, "no private key seen", l}
+ }
+ //println("Setting", strings.ToLower(k), "to", l.token, "b")
+ m[strings.ToLower(k)] = l.token
+ k = ""
+ }
+ }
+ return m, nil
+}
+
+// klexer scans the sourcefile and returns tokens on the channel c.
+func klexer(s *scan, c chan lex) {
+ var l lex
+ str := "" // Hold the current read text
+ commt := false
+ key := true
+ x, err := s.tokenText()
+ defer close(c)
+ for err == nil {
+ l.column = s.position.Column
+ l.line = s.position.Line
+ switch x {
+ case ':':
+ if commt {
+ break
+ }
+ l.token = str
+ if key {
+ l.value = zKey
+ c <- l
+ // Next token is a space, eat it
+ s.tokenText()
+ key = false
+ str = ""
+ } else {
+ l.value = zValue
+ }
+ case ';':
+ commt = true
+ case '\n':
+ if commt {
+ // Reset a comment
+ commt = false
+ }
+ l.value = zValue
+ l.token = str
+ c <- l
+ str = ""
+ commt = false
+ key = true
+ default:
+ if commt {
+ break
+ }
+ str += string(x)
+ }
+ x, err = s.tokenText()
+ }
+ if len(str) > 0 {
+ // Send remainder
+ l.token = str
+ l.value = zValue
+ c <- l
+ }
+}
--- /dev/null
+package dns
+
+import (
+ "crypto"
+ "crypto/dsa"
+ "crypto/ecdsa"
+ "crypto/rsa"
+ "math/big"
+ "strconv"
+)
+
+const format = "Private-key-format: v1.3\n"
+
+// PrivateKeyString converts a PrivateKey to a string. This string has the same
+// format as the private-key-file of BIND9 (Private-key-format: v1.3).
+// It needs some info from the key (the algorithm), so its a method of the DNSKEY
+// It supports rsa.PrivateKey, ecdsa.PrivateKey and dsa.PrivateKey
+func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
+ algorithm := strconv.Itoa(int(r.Algorithm))
+ algorithm += " (" + AlgorithmToString[r.Algorithm] + ")"
+
+ switch p := p.(type) {
+ case *rsa.PrivateKey:
+ modulus := toBase64(p.PublicKey.N.Bytes())
+ e := big.NewInt(int64(p.PublicKey.E))
+ publicExponent := toBase64(e.Bytes())
+ privateExponent := toBase64(p.D.Bytes())
+ prime1 := toBase64(p.Primes[0].Bytes())
+ prime2 := toBase64(p.Primes[1].Bytes())
+ // Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm
+ // and from: http://code.google.com/p/go/issues/detail?id=987
+ one := big.NewInt(1)
+ p1 := big.NewInt(0).Sub(p.Primes[0], one)
+ q1 := big.NewInt(0).Sub(p.Primes[1], one)
+ exp1 := big.NewInt(0).Mod(p.D, p1)
+ exp2 := big.NewInt(0).Mod(p.D, q1)
+ coeff := big.NewInt(0).ModInverse(p.Primes[1], p.Primes[0])
+
+ exponent1 := toBase64(exp1.Bytes())
+ exponent2 := toBase64(exp2.Bytes())
+ coefficient := toBase64(coeff.Bytes())
+
+ return format +
+ "Algorithm: " + algorithm + "\n" +
+ "Modulus: " + modulus + "\n" +
+ "PublicExponent: " + publicExponent + "\n" +
+ "PrivateExponent: " + privateExponent + "\n" +
+ "Prime1: " + prime1 + "\n" +
+ "Prime2: " + prime2 + "\n" +
+ "Exponent1: " + exponent1 + "\n" +
+ "Exponent2: " + exponent2 + "\n" +
+ "Coefficient: " + coefficient + "\n"
+
+ case *ecdsa.PrivateKey:
+ var intlen int
+ switch r.Algorithm {
+ case ECDSAP256SHA256:
+ intlen = 32
+ case ECDSAP384SHA384:
+ intlen = 48
+ }
+ private := toBase64(intToBytes(p.D, intlen))
+ return format +
+ "Algorithm: " + algorithm + "\n" +
+ "PrivateKey: " + private + "\n"
+
+ case *dsa.PrivateKey:
+ T := divRoundUp(divRoundUp(p.PublicKey.Parameters.G.BitLen(), 8)-64, 8)
+ prime := toBase64(intToBytes(p.PublicKey.Parameters.P, 64+T*8))
+ subprime := toBase64(intToBytes(p.PublicKey.Parameters.Q, 20))
+ base := toBase64(intToBytes(p.PublicKey.Parameters.G, 64+T*8))
+ priv := toBase64(intToBytes(p.X, 20))
+ pub := toBase64(intToBytes(p.PublicKey.Y, 64+T*8))
+ return format +
+ "Algorithm: " + algorithm + "\n" +
+ "Prime(p): " + prime + "\n" +
+ "Subprime(q): " + subprime + "\n" +
+ "Base(g): " + base + "\n" +
+ "Private_value(x): " + priv + "\n" +
+ "Public_value(y): " + pub + "\n"
+
+ default:
+ return ""
+ }
+}
--- /dev/null
+/*
+Package dns implements a full featured interface to the Domain Name System.
+Server- and client-side programming is supported.
+The package allows complete control over what is sent out to the DNS. The package
+API follows the less-is-more principle, by presenting a small, clean interface.
+
+The package dns supports (asynchronous) querying/replying, incoming/outgoing zone transfers,
+TSIG, EDNS0, dynamic updates, notifies and DNSSEC validation/signing.
+Note that domain names MUST be fully qualified, before sending them, unqualified
+names in a message will result in a packing failure.
+
+Resource records are native types. They are not stored in wire format.
+Basic usage pattern for creating a new resource record:
+
+ r := new(dns.MX)
+ r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX,
+ Class: dns.ClassINET, Ttl: 3600}
+ r.Preference = 10
+ r.Mx = "mx.miek.nl."
+
+Or directly from a string:
+
+ mx, err := dns.NewRR("miek.nl. 3600 IN MX 10 mx.miek.nl.")
+
+Or when the default origin (.) and TTL (3600) and class (IN) suit you:
+
+ mx, err := dns.NewRR("miek.nl MX 10 mx.miek.nl")
+
+Or even:
+
+ mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek")
+
+In the DNS messages are exchanged, these messages contain resource
+records (sets). Use pattern for creating a message:
+
+ m := new(dns.Msg)
+ m.SetQuestion("miek.nl.", dns.TypeMX)
+
+Or when not certain if the domain name is fully qualified:
+
+ m.SetQuestion(dns.Fqdn("miek.nl"), dns.TypeMX)
+
+The message m is now a message with the question section set to ask
+the MX records for the miek.nl. zone.
+
+The following is slightly more verbose, but more flexible:
+
+ m1 := new(dns.Msg)
+ m1.Id = dns.Id()
+ m1.RecursionDesired = true
+ m1.Question = make([]dns.Question, 1)
+ m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET}
+
+After creating a message it can be sent.
+Basic use pattern for synchronous querying the DNS at a
+server configured on 127.0.0.1 and port 53:
+
+ c := new(dns.Client)
+ in, rtt, err := c.Exchange(m1, "127.0.0.1:53")
+
+Suppressing multiple outstanding queries (with the same question, type and
+class) is as easy as setting:
+
+ c.SingleInflight = true
+
+More advanced options are availabe using a net.Dialer and the corresponding API.
+For example it is possible to set a timeout, or to specify a source IP address
+and port to use for the connection:
+
+ c := new(dns.Client)
+ laddr := net.UDPAddr{
+ IP: net.ParseIP("[::1]"),
+ Port: 12345,
+ Zone: "",
+ }
+ d := net.Dialer{
+ Timeout: 200 * time.Millisecond,
+ LocalAddr: &laddr,
+ }
+ in, rtt, err := c.ExchangeWithDialer(&d, m1, "8.8.8.8:53")
+
+If these "advanced" features are not needed, a simple UDP query can be sent,
+with:
+
+ in, err := dns.Exchange(m1, "127.0.0.1:53")
+
+When this functions returns you will get dns message. A dns message consists
+out of four sections.
+The question section: in.Question, the answer section: in.Answer,
+the authority section: in.Ns and the additional section: in.Extra.
+
+Each of these sections (except the Question section) contain a []RR. Basic
+use pattern for accessing the rdata of a TXT RR as the first RR in
+the Answer section:
+
+ if t, ok := in.Answer[0].(*dns.TXT); ok {
+ // do something with t.Txt
+ }
+
+Domain Name and TXT Character String Representations
+
+Both domain names and TXT character strings are converted to presentation
+form both when unpacked and when converted to strings.
+
+For TXT character strings, tabs, carriage returns and line feeds will be
+converted to \t, \r and \n respectively. Back slashes and quotations marks
+will be escaped. Bytes below 32 and above 127 will be converted to \DDD
+form.
+
+For domain names, in addition to the above rules brackets, periods,
+spaces, semicolons and the at symbol are escaped.
+
+DNSSEC
+
+DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It
+uses public key cryptography to sign resource records. The
+public keys are stored in DNSKEY records and the signatures in RRSIG records.
+
+Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK) bit
+to a request.
+
+ m := new(dns.Msg)
+ m.SetEdns0(4096, true)
+
+Signature generation, signature verification and key generation are all supported.
+
+DYNAMIC UPDATES
+
+Dynamic updates reuses the DNS message format, but renames three of
+the sections. Question is Zone, Answer is Prerequisite, Authority is
+Update, only the Additional is not renamed. See RFC 2136 for the gory details.
+
+You can set a rather complex set of rules for the existence of absence of
+certain resource records or names in a zone to specify if resource records
+should be added or removed. The table from RFC 2136 supplemented with the Go
+DNS function shows which functions exist to specify the prerequisites.
+
+ 3.2.4 - Table Of Metavalues Used In Prerequisite Section
+
+ CLASS TYPE RDATA Meaning Function
+ --------------------------------------------------------------
+ ANY ANY empty Name is in use dns.NameUsed
+ ANY rrset empty RRset exists (value indep) dns.RRsetUsed
+ NONE ANY empty Name is not in use dns.NameNotUsed
+ NONE rrset empty RRset does not exist dns.RRsetNotUsed
+ zone rrset rr RRset exists (value dep) dns.Used
+
+The prerequisite section can also be left empty.
+If you have decided on the prerequisites you can tell what RRs should
+be added or deleted. The next table shows the options you have and
+what functions to call.
+
+ 3.4.2.6 - Table Of Metavalues Used In Update Section
+
+ CLASS TYPE RDATA Meaning Function
+ ---------------------------------------------------------------
+ ANY ANY empty Delete all RRsets from name dns.RemoveName
+ ANY rrset empty Delete an RRset dns.RemoveRRset
+ NONE rrset rr Delete an RR from RRset dns.Remove
+ zone rrset rr Add to an RRset dns.Insert
+
+TRANSACTION SIGNATURE
+
+An TSIG or transaction signature adds a HMAC TSIG record to each message sent.
+The supported algorithms include: HmacMD5, HmacSHA1, HmacSHA256 and HmacSHA512.
+
+Basic use pattern when querying with a TSIG name "axfr." (note that these key names
+must be fully qualified - as they are domain names) and the base64 secret
+"so6ZGir4GPAqINNh9U5c3A==":
+
+If an incoming message contains a TSIG record it MUST be the last record in
+the additional section (RFC2845 3.2). This means that you should make the
+call to SetTsig last, right before executing the query. If you make any
+changes to the RRset after calling SetTsig() the signature will be incorrect.
+
+ c := new(dns.Client)
+ c.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
+ m := new(dns.Msg)
+ m.SetQuestion("miek.nl.", dns.TypeMX)
+ m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
+ ...
+ // When sending the TSIG RR is calculated and filled in before sending
+
+When requesting an zone transfer (almost all TSIG usage is when requesting zone transfers), with
+TSIG, this is the basic use pattern. In this example we request an AXFR for
+miek.nl. with TSIG key named "axfr." and secret "so6ZGir4GPAqINNh9U5c3A=="
+and using the server 176.58.119.54:
+
+ t := new(dns.Transfer)
+ m := new(dns.Msg)
+ t.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
+ m.SetAxfr("miek.nl.")
+ m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
+ c, err := t.In(m, "176.58.119.54:53")
+ for r := range c { ... }
+
+You can now read the records from the transfer as they come in. Each envelope is checked with TSIG.
+If something is not correct an error is returned.
+
+Basic use pattern validating and replying to a message that has TSIG set.
+
+ server := &dns.Server{Addr: ":53", Net: "udp"}
+ server.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
+ go server.ListenAndServe()
+ dns.HandleFunc(".", handleRequest)
+
+ func handleRequest(w dns.ResponseWriter, r *dns.Msg) {
+ m := new(dns.Msg)
+ m.SetReply(r)
+ if r.IsTsig() != nil {
+ if w.TsigStatus() == nil {
+ // *Msg r has an TSIG record and it was validated
+ m.SetTsig("axfr.", dns.HmacMD5, 300, time.Now().Unix())
+ } else {
+ // *Msg r has an TSIG records and it was not valided
+ }
+ }
+ w.WriteMsg(m)
+ }
+
+PRIVATE RRS
+
+RFC 6895 sets aside a range of type codes for private use. This range
+is 65,280 - 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these
+can be used, before requesting an official type code from IANA.
+
+see http://miek.nl/2014/September/21/idn-and-private-rr-in-go-dns/ for more
+information.
+
+EDNS0
+
+EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated
+by RFC 6891. It defines an new RR type, the OPT RR, which is then completely
+abused.
+Basic use pattern for creating an (empty) OPT RR:
+
+ o := new(dns.OPT)
+ o.Hdr.Name = "." // MUST be the root zone, per definition.
+ o.Hdr.Rrtype = dns.TypeOPT
+
+The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891)
+interfaces. Currently only a few have been standardized: EDNS0_NSID
+(RFC 5001) and EDNS0_SUBNET (draft-vandergaast-edns-client-subnet-02). Note
+that these options may be combined in an OPT RR.
+Basic use pattern for a server to check if (and which) options are set:
+
+ // o is a dns.OPT
+ for _, s := range o.Option {
+ switch e := s.(type) {
+ case *dns.EDNS0_NSID:
+ // do stuff with e.Nsid
+ case *dns.EDNS0_SUBNET:
+ // access e.Family, e.Address, etc.
+ }
+ }
+
+SIG(0)
+
+From RFC 2931:
+
+ SIG(0) provides protection for DNS transactions and requests ....
+ ... protection for glue records, DNS requests, protection for message headers
+ on requests and responses, and protection of the overall integrity of a response.
+
+It works like TSIG, except that SIG(0) uses public key cryptography, instead of the shared
+secret approach in TSIG.
+Supported algorithms: DSA, ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256 and
+RSASHA512.
+
+Signing subsequent messages in multi-message sessions is not implemented.
+*/
+package dns
--- /dev/null
+package dns
+
+import (
+ "encoding/binary"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "net"
+ "strconv"
+)
+
+// EDNS0 Option codes.
+const (
+ EDNS0LLQ = 0x1 // long lived queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
+ EDNS0UL = 0x2 // update lease draft: http://files.dns-sd.org/draft-sekar-dns-ul.txt
+ EDNS0NSID = 0x3 // nsid (RFC5001)
+ EDNS0DAU = 0x5 // DNSSEC Algorithm Understood
+ EDNS0DHU = 0x6 // DS Hash Understood
+ EDNS0N3U = 0x7 // NSEC3 Hash Understood
+ EDNS0SUBNET = 0x8 // client-subnet (RFC6891)
+ EDNS0EXPIRE = 0x9 // EDNS0 expire
+ EDNS0COOKIE = 0xa // EDNS0 Cookie
+ EDNS0TCPKEEPALIVE = 0xb // EDNS0 tcp keep alive (RFC7828)
+ EDNS0PADDING = 0xc // EDNS0 padding (RFC7830)
+ EDNS0SUBNETDRAFT = 0x50fa // Don't use! Use EDNS0SUBNET
+ EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (RFC6891)
+ EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (RFC6891)
+ _DO = 1 << 15 // dnssec ok
+)
+
+// OPT is the EDNS0 RR appended to messages to convey extra (meta) information.
+// See RFC 6891.
+type OPT struct {
+ Hdr RR_Header
+ Option []EDNS0 `dns:"opt"`
+}
+
+func (rr *OPT) String() string {
+ s := "\n;; OPT PSEUDOSECTION:\n; EDNS: version " + strconv.Itoa(int(rr.Version())) + "; "
+ if rr.Do() {
+ s += "flags: do; "
+ } else {
+ s += "flags: ; "
+ }
+ s += "udp: " + strconv.Itoa(int(rr.UDPSize()))
+
+ for _, o := range rr.Option {
+ switch o.(type) {
+ case *EDNS0_NSID:
+ s += "\n; NSID: " + o.String()
+ h, e := o.pack()
+ var r string
+ if e == nil {
+ for _, c := range h {
+ r += "(" + string(c) + ")"
+ }
+ s += " " + r
+ }
+ case *EDNS0_SUBNET:
+ s += "\n; SUBNET: " + o.String()
+ if o.(*EDNS0_SUBNET).DraftOption {
+ s += " (draft)"
+ }
+ case *EDNS0_COOKIE:
+ s += "\n; COOKIE: " + o.String()
+ case *EDNS0_UL:
+ s += "\n; UPDATE LEASE: " + o.String()
+ case *EDNS0_LLQ:
+ s += "\n; LONG LIVED QUERIES: " + o.String()
+ case *EDNS0_DAU:
+ s += "\n; DNSSEC ALGORITHM UNDERSTOOD: " + o.String()
+ case *EDNS0_DHU:
+ s += "\n; DS HASH UNDERSTOOD: " + o.String()
+ case *EDNS0_N3U:
+ s += "\n; NSEC3 HASH UNDERSTOOD: " + o.String()
+ case *EDNS0_LOCAL:
+ s += "\n; LOCAL OPT: " + o.String()
+ case *EDNS0_PADDING:
+ s += "\n; PADDING: " + o.String()
+ }
+ }
+ return s
+}
+
+func (rr *OPT) len() int {
+ l := rr.Hdr.len()
+ for i := 0; i < len(rr.Option); i++ {
+ l += 4 // Account for 2-byte option code and 2-byte option length.
+ lo, _ := rr.Option[i].pack()
+ l += len(lo)
+ }
+ return l
+}
+
+// return the old value -> delete SetVersion?
+
+// Version returns the EDNS version used. Only zero is defined.
+func (rr *OPT) Version() uint8 {
+ return uint8((rr.Hdr.Ttl & 0x00FF0000) >> 16)
+}
+
+// SetVersion sets the version of EDNS. This is usually zero.
+func (rr *OPT) SetVersion(v uint8) {
+ rr.Hdr.Ttl = rr.Hdr.Ttl&0xFF00FFFF | (uint32(v) << 16)
+}
+
+// ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL).
+func (rr *OPT) ExtendedRcode() int {
+ return int((rr.Hdr.Ttl & 0xFF000000) >> 24)
+}
+
+// SetExtendedRcode sets the EDNS extended RCODE field.
+func (rr *OPT) SetExtendedRcode(v uint8) {
+ rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | (uint32(v) << 24)
+}
+
+// UDPSize returns the UDP buffer size.
+func (rr *OPT) UDPSize() uint16 {
+ return rr.Hdr.Class
+}
+
+// SetUDPSize sets the UDP buffer size.
+func (rr *OPT) SetUDPSize(size uint16) {
+ rr.Hdr.Class = size
+}
+
+// Do returns the value of the DO (DNSSEC OK) bit.
+func (rr *OPT) Do() bool {
+ return rr.Hdr.Ttl&_DO == _DO
+}
+
+// SetDo sets the DO (DNSSEC OK) bit.
+// If we pass an argument, set the DO bit to that value.
+// It is possible to pass 2 or more arguments. Any arguments after the 1st is silently ignored.
+func (rr *OPT) SetDo(do ...bool) {
+ if len(do) == 1 {
+ if do[0] {
+ rr.Hdr.Ttl |= _DO
+ } else {
+ rr.Hdr.Ttl &^= _DO
+ }
+ } else {
+ rr.Hdr.Ttl |= _DO
+ }
+}
+
+// EDNS0 defines an EDNS0 Option. An OPT RR can have multiple options appended to it.
+type EDNS0 interface {
+ // Option returns the option code for the option.
+ Option() uint16
+ // pack returns the bytes of the option data.
+ pack() ([]byte, error)
+ // unpack sets the data as found in the buffer. Is also sets
+ // the length of the slice as the length of the option data.
+ unpack([]byte) error
+ // String returns the string representation of the option.
+ String() string
+}
+
+// EDNS0_NSID option is used to retrieve a nameserver
+// identifier. When sending a request Nsid must be set to the empty string
+// The identifier is an opaque string encoded as hex.
+// Basic use pattern for creating an nsid option:
+//
+// o := new(dns.OPT)
+// o.Hdr.Name = "."
+// o.Hdr.Rrtype = dns.TypeOPT
+// e := new(dns.EDNS0_NSID)
+// e.Code = dns.EDNS0NSID
+// e.Nsid = "AA"
+// o.Option = append(o.Option, e)
+type EDNS0_NSID struct {
+ Code uint16 // Always EDNS0NSID
+ Nsid string // This string needs to be hex encoded
+}
+
+func (e *EDNS0_NSID) pack() ([]byte, error) {
+ h, err := hex.DecodeString(e.Nsid)
+ if err != nil {
+ return nil, err
+ }
+ return h, nil
+}
+
+// Option implements the EDNS0 interface.
+func (e *EDNS0_NSID) Option() uint16 { return EDNS0NSID } // Option returns the option code.
+func (e *EDNS0_NSID) unpack(b []byte) error { e.Nsid = hex.EncodeToString(b); return nil }
+func (e *EDNS0_NSID) String() string { return string(e.Nsid) }
+
+// EDNS0_SUBNET is the subnet option that is used to give the remote nameserver
+// an idea of where the client lives. It can then give back a different
+// answer depending on the location or network topology.
+// Basic use pattern for creating an subnet option:
+//
+// o := new(dns.OPT)
+// o.Hdr.Name = "."
+// o.Hdr.Rrtype = dns.TypeOPT
+// e := new(dns.EDNS0_SUBNET)
+// e.Code = dns.EDNS0SUBNET
+// e.Family = 1 // 1 for IPv4 source address, 2 for IPv6
+// e.SourceNetmask = 32 // 32 for IPV4, 128 for IPv6
+// e.SourceScope = 0
+// e.Address = net.ParseIP("127.0.0.1").To4() // for IPv4
+// // e.Address = net.ParseIP("2001:7b8:32a::2") // for IPV6
+// o.Option = append(o.Option, e)
+//
+// Note: the spec (draft-ietf-dnsop-edns-client-subnet-00) has some insane logic
+// for which netmask applies to the address. This code will parse all the
+// available bits when unpacking (up to optlen). When packing it will apply
+// SourceNetmask. If you need more advanced logic, patches welcome and good luck.
+type EDNS0_SUBNET struct {
+ Code uint16 // Always EDNS0SUBNET
+ Family uint16 // 1 for IP, 2 for IP6
+ SourceNetmask uint8
+ SourceScope uint8
+ Address net.IP
+ DraftOption bool // Set to true if using the old (0x50fa) option code
+}
+
+// Option implements the EDNS0 interface.
+func (e *EDNS0_SUBNET) Option() uint16 {
+ if e.DraftOption {
+ return EDNS0SUBNETDRAFT
+ }
+ return EDNS0SUBNET
+}
+
+func (e *EDNS0_SUBNET) pack() ([]byte, error) {
+ b := make([]byte, 4)
+ binary.BigEndian.PutUint16(b[0:], e.Family)
+ b[2] = e.SourceNetmask
+ b[3] = e.SourceScope
+ switch e.Family {
+ case 0:
+ // "dig" sets AddressFamily to 0 if SourceNetmask is also 0
+ // We might don't need to complain either
+ if e.SourceNetmask != 0 {
+ return nil, errors.New("dns: bad address family")
+ }
+ case 1:
+ if e.SourceNetmask > net.IPv4len*8 {
+ return nil, errors.New("dns: bad netmask")
+ }
+ if len(e.Address.To4()) != net.IPv4len {
+ return nil, errors.New("dns: bad address")
+ }
+ ip := e.Address.To4().Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv4len*8))
+ needLength := (e.SourceNetmask + 8 - 1) / 8 // division rounding up
+ b = append(b, ip[:needLength]...)
+ case 2:
+ if e.SourceNetmask > net.IPv6len*8 {
+ return nil, errors.New("dns: bad netmask")
+ }
+ if len(e.Address) != net.IPv6len {
+ return nil, errors.New("dns: bad address")
+ }
+ ip := e.Address.Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv6len*8))
+ needLength := (e.SourceNetmask + 8 - 1) / 8 // division rounding up
+ b = append(b, ip[:needLength]...)
+ default:
+ return nil, errors.New("dns: bad address family")
+ }
+ return b, nil
+}
+
+func (e *EDNS0_SUBNET) unpack(b []byte) error {
+ if len(b) < 4 {
+ return ErrBuf
+ }
+ e.Family = binary.BigEndian.Uint16(b)
+ e.SourceNetmask = b[2]
+ e.SourceScope = b[3]
+ switch e.Family {
+ case 0:
+ // "dig" sets AddressFamily to 0 if SourceNetmask is also 0
+ // It's okay to accept such a packet
+ if e.SourceNetmask != 0 {
+ return errors.New("dns: bad address family")
+ }
+ e.Address = net.IPv4(0, 0, 0, 0)
+ case 1:
+ if e.SourceNetmask > net.IPv4len*8 || e.SourceScope > net.IPv4len*8 {
+ return errors.New("dns: bad netmask")
+ }
+ addr := make([]byte, net.IPv4len)
+ for i := 0; i < net.IPv4len && 4+i < len(b); i++ {
+ addr[i] = b[4+i]
+ }
+ e.Address = net.IPv4(addr[0], addr[1], addr[2], addr[3])
+ case 2:
+ if e.SourceNetmask > net.IPv6len*8 || e.SourceScope > net.IPv6len*8 {
+ return errors.New("dns: bad netmask")
+ }
+ addr := make([]byte, net.IPv6len)
+ for i := 0; i < net.IPv6len && 4+i < len(b); i++ {
+ addr[i] = b[4+i]
+ }
+ e.Address = net.IP{addr[0], addr[1], addr[2], addr[3], addr[4],
+ addr[5], addr[6], addr[7], addr[8], addr[9], addr[10],
+ addr[11], addr[12], addr[13], addr[14], addr[15]}
+ default:
+ return errors.New("dns: bad address family")
+ }
+ return nil
+}
+
+func (e *EDNS0_SUBNET) String() (s string) {
+ if e.Address == nil {
+ s = "<nil>"
+ } else if e.Address.To4() != nil {
+ s = e.Address.String()
+ } else {
+ s = "[" + e.Address.String() + "]"
+ }
+ s += "/" + strconv.Itoa(int(e.SourceNetmask)) + "/" + strconv.Itoa(int(e.SourceScope))
+ return
+}
+
+// The EDNS0_COOKIE option is used to add a DNS Cookie to a message.
+//
+// o := new(dns.OPT)
+// o.Hdr.Name = "."
+// o.Hdr.Rrtype = dns.TypeOPT
+// e := new(dns.EDNS0_COOKIE)
+// e.Code = dns.EDNS0COOKIE
+// e.Cookie = "24a5ac.."
+// o.Option = append(o.Option, e)
+//
+// The Cookie field consists out of a client cookie (RFC 7873 Section 4), that is
+// always 8 bytes. It may then optionally be followed by the server cookie. The server
+// cookie is of variable length, 8 to a maximum of 32 bytes. In other words:
+//
+// cCookie := o.Cookie[:16]
+// sCookie := o.Cookie[16:]
+//
+// There is no guarantee that the Cookie string has a specific length.
+type EDNS0_COOKIE struct {
+ Code uint16 // Always EDNS0COOKIE
+ Cookie string // Hex-encoded cookie data
+}
+
+func (e *EDNS0_COOKIE) pack() ([]byte, error) {
+ h, err := hex.DecodeString(e.Cookie)
+ if err != nil {
+ return nil, err
+ }
+ return h, nil
+}
+
+// Option implements the EDNS0 interface.
+func (e *EDNS0_COOKIE) Option() uint16 { return EDNS0COOKIE }
+func (e *EDNS0_COOKIE) unpack(b []byte) error { e.Cookie = hex.EncodeToString(b); return nil }
+func (e *EDNS0_COOKIE) String() string { return e.Cookie }
+
+// The EDNS0_UL (Update Lease) (draft RFC) option is used to tell the server to set
+// an expiration on an update RR. This is helpful for clients that cannot clean
+// up after themselves. This is a draft RFC and more information can be found at
+// http://files.dns-sd.org/draft-sekar-dns-ul.txt
+//
+// o := new(dns.OPT)
+// o.Hdr.Name = "."
+// o.Hdr.Rrtype = dns.TypeOPT
+// e := new(dns.EDNS0_UL)
+// e.Code = dns.EDNS0UL
+// e.Lease = 120 // in seconds
+// o.Option = append(o.Option, e)
+type EDNS0_UL struct {
+ Code uint16 // Always EDNS0UL
+ Lease uint32
+}
+
+// Option implements the EDNS0 interface.
+func (e *EDNS0_UL) Option() uint16 { return EDNS0UL }
+func (e *EDNS0_UL) String() string { return strconv.FormatUint(uint64(e.Lease), 10) }
+
+// Copied: http://golang.org/src/pkg/net/dnsmsg.go
+func (e *EDNS0_UL) pack() ([]byte, error) {
+ b := make([]byte, 4)
+ binary.BigEndian.PutUint32(b, e.Lease)
+ return b, nil
+}
+
+func (e *EDNS0_UL) unpack(b []byte) error {
+ if len(b) < 4 {
+ return ErrBuf
+ }
+ e.Lease = binary.BigEndian.Uint32(b)
+ return nil
+}
+
+// EDNS0_LLQ stands for Long Lived Queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
+// Implemented for completeness, as the EDNS0 type code is assigned.
+type EDNS0_LLQ struct {
+ Code uint16 // Always EDNS0LLQ
+ Version uint16
+ Opcode uint16
+ Error uint16
+ Id uint64
+ LeaseLife uint32
+}
+
+// Option implements the EDNS0 interface.
+func (e *EDNS0_LLQ) Option() uint16 { return EDNS0LLQ }
+
+func (e *EDNS0_LLQ) pack() ([]byte, error) {
+ b := make([]byte, 18)
+ binary.BigEndian.PutUint16(b[0:], e.Version)
+ binary.BigEndian.PutUint16(b[2:], e.Opcode)
+ binary.BigEndian.PutUint16(b[4:], e.Error)
+ binary.BigEndian.PutUint64(b[6:], e.Id)
+ binary.BigEndian.PutUint32(b[14:], e.LeaseLife)
+ return b, nil
+}
+
+func (e *EDNS0_LLQ) unpack(b []byte) error {
+ if len(b) < 18 {
+ return ErrBuf
+ }
+ e.Version = binary.BigEndian.Uint16(b[0:])
+ e.Opcode = binary.BigEndian.Uint16(b[2:])
+ e.Error = binary.BigEndian.Uint16(b[4:])
+ e.Id = binary.BigEndian.Uint64(b[6:])
+ e.LeaseLife = binary.BigEndian.Uint32(b[14:])
+ return nil
+}
+
+func (e *EDNS0_LLQ) String() string {
+ s := strconv.FormatUint(uint64(e.Version), 10) + " " + strconv.FormatUint(uint64(e.Opcode), 10) +
+ " " + strconv.FormatUint(uint64(e.Error), 10) + " " + strconv.FormatUint(uint64(e.Id), 10) +
+ " " + strconv.FormatUint(uint64(e.LeaseLife), 10)
+ return s
+}
+
+type EDNS0_DAU struct {
+ Code uint16 // Always EDNS0DAU
+ AlgCode []uint8
+}
+
+// Option implements the EDNS0 interface.
+func (e *EDNS0_DAU) Option() uint16 { return EDNS0DAU }
+func (e *EDNS0_DAU) pack() ([]byte, error) { return e.AlgCode, nil }
+func (e *EDNS0_DAU) unpack(b []byte) error { e.AlgCode = b; return nil }
+
+func (e *EDNS0_DAU) String() string {
+ s := ""
+ for i := 0; i < len(e.AlgCode); i++ {
+ if a, ok := AlgorithmToString[e.AlgCode[i]]; ok {
+ s += " " + a
+ } else {
+ s += " " + strconv.Itoa(int(e.AlgCode[i]))
+ }
+ }
+ return s
+}
+
+type EDNS0_DHU struct {
+ Code uint16 // Always EDNS0DHU
+ AlgCode []uint8
+}
+
+// Option implements the EDNS0 interface.
+func (e *EDNS0_DHU) Option() uint16 { return EDNS0DHU }
+func (e *EDNS0_DHU) pack() ([]byte, error) { return e.AlgCode, nil }
+func (e *EDNS0_DHU) unpack(b []byte) error { e.AlgCode = b; return nil }
+
+func (e *EDNS0_DHU) String() string {
+ s := ""
+ for i := 0; i < len(e.AlgCode); i++ {
+ if a, ok := HashToString[e.AlgCode[i]]; ok {
+ s += " " + a
+ } else {
+ s += " " + strconv.Itoa(int(e.AlgCode[i]))
+ }
+ }
+ return s
+}
+
+type EDNS0_N3U struct {
+ Code uint16 // Always EDNS0N3U
+ AlgCode []uint8
+}
+
+// Option implements the EDNS0 interface.
+func (e *EDNS0_N3U) Option() uint16 { return EDNS0N3U }
+func (e *EDNS0_N3U) pack() ([]byte, error) { return e.AlgCode, nil }
+func (e *EDNS0_N3U) unpack(b []byte) error { e.AlgCode = b; return nil }
+
+func (e *EDNS0_N3U) String() string {
+ // Re-use the hash map
+ s := ""
+ for i := 0; i < len(e.AlgCode); i++ {
+ if a, ok := HashToString[e.AlgCode[i]]; ok {
+ s += " " + a
+ } else {
+ s += " " + strconv.Itoa(int(e.AlgCode[i]))
+ }
+ }
+ return s
+}
+
+type EDNS0_EXPIRE struct {
+ Code uint16 // Always EDNS0EXPIRE
+ Expire uint32
+}
+
+// Option implements the EDNS0 interface.
+func (e *EDNS0_EXPIRE) Option() uint16 { return EDNS0EXPIRE }
+func (e *EDNS0_EXPIRE) String() string { return strconv.FormatUint(uint64(e.Expire), 10) }
+
+func (e *EDNS0_EXPIRE) pack() ([]byte, error) {
+ b := make([]byte, 4)
+ b[0] = byte(e.Expire >> 24)
+ b[1] = byte(e.Expire >> 16)
+ b[2] = byte(e.Expire >> 8)
+ b[3] = byte(e.Expire)
+ return b, nil
+}
+
+func (e *EDNS0_EXPIRE) unpack(b []byte) error {
+ if len(b) < 4 {
+ return ErrBuf
+ }
+ e.Expire = binary.BigEndian.Uint32(b)
+ return nil
+}
+
+// The EDNS0_LOCAL option is used for local/experimental purposes. The option
+// code is recommended to be within the range [EDNS0LOCALSTART, EDNS0LOCALEND]
+// (RFC6891), although any unassigned code can actually be used. The content of
+// the option is made available in Data, unaltered.
+// Basic use pattern for creating a local option:
+//
+// o := new(dns.OPT)
+// o.Hdr.Name = "."
+// o.Hdr.Rrtype = dns.TypeOPT
+// e := new(dns.EDNS0_LOCAL)
+// e.Code = dns.EDNS0LOCALSTART
+// e.Data = []byte{72, 82, 74}
+// o.Option = append(o.Option, e)
+type EDNS0_LOCAL struct {
+ Code uint16
+ Data []byte
+}
+
+// Option implements the EDNS0 interface.
+func (e *EDNS0_LOCAL) Option() uint16 { return e.Code }
+func (e *EDNS0_LOCAL) String() string {
+ return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data)
+}
+
+func (e *EDNS0_LOCAL) pack() ([]byte, error) {
+ b := make([]byte, len(e.Data))
+ copied := copy(b, e.Data)
+ if copied != len(e.Data) {
+ return nil, ErrBuf
+ }
+ return b, nil
+}
+
+func (e *EDNS0_LOCAL) unpack(b []byte) error {
+ e.Data = make([]byte, len(b))
+ copied := copy(e.Data, b)
+ if copied != len(b) {
+ return ErrBuf
+ }
+ return nil
+}
+
+// EDNS0_TCP_KEEPALIVE is an EDNS0 option that instructs the server to keep
+// the TCP connection alive. See RFC 7828.
+type EDNS0_TCP_KEEPALIVE struct {
+ Code uint16 // Always EDNSTCPKEEPALIVE
+ Length uint16 // the value 0 if the TIMEOUT is omitted, the value 2 if it is present;
+ Timeout uint16 // an idle timeout value for the TCP connection, specified in units of 100 milliseconds, encoded in network byte order.
+}
+
+// Option implements the EDNS0 interface.
+func (e *EDNS0_TCP_KEEPALIVE) Option() uint16 { return EDNS0TCPKEEPALIVE }
+
+func (e *EDNS0_TCP_KEEPALIVE) pack() ([]byte, error) {
+ if e.Timeout != 0 && e.Length != 2 {
+ return nil, errors.New("dns: timeout specified but length is not 2")
+ }
+ if e.Timeout == 0 && e.Length != 0 {
+ return nil, errors.New("dns: timeout not specified but length is not 0")
+ }
+ b := make([]byte, 4+e.Length)
+ binary.BigEndian.PutUint16(b[0:], e.Code)
+ binary.BigEndian.PutUint16(b[2:], e.Length)
+ if e.Length == 2 {
+ binary.BigEndian.PutUint16(b[4:], e.Timeout)
+ }
+ return b, nil
+}
+
+func (e *EDNS0_TCP_KEEPALIVE) unpack(b []byte) error {
+ if len(b) < 4 {
+ return ErrBuf
+ }
+ e.Length = binary.BigEndian.Uint16(b[2:4])
+ if e.Length != 0 && e.Length != 2 {
+ return errors.New("dns: length mismatch, want 0/2 but got " + strconv.FormatUint(uint64(e.Length), 10))
+ }
+ if e.Length == 2 {
+ if len(b) < 6 {
+ return ErrBuf
+ }
+ e.Timeout = binary.BigEndian.Uint16(b[4:6])
+ }
+ return nil
+}
+
+func (e *EDNS0_TCP_KEEPALIVE) String() (s string) {
+ s = "use tcp keep-alive"
+ if e.Length == 0 {
+ s += ", timeout omitted"
+ } else {
+ s += fmt.Sprintf(", timeout %dms", e.Timeout*100)
+ }
+ return
+}
+
+// EDNS0_PADDING option is used to add padding to a request/response. The default
+// value of padding SHOULD be 0x0 but other values MAY be used, for instance if
+// compression is applied before encryption which may break signatures.
+type EDNS0_PADDING struct {
+ Padding []byte
+}
+
+// Option implements the EDNS0 interface.
+func (e *EDNS0_PADDING) Option() uint16 { return EDNS0PADDING }
+func (e *EDNS0_PADDING) pack() ([]byte, error) { return e.Padding, nil }
+func (e *EDNS0_PADDING) unpack(b []byte) error { e.Padding = b; return nil }
+func (e *EDNS0_PADDING) String() string { return fmt.Sprintf("%0X", e.Padding) }
--- /dev/null
+package dns
+
+import (
+ "net"
+ "reflect"
+ "strconv"
+)
+
+// NumField returns the number of rdata fields r has.
+func NumField(r RR) int {
+ return reflect.ValueOf(r).Elem().NumField() - 1 // Remove RR_Header
+}
+
+// Field returns the rdata field i as a string. Fields are indexed starting from 1.
+// RR types that holds slice data, for instance the NSEC type bitmap will return a single
+// string where the types are concatenated using a space.
+// Accessing non existing fields will cause a panic.
+func Field(r RR, i int) string {
+ if i == 0 {
+ return ""
+ }
+ d := reflect.ValueOf(r).Elem().Field(i)
+ switch k := d.Kind(); k {
+ case reflect.String:
+ return d.String()
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return strconv.FormatInt(d.Int(), 10)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return strconv.FormatUint(d.Uint(), 10)
+ case reflect.Slice:
+ switch reflect.ValueOf(r).Elem().Type().Field(i).Tag {
+ case `dns:"a"`:
+ // TODO(miek): Hmm store this as 16 bytes
+ if d.Len() < net.IPv6len {
+ return net.IPv4(byte(d.Index(0).Uint()),
+ byte(d.Index(1).Uint()),
+ byte(d.Index(2).Uint()),
+ byte(d.Index(3).Uint())).String()
+ }
+ return net.IPv4(byte(d.Index(12).Uint()),
+ byte(d.Index(13).Uint()),
+ byte(d.Index(14).Uint()),
+ byte(d.Index(15).Uint())).String()
+ case `dns:"aaaa"`:
+ return net.IP{
+ byte(d.Index(0).Uint()),
+ byte(d.Index(1).Uint()),
+ byte(d.Index(2).Uint()),
+ byte(d.Index(3).Uint()),
+ byte(d.Index(4).Uint()),
+ byte(d.Index(5).Uint()),
+ byte(d.Index(6).Uint()),
+ byte(d.Index(7).Uint()),
+ byte(d.Index(8).Uint()),
+ byte(d.Index(9).Uint()),
+ byte(d.Index(10).Uint()),
+ byte(d.Index(11).Uint()),
+ byte(d.Index(12).Uint()),
+ byte(d.Index(13).Uint()),
+ byte(d.Index(14).Uint()),
+ byte(d.Index(15).Uint()),
+ }.String()
+ case `dns:"nsec"`:
+ if d.Len() == 0 {
+ return ""
+ }
+ s := Type(d.Index(0).Uint()).String()
+ for i := 1; i < d.Len(); i++ {
+ s += " " + Type(d.Index(i).Uint()).String()
+ }
+ return s
+ default:
+ // if it does not have a tag its a string slice
+ fallthrough
+ case `dns:"txt"`:
+ if d.Len() == 0 {
+ return ""
+ }
+ s := d.Index(0).String()
+ for i := 1; i < d.Len(); i++ {
+ s += " " + d.Index(i).String()
+ }
+ return s
+ }
+ }
+ return ""
+}
--- /dev/null
+package dns
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+// Parse the $GENERATE statement as used in BIND9 zones.
+// See http://www.zytrax.com/books/dns/ch8/generate.html for instance.
+// We are called after '$GENERATE '. After which we expect:
+// * the range (12-24/2)
+// * lhs (ownername)
+// * [[ttl][class]]
+// * type
+// * rhs (rdata)
+// But we are lazy here, only the range is parsed *all* occurrences
+// of $ after that are interpreted.
+// Any error are returned as a string value, the empty string signals
+// "no error".
+func generate(l lex, c chan lex, t chan *Token, o string) string {
+ step := 1
+ if i := strings.IndexAny(l.token, "/"); i != -1 {
+ if i+1 == len(l.token) {
+ return "bad step in $GENERATE range"
+ }
+ if s, err := strconv.Atoi(l.token[i+1:]); err == nil {
+ if s < 0 {
+ return "bad step in $GENERATE range"
+ }
+ step = s
+ } else {
+ return "bad step in $GENERATE range"
+ }
+ l.token = l.token[:i]
+ }
+ sx := strings.SplitN(l.token, "-", 2)
+ if len(sx) != 2 {
+ return "bad start-stop in $GENERATE range"
+ }
+ start, err := strconv.Atoi(sx[0])
+ if err != nil {
+ return "bad start in $GENERATE range"
+ }
+ end, err := strconv.Atoi(sx[1])
+ if err != nil {
+ return "bad stop in $GENERATE range"
+ }
+ if end < 0 || start < 0 || end < start {
+ return "bad range in $GENERATE range"
+ }
+
+ <-c // _BLANK
+ // Create a complete new string, which we then parse again.
+ s := ""
+BuildRR:
+ l = <-c
+ if l.value != zNewline && l.value != zEOF {
+ s += l.token
+ goto BuildRR
+ }
+ for i := start; i <= end; i += step {
+ var (
+ escape bool
+ dom bytes.Buffer
+ mod string
+ err error
+ offset int
+ )
+
+ for j := 0; j < len(s); j++ { // No 'range' because we need to jump around
+ switch s[j] {
+ case '\\':
+ if escape {
+ dom.WriteByte('\\')
+ escape = false
+ continue
+ }
+ escape = true
+ case '$':
+ mod = "%d"
+ offset = 0
+ if escape {
+ dom.WriteByte('$')
+ escape = false
+ continue
+ }
+ escape = false
+ if j+1 >= len(s) { // End of the string
+ dom.WriteString(fmt.Sprintf(mod, i+offset))
+ continue
+ } else {
+ if s[j+1] == '$' {
+ dom.WriteByte('$')
+ j++
+ continue
+ }
+ }
+ // Search for { and }
+ if s[j+1] == '{' { // Modifier block
+ sep := strings.Index(s[j+2:], "}")
+ if sep == -1 {
+ return "bad modifier in $GENERATE"
+ }
+ mod, offset, err = modToPrintf(s[j+2 : j+2+sep])
+ if err != nil {
+ return err.Error()
+ }
+ j += 2 + sep // Jump to it
+ }
+ dom.WriteString(fmt.Sprintf(mod, i+offset))
+ default:
+ if escape { // Pretty useless here
+ escape = false
+ continue
+ }
+ dom.WriteByte(s[j])
+ }
+ }
+ // Re-parse the RR and send it on the current channel t
+ rx, err := NewRR("$ORIGIN " + o + "\n" + dom.String())
+ if err != nil {
+ return err.Error()
+ }
+ t <- &Token{RR: rx}
+ // Its more efficient to first built the rrlist and then parse it in
+ // one go! But is this a problem?
+ }
+ return ""
+}
+
+// Convert a $GENERATE modifier 0,0,d to something Printf can deal with.
+func modToPrintf(s string) (string, int, error) {
+ xs := strings.SplitN(s, ",", 3)
+ if len(xs) != 3 {
+ return "", 0, errors.New("bad modifier in $GENERATE")
+ }
+ // xs[0] is offset, xs[1] is width, xs[2] is base
+ if xs[2] != "o" && xs[2] != "d" && xs[2] != "x" && xs[2] != "X" {
+ return "", 0, errors.New("bad base in $GENERATE")
+ }
+ offset, err := strconv.Atoi(xs[0])
+ if err != nil || offset > 255 {
+ return "", 0, errors.New("bad offset in $GENERATE")
+ }
+ width, err := strconv.Atoi(xs[1])
+ if err != nil || width > 255 {
+ return "", offset, errors.New("bad width in $GENERATE")
+ }
+ switch {
+ case width < 0:
+ return "", offset, errors.New("bad width in $GENERATE")
+ case width == 0:
+ return "%" + xs[1] + xs[2], offset, nil
+ }
+ return "%0" + xs[1] + xs[2], offset, nil
+}
--- /dev/null
+// +build linux
+
+package socket
+
+func (h *cmsghdr) len() int { return int(h.Len) }
+func (h *cmsghdr) lvl() int { return int(h.Level) }
+func (h *cmsghdr) typ() int { return int(h.Type) }
--- /dev/null
+// +build arm mips mipsle 386
+// +build linux
+
+package socket
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+const (
+ sizeofCmsghdr = 0xc
+)
+
+func (h *cmsghdr) set(l, lvl, typ int) {
+ h.Len = uint32(l)
+ h.Level = int32(lvl)
+ h.Type = int32(typ)
+}
--- /dev/null
+// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
+// +build linux
+
+package socket
+
+type cmsghdr struct {
+ Len uint64
+ Level int32
+ Type int32
+}
+
+const (
+ sizeofCmsghdr = 0x10
+)
+
+func (h *cmsghdr) set(l, lvl, typ int) {
+ h.Len = uint64(l)
+ h.Level = int32(lvl)
+ h.Type = int32(typ)
+}
--- /dev/null
+// +build !linux
+
+package socket
+
+type cmsghdr struct{}
+
+const sizeofCmsghdr = 0
+
+func (h *cmsghdr) len() int { return 0 }
+func (h *cmsghdr) lvl() int { return 0 }
+func (h *cmsghdr) typ() int { return 0 }
+
+func (h *cmsghdr) set(l, lvl, typ int) {}
--- /dev/null
+package socket
+
+import (
+ "errors"
+ "unsafe"
+)
+
+func controlHeaderLen() int {
+ return roundup(sizeofCmsghdr)
+}
+
+func controlMessageLen(dataLen int) int {
+ return roundup(sizeofCmsghdr) + dataLen
+}
+
+// returns the whole length of control message.
+func ControlMessageSpace(dataLen int) int {
+ return roundup(sizeofCmsghdr) + roundup(dataLen)
+}
+
+// A ControlMessage represents the head message in a stream of control
+// messages.
+//
+// A control message comprises of a header, data and a few padding
+// fields to conform to the interface to the kernel.
+//
+// See RFC 3542 for further information.
+type ControlMessage []byte
+
+// Data returns the data field of the control message at the head.
+func (m ControlMessage) Data(dataLen int) []byte {
+ l := controlHeaderLen()
+ if len(m) < l || len(m) < l+dataLen {
+ return nil
+ }
+ return m[l : l+dataLen]
+}
+
+// ParseHeader parses and returns the header fields of the control
+// message at the head.
+func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
+ l := controlHeaderLen()
+ if len(m) < l {
+ return 0, 0, 0, errors.New("short message")
+ }
+ h := (*cmsghdr)(unsafe.Pointer(&m[0]))
+ return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil
+}
+
+// Next returns the control message at the next.
+func (m ControlMessage) Next(dataLen int) ControlMessage {
+ l := ControlMessageSpace(dataLen)
+ if len(m) < l {
+ return nil
+ }
+ return m[l:]
+}
+
+// MarshalHeader marshals the header fields of the control message at
+// the head.
+func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
+ if len(m) < controlHeaderLen() {
+ return errors.New("short message")
+ }
+ h := (*cmsghdr)(unsafe.Pointer(&m[0]))
+ h.set(controlMessageLen(dataLen), lvl, typ)
+ return nil
+}
+
+// Marshal marshals the control message at the head, and returns the next
+// control message.
+func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) {
+ l := len(data)
+ if len(m) < ControlMessageSpace(l) {
+ return nil, errors.New("short message")
+ }
+ h := (*cmsghdr)(unsafe.Pointer(&m[0]))
+ h.set(controlMessageLen(l), lvl, typ)
+ if l > 0 {
+ copy(m.Data(l), data)
+ }
+ return m.Next(l), nil
+}
+
+// Parse parses as a single or multiple control messages.
+func (m ControlMessage) Parse() ([]ControlMessage, error) {
+ var ms []ControlMessage
+ for len(m) >= controlHeaderLen() {
+ h := (*cmsghdr)(unsafe.Pointer(&m[0]))
+ l := h.len()
+ if l <= 0 {
+ return nil, errors.New("invalid header length")
+ }
+ if uint64(l) < uint64(controlHeaderLen()) {
+ return nil, errors.New("invalid message length")
+ }
+ if uint64(l) > uint64(len(m)) {
+ return nil, errors.New("short buffer")
+ }
+ ms = append(ms, ControlMessage(m[:l]))
+ ll := l - controlHeaderLen()
+ if len(m) >= ControlMessageSpace(ll) {
+ m = m[ControlMessageSpace(ll):]
+ } else {
+ m = m[controlMessageLen(ll):]
+ }
+ }
+ return ms, nil
+}
+
+// NewControlMessage returns a new stream of control messages.
+func NewControlMessage(dataLen []int) ControlMessage {
+ var l int
+ for i := range dataLen {
+ l += ControlMessageSpace(dataLen[i])
+ }
+ return make([]byte, l)
+}
--- /dev/null
+// Package socket contains ControlMessage parsing code from
+// golang.org/x/net/internal/socket. Instead of supporting all possible
+// architectures, we're only supporting linux 32/64 bit.
+package socket
--- /dev/null
+package socket
+
+import "unsafe"
+
+var (
+ kernelAlign = func() int {
+ var p uintptr
+ return int(unsafe.Sizeof(p))
+ }()
+)
+
+func roundup(l int) int {
+ return (l + kernelAlign - 1) & ^(kernelAlign - 1)
+}
--- /dev/null
+package dns
+
+// Holds a bunch of helper functions for dealing with labels.
+
+// SplitDomainName splits a name string into it's labels.
+// www.miek.nl. returns []string{"www", "miek", "nl"}
+// .www.miek.nl. returns []string{"", "www", "miek", "nl"},
+// The root label (.) returns nil. Note that using
+// strings.Split(s) will work in most cases, but does not handle
+// escaped dots (\.) for instance.
+// s must be a syntactically valid domain name, see IsDomainName.
+func SplitDomainName(s string) (labels []string) {
+ if len(s) == 0 {
+ return nil
+ }
+ fqdnEnd := 0 // offset of the final '.' or the length of the name
+ idx := Split(s)
+ begin := 0
+ if s[len(s)-1] == '.' {
+ fqdnEnd = len(s) - 1
+ } else {
+ fqdnEnd = len(s)
+ }
+
+ switch len(idx) {
+ case 0:
+ return nil
+ case 1:
+ // no-op
+ default:
+ end := 0
+ for i := 1; i < len(idx); i++ {
+ end = idx[i]
+ labels = append(labels, s[begin:end-1])
+ begin = end
+ }
+ }
+
+ labels = append(labels, s[begin:fqdnEnd])
+ return labels
+}
+
+// CompareDomainName compares the names s1 and s2 and
+// returns how many labels they have in common starting from the *right*.
+// The comparison stops at the first inequality. The names are downcased
+// before the comparison.
+//
+// www.miek.nl. and miek.nl. have two labels in common: miek and nl
+// www.miek.nl. and www.bla.nl. have one label in common: nl
+//
+// s1 and s2 must be syntactically valid domain names.
+func CompareDomainName(s1, s2 string) (n int) {
+ // the first check: root label
+ if s1 == "." || s2 == "." {
+ return 0
+ }
+
+ l1 := Split(s1)
+ l2 := Split(s2)
+
+ j1 := len(l1) - 1 // end
+ i1 := len(l1) - 2 // start
+ j2 := len(l2) - 1
+ i2 := len(l2) - 2
+ // the second check can be done here: last/only label
+ // before we fall through into the for-loop below
+ if equal(s1[l1[j1]:], s2[l2[j2]:]) {
+ n++
+ } else {
+ return
+ }
+ for {
+ if i1 < 0 || i2 < 0 {
+ break
+ }
+ if equal(s1[l1[i1]:l1[j1]], s2[l2[i2]:l2[j2]]) {
+ n++
+ } else {
+ break
+ }
+ j1--
+ i1--
+ j2--
+ i2--
+ }
+ return
+}
+
+// CountLabel counts the the number of labels in the string s.
+// s must be a syntactically valid domain name.
+func CountLabel(s string) (labels int) {
+ if s == "." {
+ return
+ }
+ off := 0
+ end := false
+ for {
+ off, end = NextLabel(s, off)
+ labels++
+ if end {
+ return
+ }
+ }
+}
+
+// Split splits a name s into its label indexes.
+// www.miek.nl. returns []int{0, 4, 9}, www.miek.nl also returns []int{0, 4, 9}.
+// The root name (.) returns nil. Also see SplitDomainName.
+// s must be a syntactically valid domain name.
+func Split(s string) []int {
+ if s == "." {
+ return nil
+ }
+ idx := make([]int, 1, 3)
+ off := 0
+ end := false
+
+ for {
+ off, end = NextLabel(s, off)
+ if end {
+ return idx
+ }
+ idx = append(idx, off)
+ }
+}
+
+// NextLabel returns the index of the start of the next label in the
+// string s starting at offset.
+// The bool end is true when the end of the string has been reached.
+// Also see PrevLabel.
+func NextLabel(s string, offset int) (i int, end bool) {
+ quote := false
+ for i = offset; i < len(s)-1; i++ {
+ switch s[i] {
+ case '\\':
+ quote = !quote
+ default:
+ quote = false
+ case '.':
+ if quote {
+ quote = !quote
+ continue
+ }
+ return i + 1, false
+ }
+ }
+ return i + 1, true
+}
+
+// PrevLabel returns the index of the label when starting from the right and
+// jumping n labels to the left.
+// The bool start is true when the start of the string has been overshot.
+// Also see NextLabel.
+func PrevLabel(s string, n int) (i int, start bool) {
+ if n == 0 {
+ return len(s), false
+ }
+ lab := Split(s)
+ if lab == nil {
+ return 0, true
+ }
+ if n > len(lab) {
+ return 0, true
+ }
+ return lab[len(lab)-n], false
+}
+
+// equal compares a and b while ignoring case. It returns true when equal otherwise false.
+func equal(a, b string) bool {
+ // might be lifted into API function.
+ la := len(a)
+ lb := len(b)
+ if la != lb {
+ return false
+ }
+
+ for i := la - 1; i >= 0; i-- {
+ ai := a[i]
+ bi := b[i]
+ if ai >= 'A' && ai <= 'Z' {
+ ai |= ('a' - 'A')
+ }
+ if bi >= 'A' && bi <= 'Z' {
+ bi |= ('a' - 'A')
+ }
+ if ai != bi {
+ return false
+ }
+ }
+ return true
+}
--- /dev/null
+// DNS packet assembly, see RFC 1035. Converting from - Unpack() -
+// and to - Pack() - wire format.
+// All the packers and unpackers take a (msg []byte, off int)
+// and return (off1 int, ok bool). If they return ok==false, they
+// also return off1==len(msg), so that the next unpacker will
+// also fail. This lets us avoid checks of ok until the end of a
+// packing sequence.
+
+package dns
+
+//go:generate go run msg_generate.go
+//go:generate go run compress_generate.go
+
+import (
+ crand "crypto/rand"
+ "encoding/binary"
+ "fmt"
+ "math/big"
+ "math/rand"
+ "strconv"
+ "sync"
+)
+
+const (
+ maxCompressionOffset = 2 << 13 // We have 14 bits for the compression pointer
+ maxDomainNameWireOctets = 255 // See RFC 1035 section 2.3.4
+)
+
+// Errors defined in this package.
+var (
+ ErrAlg error = &Error{err: "bad algorithm"} // ErrAlg indicates an error with the (DNSSEC) algorithm.
+ ErrAuth error = &Error{err: "bad authentication"} // ErrAuth indicates an error in the TSIG authentication.
+ ErrBuf error = &Error{err: "buffer size too small"} // ErrBuf indicates that the buffer used is too small for the message.
+ ErrConnEmpty error = &Error{err: "conn has no connection"} // ErrConnEmpty indicates a connection is being used before it is initialized.
+ ErrExtendedRcode error = &Error{err: "bad extended rcode"} // ErrExtendedRcode ...
+ ErrFqdn error = &Error{err: "domain must be fully qualified"} // ErrFqdn indicates that a domain name does not have a closing dot.
+ ErrId error = &Error{err: "id mismatch"} // ErrId indicates there is a mismatch with the message's ID.
+ ErrKeyAlg error = &Error{err: "bad key algorithm"} // ErrKeyAlg indicates that the algorithm in the key is not valid.
+ ErrKey error = &Error{err: "bad key"}
+ ErrKeySize error = &Error{err: "bad key size"}
+ ErrLongDomain error = &Error{err: fmt.Sprintf("domain name exceeded %d wire-format octets", maxDomainNameWireOctets)}
+ ErrNoSig error = &Error{err: "no signature found"}
+ ErrPrivKey error = &Error{err: "bad private key"}
+ ErrRcode error = &Error{err: "bad rcode"}
+ ErrRdata error = &Error{err: "bad rdata"}
+ ErrRRset error = &Error{err: "bad rrset"}
+ ErrSecret error = &Error{err: "no secrets defined"}
+ ErrShortRead error = &Error{err: "short read"}
+ ErrSig error = &Error{err: "bad signature"} // ErrSig indicates that a signature can not be cryptographically validated.
+ ErrSoa error = &Error{err: "no SOA"} // ErrSOA indicates that no SOA RR was seen when doing zone transfers.
+ ErrTime error = &Error{err: "bad time"} // ErrTime indicates a timing error in TSIG authentication.
+ ErrTruncated error = &Error{err: "failed to unpack truncated message"} // ErrTruncated indicates that we failed to unpack a truncated message. We unpacked as much as we had so Msg can still be used, if desired.
+)
+
+// Id by default, returns a 16 bits random number to be used as a
+// message id. The random provided should be good enough. This being a
+// variable the function can be reassigned to a custom function.
+// For instance, to make it return a static value:
+//
+// dns.Id = func() uint16 { return 3 }
+var Id = id
+
+var (
+ idLock sync.Mutex
+ idRand *rand.Rand
+)
+
+// id returns a 16 bits random number to be used as a
+// message id. The random provided should be good enough.
+func id() uint16 {
+ idLock.Lock()
+
+ if idRand == nil {
+ // This (partially) works around
+ // https://github.com/golang/go/issues/11833 by only
+ // seeding idRand upon the first call to id.
+
+ var seed int64
+ var buf [8]byte
+
+ if _, err := crand.Read(buf[:]); err == nil {
+ seed = int64(binary.LittleEndian.Uint64(buf[:]))
+ } else {
+ seed = rand.Int63()
+ }
+
+ idRand = rand.New(rand.NewSource(seed))
+ }
+
+ // The call to idRand.Uint32 must be within the
+ // mutex lock because *rand.Rand is not safe for
+ // concurrent use.
+ //
+ // There is no added performance overhead to calling
+ // idRand.Uint32 inside a mutex lock over just
+ // calling rand.Uint32 as the global math/rand rng
+ // is internally protected by a sync.Mutex.
+ id := uint16(idRand.Uint32())
+
+ idLock.Unlock()
+ return id
+}
+
+// MsgHdr is a a manually-unpacked version of (id, bits).
+type MsgHdr struct {
+ Id uint16
+ Response bool
+ Opcode int
+ Authoritative bool
+ Truncated bool
+ RecursionDesired bool
+ RecursionAvailable bool
+ Zero bool
+ AuthenticatedData bool
+ CheckingDisabled bool
+ Rcode int
+}
+
+// Msg contains the layout of a DNS message.
+type Msg struct {
+ MsgHdr
+ Compress bool `json:"-"` // If true, the message will be compressed when converted to wire format.
+ Question []Question // Holds the RR(s) of the question section.
+ Answer []RR // Holds the RR(s) of the answer section.
+ Ns []RR // Holds the RR(s) of the authority section.
+ Extra []RR // Holds the RR(s) of the additional section.
+}
+
+// ClassToString is a maps Classes to strings for each CLASS wire type.
+var ClassToString = map[uint16]string{
+ ClassINET: "IN",
+ ClassCSNET: "CS",
+ ClassCHAOS: "CH",
+ ClassHESIOD: "HS",
+ ClassNONE: "NONE",
+ ClassANY: "ANY",
+}
+
+// OpcodeToString maps Opcodes to strings.
+var OpcodeToString = map[int]string{
+ OpcodeQuery: "QUERY",
+ OpcodeIQuery: "IQUERY",
+ OpcodeStatus: "STATUS",
+ OpcodeNotify: "NOTIFY",
+ OpcodeUpdate: "UPDATE",
+}
+
+// RcodeToString maps Rcodes to strings.
+var RcodeToString = map[int]string{
+ RcodeSuccess: "NOERROR",
+ RcodeFormatError: "FORMERR",
+ RcodeServerFailure: "SERVFAIL",
+ RcodeNameError: "NXDOMAIN",
+ RcodeNotImplemented: "NOTIMPL",
+ RcodeRefused: "REFUSED",
+ RcodeYXDomain: "YXDOMAIN", // See RFC 2136
+ RcodeYXRrset: "YXRRSET",
+ RcodeNXRrset: "NXRRSET",
+ RcodeNotAuth: "NOTAUTH",
+ RcodeNotZone: "NOTZONE",
+ RcodeBadSig: "BADSIG", // Also known as RcodeBadVers, see RFC 6891
+ // RcodeBadVers: "BADVERS",
+ RcodeBadKey: "BADKEY",
+ RcodeBadTime: "BADTIME",
+ RcodeBadMode: "BADMODE",
+ RcodeBadName: "BADNAME",
+ RcodeBadAlg: "BADALG",
+ RcodeBadTrunc: "BADTRUNC",
+ RcodeBadCookie: "BADCOOKIE",
+}
+
+// Domain names are a sequence of counted strings
+// split at the dots. They end with a zero-length string.
+
+// PackDomainName packs a domain name s into msg[off:].
+// If compression is wanted compress must be true and the compression
+// map needs to hold a mapping between domain names and offsets
+// pointing into msg.
+func PackDomainName(s string, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
+ off1, _, err = packDomainName(s, msg, off, compression, compress)
+ return
+}
+
+func packDomainName(s string, msg []byte, off int, compression map[string]int, compress bool) (off1 int, labels int, err error) {
+ // special case if msg == nil
+ lenmsg := 256
+ if msg != nil {
+ lenmsg = len(msg)
+ }
+ ls := len(s)
+ if ls == 0 { // Ok, for instance when dealing with update RR without any rdata.
+ return off, 0, nil
+ }
+ // If not fully qualified, error out, but only if msg == nil #ugly
+ switch {
+ case msg == nil:
+ if s[ls-1] != '.' {
+ s += "."
+ ls++
+ }
+ case msg != nil:
+ if s[ls-1] != '.' {
+ return lenmsg, 0, ErrFqdn
+ }
+ }
+ // Each dot ends a segment of the name.
+ // We trade each dot byte for a length byte.
+ // Except for escaped dots (\.), which are normal dots.
+ // There is also a trailing zero.
+
+ // Compression
+ nameoffset := -1
+ pointer := -1
+ // Emit sequence of counted strings, chopping at dots.
+ begin := 0
+ bs := []byte(s)
+ roBs, bsFresh, escapedDot := s, true, false
+ for i := 0; i < ls; i++ {
+ if bs[i] == '\\' {
+ for j := i; j < ls-1; j++ {
+ bs[j] = bs[j+1]
+ }
+ ls--
+ if off+1 > lenmsg {
+ return lenmsg, labels, ErrBuf
+ }
+ // check for \DDD
+ if i+2 < ls && isDigit(bs[i]) && isDigit(bs[i+1]) && isDigit(bs[i+2]) {
+ bs[i] = dddToByte(bs[i:])
+ for j := i + 1; j < ls-2; j++ {
+ bs[j] = bs[j+2]
+ }
+ ls -= 2
+ }
+ escapedDot = bs[i] == '.'
+ bsFresh = false
+ continue
+ }
+
+ if bs[i] == '.' {
+ if i > 0 && bs[i-1] == '.' && !escapedDot {
+ // two dots back to back is not legal
+ return lenmsg, labels, ErrRdata
+ }
+ if i-begin >= 1<<6 { // top two bits of length must be clear
+ return lenmsg, labels, ErrRdata
+ }
+ // off can already (we're in a loop) be bigger than len(msg)
+ // this happens when a name isn't fully qualified
+ if off+1 > lenmsg {
+ return lenmsg, labels, ErrBuf
+ }
+ if msg != nil {
+ msg[off] = byte(i - begin)
+ }
+ offset := off
+ off++
+ for j := begin; j < i; j++ {
+ if off+1 > lenmsg {
+ return lenmsg, labels, ErrBuf
+ }
+ if msg != nil {
+ msg[off] = bs[j]
+ }
+ off++
+ }
+ if compress && !bsFresh {
+ roBs = string(bs)
+ bsFresh = true
+ }
+ // Don't try to compress '.'
+ // We should only compress when compress it true, but we should also still pick
+ // up names that can be used for *future* compression(s).
+ if compression != nil && roBs[begin:] != "." {
+ if p, ok := compression[roBs[begin:]]; !ok {
+ // Only offsets smaller than this can be used.
+ if offset < maxCompressionOffset {
+ compression[roBs[begin:]] = offset
+ }
+ } else {
+ // The first hit is the longest matching dname
+ // keep the pointer offset we get back and store
+ // the offset of the current name, because that's
+ // where we need to insert the pointer later
+
+ // If compress is true, we're allowed to compress this dname
+ if pointer == -1 && compress {
+ pointer = p // Where to point to
+ nameoffset = offset // Where to point from
+ break
+ }
+ }
+ }
+ labels++
+ begin = i + 1
+ }
+ escapedDot = false
+ }
+ // Root label is special
+ if len(bs) == 1 && bs[0] == '.' {
+ return off, labels, nil
+ }
+ // If we did compression and we find something add the pointer here
+ if pointer != -1 {
+ // We have two bytes (14 bits) to put the pointer in
+ // if msg == nil, we will never do compression
+ binary.BigEndian.PutUint16(msg[nameoffset:], uint16(pointer^0xC000))
+ off = nameoffset + 1
+ goto End
+ }
+ if msg != nil && off < len(msg) {
+ msg[off] = 0
+ }
+End:
+ off++
+ return off, labels, nil
+}
+
+// Unpack a domain name.
+// In addition to the simple sequences of counted strings above,
+// domain names are allowed to refer to strings elsewhere in the
+// packet, to avoid repeating common suffixes when returning
+// many entries in a single domain. The pointers are marked
+// by a length byte with the top two bits set. Ignoring those
+// two bits, that byte and the next give a 14 bit offset from msg[0]
+// where we should pick up the trail.
+// Note that if we jump elsewhere in the packet,
+// we return off1 == the offset after the first pointer we found,
+// which is where the next record will start.
+// In theory, the pointers are only allowed to jump backward.
+// We let them jump anywhere and stop jumping after a while.
+
+// UnpackDomainName unpacks a domain name into a string.
+func UnpackDomainName(msg []byte, off int) (string, int, error) {
+ s := make([]byte, 0, 64)
+ off1 := 0
+ lenmsg := len(msg)
+ maxLen := maxDomainNameWireOctets
+ ptr := 0 // number of pointers followed
+Loop:
+ for {
+ if off >= lenmsg {
+ return "", lenmsg, ErrBuf
+ }
+ c := int(msg[off])
+ off++
+ switch c & 0xC0 {
+ case 0x00:
+ if c == 0x00 {
+ // end of name
+ break Loop
+ }
+ // literal string
+ if off+c > lenmsg {
+ return "", lenmsg, ErrBuf
+ }
+ for j := off; j < off+c; j++ {
+ switch b := msg[j]; b {
+ case '.', '(', ')', ';', ' ', '@':
+ fallthrough
+ case '"', '\\':
+ s = append(s, '\\', b)
+ // presentation-format \X escapes add an extra byte
+ maxLen++
+ default:
+ if b < 32 || b >= 127 { // unprintable, use \DDD
+ var buf [3]byte
+ bufs := strconv.AppendInt(buf[:0], int64(b), 10)
+ s = append(s, '\\')
+ for i := 0; i < 3-len(bufs); i++ {
+ s = append(s, '0')
+ }
+ for _, r := range bufs {
+ s = append(s, r)
+ }
+ // presentation-format \DDD escapes add 3 extra bytes
+ maxLen += 3
+ } else {
+ s = append(s, b)
+ }
+ }
+ }
+ s = append(s, '.')
+ off += c
+ case 0xC0:
+ // pointer to somewhere else in msg.
+ // remember location after first ptr,
+ // since that's how many bytes we consumed.
+ // also, don't follow too many pointers --
+ // maybe there's a loop.
+ if off >= lenmsg {
+ return "", lenmsg, ErrBuf
+ }
+ c1 := msg[off]
+ off++
+ if ptr == 0 {
+ off1 = off
+ }
+ if ptr++; ptr > 10 {
+ return "", lenmsg, &Error{err: "too many compression pointers"}
+ }
+ // pointer should guarantee that it advances and points forwards at least
+ // but the condition on previous three lines guarantees that it's
+ // at least loop-free
+ off = (c^0xC0)<<8 | int(c1)
+ default:
+ // 0x80 and 0x40 are reserved
+ return "", lenmsg, ErrRdata
+ }
+ }
+ if ptr == 0 {
+ off1 = off
+ }
+ if len(s) == 0 {
+ s = []byte(".")
+ } else if len(s) >= maxLen {
+ // error if the name is too long, but don't throw it away
+ return string(s), lenmsg, ErrLongDomain
+ }
+ return string(s), off1, nil
+}
+
+func packTxt(txt []string, msg []byte, offset int, tmp []byte) (int, error) {
+ if len(txt) == 0 {
+ if offset >= len(msg) {
+ return offset, ErrBuf
+ }
+ msg[offset] = 0
+ return offset, nil
+ }
+ var err error
+ for i := range txt {
+ if len(txt[i]) > len(tmp) {
+ return offset, ErrBuf
+ }
+ offset, err = packTxtString(txt[i], msg, offset, tmp)
+ if err != nil {
+ return offset, err
+ }
+ }
+ return offset, nil
+}
+
+func packTxtString(s string, msg []byte, offset int, tmp []byte) (int, error) {
+ lenByteOffset := offset
+ if offset >= len(msg) || len(s) > len(tmp) {
+ return offset, ErrBuf
+ }
+ offset++
+ bs := tmp[:len(s)]
+ copy(bs, s)
+ for i := 0; i < len(bs); i++ {
+ if len(msg) <= offset {
+ return offset, ErrBuf
+ }
+ if bs[i] == '\\' {
+ i++
+ if i == len(bs) {
+ break
+ }
+ // check for \DDD
+ if i+2 < len(bs) && isDigit(bs[i]) && isDigit(bs[i+1]) && isDigit(bs[i+2]) {
+ msg[offset] = dddToByte(bs[i:])
+ i += 2
+ } else {
+ msg[offset] = bs[i]
+ }
+ } else {
+ msg[offset] = bs[i]
+ }
+ offset++
+ }
+ l := offset - lenByteOffset - 1
+ if l > 255 {
+ return offset, &Error{err: "string exceeded 255 bytes in txt"}
+ }
+ msg[lenByteOffset] = byte(l)
+ return offset, nil
+}
+
+func packOctetString(s string, msg []byte, offset int, tmp []byte) (int, error) {
+ if offset >= len(msg) || len(s) > len(tmp) {
+ return offset, ErrBuf
+ }
+ bs := tmp[:len(s)]
+ copy(bs, s)
+ for i := 0; i < len(bs); i++ {
+ if len(msg) <= offset {
+ return offset, ErrBuf
+ }
+ if bs[i] == '\\' {
+ i++
+ if i == len(bs) {
+ break
+ }
+ // check for \DDD
+ if i+2 < len(bs) && isDigit(bs[i]) && isDigit(bs[i+1]) && isDigit(bs[i+2]) {
+ msg[offset] = dddToByte(bs[i:])
+ i += 2
+ } else {
+ msg[offset] = bs[i]
+ }
+ } else {
+ msg[offset] = bs[i]
+ }
+ offset++
+ }
+ return offset, nil
+}
+
+func unpackTxt(msg []byte, off0 int) (ss []string, off int, err error) {
+ off = off0
+ var s string
+ for off < len(msg) && err == nil {
+ s, off, err = unpackTxtString(msg, off)
+ if err == nil {
+ ss = append(ss, s)
+ }
+ }
+ return
+}
+
+func unpackTxtString(msg []byte, offset int) (string, int, error) {
+ if offset+1 > len(msg) {
+ return "", offset, &Error{err: "overflow unpacking txt"}
+ }
+ l := int(msg[offset])
+ if offset+l+1 > len(msg) {
+ return "", offset, &Error{err: "overflow unpacking txt"}
+ }
+ s := make([]byte, 0, l)
+ for _, b := range msg[offset+1 : offset+1+l] {
+ switch b {
+ case '"', '\\':
+ s = append(s, '\\', b)
+ default:
+ if b < 32 || b > 127 { // unprintable
+ var buf [3]byte
+ bufs := strconv.AppendInt(buf[:0], int64(b), 10)
+ s = append(s, '\\')
+ for i := 0; i < 3-len(bufs); i++ {
+ s = append(s, '0')
+ }
+ for _, r := range bufs {
+ s = append(s, r)
+ }
+ } else {
+ s = append(s, b)
+ }
+ }
+ }
+ offset += 1 + l
+ return string(s), offset, nil
+}
+
+// Helpers for dealing with escaped bytes
+func isDigit(b byte) bool { return b >= '0' && b <= '9' }
+
+func dddToByte(s []byte) byte {
+ return byte((s[0]-'0')*100 + (s[1]-'0')*10 + (s[2] - '0'))
+}
+
+// Helper function for packing and unpacking
+func intToBytes(i *big.Int, length int) []byte {
+ buf := i.Bytes()
+ if len(buf) < length {
+ b := make([]byte, length)
+ copy(b[length-len(buf):], buf)
+ return b
+ }
+ return buf
+}
+
+// PackRR packs a resource record rr into msg[off:].
+// See PackDomainName for documentation about the compression.
+func PackRR(rr RR, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
+ if rr == nil {
+ return len(msg), &Error{err: "nil rr"}
+ }
+
+ off1, err = rr.pack(msg, off, compression, compress)
+ if err != nil {
+ return len(msg), err
+ }
+ // TODO(miek): Not sure if this is needed? If removed we can remove rawmsg.go as well.
+ if rawSetRdlength(msg, off, off1) {
+ return off1, nil
+ }
+ return off, ErrRdata
+}
+
+// UnpackRR unpacks msg[off:] into an RR.
+func UnpackRR(msg []byte, off int) (rr RR, off1 int, err error) {
+ h, off, msg, err := unpackHeader(msg, off)
+ if err != nil {
+ return nil, len(msg), err
+ }
+ end := off + int(h.Rdlength)
+
+ if fn, known := typeToUnpack[h.Rrtype]; !known {
+ rr, off, err = unpackRFC3597(h, msg, off)
+ } else {
+ rr, off, err = fn(h, msg, off)
+ }
+ if off != end {
+ return &h, end, &Error{err: "bad rdlength"}
+ }
+ return rr, off, err
+}
+
+// unpackRRslice unpacks msg[off:] into an []RR.
+// If we cannot unpack the whole array, then it will return nil
+func unpackRRslice(l int, msg []byte, off int) (dst1 []RR, off1 int, err error) {
+ var r RR
+ // Optimistically make dst be the length that was sent
+ dst := make([]RR, 0, l)
+ for i := 0; i < l; i++ {
+ off1 := off
+ r, off, err = UnpackRR(msg, off)
+ if err != nil {
+ off = len(msg)
+ break
+ }
+ // If offset does not increase anymore, l is a lie
+ if off1 == off {
+ l = i
+ break
+ }
+ dst = append(dst, r)
+ }
+ if err != nil && off == len(msg) {
+ dst = nil
+ }
+ return dst, off, err
+}
+
+// Convert a MsgHdr to a string, with dig-like headers:
+//
+//;; opcode: QUERY, status: NOERROR, id: 48404
+//
+//;; flags: qr aa rd ra;
+func (h *MsgHdr) String() string {
+ if h == nil {
+ return "<nil> MsgHdr"
+ }
+
+ s := ";; opcode: " + OpcodeToString[h.Opcode]
+ s += ", status: " + RcodeToString[h.Rcode]
+ s += ", id: " + strconv.Itoa(int(h.Id)) + "\n"
+
+ s += ";; flags:"
+ if h.Response {
+ s += " qr"
+ }
+ if h.Authoritative {
+ s += " aa"
+ }
+ if h.Truncated {
+ s += " tc"
+ }
+ if h.RecursionDesired {
+ s += " rd"
+ }
+ if h.RecursionAvailable {
+ s += " ra"
+ }
+ if h.Zero { // Hmm
+ s += " z"
+ }
+ if h.AuthenticatedData {
+ s += " ad"
+ }
+ if h.CheckingDisabled {
+ s += " cd"
+ }
+
+ s += ";"
+ return s
+}
+
+// Pack packs a Msg: it is converted to to wire format.
+// If the dns.Compress is true the message will be in compressed wire format.
+func (dns *Msg) Pack() (msg []byte, err error) {
+ return dns.PackBuffer(nil)
+}
+
+// PackBuffer packs a Msg, using the given buffer buf. If buf is too small
+// a new buffer is allocated.
+func (dns *Msg) PackBuffer(buf []byte) (msg []byte, err error) {
+ // We use a similar function in tsig.go's stripTsig.
+ var (
+ dh Header
+ compression map[string]int
+ )
+
+ if dns.Compress {
+ compression = make(map[string]int) // Compression pointer mappings
+ }
+
+ if dns.Rcode < 0 || dns.Rcode > 0xFFF {
+ return nil, ErrRcode
+ }
+ if dns.Rcode > 0xF {
+ // Regular RCODE field is 4 bits
+ opt := dns.IsEdns0()
+ if opt == nil {
+ return nil, ErrExtendedRcode
+ }
+ opt.SetExtendedRcode(uint8(dns.Rcode >> 4))
+ dns.Rcode &= 0xF
+ }
+
+ // Convert convenient Msg into wire-like Header.
+ dh.Id = dns.Id
+ dh.Bits = uint16(dns.Opcode)<<11 | uint16(dns.Rcode)
+ if dns.Response {
+ dh.Bits |= _QR
+ }
+ if dns.Authoritative {
+ dh.Bits |= _AA
+ }
+ if dns.Truncated {
+ dh.Bits |= _TC
+ }
+ if dns.RecursionDesired {
+ dh.Bits |= _RD
+ }
+ if dns.RecursionAvailable {
+ dh.Bits |= _RA
+ }
+ if dns.Zero {
+ dh.Bits |= _Z
+ }
+ if dns.AuthenticatedData {
+ dh.Bits |= _AD
+ }
+ if dns.CheckingDisabled {
+ dh.Bits |= _CD
+ }
+
+ // Prepare variable sized arrays.
+ question := dns.Question
+ answer := dns.Answer
+ ns := dns.Ns
+ extra := dns.Extra
+
+ dh.Qdcount = uint16(len(question))
+ dh.Ancount = uint16(len(answer))
+ dh.Nscount = uint16(len(ns))
+ dh.Arcount = uint16(len(extra))
+
+ // We need the uncompressed length here, because we first pack it and then compress it.
+ msg = buf
+ uncompressedLen := compressedLen(dns, false)
+ if packLen := uncompressedLen + 1; len(msg) < packLen {
+ msg = make([]byte, packLen)
+ }
+
+ // Pack it in: header and then the pieces.
+ off := 0
+ off, err = dh.pack(msg, off, compression, dns.Compress)
+ if err != nil {
+ return nil, err
+ }
+ for i := 0; i < len(question); i++ {
+ off, err = question[i].pack(msg, off, compression, dns.Compress)
+ if err != nil {
+ return nil, err
+ }
+ }
+ for i := 0; i < len(answer); i++ {
+ off, err = PackRR(answer[i], msg, off, compression, dns.Compress)
+ if err != nil {
+ return nil, err
+ }
+ }
+ for i := 0; i < len(ns); i++ {
+ off, err = PackRR(ns[i], msg, off, compression, dns.Compress)
+ if err != nil {
+ return nil, err
+ }
+ }
+ for i := 0; i < len(extra); i++ {
+ off, err = PackRR(extra[i], msg, off, compression, dns.Compress)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return msg[:off], nil
+}
+
+// Unpack unpacks a binary message to a Msg structure.
+func (dns *Msg) Unpack(msg []byte) (err error) {
+ var (
+ dh Header
+ off int
+ )
+ if dh, off, err = unpackMsgHdr(msg, off); err != nil {
+ return err
+ }
+
+ dns.Id = dh.Id
+ dns.Response = (dh.Bits & _QR) != 0
+ dns.Opcode = int(dh.Bits>>11) & 0xF
+ dns.Authoritative = (dh.Bits & _AA) != 0
+ dns.Truncated = (dh.Bits & _TC) != 0
+ dns.RecursionDesired = (dh.Bits & _RD) != 0
+ dns.RecursionAvailable = (dh.Bits & _RA) != 0
+ dns.Zero = (dh.Bits & _Z) != 0
+ dns.AuthenticatedData = (dh.Bits & _AD) != 0
+ dns.CheckingDisabled = (dh.Bits & _CD) != 0
+ dns.Rcode = int(dh.Bits & 0xF)
+
+ if off == len(msg) {
+ return ErrTruncated
+ }
+
+ // Optimistically use the count given to us in the header
+ dns.Question = make([]Question, 0, int(dh.Qdcount))
+
+ for i := 0; i < int(dh.Qdcount); i++ {
+ off1 := off
+ var q Question
+ q, off, err = unpackQuestion(msg, off)
+ if err != nil {
+ // Even if Truncated is set, we only will set ErrTruncated if we
+ // actually got the questions
+ return err
+ }
+ if off1 == off { // Offset does not increase anymore, dh.Qdcount is a lie!
+ dh.Qdcount = uint16(i)
+ break
+ }
+ dns.Question = append(dns.Question, q)
+ }
+
+ dns.Answer, off, err = unpackRRslice(int(dh.Ancount), msg, off)
+ // The header counts might have been wrong so we need to update it
+ dh.Ancount = uint16(len(dns.Answer))
+ if err == nil {
+ dns.Ns, off, err = unpackRRslice(int(dh.Nscount), msg, off)
+ }
+ // The header counts might have been wrong so we need to update it
+ dh.Nscount = uint16(len(dns.Ns))
+ if err == nil {
+ dns.Extra, off, err = unpackRRslice(int(dh.Arcount), msg, off)
+ }
+ // The header counts might have been wrong so we need to update it
+ dh.Arcount = uint16(len(dns.Extra))
+
+ if off != len(msg) {
+ // TODO(miek) make this an error?
+ // use PackOpt to let people tell how detailed the error reporting should be?
+ // println("dns: extra bytes in dns packet", off, "<", len(msg))
+ } else if dns.Truncated {
+ // Whether we ran into a an error or not, we want to return that it
+ // was truncated
+ err = ErrTruncated
+ }
+ return err
+}
+
+// Convert a complete message to a string with dig-like output.
+func (dns *Msg) String() string {
+ if dns == nil {
+ return "<nil> MsgHdr"
+ }
+ s := dns.MsgHdr.String() + " "
+ s += "QUERY: " + strconv.Itoa(len(dns.Question)) + ", "
+ s += "ANSWER: " + strconv.Itoa(len(dns.Answer)) + ", "
+ s += "AUTHORITY: " + strconv.Itoa(len(dns.Ns)) + ", "
+ s += "ADDITIONAL: " + strconv.Itoa(len(dns.Extra)) + "\n"
+ if len(dns.Question) > 0 {
+ s += "\n;; QUESTION SECTION:\n"
+ for i := 0; i < len(dns.Question); i++ {
+ s += dns.Question[i].String() + "\n"
+ }
+ }
+ if len(dns.Answer) > 0 {
+ s += "\n;; ANSWER SECTION:\n"
+ for i := 0; i < len(dns.Answer); i++ {
+ if dns.Answer[i] != nil {
+ s += dns.Answer[i].String() + "\n"
+ }
+ }
+ }
+ if len(dns.Ns) > 0 {
+ s += "\n;; AUTHORITY SECTION:\n"
+ for i := 0; i < len(dns.Ns); i++ {
+ if dns.Ns[i] != nil {
+ s += dns.Ns[i].String() + "\n"
+ }
+ }
+ }
+ if len(dns.Extra) > 0 {
+ s += "\n;; ADDITIONAL SECTION:\n"
+ for i := 0; i < len(dns.Extra); i++ {
+ if dns.Extra[i] != nil {
+ s += dns.Extra[i].String() + "\n"
+ }
+ }
+ }
+ return s
+}
+
+// Len returns the message length when in (un)compressed wire format.
+// If dns.Compress is true compression it is taken into account. Len()
+// is provided to be a faster way to get the size of the resulting packet,
+// than packing it, measuring the size and discarding the buffer.
+func (dns *Msg) Len() int { return compressedLen(dns, dns.Compress) }
+
+// compressedLen returns the message length when in compressed wire format
+// when compress is true, otherwise the uncompressed length is returned.
+func compressedLen(dns *Msg, compress bool) int {
+ // We always return one more than needed.
+ l := 12 // Message header is always 12 bytes
+ if compress {
+ compression := map[string]int{}
+ for _, r := range dns.Question {
+ l += r.len()
+ compressionLenHelper(compression, r.Name)
+ }
+ l += compressionLenSlice(compression, dns.Answer)
+ l += compressionLenSlice(compression, dns.Ns)
+ l += compressionLenSlice(compression, dns.Extra)
+ } else {
+ for _, r := range dns.Question {
+ l += r.len()
+ }
+ for _, r := range dns.Answer {
+ if r != nil {
+ l += r.len()
+ }
+ }
+ for _, r := range dns.Ns {
+ if r != nil {
+ l += r.len()
+ }
+ }
+ for _, r := range dns.Extra {
+ if r != nil {
+ l += r.len()
+ }
+ }
+ }
+ return l
+}
+
+func compressionLenSlice(c map[string]int, rs []RR) int {
+ var l int
+ for _, r := range rs {
+ if r == nil {
+ continue
+ }
+ l += r.len()
+ k, ok := compressionLenSearch(c, r.Header().Name)
+ if ok {
+ l += 1 - k
+ }
+ compressionLenHelper(c, r.Header().Name)
+ k, ok = compressionLenSearchType(c, r)
+ if ok {
+ l += 1 - k
+ }
+ compressionLenHelperType(c, r)
+ }
+ return l
+}
+
+// Put the parts of the name in the compression map.
+func compressionLenHelper(c map[string]int, s string) {
+ pref := ""
+ lbs := Split(s)
+ for j := len(lbs) - 1; j >= 0; j-- {
+ pref = s[lbs[j]:]
+ if _, ok := c[pref]; !ok {
+ c[pref] = len(pref)
+ }
+ }
+}
+
+// Look for each part in the compression map and returns its length,
+// keep on searching so we get the longest match.
+func compressionLenSearch(c map[string]int, s string) (int, bool) {
+ off := 0
+ end := false
+ if s == "" { // don't bork on bogus data
+ return 0, false
+ }
+ for {
+ if _, ok := c[s[off:]]; ok {
+ return len(s[off:]), true
+ }
+ if end {
+ break
+ }
+ off, end = NextLabel(s, off)
+ }
+ return 0, false
+}
+
+// Copy returns a new RR which is a deep-copy of r.
+func Copy(r RR) RR { r1 := r.copy(); return r1 }
+
+// Len returns the length (in octets) of the uncompressed RR in wire format.
+func Len(r RR) int { return r.len() }
+
+// Copy returns a new *Msg which is a deep-copy of dns.
+func (dns *Msg) Copy() *Msg { return dns.CopyTo(new(Msg)) }
+
+// CopyTo copies the contents to the provided message using a deep-copy and returns the copy.
+func (dns *Msg) CopyTo(r1 *Msg) *Msg {
+ r1.MsgHdr = dns.MsgHdr
+ r1.Compress = dns.Compress
+
+ if len(dns.Question) > 0 {
+ r1.Question = make([]Question, len(dns.Question))
+ copy(r1.Question, dns.Question) // TODO(miek): Question is an immutable value, ok to do a shallow-copy
+ }
+
+ rrArr := make([]RR, len(dns.Answer)+len(dns.Ns)+len(dns.Extra))
+ var rri int
+
+ if len(dns.Answer) > 0 {
+ rrbegin := rri
+ for i := 0; i < len(dns.Answer); i++ {
+ rrArr[rri] = dns.Answer[i].copy()
+ rri++
+ }
+ r1.Answer = rrArr[rrbegin:rri:rri]
+ }
+
+ if len(dns.Ns) > 0 {
+ rrbegin := rri
+ for i := 0; i < len(dns.Ns); i++ {
+ rrArr[rri] = dns.Ns[i].copy()
+ rri++
+ }
+ r1.Ns = rrArr[rrbegin:rri:rri]
+ }
+
+ if len(dns.Extra) > 0 {
+ rrbegin := rri
+ for i := 0; i < len(dns.Extra); i++ {
+ rrArr[rri] = dns.Extra[i].copy()
+ rri++
+ }
+ r1.Extra = rrArr[rrbegin:rri:rri]
+ }
+
+ return r1
+}
+
+func (q *Question) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := PackDomainName(q.Name, msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(q.Qtype, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(q.Qclass, msg, off)
+ if err != nil {
+ return off, err
+ }
+ return off, nil
+}
+
+func unpackQuestion(msg []byte, off int) (Question, int, error) {
+ var (
+ q Question
+ err error
+ )
+ q.Name, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return q, off, err
+ }
+ if off == len(msg) {
+ return q, off, nil
+ }
+ q.Qtype, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return q, off, err
+ }
+ if off == len(msg) {
+ return q, off, nil
+ }
+ q.Qclass, off, err = unpackUint16(msg, off)
+ if off == len(msg) {
+ return q, off, nil
+ }
+ return q, off, err
+}
+
+func (dh *Header) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := packUint16(dh.Id, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(dh.Bits, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(dh.Qdcount, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(dh.Ancount, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(dh.Nscount, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(dh.Arcount, msg, off)
+ return off, err
+}
+
+func unpackMsgHdr(msg []byte, off int) (Header, int, error) {
+ var (
+ dh Header
+ err error
+ )
+ dh.Id, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return dh, off, err
+ }
+ dh.Bits, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return dh, off, err
+ }
+ dh.Qdcount, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return dh, off, err
+ }
+ dh.Ancount, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return dh, off, err
+ }
+ dh.Nscount, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return dh, off, err
+ }
+ dh.Arcount, off, err = unpackUint16(msg, off)
+ return dh, off, err
+}
--- /dev/null
+//+build ignore
+
+// msg_generate.go is meant to run with go generate. It will use
+// go/{importer,types} to track down all the RR struct types. Then for each type
+// it will generate pack/unpack methods based on the struct tags. The generated source is
+// written to zmsg.go, and is meant to be checked into git.
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/format"
+ "go/importer"
+ "go/types"
+ "log"
+ "os"
+ "strings"
+)
+
+var packageHdr = `
+// *** DO NOT MODIFY ***
+// AUTOGENERATED BY go generate from msg_generate.go
+
+package dns
+
+`
+
+// getTypeStruct will take a type and the package scope, and return the
+// (innermost) struct if the type is considered a RR type (currently defined as
+// those structs beginning with a RR_Header, could be redefined as implementing
+// the RR interface). The bool return value indicates if embedded structs were
+// resolved.
+func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
+ st, ok := t.Underlying().(*types.Struct)
+ if !ok {
+ return nil, false
+ }
+ if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
+ return st, false
+ }
+ if st.Field(0).Anonymous() {
+ st, _ := getTypeStruct(st.Field(0).Type(), scope)
+ return st, true
+ }
+ return nil, false
+}
+
+func main() {
+ // Import and type-check the package
+ pkg, err := importer.Default().Import("github.com/miekg/dns")
+ fatalIfErr(err)
+ scope := pkg.Scope()
+
+ // Collect actual types (*X)
+ var namedTypes []string
+ for _, name := range scope.Names() {
+ o := scope.Lookup(name)
+ if o == nil || !o.Exported() {
+ continue
+ }
+ if st, _ := getTypeStruct(o.Type(), scope); st == nil {
+ continue
+ }
+ if name == "PrivateRR" {
+ continue
+ }
+
+ // Check if corresponding TypeX exists
+ if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
+ log.Fatalf("Constant Type%s does not exist.", o.Name())
+ }
+
+ namedTypes = append(namedTypes, o.Name())
+ }
+
+ b := &bytes.Buffer{}
+ b.WriteString(packageHdr)
+
+ fmt.Fprint(b, "// pack*() functions\n\n")
+ for _, name := range namedTypes {
+ o := scope.Lookup(name)
+ st, _ := getTypeStruct(o.Type(), scope)
+
+ fmt.Fprintf(b, "func (rr *%s) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {\n", name)
+ fmt.Fprint(b, `off, err := rr.Hdr.pack(msg, off, compression, compress)
+if err != nil {
+ return off, err
+}
+headerEnd := off
+`)
+ for i := 1; i < st.NumFields(); i++ {
+ o := func(s string) {
+ fmt.Fprintf(b, s, st.Field(i).Name())
+ fmt.Fprint(b, `if err != nil {
+return off, err
+}
+`)
+ }
+
+ if _, ok := st.Field(i).Type().(*types.Slice); ok {
+ switch st.Tag(i) {
+ case `dns:"-"`: // ignored
+ case `dns:"txt"`:
+ o("off, err = packStringTxt(rr.%s, msg, off)\n")
+ case `dns:"opt"`:
+ o("off, err = packDataOpt(rr.%s, msg, off)\n")
+ case `dns:"nsec"`:
+ o("off, err = packDataNsec(rr.%s, msg, off)\n")
+ case `dns:"domain-name"`:
+ o("off, err = packDataDomainNames(rr.%s, msg, off, compression, compress)\n")
+ default:
+ log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
+ }
+ continue
+ }
+
+ switch {
+ case st.Tag(i) == `dns:"-"`: // ignored
+ case st.Tag(i) == `dns:"cdomain-name"`:
+ o("off, err = PackDomainName(rr.%s, msg, off, compression, compress)\n")
+ case st.Tag(i) == `dns:"domain-name"`:
+ o("off, err = PackDomainName(rr.%s, msg, off, compression, false)\n")
+ case st.Tag(i) == `dns:"a"`:
+ o("off, err = packDataA(rr.%s, msg, off)\n")
+ case st.Tag(i) == `dns:"aaaa"`:
+ o("off, err = packDataAAAA(rr.%s, msg, off)\n")
+ case st.Tag(i) == `dns:"uint48"`:
+ o("off, err = packUint48(rr.%s, msg, off)\n")
+ case st.Tag(i) == `dns:"txt"`:
+ o("off, err = packString(rr.%s, msg, off)\n")
+
+ case strings.HasPrefix(st.Tag(i), `dns:"size-base32`): // size-base32 can be packed just like base32
+ fallthrough
+ case st.Tag(i) == `dns:"base32"`:
+ o("off, err = packStringBase32(rr.%s, msg, off)\n")
+
+ case strings.HasPrefix(st.Tag(i), `dns:"size-base64`): // size-base64 can be packed just like base64
+ fallthrough
+ case st.Tag(i) == `dns:"base64"`:
+ o("off, err = packStringBase64(rr.%s, msg, off)\n")
+
+ case strings.HasPrefix(st.Tag(i), `dns:"size-hex:SaltLength`):
+ // directly write instead of using o() so we get the error check in the correct place
+ field := st.Field(i).Name()
+ fmt.Fprintf(b, `// Only pack salt if value is not "-", i.e. empty
+if rr.%s != "-" {
+ off, err = packStringHex(rr.%s, msg, off)
+ if err != nil {
+ return off, err
+ }
+}
+`, field, field)
+ continue
+ case strings.HasPrefix(st.Tag(i), `dns:"size-hex`): // size-hex can be packed just like hex
+ fallthrough
+ case st.Tag(i) == `dns:"hex"`:
+ o("off, err = packStringHex(rr.%s, msg, off)\n")
+
+ case st.Tag(i) == `dns:"octet"`:
+ o("off, err = packStringOctet(rr.%s, msg, off)\n")
+ case st.Tag(i) == "":
+ switch st.Field(i).Type().(*types.Basic).Kind() {
+ case types.Uint8:
+ o("off, err = packUint8(rr.%s, msg, off)\n")
+ case types.Uint16:
+ o("off, err = packUint16(rr.%s, msg, off)\n")
+ case types.Uint32:
+ o("off, err = packUint32(rr.%s, msg, off)\n")
+ case types.Uint64:
+ o("off, err = packUint64(rr.%s, msg, off)\n")
+ case types.String:
+ o("off, err = packString(rr.%s, msg, off)\n")
+ default:
+ log.Fatalln(name, st.Field(i).Name())
+ }
+ default:
+ log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
+ }
+ }
+ // We have packed everything, only now we know the rdlength of this RR
+ fmt.Fprintln(b, "rr.Header().Rdlength = uint16(off-headerEnd)")
+ fmt.Fprintln(b, "return off, nil }\n")
+ }
+
+ fmt.Fprint(b, "// unpack*() functions\n\n")
+ for _, name := range namedTypes {
+ o := scope.Lookup(name)
+ st, _ := getTypeStruct(o.Type(), scope)
+
+ fmt.Fprintf(b, "func unpack%s(h RR_Header, msg []byte, off int) (RR, int, error) {\n", name)
+ fmt.Fprintf(b, "rr := new(%s)\n", name)
+ fmt.Fprint(b, "rr.Hdr = h\n")
+ fmt.Fprint(b, `if noRdata(h) {
+return rr, off, nil
+ }
+var err error
+rdStart := off
+_ = rdStart
+
+`)
+ for i := 1; i < st.NumFields(); i++ {
+ o := func(s string) {
+ fmt.Fprintf(b, s, st.Field(i).Name())
+ fmt.Fprint(b, `if err != nil {
+return rr, off, err
+}
+`)
+ }
+
+ // size-* are special, because they reference a struct member we should use for the length.
+ if strings.HasPrefix(st.Tag(i), `dns:"size-`) {
+ structMember := structMember(st.Tag(i))
+ structTag := structTag(st.Tag(i))
+ switch structTag {
+ case "hex":
+ fmt.Fprintf(b, "rr.%s, off, err = unpackStringHex(msg, off, off + int(rr.%s))\n", st.Field(i).Name(), structMember)
+ case "base32":
+ fmt.Fprintf(b, "rr.%s, off, err = unpackStringBase32(msg, off, off + int(rr.%s))\n", st.Field(i).Name(), structMember)
+ case "base64":
+ fmt.Fprintf(b, "rr.%s, off, err = unpackStringBase64(msg, off, off + int(rr.%s))\n", st.Field(i).Name(), structMember)
+ default:
+ log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
+ }
+ fmt.Fprint(b, `if err != nil {
+return rr, off, err
+}
+`)
+ continue
+ }
+
+ if _, ok := st.Field(i).Type().(*types.Slice); ok {
+ switch st.Tag(i) {
+ case `dns:"-"`: // ignored
+ case `dns:"txt"`:
+ o("rr.%s, off, err = unpackStringTxt(msg, off)\n")
+ case `dns:"opt"`:
+ o("rr.%s, off, err = unpackDataOpt(msg, off)\n")
+ case `dns:"nsec"`:
+ o("rr.%s, off, err = unpackDataNsec(msg, off)\n")
+ case `dns:"domain-name"`:
+ o("rr.%s, off, err = unpackDataDomainNames(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
+ default:
+ log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
+ }
+ continue
+ }
+
+ switch st.Tag(i) {
+ case `dns:"-"`: // ignored
+ case `dns:"cdomain-name"`:
+ fallthrough
+ case `dns:"domain-name"`:
+ o("rr.%s, off, err = UnpackDomainName(msg, off)\n")
+ case `dns:"a"`:
+ o("rr.%s, off, err = unpackDataA(msg, off)\n")
+ case `dns:"aaaa"`:
+ o("rr.%s, off, err = unpackDataAAAA(msg, off)\n")
+ case `dns:"uint48"`:
+ o("rr.%s, off, err = unpackUint48(msg, off)\n")
+ case `dns:"txt"`:
+ o("rr.%s, off, err = unpackString(msg, off)\n")
+ case `dns:"base32"`:
+ o("rr.%s, off, err = unpackStringBase32(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
+ case `dns:"base64"`:
+ o("rr.%s, off, err = unpackStringBase64(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
+ case `dns:"hex"`:
+ o("rr.%s, off, err = unpackStringHex(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
+ case `dns:"octet"`:
+ o("rr.%s, off, err = unpackStringOctet(msg, off)\n")
+ case "":
+ switch st.Field(i).Type().(*types.Basic).Kind() {
+ case types.Uint8:
+ o("rr.%s, off, err = unpackUint8(msg, off)\n")
+ case types.Uint16:
+ o("rr.%s, off, err = unpackUint16(msg, off)\n")
+ case types.Uint32:
+ o("rr.%s, off, err = unpackUint32(msg, off)\n")
+ case types.Uint64:
+ o("rr.%s, off, err = unpackUint64(msg, off)\n")
+ case types.String:
+ o("rr.%s, off, err = unpackString(msg, off)\n")
+ default:
+ log.Fatalln(name, st.Field(i).Name())
+ }
+ default:
+ log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
+ }
+ // If we've hit len(msg) we return without error.
+ if i < st.NumFields()-1 {
+ fmt.Fprintf(b, `if off == len(msg) {
+return rr, off, nil
+ }
+`)
+ }
+ }
+ fmt.Fprintf(b, "return rr, off, err }\n\n")
+ }
+ // Generate typeToUnpack map
+ fmt.Fprintln(b, "var typeToUnpack = map[uint16]func(RR_Header, []byte, int) (RR, int, error){")
+ for _, name := range namedTypes {
+ if name == "RFC3597" {
+ continue
+ }
+ fmt.Fprintf(b, "Type%s: unpack%s,\n", name, name)
+ }
+ fmt.Fprintln(b, "}\n")
+
+ // gofmt
+ res, err := format.Source(b.Bytes())
+ if err != nil {
+ b.WriteTo(os.Stderr)
+ log.Fatal(err)
+ }
+
+ // write result
+ f, err := os.Create("zmsg.go")
+ fatalIfErr(err)
+ defer f.Close()
+ f.Write(res)
+}
+
+// structMember will take a tag like dns:"size-base32:SaltLength" and return the last part of this string.
+func structMember(s string) string {
+ fields := strings.Split(s, ":")
+ if len(fields) == 0 {
+ return ""
+ }
+ f := fields[len(fields)-1]
+ // f should have a closing "
+ if len(f) > 1 {
+ return f[:len(f)-1]
+ }
+ return f
+}
+
+// structTag will take a tag like dns:"size-base32:SaltLength" and return base32.
+func structTag(s string) string {
+ fields := strings.Split(s, ":")
+ if len(fields) < 2 {
+ return ""
+ }
+ return fields[1][len("\"size-"):]
+}
+
+func fatalIfErr(err error) {
+ if err != nil {
+ log.Fatal(err)
+ }
+}
--- /dev/null
+package dns
+
+import (
+ "encoding/base32"
+ "encoding/base64"
+ "encoding/binary"
+ "encoding/hex"
+ "net"
+ "strconv"
+)
+
+// helper functions called from the generated zmsg.go
+
+// These function are named after the tag to help pack/unpack, if there is no tag it is the name
+// of the type they pack/unpack (string, int, etc). We prefix all with unpackData or packData, so packDataA or
+// packDataDomainName.
+
+func unpackDataA(msg []byte, off int) (net.IP, int, error) {
+ if off+net.IPv4len > len(msg) {
+ return nil, len(msg), &Error{err: "overflow unpacking a"}
+ }
+ a := append(make(net.IP, 0, net.IPv4len), msg[off:off+net.IPv4len]...)
+ off += net.IPv4len
+ return a, off, nil
+}
+
+func packDataA(a net.IP, msg []byte, off int) (int, error) {
+ // It must be a slice of 4, even if it is 16, we encode only the first 4
+ if off+net.IPv4len > len(msg) {
+ return len(msg), &Error{err: "overflow packing a"}
+ }
+ switch len(a) {
+ case net.IPv4len, net.IPv6len:
+ copy(msg[off:], a.To4())
+ off += net.IPv4len
+ case 0:
+ // Allowed, for dynamic updates.
+ default:
+ return len(msg), &Error{err: "overflow packing a"}
+ }
+ return off, nil
+}
+
+func unpackDataAAAA(msg []byte, off int) (net.IP, int, error) {
+ if off+net.IPv6len > len(msg) {
+ return nil, len(msg), &Error{err: "overflow unpacking aaaa"}
+ }
+ aaaa := append(make(net.IP, 0, net.IPv6len), msg[off:off+net.IPv6len]...)
+ off += net.IPv6len
+ return aaaa, off, nil
+}
+
+func packDataAAAA(aaaa net.IP, msg []byte, off int) (int, error) {
+ if off+net.IPv6len > len(msg) {
+ return len(msg), &Error{err: "overflow packing aaaa"}
+ }
+
+ switch len(aaaa) {
+ case net.IPv6len:
+ copy(msg[off:], aaaa)
+ off += net.IPv6len
+ case 0:
+ // Allowed, dynamic updates.
+ default:
+ return len(msg), &Error{err: "overflow packing aaaa"}
+ }
+ return off, nil
+}
+
+// unpackHeader unpacks an RR header, returning the offset to the end of the header and a
+// re-sliced msg according to the expected length of the RR.
+func unpackHeader(msg []byte, off int) (rr RR_Header, off1 int, truncmsg []byte, err error) {
+ hdr := RR_Header{}
+ if off == len(msg) {
+ return hdr, off, msg, nil
+ }
+
+ hdr.Name, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return hdr, len(msg), msg, err
+ }
+ hdr.Rrtype, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return hdr, len(msg), msg, err
+ }
+ hdr.Class, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return hdr, len(msg), msg, err
+ }
+ hdr.Ttl, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return hdr, len(msg), msg, err
+ }
+ hdr.Rdlength, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return hdr, len(msg), msg, err
+ }
+ msg, err = truncateMsgFromRdlength(msg, off, hdr.Rdlength)
+ return hdr, off, msg, err
+}
+
+// pack packs an RR header, returning the offset to the end of the header.
+// See PackDomainName for documentation about the compression.
+func (hdr RR_Header) pack(msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
+ if off == len(msg) {
+ return off, nil
+ }
+
+ off, err = PackDomainName(hdr.Name, msg, off, compression, compress)
+ if err != nil {
+ return len(msg), err
+ }
+ off, err = packUint16(hdr.Rrtype, msg, off)
+ if err != nil {
+ return len(msg), err
+ }
+ off, err = packUint16(hdr.Class, msg, off)
+ if err != nil {
+ return len(msg), err
+ }
+ off, err = packUint32(hdr.Ttl, msg, off)
+ if err != nil {
+ return len(msg), err
+ }
+ off, err = packUint16(hdr.Rdlength, msg, off)
+ if err != nil {
+ return len(msg), err
+ }
+ return off, nil
+}
+
+// helper helper functions.
+
+// truncateMsgFromRdLength truncates msg to match the expected length of the RR.
+// Returns an error if msg is smaller than the expected size.
+func truncateMsgFromRdlength(msg []byte, off int, rdlength uint16) (truncmsg []byte, err error) {
+ lenrd := off + int(rdlength)
+ if lenrd > len(msg) {
+ return msg, &Error{err: "overflowing header size"}
+ }
+ return msg[:lenrd], nil
+}
+
+func fromBase32(s []byte) (buf []byte, err error) {
+ for i, b := range s {
+ if b >= 'a' && b <= 'z' {
+ s[i] = b - 32
+ }
+ }
+ buflen := base32.HexEncoding.DecodedLen(len(s))
+ buf = make([]byte, buflen)
+ n, err := base32.HexEncoding.Decode(buf, s)
+ buf = buf[:n]
+ return
+}
+
+func toBase32(b []byte) string { return base32.HexEncoding.EncodeToString(b) }
+
+func fromBase64(s []byte) (buf []byte, err error) {
+ buflen := base64.StdEncoding.DecodedLen(len(s))
+ buf = make([]byte, buflen)
+ n, err := base64.StdEncoding.Decode(buf, s)
+ buf = buf[:n]
+ return
+}
+
+func toBase64(b []byte) string { return base64.StdEncoding.EncodeToString(b) }
+
+// dynamicUpdate returns true if the Rdlength is zero.
+func noRdata(h RR_Header) bool { return h.Rdlength == 0 }
+
+func unpackUint8(msg []byte, off int) (i uint8, off1 int, err error) {
+ if off+1 > len(msg) {
+ return 0, len(msg), &Error{err: "overflow unpacking uint8"}
+ }
+ return uint8(msg[off]), off + 1, nil
+}
+
+func packUint8(i uint8, msg []byte, off int) (off1 int, err error) {
+ if off+1 > len(msg) {
+ return len(msg), &Error{err: "overflow packing uint8"}
+ }
+ msg[off] = byte(i)
+ return off + 1, nil
+}
+
+func unpackUint16(msg []byte, off int) (i uint16, off1 int, err error) {
+ if off+2 > len(msg) {
+ return 0, len(msg), &Error{err: "overflow unpacking uint16"}
+ }
+ return binary.BigEndian.Uint16(msg[off:]), off + 2, nil
+}
+
+func packUint16(i uint16, msg []byte, off int) (off1 int, err error) {
+ if off+2 > len(msg) {
+ return len(msg), &Error{err: "overflow packing uint16"}
+ }
+ binary.BigEndian.PutUint16(msg[off:], i)
+ return off + 2, nil
+}
+
+func unpackUint32(msg []byte, off int) (i uint32, off1 int, err error) {
+ if off+4 > len(msg) {
+ return 0, len(msg), &Error{err: "overflow unpacking uint32"}
+ }
+ return binary.BigEndian.Uint32(msg[off:]), off + 4, nil
+}
+
+func packUint32(i uint32, msg []byte, off int) (off1 int, err error) {
+ if off+4 > len(msg) {
+ return len(msg), &Error{err: "overflow packing uint32"}
+ }
+ binary.BigEndian.PutUint32(msg[off:], i)
+ return off + 4, nil
+}
+
+func unpackUint48(msg []byte, off int) (i uint64, off1 int, err error) {
+ if off+6 > len(msg) {
+ return 0, len(msg), &Error{err: "overflow unpacking uint64 as uint48"}
+ }
+ // Used in TSIG where the last 48 bits are occupied, so for now, assume a uint48 (6 bytes)
+ i = (uint64(uint64(msg[off])<<40 | uint64(msg[off+1])<<32 | uint64(msg[off+2])<<24 | uint64(msg[off+3])<<16 |
+ uint64(msg[off+4])<<8 | uint64(msg[off+5])))
+ off += 6
+ return i, off, nil
+}
+
+func packUint48(i uint64, msg []byte, off int) (off1 int, err error) {
+ if off+6 > len(msg) {
+ return len(msg), &Error{err: "overflow packing uint64 as uint48"}
+ }
+ msg[off] = byte(i >> 40)
+ msg[off+1] = byte(i >> 32)
+ msg[off+2] = byte(i >> 24)
+ msg[off+3] = byte(i >> 16)
+ msg[off+4] = byte(i >> 8)
+ msg[off+5] = byte(i)
+ off += 6
+ return off, nil
+}
+
+func unpackUint64(msg []byte, off int) (i uint64, off1 int, err error) {
+ if off+8 > len(msg) {
+ return 0, len(msg), &Error{err: "overflow unpacking uint64"}
+ }
+ return binary.BigEndian.Uint64(msg[off:]), off + 8, nil
+}
+
+func packUint64(i uint64, msg []byte, off int) (off1 int, err error) {
+ if off+8 > len(msg) {
+ return len(msg), &Error{err: "overflow packing uint64"}
+ }
+ binary.BigEndian.PutUint64(msg[off:], i)
+ off += 8
+ return off, nil
+}
+
+func unpackString(msg []byte, off int) (string, int, error) {
+ if off+1 > len(msg) {
+ return "", off, &Error{err: "overflow unpacking txt"}
+ }
+ l := int(msg[off])
+ if off+l+1 > len(msg) {
+ return "", off, &Error{err: "overflow unpacking txt"}
+ }
+ s := make([]byte, 0, l)
+ for _, b := range msg[off+1 : off+1+l] {
+ switch b {
+ case '"', '\\':
+ s = append(s, '\\', b)
+ default:
+ if b < 32 || b > 127 { // unprintable
+ var buf [3]byte
+ bufs := strconv.AppendInt(buf[:0], int64(b), 10)
+ s = append(s, '\\')
+ for i := 0; i < 3-len(bufs); i++ {
+ s = append(s, '0')
+ }
+ for _, r := range bufs {
+ s = append(s, r)
+ }
+ } else {
+ s = append(s, b)
+ }
+ }
+ }
+ off += 1 + l
+ return string(s), off, nil
+}
+
+func packString(s string, msg []byte, off int) (int, error) {
+ txtTmp := make([]byte, 256*4+1)
+ off, err := packTxtString(s, msg, off, txtTmp)
+ if err != nil {
+ return len(msg), err
+ }
+ return off, nil
+}
+
+func unpackStringBase32(msg []byte, off, end int) (string, int, error) {
+ if end > len(msg) {
+ return "", len(msg), &Error{err: "overflow unpacking base32"}
+ }
+ s := toBase32(msg[off:end])
+ return s, end, nil
+}
+
+func packStringBase32(s string, msg []byte, off int) (int, error) {
+ b32, err := fromBase32([]byte(s))
+ if err != nil {
+ return len(msg), err
+ }
+ if off+len(b32) > len(msg) {
+ return len(msg), &Error{err: "overflow packing base32"}
+ }
+ copy(msg[off:off+len(b32)], b32)
+ off += len(b32)
+ return off, nil
+}
+
+func unpackStringBase64(msg []byte, off, end int) (string, int, error) {
+ // Rest of the RR is base64 encoded value, so we don't need an explicit length
+ // to be set. Thus far all RR's that have base64 encoded fields have those as their
+ // last one. What we do need is the end of the RR!
+ if end > len(msg) {
+ return "", len(msg), &Error{err: "overflow unpacking base64"}
+ }
+ s := toBase64(msg[off:end])
+ return s, end, nil
+}
+
+func packStringBase64(s string, msg []byte, off int) (int, error) {
+ b64, err := fromBase64([]byte(s))
+ if err != nil {
+ return len(msg), err
+ }
+ if off+len(b64) > len(msg) {
+ return len(msg), &Error{err: "overflow packing base64"}
+ }
+ copy(msg[off:off+len(b64)], b64)
+ off += len(b64)
+ return off, nil
+}
+
+func unpackStringHex(msg []byte, off, end int) (string, int, error) {
+ // Rest of the RR is hex encoded value, so we don't need an explicit length
+ // to be set. NSEC and TSIG have hex fields with a length field.
+ // What we do need is the end of the RR!
+ if end > len(msg) {
+ return "", len(msg), &Error{err: "overflow unpacking hex"}
+ }
+
+ s := hex.EncodeToString(msg[off:end])
+ return s, end, nil
+}
+
+func packStringHex(s string, msg []byte, off int) (int, error) {
+ h, err := hex.DecodeString(s)
+ if err != nil {
+ return len(msg), err
+ }
+ if off+(len(h)) > len(msg) {
+ return len(msg), &Error{err: "overflow packing hex"}
+ }
+ copy(msg[off:off+len(h)], h)
+ off += len(h)
+ return off, nil
+}
+
+func unpackStringTxt(msg []byte, off int) ([]string, int, error) {
+ txt, off, err := unpackTxt(msg, off)
+ if err != nil {
+ return nil, len(msg), err
+ }
+ return txt, off, nil
+}
+
+func packStringTxt(s []string, msg []byte, off int) (int, error) {
+ txtTmp := make([]byte, 256*4+1) // If the whole string consists out of \DDD we need this many.
+ off, err := packTxt(s, msg, off, txtTmp)
+ if err != nil {
+ return len(msg), err
+ }
+ return off, nil
+}
+
+func unpackDataOpt(msg []byte, off int) ([]EDNS0, int, error) {
+ var edns []EDNS0
+Option:
+ code := uint16(0)
+ if off+4 > len(msg) {
+ return nil, len(msg), &Error{err: "overflow unpacking opt"}
+ }
+ code = binary.BigEndian.Uint16(msg[off:])
+ off += 2
+ optlen := binary.BigEndian.Uint16(msg[off:])
+ off += 2
+ if off+int(optlen) > len(msg) {
+ return nil, len(msg), &Error{err: "overflow unpacking opt"}
+ }
+ switch code {
+ case EDNS0NSID:
+ e := new(EDNS0_NSID)
+ if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
+ return nil, len(msg), err
+ }
+ edns = append(edns, e)
+ off += int(optlen)
+ case EDNS0SUBNET, EDNS0SUBNETDRAFT:
+ e := new(EDNS0_SUBNET)
+ if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
+ return nil, len(msg), err
+ }
+ edns = append(edns, e)
+ off += int(optlen)
+ if code == EDNS0SUBNETDRAFT {
+ e.DraftOption = true
+ }
+ case EDNS0COOKIE:
+ e := new(EDNS0_COOKIE)
+ if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
+ return nil, len(msg), err
+ }
+ edns = append(edns, e)
+ off += int(optlen)
+ case EDNS0UL:
+ e := new(EDNS0_UL)
+ if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
+ return nil, len(msg), err
+ }
+ edns = append(edns, e)
+ off += int(optlen)
+ case EDNS0LLQ:
+ e := new(EDNS0_LLQ)
+ if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
+ return nil, len(msg), err
+ }
+ edns = append(edns, e)
+ off += int(optlen)
+ case EDNS0DAU:
+ e := new(EDNS0_DAU)
+ if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
+ return nil, len(msg), err
+ }
+ edns = append(edns, e)
+ off += int(optlen)
+ case EDNS0DHU:
+ e := new(EDNS0_DHU)
+ if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
+ return nil, len(msg), err
+ }
+ edns = append(edns, e)
+ off += int(optlen)
+ case EDNS0N3U:
+ e := new(EDNS0_N3U)
+ if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
+ return nil, len(msg), err
+ }
+ edns = append(edns, e)
+ off += int(optlen)
+ case EDNS0PADDING:
+ e := new(EDNS0_PADDING)
+ if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
+ return nil, len(msg), err
+ }
+ edns = append(edns, e)
+ off += int(optlen)
+ default:
+ e := new(EDNS0_LOCAL)
+ e.Code = code
+ if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
+ return nil, len(msg), err
+ }
+ edns = append(edns, e)
+ off += int(optlen)
+ }
+
+ if off < len(msg) {
+ goto Option
+ }
+
+ return edns, off, nil
+}
+
+func packDataOpt(options []EDNS0, msg []byte, off int) (int, error) {
+ for _, el := range options {
+ b, err := el.pack()
+ if err != nil || off+3 > len(msg) {
+ return len(msg), &Error{err: "overflow packing opt"}
+ }
+ binary.BigEndian.PutUint16(msg[off:], el.Option()) // Option code
+ binary.BigEndian.PutUint16(msg[off+2:], uint16(len(b))) // Length
+ off += 4
+ if off+len(b) > len(msg) {
+ copy(msg[off:], b)
+ off = len(msg)
+ continue
+ }
+ // Actual data
+ copy(msg[off:off+len(b)], b)
+ off += len(b)
+ }
+ return off, nil
+}
+
+func unpackStringOctet(msg []byte, off int) (string, int, error) {
+ s := string(msg[off:])
+ return s, len(msg), nil
+}
+
+func packStringOctet(s string, msg []byte, off int) (int, error) {
+ txtTmp := make([]byte, 256*4+1)
+ off, err := packOctetString(s, msg, off, txtTmp)
+ if err != nil {
+ return len(msg), err
+ }
+ return off, nil
+}
+
+func unpackDataNsec(msg []byte, off int) ([]uint16, int, error) {
+ var nsec []uint16
+ length, window, lastwindow := 0, 0, -1
+ for off < len(msg) {
+ if off+2 > len(msg) {
+ return nsec, len(msg), &Error{err: "overflow unpacking nsecx"}
+ }
+ window = int(msg[off])
+ length = int(msg[off+1])
+ off += 2
+ if window <= lastwindow {
+ // RFC 4034: Blocks are present in the NSEC RR RDATA in
+ // increasing numerical order.
+ return nsec, len(msg), &Error{err: "out of order NSEC block"}
+ }
+ if length == 0 {
+ // RFC 4034: Blocks with no types present MUST NOT be included.
+ return nsec, len(msg), &Error{err: "empty NSEC block"}
+ }
+ if length > 32 {
+ return nsec, len(msg), &Error{err: "NSEC block too long"}
+ }
+ if off+length > len(msg) {
+ return nsec, len(msg), &Error{err: "overflowing NSEC block"}
+ }
+
+ // Walk the bytes in the window and extract the type bits
+ for j := 0; j < length; j++ {
+ b := msg[off+j]
+ // Check the bits one by one, and set the type
+ if b&0x80 == 0x80 {
+ nsec = append(nsec, uint16(window*256+j*8+0))
+ }
+ if b&0x40 == 0x40 {
+ nsec = append(nsec, uint16(window*256+j*8+1))
+ }
+ if b&0x20 == 0x20 {
+ nsec = append(nsec, uint16(window*256+j*8+2))
+ }
+ if b&0x10 == 0x10 {
+ nsec = append(nsec, uint16(window*256+j*8+3))
+ }
+ if b&0x8 == 0x8 {
+ nsec = append(nsec, uint16(window*256+j*8+4))
+ }
+ if b&0x4 == 0x4 {
+ nsec = append(nsec, uint16(window*256+j*8+5))
+ }
+ if b&0x2 == 0x2 {
+ nsec = append(nsec, uint16(window*256+j*8+6))
+ }
+ if b&0x1 == 0x1 {
+ nsec = append(nsec, uint16(window*256+j*8+7))
+ }
+ }
+ off += length
+ lastwindow = window
+ }
+ return nsec, off, nil
+}
+
+func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
+ if len(bitmap) == 0 {
+ return off, nil
+ }
+ var lastwindow, lastlength uint16
+ for j := 0; j < len(bitmap); j++ {
+ t := bitmap[j]
+ window := t / 256
+ length := (t-window*256)/8 + 1
+ if window > lastwindow && lastlength != 0 { // New window, jump to the new offset
+ off += int(lastlength) + 2
+ lastlength = 0
+ }
+ if window < lastwindow || length < lastlength {
+ return len(msg), &Error{err: "nsec bits out of order"}
+ }
+ if off+2+int(length) > len(msg) {
+ return len(msg), &Error{err: "overflow packing nsec"}
+ }
+ // Setting the window #
+ msg[off] = byte(window)
+ // Setting the octets length
+ msg[off+1] = byte(length)
+ // Setting the bit value for the type in the right octet
+ msg[off+1+int(length)] |= byte(1 << (7 - (t % 8)))
+ lastwindow, lastlength = window, length
+ }
+ off += int(lastlength) + 2
+ return off, nil
+}
+
+func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) {
+ var (
+ servers []string
+ s string
+ err error
+ )
+ if end > len(msg) {
+ return nil, len(msg), &Error{err: "overflow unpacking domain names"}
+ }
+ for off < end {
+ s, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return servers, len(msg), err
+ }
+ servers = append(servers, s)
+ }
+ return servers, off, nil
+}
+
+func packDataDomainNames(names []string, msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ var err error
+ for j := 0; j < len(names); j++ {
+ off, err = PackDomainName(names[j], msg, off, compression, false && compress)
+ if err != nil {
+ return len(msg), err
+ }
+ }
+ return off, nil
+}
--- /dev/null
+package dns
+
+import (
+ "crypto/sha1"
+ "hash"
+ "strings"
+)
+
+type saltWireFmt struct {
+ Salt string `dns:"size-hex"`
+}
+
+// HashName hashes a string (label) according to RFC 5155. It returns the hashed string in uppercase.
+func HashName(label string, ha uint8, iter uint16, salt string) string {
+ saltwire := new(saltWireFmt)
+ saltwire.Salt = salt
+ wire := make([]byte, DefaultMsgSize)
+ n, err := packSaltWire(saltwire, wire)
+ if err != nil {
+ return ""
+ }
+ wire = wire[:n]
+ name := make([]byte, 255)
+ off, err := PackDomainName(strings.ToLower(label), name, 0, nil, false)
+ if err != nil {
+ return ""
+ }
+ name = name[:off]
+ var s hash.Hash
+ switch ha {
+ case SHA1:
+ s = sha1.New()
+ default:
+ return ""
+ }
+
+ // k = 0
+ s.Write(name)
+ s.Write(wire)
+ nsec3 := s.Sum(nil)
+ // k > 0
+ for k := uint16(0); k < iter; k++ {
+ s.Reset()
+ s.Write(nsec3)
+ s.Write(wire)
+ nsec3 = s.Sum(nsec3[:0])
+ }
+ return toBase32(nsec3)
+}
+
+// Cover returns true if a name is covered by the NSEC3 record
+func (rr *NSEC3) Cover(name string) bool {
+ nameHash := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
+ owner := strings.ToUpper(rr.Hdr.Name)
+ labelIndices := Split(owner)
+ if len(labelIndices) < 2 {
+ return false
+ }
+ ownerHash := owner[:labelIndices[1]-1]
+ ownerZone := owner[labelIndices[1]:]
+ if !IsSubDomain(ownerZone, strings.ToUpper(name)) { // name is outside owner zone
+ return false
+ }
+
+ nextHash := rr.NextDomain
+ if ownerHash == nextHash { // empty interval
+ return false
+ }
+ if ownerHash > nextHash { // end of zone
+ if nameHash > ownerHash { // covered since there is nothing after ownerHash
+ return true
+ }
+ return nameHash < nextHash // if nameHash is before beginning of zone it is covered
+ }
+ if nameHash < ownerHash { // nameHash is before ownerHash, not covered
+ return false
+ }
+ return nameHash < nextHash // if nameHash is before nextHash is it covered (between ownerHash and nextHash)
+}
+
+// Match returns true if a name matches the NSEC3 record
+func (rr *NSEC3) Match(name string) bool {
+ nameHash := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
+ owner := strings.ToUpper(rr.Hdr.Name)
+ labelIndices := Split(owner)
+ if len(labelIndices) < 2 {
+ return false
+ }
+ ownerHash := owner[:labelIndices[1]-1]
+ ownerZone := owner[labelIndices[1]:]
+ if !IsSubDomain(ownerZone, strings.ToUpper(name)) { // name is outside owner zone
+ return false
+ }
+ if ownerHash == nameHash {
+ return true
+ }
+ return false
+}
+
+func packSaltWire(sw *saltWireFmt, msg []byte) (int, error) {
+ off, err := packStringHex(sw.Salt, msg, 0)
+ if err != nil {
+ return off, err
+ }
+ return off, nil
+}
--- /dev/null
+package dns
+
+import (
+ "fmt"
+ "strings"
+)
+
+// PrivateRdata is an interface used for implementing "Private Use" RR types, see
+// RFC 6895. This allows one to experiment with new RR types, without requesting an
+// official type code. Also see dns.PrivateHandle and dns.PrivateHandleRemove.
+type PrivateRdata interface {
+ // String returns the text presentaton of the Rdata of the Private RR.
+ String() string
+ // Parse parses the Rdata of the private RR.
+ Parse([]string) error
+ // Pack is used when packing a private RR into a buffer.
+ Pack([]byte) (int, error)
+ // Unpack is used when unpacking a private RR from a buffer.
+ // TODO(miek): diff. signature than Pack, see edns0.go for instance.
+ Unpack([]byte) (int, error)
+ // Copy copies the Rdata.
+ Copy(PrivateRdata) error
+ // Len returns the length in octets of the Rdata.
+ Len() int
+}
+
+// PrivateRR represents an RR that uses a PrivateRdata user-defined type.
+// It mocks normal RRs and implements dns.RR interface.
+type PrivateRR struct {
+ Hdr RR_Header
+ Data PrivateRdata
+}
+
+func mkPrivateRR(rrtype uint16) *PrivateRR {
+ // Panics if RR is not an instance of PrivateRR.
+ rrfunc, ok := TypeToRR[rrtype]
+ if !ok {
+ panic(fmt.Sprintf("dns: invalid operation with Private RR type %d", rrtype))
+ }
+
+ anyrr := rrfunc()
+ switch rr := anyrr.(type) {
+ case *PrivateRR:
+ return rr
+ }
+ panic(fmt.Sprintf("dns: RR is not a PrivateRR, TypeToRR[%d] generator returned %T", rrtype, anyrr))
+}
+
+// Header return the RR header of r.
+func (r *PrivateRR) Header() *RR_Header { return &r.Hdr }
+
+func (r *PrivateRR) String() string { return r.Hdr.String() + r.Data.String() }
+
+// Private len and copy parts to satisfy RR interface.
+func (r *PrivateRR) len() int { return r.Hdr.len() + r.Data.Len() }
+func (r *PrivateRR) copy() RR {
+ // make new RR like this:
+ rr := mkPrivateRR(r.Hdr.Rrtype)
+ newh := r.Hdr.copyHeader()
+ rr.Hdr = *newh
+
+ err := r.Data.Copy(rr.Data)
+ if err != nil {
+ panic("dns: got value that could not be used to copy Private rdata")
+ }
+ return rr
+}
+func (r *PrivateRR) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := r.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ n, err := r.Data.Pack(msg[off:])
+ if err != nil {
+ return len(msg), err
+ }
+ off += n
+ r.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+// PrivateHandle registers a private resource record type. It requires
+// string and numeric representation of private RR type and generator function as argument.
+func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) {
+ rtypestr = strings.ToUpper(rtypestr)
+
+ TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator()} }
+ TypeToString[rtype] = rtypestr
+ StringToType[rtypestr] = rtype
+
+ typeToUnpack[rtype] = func(h RR_Header, msg []byte, off int) (RR, int, error) {
+ if noRdata(h) {
+ return &h, off, nil
+ }
+ var err error
+
+ rr := mkPrivateRR(h.Rrtype)
+ rr.Hdr = h
+
+ off1, err := rr.Data.Unpack(msg[off:])
+ off += off1
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+ }
+
+ setPrivateRR := func(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := mkPrivateRR(h.Rrtype)
+ rr.Hdr = h
+
+ var l lex
+ text := make([]string, 0, 2) // could be 0..N elements, median is probably 1
+ Fetch:
+ for {
+ // TODO(miek): we could also be returning _QUOTE, this might or might not
+ // be an issue (basically parsing TXT becomes hard)
+ switch l = <-c; l.value {
+ case zNewline, zEOF:
+ break Fetch
+ case zString:
+ text = append(text, l.token)
+ }
+ }
+
+ err := rr.Data.Parse(text)
+ if err != nil {
+ return nil, &ParseError{f, err.Error(), l}, ""
+ }
+
+ return rr, nil, ""
+ }
+
+ typeToparserFunc[rtype] = parserFunc{setPrivateRR, true}
+}
+
+// PrivateHandleRemove removes defenitions required to support private RR type.
+func PrivateHandleRemove(rtype uint16) {
+ rtypestr, ok := TypeToString[rtype]
+ if ok {
+ delete(TypeToRR, rtype)
+ delete(TypeToString, rtype)
+ delete(typeToparserFunc, rtype)
+ delete(StringToType, rtypestr)
+ delete(typeToUnpack, rtype)
+ }
+ return
+}
--- /dev/null
+package dns
+
+import "encoding/binary"
+
+// rawSetRdlength sets the rdlength in the header of
+// the RR. The offset 'off' must be positioned at the
+// start of the header of the RR, 'end' must be the
+// end of the RR.
+func rawSetRdlength(msg []byte, off, end int) bool {
+ l := len(msg)
+Loop:
+ for {
+ if off+1 > l {
+ return false
+ }
+ c := int(msg[off])
+ off++
+ switch c & 0xC0 {
+ case 0x00:
+ if c == 0x00 {
+ // End of the domainname
+ break Loop
+ }
+ if off+c > l {
+ return false
+ }
+ off += c
+
+ case 0xC0:
+ // pointer, next byte included, ends domainname
+ off++
+ break Loop
+ }
+ }
+ // The domainname has been seen, we at the start of the fixed part in the header.
+ // Type is 2 bytes, class is 2 bytes, ttl 4 and then 2 bytes for the length.
+ off += 2 + 2 + 4
+ if off+2 > l {
+ return false
+ }
+ //off+1 is the end of the header, 'end' is the end of the rr
+ //so 'end' - 'off+2' is the length of the rdata
+ rdatalen := end - (off + 2)
+ if rdatalen > 0xFFFF {
+ return false
+ }
+ binary.BigEndian.PutUint16(msg[off:], uint16(rdatalen))
+ return true
+}
--- /dev/null
+package dns
+
+// StringToType is the reverse of TypeToString, needed for string parsing.
+var StringToType = reverseInt16(TypeToString)
+
+// StringToClass is the reverse of ClassToString, needed for string parsing.
+var StringToClass = reverseInt16(ClassToString)
+
+// StringToOpcode is a map of opcodes to strings.
+var StringToOpcode = reverseInt(OpcodeToString)
+
+// StringToRcode is a map of rcodes to strings.
+var StringToRcode = reverseInt(RcodeToString)
+
+// Reverse a map
+func reverseInt8(m map[uint8]string) map[string]uint8 {
+ n := make(map[string]uint8, len(m))
+ for u, s := range m {
+ n[s] = u
+ }
+ return n
+}
+
+func reverseInt16(m map[uint16]string) map[string]uint16 {
+ n := make(map[string]uint16, len(m))
+ for u, s := range m {
+ n[s] = u
+ }
+ return n
+}
+
+func reverseInt(m map[int]string) map[string]int {
+ n := make(map[string]int, len(m))
+ for u, s := range m {
+ n[s] = u
+ }
+ return n
+}
--- /dev/null
+package dns
+
+// Dedup removes identical RRs from rrs. It preserves the original ordering.
+// The lowest TTL of any duplicates is used in the remaining one. Dedup modifies
+// rrs.
+// m is used to store the RRs temporay. If it is nil a new map will be allocated.
+func Dedup(rrs []RR, m map[string]RR) []RR {
+ if m == nil {
+ m = make(map[string]RR)
+ }
+ // Save the keys, so we don't have to call normalizedString twice.
+ keys := make([]*string, 0, len(rrs))
+
+ for _, r := range rrs {
+ key := normalizedString(r)
+ keys = append(keys, &key)
+ if _, ok := m[key]; ok {
+ // Shortest TTL wins.
+ if m[key].Header().Ttl > r.Header().Ttl {
+ m[key].Header().Ttl = r.Header().Ttl
+ }
+ continue
+ }
+
+ m[key] = r
+ }
+ // If the length of the result map equals the amount of RRs we got,
+ // it means they were all different. We can then just return the original rrset.
+ if len(m) == len(rrs) {
+ return rrs
+ }
+
+ j := 0
+ for i, r := range rrs {
+ // If keys[i] lives in the map, we should copy and remove it.
+ if _, ok := m[*keys[i]]; ok {
+ delete(m, *keys[i])
+ rrs[j] = r
+ j++
+ }
+
+ if len(m) == 0 {
+ break
+ }
+ }
+
+ return rrs[:j]
+}
+
+// normalizedString returns a normalized string from r. The TTL
+// is removed and the domain name is lowercased. We go from this:
+// DomainName<TAB>TTL<TAB>CLASS<TAB>TYPE<TAB>RDATA to:
+// lowercasename<TAB>CLASS<TAB>TYPE...
+func normalizedString(r RR) string {
+ // A string Go DNS makes has: domainname<TAB>TTL<TAB>...
+ b := []byte(r.String())
+
+ // find the first non-escaped tab, then another, so we capture where the TTL lives.
+ esc := false
+ ttlStart, ttlEnd := 0, 0
+ for i := 0; i < len(b) && ttlEnd == 0; i++ {
+ switch {
+ case b[i] == '\\':
+ esc = !esc
+ case b[i] == '\t' && !esc:
+ if ttlStart == 0 {
+ ttlStart = i
+ continue
+ }
+ if ttlEnd == 0 {
+ ttlEnd = i
+ }
+ case b[i] >= 'A' && b[i] <= 'Z' && !esc:
+ b[i] += 32
+ default:
+ esc = false
+ }
+ }
+
+ // remove TTL.
+ copy(b[ttlStart:], b[ttlEnd:])
+ cut := ttlEnd - ttlStart
+ return string(b[:len(b)-cut])
+}
--- /dev/null
+package dns
+
+import (
+ "io"
+ "log"
+ "os"
+ "strconv"
+ "strings"
+)
+
+type debugging bool
+
+const debug debugging = false
+
+func (d debugging) Printf(format string, args ...interface{}) {
+ if d {
+ log.Printf(format, args...)
+ }
+}
+
+const maxTok = 2048 // Largest token we can return.
+const maxUint16 = 1<<16 - 1
+
+// Tokinize a RFC 1035 zone file. The tokenizer will normalize it:
+// * Add ownernames if they are left blank;
+// * Suppress sequences of spaces;
+// * Make each RR fit on one line (_NEWLINE is send as last)
+// * Handle comments: ;
+// * Handle braces - anywhere.
+const (
+ // Zonefile
+ zEOF = iota
+ zString
+ zBlank
+ zQuote
+ zNewline
+ zRrtpe
+ zOwner
+ zClass
+ zDirOrigin // $ORIGIN
+ zDirTTL // $TTL
+ zDirInclude // $INCLUDE
+ zDirGenerate // $GENERATE
+
+ // Privatekey file
+ zValue
+ zKey
+
+ zExpectOwnerDir // Ownername
+ zExpectOwnerBl // Whitespace after the ownername
+ zExpectAny // Expect rrtype, ttl or class
+ zExpectAnyNoClass // Expect rrtype or ttl
+ zExpectAnyNoClassBl // The whitespace after _EXPECT_ANY_NOCLASS
+ zExpectAnyNoTTL // Expect rrtype or class
+ zExpectAnyNoTTLBl // Whitespace after _EXPECT_ANY_NOTTL
+ zExpectRrtype // Expect rrtype
+ zExpectRrtypeBl // Whitespace BEFORE rrtype
+ zExpectRdata // The first element of the rdata
+ zExpectDirTTLBl // Space after directive $TTL
+ zExpectDirTTL // Directive $TTL
+ zExpectDirOriginBl // Space after directive $ORIGIN
+ zExpectDirOrigin // Directive $ORIGIN
+ zExpectDirIncludeBl // Space after directive $INCLUDE
+ zExpectDirInclude // Directive $INCLUDE
+ zExpectDirGenerate // Directive $GENERATE
+ zExpectDirGenerateBl // Space after directive $GENERATE
+)
+
+// ParseError is a parsing error. It contains the parse error and the location in the io.Reader
+// where the error occurred.
+type ParseError struct {
+ file string
+ err string
+ lex lex
+}
+
+func (e *ParseError) Error() (s string) {
+ if e.file != "" {
+ s = e.file + ": "
+ }
+ s += "dns: " + e.err + ": " + strconv.QuoteToASCII(e.lex.token) + " at line: " +
+ strconv.Itoa(e.lex.line) + ":" + strconv.Itoa(e.lex.column)
+ return
+}
+
+type lex struct {
+ token string // text of the token
+ tokenUpper string // uppercase text of the token
+ length int // length of the token
+ err bool // when true, token text has lexer error
+ value uint8 // value: zString, _BLANK, etc.
+ line int // line in the file
+ column int // column in the file
+ torc uint16 // type or class as parsed in the lexer, we only need to look this up in the grammar
+ comment string // any comment text seen
+}
+
+// Token holds the token that are returned when a zone file is parsed.
+type Token struct {
+ // The scanned resource record when error is not nil.
+ RR
+ // When an error occurred, this has the error specifics.
+ Error *ParseError
+ // A potential comment positioned after the RR and on the same line.
+ Comment string
+}
+
+// ttlState describes the state necessary to fill in an omitted RR TTL
+type ttlState struct {
+ ttl uint32 // ttl is the current default TTL
+ isByDirective bool // isByDirective indicates whether ttl was set by a $TTL directive
+}
+
+// NewRR reads the RR contained in the string s. Only the first RR is
+// returned. If s contains no RR, return nil with no error. The class
+// defaults to IN and TTL defaults to 3600. The full zone file syntax
+// like $TTL, $ORIGIN, etc. is supported. All fields of the returned
+// RR are set, except RR.Header().Rdlength which is set to 0.
+func NewRR(s string) (RR, error) {
+ if len(s) > 0 && s[len(s)-1] != '\n' { // We need a closing newline
+ return ReadRR(strings.NewReader(s+"\n"), "")
+ }
+ return ReadRR(strings.NewReader(s), "")
+}
+
+// ReadRR reads the RR contained in q.
+// See NewRR for more documentation.
+func ReadRR(q io.Reader, filename string) (RR, error) {
+ defttl := &ttlState{defaultTtl, false}
+ r := <-parseZoneHelper(q, ".", defttl, filename, 1)
+ if r == nil {
+ return nil, nil
+ }
+
+ if r.Error != nil {
+ return nil, r.Error
+ }
+ return r.RR, nil
+}
+
+// ParseZone reads a RFC 1035 style zonefile from r. It returns *Tokens on the
+// returned channel, each consisting of either a parsed RR and optional comment
+// or a nil RR and an error. The string file is only used
+// in error reporting. The string origin is used as the initial origin, as
+// if the file would start with an $ORIGIN directive.
+// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are supported.
+// The channel t is closed by ParseZone when the end of r is reached.
+//
+// Basic usage pattern when reading from a string (z) containing the
+// zone data:
+//
+// for x := range dns.ParseZone(strings.NewReader(z), "", "") {
+// if x.Error != nil {
+// // log.Println(x.Error)
+// } else {
+// // Do something with x.RR
+// }
+// }
+//
+// Comments specified after an RR (and on the same line!) are returned too:
+//
+// foo. IN A 10.0.0.1 ; this is a comment
+//
+// The text "; this is comment" is returned in Token.Comment. Comments inside the
+// RR are discarded. Comments on a line by themselves are discarded too.
+func ParseZone(r io.Reader, origin, file string) chan *Token {
+ return parseZoneHelper(r, origin, nil, file, 10000)
+}
+
+func parseZoneHelper(r io.Reader, origin string, defttl *ttlState, file string, chansize int) chan *Token {
+ t := make(chan *Token, chansize)
+ go parseZone(r, origin, defttl, file, t, 0)
+ return t
+}
+
+func parseZone(r io.Reader, origin string, defttl *ttlState, f string, t chan *Token, include int) {
+ defer func() {
+ if include == 0 {
+ close(t)
+ }
+ }()
+ s := scanInit(r)
+ c := make(chan lex)
+ // Start the lexer
+ go zlexer(s, c)
+ // 6 possible beginnings of a line, _ is a space
+ // 0. zRRTYPE -> all omitted until the rrtype
+ // 1. zOwner _ zRrtype -> class/ttl omitted
+ // 2. zOwner _ zString _ zRrtype -> class omitted
+ // 3. zOwner _ zString _ zClass _ zRrtype -> ttl/class
+ // 4. zOwner _ zClass _ zRrtype -> ttl omitted
+ // 5. zOwner _ zClass _ zString _ zRrtype -> class/ttl (reversed)
+ // After detecting these, we know the zRrtype so we can jump to functions
+ // handling the rdata for each of these types.
+
+ if origin != "" {
+ origin = Fqdn(origin)
+ if _, ok := IsDomainName(origin); !ok {
+ t <- &Token{Error: &ParseError{f, "bad initial origin name", lex{}}}
+ return
+ }
+ }
+
+ st := zExpectOwnerDir // initial state
+ var h RR_Header
+ var prevName string
+ for l := range c {
+ // Lexer spotted an error already
+ if l.err == true {
+ t <- &Token{Error: &ParseError{f, l.token, l}}
+ return
+
+ }
+ switch st {
+ case zExpectOwnerDir:
+ // We can also expect a directive, like $TTL or $ORIGIN
+ if defttl != nil {
+ h.Ttl = defttl.ttl
+ }
+ h.Class = ClassINET
+ switch l.value {
+ case zNewline:
+ st = zExpectOwnerDir
+ case zOwner:
+ h.Name = l.token
+ name, ok := toAbsoluteName(l.token, origin)
+ if !ok {
+ t <- &Token{Error: &ParseError{f, "bad owner name", l}}
+ return
+ }
+ h.Name = name
+ prevName = h.Name
+ st = zExpectOwnerBl
+ case zDirTTL:
+ st = zExpectDirTTLBl
+ case zDirOrigin:
+ st = zExpectDirOriginBl
+ case zDirInclude:
+ st = zExpectDirIncludeBl
+ case zDirGenerate:
+ st = zExpectDirGenerateBl
+ case zRrtpe:
+ h.Name = prevName
+ h.Rrtype = l.torc
+ st = zExpectRdata
+ case zClass:
+ h.Name = prevName
+ h.Class = l.torc
+ st = zExpectAnyNoClassBl
+ case zBlank:
+ // Discard, can happen when there is nothing on the
+ // line except the RR type
+ case zString:
+ ttl, ok := stringToTTL(l.token)
+ if !ok {
+ t <- &Token{Error: &ParseError{f, "not a TTL", l}}
+ return
+ }
+ h.Ttl = ttl
+ if defttl == nil || !defttl.isByDirective {
+ defttl = &ttlState{ttl, false}
+ }
+ st = zExpectAnyNoTTLBl
+
+ default:
+ t <- &Token{Error: &ParseError{f, "syntax error at beginning", l}}
+ return
+ }
+ case zExpectDirIncludeBl:
+ if l.value != zBlank {
+ t <- &Token{Error: &ParseError{f, "no blank after $INCLUDE-directive", l}}
+ return
+ }
+ st = zExpectDirInclude
+ case zExpectDirInclude:
+ if l.value != zString {
+ t <- &Token{Error: &ParseError{f, "expecting $INCLUDE value, not this...", l}}
+ return
+ }
+ neworigin := origin // There may be optionally a new origin set after the filename, if not use current one
+ switch l := <-c; l.value {
+ case zBlank:
+ l := <-c
+ if l.value == zString {
+ name, ok := toAbsoluteName(l.token, origin)
+ if !ok {
+ t <- &Token{Error: &ParseError{f, "bad origin name", l}}
+ return
+ }
+ neworigin = name
+ }
+ case zNewline, zEOF:
+ // Ok
+ default:
+ t <- &Token{Error: &ParseError{f, "garbage after $INCLUDE", l}}
+ return
+ }
+ // Start with the new file
+ r1, e1 := os.Open(l.token)
+ if e1 != nil {
+ t <- &Token{Error: &ParseError{f, "failed to open `" + l.token + "'", l}}
+ return
+ }
+ if include+1 > 7 {
+ t <- &Token{Error: &ParseError{f, "too deeply nested $INCLUDE", l}}
+ return
+ }
+ parseZone(r1, neworigin, defttl, l.token, t, include+1)
+ st = zExpectOwnerDir
+ case zExpectDirTTLBl:
+ if l.value != zBlank {
+ t <- &Token{Error: &ParseError{f, "no blank after $TTL-directive", l}}
+ return
+ }
+ st = zExpectDirTTL
+ case zExpectDirTTL:
+ if l.value != zString {
+ t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
+ return
+ }
+ if e, _ := slurpRemainder(c, f); e != nil {
+ t <- &Token{Error: e}
+ return
+ }
+ ttl, ok := stringToTTL(l.token)
+ if !ok {
+ t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
+ return
+ }
+ defttl = &ttlState{ttl, true}
+ st = zExpectOwnerDir
+ case zExpectDirOriginBl:
+ if l.value != zBlank {
+ t <- &Token{Error: &ParseError{f, "no blank after $ORIGIN-directive", l}}
+ return
+ }
+ st = zExpectDirOrigin
+ case zExpectDirOrigin:
+ if l.value != zString {
+ t <- &Token{Error: &ParseError{f, "expecting $ORIGIN value, not this...", l}}
+ return
+ }
+ if e, _ := slurpRemainder(c, f); e != nil {
+ t <- &Token{Error: e}
+ }
+ name, ok := toAbsoluteName(l.token, origin)
+ if !ok {
+ t <- &Token{Error: &ParseError{f, "bad origin name", l}}
+ return
+ }
+ origin = name
+ st = zExpectOwnerDir
+ case zExpectDirGenerateBl:
+ if l.value != zBlank {
+ t <- &Token{Error: &ParseError{f, "no blank after $GENERATE-directive", l}}
+ return
+ }
+ st = zExpectDirGenerate
+ case zExpectDirGenerate:
+ if l.value != zString {
+ t <- &Token{Error: &ParseError{f, "expecting $GENERATE value, not this...", l}}
+ return
+ }
+ if errMsg := generate(l, c, t, origin); errMsg != "" {
+ t <- &Token{Error: &ParseError{f, errMsg, l}}
+ return
+ }
+ st = zExpectOwnerDir
+ case zExpectOwnerBl:
+ if l.value != zBlank {
+ t <- &Token{Error: &ParseError{f, "no blank after owner", l}}
+ return
+ }
+ st = zExpectAny
+ case zExpectAny:
+ switch l.value {
+ case zRrtpe:
+ if defttl == nil {
+ t <- &Token{Error: &ParseError{f, "missing TTL with no previous value", l}}
+ return
+ }
+ h.Rrtype = l.torc
+ st = zExpectRdata
+ case zClass:
+ h.Class = l.torc
+ st = zExpectAnyNoClassBl
+ case zString:
+ ttl, ok := stringToTTL(l.token)
+ if !ok {
+ t <- &Token{Error: &ParseError{f, "not a TTL", l}}
+ return
+ }
+ h.Ttl = ttl
+ if defttl == nil || !defttl.isByDirective {
+ defttl = &ttlState{ttl, false}
+ }
+ st = zExpectAnyNoTTLBl
+ default:
+ t <- &Token{Error: &ParseError{f, "expecting RR type, TTL or class, not this...", l}}
+ return
+ }
+ case zExpectAnyNoClassBl:
+ if l.value != zBlank {
+ t <- &Token{Error: &ParseError{f, "no blank before class", l}}
+ return
+ }
+ st = zExpectAnyNoClass
+ case zExpectAnyNoTTLBl:
+ if l.value != zBlank {
+ t <- &Token{Error: &ParseError{f, "no blank before TTL", l}}
+ return
+ }
+ st = zExpectAnyNoTTL
+ case zExpectAnyNoTTL:
+ switch l.value {
+ case zClass:
+ h.Class = l.torc
+ st = zExpectRrtypeBl
+ case zRrtpe:
+ h.Rrtype = l.torc
+ st = zExpectRdata
+ default:
+ t <- &Token{Error: &ParseError{f, "expecting RR type or class, not this...", l}}
+ return
+ }
+ case zExpectAnyNoClass:
+ switch l.value {
+ case zString:
+ ttl, ok := stringToTTL(l.token)
+ if !ok {
+ t <- &Token{Error: &ParseError{f, "not a TTL", l}}
+ return
+ }
+ h.Ttl = ttl
+ if defttl == nil || !defttl.isByDirective {
+ defttl = &ttlState{ttl, false}
+ }
+ st = zExpectRrtypeBl
+ case zRrtpe:
+ h.Rrtype = l.torc
+ st = zExpectRdata
+ default:
+ t <- &Token{Error: &ParseError{f, "expecting RR type or TTL, not this...", l}}
+ return
+ }
+ case zExpectRrtypeBl:
+ if l.value != zBlank {
+ t <- &Token{Error: &ParseError{f, "no blank before RR type", l}}
+ return
+ }
+ st = zExpectRrtype
+ case zExpectRrtype:
+ if l.value != zRrtpe {
+ t <- &Token{Error: &ParseError{f, "unknown RR type", l}}
+ return
+ }
+ h.Rrtype = l.torc
+ st = zExpectRdata
+ case zExpectRdata:
+ r, e, c1 := setRR(h, c, origin, f)
+ if e != nil {
+ // If e.lex is nil than we have encounter a unknown RR type
+ // in that case we substitute our current lex token
+ if e.lex.token == "" && e.lex.value == 0 {
+ e.lex = l // Uh, dirty
+ }
+ t <- &Token{Error: e}
+ return
+ }
+ t <- &Token{RR: r, Comment: c1}
+ st = zExpectOwnerDir
+ }
+ }
+ // If we get here, we and the h.Rrtype is still zero, we haven't parsed anything, this
+ // is not an error, because an empty zone file is still a zone file.
+}
+
+// zlexer scans the sourcefile and returns tokens on the channel c.
+func zlexer(s *scan, c chan lex) {
+ var l lex
+ str := make([]byte, maxTok) // Should be enough for any token
+ stri := 0 // Offset in str (0 means empty)
+ com := make([]byte, maxTok) // Hold comment text
+ comi := 0
+ quote := false
+ escape := false
+ space := false
+ commt := false
+ rrtype := false
+ owner := true
+ brace := 0
+ x, err := s.tokenText()
+ defer close(c)
+ for err == nil {
+ l.column = s.position.Column
+ l.line = s.position.Line
+ if stri >= maxTok {
+ l.token = "token length insufficient for parsing"
+ l.err = true
+ debug.Printf("[%+v]", l.token)
+ c <- l
+ return
+ }
+ if comi >= maxTok {
+ l.token = "comment length insufficient for parsing"
+ l.err = true
+ debug.Printf("[%+v]", l.token)
+ c <- l
+ return
+ }
+
+ switch x {
+ case ' ', '\t':
+ if escape {
+ escape = false
+ str[stri] = x
+ stri++
+ break
+ }
+ if quote {
+ // Inside quotes this is legal
+ str[stri] = x
+ stri++
+ break
+ }
+ if commt {
+ com[comi] = x
+ comi++
+ break
+ }
+ if stri == 0 {
+ // Space directly in the beginning, handled in the grammar
+ } else if owner {
+ // If we have a string and its the first, make it an owner
+ l.value = zOwner
+ l.token = string(str[:stri])
+ l.tokenUpper = strings.ToUpper(l.token)
+ l.length = stri
+ // escape $... start with a \ not a $, so this will work
+ switch l.tokenUpper {
+ case "$TTL":
+ l.value = zDirTTL
+ case "$ORIGIN":
+ l.value = zDirOrigin
+ case "$INCLUDE":
+ l.value = zDirInclude
+ case "$GENERATE":
+ l.value = zDirGenerate
+ }
+ debug.Printf("[7 %+v]", l.token)
+ c <- l
+ } else {
+ l.value = zString
+ l.token = string(str[:stri])
+ l.tokenUpper = strings.ToUpper(l.token)
+ l.length = stri
+ if !rrtype {
+ if t, ok := StringToType[l.tokenUpper]; ok {
+ l.value = zRrtpe
+ l.torc = t
+ rrtype = true
+ } else {
+ if strings.HasPrefix(l.tokenUpper, "TYPE") {
+ t, ok := typeToInt(l.token)
+ if !ok {
+ l.token = "unknown RR type"
+ l.err = true
+ c <- l
+ return
+ }
+ l.value = zRrtpe
+ l.torc = t
+ }
+ }
+ if t, ok := StringToClass[l.tokenUpper]; ok {
+ l.value = zClass
+ l.torc = t
+ } else {
+ if strings.HasPrefix(l.tokenUpper, "CLASS") {
+ t, ok := classToInt(l.token)
+ if !ok {
+ l.token = "unknown class"
+ l.err = true
+ c <- l
+ return
+ }
+ l.value = zClass
+ l.torc = t
+ }
+ }
+ }
+ debug.Printf("[6 %+v]", l.token)
+ c <- l
+ }
+ stri = 0
+ // I reverse space stuff here
+ if !space && !commt {
+ l.value = zBlank
+ l.token = " "
+ l.length = 1
+ debug.Printf("[5 %+v]", l.token)
+ c <- l
+ }
+ owner = false
+ space = true
+ case ';':
+ if escape {
+ escape = false
+ str[stri] = x
+ stri++
+ break
+ }
+ if quote {
+ // Inside quotes this is legal
+ str[stri] = x
+ stri++
+ break
+ }
+ if stri > 0 {
+ l.value = zString
+ l.token = string(str[:stri])
+ l.tokenUpper = strings.ToUpper(l.token)
+ l.length = stri
+ debug.Printf("[4 %+v]", l.token)
+ c <- l
+ stri = 0
+ }
+ commt = true
+ com[comi] = ';'
+ comi++
+ case '\r':
+ escape = false
+ if quote {
+ str[stri] = x
+ stri++
+ break
+ }
+ // discard if outside of quotes
+ case '\n':
+ escape = false
+ // Escaped newline
+ if quote {
+ str[stri] = x
+ stri++
+ break
+ }
+ // inside quotes this is legal
+ if commt {
+ // Reset a comment
+ commt = false
+ rrtype = false
+ stri = 0
+ // If not in a brace this ends the comment AND the RR
+ if brace == 0 {
+ owner = true
+ owner = true
+ l.value = zNewline
+ l.token = "\n"
+ l.tokenUpper = l.token
+ l.length = 1
+ l.comment = string(com[:comi])
+ debug.Printf("[3 %+v %+v]", l.token, l.comment)
+ c <- l
+ l.comment = ""
+ comi = 0
+ break
+ }
+ com[comi] = ' ' // convert newline to space
+ comi++
+ break
+ }
+
+ if brace == 0 {
+ // If there is previous text, we should output it here
+ if stri != 0 {
+ l.value = zString
+ l.token = string(str[:stri])
+ l.tokenUpper = strings.ToUpper(l.token)
+
+ l.length = stri
+ if !rrtype {
+ if t, ok := StringToType[l.tokenUpper]; ok {
+ l.value = zRrtpe
+ l.torc = t
+ rrtype = true
+ }
+ }
+ debug.Printf("[2 %+v]", l.token)
+ c <- l
+ }
+ l.value = zNewline
+ l.token = "\n"
+ l.tokenUpper = l.token
+ l.length = 1
+ debug.Printf("[1 %+v]", l.token)
+ c <- l
+ stri = 0
+ commt = false
+ rrtype = false
+ owner = true
+ comi = 0
+ }
+ case '\\':
+ // comments do not get escaped chars, everything is copied
+ if commt {
+ com[comi] = x
+ comi++
+ break
+ }
+ // something already escaped must be in string
+ if escape {
+ str[stri] = x
+ stri++
+ escape = false
+ break
+ }
+ // something escaped outside of string gets added to string
+ str[stri] = x
+ stri++
+ escape = true
+ case '"':
+ if commt {
+ com[comi] = x
+ comi++
+ break
+ }
+ if escape {
+ str[stri] = x
+ stri++
+ escape = false
+ break
+ }
+ space = false
+ // send previous gathered text and the quote
+ if stri != 0 {
+ l.value = zString
+ l.token = string(str[:stri])
+ l.tokenUpper = strings.ToUpper(l.token)
+ l.length = stri
+
+ debug.Printf("[%+v]", l.token)
+ c <- l
+ stri = 0
+ }
+
+ // send quote itself as separate token
+ l.value = zQuote
+ l.token = "\""
+ l.tokenUpper = l.token
+ l.length = 1
+ c <- l
+ quote = !quote
+ case '(', ')':
+ if commt {
+ com[comi] = x
+ comi++
+ break
+ }
+ if escape {
+ str[stri] = x
+ stri++
+ escape = false
+ break
+ }
+ if quote {
+ str[stri] = x
+ stri++
+ break
+ }
+ switch x {
+ case ')':
+ brace--
+ if brace < 0 {
+ l.token = "extra closing brace"
+ l.tokenUpper = l.token
+ l.err = true
+ debug.Printf("[%+v]", l.token)
+ c <- l
+ return
+ }
+ case '(':
+ brace++
+ }
+ default:
+ escape = false
+ if commt {
+ com[comi] = x
+ comi++
+ break
+ }
+ str[stri] = x
+ stri++
+ space = false
+ }
+ x, err = s.tokenText()
+ }
+ if stri > 0 {
+ // Send remainder
+ l.token = string(str[:stri])
+ l.tokenUpper = strings.ToUpper(l.token)
+ l.length = stri
+ l.value = zString
+ debug.Printf("[%+v]", l.token)
+ c <- l
+ }
+ if brace != 0 {
+ l.token = "unbalanced brace"
+ l.tokenUpper = l.token
+ l.err = true
+ c <- l
+ }
+}
+
+// Extract the class number from CLASSxx
+func classToInt(token string) (uint16, bool) {
+ offset := 5
+ if len(token) < offset+1 {
+ return 0, false
+ }
+ class, err := strconv.ParseUint(token[offset:], 10, 16)
+ if err != nil {
+ return 0, false
+ }
+ return uint16(class), true
+}
+
+// Extract the rr number from TYPExxx
+func typeToInt(token string) (uint16, bool) {
+ offset := 4
+ if len(token) < offset+1 {
+ return 0, false
+ }
+ typ, err := strconv.ParseUint(token[offset:], 10, 16)
+ if err != nil {
+ return 0, false
+ }
+ return uint16(typ), true
+}
+
+// stringToTTL parses things like 2w, 2m, etc, and returns the time in seconds.
+func stringToTTL(token string) (uint32, bool) {
+ s := uint32(0)
+ i := uint32(0)
+ for _, c := range token {
+ switch c {
+ case 's', 'S':
+ s += i
+ i = 0
+ case 'm', 'M':
+ s += i * 60
+ i = 0
+ case 'h', 'H':
+ s += i * 60 * 60
+ i = 0
+ case 'd', 'D':
+ s += i * 60 * 60 * 24
+ i = 0
+ case 'w', 'W':
+ s += i * 60 * 60 * 24 * 7
+ i = 0
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ i *= 10
+ i += uint32(c) - '0'
+ default:
+ return 0, false
+ }
+ }
+ return s + i, true
+}
+
+// Parse LOC records' <digits>[.<digits>][mM] into a
+// mantissa exponent format. Token should contain the entire
+// string (i.e. no spaces allowed)
+func stringToCm(token string) (e, m uint8, ok bool) {
+ if token[len(token)-1] == 'M' || token[len(token)-1] == 'm' {
+ token = token[0 : len(token)-1]
+ }
+ s := strings.SplitN(token, ".", 2)
+ var meters, cmeters, val int
+ var err error
+ switch len(s) {
+ case 2:
+ if cmeters, err = strconv.Atoi(s[1]); err != nil {
+ return
+ }
+ fallthrough
+ case 1:
+ if meters, err = strconv.Atoi(s[0]); err != nil {
+ return
+ }
+ case 0:
+ // huh?
+ return 0, 0, false
+ }
+ ok = true
+ if meters > 0 {
+ e = 2
+ val = meters
+ } else {
+ e = 0
+ val = cmeters
+ }
+ for val > 10 {
+ e++
+ val /= 10
+ }
+ if e > 9 {
+ ok = false
+ }
+ m = uint8(val)
+ return
+}
+
+func toAbsoluteName(name, origin string) (absolute string, ok bool) {
+ // check for an explicit origin reference
+ if name == "@" {
+ // require a nonempty origin
+ if origin == "" {
+ return "", false
+ }
+ return origin, true
+ }
+
+ // require a valid domain name
+ _, ok = IsDomainName(name)
+ if !ok || name == "" {
+ return "", false
+ }
+
+ // check if name is already absolute
+ if name[len(name)-1] == '.' {
+ return name, true
+ }
+
+ // require a nonempty origin
+ if origin == "" {
+ return "", false
+ }
+ return appendOrigin(name, origin), true
+}
+
+func appendOrigin(name, origin string) string {
+ if origin == "." {
+ return name + origin
+ }
+ return name + "." + origin
+}
+
+// LOC record helper function
+func locCheckNorth(token string, latitude uint32) (uint32, bool) {
+ switch token {
+ case "n", "N":
+ return LOC_EQUATOR + latitude, true
+ case "s", "S":
+ return LOC_EQUATOR - latitude, true
+ }
+ return latitude, false
+}
+
+// LOC record helper function
+func locCheckEast(token string, longitude uint32) (uint32, bool) {
+ switch token {
+ case "e", "E":
+ return LOC_EQUATOR + longitude, true
+ case "w", "W":
+ return LOC_EQUATOR - longitude, true
+ }
+ return longitude, false
+}
+
+// "Eat" the rest of the "line". Return potential comments
+func slurpRemainder(c chan lex, f string) (*ParseError, string) {
+ l := <-c
+ com := ""
+ switch l.value {
+ case zBlank:
+ l = <-c
+ com = l.comment
+ if l.value != zNewline && l.value != zEOF {
+ return &ParseError{f, "garbage after rdata", l}, ""
+ }
+ case zNewline:
+ com = l.comment
+ case zEOF:
+ default:
+ return &ParseError{f, "garbage after rdata", l}, ""
+ }
+ return nil, com
+}
+
+// Parse a 64 bit-like ipv6 address: "0014:4fff:ff20:ee64"
+// Used for NID and L64 record.
+func stringToNodeID(l lex) (uint64, *ParseError) {
+ if len(l.token) < 19 {
+ return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l}
+ }
+ // There must be three colons at fixes postitions, if not its a parse error
+ if l.token[4] != ':' && l.token[9] != ':' && l.token[14] != ':' {
+ return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l}
+ }
+ s := l.token[0:4] + l.token[5:9] + l.token[10:14] + l.token[15:19]
+ u, err := strconv.ParseUint(s, 16, 64)
+ if err != nil {
+ return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l}
+ }
+ return u, nil
+}
--- /dev/null
+package dns
+
+import (
+ "encoding/base64"
+ "net"
+ "strconv"
+ "strings"
+)
+
+type parserFunc struct {
+ // Func defines the function that parses the tokens and returns the RR
+ // or an error. The last string contains any comments in the line as
+ // they returned by the lexer as well.
+ Func func(h RR_Header, c chan lex, origin string, file string) (RR, *ParseError, string)
+ // Signals if the RR ending is of variable length, like TXT or records
+ // that have Hexadecimal or Base64 as their last element in the Rdata. Records
+ // that have a fixed ending or for instance A, AAAA, SOA and etc.
+ Variable bool
+}
+
+// Parse the rdata of each rrtype.
+// All data from the channel c is either zString or zBlank.
+// After the rdata there may come a zBlank and then a zNewline
+// or immediately a zNewline. If this is not the case we flag
+// an *ParseError: garbage after rdata.
+func setRR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ parserfunc, ok := typeToparserFunc[h.Rrtype]
+ if ok {
+ r, e, cm := parserfunc.Func(h, c, o, f)
+ if parserfunc.Variable {
+ return r, e, cm
+ }
+ if e != nil {
+ return nil, e, ""
+ }
+ e, cm = slurpRemainder(c, f)
+ if e != nil {
+ return nil, e, ""
+ }
+ return r, nil, cm
+ }
+ // RFC3957 RR (Unknown RR handling)
+ return setRFC3597(h, c, o, f)
+}
+
+// A remainder of the rdata with embedded spaces, return the parsed string (sans the spaces)
+// or an error
+func endingToString(c chan lex, errstr, f string) (string, *ParseError, string) {
+ s := ""
+ l := <-c // zString
+ for l.value != zNewline && l.value != zEOF {
+ if l.err {
+ return s, &ParseError{f, errstr, l}, ""
+ }
+ switch l.value {
+ case zString:
+ s += l.token
+ case zBlank: // Ok
+ default:
+ return "", &ParseError{f, errstr, l}, ""
+ }
+ l = <-c
+ }
+ return s, nil, l.comment
+}
+
+// A remainder of the rdata with embedded spaces, split on unquoted whitespace
+// and return the parsed string slice or an error
+func endingToTxtSlice(c chan lex, errstr, f string) ([]string, *ParseError, string) {
+ // Get the remaining data until we see a zNewline
+ l := <-c
+ if l.err {
+ return nil, &ParseError{f, errstr, l}, ""
+ }
+
+ // Build the slice
+ s := make([]string, 0)
+ quote := false
+ empty := false
+ for l.value != zNewline && l.value != zEOF {
+ if l.err {
+ return nil, &ParseError{f, errstr, l}, ""
+ }
+ switch l.value {
+ case zString:
+ empty = false
+ if len(l.token) > 255 {
+ // split up tokens that are larger than 255 into 255-chunks
+ sx := []string{}
+ p, i := 0, 255
+ for {
+ if i <= len(l.token) {
+ sx = append(sx, l.token[p:i])
+ } else {
+ sx = append(sx, l.token[p:])
+ break
+
+ }
+ p, i = p+255, i+255
+ }
+ s = append(s, sx...)
+ break
+ }
+
+ s = append(s, l.token)
+ case zBlank:
+ if quote {
+ // zBlank can only be seen in between txt parts.
+ return nil, &ParseError{f, errstr, l}, ""
+ }
+ case zQuote:
+ if empty && quote {
+ s = append(s, "")
+ }
+ quote = !quote
+ empty = true
+ default:
+ return nil, &ParseError{f, errstr, l}, ""
+ }
+ l = <-c
+ }
+ if quote {
+ return nil, &ParseError{f, errstr, l}, ""
+ }
+ return s, nil, l.comment
+}
+
+func setA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(A)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ rr.A = net.ParseIP(l.token)
+ if rr.A == nil || l.err {
+ return nil, &ParseError{f, "bad A A", l}, ""
+ }
+ return rr, nil, ""
+}
+
+func setAAAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(AAAA)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ rr.AAAA = net.ParseIP(l.token)
+ if rr.AAAA == nil || l.err {
+ return nil, &ParseError{f, "bad AAAA AAAA", l}, ""
+ }
+ return rr, nil, ""
+}
+
+func setNS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(NS)
+ rr.Hdr = h
+
+ l := <-c
+ rr.Ns = l.token
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad NS Ns", l}, ""
+ }
+ rr.Ns = name
+ return rr, nil, ""
+}
+
+func setPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(PTR)
+ rr.Hdr = h
+
+ l := <-c
+ rr.Ptr = l.token
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad PTR Ptr", l}, ""
+ }
+ rr.Ptr = name
+ return rr, nil, ""
+}
+
+func setNSAPPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(NSAPPTR)
+ rr.Hdr = h
+
+ l := <-c
+ rr.Ptr = l.token
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad NSAP-PTR Ptr", l}, ""
+ }
+ rr.Ptr = name
+ return rr, nil, ""
+}
+
+func setRP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(RP)
+ rr.Hdr = h
+
+ l := <-c
+ rr.Mbox = l.token
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ mbox, mboxOk := toAbsoluteName(l.token, o)
+ if l.err || !mboxOk {
+ return nil, &ParseError{f, "bad RP Mbox", l}, ""
+ }
+ rr.Mbox = mbox
+
+ <-c // zBlank
+ l = <-c
+ rr.Txt = l.token
+
+ txt, txtOk := toAbsoluteName(l.token, o)
+ if l.err || !txtOk {
+ return nil, &ParseError{f, "bad RP Txt", l}, ""
+ }
+ rr.Txt = txt
+
+ return rr, nil, ""
+}
+
+func setMR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(MR)
+ rr.Hdr = h
+
+ l := <-c
+ rr.Mr = l.token
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad MR Mr", l}, ""
+ }
+ rr.Mr = name
+ return rr, nil, ""
+}
+
+func setMB(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(MB)
+ rr.Hdr = h
+
+ l := <-c
+ rr.Mb = l.token
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad MB Mb", l}, ""
+ }
+ rr.Mb = name
+ return rr, nil, ""
+}
+
+func setMG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(MG)
+ rr.Hdr = h
+
+ l := <-c
+ rr.Mg = l.token
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad MG Mg", l}, ""
+ }
+ rr.Mg = name
+ return rr, nil, ""
+}
+
+func setHINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(HINFO)
+ rr.Hdr = h
+
+ chunks, e, c1 := endingToTxtSlice(c, "bad HINFO Fields", f)
+ if e != nil {
+ return nil, e, c1
+ }
+
+ if ln := len(chunks); ln == 0 {
+ return rr, nil, ""
+ } else if ln == 1 {
+ // Can we split it?
+ if out := strings.Fields(chunks[0]); len(out) > 1 {
+ chunks = out
+ } else {
+ chunks = append(chunks, "")
+ }
+ }
+
+ rr.Cpu = chunks[0]
+ rr.Os = strings.Join(chunks[1:], " ")
+
+ return rr, nil, ""
+}
+
+func setMINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(MINFO)
+ rr.Hdr = h
+
+ l := <-c
+ rr.Rmail = l.token
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ rmail, rmailOk := toAbsoluteName(l.token, o)
+ if l.err || !rmailOk {
+ return nil, &ParseError{f, "bad MINFO Rmail", l}, ""
+ }
+ rr.Rmail = rmail
+
+ <-c // zBlank
+ l = <-c
+ rr.Email = l.token
+
+ email, emailOk := toAbsoluteName(l.token, o)
+ if l.err || !emailOk {
+ return nil, &ParseError{f, "bad MINFO Email", l}, ""
+ }
+ rr.Email = email
+
+ return rr, nil, ""
+}
+
+func setMF(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(MF)
+ rr.Hdr = h
+
+ l := <-c
+ rr.Mf = l.token
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad MF Mf", l}, ""
+ }
+ rr.Mf = name
+ return rr, nil, ""
+}
+
+func setMD(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(MD)
+ rr.Hdr = h
+
+ l := <-c
+ rr.Md = l.token
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad MD Md", l}, ""
+ }
+ rr.Md = name
+ return rr, nil, ""
+}
+
+func setMX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(MX)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad MX Pref", l}, ""
+ }
+ rr.Preference = uint16(i)
+
+ <-c // zBlank
+ l = <-c // zString
+ rr.Mx = l.token
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad MX Mx", l}, ""
+ }
+ rr.Mx = name
+
+ return rr, nil, ""
+}
+
+func setRT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(RT)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 16)
+ if e != nil {
+ return nil, &ParseError{f, "bad RT Preference", l}, ""
+ }
+ rr.Preference = uint16(i)
+
+ <-c // zBlank
+ l = <-c // zString
+ rr.Host = l.token
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad RT Host", l}, ""
+ }
+ rr.Host = name
+
+ return rr, nil, ""
+}
+
+func setAFSDB(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(AFSDB)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad AFSDB Subtype", l}, ""
+ }
+ rr.Subtype = uint16(i)
+
+ <-c // zBlank
+ l = <-c // zString
+ rr.Hostname = l.token
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad AFSDB Hostname", l}, ""
+ }
+ rr.Hostname = name
+ return rr, nil, ""
+}
+
+func setX25(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(X25)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ if l.err {
+ return nil, &ParseError{f, "bad X25 PSDNAddress", l}, ""
+ }
+ rr.PSDNAddress = l.token
+ return rr, nil, ""
+}
+
+func setKX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(KX)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad KX Pref", l}, ""
+ }
+ rr.Preference = uint16(i)
+
+ <-c // zBlank
+ l = <-c // zString
+ rr.Exchanger = l.token
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad KX Exchanger", l}, ""
+ }
+ rr.Exchanger = name
+ return rr, nil, ""
+}
+
+func setCNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(CNAME)
+ rr.Hdr = h
+
+ l := <-c
+ rr.Target = l.token
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad CNAME Target", l}, ""
+ }
+ rr.Target = name
+ return rr, nil, ""
+}
+
+func setDNAME(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(DNAME)
+ rr.Hdr = h
+
+ l := <-c
+ rr.Target = l.token
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad DNAME Target", l}, ""
+ }
+ rr.Target = name
+ return rr, nil, ""
+}
+
+func setSOA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(SOA)
+ rr.Hdr = h
+
+ l := <-c
+ rr.Ns = l.token
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ ns, nsOk := toAbsoluteName(l.token, o)
+ if l.err || !nsOk {
+ return nil, &ParseError{f, "bad SOA Ns", l}, ""
+ }
+ rr.Ns = ns
+
+ <-c // zBlank
+ l = <-c
+ rr.Mbox = l.token
+
+ mbox, mboxOk := toAbsoluteName(l.token, o)
+ if l.err || !mboxOk {
+ return nil, &ParseError{f, "bad SOA Mbox", l}, ""
+ }
+ rr.Mbox = mbox
+
+ <-c // zBlank
+
+ var (
+ v uint32
+ ok bool
+ )
+ for i := 0; i < 5; i++ {
+ l = <-c
+ if l.err {
+ return nil, &ParseError{f, "bad SOA zone parameter", l}, ""
+ }
+ if j, e := strconv.ParseUint(l.token, 10, 32); e != nil {
+ if i == 0 {
+ // Serial must be a number
+ return nil, &ParseError{f, "bad SOA zone parameter", l}, ""
+ }
+ // We allow other fields to be unitful duration strings
+ if v, ok = stringToTTL(l.token); !ok {
+ return nil, &ParseError{f, "bad SOA zone parameter", l}, ""
+
+ }
+ } else {
+ v = uint32(j)
+ }
+ switch i {
+ case 0:
+ rr.Serial = v
+ <-c // zBlank
+ case 1:
+ rr.Refresh = v
+ <-c // zBlank
+ case 2:
+ rr.Retry = v
+ <-c // zBlank
+ case 3:
+ rr.Expire = v
+ <-c // zBlank
+ case 4:
+ rr.Minttl = v
+ }
+ }
+ return rr, nil, ""
+}
+
+func setSRV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(SRV)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad SRV Priority", l}, ""
+ }
+ rr.Priority = uint16(i)
+
+ <-c // zBlank
+ l = <-c // zString
+ i, e = strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad SRV Weight", l}, ""
+ }
+ rr.Weight = uint16(i)
+
+ <-c // zBlank
+ l = <-c // zString
+ i, e = strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad SRV Port", l}, ""
+ }
+ rr.Port = uint16(i)
+
+ <-c // zBlank
+ l = <-c // zString
+ rr.Target = l.token
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad SRV Target", l}, ""
+ }
+ rr.Target = name
+ return rr, nil, ""
+}
+
+func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(NAPTR)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad NAPTR Order", l}, ""
+ }
+ rr.Order = uint16(i)
+
+ <-c // zBlank
+ l = <-c // zString
+ i, e = strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad NAPTR Preference", l}, ""
+ }
+ rr.Preference = uint16(i)
+
+ // Flags
+ <-c // zBlank
+ l = <-c // _QUOTE
+ if l.value != zQuote {
+ return nil, &ParseError{f, "bad NAPTR Flags", l}, ""
+ }
+ l = <-c // Either String or Quote
+ if l.value == zString {
+ rr.Flags = l.token
+ l = <-c // _QUOTE
+ if l.value != zQuote {
+ return nil, &ParseError{f, "bad NAPTR Flags", l}, ""
+ }
+ } else if l.value == zQuote {
+ rr.Flags = ""
+ } else {
+ return nil, &ParseError{f, "bad NAPTR Flags", l}, ""
+ }
+
+ // Service
+ <-c // zBlank
+ l = <-c // _QUOTE
+ if l.value != zQuote {
+ return nil, &ParseError{f, "bad NAPTR Service", l}, ""
+ }
+ l = <-c // Either String or Quote
+ if l.value == zString {
+ rr.Service = l.token
+ l = <-c // _QUOTE
+ if l.value != zQuote {
+ return nil, &ParseError{f, "bad NAPTR Service", l}, ""
+ }
+ } else if l.value == zQuote {
+ rr.Service = ""
+ } else {
+ return nil, &ParseError{f, "bad NAPTR Service", l}, ""
+ }
+
+ // Regexp
+ <-c // zBlank
+ l = <-c // _QUOTE
+ if l.value != zQuote {
+ return nil, &ParseError{f, "bad NAPTR Regexp", l}, ""
+ }
+ l = <-c // Either String or Quote
+ if l.value == zString {
+ rr.Regexp = l.token
+ l = <-c // _QUOTE
+ if l.value != zQuote {
+ return nil, &ParseError{f, "bad NAPTR Regexp", l}, ""
+ }
+ } else if l.value == zQuote {
+ rr.Regexp = ""
+ } else {
+ return nil, &ParseError{f, "bad NAPTR Regexp", l}, ""
+ }
+
+ // After quote no space??
+ <-c // zBlank
+ l = <-c // zString
+ rr.Replacement = l.token
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad NAPTR Replacement", l}, ""
+ }
+ rr.Replacement = name
+ return rr, nil, ""
+}
+
+func setTALINK(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(TALINK)
+ rr.Hdr = h
+
+ l := <-c
+ rr.PreviousName = l.token
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ previousName, previousNameOk := toAbsoluteName(l.token, o)
+ if l.err || !previousNameOk {
+ return nil, &ParseError{f, "bad TALINK PreviousName", l}, ""
+ }
+ rr.PreviousName = previousName
+
+ <-c // zBlank
+ l = <-c
+ rr.NextName = l.token
+
+ nextName, nextNameOk := toAbsoluteName(l.token, o)
+ if l.err || !nextNameOk {
+ return nil, &ParseError{f, "bad TALINK NextName", l}, ""
+ }
+ rr.NextName = nextName
+
+ return rr, nil, ""
+}
+
+func setLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(LOC)
+ rr.Hdr = h
+ // Non zero defaults for LOC record, see RFC 1876, Section 3.
+ rr.HorizPre = 165 // 10000
+ rr.VertPre = 162 // 10
+ rr.Size = 18 // 1
+ ok := false
+
+ // North
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+ i, e := strconv.ParseUint(l.token, 10, 32)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad LOC Latitude", l}, ""
+ }
+ rr.Latitude = 1000 * 60 * 60 * uint32(i)
+
+ <-c // zBlank
+ // Either number, 'N' or 'S'
+ l = <-c
+ if rr.Latitude, ok = locCheckNorth(l.token, rr.Latitude); ok {
+ goto East
+ }
+ i, e = strconv.ParseUint(l.token, 10, 32)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad LOC Latitude minutes", l}, ""
+ }
+ rr.Latitude += 1000 * 60 * uint32(i)
+
+ <-c // zBlank
+ l = <-c
+ if i, e := strconv.ParseFloat(l.token, 32); e != nil || l.err {
+ return nil, &ParseError{f, "bad LOC Latitude seconds", l}, ""
+ } else {
+ rr.Latitude += uint32(1000 * i)
+ }
+ <-c // zBlank
+ // Either number, 'N' or 'S'
+ l = <-c
+ if rr.Latitude, ok = locCheckNorth(l.token, rr.Latitude); ok {
+ goto East
+ }
+ // If still alive, flag an error
+ return nil, &ParseError{f, "bad LOC Latitude North/South", l}, ""
+
+East:
+ // East
+ <-c // zBlank
+ l = <-c
+ if i, e := strconv.ParseUint(l.token, 10, 32); e != nil || l.err {
+ return nil, &ParseError{f, "bad LOC Longitude", l}, ""
+ } else {
+ rr.Longitude = 1000 * 60 * 60 * uint32(i)
+ }
+ <-c // zBlank
+ // Either number, 'E' or 'W'
+ l = <-c
+ if rr.Longitude, ok = locCheckEast(l.token, rr.Longitude); ok {
+ goto Altitude
+ }
+ if i, e := strconv.ParseUint(l.token, 10, 32); e != nil || l.err {
+ return nil, &ParseError{f, "bad LOC Longitude minutes", l}, ""
+ } else {
+ rr.Longitude += 1000 * 60 * uint32(i)
+ }
+ <-c // zBlank
+ l = <-c
+ if i, e := strconv.ParseFloat(l.token, 32); e != nil || l.err {
+ return nil, &ParseError{f, "bad LOC Longitude seconds", l}, ""
+ } else {
+ rr.Longitude += uint32(1000 * i)
+ }
+ <-c // zBlank
+ // Either number, 'E' or 'W'
+ l = <-c
+ if rr.Longitude, ok = locCheckEast(l.token, rr.Longitude); ok {
+ goto Altitude
+ }
+ // If still alive, flag an error
+ return nil, &ParseError{f, "bad LOC Longitude East/West", l}, ""
+
+Altitude:
+ <-c // zBlank
+ l = <-c
+ if l.length == 0 || l.err {
+ return nil, &ParseError{f, "bad LOC Altitude", l}, ""
+ }
+ if l.token[len(l.token)-1] == 'M' || l.token[len(l.token)-1] == 'm' {
+ l.token = l.token[0 : len(l.token)-1]
+ }
+ if i, e := strconv.ParseFloat(l.token, 32); e != nil {
+ return nil, &ParseError{f, "bad LOC Altitude", l}, ""
+ } else {
+ rr.Altitude = uint32(i*100.0 + 10000000.0 + 0.5)
+ }
+
+ // And now optionally the other values
+ l = <-c
+ count := 0
+ for l.value != zNewline && l.value != zEOF {
+ switch l.value {
+ case zString:
+ switch count {
+ case 0: // Size
+ e, m, ok := stringToCm(l.token)
+ if !ok {
+ return nil, &ParseError{f, "bad LOC Size", l}, ""
+ }
+ rr.Size = (e & 0x0f) | (m << 4 & 0xf0)
+ case 1: // HorizPre
+ e, m, ok := stringToCm(l.token)
+ if !ok {
+ return nil, &ParseError{f, "bad LOC HorizPre", l}, ""
+ }
+ rr.HorizPre = (e & 0x0f) | (m << 4 & 0xf0)
+ case 2: // VertPre
+ e, m, ok := stringToCm(l.token)
+ if !ok {
+ return nil, &ParseError{f, "bad LOC VertPre", l}, ""
+ }
+ rr.VertPre = (e & 0x0f) | (m << 4 & 0xf0)
+ }
+ count++
+ case zBlank:
+ // Ok
+ default:
+ return nil, &ParseError{f, "bad LOC Size, HorizPre or VertPre", l}, ""
+ }
+ l = <-c
+ }
+ return rr, nil, ""
+}
+
+func setHIP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(HIP)
+ rr.Hdr = h
+
+ // HitLength is not represented
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, l.comment
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 8)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad HIP PublicKeyAlgorithm", l}, ""
+ }
+ rr.PublicKeyAlgorithm = uint8(i)
+
+ <-c // zBlank
+ l = <-c // zString
+ if l.length == 0 || l.err {
+ return nil, &ParseError{f, "bad HIP Hit", l}, ""
+ }
+ rr.Hit = l.token // This can not contain spaces, see RFC 5205 Section 6.
+ rr.HitLength = uint8(len(rr.Hit)) / 2
+
+ <-c // zBlank
+ l = <-c // zString
+ if l.length == 0 || l.err {
+ return nil, &ParseError{f, "bad HIP PublicKey", l}, ""
+ }
+ rr.PublicKey = l.token // This cannot contain spaces
+ rr.PublicKeyLength = uint16(base64.StdEncoding.DecodedLen(len(rr.PublicKey)))
+
+ // RendezvousServers (if any)
+ l = <-c
+ var xs []string
+ for l.value != zNewline && l.value != zEOF {
+ switch l.value {
+ case zString:
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad HIP RendezvousServers", l}, ""
+ }
+ xs = append(xs, name)
+ case zBlank:
+ // Ok
+ default:
+ return nil, &ParseError{f, "bad HIP RendezvousServers", l}, ""
+ }
+ l = <-c
+ }
+ rr.RendezvousServers = xs
+ return rr, nil, l.comment
+}
+
+func setCERT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(CERT)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, l.comment
+ }
+
+ if v, ok := StringToCertType[l.token]; ok {
+ rr.Type = v
+ } else if i, e := strconv.ParseUint(l.token, 10, 16); e != nil {
+ return nil, &ParseError{f, "bad CERT Type", l}, ""
+ } else {
+ rr.Type = uint16(i)
+ }
+ <-c // zBlank
+ l = <-c // zString
+ i, e := strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad CERT KeyTag", l}, ""
+ }
+ rr.KeyTag = uint16(i)
+ <-c // zBlank
+ l = <-c // zString
+ if v, ok := StringToAlgorithm[l.token]; ok {
+ rr.Algorithm = v
+ } else if i, e := strconv.ParseUint(l.token, 10, 8); e != nil {
+ return nil, &ParseError{f, "bad CERT Algorithm", l}, ""
+ } else {
+ rr.Algorithm = uint8(i)
+ }
+ s, e1, c1 := endingToString(c, "bad CERT Certificate", f)
+ if e1 != nil {
+ return nil, e1, c1
+ }
+ rr.Certificate = s
+ return rr, nil, c1
+}
+
+func setOPENPGPKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(OPENPGPKEY)
+ rr.Hdr = h
+
+ s, e, c1 := endingToString(c, "bad OPENPGPKEY PublicKey", f)
+ if e != nil {
+ return nil, e, c1
+ }
+ rr.PublicKey = s
+ return rr, nil, c1
+}
+
+func setSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ r, e, s := setRRSIG(h, c, o, f)
+ if r != nil {
+ return &SIG{*r.(*RRSIG)}, e, s
+ }
+ return nil, e, s
+}
+
+func setRRSIG(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(RRSIG)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, l.comment
+ }
+
+ if t, ok := StringToType[l.tokenUpper]; !ok {
+ if strings.HasPrefix(l.tokenUpper, "TYPE") {
+ t, ok = typeToInt(l.tokenUpper)
+ if !ok {
+ return nil, &ParseError{f, "bad RRSIG Typecovered", l}, ""
+ }
+ rr.TypeCovered = t
+ } else {
+ return nil, &ParseError{f, "bad RRSIG Typecovered", l}, ""
+ }
+ } else {
+ rr.TypeCovered = t
+ }
+
+ <-c // zBlank
+ l = <-c
+ i, err := strconv.ParseUint(l.token, 10, 8)
+ if err != nil || l.err {
+ return nil, &ParseError{f, "bad RRSIG Algorithm", l}, ""
+ }
+ rr.Algorithm = uint8(i)
+
+ <-c // zBlank
+ l = <-c
+ i, err = strconv.ParseUint(l.token, 10, 8)
+ if err != nil || l.err {
+ return nil, &ParseError{f, "bad RRSIG Labels", l}, ""
+ }
+ rr.Labels = uint8(i)
+
+ <-c // zBlank
+ l = <-c
+ i, err = strconv.ParseUint(l.token, 10, 32)
+ if err != nil || l.err {
+ return nil, &ParseError{f, "bad RRSIG OrigTtl", l}, ""
+ }
+ rr.OrigTtl = uint32(i)
+
+ <-c // zBlank
+ l = <-c
+ if i, err := StringToTime(l.token); err != nil {
+ // Try to see if all numeric and use it as epoch
+ if i, err := strconv.ParseInt(l.token, 10, 64); err == nil {
+ // TODO(miek): error out on > MAX_UINT32, same below
+ rr.Expiration = uint32(i)
+ } else {
+ return nil, &ParseError{f, "bad RRSIG Expiration", l}, ""
+ }
+ } else {
+ rr.Expiration = i
+ }
+
+ <-c // zBlank
+ l = <-c
+ if i, err := StringToTime(l.token); err != nil {
+ if i, err := strconv.ParseInt(l.token, 10, 64); err == nil {
+ rr.Inception = uint32(i)
+ } else {
+ return nil, &ParseError{f, "bad RRSIG Inception", l}, ""
+ }
+ } else {
+ rr.Inception = i
+ }
+
+ <-c // zBlank
+ l = <-c
+ i, err = strconv.ParseUint(l.token, 10, 16)
+ if err != nil || l.err {
+ return nil, &ParseError{f, "bad RRSIG KeyTag", l}, ""
+ }
+ rr.KeyTag = uint16(i)
+
+ <-c // zBlank
+ l = <-c
+ rr.SignerName = l.token
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad RRSIG SignerName", l}, ""
+ }
+ rr.SignerName = name
+
+ s, e, c1 := endingToString(c, "bad RRSIG Signature", f)
+ if e != nil {
+ return nil, e, c1
+ }
+ rr.Signature = s
+
+ return rr, nil, c1
+}
+
+func setNSEC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(NSEC)
+ rr.Hdr = h
+
+ l := <-c
+ rr.NextDomain = l.token
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, l.comment
+ }
+
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad NSEC NextDomain", l}, ""
+ }
+ rr.NextDomain = name
+
+ rr.TypeBitMap = make([]uint16, 0)
+ var (
+ k uint16
+ ok bool
+ )
+ l = <-c
+ for l.value != zNewline && l.value != zEOF {
+ switch l.value {
+ case zBlank:
+ // Ok
+ case zString:
+ if k, ok = StringToType[l.tokenUpper]; !ok {
+ if k, ok = typeToInt(l.tokenUpper); !ok {
+ return nil, &ParseError{f, "bad NSEC TypeBitMap", l}, ""
+ }
+ }
+ rr.TypeBitMap = append(rr.TypeBitMap, k)
+ default:
+ return nil, &ParseError{f, "bad NSEC TypeBitMap", l}, ""
+ }
+ l = <-c
+ }
+ return rr, nil, l.comment
+}
+
+func setNSEC3(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(NSEC3)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, l.comment
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 8)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad NSEC3 Hash", l}, ""
+ }
+ rr.Hash = uint8(i)
+ <-c // zBlank
+ l = <-c
+ i, e = strconv.ParseUint(l.token, 10, 8)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad NSEC3 Flags", l}, ""
+ }
+ rr.Flags = uint8(i)
+ <-c // zBlank
+ l = <-c
+ i, e = strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad NSEC3 Iterations", l}, ""
+ }
+ rr.Iterations = uint16(i)
+ <-c
+ l = <-c
+ if len(l.token) == 0 || l.err {
+ return nil, &ParseError{f, "bad NSEC3 Salt", l}, ""
+ }
+ rr.SaltLength = uint8(len(l.token)) / 2
+ rr.Salt = l.token
+
+ <-c
+ l = <-c
+ if len(l.token) == 0 || l.err {
+ return nil, &ParseError{f, "bad NSEC3 NextDomain", l}, ""
+ }
+ rr.HashLength = 20 // Fix for NSEC3 (sha1 160 bits)
+ rr.NextDomain = l.token
+
+ rr.TypeBitMap = make([]uint16, 0)
+ var (
+ k uint16
+ ok bool
+ )
+ l = <-c
+ for l.value != zNewline && l.value != zEOF {
+ switch l.value {
+ case zBlank:
+ // Ok
+ case zString:
+ if k, ok = StringToType[l.tokenUpper]; !ok {
+ if k, ok = typeToInt(l.tokenUpper); !ok {
+ return nil, &ParseError{f, "bad NSEC3 TypeBitMap", l}, ""
+ }
+ }
+ rr.TypeBitMap = append(rr.TypeBitMap, k)
+ default:
+ return nil, &ParseError{f, "bad NSEC3 TypeBitMap", l}, ""
+ }
+ l = <-c
+ }
+ return rr, nil, l.comment
+}
+
+func setNSEC3PARAM(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(NSEC3PARAM)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 8)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad NSEC3PARAM Hash", l}, ""
+ }
+ rr.Hash = uint8(i)
+ <-c // zBlank
+ l = <-c
+ i, e = strconv.ParseUint(l.token, 10, 8)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad NSEC3PARAM Flags", l}, ""
+ }
+ rr.Flags = uint8(i)
+ <-c // zBlank
+ l = <-c
+ i, e = strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad NSEC3PARAM Iterations", l}, ""
+ }
+ rr.Iterations = uint16(i)
+ <-c
+ l = <-c
+ rr.SaltLength = uint8(len(l.token))
+ rr.Salt = l.token
+ return rr, nil, ""
+}
+
+func setEUI48(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(EUI48)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ if l.length != 17 || l.err {
+ return nil, &ParseError{f, "bad EUI48 Address", l}, ""
+ }
+ addr := make([]byte, 12)
+ dash := 0
+ for i := 0; i < 10; i += 2 {
+ addr[i] = l.token[i+dash]
+ addr[i+1] = l.token[i+1+dash]
+ dash++
+ if l.token[i+1+dash] != '-' {
+ return nil, &ParseError{f, "bad EUI48 Address", l}, ""
+ }
+ }
+ addr[10] = l.token[15]
+ addr[11] = l.token[16]
+
+ i, e := strconv.ParseUint(string(addr), 16, 48)
+ if e != nil {
+ return nil, &ParseError{f, "bad EUI48 Address", l}, ""
+ }
+ rr.Address = i
+ return rr, nil, ""
+}
+
+func setEUI64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(EUI64)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ if l.length != 23 || l.err {
+ return nil, &ParseError{f, "bad EUI64 Address", l}, ""
+ }
+ addr := make([]byte, 16)
+ dash := 0
+ for i := 0; i < 14; i += 2 {
+ addr[i] = l.token[i+dash]
+ addr[i+1] = l.token[i+1+dash]
+ dash++
+ if l.token[i+1+dash] != '-' {
+ return nil, &ParseError{f, "bad EUI64 Address", l}, ""
+ }
+ }
+ addr[14] = l.token[21]
+ addr[15] = l.token[22]
+
+ i, e := strconv.ParseUint(string(addr), 16, 64)
+ if e != nil {
+ return nil, &ParseError{f, "bad EUI68 Address", l}, ""
+ }
+ rr.Address = uint64(i)
+ return rr, nil, ""
+}
+
+func setSSHFP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(SSHFP)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 8)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad SSHFP Algorithm", l}, ""
+ }
+ rr.Algorithm = uint8(i)
+ <-c // zBlank
+ l = <-c
+ i, e = strconv.ParseUint(l.token, 10, 8)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad SSHFP Type", l}, ""
+ }
+ rr.Type = uint8(i)
+ <-c // zBlank
+ s, e1, c1 := endingToString(c, "bad SSHFP Fingerprint", f)
+ if e1 != nil {
+ return nil, e1, c1
+ }
+ rr.FingerPrint = s
+ return rr, nil, ""
+}
+
+func setDNSKEYs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, string) {
+ rr := new(DNSKEY)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, l.comment
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad " + typ + " Flags", l}, ""
+ }
+ rr.Flags = uint16(i)
+ <-c // zBlank
+ l = <-c // zString
+ i, e = strconv.ParseUint(l.token, 10, 8)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad " + typ + " Protocol", l}, ""
+ }
+ rr.Protocol = uint8(i)
+ <-c // zBlank
+ l = <-c // zString
+ i, e = strconv.ParseUint(l.token, 10, 8)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad " + typ + " Algorithm", l}, ""
+ }
+ rr.Algorithm = uint8(i)
+ s, e1, c1 := endingToString(c, "bad "+typ+" PublicKey", f)
+ if e1 != nil {
+ return nil, e1, c1
+ }
+ rr.PublicKey = s
+ return rr, nil, c1
+}
+
+func setKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ r, e, s := setDNSKEYs(h, c, o, f, "KEY")
+ if r != nil {
+ return &KEY{*r.(*DNSKEY)}, e, s
+ }
+ return nil, e, s
+}
+
+func setDNSKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ r, e, s := setDNSKEYs(h, c, o, f, "DNSKEY")
+ return r, e, s
+}
+
+func setCDNSKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ r, e, s := setDNSKEYs(h, c, o, f, "CDNSKEY")
+ if r != nil {
+ return &CDNSKEY{*r.(*DNSKEY)}, e, s
+ }
+ return nil, e, s
+}
+
+func setRKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(RKEY)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, l.comment
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad RKEY Flags", l}, ""
+ }
+ rr.Flags = uint16(i)
+ <-c // zBlank
+ l = <-c // zString
+ i, e = strconv.ParseUint(l.token, 10, 8)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad RKEY Protocol", l}, ""
+ }
+ rr.Protocol = uint8(i)
+ <-c // zBlank
+ l = <-c // zString
+ i, e = strconv.ParseUint(l.token, 10, 8)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad RKEY Algorithm", l}, ""
+ }
+ rr.Algorithm = uint8(i)
+ s, e1, c1 := endingToString(c, "bad RKEY PublicKey", f)
+ if e1 != nil {
+ return nil, e1, c1
+ }
+ rr.PublicKey = s
+ return rr, nil, c1
+}
+
+func setEID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(EID)
+ rr.Hdr = h
+ s, e, c1 := endingToString(c, "bad EID Endpoint", f)
+ if e != nil {
+ return nil, e, c1
+ }
+ rr.Endpoint = s
+ return rr, nil, c1
+}
+
+func setNIMLOC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(NIMLOC)
+ rr.Hdr = h
+ s, e, c1 := endingToString(c, "bad NIMLOC Locator", f)
+ if e != nil {
+ return nil, e, c1
+ }
+ rr.Locator = s
+ return rr, nil, c1
+}
+
+func setGPOS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(GPOS)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ _, e := strconv.ParseFloat(l.token, 64)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad GPOS Longitude", l}, ""
+ }
+ rr.Longitude = l.token
+ <-c // zBlank
+ l = <-c
+ _, e = strconv.ParseFloat(l.token, 64)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad GPOS Latitude", l}, ""
+ }
+ rr.Latitude = l.token
+ <-c // zBlank
+ l = <-c
+ _, e = strconv.ParseFloat(l.token, 64)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad GPOS Altitude", l}, ""
+ }
+ rr.Altitude = l.token
+ return rr, nil, ""
+}
+
+func setDSs(h RR_Header, c chan lex, o, f, typ string) (RR, *ParseError, string) {
+ rr := new(DS)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, l.comment
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad " + typ + " KeyTag", l}, ""
+ }
+ rr.KeyTag = uint16(i)
+ <-c // zBlank
+ l = <-c
+ if i, e = strconv.ParseUint(l.token, 10, 8); e != nil {
+ i, ok := StringToAlgorithm[l.tokenUpper]
+ if !ok || l.err {
+ return nil, &ParseError{f, "bad " + typ + " Algorithm", l}, ""
+ }
+ rr.Algorithm = i
+ } else {
+ rr.Algorithm = uint8(i)
+ }
+ <-c // zBlank
+ l = <-c
+ i, e = strconv.ParseUint(l.token, 10, 8)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad " + typ + " DigestType", l}, ""
+ }
+ rr.DigestType = uint8(i)
+ s, e1, c1 := endingToString(c, "bad "+typ+" Digest", f)
+ if e1 != nil {
+ return nil, e1, c1
+ }
+ rr.Digest = s
+ return rr, nil, c1
+}
+
+func setDS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ r, e, s := setDSs(h, c, o, f, "DS")
+ return r, e, s
+}
+
+func setDLV(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ r, e, s := setDSs(h, c, o, f, "DLV")
+ if r != nil {
+ return &DLV{*r.(*DS)}, e, s
+ }
+ return nil, e, s
+}
+
+func setCDS(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ r, e, s := setDSs(h, c, o, f, "CDS")
+ if r != nil {
+ return &CDS{*r.(*DS)}, e, s
+ }
+ return nil, e, s
+}
+
+func setTA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(TA)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, l.comment
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad TA KeyTag", l}, ""
+ }
+ rr.KeyTag = uint16(i)
+ <-c // zBlank
+ l = <-c
+ if i, e := strconv.ParseUint(l.token, 10, 8); e != nil {
+ i, ok := StringToAlgorithm[l.tokenUpper]
+ if !ok || l.err {
+ return nil, &ParseError{f, "bad TA Algorithm", l}, ""
+ }
+ rr.Algorithm = i
+ } else {
+ rr.Algorithm = uint8(i)
+ }
+ <-c // zBlank
+ l = <-c
+ i, e = strconv.ParseUint(l.token, 10, 8)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad TA DigestType", l}, ""
+ }
+ rr.DigestType = uint8(i)
+ s, e, c1 := endingToString(c, "bad TA Digest", f)
+ if e != nil {
+ return nil, e.(*ParseError), c1
+ }
+ rr.Digest = s
+ return rr, nil, c1
+}
+
+func setTLSA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(TLSA)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, l.comment
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 8)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad TLSA Usage", l}, ""
+ }
+ rr.Usage = uint8(i)
+ <-c // zBlank
+ l = <-c
+ i, e = strconv.ParseUint(l.token, 10, 8)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad TLSA Selector", l}, ""
+ }
+ rr.Selector = uint8(i)
+ <-c // zBlank
+ l = <-c
+ i, e = strconv.ParseUint(l.token, 10, 8)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad TLSA MatchingType", l}, ""
+ }
+ rr.MatchingType = uint8(i)
+ // So this needs be e2 (i.e. different than e), because...??t
+ s, e2, c1 := endingToString(c, "bad TLSA Certificate", f)
+ if e2 != nil {
+ return nil, e2, c1
+ }
+ rr.Certificate = s
+ return rr, nil, c1
+}
+
+func setSMIMEA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(SMIMEA)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, l.comment
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 8)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad SMIMEA Usage", l}, ""
+ }
+ rr.Usage = uint8(i)
+ <-c // zBlank
+ l = <-c
+ i, e = strconv.ParseUint(l.token, 10, 8)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad SMIMEA Selector", l}, ""
+ }
+ rr.Selector = uint8(i)
+ <-c // zBlank
+ l = <-c
+ i, e = strconv.ParseUint(l.token, 10, 8)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad SMIMEA MatchingType", l}, ""
+ }
+ rr.MatchingType = uint8(i)
+ // So this needs be e2 (i.e. different than e), because...??t
+ s, e2, c1 := endingToString(c, "bad SMIMEA Certificate", f)
+ if e2 != nil {
+ return nil, e2, c1
+ }
+ rr.Certificate = s
+ return rr, nil, c1
+}
+
+func setRFC3597(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(RFC3597)
+ rr.Hdr = h
+
+ l := <-c
+ if l.token != "\\#" {
+ return nil, &ParseError{f, "bad RFC3597 Rdata", l}, ""
+ }
+
+ <-c // zBlank
+ l = <-c
+ rdlength, e := strconv.Atoi(l.token)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad RFC3597 Rdata ", l}, ""
+ }
+
+ s, e1, c1 := endingToString(c, "bad RFC3597 Rdata", f)
+ if e1 != nil {
+ return nil, e1, c1
+ }
+ if rdlength*2 != len(s) {
+ return nil, &ParseError{f, "bad RFC3597 Rdata", l}, ""
+ }
+ rr.Rdata = s
+ return rr, nil, c1
+}
+
+func setSPF(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(SPF)
+ rr.Hdr = h
+
+ s, e, c1 := endingToTxtSlice(c, "bad SPF Txt", f)
+ if e != nil {
+ return nil, e, ""
+ }
+ rr.Txt = s
+ return rr, nil, c1
+}
+
+func setAVC(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(AVC)
+ rr.Hdr = h
+
+ s, e, c1 := endingToTxtSlice(c, "bad AVC Txt", f)
+ if e != nil {
+ return nil, e, ""
+ }
+ rr.Txt = s
+ return rr, nil, c1
+}
+
+func setTXT(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(TXT)
+ rr.Hdr = h
+
+ // no zBlank reading here, because all this rdata is TXT
+ s, e, c1 := endingToTxtSlice(c, "bad TXT Txt", f)
+ if e != nil {
+ return nil, e, ""
+ }
+ rr.Txt = s
+ return rr, nil, c1
+}
+
+// identical to setTXT
+func setNINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(NINFO)
+ rr.Hdr = h
+
+ s, e, c1 := endingToTxtSlice(c, "bad NINFO ZSData", f)
+ if e != nil {
+ return nil, e, ""
+ }
+ rr.ZSData = s
+ return rr, nil, c1
+}
+
+func setURI(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(URI)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad URI Priority", l}, ""
+ }
+ rr.Priority = uint16(i)
+ <-c // zBlank
+ l = <-c
+ i, e = strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad URI Weight", l}, ""
+ }
+ rr.Weight = uint16(i)
+
+ <-c // zBlank
+ s, err, c1 := endingToTxtSlice(c, "bad URI Target", f)
+ if err != nil {
+ return nil, err, ""
+ }
+ if len(s) > 1 {
+ return nil, &ParseError{f, "bad URI Target", l}, ""
+ }
+ rr.Target = s[0]
+ return rr, nil, c1
+}
+
+func setDHCID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ // awesome record to parse!
+ rr := new(DHCID)
+ rr.Hdr = h
+
+ s, e, c1 := endingToString(c, "bad DHCID Digest", f)
+ if e != nil {
+ return nil, e, c1
+ }
+ rr.Digest = s
+ return rr, nil, c1
+}
+
+func setNID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(NID)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad NID Preference", l}, ""
+ }
+ rr.Preference = uint16(i)
+ <-c // zBlank
+ l = <-c // zString
+ u, err := stringToNodeID(l)
+ if err != nil || l.err {
+ return nil, err, ""
+ }
+ rr.NodeID = u
+ return rr, nil, ""
+}
+
+func setL32(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(L32)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad L32 Preference", l}, ""
+ }
+ rr.Preference = uint16(i)
+ <-c // zBlank
+ l = <-c // zString
+ rr.Locator32 = net.ParseIP(l.token)
+ if rr.Locator32 == nil || l.err {
+ return nil, &ParseError{f, "bad L32 Locator", l}, ""
+ }
+ return rr, nil, ""
+}
+
+func setLP(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(LP)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad LP Preference", l}, ""
+ }
+ rr.Preference = uint16(i)
+
+ <-c // zBlank
+ l = <-c // zString
+ rr.Fqdn = l.token
+ name, nameOk := toAbsoluteName(l.token, o)
+ if l.err || !nameOk {
+ return nil, &ParseError{f, "bad LP Fqdn", l}, ""
+ }
+ rr.Fqdn = name
+
+ return rr, nil, ""
+}
+
+func setL64(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(L64)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad L64 Preference", l}, ""
+ }
+ rr.Preference = uint16(i)
+ <-c // zBlank
+ l = <-c // zString
+ u, err := stringToNodeID(l)
+ if err != nil || l.err {
+ return nil, err, ""
+ }
+ rr.Locator64 = u
+ return rr, nil, ""
+}
+
+func setUID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(UID)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 32)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad UID Uid", l}, ""
+ }
+ rr.Uid = uint32(i)
+ return rr, nil, ""
+}
+
+func setGID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(GID)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 32)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad GID Gid", l}, ""
+ }
+ rr.Gid = uint32(i)
+ return rr, nil, ""
+}
+
+func setUINFO(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(UINFO)
+ rr.Hdr = h
+
+ s, e, c1 := endingToTxtSlice(c, "bad UINFO Uinfo", f)
+ if e != nil {
+ return nil, e, c1
+ }
+ if ln := len(s); ln == 0 {
+ return rr, nil, c1
+ }
+ rr.Uinfo = s[0] // silently discard anything after the first character-string
+ return rr, nil, c1
+}
+
+func setPX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(PX)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, ""
+ }
+
+ i, e := strconv.ParseUint(l.token, 10, 16)
+ if e != nil || l.err {
+ return nil, &ParseError{f, "bad PX Preference", l}, ""
+ }
+ rr.Preference = uint16(i)
+
+ <-c // zBlank
+ l = <-c // zString
+ rr.Map822 = l.token
+ map822, map822Ok := toAbsoluteName(l.token, o)
+ if l.err || !map822Ok {
+ return nil, &ParseError{f, "bad PX Map822", l}, ""
+ }
+ rr.Map822 = map822
+
+ <-c // zBlank
+ l = <-c // zString
+ rr.Mapx400 = l.token
+ mapx400, mapx400Ok := toAbsoluteName(l.token, o)
+ if l.err || !mapx400Ok {
+ return nil, &ParseError{f, "bad PX Mapx400", l}, ""
+ }
+ rr.Mapx400 = mapx400
+
+ return rr, nil, ""
+}
+
+func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
+ rr := new(CAA)
+ rr.Hdr = h
+
+ l := <-c
+ if l.length == 0 { // dynamic update rr.
+ return rr, nil, l.comment
+ }
+
+ i, err := strconv.ParseUint(l.token, 10, 8)
+ if err != nil || l.err {
+ return nil, &ParseError{f, "bad CAA Flag", l}, ""
+ }
+ rr.Flag = uint8(i)
+
+ <-c // zBlank
+ l = <-c // zString
+ if l.value != zString {
+ return nil, &ParseError{f, "bad CAA Tag", l}, ""
+ }
+ rr.Tag = l.token
+
+ <-c // zBlank
+ s, e, c1 := endingToTxtSlice(c, "bad CAA Value", f)
+ if e != nil {
+ return nil, e, ""
+ }
+ if len(s) > 1 {
+ return nil, &ParseError{f, "bad CAA Value", l}, ""
+ }
+ rr.Value = s[0]
+ return rr, nil, c1
+}
+
+var typeToparserFunc = map[uint16]parserFunc{
+ TypeAAAA: {setAAAA, false},
+ TypeAFSDB: {setAFSDB, false},
+ TypeA: {setA, false},
+ TypeCAA: {setCAA, true},
+ TypeCDS: {setCDS, true},
+ TypeCDNSKEY: {setCDNSKEY, true},
+ TypeCERT: {setCERT, true},
+ TypeCNAME: {setCNAME, false},
+ TypeDHCID: {setDHCID, true},
+ TypeDLV: {setDLV, true},
+ TypeDNAME: {setDNAME, false},
+ TypeKEY: {setKEY, true},
+ TypeDNSKEY: {setDNSKEY, true},
+ TypeDS: {setDS, true},
+ TypeEID: {setEID, true},
+ TypeEUI48: {setEUI48, false},
+ TypeEUI64: {setEUI64, false},
+ TypeGID: {setGID, false},
+ TypeGPOS: {setGPOS, false},
+ TypeHINFO: {setHINFO, true},
+ TypeHIP: {setHIP, true},
+ TypeKX: {setKX, false},
+ TypeL32: {setL32, false},
+ TypeL64: {setL64, false},
+ TypeLOC: {setLOC, true},
+ TypeLP: {setLP, false},
+ TypeMB: {setMB, false},
+ TypeMD: {setMD, false},
+ TypeMF: {setMF, false},
+ TypeMG: {setMG, false},
+ TypeMINFO: {setMINFO, false},
+ TypeMR: {setMR, false},
+ TypeMX: {setMX, false},
+ TypeNAPTR: {setNAPTR, false},
+ TypeNID: {setNID, false},
+ TypeNIMLOC: {setNIMLOC, true},
+ TypeNINFO: {setNINFO, true},
+ TypeNSAPPTR: {setNSAPPTR, false},
+ TypeNSEC3PARAM: {setNSEC3PARAM, false},
+ TypeNSEC3: {setNSEC3, true},
+ TypeNSEC: {setNSEC, true},
+ TypeNS: {setNS, false},
+ TypeOPENPGPKEY: {setOPENPGPKEY, true},
+ TypePTR: {setPTR, false},
+ TypePX: {setPX, false},
+ TypeSIG: {setSIG, true},
+ TypeRKEY: {setRKEY, true},
+ TypeRP: {setRP, false},
+ TypeRRSIG: {setRRSIG, true},
+ TypeRT: {setRT, false},
+ TypeSMIMEA: {setSMIMEA, true},
+ TypeSOA: {setSOA, false},
+ TypeSPF: {setSPF, true},
+ TypeAVC: {setAVC, true},
+ TypeSRV: {setSRV, false},
+ TypeSSHFP: {setSSHFP, true},
+ TypeTALINK: {setTALINK, false},
+ TypeTA: {setTA, true},
+ TypeTLSA: {setTLSA, true},
+ TypeTXT: {setTXT, true},
+ TypeUID: {setUID, false},
+ TypeUINFO: {setUINFO, true},
+ TypeURI: {setURI, true},
+ TypeX25: {setX25, false},
+}
--- /dev/null
+package dns
+
+// Implement a simple scanner, return a byte stream from an io reader.
+
+import (
+ "bufio"
+ "io"
+ "text/scanner"
+)
+
+type scan struct {
+ src *bufio.Reader
+ position scanner.Position
+ eof bool // Have we just seen a eof
+}
+
+func scanInit(r io.Reader) *scan {
+ s := new(scan)
+ s.src = bufio.NewReader(r)
+ s.position.Line = 1
+ return s
+}
+
+// tokenText returns the next byte from the input
+func (s *scan) tokenText() (byte, error) {
+ c, err := s.src.ReadByte()
+ if err != nil {
+ return c, err
+ }
+ // delay the newline handling until the next token is delivered,
+ // fixes off-by-one errors when reporting a parse error.
+ if s.eof == true {
+ s.position.Line++
+ s.position.Column = 0
+ s.eof = false
+ }
+ if c == '\n' {
+ s.eof = true
+ return c, nil
+ }
+ s.position.Column++
+ return c, nil
+}
--- /dev/null
+// DNS server implementation.
+
+package dns
+
+import (
+ "bytes"
+ "crypto/tls"
+ "encoding/binary"
+ "io"
+ "net"
+ "sync"
+ "time"
+)
+
+// Maximum number of TCP queries before we close the socket.
+const maxTCPQueries = 128
+
+// Handler is implemented by any value that implements ServeDNS.
+type Handler interface {
+ ServeDNS(w ResponseWriter, r *Msg)
+}
+
+// A ResponseWriter interface is used by an DNS handler to
+// construct an DNS response.
+type ResponseWriter interface {
+ // LocalAddr returns the net.Addr of the server
+ LocalAddr() net.Addr
+ // RemoteAddr returns the net.Addr of the client that sent the current request.
+ RemoteAddr() net.Addr
+ // WriteMsg writes a reply back to the client.
+ WriteMsg(*Msg) error
+ // Write writes a raw buffer back to the client.
+ Write([]byte) (int, error)
+ // Close closes the connection.
+ Close() error
+ // TsigStatus returns the status of the Tsig.
+ TsigStatus() error
+ // TsigTimersOnly sets the tsig timers only boolean.
+ TsigTimersOnly(bool)
+ // Hijack lets the caller take over the connection.
+ // After a call to Hijack(), the DNS package will not do anything with the connection.
+ Hijack()
+}
+
+type response struct {
+ hijacked bool // connection has been hijacked by handler
+ tsigStatus error
+ tsigTimersOnly bool
+ tsigRequestMAC string
+ tsigSecret map[string]string // the tsig secrets
+ udp *net.UDPConn // i/o connection if UDP was used
+ tcp net.Conn // i/o connection if TCP was used
+ udpSession *SessionUDP // oob data to get egress interface right
+ remoteAddr net.Addr // address of the client
+ writer Writer // writer to output the raw DNS bits
+}
+
+// ServeMux is an DNS request multiplexer. It matches the
+// zone name of each incoming request against a list of
+// registered patterns add calls the handler for the pattern
+// that most closely matches the zone name. ServeMux is DNSSEC aware, meaning
+// that queries for the DS record are redirected to the parent zone (if that
+// is also registered), otherwise the child gets the query.
+// ServeMux is also safe for concurrent access from multiple goroutines.
+type ServeMux struct {
+ z map[string]Handler
+ m *sync.RWMutex
+}
+
+// NewServeMux allocates and returns a new ServeMux.
+func NewServeMux() *ServeMux { return &ServeMux{z: make(map[string]Handler), m: new(sync.RWMutex)} }
+
+// DefaultServeMux is the default ServeMux used by Serve.
+var DefaultServeMux = NewServeMux()
+
+// The HandlerFunc type is an adapter to allow the use of
+// ordinary functions as DNS handlers. If f is a function
+// with the appropriate signature, HandlerFunc(f) is a
+// Handler object that calls f.
+type HandlerFunc func(ResponseWriter, *Msg)
+
+// ServeDNS calls f(w, r).
+func (f HandlerFunc) ServeDNS(w ResponseWriter, r *Msg) {
+ f(w, r)
+}
+
+// HandleFailed returns a HandlerFunc that returns SERVFAIL for every request it gets.
+func HandleFailed(w ResponseWriter, r *Msg) {
+ m := new(Msg)
+ m.SetRcode(r, RcodeServerFailure)
+ // does not matter if this write fails
+ w.WriteMsg(m)
+}
+
+func failedHandler() Handler { return HandlerFunc(HandleFailed) }
+
+// ListenAndServe Starts a server on address and network specified Invoke handler
+// for incoming queries.
+func ListenAndServe(addr string, network string, handler Handler) error {
+ server := &Server{Addr: addr, Net: network, Handler: handler}
+ return server.ListenAndServe()
+}
+
+// ListenAndServeTLS acts like http.ListenAndServeTLS, more information in
+// http://golang.org/pkg/net/http/#ListenAndServeTLS
+func ListenAndServeTLS(addr, certFile, keyFile string, handler Handler) error {
+ cert, err := tls.LoadX509KeyPair(certFile, keyFile)
+ if err != nil {
+ return err
+ }
+
+ config := tls.Config{
+ Certificates: []tls.Certificate{cert},
+ }
+
+ server := &Server{
+ Addr: addr,
+ Net: "tcp-tls",
+ TLSConfig: &config,
+ Handler: handler,
+ }
+
+ return server.ListenAndServe()
+}
+
+// ActivateAndServe activates a server with a listener from systemd,
+// l and p should not both be non-nil.
+// If both l and p are not nil only p will be used.
+// Invoke handler for incoming queries.
+func ActivateAndServe(l net.Listener, p net.PacketConn, handler Handler) error {
+ server := &Server{Listener: l, PacketConn: p, Handler: handler}
+ return server.ActivateAndServe()
+}
+
+func (mux *ServeMux) match(q string, t uint16) Handler {
+ mux.m.RLock()
+ defer mux.m.RUnlock()
+ var handler Handler
+ b := make([]byte, len(q)) // worst case, one label of length q
+ off := 0
+ end := false
+ for {
+ l := len(q[off:])
+ for i := 0; i < l; i++ {
+ b[i] = q[off+i]
+ if b[i] >= 'A' && b[i] <= 'Z' {
+ b[i] |= ('a' - 'A')
+ }
+ }
+ if h, ok := mux.z[string(b[:l])]; ok { // causes garbage, might want to change the map key
+ if t != TypeDS {
+ return h
+ }
+ // Continue for DS to see if we have a parent too, if so delegeate to the parent
+ handler = h
+ }
+ off, end = NextLabel(q, off)
+ if end {
+ break
+ }
+ }
+ // Wildcard match, if we have found nothing try the root zone as a last resort.
+ if h, ok := mux.z["."]; ok {
+ return h
+ }
+ return handler
+}
+
+// Handle adds a handler to the ServeMux for pattern.
+func (mux *ServeMux) Handle(pattern string, handler Handler) {
+ if pattern == "" {
+ panic("dns: invalid pattern " + pattern)
+ }
+ mux.m.Lock()
+ mux.z[Fqdn(pattern)] = handler
+ mux.m.Unlock()
+}
+
+// HandleFunc adds a handler function to the ServeMux for pattern.
+func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
+ mux.Handle(pattern, HandlerFunc(handler))
+}
+
+// HandleRemove deregistrars the handler specific for pattern from the ServeMux.
+func (mux *ServeMux) HandleRemove(pattern string) {
+ if pattern == "" {
+ panic("dns: invalid pattern " + pattern)
+ }
+ mux.m.Lock()
+ delete(mux.z, Fqdn(pattern))
+ mux.m.Unlock()
+}
+
+// ServeDNS dispatches the request to the handler whose
+// pattern most closely matches the request message. If DefaultServeMux
+// is used the correct thing for DS queries is done: a possible parent
+// is sought.
+// If no handler is found a standard SERVFAIL message is returned
+// If the request message does not have exactly one question in the
+// question section a SERVFAIL is returned, unlesss Unsafe is true.
+func (mux *ServeMux) ServeDNS(w ResponseWriter, request *Msg) {
+ var h Handler
+ if len(request.Question) < 1 { // allow more than one question
+ h = failedHandler()
+ } else {
+ if h = mux.match(request.Question[0].Name, request.Question[0].Qtype); h == nil {
+ h = failedHandler()
+ }
+ }
+ h.ServeDNS(w, request)
+}
+
+// Handle registers the handler with the given pattern
+// in the DefaultServeMux. The documentation for
+// ServeMux explains how patterns are matched.
+func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
+
+// HandleRemove deregisters the handle with the given pattern
+// in the DefaultServeMux.
+func HandleRemove(pattern string) { DefaultServeMux.HandleRemove(pattern) }
+
+// HandleFunc registers the handler function with the given pattern
+// in the DefaultServeMux.
+func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
+ DefaultServeMux.HandleFunc(pattern, handler)
+}
+
+// Writer writes raw DNS messages; each call to Write should send an entire message.
+type Writer interface {
+ io.Writer
+}
+
+// Reader reads raw DNS messages; each call to ReadTCP or ReadUDP should return an entire message.
+type Reader interface {
+ // ReadTCP reads a raw message from a TCP connection. Implementations may alter
+ // connection properties, for example the read-deadline.
+ ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error)
+ // ReadUDP reads a raw message from a UDP connection. Implementations may alter
+ // connection properties, for example the read-deadline.
+ ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error)
+}
+
+// defaultReader is an adapter for the Server struct that implements the Reader interface
+// using the readTCP and readUDP func of the embedded Server.
+type defaultReader struct {
+ *Server
+}
+
+func (dr *defaultReader) ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
+ return dr.readTCP(conn, timeout)
+}
+
+func (dr *defaultReader) ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) {
+ return dr.readUDP(conn, timeout)
+}
+
+// DecorateReader is a decorator hook for extending or supplanting the functionality of a Reader.
+// Implementations should never return a nil Reader.
+type DecorateReader func(Reader) Reader
+
+// DecorateWriter is a decorator hook for extending or supplanting the functionality of a Writer.
+// Implementations should never return a nil Writer.
+type DecorateWriter func(Writer) Writer
+
+// A Server defines parameters for running an DNS server.
+type Server struct {
+ // Address to listen on, ":dns" if empty.
+ Addr string
+ // if "tcp" or "tcp-tls" (DNS over TLS) it will invoke a TCP listener, otherwise an UDP one
+ Net string
+ // TCP Listener to use, this is to aid in systemd's socket activation.
+ Listener net.Listener
+ // TLS connection configuration
+ TLSConfig *tls.Config
+ // UDP "Listener" to use, this is to aid in systemd's socket activation.
+ PacketConn net.PacketConn
+ // Handler to invoke, dns.DefaultServeMux if nil.
+ Handler Handler
+ // Default buffer size to use to read incoming UDP messages. If not set
+ // it defaults to MinMsgSize (512 B).
+ UDPSize int
+ // The net.Conn.SetReadTimeout value for new connections, defaults to 2 * time.Second.
+ ReadTimeout time.Duration
+ // The net.Conn.SetWriteTimeout value for new connections, defaults to 2 * time.Second.
+ WriteTimeout time.Duration
+ // TCP idle timeout for multiple queries, if nil, defaults to 8 * time.Second (RFC 5966).
+ IdleTimeout func() time.Duration
+ // Secret(s) for Tsig map[<zonename>]<base64 secret>.
+ TsigSecret map[string]string
+ // Unsafe instructs the server to disregard any sanity checks and directly hand the message to
+ // the handler. It will specifically not check if the query has the QR bit not set.
+ Unsafe bool
+ // If NotifyStartedFunc is set it is called once the server has started listening.
+ NotifyStartedFunc func()
+ // DecorateReader is optional, allows customization of the process that reads raw DNS messages.
+ DecorateReader DecorateReader
+ // DecorateWriter is optional, allows customization of the process that writes raw DNS messages.
+ DecorateWriter DecorateWriter
+
+ // Graceful shutdown handling
+
+ inFlight sync.WaitGroup
+
+ lock sync.RWMutex
+ started bool
+}
+
+// ListenAndServe starts a nameserver on the configured address in *Server.
+func (srv *Server) ListenAndServe() error {
+ srv.lock.Lock()
+ defer srv.lock.Unlock()
+ if srv.started {
+ return &Error{err: "server already started"}
+ }
+ addr := srv.Addr
+ if addr == "" {
+ addr = ":domain"
+ }
+ if srv.UDPSize == 0 {
+ srv.UDPSize = MinMsgSize
+ }
+ switch srv.Net {
+ case "tcp", "tcp4", "tcp6":
+ a, err := net.ResolveTCPAddr(srv.Net, addr)
+ if err != nil {
+ return err
+ }
+ l, err := net.ListenTCP(srv.Net, a)
+ if err != nil {
+ return err
+ }
+ srv.Listener = l
+ srv.started = true
+ srv.lock.Unlock()
+ err = srv.serveTCP(l)
+ srv.lock.Lock() // to satisfy the defer at the top
+ return err
+ case "tcp-tls", "tcp4-tls", "tcp6-tls":
+ network := "tcp"
+ if srv.Net == "tcp4-tls" {
+ network = "tcp4"
+ } else if srv.Net == "tcp6-tls" {
+ network = "tcp6"
+ }
+
+ l, err := tls.Listen(network, addr, srv.TLSConfig)
+ if err != nil {
+ return err
+ }
+ srv.Listener = l
+ srv.started = true
+ srv.lock.Unlock()
+ err = srv.serveTCP(l)
+ srv.lock.Lock() // to satisfy the defer at the top
+ return err
+ case "udp", "udp4", "udp6":
+ a, err := net.ResolveUDPAddr(srv.Net, addr)
+ if err != nil {
+ return err
+ }
+ l, err := net.ListenUDP(srv.Net, a)
+ if err != nil {
+ return err
+ }
+ if e := setUDPSocketOptions(l); e != nil {
+ return e
+ }
+ srv.PacketConn = l
+ srv.started = true
+ srv.lock.Unlock()
+ err = srv.serveUDP(l)
+ srv.lock.Lock() // to satisfy the defer at the top
+ return err
+ }
+ return &Error{err: "bad network"}
+}
+
+// ActivateAndServe starts a nameserver with the PacketConn or Listener
+// configured in *Server. Its main use is to start a server from systemd.
+func (srv *Server) ActivateAndServe() error {
+ srv.lock.Lock()
+ defer srv.lock.Unlock()
+ if srv.started {
+ return &Error{err: "server already started"}
+ }
+ pConn := srv.PacketConn
+ l := srv.Listener
+ if pConn != nil {
+ if srv.UDPSize == 0 {
+ srv.UDPSize = MinMsgSize
+ }
+ // Check PacketConn interface's type is valid and value
+ // is not nil
+ if t, ok := pConn.(*net.UDPConn); ok && t != nil {
+ if e := setUDPSocketOptions(t); e != nil {
+ return e
+ }
+ srv.started = true
+ srv.lock.Unlock()
+ e := srv.serveUDP(t)
+ srv.lock.Lock() // to satisfy the defer at the top
+ return e
+ }
+ }
+ if l != nil {
+ srv.started = true
+ srv.lock.Unlock()
+ e := srv.serveTCP(l)
+ srv.lock.Lock() // to satisfy the defer at the top
+ return e
+ }
+ return &Error{err: "bad listeners"}
+}
+
+// Shutdown gracefully shuts down a server. After a call to Shutdown, ListenAndServe and
+// ActivateAndServe will return. All in progress queries are completed before the server
+// is taken down. If the Shutdown is taking longer than the reading timeout an error
+// is returned.
+func (srv *Server) Shutdown() error {
+ srv.lock.Lock()
+ if !srv.started {
+ srv.lock.Unlock()
+ return &Error{err: "server not started"}
+ }
+ srv.started = false
+ srv.lock.Unlock()
+
+ if srv.PacketConn != nil {
+ srv.PacketConn.Close()
+ }
+ if srv.Listener != nil {
+ srv.Listener.Close()
+ }
+
+ fin := make(chan bool)
+ go func() {
+ srv.inFlight.Wait()
+ fin <- true
+ }()
+
+ select {
+ case <-time.After(srv.getReadTimeout()):
+ return &Error{err: "server shutdown is pending"}
+ case <-fin:
+ return nil
+ }
+}
+
+// getReadTimeout is a helper func to use system timeout if server did not intend to change it.
+func (srv *Server) getReadTimeout() time.Duration {
+ rtimeout := dnsTimeout
+ if srv.ReadTimeout != 0 {
+ rtimeout = srv.ReadTimeout
+ }
+ return rtimeout
+}
+
+// serveTCP starts a TCP listener for the server.
+// Each request is handled in a separate goroutine.
+func (srv *Server) serveTCP(l net.Listener) error {
+ defer l.Close()
+
+ if srv.NotifyStartedFunc != nil {
+ srv.NotifyStartedFunc()
+ }
+
+ reader := Reader(&defaultReader{srv})
+ if srv.DecorateReader != nil {
+ reader = srv.DecorateReader(reader)
+ }
+
+ handler := srv.Handler
+ if handler == nil {
+ handler = DefaultServeMux
+ }
+ rtimeout := srv.getReadTimeout()
+ // deadline is not used here
+ for {
+ rw, err := l.Accept()
+ if err != nil {
+ if neterr, ok := err.(net.Error); ok && neterr.Temporary() {
+ continue
+ }
+ return err
+ }
+ m, err := reader.ReadTCP(rw, rtimeout)
+ srv.lock.RLock()
+ if !srv.started {
+ srv.lock.RUnlock()
+ return nil
+ }
+ srv.lock.RUnlock()
+ if err != nil {
+ continue
+ }
+ srv.inFlight.Add(1)
+ go srv.serve(rw.RemoteAddr(), handler, m, nil, nil, rw)
+ }
+}
+
+// serveUDP starts a UDP listener for the server.
+// Each request is handled in a separate goroutine.
+func (srv *Server) serveUDP(l *net.UDPConn) error {
+ defer l.Close()
+
+ if srv.NotifyStartedFunc != nil {
+ srv.NotifyStartedFunc()
+ }
+
+ reader := Reader(&defaultReader{srv})
+ if srv.DecorateReader != nil {
+ reader = srv.DecorateReader(reader)
+ }
+
+ handler := srv.Handler
+ if handler == nil {
+ handler = DefaultServeMux
+ }
+ rtimeout := srv.getReadTimeout()
+ // deadline is not used here
+ for {
+ m, s, err := reader.ReadUDP(l, rtimeout)
+ srv.lock.RLock()
+ if !srv.started {
+ srv.lock.RUnlock()
+ return nil
+ }
+ srv.lock.RUnlock()
+ if err != nil {
+ continue
+ }
+ srv.inFlight.Add(1)
+ go srv.serve(s.RemoteAddr(), handler, m, l, s, nil)
+ }
+}
+
+// Serve a new connection.
+func (srv *Server) serve(a net.Addr, h Handler, m []byte, u *net.UDPConn, s *SessionUDP, t net.Conn) {
+ defer srv.inFlight.Done()
+
+ w := &response{tsigSecret: srv.TsigSecret, udp: u, tcp: t, remoteAddr: a, udpSession: s}
+ if srv.DecorateWriter != nil {
+ w.writer = srv.DecorateWriter(w)
+ } else {
+ w.writer = w
+ }
+
+ q := 0 // counter for the amount of TCP queries we get
+
+ reader := Reader(&defaultReader{srv})
+ if srv.DecorateReader != nil {
+ reader = srv.DecorateReader(reader)
+ }
+Redo:
+ req := new(Msg)
+ err := req.Unpack(m)
+ if err != nil { // Send a FormatError back
+ x := new(Msg)
+ x.SetRcodeFormatError(req)
+ w.WriteMsg(x)
+ goto Exit
+ }
+ if !srv.Unsafe && req.Response {
+ goto Exit
+ }
+
+ w.tsigStatus = nil
+ if w.tsigSecret != nil {
+ if t := req.IsTsig(); t != nil {
+ secret := t.Hdr.Name
+ if _, ok := w.tsigSecret[secret]; !ok {
+ w.tsigStatus = ErrKeyAlg
+ }
+ w.tsigStatus = TsigVerify(m, w.tsigSecret[secret], "", false)
+ w.tsigTimersOnly = false
+ w.tsigRequestMAC = req.Extra[len(req.Extra)-1].(*TSIG).MAC
+ }
+ }
+ h.ServeDNS(w, req) // Writes back to the client
+
+Exit:
+ if w.tcp == nil {
+ return
+ }
+ // TODO(miek): make this number configurable?
+ if q > maxTCPQueries { // close socket after this many queries
+ w.Close()
+ return
+ }
+
+ if w.hijacked {
+ return // client calls Close()
+ }
+ if u != nil { // UDP, "close" and return
+ w.Close()
+ return
+ }
+ idleTimeout := tcpIdleTimeout
+ if srv.IdleTimeout != nil {
+ idleTimeout = srv.IdleTimeout()
+ }
+ m, err = reader.ReadTCP(w.tcp, idleTimeout)
+ if err == nil {
+ q++
+ goto Redo
+ }
+ w.Close()
+ return
+}
+
+func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
+ conn.SetReadDeadline(time.Now().Add(timeout))
+ l := make([]byte, 2)
+ n, err := conn.Read(l)
+ if err != nil || n != 2 {
+ if err != nil {
+ return nil, err
+ }
+ return nil, ErrShortRead
+ }
+ length := binary.BigEndian.Uint16(l)
+ if length == 0 {
+ return nil, ErrShortRead
+ }
+ m := make([]byte, int(length))
+ n, err = conn.Read(m[:int(length)])
+ if err != nil || n == 0 {
+ if err != nil {
+ return nil, err
+ }
+ return nil, ErrShortRead
+ }
+ i := n
+ for i < int(length) {
+ j, err := conn.Read(m[i:int(length)])
+ if err != nil {
+ return nil, err
+ }
+ i += j
+ }
+ n = i
+ m = m[:n]
+ return m, nil
+}
+
+func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) {
+ conn.SetReadDeadline(time.Now().Add(timeout))
+ m := make([]byte, srv.UDPSize)
+ n, s, err := ReadFromSessionUDP(conn, m)
+ if err != nil || n == 0 {
+ if err != nil {
+ return nil, nil, err
+ }
+ return nil, nil, ErrShortRead
+ }
+ m = m[:n]
+ return m, s, nil
+}
+
+// WriteMsg implements the ResponseWriter.WriteMsg method.
+func (w *response) WriteMsg(m *Msg) (err error) {
+ var data []byte
+ if w.tsigSecret != nil { // if no secrets, dont check for the tsig (which is a longer check)
+ if t := m.IsTsig(); t != nil {
+ data, w.tsigRequestMAC, err = TsigGenerate(m, w.tsigSecret[t.Hdr.Name], w.tsigRequestMAC, w.tsigTimersOnly)
+ if err != nil {
+ return err
+ }
+ _, err = w.writer.Write(data)
+ return err
+ }
+ }
+ data, err = m.Pack()
+ if err != nil {
+ return err
+ }
+ _, err = w.writer.Write(data)
+ return err
+}
+
+// Write implements the ResponseWriter.Write method.
+func (w *response) Write(m []byte) (int, error) {
+ switch {
+ case w.udp != nil:
+ n, err := WriteToSessionUDP(w.udp, m, w.udpSession)
+ return n, err
+ case w.tcp != nil:
+ lm := len(m)
+ if lm < 2 {
+ return 0, io.ErrShortBuffer
+ }
+ if lm > MaxMsgSize {
+ return 0, &Error{err: "message too large"}
+ }
+ l := make([]byte, 2, 2+lm)
+ binary.BigEndian.PutUint16(l, uint16(lm))
+ m = append(l, m...)
+
+ n, err := io.Copy(w.tcp, bytes.NewReader(m))
+ return int(n), err
+ }
+ panic("not reached")
+}
+
+// LocalAddr implements the ResponseWriter.LocalAddr method.
+func (w *response) LocalAddr() net.Addr {
+ if w.tcp != nil {
+ return w.tcp.LocalAddr()
+ }
+ return w.udp.LocalAddr()
+}
+
+// RemoteAddr implements the ResponseWriter.RemoteAddr method.
+func (w *response) RemoteAddr() net.Addr { return w.remoteAddr }
+
+// TsigStatus implements the ResponseWriter.TsigStatus method.
+func (w *response) TsigStatus() error { return w.tsigStatus }
+
+// TsigTimersOnly implements the ResponseWriter.TsigTimersOnly method.
+func (w *response) TsigTimersOnly(b bool) { w.tsigTimersOnly = b }
+
+// Hijack implements the ResponseWriter.Hijack method.
+func (w *response) Hijack() { w.hijacked = true }
+
+// Close implements the ResponseWriter.Close method
+func (w *response) Close() error {
+ // Can't close the udp conn, as that is actually the listener.
+ if w.tcp != nil {
+ e := w.tcp.Close()
+ w.tcp = nil
+ return e
+ }
+ return nil
+}
--- /dev/null
+package dns
+
+import (
+ "crypto"
+ "crypto/dsa"
+ "crypto/ecdsa"
+ "crypto/rsa"
+ "encoding/binary"
+ "math/big"
+ "strings"
+ "time"
+)
+
+// Sign signs a dns.Msg. It fills the signature with the appropriate data.
+// The SIG record should have the SignerName, KeyTag, Algorithm, Inception
+// and Expiration set.
+func (rr *SIG) Sign(k crypto.Signer, m *Msg) ([]byte, error) {
+ if k == nil {
+ return nil, ErrPrivKey
+ }
+ if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 {
+ return nil, ErrKey
+ }
+ rr.Header().Rrtype = TypeSIG
+ rr.Header().Class = ClassANY
+ rr.Header().Ttl = 0
+ rr.Header().Name = "."
+ rr.OrigTtl = 0
+ rr.TypeCovered = 0
+ rr.Labels = 0
+
+ buf := make([]byte, m.Len()+rr.len())
+ mbuf, err := m.PackBuffer(buf)
+ if err != nil {
+ return nil, err
+ }
+ if &buf[0] != &mbuf[0] {
+ return nil, ErrBuf
+ }
+ off, err := PackRR(rr, buf, len(mbuf), nil, false)
+ if err != nil {
+ return nil, err
+ }
+ buf = buf[:off:cap(buf)]
+
+ hash, ok := AlgorithmToHash[rr.Algorithm]
+ if !ok {
+ return nil, ErrAlg
+ }
+
+ hasher := hash.New()
+ // Write SIG rdata
+ hasher.Write(buf[len(mbuf)+1+2+2+4+2:])
+ // Write message
+ hasher.Write(buf[:len(mbuf)])
+
+ signature, err := sign(k, hasher.Sum(nil), hash, rr.Algorithm)
+ if err != nil {
+ return nil, err
+ }
+
+ rr.Signature = toBase64(signature)
+
+ buf = append(buf, signature...)
+ if len(buf) > int(^uint16(0)) {
+ return nil, ErrBuf
+ }
+ // Adjust sig data length
+ rdoff := len(mbuf) + 1 + 2 + 2 + 4
+ rdlen := binary.BigEndian.Uint16(buf[rdoff:])
+ rdlen += uint16(len(signature))
+ binary.BigEndian.PutUint16(buf[rdoff:], rdlen)
+ // Adjust additional count
+ adc := binary.BigEndian.Uint16(buf[10:])
+ adc++
+ binary.BigEndian.PutUint16(buf[10:], adc)
+ return buf, nil
+}
+
+// Verify validates the message buf using the key k.
+// It's assumed that buf is a valid message from which rr was unpacked.
+func (rr *SIG) Verify(k *KEY, buf []byte) error {
+ if k == nil {
+ return ErrKey
+ }
+ if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 {
+ return ErrKey
+ }
+
+ var hash crypto.Hash
+ switch rr.Algorithm {
+ case DSA, RSASHA1:
+ hash = crypto.SHA1
+ case RSASHA256, ECDSAP256SHA256:
+ hash = crypto.SHA256
+ case ECDSAP384SHA384:
+ hash = crypto.SHA384
+ case RSASHA512:
+ hash = crypto.SHA512
+ default:
+ return ErrAlg
+ }
+ hasher := hash.New()
+
+ buflen := len(buf)
+ qdc := binary.BigEndian.Uint16(buf[4:])
+ anc := binary.BigEndian.Uint16(buf[6:])
+ auc := binary.BigEndian.Uint16(buf[8:])
+ adc := binary.BigEndian.Uint16(buf[10:])
+ offset := 12
+ var err error
+ for i := uint16(0); i < qdc && offset < buflen; i++ {
+ _, offset, err = UnpackDomainName(buf, offset)
+ if err != nil {
+ return err
+ }
+ // Skip past Type and Class
+ offset += 2 + 2
+ }
+ for i := uint16(1); i < anc+auc+adc && offset < buflen; i++ {
+ _, offset, err = UnpackDomainName(buf, offset)
+ if err != nil {
+ return err
+ }
+ // Skip past Type, Class and TTL
+ offset += 2 + 2 + 4
+ if offset+1 >= buflen {
+ continue
+ }
+ var rdlen uint16
+ rdlen = binary.BigEndian.Uint16(buf[offset:])
+ offset += 2
+ offset += int(rdlen)
+ }
+ if offset >= buflen {
+ return &Error{err: "overflowing unpacking signed message"}
+ }
+
+ // offset should be just prior to SIG
+ bodyend := offset
+ // owner name SHOULD be root
+ _, offset, err = UnpackDomainName(buf, offset)
+ if err != nil {
+ return err
+ }
+ // Skip Type, Class, TTL, RDLen
+ offset += 2 + 2 + 4 + 2
+ sigstart := offset
+ // Skip Type Covered, Algorithm, Labels, Original TTL
+ offset += 2 + 1 + 1 + 4
+ if offset+4+4 >= buflen {
+ return &Error{err: "overflow unpacking signed message"}
+ }
+ expire := binary.BigEndian.Uint32(buf[offset:])
+ offset += 4
+ incept := binary.BigEndian.Uint32(buf[offset:])
+ offset += 4
+ now := uint32(time.Now().Unix())
+ if now < incept || now > expire {
+ return ErrTime
+ }
+ // Skip key tag
+ offset += 2
+ var signername string
+ signername, offset, err = UnpackDomainName(buf, offset)
+ if err != nil {
+ return err
+ }
+ // If key has come from the DNS name compression might
+ // have mangled the case of the name
+ if strings.ToLower(signername) != strings.ToLower(k.Header().Name) {
+ return &Error{err: "signer name doesn't match key name"}
+ }
+ sigend := offset
+ hasher.Write(buf[sigstart:sigend])
+ hasher.Write(buf[:10])
+ hasher.Write([]byte{
+ byte((adc - 1) << 8),
+ byte(adc - 1),
+ })
+ hasher.Write(buf[12:bodyend])
+
+ hashed := hasher.Sum(nil)
+ sig := buf[sigend:]
+ switch k.Algorithm {
+ case DSA:
+ pk := k.publicKeyDSA()
+ sig = sig[1:]
+ r := big.NewInt(0)
+ r.SetBytes(sig[:len(sig)/2])
+ s := big.NewInt(0)
+ s.SetBytes(sig[len(sig)/2:])
+ if pk != nil {
+ if dsa.Verify(pk, hashed, r, s) {
+ return nil
+ }
+ return ErrSig
+ }
+ case RSASHA1, RSASHA256, RSASHA512:
+ pk := k.publicKeyRSA()
+ if pk != nil {
+ return rsa.VerifyPKCS1v15(pk, hash, hashed, sig)
+ }
+ case ECDSAP256SHA256, ECDSAP384SHA384:
+ pk := k.publicKeyECDSA()
+ r := big.NewInt(0)
+ r.SetBytes(sig[:len(sig)/2])
+ s := big.NewInt(0)
+ s.SetBytes(sig[len(sig)/2:])
+ if pk != nil {
+ if ecdsa.Verify(pk, hashed, r, s) {
+ return nil
+ }
+ return ErrSig
+ }
+ }
+ return ErrKeyAlg
+}
--- /dev/null
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Adapted for dns package usage by Miek Gieben.
+
+package dns
+
+import "sync"
+import "time"
+
+// call is an in-flight or completed singleflight.Do call
+type call struct {
+ wg sync.WaitGroup
+ val *Msg
+ rtt time.Duration
+ err error
+ dups int
+}
+
+// singleflight represents a class of work and forms a namespace in
+// which units of work can be executed with duplicate suppression.
+type singleflight struct {
+ sync.Mutex // protects m
+ m map[string]*call // lazily initialized
+}
+
+// Do executes and returns the results of the given function, making
+// sure that only one execution is in-flight for a given key at a
+// time. If a duplicate comes in, the duplicate caller waits for the
+// original to complete and receives the same results.
+// The return value shared indicates whether v was given to multiple callers.
+func (g *singleflight) Do(key string, fn func() (*Msg, time.Duration, error)) (v *Msg, rtt time.Duration, err error, shared bool) {
+ g.Lock()
+ if g.m == nil {
+ g.m = make(map[string]*call)
+ }
+ if c, ok := g.m[key]; ok {
+ c.dups++
+ g.Unlock()
+ c.wg.Wait()
+ return c.val, c.rtt, c.err, true
+ }
+ c := new(call)
+ c.wg.Add(1)
+ g.m[key] = c
+ g.Unlock()
+
+ c.val, c.rtt, c.err = fn()
+ c.wg.Done()
+
+ g.Lock()
+ delete(g.m, key)
+ g.Unlock()
+
+ return c.val, c.rtt, c.err, c.dups > 0
+}
--- /dev/null
+package dns
+
+import (
+ "crypto/sha256"
+ "crypto/x509"
+ "encoding/hex"
+)
+
+// Sign creates a SMIMEA record from an SSL certificate.
+func (r *SMIMEA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (err error) {
+ r.Hdr.Rrtype = TypeSMIMEA
+ r.Usage = uint8(usage)
+ r.Selector = uint8(selector)
+ r.MatchingType = uint8(matchingType)
+
+ r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// Verify verifies a SMIMEA record against an SSL certificate. If it is OK
+// a nil error is returned.
+func (r *SMIMEA) Verify(cert *x509.Certificate) error {
+ c, err := CertificateToDANE(r.Selector, r.MatchingType, cert)
+ if err != nil {
+ return err // Not also ErrSig?
+ }
+ if r.Certificate == c {
+ return nil
+ }
+ return ErrSig // ErrSig, really?
+}
+
+// SMIMEAName returns the ownername of a SMIMEA resource record as per the
+// format specified in RFC 'draft-ietf-dane-smime-12' Section 2 and 3
+func SMIMEAName(email, domain string) (string, error) {
+ hasher := sha256.New()
+ hasher.Write([]byte(email))
+
+ // RFC Section 3: "The local-part is hashed using the SHA2-256
+ // algorithm with the hash truncated to 28 octets and
+ // represented in its hexadecimal representation to become the
+ // left-most label in the prepared domain name"
+ return hex.EncodeToString(hasher.Sum(nil)[:28]) + "." + "_smimecert." + domain, nil
+}
--- /dev/null
+package dns
+
+import (
+ "crypto/x509"
+ "net"
+ "strconv"
+)
+
+// Sign creates a TLSA record from an SSL certificate.
+func (r *TLSA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (err error) {
+ r.Hdr.Rrtype = TypeTLSA
+ r.Usage = uint8(usage)
+ r.Selector = uint8(selector)
+ r.MatchingType = uint8(matchingType)
+
+ r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// Verify verifies a TLSA record against an SSL certificate. If it is OK
+// a nil error is returned.
+func (r *TLSA) Verify(cert *x509.Certificate) error {
+ c, err := CertificateToDANE(r.Selector, r.MatchingType, cert)
+ if err != nil {
+ return err // Not also ErrSig?
+ }
+ if r.Certificate == c {
+ return nil
+ }
+ return ErrSig // ErrSig, really?
+}
+
+// TLSAName returns the ownername of a TLSA resource record as per the
+// rules specified in RFC 6698, Section 3.
+func TLSAName(name, service, network string) (string, error) {
+ if !IsFqdn(name) {
+ return "", ErrFqdn
+ }
+ p, err := net.LookupPort(network, service)
+ if err != nil {
+ return "", err
+ }
+ return "_" + strconv.Itoa(p) + "._" + network + "." + name, nil
+}
--- /dev/null
+package dns
+
+import (
+ "crypto/hmac"
+ "crypto/md5"
+ "crypto/sha1"
+ "crypto/sha256"
+ "crypto/sha512"
+ "encoding/binary"
+ "encoding/hex"
+ "hash"
+ "strconv"
+ "strings"
+ "time"
+)
+
+// HMAC hashing codes. These are transmitted as domain names.
+const (
+ HmacMD5 = "hmac-md5.sig-alg.reg.int."
+ HmacSHA1 = "hmac-sha1."
+ HmacSHA256 = "hmac-sha256."
+ HmacSHA512 = "hmac-sha512."
+)
+
+// TSIG is the RR the holds the transaction signature of a message.
+// See RFC 2845 and RFC 4635.
+type TSIG struct {
+ Hdr RR_Header
+ Algorithm string `dns:"domain-name"`
+ TimeSigned uint64 `dns:"uint48"`
+ Fudge uint16
+ MACSize uint16
+ MAC string `dns:"size-hex:MACSize"`
+ OrigId uint16
+ Error uint16
+ OtherLen uint16
+ OtherData string `dns:"size-hex:OtherLen"`
+}
+
+// TSIG has no official presentation format, but this will suffice.
+
+func (rr *TSIG) String() string {
+ s := "\n;; TSIG PSEUDOSECTION:\n"
+ s += rr.Hdr.String() +
+ " " + rr.Algorithm +
+ " " + tsigTimeToString(rr.TimeSigned) +
+ " " + strconv.Itoa(int(rr.Fudge)) +
+ " " + strconv.Itoa(int(rr.MACSize)) +
+ " " + strings.ToUpper(rr.MAC) +
+ " " + strconv.Itoa(int(rr.OrigId)) +
+ " " + strconv.Itoa(int(rr.Error)) + // BIND prints NOERROR
+ " " + strconv.Itoa(int(rr.OtherLen)) +
+ " " + rr.OtherData
+ return s
+}
+
+// The following values must be put in wireformat, so that the MAC can be calculated.
+// RFC 2845, section 3.4.2. TSIG Variables.
+type tsigWireFmt struct {
+ // From RR_Header
+ Name string `dns:"domain-name"`
+ Class uint16
+ Ttl uint32
+ // Rdata of the TSIG
+ Algorithm string `dns:"domain-name"`
+ TimeSigned uint64 `dns:"uint48"`
+ Fudge uint16
+ // MACSize, MAC and OrigId excluded
+ Error uint16
+ OtherLen uint16
+ OtherData string `dns:"size-hex:OtherLen"`
+}
+
+// If we have the MAC use this type to convert it to wiredata. Section 3.4.3. Request MAC
+type macWireFmt struct {
+ MACSize uint16
+ MAC string `dns:"size-hex:MACSize"`
+}
+
+// 3.3. Time values used in TSIG calculations
+type timerWireFmt struct {
+ TimeSigned uint64 `dns:"uint48"`
+ Fudge uint16
+}
+
+// TsigGenerate fills out the TSIG record attached to the message.
+// The message should contain
+// a "stub" TSIG RR with the algorithm, key name (owner name of the RR),
+// time fudge (defaults to 300 seconds) and the current time
+// The TSIG MAC is saved in that Tsig RR.
+// When TsigGenerate is called for the first time requestMAC is set to the empty string and
+// timersOnly is false.
+// If something goes wrong an error is returned, otherwise it is nil.
+func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, string, error) {
+ if m.IsTsig() == nil {
+ panic("dns: TSIG not last RR in additional")
+ }
+ // If we barf here, the caller is to blame
+ rawsecret, err := fromBase64([]byte(secret))
+ if err != nil {
+ return nil, "", err
+ }
+
+ rr := m.Extra[len(m.Extra)-1].(*TSIG)
+ m.Extra = m.Extra[0 : len(m.Extra)-1] // kill the TSIG from the msg
+ mbuf, err := m.Pack()
+ if err != nil {
+ return nil, "", err
+ }
+ buf := tsigBuffer(mbuf, rr, requestMAC, timersOnly)
+
+ t := new(TSIG)
+ var h hash.Hash
+ switch strings.ToLower(rr.Algorithm) {
+ case HmacMD5:
+ h = hmac.New(md5.New, []byte(rawsecret))
+ case HmacSHA1:
+ h = hmac.New(sha1.New, []byte(rawsecret))
+ case HmacSHA256:
+ h = hmac.New(sha256.New, []byte(rawsecret))
+ case HmacSHA512:
+ h = hmac.New(sha512.New, []byte(rawsecret))
+ default:
+ return nil, "", ErrKeyAlg
+ }
+ h.Write(buf)
+ t.MAC = hex.EncodeToString(h.Sum(nil))
+ t.MACSize = uint16(len(t.MAC) / 2) // Size is half!
+
+ t.Hdr = RR_Header{Name: rr.Hdr.Name, Rrtype: TypeTSIG, Class: ClassANY, Ttl: 0}
+ t.Fudge = rr.Fudge
+ t.TimeSigned = rr.TimeSigned
+ t.Algorithm = rr.Algorithm
+ t.OrigId = m.Id
+
+ tbuf := make([]byte, t.len())
+ if off, err := PackRR(t, tbuf, 0, nil, false); err == nil {
+ tbuf = tbuf[:off] // reset to actual size used
+ } else {
+ return nil, "", err
+ }
+ mbuf = append(mbuf, tbuf...)
+ // Update the ArCount directly in the buffer.
+ binary.BigEndian.PutUint16(mbuf[10:], uint16(len(m.Extra)+1))
+
+ return mbuf, t.MAC, nil
+}
+
+// TsigVerify verifies the TSIG on a message.
+// If the signature does not validate err contains the
+// error, otherwise it is nil.
+func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error {
+ rawsecret, err := fromBase64([]byte(secret))
+ if err != nil {
+ return err
+ }
+ // Strip the TSIG from the incoming msg
+ stripped, tsig, err := stripTsig(msg)
+ if err != nil {
+ return err
+ }
+
+ msgMAC, err := hex.DecodeString(tsig.MAC)
+ if err != nil {
+ return err
+ }
+
+ buf := tsigBuffer(stripped, tsig, requestMAC, timersOnly)
+
+ // Fudge factor works both ways. A message can arrive before it was signed because
+ // of clock skew.
+ now := uint64(time.Now().Unix())
+ ti := now - tsig.TimeSigned
+ if now < tsig.TimeSigned {
+ ti = tsig.TimeSigned - now
+ }
+ if uint64(tsig.Fudge) < ti {
+ return ErrTime
+ }
+
+ var h hash.Hash
+ switch strings.ToLower(tsig.Algorithm) {
+ case HmacMD5:
+ h = hmac.New(md5.New, rawsecret)
+ case HmacSHA1:
+ h = hmac.New(sha1.New, rawsecret)
+ case HmacSHA256:
+ h = hmac.New(sha256.New, rawsecret)
+ case HmacSHA512:
+ h = hmac.New(sha512.New, rawsecret)
+ default:
+ return ErrKeyAlg
+ }
+ h.Write(buf)
+ if !hmac.Equal(h.Sum(nil), msgMAC) {
+ return ErrSig
+ }
+ return nil
+}
+
+// Create a wiredata buffer for the MAC calculation.
+func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []byte {
+ var buf []byte
+ if rr.TimeSigned == 0 {
+ rr.TimeSigned = uint64(time.Now().Unix())
+ }
+ if rr.Fudge == 0 {
+ rr.Fudge = 300 // Standard (RFC) default.
+ }
+
+ // Replace message ID in header with original ID from TSIG
+ binary.BigEndian.PutUint16(msgbuf[0:2], rr.OrigId)
+
+ if requestMAC != "" {
+ m := new(macWireFmt)
+ m.MACSize = uint16(len(requestMAC) / 2)
+ m.MAC = requestMAC
+ buf = make([]byte, len(requestMAC)) // long enough
+ n, _ := packMacWire(m, buf)
+ buf = buf[:n]
+ }
+
+ tsigvar := make([]byte, DefaultMsgSize)
+ if timersOnly {
+ tsig := new(timerWireFmt)
+ tsig.TimeSigned = rr.TimeSigned
+ tsig.Fudge = rr.Fudge
+ n, _ := packTimerWire(tsig, tsigvar)
+ tsigvar = tsigvar[:n]
+ } else {
+ tsig := new(tsigWireFmt)
+ tsig.Name = strings.ToLower(rr.Hdr.Name)
+ tsig.Class = ClassANY
+ tsig.Ttl = rr.Hdr.Ttl
+ tsig.Algorithm = strings.ToLower(rr.Algorithm)
+ tsig.TimeSigned = rr.TimeSigned
+ tsig.Fudge = rr.Fudge
+ tsig.Error = rr.Error
+ tsig.OtherLen = rr.OtherLen
+ tsig.OtherData = rr.OtherData
+ n, _ := packTsigWire(tsig, tsigvar)
+ tsigvar = tsigvar[:n]
+ }
+
+ if requestMAC != "" {
+ x := append(buf, msgbuf...)
+ buf = append(x, tsigvar...)
+ } else {
+ buf = append(msgbuf, tsigvar...)
+ }
+ return buf
+}
+
+// Strip the TSIG from the raw message.
+func stripTsig(msg []byte) ([]byte, *TSIG, error) {
+ // Copied from msg.go's Unpack() Header, but modified.
+ var (
+ dh Header
+ err error
+ )
+ off, tsigoff := 0, 0
+
+ if dh, off, err = unpackMsgHdr(msg, off); err != nil {
+ return nil, nil, err
+ }
+ if dh.Arcount == 0 {
+ return nil, nil, ErrNoSig
+ }
+
+ // Rcode, see msg.go Unpack()
+ if int(dh.Bits&0xF) == RcodeNotAuth {
+ return nil, nil, ErrAuth
+ }
+
+ for i := 0; i < int(dh.Qdcount); i++ {
+ _, off, err = unpackQuestion(msg, off)
+ if err != nil {
+ return nil, nil, err
+ }
+ }
+
+ _, off, err = unpackRRslice(int(dh.Ancount), msg, off)
+ if err != nil {
+ return nil, nil, err
+ }
+ _, off, err = unpackRRslice(int(dh.Nscount), msg, off)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ rr := new(TSIG)
+ var extra RR
+ for i := 0; i < int(dh.Arcount); i++ {
+ tsigoff = off
+ extra, off, err = UnpackRR(msg, off)
+ if err != nil {
+ return nil, nil, err
+ }
+ if extra.Header().Rrtype == TypeTSIG {
+ rr = extra.(*TSIG)
+ // Adjust Arcount.
+ arcount := binary.BigEndian.Uint16(msg[10:])
+ binary.BigEndian.PutUint16(msg[10:], arcount-1)
+ break
+ }
+ }
+ if rr == nil {
+ return nil, nil, ErrNoSig
+ }
+ return msg[:tsigoff], rr, nil
+}
+
+// Translate the TSIG time signed into a date. There is no
+// need for RFC1982 calculations as this date is 48 bits.
+func tsigTimeToString(t uint64) string {
+ ti := time.Unix(int64(t), 0).UTC()
+ return ti.Format("20060102150405")
+}
+
+func packTsigWire(tw *tsigWireFmt, msg []byte) (int, error) {
+ // copied from zmsg.go TSIG packing
+ // RR_Header
+ off, err := PackDomainName(tw.Name, msg, 0, nil, false)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(tw.Class, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(tw.Ttl, msg, off)
+ if err != nil {
+ return off, err
+ }
+
+ off, err = PackDomainName(tw.Algorithm, msg, off, nil, false)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint48(tw.TimeSigned, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(tw.Fudge, msg, off)
+ if err != nil {
+ return off, err
+ }
+
+ off, err = packUint16(tw.Error, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(tw.OtherLen, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringHex(tw.OtherData, msg, off)
+ if err != nil {
+ return off, err
+ }
+ return off, nil
+}
+
+func packMacWire(mw *macWireFmt, msg []byte) (int, error) {
+ off, err := packUint16(mw.MACSize, msg, 0)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringHex(mw.MAC, msg, off)
+ if err != nil {
+ return off, err
+ }
+ return off, nil
+}
+
+func packTimerWire(tw *timerWireFmt, msg []byte) (int, error) {
+ off, err := packUint48(tw.TimeSigned, msg, 0)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(tw.Fudge, msg, off)
+ if err != nil {
+ return off, err
+ }
+ return off, nil
+}
--- /dev/null
+package dns
+
+import (
+ "fmt"
+ "net"
+ "strconv"
+ "strings"
+ "time"
+)
+
+type (
+ // Type is a DNS type.
+ Type uint16
+ // Class is a DNS class.
+ Class uint16
+ // Name is a DNS domain name.
+ Name string
+)
+
+// Packet formats
+
+// Wire constants and supported types.
+const (
+ // valid RR_Header.Rrtype and Question.qtype
+
+ TypeNone uint16 = 0
+ TypeA uint16 = 1
+ TypeNS uint16 = 2
+ TypeMD uint16 = 3
+ TypeMF uint16 = 4
+ TypeCNAME uint16 = 5
+ TypeSOA uint16 = 6
+ TypeMB uint16 = 7
+ TypeMG uint16 = 8
+ TypeMR uint16 = 9
+ TypeNULL uint16 = 10
+ TypePTR uint16 = 12
+ TypeHINFO uint16 = 13
+ TypeMINFO uint16 = 14
+ TypeMX uint16 = 15
+ TypeTXT uint16 = 16
+ TypeRP uint16 = 17
+ TypeAFSDB uint16 = 18
+ TypeX25 uint16 = 19
+ TypeISDN uint16 = 20
+ TypeRT uint16 = 21
+ TypeNSAPPTR uint16 = 23
+ TypeSIG uint16 = 24
+ TypeKEY uint16 = 25
+ TypePX uint16 = 26
+ TypeGPOS uint16 = 27
+ TypeAAAA uint16 = 28
+ TypeLOC uint16 = 29
+ TypeNXT uint16 = 30
+ TypeEID uint16 = 31
+ TypeNIMLOC uint16 = 32
+ TypeSRV uint16 = 33
+ TypeATMA uint16 = 34
+ TypeNAPTR uint16 = 35
+ TypeKX uint16 = 36
+ TypeCERT uint16 = 37
+ TypeDNAME uint16 = 39
+ TypeOPT uint16 = 41 // EDNS
+ TypeDS uint16 = 43
+ TypeSSHFP uint16 = 44
+ TypeRRSIG uint16 = 46
+ TypeNSEC uint16 = 47
+ TypeDNSKEY uint16 = 48
+ TypeDHCID uint16 = 49
+ TypeNSEC3 uint16 = 50
+ TypeNSEC3PARAM uint16 = 51
+ TypeTLSA uint16 = 52
+ TypeSMIMEA uint16 = 53
+ TypeHIP uint16 = 55
+ TypeNINFO uint16 = 56
+ TypeRKEY uint16 = 57
+ TypeTALINK uint16 = 58
+ TypeCDS uint16 = 59
+ TypeCDNSKEY uint16 = 60
+ TypeOPENPGPKEY uint16 = 61
+ TypeSPF uint16 = 99
+ TypeUINFO uint16 = 100
+ TypeUID uint16 = 101
+ TypeGID uint16 = 102
+ TypeUNSPEC uint16 = 103
+ TypeNID uint16 = 104
+ TypeL32 uint16 = 105
+ TypeL64 uint16 = 106
+ TypeLP uint16 = 107
+ TypeEUI48 uint16 = 108
+ TypeEUI64 uint16 = 109
+ TypeURI uint16 = 256
+ TypeCAA uint16 = 257
+ TypeAVC uint16 = 258
+
+ TypeTKEY uint16 = 249
+ TypeTSIG uint16 = 250
+
+ // valid Question.Qtype only
+ TypeIXFR uint16 = 251
+ TypeAXFR uint16 = 252
+ TypeMAILB uint16 = 253
+ TypeMAILA uint16 = 254
+ TypeANY uint16 = 255
+
+ TypeTA uint16 = 32768
+ TypeDLV uint16 = 32769
+ TypeReserved uint16 = 65535
+
+ // valid Question.Qclass
+ ClassINET = 1
+ ClassCSNET = 2
+ ClassCHAOS = 3
+ ClassHESIOD = 4
+ ClassNONE = 254
+ ClassANY = 255
+
+ // Message Response Codes, see https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
+ RcodeSuccess = 0 // NoError - No Error [DNS]
+ RcodeFormatError = 1 // FormErr - Format Error [DNS]
+ RcodeServerFailure = 2 // ServFail - Server Failure [DNS]
+ RcodeNameError = 3 // NXDomain - Non-Existent Domain [DNS]
+ RcodeNotImplemented = 4 // NotImp - Not Implemented [DNS]
+ RcodeRefused = 5 // Refused - Query Refused [DNS]
+ RcodeYXDomain = 6 // YXDomain - Name Exists when it should not [DNS Update]
+ RcodeYXRrset = 7 // YXRRSet - RR Set Exists when it should not [DNS Update]
+ RcodeNXRrset = 8 // NXRRSet - RR Set that should exist does not [DNS Update]
+ RcodeNotAuth = 9 // NotAuth - Server Not Authoritative for zone [DNS Update]
+ RcodeNotZone = 10 // NotZone - Name not contained in zone [DNS Update/TSIG]
+ RcodeBadSig = 16 // BADSIG - TSIG Signature Failure [TSIG]
+ RcodeBadVers = 16 // BADVERS - Bad OPT Version [EDNS0]
+ RcodeBadKey = 17 // BADKEY - Key not recognized [TSIG]
+ RcodeBadTime = 18 // BADTIME - Signature out of time window [TSIG]
+ RcodeBadMode = 19 // BADMODE - Bad TKEY Mode [TKEY]
+ RcodeBadName = 20 // BADNAME - Duplicate key name [TKEY]
+ RcodeBadAlg = 21 // BADALG - Algorithm not supported [TKEY]
+ RcodeBadTrunc = 22 // BADTRUNC - Bad Truncation [TSIG]
+ RcodeBadCookie = 23 // BADCOOKIE - Bad/missing Server Cookie [DNS Cookies]
+
+ // Message Opcodes. There is no 3.
+ OpcodeQuery = 0
+ OpcodeIQuery = 1
+ OpcodeStatus = 2
+ OpcodeNotify = 4
+ OpcodeUpdate = 5
+)
+
+// Header is the wire format for the DNS packet header.
+type Header struct {
+ Id uint16
+ Bits uint16
+ Qdcount, Ancount, Nscount, Arcount uint16
+}
+
+const (
+ headerSize = 12
+
+ // Header.Bits
+ _QR = 1 << 15 // query/response (response=1)
+ _AA = 1 << 10 // authoritative
+ _TC = 1 << 9 // truncated
+ _RD = 1 << 8 // recursion desired
+ _RA = 1 << 7 // recursion available
+ _Z = 1 << 6 // Z
+ _AD = 1 << 5 // authticated data
+ _CD = 1 << 4 // checking disabled
+)
+
+// Various constants used in the LOC RR, See RFC 1887.
+const (
+ LOC_EQUATOR = 1 << 31 // RFC 1876, Section 2.
+ LOC_PRIMEMERIDIAN = 1 << 31 // RFC 1876, Section 2.
+ LOC_HOURS = 60 * 1000
+ LOC_DEGREES = 60 * LOC_HOURS
+ LOC_ALTITUDEBASE = 100000
+)
+
+// Different Certificate Types, see RFC 4398, Section 2.1
+const (
+ CertPKIX = 1 + iota
+ CertSPKI
+ CertPGP
+ CertIPIX
+ CertISPKI
+ CertIPGP
+ CertACPKIX
+ CertIACPKIX
+ CertURI = 253
+ CertOID = 254
+)
+
+// CertTypeToString converts the Cert Type to its string representation.
+// See RFC 4398 and RFC 6944.
+var CertTypeToString = map[uint16]string{
+ CertPKIX: "PKIX",
+ CertSPKI: "SPKI",
+ CertPGP: "PGP",
+ CertIPIX: "IPIX",
+ CertISPKI: "ISPKI",
+ CertIPGP: "IPGP",
+ CertACPKIX: "ACPKIX",
+ CertIACPKIX: "IACPKIX",
+ CertURI: "URI",
+ CertOID: "OID",
+}
+
+// StringToCertType is the reverseof CertTypeToString.
+var StringToCertType = reverseInt16(CertTypeToString)
+
+//go:generate go run types_generate.go
+
+// Question holds a DNS question. There can be multiple questions in the
+// question section of a message. Usually there is just one.
+type Question struct {
+ Name string `dns:"cdomain-name"` // "cdomain-name" specifies encoding (and may be compressed)
+ Qtype uint16
+ Qclass uint16
+}
+
+func (q *Question) len() int {
+ return len(q.Name) + 1 + 2 + 2
+}
+
+func (q *Question) String() (s string) {
+ // prefix with ; (as in dig)
+ s = ";" + sprintName(q.Name) + "\t"
+ s += Class(q.Qclass).String() + "\t"
+ s += " " + Type(q.Qtype).String()
+ return s
+}
+
+// ANY is a wildcard record. See RFC 1035, Section 3.2.3. ANY
+// is named "*" there.
+type ANY struct {
+ Hdr RR_Header
+ // Does not have any rdata
+}
+
+func (rr *ANY) String() string { return rr.Hdr.String() }
+
+// CNAME RR. See RFC 1034.
+type CNAME struct {
+ Hdr RR_Header
+ Target string `dns:"cdomain-name"`
+}
+
+func (rr *CNAME) String() string { return rr.Hdr.String() + sprintName(rr.Target) }
+
+// HINFO RR. See RFC 1034.
+type HINFO struct {
+ Hdr RR_Header
+ Cpu string
+ Os string
+}
+
+func (rr *HINFO) String() string {
+ return rr.Hdr.String() + sprintTxt([]string{rr.Cpu, rr.Os})
+}
+
+// MB RR. See RFC 1035.
+type MB struct {
+ Hdr RR_Header
+ Mb string `dns:"cdomain-name"`
+}
+
+func (rr *MB) String() string { return rr.Hdr.String() + sprintName(rr.Mb) }
+
+// MG RR. See RFC 1035.
+type MG struct {
+ Hdr RR_Header
+ Mg string `dns:"cdomain-name"`
+}
+
+func (rr *MG) String() string { return rr.Hdr.String() + sprintName(rr.Mg) }
+
+// MINFO RR. See RFC 1035.
+type MINFO struct {
+ Hdr RR_Header
+ Rmail string `dns:"cdomain-name"`
+ Email string `dns:"cdomain-name"`
+}
+
+func (rr *MINFO) String() string {
+ return rr.Hdr.String() + sprintName(rr.Rmail) + " " + sprintName(rr.Email)
+}
+
+// MR RR. See RFC 1035.
+type MR struct {
+ Hdr RR_Header
+ Mr string `dns:"cdomain-name"`
+}
+
+func (rr *MR) String() string {
+ return rr.Hdr.String() + sprintName(rr.Mr)
+}
+
+// MF RR. See RFC 1035.
+type MF struct {
+ Hdr RR_Header
+ Mf string `dns:"cdomain-name"`
+}
+
+func (rr *MF) String() string {
+ return rr.Hdr.String() + sprintName(rr.Mf)
+}
+
+// MD RR. See RFC 1035.
+type MD struct {
+ Hdr RR_Header
+ Md string `dns:"cdomain-name"`
+}
+
+func (rr *MD) String() string {
+ return rr.Hdr.String() + sprintName(rr.Md)
+}
+
+// MX RR. See RFC 1035.
+type MX struct {
+ Hdr RR_Header
+ Preference uint16
+ Mx string `dns:"cdomain-name"`
+}
+
+func (rr *MX) String() string {
+ return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Mx)
+}
+
+// AFSDB RR. See RFC 1183.
+type AFSDB struct {
+ Hdr RR_Header
+ Subtype uint16
+ Hostname string `dns:"cdomain-name"`
+}
+
+func (rr *AFSDB) String() string {
+ return rr.Hdr.String() + strconv.Itoa(int(rr.Subtype)) + " " + sprintName(rr.Hostname)
+}
+
+// X25 RR. See RFC 1183, Section 3.1.
+type X25 struct {
+ Hdr RR_Header
+ PSDNAddress string
+}
+
+func (rr *X25) String() string {
+ return rr.Hdr.String() + rr.PSDNAddress
+}
+
+// RT RR. See RFC 1183, Section 3.3.
+type RT struct {
+ Hdr RR_Header
+ Preference uint16
+ Host string `dns:"cdomain-name"`
+}
+
+func (rr *RT) String() string {
+ return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Host)
+}
+
+// NS RR. See RFC 1035.
+type NS struct {
+ Hdr RR_Header
+ Ns string `dns:"cdomain-name"`
+}
+
+func (rr *NS) String() string {
+ return rr.Hdr.String() + sprintName(rr.Ns)
+}
+
+// PTR RR. See RFC 1035.
+type PTR struct {
+ Hdr RR_Header
+ Ptr string `dns:"cdomain-name"`
+}
+
+func (rr *PTR) String() string {
+ return rr.Hdr.String() + sprintName(rr.Ptr)
+}
+
+// RP RR. See RFC 1138, Section 2.2.
+type RP struct {
+ Hdr RR_Header
+ Mbox string `dns:"domain-name"`
+ Txt string `dns:"domain-name"`
+}
+
+func (rr *RP) String() string {
+ return rr.Hdr.String() + rr.Mbox + " " + sprintTxt([]string{rr.Txt})
+}
+
+// SOA RR. See RFC 1035.
+type SOA struct {
+ Hdr RR_Header
+ Ns string `dns:"cdomain-name"`
+ Mbox string `dns:"cdomain-name"`
+ Serial uint32
+ Refresh uint32
+ Retry uint32
+ Expire uint32
+ Minttl uint32
+}
+
+func (rr *SOA) String() string {
+ return rr.Hdr.String() + sprintName(rr.Ns) + " " + sprintName(rr.Mbox) +
+ " " + strconv.FormatInt(int64(rr.Serial), 10) +
+ " " + strconv.FormatInt(int64(rr.Refresh), 10) +
+ " " + strconv.FormatInt(int64(rr.Retry), 10) +
+ " " + strconv.FormatInt(int64(rr.Expire), 10) +
+ " " + strconv.FormatInt(int64(rr.Minttl), 10)
+}
+
+// TXT RR. See RFC 1035.
+type TXT struct {
+ Hdr RR_Header
+ Txt []string `dns:"txt"`
+}
+
+func (rr *TXT) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
+
+func sprintName(s string) string {
+ src := []byte(s)
+ dst := make([]byte, 0, len(src))
+ for i := 0; i < len(src); {
+ if i+1 < len(src) && src[i] == '\\' && src[i+1] == '.' {
+ dst = append(dst, src[i:i+2]...)
+ i += 2
+ } else {
+ b, n := nextByte(src, i)
+ if n == 0 {
+ i++ // dangling back slash
+ } else if b == '.' {
+ dst = append(dst, b)
+ } else {
+ dst = appendDomainNameByte(dst, b)
+ }
+ i += n
+ }
+ }
+ return string(dst)
+}
+
+func sprintTxtOctet(s string) string {
+ src := []byte(s)
+ dst := make([]byte, 0, len(src))
+ dst = append(dst, '"')
+ for i := 0; i < len(src); {
+ if i+1 < len(src) && src[i] == '\\' && src[i+1] == '.' {
+ dst = append(dst, src[i:i+2]...)
+ i += 2
+ } else {
+ b, n := nextByte(src, i)
+ if n == 0 {
+ i++ // dangling back slash
+ } else if b == '.' {
+ dst = append(dst, b)
+ } else {
+ if b < ' ' || b > '~' {
+ dst = appendByte(dst, b)
+ } else {
+ dst = append(dst, b)
+ }
+ }
+ i += n
+ }
+ }
+ dst = append(dst, '"')
+ return string(dst)
+}
+
+func sprintTxt(txt []string) string {
+ var out []byte
+ for i, s := range txt {
+ if i > 0 {
+ out = append(out, ` "`...)
+ } else {
+ out = append(out, '"')
+ }
+ bs := []byte(s)
+ for j := 0; j < len(bs); {
+ b, n := nextByte(bs, j)
+ if n == 0 {
+ break
+ }
+ out = appendTXTStringByte(out, b)
+ j += n
+ }
+ out = append(out, '"')
+ }
+ return string(out)
+}
+
+func appendDomainNameByte(s []byte, b byte) []byte {
+ switch b {
+ case '.', ' ', '\'', '@', ';', '(', ')': // additional chars to escape
+ return append(s, '\\', b)
+ }
+ return appendTXTStringByte(s, b)
+}
+
+func appendTXTStringByte(s []byte, b byte) []byte {
+ switch b {
+ case '"', '\\':
+ return append(s, '\\', b)
+ }
+ if b < ' ' || b > '~' {
+ return appendByte(s, b)
+ }
+ return append(s, b)
+}
+
+func appendByte(s []byte, b byte) []byte {
+ var buf [3]byte
+ bufs := strconv.AppendInt(buf[:0], int64(b), 10)
+ s = append(s, '\\')
+ for i := 0; i < 3-len(bufs); i++ {
+ s = append(s, '0')
+ }
+ for _, r := range bufs {
+ s = append(s, r)
+ }
+ return s
+}
+
+func nextByte(b []byte, offset int) (byte, int) {
+ if offset >= len(b) {
+ return 0, 0
+ }
+ if b[offset] != '\\' {
+ // not an escape sequence
+ return b[offset], 1
+ }
+ switch len(b) - offset {
+ case 1: // dangling escape
+ return 0, 0
+ case 2, 3: // too short to be \ddd
+ default: // maybe \ddd
+ if isDigit(b[offset+1]) && isDigit(b[offset+2]) && isDigit(b[offset+3]) {
+ return dddToByte(b[offset+1:]), 4
+ }
+ }
+ // not \ddd, just an RFC 1035 "quoted" character
+ return b[offset+1], 2
+}
+
+// SPF RR. See RFC 4408, Section 3.1.1.
+type SPF struct {
+ Hdr RR_Header
+ Txt []string `dns:"txt"`
+}
+
+func (rr *SPF) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
+
+// AVC RR. See https://www.iana.org/assignments/dns-parameters/AVC/avc-completed-template.
+type AVC struct {
+ Hdr RR_Header
+ Txt []string `dns:"txt"`
+}
+
+func (rr *AVC) String() string { return rr.Hdr.String() + sprintTxt(rr.Txt) }
+
+// SRV RR. See RFC 2782.
+type SRV struct {
+ Hdr RR_Header
+ Priority uint16
+ Weight uint16
+ Port uint16
+ Target string `dns:"domain-name"`
+}
+
+func (rr *SRV) String() string {
+ return rr.Hdr.String() +
+ strconv.Itoa(int(rr.Priority)) + " " +
+ strconv.Itoa(int(rr.Weight)) + " " +
+ strconv.Itoa(int(rr.Port)) + " " + sprintName(rr.Target)
+}
+
+// NAPTR RR. See RFC 2915.
+type NAPTR struct {
+ Hdr RR_Header
+ Order uint16
+ Preference uint16
+ Flags string
+ Service string
+ Regexp string
+ Replacement string `dns:"domain-name"`
+}
+
+func (rr *NAPTR) String() string {
+ return rr.Hdr.String() +
+ strconv.Itoa(int(rr.Order)) + " " +
+ strconv.Itoa(int(rr.Preference)) + " " +
+ "\"" + rr.Flags + "\" " +
+ "\"" + rr.Service + "\" " +
+ "\"" + rr.Regexp + "\" " +
+ rr.Replacement
+}
+
+// CERT RR. See RFC 4398.
+type CERT struct {
+ Hdr RR_Header
+ Type uint16
+ KeyTag uint16
+ Algorithm uint8
+ Certificate string `dns:"base64"`
+}
+
+func (rr *CERT) String() string {
+ var (
+ ok bool
+ certtype, algorithm string
+ )
+ if certtype, ok = CertTypeToString[rr.Type]; !ok {
+ certtype = strconv.Itoa(int(rr.Type))
+ }
+ if algorithm, ok = AlgorithmToString[rr.Algorithm]; !ok {
+ algorithm = strconv.Itoa(int(rr.Algorithm))
+ }
+ return rr.Hdr.String() + certtype +
+ " " + strconv.Itoa(int(rr.KeyTag)) +
+ " " + algorithm +
+ " " + rr.Certificate
+}
+
+// DNAME RR. See RFC 2672.
+type DNAME struct {
+ Hdr RR_Header
+ Target string `dns:"domain-name"`
+}
+
+func (rr *DNAME) String() string {
+ return rr.Hdr.String() + sprintName(rr.Target)
+}
+
+// A RR. See RFC 1035.
+type A struct {
+ Hdr RR_Header
+ A net.IP `dns:"a"`
+}
+
+func (rr *A) String() string {
+ if rr.A == nil {
+ return rr.Hdr.String()
+ }
+ return rr.Hdr.String() + rr.A.String()
+}
+
+// AAAA RR. See RFC 3596.
+type AAAA struct {
+ Hdr RR_Header
+ AAAA net.IP `dns:"aaaa"`
+}
+
+func (rr *AAAA) String() string {
+ if rr.AAAA == nil {
+ return rr.Hdr.String()
+ }
+ return rr.Hdr.String() + rr.AAAA.String()
+}
+
+// PX RR. See RFC 2163.
+type PX struct {
+ Hdr RR_Header
+ Preference uint16
+ Map822 string `dns:"domain-name"`
+ Mapx400 string `dns:"domain-name"`
+}
+
+func (rr *PX) String() string {
+ return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Map822) + " " + sprintName(rr.Mapx400)
+}
+
+// GPOS RR. See RFC 1712.
+type GPOS struct {
+ Hdr RR_Header
+ Longitude string
+ Latitude string
+ Altitude string
+}
+
+func (rr *GPOS) String() string {
+ return rr.Hdr.String() + rr.Longitude + " " + rr.Latitude + " " + rr.Altitude
+}
+
+// LOC RR. See RFC RFC 1876.
+type LOC struct {
+ Hdr RR_Header
+ Version uint8
+ Size uint8
+ HorizPre uint8
+ VertPre uint8
+ Latitude uint32
+ Longitude uint32
+ Altitude uint32
+}
+
+// cmToM takes a cm value expressed in RFC1876 SIZE mantissa/exponent
+// format and returns a string in m (two decimals for the cm)
+func cmToM(m, e uint8) string {
+ if e < 2 {
+ if e == 1 {
+ m *= 10
+ }
+
+ return fmt.Sprintf("0.%02d", m)
+ }
+
+ s := fmt.Sprintf("%d", m)
+ for e > 2 {
+ s += "0"
+ e--
+ }
+ return s
+}
+
+func (rr *LOC) String() string {
+ s := rr.Hdr.String()
+
+ lat := rr.Latitude
+ ns := "N"
+ if lat > LOC_EQUATOR {
+ lat = lat - LOC_EQUATOR
+ } else {
+ ns = "S"
+ lat = LOC_EQUATOR - lat
+ }
+ h := lat / LOC_DEGREES
+ lat = lat % LOC_DEGREES
+ m := lat / LOC_HOURS
+ lat = lat % LOC_HOURS
+ s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, (float64(lat) / 1000), ns)
+
+ lon := rr.Longitude
+ ew := "E"
+ if lon > LOC_PRIMEMERIDIAN {
+ lon = lon - LOC_PRIMEMERIDIAN
+ } else {
+ ew = "W"
+ lon = LOC_PRIMEMERIDIAN - lon
+ }
+ h = lon / LOC_DEGREES
+ lon = lon % LOC_DEGREES
+ m = lon / LOC_HOURS
+ lon = lon % LOC_HOURS
+ s += fmt.Sprintf("%02d %02d %0.3f %s ", h, m, (float64(lon) / 1000), ew)
+
+ var alt = float64(rr.Altitude) / 100
+ alt -= LOC_ALTITUDEBASE
+ if rr.Altitude%100 != 0 {
+ s += fmt.Sprintf("%.2fm ", alt)
+ } else {
+ s += fmt.Sprintf("%.0fm ", alt)
+ }
+
+ s += cmToM((rr.Size&0xf0)>>4, rr.Size&0x0f) + "m "
+ s += cmToM((rr.HorizPre&0xf0)>>4, rr.HorizPre&0x0f) + "m "
+ s += cmToM((rr.VertPre&0xf0)>>4, rr.VertPre&0x0f) + "m"
+
+ return s
+}
+
+// SIG RR. See RFC 2535. The SIG RR is identical to RRSIG and nowadays only used for SIG(0), See RFC 2931.
+type SIG struct {
+ RRSIG
+}
+
+// RRSIG RR. See RFC 4034 and RFC 3755.
+type RRSIG struct {
+ Hdr RR_Header
+ TypeCovered uint16
+ Algorithm uint8
+ Labels uint8
+ OrigTtl uint32
+ Expiration uint32
+ Inception uint32
+ KeyTag uint16
+ SignerName string `dns:"domain-name"`
+ Signature string `dns:"base64"`
+}
+
+func (rr *RRSIG) String() string {
+ s := rr.Hdr.String()
+ s += Type(rr.TypeCovered).String()
+ s += " " + strconv.Itoa(int(rr.Algorithm)) +
+ " " + strconv.Itoa(int(rr.Labels)) +
+ " " + strconv.FormatInt(int64(rr.OrigTtl), 10) +
+ " " + TimeToString(rr.Expiration) +
+ " " + TimeToString(rr.Inception) +
+ " " + strconv.Itoa(int(rr.KeyTag)) +
+ " " + sprintName(rr.SignerName) +
+ " " + rr.Signature
+ return s
+}
+
+// NSEC RR. See RFC 4034 and RFC 3755.
+type NSEC struct {
+ Hdr RR_Header
+ NextDomain string `dns:"domain-name"`
+ TypeBitMap []uint16 `dns:"nsec"`
+}
+
+func (rr *NSEC) String() string {
+ s := rr.Hdr.String() + sprintName(rr.NextDomain)
+ for i := 0; i < len(rr.TypeBitMap); i++ {
+ s += " " + Type(rr.TypeBitMap[i]).String()
+ }
+ return s
+}
+
+func (rr *NSEC) len() int {
+ l := rr.Hdr.len() + len(rr.NextDomain) + 1
+ lastwindow := uint32(2 ^ 32 + 1)
+ for _, t := range rr.TypeBitMap {
+ window := t / 256
+ if uint32(window) != lastwindow {
+ l += 1 + 32
+ }
+ lastwindow = uint32(window)
+ }
+ return l
+}
+
+// DLV RR. See RFC 4431.
+type DLV struct{ DS }
+
+// CDS RR. See RFC 7344.
+type CDS struct{ DS }
+
+// DS RR. See RFC 4034 and RFC 3658.
+type DS struct {
+ Hdr RR_Header
+ KeyTag uint16
+ Algorithm uint8
+ DigestType uint8
+ Digest string `dns:"hex"`
+}
+
+func (rr *DS) String() string {
+ return rr.Hdr.String() + strconv.Itoa(int(rr.KeyTag)) +
+ " " + strconv.Itoa(int(rr.Algorithm)) +
+ " " + strconv.Itoa(int(rr.DigestType)) +
+ " " + strings.ToUpper(rr.Digest)
+}
+
+// KX RR. See RFC 2230.
+type KX struct {
+ Hdr RR_Header
+ Preference uint16
+ Exchanger string `dns:"domain-name"`
+}
+
+func (rr *KX) String() string {
+ return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) +
+ " " + sprintName(rr.Exchanger)
+}
+
+// TA RR. See http://www.watson.org/~weiler/INI1999-19.pdf.
+type TA struct {
+ Hdr RR_Header
+ KeyTag uint16
+ Algorithm uint8
+ DigestType uint8
+ Digest string `dns:"hex"`
+}
+
+func (rr *TA) String() string {
+ return rr.Hdr.String() + strconv.Itoa(int(rr.KeyTag)) +
+ " " + strconv.Itoa(int(rr.Algorithm)) +
+ " " + strconv.Itoa(int(rr.DigestType)) +
+ " " + strings.ToUpper(rr.Digest)
+}
+
+// TALINK RR. See https://www.iana.org/assignments/dns-parameters/TALINK/talink-completed-template.
+type TALINK struct {
+ Hdr RR_Header
+ PreviousName string `dns:"domain-name"`
+ NextName string `dns:"domain-name"`
+}
+
+func (rr *TALINK) String() string {
+ return rr.Hdr.String() +
+ sprintName(rr.PreviousName) + " " + sprintName(rr.NextName)
+}
+
+// SSHFP RR. See RFC RFC 4255.
+type SSHFP struct {
+ Hdr RR_Header
+ Algorithm uint8
+ Type uint8
+ FingerPrint string `dns:"hex"`
+}
+
+func (rr *SSHFP) String() string {
+ return rr.Hdr.String() + strconv.Itoa(int(rr.Algorithm)) +
+ " " + strconv.Itoa(int(rr.Type)) +
+ " " + strings.ToUpper(rr.FingerPrint)
+}
+
+// KEY RR. See RFC RFC 2535.
+type KEY struct {
+ DNSKEY
+}
+
+// CDNSKEY RR. See RFC 7344.
+type CDNSKEY struct {
+ DNSKEY
+}
+
+// DNSKEY RR. See RFC 4034 and RFC 3755.
+type DNSKEY struct {
+ Hdr RR_Header
+ Flags uint16
+ Protocol uint8
+ Algorithm uint8
+ PublicKey string `dns:"base64"`
+}
+
+func (rr *DNSKEY) String() string {
+ return rr.Hdr.String() + strconv.Itoa(int(rr.Flags)) +
+ " " + strconv.Itoa(int(rr.Protocol)) +
+ " " + strconv.Itoa(int(rr.Algorithm)) +
+ " " + rr.PublicKey
+}
+
+// RKEY RR. See https://www.iana.org/assignments/dns-parameters/RKEY/rkey-completed-template.
+type RKEY struct {
+ Hdr RR_Header
+ Flags uint16
+ Protocol uint8
+ Algorithm uint8
+ PublicKey string `dns:"base64"`
+}
+
+func (rr *RKEY) String() string {
+ return rr.Hdr.String() + strconv.Itoa(int(rr.Flags)) +
+ " " + strconv.Itoa(int(rr.Protocol)) +
+ " " + strconv.Itoa(int(rr.Algorithm)) +
+ " " + rr.PublicKey
+}
+
+// NSAPPTR RR. See RFC 1348.
+type NSAPPTR struct {
+ Hdr RR_Header
+ Ptr string `dns:"domain-name"`
+}
+
+func (rr *NSAPPTR) String() string { return rr.Hdr.String() + sprintName(rr.Ptr) }
+
+// NSEC3 RR. See RFC 5155.
+type NSEC3 struct {
+ Hdr RR_Header
+ Hash uint8
+ Flags uint8
+ Iterations uint16
+ SaltLength uint8
+ Salt string `dns:"size-hex:SaltLength"`
+ HashLength uint8
+ NextDomain string `dns:"size-base32:HashLength"`
+ TypeBitMap []uint16 `dns:"nsec"`
+}
+
+func (rr *NSEC3) String() string {
+ s := rr.Hdr.String()
+ s += strconv.Itoa(int(rr.Hash)) +
+ " " + strconv.Itoa(int(rr.Flags)) +
+ " " + strconv.Itoa(int(rr.Iterations)) +
+ " " + saltToString(rr.Salt) +
+ " " + rr.NextDomain
+ for i := 0; i < len(rr.TypeBitMap); i++ {
+ s += " " + Type(rr.TypeBitMap[i]).String()
+ }
+ return s
+}
+
+func (rr *NSEC3) len() int {
+ l := rr.Hdr.len() + 6 + len(rr.Salt)/2 + 1 + len(rr.NextDomain) + 1
+ lastwindow := uint32(2 ^ 32 + 1)
+ for _, t := range rr.TypeBitMap {
+ window := t / 256
+ if uint32(window) != lastwindow {
+ l += 1 + 32
+ }
+ lastwindow = uint32(window)
+ }
+ return l
+}
+
+// NSEC3PARAM RR. See RFC 5155.
+type NSEC3PARAM struct {
+ Hdr RR_Header
+ Hash uint8
+ Flags uint8
+ Iterations uint16
+ SaltLength uint8
+ Salt string `dns:"size-hex:SaltLength"`
+}
+
+func (rr *NSEC3PARAM) String() string {
+ s := rr.Hdr.String()
+ s += strconv.Itoa(int(rr.Hash)) +
+ " " + strconv.Itoa(int(rr.Flags)) +
+ " " + strconv.Itoa(int(rr.Iterations)) +
+ " " + saltToString(rr.Salt)
+ return s
+}
+
+// TKEY RR. See RFC 2930.
+type TKEY struct {
+ Hdr RR_Header
+ Algorithm string `dns:"domain-name"`
+ Inception uint32
+ Expiration uint32
+ Mode uint16
+ Error uint16
+ KeySize uint16
+ Key string
+ OtherLen uint16
+ OtherData string
+}
+
+func (rr *TKEY) String() string {
+ // It has no presentation format
+ return ""
+}
+
+// RFC3597 represents an unknown/generic RR. See RFC 3597.
+type RFC3597 struct {
+ Hdr RR_Header
+ Rdata string `dns:"hex"`
+}
+
+func (rr *RFC3597) String() string {
+ // Let's call it a hack
+ s := rfc3597Header(rr.Hdr)
+
+ s += "\\# " + strconv.Itoa(len(rr.Rdata)/2) + " " + rr.Rdata
+ return s
+}
+
+func rfc3597Header(h RR_Header) string {
+ var s string
+
+ s += sprintName(h.Name) + "\t"
+ s += strconv.FormatInt(int64(h.Ttl), 10) + "\t"
+ s += "CLASS" + strconv.Itoa(int(h.Class)) + "\t"
+ s += "TYPE" + strconv.Itoa(int(h.Rrtype)) + "\t"
+ return s
+}
+
+// URI RR. See RFC 7553.
+type URI struct {
+ Hdr RR_Header
+ Priority uint16
+ Weight uint16
+ Target string `dns:"octet"`
+}
+
+func (rr *URI) String() string {
+ return rr.Hdr.String() + strconv.Itoa(int(rr.Priority)) +
+ " " + strconv.Itoa(int(rr.Weight)) + " " + sprintTxtOctet(rr.Target)
+}
+
+// DHCID RR. See RFC 4701.
+type DHCID struct {
+ Hdr RR_Header
+ Digest string `dns:"base64"`
+}
+
+func (rr *DHCID) String() string { return rr.Hdr.String() + rr.Digest }
+
+// TLSA RR. See RFC 6698.
+type TLSA struct {
+ Hdr RR_Header
+ Usage uint8
+ Selector uint8
+ MatchingType uint8
+ Certificate string `dns:"hex"`
+}
+
+func (rr *TLSA) String() string {
+ return rr.Hdr.String() +
+ strconv.Itoa(int(rr.Usage)) +
+ " " + strconv.Itoa(int(rr.Selector)) +
+ " " + strconv.Itoa(int(rr.MatchingType)) +
+ " " + rr.Certificate
+}
+
+// SMIMEA RR. See RFC 8162.
+type SMIMEA struct {
+ Hdr RR_Header
+ Usage uint8
+ Selector uint8
+ MatchingType uint8
+ Certificate string `dns:"hex"`
+}
+
+func (rr *SMIMEA) String() string {
+ s := rr.Hdr.String() +
+ strconv.Itoa(int(rr.Usage)) +
+ " " + strconv.Itoa(int(rr.Selector)) +
+ " " + strconv.Itoa(int(rr.MatchingType))
+
+ // Every Nth char needs a space on this output. If we output
+ // this as one giant line, we can't read it can in because in some cases
+ // the cert length overflows scan.maxTok (2048).
+ sx := splitN(rr.Certificate, 1024) // conservative value here
+ s += " " + strings.Join(sx, " ")
+ return s
+}
+
+// HIP RR. See RFC 8005.
+type HIP struct {
+ Hdr RR_Header
+ HitLength uint8
+ PublicKeyAlgorithm uint8
+ PublicKeyLength uint16
+ Hit string `dns:"size-hex:HitLength"`
+ PublicKey string `dns:"size-base64:PublicKeyLength"`
+ RendezvousServers []string `dns:"domain-name"`
+}
+
+func (rr *HIP) String() string {
+ s := rr.Hdr.String() +
+ strconv.Itoa(int(rr.PublicKeyAlgorithm)) +
+ " " + rr.Hit +
+ " " + rr.PublicKey
+ for _, d := range rr.RendezvousServers {
+ s += " " + sprintName(d)
+ }
+ return s
+}
+
+// NINFO RR. See https://www.iana.org/assignments/dns-parameters/NINFO/ninfo-completed-template.
+type NINFO struct {
+ Hdr RR_Header
+ ZSData []string `dns:"txt"`
+}
+
+func (rr *NINFO) String() string { return rr.Hdr.String() + sprintTxt(rr.ZSData) }
+
+// NID RR. See RFC RFC 6742.
+type NID struct {
+ Hdr RR_Header
+ Preference uint16
+ NodeID uint64
+}
+
+func (rr *NID) String() string {
+ s := rr.Hdr.String() + strconv.Itoa(int(rr.Preference))
+ node := fmt.Sprintf("%0.16x", rr.NodeID)
+ s += " " + node[0:4] + ":" + node[4:8] + ":" + node[8:12] + ":" + node[12:16]
+ return s
+}
+
+// L32 RR, See RFC 6742.
+type L32 struct {
+ Hdr RR_Header
+ Preference uint16
+ Locator32 net.IP `dns:"a"`
+}
+
+func (rr *L32) String() string {
+ if rr.Locator32 == nil {
+ return rr.Hdr.String() + strconv.Itoa(int(rr.Preference))
+ }
+ return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) +
+ " " + rr.Locator32.String()
+}
+
+// L64 RR, See RFC 6742.
+type L64 struct {
+ Hdr RR_Header
+ Preference uint16
+ Locator64 uint64
+}
+
+func (rr *L64) String() string {
+ s := rr.Hdr.String() + strconv.Itoa(int(rr.Preference))
+ node := fmt.Sprintf("%0.16X", rr.Locator64)
+ s += " " + node[0:4] + ":" + node[4:8] + ":" + node[8:12] + ":" + node[12:16]
+ return s
+}
+
+// LP RR. See RFC 6742.
+type LP struct {
+ Hdr RR_Header
+ Preference uint16
+ Fqdn string `dns:"domain-name"`
+}
+
+func (rr *LP) String() string {
+ return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + sprintName(rr.Fqdn)
+}
+
+// EUI48 RR. See RFC 7043.
+type EUI48 struct {
+ Hdr RR_Header
+ Address uint64 `dns:"uint48"`
+}
+
+func (rr *EUI48) String() string { return rr.Hdr.String() + euiToString(rr.Address, 48) }
+
+// EUI64 RR. See RFC 7043.
+type EUI64 struct {
+ Hdr RR_Header
+ Address uint64
+}
+
+func (rr *EUI64) String() string { return rr.Hdr.String() + euiToString(rr.Address, 64) }
+
+// CAA RR. See RFC 6844.
+type CAA struct {
+ Hdr RR_Header
+ Flag uint8
+ Tag string
+ Value string `dns:"octet"`
+}
+
+func (rr *CAA) String() string {
+ return rr.Hdr.String() + strconv.Itoa(int(rr.Flag)) + " " + rr.Tag + " " + sprintTxtOctet(rr.Value)
+}
+
+// UID RR. Deprecated, IANA-Reserved.
+type UID struct {
+ Hdr RR_Header
+ Uid uint32
+}
+
+func (rr *UID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Uid), 10) }
+
+// GID RR. Deprecated, IANA-Reserved.
+type GID struct {
+ Hdr RR_Header
+ Gid uint32
+}
+
+func (rr *GID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Gid), 10) }
+
+// UINFO RR. Deprecated, IANA-Reserved.
+type UINFO struct {
+ Hdr RR_Header
+ Uinfo string
+}
+
+func (rr *UINFO) String() string { return rr.Hdr.String() + sprintTxt([]string{rr.Uinfo}) }
+
+// EID RR. See http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt.
+type EID struct {
+ Hdr RR_Header
+ Endpoint string `dns:"hex"`
+}
+
+func (rr *EID) String() string { return rr.Hdr.String() + strings.ToUpper(rr.Endpoint) }
+
+// NIMLOC RR. See http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt.
+type NIMLOC struct {
+ Hdr RR_Header
+ Locator string `dns:"hex"`
+}
+
+func (rr *NIMLOC) String() string { return rr.Hdr.String() + strings.ToUpper(rr.Locator) }
+
+// OPENPGPKEY RR. See RFC 7929.
+type OPENPGPKEY struct {
+ Hdr RR_Header
+ PublicKey string `dns:"base64"`
+}
+
+func (rr *OPENPGPKEY) String() string { return rr.Hdr.String() + rr.PublicKey }
+
+// TimeToString translates the RRSIG's incep. and expir. times to the
+// string representation used when printing the record.
+// It takes serial arithmetic (RFC 1982) into account.
+func TimeToString(t uint32) string {
+ mod := ((int64(t) - time.Now().Unix()) / year68) - 1
+ if mod < 0 {
+ mod = 0
+ }
+ ti := time.Unix(int64(t)-(mod*year68), 0).UTC()
+ return ti.Format("20060102150405")
+}
+
+// StringToTime translates the RRSIG's incep. and expir. times from
+// string values like "20110403154150" to an 32 bit integer.
+// It takes serial arithmetic (RFC 1982) into account.
+func StringToTime(s string) (uint32, error) {
+ t, err := time.Parse("20060102150405", s)
+ if err != nil {
+ return 0, err
+ }
+ mod := (t.Unix() / year68) - 1
+ if mod < 0 {
+ mod = 0
+ }
+ return uint32(t.Unix() - (mod * year68)), nil
+}
+
+// saltToString converts a NSECX salt to uppercase and returns "-" when it is empty.
+func saltToString(s string) string {
+ if len(s) == 0 {
+ return "-"
+ }
+ return strings.ToUpper(s)
+}
+
+func euiToString(eui uint64, bits int) (hex string) {
+ switch bits {
+ case 64:
+ hex = fmt.Sprintf("%16.16x", eui)
+ hex = hex[0:2] + "-" + hex[2:4] + "-" + hex[4:6] + "-" + hex[6:8] +
+ "-" + hex[8:10] + "-" + hex[10:12] + "-" + hex[12:14] + "-" + hex[14:16]
+ case 48:
+ hex = fmt.Sprintf("%12.12x", eui)
+ hex = hex[0:2] + "-" + hex[2:4] + "-" + hex[4:6] + "-" + hex[6:8] +
+ "-" + hex[8:10] + "-" + hex[10:12]
+ }
+ return
+}
+
+// copyIP returns a copy of ip.
+func copyIP(ip net.IP) net.IP {
+ p := make(net.IP, len(ip))
+ copy(p, ip)
+ return p
+}
+
+// SplitN splits a string into N sized string chunks.
+// This might become an exported function once.
+func splitN(s string, n int) []string {
+ if len(s) < n {
+ return []string{s}
+ }
+ sx := []string{}
+ p, i := 0, n
+ for {
+ if i <= len(s) {
+ sx = append(sx, s[p:i])
+ } else {
+ sx = append(sx, s[p:])
+ break
+
+ }
+ p, i = p+n, i+n
+ }
+
+ return sx
+}
--- /dev/null
+//+build ignore
+
+// types_generate.go is meant to run with go generate. It will use
+// go/{importer,types} to track down all the RR struct types. Then for each type
+// it will generate conversion tables (TypeToRR and TypeToString) and banal
+// methods (len, Header, copy) based on the struct tags. The generated source is
+// written to ztypes.go, and is meant to be checked into git.
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/format"
+ "go/importer"
+ "go/types"
+ "log"
+ "os"
+ "strings"
+ "text/template"
+)
+
+var skipLen = map[string]struct{}{
+ "NSEC": {},
+ "NSEC3": {},
+ "OPT": {},
+}
+
+var packageHdr = `
+// *** DO NOT MODIFY ***
+// AUTOGENERATED BY go generate from types_generate.go
+
+package dns
+
+import (
+ "encoding/base64"
+ "net"
+)
+
+`
+
+var TypeToRR = template.Must(template.New("TypeToRR").Parse(`
+// TypeToRR is a map of constructors for each RR type.
+var TypeToRR = map[uint16]func() RR{
+{{range .}}{{if ne . "RFC3597"}} Type{{.}}: func() RR { return new({{.}}) },
+{{end}}{{end}} }
+
+`))
+
+var typeToString = template.Must(template.New("typeToString").Parse(`
+// TypeToString is a map of strings for each RR type.
+var TypeToString = map[uint16]string{
+{{range .}}{{if ne . "NSAPPTR"}} Type{{.}}: "{{.}}",
+{{end}}{{end}} TypeNSAPPTR: "NSAP-PTR",
+}
+
+`))
+
+var headerFunc = template.Must(template.New("headerFunc").Parse(`
+{{range .}} func (rr *{{.}}) Header() *RR_Header { return &rr.Hdr }
+{{end}}
+
+`))
+
+// getTypeStruct will take a type and the package scope, and return the
+// (innermost) struct if the type is considered a RR type (currently defined as
+// those structs beginning with a RR_Header, could be redefined as implementing
+// the RR interface). The bool return value indicates if embedded structs were
+// resolved.
+func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
+ st, ok := t.Underlying().(*types.Struct)
+ if !ok {
+ return nil, false
+ }
+ if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
+ return st, false
+ }
+ if st.Field(0).Anonymous() {
+ st, _ := getTypeStruct(st.Field(0).Type(), scope)
+ return st, true
+ }
+ return nil, false
+}
+
+func main() {
+ // Import and type-check the package
+ pkg, err := importer.Default().Import("github.com/miekg/dns")
+ fatalIfErr(err)
+ scope := pkg.Scope()
+
+ // Collect constants like TypeX
+ var numberedTypes []string
+ for _, name := range scope.Names() {
+ o := scope.Lookup(name)
+ if o == nil || !o.Exported() {
+ continue
+ }
+ b, ok := o.Type().(*types.Basic)
+ if !ok || b.Kind() != types.Uint16 {
+ continue
+ }
+ if !strings.HasPrefix(o.Name(), "Type") {
+ continue
+ }
+ name := strings.TrimPrefix(o.Name(), "Type")
+ if name == "PrivateRR" {
+ continue
+ }
+ numberedTypes = append(numberedTypes, name)
+ }
+
+ // Collect actual types (*X)
+ var namedTypes []string
+ for _, name := range scope.Names() {
+ o := scope.Lookup(name)
+ if o == nil || !o.Exported() {
+ continue
+ }
+ if st, _ := getTypeStruct(o.Type(), scope); st == nil {
+ continue
+ }
+ if name == "PrivateRR" {
+ continue
+ }
+
+ // Check if corresponding TypeX exists
+ if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
+ log.Fatalf("Constant Type%s does not exist.", o.Name())
+ }
+
+ namedTypes = append(namedTypes, o.Name())
+ }
+
+ b := &bytes.Buffer{}
+ b.WriteString(packageHdr)
+
+ // Generate TypeToRR
+ fatalIfErr(TypeToRR.Execute(b, namedTypes))
+
+ // Generate typeToString
+ fatalIfErr(typeToString.Execute(b, numberedTypes))
+
+ // Generate headerFunc
+ fatalIfErr(headerFunc.Execute(b, namedTypes))
+
+ // Generate len()
+ fmt.Fprint(b, "// len() functions\n")
+ for _, name := range namedTypes {
+ if _, ok := skipLen[name]; ok {
+ continue
+ }
+ o := scope.Lookup(name)
+ st, isEmbedded := getTypeStruct(o.Type(), scope)
+ if isEmbedded {
+ continue
+ }
+ fmt.Fprintf(b, "func (rr *%s) len() int {\n", name)
+ fmt.Fprintf(b, "l := rr.Hdr.len()\n")
+ for i := 1; i < st.NumFields(); i++ {
+ o := func(s string) { fmt.Fprintf(b, s, st.Field(i).Name()) }
+
+ if _, ok := st.Field(i).Type().(*types.Slice); ok {
+ switch st.Tag(i) {
+ case `dns:"-"`:
+ // ignored
+ case `dns:"cdomain-name"`, `dns:"domain-name"`, `dns:"txt"`:
+ o("for _, x := range rr.%s { l += len(x) + 1 }\n")
+ default:
+ log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
+ }
+ continue
+ }
+
+ switch {
+ case st.Tag(i) == `dns:"-"`:
+ // ignored
+ case st.Tag(i) == `dns:"cdomain-name"`, st.Tag(i) == `dns:"domain-name"`:
+ o("l += len(rr.%s) + 1\n")
+ case st.Tag(i) == `dns:"octet"`:
+ o("l += len(rr.%s)\n")
+ case strings.HasPrefix(st.Tag(i), `dns:"size-base64`):
+ fallthrough
+ case st.Tag(i) == `dns:"base64"`:
+ o("l += base64.StdEncoding.DecodedLen(len(rr.%s))\n")
+ case strings.HasPrefix(st.Tag(i), `dns:"size-hex`):
+ fallthrough
+ case st.Tag(i) == `dns:"hex"`:
+ o("l += len(rr.%s)/2 + 1\n")
+ case st.Tag(i) == `dns:"a"`:
+ o("l += net.IPv4len // %s\n")
+ case st.Tag(i) == `dns:"aaaa"`:
+ o("l += net.IPv6len // %s\n")
+ case st.Tag(i) == `dns:"txt"`:
+ o("for _, t := range rr.%s { l += len(t) + 1 }\n")
+ case st.Tag(i) == `dns:"uint48"`:
+ o("l += 6 // %s\n")
+ case st.Tag(i) == "":
+ switch st.Field(i).Type().(*types.Basic).Kind() {
+ case types.Uint8:
+ o("l++ // %s\n")
+ case types.Uint16:
+ o("l += 2 // %s\n")
+ case types.Uint32:
+ o("l += 4 // %s\n")
+ case types.Uint64:
+ o("l += 8 // %s\n")
+ case types.String:
+ o("l += len(rr.%s) + 1\n")
+ default:
+ log.Fatalln(name, st.Field(i).Name())
+ }
+ default:
+ log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
+ }
+ }
+ fmt.Fprintf(b, "return l }\n")
+ }
+
+ // Generate copy()
+ fmt.Fprint(b, "// copy() functions\n")
+ for _, name := range namedTypes {
+ o := scope.Lookup(name)
+ st, isEmbedded := getTypeStruct(o.Type(), scope)
+ if isEmbedded {
+ continue
+ }
+ fmt.Fprintf(b, "func (rr *%s) copy() RR {\n", name)
+ fields := []string{"*rr.Hdr.copyHeader()"}
+ for i := 1; i < st.NumFields(); i++ {
+ f := st.Field(i).Name()
+ if sl, ok := st.Field(i).Type().(*types.Slice); ok {
+ t := sl.Underlying().String()
+ t = strings.TrimPrefix(t, "[]")
+ if strings.Contains(t, ".") {
+ splits := strings.Split(t, ".")
+ t = splits[len(splits)-1]
+ }
+ fmt.Fprintf(b, "%s := make([]%s, len(rr.%s)); copy(%s, rr.%s)\n",
+ f, t, f, f, f)
+ fields = append(fields, f)
+ continue
+ }
+ if st.Field(i).Type().String() == "net.IP" {
+ fields = append(fields, "copyIP(rr."+f+")")
+ continue
+ }
+ fields = append(fields, "rr."+f)
+ }
+ fmt.Fprintf(b, "return &%s{%s}\n", name, strings.Join(fields, ","))
+ fmt.Fprintf(b, "}\n")
+ }
+
+ // gofmt
+ res, err := format.Source(b.Bytes())
+ if err != nil {
+ b.WriteTo(os.Stderr)
+ log.Fatal(err)
+ }
+
+ // write result
+ f, err := os.Create("ztypes.go")
+ fatalIfErr(err)
+ defer f.Close()
+ f.Write(res)
+}
+
+func fatalIfErr(err error) {
+ if err != nil {
+ log.Fatal(err)
+ }
+}
--- /dev/null
+// +build !windows
+
+package dns
+
+import (
+ "net"
+)
+
+// SessionUDP holds the remote address and the associated
+// out-of-band data.
+type SessionUDP struct {
+ raddr *net.UDPAddr
+ context []byte
+}
+
+// RemoteAddr returns the remote network address.
+func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
+
+// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
+// net.UDPAddr.
+func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
+ oob := make([]byte, 40)
+ n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob)
+ if err != nil {
+ return n, nil, err
+ }
+ return n, &SessionUDP{raddr, oob[:oobn]}, err
+}
+
+// WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr.
+func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
+ oob := correctSource(session.context)
+ n, _, err := conn.WriteMsgUDP(b, oob, session.raddr)
+ return n, err
+}
+
+// correctSource takes oob data and returns new oob data with the Src equal to the Dst
+func correctSource(oob []byte) []byte {
+ dst, err := parseUDPSocketDst(oob)
+ // If the destination could not be determined, ignore.
+ if err != nil || dst == nil {
+ return nil
+ }
+ return marshalUDPSocketSrc(dst)
+}
--- /dev/null
+// +build linux,!appengine
+
+package dns
+
+// See:
+// * http://stackoverflow.com/questions/3062205/setting-the-source-ip-for-a-udp-socket and
+// * http://blog.powerdns.com/2012/10/08/on-binding-datagram-udp-sockets-to-the-any-addresses/
+//
+// Why do we need this: When listening on 0.0.0.0 with UDP so kernel decides what is the outgoing
+// interface, this might not always be the correct one. This code will make sure the egress
+// packet's interface matched the ingress' one.
+
+import (
+ "net"
+ "syscall"
+ "unsafe"
+
+ "github.com/miekg/dns/internal/socket"
+)
+
+const (
+ sizeofInet6Pktinfo = 0x14
+ sizeofInetPktinfo = 0xc
+ protocolIP = 0
+ protocolIPv6 = 41
+)
+
+type inetPktinfo struct {
+ Ifindex int32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type inet6Pktinfo struct {
+ Addr [16]byte /* in6_addr */
+ Ifindex int32
+}
+
+type inetControlMessage struct {
+ Src net.IP // source address, specifying only
+ Dst net.IP // destination address, receiving only
+}
+
+// setUDPSocketOptions sets the UDP socket options.
+// This function is implemented on a per platform basis. See udp_*.go for more details
+func setUDPSocketOptions(conn *net.UDPConn) error {
+ sa, err := getUDPSocketName(conn)
+ if err != nil {
+ return err
+ }
+ switch sa.(type) {
+ case *syscall.SockaddrInet6:
+ v6only, err := getUDPSocketOptions6Only(conn)
+ if err != nil {
+ return err
+ }
+ setUDPSocketOptions6(conn)
+ if !v6only {
+ setUDPSocketOptions4(conn)
+ }
+ case *syscall.SockaddrInet4:
+ setUDPSocketOptions4(conn)
+ }
+ return nil
+}
+
+// setUDPSocketOptions4 prepares the v4 socket for sessions.
+func setUDPSocketOptions4(conn *net.UDPConn) error {
+ file, err := conn.File()
+ if err != nil {
+ return err
+ }
+ if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1); err != nil {
+ file.Close()
+ return err
+ }
+ // Calling File() above results in the connection becoming blocking, we must fix that.
+ // See https://github.com/miekg/dns/issues/279
+ err = syscall.SetNonblock(int(file.Fd()), true)
+ if err != nil {
+ file.Close()
+ return err
+ }
+ file.Close()
+ return nil
+}
+
+// setUDPSocketOptions6 prepares the v6 socket for sessions.
+func setUDPSocketOptions6(conn *net.UDPConn) error {
+ file, err := conn.File()
+ if err != nil {
+ return err
+ }
+ if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1); err != nil {
+ file.Close()
+ return err
+ }
+ err = syscall.SetNonblock(int(file.Fd()), true)
+ if err != nil {
+ file.Close()
+ return err
+ }
+ file.Close()
+ return nil
+}
+
+// getUDPSocketOption6Only return true if the socket is v6 only and false when it is v4/v6 combined
+// (dualstack).
+func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) {
+ file, err := conn.File()
+ if err != nil {
+ return false, err
+ }
+ // dual stack. See http://stackoverflow.com/questions/1618240/how-to-support-both-ipv4-and-ipv6-connections
+ v6only, err := syscall.GetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY)
+ if err != nil {
+ file.Close()
+ return false, err
+ }
+ file.Close()
+ return v6only == 1, nil
+}
+
+func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) {
+ file, err := conn.File()
+ if err != nil {
+ return nil, err
+ }
+ defer file.Close()
+ return syscall.Getsockname(int(file.Fd()))
+}
+
+// marshalInetPacketInfo marshals a ipv4 control message, returning
+// the byte slice for the next marshal, if any
+func marshalInetPacketInfo(b []byte, cm *inetControlMessage) []byte {
+ m := socket.ControlMessage(b)
+ m.MarshalHeader(protocolIP, syscall.IP_PKTINFO, sizeofInetPktinfo)
+ if cm != nil {
+ pi := (*inetPktinfo)(unsafe.Pointer(&m.Data(sizeofInetPktinfo)[0]))
+ if ip := cm.Src.To4(); ip != nil {
+ copy(pi.Spec_dst[:], ip)
+ }
+ }
+ return m.Next(sizeofInetPktinfo)
+}
+
+// marshalInet6PacketInfo marshals a ipv6 control message, returning
+// the byte slice for the next marshal, if any
+func marshalInet6PacketInfo(b []byte, cm *inetControlMessage) []byte {
+ m := socket.ControlMessage(b)
+ m.MarshalHeader(protocolIPv6, syscall.IPV6_PKTINFO, sizeofInet6Pktinfo)
+ if cm != nil {
+ pi := (*inet6Pktinfo)(unsafe.Pointer(&m.Data(sizeofInet6Pktinfo)[0]))
+ if ip := cm.Src.To16(); ip != nil && ip.To4() == nil {
+ copy(pi.Addr[:], ip)
+ }
+ }
+ return m.Next(sizeofInet6Pktinfo)
+}
+
+func parseInetPacketInfo(cm *inetControlMessage, b []byte) {
+ pi := (*inetPktinfo)(unsafe.Pointer(&b[0]))
+ if len(cm.Dst) < net.IPv4len {
+ cm.Dst = make(net.IP, net.IPv4len)
+ }
+ copy(cm.Dst, pi.Addr[:])
+}
+
+func parseInet6PacketInfo(cm *inetControlMessage, b []byte) {
+ pi := (*inet6Pktinfo)(unsafe.Pointer(&b[0]))
+ if len(cm.Dst) < net.IPv6len {
+ cm.Dst = make(net.IP, net.IPv6len)
+ }
+ copy(cm.Dst, pi.Addr[:])
+}
+
+// parseUDPSocketDst takes out-of-band data from ReadMsgUDP and parses it for
+// the Dst address
+func parseUDPSocketDst(oob []byte) (net.IP, error) {
+ cm := new(inetControlMessage)
+ ms, err := socket.ControlMessage(oob).Parse()
+ if err != nil {
+ return nil, err
+ }
+ for _, m := range ms {
+ lvl, typ, l, err := m.ParseHeader()
+ if err != nil {
+ return nil, err
+ }
+ if lvl == protocolIPv6 { // IPv6
+ if typ == syscall.IPV6_PKTINFO && l >= sizeofInet6Pktinfo {
+ parseInet6PacketInfo(cm, m.Data(l))
+ }
+ } else if lvl == protocolIP { // IPv4
+ if typ == syscall.IP_PKTINFO && l >= sizeofInetPktinfo {
+ parseInetPacketInfo(cm, m.Data(l))
+ }
+ }
+ }
+ return cm.Dst, nil
+}
+
+// marshalUDPSocketSrc takes the given src address and returns out-of-band data
+// to give to WriteMsgUDP
+func marshalUDPSocketSrc(src net.IP) []byte {
+ var oob []byte
+ // If the dst is definitely an ipv6, then use ipv6 control to respond
+ // otherwise use ipv4 because the ipv6 marshal ignores ipv4 messages.
+ // See marshalInet6PacketInfo
+ cm := new(inetControlMessage)
+ cm.Src = src
+ if src.To4() == nil {
+ oob = make([]byte, socket.ControlMessageSpace(sizeofInet6Pktinfo))
+ marshalInet6PacketInfo(oob, cm)
+ } else {
+ oob = make([]byte, socket.ControlMessageSpace(sizeofInetPktinfo))
+ marshalInetPacketInfo(oob, cm)
+ }
+ return oob
+}
--- /dev/null
+// +build !linux appengine
+
+package dns
+
+import (
+ "net"
+)
+
+// These do nothing. See udp_linux.go for an example of how to implement this.
+
+// We tried to adhire to some kind of naming scheme.
+func setUDPSocketOptions(conn *net.UDPConn) error { return nil }
+func setUDPSocketOptions4(conn *net.UDPConn) error { return nil }
+func setUDPSocketOptions6(conn *net.UDPConn) error { return nil }
+func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) { return false, nil }
+func parseUDPSocketDst(oob []byte) (net.IP, error) { return nil, nil }
+func marshalUDPSocketSrc(src net.IP) []byte { return nil }
--- /dev/null
+// +build windows
+
+package dns
+
+import "net"
+
+// SessionUDP holds the remote address
+type SessionUDP struct {
+ raddr *net.UDPAddr
+}
+
+// RemoteAddr returns the remote network address.
+func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
+
+// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
+// net.UDPAddr.
+func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
+ n, raddr, err := conn.ReadFrom(b)
+ if err != nil {
+ return n, nil, err
+ }
+ session := &SessionUDP{raddr.(*net.UDPAddr)}
+ return n, session, err
+}
+
+// WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr.
+func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
+ n, err := conn.WriteTo(b, session.raddr)
+ return n, err
+}
--- /dev/null
+package dns
+
+// NameUsed sets the RRs in the prereq section to
+// "Name is in use" RRs. RFC 2136 section 2.4.4.
+func (u *Msg) NameUsed(rr []RR) {
+ if u.Answer == nil {
+ u.Answer = make([]RR, 0, len(rr))
+ }
+ for _, r := range rr {
+ u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}})
+ }
+}
+
+// NameNotUsed sets the RRs in the prereq section to
+// "Name is in not use" RRs. RFC 2136 section 2.4.5.
+func (u *Msg) NameNotUsed(rr []RR) {
+ if u.Answer == nil {
+ u.Answer = make([]RR, 0, len(rr))
+ }
+ for _, r := range rr {
+ u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassNONE}})
+ }
+}
+
+// Used sets the RRs in the prereq section to
+// "RRset exists (value dependent -- with rdata)" RRs. RFC 2136 section 2.4.2.
+func (u *Msg) Used(rr []RR) {
+ if len(u.Question) == 0 {
+ panic("dns: empty question section")
+ }
+ if u.Answer == nil {
+ u.Answer = make([]RR, 0, len(rr))
+ }
+ for _, r := range rr {
+ r.Header().Class = u.Question[0].Qclass
+ u.Answer = append(u.Answer, r)
+ }
+}
+
+// RRsetUsed sets the RRs in the prereq section to
+// "RRset exists (value independent -- no rdata)" RRs. RFC 2136 section 2.4.1.
+func (u *Msg) RRsetUsed(rr []RR) {
+ if u.Answer == nil {
+ u.Answer = make([]RR, 0, len(rr))
+ }
+ for _, r := range rr {
+ u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}})
+ }
+}
+
+// RRsetNotUsed sets the RRs in the prereq section to
+// "RRset does not exist" RRs. RFC 2136 section 2.4.3.
+func (u *Msg) RRsetNotUsed(rr []RR) {
+ if u.Answer == nil {
+ u.Answer = make([]RR, 0, len(rr))
+ }
+ for _, r := range rr {
+ u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassNONE}})
+ }
+}
+
+// Insert creates a dynamic update packet that adds an complete RRset, see RFC 2136 section 2.5.1.
+func (u *Msg) Insert(rr []RR) {
+ if len(u.Question) == 0 {
+ panic("dns: empty question section")
+ }
+ if u.Ns == nil {
+ u.Ns = make([]RR, 0, len(rr))
+ }
+ for _, r := range rr {
+ r.Header().Class = u.Question[0].Qclass
+ u.Ns = append(u.Ns, r)
+ }
+}
+
+// RemoveRRset creates a dynamic update packet that deletes an RRset, see RFC 2136 section 2.5.2.
+func (u *Msg) RemoveRRset(rr []RR) {
+ if u.Ns == nil {
+ u.Ns = make([]RR, 0, len(rr))
+ }
+ for _, r := range rr {
+ u.Ns = append(u.Ns, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}})
+ }
+}
+
+// RemoveName creates a dynamic update packet that deletes all RRsets of a name, see RFC 2136 section 2.5.3
+func (u *Msg) RemoveName(rr []RR) {
+ if u.Ns == nil {
+ u.Ns = make([]RR, 0, len(rr))
+ }
+ for _, r := range rr {
+ u.Ns = append(u.Ns, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}})
+ }
+}
+
+// Remove creates a dynamic update packet deletes RR from a RRSset, see RFC 2136 section 2.5.4
+func (u *Msg) Remove(rr []RR) {
+ if u.Ns == nil {
+ u.Ns = make([]RR, 0, len(rr))
+ }
+ for _, r := range rr {
+ r.Header().Class = ClassNONE
+ r.Header().Ttl = 0
+ u.Ns = append(u.Ns, r)
+ }
+}
--- /dev/null
+package dns
+
+import (
+ "fmt"
+ "time"
+)
+
+// Envelope is used when doing a zone transfer with a remote server.
+type Envelope struct {
+ RR []RR // The set of RRs in the answer section of the xfr reply message.
+ Error error // If something went wrong, this contains the error.
+}
+
+// A Transfer defines parameters that are used during a zone transfer.
+type Transfer struct {
+ *Conn
+ DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds
+ ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds
+ WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds
+ TsigSecret map[string]string // Secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
+ tsigTimersOnly bool
+}
+
+// Think we need to away to stop the transfer
+
+// In performs an incoming transfer with the server in a.
+// If you would like to set the source IP, or some other attribute
+// of a Dialer for a Transfer, you can do so by specifying the attributes
+// in the Transfer.Conn:
+//
+// d := net.Dialer{LocalAddr: transfer_source}
+// con, err := d.Dial("tcp", master)
+// dnscon := &dns.Conn{Conn:con}
+// transfer = &dns.Transfer{Conn: dnscon}
+// channel, err := transfer.In(message, master)
+//
+func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) {
+ timeout := dnsTimeout
+ if t.DialTimeout != 0 {
+ timeout = t.DialTimeout
+ }
+ if t.Conn == nil {
+ t.Conn, err = DialTimeout("tcp", a, timeout)
+ if err != nil {
+ return nil, err
+ }
+ }
+ if err := t.WriteMsg(q); err != nil {
+ return nil, err
+ }
+ env = make(chan *Envelope)
+ go func() {
+ if q.Question[0].Qtype == TypeAXFR {
+ go t.inAxfr(q, env)
+ return
+ }
+ if q.Question[0].Qtype == TypeIXFR {
+ go t.inIxfr(q, env)
+ return
+ }
+ }()
+ return env, nil
+}
+
+func (t *Transfer) inAxfr(q *Msg, c chan *Envelope) {
+ first := true
+ defer t.Close()
+ defer close(c)
+ timeout := dnsTimeout
+ if t.ReadTimeout != 0 {
+ timeout = t.ReadTimeout
+ }
+ for {
+ t.Conn.SetReadDeadline(time.Now().Add(timeout))
+ in, err := t.ReadMsg()
+ if err != nil {
+ c <- &Envelope{nil, err}
+ return
+ }
+ if q.Id != in.Id {
+ c <- &Envelope{in.Answer, ErrId}
+ return
+ }
+ if first {
+ if in.Rcode != RcodeSuccess {
+ c <- &Envelope{in.Answer, &Error{err: fmt.Sprintf(errXFR, in.Rcode)}}
+ return
+ }
+ if !isSOAFirst(in) {
+ c <- &Envelope{in.Answer, ErrSoa}
+ return
+ }
+ first = !first
+ // only one answer that is SOA, receive more
+ if len(in.Answer) == 1 {
+ t.tsigTimersOnly = true
+ c <- &Envelope{in.Answer, nil}
+ continue
+ }
+ }
+
+ if !first {
+ t.tsigTimersOnly = true // Subsequent envelopes use this.
+ if isSOALast(in) {
+ c <- &Envelope{in.Answer, nil}
+ return
+ }
+ c <- &Envelope{in.Answer, nil}
+ }
+ }
+}
+
+func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) {
+ serial := uint32(0) // The first serial seen is the current server serial
+ axfr := true
+ n := 0
+ qser := q.Ns[0].(*SOA).Serial
+ defer t.Close()
+ defer close(c)
+ timeout := dnsTimeout
+ if t.ReadTimeout != 0 {
+ timeout = t.ReadTimeout
+ }
+ for {
+ t.SetReadDeadline(time.Now().Add(timeout))
+ in, err := t.ReadMsg()
+ if err != nil {
+ c <- &Envelope{nil, err}
+ return
+ }
+ if q.Id != in.Id {
+ c <- &Envelope{in.Answer, ErrId}
+ return
+ }
+ if in.Rcode != RcodeSuccess {
+ c <- &Envelope{in.Answer, &Error{err: fmt.Sprintf(errXFR, in.Rcode)}}
+ return
+ }
+ if n == 0 {
+ // Check if the returned answer is ok
+ if !isSOAFirst(in) {
+ c <- &Envelope{in.Answer, ErrSoa}
+ return
+ }
+ // This serial is important
+ serial = in.Answer[0].(*SOA).Serial
+ // Check if there are no changes in zone
+ if qser >= serial {
+ c <- &Envelope{in.Answer, nil}
+ return
+ }
+ }
+ // Now we need to check each message for SOA records, to see what we need to do
+ t.tsigTimersOnly = true
+ for _, rr := range in.Answer {
+ if v, ok := rr.(*SOA); ok {
+ if v.Serial == serial {
+ n++
+ // quit if it's a full axfr or the the servers' SOA is repeated the third time
+ if axfr && n == 2 || n == 3 {
+ c <- &Envelope{in.Answer, nil}
+ return
+ }
+ } else if axfr {
+ // it's an ixfr
+ axfr = false
+ }
+ }
+ }
+ c <- &Envelope{in.Answer, nil}
+ }
+}
+
+// Out performs an outgoing transfer with the client connecting in w.
+// Basic use pattern:
+//
+// ch := make(chan *dns.Envelope)
+// tr := new(dns.Transfer)
+// go tr.Out(w, r, ch)
+// ch <- &dns.Envelope{RR: []dns.RR{soa, rr1, rr2, rr3, soa}}
+// close(ch)
+// w.Hijack()
+// // w.Close() // Client closes connection
+//
+// The server is responsible for sending the correct sequence of RRs through the
+// channel ch.
+func (t *Transfer) Out(w ResponseWriter, q *Msg, ch chan *Envelope) error {
+ for x := range ch {
+ r := new(Msg)
+ // Compress?
+ r.SetReply(q)
+ r.Authoritative = true
+ // assume it fits TODO(miek): fix
+ r.Answer = append(r.Answer, x.RR...)
+ if err := w.WriteMsg(r); err != nil {
+ return err
+ }
+ }
+ w.TsigTimersOnly(true)
+ return nil
+}
+
+// ReadMsg reads a message from the transfer connection t.
+func (t *Transfer) ReadMsg() (*Msg, error) {
+ m := new(Msg)
+ p := make([]byte, MaxMsgSize)
+ n, err := t.Read(p)
+ if err != nil && n == 0 {
+ return nil, err
+ }
+ p = p[:n]
+ if err := m.Unpack(p); err != nil {
+ return nil, err
+ }
+ if ts := m.IsTsig(); ts != nil && t.TsigSecret != nil {
+ if _, ok := t.TsigSecret[ts.Hdr.Name]; !ok {
+ return m, ErrSecret
+ }
+ // Need to work on the original message p, as that was used to calculate the tsig.
+ err = TsigVerify(p, t.TsigSecret[ts.Hdr.Name], t.tsigRequestMAC, t.tsigTimersOnly)
+ t.tsigRequestMAC = ts.MAC
+ }
+ return m, err
+}
+
+// WriteMsg writes a message through the transfer connection t.
+func (t *Transfer) WriteMsg(m *Msg) (err error) {
+ var out []byte
+ if ts := m.IsTsig(); ts != nil && t.TsigSecret != nil {
+ if _, ok := t.TsigSecret[ts.Hdr.Name]; !ok {
+ return ErrSecret
+ }
+ out, t.tsigRequestMAC, err = TsigGenerate(m, t.TsigSecret[ts.Hdr.Name], t.tsigRequestMAC, t.tsigTimersOnly)
+ } else {
+ out, err = m.Pack()
+ }
+ if err != nil {
+ return err
+ }
+ if _, err = t.Write(out); err != nil {
+ return err
+ }
+ return nil
+}
+
+func isSOAFirst(in *Msg) bool {
+ if len(in.Answer) > 0 {
+ return in.Answer[0].Header().Rrtype == TypeSOA
+ }
+ return false
+}
+
+func isSOALast(in *Msg) bool {
+ if len(in.Answer) > 0 {
+ return in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
+ }
+ return false
+}
+
+const errXFR = "bad xfr rcode: %d"
--- /dev/null
+// *** DO NOT MODIFY ***
+// AUTOGENERATED BY go generate from compress_generate.go
+
+package dns
+
+func compressionLenHelperType(c map[string]int, r RR) {
+ switch x := r.(type) {
+ case *AFSDB:
+ compressionLenHelper(c, x.Hostname)
+ case *CNAME:
+ compressionLenHelper(c, x.Target)
+ case *DNAME:
+ compressionLenHelper(c, x.Target)
+ case *HIP:
+ for i := range x.RendezvousServers {
+ compressionLenHelper(c, x.RendezvousServers[i])
+ }
+ case *KX:
+ compressionLenHelper(c, x.Exchanger)
+ case *LP:
+ compressionLenHelper(c, x.Fqdn)
+ case *MB:
+ compressionLenHelper(c, x.Mb)
+ case *MD:
+ compressionLenHelper(c, x.Md)
+ case *MF:
+ compressionLenHelper(c, x.Mf)
+ case *MG:
+ compressionLenHelper(c, x.Mg)
+ case *MINFO:
+ compressionLenHelper(c, x.Rmail)
+ compressionLenHelper(c, x.Email)
+ case *MR:
+ compressionLenHelper(c, x.Mr)
+ case *MX:
+ compressionLenHelper(c, x.Mx)
+ case *NAPTR:
+ compressionLenHelper(c, x.Replacement)
+ case *NS:
+ compressionLenHelper(c, x.Ns)
+ case *NSAPPTR:
+ compressionLenHelper(c, x.Ptr)
+ case *NSEC:
+ compressionLenHelper(c, x.NextDomain)
+ case *PTR:
+ compressionLenHelper(c, x.Ptr)
+ case *PX:
+ compressionLenHelper(c, x.Map822)
+ compressionLenHelper(c, x.Mapx400)
+ case *RP:
+ compressionLenHelper(c, x.Mbox)
+ compressionLenHelper(c, x.Txt)
+ case *RRSIG:
+ compressionLenHelper(c, x.SignerName)
+ case *RT:
+ compressionLenHelper(c, x.Host)
+ case *SIG:
+ compressionLenHelper(c, x.SignerName)
+ case *SOA:
+ compressionLenHelper(c, x.Ns)
+ compressionLenHelper(c, x.Mbox)
+ case *SRV:
+ compressionLenHelper(c, x.Target)
+ case *TALINK:
+ compressionLenHelper(c, x.PreviousName)
+ compressionLenHelper(c, x.NextName)
+ case *TKEY:
+ compressionLenHelper(c, x.Algorithm)
+ case *TSIG:
+ compressionLenHelper(c, x.Algorithm)
+ }
+}
+
+func compressionLenSearchType(c map[string]int, r RR) (int, bool) {
+ switch x := r.(type) {
+ case *AFSDB:
+ k1, ok1 := compressionLenSearch(c, x.Hostname)
+ return k1, ok1
+ case *CNAME:
+ k1, ok1 := compressionLenSearch(c, x.Target)
+ return k1, ok1
+ case *MB:
+ k1, ok1 := compressionLenSearch(c, x.Mb)
+ return k1, ok1
+ case *MD:
+ k1, ok1 := compressionLenSearch(c, x.Md)
+ return k1, ok1
+ case *MF:
+ k1, ok1 := compressionLenSearch(c, x.Mf)
+ return k1, ok1
+ case *MG:
+ k1, ok1 := compressionLenSearch(c, x.Mg)
+ return k1, ok1
+ case *MINFO:
+ k1, ok1 := compressionLenSearch(c, x.Rmail)
+ k2, ok2 := compressionLenSearch(c, x.Email)
+ return k1 + k2, ok1 && ok2
+ case *MR:
+ k1, ok1 := compressionLenSearch(c, x.Mr)
+ return k1, ok1
+ case *MX:
+ k1, ok1 := compressionLenSearch(c, x.Mx)
+ return k1, ok1
+ case *NS:
+ k1, ok1 := compressionLenSearch(c, x.Ns)
+ return k1, ok1
+ case *PTR:
+ k1, ok1 := compressionLenSearch(c, x.Ptr)
+ return k1, ok1
+ case *RT:
+ k1, ok1 := compressionLenSearch(c, x.Host)
+ return k1, ok1
+ case *SOA:
+ k1, ok1 := compressionLenSearch(c, x.Ns)
+ k2, ok2 := compressionLenSearch(c, x.Mbox)
+ return k1 + k2, ok1 && ok2
+ }
+ return 0, false
+}
--- /dev/null
+// *** DO NOT MODIFY ***
+// AUTOGENERATED BY go generate from msg_generate.go
+
+package dns
+
+// pack*() functions
+
+func (rr *A) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packDataA(rr.A, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *AAAA) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packDataAAAA(rr.AAAA, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *AFSDB) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.Subtype, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = PackDomainName(rr.Hostname, msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *ANY) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *AVC) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packStringTxt(rr.Txt, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *CAA) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint8(rr.Flag, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packString(rr.Tag, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringOctet(rr.Value, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *CDNSKEY) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.Flags, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Protocol, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Algorithm, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringBase64(rr.PublicKey, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *CDS) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.KeyTag, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Algorithm, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.DigestType, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringHex(rr.Digest, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *CERT) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.Type, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.KeyTag, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Algorithm, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringBase64(rr.Certificate, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *CNAME) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = PackDomainName(rr.Target, msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *DHCID) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packStringBase64(rr.Digest, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *DLV) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.KeyTag, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Algorithm, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.DigestType, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringHex(rr.Digest, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *DNAME) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = PackDomainName(rr.Target, msg, off, compression, false)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *DNSKEY) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.Flags, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Protocol, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Algorithm, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringBase64(rr.PublicKey, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *DS) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.KeyTag, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Algorithm, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.DigestType, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringHex(rr.Digest, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *EID) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packStringHex(rr.Endpoint, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *EUI48) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint48(rr.Address, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *EUI64) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint64(rr.Address, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *GID) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint32(rr.Gid, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *GPOS) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packString(rr.Longitude, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packString(rr.Latitude, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packString(rr.Altitude, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *HINFO) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packString(rr.Cpu, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packString(rr.Os, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *HIP) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint8(rr.HitLength, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.PublicKeyAlgorithm, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.PublicKeyLength, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringHex(rr.Hit, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringBase64(rr.PublicKey, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packDataDomainNames(rr.RendezvousServers, msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *KEY) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.Flags, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Protocol, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Algorithm, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringBase64(rr.PublicKey, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *KX) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.Preference, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = PackDomainName(rr.Exchanger, msg, off, compression, false)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *L32) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.Preference, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packDataA(rr.Locator32, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *L64) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.Preference, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint64(rr.Locator64, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *LOC) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint8(rr.Version, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Size, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.HorizPre, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.VertPre, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(rr.Latitude, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(rr.Longitude, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(rr.Altitude, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *LP) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.Preference, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = PackDomainName(rr.Fqdn, msg, off, compression, false)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *MB) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = PackDomainName(rr.Mb, msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *MD) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = PackDomainName(rr.Md, msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *MF) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = PackDomainName(rr.Mf, msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *MG) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = PackDomainName(rr.Mg, msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *MINFO) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = PackDomainName(rr.Rmail, msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ off, err = PackDomainName(rr.Email, msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *MR) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = PackDomainName(rr.Mr, msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *MX) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.Preference, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = PackDomainName(rr.Mx, msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *NAPTR) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.Order, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.Preference, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packString(rr.Flags, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packString(rr.Service, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packString(rr.Regexp, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = PackDomainName(rr.Replacement, msg, off, compression, false)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *NID) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.Preference, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint64(rr.NodeID, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *NIMLOC) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packStringHex(rr.Locator, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *NINFO) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packStringTxt(rr.ZSData, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *NS) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = PackDomainName(rr.Ns, msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *NSAPPTR) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = PackDomainName(rr.Ptr, msg, off, compression, false)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *NSEC) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = PackDomainName(rr.NextDomain, msg, off, compression, false)
+ if err != nil {
+ return off, err
+ }
+ off, err = packDataNsec(rr.TypeBitMap, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *NSEC3) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint8(rr.Hash, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Flags, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.Iterations, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.SaltLength, msg, off)
+ if err != nil {
+ return off, err
+ }
+ // Only pack salt if value is not "-", i.e. empty
+ if rr.Salt != "-" {
+ off, err = packStringHex(rr.Salt, msg, off)
+ if err != nil {
+ return off, err
+ }
+ }
+ off, err = packUint8(rr.HashLength, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringBase32(rr.NextDomain, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packDataNsec(rr.TypeBitMap, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *NSEC3PARAM) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint8(rr.Hash, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Flags, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.Iterations, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.SaltLength, msg, off)
+ if err != nil {
+ return off, err
+ }
+ // Only pack salt if value is not "-", i.e. empty
+ if rr.Salt != "-" {
+ off, err = packStringHex(rr.Salt, msg, off)
+ if err != nil {
+ return off, err
+ }
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *OPENPGPKEY) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packStringBase64(rr.PublicKey, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *OPT) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packDataOpt(rr.Option, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *PTR) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = PackDomainName(rr.Ptr, msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *PX) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.Preference, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = PackDomainName(rr.Map822, msg, off, compression, false)
+ if err != nil {
+ return off, err
+ }
+ off, err = PackDomainName(rr.Mapx400, msg, off, compression, false)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *RFC3597) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packStringHex(rr.Rdata, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *RKEY) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.Flags, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Protocol, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Algorithm, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringBase64(rr.PublicKey, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *RP) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = PackDomainName(rr.Mbox, msg, off, compression, false)
+ if err != nil {
+ return off, err
+ }
+ off, err = PackDomainName(rr.Txt, msg, off, compression, false)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *RRSIG) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.TypeCovered, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Algorithm, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Labels, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(rr.OrigTtl, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(rr.Expiration, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(rr.Inception, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.KeyTag, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = PackDomainName(rr.SignerName, msg, off, compression, false)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringBase64(rr.Signature, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *RT) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.Preference, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = PackDomainName(rr.Host, msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *SIG) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.TypeCovered, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Algorithm, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Labels, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(rr.OrigTtl, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(rr.Expiration, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(rr.Inception, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.KeyTag, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = PackDomainName(rr.SignerName, msg, off, compression, false)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringBase64(rr.Signature, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *SMIMEA) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint8(rr.Usage, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Selector, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.MatchingType, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringHex(rr.Certificate, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *SOA) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = PackDomainName(rr.Ns, msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ off, err = PackDomainName(rr.Mbox, msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(rr.Serial, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(rr.Refresh, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(rr.Retry, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(rr.Expire, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(rr.Minttl, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *SPF) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packStringTxt(rr.Txt, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *SRV) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.Priority, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.Weight, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.Port, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = PackDomainName(rr.Target, msg, off, compression, false)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *SSHFP) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint8(rr.Algorithm, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Type, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringHex(rr.FingerPrint, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *TA) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.KeyTag, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Algorithm, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.DigestType, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringHex(rr.Digest, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *TALINK) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = PackDomainName(rr.PreviousName, msg, off, compression, false)
+ if err != nil {
+ return off, err
+ }
+ off, err = PackDomainName(rr.NextName, msg, off, compression, false)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *TKEY) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = PackDomainName(rr.Algorithm, msg, off, compression, false)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(rr.Inception, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint32(rr.Expiration, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.Mode, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.Error, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.KeySize, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packString(rr.Key, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.OtherLen, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packString(rr.OtherData, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *TLSA) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint8(rr.Usage, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.Selector, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint8(rr.MatchingType, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringHex(rr.Certificate, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *TSIG) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = PackDomainName(rr.Algorithm, msg, off, compression, false)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint48(rr.TimeSigned, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.Fudge, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.MACSize, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringHex(rr.MAC, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.OrigId, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.Error, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.OtherLen, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringHex(rr.OtherData, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *TXT) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packStringTxt(rr.Txt, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *UID) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint32(rr.Uid, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *UINFO) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packString(rr.Uinfo, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *URI) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packUint16(rr.Priority, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packUint16(rr.Weight, msg, off)
+ if err != nil {
+ return off, err
+ }
+ off, err = packStringOctet(rr.Target, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+func (rr *X25) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
+ off, err := rr.Hdr.pack(msg, off, compression, compress)
+ if err != nil {
+ return off, err
+ }
+ headerEnd := off
+ off, err = packString(rr.PSDNAddress, msg, off)
+ if err != nil {
+ return off, err
+ }
+ rr.Header().Rdlength = uint16(off - headerEnd)
+ return off, nil
+}
+
+// unpack*() functions
+
+func unpackA(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(A)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.A, off, err = unpackDataA(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackAAAA(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(AAAA)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.AAAA, off, err = unpackDataAAAA(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackAFSDB(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(AFSDB)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Subtype, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Hostname, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackANY(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(ANY)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ return rr, off, err
+}
+
+func unpackAVC(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(AVC)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Txt, off, err = unpackStringTxt(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackCAA(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(CAA)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Flag, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Tag, off, err = unpackString(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Value, off, err = unpackStringOctet(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackCDNSKEY(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(CDNSKEY)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Flags, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Protocol, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Algorithm, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackCDS(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(CDS)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.KeyTag, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Algorithm, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.DigestType, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackCERT(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(CERT)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Type, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.KeyTag, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Algorithm, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Certificate, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackCNAME(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(CNAME)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Target, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackDHCID(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(DHCID)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Digest, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackDLV(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(DLV)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.KeyTag, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Algorithm, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.DigestType, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackDNAME(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(DNAME)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Target, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackDNSKEY(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(DNSKEY)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Flags, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Protocol, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Algorithm, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackDS(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(DS)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.KeyTag, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Algorithm, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.DigestType, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackEID(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(EID)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Endpoint, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackEUI48(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(EUI48)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Address, off, err = unpackUint48(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackEUI64(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(EUI64)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Address, off, err = unpackUint64(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackGID(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(GID)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Gid, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackGPOS(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(GPOS)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Longitude, off, err = unpackString(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Latitude, off, err = unpackString(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Altitude, off, err = unpackString(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackHINFO(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(HINFO)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Cpu, off, err = unpackString(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Os, off, err = unpackString(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackHIP(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(HIP)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.HitLength, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.PublicKeyAlgorithm, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.PublicKeyLength, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Hit, off, err = unpackStringHex(msg, off, off+int(rr.HitLength))
+ if err != nil {
+ return rr, off, err
+ }
+ rr.PublicKey, off, err = unpackStringBase64(msg, off, off+int(rr.PublicKeyLength))
+ if err != nil {
+ return rr, off, err
+ }
+ rr.RendezvousServers, off, err = unpackDataDomainNames(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackKEY(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(KEY)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Flags, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Protocol, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Algorithm, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackKX(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(KX)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Preference, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Exchanger, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackL32(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(L32)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Preference, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Locator32, off, err = unpackDataA(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackL64(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(L64)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Preference, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Locator64, off, err = unpackUint64(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackLOC(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(LOC)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Version, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Size, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.HorizPre, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.VertPre, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Latitude, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Longitude, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Altitude, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackLP(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(LP)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Preference, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Fqdn, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackMB(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(MB)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Mb, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackMD(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(MD)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Md, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackMF(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(MF)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Mf, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackMG(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(MG)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Mg, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackMINFO(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(MINFO)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Rmail, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Email, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackMR(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(MR)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Mr, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackMX(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(MX)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Preference, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Mx, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackNAPTR(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(NAPTR)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Order, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Preference, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Flags, off, err = unpackString(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Service, off, err = unpackString(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Regexp, off, err = unpackString(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Replacement, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackNID(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(NID)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Preference, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.NodeID, off, err = unpackUint64(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackNIMLOC(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(NIMLOC)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Locator, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackNINFO(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(NINFO)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.ZSData, off, err = unpackStringTxt(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackNS(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(NS)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Ns, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackNSAPPTR(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(NSAPPTR)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Ptr, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackNSEC(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(NSEC)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.NextDomain, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.TypeBitMap, off, err = unpackDataNsec(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackNSEC3(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(NSEC3)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Hash, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Flags, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Iterations, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.SaltLength, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Salt, off, err = unpackStringHex(msg, off, off+int(rr.SaltLength))
+ if err != nil {
+ return rr, off, err
+ }
+ rr.HashLength, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.NextDomain, off, err = unpackStringBase32(msg, off, off+int(rr.HashLength))
+ if err != nil {
+ return rr, off, err
+ }
+ rr.TypeBitMap, off, err = unpackDataNsec(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackNSEC3PARAM(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(NSEC3PARAM)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Hash, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Flags, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Iterations, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.SaltLength, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Salt, off, err = unpackStringHex(msg, off, off+int(rr.SaltLength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackOPENPGPKEY(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(OPENPGPKEY)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackOPT(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(OPT)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Option, off, err = unpackDataOpt(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackPTR(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(PTR)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Ptr, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackPX(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(PX)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Preference, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Map822, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Mapx400, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackRFC3597(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(RFC3597)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Rdata, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackRKEY(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(RKEY)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Flags, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Protocol, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Algorithm, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.PublicKey, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackRP(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(RP)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Mbox, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Txt, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackRRSIG(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(RRSIG)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.TypeCovered, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Algorithm, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Labels, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.OrigTtl, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Expiration, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Inception, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.KeyTag, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.SignerName, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Signature, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackRT(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(RT)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Preference, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Host, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackSIG(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(SIG)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.TypeCovered, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Algorithm, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Labels, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.OrigTtl, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Expiration, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Inception, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.KeyTag, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.SignerName, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Signature, off, err = unpackStringBase64(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackSMIMEA(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(SMIMEA)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Usage, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Selector, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.MatchingType, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Certificate, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackSOA(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(SOA)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Ns, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Mbox, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Serial, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Refresh, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Retry, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Expire, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Minttl, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackSPF(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(SPF)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Txt, off, err = unpackStringTxt(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackSRV(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(SRV)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Priority, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Weight, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Port, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Target, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackSSHFP(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(SSHFP)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Algorithm, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Type, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.FingerPrint, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackTA(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(TA)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.KeyTag, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Algorithm, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.DigestType, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackTALINK(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(TALINK)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.PreviousName, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.NextName, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackTKEY(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(TKEY)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Algorithm, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Inception, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Expiration, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Mode, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Error, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.KeySize, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Key, off, err = unpackString(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.OtherLen, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.OtherData, off, err = unpackString(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackTLSA(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(TLSA)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Usage, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Selector, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.MatchingType, off, err = unpackUint8(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Certificate, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackTSIG(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(TSIG)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Algorithm, off, err = UnpackDomainName(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.TimeSigned, off, err = unpackUint48(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Fudge, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.MACSize, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.MAC, off, err = unpackStringHex(msg, off, off+int(rr.MACSize))
+ if err != nil {
+ return rr, off, err
+ }
+ rr.OrigId, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Error, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.OtherLen, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.OtherData, off, err = unpackStringHex(msg, off, off+int(rr.OtherLen))
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackTXT(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(TXT)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Txt, off, err = unpackStringTxt(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackUID(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(UID)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Uid, off, err = unpackUint32(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackUINFO(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(UINFO)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Uinfo, off, err = unpackString(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackURI(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(URI)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.Priority, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Weight, off, err = unpackUint16(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ if off == len(msg) {
+ return rr, off, nil
+ }
+ rr.Target, off, err = unpackStringOctet(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+func unpackX25(h RR_Header, msg []byte, off int) (RR, int, error) {
+ rr := new(X25)
+ rr.Hdr = h
+ if noRdata(h) {
+ return rr, off, nil
+ }
+ var err error
+ rdStart := off
+ _ = rdStart
+
+ rr.PSDNAddress, off, err = unpackString(msg, off)
+ if err != nil {
+ return rr, off, err
+ }
+ return rr, off, err
+}
+
+var typeToUnpack = map[uint16]func(RR_Header, []byte, int) (RR, int, error){
+ TypeA: unpackA,
+ TypeAAAA: unpackAAAA,
+ TypeAFSDB: unpackAFSDB,
+ TypeANY: unpackANY,
+ TypeAVC: unpackAVC,
+ TypeCAA: unpackCAA,
+ TypeCDNSKEY: unpackCDNSKEY,
+ TypeCDS: unpackCDS,
+ TypeCERT: unpackCERT,
+ TypeCNAME: unpackCNAME,
+ TypeDHCID: unpackDHCID,
+ TypeDLV: unpackDLV,
+ TypeDNAME: unpackDNAME,
+ TypeDNSKEY: unpackDNSKEY,
+ TypeDS: unpackDS,
+ TypeEID: unpackEID,
+ TypeEUI48: unpackEUI48,
+ TypeEUI64: unpackEUI64,
+ TypeGID: unpackGID,
+ TypeGPOS: unpackGPOS,
+ TypeHINFO: unpackHINFO,
+ TypeHIP: unpackHIP,
+ TypeKEY: unpackKEY,
+ TypeKX: unpackKX,
+ TypeL32: unpackL32,
+ TypeL64: unpackL64,
+ TypeLOC: unpackLOC,
+ TypeLP: unpackLP,
+ TypeMB: unpackMB,
+ TypeMD: unpackMD,
+ TypeMF: unpackMF,
+ TypeMG: unpackMG,
+ TypeMINFO: unpackMINFO,
+ TypeMR: unpackMR,
+ TypeMX: unpackMX,
+ TypeNAPTR: unpackNAPTR,
+ TypeNID: unpackNID,
+ TypeNIMLOC: unpackNIMLOC,
+ TypeNINFO: unpackNINFO,
+ TypeNS: unpackNS,
+ TypeNSAPPTR: unpackNSAPPTR,
+ TypeNSEC: unpackNSEC,
+ TypeNSEC3: unpackNSEC3,
+ TypeNSEC3PARAM: unpackNSEC3PARAM,
+ TypeOPENPGPKEY: unpackOPENPGPKEY,
+ TypeOPT: unpackOPT,
+ TypePTR: unpackPTR,
+ TypePX: unpackPX,
+ TypeRKEY: unpackRKEY,
+ TypeRP: unpackRP,
+ TypeRRSIG: unpackRRSIG,
+ TypeRT: unpackRT,
+ TypeSIG: unpackSIG,
+ TypeSMIMEA: unpackSMIMEA,
+ TypeSOA: unpackSOA,
+ TypeSPF: unpackSPF,
+ TypeSRV: unpackSRV,
+ TypeSSHFP: unpackSSHFP,
+ TypeTA: unpackTA,
+ TypeTALINK: unpackTALINK,
+ TypeTKEY: unpackTKEY,
+ TypeTLSA: unpackTLSA,
+ TypeTSIG: unpackTSIG,
+ TypeTXT: unpackTXT,
+ TypeUID: unpackUID,
+ TypeUINFO: unpackUINFO,
+ TypeURI: unpackURI,
+ TypeX25: unpackX25,
+}
--- /dev/null
+// *** DO NOT MODIFY ***
+// AUTOGENERATED BY go generate from types_generate.go
+
+package dns
+
+import (
+ "encoding/base64"
+ "net"
+)
+
+// TypeToRR is a map of constructors for each RR type.
+var TypeToRR = map[uint16]func() RR{
+ TypeA: func() RR { return new(A) },
+ TypeAAAA: func() RR { return new(AAAA) },
+ TypeAFSDB: func() RR { return new(AFSDB) },
+ TypeANY: func() RR { return new(ANY) },
+ TypeAVC: func() RR { return new(AVC) },
+ TypeCAA: func() RR { return new(CAA) },
+ TypeCDNSKEY: func() RR { return new(CDNSKEY) },
+ TypeCDS: func() RR { return new(CDS) },
+ TypeCERT: func() RR { return new(CERT) },
+ TypeCNAME: func() RR { return new(CNAME) },
+ TypeDHCID: func() RR { return new(DHCID) },
+ TypeDLV: func() RR { return new(DLV) },
+ TypeDNAME: func() RR { return new(DNAME) },
+ TypeDNSKEY: func() RR { return new(DNSKEY) },
+ TypeDS: func() RR { return new(DS) },
+ TypeEID: func() RR { return new(EID) },
+ TypeEUI48: func() RR { return new(EUI48) },
+ TypeEUI64: func() RR { return new(EUI64) },
+ TypeGID: func() RR { return new(GID) },
+ TypeGPOS: func() RR { return new(GPOS) },
+ TypeHINFO: func() RR { return new(HINFO) },
+ TypeHIP: func() RR { return new(HIP) },
+ TypeKEY: func() RR { return new(KEY) },
+ TypeKX: func() RR { return new(KX) },
+ TypeL32: func() RR { return new(L32) },
+ TypeL64: func() RR { return new(L64) },
+ TypeLOC: func() RR { return new(LOC) },
+ TypeLP: func() RR { return new(LP) },
+ TypeMB: func() RR { return new(MB) },
+ TypeMD: func() RR { return new(MD) },
+ TypeMF: func() RR { return new(MF) },
+ TypeMG: func() RR { return new(MG) },
+ TypeMINFO: func() RR { return new(MINFO) },
+ TypeMR: func() RR { return new(MR) },
+ TypeMX: func() RR { return new(MX) },
+ TypeNAPTR: func() RR { return new(NAPTR) },
+ TypeNID: func() RR { return new(NID) },
+ TypeNIMLOC: func() RR { return new(NIMLOC) },
+ TypeNINFO: func() RR { return new(NINFO) },
+ TypeNS: func() RR { return new(NS) },
+ TypeNSAPPTR: func() RR { return new(NSAPPTR) },
+ TypeNSEC: func() RR { return new(NSEC) },
+ TypeNSEC3: func() RR { return new(NSEC3) },
+ TypeNSEC3PARAM: func() RR { return new(NSEC3PARAM) },
+ TypeOPENPGPKEY: func() RR { return new(OPENPGPKEY) },
+ TypeOPT: func() RR { return new(OPT) },
+ TypePTR: func() RR { return new(PTR) },
+ TypePX: func() RR { return new(PX) },
+ TypeRKEY: func() RR { return new(RKEY) },
+ TypeRP: func() RR { return new(RP) },
+ TypeRRSIG: func() RR { return new(RRSIG) },
+ TypeRT: func() RR { return new(RT) },
+ TypeSIG: func() RR { return new(SIG) },
+ TypeSMIMEA: func() RR { return new(SMIMEA) },
+ TypeSOA: func() RR { return new(SOA) },
+ TypeSPF: func() RR { return new(SPF) },
+ TypeSRV: func() RR { return new(SRV) },
+ TypeSSHFP: func() RR { return new(SSHFP) },
+ TypeTA: func() RR { return new(TA) },
+ TypeTALINK: func() RR { return new(TALINK) },
+ TypeTKEY: func() RR { return new(TKEY) },
+ TypeTLSA: func() RR { return new(TLSA) },
+ TypeTSIG: func() RR { return new(TSIG) },
+ TypeTXT: func() RR { return new(TXT) },
+ TypeUID: func() RR { return new(UID) },
+ TypeUINFO: func() RR { return new(UINFO) },
+ TypeURI: func() RR { return new(URI) },
+ TypeX25: func() RR { return new(X25) },
+}
+
+// TypeToString is a map of strings for each RR type.
+var TypeToString = map[uint16]string{
+ TypeA: "A",
+ TypeAAAA: "AAAA",
+ TypeAFSDB: "AFSDB",
+ TypeANY: "ANY",
+ TypeATMA: "ATMA",
+ TypeAVC: "AVC",
+ TypeAXFR: "AXFR",
+ TypeCAA: "CAA",
+ TypeCDNSKEY: "CDNSKEY",
+ TypeCDS: "CDS",
+ TypeCERT: "CERT",
+ TypeCNAME: "CNAME",
+ TypeDHCID: "DHCID",
+ TypeDLV: "DLV",
+ TypeDNAME: "DNAME",
+ TypeDNSKEY: "DNSKEY",
+ TypeDS: "DS",
+ TypeEID: "EID",
+ TypeEUI48: "EUI48",
+ TypeEUI64: "EUI64",
+ TypeGID: "GID",
+ TypeGPOS: "GPOS",
+ TypeHINFO: "HINFO",
+ TypeHIP: "HIP",
+ TypeISDN: "ISDN",
+ TypeIXFR: "IXFR",
+ TypeKEY: "KEY",
+ TypeKX: "KX",
+ TypeL32: "L32",
+ TypeL64: "L64",
+ TypeLOC: "LOC",
+ TypeLP: "LP",
+ TypeMAILA: "MAILA",
+ TypeMAILB: "MAILB",
+ TypeMB: "MB",
+ TypeMD: "MD",
+ TypeMF: "MF",
+ TypeMG: "MG",
+ TypeMINFO: "MINFO",
+ TypeMR: "MR",
+ TypeMX: "MX",
+ TypeNAPTR: "NAPTR",
+ TypeNID: "NID",
+ TypeNIMLOC: "NIMLOC",
+ TypeNINFO: "NINFO",
+ TypeNS: "NS",
+ TypeNSEC: "NSEC",
+ TypeNSEC3: "NSEC3",
+ TypeNSEC3PARAM: "NSEC3PARAM",
+ TypeNULL: "NULL",
+ TypeNXT: "NXT",
+ TypeNone: "None",
+ TypeOPENPGPKEY: "OPENPGPKEY",
+ TypeOPT: "OPT",
+ TypePTR: "PTR",
+ TypePX: "PX",
+ TypeRKEY: "RKEY",
+ TypeRP: "RP",
+ TypeRRSIG: "RRSIG",
+ TypeRT: "RT",
+ TypeReserved: "Reserved",
+ TypeSIG: "SIG",
+ TypeSMIMEA: "SMIMEA",
+ TypeSOA: "SOA",
+ TypeSPF: "SPF",
+ TypeSRV: "SRV",
+ TypeSSHFP: "SSHFP",
+ TypeTA: "TA",
+ TypeTALINK: "TALINK",
+ TypeTKEY: "TKEY",
+ TypeTLSA: "TLSA",
+ TypeTSIG: "TSIG",
+ TypeTXT: "TXT",
+ TypeUID: "UID",
+ TypeUINFO: "UINFO",
+ TypeUNSPEC: "UNSPEC",
+ TypeURI: "URI",
+ TypeX25: "X25",
+ TypeNSAPPTR: "NSAP-PTR",
+}
+
+func (rr *A) Header() *RR_Header { return &rr.Hdr }
+func (rr *AAAA) Header() *RR_Header { return &rr.Hdr }
+func (rr *AFSDB) Header() *RR_Header { return &rr.Hdr }
+func (rr *ANY) Header() *RR_Header { return &rr.Hdr }
+func (rr *AVC) Header() *RR_Header { return &rr.Hdr }
+func (rr *CAA) Header() *RR_Header { return &rr.Hdr }
+func (rr *CDNSKEY) Header() *RR_Header { return &rr.Hdr }
+func (rr *CDS) Header() *RR_Header { return &rr.Hdr }
+func (rr *CERT) Header() *RR_Header { return &rr.Hdr }
+func (rr *CNAME) Header() *RR_Header { return &rr.Hdr }
+func (rr *DHCID) Header() *RR_Header { return &rr.Hdr }
+func (rr *DLV) Header() *RR_Header { return &rr.Hdr }
+func (rr *DNAME) Header() *RR_Header { return &rr.Hdr }
+func (rr *DNSKEY) Header() *RR_Header { return &rr.Hdr }
+func (rr *DS) Header() *RR_Header { return &rr.Hdr }
+func (rr *EID) Header() *RR_Header { return &rr.Hdr }
+func (rr *EUI48) Header() *RR_Header { return &rr.Hdr }
+func (rr *EUI64) Header() *RR_Header { return &rr.Hdr }
+func (rr *GID) Header() *RR_Header { return &rr.Hdr }
+func (rr *GPOS) Header() *RR_Header { return &rr.Hdr }
+func (rr *HINFO) Header() *RR_Header { return &rr.Hdr }
+func (rr *HIP) Header() *RR_Header { return &rr.Hdr }
+func (rr *KEY) Header() *RR_Header { return &rr.Hdr }
+func (rr *KX) Header() *RR_Header { return &rr.Hdr }
+func (rr *L32) Header() *RR_Header { return &rr.Hdr }
+func (rr *L64) Header() *RR_Header { return &rr.Hdr }
+func (rr *LOC) Header() *RR_Header { return &rr.Hdr }
+func (rr *LP) Header() *RR_Header { return &rr.Hdr }
+func (rr *MB) Header() *RR_Header { return &rr.Hdr }
+func (rr *MD) Header() *RR_Header { return &rr.Hdr }
+func (rr *MF) Header() *RR_Header { return &rr.Hdr }
+func (rr *MG) Header() *RR_Header { return &rr.Hdr }
+func (rr *MINFO) Header() *RR_Header { return &rr.Hdr }
+func (rr *MR) Header() *RR_Header { return &rr.Hdr }
+func (rr *MX) Header() *RR_Header { return &rr.Hdr }
+func (rr *NAPTR) Header() *RR_Header { return &rr.Hdr }
+func (rr *NID) Header() *RR_Header { return &rr.Hdr }
+func (rr *NIMLOC) Header() *RR_Header { return &rr.Hdr }
+func (rr *NINFO) Header() *RR_Header { return &rr.Hdr }
+func (rr *NS) Header() *RR_Header { return &rr.Hdr }
+func (rr *NSAPPTR) Header() *RR_Header { return &rr.Hdr }
+func (rr *NSEC) Header() *RR_Header { return &rr.Hdr }
+func (rr *NSEC3) Header() *RR_Header { return &rr.Hdr }
+func (rr *NSEC3PARAM) Header() *RR_Header { return &rr.Hdr }
+func (rr *OPENPGPKEY) Header() *RR_Header { return &rr.Hdr }
+func (rr *OPT) Header() *RR_Header { return &rr.Hdr }
+func (rr *PTR) Header() *RR_Header { return &rr.Hdr }
+func (rr *PX) Header() *RR_Header { return &rr.Hdr }
+func (rr *RFC3597) Header() *RR_Header { return &rr.Hdr }
+func (rr *RKEY) Header() *RR_Header { return &rr.Hdr }
+func (rr *RP) Header() *RR_Header { return &rr.Hdr }
+func (rr *RRSIG) Header() *RR_Header { return &rr.Hdr }
+func (rr *RT) Header() *RR_Header { return &rr.Hdr }
+func (rr *SIG) Header() *RR_Header { return &rr.Hdr }
+func (rr *SMIMEA) Header() *RR_Header { return &rr.Hdr }
+func (rr *SOA) Header() *RR_Header { return &rr.Hdr }
+func (rr *SPF) Header() *RR_Header { return &rr.Hdr }
+func (rr *SRV) Header() *RR_Header { return &rr.Hdr }
+func (rr *SSHFP) Header() *RR_Header { return &rr.Hdr }
+func (rr *TA) Header() *RR_Header { return &rr.Hdr }
+func (rr *TALINK) Header() *RR_Header { return &rr.Hdr }
+func (rr *TKEY) Header() *RR_Header { return &rr.Hdr }
+func (rr *TLSA) Header() *RR_Header { return &rr.Hdr }
+func (rr *TSIG) Header() *RR_Header { return &rr.Hdr }
+func (rr *TXT) Header() *RR_Header { return &rr.Hdr }
+func (rr *UID) Header() *RR_Header { return &rr.Hdr }
+func (rr *UINFO) Header() *RR_Header { return &rr.Hdr }
+func (rr *URI) Header() *RR_Header { return &rr.Hdr }
+func (rr *X25) Header() *RR_Header { return &rr.Hdr }
+
+// len() functions
+func (rr *A) len() int {
+ l := rr.Hdr.len()
+ l += net.IPv4len // A
+ return l
+}
+func (rr *AAAA) len() int {
+ l := rr.Hdr.len()
+ l += net.IPv6len // AAAA
+ return l
+}
+func (rr *AFSDB) len() int {
+ l := rr.Hdr.len()
+ l += 2 // Subtype
+ l += len(rr.Hostname) + 1
+ return l
+}
+func (rr *ANY) len() int {
+ l := rr.Hdr.len()
+ return l
+}
+func (rr *AVC) len() int {
+ l := rr.Hdr.len()
+ for _, x := range rr.Txt {
+ l += len(x) + 1
+ }
+ return l
+}
+func (rr *CAA) len() int {
+ l := rr.Hdr.len()
+ l++ // Flag
+ l += len(rr.Tag) + 1
+ l += len(rr.Value)
+ return l
+}
+func (rr *CERT) len() int {
+ l := rr.Hdr.len()
+ l += 2 // Type
+ l += 2 // KeyTag
+ l++ // Algorithm
+ l += base64.StdEncoding.DecodedLen(len(rr.Certificate))
+ return l
+}
+func (rr *CNAME) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Target) + 1
+ return l
+}
+func (rr *DHCID) len() int {
+ l := rr.Hdr.len()
+ l += base64.StdEncoding.DecodedLen(len(rr.Digest))
+ return l
+}
+func (rr *DNAME) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Target) + 1
+ return l
+}
+func (rr *DNSKEY) len() int {
+ l := rr.Hdr.len()
+ l += 2 // Flags
+ l++ // Protocol
+ l++ // Algorithm
+ l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
+ return l
+}
+func (rr *DS) len() int {
+ l := rr.Hdr.len()
+ l += 2 // KeyTag
+ l++ // Algorithm
+ l++ // DigestType
+ l += len(rr.Digest)/2 + 1
+ return l
+}
+func (rr *EID) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Endpoint)/2 + 1
+ return l
+}
+func (rr *EUI48) len() int {
+ l := rr.Hdr.len()
+ l += 6 // Address
+ return l
+}
+func (rr *EUI64) len() int {
+ l := rr.Hdr.len()
+ l += 8 // Address
+ return l
+}
+func (rr *GID) len() int {
+ l := rr.Hdr.len()
+ l += 4 // Gid
+ return l
+}
+func (rr *GPOS) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Longitude) + 1
+ l += len(rr.Latitude) + 1
+ l += len(rr.Altitude) + 1
+ return l
+}
+func (rr *HINFO) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Cpu) + 1
+ l += len(rr.Os) + 1
+ return l
+}
+func (rr *HIP) len() int {
+ l := rr.Hdr.len()
+ l++ // HitLength
+ l++ // PublicKeyAlgorithm
+ l += 2 // PublicKeyLength
+ l += len(rr.Hit)/2 + 1
+ l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
+ for _, x := range rr.RendezvousServers {
+ l += len(x) + 1
+ }
+ return l
+}
+func (rr *KX) len() int {
+ l := rr.Hdr.len()
+ l += 2 // Preference
+ l += len(rr.Exchanger) + 1
+ return l
+}
+func (rr *L32) len() int {
+ l := rr.Hdr.len()
+ l += 2 // Preference
+ l += net.IPv4len // Locator32
+ return l
+}
+func (rr *L64) len() int {
+ l := rr.Hdr.len()
+ l += 2 // Preference
+ l += 8 // Locator64
+ return l
+}
+func (rr *LOC) len() int {
+ l := rr.Hdr.len()
+ l++ // Version
+ l++ // Size
+ l++ // HorizPre
+ l++ // VertPre
+ l += 4 // Latitude
+ l += 4 // Longitude
+ l += 4 // Altitude
+ return l
+}
+func (rr *LP) len() int {
+ l := rr.Hdr.len()
+ l += 2 // Preference
+ l += len(rr.Fqdn) + 1
+ return l
+}
+func (rr *MB) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Mb) + 1
+ return l
+}
+func (rr *MD) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Md) + 1
+ return l
+}
+func (rr *MF) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Mf) + 1
+ return l
+}
+func (rr *MG) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Mg) + 1
+ return l
+}
+func (rr *MINFO) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Rmail) + 1
+ l += len(rr.Email) + 1
+ return l
+}
+func (rr *MR) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Mr) + 1
+ return l
+}
+func (rr *MX) len() int {
+ l := rr.Hdr.len()
+ l += 2 // Preference
+ l += len(rr.Mx) + 1
+ return l
+}
+func (rr *NAPTR) len() int {
+ l := rr.Hdr.len()
+ l += 2 // Order
+ l += 2 // Preference
+ l += len(rr.Flags) + 1
+ l += len(rr.Service) + 1
+ l += len(rr.Regexp) + 1
+ l += len(rr.Replacement) + 1
+ return l
+}
+func (rr *NID) len() int {
+ l := rr.Hdr.len()
+ l += 2 // Preference
+ l += 8 // NodeID
+ return l
+}
+func (rr *NIMLOC) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Locator)/2 + 1
+ return l
+}
+func (rr *NINFO) len() int {
+ l := rr.Hdr.len()
+ for _, x := range rr.ZSData {
+ l += len(x) + 1
+ }
+ return l
+}
+func (rr *NS) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Ns) + 1
+ return l
+}
+func (rr *NSAPPTR) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Ptr) + 1
+ return l
+}
+func (rr *NSEC3PARAM) len() int {
+ l := rr.Hdr.len()
+ l++ // Hash
+ l++ // Flags
+ l += 2 // Iterations
+ l++ // SaltLength
+ l += len(rr.Salt)/2 + 1
+ return l
+}
+func (rr *OPENPGPKEY) len() int {
+ l := rr.Hdr.len()
+ l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
+ return l
+}
+func (rr *PTR) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Ptr) + 1
+ return l
+}
+func (rr *PX) len() int {
+ l := rr.Hdr.len()
+ l += 2 // Preference
+ l += len(rr.Map822) + 1
+ l += len(rr.Mapx400) + 1
+ return l
+}
+func (rr *RFC3597) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Rdata)/2 + 1
+ return l
+}
+func (rr *RKEY) len() int {
+ l := rr.Hdr.len()
+ l += 2 // Flags
+ l++ // Protocol
+ l++ // Algorithm
+ l += base64.StdEncoding.DecodedLen(len(rr.PublicKey))
+ return l
+}
+func (rr *RP) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Mbox) + 1
+ l += len(rr.Txt) + 1
+ return l
+}
+func (rr *RRSIG) len() int {
+ l := rr.Hdr.len()
+ l += 2 // TypeCovered
+ l++ // Algorithm
+ l++ // Labels
+ l += 4 // OrigTtl
+ l += 4 // Expiration
+ l += 4 // Inception
+ l += 2 // KeyTag
+ l += len(rr.SignerName) + 1
+ l += base64.StdEncoding.DecodedLen(len(rr.Signature))
+ return l
+}
+func (rr *RT) len() int {
+ l := rr.Hdr.len()
+ l += 2 // Preference
+ l += len(rr.Host) + 1
+ return l
+}
+func (rr *SMIMEA) len() int {
+ l := rr.Hdr.len()
+ l++ // Usage
+ l++ // Selector
+ l++ // MatchingType
+ l += len(rr.Certificate)/2 + 1
+ return l
+}
+func (rr *SOA) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Ns) + 1
+ l += len(rr.Mbox) + 1
+ l += 4 // Serial
+ l += 4 // Refresh
+ l += 4 // Retry
+ l += 4 // Expire
+ l += 4 // Minttl
+ return l
+}
+func (rr *SPF) len() int {
+ l := rr.Hdr.len()
+ for _, x := range rr.Txt {
+ l += len(x) + 1
+ }
+ return l
+}
+func (rr *SRV) len() int {
+ l := rr.Hdr.len()
+ l += 2 // Priority
+ l += 2 // Weight
+ l += 2 // Port
+ l += len(rr.Target) + 1
+ return l
+}
+func (rr *SSHFP) len() int {
+ l := rr.Hdr.len()
+ l++ // Algorithm
+ l++ // Type
+ l += len(rr.FingerPrint)/2 + 1
+ return l
+}
+func (rr *TA) len() int {
+ l := rr.Hdr.len()
+ l += 2 // KeyTag
+ l++ // Algorithm
+ l++ // DigestType
+ l += len(rr.Digest)/2 + 1
+ return l
+}
+func (rr *TALINK) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.PreviousName) + 1
+ l += len(rr.NextName) + 1
+ return l
+}
+func (rr *TKEY) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Algorithm) + 1
+ l += 4 // Inception
+ l += 4 // Expiration
+ l += 2 // Mode
+ l += 2 // Error
+ l += 2 // KeySize
+ l += len(rr.Key) + 1
+ l += 2 // OtherLen
+ l += len(rr.OtherData) + 1
+ return l
+}
+func (rr *TLSA) len() int {
+ l := rr.Hdr.len()
+ l++ // Usage
+ l++ // Selector
+ l++ // MatchingType
+ l += len(rr.Certificate)/2 + 1
+ return l
+}
+func (rr *TSIG) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Algorithm) + 1
+ l += 6 // TimeSigned
+ l += 2 // Fudge
+ l += 2 // MACSize
+ l += len(rr.MAC)/2 + 1
+ l += 2 // OrigId
+ l += 2 // Error
+ l += 2 // OtherLen
+ l += len(rr.OtherData)/2 + 1
+ return l
+}
+func (rr *TXT) len() int {
+ l := rr.Hdr.len()
+ for _, x := range rr.Txt {
+ l += len(x) + 1
+ }
+ return l
+}
+func (rr *UID) len() int {
+ l := rr.Hdr.len()
+ l += 4 // Uid
+ return l
+}
+func (rr *UINFO) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.Uinfo) + 1
+ return l
+}
+func (rr *URI) len() int {
+ l := rr.Hdr.len()
+ l += 2 // Priority
+ l += 2 // Weight
+ l += len(rr.Target)
+ return l
+}
+func (rr *X25) len() int {
+ l := rr.Hdr.len()
+ l += len(rr.PSDNAddress) + 1
+ return l
+}
+
+// copy() functions
+func (rr *A) copy() RR {
+ return &A{*rr.Hdr.copyHeader(), copyIP(rr.A)}
+}
+func (rr *AAAA) copy() RR {
+ return &AAAA{*rr.Hdr.copyHeader(), copyIP(rr.AAAA)}
+}
+func (rr *AFSDB) copy() RR {
+ return &AFSDB{*rr.Hdr.copyHeader(), rr.Subtype, rr.Hostname}
+}
+func (rr *ANY) copy() RR {
+ return &ANY{*rr.Hdr.copyHeader()}
+}
+func (rr *AVC) copy() RR {
+ Txt := make([]string, len(rr.Txt))
+ copy(Txt, rr.Txt)
+ return &AVC{*rr.Hdr.copyHeader(), Txt}
+}
+func (rr *CAA) copy() RR {
+ return &CAA{*rr.Hdr.copyHeader(), rr.Flag, rr.Tag, rr.Value}
+}
+func (rr *CERT) copy() RR {
+ return &CERT{*rr.Hdr.copyHeader(), rr.Type, rr.KeyTag, rr.Algorithm, rr.Certificate}
+}
+func (rr *CNAME) copy() RR {
+ return &CNAME{*rr.Hdr.copyHeader(), rr.Target}
+}
+func (rr *DHCID) copy() RR {
+ return &DHCID{*rr.Hdr.copyHeader(), rr.Digest}
+}
+func (rr *DNAME) copy() RR {
+ return &DNAME{*rr.Hdr.copyHeader(), rr.Target}
+}
+func (rr *DNSKEY) copy() RR {
+ return &DNSKEY{*rr.Hdr.copyHeader(), rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey}
+}
+func (rr *DS) copy() RR {
+ return &DS{*rr.Hdr.copyHeader(), rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
+}
+func (rr *EID) copy() RR {
+ return &EID{*rr.Hdr.copyHeader(), rr.Endpoint}
+}
+func (rr *EUI48) copy() RR {
+ return &EUI48{*rr.Hdr.copyHeader(), rr.Address}
+}
+func (rr *EUI64) copy() RR {
+ return &EUI64{*rr.Hdr.copyHeader(), rr.Address}
+}
+func (rr *GID) copy() RR {
+ return &GID{*rr.Hdr.copyHeader(), rr.Gid}
+}
+func (rr *GPOS) copy() RR {
+ return &GPOS{*rr.Hdr.copyHeader(), rr.Longitude, rr.Latitude, rr.Altitude}
+}
+func (rr *HINFO) copy() RR {
+ return &HINFO{*rr.Hdr.copyHeader(), rr.Cpu, rr.Os}
+}
+func (rr *HIP) copy() RR {
+ RendezvousServers := make([]string, len(rr.RendezvousServers))
+ copy(RendezvousServers, rr.RendezvousServers)
+ return &HIP{*rr.Hdr.copyHeader(), rr.HitLength, rr.PublicKeyAlgorithm, rr.PublicKeyLength, rr.Hit, rr.PublicKey, RendezvousServers}
+}
+func (rr *KX) copy() RR {
+ return &KX{*rr.Hdr.copyHeader(), rr.Preference, rr.Exchanger}
+}
+func (rr *L32) copy() RR {
+ return &L32{*rr.Hdr.copyHeader(), rr.Preference, copyIP(rr.Locator32)}
+}
+func (rr *L64) copy() RR {
+ return &L64{*rr.Hdr.copyHeader(), rr.Preference, rr.Locator64}
+}
+func (rr *LOC) copy() RR {
+ return &LOC{*rr.Hdr.copyHeader(), rr.Version, rr.Size, rr.HorizPre, rr.VertPre, rr.Latitude, rr.Longitude, rr.Altitude}
+}
+func (rr *LP) copy() RR {
+ return &LP{*rr.Hdr.copyHeader(), rr.Preference, rr.Fqdn}
+}
+func (rr *MB) copy() RR {
+ return &MB{*rr.Hdr.copyHeader(), rr.Mb}
+}
+func (rr *MD) copy() RR {
+ return &MD{*rr.Hdr.copyHeader(), rr.Md}
+}
+func (rr *MF) copy() RR {
+ return &MF{*rr.Hdr.copyHeader(), rr.Mf}
+}
+func (rr *MG) copy() RR {
+ return &MG{*rr.Hdr.copyHeader(), rr.Mg}
+}
+func (rr *MINFO) copy() RR {
+ return &MINFO{*rr.Hdr.copyHeader(), rr.Rmail, rr.Email}
+}
+func (rr *MR) copy() RR {
+ return &MR{*rr.Hdr.copyHeader(), rr.Mr}
+}
+func (rr *MX) copy() RR {
+ return &MX{*rr.Hdr.copyHeader(), rr.Preference, rr.Mx}
+}
+func (rr *NAPTR) copy() RR {
+ return &NAPTR{*rr.Hdr.copyHeader(), rr.Order, rr.Preference, rr.Flags, rr.Service, rr.Regexp, rr.Replacement}
+}
+func (rr *NID) copy() RR {
+ return &NID{*rr.Hdr.copyHeader(), rr.Preference, rr.NodeID}
+}
+func (rr *NIMLOC) copy() RR {
+ return &NIMLOC{*rr.Hdr.copyHeader(), rr.Locator}
+}
+func (rr *NINFO) copy() RR {
+ ZSData := make([]string, len(rr.ZSData))
+ copy(ZSData, rr.ZSData)
+ return &NINFO{*rr.Hdr.copyHeader(), ZSData}
+}
+func (rr *NS) copy() RR {
+ return &NS{*rr.Hdr.copyHeader(), rr.Ns}
+}
+func (rr *NSAPPTR) copy() RR {
+ return &NSAPPTR{*rr.Hdr.copyHeader(), rr.Ptr}
+}
+func (rr *NSEC) copy() RR {
+ TypeBitMap := make([]uint16, len(rr.TypeBitMap))
+ copy(TypeBitMap, rr.TypeBitMap)
+ return &NSEC{*rr.Hdr.copyHeader(), rr.NextDomain, TypeBitMap}
+}
+func (rr *NSEC3) copy() RR {
+ TypeBitMap := make([]uint16, len(rr.TypeBitMap))
+ copy(TypeBitMap, rr.TypeBitMap)
+ return &NSEC3{*rr.Hdr.copyHeader(), rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt, rr.HashLength, rr.NextDomain, TypeBitMap}
+}
+func (rr *NSEC3PARAM) copy() RR {
+ return &NSEC3PARAM{*rr.Hdr.copyHeader(), rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt}
+}
+func (rr *OPENPGPKEY) copy() RR {
+ return &OPENPGPKEY{*rr.Hdr.copyHeader(), rr.PublicKey}
+}
+func (rr *OPT) copy() RR {
+ Option := make([]EDNS0, len(rr.Option))
+ copy(Option, rr.Option)
+ return &OPT{*rr.Hdr.copyHeader(), Option}
+}
+func (rr *PTR) copy() RR {
+ return &PTR{*rr.Hdr.copyHeader(), rr.Ptr}
+}
+func (rr *PX) copy() RR {
+ return &PX{*rr.Hdr.copyHeader(), rr.Preference, rr.Map822, rr.Mapx400}
+}
+func (rr *RFC3597) copy() RR {
+ return &RFC3597{*rr.Hdr.copyHeader(), rr.Rdata}
+}
+func (rr *RKEY) copy() RR {
+ return &RKEY{*rr.Hdr.copyHeader(), rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey}
+}
+func (rr *RP) copy() RR {
+ return &RP{*rr.Hdr.copyHeader(), rr.Mbox, rr.Txt}
+}
+func (rr *RRSIG) copy() RR {
+ return &RRSIG{*rr.Hdr.copyHeader(), rr.TypeCovered, rr.Algorithm, rr.Labels, rr.OrigTtl, rr.Expiration, rr.Inception, rr.KeyTag, rr.SignerName, rr.Signature}
+}
+func (rr *RT) copy() RR {
+ return &RT{*rr.Hdr.copyHeader(), rr.Preference, rr.Host}
+}
+func (rr *SMIMEA) copy() RR {
+ return &SMIMEA{*rr.Hdr.copyHeader(), rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate}
+}
+func (rr *SOA) copy() RR {
+ return &SOA{*rr.Hdr.copyHeader(), rr.Ns, rr.Mbox, rr.Serial, rr.Refresh, rr.Retry, rr.Expire, rr.Minttl}
+}
+func (rr *SPF) copy() RR {
+ Txt := make([]string, len(rr.Txt))
+ copy(Txt, rr.Txt)
+ return &SPF{*rr.Hdr.copyHeader(), Txt}
+}
+func (rr *SRV) copy() RR {
+ return &SRV{*rr.Hdr.copyHeader(), rr.Priority, rr.Weight, rr.Port, rr.Target}
+}
+func (rr *SSHFP) copy() RR {
+ return &SSHFP{*rr.Hdr.copyHeader(), rr.Algorithm, rr.Type, rr.FingerPrint}
+}
+func (rr *TA) copy() RR {
+ return &TA{*rr.Hdr.copyHeader(), rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
+}
+func (rr *TALINK) copy() RR {
+ return &TALINK{*rr.Hdr.copyHeader(), rr.PreviousName, rr.NextName}
+}
+func (rr *TKEY) copy() RR {
+ return &TKEY{*rr.Hdr.copyHeader(), rr.Algorithm, rr.Inception, rr.Expiration, rr.Mode, rr.Error, rr.KeySize, rr.Key, rr.OtherLen, rr.OtherData}
+}
+func (rr *TLSA) copy() RR {
+ return &TLSA{*rr.Hdr.copyHeader(), rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate}
+}
+func (rr *TSIG) copy() RR {
+ return &TSIG{*rr.Hdr.copyHeader(), rr.Algorithm, rr.TimeSigned, rr.Fudge, rr.MACSize, rr.MAC, rr.OrigId, rr.Error, rr.OtherLen, rr.OtherData}
+}
+func (rr *TXT) copy() RR {
+ Txt := make([]string, len(rr.Txt))
+ copy(Txt, rr.Txt)
+ return &TXT{*rr.Hdr.copyHeader(), Txt}
+}
+func (rr *UID) copy() RR {
+ return &UID{*rr.Hdr.copyHeader(), rr.Uid}
+}
+func (rr *UINFO) copy() RR {
+ return &UINFO{*rr.Hdr.copyHeader(), rr.Uinfo}
+}
+func (rr *URI) copy() RR {
+ return &URI{*rr.Hdr.copyHeader(), rr.Priority, rr.Weight, rr.Target}
+}
+func (rr *X25) copy() RR {
+ return &X25{*rr.Hdr.copyHeader(), rr.PSDNAddress}
+}
--- /dev/null
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
--- /dev/null
+# Go tracing and monitoring (Prometheus) for `net.Conn`
+
+[](https://travis-ci.org/mwitkow/go-conntrack)
+[](http://goreportcard.com/report/mwitkow/go-conntrack)
+[](https://godoc.org/github.com/mwitkow/go-conntrack)
+[](LICENSE)
+
+[Prometheus](https://prometheus.io/) monitoring and [`x/net/trace`](https://godoc.org/golang.org/x/net/trace#EventLog) tracing wrappers `net.Conn`, both inbound (`net.Listener`) and outbound (`net.Dialer`).
+
+## Why?
+
+Go standard library does a great job of doing "the right" things with your connections: `http.Transport` pools outbound ones, and `http.Server` sets good *Keep Alive* defaults.
+However, it is still easy to get it wrong, see the excellent [*The complete guide to Go net/http timeouts*](https://blog.cloudflare.com/the-complete-guide-to-golang-net-http-timeouts/).
+
+That's why you should be able to monitor (using Prometheus) how many connections your Go frontend servers have inbound, and how big are the connection pools to your backends. You should also be able to inspect your connection without `ssh` and `netstat`.
+
+
+
+## How to use?
+
+All of these examples can be found in [`example/server.go`](example/server.go):
+
+### Conntrack Dialer for HTTP DefaultClient
+
+Most often people use the default `http.DefaultClient` that uses `http.DefaultTransport`. The easiest way to make sure all your outbound connections monitored and trace is:
+
+```go
+http.DefaultTransport.(*http.Transport).DialContext = conntrack.NewDialContextFunc(
+ conntrack.DialWithTracing(),
+ conntrack.DialWithDialer(&net.Dialer{
+ Timeout: 30 * time.Second,
+ KeepAlive: 30 * time.Second,
+ }),
+)
+```
+
+#### Dialer Name
+
+Tracked outbound connections are organised by *dialer name* (with `default` being default). The *dialer name* is used for monitoring (`dialer_name` label) and tracing (`net.ClientConn.<dialer_name>` family).
+
+You can pass `conntrack.WithDialerName()` to `NewDialContextFunc` to set the name for the dialer. Moreover, you can set the *dialer name* per invocation of the dialer, by passing it in the `Context`. For example using the [`ctxhttp`](https://godoc.org/golang.org/x/net/context/ctxhttp) lib:
+
+```go
+callCtx := conntrack.DialNameToContext(parentCtx, "google")
+ctxhttp.Get(callCtx, http.DefaultClient, "https://www.google.com")
+```
+
+### Conntrack Listener for HTTP Server
+
+Tracked inbound connections are organised by *listener name* (with `default` being default). The *listener name* is used for monitoring (`listener_name` label) and tracing (`net.ServerConn.<listener_name>` family). For example, a simple `http.Server` can be instrumented like this:
+
+```go
+listener, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
+listener = conntrack.NewListener(listener,
+ conntrack.TrackWithName("http"),
+ conntrack.TrackWithTracing(),
+ conntrack.TrackWithTcpKeepAlive(5 * time.Minutes))
+httpServer.Serve(listener)
+```
+
+Note, the `TrackWithTcpKeepAlive`. The default `http.ListenAndServe` adds a tcp keep alive wrapper to inbound TCP connections. `conntrack.NewListener` allows you to do that without another layer of wrapping.
+
+#### TLS server example
+
+The standard lobrary `http.ListenAndServerTLS` does a lot to bootstrap TLS connections, including supporting HTTP2 negotiation. Unfortunately, that is hard to do if you want to provide your own `net.Listener`. That's why this repo comes with `connhelpers` package, which takes care of configuring `tls.Config` for that use case. Here's an example of use:
+
+```go
+listener, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
+listener = conntrack.NewListener(listener,
+ conntrack.TrackWithName("https"),
+ conntrack.TrackWithTracing(),
+ conntrack.TrackWithTcpKeepAlive(5 * time.Minutes))
+tlsConfig, err := connhelpers.TlsConfigForServerCerts(*tlsCertFilePath, *tlsKeyFilePath)
+tlsConfig, err = connhelpers.TlsConfigWithHttp2Enabled(tlsConfig)
+tlsListener := tls.NewListener(listener, tlsConfig)
+httpServer.Serve(listener)
+```
+
+# Status
+
+This code is used by Improbable's HTTP frontending and proxying stack for debuging and monitoring of established user connections.
+
+Additional tooling will be added if needed, and contributions are welcome.
+
+#License
+
+`go-conntrack` is released under the Apache 2.0 license. See the [LICENSE](LICENSE) file for details.
+
--- /dev/null
+// Copyright 2016 Michal Witkowski. All Rights Reserved.
+// See LICENSE for licensing terms.
+
+package conntrack
+
+import (
+ "context"
+ "net"
+ "os"
+ "syscall"
+
+ prom "github.com/prometheus/client_golang/prometheus"
+)
+
+type failureReason string
+
+const (
+ failedResolution = "resolution"
+ failedConnRefused = "refused"
+ failedTimeout = "timeout"
+ failedUnknown = "unknown"
+)
+
+var (
+ dialerAttemptedTotal = prom.NewCounterVec(
+ prom.CounterOpts{
+ Namespace: "net",
+ Subsystem: "conntrack",
+ Name: "dialer_conn_attempted_total",
+ Help: "Total number of connections attempted by the given dialer a given name.",
+ }, []string{"dialer_name"})
+
+ dialerConnEstablishedTotal = prom.NewCounterVec(
+ prom.CounterOpts{
+ Namespace: "net",
+ Subsystem: "conntrack",
+ Name: "dialer_conn_established_total",
+ Help: "Total number of connections successfully established by the given dialer a given name.",
+ }, []string{"dialer_name"})
+
+ dialerConnFailedTotal = prom.NewCounterVec(
+ prom.CounterOpts{
+ Namespace: "net",
+ Subsystem: "conntrack",
+ Name: "dialer_conn_failed_total",
+ Help: "Total number of connections failed to dial by the dialer a given name.",
+ }, []string{"dialer_name", "reason"})
+
+ dialerConnClosedTotal = prom.NewCounterVec(
+ prom.CounterOpts{
+ Namespace: "net",
+ Subsystem: "conntrack",
+ Name: "dialer_conn_closed_total",
+ Help: "Total number of connections closed which originated from the dialer of a given name.",
+ }, []string{"dialer_name"})
+)
+
+func init() {
+ prom.MustRegister(dialerAttemptedTotal)
+ prom.MustRegister(dialerConnEstablishedTotal)
+ prom.MustRegister(dialerConnFailedTotal)
+ prom.MustRegister(dialerConnClosedTotal)
+}
+
+// preRegisterDialerMetrics pre-populates Prometheus labels for the given dialer name, to avoid Prometheus missing labels issue.
+func PreRegisterDialerMetrics(dialerName string) {
+ dialerAttemptedTotal.WithLabelValues(dialerName)
+ dialerConnEstablishedTotal.WithLabelValues(dialerName)
+ for _, reason := range []failureReason{failedTimeout, failedResolution, failedConnRefused, failedUnknown} {
+ dialerConnFailedTotal.WithLabelValues(dialerName, string(reason))
+ }
+ dialerConnClosedTotal.WithLabelValues(dialerName)
+}
+
+func reportDialerConnAttempt(dialerName string) {
+ dialerAttemptedTotal.WithLabelValues(dialerName).Inc()
+}
+
+func reportDialerConnEstablished(dialerName string) {
+ dialerConnEstablishedTotal.WithLabelValues(dialerName).Inc()
+}
+
+func reportDialerConnClosed(dialerName string) {
+ dialerConnClosedTotal.WithLabelValues(dialerName).Inc()
+}
+
+func reportDialerConnFailed(dialerName string, err error) {
+ if netErr, ok := err.(*net.OpError); ok {
+ switch nestErr := netErr.Err.(type) {
+ case *net.DNSError:
+ dialerConnFailedTotal.WithLabelValues(dialerName, string(failedResolution)).Inc()
+ return
+ case *os.SyscallError:
+ if nestErr.Err == syscall.ECONNREFUSED {
+ dialerConnFailedTotal.WithLabelValues(dialerName, string(failedConnRefused)).Inc()
+ }
+ dialerConnFailedTotal.WithLabelValues(dialerName, string(failedUnknown)).Inc()
+ return
+ }
+ if netErr.Timeout() {
+ dialerConnFailedTotal.WithLabelValues(dialerName, string(failedTimeout)).Inc()
+ }
+ } else if err == context.Canceled || err == context.DeadlineExceeded {
+ dialerConnFailedTotal.WithLabelValues(dialerName, string(failedTimeout)).Inc()
+ return
+ }
+ dialerConnFailedTotal.WithLabelValues(dialerName, string(failedUnknown)).Inc()
+}
--- /dev/null
+// Copyright 2016 Michal Witkowski. All Rights Reserved.
+// See LICENSE for licensing terms.
+
+package conntrack
+
+import (
+ "context"
+ "fmt"
+ "net"
+ "sync"
+
+ "golang.org/x/net/trace"
+)
+
+var (
+ dialerNameKey = "conntrackDialerKey"
+)
+
+type dialerOpts struct {
+ name string
+ monitoring bool
+ tracing bool
+ parentDialContextFunc dialerContextFunc
+}
+
+type dialerOpt func(*dialerOpts)
+
+type dialerContextFunc func(context.Context, string, string) (net.Conn, error)
+
+// DialWithName sets the name of the dialer for tracking and monitoring.
+// This is the name for the dialer (default is `default`), but for `NewDialContextFunc` can be overwritten from the
+// Context using `DialNameToContext`.
+func DialWithName(name string) dialerOpt {
+ return func(opts *dialerOpts) {
+ opts.name = name
+ }
+}
+
+// DialWithoutMonitoring turns *off* Prometheus monitoring for this dialer.
+func DialWithoutMonitoring() dialerOpt {
+ return func(opts *dialerOpts) {
+ opts.monitoring = false
+ }
+}
+
+// DialWithTracing turns *on* the /debug/events tracing of the dial calls.
+func DialWithTracing() dialerOpt {
+ return func(opts *dialerOpts) {
+ opts.tracing = true
+ }
+}
+
+// DialWithDialer allows you to override the `net.Dialer` instance used to actually conduct the dials.
+func DialWithDialer(parentDialer *net.Dialer) dialerOpt {
+ return DialWithDialContextFunc(parentDialer.DialContext)
+}
+
+// DialWithDialContextFunc allows you to override func gets used for the actual dialing. The default is `net.Dialer.DialContext`.
+func DialWithDialContextFunc(parentDialerFunc dialerContextFunc) dialerOpt {
+ return func(opts *dialerOpts) {
+ opts.parentDialContextFunc = parentDialerFunc
+ }
+}
+
+// DialNameFromContext returns the name of the dialer from the context of the DialContext func, if any.
+func DialNameFromContext(ctx context.Context) string {
+ val, ok := ctx.Value(dialerNameKey).(string)
+ if !ok {
+ return ""
+ }
+ return val
+}
+
+// DialNameToContext returns a context that will contain a dialer name override.
+func DialNameToContext(ctx context.Context, dialerName string) context.Context {
+ return context.WithValue(ctx, dialerNameKey, dialerName)
+}
+
+// NewDialContextFunc returns a `DialContext` function that tracks outbound connections.
+// The signature is compatible with `http.Tranport.DialContext` and is meant to be used there.
+func NewDialContextFunc(optFuncs ...dialerOpt) func(context.Context, string, string) (net.Conn, error) {
+ opts := &dialerOpts{name: defaultName, monitoring: true, parentDialContextFunc: (&net.Dialer{}).DialContext}
+ for _, f := range optFuncs {
+ f(opts)
+ }
+ if opts.monitoring {
+ PreRegisterDialerMetrics(opts.name)
+ }
+ return func(ctx context.Context, network string, addr string) (net.Conn, error) {
+ name := opts.name
+ if ctxName := DialNameFromContext(ctx); ctxName != "" {
+ name = ctxName
+ }
+ return dialClientConnTracker(ctx, network, addr, name, opts)
+ }
+}
+
+// NewDialFunc returns a `Dial` function that tracks outbound connections.
+// The signature is compatible with `http.Tranport.Dial` and is meant to be used there for Go < 1.7.
+func NewDialFunc(optFuncs ...dialerOpt) func(string, string) (net.Conn, error) {
+ dialContextFunc := NewDialContextFunc(optFuncs...)
+ return func(network string, addr string) (net.Conn, error) {
+ return dialContextFunc(context.TODO(), network, addr)
+ }
+}
+
+type clientConnTracker struct {
+ net.Conn
+ opts *dialerOpts
+ dialerName string
+ event trace.EventLog
+ mu sync.Mutex
+}
+
+func dialClientConnTracker(ctx context.Context, network string, addr string, dialerName string, opts *dialerOpts) (net.Conn, error) {
+ var event trace.EventLog
+ if opts.tracing {
+ event = trace.NewEventLog(fmt.Sprintf("net.ClientConn.%s", dialerName), fmt.Sprintf("%v", addr))
+ }
+ if opts.monitoring {
+ reportDialerConnAttempt(dialerName)
+ }
+ conn, err := opts.parentDialContextFunc(ctx, network, addr)
+ if err != nil {
+ if event != nil {
+ event.Errorf("failed dialing: %v", err)
+ event.Finish()
+ }
+ if opts.monitoring {
+ reportDialerConnFailed(dialerName, err)
+ }
+ return nil, err
+ }
+ if event != nil {
+ event.Printf("established: %s -> %s", conn.LocalAddr(), conn.RemoteAddr())
+ }
+ if opts.monitoring {
+ reportDialerConnEstablished(dialerName)
+ }
+ tracker := &clientConnTracker{
+ Conn: conn,
+ opts: opts,
+ dialerName: dialerName,
+ event: event,
+ }
+ return tracker, nil
+}
+
+func (ct *clientConnTracker) Close() error {
+ err := ct.Conn.Close()
+ ct.mu.Lock()
+ if ct.event != nil {
+ if err != nil {
+ ct.event.Errorf("failed closing: %v", err)
+ } else {
+ ct.event.Printf("closing")
+ }
+ ct.event.Finish()
+ ct.event = nil
+ }
+ ct.mu.Unlock()
+ if ct.opts.monitoring {
+ reportDialerConnClosed(ct.dialerName)
+ }
+ return err
+}
--- /dev/null
+// Copyright 2016 Michal Witkowski. All Rights Reserved.
+// See LICENSE for licensing terms.
+
+package conntrack
+
+import prom "github.com/prometheus/client_golang/prometheus"
+
+var (
+ listenerAcceptedTotal = prom.NewCounterVec(
+ prom.CounterOpts{
+ Namespace: "net",
+ Subsystem: "conntrack",
+ Name: "listener_conn_accepted_total",
+ Help: "Total number of connections opened to the listener of a given name.",
+ }, []string{"listener_name"})
+
+ listenerClosedTotal = prom.NewCounterVec(
+ prom.CounterOpts{
+ Namespace: "net",
+ Subsystem: "conntrack",
+ Name: "listener_conn_closed_total",
+ Help: "Total number of connections closed that were made to the listener of a given name.",
+ }, []string{"listener_name"})
+)
+
+func init() {
+ prom.MustRegister(listenerAcceptedTotal)
+ prom.MustRegister(listenerClosedTotal)
+}
+
+// preRegisterListener pre-populates Prometheus labels for the given listener name, to avoid Prometheus missing labels issue.
+func preRegisterListenerMetrics(listenerName string) {
+ listenerAcceptedTotal.WithLabelValues(listenerName)
+ listenerClosedTotal.WithLabelValues(listenerName)
+}
+
+func reportListenerConnAccepted(listenerName string) {
+ listenerAcceptedTotal.WithLabelValues(listenerName).Inc()
+}
+
+func reportListenerConnClosed(listenerName string) {
+ listenerClosedTotal.WithLabelValues(listenerName).Inc()
+}
--- /dev/null
+// Copyright 2016 Michal Witkowski. All Rights Reserved.
+// See LICENSE for licensing terms.
+
+package conntrack
+
+import (
+ "fmt"
+ "net"
+
+ "sync"
+
+ "golang.org/x/net/trace"
+ "time"
+)
+
+const (
+ defaultName = "default"
+)
+
+type listenerOpts struct {
+ name string
+ monitoring bool
+ tracing bool
+ tcpKeepAlive time.Duration
+}
+
+type listenerOpt func(*listenerOpts)
+
+// TrackWithName sets the name of the Listener for use in tracking and monitoring.
+func TrackWithName(name string) listenerOpt {
+ return func(opts *listenerOpts) {
+ opts.name = name
+ }
+}
+
+// TrackWithoutMonitoring turns *off* Prometheus monitoring for this listener.
+func TrackWithoutMonitoring() listenerOpt {
+ return func(opts *listenerOpts) {
+ opts.monitoring = false
+ }
+}
+
+// TrackWithTracing turns *on* the /debug/events tracing of the live listener connections.
+func TrackWithTracing() listenerOpt {
+ return func(opts *listenerOpts) {
+ opts.tracing = true
+ }
+}
+
+// TrackWithTcpKeepAlive makes sure that any `net.TCPConn` that get accepted have a keep-alive.
+// This is useful for HTTP servers in order for, for example laptops, to not use up resources on the
+// server while they don't utilise their connection.
+// A value of 0 disables it.
+func TrackWithTcpKeepAlive(keepalive time.Duration) listenerOpt {
+ return func(opts *listenerOpts) {
+ opts.tcpKeepAlive = keepalive
+ }
+}
+
+type connTrackListener struct {
+ net.Listener
+ opts *listenerOpts
+}
+
+// NewListener returns the given listener wrapped in connection tracking listener.
+func NewListener(inner net.Listener, optFuncs ...listenerOpt) net.Listener {
+ opts := &listenerOpts{
+ name: defaultName,
+ monitoring: true,
+ tracing: false,
+ }
+ for _, f := range optFuncs {
+ f(opts)
+ }
+ if opts.monitoring {
+ preRegisterListenerMetrics(opts.name)
+ }
+ return &connTrackListener{
+ Listener: inner,
+ opts: opts,
+ }
+}
+
+func (ct *connTrackListener) Accept() (net.Conn, error) {
+ // TODO(mwitkow): Add monitoring of failed accept.
+ conn, err := ct.Listener.Accept()
+ if err != nil {
+ return nil, err
+ }
+ if tcpConn, ok := conn.(*net.TCPConn); ok && ct.opts.tcpKeepAlive > 0 {
+ tcpConn.SetKeepAlive(true)
+ tcpConn.SetKeepAlivePeriod(ct.opts.tcpKeepAlive)
+ }
+ return newServerConnTracker(conn, ct.opts), nil
+}
+
+type serverConnTracker struct {
+ net.Conn
+ opts *listenerOpts
+ event trace.EventLog
+ mu sync.Mutex
+}
+
+func newServerConnTracker(inner net.Conn, opts *listenerOpts) net.Conn {
+
+ tracker := &serverConnTracker{
+ Conn: inner,
+ opts: opts,
+ }
+ if opts.tracing {
+ tracker.event = trace.NewEventLog(fmt.Sprintf("net.ServerConn.%s", opts.name), fmt.Sprintf("%v", inner.RemoteAddr()))
+ tracker.event.Printf("accepted: %v -> %v", inner.RemoteAddr(), inner.LocalAddr())
+ }
+ if opts.monitoring {
+ reportListenerConnAccepted(opts.name)
+ }
+ return tracker
+}
+
+func (ct *serverConnTracker) Close() error {
+ err := ct.Conn.Close()
+ ct.mu.Lock()
+ if ct.event != nil {
+ if err != nil {
+ ct.event.Errorf("failed closing: %v", err)
+ } else {
+ ct.event.Printf("closing")
+ }
+ ct.event.Finish()
+ ct.event = nil
+ }
+ ct.mu.Unlock()
+ if ct.opts.monitoring {
+ reportListenerConnClosed(ct.opts.name)
+ }
+ return err
+}
--- /dev/null
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
--- /dev/null
+// Package group implements an actor-runner with deterministic teardown. It is
+// somewhat similar to package errgroup, except it does not require actor
+// goroutines to understand context semantics. This makes it suitable for use
+// in more circumstances; for example, goroutines which are handling
+// connections from net.Listeners, or scanning input from a closable io.Reader.
+package group
+
+// Group collects actors (functions) and runs them concurrently.
+// When one actor (function) returns, all actors are interrupted.
+// The zero value of a Group is useful.
+type Group struct {
+ actors []actor
+}
+
+// Add an actor (function) to the group. Each actor must be pre-emptable by an
+// interrupt function. That is, if interrupt is invoked, execute should return.
+// Also, it must be safe to call interrupt even after execute has returned.
+//
+// The first actor (function) to return interrupts all running actors.
+// The error is passed to the interrupt functions, and is returned by Run.
+func (g *Group) Add(execute func() error, interrupt func(error)) {
+ g.actors = append(g.actors, actor{execute, interrupt})
+}
+
+// Run all actors (functions) concurrently.
+// When the first actor returns, all others are interrupted.
+// Run only returns when all actors have exited.
+// Run returns the error returned by the first exiting actor.
+func (g *Group) Run() error {
+ if len(g.actors) == 0 {
+ return nil
+ }
+
+ // Run each actor.
+ errors := make(chan error, len(g.actors))
+ for _, a := range g.actors {
+ go func(a actor) {
+ errors <- a.execute()
+ }(a)
+ }
+
+ // Wait for the first actor to stop.
+ err := <-errors
+
+ // Signal all actors to stop.
+ for _, a := range g.actors {
+ a.interrupt(err)
+ }
+
+ // Wait for all actors to stop.
+ for i := 1; i < cap(errors); i++ {
+ <-errors
+ }
+
+ // Return the original error.
+ return err
+}
+
+type actor struct {
+ execute func() error
+ interrupt func(error)
+}
--- /dev/null
+- Peter Bourgon (@peterbourgon)
+- Tomás Senart (@tsenart)
--- /dev/null
+## 0.3.0 / 2017-01-03
+
+* Implement ULID.Compare method
+
+## 0.2.0 / 2016-12-13
+
+* Remove year 2262 Timestamp bug. (#1)
+* Gracefully handle invalid encodings when parsing.
+
+## 0.1.0 / 2016-12-06
+
+* First ULID release
--- /dev/null
+# Contributing
+
+We use GitHub to manage reviews of pull requests.
+
+* If you have a trivial fix or improvement, go ahead and create a pull
+ request, addressing (with `@...`) one or more of the maintainers
+ (see [AUTHORS.md](AUTHORS.md)) in the description of the pull request.
+
+* If you plan to do something more involved, first propose your ideas
+ in a Github issue. This will avoid unnecessary work and surely give
+ you and us a good deal of inspiration.
+
+* Relevant coding style guidelines are the [Go Code Review
+ Comments](https://code.google.com/p/go-wiki/wiki/CodeReviewComments)
+ and the _Formatting and style_ section of Peter Bourgon's [Go: Best
+ Practices for Production
+ Environments](http://peter.bourgon.org/go-in-production/#formatting-and-style).
--- /dev/null
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
--- /dev/null
+# Universally Unique Lexicographically Sortable Identifier
+
+
+[](http://travis-ci.org/oklog/ulid)
+[](https://goreportcard.com/report/oklog/ulid)
+[](https://coveralls.io/github/oklog/ulid?branch=master)
+[](https://godoc.org/github.com/oklog/ulid)
+[](https://raw.githubusercontent.com/oklog/ulid/master/LICENSE)
+
+A Go port of [alizain/ulid](https://github.com/alizain/ulid) with binary format implemented.
+
+## Background
+
+A GUID/UUID can be suboptimal for many use-cases because:
+
+- It isn't the most character efficient way of encoding 128 bits
+- UUID v1/v2 is impractical in many environments, as it requires access to a unique, stable MAC address
+- UUID v3/v5 requires a unique seed and produces randomly distributed IDs, which can cause fragmentation in many data structures
+- UUID v4 provides no other information than randomness which can cause fragmentation in many data structures
+
+A ULID however:
+
+- Is compatible with UUID/GUID's
+- 1.21e+24 unique ULIDs per millisecond (1,208,925,819,614,629,174,706,176 to be exact)
+- Lexicographically sortable
+- Canonically encoded as a 26 character string, as opposed to the 36 character UUID
+- Uses Crockford's base32 for better efficiency and readability (5 bits per character)
+- Case insensitive
+- No special characters (URL safe)
+
+## Install
+
+```shell
+go get github.com/oklog/ulid
+```
+
+## Usage
+
+An ULID is constructed with a `time.Time` and an `io.Reader` entropy source.
+This design allows for greater flexibility in choosing your trade-offs.
+
+Please note that `rand.Rand` from the `math` package is *not* safe for concurrent use.
+Instantiate one per long living go-routine or use a `sync.Pool` if you want to avoid the potential contention of a locked `rand.Source` as its been frequently observed in the package level functions.
+
+```go
+func ExampleULID() {
+ t := time.Unix(1000000, 0)
+ entropy := rand.New(rand.NewSource(t.UnixNano()))
+ fmt.Println(ulid.MustNew(ulid.Timestamp(t), entropy))
+ // Output: 0000XSNJG0MQJHBF4QX1EFD6Y3
+}
+
+```
+
+## Specification
+
+Below is the current specification of ULID as implemented in this repository.
+
+### Components
+
+**Timestamp**
+- 48 bits
+- UNIX-time in milliseconds
+- Won't run out of space till the year 10895 AD
+
+**Entropy**
+- 80 bits
+- User defined entropy source.
+
+### Encoding
+
+[Crockford's Base32](http://www.crockford.com/wrmg/base32.html) is used as shown.
+This alphabet excludes the letters I, L, O, and U to avoid confusion and abuse.
+
+```
+0123456789ABCDEFGHJKMNPQRSTVWXYZ
+```
+
+### Binary Layout and Byte Order
+
+The components are encoded as 16 octets. Each component is encoded with the Most Significant Byte first (network byte order).
+
+```
+0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| 32_bit_uint_time_high |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| 16_bit_uint_time_low | 16_bit_uint_random |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| 32_bit_uint_random |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| 32_bit_uint_random |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+```
+
+### String Representation
+
+```
+ 01AN4Z07BY 79KA1307SR9X4MV3
+|----------| |----------------|
+ Timestamp Entropy
+ 10 chars 16 chars
+ 48bits 80bits
+ base32 base32
+```
+
+## Test
+
+```shell
+go test ./...
+```
+
+## Benchmarks
+
+On a Intel Core i7 Ivy Bridge 2.7 GHz, MacOS 10.12.1 and Go 1.8.0beta1
+
+```
+BenchmarkNew/WithCryptoEntropy-8 2000000 771 ns/op 20.73 MB/s 16 B/op 1 allocs/op
+BenchmarkNew/WithEntropy-8 20000000 65.8 ns/op 243.01 MB/s 16 B/op 1 allocs/op
+BenchmarkNew/WithoutEntropy-8 50000000 30.0 ns/op 534.06 MB/s 16 B/op 1 allocs/op
+BenchmarkMustNew/WithCryptoEntropy-8 2000000 781 ns/op 20.48 MB/s 16 B/op 1 allocs/op
+BenchmarkMustNew/WithEntropy-8 20000000 70.0 ns/op 228.51 MB/s 16 B/op 1 allocs/op
+BenchmarkMustNew/WithoutEntropy-8 50000000 34.6 ns/op 462.98 MB/s 16 B/op 1 allocs/op
+BenchmarkParse-8 50000000 30.0 ns/op 866.16 MB/s 0 B/op 0 allocs/op
+BenchmarkMustParse-8 50000000 35.2 ns/op 738.94 MB/s 0 B/op 0 allocs/op
+BenchmarkString-8 20000000 64.9 ns/op 246.40 MB/s 32 B/op 1 allocs/op
+BenchmarkMarshal/Text-8 20000000 55.8 ns/op 286.84 MB/s 32 B/op 1 allocs/op
+BenchmarkMarshal/TextTo-8 100000000 22.4 ns/op 714.91 MB/s 0 B/op 0 allocs/op
+BenchmarkMarshal/Binary-8 300000000 4.02 ns/op 3981.77 MB/s 0 B/op 0 allocs/op
+BenchmarkMarshal/BinaryTo-8 2000000000 1.18 ns/op 13551.75 MB/s 0 B/op 0 allocs/op
+BenchmarkUnmarshal/Text-8 100000000 20.5 ns/op 1265.27 MB/s 0 B/op 0 allocs/op
+BenchmarkUnmarshal/Binary-8 300000000 4.94 ns/op 3240.01 MB/s 0 B/op 0 allocs/op
+BenchmarkNow-8 100000000 15.1 ns/op 528.09 MB/s 0 B/op 0 allocs/op
+BenchmarkTimestamp-8 2000000000 0.29 ns/op 27271.59 MB/s 0 B/op 0 allocs/op
+BenchmarkTime-8 2000000000 0.58 ns/op 13717.80 MB/s 0 B/op 0 allocs/op
+BenchmarkSetTime-8 2000000000 0.89 ns/op 9023.95 MB/s 0 B/op 0 allocs/op
+BenchmarkEntropy-8 200000000 7.62 ns/op 1311.66 MB/s 0 B/op 0 allocs/op
+BenchmarkSetEntropy-8 2000000000 0.88 ns/op 11376.54 MB/s 0 B/op 0 allocs/op
+BenchmarkCompare-8 200000000 7.34 ns/op 4359.23 MB/s 0 B/op 0 allocs/op
+```
+
+## Prior Art
+
+- [alizain/ulid](https://github.com/alizain/ulid)
+- [RobThree/NUlid](https://github.com/RobThree/NUlid)
+- [imdario/go-ulid](https://github.com/imdario/go-ulid)
--- /dev/null
+// Copyright 2016 The Oklog Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ulid
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "time"
+)
+
+/*
+An ULID is a 16 byte Universally Unique Lexicographically Sortable Identifier
+
+ The components are encoded as 16 octets.
+ Each component is encoded with the MSB first (network byte order).
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 32_bit_uint_time_high |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 16_bit_uint_time_low | 16_bit_uint_random |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 32_bit_uint_random |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 32_bit_uint_random |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+type ULID [16]byte
+
+var (
+ // ErrDataSize is returned when parsing or unmarshaling ULIDs with the wrong
+ // data size.
+ ErrDataSize = errors.New("ulid: bad data size when unmarshaling")
+
+ // ErrBufferSize is returned when marshalling ULIDs to a buffer of insufficient
+ // size.
+ ErrBufferSize = errors.New("ulid: bad buffer size when marshaling")
+
+ // ErrBigTime is returned when constructing an ULID with a time that is larger
+ // than MaxTime.
+ ErrBigTime = errors.New("ulid: time too big")
+)
+
+// New returns an ULID with the given Unix milliseconds timestamp and an
+// optional entropy source. Use the Timestamp function to convert
+// a time.Time to Unix milliseconds.
+//
+// ErrBigTime is returned when passing a timestamp bigger than MaxTime.
+// Reading from the entropy source may also return an error.
+func New(ms uint64, entropy io.Reader) (id ULID, err error) {
+ if err = id.SetTime(ms); err != nil {
+ return id, err
+ }
+
+ if entropy != nil {
+ _, err = entropy.Read(id[6:])
+ }
+
+ return id, err
+}
+
+// MustNew is a convenience function equivalent to New that panics on failure
+// instead of returning an error.
+func MustNew(ms uint64, entropy io.Reader) ULID {
+ id, err := New(ms, entropy)
+ if err != nil {
+ panic(err)
+ }
+ return id
+}
+
+// Parse parses an encoded ULID, returning an error in case of failure.
+//
+// ErrDataSize is returned if the len(ulid) is different from an encoded
+// ULID's length. Invalid encodings produce undefined ULIDs.
+func Parse(ulid string) (id ULID, err error) {
+ return id, id.UnmarshalText([]byte(ulid))
+}
+
+// MustParse is a convenience function equivalent to Parse that panics on failure
+// instead of returning an error.
+func MustParse(ulid string) ULID {
+ id, err := Parse(ulid)
+ if err != nil {
+ panic(err)
+ }
+ return id
+}
+
+// String returns a lexicographically sortable string encoded ULID
+// (26 characters, non-standard base 32) e.g. 01AN4Z07BY79KA1307SR9X4MV3
+// Format: tttttttttteeeeeeeeeeeeeeee where t is time and e is entropy
+func (id ULID) String() string {
+ ulid := make([]byte, EncodedSize)
+ _ = id.MarshalTextTo(ulid)
+ return string(ulid)
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface by
+// returning the ULID as a byte slice.
+func (id ULID) MarshalBinary() ([]byte, error) {
+ ulid := make([]byte, len(id))
+ return ulid, id.MarshalBinaryTo(ulid)
+}
+
+// MarshalBinaryTo writes the binary encoding of the ULID to the given buffer.
+// ErrBufferSize is returned when the len(dst) != 16.
+func (id ULID) MarshalBinaryTo(dst []byte) error {
+ if len(dst) != len(id) {
+ return ErrBufferSize
+ }
+
+ copy(dst, id[:])
+ return nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface by
+// copying the passed data and converting it to an ULID. ErrDataSize is
+// returned if the data length is different from ULID length.
+func (id *ULID) UnmarshalBinary(data []byte) error {
+ if len(data) != len(*id) {
+ return ErrDataSize
+ }
+
+ copy((*id)[:], data)
+ return nil
+}
+
+// Encoding is the base 32 encoding alphabet used in ULID strings.
+const Encoding = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
+
+// MarshalText implements the encoding.TextMarshaler interface by
+// returning the string encoded ULID.
+func (id ULID) MarshalText() ([]byte, error) {
+ ulid := make([]byte, EncodedSize)
+ return ulid, id.MarshalTextTo(ulid)
+}
+
+// MarshalTextTo writes the ULID as a string to the given buffer.
+// ErrBufferSize is returned when the len(dst) != 26.
+func (id ULID) MarshalTextTo(dst []byte) error {
+ // Optimized unrolled loop ahead.
+ // From https://github.com/RobThree/NUlid
+
+ if len(dst) != EncodedSize {
+ return ErrBufferSize
+ }
+
+ // 10 byte timestamp
+ dst[0] = Encoding[(id[0]&224)>>5]
+ dst[1] = Encoding[id[0]&31]
+ dst[2] = Encoding[(id[1]&248)>>3]
+ dst[3] = Encoding[((id[1]&7)<<2)|((id[2]&192)>>6)]
+ dst[4] = Encoding[(id[2]&62)>>1]
+ dst[5] = Encoding[((id[2]&1)<<4)|((id[3]&240)>>4)]
+ dst[6] = Encoding[((id[3]&15)<<1)|((id[4]&128)>>7)]
+ dst[7] = Encoding[(id[4]&124)>>2]
+ dst[8] = Encoding[((id[4]&3)<<3)|((id[5]&224)>>5)]
+ dst[9] = Encoding[id[5]&31]
+
+ // 16 bytes of entropy
+ dst[10] = Encoding[(id[6]&248)>>3]
+ dst[11] = Encoding[((id[6]&7)<<2)|((id[7]&192)>>6)]
+ dst[12] = Encoding[(id[7]&62)>>1]
+ dst[13] = Encoding[((id[7]&1)<<4)|((id[8]&240)>>4)]
+ dst[14] = Encoding[((id[8]&15)<<1)|((id[9]&128)>>7)]
+ dst[15] = Encoding[(id[9]&124)>>2]
+ dst[16] = Encoding[((id[9]&3)<<3)|((id[10]&224)>>5)]
+ dst[17] = Encoding[id[10]&31]
+ dst[18] = Encoding[(id[11]&248)>>3]
+ dst[19] = Encoding[((id[11]&7)<<2)|((id[12]&192)>>6)]
+ dst[20] = Encoding[(id[12]&62)>>1]
+ dst[21] = Encoding[((id[12]&1)<<4)|((id[13]&240)>>4)]
+ dst[22] = Encoding[((id[13]&15)<<1)|((id[14]&128)>>7)]
+ dst[23] = Encoding[(id[14]&124)>>2]
+ dst[24] = Encoding[((id[14]&3)<<3)|((id[15]&224)>>5)]
+ dst[25] = Encoding[id[15]&31]
+
+ return nil
+}
+
+// Byte to index table for O(1) lookups when unmarshaling.
+// We use 0xFF as sentinel value for invalid indexes.
+var dec = [...]byte{
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01,
+ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
+ 0x0F, 0x10, 0x11, 0xFF, 0x12, 0x13, 0xFF, 0x14, 0x15, 0xFF,
+ 0x16, 0x17, 0x18, 0x19, 0x1A, 0xFF, 0x1B, 0x1C, 0x1D, 0x1E,
+ 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0xFF, 0x12, 0x13, 0xFF, 0x14,
+ 0x15, 0xFF, 0x16, 0x17, 0x18, 0x19, 0x1A, 0xFF, 0x1B, 0x1C,
+ 0x1D, 0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+}
+
+// EncodedSize is the length of a text encoded ULID.
+const EncodedSize = 26
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface by
+// parsing the data as string encoded ULID.
+//
+// ErrDataSize is returned if the len(v) is different from an encoded
+// ULID's length. Invalid encodings produce undefined ULIDs.
+func (id *ULID) UnmarshalText(v []byte) error {
+ // Optimized unrolled loop ahead.
+ // From https://github.com/RobThree/NUlid
+ if len(v) != EncodedSize {
+ return ErrDataSize
+ }
+
+ // 6 bytes timestamp (48 bits)
+ (*id)[0] = ((dec[v[0]] << 5) | dec[v[1]])
+ (*id)[1] = ((dec[v[2]] << 3) | (dec[v[3]] >> 2))
+ (*id)[2] = ((dec[v[3]] << 6) | (dec[v[4]] << 1) | (dec[v[5]] >> 4))
+ (*id)[3] = ((dec[v[5]] << 4) | (dec[v[6]] >> 1))
+ (*id)[4] = ((dec[v[6]] << 7) | (dec[v[7]] << 2) | (dec[v[8]] >> 3))
+ (*id)[5] = ((dec[v[8]] << 5) | dec[v[9]])
+
+ // 10 bytes of entropy (80 bits)
+ (*id)[6] = ((dec[v[10]] << 3) | (dec[v[11]] >> 2))
+ (*id)[7] = ((dec[v[11]] << 6) | (dec[v[12]] << 1) | (dec[v[13]] >> 4))
+ (*id)[8] = ((dec[v[13]] << 4) | (dec[v[14]] >> 1))
+ (*id)[9] = ((dec[v[14]] << 7) | (dec[v[15]] << 2) | (dec[v[16]] >> 3))
+ (*id)[10] = ((dec[v[16]] << 5) | dec[v[17]])
+ (*id)[11] = ((dec[v[18]] << 3) | dec[v[19]]>>2)
+ (*id)[12] = ((dec[v[19]] << 6) | (dec[v[20]] << 1) | (dec[v[21]] >> 4))
+ (*id)[13] = ((dec[v[21]] << 4) | (dec[v[22]] >> 1))
+ (*id)[14] = ((dec[v[22]] << 7) | (dec[v[23]] << 2) | (dec[v[24]] >> 3))
+ (*id)[15] = ((dec[v[24]] << 5) | dec[v[25]])
+
+ return nil
+}
+
+// Time returns the Unix time in milliseconds encoded in the ULID.
+func (id ULID) Time() uint64 {
+ return uint64(id[5]) | uint64(id[4])<<8 |
+ uint64(id[3])<<16 | uint64(id[2])<<24 |
+ uint64(id[1])<<32 | uint64(id[0])<<40
+}
+
+// maxTime is the maximum Unix time in milliseconds that can be
+// represented in an ULID.
+var maxTime = ULID{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}.Time()
+
+// MaxTime returns the maximum Unix time in milliseconds that
+// can be encoded in an ULID.
+func MaxTime() uint64 { return maxTime }
+
+// Now is a convenience function that returns the current
+// UTC time in Unix milliseconds. Equivalent to:
+// Timestamp(time.Now().UTC())
+func Now() uint64 { return Timestamp(time.Now().UTC()) }
+
+// Timestamp converts a time.Time to Unix milliseconds.
+//
+// Because of the way ULID stores time, times from the year
+// 10889 produces undefined results.
+func Timestamp(t time.Time) uint64 {
+ return uint64(t.Unix())*1000 +
+ uint64(t.Nanosecond()/int(time.Millisecond))
+}
+
+// SetTime sets the time component of the ULID to the given Unix time
+// in milliseconds.
+func (id *ULID) SetTime(ms uint64) error {
+ if ms > maxTime {
+ return ErrBigTime
+ }
+
+ (*id)[0] = byte(ms >> 40)
+ (*id)[1] = byte(ms >> 32)
+ (*id)[2] = byte(ms >> 24)
+ (*id)[3] = byte(ms >> 16)
+ (*id)[4] = byte(ms >> 8)
+ (*id)[5] = byte(ms)
+
+ return nil
+}
+
+// Entropy returns the entropy from the ULID.
+func (id ULID) Entropy() []byte {
+ e := make([]byte, 10)
+ copy(e, id[6:])
+ return e
+}
+
+// SetEntropy sets the ULID entropy to the passed byte slice.
+// ErrDataSize is returned if len(e) != 10.
+func (id *ULID) SetEntropy(e []byte) error {
+ if len(e) != 10 {
+ return ErrDataSize
+ }
+
+ copy((*id)[6:], e)
+ return nil
+}
+
+// Compare returns an integer comparing id and other lexicographically.
+// The result will be 0 if id==other, -1 if id < other, and +1 if id > other.
+func (id ULID) Compare(other ULID) int {
+ return bytes.Compare(id[:], other[:])
+}
--- /dev/null
+Copyright (c) 2015, Dave Cheney <dave@cheney.net>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- /dev/null
+# errors [](https://travis-ci.org/pkg/errors) [](https://ci.appveyor.com/project/davecheney/errors/branch/master) [](http://godoc.org/github.com/pkg/errors) [](https://goreportcard.com/report/github.com/pkg/errors)
+
+Package errors provides simple error handling primitives.
+
+`go get github.com/pkg/errors`
+
+The traditional error handling idiom in Go is roughly akin to
+```go
+if err != nil {
+ return err
+}
+```
+which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error.
+
+## Adding context to an error
+
+The errors.Wrap function returns a new error that adds context to the original error. For example
+```go
+_, err := ioutil.ReadAll(r)
+if err != nil {
+ return errors.Wrap(err, "read failed")
+}
+```
+## Retrieving the cause of an error
+
+Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`.
+```go
+type causer interface {
+ Cause() error
+}
+```
+`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example:
+```go
+switch err := errors.Cause(err).(type) {
+case *MyError:
+ // handle specifically
+default:
+ // unknown error
+}
+```
+
+[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors).
+
+## Contributing
+
+We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high.
+
+Before proposing a change, please discuss your change by raising an issue.
+
+## Licence
+
+BSD-2-Clause
--- /dev/null
+// Package errors provides simple error handling primitives.
+//
+// The traditional error handling idiom in Go is roughly akin to
+//
+// if err != nil {
+// return err
+// }
+//
+// which applied recursively up the call stack results in error reports
+// without context or debugging information. The errors package allows
+// programmers to add context to the failure path in their code in a way
+// that does not destroy the original value of the error.
+//
+// Adding context to an error
+//
+// The errors.Wrap function returns a new error that adds context to the
+// original error by recording a stack trace at the point Wrap is called,
+// and the supplied message. For example
+//
+// _, err := ioutil.ReadAll(r)
+// if err != nil {
+// return errors.Wrap(err, "read failed")
+// }
+//
+// If additional control is required the errors.WithStack and errors.WithMessage
+// functions destructure errors.Wrap into its component operations of annotating
+// an error with a stack trace and an a message, respectively.
+//
+// Retrieving the cause of an error
+//
+// Using errors.Wrap constructs a stack of errors, adding context to the
+// preceding error. Depending on the nature of the error it may be necessary
+// to reverse the operation of errors.Wrap to retrieve the original error
+// for inspection. Any error value which implements this interface
+//
+// type causer interface {
+// Cause() error
+// }
+//
+// can be inspected by errors.Cause. errors.Cause will recursively retrieve
+// the topmost error which does not implement causer, which is assumed to be
+// the original cause. For example:
+//
+// switch err := errors.Cause(err).(type) {
+// case *MyError:
+// // handle specifically
+// default:
+// // unknown error
+// }
+//
+// causer interface is not exported by this package, but is considered a part
+// of stable public API.
+//
+// Formatted printing of errors
+//
+// All error values returned from this package implement fmt.Formatter and can
+// be formatted by the fmt package. The following verbs are supported
+//
+// %s print the error. If the error has a Cause it will be
+// printed recursively
+// %v see %s
+// %+v extended format. Each Frame of the error's StackTrace will
+// be printed in detail.
+//
+// Retrieving the stack trace of an error or wrapper
+//
+// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
+// invoked. This information can be retrieved with the following interface.
+//
+// type stackTracer interface {
+// StackTrace() errors.StackTrace
+// }
+//
+// Where errors.StackTrace is defined as
+//
+// type StackTrace []Frame
+//
+// The Frame type represents a call site in the stack trace. Frame supports
+// the fmt.Formatter interface that can be used for printing information about
+// the stack trace of this error. For example:
+//
+// if err, ok := err.(stackTracer); ok {
+// for _, f := range err.StackTrace() {
+// fmt.Printf("%+s:%d", f)
+// }
+// }
+//
+// stackTracer interface is not exported by this package, but is considered a part
+// of stable public API.
+//
+// See the documentation for Frame.Format for more details.
+package errors
+
+import (
+ "fmt"
+ "io"
+)
+
+// New returns an error with the supplied message.
+// New also records the stack trace at the point it was called.
+func New(message string) error {
+ return &fundamental{
+ msg: message,
+ stack: callers(),
+ }
+}
+
+// Errorf formats according to a format specifier and returns the string
+// as a value that satisfies error.
+// Errorf also records the stack trace at the point it was called.
+func Errorf(format string, args ...interface{}) error {
+ return &fundamental{
+ msg: fmt.Sprintf(format, args...),
+ stack: callers(),
+ }
+}
+
+// fundamental is an error that has a message and a stack, but no caller.
+type fundamental struct {
+ msg string
+ *stack
+}
+
+func (f *fundamental) Error() string { return f.msg }
+
+func (f *fundamental) Format(s fmt.State, verb rune) {
+ switch verb {
+ case 'v':
+ if s.Flag('+') {
+ io.WriteString(s, f.msg)
+ f.stack.Format(s, verb)
+ return
+ }
+ fallthrough
+ case 's':
+ io.WriteString(s, f.msg)
+ case 'q':
+ fmt.Fprintf(s, "%q", f.msg)
+ }
+}
+
+// WithStack annotates err with a stack trace at the point WithStack was called.
+// If err is nil, WithStack returns nil.
+func WithStack(err error) error {
+ if err == nil {
+ return nil
+ }
+ return &withStack{
+ err,
+ callers(),
+ }
+}
+
+type withStack struct {
+ error
+ *stack
+}
+
+func (w *withStack) Cause() error { return w.error }
+
+func (w *withStack) Format(s fmt.State, verb rune) {
+ switch verb {
+ case 'v':
+ if s.Flag('+') {
+ fmt.Fprintf(s, "%+v", w.Cause())
+ w.stack.Format(s, verb)
+ return
+ }
+ fallthrough
+ case 's':
+ io.WriteString(s, w.Error())
+ case 'q':
+ fmt.Fprintf(s, "%q", w.Error())
+ }
+}
+
+// Wrap returns an error annotating err with a stack trace
+// at the point Wrap is called, and the supplied message.
+// If err is nil, Wrap returns nil.
+func Wrap(err error, message string) error {
+ if err == nil {
+ return nil
+ }
+ err = &withMessage{
+ cause: err,
+ msg: message,
+ }
+ return &withStack{
+ err,
+ callers(),
+ }
+}
+
+// Wrapf returns an error annotating err with a stack trace
+// at the point Wrapf is call, and the format specifier.
+// If err is nil, Wrapf returns nil.
+func Wrapf(err error, format string, args ...interface{}) error {
+ if err == nil {
+ return nil
+ }
+ err = &withMessage{
+ cause: err,
+ msg: fmt.Sprintf(format, args...),
+ }
+ return &withStack{
+ err,
+ callers(),
+ }
+}
+
+// WithMessage annotates err with a new message.
+// If err is nil, WithMessage returns nil.
+func WithMessage(err error, message string) error {
+ if err == nil {
+ return nil
+ }
+ return &withMessage{
+ cause: err,
+ msg: message,
+ }
+}
+
+type withMessage struct {
+ cause error
+ msg string
+}
+
+func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() }
+func (w *withMessage) Cause() error { return w.cause }
+
+func (w *withMessage) Format(s fmt.State, verb rune) {
+ switch verb {
+ case 'v':
+ if s.Flag('+') {
+ fmt.Fprintf(s, "%+v\n", w.Cause())
+ io.WriteString(s, w.msg)
+ return
+ }
+ fallthrough
+ case 's', 'q':
+ io.WriteString(s, w.Error())
+ }
+}
+
+// Cause returns the underlying cause of the error, if possible.
+// An error value has a cause if it implements the following
+// interface:
+//
+// type causer interface {
+// Cause() error
+// }
+//
+// If the error does not implement Cause, the original error will
+// be returned. If the error is nil, nil will be returned without further
+// investigation.
+func Cause(err error) error {
+ type causer interface {
+ Cause() error
+ }
+
+ for err != nil {
+ cause, ok := err.(causer)
+ if !ok {
+ break
+ }
+ err = cause.Cause()
+ }
+ return err
+}
--- /dev/null
+package errors
+
+import (
+ "fmt"
+ "io"
+ "path"
+ "runtime"
+ "strings"
+)
+
+// Frame represents a program counter inside a stack frame.
+type Frame uintptr
+
+// pc returns the program counter for this frame;
+// multiple frames may have the same PC value.
+func (f Frame) pc() uintptr { return uintptr(f) - 1 }
+
+// file returns the full path to the file that contains the
+// function for this Frame's pc.
+func (f Frame) file() string {
+ fn := runtime.FuncForPC(f.pc())
+ if fn == nil {
+ return "unknown"
+ }
+ file, _ := fn.FileLine(f.pc())
+ return file
+}
+
+// line returns the line number of source code of the
+// function for this Frame's pc.
+func (f Frame) line() int {
+ fn := runtime.FuncForPC(f.pc())
+ if fn == nil {
+ return 0
+ }
+ _, line := fn.FileLine(f.pc())
+ return line
+}
+
+// Format formats the frame according to the fmt.Formatter interface.
+//
+// %s source file
+// %d source line
+// %n function name
+// %v equivalent to %s:%d
+//
+// Format accepts flags that alter the printing of some verbs, as follows:
+//
+// %+s path of source file relative to the compile time GOPATH
+// %+v equivalent to %+s:%d
+func (f Frame) Format(s fmt.State, verb rune) {
+ switch verb {
+ case 's':
+ switch {
+ case s.Flag('+'):
+ pc := f.pc()
+ fn := runtime.FuncForPC(pc)
+ if fn == nil {
+ io.WriteString(s, "unknown")
+ } else {
+ file, _ := fn.FileLine(pc)
+ fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file)
+ }
+ default:
+ io.WriteString(s, path.Base(f.file()))
+ }
+ case 'd':
+ fmt.Fprintf(s, "%d", f.line())
+ case 'n':
+ name := runtime.FuncForPC(f.pc()).Name()
+ io.WriteString(s, funcname(name))
+ case 'v':
+ f.Format(s, 's')
+ io.WriteString(s, ":")
+ f.Format(s, 'd')
+ }
+}
+
+// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
+type StackTrace []Frame
+
+func (st StackTrace) Format(s fmt.State, verb rune) {
+ switch verb {
+ case 'v':
+ switch {
+ case s.Flag('+'):
+ for _, f := range st {
+ fmt.Fprintf(s, "\n%+v", f)
+ }
+ case s.Flag('#'):
+ fmt.Fprintf(s, "%#v", []Frame(st))
+ default:
+ fmt.Fprintf(s, "%v", []Frame(st))
+ }
+ case 's':
+ fmt.Fprintf(s, "%s", []Frame(st))
+ }
+}
+
+// stack represents a stack of program counters.
+type stack []uintptr
+
+func (s *stack) Format(st fmt.State, verb rune) {
+ switch verb {
+ case 'v':
+ switch {
+ case st.Flag('+'):
+ for _, pc := range *s {
+ f := Frame(pc)
+ fmt.Fprintf(st, "\n%+v", f)
+ }
+ }
+ }
+}
+
+func (s *stack) StackTrace() StackTrace {
+ f := make([]Frame, len(*s))
+ for i := 0; i < len(f); i++ {
+ f[i] = Frame((*s)[i])
+ }
+ return f
+}
+
+func callers() *stack {
+ const depth = 32
+ var pcs [depth]uintptr
+ n := runtime.Callers(3, pcs[:])
+ var st stack = pcs[0:n]
+ return &st
+}
+
+// funcname removes the path prefix component of a function's name reported by func.Name().
+func funcname(name string) string {
+ i := strings.LastIndex(name, "/")
+ name = name[i+1:]
+ i = strings.Index(name, ".")
+ return name[i+1:]
+}
+
+func trimGOPATH(name, file string) string {
+ // Here we want to get the source file path relative to the compile time
+ // GOPATH. As of Go 1.6.x there is no direct way to know the compiled
+ // GOPATH at runtime, but we can infer the number of path segments in the
+ // GOPATH. We note that fn.Name() returns the function name qualified by
+ // the import path, which does not include the GOPATH. Thus we can trim
+ // segments from the beginning of the file path until the number of path
+ // separators remaining is one more than the number of path separators in
+ // the function name. For example, given:
+ //
+ // GOPATH /home/user
+ // file /home/user/src/pkg/sub/file.go
+ // fn.Name() pkg/sub.Type.Method
+ //
+ // We want to produce:
+ //
+ // pkg/sub/file.go
+ //
+ // From this we can easily see that fn.Name() has one less path separator
+ // than our desired output. We count separators from the end of the file
+ // path until it finds two more than in the function name and then move
+ // one character forward to preserve the initial path segment without a
+ // leading separator.
+ const sep = "/"
+ goal := strings.Count(name, sep) + 2
+ i := len(file)
+ for n := 0; n < goal; n++ {
+ i = strings.LastIndex(file[:i], sep)
+ if i == -1 {
+ // not enough separators found, set i so that the slice expression
+ // below leaves file unmodified
+ i = -len(sep)
+ break
+ }
+ }
+ // get back to 0 or trim the leading separator
+ file = file[i+len(sep):]
+ return file
+}
--- /dev/null
+Copyright (c) 2013, Patrick Mezard
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+ The names of its contributors may not be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- /dev/null
+// Package difflib is a partial port of Python difflib module.
+//
+// It provides tools to compare sequences of strings and generate textual diffs.
+//
+// The following class and functions have been ported:
+//
+// - SequenceMatcher
+//
+// - unified_diff
+//
+// - context_diff
+//
+// Getting unified diffs was the main goal of the port. Keep in mind this code
+// is mostly suitable to output text differences in a human friendly way, there
+// are no guarantees generated diffs are consumable by patch(1).
+package difflib
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "strings"
+)
+
+func min(a, b int) int {
+ if a < b {
+ return a
+ }
+ return b
+}
+
+func max(a, b int) int {
+ if a > b {
+ return a
+ }
+ return b
+}
+
+func calculateRatio(matches, length int) float64 {
+ if length > 0 {
+ return 2.0 * float64(matches) / float64(length)
+ }
+ return 1.0
+}
+
+type Match struct {
+ A int
+ B int
+ Size int
+}
+
+type OpCode struct {
+ Tag byte
+ I1 int
+ I2 int
+ J1 int
+ J2 int
+}
+
+// SequenceMatcher compares sequence of strings. The basic
+// algorithm predates, and is a little fancier than, an algorithm
+// published in the late 1980's by Ratcliff and Obershelp under the
+// hyperbolic name "gestalt pattern matching". The basic idea is to find
+// the longest contiguous matching subsequence that contains no "junk"
+// elements (R-O doesn't address junk). The same idea is then applied
+// recursively to the pieces of the sequences to the left and to the right
+// of the matching subsequence. This does not yield minimal edit
+// sequences, but does tend to yield matches that "look right" to people.
+//
+// SequenceMatcher tries to compute a "human-friendly diff" between two
+// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the
+// longest *contiguous* & junk-free matching subsequence. That's what
+// catches peoples' eyes. The Windows(tm) windiff has another interesting
+// notion, pairing up elements that appear uniquely in each sequence.
+// That, and the method here, appear to yield more intuitive difference
+// reports than does diff. This method appears to be the least vulnerable
+// to synching up on blocks of "junk lines", though (like blank lines in
+// ordinary text files, or maybe "<P>" lines in HTML files). That may be
+// because this is the only method of the 3 that has a *concept* of
+// "junk" <wink>.
+//
+// Timing: Basic R-O is cubic time worst case and quadratic time expected
+// case. SequenceMatcher is quadratic time for the worst case and has
+// expected-case behavior dependent in a complicated way on how many
+// elements the sequences have in common; best case time is linear.
+type SequenceMatcher struct {
+ a []string
+ b []string
+ b2j map[string][]int
+ IsJunk func(string) bool
+ autoJunk bool
+ bJunk map[string]struct{}
+ matchingBlocks []Match
+ fullBCount map[string]int
+ bPopular map[string]struct{}
+ opCodes []OpCode
+}
+
+func NewMatcher(a, b []string) *SequenceMatcher {
+ m := SequenceMatcher{autoJunk: true}
+ m.SetSeqs(a, b)
+ return &m
+}
+
+func NewMatcherWithJunk(a, b []string, autoJunk bool,
+ isJunk func(string) bool) *SequenceMatcher {
+
+ m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk}
+ m.SetSeqs(a, b)
+ return &m
+}
+
+// Set two sequences to be compared.
+func (m *SequenceMatcher) SetSeqs(a, b []string) {
+ m.SetSeq1(a)
+ m.SetSeq2(b)
+}
+
+// Set the first sequence to be compared. The second sequence to be compared is
+// not changed.
+//
+// SequenceMatcher computes and caches detailed information about the second
+// sequence, so if you want to compare one sequence S against many sequences,
+// use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other
+// sequences.
+//
+// See also SetSeqs() and SetSeq2().
+func (m *SequenceMatcher) SetSeq1(a []string) {
+ if &a == &m.a {
+ return
+ }
+ m.a = a
+ m.matchingBlocks = nil
+ m.opCodes = nil
+}
+
+// Set the second sequence to be compared. The first sequence to be compared is
+// not changed.
+func (m *SequenceMatcher) SetSeq2(b []string) {
+ if &b == &m.b {
+ return
+ }
+ m.b = b
+ m.matchingBlocks = nil
+ m.opCodes = nil
+ m.fullBCount = nil
+ m.chainB()
+}
+
+func (m *SequenceMatcher) chainB() {
+ // Populate line -> index mapping
+ b2j := map[string][]int{}
+ for i, s := range m.b {
+ indices := b2j[s]
+ indices = append(indices, i)
+ b2j[s] = indices
+ }
+
+ // Purge junk elements
+ m.bJunk = map[string]struct{}{}
+ if m.IsJunk != nil {
+ junk := m.bJunk
+ for s, _ := range b2j {
+ if m.IsJunk(s) {
+ junk[s] = struct{}{}
+ }
+ }
+ for s, _ := range junk {
+ delete(b2j, s)
+ }
+ }
+
+ // Purge remaining popular elements
+ popular := map[string]struct{}{}
+ n := len(m.b)
+ if m.autoJunk && n >= 200 {
+ ntest := n/100 + 1
+ for s, indices := range b2j {
+ if len(indices) > ntest {
+ popular[s] = struct{}{}
+ }
+ }
+ for s, _ := range popular {
+ delete(b2j, s)
+ }
+ }
+ m.bPopular = popular
+ m.b2j = b2j
+}
+
+func (m *SequenceMatcher) isBJunk(s string) bool {
+ _, ok := m.bJunk[s]
+ return ok
+}
+
+// Find longest matching block in a[alo:ahi] and b[blo:bhi].
+//
+// If IsJunk is not defined:
+//
+// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where
+// alo <= i <= i+k <= ahi
+// blo <= j <= j+k <= bhi
+// and for all (i',j',k') meeting those conditions,
+// k >= k'
+// i <= i'
+// and if i == i', j <= j'
+//
+// In other words, of all maximal matching blocks, return one that
+// starts earliest in a, and of all those maximal matching blocks that
+// start earliest in a, return the one that starts earliest in b.
+//
+// If IsJunk is defined, first the longest matching block is
+// determined as above, but with the additional restriction that no
+// junk element appears in the block. Then that block is extended as
+// far as possible by matching (only) junk elements on both sides. So
+// the resulting block never matches on junk except as identical junk
+// happens to be adjacent to an "interesting" match.
+//
+// If no blocks match, return (alo, blo, 0).
+func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match {
+ // CAUTION: stripping common prefix or suffix would be incorrect.
+ // E.g.,
+ // ab
+ // acab
+ // Longest matching block is "ab", but if common prefix is
+ // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so
+ // strip, so ends up claiming that ab is changed to acab by
+ // inserting "ca" in the middle. That's minimal but unintuitive:
+ // "it's obvious" that someone inserted "ac" at the front.
+ // Windiff ends up at the same place as diff, but by pairing up
+ // the unique 'b's and then matching the first two 'a's.
+ besti, bestj, bestsize := alo, blo, 0
+
+ // find longest junk-free match
+ // during an iteration of the loop, j2len[j] = length of longest
+ // junk-free match ending with a[i-1] and b[j]
+ j2len := map[int]int{}
+ for i := alo; i != ahi; i++ {
+ // look at all instances of a[i] in b; note that because
+ // b2j has no junk keys, the loop is skipped if a[i] is junk
+ newj2len := map[int]int{}
+ for _, j := range m.b2j[m.a[i]] {
+ // a[i] matches b[j]
+ if j < blo {
+ continue
+ }
+ if j >= bhi {
+ break
+ }
+ k := j2len[j-1] + 1
+ newj2len[j] = k
+ if k > bestsize {
+ besti, bestj, bestsize = i-k+1, j-k+1, k
+ }
+ }
+ j2len = newj2len
+ }
+
+ // Extend the best by non-junk elements on each end. In particular,
+ // "popular" non-junk elements aren't in b2j, which greatly speeds
+ // the inner loop above, but also means "the best" match so far
+ // doesn't contain any junk *or* popular non-junk elements.
+ for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) &&
+ m.a[besti-1] == m.b[bestj-1] {
+ besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
+ }
+ for besti+bestsize < ahi && bestj+bestsize < bhi &&
+ !m.isBJunk(m.b[bestj+bestsize]) &&
+ m.a[besti+bestsize] == m.b[bestj+bestsize] {
+ bestsize += 1
+ }
+
+ // Now that we have a wholly interesting match (albeit possibly
+ // empty!), we may as well suck up the matching junk on each
+ // side of it too. Can't think of a good reason not to, and it
+ // saves post-processing the (possibly considerable) expense of
+ // figuring out what to do with it. In the case of an empty
+ // interesting match, this is clearly the right thing to do,
+ // because no other kind of match is possible in the regions.
+ for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) &&
+ m.a[besti-1] == m.b[bestj-1] {
+ besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
+ }
+ for besti+bestsize < ahi && bestj+bestsize < bhi &&
+ m.isBJunk(m.b[bestj+bestsize]) &&
+ m.a[besti+bestsize] == m.b[bestj+bestsize] {
+ bestsize += 1
+ }
+
+ return Match{A: besti, B: bestj, Size: bestsize}
+}
+
+// Return list of triples describing matching subsequences.
+//
+// Each triple is of the form (i, j, n), and means that
+// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in
+// i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are
+// adjacent triples in the list, and the second is not the last triple in the
+// list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe
+// adjacent equal blocks.
+//
+// The last triple is a dummy, (len(a), len(b), 0), and is the only
+// triple with n==0.
+func (m *SequenceMatcher) GetMatchingBlocks() []Match {
+ if m.matchingBlocks != nil {
+ return m.matchingBlocks
+ }
+
+ var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match
+ matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match {
+ match := m.findLongestMatch(alo, ahi, blo, bhi)
+ i, j, k := match.A, match.B, match.Size
+ if match.Size > 0 {
+ if alo < i && blo < j {
+ matched = matchBlocks(alo, i, blo, j, matched)
+ }
+ matched = append(matched, match)
+ if i+k < ahi && j+k < bhi {
+ matched = matchBlocks(i+k, ahi, j+k, bhi, matched)
+ }
+ }
+ return matched
+ }
+ matched := matchBlocks(0, len(m.a), 0, len(m.b), nil)
+
+ // It's possible that we have adjacent equal blocks in the
+ // matching_blocks list now.
+ nonAdjacent := []Match{}
+ i1, j1, k1 := 0, 0, 0
+ for _, b := range matched {
+ // Is this block adjacent to i1, j1, k1?
+ i2, j2, k2 := b.A, b.B, b.Size
+ if i1+k1 == i2 && j1+k1 == j2 {
+ // Yes, so collapse them -- this just increases the length of
+ // the first block by the length of the second, and the first
+ // block so lengthened remains the block to compare against.
+ k1 += k2
+ } else {
+ // Not adjacent. Remember the first block (k1==0 means it's
+ // the dummy we started with), and make the second block the
+ // new block to compare against.
+ if k1 > 0 {
+ nonAdjacent = append(nonAdjacent, Match{i1, j1, k1})
+ }
+ i1, j1, k1 = i2, j2, k2
+ }
+ }
+ if k1 > 0 {
+ nonAdjacent = append(nonAdjacent, Match{i1, j1, k1})
+ }
+
+ nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0})
+ m.matchingBlocks = nonAdjacent
+ return m.matchingBlocks
+}
+
+// Return list of 5-tuples describing how to turn a into b.
+//
+// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple
+// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the
+// tuple preceding it, and likewise for j1 == the previous j2.
+//
+// The tags are characters, with these meanings:
+//
+// 'r' (replace): a[i1:i2] should be replaced by b[j1:j2]
+//
+// 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case.
+//
+// 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case.
+//
+// 'e' (equal): a[i1:i2] == b[j1:j2]
+func (m *SequenceMatcher) GetOpCodes() []OpCode {
+ if m.opCodes != nil {
+ return m.opCodes
+ }
+ i, j := 0, 0
+ matching := m.GetMatchingBlocks()
+ opCodes := make([]OpCode, 0, len(matching))
+ for _, m := range matching {
+ // invariant: we've pumped out correct diffs to change
+ // a[:i] into b[:j], and the next matching block is
+ // a[ai:ai+size] == b[bj:bj+size]. So we need to pump
+ // out a diff to change a[i:ai] into b[j:bj], pump out
+ // the matching block, and move (i,j) beyond the match
+ ai, bj, size := m.A, m.B, m.Size
+ tag := byte(0)
+ if i < ai && j < bj {
+ tag = 'r'
+ } else if i < ai {
+ tag = 'd'
+ } else if j < bj {
+ tag = 'i'
+ }
+ if tag > 0 {
+ opCodes = append(opCodes, OpCode{tag, i, ai, j, bj})
+ }
+ i, j = ai+size, bj+size
+ // the list of matching blocks is terminated by a
+ // sentinel with size 0
+ if size > 0 {
+ opCodes = append(opCodes, OpCode{'e', ai, i, bj, j})
+ }
+ }
+ m.opCodes = opCodes
+ return m.opCodes
+}
+
+// Isolate change clusters by eliminating ranges with no changes.
+//
+// Return a generator of groups with up to n lines of context.
+// Each group is in the same format as returned by GetOpCodes().
+func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode {
+ if n < 0 {
+ n = 3
+ }
+ codes := m.GetOpCodes()
+ if len(codes) == 0 {
+ codes = []OpCode{OpCode{'e', 0, 1, 0, 1}}
+ }
+ // Fixup leading and trailing groups if they show no changes.
+ if codes[0].Tag == 'e' {
+ c := codes[0]
+ i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
+ codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2}
+ }
+ if codes[len(codes)-1].Tag == 'e' {
+ c := codes[len(codes)-1]
+ i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
+ codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)}
+ }
+ nn := n + n
+ groups := [][]OpCode{}
+ group := []OpCode{}
+ for _, c := range codes {
+ i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
+ // End the current group and start a new one whenever
+ // there is a large range with no changes.
+ if c.Tag == 'e' && i2-i1 > nn {
+ group = append(group, OpCode{c.Tag, i1, min(i2, i1+n),
+ j1, min(j2, j1+n)})
+ groups = append(groups, group)
+ group = []OpCode{}
+ i1, j1 = max(i1, i2-n), max(j1, j2-n)
+ }
+ group = append(group, OpCode{c.Tag, i1, i2, j1, j2})
+ }
+ if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') {
+ groups = append(groups, group)
+ }
+ return groups
+}
+
+// Return a measure of the sequences' similarity (float in [0,1]).
+//
+// Where T is the total number of elements in both sequences, and
+// M is the number of matches, this is 2.0*M / T.
+// Note that this is 1 if the sequences are identical, and 0 if
+// they have nothing in common.
+//
+// .Ratio() is expensive to compute if you haven't already computed
+// .GetMatchingBlocks() or .GetOpCodes(), in which case you may
+// want to try .QuickRatio() or .RealQuickRation() first to get an
+// upper bound.
+func (m *SequenceMatcher) Ratio() float64 {
+ matches := 0
+ for _, m := range m.GetMatchingBlocks() {
+ matches += m.Size
+ }
+ return calculateRatio(matches, len(m.a)+len(m.b))
+}
+
+// Return an upper bound on ratio() relatively quickly.
+//
+// This isn't defined beyond that it is an upper bound on .Ratio(), and
+// is faster to compute.
+func (m *SequenceMatcher) QuickRatio() float64 {
+ // viewing a and b as multisets, set matches to the cardinality
+ // of their intersection; this counts the number of matches
+ // without regard to order, so is clearly an upper bound
+ if m.fullBCount == nil {
+ m.fullBCount = map[string]int{}
+ for _, s := range m.b {
+ m.fullBCount[s] = m.fullBCount[s] + 1
+ }
+ }
+
+ // avail[x] is the number of times x appears in 'b' less the
+ // number of times we've seen it in 'a' so far ... kinda
+ avail := map[string]int{}
+ matches := 0
+ for _, s := range m.a {
+ n, ok := avail[s]
+ if !ok {
+ n = m.fullBCount[s]
+ }
+ avail[s] = n - 1
+ if n > 0 {
+ matches += 1
+ }
+ }
+ return calculateRatio(matches, len(m.a)+len(m.b))
+}
+
+// Return an upper bound on ratio() very quickly.
+//
+// This isn't defined beyond that it is an upper bound on .Ratio(), and
+// is faster to compute than either .Ratio() or .QuickRatio().
+func (m *SequenceMatcher) RealQuickRatio() float64 {
+ la, lb := len(m.a), len(m.b)
+ return calculateRatio(min(la, lb), la+lb)
+}
+
+// Convert range to the "ed" format
+func formatRangeUnified(start, stop int) string {
+ // Per the diff spec at http://www.unix.org/single_unix_specification/
+ beginning := start + 1 // lines start numbering with one
+ length := stop - start
+ if length == 1 {
+ return fmt.Sprintf("%d", beginning)
+ }
+ if length == 0 {
+ beginning -= 1 // empty ranges begin at line just before the range
+ }
+ return fmt.Sprintf("%d,%d", beginning, length)
+}
+
+// Unified diff parameters
+type UnifiedDiff struct {
+ A []string // First sequence lines
+ FromFile string // First file name
+ FromDate string // First file time
+ B []string // Second sequence lines
+ ToFile string // Second file name
+ ToDate string // Second file time
+ Eol string // Headers end of line, defaults to LF
+ Context int // Number of context lines
+}
+
+// Compare two sequences of lines; generate the delta as a unified diff.
+//
+// Unified diffs are a compact way of showing line changes and a few
+// lines of context. The number of context lines is set by 'n' which
+// defaults to three.
+//
+// By default, the diff control lines (those with ---, +++, or @@) are
+// created with a trailing newline. This is helpful so that inputs
+// created from file.readlines() result in diffs that are suitable for
+// file.writelines() since both the inputs and outputs have trailing
+// newlines.
+//
+// For inputs that do not have trailing newlines, set the lineterm
+// argument to "" so that the output will be uniformly newline free.
+//
+// The unidiff format normally has a header for filenames and modification
+// times. Any or all of these may be specified using strings for
+// 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
+// The modification times are normally expressed in the ISO 8601 format.
+func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error {
+ buf := bufio.NewWriter(writer)
+ defer buf.Flush()
+ wf := func(format string, args ...interface{}) error {
+ _, err := buf.WriteString(fmt.Sprintf(format, args...))
+ return err
+ }
+ ws := func(s string) error {
+ _, err := buf.WriteString(s)
+ return err
+ }
+
+ if len(diff.Eol) == 0 {
+ diff.Eol = "\n"
+ }
+
+ started := false
+ m := NewMatcher(diff.A, diff.B)
+ for _, g := range m.GetGroupedOpCodes(diff.Context) {
+ if !started {
+ started = true
+ fromDate := ""
+ if len(diff.FromDate) > 0 {
+ fromDate = "\t" + diff.FromDate
+ }
+ toDate := ""
+ if len(diff.ToDate) > 0 {
+ toDate = "\t" + diff.ToDate
+ }
+ if diff.FromFile != "" || diff.ToFile != "" {
+ err := wf("--- %s%s%s", diff.FromFile, fromDate, diff.Eol)
+ if err != nil {
+ return err
+ }
+ err = wf("+++ %s%s%s", diff.ToFile, toDate, diff.Eol)
+ if err != nil {
+ return err
+ }
+ }
+ }
+ first, last := g[0], g[len(g)-1]
+ range1 := formatRangeUnified(first.I1, last.I2)
+ range2 := formatRangeUnified(first.J1, last.J2)
+ if err := wf("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil {
+ return err
+ }
+ for _, c := range g {
+ i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
+ if c.Tag == 'e' {
+ for _, line := range diff.A[i1:i2] {
+ if err := ws(" " + line); err != nil {
+ return err
+ }
+ }
+ continue
+ }
+ if c.Tag == 'r' || c.Tag == 'd' {
+ for _, line := range diff.A[i1:i2] {
+ if err := ws("-" + line); err != nil {
+ return err
+ }
+ }
+ }
+ if c.Tag == 'r' || c.Tag == 'i' {
+ for _, line := range diff.B[j1:j2] {
+ if err := ws("+" + line); err != nil {
+ return err
+ }
+ }
+ }
+ }
+ }
+ return nil
+}
+
+// Like WriteUnifiedDiff but returns the diff a string.
+func GetUnifiedDiffString(diff UnifiedDiff) (string, error) {
+ w := &bytes.Buffer{}
+ err := WriteUnifiedDiff(w, diff)
+ return string(w.Bytes()), err
+}
+
+// Convert range to the "ed" format.
+func formatRangeContext(start, stop int) string {
+ // Per the diff spec at http://www.unix.org/single_unix_specification/
+ beginning := start + 1 // lines start numbering with one
+ length := stop - start
+ if length == 0 {
+ beginning -= 1 // empty ranges begin at line just before the range
+ }
+ if length <= 1 {
+ return fmt.Sprintf("%d", beginning)
+ }
+ return fmt.Sprintf("%d,%d", beginning, beginning+length-1)
+}
+
+type ContextDiff UnifiedDiff
+
+// Compare two sequences of lines; generate the delta as a context diff.
+//
+// Context diffs are a compact way of showing line changes and a few
+// lines of context. The number of context lines is set by diff.Context
+// which defaults to three.
+//
+// By default, the diff control lines (those with *** or ---) are
+// created with a trailing newline.
+//
+// For inputs that do not have trailing newlines, set the diff.Eol
+// argument to "" so that the output will be uniformly newline free.
+//
+// The context diff format normally has a header for filenames and
+// modification times. Any or all of these may be specified using
+// strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate.
+// The modification times are normally expressed in the ISO 8601 format.
+// If not specified, the strings default to blanks.
+func WriteContextDiff(writer io.Writer, diff ContextDiff) error {
+ buf := bufio.NewWriter(writer)
+ defer buf.Flush()
+ var diffErr error
+ wf := func(format string, args ...interface{}) {
+ _, err := buf.WriteString(fmt.Sprintf(format, args...))
+ if diffErr == nil && err != nil {
+ diffErr = err
+ }
+ }
+ ws := func(s string) {
+ _, err := buf.WriteString(s)
+ if diffErr == nil && err != nil {
+ diffErr = err
+ }
+ }
+
+ if len(diff.Eol) == 0 {
+ diff.Eol = "\n"
+ }
+
+ prefix := map[byte]string{
+ 'i': "+ ",
+ 'd': "- ",
+ 'r': "! ",
+ 'e': " ",
+ }
+
+ started := false
+ m := NewMatcher(diff.A, diff.B)
+ for _, g := range m.GetGroupedOpCodes(diff.Context) {
+ if !started {
+ started = true
+ fromDate := ""
+ if len(diff.FromDate) > 0 {
+ fromDate = "\t" + diff.FromDate
+ }
+ toDate := ""
+ if len(diff.ToDate) > 0 {
+ toDate = "\t" + diff.ToDate
+ }
+ if diff.FromFile != "" || diff.ToFile != "" {
+ wf("*** %s%s%s", diff.FromFile, fromDate, diff.Eol)
+ wf("--- %s%s%s", diff.ToFile, toDate, diff.Eol)
+ }
+ }
+
+ first, last := g[0], g[len(g)-1]
+ ws("***************" + diff.Eol)
+
+ range1 := formatRangeContext(first.I1, last.I2)
+ wf("*** %s ****%s", range1, diff.Eol)
+ for _, c := range g {
+ if c.Tag == 'r' || c.Tag == 'd' {
+ for _, cc := range g {
+ if cc.Tag == 'i' {
+ continue
+ }
+ for _, line := range diff.A[cc.I1:cc.I2] {
+ ws(prefix[cc.Tag] + line)
+ }
+ }
+ break
+ }
+ }
+
+ range2 := formatRangeContext(first.J1, last.J2)
+ wf("--- %s ----%s", range2, diff.Eol)
+ for _, c := range g {
+ if c.Tag == 'r' || c.Tag == 'i' {
+ for _, cc := range g {
+ if cc.Tag == 'd' {
+ continue
+ }
+ for _, line := range diff.B[cc.J1:cc.J2] {
+ ws(prefix[cc.Tag] + line)
+ }
+ }
+ break
+ }
+ }
+ }
+ return diffErr
+}
+
+// Like WriteContextDiff but returns the diff a string.
+func GetContextDiffString(diff ContextDiff) (string, error) {
+ w := &bytes.Buffer{}
+ err := WriteContextDiff(w, diff)
+ return string(w.Bytes()), err
+}
+
+// Split a string on "\n" while preserving them. The output can be used
+// as input for UnifiedDiff and ContextDiff structures.
+func SplitLines(s string) []string {
+ lines := strings.SplitAfter(s, "\n")
+ lines[len(lines)-1] += "\n"
+ return lines
+}
--- /dev/null
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
--- /dev/null
+Prometheus instrumentation library for Go applications
+Copyright 2012-2015 The Prometheus Authors
+
+This product includes software developed at
+SoundCloud Ltd. (http://soundcloud.com/).
+
+
+The following components are included in this product:
+
+perks - a fork of https://github.com/bmizerany/perks
+https://github.com/beorn7/perks
+Copyright 2013-2015 Blake Mizerany, Björn Rabenstein
+See https://github.com/beorn7/perks/blob/master/README.md for license details.
+
+Go support for Protocol Buffers - Google's data interchange format
+http://github.com/golang/protobuf/
+Copyright 2010 The Go Authors
+See source code for license details.
+
+Support for streaming Protocol Buffer messages for the Go language (golang).
+https://github.com/matttproud/golang_protobuf_extensions
+Copyright 2013 Matt T. Proud
+Licensed under the Apache License, Version 2.0
--- /dev/null
+// Copyright 2015 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build go1.7
+
+// Package api provides clients for the HTTP APIs.
+package api
+
+import (
+ "context"
+ "io/ioutil"
+ "net"
+ "net/http"
+ "net/url"
+ "path"
+ "strings"
+ "time"
+)
+
+// DefaultRoundTripper is used if no RoundTripper is set in Config.
+var DefaultRoundTripper http.RoundTripper = &http.Transport{
+ Proxy: http.ProxyFromEnvironment,
+ Dial: (&net.Dialer{
+ Timeout: 30 * time.Second,
+ KeepAlive: 30 * time.Second,
+ }).Dial,
+ TLSHandshakeTimeout: 10 * time.Second,
+}
+
+// Config defines configuration parameters for a new client.
+type Config struct {
+ // The address of the Prometheus to connect to.
+ Address string
+
+ // RoundTripper is used by the Client to drive HTTP requests. If not
+ // provided, DefaultRoundTripper will be used.
+ RoundTripper http.RoundTripper
+}
+
+func (cfg *Config) roundTripper() http.RoundTripper {
+ if cfg.RoundTripper == nil {
+ return DefaultRoundTripper
+ }
+ return cfg.RoundTripper
+}
+
+// Client is the interface for an API client.
+type Client interface {
+ URL(ep string, args map[string]string) *url.URL
+ Do(context.Context, *http.Request) (*http.Response, []byte, error)
+}
+
+// NewClient returns a new Client.
+//
+// It is safe to use the returned Client from multiple goroutines.
+func NewClient(cfg Config) (Client, error) {
+ u, err := url.Parse(cfg.Address)
+ if err != nil {
+ return nil, err
+ }
+ u.Path = strings.TrimRight(u.Path, "/")
+
+ return &httpClient{
+ endpoint: u,
+ client: http.Client{Transport: cfg.roundTripper()},
+ }, nil
+}
+
+type httpClient struct {
+ endpoint *url.URL
+ client http.Client
+}
+
+func (c *httpClient) URL(ep string, args map[string]string) *url.URL {
+ p := path.Join(c.endpoint.Path, ep)
+
+ for arg, val := range args {
+ arg = ":" + arg
+ p = strings.Replace(p, arg, val, -1)
+ }
+
+ u := *c.endpoint
+ u.Path = p
+
+ return &u
+}
+
+func (c *httpClient) Do(ctx context.Context, req *http.Request) (*http.Response, []byte, error) {
+ if ctx != nil {
+ req = req.WithContext(ctx)
+ }
+ resp, err := c.client.Do(req)
+ defer func() {
+ if resp != nil {
+ resp.Body.Close()
+ }
+ }()
+
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var body []byte
+ done := make(chan struct{})
+ go func() {
+ body, err = ioutil.ReadAll(resp.Body)
+ close(done)
+ }()
+
+ select {
+ case <-ctx.Done():
+ err = resp.Body.Close()
+ <-done
+ if err == nil {
+ err = ctx.Err()
+ }
+ case <-done:
+ }
+
+ return resp, body, err
+}
--- /dev/null
+See [](https://godoc.org/github.com/prometheus/client_golang/prometheus).
--- /dev/null
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+// Collector is the interface implemented by anything that can be used by
+// Prometheus to collect metrics. A Collector has to be registered for
+// collection. See Registerer.Register.
+//
+// The stock metrics provided by this package (Gauge, Counter, Summary,
+// Histogram, Untyped) are also Collectors (which only ever collect one metric,
+// namely itself). An implementer of Collector may, however, collect multiple
+// metrics in a coordinated fashion and/or create metrics on the fly. Examples
+// for collectors already implemented in this library are the metric vectors
+// (i.e. collection of multiple instances of the same Metric but with different
+// label values) like GaugeVec or SummaryVec, and the ExpvarCollector.
+type Collector interface {
+ // Describe sends the super-set of all possible descriptors of metrics
+ // collected by this Collector to the provided channel and returns once
+ // the last descriptor has been sent. The sent descriptors fulfill the
+ // consistency and uniqueness requirements described in the Desc
+ // documentation. (It is valid if one and the same Collector sends
+ // duplicate descriptors. Those duplicates are simply ignored. However,
+ // two different Collectors must not send duplicate descriptors.) This
+ // method idempotently sends the same descriptors throughout the
+ // lifetime of the Collector. If a Collector encounters an error while
+ // executing this method, it must send an invalid descriptor (created
+ // with NewInvalidDesc) to signal the error to the registry.
+ Describe(chan<- *Desc)
+ // Collect is called by the Prometheus registry when collecting
+ // metrics. The implementation sends each collected metric via the
+ // provided channel and returns once the last metric has been sent. The
+ // descriptor of each sent metric is one of those returned by
+ // Describe. Returned metrics that share the same descriptor must differ
+ // in their variable label values. This method may be called
+ // concurrently and must therefore be implemented in a concurrency safe
+ // way. Blocking occurs at the expense of total performance of rendering
+ // all registered metrics. Ideally, Collector implementations support
+ // concurrent readers.
+ Collect(chan<- Metric)
+}
+
+// selfCollector implements Collector for a single Metric so that the Metric
+// collects itself. Add it as an anonymous field to a struct that implements
+// Metric, and call init with the Metric itself as an argument.
+type selfCollector struct {
+ self Metric
+}
+
+// init provides the selfCollector with a reference to the metric it is supposed
+// to collect. It is usually called within the factory function to create a
+// metric. See example.
+func (c *selfCollector) init(self Metric) {
+ c.self = self
+}
+
+// Describe implements Collector.
+func (c *selfCollector) Describe(ch chan<- *Desc) {
+ ch <- c.self.Desc()
+}
+
+// Collect implements Collector.
+func (c *selfCollector) Collect(ch chan<- Metric) {
+ ch <- c.self
+}
--- /dev/null
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "errors"
+ "math"
+ "sync/atomic"
+
+ dto "github.com/prometheus/client_model/go"
+)
+
+// Counter is a Metric that represents a single numerical value that only ever
+// goes up. That implies that it cannot be used to count items whose number can
+// also go down, e.g. the number of currently running goroutines. Those
+// "counters" are represented by Gauges.
+//
+// A Counter is typically used to count requests served, tasks completed, errors
+// occurred, etc.
+//
+// To create Counter instances, use NewCounter.
+type Counter interface {
+ Metric
+ Collector
+
+ // Inc increments the counter by 1. Use Add to increment it by arbitrary
+ // non-negative values.
+ Inc()
+ // Add adds the given value to the counter. It panics if the value is <
+ // 0.
+ Add(float64)
+}
+
+// CounterOpts is an alias for Opts. See there for doc comments.
+type CounterOpts Opts
+
+// NewCounter creates a new Counter based on the provided CounterOpts.
+//
+// The returned implementation tracks the counter value in two separate
+// variables, a float64 and a uint64. The latter is used to track calls of the
+// Inc method and calls of the Add method with a value that can be represented
+// as a uint64. This allows atomic increments of the counter with optimal
+// performance. (It is common to have an Inc call in very hot execution paths.)
+// Both internal tracking values are added up in the Write method. This has to
+// be taken into account when it comes to precision and overflow behavior.
+func NewCounter(opts CounterOpts) Counter {
+ desc := NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ nil,
+ opts.ConstLabels,
+ )
+ result := &counter{desc: desc, labelPairs: desc.constLabelPairs}
+ result.init(result) // Init self-collection.
+ return result
+}
+
+type counter struct {
+ // valBits contains the bits of the represented float64 value, while
+ // valInt stores values that are exact integers. Both have to go first
+ // in the struct to guarantee alignment for atomic operations.
+ // http://golang.org/pkg/sync/atomic/#pkg-note-BUG
+ valBits uint64
+ valInt uint64
+
+ selfCollector
+ desc *Desc
+
+ labelPairs []*dto.LabelPair
+}
+
+func (c *counter) Desc() *Desc {
+ return c.desc
+}
+
+func (c *counter) Add(v float64) {
+ if v < 0 {
+ panic(errors.New("counter cannot decrease in value"))
+ }
+ ival := uint64(v)
+ if float64(ival) == v {
+ atomic.AddUint64(&c.valInt, ival)
+ return
+ }
+
+ for {
+ oldBits := atomic.LoadUint64(&c.valBits)
+ newBits := math.Float64bits(math.Float64frombits(oldBits) + v)
+ if atomic.CompareAndSwapUint64(&c.valBits, oldBits, newBits) {
+ return
+ }
+ }
+}
+
+func (c *counter) Inc() {
+ atomic.AddUint64(&c.valInt, 1)
+}
+
+func (c *counter) Write(out *dto.Metric) error {
+ fval := math.Float64frombits(atomic.LoadUint64(&c.valBits))
+ ival := atomic.LoadUint64(&c.valInt)
+ val := fval + float64(ival)
+
+ return populateMetric(CounterValue, val, c.labelPairs, out)
+}
+
+// CounterVec is a Collector that bundles a set of Counters that all share the
+// same Desc, but have different values for their variable labels. This is used
+// if you want to count the same thing partitioned by various dimensions
+// (e.g. number of HTTP requests, partitioned by response code and
+// method). Create instances with NewCounterVec.
+type CounterVec struct {
+ *metricVec
+}
+
+// NewCounterVec creates a new CounterVec based on the provided CounterOpts and
+// partitioned by the given label names.
+func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
+ desc := NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ labelNames,
+ opts.ConstLabels,
+ )
+ return &CounterVec{
+ metricVec: newMetricVec(desc, func(lvs ...string) Metric {
+ if len(lvs) != len(desc.variableLabels) {
+ panic(errInconsistentCardinality)
+ }
+ result := &counter{desc: desc, labelPairs: makeLabelPairs(desc, lvs)}
+ result.init(result) // Init self-collection.
+ return result
+ }),
+ }
+}
+
+// GetMetricWithLabelValues returns the Counter for the given slice of label
+// values (same order as the VariableLabels in Desc). If that combination of
+// label values is accessed for the first time, a new Counter is created.
+//
+// It is possible to call this method without using the returned Counter to only
+// create the new Counter but leave it at its starting value 0. See also the
+// SummaryVec example.
+//
+// Keeping the Counter for later use is possible (and should be considered if
+// performance is critical), but keep in mind that Reset, DeleteLabelValues and
+// Delete can be used to delete the Counter from the CounterVec. In that case,
+// the Counter will still exist, but it will not be exported anymore, even if a
+// Counter with the same label values is created later.
+//
+// An error is returned if the number of label values is not the same as the
+// number of VariableLabels in Desc (minus any curried labels).
+//
+// Note that for more than one label value, this method is prone to mistakes
+// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
+// an alternative to avoid that type of mistake. For higher label numbers, the
+// latter has a much more readable (albeit more verbose) syntax, but it comes
+// with a performance overhead (for creating and processing the Labels map).
+// See also the GaugeVec example.
+func (v *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) {
+ metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
+ if metric != nil {
+ return metric.(Counter), err
+ }
+ return nil, err
+}
+
+// GetMetricWith returns the Counter for the given Labels map (the label names
+// must match those of the VariableLabels in Desc). If that label map is
+// accessed for the first time, a new Counter is created. Implications of
+// creating a Counter without using it and keeping the Counter for later use are
+// the same as for GetMetricWithLabelValues.
+//
+// An error is returned if the number and names of the Labels are inconsistent
+// with those of the VariableLabels in Desc (minus any curried labels).
+//
+// This method is used for the same purpose as
+// GetMetricWithLabelValues(...string). See there for pros and cons of the two
+// methods.
+func (v *CounterVec) GetMetricWith(labels Labels) (Counter, error) {
+ metric, err := v.metricVec.getMetricWith(labels)
+ if metric != nil {
+ return metric.(Counter), err
+ }
+ return nil, err
+}
+
+// WithLabelValues works as GetMetricWithLabelValues, but panics where
+// GetMetricWithLabelValues would have returned an error. Not returning an
+// error allows shortcuts like
+// myVec.WithLabelValues("404", "GET").Add(42)
+func (v *CounterVec) WithLabelValues(lvs ...string) Counter {
+ c, err := v.GetMetricWithLabelValues(lvs...)
+ if err != nil {
+ panic(err)
+ }
+ return c
+}
+
+// With works as GetMetricWith, but panics where GetMetricWithLabels would have
+// returned an error. Not returning an error allows shortcuts like
+// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42)
+func (v *CounterVec) With(labels Labels) Counter {
+ c, err := v.GetMetricWith(labels)
+ if err != nil {
+ panic(err)
+ }
+ return c
+}
+
+// CurryWith returns a vector curried with the provided labels, i.e. the
+// returned vector has those labels pre-set for all labeled operations performed
+// on it. The cardinality of the curried vector is reduced accordingly. The
+// order of the remaining labels stays the same (just with the curried labels
+// taken out of the sequence – which is relevant for the
+// (GetMetric)WithLabelValues methods). It is possible to curry a curried
+// vector, but only with labels not yet used for currying before.
+//
+// The metrics contained in the CounterVec are shared between the curried and
+// uncurried vectors. They are just accessed differently. Curried and uncurried
+// vectors behave identically in terms of collection. Only one must be
+// registered with a given registry (usually the uncurried version). The Reset
+// method deletes all metrics, even if called on a curried vector.
+func (v *CounterVec) CurryWith(labels Labels) (*CounterVec, error) {
+ vec, err := v.curryWith(labels)
+ if vec != nil {
+ return &CounterVec{vec}, err
+ }
+ return nil, err
+}
+
+// MustCurryWith works as CurryWith but panics where CurryWith would have
+// returned an error.
+func (v *CounterVec) MustCurryWith(labels Labels) *CounterVec {
+ vec, err := v.CurryWith(labels)
+ if err != nil {
+ panic(err)
+ }
+ return vec
+}
+
+// CounterFunc is a Counter whose value is determined at collect time by calling a
+// provided function.
+//
+// To create CounterFunc instances, use NewCounterFunc.
+type CounterFunc interface {
+ Metric
+ Collector
+}
+
+// NewCounterFunc creates a new CounterFunc based on the provided
+// CounterOpts. The value reported is determined by calling the given function
+// from within the Write method. Take into account that metric collection may
+// happen concurrently. If that results in concurrent calls to Write, like in
+// the case where a CounterFunc is directly registered with Prometheus, the
+// provided function must be concurrency-safe. The function should also honor
+// the contract for a Counter (values only go up, not down), but compliance will
+// not be checked.
+func NewCounterFunc(opts CounterOpts, function func() float64) CounterFunc {
+ return newValueFunc(NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ nil,
+ opts.ConstLabels,
+ ), CounterValue, function)
+}
--- /dev/null
+// Copyright 2016 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "errors"
+ "fmt"
+ "sort"
+ "strings"
+
+ "github.com/golang/protobuf/proto"
+ "github.com/prometheus/common/model"
+
+ dto "github.com/prometheus/client_model/go"
+)
+
+// Desc is the descriptor used by every Prometheus Metric. It is essentially
+// the immutable meta-data of a Metric. The normal Metric implementations
+// included in this package manage their Desc under the hood. Users only have to
+// deal with Desc if they use advanced features like the ExpvarCollector or
+// custom Collectors and Metrics.
+//
+// Descriptors registered with the same registry have to fulfill certain
+// consistency and uniqueness criteria if they share the same fully-qualified
+// name: They must have the same help string and the same label names (aka label
+// dimensions) in each, constLabels and variableLabels, but they must differ in
+// the values of the constLabels.
+//
+// Descriptors that share the same fully-qualified names and the same label
+// values of their constLabels are considered equal.
+//
+// Use NewDesc to create new Desc instances.
+type Desc struct {
+ // fqName has been built from Namespace, Subsystem, and Name.
+ fqName string
+ // help provides some helpful information about this metric.
+ help string
+ // constLabelPairs contains precalculated DTO label pairs based on
+ // the constant labels.
+ constLabelPairs []*dto.LabelPair
+ // VariableLabels contains names of labels for which the metric
+ // maintains variable values.
+ variableLabels []string
+ // id is a hash of the values of the ConstLabels and fqName. This
+ // must be unique among all registered descriptors and can therefore be
+ // used as an identifier of the descriptor.
+ id uint64
+ // dimHash is a hash of the label names (preset and variable) and the
+ // Help string. Each Desc with the same fqName must have the same
+ // dimHash.
+ dimHash uint64
+ // err is an error that occurred during construction. It is reported on
+ // registration time.
+ err error
+}
+
+// NewDesc allocates and initializes a new Desc. Errors are recorded in the Desc
+// and will be reported on registration time. variableLabels and constLabels can
+// be nil if no such labels should be set. fqName and help must not be empty.
+//
+// variableLabels only contain the label names. Their label values are variable
+// and therefore not part of the Desc. (They are managed within the Metric.)
+//
+// For constLabels, the label values are constant. Therefore, they are fully
+// specified in the Desc. See the Collector example for a usage pattern.
+func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *Desc {
+ d := &Desc{
+ fqName: fqName,
+ help: help,
+ variableLabels: variableLabels,
+ }
+ if help == "" {
+ d.err = errors.New("empty help string")
+ return d
+ }
+ if !model.IsValidMetricName(model.LabelValue(fqName)) {
+ d.err = fmt.Errorf("%q is not a valid metric name", fqName)
+ return d
+ }
+ // labelValues contains the label values of const labels (in order of
+ // their sorted label names) plus the fqName (at position 0).
+ labelValues := make([]string, 1, len(constLabels)+1)
+ labelValues[0] = fqName
+ labelNames := make([]string, 0, len(constLabels)+len(variableLabels))
+ labelNameSet := map[string]struct{}{}
+ // First add only the const label names and sort them...
+ for labelName := range constLabels {
+ if !checkLabelName(labelName) {
+ d.err = fmt.Errorf("%q is not a valid label name", labelName)
+ return d
+ }
+ labelNames = append(labelNames, labelName)
+ labelNameSet[labelName] = struct{}{}
+ }
+ sort.Strings(labelNames)
+ // ... so that we can now add const label values in the order of their names.
+ for _, labelName := range labelNames {
+ labelValues = append(labelValues, constLabels[labelName])
+ }
+ // Validate the const label values. They can't have a wrong cardinality, so
+ // use in len(labelValues) as expectedNumberOfValues.
+ if err := validateLabelValues(labelValues, len(labelValues)); err != nil {
+ d.err = err
+ return d
+ }
+ // Now add the variable label names, but prefix them with something that
+ // cannot be in a regular label name. That prevents matching the label
+ // dimension with a different mix between preset and variable labels.
+ for _, labelName := range variableLabels {
+ if !checkLabelName(labelName) {
+ d.err = fmt.Errorf("%q is not a valid label name", labelName)
+ return d
+ }
+ labelNames = append(labelNames, "$"+labelName)
+ labelNameSet[labelName] = struct{}{}
+ }
+ if len(labelNames) != len(labelNameSet) {
+ d.err = errors.New("duplicate label names")
+ return d
+ }
+
+ vh := hashNew()
+ for _, val := range labelValues {
+ vh = hashAdd(vh, val)
+ vh = hashAddByte(vh, separatorByte)
+ }
+ d.id = vh
+ // Sort labelNames so that order doesn't matter for the hash.
+ sort.Strings(labelNames)
+ // Now hash together (in this order) the help string and the sorted
+ // label names.
+ lh := hashNew()
+ lh = hashAdd(lh, help)
+ lh = hashAddByte(lh, separatorByte)
+ for _, labelName := range labelNames {
+ lh = hashAdd(lh, labelName)
+ lh = hashAddByte(lh, separatorByte)
+ }
+ d.dimHash = lh
+
+ d.constLabelPairs = make([]*dto.LabelPair, 0, len(constLabels))
+ for n, v := range constLabels {
+ d.constLabelPairs = append(d.constLabelPairs, &dto.LabelPair{
+ Name: proto.String(n),
+ Value: proto.String(v),
+ })
+ }
+ sort.Sort(LabelPairSorter(d.constLabelPairs))
+ return d
+}
+
+// NewInvalidDesc returns an invalid descriptor, i.e. a descriptor with the
+// provided error set. If a collector returning such a descriptor is registered,
+// registration will fail with the provided error. NewInvalidDesc can be used by
+// a Collector to signal inability to describe itself.
+func NewInvalidDesc(err error) *Desc {
+ return &Desc{
+ err: err,
+ }
+}
+
+func (d *Desc) String() string {
+ lpStrings := make([]string, 0, len(d.constLabelPairs))
+ for _, lp := range d.constLabelPairs {
+ lpStrings = append(
+ lpStrings,
+ fmt.Sprintf("%s=%q", lp.GetName(), lp.GetValue()),
+ )
+ }
+ return fmt.Sprintf(
+ "Desc{fqName: %q, help: %q, constLabels: {%s}, variableLabels: %v}",
+ d.fqName,
+ d.help,
+ strings.Join(lpStrings, ","),
+ d.variableLabels,
+ )
+}
--- /dev/null
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package prometheus is the core instrumentation package. It provides metrics
+// primitives to instrument code for monitoring. It also offers a registry for
+// metrics. Sub-packages allow to expose the registered metrics via HTTP
+// (package promhttp) or push them to a Pushgateway (package push). There is
+// also a sub-package promauto, which provides metrics constructors with
+// automatic registration.
+//
+// All exported functions and methods are safe to be used concurrently unless
+// specified otherwise.
+//
+// A Basic Example
+//
+// As a starting point, a very basic usage example:
+//
+// package main
+//
+// import (
+// "log"
+// "net/http"
+//
+// "github.com/prometheus/client_golang/prometheus"
+// "github.com/prometheus/client_golang/prometheus/promhttp"
+// )
+//
+// var (
+// cpuTemp = prometheus.NewGauge(prometheus.GaugeOpts{
+// Name: "cpu_temperature_celsius",
+// Help: "Current temperature of the CPU.",
+// })
+// hdFailures = prometheus.NewCounterVec(
+// prometheus.CounterOpts{
+// Name: "hd_errors_total",
+// Help: "Number of hard-disk errors.",
+// },
+// []string{"device"},
+// )
+// )
+//
+// func init() {
+// // Metrics have to be registered to be exposed:
+// prometheus.MustRegister(cpuTemp)
+// prometheus.MustRegister(hdFailures)
+// }
+//
+// func main() {
+// cpuTemp.Set(65.3)
+// hdFailures.With(prometheus.Labels{"device":"/dev/sda"}).Inc()
+//
+// // The Handler function provides a default handler to expose metrics
+// // via an HTTP server. "/metrics" is the usual endpoint for that.
+// http.Handle("/metrics", promhttp.Handler())
+// log.Fatal(http.ListenAndServe(":8080", nil))
+// }
+//
+//
+// This is a complete program that exports two metrics, a Gauge and a Counter,
+// the latter with a label attached to turn it into a (one-dimensional) vector.
+//
+// Metrics
+//
+// The number of exported identifiers in this package might appear a bit
+// overwhelming. However, in addition to the basic plumbing shown in the example
+// above, you only need to understand the different metric types and their
+// vector versions for basic usage. Furthermore, if you are not concerned with
+// fine-grained control of when and how to register metrics with the registry,
+// have a look at the promauto package, which will effectively allow you to
+// ignore registration altogether in simple cases.
+//
+// Above, you have already touched the Counter and the Gauge. There are two more
+// advanced metric types: the Summary and Histogram. A more thorough description
+// of those four metric types can be found in the Prometheus docs:
+// https://prometheus.io/docs/concepts/metric_types/
+//
+// A fifth "type" of metric is Untyped. It behaves like a Gauge, but signals the
+// Prometheus server not to assume anything about its type.
+//
+// In addition to the fundamental metric types Gauge, Counter, Summary,
+// Histogram, and Untyped, a very important part of the Prometheus data model is
+// the partitioning of samples along dimensions called labels, which results in
+// metric vectors. The fundamental types are GaugeVec, CounterVec, SummaryVec,
+// HistogramVec, and UntypedVec.
+//
+// While only the fundamental metric types implement the Metric interface, both
+// the metrics and their vector versions implement the Collector interface. A
+// Collector manages the collection of a number of Metrics, but for convenience,
+// a Metric can also “collect itself”. Note that Gauge, Counter, Summary,
+// Histogram, and Untyped are interfaces themselves while GaugeVec, CounterVec,
+// SummaryVec, HistogramVec, and UntypedVec are not.
+//
+// To create instances of Metrics and their vector versions, you need a suitable
+// …Opts struct, i.e. GaugeOpts, CounterOpts, SummaryOpts, HistogramOpts, or
+// UntypedOpts.
+//
+// Custom Collectors and constant Metrics
+//
+// While you could create your own implementations of Metric, most likely you
+// will only ever implement the Collector interface on your own. At a first
+// glance, a custom Collector seems handy to bundle Metrics for common
+// registration (with the prime example of the different metric vectors above,
+// which bundle all the metrics of the same name but with different labels).
+//
+// There is a more involved use case, too: If you already have metrics
+// available, created outside of the Prometheus context, you don't need the
+// interface of the various Metric types. You essentially want to mirror the
+// existing numbers into Prometheus Metrics during collection. An own
+// implementation of the Collector interface is perfect for that. You can create
+// Metric instances “on the fly” using NewConstMetric, NewConstHistogram, and
+// NewConstSummary (and their respective Must… versions). That will happen in
+// the Collect method. The Describe method has to return separate Desc
+// instances, representative of the “throw-away” metrics to be created later.
+// NewDesc comes in handy to create those Desc instances.
+//
+// The Collector example illustrates the use case. You can also look at the
+// source code of the processCollector (mirroring process metrics), the
+// goCollector (mirroring Go metrics), or the expvarCollector (mirroring expvar
+// metrics) as examples that are used in this package itself.
+//
+// If you just need to call a function to get a single float value to collect as
+// a metric, GaugeFunc, CounterFunc, or UntypedFunc might be interesting
+// shortcuts.
+//
+// Advanced Uses of the Registry
+//
+// While MustRegister is the by far most common way of registering a Collector,
+// sometimes you might want to handle the errors the registration might cause.
+// As suggested by the name, MustRegister panics if an error occurs. With the
+// Register function, the error is returned and can be handled.
+//
+// An error is returned if the registered Collector is incompatible or
+// inconsistent with already registered metrics. The registry aims for
+// consistency of the collected metrics according to the Prometheus data model.
+// Inconsistencies are ideally detected at registration time, not at collect
+// time. The former will usually be detected at start-up time of a program,
+// while the latter will only happen at scrape time, possibly not even on the
+// first scrape if the inconsistency only becomes relevant later. That is the
+// main reason why a Collector and a Metric have to describe themselves to the
+// registry.
+//
+// So far, everything we did operated on the so-called default registry, as it
+// can be found in the global DefaultRegisterer variable. With NewRegistry, you
+// can create a custom registry, or you can even implement the Registerer or
+// Gatherer interfaces yourself. The methods Register and Unregister work in the
+// same way on a custom registry as the global functions Register and Unregister
+// on the default registry.
+//
+// There are a number of uses for custom registries: You can use registries with
+// special properties, see NewPedanticRegistry. You can avoid global state, as
+// it is imposed by the DefaultRegisterer. You can use multiple registries at
+// the same time to expose different metrics in different ways. You can use
+// separate registries for testing purposes.
+//
+// Also note that the DefaultRegisterer comes registered with a Collector for Go
+// runtime metrics (via NewGoCollector) and a Collector for process metrics (via
+// NewProcessCollector). With a custom registry, you are in control and decide
+// yourself about the Collectors to register.
+//
+// HTTP Exposition
+//
+// The Registry implements the Gatherer interface. The caller of the Gather
+// method can then expose the gathered metrics in some way. Usually, the metrics
+// are served via HTTP on the /metrics endpoint. That's happening in the example
+// above. The tools to expose metrics via HTTP are in the promhttp sub-package.
+// (The top-level functions in the prometheus package are deprecated.)
+//
+// Pushing to the Pushgateway
+//
+// Function for pushing to the Pushgateway can be found in the push sub-package.
+//
+// Graphite Bridge
+//
+// Functions and examples to push metrics from a Gatherer to Graphite can be
+// found in the graphite sub-package.
+//
+// Other Means of Exposition
+//
+// More ways of exposing metrics can easily be added by following the approaches
+// of the existing implementations.
+package prometheus
--- /dev/null
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "encoding/json"
+ "expvar"
+)
+
+type expvarCollector struct {
+ exports map[string]*Desc
+}
+
+// NewExpvarCollector returns a newly allocated expvar Collector that still has
+// to be registered with a Prometheus registry.
+//
+// An expvar Collector collects metrics from the expvar interface. It provides a
+// quick way to expose numeric values that are already exported via expvar as
+// Prometheus metrics. Note that the data models of expvar and Prometheus are
+// fundamentally different, and that the expvar Collector is inherently slower
+// than native Prometheus metrics. Thus, the expvar Collector is probably great
+// for experiments and prototying, but you should seriously consider a more
+// direct implementation of Prometheus metrics for monitoring production
+// systems.
+//
+// The exports map has the following meaning:
+//
+// The keys in the map correspond to expvar keys, i.e. for every expvar key you
+// want to export as Prometheus metric, you need an entry in the exports
+// map. The descriptor mapped to each key describes how to export the expvar
+// value. It defines the name and the help string of the Prometheus metric
+// proxying the expvar value. The type will always be Untyped.
+//
+// For descriptors without variable labels, the expvar value must be a number or
+// a bool. The number is then directly exported as the Prometheus sample
+// value. (For a bool, 'false' translates to 0 and 'true' to 1). Expvar values
+// that are not numbers or bools are silently ignored.
+//
+// If the descriptor has one variable label, the expvar value must be an expvar
+// map. The keys in the expvar map become the various values of the one
+// Prometheus label. The values in the expvar map must be numbers or bools again
+// as above.
+//
+// For descriptors with more than one variable label, the expvar must be a
+// nested expvar map, i.e. where the values of the topmost map are maps again
+// etc. until a depth is reached that corresponds to the number of labels. The
+// leaves of that structure must be numbers or bools as above to serve as the
+// sample values.
+//
+// Anything that does not fit into the scheme above is silently ignored.
+func NewExpvarCollector(exports map[string]*Desc) Collector {
+ return &expvarCollector{
+ exports: exports,
+ }
+}
+
+// Describe implements Collector.
+func (e *expvarCollector) Describe(ch chan<- *Desc) {
+ for _, desc := range e.exports {
+ ch <- desc
+ }
+}
+
+// Collect implements Collector.
+func (e *expvarCollector) Collect(ch chan<- Metric) {
+ for name, desc := range e.exports {
+ var m Metric
+ expVar := expvar.Get(name)
+ if expVar == nil {
+ continue
+ }
+ var v interface{}
+ labels := make([]string, len(desc.variableLabels))
+ if err := json.Unmarshal([]byte(expVar.String()), &v); err != nil {
+ ch <- NewInvalidMetric(desc, err)
+ continue
+ }
+ var processValue func(v interface{}, i int)
+ processValue = func(v interface{}, i int) {
+ if i >= len(labels) {
+ copiedLabels := append(make([]string, 0, len(labels)), labels...)
+ switch v := v.(type) {
+ case float64:
+ m = MustNewConstMetric(desc, UntypedValue, v, copiedLabels...)
+ case bool:
+ if v {
+ m = MustNewConstMetric(desc, UntypedValue, 1, copiedLabels...)
+ } else {
+ m = MustNewConstMetric(desc, UntypedValue, 0, copiedLabels...)
+ }
+ default:
+ return
+ }
+ ch <- m
+ return
+ }
+ vm, ok := v.(map[string]interface{})
+ if !ok {
+ return
+ }
+ for lv, val := range vm {
+ labels[i] = lv
+ processValue(val, i+1)
+ }
+ }
+ processValue(v, 0)
+ }
+}
--- /dev/null
+package prometheus
+
+// Inline and byte-free variant of hash/fnv's fnv64a.
+
+const (
+ offset64 = 14695981039346656037
+ prime64 = 1099511628211
+)
+
+// hashNew initializies a new fnv64a hash value.
+func hashNew() uint64 {
+ return offset64
+}
+
+// hashAdd adds a string to a fnv64a hash value, returning the updated hash.
+func hashAdd(h uint64, s string) uint64 {
+ for i := 0; i < len(s); i++ {
+ h ^= uint64(s[i])
+ h *= prime64
+ }
+ return h
+}
+
+// hashAddByte adds a byte to a fnv64a hash value, returning the updated hash.
+func hashAddByte(h uint64, b byte) uint64 {
+ h ^= uint64(b)
+ h *= prime64
+ return h
+}
--- /dev/null
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "math"
+ "sync/atomic"
+ "time"
+
+ dto "github.com/prometheus/client_model/go"
+)
+
+// Gauge is a Metric that represents a single numerical value that can
+// arbitrarily go up and down.
+//
+// A Gauge is typically used for measured values like temperatures or current
+// memory usage, but also "counts" that can go up and down, like the number of
+// running goroutines.
+//
+// To create Gauge instances, use NewGauge.
+type Gauge interface {
+ Metric
+ Collector
+
+ // Set sets the Gauge to an arbitrary value.
+ Set(float64)
+ // Inc increments the Gauge by 1. Use Add to increment it by arbitrary
+ // values.
+ Inc()
+ // Dec decrements the Gauge by 1. Use Sub to decrement it by arbitrary
+ // values.
+ Dec()
+ // Add adds the given value to the Gauge. (The value can be negative,
+ // resulting in a decrease of the Gauge.)
+ Add(float64)
+ // Sub subtracts the given value from the Gauge. (The value can be
+ // negative, resulting in an increase of the Gauge.)
+ Sub(float64)
+
+ // SetToCurrentTime sets the Gauge to the current Unix time in seconds.
+ SetToCurrentTime()
+}
+
+// GaugeOpts is an alias for Opts. See there for doc comments.
+type GaugeOpts Opts
+
+// NewGauge creates a new Gauge based on the provided GaugeOpts.
+//
+// The returned implementation is optimized for a fast Set method. If you have a
+// choice for managing the value of a Gauge via Set vs. Inc/Dec/Add/Sub, pick
+// the former. For example, the Inc method of the returned Gauge is slower than
+// the Inc method of a Counter returned by NewCounter. This matches the typical
+// scenarios for Gauges and Counters, where the former tends to be Set-heavy and
+// the latter Inc-heavy.
+func NewGauge(opts GaugeOpts) Gauge {
+ desc := NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ nil,
+ opts.ConstLabels,
+ )
+ result := &gauge{desc: desc, labelPairs: desc.constLabelPairs}
+ result.init(result) // Init self-collection.
+ return result
+}
+
+type gauge struct {
+ // valBits contains the bits of the represented float64 value. It has
+ // to go first in the struct to guarantee alignment for atomic
+ // operations. http://golang.org/pkg/sync/atomic/#pkg-note-BUG
+ valBits uint64
+
+ selfCollector
+
+ desc *Desc
+ labelPairs []*dto.LabelPair
+}
+
+func (g *gauge) Desc() *Desc {
+ return g.desc
+}
+
+func (g *gauge) Set(val float64) {
+ atomic.StoreUint64(&g.valBits, math.Float64bits(val))
+}
+
+func (g *gauge) SetToCurrentTime() {
+ g.Set(float64(time.Now().UnixNano()) / 1e9)
+}
+
+func (g *gauge) Inc() {
+ g.Add(1)
+}
+
+func (g *gauge) Dec() {
+ g.Add(-1)
+}
+
+func (g *gauge) Add(val float64) {
+ for {
+ oldBits := atomic.LoadUint64(&g.valBits)
+ newBits := math.Float64bits(math.Float64frombits(oldBits) + val)
+ if atomic.CompareAndSwapUint64(&g.valBits, oldBits, newBits) {
+ return
+ }
+ }
+}
+
+func (g *gauge) Sub(val float64) {
+ g.Add(val * -1)
+}
+
+func (g *gauge) Write(out *dto.Metric) error {
+ val := math.Float64frombits(atomic.LoadUint64(&g.valBits))
+ return populateMetric(GaugeValue, val, g.labelPairs, out)
+}
+
+// GaugeVec is a Collector that bundles a set of Gauges that all share the same
+// Desc, but have different values for their variable labels. This is used if
+// you want to count the same thing partitioned by various dimensions
+// (e.g. number of operations queued, partitioned by user and operation
+// type). Create instances with NewGaugeVec.
+type GaugeVec struct {
+ *metricVec
+}
+
+// NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and
+// partitioned by the given label names.
+func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
+ desc := NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ labelNames,
+ opts.ConstLabels,
+ )
+ return &GaugeVec{
+ metricVec: newMetricVec(desc, func(lvs ...string) Metric {
+ if len(lvs) != len(desc.variableLabels) {
+ panic(errInconsistentCardinality)
+ }
+ result := &gauge{desc: desc, labelPairs: makeLabelPairs(desc, lvs)}
+ result.init(result) // Init self-collection.
+ return result
+ }),
+ }
+}
+
+// GetMetricWithLabelValues returns the Gauge for the given slice of label
+// values (same order as the VariableLabels in Desc). If that combination of
+// label values is accessed for the first time, a new Gauge is created.
+//
+// It is possible to call this method without using the returned Gauge to only
+// create the new Gauge but leave it at its starting value 0. See also the
+// SummaryVec example.
+//
+// Keeping the Gauge for later use is possible (and should be considered if
+// performance is critical), but keep in mind that Reset, DeleteLabelValues and
+// Delete can be used to delete the Gauge from the GaugeVec. In that case, the
+// Gauge will still exist, but it will not be exported anymore, even if a
+// Gauge with the same label values is created later. See also the CounterVec
+// example.
+//
+// An error is returned if the number of label values is not the same as the
+// number of VariableLabels in Desc (minus any curried labels).
+//
+// Note that for more than one label value, this method is prone to mistakes
+// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
+// an alternative to avoid that type of mistake. For higher label numbers, the
+// latter has a much more readable (albeit more verbose) syntax, but it comes
+// with a performance overhead (for creating and processing the Labels map).
+func (v *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) {
+ metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
+ if metric != nil {
+ return metric.(Gauge), err
+ }
+ return nil, err
+}
+
+// GetMetricWith returns the Gauge for the given Labels map (the label names
+// must match those of the VariableLabels in Desc). If that label map is
+// accessed for the first time, a new Gauge is created. Implications of
+// creating a Gauge without using it and keeping the Gauge for later use are
+// the same as for GetMetricWithLabelValues.
+//
+// An error is returned if the number and names of the Labels are inconsistent
+// with those of the VariableLabels in Desc (minus any curried labels).
+//
+// This method is used for the same purpose as
+// GetMetricWithLabelValues(...string). See there for pros and cons of the two
+// methods.
+func (v *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) {
+ metric, err := v.metricVec.getMetricWith(labels)
+ if metric != nil {
+ return metric.(Gauge), err
+ }
+ return nil, err
+}
+
+// WithLabelValues works as GetMetricWithLabelValues, but panics where
+// GetMetricWithLabelValues would have returned an error. Not returning an
+// error allows shortcuts like
+// myVec.WithLabelValues("404", "GET").Add(42)
+func (v *GaugeVec) WithLabelValues(lvs ...string) Gauge {
+ g, err := v.GetMetricWithLabelValues(lvs...)
+ if err != nil {
+ panic(err)
+ }
+ return g
+}
+
+// With works as GetMetricWith, but panics where GetMetricWithLabels would have
+// returned an error. Not returning an error allows shortcuts like
+// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42)
+func (v *GaugeVec) With(labels Labels) Gauge {
+ g, err := v.GetMetricWith(labels)
+ if err != nil {
+ panic(err)
+ }
+ return g
+}
+
+// CurryWith returns a vector curried with the provided labels, i.e. the
+// returned vector has those labels pre-set for all labeled operations performed
+// on it. The cardinality of the curried vector is reduced accordingly. The
+// order of the remaining labels stays the same (just with the curried labels
+// taken out of the sequence – which is relevant for the
+// (GetMetric)WithLabelValues methods). It is possible to curry a curried
+// vector, but only with labels not yet used for currying before.
+//
+// The metrics contained in the GaugeVec are shared between the curried and
+// uncurried vectors. They are just accessed differently. Curried and uncurried
+// vectors behave identically in terms of collection. Only one must be
+// registered with a given registry (usually the uncurried version). The Reset
+// method deletes all metrics, even if called on a curried vector.
+func (v *GaugeVec) CurryWith(labels Labels) (*GaugeVec, error) {
+ vec, err := v.curryWith(labels)
+ if vec != nil {
+ return &GaugeVec{vec}, err
+ }
+ return nil, err
+}
+
+// MustCurryWith works as CurryWith but panics where CurryWith would have
+// returned an error.
+func (v *GaugeVec) MustCurryWith(labels Labels) *GaugeVec {
+ vec, err := v.CurryWith(labels)
+ if err != nil {
+ panic(err)
+ }
+ return vec
+}
+
+// GaugeFunc is a Gauge whose value is determined at collect time by calling a
+// provided function.
+//
+// To create GaugeFunc instances, use NewGaugeFunc.
+type GaugeFunc interface {
+ Metric
+ Collector
+}
+
+// NewGaugeFunc creates a new GaugeFunc based on the provided GaugeOpts. The
+// value reported is determined by calling the given function from within the
+// Write method. Take into account that metric collection may happen
+// concurrently. If that results in concurrent calls to Write, like in the case
+// where a GaugeFunc is directly registered with Prometheus, the provided
+// function must be concurrency-safe.
+func NewGaugeFunc(opts GaugeOpts, function func() float64) GaugeFunc {
+ return newValueFunc(NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ nil,
+ opts.ConstLabels,
+ ), GaugeValue, function)
+}
--- /dev/null
+package prometheus
+
+import (
+ "fmt"
+ "runtime"
+ "runtime/debug"
+ "time"
+)
+
+type goCollector struct {
+ goroutinesDesc *Desc
+ threadsDesc *Desc
+ gcDesc *Desc
+ goInfoDesc *Desc
+
+ // metrics to describe and collect
+ metrics memStatsMetrics
+}
+
+// NewGoCollector returns a collector which exports metrics about the current
+// go process.
+func NewGoCollector() Collector {
+ return &goCollector{
+ goroutinesDesc: NewDesc(
+ "go_goroutines",
+ "Number of goroutines that currently exist.",
+ nil, nil),
+ threadsDesc: NewDesc(
+ "go_threads",
+ "Number of OS threads created.",
+ nil, nil),
+ gcDesc: NewDesc(
+ "go_gc_duration_seconds",
+ "A summary of the GC invocation durations.",
+ nil, nil),
+ goInfoDesc: NewDesc(
+ "go_info",
+ "Information about the Go environment.",
+ nil, Labels{"version": runtime.Version()}),
+ metrics: memStatsMetrics{
+ {
+ desc: NewDesc(
+ memstatNamespace("alloc_bytes"),
+ "Number of bytes allocated and still in use.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.Alloc) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("alloc_bytes_total"),
+ "Total number of bytes allocated, even if freed.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.TotalAlloc) },
+ valType: CounterValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("sys_bytes"),
+ "Number of bytes obtained from system.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.Sys) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("lookups_total"),
+ "Total number of pointer lookups.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.Lookups) },
+ valType: CounterValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("mallocs_total"),
+ "Total number of mallocs.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.Mallocs) },
+ valType: CounterValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("frees_total"),
+ "Total number of frees.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.Frees) },
+ valType: CounterValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("heap_alloc_bytes"),
+ "Number of heap bytes allocated and still in use.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapAlloc) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("heap_sys_bytes"),
+ "Number of heap bytes obtained from system.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapSys) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("heap_idle_bytes"),
+ "Number of heap bytes waiting to be used.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapIdle) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("heap_inuse_bytes"),
+ "Number of heap bytes that are in use.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapInuse) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("heap_released_bytes"),
+ "Number of heap bytes released to OS.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapReleased) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("heap_objects"),
+ "Number of allocated objects.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapObjects) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("stack_inuse_bytes"),
+ "Number of bytes in use by the stack allocator.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackInuse) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("stack_sys_bytes"),
+ "Number of bytes obtained from system for stack allocator.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackSys) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("mspan_inuse_bytes"),
+ "Number of bytes in use by mspan structures.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanInuse) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("mspan_sys_bytes"),
+ "Number of bytes used for mspan structures obtained from system.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanSys) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("mcache_inuse_bytes"),
+ "Number of bytes in use by mcache structures.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheInuse) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("mcache_sys_bytes"),
+ "Number of bytes used for mcache structures obtained from system.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheSys) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("buck_hash_sys_bytes"),
+ "Number of bytes used by the profiling bucket hash table.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.BuckHashSys) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("gc_sys_bytes"),
+ "Number of bytes used for garbage collection system metadata.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.GCSys) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("other_sys_bytes"),
+ "Number of bytes used for other system allocations.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.OtherSys) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("next_gc_bytes"),
+ "Number of heap bytes when next garbage collection will take place.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.NextGC) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("last_gc_time_seconds"),
+ "Number of seconds since 1970 of last garbage collection.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.LastGC) / 1e9 },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("gc_cpu_fraction"),
+ "The fraction of this program's available CPU time used by the GC since the program started.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return ms.GCCPUFraction },
+ valType: GaugeValue,
+ },
+ },
+ }
+}
+
+func memstatNamespace(s string) string {
+ return fmt.Sprintf("go_memstats_%s", s)
+}
+
+// Describe returns all descriptions of the collector.
+func (c *goCollector) Describe(ch chan<- *Desc) {
+ ch <- c.goroutinesDesc
+ ch <- c.threadsDesc
+ ch <- c.gcDesc
+ ch <- c.goInfoDesc
+ for _, i := range c.metrics {
+ ch <- i.desc
+ }
+}
+
+// Collect returns the current state of all metrics of the collector.
+func (c *goCollector) Collect(ch chan<- Metric) {
+ ch <- MustNewConstMetric(c.goroutinesDesc, GaugeValue, float64(runtime.NumGoroutine()))
+ n, _ := runtime.ThreadCreateProfile(nil)
+ ch <- MustNewConstMetric(c.threadsDesc, GaugeValue, float64(n))
+
+ var stats debug.GCStats
+ stats.PauseQuantiles = make([]time.Duration, 5)
+ debug.ReadGCStats(&stats)
+
+ quantiles := make(map[float64]float64)
+ for idx, pq := range stats.PauseQuantiles[1:] {
+ quantiles[float64(idx+1)/float64(len(stats.PauseQuantiles)-1)] = pq.Seconds()
+ }
+ quantiles[0.0] = stats.PauseQuantiles[0].Seconds()
+ ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), float64(stats.PauseTotal.Seconds()), quantiles)
+
+ ch <- MustNewConstMetric(c.goInfoDesc, GaugeValue, 1)
+
+ ms := &runtime.MemStats{}
+ runtime.ReadMemStats(ms)
+ for _, i := range c.metrics {
+ ch <- MustNewConstMetric(i.desc, i.valType, i.eval(ms))
+ }
+}
+
+// memStatsMetrics provide description, value, and value type for memstat metrics.
+type memStatsMetrics []struct {
+ desc *Desc
+ eval func(*runtime.MemStats) float64
+ valType ValueType
+}
--- /dev/null
+// Copyright 2015 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "fmt"
+ "math"
+ "sort"
+ "sync/atomic"
+
+ "github.com/golang/protobuf/proto"
+
+ dto "github.com/prometheus/client_model/go"
+)
+
+// A Histogram counts individual observations from an event or sample stream in
+// configurable buckets. Similar to a summary, it also provides a sum of
+// observations and an observation count.
+//
+// On the Prometheus server, quantiles can be calculated from a Histogram using
+// the histogram_quantile function in the query language.
+//
+// Note that Histograms, in contrast to Summaries, can be aggregated with the
+// Prometheus query language (see the documentation for detailed
+// procedures). However, Histograms require the user to pre-define suitable
+// buckets, and they are in general less accurate. The Observe method of a
+// Histogram has a very low performance overhead in comparison with the Observe
+// method of a Summary.
+//
+// To create Histogram instances, use NewHistogram.
+type Histogram interface {
+ Metric
+ Collector
+
+ // Observe adds a single observation to the histogram.
+ Observe(float64)
+}
+
+// bucketLabel is used for the label that defines the upper bound of a
+// bucket of a histogram ("le" -> "less or equal").
+const bucketLabel = "le"
+
+// DefBuckets are the default Histogram buckets. The default buckets are
+// tailored to broadly measure the response time (in seconds) of a network
+// service. Most likely, however, you will be required to define buckets
+// customized to your use case.
+var (
+ DefBuckets = []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10}
+
+ errBucketLabelNotAllowed = fmt.Errorf(
+ "%q is not allowed as label name in histograms", bucketLabel,
+ )
+)
+
+// LinearBuckets creates 'count' buckets, each 'width' wide, where the lowest
+// bucket has an upper bound of 'start'. The final +Inf bucket is not counted
+// and not included in the returned slice. The returned slice is meant to be
+// used for the Buckets field of HistogramOpts.
+//
+// The function panics if 'count' is zero or negative.
+func LinearBuckets(start, width float64, count int) []float64 {
+ if count < 1 {
+ panic("LinearBuckets needs a positive count")
+ }
+ buckets := make([]float64, count)
+ for i := range buckets {
+ buckets[i] = start
+ start += width
+ }
+ return buckets
+}
+
+// ExponentialBuckets creates 'count' buckets, where the lowest bucket has an
+// upper bound of 'start' and each following bucket's upper bound is 'factor'
+// times the previous bucket's upper bound. The final +Inf bucket is not counted
+// and not included in the returned slice. The returned slice is meant to be
+// used for the Buckets field of HistogramOpts.
+//
+// The function panics if 'count' is 0 or negative, if 'start' is 0 or negative,
+// or if 'factor' is less than or equal 1.
+func ExponentialBuckets(start, factor float64, count int) []float64 {
+ if count < 1 {
+ panic("ExponentialBuckets needs a positive count")
+ }
+ if start <= 0 {
+ panic("ExponentialBuckets needs a positive start value")
+ }
+ if factor <= 1 {
+ panic("ExponentialBuckets needs a factor greater than 1")
+ }
+ buckets := make([]float64, count)
+ for i := range buckets {
+ buckets[i] = start
+ start *= factor
+ }
+ return buckets
+}
+
+// HistogramOpts bundles the options for creating a Histogram metric. It is
+// mandatory to set Name and Help to a non-empty string. All other fields are
+// optional and can safely be left at their zero value.
+type HistogramOpts struct {
+ // Namespace, Subsystem, and Name are components of the fully-qualified
+ // name of the Histogram (created by joining these components with
+ // "_"). Only Name is mandatory, the others merely help structuring the
+ // name. Note that the fully-qualified name of the Histogram must be a
+ // valid Prometheus metric name.
+ Namespace string
+ Subsystem string
+ Name string
+
+ // Help provides information about this Histogram. Mandatory!
+ //
+ // Metrics with the same fully-qualified name must have the same Help
+ // string.
+ Help string
+
+ // ConstLabels are used to attach fixed labels to this metric. Metrics
+ // with the same fully-qualified name must have the same label names in
+ // their ConstLabels.
+ //
+ // ConstLabels are only used rarely. In particular, do not use them to
+ // attach the same labels to all your metrics. Those use cases are
+ // better covered by target labels set by the scraping Prometheus
+ // server, or by one specific metric (e.g. a build_info or a
+ // machine_role metric). See also
+ // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels
+ ConstLabels Labels
+
+ // Buckets defines the buckets into which observations are counted. Each
+ // element in the slice is the upper inclusive bound of a bucket. The
+ // values must be sorted in strictly increasing order. There is no need
+ // to add a highest bucket with +Inf bound, it will be added
+ // implicitly. The default value is DefBuckets.
+ Buckets []float64
+}
+
+// NewHistogram creates a new Histogram based on the provided HistogramOpts. It
+// panics if the buckets in HistogramOpts are not in strictly increasing order.
+func NewHistogram(opts HistogramOpts) Histogram {
+ return newHistogram(
+ NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ nil,
+ opts.ConstLabels,
+ ),
+ opts,
+ )
+}
+
+func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogram {
+ if len(desc.variableLabels) != len(labelValues) {
+ panic(errInconsistentCardinality)
+ }
+
+ for _, n := range desc.variableLabels {
+ if n == bucketLabel {
+ panic(errBucketLabelNotAllowed)
+ }
+ }
+ for _, lp := range desc.constLabelPairs {
+ if lp.GetName() == bucketLabel {
+ panic(errBucketLabelNotAllowed)
+ }
+ }
+
+ if len(opts.Buckets) == 0 {
+ opts.Buckets = DefBuckets
+ }
+
+ h := &histogram{
+ desc: desc,
+ upperBounds: opts.Buckets,
+ labelPairs: makeLabelPairs(desc, labelValues),
+ }
+ for i, upperBound := range h.upperBounds {
+ if i < len(h.upperBounds)-1 {
+ if upperBound >= h.upperBounds[i+1] {
+ panic(fmt.Errorf(
+ "histogram buckets must be in increasing order: %f >= %f",
+ upperBound, h.upperBounds[i+1],
+ ))
+ }
+ } else {
+ if math.IsInf(upperBound, +1) {
+ // The +Inf bucket is implicit. Remove it here.
+ h.upperBounds = h.upperBounds[:i]
+ }
+ }
+ }
+ // Finally we know the final length of h.upperBounds and can make counts.
+ h.counts = make([]uint64, len(h.upperBounds))
+
+ h.init(h) // Init self-collection.
+ return h
+}
+
+type histogram struct {
+ // sumBits contains the bits of the float64 representing the sum of all
+ // observations. sumBits and count have to go first in the struct to
+ // guarantee alignment for atomic operations.
+ // http://golang.org/pkg/sync/atomic/#pkg-note-BUG
+ sumBits uint64
+ count uint64
+
+ selfCollector
+ // Note that there is no mutex required.
+
+ desc *Desc
+
+ upperBounds []float64
+ counts []uint64
+
+ labelPairs []*dto.LabelPair
+}
+
+func (h *histogram) Desc() *Desc {
+ return h.desc
+}
+
+func (h *histogram) Observe(v float64) {
+ // TODO(beorn7): For small numbers of buckets (<30), a linear search is
+ // slightly faster than the binary search. If we really care, we could
+ // switch from one search strategy to the other depending on the number
+ // of buckets.
+ //
+ // Microbenchmarks (BenchmarkHistogramNoLabels):
+ // 11 buckets: 38.3 ns/op linear - binary 48.7 ns/op
+ // 100 buckets: 78.1 ns/op linear - binary 54.9 ns/op
+ // 300 buckets: 154 ns/op linear - binary 61.6 ns/op
+ i := sort.SearchFloat64s(h.upperBounds, v)
+ if i < len(h.counts) {
+ atomic.AddUint64(&h.counts[i], 1)
+ }
+ atomic.AddUint64(&h.count, 1)
+ for {
+ oldBits := atomic.LoadUint64(&h.sumBits)
+ newBits := math.Float64bits(math.Float64frombits(oldBits) + v)
+ if atomic.CompareAndSwapUint64(&h.sumBits, oldBits, newBits) {
+ break
+ }
+ }
+}
+
+func (h *histogram) Write(out *dto.Metric) error {
+ his := &dto.Histogram{}
+ buckets := make([]*dto.Bucket, len(h.upperBounds))
+
+ his.SampleSum = proto.Float64(math.Float64frombits(atomic.LoadUint64(&h.sumBits)))
+ his.SampleCount = proto.Uint64(atomic.LoadUint64(&h.count))
+ var count uint64
+ for i, upperBound := range h.upperBounds {
+ count += atomic.LoadUint64(&h.counts[i])
+ buckets[i] = &dto.Bucket{
+ CumulativeCount: proto.Uint64(count),
+ UpperBound: proto.Float64(upperBound),
+ }
+ }
+ his.Bucket = buckets
+ out.Histogram = his
+ out.Label = h.labelPairs
+ return nil
+}
+
+// HistogramVec is a Collector that bundles a set of Histograms that all share the
+// same Desc, but have different values for their variable labels. This is used
+// if you want to count the same thing partitioned by various dimensions
+// (e.g. HTTP request latencies, partitioned by status code and method). Create
+// instances with NewHistogramVec.
+type HistogramVec struct {
+ *metricVec
+}
+
+// NewHistogramVec creates a new HistogramVec based on the provided HistogramOpts and
+// partitioned by the given label names.
+func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec {
+ desc := NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ labelNames,
+ opts.ConstLabels,
+ )
+ return &HistogramVec{
+ metricVec: newMetricVec(desc, func(lvs ...string) Metric {
+ return newHistogram(desc, opts, lvs...)
+ }),
+ }
+}
+
+// GetMetricWithLabelValues returns the Histogram for the given slice of label
+// values (same order as the VariableLabels in Desc). If that combination of
+// label values is accessed for the first time, a new Histogram is created.
+//
+// It is possible to call this method without using the returned Histogram to only
+// create the new Histogram but leave it at its starting value, a Histogram without
+// any observations.
+//
+// Keeping the Histogram for later use is possible (and should be considered if
+// performance is critical), but keep in mind that Reset, DeleteLabelValues and
+// Delete can be used to delete the Histogram from the HistogramVec. In that case, the
+// Histogram will still exist, but it will not be exported anymore, even if a
+// Histogram with the same label values is created later. See also the CounterVec
+// example.
+//
+// An error is returned if the number of label values is not the same as the
+// number of VariableLabels in Desc (minus any curried labels).
+//
+// Note that for more than one label value, this method is prone to mistakes
+// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
+// an alternative to avoid that type of mistake. For higher label numbers, the
+// latter has a much more readable (albeit more verbose) syntax, but it comes
+// with a performance overhead (for creating and processing the Labels map).
+// See also the GaugeVec example.
+func (v *HistogramVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) {
+ metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
+ if metric != nil {
+ return metric.(Observer), err
+ }
+ return nil, err
+}
+
+// GetMetricWith returns the Histogram for the given Labels map (the label names
+// must match those of the VariableLabels in Desc). If that label map is
+// accessed for the first time, a new Histogram is created. Implications of
+// creating a Histogram without using it and keeping the Histogram for later use
+// are the same as for GetMetricWithLabelValues.
+//
+// An error is returned if the number and names of the Labels are inconsistent
+// with those of the VariableLabels in Desc (minus any curried labels).
+//
+// This method is used for the same purpose as
+// GetMetricWithLabelValues(...string). See there for pros and cons of the two
+// methods.
+func (v *HistogramVec) GetMetricWith(labels Labels) (Observer, error) {
+ metric, err := v.metricVec.getMetricWith(labels)
+ if metric != nil {
+ return metric.(Observer), err
+ }
+ return nil, err
+}
+
+// WithLabelValues works as GetMetricWithLabelValues, but panics where
+// GetMetricWithLabelValues would have returned an error. Not returning an
+// error allows shortcuts like
+// myVec.WithLabelValues("404", "GET").Observe(42.21)
+func (v *HistogramVec) WithLabelValues(lvs ...string) Observer {
+ h, err := v.GetMetricWithLabelValues(lvs...)
+ if err != nil {
+ panic(err)
+ }
+ return h
+}
+
+// With works as GetMetricWith but panics where GetMetricWithLabels would have
+// returned an error. Not returning an error allows shortcuts like
+// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Observe(42.21)
+func (v *HistogramVec) With(labels Labels) Observer {
+ h, err := v.GetMetricWith(labels)
+ if err != nil {
+ panic(err)
+ }
+ return h
+}
+
+// CurryWith returns a vector curried with the provided labels, i.e. the
+// returned vector has those labels pre-set for all labeled operations performed
+// on it. The cardinality of the curried vector is reduced accordingly. The
+// order of the remaining labels stays the same (just with the curried labels
+// taken out of the sequence – which is relevant for the
+// (GetMetric)WithLabelValues methods). It is possible to curry a curried
+// vector, but only with labels not yet used for currying before.
+//
+// The metrics contained in the HistogramVec are shared between the curried and
+// uncurried vectors. They are just accessed differently. Curried and uncurried
+// vectors behave identically in terms of collection. Only one must be
+// registered with a given registry (usually the uncurried version). The Reset
+// method deletes all metrics, even if called on a curried vector.
+func (v *HistogramVec) CurryWith(labels Labels) (ObserverVec, error) {
+ vec, err := v.curryWith(labels)
+ if vec != nil {
+ return &HistogramVec{vec}, err
+ }
+ return nil, err
+}
+
+// MustCurryWith works as CurryWith but panics where CurryWith would have
+// returned an error.
+func (v *HistogramVec) MustCurryWith(labels Labels) ObserverVec {
+ vec, err := v.CurryWith(labels)
+ if err != nil {
+ panic(err)
+ }
+ return vec
+}
+
+type constHistogram struct {
+ desc *Desc
+ count uint64
+ sum float64
+ buckets map[float64]uint64
+ labelPairs []*dto.LabelPair
+}
+
+func (h *constHistogram) Desc() *Desc {
+ return h.desc
+}
+
+func (h *constHistogram) Write(out *dto.Metric) error {
+ his := &dto.Histogram{}
+ buckets := make([]*dto.Bucket, 0, len(h.buckets))
+
+ his.SampleCount = proto.Uint64(h.count)
+ his.SampleSum = proto.Float64(h.sum)
+
+ for upperBound, count := range h.buckets {
+ buckets = append(buckets, &dto.Bucket{
+ CumulativeCount: proto.Uint64(count),
+ UpperBound: proto.Float64(upperBound),
+ })
+ }
+
+ if len(buckets) > 0 {
+ sort.Sort(buckSort(buckets))
+ }
+ his.Bucket = buckets
+
+ out.Histogram = his
+ out.Label = h.labelPairs
+
+ return nil
+}
+
+// NewConstHistogram returns a metric representing a Prometheus histogram with
+// fixed values for the count, sum, and bucket counts. As those parameters
+// cannot be changed, the returned value does not implement the Histogram
+// interface (but only the Metric interface). Users of this package will not
+// have much use for it in regular operations. However, when implementing custom
+// Collectors, it is useful as a throw-away metric that is generated on the fly
+// to send it to Prometheus in the Collect method.
+//
+// buckets is a map of upper bounds to cumulative counts, excluding the +Inf
+// bucket.
+//
+// NewConstHistogram returns an error if the length of labelValues is not
+// consistent with the variable labels in Desc.
+func NewConstHistogram(
+ desc *Desc,
+ count uint64,
+ sum float64,
+ buckets map[float64]uint64,
+ labelValues ...string,
+) (Metric, error) {
+ if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil {
+ return nil, err
+ }
+ return &constHistogram{
+ desc: desc,
+ count: count,
+ sum: sum,
+ buckets: buckets,
+ labelPairs: makeLabelPairs(desc, labelValues),
+ }, nil
+}
+
+// MustNewConstHistogram is a version of NewConstHistogram that panics where
+// NewConstMetric would have returned an error.
+func MustNewConstHistogram(
+ desc *Desc,
+ count uint64,
+ sum float64,
+ buckets map[float64]uint64,
+ labelValues ...string,
+) Metric {
+ m, err := NewConstHistogram(desc, count, sum, buckets, labelValues...)
+ if err != nil {
+ panic(err)
+ }
+ return m
+}
+
+type buckSort []*dto.Bucket
+
+func (s buckSort) Len() int {
+ return len(s)
+}
+
+func (s buckSort) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+func (s buckSort) Less(i, j int) bool {
+ return s[i].GetUpperBound() < s[j].GetUpperBound()
+}
--- /dev/null
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "bufio"
+ "bytes"
+ "compress/gzip"
+ "fmt"
+ "io"
+ "net"
+ "net/http"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/prometheus/common/expfmt"
+)
+
+// TODO(beorn7): Remove this whole file. It is a partial mirror of
+// promhttp/http.go (to avoid circular import chains) where everything HTTP
+// related should live. The functions here are just for avoiding
+// breakage. Everything is deprecated.
+
+const (
+ contentTypeHeader = "Content-Type"
+ contentLengthHeader = "Content-Length"
+ contentEncodingHeader = "Content-Encoding"
+ acceptEncodingHeader = "Accept-Encoding"
+)
+
+var bufPool sync.Pool
+
+func getBuf() *bytes.Buffer {
+ buf := bufPool.Get()
+ if buf == nil {
+ return &bytes.Buffer{}
+ }
+ return buf.(*bytes.Buffer)
+}
+
+func giveBuf(buf *bytes.Buffer) {
+ buf.Reset()
+ bufPool.Put(buf)
+}
+
+// Handler returns an HTTP handler for the DefaultGatherer. It is
+// already instrumented with InstrumentHandler (using "prometheus" as handler
+// name).
+//
+// Deprecated: Please note the issues described in the doc comment of
+// InstrumentHandler. You might want to consider using
+// promhttp.InstrumentedHandler instead.
+func Handler() http.Handler {
+ return InstrumentHandler("prometheus", UninstrumentedHandler())
+}
+
+// UninstrumentedHandler returns an HTTP handler for the DefaultGatherer.
+//
+// Deprecated: Use promhttp.Handler instead. See there for further documentation.
+func UninstrumentedHandler() http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ mfs, err := DefaultGatherer.Gather()
+ if err != nil {
+ http.Error(w, "An error has occurred during metrics collection:\n\n"+err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ contentType := expfmt.Negotiate(req.Header)
+ buf := getBuf()
+ defer giveBuf(buf)
+ writer, encoding := decorateWriter(req, buf)
+ enc := expfmt.NewEncoder(writer, contentType)
+ var lastErr error
+ for _, mf := range mfs {
+ if err := enc.Encode(mf); err != nil {
+ lastErr = err
+ http.Error(w, "An error has occurred during metrics encoding:\n\n"+err.Error(), http.StatusInternalServerError)
+ return
+ }
+ }
+ if closer, ok := writer.(io.Closer); ok {
+ closer.Close()
+ }
+ if lastErr != nil && buf.Len() == 0 {
+ http.Error(w, "No metrics encoded, last error:\n\n"+lastErr.Error(), http.StatusInternalServerError)
+ return
+ }
+ header := w.Header()
+ header.Set(contentTypeHeader, string(contentType))
+ header.Set(contentLengthHeader, fmt.Sprint(buf.Len()))
+ if encoding != "" {
+ header.Set(contentEncodingHeader, encoding)
+ }
+ w.Write(buf.Bytes())
+ })
+}
+
+// decorateWriter wraps a writer to handle gzip compression if requested. It
+// returns the decorated writer and the appropriate "Content-Encoding" header
+// (which is empty if no compression is enabled).
+func decorateWriter(request *http.Request, writer io.Writer) (io.Writer, string) {
+ header := request.Header.Get(acceptEncodingHeader)
+ parts := strings.Split(header, ",")
+ for _, part := range parts {
+ part := strings.TrimSpace(part)
+ if part == "gzip" || strings.HasPrefix(part, "gzip;") {
+ return gzip.NewWriter(writer), "gzip"
+ }
+ }
+ return writer, ""
+}
+
+var instLabels = []string{"method", "code"}
+
+type nower interface {
+ Now() time.Time
+}
+
+type nowFunc func() time.Time
+
+func (n nowFunc) Now() time.Time {
+ return n()
+}
+
+var now nower = nowFunc(func() time.Time {
+ return time.Now()
+})
+
+func nowSeries(t ...time.Time) nower {
+ return nowFunc(func() time.Time {
+ defer func() {
+ t = t[1:]
+ }()
+
+ return t[0]
+ })
+}
+
+// InstrumentHandler wraps the given HTTP handler for instrumentation. It
+// registers four metric collectors (if not already done) and reports HTTP
+// metrics to the (newly or already) registered collectors: http_requests_total
+// (CounterVec), http_request_duration_microseconds (Summary),
+// http_request_size_bytes (Summary), http_response_size_bytes (Summary). Each
+// has a constant label named "handler" with the provided handlerName as
+// value. http_requests_total is a metric vector partitioned by HTTP method
+// (label name "method") and HTTP status code (label name "code").
+//
+// Deprecated: InstrumentHandler has several issues. Use the tooling provided in
+// package promhttp instead. The issues are the following:
+//
+// - It uses Summaries rather than Histograms. Summaries are not useful if
+// aggregation across multiple instances is required.
+//
+// - It uses microseconds as unit, which is deprecated and should be replaced by
+// seconds.
+//
+// - The size of the request is calculated in a separate goroutine. Since this
+// calculator requires access to the request header, it creates a race with
+// any writes to the header performed during request handling.
+// httputil.ReverseProxy is a prominent example for a handler
+// performing such writes.
+//
+// - It has additional issues with HTTP/2, cf.
+// https://github.com/prometheus/client_golang/issues/272.
+func InstrumentHandler(handlerName string, handler http.Handler) http.HandlerFunc {
+ return InstrumentHandlerFunc(handlerName, handler.ServeHTTP)
+}
+
+// InstrumentHandlerFunc wraps the given function for instrumentation. It
+// otherwise works in the same way as InstrumentHandler (and shares the same
+// issues).
+//
+// Deprecated: InstrumentHandlerFunc is deprecated for the same reasons as
+// InstrumentHandler is. Use the tooling provided in package promhttp instead.
+func InstrumentHandlerFunc(handlerName string, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
+ return InstrumentHandlerFuncWithOpts(
+ SummaryOpts{
+ Subsystem: "http",
+ ConstLabels: Labels{"handler": handlerName},
+ Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
+ },
+ handlerFunc,
+ )
+}
+
+// InstrumentHandlerWithOpts works like InstrumentHandler (and shares the same
+// issues) but provides more flexibility (at the cost of a more complex call
+// syntax). As InstrumentHandler, this function registers four metric
+// collectors, but it uses the provided SummaryOpts to create them. However, the
+// fields "Name" and "Help" in the SummaryOpts are ignored. "Name" is replaced
+// by "requests_total", "request_duration_microseconds", "request_size_bytes",
+// and "response_size_bytes", respectively. "Help" is replaced by an appropriate
+// help string. The names of the variable labels of the http_requests_total
+// CounterVec are "method" (get, post, etc.), and "code" (HTTP status code).
+//
+// If InstrumentHandlerWithOpts is called as follows, it mimics exactly the
+// behavior of InstrumentHandler:
+//
+// prometheus.InstrumentHandlerWithOpts(
+// prometheus.SummaryOpts{
+// Subsystem: "http",
+// ConstLabels: prometheus.Labels{"handler": handlerName},
+// },
+// handler,
+// )
+//
+// Technical detail: "requests_total" is a CounterVec, not a SummaryVec, so it
+// cannot use SummaryOpts. Instead, a CounterOpts struct is created internally,
+// and all its fields are set to the equally named fields in the provided
+// SummaryOpts.
+//
+// Deprecated: InstrumentHandlerWithOpts is deprecated for the same reasons as
+// InstrumentHandler is. Use the tooling provided in package promhttp instead.
+func InstrumentHandlerWithOpts(opts SummaryOpts, handler http.Handler) http.HandlerFunc {
+ return InstrumentHandlerFuncWithOpts(opts, handler.ServeHTTP)
+}
+
+// InstrumentHandlerFuncWithOpts works like InstrumentHandlerFunc (and shares
+// the same issues) but provides more flexibility (at the cost of a more complex
+// call syntax). See InstrumentHandlerWithOpts for details how the provided
+// SummaryOpts are used.
+//
+// Deprecated: InstrumentHandlerFuncWithOpts is deprecated for the same reasons
+// as InstrumentHandler is. Use the tooling provided in package promhttp instead.
+func InstrumentHandlerFuncWithOpts(opts SummaryOpts, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
+ reqCnt := NewCounterVec(
+ CounterOpts{
+ Namespace: opts.Namespace,
+ Subsystem: opts.Subsystem,
+ Name: "requests_total",
+ Help: "Total number of HTTP requests made.",
+ ConstLabels: opts.ConstLabels,
+ },
+ instLabels,
+ )
+ if err := Register(reqCnt); err != nil {
+ if are, ok := err.(AlreadyRegisteredError); ok {
+ reqCnt = are.ExistingCollector.(*CounterVec)
+ } else {
+ panic(err)
+ }
+ }
+
+ opts.Name = "request_duration_microseconds"
+ opts.Help = "The HTTP request latencies in microseconds."
+ reqDur := NewSummary(opts)
+ if err := Register(reqDur); err != nil {
+ if are, ok := err.(AlreadyRegisteredError); ok {
+ reqDur = are.ExistingCollector.(Summary)
+ } else {
+ panic(err)
+ }
+ }
+
+ opts.Name = "request_size_bytes"
+ opts.Help = "The HTTP request sizes in bytes."
+ reqSz := NewSummary(opts)
+ if err := Register(reqSz); err != nil {
+ if are, ok := err.(AlreadyRegisteredError); ok {
+ reqSz = are.ExistingCollector.(Summary)
+ } else {
+ panic(err)
+ }
+ }
+
+ opts.Name = "response_size_bytes"
+ opts.Help = "The HTTP response sizes in bytes."
+ resSz := NewSummary(opts)
+ if err := Register(resSz); err != nil {
+ if are, ok := err.(AlreadyRegisteredError); ok {
+ resSz = are.ExistingCollector.(Summary)
+ } else {
+ panic(err)
+ }
+ }
+
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ now := time.Now()
+
+ delegate := &responseWriterDelegator{ResponseWriter: w}
+ out := computeApproximateRequestSize(r)
+
+ _, cn := w.(http.CloseNotifier)
+ _, fl := w.(http.Flusher)
+ _, hj := w.(http.Hijacker)
+ _, rf := w.(io.ReaderFrom)
+ var rw http.ResponseWriter
+ if cn && fl && hj && rf {
+ rw = &fancyResponseWriterDelegator{delegate}
+ } else {
+ rw = delegate
+ }
+ handlerFunc(rw, r)
+
+ elapsed := float64(time.Since(now)) / float64(time.Microsecond)
+
+ method := sanitizeMethod(r.Method)
+ code := sanitizeCode(delegate.status)
+ reqCnt.WithLabelValues(method, code).Inc()
+ reqDur.Observe(elapsed)
+ resSz.Observe(float64(delegate.written))
+ reqSz.Observe(float64(<-out))
+ })
+}
+
+func computeApproximateRequestSize(r *http.Request) <-chan int {
+ // Get URL length in current go routine for avoiding a race condition.
+ // HandlerFunc that runs in parallel may modify the URL.
+ s := 0
+ if r.URL != nil {
+ s += len(r.URL.String())
+ }
+
+ out := make(chan int, 1)
+
+ go func() {
+ s += len(r.Method)
+ s += len(r.Proto)
+ for name, values := range r.Header {
+ s += len(name)
+ for _, value := range values {
+ s += len(value)
+ }
+ }
+ s += len(r.Host)
+
+ // N.B. r.Form and r.MultipartForm are assumed to be included in r.URL.
+
+ if r.ContentLength != -1 {
+ s += int(r.ContentLength)
+ }
+ out <- s
+ close(out)
+ }()
+
+ return out
+}
+
+type responseWriterDelegator struct {
+ http.ResponseWriter
+
+ handler, method string
+ status int
+ written int64
+ wroteHeader bool
+}
+
+func (r *responseWriterDelegator) WriteHeader(code int) {
+ r.status = code
+ r.wroteHeader = true
+ r.ResponseWriter.WriteHeader(code)
+}
+
+func (r *responseWriterDelegator) Write(b []byte) (int, error) {
+ if !r.wroteHeader {
+ r.WriteHeader(http.StatusOK)
+ }
+ n, err := r.ResponseWriter.Write(b)
+ r.written += int64(n)
+ return n, err
+}
+
+type fancyResponseWriterDelegator struct {
+ *responseWriterDelegator
+}
+
+func (f *fancyResponseWriterDelegator) CloseNotify() <-chan bool {
+ return f.ResponseWriter.(http.CloseNotifier).CloseNotify()
+}
+
+func (f *fancyResponseWriterDelegator) Flush() {
+ f.ResponseWriter.(http.Flusher).Flush()
+}
+
+func (f *fancyResponseWriterDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+ return f.ResponseWriter.(http.Hijacker).Hijack()
+}
+
+func (f *fancyResponseWriterDelegator) ReadFrom(r io.Reader) (int64, error) {
+ if !f.wroteHeader {
+ f.WriteHeader(http.StatusOK)
+ }
+ n, err := f.ResponseWriter.(io.ReaderFrom).ReadFrom(r)
+ f.written += n
+ return n, err
+}
+
+func sanitizeMethod(m string) string {
+ switch m {
+ case "GET", "get":
+ return "get"
+ case "PUT", "put":
+ return "put"
+ case "HEAD", "head":
+ return "head"
+ case "POST", "post":
+ return "post"
+ case "DELETE", "delete":
+ return "delete"
+ case "CONNECT", "connect":
+ return "connect"
+ case "OPTIONS", "options":
+ return "options"
+ case "NOTIFY", "notify":
+ return "notify"
+ default:
+ return strings.ToLower(m)
+ }
+}
+
+func sanitizeCode(s int) string {
+ switch s {
+ case 100:
+ return "100"
+ case 101:
+ return "101"
+
+ case 200:
+ return "200"
+ case 201:
+ return "201"
+ case 202:
+ return "202"
+ case 203:
+ return "203"
+ case 204:
+ return "204"
+ case 205:
+ return "205"
+ case 206:
+ return "206"
+
+ case 300:
+ return "300"
+ case 301:
+ return "301"
+ case 302:
+ return "302"
+ case 304:
+ return "304"
+ case 305:
+ return "305"
+ case 307:
+ return "307"
+
+ case 400:
+ return "400"
+ case 401:
+ return "401"
+ case 402:
+ return "402"
+ case 403:
+ return "403"
+ case 404:
+ return "404"
+ case 405:
+ return "405"
+ case 406:
+ return "406"
+ case 407:
+ return "407"
+ case 408:
+ return "408"
+ case 409:
+ return "409"
+ case 410:
+ return "410"
+ case 411:
+ return "411"
+ case 412:
+ return "412"
+ case 413:
+ return "413"
+ case 414:
+ return "414"
+ case 415:
+ return "415"
+ case 416:
+ return "416"
+ case 417:
+ return "417"
+ case 418:
+ return "418"
+
+ case 500:
+ return "500"
+ case 501:
+ return "501"
+ case 502:
+ return "502"
+ case 503:
+ return "503"
+ case 504:
+ return "504"
+ case 505:
+ return "505"
+
+ case 428:
+ return "428"
+ case 429:
+ return "429"
+ case 431:
+ return "431"
+ case 511:
+ return "511"
+
+ default:
+ return strconv.Itoa(s)
+ }
+}
--- /dev/null
+package prometheus
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+ "unicode/utf8"
+
+ "github.com/prometheus/common/model"
+)
+
+// Labels represents a collection of label name -> value mappings. This type is
+// commonly used with the With(Labels) and GetMetricWith(Labels) methods of
+// metric vector Collectors, e.g.:
+// myVec.With(Labels{"code": "404", "method": "GET"}).Add(42)
+//
+// The other use-case is the specification of constant label pairs in Opts or to
+// create a Desc.
+type Labels map[string]string
+
+// reservedLabelPrefix is a prefix which is not legal in user-supplied
+// label names.
+const reservedLabelPrefix = "__"
+
+var errInconsistentCardinality = errors.New("inconsistent label cardinality")
+
+func validateValuesInLabels(labels Labels, expectedNumberOfValues int) error {
+ if len(labels) != expectedNumberOfValues {
+ return errInconsistentCardinality
+ }
+
+ for name, val := range labels {
+ if !utf8.ValidString(val) {
+ return fmt.Errorf("label %s: value %q is not valid UTF-8", name, val)
+ }
+ }
+
+ return nil
+}
+
+func validateLabelValues(vals []string, expectedNumberOfValues int) error {
+ if len(vals) != expectedNumberOfValues {
+ return errInconsistentCardinality
+ }
+
+ for _, val := range vals {
+ if !utf8.ValidString(val) {
+ return fmt.Errorf("label value %q is not valid UTF-8", val)
+ }
+ }
+
+ return nil
+}
+
+func checkLabelName(l string) bool {
+ return model.LabelName(l).IsValid() && !strings.HasPrefix(l, reservedLabelPrefix)
+}
--- /dev/null
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "strings"
+
+ dto "github.com/prometheus/client_model/go"
+)
+
+const separatorByte byte = 255
+
+// A Metric models a single sample value with its meta data being exported to
+// Prometheus. Implementations of Metric in this package are Gauge, Counter,
+// Histogram, Summary, and Untyped.
+type Metric interface {
+ // Desc returns the descriptor for the Metric. This method idempotently
+ // returns the same descriptor throughout the lifetime of the
+ // Metric. The returned descriptor is immutable by contract. A Metric
+ // unable to describe itself must return an invalid descriptor (created
+ // with NewInvalidDesc).
+ Desc() *Desc
+ // Write encodes the Metric into a "Metric" Protocol Buffer data
+ // transmission object.
+ //
+ // Metric implementations must observe concurrency safety as reads of
+ // this metric may occur at any time, and any blocking occurs at the
+ // expense of total performance of rendering all registered
+ // metrics. Ideally, Metric implementations should support concurrent
+ // readers.
+ //
+ // While populating dto.Metric, it is the responsibility of the
+ // implementation to ensure validity of the Metric protobuf (like valid
+ // UTF-8 strings or syntactically valid metric and label names). It is
+ // recommended to sort labels lexicographically. (Implementers may find
+ // LabelPairSorter useful for that.) Callers of Write should still make
+ // sure of sorting if they depend on it.
+ Write(*dto.Metric) error
+ // TODO(beorn7): The original rationale of passing in a pre-allocated
+ // dto.Metric protobuf to save allocations has disappeared. The
+ // signature of this method should be changed to "Write() (*dto.Metric,
+ // error)".
+}
+
+// Opts bundles the options for creating most Metric types. Each metric
+// implementation XXX has its own XXXOpts type, but in most cases, it is just be
+// an alias of this type (which might change when the requirement arises.)
+//
+// It is mandatory to set Name and Help to a non-empty string. All other fields
+// are optional and can safely be left at their zero value.
+type Opts struct {
+ // Namespace, Subsystem, and Name are components of the fully-qualified
+ // name of the Metric (created by joining these components with
+ // "_"). Only Name is mandatory, the others merely help structuring the
+ // name. Note that the fully-qualified name of the metric must be a
+ // valid Prometheus metric name.
+ Namespace string
+ Subsystem string
+ Name string
+
+ // Help provides information about this metric. Mandatory!
+ //
+ // Metrics with the same fully-qualified name must have the same Help
+ // string.
+ Help string
+
+ // ConstLabels are used to attach fixed labels to this metric. Metrics
+ // with the same fully-qualified name must have the same label names in
+ // their ConstLabels.
+ //
+ // ConstLabels are only used rarely. In particular, do not use them to
+ // attach the same labels to all your metrics. Those use cases are
+ // better covered by target labels set by the scraping Prometheus
+ // server, or by one specific metric (e.g. a build_info or a
+ // machine_role metric). See also
+ // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels
+ ConstLabels Labels
+}
+
+// BuildFQName joins the given three name components by "_". Empty name
+// components are ignored. If the name parameter itself is empty, an empty
+// string is returned, no matter what. Metric implementations included in this
+// library use this function internally to generate the fully-qualified metric
+// name from the name component in their Opts. Users of the library will only
+// need this function if they implement their own Metric or instantiate a Desc
+// (with NewDesc) directly.
+func BuildFQName(namespace, subsystem, name string) string {
+ if name == "" {
+ return ""
+ }
+ switch {
+ case namespace != "" && subsystem != "":
+ return strings.Join([]string{namespace, subsystem, name}, "_")
+ case namespace != "":
+ return strings.Join([]string{namespace, name}, "_")
+ case subsystem != "":
+ return strings.Join([]string{subsystem, name}, "_")
+ }
+ return name
+}
+
+// LabelPairSorter implements sort.Interface. It is used to sort a slice of
+// dto.LabelPair pointers. This is useful for implementing the Write method of
+// custom metrics.
+type LabelPairSorter []*dto.LabelPair
+
+func (s LabelPairSorter) Len() int {
+ return len(s)
+}
+
+func (s LabelPairSorter) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+func (s LabelPairSorter) Less(i, j int) bool {
+ return s[i].GetName() < s[j].GetName()
+}
+
+type hashSorter []uint64
+
+func (s hashSorter) Len() int {
+ return len(s)
+}
+
+func (s hashSorter) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+func (s hashSorter) Less(i, j int) bool {
+ return s[i] < s[j]
+}
+
+type invalidMetric struct {
+ desc *Desc
+ err error
+}
+
+// NewInvalidMetric returns a metric whose Write method always returns the
+// provided error. It is useful if a Collector finds itself unable to collect
+// a metric and wishes to report an error to the registry.
+func NewInvalidMetric(desc *Desc, err error) Metric {
+ return &invalidMetric{desc, err}
+}
+
+func (m *invalidMetric) Desc() *Desc { return m.desc }
+
+func (m *invalidMetric) Write(*dto.Metric) error { return m.err }
--- /dev/null
+// Copyright 2017 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+// Observer is the interface that wraps the Observe method, which is used by
+// Histogram and Summary to add observations.
+type Observer interface {
+ Observe(float64)
+}
+
+// The ObserverFunc type is an adapter to allow the use of ordinary
+// functions as Observers. If f is a function with the appropriate
+// signature, ObserverFunc(f) is an Observer that calls f.
+//
+// This adapter is usually used in connection with the Timer type, and there are
+// two general use cases:
+//
+// The most common one is to use a Gauge as the Observer for a Timer.
+// See the "Gauge" Timer example.
+//
+// The more advanced use case is to create a function that dynamically decides
+// which Observer to use for observing the duration. See the "Complex" Timer
+// example.
+type ObserverFunc func(float64)
+
+// Observe calls f(value). It implements Observer.
+func (f ObserverFunc) Observe(value float64) {
+ f(value)
+}
+
+// ObserverVec is an interface implemented by `HistogramVec` and `SummaryVec`.
+type ObserverVec interface {
+ GetMetricWith(Labels) (Observer, error)
+ GetMetricWithLabelValues(lvs ...string) (Observer, error)
+ With(Labels) Observer
+ WithLabelValues(...string) Observer
+ CurryWith(Labels) (ObserverVec, error)
+ MustCurryWith(Labels) ObserverVec
+
+ Collector
+}
--- /dev/null
+// Copyright 2015 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import "github.com/prometheus/procfs"
+
+type processCollector struct {
+ pid int
+ collectFn func(chan<- Metric)
+ pidFn func() (int, error)
+ cpuTotal *Desc
+ openFDs, maxFDs *Desc
+ vsize, rss *Desc
+ startTime *Desc
+}
+
+// NewProcessCollector returns a collector which exports the current state of
+// process metrics including CPU, memory and file descriptor usage as well as
+// the process start time for the given process ID under the given namespace.
+//
+// Currently, the collector depends on a Linux-style proc filesystem and
+// therefore only exports metrics for Linux.
+func NewProcessCollector(pid int, namespace string) Collector {
+ return NewProcessCollectorPIDFn(
+ func() (int, error) { return pid, nil },
+ namespace,
+ )
+}
+
+// NewProcessCollectorPIDFn works like NewProcessCollector but the process ID is
+// determined on each collect anew by calling the given pidFn function.
+func NewProcessCollectorPIDFn(
+ pidFn func() (int, error),
+ namespace string,
+) Collector {
+ ns := ""
+ if len(namespace) > 0 {
+ ns = namespace + "_"
+ }
+
+ c := processCollector{
+ pidFn: pidFn,
+ collectFn: func(chan<- Metric) {},
+
+ cpuTotal: NewDesc(
+ ns+"process_cpu_seconds_total",
+ "Total user and system CPU time spent in seconds.",
+ nil, nil,
+ ),
+ openFDs: NewDesc(
+ ns+"process_open_fds",
+ "Number of open file descriptors.",
+ nil, nil,
+ ),
+ maxFDs: NewDesc(
+ ns+"process_max_fds",
+ "Maximum number of open file descriptors.",
+ nil, nil,
+ ),
+ vsize: NewDesc(
+ ns+"process_virtual_memory_bytes",
+ "Virtual memory size in bytes.",
+ nil, nil,
+ ),
+ rss: NewDesc(
+ ns+"process_resident_memory_bytes",
+ "Resident memory size in bytes.",
+ nil, nil,
+ ),
+ startTime: NewDesc(
+ ns+"process_start_time_seconds",
+ "Start time of the process since unix epoch in seconds.",
+ nil, nil,
+ ),
+ }
+
+ // Set up process metric collection if supported by the runtime.
+ if _, err := procfs.NewStat(); err == nil {
+ c.collectFn = c.processCollect
+ }
+
+ return &c
+}
+
+// Describe returns all descriptions of the collector.
+func (c *processCollector) Describe(ch chan<- *Desc) {
+ ch <- c.cpuTotal
+ ch <- c.openFDs
+ ch <- c.maxFDs
+ ch <- c.vsize
+ ch <- c.rss
+ ch <- c.startTime
+}
+
+// Collect returns the current state of all metrics of the collector.
+func (c *processCollector) Collect(ch chan<- Metric) {
+ c.collectFn(ch)
+}
+
+// TODO(ts): Bring back error reporting by reverting 7faf9e7 as soon as the
+// client allows users to configure the error behavior.
+func (c *processCollector) processCollect(ch chan<- Metric) {
+ pid, err := c.pidFn()
+ if err != nil {
+ return
+ }
+
+ p, err := procfs.NewProc(pid)
+ if err != nil {
+ return
+ }
+
+ if stat, err := p.NewStat(); err == nil {
+ ch <- MustNewConstMetric(c.cpuTotal, CounterValue, stat.CPUTime())
+ ch <- MustNewConstMetric(c.vsize, GaugeValue, float64(stat.VirtualMemory()))
+ ch <- MustNewConstMetric(c.rss, GaugeValue, float64(stat.ResidentMemory()))
+ if startTime, err := stat.StartTime(); err == nil {
+ ch <- MustNewConstMetric(c.startTime, GaugeValue, startTime)
+ }
+ }
+
+ if fds, err := p.FileDescriptorsLen(); err == nil {
+ ch <- MustNewConstMetric(c.openFDs, GaugeValue, float64(fds))
+ }
+
+ if limits, err := p.NewLimits(); err == nil {
+ ch <- MustNewConstMetric(c.maxFDs, GaugeValue, float64(limits.OpenFiles))
+ }
+}
--- /dev/null
+// Copyright 2017 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package promhttp
+
+import (
+ "bufio"
+ "io"
+ "net"
+ "net/http"
+)
+
+const (
+ closeNotifier = 1 << iota
+ flusher
+ hijacker
+ readerFrom
+ pusher
+)
+
+type delegator interface {
+ http.ResponseWriter
+
+ Status() int
+ Written() int64
+}
+
+type responseWriterDelegator struct {
+ http.ResponseWriter
+
+ handler, method string
+ status int
+ written int64
+ wroteHeader bool
+ observeWriteHeader func(int)
+}
+
+func (r *responseWriterDelegator) Status() int {
+ return r.status
+}
+
+func (r *responseWriterDelegator) Written() int64 {
+ return r.written
+}
+
+func (r *responseWriterDelegator) WriteHeader(code int) {
+ r.status = code
+ r.wroteHeader = true
+ r.ResponseWriter.WriteHeader(code)
+ if r.observeWriteHeader != nil {
+ r.observeWriteHeader(code)
+ }
+}
+
+func (r *responseWriterDelegator) Write(b []byte) (int, error) {
+ if !r.wroteHeader {
+ r.WriteHeader(http.StatusOK)
+ }
+ n, err := r.ResponseWriter.Write(b)
+ r.written += int64(n)
+ return n, err
+}
+
+type closeNotifierDelegator struct{ *responseWriterDelegator }
+type flusherDelegator struct{ *responseWriterDelegator }
+type hijackerDelegator struct{ *responseWriterDelegator }
+type readerFromDelegator struct{ *responseWriterDelegator }
+
+func (d *closeNotifierDelegator) CloseNotify() <-chan bool {
+ return d.ResponseWriter.(http.CloseNotifier).CloseNotify()
+}
+func (d *flusherDelegator) Flush() {
+ d.ResponseWriter.(http.Flusher).Flush()
+}
+func (d *hijackerDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+ return d.ResponseWriter.(http.Hijacker).Hijack()
+}
+func (d *readerFromDelegator) ReadFrom(re io.Reader) (int64, error) {
+ if !d.wroteHeader {
+ d.WriteHeader(http.StatusOK)
+ }
+ n, err := d.ResponseWriter.(io.ReaderFrom).ReadFrom(re)
+ d.written += n
+ return n, err
+}
+
+var pickDelegator = make([]func(*responseWriterDelegator) delegator, 32)
+
+func init() {
+ // TODO(beorn7): Code generation would help here.
+ pickDelegator[0] = func(d *responseWriterDelegator) delegator { // 0
+ return d
+ }
+ pickDelegator[closeNotifier] = func(d *responseWriterDelegator) delegator { // 1
+ return &closeNotifierDelegator{d}
+ }
+ pickDelegator[flusher] = func(d *responseWriterDelegator) delegator { // 2
+ return &flusherDelegator{d}
+ }
+ pickDelegator[flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 3
+ return struct {
+ *responseWriterDelegator
+ http.Flusher
+ http.CloseNotifier
+ }{d, &flusherDelegator{d}, &closeNotifierDelegator{d}}
+ }
+ pickDelegator[hijacker] = func(d *responseWriterDelegator) delegator { // 4
+ return &hijackerDelegator{d}
+ }
+ pickDelegator[hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 5
+ return struct {
+ *responseWriterDelegator
+ http.Hijacker
+ http.CloseNotifier
+ }{d, &hijackerDelegator{d}, &closeNotifierDelegator{d}}
+ }
+ pickDelegator[hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 6
+ return struct {
+ *responseWriterDelegator
+ http.Hijacker
+ http.Flusher
+ }{d, &hijackerDelegator{d}, &flusherDelegator{d}}
+ }
+ pickDelegator[hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 7
+ return struct {
+ *responseWriterDelegator
+ http.Hijacker
+ http.Flusher
+ http.CloseNotifier
+ }{d, &hijackerDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}}
+ }
+ pickDelegator[readerFrom] = func(d *responseWriterDelegator) delegator { // 8
+ return readerFromDelegator{d}
+ }
+ pickDelegator[readerFrom+closeNotifier] = func(d *responseWriterDelegator) delegator { // 9
+ return struct {
+ *responseWriterDelegator
+ io.ReaderFrom
+ http.CloseNotifier
+ }{d, &readerFromDelegator{d}, &closeNotifierDelegator{d}}
+ }
+ pickDelegator[readerFrom+flusher] = func(d *responseWriterDelegator) delegator { // 10
+ return struct {
+ *responseWriterDelegator
+ io.ReaderFrom
+ http.Flusher
+ }{d, &readerFromDelegator{d}, &flusherDelegator{d}}
+ }
+ pickDelegator[readerFrom+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 11
+ return struct {
+ *responseWriterDelegator
+ io.ReaderFrom
+ http.Flusher
+ http.CloseNotifier
+ }{d, &readerFromDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}}
+ }
+ pickDelegator[readerFrom+hijacker] = func(d *responseWriterDelegator) delegator { // 12
+ return struct {
+ *responseWriterDelegator
+ io.ReaderFrom
+ http.Hijacker
+ }{d, &readerFromDelegator{d}, &hijackerDelegator{d}}
+ }
+ pickDelegator[readerFrom+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 13
+ return struct {
+ *responseWriterDelegator
+ io.ReaderFrom
+ http.Hijacker
+ http.CloseNotifier
+ }{d, &readerFromDelegator{d}, &hijackerDelegator{d}, &closeNotifierDelegator{d}}
+ }
+ pickDelegator[readerFrom+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 14
+ return struct {
+ *responseWriterDelegator
+ io.ReaderFrom
+ http.Hijacker
+ http.Flusher
+ }{d, &readerFromDelegator{d}, &hijackerDelegator{d}, &flusherDelegator{d}}
+ }
+ pickDelegator[readerFrom+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 15
+ return struct {
+ *responseWriterDelegator
+ io.ReaderFrom
+ http.Hijacker
+ http.Flusher
+ http.CloseNotifier
+ }{d, &readerFromDelegator{d}, &hijackerDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}}
+ }
+}
--- /dev/null
+// Copyright 2017 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build go1.8
+
+package promhttp
+
+import (
+ "io"
+ "net/http"
+)
+
+type pusherDelegator struct{ *responseWriterDelegator }
+
+func (d *pusherDelegator) Push(target string, opts *http.PushOptions) error {
+ return d.ResponseWriter.(http.Pusher).Push(target, opts)
+}
+
+func init() {
+ pickDelegator[pusher] = func(d *responseWriterDelegator) delegator { // 16
+ return &pusherDelegator{d}
+ }
+ pickDelegator[pusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 17
+ return struct {
+ *responseWriterDelegator
+ http.Pusher
+ http.CloseNotifier
+ }{d, &pusherDelegator{d}, &closeNotifierDelegator{d}}
+ }
+ pickDelegator[pusher+flusher] = func(d *responseWriterDelegator) delegator { // 18
+ return struct {
+ *responseWriterDelegator
+ http.Pusher
+ http.Flusher
+ }{d, &pusherDelegator{d}, &flusherDelegator{d}}
+ }
+ pickDelegator[pusher+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 19
+ return struct {
+ *responseWriterDelegator
+ http.Pusher
+ http.Flusher
+ http.CloseNotifier
+ }{d, &pusherDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}}
+ }
+ pickDelegator[pusher+hijacker] = func(d *responseWriterDelegator) delegator { // 20
+ return struct {
+ *responseWriterDelegator
+ http.Pusher
+ http.Hijacker
+ }{d, &pusherDelegator{d}, &hijackerDelegator{d}}
+ }
+ pickDelegator[pusher+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 21
+ return struct {
+ *responseWriterDelegator
+ http.Pusher
+ http.Hijacker
+ http.CloseNotifier
+ }{d, &pusherDelegator{d}, &hijackerDelegator{d}, &closeNotifierDelegator{d}}
+ }
+ pickDelegator[pusher+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 22
+ return struct {
+ *responseWriterDelegator
+ http.Pusher
+ http.Hijacker
+ http.Flusher
+ }{d, &pusherDelegator{d}, &hijackerDelegator{d}, &flusherDelegator{d}}
+ }
+ pickDelegator[pusher+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { //23
+ return struct {
+ *responseWriterDelegator
+ http.Pusher
+ http.Hijacker
+ http.Flusher
+ http.CloseNotifier
+ }{d, &pusherDelegator{d}, &hijackerDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}}
+ }
+ pickDelegator[pusher+readerFrom] = func(d *responseWriterDelegator) delegator { // 24
+ return struct {
+ *responseWriterDelegator
+ http.Pusher
+ io.ReaderFrom
+ }{d, &pusherDelegator{d}, &readerFromDelegator{d}}
+ }
+ pickDelegator[pusher+readerFrom+closeNotifier] = func(d *responseWriterDelegator) delegator { // 25
+ return struct {
+ *responseWriterDelegator
+ http.Pusher
+ io.ReaderFrom
+ http.CloseNotifier
+ }{d, &pusherDelegator{d}, &readerFromDelegator{d}, &closeNotifierDelegator{d}}
+ }
+ pickDelegator[pusher+readerFrom+flusher] = func(d *responseWriterDelegator) delegator { // 26
+ return struct {
+ *responseWriterDelegator
+ http.Pusher
+ io.ReaderFrom
+ http.Flusher
+ }{d, &pusherDelegator{d}, &readerFromDelegator{d}, &flusherDelegator{d}}
+ }
+ pickDelegator[pusher+readerFrom+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 27
+ return struct {
+ *responseWriterDelegator
+ http.Pusher
+ io.ReaderFrom
+ http.Flusher
+ http.CloseNotifier
+ }{d, &pusherDelegator{d}, &readerFromDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}}
+ }
+ pickDelegator[pusher+readerFrom+hijacker] = func(d *responseWriterDelegator) delegator { // 28
+ return struct {
+ *responseWriterDelegator
+ http.Pusher
+ io.ReaderFrom
+ http.Hijacker
+ }{d, &pusherDelegator{d}, &readerFromDelegator{d}, &hijackerDelegator{d}}
+ }
+ pickDelegator[pusher+readerFrom+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 29
+ return struct {
+ *responseWriterDelegator
+ http.Pusher
+ io.ReaderFrom
+ http.Hijacker
+ http.CloseNotifier
+ }{d, &pusherDelegator{d}, &readerFromDelegator{d}, &hijackerDelegator{d}, &closeNotifierDelegator{d}}
+ }
+ pickDelegator[pusher+readerFrom+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 30
+ return struct {
+ *responseWriterDelegator
+ http.Pusher
+ io.ReaderFrom
+ http.Hijacker
+ http.Flusher
+ }{d, &pusherDelegator{d}, &readerFromDelegator{d}, &hijackerDelegator{d}, &flusherDelegator{d}}
+ }
+ pickDelegator[pusher+readerFrom+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 31
+ return struct {
+ *responseWriterDelegator
+ http.Pusher
+ io.ReaderFrom
+ http.Hijacker
+ http.Flusher
+ http.CloseNotifier
+ }{d, &pusherDelegator{d}, &readerFromDelegator{d}, &hijackerDelegator{d}, &flusherDelegator{d}, &closeNotifierDelegator{d}}
+ }
+}
+
+func newDelegator(w http.ResponseWriter, observeWriteHeaderFunc func(int)) delegator {
+ d := &responseWriterDelegator{
+ ResponseWriter: w,
+ observeWriteHeader: observeWriteHeaderFunc,
+ }
+
+ id := 0
+ if _, ok := w.(http.CloseNotifier); ok {
+ id += closeNotifier
+ }
+ if _, ok := w.(http.Flusher); ok {
+ id += flusher
+ }
+ if _, ok := w.(http.Hijacker); ok {
+ id += hijacker
+ }
+ if _, ok := w.(io.ReaderFrom); ok {
+ id += readerFrom
+ }
+ if _, ok := w.(http.Pusher); ok {
+ id += pusher
+ }
+
+ return pickDelegator[id](d)
+}
--- /dev/null
+// Copyright 2017 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build !go1.8
+
+package promhttp
+
+import (
+ "io"
+ "net/http"
+)
+
+func newDelegator(w http.ResponseWriter, observeWriteHeaderFunc func(int)) delegator {
+ d := &responseWriterDelegator{
+ ResponseWriter: w,
+ observeWriteHeader: observeWriteHeaderFunc,
+ }
+
+ id := 0
+ if _, ok := w.(http.CloseNotifier); ok {
+ id += closeNotifier
+ }
+ if _, ok := w.(http.Flusher); ok {
+ id += flusher
+ }
+ if _, ok := w.(http.Hijacker); ok {
+ id += hijacker
+ }
+ if _, ok := w.(io.ReaderFrom); ok {
+ id += readerFrom
+ }
+
+ return pickDelegator[id](d)
+}
--- /dev/null
+// Copyright 2016 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package promhttp provides tooling around HTTP servers and clients.
+//
+// First, the package allows the creation of http.Handler instances to expose
+// Prometheus metrics via HTTP. promhttp.Handler acts on the
+// prometheus.DefaultGatherer. With HandlerFor, you can create a handler for a
+// custom registry or anything that implements the Gatherer interface. It also
+// allows the creation of handlers that act differently on errors or allow to
+// log errors.
+//
+// Second, the package provides tooling to instrument instances of http.Handler
+// via middleware. Middleware wrappers follow the naming scheme
+// InstrumentHandlerX, where X describes the intended use of the middleware.
+// See each function's doc comment for specific details.
+//
+// Finally, the package allows for an http.RoundTripper to be instrumented via
+// middleware. Middleware wrappers follow the naming scheme
+// InstrumentRoundTripperX, where X describes the intended use of the
+// middleware. See each function's doc comment for specific details.
+package promhttp
+
+import (
+ "bytes"
+ "compress/gzip"
+ "fmt"
+ "io"
+ "net/http"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/prometheus/common/expfmt"
+
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+const (
+ contentTypeHeader = "Content-Type"
+ contentLengthHeader = "Content-Length"
+ contentEncodingHeader = "Content-Encoding"
+ acceptEncodingHeader = "Accept-Encoding"
+)
+
+var bufPool sync.Pool
+
+func getBuf() *bytes.Buffer {
+ buf := bufPool.Get()
+ if buf == nil {
+ return &bytes.Buffer{}
+ }
+ return buf.(*bytes.Buffer)
+}
+
+func giveBuf(buf *bytes.Buffer) {
+ buf.Reset()
+ bufPool.Put(buf)
+}
+
+// Handler returns an http.Handler for the prometheus.DefaultGatherer, using
+// default HandlerOpts, i.e. it reports the first error as an HTTP error, it has
+// no error logging, and it applies compression if requested by the client.
+//
+// The returned http.Handler is already instrumented using the
+// InstrumentMetricHandler function and the prometheus.DefaultRegisterer. If you
+// create multiple http.Handlers by separate calls of the Handler function, the
+// metrics used for instrumentation will be shared between them, providing
+// global scrape counts.
+//
+// This function is meant to cover the bulk of basic use cases. If you are doing
+// anything that requires more customization (including using a non-default
+// Gatherer, different instrumentation, and non-default HandlerOpts), use the
+// HandlerFor function. See there for details.
+func Handler() http.Handler {
+ return InstrumentMetricHandler(
+ prometheus.DefaultRegisterer, HandlerFor(prometheus.DefaultGatherer, HandlerOpts{}),
+ )
+}
+
+// HandlerFor returns an uninstrumented http.Handler for the provided
+// Gatherer. The behavior of the Handler is defined by the provided
+// HandlerOpts. Thus, HandlerFor is useful to create http.Handlers for custom
+// Gatherers, with non-default HandlerOpts, and/or with custom (or no)
+// instrumentation. Use the InstrumentMetricHandler function to apply the same
+// kind of instrumentation as it is used by the Handler function.
+func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
+ var inFlightSem chan struct{}
+ if opts.MaxRequestsInFlight > 0 {
+ inFlightSem = make(chan struct{}, opts.MaxRequestsInFlight)
+ }
+
+ h := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ if inFlightSem != nil {
+ select {
+ case inFlightSem <- struct{}{}: // All good, carry on.
+ defer func() { <-inFlightSem }()
+ default:
+ http.Error(w, fmt.Sprintf(
+ "Limit of concurrent requests reached (%d), try again later.", opts.MaxRequestsInFlight,
+ ), http.StatusServiceUnavailable)
+ return
+ }
+ }
+
+ mfs, err := reg.Gather()
+ if err != nil {
+ if opts.ErrorLog != nil {
+ opts.ErrorLog.Println("error gathering metrics:", err)
+ }
+ switch opts.ErrorHandling {
+ case PanicOnError:
+ panic(err)
+ case ContinueOnError:
+ if len(mfs) == 0 {
+ http.Error(w, "No metrics gathered, last error:\n\n"+err.Error(), http.StatusInternalServerError)
+ return
+ }
+ case HTTPErrorOnError:
+ http.Error(w, "An error has occurred during metrics gathering:\n\n"+err.Error(), http.StatusInternalServerError)
+ return
+ }
+ }
+
+ contentType := expfmt.Negotiate(req.Header)
+ buf := getBuf()
+ defer giveBuf(buf)
+ writer, encoding := decorateWriter(req, buf, opts.DisableCompression)
+ enc := expfmt.NewEncoder(writer, contentType)
+ var lastErr error
+ for _, mf := range mfs {
+ if err := enc.Encode(mf); err != nil {
+ lastErr = err
+ if opts.ErrorLog != nil {
+ opts.ErrorLog.Println("error encoding metric family:", err)
+ }
+ switch opts.ErrorHandling {
+ case PanicOnError:
+ panic(err)
+ case ContinueOnError:
+ // Handled later.
+ case HTTPErrorOnError:
+ http.Error(w, "An error has occurred during metrics encoding:\n\n"+err.Error(), http.StatusInternalServerError)
+ return
+ }
+ }
+ }
+ if closer, ok := writer.(io.Closer); ok {
+ closer.Close()
+ }
+ if lastErr != nil && buf.Len() == 0 {
+ http.Error(w, "No metrics encoded, last error:\n\n"+lastErr.Error(), http.StatusInternalServerError)
+ return
+ }
+ header := w.Header()
+ header.Set(contentTypeHeader, string(contentType))
+ header.Set(contentLengthHeader, fmt.Sprint(buf.Len()))
+ if encoding != "" {
+ header.Set(contentEncodingHeader, encoding)
+ }
+ if _, err := w.Write(buf.Bytes()); err != nil && opts.ErrorLog != nil {
+ opts.ErrorLog.Println("error while sending encoded metrics:", err)
+ }
+ // TODO(beorn7): Consider streaming serving of metrics.
+ })
+
+ if opts.Timeout <= 0 {
+ return h
+ }
+ return http.TimeoutHandler(h, opts.Timeout, fmt.Sprintf(
+ "Exceeded configured timeout of %v.\n",
+ opts.Timeout,
+ ))
+}
+
+// InstrumentMetricHandler is usually used with an http.Handler returned by the
+// HandlerFor function. It instruments the provided http.Handler with two
+// metrics: A counter vector "promhttp_metric_handler_requests_total" to count
+// scrapes partitioned by HTTP status code, and a gauge
+// "promhttp_metric_handler_requests_in_flight" to track the number of
+// simultaneous scrapes. This function idempotently registers collectors for
+// both metrics with the provided Registerer. It panics if the registration
+// fails. The provided metrics are useful to see how many scrapes hit the
+// monitored target (which could be from different Prometheus servers or other
+// scrapers), and how often they overlap (which would result in more than one
+// scrape in flight at the same time). Note that the scrapes-in-flight gauge
+// will contain the scrape by which it is exposed, while the scrape counter will
+// only get incremented after the scrape is complete (as only then the status
+// code is known). For tracking scrape durations, use the
+// "scrape_duration_seconds" gauge created by the Prometheus server upon each
+// scrape.
+func InstrumentMetricHandler(reg prometheus.Registerer, handler http.Handler) http.Handler {
+ cnt := prometheus.NewCounterVec(
+ prometheus.CounterOpts{
+ Name: "promhttp_metric_handler_requests_total",
+ Help: "Total number of scrapes by HTTP status code.",
+ },
+ []string{"code"},
+ )
+ // Initialize the most likely HTTP status codes.
+ cnt.WithLabelValues("200")
+ cnt.WithLabelValues("500")
+ cnt.WithLabelValues("503")
+ if err := reg.Register(cnt); err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ cnt = are.ExistingCollector.(*prometheus.CounterVec)
+ } else {
+ panic(err)
+ }
+ }
+
+ gge := prometheus.NewGauge(prometheus.GaugeOpts{
+ Name: "promhttp_metric_handler_requests_in_flight",
+ Help: "Current number of scrapes being served.",
+ })
+ if err := reg.Register(gge); err != nil {
+ if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
+ gge = are.ExistingCollector.(prometheus.Gauge)
+ } else {
+ panic(err)
+ }
+ }
+
+ return InstrumentHandlerCounter(cnt, InstrumentHandlerInFlight(gge, handler))
+}
+
+// HandlerErrorHandling defines how a Handler serving metrics will handle
+// errors.
+type HandlerErrorHandling int
+
+// These constants cause handlers serving metrics to behave as described if
+// errors are encountered.
+const (
+ // Serve an HTTP status code 500 upon the first error
+ // encountered. Report the error message in the body.
+ HTTPErrorOnError HandlerErrorHandling = iota
+ // Ignore errors and try to serve as many metrics as possible. However,
+ // if no metrics can be served, serve an HTTP status code 500 and the
+ // last error message in the body. Only use this in deliberate "best
+ // effort" metrics collection scenarios. It is recommended to at least
+ // log errors (by providing an ErrorLog in HandlerOpts) to not mask
+ // errors completely.
+ ContinueOnError
+ // Panic upon the first error encountered (useful for "crash only" apps).
+ PanicOnError
+)
+
+// Logger is the minimal interface HandlerOpts needs for logging. Note that
+// log.Logger from the standard library implements this interface, and it is
+// easy to implement by custom loggers, if they don't do so already anyway.
+type Logger interface {
+ Println(v ...interface{})
+}
+
+// HandlerOpts specifies options how to serve metrics via an http.Handler. The
+// zero value of HandlerOpts is a reasonable default.
+type HandlerOpts struct {
+ // ErrorLog specifies an optional logger for errors collecting and
+ // serving metrics. If nil, errors are not logged at all.
+ ErrorLog Logger
+ // ErrorHandling defines how errors are handled. Note that errors are
+ // logged regardless of the configured ErrorHandling provided ErrorLog
+ // is not nil.
+ ErrorHandling HandlerErrorHandling
+ // If DisableCompression is true, the handler will never compress the
+ // response, even if requested by the client.
+ DisableCompression bool
+ // The number of concurrent HTTP requests is limited to
+ // MaxRequestsInFlight. Additional requests are responded to with 503
+ // Service Unavailable and a suitable message in the body. If
+ // MaxRequestsInFlight is 0 or negative, no limit is applied.
+ MaxRequestsInFlight int
+ // If handling a request takes longer than Timeout, it is responded to
+ // with 503 ServiceUnavailable and a suitable Message. No timeout is
+ // applied if Timeout is 0 or negative. Note that with the current
+ // implementation, reaching the timeout simply ends the HTTP requests as
+ // described above (and even that only if sending of the body hasn't
+ // started yet), while the bulk work of gathering all the metrics keeps
+ // running in the background (with the eventual result to be thrown
+ // away). Until the implementation is improved, it is recommended to
+ // implement a separate timeout in potentially slow Collectors.
+ Timeout time.Duration
+}
+
+// decorateWriter wraps a writer to handle gzip compression if requested. It
+// returns the decorated writer and the appropriate "Content-Encoding" header
+// (which is empty if no compression is enabled).
+func decorateWriter(request *http.Request, writer io.Writer, compressionDisabled bool) (io.Writer, string) {
+ if compressionDisabled {
+ return writer, ""
+ }
+ header := request.Header.Get(acceptEncodingHeader)
+ parts := strings.Split(header, ",")
+ for _, part := range parts {
+ part := strings.TrimSpace(part)
+ if part == "gzip" || strings.HasPrefix(part, "gzip;") {
+ return gzip.NewWriter(writer), "gzip"
+ }
+ }
+ return writer, ""
+}
--- /dev/null
+// Copyright 2017 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package promhttp
+
+import (
+ "net/http"
+ "time"
+
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+// The RoundTripperFunc type is an adapter to allow the use of ordinary
+// functions as RoundTrippers. If f is a function with the appropriate
+// signature, RountTripperFunc(f) is a RoundTripper that calls f.
+type RoundTripperFunc func(req *http.Request) (*http.Response, error)
+
+// RoundTrip implements the RoundTripper interface.
+func (rt RoundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) {
+ return rt(r)
+}
+
+// InstrumentRoundTripperInFlight is a middleware that wraps the provided
+// http.RoundTripper. It sets the provided prometheus.Gauge to the number of
+// requests currently handled by the wrapped http.RoundTripper.
+//
+// See the example for ExampleInstrumentRoundTripperDuration for example usage.
+func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripper) RoundTripperFunc {
+ return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
+ gauge.Inc()
+ defer gauge.Dec()
+ return next.RoundTrip(r)
+ })
+}
+
+// InstrumentRoundTripperCounter is a middleware that wraps the provided
+// http.RoundTripper to observe the request result with the provided CounterVec.
+// The CounterVec must have zero, one, or two non-const non-curried labels. For
+// those, the only allowed label names are "code" and "method". The function
+// panics otherwise. Partitioning of the CounterVec happens by HTTP status code
+// and/or HTTP method if the respective instance label names are present in the
+// CounterVec. For unpartitioned counting, use a CounterVec with zero labels.
+//
+// If the wrapped RoundTripper panics or returns a non-nil error, the Counter
+// is not incremented.
+//
+// See the example for ExampleInstrumentRoundTripperDuration for example usage.
+func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.RoundTripper) RoundTripperFunc {
+ code, method := checkLabels(counter)
+
+ return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
+ resp, err := next.RoundTrip(r)
+ if err == nil {
+ counter.With(labels(code, method, r.Method, resp.StatusCode)).Inc()
+ }
+ return resp, err
+ })
+}
+
+// InstrumentRoundTripperDuration is a middleware that wraps the provided
+// http.RoundTripper to observe the request duration with the provided
+// ObserverVec. The ObserverVec must have zero, one, or two non-const
+// non-curried labels. For those, the only allowed label names are "code" and
+// "method". The function panics otherwise. The Observe method of the Observer
+// in the ObserverVec is called with the request duration in
+// seconds. Partitioning happens by HTTP status code and/or HTTP method if the
+// respective instance label names are present in the ObserverVec. For
+// unpartitioned observations, use an ObserverVec with zero labels. Note that
+// partitioning of Histograms is expensive and should be used judiciously.
+//
+// If the wrapped RoundTripper panics or returns a non-nil error, no values are
+// reported.
+//
+// Note that this method is only guaranteed to never observe negative durations
+// if used with Go1.9+.
+func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper) RoundTripperFunc {
+ code, method := checkLabels(obs)
+
+ return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
+ start := time.Now()
+ resp, err := next.RoundTrip(r)
+ if err == nil {
+ obs.With(labels(code, method, r.Method, resp.StatusCode)).Observe(time.Since(start).Seconds())
+ }
+ return resp, err
+ })
+}
--- /dev/null
+// Copyright 2017 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build go1.8
+
+package promhttp
+
+import (
+ "context"
+ "crypto/tls"
+ "net/http"
+ "net/http/httptrace"
+ "time"
+)
+
+// InstrumentTrace is used to offer flexibility in instrumenting the available
+// httptrace.ClientTrace hook functions. Each function is passed a float64
+// representing the time in seconds since the start of the http request. A user
+// may choose to use separately buckets Histograms, or implement custom
+// instance labels on a per function basis.
+type InstrumentTrace struct {
+ GotConn func(float64)
+ PutIdleConn func(float64)
+ GotFirstResponseByte func(float64)
+ Got100Continue func(float64)
+ DNSStart func(float64)
+ DNSDone func(float64)
+ ConnectStart func(float64)
+ ConnectDone func(float64)
+ TLSHandshakeStart func(float64)
+ TLSHandshakeDone func(float64)
+ WroteHeaders func(float64)
+ Wait100Continue func(float64)
+ WroteRequest func(float64)
+}
+
+// InstrumentRoundTripperTrace is a middleware that wraps the provided
+// RoundTripper and reports times to hook functions provided in the
+// InstrumentTrace struct. Hook functions that are not present in the provided
+// InstrumentTrace struct are ignored. Times reported to the hook functions are
+// time since the start of the request. Only with Go1.9+, those times are
+// guaranteed to never be negative. (Earlier Go versions are not using a
+// monotonic clock.) Note that partitioning of Histograms is expensive and
+// should be used judiciously.
+//
+// For hook functions that receive an error as an argument, no observations are
+// made in the event of a non-nil error value.
+//
+// See the example for ExampleInstrumentRoundTripperDuration for example usage.
+func InstrumentRoundTripperTrace(it *InstrumentTrace, next http.RoundTripper) RoundTripperFunc {
+ return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
+ start := time.Now()
+
+ trace := &httptrace.ClientTrace{
+ GotConn: func(_ httptrace.GotConnInfo) {
+ if it.GotConn != nil {
+ it.GotConn(time.Since(start).Seconds())
+ }
+ },
+ PutIdleConn: func(err error) {
+ if err != nil {
+ return
+ }
+ if it.PutIdleConn != nil {
+ it.PutIdleConn(time.Since(start).Seconds())
+ }
+ },
+ DNSStart: func(_ httptrace.DNSStartInfo) {
+ if it.DNSStart != nil {
+ it.DNSStart(time.Since(start).Seconds())
+ }
+ },
+ DNSDone: func(_ httptrace.DNSDoneInfo) {
+ if it.DNSStart != nil {
+ it.DNSStart(time.Since(start).Seconds())
+ }
+ },
+ ConnectStart: func(_, _ string) {
+ if it.ConnectStart != nil {
+ it.ConnectStart(time.Since(start).Seconds())
+ }
+ },
+ ConnectDone: func(_, _ string, err error) {
+ if err != nil {
+ return
+ }
+ if it.ConnectDone != nil {
+ it.ConnectDone(time.Since(start).Seconds())
+ }
+ },
+ GotFirstResponseByte: func() {
+ if it.GotFirstResponseByte != nil {
+ it.GotFirstResponseByte(time.Since(start).Seconds())
+ }
+ },
+ Got100Continue: func() {
+ if it.Got100Continue != nil {
+ it.Got100Continue(time.Since(start).Seconds())
+ }
+ },
+ TLSHandshakeStart: func() {
+ if it.TLSHandshakeStart != nil {
+ it.TLSHandshakeStart(time.Since(start).Seconds())
+ }
+ },
+ TLSHandshakeDone: func(_ tls.ConnectionState, err error) {
+ if err != nil {
+ return
+ }
+ if it.TLSHandshakeDone != nil {
+ it.TLSHandshakeDone(time.Since(start).Seconds())
+ }
+ },
+ WroteHeaders: func() {
+ if it.WroteHeaders != nil {
+ it.WroteHeaders(time.Since(start).Seconds())
+ }
+ },
+ Wait100Continue: func() {
+ if it.Wait100Continue != nil {
+ it.Wait100Continue(time.Since(start).Seconds())
+ }
+ },
+ WroteRequest: func(_ httptrace.WroteRequestInfo) {
+ if it.WroteRequest != nil {
+ it.WroteRequest(time.Since(start).Seconds())
+ }
+ },
+ }
+ r = r.WithContext(httptrace.WithClientTrace(context.Background(), trace))
+
+ return next.RoundTrip(r)
+ })
+}
--- /dev/null
+// Copyright 2017 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package promhttp
+
+import (
+ "errors"
+ "net/http"
+ "strconv"
+ "strings"
+ "time"
+
+ dto "github.com/prometheus/client_model/go"
+
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+// magicString is used for the hacky label test in checkLabels. Remove once fixed.
+const magicString = "zZgWfBxLqvG8kc8IMv3POi2Bb0tZI3vAnBx+gBaFi9FyPzB/CzKUer1yufDa"
+
+// InstrumentHandlerInFlight is a middleware that wraps the provided
+// http.Handler. It sets the provided prometheus.Gauge to the number of
+// requests currently handled by the wrapped http.Handler.
+//
+// See the example for InstrumentHandlerDuration for example usage.
+func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ g.Inc()
+ defer g.Dec()
+ next.ServeHTTP(w, r)
+ })
+}
+
+// InstrumentHandlerDuration is a middleware that wraps the provided
+// http.Handler to observe the request duration with the provided ObserverVec.
+// The ObserverVec must have zero, one, or two non-const non-curried labels. For
+// those, the only allowed label names are "code" and "method". The function
+// panics otherwise. The Observe method of the Observer in the ObserverVec is
+// called with the request duration in seconds. Partitioning happens by HTTP
+// status code and/or HTTP method if the respective instance label names are
+// present in the ObserverVec. For unpartitioned observations, use an
+// ObserverVec with zero labels. Note that partitioning of Histograms is
+// expensive and should be used judiciously.
+//
+// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
+//
+// If the wrapped Handler panics, no values are reported.
+//
+// Note that this method is only guaranteed to never observe negative durations
+// if used with Go1.9+.
+func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc {
+ code, method := checkLabels(obs)
+
+ if code {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ now := time.Now()
+ d := newDelegator(w, nil)
+ next.ServeHTTP(d, r)
+
+ obs.With(labels(code, method, r.Method, d.Status())).Observe(time.Since(now).Seconds())
+ })
+ }
+
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ now := time.Now()
+ next.ServeHTTP(w, r)
+ obs.With(labels(code, method, r.Method, 0)).Observe(time.Since(now).Seconds())
+ })
+}
+
+// InstrumentHandlerCounter is a middleware that wraps the provided http.Handler
+// to observe the request result with the provided CounterVec. The CounterVec
+// must have zero, one, or two non-const non-curried labels. For those, the only
+// allowed label names are "code" and "method". The function panics
+// otherwise. Partitioning of the CounterVec happens by HTTP status code and/or
+// HTTP method if the respective instance label names are present in the
+// CounterVec. For unpartitioned counting, use a CounterVec with zero labels.
+//
+// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
+//
+// If the wrapped Handler panics, the Counter is not incremented.
+//
+// See the example for InstrumentHandlerDuration for example usage.
+func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler) http.HandlerFunc {
+ code, method := checkLabels(counter)
+
+ if code {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ d := newDelegator(w, nil)
+ next.ServeHTTP(d, r)
+ counter.With(labels(code, method, r.Method, d.Status())).Inc()
+ })
+ }
+
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ next.ServeHTTP(w, r)
+ counter.With(labels(code, method, r.Method, 0)).Inc()
+ })
+}
+
+// InstrumentHandlerTimeToWriteHeader is a middleware that wraps the provided
+// http.Handler to observe with the provided ObserverVec the request duration
+// until the response headers are written. The ObserverVec must have zero, one,
+// or two non-const non-curried labels. For those, the only allowed label names
+// are "code" and "method". The function panics otherwise. The Observe method of
+// the Observer in the ObserverVec is called with the request duration in
+// seconds. Partitioning happens by HTTP status code and/or HTTP method if the
+// respective instance label names are present in the ObserverVec. For
+// unpartitioned observations, use an ObserverVec with zero labels. Note that
+// partitioning of Histograms is expensive and should be used judiciously.
+//
+// If the wrapped Handler panics before calling WriteHeader, no value is
+// reported.
+//
+// Note that this method is only guaranteed to never observe negative durations
+// if used with Go1.9+.
+//
+// See the example for InstrumentHandlerDuration for example usage.
+func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc {
+ code, method := checkLabels(obs)
+
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ now := time.Now()
+ d := newDelegator(w, func(status int) {
+ obs.With(labels(code, method, r.Method, status)).Observe(time.Since(now).Seconds())
+ })
+ next.ServeHTTP(d, r)
+ })
+}
+
+// InstrumentHandlerRequestSize is a middleware that wraps the provided
+// http.Handler to observe the request size with the provided ObserverVec. The
+// ObserverVec must have zero, one, or two non-const non-curried labels. For
+// those, the only allowed label names are "code" and "method". The function
+// panics otherwise. The Observe method of the Observer in the ObserverVec is
+// called with the request size in bytes. Partitioning happens by HTTP status
+// code and/or HTTP method if the respective instance label names are present in
+// the ObserverVec. For unpartitioned observations, use an ObserverVec with zero
+// labels. Note that partitioning of Histograms is expensive and should be used
+// judiciously.
+//
+// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
+//
+// If the wrapped Handler panics, no values are reported.
+//
+// See the example for InstrumentHandlerDuration for example usage.
+func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc {
+ code, method := checkLabels(obs)
+
+ if code {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ d := newDelegator(w, nil)
+ next.ServeHTTP(d, r)
+ size := computeApproximateRequestSize(r)
+ obs.With(labels(code, method, r.Method, d.Status())).Observe(float64(size))
+ })
+ }
+
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ next.ServeHTTP(w, r)
+ size := computeApproximateRequestSize(r)
+ obs.With(labels(code, method, r.Method, 0)).Observe(float64(size))
+ })
+}
+
+// InstrumentHandlerResponseSize is a middleware that wraps the provided
+// http.Handler to observe the response size with the provided ObserverVec. The
+// ObserverVec must have zero, one, or two non-const non-curried labels. For
+// those, the only allowed label names are "code" and "method". The function
+// panics otherwise. The Observe method of the Observer in the ObserverVec is
+// called with the response size in bytes. Partitioning happens by HTTP status
+// code and/or HTTP method if the respective instance label names are present in
+// the ObserverVec. For unpartitioned observations, use an ObserverVec with zero
+// labels. Note that partitioning of Histograms is expensive and should be used
+// judiciously.
+//
+// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
+//
+// If the wrapped Handler panics, no values are reported.
+//
+// See the example for InstrumentHandlerDuration for example usage.
+func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler) http.Handler {
+ code, method := checkLabels(obs)
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ d := newDelegator(w, nil)
+ next.ServeHTTP(d, r)
+ obs.With(labels(code, method, r.Method, d.Status())).Observe(float64(d.Written()))
+ })
+}
+
+func checkLabels(c prometheus.Collector) (code bool, method bool) {
+ // TODO(beorn7): Remove this hacky way to check for instance labels
+ // once Descriptors can have their dimensionality queried.
+ var (
+ desc *prometheus.Desc
+ m prometheus.Metric
+ pm dto.Metric
+ lvs []string
+ )
+
+ // Get the Desc from the Collector.
+ descc := make(chan *prometheus.Desc, 1)
+ c.Describe(descc)
+
+ select {
+ case desc = <-descc:
+ default:
+ panic("no description provided by collector")
+ }
+ select {
+ case <-descc:
+ panic("more than one description provided by collector")
+ default:
+ }
+
+ close(descc)
+
+ // Create a ConstMetric with the Desc. Since we don't know how many
+ // variable labels there are, try for as long as it needs.
+ for err := errors.New("dummy"); err != nil; lvs = append(lvs, magicString) {
+ m, err = prometheus.NewConstMetric(desc, prometheus.UntypedValue, 0, lvs...)
+ }
+
+ // Write out the metric into a proto message and look at the labels.
+ // If the value is not the magicString, it is a constLabel, which doesn't interest us.
+ // If the label is curried, it doesn't interest us.
+ // In all other cases, only "code" or "method" is allowed.
+ if err := m.Write(&pm); err != nil {
+ panic("error checking metric for labels")
+ }
+ for _, label := range pm.Label {
+ name, value := label.GetName(), label.GetValue()
+ if value != magicString || isLabelCurried(c, name) {
+ continue
+ }
+ switch name {
+ case "code":
+ code = true
+ case "method":
+ method = true
+ default:
+ panic("metric partitioned with non-supported labels")
+ }
+ }
+ return
+}
+
+func isLabelCurried(c prometheus.Collector, label string) bool {
+ // This is even hackier than the label test above.
+ // We essentially try to curry again and see if it works.
+ // But for that, we need to type-convert to the two
+ // types we use here, ObserverVec or *CounterVec.
+ switch v := c.(type) {
+ case *prometheus.CounterVec:
+ if _, err := v.CurryWith(prometheus.Labels{label: "dummy"}); err == nil {
+ return false
+ }
+ case prometheus.ObserverVec:
+ if _, err := v.CurryWith(prometheus.Labels{label: "dummy"}); err == nil {
+ return false
+ }
+ default:
+ panic("unsupported metric vec type")
+ }
+ return true
+}
+
+// emptyLabels is a one-time allocation for non-partitioned metrics to avoid
+// unnecessary allocations on each request.
+var emptyLabels = prometheus.Labels{}
+
+func labels(code, method bool, reqMethod string, status int) prometheus.Labels {
+ if !(code || method) {
+ return emptyLabels
+ }
+ labels := prometheus.Labels{}
+
+ if code {
+ labels["code"] = sanitizeCode(status)
+ }
+ if method {
+ labels["method"] = sanitizeMethod(reqMethod)
+ }
+
+ return labels
+}
+
+func computeApproximateRequestSize(r *http.Request) int {
+ s := 0
+ if r.URL != nil {
+ s += len(r.URL.String())
+ }
+
+ s += len(r.Method)
+ s += len(r.Proto)
+ for name, values := range r.Header {
+ s += len(name)
+ for _, value := range values {
+ s += len(value)
+ }
+ }
+ s += len(r.Host)
+
+ // N.B. r.Form and r.MultipartForm are assumed to be included in r.URL.
+
+ if r.ContentLength != -1 {
+ s += int(r.ContentLength)
+ }
+ return s
+}
+
+func sanitizeMethod(m string) string {
+ switch m {
+ case "GET", "get":
+ return "get"
+ case "PUT", "put":
+ return "put"
+ case "HEAD", "head":
+ return "head"
+ case "POST", "post":
+ return "post"
+ case "DELETE", "delete":
+ return "delete"
+ case "CONNECT", "connect":
+ return "connect"
+ case "OPTIONS", "options":
+ return "options"
+ case "NOTIFY", "notify":
+ return "notify"
+ default:
+ return strings.ToLower(m)
+ }
+}
+
+// If the wrapped http.Handler has not set a status code, i.e. the value is
+// currently 0, santizeCode will return 200, for consistency with behavior in
+// the stdlib.
+func sanitizeCode(s int) string {
+ switch s {
+ case 100:
+ return "100"
+ case 101:
+ return "101"
+
+ case 200, 0:
+ return "200"
+ case 201:
+ return "201"
+ case 202:
+ return "202"
+ case 203:
+ return "203"
+ case 204:
+ return "204"
+ case 205:
+ return "205"
+ case 206:
+ return "206"
+
+ case 300:
+ return "300"
+ case 301:
+ return "301"
+ case 302:
+ return "302"
+ case 304:
+ return "304"
+ case 305:
+ return "305"
+ case 307:
+ return "307"
+
+ case 400:
+ return "400"
+ case 401:
+ return "401"
+ case 402:
+ return "402"
+ case 403:
+ return "403"
+ case 404:
+ return "404"
+ case 405:
+ return "405"
+ case 406:
+ return "406"
+ case 407:
+ return "407"
+ case 408:
+ return "408"
+ case 409:
+ return "409"
+ case 410:
+ return "410"
+ case 411:
+ return "411"
+ case 412:
+ return "412"
+ case 413:
+ return "413"
+ case 414:
+ return "414"
+ case 415:
+ return "415"
+ case 416:
+ return "416"
+ case 417:
+ return "417"
+ case 418:
+ return "418"
+
+ case 500:
+ return "500"
+ case 501:
+ return "501"
+ case 502:
+ return "502"
+ case 503:
+ return "503"
+ case 504:
+ return "504"
+ case 505:
+ return "505"
+
+ case 428:
+ return "428"
+ case 429:
+ return "429"
+ case 431:
+ return "431"
+ case 511:
+ return "511"
+
+ default:
+ return strconv.Itoa(s)
+ }
+}
--- /dev/null
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "os"
+ "runtime"
+ "sort"
+ "sync"
+ "unicode/utf8"
+
+ "github.com/golang/protobuf/proto"
+
+ dto "github.com/prometheus/client_model/go"
+)
+
+const (
+ // Capacity for the channel to collect metrics and descriptors.
+ capMetricChan = 1000
+ capDescChan = 10
+)
+
+// DefaultRegisterer and DefaultGatherer are the implementations of the
+// Registerer and Gatherer interface a number of convenience functions in this
+// package act on. Initially, both variables point to the same Registry, which
+// has a process collector (currently on Linux only, see NewProcessCollector)
+// and a Go collector (see NewGoCollector) already registered. This approach to
+// keep default instances as global state mirrors the approach of other packages
+// in the Go standard library. Note that there are caveats. Change the variables
+// with caution and only if you understand the consequences. Users who want to
+// avoid global state altogether should not use the convenience functions and
+// act on custom instances instead.
+var (
+ defaultRegistry = NewRegistry()
+ DefaultRegisterer Registerer = defaultRegistry
+ DefaultGatherer Gatherer = defaultRegistry
+)
+
+func init() {
+ MustRegister(NewProcessCollector(os.Getpid(), ""))
+ MustRegister(NewGoCollector())
+}
+
+// NewRegistry creates a new vanilla Registry without any Collectors
+// pre-registered.
+func NewRegistry() *Registry {
+ return &Registry{
+ collectorsByID: map[uint64]Collector{},
+ descIDs: map[uint64]struct{}{},
+ dimHashesByName: map[string]uint64{},
+ }
+}
+
+// NewPedanticRegistry returns a registry that checks during collection if each
+// collected Metric is consistent with its reported Desc, and if the Desc has
+// actually been registered with the registry.
+//
+// Usually, a Registry will be happy as long as the union of all collected
+// Metrics is consistent and valid even if some metrics are not consistent with
+// their own Desc or a Desc provided by their registered Collector. Well-behaved
+// Collectors and Metrics will only provide consistent Descs. This Registry is
+// useful to test the implementation of Collectors and Metrics.
+func NewPedanticRegistry() *Registry {
+ r := NewRegistry()
+ r.pedanticChecksEnabled = true
+ return r
+}
+
+// Registerer is the interface for the part of a registry in charge of
+// registering and unregistering. Users of custom registries should use
+// Registerer as type for registration purposes (rather than the Registry type
+// directly). In that way, they are free to use custom Registerer implementation
+// (e.g. for testing purposes).
+type Registerer interface {
+ // Register registers a new Collector to be included in metrics
+ // collection. It returns an error if the descriptors provided by the
+ // Collector are invalid or if they — in combination with descriptors of
+ // already registered Collectors — do not fulfill the consistency and
+ // uniqueness criteria described in the documentation of metric.Desc.
+ //
+ // If the provided Collector is equal to a Collector already registered
+ // (which includes the case of re-registering the same Collector), the
+ // returned error is an instance of AlreadyRegisteredError, which
+ // contains the previously registered Collector.
+ //
+ // It is in general not safe to register the same Collector multiple
+ // times concurrently.
+ Register(Collector) error
+ // MustRegister works like Register but registers any number of
+ // Collectors and panics upon the first registration that causes an
+ // error.
+ MustRegister(...Collector)
+ // Unregister unregisters the Collector that equals the Collector passed
+ // in as an argument. (Two Collectors are considered equal if their
+ // Describe method yields the same set of descriptors.) The function
+ // returns whether a Collector was unregistered.
+ //
+ // Note that even after unregistering, it will not be possible to
+ // register a new Collector that is inconsistent with the unregistered
+ // Collector, e.g. a Collector collecting metrics with the same name but
+ // a different help string. The rationale here is that the same registry
+ // instance must only collect consistent metrics throughout its
+ // lifetime.
+ Unregister(Collector) bool
+}
+
+// Gatherer is the interface for the part of a registry in charge of gathering
+// the collected metrics into a number of MetricFamilies. The Gatherer interface
+// comes with the same general implication as described for the Registerer
+// interface.
+type Gatherer interface {
+ // Gather calls the Collect method of the registered Collectors and then
+ // gathers the collected metrics into a lexicographically sorted slice
+ // of MetricFamily protobufs. Even if an error occurs, Gather attempts
+ // to gather as many metrics as possible. Hence, if a non-nil error is
+ // returned, the returned MetricFamily slice could be nil (in case of a
+ // fatal error that prevented any meaningful metric collection) or
+ // contain a number of MetricFamily protobufs, some of which might be
+ // incomplete, and some might be missing altogether. The returned error
+ // (which might be a MultiError) explains the details. In scenarios
+ // where complete collection is critical, the returned MetricFamily
+ // protobufs should be disregarded if the returned error is non-nil.
+ Gather() ([]*dto.MetricFamily, error)
+}
+
+// Register registers the provided Collector with the DefaultRegisterer.
+//
+// Register is a shortcut for DefaultRegisterer.Register(c). See there for more
+// details.
+func Register(c Collector) error {
+ return DefaultRegisterer.Register(c)
+}
+
+// MustRegister registers the provided Collectors with the DefaultRegisterer and
+// panics if any error occurs.
+//
+// MustRegister is a shortcut for DefaultRegisterer.MustRegister(cs...). See
+// there for more details.
+func MustRegister(cs ...Collector) {
+ DefaultRegisterer.MustRegister(cs...)
+}
+
+// Unregister removes the registration of the provided Collector from the
+// DefaultRegisterer.
+//
+// Unregister is a shortcut for DefaultRegisterer.Unregister(c). See there for
+// more details.
+func Unregister(c Collector) bool {
+ return DefaultRegisterer.Unregister(c)
+}
+
+// GathererFunc turns a function into a Gatherer.
+type GathererFunc func() ([]*dto.MetricFamily, error)
+
+// Gather implements Gatherer.
+func (gf GathererFunc) Gather() ([]*dto.MetricFamily, error) {
+ return gf()
+}
+
+// AlreadyRegisteredError is returned by the Register method if the Collector to
+// be registered has already been registered before, or a different Collector
+// that collects the same metrics has been registered before. Registration fails
+// in that case, but you can detect from the kind of error what has
+// happened. The error contains fields for the existing Collector and the
+// (rejected) new Collector that equals the existing one. This can be used to
+// find out if an equal Collector has been registered before and switch over to
+// using the old one, as demonstrated in the example.
+type AlreadyRegisteredError struct {
+ ExistingCollector, NewCollector Collector
+}
+
+func (err AlreadyRegisteredError) Error() string {
+ return "duplicate metrics collector registration attempted"
+}
+
+// MultiError is a slice of errors implementing the error interface. It is used
+// by a Gatherer to report multiple errors during MetricFamily gathering.
+type MultiError []error
+
+func (errs MultiError) Error() string {
+ if len(errs) == 0 {
+ return ""
+ }
+ buf := &bytes.Buffer{}
+ fmt.Fprintf(buf, "%d error(s) occurred:", len(errs))
+ for _, err := range errs {
+ fmt.Fprintf(buf, "\n* %s", err)
+ }
+ return buf.String()
+}
+
+// Append appends the provided error if it is not nil.
+func (errs *MultiError) Append(err error) {
+ if err != nil {
+ *errs = append(*errs, err)
+ }
+}
+
+// MaybeUnwrap returns nil if len(errs) is 0. It returns the first and only
+// contained error as error if len(errs is 1). In all other cases, it returns
+// the MultiError directly. This is helpful for returning a MultiError in a way
+// that only uses the MultiError if needed.
+func (errs MultiError) MaybeUnwrap() error {
+ switch len(errs) {
+ case 0:
+ return nil
+ case 1:
+ return errs[0]
+ default:
+ return errs
+ }
+}
+
+// Registry registers Prometheus collectors, collects their metrics, and gathers
+// them into MetricFamilies for exposition. It implements both Registerer and
+// Gatherer. The zero value is not usable. Create instances with NewRegistry or
+// NewPedanticRegistry.
+type Registry struct {
+ mtx sync.RWMutex
+ collectorsByID map[uint64]Collector // ID is a hash of the descIDs.
+ descIDs map[uint64]struct{}
+ dimHashesByName map[string]uint64
+ pedanticChecksEnabled bool
+}
+
+// Register implements Registerer.
+func (r *Registry) Register(c Collector) error {
+ var (
+ descChan = make(chan *Desc, capDescChan)
+ newDescIDs = map[uint64]struct{}{}
+ newDimHashesByName = map[string]uint64{}
+ collectorID uint64 // Just a sum of all desc IDs.
+ duplicateDescErr error
+ )
+ go func() {
+ c.Describe(descChan)
+ close(descChan)
+ }()
+ r.mtx.Lock()
+ defer r.mtx.Unlock()
+ // Conduct various tests...
+ for desc := range descChan {
+
+ // Is the descriptor valid at all?
+ if desc.err != nil {
+ return fmt.Errorf("descriptor %s is invalid: %s", desc, desc.err)
+ }
+
+ // Is the descID unique?
+ // (In other words: Is the fqName + constLabel combination unique?)
+ if _, exists := r.descIDs[desc.id]; exists {
+ duplicateDescErr = fmt.Errorf("descriptor %s already exists with the same fully-qualified name and const label values", desc)
+ }
+ // If it is not a duplicate desc in this collector, add it to
+ // the collectorID. (We allow duplicate descs within the same
+ // collector, but their existence must be a no-op.)
+ if _, exists := newDescIDs[desc.id]; !exists {
+ newDescIDs[desc.id] = struct{}{}
+ collectorID += desc.id
+ }
+
+ // Are all the label names and the help string consistent with
+ // previous descriptors of the same name?
+ // First check existing descriptors...
+ if dimHash, exists := r.dimHashesByName[desc.fqName]; exists {
+ if dimHash != desc.dimHash {
+ return fmt.Errorf("a previously registered descriptor with the same fully-qualified name as %s has different label names or a different help string", desc)
+ }
+ } else {
+ // ...then check the new descriptors already seen.
+ if dimHash, exists := newDimHashesByName[desc.fqName]; exists {
+ if dimHash != desc.dimHash {
+ return fmt.Errorf("descriptors reported by collector have inconsistent label names or help strings for the same fully-qualified name, offender is %s", desc)
+ }
+ } else {
+ newDimHashesByName[desc.fqName] = desc.dimHash
+ }
+ }
+ }
+ // Did anything happen at all?
+ if len(newDescIDs) == 0 {
+ return errors.New("collector has no descriptors")
+ }
+ if existing, exists := r.collectorsByID[collectorID]; exists {
+ return AlreadyRegisteredError{
+ ExistingCollector: existing,
+ NewCollector: c,
+ }
+ }
+ // If the collectorID is new, but at least one of the descs existed
+ // before, we are in trouble.
+ if duplicateDescErr != nil {
+ return duplicateDescErr
+ }
+
+ // Only after all tests have passed, actually register.
+ r.collectorsByID[collectorID] = c
+ for hash := range newDescIDs {
+ r.descIDs[hash] = struct{}{}
+ }
+ for name, dimHash := range newDimHashesByName {
+ r.dimHashesByName[name] = dimHash
+ }
+ return nil
+}
+
+// Unregister implements Registerer.
+func (r *Registry) Unregister(c Collector) bool {
+ var (
+ descChan = make(chan *Desc, capDescChan)
+ descIDs = map[uint64]struct{}{}
+ collectorID uint64 // Just a sum of the desc IDs.
+ )
+ go func() {
+ c.Describe(descChan)
+ close(descChan)
+ }()
+ for desc := range descChan {
+ if _, exists := descIDs[desc.id]; !exists {
+ collectorID += desc.id
+ descIDs[desc.id] = struct{}{}
+ }
+ }
+
+ r.mtx.RLock()
+ if _, exists := r.collectorsByID[collectorID]; !exists {
+ r.mtx.RUnlock()
+ return false
+ }
+ r.mtx.RUnlock()
+
+ r.mtx.Lock()
+ defer r.mtx.Unlock()
+
+ delete(r.collectorsByID, collectorID)
+ for id := range descIDs {
+ delete(r.descIDs, id)
+ }
+ // dimHashesByName is left untouched as those must be consistent
+ // throughout the lifetime of a program.
+ return true
+}
+
+// MustRegister implements Registerer.
+func (r *Registry) MustRegister(cs ...Collector) {
+ for _, c := range cs {
+ if err := r.Register(c); err != nil {
+ panic(err)
+ }
+ }
+}
+
+// Gather implements Gatherer.
+func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
+ var (
+ metricChan = make(chan Metric, capMetricChan)
+ metricHashes = map[uint64]struct{}{}
+ dimHashes = map[string]uint64{}
+ wg sync.WaitGroup
+ errs MultiError // The collected errors to return in the end.
+ registeredDescIDs map[uint64]struct{} // Only used for pedantic checks
+ )
+
+ r.mtx.RLock()
+ goroutineBudget := len(r.collectorsByID)
+ metricFamiliesByName := make(map[string]*dto.MetricFamily, len(r.dimHashesByName))
+ collectors := make(chan Collector, len(r.collectorsByID))
+ for _, collector := range r.collectorsByID {
+ collectors <- collector
+ }
+ // In case pedantic checks are enabled, we have to copy the map before
+ // giving up the RLock.
+ if r.pedanticChecksEnabled {
+ registeredDescIDs = make(map[uint64]struct{}, len(r.descIDs))
+ for id := range r.descIDs {
+ registeredDescIDs[id] = struct{}{}
+ }
+ }
+ r.mtx.RUnlock()
+
+ wg.Add(goroutineBudget)
+
+ collectWorker := func() {
+ for {
+ select {
+ case collector := <-collectors:
+ collector.Collect(metricChan)
+ wg.Done()
+ default:
+ return
+ }
+ }
+ }
+
+ // Start the first worker now to make sure at least one is running.
+ go collectWorker()
+ goroutineBudget--
+
+ // Close the metricChan once all collectors are collected.
+ go func() {
+ wg.Wait()
+ close(metricChan)
+ }()
+
+ // Drain metricChan in case of premature return.
+ defer func() {
+ for range metricChan {
+ }
+ }()
+
+collectLoop:
+ for {
+ select {
+ case metric, ok := <-metricChan:
+ if !ok {
+ // metricChan is closed, we are done.
+ break collectLoop
+ }
+ errs.Append(processMetric(
+ metric, metricFamiliesByName,
+ metricHashes, dimHashes,
+ registeredDescIDs,
+ ))
+ default:
+ if goroutineBudget <= 0 || len(collectors) == 0 {
+ // All collectors are aleady being worked on or
+ // we have already as many goroutines started as
+ // there are collectors. Just process metrics
+ // from now on.
+ for metric := range metricChan {
+ errs.Append(processMetric(
+ metric, metricFamiliesByName,
+ metricHashes, dimHashes,
+ registeredDescIDs,
+ ))
+ }
+ break collectLoop
+ }
+ // Start more workers.
+ go collectWorker()
+ goroutineBudget--
+ runtime.Gosched()
+ }
+ }
+ return normalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap()
+}
+
+// processMetric is an internal helper method only used by the Gather method.
+func processMetric(
+ metric Metric,
+ metricFamiliesByName map[string]*dto.MetricFamily,
+ metricHashes map[uint64]struct{},
+ dimHashes map[string]uint64,
+ registeredDescIDs map[uint64]struct{},
+) error {
+ desc := metric.Desc()
+ dtoMetric := &dto.Metric{}
+ if err := metric.Write(dtoMetric); err != nil {
+ return fmt.Errorf("error collecting metric %v: %s", desc, err)
+ }
+ metricFamily, ok := metricFamiliesByName[desc.fqName]
+ if ok {
+ if metricFamily.GetHelp() != desc.help {
+ return fmt.Errorf(
+ "collected metric %s %s has help %q but should have %q",
+ desc.fqName, dtoMetric, desc.help, metricFamily.GetHelp(),
+ )
+ }
+ // TODO(beorn7): Simplify switch once Desc has type.
+ switch metricFamily.GetType() {
+ case dto.MetricType_COUNTER:
+ if dtoMetric.Counter == nil {
+ return fmt.Errorf(
+ "collected metric %s %s should be a Counter",
+ desc.fqName, dtoMetric,
+ )
+ }
+ case dto.MetricType_GAUGE:
+ if dtoMetric.Gauge == nil {
+ return fmt.Errorf(
+ "collected metric %s %s should be a Gauge",
+ desc.fqName, dtoMetric,
+ )
+ }
+ case dto.MetricType_SUMMARY:
+ if dtoMetric.Summary == nil {
+ return fmt.Errorf(
+ "collected metric %s %s should be a Summary",
+ desc.fqName, dtoMetric,
+ )
+ }
+ case dto.MetricType_UNTYPED:
+ if dtoMetric.Untyped == nil {
+ return fmt.Errorf(
+ "collected metric %s %s should be Untyped",
+ desc.fqName, dtoMetric,
+ )
+ }
+ case dto.MetricType_HISTOGRAM:
+ if dtoMetric.Histogram == nil {
+ return fmt.Errorf(
+ "collected metric %s %s should be a Histogram",
+ desc.fqName, dtoMetric,
+ )
+ }
+ default:
+ panic("encountered MetricFamily with invalid type")
+ }
+ } else {
+ metricFamily = &dto.MetricFamily{}
+ metricFamily.Name = proto.String(desc.fqName)
+ metricFamily.Help = proto.String(desc.help)
+ // TODO(beorn7): Simplify switch once Desc has type.
+ switch {
+ case dtoMetric.Gauge != nil:
+ metricFamily.Type = dto.MetricType_GAUGE.Enum()
+ case dtoMetric.Counter != nil:
+ metricFamily.Type = dto.MetricType_COUNTER.Enum()
+ case dtoMetric.Summary != nil:
+ metricFamily.Type = dto.MetricType_SUMMARY.Enum()
+ case dtoMetric.Untyped != nil:
+ metricFamily.Type = dto.MetricType_UNTYPED.Enum()
+ case dtoMetric.Histogram != nil:
+ metricFamily.Type = dto.MetricType_HISTOGRAM.Enum()
+ default:
+ return fmt.Errorf("empty metric collected: %s", dtoMetric)
+ }
+ metricFamiliesByName[desc.fqName] = metricFamily
+ }
+ if err := checkMetricConsistency(metricFamily, dtoMetric, metricHashes, dimHashes); err != nil {
+ return err
+ }
+ if registeredDescIDs != nil {
+ // Is the desc registered at all?
+ if _, exist := registeredDescIDs[desc.id]; !exist {
+ return fmt.Errorf(
+ "collected metric %s %s with unregistered descriptor %s",
+ metricFamily.GetName(), dtoMetric, desc,
+ )
+ }
+ if err := checkDescConsistency(metricFamily, dtoMetric, desc); err != nil {
+ return err
+ }
+ }
+ metricFamily.Metric = append(metricFamily.Metric, dtoMetric)
+ return nil
+}
+
+// Gatherers is a slice of Gatherer instances that implements the Gatherer
+// interface itself. Its Gather method calls Gather on all Gatherers in the
+// slice in order and returns the merged results. Errors returned from the
+// Gather calles are all returned in a flattened MultiError. Duplicate and
+// inconsistent Metrics are skipped (first occurrence in slice order wins) and
+// reported in the returned error.
+//
+// Gatherers can be used to merge the Gather results from multiple
+// Registries. It also provides a way to directly inject existing MetricFamily
+// protobufs into the gathering by creating a custom Gatherer with a Gather
+// method that simply returns the existing MetricFamily protobufs. Note that no
+// registration is involved (in contrast to Collector registration), so
+// obviously registration-time checks cannot happen. Any inconsistencies between
+// the gathered MetricFamilies are reported as errors by the Gather method, and
+// inconsistent Metrics are dropped. Invalid parts of the MetricFamilies
+// (e.g. syntactically invalid metric or label names) will go undetected.
+type Gatherers []Gatherer
+
+// Gather implements Gatherer.
+func (gs Gatherers) Gather() ([]*dto.MetricFamily, error) {
+ var (
+ metricFamiliesByName = map[string]*dto.MetricFamily{}
+ metricHashes = map[uint64]struct{}{}
+ dimHashes = map[string]uint64{}
+ errs MultiError // The collected errors to return in the end.
+ )
+
+ for i, g := range gs {
+ mfs, err := g.Gather()
+ if err != nil {
+ if multiErr, ok := err.(MultiError); ok {
+ for _, err := range multiErr {
+ errs = append(errs, fmt.Errorf("[from Gatherer #%d] %s", i+1, err))
+ }
+ } else {
+ errs = append(errs, fmt.Errorf("[from Gatherer #%d] %s", i+1, err))
+ }
+ }
+ for _, mf := range mfs {
+ existingMF, exists := metricFamiliesByName[mf.GetName()]
+ if exists {
+ if existingMF.GetHelp() != mf.GetHelp() {
+ errs = append(errs, fmt.Errorf(
+ "gathered metric family %s has help %q but should have %q",
+ mf.GetName(), mf.GetHelp(), existingMF.GetHelp(),
+ ))
+ continue
+ }
+ if existingMF.GetType() != mf.GetType() {
+ errs = append(errs, fmt.Errorf(
+ "gathered metric family %s has type %s but should have %s",
+ mf.GetName(), mf.GetType(), existingMF.GetType(),
+ ))
+ continue
+ }
+ } else {
+ existingMF = &dto.MetricFamily{}
+ existingMF.Name = mf.Name
+ existingMF.Help = mf.Help
+ existingMF.Type = mf.Type
+ metricFamiliesByName[mf.GetName()] = existingMF
+ }
+ for _, m := range mf.Metric {
+ if err := checkMetricConsistency(existingMF, m, metricHashes, dimHashes); err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ existingMF.Metric = append(existingMF.Metric, m)
+ }
+ }
+ }
+ return normalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap()
+}
+
+// metricSorter is a sortable slice of *dto.Metric.
+type metricSorter []*dto.Metric
+
+func (s metricSorter) Len() int {
+ return len(s)
+}
+
+func (s metricSorter) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+func (s metricSorter) Less(i, j int) bool {
+ if len(s[i].Label) != len(s[j].Label) {
+ // This should not happen. The metrics are
+ // inconsistent. However, we have to deal with the fact, as
+ // people might use custom collectors or metric family injection
+ // to create inconsistent metrics. So let's simply compare the
+ // number of labels in this case. That will still yield
+ // reproducible sorting.
+ return len(s[i].Label) < len(s[j].Label)
+ }
+ for n, lp := range s[i].Label {
+ vi := lp.GetValue()
+ vj := s[j].Label[n].GetValue()
+ if vi != vj {
+ return vi < vj
+ }
+ }
+
+ // We should never arrive here. Multiple metrics with the same
+ // label set in the same scrape will lead to undefined ingestion
+ // behavior. However, as above, we have to provide stable sorting
+ // here, even for inconsistent metrics. So sort equal metrics
+ // by their timestamp, with missing timestamps (implying "now")
+ // coming last.
+ if s[i].TimestampMs == nil {
+ return false
+ }
+ if s[j].TimestampMs == nil {
+ return true
+ }
+ return s[i].GetTimestampMs() < s[j].GetTimestampMs()
+}
+
+// normalizeMetricFamilies returns a MetricFamily slice with empty
+// MetricFamilies pruned and the remaining MetricFamilies sorted by name within
+// the slice, with the contained Metrics sorted within each MetricFamily.
+func normalizeMetricFamilies(metricFamiliesByName map[string]*dto.MetricFamily) []*dto.MetricFamily {
+ for _, mf := range metricFamiliesByName {
+ sort.Sort(metricSorter(mf.Metric))
+ }
+ names := make([]string, 0, len(metricFamiliesByName))
+ for name, mf := range metricFamiliesByName {
+ if len(mf.Metric) > 0 {
+ names = append(names, name)
+ }
+ }
+ sort.Strings(names)
+ result := make([]*dto.MetricFamily, 0, len(names))
+ for _, name := range names {
+ result = append(result, metricFamiliesByName[name])
+ }
+ return result
+}
+
+// checkMetricConsistency checks if the provided Metric is consistent with the
+// provided MetricFamily. It also hashed the Metric labels and the MetricFamily
+// name. If the resulting hash is already in the provided metricHashes, an error
+// is returned. If not, it is added to metricHashes. The provided dimHashes maps
+// MetricFamily names to their dimHash (hashed sorted label names). If dimHashes
+// doesn't yet contain a hash for the provided MetricFamily, it is
+// added. Otherwise, an error is returned if the existing dimHashes in not equal
+// the calculated dimHash.
+func checkMetricConsistency(
+ metricFamily *dto.MetricFamily,
+ dtoMetric *dto.Metric,
+ metricHashes map[uint64]struct{},
+ dimHashes map[string]uint64,
+) error {
+ // Type consistency with metric family.
+ if metricFamily.GetType() == dto.MetricType_GAUGE && dtoMetric.Gauge == nil ||
+ metricFamily.GetType() == dto.MetricType_COUNTER && dtoMetric.Counter == nil ||
+ metricFamily.GetType() == dto.MetricType_SUMMARY && dtoMetric.Summary == nil ||
+ metricFamily.GetType() == dto.MetricType_HISTOGRAM && dtoMetric.Histogram == nil ||
+ metricFamily.GetType() == dto.MetricType_UNTYPED && dtoMetric.Untyped == nil {
+ return fmt.Errorf(
+ "collected metric %s %s is not a %s",
+ metricFamily.GetName(), dtoMetric, metricFamily.GetType(),
+ )
+ }
+
+ for _, labelPair := range dtoMetric.GetLabel() {
+ if !utf8.ValidString(*labelPair.Value) {
+ return fmt.Errorf("collected metric's label %s is not utf8: %#v", *labelPair.Name, *labelPair.Value)
+ }
+ }
+
+ // Is the metric unique (i.e. no other metric with the same name and the same label values)?
+ h := hashNew()
+ h = hashAdd(h, metricFamily.GetName())
+ h = hashAddByte(h, separatorByte)
+ dh := hashNew()
+ // Make sure label pairs are sorted. We depend on it for the consistency
+ // check.
+ sort.Sort(LabelPairSorter(dtoMetric.Label))
+ for _, lp := range dtoMetric.Label {
+ h = hashAdd(h, lp.GetValue())
+ h = hashAddByte(h, separatorByte)
+ dh = hashAdd(dh, lp.GetName())
+ dh = hashAddByte(dh, separatorByte)
+ }
+ if _, exists := metricHashes[h]; exists {
+ return fmt.Errorf(
+ "collected metric %s %s was collected before with the same name and label values",
+ metricFamily.GetName(), dtoMetric,
+ )
+ }
+ if dimHash, ok := dimHashes[metricFamily.GetName()]; ok {
+ if dimHash != dh {
+ return fmt.Errorf(
+ "collected metric %s %s has label dimensions inconsistent with previously collected metrics in the same metric family",
+ metricFamily.GetName(), dtoMetric,
+ )
+ }
+ } else {
+ dimHashes[metricFamily.GetName()] = dh
+ }
+ metricHashes[h] = struct{}{}
+ return nil
+}
+
+func checkDescConsistency(
+ metricFamily *dto.MetricFamily,
+ dtoMetric *dto.Metric,
+ desc *Desc,
+) error {
+ // Desc help consistency with metric family help.
+ if metricFamily.GetHelp() != desc.help {
+ return fmt.Errorf(
+ "collected metric %s %s has help %q but should have %q",
+ metricFamily.GetName(), dtoMetric, metricFamily.GetHelp(), desc.help,
+ )
+ }
+
+ // Is the desc consistent with the content of the metric?
+ lpsFromDesc := make([]*dto.LabelPair, 0, len(dtoMetric.Label))
+ lpsFromDesc = append(lpsFromDesc, desc.constLabelPairs...)
+ for _, l := range desc.variableLabels {
+ lpsFromDesc = append(lpsFromDesc, &dto.LabelPair{
+ Name: proto.String(l),
+ })
+ }
+ if len(lpsFromDesc) != len(dtoMetric.Label) {
+ return fmt.Errorf(
+ "labels in collected metric %s %s are inconsistent with descriptor %s",
+ metricFamily.GetName(), dtoMetric, desc,
+ )
+ }
+ sort.Sort(LabelPairSorter(lpsFromDesc))
+ for i, lpFromDesc := range lpsFromDesc {
+ lpFromMetric := dtoMetric.Label[i]
+ if lpFromDesc.GetName() != lpFromMetric.GetName() ||
+ lpFromDesc.Value != nil && lpFromDesc.GetValue() != lpFromMetric.GetValue() {
+ return fmt.Errorf(
+ "labels in collected metric %s %s are inconsistent with descriptor %s",
+ metricFamily.GetName(), dtoMetric, desc,
+ )
+ }
+ }
+ return nil
+}
--- /dev/null
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "fmt"
+ "math"
+ "sort"
+ "sync"
+ "time"
+
+ "github.com/beorn7/perks/quantile"
+ "github.com/golang/protobuf/proto"
+
+ dto "github.com/prometheus/client_model/go"
+)
+
+// quantileLabel is used for the label that defines the quantile in a
+// summary.
+const quantileLabel = "quantile"
+
+// A Summary captures individual observations from an event or sample stream and
+// summarizes them in a manner similar to traditional summary statistics: 1. sum
+// of observations, 2. observation count, 3. rank estimations.
+//
+// A typical use-case is the observation of request latencies. By default, a
+// Summary provides the median, the 90th and the 99th percentile of the latency
+// as rank estimations. However, the default behavior will change in the
+// upcoming v0.10 of the library. There will be no rank estiamtions at all by
+// default. For a sane transition, it is recommended to set the desired rank
+// estimations explicitly.
+//
+// Note that the rank estimations cannot be aggregated in a meaningful way with
+// the Prometheus query language (i.e. you cannot average or add them). If you
+// need aggregatable quantiles (e.g. you want the 99th percentile latency of all
+// queries served across all instances of a service), consider the Histogram
+// metric type. See the Prometheus documentation for more details.
+//
+// To create Summary instances, use NewSummary.
+type Summary interface {
+ Metric
+ Collector
+
+ // Observe adds a single observation to the summary.
+ Observe(float64)
+}
+
+// DefObjectives are the default Summary quantile values.
+//
+// Deprecated: DefObjectives will not be used as the default objectives in
+// v0.10 of the library. The default Summary will have no quantiles then.
+var (
+ DefObjectives = map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}
+
+ errQuantileLabelNotAllowed = fmt.Errorf(
+ "%q is not allowed as label name in summaries", quantileLabel,
+ )
+)
+
+// Default values for SummaryOpts.
+const (
+ // DefMaxAge is the default duration for which observations stay
+ // relevant.
+ DefMaxAge time.Duration = 10 * time.Minute
+ // DefAgeBuckets is the default number of buckets used to calculate the
+ // age of observations.
+ DefAgeBuckets = 5
+ // DefBufCap is the standard buffer size for collecting Summary observations.
+ DefBufCap = 500
+)
+
+// SummaryOpts bundles the options for creating a Summary metric. It is
+// mandatory to set Name and Help to a non-empty string. While all other fields
+// are optional and can safely be left at their zero value, it is recommended to
+// explicitly set the Objectives field to the desired value as the default value
+// will change in the upcoming v0.10 of the library.
+type SummaryOpts struct {
+ // Namespace, Subsystem, and Name are components of the fully-qualified
+ // name of the Summary (created by joining these components with
+ // "_"). Only Name is mandatory, the others merely help structuring the
+ // name. Note that the fully-qualified name of the Summary must be a
+ // valid Prometheus metric name.
+ Namespace string
+ Subsystem string
+ Name string
+
+ // Help provides information about this Summary. Mandatory!
+ //
+ // Metrics with the same fully-qualified name must have the same Help
+ // string.
+ Help string
+
+ // ConstLabels are used to attach fixed labels to this metric. Metrics
+ // with the same fully-qualified name must have the same label names in
+ // their ConstLabels.
+ //
+ // ConstLabels are only used rarely. In particular, do not use them to
+ // attach the same labels to all your metrics. Those use cases are
+ // better covered by target labels set by the scraping Prometheus
+ // server, or by one specific metric (e.g. a build_info or a
+ // machine_role metric). See also
+ // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels
+ ConstLabels Labels
+
+ // Objectives defines the quantile rank estimates with their respective
+ // absolute error. If Objectives[q] = e, then the value reported for q
+ // will be the φ-quantile value for some φ between q-e and q+e. The
+ // default value is DefObjectives. It is used if Objectives is left at
+ // its zero value (i.e. nil). To create a Summary without Objectives,
+ // set it to an empty map (i.e. map[float64]float64{}).
+ //
+ // Deprecated: Note that the current value of DefObjectives is
+ // deprecated. It will be replaced by an empty map in v0.10 of the
+ // library. Please explicitly set Objectives to the desired value.
+ Objectives map[float64]float64
+
+ // MaxAge defines the duration for which an observation stays relevant
+ // for the summary. Must be positive. The default value is DefMaxAge.
+ MaxAge time.Duration
+
+ // AgeBuckets is the number of buckets used to exclude observations that
+ // are older than MaxAge from the summary. A higher number has a
+ // resource penalty, so only increase it if the higher resolution is
+ // really required. For very high observation rates, you might want to
+ // reduce the number of age buckets. With only one age bucket, you will
+ // effectively see a complete reset of the summary each time MaxAge has
+ // passed. The default value is DefAgeBuckets.
+ AgeBuckets uint32
+
+ // BufCap defines the default sample stream buffer size. The default
+ // value of DefBufCap should suffice for most uses. If there is a need
+ // to increase the value, a multiple of 500 is recommended (because that
+ // is the internal buffer size of the underlying package
+ // "github.com/bmizerany/perks/quantile").
+ BufCap uint32
+}
+
+// Great fuck-up with the sliding-window decay algorithm... The Merge method of
+// perk/quantile is actually not working as advertised - and it might be
+// unfixable, as the underlying algorithm is apparently not capable of merging
+// summaries in the first place. To avoid using Merge, we are currently adding
+// observations to _each_ age bucket, i.e. the effort to add a sample is
+// essentially multiplied by the number of age buckets. When rotating age
+// buckets, we empty the previous head stream. On scrape time, we simply take
+// the quantiles from the head stream (no merging required). Result: More effort
+// on observation time, less effort on scrape time, which is exactly the
+// opposite of what we try to accomplish, but at least the results are correct.
+//
+// The quite elegant previous contraption to merge the age buckets efficiently
+// on scrape time (see code up commit 6b9530d72ea715f0ba612c0120e6e09fbf1d49d0)
+// can't be used anymore.
+
+// NewSummary creates a new Summary based on the provided SummaryOpts.
+func NewSummary(opts SummaryOpts) Summary {
+ return newSummary(
+ NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ nil,
+ opts.ConstLabels,
+ ),
+ opts,
+ )
+}
+
+func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
+ if len(desc.variableLabels) != len(labelValues) {
+ panic(errInconsistentCardinality)
+ }
+
+ for _, n := range desc.variableLabels {
+ if n == quantileLabel {
+ panic(errQuantileLabelNotAllowed)
+ }
+ }
+ for _, lp := range desc.constLabelPairs {
+ if lp.GetName() == quantileLabel {
+ panic(errQuantileLabelNotAllowed)
+ }
+ }
+
+ if opts.Objectives == nil {
+ opts.Objectives = DefObjectives
+ }
+
+ if opts.MaxAge < 0 {
+ panic(fmt.Errorf("illegal max age MaxAge=%v", opts.MaxAge))
+ }
+ if opts.MaxAge == 0 {
+ opts.MaxAge = DefMaxAge
+ }
+
+ if opts.AgeBuckets == 0 {
+ opts.AgeBuckets = DefAgeBuckets
+ }
+
+ if opts.BufCap == 0 {
+ opts.BufCap = DefBufCap
+ }
+
+ s := &summary{
+ desc: desc,
+
+ objectives: opts.Objectives,
+ sortedObjectives: make([]float64, 0, len(opts.Objectives)),
+
+ labelPairs: makeLabelPairs(desc, labelValues),
+
+ hotBuf: make([]float64, 0, opts.BufCap),
+ coldBuf: make([]float64, 0, opts.BufCap),
+ streamDuration: opts.MaxAge / time.Duration(opts.AgeBuckets),
+ }
+ s.headStreamExpTime = time.Now().Add(s.streamDuration)
+ s.hotBufExpTime = s.headStreamExpTime
+
+ for i := uint32(0); i < opts.AgeBuckets; i++ {
+ s.streams = append(s.streams, s.newStream())
+ }
+ s.headStream = s.streams[0]
+
+ for qu := range s.objectives {
+ s.sortedObjectives = append(s.sortedObjectives, qu)
+ }
+ sort.Float64s(s.sortedObjectives)
+
+ s.init(s) // Init self-collection.
+ return s
+}
+
+type summary struct {
+ selfCollector
+
+ bufMtx sync.Mutex // Protects hotBuf and hotBufExpTime.
+ mtx sync.Mutex // Protects every other moving part.
+ // Lock bufMtx before mtx if both are needed.
+
+ desc *Desc
+
+ objectives map[float64]float64
+ sortedObjectives []float64
+
+ labelPairs []*dto.LabelPair
+
+ sum float64
+ cnt uint64
+
+ hotBuf, coldBuf []float64
+
+ streams []*quantile.Stream
+ streamDuration time.Duration
+ headStream *quantile.Stream
+ headStreamIdx int
+ headStreamExpTime, hotBufExpTime time.Time
+}
+
+func (s *summary) Desc() *Desc {
+ return s.desc
+}
+
+func (s *summary) Observe(v float64) {
+ s.bufMtx.Lock()
+ defer s.bufMtx.Unlock()
+
+ now := time.Now()
+ if now.After(s.hotBufExpTime) {
+ s.asyncFlush(now)
+ }
+ s.hotBuf = append(s.hotBuf, v)
+ if len(s.hotBuf) == cap(s.hotBuf) {
+ s.asyncFlush(now)
+ }
+}
+
+func (s *summary) Write(out *dto.Metric) error {
+ sum := &dto.Summary{}
+ qs := make([]*dto.Quantile, 0, len(s.objectives))
+
+ s.bufMtx.Lock()
+ s.mtx.Lock()
+ // Swap bufs even if hotBuf is empty to set new hotBufExpTime.
+ s.swapBufs(time.Now())
+ s.bufMtx.Unlock()
+
+ s.flushColdBuf()
+ sum.SampleCount = proto.Uint64(s.cnt)
+ sum.SampleSum = proto.Float64(s.sum)
+
+ for _, rank := range s.sortedObjectives {
+ var q float64
+ if s.headStream.Count() == 0 {
+ q = math.NaN()
+ } else {
+ q = s.headStream.Query(rank)
+ }
+ qs = append(qs, &dto.Quantile{
+ Quantile: proto.Float64(rank),
+ Value: proto.Float64(q),
+ })
+ }
+
+ s.mtx.Unlock()
+
+ if len(qs) > 0 {
+ sort.Sort(quantSort(qs))
+ }
+ sum.Quantile = qs
+
+ out.Summary = sum
+ out.Label = s.labelPairs
+ return nil
+}
+
+func (s *summary) newStream() *quantile.Stream {
+ return quantile.NewTargeted(s.objectives)
+}
+
+// asyncFlush needs bufMtx locked.
+func (s *summary) asyncFlush(now time.Time) {
+ s.mtx.Lock()
+ s.swapBufs(now)
+
+ // Unblock the original goroutine that was responsible for the mutation
+ // that triggered the compaction. But hold onto the global non-buffer
+ // state mutex until the operation finishes.
+ go func() {
+ s.flushColdBuf()
+ s.mtx.Unlock()
+ }()
+}
+
+// rotateStreams needs mtx AND bufMtx locked.
+func (s *summary) maybeRotateStreams() {
+ for !s.hotBufExpTime.Equal(s.headStreamExpTime) {
+ s.headStream.Reset()
+ s.headStreamIdx++
+ if s.headStreamIdx >= len(s.streams) {
+ s.headStreamIdx = 0
+ }
+ s.headStream = s.streams[s.headStreamIdx]
+ s.headStreamExpTime = s.headStreamExpTime.Add(s.streamDuration)
+ }
+}
+
+// flushColdBuf needs mtx locked.
+func (s *summary) flushColdBuf() {
+ for _, v := range s.coldBuf {
+ for _, stream := range s.streams {
+ stream.Insert(v)
+ }
+ s.cnt++
+ s.sum += v
+ }
+ s.coldBuf = s.coldBuf[0:0]
+ s.maybeRotateStreams()
+}
+
+// swapBufs needs mtx AND bufMtx locked, coldBuf must be empty.
+func (s *summary) swapBufs(now time.Time) {
+ if len(s.coldBuf) != 0 {
+ panic("coldBuf is not empty")
+ }
+ s.hotBuf, s.coldBuf = s.coldBuf, s.hotBuf
+ // hotBuf is now empty and gets new expiration set.
+ for now.After(s.hotBufExpTime) {
+ s.hotBufExpTime = s.hotBufExpTime.Add(s.streamDuration)
+ }
+}
+
+type quantSort []*dto.Quantile
+
+func (s quantSort) Len() int {
+ return len(s)
+}
+
+func (s quantSort) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+func (s quantSort) Less(i, j int) bool {
+ return s[i].GetQuantile() < s[j].GetQuantile()
+}
+
+// SummaryVec is a Collector that bundles a set of Summaries that all share the
+// same Desc, but have different values for their variable labels. This is used
+// if you want to count the same thing partitioned by various dimensions
+// (e.g. HTTP request latencies, partitioned by status code and method). Create
+// instances with NewSummaryVec.
+type SummaryVec struct {
+ *metricVec
+}
+
+// NewSummaryVec creates a new SummaryVec based on the provided SummaryOpts and
+// partitioned by the given label names.
+func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec {
+ desc := NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ labelNames,
+ opts.ConstLabels,
+ )
+ return &SummaryVec{
+ metricVec: newMetricVec(desc, func(lvs ...string) Metric {
+ return newSummary(desc, opts, lvs...)
+ }),
+ }
+}
+
+// GetMetricWithLabelValues returns the Summary for the given slice of label
+// values (same order as the VariableLabels in Desc). If that combination of
+// label values is accessed for the first time, a new Summary is created.
+//
+// It is possible to call this method without using the returned Summary to only
+// create the new Summary but leave it at its starting value, a Summary without
+// any observations.
+//
+// Keeping the Summary for later use is possible (and should be considered if
+// performance is critical), but keep in mind that Reset, DeleteLabelValues and
+// Delete can be used to delete the Summary from the SummaryVec. In that case,
+// the Summary will still exist, but it will not be exported anymore, even if a
+// Summary with the same label values is created later. See also the CounterVec
+// example.
+//
+// An error is returned if the number of label values is not the same as the
+// number of VariableLabels in Desc (minus any curried labels).
+//
+// Note that for more than one label value, this method is prone to mistakes
+// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
+// an alternative to avoid that type of mistake. For higher label numbers, the
+// latter has a much more readable (albeit more verbose) syntax, but it comes
+// with a performance overhead (for creating and processing the Labels map).
+// See also the GaugeVec example.
+func (v *SummaryVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) {
+ metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
+ if metric != nil {
+ return metric.(Observer), err
+ }
+ return nil, err
+}
+
+// GetMetricWith returns the Summary for the given Labels map (the label names
+// must match those of the VariableLabels in Desc). If that label map is
+// accessed for the first time, a new Summary is created. Implications of
+// creating a Summary without using it and keeping the Summary for later use are
+// the same as for GetMetricWithLabelValues.
+//
+// An error is returned if the number and names of the Labels are inconsistent
+// with those of the VariableLabels in Desc (minus any curried labels).
+//
+// This method is used for the same purpose as
+// GetMetricWithLabelValues(...string). See there for pros and cons of the two
+// methods.
+func (v *SummaryVec) GetMetricWith(labels Labels) (Observer, error) {
+ metric, err := v.metricVec.getMetricWith(labels)
+ if metric != nil {
+ return metric.(Observer), err
+ }
+ return nil, err
+}
+
+// WithLabelValues works as GetMetricWithLabelValues, but panics where
+// GetMetricWithLabelValues would have returned an error. Not returning an
+// error allows shortcuts like
+// myVec.WithLabelValues("404", "GET").Observe(42.21)
+func (v *SummaryVec) WithLabelValues(lvs ...string) Observer {
+ s, err := v.GetMetricWithLabelValues(lvs...)
+ if err != nil {
+ panic(err)
+ }
+ return s
+}
+
+// With works as GetMetricWith, but panics where GetMetricWithLabels would have
+// returned an error. Not returning an error allows shortcuts like
+// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Observe(42.21)
+func (v *SummaryVec) With(labels Labels) Observer {
+ s, err := v.GetMetricWith(labels)
+ if err != nil {
+ panic(err)
+ }
+ return s
+}
+
+// CurryWith returns a vector curried with the provided labels, i.e. the
+// returned vector has those labels pre-set for all labeled operations performed
+// on it. The cardinality of the curried vector is reduced accordingly. The
+// order of the remaining labels stays the same (just with the curried labels
+// taken out of the sequence – which is relevant for the
+// (GetMetric)WithLabelValues methods). It is possible to curry a curried
+// vector, but only with labels not yet used for currying before.
+//
+// The metrics contained in the SummaryVec are shared between the curried and
+// uncurried vectors. They are just accessed differently. Curried and uncurried
+// vectors behave identically in terms of collection. Only one must be
+// registered with a given registry (usually the uncurried version). The Reset
+// method deletes all metrics, even if called on a curried vector.
+func (v *SummaryVec) CurryWith(labels Labels) (ObserverVec, error) {
+ vec, err := v.curryWith(labels)
+ if vec != nil {
+ return &SummaryVec{vec}, err
+ }
+ return nil, err
+}
+
+// MustCurryWith works as CurryWith but panics where CurryWith would have
+// returned an error.
+func (v *SummaryVec) MustCurryWith(labels Labels) ObserverVec {
+ vec, err := v.CurryWith(labels)
+ if err != nil {
+ panic(err)
+ }
+ return vec
+}
+
+type constSummary struct {
+ desc *Desc
+ count uint64
+ sum float64
+ quantiles map[float64]float64
+ labelPairs []*dto.LabelPair
+}
+
+func (s *constSummary) Desc() *Desc {
+ return s.desc
+}
+
+func (s *constSummary) Write(out *dto.Metric) error {
+ sum := &dto.Summary{}
+ qs := make([]*dto.Quantile, 0, len(s.quantiles))
+
+ sum.SampleCount = proto.Uint64(s.count)
+ sum.SampleSum = proto.Float64(s.sum)
+
+ for rank, q := range s.quantiles {
+ qs = append(qs, &dto.Quantile{
+ Quantile: proto.Float64(rank),
+ Value: proto.Float64(q),
+ })
+ }
+
+ if len(qs) > 0 {
+ sort.Sort(quantSort(qs))
+ }
+ sum.Quantile = qs
+
+ out.Summary = sum
+ out.Label = s.labelPairs
+
+ return nil
+}
+
+// NewConstSummary returns a metric representing a Prometheus summary with fixed
+// values for the count, sum, and quantiles. As those parameters cannot be
+// changed, the returned value does not implement the Summary interface (but
+// only the Metric interface). Users of this package will not have much use for
+// it in regular operations. However, when implementing custom Collectors, it is
+// useful as a throw-away metric that is generated on the fly to send it to
+// Prometheus in the Collect method.
+//
+// quantiles maps ranks to quantile values. For example, a median latency of
+// 0.23s and a 99th percentile latency of 0.56s would be expressed as:
+// map[float64]float64{0.5: 0.23, 0.99: 0.56}
+//
+// NewConstSummary returns an error if the length of labelValues is not
+// consistent with the variable labels in Desc.
+func NewConstSummary(
+ desc *Desc,
+ count uint64,
+ sum float64,
+ quantiles map[float64]float64,
+ labelValues ...string,
+) (Metric, error) {
+ if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil {
+ return nil, err
+ }
+ return &constSummary{
+ desc: desc,
+ count: count,
+ sum: sum,
+ quantiles: quantiles,
+ labelPairs: makeLabelPairs(desc, labelValues),
+ }, nil
+}
+
+// MustNewConstSummary is a version of NewConstSummary that panics where
+// NewConstMetric would have returned an error.
+func MustNewConstSummary(
+ desc *Desc,
+ count uint64,
+ sum float64,
+ quantiles map[float64]float64,
+ labelValues ...string,
+) Metric {
+ m, err := NewConstSummary(desc, count, sum, quantiles, labelValues...)
+ if err != nil {
+ panic(err)
+ }
+ return m
+}
--- /dev/null
+// Copyright 2016 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import "time"
+
+// Timer is a helper type to time functions. Use NewTimer to create new
+// instances.
+type Timer struct {
+ begin time.Time
+ observer Observer
+}
+
+// NewTimer creates a new Timer. The provided Observer is used to observe a
+// duration in seconds. Timer is usually used to time a function call in the
+// following way:
+// func TimeMe() {
+// timer := NewTimer(myHistogram)
+// defer timer.ObserveDuration()
+// // Do actual work.
+// }
+func NewTimer(o Observer) *Timer {
+ return &Timer{
+ begin: time.Now(),
+ observer: o,
+ }
+}
+
+// ObserveDuration records the duration passed since the Timer was created with
+// NewTimer. It calls the Observe method of the Observer provided during
+// construction with the duration in seconds as an argument. ObserveDuration is
+// usually called with a defer statement.
+//
+// Note that this method is only guaranteed to never observe negative durations
+// if used with Go1.9+.
+func (t *Timer) ObserveDuration() {
+ if t.observer != nil {
+ t.observer.Observe(time.Since(t.begin).Seconds())
+ }
+}
--- /dev/null
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+// UntypedOpts is an alias for Opts. See there for doc comments.
+type UntypedOpts Opts
+
+// UntypedFunc works like GaugeFunc but the collected metric is of type
+// "Untyped". UntypedFunc is useful to mirror an external metric of unknown
+// type.
+//
+// To create UntypedFunc instances, use NewUntypedFunc.
+type UntypedFunc interface {
+ Metric
+ Collector
+}
+
+// NewUntypedFunc creates a new UntypedFunc based on the provided
+// UntypedOpts. The value reported is determined by calling the given function
+// from within the Write method. Take into account that metric collection may
+// happen concurrently. If that results in concurrent calls to Write, like in
+// the case where an UntypedFunc is directly registered with Prometheus, the
+// provided function must be concurrency-safe.
+func NewUntypedFunc(opts UntypedOpts, function func() float64) UntypedFunc {
+ return newValueFunc(NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ nil,
+ opts.ConstLabels,
+ ), UntypedValue, function)
+}
--- /dev/null
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "fmt"
+ "sort"
+
+ dto "github.com/prometheus/client_model/go"
+
+ "github.com/golang/protobuf/proto"
+)
+
+// ValueType is an enumeration of metric types that represent a simple value.
+type ValueType int
+
+// Possible values for the ValueType enum.
+const (
+ _ ValueType = iota
+ CounterValue
+ GaugeValue
+ UntypedValue
+)
+
+// valueFunc is a generic metric for simple values retrieved on collect time
+// from a function. It implements Metric and Collector. Its effective type is
+// determined by ValueType. This is a low-level building block used by the
+// library to back the implementations of CounterFunc, GaugeFunc, and
+// UntypedFunc.
+type valueFunc struct {
+ selfCollector
+
+ desc *Desc
+ valType ValueType
+ function func() float64
+ labelPairs []*dto.LabelPair
+}
+
+// newValueFunc returns a newly allocated valueFunc with the given Desc and
+// ValueType. The value reported is determined by calling the given function
+// from within the Write method. Take into account that metric collection may
+// happen concurrently. If that results in concurrent calls to Write, like in
+// the case where a valueFunc is directly registered with Prometheus, the
+// provided function must be concurrency-safe.
+func newValueFunc(desc *Desc, valueType ValueType, function func() float64) *valueFunc {
+ result := &valueFunc{
+ desc: desc,
+ valType: valueType,
+ function: function,
+ labelPairs: makeLabelPairs(desc, nil),
+ }
+ result.init(result)
+ return result
+}
+
+func (v *valueFunc) Desc() *Desc {
+ return v.desc
+}
+
+func (v *valueFunc) Write(out *dto.Metric) error {
+ return populateMetric(v.valType, v.function(), v.labelPairs, out)
+}
+
+// NewConstMetric returns a metric with one fixed value that cannot be
+// changed. Users of this package will not have much use for it in regular
+// operations. However, when implementing custom Collectors, it is useful as a
+// throw-away metric that is generated on the fly to send it to Prometheus in
+// the Collect method. NewConstMetric returns an error if the length of
+// labelValues is not consistent with the variable labels in Desc.
+func NewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues ...string) (Metric, error) {
+ if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil {
+ return nil, err
+ }
+ return &constMetric{
+ desc: desc,
+ valType: valueType,
+ val: value,
+ labelPairs: makeLabelPairs(desc, labelValues),
+ }, nil
+}
+
+// MustNewConstMetric is a version of NewConstMetric that panics where
+// NewConstMetric would have returned an error.
+func MustNewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues ...string) Metric {
+ m, err := NewConstMetric(desc, valueType, value, labelValues...)
+ if err != nil {
+ panic(err)
+ }
+ return m
+}
+
+type constMetric struct {
+ desc *Desc
+ valType ValueType
+ val float64
+ labelPairs []*dto.LabelPair
+}
+
+func (m *constMetric) Desc() *Desc {
+ return m.desc
+}
+
+func (m *constMetric) Write(out *dto.Metric) error {
+ return populateMetric(m.valType, m.val, m.labelPairs, out)
+}
+
+func populateMetric(
+ t ValueType,
+ v float64,
+ labelPairs []*dto.LabelPair,
+ m *dto.Metric,
+) error {
+ m.Label = labelPairs
+ switch t {
+ case CounterValue:
+ m.Counter = &dto.Counter{Value: proto.Float64(v)}
+ case GaugeValue:
+ m.Gauge = &dto.Gauge{Value: proto.Float64(v)}
+ case UntypedValue:
+ m.Untyped = &dto.Untyped{Value: proto.Float64(v)}
+ default:
+ return fmt.Errorf("encountered unknown type %v", t)
+ }
+ return nil
+}
+
+func makeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
+ totalLen := len(desc.variableLabels) + len(desc.constLabelPairs)
+ if totalLen == 0 {
+ // Super fast path.
+ return nil
+ }
+ if len(desc.variableLabels) == 0 {
+ // Moderately fast path.
+ return desc.constLabelPairs
+ }
+ labelPairs := make([]*dto.LabelPair, 0, totalLen)
+ for i, n := range desc.variableLabels {
+ labelPairs = append(labelPairs, &dto.LabelPair{
+ Name: proto.String(n),
+ Value: proto.String(labelValues[i]),
+ })
+ }
+ for _, lp := range desc.constLabelPairs {
+ labelPairs = append(labelPairs, lp)
+ }
+ sort.Sort(LabelPairSorter(labelPairs))
+ return labelPairs
+}
--- /dev/null
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "fmt"
+ "sync"
+
+ "github.com/prometheus/common/model"
+)
+
+// metricVec is a Collector to bundle metrics of the same name that differ in
+// their label values. metricVec is not used directly (and therefore
+// unexported). It is used as a building block for implementations of vectors of
+// a given metric type, like GaugeVec, CounterVec, SummaryVec, and HistogramVec.
+// It also handles label currying. It uses basicMetricVec internally.
+type metricVec struct {
+ *metricMap
+
+ curry []curriedLabelValue
+
+ // hashAdd and hashAddByte can be replaced for testing collision handling.
+ hashAdd func(h uint64, s string) uint64
+ hashAddByte func(h uint64, b byte) uint64
+}
+
+// newMetricVec returns an initialized metricVec.
+func newMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *metricVec {
+ return &metricVec{
+ metricMap: &metricMap{
+ metrics: map[uint64][]metricWithLabelValues{},
+ desc: desc,
+ newMetric: newMetric,
+ },
+ hashAdd: hashAdd,
+ hashAddByte: hashAddByte,
+ }
+}
+
+// DeleteLabelValues removes the metric where the variable labels are the same
+// as those passed in as labels (same order as the VariableLabels in Desc). It
+// returns true if a metric was deleted.
+//
+// It is not an error if the number of label values is not the same as the
+// number of VariableLabels in Desc. However, such inconsistent label count can
+// never match an actual metric, so the method will always return false in that
+// case.
+//
+// Note that for more than one label value, this method is prone to mistakes
+// caused by an incorrect order of arguments. Consider Delete(Labels) as an
+// alternative to avoid that type of mistake. For higher label numbers, the
+// latter has a much more readable (albeit more verbose) syntax, but it comes
+// with a performance overhead (for creating and processing the Labels map).
+// See also the CounterVec example.
+func (m *metricVec) DeleteLabelValues(lvs ...string) bool {
+ h, err := m.hashLabelValues(lvs)
+ if err != nil {
+ return false
+ }
+
+ return m.metricMap.deleteByHashWithLabelValues(h, lvs, m.curry)
+}
+
+// Delete deletes the metric where the variable labels are the same as those
+// passed in as labels. It returns true if a metric was deleted.
+//
+// It is not an error if the number and names of the Labels are inconsistent
+// with those of the VariableLabels in Desc. However, such inconsistent Labels
+// can never match an actual metric, so the method will always return false in
+// that case.
+//
+// This method is used for the same purpose as DeleteLabelValues(...string). See
+// there for pros and cons of the two methods.
+func (m *metricVec) Delete(labels Labels) bool {
+ h, err := m.hashLabels(labels)
+ if err != nil {
+ return false
+ }
+
+ return m.metricMap.deleteByHashWithLabels(h, labels, m.curry)
+}
+
+func (m *metricVec) curryWith(labels Labels) (*metricVec, error) {
+ var (
+ newCurry []curriedLabelValue
+ oldCurry = m.curry
+ iCurry int
+ )
+ for i, label := range m.desc.variableLabels {
+ val, ok := labels[label]
+ if iCurry < len(oldCurry) && oldCurry[iCurry].index == i {
+ if ok {
+ return nil, fmt.Errorf("label name %q is already curried", label)
+ }
+ newCurry = append(newCurry, oldCurry[iCurry])
+ iCurry++
+ } else {
+ if !ok {
+ continue // Label stays uncurried.
+ }
+ newCurry = append(newCurry, curriedLabelValue{i, val})
+ }
+ }
+ if l := len(oldCurry) + len(labels) - len(newCurry); l > 0 {
+ return nil, fmt.Errorf("%d unknown label(s) found during currying", l)
+ }
+
+ return &metricVec{
+ metricMap: m.metricMap,
+ curry: newCurry,
+ hashAdd: m.hashAdd,
+ hashAddByte: m.hashAddByte,
+ }, nil
+}
+
+func (m *metricVec) getMetricWithLabelValues(lvs ...string) (Metric, error) {
+ h, err := m.hashLabelValues(lvs)
+ if err != nil {
+ return nil, err
+ }
+
+ return m.metricMap.getOrCreateMetricWithLabelValues(h, lvs, m.curry), nil
+}
+
+func (m *metricVec) getMetricWith(labels Labels) (Metric, error) {
+ h, err := m.hashLabels(labels)
+ if err != nil {
+ return nil, err
+ }
+
+ return m.metricMap.getOrCreateMetricWithLabels(h, labels, m.curry), nil
+}
+
+func (m *metricVec) hashLabelValues(vals []string) (uint64, error) {
+ if err := validateLabelValues(vals, len(m.desc.variableLabels)-len(m.curry)); err != nil {
+ return 0, err
+ }
+
+ var (
+ h = hashNew()
+ curry = m.curry
+ iVals, iCurry int
+ )
+ for i := 0; i < len(m.desc.variableLabels); i++ {
+ if iCurry < len(curry) && curry[iCurry].index == i {
+ h = m.hashAdd(h, curry[iCurry].value)
+ iCurry++
+ } else {
+ h = m.hashAdd(h, vals[iVals])
+ iVals++
+ }
+ h = m.hashAddByte(h, model.SeparatorByte)
+ }
+ return h, nil
+}
+
+func (m *metricVec) hashLabels(labels Labels) (uint64, error) {
+ if err := validateValuesInLabels(labels, len(m.desc.variableLabels)-len(m.curry)); err != nil {
+ return 0, err
+ }
+
+ var (
+ h = hashNew()
+ curry = m.curry
+ iCurry int
+ )
+ for i, label := range m.desc.variableLabels {
+ val, ok := labels[label]
+ if iCurry < len(curry) && curry[iCurry].index == i {
+ if ok {
+ return 0, fmt.Errorf("label name %q is already curried", label)
+ }
+ h = m.hashAdd(h, curry[iCurry].value)
+ iCurry++
+ } else {
+ if !ok {
+ return 0, fmt.Errorf("label name %q missing in label map", label)
+ }
+ h = m.hashAdd(h, val)
+ }
+ h = m.hashAddByte(h, model.SeparatorByte)
+ }
+ return h, nil
+}
+
+// metricWithLabelValues provides the metric and its label values for
+// disambiguation on hash collision.
+type metricWithLabelValues struct {
+ values []string
+ metric Metric
+}
+
+// curriedLabelValue sets the curried value for a label at the given index.
+type curriedLabelValue struct {
+ index int
+ value string
+}
+
+// metricMap is a helper for metricVec and shared between differently curried
+// metricVecs.
+type metricMap struct {
+ mtx sync.RWMutex // Protects metrics.
+ metrics map[uint64][]metricWithLabelValues
+ desc *Desc
+ newMetric func(labelValues ...string) Metric
+}
+
+// Describe implements Collector. It will send exactly one Desc to the provided
+// channel.
+func (m *metricMap) Describe(ch chan<- *Desc) {
+ ch <- m.desc
+}
+
+// Collect implements Collector.
+func (m *metricMap) Collect(ch chan<- Metric) {
+ m.mtx.RLock()
+ defer m.mtx.RUnlock()
+
+ for _, metrics := range m.metrics {
+ for _, metric := range metrics {
+ ch <- metric.metric
+ }
+ }
+}
+
+// Reset deletes all metrics in this vector.
+func (m *metricMap) Reset() {
+ m.mtx.Lock()
+ defer m.mtx.Unlock()
+
+ for h := range m.metrics {
+ delete(m.metrics, h)
+ }
+}
+
+// deleteByHashWithLabelValues removes the metric from the hash bucket h. If
+// there are multiple matches in the bucket, use lvs to select a metric and
+// remove only that metric.
+func (m *metricMap) deleteByHashWithLabelValues(
+ h uint64, lvs []string, curry []curriedLabelValue,
+) bool {
+ m.mtx.Lock()
+ defer m.mtx.Unlock()
+
+ metrics, ok := m.metrics[h]
+ if !ok {
+ return false
+ }
+
+ i := findMetricWithLabelValues(metrics, lvs, curry)
+ if i >= len(metrics) {
+ return false
+ }
+
+ if len(metrics) > 1 {
+ m.metrics[h] = append(metrics[:i], metrics[i+1:]...)
+ } else {
+ delete(m.metrics, h)
+ }
+ return true
+}
+
+// deleteByHashWithLabels removes the metric from the hash bucket h. If there
+// are multiple matches in the bucket, use lvs to select a metric and remove
+// only that metric.
+func (m *metricMap) deleteByHashWithLabels(
+ h uint64, labels Labels, curry []curriedLabelValue,
+) bool {
+ metrics, ok := m.metrics[h]
+ if !ok {
+ return false
+ }
+ i := findMetricWithLabels(m.desc, metrics, labels, curry)
+ if i >= len(metrics) {
+ return false
+ }
+
+ if len(metrics) > 1 {
+ m.metrics[h] = append(metrics[:i], metrics[i+1:]...)
+ } else {
+ delete(m.metrics, h)
+ }
+ return true
+}
+
+// getOrCreateMetricWithLabelValues retrieves the metric by hash and label value
+// or creates it and returns the new one.
+//
+// This function holds the mutex.
+func (m *metricMap) getOrCreateMetricWithLabelValues(
+ hash uint64, lvs []string, curry []curriedLabelValue,
+) Metric {
+ m.mtx.RLock()
+ metric, ok := m.getMetricWithHashAndLabelValues(hash, lvs, curry)
+ m.mtx.RUnlock()
+ if ok {
+ return metric
+ }
+
+ m.mtx.Lock()
+ defer m.mtx.Unlock()
+ metric, ok = m.getMetricWithHashAndLabelValues(hash, lvs, curry)
+ if !ok {
+ inlinedLVs := inlineLabelValues(lvs, curry)
+ metric = m.newMetric(inlinedLVs...)
+ m.metrics[hash] = append(m.metrics[hash], metricWithLabelValues{values: inlinedLVs, metric: metric})
+ }
+ return metric
+}
+
+// getOrCreateMetricWithLabelValues retrieves the metric by hash and label value
+// or creates it and returns the new one.
+//
+// This function holds the mutex.
+func (m *metricMap) getOrCreateMetricWithLabels(
+ hash uint64, labels Labels, curry []curriedLabelValue,
+) Metric {
+ m.mtx.RLock()
+ metric, ok := m.getMetricWithHashAndLabels(hash, labels, curry)
+ m.mtx.RUnlock()
+ if ok {
+ return metric
+ }
+
+ m.mtx.Lock()
+ defer m.mtx.Unlock()
+ metric, ok = m.getMetricWithHashAndLabels(hash, labels, curry)
+ if !ok {
+ lvs := extractLabelValues(m.desc, labels, curry)
+ metric = m.newMetric(lvs...)
+ m.metrics[hash] = append(m.metrics[hash], metricWithLabelValues{values: lvs, metric: metric})
+ }
+ return metric
+}
+
+// getMetricWithHashAndLabelValues gets a metric while handling possible
+// collisions in the hash space. Must be called while holding the read mutex.
+func (m *metricMap) getMetricWithHashAndLabelValues(
+ h uint64, lvs []string, curry []curriedLabelValue,
+) (Metric, bool) {
+ metrics, ok := m.metrics[h]
+ if ok {
+ if i := findMetricWithLabelValues(metrics, lvs, curry); i < len(metrics) {
+ return metrics[i].metric, true
+ }
+ }
+ return nil, false
+}
+
+// getMetricWithHashAndLabels gets a metric while handling possible collisions in
+// the hash space. Must be called while holding read mutex.
+func (m *metricMap) getMetricWithHashAndLabels(
+ h uint64, labels Labels, curry []curriedLabelValue,
+) (Metric, bool) {
+ metrics, ok := m.metrics[h]
+ if ok {
+ if i := findMetricWithLabels(m.desc, metrics, labels, curry); i < len(metrics) {
+ return metrics[i].metric, true
+ }
+ }
+ return nil, false
+}
+
+// findMetricWithLabelValues returns the index of the matching metric or
+// len(metrics) if not found.
+func findMetricWithLabelValues(
+ metrics []metricWithLabelValues, lvs []string, curry []curriedLabelValue,
+) int {
+ for i, metric := range metrics {
+ if matchLabelValues(metric.values, lvs, curry) {
+ return i
+ }
+ }
+ return len(metrics)
+}
+
+// findMetricWithLabels returns the index of the matching metric or len(metrics)
+// if not found.
+func findMetricWithLabels(
+ desc *Desc, metrics []metricWithLabelValues, labels Labels, curry []curriedLabelValue,
+) int {
+ for i, metric := range metrics {
+ if matchLabels(desc, metric.values, labels, curry) {
+ return i
+ }
+ }
+ return len(metrics)
+}
+
+func matchLabelValues(values []string, lvs []string, curry []curriedLabelValue) bool {
+ if len(values) != len(lvs)+len(curry) {
+ return false
+ }
+ var iLVs, iCurry int
+ for i, v := range values {
+ if iCurry < len(curry) && curry[iCurry].index == i {
+ if v != curry[iCurry].value {
+ return false
+ }
+ iCurry++
+ continue
+ }
+ if v != lvs[iLVs] {
+ return false
+ }
+ iLVs++
+ }
+ return true
+}
+
+func matchLabels(desc *Desc, values []string, labels Labels, curry []curriedLabelValue) bool {
+ if len(values) != len(labels)+len(curry) {
+ return false
+ }
+ iCurry := 0
+ for i, k := range desc.variableLabels {
+ if iCurry < len(curry) && curry[iCurry].index == i {
+ if values[i] != curry[iCurry].value {
+ return false
+ }
+ iCurry++
+ continue
+ }
+ if values[i] != labels[k] {
+ return false
+ }
+ }
+ return true
+}
+
+func extractLabelValues(desc *Desc, labels Labels, curry []curriedLabelValue) []string {
+ labelValues := make([]string, len(labels)+len(curry))
+ iCurry := 0
+ for i, k := range desc.variableLabels {
+ if iCurry < len(curry) && curry[iCurry].index == i {
+ labelValues[i] = curry[iCurry].value
+ iCurry++
+ continue
+ }
+ labelValues[i] = labels[k]
+ }
+ return labelValues
+}
+
+func inlineLabelValues(lvs []string, curry []curriedLabelValue) []string {
+ labelValues := make([]string, len(lvs)+len(curry))
+ var iCurry, iLVs int
+ for i := range labelValues {
+ if iCurry < len(curry) && curry[iCurry].index == i {
+ labelValues[i] = curry[iCurry].value
+ iCurry++
+ continue
+ }
+ labelValues[i] = lvs[iLVs]
+ iLVs++
+ }
+ return labelValues
+}
--- /dev/null
+// Code generated by protoc-gen-go.
+// source: metrics.proto
+// DO NOT EDIT!
+
+/*
+Package io_prometheus_client is a generated protocol buffer package.
+
+It is generated from these files:
+ metrics.proto
+
+It has these top-level messages:
+ LabelPair
+ Gauge
+ Counter
+ Quantile
+ Summary
+ Untyped
+ Histogram
+ Bucket
+ Metric
+ MetricFamily
+*/
+package io_prometheus_client
+
+import proto "github.com/golang/protobuf/proto"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = math.Inf
+
+type MetricType int32
+
+const (
+ MetricType_COUNTER MetricType = 0
+ MetricType_GAUGE MetricType = 1
+ MetricType_SUMMARY MetricType = 2
+ MetricType_UNTYPED MetricType = 3
+ MetricType_HISTOGRAM MetricType = 4
+)
+
+var MetricType_name = map[int32]string{
+ 0: "COUNTER",
+ 1: "GAUGE",
+ 2: "SUMMARY",
+ 3: "UNTYPED",
+ 4: "HISTOGRAM",
+}
+var MetricType_value = map[string]int32{
+ "COUNTER": 0,
+ "GAUGE": 1,
+ "SUMMARY": 2,
+ "UNTYPED": 3,
+ "HISTOGRAM": 4,
+}
+
+func (x MetricType) Enum() *MetricType {
+ p := new(MetricType)
+ *p = x
+ return p
+}
+func (x MetricType) String() string {
+ return proto.EnumName(MetricType_name, int32(x))
+}
+func (x *MetricType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(MetricType_value, data, "MetricType")
+ if err != nil {
+ return err
+ }
+ *x = MetricType(value)
+ return nil
+}
+
+type LabelPair struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *LabelPair) Reset() { *m = LabelPair{} }
+func (m *LabelPair) String() string { return proto.CompactTextString(m) }
+func (*LabelPair) ProtoMessage() {}
+
+func (m *LabelPair) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *LabelPair) GetValue() string {
+ if m != nil && m.Value != nil {
+ return *m.Value
+ }
+ return ""
+}
+
+type Gauge struct {
+ Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Gauge) Reset() { *m = Gauge{} }
+func (m *Gauge) String() string { return proto.CompactTextString(m) }
+func (*Gauge) ProtoMessage() {}
+
+func (m *Gauge) GetValue() float64 {
+ if m != nil && m.Value != nil {
+ return *m.Value
+ }
+ return 0
+}
+
+type Counter struct {
+ Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Counter) Reset() { *m = Counter{} }
+func (m *Counter) String() string { return proto.CompactTextString(m) }
+func (*Counter) ProtoMessage() {}
+
+func (m *Counter) GetValue() float64 {
+ if m != nil && m.Value != nil {
+ return *m.Value
+ }
+ return 0
+}
+
+type Quantile struct {
+ Quantile *float64 `protobuf:"fixed64,1,opt,name=quantile" json:"quantile,omitempty"`
+ Value *float64 `protobuf:"fixed64,2,opt,name=value" json:"value,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Quantile) Reset() { *m = Quantile{} }
+func (m *Quantile) String() string { return proto.CompactTextString(m) }
+func (*Quantile) ProtoMessage() {}
+
+func (m *Quantile) GetQuantile() float64 {
+ if m != nil && m.Quantile != nil {
+ return *m.Quantile
+ }
+ return 0
+}
+
+func (m *Quantile) GetValue() float64 {
+ if m != nil && m.Value != nil {
+ return *m.Value
+ }
+ return 0
+}
+
+type Summary struct {
+ SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count" json:"sample_count,omitempty"`
+ SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum" json:"sample_sum,omitempty"`
+ Quantile []*Quantile `protobuf:"bytes,3,rep,name=quantile" json:"quantile,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Summary) Reset() { *m = Summary{} }
+func (m *Summary) String() string { return proto.CompactTextString(m) }
+func (*Summary) ProtoMessage() {}
+
+func (m *Summary) GetSampleCount() uint64 {
+ if m != nil && m.SampleCount != nil {
+ return *m.SampleCount
+ }
+ return 0
+}
+
+func (m *Summary) GetSampleSum() float64 {
+ if m != nil && m.SampleSum != nil {
+ return *m.SampleSum
+ }
+ return 0
+}
+
+func (m *Summary) GetQuantile() []*Quantile {
+ if m != nil {
+ return m.Quantile
+ }
+ return nil
+}
+
+type Untyped struct {
+ Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Untyped) Reset() { *m = Untyped{} }
+func (m *Untyped) String() string { return proto.CompactTextString(m) }
+func (*Untyped) ProtoMessage() {}
+
+func (m *Untyped) GetValue() float64 {
+ if m != nil && m.Value != nil {
+ return *m.Value
+ }
+ return 0
+}
+
+type Histogram struct {
+ SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count" json:"sample_count,omitempty"`
+ SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum" json:"sample_sum,omitempty"`
+ Bucket []*Bucket `protobuf:"bytes,3,rep,name=bucket" json:"bucket,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Histogram) Reset() { *m = Histogram{} }
+func (m *Histogram) String() string { return proto.CompactTextString(m) }
+func (*Histogram) ProtoMessage() {}
+
+func (m *Histogram) GetSampleCount() uint64 {
+ if m != nil && m.SampleCount != nil {
+ return *m.SampleCount
+ }
+ return 0
+}
+
+func (m *Histogram) GetSampleSum() float64 {
+ if m != nil && m.SampleSum != nil {
+ return *m.SampleSum
+ }
+ return 0
+}
+
+func (m *Histogram) GetBucket() []*Bucket {
+ if m != nil {
+ return m.Bucket
+ }
+ return nil
+}
+
+type Bucket struct {
+ CumulativeCount *uint64 `protobuf:"varint,1,opt,name=cumulative_count" json:"cumulative_count,omitempty"`
+ UpperBound *float64 `protobuf:"fixed64,2,opt,name=upper_bound" json:"upper_bound,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Bucket) Reset() { *m = Bucket{} }
+func (m *Bucket) String() string { return proto.CompactTextString(m) }
+func (*Bucket) ProtoMessage() {}
+
+func (m *Bucket) GetCumulativeCount() uint64 {
+ if m != nil && m.CumulativeCount != nil {
+ return *m.CumulativeCount
+ }
+ return 0
+}
+
+func (m *Bucket) GetUpperBound() float64 {
+ if m != nil && m.UpperBound != nil {
+ return *m.UpperBound
+ }
+ return 0
+}
+
+type Metric struct {
+ Label []*LabelPair `protobuf:"bytes,1,rep,name=label" json:"label,omitempty"`
+ Gauge *Gauge `protobuf:"bytes,2,opt,name=gauge" json:"gauge,omitempty"`
+ Counter *Counter `protobuf:"bytes,3,opt,name=counter" json:"counter,omitempty"`
+ Summary *Summary `protobuf:"bytes,4,opt,name=summary" json:"summary,omitempty"`
+ Untyped *Untyped `protobuf:"bytes,5,opt,name=untyped" json:"untyped,omitempty"`
+ Histogram *Histogram `protobuf:"bytes,7,opt,name=histogram" json:"histogram,omitempty"`
+ TimestampMs *int64 `protobuf:"varint,6,opt,name=timestamp_ms" json:"timestamp_ms,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Metric) Reset() { *m = Metric{} }
+func (m *Metric) String() string { return proto.CompactTextString(m) }
+func (*Metric) ProtoMessage() {}
+
+func (m *Metric) GetLabel() []*LabelPair {
+ if m != nil {
+ return m.Label
+ }
+ return nil
+}
+
+func (m *Metric) GetGauge() *Gauge {
+ if m != nil {
+ return m.Gauge
+ }
+ return nil
+}
+
+func (m *Metric) GetCounter() *Counter {
+ if m != nil {
+ return m.Counter
+ }
+ return nil
+}
+
+func (m *Metric) GetSummary() *Summary {
+ if m != nil {
+ return m.Summary
+ }
+ return nil
+}
+
+func (m *Metric) GetUntyped() *Untyped {
+ if m != nil {
+ return m.Untyped
+ }
+ return nil
+}
+
+func (m *Metric) GetHistogram() *Histogram {
+ if m != nil {
+ return m.Histogram
+ }
+ return nil
+}
+
+func (m *Metric) GetTimestampMs() int64 {
+ if m != nil && m.TimestampMs != nil {
+ return *m.TimestampMs
+ }
+ return 0
+}
+
+type MetricFamily struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Help *string `protobuf:"bytes,2,opt,name=help" json:"help,omitempty"`
+ Type *MetricType `protobuf:"varint,3,opt,name=type,enum=io.prometheus.client.MetricType" json:"type,omitempty"`
+ Metric []*Metric `protobuf:"bytes,4,rep,name=metric" json:"metric,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MetricFamily) Reset() { *m = MetricFamily{} }
+func (m *MetricFamily) String() string { return proto.CompactTextString(m) }
+func (*MetricFamily) ProtoMessage() {}
+
+func (m *MetricFamily) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *MetricFamily) GetHelp() string {
+ if m != nil && m.Help != nil {
+ return *m.Help
+ }
+ return ""
+}
+
+func (m *MetricFamily) GetType() MetricType {
+ if m != nil && m.Type != nil {
+ return *m.Type
+ }
+ return MetricType_COUNTER
+}
+
+func (m *MetricFamily) GetMetric() []*Metric {
+ if m != nil {
+ return m.Metric
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterEnum("io.prometheus.client.MetricType", MetricType_name, MetricType_value)
+}
--- /dev/null
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
--- /dev/null
+Common libraries shared by Prometheus Go components.
+Copyright 2015 The Prometheus Authors
+
+This product includes software developed at
+SoundCloud Ltd. (http://soundcloud.com/).
--- /dev/null
+// Copyright 2016 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This package no longer handles safe yaml parsing. In order to
+// ensure correct yaml unmarshalling, use "yaml.UnmarshalStrict()".
+
+package config
+
+// Secret special type for storing secrets.
+type Secret string
+
+// MarshalYAML implements the yaml.Marshaler interface for Secrets.
+func (s Secret) MarshalYAML() (interface{}, error) {
+ if s != "" {
+ return "<secret>", nil
+ }
+ return nil, nil
+}
+
+//UnmarshalYAML implements the yaml.Unmarshaler interface for Secrets.
+func (s *Secret) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ type plain Secret
+ return unmarshal((*plain)(s))
+}
--- /dev/null
+// Copyright 2016 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+ "crypto/tls"
+ "crypto/x509"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "strings"
+ "time"
+
+ "github.com/mwitkow/go-conntrack"
+ "gopkg.in/yaml.v2"
+)
+
+// BasicAuth contains basic HTTP authentication credentials.
+type BasicAuth struct {
+ Username string `yaml:"username"`
+ Password Secret `yaml:"password,omitempty"`
+ PasswordFile string `yaml:"password_file,omitempty"`
+}
+
+// URL is a custom URL type that allows validation at configuration load time.
+type URL struct {
+ *url.URL
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface for URLs.
+func (u *URL) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ var s string
+ if err := unmarshal(&s); err != nil {
+ return err
+ }
+
+ urlp, err := url.Parse(s)
+ if err != nil {
+ return err
+ }
+ u.URL = urlp
+ return nil
+}
+
+// MarshalYAML implements the yaml.Marshaler interface for URLs.
+func (u URL) MarshalYAML() (interface{}, error) {
+ if u.URL != nil {
+ return u.String(), nil
+ }
+ return nil, nil
+}
+
+// HTTPClientConfig configures an HTTP client.
+type HTTPClientConfig struct {
+ // The HTTP basic authentication credentials for the targets.
+ BasicAuth *BasicAuth `yaml:"basic_auth,omitempty"`
+ // The bearer token for the targets.
+ BearerToken Secret `yaml:"bearer_token,omitempty"`
+ // The bearer token file for the targets.
+ BearerTokenFile string `yaml:"bearer_token_file,omitempty"`
+ // HTTP proxy server to use to connect to the targets.
+ ProxyURL URL `yaml:"proxy_url,omitempty"`
+ // TLSConfig to use to connect to the targets.
+ TLSConfig TLSConfig `yaml:"tls_config,omitempty"`
+}
+
+// Validate validates the HTTPClientConfig to check only one of BearerToken,
+// BasicAuth and BearerTokenFile is configured.
+func (c *HTTPClientConfig) Validate() error {
+ if len(c.BearerToken) > 0 && len(c.BearerTokenFile) > 0 {
+ return fmt.Errorf("at most one of bearer_token & bearer_token_file must be configured")
+ }
+ if c.BasicAuth != nil && (len(c.BearerToken) > 0 || len(c.BearerTokenFile) > 0) {
+ return fmt.Errorf("at most one of basic_auth, bearer_token & bearer_token_file must be configured")
+ }
+ if c.BasicAuth != nil && (string(c.BasicAuth.Password) != "" && c.BasicAuth.PasswordFile != "") {
+ return fmt.Errorf("at most one of basic_auth password & password_file must be configured")
+ }
+ return nil
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface
+func (c *HTTPClientConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ type plain HTTPClientConfig
+ if err := unmarshal((*plain)(c)); err != nil {
+ return err
+ }
+ return c.Validate()
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (a *BasicAuth) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ type plain BasicAuth
+ return unmarshal((*plain)(a))
+}
+
+// NewClient returns a http.Client using the specified http.RoundTripper.
+func newClient(rt http.RoundTripper) *http.Client {
+ return &http.Client{Transport: rt}
+}
+
+// NewClientFromConfig returns a new HTTP client configured for the
+// given config.HTTPClientConfig. The name is used as go-conntrack metric label.
+func NewClientFromConfig(cfg HTTPClientConfig, name string) (*http.Client, error) {
+ rt, err := NewRoundTripperFromConfig(cfg, name)
+ if err != nil {
+ return nil, err
+ }
+ return newClient(rt), nil
+}
+
+// NewRoundTripperFromConfig returns a new HTTP RoundTripper configured for the
+// given config.HTTPClientConfig. The name is used as go-conntrack metric label.
+func NewRoundTripperFromConfig(cfg HTTPClientConfig, name string) (http.RoundTripper, error) {
+ tlsConfig, err := NewTLSConfig(&cfg.TLSConfig)
+ if err != nil {
+ return nil, err
+ }
+ // The only timeout we care about is the configured scrape timeout.
+ // It is applied on request. So we leave out any timings here.
+ var rt http.RoundTripper = &http.Transport{
+ Proxy: http.ProxyURL(cfg.ProxyURL.URL),
+ MaxIdleConns: 20000,
+ MaxIdleConnsPerHost: 1000, // see https://github.com/golang/go/issues/13801
+ DisableKeepAlives: false,
+ TLSClientConfig: tlsConfig,
+ DisableCompression: true,
+ // 5 minutes is typically above the maximum sane scrape interval. So we can
+ // use keepalive for all configurations.
+ IdleConnTimeout: 5 * time.Minute,
+ DialContext: conntrack.NewDialContextFunc(
+ conntrack.DialWithTracing(),
+ conntrack.DialWithName(name),
+ ),
+ }
+
+ // If a bearer token is provided, create a round tripper that will set the
+ // Authorization header correctly on each request.
+ if len(cfg.BearerToken) > 0 {
+ rt = NewBearerAuthRoundTripper(cfg.BearerToken, rt)
+ } else if len(cfg.BearerTokenFile) > 0 {
+ rt = NewBearerAuthFileRoundTripper(cfg.BearerTokenFile, rt)
+ }
+
+ if cfg.BasicAuth != nil {
+ rt = NewBasicAuthRoundTripper(cfg.BasicAuth.Username, cfg.BasicAuth.Password, cfg.BasicAuth.PasswordFile, rt)
+ }
+
+ // Return a new configured RoundTripper.
+ return rt, nil
+}
+
+type bearerAuthRoundTripper struct {
+ bearerToken Secret
+ rt http.RoundTripper
+}
+
+// NewBearerAuthRoundTripper adds the provided bearer token to a request unless the authorization
+// header has already been set.
+func NewBearerAuthRoundTripper(token Secret, rt http.RoundTripper) http.RoundTripper {
+ return &bearerAuthRoundTripper{token, rt}
+}
+
+func (rt *bearerAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
+ if len(req.Header.Get("Authorization")) == 0 {
+ req = cloneRequest(req)
+ req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", string(rt.bearerToken)))
+ }
+ return rt.rt.RoundTrip(req)
+}
+
+type bearerAuthFileRoundTripper struct {
+ bearerFile string
+ rt http.RoundTripper
+}
+
+// NewBearerAuthFileRoundTripper adds the bearer token read from the provided file to a request unless
+// the authorization header has already been set. This file is read for every request.
+func NewBearerAuthFileRoundTripper(bearerFile string, rt http.RoundTripper) http.RoundTripper {
+ return &bearerAuthFileRoundTripper{bearerFile, rt}
+}
+
+func (rt *bearerAuthFileRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
+ if len(req.Header.Get("Authorization")) == 0 {
+ b, err := ioutil.ReadFile(rt.bearerFile)
+ if err != nil {
+ return nil, fmt.Errorf("unable to read bearer token file %s: %s", rt.bearerFile, err)
+ }
+ bearerToken := strings.TrimSpace(string(b))
+
+ req = cloneRequest(req)
+ req.Header.Set("Authorization", "Bearer "+bearerToken)
+ }
+
+ return rt.rt.RoundTrip(req)
+}
+
+type basicAuthRoundTripper struct {
+ username string
+ password Secret
+ passwordFile string
+ rt http.RoundTripper
+}
+
+// NewBasicAuthRoundTripper will apply a BASIC auth authorization header to a request unless it has
+// already been set.
+func NewBasicAuthRoundTripper(username string, password Secret, passwordFile string, rt http.RoundTripper) http.RoundTripper {
+ return &basicAuthRoundTripper{username, password, passwordFile, rt}
+}
+
+func (rt *basicAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
+ if len(req.Header.Get("Authorization")) != 0 {
+ return rt.rt.RoundTrip(req)
+ }
+ req = cloneRequest(req)
+ if rt.passwordFile != "" {
+ bs, err := ioutil.ReadFile(rt.passwordFile)
+ if err != nil {
+ return nil, fmt.Errorf("unable to read basic auth password file %s: %s", rt.passwordFile, err)
+ }
+ req.SetBasicAuth(rt.username, strings.TrimSpace(string(bs)))
+ } else {
+ req.SetBasicAuth(rt.username, strings.TrimSpace(string(rt.password)))
+ }
+ return rt.rt.RoundTrip(req)
+}
+
+// cloneRequest returns a clone of the provided *http.Request.
+// The clone is a shallow copy of the struct and its Header map.
+func cloneRequest(r *http.Request) *http.Request {
+ // Shallow copy of the struct.
+ r2 := new(http.Request)
+ *r2 = *r
+ // Deep copy of the Header.
+ r2.Header = make(http.Header)
+ for k, s := range r.Header {
+ r2.Header[k] = s
+ }
+ return r2
+}
+
+// NewTLSConfig creates a new tls.Config from the given TLSConfig.
+func NewTLSConfig(cfg *TLSConfig) (*tls.Config, error) {
+ tlsConfig := &tls.Config{InsecureSkipVerify: cfg.InsecureSkipVerify}
+
+ // If a CA cert is provided then let's read it in so we can validate the
+ // scrape target's certificate properly.
+ if len(cfg.CAFile) > 0 {
+ caCertPool := x509.NewCertPool()
+ // Load CA cert.
+ caCert, err := ioutil.ReadFile(cfg.CAFile)
+ if err != nil {
+ return nil, fmt.Errorf("unable to use specified CA cert %s: %s", cfg.CAFile, err)
+ }
+ caCertPool.AppendCertsFromPEM(caCert)
+ tlsConfig.RootCAs = caCertPool
+ }
+
+ if len(cfg.ServerName) > 0 {
+ tlsConfig.ServerName = cfg.ServerName
+ }
+ // If a client cert & key is provided then configure TLS config accordingly.
+ if len(cfg.CertFile) > 0 && len(cfg.KeyFile) == 0 {
+ return nil, fmt.Errorf("client cert file %q specified without client key file", cfg.CertFile)
+ } else if len(cfg.KeyFile) > 0 && len(cfg.CertFile) == 0 {
+ return nil, fmt.Errorf("client key file %q specified without client cert file", cfg.KeyFile)
+ } else if len(cfg.CertFile) > 0 && len(cfg.KeyFile) > 0 {
+ cert, err := tls.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile)
+ if err != nil {
+ return nil, fmt.Errorf("unable to use specified client cert (%s) & key (%s): %s", cfg.CertFile, cfg.KeyFile, err)
+ }
+ tlsConfig.Certificates = []tls.Certificate{cert}
+ }
+ tlsConfig.BuildNameToCertificate()
+
+ return tlsConfig, nil
+}
+
+// TLSConfig configures the options for TLS connections.
+type TLSConfig struct {
+ // The CA cert to use for the targets.
+ CAFile string `yaml:"ca_file,omitempty"`
+ // The client cert file for the targets.
+ CertFile string `yaml:"cert_file,omitempty"`
+ // The client key file for the targets.
+ KeyFile string `yaml:"key_file,omitempty"`
+ // Used to verify the hostname for the targets.
+ ServerName string `yaml:"server_name,omitempty"`
+ // Disable target certificate validation.
+ InsecureSkipVerify bool `yaml:"insecure_skip_verify"`
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (c *TLSConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ type plain TLSConfig
+ return unmarshal((*plain)(c))
+}
+
+func (c HTTPClientConfig) String() string {
+ b, err := yaml.Marshal(c)
+ if err != nil {
+ return fmt.Sprintf("<error creating http client config string: %s>", err)
+ }
+ return string(b)
+}
--- /dev/null
+// Copyright 2015 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package expfmt
+
+import (
+ "fmt"
+ "io"
+ "math"
+ "mime"
+ "net/http"
+
+ dto "github.com/prometheus/client_model/go"
+
+ "github.com/matttproud/golang_protobuf_extensions/pbutil"
+ "github.com/prometheus/common/model"
+)
+
+// Decoder types decode an input stream into metric families.
+type Decoder interface {
+ Decode(*dto.MetricFamily) error
+}
+
+// DecodeOptions contains options used by the Decoder and in sample extraction.
+type DecodeOptions struct {
+ // Timestamp is added to each value from the stream that has no explicit timestamp set.
+ Timestamp model.Time
+}
+
+// ResponseFormat extracts the correct format from a HTTP response header.
+// If no matching format can be found FormatUnknown is returned.
+func ResponseFormat(h http.Header) Format {
+ ct := h.Get(hdrContentType)
+
+ mediatype, params, err := mime.ParseMediaType(ct)
+ if err != nil {
+ return FmtUnknown
+ }
+
+ const textType = "text/plain"
+
+ switch mediatype {
+ case ProtoType:
+ if p, ok := params["proto"]; ok && p != ProtoProtocol {
+ return FmtUnknown
+ }
+ if e, ok := params["encoding"]; ok && e != "delimited" {
+ return FmtUnknown
+ }
+ return FmtProtoDelim
+
+ case textType:
+ if v, ok := params["version"]; ok && v != TextVersion {
+ return FmtUnknown
+ }
+ return FmtText
+ }
+
+ return FmtUnknown
+}
+
+// NewDecoder returns a new decoder based on the given input format.
+// If the input format does not imply otherwise, a text format decoder is returned.
+func NewDecoder(r io.Reader, format Format) Decoder {
+ switch format {
+ case FmtProtoDelim:
+ return &protoDecoder{r: r}
+ }
+ return &textDecoder{r: r}
+}
+
+// protoDecoder implements the Decoder interface for protocol buffers.
+type protoDecoder struct {
+ r io.Reader
+}
+
+// Decode implements the Decoder interface.
+func (d *protoDecoder) Decode(v *dto.MetricFamily) error {
+ _, err := pbutil.ReadDelimited(d.r, v)
+ if err != nil {
+ return err
+ }
+ if !model.IsValidMetricName(model.LabelValue(v.GetName())) {
+ return fmt.Errorf("invalid metric name %q", v.GetName())
+ }
+ for _, m := range v.GetMetric() {
+ if m == nil {
+ continue
+ }
+ for _, l := range m.GetLabel() {
+ if l == nil {
+ continue
+ }
+ if !model.LabelValue(l.GetValue()).IsValid() {
+ return fmt.Errorf("invalid label value %q", l.GetValue())
+ }
+ if !model.LabelName(l.GetName()).IsValid() {
+ return fmt.Errorf("invalid label name %q", l.GetName())
+ }
+ }
+ }
+ return nil
+}
+
+// textDecoder implements the Decoder interface for the text protocol.
+type textDecoder struct {
+ r io.Reader
+ p TextParser
+ fams []*dto.MetricFamily
+}
+
+// Decode implements the Decoder interface.
+func (d *textDecoder) Decode(v *dto.MetricFamily) error {
+ // TODO(fabxc): Wrap this as a line reader to make streaming safer.
+ if len(d.fams) == 0 {
+ // No cached metric families, read everything and parse metrics.
+ fams, err := d.p.TextToMetricFamilies(d.r)
+ if err != nil {
+ return err
+ }
+ if len(fams) == 0 {
+ return io.EOF
+ }
+ d.fams = make([]*dto.MetricFamily, 0, len(fams))
+ for _, f := range fams {
+ d.fams = append(d.fams, f)
+ }
+ }
+
+ *v = *d.fams[0]
+ d.fams = d.fams[1:]
+
+ return nil
+}
+
+// SampleDecoder wraps a Decoder to extract samples from the metric families
+// decoded by the wrapped Decoder.
+type SampleDecoder struct {
+ Dec Decoder
+ Opts *DecodeOptions
+
+ f dto.MetricFamily
+}
+
+// Decode calls the Decode method of the wrapped Decoder and then extracts the
+// samples from the decoded MetricFamily into the provided model.Vector.
+func (sd *SampleDecoder) Decode(s *model.Vector) error {
+ err := sd.Dec.Decode(&sd.f)
+ if err != nil {
+ return err
+ }
+ *s, err = extractSamples(&sd.f, sd.Opts)
+ return err
+}
+
+// ExtractSamples builds a slice of samples from the provided metric
+// families. If an error occurrs during sample extraction, it continues to
+// extract from the remaining metric families. The returned error is the last
+// error that has occurred.
+func ExtractSamples(o *DecodeOptions, fams ...*dto.MetricFamily) (model.Vector, error) {
+ var (
+ all model.Vector
+ lastErr error
+ )
+ for _, f := range fams {
+ some, err := extractSamples(f, o)
+ if err != nil {
+ lastErr = err
+ continue
+ }
+ all = append(all, some...)
+ }
+ return all, lastErr
+}
+
+func extractSamples(f *dto.MetricFamily, o *DecodeOptions) (model.Vector, error) {
+ switch f.GetType() {
+ case dto.MetricType_COUNTER:
+ return extractCounter(o, f), nil
+ case dto.MetricType_GAUGE:
+ return extractGauge(o, f), nil
+ case dto.MetricType_SUMMARY:
+ return extractSummary(o, f), nil
+ case dto.MetricType_UNTYPED:
+ return extractUntyped(o, f), nil
+ case dto.MetricType_HISTOGRAM:
+ return extractHistogram(o, f), nil
+ }
+ return nil, fmt.Errorf("expfmt.extractSamples: unknown metric family type %v", f.GetType())
+}
+
+func extractCounter(o *DecodeOptions, f *dto.MetricFamily) model.Vector {
+ samples := make(model.Vector, 0, len(f.Metric))
+
+ for _, m := range f.Metric {
+ if m.Counter == nil {
+ continue
+ }
+
+ lset := make(model.LabelSet, len(m.Label)+1)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName())
+
+ smpl := &model.Sample{
+ Metric: model.Metric(lset),
+ Value: model.SampleValue(m.Counter.GetValue()),
+ }
+
+ if m.TimestampMs != nil {
+ smpl.Timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000)
+ } else {
+ smpl.Timestamp = o.Timestamp
+ }
+
+ samples = append(samples, smpl)
+ }
+
+ return samples
+}
+
+func extractGauge(o *DecodeOptions, f *dto.MetricFamily) model.Vector {
+ samples := make(model.Vector, 0, len(f.Metric))
+
+ for _, m := range f.Metric {
+ if m.Gauge == nil {
+ continue
+ }
+
+ lset := make(model.LabelSet, len(m.Label)+1)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName())
+
+ smpl := &model.Sample{
+ Metric: model.Metric(lset),
+ Value: model.SampleValue(m.Gauge.GetValue()),
+ }
+
+ if m.TimestampMs != nil {
+ smpl.Timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000)
+ } else {
+ smpl.Timestamp = o.Timestamp
+ }
+
+ samples = append(samples, smpl)
+ }
+
+ return samples
+}
+
+func extractUntyped(o *DecodeOptions, f *dto.MetricFamily) model.Vector {
+ samples := make(model.Vector, 0, len(f.Metric))
+
+ for _, m := range f.Metric {
+ if m.Untyped == nil {
+ continue
+ }
+
+ lset := make(model.LabelSet, len(m.Label)+1)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName())
+
+ smpl := &model.Sample{
+ Metric: model.Metric(lset),
+ Value: model.SampleValue(m.Untyped.GetValue()),
+ }
+
+ if m.TimestampMs != nil {
+ smpl.Timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000)
+ } else {
+ smpl.Timestamp = o.Timestamp
+ }
+
+ samples = append(samples, smpl)
+ }
+
+ return samples
+}
+
+func extractSummary(o *DecodeOptions, f *dto.MetricFamily) model.Vector {
+ samples := make(model.Vector, 0, len(f.Metric))
+
+ for _, m := range f.Metric {
+ if m.Summary == nil {
+ continue
+ }
+
+ timestamp := o.Timestamp
+ if m.TimestampMs != nil {
+ timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000)
+ }
+
+ for _, q := range m.Summary.Quantile {
+ lset := make(model.LabelSet, len(m.Label)+2)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ // BUG(matt): Update other names to "quantile".
+ lset[model.LabelName(model.QuantileLabel)] = model.LabelValue(fmt.Sprint(q.GetQuantile()))
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName())
+
+ samples = append(samples, &model.Sample{
+ Metric: model.Metric(lset),
+ Value: model.SampleValue(q.GetValue()),
+ Timestamp: timestamp,
+ })
+ }
+
+ lset := make(model.LabelSet, len(m.Label)+1)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_sum")
+
+ samples = append(samples, &model.Sample{
+ Metric: model.Metric(lset),
+ Value: model.SampleValue(m.Summary.GetSampleSum()),
+ Timestamp: timestamp,
+ })
+
+ lset = make(model.LabelSet, len(m.Label)+1)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_count")
+
+ samples = append(samples, &model.Sample{
+ Metric: model.Metric(lset),
+ Value: model.SampleValue(m.Summary.GetSampleCount()),
+ Timestamp: timestamp,
+ })
+ }
+
+ return samples
+}
+
+func extractHistogram(o *DecodeOptions, f *dto.MetricFamily) model.Vector {
+ samples := make(model.Vector, 0, len(f.Metric))
+
+ for _, m := range f.Metric {
+ if m.Histogram == nil {
+ continue
+ }
+
+ timestamp := o.Timestamp
+ if m.TimestampMs != nil {
+ timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000)
+ }
+
+ infSeen := false
+
+ for _, q := range m.Histogram.Bucket {
+ lset := make(model.LabelSet, len(m.Label)+2)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ lset[model.LabelName(model.BucketLabel)] = model.LabelValue(fmt.Sprint(q.GetUpperBound()))
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_bucket")
+
+ if math.IsInf(q.GetUpperBound(), +1) {
+ infSeen = true
+ }
+
+ samples = append(samples, &model.Sample{
+ Metric: model.Metric(lset),
+ Value: model.SampleValue(q.GetCumulativeCount()),
+ Timestamp: timestamp,
+ })
+ }
+
+ lset := make(model.LabelSet, len(m.Label)+1)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_sum")
+
+ samples = append(samples, &model.Sample{
+ Metric: model.Metric(lset),
+ Value: model.SampleValue(m.Histogram.GetSampleSum()),
+ Timestamp: timestamp,
+ })
+
+ lset = make(model.LabelSet, len(m.Label)+1)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_count")
+
+ count := &model.Sample{
+ Metric: model.Metric(lset),
+ Value: model.SampleValue(m.Histogram.GetSampleCount()),
+ Timestamp: timestamp,
+ }
+ samples = append(samples, count)
+
+ if !infSeen {
+ // Append an infinity bucket sample.
+ lset := make(model.LabelSet, len(m.Label)+2)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ lset[model.LabelName(model.BucketLabel)] = model.LabelValue("+Inf")
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_bucket")
+
+ samples = append(samples, &model.Sample{
+ Metric: model.Metric(lset),
+ Value: count.Value,
+ Timestamp: timestamp,
+ })
+ }
+ }
+
+ return samples
+}
--- /dev/null
+// Copyright 2015 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package expfmt
+
+import (
+ "fmt"
+ "io"
+ "net/http"
+
+ "github.com/golang/protobuf/proto"
+ "github.com/matttproud/golang_protobuf_extensions/pbutil"
+ "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg"
+
+ dto "github.com/prometheus/client_model/go"
+)
+
+// Encoder types encode metric families into an underlying wire protocol.
+type Encoder interface {
+ Encode(*dto.MetricFamily) error
+}
+
+type encoder func(*dto.MetricFamily) error
+
+func (e encoder) Encode(v *dto.MetricFamily) error {
+ return e(v)
+}
+
+// Negotiate returns the Content-Type based on the given Accept header.
+// If no appropriate accepted type is found, FmtText is returned.
+func Negotiate(h http.Header) Format {
+ for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) {
+ // Check for protocol buffer
+ if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol {
+ switch ac.Params["encoding"] {
+ case "delimited":
+ return FmtProtoDelim
+ case "text":
+ return FmtProtoText
+ case "compact-text":
+ return FmtProtoCompact
+ }
+ }
+ // Check for text format.
+ ver := ac.Params["version"]
+ if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") {
+ return FmtText
+ }
+ }
+ return FmtText
+}
+
+// NewEncoder returns a new encoder based on content type negotiation.
+func NewEncoder(w io.Writer, format Format) Encoder {
+ switch format {
+ case FmtProtoDelim:
+ return encoder(func(v *dto.MetricFamily) error {
+ _, err := pbutil.WriteDelimited(w, v)
+ return err
+ })
+ case FmtProtoCompact:
+ return encoder(func(v *dto.MetricFamily) error {
+ _, err := fmt.Fprintln(w, v.String())
+ return err
+ })
+ case FmtProtoText:
+ return encoder(func(v *dto.MetricFamily) error {
+ _, err := fmt.Fprintln(w, proto.MarshalTextString(v))
+ return err
+ })
+ case FmtText:
+ return encoder(func(v *dto.MetricFamily) error {
+ _, err := MetricFamilyToText(w, v)
+ return err
+ })
+ }
+ panic("expfmt.NewEncoder: unknown format")
+}
--- /dev/null
+// Copyright 2015 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package expfmt contains tools for reading and writing Prometheus metrics.
+package expfmt
+
+// Format specifies the HTTP content type of the different wire protocols.
+type Format string
+
+// Constants to assemble the Content-Type values for the different wire protocols.
+const (
+ TextVersion = "0.0.4"
+ ProtoType = `application/vnd.google.protobuf`
+ ProtoProtocol = `io.prometheus.client.MetricFamily`
+ ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";"
+
+ // The Content-Type values for the different wire protocols.
+ FmtUnknown Format = `<unknown>`
+ FmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8`
+ FmtProtoDelim Format = ProtoFmt + ` encoding=delimited`
+ FmtProtoText Format = ProtoFmt + ` encoding=text`
+ FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text`
+)
+
+const (
+ hdrContentType = "Content-Type"
+ hdrAccept = "Accept"
+)
--- /dev/null
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Build only when actually fuzzing
+// +build gofuzz
+
+package expfmt
+
+import "bytes"
+
+// Fuzz text metric parser with with github.com/dvyukov/go-fuzz:
+//
+// go-fuzz-build github.com/prometheus/common/expfmt
+// go-fuzz -bin expfmt-fuzz.zip -workdir fuzz
+//
+// Further input samples should go in the folder fuzz/corpus.
+func Fuzz(in []byte) int {
+ parser := TextParser{}
+ _, err := parser.TextToMetricFamilies(bytes.NewReader(in))
+
+ if err != nil {
+ return 0
+ }
+
+ return 1
+}
--- /dev/null
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package expfmt
+
+import (
+ "fmt"
+ "io"
+ "math"
+ "strings"
+
+ dto "github.com/prometheus/client_model/go"
+ "github.com/prometheus/common/model"
+)
+
+// MetricFamilyToText converts a MetricFamily proto message into text format and
+// writes the resulting lines to 'out'. It returns the number of bytes written
+// and any error encountered. The output will have the same order as the input,
+// no further sorting is performed. Furthermore, this function assumes the input
+// is already sanitized and does not perform any sanity checks. If the input
+// contains duplicate metrics or invalid metric or label names, the conversion
+// will result in invalid text format output.
+//
+// This method fulfills the type 'prometheus.encoder'.
+func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (int, error) {
+ var written int
+
+ // Fail-fast checks.
+ if len(in.Metric) == 0 {
+ return written, fmt.Errorf("MetricFamily has no metrics: %s", in)
+ }
+ name := in.GetName()
+ if name == "" {
+ return written, fmt.Errorf("MetricFamily has no name: %s", in)
+ }
+
+ // Comments, first HELP, then TYPE.
+ if in.Help != nil {
+ n, err := fmt.Fprintf(
+ out, "# HELP %s %s\n",
+ name, escapeString(*in.Help, false),
+ )
+ written += n
+ if err != nil {
+ return written, err
+ }
+ }
+ metricType := in.GetType()
+ n, err := fmt.Fprintf(
+ out, "# TYPE %s %s\n",
+ name, strings.ToLower(metricType.String()),
+ )
+ written += n
+ if err != nil {
+ return written, err
+ }
+
+ // Finally the samples, one line for each.
+ for _, metric := range in.Metric {
+ switch metricType {
+ case dto.MetricType_COUNTER:
+ if metric.Counter == nil {
+ return written, fmt.Errorf(
+ "expected counter in metric %s %s", name, metric,
+ )
+ }
+ n, err = writeSample(
+ name, metric, "", "",
+ metric.Counter.GetValue(),
+ out,
+ )
+ case dto.MetricType_GAUGE:
+ if metric.Gauge == nil {
+ return written, fmt.Errorf(
+ "expected gauge in metric %s %s", name, metric,
+ )
+ }
+ n, err = writeSample(
+ name, metric, "", "",
+ metric.Gauge.GetValue(),
+ out,
+ )
+ case dto.MetricType_UNTYPED:
+ if metric.Untyped == nil {
+ return written, fmt.Errorf(
+ "expected untyped in metric %s %s", name, metric,
+ )
+ }
+ n, err = writeSample(
+ name, metric, "", "",
+ metric.Untyped.GetValue(),
+ out,
+ )
+ case dto.MetricType_SUMMARY:
+ if metric.Summary == nil {
+ return written, fmt.Errorf(
+ "expected summary in metric %s %s", name, metric,
+ )
+ }
+ for _, q := range metric.Summary.Quantile {
+ n, err = writeSample(
+ name, metric,
+ model.QuantileLabel, fmt.Sprint(q.GetQuantile()),
+ q.GetValue(),
+ out,
+ )
+ written += n
+ if err != nil {
+ return written, err
+ }
+ }
+ n, err = writeSample(
+ name+"_sum", metric, "", "",
+ metric.Summary.GetSampleSum(),
+ out,
+ )
+ if err != nil {
+ return written, err
+ }
+ written += n
+ n, err = writeSample(
+ name+"_count", metric, "", "",
+ float64(metric.Summary.GetSampleCount()),
+ out,
+ )
+ case dto.MetricType_HISTOGRAM:
+ if metric.Histogram == nil {
+ return written, fmt.Errorf(
+ "expected histogram in metric %s %s", name, metric,
+ )
+ }
+ infSeen := false
+ for _, q := range metric.Histogram.Bucket {
+ n, err = writeSample(
+ name+"_bucket", metric,
+ model.BucketLabel, fmt.Sprint(q.GetUpperBound()),
+ float64(q.GetCumulativeCount()),
+ out,
+ )
+ written += n
+ if err != nil {
+ return written, err
+ }
+ if math.IsInf(q.GetUpperBound(), +1) {
+ infSeen = true
+ }
+ }
+ if !infSeen {
+ n, err = writeSample(
+ name+"_bucket", metric,
+ model.BucketLabel, "+Inf",
+ float64(metric.Histogram.GetSampleCount()),
+ out,
+ )
+ if err != nil {
+ return written, err
+ }
+ written += n
+ }
+ n, err = writeSample(
+ name+"_sum", metric, "", "",
+ metric.Histogram.GetSampleSum(),
+ out,
+ )
+ if err != nil {
+ return written, err
+ }
+ written += n
+ n, err = writeSample(
+ name+"_count", metric, "", "",
+ float64(metric.Histogram.GetSampleCount()),
+ out,
+ )
+ default:
+ return written, fmt.Errorf(
+ "unexpected type in metric %s %s", name, metric,
+ )
+ }
+ written += n
+ if err != nil {
+ return written, err
+ }
+ }
+ return written, nil
+}
+
+// writeSample writes a single sample in text format to out, given the metric
+// name, the metric proto message itself, optionally an additional label name
+// and value (use empty strings if not required), and the value. The function
+// returns the number of bytes written and any error encountered.
+func writeSample(
+ name string,
+ metric *dto.Metric,
+ additionalLabelName, additionalLabelValue string,
+ value float64,
+ out io.Writer,
+) (int, error) {
+ var written int
+ n, err := fmt.Fprint(out, name)
+ written += n
+ if err != nil {
+ return written, err
+ }
+ n, err = labelPairsToText(
+ metric.Label,
+ additionalLabelName, additionalLabelValue,
+ out,
+ )
+ written += n
+ if err != nil {
+ return written, err
+ }
+ n, err = fmt.Fprintf(out, " %v", value)
+ written += n
+ if err != nil {
+ return written, err
+ }
+ if metric.TimestampMs != nil {
+ n, err = fmt.Fprintf(out, " %v", *metric.TimestampMs)
+ written += n
+ if err != nil {
+ return written, err
+ }
+ }
+ n, err = out.Write([]byte{'\n'})
+ written += n
+ if err != nil {
+ return written, err
+ }
+ return written, nil
+}
+
+// labelPairsToText converts a slice of LabelPair proto messages plus the
+// explicitly given additional label pair into text formatted as required by the
+// text format and writes it to 'out'. An empty slice in combination with an
+// empty string 'additionalLabelName' results in nothing being
+// written. Otherwise, the label pairs are written, escaped as required by the
+// text format, and enclosed in '{...}'. The function returns the number of
+// bytes written and any error encountered.
+func labelPairsToText(
+ in []*dto.LabelPair,
+ additionalLabelName, additionalLabelValue string,
+ out io.Writer,
+) (int, error) {
+ if len(in) == 0 && additionalLabelName == "" {
+ return 0, nil
+ }
+ var written int
+ separator := '{'
+ for _, lp := range in {
+ n, err := fmt.Fprintf(
+ out, `%c%s="%s"`,
+ separator, lp.GetName(), escapeString(lp.GetValue(), true),
+ )
+ written += n
+ if err != nil {
+ return written, err
+ }
+ separator = ','
+ }
+ if additionalLabelName != "" {
+ n, err := fmt.Fprintf(
+ out, `%c%s="%s"`,
+ separator, additionalLabelName,
+ escapeString(additionalLabelValue, true),
+ )
+ written += n
+ if err != nil {
+ return written, err
+ }
+ }
+ n, err := out.Write([]byte{'}'})
+ written += n
+ if err != nil {
+ return written, err
+ }
+ return written, nil
+}
+
+var (
+ escape = strings.NewReplacer("\\", `\\`, "\n", `\n`)
+ escapeWithDoubleQuote = strings.NewReplacer("\\", `\\`, "\n", `\n`, "\"", `\"`)
+)
+
+// escapeString replaces '\' by '\\', new line character by '\n', and - if
+// includeDoubleQuote is true - '"' by '\"'.
+func escapeString(v string, includeDoubleQuote bool) string {
+ if includeDoubleQuote {
+ return escapeWithDoubleQuote.Replace(v)
+ }
+
+ return escape.Replace(v)
+}
--- /dev/null
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package expfmt
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "math"
+ "strconv"
+ "strings"
+
+ dto "github.com/prometheus/client_model/go"
+
+ "github.com/golang/protobuf/proto"
+ "github.com/prometheus/common/model"
+)
+
+// A stateFn is a function that represents a state in a state machine. By
+// executing it, the state is progressed to the next state. The stateFn returns
+// another stateFn, which represents the new state. The end state is represented
+// by nil.
+type stateFn func() stateFn
+
+// ParseError signals errors while parsing the simple and flat text-based
+// exchange format.
+type ParseError struct {
+ Line int
+ Msg string
+}
+
+// Error implements the error interface.
+func (e ParseError) Error() string {
+ return fmt.Sprintf("text format parsing error in line %d: %s", e.Line, e.Msg)
+}
+
+// TextParser is used to parse the simple and flat text-based exchange format. Its
+// zero value is ready to use.
+type TextParser struct {
+ metricFamiliesByName map[string]*dto.MetricFamily
+ buf *bufio.Reader // Where the parsed input is read through.
+ err error // Most recent error.
+ lineCount int // Tracks the line count for error messages.
+ currentByte byte // The most recent byte read.
+ currentToken bytes.Buffer // Re-used each time a token has to be gathered from multiple bytes.
+ currentMF *dto.MetricFamily
+ currentMetric *dto.Metric
+ currentLabelPair *dto.LabelPair
+
+ // The remaining member variables are only used for summaries/histograms.
+ currentLabels map[string]string // All labels including '__name__' but excluding 'quantile'/'le'
+ // Summary specific.
+ summaries map[uint64]*dto.Metric // Key is created with LabelsToSignature.
+ currentQuantile float64
+ // Histogram specific.
+ histograms map[uint64]*dto.Metric // Key is created with LabelsToSignature.
+ currentBucket float64
+ // These tell us if the currently processed line ends on '_count' or
+ // '_sum' respectively and belong to a summary/histogram, representing the sample
+ // count and sum of that summary/histogram.
+ currentIsSummaryCount, currentIsSummarySum bool
+ currentIsHistogramCount, currentIsHistogramSum bool
+}
+
+// TextToMetricFamilies reads 'in' as the simple and flat text-based exchange
+// format and creates MetricFamily proto messages. It returns the MetricFamily
+// proto messages in a map where the metric names are the keys, along with any
+// error encountered.
+//
+// If the input contains duplicate metrics (i.e. lines with the same metric name
+// and exactly the same label set), the resulting MetricFamily will contain
+// duplicate Metric proto messages. Similar is true for duplicate label
+// names. Checks for duplicates have to be performed separately, if required.
+// Also note that neither the metrics within each MetricFamily are sorted nor
+// the label pairs within each Metric. Sorting is not required for the most
+// frequent use of this method, which is sample ingestion in the Prometheus
+// server. However, for presentation purposes, you might want to sort the
+// metrics, and in some cases, you must sort the labels, e.g. for consumption by
+// the metric family injection hook of the Prometheus registry.
+//
+// Summaries and histograms are rather special beasts. You would probably not
+// use them in the simple text format anyway. This method can deal with
+// summaries and histograms if they are presented in exactly the way the
+// text.Create function creates them.
+//
+// This method must not be called concurrently. If you want to parse different
+// input concurrently, instantiate a separate Parser for each goroutine.
+func (p *TextParser) TextToMetricFamilies(in io.Reader) (map[string]*dto.MetricFamily, error) {
+ p.reset(in)
+ for nextState := p.startOfLine; nextState != nil; nextState = nextState() {
+ // Magic happens here...
+ }
+ // Get rid of empty metric families.
+ for k, mf := range p.metricFamiliesByName {
+ if len(mf.GetMetric()) == 0 {
+ delete(p.metricFamiliesByName, k)
+ }
+ }
+ // If p.err is io.EOF now, we have run into a premature end of the input
+ // stream. Turn this error into something nicer and more
+ // meaningful. (io.EOF is often used as a signal for the legitimate end
+ // of an input stream.)
+ if p.err == io.EOF {
+ p.parseError("unexpected end of input stream")
+ }
+ return p.metricFamiliesByName, p.err
+}
+
+func (p *TextParser) reset(in io.Reader) {
+ p.metricFamiliesByName = map[string]*dto.MetricFamily{}
+ if p.buf == nil {
+ p.buf = bufio.NewReader(in)
+ } else {
+ p.buf.Reset(in)
+ }
+ p.err = nil
+ p.lineCount = 0
+ if p.summaries == nil || len(p.summaries) > 0 {
+ p.summaries = map[uint64]*dto.Metric{}
+ }
+ if p.histograms == nil || len(p.histograms) > 0 {
+ p.histograms = map[uint64]*dto.Metric{}
+ }
+ p.currentQuantile = math.NaN()
+ p.currentBucket = math.NaN()
+}
+
+// startOfLine represents the state where the next byte read from p.buf is the
+// start of a line (or whitespace leading up to it).
+func (p *TextParser) startOfLine() stateFn {
+ p.lineCount++
+ if p.skipBlankTab(); p.err != nil {
+ // End of input reached. This is the only case where
+ // that is not an error but a signal that we are done.
+ p.err = nil
+ return nil
+ }
+ switch p.currentByte {
+ case '#':
+ return p.startComment
+ case '\n':
+ return p.startOfLine // Empty line, start the next one.
+ }
+ return p.readingMetricName
+}
+
+// startComment represents the state where the next byte read from p.buf is the
+// start of a comment (or whitespace leading up to it).
+func (p *TextParser) startComment() stateFn {
+ if p.skipBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.currentByte == '\n' {
+ return p.startOfLine
+ }
+ if p.readTokenUntilWhitespace(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ // If we have hit the end of line already, there is nothing left
+ // to do. This is not considered a syntax error.
+ if p.currentByte == '\n' {
+ return p.startOfLine
+ }
+ keyword := p.currentToken.String()
+ if keyword != "HELP" && keyword != "TYPE" {
+ // Generic comment, ignore by fast forwarding to end of line.
+ for p.currentByte != '\n' {
+ if p.currentByte, p.err = p.buf.ReadByte(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ }
+ return p.startOfLine
+ }
+ // There is something. Next has to be a metric name.
+ if p.skipBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.readTokenAsMetricName(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.currentByte == '\n' {
+ // At the end of the line already.
+ // Again, this is not considered a syntax error.
+ return p.startOfLine
+ }
+ if !isBlankOrTab(p.currentByte) {
+ p.parseError("invalid metric name in comment")
+ return nil
+ }
+ p.setOrCreateCurrentMF()
+ if p.skipBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.currentByte == '\n' {
+ // At the end of the line already.
+ // Again, this is not considered a syntax error.
+ return p.startOfLine
+ }
+ switch keyword {
+ case "HELP":
+ return p.readingHelp
+ case "TYPE":
+ return p.readingType
+ }
+ panic(fmt.Sprintf("code error: unexpected keyword %q", keyword))
+}
+
+// readingMetricName represents the state where the last byte read (now in
+// p.currentByte) is the first byte of a metric name.
+func (p *TextParser) readingMetricName() stateFn {
+ if p.readTokenAsMetricName(); p.err != nil {
+ return nil
+ }
+ if p.currentToken.Len() == 0 {
+ p.parseError("invalid metric name")
+ return nil
+ }
+ p.setOrCreateCurrentMF()
+ // Now is the time to fix the type if it hasn't happened yet.
+ if p.currentMF.Type == nil {
+ p.currentMF.Type = dto.MetricType_UNTYPED.Enum()
+ }
+ p.currentMetric = &dto.Metric{}
+ // Do not append the newly created currentMetric to
+ // currentMF.Metric right now. First wait if this is a summary,
+ // and the metric exists already, which we can only know after
+ // having read all the labels.
+ if p.skipBlankTabIfCurrentBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ return p.readingLabels
+}
+
+// readingLabels represents the state where the last byte read (now in
+// p.currentByte) is either the first byte of the label set (i.e. a '{'), or the
+// first byte of the value (otherwise).
+func (p *TextParser) readingLabels() stateFn {
+ // Summaries/histograms are special. We have to reset the
+ // currentLabels map, currentQuantile and currentBucket before starting to
+ // read labels.
+ if p.currentMF.GetType() == dto.MetricType_SUMMARY || p.currentMF.GetType() == dto.MetricType_HISTOGRAM {
+ p.currentLabels = map[string]string{}
+ p.currentLabels[string(model.MetricNameLabel)] = p.currentMF.GetName()
+ p.currentQuantile = math.NaN()
+ p.currentBucket = math.NaN()
+ }
+ if p.currentByte != '{' {
+ return p.readingValue
+ }
+ return p.startLabelName
+}
+
+// startLabelName represents the state where the next byte read from p.buf is
+// the start of a label name (or whitespace leading up to it).
+func (p *TextParser) startLabelName() stateFn {
+ if p.skipBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.currentByte == '}' {
+ if p.skipBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ return p.readingValue
+ }
+ if p.readTokenAsLabelName(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.currentToken.Len() == 0 {
+ p.parseError(fmt.Sprintf("invalid label name for metric %q", p.currentMF.GetName()))
+ return nil
+ }
+ p.currentLabelPair = &dto.LabelPair{Name: proto.String(p.currentToken.String())}
+ if p.currentLabelPair.GetName() == string(model.MetricNameLabel) {
+ p.parseError(fmt.Sprintf("label name %q is reserved", model.MetricNameLabel))
+ return nil
+ }
+ // Special summary/histogram treatment. Don't add 'quantile' and 'le'
+ // labels to 'real' labels.
+ if !(p.currentMF.GetType() == dto.MetricType_SUMMARY && p.currentLabelPair.GetName() == model.QuantileLabel) &&
+ !(p.currentMF.GetType() == dto.MetricType_HISTOGRAM && p.currentLabelPair.GetName() == model.BucketLabel) {
+ p.currentMetric.Label = append(p.currentMetric.Label, p.currentLabelPair)
+ }
+ if p.skipBlankTabIfCurrentBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.currentByte != '=' {
+ p.parseError(fmt.Sprintf("expected '=' after label name, found %q", p.currentByte))
+ return nil
+ }
+ return p.startLabelValue
+}
+
+// startLabelValue represents the state where the next byte read from p.buf is
+// the start of a (quoted) label value (or whitespace leading up to it).
+func (p *TextParser) startLabelValue() stateFn {
+ if p.skipBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.currentByte != '"' {
+ p.parseError(fmt.Sprintf("expected '\"' at start of label value, found %q", p.currentByte))
+ return nil
+ }
+ if p.readTokenAsLabelValue(); p.err != nil {
+ return nil
+ }
+ if !model.LabelValue(p.currentToken.String()).IsValid() {
+ p.parseError(fmt.Sprintf("invalid label value %q", p.currentToken.String()))
+ return nil
+ }
+ p.currentLabelPair.Value = proto.String(p.currentToken.String())
+ // Special treatment of summaries:
+ // - Quantile labels are special, will result in dto.Quantile later.
+ // - Other labels have to be added to currentLabels for signature calculation.
+ if p.currentMF.GetType() == dto.MetricType_SUMMARY {
+ if p.currentLabelPair.GetName() == model.QuantileLabel {
+ if p.currentQuantile, p.err = strconv.ParseFloat(p.currentLabelPair.GetValue(), 64); p.err != nil {
+ // Create a more helpful error message.
+ p.parseError(fmt.Sprintf("expected float as value for 'quantile' label, got %q", p.currentLabelPair.GetValue()))
+ return nil
+ }
+ } else {
+ p.currentLabels[p.currentLabelPair.GetName()] = p.currentLabelPair.GetValue()
+ }
+ }
+ // Similar special treatment of histograms.
+ if p.currentMF.GetType() == dto.MetricType_HISTOGRAM {
+ if p.currentLabelPair.GetName() == model.BucketLabel {
+ if p.currentBucket, p.err = strconv.ParseFloat(p.currentLabelPair.GetValue(), 64); p.err != nil {
+ // Create a more helpful error message.
+ p.parseError(fmt.Sprintf("expected float as value for 'le' label, got %q", p.currentLabelPair.GetValue()))
+ return nil
+ }
+ } else {
+ p.currentLabels[p.currentLabelPair.GetName()] = p.currentLabelPair.GetValue()
+ }
+ }
+ if p.skipBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ switch p.currentByte {
+ case ',':
+ return p.startLabelName
+
+ case '}':
+ if p.skipBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ return p.readingValue
+ default:
+ p.parseError(fmt.Sprintf("unexpected end of label value %q", p.currentLabelPair.Value))
+ return nil
+ }
+}
+
+// readingValue represents the state where the last byte read (now in
+// p.currentByte) is the first byte of the sample value (i.e. a float).
+func (p *TextParser) readingValue() stateFn {
+ // When we are here, we have read all the labels, so for the
+ // special case of a summary/histogram, we can finally find out
+ // if the metric already exists.
+ if p.currentMF.GetType() == dto.MetricType_SUMMARY {
+ signature := model.LabelsToSignature(p.currentLabels)
+ if summary := p.summaries[signature]; summary != nil {
+ p.currentMetric = summary
+ } else {
+ p.summaries[signature] = p.currentMetric
+ p.currentMF.Metric = append(p.currentMF.Metric, p.currentMetric)
+ }
+ } else if p.currentMF.GetType() == dto.MetricType_HISTOGRAM {
+ signature := model.LabelsToSignature(p.currentLabels)
+ if histogram := p.histograms[signature]; histogram != nil {
+ p.currentMetric = histogram
+ } else {
+ p.histograms[signature] = p.currentMetric
+ p.currentMF.Metric = append(p.currentMF.Metric, p.currentMetric)
+ }
+ } else {
+ p.currentMF.Metric = append(p.currentMF.Metric, p.currentMetric)
+ }
+ if p.readTokenUntilWhitespace(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ value, err := strconv.ParseFloat(p.currentToken.String(), 64)
+ if err != nil {
+ // Create a more helpful error message.
+ p.parseError(fmt.Sprintf("expected float as value, got %q", p.currentToken.String()))
+ return nil
+ }
+ switch p.currentMF.GetType() {
+ case dto.MetricType_COUNTER:
+ p.currentMetric.Counter = &dto.Counter{Value: proto.Float64(value)}
+ case dto.MetricType_GAUGE:
+ p.currentMetric.Gauge = &dto.Gauge{Value: proto.Float64(value)}
+ case dto.MetricType_UNTYPED:
+ p.currentMetric.Untyped = &dto.Untyped{Value: proto.Float64(value)}
+ case dto.MetricType_SUMMARY:
+ // *sigh*
+ if p.currentMetric.Summary == nil {
+ p.currentMetric.Summary = &dto.Summary{}
+ }
+ switch {
+ case p.currentIsSummaryCount:
+ p.currentMetric.Summary.SampleCount = proto.Uint64(uint64(value))
+ case p.currentIsSummarySum:
+ p.currentMetric.Summary.SampleSum = proto.Float64(value)
+ case !math.IsNaN(p.currentQuantile):
+ p.currentMetric.Summary.Quantile = append(
+ p.currentMetric.Summary.Quantile,
+ &dto.Quantile{
+ Quantile: proto.Float64(p.currentQuantile),
+ Value: proto.Float64(value),
+ },
+ )
+ }
+ case dto.MetricType_HISTOGRAM:
+ // *sigh*
+ if p.currentMetric.Histogram == nil {
+ p.currentMetric.Histogram = &dto.Histogram{}
+ }
+ switch {
+ case p.currentIsHistogramCount:
+ p.currentMetric.Histogram.SampleCount = proto.Uint64(uint64(value))
+ case p.currentIsHistogramSum:
+ p.currentMetric.Histogram.SampleSum = proto.Float64(value)
+ case !math.IsNaN(p.currentBucket):
+ p.currentMetric.Histogram.Bucket = append(
+ p.currentMetric.Histogram.Bucket,
+ &dto.Bucket{
+ UpperBound: proto.Float64(p.currentBucket),
+ CumulativeCount: proto.Uint64(uint64(value)),
+ },
+ )
+ }
+ default:
+ p.err = fmt.Errorf("unexpected type for metric name %q", p.currentMF.GetName())
+ }
+ if p.currentByte == '\n' {
+ return p.startOfLine
+ }
+ return p.startTimestamp
+}
+
+// startTimestamp represents the state where the next byte read from p.buf is
+// the start of the timestamp (or whitespace leading up to it).
+func (p *TextParser) startTimestamp() stateFn {
+ if p.skipBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.readTokenUntilWhitespace(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ timestamp, err := strconv.ParseInt(p.currentToken.String(), 10, 64)
+ if err != nil {
+ // Create a more helpful error message.
+ p.parseError(fmt.Sprintf("expected integer as timestamp, got %q", p.currentToken.String()))
+ return nil
+ }
+ p.currentMetric.TimestampMs = proto.Int64(timestamp)
+ if p.readTokenUntilNewline(false); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.currentToken.Len() > 0 {
+ p.parseError(fmt.Sprintf("spurious string after timestamp: %q", p.currentToken.String()))
+ return nil
+ }
+ return p.startOfLine
+}
+
+// readingHelp represents the state where the last byte read (now in
+// p.currentByte) is the first byte of the docstring after 'HELP'.
+func (p *TextParser) readingHelp() stateFn {
+ if p.currentMF.Help != nil {
+ p.parseError(fmt.Sprintf("second HELP line for metric name %q", p.currentMF.GetName()))
+ return nil
+ }
+ // Rest of line is the docstring.
+ if p.readTokenUntilNewline(true); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ p.currentMF.Help = proto.String(p.currentToken.String())
+ return p.startOfLine
+}
+
+// readingType represents the state where the last byte read (now in
+// p.currentByte) is the first byte of the type hint after 'HELP'.
+func (p *TextParser) readingType() stateFn {
+ if p.currentMF.Type != nil {
+ p.parseError(fmt.Sprintf("second TYPE line for metric name %q, or TYPE reported after samples", p.currentMF.GetName()))
+ return nil
+ }
+ // Rest of line is the type.
+ if p.readTokenUntilNewline(false); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ metricType, ok := dto.MetricType_value[strings.ToUpper(p.currentToken.String())]
+ if !ok {
+ p.parseError(fmt.Sprintf("unknown metric type %q", p.currentToken.String()))
+ return nil
+ }
+ p.currentMF.Type = dto.MetricType(metricType).Enum()
+ return p.startOfLine
+}
+
+// parseError sets p.err to a ParseError at the current line with the given
+// message.
+func (p *TextParser) parseError(msg string) {
+ p.err = ParseError{
+ Line: p.lineCount,
+ Msg: msg,
+ }
+}
+
+// skipBlankTab reads (and discards) bytes from p.buf until it encounters a byte
+// that is neither ' ' nor '\t'. That byte is left in p.currentByte.
+func (p *TextParser) skipBlankTab() {
+ for {
+ if p.currentByte, p.err = p.buf.ReadByte(); p.err != nil || !isBlankOrTab(p.currentByte) {
+ return
+ }
+ }
+}
+
+// skipBlankTabIfCurrentBlankTab works exactly as skipBlankTab but doesn't do
+// anything if p.currentByte is neither ' ' nor '\t'.
+func (p *TextParser) skipBlankTabIfCurrentBlankTab() {
+ if isBlankOrTab(p.currentByte) {
+ p.skipBlankTab()
+ }
+}
+
+// readTokenUntilWhitespace copies bytes from p.buf into p.currentToken. The
+// first byte considered is the byte already read (now in p.currentByte). The
+// first whitespace byte encountered is still copied into p.currentByte, but not
+// into p.currentToken.
+func (p *TextParser) readTokenUntilWhitespace() {
+ p.currentToken.Reset()
+ for p.err == nil && !isBlankOrTab(p.currentByte) && p.currentByte != '\n' {
+ p.currentToken.WriteByte(p.currentByte)
+ p.currentByte, p.err = p.buf.ReadByte()
+ }
+}
+
+// readTokenUntilNewline copies bytes from p.buf into p.currentToken. The first
+// byte considered is the byte already read (now in p.currentByte). The first
+// newline byte encountered is still copied into p.currentByte, but not into
+// p.currentToken. If recognizeEscapeSequence is true, two escape sequences are
+// recognized: '\\' translates into '\', and '\n' into a line-feed character.
+// All other escape sequences are invalid and cause an error.
+func (p *TextParser) readTokenUntilNewline(recognizeEscapeSequence bool) {
+ p.currentToken.Reset()
+ escaped := false
+ for p.err == nil {
+ if recognizeEscapeSequence && escaped {
+ switch p.currentByte {
+ case '\\':
+ p.currentToken.WriteByte(p.currentByte)
+ case 'n':
+ p.currentToken.WriteByte('\n')
+ default:
+ p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte))
+ return
+ }
+ escaped = false
+ } else {
+ switch p.currentByte {
+ case '\n':
+ return
+ case '\\':
+ escaped = true
+ default:
+ p.currentToken.WriteByte(p.currentByte)
+ }
+ }
+ p.currentByte, p.err = p.buf.ReadByte()
+ }
+}
+
+// readTokenAsMetricName copies a metric name from p.buf into p.currentToken.
+// The first byte considered is the byte already read (now in p.currentByte).
+// The first byte not part of a metric name is still copied into p.currentByte,
+// but not into p.currentToken.
+func (p *TextParser) readTokenAsMetricName() {
+ p.currentToken.Reset()
+ if !isValidMetricNameStart(p.currentByte) {
+ return
+ }
+ for {
+ p.currentToken.WriteByte(p.currentByte)
+ p.currentByte, p.err = p.buf.ReadByte()
+ if p.err != nil || !isValidMetricNameContinuation(p.currentByte) {
+ return
+ }
+ }
+}
+
+// readTokenAsLabelName copies a label name from p.buf into p.currentToken.
+// The first byte considered is the byte already read (now in p.currentByte).
+// The first byte not part of a label name is still copied into p.currentByte,
+// but not into p.currentToken.
+func (p *TextParser) readTokenAsLabelName() {
+ p.currentToken.Reset()
+ if !isValidLabelNameStart(p.currentByte) {
+ return
+ }
+ for {
+ p.currentToken.WriteByte(p.currentByte)
+ p.currentByte, p.err = p.buf.ReadByte()
+ if p.err != nil || !isValidLabelNameContinuation(p.currentByte) {
+ return
+ }
+ }
+}
+
+// readTokenAsLabelValue copies a label value from p.buf into p.currentToken.
+// In contrast to the other 'readTokenAs...' functions, which start with the
+// last read byte in p.currentByte, this method ignores p.currentByte and starts
+// with reading a new byte from p.buf. The first byte not part of a label value
+// is still copied into p.currentByte, but not into p.currentToken.
+func (p *TextParser) readTokenAsLabelValue() {
+ p.currentToken.Reset()
+ escaped := false
+ for {
+ if p.currentByte, p.err = p.buf.ReadByte(); p.err != nil {
+ return
+ }
+ if escaped {
+ switch p.currentByte {
+ case '"', '\\':
+ p.currentToken.WriteByte(p.currentByte)
+ case 'n':
+ p.currentToken.WriteByte('\n')
+ default:
+ p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte))
+ return
+ }
+ escaped = false
+ continue
+ }
+ switch p.currentByte {
+ case '"':
+ return
+ case '\n':
+ p.parseError(fmt.Sprintf("label value %q contains unescaped new-line", p.currentToken.String()))
+ return
+ case '\\':
+ escaped = true
+ default:
+ p.currentToken.WriteByte(p.currentByte)
+ }
+ }
+}
+
+func (p *TextParser) setOrCreateCurrentMF() {
+ p.currentIsSummaryCount = false
+ p.currentIsSummarySum = false
+ p.currentIsHistogramCount = false
+ p.currentIsHistogramSum = false
+ name := p.currentToken.String()
+ if p.currentMF = p.metricFamiliesByName[name]; p.currentMF != nil {
+ return
+ }
+ // Try out if this is a _sum or _count for a summary/histogram.
+ summaryName := summaryMetricName(name)
+ if p.currentMF = p.metricFamiliesByName[summaryName]; p.currentMF != nil {
+ if p.currentMF.GetType() == dto.MetricType_SUMMARY {
+ if isCount(name) {
+ p.currentIsSummaryCount = true
+ }
+ if isSum(name) {
+ p.currentIsSummarySum = true
+ }
+ return
+ }
+ }
+ histogramName := histogramMetricName(name)
+ if p.currentMF = p.metricFamiliesByName[histogramName]; p.currentMF != nil {
+ if p.currentMF.GetType() == dto.MetricType_HISTOGRAM {
+ if isCount(name) {
+ p.currentIsHistogramCount = true
+ }
+ if isSum(name) {
+ p.currentIsHistogramSum = true
+ }
+ return
+ }
+ }
+ p.currentMF = &dto.MetricFamily{Name: proto.String(name)}
+ p.metricFamiliesByName[name] = p.currentMF
+}
+
+func isValidLabelNameStart(b byte) bool {
+ return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_'
+}
+
+func isValidLabelNameContinuation(b byte) bool {
+ return isValidLabelNameStart(b) || (b >= '0' && b <= '9')
+}
+
+func isValidMetricNameStart(b byte) bool {
+ return isValidLabelNameStart(b) || b == ':'
+}
+
+func isValidMetricNameContinuation(b byte) bool {
+ return isValidLabelNameContinuation(b) || b == ':'
+}
+
+func isBlankOrTab(b byte) bool {
+ return b == ' ' || b == '\t'
+}
+
+func isCount(name string) bool {
+ return len(name) > 6 && name[len(name)-6:] == "_count"
+}
+
+func isSum(name string) bool {
+ return len(name) > 4 && name[len(name)-4:] == "_sum"
+}
+
+func isBucket(name string) bool {
+ return len(name) > 7 && name[len(name)-7:] == "_bucket"
+}
+
+func summaryMetricName(name string) string {
+ switch {
+ case isCount(name):
+ return name[:len(name)-6]
+ case isSum(name):
+ return name[:len(name)-4]
+ default:
+ return name
+ }
+}
+
+func histogramMetricName(name string) string {
+ switch {
+ case isCount(name):
+ return name[:len(name)-6]
+ case isSum(name):
+ return name[:len(name)-4]
+ case isBucket(name):
+ return name[:len(name)-7]
+ default:
+ return name
+ }
+}
--- /dev/null
+PACKAGE
+
+package goautoneg
+import "bitbucket.org/ww/goautoneg"
+
+HTTP Content-Type Autonegotiation.
+
+The functions in this package implement the behaviour specified in
+http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
+
+Copyright (c) 2011, Open Knowledge Foundation Ltd.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ Neither the name of the Open Knowledge Foundation Ltd. nor the
+ names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+FUNCTIONS
+
+func Negotiate(header string, alternatives []string) (content_type string)
+Negotiate the most appropriate content_type given the accept header
+and a list of alternatives.
+
+func ParseAccept(header string) (accept []Accept)
+Parse an Accept Header string returning a sorted list
+of clauses
+
+
+TYPES
+
+type Accept struct {
+ Type, SubType string
+ Q float32
+ Params map[string]string
+}
+Structure to represent a clause in an HTTP Accept Header
+
+
+SUBDIRECTORIES
+
+ .hg
--- /dev/null
+/*
+HTTP Content-Type Autonegotiation.
+
+The functions in this package implement the behaviour specified in
+http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
+
+Copyright (c) 2011, Open Knowledge Foundation Ltd.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ Neither the name of the Open Knowledge Foundation Ltd. nor the
+ names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+*/
+package goautoneg
+
+import (
+ "sort"
+ "strconv"
+ "strings"
+)
+
+// Structure to represent a clause in an HTTP Accept Header
+type Accept struct {
+ Type, SubType string
+ Q float64
+ Params map[string]string
+}
+
+// For internal use, so that we can use the sort interface
+type accept_slice []Accept
+
+func (accept accept_slice) Len() int {
+ slice := []Accept(accept)
+ return len(slice)
+}
+
+func (accept accept_slice) Less(i, j int) bool {
+ slice := []Accept(accept)
+ ai, aj := slice[i], slice[j]
+ if ai.Q > aj.Q {
+ return true
+ }
+ if ai.Type != "*" && aj.Type == "*" {
+ return true
+ }
+ if ai.SubType != "*" && aj.SubType == "*" {
+ return true
+ }
+ return false
+}
+
+func (accept accept_slice) Swap(i, j int) {
+ slice := []Accept(accept)
+ slice[i], slice[j] = slice[j], slice[i]
+}
+
+// Parse an Accept Header string returning a sorted list
+// of clauses
+func ParseAccept(header string) (accept []Accept) {
+ parts := strings.Split(header, ",")
+ accept = make([]Accept, 0, len(parts))
+ for _, part := range parts {
+ part := strings.Trim(part, " ")
+
+ a := Accept{}
+ a.Params = make(map[string]string)
+ a.Q = 1.0
+
+ mrp := strings.Split(part, ";")
+
+ media_range := mrp[0]
+ sp := strings.Split(media_range, "/")
+ a.Type = strings.Trim(sp[0], " ")
+
+ switch {
+ case len(sp) == 1 && a.Type == "*":
+ a.SubType = "*"
+ case len(sp) == 2:
+ a.SubType = strings.Trim(sp[1], " ")
+ default:
+ continue
+ }
+
+ if len(mrp) == 1 {
+ accept = append(accept, a)
+ continue
+ }
+
+ for _, param := range mrp[1:] {
+ sp := strings.SplitN(param, "=", 2)
+ if len(sp) != 2 {
+ continue
+ }
+ token := strings.Trim(sp[0], " ")
+ if token == "q" {
+ a.Q, _ = strconv.ParseFloat(sp[1], 32)
+ } else {
+ a.Params[token] = strings.Trim(sp[1], " ")
+ }
+ }
+
+ accept = append(accept, a)
+ }
+
+ slice := accept_slice(accept)
+ sort.Sort(slice)
+
+ return
+}
+
+// Negotiate the most appropriate content_type given the accept header
+// and a list of alternatives.
+func Negotiate(header string, alternatives []string) (content_type string) {
+ asp := make([][]string, 0, len(alternatives))
+ for _, ctype := range alternatives {
+ asp = append(asp, strings.SplitN(ctype, "/", 2))
+ }
+ for _, clause := range ParseAccept(header) {
+ for i, ctsp := range asp {
+ if clause.Type == ctsp[0] && clause.SubType == ctsp[1] {
+ content_type = alternatives[i]
+ return
+ }
+ if clause.Type == ctsp[0] && clause.SubType == "*" {
+ content_type = alternatives[i]
+ return
+ }
+ if clause.Type == "*" && clause.SubType == "*" {
+ content_type = alternatives[i]
+ return
+ }
+ }
+ }
+ return
+}
--- /dev/null
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+import (
+ "fmt"
+ "time"
+)
+
+type AlertStatus string
+
+const (
+ AlertFiring AlertStatus = "firing"
+ AlertResolved AlertStatus = "resolved"
+)
+
+// Alert is a generic representation of an alert in the Prometheus eco-system.
+type Alert struct {
+ // Label value pairs for purpose of aggregation, matching, and disposition
+ // dispatching. This must minimally include an "alertname" label.
+ Labels LabelSet `json:"labels"`
+
+ // Extra key/value information which does not define alert identity.
+ Annotations LabelSet `json:"annotations"`
+
+ // The known time range for this alert. Both ends are optional.
+ StartsAt time.Time `json:"startsAt,omitempty"`
+ EndsAt time.Time `json:"endsAt,omitempty"`
+ GeneratorURL string `json:"generatorURL"`
+}
+
+// Name returns the name of the alert. It is equivalent to the "alertname" label.
+func (a *Alert) Name() string {
+ return string(a.Labels[AlertNameLabel])
+}
+
+// Fingerprint returns a unique hash for the alert. It is equivalent to
+// the fingerprint of the alert's label set.
+func (a *Alert) Fingerprint() Fingerprint {
+ return a.Labels.Fingerprint()
+}
+
+func (a *Alert) String() string {
+ s := fmt.Sprintf("%s[%s]", a.Name(), a.Fingerprint().String()[:7])
+ if a.Resolved() {
+ return s + "[resolved]"
+ }
+ return s + "[active]"
+}
+
+// Resolved returns true iff the activity interval ended in the past.
+func (a *Alert) Resolved() bool {
+ return a.ResolvedAt(time.Now())
+}
+
+// ResolvedAt returns true off the activity interval ended before
+// the given timestamp.
+func (a *Alert) ResolvedAt(ts time.Time) bool {
+ if a.EndsAt.IsZero() {
+ return false
+ }
+ return !a.EndsAt.After(ts)
+}
+
+// Status returns the status of the alert.
+func (a *Alert) Status() AlertStatus {
+ if a.Resolved() {
+ return AlertResolved
+ }
+ return AlertFiring
+}
+
+// Validate checks whether the alert data is inconsistent.
+func (a *Alert) Validate() error {
+ if a.StartsAt.IsZero() {
+ return fmt.Errorf("start time missing")
+ }
+ if !a.EndsAt.IsZero() && a.EndsAt.Before(a.StartsAt) {
+ return fmt.Errorf("start time must be before end time")
+ }
+ if err := a.Labels.Validate(); err != nil {
+ return fmt.Errorf("invalid label set: %s", err)
+ }
+ if len(a.Labels) == 0 {
+ return fmt.Errorf("at least one label pair required")
+ }
+ if err := a.Annotations.Validate(); err != nil {
+ return fmt.Errorf("invalid annotations: %s", err)
+ }
+ return nil
+}
+
+// Alert is a list of alerts that can be sorted in chronological order.
+type Alerts []*Alert
+
+func (as Alerts) Len() int { return len(as) }
+func (as Alerts) Swap(i, j int) { as[i], as[j] = as[j], as[i] }
+
+func (as Alerts) Less(i, j int) bool {
+ if as[i].StartsAt.Before(as[j].StartsAt) {
+ return true
+ }
+ if as[i].EndsAt.Before(as[j].EndsAt) {
+ return true
+ }
+ return as[i].Fingerprint() < as[j].Fingerprint()
+}
+
+// HasFiring returns true iff one of the alerts is not resolved.
+func (as Alerts) HasFiring() bool {
+ for _, a := range as {
+ if !a.Resolved() {
+ return true
+ }
+ }
+ return false
+}
+
+// Status returns StatusFiring iff at least one of the alerts is firing.
+func (as Alerts) Status() AlertStatus {
+ if as.HasFiring() {
+ return AlertFiring
+ }
+ return AlertResolved
+}
--- /dev/null
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+import (
+ "fmt"
+ "strconv"
+)
+
+// Fingerprint provides a hash-capable representation of a Metric.
+// For our purposes, FNV-1A 64-bit is used.
+type Fingerprint uint64
+
+// FingerprintFromString transforms a string representation into a Fingerprint.
+func FingerprintFromString(s string) (Fingerprint, error) {
+ num, err := strconv.ParseUint(s, 16, 64)
+ return Fingerprint(num), err
+}
+
+// ParseFingerprint parses the input string into a fingerprint.
+func ParseFingerprint(s string) (Fingerprint, error) {
+ num, err := strconv.ParseUint(s, 16, 64)
+ if err != nil {
+ return 0, err
+ }
+ return Fingerprint(num), nil
+}
+
+func (f Fingerprint) String() string {
+ return fmt.Sprintf("%016x", uint64(f))
+}
+
+// Fingerprints represents a collection of Fingerprint subject to a given
+// natural sorting scheme. It implements sort.Interface.
+type Fingerprints []Fingerprint
+
+// Len implements sort.Interface.
+func (f Fingerprints) Len() int {
+ return len(f)
+}
+
+// Less implements sort.Interface.
+func (f Fingerprints) Less(i, j int) bool {
+ return f[i] < f[j]
+}
+
+// Swap implements sort.Interface.
+func (f Fingerprints) Swap(i, j int) {
+ f[i], f[j] = f[j], f[i]
+}
+
+// FingerprintSet is a set of Fingerprints.
+type FingerprintSet map[Fingerprint]struct{}
+
+// Equal returns true if both sets contain the same elements (and not more).
+func (s FingerprintSet) Equal(o FingerprintSet) bool {
+ if len(s) != len(o) {
+ return false
+ }
+
+ for k := range s {
+ if _, ok := o[k]; !ok {
+ return false
+ }
+ }
+
+ return true
+}
+
+// Intersection returns the elements contained in both sets.
+func (s FingerprintSet) Intersection(o FingerprintSet) FingerprintSet {
+ myLength, otherLength := len(s), len(o)
+ if myLength == 0 || otherLength == 0 {
+ return FingerprintSet{}
+ }
+
+ subSet := s
+ superSet := o
+
+ if otherLength < myLength {
+ subSet = o
+ superSet = s
+ }
+
+ out := FingerprintSet{}
+
+ for k := range subSet {
+ if _, ok := superSet[k]; ok {
+ out[k] = struct{}{}
+ }
+ }
+
+ return out
+}
--- /dev/null
+// Copyright 2015 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+// Inline and byte-free variant of hash/fnv's fnv64a.
+
+const (
+ offset64 = 14695981039346656037
+ prime64 = 1099511628211
+)
+
+// hashNew initializies a new fnv64a hash value.
+func hashNew() uint64 {
+ return offset64
+}
+
+// hashAdd adds a string to a fnv64a hash value, returning the updated hash.
+func hashAdd(h uint64, s string) uint64 {
+ for i := 0; i < len(s); i++ {
+ h ^= uint64(s[i])
+ h *= prime64
+ }
+ return h
+}
+
+// hashAddByte adds a byte to a fnv64a hash value, returning the updated hash.
+func hashAddByte(h uint64, b byte) uint64 {
+ h ^= uint64(b)
+ h *= prime64
+ return h
+}
--- /dev/null
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+import (
+ "encoding/json"
+ "fmt"
+ "regexp"
+ "strings"
+ "unicode/utf8"
+)
+
+const (
+ // AlertNameLabel is the name of the label containing the an alert's name.
+ AlertNameLabel = "alertname"
+
+ // ExportedLabelPrefix is the prefix to prepend to the label names present in
+ // exported metrics if a label of the same name is added by the server.
+ ExportedLabelPrefix = "exported_"
+
+ // MetricNameLabel is the label name indicating the metric name of a
+ // timeseries.
+ MetricNameLabel = "__name__"
+
+ // SchemeLabel is the name of the label that holds the scheme on which to
+ // scrape a target.
+ SchemeLabel = "__scheme__"
+
+ // AddressLabel is the name of the label that holds the address of
+ // a scrape target.
+ AddressLabel = "__address__"
+
+ // MetricsPathLabel is the name of the label that holds the path on which to
+ // scrape a target.
+ MetricsPathLabel = "__metrics_path__"
+
+ // ReservedLabelPrefix is a prefix which is not legal in user-supplied
+ // label names.
+ ReservedLabelPrefix = "__"
+
+ // MetaLabelPrefix is a prefix for labels that provide meta information.
+ // Labels with this prefix are used for intermediate label processing and
+ // will not be attached to time series.
+ MetaLabelPrefix = "__meta_"
+
+ // TmpLabelPrefix is a prefix for temporary labels as part of relabelling.
+ // Labels with this prefix are used for intermediate label processing and
+ // will not be attached to time series. This is reserved for use in
+ // Prometheus configuration files by users.
+ TmpLabelPrefix = "__tmp_"
+
+ // ParamLabelPrefix is a prefix for labels that provide URL parameters
+ // used to scrape a target.
+ ParamLabelPrefix = "__param_"
+
+ // JobLabel is the label name indicating the job from which a timeseries
+ // was scraped.
+ JobLabel = "job"
+
+ // InstanceLabel is the label name used for the instance label.
+ InstanceLabel = "instance"
+
+ // BucketLabel is used for the label that defines the upper bound of a
+ // bucket of a histogram ("le" -> "less or equal").
+ BucketLabel = "le"
+
+ // QuantileLabel is used for the label that defines the quantile in a
+ // summary.
+ QuantileLabel = "quantile"
+)
+
+// LabelNameRE is a regular expression matching valid label names. Note that the
+// IsValid method of LabelName performs the same check but faster than a match
+// with this regular expression.
+var LabelNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$")
+
+// A LabelName is a key for a LabelSet or Metric. It has a value associated
+// therewith.
+type LabelName string
+
+// IsValid is true iff the label name matches the pattern of LabelNameRE. This
+// method, however, does not use LabelNameRE for the check but a much faster
+// hardcoded implementation.
+func (ln LabelName) IsValid() bool {
+ if len(ln) == 0 {
+ return false
+ }
+ for i, b := range ln {
+ if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || (b >= '0' && b <= '9' && i > 0)) {
+ return false
+ }
+ }
+ return true
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (ln *LabelName) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ var s string
+ if err := unmarshal(&s); err != nil {
+ return err
+ }
+ if !LabelName(s).IsValid() {
+ return fmt.Errorf("%q is not a valid label name", s)
+ }
+ *ln = LabelName(s)
+ return nil
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+func (ln *LabelName) UnmarshalJSON(b []byte) error {
+ var s string
+ if err := json.Unmarshal(b, &s); err != nil {
+ return err
+ }
+ if !LabelName(s).IsValid() {
+ return fmt.Errorf("%q is not a valid label name", s)
+ }
+ *ln = LabelName(s)
+ return nil
+}
+
+// LabelNames is a sortable LabelName slice. In implements sort.Interface.
+type LabelNames []LabelName
+
+func (l LabelNames) Len() int {
+ return len(l)
+}
+
+func (l LabelNames) Less(i, j int) bool {
+ return l[i] < l[j]
+}
+
+func (l LabelNames) Swap(i, j int) {
+ l[i], l[j] = l[j], l[i]
+}
+
+func (l LabelNames) String() string {
+ labelStrings := make([]string, 0, len(l))
+ for _, label := range l {
+ labelStrings = append(labelStrings, string(label))
+ }
+ return strings.Join(labelStrings, ", ")
+}
+
+// A LabelValue is an associated value for a LabelName.
+type LabelValue string
+
+// IsValid returns true iff the string is a valid UTF8.
+func (lv LabelValue) IsValid() bool {
+ return utf8.ValidString(string(lv))
+}
+
+// LabelValues is a sortable LabelValue slice. It implements sort.Interface.
+type LabelValues []LabelValue
+
+func (l LabelValues) Len() int {
+ return len(l)
+}
+
+func (l LabelValues) Less(i, j int) bool {
+ return string(l[i]) < string(l[j])
+}
+
+func (l LabelValues) Swap(i, j int) {
+ l[i], l[j] = l[j], l[i]
+}
+
+// LabelPair pairs a name with a value.
+type LabelPair struct {
+ Name LabelName
+ Value LabelValue
+}
+
+// LabelPairs is a sortable slice of LabelPair pointers. It implements
+// sort.Interface.
+type LabelPairs []*LabelPair
+
+func (l LabelPairs) Len() int {
+ return len(l)
+}
+
+func (l LabelPairs) Less(i, j int) bool {
+ switch {
+ case l[i].Name > l[j].Name:
+ return false
+ case l[i].Name < l[j].Name:
+ return true
+ case l[i].Value > l[j].Value:
+ return false
+ case l[i].Value < l[j].Value:
+ return true
+ default:
+ return false
+ }
+}
+
+func (l LabelPairs) Swap(i, j int) {
+ l[i], l[j] = l[j], l[i]
+}
--- /dev/null
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+import (
+ "encoding/json"
+ "fmt"
+ "sort"
+ "strings"
+)
+
+// A LabelSet is a collection of LabelName and LabelValue pairs. The LabelSet
+// may be fully-qualified down to the point where it may resolve to a single
+// Metric in the data store or not. All operations that occur within the realm
+// of a LabelSet can emit a vector of Metric entities to which the LabelSet may
+// match.
+type LabelSet map[LabelName]LabelValue
+
+// Validate checks whether all names and values in the label set
+// are valid.
+func (ls LabelSet) Validate() error {
+ for ln, lv := range ls {
+ if !ln.IsValid() {
+ return fmt.Errorf("invalid name %q", ln)
+ }
+ if !lv.IsValid() {
+ return fmt.Errorf("invalid value %q", lv)
+ }
+ }
+ return nil
+}
+
+// Equal returns true iff both label sets have exactly the same key/value pairs.
+func (ls LabelSet) Equal(o LabelSet) bool {
+ if len(ls) != len(o) {
+ return false
+ }
+ for ln, lv := range ls {
+ olv, ok := o[ln]
+ if !ok {
+ return false
+ }
+ if olv != lv {
+ return false
+ }
+ }
+ return true
+}
+
+// Before compares the metrics, using the following criteria:
+//
+// If m has fewer labels than o, it is before o. If it has more, it is not.
+//
+// If the number of labels is the same, the superset of all label names is
+// sorted alphanumerically. The first differing label pair found in that order
+// determines the outcome: If the label does not exist at all in m, then m is
+// before o, and vice versa. Otherwise the label value is compared
+// alphanumerically.
+//
+// If m and o are equal, the method returns false.
+func (ls LabelSet) Before(o LabelSet) bool {
+ if len(ls) < len(o) {
+ return true
+ }
+ if len(ls) > len(o) {
+ return false
+ }
+
+ lns := make(LabelNames, 0, len(ls)+len(o))
+ for ln := range ls {
+ lns = append(lns, ln)
+ }
+ for ln := range o {
+ lns = append(lns, ln)
+ }
+ // It's probably not worth it to de-dup lns.
+ sort.Sort(lns)
+ for _, ln := range lns {
+ mlv, ok := ls[ln]
+ if !ok {
+ return true
+ }
+ olv, ok := o[ln]
+ if !ok {
+ return false
+ }
+ if mlv < olv {
+ return true
+ }
+ if mlv > olv {
+ return false
+ }
+ }
+ return false
+}
+
+// Clone returns a copy of the label set.
+func (ls LabelSet) Clone() LabelSet {
+ lsn := make(LabelSet, len(ls))
+ for ln, lv := range ls {
+ lsn[ln] = lv
+ }
+ return lsn
+}
+
+// Merge is a helper function to non-destructively merge two label sets.
+func (l LabelSet) Merge(other LabelSet) LabelSet {
+ result := make(LabelSet, len(l))
+
+ for k, v := range l {
+ result[k] = v
+ }
+
+ for k, v := range other {
+ result[k] = v
+ }
+
+ return result
+}
+
+func (l LabelSet) String() string {
+ lstrs := make([]string, 0, len(l))
+ for l, v := range l {
+ lstrs = append(lstrs, fmt.Sprintf("%s=%q", l, v))
+ }
+
+ sort.Strings(lstrs)
+ return fmt.Sprintf("{%s}", strings.Join(lstrs, ", "))
+}
+
+// Fingerprint returns the LabelSet's fingerprint.
+func (ls LabelSet) Fingerprint() Fingerprint {
+ return labelSetToFingerprint(ls)
+}
+
+// FastFingerprint returns the LabelSet's Fingerprint calculated by a faster hashing
+// algorithm, which is, however, more susceptible to hash collisions.
+func (ls LabelSet) FastFingerprint() Fingerprint {
+ return labelSetToFastFingerprint(ls)
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+func (l *LabelSet) UnmarshalJSON(b []byte) error {
+ var m map[LabelName]LabelValue
+ if err := json.Unmarshal(b, &m); err != nil {
+ return err
+ }
+ // encoding/json only unmarshals maps of the form map[string]T. It treats
+ // LabelName as a string and does not call its UnmarshalJSON method.
+ // Thus, we have to replicate the behavior here.
+ for ln := range m {
+ if !ln.IsValid() {
+ return fmt.Errorf("%q is not a valid label name", ln)
+ }
+ }
+ *l = LabelSet(m)
+ return nil
+}
--- /dev/null
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+import (
+ "fmt"
+ "regexp"
+ "sort"
+ "strings"
+)
+
+var (
+ separator = []byte{0}
+ // MetricNameRE is a regular expression matching valid metric
+ // names. Note that the IsValidMetricName function performs the same
+ // check but faster than a match with this regular expression.
+ MetricNameRE = regexp.MustCompile(`^[a-zA-Z_:][a-zA-Z0-9_:]*$`)
+)
+
+// A Metric is similar to a LabelSet, but the key difference is that a Metric is
+// a singleton and refers to one and only one stream of samples.
+type Metric LabelSet
+
+// Equal compares the metrics.
+func (m Metric) Equal(o Metric) bool {
+ return LabelSet(m).Equal(LabelSet(o))
+}
+
+// Before compares the metrics' underlying label sets.
+func (m Metric) Before(o Metric) bool {
+ return LabelSet(m).Before(LabelSet(o))
+}
+
+// Clone returns a copy of the Metric.
+func (m Metric) Clone() Metric {
+ clone := make(Metric, len(m))
+ for k, v := range m {
+ clone[k] = v
+ }
+ return clone
+}
+
+func (m Metric) String() string {
+ metricName, hasName := m[MetricNameLabel]
+ numLabels := len(m) - 1
+ if !hasName {
+ numLabels = len(m)
+ }
+ labelStrings := make([]string, 0, numLabels)
+ for label, value := range m {
+ if label != MetricNameLabel {
+ labelStrings = append(labelStrings, fmt.Sprintf("%s=%q", label, value))
+ }
+ }
+
+ switch numLabels {
+ case 0:
+ if hasName {
+ return string(metricName)
+ }
+ return "{}"
+ default:
+ sort.Strings(labelStrings)
+ return fmt.Sprintf("%s{%s}", metricName, strings.Join(labelStrings, ", "))
+ }
+}
+
+// Fingerprint returns a Metric's Fingerprint.
+func (m Metric) Fingerprint() Fingerprint {
+ return LabelSet(m).Fingerprint()
+}
+
+// FastFingerprint returns a Metric's Fingerprint calculated by a faster hashing
+// algorithm, which is, however, more susceptible to hash collisions.
+func (m Metric) FastFingerprint() Fingerprint {
+ return LabelSet(m).FastFingerprint()
+}
+
+// IsValidMetricName returns true iff name matches the pattern of MetricNameRE.
+// This function, however, does not use MetricNameRE for the check but a much
+// faster hardcoded implementation.
+func IsValidMetricName(n LabelValue) bool {
+ if len(n) == 0 {
+ return false
+ }
+ for i, b := range n {
+ if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || b == ':' || (b >= '0' && b <= '9' && i > 0)) {
+ return false
+ }
+ }
+ return true
+}
--- /dev/null
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package model contains common data structures that are shared across
+// Prometheus components and libraries.
+package model
--- /dev/null
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+import (
+ "sort"
+)
+
+// SeparatorByte is a byte that cannot occur in valid UTF-8 sequences and is
+// used to separate label names, label values, and other strings from each other
+// when calculating their combined hash value (aka signature aka fingerprint).
+const SeparatorByte byte = 255
+
+var (
+ // cache the signature of an empty label set.
+ emptyLabelSignature = hashNew()
+)
+
+// LabelsToSignature returns a quasi-unique signature (i.e., fingerprint) for a
+// given label set. (Collisions are possible but unlikely if the number of label
+// sets the function is applied to is small.)
+func LabelsToSignature(labels map[string]string) uint64 {
+ if len(labels) == 0 {
+ return emptyLabelSignature
+ }
+
+ labelNames := make([]string, 0, len(labels))
+ for labelName := range labels {
+ labelNames = append(labelNames, labelName)
+ }
+ sort.Strings(labelNames)
+
+ sum := hashNew()
+ for _, labelName := range labelNames {
+ sum = hashAdd(sum, labelName)
+ sum = hashAddByte(sum, SeparatorByte)
+ sum = hashAdd(sum, labels[labelName])
+ sum = hashAddByte(sum, SeparatorByte)
+ }
+ return sum
+}
+
+// labelSetToFingerprint works exactly as LabelsToSignature but takes a LabelSet as
+// parameter (rather than a label map) and returns a Fingerprint.
+func labelSetToFingerprint(ls LabelSet) Fingerprint {
+ if len(ls) == 0 {
+ return Fingerprint(emptyLabelSignature)
+ }
+
+ labelNames := make(LabelNames, 0, len(ls))
+ for labelName := range ls {
+ labelNames = append(labelNames, labelName)
+ }
+ sort.Sort(labelNames)
+
+ sum := hashNew()
+ for _, labelName := range labelNames {
+ sum = hashAdd(sum, string(labelName))
+ sum = hashAddByte(sum, SeparatorByte)
+ sum = hashAdd(sum, string(ls[labelName]))
+ sum = hashAddByte(sum, SeparatorByte)
+ }
+ return Fingerprint(sum)
+}
+
+// labelSetToFastFingerprint works similar to labelSetToFingerprint but uses a
+// faster and less allocation-heavy hash function, which is more susceptible to
+// create hash collisions. Therefore, collision detection should be applied.
+func labelSetToFastFingerprint(ls LabelSet) Fingerprint {
+ if len(ls) == 0 {
+ return Fingerprint(emptyLabelSignature)
+ }
+
+ var result uint64
+ for labelName, labelValue := range ls {
+ sum := hashNew()
+ sum = hashAdd(sum, string(labelName))
+ sum = hashAddByte(sum, SeparatorByte)
+ sum = hashAdd(sum, string(labelValue))
+ result ^= sum
+ }
+ return Fingerprint(result)
+}
+
+// SignatureForLabels works like LabelsToSignature but takes a Metric as
+// parameter (rather than a label map) and only includes the labels with the
+// specified LabelNames into the signature calculation. The labels passed in
+// will be sorted by this function.
+func SignatureForLabels(m Metric, labels ...LabelName) uint64 {
+ if len(labels) == 0 {
+ return emptyLabelSignature
+ }
+
+ sort.Sort(LabelNames(labels))
+
+ sum := hashNew()
+ for _, label := range labels {
+ sum = hashAdd(sum, string(label))
+ sum = hashAddByte(sum, SeparatorByte)
+ sum = hashAdd(sum, string(m[label]))
+ sum = hashAddByte(sum, SeparatorByte)
+ }
+ return sum
+}
+
+// SignatureWithoutLabels works like LabelsToSignature but takes a Metric as
+// parameter (rather than a label map) and excludes the labels with any of the
+// specified LabelNames from the signature calculation.
+func SignatureWithoutLabels(m Metric, labels map[LabelName]struct{}) uint64 {
+ if len(m) == 0 {
+ return emptyLabelSignature
+ }
+
+ labelNames := make(LabelNames, 0, len(m))
+ for labelName := range m {
+ if _, exclude := labels[labelName]; !exclude {
+ labelNames = append(labelNames, labelName)
+ }
+ }
+ if len(labelNames) == 0 {
+ return emptyLabelSignature
+ }
+ sort.Sort(labelNames)
+
+ sum := hashNew()
+ for _, labelName := range labelNames {
+ sum = hashAdd(sum, string(labelName))
+ sum = hashAddByte(sum, SeparatorByte)
+ sum = hashAdd(sum, string(m[labelName]))
+ sum = hashAddByte(sum, SeparatorByte)
+ }
+ return sum
+}
--- /dev/null
+// Copyright 2015 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+import (
+ "encoding/json"
+ "fmt"
+ "regexp"
+ "time"
+)
+
+// Matcher describes a matches the value of a given label.
+type Matcher struct {
+ Name LabelName `json:"name"`
+ Value string `json:"value"`
+ IsRegex bool `json:"isRegex"`
+}
+
+func (m *Matcher) UnmarshalJSON(b []byte) error {
+ type plain Matcher
+ if err := json.Unmarshal(b, (*plain)(m)); err != nil {
+ return err
+ }
+
+ if len(m.Name) == 0 {
+ return fmt.Errorf("label name in matcher must not be empty")
+ }
+ if m.IsRegex {
+ if _, err := regexp.Compile(m.Value); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// Validate returns true iff all fields of the matcher have valid values.
+func (m *Matcher) Validate() error {
+ if !m.Name.IsValid() {
+ return fmt.Errorf("invalid name %q", m.Name)
+ }
+ if m.IsRegex {
+ if _, err := regexp.Compile(m.Value); err != nil {
+ return fmt.Errorf("invalid regular expression %q", m.Value)
+ }
+ } else if !LabelValue(m.Value).IsValid() || len(m.Value) == 0 {
+ return fmt.Errorf("invalid value %q", m.Value)
+ }
+ return nil
+}
+
+// Silence defines the representation of a silence definition in the Prometheus
+// eco-system.
+type Silence struct {
+ ID uint64 `json:"id,omitempty"`
+
+ Matchers []*Matcher `json:"matchers"`
+
+ StartsAt time.Time `json:"startsAt"`
+ EndsAt time.Time `json:"endsAt"`
+
+ CreatedAt time.Time `json:"createdAt,omitempty"`
+ CreatedBy string `json:"createdBy"`
+ Comment string `json:"comment,omitempty"`
+}
+
+// Validate returns true iff all fields of the silence have valid values.
+func (s *Silence) Validate() error {
+ if len(s.Matchers) == 0 {
+ return fmt.Errorf("at least one matcher required")
+ }
+ for _, m := range s.Matchers {
+ if err := m.Validate(); err != nil {
+ return fmt.Errorf("invalid matcher: %s", err)
+ }
+ }
+ if s.StartsAt.IsZero() {
+ return fmt.Errorf("start time missing")
+ }
+ if s.EndsAt.IsZero() {
+ return fmt.Errorf("end time missing")
+ }
+ if s.EndsAt.Before(s.StartsAt) {
+ return fmt.Errorf("start time must be before end time")
+ }
+ if s.CreatedBy == "" {
+ return fmt.Errorf("creator information missing")
+ }
+ if s.Comment == "" {
+ return fmt.Errorf("comment missing")
+ }
+ if s.CreatedAt.IsZero() {
+ return fmt.Errorf("creation timestamp missing")
+ }
+ return nil
+}
--- /dev/null
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+import (
+ "fmt"
+ "math"
+ "regexp"
+ "strconv"
+ "strings"
+ "time"
+)
+
+const (
+ // MinimumTick is the minimum supported time resolution. This has to be
+ // at least time.Second in order for the code below to work.
+ minimumTick = time.Millisecond
+ // second is the Time duration equivalent to one second.
+ second = int64(time.Second / minimumTick)
+ // The number of nanoseconds per minimum tick.
+ nanosPerTick = int64(minimumTick / time.Nanosecond)
+
+ // Earliest is the earliest Time representable. Handy for
+ // initializing a high watermark.
+ Earliest = Time(math.MinInt64)
+ // Latest is the latest Time representable. Handy for initializing
+ // a low watermark.
+ Latest = Time(math.MaxInt64)
+)
+
+// Time is the number of milliseconds since the epoch
+// (1970-01-01 00:00 UTC) excluding leap seconds.
+type Time int64
+
+// Interval describes and interval between two timestamps.
+type Interval struct {
+ Start, End Time
+}
+
+// Now returns the current time as a Time.
+func Now() Time {
+ return TimeFromUnixNano(time.Now().UnixNano())
+}
+
+// TimeFromUnix returns the Time equivalent to the Unix Time t
+// provided in seconds.
+func TimeFromUnix(t int64) Time {
+ return Time(t * second)
+}
+
+// TimeFromUnixNano returns the Time equivalent to the Unix Time
+// t provided in nanoseconds.
+func TimeFromUnixNano(t int64) Time {
+ return Time(t / nanosPerTick)
+}
+
+// Equal reports whether two Times represent the same instant.
+func (t Time) Equal(o Time) bool {
+ return t == o
+}
+
+// Before reports whether the Time t is before o.
+func (t Time) Before(o Time) bool {
+ return t < o
+}
+
+// After reports whether the Time t is after o.
+func (t Time) After(o Time) bool {
+ return t > o
+}
+
+// Add returns the Time t + d.
+func (t Time) Add(d time.Duration) Time {
+ return t + Time(d/minimumTick)
+}
+
+// Sub returns the Duration t - o.
+func (t Time) Sub(o Time) time.Duration {
+ return time.Duration(t-o) * minimumTick
+}
+
+// Time returns the time.Time representation of t.
+func (t Time) Time() time.Time {
+ return time.Unix(int64(t)/second, (int64(t)%second)*nanosPerTick)
+}
+
+// Unix returns t as a Unix time, the number of seconds elapsed
+// since January 1, 1970 UTC.
+func (t Time) Unix() int64 {
+ return int64(t) / second
+}
+
+// UnixNano returns t as a Unix time, the number of nanoseconds elapsed
+// since January 1, 1970 UTC.
+func (t Time) UnixNano() int64 {
+ return int64(t) * nanosPerTick
+}
+
+// The number of digits after the dot.
+var dotPrecision = int(math.Log10(float64(second)))
+
+// String returns a string representation of the Time.
+func (t Time) String() string {
+ return strconv.FormatFloat(float64(t)/float64(second), 'f', -1, 64)
+}
+
+// MarshalJSON implements the json.Marshaler interface.
+func (t Time) MarshalJSON() ([]byte, error) {
+ return []byte(t.String()), nil
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+func (t *Time) UnmarshalJSON(b []byte) error {
+ p := strings.Split(string(b), ".")
+ switch len(p) {
+ case 1:
+ v, err := strconv.ParseInt(string(p[0]), 10, 64)
+ if err != nil {
+ return err
+ }
+ *t = Time(v * second)
+
+ case 2:
+ v, err := strconv.ParseInt(string(p[0]), 10, 64)
+ if err != nil {
+ return err
+ }
+ v *= second
+
+ prec := dotPrecision - len(p[1])
+ if prec < 0 {
+ p[1] = p[1][:dotPrecision]
+ } else if prec > 0 {
+ p[1] = p[1] + strings.Repeat("0", prec)
+ }
+
+ va, err := strconv.ParseInt(p[1], 10, 32)
+ if err != nil {
+ return err
+ }
+
+ *t = Time(v + va)
+
+ default:
+ return fmt.Errorf("invalid time %q", string(b))
+ }
+ return nil
+}
+
+// Duration wraps time.Duration. It is used to parse the custom duration format
+// from YAML.
+// This type should not propagate beyond the scope of input/output processing.
+type Duration time.Duration
+
+// Set implements pflag/flag.Value
+func (d *Duration) Set(s string) error {
+ var err error
+ *d, err = ParseDuration(s)
+ return err
+}
+
+// Type implements pflag.Value
+func (d *Duration) Type() string {
+ return "duration"
+}
+
+var durationRE = regexp.MustCompile("^([0-9]+)(y|w|d|h|m|s|ms)$")
+
+// ParseDuration parses a string into a time.Duration, assuming that a year
+// always has 365d, a week always has 7d, and a day always has 24h.
+func ParseDuration(durationStr string) (Duration, error) {
+ matches := durationRE.FindStringSubmatch(durationStr)
+ if len(matches) != 3 {
+ return 0, fmt.Errorf("not a valid duration string: %q", durationStr)
+ }
+ var (
+ n, _ = strconv.Atoi(matches[1])
+ dur = time.Duration(n) * time.Millisecond
+ )
+ switch unit := matches[2]; unit {
+ case "y":
+ dur *= 1000 * 60 * 60 * 24 * 365
+ case "w":
+ dur *= 1000 * 60 * 60 * 24 * 7
+ case "d":
+ dur *= 1000 * 60 * 60 * 24
+ case "h":
+ dur *= 1000 * 60 * 60
+ case "m":
+ dur *= 1000 * 60
+ case "s":
+ dur *= 1000
+ case "ms":
+ // Value already correct
+ default:
+ return 0, fmt.Errorf("invalid time unit in duration string: %q", unit)
+ }
+ return Duration(dur), nil
+}
+
+func (d Duration) String() string {
+ var (
+ ms = int64(time.Duration(d) / time.Millisecond)
+ unit = "ms"
+ )
+ if ms == 0 {
+ return "0s"
+ }
+ factors := map[string]int64{
+ "y": 1000 * 60 * 60 * 24 * 365,
+ "w": 1000 * 60 * 60 * 24 * 7,
+ "d": 1000 * 60 * 60 * 24,
+ "h": 1000 * 60 * 60,
+ "m": 1000 * 60,
+ "s": 1000,
+ "ms": 1,
+ }
+
+ switch int64(0) {
+ case ms % factors["y"]:
+ unit = "y"
+ case ms % factors["w"]:
+ unit = "w"
+ case ms % factors["d"]:
+ unit = "d"
+ case ms % factors["h"]:
+ unit = "h"
+ case ms % factors["m"]:
+ unit = "m"
+ case ms % factors["s"]:
+ unit = "s"
+ }
+ return fmt.Sprintf("%v%v", ms/factors[unit], unit)
+}
+
+// MarshalYAML implements the yaml.Marshaler interface.
+func (d Duration) MarshalYAML() (interface{}, error) {
+ return d.String(), nil
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (d *Duration) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ var s string
+ if err := unmarshal(&s); err != nil {
+ return err
+ }
+ dur, err := ParseDuration(s)
+ if err != nil {
+ return err
+ }
+ *d = dur
+ return nil
+}
--- /dev/null
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+import (
+ "encoding/json"
+ "fmt"
+ "math"
+ "sort"
+ "strconv"
+ "strings"
+)
+
+var (
+ // ZeroSamplePair is the pseudo zero-value of SamplePair used to signal a
+ // non-existing sample pair. It is a SamplePair with timestamp Earliest and
+ // value 0.0. Note that the natural zero value of SamplePair has a timestamp
+ // of 0, which is possible to appear in a real SamplePair and thus not
+ // suitable to signal a non-existing SamplePair.
+ ZeroSamplePair = SamplePair{Timestamp: Earliest}
+
+ // ZeroSample is the pseudo zero-value of Sample used to signal a
+ // non-existing sample. It is a Sample with timestamp Earliest, value 0.0,
+ // and metric nil. Note that the natural zero value of Sample has a timestamp
+ // of 0, which is possible to appear in a real Sample and thus not suitable
+ // to signal a non-existing Sample.
+ ZeroSample = Sample{Timestamp: Earliest}
+)
+
+// A SampleValue is a representation of a value for a given sample at a given
+// time.
+type SampleValue float64
+
+// MarshalJSON implements json.Marshaler.
+func (v SampleValue) MarshalJSON() ([]byte, error) {
+ return json.Marshal(v.String())
+}
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (v *SampleValue) UnmarshalJSON(b []byte) error {
+ if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
+ return fmt.Errorf("sample value must be a quoted string")
+ }
+ f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64)
+ if err != nil {
+ return err
+ }
+ *v = SampleValue(f)
+ return nil
+}
+
+// Equal returns true if the value of v and o is equal or if both are NaN. Note
+// that v==o is false if both are NaN. If you want the conventional float
+// behavior, use == to compare two SampleValues.
+func (v SampleValue) Equal(o SampleValue) bool {
+ if v == o {
+ return true
+ }
+ return math.IsNaN(float64(v)) && math.IsNaN(float64(o))
+}
+
+func (v SampleValue) String() string {
+ return strconv.FormatFloat(float64(v), 'f', -1, 64)
+}
+
+// SamplePair pairs a SampleValue with a Timestamp.
+type SamplePair struct {
+ Timestamp Time
+ Value SampleValue
+}
+
+// MarshalJSON implements json.Marshaler.
+func (s SamplePair) MarshalJSON() ([]byte, error) {
+ t, err := json.Marshal(s.Timestamp)
+ if err != nil {
+ return nil, err
+ }
+ v, err := json.Marshal(s.Value)
+ if err != nil {
+ return nil, err
+ }
+ return []byte(fmt.Sprintf("[%s,%s]", t, v)), nil
+}
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (s *SamplePair) UnmarshalJSON(b []byte) error {
+ v := [...]json.Unmarshaler{&s.Timestamp, &s.Value}
+ return json.Unmarshal(b, &v)
+}
+
+// Equal returns true if this SamplePair and o have equal Values and equal
+// Timestamps. The semantics of Value equality is defined by SampleValue.Equal.
+func (s *SamplePair) Equal(o *SamplePair) bool {
+ return s == o || (s.Value.Equal(o.Value) && s.Timestamp.Equal(o.Timestamp))
+}
+
+func (s SamplePair) String() string {
+ return fmt.Sprintf("%s @[%s]", s.Value, s.Timestamp)
+}
+
+// Sample is a sample pair associated with a metric.
+type Sample struct {
+ Metric Metric `json:"metric"`
+ Value SampleValue `json:"value"`
+ Timestamp Time `json:"timestamp"`
+}
+
+// Equal compares first the metrics, then the timestamp, then the value. The
+// semantics of value equality is defined by SampleValue.Equal.
+func (s *Sample) Equal(o *Sample) bool {
+ if s == o {
+ return true
+ }
+
+ if !s.Metric.Equal(o.Metric) {
+ return false
+ }
+ if !s.Timestamp.Equal(o.Timestamp) {
+ return false
+ }
+
+ return s.Value.Equal(o.Value)
+}
+
+func (s Sample) String() string {
+ return fmt.Sprintf("%s => %s", s.Metric, SamplePair{
+ Timestamp: s.Timestamp,
+ Value: s.Value,
+ })
+}
+
+// MarshalJSON implements json.Marshaler.
+func (s Sample) MarshalJSON() ([]byte, error) {
+ v := struct {
+ Metric Metric `json:"metric"`
+ Value SamplePair `json:"value"`
+ }{
+ Metric: s.Metric,
+ Value: SamplePair{
+ Timestamp: s.Timestamp,
+ Value: s.Value,
+ },
+ }
+
+ return json.Marshal(&v)
+}
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (s *Sample) UnmarshalJSON(b []byte) error {
+ v := struct {
+ Metric Metric `json:"metric"`
+ Value SamplePair `json:"value"`
+ }{
+ Metric: s.Metric,
+ Value: SamplePair{
+ Timestamp: s.Timestamp,
+ Value: s.Value,
+ },
+ }
+
+ if err := json.Unmarshal(b, &v); err != nil {
+ return err
+ }
+
+ s.Metric = v.Metric
+ s.Timestamp = v.Value.Timestamp
+ s.Value = v.Value.Value
+
+ return nil
+}
+
+// Samples is a sortable Sample slice. It implements sort.Interface.
+type Samples []*Sample
+
+func (s Samples) Len() int {
+ return len(s)
+}
+
+// Less compares first the metrics, then the timestamp.
+func (s Samples) Less(i, j int) bool {
+ switch {
+ case s[i].Metric.Before(s[j].Metric):
+ return true
+ case s[j].Metric.Before(s[i].Metric):
+ return false
+ case s[i].Timestamp.Before(s[j].Timestamp):
+ return true
+ default:
+ return false
+ }
+}
+
+func (s Samples) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+// Equal compares two sets of samples and returns true if they are equal.
+func (s Samples) Equal(o Samples) bool {
+ if len(s) != len(o) {
+ return false
+ }
+
+ for i, sample := range s {
+ if !sample.Equal(o[i]) {
+ return false
+ }
+ }
+ return true
+}
+
+// SampleStream is a stream of Values belonging to an attached COWMetric.
+type SampleStream struct {
+ Metric Metric `json:"metric"`
+ Values []SamplePair `json:"values"`
+}
+
+func (ss SampleStream) String() string {
+ vals := make([]string, len(ss.Values))
+ for i, v := range ss.Values {
+ vals[i] = v.String()
+ }
+ return fmt.Sprintf("%s =>\n%s", ss.Metric, strings.Join(vals, "\n"))
+}
+
+// Value is a generic interface for values resulting from a query evaluation.
+type Value interface {
+ Type() ValueType
+ String() string
+}
+
+func (Matrix) Type() ValueType { return ValMatrix }
+func (Vector) Type() ValueType { return ValVector }
+func (*Scalar) Type() ValueType { return ValScalar }
+func (*String) Type() ValueType { return ValString }
+
+type ValueType int
+
+const (
+ ValNone ValueType = iota
+ ValScalar
+ ValVector
+ ValMatrix
+ ValString
+)
+
+// MarshalJSON implements json.Marshaler.
+func (et ValueType) MarshalJSON() ([]byte, error) {
+ return json.Marshal(et.String())
+}
+
+func (et *ValueType) UnmarshalJSON(b []byte) error {
+ var s string
+ if err := json.Unmarshal(b, &s); err != nil {
+ return err
+ }
+ switch s {
+ case "<ValNone>":
+ *et = ValNone
+ case "scalar":
+ *et = ValScalar
+ case "vector":
+ *et = ValVector
+ case "matrix":
+ *et = ValMatrix
+ case "string":
+ *et = ValString
+ default:
+ return fmt.Errorf("unknown value type %q", s)
+ }
+ return nil
+}
+
+func (e ValueType) String() string {
+ switch e {
+ case ValNone:
+ return "<ValNone>"
+ case ValScalar:
+ return "scalar"
+ case ValVector:
+ return "vector"
+ case ValMatrix:
+ return "matrix"
+ case ValString:
+ return "string"
+ }
+ panic("ValueType.String: unhandled value type")
+}
+
+// Scalar is a scalar value evaluated at the set timestamp.
+type Scalar struct {
+ Value SampleValue `json:"value"`
+ Timestamp Time `json:"timestamp"`
+}
+
+func (s Scalar) String() string {
+ return fmt.Sprintf("scalar: %v @[%v]", s.Value, s.Timestamp)
+}
+
+// MarshalJSON implements json.Marshaler.
+func (s Scalar) MarshalJSON() ([]byte, error) {
+ v := strconv.FormatFloat(float64(s.Value), 'f', -1, 64)
+ return json.Marshal([...]interface{}{s.Timestamp, string(v)})
+}
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (s *Scalar) UnmarshalJSON(b []byte) error {
+ var f string
+ v := [...]interface{}{&s.Timestamp, &f}
+
+ if err := json.Unmarshal(b, &v); err != nil {
+ return err
+ }
+
+ value, err := strconv.ParseFloat(f, 64)
+ if err != nil {
+ return fmt.Errorf("error parsing sample value: %s", err)
+ }
+ s.Value = SampleValue(value)
+ return nil
+}
+
+// String is a string value evaluated at the set timestamp.
+type String struct {
+ Value string `json:"value"`
+ Timestamp Time `json:"timestamp"`
+}
+
+func (s *String) String() string {
+ return s.Value
+}
+
+// MarshalJSON implements json.Marshaler.
+func (s String) MarshalJSON() ([]byte, error) {
+ return json.Marshal([]interface{}{s.Timestamp, s.Value})
+}
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (s *String) UnmarshalJSON(b []byte) error {
+ v := [...]interface{}{&s.Timestamp, &s.Value}
+ return json.Unmarshal(b, &v)
+}
+
+// Vector is basically only an alias for Samples, but the
+// contract is that in a Vector, all Samples have the same timestamp.
+type Vector []*Sample
+
+func (vec Vector) String() string {
+ entries := make([]string, len(vec))
+ for i, s := range vec {
+ entries[i] = s.String()
+ }
+ return strings.Join(entries, "\n")
+}
+
+func (vec Vector) Len() int { return len(vec) }
+func (vec Vector) Swap(i, j int) { vec[i], vec[j] = vec[j], vec[i] }
+
+// Less compares first the metrics, then the timestamp.
+func (vec Vector) Less(i, j int) bool {
+ switch {
+ case vec[i].Metric.Before(vec[j].Metric):
+ return true
+ case vec[j].Metric.Before(vec[i].Metric):
+ return false
+ case vec[i].Timestamp.Before(vec[j].Timestamp):
+ return true
+ default:
+ return false
+ }
+}
+
+// Equal compares two sets of samples and returns true if they are equal.
+func (vec Vector) Equal(o Vector) bool {
+ if len(vec) != len(o) {
+ return false
+ }
+
+ for i, sample := range vec {
+ if !sample.Equal(o[i]) {
+ return false
+ }
+ }
+ return true
+}
+
+// Matrix is a list of time series.
+type Matrix []*SampleStream
+
+func (m Matrix) Len() int { return len(m) }
+func (m Matrix) Less(i, j int) bool { return m[i].Metric.Before(m[j].Metric) }
+func (m Matrix) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
+
+func (mat Matrix) String() string {
+ matCp := make(Matrix, len(mat))
+ copy(matCp, mat)
+ sort.Sort(matCp)
+
+ strs := make([]string, len(matCp))
+
+ for i, ss := range matCp {
+ strs[i] = ss.String()
+ }
+
+ return strings.Join(strs, "\n")
+}
--- /dev/null
+// Copyright 2017 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package promlog defines standardised ways to initialize Go kit loggers
+// across Prometheus components.
+// It should typically only ever be imported by main packages.
+package promlog
+
+import (
+ "os"
+
+ "github.com/go-kit/kit/log"
+ "github.com/go-kit/kit/log/level"
+ "github.com/pkg/errors"
+)
+
+// AllowedLevel is a settable identifier for the minimum level a log entry
+// must be have.
+type AllowedLevel struct {
+ s string
+ o level.Option
+}
+
+func (l *AllowedLevel) String() string {
+ return l.s
+}
+
+// Set updates the value of the allowed level.
+func (l *AllowedLevel) Set(s string) error {
+ switch s {
+ case "debug":
+ l.o = level.AllowDebug()
+ case "info":
+ l.o = level.AllowInfo()
+ case "warn":
+ l.o = level.AllowWarn()
+ case "error":
+ l.o = level.AllowError()
+ default:
+ return errors.Errorf("unrecognized log level %q", s)
+ }
+ l.s = s
+ return nil
+}
+
+// New returns a new leveled oklog logger in the logfmt format. Each logged line will be annotated
+// with a timestamp. The output always goes to stderr.
+func New(al AllowedLevel) log.Logger {
+ l := log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
+ l = level.NewFilter(l, al.o)
+ l = log.With(l, "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller)
+ return l
+}
--- /dev/null
+package route
+
+import (
+ "net/http"
+
+ "github.com/julienschmidt/httprouter"
+ "golang.org/x/net/context"
+)
+
+type param string
+
+// Param returns param p for the context.
+func Param(ctx context.Context, p string) string {
+ return ctx.Value(param(p)).(string)
+}
+
+// WithParam returns a new context with param p set to v.
+func WithParam(ctx context.Context, p, v string) context.Context {
+ return context.WithValue(ctx, param(p), v)
+}
+
+// Router wraps httprouter.Router and adds support for prefixed sub-routers,
+// per-request context injections and instrumentation.
+type Router struct {
+ rtr *httprouter.Router
+ prefix string
+ instrh func(handlerName string, handler http.HandlerFunc) http.HandlerFunc
+}
+
+// New returns a new Router.
+func New() *Router {
+ return &Router{
+ rtr: httprouter.New(),
+ }
+}
+
+// WithInstrumentation returns a router with instrumentation support.
+func (r *Router) WithInstrumentation(instrh func(handlerName string, handler http.HandlerFunc) http.HandlerFunc) *Router {
+ return &Router{rtr: r.rtr, prefix: r.prefix, instrh: instrh}
+}
+
+// WithPrefix returns a router that prefixes all registered routes with prefix.
+func (r *Router) WithPrefix(prefix string) *Router {
+ return &Router{rtr: r.rtr, prefix: r.prefix + prefix, instrh: r.instrh}
+}
+
+// handle turns a HandlerFunc into an httprouter.Handle.
+func (r *Router) handle(handlerName string, h http.HandlerFunc) httprouter.Handle {
+ if r.instrh != nil {
+ // This needs to be outside the closure to avoid data race when reading and writing to 'h'.
+ h = r.instrh(handlerName, h)
+ }
+ return func(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+
+ for _, p := range params {
+ ctx = context.WithValue(ctx, param(p.Key), p.Value)
+ }
+ h(w, req.WithContext(ctx))
+ }
+}
+
+// Get registers a new GET route.
+func (r *Router) Get(path string, h http.HandlerFunc) {
+ r.rtr.GET(r.prefix+path, r.handle(path, h))
+}
+
+// Options registers a new OPTIONS route.
+func (r *Router) Options(path string, h http.HandlerFunc) {
+ r.rtr.OPTIONS(r.prefix+path, r.handle(path, h))
+}
+
+// Del registers a new DELETE route.
+func (r *Router) Del(path string, h http.HandlerFunc) {
+ r.rtr.DELETE(r.prefix+path, r.handle(path, h))
+}
+
+// Put registers a new PUT route.
+func (r *Router) Put(path string, h http.HandlerFunc) {
+ r.rtr.PUT(r.prefix+path, r.handle(path, h))
+}
+
+// Post registers a new POST route.
+func (r *Router) Post(path string, h http.HandlerFunc) {
+ r.rtr.POST(r.prefix+path, r.handle(path, h))
+}
+
+// Redirect takes an absolute path and sends an internal HTTP redirect for it,
+// prefixed by the router's path prefix. Note that this method does not include
+// functionality for handling relative paths or full URL redirects.
+func (r *Router) Redirect(w http.ResponseWriter, req *http.Request, path string, code int) {
+ http.Redirect(w, req, r.prefix+path, code)
+}
+
+// ServeHTTP implements http.Handler.
+func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ r.rtr.ServeHTTP(w, req)
+}
+
+// FileServe returns a new http.HandlerFunc that serves files from dir.
+// Using routes must provide the *filepath parameter.
+func FileServe(dir string) http.HandlerFunc {
+ fs := http.FileServer(http.Dir(dir))
+
+ return func(w http.ResponseWriter, r *http.Request) {
+ r.URL.Path = Param(r.Context(), "filepath")
+ fs.ServeHTTP(w, r)
+ }
+}
--- /dev/null
+// Copyright 2016 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package version
+
+import (
+ "bytes"
+ "fmt"
+ "runtime"
+ "strings"
+ "text/template"
+
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+// Build information. Populated at build-time.
+var (
+ Version string
+ Revision string
+ Branch string
+ BuildUser string
+ BuildDate string
+ GoVersion = runtime.Version()
+)
+
+// NewCollector returns a collector which exports metrics about current version information.
+func NewCollector(program string) *prometheus.GaugeVec {
+ buildInfo := prometheus.NewGaugeVec(
+ prometheus.GaugeOpts{
+ Namespace: program,
+ Name: "build_info",
+ Help: fmt.Sprintf(
+ "A metric with a constant '1' value labeled by version, revision, branch, and goversion from which %s was built.",
+ program,
+ ),
+ },
+ []string{"version", "revision", "branch", "goversion"},
+ )
+ buildInfo.WithLabelValues(Version, Revision, Branch, GoVersion).Set(1)
+ return buildInfo
+}
+
+// versionInfoTmpl contains the template used by Info.
+var versionInfoTmpl = `
+{{.program}}, version {{.version}} (branch: {{.branch}}, revision: {{.revision}})
+ build user: {{.buildUser}}
+ build date: {{.buildDate}}
+ go version: {{.goVersion}}
+`
+
+// Print returns version information.
+func Print(program string) string {
+ m := map[string]string{
+ "program": program,
+ "version": Version,
+ "revision": Revision,
+ "branch": Branch,
+ "buildUser": BuildUser,
+ "buildDate": BuildDate,
+ "goVersion": GoVersion,
+ }
+ t := template.Must(template.New("version").Parse(versionInfoTmpl))
+
+ var buf bytes.Buffer
+ if err := t.ExecuteTemplate(&buf, "version", m); err != nil {
+ panic(err)
+ }
+ return strings.TrimSpace(buf.String())
+}
+
+// Info returns version, branch and revision information.
+func Info() string {
+ return fmt.Sprintf("(version=%s, branch=%s, revision=%s)", Version, Branch, Revision)
+}
+
+// BuildContext returns goVersion, buildUser and buildDate information.
+func BuildContext() string {
+ return fmt.Sprintf("(go=%s, user=%s, date=%s)", GoVersion, BuildUser, BuildDate)
+}
--- /dev/null
+The Prometheus project was started by Matt T. Proud (emeritus) and
+Julius Volz in 2012.
+
+Maintainers of this repository:
+
+* Tobias Schmidt <ts@soundcloud.com>
+
+The following individuals have contributed code to this repository
+(listed in alphabetical order):
+
+* Armen Baghumian <abaghumian@noggin.com.au>
+* Bjoern Rabenstein <beorn@soundcloud.com>
+* David Cournapeau <cournape@gmail.com>
+* Ji-Hoon, Seol <jihoon.seol@gmail.com>
+* Jonas Große Sundrup <cherti@letopolis.de>
+* Julius Volz <julius@soundcloud.com>
+* Matthias Rampke <mr@soundcloud.com>
+* Nicky Gerritsen <nicky@streamone.nl>
+* Rémi Audebert <contact@halfr.net>
+* Tobias Schmidt <tobidt@gmail.com>
--- /dev/null
+# Contributing
+
+Prometheus uses GitHub to manage reviews of pull requests.
+
+* If you have a trivial fix or improvement, go ahead and create a pull
+ request, addressing (with `@...`) one or more of the maintainers
+ (see [AUTHORS.md](AUTHORS.md)) in the description of the pull request.
+
+* If you plan to do something more involved, first discuss your ideas
+ on our [mailing list](https://groups.google.com/forum/?fromgroups#!forum/prometheus-developers).
+ This will avoid unnecessary work and surely give you and us a good deal
+ of inspiration.
+
+* Relevant coding style guidelines are the [Go Code Review
+ Comments](https://code.google.com/p/go-wiki/wiki/CodeReviewComments)
+ and the _Formatting and style_ section of Peter Bourgon's [Go: Best
+ Practices for Production
+ Environments](http://peter.bourgon.org/go-in-production/#formatting-and-style).
--- /dev/null
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
--- /dev/null
+ci:
+ go fmt
+ go vet
+ go test -v ./...
+ go get github.com/golang/lint/golint
+ golint *.go
--- /dev/null
+procfs provides functions to retrieve system, kernel and process
+metrics from the pseudo-filesystem proc.
+
+Copyright 2014-2015 The Prometheus Authors
+
+This product includes software developed at
+SoundCloud Ltd. (http://soundcloud.com/).
--- /dev/null
+# procfs
+
+This procfs package provides functions to retrieve system, kernel and process
+metrics from the pseudo-filesystem proc.
+
+*WARNING*: This package is a work in progress. Its API may still break in
+backwards-incompatible ways without warnings. Use it at your own risk.
+
+[](https://godoc.org/github.com/prometheus/procfs)
+[](https://travis-ci.org/prometheus/procfs)
--- /dev/null
+// Copyright 2014 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package procfs provides functions to retrieve system, kernel and process
+// metrics from the pseudo-filesystem proc.
+//
+// Example:
+//
+// package main
+//
+// import (
+// "fmt"
+// "log"
+//
+// "github.com/prometheus/procfs"
+// )
+//
+// func main() {
+// p, err := procfs.Self()
+// if err != nil {
+// log.Fatalf("could not get process: %s", err)
+// }
+//
+// stat, err := p.NewStat()
+// if err != nil {
+// log.Fatalf("could not get process stat: %s", err)
+// }
+//
+// fmt.Printf("command: %s\n", stat.Comm)
+// fmt.Printf("cpu time: %fs\n", stat.CPUTime())
+// fmt.Printf("vsize: %dB\n", stat.VirtualMemory())
+// fmt.Printf("rss: %dB\n", stat.ResidentMemory())
+// }
+//
+package procfs
--- /dev/null
+package procfs
+
+import (
+ "fmt"
+ "os"
+ "path"
+)
+
+// FS represents the pseudo-filesystem proc, which provides an interface to
+// kernel data structures.
+type FS string
+
+// DefaultMountPoint is the common mount point of the proc filesystem.
+const DefaultMountPoint = "/proc"
+
+// NewFS returns a new FS mounted under the given mountPoint. It will error
+// if the mount point can't be read.
+func NewFS(mountPoint string) (FS, error) {
+ info, err := os.Stat(mountPoint)
+ if err != nil {
+ return "", fmt.Errorf("could not read %s: %s", mountPoint, err)
+ }
+ if !info.IsDir() {
+ return "", fmt.Errorf("mount point %s is not a directory", mountPoint)
+ }
+
+ return FS(mountPoint), nil
+}
+
+func (fs FS) stat(p string) (os.FileInfo, error) {
+ return os.Stat(path.Join(string(fs), p))
+}
+
+func (fs FS) open(p string) (*os.File, error) {
+ return os.Open(path.Join(string(fs), p))
+}
+
+func (fs FS) readlink(p string) (string, error) {
+ return os.Readlink(path.Join(string(fs), p))
+}
--- /dev/null
+package procfs
+
+import (
+ "bufio"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net"
+ "strconv"
+ "strings"
+)
+
+// IPVSStats holds IPVS statistics, as exposed by the kernel in `/proc/net/ip_vs_stats`.
+type IPVSStats struct {
+ // Total count of connections.
+ Connections uint64
+ // Total incoming packages processed.
+ IncomingPackets uint64
+ // Total outgoing packages processed.
+ OutgoingPackets uint64
+ // Total incoming traffic.
+ IncomingBytes uint64
+ // Total outgoing traffic.
+ OutgoingBytes uint64
+}
+
+// IPVSBackendStatus holds current metrics of one virtual / real address pair.
+type IPVSBackendStatus struct {
+ // The local (virtual) IP address.
+ LocalAddress net.IP
+ // The local (virtual) port.
+ LocalPort uint16
+ // The transport protocol (TCP, UDP).
+ Proto string
+ // The remote (real) IP address.
+ RemoteAddress net.IP
+ // The remote (real) port.
+ RemotePort uint16
+ // The current number of active connections for this virtual/real address pair.
+ ActiveConn uint64
+ // The current number of inactive connections for this virtual/real address pair.
+ InactConn uint64
+ // The current weight of this virtual/real address pair.
+ Weight uint64
+}
+
+// NewIPVSStats reads the IPVS statistics.
+func NewIPVSStats() (IPVSStats, error) {
+ fs, err := NewFS(DefaultMountPoint)
+ if err != nil {
+ return IPVSStats{}, err
+ }
+
+ return fs.NewIPVSStats()
+}
+
+// NewIPVSStats reads the IPVS statistics from the specified `proc` filesystem.
+func (fs FS) NewIPVSStats() (IPVSStats, error) {
+ file, err := fs.open("net/ip_vs_stats")
+ if err != nil {
+ return IPVSStats{}, err
+ }
+ defer file.Close()
+
+ return parseIPVSStats(file)
+}
+
+// parseIPVSStats performs the actual parsing of `ip_vs_stats`.
+func parseIPVSStats(file io.Reader) (IPVSStats, error) {
+ var (
+ statContent []byte
+ statLines []string
+ statFields []string
+ stats IPVSStats
+ )
+
+ statContent, err := ioutil.ReadAll(file)
+ if err != nil {
+ return IPVSStats{}, err
+ }
+
+ statLines = strings.SplitN(string(statContent), "\n", 4)
+ if len(statLines) != 4 {
+ return IPVSStats{}, errors.New("ip_vs_stats corrupt: too short")
+ }
+
+ statFields = strings.Fields(statLines[2])
+ if len(statFields) != 5 {
+ return IPVSStats{}, errors.New("ip_vs_stats corrupt: unexpected number of fields")
+ }
+
+ stats.Connections, err = strconv.ParseUint(statFields[0], 16, 64)
+ if err != nil {
+ return IPVSStats{}, err
+ }
+ stats.IncomingPackets, err = strconv.ParseUint(statFields[1], 16, 64)
+ if err != nil {
+ return IPVSStats{}, err
+ }
+ stats.OutgoingPackets, err = strconv.ParseUint(statFields[2], 16, 64)
+ if err != nil {
+ return IPVSStats{}, err
+ }
+ stats.IncomingBytes, err = strconv.ParseUint(statFields[3], 16, 64)
+ if err != nil {
+ return IPVSStats{}, err
+ }
+ stats.OutgoingBytes, err = strconv.ParseUint(statFields[4], 16, 64)
+ if err != nil {
+ return IPVSStats{}, err
+ }
+
+ return stats, nil
+}
+
+// NewIPVSBackendStatus reads and returns the status of all (virtual,real) server pairs.
+func NewIPVSBackendStatus() ([]IPVSBackendStatus, error) {
+ fs, err := NewFS(DefaultMountPoint)
+ if err != nil {
+ return []IPVSBackendStatus{}, err
+ }
+
+ return fs.NewIPVSBackendStatus()
+}
+
+// NewIPVSBackendStatus reads and returns the status of all (virtual,real) server pairs from the specified `proc` filesystem.
+func (fs FS) NewIPVSBackendStatus() ([]IPVSBackendStatus, error) {
+ file, err := fs.open("net/ip_vs")
+ if err != nil {
+ return nil, err
+ }
+ defer file.Close()
+
+ return parseIPVSBackendStatus(file)
+}
+
+func parseIPVSBackendStatus(file io.Reader) ([]IPVSBackendStatus, error) {
+ var (
+ status []IPVSBackendStatus
+ scanner = bufio.NewScanner(file)
+ proto string
+ localAddress net.IP
+ localPort uint16
+ err error
+ )
+
+ for scanner.Scan() {
+ fields := strings.Fields(string(scanner.Text()))
+ if len(fields) == 0 {
+ continue
+ }
+ switch {
+ case fields[0] == "IP" || fields[0] == "Prot" || fields[1] == "RemoteAddress:Port":
+ continue
+ case fields[0] == "TCP" || fields[0] == "UDP":
+ if len(fields) < 2 {
+ continue
+ }
+ proto = fields[0]
+ localAddress, localPort, err = parseIPPort(fields[1])
+ if err != nil {
+ return nil, err
+ }
+ case fields[0] == "->":
+ if len(fields) < 6 {
+ continue
+ }
+ remoteAddress, remotePort, err := parseIPPort(fields[1])
+ if err != nil {
+ return nil, err
+ }
+ weight, err := strconv.ParseUint(fields[3], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ activeConn, err := strconv.ParseUint(fields[4], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ inactConn, err := strconv.ParseUint(fields[5], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ status = append(status, IPVSBackendStatus{
+ LocalAddress: localAddress,
+ LocalPort: localPort,
+ RemoteAddress: remoteAddress,
+ RemotePort: remotePort,
+ Proto: proto,
+ Weight: weight,
+ ActiveConn: activeConn,
+ InactConn: inactConn,
+ })
+ }
+ }
+ return status, nil
+}
+
+func parseIPPort(s string) (net.IP, uint16, error) {
+ tmp := strings.SplitN(s, ":", 2)
+
+ if len(tmp) != 2 {
+ return nil, 0, fmt.Errorf("invalid IP:Port: %s", s)
+ }
+
+ if len(tmp[0]) != 8 && len(tmp[0]) != 32 {
+ return nil, 0, fmt.Errorf("invalid IP: %s", tmp[0])
+ }
+
+ ip, err := hex.DecodeString(tmp[0])
+ if err != nil {
+ return nil, 0, err
+ }
+
+ port, err := strconv.ParseUint(tmp[1], 16, 16)
+ if err != nil {
+ return nil, 0, err
+ }
+
+ return ip, uint16(port), nil
+}
--- /dev/null
+package procfs
+
+import (
+ "fmt"
+ "io/ioutil"
+ "path"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+var (
+ statuslineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[[U_]+\]`)
+ buildlineRE = regexp.MustCompile(`\((\d+)/\d+\)`)
+)
+
+// MDStat holds info parsed from /proc/mdstat.
+type MDStat struct {
+ // Name of the device.
+ Name string
+ // activity-state of the device.
+ ActivityState string
+ // Number of active disks.
+ DisksActive int64
+ // Total number of disks the device consists of.
+ DisksTotal int64
+ // Number of blocks the device holds.
+ BlocksTotal int64
+ // Number of blocks on the device that are in sync.
+ BlocksSynced int64
+}
+
+// ParseMDStat parses an mdstat-file and returns a struct with the relevant infos.
+func (fs FS) ParseMDStat() (mdstates []MDStat, err error) {
+ mdStatusFilePath := path.Join(string(fs), "mdstat")
+ content, err := ioutil.ReadFile(mdStatusFilePath)
+ if err != nil {
+ return []MDStat{}, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err)
+ }
+
+ mdStatusFile := string(content)
+
+ lines := strings.Split(mdStatusFile, "\n")
+ var currentMD string
+
+ // Each md has at least the deviceline, statusline and one empty line afterwards
+ // so we will have probably something of the order len(lines)/3 devices
+ // so we use that for preallocation.
+ estimateMDs := len(lines) / 3
+ mdStates := make([]MDStat, 0, estimateMDs)
+
+ for i, l := range lines {
+ if l == "" {
+ // Skip entirely empty lines.
+ continue
+ }
+
+ if l[0] == ' ' {
+ // Those lines are not the beginning of a md-section.
+ continue
+ }
+
+ if strings.HasPrefix(l, "Personalities") || strings.HasPrefix(l, "unused") {
+ // We aren't interested in lines with general info.
+ continue
+ }
+
+ mainLine := strings.Split(l, " ")
+ if len(mainLine) < 3 {
+ return mdStates, fmt.Errorf("error parsing mdline: %s", l)
+ }
+ currentMD = mainLine[0] // name of md-device
+ activityState := mainLine[2] // activity status of said md-device
+
+ if len(lines) <= i+3 {
+ return mdStates, fmt.Errorf("error parsing %s: entry for %s has fewer lines than expected", mdStatusFilePath, currentMD)
+ }
+
+ active, total, size, err := evalStatusline(lines[i+1]) // parse statusline, always present
+ if err != nil {
+ return mdStates, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err)
+ }
+
+ //
+ // Now get the number of synced blocks.
+ //
+
+ // Get the line number of the syncing-line.
+ var j int
+ if strings.Contains(lines[i+2], "bitmap") { // then skip the bitmap line
+ j = i + 3
+ } else {
+ j = i + 2
+ }
+
+ // If device is syncing at the moment, get the number of currently synced bytes,
+ // otherwise that number equals the size of the device.
+ syncedBlocks := size
+ if strings.Contains(lines[j], "recovery") || strings.Contains(lines[j], "resync") {
+ syncedBlocks, err = evalBuildline(lines[j])
+ if err != nil {
+ return mdStates, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err)
+ }
+ }
+
+ mdStates = append(mdStates, MDStat{currentMD, activityState, active, total, size, syncedBlocks})
+
+ }
+
+ return mdStates, nil
+}
+
+func evalStatusline(statusline string) (active, total, size int64, err error) {
+ matches := statuslineRE.FindStringSubmatch(statusline)
+
+ // +1 to make it more obvious that the whole string containing the info is also returned as matches[0].
+ if len(matches) != 3+1 {
+ return 0, 0, 0, fmt.Errorf("unexpected number matches found in statusline: %s", statusline)
+ }
+
+ size, err = strconv.ParseInt(matches[1], 10, 64)
+ if err != nil {
+ return 0, 0, 0, fmt.Errorf("%s in statusline: %s", err, statusline)
+ }
+
+ total, err = strconv.ParseInt(matches[2], 10, 64)
+ if err != nil {
+ return 0, 0, 0, fmt.Errorf("%s in statusline: %s", err, statusline)
+ }
+
+ active, err = strconv.ParseInt(matches[3], 10, 64)
+ if err != nil {
+ return 0, 0, 0, fmt.Errorf("%s in statusline: %s", err, statusline)
+ }
+
+ return active, total, size, nil
+}
+
+// Gets the size that has already been synced out of the sync-line.
+func evalBuildline(buildline string) (int64, error) {
+ matches := buildlineRE.FindStringSubmatch(buildline)
+
+ // +1 to make it more obvious that the whole string containing the info is also returned as matches[0].
+ if len(matches) < 1+1 {
+ return 0, fmt.Errorf("too few matches found in buildline: %s", buildline)
+ }
+
+ if len(matches) > 1+1 {
+ return 0, fmt.Errorf("too many matches found in buildline: %s", buildline)
+ }
+
+ syncedSize, err := strconv.ParseInt(matches[1], 10, 64)
+ if err != nil {
+ return 0, fmt.Errorf("%s in buildline: %s", err, buildline)
+ }
+
+ return syncedSize, nil
+}
--- /dev/null
+package procfs
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path"
+ "strconv"
+ "strings"
+)
+
+// Proc provides information about a running process.
+type Proc struct {
+ // The process ID.
+ PID int
+
+ fs FS
+}
+
+// Procs represents a list of Proc structs.
+type Procs []Proc
+
+func (p Procs) Len() int { return len(p) }
+func (p Procs) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+func (p Procs) Less(i, j int) bool { return p[i].PID < p[j].PID }
+
+// Self returns a process for the current process.
+func Self() (Proc, error) {
+ return NewProc(os.Getpid())
+}
+
+// NewProc returns a process for the given pid under /proc.
+func NewProc(pid int) (Proc, error) {
+ fs, err := NewFS(DefaultMountPoint)
+ if err != nil {
+ return Proc{}, err
+ }
+
+ return fs.NewProc(pid)
+}
+
+// AllProcs returns a list of all currently avaible processes under /proc.
+func AllProcs() (Procs, error) {
+ fs, err := NewFS(DefaultMountPoint)
+ if err != nil {
+ return Procs{}, err
+ }
+
+ return fs.AllProcs()
+}
+
+// NewProc returns a process for the given pid.
+func (fs FS) NewProc(pid int) (Proc, error) {
+ if _, err := fs.stat(strconv.Itoa(pid)); err != nil {
+ return Proc{}, err
+ }
+
+ return Proc{PID: pid, fs: fs}, nil
+}
+
+// AllProcs returns a list of all currently avaible processes.
+func (fs FS) AllProcs() (Procs, error) {
+ d, err := fs.open("")
+ if err != nil {
+ return Procs{}, err
+ }
+ defer d.Close()
+
+ names, err := d.Readdirnames(-1)
+ if err != nil {
+ return Procs{}, fmt.Errorf("could not read %s: %s", d.Name(), err)
+ }
+
+ p := Procs{}
+ for _, n := range names {
+ pid, err := strconv.ParseInt(n, 10, 64)
+ if err != nil {
+ continue
+ }
+ p = append(p, Proc{PID: int(pid), fs: fs})
+ }
+
+ return p, nil
+}
+
+// CmdLine returns the command line of a process.
+func (p Proc) CmdLine() ([]string, error) {
+ f, err := p.open("cmdline")
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ data, err := ioutil.ReadAll(f)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(data) < 1 {
+ return []string{}, nil
+ }
+
+ return strings.Split(string(data[:len(data)-1]), string(byte(0))), nil
+}
+
+// Executable returns the absolute path of the executable command of a process.
+func (p Proc) Executable() (string, error) {
+ exe, err := p.readlink("exe")
+
+ if os.IsNotExist(err) {
+ return "", nil
+ }
+
+ return exe, err
+}
+
+// FileDescriptors returns the currently open file descriptors of a process.
+func (p Proc) FileDescriptors() ([]uintptr, error) {
+ names, err := p.fileDescriptors()
+ if err != nil {
+ return nil, err
+ }
+
+ fds := make([]uintptr, len(names))
+ for i, n := range names {
+ fd, err := strconv.ParseInt(n, 10, 32)
+ if err != nil {
+ return nil, fmt.Errorf("could not parse fd %s: %s", n, err)
+ }
+ fds[i] = uintptr(fd)
+ }
+
+ return fds, nil
+}
+
+// FileDescriptorTargets returns the targets of all file descriptors of a process.
+// If a file descriptor is not a symlink to a file (like a socket), that value will be the empty string.
+func (p Proc) FileDescriptorTargets() ([]string, error) {
+ names, err := p.fileDescriptors()
+ if err != nil {
+ return nil, err
+ }
+
+ targets := make([]string, len(names))
+
+ for i, name := range names {
+ target, err := p.readlink("fd/" + name)
+ if err == nil {
+ targets[i] = target
+ }
+ }
+
+ return targets, nil
+}
+
+// FileDescriptorsLen returns the number of currently open file descriptors of
+// a process.
+func (p Proc) FileDescriptorsLen() (int, error) {
+ fds, err := p.fileDescriptors()
+ if err != nil {
+ return 0, err
+ }
+
+ return len(fds), nil
+}
+
+func (p Proc) fileDescriptors() ([]string, error) {
+ d, err := p.open("fd")
+ if err != nil {
+ return nil, err
+ }
+ defer d.Close()
+
+ names, err := d.Readdirnames(-1)
+ if err != nil {
+ return nil, fmt.Errorf("could not read %s: %s", d.Name(), err)
+ }
+
+ return names, nil
+}
+
+func (p Proc) open(pa string) (*os.File, error) {
+ return p.fs.open(path.Join(strconv.Itoa(p.PID), pa))
+}
+
+func (p Proc) readlink(pa string) (string, error) {
+ return p.fs.readlink(path.Join(strconv.Itoa(p.PID), pa))
+}
--- /dev/null
+package procfs
+
+import (
+ "fmt"
+ "io/ioutil"
+)
+
+// ProcIO models the content of /proc/<pid>/io.
+type ProcIO struct {
+ // Chars read.
+ RChar uint64
+ // Chars written.
+ WChar uint64
+ // Read syscalls.
+ SyscR uint64
+ // Write syscalls.
+ SyscW uint64
+ // Bytes read.
+ ReadBytes uint64
+ // Bytes written.
+ WriteBytes uint64
+ // Bytes written, but taking into account truncation. See
+ // Documentation/filesystems/proc.txt in the kernel sources for
+ // detailed explanation.
+ CancelledWriteBytes int64
+}
+
+// NewIO creates a new ProcIO instance from a given Proc instance.
+func (p Proc) NewIO() (ProcIO, error) {
+ pio := ProcIO{}
+
+ f, err := p.open("io")
+ if err != nil {
+ return pio, err
+ }
+ defer f.Close()
+
+ data, err := ioutil.ReadAll(f)
+ if err != nil {
+ return pio, err
+ }
+
+ ioFormat := "rchar: %d\nwchar: %d\nsyscr: %d\nsyscw: %d\n" +
+ "read_bytes: %d\nwrite_bytes: %d\n" +
+ "cancelled_write_bytes: %d\n"
+
+ _, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR,
+ &pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes)
+ if err != nil {
+ return pio, err
+ }
+
+ return pio, nil
+}
--- /dev/null
+package procfs
+
+import (
+ "bufio"
+ "fmt"
+ "regexp"
+ "strconv"
+)
+
+// ProcLimits represents the soft limits for each of the process's resource
+// limits.
+type ProcLimits struct {
+ CPUTime int
+ FileSize int
+ DataSize int
+ StackSize int
+ CoreFileSize int
+ ResidentSet int
+ Processes int
+ OpenFiles int
+ LockedMemory int
+ AddressSpace int
+ FileLocks int
+ PendingSignals int
+ MsqqueueSize int
+ NicePriority int
+ RealtimePriority int
+ RealtimeTimeout int
+}
+
+const (
+ limitsFields = 3
+ limitsUnlimited = "unlimited"
+)
+
+var (
+ limitsDelimiter = regexp.MustCompile(" +")
+)
+
+// NewLimits returns the current soft limits of the process.
+func (p Proc) NewLimits() (ProcLimits, error) {
+ f, err := p.open("limits")
+ if err != nil {
+ return ProcLimits{}, err
+ }
+ defer f.Close()
+
+ var (
+ l = ProcLimits{}
+ s = bufio.NewScanner(f)
+ )
+ for s.Scan() {
+ fields := limitsDelimiter.Split(s.Text(), limitsFields)
+ if len(fields) != limitsFields {
+ return ProcLimits{}, fmt.Errorf(
+ "couldn't parse %s line %s", f.Name(), s.Text())
+ }
+
+ switch fields[0] {
+ case "Max cpu time":
+ l.CPUTime, err = parseInt(fields[1])
+ case "Max file size":
+ l.FileLocks, err = parseInt(fields[1])
+ case "Max data size":
+ l.DataSize, err = parseInt(fields[1])
+ case "Max stack size":
+ l.StackSize, err = parseInt(fields[1])
+ case "Max core file size":
+ l.CoreFileSize, err = parseInt(fields[1])
+ case "Max resident set":
+ l.ResidentSet, err = parseInt(fields[1])
+ case "Max processes":
+ l.Processes, err = parseInt(fields[1])
+ case "Max open files":
+ l.OpenFiles, err = parseInt(fields[1])
+ case "Max locked memory":
+ l.LockedMemory, err = parseInt(fields[1])
+ case "Max address space":
+ l.AddressSpace, err = parseInt(fields[1])
+ case "Max file locks":
+ l.FileLocks, err = parseInt(fields[1])
+ case "Max pending signals":
+ l.PendingSignals, err = parseInt(fields[1])
+ case "Max msgqueue size":
+ l.MsqqueueSize, err = parseInt(fields[1])
+ case "Max nice priority":
+ l.NicePriority, err = parseInt(fields[1])
+ case "Max realtime priority":
+ l.RealtimePriority, err = parseInt(fields[1])
+ case "Max realtime timeout":
+ l.RealtimeTimeout, err = parseInt(fields[1])
+ }
+
+ if err != nil {
+ return ProcLimits{}, err
+ }
+ }
+
+ return l, s.Err()
+}
+
+func parseInt(s string) (int, error) {
+ if s == limitsUnlimited {
+ return -1, nil
+ }
+ i, err := strconv.ParseInt(s, 10, 32)
+ if err != nil {
+ return 0, fmt.Errorf("couldn't parse value %s: %s", s, err)
+ }
+ return int(i), nil
+}
--- /dev/null
+package procfs
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "os"
+)
+
+// Originally, this USER_HZ value was dynamically retrieved via a sysconf call which
+// required cgo. However, that caused a lot of problems regarding
+// cross-compilation. Alternatives such as running a binary to determine the
+// value, or trying to derive it in some other way were all problematic.
+// After much research it was determined that USER_HZ is actually hardcoded to
+// 100 on all Go-supported platforms as of the time of this writing. This is
+// why we decided to hardcode it here as well. It is not impossible that there
+// could be systems with exceptions, but they should be very exotic edge cases,
+// and in that case, the worst outcome will be two misreported metrics.
+//
+// See also the following discussions:
+//
+// - https://github.com/prometheus/node_exporter/issues/52
+// - https://github.com/prometheus/procfs/pull/2
+// - http://stackoverflow.com/questions/17410841/how-does-user-hz-solve-the-jiffy-scaling-issue
+const userHZ = 100
+
+// ProcStat provides status information about the process,
+// read from /proc/[pid]/stat.
+type ProcStat struct {
+ // The process ID.
+ PID int
+ // The filename of the executable.
+ Comm string
+ // The process state.
+ State string
+ // The PID of the parent of this process.
+ PPID int
+ // The process group ID of the process.
+ PGRP int
+ // The session ID of the process.
+ Session int
+ // The controlling terminal of the process.
+ TTY int
+ // The ID of the foreground process group of the controlling terminal of
+ // the process.
+ TPGID int
+ // The kernel flags word of the process.
+ Flags uint
+ // The number of minor faults the process has made which have not required
+ // loading a memory page from disk.
+ MinFlt uint
+ // The number of minor faults that the process's waited-for children have
+ // made.
+ CMinFlt uint
+ // The number of major faults the process has made which have required
+ // loading a memory page from disk.
+ MajFlt uint
+ // The number of major faults that the process's waited-for children have
+ // made.
+ CMajFlt uint
+ // Amount of time that this process has been scheduled in user mode,
+ // measured in clock ticks.
+ UTime uint
+ // Amount of time that this process has been scheduled in kernel mode,
+ // measured in clock ticks.
+ STime uint
+ // Amount of time that this process's waited-for children have been
+ // scheduled in user mode, measured in clock ticks.
+ CUTime uint
+ // Amount of time that this process's waited-for children have been
+ // scheduled in kernel mode, measured in clock ticks.
+ CSTime uint
+ // For processes running a real-time scheduling policy, this is the negated
+ // scheduling priority, minus one.
+ Priority int
+ // The nice value, a value in the range 19 (low priority) to -20 (high
+ // priority).
+ Nice int
+ // Number of threads in this process.
+ NumThreads int
+ // The time the process started after system boot, the value is expressed
+ // in clock ticks.
+ Starttime uint64
+ // Virtual memory size in bytes.
+ VSize int
+ // Resident set size in pages.
+ RSS int
+
+ fs FS
+}
+
+// NewStat returns the current status information of the process.
+func (p Proc) NewStat() (ProcStat, error) {
+ f, err := p.open("stat")
+ if err != nil {
+ return ProcStat{}, err
+ }
+ defer f.Close()
+
+ data, err := ioutil.ReadAll(f)
+ if err != nil {
+ return ProcStat{}, err
+ }
+
+ var (
+ ignore int
+
+ s = ProcStat{PID: p.PID, fs: p.fs}
+ l = bytes.Index(data, []byte("("))
+ r = bytes.LastIndex(data, []byte(")"))
+ )
+
+ if l < 0 || r < 0 {
+ return ProcStat{}, fmt.Errorf(
+ "unexpected format, couldn't extract comm: %s",
+ data,
+ )
+ }
+
+ s.Comm = string(data[l+1 : r])
+ _, err = fmt.Fscan(
+ bytes.NewBuffer(data[r+2:]),
+ &s.State,
+ &s.PPID,
+ &s.PGRP,
+ &s.Session,
+ &s.TTY,
+ &s.TPGID,
+ &s.Flags,
+ &s.MinFlt,
+ &s.CMinFlt,
+ &s.MajFlt,
+ &s.CMajFlt,
+ &s.UTime,
+ &s.STime,
+ &s.CUTime,
+ &s.CSTime,
+ &s.Priority,
+ &s.Nice,
+ &s.NumThreads,
+ &ignore,
+ &s.Starttime,
+ &s.VSize,
+ &s.RSS,
+ )
+ if err != nil {
+ return ProcStat{}, err
+ }
+
+ return s, nil
+}
+
+// VirtualMemory returns the virtual memory size in bytes.
+func (s ProcStat) VirtualMemory() int {
+ return s.VSize
+}
+
+// ResidentMemory returns the resident memory size in bytes.
+func (s ProcStat) ResidentMemory() int {
+ return s.RSS * os.Getpagesize()
+}
+
+// StartTime returns the unix timestamp of the process in seconds.
+func (s ProcStat) StartTime() (float64, error) {
+ stat, err := s.fs.NewStat()
+ if err != nil {
+ return 0, err
+ }
+ return float64(stat.BootTime) + (float64(s.Starttime) / userHZ), nil
+}
+
+// CPUTime returns the total CPU user and system time in seconds.
+func (s ProcStat) CPUTime() float64 {
+ return float64(s.UTime+s.STime) / userHZ
+}
--- /dev/null
+package procfs
+
+import (
+ "bufio"
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+// Stat represents kernel/system statistics.
+type Stat struct {
+ // Boot time in seconds since the Epoch.
+ BootTime int64
+}
+
+// NewStat returns kernel/system statistics read from /proc/stat.
+func NewStat() (Stat, error) {
+ fs, err := NewFS(DefaultMountPoint)
+ if err != nil {
+ return Stat{}, err
+ }
+
+ return fs.NewStat()
+}
+
+// NewStat returns an information about current kernel/system statistics.
+func (fs FS) NewStat() (Stat, error) {
+ f, err := fs.open("stat")
+ if err != nil {
+ return Stat{}, err
+ }
+ defer f.Close()
+
+ s := bufio.NewScanner(f)
+ for s.Scan() {
+ line := s.Text()
+ if !strings.HasPrefix(line, "btime") {
+ continue
+ }
+ fields := strings.Fields(line)
+ if len(fields) != 2 {
+ return Stat{}, fmt.Errorf("couldn't parse %s line %s", f.Name(), line)
+ }
+ i, err := strconv.ParseInt(fields[1], 10, 32)
+ if err != nil {
+ return Stat{}, fmt.Errorf("couldn't parse %s: %s", fields[1], err)
+ }
+ return Stat{BootTime: i}, nil
+ }
+ if err := s.Err(); err != nil {
+ return Stat{}, fmt.Errorf("couldn't parse %s: %s", f.Name(), err)
+ }
+
+ return Stat{}, fmt.Errorf("couldn't parse %s, missing btime", f.Name())
+}
--- /dev/null
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
--- /dev/null
+The Prometheus systems and service monitoring server
+Copyright 2012-2015 The Prometheus Authors
+
+This product includes software developed at
+SoundCloud Ltd. (http://soundcloud.com/).
+
+
+The following components are included in this product:
+
+Bootstrap
+http://getbootstrap.com
+Copyright 2011-2014 Twitter, Inc.
+Licensed under the MIT License
+
+bootstrap3-typeahead.js
+https://github.com/bassjobsen/Bootstrap-3-Typeahead
+Original written by @mdo and @fat
+Copyright 2014 Bass Jobsen @bassjobsen
+Licensed under the Apache License, Version 2.0
+
+fuzzy
+https://github.com/mattyork/fuzzy
+Original written by @mattyork
+Copyright 2012 Matt York
+Licensed under the MIT License
+
+bootstrap-datetimepicker.js
+https://github.com/Eonasdan/bootstrap-datetimepicker
+Copyright 2015 Jonathan Peterson (@Eonasdan)
+Licensed under the MIT License
+
+moment.js
+https://github.com/moment/moment/
+Copyright JS Foundation and other contributors
+Licensed under the MIT License
+
+Rickshaw
+https://github.com/shutterstock/rickshaw
+Copyright 2011-2014 by Shutterstock Images, LLC
+See https://github.com/shutterstock/rickshaw/blob/master/LICENSE for license details
+
+mustache.js
+https://github.com/janl/mustache.js
+Copyright 2009 Chris Wanstrath (Ruby)
+Copyright 2010-2014 Jan Lehnardt (JavaScript)
+Copyright 2010-2015 The mustache.js community
+Licensed under the MIT License
+
+jQuery
+https://jquery.org
+Copyright jQuery Foundation and other contributors
+Licensed under the MIT License
+
+Protocol Buffers for Go with Gadgets
+http://github.com/gogo/protobuf/
+Copyright (c) 2013, The GoGo Authors.
+See source code for license details.
+
+Go support for leveled logs, analogous to
+https://code.google.com/p/google-glog/
+Copyright 2013 Google Inc.
+Licensed under the Apache License, Version 2.0
+
+Support for streaming Protocol Buffer messages for the Go language (golang).
+https://github.com/matttproud/golang_protobuf_extensions
+Copyright 2013 Matt T. Proud
+Licensed under the Apache License, Version 2.0
+
+DNS library in Go
+http://miek.nl/posts/2014/Aug/16/go-dns-package/
+Copyright 2009 The Go Authors, 2011 Miek Gieben
+See https://github.com/miekg/dns/blob/master/LICENSE for license details.
+
+LevelDB key/value database in Go
+https://github.com/syndtr/goleveldb
+Copyright 2012 Suryandaru Triandana
+See https://github.com/syndtr/goleveldb/blob/master/LICENSE for license details.
+
+gosnappy - a fork of code.google.com/p/snappy-go
+https://github.com/syndtr/gosnappy
+Copyright 2011 The Snappy-Go Authors
+See https://github.com/syndtr/gosnappy/blob/master/LICENSE for license details.
+
+go-zookeeper - Native ZooKeeper client for Go
+https://github.com/samuel/go-zookeeper
+Copyright (c) 2013, Samuel Stauffer <samuel@descolada.com>
+See https://github.com/samuel/go-zookeeper/blob/master/LICENSE for license details.
--- /dev/null
+// Copyright 2017 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package labels
+
+import (
+ "bytes"
+ "encoding/json"
+ "sort"
+ "strconv"
+ "strings"
+
+ "github.com/cespare/xxhash"
+)
+
+const sep = '\xff'
+
+// Well-known label names used by Prometheus components.
+const (
+ MetricName = "__name__"
+ AlertName = "alertname"
+ BucketLabel = "le"
+ InstanceName = "instance"
+)
+
+// Label is a key/value pair of strings.
+type Label struct {
+ Name, Value string
+}
+
+// Labels is a sorted set of labels. Order has to be guaranteed upon
+// instantiation.
+type Labels []Label
+
+func (ls Labels) Len() int { return len(ls) }
+func (ls Labels) Swap(i, j int) { ls[i], ls[j] = ls[j], ls[i] }
+func (ls Labels) Less(i, j int) bool { return ls[i].Name < ls[j].Name }
+
+func (ls Labels) String() string {
+ var b bytes.Buffer
+
+ b.WriteByte('{')
+ for i, l := range ls {
+ if i > 0 {
+ b.WriteByte(',')
+ b.WriteByte(' ')
+ }
+ b.WriteString(l.Name)
+ b.WriteByte('=')
+ b.WriteString(strconv.Quote(l.Value))
+ }
+ b.WriteByte('}')
+
+ return b.String()
+}
+
+// MarshalJSON implements json.Marshaler.
+func (ls Labels) MarshalJSON() ([]byte, error) {
+ return json.Marshal(ls.Map())
+}
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (ls *Labels) UnmarshalJSON(b []byte) error {
+ var m map[string]string
+
+ if err := json.Unmarshal(b, &m); err != nil {
+ return err
+ }
+
+ *ls = FromMap(m)
+ return nil
+}
+
+// Hash returns a hash value for the label set.
+func (ls Labels) Hash() uint64 {
+ b := make([]byte, 0, 1024)
+
+ for _, v := range ls {
+ b = append(b, v.Name...)
+ b = append(b, sep)
+ b = append(b, v.Value...)
+ b = append(b, sep)
+ }
+ return xxhash.Sum64(b)
+}
+
+// Copy returns a copy of the labels.
+func (ls Labels) Copy() Labels {
+ res := make(Labels, len(ls))
+ copy(res, ls)
+ return res
+}
+
+// Get returns the value for the label with the given name.
+// Returns an empty string if the label doesn't exist.
+func (ls Labels) Get(name string) string {
+ for _, l := range ls {
+ if l.Name == name {
+ return l.Value
+ }
+ }
+ return ""
+}
+
+// Has returns true if the label with the given name is present.
+func (ls Labels) Has(name string) bool {
+ for _, l := range ls {
+ if l.Name == name {
+ return true
+ }
+ }
+ return false
+}
+
+// Equal returns whether the two label sets are equal.
+func Equal(ls, o Labels) bool {
+ if len(ls) != len(o) {
+ return false
+ }
+ for i, l := range ls {
+ if l.Name != o[i].Name || l.Value != o[i].Value {
+ return false
+ }
+ }
+ return true
+}
+
+// Map returns a string map of the labels.
+func (ls Labels) Map() map[string]string {
+ m := make(map[string]string, len(ls))
+ for _, l := range ls {
+ m[l.Name] = l.Value
+ }
+ return m
+}
+
+// New returns a sorted Labels from the given labels.
+// The caller has to guarantee that all label names are unique.
+func New(ls ...Label) Labels {
+ set := make(Labels, 0, len(ls))
+ for _, l := range ls {
+ set = append(set, l)
+ }
+ sort.Sort(set)
+
+ return set
+}
+
+// FromMap returns new sorted Labels from the given map.
+func FromMap(m map[string]string) Labels {
+ l := make([]Label, 0, len(m))
+ for k, v := range m {
+ l = append(l, Label{Name: k, Value: v})
+ }
+ return New(l...)
+}
+
+// FromStrings creates new labels from pairs of strings.
+func FromStrings(ss ...string) Labels {
+ if len(ss)%2 != 0 {
+ panic("invalid number of strings")
+ }
+ var res Labels
+ for i := 0; i < len(ss); i += 2 {
+ res = append(res, Label{Name: ss[i], Value: ss[i+1]})
+ }
+
+ sort.Sort(res)
+ return res
+}
+
+// Compare compares the two label sets.
+// The result will be 0 if a==b, <0 if a < b, and >0 if a > b.
+func Compare(a, b Labels) int {
+ l := len(a)
+ if len(b) < l {
+ l = len(b)
+ }
+
+ for i := 0; i < l; i++ {
+ if d := strings.Compare(a[i].Name, b[i].Name); d != 0 {
+ return d
+ }
+ if d := strings.Compare(a[i].Value, b[i].Value); d != 0 {
+ return d
+ }
+ }
+ // If all labels so far were in common, the set with fewer labels comes first.
+ return len(a) - len(b)
+}
+
+// Builder allows modifiying Labels.
+type Builder struct {
+ base Labels
+ del []string
+ add []Label
+}
+
+// NewBuilder returns a new LabelsBuilder
+func NewBuilder(base Labels) *Builder {
+ return &Builder{
+ base: base,
+ del: make([]string, 0, 5),
+ add: make([]Label, 0, 5),
+ }
+}
+
+// Del deletes the label of the given name.
+func (b *Builder) Del(ns ...string) *Builder {
+ for _, n := range ns {
+ for i, a := range b.add {
+ if a.Name == n {
+ b.add = append(b.add[:i], b.add[i+1:]...)
+ }
+ }
+ b.del = append(b.del, n)
+ }
+ return b
+}
+
+// Set the name/value pair as a label.
+func (b *Builder) Set(n, v string) *Builder {
+ for i, a := range b.add {
+ if a.Name == n {
+ b.add[i].Value = v
+ return b
+ }
+ }
+ b.add = append(b.add, Label{Name: n, Value: v})
+
+ return b
+}
+
+// Labels returns the labels from the builder. If no modifications
+// were made, the original labels are returned.
+func (b *Builder) Labels() Labels {
+ if len(b.del) == 0 && len(b.add) == 0 {
+ return b.base
+ }
+
+ // In the general case, labels are removed, modified or moved
+ // rather than added.
+ res := make(Labels, 0, len(b.base))
+Outer:
+ for _, l := range b.base {
+ for _, n := range b.del {
+ if l.Name == n {
+ continue Outer
+ }
+ }
+ for _, la := range b.add {
+ if l.Name == la.Name {
+ continue Outer
+ }
+ }
+ res = append(res, l)
+ }
+ res = append(res, b.add...)
+ sort.Sort(res)
+
+ return res
+}
--- /dev/null
+// Copyright 2017 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package labels
+
+import (
+ "fmt"
+ "regexp"
+)
+
+// MatchType is an enum for label matching types.
+type MatchType int
+
+// Possible MatchTypes.
+const (
+ MatchEqual MatchType = iota
+ MatchNotEqual
+ MatchRegexp
+ MatchNotRegexp
+)
+
+func (m MatchType) String() string {
+ typeToStr := map[MatchType]string{
+ MatchEqual: "=",
+ MatchNotEqual: "!=",
+ MatchRegexp: "=~",
+ MatchNotRegexp: "!~",
+ }
+ if str, ok := typeToStr[m]; ok {
+ return str
+ }
+ panic("unknown match type")
+}
+
+// Matcher models the matching of a label.
+type Matcher struct {
+ Type MatchType
+ Name string
+ Value string
+
+ re *regexp.Regexp
+}
+
+// NewMatcher returns a matcher object.
+func NewMatcher(t MatchType, n, v string) (*Matcher, error) {
+ m := &Matcher{
+ Type: t,
+ Name: n,
+ Value: v,
+ }
+ if t == MatchRegexp || t == MatchNotRegexp {
+ re, err := regexp.Compile("^(?:" + v + ")$")
+ if err != nil {
+ return nil, err
+ }
+ m.re = re
+ }
+ return m, nil
+}
+
+func (m *Matcher) String() string {
+ return fmt.Sprintf("%s%s%q", m.Name, m.Type, m.Value)
+}
+
+// Matches returns whether the matcher matches the given string value.
+func (m *Matcher) Matches(s string) bool {
+ switch m.Type {
+ case MatchEqual:
+ return s == m.Value
+ case MatchNotEqual:
+ return s != m.Value
+ case MatchRegexp:
+ return m.re.MatchString(s)
+ case MatchNotRegexp:
+ return !m.re.MatchString(s)
+ }
+ panic("labels.Matcher.Matches: invalid match type")
+}
--- /dev/null
+Copyright (C) 2013-2016 by Maxim Bublis <b@codemonkey.ru>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--- /dev/null
+# UUID package for Go language
+
+[](https://travis-ci.org/satori/go.uuid)
+[](http://godoc.org/github.com/satori/go.uuid)
+
+This package provides pure Go implementation of Universally Unique Identifier (UUID). Supported both creation and parsing of UUIDs.
+
+With 100% test coverage and benchmarks out of box.
+
+Supported versions:
+* Version 1, based on timestamp and MAC address (RFC 4122)
+* Version 2, based on timestamp, MAC address and POSIX UID/GID (DCE 1.1)
+* Version 3, based on MD5 hashing (RFC 4122)
+* Version 4, based on random numbers (RFC 4122)
+* Version 5, based on SHA-1 hashing (RFC 4122)
+
+## Installation
+
+Use the `go` command:
+
+ $ go get github.com/satori/go.uuid
+
+## Requirements
+
+UUID package requires any stable version of Go Programming Language.
+
+## Example
+
+```go
+package main
+
+import (
+ "fmt"
+ "github.com/satori/go.uuid"
+)
+
+func main() {
+ // Creating UUID Version 4
+ u1 := uuid.NewV4()
+ fmt.Printf("UUIDv4: %s\n", u1)
+
+ // Parsing UUID from string input
+ u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
+ if err != nil {
+ fmt.Printf("Something gone wrong: %s", err)
+ }
+ fmt.Printf("Successfully parsed: %s", u2)
+}
+```
+
+## Documentation
+
+[Documentation](http://godoc.org/github.com/satori/go.uuid) is hosted at GoDoc project.
+
+## Links
+* [RFC 4122](http://tools.ietf.org/html/rfc4122)
+* [DCE 1.1: Authentication and Security Services](http://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01)
+
+## Copyright
+
+Copyright (C) 2013-2016 by Maxim Bublis <b@codemonkey.ru>.
+
+UUID package released under MIT License.
+See [LICENSE](https://github.com/satori/go.uuid/blob/master/LICENSE) for details.
--- /dev/null
+// Copyright (C) 2013-2015 by Maxim Bublis <b@codemonkey.ru>
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+// Package uuid provides implementation of Universally Unique Identifier (UUID).
+// Supported versions are 1, 3, 4 and 5 (as specified in RFC 4122) and
+// version 2 (as specified in DCE 1.1).
+package uuid
+
+import (
+ "bytes"
+ "crypto/md5"
+ "crypto/rand"
+ "crypto/sha1"
+ "database/sql/driver"
+ "encoding/binary"
+ "encoding/hex"
+ "fmt"
+ "hash"
+ "net"
+ "os"
+ "sync"
+ "time"
+)
+
+// UUID layout variants.
+const (
+ VariantNCS = iota
+ VariantRFC4122
+ VariantMicrosoft
+ VariantFuture
+)
+
+// UUID DCE domains.
+const (
+ DomainPerson = iota
+ DomainGroup
+ DomainOrg
+)
+
+// Difference in 100-nanosecond intervals between
+// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970).
+const epochStart = 122192928000000000
+
+// Used in string method conversion
+const dash byte = '-'
+
+// UUID v1/v2 storage.
+var (
+ storageMutex sync.Mutex
+ storageOnce sync.Once
+ epochFunc = unixTimeFunc
+ clockSequence uint16
+ lastTime uint64
+ hardwareAddr [6]byte
+ posixUID = uint32(os.Getuid())
+ posixGID = uint32(os.Getgid())
+)
+
+// String parse helpers.
+var (
+ urnPrefix = []byte("urn:uuid:")
+ byteGroups = []int{8, 4, 4, 4, 12}
+)
+
+func initClockSequence() {
+ buf := make([]byte, 2)
+ safeRandom(buf)
+ clockSequence = binary.BigEndian.Uint16(buf)
+}
+
+func initHardwareAddr() {
+ interfaces, err := net.Interfaces()
+ if err == nil {
+ for _, iface := range interfaces {
+ if len(iface.HardwareAddr) >= 6 {
+ copy(hardwareAddr[:], iface.HardwareAddr)
+ return
+ }
+ }
+ }
+
+ // Initialize hardwareAddr randomly in case
+ // of real network interfaces absence
+ safeRandom(hardwareAddr[:])
+
+ // Set multicast bit as recommended in RFC 4122
+ hardwareAddr[0] |= 0x01
+}
+
+func initStorage() {
+ initClockSequence()
+ initHardwareAddr()
+}
+
+func safeRandom(dest []byte) {
+ if _, err := rand.Read(dest); err != nil {
+ panic(err)
+ }
+}
+
+// Returns difference in 100-nanosecond intervals between
+// UUID epoch (October 15, 1582) and current time.
+// This is default epoch calculation function.
+func unixTimeFunc() uint64 {
+ return epochStart + uint64(time.Now().UnixNano()/100)
+}
+
+// UUID representation compliant with specification
+// described in RFC 4122.
+type UUID [16]byte
+
+// The nil UUID is special form of UUID that is specified to have all
+// 128 bits set to zero.
+var Nil = UUID{}
+
+// Predefined namespace UUIDs.
+var (
+ NamespaceDNS, _ = FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
+ NamespaceURL, _ = FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8")
+ NamespaceOID, _ = FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
+ NamespaceX500, _ = FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
+)
+
+// And returns result of binary AND of two UUIDs.
+func And(u1 UUID, u2 UUID) UUID {
+ u := UUID{}
+ for i := 0; i < 16; i++ {
+ u[i] = u1[i] & u2[i]
+ }
+ return u
+}
+
+// Or returns result of binary OR of two UUIDs.
+func Or(u1 UUID, u2 UUID) UUID {
+ u := UUID{}
+ for i := 0; i < 16; i++ {
+ u[i] = u1[i] | u2[i]
+ }
+ return u
+}
+
+// Equal returns true if u1 and u2 equals, otherwise returns false.
+func Equal(u1 UUID, u2 UUID) bool {
+ return bytes.Equal(u1[:], u2[:])
+}
+
+// Version returns algorithm version used to generate UUID.
+func (u UUID) Version() uint {
+ return uint(u[6] >> 4)
+}
+
+// Variant returns UUID layout variant.
+func (u UUID) Variant() uint {
+ switch {
+ case (u[8] & 0x80) == 0x00:
+ return VariantNCS
+ case (u[8]&0xc0)|0x80 == 0x80:
+ return VariantRFC4122
+ case (u[8]&0xe0)|0xc0 == 0xc0:
+ return VariantMicrosoft
+ }
+ return VariantFuture
+}
+
+// Bytes returns bytes slice representation of UUID.
+func (u UUID) Bytes() []byte {
+ return u[:]
+}
+
+// Returns canonical string representation of UUID:
+// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
+func (u UUID) String() string {
+ buf := make([]byte, 36)
+
+ hex.Encode(buf[0:8], u[0:4])
+ buf[8] = dash
+ hex.Encode(buf[9:13], u[4:6])
+ buf[13] = dash
+ hex.Encode(buf[14:18], u[6:8])
+ buf[18] = dash
+ hex.Encode(buf[19:23], u[8:10])
+ buf[23] = dash
+ hex.Encode(buf[24:], u[10:])
+
+ return string(buf)
+}
+
+// SetVersion sets version bits.
+func (u *UUID) SetVersion(v byte) {
+ u[6] = (u[6] & 0x0f) | (v << 4)
+}
+
+// SetVariant sets variant bits as described in RFC 4122.
+func (u *UUID) SetVariant() {
+ u[8] = (u[8] & 0xbf) | 0x80
+}
+
+// MarshalText implements the encoding.TextMarshaler interface.
+// The encoding is the same as returned by String.
+func (u UUID) MarshalText() (text []byte, err error) {
+ text = []byte(u.String())
+ return
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface.
+// Following formats are supported:
+// "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
+// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
+// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
+func (u *UUID) UnmarshalText(text []byte) (err error) {
+ if len(text) < 32 {
+ err = fmt.Errorf("uuid: UUID string too short: %s", text)
+ return
+ }
+
+ t := text[:]
+
+ if bytes.Equal(t[:9], urnPrefix) {
+ t = t[9:]
+ } else if t[0] == '{' {
+ t = t[1:]
+ }
+
+ b := u[:]
+
+ for _, byteGroup := range byteGroups {
+ if t[0] == '-' {
+ t = t[1:]
+ }
+
+ if len(t) < byteGroup {
+ err = fmt.Errorf("uuid: UUID string too short: %s", text)
+ return
+ }
+
+ _, err = hex.Decode(b[:byteGroup/2], t[:byteGroup])
+
+ if err != nil {
+ return
+ }
+
+ t = t[byteGroup:]
+ b = b[byteGroup/2:]
+ }
+
+ return
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface.
+func (u UUID) MarshalBinary() (data []byte, err error) {
+ data = u.Bytes()
+ return
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
+// It will return error if the slice isn't 16 bytes long.
+func (u *UUID) UnmarshalBinary(data []byte) (err error) {
+ if len(data) != 16 {
+ err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data))
+ return
+ }
+ copy(u[:], data)
+
+ return
+}
+
+// Value implements the driver.Valuer interface.
+func (u UUID) Value() (driver.Value, error) {
+ return u.String(), nil
+}
+
+// Scan implements the sql.Scanner interface.
+// A 16-byte slice is handled by UnmarshalBinary, while
+// a longer byte slice or a string is handled by UnmarshalText.
+func (u *UUID) Scan(src interface{}) error {
+ switch src := src.(type) {
+ case []byte:
+ if len(src) == 16 {
+ return u.UnmarshalBinary(src)
+ }
+ return u.UnmarshalText(src)
+
+ case string:
+ return u.UnmarshalText([]byte(src))
+ }
+
+ return fmt.Errorf("uuid: cannot convert %T to UUID", src)
+}
+
+// FromBytes returns UUID converted from raw byte slice input.
+// It will return error if the slice isn't 16 bytes long.
+func FromBytes(input []byte) (u UUID, err error) {
+ err = u.UnmarshalBinary(input)
+ return
+}
+
+// FromBytesOrNil returns UUID converted from raw byte slice input.
+// Same behavior as FromBytes, but returns a Nil UUID on error.
+func FromBytesOrNil(input []byte) UUID {
+ uuid, err := FromBytes(input)
+ if err != nil {
+ return Nil
+ }
+ return uuid
+}
+
+// FromString returns UUID parsed from string input.
+// Input is expected in a form accepted by UnmarshalText.
+func FromString(input string) (u UUID, err error) {
+ err = u.UnmarshalText([]byte(input))
+ return
+}
+
+// FromStringOrNil returns UUID parsed from string input.
+// Same behavior as FromString, but returns a Nil UUID on error.
+func FromStringOrNil(input string) UUID {
+ uuid, err := FromString(input)
+ if err != nil {
+ return Nil
+ }
+ return uuid
+}
+
+// Returns UUID v1/v2 storage state.
+// Returns epoch timestamp, clock sequence, and hardware address.
+func getStorage() (uint64, uint16, []byte) {
+ storageOnce.Do(initStorage)
+
+ storageMutex.Lock()
+ defer storageMutex.Unlock()
+
+ timeNow := epochFunc()
+ // Clock changed backwards since last UUID generation.
+ // Should increase clock sequence.
+ if timeNow <= lastTime {
+ clockSequence++
+ }
+ lastTime = timeNow
+
+ return timeNow, clockSequence, hardwareAddr[:]
+}
+
+// NewV1 returns UUID based on current timestamp and MAC address.
+func NewV1() UUID {
+ u := UUID{}
+
+ timeNow, clockSeq, hardwareAddr := getStorage()
+
+ binary.BigEndian.PutUint32(u[0:], uint32(timeNow))
+ binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
+ binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
+ binary.BigEndian.PutUint16(u[8:], clockSeq)
+
+ copy(u[10:], hardwareAddr)
+
+ u.SetVersion(1)
+ u.SetVariant()
+
+ return u
+}
+
+// NewV2 returns DCE Security UUID based on POSIX UID/GID.
+func NewV2(domain byte) UUID {
+ u := UUID{}
+
+ timeNow, clockSeq, hardwareAddr := getStorage()
+
+ switch domain {
+ case DomainPerson:
+ binary.BigEndian.PutUint32(u[0:], posixUID)
+ case DomainGroup:
+ binary.BigEndian.PutUint32(u[0:], posixGID)
+ }
+
+ binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
+ binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
+ binary.BigEndian.PutUint16(u[8:], clockSeq)
+ u[9] = domain
+
+ copy(u[10:], hardwareAddr)
+
+ u.SetVersion(2)
+ u.SetVariant()
+
+ return u
+}
+
+// NewV3 returns UUID based on MD5 hash of namespace UUID and name.
+func NewV3(ns UUID, name string) UUID {
+ u := newFromHash(md5.New(), ns, name)
+ u.SetVersion(3)
+ u.SetVariant()
+
+ return u
+}
+
+// NewV4 returns random generated UUID.
+func NewV4() UUID {
+ u := UUID{}
+ safeRandom(u[:])
+ u.SetVersion(4)
+ u.SetVariant()
+
+ return u
+}
+
+// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
+func NewV5(ns UUID, name string) UUID {
+ u := newFromHash(sha1.New(), ns, name)
+ u.SetVersion(5)
+ u.SetVariant()
+
+ return u
+}
+
+// Returns UUID based on hashing of namespace UUID and name.
+func newFromHash(h hash.Hash, ns UUID, name string) UUID {
+ u := UUID{}
+ h.Write(ns[:])
+ h.Write([]byte(name))
+ copy(u[:], h.Sum(nil))
+
+ return u
+}
--- /dev/null
+MIT License
+
+Copyright (c) 2017 Sean Chittenden
+Copyright (c) 2016 Alex Dadgar
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+=====
+
+Bits of Go-lang's `once.Do()` were cribbed and reused here, too.
+
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- /dev/null
+# `seed` - Quickly Seed Go's Random Number Generator
+
+Boiler-plate to securely [seed](https://en.wikipedia.org/wiki/Random_seed) Go's
+random number generator (if possible). This library isn't anything fancy, it's
+just a canonical way of seeding Go's random number generator. Cribbed from
+[`Nomad`](https://github.com/hashicorp/nomad/commit/f89a993ec6b91636a3384dd568898245fbc273a1)
+before it was moved into
+[`Consul`](https://github.com/hashicorp/consul/commit/d695bcaae6e31ee307c11fdf55bb0bf46ea9fcf4)
+and made into a helper function, and now further modularized to be a super
+lightweight and reusable library.
+
+Time is better than
+[Go's default seed of `1`](https://golang.org/pkg/math/rand/#Seed), but friends
+don't let friends use time as a seed to a random number generator. Use
+`seed.MustInit()` instead.
+
+`seed.Init()` is an idempotent and reentrant call that will return an error if
+it can't seed the value the first time it is called. `Init()` is reentrant.
+
+`seed.MustInit()` is idempotent and reentrant call that will `panic()` if it
+can't seed the value the first time it is called. `MustInit()` is reentrant.
+
+## Usage
+
+```
+package mypackage
+
+import (
+ "github.com/sean-/seed"
+)
+
+// MustInit will panic() if it is unable to set a high-entropy random seed:
+func init() {
+ seed.MustInit()
+}
+
+// Or if you want to not panic() and can actually handle this error:
+func init() {
+ if secure, err := !seed.Init(); !secure {
+ // Handle the error
+ //panic(fmt.Sprintf("Unable to securely seed Go's RNG: %v", err))
+ }
+}
+```
--- /dev/null
+package seed
+
+import (
+ crand "crypto/rand"
+ "fmt"
+ "math"
+ "math/big"
+ "math/rand"
+ "sync"
+ "sync/atomic"
+ "time"
+)
+
+var (
+ m sync.Mutex
+ secure int32
+ seeded int32
+)
+
+func cryptoSeed() error {
+ defer atomic.StoreInt32(&seeded, 1)
+
+ var err error
+ var n *big.Int
+ n, err = crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
+ if err != nil {
+ rand.Seed(time.Now().UTC().UnixNano())
+ return err
+ }
+ rand.Seed(n.Int64())
+ atomic.StoreInt32(&secure, 1)
+ return nil
+}
+
+// Init provides best-effort seeding (which is better than running with Go's
+// default seed of 1). If `/dev/urandom` is available, Init() will seed Go's
+// runtime with entropy from `/dev/urandom` and return true because the runtime
+// was securely seeded. If Init() has already initialized the random number or
+// it had failed to securely initialize the random number generation, Init()
+// will return false. See MustInit().
+func Init() (seededSecurely bool, err error) {
+ if atomic.LoadInt32(&seeded) == 1 {
+ return false, nil
+ }
+
+ // Slow-path
+ m.Lock()
+ defer m.Unlock()
+
+ if err := cryptoSeed(); err != nil {
+ return false, err
+ }
+
+ return true, nil
+}
+
+// MustInit provides guaranteed secure seeding. If `/dev/urandom` is not
+// available, MustInit will panic() with an error indicating why reading from
+// `/dev/urandom` failed. MustInit() will upgrade the seed if for some reason a
+// call to Init() failed in the past.
+func MustInit() {
+ if atomic.LoadInt32(&secure) == 1 {
+ return
+ }
+
+ // Slow-path
+ m.Lock()
+ defer m.Unlock()
+
+ if err := cryptoSeed(); err != nil {
+ panic(fmt.Sprintf("Unable to seed the random number generator: %v", err))
+ }
+}
+
+// Secure returns true if a cryptographically secure seed was used to
+// initialize rand.
+func Secure() bool {
+ return atomic.LoadInt32(&secure) == 1
+}
+
+// Seeded returns true if Init has seeded the random number generator.
+func Seeded() bool {
+ return atomic.LoadInt32(&seeded) == 1
+}
--- /dev/null
+Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell
+
+Please consider promoting this project if you find it useful.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software,
+and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
+OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--- /dev/null
+/*
+* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
+* THIS FILE MUST NOT BE EDITED BY HAND
+*/
+
+package assert
+
+import (
+
+ http "net/http"
+ url "net/url"
+ time "time"
+)
+
+
+// Condition uses a Comparison to assert a complex condition.
+func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool {
+ return Condition(a.t, comp, msgAndArgs...)
+}
+
+
+// Contains asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// a.Contains("Hello World", "World", "But 'Hello World' does contain 'World'")
+// a.Contains(["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'")
+// a.Contains({"Hello": "World"}, "Hello", "But {'Hello': 'World'} does contain 'Hello'")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
+ return Contains(a.t, s, contains, msgAndArgs...)
+}
+
+
+// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// a.Empty(obj)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
+ return Empty(a.t, object, msgAndArgs...)
+}
+
+
+// Equal asserts that two objects are equal.
+//
+// a.Equal(123, 123, "123 and 123 should be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ return Equal(a.t, expected, actual, msgAndArgs...)
+}
+
+
+// EqualError asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// if assert.Error(t, err, "An error was expected") {
+// assert.Equal(t, err, expectedError)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool {
+ return EqualError(a.t, theError, errString, msgAndArgs...)
+}
+
+
+// EqualValues asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// a.EqualValues(uint32(123), int32(123), "123 and 123 should be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ return EqualValues(a.t, expected, actual, msgAndArgs...)
+}
+
+
+// Error asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.Error(err, "An error was expected") {
+// assert.Equal(t, err, expectedError)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool {
+ return Error(a.t, err, msgAndArgs...)
+}
+
+
+// Exactly asserts that two objects are equal is value and type.
+//
+// a.Exactly(int32(123), int64(123), "123 and 123 should NOT be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ return Exactly(a.t, expected, actual, msgAndArgs...)
+}
+
+
+// Fail reports a failure through
+func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool {
+ return Fail(a.t, failureMessage, msgAndArgs...)
+}
+
+
+// FailNow fails test
+func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool {
+ return FailNow(a.t, failureMessage, msgAndArgs...)
+}
+
+
+// False asserts that the specified value is false.
+//
+// a.False(myBool, "myBool should be false")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool {
+ return False(a.t, value, msgAndArgs...)
+}
+
+
+// HTTPBodyContains asserts that a specified handler returns a
+// body that contains a string.
+//
+// a.HTTPBodyContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool {
+ return HTTPBodyContains(a.t, handler, method, url, values, str)
+}
+
+
+// HTTPBodyNotContains asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// a.HTTPBodyNotContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool {
+ return HTTPBodyNotContains(a.t, handler, method, url, values, str)
+}
+
+
+// HTTPError asserts that a specified handler returns an error status code.
+//
+// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values) bool {
+ return HTTPError(a.t, handler, method, url, values)
+}
+
+
+// HTTPRedirect asserts that a specified handler returns a redirect status code.
+//
+// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values) bool {
+ return HTTPRedirect(a.t, handler, method, url, values)
+}
+
+
+// HTTPSuccess asserts that a specified handler returns a success status code.
+//
+// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values) bool {
+ return HTTPSuccess(a.t, handler, method, url, values)
+}
+
+
+// Implements asserts that an object is implemented by the specified interface.
+//
+// a.Implements((*MyInterface)(nil), new(MyObject), "MyObject")
+func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+ return Implements(a.t, interfaceObject, object, msgAndArgs...)
+}
+
+
+// InDelta asserts that the two numerals are within delta of each other.
+//
+// a.InDelta(math.Pi, (22 / 7.0), 0.01)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ return InDelta(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+
+// InDeltaSlice is the same as InDelta, except it compares two slices.
+func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+
+// InEpsilon asserts that expected and actual have a relative error less than epsilon
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...)
+}
+
+
+// InEpsilonSlice is the same as InEpsilon, except it compares two slices.
+func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ return InEpsilonSlice(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+
+// IsType asserts that the specified objects are of the same type.
+func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+ return IsType(a.t, expectedType, object, msgAndArgs...)
+}
+
+
+// JSONEq asserts that two JSON strings are equivalent.
+//
+// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool {
+ return JSONEq(a.t, expected, actual, msgAndArgs...)
+}
+
+
+// Len asserts that the specified object has specific length.
+// Len also fails if the object has a type that len() not accept.
+//
+// a.Len(mySlice, 3, "The size of slice is not 3")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool {
+ return Len(a.t, object, length, msgAndArgs...)
+}
+
+
+// Nil asserts that the specified object is nil.
+//
+// a.Nil(err, "err should be nothing")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool {
+ return Nil(a.t, object, msgAndArgs...)
+}
+
+
+// NoError asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.NoError(err) {
+// assert.Equal(t, actualObj, expectedObj)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool {
+ return NoError(a.t, err, msgAndArgs...)
+}
+
+
+// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// a.NotContains("Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
+// a.NotContains(["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'")
+// a.NotContains({"Hello": "World"}, "Earth", "But {'Hello': 'World'} does NOT contain 'Earth'")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
+ return NotContains(a.t, s, contains, msgAndArgs...)
+}
+
+
+// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if a.NotEmpty(obj) {
+// assert.Equal(t, "two", obj[1])
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool {
+ return NotEmpty(a.t, object, msgAndArgs...)
+}
+
+
+// NotEqual asserts that the specified values are NOT equal.
+//
+// a.NotEqual(obj1, obj2, "two objects shouldn't be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ return NotEqual(a.t, expected, actual, msgAndArgs...)
+}
+
+
+// NotNil asserts that the specified object is not nil.
+//
+// a.NotNil(err, "err should be something")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool {
+ return NotNil(a.t, object, msgAndArgs...)
+}
+
+
+// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// a.NotPanics(func(){
+// RemainCalm()
+// }, "Calling RemainCalm() should NOT panic")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ return NotPanics(a.t, f, msgAndArgs...)
+}
+
+
+// NotRegexp asserts that a specified regexp does not match a string.
+//
+// a.NotRegexp(regexp.MustCompile("starts"), "it's starting")
+// a.NotRegexp("^start", "it's not starting")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
+ return NotRegexp(a.t, rx, str, msgAndArgs...)
+}
+
+
+// NotZero asserts that i is not the zero value for its type and returns the truth.
+func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool {
+ return NotZero(a.t, i, msgAndArgs...)
+}
+
+
+// Panics asserts that the code inside the specified PanicTestFunc panics.
+//
+// a.Panics(func(){
+// GoCrazy()
+// }, "Calling GoCrazy() should panic")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ return Panics(a.t, f, msgAndArgs...)
+}
+
+
+// Regexp asserts that a specified regexp matches a string.
+//
+// a.Regexp(regexp.MustCompile("start"), "it's starting")
+// a.Regexp("start...$", "it's not starting")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
+ return Regexp(a.t, rx, str, msgAndArgs...)
+}
+
+
+// True asserts that the specified value is true.
+//
+// a.True(myBool, "myBool should be true")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool {
+ return True(a.t, value, msgAndArgs...)
+}
+
+
+// WithinDuration asserts that the two times are within duration delta of each other.
+//
+// a.WithinDuration(time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
+ return WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+
+// Zero asserts that i is the zero value for its type and returns the truth.
+func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool {
+ return Zero(a.t, i, msgAndArgs...)
+}
--- /dev/null
+{{.CommentWithoutT "a"}}
+func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool {
+ return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}})
+}
--- /dev/null
+package assert
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "math"
+ "reflect"
+ "regexp"
+ "runtime"
+ "strings"
+ "time"
+ "unicode"
+ "unicode/utf8"
+
+ "github.com/davecgh/go-spew/spew"
+ "github.com/pmezard/go-difflib/difflib"
+)
+
+// TestingT is an interface wrapper around *testing.T
+type TestingT interface {
+ Errorf(format string, args ...interface{})
+}
+
+// Comparison a custom function that returns true on success and false on failure
+type Comparison func() (success bool)
+
+/*
+ Helper functions
+*/
+
+// ObjectsAreEqual determines if two objects are considered equal.
+//
+// This function does no assertion of any kind.
+func ObjectsAreEqual(expected, actual interface{}) bool {
+
+ if expected == nil || actual == nil {
+ return expected == actual
+ }
+
+ return reflect.DeepEqual(expected, actual)
+
+}
+
+// ObjectsAreEqualValues gets whether two objects are equal, or if their
+// values are equal.
+func ObjectsAreEqualValues(expected, actual interface{}) bool {
+ if ObjectsAreEqual(expected, actual) {
+ return true
+ }
+
+ actualType := reflect.TypeOf(actual)
+ if actualType == nil {
+ return false
+ }
+ expectedValue := reflect.ValueOf(expected)
+ if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
+ // Attempt comparison after type conversion
+ return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual)
+ }
+
+ return false
+}
+
+/* CallerInfo is necessary because the assert functions use the testing object
+internally, causing it to print the file:line of the assert method, rather than where
+the problem actually occured in calling code.*/
+
+// CallerInfo returns an array of strings containing the file and line number
+// of each stack frame leading from the current test to the assert call that
+// failed.
+func CallerInfo() []string {
+
+ pc := uintptr(0)
+ file := ""
+ line := 0
+ ok := false
+ name := ""
+
+ callers := []string{}
+ for i := 0; ; i++ {
+ pc, file, line, ok = runtime.Caller(i)
+ if !ok {
+ return nil
+ }
+
+ // This is a huge edge case, but it will panic if this is the case, see #180
+ if file == "<autogenerated>" {
+ break
+ }
+
+ parts := strings.Split(file, "/")
+ dir := parts[len(parts)-2]
+ file = parts[len(parts)-1]
+ if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" {
+ callers = append(callers, fmt.Sprintf("%s:%d", file, line))
+ }
+
+ f := runtime.FuncForPC(pc)
+ if f == nil {
+ break
+ }
+ name = f.Name()
+ // Drop the package
+ segments := strings.Split(name, ".")
+ name = segments[len(segments)-1]
+ if isTest(name, "Test") ||
+ isTest(name, "Benchmark") ||
+ isTest(name, "Example") {
+ break
+ }
+ }
+
+ return callers
+}
+
+// Stolen from the `go test` tool.
+// isTest tells whether name looks like a test (or benchmark, according to prefix).
+// It is a Test (say) if there is a character after Test that is not a lower-case letter.
+// We don't want TesticularCancer.
+func isTest(name, prefix string) bool {
+ if !strings.HasPrefix(name, prefix) {
+ return false
+ }
+ if len(name) == len(prefix) { // "Test" is ok
+ return true
+ }
+ rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
+ return !unicode.IsLower(rune)
+}
+
+// getWhitespaceString returns a string that is long enough to overwrite the default
+// output from the go testing framework.
+func getWhitespaceString() string {
+
+ _, file, line, ok := runtime.Caller(1)
+ if !ok {
+ return ""
+ }
+ parts := strings.Split(file, "/")
+ file = parts[len(parts)-1]
+
+ return strings.Repeat(" ", len(fmt.Sprintf("%s:%d: ", file, line)))
+
+}
+
+func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
+ if len(msgAndArgs) == 0 || msgAndArgs == nil {
+ return ""
+ }
+ if len(msgAndArgs) == 1 {
+ return msgAndArgs[0].(string)
+ }
+ if len(msgAndArgs) > 1 {
+ return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
+ }
+ return ""
+}
+
+// Indents all lines of the message by appending a number of tabs to each line, in an output format compatible with Go's
+// test printing (see inner comment for specifics)
+func indentMessageLines(message string, tabs int) string {
+ outBuf := new(bytes.Buffer)
+
+ for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ {
+ if i != 0 {
+ outBuf.WriteRune('\n')
+ }
+ for ii := 0; ii < tabs; ii++ {
+ outBuf.WriteRune('\t')
+ // Bizarrely, all lines except the first need one fewer tabs prepended, so deliberately advance the counter
+ // by 1 prematurely.
+ if ii == 0 && i > 0 {
+ ii++
+ }
+ }
+ outBuf.WriteString(scanner.Text())
+ }
+
+ return outBuf.String()
+}
+
+type failNower interface {
+ FailNow()
+}
+
+// FailNow fails test
+func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
+ Fail(t, failureMessage, msgAndArgs...)
+
+ // We cannot extend TestingT with FailNow() and
+ // maintain backwards compatibility, so we fallback
+ // to panicking when FailNow is not available in
+ // TestingT.
+ // See issue #263
+
+ if t, ok := t.(failNower); ok {
+ t.FailNow()
+ } else {
+ panic("test failed and t is missing `FailNow()`")
+ }
+ return false
+}
+
+// Fail reports a failure through
+func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
+
+ message := messageFromMsgAndArgs(msgAndArgs...)
+
+ errorTrace := strings.Join(CallerInfo(), "\n\r\t\t\t")
+ if len(message) > 0 {
+ t.Errorf("\r%s\r\tError Trace:\t%s\n"+
+ "\r\tError:%s\n"+
+ "\r\tMessages:\t%s\n\r",
+ getWhitespaceString(),
+ errorTrace,
+ indentMessageLines(failureMessage, 2),
+ message)
+ } else {
+ t.Errorf("\r%s\r\tError Trace:\t%s\n"+
+ "\r\tError:%s\n\r",
+ getWhitespaceString(),
+ errorTrace,
+ indentMessageLines(failureMessage, 2))
+ }
+
+ return false
+}
+
+// Implements asserts that an object is implemented by the specified interface.
+//
+// assert.Implements(t, (*MyInterface)(nil), new(MyObject), "MyObject")
+func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+
+ interfaceType := reflect.TypeOf(interfaceObject).Elem()
+
+ if !reflect.TypeOf(object).Implements(interfaceType) {
+ return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// IsType asserts that the specified objects are of the same type.
+func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+
+ if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) {
+ return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...)
+ }
+
+ return true
+}
+
+// Equal asserts that two objects are equal.
+//
+// assert.Equal(t, 123, 123, "123 and 123 should be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+
+ if !ObjectsAreEqual(expected, actual) {
+ diff := diff(expected, actual)
+ return Fail(t, fmt.Sprintf("Not equal: %#v (expected)\n"+
+ " != %#v (actual)%s", expected, actual, diff), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// EqualValues asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// assert.EqualValues(t, uint32(123), int32(123), "123 and 123 should be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+
+ if !ObjectsAreEqualValues(expected, actual) {
+ return Fail(t, fmt.Sprintf("Not equal: %#v (expected)\n"+
+ " != %#v (actual)", expected, actual), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// Exactly asserts that two objects are equal is value and type.
+//
+// assert.Exactly(t, int32(123), int64(123), "123 and 123 should NOT be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+
+ aType := reflect.TypeOf(expected)
+ bType := reflect.TypeOf(actual)
+
+ if aType != bType {
+ return Fail(t, fmt.Sprintf("Types expected to match exactly\n\r\t%v != %v", aType, bType), msgAndArgs...)
+ }
+
+ return Equal(t, expected, actual, msgAndArgs...)
+
+}
+
+// NotNil asserts that the specified object is not nil.
+//
+// assert.NotNil(t, err, "err should be something")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ if !isNil(object) {
+ return true
+ }
+ return Fail(t, "Expected value not to be nil.", msgAndArgs...)
+}
+
+// isNil checks if a specified object is nil or not, without Failing.
+func isNil(object interface{}) bool {
+ if object == nil {
+ return true
+ }
+
+ value := reflect.ValueOf(object)
+ kind := value.Kind()
+ if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() {
+ return true
+ }
+
+ return false
+}
+
+// Nil asserts that the specified object is nil.
+//
+// assert.Nil(t, err, "err should be nothing")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ if isNil(object) {
+ return true
+ }
+ return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
+}
+
+var numericZeros = []interface{}{
+ int(0),
+ int8(0),
+ int16(0),
+ int32(0),
+ int64(0),
+ uint(0),
+ uint8(0),
+ uint16(0),
+ uint32(0),
+ uint64(0),
+ float32(0),
+ float64(0),
+}
+
+// isEmpty gets whether the specified object is considered empty or not.
+func isEmpty(object interface{}) bool {
+
+ if object == nil {
+ return true
+ } else if object == "" {
+ return true
+ } else if object == false {
+ return true
+ }
+
+ for _, v := range numericZeros {
+ if object == v {
+ return true
+ }
+ }
+
+ objValue := reflect.ValueOf(object)
+
+ switch objValue.Kind() {
+ case reflect.Map:
+ fallthrough
+ case reflect.Slice, reflect.Chan:
+ {
+ return (objValue.Len() == 0)
+ }
+ case reflect.Struct:
+ switch object.(type) {
+ case time.Time:
+ return object.(time.Time).IsZero()
+ }
+ case reflect.Ptr:
+ {
+ if objValue.IsNil() {
+ return true
+ }
+ switch object.(type) {
+ case *time.Time:
+ return object.(*time.Time).IsZero()
+ default:
+ return false
+ }
+ }
+ }
+ return false
+}
+
+// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// assert.Empty(t, obj)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+
+ pass := isEmpty(object)
+ if !pass {
+ Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...)
+ }
+
+ return pass
+
+}
+
+// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if assert.NotEmpty(t, obj) {
+// assert.Equal(t, "two", obj[1])
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+
+ pass := !isEmpty(object)
+ if !pass {
+ Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...)
+ }
+
+ return pass
+
+}
+
+// getLen try to get length of object.
+// return (false, 0) if impossible.
+func getLen(x interface{}) (ok bool, length int) {
+ v := reflect.ValueOf(x)
+ defer func() {
+ if e := recover(); e != nil {
+ ok = false
+ }
+ }()
+ return true, v.Len()
+}
+
+// Len asserts that the specified object has specific length.
+// Len also fails if the object has a type that len() not accept.
+//
+// assert.Len(t, mySlice, 3, "The size of slice is not 3")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool {
+ ok, l := getLen(object)
+ if !ok {
+ return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...)
+ }
+
+ if l != length {
+ return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...)
+ }
+ return true
+}
+
+// True asserts that the specified value is true.
+//
+// assert.True(t, myBool, "myBool should be true")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
+
+ if value != true {
+ return Fail(t, "Should be true", msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// False asserts that the specified value is false.
+//
+// assert.False(t, myBool, "myBool should be false")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
+
+ if value != false {
+ return Fail(t, "Should be false", msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// NotEqual asserts that the specified values are NOT equal.
+//
+// assert.NotEqual(t, obj1, obj2, "two objects shouldn't be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+
+ if ObjectsAreEqual(expected, actual) {
+ return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// containsElement try loop over the list check if the list includes the element.
+// return (false, false) if impossible.
+// return (true, false) if element was not found.
+// return (true, true) if element was found.
+func includeElement(list interface{}, element interface{}) (ok, found bool) {
+
+ listValue := reflect.ValueOf(list)
+ elementValue := reflect.ValueOf(element)
+ defer func() {
+ if e := recover(); e != nil {
+ ok = false
+ found = false
+ }
+ }()
+
+ if reflect.TypeOf(list).Kind() == reflect.String {
+ return true, strings.Contains(listValue.String(), elementValue.String())
+ }
+
+ if reflect.TypeOf(list).Kind() == reflect.Map {
+ mapKeys := listValue.MapKeys()
+ for i := 0; i < len(mapKeys); i++ {
+ if ObjectsAreEqual(mapKeys[i].Interface(), element) {
+ return true, true
+ }
+ }
+ return true, false
+ }
+
+ for i := 0; i < listValue.Len(); i++ {
+ if ObjectsAreEqual(listValue.Index(i).Interface(), element) {
+ return true, true
+ }
+ }
+ return true, false
+
+}
+
+// Contains asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// assert.Contains(t, "Hello World", "World", "But 'Hello World' does contain 'World'")
+// assert.Contains(t, ["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'")
+// assert.Contains(t, {"Hello": "World"}, "Hello", "But {'Hello': 'World'} does contain 'Hello'")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
+
+ ok, found := includeElement(s, contains)
+ if !ok {
+ return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...)
+ }
+ if !found {
+ return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// assert.NotContains(t, "Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
+// assert.NotContains(t, ["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'")
+// assert.NotContains(t, {"Hello": "World"}, "Earth", "But {'Hello': 'World'} does NOT contain 'Earth'")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
+
+ ok, found := includeElement(s, contains)
+ if !ok {
+ return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...)
+ }
+ if found {
+ return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// Condition uses a Comparison to assert a complex condition.
+func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
+ result := comp()
+ if !result {
+ Fail(t, "Condition failed!", msgAndArgs...)
+ }
+ return result
+}
+
+// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics
+// methods, and represents a simple func that takes no arguments, and returns nothing.
+type PanicTestFunc func()
+
+// didPanic returns true if the function passed to it panics. Otherwise, it returns false.
+func didPanic(f PanicTestFunc) (bool, interface{}) {
+
+ didPanic := false
+ var message interface{}
+ func() {
+
+ defer func() {
+ if message = recover(); message != nil {
+ didPanic = true
+ }
+ }()
+
+ // call the target function
+ f()
+
+ }()
+
+ return didPanic, message
+
+}
+
+// Panics asserts that the code inside the specified PanicTestFunc panics.
+//
+// assert.Panics(t, func(){
+// GoCrazy()
+// }, "Calling GoCrazy() should panic")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+
+ if funcDidPanic, panicValue := didPanic(f); !funcDidPanic {
+ return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
+ }
+
+ return true
+}
+
+// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// assert.NotPanics(t, func(){
+// RemainCalm()
+// }, "Calling RemainCalm() should NOT panic")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+
+ if funcDidPanic, panicValue := didPanic(f); funcDidPanic {
+ return Fail(t, fmt.Sprintf("func %#v should not panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
+ }
+
+ return true
+}
+
+// WithinDuration asserts that the two times are within duration delta of each other.
+//
+// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
+
+ dt := expected.Sub(actual)
+ if dt < -delta || dt > delta {
+ return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
+ }
+
+ return true
+}
+
+func toFloat(x interface{}) (float64, bool) {
+ var xf float64
+ xok := true
+
+ switch xn := x.(type) {
+ case uint8:
+ xf = float64(xn)
+ case uint16:
+ xf = float64(xn)
+ case uint32:
+ xf = float64(xn)
+ case uint64:
+ xf = float64(xn)
+ case int:
+ xf = float64(xn)
+ case int8:
+ xf = float64(xn)
+ case int16:
+ xf = float64(xn)
+ case int32:
+ xf = float64(xn)
+ case int64:
+ xf = float64(xn)
+ case float32:
+ xf = float64(xn)
+ case float64:
+ xf = float64(xn)
+ default:
+ xok = false
+ }
+
+ return xf, xok
+}
+
+// InDelta asserts that the two numerals are within delta of each other.
+//
+// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+
+ af, aok := toFloat(expected)
+ bf, bok := toFloat(actual)
+
+ if !aok || !bok {
+ return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...)
+ }
+
+ if math.IsNaN(af) {
+ return Fail(t, fmt.Sprintf("Actual must not be NaN"), msgAndArgs...)
+ }
+
+ if math.IsNaN(bf) {
+ return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...)
+ }
+
+ dt := af - bf
+ if dt < -delta || dt > delta {
+ return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
+ }
+
+ return true
+}
+
+// InDeltaSlice is the same as InDelta, except it compares two slices.
+func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ if expected == nil || actual == nil ||
+ reflect.TypeOf(actual).Kind() != reflect.Slice ||
+ reflect.TypeOf(expected).Kind() != reflect.Slice {
+ return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...)
+ }
+
+ actualSlice := reflect.ValueOf(actual)
+ expectedSlice := reflect.ValueOf(expected)
+
+ for i := 0; i < actualSlice.Len(); i++ {
+ result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta)
+ if !result {
+ return result
+ }
+ }
+
+ return true
+}
+
+func calcRelativeError(expected, actual interface{}) (float64, error) {
+ af, aok := toFloat(expected)
+ if !aok {
+ return 0, fmt.Errorf("expected value %q cannot be converted to float", expected)
+ }
+ if af == 0 {
+ return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error")
+ }
+ bf, bok := toFloat(actual)
+ if !bok {
+ return 0, fmt.Errorf("expected value %q cannot be converted to float", actual)
+ }
+
+ return math.Abs(af-bf) / math.Abs(af), nil
+}
+
+// InEpsilon asserts that expected and actual have a relative error less than epsilon
+//
+// Returns whether the assertion was successful (true) or not (false).
+func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ actualEpsilon, err := calcRelativeError(expected, actual)
+ if err != nil {
+ return Fail(t, err.Error(), msgAndArgs...)
+ }
+ if actualEpsilon > epsilon {
+ return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+
+ " < %#v (actual)", actualEpsilon, epsilon), msgAndArgs...)
+ }
+
+ return true
+}
+
+// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
+func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ if expected == nil || actual == nil ||
+ reflect.TypeOf(actual).Kind() != reflect.Slice ||
+ reflect.TypeOf(expected).Kind() != reflect.Slice {
+ return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...)
+ }
+
+ actualSlice := reflect.ValueOf(actual)
+ expectedSlice := reflect.ValueOf(expected)
+
+ for i := 0; i < actualSlice.Len(); i++ {
+ result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon)
+ if !result {
+ return result
+ }
+ }
+
+ return true
+}
+
+/*
+ Errors
+*/
+
+// NoError asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.NoError(t, err) {
+// assert.Equal(t, actualObj, expectedObj)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
+ if err != nil {
+ return Fail(t, fmt.Sprintf("Received unexpected error %q", err), msgAndArgs...)
+ }
+
+ return true
+}
+
+// Error asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.Error(t, err, "An error was expected") {
+// assert.Equal(t, err, expectedError)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
+
+ message := messageFromMsgAndArgs(msgAndArgs...)
+ if err == nil {
+ return Fail(t, "An error is expected but got nil. %s", message)
+ }
+
+ return true
+}
+
+// EqualError asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// if assert.Error(t, err, "An error was expected") {
+// assert.Equal(t, err, expectedError)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool {
+
+ message := messageFromMsgAndArgs(msgAndArgs...)
+ if !NotNil(t, theError, "An error is expected but got nil. %s", message) {
+ return false
+ }
+ s := "An error with value \"%s\" is expected but got \"%s\". %s"
+ return Equal(t, errString, theError.Error(),
+ s, errString, theError.Error(), message)
+}
+
+// matchRegexp return true if a specified regexp matches a string.
+func matchRegexp(rx interface{}, str interface{}) bool {
+
+ var r *regexp.Regexp
+ if rr, ok := rx.(*regexp.Regexp); ok {
+ r = rr
+ } else {
+ r = regexp.MustCompile(fmt.Sprint(rx))
+ }
+
+ return (r.FindStringIndex(fmt.Sprint(str)) != nil)
+
+}
+
+// Regexp asserts that a specified regexp matches a string.
+//
+// assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
+// assert.Regexp(t, "start...$", "it's not starting")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
+
+ match := matchRegexp(rx, str)
+
+ if !match {
+ Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...)
+ }
+
+ return match
+}
+
+// NotRegexp asserts that a specified regexp does not match a string.
+//
+// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
+// assert.NotRegexp(t, "^start", "it's not starting")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
+ match := matchRegexp(rx, str)
+
+ if match {
+ Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...)
+ }
+
+ return !match
+
+}
+
+// Zero asserts that i is the zero value for its type and returns the truth.
+func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
+ if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
+ return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...)
+ }
+ return true
+}
+
+// NotZero asserts that i is not the zero value for its type and returns the truth.
+func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
+ if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
+ return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...)
+ }
+ return true
+}
+
+// JSONEq asserts that two JSON strings are equivalent.
+//
+// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool {
+ var expectedJSONAsInterface, actualJSONAsInterface interface{}
+
+ if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil {
+ return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...)
+ }
+
+ if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil {
+ return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...)
+ }
+
+ return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...)
+}
+
+func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) {
+ t := reflect.TypeOf(v)
+ k := t.Kind()
+
+ if k == reflect.Ptr {
+ t = t.Elem()
+ k = t.Kind()
+ }
+ return t, k
+}
+
+// diff returns a diff of both values as long as both are of the same type and
+// are a struct, map, slice or array. Otherwise it returns an empty string.
+func diff(expected interface{}, actual interface{}) string {
+ if expected == nil || actual == nil {
+ return ""
+ }
+
+ et, ek := typeAndKind(expected)
+ at, _ := typeAndKind(actual)
+
+ if et != at {
+ return ""
+ }
+
+ if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array {
+ return ""
+ }
+
+ spew.Config.SortKeys = true
+ e := spew.Sdump(expected)
+ a := spew.Sdump(actual)
+
+ diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
+ A: difflib.SplitLines(e),
+ B: difflib.SplitLines(a),
+ FromFile: "Expected",
+ FromDate: "",
+ ToFile: "Actual",
+ ToDate: "",
+ Context: 1,
+ })
+
+ return "\n\nDiff:\n" + diff
+}
--- /dev/null
+// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system.
+//
+// Example Usage
+//
+// The following is a complete example using assert in a standard test function:
+// import (
+// "testing"
+// "github.com/stretchr/testify/assert"
+// )
+//
+// func TestSomething(t *testing.T) {
+//
+// var a string = "Hello"
+// var b string = "Hello"
+//
+// assert.Equal(t, a, b, "The two words should be the same.")
+//
+// }
+//
+// if you assert many times, use the format below:
+//
+// import (
+// "testing"
+// "github.com/stretchr/testify/assert"
+// )
+//
+// func TestSomething(t *testing.T) {
+// assert := assert.New(t)
+//
+// var a string = "Hello"
+// var b string = "Hello"
+//
+// assert.Equal(a, b, "The two words should be the same.")
+// }
+//
+// Assertions
+//
+// Assertions allow you to easily write test code, and are global funcs in the `assert` package.
+// All assertion functions take, as the first argument, the `*testing.T` object provided by the
+// testing framework. This allows the assertion funcs to write the failings and other details to
+// the correct place.
+//
+// Every assertion function also takes an optional string message as the final argument,
+// allowing custom error messages to be appended to the message the assertion method outputs.
+package assert
--- /dev/null
+package assert
+
+import (
+ "errors"
+)
+
+// AnError is an error instance useful for testing. If the code does not care
+// about error specifics, and only needs to return the error for example, this
+// error should be used to make the test code more readable.
+var AnError = errors.New("assert.AnError general error for testing")
--- /dev/null
+package assert
+
+// Assertions provides assertion methods around the
+// TestingT interface.
+type Assertions struct {
+ t TestingT
+}
+
+// New makes a new Assertions object for the specified TestingT.
+func New(t TestingT) *Assertions {
+ return &Assertions{
+ t: t,
+ }
+}
+
+//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_forward.go.tmpl
--- /dev/null
+package assert
+
+import (
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "strings"
+)
+
+// httpCode is a helper that returns HTTP code of the response. It returns -1
+// if building a new request fails.
+func httpCode(handler http.HandlerFunc, method, url string, values url.Values) int {
+ w := httptest.NewRecorder()
+ req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
+ if err != nil {
+ return -1
+ }
+ handler(w, req)
+ return w.Code
+}
+
+// HTTPSuccess asserts that a specified handler returns a success status code.
+//
+// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
+ code := httpCode(handler, method, url, values)
+ if code == -1 {
+ return false
+ }
+ return code >= http.StatusOK && code <= http.StatusPartialContent
+}
+
+// HTTPRedirect asserts that a specified handler returns a redirect status code.
+//
+// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
+ code := httpCode(handler, method, url, values)
+ if code == -1 {
+ return false
+ }
+ return code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
+}
+
+// HTTPError asserts that a specified handler returns an error status code.
+//
+// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
+ code := httpCode(handler, method, url, values)
+ if code == -1 {
+ return false
+ }
+ return code >= http.StatusBadRequest
+}
+
+// HTTPBody is a helper that returns HTTP body of the response. It returns
+// empty string if building a new request fails.
+func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
+ w := httptest.NewRecorder()
+ req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
+ if err != nil {
+ return ""
+ }
+ handler(w, req)
+ return w.Body.String()
+}
+
+// HTTPBodyContains asserts that a specified handler returns a
+// body that contains a string.
+//
+// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
+ body := HTTPBody(handler, method, url, values)
+
+ contains := strings.Contains(body, fmt.Sprint(str))
+ if !contains {
+ Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
+ }
+
+ return contains
+}
+
+// HTTPBodyNotContains asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
+ body := HTTPBody(handler, method, url, values)
+
+ contains := strings.Contains(body, fmt.Sprint(str))
+ if contains {
+ Fail(t, "Expected response body for %s to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)
+ }
+
+ return !contains
+}
--- /dev/null
+// Package require implements the same assertions as the `assert` package but
+// stops test execution when a test fails.
+//
+// Example Usage
+//
+// The following is a complete example using require in a standard test function:
+// import (
+// "testing"
+// "github.com/stretchr/testify/require"
+// )
+//
+// func TestSomething(t *testing.T) {
+//
+// var a string = "Hello"
+// var b string = "Hello"
+//
+// require.Equal(t, a, b, "The two words should be the same.")
+//
+// }
+//
+// Assertions
+//
+// The `require` package have same global functions as in the `assert` package,
+// but instead of returning a boolean result they call `t.FailNow()`.
+//
+// Every assertion function also takes an optional string message as the final argument,
+// allowing custom error messages to be appended to the message the assertion method outputs.
+package require
--- /dev/null
+package require
+
+// Assertions provides assertion methods around the
+// TestingT interface.
+type Assertions struct {
+ t TestingT
+}
+
+// New makes a new Assertions object for the specified TestingT.
+func New(t TestingT) *Assertions {
+ return &Assertions{
+ t: t,
+ }
+}
+
+//go:generate go run ../_codegen/main.go -output-package=require -template=require_forward.go.tmpl
--- /dev/null
+/*
+* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
+* THIS FILE MUST NOT BE EDITED BY HAND
+*/
+
+package require
+
+import (
+
+ assert "github.com/stretchr/testify/assert"
+ http "net/http"
+ url "net/url"
+ time "time"
+)
+
+
+// Condition uses a Comparison to assert a complex condition.
+func Condition(t TestingT, comp assert.Comparison, msgAndArgs ...interface{}) {
+ if !assert.Condition(t, comp, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// Contains asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// assert.Contains(t, "Hello World", "World", "But 'Hello World' does contain 'World'")
+// assert.Contains(t, ["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'")
+// assert.Contains(t, {"Hello": "World"}, "Hello", "But {'Hello': 'World'} does contain 'Hello'")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Contains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) {
+ if !assert.Contains(t, s, contains, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// assert.Empty(t, obj)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) {
+ if !assert.Empty(t, object, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// Equal asserts that two objects are equal.
+//
+// assert.Equal(t, 123, 123, "123 and 123 should be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Equal(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if !assert.Equal(t, expected, actual, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// EqualError asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// if assert.Error(t, err, "An error was expected") {
+// assert.Equal(t, err, expectedError)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) {
+ if !assert.EqualError(t, theError, errString, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// EqualValues asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// assert.EqualValues(t, uint32(123), int32(123), "123 and 123 should be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if !assert.EqualValues(t, expected, actual, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// Error asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.Error(t, err, "An error was expected") {
+// assert.Equal(t, err, expectedError)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Error(t TestingT, err error, msgAndArgs ...interface{}) {
+ if !assert.Error(t, err, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// Exactly asserts that two objects are equal is value and type.
+//
+// assert.Exactly(t, int32(123), int64(123), "123 and 123 should NOT be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Exactly(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if !assert.Exactly(t, expected, actual, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// Fail reports a failure through
+func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) {
+ if !assert.Fail(t, failureMessage, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// FailNow fails test
+func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) {
+ if !assert.FailNow(t, failureMessage, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// False asserts that the specified value is false.
+//
+// assert.False(t, myBool, "myBool should be false")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func False(t TestingT, value bool, msgAndArgs ...interface{}) {
+ if !assert.False(t, value, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// HTTPBodyContains asserts that a specified handler returns a
+// body that contains a string.
+//
+// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) {
+ if !assert.HTTPBodyContains(t, handler, method, url, values, str) {
+ t.FailNow()
+ }
+}
+
+
+// HTTPBodyNotContains asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) {
+ if !assert.HTTPBodyNotContains(t, handler, method, url, values, str) {
+ t.FailNow()
+ }
+}
+
+
+// HTTPError asserts that a specified handler returns an error status code.
+//
+// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values) {
+ if !assert.HTTPError(t, handler, method, url, values) {
+ t.FailNow()
+ }
+}
+
+
+// HTTPRedirect asserts that a specified handler returns a redirect status code.
+//
+// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values) {
+ if !assert.HTTPRedirect(t, handler, method, url, values) {
+ t.FailNow()
+ }
+}
+
+
+// HTTPSuccess asserts that a specified handler returns a success status code.
+//
+// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values) {
+ if !assert.HTTPSuccess(t, handler, method, url, values) {
+ t.FailNow()
+ }
+}
+
+
+// Implements asserts that an object is implemented by the specified interface.
+//
+// assert.Implements(t, (*MyInterface)(nil), new(MyObject), "MyObject")
+func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) {
+ if !assert.Implements(t, interfaceObject, object, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// InDelta asserts that the two numerals are within delta of each other.
+//
+// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func InDelta(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) {
+ if !assert.InDelta(t, expected, actual, delta, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// InDeltaSlice is the same as InDelta, except it compares two slices.
+func InDeltaSlice(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) {
+ if !assert.InDeltaSlice(t, expected, actual, delta, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// InEpsilon asserts that expected and actual have a relative error less than epsilon
+//
+// Returns whether the assertion was successful (true) or not (false).
+func InEpsilon(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) {
+ if !assert.InEpsilon(t, expected, actual, epsilon, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// InEpsilonSlice is the same as InEpsilon, except it compares two slices.
+func InEpsilonSlice(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) {
+ if !assert.InEpsilonSlice(t, expected, actual, delta, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// IsType asserts that the specified objects are of the same type.
+func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) {
+ if !assert.IsType(t, expectedType, object, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// JSONEq asserts that two JSON strings are equivalent.
+//
+// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) {
+ if !assert.JSONEq(t, expected, actual, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// Len asserts that the specified object has specific length.
+// Len also fails if the object has a type that len() not accept.
+//
+// assert.Len(t, mySlice, 3, "The size of slice is not 3")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) {
+ if !assert.Len(t, object, length, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// Nil asserts that the specified object is nil.
+//
+// assert.Nil(t, err, "err should be nothing")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) {
+ if !assert.Nil(t, object, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// NoError asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.NoError(t, err) {
+// assert.Equal(t, actualObj, expectedObj)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NoError(t TestingT, err error, msgAndArgs ...interface{}) {
+ if !assert.NoError(t, err, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// assert.NotContains(t, "Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
+// assert.NotContains(t, ["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'")
+// assert.NotContains(t, {"Hello": "World"}, "Earth", "But {'Hello': 'World'} does NOT contain 'Earth'")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotContains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) {
+ if !assert.NotContains(t, s, contains, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if assert.NotEmpty(t, obj) {
+// assert.Equal(t, "two", obj[1])
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) {
+ if !assert.NotEmpty(t, object, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// NotEqual asserts that the specified values are NOT equal.
+//
+// assert.NotEqual(t, obj1, obj2, "two objects shouldn't be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotEqual(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if !assert.NotEqual(t, expected, actual, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// NotNil asserts that the specified object is not nil.
+//
+// assert.NotNil(t, err, "err should be something")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) {
+ if !assert.NotNil(t, object, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// assert.NotPanics(t, func(){
+// RemainCalm()
+// }, "Calling RemainCalm() should NOT panic")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotPanics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) {
+ if !assert.NotPanics(t, f, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// NotRegexp asserts that a specified regexp does not match a string.
+//
+// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
+// assert.NotRegexp(t, "^start", "it's not starting")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) {
+ if !assert.NotRegexp(t, rx, str, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// NotZero asserts that i is not the zero value for its type and returns the truth.
+func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) {
+ if !assert.NotZero(t, i, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// Panics asserts that the code inside the specified PanicTestFunc panics.
+//
+// assert.Panics(t, func(){
+// GoCrazy()
+// }, "Calling GoCrazy() should panic")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Panics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) {
+ if !assert.Panics(t, f, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// Regexp asserts that a specified regexp matches a string.
+//
+// assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
+// assert.Regexp(t, "start...$", "it's not starting")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) {
+ if !assert.Regexp(t, rx, str, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// True asserts that the specified value is true.
+//
+// assert.True(t, myBool, "myBool should be true")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func True(t TestingT, value bool, msgAndArgs ...interface{}) {
+ if !assert.True(t, value, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// WithinDuration asserts that the two times are within duration delta of each other.
+//
+// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func WithinDuration(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) {
+ if !assert.WithinDuration(t, expected, actual, delta, msgAndArgs...) {
+ t.FailNow()
+ }
+}
+
+
+// Zero asserts that i is the zero value for its type and returns the truth.
+func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) {
+ if !assert.Zero(t, i, msgAndArgs...) {
+ t.FailNow()
+ }
+}
--- /dev/null
+{{.Comment}}
+func {{.DocInfo.Name}}(t TestingT, {{.Params}}) {
+ if !assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) {
+ t.FailNow()
+ }
+}
--- /dev/null
+/*
+* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
+* THIS FILE MUST NOT BE EDITED BY HAND
+*/
+
+package require
+
+import (
+
+ assert "github.com/stretchr/testify/assert"
+ http "net/http"
+ url "net/url"
+ time "time"
+)
+
+
+// Condition uses a Comparison to assert a complex condition.
+func (a *Assertions) Condition(comp assert.Comparison, msgAndArgs ...interface{}) {
+ Condition(a.t, comp, msgAndArgs...)
+}
+
+
+// Contains asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// a.Contains("Hello World", "World", "But 'Hello World' does contain 'World'")
+// a.Contains(["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'")
+// a.Contains({"Hello": "World"}, "Hello", "But {'Hello': 'World'} does contain 'Hello'")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) {
+ Contains(a.t, s, contains, msgAndArgs...)
+}
+
+
+// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// a.Empty(obj)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) {
+ Empty(a.t, object, msgAndArgs...)
+}
+
+
+// Equal asserts that two objects are equal.
+//
+// a.Equal(123, 123, "123 and 123 should be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ Equal(a.t, expected, actual, msgAndArgs...)
+}
+
+
+// EqualError asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// if assert.Error(t, err, "An error was expected") {
+// assert.Equal(t, err, expectedError)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) {
+ EqualError(a.t, theError, errString, msgAndArgs...)
+}
+
+
+// EqualValues asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// a.EqualValues(uint32(123), int32(123), "123 and 123 should be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ EqualValues(a.t, expected, actual, msgAndArgs...)
+}
+
+
+// Error asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.Error(err, "An error was expected") {
+// assert.Equal(t, err, expectedError)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Error(err error, msgAndArgs ...interface{}) {
+ Error(a.t, err, msgAndArgs...)
+}
+
+
+// Exactly asserts that two objects are equal is value and type.
+//
+// a.Exactly(int32(123), int64(123), "123 and 123 should NOT be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ Exactly(a.t, expected, actual, msgAndArgs...)
+}
+
+
+// Fail reports a failure through
+func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) {
+ Fail(a.t, failureMessage, msgAndArgs...)
+}
+
+
+// FailNow fails test
+func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) {
+ FailNow(a.t, failureMessage, msgAndArgs...)
+}
+
+
+// False asserts that the specified value is false.
+//
+// a.False(myBool, "myBool should be false")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) False(value bool, msgAndArgs ...interface{}) {
+ False(a.t, value, msgAndArgs...)
+}
+
+
+// HTTPBodyContains asserts that a specified handler returns a
+// body that contains a string.
+//
+// a.HTTPBodyContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) {
+ HTTPBodyContains(a.t, handler, method, url, values, str)
+}
+
+
+// HTTPBodyNotContains asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// a.HTTPBodyNotContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) {
+ HTTPBodyNotContains(a.t, handler, method, url, values, str)
+}
+
+
+// HTTPError asserts that a specified handler returns an error status code.
+//
+// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values) {
+ HTTPError(a.t, handler, method, url, values)
+}
+
+
+// HTTPRedirect asserts that a specified handler returns a redirect status code.
+//
+// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values) {
+ HTTPRedirect(a.t, handler, method, url, values)
+}
+
+
+// HTTPSuccess asserts that a specified handler returns a success status code.
+//
+// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values) {
+ HTTPSuccess(a.t, handler, method, url, values)
+}
+
+
+// Implements asserts that an object is implemented by the specified interface.
+//
+// a.Implements((*MyInterface)(nil), new(MyObject), "MyObject")
+func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) {
+ Implements(a.t, interfaceObject, object, msgAndArgs...)
+}
+
+
+// InDelta asserts that the two numerals are within delta of each other.
+//
+// a.InDelta(math.Pi, (22 / 7.0), 0.01)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) {
+ InDelta(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+
+// InDeltaSlice is the same as InDelta, except it compares two slices.
+func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) {
+ InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+
+// InEpsilon asserts that expected and actual have a relative error less than epsilon
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) {
+ InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...)
+}
+
+
+// InEpsilonSlice is the same as InEpsilon, except it compares two slices.
+func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) {
+ InEpsilonSlice(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+
+// IsType asserts that the specified objects are of the same type.
+func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) {
+ IsType(a.t, expectedType, object, msgAndArgs...)
+}
+
+
+// JSONEq asserts that two JSON strings are equivalent.
+//
+// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) {
+ JSONEq(a.t, expected, actual, msgAndArgs...)
+}
+
+
+// Len asserts that the specified object has specific length.
+// Len also fails if the object has a type that len() not accept.
+//
+// a.Len(mySlice, 3, "The size of slice is not 3")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) {
+ Len(a.t, object, length, msgAndArgs...)
+}
+
+
+// Nil asserts that the specified object is nil.
+//
+// a.Nil(err, "err should be nothing")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) {
+ Nil(a.t, object, msgAndArgs...)
+}
+
+
+// NoError asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.NoError(err) {
+// assert.Equal(t, actualObj, expectedObj)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) {
+ NoError(a.t, err, msgAndArgs...)
+}
+
+
+// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// a.NotContains("Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
+// a.NotContains(["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'")
+// a.NotContains({"Hello": "World"}, "Earth", "But {'Hello': 'World'} does NOT contain 'Earth'")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) {
+ NotContains(a.t, s, contains, msgAndArgs...)
+}
+
+
+// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if a.NotEmpty(obj) {
+// assert.Equal(t, "two", obj[1])
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) {
+ NotEmpty(a.t, object, msgAndArgs...)
+}
+
+
+// NotEqual asserts that the specified values are NOT equal.
+//
+// a.NotEqual(obj1, obj2, "two objects shouldn't be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ NotEqual(a.t, expected, actual, msgAndArgs...)
+}
+
+
+// NotNil asserts that the specified object is not nil.
+//
+// a.NotNil(err, "err should be something")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) {
+ NotNil(a.t, object, msgAndArgs...)
+}
+
+
+// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// a.NotPanics(func(){
+// RemainCalm()
+// }, "Calling RemainCalm() should NOT panic")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotPanics(f assert.PanicTestFunc, msgAndArgs ...interface{}) {
+ NotPanics(a.t, f, msgAndArgs...)
+}
+
+
+// NotRegexp asserts that a specified regexp does not match a string.
+//
+// a.NotRegexp(regexp.MustCompile("starts"), "it's starting")
+// a.NotRegexp("^start", "it's not starting")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) {
+ NotRegexp(a.t, rx, str, msgAndArgs...)
+}
+
+
+// NotZero asserts that i is not the zero value for its type and returns the truth.
+func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) {
+ NotZero(a.t, i, msgAndArgs...)
+}
+
+
+// Panics asserts that the code inside the specified PanicTestFunc panics.
+//
+// a.Panics(func(){
+// GoCrazy()
+// }, "Calling GoCrazy() should panic")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interface{}) {
+ Panics(a.t, f, msgAndArgs...)
+}
+
+
+// Regexp asserts that a specified regexp matches a string.
+//
+// a.Regexp(regexp.MustCompile("start"), "it's starting")
+// a.Regexp("start...$", "it's not starting")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) {
+ Regexp(a.t, rx, str, msgAndArgs...)
+}
+
+
+// True asserts that the specified value is true.
+//
+// a.True(myBool, "myBool should be true")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) True(value bool, msgAndArgs ...interface{}) {
+ True(a.t, value, msgAndArgs...)
+}
+
+
+// WithinDuration asserts that the two times are within duration delta of each other.
+//
+// a.WithinDuration(time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) {
+ WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+
+// Zero asserts that i is the zero value for its type and returns the truth.
+func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) {
+ Zero(a.t, i, msgAndArgs...)
+}
--- /dev/null
+{{.CommentWithoutT "a"}}
+func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) {
+ {{.DocInfo.Name}}(a.t, {{.ForwardedParams}})
+}
--- /dev/null
+package require
+
+// TestingT is an interface wrapper around *testing.T
+type TestingT interface {
+ Errorf(format string, args ...interface{})
+ FailNow()
+}
+
+//go:generate go run ../_codegen/main.go -output-package=require -template=require.go.tmpl
--- /dev/null
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- /dev/null
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
--- /dev/null
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package context defines the Context type, which carries deadlines,
+// cancelation signals, and other request-scoped values across API boundaries
+// and between processes.
+//
+// Incoming requests to a server should create a Context, and outgoing calls to
+// servers should accept a Context. The chain of function calls between must
+// propagate the Context, optionally replacing it with a modified copy created
+// using WithDeadline, WithTimeout, WithCancel, or WithValue.
+//
+// Programs that use Contexts should follow these rules to keep interfaces
+// consistent across packages and enable static analysis tools to check context
+// propagation:
+//
+// Do not store Contexts inside a struct type; instead, pass a Context
+// explicitly to each function that needs it. The Context should be the first
+// parameter, typically named ctx:
+//
+// func DoSomething(ctx context.Context, arg Arg) error {
+// // ... use ctx ...
+// }
+//
+// Do not pass a nil Context, even if a function permits it. Pass context.TODO
+// if you are unsure about which Context to use.
+//
+// Use context Values only for request-scoped data that transits processes and
+// APIs, not for passing optional parameters to functions.
+//
+// The same Context may be passed to functions running in different goroutines;
+// Contexts are safe for simultaneous use by multiple goroutines.
+//
+// See http://blog.golang.org/context for example code for a server that uses
+// Contexts.
+package context // import "golang.org/x/net/context"
+
+import (
+ "errors"
+ "fmt"
+ "sync"
+ "time"
+)
+
+// A Context carries a deadline, a cancelation signal, and other values across
+// API boundaries.
+//
+// Context's methods may be called by multiple goroutines simultaneously.
+type Context interface {
+ // Deadline returns the time when work done on behalf of this context
+ // should be canceled. Deadline returns ok==false when no deadline is
+ // set. Successive calls to Deadline return the same results.
+ Deadline() (deadline time.Time, ok bool)
+
+ // Done returns a channel that's closed when work done on behalf of this
+ // context should be canceled. Done may return nil if this context can
+ // never be canceled. Successive calls to Done return the same value.
+ //
+ // WithCancel arranges for Done to be closed when cancel is called;
+ // WithDeadline arranges for Done to be closed when the deadline
+ // expires; WithTimeout arranges for Done to be closed when the timeout
+ // elapses.
+ //
+ // Done is provided for use in select statements:
+ //
+ // // Stream generates values with DoSomething and sends them to out
+ // // until DoSomething returns an error or ctx.Done is closed.
+ // func Stream(ctx context.Context, out <-chan Value) error {
+ // for {
+ // v, err := DoSomething(ctx)
+ // if err != nil {
+ // return err
+ // }
+ // select {
+ // case <-ctx.Done():
+ // return ctx.Err()
+ // case out <- v:
+ // }
+ // }
+ // }
+ //
+ // See http://blog.golang.org/pipelines for more examples of how to use
+ // a Done channel for cancelation.
+ Done() <-chan struct{}
+
+ // Err returns a non-nil error value after Done is closed. Err returns
+ // Canceled if the context was canceled or DeadlineExceeded if the
+ // context's deadline passed. No other values for Err are defined.
+ // After Done is closed, successive calls to Err return the same value.
+ Err() error
+
+ // Value returns the value associated with this context for key, or nil
+ // if no value is associated with key. Successive calls to Value with
+ // the same key returns the same result.
+ //
+ // Use context values only for request-scoped data that transits
+ // processes and API boundaries, not for passing optional parameters to
+ // functions.
+ //
+ // A key identifies a specific value in a Context. Functions that wish
+ // to store values in Context typically allocate a key in a global
+ // variable then use that key as the argument to context.WithValue and
+ // Context.Value. A key can be any type that supports equality;
+ // packages should define keys as an unexported type to avoid
+ // collisions.
+ //
+ // Packages that define a Context key should provide type-safe accessors
+ // for the values stores using that key:
+ //
+ // // Package user defines a User type that's stored in Contexts.
+ // package user
+ //
+ // import "golang.org/x/net/context"
+ //
+ // // User is the type of value stored in the Contexts.
+ // type User struct {...}
+ //
+ // // key is an unexported type for keys defined in this package.
+ // // This prevents collisions with keys defined in other packages.
+ // type key int
+ //
+ // // userKey is the key for user.User values in Contexts. It is
+ // // unexported; clients use user.NewContext and user.FromContext
+ // // instead of using this key directly.
+ // var userKey key = 0
+ //
+ // // NewContext returns a new Context that carries value u.
+ // func NewContext(ctx context.Context, u *User) context.Context {
+ // return context.WithValue(ctx, userKey, u)
+ // }
+ //
+ // // FromContext returns the User value stored in ctx, if any.
+ // func FromContext(ctx context.Context) (*User, bool) {
+ // u, ok := ctx.Value(userKey).(*User)
+ // return u, ok
+ // }
+ Value(key interface{}) interface{}
+}
+
+// Canceled is the error returned by Context.Err when the context is canceled.
+var Canceled = errors.New("context canceled")
+
+// DeadlineExceeded is the error returned by Context.Err when the context's
+// deadline passes.
+var DeadlineExceeded = errors.New("context deadline exceeded")
+
+// An emptyCtx is never canceled, has no values, and has no deadline. It is not
+// struct{}, since vars of this type must have distinct addresses.
+type emptyCtx int
+
+func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
+ return
+}
+
+func (*emptyCtx) Done() <-chan struct{} {
+ return nil
+}
+
+func (*emptyCtx) Err() error {
+ return nil
+}
+
+func (*emptyCtx) Value(key interface{}) interface{} {
+ return nil
+}
+
+func (e *emptyCtx) String() string {
+ switch e {
+ case background:
+ return "context.Background"
+ case todo:
+ return "context.TODO"
+ }
+ return "unknown empty Context"
+}
+
+var (
+ background = new(emptyCtx)
+ todo = new(emptyCtx)
+)
+
+// Background returns a non-nil, empty Context. It is never canceled, has no
+// values, and has no deadline. It is typically used by the main function,
+// initialization, and tests, and as the top-level Context for incoming
+// requests.
+func Background() Context {
+ return background
+}
+
+// TODO returns a non-nil, empty Context. Code should use context.TODO when
+// it's unclear which Context to use or it's is not yet available (because the
+// surrounding function has not yet been extended to accept a Context
+// parameter). TODO is recognized by static analysis tools that determine
+// whether Contexts are propagated correctly in a program.
+func TODO() Context {
+ return todo
+}
+
+// A CancelFunc tells an operation to abandon its work.
+// A CancelFunc does not wait for the work to stop.
+// After the first call, subsequent calls to a CancelFunc do nothing.
+type CancelFunc func()
+
+// WithCancel returns a copy of parent with a new Done channel. The returned
+// context's Done channel is closed when the returned cancel function is called
+// or when the parent context's Done channel is closed, whichever happens first.
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete.
+func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
+ c := newCancelCtx(parent)
+ propagateCancel(parent, &c)
+ return &c, func() { c.cancel(true, Canceled) }
+}
+
+// newCancelCtx returns an initialized cancelCtx.
+func newCancelCtx(parent Context) cancelCtx {
+ return cancelCtx{
+ Context: parent,
+ done: make(chan struct{}),
+ }
+}
+
+// propagateCancel arranges for child to be canceled when parent is.
+func propagateCancel(parent Context, child canceler) {
+ if parent.Done() == nil {
+ return // parent is never canceled
+ }
+ if p, ok := parentCancelCtx(parent); ok {
+ p.mu.Lock()
+ if p.err != nil {
+ // parent has already been canceled
+ child.cancel(false, p.err)
+ } else {
+ if p.children == nil {
+ p.children = make(map[canceler]bool)
+ }
+ p.children[child] = true
+ }
+ p.mu.Unlock()
+ } else {
+ go func() {
+ select {
+ case <-parent.Done():
+ child.cancel(false, parent.Err())
+ case <-child.Done():
+ }
+ }()
+ }
+}
+
+// parentCancelCtx follows a chain of parent references until it finds a
+// *cancelCtx. This function understands how each of the concrete types in this
+// package represents its parent.
+func parentCancelCtx(parent Context) (*cancelCtx, bool) {
+ for {
+ switch c := parent.(type) {
+ case *cancelCtx:
+ return c, true
+ case *timerCtx:
+ return &c.cancelCtx, true
+ case *valueCtx:
+ parent = c.Context
+ default:
+ return nil, false
+ }
+ }
+}
+
+// removeChild removes a context from its parent.
+func removeChild(parent Context, child canceler) {
+ p, ok := parentCancelCtx(parent)
+ if !ok {
+ return
+ }
+ p.mu.Lock()
+ if p.children != nil {
+ delete(p.children, child)
+ }
+ p.mu.Unlock()
+}
+
+// A canceler is a context type that can be canceled directly. The
+// implementations are *cancelCtx and *timerCtx.
+type canceler interface {
+ cancel(removeFromParent bool, err error)
+ Done() <-chan struct{}
+}
+
+// A cancelCtx can be canceled. When canceled, it also cancels any children
+// that implement canceler.
+type cancelCtx struct {
+ Context
+
+ done chan struct{} // closed by the first cancel call.
+
+ mu sync.Mutex
+ children map[canceler]bool // set to nil by the first cancel call
+ err error // set to non-nil by the first cancel call
+}
+
+func (c *cancelCtx) Done() <-chan struct{} {
+ return c.done
+}
+
+func (c *cancelCtx) Err() error {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ return c.err
+}
+
+func (c *cancelCtx) String() string {
+ return fmt.Sprintf("%v.WithCancel", c.Context)
+}
+
+// cancel closes c.done, cancels each of c's children, and, if
+// removeFromParent is true, removes c from its parent's children.
+func (c *cancelCtx) cancel(removeFromParent bool, err error) {
+ if err == nil {
+ panic("context: internal error: missing cancel error")
+ }
+ c.mu.Lock()
+ if c.err != nil {
+ c.mu.Unlock()
+ return // already canceled
+ }
+ c.err = err
+ close(c.done)
+ for child := range c.children {
+ // NOTE: acquiring the child's lock while holding parent's lock.
+ child.cancel(false, err)
+ }
+ c.children = nil
+ c.mu.Unlock()
+
+ if removeFromParent {
+ removeChild(c.Context, c)
+ }
+}
+
+// WithDeadline returns a copy of the parent context with the deadline adjusted
+// to be no later than d. If the parent's deadline is already earlier than d,
+// WithDeadline(parent, d) is semantically equivalent to parent. The returned
+// context's Done channel is closed when the deadline expires, when the returned
+// cancel function is called, or when the parent context's Done channel is
+// closed, whichever happens first.
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete.
+func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
+ if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
+ // The current deadline is already sooner than the new one.
+ return WithCancel(parent)
+ }
+ c := &timerCtx{
+ cancelCtx: newCancelCtx(parent),
+ deadline: deadline,
+ }
+ propagateCancel(parent, c)
+ d := deadline.Sub(time.Now())
+ if d <= 0 {
+ c.cancel(true, DeadlineExceeded) // deadline has already passed
+ return c, func() { c.cancel(true, Canceled) }
+ }
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ if c.err == nil {
+ c.timer = time.AfterFunc(d, func() {
+ c.cancel(true, DeadlineExceeded)
+ })
+ }
+ return c, func() { c.cancel(true, Canceled) }
+}
+
+// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
+// implement Done and Err. It implements cancel by stopping its timer then
+// delegating to cancelCtx.cancel.
+type timerCtx struct {
+ cancelCtx
+ timer *time.Timer // Under cancelCtx.mu.
+
+ deadline time.Time
+}
+
+func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
+ return c.deadline, true
+}
+
+func (c *timerCtx) String() string {
+ return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
+}
+
+func (c *timerCtx) cancel(removeFromParent bool, err error) {
+ c.cancelCtx.cancel(false, err)
+ if removeFromParent {
+ // Remove this timerCtx from its parent cancelCtx's children.
+ removeChild(c.cancelCtx.Context, c)
+ }
+ c.mu.Lock()
+ if c.timer != nil {
+ c.timer.Stop()
+ c.timer = nil
+ }
+ c.mu.Unlock()
+}
+
+// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete:
+//
+// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
+// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
+// defer cancel() // releases resources if slowOperation completes before timeout elapses
+// return slowOperation(ctx)
+// }
+func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
+ return WithDeadline(parent, time.Now().Add(timeout))
+}
+
+// WithValue returns a copy of parent in which the value associated with key is
+// val.
+//
+// Use context Values only for request-scoped data that transits processes and
+// APIs, not for passing optional parameters to functions.
+func WithValue(parent Context, key interface{}, val interface{}) Context {
+ return &valueCtx{parent, key, val}
+}
+
+// A valueCtx carries a key-value pair. It implements Value for that key and
+// delegates all other calls to the embedded Context.
+type valueCtx struct {
+ Context
+ key, val interface{}
+}
+
+func (c *valueCtx) String() string {
+ return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
+}
+
+func (c *valueCtx) Value(key interface{}) interface{} {
+ if c.key == key {
+ return c.val
+ }
+ return c.Context.Value(key)
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.5
+
+package ctxhttp
+
+import "net/http"
+
+func canceler(client *http.Client, req *http.Request) func() {
+ ch := make(chan struct{})
+ req.Cancel = ch
+
+ return func() {
+ close(ch)
+ }
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.5
+
+package ctxhttp
+
+import "net/http"
+
+type requestCanceler interface {
+ CancelRequest(*http.Request)
+}
+
+func canceler(client *http.Client, req *http.Request) func() {
+ rc, ok := client.Transport.(requestCanceler)
+ if !ok {
+ return func() {}
+ }
+ return func() {
+ rc.CancelRequest(req)
+ }
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package ctxhttp provides helper functions for performing context-aware HTTP requests.
+package ctxhttp // import "golang.org/x/net/context/ctxhttp"
+
+import (
+ "io"
+ "net/http"
+ "net/url"
+ "strings"
+
+ "golang.org/x/net/context"
+)
+
+// Do sends an HTTP request with the provided http.Client and returns an HTTP response.
+// If the client is nil, http.DefaultClient is used.
+// If the context is canceled or times out, ctx.Err() will be returned.
+func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
+ if client == nil {
+ client = http.DefaultClient
+ }
+
+ // Request cancelation changed in Go 1.5, see cancelreq.go and cancelreq_go14.go.
+ cancel := canceler(client, req)
+
+ type responseAndError struct {
+ resp *http.Response
+ err error
+ }
+ result := make(chan responseAndError, 1)
+
+ go func() {
+ resp, err := client.Do(req)
+ result <- responseAndError{resp, err}
+ }()
+
+ select {
+ case <-ctx.Done():
+ cancel()
+ return nil, ctx.Err()
+ case r := <-result:
+ return r.resp, r.err
+ }
+}
+
+// Get issues a GET request via the Do function.
+func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
+ req, err := http.NewRequest("GET", url, nil)
+ if err != nil {
+ return nil, err
+ }
+ return Do(ctx, client, req)
+}
+
+// Head issues a HEAD request via the Do function.
+func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
+ req, err := http.NewRequest("HEAD", url, nil)
+ if err != nil {
+ return nil, err
+ }
+ return Do(ctx, client, req)
+}
+
+// Post issues a POST request via the Do function.
+func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) {
+ req, err := http.NewRequest("POST", url, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Content-Type", bodyType)
+ return Do(ctx, client, req)
+}
+
+// PostForm issues a POST request via the Do function.
+func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
+ return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package timeseries implements a time series structure for stats collection.
+package timeseries // import "golang.org/x/net/internal/timeseries"
+
+import (
+ "fmt"
+ "log"
+ "time"
+)
+
+const (
+ timeSeriesNumBuckets = 64
+ minuteHourSeriesNumBuckets = 60
+)
+
+var timeSeriesResolutions = []time.Duration{
+ 1 * time.Second,
+ 10 * time.Second,
+ 1 * time.Minute,
+ 10 * time.Minute,
+ 1 * time.Hour,
+ 6 * time.Hour,
+ 24 * time.Hour, // 1 day
+ 7 * 24 * time.Hour, // 1 week
+ 4 * 7 * 24 * time.Hour, // 4 weeks
+ 16 * 7 * 24 * time.Hour, // 16 weeks
+}
+
+var minuteHourSeriesResolutions = []time.Duration{
+ 1 * time.Second,
+ 1 * time.Minute,
+}
+
+// An Observable is a kind of data that can be aggregated in a time series.
+type Observable interface {
+ Multiply(ratio float64) // Multiplies the data in self by a given ratio
+ Add(other Observable) // Adds the data from a different observation to self
+ Clear() // Clears the observation so it can be reused.
+ CopyFrom(other Observable) // Copies the contents of a given observation to self
+}
+
+// Float attaches the methods of Observable to a float64.
+type Float float64
+
+// NewFloat returns a Float.
+func NewFloat() Observable {
+ f := Float(0)
+ return &f
+}
+
+// String returns the float as a string.
+func (f *Float) String() string { return fmt.Sprintf("%g", f.Value()) }
+
+// Value returns the float's value.
+func (f *Float) Value() float64 { return float64(*f) }
+
+func (f *Float) Multiply(ratio float64) { *f *= Float(ratio) }
+
+func (f *Float) Add(other Observable) {
+ o := other.(*Float)
+ *f += *o
+}
+
+func (f *Float) Clear() { *f = 0 }
+
+func (f *Float) CopyFrom(other Observable) {
+ o := other.(*Float)
+ *f = *o
+}
+
+// A Clock tells the current time.
+type Clock interface {
+ Time() time.Time
+}
+
+type defaultClock int
+
+var defaultClockInstance defaultClock
+
+func (defaultClock) Time() time.Time { return time.Now() }
+
+// Information kept per level. Each level consists of a circular list of
+// observations. The start of the level may be derived from end and the
+// len(buckets) * sizeInMillis.
+type tsLevel struct {
+ oldest int // index to oldest bucketed Observable
+ newest int // index to newest bucketed Observable
+ end time.Time // end timestamp for this level
+ size time.Duration // duration of the bucketed Observable
+ buckets []Observable // collections of observations
+ provider func() Observable // used for creating new Observable
+}
+
+func (l *tsLevel) Clear() {
+ l.oldest = 0
+ l.newest = len(l.buckets) - 1
+ l.end = time.Time{}
+ for i := range l.buckets {
+ if l.buckets[i] != nil {
+ l.buckets[i].Clear()
+ l.buckets[i] = nil
+ }
+ }
+}
+
+func (l *tsLevel) InitLevel(size time.Duration, numBuckets int, f func() Observable) {
+ l.size = size
+ l.provider = f
+ l.buckets = make([]Observable, numBuckets)
+}
+
+// Keeps a sequence of levels. Each level is responsible for storing data at
+// a given resolution. For example, the first level stores data at a one
+// minute resolution while the second level stores data at a one hour
+// resolution.
+
+// Each level is represented by a sequence of buckets. Each bucket spans an
+// interval equal to the resolution of the level. New observations are added
+// to the last bucket.
+type timeSeries struct {
+ provider func() Observable // make more Observable
+ numBuckets int // number of buckets in each level
+ levels []*tsLevel // levels of bucketed Observable
+ lastAdd time.Time // time of last Observable tracked
+ total Observable // convenient aggregation of all Observable
+ clock Clock // Clock for getting current time
+ pending Observable // observations not yet bucketed
+ pendingTime time.Time // what time are we keeping in pending
+ dirty bool // if there are pending observations
+}
+
+// init initializes a level according to the supplied criteria.
+func (ts *timeSeries) init(resolutions []time.Duration, f func() Observable, numBuckets int, clock Clock) {
+ ts.provider = f
+ ts.numBuckets = numBuckets
+ ts.clock = clock
+ ts.levels = make([]*tsLevel, len(resolutions))
+
+ for i := range resolutions {
+ if i > 0 && resolutions[i-1] >= resolutions[i] {
+ log.Print("timeseries: resolutions must be monotonically increasing")
+ break
+ }
+ newLevel := new(tsLevel)
+ newLevel.InitLevel(resolutions[i], ts.numBuckets, ts.provider)
+ ts.levels[i] = newLevel
+ }
+
+ ts.Clear()
+}
+
+// Clear removes all observations from the time series.
+func (ts *timeSeries) Clear() {
+ ts.lastAdd = time.Time{}
+ ts.total = ts.resetObservation(ts.total)
+ ts.pending = ts.resetObservation(ts.pending)
+ ts.pendingTime = time.Time{}
+ ts.dirty = false
+
+ for i := range ts.levels {
+ ts.levels[i].Clear()
+ }
+}
+
+// Add records an observation at the current time.
+func (ts *timeSeries) Add(observation Observable) {
+ ts.AddWithTime(observation, ts.clock.Time())
+}
+
+// AddWithTime records an observation at the specified time.
+func (ts *timeSeries) AddWithTime(observation Observable, t time.Time) {
+
+ smallBucketDuration := ts.levels[0].size
+
+ if t.After(ts.lastAdd) {
+ ts.lastAdd = t
+ }
+
+ if t.After(ts.pendingTime) {
+ ts.advance(t)
+ ts.mergePendingUpdates()
+ ts.pendingTime = ts.levels[0].end
+ ts.pending.CopyFrom(observation)
+ ts.dirty = true
+ } else if t.After(ts.pendingTime.Add(-1 * smallBucketDuration)) {
+ // The observation is close enough to go into the pending bucket.
+ // This compensates for clock skewing and small scheduling delays
+ // by letting the update stay in the fast path.
+ ts.pending.Add(observation)
+ ts.dirty = true
+ } else {
+ ts.mergeValue(observation, t)
+ }
+}
+
+// mergeValue inserts the observation at the specified time in the past into all levels.
+func (ts *timeSeries) mergeValue(observation Observable, t time.Time) {
+ for _, level := range ts.levels {
+ index := (ts.numBuckets - 1) - int(level.end.Sub(t)/level.size)
+ if 0 <= index && index < ts.numBuckets {
+ bucketNumber := (level.oldest + index) % ts.numBuckets
+ if level.buckets[bucketNumber] == nil {
+ level.buckets[bucketNumber] = level.provider()
+ }
+ level.buckets[bucketNumber].Add(observation)
+ }
+ }
+ ts.total.Add(observation)
+}
+
+// mergePendingUpdates applies the pending updates into all levels.
+func (ts *timeSeries) mergePendingUpdates() {
+ if ts.dirty {
+ ts.mergeValue(ts.pending, ts.pendingTime)
+ ts.pending = ts.resetObservation(ts.pending)
+ ts.dirty = false
+ }
+}
+
+// advance cycles the buckets at each level until the latest bucket in
+// each level can hold the time specified.
+func (ts *timeSeries) advance(t time.Time) {
+ if !t.After(ts.levels[0].end) {
+ return
+ }
+ for i := 0; i < len(ts.levels); i++ {
+ level := ts.levels[i]
+ if !level.end.Before(t) {
+ break
+ }
+
+ // If the time is sufficiently far, just clear the level and advance
+ // directly.
+ if !t.Before(level.end.Add(level.size * time.Duration(ts.numBuckets))) {
+ for _, b := range level.buckets {
+ ts.resetObservation(b)
+ }
+ level.end = time.Unix(0, (t.UnixNano()/level.size.Nanoseconds())*level.size.Nanoseconds())
+ }
+
+ for t.After(level.end) {
+ level.end = level.end.Add(level.size)
+ level.newest = level.oldest
+ level.oldest = (level.oldest + 1) % ts.numBuckets
+ ts.resetObservation(level.buckets[level.newest])
+ }
+
+ t = level.end
+ }
+}
+
+// Latest returns the sum of the num latest buckets from the level.
+func (ts *timeSeries) Latest(level, num int) Observable {
+ now := ts.clock.Time()
+ if ts.levels[0].end.Before(now) {
+ ts.advance(now)
+ }
+
+ ts.mergePendingUpdates()
+
+ result := ts.provider()
+ l := ts.levels[level]
+ index := l.newest
+
+ for i := 0; i < num; i++ {
+ if l.buckets[index] != nil {
+ result.Add(l.buckets[index])
+ }
+ if index == 0 {
+ index = ts.numBuckets
+ }
+ index--
+ }
+
+ return result
+}
+
+// LatestBuckets returns a copy of the num latest buckets from level.
+func (ts *timeSeries) LatestBuckets(level, num int) []Observable {
+ if level < 0 || level > len(ts.levels) {
+ log.Print("timeseries: bad level argument: ", level)
+ return nil
+ }
+ if num < 0 || num >= ts.numBuckets {
+ log.Print("timeseries: bad num argument: ", num)
+ return nil
+ }
+
+ results := make([]Observable, num)
+ now := ts.clock.Time()
+ if ts.levels[0].end.Before(now) {
+ ts.advance(now)
+ }
+
+ ts.mergePendingUpdates()
+
+ l := ts.levels[level]
+ index := l.newest
+
+ for i := 0; i < num; i++ {
+ result := ts.provider()
+ results[i] = result
+ if l.buckets[index] != nil {
+ result.CopyFrom(l.buckets[index])
+ }
+
+ if index == 0 {
+ index = ts.numBuckets
+ }
+ index -= 1
+ }
+ return results
+}
+
+// ScaleBy updates observations by scaling by factor.
+func (ts *timeSeries) ScaleBy(factor float64) {
+ for _, l := range ts.levels {
+ for i := 0; i < ts.numBuckets; i++ {
+ l.buckets[i].Multiply(factor)
+ }
+ }
+
+ ts.total.Multiply(factor)
+ ts.pending.Multiply(factor)
+}
+
+// Range returns the sum of observations added over the specified time range.
+// If start or finish times don't fall on bucket boundaries of the same
+// level, then return values are approximate answers.
+func (ts *timeSeries) Range(start, finish time.Time) Observable {
+ return ts.ComputeRange(start, finish, 1)[0]
+}
+
+// Recent returns the sum of observations from the last delta.
+func (ts *timeSeries) Recent(delta time.Duration) Observable {
+ now := ts.clock.Time()
+ return ts.Range(now.Add(-delta), now)
+}
+
+// Total returns the total of all observations.
+func (ts *timeSeries) Total() Observable {
+ ts.mergePendingUpdates()
+ return ts.total
+}
+
+// ComputeRange computes a specified number of values into a slice using
+// the observations recorded over the specified time period. The return
+// values are approximate if the start or finish times don't fall on the
+// bucket boundaries at the same level or if the number of buckets spanning
+// the range is not an integral multiple of num.
+func (ts *timeSeries) ComputeRange(start, finish time.Time, num int) []Observable {
+ if start.After(finish) {
+ log.Printf("timeseries: start > finish, %v>%v", start, finish)
+ return nil
+ }
+
+ if num < 0 {
+ log.Printf("timeseries: num < 0, %v", num)
+ return nil
+ }
+
+ results := make([]Observable, num)
+
+ for _, l := range ts.levels {
+ if !start.Before(l.end.Add(-l.size * time.Duration(ts.numBuckets))) {
+ ts.extract(l, start, finish, num, results)
+ return results
+ }
+ }
+
+ // Failed to find a level that covers the desired range. So just
+ // extract from the last level, even if it doesn't cover the entire
+ // desired range.
+ ts.extract(ts.levels[len(ts.levels)-1], start, finish, num, results)
+
+ return results
+}
+
+// RecentList returns the specified number of values in slice over the most
+// recent time period of the specified range.
+func (ts *timeSeries) RecentList(delta time.Duration, num int) []Observable {
+ if delta < 0 {
+ return nil
+ }
+ now := ts.clock.Time()
+ return ts.ComputeRange(now.Add(-delta), now, num)
+}
+
+// extract returns a slice of specified number of observations from a given
+// level over a given range.
+func (ts *timeSeries) extract(l *tsLevel, start, finish time.Time, num int, results []Observable) {
+ ts.mergePendingUpdates()
+
+ srcInterval := l.size
+ dstInterval := finish.Sub(start) / time.Duration(num)
+ dstStart := start
+ srcStart := l.end.Add(-srcInterval * time.Duration(ts.numBuckets))
+
+ srcIndex := 0
+
+ // Where should scanning start?
+ if dstStart.After(srcStart) {
+ advance := dstStart.Sub(srcStart) / srcInterval
+ srcIndex += int(advance)
+ srcStart = srcStart.Add(advance * srcInterval)
+ }
+
+ // The i'th value is computed as show below.
+ // interval = (finish/start)/num
+ // i'th value = sum of observation in range
+ // [ start + i * interval,
+ // start + (i + 1) * interval )
+ for i := 0; i < num; i++ {
+ results[i] = ts.resetObservation(results[i])
+ dstEnd := dstStart.Add(dstInterval)
+ for srcIndex < ts.numBuckets && srcStart.Before(dstEnd) {
+ srcEnd := srcStart.Add(srcInterval)
+ if srcEnd.After(ts.lastAdd) {
+ srcEnd = ts.lastAdd
+ }
+
+ if !srcEnd.Before(dstStart) {
+ srcValue := l.buckets[(srcIndex+l.oldest)%ts.numBuckets]
+ if !srcStart.Before(dstStart) && !srcEnd.After(dstEnd) {
+ // dst completely contains src.
+ if srcValue != nil {
+ results[i].Add(srcValue)
+ }
+ } else {
+ // dst partially overlaps src.
+ overlapStart := maxTime(srcStart, dstStart)
+ overlapEnd := minTime(srcEnd, dstEnd)
+ base := srcEnd.Sub(srcStart)
+ fraction := overlapEnd.Sub(overlapStart).Seconds() / base.Seconds()
+
+ used := ts.provider()
+ if srcValue != nil {
+ used.CopyFrom(srcValue)
+ }
+ used.Multiply(fraction)
+ results[i].Add(used)
+ }
+
+ if srcEnd.After(dstEnd) {
+ break
+ }
+ }
+ srcIndex++
+ srcStart = srcStart.Add(srcInterval)
+ }
+ dstStart = dstStart.Add(dstInterval)
+ }
+}
+
+// resetObservation clears the content so the struct may be reused.
+func (ts *timeSeries) resetObservation(observation Observable) Observable {
+ if observation == nil {
+ observation = ts.provider()
+ } else {
+ observation.Clear()
+ }
+ return observation
+}
+
+// TimeSeries tracks data at granularities from 1 second to 16 weeks.
+type TimeSeries struct {
+ timeSeries
+}
+
+// NewTimeSeries creates a new TimeSeries using the function provided for creating new Observable.
+func NewTimeSeries(f func() Observable) *TimeSeries {
+ return NewTimeSeriesWithClock(f, defaultClockInstance)
+}
+
+// NewTimeSeriesWithClock creates a new TimeSeries using the function provided for creating new Observable and the clock for
+// assigning timestamps.
+func NewTimeSeriesWithClock(f func() Observable, clock Clock) *TimeSeries {
+ ts := new(TimeSeries)
+ ts.timeSeries.init(timeSeriesResolutions, f, timeSeriesNumBuckets, clock)
+ return ts
+}
+
+// MinuteHourSeries tracks data at granularities of 1 minute and 1 hour.
+type MinuteHourSeries struct {
+ timeSeries
+}
+
+// NewMinuteHourSeries creates a new MinuteHourSeries using the function provided for creating new Observable.
+func NewMinuteHourSeries(f func() Observable) *MinuteHourSeries {
+ return NewMinuteHourSeriesWithClock(f, defaultClockInstance)
+}
+
+// NewMinuteHourSeriesWithClock creates a new MinuteHourSeries using the function provided for creating new Observable and the clock for
+// assigning timestamps.
+func NewMinuteHourSeriesWithClock(f func() Observable, clock Clock) *MinuteHourSeries {
+ ts := new(MinuteHourSeries)
+ ts.timeSeries.init(minuteHourSeriesResolutions, f,
+ minuteHourSeriesNumBuckets, clock)
+ return ts
+}
+
+func (ts *MinuteHourSeries) Minute() Observable {
+ return ts.timeSeries.Latest(0, 60)
+}
+
+func (ts *MinuteHourSeries) Hour() Observable {
+ return ts.timeSeries.Latest(1, 60)
+}
+
+func minTime(a, b time.Time) time.Time {
+ if a.Before(b) {
+ return a
+ }
+ return b
+}
+
+func maxTime(a, b time.Time) time.Time {
+ if a.After(b) {
+ return a
+ }
+ return b
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package trace
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "io"
+ "log"
+ "net/http"
+ "runtime"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "text/tabwriter"
+ "time"
+)
+
+const maxEventsPerLog = 100
+
+type bucket struct {
+ MaxErrAge time.Duration
+ String string
+}
+
+var buckets = []bucket{
+ {0, "total"},
+ {10 * time.Second, "errs<10s"},
+ {1 * time.Minute, "errs<1m"},
+ {10 * time.Minute, "errs<10m"},
+ {1 * time.Hour, "errs<1h"},
+ {10 * time.Hour, "errs<10h"},
+ {24000 * time.Hour, "errors"},
+}
+
+// RenderEvents renders the HTML page typically served at /debug/events.
+// It does not do any auth checking. The request may be nil.
+//
+// Most users will use the Events handler.
+func RenderEvents(w http.ResponseWriter, req *http.Request, sensitive bool) {
+ now := time.Now()
+ data := &struct {
+ Families []string // family names
+ Buckets []bucket
+ Counts [][]int // eventLog count per family/bucket
+
+ // Set when a bucket has been selected.
+ Family string
+ Bucket int
+ EventLogs eventLogs
+ Expanded bool
+ }{
+ Buckets: buckets,
+ }
+
+ data.Families = make([]string, 0, len(families))
+ famMu.RLock()
+ for name := range families {
+ data.Families = append(data.Families, name)
+ }
+ famMu.RUnlock()
+ sort.Strings(data.Families)
+
+ // Count the number of eventLogs in each family for each error age.
+ data.Counts = make([][]int, len(data.Families))
+ for i, name := range data.Families {
+ // TODO(sameer): move this loop under the family lock.
+ f := getEventFamily(name)
+ data.Counts[i] = make([]int, len(data.Buckets))
+ for j, b := range data.Buckets {
+ data.Counts[i][j] = f.Count(now, b.MaxErrAge)
+ }
+ }
+
+ if req != nil {
+ var ok bool
+ data.Family, data.Bucket, ok = parseEventsArgs(req)
+ if !ok {
+ // No-op
+ } else {
+ data.EventLogs = getEventFamily(data.Family).Copy(now, buckets[data.Bucket].MaxErrAge)
+ }
+ if data.EventLogs != nil {
+ defer data.EventLogs.Free()
+ sort.Sort(data.EventLogs)
+ }
+ if exp, err := strconv.ParseBool(req.FormValue("exp")); err == nil {
+ data.Expanded = exp
+ }
+ }
+
+ famMu.RLock()
+ defer famMu.RUnlock()
+ if err := eventsTmpl().Execute(w, data); err != nil {
+ log.Printf("net/trace: Failed executing template: %v", err)
+ }
+}
+
+func parseEventsArgs(req *http.Request) (fam string, b int, ok bool) {
+ fam, bStr := req.FormValue("fam"), req.FormValue("b")
+ if fam == "" || bStr == "" {
+ return "", 0, false
+ }
+ b, err := strconv.Atoi(bStr)
+ if err != nil || b < 0 || b >= len(buckets) {
+ return "", 0, false
+ }
+ return fam, b, true
+}
+
+// An EventLog provides a log of events associated with a specific object.
+type EventLog interface {
+ // Printf formats its arguments with fmt.Sprintf and adds the
+ // result to the event log.
+ Printf(format string, a ...interface{})
+
+ // Errorf is like Printf, but it marks this event as an error.
+ Errorf(format string, a ...interface{})
+
+ // Finish declares that this event log is complete.
+ // The event log should not be used after calling this method.
+ Finish()
+}
+
+// NewEventLog returns a new EventLog with the specified family name
+// and title.
+func NewEventLog(family, title string) EventLog {
+ el := newEventLog()
+ el.ref()
+ el.Family, el.Title = family, title
+ el.Start = time.Now()
+ el.events = make([]logEntry, 0, maxEventsPerLog)
+ el.stack = make([]uintptr, 32)
+ n := runtime.Callers(2, el.stack)
+ el.stack = el.stack[:n]
+
+ getEventFamily(family).add(el)
+ return el
+}
+
+func (el *eventLog) Finish() {
+ getEventFamily(el.Family).remove(el)
+ el.unref() // matches ref in New
+}
+
+var (
+ famMu sync.RWMutex
+ families = make(map[string]*eventFamily) // family name => family
+)
+
+func getEventFamily(fam string) *eventFamily {
+ famMu.Lock()
+ defer famMu.Unlock()
+ f := families[fam]
+ if f == nil {
+ f = &eventFamily{}
+ families[fam] = f
+ }
+ return f
+}
+
+type eventFamily struct {
+ mu sync.RWMutex
+ eventLogs eventLogs
+}
+
+func (f *eventFamily) add(el *eventLog) {
+ f.mu.Lock()
+ f.eventLogs = append(f.eventLogs, el)
+ f.mu.Unlock()
+}
+
+func (f *eventFamily) remove(el *eventLog) {
+ f.mu.Lock()
+ defer f.mu.Unlock()
+ for i, el0 := range f.eventLogs {
+ if el == el0 {
+ copy(f.eventLogs[i:], f.eventLogs[i+1:])
+ f.eventLogs = f.eventLogs[:len(f.eventLogs)-1]
+ return
+ }
+ }
+}
+
+func (f *eventFamily) Count(now time.Time, maxErrAge time.Duration) (n int) {
+ f.mu.RLock()
+ defer f.mu.RUnlock()
+ for _, el := range f.eventLogs {
+ if el.hasRecentError(now, maxErrAge) {
+ n++
+ }
+ }
+ return
+}
+
+func (f *eventFamily) Copy(now time.Time, maxErrAge time.Duration) (els eventLogs) {
+ f.mu.RLock()
+ defer f.mu.RUnlock()
+ els = make(eventLogs, 0, len(f.eventLogs))
+ for _, el := range f.eventLogs {
+ if el.hasRecentError(now, maxErrAge) {
+ el.ref()
+ els = append(els, el)
+ }
+ }
+ return
+}
+
+type eventLogs []*eventLog
+
+// Free calls unref on each element of the list.
+func (els eventLogs) Free() {
+ for _, el := range els {
+ el.unref()
+ }
+}
+
+// eventLogs may be sorted in reverse chronological order.
+func (els eventLogs) Len() int { return len(els) }
+func (els eventLogs) Less(i, j int) bool { return els[i].Start.After(els[j].Start) }
+func (els eventLogs) Swap(i, j int) { els[i], els[j] = els[j], els[i] }
+
+// A logEntry is a timestamped log entry in an event log.
+type logEntry struct {
+ When time.Time
+ Elapsed time.Duration // since previous event in log
+ NewDay bool // whether this event is on a different day to the previous event
+ What string
+ IsErr bool
+}
+
+// WhenString returns a string representation of the elapsed time of the event.
+// It will include the date if midnight was crossed.
+func (e logEntry) WhenString() string {
+ if e.NewDay {
+ return e.When.Format("2006/01/02 15:04:05.000000")
+ }
+ return e.When.Format("15:04:05.000000")
+}
+
+// An eventLog represents an active event log.
+type eventLog struct {
+ // Family is the top-level grouping of event logs to which this belongs.
+ Family string
+
+ // Title is the title of this event log.
+ Title string
+
+ // Timing information.
+ Start time.Time
+
+ // Call stack where this event log was created.
+ stack []uintptr
+
+ // Append-only sequence of events.
+ //
+ // TODO(sameer): change this to a ring buffer to avoid the array copy
+ // when we hit maxEventsPerLog.
+ mu sync.RWMutex
+ events []logEntry
+ LastErrorTime time.Time
+ discarded int
+
+ refs int32 // how many buckets this is in
+}
+
+func (el *eventLog) reset() {
+ // Clear all but the mutex. Mutexes may not be copied, even when unlocked.
+ el.Family = ""
+ el.Title = ""
+ el.Start = time.Time{}
+ el.stack = nil
+ el.events = nil
+ el.LastErrorTime = time.Time{}
+ el.discarded = 0
+ el.refs = 0
+}
+
+func (el *eventLog) hasRecentError(now time.Time, maxErrAge time.Duration) bool {
+ if maxErrAge == 0 {
+ return true
+ }
+ el.mu.RLock()
+ defer el.mu.RUnlock()
+ return now.Sub(el.LastErrorTime) < maxErrAge
+}
+
+// delta returns the elapsed time since the last event or the log start,
+// and whether it spans midnight.
+// L >= el.mu
+func (el *eventLog) delta(t time.Time) (time.Duration, bool) {
+ if len(el.events) == 0 {
+ return t.Sub(el.Start), false
+ }
+ prev := el.events[len(el.events)-1].When
+ return t.Sub(prev), prev.Day() != t.Day()
+
+}
+
+func (el *eventLog) Printf(format string, a ...interface{}) {
+ el.printf(false, format, a...)
+}
+
+func (el *eventLog) Errorf(format string, a ...interface{}) {
+ el.printf(true, format, a...)
+}
+
+func (el *eventLog) printf(isErr bool, format string, a ...interface{}) {
+ e := logEntry{When: time.Now(), IsErr: isErr, What: fmt.Sprintf(format, a...)}
+ el.mu.Lock()
+ e.Elapsed, e.NewDay = el.delta(e.When)
+ if len(el.events) < maxEventsPerLog {
+ el.events = append(el.events, e)
+ } else {
+ // Discard the oldest event.
+ if el.discarded == 0 {
+ // el.discarded starts at two to count for the event it
+ // is replacing, plus the next one that we are about to
+ // drop.
+ el.discarded = 2
+ } else {
+ el.discarded++
+ }
+ // TODO(sameer): if this causes allocations on a critical path,
+ // change eventLog.What to be a fmt.Stringer, as in trace.go.
+ el.events[0].What = fmt.Sprintf("(%d events discarded)", el.discarded)
+ // The timestamp of the discarded meta-event should be
+ // the time of the last event it is representing.
+ el.events[0].When = el.events[1].When
+ copy(el.events[1:], el.events[2:])
+ el.events[maxEventsPerLog-1] = e
+ }
+ if e.IsErr {
+ el.LastErrorTime = e.When
+ }
+ el.mu.Unlock()
+}
+
+func (el *eventLog) ref() {
+ atomic.AddInt32(&el.refs, 1)
+}
+
+func (el *eventLog) unref() {
+ if atomic.AddInt32(&el.refs, -1) == 0 {
+ freeEventLog(el)
+ }
+}
+
+func (el *eventLog) When() string {
+ return el.Start.Format("2006/01/02 15:04:05.000000")
+}
+
+func (el *eventLog) ElapsedTime() string {
+ elapsed := time.Since(el.Start)
+ return fmt.Sprintf("%.6f", elapsed.Seconds())
+}
+
+func (el *eventLog) Stack() string {
+ buf := new(bytes.Buffer)
+ tw := tabwriter.NewWriter(buf, 1, 8, 1, '\t', 0)
+ printStackRecord(tw, el.stack)
+ tw.Flush()
+ return buf.String()
+}
+
+// printStackRecord prints the function + source line information
+// for a single stack trace.
+// Adapted from runtime/pprof/pprof.go.
+func printStackRecord(w io.Writer, stk []uintptr) {
+ for _, pc := range stk {
+ f := runtime.FuncForPC(pc)
+ if f == nil {
+ continue
+ }
+ file, line := f.FileLine(pc)
+ name := f.Name()
+ // Hide runtime.goexit and any runtime functions at the beginning.
+ if strings.HasPrefix(name, "runtime.") {
+ continue
+ }
+ fmt.Fprintf(w, "# %s\t%s:%d\n", name, file, line)
+ }
+}
+
+func (el *eventLog) Events() []logEntry {
+ el.mu.RLock()
+ defer el.mu.RUnlock()
+ return el.events
+}
+
+// freeEventLogs is a freelist of *eventLog
+var freeEventLogs = make(chan *eventLog, 1000)
+
+// newEventLog returns a event log ready to use.
+func newEventLog() *eventLog {
+ select {
+ case el := <-freeEventLogs:
+ return el
+ default:
+ return new(eventLog)
+ }
+}
+
+// freeEventLog adds el to freeEventLogs if there's room.
+// This is non-blocking.
+func freeEventLog(el *eventLog) {
+ el.reset()
+ select {
+ case freeEventLogs <- el:
+ default:
+ }
+}
+
+var eventsTmplCache *template.Template
+var eventsTmplOnce sync.Once
+
+func eventsTmpl() *template.Template {
+ eventsTmplOnce.Do(func() {
+ eventsTmplCache = template.Must(template.New("events").Funcs(template.FuncMap{
+ "elapsed": elapsed,
+ "trimSpace": strings.TrimSpace,
+ }).Parse(eventsHTML))
+ })
+ return eventsTmplCache
+}
+
+const eventsHTML = `
+<html>
+ <head>
+ <title>events</title>
+ </head>
+ <style type="text/css">
+ body {
+ font-family: sans-serif;
+ }
+ table#req-status td.family {
+ padding-right: 2em;
+ }
+ table#req-status td.active {
+ padding-right: 1em;
+ }
+ table#req-status td.empty {
+ color: #aaa;
+ }
+ table#reqs {
+ margin-top: 1em;
+ }
+ table#reqs tr.first {
+ {{if $.Expanded}}font-weight: bold;{{end}}
+ }
+ table#reqs td {
+ font-family: monospace;
+ }
+ table#reqs td.when {
+ text-align: right;
+ white-space: nowrap;
+ }
+ table#reqs td.elapsed {
+ padding: 0 0.5em;
+ text-align: right;
+ white-space: pre;
+ width: 10em;
+ }
+ address {
+ font-size: smaller;
+ margin-top: 5em;
+ }
+ </style>
+ <body>
+
+<h1>/debug/events</h1>
+
+<table id="req-status">
+ {{range $i, $fam := .Families}}
+ <tr>
+ <td class="family">{{$fam}}</td>
+
+ {{range $j, $bucket := $.Buckets}}
+ {{$n := index $.Counts $i $j}}
+ <td class="{{if not $bucket.MaxErrAge}}active{{end}}{{if not $n}}empty{{end}}">
+ {{if $n}}<a href="?fam={{$fam}}&b={{$j}}{{if $.Expanded}}&exp=1{{end}}">{{end}}
+ [{{$n}} {{$bucket.String}}]
+ {{if $n}}</a>{{end}}
+ </td>
+ {{end}}
+
+ </tr>{{end}}
+</table>
+
+{{if $.EventLogs}}
+<hr />
+<h3>Family: {{$.Family}}</h3>
+
+{{if $.Expanded}}<a href="?fam={{$.Family}}&b={{$.Bucket}}">{{end}}
+[Summary]{{if $.Expanded}}</a>{{end}}
+
+{{if not $.Expanded}}<a href="?fam={{$.Family}}&b={{$.Bucket}}&exp=1">{{end}}
+[Expanded]{{if not $.Expanded}}</a>{{end}}
+
+<table id="reqs">
+ <tr><th>When</th><th>Elapsed</th></tr>
+ {{range $el := $.EventLogs}}
+ <tr class="first">
+ <td class="when">{{$el.When}}</td>
+ <td class="elapsed">{{$el.ElapsedTime}}</td>
+ <td>{{$el.Title}}
+ </tr>
+ {{if $.Expanded}}
+ <tr>
+ <td class="when"></td>
+ <td class="elapsed"></td>
+ <td><pre>{{$el.Stack|trimSpace}}</pre></td>
+ </tr>
+ {{range $el.Events}}
+ <tr>
+ <td class="when">{{.WhenString}}</td>
+ <td class="elapsed">{{elapsed .Elapsed}}</td>
+ <td>.{{if .IsErr}}E{{else}}.{{end}}. {{.What}}</td>
+ </tr>
+ {{end}}
+ {{end}}
+ {{end}}
+</table>
+{{end}}
+ </body>
+</html>
+`
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package trace
+
+// This file implements histogramming for RPC statistics collection.
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "log"
+ "math"
+ "sync"
+
+ "golang.org/x/net/internal/timeseries"
+)
+
+const (
+ bucketCount = 38
+)
+
+// histogram keeps counts of values in buckets that are spaced
+// out in powers of 2: 0-1, 2-3, 4-7...
+// histogram implements timeseries.Observable
+type histogram struct {
+ sum int64 // running total of measurements
+ sumOfSquares float64 // square of running total
+ buckets []int64 // bucketed values for histogram
+ value int // holds a single value as an optimization
+ valueCount int64 // number of values recorded for single value
+}
+
+// AddMeasurement records a value measurement observation to the histogram.
+func (h *histogram) addMeasurement(value int64) {
+ // TODO: assert invariant
+ h.sum += value
+ h.sumOfSquares += float64(value) * float64(value)
+
+ bucketIndex := getBucket(value)
+
+ if h.valueCount == 0 || (h.valueCount > 0 && h.value == bucketIndex) {
+ h.value = bucketIndex
+ h.valueCount++
+ } else {
+ h.allocateBuckets()
+ h.buckets[bucketIndex]++
+ }
+}
+
+func (h *histogram) allocateBuckets() {
+ if h.buckets == nil {
+ h.buckets = make([]int64, bucketCount)
+ h.buckets[h.value] = h.valueCount
+ h.value = 0
+ h.valueCount = -1
+ }
+}
+
+func log2(i int64) int {
+ n := 0
+ for ; i >= 0x100; i >>= 8 {
+ n += 8
+ }
+ for ; i > 0; i >>= 1 {
+ n += 1
+ }
+ return n
+}
+
+func getBucket(i int64) (index int) {
+ index = log2(i) - 1
+ if index < 0 {
+ index = 0
+ }
+ if index >= bucketCount {
+ index = bucketCount - 1
+ }
+ return
+}
+
+// Total returns the number of recorded observations.
+func (h *histogram) total() (total int64) {
+ if h.valueCount >= 0 {
+ total = h.valueCount
+ }
+ for _, val := range h.buckets {
+ total += int64(val)
+ }
+ return
+}
+
+// Average returns the average value of recorded observations.
+func (h *histogram) average() float64 {
+ t := h.total()
+ if t == 0 {
+ return 0
+ }
+ return float64(h.sum) / float64(t)
+}
+
+// Variance returns the variance of recorded observations.
+func (h *histogram) variance() float64 {
+ t := float64(h.total())
+ if t == 0 {
+ return 0
+ }
+ s := float64(h.sum) / t
+ return h.sumOfSquares/t - s*s
+}
+
+// StandardDeviation returns the standard deviation of recorded observations.
+func (h *histogram) standardDeviation() float64 {
+ return math.Sqrt(h.variance())
+}
+
+// PercentileBoundary estimates the value that the given fraction of recorded
+// observations are less than.
+func (h *histogram) percentileBoundary(percentile float64) int64 {
+ total := h.total()
+
+ // Corner cases (make sure result is strictly less than Total())
+ if total == 0 {
+ return 0
+ } else if total == 1 {
+ return int64(h.average())
+ }
+
+ percentOfTotal := round(float64(total) * percentile)
+ var runningTotal int64
+
+ for i := range h.buckets {
+ value := h.buckets[i]
+ runningTotal += value
+ if runningTotal == percentOfTotal {
+ // We hit an exact bucket boundary. If the next bucket has data, it is a
+ // good estimate of the value. If the bucket is empty, we interpolate the
+ // midpoint between the next bucket's boundary and the next non-zero
+ // bucket. If the remaining buckets are all empty, then we use the
+ // boundary for the next bucket as the estimate.
+ j := uint8(i + 1)
+ min := bucketBoundary(j)
+ if runningTotal < total {
+ for h.buckets[j] == 0 {
+ j++
+ }
+ }
+ max := bucketBoundary(j)
+ return min + round(float64(max-min)/2)
+ } else if runningTotal > percentOfTotal {
+ // The value is in this bucket. Interpolate the value.
+ delta := runningTotal - percentOfTotal
+ percentBucket := float64(value-delta) / float64(value)
+ bucketMin := bucketBoundary(uint8(i))
+ nextBucketMin := bucketBoundary(uint8(i + 1))
+ bucketSize := nextBucketMin - bucketMin
+ return bucketMin + round(percentBucket*float64(bucketSize))
+ }
+ }
+ return bucketBoundary(bucketCount - 1)
+}
+
+// Median returns the estimated median of the observed values.
+func (h *histogram) median() int64 {
+ return h.percentileBoundary(0.5)
+}
+
+// Add adds other to h.
+func (h *histogram) Add(other timeseries.Observable) {
+ o := other.(*histogram)
+ if o.valueCount == 0 {
+ // Other histogram is empty
+ } else if h.valueCount >= 0 && o.valueCount > 0 && h.value == o.value {
+ // Both have a single bucketed value, aggregate them
+ h.valueCount += o.valueCount
+ } else {
+ // Two different values necessitate buckets in this histogram
+ h.allocateBuckets()
+ if o.valueCount >= 0 {
+ h.buckets[o.value] += o.valueCount
+ } else {
+ for i := range h.buckets {
+ h.buckets[i] += o.buckets[i]
+ }
+ }
+ }
+ h.sumOfSquares += o.sumOfSquares
+ h.sum += o.sum
+}
+
+// Clear resets the histogram to an empty state, removing all observed values.
+func (h *histogram) Clear() {
+ h.buckets = nil
+ h.value = 0
+ h.valueCount = 0
+ h.sum = 0
+ h.sumOfSquares = 0
+}
+
+// CopyFrom copies from other, which must be a *histogram, into h.
+func (h *histogram) CopyFrom(other timeseries.Observable) {
+ o := other.(*histogram)
+ if o.valueCount == -1 {
+ h.allocateBuckets()
+ copy(h.buckets, o.buckets)
+ }
+ h.sum = o.sum
+ h.sumOfSquares = o.sumOfSquares
+ h.value = o.value
+ h.valueCount = o.valueCount
+}
+
+// Multiply scales the histogram by the specified ratio.
+func (h *histogram) Multiply(ratio float64) {
+ if h.valueCount == -1 {
+ for i := range h.buckets {
+ h.buckets[i] = int64(float64(h.buckets[i]) * ratio)
+ }
+ } else {
+ h.valueCount = int64(float64(h.valueCount) * ratio)
+ }
+ h.sum = int64(float64(h.sum) * ratio)
+ h.sumOfSquares = h.sumOfSquares * ratio
+}
+
+// New creates a new histogram.
+func (h *histogram) New() timeseries.Observable {
+ r := new(histogram)
+ r.Clear()
+ return r
+}
+
+func (h *histogram) String() string {
+ return fmt.Sprintf("%d, %f, %d, %d, %v",
+ h.sum, h.sumOfSquares, h.value, h.valueCount, h.buckets)
+}
+
+// round returns the closest int64 to the argument
+func round(in float64) int64 {
+ return int64(math.Floor(in + 0.5))
+}
+
+// bucketBoundary returns the first value in the bucket.
+func bucketBoundary(bucket uint8) int64 {
+ if bucket == 0 {
+ return 0
+ }
+ return 1 << bucket
+}
+
+// bucketData holds data about a specific bucket for use in distTmpl.
+type bucketData struct {
+ Lower, Upper int64
+ N int64
+ Pct, CumulativePct float64
+ GraphWidth int
+}
+
+// data holds data about a Distribution for use in distTmpl.
+type data struct {
+ Buckets []*bucketData
+ Count, Median int64
+ Mean, StandardDeviation float64
+}
+
+// maxHTMLBarWidth is the maximum width of the HTML bar for visualizing buckets.
+const maxHTMLBarWidth = 350.0
+
+// newData returns data representing h for use in distTmpl.
+func (h *histogram) newData() *data {
+ // Force the allocation of buckets to simplify the rendering implementation
+ h.allocateBuckets()
+ // We scale the bars on the right so that the largest bar is
+ // maxHTMLBarWidth pixels in width.
+ maxBucket := int64(0)
+ for _, n := range h.buckets {
+ if n > maxBucket {
+ maxBucket = n
+ }
+ }
+ total := h.total()
+ barsizeMult := maxHTMLBarWidth / float64(maxBucket)
+ var pctMult float64
+ if total == 0 {
+ pctMult = 1.0
+ } else {
+ pctMult = 100.0 / float64(total)
+ }
+
+ buckets := make([]*bucketData, len(h.buckets))
+ runningTotal := int64(0)
+ for i, n := range h.buckets {
+ if n == 0 {
+ continue
+ }
+ runningTotal += n
+ var upperBound int64
+ if i < bucketCount-1 {
+ upperBound = bucketBoundary(uint8(i + 1))
+ } else {
+ upperBound = math.MaxInt64
+ }
+ buckets[i] = &bucketData{
+ Lower: bucketBoundary(uint8(i)),
+ Upper: upperBound,
+ N: n,
+ Pct: float64(n) * pctMult,
+ CumulativePct: float64(runningTotal) * pctMult,
+ GraphWidth: int(float64(n) * barsizeMult),
+ }
+ }
+ return &data{
+ Buckets: buckets,
+ Count: total,
+ Median: h.median(),
+ Mean: h.average(),
+ StandardDeviation: h.standardDeviation(),
+ }
+}
+
+func (h *histogram) html() template.HTML {
+ buf := new(bytes.Buffer)
+ if err := distTmpl().Execute(buf, h.newData()); err != nil {
+ buf.Reset()
+ log.Printf("net/trace: couldn't execute template: %v", err)
+ }
+ return template.HTML(buf.String())
+}
+
+var distTmplCache *template.Template
+var distTmplOnce sync.Once
+
+func distTmpl() *template.Template {
+ distTmplOnce.Do(func() {
+ // Input: data
+ distTmplCache = template.Must(template.New("distTmpl").Parse(`
+<table>
+<tr>
+ <td style="padding:0.25em">Count: {{.Count}}</td>
+ <td style="padding:0.25em">Mean: {{printf "%.0f" .Mean}}</td>
+ <td style="padding:0.25em">StdDev: {{printf "%.0f" .StandardDeviation}}</td>
+ <td style="padding:0.25em">Median: {{.Median}}</td>
+</tr>
+</table>
+<hr>
+<table>
+{{range $b := .Buckets}}
+{{if $b}}
+ <tr>
+ <td style="padding:0 0 0 0.25em">[</td>
+ <td style="text-align:right;padding:0 0.25em">{{.Lower}},</td>
+ <td style="text-align:right;padding:0 0.25em">{{.Upper}})</td>
+ <td style="text-align:right;padding:0 0.25em">{{.N}}</td>
+ <td style="text-align:right;padding:0 0.25em">{{printf "%#.3f" .Pct}}%</td>
+ <td style="text-align:right;padding:0 0.25em">{{printf "%#.3f" .CumulativePct}}%</td>
+ <td><div style="background-color: blue; height: 1em; width: {{.GraphWidth}};"></div></td>
+ </tr>
+{{end}}
+{{end}}
+</table>
+`))
+ })
+ return distTmplCache
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package trace implements tracing of requests and long-lived objects.
+It exports HTTP interfaces on /debug/requests and /debug/events.
+
+A trace.Trace provides tracing for short-lived objects, usually requests.
+A request handler might be implemented like this:
+
+ func fooHandler(w http.ResponseWriter, req *http.Request) {
+ tr := trace.New("mypkg.Foo", req.URL.Path)
+ defer tr.Finish()
+ ...
+ tr.LazyPrintf("some event %q happened", str)
+ ...
+ if err := somethingImportant(); err != nil {
+ tr.LazyPrintf("somethingImportant failed: %v", err)
+ tr.SetError()
+ }
+ }
+
+The /debug/requests HTTP endpoint organizes the traces by family,
+errors, and duration. It also provides histogram of request duration
+for each family.
+
+A trace.EventLog provides tracing for long-lived objects, such as RPC
+connections.
+
+ // A Fetcher fetches URL paths for a single domain.
+ type Fetcher struct {
+ domain string
+ events trace.EventLog
+ }
+
+ func NewFetcher(domain string) *Fetcher {
+ return &Fetcher{
+ domain,
+ trace.NewEventLog("mypkg.Fetcher", domain),
+ }
+ }
+
+ func (f *Fetcher) Fetch(path string) (string, error) {
+ resp, err := http.Get("http://" + f.domain + "/" + path)
+ if err != nil {
+ f.events.Errorf("Get(%q) = %v", path, err)
+ return "", err
+ }
+ f.events.Printf("Get(%q) = %s", path, resp.Status)
+ ...
+ }
+
+ func (f *Fetcher) Close() error {
+ f.events.Finish()
+ return nil
+ }
+
+The /debug/events HTTP endpoint organizes the event logs by family and
+by time since the last error. The expanded view displays recent log
+entries and the log's call stack.
+*/
+package trace // import "golang.org/x/net/trace"
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "io"
+ "log"
+ "net"
+ "net/http"
+ "runtime"
+ "sort"
+ "strconv"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "golang.org/x/net/internal/timeseries"
+)
+
+// DebugUseAfterFinish controls whether to debug uses of Trace values after finishing.
+// FOR DEBUGGING ONLY. This will slow down the program.
+var DebugUseAfterFinish = false
+
+// AuthRequest determines whether a specific request is permitted to load the
+// /debug/requests or /debug/events pages.
+//
+// It returns two bools; the first indicates whether the page may be viewed at all,
+// and the second indicates whether sensitive events will be shown.
+//
+// AuthRequest may be replaced by a program to customize its authorization requirements.
+//
+// The default AuthRequest function returns (true, true) if and only if the request
+// comes from localhost/127.0.0.1/[::1].
+var AuthRequest = func(req *http.Request) (any, sensitive bool) {
+ // RemoteAddr is commonly in the form "IP" or "IP:port".
+ // If it is in the form "IP:port", split off the port.
+ host, _, err := net.SplitHostPort(req.RemoteAddr)
+ if err != nil {
+ host = req.RemoteAddr
+ }
+ switch host {
+ case "localhost", "127.0.0.1", "::1":
+ return true, true
+ default:
+ return false, false
+ }
+}
+
+func init() {
+ // TODO(jbd): Serve Traces from /debug/traces in the future?
+ // There is no requirement for a request to be present to have traces.
+ http.HandleFunc("/debug/requests", Traces)
+ http.HandleFunc("/debug/events", Events)
+}
+
+// Traces responds with traces from the program.
+// The package initialization registers it in http.DefaultServeMux
+// at /debug/requests.
+//
+// It performs authorization by running AuthRequest.
+func Traces(w http.ResponseWriter, req *http.Request) {
+ any, sensitive := AuthRequest(req)
+ if !any {
+ http.Error(w, "not allowed", http.StatusUnauthorized)
+ return
+ }
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ Render(w, req, sensitive)
+}
+
+// Events responds with a page of events collected by EventLogs.
+// The package initialization registers it in http.DefaultServeMux
+// at /debug/events.
+//
+// It performs authorization by running AuthRequest.
+func Events(w http.ResponseWriter, req *http.Request) {
+ any, sensitive := AuthRequest(req)
+ if !any {
+ http.Error(w, "not allowed", http.StatusUnauthorized)
+ return
+ }
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ RenderEvents(w, req, sensitive)
+}
+
+// Render renders the HTML page typically served at /debug/requests.
+// It does not do any auth checking. The request may be nil.
+//
+// Most users will use the Traces handler.
+func Render(w io.Writer, req *http.Request, sensitive bool) {
+ data := &struct {
+ Families []string
+ ActiveTraceCount map[string]int
+ CompletedTraces map[string]*family
+
+ // Set when a bucket has been selected.
+ Traces traceList
+ Family string
+ Bucket int
+ Expanded bool
+ Traced bool
+ Active bool
+ ShowSensitive bool // whether to show sensitive events
+
+ Histogram template.HTML
+ HistogramWindow string // e.g. "last minute", "last hour", "all time"
+
+ // If non-zero, the set of traces is a partial set,
+ // and this is the total number.
+ Total int
+ }{
+ CompletedTraces: completedTraces,
+ }
+
+ data.ShowSensitive = sensitive
+ if req != nil {
+ // Allow show_sensitive=0 to force hiding of sensitive data for testing.
+ // This only goes one way; you can't use show_sensitive=1 to see things.
+ if req.FormValue("show_sensitive") == "0" {
+ data.ShowSensitive = false
+ }
+
+ if exp, err := strconv.ParseBool(req.FormValue("exp")); err == nil {
+ data.Expanded = exp
+ }
+ if exp, err := strconv.ParseBool(req.FormValue("rtraced")); err == nil {
+ data.Traced = exp
+ }
+ }
+
+ completedMu.RLock()
+ data.Families = make([]string, 0, len(completedTraces))
+ for fam := range completedTraces {
+ data.Families = append(data.Families, fam)
+ }
+ completedMu.RUnlock()
+ sort.Strings(data.Families)
+
+ // We are careful here to minimize the time spent locking activeMu,
+ // since that lock is required every time an RPC starts and finishes.
+ data.ActiveTraceCount = make(map[string]int, len(data.Families))
+ activeMu.RLock()
+ for fam, s := range activeTraces {
+ data.ActiveTraceCount[fam] = s.Len()
+ }
+ activeMu.RUnlock()
+
+ var ok bool
+ data.Family, data.Bucket, ok = parseArgs(req)
+ switch {
+ case !ok:
+ // No-op
+ case data.Bucket == -1:
+ data.Active = true
+ n := data.ActiveTraceCount[data.Family]
+ data.Traces = getActiveTraces(data.Family)
+ if len(data.Traces) < n {
+ data.Total = n
+ }
+ case data.Bucket < bucketsPerFamily:
+ if b := lookupBucket(data.Family, data.Bucket); b != nil {
+ data.Traces = b.Copy(data.Traced)
+ }
+ default:
+ if f := getFamily(data.Family, false); f != nil {
+ var obs timeseries.Observable
+ f.LatencyMu.RLock()
+ switch o := data.Bucket - bucketsPerFamily; o {
+ case 0:
+ obs = f.Latency.Minute()
+ data.HistogramWindow = "last minute"
+ case 1:
+ obs = f.Latency.Hour()
+ data.HistogramWindow = "last hour"
+ case 2:
+ obs = f.Latency.Total()
+ data.HistogramWindow = "all time"
+ }
+ f.LatencyMu.RUnlock()
+ if obs != nil {
+ data.Histogram = obs.(*histogram).html()
+ }
+ }
+ }
+
+ if data.Traces != nil {
+ defer data.Traces.Free()
+ sort.Sort(data.Traces)
+ }
+
+ completedMu.RLock()
+ defer completedMu.RUnlock()
+ if err := pageTmpl().ExecuteTemplate(w, "Page", data); err != nil {
+ log.Printf("net/trace: Failed executing template: %v", err)
+ }
+}
+
+func parseArgs(req *http.Request) (fam string, b int, ok bool) {
+ if req == nil {
+ return "", 0, false
+ }
+ fam, bStr := req.FormValue("fam"), req.FormValue("b")
+ if fam == "" || bStr == "" {
+ return "", 0, false
+ }
+ b, err := strconv.Atoi(bStr)
+ if err != nil || b < -1 {
+ return "", 0, false
+ }
+
+ return fam, b, true
+}
+
+func lookupBucket(fam string, b int) *traceBucket {
+ f := getFamily(fam, false)
+ if f == nil || b < 0 || b >= len(f.Buckets) {
+ return nil
+ }
+ return f.Buckets[b]
+}
+
+type contextKeyT string
+
+var contextKey = contextKeyT("golang.org/x/net/trace.Trace")
+
+// Trace represents an active request.
+type Trace interface {
+ // LazyLog adds x to the event log. It will be evaluated each time the
+ // /debug/requests page is rendered. Any memory referenced by x will be
+ // pinned until the trace is finished and later discarded.
+ LazyLog(x fmt.Stringer, sensitive bool)
+
+ // LazyPrintf evaluates its arguments with fmt.Sprintf each time the
+ // /debug/requests page is rendered. Any memory referenced by a will be
+ // pinned until the trace is finished and later discarded.
+ LazyPrintf(format string, a ...interface{})
+
+ // SetError declares that this trace resulted in an error.
+ SetError()
+
+ // SetRecycler sets a recycler for the trace.
+ // f will be called for each event passed to LazyLog at a time when
+ // it is no longer required, whether while the trace is still active
+ // and the event is discarded, or when a completed trace is discarded.
+ SetRecycler(f func(interface{}))
+
+ // SetTraceInfo sets the trace info for the trace.
+ // This is currently unused.
+ SetTraceInfo(traceID, spanID uint64)
+
+ // SetMaxEvents sets the maximum number of events that will be stored
+ // in the trace. This has no effect if any events have already been
+ // added to the trace.
+ SetMaxEvents(m int)
+
+ // Finish declares that this trace is complete.
+ // The trace should not be used after calling this method.
+ Finish()
+}
+
+type lazySprintf struct {
+ format string
+ a []interface{}
+}
+
+func (l *lazySprintf) String() string {
+ return fmt.Sprintf(l.format, l.a...)
+}
+
+// New returns a new Trace with the specified family and title.
+func New(family, title string) Trace {
+ tr := newTrace()
+ tr.ref()
+ tr.Family, tr.Title = family, title
+ tr.Start = time.Now()
+ tr.maxEvents = maxEventsPerTrace
+ tr.events = tr.eventsBuf[:0]
+
+ activeMu.RLock()
+ s := activeTraces[tr.Family]
+ activeMu.RUnlock()
+ if s == nil {
+ activeMu.Lock()
+ s = activeTraces[tr.Family] // check again
+ if s == nil {
+ s = new(traceSet)
+ activeTraces[tr.Family] = s
+ }
+ activeMu.Unlock()
+ }
+ s.Add(tr)
+
+ // Trigger allocation of the completed trace structure for this family.
+ // This will cause the family to be present in the request page during
+ // the first trace of this family. We don't care about the return value,
+ // nor is there any need for this to run inline, so we execute it in its
+ // own goroutine, but only if the family isn't allocated yet.
+ completedMu.RLock()
+ if _, ok := completedTraces[tr.Family]; !ok {
+ go allocFamily(tr.Family)
+ }
+ completedMu.RUnlock()
+
+ return tr
+}
+
+func (tr *trace) Finish() {
+ elapsed := time.Now().Sub(tr.Start)
+ tr.mu.Lock()
+ tr.Elapsed = elapsed
+ tr.mu.Unlock()
+
+ if DebugUseAfterFinish {
+ buf := make([]byte, 4<<10) // 4 KB should be enough
+ n := runtime.Stack(buf, false)
+ tr.finishStack = buf[:n]
+ }
+
+ activeMu.RLock()
+ m := activeTraces[tr.Family]
+ activeMu.RUnlock()
+ m.Remove(tr)
+
+ f := getFamily(tr.Family, true)
+ tr.mu.RLock() // protects tr fields in Cond.match calls
+ for _, b := range f.Buckets {
+ if b.Cond.match(tr) {
+ b.Add(tr)
+ }
+ }
+ tr.mu.RUnlock()
+
+ // Add a sample of elapsed time as microseconds to the family's timeseries
+ h := new(histogram)
+ h.addMeasurement(elapsed.Nanoseconds() / 1e3)
+ f.LatencyMu.Lock()
+ f.Latency.Add(h)
+ f.LatencyMu.Unlock()
+
+ tr.unref() // matches ref in New
+}
+
+const (
+ bucketsPerFamily = 9
+ tracesPerBucket = 10
+ maxActiveTraces = 20 // Maximum number of active traces to show.
+ maxEventsPerTrace = 10
+ numHistogramBuckets = 38
+)
+
+var (
+ // The active traces.
+ activeMu sync.RWMutex
+ activeTraces = make(map[string]*traceSet) // family -> traces
+
+ // Families of completed traces.
+ completedMu sync.RWMutex
+ completedTraces = make(map[string]*family) // family -> traces
+)
+
+type traceSet struct {
+ mu sync.RWMutex
+ m map[*trace]bool
+
+ // We could avoid the entire map scan in FirstN by having a slice of all the traces
+ // ordered by start time, and an index into that from the trace struct, with a periodic
+ // repack of the slice after enough traces finish; we could also use a skip list or similar.
+ // However, that would shift some of the expense from /debug/requests time to RPC time,
+ // which is probably the wrong trade-off.
+}
+
+func (ts *traceSet) Len() int {
+ ts.mu.RLock()
+ defer ts.mu.RUnlock()
+ return len(ts.m)
+}
+
+func (ts *traceSet) Add(tr *trace) {
+ ts.mu.Lock()
+ if ts.m == nil {
+ ts.m = make(map[*trace]bool)
+ }
+ ts.m[tr] = true
+ ts.mu.Unlock()
+}
+
+func (ts *traceSet) Remove(tr *trace) {
+ ts.mu.Lock()
+ delete(ts.m, tr)
+ ts.mu.Unlock()
+}
+
+// FirstN returns the first n traces ordered by time.
+func (ts *traceSet) FirstN(n int) traceList {
+ ts.mu.RLock()
+ defer ts.mu.RUnlock()
+
+ if n > len(ts.m) {
+ n = len(ts.m)
+ }
+ trl := make(traceList, 0, n)
+
+ // Fast path for when no selectivity is needed.
+ if n == len(ts.m) {
+ for tr := range ts.m {
+ tr.ref()
+ trl = append(trl, tr)
+ }
+ sort.Sort(trl)
+ return trl
+ }
+
+ // Pick the oldest n traces.
+ // This is inefficient. See the comment in the traceSet struct.
+ for tr := range ts.m {
+ // Put the first n traces into trl in the order they occur.
+ // When we have n, sort trl, and thereafter maintain its order.
+ if len(trl) < n {
+ tr.ref()
+ trl = append(trl, tr)
+ if len(trl) == n {
+ // This is guaranteed to happen exactly once during this loop.
+ sort.Sort(trl)
+ }
+ continue
+ }
+ if tr.Start.After(trl[n-1].Start) {
+ continue
+ }
+
+ // Find where to insert this one.
+ tr.ref()
+ i := sort.Search(n, func(i int) bool { return trl[i].Start.After(tr.Start) })
+ trl[n-1].unref()
+ copy(trl[i+1:], trl[i:])
+ trl[i] = tr
+ }
+
+ return trl
+}
+
+func getActiveTraces(fam string) traceList {
+ activeMu.RLock()
+ s := activeTraces[fam]
+ activeMu.RUnlock()
+ if s == nil {
+ return nil
+ }
+ return s.FirstN(maxActiveTraces)
+}
+
+func getFamily(fam string, allocNew bool) *family {
+ completedMu.RLock()
+ f := completedTraces[fam]
+ completedMu.RUnlock()
+ if f == nil && allocNew {
+ f = allocFamily(fam)
+ }
+ return f
+}
+
+func allocFamily(fam string) *family {
+ completedMu.Lock()
+ defer completedMu.Unlock()
+ f := completedTraces[fam]
+ if f == nil {
+ f = newFamily()
+ completedTraces[fam] = f
+ }
+ return f
+}
+
+// family represents a set of trace buckets and associated latency information.
+type family struct {
+ // traces may occur in multiple buckets.
+ Buckets [bucketsPerFamily]*traceBucket
+
+ // latency time series
+ LatencyMu sync.RWMutex
+ Latency *timeseries.MinuteHourSeries
+}
+
+func newFamily() *family {
+ return &family{
+ Buckets: [bucketsPerFamily]*traceBucket{
+ {Cond: minCond(0)},
+ {Cond: minCond(50 * time.Millisecond)},
+ {Cond: minCond(100 * time.Millisecond)},
+ {Cond: minCond(200 * time.Millisecond)},
+ {Cond: minCond(500 * time.Millisecond)},
+ {Cond: minCond(1 * time.Second)},
+ {Cond: minCond(10 * time.Second)},
+ {Cond: minCond(100 * time.Second)},
+ {Cond: errorCond{}},
+ },
+ Latency: timeseries.NewMinuteHourSeries(func() timeseries.Observable { return new(histogram) }),
+ }
+}
+
+// traceBucket represents a size-capped bucket of historic traces,
+// along with a condition for a trace to belong to the bucket.
+type traceBucket struct {
+ Cond cond
+
+ // Ring buffer implementation of a fixed-size FIFO queue.
+ mu sync.RWMutex
+ buf [tracesPerBucket]*trace
+ start int // < tracesPerBucket
+ length int // <= tracesPerBucket
+}
+
+func (b *traceBucket) Add(tr *trace) {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+
+ i := b.start + b.length
+ if i >= tracesPerBucket {
+ i -= tracesPerBucket
+ }
+ if b.length == tracesPerBucket {
+ // "Remove" an element from the bucket.
+ b.buf[i].unref()
+ b.start++
+ if b.start == tracesPerBucket {
+ b.start = 0
+ }
+ }
+ b.buf[i] = tr
+ if b.length < tracesPerBucket {
+ b.length++
+ }
+ tr.ref()
+}
+
+// Copy returns a copy of the traces in the bucket.
+// If tracedOnly is true, only the traces with trace information will be returned.
+// The logs will be ref'd before returning; the caller should call
+// the Free method when it is done with them.
+// TODO(dsymonds): keep track of traced requests in separate buckets.
+func (b *traceBucket) Copy(tracedOnly bool) traceList {
+ b.mu.RLock()
+ defer b.mu.RUnlock()
+
+ trl := make(traceList, 0, b.length)
+ for i, x := 0, b.start; i < b.length; i++ {
+ tr := b.buf[x]
+ if !tracedOnly || tr.spanID != 0 {
+ tr.ref()
+ trl = append(trl, tr)
+ }
+ x++
+ if x == b.length {
+ x = 0
+ }
+ }
+ return trl
+}
+
+func (b *traceBucket) Empty() bool {
+ b.mu.RLock()
+ defer b.mu.RUnlock()
+ return b.length == 0
+}
+
+// cond represents a condition on a trace.
+type cond interface {
+ match(t *trace) bool
+ String() string
+}
+
+type minCond time.Duration
+
+func (m minCond) match(t *trace) bool { return t.Elapsed >= time.Duration(m) }
+func (m minCond) String() string { return fmt.Sprintf("≥%gs", time.Duration(m).Seconds()) }
+
+type errorCond struct{}
+
+func (e errorCond) match(t *trace) bool { return t.IsError }
+func (e errorCond) String() string { return "errors" }
+
+type traceList []*trace
+
+// Free calls unref on each element of the list.
+func (trl traceList) Free() {
+ for _, t := range trl {
+ t.unref()
+ }
+}
+
+// traceList may be sorted in reverse chronological order.
+func (trl traceList) Len() int { return len(trl) }
+func (trl traceList) Less(i, j int) bool { return trl[i].Start.After(trl[j].Start) }
+func (trl traceList) Swap(i, j int) { trl[i], trl[j] = trl[j], trl[i] }
+
+// An event is a timestamped log entry in a trace.
+type event struct {
+ When time.Time
+ Elapsed time.Duration // since previous event in trace
+ NewDay bool // whether this event is on a different day to the previous event
+ Recyclable bool // whether this event was passed via LazyLog
+ Sensitive bool // whether this event contains sensitive information
+ What interface{} // string or fmt.Stringer
+}
+
+// WhenString returns a string representation of the elapsed time of the event.
+// It will include the date if midnight was crossed.
+func (e event) WhenString() string {
+ if e.NewDay {
+ return e.When.Format("2006/01/02 15:04:05.000000")
+ }
+ return e.When.Format("15:04:05.000000")
+}
+
+// discarded represents a number of discarded events.
+// It is stored as *discarded to make it easier to update in-place.
+type discarded int
+
+func (d *discarded) String() string {
+ return fmt.Sprintf("(%d events discarded)", int(*d))
+}
+
+// trace represents an active or complete request,
+// either sent or received by this program.
+type trace struct {
+ // Family is the top-level grouping of traces to which this belongs.
+ Family string
+
+ // Title is the title of this trace.
+ Title string
+
+ // Start time of the this trace.
+ Start time.Time
+
+ mu sync.RWMutex
+ events []event // Append-only sequence of events (modulo discards).
+ maxEvents int
+ recycler func(interface{})
+ IsError bool // Whether this trace resulted in an error.
+ Elapsed time.Duration // Elapsed time for this trace, zero while active.
+ traceID uint64 // Trace information if non-zero.
+ spanID uint64
+
+ refs int32 // how many buckets this is in
+ disc discarded // scratch space to avoid allocation
+
+ finishStack []byte // where finish was called, if DebugUseAfterFinish is set
+
+ eventsBuf [4]event // preallocated buffer in case we only log a few events
+}
+
+func (tr *trace) reset() {
+ // Clear all but the mutex. Mutexes may not be copied, even when unlocked.
+ tr.Family = ""
+ tr.Title = ""
+ tr.Start = time.Time{}
+
+ tr.mu.Lock()
+ tr.Elapsed = 0
+ tr.traceID = 0
+ tr.spanID = 0
+ tr.IsError = false
+ tr.maxEvents = 0
+ tr.events = nil
+ tr.recycler = nil
+ tr.mu.Unlock()
+
+ tr.refs = 0
+ tr.disc = 0
+ tr.finishStack = nil
+ for i := range tr.eventsBuf {
+ tr.eventsBuf[i] = event{}
+ }
+}
+
+// delta returns the elapsed time since the last event or the trace start,
+// and whether it spans midnight.
+// L >= tr.mu
+func (tr *trace) delta(t time.Time) (time.Duration, bool) {
+ if len(tr.events) == 0 {
+ return t.Sub(tr.Start), false
+ }
+ prev := tr.events[len(tr.events)-1].When
+ return t.Sub(prev), prev.Day() != t.Day()
+}
+
+func (tr *trace) addEvent(x interface{}, recyclable, sensitive bool) {
+ if DebugUseAfterFinish && tr.finishStack != nil {
+ buf := make([]byte, 4<<10) // 4 KB should be enough
+ n := runtime.Stack(buf, false)
+ log.Printf("net/trace: trace used after finish:\nFinished at:\n%s\nUsed at:\n%s", tr.finishStack, buf[:n])
+ }
+
+ /*
+ NOTE TO DEBUGGERS
+
+ If you are here because your program panicked in this code,
+ it is almost definitely the fault of code using this package,
+ and very unlikely to be the fault of this code.
+
+ The most likely scenario is that some code elsewhere is using
+ a trace.Trace after its Finish method is called.
+ You can temporarily set the DebugUseAfterFinish var
+ to help discover where that is; do not leave that var set,
+ since it makes this package much less efficient.
+ */
+
+ e := event{When: time.Now(), What: x, Recyclable: recyclable, Sensitive: sensitive}
+ tr.mu.Lock()
+ e.Elapsed, e.NewDay = tr.delta(e.When)
+ if len(tr.events) < tr.maxEvents {
+ tr.events = append(tr.events, e)
+ } else {
+ // Discard the middle events.
+ di := int((tr.maxEvents - 1) / 2)
+ if d, ok := tr.events[di].What.(*discarded); ok {
+ (*d)++
+ } else {
+ // disc starts at two to count for the event it is replacing,
+ // plus the next one that we are about to drop.
+ tr.disc = 2
+ if tr.recycler != nil && tr.events[di].Recyclable {
+ go tr.recycler(tr.events[di].What)
+ }
+ tr.events[di].What = &tr.disc
+ }
+ // The timestamp of the discarded meta-event should be
+ // the time of the last event it is representing.
+ tr.events[di].When = tr.events[di+1].When
+
+ if tr.recycler != nil && tr.events[di+1].Recyclable {
+ go tr.recycler(tr.events[di+1].What)
+ }
+ copy(tr.events[di+1:], tr.events[di+2:])
+ tr.events[tr.maxEvents-1] = e
+ }
+ tr.mu.Unlock()
+}
+
+func (tr *trace) LazyLog(x fmt.Stringer, sensitive bool) {
+ tr.addEvent(x, true, sensitive)
+}
+
+func (tr *trace) LazyPrintf(format string, a ...interface{}) {
+ tr.addEvent(&lazySprintf{format, a}, false, false)
+}
+
+func (tr *trace) SetError() {
+ tr.mu.Lock()
+ tr.IsError = true
+ tr.mu.Unlock()
+}
+
+func (tr *trace) SetRecycler(f func(interface{})) {
+ tr.mu.Lock()
+ tr.recycler = f
+ tr.mu.Unlock()
+}
+
+func (tr *trace) SetTraceInfo(traceID, spanID uint64) {
+ tr.mu.Lock()
+ tr.traceID, tr.spanID = traceID, spanID
+ tr.mu.Unlock()
+}
+
+func (tr *trace) SetMaxEvents(m int) {
+ tr.mu.Lock()
+ // Always keep at least three events: first, discarded count, last.
+ if len(tr.events) == 0 && m > 3 {
+ tr.maxEvents = m
+ }
+ tr.mu.Unlock()
+}
+
+func (tr *trace) ref() {
+ atomic.AddInt32(&tr.refs, 1)
+}
+
+func (tr *trace) unref() {
+ if atomic.AddInt32(&tr.refs, -1) == 0 {
+ tr.mu.RLock()
+ if tr.recycler != nil {
+ // freeTrace clears tr, so we hold tr.recycler and tr.events here.
+ go func(f func(interface{}), es []event) {
+ for _, e := range es {
+ if e.Recyclable {
+ f(e.What)
+ }
+ }
+ }(tr.recycler, tr.events)
+ }
+ tr.mu.RUnlock()
+
+ freeTrace(tr)
+ }
+}
+
+func (tr *trace) When() string {
+ return tr.Start.Format("2006/01/02 15:04:05.000000")
+}
+
+func (tr *trace) ElapsedTime() string {
+ tr.mu.RLock()
+ t := tr.Elapsed
+ tr.mu.RUnlock()
+
+ if t == 0 {
+ // Active trace.
+ t = time.Since(tr.Start)
+ }
+ return fmt.Sprintf("%.6f", t.Seconds())
+}
+
+func (tr *trace) Events() []event {
+ tr.mu.RLock()
+ defer tr.mu.RUnlock()
+ return tr.events
+}
+
+var traceFreeList = make(chan *trace, 1000) // TODO(dsymonds): Use sync.Pool?
+
+// newTrace returns a trace ready to use.
+func newTrace() *trace {
+ select {
+ case tr := <-traceFreeList:
+ return tr
+ default:
+ return new(trace)
+ }
+}
+
+// freeTrace adds tr to traceFreeList if there's room.
+// This is non-blocking.
+func freeTrace(tr *trace) {
+ if DebugUseAfterFinish {
+ return // never reuse
+ }
+ tr.reset()
+ select {
+ case traceFreeList <- tr:
+ default:
+ }
+}
+
+func elapsed(d time.Duration) string {
+ b := []byte(fmt.Sprintf("%.6f", d.Seconds()))
+
+ // For subsecond durations, blank all zeros before decimal point,
+ // and all zeros between the decimal point and the first non-zero digit.
+ if d < time.Second {
+ dot := bytes.IndexByte(b, '.')
+ for i := 0; i < dot; i++ {
+ b[i] = ' '
+ }
+ for i := dot + 1; i < len(b); i++ {
+ if b[i] == '0' {
+ b[i] = ' '
+ } else {
+ break
+ }
+ }
+ }
+
+ return string(b)
+}
+
+var pageTmplCache *template.Template
+var pageTmplOnce sync.Once
+
+func pageTmpl() *template.Template {
+ pageTmplOnce.Do(func() {
+ pageTmplCache = template.Must(template.New("Page").Funcs(template.FuncMap{
+ "elapsed": elapsed,
+ "add": func(a, b int) int { return a + b },
+ }).Parse(pageHTML))
+ })
+ return pageTmplCache
+}
+
+const pageHTML = `
+{{template "Prolog" .}}
+{{template "StatusTable" .}}
+{{template "Epilog" .}}
+
+{{define "Prolog"}}
+<html>
+ <head>
+ <title>/debug/requests</title>
+ <style type="text/css">
+ body {
+ font-family: sans-serif;
+ }
+ table#tr-status td.family {
+ padding-right: 2em;
+ }
+ table#tr-status td.active {
+ padding-right: 1em;
+ }
+ table#tr-status td.latency-first {
+ padding-left: 1em;
+ }
+ table#tr-status td.empty {
+ color: #aaa;
+ }
+ table#reqs {
+ margin-top: 1em;
+ }
+ table#reqs tr.first {
+ {{if $.Expanded}}font-weight: bold;{{end}}
+ }
+ table#reqs td {
+ font-family: monospace;
+ }
+ table#reqs td.when {
+ text-align: right;
+ white-space: nowrap;
+ }
+ table#reqs td.elapsed {
+ padding: 0 0.5em;
+ text-align: right;
+ white-space: pre;
+ width: 10em;
+ }
+ address {
+ font-size: smaller;
+ margin-top: 5em;
+ }
+ </style>
+ </head>
+ <body>
+
+<h1>/debug/requests</h1>
+{{end}} {{/* end of Prolog */}}
+
+{{define "StatusTable"}}
+<table id="tr-status">
+ {{range $fam := .Families}}
+ <tr>
+ <td class="family">{{$fam}}</td>
+
+ {{$n := index $.ActiveTraceCount $fam}}
+ <td class="active {{if not $n}}empty{{end}}">
+ {{if $n}}<a href="?fam={{$fam}}&b=-1{{if $.Expanded}}&exp=1{{end}}">{{end}}
+ [{{$n}} active]
+ {{if $n}}</a>{{end}}
+ </td>
+
+ {{$f := index $.CompletedTraces $fam}}
+ {{range $i, $b := $f.Buckets}}
+ {{$empty := $b.Empty}}
+ <td {{if $empty}}class="empty"{{end}}>
+ {{if not $empty}}<a href="?fam={{$fam}}&b={{$i}}{{if $.Expanded}}&exp=1{{end}}">{{end}}
+ [{{.Cond}}]
+ {{if not $empty}}</a>{{end}}
+ </td>
+ {{end}}
+
+ {{$nb := len $f.Buckets}}
+ <td class="latency-first">
+ <a href="?fam={{$fam}}&b={{$nb}}">[minute]</a>
+ </td>
+ <td>
+ <a href="?fam={{$fam}}&b={{add $nb 1}}">[hour]</a>
+ </td>
+ <td>
+ <a href="?fam={{$fam}}&b={{add $nb 2}}">[total]</a>
+ </td>
+
+ </tr>
+ {{end}}
+</table>
+{{end}} {{/* end of StatusTable */}}
+
+{{define "Epilog"}}
+{{if $.Traces}}
+<hr />
+<h3>Family: {{$.Family}}</h3>
+
+{{if or $.Expanded $.Traced}}
+ <a href="?fam={{$.Family}}&b={{$.Bucket}}">[Normal/Summary]</a>
+{{else}}
+ [Normal/Summary]
+{{end}}
+
+{{if or (not $.Expanded) $.Traced}}
+ <a href="?fam={{$.Family}}&b={{$.Bucket}}&exp=1">[Normal/Expanded]</a>
+{{else}}
+ [Normal/Expanded]
+{{end}}
+
+{{if not $.Active}}
+ {{if or $.Expanded (not $.Traced)}}
+ <a href="?fam={{$.Family}}&b={{$.Bucket}}&rtraced=1">[Traced/Summary]</a>
+ {{else}}
+ [Traced/Summary]
+ {{end}}
+ {{if or (not $.Expanded) (not $.Traced)}}
+ <a href="?fam={{$.Family}}&b={{$.Bucket}}&exp=1&rtraced=1">[Traced/Expanded]</a>
+ {{else}}
+ [Traced/Expanded]
+ {{end}}
+{{end}}
+
+{{if $.Total}}
+<p><em>Showing <b>{{len $.Traces}}</b> of <b>{{$.Total}}</b> traces.</em></p>
+{{end}}
+
+<table id="reqs">
+ <caption>
+ {{if $.Active}}Active{{else}}Completed{{end}} Requests
+ </caption>
+ <tr><th>When</th><th>Elapsed (s)</th></tr>
+ {{range $tr := $.Traces}}
+ <tr class="first">
+ <td class="when">{{$tr.When}}</td>
+ <td class="elapsed">{{$tr.ElapsedTime}}</td>
+ <td>{{$tr.Title}}</td>
+ {{/* TODO: include traceID/spanID */}}
+ </tr>
+ {{if $.Expanded}}
+ {{range $tr.Events}}
+ <tr>
+ <td class="when">{{.WhenString}}</td>
+ <td class="elapsed">{{elapsed .Elapsed}}</td>
+ <td>{{if or $.ShowSensitive (not .Sensitive)}}... {{.What}}{{else}}<em>[redacted]</em>{{end}}</td>
+ </tr>
+ {{end}}
+ {{end}}
+ {{end}}
+</table>
+{{end}} {{/* if $.Traces */}}
+
+{{if $.Histogram}}
+<h4>Latency (µs) of {{$.Family}} over {{$.HistogramWindow}}</h4>
+{{$.Histogram}}
+{{end}} {{/* if $.Histogram */}}
+
+ </body>
+</html>
+{{end}} {{/* end of Epilog */}}
+`
--- /dev/null
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.7
+
+package trace
+
+import "golang.org/x/net/context"
+
+// NewContext returns a copy of the parent context
+// and associates it with a Trace.
+func NewContext(ctx context.Context, tr Trace) context.Context {
+ return context.WithValue(ctx, contextKey, tr)
+}
+
+// FromContext returns the Trace bound to the context, if any.
+func FromContext(ctx context.Context) (tr Trace, ok bool) {
+ tr, ok = ctx.Value(contextKey).(Trace)
+ return
+}
--- /dev/null
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.7
+
+package trace
+
+import "context"
+
+// NewContext returns a copy of the parent context
+// and associates it with a Trace.
+func NewContext(ctx context.Context, tr Trace) context.Context {
+ return context.WithValue(ctx, contextKey, tr)
+}
+
+// FromContext returns the Trace bound to the context, if any.
+func FromContext(ctx context.Context) (tr Trace, ok bool) {
+ tr, ok = ctx.Value(contextKey).(Trace)
+ return
+}
--- /dev/null
+Copyright (C) 2014 Alec Thomas
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
--- /dev/null
+# Kingpin - A Go (golang) command line and flag parser
+[](http://godoc.org/github.com/alecthomas/kingpin) [](https://travis-ci.org/alecthomas/kingpin) [](https://gitter.im/alecthomas/Lobby)
+
+
+
+<!-- MarkdownTOC -->
+
+- [Overview](#overview)
+- [Features](#features)
+- [User-visible changes between v1 and v2](#user-visible-changes-between-v1-and-v2)
+ - [Flags can be used at any point after their definition.](#flags-can-be-used-at-any-point-after-their-definition)
+ - [Short flags can be combined with their parameters](#short-flags-can-be-combined-with-their-parameters)
+- [API changes between v1 and v2](#api-changes-between-v1-and-v2)
+- [Versions](#versions)
+ - [V2 is the current stable version](#v2-is-the-current-stable-version)
+ - [V1 is the OLD stable version](#v1-is-the-old-stable-version)
+- [Change History](#change-history)
+- [Examples](#examples)
+ - [Simple Example](#simple-example)
+ - [Complex Example](#complex-example)
+- [Reference Documentation](#reference-documentation)
+ - [Displaying errors and usage information](#displaying-errors-and-usage-information)
+ - [Sub-commands](#sub-commands)
+ - [Custom Parsers](#custom-parsers)
+ - [Repeatable flags](#repeatable-flags)
+ - [Boolean Values](#boolean-values)
+ - [Default Values](#default-values)
+ - [Place-holders in Help](#place-holders-in-help)
+ - [Consuming all remaining arguments](#consuming-all-remaining-arguments)
+ - [Bash/ZSH Shell Completion](#bashzsh-shell-completion)
+ - [Supporting -h for help](#supporting--h-for-help)
+ - [Custom help](#custom-help)
+
+<!-- /MarkdownTOC -->
+
+## Overview
+
+Kingpin is a [fluent-style](http://en.wikipedia.org/wiki/Fluent_interface),
+type-safe command-line parser. It supports flags, nested commands, and
+positional arguments.
+
+Install it with:
+
+ $ go get gopkg.in/alecthomas/kingpin.v2
+
+It looks like this:
+
+```go
+var (
+ verbose = kingpin.Flag("verbose", "Verbose mode.").Short('v').Bool()
+ name = kingpin.Arg("name", "Name of user.").Required().String()
+)
+
+func main() {
+ kingpin.Parse()
+ fmt.Printf("%v, %s\n", *verbose, *name)
+}
+```
+
+More [examples](https://github.com/alecthomas/kingpin/tree/master/_examples) are available.
+
+Second to parsing, providing the user with useful help is probably the most
+important thing a command-line parser does. Kingpin tries to provide detailed
+contextual help if `--help` is encountered at any point in the command line
+(excluding after `--`).
+
+## Features
+
+- Help output that isn't as ugly as sin.
+- Fully [customisable help](#custom-help), via Go templates.
+- Parsed, type-safe flags (`kingpin.Flag("f", "help").Int()`)
+- Parsed, type-safe positional arguments (`kingpin.Arg("a", "help").Int()`).
+- Parsed, type-safe, arbitrarily deep commands (`kingpin.Command("c", "help")`).
+- Support for required flags and required positional arguments (`kingpin.Flag("f", "").Required().Int()`).
+- Support for arbitrarily nested default commands (`command.Default()`).
+- Callbacks per command, flag and argument (`kingpin.Command("c", "").Action(myAction)`).
+- POSIX-style short flag combining (`-a -b` -> `-ab`).
+- Short-flag+parameter combining (`-a parm` -> `-aparm`).
+- Read command-line from files (`@<file>`).
+- Automatically generate man pages (`--help-man`).
+
+## User-visible changes between v1 and v2
+
+### Flags can be used at any point after their definition.
+
+Flags can be specified at any point after their definition, not just
+*immediately after their associated command*. From the chat example below, the
+following used to be required:
+
+```
+$ chat --server=chat.server.com:8080 post --image=~/Downloads/owls.jpg pics
+```
+
+But the following will now work:
+
+```
+$ chat post --server=chat.server.com:8080 --image=~/Downloads/owls.jpg pics
+```
+
+### Short flags can be combined with their parameters
+
+Previously, if a short flag was used, any argument to that flag would have to
+be separated by a space. That is no longer the case.
+
+## API changes between v1 and v2
+
+- `ParseWithFileExpansion()` is gone. The new parser directly supports expanding `@<file>`.
+- Added `FatalUsage()` and `FatalUsageContext()` for displaying an error + usage and terminating.
+- `Dispatch()` renamed to `Action()`.
+- Added `ParseContext()` for parsing a command line into its intermediate context form without executing.
+- Added `Terminate()` function to override the termination function.
+- Added `UsageForContextWithTemplate()` for printing usage via a custom template.
+- Added `UsageTemplate()` for overriding the default template to use. Two templates are included:
+ 1. `DefaultUsageTemplate` - default template.
+ 2. `CompactUsageTemplate` - compact command template for larger applications.
+
+## Versions
+
+Kingpin uses [gopkg.in](https://gopkg.in/alecthomas/kingpin) for versioning.
+
+The current stable version is [gopkg.in/alecthomas/kingpin.v2](https://gopkg.in/alecthomas/kingpin.v2). The previous version, [gopkg.in/alecthomas/kingpin.v1](https://gopkg.in/alecthomas/kingpin.v1), is deprecated and in maintenance mode.
+
+### [V2](https://gopkg.in/alecthomas/kingpin.v2) is the current stable version
+
+Installation:
+
+```sh
+$ go get gopkg.in/alecthomas/kingpin.v2
+```
+
+### [V1](https://gopkg.in/alecthomas/kingpin.v1) is the OLD stable version
+
+Installation:
+
+```sh
+$ go get gopkg.in/alecthomas/kingpin.v1
+```
+
+## Change History
+
+- *2015-09-19* -- Stable v2.1.0 release.
+ - Added `command.Default()` to specify a default command to use if no other
+ command matches. This allows for convenient user shortcuts.
+ - Exposed `HelpFlag` and `VersionFlag` for further customisation.
+ - `Action()` and `PreAction()` added and both now support an arbitrary
+ number of callbacks.
+ - `kingpin.SeparateOptionalFlagsUsageTemplate`.
+ - `--help-long` and `--help-man` (hidden by default) flags.
+ - Flags are "interspersed" by default, but can be disabled with `app.Interspersed(false)`.
+ - Added flags for all simple builtin types (int8, uint16, etc.) and slice variants.
+ - Use `app.Writer(os.Writer)` to specify the default writer for all output functions.
+ - Dropped `os.Writer` prefix from all printf-like functions.
+
+- *2015-05-22* -- Stable v2.0.0 release.
+ - Initial stable release of v2.0.0.
+ - Fully supports interspersed flags, commands and arguments.
+ - Flags can be present at any point after their logical definition.
+ - Application.Parse() terminates if commands are present and a command is not parsed.
+ - Dispatch() -> Action().
+ - Actions are dispatched after all values are populated.
+ - Override termination function (defaults to os.Exit).
+ - Override output stream (defaults to os.Stderr).
+ - Templatised usage help, with default and compact templates.
+ - Make error/usage functions more consistent.
+ - Support argument expansion from files by default (with @<file>).
+ - Fully public data model is available via .Model().
+ - Parser has been completely refactored.
+ - Parsing and execution has been split into distinct stages.
+ - Use `go generate` to generate repeated flags.
+ - Support combined short-flag+argument: -fARG.
+
+- *2015-01-23* -- Stable v1.3.4 release.
+ - Support "--" for separating flags from positional arguments.
+ - Support loading flags from files (ParseWithFileExpansion()). Use @FILE as an argument.
+ - Add post-app and post-cmd validation hooks. This allows arbitrary validation to be added.
+ - A bunch of improvements to help usage and formatting.
+ - Support arbitrarily nested sub-commands.
+
+- *2014-07-08* -- Stable v1.2.0 release.
+ - Pass any value through to `Strings()` when final argument.
+ Allows for values that look like flags to be processed.
+ - Allow `--help` to be used with commands.
+ - Support `Hidden()` flags.
+ - Parser for [units.Base2Bytes](https://github.com/alecthomas/units)
+ type. Allows for flags like `--ram=512MB` or `--ram=1GB`.
+ - Add an `Enum()` value, allowing only one of a set of values
+ to be selected. eg. `Flag(...).Enum("debug", "info", "warning")`.
+
+- *2014-06-27* -- Stable v1.1.0 release.
+ - Bug fixes.
+ - Always return an error (rather than panicing) when misconfigured.
+ - `OpenFile(flag, perm)` value type added, for finer control over opening files.
+ - Significantly improved usage formatting.
+
+- *2014-06-19* -- Stable v1.0.0 release.
+ - Support [cumulative positional](#consuming-all-remaining-arguments) arguments.
+ - Return error rather than panic when there are fatal errors not caught by
+ the type system. eg. when a default value is invalid.
+ - Use gokpg.in.
+
+- *2014-06-10* -- Place-holder streamlining.
+ - Renamed `MetaVar` to `PlaceHolder`.
+ - Removed `MetaVarFromDefault`. Kingpin now uses [heuristics](#place-holders-in-help)
+ to determine what to display.
+
+## Examples
+
+### Simple Example
+
+Kingpin can be used for simple flag+arg applications like so:
+
+```
+$ ping --help
+usage: ping [<flags>] <ip> [<count>]
+
+Flags:
+ --debug Enable debug mode.
+ --help Show help.
+ -t, --timeout=5s Timeout waiting for ping.
+
+Args:
+ <ip> IP address to ping.
+ [<count>] Number of packets to send
+$ ping 1.2.3.4 5
+Would ping: 1.2.3.4 with timeout 5s and count 5
+```
+
+From the following source:
+
+```go
+package main
+
+import (
+ "fmt"
+
+ "gopkg.in/alecthomas/kingpin.v2"
+)
+
+var (
+ debug = kingpin.Flag("debug", "Enable debug mode.").Bool()
+ timeout = kingpin.Flag("timeout", "Timeout waiting for ping.").Default("5s").OverrideDefaultFromEnvar("PING_TIMEOUT").Short('t').Duration()
+ ip = kingpin.Arg("ip", "IP address to ping.").Required().IP()
+ count = kingpin.Arg("count", "Number of packets to send").Int()
+)
+
+func main() {
+ kingpin.Version("0.0.1")
+ kingpin.Parse()
+ fmt.Printf("Would ping: %s with timeout %s and count %d\n", *ip, *timeout, *count)
+}
+```
+
+### Complex Example
+
+Kingpin can also produce complex command-line applications with global flags,
+subcommands, and per-subcommand flags, like this:
+
+```
+$ chat --help
+usage: chat [<flags>] <command> [<flags>] [<args> ...]
+
+A command-line chat application.
+
+Flags:
+ --help Show help.
+ --debug Enable debug mode.
+ --server=127.0.0.1 Server address.
+
+Commands:
+ help [<command>]
+ Show help for a command.
+
+ register <nick> <name>
+ Register a new user.
+
+ post [<flags>] <channel> [<text>]
+ Post a message to a channel.
+
+$ chat help post
+usage: chat [<flags>] post [<flags>] <channel> [<text>]
+
+Post a message to a channel.
+
+Flags:
+ --image=IMAGE Image to post.
+
+Args:
+ <channel> Channel to post to.
+ [<text>] Text to post.
+
+$ chat post --image=~/Downloads/owls.jpg pics
+...
+```
+
+From this code:
+
+```go
+package main
+
+import (
+ "os"
+ "strings"
+ "gopkg.in/alecthomas/kingpin.v2"
+)
+
+var (
+ app = kingpin.New("chat", "A command-line chat application.")
+ debug = app.Flag("debug", "Enable debug mode.").Bool()
+ serverIP = app.Flag("server", "Server address.").Default("127.0.0.1").IP()
+
+ register = app.Command("register", "Register a new user.")
+ registerNick = register.Arg("nick", "Nickname for user.").Required().String()
+ registerName = register.Arg("name", "Name of user.").Required().String()
+
+ post = app.Command("post", "Post a message to a channel.")
+ postImage = post.Flag("image", "Image to post.").File()
+ postChannel = post.Arg("channel", "Channel to post to.").Required().String()
+ postText = post.Arg("text", "Text to post.").Strings()
+)
+
+func main() {
+ switch kingpin.MustParse(app.Parse(os.Args[1:])) {
+ // Register user
+ case register.FullCommand():
+ println(*registerNick)
+
+ // Post message
+ case post.FullCommand():
+ if *postImage != nil {
+ }
+ text := strings.Join(*postText, " ")
+ println("Post:", text)
+ }
+}
+```
+
+## Reference Documentation
+
+### Displaying errors and usage information
+
+Kingpin exports a set of functions to provide consistent errors and usage
+information to the user.
+
+Error messages look something like this:
+
+ <app>: error: <message>
+
+The functions on `Application` are:
+
+Function | Purpose
+---------|--------------
+`Errorf(format, args)` | Display a printf formatted error to the user.
+`Fatalf(format, args)` | As with Errorf, but also call the termination handler.
+`FatalUsage(format, args)` | As with Fatalf, but also print contextual usage information.
+`FatalUsageContext(context, format, args)` | As with Fatalf, but also print contextual usage information from a `ParseContext`.
+`FatalIfError(err, format, args)` | Conditionally print an error prefixed with format+args, then call the termination handler
+
+There are equivalent global functions in the kingpin namespace for the default
+`kingpin.CommandLine` instance.
+
+### Sub-commands
+
+Kingpin supports nested sub-commands, with separate flag and positional
+arguments per sub-command. Note that positional arguments may only occur after
+sub-commands.
+
+For example:
+
+```go
+var (
+ deleteCommand = kingpin.Command("delete", "Delete an object.")
+ deleteUserCommand = deleteCommand.Command("user", "Delete a user.")
+ deleteUserUIDFlag = deleteUserCommand.Flag("uid", "Delete user by UID rather than username.")
+ deleteUserUsername = deleteUserCommand.Arg("username", "Username to delete.")
+ deletePostCommand = deleteCommand.Command("post", "Delete a post.")
+)
+
+func main() {
+ switch kingpin.Parse() {
+ case "delete user":
+ case "delete post":
+ }
+}
+```
+
+### Custom Parsers
+
+Kingpin supports both flag and positional argument parsers for converting to
+Go types. For example, some included parsers are `Int()`, `Float()`,
+`Duration()` and `ExistingFile()` (see [parsers.go](./parsers.go) for a complete list of included parsers).
+
+Parsers conform to Go's [`flag.Value`](http://godoc.org/flag#Value)
+interface, so any existing implementations will work.
+
+For example, a parser for accumulating HTTP header values might look like this:
+
+```go
+type HTTPHeaderValue http.Header
+
+func (h *HTTPHeaderValue) Set(value string) error {
+ parts := strings.SplitN(value, ":", 2)
+ if len(parts) != 2 {
+ return fmt.Errorf("expected HEADER:VALUE got '%s'", value)
+ }
+ (*http.Header)(h).Add(parts[0], parts[1])
+ return nil
+}
+
+func (h *HTTPHeaderValue) String() string {
+ return ""
+}
+```
+
+As a convenience, I would recommend something like this:
+
+```go
+func HTTPHeader(s Settings) (target *http.Header) {
+ target = &http.Header{}
+ s.SetValue((*HTTPHeaderValue)(target))
+ return
+}
+```
+
+You would use it like so:
+
+```go
+headers = HTTPHeader(kingpin.Flag("header", "Add a HTTP header to the request.").Short('H'))
+```
+
+### Repeatable flags
+
+Depending on the `Value` they hold, some flags may be repeated. The
+`IsCumulative() bool` function on `Value` tells if it's safe to call `Set()`
+multiple times or if an error should be raised if several values are passed.
+
+The built-in `Value`s returning slices and maps, as well as `Counter` are
+examples of `Value`s that make a flag repeatable.
+
+### Boolean values
+
+Boolean values are uniquely managed by Kingpin. Each boolean flag will have a negative complement:
+`--<name>` and `--no-<name>`.
+
+### Default Values
+
+The default value is the zero value for a type. This can be overridden with
+the `Default(value...)` function on flags and arguments. This function accepts
+one or several strings, which are parsed by the value itself, so they *must*
+be compliant with the format expected.
+
+### Place-holders in Help
+
+The place-holder value for a flag is the value used in the help to describe
+the value of a non-boolean flag.
+
+The value provided to PlaceHolder() is used if provided, then the value
+provided by Default() if provided, then finally the capitalised flag name is
+used.
+
+Here are some examples of flags with various permutations:
+
+ --name=NAME // Flag(...).String()
+ --name="Harry" // Flag(...).Default("Harry").String()
+ --name=FULL-NAME // Flag(...).PlaceHolder("FULL-NAME").Default("Harry").String()
+
+### Consuming all remaining arguments
+
+A common command-line idiom is to use all remaining arguments for some
+purpose. eg. The following command accepts an arbitrary number of
+IP addresses as positional arguments:
+
+ ./cmd ping 10.1.1.1 192.168.1.1
+
+Such arguments are similar to [repeatable flags](#repeatable-flags), but for
+arguments. Therefore they use the same `IsCumulative() bool` function on the
+underlying `Value`, so the built-in `Value`s for which the `Set()` function
+can be called several times will consume multiple arguments.
+
+To implement the above example with a custom `Value`, we might do something
+like this:
+
+```go
+type ipList []net.IP
+
+func (i *ipList) Set(value string) error {
+ if ip := net.ParseIP(value); ip == nil {
+ return fmt.Errorf("'%s' is not an IP address", value)
+ } else {
+ *i = append(*i, ip)
+ return nil
+ }
+}
+
+func (i *ipList) String() string {
+ return ""
+}
+
+func (i *ipList) IsCumulative() bool {
+ return true
+}
+
+func IPList(s Settings) (target *[]net.IP) {
+ target = new([]net.IP)
+ s.SetValue((*ipList)(target))
+ return
+}
+```
+
+And use it like so:
+
+```go
+ips := IPList(kingpin.Arg("ips", "IP addresses to ping."))
+```
+
+### Bash/ZSH Shell Completion
+
+By default, all flags and commands/subcommands generate completions
+internally.
+
+Out of the box, CLI tools using kingpin should be able to take advantage
+of completion hinting for flags and commands. By specifying
+`--completion-bash` as the first argument, your CLI tool will show
+possible subcommands. By ending your argv with `--`, hints for flags
+will be shown.
+
+To allow your end users to take advantage you must package a
+`/etc/bash_completion.d` script with your distribution (or the equivalent
+for your target platform/shell). An alternative is to instruct your end
+user to source a script from their `bash_profile` (or equivalent).
+
+Fortunately Kingpin makes it easy to generate or source a script for use
+with end users shells. `./yourtool --completion-script-bash` and
+`./yourtool --completion-script-zsh` will generate these scripts for you.
+
+**Installation by Package**
+
+For the best user experience, you should bundle your pre-created
+completion script with your CLI tool and install it inside
+`/etc/bash_completion.d` (or equivalent). A good suggestion is to add
+this as an automated step to your build pipeline, in the implementation
+is improved for bug fixed.
+
+**Installation by `bash_profile`**
+
+Alternatively, instruct your users to add an additional statement to
+their `bash_profile` (or equivalent):
+
+```
+eval "$(your-cli-tool --completion-script-bash)"
+```
+
+Or for ZSH
+
+```
+eval "$(your-cli-tool --completion-script-zsh)"
+```
+
+#### Additional API
+To provide more flexibility, a completion option API has been
+exposed for flags to allow user defined completion options, to extend
+completions further than just EnumVar/Enum.
+
+
+**Provide Static Options**
+
+When using an `Enum` or `EnumVar`, users are limited to only the options
+given. Maybe we wish to hint possible options to the user, but also
+allow them to provide their own custom option. `HintOptions` gives
+this functionality to flags.
+
+```
+app := kingpin.New("completion", "My application with bash completion.")
+app.Flag("port", "Provide a port to connect to").
+ Required().
+ HintOptions("80", "443", "8080").
+ IntVar(&c.port)
+```
+
+**Provide Dynamic Options**
+Consider the case that you needed to read a local database or a file to
+provide suggestions. You can dynamically generate the options
+
+```
+func listHosts() []string {
+ // Provide a dynamic list of hosts from a hosts file or otherwise
+ // for bash completion. In this example we simply return static slice.
+
+ // You could use this functionality to reach into a hosts file to provide
+ // completion for a list of known hosts.
+ return []string{"sshhost.example", "webhost.example", "ftphost.example"}
+}
+
+app := kingpin.New("completion", "My application with bash completion.")
+app.Flag("flag-1", "").HintAction(listHosts).String()
+```
+
+**EnumVar/Enum**
+When using `Enum` or `EnumVar`, any provided options will be automatically
+used for bash autocompletion. However, if you wish to provide a subset or
+different options, you can use `HintOptions` or `HintAction` which will override
+the default completion options for `Enum`/`EnumVar`.
+
+
+**Examples**
+You can see an in depth example of the completion API within
+`examples/completion/main.go`
+
+
+### Supporting -h for help
+
+`kingpin.CommandLine.HelpFlag.Short('h')`
+
+### Custom help
+
+Kingpin v2 supports templatised help using the text/template library (actually, [a fork](https://github.com/alecthomas/template)).
+
+You can specify the template to use with the [Application.UsageTemplate()](http://godoc.org/gopkg.in/alecthomas/kingpin.v2#Application.UsageTemplate) function.
+
+There are four included templates: `kingpin.DefaultUsageTemplate` is the default,
+`kingpin.CompactUsageTemplate` provides a more compact representation for more complex command-line structures,
+`kingpin.SeparateOptionalFlagsUsageTemplate` looks like the default template, but splits required
+and optional command flags into separate lists, and `kingpin.ManPageTemplate` is used to generate man pages.
+
+See the above templates for examples of usage, and the the function [UsageForContextWithTemplate()](https://github.com/alecthomas/kingpin/blob/master/usage.go#L198) method for details on the context.
+
+#### Default help template
+
+```
+$ go run ./examples/curl/curl.go --help
+usage: curl [<flags>] <command> [<args> ...]
+
+An example implementation of curl.
+
+Flags:
+ --help Show help.
+ -t, --timeout=5s Set connection timeout.
+ -H, --headers=HEADER=VALUE
+ Add HTTP headers to the request.
+
+Commands:
+ help [<command>...]
+ Show help.
+
+ get url <url>
+ Retrieve a URL.
+
+ get file <file>
+ Retrieve a file.
+
+ post [<flags>] <url>
+ POST a resource.
+```
+
+#### Compact help template
+
+```
+$ go run ./examples/curl/curl.go --help
+usage: curl [<flags>] <command> [<args> ...]
+
+An example implementation of curl.
+
+Flags:
+ --help Show help.
+ -t, --timeout=5s Set connection timeout.
+ -H, --headers=HEADER=VALUE
+ Add HTTP headers to the request.
+
+Commands:
+ help [<command>...]
+ get [<flags>]
+ url <url>
+ file <file>
+ post [<flags>] <url>
+```
--- /dev/null
+package kingpin
+
+// Action callback executed at various stages after all values are populated.
+// The application, commands, arguments and flags all have corresponding
+// actions.
+type Action func(*ParseContext) error
+
+type actionMixin struct {
+ actions []Action
+ preActions []Action
+}
+
+type actionApplier interface {
+ applyActions(*ParseContext) error
+ applyPreActions(*ParseContext) error
+}
+
+func (a *actionMixin) addAction(action Action) {
+ a.actions = append(a.actions, action)
+}
+
+func (a *actionMixin) addPreAction(action Action) {
+ a.preActions = append(a.preActions, action)
+}
+
+func (a *actionMixin) applyActions(context *ParseContext) error {
+ for _, action := range a.actions {
+ if err := action(context); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (a *actionMixin) applyPreActions(context *ParseContext) error {
+ for _, preAction := range a.preActions {
+ if err := preAction(context); err != nil {
+ return err
+ }
+ }
+ return nil
+}
--- /dev/null
+package kingpin
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "regexp"
+ "strings"
+)
+
+var (
+ ErrCommandNotSpecified = fmt.Errorf("command not specified")
+)
+
+var (
+ envarTransformRegexp = regexp.MustCompile(`[^a-zA-Z0-9_]+`)
+)
+
+type ApplicationValidator func(*Application) error
+
+// An Application contains the definitions of flags, arguments and commands
+// for an application.
+type Application struct {
+ cmdMixin
+ initialized bool
+
+ Name string
+ Help string
+
+ author string
+ version string
+ errorWriter io.Writer // Destination for errors.
+ usageWriter io.Writer // Destination for usage
+ usageTemplate string
+ validator ApplicationValidator
+ terminate func(status int) // See Terminate()
+ noInterspersed bool // can flags be interspersed with args (or must they come first)
+ defaultEnvars bool
+ completion bool
+
+ // Help flag. Exposed for user customisation.
+ HelpFlag *FlagClause
+ // Help command. Exposed for user customisation. May be nil.
+ HelpCommand *CmdClause
+ // Version flag. Exposed for user customisation. May be nil.
+ VersionFlag *FlagClause
+}
+
+// New creates a new Kingpin application instance.
+func New(name, help string) *Application {
+ a := &Application{
+ Name: name,
+ Help: help,
+ errorWriter: os.Stderr, // Left for backwards compatibility purposes.
+ usageWriter: os.Stderr,
+ usageTemplate: DefaultUsageTemplate,
+ terminate: os.Exit,
+ }
+ a.flagGroup = newFlagGroup()
+ a.argGroup = newArgGroup()
+ a.cmdGroup = newCmdGroup(a)
+ a.HelpFlag = a.Flag("help", "Show context-sensitive help (also try --help-long and --help-man).")
+ a.HelpFlag.Bool()
+ a.Flag("help-long", "Generate long help.").Hidden().PreAction(a.generateLongHelp).Bool()
+ a.Flag("help-man", "Generate a man page.").Hidden().PreAction(a.generateManPage).Bool()
+ a.Flag("completion-bash", "Output possible completions for the given args.").Hidden().BoolVar(&a.completion)
+ a.Flag("completion-script-bash", "Generate completion script for bash.").Hidden().PreAction(a.generateBashCompletionScript).Bool()
+ a.Flag("completion-script-zsh", "Generate completion script for ZSH.").Hidden().PreAction(a.generateZSHCompletionScript).Bool()
+
+ return a
+}
+
+func (a *Application) generateLongHelp(c *ParseContext) error {
+ a.Writer(os.Stdout)
+ if err := a.UsageForContextWithTemplate(c, 2, LongHelpTemplate); err != nil {
+ return err
+ }
+ a.terminate(0)
+ return nil
+}
+
+func (a *Application) generateManPage(c *ParseContext) error {
+ a.Writer(os.Stdout)
+ if err := a.UsageForContextWithTemplate(c, 2, ManPageTemplate); err != nil {
+ return err
+ }
+ a.terminate(0)
+ return nil
+}
+
+func (a *Application) generateBashCompletionScript(c *ParseContext) error {
+ a.Writer(os.Stdout)
+ if err := a.UsageForContextWithTemplate(c, 2, BashCompletionTemplate); err != nil {
+ return err
+ }
+ a.terminate(0)
+ return nil
+}
+
+func (a *Application) generateZSHCompletionScript(c *ParseContext) error {
+ a.Writer(os.Stdout)
+ if err := a.UsageForContextWithTemplate(c, 2, ZshCompletionTemplate); err != nil {
+ return err
+ }
+ a.terminate(0)
+ return nil
+}
+
+// DefaultEnvars configures all flags (that do not already have an associated
+// envar) to use a default environment variable in the form "<app>_<flag>".
+//
+// For example, if the application is named "foo" and a flag is named "bar-
+// waz" the environment variable: "FOO_BAR_WAZ".
+func (a *Application) DefaultEnvars() *Application {
+ a.defaultEnvars = true
+ return a
+}
+
+// Terminate specifies the termination handler. Defaults to os.Exit(status).
+// If nil is passed, a no-op function will be used.
+func (a *Application) Terminate(terminate func(int)) *Application {
+ if terminate == nil {
+ terminate = func(int) {}
+ }
+ a.terminate = terminate
+ return a
+}
+
+// Writer specifies the writer to use for usage and errors. Defaults to os.Stderr.
+// DEPRECATED: See ErrorWriter and UsageWriter.
+func (a *Application) Writer(w io.Writer) *Application {
+ a.errorWriter = w
+ a.usageWriter = w
+ return a
+}
+
+// ErrorWriter sets the io.Writer to use for errors.
+func (a *Application) ErrorWriter(w io.Writer) *Application {
+ a.errorWriter = w
+ return a
+}
+
+// UsageWriter sets the io.Writer to use for errors.
+func (a *Application) UsageWriter(w io.Writer) *Application {
+ a.usageWriter = w
+ return a
+}
+
+// UsageTemplate specifies the text template to use when displaying usage
+// information. The default is UsageTemplate.
+func (a *Application) UsageTemplate(template string) *Application {
+ a.usageTemplate = template
+ return a
+}
+
+// Validate sets a validation function to run when parsing.
+func (a *Application) Validate(validator ApplicationValidator) *Application {
+ a.validator = validator
+ return a
+}
+
+// ParseContext parses the given command line and returns the fully populated
+// ParseContext.
+func (a *Application) ParseContext(args []string) (*ParseContext, error) {
+ return a.parseContext(false, args)
+}
+
+func (a *Application) parseContext(ignoreDefault bool, args []string) (*ParseContext, error) {
+ if err := a.init(); err != nil {
+ return nil, err
+ }
+ context := tokenize(args, ignoreDefault)
+ err := parse(context, a)
+ return context, err
+}
+
+// Parse parses command-line arguments. It returns the selected command and an
+// error. The selected command will be a space separated subcommand, if
+// subcommands have been configured.
+//
+// This will populate all flag and argument values, call all callbacks, and so
+// on.
+func (a *Application) Parse(args []string) (command string, err error) {
+
+ context, parseErr := a.ParseContext(args)
+ selected := []string{}
+ var setValuesErr error
+
+ if context == nil {
+ // Since we do not throw error immediately, there could be a case
+ // where a context returns nil. Protect against that.
+ return "", parseErr
+ }
+
+ if err = a.setDefaults(context); err != nil {
+ return "", err
+ }
+
+ selected, setValuesErr = a.setValues(context)
+
+ if err = a.applyPreActions(context, !a.completion); err != nil {
+ return "", err
+ }
+
+ if a.completion {
+ a.generateBashCompletion(context)
+ a.terminate(0)
+ } else {
+ if parseErr != nil {
+ return "", parseErr
+ }
+
+ a.maybeHelp(context)
+ if !context.EOL() {
+ return "", fmt.Errorf("unexpected argument '%s'", context.Peek())
+ }
+
+ if setValuesErr != nil {
+ return "", setValuesErr
+ }
+
+ command, err = a.execute(context, selected)
+ if err == ErrCommandNotSpecified {
+ a.writeUsage(context, nil)
+ }
+ }
+ return command, err
+}
+
+func (a *Application) writeUsage(context *ParseContext, err error) {
+ if err != nil {
+ a.Errorf("%s", err)
+ }
+ if err := a.UsageForContext(context); err != nil {
+ panic(err)
+ }
+ if err != nil {
+ a.terminate(1)
+ } else {
+ a.terminate(0)
+ }
+}
+
+func (a *Application) maybeHelp(context *ParseContext) {
+ for _, element := range context.Elements {
+ if flag, ok := element.Clause.(*FlagClause); ok && flag == a.HelpFlag {
+ // Re-parse the command-line ignoring defaults, so that help works correctly.
+ context, _ = a.parseContext(true, context.rawArgs)
+ a.writeUsage(context, nil)
+ }
+ }
+}
+
+// Version adds a --version flag for displaying the application version.
+func (a *Application) Version(version string) *Application {
+ a.version = version
+ a.VersionFlag = a.Flag("version", "Show application version.").PreAction(func(*ParseContext) error {
+ fmt.Fprintln(a.usageWriter, version)
+ a.terminate(0)
+ return nil
+ })
+ a.VersionFlag.Bool()
+ return a
+}
+
+// Author sets the author output by some help templates.
+func (a *Application) Author(author string) *Application {
+ a.author = author
+ return a
+}
+
+// Action callback to call when all values are populated and parsing is
+// complete, but before any command, flag or argument actions.
+//
+// All Action() callbacks are called in the order they are encountered on the
+// command line.
+func (a *Application) Action(action Action) *Application {
+ a.addAction(action)
+ return a
+}
+
+// Action called after parsing completes but before validation and execution.
+func (a *Application) PreAction(action Action) *Application {
+ a.addPreAction(action)
+ return a
+}
+
+// Command adds a new top-level command.
+func (a *Application) Command(name, help string) *CmdClause {
+ return a.addCommand(name, help)
+}
+
+// Interspersed control if flags can be interspersed with positional arguments
+//
+// true (the default) means that they can, false means that all the flags must appear before the first positional arguments.
+func (a *Application) Interspersed(interspersed bool) *Application {
+ a.noInterspersed = !interspersed
+ return a
+}
+
+func (a *Application) defaultEnvarPrefix() string {
+ if a.defaultEnvars {
+ return a.Name
+ }
+ return ""
+}
+
+func (a *Application) init() error {
+ if a.initialized {
+ return nil
+ }
+ if a.cmdGroup.have() && a.argGroup.have() {
+ return fmt.Errorf("can't mix top-level Arg()s with Command()s")
+ }
+
+ // If we have subcommands, add a help command at the top-level.
+ if a.cmdGroup.have() {
+ var command []string
+ a.HelpCommand = a.Command("help", "Show help.").PreAction(func(context *ParseContext) error {
+ a.Usage(command)
+ a.terminate(0)
+ return nil
+ })
+ a.HelpCommand.Arg("command", "Show help on command.").StringsVar(&command)
+ // Make help first command.
+ l := len(a.commandOrder)
+ a.commandOrder = append(a.commandOrder[l-1:l], a.commandOrder[:l-1]...)
+ }
+
+ if err := a.flagGroup.init(a.defaultEnvarPrefix()); err != nil {
+ return err
+ }
+ if err := a.cmdGroup.init(); err != nil {
+ return err
+ }
+ if err := a.argGroup.init(); err != nil {
+ return err
+ }
+ for _, cmd := range a.commands {
+ if err := cmd.init(); err != nil {
+ return err
+ }
+ }
+ flagGroups := []*flagGroup{a.flagGroup}
+ for _, cmd := range a.commandOrder {
+ if err := checkDuplicateFlags(cmd, flagGroups); err != nil {
+ return err
+ }
+ }
+ a.initialized = true
+ return nil
+}
+
+// Recursively check commands for duplicate flags.
+func checkDuplicateFlags(current *CmdClause, flagGroups []*flagGroup) error {
+ // Check for duplicates.
+ for _, flags := range flagGroups {
+ for _, flag := range current.flagOrder {
+ if flag.shorthand != 0 {
+ if _, ok := flags.short[string(flag.shorthand)]; ok {
+ return fmt.Errorf("duplicate short flag -%c", flag.shorthand)
+ }
+ }
+ if _, ok := flags.long[flag.name]; ok {
+ return fmt.Errorf("duplicate long flag --%s", flag.name)
+ }
+ }
+ }
+ flagGroups = append(flagGroups, current.flagGroup)
+ // Check subcommands.
+ for _, subcmd := range current.commandOrder {
+ if err := checkDuplicateFlags(subcmd, flagGroups); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (a *Application) execute(context *ParseContext, selected []string) (string, error) {
+ var err error
+
+ if err = a.validateRequired(context); err != nil {
+ return "", err
+ }
+
+ if err = a.applyValidators(context); err != nil {
+ return "", err
+ }
+
+ if err = a.applyActions(context); err != nil {
+ return "", err
+ }
+
+ command := strings.Join(selected, " ")
+ if command == "" && a.cmdGroup.have() {
+ return "", ErrCommandNotSpecified
+ }
+ return command, err
+}
+
+func (a *Application) setDefaults(context *ParseContext) error {
+ flagElements := map[string]*ParseElement{}
+ for _, element := range context.Elements {
+ if flag, ok := element.Clause.(*FlagClause); ok {
+ if flag.name == "help" {
+ return nil
+ }
+ flagElements[flag.name] = element
+ }
+ }
+
+ argElements := map[string]*ParseElement{}
+ for _, element := range context.Elements {
+ if arg, ok := element.Clause.(*ArgClause); ok {
+ argElements[arg.name] = element
+ }
+ }
+
+ // Check required flags and set defaults.
+ for _, flag := range context.flags.long {
+ if flagElements[flag.name] == nil {
+ if err := flag.setDefault(); err != nil {
+ return err
+ }
+ }
+ }
+
+ for _, arg := range context.arguments.args {
+ if argElements[arg.name] == nil {
+ if err := arg.setDefault(); err != nil {
+ return err
+ }
+ }
+ }
+
+ return nil
+}
+
+func (a *Application) validateRequired(context *ParseContext) error {
+ flagElements := map[string]*ParseElement{}
+ for _, element := range context.Elements {
+ if flag, ok := element.Clause.(*FlagClause); ok {
+ flagElements[flag.name] = element
+ }
+ }
+
+ argElements := map[string]*ParseElement{}
+ for _, element := range context.Elements {
+ if arg, ok := element.Clause.(*ArgClause); ok {
+ argElements[arg.name] = element
+ }
+ }
+
+ // Check required flags and set defaults.
+ for _, flag := range context.flags.long {
+ if flagElements[flag.name] == nil {
+ // Check required flags were provided.
+ if flag.needsValue() {
+ return fmt.Errorf("required flag --%s not provided", flag.name)
+ }
+ }
+ }
+
+ for _, arg := range context.arguments.args {
+ if argElements[arg.name] == nil {
+ if arg.needsValue() {
+ return fmt.Errorf("required argument '%s' not provided", arg.name)
+ }
+ }
+ }
+ return nil
+}
+
+func (a *Application) setValues(context *ParseContext) (selected []string, err error) {
+ // Set all arg and flag values.
+ var (
+ lastCmd *CmdClause
+ flagSet = map[string]struct{}{}
+ )
+ for _, element := range context.Elements {
+ switch clause := element.Clause.(type) {
+ case *FlagClause:
+ if _, ok := flagSet[clause.name]; ok {
+ if v, ok := clause.value.(repeatableFlag); !ok || !v.IsCumulative() {
+ return nil, fmt.Errorf("flag '%s' cannot be repeated", clause.name)
+ }
+ }
+ if err = clause.value.Set(*element.Value); err != nil {
+ return
+ }
+ flagSet[clause.name] = struct{}{}
+
+ case *ArgClause:
+ if err = clause.value.Set(*element.Value); err != nil {
+ return
+ }
+
+ case *CmdClause:
+ if clause.validator != nil {
+ if err = clause.validator(clause); err != nil {
+ return
+ }
+ }
+ selected = append(selected, clause.name)
+ lastCmd = clause
+ }
+ }
+
+ if lastCmd != nil && len(lastCmd.commands) > 0 {
+ return nil, fmt.Errorf("must select a subcommand of '%s'", lastCmd.FullCommand())
+ }
+
+ return
+}
+
+func (a *Application) applyValidators(context *ParseContext) (err error) {
+ // Call command validation functions.
+ for _, element := range context.Elements {
+ if cmd, ok := element.Clause.(*CmdClause); ok && cmd.validator != nil {
+ if err = cmd.validator(cmd); err != nil {
+ return err
+ }
+ }
+ }
+
+ if a.validator != nil {
+ err = a.validator(a)
+ }
+ return err
+}
+
+func (a *Application) applyPreActions(context *ParseContext, dispatch bool) error {
+ if err := a.actionMixin.applyPreActions(context); err != nil {
+ return err
+ }
+ // Dispatch to actions.
+ if dispatch {
+ for _, element := range context.Elements {
+ if applier, ok := element.Clause.(actionApplier); ok {
+ if err := applier.applyPreActions(context); err != nil {
+ return err
+ }
+ }
+ }
+ }
+
+ return nil
+}
+
+func (a *Application) applyActions(context *ParseContext) error {
+ if err := a.actionMixin.applyActions(context); err != nil {
+ return err
+ }
+ // Dispatch to actions.
+ for _, element := range context.Elements {
+ if applier, ok := element.Clause.(actionApplier); ok {
+ if err := applier.applyActions(context); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+// Errorf prints an error message to w in the format "<appname>: error: <message>".
+func (a *Application) Errorf(format string, args ...interface{}) {
+ fmt.Fprintf(a.errorWriter, a.Name+": error: "+format+"\n", args...)
+}
+
+// Fatalf writes a formatted error to w then terminates with exit status 1.
+func (a *Application) Fatalf(format string, args ...interface{}) {
+ a.Errorf(format, args...)
+ a.terminate(1)
+}
+
+// FatalUsage prints an error message followed by usage information, then
+// exits with a non-zero status.
+func (a *Application) FatalUsage(format string, args ...interface{}) {
+ a.Errorf(format, args...)
+ // Force usage to go to error output.
+ a.usageWriter = a.errorWriter
+ a.Usage([]string{})
+ a.terminate(1)
+}
+
+// FatalUsageContext writes a printf formatted error message to w, then usage
+// information for the given ParseContext, before exiting.
+func (a *Application) FatalUsageContext(context *ParseContext, format string, args ...interface{}) {
+ a.Errorf(format, args...)
+ if err := a.UsageForContext(context); err != nil {
+ panic(err)
+ }
+ a.terminate(1)
+}
+
+// FatalIfError prints an error and exits if err is not nil. The error is printed
+// with the given formatted string, if any.
+func (a *Application) FatalIfError(err error, format string, args ...interface{}) {
+ if err != nil {
+ prefix := ""
+ if format != "" {
+ prefix = fmt.Sprintf(format, args...) + ": "
+ }
+ a.Errorf(prefix+"%s", err)
+ a.terminate(1)
+ }
+}
+
+func (a *Application) completionOptions(context *ParseContext) []string {
+ args := context.rawArgs
+
+ var (
+ currArg string
+ prevArg string
+ target cmdMixin
+ )
+
+ numArgs := len(args)
+ if numArgs > 1 {
+ args = args[1:]
+ currArg = args[len(args)-1]
+ }
+ if numArgs > 2 {
+ prevArg = args[len(args)-2]
+ }
+
+ target = a.cmdMixin
+ if context.SelectedCommand != nil {
+ // A subcommand was in use. We will use it as the target
+ target = context.SelectedCommand.cmdMixin
+ }
+
+ if (currArg != "" && strings.HasPrefix(currArg, "--")) || strings.HasPrefix(prevArg, "--") {
+ // Perform completion for A flag. The last/current argument started with "-"
+ var (
+ flagName string // The name of a flag if given (could be half complete)
+ flagValue string // The value assigned to a flag (if given) (could be half complete)
+ )
+
+ if strings.HasPrefix(prevArg, "--") && !strings.HasPrefix(currArg, "--") {
+ // Matches: ./myApp --flag value
+ // Wont Match: ./myApp --flag --
+ flagName = prevArg[2:] // Strip the "--"
+ flagValue = currArg
+ } else if strings.HasPrefix(currArg, "--") {
+ // Matches: ./myApp --flag --
+ // Matches: ./myApp --flag somevalue --
+ // Matches: ./myApp --
+ flagName = currArg[2:] // Strip the "--"
+ }
+
+ options, flagMatched, valueMatched := target.FlagCompletion(flagName, flagValue)
+ if valueMatched {
+ // Value Matched. Show cmdCompletions
+ return target.CmdCompletion(context)
+ }
+
+ // Add top level flags if we're not at the top level and no match was found.
+ if context.SelectedCommand != nil && !flagMatched {
+ topOptions, topFlagMatched, topValueMatched := a.FlagCompletion(flagName, flagValue)
+ if topValueMatched {
+ // Value Matched. Back to cmdCompletions
+ return target.CmdCompletion(context)
+ }
+
+ if topFlagMatched {
+ // Top level had a flag which matched the input. Return it's options.
+ options = topOptions
+ } else {
+ // Add top level flags
+ options = append(options, topOptions...)
+ }
+ }
+ return options
+ }
+
+ // Perform completion for sub commands and arguments.
+ return target.CmdCompletion(context)
+}
+
+func (a *Application) generateBashCompletion(context *ParseContext) {
+ options := a.completionOptions(context)
+ fmt.Printf("%s", strings.Join(options, "\n"))
+}
+
+func envarTransform(name string) string {
+ return strings.ToUpper(envarTransformRegexp.ReplaceAllString(name, "_"))
+}
--- /dev/null
+package kingpin
+
+import (
+ "fmt"
+)
+
+type argGroup struct {
+ args []*ArgClause
+}
+
+func newArgGroup() *argGroup {
+ return &argGroup{}
+}
+
+func (a *argGroup) have() bool {
+ return len(a.args) > 0
+}
+
+// GetArg gets an argument definition.
+//
+// This allows existing arguments to be modified after definition but before parsing. Useful for
+// modular applications.
+func (a *argGroup) GetArg(name string) *ArgClause {
+ for _, arg := range a.args {
+ if arg.name == name {
+ return arg
+ }
+ }
+ return nil
+}
+
+func (a *argGroup) Arg(name, help string) *ArgClause {
+ arg := newArg(name, help)
+ a.args = append(a.args, arg)
+ return arg
+}
+
+func (a *argGroup) init() error {
+ required := 0
+ seen := map[string]struct{}{}
+ previousArgMustBeLast := false
+ for i, arg := range a.args {
+ if previousArgMustBeLast {
+ return fmt.Errorf("Args() can't be followed by another argument '%s'", arg.name)
+ }
+ if arg.consumesRemainder() {
+ previousArgMustBeLast = true
+ }
+ if _, ok := seen[arg.name]; ok {
+ return fmt.Errorf("duplicate argument '%s'", arg.name)
+ }
+ seen[arg.name] = struct{}{}
+ if arg.required && required != i {
+ return fmt.Errorf("required arguments found after non-required")
+ }
+ if arg.required {
+ required++
+ }
+ if err := arg.init(); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+type ArgClause struct {
+ actionMixin
+ parserMixin
+ completionsMixin
+ envarMixin
+ name string
+ help string
+ defaultValues []string
+ required bool
+}
+
+func newArg(name, help string) *ArgClause {
+ a := &ArgClause{
+ name: name,
+ help: help,
+ }
+ return a
+}
+
+func (a *ArgClause) setDefault() error {
+ if a.HasEnvarValue() {
+ if v, ok := a.value.(remainderArg); !ok || !v.IsCumulative() {
+ // Use the value as-is
+ return a.value.Set(a.GetEnvarValue())
+ }
+ for _, value := range a.GetSplitEnvarValue() {
+ if err := a.value.Set(value); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+
+ if len(a.defaultValues) > 0 {
+ for _, defaultValue := range a.defaultValues {
+ if err := a.value.Set(defaultValue); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+
+ return nil
+}
+
+func (a *ArgClause) needsValue() bool {
+ haveDefault := len(a.defaultValues) > 0
+ return a.required && !(haveDefault || a.HasEnvarValue())
+}
+
+func (a *ArgClause) consumesRemainder() bool {
+ if r, ok := a.value.(remainderArg); ok {
+ return r.IsCumulative()
+ }
+ return false
+}
+
+// Required arguments must be input by the user. They can not have a Default() value provided.
+func (a *ArgClause) Required() *ArgClause {
+ a.required = true
+ return a
+}
+
+// Default values for this argument. They *must* be parseable by the value of the argument.
+func (a *ArgClause) Default(values ...string) *ArgClause {
+ a.defaultValues = values
+ return a
+}
+
+// Envar overrides the default value(s) for a flag from an environment variable,
+// if it is set. Several default values can be provided by using new lines to
+// separate them.
+func (a *ArgClause) Envar(name string) *ArgClause {
+ a.envar = name
+ a.noEnvar = false
+ return a
+}
+
+// NoEnvar forces environment variable defaults to be disabled for this flag.
+// Most useful in conjunction with app.DefaultEnvars().
+func (a *ArgClause) NoEnvar() *ArgClause {
+ a.envar = ""
+ a.noEnvar = true
+ return a
+}
+
+func (a *ArgClause) Action(action Action) *ArgClause {
+ a.addAction(action)
+ return a
+}
+
+func (a *ArgClause) PreAction(action Action) *ArgClause {
+ a.addPreAction(action)
+ return a
+}
+
+// HintAction registers a HintAction (function) for the arg to provide completions
+func (a *ArgClause) HintAction(action HintAction) *ArgClause {
+ a.addHintAction(action)
+ return a
+}
+
+// HintOptions registers any number of options for the flag to provide completions
+func (a *ArgClause) HintOptions(options ...string) *ArgClause {
+ a.addHintAction(func() []string {
+ return options
+ })
+ return a
+}
+
+func (a *ArgClause) init() error {
+ if a.required && len(a.defaultValues) > 0 {
+ return fmt.Errorf("required argument '%s' with unusable default value", a.name)
+ }
+ if a.value == nil {
+ return fmt.Errorf("no parser defined for arg '%s'", a.name)
+ }
+ return nil
+}
--- /dev/null
+package kingpin
+
+import (
+ "fmt"
+ "strings"
+)
+
+type cmdMixin struct {
+ *flagGroup
+ *argGroup
+ *cmdGroup
+ actionMixin
+}
+
+// CmdCompletion returns completion options for arguments, if that's where
+// parsing left off, or commands if there aren't any unsatisfied args.
+func (c *cmdMixin) CmdCompletion(context *ParseContext) []string {
+ var options []string
+
+ // Count args already satisfied - we won't complete those, and add any
+ // default commands' alternatives, since they weren't listed explicitly
+ // and the user may want to explicitly list something else.
+ argsSatisfied := 0
+ for _, el := range context.Elements {
+ switch clause := el.Clause.(type) {
+ case *ArgClause:
+ if el.Value != nil && *el.Value != "" {
+ argsSatisfied++
+ }
+ case *CmdClause:
+ options = append(options, clause.completionAlts...)
+ default:
+ }
+ }
+
+ if argsSatisfied < len(c.argGroup.args) {
+ // Since not all args have been satisfied, show options for the current one
+ options = append(options, c.argGroup.args[argsSatisfied].resolveCompletions()...)
+ } else {
+ // If all args are satisfied, then go back to completing commands
+ for _, cmd := range c.cmdGroup.commandOrder {
+ if !cmd.hidden {
+ options = append(options, cmd.name)
+ }
+ }
+ }
+
+ return options
+}
+
+func (c *cmdMixin) FlagCompletion(flagName string, flagValue string) (choices []string, flagMatch bool, optionMatch bool) {
+ // Check if flagName matches a known flag.
+ // If it does, show the options for the flag
+ // Otherwise, show all flags
+
+ options := []string{}
+
+ for _, flag := range c.flagGroup.flagOrder {
+ // Loop through each flag and determine if a match exists
+ if flag.name == flagName {
+ // User typed entire flag. Need to look for flag options.
+ options = flag.resolveCompletions()
+ if len(options) == 0 {
+ // No Options to Choose From, Assume Match.
+ return options, true, true
+ }
+
+ // Loop options to find if the user specified value matches
+ isPrefix := false
+ matched := false
+
+ for _, opt := range options {
+ if flagValue == opt {
+ matched = true
+ } else if strings.HasPrefix(opt, flagValue) {
+ isPrefix = true
+ }
+ }
+
+ // Matched Flag Directly
+ // Flag Value Not Prefixed, and Matched Directly
+ return options, true, !isPrefix && matched
+ }
+
+ if !flag.hidden {
+ options = append(options, "--"+flag.name)
+ }
+ }
+ // No Flag directly matched.
+ return options, false, false
+
+}
+
+type cmdGroup struct {
+ app *Application
+ parent *CmdClause
+ commands map[string]*CmdClause
+ commandOrder []*CmdClause
+}
+
+func (c *cmdGroup) defaultSubcommand() *CmdClause {
+ for _, cmd := range c.commandOrder {
+ if cmd.isDefault {
+ return cmd
+ }
+ }
+ return nil
+}
+
+func (c *cmdGroup) cmdNames() []string {
+ names := make([]string, 0, len(c.commandOrder))
+ for _, cmd := range c.commandOrder {
+ names = append(names, cmd.name)
+ }
+ return names
+}
+
+// GetArg gets a command definition.
+//
+// This allows existing commands to be modified after definition but before parsing. Useful for
+// modular applications.
+func (c *cmdGroup) GetCommand(name string) *CmdClause {
+ return c.commands[name]
+}
+
+func newCmdGroup(app *Application) *cmdGroup {
+ return &cmdGroup{
+ app: app,
+ commands: make(map[string]*CmdClause),
+ }
+}
+
+func (c *cmdGroup) flattenedCommands() (out []*CmdClause) {
+ for _, cmd := range c.commandOrder {
+ if len(cmd.commands) == 0 {
+ out = append(out, cmd)
+ }
+ out = append(out, cmd.flattenedCommands()...)
+ }
+ return
+}
+
+func (c *cmdGroup) addCommand(name, help string) *CmdClause {
+ cmd := newCommand(c.app, name, help)
+ c.commands[name] = cmd
+ c.commandOrder = append(c.commandOrder, cmd)
+ return cmd
+}
+
+func (c *cmdGroup) init() error {
+ seen := map[string]bool{}
+ if c.defaultSubcommand() != nil && !c.have() {
+ return fmt.Errorf("default subcommand %q provided but no subcommands defined", c.defaultSubcommand().name)
+ }
+ defaults := []string{}
+ for _, cmd := range c.commandOrder {
+ if cmd.isDefault {
+ defaults = append(defaults, cmd.name)
+ }
+ if seen[cmd.name] {
+ return fmt.Errorf("duplicate command %q", cmd.name)
+ }
+ seen[cmd.name] = true
+ for _, alias := range cmd.aliases {
+ if seen[alias] {
+ return fmt.Errorf("alias duplicates existing command %q", alias)
+ }
+ c.commands[alias] = cmd
+ }
+ if err := cmd.init(); err != nil {
+ return err
+ }
+ }
+ if len(defaults) > 1 {
+ return fmt.Errorf("more than one default subcommand exists: %s", strings.Join(defaults, ", "))
+ }
+ return nil
+}
+
+func (c *cmdGroup) have() bool {
+ return len(c.commands) > 0
+}
+
+type CmdClauseValidator func(*CmdClause) error
+
+// A CmdClause is a single top-level command. It encapsulates a set of flags
+// and either subcommands or positional arguments.
+type CmdClause struct {
+ cmdMixin
+ app *Application
+ name string
+ aliases []string
+ help string
+ isDefault bool
+ validator CmdClauseValidator
+ hidden bool
+ completionAlts []string
+}
+
+func newCommand(app *Application, name, help string) *CmdClause {
+ c := &CmdClause{
+ app: app,
+ name: name,
+ help: help,
+ }
+ c.flagGroup = newFlagGroup()
+ c.argGroup = newArgGroup()
+ c.cmdGroup = newCmdGroup(app)
+ return c
+}
+
+// Add an Alias for this command.
+func (c *CmdClause) Alias(name string) *CmdClause {
+ c.aliases = append(c.aliases, name)
+ return c
+}
+
+// Validate sets a validation function to run when parsing.
+func (c *CmdClause) Validate(validator CmdClauseValidator) *CmdClause {
+ c.validator = validator
+ return c
+}
+
+func (c *CmdClause) FullCommand() string {
+ out := []string{c.name}
+ for p := c.parent; p != nil; p = p.parent {
+ out = append([]string{p.name}, out...)
+ }
+ return strings.Join(out, " ")
+}
+
+// Command adds a new sub-command.
+func (c *CmdClause) Command(name, help string) *CmdClause {
+ cmd := c.addCommand(name, help)
+ cmd.parent = c
+ return cmd
+}
+
+// Default makes this command the default if commands don't match.
+func (c *CmdClause) Default() *CmdClause {
+ c.isDefault = true
+ return c
+}
+
+func (c *CmdClause) Action(action Action) *CmdClause {
+ c.addAction(action)
+ return c
+}
+
+func (c *CmdClause) PreAction(action Action) *CmdClause {
+ c.addPreAction(action)
+ return c
+}
+
+func (c *CmdClause) init() error {
+ if err := c.flagGroup.init(c.app.defaultEnvarPrefix()); err != nil {
+ return err
+ }
+ if c.argGroup.have() && c.cmdGroup.have() {
+ return fmt.Errorf("can't mix Arg()s with Command()s")
+ }
+ if err := c.argGroup.init(); err != nil {
+ return err
+ }
+ if err := c.cmdGroup.init(); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (c *CmdClause) Hidden() *CmdClause {
+ c.hidden = true
+ return c
+}
--- /dev/null
+package kingpin
+
+// HintAction is a function type who is expected to return a slice of possible
+// command line arguments.
+type HintAction func() []string
+type completionsMixin struct {
+ hintActions []HintAction
+ builtinHintActions []HintAction
+}
+
+func (a *completionsMixin) addHintAction(action HintAction) {
+ a.hintActions = append(a.hintActions, action)
+}
+
+// Allow adding of HintActions which are added internally, ie, EnumVar
+func (a *completionsMixin) addHintActionBuiltin(action HintAction) {
+ a.builtinHintActions = append(a.builtinHintActions, action)
+}
+
+func (a *completionsMixin) resolveCompletions() []string {
+ var hints []string
+
+ options := a.builtinHintActions
+ if len(a.hintActions) > 0 {
+ // User specified their own hintActions. Use those instead.
+ options = a.hintActions
+ }
+
+ for _, hintAction := range options {
+ hints = append(hints, hintAction()...)
+ }
+ return hints
+}
--- /dev/null
+// Package kingpin provides command line interfaces like this:
+//
+// $ chat
+// usage: chat [<flags>] <command> [<flags>] [<args> ...]
+//
+// Flags:
+// --debug enable debug mode
+// --help Show help.
+// --server=127.0.0.1 server address
+//
+// Commands:
+// help <command>
+// Show help for a command.
+//
+// post [<flags>] <channel>
+// Post a message to a channel.
+//
+// register <nick> <name>
+// Register a new user.
+//
+// $ chat help post
+// usage: chat [<flags>] post [<flags>] <channel> [<text>]
+//
+// Post a message to a channel.
+//
+// Flags:
+// --image=IMAGE image to post
+//
+// Args:
+// <channel> channel to post to
+// [<text>] text to post
+// $ chat post --image=~/Downloads/owls.jpg pics
+//
+// From code like this:
+//
+// package main
+//
+// import "gopkg.in/alecthomas/kingpin.v2"
+//
+// var (
+// debug = kingpin.Flag("debug", "enable debug mode").Default("false").Bool()
+// serverIP = kingpin.Flag("server", "server address").Default("127.0.0.1").IP()
+//
+// register = kingpin.Command("register", "Register a new user.")
+// registerNick = register.Arg("nick", "nickname for user").Required().String()
+// registerName = register.Arg("name", "name of user").Required().String()
+//
+// post = kingpin.Command("post", "Post a message to a channel.")
+// postImage = post.Flag("image", "image to post").ExistingFile()
+// postChannel = post.Arg("channel", "channel to post to").Required().String()
+// postText = post.Arg("text", "text to post").String()
+// )
+//
+// func main() {
+// switch kingpin.Parse() {
+// // Register user
+// case "register":
+// println(*registerNick)
+//
+// // Post message
+// case "post":
+// if *postImage != nil {
+// }
+// if *postText != "" {
+// }
+// }
+// }
+package kingpin
--- /dev/null
+package kingpin
+
+import (
+ "os"
+ "regexp"
+)
+
+var (
+ envVarValuesSeparator = "\r?\n"
+ envVarValuesTrimmer = regexp.MustCompile(envVarValuesSeparator + "$")
+ envVarValuesSplitter = regexp.MustCompile(envVarValuesSeparator)
+)
+
+type envarMixin struct {
+ envar string
+ noEnvar bool
+}
+
+func (e *envarMixin) HasEnvarValue() bool {
+ return e.GetEnvarValue() != ""
+}
+
+func (e *envarMixin) GetEnvarValue() string {
+ if e.noEnvar || e.envar == "" {
+ return ""
+ }
+ return os.Getenv(e.envar)
+}
+
+func (e *envarMixin) GetSplitEnvarValue() []string {
+ values := make([]string, 0)
+
+ envarValue := e.GetEnvarValue()
+ if envarValue == "" {
+ return values
+ }
+
+ // Split by new line to extract multiple values, if any.
+ trimmed := envVarValuesTrimmer.ReplaceAllString(envarValue, "")
+ for _, value := range envVarValuesSplitter.Split(trimmed, -1) {
+ values = append(values, value)
+ }
+
+ return values
+}
--- /dev/null
+package kingpin
+
+import (
+ "fmt"
+ "strings"
+)
+
+type flagGroup struct {
+ short map[string]*FlagClause
+ long map[string]*FlagClause
+ flagOrder []*FlagClause
+}
+
+func newFlagGroup() *flagGroup {
+ return &flagGroup{
+ short: map[string]*FlagClause{},
+ long: map[string]*FlagClause{},
+ }
+}
+
+// GetFlag gets a flag definition.
+//
+// This allows existing flags to be modified after definition but before parsing. Useful for
+// modular applications.
+func (f *flagGroup) GetFlag(name string) *FlagClause {
+ return f.long[name]
+}
+
+// Flag defines a new flag with the given long name and help.
+func (f *flagGroup) Flag(name, help string) *FlagClause {
+ flag := newFlag(name, help)
+ f.long[name] = flag
+ f.flagOrder = append(f.flagOrder, flag)
+ return flag
+}
+
+func (f *flagGroup) init(defaultEnvarPrefix string) error {
+ if err := f.checkDuplicates(); err != nil {
+ return err
+ }
+ for _, flag := range f.long {
+ if defaultEnvarPrefix != "" && !flag.noEnvar && flag.envar == "" {
+ flag.envar = envarTransform(defaultEnvarPrefix + "_" + flag.name)
+ }
+ if err := flag.init(); err != nil {
+ return err
+ }
+ if flag.shorthand != 0 {
+ f.short[string(flag.shorthand)] = flag
+ }
+ }
+ return nil
+}
+
+func (f *flagGroup) checkDuplicates() error {
+ seenShort := map[rune]bool{}
+ seenLong := map[string]bool{}
+ for _, flag := range f.flagOrder {
+ if flag.shorthand != 0 {
+ if _, ok := seenShort[flag.shorthand]; ok {
+ return fmt.Errorf("duplicate short flag -%c", flag.shorthand)
+ }
+ seenShort[flag.shorthand] = true
+ }
+ if _, ok := seenLong[flag.name]; ok {
+ return fmt.Errorf("duplicate long flag --%s", flag.name)
+ }
+ seenLong[flag.name] = true
+ }
+ return nil
+}
+
+func (f *flagGroup) parse(context *ParseContext) (*FlagClause, error) {
+ var token *Token
+
+loop:
+ for {
+ token = context.Peek()
+ switch token.Type {
+ case TokenEOL:
+ break loop
+
+ case TokenLong, TokenShort:
+ flagToken := token
+ defaultValue := ""
+ var flag *FlagClause
+ var ok bool
+ invert := false
+
+ name := token.Value
+ if token.Type == TokenLong {
+ flag, ok = f.long[name]
+ if !ok {
+ if strings.HasPrefix(name, "no-") {
+ name = name[3:]
+ invert = true
+ }
+ flag, ok = f.long[name]
+ }
+ if !ok {
+ return nil, fmt.Errorf("unknown long flag '%s'", flagToken)
+ }
+ } else {
+ flag, ok = f.short[name]
+ if !ok {
+ return nil, fmt.Errorf("unknown short flag '%s'", flagToken)
+ }
+ }
+
+ context.Next()
+
+ fb, ok := flag.value.(boolFlag)
+ if ok && fb.IsBoolFlag() {
+ if invert {
+ defaultValue = "false"
+ } else {
+ defaultValue = "true"
+ }
+ } else {
+ if invert {
+ context.Push(token)
+ return nil, fmt.Errorf("unknown long flag '%s'", flagToken)
+ }
+ token = context.Peek()
+ if token.Type != TokenArg {
+ context.Push(token)
+ return nil, fmt.Errorf("expected argument for flag '%s'", flagToken)
+ }
+ context.Next()
+ defaultValue = token.Value
+ }
+
+ context.matchedFlag(flag, defaultValue)
+ return flag, nil
+
+ default:
+ break loop
+ }
+ }
+ return nil, nil
+}
+
+// FlagClause is a fluid interface used to build flags.
+type FlagClause struct {
+ parserMixin
+ actionMixin
+ completionsMixin
+ envarMixin
+ name string
+ shorthand rune
+ help string
+ defaultValues []string
+ placeholder string
+ hidden bool
+}
+
+func newFlag(name, help string) *FlagClause {
+ f := &FlagClause{
+ name: name,
+ help: help,
+ }
+ return f
+}
+
+func (f *FlagClause) setDefault() error {
+ if f.HasEnvarValue() {
+ if v, ok := f.value.(repeatableFlag); !ok || !v.IsCumulative() {
+ // Use the value as-is
+ return f.value.Set(f.GetEnvarValue())
+ } else {
+ for _, value := range f.GetSplitEnvarValue() {
+ if err := f.value.Set(value); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+ }
+
+ if len(f.defaultValues) > 0 {
+ for _, defaultValue := range f.defaultValues {
+ if err := f.value.Set(defaultValue); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+
+ return nil
+}
+
+func (f *FlagClause) needsValue() bool {
+ haveDefault := len(f.defaultValues) > 0
+ return f.required && !(haveDefault || f.HasEnvarValue())
+}
+
+func (f *FlagClause) init() error {
+ if f.required && len(f.defaultValues) > 0 {
+ return fmt.Errorf("required flag '--%s' with default value that will never be used", f.name)
+ }
+ if f.value == nil {
+ return fmt.Errorf("no type defined for --%s (eg. .String())", f.name)
+ }
+ if v, ok := f.value.(repeatableFlag); (!ok || !v.IsCumulative()) && len(f.defaultValues) > 1 {
+ return fmt.Errorf("invalid default for '--%s', expecting single value", f.name)
+ }
+ return nil
+}
+
+// Dispatch to the given function after the flag is parsed and validated.
+func (f *FlagClause) Action(action Action) *FlagClause {
+ f.addAction(action)
+ return f
+}
+
+func (f *FlagClause) PreAction(action Action) *FlagClause {
+ f.addPreAction(action)
+ return f
+}
+
+// HintAction registers a HintAction (function) for the flag to provide completions
+func (a *FlagClause) HintAction(action HintAction) *FlagClause {
+ a.addHintAction(action)
+ return a
+}
+
+// HintOptions registers any number of options for the flag to provide completions
+func (a *FlagClause) HintOptions(options ...string) *FlagClause {
+ a.addHintAction(func() []string {
+ return options
+ })
+ return a
+}
+
+func (a *FlagClause) EnumVar(target *string, options ...string) {
+ a.parserMixin.EnumVar(target, options...)
+ a.addHintActionBuiltin(func() []string {
+ return options
+ })
+}
+
+func (a *FlagClause) Enum(options ...string) (target *string) {
+ a.addHintActionBuiltin(func() []string {
+ return options
+ })
+ return a.parserMixin.Enum(options...)
+}
+
+// Default values for this flag. They *must* be parseable by the value of the flag.
+func (f *FlagClause) Default(values ...string) *FlagClause {
+ f.defaultValues = values
+ return f
+}
+
+// DEPRECATED: Use Envar(name) instead.
+func (f *FlagClause) OverrideDefaultFromEnvar(envar string) *FlagClause {
+ return f.Envar(envar)
+}
+
+// Envar overrides the default value(s) for a flag from an environment variable,
+// if it is set. Several default values can be provided by using new lines to
+// separate them.
+func (f *FlagClause) Envar(name string) *FlagClause {
+ f.envar = name
+ f.noEnvar = false
+ return f
+}
+
+// NoEnvar forces environment variable defaults to be disabled for this flag.
+// Most useful in conjunction with app.DefaultEnvars().
+func (f *FlagClause) NoEnvar() *FlagClause {
+ f.envar = ""
+ f.noEnvar = true
+ return f
+}
+
+// PlaceHolder sets the place-holder string used for flag values in the help. The
+// default behaviour is to use the value provided by Default() if provided,
+// then fall back on the capitalized flag name.
+func (f *FlagClause) PlaceHolder(placeholder string) *FlagClause {
+ f.placeholder = placeholder
+ return f
+}
+
+// Hidden hides a flag from usage but still allows it to be used.
+func (f *FlagClause) Hidden() *FlagClause {
+ f.hidden = true
+ return f
+}
+
+// Required makes the flag required. You can not provide a Default() value to a Required() flag.
+func (f *FlagClause) Required() *FlagClause {
+ f.required = true
+ return f
+}
+
+// Short sets the short flag name.
+func (f *FlagClause) Short(name rune) *FlagClause {
+ f.shorthand = name
+ return f
+}
+
+// Bool makes this flag a boolean flag.
+func (f *FlagClause) Bool() (target *bool) {
+ target = new(bool)
+ f.SetValue(newBoolValue(target))
+ return
+}
--- /dev/null
+package kingpin
+
+import (
+ "os"
+ "path/filepath"
+)
+
+var (
+ // CommandLine is the default Kingpin parser.
+ CommandLine = New(filepath.Base(os.Args[0]), "")
+ // Global help flag. Exposed for user customisation.
+ HelpFlag = CommandLine.HelpFlag
+ // Top-level help command. Exposed for user customisation. May be nil.
+ HelpCommand = CommandLine.HelpCommand
+ // Global version flag. Exposed for user customisation. May be nil.
+ VersionFlag = CommandLine.VersionFlag
+)
+
+// Command adds a new command to the default parser.
+func Command(name, help string) *CmdClause {
+ return CommandLine.Command(name, help)
+}
+
+// Flag adds a new flag to the default parser.
+func Flag(name, help string) *FlagClause {
+ return CommandLine.Flag(name, help)
+}
+
+// Arg adds a new argument to the top-level of the default parser.
+func Arg(name, help string) *ArgClause {
+ return CommandLine.Arg(name, help)
+}
+
+// Parse and return the selected command. Will call the termination handler if
+// an error is encountered.
+func Parse() string {
+ selected := MustParse(CommandLine.Parse(os.Args[1:]))
+ if selected == "" && CommandLine.cmdGroup.have() {
+ Usage()
+ CommandLine.terminate(0)
+ }
+ return selected
+}
+
+// Errorf prints an error message to stderr.
+func Errorf(format string, args ...interface{}) {
+ CommandLine.Errorf(format, args...)
+}
+
+// Fatalf prints an error message to stderr and exits.
+func Fatalf(format string, args ...interface{}) {
+ CommandLine.Fatalf(format, args...)
+}
+
+// FatalIfError prints an error and exits if err is not nil. The error is printed
+// with the given prefix.
+func FatalIfError(err error, format string, args ...interface{}) {
+ CommandLine.FatalIfError(err, format, args...)
+}
+
+// FatalUsage prints an error message followed by usage information, then
+// exits with a non-zero status.
+func FatalUsage(format string, args ...interface{}) {
+ CommandLine.FatalUsage(format, args...)
+}
+
+// FatalUsageContext writes a printf formatted error message to stderr, then
+// usage information for the given ParseContext, before exiting.
+func FatalUsageContext(context *ParseContext, format string, args ...interface{}) {
+ CommandLine.FatalUsageContext(context, format, args...)
+}
+
+// Usage prints usage to stderr.
+func Usage() {
+ CommandLine.Usage(os.Args[1:])
+}
+
+// Set global usage template to use (defaults to DefaultUsageTemplate).
+func UsageTemplate(template string) *Application {
+ return CommandLine.UsageTemplate(template)
+}
+
+// MustParse can be used with app.Parse(args) to exit with an error if parsing fails.
+func MustParse(command string, err error) string {
+ if err != nil {
+ Fatalf("%s, try --help", err)
+ }
+ return command
+}
+
+// Version adds a flag for displaying the application version number.
+func Version(version string) *Application {
+ return CommandLine.Version(version)
+}
--- /dev/null
+// +build appengine !linux,!freebsd,!darwin,!dragonfly,!netbsd,!openbsd
+
+package kingpin
+
+import "io"
+
+func guessWidth(w io.Writer) int {
+ return 80
+}
--- /dev/null
+// +build !appengine,linux freebsd darwin dragonfly netbsd openbsd
+
+package kingpin
+
+import (
+ "io"
+ "os"
+ "strconv"
+ "syscall"
+ "unsafe"
+)
+
+func guessWidth(w io.Writer) int {
+ // check if COLUMNS env is set to comply with
+ // http://pubs.opengroup.org/onlinepubs/009604499/basedefs/xbd_chap08.html
+ colsStr := os.Getenv("COLUMNS")
+ if colsStr != "" {
+ if cols, err := strconv.Atoi(colsStr); err == nil {
+ return cols
+ }
+ }
+
+ if t, ok := w.(*os.File); ok {
+ fd := t.Fd()
+ var dimensions [4]uint16
+
+ if _, _, err := syscall.Syscall6(
+ syscall.SYS_IOCTL,
+ uintptr(fd),
+ uintptr(syscall.TIOCGWINSZ),
+ uintptr(unsafe.Pointer(&dimensions)),
+ 0, 0, 0,
+ ); err == 0 {
+ return int(dimensions[1])
+ }
+ }
+ return 80
+}
--- /dev/null
+package kingpin
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+// Data model for Kingpin command-line structure.
+
+type FlagGroupModel struct {
+ Flags []*FlagModel
+}
+
+func (f *FlagGroupModel) FlagSummary() string {
+ out := []string{}
+ count := 0
+ for _, flag := range f.Flags {
+ if flag.Name != "help" {
+ count++
+ }
+ if flag.Required {
+ if flag.IsBoolFlag() {
+ out = append(out, fmt.Sprintf("--[no-]%s", flag.Name))
+ } else {
+ out = append(out, fmt.Sprintf("--%s=%s", flag.Name, flag.FormatPlaceHolder()))
+ }
+ }
+ }
+ if count != len(out) {
+ out = append(out, "[<flags>]")
+ }
+ return strings.Join(out, " ")
+}
+
+type FlagModel struct {
+ Name string
+ Help string
+ Short rune
+ Default []string
+ Envar string
+ PlaceHolder string
+ Required bool
+ Hidden bool
+ Value Value
+}
+
+func (f *FlagModel) String() string {
+ return f.Value.String()
+}
+
+func (f *FlagModel) IsBoolFlag() bool {
+ if fl, ok := f.Value.(boolFlag); ok {
+ return fl.IsBoolFlag()
+ }
+ return false
+}
+
+func (f *FlagModel) FormatPlaceHolder() string {
+ if f.PlaceHolder != "" {
+ return f.PlaceHolder
+ }
+ if len(f.Default) > 0 {
+ ellipsis := ""
+ if len(f.Default) > 1 {
+ ellipsis = "..."
+ }
+ if _, ok := f.Value.(*stringValue); ok {
+ return strconv.Quote(f.Default[0]) + ellipsis
+ }
+ return f.Default[0] + ellipsis
+ }
+ return strings.ToUpper(f.Name)
+}
+
+type ArgGroupModel struct {
+ Args []*ArgModel
+}
+
+func (a *ArgGroupModel) ArgSummary() string {
+ depth := 0
+ out := []string{}
+ for _, arg := range a.Args {
+ h := "<" + arg.Name + ">"
+ if !arg.Required {
+ h = "[" + h
+ depth++
+ }
+ out = append(out, h)
+ }
+ out[len(out)-1] = out[len(out)-1] + strings.Repeat("]", depth)
+ return strings.Join(out, " ")
+}
+
+type ArgModel struct {
+ Name string
+ Help string
+ Default []string
+ Envar string
+ Required bool
+ Value Value
+}
+
+func (a *ArgModel) String() string {
+ return a.Value.String()
+}
+
+type CmdGroupModel struct {
+ Commands []*CmdModel
+}
+
+func (c *CmdGroupModel) FlattenedCommands() (out []*CmdModel) {
+ for _, cmd := range c.Commands {
+ if len(cmd.Commands) == 0 {
+ out = append(out, cmd)
+ }
+ out = append(out, cmd.FlattenedCommands()...)
+ }
+ return
+}
+
+type CmdModel struct {
+ Name string
+ Aliases []string
+ Help string
+ FullCommand string
+ Depth int
+ Hidden bool
+ Default bool
+ *FlagGroupModel
+ *ArgGroupModel
+ *CmdGroupModel
+}
+
+func (c *CmdModel) String() string {
+ return c.FullCommand
+}
+
+type ApplicationModel struct {
+ Name string
+ Help string
+ Version string
+ Author string
+ *ArgGroupModel
+ *CmdGroupModel
+ *FlagGroupModel
+}
+
+func (a *Application) Model() *ApplicationModel {
+ return &ApplicationModel{
+ Name: a.Name,
+ Help: a.Help,
+ Version: a.version,
+ Author: a.author,
+ FlagGroupModel: a.flagGroup.Model(),
+ ArgGroupModel: a.argGroup.Model(),
+ CmdGroupModel: a.cmdGroup.Model(),
+ }
+}
+
+func (a *argGroup) Model() *ArgGroupModel {
+ m := &ArgGroupModel{}
+ for _, arg := range a.args {
+ m.Args = append(m.Args, arg.Model())
+ }
+ return m
+}
+
+func (a *ArgClause) Model() *ArgModel {
+ return &ArgModel{
+ Name: a.name,
+ Help: a.help,
+ Default: a.defaultValues,
+ Envar: a.envar,
+ Required: a.required,
+ Value: a.value,
+ }
+}
+
+func (f *flagGroup) Model() *FlagGroupModel {
+ m := &FlagGroupModel{}
+ for _, fl := range f.flagOrder {
+ m.Flags = append(m.Flags, fl.Model())
+ }
+ return m
+}
+
+func (f *FlagClause) Model() *FlagModel {
+ return &FlagModel{
+ Name: f.name,
+ Help: f.help,
+ Short: rune(f.shorthand),
+ Default: f.defaultValues,
+ Envar: f.envar,
+ PlaceHolder: f.placeholder,
+ Required: f.required,
+ Hidden: f.hidden,
+ Value: f.value,
+ }
+}
+
+func (c *cmdGroup) Model() *CmdGroupModel {
+ m := &CmdGroupModel{}
+ for _, cm := range c.commandOrder {
+ m.Commands = append(m.Commands, cm.Model())
+ }
+ return m
+}
+
+func (c *CmdClause) Model() *CmdModel {
+ depth := 0
+ for i := c; i != nil; i = i.parent {
+ depth++
+ }
+ return &CmdModel{
+ Name: c.name,
+ Aliases: c.aliases,
+ Help: c.help,
+ Depth: depth,
+ Hidden: c.hidden,
+ Default: c.isDefault,
+ FullCommand: c.FullCommand(),
+ FlagGroupModel: c.flagGroup.Model(),
+ ArgGroupModel: c.argGroup.Model(),
+ CmdGroupModel: c.cmdGroup.Model(),
+ }
+}
--- /dev/null
+package kingpin
+
+import (
+ "bufio"
+ "fmt"
+ "os"
+ "strings"
+ "unicode/utf8"
+)
+
+type TokenType int
+
+// Token types.
+const (
+ TokenShort TokenType = iota
+ TokenLong
+ TokenArg
+ TokenError
+ TokenEOL
+)
+
+func (t TokenType) String() string {
+ switch t {
+ case TokenShort:
+ return "short flag"
+ case TokenLong:
+ return "long flag"
+ case TokenArg:
+ return "argument"
+ case TokenError:
+ return "error"
+ case TokenEOL:
+ return "<EOL>"
+ }
+ return "?"
+}
+
+var (
+ TokenEOLMarker = Token{-1, TokenEOL, ""}
+)
+
+type Token struct {
+ Index int
+ Type TokenType
+ Value string
+}
+
+func (t *Token) Equal(o *Token) bool {
+ return t.Index == o.Index
+}
+
+func (t *Token) IsFlag() bool {
+ return t.Type == TokenShort || t.Type == TokenLong
+}
+
+func (t *Token) IsEOF() bool {
+ return t.Type == TokenEOL
+}
+
+func (t *Token) String() string {
+ switch t.Type {
+ case TokenShort:
+ return "-" + t.Value
+ case TokenLong:
+ return "--" + t.Value
+ case TokenArg:
+ return t.Value
+ case TokenError:
+ return "error: " + t.Value
+ case TokenEOL:
+ return "<EOL>"
+ default:
+ panic("unhandled type")
+ }
+}
+
+// A union of possible elements in a parse stack.
+type ParseElement struct {
+ // Clause is either *CmdClause, *ArgClause or *FlagClause.
+ Clause interface{}
+ // Value is corresponding value for an ArgClause or FlagClause (if any).
+ Value *string
+}
+
+// ParseContext holds the current context of the parser. When passed to
+// Action() callbacks Elements will be fully populated with *FlagClause,
+// *ArgClause and *CmdClause values and their corresponding arguments (if
+// any).
+type ParseContext struct {
+ SelectedCommand *CmdClause
+ ignoreDefault bool
+ argsOnly bool
+ peek []*Token
+ argi int // Index of current command-line arg we're processing.
+ args []string
+ rawArgs []string
+ flags *flagGroup
+ arguments *argGroup
+ argumenti int // Cursor into arguments
+ // Flags, arguments and commands encountered and collected during parse.
+ Elements []*ParseElement
+}
+
+func (p *ParseContext) nextArg() *ArgClause {
+ if p.argumenti >= len(p.arguments.args) {
+ return nil
+ }
+ arg := p.arguments.args[p.argumenti]
+ if !arg.consumesRemainder() {
+ p.argumenti++
+ }
+ return arg
+}
+
+func (p *ParseContext) next() {
+ p.argi++
+ p.args = p.args[1:]
+}
+
+// HasTrailingArgs returns true if there are unparsed command-line arguments.
+// This can occur if the parser can not match remaining arguments.
+func (p *ParseContext) HasTrailingArgs() bool {
+ return len(p.args) > 0
+}
+
+func tokenize(args []string, ignoreDefault bool) *ParseContext {
+ return &ParseContext{
+ ignoreDefault: ignoreDefault,
+ args: args,
+ rawArgs: args,
+ flags: newFlagGroup(),
+ arguments: newArgGroup(),
+ }
+}
+
+func (p *ParseContext) mergeFlags(flags *flagGroup) {
+ for _, flag := range flags.flagOrder {
+ if flag.shorthand != 0 {
+ p.flags.short[string(flag.shorthand)] = flag
+ }
+ p.flags.long[flag.name] = flag
+ p.flags.flagOrder = append(p.flags.flagOrder, flag)
+ }
+}
+
+func (p *ParseContext) mergeArgs(args *argGroup) {
+ for _, arg := range args.args {
+ p.arguments.args = append(p.arguments.args, arg)
+ }
+}
+
+func (p *ParseContext) EOL() bool {
+ return p.Peek().Type == TokenEOL
+}
+
+func (p *ParseContext) Error() bool {
+ return p.Peek().Type == TokenError
+}
+
+// Next token in the parse context.
+func (p *ParseContext) Next() *Token {
+ if len(p.peek) > 0 {
+ return p.pop()
+ }
+
+ // End of tokens.
+ if len(p.args) == 0 {
+ return &Token{Index: p.argi, Type: TokenEOL}
+ }
+
+ arg := p.args[0]
+ p.next()
+
+ if p.argsOnly {
+ return &Token{p.argi, TokenArg, arg}
+ }
+
+ // All remaining args are passed directly.
+ if arg == "--" {
+ p.argsOnly = true
+ return p.Next()
+ }
+
+ if strings.HasPrefix(arg, "--") {
+ parts := strings.SplitN(arg[2:], "=", 2)
+ token := &Token{p.argi, TokenLong, parts[0]}
+ if len(parts) == 2 {
+ p.Push(&Token{p.argi, TokenArg, parts[1]})
+ }
+ return token
+ }
+
+ if strings.HasPrefix(arg, "-") {
+ if len(arg) == 1 {
+ return &Token{Index: p.argi, Type: TokenShort}
+ }
+ shortRune, size := utf8.DecodeRuneInString(arg[1:])
+ short := string(shortRune)
+ flag, ok := p.flags.short[short]
+ // Not a known short flag, we'll just return it anyway.
+ if !ok {
+ } else if fb, ok := flag.value.(boolFlag); ok && fb.IsBoolFlag() {
+ // Bool short flag.
+ } else {
+ // Short flag with combined argument: -fARG
+ token := &Token{p.argi, TokenShort, short}
+ if len(arg) > size+1 {
+ p.Push(&Token{p.argi, TokenArg, arg[size+1:]})
+ }
+ return token
+ }
+
+ if len(arg) > size+1 {
+ p.args = append([]string{"-" + arg[size+1:]}, p.args...)
+ }
+ return &Token{p.argi, TokenShort, short}
+ } else if strings.HasPrefix(arg, "@") {
+ expanded, err := ExpandArgsFromFile(arg[1:])
+ if err != nil {
+ return &Token{p.argi, TokenError, err.Error()}
+ }
+ if len(p.args) == 0 {
+ p.args = expanded
+ } else {
+ p.args = append(expanded, p.args...)
+ }
+ return p.Next()
+ }
+
+ return &Token{p.argi, TokenArg, arg}
+}
+
+func (p *ParseContext) Peek() *Token {
+ if len(p.peek) == 0 {
+ return p.Push(p.Next())
+ }
+ return p.peek[len(p.peek)-1]
+}
+
+func (p *ParseContext) Push(token *Token) *Token {
+ p.peek = append(p.peek, token)
+ return token
+}
+
+func (p *ParseContext) pop() *Token {
+ end := len(p.peek) - 1
+ token := p.peek[end]
+ p.peek = p.peek[0:end]
+ return token
+}
+
+func (p *ParseContext) String() string {
+ return p.SelectedCommand.FullCommand()
+}
+
+func (p *ParseContext) matchedFlag(flag *FlagClause, value string) {
+ p.Elements = append(p.Elements, &ParseElement{Clause: flag, Value: &value})
+}
+
+func (p *ParseContext) matchedArg(arg *ArgClause, value string) {
+ p.Elements = append(p.Elements, &ParseElement{Clause: arg, Value: &value})
+}
+
+func (p *ParseContext) matchedCmd(cmd *CmdClause) {
+ p.Elements = append(p.Elements, &ParseElement{Clause: cmd})
+ p.mergeFlags(cmd.flagGroup)
+ p.mergeArgs(cmd.argGroup)
+ p.SelectedCommand = cmd
+}
+
+// Expand arguments from a file. Lines starting with # will be treated as comments.
+func ExpandArgsFromFile(filename string) (out []string, err error) {
+ if filename == "" {
+ return nil, fmt.Errorf("expected @ file to expand arguments from")
+ }
+ r, err := os.Open(filename)
+ if err != nil {
+ return nil, fmt.Errorf("failed to open arguments file %q: %s", filename, err)
+ }
+ defer r.Close()
+ scanner := bufio.NewScanner(r)
+ for scanner.Scan() {
+ line := scanner.Text()
+ if strings.HasPrefix(line, "#") {
+ continue
+ }
+ out = append(out, line)
+ }
+ err = scanner.Err()
+ if err != nil {
+ return nil, fmt.Errorf("failed to read arguments from %q: %s", filename, err)
+ }
+ return
+}
+
+func parse(context *ParseContext, app *Application) (err error) {
+ context.mergeFlags(app.flagGroup)
+ context.mergeArgs(app.argGroup)
+
+ cmds := app.cmdGroup
+ ignoreDefault := context.ignoreDefault
+
+loop:
+ for !context.EOL() && !context.Error() {
+ token := context.Peek()
+
+ switch token.Type {
+ case TokenLong, TokenShort:
+ if flag, err := context.flags.parse(context); err != nil {
+ if !ignoreDefault {
+ if cmd := cmds.defaultSubcommand(); cmd != nil {
+ cmd.completionAlts = cmds.cmdNames()
+ context.matchedCmd(cmd)
+ cmds = cmd.cmdGroup
+ break
+ }
+ }
+ return err
+ } else if flag == HelpFlag {
+ ignoreDefault = true
+ }
+
+ case TokenArg:
+ if cmds.have() {
+ selectedDefault := false
+ cmd, ok := cmds.commands[token.String()]
+ if !ok {
+ if !ignoreDefault {
+ if cmd = cmds.defaultSubcommand(); cmd != nil {
+ cmd.completionAlts = cmds.cmdNames()
+ selectedDefault = true
+ }
+ }
+ if cmd == nil {
+ return fmt.Errorf("expected command but got %q", token)
+ }
+ }
+ if cmd == HelpCommand {
+ ignoreDefault = true
+ }
+ cmd.completionAlts = nil
+ context.matchedCmd(cmd)
+ cmds = cmd.cmdGroup
+ if !selectedDefault {
+ context.Next()
+ }
+ } else if context.arguments.have() {
+ if app.noInterspersed {
+ // no more flags
+ context.argsOnly = true
+ }
+ arg := context.nextArg()
+ if arg == nil {
+ break loop
+ }
+ context.matchedArg(arg, token.String())
+ context.Next()
+ } else {
+ break loop
+ }
+
+ case TokenEOL:
+ break loop
+ }
+ }
+
+ // Move to innermost default command.
+ for !ignoreDefault {
+ if cmd := cmds.defaultSubcommand(); cmd != nil {
+ cmd.completionAlts = cmds.cmdNames()
+ context.matchedCmd(cmd)
+ cmds = cmd.cmdGroup
+ } else {
+ break
+ }
+ }
+
+ if context.Error() {
+ return fmt.Errorf("%s", context.Peek().Value)
+ }
+
+ if !context.EOL() {
+ return fmt.Errorf("unexpected %s", context.Peek())
+ }
+
+ // Set defaults for all remaining args.
+ for arg := context.nextArg(); arg != nil && !arg.consumesRemainder(); arg = context.nextArg() {
+ for _, defaultValue := range arg.defaultValues {
+ if err := arg.value.Set(defaultValue); err != nil {
+ return fmt.Errorf("invalid default value '%s' for argument '%s'", defaultValue, arg.name)
+ }
+ }
+ }
+
+ return
+}
--- /dev/null
+package kingpin
+
+import (
+ "net"
+ "net/url"
+ "os"
+ "time"
+
+ "github.com/alecthomas/units"
+)
+
+type Settings interface {
+ SetValue(value Value)
+}
+
+type parserMixin struct {
+ value Value
+ required bool
+}
+
+func (p *parserMixin) SetValue(value Value) {
+ p.value = value
+}
+
+// StringMap provides key=value parsing into a map.
+func (p *parserMixin) StringMap() (target *map[string]string) {
+ target = &(map[string]string{})
+ p.StringMapVar(target)
+ return
+}
+
+// Duration sets the parser to a time.Duration parser.
+func (p *parserMixin) Duration() (target *time.Duration) {
+ target = new(time.Duration)
+ p.DurationVar(target)
+ return
+}
+
+// Bytes parses numeric byte units. eg. 1.5KB
+func (p *parserMixin) Bytes() (target *units.Base2Bytes) {
+ target = new(units.Base2Bytes)
+ p.BytesVar(target)
+ return
+}
+
+// IP sets the parser to a net.IP parser.
+func (p *parserMixin) IP() (target *net.IP) {
+ target = new(net.IP)
+ p.IPVar(target)
+ return
+}
+
+// TCP (host:port) address.
+func (p *parserMixin) TCP() (target **net.TCPAddr) {
+ target = new(*net.TCPAddr)
+ p.TCPVar(target)
+ return
+}
+
+// TCPVar (host:port) address.
+func (p *parserMixin) TCPVar(target **net.TCPAddr) {
+ p.SetValue(newTCPAddrValue(target))
+}
+
+// ExistingFile sets the parser to one that requires and returns an existing file.
+func (p *parserMixin) ExistingFile() (target *string) {
+ target = new(string)
+ p.ExistingFileVar(target)
+ return
+}
+
+// ExistingDir sets the parser to one that requires and returns an existing directory.
+func (p *parserMixin) ExistingDir() (target *string) {
+ target = new(string)
+ p.ExistingDirVar(target)
+ return
+}
+
+// ExistingFileOrDir sets the parser to one that requires and returns an existing file OR directory.
+func (p *parserMixin) ExistingFileOrDir() (target *string) {
+ target = new(string)
+ p.ExistingFileOrDirVar(target)
+ return
+}
+
+// File returns an os.File against an existing file.
+func (p *parserMixin) File() (target **os.File) {
+ target = new(*os.File)
+ p.FileVar(target)
+ return
+}
+
+// File attempts to open a File with os.OpenFile(flag, perm).
+func (p *parserMixin) OpenFile(flag int, perm os.FileMode) (target **os.File) {
+ target = new(*os.File)
+ p.OpenFileVar(target, flag, perm)
+ return
+}
+
+// URL provides a valid, parsed url.URL.
+func (p *parserMixin) URL() (target **url.URL) {
+ target = new(*url.URL)
+ p.URLVar(target)
+ return
+}
+
+// StringMap provides key=value parsing into a map.
+func (p *parserMixin) StringMapVar(target *map[string]string) {
+ p.SetValue(newStringMapValue(target))
+}
+
+// Float sets the parser to a float64 parser.
+func (p *parserMixin) Float() (target *float64) {
+ return p.Float64()
+}
+
+// Float sets the parser to a float64 parser.
+func (p *parserMixin) FloatVar(target *float64) {
+ p.Float64Var(target)
+}
+
+// Duration sets the parser to a time.Duration parser.
+func (p *parserMixin) DurationVar(target *time.Duration) {
+ p.SetValue(newDurationValue(target))
+}
+
+// BytesVar parses numeric byte units. eg. 1.5KB
+func (p *parserMixin) BytesVar(target *units.Base2Bytes) {
+ p.SetValue(newBytesValue(target))
+}
+
+// IP sets the parser to a net.IP parser.
+func (p *parserMixin) IPVar(target *net.IP) {
+ p.SetValue(newIPValue(target))
+}
+
+// ExistingFile sets the parser to one that requires and returns an existing file.
+func (p *parserMixin) ExistingFileVar(target *string) {
+ p.SetValue(newExistingFileValue(target))
+}
+
+// ExistingDir sets the parser to one that requires and returns an existing directory.
+func (p *parserMixin) ExistingDirVar(target *string) {
+ p.SetValue(newExistingDirValue(target))
+}
+
+// ExistingDir sets the parser to one that requires and returns an existing directory.
+func (p *parserMixin) ExistingFileOrDirVar(target *string) {
+ p.SetValue(newExistingFileOrDirValue(target))
+}
+
+// FileVar opens an existing file.
+func (p *parserMixin) FileVar(target **os.File) {
+ p.SetValue(newFileValue(target, os.O_RDONLY, 0))
+}
+
+// OpenFileVar calls os.OpenFile(flag, perm)
+func (p *parserMixin) OpenFileVar(target **os.File, flag int, perm os.FileMode) {
+ p.SetValue(newFileValue(target, flag, perm))
+}
+
+// URL provides a valid, parsed url.URL.
+func (p *parserMixin) URLVar(target **url.URL) {
+ p.SetValue(newURLValue(target))
+}
+
+// URLList provides a parsed list of url.URL values.
+func (p *parserMixin) URLList() (target *[]*url.URL) {
+ target = new([]*url.URL)
+ p.URLListVar(target)
+ return
+}
+
+// URLListVar provides a parsed list of url.URL values.
+func (p *parserMixin) URLListVar(target *[]*url.URL) {
+ p.SetValue(newURLListValue(target))
+}
+
+// Enum allows a value from a set of options.
+func (p *parserMixin) Enum(options ...string) (target *string) {
+ target = new(string)
+ p.EnumVar(target, options...)
+ return
+}
+
+// EnumVar allows a value from a set of options.
+func (p *parserMixin) EnumVar(target *string, options ...string) {
+ p.SetValue(newEnumFlag(target, options...))
+}
+
+// Enums allows a set of values from a set of options.
+func (p *parserMixin) Enums(options ...string) (target *[]string) {
+ target = new([]string)
+ p.EnumsVar(target, options...)
+ return
+}
+
+// EnumVar allows a value from a set of options.
+func (p *parserMixin) EnumsVar(target *[]string, options ...string) {
+ p.SetValue(newEnumsFlag(target, options...))
+}
+
+// A Counter increments a number each time it is encountered.
+func (p *parserMixin) Counter() (target *int) {
+ target = new(int)
+ p.CounterVar(target)
+ return
+}
+
+func (p *parserMixin) CounterVar(target *int) {
+ p.SetValue(newCounterValue(target))
+}
--- /dev/null
+package kingpin
+
+// Default usage template.
+var DefaultUsageTemplate = `{{define "FormatCommand"}}\
+{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
+{{range .Args}} {{if not .Required}}[{{end}}<{{.Name}}>{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}\
+{{end}}\
+
+{{define "FormatCommands"}}\
+{{range .FlattenedCommands}}\
+{{if not .Hidden}}\
+ {{.FullCommand}}{{if .Default}}*{{end}}{{template "FormatCommand" .}}
+{{.Help|Wrap 4}}
+{{end}}\
+{{end}}\
+{{end}}\
+
+{{define "FormatUsage"}}\
+{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
+{{if .Help}}
+{{.Help|Wrap 0}}\
+{{end}}\
+
+{{end}}\
+
+{{if .Context.SelectedCommand}}\
+usage: {{.App.Name}} {{.Context.SelectedCommand}}{{template "FormatUsage" .Context.SelectedCommand}}
+{{else}}\
+usage: {{.App.Name}}{{template "FormatUsage" .App}}
+{{end}}\
+{{if .Context.Flags}}\
+Flags:
+{{.Context.Flags|FlagsToTwoColumns|FormatTwoColumns}}
+{{end}}\
+{{if .Context.Args}}\
+Args:
+{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
+{{end}}\
+{{if .Context.SelectedCommand}}\
+{{if len .Context.SelectedCommand.Commands}}\
+Subcommands:
+{{template "FormatCommands" .Context.SelectedCommand}}
+{{end}}\
+{{else if .App.Commands}}\
+Commands:
+{{template "FormatCommands" .App}}
+{{end}}\
+`
+
+// Usage template where command's optional flags are listed separately
+var SeparateOptionalFlagsUsageTemplate = `{{define "FormatCommand"}}\
+{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
+{{range .Args}} {{if not .Required}}[{{end}}<{{.Name}}>{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}\
+{{end}}\
+
+{{define "FormatCommands"}}\
+{{range .FlattenedCommands}}\
+{{if not .Hidden}}\
+ {{.FullCommand}}{{if .Default}}*{{end}}{{template "FormatCommand" .}}
+{{.Help|Wrap 4}}
+{{end}}\
+{{end}}\
+{{end}}\
+
+{{define "FormatUsage"}}\
+{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
+{{if .Help}}
+{{.Help|Wrap 0}}\
+{{end}}\
+
+{{end}}\
+{{if .Context.SelectedCommand}}\
+usage: {{.App.Name}} {{.Context.SelectedCommand}}{{template "FormatUsage" .Context.SelectedCommand}}
+{{else}}\
+usage: {{.App.Name}}{{template "FormatUsage" .App}}
+{{end}}\
+
+{{if .Context.Flags|RequiredFlags}}\
+Required flags:
+{{.Context.Flags|RequiredFlags|FlagsToTwoColumns|FormatTwoColumns}}
+{{end}}\
+{{if .Context.Flags|OptionalFlags}}\
+Optional flags:
+{{.Context.Flags|OptionalFlags|FlagsToTwoColumns|FormatTwoColumns}}
+{{end}}\
+{{if .Context.Args}}\
+Args:
+{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
+{{end}}\
+{{if .Context.SelectedCommand}}\
+Subcommands:
+{{if .Context.SelectedCommand.Commands}}\
+{{template "FormatCommands" .Context.SelectedCommand}}
+{{end}}\
+{{else if .App.Commands}}\
+Commands:
+{{template "FormatCommands" .App}}
+{{end}}\
+`
+
+// Usage template with compactly formatted commands.
+var CompactUsageTemplate = `{{define "FormatCommand"}}\
+{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
+{{range .Args}} {{if not .Required}}[{{end}}<{{.Name}}>{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}\
+{{end}}\
+
+{{define "FormatCommandList"}}\
+{{range .}}\
+{{if not .Hidden}}\
+{{.Depth|Indent}}{{.Name}}{{if .Default}}*{{end}}{{template "FormatCommand" .}}
+{{end}}\
+{{template "FormatCommandList" .Commands}}\
+{{end}}\
+{{end}}\
+
+{{define "FormatUsage"}}\
+{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
+{{if .Help}}
+{{.Help|Wrap 0}}\
+{{end}}\
+
+{{end}}\
+
+{{if .Context.SelectedCommand}}\
+usage: {{.App.Name}} {{.Context.SelectedCommand}}{{template "FormatUsage" .Context.SelectedCommand}}
+{{else}}\
+usage: {{.App.Name}}{{template "FormatUsage" .App}}
+{{end}}\
+{{if .Context.Flags}}\
+Flags:
+{{.Context.Flags|FlagsToTwoColumns|FormatTwoColumns}}
+{{end}}\
+{{if .Context.Args}}\
+Args:
+{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
+{{end}}\
+{{if .Context.SelectedCommand}}\
+{{if .Context.SelectedCommand.Commands}}\
+Commands:
+ {{.Context.SelectedCommand}}
+{{template "FormatCommandList" .Context.SelectedCommand.Commands}}
+{{end}}\
+{{else if .App.Commands}}\
+Commands:
+{{template "FormatCommandList" .App.Commands}}
+{{end}}\
+`
+
+var ManPageTemplate = `{{define "FormatFlags"}}\
+{{range .Flags}}\
+{{if not .Hidden}}\
+.TP
+\fB{{if .Short}}-{{.Short|Char}}, {{end}}--{{.Name}}{{if not .IsBoolFlag}}={{.FormatPlaceHolder}}{{end}}\\fR
+{{.Help}}
+{{end}}\
+{{end}}\
+{{end}}\
+
+{{define "FormatCommand"}}\
+{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
+{{range .Args}} {{if not .Required}}[{{end}}<{{.Name}}{{if .Default}}*{{end}}>{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}\
+{{end}}\
+
+{{define "FormatCommands"}}\
+{{range .FlattenedCommands}}\
+{{if not .Hidden}}\
+.SS
+\fB{{.FullCommand}}{{template "FormatCommand" .}}\\fR
+.PP
+{{.Help}}
+{{template "FormatFlags" .}}\
+{{end}}\
+{{end}}\
+{{end}}\
+
+{{define "FormatUsage"}}\
+{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}\\fR
+{{end}}\
+
+.TH {{.App.Name}} 1 {{.App.Version}} "{{.App.Author}}"
+.SH "NAME"
+{{.App.Name}}
+.SH "SYNOPSIS"
+.TP
+\fB{{.App.Name}}{{template "FormatUsage" .App}}
+.SH "DESCRIPTION"
+{{.App.Help}}
+.SH "OPTIONS"
+{{template "FormatFlags" .App}}\
+{{if .App.Commands}}\
+.SH "COMMANDS"
+{{template "FormatCommands" .App}}\
+{{end}}\
+`
+
+// Default usage template.
+var LongHelpTemplate = `{{define "FormatCommand"}}\
+{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
+{{range .Args}} {{if not .Required}}[{{end}}<{{.Name}}>{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}\
+{{end}}\
+
+{{define "FormatCommands"}}\
+{{range .FlattenedCommands}}\
+{{if not .Hidden}}\
+ {{.FullCommand}}{{template "FormatCommand" .}}
+{{.Help|Wrap 4}}
+{{with .Flags|FlagsToTwoColumns}}{{FormatTwoColumnsWithIndent . 4 2}}{{end}}
+{{end}}\
+{{end}}\
+{{end}}\
+
+{{define "FormatUsage"}}\
+{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
+{{if .Help}}
+{{.Help|Wrap 0}}\
+{{end}}\
+
+{{end}}\
+
+usage: {{.App.Name}}{{template "FormatUsage" .App}}
+{{if .Context.Flags}}\
+Flags:
+{{.Context.Flags|FlagsToTwoColumns|FormatTwoColumns}}
+{{end}}\
+{{if .Context.Args}}\
+Args:
+{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
+{{end}}\
+{{if .App.Commands}}\
+Commands:
+{{template "FormatCommands" .App}}
+{{end}}\
+`
+
+var BashCompletionTemplate = `
+_{{.App.Name}}_bash_autocomplete() {
+ local cur prev opts base
+ COMPREPLY=()
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ opts=$( ${COMP_WORDS[0]} --completion-bash ${COMP_WORDS[@]:1:$COMP_CWORD} )
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+}
+complete -F _{{.App.Name}}_bash_autocomplete {{.App.Name}}
+
+`
+
+var ZshCompletionTemplate = `
+#compdef {{.App.Name}}
+autoload -U compinit && compinit
+autoload -U bashcompinit && bashcompinit
+
+_{{.App.Name}}_bash_autocomplete() {
+ local cur prev opts base
+ COMPREPLY=()
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ opts=$( ${COMP_WORDS[0]} --completion-bash ${COMP_WORDS[@]:1:$COMP_CWORD} )
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+ return 0
+}
+complete -F _{{.App.Name}}_bash_autocomplete {{.App.Name}}
+`
--- /dev/null
+package kingpin
+
+import (
+ "bytes"
+ "fmt"
+ "go/doc"
+ "io"
+ "strings"
+
+ "github.com/alecthomas/template"
+)
+
+var (
+ preIndent = " "
+)
+
+func formatTwoColumns(w io.Writer, indent, padding, width int, rows [][2]string) {
+ // Find size of first column.
+ s := 0
+ for _, row := range rows {
+ if c := len(row[0]); c > s && c < 30 {
+ s = c
+ }
+ }
+
+ indentStr := strings.Repeat(" ", indent)
+ offsetStr := strings.Repeat(" ", s+padding)
+
+ for _, row := range rows {
+ buf := bytes.NewBuffer(nil)
+ doc.ToText(buf, row[1], "", preIndent, width-s-padding-indent)
+ lines := strings.Split(strings.TrimRight(buf.String(), "\n"), "\n")
+ fmt.Fprintf(w, "%s%-*s%*s", indentStr, s, row[0], padding, "")
+ if len(row[0]) >= 30 {
+ fmt.Fprintf(w, "\n%s%s", indentStr, offsetStr)
+ }
+ fmt.Fprintf(w, "%s\n", lines[0])
+ for _, line := range lines[1:] {
+ fmt.Fprintf(w, "%s%s%s\n", indentStr, offsetStr, line)
+ }
+ }
+}
+
+// Usage writes application usage to w. It parses args to determine
+// appropriate help context, such as which command to show help for.
+func (a *Application) Usage(args []string) {
+ context, err := a.parseContext(true, args)
+ a.FatalIfError(err, "")
+ if err := a.UsageForContextWithTemplate(context, 2, a.usageTemplate); err != nil {
+ panic(err)
+ }
+}
+
+func formatAppUsage(app *ApplicationModel) string {
+ s := []string{app.Name}
+ if len(app.Flags) > 0 {
+ s = append(s, app.FlagSummary())
+ }
+ if len(app.Args) > 0 {
+ s = append(s, app.ArgSummary())
+ }
+ return strings.Join(s, " ")
+}
+
+func formatCmdUsage(app *ApplicationModel, cmd *CmdModel) string {
+ s := []string{app.Name, cmd.String()}
+ if len(app.Flags) > 0 {
+ s = append(s, app.FlagSummary())
+ }
+ if len(app.Args) > 0 {
+ s = append(s, app.ArgSummary())
+ }
+ return strings.Join(s, " ")
+}
+
+func formatFlag(haveShort bool, flag *FlagModel) string {
+ flagString := ""
+ if flag.Short != 0 {
+ flagString += fmt.Sprintf("-%c, --%s", flag.Short, flag.Name)
+ } else {
+ if haveShort {
+ flagString += fmt.Sprintf(" --%s", flag.Name)
+ } else {
+ flagString += fmt.Sprintf("--%s", flag.Name)
+ }
+ }
+ if !flag.IsBoolFlag() {
+ flagString += fmt.Sprintf("=%s", flag.FormatPlaceHolder())
+ }
+ if v, ok := flag.Value.(repeatableFlag); ok && v.IsCumulative() {
+ flagString += " ..."
+ }
+ return flagString
+}
+
+type templateParseContext struct {
+ SelectedCommand *CmdModel
+ *FlagGroupModel
+ *ArgGroupModel
+}
+
+type templateContext struct {
+ App *ApplicationModel
+ Width int
+ Context *templateParseContext
+}
+
+// UsageForContext displays usage information from a ParseContext (obtained from
+// Application.ParseContext() or Action(f) callbacks).
+func (a *Application) UsageForContext(context *ParseContext) error {
+ return a.UsageForContextWithTemplate(context, 2, a.usageTemplate)
+}
+
+// UsageForContextWithTemplate is the base usage function. You generally don't need to use this.
+func (a *Application) UsageForContextWithTemplate(context *ParseContext, indent int, tmpl string) error {
+ width := guessWidth(a.usageWriter)
+ funcs := template.FuncMap{
+ "Indent": func(level int) string {
+ return strings.Repeat(" ", level*indent)
+ },
+ "Wrap": func(indent int, s string) string {
+ buf := bytes.NewBuffer(nil)
+ indentText := strings.Repeat(" ", indent)
+ doc.ToText(buf, s, indentText, " "+indentText, width-indent)
+ return buf.String()
+ },
+ "FormatFlag": formatFlag,
+ "FlagsToTwoColumns": func(f []*FlagModel) [][2]string {
+ rows := [][2]string{}
+ haveShort := false
+ for _, flag := range f {
+ if flag.Short != 0 {
+ haveShort = true
+ break
+ }
+ }
+ for _, flag := range f {
+ if !flag.Hidden {
+ rows = append(rows, [2]string{formatFlag(haveShort, flag), flag.Help})
+ }
+ }
+ return rows
+ },
+ "RequiredFlags": func(f []*FlagModel) []*FlagModel {
+ requiredFlags := []*FlagModel{}
+ for _, flag := range f {
+ if flag.Required {
+ requiredFlags = append(requiredFlags, flag)
+ }
+ }
+ return requiredFlags
+ },
+ "OptionalFlags": func(f []*FlagModel) []*FlagModel {
+ optionalFlags := []*FlagModel{}
+ for _, flag := range f {
+ if !flag.Required {
+ optionalFlags = append(optionalFlags, flag)
+ }
+ }
+ return optionalFlags
+ },
+ "ArgsToTwoColumns": func(a []*ArgModel) [][2]string {
+ rows := [][2]string{}
+ for _, arg := range a {
+ s := "<" + arg.Name + ">"
+ if !arg.Required {
+ s = "[" + s + "]"
+ }
+ rows = append(rows, [2]string{s, arg.Help})
+ }
+ return rows
+ },
+ "FormatTwoColumns": func(rows [][2]string) string {
+ buf := bytes.NewBuffer(nil)
+ formatTwoColumns(buf, indent, indent, width, rows)
+ return buf.String()
+ },
+ "FormatTwoColumnsWithIndent": func(rows [][2]string, indent, padding int) string {
+ buf := bytes.NewBuffer(nil)
+ formatTwoColumns(buf, indent, padding, width, rows)
+ return buf.String()
+ },
+ "FormatAppUsage": formatAppUsage,
+ "FormatCommandUsage": formatCmdUsage,
+ "IsCumulative": func(value Value) bool {
+ r, ok := value.(remainderArg)
+ return ok && r.IsCumulative()
+ },
+ "Char": func(c rune) string {
+ return string(c)
+ },
+ }
+ t, err := template.New("usage").Funcs(funcs).Parse(tmpl)
+ if err != nil {
+ return err
+ }
+ var selectedCommand *CmdModel
+ if context.SelectedCommand != nil {
+ selectedCommand = context.SelectedCommand.Model()
+ }
+ ctx := templateContext{
+ App: a.Model(),
+ Width: width,
+ Context: &templateParseContext{
+ SelectedCommand: selectedCommand,
+ FlagGroupModel: context.flags.Model(),
+ ArgGroupModel: context.arguments.Model(),
+ },
+ }
+ return t.Execute(a.usageWriter, ctx)
+}
--- /dev/null
+package kingpin
+
+//go:generate go run ./cmd/genvalues/main.go
+
+import (
+ "fmt"
+ "net"
+ "net/url"
+ "os"
+ "reflect"
+ "regexp"
+ "strings"
+ "time"
+
+ "github.com/alecthomas/units"
+)
+
+// NOTE: Most of the base type values were lifted from:
+// http://golang.org/src/pkg/flag/flag.go?s=20146:20222
+
+// Value is the interface to the dynamic value stored in a flag.
+// (The default value is represented as a string.)
+//
+// If a Value has an IsBoolFlag() bool method returning true, the command-line
+// parser makes --name equivalent to -name=true rather than using the next
+// command-line argument, and adds a --no-name counterpart for negating the
+// flag.
+type Value interface {
+ String() string
+ Set(string) error
+}
+
+// Getter is an interface that allows the contents of a Value to be retrieved.
+// It wraps the Value interface, rather than being part of it, because it
+// appeared after Go 1 and its compatibility rules. All Value types provided
+// by this package satisfy the Getter interface.
+type Getter interface {
+ Value
+ Get() interface{}
+}
+
+// Optional interface to indicate boolean flags that don't accept a value, and
+// implicitly have a --no-<x> negation counterpart.
+type boolFlag interface {
+ Value
+ IsBoolFlag() bool
+}
+
+// Optional interface for arguments that cumulatively consume all remaining
+// input.
+type remainderArg interface {
+ Value
+ IsCumulative() bool
+}
+
+// Optional interface for flags that can be repeated.
+type repeatableFlag interface {
+ Value
+ IsCumulative() bool
+}
+
+type accumulator struct {
+ element func(value interface{}) Value
+ typ reflect.Type
+ slice reflect.Value
+}
+
+// Use reflection to accumulate values into a slice.
+//
+// target := []string{}
+// newAccumulator(&target, func (value interface{}) Value {
+// return newStringValue(value.(*string))
+// })
+func newAccumulator(slice interface{}, element func(value interface{}) Value) *accumulator {
+ typ := reflect.TypeOf(slice)
+ if typ.Kind() != reflect.Ptr || typ.Elem().Kind() != reflect.Slice {
+ panic("expected a pointer to a slice")
+ }
+ return &accumulator{
+ element: element,
+ typ: typ.Elem().Elem(),
+ slice: reflect.ValueOf(slice),
+ }
+}
+
+func (a *accumulator) String() string {
+ out := []string{}
+ s := a.slice.Elem()
+ for i := 0; i < s.Len(); i++ {
+ out = append(out, a.element(s.Index(i).Addr().Interface()).String())
+ }
+ return strings.Join(out, ",")
+}
+
+func (a *accumulator) Set(value string) error {
+ e := reflect.New(a.typ)
+ if err := a.element(e.Interface()).Set(value); err != nil {
+ return err
+ }
+ slice := reflect.Append(a.slice.Elem(), e.Elem())
+ a.slice.Elem().Set(slice)
+ return nil
+}
+
+func (a *accumulator) Get() interface{} {
+ return a.slice.Interface()
+}
+
+func (a *accumulator) IsCumulative() bool {
+ return true
+}
+
+func (b *boolValue) IsBoolFlag() bool { return true }
+
+// -- time.Duration Value
+type durationValue time.Duration
+
+func newDurationValue(p *time.Duration) *durationValue {
+ return (*durationValue)(p)
+}
+
+func (d *durationValue) Set(s string) error {
+ v, err := time.ParseDuration(s)
+ *d = durationValue(v)
+ return err
+}
+
+func (d *durationValue) Get() interface{} { return time.Duration(*d) }
+
+func (d *durationValue) String() string { return (*time.Duration)(d).String() }
+
+// -- map[string]string Value
+type stringMapValue map[string]string
+
+func newStringMapValue(p *map[string]string) *stringMapValue {
+ return (*stringMapValue)(p)
+}
+
+var stringMapRegex = regexp.MustCompile("[:=]")
+
+func (s *stringMapValue) Set(value string) error {
+ parts := stringMapRegex.Split(value, 2)
+ if len(parts) != 2 {
+ return fmt.Errorf("expected KEY=VALUE got '%s'", value)
+ }
+ (*s)[parts[0]] = parts[1]
+ return nil
+}
+
+func (s *stringMapValue) Get() interface{} {
+ return (map[string]string)(*s)
+}
+
+func (s *stringMapValue) String() string {
+ return fmt.Sprintf("%s", map[string]string(*s))
+}
+
+func (s *stringMapValue) IsCumulative() bool {
+ return true
+}
+
+// -- net.IP Value
+type ipValue net.IP
+
+func newIPValue(p *net.IP) *ipValue {
+ return (*ipValue)(p)
+}
+
+func (i *ipValue) Set(value string) error {
+ if ip := net.ParseIP(value); ip == nil {
+ return fmt.Errorf("'%s' is not an IP address", value)
+ } else {
+ *i = *(*ipValue)(&ip)
+ return nil
+ }
+}
+
+func (i *ipValue) Get() interface{} {
+ return (net.IP)(*i)
+}
+
+func (i *ipValue) String() string {
+ return (*net.IP)(i).String()
+}
+
+// -- *net.TCPAddr Value
+type tcpAddrValue struct {
+ addr **net.TCPAddr
+}
+
+func newTCPAddrValue(p **net.TCPAddr) *tcpAddrValue {
+ return &tcpAddrValue{p}
+}
+
+func (i *tcpAddrValue) Set(value string) error {
+ if addr, err := net.ResolveTCPAddr("tcp", value); err != nil {
+ return fmt.Errorf("'%s' is not a valid TCP address: %s", value, err)
+ } else {
+ *i.addr = addr
+ return nil
+ }
+}
+
+func (t *tcpAddrValue) Get() interface{} {
+ return (*net.TCPAddr)(*t.addr)
+}
+
+func (i *tcpAddrValue) String() string {
+ return (*i.addr).String()
+}
+
+// -- existingFile Value
+
+type fileStatValue struct {
+ path *string
+ predicate func(os.FileInfo) error
+}
+
+func newFileStatValue(p *string, predicate func(os.FileInfo) error) *fileStatValue {
+ return &fileStatValue{
+ path: p,
+ predicate: predicate,
+ }
+}
+
+func (e *fileStatValue) Set(value string) error {
+ if s, err := os.Stat(value); os.IsNotExist(err) {
+ return fmt.Errorf("path '%s' does not exist", value)
+ } else if err != nil {
+ return err
+ } else if err := e.predicate(s); err != nil {
+ return err
+ }
+ *e.path = value
+ return nil
+}
+
+func (f *fileStatValue) Get() interface{} {
+ return (string)(*f.path)
+}
+
+func (e *fileStatValue) String() string {
+ return *e.path
+}
+
+// -- os.File value
+
+type fileValue struct {
+ f **os.File
+ flag int
+ perm os.FileMode
+}
+
+func newFileValue(p **os.File, flag int, perm os.FileMode) *fileValue {
+ return &fileValue{p, flag, perm}
+}
+
+func (f *fileValue) Set(value string) error {
+ if fd, err := os.OpenFile(value, f.flag, f.perm); err != nil {
+ return err
+ } else {
+ *f.f = fd
+ return nil
+ }
+}
+
+func (f *fileValue) Get() interface{} {
+ return (*os.File)(*f.f)
+}
+
+func (f *fileValue) String() string {
+ if *f.f == nil {
+ return "<nil>"
+ }
+ return (*f.f).Name()
+}
+
+// -- url.URL Value
+type urlValue struct {
+ u **url.URL
+}
+
+func newURLValue(p **url.URL) *urlValue {
+ return &urlValue{p}
+}
+
+func (u *urlValue) Set(value string) error {
+ if url, err := url.Parse(value); err != nil {
+ return fmt.Errorf("invalid URL: %s", err)
+ } else {
+ *u.u = url
+ return nil
+ }
+}
+
+func (u *urlValue) Get() interface{} {
+ return (*url.URL)(*u.u)
+}
+
+func (u *urlValue) String() string {
+ if *u.u == nil {
+ return "<nil>"
+ }
+ return (*u.u).String()
+}
+
+// -- []*url.URL Value
+type urlListValue []*url.URL
+
+func newURLListValue(p *[]*url.URL) *urlListValue {
+ return (*urlListValue)(p)
+}
+
+func (u *urlListValue) Set(value string) error {
+ if url, err := url.Parse(value); err != nil {
+ return fmt.Errorf("invalid URL: %s", err)
+ } else {
+ *u = append(*u, url)
+ return nil
+ }
+}
+
+func (u *urlListValue) Get() interface{} {
+ return ([]*url.URL)(*u)
+}
+
+func (u *urlListValue) String() string {
+ out := []string{}
+ for _, url := range *u {
+ out = append(out, url.String())
+ }
+ return strings.Join(out, ",")
+}
+
+func (u *urlListValue) IsCumulative() bool {
+ return true
+}
+
+// A flag whose value must be in a set of options.
+type enumValue struct {
+ value *string
+ options []string
+}
+
+func newEnumFlag(target *string, options ...string) *enumValue {
+ return &enumValue{
+ value: target,
+ options: options,
+ }
+}
+
+func (a *enumValue) String() string {
+ return *a.value
+}
+
+func (a *enumValue) Set(value string) error {
+ for _, v := range a.options {
+ if v == value {
+ *a.value = value
+ return nil
+ }
+ }
+ return fmt.Errorf("enum value must be one of %s, got '%s'", strings.Join(a.options, ","), value)
+}
+
+func (e *enumValue) Get() interface{} {
+ return (string)(*e.value)
+}
+
+// -- []string Enum Value
+type enumsValue struct {
+ value *[]string
+ options []string
+}
+
+func newEnumsFlag(target *[]string, options ...string) *enumsValue {
+ return &enumsValue{
+ value: target,
+ options: options,
+ }
+}
+
+func (s *enumsValue) Set(value string) error {
+ for _, v := range s.options {
+ if v == value {
+ *s.value = append(*s.value, value)
+ return nil
+ }
+ }
+ return fmt.Errorf("enum value must be one of %s, got '%s'", strings.Join(s.options, ","), value)
+}
+
+func (e *enumsValue) Get() interface{} {
+ return ([]string)(*e.value)
+}
+
+func (s *enumsValue) String() string {
+ return strings.Join(*s.value, ",")
+}
+
+func (s *enumsValue) IsCumulative() bool {
+ return true
+}
+
+// -- units.Base2Bytes Value
+type bytesValue units.Base2Bytes
+
+func newBytesValue(p *units.Base2Bytes) *bytesValue {
+ return (*bytesValue)(p)
+}
+
+func (d *bytesValue) Set(s string) error {
+ v, err := units.ParseBase2Bytes(s)
+ *d = bytesValue(v)
+ return err
+}
+
+func (d *bytesValue) Get() interface{} { return units.Base2Bytes(*d) }
+
+func (d *bytesValue) String() string { return (*units.Base2Bytes)(d).String() }
+
+func newExistingFileValue(target *string) *fileStatValue {
+ return newFileStatValue(target, func(s os.FileInfo) error {
+ if s.IsDir() {
+ return fmt.Errorf("'%s' is a directory", s.Name())
+ }
+ return nil
+ })
+}
+
+func newExistingDirValue(target *string) *fileStatValue {
+ return newFileStatValue(target, func(s os.FileInfo) error {
+ if !s.IsDir() {
+ return fmt.Errorf("'%s' is a file", s.Name())
+ }
+ return nil
+ })
+}
+
+func newExistingFileOrDirValue(target *string) *fileStatValue {
+ return newFileStatValue(target, func(s os.FileInfo) error { return nil })
+}
+
+type counterValue int
+
+func newCounterValue(n *int) *counterValue {
+ return (*counterValue)(n)
+}
+
+func (c *counterValue) Set(s string) error {
+ *c++
+ return nil
+}
+
+func (c *counterValue) Get() interface{} { return (int)(*c) }
+func (c *counterValue) IsBoolFlag() bool { return true }
+func (c *counterValue) String() string { return fmt.Sprintf("%d", *c) }
+func (c *counterValue) IsCumulative() bool { return true }
+
+func resolveHost(value string) (net.IP, error) {
+ if ip := net.ParseIP(value); ip != nil {
+ return ip, nil
+ } else {
+ if addr, err := net.ResolveIPAddr("ip", value); err != nil {
+ return nil, err
+ } else {
+ return addr.IP, nil
+ }
+ }
+}
--- /dev/null
+[
+ {"type": "bool", "parser": "strconv.ParseBool(s)"},
+ {"type": "string", "parser": "s, error(nil)", "format": "string(*f.v)", "plural": "Strings"},
+ {"type": "uint", "parser": "strconv.ParseUint(s, 0, 64)", "plural": "Uints"},
+ {"type": "uint8", "parser": "strconv.ParseUint(s, 0, 8)"},
+ {"type": "uint16", "parser": "strconv.ParseUint(s, 0, 16)"},
+ {"type": "uint32", "parser": "strconv.ParseUint(s, 0, 32)"},
+ {"type": "uint64", "parser": "strconv.ParseUint(s, 0, 64)"},
+ {"type": "int", "parser": "strconv.ParseFloat(s, 64)", "plural": "Ints"},
+ {"type": "int8", "parser": "strconv.ParseInt(s, 0, 8)"},
+ {"type": "int16", "parser": "strconv.ParseInt(s, 0, 16)"},
+ {"type": "int32", "parser": "strconv.ParseInt(s, 0, 32)"},
+ {"type": "int64", "parser": "strconv.ParseInt(s, 0, 64)"},
+ {"type": "float64", "parser": "strconv.ParseFloat(s, 64)"},
+ {"type": "float32", "parser": "strconv.ParseFloat(s, 32)"},
+ {"name": "Duration", "type": "time.Duration", "no_value_parser": true},
+ {"name": "IP", "type": "net.IP", "no_value_parser": true},
+ {"name": "TCPAddr", "Type": "*net.TCPAddr", "plural": "TCPList", "no_value_parser": true},
+ {"name": "ExistingFile", "Type": "string", "plural": "ExistingFiles", "no_value_parser": true},
+ {"name": "ExistingDir", "Type": "string", "plural": "ExistingDirs", "no_value_parser": true},
+ {"name": "ExistingFileOrDir", "Type": "string", "plural": "ExistingFilesOrDirs", "no_value_parser": true},
+ {"name": "Regexp", "Type": "*regexp.Regexp", "parser": "regexp.Compile(s)"},
+ {"name": "ResolvedIP", "Type": "net.IP", "parser": "resolveHost(s)", "help": "Resolve a hostname or IP to an IP."},
+ {"name": "HexBytes", "Type": "[]byte", "parser": "hex.DecodeString(s)", "help": "Bytes as a hex string."}
+]
--- /dev/null
+package kingpin
+
+import (
+ "encoding/hex"
+ "fmt"
+ "net"
+ "regexp"
+ "strconv"
+ "time"
+)
+
+// This file is autogenerated by "go generate .". Do not modify.
+
+// -- bool Value
+type boolValue struct{ v *bool }
+
+func newBoolValue(p *bool) *boolValue {
+ return &boolValue{p}
+}
+
+func (f *boolValue) Set(s string) error {
+ v, err := strconv.ParseBool(s)
+ if err == nil {
+ *f.v = (bool)(v)
+ }
+ return err
+}
+
+func (f *boolValue) Get() interface{} { return (bool)(*f.v) }
+
+func (f *boolValue) String() string { return fmt.Sprintf("%v", *f.v) }
+
+// Bool parses the next command-line value as bool.
+func (p *parserMixin) Bool() (target *bool) {
+ target = new(bool)
+ p.BoolVar(target)
+ return
+}
+
+func (p *parserMixin) BoolVar(target *bool) {
+ p.SetValue(newBoolValue(target))
+}
+
+// BoolList accumulates bool values into a slice.
+func (p *parserMixin) BoolList() (target *[]bool) {
+ target = new([]bool)
+ p.BoolListVar(target)
+ return
+}
+
+func (p *parserMixin) BoolListVar(target *[]bool) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newBoolValue(v.(*bool))
+ }))
+}
+
+// -- string Value
+type stringValue struct{ v *string }
+
+func newStringValue(p *string) *stringValue {
+ return &stringValue{p}
+}
+
+func (f *stringValue) Set(s string) error {
+ v, err := s, error(nil)
+ if err == nil {
+ *f.v = (string)(v)
+ }
+ return err
+}
+
+func (f *stringValue) Get() interface{} { return (string)(*f.v) }
+
+func (f *stringValue) String() string { return string(*f.v) }
+
+// String parses the next command-line value as string.
+func (p *parserMixin) String() (target *string) {
+ target = new(string)
+ p.StringVar(target)
+ return
+}
+
+func (p *parserMixin) StringVar(target *string) {
+ p.SetValue(newStringValue(target))
+}
+
+// Strings accumulates string values into a slice.
+func (p *parserMixin) Strings() (target *[]string) {
+ target = new([]string)
+ p.StringsVar(target)
+ return
+}
+
+func (p *parserMixin) StringsVar(target *[]string) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newStringValue(v.(*string))
+ }))
+}
+
+// -- uint Value
+type uintValue struct{ v *uint }
+
+func newUintValue(p *uint) *uintValue {
+ return &uintValue{p}
+}
+
+func (f *uintValue) Set(s string) error {
+ v, err := strconv.ParseUint(s, 0, 64)
+ if err == nil {
+ *f.v = (uint)(v)
+ }
+ return err
+}
+
+func (f *uintValue) Get() interface{} { return (uint)(*f.v) }
+
+func (f *uintValue) String() string { return fmt.Sprintf("%v", *f.v) }
+
+// Uint parses the next command-line value as uint.
+func (p *parserMixin) Uint() (target *uint) {
+ target = new(uint)
+ p.UintVar(target)
+ return
+}
+
+func (p *parserMixin) UintVar(target *uint) {
+ p.SetValue(newUintValue(target))
+}
+
+// Uints accumulates uint values into a slice.
+func (p *parserMixin) Uints() (target *[]uint) {
+ target = new([]uint)
+ p.UintsVar(target)
+ return
+}
+
+func (p *parserMixin) UintsVar(target *[]uint) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newUintValue(v.(*uint))
+ }))
+}
+
+// -- uint8 Value
+type uint8Value struct{ v *uint8 }
+
+func newUint8Value(p *uint8) *uint8Value {
+ return &uint8Value{p}
+}
+
+func (f *uint8Value) Set(s string) error {
+ v, err := strconv.ParseUint(s, 0, 8)
+ if err == nil {
+ *f.v = (uint8)(v)
+ }
+ return err
+}
+
+func (f *uint8Value) Get() interface{} { return (uint8)(*f.v) }
+
+func (f *uint8Value) String() string { return fmt.Sprintf("%v", *f.v) }
+
+// Uint8 parses the next command-line value as uint8.
+func (p *parserMixin) Uint8() (target *uint8) {
+ target = new(uint8)
+ p.Uint8Var(target)
+ return
+}
+
+func (p *parserMixin) Uint8Var(target *uint8) {
+ p.SetValue(newUint8Value(target))
+}
+
+// Uint8List accumulates uint8 values into a slice.
+func (p *parserMixin) Uint8List() (target *[]uint8) {
+ target = new([]uint8)
+ p.Uint8ListVar(target)
+ return
+}
+
+func (p *parserMixin) Uint8ListVar(target *[]uint8) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newUint8Value(v.(*uint8))
+ }))
+}
+
+// -- uint16 Value
+type uint16Value struct{ v *uint16 }
+
+func newUint16Value(p *uint16) *uint16Value {
+ return &uint16Value{p}
+}
+
+func (f *uint16Value) Set(s string) error {
+ v, err := strconv.ParseUint(s, 0, 16)
+ if err == nil {
+ *f.v = (uint16)(v)
+ }
+ return err
+}
+
+func (f *uint16Value) Get() interface{} { return (uint16)(*f.v) }
+
+func (f *uint16Value) String() string { return fmt.Sprintf("%v", *f.v) }
+
+// Uint16 parses the next command-line value as uint16.
+func (p *parserMixin) Uint16() (target *uint16) {
+ target = new(uint16)
+ p.Uint16Var(target)
+ return
+}
+
+func (p *parserMixin) Uint16Var(target *uint16) {
+ p.SetValue(newUint16Value(target))
+}
+
+// Uint16List accumulates uint16 values into a slice.
+func (p *parserMixin) Uint16List() (target *[]uint16) {
+ target = new([]uint16)
+ p.Uint16ListVar(target)
+ return
+}
+
+func (p *parserMixin) Uint16ListVar(target *[]uint16) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newUint16Value(v.(*uint16))
+ }))
+}
+
+// -- uint32 Value
+type uint32Value struct{ v *uint32 }
+
+func newUint32Value(p *uint32) *uint32Value {
+ return &uint32Value{p}
+}
+
+func (f *uint32Value) Set(s string) error {
+ v, err := strconv.ParseUint(s, 0, 32)
+ if err == nil {
+ *f.v = (uint32)(v)
+ }
+ return err
+}
+
+func (f *uint32Value) Get() interface{} { return (uint32)(*f.v) }
+
+func (f *uint32Value) String() string { return fmt.Sprintf("%v", *f.v) }
+
+// Uint32 parses the next command-line value as uint32.
+func (p *parserMixin) Uint32() (target *uint32) {
+ target = new(uint32)
+ p.Uint32Var(target)
+ return
+}
+
+func (p *parserMixin) Uint32Var(target *uint32) {
+ p.SetValue(newUint32Value(target))
+}
+
+// Uint32List accumulates uint32 values into a slice.
+func (p *parserMixin) Uint32List() (target *[]uint32) {
+ target = new([]uint32)
+ p.Uint32ListVar(target)
+ return
+}
+
+func (p *parserMixin) Uint32ListVar(target *[]uint32) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newUint32Value(v.(*uint32))
+ }))
+}
+
+// -- uint64 Value
+type uint64Value struct{ v *uint64 }
+
+func newUint64Value(p *uint64) *uint64Value {
+ return &uint64Value{p}
+}
+
+func (f *uint64Value) Set(s string) error {
+ v, err := strconv.ParseUint(s, 0, 64)
+ if err == nil {
+ *f.v = (uint64)(v)
+ }
+ return err
+}
+
+func (f *uint64Value) Get() interface{} { return (uint64)(*f.v) }
+
+func (f *uint64Value) String() string { return fmt.Sprintf("%v", *f.v) }
+
+// Uint64 parses the next command-line value as uint64.
+func (p *parserMixin) Uint64() (target *uint64) {
+ target = new(uint64)
+ p.Uint64Var(target)
+ return
+}
+
+func (p *parserMixin) Uint64Var(target *uint64) {
+ p.SetValue(newUint64Value(target))
+}
+
+// Uint64List accumulates uint64 values into a slice.
+func (p *parserMixin) Uint64List() (target *[]uint64) {
+ target = new([]uint64)
+ p.Uint64ListVar(target)
+ return
+}
+
+func (p *parserMixin) Uint64ListVar(target *[]uint64) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newUint64Value(v.(*uint64))
+ }))
+}
+
+// -- int Value
+type intValue struct{ v *int }
+
+func newIntValue(p *int) *intValue {
+ return &intValue{p}
+}
+
+func (f *intValue) Set(s string) error {
+ v, err := strconv.ParseFloat(s, 64)
+ if err == nil {
+ *f.v = (int)(v)
+ }
+ return err
+}
+
+func (f *intValue) Get() interface{} { return (int)(*f.v) }
+
+func (f *intValue) String() string { return fmt.Sprintf("%v", *f.v) }
+
+// Int parses the next command-line value as int.
+func (p *parserMixin) Int() (target *int) {
+ target = new(int)
+ p.IntVar(target)
+ return
+}
+
+func (p *parserMixin) IntVar(target *int) {
+ p.SetValue(newIntValue(target))
+}
+
+// Ints accumulates int values into a slice.
+func (p *parserMixin) Ints() (target *[]int) {
+ target = new([]int)
+ p.IntsVar(target)
+ return
+}
+
+func (p *parserMixin) IntsVar(target *[]int) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newIntValue(v.(*int))
+ }))
+}
+
+// -- int8 Value
+type int8Value struct{ v *int8 }
+
+func newInt8Value(p *int8) *int8Value {
+ return &int8Value{p}
+}
+
+func (f *int8Value) Set(s string) error {
+ v, err := strconv.ParseInt(s, 0, 8)
+ if err == nil {
+ *f.v = (int8)(v)
+ }
+ return err
+}
+
+func (f *int8Value) Get() interface{} { return (int8)(*f.v) }
+
+func (f *int8Value) String() string { return fmt.Sprintf("%v", *f.v) }
+
+// Int8 parses the next command-line value as int8.
+func (p *parserMixin) Int8() (target *int8) {
+ target = new(int8)
+ p.Int8Var(target)
+ return
+}
+
+func (p *parserMixin) Int8Var(target *int8) {
+ p.SetValue(newInt8Value(target))
+}
+
+// Int8List accumulates int8 values into a slice.
+func (p *parserMixin) Int8List() (target *[]int8) {
+ target = new([]int8)
+ p.Int8ListVar(target)
+ return
+}
+
+func (p *parserMixin) Int8ListVar(target *[]int8) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newInt8Value(v.(*int8))
+ }))
+}
+
+// -- int16 Value
+type int16Value struct{ v *int16 }
+
+func newInt16Value(p *int16) *int16Value {
+ return &int16Value{p}
+}
+
+func (f *int16Value) Set(s string) error {
+ v, err := strconv.ParseInt(s, 0, 16)
+ if err == nil {
+ *f.v = (int16)(v)
+ }
+ return err
+}
+
+func (f *int16Value) Get() interface{} { return (int16)(*f.v) }
+
+func (f *int16Value) String() string { return fmt.Sprintf("%v", *f.v) }
+
+// Int16 parses the next command-line value as int16.
+func (p *parserMixin) Int16() (target *int16) {
+ target = new(int16)
+ p.Int16Var(target)
+ return
+}
+
+func (p *parserMixin) Int16Var(target *int16) {
+ p.SetValue(newInt16Value(target))
+}
+
+// Int16List accumulates int16 values into a slice.
+func (p *parserMixin) Int16List() (target *[]int16) {
+ target = new([]int16)
+ p.Int16ListVar(target)
+ return
+}
+
+func (p *parserMixin) Int16ListVar(target *[]int16) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newInt16Value(v.(*int16))
+ }))
+}
+
+// -- int32 Value
+type int32Value struct{ v *int32 }
+
+func newInt32Value(p *int32) *int32Value {
+ return &int32Value{p}
+}
+
+func (f *int32Value) Set(s string) error {
+ v, err := strconv.ParseInt(s, 0, 32)
+ if err == nil {
+ *f.v = (int32)(v)
+ }
+ return err
+}
+
+func (f *int32Value) Get() interface{} { return (int32)(*f.v) }
+
+func (f *int32Value) String() string { return fmt.Sprintf("%v", *f.v) }
+
+// Int32 parses the next command-line value as int32.
+func (p *parserMixin) Int32() (target *int32) {
+ target = new(int32)
+ p.Int32Var(target)
+ return
+}
+
+func (p *parserMixin) Int32Var(target *int32) {
+ p.SetValue(newInt32Value(target))
+}
+
+// Int32List accumulates int32 values into a slice.
+func (p *parserMixin) Int32List() (target *[]int32) {
+ target = new([]int32)
+ p.Int32ListVar(target)
+ return
+}
+
+func (p *parserMixin) Int32ListVar(target *[]int32) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newInt32Value(v.(*int32))
+ }))
+}
+
+// -- int64 Value
+type int64Value struct{ v *int64 }
+
+func newInt64Value(p *int64) *int64Value {
+ return &int64Value{p}
+}
+
+func (f *int64Value) Set(s string) error {
+ v, err := strconv.ParseInt(s, 0, 64)
+ if err == nil {
+ *f.v = (int64)(v)
+ }
+ return err
+}
+
+func (f *int64Value) Get() interface{} { return (int64)(*f.v) }
+
+func (f *int64Value) String() string { return fmt.Sprintf("%v", *f.v) }
+
+// Int64 parses the next command-line value as int64.
+func (p *parserMixin) Int64() (target *int64) {
+ target = new(int64)
+ p.Int64Var(target)
+ return
+}
+
+func (p *parserMixin) Int64Var(target *int64) {
+ p.SetValue(newInt64Value(target))
+}
+
+// Int64List accumulates int64 values into a slice.
+func (p *parserMixin) Int64List() (target *[]int64) {
+ target = new([]int64)
+ p.Int64ListVar(target)
+ return
+}
+
+func (p *parserMixin) Int64ListVar(target *[]int64) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newInt64Value(v.(*int64))
+ }))
+}
+
+// -- float64 Value
+type float64Value struct{ v *float64 }
+
+func newFloat64Value(p *float64) *float64Value {
+ return &float64Value{p}
+}
+
+func (f *float64Value) Set(s string) error {
+ v, err := strconv.ParseFloat(s, 64)
+ if err == nil {
+ *f.v = (float64)(v)
+ }
+ return err
+}
+
+func (f *float64Value) Get() interface{} { return (float64)(*f.v) }
+
+func (f *float64Value) String() string { return fmt.Sprintf("%v", *f.v) }
+
+// Float64 parses the next command-line value as float64.
+func (p *parserMixin) Float64() (target *float64) {
+ target = new(float64)
+ p.Float64Var(target)
+ return
+}
+
+func (p *parserMixin) Float64Var(target *float64) {
+ p.SetValue(newFloat64Value(target))
+}
+
+// Float64List accumulates float64 values into a slice.
+func (p *parserMixin) Float64List() (target *[]float64) {
+ target = new([]float64)
+ p.Float64ListVar(target)
+ return
+}
+
+func (p *parserMixin) Float64ListVar(target *[]float64) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newFloat64Value(v.(*float64))
+ }))
+}
+
+// -- float32 Value
+type float32Value struct{ v *float32 }
+
+func newFloat32Value(p *float32) *float32Value {
+ return &float32Value{p}
+}
+
+func (f *float32Value) Set(s string) error {
+ v, err := strconv.ParseFloat(s, 32)
+ if err == nil {
+ *f.v = (float32)(v)
+ }
+ return err
+}
+
+func (f *float32Value) Get() interface{} { return (float32)(*f.v) }
+
+func (f *float32Value) String() string { return fmt.Sprintf("%v", *f.v) }
+
+// Float32 parses the next command-line value as float32.
+func (p *parserMixin) Float32() (target *float32) {
+ target = new(float32)
+ p.Float32Var(target)
+ return
+}
+
+func (p *parserMixin) Float32Var(target *float32) {
+ p.SetValue(newFloat32Value(target))
+}
+
+// Float32List accumulates float32 values into a slice.
+func (p *parserMixin) Float32List() (target *[]float32) {
+ target = new([]float32)
+ p.Float32ListVar(target)
+ return
+}
+
+func (p *parserMixin) Float32ListVar(target *[]float32) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newFloat32Value(v.(*float32))
+ }))
+}
+
+// DurationList accumulates time.Duration values into a slice.
+func (p *parserMixin) DurationList() (target *[]time.Duration) {
+ target = new([]time.Duration)
+ p.DurationListVar(target)
+ return
+}
+
+func (p *parserMixin) DurationListVar(target *[]time.Duration) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newDurationValue(v.(*time.Duration))
+ }))
+}
+
+// IPList accumulates net.IP values into a slice.
+func (p *parserMixin) IPList() (target *[]net.IP) {
+ target = new([]net.IP)
+ p.IPListVar(target)
+ return
+}
+
+func (p *parserMixin) IPListVar(target *[]net.IP) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newIPValue(v.(*net.IP))
+ }))
+}
+
+// TCPList accumulates *net.TCPAddr values into a slice.
+func (p *parserMixin) TCPList() (target *[]*net.TCPAddr) {
+ target = new([]*net.TCPAddr)
+ p.TCPListVar(target)
+ return
+}
+
+func (p *parserMixin) TCPListVar(target *[]*net.TCPAddr) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newTCPAddrValue(v.(**net.TCPAddr))
+ }))
+}
+
+// ExistingFiles accumulates string values into a slice.
+func (p *parserMixin) ExistingFiles() (target *[]string) {
+ target = new([]string)
+ p.ExistingFilesVar(target)
+ return
+}
+
+func (p *parserMixin) ExistingFilesVar(target *[]string) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newExistingFileValue(v.(*string))
+ }))
+}
+
+// ExistingDirs accumulates string values into a slice.
+func (p *parserMixin) ExistingDirs() (target *[]string) {
+ target = new([]string)
+ p.ExistingDirsVar(target)
+ return
+}
+
+func (p *parserMixin) ExistingDirsVar(target *[]string) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newExistingDirValue(v.(*string))
+ }))
+}
+
+// ExistingFilesOrDirs accumulates string values into a slice.
+func (p *parserMixin) ExistingFilesOrDirs() (target *[]string) {
+ target = new([]string)
+ p.ExistingFilesOrDirsVar(target)
+ return
+}
+
+func (p *parserMixin) ExistingFilesOrDirsVar(target *[]string) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newExistingFileOrDirValue(v.(*string))
+ }))
+}
+
+// -- *regexp.Regexp Value
+type regexpValue struct{ v **regexp.Regexp }
+
+func newRegexpValue(p **regexp.Regexp) *regexpValue {
+ return ®expValue{p}
+}
+
+func (f *regexpValue) Set(s string) error {
+ v, err := regexp.Compile(s)
+ if err == nil {
+ *f.v = (*regexp.Regexp)(v)
+ }
+ return err
+}
+
+func (f *regexpValue) Get() interface{} { return (*regexp.Regexp)(*f.v) }
+
+func (f *regexpValue) String() string { return fmt.Sprintf("%v", *f.v) }
+
+// Regexp parses the next command-line value as *regexp.Regexp.
+func (p *parserMixin) Regexp() (target **regexp.Regexp) {
+ target = new(*regexp.Regexp)
+ p.RegexpVar(target)
+ return
+}
+
+func (p *parserMixin) RegexpVar(target **regexp.Regexp) {
+ p.SetValue(newRegexpValue(target))
+}
+
+// RegexpList accumulates *regexp.Regexp values into a slice.
+func (p *parserMixin) RegexpList() (target *[]*regexp.Regexp) {
+ target = new([]*regexp.Regexp)
+ p.RegexpListVar(target)
+ return
+}
+
+func (p *parserMixin) RegexpListVar(target *[]*regexp.Regexp) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newRegexpValue(v.(**regexp.Regexp))
+ }))
+}
+
+// -- net.IP Value
+type resolvedIPValue struct{ v *net.IP }
+
+func newResolvedIPValue(p *net.IP) *resolvedIPValue {
+ return &resolvedIPValue{p}
+}
+
+func (f *resolvedIPValue) Set(s string) error {
+ v, err := resolveHost(s)
+ if err == nil {
+ *f.v = (net.IP)(v)
+ }
+ return err
+}
+
+func (f *resolvedIPValue) Get() interface{} { return (net.IP)(*f.v) }
+
+func (f *resolvedIPValue) String() string { return fmt.Sprintf("%v", *f.v) }
+
+// Resolve a hostname or IP to an IP.
+func (p *parserMixin) ResolvedIP() (target *net.IP) {
+ target = new(net.IP)
+ p.ResolvedIPVar(target)
+ return
+}
+
+func (p *parserMixin) ResolvedIPVar(target *net.IP) {
+ p.SetValue(newResolvedIPValue(target))
+}
+
+// ResolvedIPList accumulates net.IP values into a slice.
+func (p *parserMixin) ResolvedIPList() (target *[]net.IP) {
+ target = new([]net.IP)
+ p.ResolvedIPListVar(target)
+ return
+}
+
+func (p *parserMixin) ResolvedIPListVar(target *[]net.IP) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newResolvedIPValue(v.(*net.IP))
+ }))
+}
+
+// -- []byte Value
+type hexBytesValue struct{ v *[]byte }
+
+func newHexBytesValue(p *[]byte) *hexBytesValue {
+ return &hexBytesValue{p}
+}
+
+func (f *hexBytesValue) Set(s string) error {
+ v, err := hex.DecodeString(s)
+ if err == nil {
+ *f.v = ([]byte)(v)
+ }
+ return err
+}
+
+func (f *hexBytesValue) Get() interface{} { return ([]byte)(*f.v) }
+
+func (f *hexBytesValue) String() string { return fmt.Sprintf("%v", *f.v) }
+
+// Bytes as a hex string.
+func (p *parserMixin) HexBytes() (target *[]byte) {
+ target = new([]byte)
+ p.HexBytesVar(target)
+ return
+}
+
+func (p *parserMixin) HexBytesVar(target *[]byte) {
+ p.SetValue(newHexBytesValue(target))
+}
+
+// HexBytesList accumulates []byte values into a slice.
+func (p *parserMixin) HexBytesList() (target *[][]byte) {
+ target = new([][]byte)
+ p.HexBytesListVar(target)
+ return
+}
+
+func (p *parserMixin) HexBytesListVar(target *[][]byte) {
+ p.SetValue(newAccumulator(target, func(v interface{}) Value {
+ return newHexBytesValue(v.(*[]byte))
+ }))
+}
--- /dev/null
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
--- /dev/null
+The following files were ported to Go from C files of libyaml, and thus
+are still covered by their original copyright and license:
+
+ apic.go
+ emitterc.go
+ parserc.go
+ readerc.go
+ scannerc.go
+ writerc.go
+ yamlh.go
+ yamlprivateh.go
+
+Copyright (c) 2006 Kirill Simonov
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
--- /dev/null
+Copyright 2011-2016 Canonical Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
--- /dev/null
+# YAML support for the Go language
+
+Introduction
+------------
+
+The yaml package enables Go programs to comfortably encode and decode YAML
+values. It was developed within [Canonical](https://www.canonical.com) as
+part of the [juju](https://juju.ubuntu.com) project, and is based on a
+pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML)
+C library to parse and generate YAML data quickly and reliably.
+
+Compatibility
+-------------
+
+The yaml package supports most of YAML 1.1 and 1.2, including support for
+anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
+implemented, and base-60 floats from YAML 1.1 are purposefully not
+supported since they're a poor design and are gone in YAML 1.2.
+
+Installation and usage
+----------------------
+
+The import path for the package is *gopkg.in/yaml.v2*.
+
+To install it, run:
+
+ go get gopkg.in/yaml.v2
+
+API documentation
+-----------------
+
+If opened in a browser, the import path itself leads to the API documentation:
+
+ * [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2)
+
+API stability
+-------------
+
+The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in).
+
+
+License
+-------
+
+The yaml package is licensed under the Apache License 2.0. Please see the LICENSE file for details.
+
+
+Example
+-------
+
+```Go
+package main
+
+import (
+ "fmt"
+ "log"
+
+ "gopkg.in/yaml.v2"
+)
+
+var data = `
+a: Easy!
+b:
+ c: 2
+ d: [3, 4]
+`
+
+// Note: struct fields must be public in order for unmarshal to
+// correctly populate the data.
+type T struct {
+ A string
+ B struct {
+ RenamedC int `yaml:"c"`
+ D []int `yaml:",flow"`
+ }
+}
+
+func main() {
+ t := T{}
+
+ err := yaml.Unmarshal([]byte(data), &t)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- t:\n%v\n\n", t)
+
+ d, err := yaml.Marshal(&t)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- t dump:\n%s\n\n", string(d))
+
+ m := make(map[interface{}]interface{})
+
+ err = yaml.Unmarshal([]byte(data), &m)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- m:\n%v\n\n", m)
+
+ d, err = yaml.Marshal(&m)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- m dump:\n%s\n\n", string(d))
+}
+```
+
+This example will generate the following output:
+
+```
+--- t:
+{Easy! {2 [3 4]}}
+
+--- t dump:
+a: Easy!
+b:
+ c: 2
+ d: [3, 4]
+
+
+--- m:
+map[a:Easy! b:map[c:2 d:[3 4]]]
+
+--- m dump:
+a: Easy!
+b:
+ c: 2
+ d:
+ - 3
+ - 4
+```
+
--- /dev/null
+package yaml
+
+import (
+ "io"
+)
+
+func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) {
+ //fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens))
+
+ // Check if we can move the queue at the beginning of the buffer.
+ if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) {
+ if parser.tokens_head != len(parser.tokens) {
+ copy(parser.tokens, parser.tokens[parser.tokens_head:])
+ }
+ parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head]
+ parser.tokens_head = 0
+ }
+ parser.tokens = append(parser.tokens, *token)
+ if pos < 0 {
+ return
+ }
+ copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:])
+ parser.tokens[parser.tokens_head+pos] = *token
+}
+
+// Create a new parser object.
+func yaml_parser_initialize(parser *yaml_parser_t) bool {
+ *parser = yaml_parser_t{
+ raw_buffer: make([]byte, 0, input_raw_buffer_size),
+ buffer: make([]byte, 0, input_buffer_size),
+ }
+ return true
+}
+
+// Destroy a parser object.
+func yaml_parser_delete(parser *yaml_parser_t) {
+ *parser = yaml_parser_t{}
+}
+
+// String read handler.
+func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
+ if parser.input_pos == len(parser.input) {
+ return 0, io.EOF
+ }
+ n = copy(buffer, parser.input[parser.input_pos:])
+ parser.input_pos += n
+ return n, nil
+}
+
+// Reader read handler.
+func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
+ return parser.input_reader.Read(buffer)
+}
+
+// Set a string input.
+func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
+ if parser.read_handler != nil {
+ panic("must set the input source only once")
+ }
+ parser.read_handler = yaml_string_read_handler
+ parser.input = input
+ parser.input_pos = 0
+}
+
+// Set a file input.
+func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) {
+ if parser.read_handler != nil {
+ panic("must set the input source only once")
+ }
+ parser.read_handler = yaml_reader_read_handler
+ parser.input_reader = r
+}
+
+// Set the source encoding.
+func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) {
+ if parser.encoding != yaml_ANY_ENCODING {
+ panic("must set the encoding only once")
+ }
+ parser.encoding = encoding
+}
+
+// Create a new emitter object.
+func yaml_emitter_initialize(emitter *yaml_emitter_t) {
+ *emitter = yaml_emitter_t{
+ buffer: make([]byte, output_buffer_size),
+ raw_buffer: make([]byte, 0, output_raw_buffer_size),
+ states: make([]yaml_emitter_state_t, 0, initial_stack_size),
+ events: make([]yaml_event_t, 0, initial_queue_size),
+ }
+}
+
+// Destroy an emitter object.
+func yaml_emitter_delete(emitter *yaml_emitter_t) {
+ *emitter = yaml_emitter_t{}
+}
+
+// String write handler.
+func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
+ *emitter.output_buffer = append(*emitter.output_buffer, buffer...)
+ return nil
+}
+
+// yaml_writer_write_handler uses emitter.output_writer to write the
+// emitted text.
+func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
+ _, err := emitter.output_writer.Write(buffer)
+ return err
+}
+
+// Set a string output.
+func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) {
+ if emitter.write_handler != nil {
+ panic("must set the output target only once")
+ }
+ emitter.write_handler = yaml_string_write_handler
+ emitter.output_buffer = output_buffer
+}
+
+// Set a file output.
+func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) {
+ if emitter.write_handler != nil {
+ panic("must set the output target only once")
+ }
+ emitter.write_handler = yaml_writer_write_handler
+ emitter.output_writer = w
+}
+
+// Set the output encoding.
+func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) {
+ if emitter.encoding != yaml_ANY_ENCODING {
+ panic("must set the output encoding only once")
+ }
+ emitter.encoding = encoding
+}
+
+// Set the canonical output style.
+func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) {
+ emitter.canonical = canonical
+}
+
+//// Set the indentation increment.
+func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) {
+ if indent < 2 || indent > 9 {
+ indent = 2
+ }
+ emitter.best_indent = indent
+}
+
+// Set the preferred line width.
+func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) {
+ if width < 0 {
+ width = -1
+ }
+ emitter.best_width = width
+}
+
+// Set if unescaped non-ASCII characters are allowed.
+func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) {
+ emitter.unicode = unicode
+}
+
+// Set the preferred line break character.
+func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) {
+ emitter.line_break = line_break
+}
+
+///*
+// * Destroy a token object.
+// */
+//
+//YAML_DECLARE(void)
+//yaml_token_delete(yaml_token_t *token)
+//{
+// assert(token); // Non-NULL token object expected.
+//
+// switch (token.type)
+// {
+// case YAML_TAG_DIRECTIVE_TOKEN:
+// yaml_free(token.data.tag_directive.handle);
+// yaml_free(token.data.tag_directive.prefix);
+// break;
+//
+// case YAML_ALIAS_TOKEN:
+// yaml_free(token.data.alias.value);
+// break;
+//
+// case YAML_ANCHOR_TOKEN:
+// yaml_free(token.data.anchor.value);
+// break;
+//
+// case YAML_TAG_TOKEN:
+// yaml_free(token.data.tag.handle);
+// yaml_free(token.data.tag.suffix);
+// break;
+//
+// case YAML_SCALAR_TOKEN:
+// yaml_free(token.data.scalar.value);
+// break;
+//
+// default:
+// break;
+// }
+//
+// memset(token, 0, sizeof(yaml_token_t));
+//}
+//
+///*
+// * Check if a string is a valid UTF-8 sequence.
+// *
+// * Check 'reader.c' for more details on UTF-8 encoding.
+// */
+//
+//static int
+//yaml_check_utf8(yaml_char_t *start, size_t length)
+//{
+// yaml_char_t *end = start+length;
+// yaml_char_t *pointer = start;
+//
+// while (pointer < end) {
+// unsigned char octet;
+// unsigned int width;
+// unsigned int value;
+// size_t k;
+//
+// octet = pointer[0];
+// width = (octet & 0x80) == 0x00 ? 1 :
+// (octet & 0xE0) == 0xC0 ? 2 :
+// (octet & 0xF0) == 0xE0 ? 3 :
+// (octet & 0xF8) == 0xF0 ? 4 : 0;
+// value = (octet & 0x80) == 0x00 ? octet & 0x7F :
+// (octet & 0xE0) == 0xC0 ? octet & 0x1F :
+// (octet & 0xF0) == 0xE0 ? octet & 0x0F :
+// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
+// if (!width) return 0;
+// if (pointer+width > end) return 0;
+// for (k = 1; k < width; k ++) {
+// octet = pointer[k];
+// if ((octet & 0xC0) != 0x80) return 0;
+// value = (value << 6) + (octet & 0x3F);
+// }
+// if (!((width == 1) ||
+// (width == 2 && value >= 0x80) ||
+// (width == 3 && value >= 0x800) ||
+// (width == 4 && value >= 0x10000))) return 0;
+//
+// pointer += width;
+// }
+//
+// return 1;
+//}
+//
+
+// Create STREAM-START.
+func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) {
+ *event = yaml_event_t{
+ typ: yaml_STREAM_START_EVENT,
+ encoding: encoding,
+ }
+}
+
+// Create STREAM-END.
+func yaml_stream_end_event_initialize(event *yaml_event_t) {
+ *event = yaml_event_t{
+ typ: yaml_STREAM_END_EVENT,
+ }
+}
+
+// Create DOCUMENT-START.
+func yaml_document_start_event_initialize(
+ event *yaml_event_t,
+ version_directive *yaml_version_directive_t,
+ tag_directives []yaml_tag_directive_t,
+ implicit bool,
+) {
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_START_EVENT,
+ version_directive: version_directive,
+ tag_directives: tag_directives,
+ implicit: implicit,
+ }
+}
+
+// Create DOCUMENT-END.
+func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) {
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_END_EVENT,
+ implicit: implicit,
+ }
+}
+
+///*
+// * Create ALIAS.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_alias_event_initialize(event *yaml_event_t, anchor *yaml_char_t)
+//{
+// mark yaml_mark_t = { 0, 0, 0 }
+// anchor_copy *yaml_char_t = NULL
+//
+// assert(event) // Non-NULL event object is expected.
+// assert(anchor) // Non-NULL anchor is expected.
+//
+// if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0
+//
+// anchor_copy = yaml_strdup(anchor)
+// if (!anchor_copy)
+// return 0
+//
+// ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark)
+//
+// return 1
+//}
+
+// Create SCALAR.
+func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool {
+ *event = yaml_event_t{
+ typ: yaml_SCALAR_EVENT,
+ anchor: anchor,
+ tag: tag,
+ value: value,
+ implicit: plain_implicit,
+ quoted_implicit: quoted_implicit,
+ style: yaml_style_t(style),
+ }
+ return true
+}
+
+// Create SEQUENCE-START.
+func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool {
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_START_EVENT,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(style),
+ }
+ return true
+}
+
+// Create SEQUENCE-END.
+func yaml_sequence_end_event_initialize(event *yaml_event_t) bool {
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_END_EVENT,
+ }
+ return true
+}
+
+// Create MAPPING-START.
+func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) {
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_START_EVENT,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(style),
+ }
+}
+
+// Create MAPPING-END.
+func yaml_mapping_end_event_initialize(event *yaml_event_t) {
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_END_EVENT,
+ }
+}
+
+// Destroy an event object.
+func yaml_event_delete(event *yaml_event_t) {
+ *event = yaml_event_t{}
+}
+
+///*
+// * Create a document object.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_initialize(document *yaml_document_t,
+// version_directive *yaml_version_directive_t,
+// tag_directives_start *yaml_tag_directive_t,
+// tag_directives_end *yaml_tag_directive_t,
+// start_implicit int, end_implicit int)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// struct {
+// start *yaml_node_t
+// end *yaml_node_t
+// top *yaml_node_t
+// } nodes = { NULL, NULL, NULL }
+// version_directive_copy *yaml_version_directive_t = NULL
+// struct {
+// start *yaml_tag_directive_t
+// end *yaml_tag_directive_t
+// top *yaml_tag_directive_t
+// } tag_directives_copy = { NULL, NULL, NULL }
+// value yaml_tag_directive_t = { NULL, NULL }
+// mark yaml_mark_t = { 0, 0, 0 }
+//
+// assert(document) // Non-NULL document object is expected.
+// assert((tag_directives_start && tag_directives_end) ||
+// (tag_directives_start == tag_directives_end))
+// // Valid tag directives are expected.
+//
+// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error
+//
+// if (version_directive) {
+// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t))
+// if (!version_directive_copy) goto error
+// version_directive_copy.major = version_directive.major
+// version_directive_copy.minor = version_directive.minor
+// }
+//
+// if (tag_directives_start != tag_directives_end) {
+// tag_directive *yaml_tag_directive_t
+// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
+// goto error
+// for (tag_directive = tag_directives_start
+// tag_directive != tag_directives_end; tag_directive ++) {
+// assert(tag_directive.handle)
+// assert(tag_directive.prefix)
+// if (!yaml_check_utf8(tag_directive.handle,
+// strlen((char *)tag_directive.handle)))
+// goto error
+// if (!yaml_check_utf8(tag_directive.prefix,
+// strlen((char *)tag_directive.prefix)))
+// goto error
+// value.handle = yaml_strdup(tag_directive.handle)
+// value.prefix = yaml_strdup(tag_directive.prefix)
+// if (!value.handle || !value.prefix) goto error
+// if (!PUSH(&context, tag_directives_copy, value))
+// goto error
+// value.handle = NULL
+// value.prefix = NULL
+// }
+// }
+//
+// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
+// tag_directives_copy.start, tag_directives_copy.top,
+// start_implicit, end_implicit, mark, mark)
+//
+// return 1
+//
+//error:
+// STACK_DEL(&context, nodes)
+// yaml_free(version_directive_copy)
+// while (!STACK_EMPTY(&context, tag_directives_copy)) {
+// value yaml_tag_directive_t = POP(&context, tag_directives_copy)
+// yaml_free(value.handle)
+// yaml_free(value.prefix)
+// }
+// STACK_DEL(&context, tag_directives_copy)
+// yaml_free(value.handle)
+// yaml_free(value.prefix)
+//
+// return 0
+//}
+//
+///*
+// * Destroy a document object.
+// */
+//
+//YAML_DECLARE(void)
+//yaml_document_delete(document *yaml_document_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// tag_directive *yaml_tag_directive_t
+//
+// context.error = YAML_NO_ERROR // Eliminate a compiler warning.
+//
+// assert(document) // Non-NULL document object is expected.
+//
+// while (!STACK_EMPTY(&context, document.nodes)) {
+// node yaml_node_t = POP(&context, document.nodes)
+// yaml_free(node.tag)
+// switch (node.type) {
+// case YAML_SCALAR_NODE:
+// yaml_free(node.data.scalar.value)
+// break
+// case YAML_SEQUENCE_NODE:
+// STACK_DEL(&context, node.data.sequence.items)
+// break
+// case YAML_MAPPING_NODE:
+// STACK_DEL(&context, node.data.mapping.pairs)
+// break
+// default:
+// assert(0) // Should not happen.
+// }
+// }
+// STACK_DEL(&context, document.nodes)
+//
+// yaml_free(document.version_directive)
+// for (tag_directive = document.tag_directives.start
+// tag_directive != document.tag_directives.end
+// tag_directive++) {
+// yaml_free(tag_directive.handle)
+// yaml_free(tag_directive.prefix)
+// }
+// yaml_free(document.tag_directives.start)
+//
+// memset(document, 0, sizeof(yaml_document_t))
+//}
+//
+///**
+// * Get a document node.
+// */
+//
+//YAML_DECLARE(yaml_node_t *)
+//yaml_document_get_node(document *yaml_document_t, index int)
+//{
+// assert(document) // Non-NULL document object is expected.
+//
+// if (index > 0 && document.nodes.start + index <= document.nodes.top) {
+// return document.nodes.start + index - 1
+// }
+// return NULL
+//}
+//
+///**
+// * Get the root object.
+// */
+//
+//YAML_DECLARE(yaml_node_t *)
+//yaml_document_get_root_node(document *yaml_document_t)
+//{
+// assert(document) // Non-NULL document object is expected.
+//
+// if (document.nodes.top != document.nodes.start) {
+// return document.nodes.start
+// }
+// return NULL
+//}
+//
+///*
+// * Add a scalar node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_scalar(document *yaml_document_t,
+// tag *yaml_char_t, value *yaml_char_t, length int,
+// style yaml_scalar_style_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// mark yaml_mark_t = { 0, 0, 0 }
+// tag_copy *yaml_char_t = NULL
+// value_copy *yaml_char_t = NULL
+// node yaml_node_t
+//
+// assert(document) // Non-NULL document object is expected.
+// assert(value) // Non-NULL value is expected.
+//
+// if (!tag) {
+// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG
+// }
+//
+// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+// tag_copy = yaml_strdup(tag)
+// if (!tag_copy) goto error
+//
+// if (length < 0) {
+// length = strlen((char *)value)
+// }
+//
+// if (!yaml_check_utf8(value, length)) goto error
+// value_copy = yaml_malloc(length+1)
+// if (!value_copy) goto error
+// memcpy(value_copy, value, length)
+// value_copy[length] = '\0'
+//
+// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark)
+// if (!PUSH(&context, document.nodes, node)) goto error
+//
+// return document.nodes.top - document.nodes.start
+//
+//error:
+// yaml_free(tag_copy)
+// yaml_free(value_copy)
+//
+// return 0
+//}
+//
+///*
+// * Add a sequence node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_sequence(document *yaml_document_t,
+// tag *yaml_char_t, style yaml_sequence_style_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// mark yaml_mark_t = { 0, 0, 0 }
+// tag_copy *yaml_char_t = NULL
+// struct {
+// start *yaml_node_item_t
+// end *yaml_node_item_t
+// top *yaml_node_item_t
+// } items = { NULL, NULL, NULL }
+// node yaml_node_t
+//
+// assert(document) // Non-NULL document object is expected.
+//
+// if (!tag) {
+// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG
+// }
+//
+// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+// tag_copy = yaml_strdup(tag)
+// if (!tag_copy) goto error
+//
+// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error
+//
+// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
+// style, mark, mark)
+// if (!PUSH(&context, document.nodes, node)) goto error
+//
+// return document.nodes.top - document.nodes.start
+//
+//error:
+// STACK_DEL(&context, items)
+// yaml_free(tag_copy)
+//
+// return 0
+//}
+//
+///*
+// * Add a mapping node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_mapping(document *yaml_document_t,
+// tag *yaml_char_t, style yaml_mapping_style_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// mark yaml_mark_t = { 0, 0, 0 }
+// tag_copy *yaml_char_t = NULL
+// struct {
+// start *yaml_node_pair_t
+// end *yaml_node_pair_t
+// top *yaml_node_pair_t
+// } pairs = { NULL, NULL, NULL }
+// node yaml_node_t
+//
+// assert(document) // Non-NULL document object is expected.
+//
+// if (!tag) {
+// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG
+// }
+//
+// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+// tag_copy = yaml_strdup(tag)
+// if (!tag_copy) goto error
+//
+// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error
+//
+// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
+// style, mark, mark)
+// if (!PUSH(&context, document.nodes, node)) goto error
+//
+// return document.nodes.top - document.nodes.start
+//
+//error:
+// STACK_DEL(&context, pairs)
+// yaml_free(tag_copy)
+//
+// return 0
+//}
+//
+///*
+// * Append an item to a sequence node.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_append_sequence_item(document *yaml_document_t,
+// sequence int, item int)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+//
+// assert(document) // Non-NULL document is required.
+// assert(sequence > 0
+// && document.nodes.start + sequence <= document.nodes.top)
+// // Valid sequence id is required.
+// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE)
+// // A sequence node is required.
+// assert(item > 0 && document.nodes.start + item <= document.nodes.top)
+// // Valid item id is required.
+//
+// if (!PUSH(&context,
+// document.nodes.start[sequence-1].data.sequence.items, item))
+// return 0
+//
+// return 1
+//}
+//
+///*
+// * Append a pair of a key and a value to a mapping node.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_append_mapping_pair(document *yaml_document_t,
+// mapping int, key int, value int)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+//
+// pair yaml_node_pair_t
+//
+// assert(document) // Non-NULL document is required.
+// assert(mapping > 0
+// && document.nodes.start + mapping <= document.nodes.top)
+// // Valid mapping id is required.
+// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE)
+// // A mapping node is required.
+// assert(key > 0 && document.nodes.start + key <= document.nodes.top)
+// // Valid key id is required.
+// assert(value > 0 && document.nodes.start + value <= document.nodes.top)
+// // Valid value id is required.
+//
+// pair.key = key
+// pair.value = value
+//
+// if (!PUSH(&context,
+// document.nodes.start[mapping-1].data.mapping.pairs, pair))
+// return 0
+//
+// return 1
+//}
+//
+//
--- /dev/null
+package yaml
+
+import (
+ "encoding"
+ "encoding/base64"
+ "fmt"
+ "io"
+ "math"
+ "reflect"
+ "strconv"
+ "time"
+)
+
+const (
+ documentNode = 1 << iota
+ mappingNode
+ sequenceNode
+ scalarNode
+ aliasNode
+)
+
+type node struct {
+ kind int
+ line, column int
+ tag string
+ // For an alias node, alias holds the resolved alias.
+ alias *node
+ value string
+ implicit bool
+ children []*node
+ anchors map[string]*node
+}
+
+// ----------------------------------------------------------------------------
+// Parser, produces a node tree out of a libyaml event stream.
+
+type parser struct {
+ parser yaml_parser_t
+ event yaml_event_t
+ doc *node
+ doneInit bool
+}
+
+func newParser(b []byte) *parser {
+ p := parser{}
+ if !yaml_parser_initialize(&p.parser) {
+ panic("failed to initialize YAML emitter")
+ }
+ if len(b) == 0 {
+ b = []byte{'\n'}
+ }
+ yaml_parser_set_input_string(&p.parser, b)
+ return &p
+}
+
+func newParserFromReader(r io.Reader) *parser {
+ p := parser{}
+ if !yaml_parser_initialize(&p.parser) {
+ panic("failed to initialize YAML emitter")
+ }
+ yaml_parser_set_input_reader(&p.parser, r)
+ return &p
+}
+
+func (p *parser) init() {
+ if p.doneInit {
+ return
+ }
+ p.expect(yaml_STREAM_START_EVENT)
+ p.doneInit = true
+}
+
+func (p *parser) destroy() {
+ if p.event.typ != yaml_NO_EVENT {
+ yaml_event_delete(&p.event)
+ }
+ yaml_parser_delete(&p.parser)
+}
+
+// expect consumes an event from the event stream and
+// checks that it's of the expected type.
+func (p *parser) expect(e yaml_event_type_t) {
+ if p.event.typ == yaml_NO_EVENT {
+ if !yaml_parser_parse(&p.parser, &p.event) {
+ p.fail()
+ }
+ }
+ if p.event.typ == yaml_STREAM_END_EVENT {
+ failf("attempted to go past the end of stream; corrupted value?")
+ }
+ if p.event.typ != e {
+ p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ)
+ p.fail()
+ }
+ yaml_event_delete(&p.event)
+ p.event.typ = yaml_NO_EVENT
+}
+
+// peek peeks at the next event in the event stream,
+// puts the results into p.event and returns the event type.
+func (p *parser) peek() yaml_event_type_t {
+ if p.event.typ != yaml_NO_EVENT {
+ return p.event.typ
+ }
+ if !yaml_parser_parse(&p.parser, &p.event) {
+ p.fail()
+ }
+ return p.event.typ
+}
+
+func (p *parser) fail() {
+ var where string
+ var line int
+ if p.parser.problem_mark.line != 0 {
+ line = p.parser.problem_mark.line
+ // Scanner errors don't iterate line before returning error
+ if p.parser.error == yaml_SCANNER_ERROR {
+ line++
+ }
+ } else if p.parser.context_mark.line != 0 {
+ line = p.parser.context_mark.line
+ }
+ if line != 0 {
+ where = "line " + strconv.Itoa(line) + ": "
+ }
+ var msg string
+ if len(p.parser.problem) > 0 {
+ msg = p.parser.problem
+ } else {
+ msg = "unknown problem parsing YAML content"
+ }
+ failf("%s%s", where, msg)
+}
+
+func (p *parser) anchor(n *node, anchor []byte) {
+ if anchor != nil {
+ p.doc.anchors[string(anchor)] = n
+ }
+}
+
+func (p *parser) parse() *node {
+ p.init()
+ switch p.peek() {
+ case yaml_SCALAR_EVENT:
+ return p.scalar()
+ case yaml_ALIAS_EVENT:
+ return p.alias()
+ case yaml_MAPPING_START_EVENT:
+ return p.mapping()
+ case yaml_SEQUENCE_START_EVENT:
+ return p.sequence()
+ case yaml_DOCUMENT_START_EVENT:
+ return p.document()
+ case yaml_STREAM_END_EVENT:
+ // Happens when attempting to decode an empty buffer.
+ return nil
+ default:
+ panic("attempted to parse unknown event: " + p.event.typ.String())
+ }
+}
+
+func (p *parser) node(kind int) *node {
+ return &node{
+ kind: kind,
+ line: p.event.start_mark.line,
+ column: p.event.start_mark.column,
+ }
+}
+
+func (p *parser) document() *node {
+ n := p.node(documentNode)
+ n.anchors = make(map[string]*node)
+ p.doc = n
+ p.expect(yaml_DOCUMENT_START_EVENT)
+ n.children = append(n.children, p.parse())
+ p.expect(yaml_DOCUMENT_END_EVENT)
+ return n
+}
+
+func (p *parser) alias() *node {
+ n := p.node(aliasNode)
+ n.value = string(p.event.anchor)
+ n.alias = p.doc.anchors[n.value]
+ if n.alias == nil {
+ failf("unknown anchor '%s' referenced", n.value)
+ }
+ p.expect(yaml_ALIAS_EVENT)
+ return n
+}
+
+func (p *parser) scalar() *node {
+ n := p.node(scalarNode)
+ n.value = string(p.event.value)
+ n.tag = string(p.event.tag)
+ n.implicit = p.event.implicit
+ p.anchor(n, p.event.anchor)
+ p.expect(yaml_SCALAR_EVENT)
+ return n
+}
+
+func (p *parser) sequence() *node {
+ n := p.node(sequenceNode)
+ p.anchor(n, p.event.anchor)
+ p.expect(yaml_SEQUENCE_START_EVENT)
+ for p.peek() != yaml_SEQUENCE_END_EVENT {
+ n.children = append(n.children, p.parse())
+ }
+ p.expect(yaml_SEQUENCE_END_EVENT)
+ return n
+}
+
+func (p *parser) mapping() *node {
+ n := p.node(mappingNode)
+ p.anchor(n, p.event.anchor)
+ p.expect(yaml_MAPPING_START_EVENT)
+ for p.peek() != yaml_MAPPING_END_EVENT {
+ n.children = append(n.children, p.parse(), p.parse())
+ }
+ p.expect(yaml_MAPPING_END_EVENT)
+ return n
+}
+
+// ----------------------------------------------------------------------------
+// Decoder, unmarshals a node into a provided value.
+
+type decoder struct {
+ doc *node
+ aliases map[*node]bool
+ mapType reflect.Type
+ terrors []string
+ strict bool
+}
+
+var (
+ mapItemType = reflect.TypeOf(MapItem{})
+ durationType = reflect.TypeOf(time.Duration(0))
+ defaultMapType = reflect.TypeOf(map[interface{}]interface{}{})
+ ifaceType = defaultMapType.Elem()
+ timeType = reflect.TypeOf(time.Time{})
+ ptrTimeType = reflect.TypeOf(&time.Time{})
+)
+
+func newDecoder(strict bool) *decoder {
+ d := &decoder{mapType: defaultMapType, strict: strict}
+ d.aliases = make(map[*node]bool)
+ return d
+}
+
+func (d *decoder) terror(n *node, tag string, out reflect.Value) {
+ if n.tag != "" {
+ tag = n.tag
+ }
+ value := n.value
+ if tag != yaml_SEQ_TAG && tag != yaml_MAP_TAG {
+ if len(value) > 10 {
+ value = " `" + value[:7] + "...`"
+ } else {
+ value = " `" + value + "`"
+ }
+ }
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.line+1, shortTag(tag), value, out.Type()))
+}
+
+func (d *decoder) callUnmarshaler(n *node, u Unmarshaler) (good bool) {
+ terrlen := len(d.terrors)
+ err := u.UnmarshalYAML(func(v interface{}) (err error) {
+ defer handleErr(&err)
+ d.unmarshal(n, reflect.ValueOf(v))
+ if len(d.terrors) > terrlen {
+ issues := d.terrors[terrlen:]
+ d.terrors = d.terrors[:terrlen]
+ return &TypeError{issues}
+ }
+ return nil
+ })
+ if e, ok := err.(*TypeError); ok {
+ d.terrors = append(d.terrors, e.Errors...)
+ return false
+ }
+ if err != nil {
+ fail(err)
+ }
+ return true
+}
+
+// d.prepare initializes and dereferences pointers and calls UnmarshalYAML
+// if a value is found to implement it.
+// It returns the initialized and dereferenced out value, whether
+// unmarshalling was already done by UnmarshalYAML, and if so whether
+// its types unmarshalled appropriately.
+//
+// If n holds a null value, prepare returns before doing anything.
+func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
+ if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "~" || n.value == "" && n.implicit) {
+ return out, false, false
+ }
+ again := true
+ for again {
+ again = false
+ if out.Kind() == reflect.Ptr {
+ if out.IsNil() {
+ out.Set(reflect.New(out.Type().Elem()))
+ }
+ out = out.Elem()
+ again = true
+ }
+ if out.CanAddr() {
+ if u, ok := out.Addr().Interface().(Unmarshaler); ok {
+ good = d.callUnmarshaler(n, u)
+ return out, true, good
+ }
+ }
+ }
+ return out, false, false
+}
+
+func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) {
+ switch n.kind {
+ case documentNode:
+ return d.document(n, out)
+ case aliasNode:
+ return d.alias(n, out)
+ }
+ out, unmarshaled, good := d.prepare(n, out)
+ if unmarshaled {
+ return good
+ }
+ switch n.kind {
+ case scalarNode:
+ good = d.scalar(n, out)
+ case mappingNode:
+ good = d.mapping(n, out)
+ case sequenceNode:
+ good = d.sequence(n, out)
+ default:
+ panic("internal error: unknown node kind: " + strconv.Itoa(n.kind))
+ }
+ return good
+}
+
+func (d *decoder) document(n *node, out reflect.Value) (good bool) {
+ if len(n.children) == 1 {
+ d.doc = n
+ d.unmarshal(n.children[0], out)
+ return true
+ }
+ return false
+}
+
+func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
+ if d.aliases[n] {
+ // TODO this could actually be allowed in some circumstances.
+ failf("anchor '%s' value contains itself", n.value)
+ }
+ d.aliases[n] = true
+ good = d.unmarshal(n.alias, out)
+ delete(d.aliases, n)
+ return good
+}
+
+var zeroValue reflect.Value
+
+func resetMap(out reflect.Value) {
+ for _, k := range out.MapKeys() {
+ out.SetMapIndex(k, zeroValue)
+ }
+}
+
+func (d *decoder) scalar(n *node, out reflect.Value) bool {
+ var tag string
+ var resolved interface{}
+ if n.tag == "" && !n.implicit {
+ tag = yaml_STR_TAG
+ resolved = n.value
+ } else {
+ tag, resolved = resolve(n.tag, n.value)
+ if tag == yaml_BINARY_TAG {
+ data, err := base64.StdEncoding.DecodeString(resolved.(string))
+ if err != nil {
+ failf("!!binary value contains invalid base64 data")
+ }
+ resolved = string(data)
+ }
+ }
+ if resolved == nil {
+ if out.Kind() == reflect.Map && !out.CanAddr() {
+ resetMap(out)
+ } else {
+ out.Set(reflect.Zero(out.Type()))
+ }
+ return true
+ }
+ if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
+ // We've resolved to exactly the type we want, so use that.
+ out.Set(resolvedv)
+ return true
+ }
+ // Perhaps we can use the value as a TextUnmarshaler to
+ // set its value.
+ if out.CanAddr() {
+ u, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
+ if ok {
+ var text []byte
+ if tag == yaml_BINARY_TAG {
+ text = []byte(resolved.(string))
+ } else {
+ // We let any value be unmarshaled into TextUnmarshaler.
+ // That might be more lax than we'd like, but the
+ // TextUnmarshaler itself should bowl out any dubious values.
+ text = []byte(n.value)
+ }
+ err := u.UnmarshalText(text)
+ if err != nil {
+ fail(err)
+ }
+ return true
+ }
+ }
+ switch out.Kind() {
+ case reflect.String:
+ if tag == yaml_BINARY_TAG {
+ out.SetString(resolved.(string))
+ return true
+ }
+ if resolved != nil {
+ out.SetString(n.value)
+ return true
+ }
+ case reflect.Interface:
+ if resolved == nil {
+ out.Set(reflect.Zero(out.Type()))
+ } else if tag == yaml_TIMESTAMP_TAG {
+ // It looks like a timestamp but for backward compatibility
+ // reasons we set it as a string, so that code that unmarshals
+ // timestamp-like values into interface{} will continue to
+ // see a string and not a time.Time.
+ // TODO(v3) Drop this.
+ out.Set(reflect.ValueOf(n.value))
+ } else {
+ out.Set(reflect.ValueOf(resolved))
+ }
+ return true
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ switch resolved := resolved.(type) {
+ case int:
+ if !out.OverflowInt(int64(resolved)) {
+ out.SetInt(int64(resolved))
+ return true
+ }
+ case int64:
+ if !out.OverflowInt(resolved) {
+ out.SetInt(resolved)
+ return true
+ }
+ case uint64:
+ if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
+ out.SetInt(int64(resolved))
+ return true
+ }
+ case float64:
+ if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
+ out.SetInt(int64(resolved))
+ return true
+ }
+ case string:
+ if out.Type() == durationType {
+ d, err := time.ParseDuration(resolved)
+ if err == nil {
+ out.SetInt(int64(d))
+ return true
+ }
+ }
+ }
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ switch resolved := resolved.(type) {
+ case int:
+ if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ case int64:
+ if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ case uint64:
+ if !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ case float64:
+ if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ }
+ case reflect.Bool:
+ switch resolved := resolved.(type) {
+ case bool:
+ out.SetBool(resolved)
+ return true
+ }
+ case reflect.Float32, reflect.Float64:
+ switch resolved := resolved.(type) {
+ case int:
+ out.SetFloat(float64(resolved))
+ return true
+ case int64:
+ out.SetFloat(float64(resolved))
+ return true
+ case uint64:
+ out.SetFloat(float64(resolved))
+ return true
+ case float64:
+ out.SetFloat(resolved)
+ return true
+ }
+ case reflect.Struct:
+ if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
+ out.Set(resolvedv)
+ return true
+ }
+ case reflect.Ptr:
+ if out.Type().Elem() == reflect.TypeOf(resolved) {
+ // TODO DOes this make sense? When is out a Ptr except when decoding a nil value?
+ elem := reflect.New(out.Type().Elem())
+ elem.Elem().Set(reflect.ValueOf(resolved))
+ out.Set(elem)
+ return true
+ }
+ }
+ d.terror(n, tag, out)
+ return false
+}
+
+func settableValueOf(i interface{}) reflect.Value {
+ v := reflect.ValueOf(i)
+ sv := reflect.New(v.Type()).Elem()
+ sv.Set(v)
+ return sv
+}
+
+func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
+ l := len(n.children)
+
+ var iface reflect.Value
+ switch out.Kind() {
+ case reflect.Slice:
+ out.Set(reflect.MakeSlice(out.Type(), l, l))
+ case reflect.Array:
+ if l != out.Len() {
+ failf("invalid array: want %d elements but got %d", out.Len(), l)
+ }
+ case reflect.Interface:
+ // No type hints. Will have to use a generic sequence.
+ iface = out
+ out = settableValueOf(make([]interface{}, l))
+ default:
+ d.terror(n, yaml_SEQ_TAG, out)
+ return false
+ }
+ et := out.Type().Elem()
+
+ j := 0
+ for i := 0; i < l; i++ {
+ e := reflect.New(et).Elem()
+ if ok := d.unmarshal(n.children[i], e); ok {
+ out.Index(j).Set(e)
+ j++
+ }
+ }
+ if out.Kind() != reflect.Array {
+ out.Set(out.Slice(0, j))
+ }
+ if iface.IsValid() {
+ iface.Set(out)
+ }
+ return true
+}
+
+func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
+ switch out.Kind() {
+ case reflect.Struct:
+ return d.mappingStruct(n, out)
+ case reflect.Slice:
+ return d.mappingSlice(n, out)
+ case reflect.Map:
+ // okay
+ case reflect.Interface:
+ if d.mapType.Kind() == reflect.Map {
+ iface := out
+ out = reflect.MakeMap(d.mapType)
+ iface.Set(out)
+ } else {
+ slicev := reflect.New(d.mapType).Elem()
+ if !d.mappingSlice(n, slicev) {
+ return false
+ }
+ out.Set(slicev)
+ return true
+ }
+ default:
+ d.terror(n, yaml_MAP_TAG, out)
+ return false
+ }
+ outt := out.Type()
+ kt := outt.Key()
+ et := outt.Elem()
+
+ mapType := d.mapType
+ if outt.Key() == ifaceType && outt.Elem() == ifaceType {
+ d.mapType = outt
+ }
+
+ if out.IsNil() {
+ out.Set(reflect.MakeMap(outt))
+ }
+ l := len(n.children)
+ for i := 0; i < l; i += 2 {
+ if isMerge(n.children[i]) {
+ d.merge(n.children[i+1], out)
+ continue
+ }
+ k := reflect.New(kt).Elem()
+ if d.unmarshal(n.children[i], k) {
+ kkind := k.Kind()
+ if kkind == reflect.Interface {
+ kkind = k.Elem().Kind()
+ }
+ if kkind == reflect.Map || kkind == reflect.Slice {
+ failf("invalid map key: %#v", k.Interface())
+ }
+ e := reflect.New(et).Elem()
+ if d.unmarshal(n.children[i+1], e) {
+ d.setMapIndex(n.children[i+1], out, k, e)
+ }
+ }
+ }
+ d.mapType = mapType
+ return true
+}
+
+func (d *decoder) setMapIndex(n *node, out, k, v reflect.Value) {
+ if d.strict && out.MapIndex(k) != zeroValue {
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: key %#v already set in map", n.line+1, k.Interface()))
+ return
+ }
+ out.SetMapIndex(k, v)
+}
+
+func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) {
+ outt := out.Type()
+ if outt.Elem() != mapItemType {
+ d.terror(n, yaml_MAP_TAG, out)
+ return false
+ }
+
+ mapType := d.mapType
+ d.mapType = outt
+
+ var slice []MapItem
+ var l = len(n.children)
+ for i := 0; i < l; i += 2 {
+ if isMerge(n.children[i]) {
+ d.merge(n.children[i+1], out)
+ continue
+ }
+ item := MapItem{}
+ k := reflect.ValueOf(&item.Key).Elem()
+ if d.unmarshal(n.children[i], k) {
+ v := reflect.ValueOf(&item.Value).Elem()
+ if d.unmarshal(n.children[i+1], v) {
+ slice = append(slice, item)
+ }
+ }
+ }
+ out.Set(reflect.ValueOf(slice))
+ d.mapType = mapType
+ return true
+}
+
+func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
+ sinfo, err := getStructInfo(out.Type())
+ if err != nil {
+ panic(err)
+ }
+ name := settableValueOf("")
+ l := len(n.children)
+
+ var inlineMap reflect.Value
+ var elemType reflect.Type
+ if sinfo.InlineMap != -1 {
+ inlineMap = out.Field(sinfo.InlineMap)
+ inlineMap.Set(reflect.New(inlineMap.Type()).Elem())
+ elemType = inlineMap.Type().Elem()
+ }
+
+ var doneFields []bool
+ if d.strict {
+ doneFields = make([]bool, len(sinfo.FieldsList))
+ }
+ for i := 0; i < l; i += 2 {
+ ni := n.children[i]
+ if isMerge(ni) {
+ d.merge(n.children[i+1], out)
+ continue
+ }
+ if !d.unmarshal(ni, name) {
+ continue
+ }
+ if info, ok := sinfo.FieldsMap[name.String()]; ok {
+ if d.strict {
+ if doneFields[info.Id] {
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.line+1, name.String(), out.Type()))
+ continue
+ }
+ doneFields[info.Id] = true
+ }
+ var field reflect.Value
+ if info.Inline == nil {
+ field = out.Field(info.Num)
+ } else {
+ field = out.FieldByIndex(info.Inline)
+ }
+ d.unmarshal(n.children[i+1], field)
+ } else if sinfo.InlineMap != -1 {
+ if inlineMap.IsNil() {
+ inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
+ }
+ value := reflect.New(elemType).Elem()
+ d.unmarshal(n.children[i+1], value)
+ d.setMapIndex(n.children[i+1], inlineMap, name, value)
+ } else if d.strict {
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.line+1, name.String(), out.Type()))
+ }
+ }
+ return true
+}
+
+func failWantMap() {
+ failf("map merge requires map or sequence of maps as the value")
+}
+
+func (d *decoder) merge(n *node, out reflect.Value) {
+ switch n.kind {
+ case mappingNode:
+ d.unmarshal(n, out)
+ case aliasNode:
+ an, ok := d.doc.anchors[n.value]
+ if ok && an.kind != mappingNode {
+ failWantMap()
+ }
+ d.unmarshal(n, out)
+ case sequenceNode:
+ // Step backwards as earlier nodes take precedence.
+ for i := len(n.children) - 1; i >= 0; i-- {
+ ni := n.children[i]
+ if ni.kind == aliasNode {
+ an, ok := d.doc.anchors[ni.value]
+ if ok && an.kind != mappingNode {
+ failWantMap()
+ }
+ } else if ni.kind != mappingNode {
+ failWantMap()
+ }
+ d.unmarshal(ni, out)
+ }
+ default:
+ failWantMap()
+ }
+}
+
+func isMerge(n *node) bool {
+ return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == yaml_MERGE_TAG)
+}
--- /dev/null
+package yaml
+
+import (
+ "bytes"
+ "fmt"
+)
+
+// Flush the buffer if needed.
+func flush(emitter *yaml_emitter_t) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) {
+ return yaml_emitter_flush(emitter)
+ }
+ return true
+}
+
+// Put a character to the output buffer.
+func put(emitter *yaml_emitter_t, value byte) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+ return false
+ }
+ emitter.buffer[emitter.buffer_pos] = value
+ emitter.buffer_pos++
+ emitter.column++
+ return true
+}
+
+// Put a line break to the output buffer.
+func put_break(emitter *yaml_emitter_t) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+ return false
+ }
+ switch emitter.line_break {
+ case yaml_CR_BREAK:
+ emitter.buffer[emitter.buffer_pos] = '\r'
+ emitter.buffer_pos += 1
+ case yaml_LN_BREAK:
+ emitter.buffer[emitter.buffer_pos] = '\n'
+ emitter.buffer_pos += 1
+ case yaml_CRLN_BREAK:
+ emitter.buffer[emitter.buffer_pos+0] = '\r'
+ emitter.buffer[emitter.buffer_pos+1] = '\n'
+ emitter.buffer_pos += 2
+ default:
+ panic("unknown line break setting")
+ }
+ emitter.column = 0
+ emitter.line++
+ return true
+}
+
+// Copy a character from a string into buffer.
+func write(emitter *yaml_emitter_t, s []byte, i *int) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+ return false
+ }
+ p := emitter.buffer_pos
+ w := width(s[*i])
+ switch w {
+ case 4:
+ emitter.buffer[p+3] = s[*i+3]
+ fallthrough
+ case 3:
+ emitter.buffer[p+2] = s[*i+2]
+ fallthrough
+ case 2:
+ emitter.buffer[p+1] = s[*i+1]
+ fallthrough
+ case 1:
+ emitter.buffer[p+0] = s[*i+0]
+ default:
+ panic("unknown character width")
+ }
+ emitter.column++
+ emitter.buffer_pos += w
+ *i += w
+ return true
+}
+
+// Write a whole string into buffer.
+func write_all(emitter *yaml_emitter_t, s []byte) bool {
+ for i := 0; i < len(s); {
+ if !write(emitter, s, &i) {
+ return false
+ }
+ }
+ return true
+}
+
+// Copy a line break character from a string into buffer.
+func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool {
+ if s[*i] == '\n' {
+ if !put_break(emitter) {
+ return false
+ }
+ *i++
+ } else {
+ if !write(emitter, s, i) {
+ return false
+ }
+ emitter.column = 0
+ emitter.line++
+ }
+ return true
+}
+
+// Set an emitter error and return false.
+func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool {
+ emitter.error = yaml_EMITTER_ERROR
+ emitter.problem = problem
+ return false
+}
+
+// Emit an event.
+func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ emitter.events = append(emitter.events, *event)
+ for !yaml_emitter_need_more_events(emitter) {
+ event := &emitter.events[emitter.events_head]
+ if !yaml_emitter_analyze_event(emitter, event) {
+ return false
+ }
+ if !yaml_emitter_state_machine(emitter, event) {
+ return false
+ }
+ yaml_event_delete(event)
+ emitter.events_head++
+ }
+ return true
+}
+
+// Check if we need to accumulate more events before emitting.
+//
+// We accumulate extra
+// - 1 event for DOCUMENT-START
+// - 2 events for SEQUENCE-START
+// - 3 events for MAPPING-START
+//
+func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool {
+ if emitter.events_head == len(emitter.events) {
+ return true
+ }
+ var accumulate int
+ switch emitter.events[emitter.events_head].typ {
+ case yaml_DOCUMENT_START_EVENT:
+ accumulate = 1
+ break
+ case yaml_SEQUENCE_START_EVENT:
+ accumulate = 2
+ break
+ case yaml_MAPPING_START_EVENT:
+ accumulate = 3
+ break
+ default:
+ return false
+ }
+ if len(emitter.events)-emitter.events_head > accumulate {
+ return false
+ }
+ var level int
+ for i := emitter.events_head; i < len(emitter.events); i++ {
+ switch emitter.events[i].typ {
+ case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT:
+ level++
+ case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT:
+ level--
+ }
+ if level == 0 {
+ return false
+ }
+ }
+ return true
+}
+
+// Append a directive to the directives stack.
+func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool {
+ for i := 0; i < len(emitter.tag_directives); i++ {
+ if bytes.Equal(value.handle, emitter.tag_directives[i].handle) {
+ if allow_duplicates {
+ return true
+ }
+ return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive")
+ }
+ }
+
+ // [Go] Do we actually need to copy this given garbage collection
+ // and the lack of deallocating destructors?
+ tag_copy := yaml_tag_directive_t{
+ handle: make([]byte, len(value.handle)),
+ prefix: make([]byte, len(value.prefix)),
+ }
+ copy(tag_copy.handle, value.handle)
+ copy(tag_copy.prefix, value.prefix)
+ emitter.tag_directives = append(emitter.tag_directives, tag_copy)
+ return true
+}
+
+// Increase the indentation level.
+func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool {
+ emitter.indents = append(emitter.indents, emitter.indent)
+ if emitter.indent < 0 {
+ if flow {
+ emitter.indent = emitter.best_indent
+ } else {
+ emitter.indent = 0
+ }
+ } else if !indentless {
+ emitter.indent += emitter.best_indent
+ }
+ return true
+}
+
+// State dispatcher.
+func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ switch emitter.state {
+ default:
+ case yaml_EMIT_STREAM_START_STATE:
+ return yaml_emitter_emit_stream_start(emitter, event)
+
+ case yaml_EMIT_FIRST_DOCUMENT_START_STATE:
+ return yaml_emitter_emit_document_start(emitter, event, true)
+
+ case yaml_EMIT_DOCUMENT_START_STATE:
+ return yaml_emitter_emit_document_start(emitter, event, false)
+
+ case yaml_EMIT_DOCUMENT_CONTENT_STATE:
+ return yaml_emitter_emit_document_content(emitter, event)
+
+ case yaml_EMIT_DOCUMENT_END_STATE:
+ return yaml_emitter_emit_document_end(emitter, event)
+
+ case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE:
+ return yaml_emitter_emit_flow_sequence_item(emitter, event, true)
+
+ case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE:
+ return yaml_emitter_emit_flow_sequence_item(emitter, event, false)
+
+ case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE:
+ return yaml_emitter_emit_flow_mapping_key(emitter, event, true)
+
+ case yaml_EMIT_FLOW_MAPPING_KEY_STATE:
+ return yaml_emitter_emit_flow_mapping_key(emitter, event, false)
+
+ case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE:
+ return yaml_emitter_emit_flow_mapping_value(emitter, event, true)
+
+ case yaml_EMIT_FLOW_MAPPING_VALUE_STATE:
+ return yaml_emitter_emit_flow_mapping_value(emitter, event, false)
+
+ case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE:
+ return yaml_emitter_emit_block_sequence_item(emitter, event, true)
+
+ case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE:
+ return yaml_emitter_emit_block_sequence_item(emitter, event, false)
+
+ case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE:
+ return yaml_emitter_emit_block_mapping_key(emitter, event, true)
+
+ case yaml_EMIT_BLOCK_MAPPING_KEY_STATE:
+ return yaml_emitter_emit_block_mapping_key(emitter, event, false)
+
+ case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE:
+ return yaml_emitter_emit_block_mapping_value(emitter, event, true)
+
+ case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE:
+ return yaml_emitter_emit_block_mapping_value(emitter, event, false)
+
+ case yaml_EMIT_END_STATE:
+ return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END")
+ }
+ panic("invalid emitter state")
+}
+
+// Expect STREAM-START.
+func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if event.typ != yaml_STREAM_START_EVENT {
+ return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START")
+ }
+ if emitter.encoding == yaml_ANY_ENCODING {
+ emitter.encoding = event.encoding
+ if emitter.encoding == yaml_ANY_ENCODING {
+ emitter.encoding = yaml_UTF8_ENCODING
+ }
+ }
+ if emitter.best_indent < 2 || emitter.best_indent > 9 {
+ emitter.best_indent = 2
+ }
+ if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 {
+ emitter.best_width = 80
+ }
+ if emitter.best_width < 0 {
+ emitter.best_width = 1<<31 - 1
+ }
+ if emitter.line_break == yaml_ANY_BREAK {
+ emitter.line_break = yaml_LN_BREAK
+ }
+
+ emitter.indent = -1
+ emitter.line = 0
+ emitter.column = 0
+ emitter.whitespace = true
+ emitter.indention = true
+
+ if emitter.encoding != yaml_UTF8_ENCODING {
+ if !yaml_emitter_write_bom(emitter) {
+ return false
+ }
+ }
+ emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE
+ return true
+}
+
+// Expect DOCUMENT-START or STREAM-END.
+func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+
+ if event.typ == yaml_DOCUMENT_START_EVENT {
+
+ if event.version_directive != nil {
+ if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) {
+ return false
+ }
+ }
+
+ for i := 0; i < len(event.tag_directives); i++ {
+ tag_directive := &event.tag_directives[i]
+ if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) {
+ return false
+ }
+ if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) {
+ return false
+ }
+ }
+
+ for i := 0; i < len(default_tag_directives); i++ {
+ tag_directive := &default_tag_directives[i]
+ if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) {
+ return false
+ }
+ }
+
+ implicit := event.implicit
+ if !first || emitter.canonical {
+ implicit = false
+ }
+
+ if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) {
+ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if event.version_directive != nil {
+ implicit = false
+ if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if len(event.tag_directives) > 0 {
+ implicit = false
+ for i := 0; i < len(event.tag_directives); i++ {
+ tag_directive := &event.tag_directives[i]
+ if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) {
+ return false
+ }
+ if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ }
+
+ if yaml_emitter_check_empty_document(emitter) {
+ implicit = false
+ }
+ if !implicit {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) {
+ return false
+ }
+ if emitter.canonical {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ }
+
+ emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE
+ return true
+ }
+
+ if event.typ == yaml_STREAM_END_EVENT {
+ if emitter.open_ended {
+ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_flush(emitter) {
+ return false
+ }
+ emitter.state = yaml_EMIT_END_STATE
+ return true
+ }
+
+ return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END")
+}
+
+// Expect the root node.
+func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE)
+ return yaml_emitter_emit_node(emitter, event, true, false, false, false)
+}
+
+// Expect DOCUMENT-END.
+func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if event.typ != yaml_DOCUMENT_END_EVENT {
+ return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END")
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !event.implicit {
+ // [Go] Allocate the slice elsewhere.
+ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_flush(emitter) {
+ return false
+ }
+ emitter.state = yaml_EMIT_DOCUMENT_START_STATE
+ emitter.tag_directives = emitter.tag_directives[:0]
+ return true
+}
+
+// Expect a flow item node.
+func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+ if first {
+ if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) {
+ return false
+ }
+ if !yaml_emitter_increase_indent(emitter, true, false) {
+ return false
+ }
+ emitter.flow_level++
+ }
+
+ if event.typ == yaml_SEQUENCE_END_EVENT {
+ emitter.flow_level--
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ if emitter.canonical && !first {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) {
+ return false
+ }
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+
+ return true
+ }
+
+ if !first {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+
+ if emitter.canonical || emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, true, false, false)
+}
+
+// Expect a flow key node.
+func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+ if first {
+ if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) {
+ return false
+ }
+ if !yaml_emitter_increase_indent(emitter, true, false) {
+ return false
+ }
+ emitter.flow_level++
+ }
+
+ if event.typ == yaml_MAPPING_END_EVENT {
+ emitter.flow_level--
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ if emitter.canonical && !first {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) {
+ return false
+ }
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+ }
+
+ if !first {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+ if emitter.canonical || emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if !emitter.canonical && yaml_emitter_check_simple_key(emitter) {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, true)
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) {
+ return false
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+// Expect a flow value node.
+func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
+ if simple {
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
+ return false
+ }
+ } else {
+ if emitter.canonical || emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) {
+ return false
+ }
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+// Expect a block item node.
+func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+ if first {
+ if !yaml_emitter_increase_indent(emitter, false, emitter.mapping_context && !emitter.indention) {
+ return false
+ }
+ }
+ if event.typ == yaml_SEQUENCE_END_EVENT {
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) {
+ return false
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, true, false, false)
+}
+
+// Expect a block key node.
+func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+ if first {
+ if !yaml_emitter_increase_indent(emitter, false, false) {
+ return false
+ }
+ }
+ if event.typ == yaml_MAPPING_END_EVENT {
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if yaml_emitter_check_simple_key(emitter) {
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, true)
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) {
+ return false
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+// Expect a block value node.
+func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
+ if simple {
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
+ return false
+ }
+ } else {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) {
+ return false
+ }
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+// Expect a node.
+func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t,
+ root bool, sequence bool, mapping bool, simple_key bool) bool {
+
+ emitter.root_context = root
+ emitter.sequence_context = sequence
+ emitter.mapping_context = mapping
+ emitter.simple_key_context = simple_key
+
+ switch event.typ {
+ case yaml_ALIAS_EVENT:
+ return yaml_emitter_emit_alias(emitter, event)
+ case yaml_SCALAR_EVENT:
+ return yaml_emitter_emit_scalar(emitter, event)
+ case yaml_SEQUENCE_START_EVENT:
+ return yaml_emitter_emit_sequence_start(emitter, event)
+ case yaml_MAPPING_START_EVENT:
+ return yaml_emitter_emit_mapping_start(emitter, event)
+ default:
+ return yaml_emitter_set_emitter_error(emitter,
+ fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ))
+ }
+}
+
+// Expect ALIAS.
+func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+}
+
+// Expect SCALAR.
+func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_select_scalar_style(emitter, event) {
+ return false
+ }
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_tag(emitter) {
+ return false
+ }
+ if !yaml_emitter_increase_indent(emitter, true, false) {
+ return false
+ }
+ if !yaml_emitter_process_scalar(emitter) {
+ return false
+ }
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+}
+
+// Expect SEQUENCE-START.
+func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_tag(emitter) {
+ return false
+ }
+ if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE ||
+ yaml_emitter_check_empty_sequence(emitter) {
+ emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE
+ } else {
+ emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE
+ }
+ return true
+}
+
+// Expect MAPPING-START.
+func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_tag(emitter) {
+ return false
+ }
+ if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE ||
+ yaml_emitter_check_empty_mapping(emitter) {
+ emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE
+ } else {
+ emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE
+ }
+ return true
+}
+
+// Check if the document content is an empty scalar.
+func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool {
+ return false // [Go] Huh?
+}
+
+// Check if the next events represent an empty sequence.
+func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool {
+ if len(emitter.events)-emitter.events_head < 2 {
+ return false
+ }
+ return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT &&
+ emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT
+}
+
+// Check if the next events represent an empty mapping.
+func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool {
+ if len(emitter.events)-emitter.events_head < 2 {
+ return false
+ }
+ return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT &&
+ emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT
+}
+
+// Check if the next node can be expressed as a simple key.
+func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool {
+ length := 0
+ switch emitter.events[emitter.events_head].typ {
+ case yaml_ALIAS_EVENT:
+ length += len(emitter.anchor_data.anchor)
+ case yaml_SCALAR_EVENT:
+ if emitter.scalar_data.multiline {
+ return false
+ }
+ length += len(emitter.anchor_data.anchor) +
+ len(emitter.tag_data.handle) +
+ len(emitter.tag_data.suffix) +
+ len(emitter.scalar_data.value)
+ case yaml_SEQUENCE_START_EVENT:
+ if !yaml_emitter_check_empty_sequence(emitter) {
+ return false
+ }
+ length += len(emitter.anchor_data.anchor) +
+ len(emitter.tag_data.handle) +
+ len(emitter.tag_data.suffix)
+ case yaml_MAPPING_START_EVENT:
+ if !yaml_emitter_check_empty_mapping(emitter) {
+ return false
+ }
+ length += len(emitter.anchor_data.anchor) +
+ len(emitter.tag_data.handle) +
+ len(emitter.tag_data.suffix)
+ default:
+ return false
+ }
+ return length <= 128
+}
+
+// Determine an acceptable scalar style.
+func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+
+ no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0
+ if no_tag && !event.implicit && !event.quoted_implicit {
+ return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified")
+ }
+
+ style := event.scalar_style()
+ if style == yaml_ANY_SCALAR_STYLE {
+ style = yaml_PLAIN_SCALAR_STYLE
+ }
+ if emitter.canonical {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ if emitter.simple_key_context && emitter.scalar_data.multiline {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+
+ if style == yaml_PLAIN_SCALAR_STYLE {
+ if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed ||
+ emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed {
+ style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+ }
+ if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) {
+ style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+ }
+ if no_tag && !event.implicit {
+ style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+ }
+ }
+ if style == yaml_SINGLE_QUOTED_SCALAR_STYLE {
+ if !emitter.scalar_data.single_quoted_allowed {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ }
+ if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE {
+ if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ }
+
+ if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE {
+ emitter.tag_data.handle = []byte{'!'}
+ }
+ emitter.scalar_data.style = style
+ return true
+}
+
+// Write an anchor.
+func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool {
+ if emitter.anchor_data.anchor == nil {
+ return true
+ }
+ c := []byte{'&'}
+ if emitter.anchor_data.alias {
+ c[0] = '*'
+ }
+ if !yaml_emitter_write_indicator(emitter, c, true, false, false) {
+ return false
+ }
+ return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor)
+}
+
+// Write a tag.
+func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool {
+ if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 {
+ return true
+ }
+ if len(emitter.tag_data.handle) > 0 {
+ if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) {
+ return false
+ }
+ if len(emitter.tag_data.suffix) > 0 {
+ if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
+ return false
+ }
+ }
+ } else {
+ // [Go] Allocate these slices elsewhere.
+ if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) {
+ return false
+ }
+ }
+ return true
+}
+
+// Write a scalar.
+func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool {
+ switch emitter.scalar_data.style {
+ case yaml_PLAIN_SCALAR_STYLE:
+ return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+ case yaml_SINGLE_QUOTED_SCALAR_STYLE:
+ return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+ case yaml_DOUBLE_QUOTED_SCALAR_STYLE:
+ return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+ case yaml_LITERAL_SCALAR_STYLE:
+ return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value)
+
+ case yaml_FOLDED_SCALAR_STYLE:
+ return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value)
+ }
+ panic("unknown scalar style")
+}
+
+// Check if a %YAML directive is valid.
+func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool {
+ if version_directive.major != 1 || version_directive.minor != 1 {
+ return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive")
+ }
+ return true
+}
+
+// Check if a %TAG directive is valid.
+func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool {
+ handle := tag_directive.handle
+ prefix := tag_directive.prefix
+ if len(handle) == 0 {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty")
+ }
+ if handle[0] != '!' {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'")
+ }
+ if handle[len(handle)-1] != '!' {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'")
+ }
+ for i := 1; i < len(handle)-1; i += width(handle[i]) {
+ if !is_alpha(handle, i) {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only")
+ }
+ }
+ if len(prefix) == 0 {
+ return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty")
+ }
+ return true
+}
+
+// Check if an anchor is valid.
+func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool {
+ if len(anchor) == 0 {
+ problem := "anchor value must not be empty"
+ if alias {
+ problem = "alias value must not be empty"
+ }
+ return yaml_emitter_set_emitter_error(emitter, problem)
+ }
+ for i := 0; i < len(anchor); i += width(anchor[i]) {
+ if !is_alpha(anchor, i) {
+ problem := "anchor value must contain alphanumerical characters only"
+ if alias {
+ problem = "alias value must contain alphanumerical characters only"
+ }
+ return yaml_emitter_set_emitter_error(emitter, problem)
+ }
+ }
+ emitter.anchor_data.anchor = anchor
+ emitter.anchor_data.alias = alias
+ return true
+}
+
+// Check if a tag is valid.
+func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool {
+ if len(tag) == 0 {
+ return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty")
+ }
+ for i := 0; i < len(emitter.tag_directives); i++ {
+ tag_directive := &emitter.tag_directives[i]
+ if bytes.HasPrefix(tag, tag_directive.prefix) {
+ emitter.tag_data.handle = tag_directive.handle
+ emitter.tag_data.suffix = tag[len(tag_directive.prefix):]
+ return true
+ }
+ }
+ emitter.tag_data.suffix = tag
+ return true
+}
+
+// Check if a scalar is valid.
+func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
+ var (
+ block_indicators = false
+ flow_indicators = false
+ line_breaks = false
+ special_characters = false
+
+ leading_space = false
+ leading_break = false
+ trailing_space = false
+ trailing_break = false
+ break_space = false
+ space_break = false
+
+ preceded_by_whitespace = false
+ followed_by_whitespace = false
+ previous_space = false
+ previous_break = false
+ )
+
+ emitter.scalar_data.value = value
+
+ if len(value) == 0 {
+ emitter.scalar_data.multiline = false
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = true
+ emitter.scalar_data.single_quoted_allowed = true
+ emitter.scalar_data.block_allowed = false
+ return true
+ }
+
+ if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) {
+ block_indicators = true
+ flow_indicators = true
+ }
+
+ preceded_by_whitespace = true
+ for i, w := 0, 0; i < len(value); i += w {
+ w = width(value[i])
+ followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w)
+
+ if i == 0 {
+ switch value[i] {
+ case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`':
+ flow_indicators = true
+ block_indicators = true
+ case '?', ':':
+ flow_indicators = true
+ if followed_by_whitespace {
+ block_indicators = true
+ }
+ case '-':
+ if followed_by_whitespace {
+ flow_indicators = true
+ block_indicators = true
+ }
+ }
+ } else {
+ switch value[i] {
+ case ',', '?', '[', ']', '{', '}':
+ flow_indicators = true
+ case ':':
+ flow_indicators = true
+ if followed_by_whitespace {
+ block_indicators = true
+ }
+ case '#':
+ if preceded_by_whitespace {
+ flow_indicators = true
+ block_indicators = true
+ }
+ }
+ }
+
+ if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode {
+ special_characters = true
+ }
+ if is_space(value, i) {
+ if i == 0 {
+ leading_space = true
+ }
+ if i+width(value[i]) == len(value) {
+ trailing_space = true
+ }
+ if previous_break {
+ break_space = true
+ }
+ previous_space = true
+ previous_break = false
+ } else if is_break(value, i) {
+ line_breaks = true
+ if i == 0 {
+ leading_break = true
+ }
+ if i+width(value[i]) == len(value) {
+ trailing_break = true
+ }
+ if previous_space {
+ space_break = true
+ }
+ previous_space = false
+ previous_break = true
+ } else {
+ previous_space = false
+ previous_break = false
+ }
+
+ // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition.
+ preceded_by_whitespace = is_blankz(value, i)
+ }
+
+ emitter.scalar_data.multiline = line_breaks
+ emitter.scalar_data.flow_plain_allowed = true
+ emitter.scalar_data.block_plain_allowed = true
+ emitter.scalar_data.single_quoted_allowed = true
+ emitter.scalar_data.block_allowed = true
+
+ if leading_space || leading_break || trailing_space || trailing_break {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ }
+ if trailing_space {
+ emitter.scalar_data.block_allowed = false
+ }
+ if break_space {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ emitter.scalar_data.single_quoted_allowed = false
+ }
+ if space_break || special_characters {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ emitter.scalar_data.single_quoted_allowed = false
+ emitter.scalar_data.block_allowed = false
+ }
+ if line_breaks {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ }
+ if flow_indicators {
+ emitter.scalar_data.flow_plain_allowed = false
+ }
+ if block_indicators {
+ emitter.scalar_data.block_plain_allowed = false
+ }
+ return true
+}
+
+// Check if the event data is valid.
+func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+
+ emitter.anchor_data.anchor = nil
+ emitter.tag_data.handle = nil
+ emitter.tag_data.suffix = nil
+ emitter.scalar_data.value = nil
+
+ switch event.typ {
+ case yaml_ALIAS_EVENT:
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) {
+ return false
+ }
+
+ case yaml_SCALAR_EVENT:
+ if len(event.anchor) > 0 {
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+ return false
+ }
+ }
+ if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) {
+ if !yaml_emitter_analyze_tag(emitter, event.tag) {
+ return false
+ }
+ }
+ if !yaml_emitter_analyze_scalar(emitter, event.value) {
+ return false
+ }
+
+ case yaml_SEQUENCE_START_EVENT:
+ if len(event.anchor) > 0 {
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+ return false
+ }
+ }
+ if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
+ if !yaml_emitter_analyze_tag(emitter, event.tag) {
+ return false
+ }
+ }
+
+ case yaml_MAPPING_START_EVENT:
+ if len(event.anchor) > 0 {
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+ return false
+ }
+ }
+ if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
+ if !yaml_emitter_analyze_tag(emitter, event.tag) {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+// Write the BOM character.
+func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool {
+ if !flush(emitter) {
+ return false
+ }
+ pos := emitter.buffer_pos
+ emitter.buffer[pos+0] = '\xEF'
+ emitter.buffer[pos+1] = '\xBB'
+ emitter.buffer[pos+2] = '\xBF'
+ emitter.buffer_pos += 3
+ return true
+}
+
+func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool {
+ indent := emitter.indent
+ if indent < 0 {
+ indent = 0
+ }
+ if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ for emitter.column < indent {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ emitter.whitespace = true
+ emitter.indention = true
+ return true
+}
+
+func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool {
+ if need_whitespace && !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ if !write_all(emitter, indicator) {
+ return false
+ }
+ emitter.whitespace = is_whitespace
+ emitter.indention = (emitter.indention && is_indention)
+ emitter.open_ended = false
+ return true
+}
+
+func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool {
+ if !write_all(emitter, value) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool {
+ if !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ if !write_all(emitter, value) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool {
+ if need_whitespace && !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ for i := 0; i < len(value); {
+ var must_write bool
+ switch value[i] {
+ case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']':
+ must_write = true
+ default:
+ must_write = is_alpha(value, i)
+ }
+ if must_write {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ } else {
+ w := width(value[i])
+ for k := 0; k < w; k++ {
+ octet := value[i]
+ i++
+ if !put(emitter, '%') {
+ return false
+ }
+
+ c := octet >> 4
+ if c < 10 {
+ c += '0'
+ } else {
+ c += 'A' - 10
+ }
+ if !put(emitter, c) {
+ return false
+ }
+
+ c = octet & 0x0f
+ if c < 10 {
+ c += '0'
+ } else {
+ c += 'A' - 10
+ }
+ if !put(emitter, c) {
+ return false
+ }
+ }
+ }
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+ if !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+
+ spaces := false
+ breaks := false
+ for i := 0; i < len(value); {
+ if is_space(value, i) {
+ if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ i += width(value[i])
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ }
+ spaces = true
+ } else if is_break(value, i) {
+ if !breaks && value[i] == '\n' {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !write(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = false
+ spaces = false
+ breaks = false
+ }
+ }
+
+ emitter.whitespace = false
+ emitter.indention = false
+ if emitter.root_context {
+ emitter.open_ended = true
+ }
+
+ return true
+}
+
+func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+
+ if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) {
+ return false
+ }
+
+ spaces := false
+ breaks := false
+ for i := 0; i < len(value); {
+ if is_space(value, i) {
+ if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ i += width(value[i])
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ }
+ spaces = true
+ } else if is_break(value, i) {
+ if !breaks && value[i] == '\n' {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if value[i] == '\'' {
+ if !put(emitter, '\'') {
+ return false
+ }
+ }
+ if !write(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = false
+ spaces = false
+ breaks = false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+ spaces := false
+ if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) {
+ return false
+ }
+
+ for i := 0; i < len(value); {
+ if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) ||
+ is_bom(value, i) || is_break(value, i) ||
+ value[i] == '"' || value[i] == '\\' {
+
+ octet := value[i]
+
+ var w int
+ var v rune
+ switch {
+ case octet&0x80 == 0x00:
+ w, v = 1, rune(octet&0x7F)
+ case octet&0xE0 == 0xC0:
+ w, v = 2, rune(octet&0x1F)
+ case octet&0xF0 == 0xE0:
+ w, v = 3, rune(octet&0x0F)
+ case octet&0xF8 == 0xF0:
+ w, v = 4, rune(octet&0x07)
+ }
+ for k := 1; k < w; k++ {
+ octet = value[i+k]
+ v = (v << 6) + (rune(octet) & 0x3F)
+ }
+ i += w
+
+ if !put(emitter, '\\') {
+ return false
+ }
+
+ var ok bool
+ switch v {
+ case 0x00:
+ ok = put(emitter, '0')
+ case 0x07:
+ ok = put(emitter, 'a')
+ case 0x08:
+ ok = put(emitter, 'b')
+ case 0x09:
+ ok = put(emitter, 't')
+ case 0x0A:
+ ok = put(emitter, 'n')
+ case 0x0b:
+ ok = put(emitter, 'v')
+ case 0x0c:
+ ok = put(emitter, 'f')
+ case 0x0d:
+ ok = put(emitter, 'r')
+ case 0x1b:
+ ok = put(emitter, 'e')
+ case 0x22:
+ ok = put(emitter, '"')
+ case 0x5c:
+ ok = put(emitter, '\\')
+ case 0x85:
+ ok = put(emitter, 'N')
+ case 0xA0:
+ ok = put(emitter, '_')
+ case 0x2028:
+ ok = put(emitter, 'L')
+ case 0x2029:
+ ok = put(emitter, 'P')
+ default:
+ if v <= 0xFF {
+ ok = put(emitter, 'x')
+ w = 2
+ } else if v <= 0xFFFF {
+ ok = put(emitter, 'u')
+ w = 4
+ } else {
+ ok = put(emitter, 'U')
+ w = 8
+ }
+ for k := (w - 1) * 4; ok && k >= 0; k -= 4 {
+ digit := byte((v >> uint(k)) & 0x0F)
+ if digit < 10 {
+ ok = put(emitter, digit+'0')
+ } else {
+ ok = put(emitter, digit+'A'-10)
+ }
+ }
+ }
+ if !ok {
+ return false
+ }
+ spaces = false
+ } else if is_space(value, i) {
+ if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if is_space(value, i+1) {
+ if !put(emitter, '\\') {
+ return false
+ }
+ }
+ i += width(value[i])
+ } else if !write(emitter, value, &i) {
+ return false
+ }
+ spaces = true
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ spaces = false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool {
+ if is_space(value, 0) || is_break(value, 0) {
+ indent_hint := []byte{'0' + byte(emitter.best_indent)}
+ if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) {
+ return false
+ }
+ }
+
+ emitter.open_ended = false
+
+ var chomp_hint [1]byte
+ if len(value) == 0 {
+ chomp_hint[0] = '-'
+ } else {
+ i := len(value) - 1
+ for value[i]&0xC0 == 0x80 {
+ i--
+ }
+ if !is_break(value, i) {
+ chomp_hint[0] = '-'
+ } else if i == 0 {
+ chomp_hint[0] = '+'
+ emitter.open_ended = true
+ } else {
+ i--
+ for value[i]&0xC0 == 0x80 {
+ i--
+ }
+ if is_break(value, i) {
+ chomp_hint[0] = '+'
+ emitter.open_ended = true
+ }
+ }
+ }
+ if chomp_hint[0] != 0 {
+ if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) {
+ return false
+ }
+ }
+ return true
+}
+
+func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool {
+ if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_block_scalar_hints(emitter, value) {
+ return false
+ }
+ if !put_break(emitter) {
+ return false
+ }
+ emitter.indention = true
+ emitter.whitespace = true
+ breaks := true
+ for i := 0; i < len(value); {
+ if is_break(value, i) {
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !write(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = false
+ breaks = false
+ }
+ }
+
+ return true
+}
+
+func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool {
+ if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_block_scalar_hints(emitter, value) {
+ return false
+ }
+
+ if !put_break(emitter) {
+ return false
+ }
+ emitter.indention = true
+ emitter.whitespace = true
+
+ breaks := true
+ leading_spaces := true
+ for i := 0; i < len(value); {
+ if is_break(value, i) {
+ if !breaks && !leading_spaces && value[i] == '\n' {
+ k := 0
+ for is_break(value, k) {
+ k += width(value[k])
+ }
+ if !is_blankz(value, k) {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ }
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ leading_spaces = is_blank(value, i)
+ }
+ if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ i += width(value[i])
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ }
+ emitter.indention = false
+ breaks = false
+ }
+ }
+ return true
+}
--- /dev/null
+package yaml
+
+import (
+ "encoding"
+ "fmt"
+ "io"
+ "reflect"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+ "unicode/utf8"
+)
+
+type encoder struct {
+ emitter yaml_emitter_t
+ event yaml_event_t
+ out []byte
+ flow bool
+ // doneInit holds whether the initial stream_start_event has been
+ // emitted.
+ doneInit bool
+}
+
+func newEncoder() *encoder {
+ e := &encoder{}
+ yaml_emitter_initialize(&e.emitter)
+ yaml_emitter_set_output_string(&e.emitter, &e.out)
+ yaml_emitter_set_unicode(&e.emitter, true)
+ return e
+}
+
+func newEncoderWithWriter(w io.Writer) *encoder {
+ e := &encoder{}
+ yaml_emitter_initialize(&e.emitter)
+ yaml_emitter_set_output_writer(&e.emitter, w)
+ yaml_emitter_set_unicode(&e.emitter, true)
+ return e
+}
+
+func (e *encoder) init() {
+ if e.doneInit {
+ return
+ }
+ yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)
+ e.emit()
+ e.doneInit = true
+}
+
+func (e *encoder) finish() {
+ e.emitter.open_ended = false
+ yaml_stream_end_event_initialize(&e.event)
+ e.emit()
+}
+
+func (e *encoder) destroy() {
+ yaml_emitter_delete(&e.emitter)
+}
+
+func (e *encoder) emit() {
+ // This will internally delete the e.event value.
+ e.must(yaml_emitter_emit(&e.emitter, &e.event))
+}
+
+func (e *encoder) must(ok bool) {
+ if !ok {
+ msg := e.emitter.problem
+ if msg == "" {
+ msg = "unknown problem generating YAML content"
+ }
+ failf("%s", msg)
+ }
+}
+
+func (e *encoder) marshalDoc(tag string, in reflect.Value) {
+ e.init()
+ yaml_document_start_event_initialize(&e.event, nil, nil, true)
+ e.emit()
+ e.marshal(tag, in)
+ yaml_document_end_event_initialize(&e.event, true)
+ e.emit()
+}
+
+func (e *encoder) marshal(tag string, in reflect.Value) {
+ if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() {
+ e.nilv()
+ return
+ }
+ iface := in.Interface()
+ switch m := iface.(type) {
+ case time.Time, *time.Time:
+ // Although time.Time implements TextMarshaler,
+ // we don't want to treat it as a string for YAML
+ // purposes because YAML has special support for
+ // timestamps.
+ case Marshaler:
+ v, err := m.MarshalYAML()
+ if err != nil {
+ fail(err)
+ }
+ if v == nil {
+ e.nilv()
+ return
+ }
+ in = reflect.ValueOf(v)
+ case encoding.TextMarshaler:
+ text, err := m.MarshalText()
+ if err != nil {
+ fail(err)
+ }
+ in = reflect.ValueOf(string(text))
+ case nil:
+ e.nilv()
+ return
+ }
+ switch in.Kind() {
+ case reflect.Interface:
+ e.marshal(tag, in.Elem())
+ case reflect.Map:
+ e.mapv(tag, in)
+ case reflect.Ptr:
+ if in.Type() == ptrTimeType {
+ e.timev(tag, in.Elem())
+ } else {
+ e.marshal(tag, in.Elem())
+ }
+ case reflect.Struct:
+ if in.Type() == timeType {
+ e.timev(tag, in)
+ } else {
+ e.structv(tag, in)
+ }
+ case reflect.Slice, reflect.Array:
+ if in.Type().Elem() == mapItemType {
+ e.itemsv(tag, in)
+ } else {
+ e.slicev(tag, in)
+ }
+ case reflect.String:
+ e.stringv(tag, in)
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ if in.Type() == durationType {
+ e.stringv(tag, reflect.ValueOf(iface.(time.Duration).String()))
+ } else {
+ e.intv(tag, in)
+ }
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ e.uintv(tag, in)
+ case reflect.Float32, reflect.Float64:
+ e.floatv(tag, in)
+ case reflect.Bool:
+ e.boolv(tag, in)
+ default:
+ panic("cannot marshal type: " + in.Type().String())
+ }
+}
+
+func (e *encoder) mapv(tag string, in reflect.Value) {
+ e.mappingv(tag, func() {
+ keys := keyList(in.MapKeys())
+ sort.Sort(keys)
+ for _, k := range keys {
+ e.marshal("", k)
+ e.marshal("", in.MapIndex(k))
+ }
+ })
+}
+
+func (e *encoder) itemsv(tag string, in reflect.Value) {
+ e.mappingv(tag, func() {
+ slice := in.Convert(reflect.TypeOf([]MapItem{})).Interface().([]MapItem)
+ for _, item := range slice {
+ e.marshal("", reflect.ValueOf(item.Key))
+ e.marshal("", reflect.ValueOf(item.Value))
+ }
+ })
+}
+
+func (e *encoder) structv(tag string, in reflect.Value) {
+ sinfo, err := getStructInfo(in.Type())
+ if err != nil {
+ panic(err)
+ }
+ e.mappingv(tag, func() {
+ for _, info := range sinfo.FieldsList {
+ var value reflect.Value
+ if info.Inline == nil {
+ value = in.Field(info.Num)
+ } else {
+ value = in.FieldByIndex(info.Inline)
+ }
+ if info.OmitEmpty && isZero(value) {
+ continue
+ }
+ e.marshal("", reflect.ValueOf(info.Key))
+ e.flow = info.Flow
+ e.marshal("", value)
+ }
+ if sinfo.InlineMap >= 0 {
+ m := in.Field(sinfo.InlineMap)
+ if m.Len() > 0 {
+ e.flow = false
+ keys := keyList(m.MapKeys())
+ sort.Sort(keys)
+ for _, k := range keys {
+ if _, found := sinfo.FieldsMap[k.String()]; found {
+ panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", k.String()))
+ }
+ e.marshal("", k)
+ e.flow = false
+ e.marshal("", m.MapIndex(k))
+ }
+ }
+ }
+ })
+}
+
+func (e *encoder) mappingv(tag string, f func()) {
+ implicit := tag == ""
+ style := yaml_BLOCK_MAPPING_STYLE
+ if e.flow {
+ e.flow = false
+ style = yaml_FLOW_MAPPING_STYLE
+ }
+ yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)
+ e.emit()
+ f()
+ yaml_mapping_end_event_initialize(&e.event)
+ e.emit()
+}
+
+func (e *encoder) slicev(tag string, in reflect.Value) {
+ implicit := tag == ""
+ style := yaml_BLOCK_SEQUENCE_STYLE
+ if e.flow {
+ e.flow = false
+ style = yaml_FLOW_SEQUENCE_STYLE
+ }
+ e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
+ e.emit()
+ n := in.Len()
+ for i := 0; i < n; i++ {
+ e.marshal("", in.Index(i))
+ }
+ e.must(yaml_sequence_end_event_initialize(&e.event))
+ e.emit()
+}
+
+// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
+//
+// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
+// in YAML 1.2 and by this package, but these should be marshalled quoted for
+// the time being for compatibility with other parsers.
+func isBase60Float(s string) (result bool) {
+ // Fast path.
+ if s == "" {
+ return false
+ }
+ c := s[0]
+ if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
+ return false
+ }
+ // Do the full match.
+ return base60float.MatchString(s)
+}
+
+// From http://yaml.org/type/float.html, except the regular expression there
+// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
+var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
+
+func (e *encoder) stringv(tag string, in reflect.Value) {
+ var style yaml_scalar_style_t
+ s := in.String()
+ canUsePlain := true
+ switch {
+ case !utf8.ValidString(s):
+ if tag == yaml_BINARY_TAG {
+ failf("explicitly tagged !!binary data must be base64-encoded")
+ }
+ if tag != "" {
+ failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
+ }
+ // It can't be encoded directly as YAML so use a binary tag
+ // and encode it as base64.
+ tag = yaml_BINARY_TAG
+ s = encodeBase64(s)
+ case tag == "":
+ // Check to see if it would resolve to a specific
+ // tag when encoded unquoted. If it doesn't,
+ // there's no need to quote it.
+ rtag, _ := resolve("", s)
+ canUsePlain = rtag == yaml_STR_TAG && !isBase60Float(s)
+ }
+ // Note: it's possible for user code to emit invalid YAML
+ // if they explicitly specify a tag and a string containing
+ // text that's incompatible with that tag.
+ switch {
+ case strings.Contains(s, "\n"):
+ style = yaml_LITERAL_SCALAR_STYLE
+ case canUsePlain:
+ style = yaml_PLAIN_SCALAR_STYLE
+ default:
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ e.emitScalar(s, "", tag, style)
+}
+
+func (e *encoder) boolv(tag string, in reflect.Value) {
+ var s string
+ if in.Bool() {
+ s = "true"
+ } else {
+ s = "false"
+ }
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
+}
+
+func (e *encoder) intv(tag string, in reflect.Value) {
+ s := strconv.FormatInt(in.Int(), 10)
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
+}
+
+func (e *encoder) uintv(tag string, in reflect.Value) {
+ s := strconv.FormatUint(in.Uint(), 10)
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
+}
+
+func (e *encoder) timev(tag string, in reflect.Value) {
+ t := in.Interface().(time.Time)
+ s := t.Format(time.RFC3339Nano)
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
+}
+
+func (e *encoder) floatv(tag string, in reflect.Value) {
+ // Issue #352: When formatting, use the precision of the underlying value
+ precision := 64
+ if in.Kind() == reflect.Float32 {
+ precision = 32
+ }
+
+ s := strconv.FormatFloat(in.Float(), 'g', -1, precision)
+ switch s {
+ case "+Inf":
+ s = ".inf"
+ case "-Inf":
+ s = "-.inf"
+ case "NaN":
+ s = ".nan"
+ }
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
+}
+
+func (e *encoder) nilv() {
+ e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE)
+}
+
+func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) {
+ implicit := tag == ""
+ e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
+ e.emit()
+}
--- /dev/null
+module "gopkg.in/yaml.v2"
+
+require (
+ "gopkg.in/check.v1" v0.0.0-20161208181325-20d25e280405
+)
--- /dev/null
+package yaml
+
+import (
+ "bytes"
+)
+
+// The parser implements the following grammar:
+//
+// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
+// implicit_document ::= block_node DOCUMENT-END*
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+// block_node_or_indentless_sequence ::=
+// ALIAS
+// | properties (block_content | indentless_block_sequence)?
+// | block_content
+// | indentless_block_sequence
+// block_node ::= ALIAS
+// | properties block_content?
+// | block_content
+// flow_node ::= ALIAS
+// | properties flow_content?
+// | flow_content
+// properties ::= TAG ANCHOR? | ANCHOR TAG?
+// block_content ::= block_collection | flow_collection | SCALAR
+// flow_content ::= flow_collection | SCALAR
+// block_collection ::= block_sequence | block_mapping
+// flow_collection ::= flow_sequence | flow_mapping
+// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
+// block_mapping ::= BLOCK-MAPPING_START
+// ((KEY block_node_or_indentless_sequence?)?
+// (VALUE block_node_or_indentless_sequence?)?)*
+// BLOCK-END
+// flow_sequence ::= FLOW-SEQUENCE-START
+// (flow_sequence_entry FLOW-ENTRY)*
+// flow_sequence_entry?
+// FLOW-SEQUENCE-END
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// flow_mapping ::= FLOW-MAPPING-START
+// (flow_mapping_entry FLOW-ENTRY)*
+// flow_mapping_entry?
+// FLOW-MAPPING-END
+// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+
+// Peek the next token in the token queue.
+func peek_token(parser *yaml_parser_t) *yaml_token_t {
+ if parser.token_available || yaml_parser_fetch_more_tokens(parser) {
+ return &parser.tokens[parser.tokens_head]
+ }
+ return nil
+}
+
+// Remove the next token from the queue (must be called after peek_token).
+func skip_token(parser *yaml_parser_t) {
+ parser.token_available = false
+ parser.tokens_parsed++
+ parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN
+ parser.tokens_head++
+}
+
+// Get the next event.
+func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool {
+ // Erase the event object.
+ *event = yaml_event_t{}
+
+ // No events after the end of the stream or error.
+ if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE {
+ return true
+ }
+
+ // Generate the next event.
+ return yaml_parser_state_machine(parser, event)
+}
+
+// Set parser error.
+func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool {
+ parser.error = yaml_PARSER_ERROR
+ parser.problem = problem
+ parser.problem_mark = problem_mark
+ return false
+}
+
+func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool {
+ parser.error = yaml_PARSER_ERROR
+ parser.context = context
+ parser.context_mark = context_mark
+ parser.problem = problem
+ parser.problem_mark = problem_mark
+ return false
+}
+
+// State dispatcher.
+func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool {
+ //trace("yaml_parser_state_machine", "state:", parser.state.String())
+
+ switch parser.state {
+ case yaml_PARSE_STREAM_START_STATE:
+ return yaml_parser_parse_stream_start(parser, event)
+
+ case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
+ return yaml_parser_parse_document_start(parser, event, true)
+
+ case yaml_PARSE_DOCUMENT_START_STATE:
+ return yaml_parser_parse_document_start(parser, event, false)
+
+ case yaml_PARSE_DOCUMENT_CONTENT_STATE:
+ return yaml_parser_parse_document_content(parser, event)
+
+ case yaml_PARSE_DOCUMENT_END_STATE:
+ return yaml_parser_parse_document_end(parser, event)
+
+ case yaml_PARSE_BLOCK_NODE_STATE:
+ return yaml_parser_parse_node(parser, event, true, false)
+
+ case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
+ return yaml_parser_parse_node(parser, event, true, true)
+
+ case yaml_PARSE_FLOW_NODE_STATE:
+ return yaml_parser_parse_node(parser, event, false, false)
+
+ case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
+ return yaml_parser_parse_block_sequence_entry(parser, event, true)
+
+ case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
+ return yaml_parser_parse_block_sequence_entry(parser, event, false)
+
+ case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
+ return yaml_parser_parse_indentless_sequence_entry(parser, event)
+
+ case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
+ return yaml_parser_parse_block_mapping_key(parser, event, true)
+
+ case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
+ return yaml_parser_parse_block_mapping_key(parser, event, false)
+
+ case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
+ return yaml_parser_parse_block_mapping_value(parser, event)
+
+ case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
+ return yaml_parser_parse_flow_sequence_entry(parser, event, true)
+
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
+ return yaml_parser_parse_flow_sequence_entry(parser, event, false)
+
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
+ return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event)
+
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
+ return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event)
+
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
+ return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event)
+
+ case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
+ return yaml_parser_parse_flow_mapping_key(parser, event, true)
+
+ case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
+ return yaml_parser_parse_flow_mapping_key(parser, event, false)
+
+ case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
+ return yaml_parser_parse_flow_mapping_value(parser, event, false)
+
+ case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
+ return yaml_parser_parse_flow_mapping_value(parser, event, true)
+
+ default:
+ panic("invalid parser state")
+ }
+}
+
+// Parse the production:
+// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
+// ************
+func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_STREAM_START_TOKEN {
+ return yaml_parser_set_parser_error(parser, "did not find expected <stream-start>", token.start_mark)
+ }
+ parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE
+ *event = yaml_event_t{
+ typ: yaml_STREAM_START_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ encoding: token.encoding,
+ }
+ skip_token(parser)
+ return true
+}
+
+// Parse the productions:
+// implicit_document ::= block_node DOCUMENT-END*
+// *
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+// *************************
+func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool {
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ // Parse extra document end indicators.
+ if !implicit {
+ for token.typ == yaml_DOCUMENT_END_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ }
+ }
+
+ if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN &&
+ token.typ != yaml_TAG_DIRECTIVE_TOKEN &&
+ token.typ != yaml_DOCUMENT_START_TOKEN &&
+ token.typ != yaml_STREAM_END_TOKEN {
+ // Parse an implicit document.
+ if !yaml_parser_process_directives(parser, nil, nil) {
+ return false
+ }
+ parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)
+ parser.state = yaml_PARSE_BLOCK_NODE_STATE
+
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_START_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+
+ } else if token.typ != yaml_STREAM_END_TOKEN {
+ // Parse an explicit document.
+ var version_directive *yaml_version_directive_t
+ var tag_directives []yaml_tag_directive_t
+ start_mark := token.start_mark
+ if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) {
+ return false
+ }
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_DOCUMENT_START_TOKEN {
+ yaml_parser_set_parser_error(parser,
+ "did not find expected <document start>", token.start_mark)
+ return false
+ }
+ parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)
+ parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE
+ end_mark := token.end_mark
+
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ version_directive: version_directive,
+ tag_directives: tag_directives,
+ implicit: false,
+ }
+ skip_token(parser)
+
+ } else {
+ // Parse the stream end.
+ parser.state = yaml_PARSE_END_STATE
+ *event = yaml_event_t{
+ typ: yaml_STREAM_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+ skip_token(parser)
+ }
+
+ return true
+}
+
+// Parse the productions:
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+// ***********
+//
+func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ == yaml_VERSION_DIRECTIVE_TOKEN ||
+ token.typ == yaml_TAG_DIRECTIVE_TOKEN ||
+ token.typ == yaml_DOCUMENT_START_TOKEN ||
+ token.typ == yaml_DOCUMENT_END_TOKEN ||
+ token.typ == yaml_STREAM_END_TOKEN {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ return yaml_parser_process_empty_scalar(parser, event,
+ token.start_mark)
+ }
+ return yaml_parser_parse_node(parser, event, true, false)
+}
+
+// Parse the productions:
+// implicit_document ::= block_node DOCUMENT-END*
+// *************
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+//
+func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ start_mark := token.start_mark
+ end_mark := token.start_mark
+
+ implicit := true
+ if token.typ == yaml_DOCUMENT_END_TOKEN {
+ end_mark = token.end_mark
+ skip_token(parser)
+ implicit = false
+ }
+
+ parser.tag_directives = parser.tag_directives[:0]
+
+ parser.state = yaml_PARSE_DOCUMENT_START_STATE
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_END_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ implicit: implicit,
+ }
+ return true
+}
+
+// Parse the productions:
+// block_node_or_indentless_sequence ::=
+// ALIAS
+// *****
+// | properties (block_content | indentless_block_sequence)?
+// ********** *
+// | block_content | indentless_block_sequence
+// *
+// block_node ::= ALIAS
+// *****
+// | properties block_content?
+// ********** *
+// | block_content
+// *
+// flow_node ::= ALIAS
+// *****
+// | properties flow_content?
+// ********** *
+// | flow_content
+// *
+// properties ::= TAG ANCHOR? | ANCHOR TAG?
+// *************************
+// block_content ::= block_collection | flow_collection | SCALAR
+// ******
+// flow_content ::= flow_collection | SCALAR
+// ******
+func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool {
+ //defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)()
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ == yaml_ALIAS_TOKEN {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ *event = yaml_event_t{
+ typ: yaml_ALIAS_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ anchor: token.value,
+ }
+ skip_token(parser)
+ return true
+ }
+
+ start_mark := token.start_mark
+ end_mark := token.start_mark
+
+ var tag_token bool
+ var tag_handle, tag_suffix, anchor []byte
+ var tag_mark yaml_mark_t
+ if token.typ == yaml_ANCHOR_TOKEN {
+ anchor = token.value
+ start_mark = token.start_mark
+ end_mark = token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ == yaml_TAG_TOKEN {
+ tag_token = true
+ tag_handle = token.value
+ tag_suffix = token.suffix
+ tag_mark = token.start_mark
+ end_mark = token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ }
+ } else if token.typ == yaml_TAG_TOKEN {
+ tag_token = true
+ tag_handle = token.value
+ tag_suffix = token.suffix
+ start_mark = token.start_mark
+ tag_mark = token.start_mark
+ end_mark = token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ == yaml_ANCHOR_TOKEN {
+ anchor = token.value
+ end_mark = token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ }
+ }
+
+ var tag []byte
+ if tag_token {
+ if len(tag_handle) == 0 {
+ tag = tag_suffix
+ tag_suffix = nil
+ } else {
+ for i := range parser.tag_directives {
+ if bytes.Equal(parser.tag_directives[i].handle, tag_handle) {
+ tag = append([]byte(nil), parser.tag_directives[i].prefix...)
+ tag = append(tag, tag_suffix...)
+ break
+ }
+ }
+ if len(tag) == 0 {
+ yaml_parser_set_parser_error_context(parser,
+ "while parsing a node", start_mark,
+ "found undefined tag handle", tag_mark)
+ return false
+ }
+ }
+ }
+
+ implicit := len(tag) == 0
+ if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN {
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),
+ }
+ return true
+ }
+ if token.typ == yaml_SCALAR_TOKEN {
+ var plain_implicit, quoted_implicit bool
+ end_mark = token.end_mark
+ if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') {
+ plain_implicit = true
+ } else if len(tag) == 0 {
+ quoted_implicit = true
+ }
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SCALAR_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ value: token.value,
+ implicit: plain_implicit,
+ quoted_implicit: quoted_implicit,
+ style: yaml_style_t(token.style),
+ }
+ skip_token(parser)
+ return true
+ }
+ if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN {
+ // [Go] Some of the events below can be merged as they differ only on style.
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_FLOW_SEQUENCE_STYLE),
+ }
+ return true
+ }
+ if token.typ == yaml_FLOW_MAPPING_START_TOKEN {
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_FLOW_MAPPING_STYLE),
+ }
+ return true
+ }
+ if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN {
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),
+ }
+ return true
+ }
+ if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN {
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE),
+ }
+ return true
+ }
+ if len(anchor) > 0 || len(tag) > 0 {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SCALAR_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ quoted_implicit: false,
+ style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE),
+ }
+ return true
+ }
+
+ context := "while parsing a flow node"
+ if block {
+ context = "while parsing a block node"
+ }
+ yaml_parser_set_parser_error_context(parser, context, start_mark,
+ "did not find expected node content", token.start_mark)
+ return false
+}
+
+// Parse the productions:
+// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+// ******************** *********** * *********
+//
+func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+ if first {
+ token := peek_token(parser)
+ parser.marks = append(parser.marks, token.start_mark)
+ skip_token(parser)
+ }
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ == yaml_BLOCK_ENTRY_TOKEN {
+ mark := token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE)
+ return yaml_parser_parse_node(parser, event, true, false)
+ } else {
+ parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+ }
+ }
+ if token.typ == yaml_BLOCK_END_TOKEN {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+
+ skip_token(parser)
+ return true
+ }
+
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a block collection", context_mark,
+ "did not find expected '-' indicator", token.start_mark)
+}
+
+// Parse the productions:
+// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
+// *********** *
+func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ == yaml_BLOCK_ENTRY_TOKEN {
+ mark := token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_BLOCK_ENTRY_TOKEN &&
+ token.typ != yaml_KEY_TOKEN &&
+ token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_BLOCK_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE)
+ return yaml_parser_parse_node(parser, event, true, false)
+ }
+ parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+ }
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.start_mark, // [Go] Shouldn't this be token.end_mark?
+ }
+ return true
+}
+
+// Parse the productions:
+// block_mapping ::= BLOCK-MAPPING_START
+// *******************
+// ((KEY block_node_or_indentless_sequence?)?
+// *** *
+// (VALUE block_node_or_indentless_sequence?)?)*
+//
+// BLOCK-END
+// *********
+//
+func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+ if first {
+ token := peek_token(parser)
+ parser.marks = append(parser.marks, token.start_mark)
+ skip_token(parser)
+ }
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ == yaml_KEY_TOKEN {
+ mark := token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_KEY_TOKEN &&
+ token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_BLOCK_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE)
+ return yaml_parser_parse_node(parser, event, true, true)
+ } else {
+ parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+ }
+ } else if token.typ == yaml_BLOCK_END_TOKEN {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+ skip_token(parser)
+ return true
+ }
+
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a block mapping", context_mark,
+ "did not find expected key", token.start_mark)
+}
+
+// Parse the productions:
+// block_mapping ::= BLOCK-MAPPING_START
+//
+// ((KEY block_node_or_indentless_sequence?)?
+//
+// (VALUE block_node_or_indentless_sequence?)?)*
+// ***** *
+// BLOCK-END
+//
+//
+func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ == yaml_VALUE_TOKEN {
+ mark := token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_KEY_TOKEN &&
+ token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_BLOCK_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE)
+ return yaml_parser_parse_node(parser, event, true, true)
+ }
+ parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+ }
+ parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+}
+
+// Parse the productions:
+// flow_sequence ::= FLOW-SEQUENCE-START
+// *******************
+// (flow_sequence_entry FLOW-ENTRY)*
+// * **********
+// flow_sequence_entry?
+// *
+// FLOW-SEQUENCE-END
+// *****************
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// *
+//
+func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+ if first {
+ token := peek_token(parser)
+ parser.marks = append(parser.marks, token.start_mark)
+ skip_token(parser)
+ }
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+ if !first {
+ if token.typ == yaml_FLOW_ENTRY_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ } else {
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a flow sequence", context_mark,
+ "did not find expected ',' or ']'", token.start_mark)
+ }
+ }
+
+ if token.typ == yaml_KEY_TOKEN {
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_START_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ implicit: true,
+ style: yaml_style_t(yaml_FLOW_MAPPING_STYLE),
+ }
+ skip_token(parser)
+ return true
+ } else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ }
+
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+
+ skip_token(parser)
+ return true
+}
+
+//
+// Parse the productions:
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// *** *
+//
+func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_FLOW_ENTRY_TOKEN &&
+ token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ mark := token.end_mark
+ skip_token(parser)
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+}
+
+// Parse the productions:
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// ***** *
+//
+func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ == yaml_VALUE_TOKEN {
+ skip_token(parser)
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ }
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+}
+
+// Parse the productions:
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// *
+//
+func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.start_mark, // [Go] Shouldn't this be end_mark?
+ }
+ return true
+}
+
+// Parse the productions:
+// flow_mapping ::= FLOW-MAPPING-START
+// ******************
+// (flow_mapping_entry FLOW-ENTRY)*
+// * **********
+// flow_mapping_entry?
+// ******************
+// FLOW-MAPPING-END
+// ****************
+// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// * *** *
+//
+func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+ if first {
+ token := peek_token(parser)
+ parser.marks = append(parser.marks, token.start_mark)
+ skip_token(parser)
+ }
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+ if !first {
+ if token.typ == yaml_FLOW_ENTRY_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ } else {
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a flow mapping", context_mark,
+ "did not find expected ',' or '}'", token.start_mark)
+ }
+ }
+
+ if token.typ == yaml_KEY_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_FLOW_ENTRY_TOKEN &&
+ token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ } else {
+ parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+ }
+ } else if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ }
+
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+ skip_token(parser)
+ return true
+}
+
+// Parse the productions:
+// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// * ***** *
+//
+func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if empty {
+ parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+ }
+ if token.typ == yaml_VALUE_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ }
+ parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+}
+
+// Generate an empty scalar event.
+func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool {
+ *event = yaml_event_t{
+ typ: yaml_SCALAR_EVENT,
+ start_mark: mark,
+ end_mark: mark,
+ value: nil, // Empty
+ implicit: true,
+ style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE),
+ }
+ return true
+}
+
+var default_tag_directives = []yaml_tag_directive_t{
+ {[]byte("!"), []byte("!")},
+ {[]byte("!!"), []byte("tag:yaml.org,2002:")},
+}
+
+// Parse directives.
+func yaml_parser_process_directives(parser *yaml_parser_t,
+ version_directive_ref **yaml_version_directive_t,
+ tag_directives_ref *[]yaml_tag_directive_t) bool {
+
+ var version_directive *yaml_version_directive_t
+ var tag_directives []yaml_tag_directive_t
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN {
+ if token.typ == yaml_VERSION_DIRECTIVE_TOKEN {
+ if version_directive != nil {
+ yaml_parser_set_parser_error(parser,
+ "found duplicate %YAML directive", token.start_mark)
+ return false
+ }
+ if token.major != 1 || token.minor != 1 {
+ yaml_parser_set_parser_error(parser,
+ "found incompatible YAML document", token.start_mark)
+ return false
+ }
+ version_directive = &yaml_version_directive_t{
+ major: token.major,
+ minor: token.minor,
+ }
+ } else if token.typ == yaml_TAG_DIRECTIVE_TOKEN {
+ value := yaml_tag_directive_t{
+ handle: token.value,
+ prefix: token.prefix,
+ }
+ if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) {
+ return false
+ }
+ tag_directives = append(tag_directives, value)
+ }
+
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ }
+
+ for i := range default_tag_directives {
+ if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) {
+ return false
+ }
+ }
+
+ if version_directive_ref != nil {
+ *version_directive_ref = version_directive
+ }
+ if tag_directives_ref != nil {
+ *tag_directives_ref = tag_directives
+ }
+ return true
+}
+
+// Append a tag directive to the directives stack.
+func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool {
+ for i := range parser.tag_directives {
+ if bytes.Equal(value.handle, parser.tag_directives[i].handle) {
+ if allow_duplicates {
+ return true
+ }
+ return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark)
+ }
+ }
+
+ // [Go] I suspect the copy is unnecessary. This was likely done
+ // because there was no way to track ownership of the data.
+ value_copy := yaml_tag_directive_t{
+ handle: make([]byte, len(value.handle)),
+ prefix: make([]byte, len(value.prefix)),
+ }
+ copy(value_copy.handle, value.handle)
+ copy(value_copy.prefix, value.prefix)
+ parser.tag_directives = append(parser.tag_directives, value_copy)
+ return true
+}
--- /dev/null
+package yaml
+
+import (
+ "io"
+)
+
+// Set the reader error and return 0.
+func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool {
+ parser.error = yaml_READER_ERROR
+ parser.problem = problem
+ parser.problem_offset = offset
+ parser.problem_value = value
+ return false
+}
+
+// Byte order marks.
+const (
+ bom_UTF8 = "\xef\xbb\xbf"
+ bom_UTF16LE = "\xff\xfe"
+ bom_UTF16BE = "\xfe\xff"
+)
+
+// Determine the input stream encoding by checking the BOM symbol. If no BOM is
+// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
+func yaml_parser_determine_encoding(parser *yaml_parser_t) bool {
+ // Ensure that we had enough bytes in the raw buffer.
+ for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 {
+ if !yaml_parser_update_raw_buffer(parser) {
+ return false
+ }
+ }
+
+ // Determine the encoding.
+ buf := parser.raw_buffer
+ pos := parser.raw_buffer_pos
+ avail := len(buf) - pos
+ if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] {
+ parser.encoding = yaml_UTF16LE_ENCODING
+ parser.raw_buffer_pos += 2
+ parser.offset += 2
+ } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] {
+ parser.encoding = yaml_UTF16BE_ENCODING
+ parser.raw_buffer_pos += 2
+ parser.offset += 2
+ } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] {
+ parser.encoding = yaml_UTF8_ENCODING
+ parser.raw_buffer_pos += 3
+ parser.offset += 3
+ } else {
+ parser.encoding = yaml_UTF8_ENCODING
+ }
+ return true
+}
+
+// Update the raw buffer.
+func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool {
+ size_read := 0
+
+ // Return if the raw buffer is full.
+ if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) {
+ return true
+ }
+
+ // Return on EOF.
+ if parser.eof {
+ return true
+ }
+
+ // Move the remaining bytes in the raw buffer to the beginning.
+ if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) {
+ copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:])
+ }
+ parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos]
+ parser.raw_buffer_pos = 0
+
+ // Call the read handler to fill the buffer.
+ size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)])
+ parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read]
+ if err == io.EOF {
+ parser.eof = true
+ } else if err != nil {
+ return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1)
+ }
+ return true
+}
+
+// Ensure that the buffer contains at least `length` characters.
+// Return true on success, false on failure.
+//
+// The length is supposed to be significantly less that the buffer size.
+func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
+ if parser.read_handler == nil {
+ panic("read handler must be set")
+ }
+
+ // [Go] This function was changed to guarantee the requested length size at EOF.
+ // The fact we need to do this is pretty awful, but the description above implies
+ // for that to be the case, and there are tests
+
+ // If the EOF flag is set and the raw buffer is empty, do nothing.
+ if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) {
+ // [Go] ACTUALLY! Read the documentation of this function above.
+ // This is just broken. To return true, we need to have the
+ // given length in the buffer. Not doing that means every single
+ // check that calls this function to make sure the buffer has a
+ // given length is Go) panicking; or C) accessing invalid memory.
+ //return true
+ }
+
+ // Return if the buffer contains enough characters.
+ if parser.unread >= length {
+ return true
+ }
+
+ // Determine the input encoding if it is not known yet.
+ if parser.encoding == yaml_ANY_ENCODING {
+ if !yaml_parser_determine_encoding(parser) {
+ return false
+ }
+ }
+
+ // Move the unread characters to the beginning of the buffer.
+ buffer_len := len(parser.buffer)
+ if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len {
+ copy(parser.buffer, parser.buffer[parser.buffer_pos:])
+ buffer_len -= parser.buffer_pos
+ parser.buffer_pos = 0
+ } else if parser.buffer_pos == buffer_len {
+ buffer_len = 0
+ parser.buffer_pos = 0
+ }
+
+ // Open the whole buffer for writing, and cut it before returning.
+ parser.buffer = parser.buffer[:cap(parser.buffer)]
+
+ // Fill the buffer until it has enough characters.
+ first := true
+ for parser.unread < length {
+
+ // Fill the raw buffer if necessary.
+ if !first || parser.raw_buffer_pos == len(parser.raw_buffer) {
+ if !yaml_parser_update_raw_buffer(parser) {
+ parser.buffer = parser.buffer[:buffer_len]
+ return false
+ }
+ }
+ first = false
+
+ // Decode the raw buffer.
+ inner:
+ for parser.raw_buffer_pos != len(parser.raw_buffer) {
+ var value rune
+ var width int
+
+ raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos
+
+ // Decode the next character.
+ switch parser.encoding {
+ case yaml_UTF8_ENCODING:
+ // Decode a UTF-8 character. Check RFC 3629
+ // (http://www.ietf.org/rfc/rfc3629.txt) for more details.
+ //
+ // The following table (taken from the RFC) is used for
+ // decoding.
+ //
+ // Char. number range | UTF-8 octet sequence
+ // (hexadecimal) | (binary)
+ // --------------------+------------------------------------
+ // 0000 0000-0000 007F | 0xxxxxxx
+ // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
+ // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
+ // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ //
+ // Additionally, the characters in the range 0xD800-0xDFFF
+ // are prohibited as they are reserved for use with UTF-16
+ // surrogate pairs.
+
+ // Determine the length of the UTF-8 sequence.
+ octet := parser.raw_buffer[parser.raw_buffer_pos]
+ switch {
+ case octet&0x80 == 0x00:
+ width = 1
+ case octet&0xE0 == 0xC0:
+ width = 2
+ case octet&0xF0 == 0xE0:
+ width = 3
+ case octet&0xF8 == 0xF0:
+ width = 4
+ default:
+ // The leading octet is invalid.
+ return yaml_parser_set_reader_error(parser,
+ "invalid leading UTF-8 octet",
+ parser.offset, int(octet))
+ }
+
+ // Check if the raw buffer contains an incomplete character.
+ if width > raw_unread {
+ if parser.eof {
+ return yaml_parser_set_reader_error(parser,
+ "incomplete UTF-8 octet sequence",
+ parser.offset, -1)
+ }
+ break inner
+ }
+
+ // Decode the leading octet.
+ switch {
+ case octet&0x80 == 0x00:
+ value = rune(octet & 0x7F)
+ case octet&0xE0 == 0xC0:
+ value = rune(octet & 0x1F)
+ case octet&0xF0 == 0xE0:
+ value = rune(octet & 0x0F)
+ case octet&0xF8 == 0xF0:
+ value = rune(octet & 0x07)
+ default:
+ value = 0
+ }
+
+ // Check and decode the trailing octets.
+ for k := 1; k < width; k++ {
+ octet = parser.raw_buffer[parser.raw_buffer_pos+k]
+
+ // Check if the octet is valid.
+ if (octet & 0xC0) != 0x80 {
+ return yaml_parser_set_reader_error(parser,
+ "invalid trailing UTF-8 octet",
+ parser.offset+k, int(octet))
+ }
+
+ // Decode the octet.
+ value = (value << 6) + rune(octet&0x3F)
+ }
+
+ // Check the length of the sequence against the value.
+ switch {
+ case width == 1:
+ case width == 2 && value >= 0x80:
+ case width == 3 && value >= 0x800:
+ case width == 4 && value >= 0x10000:
+ default:
+ return yaml_parser_set_reader_error(parser,
+ "invalid length of a UTF-8 sequence",
+ parser.offset, -1)
+ }
+
+ // Check the range of the value.
+ if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF {
+ return yaml_parser_set_reader_error(parser,
+ "invalid Unicode character",
+ parser.offset, int(value))
+ }
+
+ case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING:
+ var low, high int
+ if parser.encoding == yaml_UTF16LE_ENCODING {
+ low, high = 0, 1
+ } else {
+ low, high = 1, 0
+ }
+
+ // The UTF-16 encoding is not as simple as one might
+ // naively think. Check RFC 2781
+ // (http://www.ietf.org/rfc/rfc2781.txt).
+ //
+ // Normally, two subsequent bytes describe a Unicode
+ // character. However a special technique (called a
+ // surrogate pair) is used for specifying character
+ // values larger than 0xFFFF.
+ //
+ // A surrogate pair consists of two pseudo-characters:
+ // high surrogate area (0xD800-0xDBFF)
+ // low surrogate area (0xDC00-0xDFFF)
+ //
+ // The following formulas are used for decoding
+ // and encoding characters using surrogate pairs:
+ //
+ // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF)
+ // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF)
+ // W1 = 110110yyyyyyyyyy
+ // W2 = 110111xxxxxxxxxx
+ //
+ // where U is the character value, W1 is the high surrogate
+ // area, W2 is the low surrogate area.
+
+ // Check for incomplete UTF-16 character.
+ if raw_unread < 2 {
+ if parser.eof {
+ return yaml_parser_set_reader_error(parser,
+ "incomplete UTF-16 character",
+ parser.offset, -1)
+ }
+ break inner
+ }
+
+ // Get the character.
+ value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) +
+ (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8)
+
+ // Check for unexpected low surrogate area.
+ if value&0xFC00 == 0xDC00 {
+ return yaml_parser_set_reader_error(parser,
+ "unexpected low surrogate area",
+ parser.offset, int(value))
+ }
+
+ // Check for a high surrogate area.
+ if value&0xFC00 == 0xD800 {
+ width = 4
+
+ // Check for incomplete surrogate pair.
+ if raw_unread < 4 {
+ if parser.eof {
+ return yaml_parser_set_reader_error(parser,
+ "incomplete UTF-16 surrogate pair",
+ parser.offset, -1)
+ }
+ break inner
+ }
+
+ // Get the next character.
+ value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) +
+ (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8)
+
+ // Check for a low surrogate area.
+ if value2&0xFC00 != 0xDC00 {
+ return yaml_parser_set_reader_error(parser,
+ "expected low surrogate area",
+ parser.offset+2, int(value2))
+ }
+
+ // Generate the value of the surrogate pair.
+ value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF)
+ } else {
+ width = 2
+ }
+
+ default:
+ panic("impossible")
+ }
+
+ // Check if the character is in the allowed range:
+ // #x9 | #xA | #xD | [#x20-#x7E] (8 bit)
+ // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit)
+ // | [#x10000-#x10FFFF] (32 bit)
+ switch {
+ case value == 0x09:
+ case value == 0x0A:
+ case value == 0x0D:
+ case value >= 0x20 && value <= 0x7E:
+ case value == 0x85:
+ case value >= 0xA0 && value <= 0xD7FF:
+ case value >= 0xE000 && value <= 0xFFFD:
+ case value >= 0x10000 && value <= 0x10FFFF:
+ default:
+ return yaml_parser_set_reader_error(parser,
+ "control characters are not allowed",
+ parser.offset, int(value))
+ }
+
+ // Move the raw pointers.
+ parser.raw_buffer_pos += width
+ parser.offset += width
+
+ // Finally put the character into the buffer.
+ if value <= 0x7F {
+ // 0000 0000-0000 007F . 0xxxxxxx
+ parser.buffer[buffer_len+0] = byte(value)
+ buffer_len += 1
+ } else if value <= 0x7FF {
+ // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx
+ parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6))
+ parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F))
+ buffer_len += 2
+ } else if value <= 0xFFFF {
+ // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx
+ parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12))
+ parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F))
+ parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F))
+ buffer_len += 3
+ } else {
+ // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18))
+ parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F))
+ parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F))
+ parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F))
+ buffer_len += 4
+ }
+
+ parser.unread++
+ }
+
+ // On EOF, put NUL into the buffer and return.
+ if parser.eof {
+ parser.buffer[buffer_len] = 0
+ buffer_len++
+ parser.unread++
+ break
+ }
+ }
+ // [Go] Read the documentation of this function above. To return true,
+ // we need to have the given length in the buffer. Not doing that means
+ // every single check that calls this function to make sure the buffer
+ // has a given length is Go) panicking; or C) accessing invalid memory.
+ // This happens here due to the EOF above breaking early.
+ for buffer_len < length {
+ parser.buffer[buffer_len] = 0
+ buffer_len++
+ }
+ parser.buffer = parser.buffer[:buffer_len]
+ return true
+}
--- /dev/null
+package yaml
+
+import (
+ "encoding/base64"
+ "math"
+ "regexp"
+ "strconv"
+ "strings"
+ "time"
+)
+
+type resolveMapItem struct {
+ value interface{}
+ tag string
+}
+
+var resolveTable = make([]byte, 256)
+var resolveMap = make(map[string]resolveMapItem)
+
+func init() {
+ t := resolveTable
+ t[int('+')] = 'S' // Sign
+ t[int('-')] = 'S'
+ for _, c := range "0123456789" {
+ t[int(c)] = 'D' // Digit
+ }
+ for _, c := range "yYnNtTfFoO~" {
+ t[int(c)] = 'M' // In map
+ }
+ t[int('.')] = '.' // Float (potentially in map)
+
+ var resolveMapList = []struct {
+ v interface{}
+ tag string
+ l []string
+ }{
+ {true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}},
+ {true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}},
+ {true, yaml_BOOL_TAG, []string{"on", "On", "ON"}},
+ {false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}},
+ {false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}},
+ {false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}},
+ {nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}},
+ {math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}},
+ {math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}},
+ {math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}},
+ {math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}},
+ {"<<", yaml_MERGE_TAG, []string{"<<"}},
+ }
+
+ m := resolveMap
+ for _, item := range resolveMapList {
+ for _, s := range item.l {
+ m[s] = resolveMapItem{item.v, item.tag}
+ }
+ }
+}
+
+const longTagPrefix = "tag:yaml.org,2002:"
+
+func shortTag(tag string) string {
+ // TODO This can easily be made faster and produce less garbage.
+ if strings.HasPrefix(tag, longTagPrefix) {
+ return "!!" + tag[len(longTagPrefix):]
+ }
+ return tag
+}
+
+func longTag(tag string) string {
+ if strings.HasPrefix(tag, "!!") {
+ return longTagPrefix + tag[2:]
+ }
+ return tag
+}
+
+func resolvableTag(tag string) bool {
+ switch tag {
+ case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG, yaml_TIMESTAMP_TAG:
+ return true
+ }
+ return false
+}
+
+var yamlStyleFloat = regexp.MustCompile(`^[-+]?[0-9]*\.?[0-9]+([eE][-+][0-9]+)?$`)
+
+func resolve(tag string, in string) (rtag string, out interface{}) {
+ if !resolvableTag(tag) {
+ return tag, in
+ }
+
+ defer func() {
+ switch tag {
+ case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG:
+ return
+ case yaml_FLOAT_TAG:
+ if rtag == yaml_INT_TAG {
+ switch v := out.(type) {
+ case int64:
+ rtag = yaml_FLOAT_TAG
+ out = float64(v)
+ return
+ case int:
+ rtag = yaml_FLOAT_TAG
+ out = float64(v)
+ return
+ }
+ }
+ }
+ failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))
+ }()
+
+ // Any data is accepted as a !!str or !!binary.
+ // Otherwise, the prefix is enough of a hint about what it might be.
+ hint := byte('N')
+ if in != "" {
+ hint = resolveTable[in[0]]
+ }
+ if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG {
+ // Handle things we can lookup in a map.
+ if item, ok := resolveMap[in]; ok {
+ return item.tag, item.value
+ }
+
+ // Base 60 floats are a bad idea, were dropped in YAML 1.2, and
+ // are purposefully unsupported here. They're still quoted on
+ // the way out for compatibility with other parser, though.
+
+ switch hint {
+ case 'M':
+ // We've already checked the map above.
+
+ case '.':
+ // Not in the map, so maybe a normal float.
+ floatv, err := strconv.ParseFloat(in, 64)
+ if err == nil {
+ return yaml_FLOAT_TAG, floatv
+ }
+
+ case 'D', 'S':
+ // Int, float, or timestamp.
+ // Only try values as a timestamp if the value is unquoted or there's an explicit
+ // !!timestamp tag.
+ if tag == "" || tag == yaml_TIMESTAMP_TAG {
+ t, ok := parseTimestamp(in)
+ if ok {
+ return yaml_TIMESTAMP_TAG, t
+ }
+ }
+
+ plain := strings.Replace(in, "_", "", -1)
+ intv, err := strconv.ParseInt(plain, 0, 64)
+ if err == nil {
+ if intv == int64(int(intv)) {
+ return yaml_INT_TAG, int(intv)
+ } else {
+ return yaml_INT_TAG, intv
+ }
+ }
+ uintv, err := strconv.ParseUint(plain, 0, 64)
+ if err == nil {
+ return yaml_INT_TAG, uintv
+ }
+ if yamlStyleFloat.MatchString(plain) {
+ floatv, err := strconv.ParseFloat(plain, 64)
+ if err == nil {
+ return yaml_FLOAT_TAG, floatv
+ }
+ }
+ if strings.HasPrefix(plain, "0b") {
+ intv, err := strconv.ParseInt(plain[2:], 2, 64)
+ if err == nil {
+ if intv == int64(int(intv)) {
+ return yaml_INT_TAG, int(intv)
+ } else {
+ return yaml_INT_TAG, intv
+ }
+ }
+ uintv, err := strconv.ParseUint(plain[2:], 2, 64)
+ if err == nil {
+ return yaml_INT_TAG, uintv
+ }
+ } else if strings.HasPrefix(plain, "-0b") {
+ intv, err := strconv.ParseInt("-" + plain[3:], 2, 64)
+ if err == nil {
+ if true || intv == int64(int(intv)) {
+ return yaml_INT_TAG, int(intv)
+ } else {
+ return yaml_INT_TAG, intv
+ }
+ }
+ }
+ default:
+ panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")")
+ }
+ }
+ return yaml_STR_TAG, in
+}
+
+// encodeBase64 encodes s as base64 that is broken up into multiple lines
+// as appropriate for the resulting length.
+func encodeBase64(s string) string {
+ const lineLen = 70
+ encLen := base64.StdEncoding.EncodedLen(len(s))
+ lines := encLen/lineLen + 1
+ buf := make([]byte, encLen*2+lines)
+ in := buf[0:encLen]
+ out := buf[encLen:]
+ base64.StdEncoding.Encode(in, []byte(s))
+ k := 0
+ for i := 0; i < len(in); i += lineLen {
+ j := i + lineLen
+ if j > len(in) {
+ j = len(in)
+ }
+ k += copy(out[k:], in[i:j])
+ if lines > 1 {
+ out[k] = '\n'
+ k++
+ }
+ }
+ return string(out[:k])
+}
+
+// This is a subset of the formats allowed by the regular expression
+// defined at http://yaml.org/type/timestamp.html.
+var allowedTimestampFormats = []string{
+ "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields.
+ "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t".
+ "2006-1-2 15:4:5.999999999", // space separated with no time zone
+ "2006-1-2", // date only
+ // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5"
+ // from the set of examples.
+}
+
+// parseTimestamp parses s as a timestamp string and
+// returns the timestamp and reports whether it succeeded.
+// Timestamp formats are defined at http://yaml.org/type/timestamp.html
+func parseTimestamp(s string) (time.Time, bool) {
+ // TODO write code to check all the formats supported by
+ // http://yaml.org/type/timestamp.html instead of using time.Parse.
+
+ // Quick check: all date formats start with YYYY-.
+ i := 0
+ for ; i < len(s); i++ {
+ if c := s[i]; c < '0' || c > '9' {
+ break
+ }
+ }
+ if i != 4 || i == len(s) || s[i] != '-' {
+ return time.Time{}, false
+ }
+ for _, format := range allowedTimestampFormats {
+ if t, err := time.Parse(format, s); err == nil {
+ return t, true
+ }
+ }
+ return time.Time{}, false
+}
--- /dev/null
+package yaml
+
+import (
+ "bytes"
+ "fmt"
+)
+
+// Introduction
+// ************
+//
+// The following notes assume that you are familiar with the YAML specification
+// (http://yaml.org/spec/1.2/spec.html). We mostly follow it, although in
+// some cases we are less restrictive that it requires.
+//
+// The process of transforming a YAML stream into a sequence of events is
+// divided on two steps: Scanning and Parsing.
+//
+// The Scanner transforms the input stream into a sequence of tokens, while the
+// parser transform the sequence of tokens produced by the Scanner into a
+// sequence of parsing events.
+//
+// The Scanner is rather clever and complicated. The Parser, on the contrary,
+// is a straightforward implementation of a recursive-descendant parser (or,
+// LL(1) parser, as it is usually called).
+//
+// Actually there are two issues of Scanning that might be called "clever", the
+// rest is quite straightforward. The issues are "block collection start" and
+// "simple keys". Both issues are explained below in details.
+//
+// Here the Scanning step is explained and implemented. We start with the list
+// of all the tokens produced by the Scanner together with short descriptions.
+//
+// Now, tokens:
+//
+// STREAM-START(encoding) # The stream start.
+// STREAM-END # The stream end.
+// VERSION-DIRECTIVE(major,minor) # The '%YAML' directive.
+// TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive.
+// DOCUMENT-START # '---'
+// DOCUMENT-END # '...'
+// BLOCK-SEQUENCE-START # Indentation increase denoting a block
+// BLOCK-MAPPING-START # sequence or a block mapping.
+// BLOCK-END # Indentation decrease.
+// FLOW-SEQUENCE-START # '['
+// FLOW-SEQUENCE-END # ']'
+// BLOCK-SEQUENCE-START # '{'
+// BLOCK-SEQUENCE-END # '}'
+// BLOCK-ENTRY # '-'
+// FLOW-ENTRY # ','
+// KEY # '?' or nothing (simple keys).
+// VALUE # ':'
+// ALIAS(anchor) # '*anchor'
+// ANCHOR(anchor) # '&anchor'
+// TAG(handle,suffix) # '!handle!suffix'
+// SCALAR(value,style) # A scalar.
+//
+// The following two tokens are "virtual" tokens denoting the beginning and the
+// end of the stream:
+//
+// STREAM-START(encoding)
+// STREAM-END
+//
+// We pass the information about the input stream encoding with the
+// STREAM-START token.
+//
+// The next two tokens are responsible for tags:
+//
+// VERSION-DIRECTIVE(major,minor)
+// TAG-DIRECTIVE(handle,prefix)
+//
+// Example:
+//
+// %YAML 1.1
+// %TAG ! !foo
+// %TAG !yaml! tag:yaml.org,2002:
+// ---
+//
+// The correspoding sequence of tokens:
+//
+// STREAM-START(utf-8)
+// VERSION-DIRECTIVE(1,1)
+// TAG-DIRECTIVE("!","!foo")
+// TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:")
+// DOCUMENT-START
+// STREAM-END
+//
+// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole
+// line.
+//
+// The document start and end indicators are represented by:
+//
+// DOCUMENT-START
+// DOCUMENT-END
+//
+// Note that if a YAML stream contains an implicit document (without '---'
+// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be
+// produced.
+//
+// In the following examples, we present whole documents together with the
+// produced tokens.
+//
+// 1. An implicit document:
+//
+// 'a scalar'
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// SCALAR("a scalar",single-quoted)
+// STREAM-END
+//
+// 2. An explicit document:
+//
+// ---
+// 'a scalar'
+// ...
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// DOCUMENT-START
+// SCALAR("a scalar",single-quoted)
+// DOCUMENT-END
+// STREAM-END
+//
+// 3. Several documents in a stream:
+//
+// 'a scalar'
+// ---
+// 'another scalar'
+// ---
+// 'yet another scalar'
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// SCALAR("a scalar",single-quoted)
+// DOCUMENT-START
+// SCALAR("another scalar",single-quoted)
+// DOCUMENT-START
+// SCALAR("yet another scalar",single-quoted)
+// STREAM-END
+//
+// We have already introduced the SCALAR token above. The following tokens are
+// used to describe aliases, anchors, tag, and scalars:
+//
+// ALIAS(anchor)
+// ANCHOR(anchor)
+// TAG(handle,suffix)
+// SCALAR(value,style)
+//
+// The following series of examples illustrate the usage of these tokens:
+//
+// 1. A recursive sequence:
+//
+// &A [ *A ]
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// ANCHOR("A")
+// FLOW-SEQUENCE-START
+// ALIAS("A")
+// FLOW-SEQUENCE-END
+// STREAM-END
+//
+// 2. A tagged scalar:
+//
+// !!float "3.14" # A good approximation.
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// TAG("!!","float")
+// SCALAR("3.14",double-quoted)
+// STREAM-END
+//
+// 3. Various scalar styles:
+//
+// --- # Implicit empty plain scalars do not produce tokens.
+// --- a plain scalar
+// --- 'a single-quoted scalar'
+// --- "a double-quoted scalar"
+// --- |-
+// a literal scalar
+// --- >-
+// a folded
+// scalar
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// DOCUMENT-START
+// DOCUMENT-START
+// SCALAR("a plain scalar",plain)
+// DOCUMENT-START
+// SCALAR("a single-quoted scalar",single-quoted)
+// DOCUMENT-START
+// SCALAR("a double-quoted scalar",double-quoted)
+// DOCUMENT-START
+// SCALAR("a literal scalar",literal)
+// DOCUMENT-START
+// SCALAR("a folded scalar",folded)
+// STREAM-END
+//
+// Now it's time to review collection-related tokens. We will start with
+// flow collections:
+//
+// FLOW-SEQUENCE-START
+// FLOW-SEQUENCE-END
+// FLOW-MAPPING-START
+// FLOW-MAPPING-END
+// FLOW-ENTRY
+// KEY
+// VALUE
+//
+// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and
+// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}'
+// correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the
+// indicators '?' and ':', which are used for denoting mapping keys and values,
+// are represented by the KEY and VALUE tokens.
+//
+// The following examples show flow collections:
+//
+// 1. A flow sequence:
+//
+// [item 1, item 2, item 3]
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// FLOW-SEQUENCE-START
+// SCALAR("item 1",plain)
+// FLOW-ENTRY
+// SCALAR("item 2",plain)
+// FLOW-ENTRY
+// SCALAR("item 3",plain)
+// FLOW-SEQUENCE-END
+// STREAM-END
+//
+// 2. A flow mapping:
+//
+// {
+// a simple key: a value, # Note that the KEY token is produced.
+// ? a complex key: another value,
+// }
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// FLOW-MAPPING-START
+// KEY
+// SCALAR("a simple key",plain)
+// VALUE
+// SCALAR("a value",plain)
+// FLOW-ENTRY
+// KEY
+// SCALAR("a complex key",plain)
+// VALUE
+// SCALAR("another value",plain)
+// FLOW-ENTRY
+// FLOW-MAPPING-END
+// STREAM-END
+//
+// A simple key is a key which is not denoted by the '?' indicator. Note that
+// the Scanner still produce the KEY token whenever it encounters a simple key.
+//
+// For scanning block collections, the following tokens are used (note that we
+// repeat KEY and VALUE here):
+//
+// BLOCK-SEQUENCE-START
+// BLOCK-MAPPING-START
+// BLOCK-END
+// BLOCK-ENTRY
+// KEY
+// VALUE
+//
+// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation
+// increase that precedes a block collection (cf. the INDENT token in Python).
+// The token BLOCK-END denote indentation decrease that ends a block collection
+// (cf. the DEDENT token in Python). However YAML has some syntax pecularities
+// that makes detections of these tokens more complex.
+//
+// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators
+// '-', '?', and ':' correspondingly.
+//
+// The following examples show how the tokens BLOCK-SEQUENCE-START,
+// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner:
+//
+// 1. Block sequences:
+//
+// - item 1
+// - item 2
+// -
+// - item 3.1
+// - item 3.2
+// -
+// key 1: value 1
+// key 2: value 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-ENTRY
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 3.1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 3.2",plain)
+// BLOCK-END
+// BLOCK-ENTRY
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// 2. Block mappings:
+//
+// a simple key: a value # The KEY token is produced here.
+// ? a complex key
+// : another value
+// a mapping:
+// key 1: value 1
+// key 2: value 2
+// a sequence:
+// - item 1
+// - item 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("a simple key",plain)
+// VALUE
+// SCALAR("a value",plain)
+// KEY
+// SCALAR("a complex key",plain)
+// VALUE
+// SCALAR("another value",plain)
+// KEY
+// SCALAR("a mapping",plain)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// KEY
+// SCALAR("a sequence",plain)
+// VALUE
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// YAML does not always require to start a new block collection from a new
+// line. If the current line contains only '-', '?', and ':' indicators, a new
+// block collection may start at the current line. The following examples
+// illustrate this case:
+//
+// 1. Collections in a sequence:
+//
+// - - item 1
+// - item 2
+// - key 1: value 1
+// key 2: value 2
+// - ? complex key
+// : complex value
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+// BLOCK-ENTRY
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// BLOCK-ENTRY
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("complex key")
+// VALUE
+// SCALAR("complex value")
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// 2. Collections in a mapping:
+//
+// ? a sequence
+// : - item 1
+// - item 2
+// ? a mapping
+// : key 1: value 1
+// key 2: value 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("a sequence",plain)
+// VALUE
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+// KEY
+// SCALAR("a mapping",plain)
+// VALUE
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// YAML also permits non-indented sequences if they are included into a block
+// mapping. In this case, the token BLOCK-SEQUENCE-START is not produced:
+//
+// key:
+// - item 1 # BLOCK-SEQUENCE-START is NOT produced here.
+// - item 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key",plain)
+// VALUE
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+//
+
+// Ensure that the buffer contains the required number of characters.
+// Return true on success, false on failure (reader error or memory error).
+func cache(parser *yaml_parser_t, length int) bool {
+ // [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B)
+ return parser.unread >= length || yaml_parser_update_buffer(parser, length)
+}
+
+// Advance the buffer pointer.
+func skip(parser *yaml_parser_t) {
+ parser.mark.index++
+ parser.mark.column++
+ parser.unread--
+ parser.buffer_pos += width(parser.buffer[parser.buffer_pos])
+}
+
+func skip_line(parser *yaml_parser_t) {
+ if is_crlf(parser.buffer, parser.buffer_pos) {
+ parser.mark.index += 2
+ parser.mark.column = 0
+ parser.mark.line++
+ parser.unread -= 2
+ parser.buffer_pos += 2
+ } else if is_break(parser.buffer, parser.buffer_pos) {
+ parser.mark.index++
+ parser.mark.column = 0
+ parser.mark.line++
+ parser.unread--
+ parser.buffer_pos += width(parser.buffer[parser.buffer_pos])
+ }
+}
+
+// Copy a character to a string buffer and advance pointers.
+func read(parser *yaml_parser_t, s []byte) []byte {
+ w := width(parser.buffer[parser.buffer_pos])
+ if w == 0 {
+ panic("invalid character sequence")
+ }
+ if len(s) == 0 {
+ s = make([]byte, 0, 32)
+ }
+ if w == 1 && len(s)+w <= cap(s) {
+ s = s[:len(s)+1]
+ s[len(s)-1] = parser.buffer[parser.buffer_pos]
+ parser.buffer_pos++
+ } else {
+ s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...)
+ parser.buffer_pos += w
+ }
+ parser.mark.index++
+ parser.mark.column++
+ parser.unread--
+ return s
+}
+
+// Copy a line break character to a string buffer and advance pointers.
+func read_line(parser *yaml_parser_t, s []byte) []byte {
+ buf := parser.buffer
+ pos := parser.buffer_pos
+ switch {
+ case buf[pos] == '\r' && buf[pos+1] == '\n':
+ // CR LF . LF
+ s = append(s, '\n')
+ parser.buffer_pos += 2
+ parser.mark.index++
+ parser.unread--
+ case buf[pos] == '\r' || buf[pos] == '\n':
+ // CR|LF . LF
+ s = append(s, '\n')
+ parser.buffer_pos += 1
+ case buf[pos] == '\xC2' && buf[pos+1] == '\x85':
+ // NEL . LF
+ s = append(s, '\n')
+ parser.buffer_pos += 2
+ case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'):
+ // LS|PS . LS|PS
+ s = append(s, buf[parser.buffer_pos:pos+3]...)
+ parser.buffer_pos += 3
+ default:
+ return s
+ }
+ parser.mark.index++
+ parser.mark.column = 0
+ parser.mark.line++
+ parser.unread--
+ return s
+}
+
+// Get the next token.
+func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool {
+ // Erase the token object.
+ *token = yaml_token_t{} // [Go] Is this necessary?
+
+ // No tokens after STREAM-END or error.
+ if parser.stream_end_produced || parser.error != yaml_NO_ERROR {
+ return true
+ }
+
+ // Ensure that the tokens queue contains enough tokens.
+ if !parser.token_available {
+ if !yaml_parser_fetch_more_tokens(parser) {
+ return false
+ }
+ }
+
+ // Fetch the next token from the queue.
+ *token = parser.tokens[parser.tokens_head]
+ parser.tokens_head++
+ parser.tokens_parsed++
+ parser.token_available = false
+
+ if token.typ == yaml_STREAM_END_TOKEN {
+ parser.stream_end_produced = true
+ }
+ return true
+}
+
+// Set the scanner error and return false.
+func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool {
+ parser.error = yaml_SCANNER_ERROR
+ parser.context = context
+ parser.context_mark = context_mark
+ parser.problem = problem
+ parser.problem_mark = parser.mark
+ return false
+}
+
+func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool {
+ context := "while parsing a tag"
+ if directive {
+ context = "while parsing a %TAG directive"
+ }
+ return yaml_parser_set_scanner_error(parser, context, context_mark, problem)
+}
+
+func trace(args ...interface{}) func() {
+ pargs := append([]interface{}{"+++"}, args...)
+ fmt.Println(pargs...)
+ pargs = append([]interface{}{"---"}, args...)
+ return func() { fmt.Println(pargs...) }
+}
+
+// Ensure that the tokens queue contains at least one token which can be
+// returned to the Parser.
+func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool {
+ // While we need more tokens to fetch, do it.
+ for {
+ // Check if we really need to fetch more tokens.
+ need_more_tokens := false
+
+ if parser.tokens_head == len(parser.tokens) {
+ // Queue is empty.
+ need_more_tokens = true
+ } else {
+ // Check if any potential simple key may occupy the head position.
+ if !yaml_parser_stale_simple_keys(parser) {
+ return false
+ }
+
+ for i := range parser.simple_keys {
+ simple_key := &parser.simple_keys[i]
+ if simple_key.possible && simple_key.token_number == parser.tokens_parsed {
+ need_more_tokens = true
+ break
+ }
+ }
+ }
+
+ // We are finished.
+ if !need_more_tokens {
+ break
+ }
+ // Fetch the next token.
+ if !yaml_parser_fetch_next_token(parser) {
+ return false
+ }
+ }
+
+ parser.token_available = true
+ return true
+}
+
+// The dispatcher for token fetchers.
+func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool {
+ // Ensure that the buffer is initialized.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ // Check if we just started scanning. Fetch STREAM-START then.
+ if !parser.stream_start_produced {
+ return yaml_parser_fetch_stream_start(parser)
+ }
+
+ // Eat whitespaces and comments until we reach the next token.
+ if !yaml_parser_scan_to_next_token(parser) {
+ return false
+ }
+
+ // Remove obsolete potential simple keys.
+ if !yaml_parser_stale_simple_keys(parser) {
+ return false
+ }
+
+ // Check the indentation level against the current column.
+ if !yaml_parser_unroll_indent(parser, parser.mark.column) {
+ return false
+ }
+
+ // Ensure that the buffer contains at least 4 characters. 4 is the length
+ // of the longest indicators ('--- ' and '... ').
+ if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
+ return false
+ }
+
+ // Is it the end of the stream?
+ if is_z(parser.buffer, parser.buffer_pos) {
+ return yaml_parser_fetch_stream_end(parser)
+ }
+
+ // Is it a directive?
+ if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' {
+ return yaml_parser_fetch_directive(parser)
+ }
+
+ buf := parser.buffer
+ pos := parser.buffer_pos
+
+ // Is it the document start indicator?
+ if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) {
+ return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN)
+ }
+
+ // Is it the document end indicator?
+ if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) {
+ return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN)
+ }
+
+ // Is it the flow sequence start indicator?
+ if buf[pos] == '[' {
+ return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN)
+ }
+
+ // Is it the flow mapping start indicator?
+ if parser.buffer[parser.buffer_pos] == '{' {
+ return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN)
+ }
+
+ // Is it the flow sequence end indicator?
+ if parser.buffer[parser.buffer_pos] == ']' {
+ return yaml_parser_fetch_flow_collection_end(parser,
+ yaml_FLOW_SEQUENCE_END_TOKEN)
+ }
+
+ // Is it the flow mapping end indicator?
+ if parser.buffer[parser.buffer_pos] == '}' {
+ return yaml_parser_fetch_flow_collection_end(parser,
+ yaml_FLOW_MAPPING_END_TOKEN)
+ }
+
+ // Is it the flow entry indicator?
+ if parser.buffer[parser.buffer_pos] == ',' {
+ return yaml_parser_fetch_flow_entry(parser)
+ }
+
+ // Is it the block entry indicator?
+ if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) {
+ return yaml_parser_fetch_block_entry(parser)
+ }
+
+ // Is it the key indicator?
+ if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) {
+ return yaml_parser_fetch_key(parser)
+ }
+
+ // Is it the value indicator?
+ if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) {
+ return yaml_parser_fetch_value(parser)
+ }
+
+ // Is it an alias?
+ if parser.buffer[parser.buffer_pos] == '*' {
+ return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN)
+ }
+
+ // Is it an anchor?
+ if parser.buffer[parser.buffer_pos] == '&' {
+ return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN)
+ }
+
+ // Is it a tag?
+ if parser.buffer[parser.buffer_pos] == '!' {
+ return yaml_parser_fetch_tag(parser)
+ }
+
+ // Is it a literal scalar?
+ if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 {
+ return yaml_parser_fetch_block_scalar(parser, true)
+ }
+
+ // Is it a folded scalar?
+ if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 {
+ return yaml_parser_fetch_block_scalar(parser, false)
+ }
+
+ // Is it a single-quoted scalar?
+ if parser.buffer[parser.buffer_pos] == '\'' {
+ return yaml_parser_fetch_flow_scalar(parser, true)
+ }
+
+ // Is it a double-quoted scalar?
+ if parser.buffer[parser.buffer_pos] == '"' {
+ return yaml_parser_fetch_flow_scalar(parser, false)
+ }
+
+ // Is it a plain scalar?
+ //
+ // A plain scalar may start with any non-blank characters except
+ //
+ // '-', '?', ':', ',', '[', ']', '{', '}',
+ // '#', '&', '*', '!', '|', '>', '\'', '\"',
+ // '%', '@', '`'.
+ //
+ // In the block context (and, for the '-' indicator, in the flow context
+ // too), it may also start with the characters
+ //
+ // '-', '?', ':'
+ //
+ // if it is followed by a non-space character.
+ //
+ // The last rule is more restrictive than the specification requires.
+ // [Go] Make this logic more reasonable.
+ //switch parser.buffer[parser.buffer_pos] {
+ //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`':
+ //}
+ if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' ||
+ parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' ||
+ parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' ||
+ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
+ parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' ||
+ parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' ||
+ parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' ||
+ parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' ||
+ parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' ||
+ parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') ||
+ (parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) ||
+ (parser.flow_level == 0 &&
+ (parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') &&
+ !is_blankz(parser.buffer, parser.buffer_pos+1)) {
+ return yaml_parser_fetch_plain_scalar(parser)
+ }
+
+ // If we don't determine the token type so far, it is an error.
+ return yaml_parser_set_scanner_error(parser,
+ "while scanning for the next token", parser.mark,
+ "found character that cannot start any token")
+}
+
+// Check the list of potential simple keys and remove the positions that
+// cannot contain simple keys anymore.
+func yaml_parser_stale_simple_keys(parser *yaml_parser_t) bool {
+ // Check for a potential simple key for each flow level.
+ for i := range parser.simple_keys {
+ simple_key := &parser.simple_keys[i]
+
+ // The specification requires that a simple key
+ //
+ // - is limited to a single line,
+ // - is shorter than 1024 characters.
+ if simple_key.possible && (simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index) {
+
+ // Check if the potential simple key to be removed is required.
+ if simple_key.required {
+ return yaml_parser_set_scanner_error(parser,
+ "while scanning a simple key", simple_key.mark,
+ "could not find expected ':'")
+ }
+ simple_key.possible = false
+ }
+ }
+ return true
+}
+
+// Check if a simple key may start at the current position and add it if
+// needed.
+func yaml_parser_save_simple_key(parser *yaml_parser_t) bool {
+ // A simple key is required at the current position if the scanner is in
+ // the block context and the current column coincides with the indentation
+ // level.
+
+ required := parser.flow_level == 0 && parser.indent == parser.mark.column
+
+ //
+ // If the current position may start a simple key, save it.
+ //
+ if parser.simple_key_allowed {
+ simple_key := yaml_simple_key_t{
+ possible: true,
+ required: required,
+ token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),
+ }
+ simple_key.mark = parser.mark
+
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+ parser.simple_keys[len(parser.simple_keys)-1] = simple_key
+ }
+ return true
+}
+
+// Remove a potential simple key at the current flow level.
+func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool {
+ i := len(parser.simple_keys) - 1
+ if parser.simple_keys[i].possible {
+ // If the key is required, it is an error.
+ if parser.simple_keys[i].required {
+ return yaml_parser_set_scanner_error(parser,
+ "while scanning a simple key", parser.simple_keys[i].mark,
+ "could not find expected ':'")
+ }
+ }
+ // Remove the key from the stack.
+ parser.simple_keys[i].possible = false
+ return true
+}
+
+// Increase the flow level and resize the simple key list if needed.
+func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool {
+ // Reset the simple key on the next level.
+ parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{})
+
+ // Increase the flow level.
+ parser.flow_level++
+ return true
+}
+
+// Decrease the flow level.
+func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool {
+ if parser.flow_level > 0 {
+ parser.flow_level--
+ parser.simple_keys = parser.simple_keys[:len(parser.simple_keys)-1]
+ }
+ return true
+}
+
+// Push the current indentation level to the stack and set the new level
+// the current column is greater than the indentation level. In this case,
+// append or insert the specified token into the token queue.
+func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool {
+ // In the flow context, do nothing.
+ if parser.flow_level > 0 {
+ return true
+ }
+
+ if parser.indent < column {
+ // Push the current indentation level to the stack and set the new
+ // indentation level.
+ parser.indents = append(parser.indents, parser.indent)
+ parser.indent = column
+
+ // Create a token and insert it into the queue.
+ token := yaml_token_t{
+ typ: typ,
+ start_mark: mark,
+ end_mark: mark,
+ }
+ if number > -1 {
+ number -= parser.tokens_parsed
+ }
+ yaml_insert_token(parser, number, &token)
+ }
+ return true
+}
+
+// Pop indentation levels from the indents stack until the current level
+// becomes less or equal to the column. For each indentation level, append
+// the BLOCK-END token.
+func yaml_parser_unroll_indent(parser *yaml_parser_t, column int) bool {
+ // In the flow context, do nothing.
+ if parser.flow_level > 0 {
+ return true
+ }
+
+ // Loop through the indentation levels in the stack.
+ for parser.indent > column {
+ // Create a token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_BLOCK_END_TOKEN,
+ start_mark: parser.mark,
+ end_mark: parser.mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+
+ // Pop the indentation level.
+ parser.indent = parser.indents[len(parser.indents)-1]
+ parser.indents = parser.indents[:len(parser.indents)-1]
+ }
+ return true
+}
+
+// Initialize the scanner and produce the STREAM-START token.
+func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool {
+
+ // Set the initial indentation.
+ parser.indent = -1
+
+ // Initialize the simple key stack.
+ parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{})
+
+ // A simple key is allowed at the beginning of the stream.
+ parser.simple_key_allowed = true
+
+ // We have started.
+ parser.stream_start_produced = true
+
+ // Create the STREAM-START token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_STREAM_START_TOKEN,
+ start_mark: parser.mark,
+ end_mark: parser.mark,
+ encoding: parser.encoding,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the STREAM-END token and shut down the scanner.
+func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool {
+
+ // Force new line.
+ if parser.mark.column != 0 {
+ parser.mark.column = 0
+ parser.mark.line++
+ }
+
+ // Reset the indentation level.
+ if !yaml_parser_unroll_indent(parser, -1) {
+ return false
+ }
+
+ // Reset simple keys.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ parser.simple_key_allowed = false
+
+ // Create the STREAM-END token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_STREAM_END_TOKEN,
+ start_mark: parser.mark,
+ end_mark: parser.mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token.
+func yaml_parser_fetch_directive(parser *yaml_parser_t) bool {
+ // Reset the indentation level.
+ if !yaml_parser_unroll_indent(parser, -1) {
+ return false
+ }
+
+ // Reset simple keys.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ parser.simple_key_allowed = false
+
+ // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token.
+ token := yaml_token_t{}
+ if !yaml_parser_scan_directive(parser, &token) {
+ return false
+ }
+ // Append the token to the queue.
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the DOCUMENT-START or DOCUMENT-END token.
+func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+ // Reset the indentation level.
+ if !yaml_parser_unroll_indent(parser, -1) {
+ return false
+ }
+
+ // Reset simple keys.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ parser.simple_key_allowed = false
+
+ // Consume the token.
+ start_mark := parser.mark
+
+ skip(parser)
+ skip(parser)
+ skip(parser)
+
+ end_mark := parser.mark
+
+ // Create the DOCUMENT-START or DOCUMENT-END token.
+ token := yaml_token_t{
+ typ: typ,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ // Append the token to the queue.
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
+func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+ // The indicators '[' and '{' may start a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // Increase the flow level.
+ if !yaml_parser_increase_flow_level(parser) {
+ return false
+ }
+
+ // A simple key may follow the indicators '[' and '{'.
+ parser.simple_key_allowed = true
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token.
+ token := yaml_token_t{
+ typ: typ,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ // Append the token to the queue.
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token.
+func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+ // Reset any potential simple key on the current flow level.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // Decrease the flow level.
+ if !yaml_parser_decrease_flow_level(parser) {
+ return false
+ }
+
+ // No simple keys after the indicators ']' and '}'.
+ parser.simple_key_allowed = false
+
+ // Consume the token.
+
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token.
+ token := yaml_token_t{
+ typ: typ,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ // Append the token to the queue.
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the FLOW-ENTRY token.
+func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool {
+ // Reset any potential simple keys on the current flow level.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // Simple keys are allowed after ','.
+ parser.simple_key_allowed = true
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the FLOW-ENTRY token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_FLOW_ENTRY_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the BLOCK-ENTRY token.
+func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool {
+ // Check if the scanner is in the block context.
+ if parser.flow_level == 0 {
+ // Check if we are allowed to start a new entry.
+ if !parser.simple_key_allowed {
+ return yaml_parser_set_scanner_error(parser, "", parser.mark,
+ "block sequence entries are not allowed in this context")
+ }
+ // Add the BLOCK-SEQUENCE-START token if needed.
+ if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) {
+ return false
+ }
+ } else {
+ // It is an error for the '-' indicator to occur in the flow context,
+ // but we let the Parser detect and report about it because the Parser
+ // is able to point to the context.
+ }
+
+ // Reset any potential simple keys on the current flow level.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // Simple keys are allowed after '-'.
+ parser.simple_key_allowed = true
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the BLOCK-ENTRY token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_BLOCK_ENTRY_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the KEY token.
+func yaml_parser_fetch_key(parser *yaml_parser_t) bool {
+
+ // In the block context, additional checks are required.
+ if parser.flow_level == 0 {
+ // Check if we are allowed to start a new key (not nessesary simple).
+ if !parser.simple_key_allowed {
+ return yaml_parser_set_scanner_error(parser, "", parser.mark,
+ "mapping keys are not allowed in this context")
+ }
+ // Add the BLOCK-MAPPING-START token if needed.
+ if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) {
+ return false
+ }
+ }
+
+ // Reset any potential simple keys on the current flow level.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // Simple keys are allowed after '?' in the block context.
+ parser.simple_key_allowed = parser.flow_level == 0
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the KEY token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_KEY_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the VALUE token.
+func yaml_parser_fetch_value(parser *yaml_parser_t) bool {
+
+ simple_key := &parser.simple_keys[len(parser.simple_keys)-1]
+
+ // Have we found a simple key?
+ if simple_key.possible {
+ // Create the KEY token and insert it into the queue.
+ token := yaml_token_t{
+ typ: yaml_KEY_TOKEN,
+ start_mark: simple_key.mark,
+ end_mark: simple_key.mark,
+ }
+ yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token)
+
+ // In the block context, we may need to add the BLOCK-MAPPING-START token.
+ if !yaml_parser_roll_indent(parser, simple_key.mark.column,
+ simple_key.token_number,
+ yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) {
+ return false
+ }
+
+ // Remove the simple key.
+ simple_key.possible = false
+
+ // A simple key cannot follow another simple key.
+ parser.simple_key_allowed = false
+
+ } else {
+ // The ':' indicator follows a complex key.
+
+ // In the block context, extra checks are required.
+ if parser.flow_level == 0 {
+
+ // Check if we are allowed to start a complex value.
+ if !parser.simple_key_allowed {
+ return yaml_parser_set_scanner_error(parser, "", parser.mark,
+ "mapping values are not allowed in this context")
+ }
+
+ // Add the BLOCK-MAPPING-START token if needed.
+ if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) {
+ return false
+ }
+ }
+
+ // Simple keys after ':' are allowed in the block context.
+ parser.simple_key_allowed = parser.flow_level == 0
+ }
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the VALUE token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_VALUE_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the ALIAS or ANCHOR token.
+func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+ // An anchor or an alias could be a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // A simple key cannot follow an anchor or an alias.
+ parser.simple_key_allowed = false
+
+ // Create the ALIAS or ANCHOR token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_anchor(parser, &token, typ) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the TAG token.
+func yaml_parser_fetch_tag(parser *yaml_parser_t) bool {
+ // A tag could be a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // A simple key cannot follow a tag.
+ parser.simple_key_allowed = false
+
+ // Create the TAG token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_tag(parser, &token) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens.
+func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool {
+ // Remove any potential simple keys.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // A simple key may follow a block scalar.
+ parser.simple_key_allowed = true
+
+ // Create the SCALAR token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_block_scalar(parser, &token, literal) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens.
+func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool {
+ // A plain scalar could be a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // A simple key cannot follow a flow scalar.
+ parser.simple_key_allowed = false
+
+ // Create the SCALAR token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_flow_scalar(parser, &token, single) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the SCALAR(...,plain) token.
+func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool {
+ // A plain scalar could be a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // A simple key cannot follow a flow scalar.
+ parser.simple_key_allowed = false
+
+ // Create the SCALAR token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_plain_scalar(parser, &token) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Eat whitespaces and comments until the next token is found.
+func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool {
+
+ // Until the next token is not found.
+ for {
+ // Allow the BOM mark to start a line.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ }
+
+ // Eat whitespaces.
+ // Tabs are allowed:
+ // - in the flow context
+ // - in the block context, but not at the beginning of the line or
+ // after '-', '?', or ':' (complex value).
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Eat a comment until a line break.
+ if parser.buffer[parser.buffer_pos] == '#' {
+ for !is_breakz(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+ }
+
+ // If it is a line break, eat it.
+ if is_break(parser.buffer, parser.buffer_pos) {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ skip_line(parser)
+
+ // In the block context, a new line may start a simple key.
+ if parser.flow_level == 0 {
+ parser.simple_key_allowed = true
+ }
+ } else {
+ break // We have found a token.
+ }
+ }
+
+ return true
+}
+
+// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
+//
+// Scope:
+// %YAML 1.1 # a comment \n
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// %TAG !yaml! tag:yaml.org,2002: \n
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool {
+ // Eat '%'.
+ start_mark := parser.mark
+ skip(parser)
+
+ // Scan the directive name.
+ var name []byte
+ if !yaml_parser_scan_directive_name(parser, start_mark, &name) {
+ return false
+ }
+
+ // Is it a YAML directive?
+ if bytes.Equal(name, []byte("YAML")) {
+ // Scan the VERSION directive value.
+ var major, minor int8
+ if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) {
+ return false
+ }
+ end_mark := parser.mark
+
+ // Create a VERSION-DIRECTIVE token.
+ *token = yaml_token_t{
+ typ: yaml_VERSION_DIRECTIVE_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ major: major,
+ minor: minor,
+ }
+
+ // Is it a TAG directive?
+ } else if bytes.Equal(name, []byte("TAG")) {
+ // Scan the TAG directive value.
+ var handle, prefix []byte
+ if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) {
+ return false
+ }
+ end_mark := parser.mark
+
+ // Create a TAG-DIRECTIVE token.
+ *token = yaml_token_t{
+ typ: yaml_TAG_DIRECTIVE_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: handle,
+ prefix: prefix,
+ }
+
+ // Unknown directive.
+ } else {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "found unknown directive name")
+ return false
+ }
+
+ // Eat the rest of the line including any comments.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ if parser.buffer[parser.buffer_pos] == '#' {
+ for !is_breakz(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+ }
+
+ // Check if we are at the end of the line.
+ if !is_breakz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "did not find expected comment or line break")
+ return false
+ }
+
+ // Eat a line break.
+ if is_break(parser.buffer, parser.buffer_pos) {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ skip_line(parser)
+ }
+
+ return true
+}
+
+// Scan the directive name.
+//
+// Scope:
+// %YAML 1.1 # a comment \n
+// ^^^^
+// %TAG !yaml! tag:yaml.org,2002: \n
+// ^^^
+//
+func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool {
+ // Consume the directive name.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ var s []byte
+ for is_alpha(parser.buffer, parser.buffer_pos) {
+ s = read(parser, s)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Check if the name is empty.
+ if len(s) == 0 {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "could not find expected directive name")
+ return false
+ }
+
+ // Check for an blank character after the name.
+ if !is_blankz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "found unexpected non-alphabetical character")
+ return false
+ }
+ *name = s
+ return true
+}
+
+// Scan the value of VERSION-DIRECTIVE.
+//
+// Scope:
+// %YAML 1.1 # a comment \n
+// ^^^^^^
+func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool {
+ // Eat whitespaces.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Consume the major version number.
+ if !yaml_parser_scan_version_directive_number(parser, start_mark, major) {
+ return false
+ }
+
+ // Eat '.'.
+ if parser.buffer[parser.buffer_pos] != '.' {
+ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+ start_mark, "did not find expected digit or '.' character")
+ }
+
+ skip(parser)
+
+ // Consume the minor version number.
+ if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) {
+ return false
+ }
+ return true
+}
+
+const max_number_length = 2
+
+// Scan the version number of VERSION-DIRECTIVE.
+//
+// Scope:
+// %YAML 1.1 # a comment \n
+// ^
+// %YAML 1.1 # a comment \n
+// ^
+func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool {
+
+ // Repeat while the next character is digit.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ var value, length int8
+ for is_digit(parser.buffer, parser.buffer_pos) {
+ // Check if the number is too long.
+ length++
+ if length > max_number_length {
+ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+ start_mark, "found extremely long version number")
+ }
+ value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos))
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Check if the number was present.
+ if length == 0 {
+ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+ start_mark, "did not find expected version number")
+ }
+ *number = value
+ return true
+}
+
+// Scan the value of a TAG-DIRECTIVE token.
+//
+// Scope:
+// %TAG !yaml! tag:yaml.org,2002: \n
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool {
+ var handle_value, prefix_value []byte
+
+ // Eat whitespaces.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Scan a handle.
+ if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) {
+ return false
+ }
+
+ // Expect a whitespace.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if !is_blank(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
+ start_mark, "did not find expected whitespace")
+ return false
+ }
+
+ // Eat whitespaces.
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Scan a prefix.
+ if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) {
+ return false
+ }
+
+ // Expect a whitespace or line break.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if !is_blankz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
+ start_mark, "did not find expected whitespace or line break")
+ return false
+ }
+
+ *handle = handle_value
+ *prefix = prefix_value
+ return true
+}
+
+func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool {
+ var s []byte
+
+ // Eat the indicator character.
+ start_mark := parser.mark
+ skip(parser)
+
+ // Consume the value.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for is_alpha(parser.buffer, parser.buffer_pos) {
+ s = read(parser, s)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ end_mark := parser.mark
+
+ /*
+ * Check if length of the anchor is greater than 0 and it is followed by
+ * a whitespace character or one of the indicators:
+ *
+ * '?', ':', ',', ']', '}', '%', '@', '`'.
+ */
+
+ if len(s) == 0 ||
+ !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' ||
+ parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' ||
+ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' ||
+ parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' ||
+ parser.buffer[parser.buffer_pos] == '`') {
+ context := "while scanning an alias"
+ if typ == yaml_ANCHOR_TOKEN {
+ context = "while scanning an anchor"
+ }
+ yaml_parser_set_scanner_error(parser, context, start_mark,
+ "did not find expected alphabetic or numeric character")
+ return false
+ }
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: typ,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: s,
+ }
+
+ return true
+}
+
+/*
+ * Scan a TAG token.
+ */
+
+func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool {
+ var handle, suffix []byte
+
+ start_mark := parser.mark
+
+ // Check if the tag is in the canonical form.
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+
+ if parser.buffer[parser.buffer_pos+1] == '<' {
+ // Keep the handle as ''
+
+ // Eat '!<'
+ skip(parser)
+ skip(parser)
+
+ // Consume the tag value.
+ if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) {
+ return false
+ }
+
+ // Check for '>' and eat it.
+ if parser.buffer[parser.buffer_pos] != '>' {
+ yaml_parser_set_scanner_error(parser, "while scanning a tag",
+ start_mark, "did not find the expected '>'")
+ return false
+ }
+
+ skip(parser)
+ } else {
+ // The tag has either the '!suffix' or the '!handle!suffix' form.
+
+ // First, try to scan a handle.
+ if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) {
+ return false
+ }
+
+ // Check if it is, indeed, handle.
+ if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' {
+ // Scan the suffix now.
+ if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) {
+ return false
+ }
+ } else {
+ // It wasn't a handle after all. Scan the rest of the tag.
+ if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) {
+ return false
+ }
+
+ // Set the handle to '!'.
+ handle = []byte{'!'}
+
+ // A special case: the '!' tag. Set the handle to '' and the
+ // suffix to '!'.
+ if len(suffix) == 0 {
+ handle, suffix = suffix, handle
+ }
+ }
+ }
+
+ // Check the character which ends the tag.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if !is_blankz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a tag",
+ start_mark, "did not find expected whitespace or line break")
+ return false
+ }
+
+ end_mark := parser.mark
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: yaml_TAG_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: handle,
+ suffix: suffix,
+ }
+ return true
+}
+
+// Scan a tag handle.
+func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool {
+ // Check the initial '!' character.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if parser.buffer[parser.buffer_pos] != '!' {
+ yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "did not find expected '!'")
+ return false
+ }
+
+ var s []byte
+
+ // Copy the '!' character.
+ s = read(parser, s)
+
+ // Copy all subsequent alphabetical and numerical characters.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ for is_alpha(parser.buffer, parser.buffer_pos) {
+ s = read(parser, s)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Check if the trailing character is '!' and copy it.
+ if parser.buffer[parser.buffer_pos] == '!' {
+ s = read(parser, s)
+ } else {
+ // It's either the '!' tag or not really a tag handle. If it's a %TAG
+ // directive, it's an error. If it's a tag token, it must be a part of URI.
+ if directive && string(s) != "!" {
+ yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "did not find expected '!'")
+ return false
+ }
+ }
+
+ *handle = s
+ return true
+}
+
+// Scan a tag.
+func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool {
+ //size_t length = head ? strlen((char *)head) : 0
+ var s []byte
+ hasTag := len(head) > 0
+
+ // Copy the head if needed.
+ //
+ // Note that we don't copy the leading '!' character.
+ if len(head) > 1 {
+ s = append(s, head[1:]...)
+ }
+
+ // Scan the tag.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ // The set of characters that may appear in URI is as follows:
+ //
+ // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&',
+ // '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']',
+ // '%'.
+ // [Go] Convert this into more reasonable logic.
+ for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' ||
+ parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' ||
+ parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' ||
+ parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' ||
+ parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' ||
+ parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' ||
+ parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' ||
+ parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' ||
+ parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' ||
+ parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' ||
+ parser.buffer[parser.buffer_pos] == '%' {
+ // Check if it is a URI-escape sequence.
+ if parser.buffer[parser.buffer_pos] == '%' {
+ if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) {
+ return false
+ }
+ } else {
+ s = read(parser, s)
+ }
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ hasTag = true
+ }
+
+ if !hasTag {
+ yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "did not find expected tag URI")
+ return false
+ }
+ *uri = s
+ return true
+}
+
+// Decode an URI-escape sequence corresponding to a single UTF-8 character.
+func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool {
+
+ // Decode the required number of characters.
+ w := 1024
+ for w > 0 {
+ // Check for a URI-escaped octet.
+ if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) {
+ return false
+ }
+
+ if !(parser.buffer[parser.buffer_pos] == '%' &&
+ is_hex(parser.buffer, parser.buffer_pos+1) &&
+ is_hex(parser.buffer, parser.buffer_pos+2)) {
+ return yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "did not find URI escaped octet")
+ }
+
+ // Get the octet.
+ octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2))
+
+ // If it is the leading octet, determine the length of the UTF-8 sequence.
+ if w == 1024 {
+ w = width(octet)
+ if w == 0 {
+ return yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "found an incorrect leading UTF-8 octet")
+ }
+ } else {
+ // Check if the trailing octet is correct.
+ if octet&0xC0 != 0x80 {
+ return yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "found an incorrect trailing UTF-8 octet")
+ }
+ }
+
+ // Copy the octet and move the pointers.
+ *s = append(*s, octet)
+ skip(parser)
+ skip(parser)
+ skip(parser)
+ w--
+ }
+ return true
+}
+
+// Scan a block scalar.
+func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool {
+ // Eat the indicator '|' or '>'.
+ start_mark := parser.mark
+ skip(parser)
+
+ // Scan the additional block scalar indicators.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ // Check for a chomping indicator.
+ var chomping, increment int
+ if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {
+ // Set the chomping method and eat the indicator.
+ if parser.buffer[parser.buffer_pos] == '+' {
+ chomping = +1
+ } else {
+ chomping = -1
+ }
+ skip(parser)
+
+ // Check for an indentation indicator.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if is_digit(parser.buffer, parser.buffer_pos) {
+ // Check that the indentation is greater than 0.
+ if parser.buffer[parser.buffer_pos] == '0' {
+ yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "found an indentation indicator equal to 0")
+ return false
+ }
+
+ // Get the indentation level and eat the indicator.
+ increment = as_digit(parser.buffer, parser.buffer_pos)
+ skip(parser)
+ }
+
+ } else if is_digit(parser.buffer, parser.buffer_pos) {
+ // Do the same as above, but in the opposite order.
+
+ if parser.buffer[parser.buffer_pos] == '0' {
+ yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "found an indentation indicator equal to 0")
+ return false
+ }
+ increment = as_digit(parser.buffer, parser.buffer_pos)
+ skip(parser)
+
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {
+ if parser.buffer[parser.buffer_pos] == '+' {
+ chomping = +1
+ } else {
+ chomping = -1
+ }
+ skip(parser)
+ }
+ }
+
+ // Eat whitespaces and comments to the end of the line.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+ if parser.buffer[parser.buffer_pos] == '#' {
+ for !is_breakz(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+ }
+
+ // Check if we are at the end of the line.
+ if !is_breakz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "did not find expected comment or line break")
+ return false
+ }
+
+ // Eat a line break.
+ if is_break(parser.buffer, parser.buffer_pos) {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ skip_line(parser)
+ }
+
+ end_mark := parser.mark
+
+ // Set the indentation level if it was specified.
+ var indent int
+ if increment > 0 {
+ if parser.indent >= 0 {
+ indent = parser.indent + increment
+ } else {
+ indent = increment
+ }
+ }
+
+ // Scan the leading line breaks and determine the indentation level if needed.
+ var s, leading_break, trailing_breaks []byte
+ if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) {
+ return false
+ }
+
+ // Scan the block scalar content.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ var leading_blank, trailing_blank bool
+ for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) {
+ // We are at the beginning of a non-empty line.
+
+ // Is it a trailing whitespace?
+ trailing_blank = is_blank(parser.buffer, parser.buffer_pos)
+
+ // Check if we need to fold the leading line break.
+ if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' {
+ // Do we need to join the lines by space?
+ if len(trailing_breaks) == 0 {
+ s = append(s, ' ')
+ }
+ } else {
+ s = append(s, leading_break...)
+ }
+ leading_break = leading_break[:0]
+
+ // Append the remaining line breaks.
+ s = append(s, trailing_breaks...)
+ trailing_breaks = trailing_breaks[:0]
+
+ // Is it a leading whitespace?
+ leading_blank = is_blank(parser.buffer, parser.buffer_pos)
+
+ // Consume the current line.
+ for !is_breakz(parser.buffer, parser.buffer_pos) {
+ s = read(parser, s)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Consume the line break.
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+
+ leading_break = read_line(parser, leading_break)
+
+ // Eat the following indentation spaces and line breaks.
+ if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) {
+ return false
+ }
+ }
+
+ // Chomp the tail.
+ if chomping != -1 {
+ s = append(s, leading_break...)
+ }
+ if chomping == 1 {
+ s = append(s, trailing_breaks...)
+ }
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: yaml_SCALAR_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: s,
+ style: yaml_LITERAL_SCALAR_STYLE,
+ }
+ if !literal {
+ token.style = yaml_FOLDED_SCALAR_STYLE
+ }
+ return true
+}
+
+// Scan indentation spaces and line breaks for a block scalar. Determine the
+// indentation level if needed.
+func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool {
+ *end_mark = parser.mark
+
+ // Eat the indentation spaces and line breaks.
+ max_indent := 0
+ for {
+ // Eat the indentation spaces.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+ if parser.mark.column > max_indent {
+ max_indent = parser.mark.column
+ }
+
+ // Check for a tab character messing the indentation.
+ if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) {
+ return yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "found a tab character where an indentation space is expected")
+ }
+
+ // Have we found a non-empty line?
+ if !is_break(parser.buffer, parser.buffer_pos) {
+ break
+ }
+
+ // Consume the line break.
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ // [Go] Should really be returning breaks instead.
+ *breaks = read_line(parser, *breaks)
+ *end_mark = parser.mark
+ }
+
+ // Determine the indentation level if needed.
+ if *indent == 0 {
+ *indent = max_indent
+ if *indent < parser.indent+1 {
+ *indent = parser.indent + 1
+ }
+ if *indent < 1 {
+ *indent = 1
+ }
+ }
+ return true
+}
+
+// Scan a quoted scalar.
+func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool {
+ // Eat the left quote.
+ start_mark := parser.mark
+ skip(parser)
+
+ // Consume the content of the quoted scalar.
+ var s, leading_break, trailing_breaks, whitespaces []byte
+ for {
+ // Check that there are no document indicators at the beginning of the line.
+ if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
+ return false
+ }
+
+ if parser.mark.column == 0 &&
+ ((parser.buffer[parser.buffer_pos+0] == '-' &&
+ parser.buffer[parser.buffer_pos+1] == '-' &&
+ parser.buffer[parser.buffer_pos+2] == '-') ||
+ (parser.buffer[parser.buffer_pos+0] == '.' &&
+ parser.buffer[parser.buffer_pos+1] == '.' &&
+ parser.buffer[parser.buffer_pos+2] == '.')) &&
+ is_blankz(parser.buffer, parser.buffer_pos+3) {
+ yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
+ start_mark, "found unexpected document indicator")
+ return false
+ }
+
+ // Check for EOF.
+ if is_z(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
+ start_mark, "found unexpected end of stream")
+ return false
+ }
+
+ // Consume non-blank characters.
+ leading_blanks := false
+ for !is_blankz(parser.buffer, parser.buffer_pos) {
+ if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' {
+ // Is is an escaped single quote.
+ s = append(s, '\'')
+ skip(parser)
+ skip(parser)
+
+ } else if single && parser.buffer[parser.buffer_pos] == '\'' {
+ // It is a right single quote.
+ break
+ } else if !single && parser.buffer[parser.buffer_pos] == '"' {
+ // It is a right double quote.
+ break
+
+ } else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) {
+ // It is an escaped line break.
+ if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) {
+ return false
+ }
+ skip(parser)
+ skip_line(parser)
+ leading_blanks = true
+ break
+
+ } else if !single && parser.buffer[parser.buffer_pos] == '\\' {
+ // It is an escape sequence.
+ code_length := 0
+
+ // Check the escape character.
+ switch parser.buffer[parser.buffer_pos+1] {
+ case '0':
+ s = append(s, 0)
+ case 'a':
+ s = append(s, '\x07')
+ case 'b':
+ s = append(s, '\x08')
+ case 't', '\t':
+ s = append(s, '\x09')
+ case 'n':
+ s = append(s, '\x0A')
+ case 'v':
+ s = append(s, '\x0B')
+ case 'f':
+ s = append(s, '\x0C')
+ case 'r':
+ s = append(s, '\x0D')
+ case 'e':
+ s = append(s, '\x1B')
+ case ' ':
+ s = append(s, '\x20')
+ case '"':
+ s = append(s, '"')
+ case '\'':
+ s = append(s, '\'')
+ case '\\':
+ s = append(s, '\\')
+ case 'N': // NEL (#x85)
+ s = append(s, '\xC2')
+ s = append(s, '\x85')
+ case '_': // #xA0
+ s = append(s, '\xC2')
+ s = append(s, '\xA0')
+ case 'L': // LS (#x2028)
+ s = append(s, '\xE2')
+ s = append(s, '\x80')
+ s = append(s, '\xA8')
+ case 'P': // PS (#x2029)
+ s = append(s, '\xE2')
+ s = append(s, '\x80')
+ s = append(s, '\xA9')
+ case 'x':
+ code_length = 2
+ case 'u':
+ code_length = 4
+ case 'U':
+ code_length = 8
+ default:
+ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+ start_mark, "found unknown escape character")
+ return false
+ }
+
+ skip(parser)
+ skip(parser)
+
+ // Consume an arbitrary escape code.
+ if code_length > 0 {
+ var value int
+
+ // Scan the character value.
+ if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) {
+ return false
+ }
+ for k := 0; k < code_length; k++ {
+ if !is_hex(parser.buffer, parser.buffer_pos+k) {
+ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+ start_mark, "did not find expected hexdecimal number")
+ return false
+ }
+ value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k)
+ }
+
+ // Check the value and write the character.
+ if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF {
+ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+ start_mark, "found invalid Unicode character escape code")
+ return false
+ }
+ if value <= 0x7F {
+ s = append(s, byte(value))
+ } else if value <= 0x7FF {
+ s = append(s, byte(0xC0+(value>>6)))
+ s = append(s, byte(0x80+(value&0x3F)))
+ } else if value <= 0xFFFF {
+ s = append(s, byte(0xE0+(value>>12)))
+ s = append(s, byte(0x80+((value>>6)&0x3F)))
+ s = append(s, byte(0x80+(value&0x3F)))
+ } else {
+ s = append(s, byte(0xF0+(value>>18)))
+ s = append(s, byte(0x80+((value>>12)&0x3F)))
+ s = append(s, byte(0x80+((value>>6)&0x3F)))
+ s = append(s, byte(0x80+(value&0x3F)))
+ }
+
+ // Advance the pointer.
+ for k := 0; k < code_length; k++ {
+ skip(parser)
+ }
+ }
+ } else {
+ // It is a non-escaped non-blank character.
+ s = read(parser, s)
+ }
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ }
+
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ // Check if we are at the end of the scalar.
+ if single {
+ if parser.buffer[parser.buffer_pos] == '\'' {
+ break
+ }
+ } else {
+ if parser.buffer[parser.buffer_pos] == '"' {
+ break
+ }
+ }
+
+ // Consume blank characters.
+ for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
+ if is_blank(parser.buffer, parser.buffer_pos) {
+ // Consume a space or a tab character.
+ if !leading_blanks {
+ whitespaces = read(parser, whitespaces)
+ } else {
+ skip(parser)
+ }
+ } else {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+
+ // Check if it is a first line break.
+ if !leading_blanks {
+ whitespaces = whitespaces[:0]
+ leading_break = read_line(parser, leading_break)
+ leading_blanks = true
+ } else {
+ trailing_breaks = read_line(parser, trailing_breaks)
+ }
+ }
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Join the whitespaces or fold line breaks.
+ if leading_blanks {
+ // Do we need to fold line breaks?
+ if len(leading_break) > 0 && leading_break[0] == '\n' {
+ if len(trailing_breaks) == 0 {
+ s = append(s, ' ')
+ } else {
+ s = append(s, trailing_breaks...)
+ }
+ } else {
+ s = append(s, leading_break...)
+ s = append(s, trailing_breaks...)
+ }
+ trailing_breaks = trailing_breaks[:0]
+ leading_break = leading_break[:0]
+ } else {
+ s = append(s, whitespaces...)
+ whitespaces = whitespaces[:0]
+ }
+ }
+
+ // Eat the right quote.
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: yaml_SCALAR_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: s,
+ style: yaml_SINGLE_QUOTED_SCALAR_STYLE,
+ }
+ if !single {
+ token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ return true
+}
+
+// Scan a plain scalar.
+func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool {
+
+ var s, leading_break, trailing_breaks, whitespaces []byte
+ var leading_blanks bool
+ var indent = parser.indent + 1
+
+ start_mark := parser.mark
+ end_mark := parser.mark
+
+ // Consume the content of the plain scalar.
+ for {
+ // Check for a document indicator.
+ if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
+ return false
+ }
+ if parser.mark.column == 0 &&
+ ((parser.buffer[parser.buffer_pos+0] == '-' &&
+ parser.buffer[parser.buffer_pos+1] == '-' &&
+ parser.buffer[parser.buffer_pos+2] == '-') ||
+ (parser.buffer[parser.buffer_pos+0] == '.' &&
+ parser.buffer[parser.buffer_pos+1] == '.' &&
+ parser.buffer[parser.buffer_pos+2] == '.')) &&
+ is_blankz(parser.buffer, parser.buffer_pos+3) {
+ break
+ }
+
+ // Check for a comment.
+ if parser.buffer[parser.buffer_pos] == '#' {
+ break
+ }
+
+ // Consume non-blank characters.
+ for !is_blankz(parser.buffer, parser.buffer_pos) {
+
+ // Check for indicators that may end a plain scalar.
+ if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) ||
+ (parser.flow_level > 0 &&
+ (parser.buffer[parser.buffer_pos] == ',' ||
+ parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' ||
+ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
+ parser.buffer[parser.buffer_pos] == '}')) {
+ break
+ }
+
+ // Check if we need to join whitespaces and breaks.
+ if leading_blanks || len(whitespaces) > 0 {
+ if leading_blanks {
+ // Do we need to fold line breaks?
+ if leading_break[0] == '\n' {
+ if len(trailing_breaks) == 0 {
+ s = append(s, ' ')
+ } else {
+ s = append(s, trailing_breaks...)
+ }
+ } else {
+ s = append(s, leading_break...)
+ s = append(s, trailing_breaks...)
+ }
+ trailing_breaks = trailing_breaks[:0]
+ leading_break = leading_break[:0]
+ leading_blanks = false
+ } else {
+ s = append(s, whitespaces...)
+ whitespaces = whitespaces[:0]
+ }
+ }
+
+ // Copy the character.
+ s = read(parser, s)
+
+ end_mark = parser.mark
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ }
+
+ // Is it the end?
+ if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) {
+ break
+ }
+
+ // Consume blank characters.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
+ if is_blank(parser.buffer, parser.buffer_pos) {
+
+ // Check for tab characters that abuse indentation.
+ if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
+ start_mark, "found a tab character that violates indentation")
+ return false
+ }
+
+ // Consume a space or a tab character.
+ if !leading_blanks {
+ whitespaces = read(parser, whitespaces)
+ } else {
+ skip(parser)
+ }
+ } else {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+
+ // Check if it is a first line break.
+ if !leading_blanks {
+ whitespaces = whitespaces[:0]
+ leading_break = read_line(parser, leading_break)
+ leading_blanks = true
+ } else {
+ trailing_breaks = read_line(parser, trailing_breaks)
+ }
+ }
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Check indentation level.
+ if parser.flow_level == 0 && parser.mark.column < indent {
+ break
+ }
+ }
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: yaml_SCALAR_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: s,
+ style: yaml_PLAIN_SCALAR_STYLE,
+ }
+
+ // Note that we change the 'simple_key_allowed' flag.
+ if leading_blanks {
+ parser.simple_key_allowed = true
+ }
+ return true
+}
--- /dev/null
+package yaml
+
+import (
+ "reflect"
+ "unicode"
+)
+
+type keyList []reflect.Value
+
+func (l keyList) Len() int { return len(l) }
+func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
+func (l keyList) Less(i, j int) bool {
+ a := l[i]
+ b := l[j]
+ ak := a.Kind()
+ bk := b.Kind()
+ for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() {
+ a = a.Elem()
+ ak = a.Kind()
+ }
+ for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() {
+ b = b.Elem()
+ bk = b.Kind()
+ }
+ af, aok := keyFloat(a)
+ bf, bok := keyFloat(b)
+ if aok && bok {
+ if af != bf {
+ return af < bf
+ }
+ if ak != bk {
+ return ak < bk
+ }
+ return numLess(a, b)
+ }
+ if ak != reflect.String || bk != reflect.String {
+ return ak < bk
+ }
+ ar, br := []rune(a.String()), []rune(b.String())
+ for i := 0; i < len(ar) && i < len(br); i++ {
+ if ar[i] == br[i] {
+ continue
+ }
+ al := unicode.IsLetter(ar[i])
+ bl := unicode.IsLetter(br[i])
+ if al && bl {
+ return ar[i] < br[i]
+ }
+ if al || bl {
+ return bl
+ }
+ var ai, bi int
+ var an, bn int64
+ if ar[i] == '0' || br[i] == '0' {
+ for j := i-1; j >= 0 && unicode.IsDigit(ar[j]); j-- {
+ if ar[j] != '0' {
+ an = 1
+ bn = 1
+ break
+ }
+ }
+ }
+ for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
+ an = an*10 + int64(ar[ai]-'0')
+ }
+ for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ {
+ bn = bn*10 + int64(br[bi]-'0')
+ }
+ if an != bn {
+ return an < bn
+ }
+ if ai != bi {
+ return ai < bi
+ }
+ return ar[i] < br[i]
+ }
+ return len(ar) < len(br)
+}
+
+// keyFloat returns a float value for v if it is a number/bool
+// and whether it is a number/bool or not.
+func keyFloat(v reflect.Value) (f float64, ok bool) {
+ switch v.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return float64(v.Int()), true
+ case reflect.Float32, reflect.Float64:
+ return v.Float(), true
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return float64(v.Uint()), true
+ case reflect.Bool:
+ if v.Bool() {
+ return 1, true
+ }
+ return 0, true
+ }
+ return 0, false
+}
+
+// numLess returns whether a < b.
+// a and b must necessarily have the same kind.
+func numLess(a, b reflect.Value) bool {
+ switch a.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return a.Int() < b.Int()
+ case reflect.Float32, reflect.Float64:
+ return a.Float() < b.Float()
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return a.Uint() < b.Uint()
+ case reflect.Bool:
+ return !a.Bool() && b.Bool()
+ }
+ panic("not a number")
+}
--- /dev/null
+package yaml
+
+// Set the writer error and return false.
+func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool {
+ emitter.error = yaml_WRITER_ERROR
+ emitter.problem = problem
+ return false
+}
+
+// Flush the output buffer.
+func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
+ if emitter.write_handler == nil {
+ panic("write handler not set")
+ }
+
+ // Check if the buffer is empty.
+ if emitter.buffer_pos == 0 {
+ return true
+ }
+
+ if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
+ return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
+ }
+ emitter.buffer_pos = 0
+ return true
+}
--- /dev/null
+// Package yaml implements YAML support for the Go language.
+//
+// Source code and other details for the project are available at GitHub:
+//
+// https://github.com/go-yaml/yaml
+//
+package yaml
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "reflect"
+ "strings"
+ "sync"
+)
+
+// MapSlice encodes and decodes as a YAML map.
+// The order of keys is preserved when encoding and decoding.
+type MapSlice []MapItem
+
+// MapItem is an item in a MapSlice.
+type MapItem struct {
+ Key, Value interface{}
+}
+
+// The Unmarshaler interface may be implemented by types to customize their
+// behavior when being unmarshaled from a YAML document. The UnmarshalYAML
+// method receives a function that may be called to unmarshal the original
+// YAML value into a field or variable. It is safe to call the unmarshal
+// function parameter more than once if necessary.
+type Unmarshaler interface {
+ UnmarshalYAML(unmarshal func(interface{}) error) error
+}
+
+// The Marshaler interface may be implemented by types to customize their
+// behavior when being marshaled into a YAML document. The returned value
+// is marshaled in place of the original value implementing Marshaler.
+//
+// If an error is returned by MarshalYAML, the marshaling procedure stops
+// and returns with the provided error.
+type Marshaler interface {
+ MarshalYAML() (interface{}, error)
+}
+
+// Unmarshal decodes the first document found within the in byte slice
+// and assigns decoded values into the out value.
+//
+// Maps and pointers (to a struct, string, int, etc) are accepted as out
+// values. If an internal pointer within a struct is not initialized,
+// the yaml package will initialize it if necessary for unmarshalling
+// the provided data. The out parameter must not be nil.
+//
+// The type of the decoded values should be compatible with the respective
+// values in out. If one or more values cannot be decoded due to a type
+// mismatches, decoding continues partially until the end of the YAML
+// content, and a *yaml.TypeError is returned with details for all
+// missed values.
+//
+// Struct fields are only unmarshalled if they are exported (have an
+// upper case first letter), and are unmarshalled using the field name
+// lowercased as the default key. Custom keys may be defined via the
+// "yaml" name in the field tag: the content preceding the first comma
+// is used as the key, and the following comma-separated options are
+// used to tweak the marshalling process (see Marshal).
+// Conflicting names result in a runtime error.
+//
+// For example:
+//
+// type T struct {
+// F int `yaml:"a,omitempty"`
+// B int
+// }
+// var t T
+// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
+//
+// See the documentation of Marshal for the format of tags and a list of
+// supported tag options.
+//
+func Unmarshal(in []byte, out interface{}) (err error) {
+ return unmarshal(in, out, false)
+}
+
+// UnmarshalStrict is like Unmarshal except that any fields that are found
+// in the data that do not have corresponding struct members, or mapping
+// keys that are duplicates, will result in
+// an error.
+func UnmarshalStrict(in []byte, out interface{}) (err error) {
+ return unmarshal(in, out, true)
+}
+
+// A Decorder reads and decodes YAML values from an input stream.
+type Decoder struct {
+ strict bool
+ parser *parser
+}
+
+// NewDecoder returns a new decoder that reads from r.
+//
+// The decoder introduces its own buffering and may read
+// data from r beyond the YAML values requested.
+func NewDecoder(r io.Reader) *Decoder {
+ return &Decoder{
+ parser: newParserFromReader(r),
+ }
+}
+
+// SetStrict sets whether strict decoding behaviour is enabled when
+// decoding items in the data (see UnmarshalStrict). By default, decoding is not strict.
+func (dec *Decoder) SetStrict(strict bool) {
+ dec.strict = strict
+}
+
+// Decode reads the next YAML-encoded value from its input
+// and stores it in the value pointed to by v.
+//
+// See the documentation for Unmarshal for details about the
+// conversion of YAML into a Go value.
+func (dec *Decoder) Decode(v interface{}) (err error) {
+ d := newDecoder(dec.strict)
+ defer handleErr(&err)
+ node := dec.parser.parse()
+ if node == nil {
+ return io.EOF
+ }
+ out := reflect.ValueOf(v)
+ if out.Kind() == reflect.Ptr && !out.IsNil() {
+ out = out.Elem()
+ }
+ d.unmarshal(node, out)
+ if len(d.terrors) > 0 {
+ return &TypeError{d.terrors}
+ }
+ return nil
+}
+
+func unmarshal(in []byte, out interface{}, strict bool) (err error) {
+ defer handleErr(&err)
+ d := newDecoder(strict)
+ p := newParser(in)
+ defer p.destroy()
+ node := p.parse()
+ if node != nil {
+ v := reflect.ValueOf(out)
+ if v.Kind() == reflect.Ptr && !v.IsNil() {
+ v = v.Elem()
+ }
+ d.unmarshal(node, v)
+ }
+ if len(d.terrors) > 0 {
+ return &TypeError{d.terrors}
+ }
+ return nil
+}
+
+// Marshal serializes the value provided into a YAML document. The structure
+// of the generated document will reflect the structure of the value itself.
+// Maps and pointers (to struct, string, int, etc) are accepted as the in value.
+//
+// Struct fields are only marshalled if they are exported (have an upper case
+// first letter), and are marshalled using the field name lowercased as the
+// default key. Custom keys may be defined via the "yaml" name in the field
+// tag: the content preceding the first comma is used as the key, and the
+// following comma-separated options are used to tweak the marshalling process.
+// Conflicting names result in a runtime error.
+//
+// The field tag format accepted is:
+//
+// `(...) yaml:"[<key>][,<flag1>[,<flag2>]]" (...)`
+//
+// The following flags are currently supported:
+//
+// omitempty Only include the field if it's not set to the zero
+// value for the type or to empty slices or maps.
+// Zero valued structs will be omitted if all their public
+// fields are zero, unless they implement an IsZero
+// method (see the IsZeroer interface type), in which
+// case the field will be included if that method returns true.
+//
+// flow Marshal using a flow style (useful for structs,
+// sequences and maps).
+//
+// inline Inline the field, which must be a struct or a map,
+// causing all of its fields or keys to be processed as if
+// they were part of the outer struct. For maps, keys must
+// not conflict with the yaml keys of other struct fields.
+//
+// In addition, if the key is "-", the field is ignored.
+//
+// For example:
+//
+// type T struct {
+// F int `yaml:"a,omitempty"`
+// B int
+// }
+// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
+// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
+//
+func Marshal(in interface{}) (out []byte, err error) {
+ defer handleErr(&err)
+ e := newEncoder()
+ defer e.destroy()
+ e.marshalDoc("", reflect.ValueOf(in))
+ e.finish()
+ out = e.out
+ return
+}
+
+// An Encoder writes YAML values to an output stream.
+type Encoder struct {
+ encoder *encoder
+}
+
+// NewEncoder returns a new encoder that writes to w.
+// The Encoder should be closed after use to flush all data
+// to w.
+func NewEncoder(w io.Writer) *Encoder {
+ return &Encoder{
+ encoder: newEncoderWithWriter(w),
+ }
+}
+
+// Encode writes the YAML encoding of v to the stream.
+// If multiple items are encoded to the stream, the
+// second and subsequent document will be preceded
+// with a "---" document separator, but the first will not.
+//
+// See the documentation for Marshal for details about the conversion of Go
+// values to YAML.
+func (e *Encoder) Encode(v interface{}) (err error) {
+ defer handleErr(&err)
+ e.encoder.marshalDoc("", reflect.ValueOf(v))
+ return nil
+}
+
+// Close closes the encoder by writing any remaining data.
+// It does not write a stream terminating string "...".
+func (e *Encoder) Close() (err error) {
+ defer handleErr(&err)
+ e.encoder.finish()
+ return nil
+}
+
+func handleErr(err *error) {
+ if v := recover(); v != nil {
+ if e, ok := v.(yamlError); ok {
+ *err = e.err
+ } else {
+ panic(v)
+ }
+ }
+}
+
+type yamlError struct {
+ err error
+}
+
+func fail(err error) {
+ panic(yamlError{err})
+}
+
+func failf(format string, args ...interface{}) {
+ panic(yamlError{fmt.Errorf("yaml: "+format, args...)})
+}
+
+// A TypeError is returned by Unmarshal when one or more fields in
+// the YAML document cannot be properly decoded into the requested
+// types. When this error is returned, the value is still
+// unmarshaled partially.
+type TypeError struct {
+ Errors []string
+}
+
+func (e *TypeError) Error() string {
+ return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n "))
+}
+
+// --------------------------------------------------------------------------
+// Maintain a mapping of keys to structure field indexes
+
+// The code in this section was copied from mgo/bson.
+
+// structInfo holds details for the serialization of fields of
+// a given struct.
+type structInfo struct {
+ FieldsMap map[string]fieldInfo
+ FieldsList []fieldInfo
+
+ // InlineMap is the number of the field in the struct that
+ // contains an ,inline map, or -1 if there's none.
+ InlineMap int
+}
+
+type fieldInfo struct {
+ Key string
+ Num int
+ OmitEmpty bool
+ Flow bool
+ // Id holds the unique field identifier, so we can cheaply
+ // check for field duplicates without maintaining an extra map.
+ Id int
+
+ // Inline holds the field index if the field is part of an inlined struct.
+ Inline []int
+}
+
+var structMap = make(map[reflect.Type]*structInfo)
+var fieldMapMutex sync.RWMutex
+
+func getStructInfo(st reflect.Type) (*structInfo, error) {
+ fieldMapMutex.RLock()
+ sinfo, found := structMap[st]
+ fieldMapMutex.RUnlock()
+ if found {
+ return sinfo, nil
+ }
+
+ n := st.NumField()
+ fieldsMap := make(map[string]fieldInfo)
+ fieldsList := make([]fieldInfo, 0, n)
+ inlineMap := -1
+ for i := 0; i != n; i++ {
+ field := st.Field(i)
+ if field.PkgPath != "" && !field.Anonymous {
+ continue // Private field
+ }
+
+ info := fieldInfo{Num: i}
+
+ tag := field.Tag.Get("yaml")
+ if tag == "" && strings.Index(string(field.Tag), ":") < 0 {
+ tag = string(field.Tag)
+ }
+ if tag == "-" {
+ continue
+ }
+
+ inline := false
+ fields := strings.Split(tag, ",")
+ if len(fields) > 1 {
+ for _, flag := range fields[1:] {
+ switch flag {
+ case "omitempty":
+ info.OmitEmpty = true
+ case "flow":
+ info.Flow = true
+ case "inline":
+ inline = true
+ default:
+ return nil, errors.New(fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st))
+ }
+ }
+ tag = fields[0]
+ }
+
+ if inline {
+ switch field.Type.Kind() {
+ case reflect.Map:
+ if inlineMap >= 0 {
+ return nil, errors.New("Multiple ,inline maps in struct " + st.String())
+ }
+ if field.Type.Key() != reflect.TypeOf("") {
+ return nil, errors.New("Option ,inline needs a map with string keys in struct " + st.String())
+ }
+ inlineMap = info.Num
+ case reflect.Struct:
+ sinfo, err := getStructInfo(field.Type)
+ if err != nil {
+ return nil, err
+ }
+ for _, finfo := range sinfo.FieldsList {
+ if _, found := fieldsMap[finfo.Key]; found {
+ msg := "Duplicated key '" + finfo.Key + "' in struct " + st.String()
+ return nil, errors.New(msg)
+ }
+ if finfo.Inline == nil {
+ finfo.Inline = []int{i, finfo.Num}
+ } else {
+ finfo.Inline = append([]int{i}, finfo.Inline...)
+ }
+ finfo.Id = len(fieldsList)
+ fieldsMap[finfo.Key] = finfo
+ fieldsList = append(fieldsList, finfo)
+ }
+ default:
+ //return nil, errors.New("Option ,inline needs a struct value or map field")
+ return nil, errors.New("Option ,inline needs a struct value field")
+ }
+ continue
+ }
+
+ if tag != "" {
+ info.Key = tag
+ } else {
+ info.Key = strings.ToLower(field.Name)
+ }
+
+ if _, found = fieldsMap[info.Key]; found {
+ msg := "Duplicated key '" + info.Key + "' in struct " + st.String()
+ return nil, errors.New(msg)
+ }
+
+ info.Id = len(fieldsList)
+ fieldsList = append(fieldsList, info)
+ fieldsMap[info.Key] = info
+ }
+
+ sinfo = &structInfo{
+ FieldsMap: fieldsMap,
+ FieldsList: fieldsList,
+ InlineMap: inlineMap,
+ }
+
+ fieldMapMutex.Lock()
+ structMap[st] = sinfo
+ fieldMapMutex.Unlock()
+ return sinfo, nil
+}
+
+// IsZeroer is used to check whether an object is zero to
+// determine whether it should be omitted when marshaling
+// with the omitempty flag. One notable implementation
+// is time.Time.
+type IsZeroer interface {
+ IsZero() bool
+}
+
+func isZero(v reflect.Value) bool {
+ kind := v.Kind()
+ if z, ok := v.Interface().(IsZeroer); ok {
+ if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() {
+ return true
+ }
+ return z.IsZero()
+ }
+ switch kind {
+ case reflect.String:
+ return len(v.String()) == 0
+ case reflect.Interface, reflect.Ptr:
+ return v.IsNil()
+ case reflect.Slice:
+ return v.Len() == 0
+ case reflect.Map:
+ return v.Len() == 0
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return v.Uint() == 0
+ case reflect.Bool:
+ return !v.Bool()
+ case reflect.Struct:
+ vt := v.Type()
+ for i := v.NumField() - 1; i >= 0; i-- {
+ if vt.Field(i).PkgPath != "" {
+ continue // Private field
+ }
+ if !isZero(v.Field(i)) {
+ return false
+ }
+ }
+ return true
+ }
+ return false
+}
--- /dev/null
+package yaml
+
+import (
+ "fmt"
+ "io"
+)
+
+// The version directive data.
+type yaml_version_directive_t struct {
+ major int8 // The major version number.
+ minor int8 // The minor version number.
+}
+
+// The tag directive data.
+type yaml_tag_directive_t struct {
+ handle []byte // The tag handle.
+ prefix []byte // The tag prefix.
+}
+
+type yaml_encoding_t int
+
+// The stream encoding.
+const (
+ // Let the parser choose the encoding.
+ yaml_ANY_ENCODING yaml_encoding_t = iota
+
+ yaml_UTF8_ENCODING // The default UTF-8 encoding.
+ yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM.
+ yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM.
+)
+
+type yaml_break_t int
+
+// Line break types.
+const (
+ // Let the parser choose the break type.
+ yaml_ANY_BREAK yaml_break_t = iota
+
+ yaml_CR_BREAK // Use CR for line breaks (Mac style).
+ yaml_LN_BREAK // Use LN for line breaks (Unix style).
+ yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style).
+)
+
+type yaml_error_type_t int
+
+// Many bad things could happen with the parser and emitter.
+const (
+ // No error is produced.
+ yaml_NO_ERROR yaml_error_type_t = iota
+
+ yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory.
+ yaml_READER_ERROR // Cannot read or decode the input stream.
+ yaml_SCANNER_ERROR // Cannot scan the input stream.
+ yaml_PARSER_ERROR // Cannot parse the input stream.
+ yaml_COMPOSER_ERROR // Cannot compose a YAML document.
+ yaml_WRITER_ERROR // Cannot write to the output stream.
+ yaml_EMITTER_ERROR // Cannot emit a YAML stream.
+)
+
+// The pointer position.
+type yaml_mark_t struct {
+ index int // The position index.
+ line int // The position line.
+ column int // The position column.
+}
+
+// Node Styles
+
+type yaml_style_t int8
+
+type yaml_scalar_style_t yaml_style_t
+
+// Scalar styles.
+const (
+ // Let the emitter choose the style.
+ yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = iota
+
+ yaml_PLAIN_SCALAR_STYLE // The plain scalar style.
+ yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style.
+ yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style.
+ yaml_LITERAL_SCALAR_STYLE // The literal scalar style.
+ yaml_FOLDED_SCALAR_STYLE // The folded scalar style.
+)
+
+type yaml_sequence_style_t yaml_style_t
+
+// Sequence styles.
+const (
+ // Let the emitter choose the style.
+ yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota
+
+ yaml_BLOCK_SEQUENCE_STYLE // The block sequence style.
+ yaml_FLOW_SEQUENCE_STYLE // The flow sequence style.
+)
+
+type yaml_mapping_style_t yaml_style_t
+
+// Mapping styles.
+const (
+ // Let the emitter choose the style.
+ yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota
+
+ yaml_BLOCK_MAPPING_STYLE // The block mapping style.
+ yaml_FLOW_MAPPING_STYLE // The flow mapping style.
+)
+
+// Tokens
+
+type yaml_token_type_t int
+
+// Token types.
+const (
+ // An empty token.
+ yaml_NO_TOKEN yaml_token_type_t = iota
+
+ yaml_STREAM_START_TOKEN // A STREAM-START token.
+ yaml_STREAM_END_TOKEN // A STREAM-END token.
+
+ yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token.
+ yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token.
+ yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token.
+ yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token.
+
+ yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token.
+ yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token.
+ yaml_BLOCK_END_TOKEN // A BLOCK-END token.
+
+ yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token.
+ yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token.
+ yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token.
+ yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token.
+
+ yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token.
+ yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token.
+ yaml_KEY_TOKEN // A KEY token.
+ yaml_VALUE_TOKEN // A VALUE token.
+
+ yaml_ALIAS_TOKEN // An ALIAS token.
+ yaml_ANCHOR_TOKEN // An ANCHOR token.
+ yaml_TAG_TOKEN // A TAG token.
+ yaml_SCALAR_TOKEN // A SCALAR token.
+)
+
+func (tt yaml_token_type_t) String() string {
+ switch tt {
+ case yaml_NO_TOKEN:
+ return "yaml_NO_TOKEN"
+ case yaml_STREAM_START_TOKEN:
+ return "yaml_STREAM_START_TOKEN"
+ case yaml_STREAM_END_TOKEN:
+ return "yaml_STREAM_END_TOKEN"
+ case yaml_VERSION_DIRECTIVE_TOKEN:
+ return "yaml_VERSION_DIRECTIVE_TOKEN"
+ case yaml_TAG_DIRECTIVE_TOKEN:
+ return "yaml_TAG_DIRECTIVE_TOKEN"
+ case yaml_DOCUMENT_START_TOKEN:
+ return "yaml_DOCUMENT_START_TOKEN"
+ case yaml_DOCUMENT_END_TOKEN:
+ return "yaml_DOCUMENT_END_TOKEN"
+ case yaml_BLOCK_SEQUENCE_START_TOKEN:
+ return "yaml_BLOCK_SEQUENCE_START_TOKEN"
+ case yaml_BLOCK_MAPPING_START_TOKEN:
+ return "yaml_BLOCK_MAPPING_START_TOKEN"
+ case yaml_BLOCK_END_TOKEN:
+ return "yaml_BLOCK_END_TOKEN"
+ case yaml_FLOW_SEQUENCE_START_TOKEN:
+ return "yaml_FLOW_SEQUENCE_START_TOKEN"
+ case yaml_FLOW_SEQUENCE_END_TOKEN:
+ return "yaml_FLOW_SEQUENCE_END_TOKEN"
+ case yaml_FLOW_MAPPING_START_TOKEN:
+ return "yaml_FLOW_MAPPING_START_TOKEN"
+ case yaml_FLOW_MAPPING_END_TOKEN:
+ return "yaml_FLOW_MAPPING_END_TOKEN"
+ case yaml_BLOCK_ENTRY_TOKEN:
+ return "yaml_BLOCK_ENTRY_TOKEN"
+ case yaml_FLOW_ENTRY_TOKEN:
+ return "yaml_FLOW_ENTRY_TOKEN"
+ case yaml_KEY_TOKEN:
+ return "yaml_KEY_TOKEN"
+ case yaml_VALUE_TOKEN:
+ return "yaml_VALUE_TOKEN"
+ case yaml_ALIAS_TOKEN:
+ return "yaml_ALIAS_TOKEN"
+ case yaml_ANCHOR_TOKEN:
+ return "yaml_ANCHOR_TOKEN"
+ case yaml_TAG_TOKEN:
+ return "yaml_TAG_TOKEN"
+ case yaml_SCALAR_TOKEN:
+ return "yaml_SCALAR_TOKEN"
+ }
+ return "<unknown token>"
+}
+
+// The token structure.
+type yaml_token_t struct {
+ // The token type.
+ typ yaml_token_type_t
+
+ // The start/end of the token.
+ start_mark, end_mark yaml_mark_t
+
+ // The stream encoding (for yaml_STREAM_START_TOKEN).
+ encoding yaml_encoding_t
+
+ // The alias/anchor/scalar value or tag/tag directive handle
+ // (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN).
+ value []byte
+
+ // The tag suffix (for yaml_TAG_TOKEN).
+ suffix []byte
+
+ // The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN).
+ prefix []byte
+
+ // The scalar style (for yaml_SCALAR_TOKEN).
+ style yaml_scalar_style_t
+
+ // The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN).
+ major, minor int8
+}
+
+// Events
+
+type yaml_event_type_t int8
+
+// Event types.
+const (
+ // An empty event.
+ yaml_NO_EVENT yaml_event_type_t = iota
+
+ yaml_STREAM_START_EVENT // A STREAM-START event.
+ yaml_STREAM_END_EVENT // A STREAM-END event.
+ yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event.
+ yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event.
+ yaml_ALIAS_EVENT // An ALIAS event.
+ yaml_SCALAR_EVENT // A SCALAR event.
+ yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event.
+ yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event.
+ yaml_MAPPING_START_EVENT // A MAPPING-START event.
+ yaml_MAPPING_END_EVENT // A MAPPING-END event.
+)
+
+var eventStrings = []string{
+ yaml_NO_EVENT: "none",
+ yaml_STREAM_START_EVENT: "stream start",
+ yaml_STREAM_END_EVENT: "stream end",
+ yaml_DOCUMENT_START_EVENT: "document start",
+ yaml_DOCUMENT_END_EVENT: "document end",
+ yaml_ALIAS_EVENT: "alias",
+ yaml_SCALAR_EVENT: "scalar",
+ yaml_SEQUENCE_START_EVENT: "sequence start",
+ yaml_SEQUENCE_END_EVENT: "sequence end",
+ yaml_MAPPING_START_EVENT: "mapping start",
+ yaml_MAPPING_END_EVENT: "mapping end",
+}
+
+func (e yaml_event_type_t) String() string {
+ if e < 0 || int(e) >= len(eventStrings) {
+ return fmt.Sprintf("unknown event %d", e)
+ }
+ return eventStrings[e]
+}
+
+// The event structure.
+type yaml_event_t struct {
+
+ // The event type.
+ typ yaml_event_type_t
+
+ // The start and end of the event.
+ start_mark, end_mark yaml_mark_t
+
+ // The document encoding (for yaml_STREAM_START_EVENT).
+ encoding yaml_encoding_t
+
+ // The version directive (for yaml_DOCUMENT_START_EVENT).
+ version_directive *yaml_version_directive_t
+
+ // The list of tag directives (for yaml_DOCUMENT_START_EVENT).
+ tag_directives []yaml_tag_directive_t
+
+ // The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT).
+ anchor []byte
+
+ // The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
+ tag []byte
+
+ // The scalar value (for yaml_SCALAR_EVENT).
+ value []byte
+
+ // Is the document start/end indicator implicit, or the tag optional?
+ // (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT).
+ implicit bool
+
+ // Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT).
+ quoted_implicit bool
+
+ // The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
+ style yaml_style_t
+}
+
+func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) }
+func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) }
+func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) }
+
+// Nodes
+
+const (
+ yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null.
+ yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false.
+ yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values.
+ yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values.
+ yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values.
+ yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values.
+
+ yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences.
+ yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping.
+
+ // Not in original libyaml.
+ yaml_BINARY_TAG = "tag:yaml.org,2002:binary"
+ yaml_MERGE_TAG = "tag:yaml.org,2002:merge"
+
+ yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str.
+ yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq.
+ yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map.
+)
+
+type yaml_node_type_t int
+
+// Node types.
+const (
+ // An empty node.
+ yaml_NO_NODE yaml_node_type_t = iota
+
+ yaml_SCALAR_NODE // A scalar node.
+ yaml_SEQUENCE_NODE // A sequence node.
+ yaml_MAPPING_NODE // A mapping node.
+)
+
+// An element of a sequence node.
+type yaml_node_item_t int
+
+// An element of a mapping node.
+type yaml_node_pair_t struct {
+ key int // The key of the element.
+ value int // The value of the element.
+}
+
+// The node structure.
+type yaml_node_t struct {
+ typ yaml_node_type_t // The node type.
+ tag []byte // The node tag.
+
+ // The node data.
+
+ // The scalar parameters (for yaml_SCALAR_NODE).
+ scalar struct {
+ value []byte // The scalar value.
+ length int // The length of the scalar value.
+ style yaml_scalar_style_t // The scalar style.
+ }
+
+ // The sequence parameters (for YAML_SEQUENCE_NODE).
+ sequence struct {
+ items_data []yaml_node_item_t // The stack of sequence items.
+ style yaml_sequence_style_t // The sequence style.
+ }
+
+ // The mapping parameters (for yaml_MAPPING_NODE).
+ mapping struct {
+ pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value).
+ pairs_start *yaml_node_pair_t // The beginning of the stack.
+ pairs_end *yaml_node_pair_t // The end of the stack.
+ pairs_top *yaml_node_pair_t // The top of the stack.
+ style yaml_mapping_style_t // The mapping style.
+ }
+
+ start_mark yaml_mark_t // The beginning of the node.
+ end_mark yaml_mark_t // The end of the node.
+
+}
+
+// The document structure.
+type yaml_document_t struct {
+
+ // The document nodes.
+ nodes []yaml_node_t
+
+ // The version directive.
+ version_directive *yaml_version_directive_t
+
+ // The list of tag directives.
+ tag_directives_data []yaml_tag_directive_t
+ tag_directives_start int // The beginning of the tag directives list.
+ tag_directives_end int // The end of the tag directives list.
+
+ start_implicit int // Is the document start indicator implicit?
+ end_implicit int // Is the document end indicator implicit?
+
+ // The start/end of the document.
+ start_mark, end_mark yaml_mark_t
+}
+
+// The prototype of a read handler.
+//
+// The read handler is called when the parser needs to read more bytes from the
+// source. The handler should write not more than size bytes to the buffer.
+// The number of written bytes should be set to the size_read variable.
+//
+// [in,out] data A pointer to an application data specified by
+// yaml_parser_set_input().
+// [out] buffer The buffer to write the data from the source.
+// [in] size The size of the buffer.
+// [out] size_read The actual number of bytes read from the source.
+//
+// On success, the handler should return 1. If the handler failed,
+// the returned value should be 0. On EOF, the handler should set the
+// size_read to 0 and return 1.
+type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error)
+
+// This structure holds information about a potential simple key.
+type yaml_simple_key_t struct {
+ possible bool // Is a simple key possible?
+ required bool // Is a simple key required?
+ token_number int // The number of the token.
+ mark yaml_mark_t // The position mark.
+}
+
+// The states of the parser.
+type yaml_parser_state_t int
+
+const (
+ yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota
+
+ yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document.
+ yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START.
+ yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document.
+ yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END.
+ yaml_PARSE_BLOCK_NODE_STATE // Expect a block node.
+ yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence.
+ yaml_PARSE_FLOW_NODE_STATE // Expect a flow node.
+ yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence.
+ yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence.
+ yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence.
+ yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
+ yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key.
+ yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value.
+ yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence.
+ yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence.
+ yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping.
+ yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping.
+ yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry.
+ yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
+ yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
+ yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
+ yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping.
+ yaml_PARSE_END_STATE // Expect nothing.
+)
+
+func (ps yaml_parser_state_t) String() string {
+ switch ps {
+ case yaml_PARSE_STREAM_START_STATE:
+ return "yaml_PARSE_STREAM_START_STATE"
+ case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
+ return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE"
+ case yaml_PARSE_DOCUMENT_START_STATE:
+ return "yaml_PARSE_DOCUMENT_START_STATE"
+ case yaml_PARSE_DOCUMENT_CONTENT_STATE:
+ return "yaml_PARSE_DOCUMENT_CONTENT_STATE"
+ case yaml_PARSE_DOCUMENT_END_STATE:
+ return "yaml_PARSE_DOCUMENT_END_STATE"
+ case yaml_PARSE_BLOCK_NODE_STATE:
+ return "yaml_PARSE_BLOCK_NODE_STATE"
+ case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
+ return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE"
+ case yaml_PARSE_FLOW_NODE_STATE:
+ return "yaml_PARSE_FLOW_NODE_STATE"
+ case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
+ return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE"
+ case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
+ return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE"
+ case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
+ return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE"
+ case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
+ return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE"
+ case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
+ return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE"
+ case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
+ return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE"
+ case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
+ return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE"
+ case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
+ return "yaml_PARSE_FLOW_MAPPING_KEY_STATE"
+ case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
+ return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE"
+ case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
+ return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE"
+ case yaml_PARSE_END_STATE:
+ return "yaml_PARSE_END_STATE"
+ }
+ return "<unknown parser state>"
+}
+
+// This structure holds aliases data.
+type yaml_alias_data_t struct {
+ anchor []byte // The anchor.
+ index int // The node id.
+ mark yaml_mark_t // The anchor mark.
+}
+
+// The parser structure.
+//
+// All members are internal. Manage the structure using the
+// yaml_parser_ family of functions.
+type yaml_parser_t struct {
+
+ // Error handling
+
+ error yaml_error_type_t // Error type.
+
+ problem string // Error description.
+
+ // The byte about which the problem occurred.
+ problem_offset int
+ problem_value int
+ problem_mark yaml_mark_t
+
+ // The error context.
+ context string
+ context_mark yaml_mark_t
+
+ // Reader stuff
+
+ read_handler yaml_read_handler_t // Read handler.
+
+ input_reader io.Reader // File input data.
+ input []byte // String input data.
+ input_pos int
+
+ eof bool // EOF flag
+
+ buffer []byte // The working buffer.
+ buffer_pos int // The current position of the buffer.
+
+ unread int // The number of unread characters in the buffer.
+
+ raw_buffer []byte // The raw buffer.
+ raw_buffer_pos int // The current position of the buffer.
+
+ encoding yaml_encoding_t // The input encoding.
+
+ offset int // The offset of the current position (in bytes).
+ mark yaml_mark_t // The mark of the current position.
+
+ // Scanner stuff
+
+ stream_start_produced bool // Have we started to scan the input stream?
+ stream_end_produced bool // Have we reached the end of the input stream?
+
+ flow_level int // The number of unclosed '[' and '{' indicators.
+
+ tokens []yaml_token_t // The tokens queue.
+ tokens_head int // The head of the tokens queue.
+ tokens_parsed int // The number of tokens fetched from the queue.
+ token_available bool // Does the tokens queue contain a token ready for dequeueing.
+
+ indent int // The current indentation level.
+ indents []int // The indentation levels stack.
+
+ simple_key_allowed bool // May a simple key occur at the current position?
+ simple_keys []yaml_simple_key_t // The stack of simple keys.
+
+ // Parser stuff
+
+ state yaml_parser_state_t // The current parser state.
+ states []yaml_parser_state_t // The parser states stack.
+ marks []yaml_mark_t // The stack of marks.
+ tag_directives []yaml_tag_directive_t // The list of TAG directives.
+
+ // Dumper stuff
+
+ aliases []yaml_alias_data_t // The alias data.
+
+ document *yaml_document_t // The currently parsed document.
+}
+
+// Emitter Definitions
+
+// The prototype of a write handler.
+//
+// The write handler is called when the emitter needs to flush the accumulated
+// characters to the output. The handler should write @a size bytes of the
+// @a buffer to the output.
+//
+// @param[in,out] data A pointer to an application data specified by
+// yaml_emitter_set_output().
+// @param[in] buffer The buffer with bytes to be written.
+// @param[in] size The size of the buffer.
+//
+// @returns On success, the handler should return @c 1. If the handler failed,
+// the returned value should be @c 0.
+//
+type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error
+
+type yaml_emitter_state_t int
+
+// The emitter states.
+const (
+ // Expect STREAM-START.
+ yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota
+
+ yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END.
+ yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END.
+ yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document.
+ yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END.
+ yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence.
+ yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence.
+ yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
+ yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
+ yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping.
+ yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
+ yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence.
+ yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence.
+ yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
+ yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping.
+ yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping.
+ yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping.
+ yaml_EMIT_END_STATE // Expect nothing.
+)
+
+// The emitter structure.
+//
+// All members are internal. Manage the structure using the @c yaml_emitter_
+// family of functions.
+type yaml_emitter_t struct {
+
+ // Error handling
+
+ error yaml_error_type_t // Error type.
+ problem string // Error description.
+
+ // Writer stuff
+
+ write_handler yaml_write_handler_t // Write handler.
+
+ output_buffer *[]byte // String output data.
+ output_writer io.Writer // File output data.
+
+ buffer []byte // The working buffer.
+ buffer_pos int // The current position of the buffer.
+
+ raw_buffer []byte // The raw buffer.
+ raw_buffer_pos int // The current position of the buffer.
+
+ encoding yaml_encoding_t // The stream encoding.
+
+ // Emitter stuff
+
+ canonical bool // If the output is in the canonical style?
+ best_indent int // The number of indentation spaces.
+ best_width int // The preferred width of the output lines.
+ unicode bool // Allow unescaped non-ASCII characters?
+ line_break yaml_break_t // The preferred line break.
+
+ state yaml_emitter_state_t // The current emitter state.
+ states []yaml_emitter_state_t // The stack of states.
+
+ events []yaml_event_t // The event queue.
+ events_head int // The head of the event queue.
+
+ indents []int // The stack of indentation levels.
+
+ tag_directives []yaml_tag_directive_t // The list of tag directives.
+
+ indent int // The current indentation level.
+
+ flow_level int // The current flow level.
+
+ root_context bool // Is it the document root context?
+ sequence_context bool // Is it a sequence context?
+ mapping_context bool // Is it a mapping context?
+ simple_key_context bool // Is it a simple mapping key context?
+
+ line int // The current line.
+ column int // The current column.
+ whitespace bool // If the last character was a whitespace?
+ indention bool // If the last character was an indentation character (' ', '-', '?', ':')?
+ open_ended bool // If an explicit document end is required?
+
+ // Anchor analysis.
+ anchor_data struct {
+ anchor []byte // The anchor value.
+ alias bool // Is it an alias?
+ }
+
+ // Tag analysis.
+ tag_data struct {
+ handle []byte // The tag handle.
+ suffix []byte // The tag suffix.
+ }
+
+ // Scalar analysis.
+ scalar_data struct {
+ value []byte // The scalar value.
+ multiline bool // Does the scalar contain line breaks?
+ flow_plain_allowed bool // Can the scalar be expessed in the flow plain style?
+ block_plain_allowed bool // Can the scalar be expressed in the block plain style?
+ single_quoted_allowed bool // Can the scalar be expressed in the single quoted style?
+ block_allowed bool // Can the scalar be expressed in the literal or folded styles?
+ style yaml_scalar_style_t // The output style.
+ }
+
+ // Dumper stuff
+
+ opened bool // If the stream was already opened?
+ closed bool // If the stream was already closed?
+
+ // The information associated with the document nodes.
+ anchors *struct {
+ references int // The number of references.
+ anchor int // The anchor id.
+ serialized bool // If the node has been emitted?
+ }
+
+ last_anchor_id int // The last assigned anchor id.
+
+ document *yaml_document_t // The currently emitted document.
+}
--- /dev/null
+package yaml
+
+const (
+ // The size of the input raw buffer.
+ input_raw_buffer_size = 512
+
+ // The size of the input buffer.
+ // It should be possible to decode the whole raw buffer.
+ input_buffer_size = input_raw_buffer_size * 3
+
+ // The size of the output buffer.
+ output_buffer_size = 128
+
+ // The size of the output raw buffer.
+ // It should be possible to encode the whole output buffer.
+ output_raw_buffer_size = (output_buffer_size*2 + 2)
+
+ // The size of other stacks and queues.
+ initial_stack_size = 16
+ initial_queue_size = 16
+ initial_string_size = 16
+)
+
+// Check if the character at the specified position is an alphabetical
+// character, a digit, '_', or '-'.
+func is_alpha(b []byte, i int) bool {
+ return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-'
+}
+
+// Check if the character at the specified position is a digit.
+func is_digit(b []byte, i int) bool {
+ return b[i] >= '0' && b[i] <= '9'
+}
+
+// Get the value of a digit.
+func as_digit(b []byte, i int) int {
+ return int(b[i]) - '0'
+}
+
+// Check if the character at the specified position is a hex-digit.
+func is_hex(b []byte, i int) bool {
+ return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f'
+}
+
+// Get the value of a hex-digit.
+func as_hex(b []byte, i int) int {
+ bi := b[i]
+ if bi >= 'A' && bi <= 'F' {
+ return int(bi) - 'A' + 10
+ }
+ if bi >= 'a' && bi <= 'f' {
+ return int(bi) - 'a' + 10
+ }
+ return int(bi) - '0'
+}
+
+// Check if the character is ASCII.
+func is_ascii(b []byte, i int) bool {
+ return b[i] <= 0x7F
+}
+
+// Check if the character at the start of the buffer can be printed unescaped.
+func is_printable(b []byte, i int) bool {
+ return ((b[i] == 0x0A) || // . == #x0A
+ (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E
+ (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF
+ (b[i] > 0xC2 && b[i] < 0xED) ||
+ (b[i] == 0xED && b[i+1] < 0xA0) ||
+ (b[i] == 0xEE) ||
+ (b[i] == 0xEF && // #xE000 <= . <= #xFFFD
+ !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF
+ !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF))))
+}
+
+// Check if the character at the specified position is NUL.
+func is_z(b []byte, i int) bool {
+ return b[i] == 0x00
+}
+
+// Check if the beginning of the buffer is a BOM.
+func is_bom(b []byte, i int) bool {
+ return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF
+}
+
+// Check if the character at the specified position is space.
+func is_space(b []byte, i int) bool {
+ return b[i] == ' '
+}
+
+// Check if the character at the specified position is tab.
+func is_tab(b []byte, i int) bool {
+ return b[i] == '\t'
+}
+
+// Check if the character at the specified position is blank (space or tab).
+func is_blank(b []byte, i int) bool {
+ //return is_space(b, i) || is_tab(b, i)
+ return b[i] == ' ' || b[i] == '\t'
+}
+
+// Check if the character at the specified position is a line break.
+func is_break(b []byte, i int) bool {
+ return (b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029)
+}
+
+func is_crlf(b []byte, i int) bool {
+ return b[i] == '\r' && b[i+1] == '\n'
+}
+
+// Check if the character is a line break or NUL.
+func is_breakz(b []byte, i int) bool {
+ //return is_break(b, i) || is_z(b, i)
+ return ( // is_break:
+ b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+ // is_z:
+ b[i] == 0)
+}
+
+// Check if the character is a line break, space, or NUL.
+func is_spacez(b []byte, i int) bool {
+ //return is_space(b, i) || is_breakz(b, i)
+ return ( // is_space:
+ b[i] == ' ' ||
+ // is_breakz:
+ b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+ b[i] == 0)
+}
+
+// Check if the character is a line break, space, tab, or NUL.
+func is_blankz(b []byte, i int) bool {
+ //return is_blank(b, i) || is_breakz(b, i)
+ return ( // is_blank:
+ b[i] == ' ' || b[i] == '\t' ||
+ // is_breakz:
+ b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+ b[i] == 0)
+}
+
+// Determine the width of the character.
+func width(b byte) int {
+ // Don't replace these by a switch without first
+ // confirming that it is being inlined.
+ if b&0x80 == 0x00 {
+ return 1
+ }
+ if b&0xE0 == 0xC0 {
+ return 2
+ }
+ if b&0xF0 == 0xE0 {
+ return 3
+ }
+ if b&0xF8 == 0xF0 {
+ return 4
+ }
+ return 0
+
+}
--- /dev/null
+{
+ "comment": "",
+ "ignore": "test",
+ "package": [
+ {
+ "checksumSHA1": "KmjnydoAbofMieIWm+it5OWERaM=",
+ "path": "github.com/alecthomas/template",
+ "revision": "a0175ee3bccc567396460bf5acd36800cb10c49c",
+ "revisionTime": "2016-04-05T07:15:01Z"
+ },
+ {
+ "checksumSHA1": "3wt0pTXXeS+S93unwhGoLIyGX/Q=",
+ "path": "github.com/alecthomas/template/parse",
+ "revision": "a0175ee3bccc567396460bf5acd36800cb10c49c",
+ "revisionTime": "2016-04-05T07:15:01Z"
+ },
+ {
+ "checksumSHA1": "fCc3grA7vIxfBru7R3SqjcW+oLI=",
+ "path": "github.com/alecthomas/units",
+ "revision": "2efee857e7cfd4f3d0138cc3cbb1b4966962b93a",
+ "revisionTime": "2015-10-22T06:55:26Z"
+ },
+ {
+ "checksumSHA1": "xp/2s4XclLL17DThGBI7jXZ4Crs=",
+ "path": "github.com/armon/go-metrics",
+ "revision": "9a4b6e10bed6220a1665955aa2b75afc91eb10b3",
+ "revisionTime": "2017-10-02T18:27:31Z"
+ },
+ {
+ "checksumSHA1": "4QnLdmB1kG3N+KlDd1N+G9TWAGQ=",
+ "path": "github.com/beorn7/perks/quantile",
+ "revision": "1e01b2bdbae8edb393fcf555732304f34d192fc9",
+ "revisionTime": "2016-11-21T14:22:35Z"
+ },
+ {
+ "checksumSHA1": "b55VMQZmwBl4iSpI9BfdesJI9vQ=",
+ "path": "github.com/cenkalti/backoff",
+ "revision": "1e01b2bdbae8edb393fcf555732304f34d192fc9",
+ "revisionTime": "2016-11-21T14:22:35Z"
+ },
+ {
+ "checksumSHA1": "OFu4xJEIjiI8Suu+j/gabfp+y6Q=",
+ "origin": "github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew",
+ "path": "github.com/davecgh/go-spew/spew",
+ "revision": "346938d642f2ec3594ed81d874461961cd0faa76",
+ "revisionTime": "2016-10-29T20:57:26Z"
+ },
+ {
+ "checksumSHA1": "KrIRJ4p3nRze4NcxfgX5+N9+D1M=",
+ "path": "github.com/go-kit/kit/log",
+ "revision": "e2b298466b32c7cd5579a9b9b07e968fc9d9452c",
+ "revisionTime": "2017-10-21T13:24:59Z"
+ },
+ {
+ "checksumSHA1": "t7aTpDH0h4BZcGU0KkUr14QQG2w=",
+ "path": "github.com/go-kit/kit/log/level",
+ "revision": "e2b298466b32c7cd5579a9b9b07e968fc9d9452c",
+ "revisionTime": "2017-10-21T13:24:59Z"
+ },
+ {
+ "checksumSHA1": "KxX/Drph+byPXBFIXaCZaCOAnrU=",
+ "path": "github.com/go-logfmt/logfmt",
+ "revision": "390ab7935ee28ec6b286364bba9b4dd6410cb3d5",
+ "revisionTime": "2016-11-15T14:25:13Z"
+ },
+ {
+ "checksumSHA1": "j6vhe49MX+dyHR9rU91P6vMx55o=",
+ "path": "github.com/go-stack/stack",
+ "revision": "817915b46b97fd7bb80e8ab6b69f01a53ac3eebf",
+ "revisionTime": "2017-07-24T01:23:01Z"
+ },
+ {
+ "checksumSHA1": "FhLvgtYfuKY0ow9wtLJRoeg7d6w=",
+ "path": "github.com/gogo/protobuf/gogoproto",
+ "revision": "616a82ed12d78d24d4839363e8f3c5d3f20627cf",
+ "revisionTime": "2017-11-09T18:15:19Z"
+ },
+ {
+ "checksumSHA1": "6ZxSmrIx3Jd15aou16oG0HPylP4=",
+ "path": "github.com/gogo/protobuf/proto",
+ "revision": "c0656edd0d9eab7c66d1eb0c568f9039345796f7",
+ "revisionTime": "2017-03-30T07:10:51Z"
+ },
+ {
+ "checksumSHA1": "F+PKpdY6PyIrxQ8b20TzsM+1JuI=",
+ "path": "github.com/gogo/protobuf/protoc-gen-gogo/descriptor",
+ "revision": "616a82ed12d78d24d4839363e8f3c5d3f20627cf",
+ "revisionTime": "2017-11-09T18:15:19Z"
+ },
+ {
+ "checksumSHA1": "HPVQZu059/Rfw2bAWM538bVTcUc=",
+ "path": "github.com/gogo/protobuf/sortkeys",
+ "revision": "c0656edd0d9eab7c66d1eb0c568f9039345796f7",
+ "revisionTime": "2017-03-30T07:10:51Z"
+ },
+ {
+ "checksumSHA1": "b1p91yJ1mx+abXDUtM5UV3xEiaw=",
+ "path": "github.com/gogo/protobuf/types",
+ "revision": "c0656edd0d9eab7c66d1eb0c568f9039345796f7",
+ "revisionTime": "2017-03-30T07:10:51Z"
+ },
+ {
+ "checksumSHA1": "M/1HiQFl2DyE+q3pFf8swvAQ3MY=",
+ "path": "github.com/golang/protobuf/proto",
+ "revision": "1e01b2bdbae8edb393fcf555732304f34d192fc9",
+ "revisionTime": "2016-11-21T14:22:35Z"
+ },
+ {
+ "checksumSHA1": "cdOCt0Yb+hdErz8NAQqayxPmRsY=",
+ "origin": "github.com/hashicorp/go-multierror/vendor/github.com/hashicorp/errwrap",
+ "path": "github.com/hashicorp/errwrap",
+ "revision": "83588e72410abfbe4df460eeb6f30841ae47d4c4",
+ "revisionTime": "2017-06-22T06:09:55Z"
+ },
+ {
+ "checksumSHA1": "Cas2nprG6pWzf05A2F/OlnjUu2Y=",
+ "path": "github.com/hashicorp/go-immutable-radix",
+ "revision": "8aac2701530899b64bdea735a1de8da899815220",
+ "revisionTime": "2017-07-25T22:12:15Z"
+ },
+ {
+ "checksumSHA1": "TNlVzNR1OaajcNi3CbQ3bGbaLGU=",
+ "path": "github.com/hashicorp/go-msgpack/codec",
+ "revision": "fa3f63826f7c23912c15263591e65d54d080b458",
+ "revisionTime": "2015-05-18T23:42:57Z"
+ },
+ {
+ "checksumSHA1": "g7uHECbzuaWwdxvwoyxBwgeERPk=",
+ "path": "github.com/hashicorp/go-multierror",
+ "revision": "83588e72410abfbe4df460eeb6f30841ae47d4c4",
+ "revisionTime": "2017-06-22T06:09:55Z"
+ },
+ {
+ "checksumSHA1": "eCWvhgknHMj5K19ePPjIA3l401Q=",
+ "path": "github.com/hashicorp/go-sockaddr",
+ "revision": "9b4c5fa5b10a683339a270d664474b9f4aee62fc",
+ "revisionTime": "2017-10-30T10:43:12Z"
+ },
+ {
+ "checksumSHA1": "9hffs0bAIU6CquiRhKQdzjHnKt0=",
+ "path": "github.com/hashicorp/golang-lru/simplelru",
+ "revision": "0a025b7e63adc15a622f29b0b2c4c3848243bbf6",
+ "revisionTime": "2016-08-13T22:13:03Z"
+ },
+ {
+ "checksumSHA1": "vwj2yOi577Mmn+IfJwV8YXYeALk=",
+ "path": "github.com/hashicorp/memberlist",
+ "revision": "687988a0b5daaf7ed5051e5e374aef27f8254822",
+ "revisionTime": "2017-09-19T17:31:51Z"
+ },
+ {
+ "checksumSHA1": "gKyBj05YkfuLFruAyPZ4KV9nFp8=",
+ "path": "github.com/julienschmidt/httprouter",
+ "revision": "975b5c4c7c21c0e3d2764200bf2aa8e34657ae6e",
+ "revisionTime": "2017-04-30T22:20:11Z"
+ },
+ {
+ "checksumSHA1": "abKzFXAn0KDr5U+JON1ZgJ2lUtU=",
+ "path": "github.com/kr/logfmt",
+ "revision": "b84e30acd515aadc4b783ad4ff83aff3299bdfe0",
+ "revisionTime": "2014-02-26T03:06:59Z"
+ },
+ {
+ "checksumSHA1": "0utJAePiKZZzPG3SxPA+xWQ3JAw=",
+ "path": "github.com/kylelemons/godebug/diff",
+ "revision": "1e01b2bdbae8edb393fcf555732304f34d192fc9",
+ "revisionTime": "2016-11-21T14:22:35Z"
+ },
+ {
+ "checksumSHA1": "f1Cya7f83KJIkWcYWxT3ZZxDeZc=",
+ "path": "github.com/kylelemons/godebug/pretty",
+ "revision": "1e01b2bdbae8edb393fcf555732304f34d192fc9",
+ "revisionTime": "2016-11-21T14:22:35Z"
+ },
+ {
+ "checksumSHA1": "Q2vw4HZBbnU8BLFt8VrzStwqSJg=",
+ "path": "github.com/matttproud/golang_protobuf_extensions/pbutil",
+ "revision": "1e01b2bdbae8edb393fcf555732304f34d192fc9",
+ "revisionTime": "2016-11-21T14:22:35Z"
+ },
+ {
+ "checksumSHA1": "DpaOH7hx9TRqhDnhOjaXfjNsitQ=",
+ "path": "github.com/miekg/dns",
+ "revision": "388f6eea2949b6d9071d25f08cf5b6686da15265",
+ "revisionTime": "2017-11-08T10:01:19Z"
+ },
+ {
+ "checksumSHA1": "AYjG78HsyaohvBTuzCgdxU48dFE=",
+ "path": "github.com/miekg/dns/internal/socket",
+ "revision": "388f6eea2949b6d9071d25f08cf5b6686da15265",
+ "revisionTime": "2017-11-08T10:01:19Z"
+ },
+ {
+ "checksumSHA1": "ZYfqG6bNE3cRlbsvpJBL0bF6DSc=",
+ "path": "github.com/mwitkow/go-conntrack",
+ "revision": "cc309e4a22231782e8893f3c35ced0967807a33e",
+ "revisionTime": "2016-11-29T09:58:57Z"
+ },
+ {
+ "checksumSHA1": "gkyBg/2hcIWR/8qGEeGVoHwOyfo=",
+ "path": "github.com/oklog/oklog/pkg/group",
+ "revision": "f857583a70c345341d679b3f27aa542c8db70a21",
+ "revisionTime": "2017-09-18T07:00:58Z"
+ },
+ {
+ "checksumSHA1": "B1iGaUz7NrjEmCjVdIgH5pvkTe8=",
+ "path": "github.com/oklog/ulid",
+ "revision": "66bb6560562feca7045b23db1ae85b01260f87c5",
+ "revisionTime": "2017-01-17T20:06:51Z"
+ },
+ {
+ "checksumSHA1": "ynJSWoF6v+3zMnh9R0QmmG6iGV8=",
+ "path": "github.com/pkg/errors",
+ "revision": "ff09b135c25aae272398c51a07235b90a75aa4f0",
+ "revisionTime": "2017-03-16T20:15:38Z"
+ },
+ {
+ "checksumSHA1": "zKKp5SZ3d3ycKe4EKMNT0BqAWBw=",
+ "origin": "github.com/stretchr/testify/vendor/github.com/pmezard/go-difflib/difflib",
+ "path": "github.com/pmezard/go-difflib/difflib",
+ "revision": "18a02ba4a312f95da08ff4cfc0055750ce50ae9e",
+ "revisionTime": "2016-11-17T07:43:51Z"
+ },
+ {
+ "checksumSHA1": "4VppKBbzCSmoFfQxGNUm0TYiFCA=",
+ "path": "github.com/prometheus/client_golang/api",
+ "revision": "c3324c1198cf3374996e9d3098edd46a6b55afc9",
+ "revisionTime": "2018-02-23T14:47:18Z"
+ },
+ {
+ "checksumSHA1": "I87tkF1e/hrl4d/XIKFfkPRq1ww=",
+ "path": "github.com/prometheus/client_golang/prometheus",
+ "revision": "d49167c4b9f3c4451707560c5c71471ff5291aaa",
+ "revisionTime": "2018-03-19T13:17:21Z"
+ },
+ {
+ "checksumSHA1": "mIWVz1E1QJ6yZnf7ELNwLboyK4w=",
+ "path": "github.com/prometheus/client_golang/prometheus/promhttp",
+ "revision": "d49167c4b9f3c4451707560c5c71471ff5291aaa",
+ "revisionTime": "2018-03-19T13:17:21Z"
+ },
+ {
+ "checksumSHA1": "DvwvOlPNAgRntBzt3b3OSRMS2N4=",
+ "path": "github.com/prometheus/client_model/go",
+ "revision": "1e01b2bdbae8edb393fcf555732304f34d192fc9",
+ "revisionTime": "2016-11-21T14:22:35Z"
+ },
+ {
+ "checksumSHA1": "cxLURB7wEFsMAZ6fi5Ptfdrwdc8=",
+ "path": "github.com/prometheus/common/config",
+ "revision": "7600349dcfe1abd18d72d3a1770870d9800a7801",
+ "revisionTime": "2018-05-18T15:47:59Z"
+ },
+ {
+ "checksumSHA1": "vPdC/DzEm7YbzRir2wwnpLPfay8=",
+ "path": "github.com/prometheus/common/expfmt",
+ "revision": "7600349dcfe1abd18d72d3a1770870d9800a7801",
+ "revisionTime": "2018-05-18T15:47:59Z"
+ },
+ {
+ "checksumSHA1": "GWlM3d2vPYyNATtTFgftS10/A9w=",
+ "path": "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg",
+ "revision": "7600349dcfe1abd18d72d3a1770870d9800a7801",
+ "revisionTime": "2018-05-18T15:47:59Z"
+ },
+ {
+ "checksumSHA1": "EXTRY7DL9gFW8c341Dk6LDXCBn8=",
+ "path": "github.com/prometheus/common/model",
+ "revision": "7600349dcfe1abd18d72d3a1770870d9800a7801",
+ "revisionTime": "2018-05-18T15:47:59Z"
+ },
+ {
+ "checksumSHA1": "Yseprf8kAFr/s7wztkQnrFuFN+8=",
+ "path": "github.com/prometheus/common/promlog",
+ "revision": "7600349dcfe1abd18d72d3a1770870d9800a7801",
+ "revisionTime": "2018-05-18T15:47:59Z"
+ },
+ {
+ "checksumSHA1": "9doPk0x0LONG/idxK61JnZYcxBs=",
+ "path": "github.com/prometheus/common/route",
+ "revision": "7600349dcfe1abd18d72d3a1770870d9800a7801",
+ "revisionTime": "2018-05-18T15:47:59Z"
+ },
+ {
+ "checksumSHA1": "91KYK0SpvkaMJJA2+BcxbVnyRO0=",
+ "path": "github.com/prometheus/common/version",
+ "revision": "7600349dcfe1abd18d72d3a1770870d9800a7801",
+ "revisionTime": "2018-05-18T15:47:59Z"
+ },
+ {
+ "checksumSHA1": "gc+7liWFv9C7S5kS2l7qLajiWdc=",
+ "path": "github.com/prometheus/procfs",
+ "revision": "1e01b2bdbae8edb393fcf555732304f34d192fc9",
+ "revisionTime": "2016-11-21T14:22:35Z"
+ },
+ {
+ "checksumSHA1": "VvJ7kr3WkRUwMKxzbnxroYVZMmg=",
+ "path": "github.com/prometheus/prometheus/pkg/labels",
+ "revision": "58e2a31db8de12da60783d91d748008daed95159",
+ "revisionTime": "2018-03-15T08:59:19Z"
+ },
+ {
+ "checksumSHA1": "cKNzpMpci3WUAzXpe+tVnBv2cjE=",
+ "path": "github.com/satori/go.uuid",
+ "revision": "1e01b2bdbae8edb393fcf555732304f34d192fc9",
+ "revisionTime": "2016-11-21T14:22:35Z"
+ },
+ {
+ "checksumSHA1": "tnMZLo/kR9Kqx6GtmWwowtTLlA8=",
+ "path": "github.com/sean-/seed",
+ "revision": "e2103e2c35297fb7e17febb81e49b312087a2372",
+ "revisionTime": "2017-03-13T16:33:22Z"
+ },
+ {
+ "checksumSHA1": "iydUphwYqZRq3WhstEdGsbvBAKs=",
+ "path": "github.com/stretchr/testify/assert",
+ "revision": "1e01b2bdbae8edb393fcf555732304f34d192fc9",
+ "revisionTime": "2016-11-21T14:22:35Z"
+ },
+ {
+ "checksumSHA1": "P9FJpir2c4G5PA46qEkaWy3l60U=",
+ "path": "github.com/stretchr/testify/require",
+ "revision": "1e01b2bdbae8edb393fcf555732304f34d192fc9",
+ "revisionTime": "2016-11-21T14:22:35Z"
+ },
+ {
+ "checksumSHA1": "hKZGpbFuCrkE4s1vxubKK1aFlfI=",
+ "path": "golang.org/x/net/context",
+ "revision": "1e01b2bdbae8edb393fcf555732304f34d192fc9",
+ "revisionTime": "2016-11-21T14:22:35Z"
+ },
+ {
+ "checksumSHA1": "GNnwCoCCsZTbfmQsw7A7eIf++Ms=",
+ "path": "golang.org/x/net/context/ctxhttp",
+ "revision": "1e01b2bdbae8edb393fcf555732304f34d192fc9",
+ "revisionTime": "2016-11-21T14:22:35Z"
+ },
+ {
+ "checksumSHA1": "UxahDzW2v4mf/+aFxruuupaoIwo=",
+ "path": "golang.org/x/net/internal/timeseries",
+ "revision": "db08ff08e8622530d9ed3a0e8ac279f6d4c02196",
+ "revisionTime": "2018-06-11T16:35:41Z"
+ },
+ {
+ "checksumSHA1": "rJn3m/27kO+2IU6KCCZ74Miby+8=",
+ "path": "golang.org/x/net/trace",
+ "revision": "db08ff08e8622530d9ed3a0e8ac279f6d4c02196",
+ "revisionTime": "2018-06-11T16:35:41Z"
+ },
+ {
+ "checksumSHA1": "sToCp8GThnMnsBzsHv+L/tBYQrQ=",
+ "path": "gopkg.in/alecthomas/kingpin.v2",
+ "revision": "947dcec5ba9c011838740e680966fd7087a71d0d",
+ "revisionTime": "2017-12-17T18:08:21Z"
+ },
+ {
+ "checksumSHA1": "ZSWoOPUNRr5+3dhkLK3C4cZAQPk=",
+ "path": "gopkg.in/yaml.v2",
+ "revision": "5420a8b6744d3b0345ab293f6fcba19c978f1183",
+ "revisionTime": "2018-03-28T19:50:20Z",
+ "version": "v2.2",
+ "versionExact": "v2.2.1"
+ }
+ ],
+ "rootPath": "github.com/prometheus/alertmanager"
+}